diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -193,6 +193,9 @@ endif(NOT LIBICAL_FOUND) endif(ENABLE_LIBICAL) +option(ENABLE_QIFIMPORTER "Enable QIF Importer" ON) +option(ENABLE_QIFEXPORTER "Enable QIF Exporter" ON) + # TODO: this should be removed enable_testing() diff --git a/kmymoney/converter/CMakeLists.txt b/kmymoney/converter/CMakeLists.txt --- a/kmymoney/converter/CMakeLists.txt +++ b/kmymoney/converter/CMakeLists.txt @@ -2,9 +2,6 @@ set (libconverter_a_SOURCES mymoneygncreader.cpp - mymoneyqifprofile.cpp - mymoneyqifreader.cpp - mymoneyqifwriter.cpp mymoneystatementreader.cpp mymoneytemplate.cpp webpricequote.cpp diff --git a/kmymoney/converter/mymoneystatementreader.h b/kmymoney/converter/mymoneystatementreader.h --- a/kmymoney/converter/mymoneystatementreader.h +++ b/kmymoney/converter/mymoneystatementreader.h @@ -28,7 +28,6 @@ #include #include -#include "mymoneyqifprofile.h" #include "mymoneyaccount.h" #include "mymoneystatement.h" #include "transactionmatcher.h" diff --git a/kmymoney/converter/webpricequote.cpp b/kmymoney/converter/webpricequote.cpp --- a/kmymoney/converter/webpricequote.cpp +++ b/kmymoney/converter/webpricequote.cpp @@ -52,7 +52,6 @@ // Project Headers #include "mymoneyexception.h" -#include "mymoneyqifprofile.h" #include "mymoneyfile.h" Q_DECLARE_LOGGING_CATEGORY(WEBPRICEQUOTE) diff --git a/kmymoney/dialogs/CMakeLists.txt b/kmymoney/dialogs/CMakeLists.txt --- a/kmymoney/dialogs/CMakeLists.txt +++ b/kmymoney/dialogs/CMakeLists.txt @@ -21,13 +21,11 @@ kenterscheduledlg.cpp kequitypriceupdatedlg.cpp kequitypriceupdateconfdlg.cpp - kexportdlg.cpp kfindtransactiondlg.cpp kgeneratesqldlg.cpp kgncimportoptionsdlg.cpp kgncpricesourcedlg.cpp kgpgkeyselectiondlg.cpp - kimportdlg.cpp kloadtemplatedlg.cpp kmergetransactionsdlg.cpp kmymoneyfileinfodlg.cpp @@ -46,7 +44,6 @@ ksplittransactiondlg.cpp ktemplateexportdlg.cpp kupdatestockpricedlg.cpp - mymoneyqifprofileeditor.cpp transactioneditor.cpp transactionmatcher.cpp konlinetransferform.cpp @@ -65,17 +62,17 @@ kcurrencycalculatordecl.ui kcurrencyeditdlg.ui kavailablecurrencydlg.ui kcurrencyeditordlg.ui keditscheduledlgdecl.ui kenterscheduledlgdecl.ui - kequitypriceupdatedlgdecl.ui kequitypriceupdateconfdlg.ui kexportdlgdecl.ui + kequitypriceupdatedlgdecl.ui kequitypriceupdateconfdlg.ui kfindtransactiondlgdecl.ui kgeneratesqldlgdecl.ui kgncimportoptionsdlgdecl.ui - kgncpricesourcedlgdecl.ui kimportdlgdecl.ui kloadtemplatedlgdecl.ui + kgncpricesourcedlgdecl.ui kloadtemplatedlgdecl.ui kmymoneyfileinfodlgdecl.ui kmymoneypricedlgdecl.ui knewaccountdlgdecl.ui knewbankdlgdecl.ui knewbudgetdlgdecl.ui knewequityentrydecl.ui editpersonaldatadlgdecl.ui kpayeereassigndlgdecl.ui ktagreassigndlgdecl.ui kselectdatabasedlgdecl.ui kselecttransactionsdlgdecl.ui ksortoptiondlg.ui ksplitcorrectiondlg.ui ksplittransactiondlgdecl.ui ktemplateexportdlg.ui - kupdatestockpricedlgdecl.ui mymoneyqifprofileeditordecl.ui + kupdatestockpricedlgdecl.ui ../widgets/kaccounttemplateselectordecl.ui ../widgets/transactionsortoptiondecl.ui konlinetransferformdecl.ui ) diff --git a/kmymoney/dialogs/kexportdlgdecl.ui b/kmymoney/dialogs/kexportdlgdecl.ui deleted file mode 100644 --- a/kmymoney/dialogs/kexportdlgdecl.ui +++ /dev/null @@ -1,424 +0,0 @@ - - - - - - KExportDlgDecl - - - QIF Export - - - true - - - - 11 - - - 6 - - - - - 0 - - - 6 - - - - - - 5 - 7 - 0 - 0 - - - - From this dialog you are able to export transactions to a quicken compatible file, (known as a QIF file, because of the extension). Please enter the path to the QIF file or select it by clicking on the Browse button. - -You can choose the file's path, the account and the format of the QIF file (profile). Choose Account to export all the transactions between the specified dates or just categories. You can also limit the transactions that are exported by start and ending date. Once you have pressed the Export button a message box will appear when the export has completed detailing how many transactions, categories and payees were exported. - - - Qt::AlignTop|Qt::AlignLeft - - - true - - - - - - - - - QFrame::HLine - - - QFrame::Raised - - - - - - - 0 - - - 6 - - - - - - 0 - 1 - 0 - 0 - - - - File to export to: - - - false - - - - - - - - - - &Browse... - - - - - - - - - - - - - Account to export - - - false - - - - - - - - - - - - 0 - - - 6 - - - - - QIF Profile - - - false - - - - - - - 0 - - - 6 - - - - - - 3 - 0 - 0 - 0 - - - - - 200 - 0 - - - - false - - - - - - - New... - - - - - - - - - - - - - - - Contents to Export - - - - 11 - - - 6 - - - - - Account - - - - - - - Categories - - - - - - - - - - Date Range - - - - 11 - - - 6 - - - - - - - - - - - 0 - 1 - 0 - 0 - - - - - 50 - 0 - - - - End on: - - - false - - - - - - - - 0 - 1 - 0 - 0 - - - - - 50 - 0 - - - - Start on: - - - false - - - - - - - - 3 - 1 - 0 - 0 - - - - - - - - - - - - - - 230 - 16 - - - - QSizePolicy::Expanding - - - Qt::Horizontal - - - - - - - - - QFrame::HLine - - - QFrame::Sunken - - - - - - - 0 - - - 6 - - - - - - 451 - 0 - - - - QSizePolicy::Expanding - - - Qt::Horizontal - - - - - - - &Export - - - true - - - true - - - - - - - Cancel - - - true - - - - - - - - - - - kMyMoneyDateInput - QWidget -
../widgets/kmymoneydateinput.h
- - 90 - 25 - - 0 - - 1 - 1 - - image0 -
- - KMyMoneyAccountCombo - QWidget -
../widgets/kmymoneyaccountcombo.h
- - -1 - 25 - - 0 - - 3 - 5 - - image1 -
- - KComboBox - QComboBox -
kcombobox.h
-
- - KLineEdit - QLineEdit -
klineedit.h
-
-
- - - 789c6dd2c10ac2300c00d07bbf2234b7229d1be245fc04c5a3201e4615f430059d0711ff5ddb2e6bb236ec90eed134cb5a19d8ef36602af5ecdbfeeac05dda0798d3abebde87e3faa374d3807fa0d633a52d38d8de6f679fe33fc776e196f53cd010188256a3600a292882096246517815ca99884606e18044a3a40d91824820924265a7923a2e8bcd05f33db1173e002913175f2a6be6d3294871a2d95fa00e8a94ee017b69d339d90df1e77c57ea072ede6758 - - - 789c9595c94eeb581086f73c4544ed50ab6eecd889ad562f1802843961a6d58b632764228c616cf5bb77f9d45fe75e11165c4c703e55d55fc319f8b152bb38daafadfc587a9abbf9b8ac9523f7585be93fcf66ef7ffff3d7bf4bcb715c93df2891d7f21f4bcb5cd4cadac1ddedc003fd02ddf9af16274075ffe3b91738f33c01276aa722b0b753ec390b7c0cce107f092e238d7fa838aa578fe713b0c5bf1aabdddd8033e49f1923be052e11df31867dc77366fe1c81cdbeab1c5b3d4d30f2d351c571dd988fc196ffda731e43cf811b98a79b06d6fa5e8c11ff1458e775054ec0dd8a1b91f9731d9ca9dd0d9513d35ff79c9b9dc7c68ddcdbf7c125ecefca16cf7e9e4994987dcfb34b73d86363e41f559cc6691ff93f8c119f2a3723b5bb8931faffc91abf691cabfd0e9c42ffd21876bf9ea90bf946c6a9f37ca66cf16e0c463fb46a8cf95e0456bb3346be3ad8fa3d34463fcf153763b33b678cf853e516e6415bc688bf31567fde04a7e8cffcd13ffbf56f4afea6ef971265f157bdd218f9d7c0e8878fc0a88ffdfe6f355a51abe1b9ad9c59ff0781fd7e62afdf2a5a79abf0f63765f377857123f2f67bb0e5f3e7256bb4f24cf3ed83fbcad4530efe99e722373e5476981faf05d679ad1aa3fe0b63ad8737c0982fed19c33ea8384ff2284f3c1f283b9be746609dc79bb19e37877837403d3bca458cf3531a23de9fdfbc147fed673bb0d6f7688cfc5960cdd737c6bc87caa2affe8dc09aefc338d17e3be026f291b1fad318ecb0bf38b0f677628cf5f1f7ab4b4c8f7363d4731b58eb2763d43f02231f9f0656bd8631f44cdfe6d535c67afaf9b8d245aef43c05a7e04439c44f8d511f2b9736cf79609d0ff44b9bd719d8ea7b0763fdd89f8742ea6beabfed73e53206df05d6fbecd618e7f311dc84ff0bd82993df7f453fd81f02abdecc58f737a56087fbf3d518f14f81f5bed17afb7dac07b58dd19fbfcfcab418383d3f73e550df36d8fa7f0eacfa57ca03ccbb3b67928ffbc6435eaf10ef92fb3ce06b1e7ef18c78cc138d80bee329dff08c6ff98eeff9811ff989e7fcecdf2ffcca6ffcfed39f0bf93610ef0f5ee5355ee70d6ef3266fc9df6deec8b3c3bbbcf7497f5fb40ff8503c8eb8cb3d6fedf1b1d0099f4accd927fd219f7bef0bf1eaf1255f719d23ff3de606279c7ed26f4addeba25629b738e39c98881c891695d45fd4a7016fd075e54d431ad1980f684253bae11ecde896ee16f41fe95e6c0f9c55def4484f92ab4573afd1a6e785fa5f65264ebc72effd22b1aff446eff421d60b5a5dd09fd39af8af134b254fbe8f8836a84d958aa3ad85fab765de3dea48979b555db4237ebbb447fbf23ea0c3c5fa799b643ea2d595ba7ba2bd2b9e0f744c27dca0d32feaef5029fe056f499767744e173413cb842ee98aea5fe877a4d7a85a577aa148a6b94fb1ecb3091d5183924ffa234a659f9c4ae61b8e6cffd2896837a945d9c2fa8e650fcadea2bc72e3b69399b842a2afe41eebbb81bbfea43f7143d983a91b714a776e4cab74e89f3a6db9899bba9b4ffadf7c82fe6ff857e7f7f7f425e25b39baf3e5fffe5cfa1fdc4beba0 - - -
diff --git a/kmymoney/dialogs/mymoneyqifprofileeditordecl.ui b/kmymoney/dialogs/mymoneyqifprofileeditordecl.ui deleted file mode 100644 --- a/kmymoney/dialogs/mymoneyqifprofileeditordecl.ui +++ /dev/null @@ -1,820 +0,0 @@ - - - - - - MyMoneyQifProfileEditorDecl - - - - 0 - 0 - 736 - 300 - - - - QIF Profile Editor - - - true - - - - 11 - - - 6 - - - - - - - - 0 - 7 - 0 - 0 - - - - - - - - - - - - - - General - - - - - - - - - 140 - 0 - - - - Void mark - - - false - - - - - - - - 140 - 0 - - - - Opening Balance text - - - false - - - - - - - - - - - 140 - 0 - - - - Type field text - - - false - - - - - - - - - - - - - - 140 - 0 - - - - Account delimiter - - - false - - - - - - - - - - - - - - 140 - 0 - - - - Description - - - false - - - - - - - - - Attempt to match similar transactions - - - - - - - - 20 - 20 - - - - QSizePolicy::Expanding - - - Qt::Vertical - - - - - - - - Filter - - - - - - - - - 140 - 0 - - - - Output filter location - - - false - - - - - - - - - - false - - - - - - - - 140 - 0 - - - - Input filter file type - - - false - - - - - - - *.qif - - - - - - - - 140 - 0 - - - - Input filter location - - - false - - - - - - - - - - 20 - 90 - - - - QSizePolicy::Expanding - - - Qt::Vertical - - - - - - - - Date - - - - - - - - - - The format of the dates in the QIF file. - - - - - - - - 140 - 0 - - - - Date Format - - - The format of the dates in the QIF file. - - - false - - - - - - - If a QIF file contains date entries with years represented with two digits then either an apostrophe or a slash may be used to delimit the year in the dates for certain centuries. This enables 1905 to be distinguished from 2005. Specify here which range of years will have year delimited by an apostrophe (eg. for Quicken this is usually 1900-1949). - - - - - - - - 140 - 0 - - - - Apostrophe Handling - - - If a QIF file contains date entries with years represented with two digits then either an apostrophe or a slash may be used to delimit the year in the dates for certain centuries. This enables 1905 to be distinguished from 2005. Specify here which range of years will have year delimited by an apostrophe (eg. for Quicken this is usually 1900-1949). - - - false - - - - - - - - - - 90 - 20 - - - - QSizePolicy::Expanding - - - Qt::Horizontal - - - - - - - - - - 20 - 80 - - - - QSizePolicy::Expanding - - - Qt::Vertical - - - - - - - - Amounts - - - - - - Qt::ScrollBarAlwaysOff - - - true - - - QAbstractItemView::SingleSelection - - - - Field - - - false - - - false - - - - - QIF-Record - - - false - - - false - - - - - Decimal Symbol - - - false - - - false - - - - - Thousand Delimiter - - - false - - - false - - - - - SortColumnInvisible - - - true - - - true - - - - - Value - - - T - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - Split-Value - - - $ - - - - - - - - - 1 - - - - - - - - - - - - - - - - - - - - Commission - - - O - - - - - - - - - 2 - - - - - - - - - - - - - - - - - - - - Price - - - I - - - - - - - - - 3 - - - - - - - - - - - - - - - - - - - - Quantity - - - Q - - - - - - - - - 4 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 150 - 0 - - - - Decimal Symbol - - - false - - - - - - - - 150 - 0 - - - - Thousands Separator - - - false - - - - - - - - - - - - - 100 - 20 - - - - QSizePolicy::Expanding - - - Qt::Horizontal - - - - - - - - - - 16 - 16 - - - - QSizePolicy::Expanding - - - Qt::Vertical - - - - - - - - - - - - - 0 - - - 6 - - - - - Help - - - - - - - New - - - - - - - Delete - - - - - - - Rename - - - - - - - - 104 - 0 - - - - QSizePolicy::Expanding - - - Qt::Horizontal - - - - - - - Reset - - - - - - - OK - - - - - - true - - - true - - - - - - - Cancel - - - - - - true - - - - - - - - - - - KComboBox - QComboBox -
kcombobox.h
-
- - KLineEdit - QLineEdit -
klineedit.h
-
- - QTabWidget - QTabWidget -
ktabwidget.h
-
-
- - m_profileListBox - profileTabs - m_editDescription - m_editType - m_editOpeningBalance - m_editAccountDelimiter - m_editVoidMark - m_helpButton - m_newButton - m_deleteButton - m_renameButton - m_resetButton - m_okButton - m_cancelButton - m_editDateFormat - m_editApostrophe - m_decimalBox - m_thousandsBox - m_editAmounts - m_editInputFilterLocation - m_editOutputFilterLocation - -
diff --git a/kmymoney/kmymoney.h b/kmymoney/kmymoney.h --- a/kmymoney/kmymoney.h +++ b/kmymoney/kmymoney.h @@ -53,7 +53,7 @@ enum class Action { FileOpenDatabase, FileSaveAsDatabase, FileBackup, - FileImportGNC, FileImportQIF, FileExportQIF, + FileImportGNC, FileImportStatement, FileImportTemplate, FileExportTemplate, #ifdef KMM_DEBUG @@ -76,7 +76,7 @@ AccountCreditTransfer, CategoryNew, CategoryEdit, CategoryDelete, - ToolQIF, ToolCurrencies, + ToolCurrencies, ToolPrices, ToolUpdatePrices, ToolConsistency, ToolPerformance, ToolSQL, ToolCalculator, @@ -214,20 +214,6 @@ */ void slotFileViewPersonal(); - /** - * Called when the user wishes to import tab delimeted transactions - * into the current account. An account must be open for this to - * work. Calls KMyMoneyView::slotAccountImportAscii. - * - * @see MyMoneyAccount - */ - void slotQifImport(); - - /** - * Called when a QIF import is finished. - */ - void slotQifImportFinished(); - /** * Opens a file selector dialog for the user to choose an existing OFX * file from the file system to be imported. This slot is expected to @@ -252,13 +238,6 @@ void slotLoadAccountTemplates(); void slotSaveAccountTemplates(); - /** - * Called when the user wishes to export some transaction to a - * QIF formatted file. An account must be open for this to work. - * Uses MyMoneyQifWriter() for the actual output. - */ - void slotQifExport(); - /** * Open up the application wide settings dialog. * @@ -303,8 +282,6 @@ void slotShowTipOfTheDay(); - void slotQifProfileEditor(); - void slotShowPreviousView(); void slotShowNextView(); @@ -713,22 +690,6 @@ QUrl selectFile(const QString& title, const QString& path, const QString& mask, QFileDialog::FileMode, QWidget *widget); - /** - * This methods returns the account from the list of accounts identified by - * an account id or account name including an account hierachy. - * - * The parent account specifies from which account the search should be started. - * In case the parent account does not have an id, the method scans all top-level accounts. - * - * If the account is not found in the list of accounts, MyMoneyAccount() is returned. - * - * @param acc account to find - * @param parent parent account to search from - * @retval found MyMoneyAccount account instance - * @retval MyMoneyAccount() if not found - */ - const MyMoneyAccount& findAccount(const MyMoneyAccount& acc, const MyMoneyAccount& parent) const; - void createAccount(MyMoneyAccount& newAccount, MyMoneyAccount& parentAccount, MyMoneyAccount& brokerageAccount, MyMoneyMoney openingBal); QString filename() const; diff --git a/kmymoney/kmymoney.cpp b/kmymoney/kmymoney.cpp --- a/kmymoney/kmymoney.cpp +++ b/kmymoney/kmymoney.cpp @@ -98,9 +98,6 @@ #include "dialogs/settings/ksettingskmymoney.h" #include "dialogs/kbackupdlg.h" -#include "dialogs/kexportdlg.h" -#include "dialogs/kimportdlg.h" -#include "dialogs/mymoneyqifprofileeditor.h" #include "dialogs/kenterscheduledlg.h" #include "dialogs/kconfirmmanualenterdlg.h" #include "dialogs/kmymoneypricedlg.h" @@ -149,8 +146,6 @@ #include "mymoney/onlinetransfer.h" #include "mymoney/onlinejobadministration.h" -#include "converter/mymoneyqifwriter.h" -#include "converter/mymoneyqifreader.h" #include "converter/mymoneystatementreader.h" #include "converter/mymoneytemplate.h" @@ -190,8 +185,6 @@ {Action::FileSaveAsDatabase, QStringLiteral("saveas_database")}, {Action::FileBackup, QStringLiteral("file_backup")}, {Action::FileImportGNC, QStringLiteral("file_import_gnc")}, - {Action::FileImportQIF, QStringLiteral("file_import_qif")}, - {Action::FileExportQIF, QStringLiteral("file_export_qif")}, {Action::FileImportStatement, QStringLiteral("file_import_statement")}, {Action::FileImportTemplate, QStringLiteral("file_import_template")}, {Action::FileExportTemplate, QStringLiteral("file_export_template")}, @@ -228,7 +221,6 @@ {Action::CategoryNew, QStringLiteral("category_new")}, {Action::CategoryEdit, QStringLiteral("category_edit")}, {Action::CategoryDelete, QStringLiteral("category_delete")}, - {Action::ToolQIF, QStringLiteral("tools_qif_editor")}, {Action::ToolCurrencies, QStringLiteral("tools_currency_editor")}, {Action::ToolPrices, QStringLiteral("tools_price_editor")}, {Action::ToolUpdatePrices, QStringLiteral("tools_update_prices")}, @@ -329,7 +321,6 @@ m_ignoreBackupExitCode(false), m_myMoneyView(0), m_progressBar(0), - m_qifReader(0), m_smtReader(0), m_searchDlg(0), m_autoSaveTimer(0), @@ -443,7 +434,6 @@ QTime m_lastUpdate; QLabel* m_statusLabel; - MyMoneyQifReader* m_qifReader; MyMoneyStatementReader* m_smtReader; // allows multiple imports to be launched trough web connect and to be executed sequentially QQueue m_importUrlsQueue; @@ -615,7 +605,6 @@ unloadPlugins(); delete d->m_searchDlg; - delete d->m_qifReader; delete d->m_transactionEditor; delete d->m_endingBalanceDlg; delete d->m_moveToAccountSelector; @@ -748,8 +737,6 @@ {Action::FileSaveAsDatabase, &KMyMoneyApp::slotSaveAsDatabase, i18n("Save as database..."), Icon::FileArchiver}, {Action::FileBackup, &KMyMoneyApp::slotBackupFile, i18n("Backup..."), Icon::Empty}, {Action::FileImportGNC, &KMyMoneyApp::slotGncImport, i18n("GnuCash..."), Icon::Empty}, - {Action::FileImportQIF, &KMyMoneyApp::slotQifImport, i18n("QIF..."), Icon::Empty}, - {Action::FileExportQIF, &KMyMoneyApp::slotQifExport, i18n("QIF..."), Icon::Empty}, {Action::FileImportStatement, &KMyMoneyApp::slotStatementImport, i18n("Statement file..."), Icon::Empty}, {Action::FileImportTemplate, &KMyMoneyApp::slotLoadAccountTemplates, i18n("Account Template..."), Icon::Empty}, {Action::FileExportTemplate, &KMyMoneyApp::slotSaveAccountTemplates, i18n("Account Template..."), Icon::Empty}, @@ -804,7 +791,6 @@ // ************** // The tools menu // ************** - {Action::ToolQIF, &KMyMoneyApp::slotQifProfileEditor, i18n("QIF Profile Editor..."), Icon::DocumentProperties}, {Action::ToolCurrencies, &KMyMoneyApp::slotCurrencyDialog, i18n("Currencies..."), Icon::ViewCurrencyList}, {Action::ToolPrices, &KMyMoneyApp::slotPriceDialog, i18n("Prices..."), Icon::Empty}, {Action::ToolUpdatePrices, &KMyMoneyApp::slotEquityPriceUpdate, i18n("Update Stock and Currency Prices..."), Icon::Empty}, @@ -2075,98 +2061,6 @@ } } -void KMyMoneyApp::slotQifImport() -{ - if (d->m_qifReader == 0) { - // FIXME: the menu entry for qif import should be disabled here - - QPointer dlg = new KImportDlg(this); - - if (dlg->exec() == QDialog::Accepted && dlg != 0) { - KMSTATUS(i18n("Importing file...")); - d->m_qifReader = new MyMoneyQifReader; - - // remove all kmm-statement-#.txt files - d->unlinkStatementXML(); - - connect(d->m_qifReader, SIGNAL(importFinished()), this, SLOT(slotQifImportFinished())); - - d->m_qifReader->setURL(dlg->file()); - - d->m_qifReader->setProfile(dlg->profile()); - d->m_qifReader->setCategoryMapping(dlg->m_typeComboBox->currentIndex() == 0); - d->m_qifReader->setProgressCallback(&progressCallback); - - // disable all standard widgets during the import - setEnabled(false); - - d->m_ft = new MyMoneyFileTransaction(); - d->m_collectingStatements = true; - d->m_statementResults.clear(); - if (!d->m_qifReader->startImport()) { - // if the import failed to start make sure that slotQifImportFinished is called otherwise the application will be left disabled - QTimer::singleShot(0, this, SLOT(slotQifImportFinished())); - } - } - delete dlg; - - slotUpdateActions(); - } -} - -void KMyMoneyApp::slotQifImportFinished() -{ - if (d->m_qifReader != 0) { - d->m_qifReader->finishImport(); - d->m_ft->commit(); - d->m_collectingStatements = false; - - KMessageBox::informationList(this, i18n("The statements have been processed with the following results:"), d->m_statementResults, i18n("Statement stats")); - -#if 0 - // fixme: re-enable the QIF import menu options - if (d->m_qifReader->finishImport()) { - if (verifyImportedData(d->m_qifReader->account())) { - // keep the new data set, destroy the backup copy - delete d->m_engineBackup; - d->m_engineBackup = 0; - } - } - - if (d->m_engineBackup != 0) { - // user cancelled, destroy the updated set and keep the backup copy - IMyMoneyStorage* data = file->storage(); - - - if (data != 0) { - file->detachStorage(data); - delete data; - } - file->attachStorage(d->m_engineBackup); - d->m_engineBackup = 0; - - } -#endif - - // update the views as they might still contain invalid data - // from the import session. The same applies for the window caption - d->m_myMoneyView->slotRefreshViews(); - updateCaption(); - - delete d->m_qifReader; - d->m_qifReader = 0; - } - delete d->m_ft; - d->m_ft = 0; - - slotStatusProgressBar(-1, -1); - ready(); - - // re-enable all standard widgets - setEnabled(true); - slotUpdateActions(); -} - void KMyMoneyApp::slotGncImport() { if (d->m_myMoneyView->fileOpen()) { @@ -2325,25 +2219,6 @@ return result; } -void KMyMoneyApp::slotQifExport() -{ - KMSTATUS(i18n("Exporting file...")); - - QPointer dlg = new KExportDlg(this); - - if (dlg->exec() == QDialog::Accepted && dlg != 0) { - if (okToWriteFile(QUrl::fromLocalFile(dlg->filename()))) { - MyMoneyQifWriter writer; - connect(&writer, SIGNAL(signalProgress(int,int)), this, SLOT(slotStatusProgressBar(int,int))); - - writer.write(dlg->filename(), dlg->profile(), dlg->accountId(), - dlg->accountSelected(), dlg->categorySelected(), - dlg->startDate(), dlg->endDate()); - } - } - delete dlg; -} - bool KMyMoneyApp::okToWriteFile(const QUrl &url) { Q_UNUSED(url) @@ -2657,15 +2532,6 @@ delete editor; } -void KMyMoneyApp::slotQifProfileEditor() -{ - QPointer editor = new MyMoneyQifProfileEditor(true, this); - editor->setObjectName("QIF Profile Editor"); - editor->exec(); - delete editor; - -} - void KMyMoneyApp::slotToolsStartKCalc() { QString cmd = KMyMoneyGlobalSettings::externalCalculator(); @@ -2796,64 +2662,6 @@ } } -const MyMoneyAccount& KMyMoneyApp::findAccount(const MyMoneyAccount& acc, const MyMoneyAccount& parent) const -{ - static MyMoneyAccount nullAccount; - - MyMoneyFile* file = MyMoneyFile::instance(); - QList parents; - try { - // search by id - if (!acc.id().isEmpty()) { - return file->account(acc.id()); - } - // collect the parents. in case parent does not have an id, we scan the all top-level accounts - if (parent.id().isEmpty()) { - parents << file->asset(); - parents << file->liability(); - parents << file->income(); - parents << file->expense(); - parents << file->equity(); - } else { - parents << parent; - } - QList::const_iterator it_p; - for (it_p = parents.constBegin(); it_p != parents.constEnd(); ++it_p) { - MyMoneyAccount parentAccount = *it_p; - // search by name (allow hierarchy) - int pos; - // check for ':' in the name and use it as separator for a hierarchy - QString name = acc.name(); - bool notFound = false; - while ((pos = name.indexOf(MyMoneyFile::AccountSeperator)) != -1) { - QString part = name.left(pos); - QString remainder = name.mid(pos + 1); - const MyMoneyAccount& existingAccount = file->subAccountByName(parentAccount, part); - // if account has not been found, continue with next top level parent - if (existingAccount.id().isEmpty()) { - notFound = true; - break; - } - parentAccount = existingAccount; - name = remainder; - } - if (notFound) - continue; - const MyMoneyAccount& existingAccount = file->subAccountByName(parentAccount, name); - if (!existingAccount.id().isEmpty()) { - if (acc.accountType() != MyMoneyAccount::UnknownAccountType) { - if (acc.accountType() != existingAccount.accountType()) - continue; - } - return existingAccount; - } - } - } catch (const MyMoneyException &e) { - KMessageBox::error(0, i18n("Unable to find account: %1", e.what())); - } - return nullAccount; -} - void KMyMoneyApp::createAccount(MyMoneyAccount& newAccount, MyMoneyAccount& parentAccount, MyMoneyAccount& brokerageAccount, MyMoneyMoney openingBal) { MyMoneyFile *file = MyMoneyFile::instance(); @@ -6182,7 +5990,7 @@ MyMoneyFile* file = MyMoneyFile::instance(); const bool fileOpen = d->m_myMoneyView->fileOpen(); const bool modified = file->dirty(); - const bool importRunning = (d->m_qifReader != 0) || (d->m_smtReader != 0); + const bool importRunning = (d->m_smtReader != 0); QWidget* w; KActionCollection *aC = actionCollection(); @@ -6225,8 +6033,6 @@ {qMakePair(Action::FilePersonalData, fileOpen)}, {qMakePair(Action::FileBackup, (fileOpen && !d->m_myMoneyView->isDatabase()))}, {qMakePair(Action::FileInformation, fileOpen)}, - {qMakePair(Action::FileExportQIF, fileOpen && !importRunning)}, - {qMakePair(Action::FileImportQIF, fileOpen && !importRunning)}, {qMakePair(Action::FileImportGNC, !importRunning)}, {qMakePair(Action::FileImportTemplate, fileOpen && !importRunning)}, {qMakePair(Action::FileExportTemplate, fileOpen && !importRunning)}, diff --git a/kmymoney/kmymoneyui.rc b/kmymoney/kmymoneyui.rc --- a/kmymoney/kmymoneyui.rc +++ b/kmymoney/kmymoneyui.rc @@ -6,16 +6,14 @@ &Import - &Export - @@ -97,7 +95,6 @@ T&ools - diff --git a/kmymoney/plugins/CMakeLists.txt b/kmymoney/plugins/CMakeLists.txt --- a/kmymoney/plugins/CMakeLists.txt +++ b/kmymoney/plugins/CMakeLists.txt @@ -3,6 +3,7 @@ add_subdirectory( interfaces ) add_subdirectory( csvimport ) add_subdirectory( csvexport ) +add_subdirectory( qif ) if(LIBOFX_FOUND) add_subdirectory( ofximport ) diff --git a/kmymoney/plugins/qif/CMakeLists.txt b/kmymoney/plugins/qif/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/kmymoney/plugins/qif/CMakeLists.txt @@ -0,0 +1,11 @@ +if(ENABLE_QIFIMPORTER) + add_subdirectory( import ) +endif() + +if(ENABLE_QIFEXPORTER) + add_subdirectory( export ) +endif() + +if(ENABLE_QIFIMPORTER OR ENABLE_QIFEXPORTER) + add_subdirectory( config ) +endif() diff --git a/kmymoney/plugins/qif/config/CMakeLists.txt b/kmymoney/plugins/qif/config/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/kmymoney/plugins/qif/config/CMakeLists.txt @@ -0,0 +1,41 @@ +# the KCM module +set(kcm_kmm_qif_PART_SRCS + mymoneyqifprofileeditor.cpp + mymoneyqifprofile.cpp + kcm_qif.cpp + ) + +ki18n_wrap_ui(kcm_kmm_qif_PART_SRCS mymoneyqifprofileeditor.ui) + +add_library(kcm_kmm_qif MODULE ${kcm_kmm_qif_PART_SRCS}) + +if(ENABLE_QIFIMPORTER) + kcoreaddons_desktop_to_json(kcm_kmm_qif kcm_kmm_qifimport.desktop) +endif() + +if(ENABLE_QIFEXPORTER) + kcoreaddons_desktop_to_json(kcm_kmm_qif kcm_kmm_qifexport.desktop) +endif() + + +target_link_libraries(kcm_kmm_qif + kmm_mymoney + KF5::I18n + KF5::ConfigWidgets + KF5::Completion + KF5::KIOWidgets + ) + +install(TARGETS kcm_kmm_qif + DESTINATION ${KDE_INSTALL_PLUGINDIR}) + +if(ENABLE_QIFIMPORTER) + install(FILES kcm_kmm_qifimport.desktop + DESTINATION ${SERVICES_INSTALL_DIR}) +endif() + +if(ENABLE_QIFEXPORTER) + install(FILES kcm_kmm_qifexport.desktop + DESTINATION ${SERVICES_INSTALL_DIR}) +endif() + diff --git a/kmymoney/plugins/qif/config/kcm_kmm_qifexport.desktop b/kmymoney/plugins/qif/config/kcm_kmm_qifexport.desktop new file mode 100644 --- /dev/null +++ b/kmymoney/plugins/qif/config/kcm_kmm_qifexport.desktop @@ -0,0 +1,15 @@ +[Desktop Entry] +Name=QIF Importer configuration +Name[x-test]=xxQIF Importer configurationxx +Icon=document-import +Type=Service +ServiceTypes=KCModule +Exec=kcmshell5 kmm_qifexport +Categories=Qt;KDE;kmymoney; +Keywords=qifexport;kmymoney; +Keywords[x-test]=xxqifimportxx;xxkmymoneyxx; +X-KDE-Library=kcm_kmm_qif +X-KDE-ParentApp=qifexport +X-KDE-ParentComponents=qifexport +Comment=Configuration for QIF Importer plugin +Comment[x-test]=xxConfiguration for QIF Importer pluginxx diff --git a/kmymoney/plugins/qif/config/kcm_kmm_qifimport.desktop b/kmymoney/plugins/qif/config/kcm_kmm_qifimport.desktop new file mode 100644 --- /dev/null +++ b/kmymoney/plugins/qif/config/kcm_kmm_qifimport.desktop @@ -0,0 +1,15 @@ +[Desktop Entry] +Name=QIF Importer configuration +Name[x-test]=xxQIF Importer configurationxx +Icon=document-import +Type=Service +ServiceTypes=KCModule +Exec=kcmshell5 kmm_qifimport +Categories=Qt;KDE;kmymoney; +Keywords=qifimport;kmymoney; +Keywords[x-test]=xxqifimportxx;xxkmymoneyxx; +X-KDE-Library=kcm_kmm_qif +X-KDE-ParentApp=qifimport +X-KDE-ParentComponents=qifimport +Comment=Configuration for QIF Importer plugin +Comment[x-test]=xxConfiguration for QIF Importer pluginxx diff --git a/kmymoney/plugins/qif/config/kcm_qif.h b/kmymoney/plugins/qif/config/kcm_qif.h new file mode 100644 --- /dev/null +++ b/kmymoney/plugins/qif/config/kcm_qif.h @@ -0,0 +1,32 @@ +/*************************************************************************** + * Copyright 2017 Łukasz Wojniłowicz lukasz.wojnilowicz@gmail.com * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 2 of * + * the License or (at your option) version 3 or any later version * + * accepted by the membership of KDE e.V. (or its successor approved * + * by the membership of KDE e.V.), which shall act as a proxy * + * defined in Section 14 of version 3 of the license. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see * + ***************************************************************************/ +#ifndef KCM_QIF_H +#define KCM_QIF_H + +#include + +class KCMqif : public KCModule +{ +public: + KCMqif(QWidget* parent, const QVariantList& args); +}; + +#endif // KCM_QIF_H + diff --git a/kmymoney/plugins/qif/config/kcm_qif.cpp b/kmymoney/plugins/qif/config/kcm_qif.cpp new file mode 100644 --- /dev/null +++ b/kmymoney/plugins/qif/config/kcm_qif.cpp @@ -0,0 +1,40 @@ +/*************************************************************************** + * Copyright 2017 Łukasz Wojniłowicz lukasz.wojnilowicz@gmail.com * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 2 of * + * the License or (at your option) version 3 or any later version * + * accepted by the membership of KDE e.V. (or its successor approved * + * by the membership of KDE e.V.), which shall act as a proxy * + * defined in Section 14 of version 3 of the license. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see * + ***************************************************************************/ + +#include "kcm_qif.h" + +// KDE includes +#include + +#include "mymoneyqifprofileeditor.h" + +K_PLUGIN_FACTORY(KCMqifFactory, registerPlugin();) + +KCMqif::KCMqif(QWidget *parent, const QVariantList& args) : KCModule(0/*KCMqifFactory::componentData()*/, parent, args) +{ + auto editor = new MyMoneyQifProfileEditor(true, this); + auto layout = new QVBoxLayout; + setLayout(layout); + layout->addWidget(editor); + setButtons(NoAdditionalButton); + load(); +} + +#include "kcm_qif.moc" diff --git a/kmymoney/converter/mymoneyqifprofile.h b/kmymoney/plugins/qif/config/mymoneyqifprofile.h rename from kmymoney/converter/mymoneyqifprofile.h rename to kmymoney/plugins/qif/config/mymoneyqifprofile.h diff --git a/kmymoney/converter/mymoneyqifprofile.cpp b/kmymoney/plugins/qif/config/mymoneyqifprofile.cpp rename from kmymoney/converter/mymoneyqifprofile.cpp rename to kmymoney/plugins/qif/config/mymoneyqifprofile.cpp diff --git a/kmymoney/dialogs/mymoneyqifprofileeditor.h b/kmymoney/plugins/qif/config/mymoneyqifprofileeditor.h rename from kmymoney/dialogs/mymoneyqifprofileeditor.h rename to kmymoney/plugins/qif/config/mymoneyqifprofileeditor.h --- a/kmymoney/dialogs/mymoneyqifprofileeditor.h +++ b/kmymoney/plugins/qif/config/mymoneyqifprofileeditor.h @@ -31,7 +31,7 @@ // ---------------------------------------------------------------------------- // Project Includes -#include "ui_mymoneyqifprofileeditordecl.h" +#include "ui_mymoneyqifprofileeditor.h" #include "mymoneyqifprofile.h" /** @@ -50,15 +50,7 @@ }; -class MyMoneyQifProfileEditorDecl : public QDialog, public Ui::MyMoneyQifProfileEditorDecl -{ -public: - MyMoneyQifProfileEditorDecl(QWidget *parent) : QDialog(parent) { - setupUi(this); - } -}; - -class MyMoneyQifProfileEditor : public MyMoneyQifProfileEditorDecl +class MyMoneyQifProfileEditor : public QWidget, public Ui::MyMoneyQifProfileEditor { Q_OBJECT @@ -71,9 +63,6 @@ */ const QString selectedProfile() const; -public slots: - void slotOk(); - protected slots: void slotLoadProfileFromConfig(const QString& name); void slotReset(); diff --git a/kmymoney/dialogs/mymoneyqifprofileeditor.cpp b/kmymoney/plugins/qif/config/mymoneyqifprofileeditor.cpp rename from kmymoney/dialogs/mymoneyqifprofileeditor.cpp rename to kmymoney/plugins/qif/config/mymoneyqifprofileeditor.cpp --- a/kmymoney/dialogs/mymoneyqifprofileeditor.cpp +++ b/kmymoney/plugins/qif/config/mymoneyqifprofileeditor.cpp @@ -76,19 +76,18 @@ } MyMoneyQifProfileEditor::MyMoneyQifProfileEditor(const bool edit, QWidget *parent) - : MyMoneyQifProfileEditorDecl(parent), + : QWidget(parent), m_inEdit(edit), m_isDirty(false), m_isAccepted(false), m_selectedAmountType(0) { + setupUi(this); loadWidgets(); loadProfileListFromConfig(); // load button icons KGuiItem::assign(m_resetButton, KStandardGuiItem::reset()); - KGuiItem::assign(m_cancelButton, KStandardGuiItem::cancel()); - KGuiItem::assign(m_okButton, KStandardGuiItem::ok()); KGuiItem::assign(m_deleteButton, KStandardGuiItem::del()); KGuiItem::assign(m_helpButton, KStandardGuiItem::help()); @@ -98,37 +97,35 @@ i18n("Use this to create a new QIF import/export profile")); KGuiItem::assign(m_newButton, newButtenItem); - connect(m_profileListBox, SIGNAL(currentTextChanged(QString)), this, SLOT(slotLoadProfileFromConfig(QString))); - connect(m_resetButton, SIGNAL(clicked()), this, SLOT(slotReset())); - connect(m_okButton, SIGNAL(clicked()), this, SLOT(slotOk())); - connect(m_renameButton, SIGNAL(clicked()), this, SLOT(slotRename())); - connect(m_deleteButton, SIGNAL(clicked()), this, SLOT(slotDelete())); - connect(m_newButton, SIGNAL(clicked()), this, SLOT(slotNew())); - connect(m_cancelButton, SIGNAL(clicked()), this, SLOT(reject())); - connect(m_helpButton, SIGNAL(clicked()), this, SLOT(slotHelp())); - - connect(m_editDescription, SIGNAL(textChanged(QString)), &m_profile, SLOT(setProfileDescription(QString))); - connect(m_editType, SIGNAL(textChanged(QString)), &m_profile, SLOT(setProfileType(QString))); - connect(m_editOpeningBalance, SIGNAL(textChanged(QString)), &m_profile, SLOT(setOpeningBalanceText(QString))); - connect(m_editAccountDelimiter, SIGNAL(textChanged(QString)), &m_profile, SLOT(setAccountDelimiter(QString))); - connect(m_editVoidMark, SIGNAL(textChanged(QString)), &m_profile, SLOT(setVoidMark(QString))); + connect(m_profileListBox, &QListWidget::currentTextChanged, this, &MyMoneyQifProfileEditor::slotLoadProfileFromConfig); + connect(m_resetButton, &QAbstractButton::clicked, this, &MyMoneyQifProfileEditor::slotReset); + connect(m_renameButton, &QAbstractButton::clicked, this, &MyMoneyQifProfileEditor::slotRename); + connect(m_deleteButton, &QAbstractButton::clicked, this, &MyMoneyQifProfileEditor::slotDelete); + connect(m_newButton, &QAbstractButton::clicked, this, &MyMoneyQifProfileEditor::slotNew); + connect(m_helpButton, &QAbstractButton::clicked, this, &MyMoneyQifProfileEditor::slotHelp); + + connect(m_editDescription, &QLineEdit::textChanged, &m_profile, &MyMoneyQifProfile::setProfileDescription); + connect(m_editType, &QLineEdit::textChanged, &m_profile, &MyMoneyQifProfile::setProfileType); + connect(m_editOpeningBalance, &QLineEdit::textChanged, &m_profile, &MyMoneyQifProfile::setOpeningBalanceText); + connect(m_editAccountDelimiter, &QLineEdit::textChanged, &m_profile, &MyMoneyQifProfile::setAccountDelimiter); + connect(m_editVoidMark, &QLineEdit::textChanged, &m_profile, &MyMoneyQifProfile::setVoidMark); connect(m_editDateFormat, SIGNAL(highlighted(QString)), &m_profile, SLOT(setOutputDateFormat(QString))); connect(m_editApostrophe, SIGNAL(highlighted(QString)), &m_profile, SLOT(setApostropheFormat(QString))); - connect(m_editAmounts, SIGNAL(itemSelectionChanged()), this, SLOT(slotAmountTypeSelected())); + connect(m_editAmounts, &QTreeWidget::itemSelectionChanged, this, &MyMoneyQifProfileEditor::slotAmountTypeSelected); connect(m_decimalBox, SIGNAL(activated(QString)), this, SLOT(slotDecimalChanged(QString))); connect(m_thousandsBox, SIGNAL(activated(QString)), this, SLOT(slotThousandsChanged(QString))); - connect(m_editInputFilterLocation, SIGNAL(textChanged(QString)), &m_profile, SLOT(setFilterScriptImport(QString))); - connect(m_editInputFilterLocation, SIGNAL(urlSelected(QUrl)), m_editInputFilterLocation, SLOT(setUrl(QUrl))); + connect(m_editInputFilterLocation, &KUrlRequester::textChanged, &m_profile, &MyMoneyQifProfile::setFilterScriptImport); + connect(m_editInputFilterLocation, &KUrlRequester::urlSelected, m_editInputFilterLocation, &KUrlRequester::setUrl); - connect(m_editInputFilterFileType, SIGNAL(textChanged(QString)), &m_profile, SLOT(setFilterFileType(QString))); + connect(m_editInputFilterFileType, &QLineEdit::textChanged, &m_profile, &MyMoneyQifProfile::setFilterFileType); - connect(m_editOutputFilterLocation, SIGNAL(textChanged(QString)), &m_profile, SLOT(setFilterScriptExport(QString))); - connect(m_editOutputFilterLocation, SIGNAL(urlSelected(QUrl)), m_editOutputFilterLocation, SLOT(setUrl(QUrl))); + connect(m_editOutputFilterLocation, &KUrlRequester::textChanged, &m_profile, &MyMoneyQifProfile::setFilterScriptExport); + connect(m_editOutputFilterLocation, &KUrlRequester::urlSelected, m_editOutputFilterLocation, &KUrlRequester::setUrl); - connect(m_attemptMatch, SIGNAL(toggled(bool)), &m_profile, SLOT(setAttemptMatchDuplicates(bool))); + connect(m_attemptMatch, &QAbstractButton::toggled, &m_profile, &MyMoneyQifProfile::setAttemptMatchDuplicates); } MyMoneyQifProfileEditor::~MyMoneyQifProfileEditor() @@ -346,20 +343,6 @@ m_isDirty = true; } -void MyMoneyQifProfileEditor::slotOk() -{ - if (m_profile.isDirty()) - m_isDirty = true; - - m_profile.saveProfile(); - - KSharedConfigPtr config = KSharedConfig::openConfig(); - config->sync(); - - m_isAccepted = true; - accept(); -} - void MyMoneyQifProfileEditor::slotReset() { // first flush any changes diff --git a/kmymoney/plugins/qif/config/mymoneyqifprofileeditor.ui b/kmymoney/plugins/qif/config/mymoneyqifprofileeditor.ui new file mode 100644 --- /dev/null +++ b/kmymoney/plugins/qif/config/mymoneyqifprofileeditor.ui @@ -0,0 +1,696 @@ + + + MyMoneyQifProfileEditor + + + + 0 + 0 + 736 + 334 + + + + QIF Profile Editor + + + + 6 + + + 11 + + + 11 + + + 11 + + + 11 + + + + + + + + 0 + 0 + + + + + + + + + + + + + + General + + + + + + + + + 140 + 0 + + + + Void mark + + + false + + + + + + + + 140 + 0 + + + + Opening Balance text + + + false + + + + + + + + + + + 140 + 0 + + + + Type field text + + + false + + + + + + + + + + + + + + 140 + 0 + + + + Account delimiter + + + false + + + + + + + + + + + + + + 140 + 0 + + + + Description + + + false + + + + + + + + + Attempt to match similar transactions + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 20 + + + + + + + + + Filter + + + + + + + + + 140 + 0 + + + + Output filter location + + + false + + + + + + + + + + false + + + + + + + + 140 + 0 + + + + Input filter file type + + + false + + + + + + + *.qif + + + + + + + + 140 + 0 + + + + Input filter location + + + false + + + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 90 + + + + + + + + + Date + + + + + + + + + + The format of the dates in the QIF file. + + + + + + + + 140 + 0 + + + + The format of the dates in the QIF file. + + + Date Format + + + false + + + + + + + If a QIF file contains date entries with years represented with two digits then either an apostrophe or a slash may be used to delimit the year in the dates for certain centuries. This enables 1905 to be distinguished from 2005. Specify here which range of years will have year delimited by an apostrophe (eg. for Quicken this is usually 1900-1949). + + + + + + + + 140 + 0 + + + + If a QIF file contains date entries with years represented with two digits then either an apostrophe or a slash may be used to delimit the year in the dates for certain centuries. This enables 1905 to be distinguished from 2005. Specify here which range of years will have year delimited by an apostrophe (eg. for Quicken this is usually 1900-1949). + + + Apostrophe Handling + + + false + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 90 + 20 + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 80 + + + + + + + + + Amounts + + + + + + Qt::ScrollBarAlwaysOff + + + QAbstractItemView::SingleSelection + + + true + + + + Field + + + + + QIF-Record + + + + + Decimal Symbol + + + + + Thousand Delimiter + + + + + SortColumnInvisible + + + + + Value + + + T + + + + + + + + + 0 + + + + + Split-Value + + + $ + + + + + + + + + 1 + + + + + Commission + + + O + + + + + + + + + 2 + + + + + Price + + + I + + + + + + + + + 3 + + + + + Quantity + + + Q + + + + + + + + + 4 + + + + + + + + + + + + + + + + 150 + 0 + + + + Decimal Symbol + + + false + + + + + + + + 150 + 0 + + + + Thousands Separator + + + false + + + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 100 + 20 + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 16 + 16 + + + + + + + + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Help + + + + + + + New + + + + + + + Delete + + + + + + + Rename + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 104 + 0 + + + + + + + + Reset + + + + + + + + + + + KUrlRequester + QWidget +
kurlrequester.h
+
+ + KLineEdit + QLineEdit +
klineedit.h
+
+ + KComboBox + QComboBox +
kcombobox.h
+
+
+ + m_profileListBox + profileTabs + m_editDescription + m_editType + m_editOpeningBalance + m_editAccountDelimiter + m_editVoidMark + m_helpButton + m_newButton + m_deleteButton + m_renameButton + m_resetButton + m_editDateFormat + m_editApostrophe + m_decimalBox + m_thousandsBox + m_editAmounts + m_editInputFilterLocation + m_editOutputFilterLocation + + + +
diff --git a/kmymoney/plugins/qif/export/CMakeLists.txt b/kmymoney/plugins/qif/export/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/kmymoney/plugins/qif/export/CMakeLists.txt @@ -0,0 +1,33 @@ +# patch the version with the version defined in the build system +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/qifexport.json.in ${CMAKE_CURRENT_BINARY_DIR}/qifexport.json @ONLY) + +########### next target ############### + +set(kmm_qifexport_PART_SRCS + qifexporterplugin.cpp + ../config/mymoneyqifprofile.cpp + mymoneyqifwriter.cpp + kexportdlg.cpp + ${CMAKE_SOURCE_DIR}/kmymoney/widgets/kmymoneyaccountcombo.cpp +) + +set(kmm_qifexport_PART_UI + kexportdlgdecl.ui +) + +ki18n_wrap_ui(kmm_qifexport_PART_SRCS ${kmm_qifexport_PART_UI}) + +add_library(kmm_qifexport MODULE ${kmm_qifexport_PART_SRCS}) + +target_link_libraries(kmm_qifexport + kmm_plugin + models #TODO: Get rid of this big dependency +) + +########### install files ############### + +install(FILES kmm_qifexport.rc + DESTINATION "${KXMLGUI_INSTALL_DIR}/kmm_qifexport") + +install(TARGETS kmm_qifexport + DESTINATION "${KDE_INSTALL_PLUGINDIR}/kmymoney/") diff --git a/kmymoney/plugins/qif/export/kcm_kmm_qifexport.desktop b/kmymoney/plugins/qif/export/kcm_kmm_qifexport.desktop new file mode 100644 --- /dev/null +++ b/kmymoney/plugins/qif/export/kcm_kmm_qifexport.desktop @@ -0,0 +1,15 @@ +[Desktop Entry] +Name=QIF Importer configuration +Name[x-test]=xxQIF Importer configurationxx +Icon=document-import +Type=Service +ServiceTypes=KCModule +Exec=kcmshell5 kmm_qifimport +Categories=Qt;KDE;kmymoney; +Keywords=qifexport;kmymoney; +Keywords[x-test]=xxqifimportxx;xxkmymoneyxx; +X-KDE-Library=kcm_kmm_qifimport +X-KDE-ParentApp=qifexport +X-KDE-ParentComponents=qifexport +Comment=Configuration for QIF Importer plugin +Comment[x-test]=xxConfiguration for QIF Importer pluginxx diff --git a/kmymoney/dialogs/kexportdlg.h b/kmymoney/plugins/qif/export/kexportdlg.h rename from kmymoney/dialogs/kexportdlg.h rename to kmymoney/plugins/qif/export/kexportdlg.h --- a/kmymoney/dialogs/kexportdlg.h +++ b/kmymoney/plugins/qif/export/kexportdlg.h @@ -134,11 +134,6 @@ */ void slotBrowse(); - /** - * Called when the user needs a new profile - */ - void slotNewProfile(); - /** * This slot checks whether all data is correct to enable * the 'Export' button. The enable state of the 'Export' button diff --git a/kmymoney/dialogs/kexportdlg.cpp b/kmymoney/plugins/qif/export/kexportdlg.cpp rename from kmymoney/dialogs/kexportdlg.cpp rename to kmymoney/plugins/qif/export/kexportdlg.cpp --- a/kmymoney/dialogs/kexportdlg.cpp +++ b/kmymoney/plugins/qif/export/kexportdlg.cpp @@ -28,6 +28,7 @@ #include #include #include +#include // ---------------------------------------------------------------------------- // KDE Headers @@ -43,7 +44,6 @@ // Project Headers #include "mymoneycategory.h" -#include "mymoneyqifprofileeditor.h" #include "mymoneyfile.h" #include "kmymoneyaccountcombo.h" #include "kmymoneyutils.h" @@ -76,18 +76,10 @@ i18n("Use this to select a filename to export to")); KGuiItem::assign(m_qbuttonBrowse, browseButtenItem); - KGuiItem newButtenItem(i18nc("New profile", "&New..."), - QIcon::fromTheme(g_Icons[Icon::DocumentNew]), - i18n("Create a new profile"), - i18n("Use this to open the profile editor")); - KGuiItem::assign(m_profileEditorButton, newButtenItem); - - // connect the buttons to their functionality - connect(m_qbuttonBrowse, SIGNAL(clicked()), this, SLOT(slotBrowse())); - connect(m_profileEditorButton, SIGNAL(clicked()), this, SLOT(slotNewProfile())); - connect(m_qbuttonOk, SIGNAL(clicked()), this, SLOT(slotOkClicked())); - connect(m_qbuttonCancel, SIGNAL(clicked()), this, SLOT(reject())); + connect(m_qbuttonBrowse, &QAbstractButton::clicked, this, &KExportDlg::slotBrowse); + connect(m_qbuttonOk, &QAbstractButton::clicked, this, &KExportDlg::slotOkClicked); + connect(m_qbuttonCancel, &QAbstractButton::clicked, this, &QDialog::reject); // connect the change signals to the check slot and perform initial check connect(m_qlineeditFile, SIGNAL(textChanged(QString)), this, SLOT(checkData())); @@ -107,31 +99,15 @@ void KExportDlg::slotBrowse() { - QString newName(QFileDialog::getSaveFileName(this, QString(), QString(), QLatin1String("*.QIF"))); - KMyMoneyUtils::appendCorrectFileExt(newName, QLatin1String("qif")); + auto newName(QFileDialog::getSaveFileName(this, QString(), QString(), QLatin1String("*.QIF"))); + if (!newName.endsWith(QLatin1String(".qif"), Qt::CaseInsensitive)) + newName.append(QLatin1String(".qif")); if (!newName.isEmpty()) m_qlineeditFile->setText(newName); } -void KExportDlg::slotNewProfile() -{ - QPointer editor = new MyMoneyQifProfileEditor(true, this); - editor->setObjectName("QIF Profile Editor"); - if (editor->exec()) { - m_profileComboBox->setCurrentIndex(m_profileComboBox->findText(editor->selectedProfile(), Qt::MatchExactly)); - loadProfiles(); - } - delete editor; -} - void KExportDlg::loadProfiles(const bool selectLast) { - // Creating an editor object here makes sure that - // we have at least the default profile available - MyMoneyQifProfileEditor* edit = new MyMoneyQifProfileEditor(true, 0); - edit->slotOk(); - delete edit; - QString current = m_profileComboBox->currentText(); m_profileComboBox->clear(); @@ -192,9 +168,10 @@ bool okEnabled = false; if (!m_qlineeditFile->text().isEmpty()) { - QString strFile(m_qlineeditFile->text()); - if (KMyMoneyUtils::appendCorrectFileExt(strFile, QString("qif"))) - m_qlineeditFile->setText(strFile); + auto strFile(m_qlineeditFile->text()); + if (!strFile.endsWith(QLatin1String(".qif"), Qt::CaseInsensitive)) + strFile.append(QLatin1String(".qif")); + m_qlineeditFile->setText(strFile); } MyMoneyAccount account; @@ -233,6 +210,7 @@ auto filterProxyModel = new AccountNamesFilterProxyModel(this); filterProxyModel->addAccountGroup(QVector {MyMoneyAccount::Asset, MyMoneyAccount::Liability}); auto const model = Models::instance()->accountsModel(); + model->load(); filterProxyModel->init(model, model->getColumns()); filterProxyModel->sort(AccountsModel::Account); m_accountComboBox->setModel(filterProxyModel); diff --git a/kmymoney/plugins/qif/export/kexportdlgdecl.ui b/kmymoney/plugins/qif/export/kexportdlgdecl.ui new file mode 100644 --- /dev/null +++ b/kmymoney/plugins/qif/export/kexportdlgdecl.ui @@ -0,0 +1,459 @@ + + + KExportDlgDecl + + + + 0 + 0 + 655 + 468 + + + + QIF Export + + + true + + + true + + + + 6 + + + 11 + + + 11 + + + 11 + + + 11 + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + From this dialog you are able to export transactions to a quicken compatible file, (known as a QIF file, because of the extension). Please enter the path to the QIF file or select it by clicking on the Browse button. + +You can choose the file's path, the account and the format of the QIF file (profile). Choose Account to export all the transactions between the specified dates or just categories. You can also limit the transactions that are exported by start and ending date. Once you have pressed the Export button a message box will appear when the export has completed detailing how many transactions, categories and payees were exported. + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + true + + + + + + + + + QFrame::HLine + + + QFrame::Raised + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + File to export to: + + + false + + + + + + + + + + &Browse... + + + + + + + + + + + + + Account to export + + + false + + + + + + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QIF Profile + + + false + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 200 + 0 + + + + false + + + + + + + + + + + + + + + Contents to Export + + + + 6 + + + 11 + + + 11 + + + 11 + + + 11 + + + + + Account + + + + + + + Categories + + + + + + + + + + Date Range + + + + 6 + + + 11 + + + 11 + + + 11 + + + 11 + + + + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + End on: + + + false + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + Start on: + + + false + + + + + + + + 0 + 0 + + + + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 230 + 16 + + + + + + + + + + QFrame::HLine + + + QFrame::Sunken + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 451 + 0 + + + + + + + + &Export + + + true + + + true + + + + + + + Cancel + + + true + + + + + + + + + + + KLineEdit + QLineEdit +
klineedit.h
+
+ + KComboBox + QComboBox +
kcombobox.h
+
+ + kMyMoneyDateInput + QWidget +
../widgets/kmymoneydateinput.h
+
+ + KMyMoneyAccountCombo + QWidget +
../widgets/kmymoneyaccountcombo.h
+
+
+ + +
diff --git a/kmymoney/plugins/qif/export/kmm_qifexport.rc b/kmymoney/plugins/qif/export/kmm_qifexport.rc new file mode 100644 --- /dev/null +++ b/kmymoney/plugins/qif/export/kmm_qifexport.rc @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/kmymoney/converter/mymoneyqifwriter.h b/kmymoney/plugins/qif/export/mymoneyqifwriter.h rename from kmymoney/converter/mymoneyqifwriter.h rename to kmymoney/plugins/qif/export/mymoneyqifwriter.h --- a/kmymoney/converter/mymoneyqifwriter.h +++ b/kmymoney/plugins/qif/export/mymoneyqifwriter.h @@ -36,9 +36,10 @@ // ---------------------------------------------------------------------------- // Project Headers +#include "../config/mymoneyqifprofile.h" + class MyMoneyTransaction; class MyMoneySplit; -#include "mymoneyqifprofile.h" /** * @author Thomas Baumgart diff --git a/kmymoney/converter/mymoneyqifwriter.cpp b/kmymoney/plugins/qif/export/mymoneyqifwriter.cpp rename from kmymoney/converter/mymoneyqifwriter.cpp rename to kmymoney/plugins/qif/export/mymoneyqifwriter.cpp diff --git a/kmymoney/plugins/qif/export/qifexport.json.in b/kmymoney/plugins/qif/export/qifexport.json.in new file mode 100644 --- /dev/null +++ b/kmymoney/plugins/qif/export/qifexport.json.in @@ -0,0 +1,21 @@ +{ + "KPlugin": { + "Authors": [ + { + "Email": "mte@users.sourceforge.net", + "Name": "Michael Edwardes" + } + ], + "Description": "Add QIF exporting to KMyMoney", + "EnabledByDefault": true, + "Icon": "document-export", + "Id": "qifexport", + "License": "GPL", + "Name": "QIF Exporter", + "ServiceTypes": [ + "KMyMoney/Plugin" + ], + "Version": "@PROJECT_VERSION@@PROJECT_VERSION_SUFFIX@", + "Website": "https://kmymoney.org/plugins.html" + } +} diff --git a/kmymoney/plugins/qif/export/qifexporterplugin.h b/kmymoney/plugins/qif/export/qifexporterplugin.h new file mode 100644 --- /dev/null +++ b/kmymoney/plugins/qif/export/qifexporterplugin.h @@ -0,0 +1,57 @@ +/*************************************************************************** + qifexporterplugin.h + ------------------- + copyright : (C) 2017 by Łukasz Wojniłowicz + email : lukasz.wojnilowicz@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef QIFEXPORTERPLUGIN_H +#define QIFEXPORTERPLUGIN_H + +// ---------------------------------------------------------------------------- +// KDE Includes + +// ---------------------------------------------------------------------------- +// QT Includes + +// Project Includes + +#include "kmymoneyplugin.h" + +class MyMoneyQifReader; + +class QIFExporterPlugin : public KMyMoneyPlugin::Plugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.kmymoney.plugins.qifexport" FILE "qifexport.json") + +public: + explicit QIFExporterPlugin(); + ~QIFExporterPlugin(); + + QAction *m_action; + + MyMoneyQifReader *m_qifReader; + +public slots: + /** + * Called when the user wishes to export some transaction to a + * QIF formatted file. An account must be open for this to work. + * Uses MyMoneyQifWriter() for the actual output. + */ + void slotQifExport(); + +protected: + void createActions(); +}; + +#endif diff --git a/kmymoney/plugins/qif/export/qifexporterplugin.cpp b/kmymoney/plugins/qif/export/qifexporterplugin.cpp new file mode 100644 --- /dev/null +++ b/kmymoney/plugins/qif/export/qifexporterplugin.cpp @@ -0,0 +1,78 @@ +/*************************************************************************** + qifimporterplugin.cpp + (based on qifimporterplugin.cpp) + ------------------- + + copyright : (C) 2017 by Łukasz Wojniłowicz + email : lukasz.wojnilowicz@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "qifexporterplugin.h" + +// ---------------------------------------------------------------------------- +// QT Includes + +// ---------------------------------------------------------------------------- +// KDE Includes + +#include +#include + +// ---------------------------------------------------------------------------- +// Project Includes + +#include "kexportdlg.h" + +#include "mymoneyqifwriter.h" + + +QIFExporterPlugin::QIFExporterPlugin() : + KMyMoneyPlugin::Plugin(nullptr, "qifexport"/*must be the same as X-KDE-PluginInfo-Name*/) +{ + setComponentName("kmm_qifexport", i18n("QIF exporter")); + setXMLFile("kmm_qifexport.rc"); + createActions(); + // For information, announce that we have been loaded. + qDebug("KMyMoney qifexport plugin loaded"); +} + +QIFExporterPlugin::~QIFExporterPlugin() +{ +} + +void QIFExporterPlugin::createActions() +{ + m_action = actionCollection()->addAction("file_export_qif"); + m_action->setText(i18n("QIF...")); + connect(m_action, &QAction::triggered, this, &QIFExporterPlugin::slotQifExport); +} + + +void QIFExporterPlugin::slotQifExport() +{ + m_action->setEnabled(false); + QPointer dlg = new KExportDlg(nullptr); + if (dlg->exec() == QDialog::Accepted && dlg != nullptr) { +// if (okToWriteFile(QUrl::fromLocalFile(dlg->filename()))) { + MyMoneyQifWriter writer; + connect(&writer, SIGNAL(signalProgress(int,int)), this, SLOT(slotStatusProgressBar(int,int))); + + writer.write(dlg->filename(), dlg->profile(), dlg->accountId(), + dlg->accountSelected(), dlg->categorySelected(), + dlg->startDate(), dlg->endDate()); +// } + } + delete dlg; + m_action->setEnabled(true); +} + +//#include "qifexporterplugin.moc" diff --git a/kmymoney/plugins/qif/import/CMakeLists.txt b/kmymoney/plugins/qif/import/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/kmymoney/plugins/qif/import/CMakeLists.txt @@ -0,0 +1,32 @@ +# patch the version with the version defined in the build system +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/qifimport.json.in ${CMAKE_CURRENT_BINARY_DIR}/qifimport.json @ONLY) + +########### next target ############### + +set(kmm_qifimport_PART_SRCS + qifimporterplugin.cpp + ../config/mymoneyqifprofile.cpp + mymoneyqifreader.cpp + kimportdlg.cpp +) + +set(kmm_qifimport_PART_UI + kimportdlgdecl.ui +) + +ki18n_wrap_ui(kmm_qifimport_PART_SRCS ${kmm_qifimport_PART_UI}) + +add_library(kmm_qifimport MODULE ${kmm_qifimport_PART_SRCS}) + +target_link_libraries(kmm_qifimport + kmm_plugin + Alkimia::alkimia +) + +########### install files ############### + +install(FILES kmm_qifimport.rc + DESTINATION "${KXMLGUI_INSTALL_DIR}/kmm_qifimport") + +install(TARGETS kmm_qifimport + DESTINATION "${KDE_INSTALL_PLUGINDIR}/kmymoney/") diff --git a/kmymoney/dialogs/kimportdlg.h b/kmymoney/plugins/qif/import/kimportdlg.h rename from kmymoney/dialogs/kimportdlg.h rename to kmymoney/plugins/qif/import/kimportdlg.h --- a/kmymoney/dialogs/kimportdlg.h +++ b/kmymoney/plugins/qif/import/kimportdlg.h @@ -91,11 +91,6 @@ /** Test whether to enable the buttons */ void slotFileTextChanged(const QString& text); - /** - * Called when the user needs a new profile - */ - void slotNewProfile(); - void slotOkClicked(); private: diff --git a/kmymoney/dialogs/kimportdlg.cpp b/kmymoney/plugins/qif/import/kimportdlg.cpp rename from kmymoney/dialogs/kimportdlg.cpp rename to kmymoney/plugins/qif/import/kimportdlg.cpp --- a/kmymoney/dialogs/kimportdlg.cpp +++ b/kmymoney/plugins/qif/import/kimportdlg.cpp @@ -28,6 +28,7 @@ #include #include #include +#include // ---------------------------------------------------------------------------- // KDE Headers @@ -44,8 +45,7 @@ #include "kmymoneyutils.h" #include #include -#include "mymoneyqifprofileeditor.h" -#include "mymoneyqifprofile.h" +#include "../config/mymoneyqifprofile.h" #include using namespace Icons; @@ -75,13 +75,11 @@ QIcon::fromTheme(g_Icons[Icon::DocumentNew]), i18n("Create a new profile"), i18n("Use this to open the profile editor")); - KGuiItem::assign(m_profileEditorButton, newButtenItem); // connect the buttons to their functionality connect(m_qbuttonBrowse, SIGNAL(clicked()), this, SLOT(slotBrowse())); connect(m_buttonBox, SIGNAL(accepted()), this, SLOT(slotOkClicked())); connect(m_buttonBox, SIGNAL(rejected()), this, SLOT(reject())); - connect(m_profileEditorButton, SIGNAL(clicked()), this, SLOT(slotNewProfile())); // connect the change signals to the check slot and perform initial check connect(m_qlineeditFile, SIGNAL(textChanged(QString)), this, @@ -153,27 +151,8 @@ #endif } -void KImportDlg::slotNewProfile() -{ - QPointer editor = new MyMoneyQifProfileEditor(true, this); - editor->setObjectName("QIF Profile Editor"); - - if (editor->exec()) { - loadProfiles(); - m_profileComboBox->setCurrentIndex(m_profileComboBox->findText(editor->selectedProfile(), Qt::MatchExactly)); - } - - delete editor; -} - void KImportDlg::loadProfiles(const bool selectLast) { - // Creating an editor object here makes sure that - // we have at least the default profile available - MyMoneyQifProfileEditor* edit = new MyMoneyQifProfileEditor(true, 0); - edit->slotOk(); - delete edit; - QString current = m_profileComboBox->currentText(); m_profileComboBox->clear(); diff --git a/kmymoney/dialogs/kimportdlgdecl.ui b/kmymoney/plugins/qif/import/kimportdlgdecl.ui rename from kmymoney/dialogs/kimportdlgdecl.ui rename to kmymoney/plugins/qif/import/kimportdlgdecl.ui --- a/kmymoney/dialogs/kimportdlgdecl.ui +++ b/kmymoney/plugins/qif/import/kimportdlgdecl.ui @@ -2,9 +2,6 @@ KImportDlgDecl - - Qt::WindowModal - 0 @@ -19,6 +16,9 @@ true + + true + @@ -76,46 +76,20 @@ Import options - - + + - QIF Profile + Source of QIF false - - - - - 0 - 0 - - - - - 200 - 0 - - - - false - - - - - - - New... - - - - - + + - Source of QIF + QIF Profile false @@ -139,6 +113,25 @@ + + + + + 0 + 0 + + + + + 200 + 0 + + + + false + + + diff --git a/kmymoney/plugins/qif/import/kmm_qifimport.rc b/kmymoney/plugins/qif/import/kmm_qifimport.rc new file mode 100644 --- /dev/null +++ b/kmymoney/plugins/qif/import/kmm_qifimport.rc @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/kmymoney/converter/mymoneyqifreader.h b/kmymoney/plugins/qif/import/mymoneyqifreader.h rename from kmymoney/converter/mymoneyqifreader.h rename to kmymoney/plugins/qif/import/mymoneyqifreader.h --- a/kmymoney/converter/mymoneyqifreader.h +++ b/kmymoney/plugins/qif/import/mymoneyqifreader.h @@ -41,11 +41,13 @@ // ---------------------------------------------------------------------------- // Project Headers -#include "mymoneyqifprofile.h" #include "mymoneyaccount.h" #include "mymoneytransaction.h" +#include "../config/mymoneyqifprofile.h" class MyMoneyFileTransaction; +class MyMoneyStatement; +class MyMoneyQifProfile; /** * @author Thomas Baumgart @@ -122,17 +124,6 @@ */ bool startImport(); - /** - * This method must be called once the signal importFinished() has - * been emitted. It will clean up the reader state and determines - * the actual return code of the import. - * - * @retval true Import was successful. - * @retval false Import failed because the filter program terminated - * abnormally or the user aborted the import process. - */ - bool finishImport(); - void setCategoryMapping(bool map); inline const MyMoneyAccount& account() const { @@ -244,45 +235,6 @@ Create = 0, Select }; - /** - * This method is used to find an account using the account's name - * stored in @p account in the current MyMoneyFile object. If it does not - * exist, the user has the chance to create it or to skip processing - * of this account. - * - * If an account has been selected, account will be set to contain it's data. - * If the skip operation was requested, account will be empty. - * - * Depending on @p mode the bahaviour of this method is slightly different. - * The following table shows the dependencies: - * - * @code - * case mode operation - * ----------------------------------------------------------------------------- - * account with same name exists Create returns immediately - * m_account contains data - * of existing account - * - * account does not exist Create immediately calls dialog - * to create account - * - * account with same name exists Select User will be asked if - * he wants to use the existing - * account or create a new one - * - * account does not exist Select User will be asked to - * select a different account - * or create a new one - * - * @endcode - * - * @param mode Is either Create or Select depending on the above table - * @param account Reference to MyMoneyAccount object - * @param openingBalance the opening balance of the account to be created - * defaults to zero - */ - - void selectOrCreateAccount(const SelectCreateMode mode, MyMoneyAccount& account, const MyMoneyMoney& openingBalance = MyMoneyMoney()); /** * This method looks up the @p searchname account by name and returns its id @@ -304,6 +256,22 @@ */ static const QString findOrCreateExpenseAccount(const QString& searchname); + /** + * This methods returns the account from the list of accounts identified by + * an account id or account name including an account hierachy. + * + * The parent account specifies from which account the search should be started. + * In case the parent account does not have an id, the method scans all top-level accounts. + * + * If the account is not found in the list of accounts, MyMoneyAccount() is returned. + * + * @param acc account to find + * @param parent parent account to search from + * @retval found MyMoneyAccount account instance + * @retval MyMoneyAccount() if not found + */ + const MyMoneyAccount& findAccount(const MyMoneyAccount& acc, const MyMoneyAccount& parent) const; + /** * This method returns the account id for a given account @a name. In * case @a name references an investment account and @a useBrokerage is @a true @@ -316,10 +284,7 @@ void createOpeningBalance(MyMoneyAccount::_accountTypeE accType = MyMoneyAccount::Checkings); signals: - /** - * This signal will be emitted when the import is finished. - */ - void importFinished(); + void statementsReady(QList &); private slots: void slotSendDataToFilter(); diff --git a/kmymoney/converter/mymoneyqifreader.cpp b/kmymoney/plugins/qif/import/mymoneyqifreader.cpp rename from kmymoney/converter/mymoneyqifreader.cpp rename to kmymoney/plugins/qif/import/mymoneyqifreader.cpp --- a/kmymoney/converter/mymoneyqifreader.cpp +++ b/kmymoney/plugins/qif/import/mymoneyqifreader.cpp @@ -33,6 +33,7 @@ #include #include #include +#include // ---------------------------------------------------------------------------- // KDE Headers @@ -49,11 +50,8 @@ // Project Headers #include "mymoneyfile.h" -#include "kaccountselectdlg.h" -#include "kmymoney.h" #include "kmymoneyglobalsettings.h" -#include "mymoneystatementreader.h" #include // define this to debug the code. Using external filters @@ -399,7 +397,7 @@ qDebug("%d lines processed", m_linenumber); signalProgress(-1, -1); - emit importFinished(); + emit statementsReady(d->statements); } bool MyMoneyQifReader::startImport() @@ -426,7 +424,7 @@ m_filename += m_url.fileName(); qDebug() << "Source:" << m_url.toDisplayString() << "Destination:" << m_filename; KIO::FileCopyJob *job = KIO::file_copy(m_url, QUrl::fromUserInput(m_filename), -1, KIO::Overwrite); - KJobWidgets::setWindow(job, kmymoney); +// KJobWidgets::setWindow(job, kmymoney); job->exec(); if (job->error()) { KMessageBox::detailedError(0, i18n("Error while loading file '%1'.", m_url.toDisplayString()), @@ -481,6 +479,7 @@ signalProgress(0, m_file->size(), i18n("Reading QIF...")); slotSendDataToFilter(); rc = true; +// emit statementsReady(d->statements); } else { KMessageBox::detailedError(0, i18n("Error while running the filter '%1'.", m_filter.program()), m_filter.errorString(), @@ -491,66 +490,6 @@ return rc; } -bool MyMoneyQifReader::finishImport() -{ - bool rc = false; - -#ifdef DEBUG_IMPORT - delete m_file; - m_file = 0; - - // remove the Don't ask again entries - KSharedConfigPtr config = KSharedConfig::openConfig(); - KConfigGroup grp = config->group(QString::fromLatin1("Notification Messages")); - QStringList::ConstIterator it; - - for (it = m_dontAskAgain.begin(); it != m_dontAskAgain.end(); ++it) { - grp.deleteEntry(*it); - } - grp.sync(); - m_dontAskAgain.clear(); - m_accountTranslation.clear(); - - signalProgress(-1, -1); - rc = !m_userAbort; - -#else - if (QProcess::Running != m_filter.state()) { - delete m_file; - m_file = 0; - - // remove the Don't ask again entries - KSharedConfigPtr config = KSharedConfig::openConfig(); - KConfigGroup grp = config->group(QString::fromLatin1("Notification Messages")); - QStringList::ConstIterator it; - - for (it = m_dontAskAgain.constBegin(); it != m_dontAskAgain.constEnd(); ++it) { - grp.deleteEntry(*it); - } - grp.sync(); - m_dontAskAgain.clear(); - m_accountTranslation.clear(); - - signalProgress(-1, -1); - rc = !m_userAbort && QProcess::NormalExit == m_filter.exitStatus(); - } else { - qWarning("MyMoneyQifReader::finishImport() must not be called while the filter\n\tprocess is still running."); - } -#endif - - // if a temporary file was constructed by NetAccess::download, - // then it will be removed with the next call. Otherwise, it - // stays untouched on the local filesystem - if(!m_url.isLocalFile()) - KIO::file_delete(QUrl::fromUserInput(m_filename)); - - // Now to import the statements - QList::const_iterator it_st; - for (it_st = d->statements.constBegin(); it_st != d->statements.constEnd(); ++it_st) - kmymoney->slotStatementImport(*it_st); - return rc; -} - void MyMoneyQifReader::processQifSpecial(const QString& _line) { QString line = _line.mid(1); // get rid of exclamation mark @@ -898,15 +837,73 @@ } // check if we can find the account already in the file - MyMoneyAccount acc = kmymoney->findAccount(account, MyMoneyAccount()); + auto acc = findAccount(account, MyMoneyAccount()); // if not, we just create it if (acc.id().isEmpty()) { MyMoneyAccount brokerage; file->createAccount(account, parentAccount, brokerage, MyMoneyMoney()); } } +const MyMoneyAccount& MyMoneyQifReader::findAccount(const MyMoneyAccount& acc, const MyMoneyAccount& parent) const +{ + static MyMoneyAccount nullAccount; + + MyMoneyFile* file = MyMoneyFile::instance(); + QList parents; + try { + // search by id + if (!acc.id().isEmpty()) { + return file->account(acc.id()); + } + // collect the parents. in case parent does not have an id, we scan the all top-level accounts + if (parent.id().isEmpty()) { + parents << file->asset(); + parents << file->liability(); + parents << file->income(); + parents << file->expense(); + parents << file->equity(); + } else { + parents << parent; + } + QList::const_iterator it_p; + for (it_p = parents.constBegin(); it_p != parents.constEnd(); ++it_p) { + MyMoneyAccount parentAccount = *it_p; + // search by name (allow hierarchy) + int pos; + // check for ':' in the name and use it as separator for a hierarchy + QString name = acc.name(); + bool notFound = false; + while ((pos = name.indexOf(MyMoneyFile::AccountSeperator)) != -1) { + QString part = name.left(pos); + QString remainder = name.mid(pos + 1); + const MyMoneyAccount& existingAccount = file->subAccountByName(parentAccount, part); + // if account has not been found, continue with next top level parent + if (existingAccount.id().isEmpty()) { + notFound = true; + break; + } + parentAccount = existingAccount; + name = remainder; + } + if (notFound) + continue; + const MyMoneyAccount& existingAccount = file->subAccountByName(parentAccount, name); + if (!existingAccount.id().isEmpty()) { + if (acc.accountType() != MyMoneyAccount::UnknownAccountType) { + if (acc.accountType() != existingAccount.accountType()) + continue; + } + return existingAccount; + } + } + } catch (const MyMoneyException &e) { + KMessageBox::error(0, i18n("Unable to find account: %1", e.what())); + } + return nullAccount; +} + const QString MyMoneyQifReader::transferAccount(const QString& name, bool useBrokerage) { QString accountId; @@ -1937,7 +1934,7 @@ } // check if we can find the account already in the file - MyMoneyAccount acc = kmymoney->findAccount(account, MyMoneyAccount()); + auto acc = findAccount(account, MyMoneyAccount()); if (acc.id().isEmpty()) { // in case the account is not found by name and the type is // unknown, we have to assume something and create a checking account. @@ -1997,170 +1994,6 @@ return acc.id(); } -void MyMoneyQifReader::selectOrCreateAccount(const SelectCreateMode mode, MyMoneyAccount& account, const MyMoneyMoney& balance) -{ - MyMoneyFile* file = MyMoneyFile::instance(); - - QString accountId; - QString msg; - QString typeStr; - QString leadIn; - KMyMoneyUtils::categoryTypeE type; - - QMap::ConstIterator it; - - type = KMyMoneyUtils::none; - switch (account.accountGroup()) { - default: - type = KMyMoneyUtils::asset; - type = (KMyMoneyUtils::categoryTypeE)(type | KMyMoneyUtils::liability); - typeStr = i18n("account"); - leadIn = i18n("al"); - break; - - case MyMoneyAccount::Income: - case MyMoneyAccount::Expense: - type = KMyMoneyUtils::income; - type = (KMyMoneyUtils::categoryTypeE)(type | KMyMoneyUtils::expense); - typeStr = i18n("category"); - leadIn = i18n("ei"); - msg = i18n("Category selection"); - break; - } - - QPointer accountSelect = new KAccountSelectDlg(type, "QifImport", kmymoney); - if (!msg.isEmpty()) - accountSelect->setWindowTitle(msg); - - it = m_accountTranslation.constFind(QString(leadIn + MyMoneyFile::AccountSeperator + account.name()).toLower()); - if (it != m_accountTranslation.constEnd()) { - try { - account = file->account(*it); - delete accountSelect; - return; - - } catch (const MyMoneyException &e) { - const QString message(i18n("Account \"%1\" disappeared: %2", account.name(), e.what())); - KMessageBox::error(0, message); - } - } - - // This is so the QPointer to the dialog gets properly destroyed if something throws. - try { - if (!account.name().isEmpty()) { - if (type & (KMyMoneyUtils::income | KMyMoneyUtils::expense)) { - accountId = file->categoryToAccount(account.name()); - } else { - accountId = file->nameToAccount(account.name()); - } - - if (mode == Create) { - if (!accountId.isEmpty()) { - account = file->account(accountId); - delete accountSelect; - return; - - } else { - switch (KMessageBox::questionYesNo(0, - i18nc("The 'type of object' 'x' does not exist", "The %1 '%2' does not exist. Do you " - "want to create it?", typeStr, account.name()))) { - case KMessageBox::Yes: - break; - case KMessageBox::No: - default: - delete accountSelect; - return; - } - } - } else { - accountSelect->setHeader(i18nc("To select account", "Select %1", typeStr)); - if (!accountId.isEmpty()) { - msg = i18n("The %1 %2 currently exists. Do you want " - "to import transactions to this account?", typeStr, account.name()); - - } else { - msg = i18n("The %1 %2 currently does not exist. You can " - "create a new %3 by pressing the Create button " - "or select another %4 manually from the selection box.", typeStr, account.name(), typeStr, typeStr); - } - } - - accountSelect->setDescription(msg); - accountSelect->setAccount(account, accountId); - accountSelect->setMode(mode == Create); - accountSelect->showAbortButton(true); - - // display current entry in widget, the offending line (if any) will be shown in red - QStringList::Iterator it_e; - int i = 0; - for (it_e = m_qifEntry.begin(); it_e != m_qifEntry.end(); ++it_e) { - if (m_extractedLine == i) - accountSelect->m_qifEntry->setTextColor(QColor("red")); - accountSelect->m_qifEntry->append(*it_e); - accountSelect->m_qifEntry->setTextColor(QColor("black")); - ++i; - } - - for (;;) { - if (accountSelect->exec() == QDialog::Accepted) { - if (!accountSelect->selectedAccount().isEmpty()) { - accountId = accountSelect->selectedAccount(); - - m_accountTranslation[QString(leadIn + MyMoneyFile::AccountSeperator + account.name()).toLower()] = accountId; - - // MMAccount::openingBalance() is where the accountSelect dialog has - // stashed the opening balance that the user chose. - MyMoneyAccount importedAccountData(account); - // MyMoneyMoney balance = importedAccountData.openingBalance(); - account = file->account(accountId); - if (! balance.isZero()) { - QString openingtxid = file->openingBalanceTransaction(account); - MyMoneyFileTransaction ft; - if (! openingtxid.isEmpty()) { - MyMoneyTransaction openingtx = file->transaction(openingtxid); - MyMoneySplit split = openingtx.splitByAccount(account.id()); - - if (split.shares() != balance) { - const MyMoneySecurity& sec = file->security(account.currencyId()); - if (KMessageBox::questionYesNo( - KMyMoneyUtils::mainWindow(), - i18n("The %1 account currently has an opening balance of %2. This QIF file reports an opening balance of %3. Would you like to overwrite the current balance with the one from the QIF file?", account.name(), MyMoneyUtils::formatMoney(split.shares(), account, sec), MyMoneyUtils::formatMoney(balance, account, sec)), - i18n("Overwrite opening balance"), - KStandardGuiItem::yes(), - KStandardGuiItem::no(), - "OverwriteOpeningBalance") - == KMessageBox::Yes) { - file->removeTransaction(openingtx); - file->createOpeningBalanceTransaction(account, balance); - } - } - } else { - // Add an opening balance - file->createOpeningBalanceTransaction(account, balance); - } - ft.commit(); - } - break; - } - - } else if (accountSelect->aborted()) - throw MYMONEYEXCEPTION("USERABORT"); - - if (typeStr == i18n("account")) { - KMessageBox::error(0, i18n("You must select or create an account.")); - } else { - KMessageBox::error(0, i18n("You must select or create a category.")); - } - } - } - } catch (...) { - // cleanup the dialog pointer. - delete accountSelect; - throw; - } - delete accountSelect; -} - void MyMoneyQifReader::setProgressCallback(void(*callback)(int, int, const QString&)) { m_progressCallback = callback; diff --git a/kmymoney/plugins/qif/import/qifimport.json.in b/kmymoney/plugins/qif/import/qifimport.json.in new file mode 100644 --- /dev/null +++ b/kmymoney/plugins/qif/import/qifimport.json.in @@ -0,0 +1,21 @@ +{ + "KPlugin": { + "Authors": [ + { + "Email": "mte@users.sourceforge.net", + "Name": "Michael Edwardes" + } + ], + "Description": "Add QIF importing to KMyMoney", + "EnabledByDefault": true, + "Icon": "document-import", + "Id": "qifimport", + "License": "GPL", + "Name": "QIF Importer", + "ServiceTypes": [ + "KMyMoney/Plugin" + ], + "Version": "@PROJECT_VERSION@@PROJECT_VERSION_SUFFIX@", + "Website": "https://kmymoney.org/plugins.html" + } +} diff --git a/kmymoney/plugins/qif/import/qifimporterplugin.h b/kmymoney/plugins/qif/import/qifimporterplugin.h new file mode 100644 --- /dev/null +++ b/kmymoney/plugins/qif/import/qifimporterplugin.h @@ -0,0 +1,63 @@ +/*************************************************************************** + qifimporterplugin.h + ------------------- + copyright : (C) 2017 by Łukasz Wojniłowicz + email : lukasz.wojnilowicz@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef QIFIMPORTERPLUGIN_H +#define QIFIMPORTERPLUGIN_H + +// ---------------------------------------------------------------------------- +// KDE Includes + +// ---------------------------------------------------------------------------- +// QT Includes + +// Project Includes + +#include "kmymoneyplugin.h" + +class MyMoneyQifReader; + +class QIFImporterPlugin : public KMyMoneyPlugin::Plugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.kmymoney.plugins.qifimport" FILE "qifimport.json") + +public: + explicit QIFImporterPlugin(); + ~QIFImporterPlugin(); + + QAction *m_action; + +private: + MyMoneyQifReader *m_qifReader; + +private slots: + + /** + * Called when the user wishes to import tab delimeted transactions + * into the current account. An account must be open for this to + * work. Calls KMyMoneyView::slotAccountImportAscii. + * + * @see MyMoneyAccount + */ + void slotQifImport(); + + bool slotGetStatements(QList &statements); + +protected: + void createActions(); +}; + +#endif diff --git a/kmymoney/plugins/qif/import/qifimporterplugin.cpp b/kmymoney/plugins/qif/import/qifimporterplugin.cpp new file mode 100644 --- /dev/null +++ b/kmymoney/plugins/qif/import/qifimporterplugin.cpp @@ -0,0 +1,87 @@ +/*************************************************************************** + qifimporterplugin.cpp + (based on qifimporterplugin.cpp) + ------------------- + + copyright : (C) 2017 by Łukasz Wojniłowicz + email : lukasz.wojnilowicz@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "qifimporterplugin.h" + +// ---------------------------------------------------------------------------- +// QT Includes + +// ---------------------------------------------------------------------------- +// KDE Includes + +#include +#include +#include + +// ---------------------------------------------------------------------------- +// Project Includes + +#include "kimportdlg.h" +#include "mymoneyqifreader.h" + +QIFImporterPlugin::QIFImporterPlugin() : + KMyMoneyPlugin::Plugin(nullptr, "qifimport"/*must be the same as X-KDE-PluginInfo-Name*/) +{ + setComponentName("kmm_qifimport", i18n("QIF importer")); + setXMLFile("kmm_qifimport.rc"); + createActions(); + // For information, announce that we have been loaded. + qDebug("KMyMoney qifimport plugin loaded"); +} + +QIFImporterPlugin::~QIFImporterPlugin() +{ +} + +void QIFImporterPlugin::createActions() +{ + m_action = actionCollection()->addAction("file_import_qif"); + m_action->setText(i18n("QIF...")); + connect(m_action, &QAction::triggered, this, &QIFImporterPlugin::slotQifImport); +} + +void QIFImporterPlugin::slotQifImport() +{ + m_action->setEnabled(false); + QPointer dlg = new KImportDlg(nullptr); + + if (dlg->exec() == QDialog::Accepted && dlg != nullptr) { + m_qifReader = new MyMoneyQifReader; + connect(m_qifReader, &MyMoneyQifReader::statementsReady, this, &QIFImporterPlugin::slotGetStatements); + + m_qifReader->setURL(dlg->file()); + m_qifReader->setProfile(dlg->profile()); + m_qifReader->setCategoryMapping(dlg->m_typeComboBox->currentIndex() == 0); + if (!m_qifReader->startImport()) + delete m_qifReader; + } + delete dlg; + m_action->setEnabled(true); +} + +bool QIFImporterPlugin::slotGetStatements(QList &statements) +{ + auto ret = true; + foreach (const auto statement, statements) + ret &= statementInterface()->import(statement); + + delete m_qifReader; + return ret; +} + +//#include "qifimporterplugin.moc" diff --git a/kmymoney/views/kmymoneyview.cpp b/kmymoney/views/kmymoneyview.cpp --- a/kmymoney/views/kmymoneyview.cpp +++ b/kmymoney/views/kmymoneyview.cpp @@ -68,8 +68,6 @@ #include #include "kendingbalancedlg.h" #include "kchooseimportexportdlg.h" -#include "kimportdlg.h" -#include "kexportdlg.h" #include "knewloanwizard.h" #include "kcurrencyeditdlg.h" #include "kfindtransactiondlg.h"