File indexing completed on 2024-05-12 16:43:48

0001 /*
0002     SPDX-FileCopyrightText: 2007 Thomas Baumgart <ipwizard@users.sourceforge.net>
0003     SPDX-FileCopyrightText: 2017 Łukasz Wojniłowicz <lukasz.wojnilowicz@gmail.com>
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #ifndef KINVESTMENTVIEW_P_H
0008 #define KINVESTMENTVIEW_P_H
0009 
0010 #include "kinvestmentview.h"
0011 
0012 // ----------------------------------------------------------------------------
0013 // QT Includes
0014 
0015 #include <QIcon>
0016 
0017 // ----------------------------------------------------------------------------
0018 // KDE Includes
0019 
0020 #include <KSharedConfig>
0021 
0022 // ----------------------------------------------------------------------------
0023 // Project Includes
0024 
0025 #include "ui_kinvestmentview.h"
0026 #include "kmymoneyviewbase_p.h"
0027 
0028 #include "mymoneyexception.h"
0029 #include "mymoneyfile.h"
0030 #include "mymoneysecurity.h"
0031 #include "mymoneyaccount.h"
0032 #include "kmymoneysettings.h"
0033 #include "kmymoneyaccountcombo.h"
0034 #include "accountsmodel.h"
0035 #include "models.h"
0036 #include "equitiesmodel.h"
0037 #include "securitiesmodel.h"
0038 #include "icons.h"
0039 #include "modelenums.h"
0040 #include "mymoneyenums.h"
0041 
0042 using namespace Icons;
0043 
0044 namespace eView {
0045 namespace Investment {
0046 enum Tab { Equities = 0, Securities };
0047 }
0048 }
0049 
0050 class KInvestmentViewPrivate : public KMyMoneyViewBasePrivate
0051 {
0052     Q_DECLARE_PUBLIC(KInvestmentView)
0053 
0054 public:
0055     explicit KInvestmentViewPrivate(KInvestmentView *qq) :
0056         KMyMoneyViewBasePrivate(),
0057         q_ptr(qq),
0058         ui(new Ui::KInvestmentView),
0059         m_idInvAcc(QString()),
0060         m_needLoad(true),
0061         m_accountsProxyModel(nullptr),
0062         m_equitiesProxyModel(nullptr),
0063         m_securitiesProxyModel(nullptr)
0064     {
0065     }
0066 
0067     ~KInvestmentViewPrivate()
0068     {
0069         if (!m_needLoad) {
0070             // save the header state of the equities list
0071             auto cfgGroup = KSharedConfig::openConfig()->group("KInvestmentView_Equities");
0072             auto cfgHeader = ui->m_equitiesTree->header()->saveState();
0073             auto visEColumns = m_equitiesProxyModel->getVisibleColumns();
0074 
0075             QList<int> cfgColumns;
0076             foreach (const auto visColumn, visEColumns)
0077                 cfgColumns.append(static_cast<int>(visColumn));
0078 
0079             cfgGroup.writeEntry("HeaderState", cfgHeader);
0080             cfgGroup.writeEntry("ColumnsSelection", cfgColumns);
0081 
0082             // save the header state of the securities list
0083             cfgGroup = KSharedConfig::openConfig()->group("KInvestmentView_Securities");
0084             cfgHeader = ui->m_securitiesTree->header()->saveState();
0085             auto visSColumns = m_securitiesProxyModel->getVisibleColumns();
0086             cfgColumns.clear();
0087             foreach (const auto visColumn, visSColumns)
0088                 cfgColumns.append(static_cast<int>(visColumn));
0089 
0090             cfgGroup.writeEntry("HeaderState", cfgHeader);
0091             cfgGroup.writeEntry("ColumnsSelection", cfgColumns);
0092         }
0093         delete ui;
0094     }
0095 
0096     void init()
0097     {
0098         Q_Q(KInvestmentView);
0099         m_needLoad = false;
0100         ui->setupUi(q);
0101 
0102         // Equities tab
0103         m_accountsProxyModel = new AccountNamesFilterProxyModel(q);
0104         m_accountsProxyModel->addAccountType(eMyMoney::Account::Type::Investment);
0105         m_accountsProxyModel->setHideEquityAccounts(false);
0106         auto const model = Models::instance()->accountsModel();
0107         m_accountsProxyModel->setSourceColumns(model->getColumns());
0108         m_accountsProxyModel->setSourceModel(model);
0109         m_accountsProxyModel->sort((int)eAccountsModel::Column::Account);
0110         ui->m_accountComboBox->setModel(m_accountsProxyModel);
0111         ui->m_accountComboBox->expandAll();
0112 
0113         auto cfgGroup = KSharedConfig::openConfig()->group("KInvestmentView_Equities");
0114         auto cfgHeader = cfgGroup.readEntry("HeaderState", QByteArray());
0115         auto cfgColumns = cfgGroup.readEntry("ColumnsSelection", QList<int>());
0116         QList<EquitiesModel::Column> visEColumns {EquitiesModel::Equity};
0117         foreach (const auto cfgColumn, cfgColumns) {
0118             const auto visColumn = static_cast<EquitiesModel::Column>(cfgColumn);
0119             if (!visEColumns.contains(visColumn))
0120                 visEColumns.append(visColumn);
0121         }
0122 
0123         m_equitiesProxyModel = new EquitiesFilterProxyModel(q, Models::instance()->equitiesModel(), visEColumns);
0124         ui->m_equitiesTree->setModel(m_equitiesProxyModel);
0125         ui->m_equitiesTree->header()->restoreState(cfgHeader);
0126         ui->m_equitiesTree->header()->setContextMenuPolicy(Qt::CustomContextMenu);
0127 
0128         q->connect(ui->m_equitiesTree, &QWidget::customContextMenuRequested, q, &KInvestmentView::slotInvestmentMenuRequested);
0129         q->connect(ui->m_equitiesTree->selectionModel(), &QItemSelectionModel::currentRowChanged, q, &KInvestmentView::slotEquitySelected);
0130         q->connect(ui->m_equitiesTree, &QTreeView::doubleClicked, q, &KInvestmentView::slotEditInvestment);
0131         q->connect(ui->m_equitiesTree->header(), &QWidget::customContextMenuRequested, m_equitiesProxyModel, &EquitiesFilterProxyModel::slotColumnsMenu);
0132         q->connect(ui->m_accountComboBox, &KMyMoneyAccountCombo::accountSelected, q, &KInvestmentView::slotLoadAccount);
0133 
0134         // Securities tab
0135         cfgGroup = KSharedConfig::openConfig()->group("KInvestmentView_Securities");
0136         cfgHeader = cfgGroup.readEntry("HeaderState", QByteArray());
0137         cfgColumns = cfgGroup.readEntry("ColumnsSelection", QList<int>());
0138         QList<SecuritiesModel::Column> visSColumns {SecuritiesModel::Security};
0139         foreach (const auto cfgColumn, cfgColumns) {
0140             const auto visColumn = static_cast<SecuritiesModel::Column>(cfgColumn);
0141             if (!visSColumns.contains(visColumn))
0142                 visSColumns.append(visColumn);
0143         }
0144 
0145         m_securitiesProxyModel = new SecuritiesFilterProxyModel(q, Models::instance()->securitiesModel(), visSColumns);
0146         ui->m_securitiesTree->setModel(m_securitiesProxyModel);
0147         ui->m_securitiesTree->header()->restoreState(cfgHeader);
0148 
0149         q->connect(ui->m_searchSecurities, &QLineEdit::textChanged, m_securitiesProxyModel, &QSortFilterProxyModel::setFilterFixedString);
0150 
0151         ui->m_deleteSecurityButton->setIcon(Icons::get(Icon::EditDelete));
0152         ui->m_editSecurityButton->setIcon(Icons::get(Icon::DocumentEdit));
0153 
0154         q->connect(ui->m_securitiesTree->selectionModel(), &QItemSelectionModel::currentRowChanged, q, &KInvestmentView::slotSecuritySelected);
0155         q->connect(ui->m_editSecurityButton, &QAbstractButton::clicked, q, &KInvestmentView::slotEditSecurity);
0156         q->connect(ui->m_deleteSecurityButton, &QAbstractButton::clicked, q, &KInvestmentView::slotDeleteSecurity);
0157         ui->m_securitiesTree->header()->setContextMenuPolicy(Qt::CustomContextMenu);
0158         q->connect(ui->m_securitiesTree->header(), &QWidget::customContextMenuRequested, m_securitiesProxyModel, &SecuritiesFilterProxyModel::slotColumnsMenu);
0159 
0160         // Investment Page
0161         m_needReload[eView::Investment::Tab::Equities] = m_needReload[eView::Investment::Tab::Securities] = true;
0162         q->connect(ui->m_tab, &QTabWidget::currentChanged, q, &KInvestmentView::slotLoadTab);
0163         q->connect(MyMoneyFile::instance(), &MyMoneyFile::dataChanged, q, &KInvestmentView::refresh);
0164     }
0165 
0166     void loadInvestmentTab()
0167     {
0168         Q_Q(KInvestmentView);
0169         m_equitiesProxyModel->setHideClosedAccounts(!KMyMoneySettings::showAllAccounts());
0170         m_equitiesProxyModel->setHideZeroBalanceAccounts(KMyMoneySettings::hideZeroBalanceEquities());
0171         m_equitiesProxyModel->invalidate();
0172 
0173         m_accountsProxyModel->setHideClosedAccounts(!KMyMoneySettings::showAllAccounts());
0174         m_accountsProxyModel->invalidate();
0175 
0176         if (!m_idInvAcc.isEmpty()) {                                          // check if account to be selected exist
0177             try {                                                                  // it could not exist anymore (e.g. another file has been opened)
0178                 const auto acc = MyMoneyFile::instance()->account(m_idInvAcc);    // then this should throw an exception
0179                 if (acc.accountType() == eMyMoney::Account::Type::Investment)                 // it could be that id exists but account in new file isn't investment account anymore
0180                     q->slotSelectAccount(m_idInvAcc);                                  // otherwise select preset account
0181                 else
0182                     m_idInvAcc.clear();
0183             } catch (const MyMoneyException &) {
0184                 m_idInvAcc.clear();                                               // account is invalid
0185             }
0186         }
0187 
0188         if (m_idInvAcc.isEmpty())                                             // if account is invalid select default one
0189             selectDefaultInvestmentAccount();
0190 
0191         ui->m_accountComboBox->expandAll();
0192     }
0193 
0194     void loadSecuritiesTab()
0195     {
0196         ui->m_deleteSecurityButton->setEnabled(false);
0197         ui->m_editSecurityButton->setEnabled(false);
0198 
0199         m_securitiesProxyModel->invalidate();
0200         // securities model contains both securities and currencies, so...
0201         // ...search here for securities node and show only this
0202         const auto indexList = m_securitiesProxyModel->match(m_securitiesProxyModel->index(0, 0), Qt::DisplayRole, QLatin1String("Securities"), 1, Qt::MatchFlags(Qt::MatchExactly | Qt::MatchWrap));
0203         if (!indexList.isEmpty())
0204             ui->m_securitiesTree->setRootIndex(indexList.first());
0205     }
0206 
0207     /**
0208       * This slot is used to programatically preselect default account in investment view
0209       */
0210     void selectDefaultInvestmentAccount()
0211     {
0212         Q_Q(KInvestmentView);
0213         if (m_accountsProxyModel->rowCount() > 0) {
0214             auto firsitem = m_accountsProxyModel->index(0, 0, QModelIndex());
0215             if (m_accountsProxyModel->hasChildren(firsitem)) {
0216                 auto seconditem = m_accountsProxyModel->index(0, 0, firsitem);
0217                 q->slotSelectAccount(seconditem.data(EquitiesModel::EquityID).toString());
0218             }
0219         }
0220     }
0221 
0222     /**
0223       * This slots returns security currently selected in tree view
0224       */
0225     MyMoneySecurity currentSecurity()
0226     {
0227         MyMoneySecurity sec;
0228         auto treeItem = ui->m_securitiesTree->currentIndex();
0229         if (treeItem.isValid()) {
0230             auto mdlItem = m_securitiesProxyModel->index(treeItem.row(), SecuritiesModel::Security, treeItem.parent());
0231             sec = MyMoneyFile::instance()->security(mdlItem.data(Qt::UserRole).toString());
0232         }
0233         return sec;
0234     }
0235 
0236     /**
0237       * This slots returns equity currently selected in tree view
0238       */
0239     MyMoneyAccount currentEquity()
0240     {
0241         MyMoneyAccount equ;
0242         auto treeItem = ui->m_equitiesTree->currentIndex();
0243         if (treeItem.isValid()) {
0244             auto mdlItem = m_equitiesProxyModel->index(treeItem.row(), EquitiesModel::Equity, treeItem.parent());
0245             equ = MyMoneyFile::instance()->account(mdlItem.data(EquitiesModel::EquityID).toString());
0246         }
0247         return equ;
0248     }
0249 
0250     KInvestmentView     *q_ptr;
0251     Ui::KInvestmentView *ui;
0252     QString             m_idInvAcc;
0253 
0254     /**
0255       * This member holds the load state of page
0256       */
0257     bool m_needLoad;
0258 
0259     bool m_needReload[2];
0260     AccountNamesFilterProxyModel *m_accountsProxyModel;
0261     EquitiesFilterProxyModel     *m_equitiesProxyModel;
0262     SecuritiesFilterProxyModel   *m_securitiesProxyModel;
0263 
0264     MyMoneyAccount m_currentEquity;
0265 };
0266 
0267 #endif