File indexing completed on 2024-05-12 05:07:56
0001 /* 0002 SPDX-FileCopyrightText: 2010-2014 Cristian Oneț <onet.cristian@gmail.com> 0003 SPDX-FileCopyrightText: 2017-2018 Łukasz Wojniłowicz <lukasz.wojnilowicz@gmail.com> 0004 SPDX-FileCopyrightText: 2019 Thomas Baumgart <tbaumgart@kde.org> 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "kmymoneyaccounttreeview.h" 0009 0010 // ---------------------------------------------------------------------------- 0011 // QT Includes 0012 0013 #include <QObject> 0014 #include <QHeaderView> 0015 #include <QMouseEvent> 0016 #include <QPoint> 0017 0018 // ---------------------------------------------------------------------------- 0019 // KDE Includes 0020 0021 #include <KConfigGroup> 0022 #include <KSharedConfig> 0023 0024 // ---------------------------------------------------------------------------- 0025 // Project Includes 0026 0027 #include "mymoneyfile.h" 0028 #include "mymoneyinstitution.h" 0029 #include "mymoneyaccount.h" 0030 #include "accountsmodel.h" 0031 #include "institutionsmodel.h" 0032 #include "accountsproxymodel.h" 0033 #include "menuenums.h" 0034 #include "selectedobjects.h" 0035 0036 class KMyMoneyAccountTreeViewPrivate 0037 { 0038 Q_DECLARE_PUBLIC(KMyMoneyAccountTreeView) 0039 Q_DISABLE_COPY_MOVE(KMyMoneyAccountTreeViewPrivate) 0040 0041 public: 0042 KMyMoneyAccountTreeViewPrivate(KMyMoneyAccountTreeView *qq) 0043 : q_ptr(qq), 0044 proxyModel(new AccountsProxyModel(qq)) 0045 {} 0046 0047 void openIndex(const QModelIndex &index) 0048 { 0049 Q_Q(KMyMoneyAccountTreeView); 0050 if (index.isValid()) { 0051 QModelIndex baseIdx = MyMoneyFile::baseModel()->mapToBaseSource(index); 0052 // baseIdx could point into the accountsModel or the institutionsModel. 0053 // in case of the institutionsModel it is unclear if it is an account or 0054 // an institution. So we simply extract the id and check where we find 0055 // the object. 0056 const auto objId = baseIdx.data(eMyMoney::Model::IdRole).toString(); 0057 auto idx = MyMoneyFile::instance()->accountsModel()->indexById(objId); 0058 if (idx.isValid() || (objId == MyMoneyAccount::stdAccName(eMyMoney::Account::Standard::Favorite))) { 0059 // In case we should open an account or category we do it 0060 // For the top level accounts we switch between expanded and collapsed view 0061 if (index.parent().isValid()) { 0062 Q_EMIT q->requestActionTrigger(eMenu::Action::OpenAccount); 0063 } else { 0064 q->setExpanded(index, !q->isExpanded(index)); 0065 } 0066 } else { 0067 idx = MyMoneyFile::instance()->institutionsModel()->indexById(objId); 0068 if (idx.isValid()) { 0069 Q_EMIT q->requestActionTrigger(eMenu::Action::EditInstitution); 0070 } 0071 } 0072 } 0073 } 0074 0075 KMyMoneyAccountTreeView* q_ptr; 0076 AccountsProxyModel* proxyModel; 0077 }; 0078 0079 KMyMoneyAccountTreeView::KMyMoneyAccountTreeView(QWidget *parent) 0080 : KMyMoneyTreeView(parent) 0081 , d_ptr(new KMyMoneyAccountTreeViewPrivate(this)) 0082 { 0083 setContextMenuPolicy(Qt::CustomContextMenu); // allow context menu to be opened on tree items 0084 connect(this, &QWidget::customContextMenuRequested, this, &KMyMoneyAccountTreeView::customContextMenuRequested); 0085 setAllColumnsShowFocus(true); 0086 setAlternatingRowColors(true); 0087 setIconSize(QSize(22, 22)); 0088 setSortingEnabled(true); 0089 QTreeView::header()->setStretchLastSection(false); 0090 0091 connect(this, &KMyMoneyTreeView::startEdit, this, [&](const QModelIndex& idx) { 0092 Q_D(KMyMoneyAccountTreeView); 0093 d->openIndex(idx); 0094 }); 0095 } 0096 0097 KMyMoneyAccountTreeView::~KMyMoneyAccountTreeView() 0098 { 0099 } 0100 0101 0102 void KMyMoneyAccountTreeView::setModel(QAbstractItemModel* model) 0103 { 0104 Q_D(KMyMoneyAccountTreeView); 0105 d->proxyModel->setSourceModel(model); 0106 QTreeView::setModel(d->proxyModel); 0107 0108 for (int column = 0; column < model->columnCount(); column++) { 0109 QVariant headerData = model->headerData(column, Qt::Horizontal, Qt::UserRole); 0110 QHeaderView::ResizeMode mode = QHeaderView::ResizeMode(headerData.toInt()); 0111 QTreeView::header()->setSectionResizeMode(column, mode); 0112 } 0113 } 0114 0115 void KMyMoneyAccountTreeView::setProxyModel(AccountsProxyModel* model) 0116 { 0117 Q_D(KMyMoneyAccountTreeView); 0118 // unlink a possible sourceModel 0119 QAbstractItemModel* sourceModel = d->proxyModel->sourceModel(); 0120 if (sourceModel) { 0121 d->proxyModel->setSourceModel(nullptr); 0122 } 0123 0124 // delete the old proxy 0125 d->proxyModel->deleteLater(); 0126 0127 // reparent the new proxy 0128 model->setParent(this); 0129 0130 // and insert it into the chain 0131 d->proxyModel = model; 0132 d->proxyModel->setSourceModel(sourceModel); 0133 QTreeView::setModel(d->proxyModel); 0134 0135 } 0136 0137 AccountsProxyModel* KMyMoneyAccountTreeView::proxyModel() const 0138 { 0139 Q_D(const KMyMoneyAccountTreeView); 0140 return d->proxyModel; 0141 } 0142 0143 void KMyMoneyAccountTreeView::customContextMenuRequested(const QPoint pos) 0144 { 0145 if (currentIndex().isValid() && (model()->flags(currentIndex()) & Qt::ItemIsSelectable)) { 0146 auto objId = currentIndex().data(eMyMoney::Model::IdRole).toString(); 0147 const auto account = MyMoneyFile::instance()->accountsModel()->itemById(objId); 0148 if (!account.id().isEmpty()) { 0149 if (account.isIncomeExpense()) { 0150 Q_EMIT requestCustomContextMenu(eMenu::Menu::Category, viewport()->mapToGlobal(pos)); 0151 } else { 0152 Q_EMIT requestCustomContextMenu(eMenu::Menu::Account, viewport()->mapToGlobal(pos)); 0153 } 0154 } 0155 const auto institution = MyMoneyFile::instance()->institutionsModel()->itemById(objId); 0156 if (!institution.id().isEmpty()) { 0157 // the institutions model also reports accounts as institutions at this point. 0158 // We can differentiate between the two objects by looking at the parent of 0159 // the index. If it is valid, we have been called via an account, 0160 // if it is invalid the source is an institution. 0161 if (!currentIndex().parent().isValid()) { 0162 Q_EMIT requestCustomContextMenu(eMenu::Menu::Institution, viewport()->mapToGlobal(pos)); 0163 } 0164 } 0165 } 0166 } 0167 0168 void KMyMoneyAccountTreeView::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) 0169 { 0170 SelectedObjects selections; 0171 0172 QTreeView::selectionChanged(selected, deselected); 0173 if (!selected.isEmpty()) { 0174 QModelIndexList idxList = selected.indexes(); 0175 if (!idxList.isEmpty()) { 0176 auto objId = selected.indexes().front().data(eMyMoney::Model::IdRole).toString(); 0177 const auto account = MyMoneyFile::instance()->accountsModel()->itemById(objId); 0178 if (!account.id().isEmpty()) { 0179 selections.addSelection(SelectedObjects::Account, account.id()); 0180 if (!account.institutionId().isEmpty()) { 0181 selections.addSelection(SelectedObjects::Institution, account.institutionId()); 0182 } 0183 } else { 0184 0185 const auto institution = MyMoneyFile::instance()->institutionsModel()->itemById(objId); 0186 if (!institution.id().isEmpty()) { 0187 selections.addSelection(SelectedObjects::Institution, institution.id()); 0188 } 0189 } 0190 } 0191 } 0192 // since no object was selected reset the object selection 0193 Q_EMIT requestSelectionChange(selections); 0194 }