File indexing completed on 2024-05-19 05:08:23
0001 /* 0002 SPDX-FileCopyrightText: 2021 Thomas Baumgart <tbaumgart@kde.org> 0003 SPDX-License-Identifier: GPL-2.0-or-later 0004 */ 0005 0006 #ifndef LEDGERVIEWPAGE_P_H 0007 #define LEDGERVIEWPAGE_P_H 0008 0009 // ---------------------------------------------------------------------------- 0010 // QT Includes 0011 0012 #include <QDate> 0013 #include <QPointer> 0014 #include <QTimer> 0015 0016 // ---------------------------------------------------------------------------- 0017 // KDE Includes 0018 0019 // ---------------------------------------------------------------------------- 0020 // Project Includes 0021 0022 #include "accountsmodel.h" 0023 #include "kmymoneysettings.h" 0024 #include "ktransactionsortoptionsdlg.h" 0025 #include "ledgeraccountfilter.h" 0026 #include "ledgerfilter.h" 0027 #include "ledgerviewsettings.h" 0028 #include "mymoneyexception.h" 0029 #include "mymoneyfile.h" 0030 #include "mymoneymoney.h" 0031 #include "mymoneyprice.h" 0032 #include "mymoneysecurity.h" 0033 #include "mymoneyutils.h" 0034 #include "newtransactionform.h" 0035 #include "selectedobjects.h" 0036 #include "specialledgeritemfilter.h" 0037 0038 #include <ui_ledgerviewpage.h> 0039 0040 class LedgerViewPage::Private 0041 { 0042 public: 0043 Private(LedgerViewPage* qq) 0044 : q(qq) 0045 , ui(new Ui_LedgerViewPage) 0046 , accountFilter(nullptr) 0047 , specialItemFilter(nullptr) 0048 , stateFilter(nullptr) 0049 , form(nullptr) 0050 , stackedView(nullptr) 0051 , sortOrderType(LedgerViewSettings::SortOrderStd) 0052 , needModelInit(true) 0053 , showEntryForNewTransaction(false) 0054 , isInvestmentView(false) 0055 , precision(-1) 0056 { 0057 } 0058 0059 virtual ~Private() 0060 { 0061 delete ui; 0062 } 0063 0064 void initWidgets(const QString& configGroupName) 0065 { 0066 ui->setupUi(q); 0067 0068 // make sure, we can disable the detail form but not the ledger view 0069 ui->m_splitter->setCollapsible(0, false); 0070 ui->m_splitter->setCollapsible(1, true); 0071 0072 // make sure the ledger gets all the stretching 0073 ui->m_splitter->setStretchFactor(0, 3); 0074 ui->m_splitter->setStretchFactor(1, 1); 0075 ui->m_splitter->setSizes(QList<int>() << 10000 << ui->m_formWidget->sizeHint().height()); 0076 0077 delayTimer.setSingleShot(true); 0078 0079 connect(ui->m_ledgerView, &LedgerView::transactionSelected, q, &LedgerViewPage::transactionSelected); 0080 connect(ui->m_ledgerView, &LedgerView::aboutToStartEdit, q, &LedgerViewPage::aboutToStartEdit); 0081 connect(ui->m_ledgerView, &LedgerView::aboutToFinishEdit, q, &LedgerViewPage::aboutToFinishEdit); 0082 connect(ui->m_ledgerView, &LedgerView::aboutToStartEdit, q, &LedgerViewPage::startEdit); 0083 connect(ui->m_ledgerView, &LedgerView::aboutToFinishEdit, q, &LedgerViewPage::finishEdit); 0084 connect(ui->m_ledgerView, &LedgerView::transactionSelectionChanged, q, &LedgerViewPage::slotRequestSelectionChanged); 0085 connect(ui->m_ledgerView, &LedgerView::requestCustomContextMenu, q, &LedgerViewPage::requestCustomContextMenu); 0086 0087 connect(ui->m_splitter, &QSplitter::splitterMoved, q, &LedgerViewPage::splitterChanged); 0088 0089 ui->m_ledgerView->setColumnSelectorGroupName(configGroupName); 0090 0091 needModelInit = true; 0092 } 0093 0094 virtual void updateSummaryInformation() const 0095 { 0096 if (reconciliationDate.isValid()) { 0097 ui->m_leftLabel->setText(i18nc("@label:textbox Reconciliation date", "Last reconciliation: %1", MyMoneyUtils::formatDate(reconciliationDate))); 0098 } else { 0099 ui->m_leftLabel->setText(i18nc("@label:textbox Reconciliation date", "Never reconciled")); 0100 } 0101 0102 if (isInvestmentView) { 0103 const auto file = MyMoneyFile::instance(); 0104 const auto account = file->accountsModel()->itemById(accountId); 0105 const auto baseCurrency = file->baseCurrency(); 0106 0107 // collect accounts and their balances 0108 QMap<QString, MyMoneyMoney> actBalance; 0109 actBalance[accountId] = file->balance(accountId); 0110 const auto subAccounts = account.accountList(); 0111 for (const auto& accId : qAsConst(subAccounts)) { 0112 actBalance[accId] = file->balance(accId); 0113 } 0114 0115 MyMoneyMoney balance; 0116 bool balanceIsApproximated = false; 0117 QMap<QString, MyMoneyMoney>::const_iterator it_b; 0118 for (it_b = actBalance.cbegin(); it_b != actBalance.cend(); ++it_b) { 0119 MyMoneyAccount stock = file->account(it_b.key()); 0120 QString currencyId = stock.currencyId(); 0121 MyMoneySecurity sec = file->security(currencyId); 0122 MyMoneyMoney rate(1, 1); 0123 0124 if (stock.isInvest()) { 0125 currencyId = sec.tradingCurrency(); 0126 const MyMoneyPrice& priceInfo = file->price(sec.id(), currencyId); 0127 balanceIsApproximated |= !priceInfo.isValid(); 0128 rate = priceInfo.rate(sec.tradingCurrency()); 0129 } 0130 0131 if (currencyId != baseCurrency.id()) { 0132 const MyMoneyPrice& priceInfo = file->price(sec.tradingCurrency(), baseCurrency.id()); 0133 balanceIsApproximated |= !priceInfo.isValid(); 0134 rate = (rate * priceInfo.rate(baseCurrency.id())).convertPrecision(sec.pricePrecision()); 0135 } 0136 balance += ((*it_b) * rate).convert(baseCurrency.smallestAccountFraction()); 0137 } 0138 0139 ui->m_centerLabel->setText(QString()); 0140 ui->m_rightLabel->setText(i18nc("@label:textbox Total value of investment", 0141 "Investment value: %1%2", 0142 balanceIsApproximated ? QLatin1String("~") : QString(), 0143 balance.formatMoney(baseCurrency.tradingSymbol(), precision))); 0144 } else { 0145 ui->m_centerLabel->setText(i18nc("@label:textbox Cleared balance", "Cleared: %1", clearedBalance.formatMoney("", precision))); 0146 if (selections.count(SelectedObjects::JournalEntry) > 1) { 0147 ui->m_rightLabel->setText(i18nc("@label:textbox %1 sum symbol, %2 number of selected tx, %3 sum of tx", 0148 "%1 of %2: %3", 0149 QChar(0x2211), 0150 selections.count(SelectedObjects::JournalEntry), 0151 selectedTotal.formatMoney("", precision))); 0152 } else { 0153 ui->m_rightLabel->setText(i18nc("@label:textbox Total balance", "Balance: %1", totalBalance.formatMoney("", precision))); 0154 } 0155 } 0156 } 0157 0158 virtual void clearFilter() 0159 { 0160 stateFilter->clearFilter(); 0161 ui->m_ledgerView->setFocus(); 0162 QMetaObject::invokeMethod(ui->m_ledgerView, &LedgerView::ensureCurrentItemIsVisible, Qt::QueuedConnection); 0163 } 0164 0165 virtual void updateAccountData(const MyMoneyAccount& account) 0166 { 0167 reconciliationDate = account.lastReconciliationDate(); 0168 precision = MyMoneyMoney::denomToPrec(account.fraction()); 0169 accountName = account.name(); 0170 0171 sortOptionKey = QLatin1String("kmm-sort-std"); 0172 const auto sortOption = account.value(sortOptionKey); 0173 0174 if (account.accountType() == eMyMoney::Account::Type::Investment) { 0175 sortOrderType = LedgerViewSettings::SortOrderInvest; 0176 } else { 0177 sortOrderType = LedgerViewSettings::SortOrderStd; 0178 } 0179 0180 const LedgerSortOrder previousSortOrder = sortOrder; 0181 0182 // check if we have a specific sort order or rely on the default 0183 if (!sortOption.isEmpty()) { 0184 sortOrder = LedgerSortOrder(sortOption); 0185 } else { 0186 sortOrder = LedgerViewSettings::instance()->sortOrder(sortOrderType); 0187 } 0188 0189 if (previousSortOrder != sortOrder) { 0190 specialItemFilter->setLedgerSortOrder(sortOrder); 0191 specialItemFilter->forceReload(); 0192 } 0193 } 0194 0195 void selectSortOrder() 0196 { 0197 auto file = MyMoneyFile::instance(); 0198 QPointer<KTransactionSortOptionsDlg> dlg = new KTransactionSortOptionsDlg(q); 0199 auto account = file->accountsModel()->itemById(accountId); 0200 const auto defaultSortOption = 0201 (sortOrderType == LedgerViewSettings::SortOrderStd) ? KMyMoneySettings::sortNormalView() : KMyMoneySettings::sortNormalView(); 0202 dlg->setSortOption(account.value(sortOptionKey), defaultSortOption); 0203 if ((dlg->exec() == QDialog::Accepted) && dlg) { 0204 const auto newSortOption = dlg->sortOption(); 0205 if (newSortOption != account.value(sortOptionKey)) { 0206 if (newSortOption.isEmpty()) { 0207 account.deletePair(sortOptionKey); 0208 } else { 0209 account.setValue(sortOptionKey, newSortOption); 0210 } 0211 MyMoneyFileTransaction ft; 0212 try { 0213 file->modifyAccount(account); 0214 ft.commit(); 0215 } catch (const MyMoneyException& e) { 0216 qDebug() << "Unable to store sort options with account" << account.name() << e.what(); 0217 } 0218 } 0219 } 0220 delete dlg; 0221 } 0222 0223 LedgerViewPage* q; 0224 Ui_LedgerViewPage* ui; 0225 LedgerAccountFilter* accountFilter; 0226 SpecialLedgerItemFilter* specialItemFilter; 0227 LedgerFilter* stateFilter; 0228 NewTransactionForm* form; 0229 LedgerViewPage* stackedView; 0230 QSet<QString> hideFormReasons; 0231 QString accountId; 0232 QString accountName; 0233 QString sortOptionKey; 0234 SelectedObjects selections; 0235 QTimer delayTimer; 0236 QDate reconciliationDate; 0237 MyMoneyMoney totalBalance; 0238 MyMoneyMoney clearedBalance; 0239 MyMoneyMoney selectedTotal; 0240 LedgerViewSettings::SortOrderType sortOrderType; 0241 LedgerSortOrder sortOrder; 0242 bool needModelInit; 0243 bool showEntryForNewTransaction; 0244 bool isInvestmentView; 0245 int precision; 0246 }; 0247 0248 #endif // LEDGERVIEWPAGE_P_H