File indexing completed on 2024-05-12 16:44:05

0001 /*
0002     SPDX-FileCopyrightText: 2002-2018 Thomas Baumgart <tbaumgart@kde.org>
0003     SPDX-FileCopyrightText: 2017-2018 Łukasz Wojniłowicz <lukasz.wojnilowicz@gmail.com>
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #ifndef KTRANSACTIONFILTER_P_H
0008 #define KTRANSACTIONFILTER_P_H
0009 
0010 #include "ktransactionfilter.h"
0011 
0012 // ----------------------------------------------------------------------------
0013 // QT Includes
0014 
0015 // ----------------------------------------------------------------------------
0016 // KDE Includes
0017 
0018 #include <KLocalizedString>
0019 
0020 // ----------------------------------------------------------------------------
0021 // Project Includes
0022 
0023 #include "ui_ktransactionfilter.h"
0024 
0025 #include "mymoneyaccount.h"
0026 #include "mymoneyfile.h"
0027 #include "mymoneypayee.h"
0028 #include "mymoneytag.h"
0029 #include "kmymoneysettings.h"
0030 #include "transaction.h"
0031 #include "daterangedlg.h"
0032 #include "mymoneytransactionfilter.h"
0033 
0034 #include "widgetenums.h"
0035 #include "mymoneyenums.h"
0036 
0037 class KTransactionFilterPrivate
0038 {
0039     Q_DISABLE_COPY(KTransactionFilterPrivate)
0040     Q_DECLARE_PUBLIC(KTransactionFilter)
0041 
0042 public:
0043     enum opTypeE {
0044         addAccountToFilter = 0,
0045         addCategoryToFilter,
0046         addPayeeToFilter,
0047         addTagToFilter
0048     };
0049 
0050     // the set of accounts to choose from
0051     AccountSet accountSet;
0052 
0053     explicit KTransactionFilterPrivate(KTransactionFilter *qq) :
0054         q_ptr(qq),
0055         ui(new Ui::KTransactionFilter),
0056         m_dateRange(nullptr)
0057     {
0058     }
0059 
0060     ~KTransactionFilterPrivate()
0061     {
0062         delete ui;
0063     }
0064 
0065     void init(bool withEquityAccounts, bool withInvestments, bool withDataTab)
0066     {
0067         Q_Q(KTransactionFilter);
0068         ui->setupUi(q);
0069 
0070         if (withDataTab) {
0071             m_dateRange = new DateRangeDlg;
0072             ui->dateRangeLayout->insertWidget(0, m_dateRange);
0073             // in case the date selection changes, we update the selection
0074             q->connect(m_dateRange, &DateRangeDlg::rangeChanged, q, &KTransactionFilter::slotUpdateSelections);
0075         } else {
0076             ui->m_criteriaTab->removeTab(ui->m_criteriaTab->indexOf(ui->m_dateTab));
0077             ui->m_dateTab->deleteLater();
0078         }
0079 
0080         // 'cause we don't have a separate setupTextPage
0081         q->connect(ui->m_textEdit, &QLineEdit::textChanged, q, &KTransactionFilter::slotUpdateSelections);
0082 
0083         setupAccountsPage(withEquityAccounts, withInvestments);
0084         setupCategoriesPage();
0085         setupAmountPage();
0086         setupPayeesPage();
0087         setupTagsPage();
0088         setupDetailsPage();
0089 
0090         // We don't need to add the default into the list (see ::slotShowHelp() why)
0091         // m_helpAnchor[m_ui->m_textTab] = QLatin1String("details.search");
0092         m_helpAnchor[ui->m_accountTab] = QLatin1String("details.search.account");
0093         m_helpAnchor[ui->m_dateTab] = QLatin1String("details.search.date");
0094         m_helpAnchor[ui->m_amountTab] = QLatin1String("details.search.amount");
0095         m_helpAnchor[ui->m_categoryTab] = QLatin1String("details.search.category");
0096         m_helpAnchor[ui->m_payeeTab] = QLatin1String("details.search.payee");
0097         m_helpAnchor[ui->m_tagTab] = QLatin1String("details.search.tag"); //FIXME-ALEX update Help
0098         m_helpAnchor[ui->m_detailsTab] = QLatin1String("details.search.details");
0099 
0100         q->slotUpdateSelections();
0101 
0102         ui->m_textEdit->setFocus();
0103     }
0104 
0105     /**
0106       * q method returns information about the selection state
0107       * of the items in the m_accountsView.
0108       *
0109       * @param view pointer to the listview to scan
0110       *
0111       * @retval true if all items in the view are marked
0112       * @retval false if at least one item is not marked
0113       *
0114       * @note If the view contains no items the method returns @p true.
0115       */
0116     bool allItemsSelected(const QTreeWidgetItem *item) const
0117     {
0118         QTreeWidgetItem* it_v;
0119 
0120         for (auto i = 0; i < item->childCount(); ++i) {
0121             it_v = item->child(i);
0122             if (!(it_v->checkState(0) == Qt::Checked && allItemsSelected(it_v))) {
0123                 return false;
0124             }
0125         }
0126         return true;
0127     }
0128 
0129     bool allItemsSelected(const QTreeWidget* view) const
0130     {
0131         QTreeWidgetItem* it_v;
0132 
0133         for (int i = 0; i < view->invisibleRootItem()->childCount(); ++i) {
0134             it_v = view->invisibleRootItem()->child(i);
0135             if (it_v->flags() & Qt::ItemIsUserCheckable) {
0136                 if (!(it_v->checkState(0) == Qt::Checked && allItemsSelected(it_v))) {
0137                     return false;
0138                 } else {
0139                     if (!allItemsSelected(it_v))
0140                         return false;
0141                 }
0142             }
0143         }
0144         return true;
0145     }
0146 
0147     void addItemToFilter(const opTypeE op, const QString& id)
0148     {
0149         switch (op) {
0150         case addAccountToFilter:
0151             m_filter.addAccount(id);
0152             break;
0153         case addCategoryToFilter:
0154             m_filter.addCategory(id);
0155             break;
0156         case addPayeeToFilter:
0157             m_filter.addPayee(id);
0158             break;
0159         case addTagToFilter:
0160             m_filter.addTag(id);
0161             break;
0162         }
0163     }
0164 
0165     void scanCheckListItems(const QTreeWidgetItem* item, const opTypeE op)
0166     {
0167         QTreeWidgetItem* it_v;
0168 
0169         for (auto i = 0; i < item->childCount(); ++i) {
0170             it_v = item->child(i);
0171             QVariant idData = it_v->data(0, Qt::UserRole);
0172             if (it_v->flags() & Qt::ItemIsUserCheckable) {
0173                 if (it_v->checkState(0) == Qt::Checked)
0174                     addItemToFilter(op, idData.toString());
0175             }
0176             scanCheckListItems(it_v, op);
0177         }
0178     }
0179 
0180     void scanCheckListItems(const QTreeWidget* view, const opTypeE op)
0181     {
0182         QTreeWidgetItem* it_v;
0183 
0184         for (auto i = 0; i < view->invisibleRootItem()->childCount(); ++i) {
0185             it_v = view->invisibleRootItem()->child(i);
0186             QVariant idData = it_v->data(0, Qt::UserRole);
0187             if (it_v->flags() & Qt::ItemIsUserCheckable) {
0188                 if (it_v->checkState(0) == Qt::Checked) {
0189                     addItemToFilter(op, idData.toString());
0190                 }
0191             }
0192             scanCheckListItems(it_v, op);
0193         }
0194     }
0195 
0196     void selectAllItems(QTreeWidget* view, const bool state)
0197     {
0198         QTreeWidgetItem* it_v;
0199 
0200         for (int i = 0; i < view->invisibleRootItem()->childCount(); ++i) {
0201             it_v = view->invisibleRootItem()->child(i);
0202             if (it_v->flags() & Qt::ItemIsUserCheckable) {
0203                 it_v->setCheckState(0, state ? Qt::Checked : Qt::Unchecked);
0204             }
0205             selectAllSubItems(it_v, state);
0206         }
0207         Q_Q(KTransactionFilter);
0208         q->slotUpdateSelections();
0209     }
0210 
0211     void selectItems(QTreeWidget* view, const QStringList& list, const bool state)
0212     {
0213         QTreeWidgetItem* it_v;
0214 
0215         for (int i = 0; i < view->invisibleRootItem()->childCount(); ++i) {
0216             it_v = view->invisibleRootItem()->child(i);
0217             QVariant idData = it_v->data(0, Qt::UserRole);
0218             if (it_v->flags() & Qt::ItemIsUserCheckable && list.contains(idData.toString())) {
0219                 it_v->setCheckState(0, state ? Qt::Checked : Qt::Unchecked);
0220             }
0221             selectSubItems(it_v, list, state);
0222         }
0223 
0224         Q_Q(KTransactionFilter);
0225         q->slotUpdateSelections();
0226     }
0227 
0228     void selectAllSubItems(QTreeWidgetItem* item, const bool state)
0229     {
0230         QTreeWidgetItem* it_v;
0231 
0232         for (int i = 0; i < item->childCount(); ++i) {
0233             it_v = item->child(i);
0234             it_v->setCheckState(0, state ? Qt::Checked : Qt::Unchecked);
0235             selectAllSubItems(it_v, state);
0236         }
0237     }
0238 
0239     void selectSubItems(QTreeWidgetItem* item, const QStringList& list, const bool state)
0240     {
0241         QTreeWidgetItem* it_v;
0242 
0243         for (int i = 0; i < item->childCount(); ++i) {
0244             it_v = item->child(i);
0245             QVariant idData = it_v->data(0, Qt::UserRole);
0246             if (list.contains(idData.toString()))
0247                 it_v->setCheckState(0, state ? Qt::Checked : Qt::Unchecked);
0248             selectSubItems(it_v, list, state);
0249         }
0250     }
0251 
0252     /**
0253       * q method loads the m_tagsView with the tags name
0254       * found in the engine.
0255       */
0256     void loadTags()
0257     {
0258         MyMoneyFile* file = MyMoneyFile::instance();
0259         QList<MyMoneyTag> list;
0260         QList<MyMoneyTag>::Iterator it_l;
0261 
0262         list = file->tagList();
0263         // load view
0264         for (it_l = list.begin(); it_l != list.end(); ++it_l) {
0265             auto item = new QTreeWidgetItem(ui->m_tagsView);
0266             item->setText(0, (*it_l).name());
0267             item->setData(0, Qt::UserRole, (*it_l).id());
0268             item->setCheckState(0, Qt::Checked);
0269         }
0270     }
0271 
0272     /**
0273       * q method loads the m_payeesView with the payees name
0274       * found in the engine.
0275       */
0276     void loadPayees()
0277     {
0278         MyMoneyFile* file = MyMoneyFile::instance();
0279         QList<MyMoneyPayee> list;
0280         QList<MyMoneyPayee>::Iterator it_l;
0281 
0282         list = file->payeeList();
0283         // load view
0284         for (it_l = list.begin(); it_l != list.end(); ++it_l) {
0285             auto item = new QTreeWidgetItem(ui->m_payeesView);
0286             item->setText(0, (*it_l).name());
0287             item->setData(0, Qt::UserRole, (*it_l).id());
0288             item->setCheckState(0, Qt::Checked);
0289         }
0290     }
0291 
0292     void setupDetailsPage()
0293     {
0294         Q_Q(KTransactionFilter);
0295         q->connect(ui->m_typeBox,     static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), q, &KTransactionFilter::slotUpdateSelections);
0296         q->connect(ui->m_stateBox,    static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), q, &KTransactionFilter::slotUpdateSelections);
0297         q->connect(ui->m_validityBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), q, &KTransactionFilter::slotUpdateSelections);
0298 
0299         q->connect(ui->m_nrButton, &QAbstractButton::clicked, q, &KTransactionFilter::slotNrSelected);
0300         q->connect(ui->m_nrRangeButton, &QAbstractButton::clicked, q, &KTransactionFilter::slotNrRangeSelected);
0301         q->connect(ui->m_nrEdit,      &QLineEdit::textChanged, q, &KTransactionFilter::slotUpdateSelections);
0302         q->connect(ui->m_nrFromEdit,  &QLineEdit::textChanged, q, &KTransactionFilter::slotUpdateSelections);
0303         q->connect(ui->m_nrToEdit,    &QLineEdit::textChanged, q, &KTransactionFilter::slotUpdateSelections);
0304 
0305         ui->m_nrButton->setChecked(true);
0306         q->slotNrSelected();
0307     }
0308 
0309     void setupTagsPage()
0310     {
0311         Q_Q(KTransactionFilter);
0312         ui->m_tagsView->setSelectionMode(QAbstractItemView::SingleSelection);
0313         ui->m_tagsView->header()->hide();
0314         ui->m_tagsView->setAlternatingRowColors(true);
0315 
0316         loadTags();
0317 
0318         ui->m_tagsView->sortItems(0, Qt::AscendingOrder);
0319         ui->m_emptyTagsButton->setCheckState(Qt::Unchecked);
0320 
0321         q->connect(ui->m_allTagsButton,   &QAbstractButton::clicked, q, &KTransactionFilter::slotSelectAllTags);
0322         q->connect(ui->m_clearTagsButton, &QAbstractButton::clicked, q, &KTransactionFilter::slotDeselectAllTags);
0323         q->connect(ui->m_emptyTagsButton, &QCheckBox::stateChanged,  q, &KTransactionFilter::slotUpdateSelections);
0324         q->connect(ui->m_tagsView,        &QTreeWidget::itemChanged, q, &KTransactionFilter::slotUpdateSelections);
0325     }
0326 
0327     void setupPayeesPage()
0328     {
0329         Q_Q(KTransactionFilter);
0330         ui->m_payeesView->setSelectionMode(QAbstractItemView::SingleSelection);
0331         ui->m_payeesView->header()->hide();
0332         ui->m_payeesView->setAlternatingRowColors(true);
0333 
0334         loadPayees();
0335 
0336         ui->m_payeesView->sortItems(0, Qt::AscendingOrder);
0337         ui->m_emptyPayeesButton->setCheckState(Qt::Unchecked);
0338 
0339         q->connect(ui->m_allPayeesButton, &QAbstractButton::clicked, q, &KTransactionFilter::slotSelectAllPayees);
0340         q->connect(ui->m_clearPayeesButton, &QAbstractButton::clicked, q, &KTransactionFilter::slotDeselectAllPayees);
0341         q->connect(ui->m_emptyPayeesButton, &QCheckBox::stateChanged,  q, &KTransactionFilter::slotUpdateSelections);
0342         q->connect(ui->m_payeesView,        &QTreeWidget::itemChanged, q, &KTransactionFilter::slotUpdateSelections);
0343     }
0344 
0345     void setupAmountPage()
0346     {
0347         Q_Q(KTransactionFilter);
0348         q->connect(ui->m_amountButton, &QAbstractButton::clicked, q, &KTransactionFilter::slotAmountSelected);
0349         q->connect(ui->m_amountRangeButton, &QAbstractButton::clicked, q, &KTransactionFilter::slotAmountRangeSelected);
0350 
0351         q->connect(ui->m_amountEdit,      &AmountEdit::textChanged, q, &KTransactionFilter::slotUpdateSelections);
0352         q->connect(ui->m_amountFromEdit,  &AmountEdit::textChanged, q, &KTransactionFilter::slotUpdateSelections);
0353         q->connect(ui->m_amountToEdit,    &AmountEdit::textChanged, q, &KTransactionFilter::slotUpdateSelections);
0354 
0355         ui->m_amountButton->setChecked(true);
0356         q->slotAmountSelected();
0357     }
0358 
0359     void setupCategoriesPage()
0360     {
0361         Q_Q(KTransactionFilter);
0362         ui->m_categoriesView->setSelectionMode(QTreeWidget::MultiSelection);
0363         AccountSet categorySet;
0364         categorySet.addAccountGroup(eMyMoney::Account::Type::Income);
0365         categorySet.addAccountGroup(eMyMoney::Account::Type::Expense);
0366         categorySet.load(ui->m_categoriesView);
0367         q->connect(ui->m_categoriesView, &KMyMoneyAccountSelector::stateChanged, q, &KTransactionFilter::slotUpdateSelections);
0368     }
0369 
0370     void setupAccountsPage(bool withEquityAccounts, bool withInvestments)
0371     {
0372         Q_Q(KTransactionFilter);
0373         ui->m_accountsView->setSelectionMode(QTreeWidget::MultiSelection);
0374         accountSet.addAccountGroup(eMyMoney::Account::Type::Asset);
0375         accountSet.addAccountGroup(eMyMoney::Account::Type::Liability);
0376 
0377         if (withEquityAccounts)
0378             accountSet.addAccountGroup(eMyMoney::Account::Type::Equity);
0379 
0380         // set the accountset to show closed account if the settings say so
0381         accountSet.setHideClosedAccounts(!KMyMoneySettings::showAllAccounts());
0382         accountSet.setShowInvestments(withInvestments);
0383         accountSet.load(ui->m_accountsView);
0384         q->connect(ui->m_accountsView, &KMyMoneyAccountSelector::stateChanged, q, &KTransactionFilter::slotUpdateSelections);
0385     }
0386 
0387     KTransactionFilter      *q_ptr;
0388     Ui::KTransactionFilter  *ui;
0389     QDate                m_startDates[(int)eMyMoney::TransactionFilter::Date::LastDateItem];
0390     QDate                m_endDates[(int)eMyMoney::TransactionFilter::Date::LastDateItem];
0391 
0392     MyMoneyTransactionFilter        m_filter;
0393 
0394     QMap<QWidget*, QString>         m_helpAnchor;
0395 
0396     DateRangeDlg                    *m_dateRange;
0397 
0398 };
0399 
0400 #endif