File indexing completed on 2024-05-19 05:07:22

0001 /*
0002     SPDX-FileCopyrightText: 2004-2006 Ace Jones <acejones@users.sourceforge.net>
0003     SPDX-FileCopyrightText: 2006 Darren Gould <darren_gould@gmx.de>
0004     SPDX-FileCopyrightText: 2007-2010 Alvaro Soliverez <asoliverez@gmail.com>
0005     SPDX-FileCopyrightText: 2010-2019 Thomas Baumgart <tbaumgart@kde.org>
0006     SPDX-FileCopyrightText: 2017-2018 Łukasz Wojniłowicz <lukasz.wojnilowicz@gmail.com>
0007     SPDX-FileCopyrightText: 2018 Michael Kiefer <Michael-Kiefer@web.de>
0008     SPDX-License-Identifier: GPL-2.0-or-later
0009 */
0010 
0011 #include "mymoneyreport_p.h"
0012 
0013 // ----------------------------------------------------------------------------
0014 // QT Includes
0015 
0016 #include <QSet>
0017 
0018 // ----------------------------------------------------------------------------
0019 // KDE Includes
0020 
0021 // ----------------------------------------------------------------------------
0022 // Project Includes
0023 
0024 #include "journalmodel.h"
0025 #include "mymoneyaccount.h"
0026 #include "mymoneyexception.h"
0027 #include "mymoneyfile.h"
0028 #include "mymoneymoney.h"
0029 #include "mymoneytransaction.h"
0030 #include "mymoneytransactionfilter.h"
0031 
0032 MyMoneyReport::MyMoneyReport()
0033     : MyMoneyObject(*new MyMoneyReportPrivate(this))
0034 {
0035 }
0036 
0037 MyMoneyReport::MyMoneyReport(const QString& id)
0038     : MyMoneyObject(*new MyMoneyReportPrivate(this), id)
0039 {
0040 }
0041 
0042 MyMoneyReport::MyMoneyReport(eMyMoney::Report::RowType rt,
0043                              unsigned ct,
0044                              eMyMoney::TransactionFilter::Date dl,
0045                              eMyMoney::Report::DetailLevel ss,
0046                              const QString& name,
0047                              const QString& comment)
0048     : MyMoneyObject(*new MyMoneyReportPrivate(this))
0049 {
0050     Q_D(MyMoneyReport);
0051     d->m_name = name;
0052     d->m_comment = comment;
0053     d->m_detailLevel = ss;
0054     d->m_investmentSum = ct & eMyMoney::Report::QueryColumn::CapitalGain ? eMyMoney::Report::InvestmentSum::Sold : eMyMoney::Report::InvestmentSum::Period;
0055     d->m_reportType = d->rowTypeToReportType(rt);
0056     d->m_rowType = rt;
0057     d->m_dateLock = dl;
0058 
0059     //set report type
0060     if (d->m_reportType == eMyMoney::Report::ReportType::PivotTable)
0061         d->m_columnType = static_cast<eMyMoney::Report::ColumnType>(ct);
0062     if (d->m_reportType == eMyMoney::Report::ReportType::QueryTable)
0063         d->m_queryColumns = static_cast<eMyMoney::Report::QueryColumn>(ct);
0064     setDateFilter(dl);
0065 
0066     //throw exception if the type is inconsistent
0067     if (d->rowTypeToReportType(rt) == eMyMoney::Report::ReportType::Invalid ||
0068             d->m_reportType == eMyMoney::Report::ReportType::NoReport)
0069         throw MYMONEYEXCEPTION_CSTRING("Invalid report type");
0070 
0071     //add the corresponding account groups
0072     addAccountGroupsByRowType(rt);
0073     switch(rt) {
0074     case eMyMoney::Report::RowType::AssetLiability:
0075     case eMyMoney::Report::RowType::Account:
0076     case eMyMoney::Report::RowType::ExpenseIncome:
0077         d->m_showRowTotals = true;
0078         break;
0079     default:
0080         break;
0081     }
0082 
0083 #ifdef DEBUG_REPORTS
0084     QDebug out = qDebug();
0085     out << _name << toString(_rt) << toString(m_reportType);
0086     for (const eMyMoney::Account::Type& accountType : m_accountGroups)
0087         out << MyMoneyeMyMoney::Account::accountTypeToString(accountType);
0088     if (m_accounts.size() > 0)
0089         out << m_accounts;
0090 #endif
0091 }
0092 
0093 MyMoneyReport::MyMoneyReport(const MyMoneyReport& other) :
0094     MyMoneyObject(*new MyMoneyReportPrivate(*other.d_func()), other.id()),
0095     MyMoneyTransactionFilter(other)
0096 {
0097 }
0098 
0099 MyMoneyReport::MyMoneyReport(const QString& id, const MyMoneyReport& other) :
0100     MyMoneyObject(*new MyMoneyReportPrivate(*other.d_func()), id),
0101     MyMoneyTransactionFilter(other)
0102 {
0103     Q_D(MyMoneyReport);
0104     d->m_movingAverageDays = 0;
0105     d->m_currentDateColumn = 0;
0106 }
0107 
0108 MyMoneyReport::~MyMoneyReport()
0109 {
0110 }
0111 
0112 void MyMoneyReport::addAccountGroupsByRowType(eMyMoney::Report::RowType rt)
0113 {
0114     //add the corresponding account groups
0115     switch(rt) {
0116     case eMyMoney::Report::RowType::AccountInfo:
0117     case eMyMoney::Report::RowType::AssetLiability:
0118         addAccountGroup(eMyMoney::Account::Type::Asset);
0119         addAccountGroup(eMyMoney::Account::Type::Liability);
0120         break;
0121 
0122     case eMyMoney::Report::RowType::Account:
0123         addAccountGroup(eMyMoney::Account::Type::Asset);
0124         addAccountGroup(eMyMoney::Account::Type::AssetLoan);
0125         addAccountGroup(eMyMoney::Account::Type::Cash);
0126         addAccountGroup(eMyMoney::Account::Type::Checkings);
0127         addAccountGroup(eMyMoney::Account::Type::CreditCard);
0128         if (m_expertMode)
0129             addAccountGroup(eMyMoney::Account::Type::Equity);
0130         addAccountGroup(eMyMoney::Account::Type::Expense);
0131         addAccountGroup(eMyMoney::Account::Type::Income);
0132         addAccountGroup(eMyMoney::Account::Type::Liability);
0133         addAccountGroup(eMyMoney::Account::Type::Loan);
0134         addAccountGroup(eMyMoney::Account::Type::Savings);
0135         addAccountGroup(eMyMoney::Account::Type::Stock);
0136         break;
0137 
0138     case eMyMoney::Report::RowType::ExpenseIncome:
0139         addAccountGroup(eMyMoney::Account::Type::Expense);
0140         addAccountGroup(eMyMoney::Account::Type::Income);
0141         break;
0142 
0143     //FIXME take this out once we have sorted out all issues regarding budget of assets and liabilities -- asoliverez@gmail.com
0144     case eMyMoney::Report::RowType::Budget:
0145     case eMyMoney::Report::RowType::BudgetActual:
0146         addAccountGroup(eMyMoney::Account::Type::Expense);
0147         addAccountGroup(eMyMoney::Account::Type::Income);
0148         break;
0149 
0150     //cash flow reports show splits for all account groups
0151     case eMyMoney::Report::RowType::CashFlow:
0152         addAccountGroup(eMyMoney::Account::Type::Expense);
0153         addAccountGroup(eMyMoney::Account::Type::Income);
0154         addAccountGroup(eMyMoney::Account::Type::Asset);
0155         addAccountGroup(eMyMoney::Account::Type::Liability);
0156         break;
0157     default:
0158         break;
0159     }
0160 }
0161 
0162 eMyMoney::Report::ReportType MyMoneyReport::reportType() const
0163 {
0164     Q_D(const MyMoneyReport);
0165     return d->m_reportType;
0166 }
0167 
0168 void MyMoneyReport::setReportType(eMyMoney::Report::ReportType rt)
0169 {
0170     Q_D(MyMoneyReport);
0171     d->m_reportType = rt;
0172 }
0173 
0174 QString MyMoneyReport::name() const
0175 {
0176     Q_D(const MyMoneyReport);
0177     return d->m_name;
0178 }
0179 
0180 void MyMoneyReport::setName(const QString& s)
0181 {
0182     Q_D(MyMoneyReport);
0183     d->m_name = s;
0184 }
0185 
0186 bool MyMoneyReport::isShowingRowTotals() const
0187 {
0188     Q_D(const MyMoneyReport);
0189     return (d->m_showRowTotals);
0190 }
0191 
0192 void MyMoneyReport::setShowingRowTotals(bool f)
0193 {
0194     Q_D(MyMoneyReport);
0195     d->m_showRowTotals = f;
0196 }
0197 
0198 bool MyMoneyReport::isShowingColumnTotals() const
0199 {
0200     Q_D(const MyMoneyReport);
0201     return d->m_showColumnTotals;
0202 }
0203 
0204 void MyMoneyReport::setShowingColumnTotals(bool f)
0205 {
0206     Q_D(MyMoneyReport);
0207     d->m_showColumnTotals = f;
0208 }
0209 
0210 eMyMoney::Report::RowType MyMoneyReport::rowType() const
0211 {
0212     Q_D(const MyMoneyReport);
0213     return d->m_rowType;
0214 }
0215 
0216 void MyMoneyReport::setRowType(eMyMoney::Report::RowType rt)
0217 {
0218     Q_D(MyMoneyReport);
0219     d->m_rowType = rt;
0220     d->m_reportType = d->rowTypeToReportType(rt);
0221 
0222     d->m_accountGroupFilter = false;
0223     d->m_accountGroups.clear();
0224 
0225     addAccountGroupsByRowType(rt);
0226 }
0227 
0228 bool MyMoneyReport::isRunningSum() const
0229 {
0230     Q_D(const MyMoneyReport);
0231     return (d->m_rowType == eMyMoney::Report::RowType::AssetLiability);
0232 }
0233 
0234 eMyMoney::Report::ColumnType MyMoneyReport::columnType() const
0235 {
0236     Q_D(const MyMoneyReport);
0237     return d->m_columnType;
0238 }
0239 
0240 void MyMoneyReport::setColumnType(eMyMoney::Report::ColumnType ct)
0241 {
0242     Q_D(MyMoneyReport);
0243     d->m_columnType = ct;
0244 }
0245 
0246 bool MyMoneyReport::isConvertCurrency() const
0247 {
0248     Q_D(const MyMoneyReport);
0249     return d->m_convertCurrency;
0250 }
0251 
0252 void MyMoneyReport::setConvertCurrency(bool f)
0253 {
0254     Q_D(MyMoneyReport);
0255     d->m_convertCurrency = f;
0256 }
0257 
0258 uint MyMoneyReport::columnPitch() const
0259 {
0260     Q_D(const MyMoneyReport);
0261     return static_cast<uint>(d->m_columnType);
0262 }
0263 
0264 QString MyMoneyReport::comment() const
0265 {
0266     Q_D(const MyMoneyReport);
0267     return d->m_comment;
0268 }
0269 
0270 void MyMoneyReport::setComment(const QString& comment)
0271 {
0272     Q_D(MyMoneyReport);
0273     d->m_comment = comment;
0274 }
0275 
0276 eMyMoney::Report::QueryColumn MyMoneyReport::queryColumns() const
0277 {
0278     Q_D(const MyMoneyReport);
0279     return d->m_queryColumns;
0280 }
0281 
0282 void MyMoneyReport::setQueryColumns(eMyMoney::Report::QueryColumn qc)
0283 {
0284     Q_D(MyMoneyReport);
0285     d->m_queryColumns = qc;
0286 }
0287 
0288 QString MyMoneyReport::group() const
0289 {
0290     Q_D(const MyMoneyReport);
0291     return d->m_group;
0292 }
0293 
0294 void MyMoneyReport::setGroup(const QString& group)
0295 {
0296     Q_D(MyMoneyReport);
0297     d->m_group = group;
0298 }
0299 
0300 bool MyMoneyReport::isFavorite() const
0301 {
0302     Q_D(const MyMoneyReport);
0303     return d->m_favorite;
0304 }
0305 
0306 void MyMoneyReport::setFavorite(bool f)
0307 {
0308     Q_D(MyMoneyReport);
0309     d->m_favorite = f;
0310 }
0311 
0312 bool MyMoneyReport::isTax() const
0313 {
0314     Q_D(const MyMoneyReport);
0315     return d->m_tax;
0316 }
0317 
0318 void MyMoneyReport::setTax(bool f)
0319 {
0320     Q_D(MyMoneyReport);
0321     d->m_tax = f;
0322 }
0323 
0324 bool MyMoneyReport::isPropagateBudgetDifference() const
0325 {
0326     Q_D(const MyMoneyReport);
0327     return d->m_propagateBudgetDifference;
0328 }
0329 
0330 void MyMoneyReport::setPropagateBudgetDifference(bool f)
0331 {
0332     Q_D(MyMoneyReport);
0333     d->m_propagateBudgetDifference = f;
0334 }
0335 
0336 bool MyMoneyReport::isInvestmentsOnly() const
0337 {
0338     Q_D(const MyMoneyReport);
0339     return d->m_investments;
0340 }
0341 
0342 void MyMoneyReport::setInvestmentsOnly(bool f)
0343 {
0344     Q_D(MyMoneyReport);
0345     d->m_investments = f;
0346     if (f) d->m_loans = false;
0347 }
0348 
0349 bool MyMoneyReport::isLoansOnly() const
0350 {
0351     Q_D(const MyMoneyReport);
0352     return d->m_loans;
0353 }
0354 
0355 void MyMoneyReport::setLoansOnly(bool f)
0356 {
0357     Q_D(MyMoneyReport);
0358     d->m_loans = f;
0359     if (f) d->m_investments = false;
0360 }
0361 
0362 eMyMoney::Report::DetailLevel MyMoneyReport::detailLevel() const
0363 {
0364     Q_D(const MyMoneyReport);
0365     return d->m_detailLevel;
0366 }
0367 
0368 void MyMoneyReport::setDetailLevel(eMyMoney::Report::DetailLevel detail)
0369 {
0370     Q_D(MyMoneyReport);
0371     d->m_detailLevel = detail;
0372 }
0373 
0374 eMyMoney::Report::InvestmentSum MyMoneyReport::investmentSum() const
0375 {
0376     Q_D(const MyMoneyReport);
0377     return d->m_investmentSum;
0378 }
0379 
0380 void MyMoneyReport::setInvestmentSum(eMyMoney::Report::InvestmentSum sum)
0381 {
0382     Q_D(MyMoneyReport);
0383     d->m_investmentSum = sum;
0384 }
0385 
0386 bool MyMoneyReport::isHideTransactions() const
0387 {
0388     Q_D(const MyMoneyReport);
0389     return d->m_hideTransactions;
0390 }
0391 
0392 void MyMoneyReport::setHideTransactions(bool f)
0393 {
0394     Q_D(MyMoneyReport);
0395     d->m_hideTransactions = f;
0396 }
0397 
0398 eMyMoney::Report::ChartType MyMoneyReport::chartType() const
0399 {
0400     Q_D(const MyMoneyReport);
0401     return d->m_chartType;
0402 }
0403 
0404 void MyMoneyReport::setChartType(eMyMoney::Report::ChartType type)
0405 {
0406     Q_D(MyMoneyReport);
0407     d->m_chartType = type;
0408 }
0409 
0410 eMyMoney::Report::ChartPalette MyMoneyReport::chartPalette() const
0411 {
0412     Q_D(const MyMoneyReport);
0413     return d->m_chartPalette;
0414 }
0415 
0416 void MyMoneyReport::setChartPalette(eMyMoney::Report::ChartPalette type)
0417 {
0418     Q_D(MyMoneyReport);
0419     d->m_chartPalette = type;
0420 }
0421 
0422 bool MyMoneyReport::isChartDataLabels() const
0423 {
0424     Q_D(const MyMoneyReport);
0425     return d->m_chartDataLabels;
0426 }
0427 
0428 void MyMoneyReport::setChartDataLabels(bool f)
0429 {
0430     Q_D(MyMoneyReport);
0431     d->m_chartDataLabels = f;
0432 }
0433 
0434 bool MyMoneyReport::isChartCHGridLines() const
0435 {
0436     Q_D(const MyMoneyReport);
0437     return d->m_chartCHGridLines;
0438 }
0439 
0440 void MyMoneyReport::setChartCHGridLines(bool f)
0441 {
0442     Q_D(MyMoneyReport);
0443     d->m_chartCHGridLines = f;
0444 }
0445 
0446 bool MyMoneyReport::isChartSVGridLines() const
0447 {
0448     Q_D(const MyMoneyReport);
0449     return d->m_chartSVGridLines;
0450 }
0451 
0452 void MyMoneyReport::setChartSVGridLines(bool f)
0453 {
0454     Q_D(MyMoneyReport);
0455     d->m_chartSVGridLines = f;
0456 }
0457 
0458 bool MyMoneyReport::isChartByDefault() const
0459 {
0460     Q_D(const MyMoneyReport);
0461     return d->m_chartByDefault;
0462 }
0463 
0464 void MyMoneyReport::setChartByDefault(bool f)
0465 {
0466     Q_D(MyMoneyReport);
0467     d->m_chartByDefault = f;
0468 }
0469 
0470 uint MyMoneyReport::chartLineWidth() const
0471 {
0472     Q_D(const MyMoneyReport);
0473     return d->m_chartLineWidth;
0474 }
0475 
0476 void MyMoneyReport::setChartLineWidth(uint f)
0477 {
0478     Q_D(MyMoneyReport);
0479     d->m_chartLineWidth = f;
0480 }
0481 
0482 bool MyMoneyReport::isLogYAxis() const
0483 {
0484     Q_D(const MyMoneyReport);
0485     return d->m_logYaxis;
0486 }
0487 
0488 void MyMoneyReport::setLogYAxis(bool f)
0489 {
0490     Q_D(MyMoneyReport);
0491     d->m_logYaxis = f;
0492 }
0493 
0494 bool MyMoneyReport::isNegExpenses() const
0495 {
0496     Q_D(const MyMoneyReport);
0497     return d->m_negExpenses;
0498 }
0499 
0500 void MyMoneyReport::setNegExpenses(bool f)
0501 {
0502     Q_D(MyMoneyReport);
0503     d->m_negExpenses = f;
0504 }
0505 
0506 QString MyMoneyReport::dataRangeStart() const
0507 {
0508     Q_D(const MyMoneyReport);
0509     return d->m_dataRangeStart;
0510 }
0511 
0512 void MyMoneyReport::setDataRangeStart(const QString& f)
0513 {
0514     Q_D(MyMoneyReport);
0515     d->m_dataRangeStart = f;
0516 }
0517 
0518 QString MyMoneyReport::dataRangeEnd() const
0519 {
0520     Q_D(const MyMoneyReport);
0521     return d->m_dataRangeEnd;
0522 }
0523 
0524 void MyMoneyReport::setDataRangeEnd(const QString& f)
0525 {
0526     Q_D(MyMoneyReport);
0527     d->m_dataRangeEnd = f;
0528 }
0529 
0530 QString MyMoneyReport::dataMajorTick() const
0531 {
0532     Q_D(const MyMoneyReport);
0533     return d->m_dataMajorTick;
0534 }
0535 
0536 void MyMoneyReport::setDataMajorTick(const QString& f)
0537 {
0538     Q_D(MyMoneyReport);
0539     d->m_dataMajorTick = f;
0540 }
0541 
0542 QString MyMoneyReport::dataMinorTick() const
0543 {
0544     Q_D(const MyMoneyReport);
0545     return d->m_dataMinorTick;
0546 }
0547 
0548 void MyMoneyReport::setDataMinorTick(const QString& f)
0549 {
0550     Q_D(MyMoneyReport);
0551     d->m_dataMinorTick = f;
0552 }
0553 
0554 uint MyMoneyReport::yLabelsPrecision() const
0555 {
0556     Q_D(const MyMoneyReport);
0557     return d->m_yLabelsPrecision;
0558 }
0559 
0560 void MyMoneyReport::setYLabelsPrecision(int f)
0561 {
0562     Q_D(MyMoneyReport);
0563     d->m_yLabelsPrecision = f;
0564 }
0565 
0566 bool MyMoneyReport::isIncludingSchedules() const
0567 {
0568     Q_D(const MyMoneyReport);
0569     return d->m_includeSchedules;
0570 }
0571 
0572 void MyMoneyReport::setIncludingSchedules(bool f)
0573 {
0574     Q_D(MyMoneyReport);
0575     d->m_includeSchedules = f;
0576 }
0577 
0578 bool MyMoneyReport::isColumnsAreDays() const
0579 {
0580     Q_D(const MyMoneyReport);
0581     return d->m_columnsAreDays;
0582 }
0583 
0584 void MyMoneyReport::setColumnsAreDays(bool f)
0585 {
0586     Q_D(MyMoneyReport);
0587     d->m_columnsAreDays = f;
0588 }
0589 
0590 bool MyMoneyReport::isIncludingTransfers() const
0591 {
0592     Q_D(const MyMoneyReport);
0593     return d->m_includeTransfers;
0594 }
0595 
0596 void MyMoneyReport::setIncludingTransfers(bool f)
0597 {
0598     Q_D(MyMoneyReport);
0599     d->m_includeTransfers = f;
0600 }
0601 
0602 bool MyMoneyReport::isIncludingUnusedAccounts() const
0603 {
0604     Q_D(const MyMoneyReport);
0605     return d->m_includeUnusedAccounts;
0606 }
0607 
0608 void MyMoneyReport::setIncludingUnusedAccounts(bool f)
0609 {
0610     Q_D(MyMoneyReport);
0611     d->m_includeUnusedAccounts = f;
0612 }
0613 
0614 bool MyMoneyReport::hasBudget() const
0615 {
0616     Q_D(const MyMoneyReport);
0617     return !d->m_budgetId.isEmpty();
0618 }
0619 
0620 QString MyMoneyReport::budget() const
0621 {
0622     Q_D(const MyMoneyReport);
0623     return d->m_budgetId;
0624 }
0625 
0626 /**
0627   * Sets the budget used for this report
0628   *
0629   * @param budget The ID of the budget to use, or an empty string
0630   * to indicate a budget is NOT included
0631   * @param fa Whether to display actual data alongside the budget.
0632   * Setting to false means the report displays ONLY the budget itself.
0633   * @warning For now, the budget ID is ignored.  The budget id is
0634   * simply checked for any non-empty string, and if so, hasBudget()
0635   * will return true.
0636   */
0637 void MyMoneyReport::setBudget(const QString& budget, bool fa)
0638 {
0639     Q_D(MyMoneyReport);
0640     d->m_budgetId = budget;
0641     d->m_includeBudgetActuals = fa;
0642 }
0643 
0644 bool MyMoneyReport::isIncludingBudgetActuals() const
0645 {
0646     Q_D(const MyMoneyReport);
0647     return d->m_includeBudgetActuals;
0648 }
0649 
0650 void MyMoneyReport::setIncludingBudgetActuals(bool f)
0651 {
0652     Q_D(MyMoneyReport);
0653     d->m_includeBudgetActuals = f;
0654 }
0655 
0656 bool MyMoneyReport::isIncludingForecast() const
0657 {
0658     Q_D(const MyMoneyReport);
0659     return d->m_includeForecast;
0660 }
0661 
0662 void MyMoneyReport::setIncludingForecast(bool f)
0663 {
0664     Q_D(MyMoneyReport);
0665     d->m_includeForecast = f;
0666 }
0667 
0668 bool MyMoneyReport::isIncludingMovingAverage() const
0669 {
0670     Q_D(const MyMoneyReport);
0671     return d->m_includeMovingAverage;
0672 }
0673 
0674 void MyMoneyReport::setIncludingMovingAverage(bool f)
0675 {
0676     Q_D(MyMoneyReport);
0677     d->m_includeMovingAverage = f;
0678 }
0679 
0680 int MyMoneyReport::movingAverageDays() const
0681 {
0682     Q_D(const MyMoneyReport);
0683     return d->m_movingAverageDays;
0684 }
0685 
0686 void MyMoneyReport::setMovingAverageDays(int days)
0687 {
0688     Q_D(MyMoneyReport);
0689     d->m_movingAverageDays = days;
0690 }
0691 
0692 bool MyMoneyReport::isIncludingPrice() const
0693 {
0694     Q_D(const MyMoneyReport);
0695     return d->m_includePrice;
0696 }
0697 
0698 void MyMoneyReport::setIncludingPrice(bool f)
0699 {
0700     Q_D(MyMoneyReport);
0701     d->m_includePrice = f;
0702 }
0703 
0704 bool MyMoneyReport::isIncludingAveragePrice() const
0705 {
0706     Q_D(const MyMoneyReport);
0707     return d->m_includeAveragePrice;
0708 }
0709 
0710 void MyMoneyReport::setIncludingAveragePrice(bool f)
0711 {
0712     Q_D(MyMoneyReport);
0713     d->m_includeAveragePrice = f;
0714 }
0715 
0716 eMyMoney::Report::DataLock MyMoneyReport::dataFilter() const
0717 {
0718     Q_D(const MyMoneyReport);
0719     return d->m_dataLock;
0720 }
0721 
0722 bool MyMoneyReport::isDataUserDefined() const
0723 {
0724     Q_D(const MyMoneyReport);
0725     return d->m_dataLock == eMyMoney::Report::DataLock::UserDefined;
0726 }
0727 
0728 void MyMoneyReport::setDataFilter(eMyMoney::Report::DataLock u)
0729 {
0730     Q_D(MyMoneyReport);
0731     d->m_dataLock = u;
0732 }
0733 
0734 eMyMoney::TransactionFilter::Date MyMoneyReport::dateRange() const
0735 {
0736     Q_D(const MyMoneyReport);
0737     return d->m_dateLock;
0738 }
0739 
0740 bool MyMoneyReport::isDateUserDefined() const
0741 {
0742     Q_D(const MyMoneyReport);
0743     return d->m_dateLock == eMyMoney::TransactionFilter::Date::UserDefined;
0744 }
0745 
0746 /**
0747   * Set the underlying date filter and LOCK that filter to the specified
0748   * range.  For example, if @p _u is "CurrentMonth", this report should always
0749   * be updated to the current month no matter when the report is run.
0750   *
0751   * This updating is not entirely automatic, you should update it yourself by
0752   * calling updateDateFilter.
0753   *
0754   * @param _u The date range constant (MyMoneyTransactionFilter::dateRangeE)
0755   *          which this report should be locked to.
0756   */
0757 
0758 void MyMoneyReport::setDateFilter(eMyMoney::TransactionFilter::Date u)
0759 {
0760     Q_D(MyMoneyReport);
0761     d->m_dateLock = u;
0762     if (u != eMyMoney::TransactionFilter::Date::UserDefined)
0763         MyMoneyTransactionFilter::setDateFilter(u);
0764 }
0765 
0766 void MyMoneyReport::setDateFilter(const QDate& db, const QDate& de)
0767 {
0768     MyMoneyTransactionFilter::setDateFilter(db, de);
0769 }
0770 
0771 void MyMoneyReport::updateDateFilter()
0772 {
0773     Q_D(MyMoneyReport);
0774     if (d->m_dateLock != eMyMoney::TransactionFilter::Date::UserDefined) {
0775         MyMoneyTransactionFilter::setDateFilter(d->m_dateLock);
0776     }
0777 }
0778 
0779 
0780 bool MyMoneyReport::isMixedTime() const
0781 {
0782     Q_D(const MyMoneyReport);
0783     return d->m_mixedTime;
0784 }
0785 
0786 void MyMoneyReport::setMixedTime(bool f)
0787 {
0788     Q_D(MyMoneyReport);
0789     d->m_mixedTime = f;
0790 }
0791 
0792 int MyMoneyReport::currentDateColumn() const
0793 {
0794     Q_D(const MyMoneyReport);
0795     return d->m_currentDateColumn;
0796 }
0797 
0798 void MyMoneyReport::setCurrentDateColumn(int f)
0799 {
0800     Q_D(MyMoneyReport);
0801     d->m_currentDateColumn = f;
0802 }
0803 
0804 uint MyMoneyReport::settlementPeriod() const
0805 {
0806     Q_D(const MyMoneyReport);
0807     return d->m_settlementPeriod;
0808 }
0809 
0810 void MyMoneyReport::setSettlementPeriod(uint days)
0811 {
0812     Q_D(MyMoneyReport);
0813     d->m_settlementPeriod = days;
0814 }
0815 
0816 bool MyMoneyReport::isShowingSTLTCapitalGains() const
0817 {
0818     Q_D(const MyMoneyReport);
0819     return d->m_showSTLTCapitalGains;
0820 }
0821 
0822 void MyMoneyReport::setShowSTLTCapitalGains(bool f)
0823 {
0824     Q_D(MyMoneyReport);
0825     d->m_showSTLTCapitalGains = f;
0826 }
0827 
0828 QDate MyMoneyReport::termSeparator() const
0829 {
0830     Q_D(const MyMoneyReport);
0831     return d->m_tseparator;
0832 }
0833 
0834 void MyMoneyReport::setTermSeparator(const QDate& date)
0835 {
0836     Q_D(MyMoneyReport);
0837     d->m_tseparator = date;
0838 }
0839 
0840 bool MyMoneyReport::isSkippingZero() const
0841 {
0842     Q_D(const MyMoneyReport);
0843     return d->m_skipZero;
0844 }
0845 
0846 void MyMoneyReport::setSkipZero(int f)
0847 {
0848     Q_D(MyMoneyReport);
0849     d->m_skipZero = f;
0850 }
0851 
0852 void MyMoneyReport::clearTransactionFilter()
0853 {
0854     Q_D(MyMoneyReport);
0855     d->m_accountGroupFilter = false;
0856     d->m_accountGroups.clear();
0857 
0858     MyMoneyTransactionFilter::clear();
0859 }
0860 
0861 void MyMoneyReport::assignFilter(const MyMoneyTransactionFilter& filter)
0862 {
0863     MyMoneyTransactionFilter::operator=(filter);
0864 }
0865 
0866 void MyMoneyReport::validDateRange(QDate& db, QDate& de)
0867 {
0868     db = fromDate();
0869     de = toDate();
0870 
0871     // if either begin or end date are invalid we have one of the following
0872     // possible date filters:
0873     //
0874     // a) begin date not set - first transaction until given end date
0875     // b) end date not set   - from given date until last transaction
0876     // c) both not set       - first transaction until last transaction
0877     //
0878     // If there is no transaction in the engine at all, we use the current
0879     // year as the filter criteria.
0880 
0881     if (!db.isValid() || !de.isValid()) {
0882         const auto dateRange = MyMoneyFile::instance()->journalModel()->dateRange();
0883         auto tmpBegin = dateRange.firstTransaction;
0884         auto tmpEnd = dateRange.lastTransaction;
0885 
0886         // make sure that we leave this function with valid dates no matter what
0887         if (!tmpBegin.isValid() || !tmpEnd.isValid() || tmpBegin > tmpEnd) {
0888             tmpBegin = QDate(QDate::currentDate().year(), 1, 1);   // the first date in the file
0889             tmpEnd = QDate(QDate::currentDate().year(), 12, 31);   // the last date in the file
0890         }
0891         if (!db.isValid())
0892             db = tmpBegin;
0893         if (!de.isValid())
0894             de = tmpEnd;
0895     }
0896     if (db > de)
0897         db = de;
0898 }
0899 
0900 bool MyMoneyReport::accountGroups(QList<eMyMoney::Account::Type>& list) const
0901 {
0902     Q_D(const MyMoneyReport);
0903     bool result = d->m_accountGroupFilter;
0904 
0905     if (result) {
0906         QList<eMyMoney::Account::Type>::const_iterator it_group = d->m_accountGroups.begin();
0907         while (it_group != d->m_accountGroups.end()) {
0908             list += (*it_group);
0909             ++it_group;
0910         }
0911     }
0912     return result;
0913 }
0914 
0915 void MyMoneyReport::addAccountGroup(eMyMoney::Account::Type type)
0916 {
0917     Q_D(MyMoneyReport);
0918     if (!d->m_accountGroups.isEmpty() && type != eMyMoney::Account::Type::Unknown) {
0919         if (d->m_accountGroups.contains(type))
0920             return;
0921     }
0922     d->m_accountGroupFilter = true;
0923     if (type != eMyMoney::Account::Type::Unknown)
0924         d->m_accountGroups.push_back(type);
0925 }
0926 
0927 bool MyMoneyReport::includesAccountGroup(eMyMoney::Account::Type type) const
0928 {
0929     Q_D(const MyMoneyReport);
0930     bool result = (! d->m_accountGroupFilter)
0931                   || (isIncludingTransfers() && d->m_rowType == eMyMoney::Report::RowType::ExpenseIncome)
0932                   || d->m_accountGroups.contains(type);
0933 
0934     return result;
0935 }
0936 
0937 bool MyMoneyReport::includes(const MyMoneyAccount& acc) const
0938 {
0939     Q_D(const MyMoneyReport);
0940     auto result = false;
0941 
0942     if (includesAccountGroup(acc.accountGroup())) {
0943         switch (acc.accountGroup()) {
0944         case eMyMoney::Account::Type::Income:
0945         case eMyMoney::Account::Type::Expense:
0946             if (isTax())
0947                 result = acc.isInTaxReports() && includesCategory(acc.id());
0948             else
0949                 result = includesCategory(acc.id());
0950             break;
0951         case eMyMoney::Account::Type::Asset:
0952         case eMyMoney::Account::Type::Liability:
0953             if (isLoansOnly())
0954                 result = acc.isLoan() && includesAccount(acc.id());
0955             else if (isInvestmentsOnly())
0956                 result = acc.isInvest() && includesAccount(acc.id());
0957             else if (isIncludingTransfers() && d->m_rowType == eMyMoney::Report::RowType::ExpenseIncome)
0958                 // If transfers are included, ONLY include this account if it is NOT
0959                 // included in the report itself!!
0960                 result = ! includesAccount(acc.id());
0961             else
0962                 result = includesAccount(acc.id());
0963             break;
0964         case eMyMoney::Account::Type::Equity:
0965             if (isInvestmentsOnly())
0966                 result = (isIncludingPrice() || isIncludingAveragePrice()) && acc.isInvest() && includesAccount(acc.id());
0967             break;
0968         default:
0969             result = includesAccount(acc.id());
0970         }
0971     }
0972     return result;
0973 }
0974 
0975 int MyMoneyReport::m_lineWidth = 2;
0976 bool MyMoneyReport::m_expertMode = false;
0977 
0978 void MyMoneyReport::setLineWidth(int width)
0979 {
0980     m_lineWidth = width;
0981 }
0982 
0983 int MyMoneyReport::lineWidth()
0984 {
0985     return m_lineWidth;
0986 }
0987 
0988 void MyMoneyReport::setExpertMode(bool expertMode)
0989 {
0990     m_expertMode = expertMode;
0991 }
0992 
0993 QString MyMoneyReport::toString(eMyMoney::Report::RowType type)
0994 {
0995     switch(type) {
0996     case eMyMoney::Report::RowType::NoRows             :
0997         return "eMyMoney::Report::RowType::NoRows";
0998     case eMyMoney::Report::RowType::AssetLiability     :
0999         return "eMyMoney::Report::RowType::AssetLiability";
1000     case eMyMoney::Report::RowType::ExpenseIncome      :
1001         return "eMyMoney::Report::RowType::ExpenseIncome";
1002     case eMyMoney::Report::RowType::Category           :
1003         return "eMyMoney::Report::RowType::Category";
1004     case eMyMoney::Report::RowType::TopCategory        :
1005         return "eTopCategory";
1006     case eMyMoney::Report::RowType::Account            :
1007         return "eAccount";
1008     case eMyMoney::Report::RowType::Tag                :
1009         return "eTag";
1010     case eMyMoney::Report::RowType::Payee              :
1011         return "ePayee";
1012     case eMyMoney::Report::RowType::Month              :
1013         return "eMonth";
1014     case eMyMoney::Report::RowType::Week               :
1015         return "eWeek";
1016     case eMyMoney::Report::RowType::TopAccount         :
1017         return "eTopAccount";
1018     case eMyMoney::Report::RowType::AccountByTopAccount:
1019         return "eAccountByTopAccount";
1020     case eMyMoney::Report::RowType::EquityType         :
1021         return "eEquityType";
1022     case eMyMoney::Report::RowType::AccountType        :
1023         return "eAccountType";
1024     case eMyMoney::Report::RowType::Institution        :
1025         return "eInstitution";
1026     case eMyMoney::Report::RowType::Budget             :
1027         return "eBudget";
1028     case eMyMoney::Report::RowType::BudgetActual       :
1029         return "eBudgetActual";
1030     case eMyMoney::Report::RowType::Schedule           :
1031         return "eSchedule";
1032     case eMyMoney::Report::RowType::AccountInfo        :
1033         return "eAccountInfo";
1034     case eMyMoney::Report::RowType::AccountLoanInfo    :
1035         return "eAccountLoanInfo";
1036     case eMyMoney::Report::RowType::AccountReconcile   :
1037         return "eAccountReconcile";
1038     case eMyMoney::Report::RowType::CashFlow           :
1039         return "eCashFlow";
1040     default                  :
1041         return "undefined";
1042     }
1043 }
1044 
1045 QString MyMoneyReport::toString(eMyMoney::Report::ReportType type)
1046 {
1047     switch(type) {
1048     case eMyMoney::Report::ReportType::NoReport:
1049         return "eNoReport";
1050     case eMyMoney::Report::ReportType::PivotTable:
1051         return "ePivotTable";
1052     case eMyMoney::Report::ReportType::QueryTable:
1053         return "eQueryTable";
1054     case eMyMoney::Report::ReportType::InfoTable:
1055         return "eInfoTable";
1056     default:
1057         return "undefined";
1058     }
1059 }