diff --git a/kmymoney/dialogs/kavailablecurrencydlg.ui b/kmymoney/dialogs/kavailablecurrencydlg.ui index ddba3fc9f..63048544e 100644 --- a/kmymoney/dialogs/kavailablecurrencydlg.ui +++ b/kmymoney/dialogs/kavailablecurrencydlg.ui @@ -1,102 +1,102 @@ KAvailableCurrencyDlg 0 0 400 516 Select currencies to add true 1 1 QAbstractItemView::NoEditTriggers QAbstractItemView::ExtendedSelection false true Name ID - Symbol + Symbol QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox accepted() KAvailableCurrencyDlg accept() 199 492 199 257 buttonBox rejected() KAvailableCurrencyDlg reject() 199 492 199 257 diff --git a/kmymoney/dialogs/kcurrencyeditdlg.ui b/kmymoney/dialogs/kcurrencyeditdlg.ui index 919c6b286..0e2a9428d 100644 --- a/kmymoney/dialogs/kcurrencyeditdlg.ui +++ b/kmymoney/dialogs/kcurrencyeditdlg.ui @@ -1,146 +1,146 @@ KCurrencyEditDlg 0 0 400 516 Currencies true 1 1 Qt::CustomContextMenu QAbstractItemView::ExtendedSelection false true Name ID - Symbol + Symbol Remove .. Add .. Edit Remove unused currencies .. Close Select as base currency m_currencyList m_addCurrencyButton m_removeCurrencyButton m_editCurrencyButton m_removeUnusedCurrencyButton m_selectBaseCurrencyButton m_closeButton m_closeButton clicked() KCurrencyEditDlg reject() 296 488 199 257 diff --git a/kmymoney/dialogs/kequitypriceupdatedlg.ui b/kmymoney/dialogs/kequitypriceupdatedlg.ui index c07429a2f..e1d2aae1a 100644 --- a/kmymoney/dialogs/kequitypriceupdatedlg.ui +++ b/kmymoney/dialogs/kequitypriceupdatedlg.ui @@ -1,197 +1,197 @@ Kevin Tambascio <ktambascio@users.sourceforge.net> KEquityPriceUpdateDlg 0 0 537 482 Update Stock and Currency Prices 350 0 List of known Equities, and the date they were last updated on. QFrame::StyledPanel QFrame::Plain true false true true 1 - From + From - To + To Configure Qt::Horizontal QSizePolicy::Expanding 21 20 Update All Update Selected Status: false true QDialogButtonBox::Cancel|QDialogButtonBox::Ok KTextEdit QTextEdit
ktextedit.h
KMyMoneyDateInput QWidget
kmymoneydateinput.h
1
buttonBox accepted() KEquityPriceUpdateDlg accept() 268 458 268 240 buttonBox rejected() KEquityPriceUpdateDlg reject() 268 458 268 240
diff --git a/kmymoney/dialogs/settings/ksettingsonlinequotes.cpp b/kmymoney/dialogs/settings/ksettingsonlinequotes.cpp index 040db4aba..15a8d557b 100644 --- a/kmymoney/dialogs/settings/ksettingsonlinequotes.cpp +++ b/kmymoney/dialogs/settings/ksettingsonlinequotes.cpp @@ -1,377 +1,377 @@ /* * Copyright 2005-2010 Thomas Baumgart * Copyright 2017-2018 Łukasz Wojniłowicz * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "ksettingsonlinequotes.h" // ---------------------------------------------------------------------------- // QT Includes #include #include // ---------------------------------------------------------------------------- // KDE Includes #include #include #include // ---------------------------------------------------------------------------- // Project Includes #include "ui_ksettingsonlinequotes.h" #include "kmymoney/converter/webpricequote.h" #include "mymoneyfile.h" #include "mymoneysecurity.h" #include "icons/icons.h" using namespace Icons; class KSettingsOnlineQuotesPrivate { Q_DISABLE_COPY(KSettingsOnlineQuotesPrivate) public: KSettingsOnlineQuotesPrivate() : ui(new Ui::KSettingsOnlineQuotes), m_quoteInEditing(false) { } ~KSettingsOnlineQuotesPrivate() { delete ui; } Ui::KSettingsOnlineQuotes *ui; QList m_resetList; WebPriceQuoteSource m_currentItem; bool m_quoteInEditing; }; KSettingsOnlineQuotes::KSettingsOnlineQuotes(QWidget *parent) : QWidget(parent), d_ptr(new KSettingsOnlineQuotesPrivate) { Q_D(KSettingsOnlineQuotes); d->ui->setupUi(this); QStringList groups = WebPriceQuote::quoteSources(); loadList(true /*updateResetList*/); d->ui->m_updateButton->setEnabled(false); d->ui->m_updateButton->setIcon(Icons::get(Icon::DialogOK)); d->ui->m_deleteButton->setIcon(Icons::get(Icon::EditDelete)); d->ui->m_newButton->setIcon(Icons::get(Icon::DocumentNew)); - d->ui->m_editIdentifyBy->addItem(i18n("Symbol"), WebPriceQuoteSource::identifyBy::Symbol); - d->ui->m_editIdentifyBy->addItem(i18n("Identification number"), WebPriceQuoteSource::identifyBy::IdentificationNumber); - d->ui->m_editIdentifyBy->addItem(i18n("Name"), WebPriceQuoteSource::identifyBy::Name); + d->ui->m_editIdentifyBy->addItem(i18nc("@item:inlistbox Stock", "Symbol"), WebPriceQuoteSource::identifyBy::Symbol); + d->ui->m_editIdentifyBy->addItem(i18nc("@item:inlistbox Stock", "Identification number"), WebPriceQuoteSource::identifyBy::IdentificationNumber); + d->ui->m_editIdentifyBy->addItem(i18nc("@item:inlistbox Stock", "Name"), WebPriceQuoteSource::identifyBy::Name); connect(d->ui->m_dumpCSVProfile, &QAbstractButton::clicked, this, &KSettingsOnlineQuotes::slotDumpCSVProfile); connect(d->ui->m_updateButton, &QAbstractButton::clicked, this, &KSettingsOnlineQuotes::slotUpdateEntry); connect(d->ui->m_newButton, &QAbstractButton::clicked, this, &KSettingsOnlineQuotes::slotNewEntry); connect(d->ui->m_deleteButton, &QAbstractButton::clicked, this, &KSettingsOnlineQuotes::slotDeleteEntry); connect(d->ui->m_quoteSourceList, &QListWidget::itemSelectionChanged, this, &KSettingsOnlineQuotes::slotLoadWidgets); connect(d->ui->m_quoteSourceList, &QListWidget::itemChanged, this, &KSettingsOnlineQuotes::slotEntryRenamed); connect(d->ui->m_quoteSourceList, &QListWidget::itemDoubleClicked, this, &KSettingsOnlineQuotes::slotStartRename); connect(d->ui->m_editURL, &QLineEdit::textChanged, this, static_cast(&KSettingsOnlineQuotes::slotEntryChanged)); connect(d->ui->m_editCSVURL, &QLineEdit::textChanged, this, static_cast(&KSettingsOnlineQuotes::slotEntryChanged)); connect(d->ui->m_editIdentifier, &QLineEdit::textChanged, this, static_cast(&KSettingsOnlineQuotes::slotEntryChanged)); connect(d->ui->m_editIdentifyBy, static_cast(&QComboBox::currentIndexChanged), this, static_cast(&KSettingsOnlineQuotes::slotEntryChanged)); connect(d->ui->m_editDate, &QLineEdit::textChanged, this, static_cast(&KSettingsOnlineQuotes::slotEntryChanged)); connect(d->ui->m_editDateFormat, &QLineEdit::textChanged, this, static_cast(&KSettingsOnlineQuotes::slotEntryChanged)); connect(d->ui->m_editPrice, &QLineEdit::textChanged, this, static_cast(&KSettingsOnlineQuotes::slotEntryChanged)); connect(d->ui->m_skipStripping, &QAbstractButton::toggled, this, static_cast(&KSettingsOnlineQuotes::slotEntryChanged)); } KSettingsOnlineQuotes::~KSettingsOnlineQuotes() { Q_D(KSettingsOnlineQuotes); delete d; } void KSettingsOnlineQuotes::loadList(const bool updateResetList) { Q_D(KSettingsOnlineQuotes); //disconnect the slot while items are being loaded and reconnect at the end disconnect(d->ui->m_quoteSourceList, &QListWidget::itemChanged, this, &KSettingsOnlineQuotes::slotEntryRenamed); d->m_quoteInEditing = false; QStringList groups = WebPriceQuote::quoteSources(); if (updateResetList) d->m_resetList.clear(); d->ui->m_quoteSourceList->clear(); QStringList::Iterator it; for (it = groups.begin(); it != groups.end(); ++it) { QListWidgetItem* item = new QListWidgetItem(*it); item->setFlags(Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsEnabled); d->ui->m_quoteSourceList->addItem(item); if (updateResetList) d->m_resetList += WebPriceQuoteSource(*it); } d->ui->m_quoteSourceList->sortItems(); QListWidgetItem* first = d->ui->m_quoteSourceList->item(0); if (first) d->ui->m_quoteSourceList->setCurrentItem(first); slotLoadWidgets(); d->ui->m_newButton->setEnabled((d->ui->m_quoteSourceList->findItems(i18n("New Quote Source"), Qt::MatchExactly)).count() == 0); connect(d->ui->m_quoteSourceList, &QListWidget::itemChanged, this, &KSettingsOnlineQuotes::slotEntryRenamed); } void KSettingsOnlineQuotes::resetConfig() { Q_D(KSettingsOnlineQuotes); QStringList::ConstIterator it; QStringList groups = WebPriceQuote::quoteSources(); // delete all currently defined entries for (it = groups.constBegin(); it != groups.constEnd(); ++it) { WebPriceQuoteSource(*it).remove(); } // and write back the one's from the reset list QList::ConstIterator itr; for (itr = d->m_resetList.constBegin(); itr != d->m_resetList.constEnd(); ++itr) { (*itr).write(); } loadList(); } void KSettingsOnlineQuotes::slotLoadWidgets() { Q_D(KSettingsOnlineQuotes); d->m_quoteInEditing = false; QListWidgetItem* item = d->ui->m_quoteSourceList->currentItem(); d->ui->m_editURL->setEnabled(true); d->ui->m_editCSVURL->setEnabled(true); d->ui->m_editIdentifier->setEnabled(true); d->ui->m_editIdentifyBy->setEnabled(true); d->ui->m_editPrice->setEnabled(true); d->ui->m_editDate->setEnabled(true); d->ui->m_editDateFormat->setEnabled(true); d->ui->m_skipStripping->setEnabled(true); d->ui->m_dumpCSVProfile->setEnabled(true); d->ui->m_deleteButton->setEnabled(true); d->ui->m_editURL->setText(QString()); d->ui->m_editCSVURL->setText(QString()); d->ui->m_editIdentifier->setText(QString()); d->ui->m_editIdentifyBy->setCurrentIndex(WebPriceQuoteSource::identifyBy::Symbol); d->ui->m_editPrice->setText(QString()); d->ui->m_editDate->setText(QString()); d->ui->m_editDateFormat->setText(QString()); if (item) { d->m_currentItem = WebPriceQuoteSource(item->text()); d->ui->m_editURL->setText(d->m_currentItem.m_url); d->ui->m_editCSVURL->setText(d->m_currentItem.m_csvUrl); d->ui->m_editIdentifier->setText(d->m_currentItem.m_webID); d->ui->m_editIdentifyBy->setCurrentIndex(d->m_currentItem.m_webIDBy); d->ui->m_editPrice->setText(d->m_currentItem.m_price); d->ui->m_editDate->setText(d->m_currentItem.m_date); d->ui->m_editDateFormat->setText(d->m_currentItem.m_dateformat); d->ui->m_skipStripping->setChecked(d->m_currentItem.m_skipStripping); } else { d->ui->m_editURL->setEnabled(false); d->ui->m_editCSVURL->setEnabled(false); d->ui->m_editIdentifier->setEnabled(false); d->ui->m_editIdentifyBy->setEnabled(false); d->ui->m_editPrice->setEnabled(false); d->ui->m_editDate->setEnabled(false); d->ui->m_editDateFormat->setEnabled(false); d->ui->m_skipStripping->setEnabled(false); d->ui->m_dumpCSVProfile->setEnabled(false); d->ui->m_deleteButton->setEnabled(false); } d->ui->m_updateButton->setEnabled(false); } void KSettingsOnlineQuotes::slotEntryChanged() { Q_D(KSettingsOnlineQuotes); bool modified = d->ui->m_editURL->text() != d->m_currentItem.m_url || d->ui->m_editCSVURL->text() != d->m_currentItem.m_csvUrl || d->ui->m_editIdentifier->text() != d->m_currentItem.m_webID || d->ui->m_editIdentifyBy->currentData().toInt() != static_cast(d->m_currentItem.m_webIDBy) || d->ui->m_editDate->text() != d->m_currentItem.m_date || d->ui->m_editDateFormat->text() != d->m_currentItem.m_dateformat || d->ui->m_editPrice->text() != d->m_currentItem.m_price || d->ui->m_skipStripping->isChecked() != d->m_currentItem.m_skipStripping; d->ui->m_updateButton->setEnabled(modified); } void KSettingsOnlineQuotes::slotEntryChanged(int) { slotEntryChanged(); } void KSettingsOnlineQuotes::slotEntryChanged(const QString&) { slotEntryChanged(); } void KSettingsOnlineQuotes::slotEntryChanged(bool) { slotEntryChanged(); } void KSettingsOnlineQuotes::slotDumpCSVProfile() { Q_D(KSettingsOnlineQuotes); KSharedConfigPtr config = CSVImporterCore::configFile(); PricesProfile profile; profile.m_profileName = d->m_currentItem.m_name; profile.m_profileType = Profile::StockPrices; bool profileExists = false; bool writeProfile = true; if (profile.readSettings(config)) profileExists = true; else { profile.m_profileType = Profile::CurrencyPrices; if (profile.readSettings(config)) profileExists = true; } if (profileExists) writeProfile = (KMessageBox::questionYesNoCancel(this, i18n("CSV profile %1 already exists.
" "Do you want to overwrite it?", d->m_currentItem.m_name), i18n("CSV Profile Already Exists")) == KMessageBox::Yes ? true : false); if (writeProfile) { QMap quoteSources = WebPriceQuote::defaultCSVQuoteSources(); profile = quoteSources.value(d->m_currentItem.m_name); if (profile.m_profileName.compare(d->m_currentItem.m_name, Qt::CaseInsensitive) == 0) { profile.writeSettings(config); CSVImporterCore::profilesAction(profile.type(), ProfileAction::Add, profile.m_profileName, profile.m_profileName); } } CSVImporterCore::profilesAction(profile.type(), ProfileAction::UpdateLastUsed, profile.m_profileName, profile.m_profileName); } void KSettingsOnlineQuotes::slotUpdateEntry() { Q_D(KSettingsOnlineQuotes); d->m_currentItem.m_url = d->ui->m_editURL->text(); d->m_currentItem.m_csvUrl = d->ui->m_editCSVURL->text(); d->m_currentItem.m_webID = d->ui->m_editIdentifier->text(); d->m_currentItem.m_webIDBy = static_cast(d->ui->m_editIdentifyBy->currentData().toInt()); d->m_currentItem.m_date = d->ui->m_editDate->text(); d->m_currentItem.m_dateformat = d->ui->m_editDateFormat->text(); d->m_currentItem.m_price = d->ui->m_editPrice->text(); d->m_currentItem.m_skipStripping = d->ui->m_skipStripping->isChecked(); d->m_currentItem.write(); slotEntryChanged(); } void KSettingsOnlineQuotes::slotNewEntry() { Q_D(KSettingsOnlineQuotes); WebPriceQuoteSource newSource(i18n("New Quote Source")); newSource.write(); loadList(); QListWidgetItem* item = d->ui->m_quoteSourceList->findItems(i18n("New Quote Source"), Qt::MatchExactly).at(0); if (item) { d->ui->m_quoteSourceList->setCurrentItem(item); slotLoadWidgets(); } } void KSettingsOnlineQuotes::slotDeleteEntry() { Q_D(KSettingsOnlineQuotes); // first check if no security is using this online source auto securities = MyMoneyFile::instance()->securityList(); foreach(const auto security, securities) { if (security.value(QStringLiteral("kmm-online-source")).compare(d->m_currentItem.m_name) == 0) { if (KMessageBox::questionYesNo(this, i18n("Security %1 uses this quote source.
" "Do you really want to remove it?", security.name()), i18n("Delete quote source")) == KMessageBox::Yes) break; // webpricequote can handle missing online quotes, so proceed without any extra action else return; } } // remove online source from webpricequote... d->m_currentItem.remove(); // ...and from setting's list auto row = d->ui->m_quoteSourceList->currentRow(); QListWidgetItem *item = d->ui->m_quoteSourceList->takeItem(row); if (item) delete item; item = nullptr; int count = d->ui->m_quoteSourceList->count(); if (row < count) // select next available entry... item = d->ui->m_quoteSourceList->item(row); else if (row >= count && count > 0) // ...or last entry if this was the last entry... item = d->ui->m_quoteSourceList->item(count - 1); if (item) { d->ui->m_quoteSourceList->setCurrentItem(item); slotLoadWidgets(); } } void KSettingsOnlineQuotes::slotStartRename(QListWidgetItem* item) { Q_D(KSettingsOnlineQuotes); d->m_quoteInEditing = true; d->ui->m_quoteSourceList->editItem(item); } void KSettingsOnlineQuotes::slotEntryRenamed(QListWidgetItem* item) { Q_D(KSettingsOnlineQuotes); //if there is no current item selected, exit if (d->m_quoteInEditing == false || !d->ui->m_quoteSourceList->currentItem() || item != d->ui->m_quoteSourceList->currentItem()) return; d->m_quoteInEditing = false; QString text = item->text(); int nameCount = 0; for (auto i = 0; i < d->ui->m_quoteSourceList->count(); ++i) { if (d->ui->m_quoteSourceList->item(i)->text() == text) ++nameCount; } // Make sure we get a non-empty and unique name if (text.length() > 0 && nameCount == 1) { d->m_currentItem.rename(text); } else { item->setText(d->m_currentItem.m_name); } d->ui->m_quoteSourceList->sortItems(); d->ui->m_newButton->setEnabled(d->ui->m_quoteSourceList->findItems(i18n("New Quote Source"), Qt::MatchExactly).count() == 0); } diff --git a/kmymoney/models/equitiesmodel.cpp b/kmymoney/models/equitiesmodel.cpp index 0bd0b0646..e82b96668 100644 --- a/kmymoney/models/equitiesmodel.cpp +++ b/kmymoney/models/equitiesmodel.cpp @@ -1,489 +1,489 @@ /* * Copyright 2017-2018 Łukasz Wojniłowicz * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "equitiesmodel.h" // ---------------------------------------------------------------------------- // QT Includes #include #include // ---------------------------------------------------------------------------- // KDE Includes #include // ---------------------------------------------------------------------------- // Project Includes #include "mymoneymoney.h" #include "mymoneyfile.h" #include "mymoneyaccount.h" #include "mymoneysecurity.h" #include "mymoneyprice.h" #include "mymoneyenums.h" class EquitiesModel::Private { public: Private() : m_file(MyMoneyFile::instance()) { QVector columns {Column::Equity, Column::Symbol, Column::Value, Column::Quantity, Column::Price}; foreach (auto const column, columns) m_columns.append(column); } ~Private() {} void loadInvestmentAccount(QStandardItem *node, const MyMoneyAccount &invAcc) { auto itInvAcc = new QStandardItem(invAcc.name()); node->appendRow(itInvAcc); // investment account is meant to be added under root item itInvAcc->setEditable(false); itInvAcc->setColumnCount(m_columns.count()); setAccountData(node, itInvAcc->row(), invAcc, m_columns); foreach (const auto strStkAcc, invAcc.accountList()) { // only stock or bond accounts are expected here auto stkAcc = m_file->account(strStkAcc); auto itStkAcc = new QStandardItem(strStkAcc); itStkAcc->setEditable(false); itInvAcc->appendRow(itStkAcc); setAccountData(itInvAcc, itStkAcc->row(), stkAcc, m_columns); } } void setAccountData(QStandardItem *node, const int row, const MyMoneyAccount &account, const QList &columns) { QStandardItem *cell; auto getCell = [&, row](const auto column) { cell = node->child(row, column); // try to get QStandardItem if (!cell) { // it may be uninitialized cell = new QStandardItem; // so create one node->setChild(row, column, cell); // and add it under the node cell->setEditable(false); // and don't forget that it's non-editable } }; auto colNum = m_columns.indexOf(Column::Equity); if (colNum == -1) return; // Equity getCell(colNum); if (columns.contains(Column::Equity)) { cell->setData(account.name(), Qt::DisplayRole); cell->setData(account.id(), Role::EquityID); cell->setData(account.currencyId(), Role::SecurityID); } if (account.accountType() == eMyMoney::Account::Type::Investment) // investments accounts are not meant to be displayed, so stop here return; // Display the name of the equity with strikeout font in case it is closed auto font = cell->data(Qt::FontRole).value(); if (account.isClosed() != font.strikeOut()) { font.setStrikeOut(account.isClosed()); cell->setData(font, Qt::FontRole); } // Symbol if (columns.contains(Column::Symbol)) { colNum = m_columns.indexOf(Column::Symbol); if (colNum != -1) { auto security = m_file->security(account.currencyId()); getCell(colNum); cell->setData(security.tradingSymbol(), Qt::DisplayRole); } } setAccountBalanceAndValue(node, row, account, columns); } void setAccountBalanceAndValue(QStandardItem *node, const int row, const MyMoneyAccount &account, const QList &columns) { QStandardItem *cell; auto getCell = [&, row](const auto column) { cell = node->child(row, column); // try to get QStandardItem if (!cell) { // it may be uninitialized cell = new QStandardItem; // so create one node->setChild(row, column, cell); // and add it under the node cell->setEditable(false); // and don't forget that it's non-editable } }; auto colNum = m_columns.indexOf(Column::Equity); if (colNum == -1) return; auto balance = m_file->balance(account.id()); auto security = m_file->security(account.currencyId()); auto tradingCurrency = m_file->security(security.tradingCurrency()); auto price = m_file->price(account.currencyId(), tradingCurrency.id()); // Value if (columns.contains(Column::Value)) { colNum = m_columns.indexOf(Column::Value); if (colNum != -1) { getCell(colNum); if (price.isValid()) { auto prec = MyMoneyMoney::denomToPrec(tradingCurrency.smallestAccountFraction()); auto value = balance * price.rate(tradingCurrency.id()); auto strValue = QVariant(value.formatMoney(tradingCurrency.tradingSymbol(), prec)); cell->setData(strValue, Qt::DisplayRole); } else { cell->setData(QVariant("---"), Qt::DisplayRole); } cell->setData(QVariant(Qt::AlignRight | Qt::AlignVCenter), Qt::TextAlignmentRole); } } // Quantity if (columns.contains(Column::Quantity)) { colNum = m_columns.indexOf(Column::Quantity); if (colNum != -1) { getCell(colNum); auto prec = MyMoneyMoney::denomToPrec(security.smallestAccountFraction()); auto strQuantity = QVariant(balance.formatMoney(QString(), prec)); cell->setData(strQuantity, Qt::DisplayRole); cell->setData(QVariant(Qt::AlignRight | Qt::AlignVCenter), Qt::TextAlignmentRole); } } // Price if (columns.contains(Column::Price)) { colNum = m_columns.indexOf(Column::Price); if (colNum != -1) { getCell(colNum); if (price.isValid()) { auto prec = security.pricePrecision(); auto strPrice = QVariant(price.rate(tradingCurrency.id()).formatMoney(tradingCurrency.tradingSymbol(), prec)); cell->setData(strPrice, Qt::DisplayRole); } else { cell->setData(QVariant("---"), Qt::DisplayRole); } cell->setData(QVariant(Qt::AlignRight | Qt::AlignVCenter), Qt::TextAlignmentRole); } } } QStandardItem *itemFromId(QStandardItemModel *model, const QString &id, const Role role) { const auto itemList = model->match(model->index(0, 0), role, QVariant(id), 1, Qt::MatchFlags(Qt::MatchExactly | Qt::MatchCaseSensitive | Qt::MatchRecursive)); if (!itemList.isEmpty()) return model->itemFromIndex(itemList.first()); return nullptr; } MyMoneyFile *m_file; QList m_columns; }; EquitiesModel::EquitiesModel(QObject *parent) : QStandardItemModel(parent), d(new Private) { init(); } EquitiesModel::~EquitiesModel() { delete d; } void EquitiesModel::init() { QStringList headerLabels; foreach (const auto column, d->m_columns) headerLabels.append(getHeaderName(column)); setHorizontalHeaderLabels(headerLabels); } void EquitiesModel::load() { this->blockSignals(true); auto rootItem = invisibleRootItem(); QList accList; d->m_file->accountList(accList); // get all available accounts foreach (const auto acc, accList) if (acc.accountType() == eMyMoney::Account::Type::Investment) // but add only investment accounts (and its children) to the model d->loadInvestmentAccount(rootItem, acc); this->blockSignals(false); } /** * Notify the model that an object has been added. An action is performed only if the object is an account. */ void EquitiesModel::slotObjectAdded(eMyMoney::File::Object objType, const QString& id) { // check whether change is about accounts if (objType != eMyMoney::File::Object::Account) return; // check whether change is about either investment or stock account const auto acc = MyMoneyFile::instance()->account(id); if (acc.accountType() != eMyMoney::Account::Type::Investment && acc.accountType() != eMyMoney::Account::Type::Stock) return; auto itAcc = d->itemFromId(this, id, Role::EquityID); QStandardItem *itParentAcc; if (acc.accountType() == eMyMoney::Account::Type::Investment) // if it's investment account then its parent is root item itParentAcc = invisibleRootItem(); else // otherwise it's stock account and its parent is investment account itParentAcc = d->itemFromId(this, acc.parentAccountId(), Role::InvestmentID); // if account doesn't exist in model then add it if (!itAcc) { itAcc = new QStandardItem(acc.name()); itParentAcc->appendRow(itAcc); itAcc->setEditable(false); } d->setAccountData(itParentAcc, itAcc->row(), acc, d->m_columns); } /** * Notify the model that an object has been modified. An action is performed only if the object is an account. */ void EquitiesModel::slotObjectModified(eMyMoney::File::Object objType, const QString& id) { MyMoneyAccount acc; QStandardItem *itAcc; switch (objType) { case eMyMoney::File::Object::Account: { auto tmpAcc = MyMoneyFile::instance()->account(id); if (tmpAcc.accountType() != eMyMoney::Account::Type::Stock) return; acc = MyMoneyAccount(tmpAcc); itAcc = d->itemFromId(this, acc.id(), Role::EquityID); break; } case eMyMoney::File::Object::Security: { auto sec = MyMoneyFile::instance()->security(id); // in case we hit a currency, we simply bail out here // as there is nothing to do for us if(sec.isCurrency()) return; itAcc = d->itemFromId(this, sec.id(), Role::SecurityID); if (!itAcc) return; const auto idAcc = itAcc->data(Role::EquityID).toString(); acc = d->m_file->account(idAcc); break; } default: return; } auto itParentAcc = d->itemFromId(this, acc.parentAccountId(), Role::InvestmentID); // in case something went wrong, we bail out if(itParentAcc == nullptr) { qWarning() << "EquitiesModel::slotObjectModified: itParentAcc == 0"; return; } auto modelID = itParentAcc->data(Role::InvestmentID).toString(); // get parent account from model if (modelID == acc.parentAccountId()) { // and if it matches with those from file then modify only d->setAccountData(itParentAcc, itAcc->row(), acc, d->m_columns); } else { // and if not then reparent slotObjectRemoved(eMyMoney::File::Object::Account, acc.id()); slotObjectAdded(eMyMoney::File::Object::Account, id); } } /** * Notify the model that an object has been removed. An action is performed only if the object is an account. * */ void EquitiesModel::slotObjectRemoved(eMyMoney::File::Object objType, const QString& id) { if (objType != eMyMoney::File::Object::Account) return; const auto indexList = match(index(0, 0), Role::EquityID, id, -1, Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive)); foreach (const auto index, indexList) removeRow(index.row(), index.parent()); } /** * Notify the model that the account balance has been changed. */ void EquitiesModel::slotBalanceOrValueChanged(const MyMoneyAccount &account) { if (account.accountType() != eMyMoney::Account::Type::Stock) return; const auto itAcc = d->itemFromId(this, account.id(), Role::EquityID); if (!itAcc) return; d->setAccountBalanceAndValue(itAcc->parent(), itAcc->row(), account, d->m_columns); } auto EquitiesModel::getColumns() { return &d->m_columns; } QString EquitiesModel::getHeaderName(const Column column) { switch(column) { case Equity: return i18n("Equity"); case Symbol: - return i18n("Symbol"); + return i18nc("@title stock symbol column", "Symbol"); case Value: return i18n("Value"); case Quantity: return i18n("Quantity"); case Price: return i18n("Price"); default: return QString(); } } class EquitiesFilterProxyModel::Private { public: Private() : m_mdlColumns(nullptr), m_file(MyMoneyFile::instance()), m_hideClosedAccounts(false), m_hideZeroBalanceAccounts(false) {} ~Private() {} QList *m_mdlColumns; QList m_visColumns; MyMoneyFile *m_file; bool m_hideClosedAccounts; bool m_hideZeroBalanceAccounts; }; EquitiesFilterProxyModel::EquitiesFilterProxyModel(QObject *parent, EquitiesModel *model, const QList &columns) : KRecursiveFilterProxyModel(parent), d(new Private) { setDynamicSortFilter(true); setFilterKeyColumn(-1); setSortLocaleAware(true); setFilterCaseSensitivity(Qt::CaseInsensitive); setSourceModel(model); d->m_mdlColumns = model->getColumns(); d->m_visColumns.append(columns); } EquitiesFilterProxyModel::~EquitiesFilterProxyModel() { delete d; } /** * Set if closed accounts should be hidden or not. * @param hideClosedAccounts */ void EquitiesFilterProxyModel::setHideClosedAccounts(const bool hideClosedAccounts) { d->m_hideClosedAccounts = hideClosedAccounts; } /** * Set if zero balance accounts should be hidden or not. * @param hideZeroBalanceAccounts */ void EquitiesFilterProxyModel::setHideZeroBalanceAccounts(const bool hideZeroBalanceAccounts) { d->m_hideZeroBalanceAccounts = hideZeroBalanceAccounts; } bool EquitiesFilterProxyModel::filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const { Q_UNUSED(source_parent) if (d->m_visColumns.isEmpty() || d->m_visColumns.contains(d->m_mdlColumns->at(source_column))) return true; return false; } bool EquitiesFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { if (d->m_hideClosedAccounts || d->m_hideZeroBalanceAccounts) { const auto ixRow = sourceModel()->index(source_row, EquitiesModel::Equity, source_parent); const auto idAcc = sourceModel()->data(ixRow, EquitiesModel::EquityID).toString(); const auto acc = d->m_file->account(idAcc); if (d->m_hideClosedAccounts && acc.isClosed()) return false; if (d->m_hideZeroBalanceAccounts && acc.accountType() != eMyMoney::Account::Type::Investment && acc.balance().isZero()) // we should never hide investment account because all underlaying stocks will be hidden as well return false; } return true; } QList &EquitiesFilterProxyModel::getVisibleColumns() { return d->m_visColumns; } void EquitiesFilterProxyModel::slotColumnsMenu(const QPoint) { // construct all hideable columns list const QList idColumns { EquitiesModel::Symbol, EquitiesModel::Value, EquitiesModel::Quantity, EquitiesModel::Price }; // create menu QMenu menu(i18n("Displayed columns")); QList actions; foreach (const auto idColumn, idColumns) { auto a = new QAction(nullptr); a->setObjectName(QString::number(idColumn)); a->setText(EquitiesModel::getHeaderName(idColumn)); a->setCheckable(true); a->setChecked(d->m_visColumns.contains(idColumn)); actions.append(a); } menu.addActions(actions); // execute menu and get result const auto retAction = menu.exec(QCursor::pos()); if (retAction) { const auto idColumn = static_cast(retAction->objectName().toInt()); const auto isChecked = retAction->isChecked(); const auto contains = d->m_visColumns.contains(idColumn); if (isChecked && !contains) { // column has just been enabled d->m_visColumns.append(idColumn); // change filtering variable emit columnToggled(idColumn, true); // emit signal for method to add column to model invalidate(); // refresh model to reflect recent changes } else if (!isChecked && contains) { // column has just been disabled d->m_visColumns.removeOne(idColumn); emit columnToggled(idColumn, false); invalidate(); } } } diff --git a/kmymoney/models/securitiesmodel.cpp b/kmymoney/models/securitiesmodel.cpp index 097cca6fd..ed9c3a318 100644 --- a/kmymoney/models/securitiesmodel.cpp +++ b/kmymoney/models/securitiesmodel.cpp @@ -1,373 +1,373 @@ /* * Copyright 2017-2018 Łukasz Wojniłowicz * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "securitiesmodel.h" // ---------------------------------------------------------------------------- // QT Includes #include // ---------------------------------------------------------------------------- // KDE Includes #include // ---------------------------------------------------------------------------- // Project Includes #include "mymoneyfile.h" #include "mymoneysecurity.h" #include "mymoneyenums.h" class SecuritiesModel::Private { public: Private() : m_file(MyMoneyFile::instance()), m_ndCurrencies(nullptr), m_ndSecurities(nullptr) { QVector columns { Column::Security, Column::Symbol, Column::Type, Column::Market, Column::Currency, Column::Fraction }; foreach (auto const column, columns) m_columns.append(column); } ~Private() {} void loadSecurity(QStandardItem *node, const MyMoneySecurity &sec) { auto itSec = new QStandardItem(sec.name()); node->appendRow(itSec); itSec->setEditable(false); setSecurityData(node, itSec->row(), sec, m_columns); } void setSecurityData(QStandardItem *node, const int row, const MyMoneySecurity &security, const QList &columns) { QStandardItem *cell; auto getCell = [&, row](const auto column) { cell = node->child(row, column); // try to get QStandardItem if (!cell) { // it may be uninitialized cell = new QStandardItem; // so create one node->setChild(row, column, cell); // and add it under the node cell->setEditable(false); // and don't forget that it's non-editable } }; auto colNum = m_columns.indexOf(Column::Security); if (colNum == -1) return; // Security getCell(colNum); if (columns.contains(Column::Security)) { cell->setData(security.name(), Qt::DisplayRole); cell->setData(security.id(), Qt::UserRole); } // Symbol if (columns.contains(Column::Symbol)) { colNum = m_columns.indexOf(Column::Symbol); if (colNum != -1) { getCell(colNum); cell->setData(security.tradingSymbol(), Qt::DisplayRole); } } // Type if (columns.contains(Column::Type)) { colNum = m_columns.indexOf(Column::Type); if (colNum != -1) { getCell(colNum); cell->setData(security.securityTypeToString(security.securityType()), Qt::DisplayRole); } } // Market if (columns.contains(Column::Market)) { colNum = m_columns.indexOf(Column::Market); if (colNum != -1) { getCell(colNum); QString market; if (security.isCurrency()) market = QLatin1String("ISO 4217"); else market = security.tradingMarket(); cell->setData(market, Qt::DisplayRole); } } // Currency if (columns.contains(Column::Currency)) { colNum = m_columns.indexOf(Column::Currency); if (colNum != -1) { getCell(colNum); MyMoneySecurity tradingCurrency; if (!security.isCurrency()) tradingCurrency = m_file->security(security.tradingCurrency()); cell->setData(tradingCurrency.tradingSymbol(), Qt::DisplayRole); } } // Fraction if (columns.contains(Column::Fraction)) { colNum = m_columns.indexOf(Column::Fraction); if (colNum != -1) { getCell(colNum); cell->setData(QString::number(security.smallestAccountFraction()), Qt::DisplayRole); } } } QStandardItem *itemFromSecurityId(QStandardItemModel *model, const QString &securityId) { const auto itemList = model->match(model->index(0, 0), Qt::UserRole, QVariant(securityId), 1, Qt::MatchFlags(Qt::MatchExactly | Qt::MatchCaseSensitive | Qt::MatchRecursive)); if (!itemList.isEmpty()) return model->itemFromIndex(itemList.first()); return nullptr; } MyMoneyFile *m_file; QList m_columns; QStandardItem *m_ndCurrencies; QStandardItem *m_ndSecurities; }; SecuritiesModel::SecuritiesModel(QObject *parent) : QStandardItemModel(parent), d(new Private) { init(); } SecuritiesModel::~SecuritiesModel() { delete d; } void SecuritiesModel::init() { QStringList headerLabels; foreach (const auto column, d->m_columns) headerLabels.append(getHeaderName(column)); setHorizontalHeaderLabels(headerLabels); } void SecuritiesModel::load() { this->blockSignals(true); auto rootItem = invisibleRootItem(); auto secList = d->m_file->securityList(); // get all available securities d->m_ndSecurities = new QStandardItem(QStringLiteral("Securities")); d->m_ndSecurities->setEditable(false); rootItem->appendRow(d->m_ndSecurities); foreach (const auto sec, secList) d->loadSecurity(d->m_ndSecurities, sec); secList = d->m_file->currencyList(); // get all available currencies d->m_ndCurrencies = new QStandardItem(QStringLiteral("Currencies")); d->m_ndCurrencies->setEditable(false); rootItem->appendRow(d->m_ndCurrencies); foreach (const auto sec, secList) d->loadSecurity(d->m_ndCurrencies, sec); this->blockSignals(false); } /** * Notify the model that an object has been added. An action is performed only if the object is a security. * */ void SecuritiesModel::slotObjectAdded(eMyMoney::File::Object objType, const QString& id) { // check whether change is about security if (objType != eMyMoney::File::Object::Security) return; // check that we're about to add security auto sec = MyMoneyFile::instance()->security(id); auto itSec = d->itemFromSecurityId(this, id); QStandardItem *node; if (sec.isCurrency()) node = d->m_ndCurrencies; else node = d->m_ndSecurities; // if security doesn't exist in model then add it if (!itSec) { itSec = new QStandardItem(sec.name()); node->appendRow(itSec); itSec->setEditable(false); } d->setSecurityData(node, itSec->row(), sec, d->m_columns); } /** * Notify the model that an object has been modified. An action is performed only if the object is a security. * */ void SecuritiesModel::slotObjectModified(eMyMoney::File::Object objType, const QString& id) { if (objType != eMyMoney::File::Object::Security) return; // check that we're about to modify security auto sec = MyMoneyFile::instance()->security(id); auto itSec = d->itemFromSecurityId(this, id); QStandardItem *node; if (sec.isCurrency()) node = d->m_ndCurrencies; else node = d->m_ndSecurities; d->setSecurityData(node, itSec->row(), sec, d->m_columns); } /** * Notify the model that an object has been removed. An action is performed only if the object is an account. * */ void SecuritiesModel::slotObjectRemoved(eMyMoney::File::Object objType, const QString& id) { if (objType != eMyMoney::File::Object::Security) return; const auto indexList = match(index(0, 0), Qt::UserRole, id, -1, Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive)); foreach (const auto index, indexList) removeRow(index.row(), index.parent()); } auto SecuritiesModel::getColumns() { return &d->m_columns; } QString SecuritiesModel::getHeaderName(const Column column) { switch(column) { case Security: return i18n("Security"); case Symbol: - return i18n("Symbol"); + return i18nc("@title stock symbol column", "Symbol"); case Type: return i18n("Type"); case Market: return i18n("Market"); case Currency: return i18n("Currency"); case Fraction: return i18n("Fraction"); default: return QString(); } } class SecuritiesFilterProxyModel::Private { public: Private() : m_mdlColumns(nullptr), m_file(MyMoneyFile::instance()) {} ~Private() {} QList *m_mdlColumns; QList m_visColumns; MyMoneyFile *m_file; }; SecuritiesFilterProxyModel::SecuritiesFilterProxyModel(QObject *parent, SecuritiesModel *model, const QList &columns) : KRecursiveFilterProxyModel(parent), d(new Private) { setDynamicSortFilter(true); setFilterKeyColumn(-1); setSortLocaleAware(true); setFilterCaseSensitivity(Qt::CaseInsensitive); setSourceModel(model); d->m_mdlColumns = model->getColumns(); d->m_visColumns.append(columns); } SecuritiesFilterProxyModel::~SecuritiesFilterProxyModel() { delete d; } bool SecuritiesFilterProxyModel::filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const { Q_UNUSED(source_parent) if (d->m_visColumns.isEmpty() || d->m_visColumns.contains(d->m_mdlColumns->at(source_column))) return true; return false; } QList &SecuritiesFilterProxyModel::getVisibleColumns() { return d->m_visColumns; } void SecuritiesFilterProxyModel::slotColumnsMenu(const QPoint) { // construct all hideable columns list const QList idColumns { SecuritiesModel::Symbol, SecuritiesModel::Type, SecuritiesModel::Market, SecuritiesModel::Currency, SecuritiesModel::Fraction }; // create menu QMenu menu(i18n("Displayed columns")); QList actions; foreach (const auto idColumn, idColumns) { auto a = new QAction(nullptr); a->setObjectName(QString::number(idColumn)); a->setText(SecuritiesModel::getHeaderName(idColumn)); a->setCheckable(true); a->setChecked(d->m_visColumns.contains(idColumn)); actions.append(a); } menu.addActions(actions); // execute menu and get result const auto retAction = menu.exec(QCursor::pos()); if (retAction) { const auto idColumn = static_cast(retAction->objectName().toInt()); const auto isChecked = retAction->isChecked(); const auto contains = d->m_visColumns.contains(idColumn); if (isChecked && !contains) { // column has just been enabled d->m_visColumns.append(idColumn); // change filtering variable emit columnToggled(idColumn, true); // emit signal for method to add column to model invalidate(); // refresh model to reflect recent changes } else if (!isChecked && contains) { // column has just been disabled d->m_visColumns.removeOne(idColumn); emit columnToggled(idColumn, false); invalidate(); } } } diff --git a/kmymoney/plugins/csv/import/investmentwizardpage.cpp b/kmymoney/plugins/csv/import/investmentwizardpage.cpp index 537284f82..b0ef37cfe 100644 --- a/kmymoney/plugins/csv/import/investmentwizardpage.cpp +++ b/kmymoney/plugins/csv/import/investmentwizardpage.cpp @@ -1,665 +1,665 @@ /* * Copyright 2010-2017 Allan Anderson * Copyright 2016-2018 Łukasz Wojniłowicz * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "investmentwizardpage.h" // ---------------------------------------------------------------------------- // QT Includes #include #include #include #include // ---------------------------------------------------------------------------- // KDE Includes #include // ---------------------------------------------------------------------------- // Project Includes #include "mymoneyfile.h" #include "mymoneysecurity.h" #include "csvwizard.h" #include "core/csvimportercore.h" #include "transactiondlg.h" #include "securitydlg.h" #include "securitiesdlg.h" #include "ui_investmentwizardpage.h" #include "ui_securitiesdlg.h" #include "ui_securitydlg.h" // ---------------------------------------------------------------------------- InvestmentPage::InvestmentPage(CSVWizard *dlg, CSVImporterCore *imp) : CSVWizardPage(dlg, imp), ui(new Ui::InvestmentPage) { ui->setupUi(this); 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(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::Symbol, i18nc("@title stock symbol column", "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 m_securitiesDlg; delete ui; } void InvestmentPage::calculateFee() { m_imp->calculateFee(); m_dlg->updateWindowSize(); m_dlg->markUnwantedRows(); } 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) m_dlg->initializeComboBoxes(columns); ui->m_feeIsPercentage->setChecked(m_profile->m_feeIsPercentage); 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) ); ui->m_minFee->setValidator(new QRegularExpressionValidator(QRegularExpression(QStringLiteral("[0-9]{1,}[") + QLocale().decimalPoint() + QStringLiteral("]{0,1}[0-9]{0,}")), this) ); if (!m_profile->m_feeRate.isEmpty()) { // fee rate indicates that fee column needs to be calculated if (m_imp->calculateFee()) { ui->m_feeCol->blockSignals(true); int feeCol = ui->m_feeCol->count(); ui->m_feeCol->addItem(QString::number(feeCol + 1)); ui->m_feeCol->setEnabled(false); ui->m_feeCol->setCurrentIndex(feeCol); ui->m_feeCol->blockSignals(false); m_dlg->updateWindowSize(); m_dlg->markUnwantedRows(); } } else if (m_profile->m_colTypeNum.value(Column::Fee, -1) >= ui->m_feeCol->count()) { // no fee rate, calculated fee column index exist, but the column doesn't exist and that's not ok m_profile->m_colTypeNum[Column::Fee] = -1; m_profile->m_colNumType.remove(m_profile->m_colNumType.key(Column::Fee)); } for (int i = 0; i < m_profile->m_memoColList.count(); ++i) { // Set up all memo fields... int tmp = m_profile->m_memoColList.at(i); if (tmp < m_profile->m_colTypeNum.count()) ui->m_memoCol->setCurrentIndex(tmp); } feeInputsChanged(); } bool InvestmentPage::isComplete() const { return ui->m_dateCol->currentIndex() > -1 && ui->m_typeCol->currentIndex() > -1 && ui->m_quantityCol->currentIndex() > -1 && ui->m_priceCol->currentIndex() > -1 && ui->m_amountCol->currentIndex() > -1 && ui->m_priceFraction->currentIndex() > -1; } bool InvestmentPage::validatePage() { if (ui->m_symbolCol->currentIndex() == -1 && ui->m_nameCol->currentIndex() == -1) return validateSecurity(); else return validateSecurities(); } void InvestmentPage::cleanupPage() { clearFeeCol(); } void InvestmentPage::memoColSelected(int col) { 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.
" "
If you wish to copy that 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('*'))); 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(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(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, Column::Memo)) if (col != - 1 && !m_profile->m_memoColList.contains(col)) m_profile->m_memoColList.append(col); } void InvestmentPage::dateColSelected(int col) { validateSelectedColumn(col, Column::Date); } void InvestmentPage::feeColSelected(int col) { validateSelectedColumn(col, Column::Fee); feeInputsChanged(); } void InvestmentPage::typeColSelected(int col) { 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, Column::Quantity); } void InvestmentPage::priceColSelected(int col) { validateSelectedColumn(col, Column::Price); } void InvestmentPage::amountColSelected(int col) { validateSelectedColumn(col, Column::Amount); clearFeeCol(); feeInputsChanged(); } void InvestmentPage::symbolColSelected(int col) { 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, 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 } void InvestmentPage::feeIsPercentageClicked(bool checked) { m_profile->m_feeIsPercentage = checked; } void InvestmentPage::fractionChanged(int col) { m_profile->m_priceFraction = col; emit completeChanged(); } void InvestmentPage::clearColumns() { ui->m_amountCol->setCurrentIndex(-1); ui->m_dateCol->setCurrentIndex(-1); ui->m_priceCol->setCurrentIndex(-1); ui->m_quantityCol->setCurrentIndex(-1); ui->m_memoCol->setCurrentIndex(-1); ui->m_typeCol->setCurrentIndex(-1); ui->m_nameCol->setCurrentIndex(-1); ui->m_symbolCol->setCurrentIndex(-1); ui->m_priceFraction->setCurrentIndex(-1); clearFee(); } void InvestmentPage::clearFee() { clearFeeCol(); ui->m_feeCol->setCurrentIndex(-1); ui->m_feeIsPercentage->setChecked(false); ui->m_calculateFee->setEnabled(false); ui->m_feeRate->setEnabled(true); ui->m_minFee->setEnabled(false); ui->m_feeRate->clear(); ui->m_minFee->clear(); } void InvestmentPage::feeInputsChanged() { // if (ui->comboBoxInv_feeCol->currentIndex() < m_importer->m_file->m_columnCount && // ui->comboBoxInv_feeCol->currentIndex() > -1) { // ui->lineEdit_minFee->setEnabled(false); // ui->lineEdit_feeRate->setEnabled(false); // ui->lineEdit_minFee->clear(); // ui->lineEdit_feeRate->clear(); // } if (m_profile->m_feeRate.isEmpty()) { ui->m_feeCol->setEnabled(true); ui->m_feeIsPercentage->setEnabled(true); ui->m_minFee->setEnabled(false); ui->m_calculateFee->setEnabled(false); } else { ui->m_feeCol->setEnabled(false); ui->m_feeIsPercentage->setEnabled(false); ui->m_feeIsPercentage->setChecked(true); ui->m_minFee->setEnabled(true); ui->m_feeRate->setEnabled(true); if (m_profile->m_colTypeNum.value(Column::Amount) != -1) ui->m_calculateFee->setEnabled(true); } } void InvestmentPage::feeRateChanged(const QString &text) { m_profile->m_feeRate = text; } void InvestmentPage::minFeeChanged(const QString &text) { m_profile->m_minFee = text; } void InvestmentPage::clearFeeCol() { if (!m_profile->m_feeRate.isEmpty() && // if fee rate isn't empty... 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); int feeCol = ui->m_feeCol->currentIndex(); ui->m_feeCol->setCurrentIndex(-1); ui->m_feeCol->removeItem(feeCol); m_dlg->updateWindowSize(); } ui->m_feeCol->setEnabled(true); ui->m_feeIsPercentage->setEnabled(true); ui->m_feeIsPercentage->setChecked(false); } void InvestmentPage::resetComboBox(const Column comboBox) { switch (comboBox) { case Column::Amount: ui->m_amountCol->setCurrentIndex(-1); break; case Column::Date: ui->m_dateCol->setCurrentIndex(-1); break; case Column::Fee: ui->m_feeCol->setCurrentIndex(-1); break; case Column::Memo: ui->m_memoCol->setCurrentIndex(-1); break; case Column::Price: ui->m_priceCol->setCurrentIndex(-1); break; case Column::Quantity: ui->m_quantityCol->setCurrentIndex(-1); break; case Column::Type: ui->m_typeCol->setCurrentIndex(-1); break; case Column::Symbol: ui->m_symbolCol->setCurrentIndex(-1); break; 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.", (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(Column::Quantity); tr.m_shares = m_imp->processQuantityField(m_profile, row, col); // process price field 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(Column::Amount); tr.m_amount = m_imp->processAmountField(m_profile, row, col); // process type field col = m_profile->m_colTypeNum.value(Column::Type); tr.m_eAction = m_imp->processActionTypeField(m_profile, row, col); switch(m_imp->validateActionType(tr)) { case InvalidActionValues: KMessageBox::sorry(m_dlg, i18n("The values in the columns you have selected\ndo not match any expected investment type.\n" "Please check the fields in the current transaction,\nand also your selections."), i18n("CSV import")); return false; break; case NoActionType: { bool unknownType = false; if (tr.m_eAction == eMyMoney::Transaction::Action::None) unknownType = true; QStringList colList; QStringList colHeaders; for (col = 0; col < m_imp->m_file->m_columnCount; ++col) { 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); QPointer 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.
" "
Please check the parameters supplied.
"), i18n("CSV import")); return false; } else tr.m_eAction = transactionDlg->getActionType(); delete transactionDlg; if (unknownType) { // type was unknown so store it 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 } } default: break; } } m_imp->m_isActionTypeValidated = true; return true; } 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' bool ret = true; if (col == -1) { // user only wanted to reset his column so allow him m_profile->m_colTypeNum[type] = col; // assign new column 'number' to this 'type' } else if (m_profile->m_colNumType.contains(col)) { // if this column 'number' has already 'type' assigned KMessageBox::information(m_dlg, i18n("The '%1' field already has this column selected.
Please reselect both entries as necessary.
", m_dlg->m_colTypeName.value(m_profile->m_colNumType.value(col)))); resetComboBox(m_profile->m_colNumType[col]); resetComboBox(type); ret = false; } else { m_profile->m_colTypeNum[type] = col; // assign new column 'number' to this 'type' m_profile->m_colNumType[col] = type; // assign new 'type' to this column 'number' } emit completeChanged(); return ret; } bool InvestmentPage::validateMemoComboBox() { if (m_profile->m_memoColList.count() == 0) return true; for (int i = 0; i < ui->m_memoCol->count(); ++i) { QString txt = ui->m_memoCol->itemText(i); 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; } } return true; } bool InvestmentPage::validateSecurities() { if (m_securitiesDlg.isNull() && m_imp->m_mapSymbolName.isEmpty()) { QSet onlySymbols; QSet onlyNames; m_imp->sortSecurities(onlySymbols, onlyNames, m_imp->m_mapSymbolName); if (!onlySymbols.isEmpty() || !onlyNames.isEmpty()) { m_securitiesDlg = new SecuritiesDlg; for (QSet::const_iterator symbol = onlySymbols.cbegin(); symbol != onlySymbols.cend(); ++symbol) m_securitiesDlg->displayLine(*symbol, QString()); for (QSet::const_iterator name = onlyNames.cbegin(); name != onlyNames.cend(); ++name) m_securitiesDlg->displayLine(QString(), *name); } } if (!m_securitiesDlg.isNull()) { QTableWidget* symbolTable = m_securitiesDlg->ui->tableWidget; if (m_securitiesDlg->exec() == QDialog::Rejected) { return false; } else { for (int row = 0; row < symbolTable->rowCount(); ++row) { QString symbol = symbolTable->item(row, 1)->text(); QString name = symbolTable->item(row, 2)->text(); m_imp->m_mapSymbolName.insert(symbol, name); } delete m_securitiesDlg; } } return true; } bool InvestmentPage::validateSecurity() { if (!m_profile->m_securitySymbol.isEmpty() && !m_profile->m_securityName.isEmpty()) m_imp->m_mapSymbolName.insert(m_profile->m_securitySymbol, m_profile->m_securityName); MyMoneyFile* file = MyMoneyFile::instance(); if (m_securityDlg.isNull() && (m_imp->m_mapSymbolName.isEmpty() || !(m_profile->m_dontAsk && m_dlg->m_skipSetup))) { m_securityDlg = new SecurityDlg; m_securityDlg->initializeSecurities(m_profile->m_securitySymbol, m_profile->m_securityName); m_securityDlg->ui->cbDontAsk->setChecked(m_profile->m_dontAsk); } if (!m_securityDlg.isNull()) { if (m_securityDlg->exec() == QDialog::Rejected) { return false; } else { QString securityID = m_securityDlg->security(); if (!securityID.isEmpty()) { m_profile->m_securityName = file->security(securityID).name(); m_profile->m_securitySymbol = file->security(securityID).tradingSymbol(); } else { m_profile->m_securityName = m_securityDlg->name(); m_profile->m_securitySymbol = m_securityDlg->symbol(); } m_profile->m_dontAsk = m_securityDlg->dontAsk(); m_imp->m_mapSymbolName.clear(); m_imp->m_mapSymbolName.insert(m_profile->m_securitySymbol, m_profile->m_securityName); // probably we should check if security with given symbol and name exists... delete m_securityDlg; // ...but KMM allows creating duplicates, so don't bother } } if (m_imp->m_mapSymbolName.isEmpty()) return false; return true; } void InvestmentPage::makeQIF(const MyMoneyStatement& st, const QString& outFileName) { QFile oFile(outFileName); oFile.open(QIODevice::WriteOnly); QTextStream out(&oFile); QString buffer; QString strEType; switch (st.m_eType) { case eMyMoney::Statement::Type::Investment: default: strEType = QStringLiteral("Invst"); } if (!st.m_strAccountName.isEmpty()) { buffer.append(QStringLiteral("!Account\n")); buffer.append(QChar(QLatin1Char('N')) + st.m_strAccountName + QChar(QLatin1Char('\n'))); buffer.append(QChar(QLatin1Char('T')) + strEType + QChar(QLatin1Char('\n'))); buffer.append(QStringLiteral("^\n")); } for (QList::const_iterator it = st.m_listSecurities.constBegin(); it != st.m_listSecurities.constEnd(); ++it) { buffer.append(QStringLiteral("!Type:Security\n")); buffer.append(QChar(QLatin1Char('N')) + (*it).m_strName + QChar(QLatin1Char('\n'))); buffer.append(QChar(QLatin1Char('S')) + (*it).m_strSymbol + QChar(QLatin1Char('\n'))); buffer.append(QStringLiteral("TStock\n^\n")); } if (!st.m_strAccountName.isEmpty()) { buffer.append(QStringLiteral("!Account\n")); buffer.append(QChar(QLatin1Char('N')) + st.m_strAccountName + QChar(QLatin1Char('\n'))); buffer.append(QChar(QLatin1Char('T')) + strEType + QChar(QLatin1Char('\n'))); buffer.append(QStringLiteral("^\n")); } buffer.append(QStringLiteral("!Type:") + strEType + QChar(QLatin1Char('\n'))); for (QList::const_iterator it = st.m_listTransactions.constBegin(); it != st.m_listTransactions.constEnd(); ++it) { buffer.append(QChar(QLatin1Char('D')) + it->m_datePosted.toString(QStringLiteral("MM/dd/yyyy")) + QChar(QLatin1Char('\n'))); buffer.append(QChar(QLatin1Char('Y')) + it->m_strSecurity + QChar(QLatin1Char('\n'))); QString txt; switch (it->m_eAction) { case eMyMoney::Transaction::Action::Buy: txt = QStringLiteral("Buy"); break; case eMyMoney::Transaction::Action::Sell: txt = QStringLiteral("Sell"); break; case eMyMoney::Transaction::Action::ReinvestDividend: txt = QStringLiteral("ReinvDiv"); break; case eMyMoney::Transaction::Action::CashDividend: txt = QStringLiteral("Div"); break; case eMyMoney::Transaction::Action::Interest: txt = QStringLiteral("IntInc"); break; case eMyMoney::Transaction::Action::Shrsin: txt = QStringLiteral("ShrsIn"); break; case eMyMoney::Transaction::Action::Shrsout: txt = QStringLiteral("ShrsOut"); break; case eMyMoney::Transaction::Action::Stksplit: txt = QStringLiteral("stksplit"); break; default: txt = QStringLiteral("unknown"); // shouldn't happen } buffer.append(QChar(QLatin1Char('N')) + txt + QChar(QLatin1Char('\n'))); if (it->m_eAction == eMyMoney::Transaction::Action::Buy) // we added 'N' field so buy transaction should have any sign txt.setNum(it->m_amount.abs().toDouble(), 'f', 4); else txt.setNum(it->m_amount.toDouble(), 'f', 4); buffer.append(QChar(QLatin1Char('T')) + txt + QChar(QLatin1Char('\n'))); txt.setNum(it->m_shares.toDouble(), 'f', 4); buffer.append(QChar(QLatin1Char('Q')) + txt + QChar(QLatin1Char('\n'))); txt.setNum(it->m_price.toDouble(), 'f', 4); buffer.append(QChar(QLatin1Char('I')) + txt + QChar(QLatin1Char('\n'))); if (!it->m_fees.isZero()) { txt.setNum(it->m_fees.toDouble(), 'f', 4); buffer.append(QChar(QLatin1Char('O')) + txt + QChar(QLatin1Char('\n'))); } if (!it->m_strBrokerageAccount.isEmpty()) buffer.append(QChar(QLatin1Char('L')) + it->m_strBrokerageAccount + QChar(QLatin1Char('\n'))); if (!it->m_strMemo.isEmpty()) buffer.append(QChar(QLatin1Char('M')) + it->m_strMemo + QChar(QLatin1Char('\n'))); buffer.append(QStringLiteral("^\n")); out << buffer;// output qif file buffer.clear(); } oFile.close(); } diff --git a/kmymoney/plugins/csv/import/investmentwizardpage.ui b/kmymoney/plugins/csv/import/investmentwizardpage.ui index 4f2edca46..b52b3b1dc 100644 --- a/kmymoney/plugins/csv/import/investmentwizardpage.ui +++ b/kmymoney/plugins/csv/import/investmentwizardpage.ui @@ -1,564 +1,564 @@ InvestmentPage 0 0 846 284 0 0 Investment Wizard Page Qt::Horizontal 40 20 0 0 50 false Please select the appropriate columns to use, corresponding to your data. If there is just a single security in the file, enter its name below. Otherwise, select the column for the symbol, and for the description or name. Qt::AlignCenter true 0 0 Qt::Horizontal Memo Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter true Quantity Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 Select column containing amount field. 12 0 0 If necessary, select a fraction/multiplier for compatibility between imported and stored prices. For instance, if the import price is in cents but the file is priced in dollars, select 0.01. 5 Select column containing date field Date Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter true 16777215 16777215 Price Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 Select column containing date field. 12 true Amount Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 Select column containing quantity field. 12 0 0 Select column containing price field. 12 0 0 If more than one stock is present in the file, and if the stock symbols are shown in one of the columns, select it here. 0 0 Clear selected column entries. Clear 0 0 Qt::Horizontal 16777215 16777215 Price Fraction Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - Symbol + Symbol Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 If a descriptive column also contains an activity type, select it here. See also Filter text field. Name Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Fee is Percentage Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::LeftToRight Fee Column Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 Check box if any fee is a percentage figure rather than a value. Qt::RightToLeft 0 0 Select column containing investment type field. 12 0 0 If necessary, select column containing fee. Caution. This might already have been incorporated into the price. 12 0 0 Fee rate Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 Type/Action Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 Select column containing memo field. More than one column may be entered successively. May also be selected to contain a copy of the type or name column. 12 Minimal Fee Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 Qt::Horizontal 0 0 Clear Fee 0 0 Calculate Fee Qt::Horizontal 40 20 m_dateCol m_typeCol m_memoCol m_priceCol m_quantityCol m_amountCol m_priceFraction m_symbolCol m_nameCol m_feeCol m_feeIsPercentage m_feeRate m_minFee m_calculateFee m_clear m_clearFee diff --git a/kmymoney/plugins/csv/import/securitiesdlg.ui b/kmymoney/plugins/csv/import/securitiesdlg.ui index 0800a75d9..ea7fbc785 100644 --- a/kmymoney/plugins/csv/import/securitiesdlg.ui +++ b/kmymoney/plugins/csv/import/securitiesdlg.ui @@ -1,158 +1,158 @@ SecuritiesDlg 0 0 606 306 Securities 75 true Missing names and symbols Qt::AlignCenter The following securities' names and symbols are not known to KMyMoney. Please complete every missing name or symbol. Qt::AlignCenter true QAbstractItemView::NoSelection false 3 true true false Status - Symbol + Symbol Name 0 0 QDialogButtonBox::Cancel|QDialogButtonBox::Ok true buttonBox accepted() SecuritiesDlg accept() 302 280 302 152 buttonBox rejected() SecuritiesDlg reject() 302 280 302 152 2 2 true true true diff --git a/kmymoney/widgets/kmymoneycashflowcombo.cpp b/kmymoney/widgets/kmymoneycashflowcombo.cpp index cbb7ba5ee..bb4ce69d3 100644 --- a/kmymoney/widgets/kmymoneycashflowcombo.cpp +++ b/kmymoney/widgets/kmymoneycashflowcombo.cpp @@ -1,106 +1,106 @@ /* * Copyright 2009-2010 Cristian Oneț * Copyright 2009-2010 Alvaro Soliverez * Copyright 2011-2017 Thomas Baumgart * Copyright 2017 Łukasz Wojniłowicz * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "kmymoneycashflowcombo.h" #include "kmymoneymvccombo_p.h" // ---------------------------------------------------------------------------- // QT Includes // ---------------------------------------------------------------------------- // KDE Includes #include // ---------------------------------------------------------------------------- // Project Includes #include "mymoneyenums.h" #include "widgetenums.h" using namespace eWidgets; using namespace eMyMoney; class KMyMoneyCashFlowComboPrivate : public KMyMoneyMVCComboPrivate { Q_DISABLE_COPY(KMyMoneyCashFlowComboPrivate) public: KMyMoneyCashFlowComboPrivate() : m_dir(eRegister::CashFlowDirection::Unknown) { } eRegister::CashFlowDirection m_dir; }; KMyMoneyCashFlowCombo::KMyMoneyCashFlowCombo(Account::Type accountType, QWidget* parent) : KMyMoneyMVCCombo(*new KMyMoneyCashFlowComboPrivate, false, parent) { addItem(" ", QVariant((int)eRegister::CashFlowDirection::Unknown)); if (accountType == Account::Type::Income || accountType == Account::Type::Expense) { // this is used for income/expense accounts to just show the reverse sense addItem(i18nc("Activity for income categories", "Received"), QVariant((int)eRegister::CashFlowDirection::Payment)); addItem(i18nc("Activity for expense categories", "Paid"), QVariant((int)eRegister::CashFlowDirection::Deposit)); } else { - addItem(i18n("Pay to"), QVariant((int)eRegister::CashFlowDirection::Payment)); - addItem(i18n("From"), QVariant((int)eRegister::CashFlowDirection::Deposit)); + addItem(i18nc("Payee", "Pay to"), QVariant((int)eRegister::CashFlowDirection::Payment)); + addItem(i18nc("Payer", "From"), QVariant((int)eRegister::CashFlowDirection::Deposit)); } connect(this, &KMyMoneyMVCCombo::itemSelected, this, &KMyMoneyCashFlowCombo::slotSetDirection); } KMyMoneyCashFlowCombo::~KMyMoneyCashFlowCombo() { } void KMyMoneyCashFlowCombo::setDirection(eRegister::CashFlowDirection dir) { Q_D(KMyMoneyCashFlowCombo); d->m_dir = dir; QString num; setSelectedItem(num.setNum((int)dir)); } eRegister::CashFlowDirection KMyMoneyCashFlowCombo::direction() const { Q_D(const KMyMoneyCashFlowCombo); return d->m_dir; } void KMyMoneyCashFlowCombo::slotSetDirection(const QString& id) { Q_D(KMyMoneyCashFlowCombo); QString num; for (int i = (int)eRegister::CashFlowDirection::Deposit; i <= (int)eRegister::CashFlowDirection::Unknown; ++i) { num.setNum(i); if (num == id) { d->m_dir = static_cast(i); break; } } emit directionSelected(d->m_dir); update(); } void KMyMoneyCashFlowCombo::removeDontCare() { removeItem(findData(QVariant((int)eRegister::CashFlowDirection::Unknown), Qt::UserRole, Qt::MatchExactly)); } diff --git a/kmymoney/widgets/transaction_p.h b/kmymoney/widgets/transaction_p.h index af3f671de..759c8aa7c 100644 --- a/kmymoney/widgets/transaction_p.h +++ b/kmymoney/widgets/transaction_p.h @@ -1,135 +1,135 @@ /* * Copyright 2006-2018 Thomas Baumgart * Copyright 2017-2018 Łukasz Wojniłowicz * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef TRANSACTION_P_H #define TRANSACTION_P_H #include "registeritem_p.h" // ---------------------------------------------------------------------------- // QT Includes #include #include // ---------------------------------------------------------------------------- // KDE Includes #include // ---------------------------------------------------------------------------- // Project Includes #include "register.h" #include "mymoneyaccount.h" #include "mymoneyfile.h" #include "mymoneymoney.h" #include "mymoneypayee.h" #include "mymoneysplit.h" #include "mymoneytag.h" #include "mymoneytransaction.h" namespace KMyMoneyRegister { class TransactionPrivate : public RegisterItemPrivate { public: TransactionPrivate() : m_form(nullptr), m_formRowHeight(-1), m_selected(false), m_focus(false), m_erroneous(false), m_inEdit(false), m_inRegisterEdit(false), m_showBalance(true), m_reducedIntensity(false) { } virtual ~ TransactionPrivate() { } void init(int uniqueId) { auto file = MyMoneyFile::instance(); // load the account if (!m_split.accountId().isEmpty()) m_account = file->account(m_split.accountId()); // load the payee if (!m_split.payeeId().isEmpty()) { m_payee = file->payee(m_split.payeeId()).name(); } if (m_parent->account().isIncomeExpense()) { - m_payeeHeader = m_split.shares().isNegative() ? i18n("From") : i18n("Pay to"); + m_payeeHeader = m_split.shares().isNegative() ? i18nc("Payer", "From") : i18nc("Payee", "Pay to"); } else { - m_payeeHeader = m_split.shares().isNegative() ? i18n("Pay to") : i18n("From"); + m_payeeHeader = m_split.shares().isNegative() ? i18nc("Payee", "Pay to") : i18nc("Payer", "From"); } // load the tag if (!m_split.tagIdList().isEmpty()) { const QList t = m_split.tagIdList(); for (auto i = 0; i < t.count(); i++) { m_tagList << file->tag(t[i]).name(); m_tagColorList << file->tag(t[i]).tagColor(); } } // load the currency if (!m_transaction.id().isEmpty()) m_splitCurrencyId = m_account.currencyId(); // check if transaction is erroneous or not m_erroneous = !m_transaction.splitSum().isZero(); if (!m_uniqueId.isEmpty()) { m_uniqueId += '-'; QString id; id.setNum(uniqueId); m_uniqueId += id.rightJustified(3, '0'); } } MyMoneyTransaction m_transaction; MyMoneySplit m_split; MyMoneyAccount m_account; MyMoneyMoney m_balance; QTableWidget* m_form; QString m_category; QString m_payee; QString m_payeeHeader; QList m_tagList; QList m_tagColorList; QString m_categoryHeader; QString m_splitCurrencyId; QString m_uniqueId; int m_formRowHeight; bool m_selected; bool m_focus; bool m_erroneous; bool m_inEdit; bool m_inRegisterEdit; bool m_showBalance; bool m_reducedIntensity; }; } #endif