diff --git a/kmymoney/converter/CMakeLists.txt b/kmymoney/converter/CMakeLists.txt --- a/kmymoney/converter/CMakeLists.txt +++ b/kmymoney/converter/CMakeLists.txt @@ -16,7 +16,7 @@ add_library(converter STATIC ${libconverter_a_SOURCES}) # TODO: clean dependencies -target_link_libraries(converter PUBLIC KF5::Service KF5::XmlGui KF5::Completion KF5::TextWidgets KF5::WidgetsAddons KF5::ConfigCore KF5::I18n Qt5::Widgets Qt5::Gui Qt5::Sql Qt5::Xml Alkimia::alkimia KF5::KIOWidgets kmm_csvimport_static) +target_link_libraries(converter PUBLIC KF5::Service KF5::XmlGui KF5::Completion KF5::TextWidgets KF5::WidgetsAddons KF5::ConfigCore KF5::I18n Qt5::Widgets Qt5::Gui Qt5::Sql Qt5::Xml Alkimia::alkimia KF5::KIOWidgets kmm_csvimport_core) # we rely on some dialogs to be generated add_dependencies(converter dialogs) diff --git a/kmymoney/converter/mymoneyqifreader.h b/kmymoney/converter/mymoneyqifreader.h --- a/kmymoney/converter/mymoneyqifreader.h +++ b/kmymoney/converter/mymoneyqifreader.h @@ -221,22 +221,6 @@ void processQifSpecial(const QString& _line); /** - * This method is used to get the account id of the split for - * a transaction from the text found in the QIF $ or L record. - * If an account with the name is not found, the user is asked - * if it should be created. - * - * @param name name of account as found in the QIF file - * @param value value found in the T record - * @param value2 value found in the $ record for split transactions - * - * @return id of the account for the split. If no name is specified - * or the account was not found and not created the - * return value will be "". - */ - const QString checkCategory(const QString& name, const MyMoneyMoney& value, const MyMoneyMoney& value2); - - /** * This method extracts the line beginning with the letter @p id * from the lines contained in the QStringList object @p m_qifEntry. * An empty QString is returned, if the line is not found. diff --git a/kmymoney/converter/mymoneyqifreader.cpp b/kmymoney/converter/mymoneyqifreader.cpp --- a/kmymoney/converter/mymoneyqifreader.cpp +++ b/kmymoney/converter/mymoneyqifreader.cpp @@ -903,8 +903,7 @@ // if not, we just create it if (acc.id().isEmpty()) { MyMoneyAccount brokerage; - MyMoneyMoney balance; - kmymoney->createAccount(account, parentAccount, brokerage, balance); + file->createAccount(account, parentAccount, brokerage, MyMoneyMoney()); } } @@ -1181,7 +1180,7 @@ // it's an expense / income tmp = tmp.trimmed(); - accountId = checkCategory(tmp, s1.m_amount, s2.m_amount); + accountId = file->checkCategory(tmp, s1.m_amount, s2.m_amount); } if (!accountId.isEmpty()) { @@ -1227,7 +1226,7 @@ tmp = tmp.left(pos); } tmp = tmp.trimmed(); - accountId = checkCategory(tmp, s1.m_amount, s2.m_amount); + accountId = file->checkCategory(tmp, s1.m_amount, s2.m_amount); } if (!accountId.isEmpty()) { @@ -1892,67 +1891,6 @@ return result; } -const QString MyMoneyQifReader::checkCategory(const QString& name, const MyMoneyMoney& value, const MyMoneyMoney& value2) -{ - QString accountId; - MyMoneyFile *file = MyMoneyFile::instance(); - MyMoneyAccount account; - bool found = true; - - if (!name.isEmpty()) { - // The category might be constructed with an arbitraty depth (number of - // colon delimited fields). We try to find a parent account within this - // hierarchy by searching the following sequence: - // - // aaaa:bbbb:cccc:ddddd - // - // 1. search aaaa:bbbb:cccc:dddd, create nothing - // 2. search aaaa:bbbb:cccc , create dddd - // 3. search aaaa:bbbb , create cccc:dddd - // 4. search aaaa , create bbbb:cccc:dddd - // 5. don't search , create aaaa:bbbb:cccc:dddd - - account.setName(name); - QString accName; // part to be created (right side in above list) - QString parent(name); // a possible parent part (left side in above list) - do { - accountId = file->categoryToAccount(parent); - if (accountId.isEmpty()) { - found = false; - // prepare next step - if (!accName.isEmpty()) - accName.prepend(':'); - accName.prepend(parent.section(':', -1)); - account.setName(accName); - parent = parent.section(':', 0, -2); - } else if (!accName.isEmpty()) { - account.setParentAccountId(accountId); - } - } while (!parent.isEmpty() && accountId.isEmpty()); - - // if we did not find the category, we create it - if (!found) { - MyMoneyAccount parent; - if (account.parentAccountId().isEmpty()) { - if (!value.isNegative() && value2.isNegative()) - parent = file->income(); - else - parent = file->expense(); - } else { - parent = file->account(account.parentAccountId()); - } - account.setAccountType((!value.isNegative() && value2.isNegative()) ? MyMoneyAccount::Income : MyMoneyAccount::Expense); - MyMoneyAccount brokerage; - // clear out the parent id, because createAccount() does not like that - account.setParentAccountId(QString()); - kmymoney->createAccount(account, parent, brokerage, MyMoneyMoney()); - accountId = account.id(); - } - } - - return accountId; -} - const QString MyMoneyQifReader::processAccountEntry(bool resetAccountId) { MyMoneyFile* file = MyMoneyFile::instance(); @@ -2009,14 +1947,13 @@ MyMoneyAccount parentAccount; MyMoneyAccount brokerage; - MyMoneyMoney balance; // in case it's a stock account, we need to setup a fix investment account if (account.isInvest()) { acc.setName(i18n("%1 (Investment)", account.name())); // use the same name for the investment account acc.setDescription(i18n("Autogenerated by QIF importer from type Mutual account entry")); acc.setAccountType(MyMoneyAccount::Investment); parentAccount = file->asset(); - kmymoney->createAccount(acc, parentAccount, brokerage, MyMoneyMoney()); + file->createAccount(acc, parentAccount, brokerage, MyMoneyMoney()); parentAccount = acc; qDebug("We still need to create the stock account in MyMoneyQifReader::processAccountEntry()"); } else { @@ -2043,7 +1980,7 @@ brokerage.setAccountType(MyMoneyAccount::Checkings); brokerage.setCurrencyId(MyMoneyFile::instance()->baseCurrency().id()); } - kmymoney->createAccount(account, parentAccount, brokerage, balance); + file->createAccount(account, parentAccount, brokerage, MyMoneyMoney()); acc = account; // qDebug("Account created"); } else { diff --git a/kmymoney/converter/webpricequote.cpp b/kmymoney/converter/webpricequote.cpp --- a/kmymoney/converter/webpricequote.cpp +++ b/kmymoney/converter/webpricequote.cpp @@ -168,10 +168,10 @@ bool isCurrency = false; if (urlStr.contains(QLatin1String("%2"))) { - d->m_CSVSource.m_profileType = ProfileCurrencyPrices; + d->m_CSVSource.m_profileType = Profile::CurrencyPrices; isCurrency = true; } else - d->m_CSVSource.m_profileType = ProfileStockPrices; + d->m_CSVSource.m_profileType = Profile::StockPrices; d->m_CSVSource.m_profileName = sourcename; if (!d->m_CSVSource.readSettings(CSVImporter::configFile())) { @@ -520,32 +520,37 @@ { QMap result; - // tip: possible delimiter indexes are in csvutil.cpp + // tip: possible delimiter indexes are in csvenums.h result[QLatin1String("Stooq")] = PricesProfile(QLatin1String("Stooq"), - 106, 1, 0, 0, 1, 0, 0, - QMap{{ColumnDate, 0}, {ColumnPrice, 4}}, - 2, ProfileStockPrices); + 106, 1, 0, DateFormat::YearMonthDay, FieldDelimiter::Semicolon, + TextDelimiter::DoubleQuote, DecimalSymbol::Dot, + QMap{{Column::Date, 0}, {Column::Price, 4}}, + 2, Profile::StockPrices); result[QLatin1String("Stooq Currency")] = PricesProfile(QLatin1String("Stooq Currency"), - 106, 1, 0, 0, 1, 0, 0, - QMap{{ColumnDate, 0}, {ColumnPrice, 4}}, - 2, ProfileCurrencyPrices); + 106, 1, 0, DateFormat::YearMonthDay, FieldDelimiter::Semicolon, + TextDelimiter::DoubleQuote, DecimalSymbol::Dot, + QMap{{Column::Date, 0}, {Column::Price, 4}}, + 2, Profile::CurrencyPrices); result[QLatin1String("Yahoo")] = PricesProfile(QLatin1String("Yahoo"), - 106, 1, 0, 0, 0, 0, 0, - QMap{{ColumnDate, 0}, {ColumnPrice, 4}}, - 2, ProfileStockPrices); + 106, 1, 0, DateFormat::YearMonthDay, FieldDelimiter::Comma, + TextDelimiter::DoubleQuote, DecimalSymbol::Dot, + QMap{{Column::Date, 0}, {Column::Price, 4}}, + 2, Profile::StockPrices); result[QLatin1String("Nasdaq Baltic - Shares")] = PricesProfile(QLatin1String("Nasdaq Baltic - Shares"), - 106, 1, 0, 2, 3, 0, 0, - QMap{{ColumnDate, 0}, {ColumnPrice, 5}}, - 2, ProfileStockPrices); + 106, 1, 0, DateFormat::DayMonthYear, FieldDelimiter::Tab, + TextDelimiter::DoubleQuote, DecimalSymbol::Dot, + QMap{{Column::Date, 0}, {Column::Price, 5}}, + 2, Profile::StockPrices); result[QLatin1String("Nasdaq Baltic - Funds")] = PricesProfile(QLatin1String("Nasdaq Baltic - Funds"), - 106, 1, 0, 2, 3, 0, 0, - QMap{{ColumnDate, 0}, {ColumnPrice, 5}}, - 2, ProfileStockPrices); + 106, 1, 0, DateFormat::DayMonthYear, FieldDelimiter::Tab, + TextDelimiter::DoubleQuote, DecimalSymbol::Dot, + QMap{{Column::Date, 0}, {Column::Price, 5}}, + 2, Profile::StockPrices); return result; } diff --git a/kmymoney/dialogs/settings/ksettingsonlinequotes.cpp b/kmymoney/dialogs/settings/ksettingsonlinequotes.cpp --- a/kmymoney/dialogs/settings/ksettingsonlinequotes.cpp +++ b/kmymoney/dialogs/settings/ksettingsonlinequotes.cpp @@ -207,14 +207,14 @@ KSharedConfigPtr config = CSVImporter::configFile(); PricesProfile profile; profile.m_profileName = m_currentItem.m_name; - profile.m_profileType = ProfileStockPrices; + profile.m_profileType = Profile::StockPrices; bool profileExists = false; bool writeProfile = true; if (profile.readSettings(config)) profileExists = true; else { - profile.m_profileType = ProfileCurrencyPrices; + profile.m_profileType = Profile::CurrencyPrices; if (profile.readSettings(config)) profileExists = true; } @@ -231,10 +231,10 @@ profile = quoteSources.value(m_currentItem.m_name); if (profile.m_profileName.compare(m_currentItem.m_name, Qt::CaseInsensitive) == 0) { profile.writeSettings(config); - CSVImporter::profilesAction(profile.type(), ProfilesAdd, profile.m_profileName, profile.m_profileName); + CSVImporter::profilesAction(profile.type(), ProfileAction::Add, profile.m_profileName, profile.m_profileName); } } - CSVImporter::profilesAction(profile.type(), ProfilesUpdateLastUsed, profile.m_profileName, profile.m_profileName); + CSVImporter::profilesAction(profile.type(), ProfileAction::UpdateLastUsed, profile.m_profileName, profile.m_profileName); } void KSettingsOnlineQuotes::slotUpdateEntry() diff --git a/kmymoney/kmymoney.cpp b/kmymoney/kmymoney.cpp --- a/kmymoney/kmymoney.cpp +++ b/kmymoney/kmymoney.cpp @@ -2995,34 +2995,8 @@ void KMyMoneyApp::createAccount(MyMoneyAccount& newAccount, MyMoneyAccount& parentAccount, MyMoneyAccount& brokerageAccount, MyMoneyMoney openingBal) { - MyMoneyFile* file = MyMoneyFile::instance(); - - // make sure we have a currency. If none is assigned, we assume base currency - if (newAccount.currencyId().isEmpty()) - newAccount.setCurrencyId(file->baseCurrency().id()); - - MyMoneyFileTransaction ft; + MyMoneyFile *file = MyMoneyFile::instance(); try { - int pos; - // check for ':' in the name and use it as separator for a hierarchy - while ((pos = newAccount.name().indexOf(MyMoneyFile::AccountSeperator)) != -1) { - QString part = newAccount.name().left(pos); - QString remainder = newAccount.name().mid(pos + 1); - const MyMoneyAccount& existingAccount = file->subAccountByName(parentAccount, part); - if (existingAccount.id().isEmpty()) { - newAccount.setName(part); - - file->addAccount(newAccount, parentAccount); - parentAccount = newAccount; - } else { - parentAccount = existingAccount; - } - newAccount.setParentAccountId(QString()); // make sure, there's no parent - newAccount.clearId(); // and no id set for adding - newAccount.removeAccountIds(); // and no sub-account ids - newAccount.setName(remainder); - } - const MyMoneySecurity& sec = file->security(newAccount.currencyId()); // Check the opening balance if (openingBal.isPositive() && newAccount.accountGroup() == MyMoneyAccount::Liability) { @@ -3043,51 +3017,8 @@ return; } - file->addAccount(newAccount, parentAccount); - - // in case of a loan account, we add the initial payment - if ((newAccount.accountType() == MyMoneyAccount::Loan - || newAccount.accountType() == MyMoneyAccount::AssetLoan) - && !newAccount.value("kmm-loan-payment-acc").isEmpty() - && !newAccount.value("kmm-loan-payment-date").isEmpty()) { - MyMoneyAccountLoan acc(newAccount); - MyMoneyTransaction t; - MyMoneySplit a, b; - a.setAccountId(acc.id()); - b.setAccountId(acc.value("kmm-loan-payment-acc").toLatin1()); - a.setValue(acc.loanAmount()); - if (acc.accountType() == MyMoneyAccount::Loan) - a.setValue(-a.value()); - - a.setShares(a.value()); - b.setValue(-a.value()); - b.setShares(b.value()); - a.setMemo(i18n("Loan payout")); - b.setMemo(i18n("Loan payout")); - t.setPostDate(QDate::fromString(acc.value("kmm-loan-payment-date"), Qt::ISODate)); - newAccount.deletePair("kmm-loan-payment-acc"); - newAccount.deletePair("kmm-loan-payment-date"); - MyMoneyFile::instance()->modifyAccount(newAccount); - - t.addSplit(a); - t.addSplit(b); - file->addTransaction(t); - file->createOpeningBalanceTransaction(newAccount, openingBal); - - // in case of an investment account we check if we should create - // a brokerage account - } else if (newAccount.accountType() == MyMoneyAccount::Investment - && !brokerageAccount.name().isEmpty()) { - file->addAccount(brokerageAccount, parentAccount); - - // set a link from the investment account to the brokerage account - file->modifyAccount(newAccount); - file->createOpeningBalanceTransaction(brokerageAccount, openingBal); + file->createAccount(newAccount, parentAccount, brokerageAccount, openingBal); - } else - file->createOpeningBalanceTransaction(newAccount, openingBal); - - ft.commit(); } catch (const MyMoneyException &e) { KMessageBox::information(this, i18n("Unable to add account: %1", e.what())); } @@ -3159,7 +3090,7 @@ account = dialog->account(); parentAccount = dialog->parentAccount(); - createAccount(account, parentAccount, brokerageAccount, MyMoneyMoney()); + MyMoneyFile::instance()->createAccount(account, parentAccount, brokerageAccount, MyMoneyMoney()); } delete dialog; } diff --git a/kmymoney/mymoney/mymoneyfile.h b/kmymoney/mymoney/mymoneyfile.h --- a/kmymoney/mymoney/mymoneyfile.h +++ b/kmymoney/mymoney/mymoneyfile.h @@ -409,6 +409,7 @@ */ void removeInstitution(const MyMoneyInstitution& institution); + void createAccount(MyMoneyAccount& newAccount, MyMoneyAccount& parentAccount, MyMoneyAccount& brokerageAccount, MyMoneyMoney openingBal); /** * Adds an account to the file-global account pool. A respective * account-ID will be generated within this record. The modified @@ -1094,6 +1095,22 @@ **/ QString createCategory(const MyMoneyAccount& base, const QString& name); + /** + * This method is used to get the account id of the split for + * a transaction from the text found in the QIF $ or L record. + * If an account with the name is not found, the user is asked + * if it should be created. + * + * @param name name of account as found in the QIF file + * @param value value found in the T record + * @param value2 value found in the $ record for split transactions + * + * @return id of the account for the split. If no name is specified + * or the account was not found and not created the + * return value will be "". + */ + QString checkCategory(const QString& name, const MyMoneyMoney& value, const MyMoneyMoney& value2); + const QList scheduleListEx(int scheduleTypes, int scheduleOcurrences, int schedulePaymentTypes, diff --git a/kmymoney/mymoney/mymoneyfile.cpp b/kmymoney/mymoney/mymoneyfile.cpp --- a/kmymoney/mymoney/mymoneyfile.cpp +++ b/kmymoney/mymoney/mymoneyfile.cpp @@ -905,6 +905,85 @@ d->addCacheNotification(institution.id(), false); } +void MyMoneyFile::createAccount(MyMoneyAccount& newAccount, MyMoneyAccount& parentAccount, MyMoneyAccount& brokerageAccount, MyMoneyMoney openingBal) +{ + // make sure we have a currency. If none is assigned, we assume base currency + if (newAccount.currencyId().isEmpty()) + newAccount.setCurrencyId(baseCurrency().id()); + + MyMoneyFileTransaction ft; + try { + int pos; + // check for ':' in the name and use it as separator for a hierarchy + while ((pos = newAccount.name().indexOf(MyMoneyFile::AccountSeperator)) != -1) { + QString part = newAccount.name().left(pos); + QString remainder = newAccount.name().mid(pos + 1); + const MyMoneyAccount& existingAccount = subAccountByName(parentAccount, part); + if (existingAccount.id().isEmpty()) { + newAccount.setName(part); + + addAccount(newAccount, parentAccount); + parentAccount = newAccount; + } else { + parentAccount = existingAccount; + } + newAccount.setParentAccountId(QString()); // make sure, there's no parent + newAccount.clearId(); // and no id set for adding + newAccount.removeAccountIds(); // and no sub-account ids + newAccount.setName(remainder); + } + + addAccount(newAccount, parentAccount); + + // in case of a loan account, we add the initial payment + if ((newAccount.accountType() == MyMoneyAccount::Loan + || newAccount.accountType() == MyMoneyAccount::AssetLoan) + && !newAccount.value("kmm-loan-payment-acc").isEmpty() + && !newAccount.value("kmm-loan-payment-date").isEmpty()) { + MyMoneyAccountLoan acc(newAccount); + MyMoneyTransaction t; + MyMoneySplit a, b; + a.setAccountId(acc.id()); + b.setAccountId(acc.value("kmm-loan-payment-acc").toLatin1()); + a.setValue(acc.loanAmount()); + if (acc.accountType() == MyMoneyAccount::Loan) + a.setValue(-a.value()); + + a.setShares(a.value()); + b.setValue(-a.value()); + b.setShares(b.value()); + a.setMemo(i18n("Loan payout")); + b.setMemo(i18n("Loan payout")); + t.setPostDate(QDate::fromString(acc.value("kmm-loan-payment-date"), Qt::ISODate)); + newAccount.deletePair("kmm-loan-payment-acc"); + newAccount.deletePair("kmm-loan-payment-date"); + MyMoneyFile::instance()->modifyAccount(newAccount); + + t.addSplit(a); + t.addSplit(b); + addTransaction(t); + createOpeningBalanceTransaction(newAccount, openingBal); + + // in case of an investment account we check if we should create + // a brokerage account + } else if (newAccount.accountType() == MyMoneyAccount::Investment + && !brokerageAccount.name().isEmpty()) { + addAccount(brokerageAccount, parentAccount); + + // set a link from the investment account to the brokerage account + modifyAccount(newAccount); + createOpeningBalanceTransaction(brokerageAccount, openingBal); + + } else + createOpeningBalanceTransaction(newAccount, openingBal); + + ft.commit(); + } catch (const MyMoneyException &e) { + qWarning("Unable to create account: %s", qPrintable(e.what())); + throw MYMONEYEXCEPTION(e.what()); + } +} + void MyMoneyFile::addAccount(MyMoneyAccount& account, MyMoneyAccount& parent) { d->checkTransaction(Q_FUNC_INFO); @@ -2559,6 +2638,66 @@ return categoryToAccount(name); } +QString MyMoneyFile::checkCategory(const QString& name, const MyMoneyMoney& value, const MyMoneyMoney& value2) +{ + QString accountId; + MyMoneyAccount newAccount; + bool found = true; + + if (!name.isEmpty()) { + // The category might be constructed with an arbitraty depth (number of + // colon delimited fields). We try to find a parent account within this + // hierarchy by searching the following sequence: + // + // aaaa:bbbb:cccc:ddddd + // + // 1. search aaaa:bbbb:cccc:dddd, create nothing + // 2. search aaaa:bbbb:cccc , create dddd + // 3. search aaaa:bbbb , create cccc:dddd + // 4. search aaaa , create bbbb:cccc:dddd + // 5. don't search , create aaaa:bbbb:cccc:dddd + + newAccount.setName(name); + QString accName; // part to be created (right side in above list) + QString parent(name); // a possible parent part (left side in above list) + do { + accountId = categoryToAccount(parent); + if (accountId.isEmpty()) { + found = false; + // prepare next step + if (!accName.isEmpty()) + accName.prepend(':'); + accName.prepend(parent.section(':', -1)); + newAccount.setName(accName); + parent = parent.section(':', 0, -2); + } else if (!accName.isEmpty()) { + newAccount.setParentAccountId(accountId); + } + } while (!parent.isEmpty() && accountId.isEmpty()); + + // if we did not find the category, we create it + if (!found) { + MyMoneyAccount parent; + if (newAccount.parentAccountId().isEmpty()) { + if (!value.isNegative() && value2.isNegative()) + parent = income(); + else + parent = expense(); + } else { + parent = account(newAccount.parentAccountId()); + } + newAccount.setAccountType((!value.isNegative() && value2.isNegative()) ? MyMoneyAccount::Income : MyMoneyAccount::Expense); + MyMoneyAccount brokerage; + // clear out the parent id, because createAccount() does not like that + newAccount.setParentAccountId(QString()); + createAccount(newAccount, parent, brokerage, MyMoneyMoney()); + accountId = newAccount.id(); + } + } + + return accountId; +} + const QList MyMoneyFile::scheduleListEx(int scheduleTypes, int scheduleOcurrences, int schedulePaymentTypes, diff --git a/kmymoney/plugins/CMakeLists.txt b/kmymoney/plugins/CMakeLists.txt --- a/kmymoney/plugins/CMakeLists.txt +++ b/kmymoney/plugins/CMakeLists.txt @@ -60,11 +60,9 @@ KF5::XmlGui KF5::KCMUtils KF5::KIOWidgets - KF5::XmlGui Qt5::Gui Qt5::Widgets kmm_mymoney - Alkimia::alkimia ) set_target_properties(kmm_plugin PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR}) diff --git a/kmymoney/plugins/csvimport/CMakeLists.txt b/kmymoney/plugins/csvimport/CMakeLists.txt --- a/kmymoney/plugins/csvimport/CMakeLists.txt +++ b/kmymoney/plugins/csvimport/CMakeLists.txt @@ -5,16 +5,33 @@ ########### next target ############### +set(kmm_csvimport_core_PART_SRCS + csvimporter.cpp + convdate.cpp + csvutil.cpp +) + +add_library(kmm_csvimport_core SHARED ${kmm_csvimport_core_PART_SRCS}) +generate_export_header(kmm_csvimport_core) +target_link_libraries(kmm_csvimport_core + PUBLIC + kmm_mymoney +) + +########### install files ############### + +install(TARGETS kmm_csvimport_core + ${INSTALL_TARGETS_DEFAULT_ARGS} ) + +########### next target ############### + set(kmm_csvimport_PART_SRCS csvimporterplugin.cpp - csvimporter.cpp csvwizard.cpp bankingwizardpage.cpp investmentwizardpage.cpp priceswizardpage.cpp transactiondlg.cpp - convdate.cpp - csvutil.cpp securitiesdlg.cpp securitydlg.cpp currenciesdlg.cpp @@ -42,20 +59,8 @@ target_link_libraries(kmm_csvimport PUBLIC - kmm_mymoney - kmm_plugin - kmymoney_common - Qt5::Core - Qt5::Widgets -) - -add_library(kmm_csvimport_static STATIC ${kmm_csvimport_PART_SRCS}) - -target_link_libraries(kmm_csvimport_static + kmm_csvimport_core kmm_plugin - kmymoney_common - Qt5::Core - Qt5::Widgets ) ########### install files ############### diff --git a/kmymoney/plugins/csvimport/bankingwizardpage.h b/kmymoney/plugins/csvimport/bankingwizardpage.h --- a/kmymoney/plugins/csvimport/bankingwizardpage.h +++ b/kmymoney/plugins/csvimport/bankingwizardpage.h @@ -23,21 +23,18 @@ // ---------------------------------------------------------------------------- // QT Includes -#include -#include - // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes -#include -#include +#include "csvwizardpage.h" // ---------------------------------------------------------------------------- class BankingProfile; +class MyMoneyStatement; namespace Ui { @@ -52,26 +49,23 @@ explicit BankingPage(CSVWizard *dlg, CSVImporter *imp); ~BankingPage(); - Ui::BankingPage *ui; - QVBoxLayout *m_pageLayout; - bool validateCreditDebit(); /** * This method fills QIF file with bank/credit card data */ - void makeQIF(MyMoneyStatement &st, QFile &file); + void makeQIF(const MyMoneyStatement &st, const QString &outFileName); private: void initializePage(); bool isComplete() const; int nextId() const; - void initializeComboBoxes(); bool validateMemoComboBox(); - void resetComboBox(const columnTypeE comboBox); - bool validateSelectedColumn(const int col, const columnTypeE type); + void resetComboBox(const Column comboBox); + bool validateSelectedColumn(const int col, const Column type); BankingProfile *m_profile; + Ui::BankingPage *ui; private slots: void memoColSelected(int col); diff --git a/kmymoney/plugins/csvimport/bankingwizardpage.cpp b/kmymoney/plugins/csvimport/bankingwizardpage.cpp --- a/kmymoney/plugins/csvimport/bankingwizardpage.cpp +++ b/kmymoney/plugins/csvimport/bankingwizardpage.cpp @@ -23,6 +23,7 @@ // QT Includes #include +#include // ---------------------------------------------------------------------------- // KDE Includes @@ -32,8 +33,9 @@ // ---------------------------------------------------------------------------- // Project Includes -#include "mymoneyfile.h" +#include #include "csvwizard.h" +#include "csvimporter.h" #include "ui_bankingwizardpage.h" @@ -44,69 +46,24 @@ ui(new Ui::BankingPage) { ui->setupUi(this); - m_pageLayout = new QVBoxLayout; - ui->horizontalLayout->insertLayout(0, m_pageLayout); connect(ui->m_clear, &QAbstractButton::clicked, this, &BankingPage::clearColumns); connect(ui->m_radioAmount, &QAbstractButton::toggled, this, &BankingPage::amountToggled); connect(ui->m_radioDebitCredit, &QAbstractButton::toggled, this, &BankingPage::debitCreditToggled); connect(ui->m_oppositeSigns, &QAbstractButton::clicked, this, &BankingPage::oppositeSignsClicked); // initialize column names - m_dlg->m_colTypeName.insert(ColumnPayee,i18n("Payee")); - m_dlg->m_colTypeName.insert(ColumnNumber,i18n("Number")); - m_dlg->m_colTypeName.insert(ColumnDebit,i18n("Debit")); - m_dlg->m_colTypeName.insert(ColumnCredit,i18n("Credit")); - m_dlg->m_colTypeName.insert(ColumnDate,i18n("Date")); - m_dlg->m_colTypeName.insert(ColumnAmount,i18n("Amount")); - m_dlg->m_colTypeName.insert(ColumnCategory,i18n("Category")); - m_dlg->m_colTypeName.insert(ColumnMemo,i18n("Memo")); + m_dlg->m_colTypeName.insert(Column::Payee,i18n("Payee")); + m_dlg->m_colTypeName.insert(Column::Number,i18n("Number")); + m_dlg->m_colTypeName.insert(Column::Debit,i18n("Debit")); + m_dlg->m_colTypeName.insert(Column::Credit,i18n("Credit")); + m_dlg->m_colTypeName.insert(Column::Date,i18n("Date")); + m_dlg->m_colTypeName.insert(Column::Amount,i18n("Amount")); + m_dlg->m_colTypeName.insert(Column::Category,i18n("Category")); + m_dlg->m_colTypeName.insert(Column::Memo,i18n("Memo")); m_profile = dynamic_cast(m_imp->m_profile); -} - -BankingPage::~BankingPage() -{ - delete ui; -} -void BankingPage::initializeComboBoxes() -{ - // disable banking widgets allowing their initialization - disconnect(ui->m_amountCol, SIGNAL(currentIndexChanged(int)), this, SLOT(amountColSelected(int))); - disconnect(ui->m_debitCol, SIGNAL(currentIndexChanged(int)), this, SLOT(debitColSelected(int))); - disconnect(ui->m_creditCol, SIGNAL(currentIndexChanged(int)), this, SLOT(creditColSelected(int))); - disconnect(ui->m_memoCol, SIGNAL(currentIndexChanged(int)), this, SLOT(memoColSelected(int))); - disconnect(ui->m_numberCol, SIGNAL(currentIndexChanged(int)), this, SLOT(numberColSelected(int))); - disconnect(ui->m_dateCol, SIGNAL(currentIndexChanged(int)), this, SLOT(dateColSelected(int))); - disconnect(ui->m_payeeCol, SIGNAL(currentIndexChanged(int)), this, SLOT(payeeColSelected(int))); - disconnect(ui->m_categoryCol, SIGNAL(currentIndexChanged(int)), this, SLOT(categoryColSelected(int))); - - // clear all existing items before adding new ones - ui->m_numberCol->clear(); - ui->m_dateCol->clear(); - ui->m_payeeCol->clear(); - ui->m_memoCol->clear(); - ui->m_amountCol->clear(); - ui->m_creditCol->clear(); - ui->m_debitCol->clear(); - ui->m_categoryCol->clear(); - - QStringList columnNumbers; - for (int i = 0; i < m_imp->m_file->m_columnCount; ++i) - columnNumbers.append(QString::number(i + 1)); - - // populate comboboxes with col # values - ui->m_numberCol->addItems(columnNumbers); - ui->m_dateCol->addItems(columnNumbers); - ui->m_payeeCol->addItems(columnNumbers); - ui->m_memoCol->addItems(columnNumbers); - ui->m_amountCol->addItems(columnNumbers); - ui->m_creditCol->addItems(columnNumbers); - ui->m_debitCol->addItems(columnNumbers); - ui->m_categoryCol->addItems(columnNumbers); - - clearColumns(); // all comboboxes are set to 0 so set them to -1 connect(ui->m_amountCol, SIGNAL(currentIndexChanged(int)), this, SLOT(amountColSelected(int))); connect(ui->m_debitCol, SIGNAL(currentIndexChanged(int)), this, SLOT(debitColSelected(int))); connect(ui->m_creditCol, SIGNAL(currentIndexChanged(int)), this, SLOT(creditColSelected(int))); @@ -117,18 +74,25 @@ connect(ui->m_categoryCol, SIGNAL(currentIndexChanged(int)), this, SLOT(categoryColSelected(int))); } +BankingPage::~BankingPage() +{ + delete ui; +} + void BankingPage::initializePage() { + QHash columns {{Column::Amount, ui->m_amountCol}, {Column::Debit, ui->m_debitCol}, + {Column::Credit, ui->m_creditCol}, {Column::Memo, ui->m_memoCol}, + {Column::Number, ui->m_numberCol}, {Column::Date, ui->m_dateCol}, + {Column::Payee, ui->m_payeeCol}, {Column::Category, ui->m_categoryCol}}; + if (ui->m_dateCol->count() != m_imp->m_file->m_columnCount) - initializeComboBoxes(); - - ui->m_payeeCol->setCurrentIndex(m_profile->m_colTypeNum.value(ColumnPayee)); - ui->m_numberCol->setCurrentIndex(m_profile->m_colTypeNum.value(ColumnNumber)); - ui->m_amountCol->setCurrentIndex(m_profile->m_colTypeNum.value(ColumnAmount)); - ui->m_debitCol->setCurrentIndex(m_profile->m_colTypeNum.value(ColumnDebit)); - ui->m_creditCol->setCurrentIndex(m_profile->m_colTypeNum.value(ColumnCredit)); - ui->m_dateCol->setCurrentIndex(m_profile->m_colTypeNum.value(ColumnDate)); - ui->m_categoryCol->setCurrentIndex(m_profile->m_colTypeNum.value(ColumnCategory)); + m_dlg->initializeComboBoxes(columns); + + columns.remove(Column::Memo); + for (auto it = columns.cbegin(); it != columns.cend(); ++it) + it.value()->setCurrentIndex(m_profile->m_colTypeNum.value(it.key())); + ui->m_oppositeSigns->setChecked(m_profile->m_oppositeSigns); if (m_profile->m_memoColList.count() > 0) @@ -138,7 +102,7 @@ } else ui->m_memoCol->setCurrentIndex(-1); - if (this->m_profile->m_colTypeNum.value(ColumnDebit) == -1) // If amount previously selected, set check radio_amount + if (this->m_profile->m_colTypeNum.value(Column::Debit) == -1) // If amount previously selected, set check radio_amount ui->m_radioAmount->setChecked(true); else // ...else set check radio_debCred to clear amount col ui->m_radioDebitCredit->setChecked(true); @@ -165,8 +129,8 @@ for (int i = 0; i < ui->m_memoCol->count(); ++i) { QString txt = ui->m_memoCol->itemText(i); - if (txt.contains(QChar(QLatin1Char('*')))) // check if text containing '*' belongs to valid column types - if (m_profile->m_colNumType.value(i) != ColumnPayee) { + if (txt.contains(QLatin1Char('*'))) // check if text containing '*' belongs to valid column types + if (m_profile->m_colNumType.value(i) != Column::Payee) { ui->m_memoCol->setItemText(i, QString::number(i + 1)); m_profile->m_memoColList.removeOne(i); return false; @@ -177,73 +141,73 @@ void BankingPage::memoColSelected(int col) { - if (m_profile->m_colNumType.value(col) == ColumnPayee ) { + if (m_profile->m_colNumType.value(col) == Column::Payee ) { int rc = KMessageBox::Yes; if (isVisible()) rc = KMessageBox::questionYesNo(m_dlg, i18n("
The '%1' field already has this column selected.
" "
If you wish to copy the Payee data to the memo field, click 'Yes'.
", m_dlg->m_colTypeName.value(m_profile->m_colNumType.value(col)))); if (rc == KMessageBox::Yes) { - ui->m_memoCol->setItemText(col, QString::number(col + 1) + QChar(QLatin1Char('*'))); + ui->m_memoCol->setItemText(col, QString::number(col + 1) + QLatin1Char('*')); if (!m_profile->m_memoColList.contains(col)) m_profile->m_memoColList.append(col); } else { ui->m_memoCol->setItemText(col, QString::number(col + 1)); m_profile->m_memoColList.removeOne(col); } //allow only separate memo field occupy combobox ui->m_memoCol->blockSignals(true); - if (m_profile->m_colTypeNum.value(ColumnMemo) != -1) - ui->m_memoCol->setCurrentIndex(m_profile->m_colTypeNum.value(ColumnMemo)); + if (m_profile->m_colTypeNum.value(Column::Memo) != -1) + ui->m_memoCol->setCurrentIndex(m_profile->m_colTypeNum.value(Column::Memo)); else ui->m_memoCol->setCurrentIndex(-1); ui->m_memoCol->blockSignals(false); return; } - if (m_profile->m_colTypeNum.value(ColumnMemo) != -1) // check if this memo has any column 'number' assigned... + if (m_profile->m_colTypeNum.value(Column::Memo) != -1) // check if this memo has any column 'number' assigned... m_profile->m_memoColList.removeOne(col); // ...if true remove it from memo list - if(validateSelectedColumn(col, ColumnMemo)) + if(validateSelectedColumn(col, Column::Memo)) if (col != - 1 && !m_profile->m_memoColList.contains(col)) m_profile->m_memoColList.append(col); } void BankingPage::categoryColSelected(int col) { - validateSelectedColumn(col, ColumnCategory); + validateSelectedColumn(col, Column::Category); } void BankingPage::numberColSelected(int col) { - validateSelectedColumn(col, ColumnNumber); + validateSelectedColumn(col, Column::Number); } void BankingPage::payeeColSelected(int col) { - if (validateSelectedColumn(col, ColumnPayee)) + if (validateSelectedColumn(col, Column::Payee)) if (!validateMemoComboBox()) // user could have it already in memo so... memoColSelected(col); // ...if true set memo field again } void BankingPage::dateColSelected(int col) { - validateSelectedColumn(col, ColumnDate); + validateSelectedColumn(col, Column::Date); } void BankingPage::debitColSelected(int col) { - validateSelectedColumn(col, ColumnDebit); + validateSelectedColumn(col, Column::Debit); } void BankingPage::creditColSelected(int col) { - validateSelectedColumn(col, ColumnCredit); + validateSelectedColumn(col, Column::Credit); } void BankingPage::amountColSelected(int col) { - validateSelectedColumn(col, ColumnAmount); + validateSelectedColumn(col, Column::Amount); } void BankingPage::amountToggled(bool checked) @@ -292,40 +256,40 @@ ui->m_categoryCol->setCurrentIndex(-1); } -void BankingPage::resetComboBox(const columnTypeE comboBox) +void BankingPage::resetComboBox(const Column comboBox) { switch (comboBox) { - case ColumnAmount: + case Column::Amount: ui->m_amountCol->setCurrentIndex(-1); break; - case ColumnCredit: + case Column::Credit: ui->m_creditCol->setCurrentIndex(-1); break; - case ColumnDate: + case Column::Date: ui->m_dateCol->setCurrentIndex(-1); break; - case ColumnDebit: + case Column::Debit: ui->m_debitCol->setCurrentIndex(-1); break; - case ColumnMemo: + case Column::Memo: ui->m_memoCol->setCurrentIndex(-1); break; - case ColumnNumber: + case Column::Number: ui->m_numberCol->setCurrentIndex(-1); break; - case ColumnPayee: + case Column::Payee: ui->m_payeeCol->setCurrentIndex(-1); break; - case ColumnCategory: + case Column::Category: ui->m_categoryCol->setCurrentIndex(-1); break; default: KMessageBox::sorry(m_dlg, i18n("
Field name not recognised.
'%1'
Please re-enter your column selections." - , comboBox), i18n("CSV import")); + , (int)comboBox), i18n("CSV import")); } } -bool BankingPage::validateSelectedColumn(const int col, const columnTypeE type) +bool BankingPage::validateSelectedColumn(const int col, const Column type) { if (m_profile->m_colTypeNum.value(type) != -1) // check if this 'type' has any column 'number' assigned... m_profile->m_colNumType.remove(m_profile->m_colTypeNum[type]); // ...if true remove 'type' assigned to this column 'number' @@ -351,43 +315,45 @@ { for (int row = m_profile->m_startLine; row <= m_profile->m_endLine; ++row) { // process credit/debit field - if (m_profile->m_colTypeNum.value(ColumnCredit) != -1 && - m_profile->m_colTypeNum.value(ColumnDebit) != -1) { - QString credit = m_imp->m_file->m_model->item(row, m_profile->m_colTypeNum.value(ColumnCredit))->text(); - QString debit = m_imp->m_file->m_model->item(row, m_profile->m_colTypeNum.value(ColumnDebit))->text(); + if (m_profile->m_colTypeNum.value(Column::Credit) != -1 && + m_profile->m_colTypeNum.value(Column::Debit) != -1) { + QString credit = m_imp->m_file->m_model->item(row, m_profile->m_colTypeNum.value(Column::Credit))->text(); + QString debit = m_imp->m_file->m_model->item(row, m_profile->m_colTypeNum.value(Column::Debit))->text(); m_imp->processCreditDebit(credit, debit); if (!credit.isEmpty() && !debit.isEmpty()) { int ret = KMessageBox::questionYesNoCancel(m_dlg, i18n("
The %1 field contains '%2'
" "
and the %3 field contains '%4'.
" "
Please choose which you wish to accept.
", - m_dlg->m_colTypeName.value(ColumnDebit), + m_dlg->m_colTypeName.value(Column::Debit), debit, - m_dlg->m_colTypeName.value(ColumnCredit), + m_dlg->m_colTypeName.value(Column::Credit), credit), i18n("CSV invalid field values"), - KGuiItem(i18n("Accept %1", m_dlg->m_colTypeName.value(ColumnDebit))), - KGuiItem(i18n("Accept %1", m_dlg->m_colTypeName.value(ColumnCredit))), + KGuiItem(i18n("Accept %1", m_dlg->m_colTypeName.value(Column::Debit))), + KGuiItem(i18n("Accept %1", m_dlg->m_colTypeName.value(Column::Credit))), KGuiItem(i18n("Cancel"))); switch(ret) { case KMessageBox::Cancel: return false; case KMessageBox::Yes: - m_imp->m_file->m_model->item(row, m_profile->m_colTypeNum.value(ColumnCredit))->setText(QString()); + m_imp->m_file->m_model->item(row, m_profile->m_colTypeNum.value(Column::Credit))->setText(QString()); break; case KMessageBox::No: - m_imp->m_file->m_model->item(row, m_profile->m_colTypeNum.value(ColumnDebit))->setText(QString()); + m_imp->m_file->m_model->item(row, m_profile->m_colTypeNum.value(Column::Debit))->setText(QString()); break; } } } } return true; } -void BankingPage::makeQIF(MyMoneyStatement& st, QFile& file) +void BankingPage::makeQIF(const MyMoneyStatement& st, const QString& outFileName) { - QTextStream out(&file); + QFile oFile(outFileName); + oFile.open(QIODevice::WriteOnly); + QTextStream out(&oFile); QString buffer; QString strEType; @@ -426,4 +392,5 @@ out << buffer;// output qif file buffer.clear(); } + oFile.close(); } diff --git a/kmymoney/plugins/csvimport/convdate.h b/kmymoney/plugins/csvimport/convdate.h --- a/kmymoney/plugins/csvimport/convdate.h +++ b/kmymoney/plugins/csvimport/convdate.h @@ -1,9 +1,11 @@ /*************************************************************************** - convDate.h + convdate.h ------------------- begin : Sat Jan 01 2010 copyright : (C) 2010 by Allan Anderson email : agander93@gmail.com +copyright : (C) 2017 by Łukasz Wojniłowicz +email : lukasz.wojnilowicz@gmail.com ***************************************************************************/ /************************************************************************** @@ -18,13 +20,13 @@ #ifndef CONVDATE_H #define CONVDATE_H -#include -#include -#include +#include +#include "csvenums.h" -class ConvertDate: public QObject +#include "csvimport/kmm_csvimport_core_export.h" + +class KMM_CSVIMPORT_CORE_EXPORT ConvertDate { - Q_OBJECT public: ConvertDate(); @@ -42,18 +44,10 @@ */ QString stringFormat(); - void setDateFormatIndex(int index); + void setDateFormatIndex(const DateFormat _d); private: - int m_dateFormatIndex; - -private slots: - - /** - * This method is called when the user clicks the Date button and selects - * the date format for the input file. - */ - void dateFormatSelected(int dateFormat); + DateFormat m_dateFormatIndex; } ; #endif diff --git a/kmymoney/plugins/csvimport/convdate.cpp b/kmymoney/plugins/csvimport/convdate.cpp --- a/kmymoney/plugins/csvimport/convdate.cpp +++ b/kmymoney/plugins/csvimport/convdate.cpp @@ -19,13 +19,13 @@ #include "convdate.h" -#include #include -#include +#include + +ConvertDate::ConvertDate(): + m_dateFormatIndex(DateFormat::YearMonthDay) -ConvertDate::ConvertDate() { - m_dateFormatIndex = 0; } ConvertDate::~ConvertDate() @@ -38,46 +38,46 @@ QString aMonth; QString aDay; QString aFormat; - static QString dat; + QString dat; QDate aDate; QString dateFormatString = stringFormat(); - QRegExp rx("[\\. :-]"); // replace date field separators '.' ' ' ':' '-' + QRegularExpression rx(QStringLiteral("[\\. :-]")); // replace date field separators '.' ' ' ':' '-' QString buffer = txt.trimmed(); - buffer = buffer.replace(rx, QString('/')); // ....with '/' - int count = buffer.count('/', Qt::CaseSensitive); + buffer = buffer.replace(rx, QString::fromLatin1("/")); // ....with '/' + int count = buffer.count(QLatin1Char('/'), Qt::CaseSensitive); if (count == 0) { // no separators so use QDate() QDate result = QDate::fromString(buffer, dateFormatString); if (result.year() < 1950) { result = QDate(); } return result; } - QStringList dateSplit = buffer.split('/'); + QStringList dateSplit = buffer.split(QLatin1Char('/')); if (dateSplit.count() > 3) { // it can be date and time qDebug("ConvertDate - assuming date and time format"); bool dateFound = false; for (int i = 0; i < dateSplit.count(); i++) { if(dateSplit[i].length() == 4 && dateSplit[i].toInt() > 0) { switch (m_dateFormatIndex) { - case(0) : // %y %m %d + case DateFormat::YearMonthDay: // %y %m %d if(i+2 < dateSplit.count()) { aYear = dateSplit[i]; aMonth = dateSplit[i+1]; aDay = dateSplit[i+2]; dateFound = true; } break; - case(1) : // %m %d %y + case DateFormat::MonthDayYear: // %m %d %y if(i-2 >= 0) { aMonth = dateSplit[i-2]; aDay = dateSplit[i-1]; aYear = dateSplit[i]; dateFound = true; } break; - case(2) : // %d %m %y + case DateFormat::DayMonthYear: // %d %m %y if(i-2 >= 0) { aDay = dateSplit[i-2]; aMonth = dateSplit[i-1]; @@ -97,17 +97,17 @@ } } else if(dateSplit.count() == 3) { switch (m_dateFormatIndex) { - case(0) : // %y %m %d + case DateFormat::YearMonthDay: // %y %m %d aYear = dateSplit[0]; aMonth = dateSplit[1]; aDay = dateSplit[2]; break; - case(1) : // %m %d %y + case DateFormat::MonthDayYear: // %m %d %y aMonth = dateSplit[0]; aDay = dateSplit[1]; aYear = dateSplit[2]; break; - case(2) : // %d %m %y + case DateFormat::DayMonthYear: // %d %m %y aDay = dateSplit[0]; aMonth = dateSplit[1]; aYear = dateSplit[2]; @@ -124,17 +124,17 @@ else return QDate(); switch (m_dateFormatIndex) { - case(0) : // %y %m %d + case DateFormat::YearMonthDay: // %y %m %d aYear = date.left(4); aMonth = date.mid(4,2); aDay = date.right(2); break; - case(1) : // %m %d %y + case DateFormat::MonthDayYear: // %m %d %y aMonth = date.left(2); aDay = date.mid(2,2); aYear = date.right(4); break; - case(2) : // %d %m %y + case DateFormat::DayMonthYear: // %d %m %y aDay = date.left(2); aMonth = date.mid(2,2); aYear = date.right(4); @@ -148,9 +148,9 @@ // Check year if (aYear.length() == 2) { // 2 digits if ((aYear.toInt() >= 0) && (aYear.toInt() < 50)) { - aYear = "20" + aYear;// take year to be 2000-2049 + aYear.prepend(QLatin1String("20"));// take year to be 2000-2049 } else if ((aYear.toInt() >= 50) && (aYear.toInt() <= 99)) - aYear = "19" + aYear;// take year to be 1950-1999 + aYear.prepend(QLatin1String("19"));// take year to be 1950-1999 } else if (aYear.length() == 4) { if ((aYear.toInt() < 1950) || (aYear.toInt() > 2050)) { // not a valid year return QDate(); @@ -161,41 +161,41 @@ // only years 1950-2050 valid // check day if (aDay.length() == 1) - aDay = '0' + aDay;// add a leading '0' + aDay.prepend(QLatin1Char('0'));// add a leading '0' if ((aDay.toInt() < 0) || (aDay.toInt() > 31) // check day value || (aDay.length() < 1) || (aDay.length() > 2)) { return QDate();// not a valid day } // check month if (aMonth.length() == 1) { - aMonth = '0' + aMonth; - aFormat = "MM"; + aMonth.prepend(QLatin1Char('0')); + aFormat = QLatin1String("MM"); } else if (aMonth.length() == 2) { // assume numeric bool datefound = ((aMonth.toUInt() > 0) && (aMonth.toUInt() < 13)); if (!datefound) { return QDate();// not a valid day } - aFormat = "MM";// aMonth is numeric + aFormat = QLatin1String("MM");// aMonth is numeric } else {// aMonth NOT numeric if (aMonth.length() == 3) - aFormat = "MMM"; + aFormat = QLatin1String("MMM"); else - aFormat = "MMMM"; + aFormat = QLatin1String("MMMM"); } QString dateFormat; switch (m_dateFormatIndex) { - case(0) : // %y %m %d - dateFormat = "yyyy" + aFormat + "dd"; + case DateFormat::YearMonthDay: // %y %m %d + dateFormat = QString::fromLatin1("yyyy%1dd").arg(aFormat); dat = aYear + aMonth + aDay; break; - case(1) : // %m %d %y - dateFormat = aFormat + "dd" + "yyyy"; + case DateFormat::MonthDayYear: // %m %d %y + dateFormat = QString::fromLatin1("%1ddyyyy").arg(aFormat); dat = aMonth + aDay + aYear; break; - case(2) : // %d %m %y - dateFormat = "dd" + aFormat + "yyyy"; + case DateFormat::DayMonthYear: // %d %m %y + dateFormat = QString::fromLatin1("dd%1yyyy").arg(aFormat); dat = aDay + aMonth + aYear; break; default: @@ -205,31 +205,23 @@ return aDate; } -void ConvertDate::dateFormatSelected(int dateFormat) -{ - if (dateFormat == -1) { // need UK, USA or ISO date format - return;// no selection made - } - m_dateFormatIndex = dateFormat; -} - -void ConvertDate::setDateFormatIndex(int index) +void ConvertDate::setDateFormatIndex(const DateFormat _d) { - m_dateFormatIndex = index; + m_dateFormatIndex = _d; } QString ConvertDate::stringFormat() { QString dateFormatString; switch (m_dateFormatIndex) { - case(0) : // %y %m %d - dateFormatString = "yyyyMMdd"; + case DateFormat::YearMonthDay: // %y %m %d + dateFormatString = QLatin1String("yyyyMMdd"); break; - case(1) : // %m %d %y - dateFormatString = "MMddyyyy"; + case DateFormat::MonthDayYear: // %m %d %y + dateFormatString = QLatin1String("MMddyyyy"); break; - case(2) : // %d %m %y - dateFormatString = "ddMMyyyy"; + case DateFormat::DayMonthYear: // %d %m %y + dateFormatString = QLatin1String("ddMMyyyy"); break; default: qDebug("ConvertDate - date format unknown"); diff --git a/kmymoney/plugins/csvimport/csvenums.h b/kmymoney/plugins/csvimport/csvenums.h new file mode 100644 --- /dev/null +++ b/kmymoney/plugins/csvimport/csvenums.h @@ -0,0 +1,35 @@ +/*************************************************************************** + csvenums.h + ----------- +begin : Sun Jun 09 2010 +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 + +#ifndef CSVENUMS_H +#define CSVENUMS_H + +enum class FieldDelimiter { Comma = 0, Semicolon, Colon, Tab, Auto }; +enum class TextDelimiter { DoubleQuote = 0, SingleQuote }; +enum class DecimalSymbol { Dot = 0, Comma, Auto }; +enum class ThousandSeparator { Comma = 0, Dot }; +enum class DateFormat { YearMonthDay = 0, MonthDayYear, DayMonthYear }; +enum class Column { Date, Memo, Number, Payee, Amount, Credit, Debit, Category, Type, Price, Quantity, Fee, Symbol, Name, Empty = 0xFE, Invalid = 0xFF }; +enum class Profile { Banking, Investment, CurrencyPrices, StockPrices }; +enum class ProfileAction { Add, Remove, Rename, UpdateLastUsed }; + +inline uint qHash(const Column key, uint seed) { return ::qHash(static_cast(key), seed); } +inline uint qHash(const Profile key, uint seed) { return ::qHash(static_cast(key), seed); } + +#endif diff --git a/kmymoney/plugins/csvimport/csvimporter.h b/kmymoney/plugins/csvimport/csvimporter.h --- a/kmymoney/plugins/csvimport/csvimporter.h +++ b/kmymoney/plugins/csvimport/csvimporter.h @@ -29,48 +29,25 @@ // QT Includes #include +#include // Project Includes -#include "convdate.h" -#include "csvutil.h" -#include "mymoneystatement.h" +#include +#include +#include "csvenums.h" +#include "csvimport/kmm_csvimport_core_export.h" -#include - -class CSVWizard; -class CSVImporter; - -class CSVWizardPage : public QWizardPage -{ -public: - CSVWizardPage(CSVWizard *dlg, CSVImporter *imp) : QWizardPage(nullptr), m_dlg(dlg), m_imp(imp) {} - -protected: - CSVWizard *m_dlg; - CSVImporter *m_imp; -}; - -enum profileTypeE { ProfileBank, ProfileInvest, - ProfileCurrencyPrices, ProfileStockPrices - }; - -enum profilesActionE { ProfilesAdd, ProfilesRemove, ProfilesRename, ProfilesUpdateLastUsed }; +class Parse; +class CsvUtil; +class ConvertDate; enum autodetectTypeE { AutoFieldDelimiter, AutoDecimalSymbol, AutoDateFormat, AutoAccountInvest, AutoAccountBank }; -enum columnTypeE { ColumnDate, ColumnMemo, - ColumnNumber, ColumnPayee, ColumnAmount, - ColumnCredit, ColumnDebit, ColumnCategory, - ColumnType, ColumnPrice, ColumnQuantity, - ColumnFee, ColumnSymbol, ColumnName, - ColumnEmpty = 0xFE, ColumnInvalid = 0xFF - }; - enum miscSettingsE { ConfDirectory, ConfEncoding, ConfDateFormat, - ConfFieldDelimiter, ConfTextDeimiter, ConfDecimalSymbol, + ConfFieldDelimiter, ConfTextDelimiter, ConfDecimalSymbol, ConfStartLine, ConfTrailerLines, ConfOppositeSigns, ConfFeeIsPercentage, ConfFeeRate, ConfMinFee, @@ -82,18 +59,18 @@ enum validationResultE { ValidActionType, InvalidActionValues, NoActionType }; -class CSVProfile +class KMM_CSVIMPORT_CORE_NO_EXPORT CSVProfile { protected: CSVProfile() {} CSVProfile(const QString &profileName, int encodingMIBEnum, int startLine, int trailerLines, - int dateFormatIndex, int fieldDelimiterIndex, int textDelimiterIndex, int decimalSymbolIndex, - QMap &colTypeNum) : + DateFormat dateFormat, FieldDelimiter fieldDelimiter, TextDelimiter textDelimiter, DecimalSymbol decimalSymbol, + QMap &colTypeNum) : m_profileName(profileName), m_encodingMIBEnum(encodingMIBEnum), m_startLine(startLine), m_trailerLines(trailerLines), - m_dateFormatIndex(dateFormatIndex), m_fieldDelimiterIndex(fieldDelimiterIndex), - m_textDelimiterIndex(textDelimiterIndex), m_decimalSymbolIndex(decimalSymbolIndex), + m_dateFormat(dateFormat), m_fieldDelimiter(fieldDelimiter), + m_textDelimiter(textDelimiter), m_decimalSymbol(decimalSymbol), m_colTypeNum(colTypeNum) { initColNumType(); @@ -107,7 +84,7 @@ public: virtual ~CSVProfile() {} - virtual profileTypeE type() const = 0; + virtual Profile type() const = 0; virtual bool readSettings(const KSharedConfigPtr &config) = 0; virtual void writeSettings(const KSharedConfigPtr &config) = 0; @@ -120,31 +97,31 @@ int m_endLine; int m_trailerLines; - int m_dateFormatIndex; - int m_fieldDelimiterIndex; - int m_textDelimiterIndex; - int m_decimalSymbolIndex; + DateFormat m_dateFormat; + FieldDelimiter m_fieldDelimiter; + TextDelimiter m_textDelimiter; + DecimalSymbol m_decimalSymbol; - QMap m_colTypeNum; - QMap m_colNumType; + QMap m_colTypeNum; + QMap m_colNumType; }; -class BankingProfile : public CSVProfile +class KMM_CSVIMPORT_CORE_EXPORT BankingProfile : public CSVProfile { public: - profileTypeE type() const { return ProfileBank; } + Profile type() const { return Profile::Banking; } bool readSettings(const KSharedConfigPtr &config); void writeSettings(const KSharedConfigPtr &config); QList m_memoColList; bool m_oppositeSigns; }; -class InvestmentProfile : public CSVProfile +class KMM_CSVIMPORT_CORE_EXPORT InvestmentProfile : public CSVProfile { public: - profileTypeE type() const { return ProfileInvest; } + Profile type() const { return Profile::Investment; } bool readSettings(const KSharedConfigPtr &config); void writeSettings(const KSharedConfigPtr &config); @@ -162,23 +139,23 @@ int m_dontAsk; }; -class PricesProfile : public CSVProfile +class KMM_CSVIMPORT_CORE_EXPORT PricesProfile : public CSVProfile { public: explicit PricesProfile() : CSVProfile() {} - explicit PricesProfile(const profileTypeE profileType) : CSVProfile(), m_profileType(profileType) {} + explicit PricesProfile(const Profile profileType) : CSVProfile(), m_profileType(profileType) {} PricesProfile(QString profileName, int encodingMIBEnum, int startLine, int trailerLines, - int dateFormatIndex, int fieldDelimiterIndex, int textDelimiterIndex, int decimalSymbolIndex, - QMap colTypeNum, - int priceFraction, profileTypeE profileType) : + DateFormat dateFormat, FieldDelimiter fieldDelimiter, TextDelimiter textDelimiter, DecimalSymbol decimalSymbol, + QMap colTypeNum, + int priceFraction, Profile profileType) : CSVProfile(profileName, encodingMIBEnum, startLine, trailerLines, - dateFormatIndex, fieldDelimiterIndex, textDelimiterIndex, decimalSymbolIndex, + dateFormat, fieldDelimiter, textDelimiter, decimalSymbol, colTypeNum), m_priceFraction(priceFraction), m_profileType(profileType) {} - profileTypeE type() const { return m_profileType; } + Profile type() const { return m_profileType; } bool readSettings(const KSharedConfigPtr &config); void writeSettings(const KSharedConfigPtr &config); @@ -189,10 +166,10 @@ int m_dontAsk; int m_priceFraction; - profileTypeE m_profileType; + Profile m_profileType; }; -class CSVFile +class KMM_CSVIMPORT_CORE_EXPORT CSVFile { public: explicit CSVFile(); @@ -220,7 +197,6 @@ */ void readFile(CSVProfile *profile); - CsvUtil *m_csvUtil; Parse *m_parse; QStandardItemModel *m_model; @@ -230,9 +206,8 @@ int m_rowCount; }; -class CSVImporter : public QObject +class KMM_CSVIMPORT_CORE_EXPORT CSVImporter { - Q_OBJECT public: explicit CSVImporter(); ~CSVImporter(); @@ -243,7 +218,7 @@ MyMoneyStatement unattendedPricesImport(const QString &filename, PricesProfile *profile); static KSharedConfigPtr configFile(); - void profileFactory(const profileTypeE type, const QString &name); + void profileFactory(const Profile type, const QString &name); void readMiscSettings(); /** @@ -261,7 +236,7 @@ /** * This method will update [ProfileNames] in csvimporterrrc */ - static bool profilesAction(const profileTypeE type, const profilesActionE action, const QString &name, const QString &newname); + static bool profilesAction(const Profile type, const ProfileAction action, const QString &name, const QString &newname); /** * This methods will ensure that fields of input rows are correct. @@ -278,7 +253,7 @@ * This method will try to detect decimal symbol in input column. */ int detectDecimalSymbols(const QList &columns); - int detectDecimalSymbol(const int col, const QString &exclude); + DecimalSymbol detectDecimalSymbol(const int col, const QString &exclude); /** * This method will try to detect account from csv header. @@ -344,20 +319,17 @@ QList m_priceFractions; QSet m_hashSet; - QMap m_decimalSymbolIndexMap; + QMap m_decimalSymbolIndexMap; QMap m_mapSymbolName; QMap m_autodetect; - static const QMap m_colTypeConfName; - static const QMap m_profileConfPrefix; - static const QMap m_transactionConfName; - static const QMap m_miscSettingsConfName; - static const QString m_confProfileNames; - static const QString m_confPriorName; - static const QString m_confMiscName; - -signals: - void statementReady(MyMoneyStatement&); + static const QHash m_colTypeConfName; + static const QHash m_profileConfPrefix; + static const QHash m_transactionConfName; + static const QHash m_miscSettingsConfName; + static const QString m_confProfileNames; + static const QString m_confPriorName; + static const QString m_confMiscName; }; #endif diff --git a/kmymoney/plugins/csvimport/csvimporter.cpp b/kmymoney/plugins/csvimport/csvimporter.cpp --- a/kmymoney/plugins/csvimport/csvimporter.cpp +++ b/kmymoney/plugins/csvimport/csvimporter.cpp @@ -22,57 +22,54 @@ // ---------------------------------------------------------------------------- // QT Includes -#include -#include #include #include -#include -#include #include +#include // ---------------------------------------------------------------------------- // KDE Includes #include -#include #include // ---------------------------------------------------------------------------- // Project Includes -#include "mymoneystatementreader.h" -#include "mymoneyfile.h" +#include +#include "csvutil.h" +#include "convdate.h" -const QMap CSVImporter::m_profileConfPrefix = QMap{ - {ProfileBank, QStringLiteral("Bank")}, - {ProfileInvest, QStringLiteral("Invest")}, - {ProfileCurrencyPrices, QStringLiteral("CPrices")}, - {ProfileStockPrices, QStringLiteral("SPrices")} +const QHash CSVImporter::m_profileConfPrefix { + {Profile::Banking, QStringLiteral("Bank")}, + {Profile::Investment, QStringLiteral("Invest")}, + {Profile::CurrencyPrices, QStringLiteral("CPrices")}, + {Profile::StockPrices, QStringLiteral("SPrices")} }; -const QMap CSVImporter::m_colTypeConfName = QMap{ - {ColumnDate, QStringLiteral("DateCol")}, - {ColumnMemo, QStringLiteral("MemoCol")}, - {ColumnNumber, QStringLiteral("NumberCol")}, - {ColumnPayee, QStringLiteral("PayeeCol")}, - {ColumnAmount, QStringLiteral("AmountCol")}, - {ColumnCredit, QStringLiteral("CreditCol")}, - {ColumnDebit, QStringLiteral("DebitCol")}, - {ColumnCategory, QStringLiteral("CategoryCol")}, - {ColumnType, QStringLiteral("TypeCol")}, - {ColumnPrice, QStringLiteral("PriceCol")}, - {ColumnQuantity, QStringLiteral("QuantityCol")}, - {ColumnFee, QStringLiteral("FeeCol")}, - {ColumnSymbol, QStringLiteral("SymbolCol")}, - {ColumnName, QStringLiteral("NameCol")}, +const QHash CSVImporter::m_colTypeConfName { + {Column::Date, QStringLiteral("DateCol")}, + {Column::Memo, QStringLiteral("MemoCol")}, + {Column::Number, QStringLiteral("NumberCol")}, + {Column::Payee, QStringLiteral("PayeeCol")}, + {Column::Amount, QStringLiteral("AmountCol")}, + {Column::Credit, QStringLiteral("CreditCol")}, + {Column::Debit, QStringLiteral("DebitCol")}, + {Column::Category, QStringLiteral("CategoryCol")}, + {Column::Type, QStringLiteral("TypeCol")}, + {Column::Price, QStringLiteral("PriceCol")}, + {Column::Quantity, QStringLiteral("QuantityCol")}, + {Column::Fee, QStringLiteral("FeeCol")}, + {Column::Symbol, QStringLiteral("SymbolCol")}, + {Column::Name, QStringLiteral("NameCol")}, }; -const QMap CSVImporter::m_miscSettingsConfName = QMap{ +const QHash CSVImporter::m_miscSettingsConfName { {ConfDirectory, QStringLiteral("Directory")}, {ConfEncoding, QStringLiteral("Encoding")}, {ConfDateFormat, QStringLiteral("DateFormat")}, {ConfFieldDelimiter, QStringLiteral("FieldDelimiter")}, - {ConfTextDeimiter, QStringLiteral("TextDelimiter")}, + {ConfTextDelimiter, QStringLiteral("TextDelimiter")}, {ConfDecimalSymbol, QStringLiteral("DecimalSymbol")}, {ConfStartLine, QStringLiteral("StartLine")}, {ConfTrailerLines, QStringLiteral("TrailerLines")}, @@ -89,7 +86,7 @@ {ConfWidth, QStringLiteral("Width")} }; -const QMap CSVImporter::m_transactionConfName = QMap{ +const QHash CSVImporter::m_transactionConfName { {MyMoneyStatement::Transaction::eaBuy, QStringLiteral("BuyParam")}, {MyMoneyStatement::Transaction::eaSell, QStringLiteral("SellParam")}, {MyMoneyStatement::Transaction::eaReinvestDividend, QStringLiteral("ReinvdivParam")}, @@ -123,7 +120,7 @@ { MyMoneyStatement st; m_profile = profile; - m_convertDate->setDateFormatIndex(m_profile->m_dateFormatIndex); + m_convertDate->setDateFormatIndex(m_profile->m_dateFormat); if (m_file->getInFileName(filename)) { m_file->readFile(m_profile); @@ -142,21 +139,23 @@ .filePath(QStringLiteral("csvimporterrc"))); } -void CSVImporter::profileFactory(const profileTypeE type, const QString &name) +void CSVImporter::profileFactory(const Profile type, const QString &name) { - if (!m_profile) + if (!m_profile) { delete m_profile; + m_profile = nullptr; + } switch (type) { default: - case ProfileInvest: + case Profile::Investment: m_profile = new InvestmentProfile; break; - case ProfileBank: + case Profile::Banking: m_profile = new BankingProfile; break; - case ProfileCurrencyPrices: - case ProfileStockPrices: + case Profile::CurrencyPrices: + case Profile::StockPrices: m_profile = new PricesProfile(type); break; } @@ -178,14 +177,14 @@ const KSharedConfigPtr config = configFile(); KConfigGroup profileNamesGroup(config, m_confProfileNames); if (!profileNamesGroup.exists()) { - profileNamesGroup.writeEntry(m_profileConfPrefix.value(ProfileBank), QStringList()); - profileNamesGroup.writeEntry(m_profileConfPrefix.value(ProfileInvest), QStringList()); - profileNamesGroup.writeEntry(m_profileConfPrefix.value(ProfileCurrencyPrices), QStringList()); - profileNamesGroup.writeEntry(m_profileConfPrefix.value(ProfileStockPrices), QStringList()); - profileNamesGroup.writeEntry(m_confPriorName + m_profileConfPrefix.value(ProfileBank), int()); - profileNamesGroup.writeEntry(m_confPriorName + m_profileConfPrefix.value(ProfileInvest), int()); - profileNamesGroup.writeEntry(m_confPriorName + m_profileConfPrefix.value(ProfileCurrencyPrices), int()); - profileNamesGroup.writeEntry(m_confPriorName + m_profileConfPrefix.value(ProfileStockPrices), int()); + profileNamesGroup.writeEntry(m_profileConfPrefix.value(Profile::Banking), QStringList()); + profileNamesGroup.writeEntry(m_profileConfPrefix.value(Profile::Investment), QStringList()); + profileNamesGroup.writeEntry(m_profileConfPrefix.value(Profile::CurrencyPrices), QStringList()); + profileNamesGroup.writeEntry(m_profileConfPrefix.value(Profile::StockPrices), QStringList()); + profileNamesGroup.writeEntry(m_confPriorName + m_profileConfPrefix.value(Profile::Banking), int()); + profileNamesGroup.writeEntry(m_confPriorName + m_profileConfPrefix.value(Profile::Investment), int()); + profileNamesGroup.writeEntry(m_confPriorName + m_profileConfPrefix.value(Profile::CurrencyPrices), int()); + profileNamesGroup.writeEntry(m_confPriorName + m_profileConfPrefix.value(Profile::StockPrices), int()); profileNamesGroup.sync(); } @@ -224,12 +223,12 @@ QFile::copy(configFilePath, configFilePath + QLatin1String(".bak")); KConfigGroup profileNamesGroup(config, m_confProfileNames); - QStringList bankProfiles = profileNamesGroup.readEntry(m_profileConfPrefix.value(ProfileBank), QStringList()); - QStringList investProfiles = profileNamesGroup.readEntry(m_profileConfPrefix.value(ProfileInvest), QStringList()); - QStringList invalidBankProfiles = profileNamesGroup.readEntry(QLatin1String("Invalid") + m_profileConfPrefix.value(ProfileBank), QStringList()); // get profiles that was marked invalid during last update - QStringList invalidInvestProfiles = profileNamesGroup.readEntry(QLatin1String("Invalid") + m_profileConfPrefix.value(ProfileInvest), QStringList()); - QString bankPrefix = m_profileConfPrefix.value(ProfileBank) + QLatin1Char('-'); - QString investPrefix = m_profileConfPrefix.value(ProfileInvest) + QLatin1Char('-'); + QStringList bankProfiles = profileNamesGroup.readEntry(m_profileConfPrefix.value(Profile::Banking), QStringList()); + QStringList investProfiles = profileNamesGroup.readEntry(m_profileConfPrefix.value(Profile::Investment), QStringList()); + QStringList invalidBankProfiles = profileNamesGroup.readEntry(QLatin1String("Invalid") + m_profileConfPrefix.value(Profile::Banking), QStringList()); // get profiles that was marked invalid during last update + QStringList invalidInvestProfiles = profileNamesGroup.readEntry(QLatin1String("Invalid") + m_profileConfPrefix.value(Profile::Investment), QStringList()); + QString bankPrefix = m_profileConfPrefix.value(Profile::Banking) + QLatin1Char('-'); + QString investPrefix = m_profileConfPrefix.value(Profile::Investment) + QLatin1Char('-'); // for kmm < 5.0.0 change 'BankNames' to 'ProfileNames' and remove 'MainWindow' group if (confVersion < 500 && bankProfiles.isEmpty()) { @@ -247,7 +246,7 @@ if (invalidBankProfiles.isEmpty() && invalidInvestProfiles.isEmpty()) // if there is no invalid profiles then this might be first update try firstTry = true; - int invalidProfileResponse = QMessageBox::No; + int invalidProfileResponse = QDialogButtonBox::No; for (auto profileName = bankProfiles.begin(); profileName != bankProfiles.end();) { KConfigGroup bankProfile(config, bankPrefix + *profileName); @@ -264,45 +263,46 @@ KConfigGroup newProfile; if (oldProfileType == QLatin1String("Invest")) { oldBankProfile.deleteEntry("BrokerageParam"); - oldBankProfile.writeEntry(m_colTypeConfName.value(ColumnType), oldBankProfile.readEntry("PayeeCol")); + oldBankProfile.writeEntry(m_colTypeConfName.value(Column::Type), oldBankProfile.readEntry("PayeeCol")); oldBankProfile.deleteEntry("PayeeCol"); oldBankProfile.deleteEntry("Filter"); oldBankProfile.deleteEntry("SecurityName"); lastUsedDirectory = oldBankProfile.readEntry("InvDirectory"); - newProfile = KConfigGroup(config, m_profileConfPrefix.value(ProfileInvest) + QLatin1Char('-') + *profileName); + newProfile = KConfigGroup(config, m_profileConfPrefix.value(Profile::Investment) + QLatin1Char('-') + *profileName); investProfiles.append(*profileName); profileName = bankProfiles.erase(profileName); } else if (oldProfileType == QLatin1String("Banking")) { lastUsedDirectory = oldBankProfile.readEntry("CsvDirectory"); - newProfile = KConfigGroup(config, m_profileConfPrefix.value(ProfileBank) + QLatin1Char('-') + *profileName); + newProfile = KConfigGroup(config, m_profileConfPrefix.value(Profile::Banking) + QLatin1Char('-') + *profileName); ++profileName; } else { - if (invalidProfileResponse != QMessageBox::YesToAll && invalidProfileResponse != QMessageBox::NoToAll) { + if (invalidProfileResponse != QDialogButtonBox::YesToAll && invalidProfileResponse != QDialogButtonBox::NoToAll) { if (!firstTry && !invalidBankProfiles.contains(*profileName)) { // if it isn't first update run and profile isn't on the list of invalid ones then don't bother ++profileName; continue; } - invalidProfileResponse = QMessageBox::warning(0, i18n("CSV import"), - i18n("
During update of %1
" - "the profile type for %2 could not be recognized.
" - "The profile cannot be used because of that.
" - "Do you want to delete it?
", - configFilePath, *profileName), - QMessageBox::Yes | QMessageBox::YesToAll | - QMessageBox::No | QMessageBox::NoToAll, QMessageBox::No ); + invalidProfileResponse = KMessageBox::createKMessageBox(nullptr, + new QDialogButtonBox(QDialogButtonBox::Yes | QDialogButtonBox::YesToAll | + QDialogButtonBox::No | QDialogButtonBox::NoToAll), + QMessageBox::Warning, + i18n("
During update of %1
" + "the profile type for %2 could not be recognized.
" + "The profile cannot be used because of that.
" + "Do you want to delete it?
", + configFilePath, *profileName), + QStringList(), QString(), nullptr, KMessageBox::Dangerous); } - switch (invalidProfileResponse) { - case QMessageBox::YesToAll: - case QMessageBox::Yes: + case QDialogButtonBox::YesToAll: + case QDialogButtonBox::Yes: oldBankProfile.deleteGroup(); invalidBankProfiles.removeOne(*profileName); profileName = bankProfiles.erase(profileName); break; - case QMessageBox::NoToAll: - case QMessageBox::No: + case QDialogButtonBox::NoToAll: + case QDialogButtonBox::No: if (!invalidBankProfiles.contains(*profileName)) // on user request: don't delete profile but keep eye on it invalidBankProfiles.append(*profileName); ret = false; @@ -334,8 +334,8 @@ ++profileName; } - profileNamesGroup.writeEntry(m_profileConfPrefix.value(ProfileBank), bankProfiles); // update profile names as some of them might have been changed - profileNamesGroup.writeEntry(m_profileConfPrefix.value(ProfileInvest), investProfiles); + profileNamesGroup.writeEntry(m_profileConfPrefix.value(Profile::Banking), bankProfiles); // update profile names as some of them might have been changed + profileNamesGroup.writeEntry(m_profileConfPrefix.value(Profile::Investment), investProfiles); if (invalidBankProfiles.isEmpty()) // if no invalid profiles then we don't need this variable anymore profileNamesGroup.deleteEntry("InvalidBank"); @@ -353,7 +353,7 @@ return ret; } -bool CSVImporter::profilesAction(const profileTypeE type, const profilesActionE action, const QString &name, const QString &newname) +bool CSVImporter::profilesAction(const Profile type, const ProfileAction action, const QString &name, const QString &newname) { bool ret = false; const KSharedConfigPtr config = configFile(); @@ -363,24 +363,24 @@ KConfigGroup profileName(config, profileTypeStr + QLatin1Char('-') + name); switch (action) { - case ProfilesUpdateLastUsed: + case ProfileAction::UpdateLastUsed: profileNamesGroup.writeEntry(m_confPriorName + profileTypeStr, profiles.indexOf(name)); break; - case ProfilesAdd: + case ProfileAction::Add: if (!profiles.contains(newname)) { profiles.append(newname); ret = true; } break; - case ProfilesRemove: + case ProfileAction::Remove: { profiles.removeOne(name); profileName.deleteGroup(); profileName.sync(); ret = true; break; } - case ProfilesRename: + case ProfileAction::Rename: { if (!newname.isEmpty() && name != newname) { int idx = profiles.indexOf(name); @@ -423,7 +423,6 @@ bool isOK = true; foreach (const auto column, columns) { m_file->m_parse->setDecimalSymbol(m_decimalSymbolIndexMap.value(column)); - m_file->m_parse->setThousandsSeparator(m_decimalSymbolIndexMap.value(column)); for (int row = m_profile->m_startLine; row <= m_profile->m_endLine; ++row) { QStandardItem *item = m_file->m_model->item(row, column); @@ -512,20 +511,18 @@ if (!profile) return false; if ((profile->m_feeRate.isEmpty() || // check whether feeRate... - profile->m_colTypeNum.value(ColumnAmount) == -1)) // ...and amount is in place + profile->m_colTypeNum.value(Column::Amount) == -1)) // ...and amount is in place return false; QString decimalSymbol; - if (profile->m_decimalSymbolIndex == 2 || - profile->m_decimalSymbolIndex == -1) { - int detectedSymbol = detectDecimalSymbol(profile->m_colTypeNum.value(ColumnAmount), QString()); - if (detectedSymbol == -1) + if (profile->m_decimalSymbol == DecimalSymbol::Auto) { + DecimalSymbol detectedSymbol = detectDecimalSymbol(profile->m_colTypeNum.value(Column::Amount), QString()); + if (detectedSymbol == DecimalSymbol::Auto) return false; m_file->m_parse->setDecimalSymbol(detectedSymbol); - m_file->m_parse->setThousandsSeparator(detectedSymbol); // separator list is in reverse so it's ok decimalSymbol = m_file->m_parse->decimalSymbol(detectedSymbol); } else - decimalSymbol = m_file->m_parse->decimalSymbol(profile->m_decimalSymbolIndex); + decimalSymbol = m_file->m_parse->decimalSymbol(profile->m_decimalSymbol); MyMoneyMoney feePercent(m_file->m_parse->possiblyReplaceSymbol(profile->m_feeRate)); // convert 0.67% ... @@ -543,7 +540,7 @@ for (int row = profile->m_startLine; row <= profile->m_endLine; ++row) { QString txt, numbers; bool ok = false; - numbers = txt = m_file->m_model->item(row, profile->m_colTypeNum.value(ColumnAmount))->text(); + numbers = txt = m_file->m_model->item(row, profile->m_colTypeNum.value(Column::Amount))->text(); numbers.remove(QRegularExpression(QStringLiteral("[,. ]"))).toInt(&ok); if (!ok) { // check if it's numerical string... items.append(new QStandardItem(QString())); @@ -566,7 +563,7 @@ for (int row = profile->m_endLine + 1; row < m_file->m_rowCount; ++row) // fill rows below with whitespace for nice effect with markUnwantedRows items.append(new QStandardItem(QString())); - int col = profile->m_colTypeNum.value(ColumnFee); + int col = profile->m_colTypeNum.value(Column::Fee); if (col == -1) { // fee column isn't present m_file->m_model->appendColumn(items); ++m_file->m_columnCount; @@ -577,13 +574,13 @@ m_file->m_model->removeColumn(m_file->m_columnCount - 1); m_file->m_model->appendColumn(items); } - profile->m_colTypeNum[ColumnFee] = m_file->m_columnCount - 1; + profile->m_colTypeNum[Column::Fee] = m_file->m_columnCount - 1; return true; } -int CSVImporter::detectDecimalSymbol(const int col, const QString &exclude) +DecimalSymbol CSVImporter::detectDecimalSymbol(const int col, const QString &exclude) { - int detectedSymbol = -1; + DecimalSymbol detectedSymbol = DecimalSymbol::Auto; QString pattern; QRegularExpression re("^[\\(+-]?\\d+[\\)]?$"); // matches '0' ; '+12' ; '-345' ; '(6789)' @@ -646,14 +643,14 @@ } if (dotIsDecimalSeparator) - detectedSymbol = 0; + detectedSymbol = DecimalSymbol::Dot; else if (commaIsDecimalSeparator) - detectedSymbol = 1; + detectedSymbol = DecimalSymbol::Comma; else { // whole column was empty, but we don't want to fail so take OS's decimal symbol if (QLocale().decimalPoint() == QLatin1Char('.')) - detectedSymbol = 0; + detectedSymbol = DecimalSymbol::Dot; else - detectedSymbol = 1; + detectedSymbol = DecimalSymbol::Comma; } return detectedSymbol; } @@ -687,11 +684,11 @@ } } QString filteredCurrencies = QStringList(currencySymbols.values()).join(""); - QString pattern = QString(QLatin1String("%1%2")).arg(QLocale().currencySymbol()).arg(filteredCurrencies); + QString pattern = QString::fromLatin1("%1%2").arg(QLocale().currencySymbol()).arg(filteredCurrencies); foreach (const auto column, columns) { - int detectedSymbol = detectDecimalSymbol(column, pattern); - if (detectedSymbol == -1) { + DecimalSymbol detectedSymbol = detectDecimalSymbol(column, pattern); + if (detectedSymbol == DecimalSymbol::Auto) { ret = column; return ret; } @@ -708,7 +705,7 @@ QList filteredTypes; QList filteredAccounts; QList::iterator account; - QRegularExpression filterOutChars = QRegularExpression(QStringLiteral("-., ")); + QRegularExpression filterOutChars(QStringLiteral("[-., ]")); foreach (const auto account, accountList) { if (accountTypes.contains(account.accountType()) && !(account).isClosed()) @@ -719,6 +716,8 @@ foreach (const auto account, filteredTypes) { QString txt = account.name(); txt.remove(filterOutChars); + if (txt.isEmpty() || txt.length() < 3) + continue; if (statementHeader.contains(txt, Qt::CaseInsensitive)) filteredAccounts.append(account); } @@ -744,6 +743,8 @@ foreach (const auto account, filteredTypes) { QString txt = account.number(); txt.remove(filterOutChars); + if (txt.isEmpty() || txt.length() < 3) + continue; if (statementHeader.contains(txt, Qt::CaseInsensitive)) filteredAccounts.append(account); } @@ -758,14 +759,14 @@ for (int col = 0; col < m_file->m_columnCount; ++col) statementHeader.append(m_file->m_model->item(row, col)->text()); - statementHeader.remove(QRegularExpression(QStringLiteral("-., "))); + statementHeader.remove(QRegularExpression(QStringLiteral("[-., ]"))); QList accounts; QList accountTypes; switch(m_profile->type()) { default: - case ProfileBank: + case Profile::Banking: accountTypes << MyMoneyAccount::Checkings << MyMoneyAccount::Savings << MyMoneyAccount::Liability << @@ -778,7 +779,7 @@ MyMoneyAccount::Liability; accounts = findAccounts(accountTypes, statementHeader); break; - case ProfileInvest: + case Profile::Investment: accountTypes << MyMoneyAccount::Investment; // take investment accounts... accounts = findAccounts(accountTypes, statementHeader); //...and search them in statement header break; @@ -817,22 +818,22 @@ QString txt; // process number field - if (profile->m_colTypeNum.value(ColumnNumber) != -1) + if (profile->m_colTypeNum.value(Column::Number) != -1) tr.m_strNumber = txt; // process date field - int col = profile->m_colTypeNum.value(ColumnDate); + int col = profile->m_colTypeNum.value(Column::Date); tr.m_datePosted = processDateField(row, col); if (tr.m_datePosted == QDate()) return false; // process payee field - col = profile->m_colTypeNum.value(ColumnPayee); + col = profile->m_colTypeNum.value(Column::Payee); if (col != -1) tr.m_strPayee = m_file->m_model->item(row, col)->text(); // process memo field - col = profile->m_colTypeNum.value(ColumnMemo); + col = profile->m_colTypeNum.value(Column::Memo); if (col != -1) memo.append(m_file->m_model->item(row, col)->text()); @@ -847,16 +848,16 @@ tr.m_strMemo = memo; // process amount field - col = profile->m_colTypeNum.value(ColumnAmount); + col = profile->m_colTypeNum.value(Column::Amount); tr.m_amount = processAmountField(profile, row, col); if (col != -1 && profile->m_oppositeSigns) // change signs to opposite if requested by user tr.m_amount *= MyMoneyMoney(-1); // process credit/debit field - if (profile->m_colTypeNum.value(ColumnCredit) != -1 && - profile->m_colTypeNum.value(ColumnDebit) != -1) { - QString credit = m_file->m_model->item(row, profile->m_colTypeNum.value(ColumnCredit))->text(); - QString debit = m_file->m_model->item(row, profile->m_colTypeNum.value(ColumnDebit))->text(); + if (profile->m_colTypeNum.value(Column::Credit) != -1 && + profile->m_colTypeNum.value(Column::Debit) != -1) { + QString credit = m_file->m_model->item(row, profile->m_colTypeNum.value(Column::Credit))->text(); + QString debit = m_file->m_model->item(row, profile->m_colTypeNum.value(Column::Debit))->text(); tr.m_amount = processCreditDebit(credit, debit); if (!credit.isEmpty() && !debit.isEmpty()) return false; @@ -867,13 +868,13 @@ s1.m_strMemo = tr.m_strMemo; MyMoneyStatement::Split s2 = s1; s2.m_reconcile = tr.m_reconcile; - s2.m_amount = (-s1.m_amount); + s2.m_amount = -s1.m_amount; // process category field - col = profile->m_colTypeNum.value(ColumnCategory); + col = profile->m_colTypeNum.value(Column::Category); if (col != -1) { txt = m_file->m_model->item(row, col)->text(); - QString accountId = m_file->m_csvUtil->checkCategory(txt, s1.m_amount, s2.m_amount); + QString accountId = MyMoneyFile::instance()->checkCategory(txt, s1.m_amount, s2.m_amount); if (!accountId.isEmpty()) { s2.m_accountId = accountId; @@ -886,12 +887,12 @@ txt.clear(); for (int i = 0; i < m_file->m_columnCount; ++i) txt.append(m_file->m_model->item(row, i)->text()); - QString hashBase = QString(QLatin1String("%1-%2")) + QString hashBase = QString::fromLatin1("%1-%2") .arg(tr.m_datePosted.toString(Qt::ISODate)) .arg(MyMoneyTransaction::hash(txt)); QString hash; for (uchar idx = 0; idx < 0xFF; ++idx) { // assuming threre will be no more than 256 transactions with the same hashBase - hash = QString(QLatin1String("%1-%2")).arg(hashBase).arg(idx); + hash = QString::fromLatin1("%1-%2").arg(hashBase).arg(idx); QSet::const_iterator it = m_hashSet.constFind(hash); if (it == m_hashSet.constEnd()) break; @@ -910,37 +911,36 @@ QString memo; QString txt; // process date field - int col = profile->m_colTypeNum.value(ColumnDate); + int col = profile->m_colTypeNum.value(Column::Date); tr.m_datePosted = processDateField(row, col); if (tr.m_datePosted == QDate()) return false; // process quantity field - col = profile->m_colTypeNum.value(ColumnQuantity); + col = profile->m_colTypeNum.value(Column::Quantity); tr.m_shares = processQuantityField(profile, row, col); // process price field - col = profile->m_colTypeNum.value(ColumnPrice); + col = profile->m_colTypeNum.value(Column::Price); tr.m_price = processPriceField(profile, row, col); // process amount field - col = profile->m_colTypeNum.value(ColumnAmount); + col = profile->m_colTypeNum.value(Column::Amount); tr.m_amount = processAmountField(profile, row, col); // process type field - col = profile->m_colTypeNum.value(ColumnType); + col = profile->m_colTypeNum.value(Column::Type); tr.m_eAction = processActionTypeField(profile, row, col); if (!m_isActionTypeValidated && col != -1 && // if action type wasn't validated in wizard then... validateActionType(tr) != ValidActionType) // ...check if price, amount, quantity is appropriate return false; // process fee field - col = profile->m_colTypeNum.value(ColumnFee); + col = profile->m_colTypeNum.value(Column::Fee); if (col != -1) { - if (profile->m_decimalSymbolIndex == 2) { - int decimalSymbolIndex = m_decimalSymbolIndexMap.value(col); - m_file->m_parse->setDecimalSymbol(decimalSymbolIndex); - m_file->m_parse->setThousandsSeparator(decimalSymbolIndex); + if (profile->m_decimalSymbol == DecimalSymbol::Auto) { + DecimalSymbol decimalSymbol = m_decimalSymbolIndexMap.value(col); + m_file->m_parse->setDecimalSymbol(decimalSymbol); } txt = m_file->m_model->item(row, col)->text(); @@ -959,10 +959,10 @@ } // process symbol and name field - col = profile->m_colTypeNum.value(ColumnSymbol); + col = profile->m_colTypeNum.value(Column::Symbol); if (col != -1) tr.m_strSymbol = m_file->m_model->item(row, col)->text(); - col = profile->m_colTypeNum.value(ColumnName); + col = profile->m_colTypeNum.value(Column::Name); if (col != -1 && tr.m_strSymbol.isEmpty()) { // case in which symbol field is empty txt = m_file->m_model->item(row, col)->text(); @@ -974,7 +974,7 @@ tr.m_strSecurity = m_mapSymbolName.value(tr.m_strSymbol); // take name from prepared names to avoid potential name mismatch // process memo field - col = profile->m_colTypeNum.value(ColumnMemo); + col = profile->m_colTypeNum.value(Column::Memo); if (col != -1) memo.append(m_file->m_model->item(row, col)->text()); @@ -995,8 +995,8 @@ s1.m_amount = tr.m_amount; s1.m_strMemo = tr.m_strMemo; MyMoneyStatement::Split s2 = s1; - s2.m_amount = MyMoneyMoney(-s1.m_amount); - s2.m_accountId = m_file->m_csvUtil->checkCategory(tr.m_strInterestCategory, s1.m_amount, s2.m_amount); + s2.m_amount = -s1.m_amount; + s2.m_accountId = MyMoneyFile::instance()->checkCategory(tr.m_strInterestCategory, s1.m_amount, s2.m_amount); // deduct fees from amount if (tr.m_eAction == MyMoneyStatement::Transaction::eaCashDividend || @@ -1020,23 +1020,23 @@ MyMoneyStatement::Price pr; // process date field - int col = profile->m_colTypeNum.value(ColumnDate); + int col = profile->m_colTypeNum.value(Column::Date); pr.m_date = processDateField(row, col); if (pr.m_date == QDate()) return false; // process price field - col = profile->m_colTypeNum.value(ColumnPrice); + col = profile->m_colTypeNum.value(Column::Price); pr.m_amount = processPriceField(profile, row, col); switch (profile->type()) { - case ProfileCurrencyPrices: + case Profile::CurrencyPrices: if (profile->m_securitySymbol.isEmpty() || profile->m_currencySymbol.isEmpty()) return false; pr.m_strSecurity = profile->m_securitySymbol; pr.m_strCurrency = profile->m_currencySymbol; break; - case ProfileStockPrices: + case Profile::StockPrices: if (profile->m_securityName.isEmpty()) return false; pr.m_strSecurity = profile->m_securityName; @@ -1063,8 +1063,8 @@ MyMoneyMoney CSVImporter::processCreditDebit(QString &credit, QString &debit) { MyMoneyMoney amount; - if (m_profile->m_decimalSymbolIndex == 2) - setupFieldDecimalSymbol(m_profile->m_colTypeNum.value(ColumnCredit)); + if (m_profile->m_decimalSymbol == DecimalSymbol::Auto) + setupFieldDecimalSymbol(m_profile->m_colTypeNum.value(Column::Credit)); if (credit.startsWith(QLatin1Char('('))) { // check if brackets notation is used for negative numbers credit.remove(QRegularExpression(QStringLiteral("[()]"))); @@ -1103,7 +1103,7 @@ { MyMoneyMoney shares; if (col != -1) { - if (profile->m_decimalSymbolIndex == 2) + if (profile->m_decimalSymbol == DecimalSymbol::Auto) setupFieldDecimalSymbol(col); QString txt = m_file->m_model->item(row, col)->text(); @@ -1119,7 +1119,7 @@ { MyMoneyMoney amount; if (col != -1) { - if (profile->m_decimalSymbolIndex == 2) + if (profile->m_decimalSymbol == DecimalSymbol::Auto) setupFieldDecimalSymbol(col); QString txt = m_file->m_model->item(row, col)->text(); @@ -1138,7 +1138,7 @@ { MyMoneyMoney price; if (col != -1) { - if (profile->m_decimalSymbolIndex == 2) + if (profile->m_decimalSymbol == DecimalSymbol::Auto) setupFieldDecimalSymbol(col); QString txt = m_file->m_model->item(row, col)->text(); @@ -1154,7 +1154,7 @@ { MyMoneyMoney price; if (col != -1) { - if (profile->m_decimalSymbolIndex == 2) + if (profile->m_decimalSymbol == DecimalSymbol::Auto) setupFieldDecimalSymbol(col); QString txt = m_file->m_model->item(row, col)->text(); @@ -1193,8 +1193,8 @@ bool CSVImporter::sortSecurities(QSet& onlySymbols, QSet& onlyNames, QMap& mapSymbolName) { QList securityList = MyMoneyFile::instance()->securityList(); - int symbolCol = m_profile->m_colTypeNum.value(ColumnSymbol); - int nameCol = m_profile->m_colTypeNum.value(ColumnName); + int symbolCol = m_profile->m_colTypeNum.value(Column::Symbol); + int nameCol = m_profile->m_colTypeNum.value(Column::Name); // sort by availability of symbol and name for (int row = m_profile->m_startLine; row <= m_profile->m_endLine; ++row) { @@ -1256,33 +1256,31 @@ } void CSVImporter::setupFieldDecimalSymbol(int col) { - int decimalSymbolIndex = m_decimalSymbolIndexMap.value(col); - m_file->m_parse->setDecimalSymbol(decimalSymbolIndex); - m_file->m_parse->setThousandsSeparator(decimalSymbolIndex); + m_file->m_parse->setDecimalSymbol(m_decimalSymbolIndexMap.value(col)); } QList CSVImporter::getNumericalColumns() { QList columns; switch(m_profile->type()) { - case ProfileBank: - if (m_profile->m_colTypeNum.value(ColumnAmount) != -1) { - columns << m_profile->m_colTypeNum.value(ColumnAmount); + case Profile::Banking: + if (m_profile->m_colTypeNum.value(Column::Amount) != -1) { + columns << m_profile->m_colTypeNum.value(Column::Amount); } else { - columns << m_profile->m_colTypeNum.value(ColumnDebit); - columns << m_profile->m_colTypeNum.value(ColumnCredit); + columns << m_profile->m_colTypeNum.value(Column::Debit); + columns << m_profile->m_colTypeNum.value(Column::Credit); } break; - case ProfileInvest: - columns << m_profile->m_colTypeNum.value(ColumnAmount); - columns << m_profile->m_colTypeNum.value(ColumnPrice); - columns << m_profile->m_colTypeNum.value(ColumnQuantity); - if (m_profile->m_colTypeNum.value(ColumnFee) != -1) - columns << m_profile->m_colTypeNum.value(ColumnFee); + case Profile::Investment: + columns << m_profile->m_colTypeNum.value(Column::Amount); + columns << m_profile->m_colTypeNum.value(Column::Price); + columns << m_profile->m_colTypeNum.value(Column::Quantity); + if (m_profile->m_colTypeNum.value(Column::Fee) != -1) + columns << m_profile->m_colTypeNum.value(Column::Fee); break; - case ProfileCurrencyPrices: - case ProfileStockPrices: - columns << m_profile->m_colTypeNum.value(ColumnPrice); + case Profile::CurrencyPrices: + case Profile::StockPrices: + columns << m_profile->m_colTypeNum.value(Column::Price); break; default: break; @@ -1293,7 +1291,7 @@ bool CSVImporter::createStatement(MyMoneyStatement &st) { switch (m_profile->type()) { - case ProfileBank: + case Profile::Banking: { if (!st.m_listTransactions.isEmpty()) // don't create statement if there is one return true; @@ -1311,17 +1309,17 @@ return true; break; } - case ProfileInvest: + case Profile::Investment: { if (!st.m_listTransactions.isEmpty()) // don't create statement if there is one return true; st.m_eType = MyMoneyStatement::etInvestment; if (m_autodetect.value(AutoAccountInvest)) detectAccount(st); InvestmentProfile *profile = dynamic_cast(m_profile); - if ((m_profile->m_colTypeNum.value(ColumnFee) == -1 || - m_profile->m_colTypeNum.value(ColumnFee) >= m_file->m_columnCount) && + if ((m_profile->m_colTypeNum.value(Column::Fee) == -1 || + m_profile->m_colTypeNum.value(Column::Fee) >= m_file->m_columnCount) && !profile->m_feeRate.isEmpty()) // fee column has not been calculated so do it now calculateFee(); @@ -1341,8 +1339,8 @@ break; } default: - case ProfileCurrencyPrices: - case ProfileStockPrices: + case Profile::CurrencyPrices: + case Profile::StockPrices: { if (!st.m_listPrices.isEmpty()) // don't create statement if there is one return true; @@ -1374,10 +1372,10 @@ m_trailerLines = profilesGroup.readEntry(CSVImporter::m_miscSettingsConfName.value(ConfTrailerLines), 0); m_encodingMIBEnum = profilesGroup.readEntry(CSVImporter::m_miscSettingsConfName.value(ConfEncoding), 106 /* UTF-8 */); - m_dateFormatIndex = profilesGroup.readEntry(CSVImporter::m_miscSettingsConfName.value(ConfDateFormat), 0); - m_textDelimiterIndex = profilesGroup.readEntry(CSVImporter::m_miscSettingsConfName.value(ConfTextDeimiter), 0); - m_fieldDelimiterIndex = profilesGroup.readEntry(CSVImporter::m_miscSettingsConfName.value(ConfFieldDelimiter), -1); - m_decimalSymbolIndex = profilesGroup.readEntry(CSVImporter::m_miscSettingsConfName.value(ConfDecimalSymbol), 2); + m_dateFormat = static_cast(profilesGroup.readEntry(CSVImporter::m_miscSettingsConfName.value(ConfDateFormat), (int)DateFormat::YearMonthDay)); + m_textDelimiter = static_cast(profilesGroup.readEntry(CSVImporter::m_miscSettingsConfName.value(ConfTextDelimiter), (int)TextDelimiter::DoubleQuote)); + m_fieldDelimiter = static_cast(profilesGroup.readEntry(CSVImporter::m_miscSettingsConfName.value(ConfFieldDelimiter), (int)FieldDelimiter::Auto)); + m_decimalSymbol = static_cast(profilesGroup.readEntry(CSVImporter::m_miscSettingsConfName.value(ConfDecimalSymbol), (int)DecimalSymbol::Auto)); initColNumType(); } @@ -1391,10 +1389,10 @@ } profilesGroup.writeEntry(CSVImporter::m_miscSettingsConfName.value(ConfDirectory), m_lastUsedDirectory); profilesGroup.writeEntry(CSVImporter::m_miscSettingsConfName.value(ConfEncoding), m_encodingMIBEnum); - profilesGroup.writeEntry(CSVImporter::m_miscSettingsConfName.value(ConfDateFormat), m_dateFormatIndex); - profilesGroup.writeEntry(CSVImporter::m_miscSettingsConfName.value(ConfFieldDelimiter), m_fieldDelimiterIndex); - profilesGroup.writeEntry(CSVImporter::m_miscSettingsConfName.value(ConfTextDeimiter), m_textDelimiterIndex); - profilesGroup.writeEntry(CSVImporter::m_miscSettingsConfName.value(ConfDecimalSymbol), m_decimalSymbolIndex); + profilesGroup.writeEntry(CSVImporter::m_miscSettingsConfName.value(ConfDateFormat), (int)m_dateFormat); + profilesGroup.writeEntry(CSVImporter::m_miscSettingsConfName.value(ConfFieldDelimiter), (int)m_fieldDelimiter); + profilesGroup.writeEntry(CSVImporter::m_miscSettingsConfName.value(ConfTextDelimiter), (int)m_textDelimiter); + profilesGroup.writeEntry(CSVImporter::m_miscSettingsConfName.value(ConfDecimalSymbol), (int)m_decimalSymbol); profilesGroup.writeEntry(CSVImporter::m_miscSettingsConfName.value(ConfStartLine), m_startLine); profilesGroup.writeEntry(CSVImporter::m_miscSettingsConfName.value(ConfTrailerLines), m_trailerLines); } @@ -1406,16 +1404,16 @@ if (!profilesGroup.exists()) exists = false; - m_colTypeNum[ColumnPayee] = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(ColumnPayee), -1); - m_colTypeNum[ColumnNumber] = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(ColumnNumber), -1); - m_colTypeNum[ColumnAmount] = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(ColumnAmount), -1); - m_colTypeNum[ColumnDebit] = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(ColumnDebit), -1); - m_colTypeNum[ColumnCredit] = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(ColumnCredit), -1); - m_colTypeNum[ColumnDate] = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(ColumnDate), -1); - m_colTypeNum[ColumnCategory] = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(ColumnCategory), -1); - m_colTypeNum[ColumnMemo] = -1; // initialize, otherwise random data may go here + m_colTypeNum[Column::Payee] = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(Column::Payee), -1); + m_colTypeNum[Column::Number] = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(Column::Number), -1); + m_colTypeNum[Column::Amount] = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(Column::Amount), -1); + m_colTypeNum[Column::Debit] = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(Column::Debit), -1); + m_colTypeNum[Column::Credit] = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(Column::Credit), -1); + m_colTypeNum[Column::Date] = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(Column::Date), -1); + m_colTypeNum[Column::Category] = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(Column::Category), -1); + m_colTypeNum[Column::Memo] = -1; // initialize, otherwise random data may go here m_oppositeSigns = profilesGroup.readEntry(CSVImporter::m_miscSettingsConfName.value(ConfOppositeSigns), 0); - m_memoColList = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(ColumnMemo), QList()); + m_memoColList = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(Column::Memo), QList()); CSVProfile::readSettings(profilesGroup); return exists; @@ -1427,21 +1425,21 @@ CSVProfile::writeSettings(profilesGroup); profilesGroup.writeEntry(CSVImporter::m_miscSettingsConfName.value(ConfOppositeSigns), m_oppositeSigns); - profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(ColumnPayee), - m_colTypeNum.value(ColumnPayee)); - profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(ColumnNumber), - m_colTypeNum.value(ColumnNumber)); - profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(ColumnAmount), - m_colTypeNum.value(ColumnAmount)); - profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(ColumnDebit), - m_colTypeNum.value(ColumnDebit)); - profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(ColumnCredit), - m_colTypeNum.value(ColumnCredit)); - profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(ColumnDate), - m_colTypeNum.value(ColumnDate)); - profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(ColumnCategory), - m_colTypeNum.value(ColumnCategory)); - profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(ColumnMemo), + profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(Column::Payee), + m_colTypeNum.value(Column::Payee)); + profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(Column::Number), + m_colTypeNum.value(Column::Number)); + profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(Column::Amount), + m_colTypeNum.value(Column::Amount)); + profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(Column::Debit), + m_colTypeNum.value(Column::Debit)); + profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(Column::Credit), + m_colTypeNum.value(Column::Credit)); + profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(Column::Date), + m_colTypeNum.value(Column::Date)); + profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(Column::Category), + m_colTypeNum.value(Column::Category)); + profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(Column::Memo), m_memoColList); profilesGroup.config()->sync(); } @@ -1468,20 +1466,20 @@ m_transactionNames[MyMoneyStatement::Transaction::eaShrsout] = profilesGroup.readEntry(CSVImporter::m_transactionConfName.value(MyMoneyStatement::Transaction::eaShrsout), QString(i18nc("Type of operation as in financial statement", "remove")).split(',', QString::SkipEmptyParts)); - m_colTypeNum[ColumnDate] = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(ColumnDate), -1); - m_colTypeNum[ColumnType] = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(ColumnType), -1); //use for type col. - m_colTypeNum[ColumnPrice] = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(ColumnPrice), -1); - m_colTypeNum[ColumnQuantity] = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(ColumnQuantity), -1); - m_colTypeNum[ColumnAmount] = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(ColumnAmount), -1); - m_colTypeNum[ColumnName] = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(ColumnName), -1); - m_colTypeNum[ColumnFee] = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(ColumnFee), -1); - m_colTypeNum[ColumnSymbol] = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(ColumnSymbol), -1); - m_colTypeNum[ColumnMemo] = -1; // initialize, otherwise random data may go here + m_colTypeNum[Column::Date] = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(Column::Date), -1); + m_colTypeNum[Column::Type] = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(Column::Type), -1); //use for type col. + m_colTypeNum[Column::Price] = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(Column::Price), -1); + m_colTypeNum[Column::Quantity] = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(Column::Quantity), -1); + m_colTypeNum[Column::Amount] = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(Column::Amount), -1); + m_colTypeNum[Column::Name] = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(Column::Name), -1); + m_colTypeNum[Column::Fee] = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(Column::Fee), -1); + m_colTypeNum[Column::Symbol] = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(Column::Symbol), -1); + m_colTypeNum[Column::Memo] = -1; // initialize, otherwise random data may go here m_feeIsPercentage = profilesGroup.readEntry(CSVImporter::m_miscSettingsConfName.value(ConfFeeIsPercentage), 0); m_feeRate = profilesGroup.readEntry(CSVImporter::m_miscSettingsConfName.value(ConfFeeRate), QString()); m_minFee = profilesGroup.readEntry(CSVImporter::m_miscSettingsConfName.value(ConfMinFee), QString()); - m_memoColList = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(ColumnMemo), QList()); + m_memoColList = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(Column::Memo), QList()); m_securityName = profilesGroup.readEntry(CSVImporter::m_miscSettingsConfName.value(ConfSecurityName), QString()); m_securitySymbol = profilesGroup.readEntry(CSVImporter::m_miscSettingsConfName.value(ConfSecuritySymbol), QString()); m_dontAsk = profilesGroup.readEntry(CSVImporter::m_miscSettingsConfName.value(ConfDontAsk), 0); @@ -1519,23 +1517,23 @@ profilesGroup.writeEntry(CSVImporter::m_miscSettingsConfName.value(ConfSecuritySymbol), m_securitySymbol); profilesGroup.writeEntry(CSVImporter::m_miscSettingsConfName.value(ConfDontAsk), m_dontAsk); - profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(ColumnDate), - m_colTypeNum.value(ColumnDate)); - profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(ColumnType), - m_colTypeNum.value(ColumnType)); - profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(ColumnQuantity), - m_colTypeNum.value(ColumnQuantity)); - profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(ColumnAmount), - m_colTypeNum.value(ColumnAmount)); - profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(ColumnPrice), - m_colTypeNum.value(ColumnPrice)); - profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(ColumnSymbol), - m_colTypeNum.value(ColumnSymbol)); - profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(ColumnName), - m_colTypeNum.value(ColumnName)); - profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(ColumnFee), - m_colTypeNum.value(ColumnFee)); - profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(ColumnMemo), + profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(Column::Date), + m_colTypeNum.value(Column::Date)); + profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(Column::Type), + m_colTypeNum.value(Column::Type)); + profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(Column::Quantity), + m_colTypeNum.value(Column::Quantity)); + profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(Column::Amount), + m_colTypeNum.value(Column::Amount)); + profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(Column::Price), + m_colTypeNum.value(Column::Price)); + profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(Column::Symbol), + m_colTypeNum.value(Column::Symbol)); + profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(Column::Name), + m_colTypeNum.value(Column::Name)); + profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(Column::Fee), + m_colTypeNum.value(Column::Fee)); + profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(Column::Memo), m_memoColList); profilesGroup.config()->sync(); } @@ -1547,8 +1545,8 @@ if (!profilesGroup.exists()) exists = false; - m_colTypeNum[ColumnDate] = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(ColumnDate), -1); - m_colTypeNum[ColumnPrice] = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(ColumnPrice), -1); + m_colTypeNum[Column::Date] = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(Column::Date), -1); + m_colTypeNum[Column::Price] = profilesGroup.readEntry(CSVImporter::m_colTypeConfName.value(Column::Price), -1); m_priceFraction = profilesGroup.readEntry(CSVImporter::m_miscSettingsConfName.value(ConfPriceFraction), 2); m_securityName = profilesGroup.readEntry(CSVImporter::m_miscSettingsConfName.value(ConfSecurityName), QString()); m_securitySymbol = profilesGroup.readEntry(CSVImporter::m_miscSettingsConfName.value(ConfSecuritySymbol), QString()); @@ -1564,10 +1562,10 @@ KConfigGroup profilesGroup(config, CSVImporter::m_profileConfPrefix.value(type()) + QLatin1Char('-') + m_profileName); CSVProfile::writeSettings(profilesGroup); - profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(ColumnDate), - m_colTypeNum.value(ColumnDate)); - profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(ColumnPrice), - m_colTypeNum.value(ColumnPrice)); + profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(Column::Date), + m_colTypeNum.value(Column::Date)); + profilesGroup.writeEntry(CSVImporter::m_colTypeConfName.value(Column::Price), + m_colTypeNum.value(Column::Price)); profilesGroup.writeEntry(CSVImporter::m_miscSettingsConfName.value(ConfPriceFraction), m_priceFraction); profilesGroup.writeEntry(CSVImporter::m_miscSettingsConfName.value(ConfSecurityName), m_securityName); profilesGroup.writeEntry(CSVImporter::m_miscSettingsConfName.value(ConfSecuritySymbol), m_securitySymbol); @@ -1579,14 +1577,12 @@ CSVFile::CSVFile() { m_parse = new Parse; - m_csvUtil = new CsvUtil; - m_model = new QStandardItemModel(); + m_model = new QStandardItemModel; } CSVFile::~CSVFile() { delete m_parse; - delete m_csvUtil; delete m_model; } @@ -1596,46 +1592,46 @@ if (profile->m_endLine > profile->m_trailerLines) profile->m_endLine -= profile->m_trailerLines; - if (profile->m_startLine > m_rowCount - 1) // Don't allow m_startLine > m_endLine - profile->m_startLine = m_rowCount - 1; + if (profile->m_startLine > profile->m_endLine) // Don't allow m_startLine > m_endLine + profile->m_startLine = profile->m_endLine; } void CSVFile::getColumnCount(CSVProfile *profile, const QStringList &rows) { if (rows.isEmpty()) return; - QList delimiterIndexes; - if (profile->m_fieldDelimiterIndex == -1) - delimiterIndexes = QList{0, 1, 2, 3}; // include all delimiters to test or ... + QVector delimiterIndexes; + if (profile->m_fieldDelimiter == FieldDelimiter::Auto) + delimiterIndexes = QVector{FieldDelimiter::Comma, FieldDelimiter::Semicolon, FieldDelimiter::Colon, FieldDelimiter::Tab}; // include all delimiters to test or ... else - delimiterIndexes = QList{profile->m_fieldDelimiterIndex}; // ... only the one specified + delimiterIndexes = QVector{profile->m_fieldDelimiter}; // ... only the one specified QList totalDelimiterCount({0, 0, 0, 0}); // Total in file for each delimiter QList thisDelimiterCount({0, 0, 0, 0}); // Total in this line for each delimiter int colCount = 0; // Total delimiters in this line - int possibleDelimiter = 0; + FieldDelimiter possibleDelimiter = FieldDelimiter::Comma; m_columnCount = 0; foreach (const auto row, rows) { foreach(const auto delimiterIndex, delimiterIndexes) { - m_parse->setFieldDelimiterIndex(delimiterIndex); + m_parse->setFieldDelimiter(delimiterIndex); colCount = m_parse->parseLine(row).count(); // parse each line using each delimiter - if (colCount > thisDelimiterCount.at(delimiterIndex)) - thisDelimiterCount[delimiterIndex] = colCount; + if (colCount > thisDelimiterCount.at((int)delimiterIndex)) + thisDelimiterCount[(int)delimiterIndex] = colCount; - if (thisDelimiterCount[delimiterIndex] > m_columnCount) - m_columnCount = thisDelimiterCount.at(delimiterIndex); + if (thisDelimiterCount[(int)delimiterIndex] > m_columnCount) + m_columnCount = thisDelimiterCount.at((int)delimiterIndex); - totalDelimiterCount[delimiterIndex] += colCount; - if (totalDelimiterCount.at(delimiterIndex) > totalDelimiterCount.at(possibleDelimiter)) + totalDelimiterCount[(int)delimiterIndex] += colCount; + if (totalDelimiterCount.at((int)delimiterIndex) > totalDelimiterCount.at((int)possibleDelimiter)) possibleDelimiter = delimiterIndex; } } - if (delimiterIndexes.count() != 1) // if purpose was to autodetect... - profile->m_fieldDelimiterIndex = possibleDelimiter; // ... then change field delimiter - m_parse->setFieldDelimiterIndex(profile->m_fieldDelimiterIndex); // restore original field delimiter + if (delimiterIndexes.count() != 1) // if purpose was to autodetect... + profile->m_fieldDelimiter = possibleDelimiter; // ... then change field delimiter + m_parse->setFieldDelimiter(profile->m_fieldDelimiter); // restore original field delimiter } bool CSVFile::getInFileName(QString inFileName) @@ -1683,12 +1679,10 @@ void CSVFile::setupParser(CSVProfile *profile) { - if (profile->m_decimalSymbolIndex != 2) { - m_parse->setDecimalSymbol(profile->m_decimalSymbolIndex); - m_parse->setThousandsSeparator(profile->m_decimalSymbolIndex); - } - m_parse->setFieldDelimiterCharacter(profile->m_fieldDelimiterIndex); - m_parse->setTextDelimiterCharacter(profile->m_textDelimiterIndex); + if (profile->m_decimalSymbol != DecimalSymbol::Auto) + m_parse->setDecimalSymbol(profile->m_decimalSymbol); + m_parse->setFieldDelimiter(profile->m_fieldDelimiter); + m_parse->setTextDelimiter(profile->m_textDelimiter); } void CSVFile::readFile(CSVProfile *profile) @@ -1703,8 +1697,8 @@ QString buf = inStream.readAll(); inFile.close(); - m_parse->setTextDelimiterCharacter(profile->m_textDelimiterIndex); - QStringList rows = m_parse->parseFile(buf, 1, 0); // parse the buffer + m_parse->setTextDelimiter(profile->m_textDelimiter); + QStringList rows = m_parse->parseFile(buf); // parse the buffer m_rowCount = m_parse->lastLine(); // won't work without above line getColumnCount(profile, rows); getStartEndRow(profile); diff --git a/kmymoney/plugins/csvimport/csvimporterplugin.h b/kmymoney/plugins/csvimport/csvimporterplugin.h --- a/kmymoney/plugins/csvimport/csvimporterplugin.h +++ b/kmymoney/plugins/csvimport/csvimporterplugin.h @@ -28,9 +28,7 @@ // Project Includes -#include "csvimporter.h" #include "kmymoneyplugin.h" -#include "csvwizard.h" class CSVImporter; class CSVWizard; diff --git a/kmymoney/plugins/csvimport/csvimporterplugin.cpp b/kmymoney/plugins/csvimport/csvimporterplugin.cpp --- a/kmymoney/plugins/csvimport/csvimporterplugin.cpp +++ b/kmymoney/plugins/csvimport/csvimporterplugin.cpp @@ -23,24 +23,16 @@ // ---------------------------------------------------------------------------- // QT Includes -#include -#include -#include -#include -#include - // ---------------------------------------------------------------------------- // KDE Includes #include -#include // ---------------------------------------------------------------------------- // Project Includes -#include "mymoneystatementreader.h" -#include "mymoneystatement.h" -#include "mymoneyfile.h" +#include "csvimporter.h" +#include "csvwizard.h" CsvImporterPlugin::CsvImporterPlugin() : KMyMoneyPlugin::Plugin(nullptr, "csvimport"/*must be the same as X-KDE-PluginInfo-Name*/) @@ -69,7 +61,7 @@ m_importer = new CSVImporter; m_wizard = new CSVWizard(this, m_importer); m_silent = false; - connect(m_importer, SIGNAL(statementReady(MyMoneyStatement&)), this, SLOT(slotGetStatement(MyMoneyStatement&))); + connect(m_wizard, SIGNAL(statementReady(MyMoneyStatement&)), this, SLOT(slotGetStatement(MyMoneyStatement&))); m_action->setEnabled(false);// don't allow further plugins to start while this is open } diff --git a/kmymoney/plugins/csvimport/csvutil.h b/kmymoney/plugins/csvimport/csvutil.h --- a/kmymoney/plugins/csvimport/csvutil.h +++ b/kmymoney/plugins/csvimport/csvutil.h @@ -4,6 +4,8 @@ begin : Sat Jan 01 2010 copyright : (C) 2010 by Allan Anderson email : agander93@gmail.com +copyright : (C) 2017 by Łukasz Wojniłowicz +email : lukasz.wojnilowicz@gmail.com ***************************************************************************/ /************************************************************************** @@ -18,22 +20,13 @@ #ifndef CSVUTIL_H #define CSVUTIL_H -#include -#include -#include -#include -#include +#include +#include "csvenums.h" -#include "investtransactioneditor.h" +#include "csvimport/kmm_csvimport_core_export.h" -class MyMoneyAccount; -class InvestTransactionEditor; -class TransactionEditor; - -class Parse: public QObject +class KMM_CSVIMPORT_CORE_EXPORT Parse { - Q_OBJECT - public: Parse(); ~Parse(); @@ -45,93 +38,44 @@ * more 'thousand separators' which happen to be the same as the field * delimiter, and re-assembles the string. */ - QStringList parseLine(const QString& data); - QStringList parseFile(const QString& buf, int strt, int end); - QStringList m_fieldDelimiterCharList; + QStringList parseLine(const QString &data); + QStringList parseFile(const QString &buf); - QString fieldDelimiterCharacter(int index); - QString decimalSymbol(int index); - int decimalSymbolIndex(); - QString textDelimiterCharacter(int index); - void thousandsSeparatorChanged(int index); - QString thousandsSeparator(); + QChar decimalSymbol(const DecimalSymbol _d); /** * Check for presence of the selected decimal symbol * and evaluate if the proposed conversion is valid. * If so, change the symbol. */ QString possiblyReplaceSymbol(const QString& str); - void setFieldDelimiterIndex(int index); - void setFieldDelimiterCharacter(int index); - - void setTextDelimiterIndex(int index); - void setTextDelimiterCharacter(int index); + void setFieldDelimiter(const FieldDelimiter _d); - void setDecimalSymbolIndex(int index); - void setDecimalSymbol(int index); + void setTextDelimiter(const TextDelimiter _d); - void setThousandsSeparatorIndex(int index); - void setThousandsSeparator(int index); - - bool symbolFound(); - void setSymbolFound(bool found); + void setDecimalSymbol(const DecimalSymbol _d); bool invalidConversion(); int lastLine(); -public slots: - - void decimalSymbolSelected(int index); - private : - QStringList m_decimalSymbolList; - QStringList m_textDelimiterCharList; - QStringList m_thousandsSeparatorList; + QVector m_fieldDelimiters; + QVector m_textDelimiters; + QVector m_decimalSymbols; + QVector m_thousandsSeparators; - QString m_decimalSymbol; - QString m_fieldDelimiterCharacter; - QString m_textDelimiterCharacter; - QString m_thousandsSeparator; + QChar m_fieldDelimiter; + QChar m_textDelimiter; + QChar m_decimalSymbol; + QChar m_thousandsSeparator; - int m_decimalSymbolIndex; - int m_fieldDelimiterIndex; int m_lastLine; - int m_textDelimiterIndex; - int m_thousandsSeparatorIndex; bool m_symbolFound; bool m_invalidConversion; -} -; - -class CsvUtil: public QObject -{ - Q_OBJECT - -public: - CsvUtil(); - ~CsvUtil(); - - InvestTransactionEditor* m_investTransactionEditor; - - const QString& feeId(const MyMoneyAccount& invAcc); - const QString& interestId(const MyMoneyAccount& invAcc); - QString expenseId(const QString& name); - QString interestId(const QString& name); - QString feeId(const QString& name); - QString nameToId(const QString& name, MyMoneyAccount& parent); - void scanCategories(QString& id, const MyMoneyAccount& invAcc, const MyMoneyAccount& parentAccount, const QString& defaultName); - void previouslyUsedCategories(const QString& investmentAccount, QString& feesId, QString& interestId); - const QString checkCategory(const QString& name, const MyMoneyMoney& value, const MyMoneyMoney& value2); - void createAccount(MyMoneyAccount& newAccount, MyMoneyAccount& parentAccount, MyMoneyAccount& brokerageAccount, MyMoneyMoney openingBal); -private: - QString m_feeId; - QString m_interestId; - bool m_scannedCategories; }; #endif diff --git a/kmymoney/plugins/csvimport/csvutil.cpp b/kmymoney/plugins/csvimport/csvutil.cpp --- a/kmymoney/plugins/csvimport/csvutil.cpp +++ b/kmymoney/plugins/csvimport/csvutil.cpp @@ -15,576 +15,170 @@ * * ***************************************************************************/ #include "csvutil.h" - -#include -#include -#include - -#include -#include -#include -#include "kmymoneyutils.h" -#include "investtransactioneditor.h" -#include "transactioneditor.h" -#include "mymoneyaccount.h" +//#include +//#include +#include +#include Parse::Parse() : - m_decimalSymbolIndex(0), - m_fieldDelimiterIndex(0), m_lastLine(0), - m_textDelimiterIndex(0), - m_thousandsSeparatorIndex(0), - m_symbolFound(false) + m_symbolFound(false), + m_invalidConversion(false) { - m_fieldDelimiterCharList << "," << ";" << ":" << "\t"; - m_fieldDelimiterCharacter = m_fieldDelimiterCharList[m_fieldDelimiterIndex]; - m_textDelimiterCharList << "\"" << "'"; - m_textDelimiterCharacter = m_textDelimiterCharList[m_textDelimiterIndex]; - m_decimalSymbolList << "." << ","; - m_thousandsSeparatorList << "," << "."; - m_invalidConversion = false; + m_fieldDelimiters = {QLatin1Char(','), QLatin1Char(';'), QLatin1Char(':'), QLatin1Char('\t')}; + m_textDelimiters = {QLatin1Char('"'), QLatin1Char('\'')}; + m_decimalSymbols = {QLatin1Char('.'), QLatin1Char(',')}; + m_thousandsSeparators = {QLatin1Char(','), QLatin1Char('.')}; + + setFieldDelimiter(FieldDelimiter::Comma); + setTextDelimiter(TextDelimiter::DoubleQuote); + setDecimalSymbol(DecimalSymbol::Dot); } Parse::~Parse() { } QStringList Parse::parseLine(const QString& data) { - QStringList listIn; QStringList listOut; - QString txt; - QString txt1; - m_fieldDelimiterCharacter = m_fieldDelimiterCharList[m_fieldDelimiterIndex]; - listIn = data.split(m_fieldDelimiterCharacter); // firstly, split on m_fieldDelimiterCharacter - - QStringList::const_iterator constIterator; - - for (constIterator = listIn.constBegin(); constIterator < listIn.constEnd(); ++constIterator) { - txt = (*constIterator); - + const QStringList listIn = data.split(m_fieldDelimiter); // firstly, split on m_fieldDelimiterCharacter + QString cell; + foreach (const auto it, listIn) { + cell.append(it); // detect where a "quoted" string has been erroneously split, because of a comma, // or in a value, a 'thousand separator' being mistaken for a field delimiter. //Also, where a 'field seperator' is within quotes and the quotes don't include the whole of the field. - - while ((txt.startsWith(m_textDelimiterCharacter)) && (!txt.mid(1, -1).contains(m_textDelimiterCharacter))) { - if (++constIterator < listIn.constEnd()) { - txt1 = (*constIterator);// second part of the split string - txt += m_fieldDelimiterCharacter + txt1;// rejoin the string - } else break; + if (cell.startsWith(m_textDelimiter)) { + if (!cell.endsWith(m_textDelimiter)) { + cell.append(m_fieldDelimiter); + continue; + } + cell.remove(m_textDelimiter); } - listOut += txt.remove(m_textDelimiterCharacter); + listOut.append(cell); + cell.clear(); } return listOut; } -QStringList Parse::parseFile(const QString& buf, int strt, int end) +QStringList Parse::parseFile(const QString &buf) { - QStringList outBuffer; - outBuffer.clear(); int lineCount = 0; - QString tmpBuffer; - tmpBuffer.clear(); bool inQuotes = false; - int charCount = buf.count(); - QString::const_iterator constIterator; + QString line; + QStringList lines; - for (constIterator = buf.constBegin(); constIterator != buf.constEnd(); - ++constIterator) { - QString chr = (*constIterator); - charCount -= 1; - if (chr == m_textDelimiterCharacter) { - tmpBuffer += chr; - if (inQuotes == true) { // if already in quoted field.. - inQuotes = false;// ..end it - } else {// if not.. - inQuotes = true;// ..start it - } + foreach (const auto chr, buf) { + if (chr == m_textDelimiter) { + line += chr; + inQuotes = !inQuotes; continue; - - // find carriage return and line feed chars - - } else if ((chr == "\r") || (chr == "\n")) { - if (inQuotes == true) { // embedded '\n' or '\r' in quoted field - chr = '~';// replace it with ~ for now - tmpBuffer += chr; - if (charCount > 0) // more chars yet - continue;// more chars yet - } - // true EOL (not in quotes) - if (tmpBuffer.isEmpty()) { - continue; - } - lineCount ++; - if (lineCount < strt) { // startLine not yet reached first wanted line - tmpBuffer.clear(); + } else if (chr == QLatin1Char('\r') || chr == QLatin1Char('\n')) { + if (inQuotes) { + line += QLatin1Char('~'); continue; } - outBuffer << tmpBuffer; - tmpBuffer.clear(); - // look for start of wanted data - // if first pass or if not at last line, proceed - if ((!end == 0) && (lineCount >= end)) { // m_endLine is set from UI after first pass - m_lastLine = lineCount; - break; - } - } - - // end of 'EOL detected' loop - - else {// must be data char - tmpBuffer += chr; - - if (charCount > 0) { // more chars yet + if (line.isEmpty()) continue; - } else {// else eoFile = true; - // last char in file is data char - // meaning no return on last line - // so bump line count - lineCount ++; - } - } - if (!tmpBuffer.isEmpty()) { - outBuffer << tmpBuffer; + ++lineCount; + lines += line; + line.clear(); + } else { + line += chr; + continue; } } m_lastLine = lineCount; - return outBuffer; -} - -QString Parse::fieldDelimiterCharacter(int index) -{ - if (index == -1) { - return 0; - } - return m_fieldDelimiterCharList[index]; -} - -void Parse::setFieldDelimiterCharacter(int index) -{ - m_fieldDelimiterCharacter = m_fieldDelimiterCharList[index]; -} - -void Parse::setFieldDelimiterIndex(int index) -{ - m_fieldDelimiterIndex = index; -} - -QString Parse::textDelimiterCharacter(int index) -{ - return m_textDelimiterCharList[index]; -} - -void Parse::setTextDelimiterCharacter(int index) -{ - m_textDelimiterCharacter = m_textDelimiterCharList[index]; + return lines; } -void Parse::setTextDelimiterIndex(int index) +void Parse::setFieldDelimiter(const FieldDelimiter _d) { - m_textDelimiterIndex = index; -} - -void Parse::decimalSymbolSelected(int val) -{ - if (val < 0) { + if (_d == FieldDelimiter::Auto) return; - } - - m_decimalSymbolIndex = val; - m_decimalSymbol = m_decimalSymbolList[val]; - thousandsSeparatorChanged(val); -} - -QString Parse::decimalSymbol(int index) -{ - return m_decimalSymbolList[index]; -} - -void Parse::setDecimalSymbol(int index) -{ - m_decimalSymbol = m_decimalSymbolList[index]; + m_fieldDelimiter = m_fieldDelimiters.at((int)_d); } -int Parse::decimalSymbolIndex() +void Parse::setTextDelimiter(const TextDelimiter _d) { - return m_decimalSymbolIndex; + m_textDelimiter = m_textDelimiters.at((int)_d); } -void Parse::setDecimalSymbolIndex(int index) +void Parse::setDecimalSymbol(const DecimalSymbol _d) { - m_decimalSymbolIndex = index; -} - -void Parse::thousandsSeparatorChanged(int val) -{ - m_thousandsSeparatorIndex = val; - m_thousandsSeparator = m_thousandsSeparatorList[val]; - if (m_thousandsSeparator == QLocale().groupSeparator()) { + if (_d == DecimalSymbol::Auto) return; - } + m_decimalSymbol = m_decimalSymbols.at((int)_d); + if (_d == DecimalSymbol::Comma) + m_thousandsSeparator = m_thousandsSeparators.at((int)ThousandSeparator::Dot); + else + m_thousandsSeparator = m_thousandsSeparators.at((int)ThousandSeparator::Comma); } -QString Parse::thousandsSeparator() +QChar Parse::decimalSymbol(const DecimalSymbol _d) { - return m_thousandsSeparator; -} - -void Parse::setThousandsSeparator(int index) -{ - m_thousandsSeparator = m_thousandsSeparatorList[index]; -} - -void Parse::setThousandsSeparatorIndex(int index) -{ - m_thousandsSeparatorIndex = index; + if (_d == DecimalSymbol::Auto) + return QChar(); + return m_decimalSymbols.at((int)_d); } int Parse::lastLine() { return m_lastLine; } -bool Parse::symbolFound() -{ - return m_symbolFound; -} - -void Parse::setSymbolFound(bool found) -{ - m_symbolFound = found; -} - QString Parse::possiblyReplaceSymbol(const QString& str) { + // examples given if decimal symbol is '.' and thousand symbol is ',' m_symbolFound = false; - m_invalidConversion = false; + m_invalidConversion = true; QString txt = str.trimmed(); - if (txt.isEmpty()) { - return txt; // exit as no decimal symbol - } - if (txt.contains('(')) { // "(" or "Af" = debit - txt = txt.remove(QRegExp("[()]")); - txt = '-' + txt; - } - int decimalIndex = txt.indexOf(m_decimalSymbol, 0); - int length = txt.length(); - int thouIndex = txt.lastIndexOf(m_thousandsSeparator, -1); - - // Check if this col/cell contains decimal symbol - - if (decimalIndex == -1) { // selected decimal not found - m_symbolFound = false; - if ((thouIndex == -1) || (thouIndex == length - 4)) { //no separator || correct format - txt.remove(m_thousandsSeparator); - txt.remove(QRegularExpression("[^\\d]")); // remove all non-digits - if (!txt.isEmpty()) // if no digit left, then it isn't number - txt = txt + QLocale().decimalPoint() + "00"; - else - m_invalidConversion = true; - return txt; - } else - m_invalidConversion = true; + if (txt.isEmpty()) // empty strings not allowed return txt; - } - txt.remove(m_thousandsSeparator); // remove unwanted old thousands separator - // Found decimal + bool parentheses = false; + if (txt.contains(QLatin1Char('('))) // (1.23) is in fact -1.23 + parentheses = true; - m_symbolFound = true; // found genuine decimal - - if (thouIndex >= 0) { // there was a separator - if (decimalIndex < thouIndex) { // invalid conversion - m_invalidConversion = true; - } - if (decimalIndex == length - 1) { // ...decimal point with no decimal part (strange?) - txt += m_decimalSymbol + "00"; - } - }// thouIndex = -1 no thousands separator - - // m_symbolFound = true found genuine decimal - txt.replace(m_decimalSymbol, QLocale().decimalPoint()); // so swap it - return txt; -} - -bool Parse::invalidConversion() -{ - return m_invalidConversion; -} - -//-------------------------------------------------------------------------------------------------------------------------------- - -CsvUtil::CsvUtil() : - m_investTransactionEditor(0), - m_scannedCategories(false) -{ -} - -CsvUtil::~CsvUtil() -{ -} - -const QString& CsvUtil::feeId(const MyMoneyAccount& invAcc) -{ - scanCategories(m_feeId, invAcc, MyMoneyFile::instance()->expense(), i18n("_Fees")); - return m_feeId; -} - -const QString& CsvUtil::interestId(const MyMoneyAccount& invAcc) -{ - scanCategories(m_interestId, invAcc, MyMoneyFile::instance()->income(), i18n("_Dividend")); - return m_interestId; -} - -QString CsvUtil::nameToId(const QString& name, MyMoneyAccount& parent) -{ - // Adapted from KMyMoneyApp::createAccount(MyMoneyAccount& newAccount, MyMoneyAccount& parentAccount, MyMoneyAccount& brokerageAccount, MyMoneyMoney openingBal) - // Needed to find/create category:sub-categories - MyMoneyFile* file = MyMoneyFile::instance(); - - QString id = file->categoryToAccount(name, MyMoneyAccount::UnknownAccountType); - // if it does not exist, we have to create it - if (id.isEmpty()) { - MyMoneyAccount newAccount; - MyMoneyAccount parentAccount = parent; - newAccount.setName(name) ; - int pos; - // check for ':' in the name and use it as separator for a hierarchy - while ((pos = newAccount.name().indexOf(MyMoneyFile::AccountSeperator)) != -1) { - QString part = newAccount.name().left(pos); - QString remainder = newAccount.name().mid(pos + 1); - const MyMoneyAccount& existingAccount = file->subAccountByName(parentAccount, part); - if (existingAccount.id().isEmpty()) { - newAccount.setName(part); - newAccount.setAccountType(parentAccount.accountType()); - file->addAccount(newAccount, parentAccount); - parentAccount = newAccount; - } else { - parentAccount = existingAccount; - } - newAccount.setParentAccountId(QString()); // make sure, there's no parent - newAccount.clearId(); // and no id set for adding - newAccount.removeAccountIds(); // and no sub-account ids - newAccount.setName(remainder); - }//end while - newAccount.setAccountType(parentAccount.accountType()); - - // make sure we have a currency. If none is assigned, we assume base currency - if (newAccount.currencyId().isEmpty()) - newAccount.setCurrencyId(file->baseCurrency().id()); - - file->addAccount(newAccount, parentAccount); - id = newAccount.id(); - } - return id; -} - -QString CsvUtil::expenseId(const QString& name) -{ - MyMoneyAccount parent = MyMoneyFile::instance()->expense(); - return nameToId(name, parent); -} - -QString CsvUtil::interestId(const QString& name) -{ - MyMoneyAccount parent = MyMoneyFile::instance()->income(); - return nameToId(name, parent); -} - -QString CsvUtil::feeId(const QString& name) -{ - MyMoneyAccount parent = MyMoneyFile::instance()->expense(); - return nameToId(name, parent); -} + int length = txt.length(); + int decimalIndex = txt.indexOf(m_decimalSymbol); + int thouIndex = txt.lastIndexOf(m_thousandsSeparator); + txt.remove(QRegularExpression(QStringLiteral("[^\\d.,-+]"))); // remove all non-digits + txt.remove(m_thousandsSeparator); -void CsvUtil::scanCategories(QString& id, const MyMoneyAccount& invAcc, const MyMoneyAccount& parentAccount, const QString& defaultName) -{ - if (!m_scannedCategories) { - previouslyUsedCategories(invAcc.id(), m_feeId, m_interestId); - m_scannedCategories = true; - } + if (txt.isEmpty()) // empty strings not allowed + return txt; - if (id.isEmpty()) { - MyMoneyFile* file = MyMoneyFile::instance(); - MyMoneyAccount acc = file->accountByName(defaultName); - // if it does not exist, we have to create it - if (acc.id().isEmpty()) { - MyMoneyAccount parent = parentAccount; - acc.setName(defaultName); - acc.setAccountType(parent.accountType()); - acc.setCurrencyId(parent.currencyId()); - file->addAccount(acc, parent); + if (decimalIndex == -1) { // e.g. 1 ; 1,234 ; 1,234,567; 12, + if (thouIndex == -1 || thouIndex == length - 4) { // e.g. 1 ; 1,234 ; 1,234,567 + txt.append(QLocale().decimalPoint() + QLatin1String("00")); // e.g. 1.00 ; 1234.00 ; 1234567.00 + m_invalidConversion = false; } - id = acc.id(); + return txt; } -} + m_symbolFound = true; // decimal symbol found -void CsvUtil::previouslyUsedCategories(const QString& investmentAccount, QString& feesId, QString& interestId) -{ - feesId.clear(); - interestId.clear(); - MyMoneyFile* file = MyMoneyFile::instance(); - try { - MyMoneyAccount acc = file->account(investmentAccount); - MyMoneyTransactionFilter filter(investmentAccount); - filter.setReportAllSplits(false); - // since we assume an investment account here, we need to collect the stock accounts as well - filter.addAccount(acc.accountList()); - QList< QPair > list; - file->transactionList(list, filter); - QList< QPair >::const_iterator it_t; - for (it_t = list.constBegin(); it_t != list.constEnd(); ++it_t) { - const MyMoneyTransaction& t = (*it_t).first; - const MyMoneySplit&s = (*it_t).second; - MyMoneySplit assetAccountSplit; - QList feeSplits; - QList interestSplits; - MyMoneySecurity security; - MyMoneySecurity currency; - MyMoneySplit::investTransactionTypeE transactionType; - KMyMoneyUtils::dissectTransaction(t, s, assetAccountSplit, feeSplits, interestSplits, security, currency, transactionType); - if (feeSplits.count() == 1) { - feesId = feeSplits.first().accountId(); - } - if (interestSplits.count() == 1) { - interestId = interestSplits.first().accountId(); - } - } - } catch (const MyMoneyException &) { - } -} + if (decimalIndex < thouIndex) // e.g. 1.234,567 ; 1.23,45 + return txt; -const QString CsvUtil::checkCategory(const QString& name, const MyMoneyMoney& value, const MyMoneyMoney& value2) -{ - // Borrowed from MyMoneyQifReader::checkCategory() - QString accountId; - MyMoneyFile *file = MyMoneyFile::instance(); - MyMoneyAccount account; - bool found = true; + m_invalidConversion = false; // it cannot be true after this point + txt.replace(m_decimalSymbol, QLocale().decimalPoint()); // so swap it - if (!name.isEmpty()) { - // The category might be constructed with an arbitraty depth (number of - // colon delimited fields). We try to find a parent account within this - // hierarchy by searching the following sequence: - // - // aaaa:bbbb:cccc:ddddd - // - // 1. search aaaa:bbbb:cccc:dddd, create nothing - // 2. search aaaa:bbbb:cccc , create dddd - // 3. search aaaa:bbbb , create cccc:dddd - // 4. search aaaa , create bbbb:cccc:dddd - // 5. don't search , create aaaa:bbbb:cccc:dddd + if (decimalIndex == length - 1) // e.g. 1. ; 123. + txt.append(QLatin1String("00")); - account.setName(name); - QString accName; // part to be created (right side in above list) - QString parent(name); // a possible parent part (left side in above list) - do { - accountId = file->categoryToAccount(parent); - if (accountId.isEmpty()) { - found = false; - // prepare next step - if (!accName.isEmpty()) - accName.prepend(':'); - accName.prepend(parent.section(':', -1)); - account.setName(accName); - parent = parent.section(':', 0, -2); - } else if (!accName.isEmpty()) { - account.setParentAccountId(accountId); - } - } while (!parent.isEmpty() && accountId.isEmpty()); + if (parentheses) + txt.prepend(QLatin1Char('-')); - // if we did not find the category, we create it - if (!found) { - MyMoneyAccount parent; - if (account.parentAccountId().isEmpty()) { - if (!value.isNegative() && value2.isNegative()) - parent = file->income(); - else - parent = file->expense(); - } else { - parent = file->account(account.parentAccountId()); - } - account.setAccountType((!value.isNegative() && value2.isNegative()) ? MyMoneyAccount::Income : MyMoneyAccount::Expense); - MyMoneyAccount brokerage; - // clear out the parent id, because createAccount() does not like that - account.setParentAccountId(QString()); - createAccount(account, parent, brokerage, MyMoneyMoney()); - accountId = account.id(); - } - } - - return accountId; + return txt; } - -void CsvUtil::createAccount(MyMoneyAccount& newAccount, MyMoneyAccount& parentAccount, MyMoneyAccount& brokerageAccount, MyMoneyMoney openingBal) +bool Parse::invalidConversion() { - MyMoneyFile* file = MyMoneyFile::instance(); - - // make sure we have a currency. If none is assigned, we assume base currency - if (newAccount.currencyId().isEmpty()) - newAccount.setCurrencyId(file->baseCurrency().id()); - - MyMoneyFileTransaction ft; - try { - int pos; - // check for ':' in the name and use it as separator for a hierarchy - while ((pos = newAccount.name().indexOf(MyMoneyFile::AccountSeperator)) != -1) { - QString part = newAccount.name().left(pos); - QString remainder = newAccount.name().mid(pos + 1); - const MyMoneyAccount& existingAccount = file->subAccountByName(parentAccount, part); - if (existingAccount.id().isEmpty()) { - newAccount.setName(part); - - file->addAccount(newAccount, parentAccount); - parentAccount = newAccount; - } else { - parentAccount = existingAccount; - } - newAccount.setParentAccountId(QString()); // make sure, there's no parent - newAccount.clearId(); // and no id set for adding - newAccount.removeAccountIds(); // and no sub-account ids - newAccount.setName(remainder); - } - - const MyMoneySecurity& sec = file->security(newAccount.currencyId()); - // Check the opening balance - if (openingBal.isPositive() && newAccount.accountGroup() == MyMoneyAccount::Liability) { - QString message = i18n("This account is a liability and if the " - "opening balance represents money owed, then it should be negative. " - "Negate the amount?\n\n" - "Please click Yes to change the opening balance to %1,\n" - "Please click No to leave the amount as %2,\n" - "Please click Cancel to abort the account creation." - , MyMoneyUtils::formatMoney(-openingBal, newAccount, sec) - , MyMoneyUtils::formatMoney(openingBal, newAccount, sec)); - - int ans = KMessageBox::questionYesNoCancel(0, message); - if (ans == KMessageBox::Yes) { - openingBal = -openingBal; - - } else if (ans == KMessageBox::Cancel) - return; - } - - file->addAccount(newAccount, parentAccount); - - if (newAccount.accountType() == MyMoneyAccount::Investment - && !brokerageAccount.name().isEmpty()) { - file->addAccount(brokerageAccount, parentAccount); - - // set a link from the investment account to the brokerage account - file->modifyAccount(newAccount); - file->createOpeningBalanceTransaction(brokerageAccount, openingBal); - - } else - file->createOpeningBalanceTransaction(newAccount, openingBal); - - ft.commit(); - } catch (const MyMoneyException &e) { - KMessageBox::information(0, i18n("Unable to add account: %1", e.what())); - } + return m_invalidConversion; } +//-------------------------------------------------------------------------------------------------------------------------------- diff --git a/kmymoney/plugins/csvimport/csvwizard.h b/kmymoney/plugins/csvimport/csvwizard.h --- a/kmymoney/plugins/csvimport/csvwizard.h +++ b/kmymoney/plugins/csvimport/csvwizard.h @@ -23,11 +23,9 @@ // ---------------------------------------------------------------------------- // QT Includes -#include #include #include #include -#include // ---------------------------------------------------------------------------- // KDE Includes @@ -42,13 +40,11 @@ #include "securitiesdlg.h" #include "currenciesdlg.h" -//#include "csvimporter.h" -#include "csvimporterplugin.h" +#include "csvwizardpage.h" #include "bankingwizardpage.h" #include "investmentwizardpage.h" #include "priceswizardpage.h" - class CsvImporterPlugin; class CSVImporter; @@ -86,76 +82,73 @@ PageBanking, PageInvestment, PagePrices, PageFormats }; - Ui::CSVWizard* ui; + Ui::CSVWizard *ui; + MyMoneyStatement m_st; + QScrollBar *m_vScrollBar; + IntroPage *m_pageIntro; + + int m_initialHeight; + int m_initialWidth; + + QBrush m_clearBrush; + QBrush m_clearBrushText; + QBrush m_colorBrush; + QBrush m_colorBrushText; + QBrush m_errorBrush; + QBrush m_errorBrushText; + + QMap m_colTypeName; + bool m_skipSetup; + + void clearColumnsBackground(const int col); + void clearColumnsBackground(const QList &columnList); + void clearBackground(); + void markUnwantedRows(); + void importClicked(); + /** + * Called in order to adjust window size to suit the file, + */ + void updateWindowSize(); - CsvImporterPlugin* m_plugin; - CSVImporter* m_imp; - QWizard* m_wiz; + void initializeComboBoxes(const QHash &columns); + +private: + QList m_stageLabels; + + int m_curId; + int m_lastId; - IntroPage *m_pageIntro; SeparatorPage *m_pageSeparator; RowsPage *m_pageRows; QPointer m_pageBanking; QPointer m_pageInvestment; QPointer m_pagePrices; FormatsPage *m_pageFormats; - MyMoneyStatement m_st; - - QList m_stageLabels; - QScrollBar *m_vScrollBar; - - QBrush m_clearBrush; - QBrush m_clearBrushText; - QBrush m_colorBrush; - QBrush m_colorBrushText; - QBrush m_errorBrush; - QBrush m_errorBrushText; - - int m_initialHeight; - int m_initialWidth; - - QMap m_colTypeName; - bool m_skipSetup; - - void showStage(); + CsvImporterPlugin* m_plugin; + CSVImporter* m_imp; + QWizard* m_wiz; - void clearColumnsBackground(const int col); - void clearColumnsBackground(const QList &columnList); - void clearBackground(); - void markUnwantedRows(); + void readWindowSize(const KSharedConfigPtr& config); + void saveWindowSize(const KSharedConfigPtr& config); + void showStage(); -public slots: + void closeEvent(QCloseEvent *event); + bool eventFilter(QObject *object, QEvent *event); +private slots: /** * This method is called when 'Exit' is clicked. The plugin settings will * be saved and the plugin will be terminated. */ void slotClose(); - - /** - * Called in order to adjust window size to suit the file, - */ - void updateWindowSize(); - - void readWindowSize(const KSharedConfigPtr& config); - void saveWindowSize(const KSharedConfigPtr& config); - - void slotIdChanged(int id); - void fileDialogClicked(); - void importClicked(); void saveAsQIFClicked(); -private: - int m_curId; - int m_lastId; - void closeEvent(QCloseEvent *event); - bool eventFilter(QObject *object, QEvent *event); -// void resizeEvent(QResizeEvent* ev); -} -; +signals: + void statementReady(MyMoneyStatement&); +}; namespace Ui { @@ -170,28 +163,24 @@ explicit IntroPage(CSVWizard *dlg, CSVImporter *imp); ~IntroPage(); - Ui::IntroPage *ui; - void initializePage(); -// void setParent(CSVWizard* dlg, CSVImporter *imp); + void initializePage(); - QVBoxLayout* m_pageLayout; - profileTypeE m_profileType; + Profile m_profileType; + Ui::IntroPage *ui; signals: void signalBankClicked(bool); void activated(int); void returnPressed(); private: - bool validatePage(); - int nextId() const; - QStringList m_profiles; - void profileChanged(const profilesActionE action); - void profileTypeChanged(const profileTypeE profileType, bool toggled); + bool validatePage(); + int nextId() const; -public slots: + void profileChanged(const ProfileAction action); + void profileTypeChanged(const Profile profileType, bool toggled); private slots: void slotAddProfile(); @@ -217,29 +206,21 @@ explicit SeparatorPage(CSVWizard *dlg, CSVImporter *imp); ~SeparatorPage(); - Ui::SeparatorPage *ui; - - QVBoxLayout *m_pageLayout; - - void initializePage(); - bool isComplete() const; - -public slots: - void encodingChanged(const int index); - void fieldDelimiterChanged(const int index); - void textDelimiterChanged(const int index); +private slots: + void encodingChanged(const int index); + void fieldDelimiterChanged(const int index); + void textDelimiterChanged(const int index); signals: void completeChanged(); private: + Ui::SeparatorPage *ui; void initializeEncodingCombobox(); + void initializePage(); + bool isComplete() const; void cleanupPage(); bool validatePage(); - -private slots: - -signals: }; namespace Ui @@ -255,31 +236,23 @@ explicit RowsPage(CSVWizard *dlg, CSVImporter *imp); ~RowsPage(); - Ui::RowsPage *ui; - - QVBoxLayout *m_pageLayout; - - void initializePage(); - int nextId() const; - -signals: - -public slots: +private slots: /** * This method is called when the user edits the startLine setting. */ - void startRowChanged(int val); + void startRowChanged(int val); /** * This method is called when the user edits the lastLine setting. */ - void endRowChanged(int val); + void endRowChanged(int val); private: - void cleanupPage(); + Ui::RowsPage *ui; + void initializePage(); + int nextId() const; + void cleanupPage(); }; - - namespace Ui { class FormatsPage; @@ -293,37 +266,33 @@ explicit FormatsPage(CSVWizard *dlg, CSVImporter *imp); ~FormatsPage(); - Ui::FormatsPage *ui; - - QVBoxLayout *m_pageLayout; - - void initializePage(); +private: + Ui::FormatsPage *ui; + bool m_isDecimalSymbolOK; + bool m_isDateFormatOK; /** * This method is called when the user selects a new decimal symbol. The * UI is updated using the new symbol, and on importing, the new symbol * also will be used. */ - bool validateDecimalSymbols(const QList &columns); + bool validateDecimalSymbols(const QList &columns); /** * This method checks if all dates in date column are valid. */ - bool validateDateFormat(const int index); - -signals: -void completeChanged(); -public slots: + bool validateDateFormat(const int index); + void initializePage(); + bool isComplete() const; + void cleanupPage(); - void decimalSymbolChanged(int); - void dateFormatChanged(const int index); -private: - bool m_isDecimalSymbolOK; - bool m_isDateFormatOK; +signals: + void completeChanged(); - bool isComplete() const; - void cleanupPage(); +private slots: + void decimalSymbolChanged(int); + void dateFormatChanged(const int index); }; #endif // CSVWIZARD_H diff --git a/kmymoney/plugins/csvimport/csvwizard.cpp b/kmymoney/plugins/csvimport/csvwizard.cpp --- a/kmymoney/plugins/csvimport/csvwizard.cpp +++ b/kmymoney/plugins/csvimport/csvwizard.cpp @@ -24,7 +24,6 @@ #include #include -#include #include #include @@ -39,6 +38,10 @@ // ---------------------------------------------------------------------------- // Project Includes +#include "csvimporterplugin.h" +#include "csvutil.h" +#include "convdate.h" +#include "csvimporter.h" #include "ui_csvwizard.h" #include "ui_introwizardpage.h" #include "ui_separatorwizardpage.h" @@ -52,10 +55,10 @@ #include "ui_securitydlg.h" CSVWizard::CSVWizard(CsvImporterPlugin* plugin, CSVImporter* importer) : - ui(new Ui::CSVWizard), - m_plugin(plugin), - m_imp(importer), - m_wiz(new QWizard) + ui(new Ui::CSVWizard), + m_plugin(plugin), + m_imp(importer), + m_wiz(new QWizard) { ui->setupUi(this); ui->tableView->setModel(m_imp->m_file->m_model); @@ -121,14 +124,12 @@ CSVWizard::~CSVWizard() { delete ui; - if (m_wiz) - delete m_wiz; } void CSVWizard::showStage() { QString str = ui->label_intro->text(); - ui->label_intro->setText(QLatin1String("") + str + QLatin1String("/")); + ui->label_intro->setText(QString::fromLatin1("%1").arg(str)); } void CSVWizard::readWindowSize(const KSharedConfigPtr& config) { @@ -159,7 +160,7 @@ m_stageLabels[m_lastId]->setText(txt); txt = m_stageLabels[m_curId]->text(); - txt = QLatin1String("") + txt + QLatin1String(""); + txt = QString::fromLatin1("%1").arg(txt); m_stageLabels[m_curId]->setText(txt); } @@ -301,7 +302,7 @@ { m_imp->m_profile->m_lastUsedDirectory = m_imp->m_file->m_inFileName; m_imp->m_profile->writeSettings(CSVImporter::configFile()); - m_imp->profilesAction(m_imp->m_profile->type(), ProfilesUpdateLastUsed, m_imp->m_profile->m_profileName, m_imp->m_profile->m_profileName); + m_imp->profilesAction(m_imp->m_profile->type(), ProfileAction::UpdateLastUsed, m_imp->m_profile->m_profileName, m_imp->m_profile->m_profileName); close(); } @@ -320,20 +321,20 @@ m_skipSetup = m_pageIntro->ui->m_skipSetup->isChecked(); switch(m_imp->m_profile->type()) { - case ProfileInvest: + case Profile::Investment: if (!m_pageInvestment) { m_pageInvestment = new InvestmentPage(this, m_imp); m_wiz->setPage(CSVWizard::PageInvestment, m_pageInvestment); } break; - case ProfileBank: + case Profile::Banking: if (!m_pageBanking) { m_pageBanking = new BankingPage(this, m_imp); m_wiz->setPage(CSVWizard::PageBanking, m_pageBanking); } break; - case ProfileStockPrices: - case ProfileCurrencyPrices: + case Profile::StockPrices: + case Profile::CurrencyPrices: if (!m_pagePrices) { m_pagePrices = new PricesPage(this, m_imp); m_wiz->setPage(CSVWizard::PagePrices, m_pagePrices); @@ -353,11 +354,11 @@ void CSVWizard::importClicked() { switch (m_imp->m_profile->type()) { - case ProfileBank: + case Profile::Banking: if (!m_pageBanking->validateCreditDebit()) return; break; - case ProfileInvest: + case Profile::Investment: if (!m_pageInvestment->validateActionType()) return; break; @@ -368,17 +369,17 @@ if (!m_imp->createStatement(m_st)) return; slotClose(); - emit m_imp->statementReady(m_st); + emit statementReady(m_st); } void CSVWizard::saveAsQIFClicked() { switch (m_imp->m_profile->type()) { - case ProfileBank: + case Profile::Banking: if (!m_pageBanking->validateCreditDebit()) return; break; - case ProfileInvest: + case Profile::Investment: if (!m_pageInvestment->validateActionType()) return; break; @@ -396,26 +397,42 @@ outFileName = QFileDialog::getSaveFileName(this, i18n("Save QIF"), outFileName, i18n("QIF Files (*.qif)")); if (outFileName.isEmpty()) return; - QFile oFile(outFileName); - oFile.open(QIODevice::WriteOnly); switch (m_imp->m_profile->type()) { - case ProfileBank: - m_pageBanking->makeQIF(m_st, oFile); + case Profile::Banking: + m_pageBanking->makeQIF(m_st, outFileName); break; - case ProfileInvest: - m_pageInvestment->makeQIF(m_st, oFile); + case Profile::Investment: + m_pageInvestment->makeQIF(m_st, outFileName); break; default: break; } - oFile.close(); +} + +void CSVWizard::initializeComboBoxes(const QHash &columns) +{ + QStringList columnNumbers; + for (int i = 0; i < m_imp->m_file->m_columnCount; ++i) + columnNumbers.append(QString::number(i + 1)); + + foreach (const auto column, columns) { + // disable widgets allowing their initialization + column->blockSignals(true); + // clear all existing items before adding new ones + column->clear(); + // populate comboboxes with col # values + column->addItems(columnNumbers); + // all comboboxes are set to 0 so set them to -1 + column->setCurrentIndex(-1); + // enable widgets after their initialization + column->blockSignals(false); + } } //------------------------------------------------------------------------------------------------------- IntroPage::IntroPage(CSVWizard *dlg, CSVImporter *imp) : CSVWizardPage(dlg, imp), - ui(new Ui::IntroPage), - m_pageLayout(0) + ui(new Ui::IntroPage) { ui->setupUi(this); } @@ -445,13 +462,13 @@ ui->m_profiles->lineEdit()->setClearButtonEnabled(true); connect(ui->m_profiles, SIGNAL(currentIndexChanged(int)), this, SLOT(slotComboSourceIndexChanged(int))); - connect(ui->m_add, SIGNAL(clicked()), this, SLOT(slotAddProfile())); - connect(ui->m_remove, SIGNAL(clicked()), this, SLOT(slotRemoveProfile())); - connect(ui->m_rename, SIGNAL(clicked()), this, SLOT(slotRenameProfile())); - connect(ui->m_profilesBank, SIGNAL(toggled(bool)), this, SLOT(slotBankRadioToggled(bool))); - connect(ui->m_profilesInvest, SIGNAL(toggled(bool)), this, SLOT(slotInvestRadioToggled(bool))); - connect(ui->m_profilesCurrencyPrices, SIGNAL(toggled(bool)), this, SLOT(slotCurrencyPricesRadioToggled(bool))); - connect(ui->m_profilesStockPrices, SIGNAL(toggled(bool)), this, SLOT(slotStockPricesRadioToggled(bool))); + connect(ui->m_add, &QAbstractButton::clicked, this, &IntroPage::slotAddProfile); + connect(ui->m_remove, &QAbstractButton::clicked, this, &IntroPage::slotRemoveProfile); + connect(ui->m_rename, &QAbstractButton::clicked, this, &IntroPage::slotRenameProfile); + connect(ui->m_profilesBank, &QAbstractButton::toggled, this, &IntroPage::slotBankRadioToggled); + connect(ui->m_profilesInvest, &QAbstractButton::toggled, this, &IntroPage::slotInvestRadioToggled); + connect(ui->m_profilesCurrencyPrices, &QAbstractButton::toggled, this, &IntroPage::slotCurrencyPricesRadioToggled); + connect(ui->m_profilesStockPrices, &QAbstractButton::toggled, this, &IntroPage::slotStockPricesRadioToggled); if (m_dlg->m_initialHeight == -1 || m_dlg->m_initialWidth == -1) { m_dlg->m_initialHeight = m_dlg->geometry().height(); m_dlg->m_initialWidth = m_dlg->geometry().width(); @@ -475,30 +492,30 @@ void IntroPage::slotAddProfile() { - profileChanged(ProfilesAdd); + profileChanged(ProfileAction::Add); } void IntroPage::slotRemoveProfile() { - profileChanged(ProfilesRemove); + profileChanged(ProfileAction::Remove); } void IntroPage::slotRenameProfile() { - profileChanged(ProfilesRename); + profileChanged(ProfileAction::Rename); } -void IntroPage::profileChanged(const profilesActionE action) +void IntroPage::profileChanged(const ProfileAction action) { QString cbText = ui->m_profiles->currentText(); if (cbText.isEmpty()) // you cannot neither add nor remove empty name profile or rename to empty name return; int cbIndex = ui->m_profiles->currentIndex(); switch (action) { - case ProfilesRename: - case ProfilesAdd: + case ProfileAction::Rename: + case ProfileAction::Add: { int dupIndex = m_profiles.indexOf(QRegularExpression (cbText)); if (dupIndex == cbIndex && cbIndex != -1) // if profile name wasn't changed then return @@ -512,7 +529,7 @@ } break; } - case ProfilesRemove: + case ProfileAction::Remove: if (m_profiles.value(cbIndex) != cbText) // user changed name of the profile and tries to remove it return; break; @@ -522,21 +539,21 @@ if (CSVImporter::profilesAction(m_profileType, action, m_profiles.value(cbIndex), cbText)) { switch (action) { - case ProfilesAdd: + case ProfileAction::Add: m_profiles.append(cbText); ui->m_profiles->addItem(cbText); ui->m_profiles->setCurrentIndex(m_profiles.count() - 1); KMessageBox::information(m_dlg, i18n("
Profile %1 has been added.
", cbText)); break; - case ProfilesRemove: + case ProfileAction::Remove: m_profiles.removeAt(cbIndex); ui->m_profiles->removeItem(cbIndex); KMessageBox::information(m_dlg, i18n("
Profile %1 has been removed.
", cbText)); break; - case ProfilesRename: + case ProfileAction::Rename: ui->m_profiles->setItemText(cbIndex, cbText); KMessageBox::information(m_dlg, i18n("
Profile name has been renamed from %1 to %2.
", @@ -565,31 +582,31 @@ } } -void IntroPage::profileTypeChanged(const profileTypeE profileType, bool toggled) +void IntroPage::profileTypeChanged(const Profile profileType, bool toggled) { if (!toggled) return; KConfigGroup profilesGroup(CSVImporter::configFile(), CSVImporter::m_confProfileNames); m_profileType = profileType; QString profileTypeStr; switch (m_profileType) { - case ProfileBank: + case Profile::Banking: ui->m_profilesInvest->setChecked(false); ui->m_profilesStockPrices->setChecked(false); ui->m_profilesCurrencyPrices->setChecked(false); break; - case ProfileInvest: + case Profile::Investment: ui->m_profilesBank->setChecked(false); ui->m_profilesStockPrices->setChecked(false); ui->m_profilesCurrencyPrices->setChecked(false); break; - case ProfileStockPrices: + case Profile::StockPrices: ui->m_profilesBank->setChecked(false); ui->m_profilesInvest->setChecked(false); ui->m_profilesCurrencyPrices->setChecked(false); break; - case ProfileCurrencyPrices: + case Profile::CurrencyPrices: ui->m_profilesBank->setChecked(false); ui->m_profilesInvest->setChecked(false); ui->m_profilesStockPrices->setChecked(false); @@ -610,32 +627,32 @@ void IntroPage::slotBankRadioToggled(bool toggled) { - profileTypeChanged(ProfileBank, toggled); + profileTypeChanged(Profile::Banking, toggled); } void IntroPage::slotInvestRadioToggled(bool toggled) { - profileTypeChanged(ProfileInvest, toggled); + profileTypeChanged(Profile::Investment, toggled); } void IntroPage::slotCurrencyPricesRadioToggled(bool toggled) { - profileTypeChanged(ProfileCurrencyPrices, toggled); + profileTypeChanged(Profile::CurrencyPrices, toggled); } void IntroPage::slotStockPricesRadioToggled(bool toggled) { - profileTypeChanged(ProfileStockPrices, toggled); + profileTypeChanged(Profile::StockPrices, toggled); } SeparatorPage::SeparatorPage(CSVWizard *dlg, CSVImporter *imp) : CSVWizardPage(dlg, imp), ui(new Ui::SeparatorPage) { ui->setupUi(this); - - m_pageLayout = new QVBoxLayout; - ui->horizontalLayout->insertLayout(0, m_pageLayout); + connect(ui->m_encoding, SIGNAL(currentIndexChanged(int)), this, SLOT(encodingChanged(int))); + connect(ui->m_fieldDelimiter, SIGNAL(currentIndexChanged(int)), this, SLOT(fieldDelimiterChanged(int))); + connect(ui->m_textDelimiter, SIGNAL(currentIndexChanged(int)), this, SLOT(textDelimiterChanged(int))); } SeparatorPage::~SeparatorPage() @@ -646,15 +663,17 @@ void SeparatorPage::initializePage() { // comboboxes are preset to -1 and, in new profile case, can be set here to -1 as well ... + // ... so block their signals until setting them ... + ui->m_encoding->blockSignals(true); + ui->m_fieldDelimiter->blockSignals(true); + ui->m_textDelimiter->blockSignals(true); initializeEncodingCombobox(); ui->m_encoding->setCurrentIndex(ui->m_encoding->findData(m_imp->m_profile->m_encodingMIBEnum)); - ui->m_fieldDelimiter->setCurrentIndex(m_imp->m_profile->m_fieldDelimiterIndex); - ui->m_textDelimiter->setCurrentIndex(m_imp->m_profile->m_textDelimiterIndex); - - // ... so connect their signals after setting them ... - connect(ui->m_encoding, SIGNAL(currentIndexChanged(int)), this, SLOT(encodingChanged(int))); - connect(ui->m_fieldDelimiter, SIGNAL(currentIndexChanged(int)), this, SLOT(fieldDelimiterChanged(int))); - connect(ui->m_textDelimiter, SIGNAL(currentIndexChanged(int)), this, SLOT(textDelimiterChanged(int))); + ui->m_fieldDelimiter->setCurrentIndex((int)m_imp->m_profile->m_fieldDelimiter); + ui->m_textDelimiter->setCurrentIndex((int)m_imp->m_profile->m_textDelimiter); + ui->m_encoding->blockSignals(false); + ui->m_fieldDelimiter->blockSignals(false); + ui->m_textDelimiter->blockSignals(false); // ... and ensure that their signal receivers will always be called emit ui->m_encoding->currentIndexChanged(ui->m_encoding->currentIndex()); @@ -669,7 +688,6 @@ void SeparatorPage::initializeEncodingCombobox() { - ui->m_encoding->blockSignals(true); ui->m_encoding->clear(); QList codecs; @@ -702,7 +720,6 @@ foreach (const auto codec, codecs) ui->m_encoding->addItem(codec->name(), codec->mibEnum()); - ui->m_encoding->blockSignals(false); } void SeparatorPage::encodingChanged(const int index) @@ -722,16 +739,16 @@ if (index == -1 && // if field delimiter isn't set... !m_imp->m_autodetect.value(AutoFieldDelimiter)) // ... and user disabled autodetecting... return; // ... then wait for him to choose - else if (index == m_imp->m_profile->m_fieldDelimiterIndex) + else if (index == (int)m_imp->m_profile->m_fieldDelimiter) return; - m_imp->m_profile->m_fieldDelimiterIndex = index; + m_imp->m_profile->m_fieldDelimiter = static_cast(int(index)); m_imp->m_file->readFile(m_imp->m_profile); // get column count, we get with this fieldDelimiter m_imp->m_file->setupParser(m_imp->m_profile); if (index == -1) { ui->m_fieldDelimiter->blockSignals(true); - ui->m_fieldDelimiter->setCurrentIndex(m_imp->m_profile->m_fieldDelimiterIndex); + ui->m_fieldDelimiter->setCurrentIndex((int)m_imp->m_profile->m_fieldDelimiter); ui->m_fieldDelimiter->blockSignals(false); } m_dlg->updateWindowSize(); @@ -745,12 +762,12 @@ return; } - m_imp->m_profile->m_textDelimiterIndex = index; + m_imp->m_profile->m_textDelimiter = static_cast(index); m_imp->m_file->setupParser(m_imp->m_profile); if (index == -1) { ui->m_textDelimiter->blockSignals(true); - ui->m_textDelimiter->setCurrentIndex(m_imp->m_profile->m_textDelimiterIndex); + ui->m_textDelimiter->setCurrentIndex((int)m_imp->m_profile->m_textDelimiter); ui->m_textDelimiter->blockSignals(false); } emit completeChanged(); @@ -763,16 +780,16 @@ ui->m_fieldDelimiter->currentIndex() != -1 && ui->m_textDelimiter->currentIndex() != -1) { switch(m_imp->m_profile->type()) { - case ProfileBank: + case Profile::Banking: if (m_imp->m_file->m_columnCount > 2) rc = true; break; - case ProfileInvest: + case Profile::Investment: if (m_imp->m_file->m_columnCount > 3) rc = true; break; - case ProfileCurrencyPrices: - case ProfileStockPrices: + case Profile::CurrencyPrices: + case Profile::StockPrices: if (m_imp->m_file->m_columnCount > 1) rc = true; break; @@ -792,18 +809,16 @@ { // On completion with error force use of 'Back' button. // ...to allow resetting of 'Skip setup' - disconnect(ui->m_fieldDelimiter, SIGNAL(currentIndexChanged(int)), this, SLOT(fieldDelimiterChanged(int))); - disconnect(ui->m_textDelimiter, SIGNAL(currentIndexChanged(int)), this, SLOT(textDelimiterChanged(int))); m_dlg->m_pageIntro->initializePage(); // Need to show button(QWizard::CustomButton1) not 'NextButton' } RowsPage::RowsPage(CSVWizard *dlg, CSVImporter *imp) : CSVWizardPage(dlg, imp), ui(new Ui::RowsPage) { ui->setupUi(this); - m_pageLayout = new QVBoxLayout; - ui->horizontalLayout->insertLayout(0, m_pageLayout); + connect(ui->m_startLine, SIGNAL(valueChanged(int)), this, SLOT(startRowChanged(int)));; + connect(ui->m_endLine, SIGNAL(valueChanged(int)), this, SLOT(endRowChanged(int))); } RowsPage::~RowsPage() @@ -813,20 +828,18 @@ void RowsPage::initializePage() { -// disconnect(ui->m_startLine, &QSpinBox::valueChanged, this, &RowsPage::startRowChanged); -// disconnect(ui->m_endLine, &QSpinBox::valueChanged, this, &RowsPage::endRowChanged); - + ui->m_startLine->blockSignals(true); + ui->m_endLine->blockSignals(true); ui->m_startLine->setMaximum(m_imp->m_file->m_rowCount); ui->m_endLine->setMaximum(m_imp->m_file->m_rowCount); ui->m_startLine->setValue(m_imp->m_profile->m_startLine + 1); ui->m_endLine->setValue(m_imp->m_profile->m_endLine + 1); + ui->m_startLine->blockSignals(false); + ui->m_endLine->blockSignals(false); m_dlg->markUnwantedRows(); m_dlg->m_vScrollBar->setValue(m_imp->m_profile->m_startLine); - connect(ui->m_startLine, SIGNAL(valueChanged(int)), this, SLOT(startRowChanged(int)));; - connect(ui->m_endLine, SIGNAL(valueChanged(int)), this, SLOT(endRowChanged(int))); - QList layout; layout << QWizard::Stretch << QWizard::BackButton << @@ -837,23 +850,21 @@ void RowsPage::cleanupPage() { - disconnect(ui->m_startLine, SIGNAL(valueChanged(int)), this, SLOT(startRowChanged(int)));; - disconnect(ui->m_endLine, SIGNAL(valueChanged(int)), this, SLOT(endRowChanged(int))); m_dlg->clearBackground(); } int RowsPage::nextId() const { int ret; switch (m_imp->m_profile->type()) { - case ProfileBank: + case Profile::Banking: ret = CSVWizard::PageBanking; break; - case ProfileInvest: + case Profile::Investment: ret = CSVWizard::PageInvestment; break; - case ProfileStockPrices: - case ProfileCurrencyPrices: + case Profile::StockPrices: + case Profile::CurrencyPrices: ret = CSVWizard::PagePrices; break; default: @@ -866,12 +877,13 @@ void RowsPage::startRowChanged(int val) { if (val > m_imp->m_file->m_rowCount) { - ui->m_startLine->setValue(m_imp->m_file->m_rowCount); + ui->m_startLine->setValue(m_imp->m_file->m_rowCount - 1); return; } --val; if (val > m_imp->m_profile->m_endLine) { - ui->m_startLine->setValue(m_imp->m_profile->m_endLine); + if (m_imp->m_profile->m_endLine <= m_imp->m_file->m_rowCount) + ui->m_startLine->setValue(m_imp->m_profile->m_endLine + 1); return; } m_imp->m_profile->m_startLine = val; @@ -882,30 +894,28 @@ void RowsPage::endRowChanged(int val) { if (val > m_imp->m_file->m_rowCount) { - ui->m_endLine->setValue(m_imp->m_file->m_rowCount); + ui->m_endLine->setValue(m_imp->m_file->m_rowCount - 1); return; } --val; if (val < m_imp->m_profile->m_startLine) { - ui->m_endLine->setValue(m_imp->m_profile->m_startLine); + if (m_imp->m_profile->m_startLine <= m_imp->m_file->m_rowCount) + ui->m_endLine->setValue(m_imp->m_profile->m_startLine + 1); return; } m_imp->m_profile->m_trailerLines = m_imp->m_file->m_rowCount - val; m_imp->m_profile->m_endLine = val; m_dlg->markUnwantedRows(); } - - - FormatsPage::FormatsPage(CSVWizard *dlg, CSVImporter *imp) : CSVWizardPage(dlg, imp), ui(new Ui::FormatsPage) { ui->setupUi(this); - m_pageLayout = new QVBoxLayout; - ui->horizontalLayout->insertLayout(0, m_pageLayout); + connect(ui->m_dateFormat, SIGNAL(currentIndexChanged(int)), this, SLOT(dateFormatChanged(int))); + connect(ui->m_decimalSymbol, SIGNAL(currentIndexChanged(int)), this, SLOT(decimalSymbolChanged(int))); } FormatsPage::~FormatsPage() @@ -915,8 +925,6 @@ void FormatsPage::initializePage() { - disconnect(ui->comboBox_dateFormat, SIGNAL(currentIndexChanged(int)), this, SLOT(dateFormatChanged(int))); - disconnect(ui->comboBox_decimalSymbol, SIGNAL(currentIndexChanged(int)), this, SLOT(decimalSymbolChanged(int))); m_isDecimalSymbolOK = false; m_isDateFormatOK = false; QList layout; @@ -935,65 +943,70 @@ wizard()->button(QWizard::CustomButton3)->setEnabled(false); wizard()->button(QWizard::FinishButton)->setEnabled(false); - ui->comboBox_thousandsDelimiter->setEnabled(false); + ui->m_thousandsDelimiter->setEnabled(false); - ui->comboBox_dateFormat->setCurrentIndex(m_imp->m_profile->m_dateFormatIndex); // put before connect to not emit update signal - connect(ui->comboBox_dateFormat, SIGNAL(currentIndexChanged(int)), this, SLOT(dateFormatChanged(int))); - emit ui->comboBox_dateFormat->currentIndexChanged(m_imp->m_profile->m_dateFormatIndex); // emit update signal manually regardless of change to combobox + ui->m_dateFormat->blockSignals(true); + ui->m_dateFormat->setCurrentIndex((int)m_imp->m_profile->m_dateFormat); + ui->m_dateFormat->blockSignals(false); + emit ui->m_dateFormat->currentIndexChanged((int)m_imp->m_profile->m_dateFormat); // emit update signal manually regardless of change to combobox - ui->comboBox_decimalSymbol->setCurrentIndex(m_imp->m_profile->m_decimalSymbolIndex); // put before connect to not emit update signal - connect(ui->comboBox_decimalSymbol, SIGNAL(currentIndexChanged(int)), this, SLOT(decimalSymbolChanged(int))); - emit ui->comboBox_decimalSymbol->currentIndexChanged(m_imp->m_profile->m_decimalSymbolIndex); // emit update signal manually regardless of change to combobox + ui->m_decimalSymbol->blockSignals(true); + if (m_imp->m_profile->m_decimalSymbol == DecimalSymbol::Auto && !m_imp->m_autodetect.value(AutoDecimalSymbol)) + ui->m_decimalSymbol->setCurrentIndex(-1); + else + ui->m_decimalSymbol->setCurrentIndex((int)m_imp->m_profile->m_decimalSymbol); + ui->m_decimalSymbol->blockSignals(false); + emit ui->m_decimalSymbol->currentIndexChanged((int)m_imp->m_profile->m_decimalSymbol); // emit update signal manually regardless of change to combobox if (m_dlg->m_skipSetup && wizard()->button(QWizard::CustomButton2)->isEnabled()) m_dlg->importClicked(); } void FormatsPage::decimalSymbolChanged(int index) { - QList columns = m_imp->getNumericalColumns(); + const QList columns = m_imp->getNumericalColumns(); switch (index) { case -1: if (!m_imp->m_autodetect.value(AutoDecimalSymbol)) break; - /// @fixme add a break statement or leave a 'intentional fall through' comment + // fall through intentional case 2: { - ui->comboBox_decimalSymbol->blockSignals(true); - m_imp->m_profile->m_decimalSymbolIndex = 2; + ui->m_decimalSymbol->blockSignals(true); + m_imp->m_profile->m_decimalSymbol = DecimalSymbol::Auto; int failColumn = m_imp->detectDecimalSymbols(columns); if (failColumn != -2) { KMessageBox::sorry(this, i18n("
Autodetect could not detect your decimal symbol in column %1.
" "
Try manual selection to see problematic cells and correct your data.
", failColumn), i18n("CSV import")); - ui->comboBox_decimalSymbol->setCurrentIndex(-1); - ui->comboBox_thousandsDelimiter->setCurrentIndex(-1); + ui->m_decimalSymbol->setCurrentIndex(-1); + ui->m_thousandsDelimiter->setCurrentIndex(-1); } else if (index == -1) { // if detection went well and decimal symbol was unspecified then we'll be specifying it - int firstDecSymbol = m_imp->m_decimalSymbolIndexMap.first(); + DecimalSymbol firstDecSymbol = m_imp->m_decimalSymbolIndexMap.first(); bool allSymbolsEqual = true; foreach (const auto mapDecSymbol, m_imp->m_decimalSymbolIndexMap) { if (firstDecSymbol != mapDecSymbol) allSymbolsEqual = false; } if (allSymbolsEqual) { // if symbol in all columns is equal then set it... - m_imp->m_profile->m_decimalSymbolIndex = firstDecSymbol; - ui->comboBox_decimalSymbol->setCurrentIndex(firstDecSymbol); - ui->comboBox_thousandsDelimiter->setCurrentIndex(firstDecSymbol); + m_imp->m_profile->m_decimalSymbol = firstDecSymbol; + ui->m_decimalSymbol->setCurrentIndex((int)firstDecSymbol); + ui->m_thousandsDelimiter->setCurrentIndex((int)firstDecSymbol); } else { // else set to auto - m_imp->m_profile->m_decimalSymbolIndex = 2; - ui->comboBox_decimalSymbol->setCurrentIndex(2); - ui->comboBox_thousandsDelimiter->setCurrentIndex(2); + m_imp->m_profile->m_decimalSymbol = DecimalSymbol::Auto; + ui->m_decimalSymbol->setCurrentIndex((int)DecimalSymbol::Auto); + ui->m_thousandsDelimiter->setCurrentIndex((int)DecimalSymbol::Auto); } } - ui->comboBox_decimalSymbol->blockSignals(false); + ui->m_decimalSymbol->blockSignals(false); break; } default: foreach (const auto column, columns) - m_imp->m_decimalSymbolIndexMap.insert(column, index); - ui->comboBox_thousandsDelimiter->setCurrentIndex(index); - m_imp->m_profile->m_decimalSymbolIndex = index; + m_imp->m_decimalSymbolIndexMap.insert(column, static_cast(index)); + ui->m_thousandsDelimiter->setCurrentIndex(index); + m_imp->m_profile->m_decimalSymbol = static_cast(index); } m_isDecimalSymbolOK = validateDecimalSymbols(columns); @@ -1005,7 +1018,6 @@ bool isOK = true; foreach (const auto col, columns) { m_imp->m_file->m_parse->setDecimalSymbol(m_imp->m_decimalSymbolIndexMap.value(col)); - m_imp->m_file->m_parse->setThousandsSeparator(m_imp->m_decimalSymbolIndexMap.value(col)); m_dlg->clearColumnsBackground(col); for (int row = m_imp->m_profile->m_startLine; row <= m_imp->m_profile->m_endLine; ++row) { QStandardItem *item = m_imp->m_file->m_model->item(row, col); @@ -1032,9 +1044,9 @@ if (index == -1) return; - int col = m_imp->m_profile->m_colTypeNum.value(ColumnDate); - m_imp->m_profile->m_dateFormatIndex = index; - m_imp->m_convertDate->setDateFormatIndex(index); + int col = m_imp->m_profile->m_colTypeNum.value(Column::Date); + m_imp->m_profile->m_dateFormat = static_cast(index); + m_imp->m_convertDate->setDateFormatIndex(static_cast(index)); m_isDateFormatOK = validateDateFormat(col); if (!m_isDateFormatOK) { KMessageBox::sorry(this, i18n("
There are invalid date formats in column '%1'.
" @@ -1047,12 +1059,13 @@ bool FormatsPage::validateDateFormat(const int col) { m_dlg->clearColumnsBackground(col); + QDate emptyDate; bool isOK = true; for (int row = m_imp->m_profile->m_startLine; row <= m_imp->m_profile->m_endLine; ++row) { QStandardItem* item = m_imp->m_file->m_model->item(row, col); QDate dat = m_imp->m_convertDate->convertDate(item->text()); - if (dat == QDate()) { + if (dat == emptyDate) { isOK = false; m_dlg->ui->tableView->scrollTo(item->index(), QAbstractItemView::EnsureVisible); item->setBackground(m_dlg->m_errorBrush); @@ -1069,19 +1082,16 @@ { const bool enable = m_isDecimalSymbolOK && m_isDateFormatOK; wizard()->button(QWizard::CustomButton2)->setEnabled(enable); - if (m_imp->m_profile->type() != ProfileStockPrices && - m_imp->m_profile->type() != ProfileCurrencyPrices) + if (m_imp->m_profile->type() != Profile::StockPrices && + m_imp->m_profile->type() != Profile::CurrencyPrices) wizard()->button(QWizard::CustomButton3)->setEnabled(enable); return enable; } void FormatsPage::cleanupPage() { - disconnect(ui->comboBox_dateFormat, SIGNAL(currentIndexChanged(int)), this, SLOT(dateFormatChanged(int))); - disconnect(ui->comboBox_decimalSymbol, SIGNAL(currentIndexChanged(int)), this, SLOT(decimalSymbolChanged(int))); - QList columns = m_imp->getNumericalColumns(); - columns.append(m_imp->m_profile->m_colTypeNum.value(ColumnDate)); + columns.append(m_imp->m_profile->m_colTypeNum.value(Column::Date)); m_dlg->clearColumnsBackground(columns); m_dlg->m_st = MyMoneyStatement(); // any change on investment/banking page invalidates created statement diff --git a/kmymoney/plugins/csvimport/csvwizardpage.h b/kmymoney/plugins/csvimport/csvwizardpage.h new file mode 100644 --- /dev/null +++ b/kmymoney/plugins/csvimport/csvwizardpage.h @@ -0,0 +1,36 @@ +/******************************************************************************* +* csvwizardpage.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 CSVWIZARDPAGE_H +#define CSVWIZARDPAGE_H + +#include +#include "csvenums.h" + +class CSVWizard; +class CSVImporter; + +class CSVWizardPage : public QWizardPage +{ +public: + CSVWizardPage(CSVWizard *dlg, CSVImporter *imp) : QWizardPage(nullptr), m_dlg(dlg), m_imp(imp) {} + +protected: + CSVWizard *m_dlg; + CSVImporter *m_imp; +}; + +#endif // CSVWIZARDPAGE_H diff --git a/kmymoney/plugins/csvimport/formatswizardpage.ui b/kmymoney/plugins/csvimport/formatswizardpage.ui --- a/kmymoney/plugins/csvimport/formatswizardpage.ui +++ b/kmymoney/plugins/csvimport/formatswizardpage.ui @@ -99,7 +99,7 @@ - + false @@ -140,7 +140,7 @@ - + 0 @@ -192,7 +192,7 @@ - + 0 diff --git a/kmymoney/plugins/csvimport/investmentwizardpage.h b/kmymoney/plugins/csvimport/investmentwizardpage.h --- a/kmymoney/plugins/csvimport/investmentwizardpage.h +++ b/kmymoney/plugins/csvimport/investmentwizardpage.h @@ -23,25 +23,23 @@ // ---------------------------------------------------------------------------- // QT Includes -#include #include -#include // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes -#include -#include +#include "csvwizardpage.h" // ---------------------------------------------------------------------------- class InvestmentProfile; class TransactionDlg; class SecurityDlg; class SecuritiesDlg; +class MyMoneyStatement; namespace Ui { @@ -56,15 +54,10 @@ explicit InvestmentPage(CSVWizard *dlg, CSVImporter *imp); ~InvestmentPage(); - Ui::InvestmentPage *ui; - - QVBoxLayout *m_pageLayout; - - /** * This method fills QIF file with investment data */ - void makeQIF(MyMoneyStatement& st, QFile& file); + void makeQIF(const MyMoneyStatement &st, const QString &outFileName); /** * This method validates the column numbers entered by the user. It then @@ -79,21 +72,20 @@ bool validatePage(); void cleanupPage(); - void initializeComboBoxes(); void clearFeeCol(); /** * This method will check whether memo combobox is still valid * after changing name or type column. */ bool validateMemoComboBox(); - void resetComboBox(const columnTypeE comboBox); + void resetComboBox(const Column comboBox); /** * This method is called column on investment page is selected. * It sets m_colTypeNum, m_colNumType and runs column validation. */ - bool validateSelectedColumn(const int col, const columnTypeE type); + bool validateSelectedColumn(const int col, const Column type); /** * This method ensures that every security has symbol and name. @@ -104,6 +96,7 @@ QPointer m_securityDlg; QPointer m_securitiesDlg; InvestmentProfile *m_profile; + Ui::InvestmentPage *ui; private slots: void clearFee(); diff --git a/kmymoney/plugins/csvimport/investmentwizardpage.cpp b/kmymoney/plugins/csvimport/investmentwizardpage.cpp --- a/kmymoney/plugins/csvimport/investmentwizardpage.cpp +++ b/kmymoney/plugins/csvimport/investmentwizardpage.cpp @@ -24,6 +24,7 @@ #include #include +#include // ---------------------------------------------------------------------------- // KDE Includes @@ -33,8 +34,9 @@ // ---------------------------------------------------------------------------- // Project Includes -#include "mymoneyfile.h" +#include #include "csvwizard.h" +#include "csvimporter.h" #include "transactiondlg.h" #include "securitydlg.h" @@ -50,31 +52,43 @@ { ui->setupUi(this); - m_pageLayout = new QVBoxLayout; - ui->horizontalLayout->insertLayout(0, m_pageLayout); - connect(ui->m_clear, &QAbstractButton::clicked, this, &InvestmentPage::clearColumns); connect(ui->m_clearFee, &QAbstractButton::clicked, this, &InvestmentPage::clearFee); connect(ui->m_calculateFee, &QAbstractButton::clicked, this, &InvestmentPage::calculateFee); // initialize column names - m_dlg->m_colTypeName.insert(ColumnType, i18n("Type")); - m_dlg->m_colTypeName.insert(ColumnPrice, i18n("Price")); - m_dlg->m_colTypeName.insert(ColumnQuantity, i18n("Quantity")); - m_dlg->m_colTypeName.insert(ColumnFee, i18n("Fee")); - m_dlg->m_colTypeName.insert(ColumnDate, i18n("Date")); - m_dlg->m_colTypeName.insert(ColumnAmount, i18n("Amount")); - m_dlg->m_colTypeName.insert(ColumnSymbol, i18n("Symbol")); - m_dlg->m_colTypeName.insert(ColumnName, i18n("Name")); - m_dlg->m_colTypeName.insert(ColumnMemo, i18n("Memo")); + m_dlg->m_colTypeName.insert(Column::Type, i18n("Type")); + m_dlg->m_colTypeName.insert(Column::Price, i18n("Price")); + m_dlg->m_colTypeName.insert(Column::Quantity, i18n("Quantity")); + m_dlg->m_colTypeName.insert(Column::Fee, i18n("Fee")); + m_dlg->m_colTypeName.insert(Column::Date, i18n("Date")); + m_dlg->m_colTypeName.insert(Column::Amount, i18n("Amount")); + m_dlg->m_colTypeName.insert(Column::Symbol, i18n("Symbol")); + m_dlg->m_colTypeName.insert(Column::Name, i18n("Name")); + m_dlg->m_colTypeName.insert(Column::Memo, i18n("Memo")); m_profile = dynamic_cast(m_imp->m_profile); + + connect(ui->m_memoCol, SIGNAL(currentIndexChanged(int)), this, SLOT(memoColSelected(int))); + connect(ui->m_typeCol, SIGNAL(currentIndexChanged(int)), this, SLOT(typeColSelected(int))); + connect(ui->m_dateCol, SIGNAL(currentIndexChanged(int)), this, SLOT(dateColSelected(int))); + connect(ui->m_quantityCol, SIGNAL(currentIndexChanged(int)), this, SLOT(quantityColSelected(int))); + connect(ui->m_priceCol, SIGNAL(currentIndexChanged(int)), this, SLOT(priceColSelected(int))); + connect(ui->m_priceFraction, SIGNAL(currentIndexChanged(int)), this, SLOT(fractionChanged(int))); + connect(ui->m_amountCol, SIGNAL(currentIndexChanged(int)), this, SLOT(amountColSelected(int))); + connect(ui->m_feeCol, SIGNAL(currentIndexChanged(int)), this, SLOT(feeColSelected(int))); + connect(ui->m_symbolCol, SIGNAL(currentIndexChanged(int)), this, SLOT(symbolColSelected(int))); + connect(ui->m_nameCol, SIGNAL(currentIndexChanged(int)), this, SLOT(nameColSelected(int))); + connect(ui->m_feeIsPercentage, &QAbstractButton::clicked, this, &InvestmentPage::feeIsPercentageClicked); + connect(ui->m_feeRate, &QLineEdit::editingFinished, this, &InvestmentPage::feeInputsChanged); + connect(ui->m_feeRate, &QLineEdit::textChanged, this, &InvestmentPage::feeRateChanged); + connect(ui->m_minFee, &QLineEdit::textChanged, this, &InvestmentPage::minFeeChanged); } InvestmentPage::~InvestmentPage() { - delete ui; delete m_securitiesDlg; + delete ui; } void InvestmentPage::calculateFee() @@ -84,87 +98,28 @@ m_dlg->markUnwantedRows(); } -void InvestmentPage::initializeComboBoxes() -{ - // disable investment widgets allowing their initialization - disconnect(ui->m_memoCol, SIGNAL(currentIndexChanged(int)), this, SLOT(memoColSelected(int))); - disconnect(ui->m_typeCol, SIGNAL(currentIndexChanged(int)), this, SLOT(typeColSelected(int))); - disconnect(ui->m_dateCol, SIGNAL(currentIndexChanged(int)), this, SLOT(dateColSelected(int))); - disconnect(ui->m_quantityCol, SIGNAL(currentIndexChanged(int)), this, SLOT(quantityColSelected(int))); - disconnect(ui->m_priceCol, SIGNAL(currentIndexChanged(int)), this, SLOT(priceColSelected(int))); - disconnect(ui->m_priceFraction, SIGNAL(currentIndexChanged(int)), this, SLOT(fractionChanged(int))); - disconnect(ui->m_amountCol, SIGNAL(currentIndexChanged(int)), this, SLOT(amountColSelected(int))); - disconnect(ui->m_feeRate, SIGNAL(editingFinished()), this, SLOT(feeInputsChanged())); - disconnect(ui->m_feeRate, SIGNAL(textChanged(QString)), this, SLOT(feeRateChanged(QString))); - disconnect(ui->m_minFee, SIGNAL(textChanged(QString)), this, SLOT(minFeeChanged(QString))); - disconnect(ui->m_feeCol, SIGNAL(currentIndexChanged(int)), this, SLOT(feeColSelected(int))); - disconnect(ui->m_symbolCol, SIGNAL(currentIndexChanged(int)), this, SLOT(symbolColSelected(int))); - disconnect(ui->m_nameCol, SIGNAL(currentIndexChanged(int)), this, SLOT(nameColSelected(int))); - disconnect(ui->m_feeIsPercentage, SIGNAL(clicked(bool)), this, SLOT(feeIsPercentageClicked(bool))); - - // clear all existing items before adding new ones - ui->m_amountCol->clear(); // clear all existing items before adding new ones - ui->m_dateCol->clear(); - ui->m_memoCol->clear(); - ui->m_priceCol->clear(); - ui->m_quantityCol->clear(); - ui->m_typeCol->clear(); - ui->m_feeCol->clear(); - ui->m_symbolCol->clear(); - ui->m_nameCol->clear(); - ui->m_feeRate->clear(); - ui->m_minFee->clear(); - - QStringList columnNumbers; - for (int i = 0; i < m_imp->m_file->m_columnCount; ++i) - columnNumbers.append(QString::number(i + 1)); - - // populate comboboxes with col # values - ui->m_amountCol->addItems(columnNumbers); - ui->m_dateCol->addItems(columnNumbers); - ui->m_memoCol->addItems(columnNumbers); - ui->m_priceCol->addItems(columnNumbers); - ui->m_quantityCol->addItems(columnNumbers); - ui->m_typeCol->addItems(columnNumbers); - ui->m_feeCol->addItems(columnNumbers); - ui->m_symbolCol->addItems(columnNumbers); - ui->m_nameCol->addItems(columnNumbers); - - clearColumns(); // all comboboxes are set to 0 so set them to -1 - connect(ui->m_memoCol, SIGNAL(currentIndexChanged(int)), this, SLOT(memoColSelected(int))); - connect(ui->m_typeCol, SIGNAL(currentIndexChanged(int)), this, SLOT(typeColSelected(int))); - connect(ui->m_dateCol, SIGNAL(currentIndexChanged(int)), this, SLOT(dateColSelected(int))); - connect(ui->m_quantityCol, SIGNAL(currentIndexChanged(int)), this, SLOT(quantityColSelected(int))); - connect(ui->m_priceCol, SIGNAL(currentIndexChanged(int)), this, SLOT(priceColSelected(int))); - connect(ui->m_priceFraction, SIGNAL(currentIndexChanged(int)), this, SLOT(fractionChanged(int))); - connect(ui->m_amountCol, SIGNAL(currentIndexChanged(int)), this, SLOT(amountColSelected(int))); - connect(ui->m_feeRate, SIGNAL(editingFinished()), this, SLOT(feeInputsChanged())); - connect(ui->m_feeRate, SIGNAL(textChanged(QString)), this, SLOT(feeRateChanged(QString))); - connect(ui->m_minFee, SIGNAL(textChanged(QString)), this, SLOT(minFeeChanged(QString))); - connect(ui->m_feeCol, SIGNAL(currentIndexChanged(int)), this, SLOT(feeColSelected(int))); - connect(ui->m_symbolCol, SIGNAL(currentIndexChanged(int)), this, SLOT(symbolColSelected(int))); - connect(ui->m_nameCol, SIGNAL(currentIndexChanged(int)), this, SLOT(nameColSelected(int))); - connect(ui->m_feeIsPercentage, SIGNAL(clicked(bool)), this, SLOT(feeIsPercentageClicked(bool))); -} - void InvestmentPage::initializePage() { + QHash columns {{Column::Amount, ui->m_amountCol}, {Column::Type, ui->m_typeCol}, + {Column::Quantity, ui->m_quantityCol}, {Column::Memo, ui->m_memoCol}, + {Column::Price, ui->m_priceCol}, {Column::Date, ui->m_dateCol}, + {Column::Fee, ui->m_feeCol}, {Column::Symbol, ui->m_symbolCol}, + {Column::Name, ui->m_nameCol}}; + if (ui->m_dateCol->count() != m_imp->m_file->m_columnCount) - initializeComboBoxes(); - ui->m_dateCol->setCurrentIndex(m_profile->m_colTypeNum.value(ColumnDate)); - ui->m_typeCol->setCurrentIndex(m_profile->m_colTypeNum.value(ColumnType)); - ui->m_priceCol->setCurrentIndex(m_profile->m_colTypeNum.value(ColumnPrice)); - ui->m_quantityCol->setCurrentIndex(m_profile->m_colTypeNum.value(ColumnQuantity)); - ui->m_amountCol->setCurrentIndex(m_profile->m_colTypeNum.value(ColumnAmount)); - ui->m_nameCol->setCurrentIndex(m_profile->m_colTypeNum.value(ColumnName)); - ui->m_symbolCol->setCurrentIndex(m_profile->m_colTypeNum.value(ColumnSymbol)); + m_dlg->initializeComboBoxes(columns); + ui->m_feeIsPercentage->setChecked(m_profile->m_feeIsPercentage); - ui->m_feeCol->setCurrentIndex(m_profile->m_colTypeNum.value(ColumnFee)); + columns.remove(Column::Memo); + for (auto it = columns.cbegin(); it != columns.cend(); ++it) + it.value()->setCurrentIndex(m_profile->m_colTypeNum.value(it.key())); + ui->m_priceFraction->blockSignals(true); foreach (const auto priceFraction, m_imp->m_priceFractions) ui->m_priceFraction->addItem(QString::number(priceFraction.toDouble(), 'g', 3)); ui->m_priceFraction->blockSignals(false); ui->m_priceFraction->setCurrentIndex(m_profile->m_priceFraction); + ui->m_feeRate->setText(m_profile->m_feeRate); ui->m_minFee->setText(m_profile->m_minFee); ui->m_feeRate->setValidator(new QRegularExpressionValidator(QRegularExpression(QStringLiteral("[0-9]{1,2}[") + QLocale().decimalPoint() + QStringLiteral("]{1,1}[0-9]{0,2}")), this) ); @@ -217,8 +172,8 @@ void InvestmentPage::memoColSelected(int col) { - if (m_profile->m_colNumType.value(col) == ColumnType || - m_profile->m_colNumType.value(col) == ColumnName) { + if (m_profile->m_colNumType.value(col) == Column::Type || + m_profile->m_colNumType.value(col) == Column::Name) { int rc = KMessageBox::Yes; if (isVisible()) rc = KMessageBox::questionYesNo(m_dlg, i18n("
The '%1' field already has this column selected.
" @@ -234,66 +189,66 @@ } //allow only separate memo field occupy combobox ui->m_memoCol->blockSignals(true); - if (m_profile->m_colTypeNum.value(ColumnMemo) != -1) - ui->m_memoCol->setCurrentIndex(m_profile->m_colTypeNum.value(ColumnMemo)); + if (m_profile->m_colTypeNum.value(Column::Memo) != -1) + ui->m_memoCol->setCurrentIndex(m_profile->m_colTypeNum.value(Column::Memo)); else ui->m_memoCol->setCurrentIndex(-1); ui->m_memoCol->blockSignals(false); return; } - if (m_profile->m_colTypeNum.value(ColumnMemo) != -1) // check if this memo has any column 'number' assigned... + if (m_profile->m_colTypeNum.value(Column::Memo) != -1) // check if this memo has any column 'number' assigned... m_profile->m_memoColList.removeOne(col); // ...if true remove it from memo list - if(validateSelectedColumn(col, ColumnMemo)) + if(validateSelectedColumn(col, Column::Memo)) if (col != - 1 && !m_profile->m_memoColList.contains(col)) m_profile->m_memoColList.append(col); } void InvestmentPage::dateColSelected(int col) { - validateSelectedColumn(col, ColumnDate); + validateSelectedColumn(col, Column::Date); } void InvestmentPage::feeColSelected(int col) { - validateSelectedColumn(col, ColumnFee); + validateSelectedColumn(col, Column::Fee); feeInputsChanged(); } void InvestmentPage::typeColSelected(int col) { - if (validateSelectedColumn(col, ColumnType)) + if (validateSelectedColumn(col, Column::Type)) if (!validateMemoComboBox()) // user could have it already in memo so... memoColSelected(col); // ...if true set memo field again } void InvestmentPage::quantityColSelected(int col) { - validateSelectedColumn(col, ColumnQuantity); + validateSelectedColumn(col, Column::Quantity); } void InvestmentPage::priceColSelected(int col) { - validateSelectedColumn(col, ColumnPrice); + validateSelectedColumn(col, Column::Price); } void InvestmentPage::amountColSelected(int col) { - validateSelectedColumn(col, ColumnAmount); + validateSelectedColumn(col, Column::Amount); clearFeeCol(); feeInputsChanged(); } void InvestmentPage::symbolColSelected(int col) { - validateSelectedColumn(col, ColumnSymbol); + validateSelectedColumn(col, Column::Symbol); m_imp->m_mapSymbolName.clear(); // new symbol column so this map is no longer valid } void InvestmentPage::nameColSelected(int col) { - if (validateSelectedColumn(col, ColumnName)) + if (validateSelectedColumn(col, Column::Name)) if (!validateMemoComboBox()) // user could have it already in memo so... memoColSelected(col); // ...if true set memo field again m_imp->m_mapSymbolName.clear(); // new name column so this map is no longer valid @@ -358,7 +313,7 @@ ui->m_feeIsPercentage->setChecked(true); ui->m_minFee->setEnabled(true); ui->m_feeRate->setEnabled(true); - if (m_profile->m_colTypeNum.value(ColumnAmount) != -1) + if (m_profile->m_colTypeNum.value(Column::Amount) != -1) ui->m_calculateFee->setEnabled(true); } } @@ -376,7 +331,7 @@ void InvestmentPage::clearFeeCol() { if (!m_profile->m_feeRate.isEmpty() && // if fee rate isn't empty... - m_profile->m_colTypeNum.value(ColumnFee) >= m_imp->m_file->m_columnCount - 1 && + m_profile->m_colTypeNum.value(Column::Fee) >= m_imp->m_file->m_columnCount - 1 && !ui->m_feeCol->isEnabled()) { // ...and fee column is last... --m_imp->m_file->m_columnCount; m_imp->m_file->m_model->removeColumn(m_imp->m_file->m_columnCount); @@ -390,59 +345,59 @@ ui->m_feeIsPercentage->setChecked(false); } -void InvestmentPage::resetComboBox(const columnTypeE comboBox) +void InvestmentPage::resetComboBox(const Column comboBox) { switch (comboBox) { - case ColumnAmount: + case Column::Amount: ui->m_amountCol->setCurrentIndex(-1); break; - case ColumnDate: + case Column::Date: ui->m_dateCol->setCurrentIndex(-1); break; - case ColumnFee: + case Column::Fee: ui->m_feeCol->setCurrentIndex(-1); break; - case ColumnMemo: + case Column::Memo: ui->m_memoCol->setCurrentIndex(-1); break; - case ColumnPrice: + case Column::Price: ui->m_priceCol->setCurrentIndex(-1); break; - case ColumnQuantity: + case Column::Quantity: ui->m_quantityCol->setCurrentIndex(-1); break; - case ColumnType: + case Column::Type: ui->m_typeCol->setCurrentIndex(-1); break; - case ColumnSymbol: + case Column::Symbol: ui->m_symbolCol->setCurrentIndex(-1); break; - case ColumnName: + case Column::Name: ui->m_nameCol->setCurrentIndex(-1); break; default: - KMessageBox::sorry(m_dlg, i18n("
Field name not recognised.
'%1'
Please re-enter your column selections.", comboBox), i18n("CSV import")); + KMessageBox::sorry(m_dlg, i18n("
Field name not recognised.
'%1'
Please re-enter your column selections.", (int)comboBox), i18n("CSV import")); } } bool InvestmentPage::validateActionType() { for (int row = m_profile->m_startLine; row <= m_profile->m_endLine; ++row) { MyMoneyStatement::Transaction tr; // process quantity field - int col = m_profile->m_colTypeNum.value(ColumnQuantity); + int col = m_profile->m_colTypeNum.value(Column::Quantity); tr.m_shares = m_imp->processQuantityField(m_profile, row, col); // process price field - col = m_profile->m_colTypeNum.value(ColumnPrice); + col = m_profile->m_colTypeNum.value(Column::Price); tr.m_price = m_imp->processPriceField(m_profile, row, col); // process amount field - col = m_profile->m_colTypeNum.value(ColumnAmount); + col = m_profile->m_colTypeNum.value(Column::Amount); tr.m_amount = m_imp->processAmountField(m_profile, row, col); // process type field - col = m_profile->m_colTypeNum.value(ColumnType); + col = m_profile->m_colTypeNum.value(Column::Type); tr.m_eAction = m_imp->processActionTypeField(m_profile, row, col); switch(m_imp->validateActionType(tr)) { @@ -462,11 +417,11 @@ QStringList colList; QStringList colHeaders; for (int col = 0; col < m_imp->m_file->m_columnCount; ++col) { - colHeaders.append(m_dlg->m_colTypeName.value(m_profile->m_colNumType.value(col, ColumnInvalid), QString(i18nc("Unused column", "Unused")))); + colHeaders.append(m_dlg->m_colTypeName.value(m_profile->m_colNumType.value(col, Column::Invalid), QString(i18nc("Unused column", "Unused")))); colList.append(m_imp->m_file->m_model->item(row, col)->text()); } QList validActionTypes = m_imp->createValidActionTypes(tr); - TransactionDlg* transactionDlg = new TransactionDlg(colList, colHeaders, m_profile->m_colTypeNum.value(ColumnType), validActionTypes); + TransactionDlg* transactionDlg = new TransactionDlg(colList, colHeaders, m_profile->m_colTypeNum.value(Column::Type), validActionTypes); if (transactionDlg->exec() == QDialog::Rejected) { KMessageBox::information(m_dlg, i18n("
No valid action type found for this transaction.
" @@ -478,7 +433,7 @@ delete transactionDlg; if (unknownType) { // type was unknown so store it - col = m_profile->m_colTypeNum.value(ColumnType); + col = m_profile->m_colTypeNum.value(Column::Type); m_profile->m_transactionNames[tr.m_eAction].append(m_imp->m_file->m_model->item(row, col)->text()); // store action type } } @@ -490,7 +445,7 @@ return true; } -bool InvestmentPage::validateSelectedColumn(const int col, const columnTypeE type) +bool InvestmentPage::validateSelectedColumn(const int col, const Column type) { if (m_profile->m_colTypeNum.value(type) != -1) // check if this 'type' has any column 'number' assigned... m_profile->m_colNumType.remove(m_profile->m_colTypeNum.value(type)); // ...if true remove 'type' assigned to this column 'number' @@ -519,9 +474,9 @@ for (int i = 0; i < ui->m_memoCol->count(); ++i) { QString txt = ui->m_memoCol->itemText(i); - if (txt.contains(QChar(QLatin1Char('*')))) // check if text containing '*' belongs to valid column types - if (m_profile->m_colNumType.value(i) != ColumnName && - m_profile->m_colNumType.value(i) != ColumnType) { + if (txt.contains(QLatin1Char('*'))) // check if text containing '*' belongs to valid column types + if (m_profile->m_colNumType.value(i) != Column::Name && + m_profile->m_colNumType.value(i) != Column::Type) { ui->m_memoCol->setItemText(i, QString::number(i + 1)); m_profile->m_memoColList.removeOne(i); return false; @@ -604,9 +559,11 @@ return true; } -void InvestmentPage::makeQIF(MyMoneyStatement &st, QFile &file) +void InvestmentPage::makeQIF(const MyMoneyStatement& st, const QString& outFileName) { - QTextStream out(&file); + QFile oFile(outFileName); + oFile.open(QIODevice::WriteOnly); + QTextStream out(&oFile); QString buffer; QString strEType; @@ -697,4 +654,5 @@ out << buffer;// output qif file buffer.clear(); } + oFile.close(); } diff --git a/kmymoney/plugins/csvimport/priceswizardpage.h b/kmymoney/plugins/csvimport/priceswizardpage.h --- a/kmymoney/plugins/csvimport/priceswizardpage.h +++ b/kmymoney/plugins/csvimport/priceswizardpage.h @@ -21,18 +21,15 @@ // ---------------------------------------------------------------------------- // QT Includes -#include #include -#include // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes -#include -#include +#include "csvwizardpage.h" // ---------------------------------------------------------------------------- @@ -53,23 +50,17 @@ explicit PricesPage(CSVWizard *dlg, CSVImporter *imp); ~PricesPage(); - Ui::PricesPage *ui; - - QVBoxLayout *m_pageLayout; - private: void initializePage(); bool isComplete() const; bool validatePage(); - void initializeComboBoxes(); - - void resetComboBox(const columnTypeE comboBox); + void resetComboBox(const Column comboBox); /** * This method is called column on prices page is selected. * It sets m_colTypeNum, m_colNumType and runs column validation. */ - bool validateSelectedColumn(const int col, const columnTypeE type); + bool validateSelectedColumn(const int col, const Column type); /** * This method ensures that there is security for price import. @@ -82,6 +73,7 @@ bool validateCurrencies(); PricesProfile *m_profile; + Ui::PricesPage *ui; QPointer m_securityDlg; QPointer m_currenciesDlg; diff --git a/kmymoney/plugins/csvimport/priceswizardpage.cpp b/kmymoney/plugins/csvimport/priceswizardpage.cpp --- a/kmymoney/plugins/csvimport/priceswizardpage.cpp +++ b/kmymoney/plugins/csvimport/priceswizardpage.cpp @@ -31,10 +31,10 @@ // ---------------------------------------------------------------------------- // Project Includes -#include "mymoneyfile.h" +#include -#include "csvimporter.h" #include "csvwizard.h" +#include "csvimporter.h" #include "securitydlg.h" #include "currenciesdlg.h" @@ -48,56 +48,35 @@ { ui->setupUi(this); - m_pageLayout = new QVBoxLayout; - ui->horizontalLayout->insertLayout(0, m_pageLayout); - - connect(ui->button_clear, SIGNAL(clicked()), this, SLOT(clearColumns())); + connect(ui->button_clear, &QAbstractButton::clicked, this, &PricesPage::clearColumns); m_profile = dynamic_cast(m_imp->m_profile); // initialize column names - m_dlg->m_colTypeName.insert(ColumnPrice, i18n("Price")); - m_dlg->m_colTypeName.insert(ColumnDate, i18n("Date")); + m_dlg->m_colTypeName.insert(Column::Price, i18n("Price")); + m_dlg->m_colTypeName.insert(Column::Date, i18n("Date")); + connect(ui->m_dateCol, SIGNAL(currentIndexChanged(int)), this, SLOT(dateColSelected(int))); + connect(ui->m_priceCol, SIGNAL(currentIndexChanged(int)), this, SLOT(priceColSelected(int))); + connect(ui->m_priceFraction, SIGNAL(currentIndexChanged(int)), this, SLOT(fractionChanged(int))); } PricesPage::~PricesPage() { - delete ui; delete m_securityDlg; delete m_currenciesDlg; + delete ui; } -void PricesPage::initializeComboBoxes() +void PricesPage::initializePage() { - // disable prices widgets allowing their initialization - disconnect(ui->m_dateCol, SIGNAL(currentIndexChanged(int)), this, SLOT(dateColSelected(int))); - disconnect(ui->m_priceCol, SIGNAL(currentIndexChanged(int)), this, SLOT(priceColSelected(int))); - disconnect(ui->m_priceFraction, SIGNAL(currentIndexChanged(int)), this, SLOT(fractionChanged(int))); - - // clear all existing items before adding new ones - ui->m_dateCol->clear(); - ui->m_priceCol->clear(); + const QHash columns {{Column::Price, ui->m_priceCol}, {Column::Date, ui->m_dateCol}}; - QStringList columnNumbers; - for (int i = 0; i < m_imp->m_file->m_columnCount; ++i) - columnNumbers.append(QString::number(i + 1)); + if (ui->m_dateCol->count() != m_imp->m_file->m_columnCount) + m_dlg->initializeComboBoxes(columns); - // populate comboboxes with col # values - ui->m_dateCol->addItems(columnNumbers); - ui->m_priceCol->addItems(columnNumbers); + for (auto it = columns.cbegin(); it != columns.cend(); ++it) + it.value()->setCurrentIndex(m_profile->m_colTypeNum.value(it.key())); - clearColumns(); // all comboboxes are set to 0 so set them to -1 - connect(ui->m_dateCol, SIGNAL(currentIndexChanged(int)), this, SLOT(dateColSelected(int))); - connect(ui->m_priceCol, SIGNAL(currentIndexChanged(int)), this, SLOT(priceColSelected(int))); - connect(ui->m_priceFraction, SIGNAL(currentIndexChanged(int)), this, SLOT(fractionChanged(int))); -} - -void PricesPage::initializePage() -{ - if (ui->m_dateCol->count() != m_imp->m_file->m_columnCount) - initializeComboBoxes(); - ui->m_dateCol->setCurrentIndex(m_imp->m_profile->m_colTypeNum.value(ColumnDate)); - ui->m_priceCol->setCurrentIndex(m_imp->m_profile->m_colTypeNum.value(ColumnPrice)); ui->m_priceFraction->blockSignals(true); foreach (const auto priceFraction, m_imp->m_priceFractions) ui->m_priceFraction->addItem(QString::number(priceFraction.toDouble(), 'g', 3)); @@ -122,23 +101,23 @@ bool PricesPage::validatePage() { switch (m_imp->m_profile->type()) { - case ProfileCurrencyPrices: + case Profile::CurrencyPrices: return validateCurrencies(); - case ProfileStockPrices: + case Profile::StockPrices: return validateSecurity(); default: return false; } } void PricesPage::dateColSelected(int col) { - validateSelectedColumn(col, ColumnDate); + validateSelectedColumn(col, Column::Date); } void PricesPage::priceColSelected(int col) { - validateSelectedColumn(col, ColumnPrice); + validateSelectedColumn(col, Column::Price); } void PricesPage::fractionChanged(int col) @@ -154,24 +133,24 @@ ui->m_priceFraction->setCurrentIndex(-1); } -void PricesPage::resetComboBox(const columnTypeE comboBox) +void PricesPage::resetComboBox(const Column comboBox) { switch (comboBox) { - case ColumnDate: + case Column::Date: ui->m_dateCol->setCurrentIndex(-1); break; - case ColumnPrice: + case Column::Price: ui->m_priceCol->setCurrentIndex(-1); break; default: - KMessageBox::sorry(m_dlg, i18n("
Field name not recognised.
'%1'
Please re-enter your column selections.", comboBox), i18n("CSV import")); + KMessageBox::sorry(m_dlg, i18n("
Field name not recognised.
'%1'
Please re-enter your column selections.", (int)comboBox), i18n("CSV import")); } } -bool PricesPage::validateSelectedColumn(const int col, const columnTypeE type) +bool PricesPage::validateSelectedColumn(const int col, const Column type) { - QMap &colTypeNum = m_imp->m_profile->m_colTypeNum; - QMap &colNumType = m_imp->m_profile->m_colNumType; + QMap &colTypeNum = m_imp->m_profile->m_colTypeNum; + QMap &colNumType = m_imp->m_profile->m_colNumType; if (colTypeNum.value(type) != -1) // check if this 'type' has any column 'number' assigned... colNumType.remove(colTypeNum.value(type)); // ...if true remove 'type' assigned to this column 'number' diff --git a/kmymoney/plugins/csvimport/tests/CMakeLists.txt b/kmymoney/plugins/csvimport/tests/CMakeLists.txt --- a/kmymoney/plugins/csvimport/tests/CMakeLists.txt +++ b/kmymoney/plugins/csvimport/tests/CMakeLists.txt @@ -5,7 +5,6 @@ NAME_PREFIX "csvimport-" LINK_LIBRARIES - Qt5::Core Qt5::Test - kmm_csvimport_static + kmm_csvimport_core ) diff --git a/kmymoney/plugins/csvimport/tests/csvdate-test.cpp b/kmymoney/plugins/csvimport/tests/csvdate-test.cpp --- a/kmymoney/plugins/csvimport/tests/csvdate-test.cpp +++ b/kmymoney/plugins/csvimport/tests/csvdate-test.cpp @@ -36,7 +36,7 @@ void CsvDateTest::testConvertDate() { - m_convert->setDateFormatIndex(0); // ISO date format + m_convert->setDateFormatIndex(DateFormat::YearMonthDay); // ISO date format QVERIFY(m_convert->convertDate("2001-11-30") == QDate(2001, 11, 30)); QVERIFY(m_convert->convertDate("20011130") == QDate(2001, 11, 30)); @@ -50,14 +50,14 @@ QVERIFY(m_convert->convertDate("11-30-2001") == QDate()); QVERIFY(m_convert->convertDate("11302001") == QDate()); - m_convert->setDateFormatIndex(1); // US date format + m_convert->setDateFormatIndex(DateFormat::MonthDayYear); // US date format QVERIFY(m_convert->convertDate("2001-11-30") == QDate()); QVERIFY(m_convert->convertDate("20011130") == QDate()); QVERIFY(m_convert->convertDate("11-30-2001") == QDate(2001, 11, 30)); QVERIFY(m_convert->convertDate("11302001") == QDate(2001, 11, 30)); - m_convert->setDateFormatIndex(2); // UK/EU date format; + m_convert->setDateFormatIndex(DateFormat::DayMonthYear); // UK/EU date format; QVERIFY(m_convert->convertDate("13/09/81") == QDate(1981, 9, 13)); QVERIFY(m_convert->convertDate("13/09/01") == QDate(2001, 9, 13)); diff --git a/kmymoney/plugins/csvimport/tests/parsedata-test.cpp b/kmymoney/plugins/csvimport/tests/parsedata-test.cpp --- a/kmymoney/plugins/csvimport/tests/parsedata-test.cpp +++ b/kmymoney/plugins/csvimport/tests/parsedata-test.cpp @@ -39,9 +39,9 @@ void ParseDataTest::parseSplitString() { - for (int i = 0; i <= 3; i++) { // All four delimiters should produce same result - m_parse->setFieldDelimiterIndex(i); - m_parse->setFieldDelimiterCharacter(i); + QVector delimiters {FieldDelimiter::Comma, FieldDelimiter::Semicolon, FieldDelimiter::Colon, FieldDelimiter::Tab}; + foreach (const auto delimiter, delimiters) { // All four delimiters should produce same result + m_parse->setFieldDelimiter(delimiter); QString input = "abc,defgh,";// When this string is QString::split(), two strings // ....will result if ',' is the field delimiter. diff --git a/kmymoney/plugins/csvimport/tests/symbol-test.cpp b/kmymoney/plugins/csvimport/tests/symbol-test.cpp --- a/kmymoney/plugins/csvimport/tests/symbol-test.cpp +++ b/kmymoney/plugins/csvimport/tests/symbol-test.cpp @@ -32,7 +32,7 @@ void SymbolTest::init() { m_parse = new Parse; - m_parse->setDecimalSymbol(0); + m_parse->setDecimalSymbol(DecimalSymbol::Dot); m_localeDecimal = QLocale().decimalPoint(); m_localeThousands = QLocale().groupSeparator(); } @@ -46,8 +46,7 @@ { // Detect '.' as decimal and replace from locale - m_parse->setDecimalSymbol(0); // "." - m_parse->setThousandsSeparator(0); + m_parse->setDecimalSymbol(DecimalSymbol::Dot); // "." QFETCH(QString, input); QFETCH(QString, result); @@ -59,8 +58,7 @@ { // Detect ',' as decimal and replace from locale - m_parse->setDecimalSymbol(1); // "," - m_parse->setThousandsSeparator(1); + m_parse->setDecimalSymbol(DecimalSymbol::Comma); // "," QFETCH(QString, input); QFETCH(QString, result); @@ -72,9 +70,8 @@ { // Check for ',' as decimal, and none present - m_parse->setDecimalSymbol(1); // "," - m_parse->setThousandsSeparator(1); - m_testDecimal = m_parse->decimalSymbol(1); + m_parse->setDecimalSymbol(DecimalSymbol::Comma); // "," + m_testDecimal = m_parse->decimalSymbol(DecimalSymbol::Comma); QFETCH(QString, input); QFETCH(QString, result);