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

0001 /*
0002     SPDX-FileCopyrightText: 2019 Thomas Baumgart <tbaumgart@kde.org>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "ledgerfilterbase.h"
0007 #include "ledgerfilterbase_p.h"
0008 
0009 // ----------------------------------------------------------------------------
0010 // QT Includes
0011 
0012 #include <QDate>
0013 
0014 // ----------------------------------------------------------------------------
0015 // KDE Includes
0016 
0017 #include <KLocalizedString>
0018 
0019 // ----------------------------------------------------------------------------
0020 // Project Includes
0021 
0022 #include "accountsmodel.h"
0023 #include "journalmodel.h"
0024 #include "ledgerviewsettings.h"
0025 #include "mymoneyenums.h"
0026 #include "mymoneyfile.h"
0027 #include "specialdatesmodel.h"
0028 
0029 using namespace eMyMoney;
0030 
0031 LedgerFilterBase::LedgerFilterBase(LedgerFilterBasePrivate* dd, QObject* parent)
0032     : LedgerSortProxyModel(dd, parent)
0033 {
0034     Q_D(LedgerFilterBase);
0035     d->concatModel = new LedgerConcatenateModel(parent);
0036     connect(d->concatModel, &QAbstractItemModel::modelReset, this, [&]() {
0037         Q_D(LedgerFilterBase);
0038         d->splitMaxLineCount.clear();
0039     });
0040 
0041     setFilterRole(-1);
0042     setFilterKeyColumn(-1);
0043 }
0044 
0045 LedgerFilterBase::~LedgerFilterBase()
0046 {
0047 }
0048 
0049 void LedgerFilterBase::setAccountType(Account::Type type)
0050 {
0051     Q_D(LedgerFilterBase);
0052     d->accountType = type;
0053 }
0054 
0055 QVariant LedgerFilterBase::headerData(int section, Qt::Orientation orientation, int role) const
0056 {
0057     if(orientation == Qt::Horizontal && role == Qt::DisplayRole) {
0058         Q_D(const LedgerFilterBase);
0059         switch(section) {
0060         case JournalModel::Column::Payment:
0061             switch(d->accountType) {
0062             case Account::Type::CreditCard:
0063                 return i18nc("Payment made with credit card", "Charge");
0064 
0065             case Account::Type::Asset:
0066             case Account::Type::AssetLoan:
0067                 return i18nc("Decrease of asset/liability value", "Decrease");
0068 
0069             case Account::Type::Liability:
0070             case Account::Type::Loan:
0071                 return i18nc("Increase of asset/liability value", "Increase");
0072 
0073             case Account::Type::Income:
0074             case Account::Type::Expense:
0075                 return i18n("Income");
0076 
0077             default:
0078                 break;
0079             }
0080             break;
0081 
0082         case JournalModel::Column::Deposit:
0083             switch(d->accountType) {
0084             case Account::Type::CreditCard:
0085                 return i18nc("Payment towards credit card", "Payment");
0086 
0087             case Account::Type::Asset:
0088             case Account::Type::AssetLoan:
0089                 return i18nc("Increase of asset/liability value", "Increase");
0090 
0091             case Account::Type::Liability:
0092             case Account::Type::Loan:
0093                 return i18nc("Decrease of asset/liability value", "Decrease");
0094 
0095             case Account::Type::Income:
0096             case Account::Type::Expense:
0097                 return i18n("Expense");
0098 
0099             default:
0100                 break;
0101             }
0102             break;
0103         }
0104     }
0105     return QSortFilterProxyModel::headerData(section, orientation, role);
0106 }
0107 
0108 void LedgerFilterBase::setMaintainBalances(bool maintainBalances)
0109 {
0110     Q_D(LedgerFilterBase);
0111     d->maintainBalances = maintainBalances;
0112 }
0113 
0114 bool LedgerFilterBase::setData(const QModelIndex& index, const QVariant& value, int role)
0115 {
0116     Q_D(LedgerFilterBase);
0117 
0118     // check for cache reset which can occur with an invalid index
0119     if ((role == eMyMoney::Model::JournalSplitMaxLinesCountRole) && (value.toInt() < 0)) {
0120         d->splitMaxLineCount.clear();
0121         return true;
0122     }
0123 
0124     if (index.isValid()) {
0125         if ((d->maintainBalances) && (role == eMyMoney::Model::JournalBalanceRole)) {
0126             if (rowCount() >= d->balances.size()) {
0127                 d->balances.resize(rowCount() + 1);
0128             }
0129             d->balances[index.row()] = qvariant_cast<MyMoneyMoney>(value);
0130             return true;
0131 
0132         } else if (role == eMyMoney::Model::JournalSplitMaxLinesCountRole) {
0133             const int cacheValue = value.toInt();
0134             if (rowCount() >= d->splitMaxLineCount.size()) {
0135                 d->splitMaxLineCount.resize(rowCount() + 1);
0136             }
0137             d->splitMaxLineCount[index.row()] = cacheValue;
0138             return true;
0139         }
0140         return false;
0141     }
0142     return LedgerSortProxyModel::setData(index, value, role);
0143 }
0144 
0145 QVariant LedgerFilterBase::data(const QModelIndex& index, int role) const
0146 {
0147     Q_D(const LedgerFilterBase);
0148     if (index.isValid()) {
0149         if (role == eMyMoney::Model::JournalSplitMaxLinesCountRole) {
0150             if (rowCount() > d->splitMaxLineCount.size()) {
0151                 return 0;
0152             }
0153             return d->splitMaxLineCount.at(index.row());
0154         }
0155     }
0156     return LedgerSortProxyModel::data(index, role);
0157 }
0158 
0159 Qt::ItemFlags LedgerFilterBase::flags(const QModelIndex& idx) const
0160 {
0161     Q_D(const LedgerFilterBase);
0162     auto flags = LedgerSortProxyModel::flags(idx);
0163     if (!d->enableEdit) {
0164         flags &= ~Qt::ItemIsEditable;
0165     }
0166     return flags;
0167 }
0168 
0169 bool LedgerFilterBase::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const
0170 {
0171     Q_D(const LedgerFilterBase);
0172 
0173     // if no filter is set, we don't display anything
0174     if (d->filterIds.isEmpty())
0175         return false;
0176 
0177     // special dates are always true
0178     const auto idx = sourceModel()->index(source_row, 0, source_parent);
0179     if (d->isSpecialDatesModel(idx)) {
0180         return true;
0181     }
0182 
0183     if (LedgerSortProxyModel::filterAcceptsRow(source_row, source_parent)) {
0184         const auto id = idx.data(filterRole()).toString();
0185         bool rc = d->filterIds.contains(id);
0186 
0187         // in case a journal entry has no id, it is the new transaction placeholder
0188         if (!rc) {
0189             rc = idx.data(eMyMoney::Model::IdRole).toString().isEmpty();
0190         }
0191         return rc;
0192     }
0193     return false;
0194 }
0195 
0196 void LedgerFilterBase::setFilterFixedString(const QString& id)
0197 {
0198     setFilterFixedStrings(QStringList() << id);
0199 }
0200 
0201 void LedgerFilterBase::setFilterFixedStrings(const QStringList& filters)
0202 {
0203     Q_D(LedgerFilterBase);
0204     d->filterIds = filters;
0205     invalidateFilter();
0206 }
0207 
0208 void LedgerFilterBase::appendFilterFixedString(const QString& filter)
0209 {
0210     Q_D(LedgerFilterBase);
0211     if (!d->filterIds.contains(filter)) {
0212         d->filterIds.append(filter);
0213         invalidateFilter();
0214     }
0215 }
0216 
0217 QStringList LedgerFilterBase::filterFixedStrings() const
0218 {
0219     Q_D(const LedgerFilterBase);
0220     return d->filterIds;
0221 }
0222 
0223 
0224 void LedgerFilterBase::setShowEntryForNewTransaction(bool show)
0225 {
0226     if (show) {
0227         addSourceModel(MyMoneyFile::instance()->journalModel()->newTransaction());
0228     } else {
0229         removeSourceModel(MyMoneyFile::instance()->journalModel()->newTransaction());
0230     }
0231 }
0232 
0233 
0234 void LedgerFilterBase::addSourceModel(QAbstractItemModel* model)
0235 {
0236     Q_D(LedgerFilterBase);
0237     if (model && !d->sourceModels.contains(model)) {
0238         d->concatModel->addSourceModel(model);
0239         d->sourceModels.insert(model);
0240         invalidateFilter();
0241     }
0242 }
0243 
0244 void LedgerFilterBase::removeSourceModel(QAbstractItemModel* model)
0245 {
0246     Q_D(LedgerFilterBase);
0247     if (model && d->sourceModels.contains(model)) {
0248         d->concatModel->removeSourceModel(model);
0249         d->sourceModels.remove(model);
0250         invalidateFilter();
0251     }
0252 }
0253 
0254 void LedgerFilterBase::setLedgerIsEditable(bool enableEdit)
0255 {
0256     Q_D(LedgerFilterBase);
0257     d->enableEdit = enableEdit;
0258 }