diff --git a/kmymoney/converter/mymoneystatementreader.cpp b/kmymoney/converter/mymoneystatementreader.cpp --- a/kmymoney/converter/mymoneystatementreader.cpp +++ b/kmymoney/converter/mymoneystatementreader.cpp @@ -1019,15 +1019,13 @@ QLabel *label1 = new QLabel(i18n("Please select a default category for payee '%1'", payeename)); topcontents->addWidget(label1); - AccountNamesFilterProxyModel *filterProxyModel = new AccountNamesFilterProxyModel(this); + auto filterProxyModel = new AccountNamesFilterProxyModel(this); filterProxyModel->setHideEquityAccounts(!KMyMoneyGlobalSettings::expertMode()); - filterProxyModel->addAccountGroup(MyMoneyAccount::Asset); - filterProxyModel->addAccountGroup(MyMoneyAccount::Liability); - filterProxyModel->addAccountGroup(MyMoneyAccount::Equity); - filterProxyModel->addAccountGroup(MyMoneyAccount::Income); - filterProxyModel->addAccountGroup(MyMoneyAccount::Expense); - filterProxyModel->setSourceModel(Models::instance()->accountsModel()); - filterProxyModel->sort(0); + filterProxyModel->addAccountGroup(QVector {MyMoneyAccount::Asset, MyMoneyAccount::Liability, MyMoneyAccount::Equity, MyMoneyAccount::Income, MyMoneyAccount::Expense}); + + auto const model = Models::instance()->accountsModel(); + filterProxyModel->init(model,model->getColumns()); + filterProxyModel->sort(AccountsModel::Account); QPointer accountCombo = new KMyMoneyAccountCombo(filterProxyModel); topcontents->addWidget(accountCombo); diff --git a/kmymoney/dialogs/kexportdlg.cpp b/kmymoney/dialogs/kexportdlg.cpp --- a/kmymoney/dialogs/kexportdlg.cpp +++ b/kmymoney/dialogs/kexportdlg.cpp @@ -230,11 +230,11 @@ void KExportDlg::loadAccounts() { - AccountNamesFilterProxyModel *filterProxyModel = new AccountNamesFilterProxyModel(this); - filterProxyModel->addAccountGroup(MyMoneyAccount::Asset); - filterProxyModel->addAccountGroup(MyMoneyAccount::Liability); - filterProxyModel->setSourceModel(Models::instance()->accountsModel()); - filterProxyModel->sort(0); + auto filterProxyModel = new AccountNamesFilterProxyModel(this); + filterProxyModel->addAccountGroup(QVector {MyMoneyAccount::Asset, MyMoneyAccount::Liability}); + auto const model = Models::instance()->accountsModel(); + filterProxyModel->init(model, model->getColumns()); + filterProxyModel->sort(AccountsModel::Account); m_accountComboBox->setModel(filterProxyModel); } diff --git a/kmymoney/dialogs/knewaccountdlg.cpp b/kmymoney/dialogs/knewaccountdlg.cpp --- a/kmymoney/dialogs/knewaccountdlg.cpp +++ b/kmymoney/dialogs/knewaccountdlg.cpp @@ -110,7 +110,7 @@ bool HierarchyFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { if (!source_parent.isValid()) { - QVariant data = sourceModel()->index(source_row, 0, source_parent).data(AccountsModel::AccountIdRole); + const auto data = sourceModel()->index(source_row, AccountsModel::Account, source_parent).data(AccountsModel::AccountIdRole); if (data.isValid() && data.toString() == AccountsModel::favoritesAccountId) return false; } @@ -139,7 +139,7 @@ MyMoneyFile *file = MyMoneyFile::instance(); // initialize the m_parentAccount member - MyMoneyAccount::accountTypeE filterAccountGroup = m_account.accountGroup(); + QVector filterAccountGroup {m_account.accountGroup()}; switch (m_account.accountGroup()) { case MyMoneyAccount::Asset: m_parentAccount = file->asset(); @@ -160,10 +160,10 @@ qDebug("Seems we have an account that hasn't been mapped to the top five"); if (m_categoryEditor) { m_parentAccount = file->income(); - filterAccountGroup = MyMoneyAccount::Income; + filterAccountGroup[0] = MyMoneyAccount::Income; } else { m_parentAccount = file->asset(); - filterAccountGroup = MyMoneyAccount::Asset; + filterAccountGroup[0] = MyMoneyAccount::Asset; } } @@ -176,15 +176,12 @@ m_filterProxyModel->setHideEquityAccounts(!KMyMoneyGlobalSettings::expertMode()); m_filterProxyModel->addAccountGroup(filterAccountGroup); m_filterProxyModel->setCurrentAccountId(m_account.id()); - m_filterProxyModel->setSourceModel(Models::instance()->accountsModel()); + auto const model = Models::instance()->accountsModel(); + m_filterProxyModel->init(model, m_parentAccounts->getColumns(KMyMoneyView::View::None)); m_filterProxyModel->setDynamicSortFilter(true); - m_parentAccounts->setAlternatingRowColors(true); - m_parentAccounts->setIconSize(QSize(22, 22)); - m_parentAccounts->setSortingEnabled(true); - m_parentAccounts->setAllColumnsShowFocus(true); - m_parentAccounts->setModel(m_filterProxyModel); - m_parentAccounts->sortByColumn(0, Qt::AscendingOrder); + m_parentAccounts->init(m_filterProxyModel, model->getColumns()); + m_parentAccounts->sortByColumn(AccountsModel::Account, Qt::AscendingOrder); m_subAccountLabel->setText(i18n("Is a sub account")); @@ -800,7 +797,7 @@ m_account.setAccountType(type); // update the account group displayed in the accounts hierarchy m_filterProxyModel->clear(); - m_filterProxyModel->addAccountGroup(m_account.accountGroup()); + m_filterProxyModel->addAccountGroup(QVector {m_account.accountGroup()}); } } catch (const MyMoneyException &) { qWarning("Unexpected exception in KNewAccountDlg::slotAccountTypeChanged()"); diff --git a/kmymoney/dialogs/konlinetransferform.cpp b/kmymoney/dialogs/konlinetransferform.cpp --- a/kmymoney/dialogs/konlinetransferform.cpp +++ b/kmymoney/dialogs/konlinetransferform.cpp @@ -55,7 +55,8 @@ delete ui->creditTransferEdit->takeWidget(); OnlineBankingAccountNamesFilterProxyModel* accountsModel = new OnlineBankingAccountNamesFilterProxyModel(this); - accountsModel->setSourceModel(Models::instance()->accountsModel()); + auto const model = Models::instance()->accountsModel(); + accountsModel->setSourceModel(model); ui->originAccount->setModel(accountsModel); ui->convertMessage->hide(); diff --git a/kmymoney/models/accountsmodel.h b/kmymoney/models/accountsmodel.h --- a/kmymoney/models/accountsmodel.h +++ b/kmymoney/models/accountsmodel.h @@ -1,5 +1,6 @@ /*************************************************************************** * Copyright 2010 Cristian Onet onet.cristian@gmail.com * + * Copyright 2017 Łukasz Wojniłowicz lukasz.wojnilowicz@gmail.com * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * @@ -68,9 +69,6 @@ AccountBalanceRole = Qt::UserRole + 3, /**< The account balance is stored in this role in column 0 as a MyMoneyMoney object.*/ AccountValueRole = Qt::UserRole + 4, /**< The account value (the balance converted to base currency) is stored in this role in column 0 as a MyMoneyMoney object.*/ AccountTotalValueRole = Qt::UserRole + 5, /**< The account total value (the value of the account and of child accounts) is stored in this role in column 0 as a MyMoneyMoney object.*/ - AccountBalanceDisplayRole = Qt::UserRole + 6, /**< The account balance is stored in this role in column TotalBalance as a formatted string for the user.*/ - AccountValueDisplayRole = Qt::UserRole + 7, /**< The account value (the balance converted to base currency) is stored in this role in column TotalValue as a formated string for the user.*/ - AccountTotalValueDisplayRole = Qt::UserRole + 8, /**< The account total value is stored in this role in column TotalValue as a formatted string for the user.*/ DisplayOrderRole = Qt::UserRole + 9, /**< This role is used by the filtering proxies to order the accounts for displaying.*/ FullNameRole = Qt::UserRole + 10, /**< This role is used to provide the full pathname of the account */ }; @@ -80,14 +78,16 @@ */ enum Columns { FirstColumnMarker = 0, - Account = 0, + Account = 0, // CAUTION! Assumption is being made that Account column number is always 0 and you shouldn't change this Type, Tax, VAT, CostCenter, TotalBalance, PostedValue, TotalValue, + AccountNumber, + AccountSortCode, LastColumnMarker }; @@ -120,6 +120,11 @@ */ QModelIndex accountById(const QString& id) const; + QList *getColumns(); + + void setColumnVisibility(const Columns column, const bool show); + static QString getHeaderName(const Columns column); + public slots: void slotReconcileAccount(const MyMoneyAccount &account, const QDate &reconciliationDate, const MyMoneyMoney &endingBalance); @@ -239,7 +244,7 @@ ~AccountsFilterProxyModel(); void addAccountType(MyMoneyAccount::accountTypeE type); - void addAccountGroup(MyMoneyAccount::accountTypeE type); + void addAccountGroup(const QVector &groups); void removeAccountType(MyMoneyAccount::accountTypeE type); void clear(); @@ -255,15 +260,21 @@ int visibleItems(bool includeBaseAccounts = false) const; + void init(AccountsModel *model, QList *visColumns); + void init(AccountsModel *model); + protected: virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const; + virtual bool filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const; virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const; virtual bool acceptSourceItem(const QModelIndex &source) const; bool filterAcceptsRowOrChildRows(int source_row, const QModelIndex &source_parent) const; int visibleItems(const QModelIndex& index) const; + QList *m_mdlColumns; + QList *m_visColumns; signals: void unusedIncomeExpenseAccountHidden() const; diff --git a/kmymoney/models/accountsmodel.cpp b/kmymoney/models/accountsmodel.cpp --- a/kmymoney/models/accountsmodel.cpp +++ b/kmymoney/models/accountsmodel.cpp @@ -1,5 +1,6 @@ /*************************************************************************** * Copyright 2010 Cristian Onet onet.cristian@gmail.com * + * Copyright 2017 Łukasz Wojniłowicz lukasz.wojnilowicz@gmail.com * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * @@ -49,11 +50,29 @@ */ Private() : m_file(MyMoneyFile::instance()) { + m_columns.append(Columns::Account); } ~Private() { } + void loadPreferredAccount(const MyMoneyAccount &acc, QStandardItem *fromNode /*accounts' regular node*/, const int row, QStandardItem *toNode /*accounts' favourite node*/) + { + if (acc.value(QStringLiteral("PreferredAccount")) != QLatin1String("Yes")) + return; + + auto favRow = toNode->rowCount(); + auto favItem = itemFromAccountId(toNode, acc.id()); + if (favItem) + favRow = favItem->row(); + + for (auto i = 0; i < fromNode->columnCount(); ++i) { + auto itemToClone = fromNode->child(row, i); + if (itemToClone) + toNode->setChild(favRow, i, itemToClone->clone()); + } + } + /** * Load all the sub-accounts recursively. * @@ -63,155 +82,271 @@ * @param list The list of the account id's of the sub-accounts which are being loaded. * */ - void loadSubAccounts(QStandardItemModel *model, QStandardItem *accountsItem, QStandardItem *favoriteAccountsItem, const QStringList& list) { - for (QStringList::ConstIterator it_l = list.constBegin(); it_l != list.constEnd(); ++it_l) { - const MyMoneyAccount& acc = m_file->account(*it_l); + void loadSubaccounts(QStandardItem *node, QStandardItem *favoriteAccountsItem, const QStringList& subaccounts) + { + if (subaccounts.isEmpty()) + return; + foreach (const auto subaccStr, subaccounts) { + const auto subacc = m_file->account(subaccStr); - QStandardItem *item = new QStandardItem(acc.name()); - accountsItem->appendRow(item); - item->setColumnCount(model->columnCount()); + auto item = new QStandardItem(subacc.name()); // initialize first column of subaccount + node->appendRow(item); // add subaccount row to node item->setEditable(false); - item->setData(accountsItem->data(DisplayOrderRole), DisplayOrderRole); + item->setData(node->data(DisplayOrderRole), DisplayOrderRole); // inherit display order role from node + + loadSubaccounts(item, favoriteAccountsItem, subacc.accountList()); // subaccount may have subaccounts as well - if (acc.accountList().count() > 0) { - loadSubAccounts(model, item, favoriteAccountsItem, acc.accountList()); - } // set the account data after the children have been loaded - setAccountData(model, item->index(), acc); - - if (acc.value("PreferredAccount") == "Yes") { - QStandardItem *item = new QStandardItem(acc.name()); - favoriteAccountsItem->appendRow(item); - item->setColumnCount(model->columnCount()); - item->setEditable(false); - // set the account data after the children have been loaded - setAccountData(model, item->index(), acc); - } + const auto row = item->row(); + setAccountData(node, row, subacc, m_columns); // initialize rest of columns of subaccount + loadPreferredAccount(subacc, node, row, favoriteAccountsItem); // add to favourites node if preferred } } /** * Note: this functions should only be called after the child account data has been set. */ - void setAccountData(QStandardItemModel *model, const QModelIndex &index, const MyMoneyAccount &account) { - // Account - model->setData(index, account.name(), Qt::DisplayRole); - model->setData(index, QVariant::fromValue(account), AccountRole); - model->setData(index, QVariant(account.id()), AccountIdRole); - model->setData(index, QVariant(account.value("PreferredAccount") == "Yes"), AccountFavoriteRole); - model->setData(index, QVariant(QIcon(account.accountPixmap(account.id() == m_reconciledAccount.id()))), Qt::DecorationRole); - model->setData(index, MyMoneyFile::instance()->accountToCategory(account.id(), true), FullNameRole); - - QFont font = model->data(index, Qt::FontRole).value(); + 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 + } + }; + auto colNum = m_columns.indexOf(Columns::Account); + if (colNum == -1) + return; + getCell(colNum); + auto font = cell->data(Qt::FontRole).value(); // display the names of closed accounts with strikeout font - if (account.isClosed() != font.strikeOut()) { + if (account.isClosed() != font.strikeOut()) font.setStrikeOut(account.isClosed()); - model->setData(index, font, Qt::FontRole); + + if (columns.contains(Columns::Account)) { + // setting account column + cell->setData(account.name(), Qt::DisplayRole); +// cell->setData(QVariant::fromValue(account), AccountRole); // is set in setAccountBalanceAndValue + cell->setData(QVariant(account.id()), AccountIdRole); + cell->setData(QVariant(account.value("PreferredAccount") == QLatin1String("Yes")), AccountFavoriteRole); + cell->setData(QVariant(QIcon(account.accountPixmap(account.id() == m_reconciledAccount.id()))), Qt::DecorationRole); + cell->setData(MyMoneyFile::instance()->accountToCategory(account.id(), true), FullNameRole); + cell->setData(font, Qt::FontRole); } // Type - QModelIndex newIndex = model->index(index.row(), index.column() + Type, index.parent()); - model->setData(newIndex, KMyMoneyUtils::accountTypeToString(account.accountType()), Qt::DisplayRole); - model->setData(newIndex, font, Qt::FontRole); + if (columns.contains(Columns::Type)) { + colNum = m_columns.indexOf(Columns::Type); + if (colNum != -1) { + getCell(colNum); + cell->setData(KMyMoneyUtils::accountTypeToString(account.accountType()), Qt::DisplayRole); + cell->setData(font, Qt::FontRole); + } + } - QIcon checkMark = QIcon::fromTheme(g_Icons[Icon::DialogOK]); + // Account's number + if (columns.contains(Columns::AccountNumber)) { + colNum = m_columns.indexOf(Columns::AccountNumber); + if (colNum != -1) { + getCell(colNum); + cell->setData(account.number(), Qt::DisplayRole); + cell->setData(font, Qt::FontRole); + } + } + + // Account's sort code + if (columns.contains(Columns::AccountSortCode)) { + colNum = m_columns.indexOf(Columns::AccountSortCode); + if (colNum != -1) { + getCell(colNum); + cell->setData(account.value("iban"), Qt::DisplayRole); + cell->setData(font, Qt::FontRole); + } + } + + const auto checkMark = QIcon::fromTheme(g_Icons[Icon::DialogOK]); switch (account.accountType()) { case MyMoneyAccount::Income: case MyMoneyAccount::Expense: case MyMoneyAccount::Asset: case MyMoneyAccount::Liability: // Tax - newIndex = model->index(index.row(), index.column() + Tax, index.parent()); - if (account.value("Tax").toLower() == "yes") { - model->setData(newIndex, checkMark, Qt::DecorationRole); - } else { - model->setData(newIndex, QPixmap(), Qt::DecorationRole); + if (columns.contains(Columns::Tax)) { + colNum = m_columns.indexOf(Columns::Tax); + if (colNum != -1) { + getCell(colNum); + if (account.value("Tax").toLower() == "yes") + cell->setData(checkMark, Qt::DecorationRole); + else + cell->setData(QIcon(), Qt::DecorationRole); + } } // VAT Account - newIndex = model->index(index.row(), index.column() + VAT, index.parent()); - if (!account.value("VatAccount").isEmpty()) { - MyMoneyFile* file = MyMoneyFile::instance(); - const MyMoneyAccount &vatAccount = file->account(account.value("VatAccount")); - - model->setData(newIndex, vatAccount.name(), Qt::DisplayRole); - model->setData(newIndex, QVariant(Qt::AlignLeft | Qt::AlignVCenter), Qt::TextAlignmentRole); - - // VAT Rate - } else if (!account.value("VatRate").isEmpty()) { - MyMoneyMoney vatRate = MyMoneyMoney(account.value("VatRate")) * MyMoneyMoney(100, 1); - model->setData(newIndex, QString("%1 %").arg(vatRate.formatMoney("", 1)), Qt::DisplayRole); - model->setData(newIndex, QVariant(Qt::AlignRight | Qt::AlignVCenter), Qt::TextAlignmentRole); - - } else { - model->setData(newIndex, QString(), Qt::DisplayRole); + if (columns.contains(Columns::VAT)) { + colNum = m_columns.indexOf(Columns::VAT); + if (colNum != -1) { + getCell(colNum); + if (!account.value("VatAccount").isEmpty()) { + const auto vatAccount = MyMoneyFile::instance()->account(account.value("VatAccount")); + cell->setData(vatAccount.name(), Qt::DisplayRole); + cell->setData(QVariant(Qt::AlignLeft | Qt::AlignVCenter), Qt::TextAlignmentRole); + + // VAT Rate + } else if (!account.value("VatRate").isEmpty()) { + const auto vatRate = MyMoneyMoney(account.value("VatRate")) * MyMoneyMoney(100, 1); + cell->setData(QString::fromLatin1("%1 %").arg(vatRate.formatMoney(QString(), 1)), Qt::DisplayRole); + cell->setData(QVariant(Qt::AlignRight | Qt::AlignVCenter), Qt::TextAlignmentRole); + + } else { + cell->setData(QString(), Qt::DisplayRole); + } + } } // CostCenter - newIndex = model->index(index.row(), index.column() + CostCenter, index.parent()); - if (account.isCostCenterRequired()) { - model->setData(newIndex, checkMark, Qt::DecorationRole); - } else { - model->setData(newIndex, QPixmap(), Qt::DecorationRole); + if (columns.contains(Columns::CostCenter)) { + colNum = m_columns.indexOf(Columns::CostCenter); + if (colNum != -1) { + getCell(colNum); + if (account.isCostCenterRequired()) + cell->setData(checkMark, Qt::DecorationRole); + else + cell->setData(QIcon(), Qt::DecorationRole); + } } break; default: break; } // balance and value - setAccountBalanceAndValue(model, index, account); + setAccountBalanceAndValue(node, row, account, columns); } - void setAccountBalanceAndValue(QStandardItemModel *model, const QModelIndex &index, const MyMoneyAccount &account) { - // set the account object also since it's balance has changed - model->setData(index, QVariant::fromValue(account), AccountRole); - // set the balance of the account - MyMoneyMoney accountBalance = balance(account); - model->setData(index, QVariant::fromValue(accountBalance), AccountBalanceRole); - // set the value of the account - MyMoneyMoney accountValue = value(account, accountBalance); - model->setData(index, QVariant::fromValue(accountValue), AccountValueRole); - // set the total value of the account - MyMoneyMoney accountTotalValue = childrenTotalValue(index) + accountValue; - model->setData(index, QVariant::fromValue(accountTotalValue), AccountTotalValueRole); - - QFont font = model->data(index, Qt::FontRole).value(); - - // Total Balance - QModelIndex newIndex = model->index(index.row(), index.column() + TotalBalance, index.parent()); - // only show the balance, if its a different security/currency - if (m_file->security(account.currencyId()) != m_file->baseCurrency()) { - model->setData(newIndex, MyMoneyUtils::formatMoney(accountBalance, m_file->security(account.currencyId())), Qt::DisplayRole); - model->setData(newIndex, MyMoneyUtils::formatMoney(accountBalance, m_file->security(account.currencyId())), AccountBalanceDisplayRole); + void setInstitutionTotalValue(QStandardItem *node, const int row) + { + const auto colInstitution = m_columns.indexOf(Columns::Account); + auto itInstitution = node->child(row, colInstitution); + const auto valInstitution = childrenTotalValue(itInstitution, true); + itInstitution->setData(QVariant::fromValue(valInstitution ), AccountTotalValueRole); + + const auto colTotalValue = m_columns.indexOf(Columns::TotalValue); + if (colTotalValue == -1) + return; + auto cell = node->child(row, colTotalValue); + if (!cell) { + cell = new QStandardItem; + node->setChild(row, colTotalValue, cell); + } + QColor color; + if (valInstitution.isNegative()) + color = KMyMoneyGlobalSettings::listNegativeValueColor(); + else + color = KColorScheme(QPalette::Active).foreground(KColorScheme::NormalText).color(); + + cell->setData(QVariant(color), Qt::ForegroundRole); + cell->setData(QVariant(itInstitution->data(Qt::FontRole).value()), Qt::FontRole); + cell->setData(QVariant(Qt::AlignRight | Qt::AlignVCenter), Qt::TextAlignmentRole); + cell->setData(MyMoneyUtils::formatMoney(valInstitution, m_file->baseCurrency()), Qt::DisplayRole); + } + + void setAccountBalanceAndValue(QStandardItem *node, const int row, const MyMoneyAccount &account, const QList &columns) + { + QStandardItem *cell; + + auto getCell = [&, row](auto column) + { + cell = node->child(row, column); + if (!cell) { + cell = new QStandardItem; + node->setChild(row, column, cell); + } + }; + + // setting account column + auto colNum = m_columns.indexOf(Columns::Account); + if (colNum == -1) + return; + getCell(colNum); + + MyMoneyMoney accountBalance, accountValue, accountTotalValue; + if (columns.contains(Columns::Account)) { // update values only when requested + accountBalance = balance(account); + accountValue = value(account, accountBalance); + accountTotalValue = childrenTotalValue(cell) + accountValue; + cell->setData(QVariant::fromValue(account), AccountRole); + cell->setData(QVariant::fromValue(accountBalance), AccountBalanceRole); + cell->setData(QVariant::fromValue(accountValue), AccountValueRole); + cell->setData(QVariant::fromValue(accountTotalValue), AccountTotalValueRole); + } else { // otherwise save up on tedious calculations + accountBalance = cell->data(AccountBalanceRole).value(); + accountValue = cell->data(AccountValueRole).value(); + accountTotalValue = cell->data(AccountTotalValueRole).value(); + } + + const auto font = QVariant(cell->data(Qt::FontRole).value()); + const auto alignment = QVariant(Qt::AlignRight | Qt::AlignVCenter); + + // setting total balance column + if (columns.contains(Columns::TotalBalance)) { + colNum = m_columns.indexOf(Columns::TotalBalance); + if (colNum != -1) { + const auto accountBalanceStr = QVariant::fromValue(MyMoneyUtils::formatMoney(accountBalance, m_file->security(account.currencyId()))); + getCell(colNum); + // only show the balance, if its a different security/currency + if (m_file->security(account.currencyId()) != m_file->baseCurrency()) { + cell->setData(accountBalanceStr, Qt::DisplayRole); + } + cell->setData(font, Qt::FontRole); + cell->setData(alignment, Qt::TextAlignmentRole); + } + } + + // setting posted value column + if (columns.contains(Columns::PostedValue)) { + colNum = m_columns.indexOf(Columns::PostedValue); + if (colNum != -1) { + const auto accountValueStr = QVariant::fromValue(MyMoneyUtils::formatMoney(accountValue, m_file->baseCurrency())); + getCell(colNum); + cell->setData(accountValueStr, Qt::DisplayRole); + cell->setData(font, Qt::FontRole); + cell->setData(alignment, Qt::TextAlignmentRole); + } + } + + // setting total value column + if (columns.contains(Columns::TotalValue)) { + colNum = m_columns.indexOf(Columns::TotalValue); + if (colNum != -1) { + const auto accountTotalValueStr = QVariant::fromValue(MyMoneyUtils::formatMoney(accountTotalValue, m_file->baseCurrency())); + getCell(colNum); + QColor color; + if (accountTotalValue.isNegative()) + color = KMyMoneyGlobalSettings::listNegativeValueColor(); + else + color = KColorScheme(QPalette::Active).foreground(KColorScheme::NormalText).color(); + + cell->setData(accountTotalValueStr, Qt::DisplayRole); + cell->setData(font, Qt::FontRole); + cell->setData(QVariant(color), Qt::ForegroundRole); + cell->setData(alignment, Qt::TextAlignmentRole); + } } - model->setData(newIndex, font, Qt::FontRole); - model->setData(newIndex, QVariant(Qt::AlignRight | Qt::AlignVCenter), Qt::TextAlignmentRole); - - // Total Value - newIndex = model->index(index.row(), index.column() + TotalValue , index.parent()); - model->setData(newIndex, MyMoneyUtils::formatMoney(accountTotalValue, m_file->baseCurrency()), Qt::DisplayRole); - model->setData(newIndex, MyMoneyUtils::formatMoney(accountTotalValue, m_file->baseCurrency()), AccountValueDisplayRole); - model->setData(newIndex, MyMoneyUtils::formatMoney(accountTotalValue, m_file->baseCurrency()), AccountTotalValueDisplayRole); - model->setData(newIndex, font, Qt::FontRole); - model->setData(newIndex, QVariant(Qt::AlignRight | Qt::AlignVCenter), Qt::TextAlignmentRole); - - //Posted Value - newIndex = model->index(index.row(), index.column() + PostedValue , index.parent()); - model->setData(newIndex, MyMoneyUtils::formatMoney(accountValue, m_file->baseCurrency()), Qt::DisplayRole); - model->setData(newIndex, MyMoneyUtils::formatMoney(accountValue, m_file->baseCurrency()), AccountValueDisplayRole); - model->setData(newIndex, font, Qt::FontRole); - model->setData(newIndex, QVariant(Qt::AlignRight | Qt::AlignVCenter), Qt::TextAlignmentRole); } /** * Compute the balance of the given account. * * @param account The account for which the balance is being computed. */ - MyMoneyMoney balance(const MyMoneyAccount &account) { + MyMoneyMoney balance(const MyMoneyAccount &account) + { MyMoneyMoney balance; // a closed account has a zero balance by definition if (!account.isClosed()) { @@ -246,7 +381,8 @@ * * @see balance */ - MyMoneyMoney value(const MyMoneyAccount &account, const MyMoneyMoney &balance) { + MyMoneyMoney value(const MyMoneyAccount &account, const MyMoneyMoney &balance) + { if (account.isClosed()) return MyMoneyMoney(); @@ -295,20 +431,25 @@ * @param index The index of the account in the model. * @see value */ - MyMoneyMoney childrenTotalValue(const QModelIndex &index) { + MyMoneyMoney childrenTotalValue(const QStandardItem *node, const bool isInstitutionsModel = false) + { MyMoneyMoney totalValue; - if (!index.isValid()) + if (!node) return totalValue; - const QAbstractItemModel *model = index.model(); - for (int i = 0; i < model->rowCount(index); ++i) { - QModelIndex childIndex = model->index(i, index.column(), index); - if (model->hasChildren(childIndex)) { - totalValue += childrenTotalValue(childIndex); - } - QVariant data = model->data(childIndex, AccountValueRole); + for (auto i = 0; i < node->rowCount(); ++i) { + const auto childNode = node->child(i, Columns::Account); + if (childNode->hasChildren()) + totalValue += childrenTotalValue(childNode, isInstitutionsModel); + const auto data = childNode->data(AccountValueRole); if (data.isValid()) { - totalValue += data.value(); + auto value = data.value(); + if (isInstitutionsModel) { + const auto account = childNode->data(AccountRole).value(); + if (account.accountGroup() == MyMoneyAccount::Liability) + value = -value; + } + totalValue += value; } } return totalValue; @@ -323,13 +464,12 @@ * @return The item corresponding to the given account id, NULL if the account was not found. */ QStandardItem *itemFromAccountId(QStandardItem *parent, const QString &accountId) { - QStandardItemModel *model = parent->model(); - QModelIndexList list = model->match(model->index(0, 0, parent->index()), AccountsModel::AccountIdRole, QVariant(accountId), 1, Qt::MatchFlags(Qt::MatchExactly | Qt::MatchCaseSensitive)); - if (list.count() > 0) { + auto const model = parent->model(); + const auto list = model->match(model->index(0, 0, parent->index()), AccountsModel::AccountIdRole, QVariant(accountId), 1, Qt::MatchFlags(Qt::MatchExactly | Qt::MatchCaseSensitive)); + if (!list.isEmpty()) return model->itemFromIndex(list.front()); - } // TODO: if not found at this item search for it in the model and if found reparent it. - return 0; + return nullptr; } /** @@ -342,15 +482,15 @@ * * @return The item corresponding to the given account id, NULL if the account was not found. */ - QStandardItem *itemFromAccountId(QStandardItemModel *model, const QString &accountId) { - QModelIndexList list = model->match(model->index(0, 0), AccountsModel::AccountIdRole, QVariant(accountId), -1, Qt::MatchFlags(Qt::MatchExactly | Qt::MatchCaseSensitive | Qt::MatchRecursive)); + QStandardItem *itemFromAccountId(QStandardItemModel *model, const QString &accountId) + { + const auto list = model->match(model->index(0, 0), AccountsModel::AccountIdRole, QVariant(accountId), -1, Qt::MatchFlags(Qt::MatchExactly | Qt::MatchCaseSensitive | Qt::MatchRecursive)); foreach (const QModelIndex &index, list) { // always return the account which is not the child of the favorite accounts item - if (index.parent().data(AccountsModel::AccountIdRole).toString() != AccountsModel::favoritesAccountId) { + if (index.parent().data(AccountsModel::AccountIdRole).toString() != AccountsModel::favoritesAccountId) return model->itemFromIndex(index); - } } - return 0; + return nullptr; } /** @@ -369,9 +509,16 @@ * Used to set the reconciliation flag. */ MyMoneyAccount m_reconciledAccount; + + QList m_columns; + static const QString m_accountsModelConfGroup; + static const QString m_accountsModelColumnSelection; }; -const QString AccountsModel::favoritesAccountId("Favorites"); +const QString AccountsModel::Private::m_accountsModelConfGroup = QStringLiteral("AccountsModel"); +const QString AccountsModel::Private::m_accountsModelColumnSelection = QStringLiteral("ColumnSelection"); + +const QString AccountsModel::favoritesAccountId(QStringLiteral("Favorites")); /** * The constructor is private so that only the @ref Models object can create such an object. @@ -396,36 +543,8 @@ void AccountsModel::init() { QStringList headerLabels; - for (int i = 0; i < LastColumnMarker; ++i) { - switch (i) { - case Account: - headerLabels << i18n("Account"); - break; - case Type: - headerLabels << i18n("Type"); - break; - case Tax: - headerLabels << i18nc("Column heading for category in tax report", "Tax"); - break; - case VAT: - headerLabels << i18nc("Column heading for VAT category", "VAT"); - break; - case CostCenter: - headerLabels << i18nc("Column heading for Cost Center", "CC"); - break; - case TotalBalance: - headerLabels << i18n("Total Balance"); - break; - case PostedValue: - headerLabels << i18n("Posted Value"); - break; - case TotalValue: - headerLabels << i18n("Total Value"); - break; - default: - headerLabels << QString(); - } - } + foreach (const auto column, d->m_columns) + headerLabels.append(getHeaderName(column)); setHorizontalHeaderLabels(headerLabels); } @@ -436,23 +555,27 @@ */ void AccountsModel::load() { + this->blockSignals(true); QStandardItem *rootItem = invisibleRootItem(); QFont font; font.setBold(true); - // Favorite accounts - QStandardItem *favoriteAccountsItem = new QStandardItem(i18n("Favorites")); - rootItem->appendRow(favoriteAccountsItem); - setData(favoriteAccountsItem->index(), i18n("Favorites"), FullNameRole); - setData(favoriteAccountsItem->index(), i18n("Favorites"), Qt::EditRole); - setData(favoriteAccountsItem->index(), favoritesAccountId, AccountIdRole); - setData(favoriteAccountsItem->index(), 0, DisplayOrderRole); - favoriteAccountsItem->setColumnCount(columnCount()); - favoriteAccountsItem->setIcon(QIcon::fromTheme(g_Icons[Icon::ViewBankAccount])); + // adding favourite accounts node + auto favoriteAccountsItem = new QStandardItem(); favoriteAccountsItem->setEditable(false); - favoriteAccountsItem->setFont(font); + rootItem->appendRow(favoriteAccountsItem); + { + QMap itemData; + itemData[Qt::DisplayRole] = itemData[Qt::EditRole] = itemData[FullNameRole] = i18n("Favorites"); + itemData[Qt::FontRole] = font; + itemData[Qt::DecorationRole] = QIcon::fromTheme(g_Icons.value(Icon::ViewBankAccount)); + itemData[AccountIdRole] = favoritesAccountId; + itemData[DisplayOrderRole] = 0; + this->setItemData(favoriteAccountsItem->index(), itemData); + } + // adding account categories (asset, liability, etc.) node for (int mask = 0x01; mask != KMyMoneyUtils::last; mask <<= 1) { MyMoneyAccount account; QString accountName; @@ -463,81 +586,72 @@ account = d->m_file->asset(); accountName = i18n("Asset accounts"); displayOrder = 1; - } - - if ((mask & KMyMoneyUtils::liability) != 0) { + } else if ((mask & KMyMoneyUtils::liability) != 0) { // Liability accounts account = d->m_file->liability(); accountName = i18n("Liability accounts"); displayOrder = 2; - } - - if ((mask & KMyMoneyUtils::income) != 0) { + } else if ((mask & KMyMoneyUtils::income) != 0) { // Income categories account = d->m_file->income(); accountName = i18n("Income categories"); displayOrder = 3; - } - - if ((mask & KMyMoneyUtils::expense) != 0) { + } else if ((mask & KMyMoneyUtils::expense) != 0) { // Expense categories account = d->m_file->expense(); accountName = i18n("Expense categories"); displayOrder = 4; - } - - if ((mask & KMyMoneyUtils::equity) != 0) { + } else if ((mask & KMyMoneyUtils::equity) != 0) { // Equity accounts account = d->m_file->equity(); accountName = i18n("Equity accounts"); displayOrder = 5; } - QStandardItem *accountsItem = new QStandardItem(accountName); - rootItem->appendRow(accountsItem); - setData(accountsItem->index(), QVariant(displayOrder), DisplayOrderRole); - setData(accountsItem->index(), MyMoneyFile::instance()->accountToCategory(account.id(), true), FullNameRole); - setData(accountsItem->index(), MyMoneyFile::instance()->accountToCategory(account.id(), true), Qt::EditRole); - accountsItem->setColumnCount(columnCount()); - accountsItem->setFont(font); + auto accountsItem = new QStandardItem(accountName); accountsItem->setEditable(false); + rootItem->appendRow(accountsItem); - QStringList list = account.accountList(); + { + QMap itemData; + itemData[Qt::DisplayRole] = accountName; + itemData[FullNameRole] = itemData[Qt::EditRole] = QVariant::fromValue(MyMoneyFile::instance()->accountToCategory(account.id(), true)); + itemData[Qt::FontRole] = font; + itemData[DisplayOrderRole] = displayOrder; + this->setItemData(accountsItem->index(), itemData); + } - for (QStringList::ConstIterator it_l = list.constBegin(); it_l != list.constEnd(); ++it_l) { - const MyMoneyAccount& acc = d->m_file->account(*it_l); + // adding accounts (specific bank/investment accounts) belonging to given accounts category + const auto accountsStr = account.accountList(); + foreach (const auto accStr, accountsStr) { + const auto acc = d->m_file->account(accStr); - QStandardItem *item = new QStandardItem(acc.name()); + auto item = new QStandardItem(acc.name()); accountsItem->appendRow(item); - item->setColumnCount(columnCount()); item->setEditable(false); - QStringList subaccountsList = acc.accountList(); + auto subaccountsStr = acc.accountList(); // filter out stocks with zero balance if requested by user - for (QStringList::Iterator it = subaccountsList.begin(); it != subaccountsList.end();) { - const MyMoneyAccount& subAcc = d->m_file->account(*it); - if (subAcc.isInvest() && KMyMoneyGlobalSettings::hideZeroBalanceEquities() && subAcc.balance().isZero()) - it = subaccountsList.erase(it); + for (auto subaccStr = subaccountsStr.begin(); subaccStr != subaccountsStr.end();) { + const auto subacc = d->m_file->account(*subaccStr); + if (subacc.isInvest() && KMyMoneyGlobalSettings::hideZeroBalanceEquities() && subacc.balance().isZero()) + subaccStr = subaccountsStr.erase(subaccStr); else - ++it; - } - if (!subaccountsList.isEmpty()) - d->loadSubAccounts(this, item, favoriteAccountsItem, subaccountsList); - d->setAccountData(this, item->index(), acc); - // set the account data after the children have been loaded - if (acc.value("PreferredAccount") == "Yes") { - item = new QStandardItem(acc.name()); - favoriteAccountsItem->appendRow(item); - item->setColumnCount(columnCount()); - item->setEditable(false); - d->setAccountData(this, item->index(), acc); + ++subaccStr; } + + // adding subaccounts (e.g. stocks under given investment account) belonging to given account + d->loadSubaccounts(item, favoriteAccountsItem, subaccountsStr); + const auto row = item->row(); + d->setAccountData(accountsItem, row, acc, d->m_columns); + d->loadPreferredAccount(acc, accountsItem, row, favoriteAccountsItem); } - d->setAccountData(this, accountsItem->index(), account); + d->setAccountData(rootItem, accountsItem->row(), account, d->m_columns); } checkNetWorth(); checkProfit(); + this->blockSignals(false); } QModelIndex AccountsModel::accountById(const QString& id) const @@ -554,6 +668,105 @@ return QModelIndex(); } +QList *AccountsModel::getColumns() +{ + return &d->m_columns; +} + +void AccountsModel::setColumnVisibility(const Columns column, const bool show) +{ + const auto ixCol = d->m_columns.indexOf(column); // get column index in our column's map + if (!show && ixCol != -1) { // start removing column row by row from bottom to up + d->m_columns.removeOne(column); // remove it from our column's map + blockSignals(true); // block signals to not emit resources consuming dataChanged + for (auto i = 0; i < rowCount(); ++i) { + // recursive lambda function to remove cell belonging to unwanted column from all rows + auto removeCellFromRow = [=](auto &&self, QStandardItem *item) -> bool { + for(auto j = 0; j < item->rowCount(); ++j) { + auto childItem = item->child(j); + if (childItem->hasChildren()) + self(self, childItem); + childItem->removeColumn(ixCol); + } + return true; + }; + + auto topItem = item(i); + if (topItem->hasChildren()) + removeCellFromRow(removeCellFromRow, topItem); + topItem->removeColumn(ixCol); + } + blockSignals(false); // unblock signals, so model can update itself with new column + removeColumn(ixCol); // remove column from invisible root item which triggers model's view update + } else if (show && ixCol == -1) { // start inserting columns row by row from up to bottom (otherwise columns will be inserted automatically) + auto model = qobject_cast(this); + const auto isInstitutionsModel = model ? true : false; // if it's institution's model, then don't set any data on institution nodes + + auto newColPos = 0; + for(; newColPos < d->m_columns.count(); ++newColPos) { + if (d->m_columns.at(newColPos) > column) + break; + } + d->m_columns.insert(newColPos, column); // insert columns according to enum order for cleanliness + + insertColumn(newColPos); + setHorizontalHeaderItem(newColPos, new QStandardItem(getHeaderName(column))); + blockSignals(true); + for (auto i = 0; i < rowCount(); ++i) { + // recursive lambda function to remove cell belonging to unwanted column from all rows + auto addCellToRow = [&, newColPos](auto &&self, QStandardItem *item) -> bool { + for(auto j = 0; j < item->rowCount(); ++j) { + auto childItem = item->child(j); + childItem->insertColumns(newColPos, 1); + if (childItem->hasChildren()) + self(self, childItem); + this->d->setAccountData(item, j, childItem->data(AccountRole).value(), QList {column}); + } + return true; + }; + + auto topItem = item(i); + topItem->insertColumns(newColPos, 1); + if (topItem->hasChildren()) + addCellToRow(addCellToRow, topItem); + + if (isInstitutionsModel) + d->setInstitutionTotalValue(invisibleRootItem(), i); + else if (i !=0) // favourites node doesn't play well here, so exclude it from update + d->setAccountData(invisibleRootItem(), i, topItem->data(AccountRole).value(), QList {column}); + } + blockSignals(false); + } +} + +QString AccountsModel::getHeaderName(const Columns column) +{ + switch(column) { + case Account: + return i18n("Account"); + case Type: + return i18n("Type"); + case Tax: + return i18nc("Column heading for category in tax report", "Tax"); + case VAT: + return i18nc("Column heading for VAT category", "VAT"); + case CostCenter: + return i18nc("Column heading for Cost Center", "CC"); + case TotalBalance: + return i18n("Total Balance"); + case PostedValue: + return i18n("Posted Value"); + case TotalValue: + return i18n("Total Value"); + case AccountNumber: + return i18n("Number"); + case AccountSortCode: + return i18nc("IBAN, SWIFT, etc.", "Sort Code"); + default: + return QString(); + } +} + /** * Check if netWorthChanged should be emitted. */ @@ -574,12 +787,11 @@ MyMoneyMoney netWorth; if (!assetList.isEmpty() && !liabilityList.isEmpty()) { - QVariant assetValue = data(assetList.front(), AccountsModel::AccountTotalValueRole); - QVariant liabilityValue = data(liabilityList.front(), AccountsModel::AccountTotalValueRole); + const auto assetValue = data(assetList.front(), AccountsModel::AccountTotalValueRole); + const auto liabilityValue = data(liabilityList.front(), AccountsModel::AccountTotalValueRole); - if (assetValue.isValid() && liabilityValue.isValid()) { + if (assetValue.isValid() && liabilityValue.isValid()) netWorth = assetValue.value() - liabilityValue.value(); - } } if (d->m_lastNetWorth != netWorth) { d->m_lastNetWorth = netWorth; @@ -593,26 +805,25 @@ void AccountsModel::checkProfit() { // compute the profit - QModelIndexList incomeList = match(index(0, 0), - AccountsModel::AccountIdRole, - MyMoneyFile::instance()->income().id(), - 1, - Qt::MatchFlags(Qt::MatchExactly | Qt::MatchCaseSensitive)); - - QModelIndexList expenseList = match(index(0, 0), - AccountsModel::AccountIdRole, - MyMoneyFile::instance()->expense().id(), - 1, - Qt::MatchFlags(Qt::MatchExactly | Qt::MatchCaseSensitive)); + const auto incomeList = match(index(0, 0), + AccountsModel::AccountIdRole, + MyMoneyFile::instance()->income().id(), + 1, + Qt::MatchFlags(Qt::MatchExactly | Qt::MatchCaseSensitive)); + + const auto expenseList = match(index(0, 0), + AccountsModel::AccountIdRole, + MyMoneyFile::instance()->expense().id(), + 1, + Qt::MatchFlags(Qt::MatchExactly | Qt::MatchCaseSensitive)); MyMoneyMoney profit; if (!incomeList.isEmpty() && !expenseList.isEmpty()) { - QVariant incomeValue = data(incomeList.front(), AccountsModel::AccountTotalValueRole); - QVariant expenseValue = data(expenseList.front(), AccountsModel::AccountTotalValueRole); + const auto incomeValue = data(incomeList.front(), AccountsModel::AccountTotalValueRole); + const auto expenseValue = data(expenseList.front(), AccountsModel::AccountTotalValueRole); - if (incomeValue.isValid() && expenseValue.isValid()) { + if (incomeValue.isValid() && expenseValue.isValid()) profit = incomeValue.value() - expenseValue.value(); - } } if (d->m_lastProfit != profit) { d->m_lastProfit = profit; @@ -635,17 +846,15 @@ if (d->m_reconciledAccount.id() != account.id()) { // first clear the flag of the old reconciliation account if (!d->m_reconciledAccount.id().isEmpty()) { - QModelIndexList list = match(index(0, 0), AccountsModel::AccountIdRole, QVariant(d->m_reconciledAccount.id()), -1, Qt::MatchFlags(Qt::MatchExactly | Qt::MatchCaseSensitive | Qt::MatchRecursive)); - foreach (const QModelIndex &index, list) { + const auto list = match(index(0, 0), AccountsModel::AccountIdRole, QVariant(d->m_reconciledAccount.id()), -1, Qt::MatchFlags(Qt::MatchExactly | Qt::MatchCaseSensitive | Qt::MatchRecursive)); + foreach (const auto index, list) setData(index, QVariant(QIcon(account.accountPixmap(false))), Qt::DecorationRole); - } } // then set the reconciliation flag of the new reconciliation account - QModelIndexList list = match(index(0, 0), AccountsModel::AccountIdRole, QVariant(account.id()), -1, Qt::MatchFlags(Qt::MatchExactly | Qt::MatchCaseSensitive | Qt::MatchRecursive)); - foreach (const QModelIndex &index, list) { + const auto list = match(index(0, 0), AccountsModel::AccountIdRole, QVariant(account.id()), -1, Qt::MatchFlags(Qt::MatchExactly | Qt::MatchCaseSensitive | Qt::MatchRecursive)); + foreach (const auto index, list) setData(index, QVariant(QIcon(account.accountPixmap(true))), Qt::DecorationRole); - } d->m_reconciledAccount = account; } } @@ -663,32 +872,21 @@ if (!account) return; - QStandardItem *favoriteAccountsItem = d->itemFromAccountId(this, favoritesAccountId); - QStandardItem *parentAccountItem = d->itemFromAccountId(this, account->parentAccountId()); - QStandardItem *item = d->itemFromAccountId(parentAccountItem, account->id()); + auto favoriteAccountsItem = d->itemFromAccountId(this, favoritesAccountId); + auto parentAccountItem = d->itemFromAccountId(this, account->parentAccountId()); + auto item = d->itemFromAccountId(parentAccountItem, account->id()); if (!item) { item = new QStandardItem(account->name()); parentAccountItem->appendRow(item); - item->setColumnCount(columnCount()); item->setEditable(false); } // load the sub-accounts if there are any - there could be sub accounts if this is an add operation // that was triggered in slotObjectModified on an already existing account which went trough a hierarchy change - if (account->accountList().count() > 0) { - d->loadSubAccounts(this, item, favoriteAccountsItem, account->accountList()); - } - d->setAccountData(this, item->index(), *account); - // set the account data - if (account->value("PreferredAccount") == "Yes") { - QStandardItem *item = d->itemFromAccountId(favoriteAccountsItem, account->id()); - if (!item) { - item = new QStandardItem(account->name()); - favoriteAccountsItem->appendRow(item); - item->setColumnCount(columnCount()); - item->setEditable(false); - } - d->setAccountData(this, item->index(), *account); - } + d->loadSubaccounts(item, favoriteAccountsItem, account->accountList()); + + const auto row = item->row(); + d->setAccountData(parentAccountItem, row, *account, d->m_columns); + d->loadPreferredAccount(*account, parentAccountItem, row, favoriteAccountsItem); checkNetWorth(); checkProfit(); @@ -706,30 +904,22 @@ const MyMoneyAccount * const account = dynamic_cast(obj); if (!account) return; - - QStandardItem *favoriteAccountsItem = d->itemFromAccountId(this, favoritesAccountId); - QStandardItem *accountItem = d->itemFromAccountId(this, account->id()); - MyMoneyAccount oldAccount = accountItem->data(AccountRole).value(); + auto favoriteAccountsItem = d->itemFromAccountId(this, favoritesAccountId); + auto accountItem = d->itemFromAccountId(this, account->id()); + const auto oldAccount = accountItem->data(AccountRole).value(); if (oldAccount.parentAccountId() == account->parentAccountId()) { // the hierarchy did not change so update the account data - d->setAccountData(this, accountItem->index(), *account); + auto parentAccountItem = accountItem->parent(); + if (!parentAccountItem) + parentAccountItem = this->invisibleRootItem(); + const auto row = accountItem->row(); + d->setAccountData(parentAccountItem, row, *account, d->m_columns); // and the child of the favorite item if the account is a favorite account or it's favorite status has just changed - QStandardItem *item = d->itemFromAccountId(favoriteAccountsItem, account->id()); - if (account->value("PreferredAccount") == "Yes") { - if (!item) { - // the favorite item for this account does not exist and the account is favorite - item = new QStandardItem(account->name()); - favoriteAccountsItem->appendRow(item); - item->setColumnCount(columnCount()); - item->setEditable(false); - } - d->setAccountData(this, item->index(), *account); - } else { - if (item) { - // it's not favorite anymore - removeRow(item->index().row(), item->index().parent()); - } - } + auto favItem = d->itemFromAccountId(favoriteAccountsItem, account->id()); + if (account->value("PreferredAccount") == QLatin1String("Yes")) + d->loadPreferredAccount(*account, parentAccountItem, row, favoriteAccountsItem); + else if (favItem) + favoriteAccountsItem->removeRow(favItem->row()); // it's not favorite anymore } else { // this means that the hierarchy was changed - simulate this with a remove followed by and add operation slotObjectRemoved(MyMoneyFile::notifyAccount, oldAccount.id()); @@ -749,10 +939,9 @@ if (objType != MyMoneyFile::notifyAccount) return; - QModelIndexList list = match(index(0, 0), AccountsModel::AccountIdRole, id, -1, Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive)); - foreach (const QModelIndex &index, list) { + auto list = match(index(0, 0), AccountsModel::AccountIdRole, id, -1, Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive)); + foreach (const auto index, list) removeRow(index.row(), index.parent()); - } checkNetWorth(); checkProfit(); @@ -763,12 +952,21 @@ */ void AccountsModel::slotBalanceOrValueChanged(const MyMoneyAccount &account) { - QStandardItem *currentItem = d->itemFromAccountId(this, account.id()); - const MyMoneyAccount *currentAccount = &account; - while (currentItem) { - d->setAccountBalanceAndValue(this, currentItem->index(), *currentAccount); - currentItem = currentItem->parent(); - currentAccount = &d->m_file->account(currentAccount->parentAccountId()); + auto itParent = d->itemFromAccountId(this, account.id()); // get node of account in model + auto isTopLevel = false; // it could be top-level but we don't know it yet + while (itParent && !isTopLevel) { // loop in which we set total values and balances from the bottom to the top + auto itCurrent = itParent; + auto accCurrent = &d->m_file->account(itCurrent->data(AccountRole).value().id()); + if (accCurrent->id().isEmpty()) { // this is institution + d->setInstitutionTotalValue(invisibleRootItem(), itCurrent->row()); + break; // it's top-level node so nothing above that; + } + itParent = itCurrent->parent(); + if (!itParent) { + itParent = this->invisibleRootItem(); + isTopLevel = true; + } + d->setAccountBalanceAndValue(itParent, itCurrent->row(), *accCurrent, d->m_columns); } checkNetWorth(); checkProfit(); @@ -789,11 +987,10 @@ * @return The item corresponding to the given institution id, NULL if the institution was not found. */ QStandardItem *institutionItemFromId(QStandardItemModel *model, const QString &institutionId) { - QModelIndexList list = model->match(model->index(0, 0), AccountsModel::AccountIdRole, QVariant(institutionId), 1, Qt::MatchFlags(Qt::MatchExactly | Qt::MatchCaseSensitive)); - if (list.count() > 0) { + const auto list = model->match(model->index(0, 0), AccountsModel::AccountIdRole, QVariant(institutionId), 1, Qt::MatchFlags(Qt::MatchExactly | Qt::MatchCaseSensitive)); + if (!list.isEmpty()) return model->itemFromIndex(list.front()); - } - return 0; + return nullptr; // this should rarely fail as we add all institutions early on } /** @@ -807,51 +1004,34 @@ if (!account.isAssetLiability() && !account.isInvest()) return; - QFont font; - font.setBold(true); - - QString institutionId = account.institutionId(); - if (account.isInvest()) { - MyMoneyAccount parentAccount = m_file->account(account.parentAccountId()); - institutionId = parentAccount.institutionId(); + // we've got account but don't know under which institution it should be added, so we find it out + auto idInstitution = account.institutionId(); + if (account.isInvest()) { // if it's stock account then... + const auto investmentAccount = m_file->account(account.parentAccountId()); // ...get investment account it's under and... + idInstitution = investmentAccount.institutionId(); // ...get institution from investment account } - QStandardItem *institutionItem = institutionItemFromId(model, institutionId); - QStandardItem *item = itemFromAccountId(institutionItem, account.id()); - // only investment accounts are added to their parent in the institutions view - // this makes hierarchy maintenance a lot easier since the investment accounts + auto itInstitution = institutionItemFromId(model, idInstitution); + auto itAccount = itemFromAccountId(itInstitution, account.id()); // check if account already exists under institution + // only stock accounts are added to their parent in the institutions view + // this makes hierarchy maintenance a lot easier since the stock accounts // are the only ones that always have the same institution as their parent - QStandardItem *parentAccounItem = account.isInvest() ? itemFromAccountId(institutionItem, account.parentAccountId()) : 0; - if (!item) { - item = new QStandardItem(account.name()); - if (parentAccounItem) { - parentAccounItem->appendRow(item); - } else { - institutionItem->appendRow(item); - } - item->setColumnCount(model->columnCount()); - item->setEditable(false); - } - setAccountData(model, item->index(), account); - if (parentAccounItem) - setAccountData(model, parentAccounItem->index(), m_file->account(account.parentAccountId())); - MyMoneyMoney accountTotalValue = item->data(AccountTotalValueRole).value(); - if (account.accountGroup() == MyMoneyAccount::Liability) { - accountTotalValue = -accountTotalValue; // the account is a liability so change the account value sign + auto itInvestmentAccount = account.isInvest() ? itemFromAccountId(itInstitution, account.parentAccountId()) : nullptr; + if (!itAccount) { + itAccount = new QStandardItem(account.name()); + if (itInvestmentAccount) // stock account nodes go under investment account nodes and... + itInvestmentAccount->appendRow(itAccount); + else if (itInstitution) // ...the rest goes under institution's node + itInstitution->appendRow(itAccount); + else + return; + itAccount->setEditable(false); } - MyMoneyMoney institutionValue = institutionItem->data(AccountTotalValueRole).value() + accountTotalValue; - institutionItem->setData(QVariant::fromValue(institutionValue), AccountTotalValueRole); - QModelIndex instIndex = institutionItem->index(); - QModelIndex newIndex = model->index(instIndex.row(), instIndex.column() + TotalValue, instIndex.parent()); - if (institutionValue.isNegative()) { - model->setData(newIndex, KMyMoneyGlobalSettings::listNegativeValueColor(), Qt::ForegroundRole); - } else { - model->setData(newIndex, KColorScheme(QPalette::Active).foreground(KColorScheme::NormalText).color(), Qt::ForegroundRole); + if (itInvestmentAccount) { + setAccountData(itInvestmentAccount, itAccount->row(), account, m_columns); // set data for stock account node + setAccountData(itInstitution, itInvestmentAccount->row(), m_file->account(account.parentAccountId()), m_columns); // set data for investment account node + } else if (itInstitution) { + setAccountData(itInstitution, itAccount->row(), account, m_columns); } - - model->setData(newIndex, MyMoneyUtils::formatMoney(institutionValue, m_file->baseCurrency()), Qt::DisplayRole); - model->setData(newIndex, MyMoneyUtils::formatMoney(institutionValue, m_file->baseCurrency()), AccountTotalValueDisplayRole); - model->setData(newIndex, font, Qt::FontRole); - model->setData(newIndex, QVariant(Qt::AlignRight | Qt::AlignVCenter), Qt::TextAlignmentRole); } /** @@ -864,19 +1044,15 @@ void addInstitutionItem(QStandardItemModel *model, const MyMoneyInstitution &institution) { QFont font; font.setBold(true); - QStandardItem *institutionItem = new QStandardItem(institution.name()); - model->invisibleRootItem()->appendRow(institutionItem); - institutionItem->setData(institution.name(), Qt::DisplayRole); - institutionItem->setData(QVariant::fromValue(institution), AccountRole); - institutionItem->setData(QVariant::fromValue(MyMoneyMoney()), AccountBalanceRole); - institutionItem->setData(QVariant::fromValue(MyMoneyMoney()), AccountValueRole); - institutionItem->setData(QVariant::fromValue(MyMoneyMoney()), AccountTotalValueRole); - institutionItem->setData(institution.id(), AccountIdRole); - institutionItem->setData(6, DisplayOrderRole); - institutionItem->setColumnCount(model->columnCount()); - institutionItem->setIcon(institution.pixmap()); - institutionItem->setFont(font); - institutionItem->setEditable(false); + auto itInstitution = new QStandardItem(QIcon::fromTheme(g_Icons.value(Icon::ViewInstitutions)), institution.name()); + itInstitution->setFont(font); + itInstitution->setData(QVariant::fromValue(MyMoneyMoney()), AccountTotalValueRole); + itInstitution->setData(institution.id(), AccountIdRole); + itInstitution->setData(QVariant::fromValue(institution), AccountRole); + itInstitution->setData(6, DisplayOrderRole); + itInstitution->setEditable(false); + model->invisibleRootItem()->appendRow(itInstitution); + setInstitutionTotalValue(model->invisibleRootItem(), itInstitution->row()); } }; @@ -902,37 +1078,42 @@ MyMoneyInstitution none; none.setName(i18n("Accounts with no institution assigned")); institutionList.append(none); - foreach (const auto institution, institutionList) - static_cast(d)->addInstitutionItem(this, institution); + auto modelUtils = static_cast(d); + foreach (const auto institution, institutionList) // add all known institutions as top-level nodes + modelUtils->addInstitutionItem(this, institution); QList accountsList; QList stocksList; d->m_file->accountList(accountsList); - foreach (const auto account, accountsList) { // create items for all the accounts... + foreach (const auto account, accountsList) { // add account nodes under institution nodes... if (account.isInvest()) // ...but wait with stocks until investment accounts appear stocksList.append(account); else - static_cast(d)->loadInstitution(this, account); + modelUtils->loadInstitution(this, account); } foreach (const auto stock, stocksList) { if (!(KMyMoneyGlobalSettings::hideZeroBalanceEquities() && stock.balance().isZero())) - static_cast(d)->loadInstitution(this, stock); + modelUtils->loadInstitution(this, stock); } + + for (auto i = 0 ; i < rowCount(); ++i) + d->setInstitutionTotalValue(invisibleRootItem(), i); } /** * Notify the model that an object has been added. An action is performed only if the object is an account or an institution. * */ void InstitutionsModel::slotObjectAdded(MyMoneyFile::notificationObjectT objType, const MyMoneyObject * const obj) { + auto modelUtils = static_cast(d); if (objType == MyMoneyFile::notifyInstitution) { // if an institution was added then add the item which will represent it const MyMoneyInstitution * const institution = dynamic_cast(obj); if (!institution) return; - static_cast(d)->addInstitutionItem(this, *institution); + modelUtils->addInstitutionItem(this, *institution); } if (objType != MyMoneyFile::notifyAccount) @@ -945,16 +1126,16 @@ return; // load the account into the institution - static_cast(d)->loadInstitution(this, *account); + modelUtils->loadInstitution(this, *account); // load the investment sub-accounts if there are any - there could be sub-accounts if this is an add operation // that was triggered in slotObjectModified on an already existing account which went trough a hierarchy change if (!account->accountList().isEmpty()) { QList subAccounts; d->m_file->accountList(subAccounts, account->accountList()); - for (QList::ConstIterator it_a = subAccounts.constBegin(); it_a != subAccounts.constEnd(); ++it_a) { - if ((*it_a).isInvest()) { - static_cast(d)->loadInstitution(this, *it_a); + foreach (const auto subAccount, subAccounts) { + if (subAccount.isInvest()) { + modelUtils->loadInstitution(this, subAccount); } } } @@ -971,7 +1152,7 @@ const MyMoneyInstitution * const institution = dynamic_cast(obj); if (!institution) return; - QStandardItem *institutionItem = static_cast(d)->institutionItemFromId(this, institution->id()); + auto institutionItem = static_cast(d)->institutionItemFromId(this, institution->id()); institutionItem->setData(institution->name(), Qt::DisplayRole); institutionItem->setData(QVariant::fromValue(*institution), AccountRole); institutionItem->setIcon(institution->pixmap()); @@ -986,11 +1167,11 @@ if (!account || account->parentAccountId().isEmpty() || account->isIncomeExpense() || account->accountType() == MyMoneyAccount::Equity) return; - QStandardItem *accountItem = d->itemFromAccountId(this, account->id()); - MyMoneyAccount oldAccount = accountItem->data(AccountRole).value(); + auto accountItem = d->itemFromAccountId(this, account->id()); + const auto oldAccount = accountItem->data(AccountRole).value(); if (oldAccount.institutionId() == account->institutionId()) { // the hierarchy did not change so update the account data - d->setAccountData(this, accountItem->index(), *account); + d->setAccountData(accountItem->parent(), accountItem->row(), *account, d->m_columns); } else { // this means that the hierarchy was changed - simulate this with a remove followed by and add operation slotObjectRemoved(MyMoneyFile::notifyAccount, oldAccount.id()); @@ -1006,45 +1187,24 @@ { if (objType == MyMoneyFile::notifyInstitution) { // if an institution was removed then remove the item which represents it - QStandardItem *institutionItem = static_cast(d)->institutionItemFromId(this, id); - if (institutionItem) - removeRow(institutionItem->row(), institutionItem->index().parent()); + auto itInstitution = static_cast(d)->institutionItemFromId(this, id); + if (itInstitution) + removeRow(itInstitution->row(), itInstitution->index().parent()); } if (objType != MyMoneyFile::notifyAccount) return; // if an account was removed then remove the item which represents it and recompute the institution's value - QStandardItem *accountItem = d->itemFromAccountId(this, id); - if (!accountItem) + auto itAccount = d->itemFromAccountId(this, id); + if (!itAccount) return; // this could happen if the account isIncomeExpense - MyMoneyAccount oldAccount = accountItem->data(AccountRole).value(); - QStandardItem *institutionItem = d->itemFromAccountId(this, oldAccount.institutionId()); - - MyMoneyMoney accountTotalValue = accountItem->data(AccountTotalValueRole).value(); - if (oldAccount.accountGroup() == MyMoneyAccount::Liability) { - accountTotalValue = -accountTotalValue; // the account is a liability so change the account value sign - } - MyMoneyMoney institutionValue = institutionItem->data(AccountTotalValueRole).value() - accountTotalValue; - institutionItem->setData(QVariant::fromValue(institutionValue), AccountTotalValueRole); - QModelIndex instIndex = institutionItem->index(); - QModelIndex newIndex = index(instIndex.row(), instIndex.column() + TotalValue, instIndex.parent()); - if (institutionValue.isNegative()) { - setData(newIndex, KMyMoneyGlobalSettings::listNegativeValueColor(), Qt::ForegroundRole); - } else { - setData(newIndex, KColorScheme(QPalette::Active).foreground(KColorScheme::NormalText).color(), Qt::ForegroundRole); - } - - QFont font; - font.setBold(true); - - setData(newIndex, MyMoneyUtils::formatMoney(institutionValue, d->m_file->baseCurrency()), Qt::DisplayRole); - setData(newIndex, MyMoneyUtils::formatMoney(institutionValue, d->m_file->baseCurrency()), AccountTotalValueDisplayRole); - setData(newIndex, font, Qt::FontRole); - setData(newIndex, QVariant(Qt::AlignRight | Qt::AlignVCenter), Qt::TextAlignmentRole); + const auto account = itAccount->data(AccountRole).value(); + auto itInstitution = d->itemFromAccountId(this, account.institutionId()); AccountsModel::slotObjectRemoved(objType, id); + d->setInstitutionTotalValue(invisibleRootItem(), itInstitution->row()); } /** @@ -1089,12 +1249,14 @@ */ bool AccountsFilterProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const { + if (!left.isValid() || !right.isValid()) + return false; // different sorting based on the column which is being sorted - switch (left.column()) { + switch (m_mdlColumns->at(left.column())) { // for the accounts column sort based on the DisplayOrderRole case AccountsModel::Account: { - QVariant leftData = sourceModel()->data(left, AccountsModel::DisplayOrderRole); - QVariant rightData = sourceModel()->data(right, AccountsModel::DisplayOrderRole); + const auto leftData = sourceModel()->data(left, AccountsModel::DisplayOrderRole); + const auto rightData = sourceModel()->data(right, AccountsModel::DisplayOrderRole); if (leftData.toInt() == rightData.toInt()) { // sort items of the same display order alphabetically @@ -1105,20 +1267,30 @@ // the total balance and value columns are sorted based on the value of the account case AccountsModel::TotalBalance: case AccountsModel::TotalValue: { - QVariant leftData = sourceModel()->data(sourceModel()->index(left.row(), 0, left.parent()), AccountsModel::AccountTotalValueRole); - QVariant rightData = sourceModel()->data(sourceModel()->index(right.row(), 0, right.parent()), AccountsModel::AccountTotalValueRole); + const auto leftData = sourceModel()->data(sourceModel()->index(left.row(), AccountsModel::Account, left.parent()), AccountsModel::AccountTotalValueRole); + const auto rightData = sourceModel()->data(sourceModel()->index(right.row(), AccountsModel::Account, right.parent()), AccountsModel::AccountTotalValueRole); return leftData.value() < rightData.value(); } + default: + break; } return QSortFilterProxyModel::lessThan(left, right); } +bool AccountsFilterProxyModel::filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const +{ + Q_UNUSED(source_parent) + if (m_visColumns->isEmpty() || m_visColumns->contains(m_mdlColumns->at(source_column))) + return true; + return false; +} + /** * This function was re-implemented to consider all the filtering aspects that we need in the application. */ bool AccountsFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { - QModelIndex index = sourceModel()->index(source_row, 0, source_parent); + const auto index = sourceModel()->index(source_row, AccountsModel::Account, source_parent); return acceptSourceItem(index) && filterAcceptsRowOrChildRows(source_row, source_parent); } @@ -1128,12 +1300,11 @@ */ bool AccountsFilterProxyModel::filterAcceptsRowOrChildRows(int source_row, const QModelIndex &source_parent) const { - if (QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent)) { + if (QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent)) return true; - } - QModelIndex index = sourceModel()->index(source_row, 0, source_parent); - for (int i = 0; i < sourceModel()->rowCount(index); ++i) { + const auto index = sourceModel()->index(source_row, AccountsModel::Account, source_parent); + for (auto i = 0; i < sourceModel()->rowCount(index); ++i) { if (filterAcceptsRowOrChildRows(i, index)) return true; } @@ -1145,29 +1316,39 @@ * @param group The account group to be added. * @see MyMoneyAccount::accountTypeE */ -void AccountsFilterProxyModel::addAccountGroup(MyMoneyAccount::accountTypeE group) +void AccountsFilterProxyModel::addAccountGroup(const QVector &groups) { - if (group == MyMoneyAccount::Asset) { - d->m_typeList << MyMoneyAccount::Checkings; - d->m_typeList << MyMoneyAccount::Savings; - d->m_typeList << MyMoneyAccount::Cash; - d->m_typeList << MyMoneyAccount::AssetLoan; - d->m_typeList << MyMoneyAccount::CertificateDep; - d->m_typeList << MyMoneyAccount::Investment; - d->m_typeList << MyMoneyAccount::Stock; - d->m_typeList << MyMoneyAccount::MoneyMarket; - d->m_typeList << MyMoneyAccount::Asset; - d->m_typeList << MyMoneyAccount::Currency; - } else if (group == MyMoneyAccount::Liability) { - d->m_typeList << MyMoneyAccount::CreditCard; - d->m_typeList << MyMoneyAccount::Loan; - d->m_typeList << MyMoneyAccount::Liability; - } else if (group == MyMoneyAccount::Income) { - d->m_typeList << MyMoneyAccount::Income; - } else if (group == MyMoneyAccount::Expense) { - d->m_typeList << MyMoneyAccount::Expense; - } else if (group == MyMoneyAccount::Equity) { - d->m_typeList << MyMoneyAccount::Equity; + foreach (const auto group, groups) { + switch (group) { + case MyMoneyAccount::Asset: + d->m_typeList << MyMoneyAccount::Checkings; + d->m_typeList << MyMoneyAccount::Savings; + d->m_typeList << MyMoneyAccount::Cash; + d->m_typeList << MyMoneyAccount::AssetLoan; + d->m_typeList << MyMoneyAccount::CertificateDep; + d->m_typeList << MyMoneyAccount::Investment; + d->m_typeList << MyMoneyAccount::Stock; + d->m_typeList << MyMoneyAccount::MoneyMarket; + d->m_typeList << MyMoneyAccount::Asset; + d->m_typeList << MyMoneyAccount::Currency; + break; + case MyMoneyAccount::Liability: + d->m_typeList << MyMoneyAccount::CreditCard; + d->m_typeList << MyMoneyAccount::Loan; + d->m_typeList << MyMoneyAccount::Liability; + break; + case MyMoneyAccount::Income: + d->m_typeList << MyMoneyAccount::Income; + break; + case MyMoneyAccount::Expense: + d->m_typeList << MyMoneyAccount::Expense; + break; + case MyMoneyAccount::Equity: + d->m_typeList << MyMoneyAccount::Equity; + break; + default: + break; + } } invalidate(); } @@ -1210,10 +1391,10 @@ bool AccountsFilterProxyModel::acceptSourceItem(const QModelIndex &source) const { if (source.isValid()) { - QVariant data = sourceModel()->data(source, AccountsModel::AccountRole); + const auto data = sourceModel()->data(source, AccountsModel::AccountRole); if (data.isValid()) { if (data.canConvert()) { - MyMoneyAccount account = data.value(); + const auto account = data.value(); if ((hideClosedAccounts() && account.isClosed())) return false; @@ -1227,27 +1408,26 @@ // we hide unused income and expense accounts if the specific flag is set if ((account.accountType() == MyMoneyAccount::Income || account.accountType() == MyMoneyAccount::Expense) && hideUnusedIncomeExpenseAccounts()) { - QVariant totalValue = sourceModel()->data(source, AccountsModel::AccountTotalValueRole); + const auto totalValue = sourceModel()->data(source, AccountsModel::AccountTotalValueRole); if (totalValue.isValid() && totalValue.value().isZero()) { emit unusedIncomeExpenseAccountHidden(); return false; } } if (d->m_typeList.contains(account.accountType())) return true; - } - if (data.canConvert() && sourceModel()->rowCount(source) == 0) { + } else if (data.canConvert() && sourceModel()->rowCount(source) == 0) { // if this is an institution that has no children show it only if hide unused institutions (hide closed accounts for now) is not checked return !hideClosedAccounts(); } // let the visibility of all other institutions (the ones with children) be controlled by the visibility of their children } // all parents that have at least one visible child must be visible - int rowCount = sourceModel()->rowCount(source); - for (int i = 0; i < rowCount; ++i) { - QModelIndex index = sourceModel()->index(i, 0, source); + const auto rowCount = sourceModel()->rowCount(source); + for (auto i = 0; i < rowCount; ++i) { + const auto index = sourceModel()->index(i, AccountsModel::Account, source); if (acceptSourceItem(index)) return true; } @@ -1322,12 +1502,12 @@ */ int AccountsFilterProxyModel::visibleItems(bool includeBaseAccounts) const { - int rows = 0; - for (int i = 0; i < rowCount(QModelIndex()); ++i) { + auto rows = 0; + for (auto i = 0; i < rowCount(QModelIndex()); ++i) { if(includeBaseAccounts) { ++rows; } - QModelIndex childIndex = index(i, 0); + const auto childIndex = index(i, 0); if (hasChildren(childIndex)) { rows += visibleItems(childIndex); } @@ -1342,16 +1522,29 @@ */ int AccountsFilterProxyModel::visibleItems(const QModelIndex& index) const { - int rows = 0; - if (index.isValid() && index.column() == 0) { - const QAbstractItemModel *model = index.model(); - for (int i = 0; i < model->rowCount(index); ++i) { + auto rows = 0; + if (index.isValid() && index.column() == AccountsModel::Account) { // CAUTION! Assumption is being made that Account column number is always 0 + const auto *model = index.model(); + const auto rowCount = model->rowCount(index); + for (auto i = 0; i < rowCount; ++i) { ++rows; - QModelIndex childIndex = model->index(i, index.column(), index); - if (model->hasChildren(childIndex)) { + const auto childIndex = model->index(i, index.column(), index); + if (model->hasChildren(childIndex)) rows += visibleItems(childIndex); - } } } return rows; } + +void AccountsFilterProxyModel::init(AccountsModel *model, QList *visColumns) +{ + m_mdlColumns = model->getColumns(); + m_visColumns = visColumns; + setSourceModel(model); +} + +void AccountsFilterProxyModel::init(AccountsModel *model) +{ + setSourceModel(model); + m_visColumns = m_mdlColumns = model->getColumns(); +} diff --git a/kmymoney/models/onlinebankingaccountsfilterproxymodel.cpp b/kmymoney/models/onlinebankingaccountsfilterproxymodel.cpp --- a/kmymoney/models/onlinebankingaccountsfilterproxymodel.cpp +++ b/kmymoney/models/onlinebankingaccountsfilterproxymodel.cpp @@ -49,10 +49,11 @@ bool OnlineBankingAccountsFilterProxyModel::filterAcceptsParent(const QModelIndex& index) const { - const int rowCount = sourceModel()->rowCount(index); - for (int i = 0; i < rowCount; i++) { - const QModelIndex childIndex = sourceModel()->index(i, 0, index); - if (onlineJobAdministration::instance()->isAnyJobSupported(sourceModel()->data(childIndex, AccountsModel::AccountIdRole).toString())) + auto const model = sourceModel(); + const auto rowCount = model->rowCount(index); + for (auto i = 0; i < rowCount; ++i) { + const auto childIndex = model->index(i, AccountsModel::Account, index); // CAUTION! Assumption is being made that Account column number is always 0 + if (onlineJobAdministration::instance()->isAnyJobSupported(model->data(childIndex, AccountsModel::AccountIdRole).toString())) return true; if (filterAcceptsParent(childIndex)) return true; diff --git a/kmymoney/mymoney/mymoneyaccount.cpp b/kmymoney/mymoney/mymoneyaccount.cpp --- a/kmymoney/mymoney/mymoneyaccount.cpp +++ b/kmymoney/mymoney/mymoneyaccount.cpp @@ -682,11 +682,11 @@ }; Icon ixIcon = accToIco.value(accountType(), Icon::ViewLiability); - QString kyIcon = g_Icons[ixIcon] + QString(size); + QString kyIcon = g_Icons.value(ixIcon) + QString::number(size); QPixmap pxIcon; if (!QPixmapCache::find(kyIcon, pxIcon)) { - pxIcon = QIcon::fromTheme(g_Icons[ixIcon]).pixmap(size); // Qt::AA_UseHighDpiPixmaps (in Qt 5.7) doesn't return highdpi pixmap + pxIcon = QIcon::fromTheme(g_Icons.value(ixIcon)).pixmap(size); // Qt::AA_UseHighDpiPixmaps (in Qt 5.7) doesn't return highdpi pixmap QPixmapCache::insert(kyIcon, pxIcon); } diff --git a/kmymoney/views/kaccountsview.h b/kmymoney/views/kaccountsview.h --- a/kmymoney/views/kaccountsview.h +++ b/kmymoney/views/kaccountsview.h @@ -1,8 +1,8 @@ /*************************************************************************** kaccountssview.h ------------------- - copyright : (C) 2005 by Thomas Baumgart - email : ipwizard@users.sourceforge.net + copyright : (C) 2007 by Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** @@ -34,66 +34,59 @@ #include "ui_kaccountsviewdecl.h" - +class KMyMoneyApp; /** * This class implements the accounts hierarchical and iconic 'view'. */ -class KAccountsView : public QWidget, private Ui::KAccountsViewDecl +class KAccountsView : public QWidget, public Ui::KAccountsViewDecl { Q_OBJECT public: - KAccountsView(QWidget *parent = 0); + explicit KAccountsView(KMyMoneyApp *kmymoney, KMyMoneyView *kmymoneyview); virtual ~KAccountsView(); + KRecursiveFilterProxyModel *getProxyModel(); + QList *getProxyColumns(); + bool isLoaded(); + public slots: void slotLoadAccounts(); protected: + void loadAccounts(); + + // for now it contains the implementation from show() + virtual void showEvent(QShowEvent * event); + enum accountViewRole { reconcileRole = Qt::UserRole + 1 }; void loadIconGroups(); protected slots: void slotNetWorthChanged(const MyMoneyMoney &); - void slotOpenContextMenu(MyMoneyAccount account); - void slotOpenObject(QListWidgetItem* item); void slotExpandCollapse(); void slotUnusedIncomeExpenseAccountHidden(); -signals: - /** - * This signal serves as proxy for KMyMoneyAccountTreeView::selectObject() - * - * @param obj const reference to object - */ - void selectObject(const MyMoneyObject& obj); +private: + KMyMoneyApp *m_kmymoney; + KMyMoneyView *m_kmymoneyview; - /** - * This signal serves as proxy for - * KMyMoneyAccountTreeView::openContextMenu(const MyMoneyObject&) - * - * @param obj const reference to object - */ - void openContextMenu(const MyMoneyObject& obj); + /** Initializes page and sets its load status to initialized + */ + void init(); - /** - * This signal will be emitted when the left mouse button is double - * clicked (actually the KDE executed setting is used) on an object. - * - * @param obj const reference to object - */ - void openObject(const MyMoneyObject& obj); + bool m_haveUnusedCategories; + + /// set if a view needs to be reloaded during show() + bool m_needReload; /** - * This signal is emitted whenever the view is about to be shown. + * This member holds the load state of page */ - void aboutToShow(); - -private: - bool m_haveUnusedCategories; + bool m_needLoad; AccountsViewFilterProxyModel *m_filterProxyModel; }; diff --git a/kmymoney/views/kaccountsview.cpp b/kmymoney/views/kaccountsview.cpp --- a/kmymoney/views/kaccountsview.cpp +++ b/kmymoney/views/kaccountsview.cpp @@ -1,8 +1,8 @@ /*************************************************************************** kaccountsview.cpp ------------------- - copyright : (C) 2005 by Thomas Baumgart - email : ipwizard@users.sourceforge.net + copyright : (C) 2007 by Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** @@ -50,69 +50,98 @@ using namespace Icons; -KAccountsView::KAccountsView(QWidget *parent) : - QWidget(parent) +KAccountsView::KAccountsView(KMyMoneyApp *kmymoney, KMyMoneyView *kmymoneyview) : + QWidget(nullptr), + m_kmymoney(kmymoney), + m_kmymoneyview(kmymoneyview), + m_needReload(false), + m_needLoad(true) { +} + +KAccountsView::~KAccountsView() +{ +} + +KRecursiveFilterProxyModel *KAccountsView::getProxyModel() +{ + return m_filterProxyModel; +} + +QList *KAccountsView::getProxyColumns() +{ + return m_accountTree->getColumns(KMyMoneyView::View::Accounts); +} + +bool KAccountsView::isLoaded() +{ + return !m_needLoad; +} + +void KAccountsView::init() +{ + m_needLoad = false; setupUi(this); // setup icons for collapse and expand button - KGuiItem collapseGuiItem(QString(), - QIcon::fromTheme(g_Icons[Icon::ListCollapse]), - QString(), - QString()); - KGuiItem expandGuiItem(QString(), - QIcon::fromTheme(g_Icons[Icon::ListExpand]), - QString(), - QString()); - KGuiItem::assign(m_collapseButton, collapseGuiItem); - KGuiItem::assign(m_expandButton, expandGuiItem); - - connect(Models::instance()->accountsModel(), SIGNAL(netWorthChanged(MyMoneyMoney)), this, SLOT(slotNetWorthChanged(MyMoneyMoney))); + m_collapseButton->setIcon(QIcon::fromTheme(g_Icons[Icon::ListCollapse])); + m_expandButton->setIcon(QIcon::fromTheme(g_Icons[Icon::ListExpand])); + + auto const model = Models::instance()->accountsModel(); // the proxy filter model m_filterProxyModel = new AccountsViewFilterProxyModel(this); - m_filterProxyModel->addAccountGroup(MyMoneyAccount::Asset); - m_filterProxyModel->addAccountGroup(MyMoneyAccount::Liability); - m_filterProxyModel->addAccountGroup(MyMoneyAccount::Equity); - if (KMyMoneyGlobalSettings::showCategoriesInAccountsView()) { - m_filterProxyModel->addAccountGroup(MyMoneyAccount::Income); - m_filterProxyModel->addAccountGroup(MyMoneyAccount::Expense); - } - m_filterProxyModel->setSourceModel(Models::instance()->accountsModel()); - m_filterProxyModel->setFilterKeyColumn(-1); - connect(m_filterProxyModel, SIGNAL(unusedIncomeExpenseAccountHidden()), this, SLOT(slotUnusedIncomeExpenseAccountHidden())); + QVector accGroups {MyMoneyAccount::Asset, MyMoneyAccount::Liability, MyMoneyAccount::Equity}; + if (KMyMoneyGlobalSettings::showCategoriesInAccountsView()) + accGroups << MyMoneyAccount::Income << MyMoneyAccount::Expense; - m_accountTree->setModel(m_filterProxyModel); - m_accountTree->setConfigGroupName("KAccountsView"); - m_accountTree->setAlternatingRowColors(true); - m_accountTree->setIconSize(QSize(22, 22)); - m_accountTree->setSortingEnabled(true); + m_filterProxyModel->addAccountGroup(accGroups); + m_filterProxyModel->init(model, getProxyColumns()); + m_filterProxyModel->setFilterKeyColumn(-1); + m_accountTree->init(m_filterProxyModel, model->getColumns()); - connect(m_searchWidget, SIGNAL(textChanged(QString)), m_filterProxyModel, SLOT(setFilterFixedString(QString))); + connect(m_accountTree, SIGNAL(selectObject(MyMoneyObject)), m_kmymoney, SLOT(slotSelectAccount(MyMoneyObject))); + connect(m_accountTree, SIGNAL(selectObject(MyMoneyObject)), m_kmymoney, SLOT(slotSelectInstitution(MyMoneyObject))); + connect(m_accountTree, SIGNAL(selectObject(MyMoneyObject)), m_kmymoney, SLOT(slotSelectInvestment(MyMoneyObject))); + connect(m_accountTree, &KMyMoneyAccountTreeView::openContextMenu, m_kmymoney, &KMyMoneyApp::slotShowAccountContextMenu); + connect(m_accountTree, SIGNAL(openObject(MyMoneyObject)), m_kmymoney, SLOT(slotAccountOpen(MyMoneyObject))); - // let the model know if the item is expanded or collapsed - connect(m_accountTree, SIGNAL(collapsed(QModelIndex)), m_filterProxyModel, SLOT(collapsed(QModelIndex))); - connect(m_accountTree, SIGNAL(expanded(QModelIndex)), m_filterProxyModel, SLOT(expanded(QModelIndex))); + connect(m_filterProxyModel, &AccountsFilterProxyModel::unusedIncomeExpenseAccountHidden, this, &KAccountsView::slotUnusedIncomeExpenseAccountHidden); + connect(m_searchWidget, &QLineEdit::textChanged, m_filterProxyModel, &QSortFilterProxyModel::setFilterFixedString); - connect(m_accountTree, SIGNAL(selectObject(MyMoneyObject)), this, SIGNAL(selectObject(MyMoneyObject))); - connect(m_accountTree, SIGNAL(openContextMenu(MyMoneyObject)), this, SIGNAL(openContextMenu(MyMoneyObject))); - connect(m_accountTree, SIGNAL(openObject(MyMoneyObject)), this, SIGNAL(openObject(MyMoneyObject))); - - connect(MyMoneyFile::instance(), SIGNAL(dataChanged()), this, SLOT(slotLoadAccounts())); + // let the model know if the item is expanded or collapsed + connect(m_accountTree, &QTreeView::collapsed, m_filterProxyModel, &AccountsViewFilterProxyModel::collapsed); + connect(m_accountTree, &QTreeView::expanded, m_filterProxyModel, &AccountsViewFilterProxyModel::expanded); + connect(m_accountTree, &KMyMoneyAccountTreeView::columnToggled , m_kmymoneyview, &KMyMoneyView::slotAccountTreeViewChanged); // connect the two buttons to all required slots - connect(m_collapseButton, SIGNAL(clicked()), this, SLOT(slotExpandCollapse())); - connect(m_collapseButton, SIGNAL(clicked()), m_accountTree, SLOT(collapseAll())); - connect(m_accountTree, SIGNAL(collapsedAll()), m_filterProxyModel, SLOT(collapseAll())); - connect(m_expandButton, SIGNAL(clicked()), this, SLOT(slotExpandCollapse())); - connect(m_expandButton, SIGNAL(clicked()), m_accountTree, SLOT(expandAll())); - connect(m_accountTree, SIGNAL(expandedAll()), m_filterProxyModel, SLOT(expandAll())); + connect(m_collapseButton, &QAbstractButton::clicked, this, &KAccountsView::slotExpandCollapse); + connect(m_collapseButton, &QAbstractButton::clicked, m_accountTree, &KMyMoneyAccountTreeView::collapseAll); + connect(m_accountTree, &KMyMoneyAccountTreeView::collapsedAll, m_filterProxyModel, &AccountsViewFilterProxyModel::collapseAll); + connect(m_expandButton, &QAbstractButton::clicked, this, &KAccountsView::slotExpandCollapse); + connect(m_expandButton, &QAbstractButton::clicked, m_accountTree, &KMyMoneyAccountTreeView::expandAll); + connect(m_accountTree, &KMyMoneyAccountTreeView::expandedAll, m_filterProxyModel, &AccountsViewFilterProxyModel::expandAll); + + connect(model, &AccountsModel::netWorthChanged, this, &KAccountsView::slotNetWorthChanged); + connect(MyMoneyFile::instance(), &MyMoneyFile::dataChanged, this, &KAccountsView::slotLoadAccounts); } -KAccountsView::~KAccountsView() +void KAccountsView::showEvent(QShowEvent * event) { + if (m_needLoad) + init(); + + m_kmymoney->slotResetSelections(); + + if (m_needReload) { + loadAccounts(); + m_needReload = false; + } + + // don't forget base class implementation + QWidget::showEvent(event); } void KAccountsView::slotExpandCollapse() @@ -133,13 +162,20 @@ void KAccountsView::slotLoadAccounts() { + if (isVisible()) + loadAccounts(); + else + m_needReload = true; +} + +void KAccountsView::loadAccounts() +{ // TODO: check why the invalidate is needed here m_filterProxyModel->invalidate(); m_filterProxyModel->setHideClosedAccounts(KMyMoneyGlobalSettings::hideClosedAccounts() && !kmymoney->isActionToggled(Action::ViewShowAll)); m_filterProxyModel->setHideEquityAccounts(!KMyMoneyGlobalSettings::expertMode()); if (KMyMoneyGlobalSettings::showCategoriesInAccountsView()) { - m_filterProxyModel->addAccountGroup(MyMoneyAccount::Income); - m_filterProxyModel->addAccountGroup(MyMoneyAccount::Expense); + m_filterProxyModel->addAccountGroup(QVector {MyMoneyAccount::Income, MyMoneyAccount::Expense}); } else { m_filterProxyModel->removeAccountType(MyMoneyAccount::Income); m_filterProxyModel->removeAccountType(MyMoneyAccount::Expense); @@ -159,34 +195,5 @@ void KAccountsView::slotNetWorthChanged(const MyMoneyMoney &netWorth) { - QString s(i18n("Net Worth: ")); - - // FIXME figure out how to deal with the approximate - // if(!(file->totalValueValid(assetAccount.id()) & file->totalValueValid(liabilityAccount.id()))) - // s += "~ "; - - s.replace(QString(" "), QString(" ")); - if (netWorth.isNegative()) { - s += ""; - } - const MyMoneySecurity& sec = MyMoneyFile::instance()->baseCurrency(); - QString v(MyMoneyUtils::formatMoney(netWorth, sec)); - s += v.replace(QString(" "), QString(" ")); - if (netWorth.isNegative()) { - s += ""; - } - - m_totalProfitsLabel->setFont(KMyMoneyGlobalSettings::listCellFont()); - m_totalProfitsLabel->setText(s); -} - -void KAccountsView::slotOpenContextMenu(MyMoneyAccount account) -{ - emit openContextMenu(account); -} - -void KAccountsView::slotOpenObject(QListWidgetItem* item) -{ - if (item) - emit openObject((item->data(Qt::UserRole)).value()); + m_kmymoneyview->slotNetBalProChanged(netWorth, m_totalProfitsLabel, KMyMoneyView::View::Accounts); } diff --git a/kmymoney/views/kbudgetview.h b/kmymoney/views/kbudgetview.h --- a/kmymoney/views/kbudgetview.h +++ b/kmymoney/views/kbudgetview.h @@ -5,6 +5,7 @@ copyright : (C) 2006 by Darren Gould email : darren_gould@gmx.de Alvaro Soliverez + (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** @@ -65,7 +66,6 @@ protected: bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const; - bool filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const; MyMoneyMoney accountBalance(const QString &accountId) const; MyMoneyMoney accountValue(const MyMoneyAccount &account, const MyMoneyMoney &balance) const; MyMoneyMoney computeTotalValue(const QModelIndex &source_index) const; @@ -88,9 +88,13 @@ Q_OBJECT public: - KBudgetView(QWidget *parent = 0); + explicit KBudgetView(KMyMoneyApp *kmymoney, KMyMoneyView *kmymoneyview); ~KBudgetView(); + KRecursiveFilterProxyModel *getProxyModel(); + QList *getProxyColumns(); + bool isLoaded(); + /** * Override the base class behaviour to include all updates that * happened in the meantime and restore the layout. @@ -197,6 +201,9 @@ void aboutToShow(); private: + KMyMoneyApp *m_kmymoney; + KMyMoneyView *m_kmymoneyview; + typedef enum { eNone = -1, eYearly = 0, diff --git a/kmymoney/views/kbudgetview.cpp b/kmymoney/views/kbudgetview.cpp --- a/kmymoney/views/kbudgetview.cpp +++ b/kmymoney/views/kbudgetview.cpp @@ -5,6 +5,7 @@ copyright : (C) 2006 by Darren Gould email : darren_gould@gmx.de Alvaro Soliverez + (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** @@ -115,8 +116,7 @@ BudgetAccountsProxyModel::BudgetAccountsProxyModel(QObject *parent/* = 0*/) : AccountsViewFilterProxyModel(parent) { - addAccountGroup(MyMoneyAccount::Income); - addAccountGroup(MyMoneyAccount::Expense); + addAccountGroup(QVector {MyMoneyAccount::Income, MyMoneyAccount::Expense}); } /** @@ -127,41 +127,43 @@ { if (!MyMoneyFile::instance()->storageAttached()) return QVariant(); - QModelIndex normalizedIndex = BudgetAccountsProxyModel::index(index.row(), 0, index.parent()); - if (role == AccountsModel::AccountBalanceRole || - role == AccountsModel::AccountBalanceDisplayRole || - role == AccountsModel::AccountValueRole || - role == AccountsModel::AccountValueDisplayRole) { - QVariant accountData = data(normalizedIndex, AccountsModel::AccountRole); - if (accountData.canConvert()) { - MyMoneyAccount account = accountData.value(); - MyMoneyMoney balance = accountBalance(account.id()); - MyMoneyMoney value = accountValue(account, balance); - switch (role) { - case AccountsModel::AccountBalanceRole: - return QVariant::fromValue(balance); - case AccountsModel::AccountBalanceDisplayRole: - if (MyMoneyFile::instance()->security(account.currencyId()) != MyMoneyFile::instance()->baseCurrency()) { - return MyMoneyUtils::formatMoney(balance, MyMoneyFile::instance()->security(account.currencyId())); - } else { - return QVariant(); - } - case AccountsModel::AccountValueRole: - return QVariant::fromValue(value); - case AccountsModel::AccountValueDisplayRole: - return MyMoneyUtils::formatMoney(value, MyMoneyFile::instance()->baseCurrency()); - } - } - } - if (role == AccountsModel::AccountTotalValueRole || - role == AccountsModel::AccountTotalValueDisplayRole) { - MyMoneyMoney totalValue = computeTotalValue(mapToSource(normalizedIndex)); - switch (role) { - case AccountsModel::AccountTotalValueRole: - return QVariant::fromValue(totalValue); - case AccountsModel::AccountTotalValueDisplayRole: - return MyMoneyUtils::formatMoney(totalValue, MyMoneyFile::instance()->baseCurrency()); - } + const auto sourceColumn = m_mdlColumns->at(mapToSource(index).column()); + static QVector columnsToProcess {AccountsModel::TotalBalance, AccountsModel::TotalValue/*, AccountsModel::PostedValue*/, AccountsModel::Account}; + if (columnsToProcess.contains(sourceColumn)) { + const auto ixAccount = mapToSource(BudgetAccountsProxyModel::index(index.row(), AccountsModel::Account, index.parent())); + const auto account = ixAccount.data(AccountsModel::AccountRole).value(); + auto const file = MyMoneyFile::instance(); + + switch (role) { + case Qt::DisplayRole: + { + switch (sourceColumn) { + case AccountsModel::TotalBalance: + if (file->security(account.currencyId()) != file->baseCurrency()) + return QVariant(MyMoneyUtils::formatMoney(accountBalance(account.id()), file->security(account.currencyId()))); + else + return QVariant(); + case AccountsModel::TotalValue: + return QVariant(MyMoneyUtils::formatMoney(computeTotalValue(ixAccount), file->baseCurrency())); + // FIXME: Posted value doesn't correspond with total value without below code. Investigate why and wheather it matters. + // case AccountsModel::PostedValue: + // return QVariant(MyMoneyUtils::formatMoney(accountValue(account, accountBalance(account.id())), file->baseCurrency())); + default: + break; + } + } + case AccountsModel::AccountBalanceRole: + if (file->security(account.currencyId()) != file->baseCurrency()) + return QVariant::fromValue(accountBalance(account.id())); + else + return QVariant(); + case AccountsModel::AccountTotalValueRole: + return QVariant::fromValue(computeTotalValue(ixAccount)); + case AccountsModel::AccountValueRole: + return QVariant::fromValue(accountValue(account, accountBalance(account.id()))); + default: + break; + } } return AccountsViewFilterProxyModel::data(index, role); } @@ -203,42 +205,35 @@ bool BudgetAccountsProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { if (hideUnusedIncomeExpenseAccounts()) { - QModelIndex index = sourceModel()->index(source_row, 0, source_parent); - QVariant accountData = sourceModel()->data(index, AccountsModel::AccountRole); + const auto index = sourceModel()->index(source_row, AccountsModel::Account, source_parent); + const auto accountData = sourceModel()->data(index, AccountsModel::AccountRole); if (accountData.canConvert()) { - MyMoneyAccount account = accountData.value(); + const auto account = accountData.value(); MyMoneyMoney balance; // find out if the account is budgeted - MyMoneyBudget::AccountGroup budgetAccount = m_budget.account(account.id()); + const auto budgetAccount = m_budget.account(account.id()); if (budgetAccount.id() == account.id()) { balance = budgetAccount.balance(); switch (budgetAccount.budgetLevel()) { case MyMoneyBudget::AccountGroup::eMonthly: - balance = balance * 12; + balance *= MyMoneyMoney(12); break; default: break; } } if (!balance.isZero()) return AccountsFilterProxyModel::filterAcceptsRow(source_row, source_parent); } - for (int i = 0; i < sourceModel()->rowCount(index); ++i) { + for (auto i = 0; i < sourceModel()->rowCount(index); ++i) { if (filterAcceptsRow(i, index)) return AccountsFilterProxyModel::filterAcceptsRow(i, index); } return false; } return AccountsFilterProxyModel::filterAcceptsRow(source_row, source_parent); } -bool BudgetAccountsProxyModel::filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const -{ - if (source_column == AccountsModel::Tax || source_column == AccountsModel::VAT) - return false; - return AccountsFilterProxyModel::filterAcceptsColumn(source_column, source_parent); -} - MyMoneyMoney BudgetAccountsProxyModel::accountBalance(const QString &accountId) const { MyMoneyMoney balance; @@ -248,7 +243,7 @@ balance = budgetAccount.balance(); switch (budgetAccount.budgetLevel()) { case MyMoneyBudget::AccountGroup::eMonthly: - balance = balance * 12; + balance *= MyMoneyMoney(12); break; default: break; @@ -264,15 +259,11 @@ MyMoneyMoney BudgetAccountsProxyModel::computeTotalValue(const QModelIndex &source_index) const { - MyMoneyMoney totalValue; - QVariant accountData = sourceModel()->data(source_index, AccountsModel::AccountRole); - if (accountData.canConvert()) { - MyMoneyAccount account = accountData.value(); - totalValue = accountValue(account, accountBalance(account.id())); - for (int i = 0; i < sourceModel()->rowCount(source_index); ++i) { - totalValue += computeTotalValue(sourceModel()->index(i, 0, source_index)); - } - } + auto model = sourceModel(); + auto account = model->data(source_index, AccountsModel::AccountRole).value(); + auto totalValue = accountValue(account, accountBalance(account.id())); + for (auto i = 0; i < model->rowCount(source_index); ++i) + totalValue += computeTotalValue(model->index(i, AccountsModel::Account, source_index)); return totalValue; } @@ -306,8 +297,10 @@ } } -KBudgetView::KBudgetView(QWidget *parent) : - QWidget(parent), +KBudgetView::KBudgetView(KMyMoneyApp *kmymoney, KMyMoneyView *kmymoneyview) : + QWidget(nullptr), + m_kmymoney(kmymoney), + m_kmymoneyview(kmymoneyview), m_needReload(false), m_needLoad(true), m_inSelection(false) @@ -324,6 +317,21 @@ } } +KRecursiveFilterProxyModel *KBudgetView::getProxyModel() +{ + return m_filterProxyModel; +} + +QList *KBudgetView::getProxyColumns() +{ + return m_accountTree->getColumns(KMyMoneyView::View::Budget); +} + +bool KBudgetView::isLoaded() +{ + return !m_needLoad; +} + void KBudgetView::init() { m_needLoad = false; @@ -367,79 +375,74 @@ KGuiItem::assign(m_resetButton, resetButtonItem); m_resetButton->setToolTip(resetButtonItem.toolTip()); - KGuiItem collapseGuiItem(QString(), - QIcon::fromTheme(g_Icons[Icon::ListCollapse]), - QString(), - QString()); - KGuiItem expandGuiItem(QString(), - QIcon::fromTheme(g_Icons[Icon::ListExpand]), - QString(), - QString()); - KGuiItem::assign(m_collapseButton, collapseGuiItem); - KGuiItem::assign(m_expandButton, expandGuiItem); + m_collapseButton->setIcon(QIcon::fromTheme(g_Icons[Icon::ListCollapse])); + m_expandButton->setIcon(QIcon::fromTheme(g_Icons[Icon::ListExpand])); m_filterProxyModel = new BudgetAccountsProxyModel(this); - m_filterProxyModel->setSourceModel(Models::instance()->accountsModel()); + + auto const model = Models::instance()->accountsModel(); + m_filterProxyModel->init(model, getProxyColumns()); m_filterProxyModel->setFilterKeyColumn(-1); + m_accountTree->init(m_filterProxyModel, model->getColumns()); - m_accountTree->setModel(m_filterProxyModel); - m_accountTree->setConfigGroupName("KBudgetsView"); - m_accountTree->setAlternatingRowColors(true); - m_accountTree->setIconSize(QSize(22, 22)); - m_accountTree->setSortingEnabled(true); + connect(this, &KBudgetView::openContextMenu, m_kmymoney, &KMyMoneyApp::slotShowBudgetContextMenu); + connect(this, &KBudgetView::selectObjects, m_kmymoney, &KMyMoneyApp::slotSelectBudget); + connect(m_kmymoney, &KMyMoneyApp::budgetRename, this, &KBudgetView::slotStartRename); + connect(this, &KBudgetView::aboutToShow, m_kmymoneyview, &KMyMoneyView::aboutToChangeView); - connect(m_filterProxyModel, SIGNAL(balanceChanged(MyMoneyMoney)), this, SLOT(slotBudgetBalanceChanged(MyMoneyMoney))); + connect(m_filterProxyModel, &BudgetAccountsProxyModel::balanceChanged, this, &KBudgetView::slotBudgetBalanceChanged); // let the model know if the item is expanded or collapsed - connect(m_accountTree, SIGNAL(collapsed(QModelIndex)), m_filterProxyModel, SLOT(collapsed(QModelIndex))); - connect(m_accountTree, SIGNAL(expanded(QModelIndex)), m_filterProxyModel, SLOT(expanded(QModelIndex))); + connect(m_accountTree, &QTreeView::collapsed, m_filterProxyModel, &AccountsViewFilterProxyModel::collapsed); + connect(m_accountTree, &QTreeView::expanded, m_filterProxyModel, &AccountsViewFilterProxyModel::expanded); + connect(m_accountTree, &KMyMoneyAccountTreeView::columnToggled , m_kmymoneyview, &KMyMoneyView::slotAccountTreeViewChanged); connect(m_accountTree, SIGNAL(selectObject(MyMoneyObject)), this, SLOT(slotSelectAccount(MyMoneyObject))); - connect(m_accountTree, SIGNAL(selectObject(MyMoneyObject)), kmymoney, SLOT(slotSelectAccount(MyMoneyObject))); - connect(m_accountTree, SIGNAL(selectObject(MyMoneyObject)), kmymoney, SLOT(slotSelectInstitution(MyMoneyObject))); - connect(m_accountTree, SIGNAL(selectObject(MyMoneyObject)), kmymoney, SLOT(slotSelectInvestment(MyMoneyObject))); - connect(m_accountTree, SIGNAL(openContextMenu(MyMoneyObject)), kmymoney, SLOT(slotShowAccountContextMenu(MyMoneyObject))); - connect(m_accountTree, SIGNAL(openObject(MyMoneyObject)), kmymoney, SLOT(slotAccountOpen(MyMoneyObject))); + connect(m_accountTree, SIGNAL(selectObject(MyMoneyObject)), m_kmymoney, SLOT(slotSelectAccount(MyMoneyObject))); + connect(m_accountTree, SIGNAL(selectObject(MyMoneyObject)), m_kmymoney, SLOT(slotSelectInstitution(MyMoneyObject))); + connect(m_accountTree, SIGNAL(selectObject(MyMoneyObject)), m_kmymoney, SLOT(slotSelectInvestment(MyMoneyObject))); + connect(m_accountTree, &KMyMoneyAccountTreeView::openContextMenu, m_kmymoney, &KMyMoneyApp::slotShowAccountContextMenu); + connect(m_accountTree, SIGNAL(openObject(MyMoneyObject)), m_kmymoney, SLOT(slotAccountOpen(MyMoneyObject))); - connect(m_budgetList, SIGNAL(customContextMenuRequested(QPoint)), - this, SLOT(slotOpenContextMenu(QPoint))); - connect(m_budgetList->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(slotSelectBudget())); - connect(m_budgetList, SIGNAL(itemChanged(QTreeWidgetItem*,int)), this, SLOT(slotItemChanged(QTreeWidgetItem*,int))); + connect(m_budgetList, &QWidget::customContextMenuRequested, + this, &KBudgetView::slotOpenContextMenu); + connect(m_budgetList->selectionModel(), &QItemSelectionModel::selectionChanged, this, &KBudgetView::slotSelectBudget); + connect(m_budgetList, &QTreeWidget::itemChanged, this, &KBudgetView::slotItemChanged); - connect(m_cbBudgetSubaccounts, SIGNAL(clicked()), this, SLOT(cb_includesSubaccounts_clicked())); + connect(m_cbBudgetSubaccounts, &QAbstractButton::clicked, this, &KBudgetView::cb_includesSubaccounts_clicked); // connect the buttons to the actions. Make sure the enabled state // of the actions is reflected by the buttons - connect(m_renameButton, SIGNAL(clicked()), kmymoney->actionCollection()->action(kmymoney->s_Actions[Action::BudgetRename]), SLOT(trigger())); - connect(m_deleteButton, SIGNAL(clicked()), kmymoney->actionCollection()->action(kmymoney->s_Actions[Action::BudgetDelete]), SLOT(trigger())); + connect(m_renameButton, &QAbstractButton::clicked, kmymoney->actionCollection()->action(kmymoney->s_Actions[Action::BudgetRename]), &QAction::trigger); + connect(m_deleteButton, &QAbstractButton::clicked, kmymoney->actionCollection()->action(kmymoney->s_Actions[Action::BudgetDelete]), &QAction::trigger); - connect(m_budgetValue, SIGNAL(valuesChanged()), this, SLOT(slotBudgetedAmountChanged())); + connect(m_budgetValue, &KBudgetValues::valuesChanged, this, &KBudgetView::slotBudgetedAmountChanged); - connect(m_newButton, SIGNAL(clicked()), this, SLOT(slotNewBudget())); - connect(m_updateButton, SIGNAL(pressed()), this, SLOT(slotUpdateBudget())); - connect(m_resetButton, SIGNAL(pressed()), this, SLOT(slotResetBudget())); + connect(m_newButton, &QAbstractButton::clicked, this, &KBudgetView::slotNewBudget); + connect(m_updateButton, &QAbstractButton::pressed, this, &KBudgetView::slotUpdateBudget); + connect(m_resetButton, &QAbstractButton::pressed, this, &KBudgetView::slotResetBudget); - connect(m_hideUnusedButton, SIGNAL(toggled(bool)), this, SLOT(slotHideUnused(bool))); + connect(m_hideUnusedButton, &QAbstractButton::toggled, this, &KBudgetView::slotHideUnused); - connect(m_collapseButton, SIGNAL(clicked()), this, SLOT(slotExpandCollapse())); - connect(m_expandButton, SIGNAL(clicked()), this, SLOT(slotExpandCollapse())); + connect(m_collapseButton, &QAbstractButton::clicked, this, &KBudgetView::slotExpandCollapse); + connect(m_expandButton, &QAbstractButton::clicked, this, &KBudgetView::slotExpandCollapse); // connect the two buttons to all required slots - connect(m_collapseButton, SIGNAL(clicked()), this, SLOT(slotExpandCollapse())); - connect(m_collapseButton, SIGNAL(clicked()), m_accountTree, SLOT(collapseAll())); - connect(m_accountTree, SIGNAL(collapsedAll()), m_filterProxyModel, SLOT(collapseAll())); - connect(m_expandButton, SIGNAL(clicked()), this, SLOT(slotExpandCollapse())); - connect(m_expandButton, SIGNAL(clicked()), m_accountTree, SLOT(expandAll())); - connect(m_accountTree, SIGNAL(expandedAll()), m_filterProxyModel, SLOT(expandAll())); + connect(m_collapseButton, &QAbstractButton::clicked, this, &KBudgetView::slotExpandCollapse); + connect(m_collapseButton, &QAbstractButton::clicked, m_accountTree, &KMyMoneyAccountTreeView::collapseAll); + connect(m_accountTree, &KMyMoneyAccountTreeView::collapsedAll, m_filterProxyModel, &AccountsViewFilterProxyModel::collapseAll); + connect(m_expandButton, &QAbstractButton::clicked, this, &KBudgetView::slotExpandCollapse); + connect(m_expandButton, &QAbstractButton::clicked, m_accountTree, &KMyMoneyAccountTreeView::expandAll); + connect(m_accountTree, &KMyMoneyAccountTreeView::expandedAll, m_filterProxyModel, &AccountsViewFilterProxyModel::expandAll); connect(m_searchWidget, SIGNAL(textChanged(QString)), m_filterProxyModel, SLOT(setFilterFixedString(QString))); // setup initial state m_newButton->setEnabled(kmymoney->actionCollection()->action(kmymoney->s_Actions[Action::BudgetNew])->isEnabled()); m_renameButton->setEnabled(kmymoney->actionCollection()->action(kmymoney->s_Actions[Action::BudgetRename])->isEnabled()); m_deleteButton->setEnabled(kmymoney->actionCollection()->action(kmymoney->s_Actions[Action::BudgetDelete])->isEnabled()); - connect(MyMoneyFile::instance(), SIGNAL(dataChanged()), this, SLOT(slotRefreshView())); + connect(MyMoneyFile::instance(), &MyMoneyFile::dataChanged, this, &KBudgetView::slotRefreshView); KConfigGroup grp = KSharedConfig::openConfig()->group("Last Use Settings"); m_splitter->restoreState(grp.readEntry("KBudgetViewSplitterSize", QByteArray())); @@ -893,19 +896,5 @@ void KBudgetView::slotBudgetBalanceChanged(const MyMoneyMoney &balance) { - QString s(i18nc("The balance of the selected budget", "Balance: ")); - - s.replace(QString(" "), QString(" ")); - if (balance.isNegative()) { - s += ""; - } - const MyMoneySecurity& sec = MyMoneyFile::instance()->baseCurrency(); - QString v(MyMoneyUtils::formatMoney(balance, sec)); - s += v.replace(QString(" "), QString(" ")); - if (balance.isNegative()) { - s += ""; - } - - m_balanceLabel->setFont(KMyMoneyGlobalSettings::listCellFont()); - m_balanceLabel->setText(s); + m_kmymoneyview->slotNetBalProChanged(balance, m_balanceLabel, KMyMoneyView::View::Budget); } diff --git a/kmymoney/views/kcategoriesview.h b/kmymoney/views/kcategoriesview.h --- a/kmymoney/views/kcategoriesview.h +++ b/kmymoney/views/kcategoriesview.h @@ -8,6 +8,7 @@ Felix Rodriguez John C Kevin Tambascio + (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** @@ -64,9 +65,13 @@ Q_OBJECT public: - KCategoriesView(QWidget *parent = 0); + explicit KCategoriesView(KMyMoneyApp *kmymoney, KMyMoneyView *kmymoneyview); virtual ~KCategoriesView(); + KRecursiveFilterProxyModel *getProxyModel(); + QList *getProxyColumns(); + bool isLoaded(); + protected: void loadAccounts(); @@ -95,37 +100,18 @@ signals: /** - * This signal serves as proxy for KMyMoneyAccountTreeView::selectObject() - */ - void selectObject(const MyMoneyObject&); - - /** - * This signal serves as proxy for - * KMyMoneyAccountTreeView::openContextMenu(const MyMoneyObject&) - */ - void openContextMenu(const MyMoneyObject& obj); - - /** - * This signal will be emitted when the left mouse button is double - * clicked (actually the KDE executed setting is used) on an account. - */ - void openObject(const MyMoneyObject& obj); - - /** * This signal is emitted, when the user selected to reparent the * account @p acc to be a subordinate account of @p parent. * * @param acc const reference to account to be reparented * @param parent const reference to new parent account */ void reparent(const MyMoneyAccount& acc, const MyMoneyAccount& parent); - /** - * This signal is emitted whenever the view is about to be shown. - */ - void aboutToShow(); - private: + KMyMoneyApp *m_kmymoney; + KMyMoneyView *m_kmymoneyview; + /// set if a view needs to be reloaded during showEvent() bool m_needReload; diff --git a/kmymoney/views/kcategoriesview.cpp b/kmymoney/views/kcategoriesview.cpp --- a/kmymoney/views/kcategoriesview.cpp +++ b/kmymoney/views/kcategoriesview.cpp @@ -8,6 +8,7 @@ John C Thomas Baumgart Kevin Tambascio + (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** @@ -48,8 +49,10 @@ using namespace Icons; -KCategoriesView::KCategoriesView(QWidget *parent) : - QWidget(parent), +KCategoriesView::KCategoriesView(KMyMoneyApp *kmymoney, KMyMoneyView *kmymoneyview) : + QWidget(nullptr), + m_kmymoney(kmymoney), + m_kmymoneyview(kmymoneyview), m_needReload(false), m_needLoad(true), m_haveUnusedCategories(false) @@ -60,60 +63,69 @@ { } +KRecursiveFilterProxyModel *KCategoriesView::getProxyModel() +{ + return m_filterProxyModel; +} + +QList *KCategoriesView::getProxyColumns() +{ + return m_accountTree->getColumns(KMyMoneyView::View::Categories); +} + +bool KCategoriesView::isLoaded() +{ + return !m_needLoad; +} + void KCategoriesView::init() { m_needLoad = false; setupUi(this); // setup icons for collapse and expand button - KGuiItem collapseGuiItem(QString(), - QIcon::fromTheme(g_Icons[Icon::ListCollapse]), - QString(), - QString()); - KGuiItem expandGuiItem(QString(), - QIcon::fromTheme(g_Icons[Icon::ListExpand]), - QString(), - QString()); - KGuiItem::assign(m_collapseButton, collapseGuiItem); - KGuiItem::assign(m_expandButton, expandGuiItem); - - connect(Models::instance()->accountsModel(), SIGNAL(profitChanged(MyMoneyMoney)), this, SLOT(slotProfitChanged(MyMoneyMoney))); + m_collapseButton->setIcon(QIcon::fromTheme(g_Icons[Icon::ListCollapse])); + m_expandButton->setIcon(QIcon::fromTheme(g_Icons[Icon::ListExpand])); + + auto const model = Models::instance()->accountsModel(); + connect(model, &AccountsModel::profitChanged, this, &KCategoriesView::slotProfitChanged); // the proxy filter model m_filterProxyModel = new AccountsViewFilterProxyModel(this); - m_filterProxyModel->addAccountGroup(MyMoneyAccount::Income); - m_filterProxyModel->addAccountGroup(MyMoneyAccount::Expense); - m_filterProxyModel->setSourceModel(Models::instance()->accountsModel()); + +// const QVector accGroups {MyMoneyAccount::Income, MyMoneyAccount::Expense}; + m_filterProxyModel->addAccountGroup(QVector {MyMoneyAccount::Income, MyMoneyAccount::Expense}); + + m_filterProxyModel->init(model, getProxyColumns()); m_filterProxyModel->setFilterKeyColumn(-1); - connect(m_filterProxyModel, SIGNAL(unusedIncomeExpenseAccountHidden()), this, SLOT(slotUnusedIncomeExpenseAccountHidden())); + m_accountTree->init(m_filterProxyModel, model->getColumns()); - m_accountTree->setModel(m_filterProxyModel); - m_accountTree->setConfigGroupName("KCategoriesView"); - m_accountTree->setAlternatingRowColors(true); - m_accountTree->setIconSize(QSize(22, 22)); - m_accountTree->setSortingEnabled(true); + connect(m_accountTree, SIGNAL(selectObject(MyMoneyObject)), m_kmymoney, SLOT(slotSelectAccount(MyMoneyObject))); + connect(m_accountTree, SIGNAL(selectObject(MyMoneyObject)), m_kmymoney, SLOT(slotSelectInstitution(MyMoneyObject))); + connect(m_accountTree, &KMyMoneyAccountTreeView::openContextMenu, m_kmymoney, &KMyMoneyApp::slotShowAccountContextMenu); + connect(m_accountTree, SIGNAL(openObject(MyMoneyObject)), m_kmymoney, SLOT(slotAccountOpen(MyMoneyObject))); + connect(this, SIGNAL(reparent(MyMoneyAccount,MyMoneyAccount)), m_kmymoney, SLOT(slotReparentAccount(MyMoneyAccount,MyMoneyAccount))); //TODO : nothing emits this signal - connect(m_searchWidget, SIGNAL(textChanged(QString)), m_filterProxyModel, SLOT(setFilterFixedString(QString))); + connect(m_filterProxyModel, &AccountsFilterProxyModel::unusedIncomeExpenseAccountHidden, this, &KCategoriesView::slotUnusedIncomeExpenseAccountHidden); + connect(m_searchWidget, &QLineEdit::textChanged, m_filterProxyModel, &QSortFilterProxyModel::setFilterFixedString); // let the model know if the item is expanded or collapsed - connect(m_accountTree, SIGNAL(collapsed(QModelIndex)), m_filterProxyModel, SLOT(collapsed(QModelIndex))); - connect(m_accountTree, SIGNAL(expanded(QModelIndex)), m_filterProxyModel, SLOT(expanded(QModelIndex))); - connect(m_accountTree, SIGNAL(selectObject(MyMoneyObject)), this, SIGNAL(selectObject(MyMoneyObject))); - connect(m_accountTree, SIGNAL(openContextMenu(MyMoneyObject)), this, SIGNAL(openContextMenu(MyMoneyObject))); - connect(m_accountTree, SIGNAL(openObject(MyMoneyObject)), this, SIGNAL(openObject(MyMoneyObject))); + connect(m_accountTree, &QTreeView::collapsed, m_filterProxyModel, &AccountsViewFilterProxyModel::collapsed); + connect(m_accountTree, &QTreeView::expanded, m_filterProxyModel, &AccountsViewFilterProxyModel::expanded); + connect(m_accountTree, &KMyMoneyAccountTreeView::columnToggled , m_kmymoneyview, &KMyMoneyView::slotAccountTreeViewChanged); - connect(MyMoneyFile::instance(), SIGNAL(dataChanged()), this, SLOT(slotLoadAccounts())); - connect(m_collapseButton, SIGNAL(clicked()), this, SLOT(slotExpandCollapse())); - connect(m_expandButton, SIGNAL(clicked()), this, SLOT(slotExpandCollapse())); + connect(MyMoneyFile::instance(), &MyMoneyFile::dataChanged, this, &KCategoriesView::slotLoadAccounts); + connect(m_collapseButton, &QAbstractButton::clicked, this, &KCategoriesView::slotExpandCollapse); + connect(m_expandButton, &QAbstractButton::clicked, this, &KCategoriesView::slotExpandCollapse); // connect the two buttons to all required slots - connect(m_collapseButton, SIGNAL(clicked()), this, SLOT(slotExpandCollapse())); - connect(m_collapseButton, SIGNAL(clicked()), m_accountTree, SLOT(collapseAll())); - connect(m_accountTree, SIGNAL(collapsedAll()), m_filterProxyModel, SLOT(collapseAll())); - connect(m_expandButton, SIGNAL(clicked()), this, SLOT(slotExpandCollapse())); - connect(m_expandButton, SIGNAL(clicked()), m_accountTree, SLOT(expandAll())); - connect(m_accountTree, SIGNAL(expandedAll()), m_filterProxyModel, SLOT(expandAll())); + connect(m_collapseButton, &QAbstractButton::clicked, this, &KCategoriesView::slotExpandCollapse); + connect(m_collapseButton, &QAbstractButton::clicked, m_accountTree, &KMyMoneyAccountTreeView::collapseAll); + connect(m_accountTree, &KMyMoneyAccountTreeView::collapsedAll, m_filterProxyModel, &AccountsViewFilterProxyModel::collapseAll); + connect(m_expandButton, &QAbstractButton::clicked, this, &KCategoriesView::slotExpandCollapse); + connect(m_expandButton, &QAbstractButton::clicked, m_accountTree, &KMyMoneyAccountTreeView::expandAll); + connect(m_accountTree, &KMyMoneyAccountTreeView::expandedAll, m_filterProxyModel, &AccountsViewFilterProxyModel::expandAll); } void KCategoriesView::slotExpandCollapse() @@ -128,7 +140,7 @@ if (m_needLoad) init(); - emit aboutToShow(); + m_kmymoney->slotResetSelections(); if (m_needReload) { loadAccounts(); @@ -175,25 +187,5 @@ void KCategoriesView::slotProfitChanged(const MyMoneyMoney &profit) { - QString s(i18n("Profit: ")); - if (profit.isNegative()) - s = i18n("Loss: "); - - // FIXME figure out how to deal with the approximate - // if(!(file->totalValueValid(assetAccount.id()) & file->totalValueValid(liabilityAccount.id()))) - // s += "~ "; - - s.replace(QString(" "), QString(" ")); - if (profit.isNegative()) { - s += ""; - } - const MyMoneySecurity& sec = MyMoneyFile::instance()->baseCurrency(); - QString v(MyMoneyUtils::formatMoney(profit.abs(), sec)); - s += v.replace(QString(" "), QString(" ")); - if (profit.isNegative()) { - s += ""; - } - - m_totalProfitsLabel->setFont(KMyMoneyGlobalSettings::listCellFont()); - m_totalProfitsLabel->setText(s); + m_kmymoneyview->slotNetBalProChanged(profit, m_totalProfitsLabel, KMyMoneyView::View::Categories); } diff --git a/kmymoney/views/kgloballedgerview.cpp b/kmymoney/views/kgloballedgerview.cpp --- a/kmymoney/views/kgloballedgerview.cpp +++ b/kmymoney/views/kgloballedgerview.cpp @@ -216,26 +216,25 @@ // the proxy filter model d->m_filterProxyModel = new AccountNamesFilterProxyModel(this); - d->m_filterProxyModel->addAccountGroup(MyMoneyAccount::Asset); - d->m_filterProxyModel->addAccountGroup(MyMoneyAccount::Liability); - d->m_filterProxyModel->addAccountGroup(MyMoneyAccount::Equity); - d->m_filterProxyModel->setSourceModel(Models::instance()->accountsModel()); - d->m_filterProxyModel->sort(0); + d->m_filterProxyModel->addAccountGroup(QVector {MyMoneyAccount::Asset, MyMoneyAccount::Liability, MyMoneyAccount::Equity}); + d->m_filterProxyModel->init(Models::instance()->accountsModel()); + d->m_filterProxyModel->sort(AccountsModel::Account); // create the toolbar frame at the top of the view - m_toolbarFrame = new QFrame(this); + m_toolbarFrame = new QFrame(); QHBoxLayout* toolbarLayout = new QHBoxLayout(m_toolbarFrame); toolbarLayout->setContentsMargins(0, 0, 0, 0); toolbarLayout->setSpacing(6); // the account selector widget - d->m_accountComboBox = new KMyMoneyAccountCombo(d->m_filterProxyModel, m_toolbarFrame); + d->m_accountComboBox = new KMyMoneyAccountCombo(); + d->m_accountComboBox->setModel(d->m_filterProxyModel); toolbarLayout->addWidget(d->m_accountComboBox); layout()->addWidget(m_toolbarFrame); toolbarLayout->setStretchFactor(d->m_accountComboBox, 60); // create the register frame - m_registerFrame = new QFrame(this); + m_registerFrame = new QFrame(); QVBoxLayout* registerFrameLayout = new QVBoxLayout(m_registerFrame); registerFrameLayout->setContentsMargins(0, 0, 0, 0); registerFrameLayout->setSpacing(0); @@ -256,7 +255,7 @@ toolbarLayout->addWidget(d->m_registerSearchLine); toolbarLayout->setStretchFactor(d->m_registerSearchLine, 100); // create the summary frame - m_summaryFrame = new QFrame(this); + m_summaryFrame = new QFrame(); QHBoxLayout* summaryFrameLayout = new QHBoxLayout(m_summaryFrame); summaryFrameLayout->setContentsMargins(0, 0, 0, 0); summaryFrameLayout->setSpacing(0); @@ -869,6 +868,7 @@ void KGlobalLedgerView::loadAccounts() { MyMoneyFile* file = MyMoneyFile::instance(); + auto const model = Models::instance()->accountsModel(); // check if the current account still exists and make it the // current account @@ -890,7 +890,7 @@ if (m_account.id().isEmpty()) { // find the first favorite account - QModelIndexList list = Models::instance()->accountsModel()->match(Models::instance()->accountsModel()->index(0, 0), + QModelIndexList list = model->match(model->index(0, 0), AccountsModel::AccountFavoriteRole, QVariant(true), 1, @@ -904,7 +904,7 @@ if (m_account.id().isEmpty()) { // there are no favorite accounts find any account - QModelIndexList list = Models::instance()->accountsModel()->match(Models::instance()->accountsModel()->index(0, 0), + QModelIndexList list = model->match(model->index(0, 0), Qt::DisplayRole, QVariant(QString("*")), -1, diff --git a/kmymoney/views/kinstitutionsview.h b/kmymoney/views/kinstitutionsview.h --- a/kmymoney/views/kinstitutionsview.h +++ b/kmymoney/views/kinstitutionsview.h @@ -1,8 +1,8 @@ /*************************************************************************** kinstitutionssview.h ------------------- - copyright : (C) 2005 by Thomas Baumgart - email : ipwizard@users.sourceforge.net + copyright : (C) 2007 by Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** @@ -41,14 +41,20 @@ * This class implements the institutions hierarchical 'view'. */ +class KMyMoneyApp; + class KInstitutionsView : public QWidget, private Ui::KInstitutionsViewDecl { Q_OBJECT public: - KInstitutionsView(QWidget *parent = 0); + KInstitutionsView(KMyMoneyApp *kmymoney, KMyMoneyView *kmymoneyview); virtual ~KInstitutionsView(); + KRecursiveFilterProxyModel *getProxyModel(); + QList *getProxyColumns(); + bool isLoaded(); + public slots: void slotLoadAccounts(); @@ -75,31 +81,10 @@ */ void init(); -signals: - /** - * This signal serves as proxy for KMyMoneyAccountTreeView::selectObject() - */ - void selectObject(const MyMoneyObject&); - - /** - * This signal serves as proxy for - * KMyMoneyAccountTreeView::openContextMenu(const MyMoneyObject&) - */ - void openContextMenu(const MyMoneyObject& obj); - - /** - * This signal will be emitted when the left mouse button is double - * clicked (actually the KDE executed setting is used) on an account - * or institution. - */ - void openObject(const MyMoneyObject& obj); - - /** - * This signal is emitted whenever the view is about to be shown. - */ - void aboutToShow(); - private: + KMyMoneyApp *m_kmymoney; + KMyMoneyView *m_kmymoneyview; + /// set if a view needs to be reloaded during show() bool m_needReload; diff --git a/kmymoney/views/kinstitutionsview.cpp b/kmymoney/views/kinstitutionsview.cpp --- a/kmymoney/views/kinstitutionsview.cpp +++ b/kmymoney/views/kinstitutionsview.cpp @@ -1,8 +1,8 @@ /*************************************************************************** kinstitutionsview.cpp ------------------- - copyright : (C) 2005 by Thomas Baumgart - email : ipwizard@users.sourceforge.net + copyright : (C) 2007 by Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** @@ -40,8 +40,10 @@ using namespace Icons; -KInstitutionsView::KInstitutionsView(QWidget *parent) : - QWidget(parent), +KInstitutionsView::KInstitutionsView(KMyMoneyApp *kmymoney, KMyMoneyView *kmymoneyview) : + QWidget(nullptr), + m_kmymoney(kmymoney), + m_kmymoneyview(kmymoneyview), m_needReload(false), m_needLoad(true) { @@ -51,64 +53,70 @@ { } +KRecursiveFilterProxyModel *KInstitutionsView::getProxyModel() +{ + return m_filterProxyModel; +} + +QList *KInstitutionsView::getProxyColumns() +{ + return m_accountTree->getColumns(KMyMoneyView::View::Institutions); +} + +bool KInstitutionsView::isLoaded() +{ + return !m_needLoad; +} + void KInstitutionsView::init() { m_needLoad = false; setupUi(this); // setup icons for collapse and expand button - KGuiItem collapseGuiItem(QString(), - QIcon::fromTheme(g_Icons[Icon::ListCollapse]), - QString(), - QString()); - KGuiItem expandGuiItem(QString(), - QIcon::fromTheme(g_Icons[Icon::ListExpand]), - QString(), - QString()); - KGuiItem::assign(m_collapseButton, collapseGuiItem); - KGuiItem::assign(m_expandButton, expandGuiItem); + m_collapseButton->setIcon(QIcon::fromTheme(g_Icons[Icon::ListCollapse])); + m_expandButton->setIcon(QIcon::fromTheme(g_Icons[Icon::ListExpand])); // the proxy filter model m_filterProxyModel = new AccountsViewFilterProxyModel(this); - m_filterProxyModel->addAccountGroup(MyMoneyAccount::Asset); - m_filterProxyModel->addAccountGroup(MyMoneyAccount::Liability); - m_filterProxyModel->addAccountGroup(MyMoneyAccount::Equity); - m_filterProxyModel->setSourceModel(Models::instance()->institutionsModel()); + m_filterProxyModel->addAccountGroup(QVector {MyMoneyAccount::Asset, MyMoneyAccount::Liability, MyMoneyAccount::Equity}); + auto const model = Models::instance()->institutionsModel(); + m_filterProxyModel->init(model, getProxyColumns()); m_filterProxyModel->setFilterKeyColumn(-1); + m_accountTree->init(m_filterProxyModel, model->getColumns()); - m_accountTree->setModel(m_filterProxyModel); - m_accountTree->setConfigGroupName("KInstitutionsView"); - m_accountTree->setAlternatingRowColors(true); - m_accountTree->setIconSize(QSize(22, 22)); - m_accountTree->setSortingEnabled(true); + connect(m_accountTree, SIGNAL(selectObject(MyMoneyObject)), m_kmymoney, SLOT(slotSelectAccount(MyMoneyObject))); + connect(m_accountTree, SIGNAL(selectObject(MyMoneyObject)), m_kmymoney, SLOT(slotSelectInstitution(MyMoneyObject))); + connect(m_accountTree, &KMyMoneyAccountTreeView::openContextMenu, m_kmymoney, &KMyMoneyApp::slotShowAccountContextMenu); + connect(m_accountTree, SIGNAL(openContextMenu(MyMoneyObject)), m_kmymoney, SLOT(slotShowInstitutionContextMenu(MyMoneyObject))); + connect(m_accountTree, SIGNAL(openObject(MyMoneyObject)), m_kmymoney, SLOT(slotInstitutionEdit(MyMoneyObject))); + connect(m_accountTree, SIGNAL(openObject(MyMoneyObject)), m_kmymoney, SLOT(slotAccountOpen(MyMoneyObject))); // let the model know if the item is expanded or collapsed - connect(m_accountTree, SIGNAL(collapsed(QModelIndex)), m_filterProxyModel, SLOT(collapsed(QModelIndex))); - connect(m_accountTree, SIGNAL(expanded(QModelIndex)), m_filterProxyModel, SLOT(expanded(QModelIndex))); - connect(m_accountTree, SIGNAL(selectObject(MyMoneyObject)), this, SIGNAL(selectObject(MyMoneyObject))); - connect(m_accountTree, SIGNAL(openContextMenu(MyMoneyObject)), this, SIGNAL(openContextMenu(MyMoneyObject))); - connect(m_accountTree, SIGNAL(openObject(MyMoneyObject)), this, SIGNAL(openObject(MyMoneyObject))); + connect(m_accountTree, &QTreeView::collapsed, m_filterProxyModel, &AccountsViewFilterProxyModel::collapsed); + connect(m_accountTree, &QTreeView::expanded, m_filterProxyModel, &AccountsViewFilterProxyModel::expanded); + connect(m_accountTree, &KMyMoneyAccountTreeView::columnToggled , m_kmymoneyview, &KMyMoneyView::slotAccountTreeViewChanged); // connect the two buttons to all required slots - connect(m_collapseButton, SIGNAL(clicked()), this, SLOT(slotExpandCollapse())); - connect(m_collapseButton, SIGNAL(clicked()), m_accountTree, SLOT(collapseAll())); - connect(m_collapseButton, SIGNAL(clicked()), m_filterProxyModel, SLOT(collapseAll())); - connect(m_expandButton, SIGNAL(clicked()), this, SLOT(slotExpandCollapse())); - connect(m_expandButton, SIGNAL(clicked()), m_accountTree, SLOT(expandAll())); - connect(m_expandButton, SIGNAL(clicked()), m_filterProxyModel, SLOT(expandAll())); + connect(m_collapseButton, &QAbstractButton::clicked, this, &KInstitutionsView::slotExpandCollapse); + connect(m_collapseButton, &QAbstractButton::clicked, m_accountTree, &KMyMoneyAccountTreeView::collapseAll); + connect(m_collapseButton, &QAbstractButton::clicked, m_filterProxyModel, &AccountsViewFilterProxyModel::collapseAll); + connect(m_expandButton, &QAbstractButton::clicked, this, &KInstitutionsView::slotExpandCollapse); + connect(m_expandButton, &QAbstractButton::clicked, m_accountTree, &KMyMoneyAccountTreeView::expandAll); + connect(m_expandButton, &QAbstractButton::clicked, m_filterProxyModel, &AccountsViewFilterProxyModel::expandAll); - connect(m_searchWidget, SIGNAL(textChanged(QString)), m_filterProxyModel, SLOT(setFilterFixedString(QString))); + connect(m_searchWidget, &QLineEdit::textChanged, m_filterProxyModel, &QSortFilterProxyModel::setFilterFixedString); - connect(Models::instance()->accountsModel(), SIGNAL(netWorthChanged(MyMoneyMoney)), this, SLOT(slotNetWorthChanged(MyMoneyMoney))); - connect(MyMoneyFile::instance(), SIGNAL(dataChanged()), this, SLOT(slotLoadAccounts())); + connect(model, &AccountsModel::netWorthChanged, this, &KInstitutionsView::slotNetWorthChanged); + connect(MyMoneyFile::instance(), &MyMoneyFile::dataChanged, this, &KInstitutionsView::slotLoadAccounts); } void KInstitutionsView::showEvent(QShowEvent * event) { if (m_needLoad) init(); - emit aboutToShow(); + m_kmymoney->slotResetSelections(); if (m_needReload) { loadAccounts(); @@ -121,11 +129,15 @@ void KInstitutionsView::slotLoadAccounts() { - if (isVisible()) { + if (isVisible()) loadAccounts(); - } else { + else m_needReload = true; - } +} + +void KInstitutionsView::slotNetWorthChanged(const MyMoneyMoney &netWorth) +{ + m_kmymoneyview->slotNetBalProChanged(netWorth, m_totalProfitsLabel, KMyMoneyView::View::Institutions); } void KInstitutionsView::loadAccounts() @@ -135,29 +147,6 @@ m_filterProxyModel->setHideClosedAccounts(KMyMoneyGlobalSettings::hideClosedAccounts() && !kmymoney->isActionToggled(Action::ViewShowAll)); } -void KInstitutionsView::slotNetWorthChanged(const MyMoneyMoney &netWorth) -{ - QString s(i18n("Net Worth: ")); - - // FIXME figure out how to deal with the approximate - // if(!(file->totalValueValid(assetAccount.id()) & file->totalValueValid(liabilityAccount.id()))) - // s += "~ "; - - s.replace(QString(" "), QString(" ")); - if (netWorth.isNegative()) { - s += ""; - } - const MyMoneySecurity& sec = MyMoneyFile::instance()->baseCurrency(); - QString v(MyMoneyUtils::formatMoney(netWorth, sec)); - s += v.replace(QString(" "), QString(" ")); - if (netWorth.isNegative()) { - s += ""; - } - - m_totalProfitsLabel->setFont(KMyMoneyGlobalSettings::listCellFont()); - m_totalProfitsLabel->setText(s); -} - void KInstitutionsView::slotExpandCollapse() { if (sender()) { diff --git a/kmymoney/views/kinvestmentview.cpp b/kmymoney/views/kinvestmentview.cpp --- a/kmymoney/views/kinvestmentview.cpp +++ b/kmymoney/views/kinvestmentview.cpp @@ -137,14 +137,15 @@ d->m_filterProxyModel = new AccountNamesFilterProxyModel(this); d->m_filterProxyModel->addAccountType(MyMoneyAccount::Investment); d->m_filterProxyModel->setHideEquityAccounts(false); - d->m_filterProxyModel->setSourceModel(Models::instance()->accountsModel()); - d->m_filterProxyModel->sort(0); + auto const model = Models::instance()->accountsModel(); + d->m_filterProxyModel->init(model, model->getColumns()); + d->m_filterProxyModel->sort(AccountsModel::Account); m_accountComboBox->setModel(d->m_filterProxyModel); m_investmentsList->setContextMenuPolicy(Qt::CustomContextMenu); m_investmentsList->setSortingEnabled(true); - for (int i = 0; i < MaxViewTabs; ++i) + for (auto i = 0; i < MaxViewTabs; ++i) d->m_needReload[i] = false; connect(m_tab, SIGNAL(currentChanged(int)), this, SLOT(slotTabCurrentChanged(int))); diff --git a/kmymoney/views/kmymoneyview.h b/kmymoney/views/kmymoneyview.h --- a/kmymoney/views/kmymoneyview.h +++ b/kmymoney/views/kmymoneyview.h @@ -1,8 +1,9 @@ /*************************************************************************** kmymoneyview.h ------------------- - copyright : (C) 2000-2001 by Michael Edwardes - email : + copyright : (C) 2000-2001 by Michael Edwardes + 2004 by Thomas Baumgart + 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** @@ -45,14 +46,16 @@ #include "mymoneyschedule.h" #include "mymoneysecurity.h" #include "selectedtransaction.h" +#include #ifdef KF5Activities_FOUND namespace KActivities { class ResourceInstance; } #endif +class KMyMoneyApp; class KHomeView; class KAccountsView; class KCategoriesView; @@ -72,6 +75,8 @@ class KForecastView; class KOnlineJobOutbox; class KMyMoneyTitleLabel; +class QLabel; + /** * This class represents the view of the MyMoneyFile which contains * Banks/Accounts/Transactions, Recurring transactions (or Bills & Deposits) @@ -99,7 +104,8 @@ Reports, Budget, Forecast, - OnlineJobOutbox + OnlineJobOutbox, + None }; // file actions for plugin enum fileActions { @@ -220,7 +226,7 @@ * The constructor for KMyMoneyView. Just creates all the tabs for the * different aspects of the MyMoneyFile. */ - explicit KMyMoneyView(QObject *kmymoney, QWidget *parent = nullptr); + explicit KMyMoneyView(KMyMoneyApp *kmymoney); /** * Destructor @@ -422,6 +428,10 @@ */ void updateViewType(); + void slotAccountTreeViewChanged(const AccountsModel::Columns column, const bool show); + + void slotNetBalProChanged(const MyMoneyMoney &val, QLabel *label, const View view); + protected: /** * Overwritten because KMyMoney has it's custom header. diff --git a/kmymoney/views/kmymoneyview.cpp b/kmymoney/views/kmymoneyview.cpp --- a/kmymoney/views/kmymoneyview.cpp +++ b/kmymoney/views/kmymoneyview.cpp @@ -1,8 +1,9 @@ /*************************************************************************** kmymoneyview.cpp ------------------- - copyright : (C) 2000 by Michael Edwardes + copyright : (C) 2000-2001 by Michael Edwardes 2004 by Thomas Baumgart + 2017 by Łukasz Wojniłowicz ***************************************************************************/ @@ -108,8 +109,8 @@ static constexpr KCompressionDevice::CompressionType COMPRESSION_TYPE = KCompressionDevice::GZip; static constexpr char recoveryKeyId[] = "0xD2B08440"; -KMyMoneyView::KMyMoneyView(QObject *kmymoney, QWidget *parent) - : KPageWidget(parent), +KMyMoneyView::KMyMoneyView(KMyMoneyApp *kmymoney) + : KPageWidget(nullptr), m_header(0), m_inConstructor(true), m_fileOpen(false), @@ -162,30 +163,15 @@ connect(m_homeView, SIGNAL(aboutToShow()), this, SIGNAL(aboutToChangeView())); // Page 1 - m_institutionsView = new KInstitutionsView(); + m_institutionsView = new KInstitutionsView(kmymoney, this); viewFrames[View::Institutions] = m_model->addPage(m_institutionsView, i18n("Institutions")); viewFrames[View::Institutions]->setIcon(QIcon::fromTheme(g_Icons[Icon::ViewInstitutions])); - connect(m_institutionsView, SIGNAL(selectObject(MyMoneyObject)), kmymoney, SLOT(slotSelectAccount(MyMoneyObject))); - connect(m_institutionsView, SIGNAL(selectObject(MyMoneyObject)), kmymoney, SLOT(slotSelectInstitution(MyMoneyObject))); - connect(m_institutionsView, SIGNAL(openContextMenu(MyMoneyObject)), kmymoney, SLOT(slotShowAccountContextMenu(MyMoneyObject))); - connect(m_institutionsView, SIGNAL(openContextMenu(MyMoneyObject)), kmymoney, SLOT(slotShowInstitutionContextMenu(MyMoneyObject))); - connect(m_institutionsView, SIGNAL(openObject(MyMoneyObject)), kmymoney, SLOT(slotInstitutionEdit(MyMoneyObject))); - connect(m_institutionsView, SIGNAL(openObject(MyMoneyObject)), kmymoney, SLOT(slotAccountOpen(MyMoneyObject))); - connect(m_institutionsView, SIGNAL(aboutToShow()), this, SIGNAL(aboutToChangeView())); - // Page 2 - m_accountsView = new KAccountsView(); + m_accountsView = new KAccountsView(kmymoney, this); viewFrames[View::Accounts] = m_model->addPage(m_accountsView, i18n("Accounts")); viewFrames[View::Accounts]->setIcon(QIcon::fromTheme(g_Icons[Icon::ViewAccounts])); - connect(m_accountsView, SIGNAL(selectObject(MyMoneyObject)), kmymoney, SLOT(slotSelectAccount(MyMoneyObject))); - connect(m_accountsView, SIGNAL(selectObject(MyMoneyObject)), kmymoney, SLOT(slotSelectInstitution(MyMoneyObject))); - connect(m_accountsView, SIGNAL(selectObject(MyMoneyObject)), kmymoney, SLOT(slotSelectInvestment(MyMoneyObject))); - connect(m_accountsView, SIGNAL(openContextMenu(MyMoneyObject)), kmymoney, SLOT(slotShowAccountContextMenu(MyMoneyObject))); - connect(m_accountsView, SIGNAL(openObject(MyMoneyObject)), kmymoney, SLOT(slotAccountOpen(MyMoneyObject))); - connect(m_accountsView, SIGNAL(aboutToShow()), this, SIGNAL(aboutToChangeView())); - // Page 3 m_scheduledView = new KScheduledView(); //this is to solve the way long strings are handled differently among versions of KPageWidget @@ -200,17 +186,10 @@ connect(m_scheduledView, SIGNAL(aboutToShow()), this, SIGNAL(aboutToChangeView())); // Page 4 - m_categoriesView = new KCategoriesView(); + m_categoriesView = new KCategoriesView(kmymoney, this); viewFrames[View::Categories] = m_model->addPage(m_categoriesView, i18n("Categories")); viewFrames[View::Categories]->setIcon(QIcon::fromTheme(g_Icons[Icon::ViewCategories])); - connect(m_categoriesView, SIGNAL(selectObject(MyMoneyObject)), kmymoney, SLOT(slotSelectAccount(MyMoneyObject))); - connect(m_categoriesView, SIGNAL(selectObject(MyMoneyObject)), kmymoney, SLOT(slotSelectInstitution(MyMoneyObject))); - connect(m_categoriesView, SIGNAL(openContextMenu(MyMoneyObject)), kmymoney, SLOT(slotShowAccountContextMenu(MyMoneyObject))); - connect(m_categoriesView, SIGNAL(openObject(MyMoneyObject)), kmymoney, SLOT(slotAccountOpen(MyMoneyObject))); - connect(m_categoriesView, SIGNAL(reparent(MyMoneyAccount,MyMoneyAccount)), kmymoney, SLOT(slotReparentAccount(MyMoneyAccount,MyMoneyAccount))); - connect(m_categoriesView, SIGNAL(aboutToShow()), this, SIGNAL(aboutToChangeView())); - // Page 5 m_tagsView = new KTagsView(); viewFrames[View::Tags] = m_model->addPage(m_tagsView, i18n("Tags")); @@ -274,15 +253,10 @@ connect(m_reportsView, SIGNAL(aboutToShow()), this, SIGNAL(aboutToChangeView())); // Page 10 - m_budgetView = new KBudgetView(); + m_budgetView = new KBudgetView(kmymoney, this); viewFrames[View::Budget] = m_model->addPage(m_budgetView, i18n("Budgets")); viewFrames[View::Budget]->setIcon(QIcon::fromTheme(g_Icons[Icon::ViewBudgets])); - connect(m_budgetView, SIGNAL(openContextMenu(MyMoneyObject)), kmymoney, SLOT(slotShowBudgetContextMenu())); - connect(m_budgetView, SIGNAL(selectObjects(QList)), kmymoney, SLOT(slotSelectBudget(QList))); - connect(kmymoney, SIGNAL(budgetRename()), m_budgetView, SLOT(slotStartRename())); - connect(m_budgetView, SIGNAL(aboutToShow()), this, SIGNAL(aboutToChangeView())); - // Page 11 m_forecastView = new KForecastView(); viewFrames[View::Forecast] = m_model->addPage(m_forecastView, i18n("Forecast")); @@ -363,6 +337,98 @@ } } +void KMyMoneyView::slotAccountTreeViewChanged(const AccountsModel::Columns column, const bool show) +{ + struct viewInfo { + KRecursiveFilterProxyModel *proxyModel; + QList *proxyColumns; + }; + + QList viewInfos; + if (m_institutionsView->isLoaded()) + viewInfos.append({m_institutionsView->getProxyModel(), m_institutionsView->getProxyColumns()}); + if (m_accountsView->isLoaded()) + viewInfos.append({m_accountsView->getProxyModel(), m_accountsView->getProxyColumns()}); + if (m_categoriesView->isLoaded()) + viewInfos.append({m_categoriesView->getProxyModel(), m_categoriesView->getProxyColumns()}); + if (m_budgetView->isLoaded()) + viewInfos.append({m_budgetView->getProxyModel(), m_budgetView->getProxyColumns()}); + + if (show) { + Models::instance()->accountsModel()->setColumnVisibility(column, show); + Models::instance()->institutionsModel()->setColumnVisibility(column, show); + if (viewInfos.count() == 1 || + KMessageBox::questionYesNo(this, + i18n("Do you want to show %1 column on every loaded view?", AccountsModel::getHeaderName(column)), + QString(), + KStandardGuiItem::yes(), KStandardGuiItem::no(), + QStringLiteral("ShowColumnOnEveryView")) == KMessageBox::Yes) { + foreach(viewInfo view, viewInfos) { + if (!view.proxyColumns->contains(column)) { + view.proxyColumns->append(column); + view.proxyModel->invalidate(); + } + } + } + } else { + if (viewInfos.count() == 1 || + KMessageBox::questionYesNo(this, + i18n("Do you want to hide %1 column on every loaded view?", AccountsModel::getHeaderName(column)), + QString(), + KStandardGuiItem::yes(), KStandardGuiItem::no(), + QStringLiteral("HideColumnOnEveryView")) == KMessageBox::Yes) { + Models::instance()->accountsModel()->setColumnVisibility(column, show); + Models::instance()->institutionsModel()->setColumnVisibility(column, show); + foreach(viewInfo view, viewInfos) { + if (view.proxyColumns->contains(column)) { + view.proxyColumns->removeOne(column); + view.proxyModel->invalidate(); + } + } + } + } +} + +void KMyMoneyView::slotNetBalProChanged(const MyMoneyMoney &val, QLabel *label, const View view) +{ + QString s; + const auto isNegative = val.isNegative(); + switch (view) { + case View::Institutions: + case View::Accounts: + s = i18n("Net Worth: "); + break; + case View::Categories: + if (isNegative) + s = i18n("Loss: "); + else + s = i18n("Profit: "); + break; + case View::Budget: + s = (i18nc("The balance of the selected budget", "Balance: ")); + break; + default: + return; + } + + // FIXME figure out how to deal with the approximate + // if(!(file->totalValueValid(assetAccount.id()) & file->totalValueValid(liabilityAccount.id()))) + // s += "~ "; + + s.replace(QLatin1Char(' '), QLatin1String(" ")); + + if (isNegative) + s.append(QLatin1String("")); + const auto sec = MyMoneyFile::instance()->baseCurrency(); + QString v(MyMoneyUtils::formatMoney(val, sec)); + s.append((v.replace(QLatin1Char(' '), QLatin1String(" ")))); + if (isNegative) + s.append(QLatin1String("")); + + label->setFont(KMyMoneyGlobalSettings::listCellFont()); + label->setText(s); +} + bool KMyMoneyView::showPageHeader() const { return false; diff --git a/kmymoney/views/kpayeesview.cpp b/kmymoney/views/kpayeesview.cpp --- a/kmymoney/views/kpayeesview.cpp +++ b/kmymoney/views/kpayeesview.cpp @@ -111,13 +111,10 @@ m_filterProxyModel = new AccountNamesFilterProxyModel(this); m_filterProxyModel->setHideEquityAccounts(!KMyMoneyGlobalSettings::expertMode()); - m_filterProxyModel->addAccountGroup(MyMoneyAccount::Asset); - m_filterProxyModel->addAccountGroup(MyMoneyAccount::Liability); - m_filterProxyModel->addAccountGroup(MyMoneyAccount::Equity); - m_filterProxyModel->addAccountGroup(MyMoneyAccount::Income); - m_filterProxyModel->addAccountGroup(MyMoneyAccount::Expense); - m_filterProxyModel->setSourceModel(Models::instance()->accountsModel()); - m_filterProxyModel->sort(0); + m_filterProxyModel->addAccountGroup(QVector {MyMoneyAccount::Asset, MyMoneyAccount::Liability, MyMoneyAccount::Income, MyMoneyAccount::Expense, MyMoneyAccount::Equity}); + + m_filterProxyModel->init(Models::instance()->accountsModel()); + m_filterProxyModel->sort(AccountsModel::Account); comboDefaultCategory->setModel(m_filterProxyModel); matchTypeCombo->addItem(i18nc("@item No matching", "No matching"), MyMoneyPayee::matchDisabled); diff --git a/kmymoney/views/ktagsview.cpp b/kmymoney/views/ktagsview.cpp --- a/kmymoney/views/ktagsview.cpp +++ b/kmymoney/views/ktagsview.cpp @@ -105,12 +105,9 @@ setupUi(this); m_filterProxyModel = new AccountNamesFilterProxyModel(this); - m_filterProxyModel->addAccountGroup(MyMoneyAccount::Asset); - m_filterProxyModel->addAccountGroup(MyMoneyAccount::Liability); - m_filterProxyModel->addAccountGroup(MyMoneyAccount::Income); - m_filterProxyModel->addAccountGroup(MyMoneyAccount::Expense); - m_filterProxyModel->setSourceModel(Models::instance()->accountsModel()); - m_filterProxyModel->sort(0); + m_filterProxyModel->addAccountGroup(QVector {MyMoneyAccount::Asset, MyMoneyAccount::Liability, MyMoneyAccount::Income, MyMoneyAccount::Expense}); + m_filterProxyModel->init(Models::instance()->accountsModel()); + m_filterProxyModel->sort(AccountsModel::Account); // create the searchline widget // and insert it into the existing layout diff --git a/kmymoney/views/newspliteditor.cpp b/kmymoney/views/newspliteditor.cpp --- a/kmymoney/views/newspliteditor.cpp +++ b/kmymoney/views/newspliteditor.cpp @@ -197,19 +197,17 @@ d->ui->setupUi(this); d->ui->enterButton->setIcon(QIcon::fromTheme(g_Icons[Icon::DialogOK])); d->ui->cancelButton->setIcon(QIcon::fromTheme(g_Icons[Icon::DialogCancel])); - d->accountsModel->addAccountGroup(MyMoneyAccount::Asset); - d->accountsModel->addAccountGroup(MyMoneyAccount::Liability); - d->accountsModel->addAccountGroup(MyMoneyAccount::Income); - d->accountsModel->addAccountGroup(MyMoneyAccount::Expense); - d->accountsModel->addAccountGroup(MyMoneyAccount::Equity); + + d->accountsModel->addAccountGroup(QVector {MyMoneyAccount::Asset, MyMoneyAccount::Liability, MyMoneyAccount::Income, MyMoneyAccount::Expense, MyMoneyAccount::Equity}); d->accountsModel->setHideEquityAccounts(false); - d->accountsModel->setSourceModel(Models::instance()->accountsModel()); - d->accountsModel->sort(0); + auto const model = Models::instance()->accountsModel(); + d->accountsModel->init(model, model->getColumns()); + d->accountsModel->sort(AccountsModel::Account); d->ui->accountCombo->setModel(d->accountsModel); d->costCenterModel->setSortRole(Qt::DisplayRole); d->costCenterModel->setSourceModel(Models::instance()->costCenterModel()); - d->costCenterModel->sort(0); + d->costCenterModel->sort(AccountsModel::Account); d->ui->costCenterCombo->setEditable(true); d->ui->costCenterCombo->setModel(d->costCenterModel); diff --git a/kmymoney/views/newtransactioneditor.cpp b/kmymoney/views/newtransactioneditor.cpp --- a/kmymoney/views/newtransactioneditor.cpp +++ b/kmymoney/views/newtransactioneditor.cpp @@ -341,19 +341,17 @@ : QFrame(parent, Qt::FramelessWindowHint /* | Qt::X11BypassWindowManagerHint */) , d(new Private(this)) { + auto const model = Models::instance()->accountsModel(); // extract account information from model - QModelIndex index = Models::instance()->accountsModel()->accountById(accountId); - d->account = Models::instance()->accountsModel()->data(index, AccountsModel::AccountRole).value(); + const auto index = model->accountById(accountId); + d->account = model->data(index, AccountsModel::AccountRole).value(); d->ui->setupUi(this); - d->accountsModel->addAccountGroup(MyMoneyAccount::Asset); - d->accountsModel->addAccountGroup(MyMoneyAccount::Liability); - d->accountsModel->addAccountGroup(MyMoneyAccount::Income); - d->accountsModel->addAccountGroup(MyMoneyAccount::Expense); - d->accountsModel->addAccountGroup(MyMoneyAccount::Equity); + + d->accountsModel->addAccountGroup(QVector {MyMoneyAccount::Asset, MyMoneyAccount::Liability, MyMoneyAccount::Income, MyMoneyAccount::Expense, MyMoneyAccount::Equity}); d->accountsModel->setHideEquityAccounts(false); - d->accountsModel->setSourceModel(Models::instance()->accountsModel()); - d->accountsModel->sort(0); + d->accountsModel->init(model); + d->accountsModel->sort(AccountsModel::Account); d->ui->accountCombo->setModel(d->accountsModel); d->costCenterModel->setSortRole(Qt::DisplayRole); diff --git a/kmymoney/views/simpleledgerview.cpp b/kmymoney/views/simpleledgerview.cpp --- a/kmymoney/views/simpleledgerview.cpp +++ b/kmymoney/views/simpleledgerview.cpp @@ -90,12 +90,12 @@ connect(Models::instance(), SIGNAL(modelsLoaded()), this, SLOT(updateModels())); connect(d->ui->ledgerTab, SIGNAL(tabCloseRequested(int)), this, SLOT(closeLedger(int))); - d->accountsModel->addAccountGroup(MyMoneyAccount::Asset); - d->accountsModel->addAccountGroup(MyMoneyAccount::Liability); - d->accountsModel->addAccountGroup(MyMoneyAccount::Equity); + d->accountsModel->addAccountGroup(QVector {MyMoneyAccount::Asset, MyMoneyAccount::Liability, MyMoneyAccount::Equity}); + d->accountsModel->setHideEquityAccounts(false); - d->accountsModel->setSourceModel(Models::instance()->accountsModel()); - d->accountsModel->sort(0); + auto const model = Models::instance()->accountsModel(); + d->accountsModel->init(model, model->getColumns()); + d->accountsModel->sort(AccountsModel::Account); d->ui->accountCombo->setModel(d->accountsModel); tabSelected(0); diff --git a/kmymoney/widgets/kmymoneyaccountcombo.cpp b/kmymoney/widgets/kmymoneyaccountcombo.cpp --- a/kmymoney/widgets/kmymoneyaccountcombo.cpp +++ b/kmymoney/widgets/kmymoneyaccountcombo.cpp @@ -237,8 +237,7 @@ delete d->m_popupView; KComboBox::setModel(model); - - model->setFilterKeyColumn(AccountsModel::Account); + model->setFilterKeyColumn(AccountsModel::Account); // CAUTION! Assumption is being made that Account column number is always 0 model->setFilterRole(AccountsModel::FullNameRole); d->m_popupView = new QTreeView(this); @@ -276,20 +275,21 @@ AccountNamesFilterProxyModel* filterModel = qobject_cast(model()); if(filterModel) { + const auto completionStr = QStringLiteral(".*"); if (txt.contains(MyMoneyFile::AccountSeperator) == 0) { // for some reason it helps to avoid internal errors if we // clear the filter before setting it to a new value filterModel->setFilterFixedString(QString()); - const QString filterString = QString("%1%2%3").arg(".*").arg(QRegExp::escape(txt)).arg(".*"); + const auto filterString = QString::fromLatin1("%1%2%3").arg(completionStr).arg(QRegExp::escape(txt)).arg(completionStr); filterModel->setFilterRegExp(QRegExp(filterString, Qt::CaseInsensitive)); } else { QStringList parts = txt.split(MyMoneyFile::AccountSeperator /*, QString::SkipEmptyParts */); QString pattern; QStringList::iterator it; for (it = parts.begin(); it != parts.end(); ++it) { if (pattern.length() > 1) pattern += MyMoneyFile::AccountSeperator; - pattern += QRegExp::escape(QString(*it).trimmed()) + ".*"; + pattern += QRegExp::escape(QString(*it).trimmed()) + completionStr; } // for some reason it helps to avoid internal errors if we // clear the filter before setting it to a new value @@ -300,7 +300,7 @@ if (filterModel->visibleItems() == 0) { // for some reason it helps to avoid internal errors if we // clear the filter before setting it to a new value - pattern = pattern.prepend(QString(".*") + MyMoneyFile::AccountSeperator); + pattern = pattern.prepend(completionStr + MyMoneyFile::AccountSeperator); filterModel->setFilterFixedString(QString()); filterModel->setFilterRegExp(QRegExp(pattern, Qt::CaseInsensitive)); } diff --git a/kmymoney/widgets/kmymoneyaccounttreeview.h b/kmymoney/widgets/kmymoneyaccounttreeview.h --- a/kmymoney/widgets/kmymoneyaccounttreeview.h +++ b/kmymoney/widgets/kmymoneyaccounttreeview.h @@ -1,5 +1,6 @@ /*************************************************************************** * Copyright 2010 Cristian Onet onet.cristian@gmail.com * + * Copyright 2017 Łukasz Wojniłowicz lukasz.wojnilowicz@gmail.com * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * @@ -33,7 +34,9 @@ // Project Includes #include "accountsmodel.h" +#include +class AccountsViewFilterProxyModel; /** * This view was created to handle the actions that could be performed with the accounts. */ @@ -45,6 +48,8 @@ KMyMoneyAccountTreeView(QWidget *parent = 0); ~KMyMoneyAccountTreeView(); + void init(QAbstractItemModel *model, QList *columns); + public slots: /** * Overridden for internal reasons. @sa collapsedAll(). @@ -56,14 +61,16 @@ */ void expandAll(); - void setConfigGroupName(const QString& group); + QList *getColumns(const KMyMoneyView::View view); protected: void mouseDoubleClickEvent(QMouseEvent *event); void keyPressEvent(QKeyEvent *event); protected slots: - void customContextMenuRequested(const QPoint &pos); + void customContextMenuRequested(const QPoint); + void customHeaderContextMenuRequested(const QPoint); + void slotColumnToggled(bool); void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected); signals: @@ -99,11 +106,17 @@ void collapsedAll(); void expandedAll(); + void columnToggled(const AccountsModel::Columns column, const bool show); + private: void openIndex(const QModelIndex &index); + static QString getConfGrpName(const KMyMoneyView::View view); private: - QString m_groupName; + QList *m_mdlColumns; + QList m_visColumns; + KMyMoneyView::View m_view; + QMenu *m_menu; }; /** @@ -123,14 +136,12 @@ public slots: void collapseAll(); void expandAll(); + void collapsed(const QModelIndex &index); + void expanded(const QModelIndex &index); protected: bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const; -protected slots: - void collapsed(const QModelIndex &index); - void expanded(const QModelIndex &index); - private: class Private; Private* const d; diff --git a/kmymoney/widgets/kmymoneyaccounttreeview.cpp b/kmymoney/widgets/kmymoneyaccounttreeview.cpp --- a/kmymoney/widgets/kmymoneyaccounttreeview.cpp +++ b/kmymoney/widgets/kmymoneyaccounttreeview.cpp @@ -1,5 +1,6 @@ /*************************************************************************** * Copyright 2010 Cristian Onet onet.cristian@gmail.com * + * Copyright 2017 Łukasz Wojniłowicz lukasz.wojnilowicz@gmail.com * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * @@ -32,41 +33,51 @@ #include #include #include +#include // ---------------------------------------------------------------------------- // Project Includes #include +#include KMyMoneyAccountTreeView::KMyMoneyAccountTreeView(QWidget *parent) : QTreeView(parent) { setContextMenuPolicy(Qt::CustomContextMenu); - connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(customContextMenuRequested(QPoint))); + header()->setContextMenuPolicy(Qt::CustomContextMenu); + connect(this, &QWidget::customContextMenuRequested, this, &KMyMoneyAccountTreeView::customContextMenuRequested); + connect(this->header(), &QWidget::customContextMenuRequested, this, &KMyMoneyAccountTreeView::customHeaderContextMenuRequested); setAllColumnsShowFocus(true); + setAlternatingRowColors(true); + setIconSize(QSize(22, 22)); + setSortingEnabled(true); + m_view = KMyMoneyView::View::None; } KMyMoneyAccountTreeView::~KMyMoneyAccountTreeView() { - if (!m_groupName.isEmpty()) { - KConfigGroup grp = KSharedConfig::openConfig()->group(m_groupName); - QByteArray columns = header()->saveState(); + if (m_view != KMyMoneyView::View::None) { + auto grp = KSharedConfig::openConfig()->group(getConfGrpName(m_view)); + const auto columns = header()->saveState(); grp.writeEntry("HeaderState", columns); + QList visColumns; + foreach (const auto column, m_visColumns) + visColumns.append(static_cast(column)); + grp.writeEntry("ColumnsSelection", visColumns); + grp.sync(); } } -/** - * Set the name of the configuration group where the view's persistent data is saved to @param group . - */ -void KMyMoneyAccountTreeView::setConfigGroupName(const QString& group) +void KMyMoneyAccountTreeView::init(QAbstractItemModel *model, QList *columns) { - if (!group.isEmpty()) { - m_groupName = group; + setModel(model); + m_mdlColumns = columns; + if (m_view != KMyMoneyView::View::None) { // restore the headers - KConfigGroup grp = KSharedConfig::openConfig()->group(m_groupName); - QByteArray columns; - columns = grp.readEntry("HeaderState", columns); - header()->restoreState(columns); + const auto grp = KSharedConfig::openConfig()->group(getConfGrpName(m_view)); + const auto columnNames = grp.readEntry("HeaderState", QByteArray()); + header()->restoreState(columnNames); } } @@ -101,12 +112,27 @@ } } -void KMyMoneyAccountTreeView::customContextMenuRequested(const QPoint &pos) +QString KMyMoneyAccountTreeView::getConfGrpName(const KMyMoneyView::View view) +{ + switch (view) { + case KMyMoneyView::View::Institutions: + return QStringLiteral("KInstitutionsView"); + case KMyMoneyView::View::Accounts: + return QStringLiteral("KAccountsView"); + case KMyMoneyView::View::Categories: + return QStringLiteral("KCategoriesView"); + case KMyMoneyView::View::Budget: + return QStringLiteral("KBudgetsView"); + default: + return QString(); + } +} + +void KMyMoneyAccountTreeView::customContextMenuRequested(const QPoint) { - Q_UNUSED(pos) - QModelIndex index = model()->index(currentIndex().row(), AccountsModel::Account, currentIndex().parent()); + const auto index = model()->index(currentIndex().row(), AccountsModel::Account, currentIndex().parent()); if (index.isValid() && (model()->flags(index) & Qt::ItemIsSelectable)) { - QVariant data = model()->data(index, AccountsModel::AccountRole); + const auto data = model()->data(index, AccountsModel::AccountRole); if (data.isValid()) { if (data.canConvert()) { emit selectObject(data.value()); @@ -120,13 +146,62 @@ } } +void KMyMoneyAccountTreeView::customHeaderContextMenuRequested(const QPoint) +{ + const QList defColumns = { AccountsModel::Type, AccountsModel::Tax, + AccountsModel::VAT, AccountsModel::CostCenter, + AccountsModel::TotalBalance, AccountsModel::PostedValue, + AccountsModel::TotalValue, AccountsModel::AccountNumber, + AccountsModel::AccountSortCode + }; + + m_menu = new QMenu(i18n("Displayed columns")); + QList actions; + foreach (const auto column, defColumns) { + auto a = new QAction(); + a->setObjectName(QString::number(column)); + a->setText(AccountsModel::getHeaderName(column)); + a->setCheckable(true); + a->setChecked(m_visColumns.contains(column)); + connect(a, &QAction::toggled, this, &KMyMoneyAccountTreeView::slotColumnToggled); + actions.append(a); + } + + m_menu->addActions(actions); + m_menu->exec(QCursor::pos()); + connect(m_menu, &QMenu::aboutToHide, this, &QMenu::deleteLater); +} + +void KMyMoneyAccountTreeView::slotColumnToggled(bool) +{ + QList selColumns; + selColumns.append(AccountsModel::Account); + const auto actions = m_menu->actions(); + foreach (const auto action, actions) { + const auto columnID = static_cast(action->objectName().toInt()); + const auto isChecked = action->isChecked(); + const auto contains = m_visColumns.contains(columnID); + if (isChecked && !contains) { + m_visColumns.append(columnID); + emit columnToggled(columnID, true); + break; + } else if (!isChecked && contains) { + m_visColumns.removeOne(columnID); + emit columnToggled(columnID, false); + break; + } + } + auto mdl = qobject_cast(model()); + mdl->invalidate(); +} + void KMyMoneyAccountTreeView::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) { QTreeView::selectionChanged(selected, deselected); if (!selected.empty()) { - QModelIndexList indexes = selected.front().indexes(); + auto indexes = selected.front().indexes(); if (!indexes.empty()) { - QVariant data = model()->data(model()->index(indexes.front().row(), AccountsModel::Account, indexes.front().parent()), AccountsModel::AccountRole); + const auto data = model()->data(model()->index(indexes.front().row(), AccountsModel::Account, indexes.front().parent()), AccountsModel::AccountRole); if (data.isValid()) { if (data.canConvert()) { emit selectObject(data.value()); @@ -156,6 +231,26 @@ emit expandedAll(); } +QList *KMyMoneyAccountTreeView::getColumns(const KMyMoneyView::View view) +{ + m_view = view; + if (m_view != KMyMoneyView::View::None && m_visColumns.isEmpty()) { + auto const mdlAccounts = Models::instance()->accountsModel(); + auto const mdlInstitutions = Models::instance()->institutionsModel(); + const auto grp = KSharedConfig::openConfig()->group(getConfGrpName(m_view)); + const auto cfgColumns = grp.readEntry("ColumnsSelection", QList()); + m_visColumns.append(AccountsModel::Account); + foreach (const auto column, cfgColumns) { + const auto visColumn = static_cast(column); + if (!m_visColumns.contains(visColumn)) { + m_visColumns.append(visColumn); + mdlAccounts->setColumnVisibility(visColumn, true); + mdlInstitutions->setColumnVisibility(visColumn, true); + } + } + } + return &m_visColumns; +} class AccountsViewFilterProxyModel::Private { @@ -209,40 +304,16 @@ */ QVariant AccountsViewFilterProxyModel::data(const QModelIndex &index, int role) const { - if (index.isValid() && role == Qt::DisplayRole) { - int sourceColumn = mapToSource(index).column(); - if (sourceColumn == AccountsModel::TotalValue) { - MyMoneyAccount account = mapToSource(AccountsViewFilterProxyModel::index(index.row(), 0, index.parent())) - .data(AccountsModel::AccountRole).value(); - - // show the accounts value incl. the value of sub-accounts - // if the account is not expanded or, - bool showTotalValue = !d->isAccountExpanded(account.id()); - // the account is a top-level account or - showTotalValue |= !index.parent().isValid(); - // the account is an investment account and equity accounts are hidden - showTotalValue |= (account.accountType() == MyMoneyAccount::Investment && hideEquityAccounts()); - - if (showTotalValue) { - return data(index, AccountsModel::AccountTotalValueDisplayRole); - } else { - return data(index, AccountsModel::AccountValueDisplayRole); - } - } - if (sourceColumn == AccountsModel::TotalBalance) { - return data(index, AccountsModel::AccountBalanceDisplayRole); - } - } return AccountsFilterProxyModel::data(index, role); } -/** + /* * Reimplemented to filter all but the account displayed in the accounts view. */ bool AccountsViewFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { if (!source_parent.isValid()) { - QVariant data = sourceModel()->index(source_row, 0, source_parent).data(AccountsModel::AccountIdRole); + const auto data = sourceModel()->index(source_row, AccountsModel::Account, source_parent).data(AccountsModel::AccountIdRole); if (data.isValid() && data.toString() == AccountsModel::favoritesAccountId) return false; } @@ -255,22 +326,20 @@ */ void AccountsViewFilterProxyModel::collapsed(const QModelIndex &index) { - QVariant accountId = mapToSource(index).data(AccountsModel::AccountIdRole); - if (accountId.isValid()) { + const auto accountId = mapToSource(index).data(AccountsModel::AccountIdRole); + if (accountId.isValid()) d->markAccountCollapsed(accountId.toString()); - } } /** * The model is notified that the representation of the item at index was expanded. * @param index The index of the item which was expanded. */ void AccountsViewFilterProxyModel::expanded(const QModelIndex &index) { - QVariant accountId = mapToSource(index).data(AccountsModel::AccountIdRole); - if (accountId.isValid()) { + const auto accountId = mapToSource(index).data(AccountsModel::AccountIdRole); + if (accountId.isValid()) d->markAccountExpanded(accountId.toString()); - } } /** diff --git a/kmymoney/wizards/newaccountwizard/knewaccountwizard.cpp b/kmymoney/wizards/newaccountwizard/knewaccountwizard.cpp --- a/kmymoney/wizards/newaccountwizard/knewaccountwizard.cpp +++ b/kmymoney/wizards/newaccountwizard/knewaccountwizard.cpp @@ -1463,7 +1463,8 @@ bool HierarchyFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { if (!source_parent.isValid()) { - QVariant data = sourceModel()->index(source_row, 0, source_parent).data(AccountsModel::AccountIdRole); + auto accCol = m_mdlColumns->indexOf(AccountsModel::Account); + QVariant data = sourceModel()->index(source_row, accCol, source_parent).data(AccountsModel::AccountIdRole); if (data.isValid() && data.toString() == AccountsModel::favoritesAccountId) return false; } @@ -1484,22 +1485,19 @@ HierarchyPage::HierarchyPage(Wizard* wizard) : KHierarchyPageDecl(wizard), WizardPage(StepParentAccount, this, wizard), - m_filterProxyModel(0) + m_filterProxyModel(nullptr) { // the proxy filter model m_filterProxyModel = new HierarchyFilterProxyModel(this); m_filterProxyModel->setHideClosedAccounts(true); m_filterProxyModel->setHideEquityAccounts(!KMyMoneyGlobalSettings::expertMode()); - m_filterProxyModel->addAccountGroup(MyMoneyAccount::Asset); - m_filterProxyModel->addAccountGroup(MyMoneyAccount::Liability); - m_filterProxyModel->setSourceModel(Models::instance()->accountsModel()); + m_filterProxyModel->addAccountGroup(QVector {MyMoneyAccount::Asset, MyMoneyAccount::Liability}); + auto const model = Models::instance()->accountsModel(); + m_filterProxyModel->init(model, model->getColumns()); m_filterProxyModel->setDynamicSortFilter(true); - m_parentAccounts->setAlternatingRowColors(true); - m_parentAccounts->setIconSize(QSize(22, 22)); - m_parentAccounts->setSortingEnabled(true); - m_parentAccounts->setModel(m_filterProxyModel); - m_parentAccounts->sortByColumn(0, Qt::AscendingOrder); + m_parentAccounts->init(m_filterProxyModel, model->getColumns()); + m_parentAccounts->sortByColumn(AccountsModel::Account, Qt::AscendingOrder); connect(m_parentAccounts->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(parentAccountChanged())); } @@ -1509,7 +1507,7 @@ // Ensure that the list reflects the Account Type MyMoneyAccount topAccount = m_wizard->m_accountTypePage->parentAccount(); m_filterProxyModel->clear(); - m_filterProxyModel->addAccountGroup(topAccount.accountGroup()); + m_filterProxyModel->addAccountGroup(QVector {topAccount.accountGroup()}); m_parentAccounts->expandAll(); }