diff --git a/kmymoney/dialogs/kreportconfigurationfilterdlg.cpp b/kmymoney/dialogs/kreportconfigurationfilterdlg.cpp index 2b4e70046..5a7ba1200 100644 --- a/kmymoney/dialogs/kreportconfigurationfilterdlg.cpp +++ b/kmymoney/dialogs/kreportconfigurationfilterdlg.cpp @@ -1,710 +1,714 @@ /*************************************************************************** kreportconfigurationdlg.cpp - description ------------------- begin : Mon Jun 21 2004 copyright : (C) 2000-2004 by Michael Edwardes email : mte@users.sourceforge.net Javier Campos Morales Felix Rodriguez John C Thomas Baumgart Kevin Tambascio Ace Jones ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "kreportconfigurationfilterdlg.h" // ---------------------------------------------------------------------------- // QT Includes #include #include #include #include #include #include #include #include #include #include #include #include // ---------------------------------------------------------------------------- // KDE Includes #include #include #include #include #include #include // ---------------------------------------------------------------------------- // Project Includes #include #include #include #include #include #include #include #include "ui_kfindtransactiondlgdecl.h" #include "ui_daterangedlgdecl.h" #include "ui_kmymoneyreportconfigtabrangedecl.h" KReportConfigurationFilterDlg::KReportConfigurationFilterDlg( MyMoneyReport report, QWidget *parent) : KFindTransactionDlg(parent), m_tab2(0), m_tab3(0), m_tabChart(0), m_tabRange(0), m_initialState(report), m_currentState(report) { // // Rework labeling // setWindowTitle(i18n("Report Configuration")); delete m_ui->TextLabel1; // // Rework the buttons // // the Apply button is always enabled disconnect(SIGNAL(selectionNotEmpty(bool))); m_ui->buttonBox->button(QDialogButtonBox::Apply)->setEnabled(true); KGuiItem::assign(m_ui->buttonBox->button(QDialogButtonBox::Apply), KStandardGuiItem::ok()); m_ui->buttonBox->button(QDialogButtonBox::Apply)->setToolTip(i18nc("@info:tooltip for report configuration apply button", "Apply the configuration changes to the report")); // // Add new tabs // m_tab1 = new kMyMoneyReportConfigTab1Decl(m_ui->m_criteriaTab); m_tab1->setObjectName("kMyMoneyReportConfigTab1"); m_ui->m_criteriaTab->insertTab(0, m_tab1, i18n("Report")); if (m_initialState.reportType() == MyMoneyReport::ePivotTable) { m_tab2 = new kMyMoneyReportConfigTab2Decl(m_ui->m_criteriaTab); m_tab2->setObjectName("kMyMoneyReportConfigTab2"); m_ui->m_criteriaTab->insertTab(1, m_tab2, i18n("Rows/Columns")); connect(m_tab2->findChild("m_comboRows"), SIGNAL(activated(int)), this, SLOT(slotRowTypeChanged(int))); connect(m_tab2->findChild("m_comboRows"), SIGNAL(activated(int)), this, SLOT(slotUpdateColumnsCombo())); //control the state of the includeTransfer check connect(m_ui->m_categoriesView, SIGNAL(stateChanged()), this, SLOT(slotUpdateCheckTransfers())); m_tabChart = new kMyMoneyReportConfigTabChartDecl(m_ui->m_criteriaTab); m_tabChart->setObjectName("kMyMoneyReportConfigTabChart"); m_ui->m_criteriaTab->insertTab(2, m_tabChart, i18n("Chart")); m_tabRange = new kMyMoneyReportConfigTabRangeDecl(m_ui->m_criteriaTab); m_tabRange->setObjectName("kMyMoneyReportConfigTabRange"); m_ui->m_criteriaTab->insertTab(3, m_tabRange, i18n("Range")); // date tab is going to be replaced by range tab, so delete it m_ui->dateRangeLayout->removeWidget(m_dateRange); m_dateRange->deleteLater(); m_ui->m_criteriaTab->removeTab(m_ui->m_criteriaTab->indexOf(m_ui->m_dateTab)); m_ui->m_dateTab->deleteLater(); m_dateRange = m_tabRange->m_dateRange; connect(m_tabRange->ui->m_comboColumns, SIGNAL(activated(int)), this, SLOT(slotColumnTypeChanged(int))); connect(m_tabRange->ui->m_comboColumns, SIGNAL(activated(int)), this, SLOT(slotUpdateColumnsCombo())); connect(m_tabChart->findChild("m_logYaxis"), SIGNAL(stateChanged(int)), this, SLOT(slotLogAxisChanged(int))); } else if (m_initialState.reportType() == MyMoneyReport::eQueryTable) { // eInvestmentHoldings is a special-case report, and you cannot configure the // rows & columns of that report. if (m_initialState.rowType() < MyMoneyReport::eAccountByTopAccount) { m_tab3 = new kMyMoneyReportConfigTab3Decl(m_ui->m_criteriaTab); m_tab3->setObjectName("kMyMoneyReportConfigTab3"); m_ui->m_criteriaTab->insertTab(1, m_tab3, i18n("Rows/Columns")); } } m_ui->m_criteriaTab->setCurrentIndex(m_ui->m_criteriaTab->indexOf(m_tab1)); m_ui->m_criteriaTab->setMinimumSize(500, 200); QList list = MyMoneyFile::instance()->budgetList(); QList::const_iterator it_b; for (it_b = list.constBegin(); it_b != list.constEnd(); ++it_b) { m_budgets.push_back(*it_b); } // // Now set up the widgets with proper values // slotReset(); } KReportConfigurationFilterDlg::~KReportConfigurationFilterDlg() { } void KReportConfigurationFilterDlg::slotSearch() { // setup the filter from the dialog widgets setupFilter(); // Copy the m_filter over to the filter part of m_currentConfig. m_currentState.assignFilter(m_filter); // Then extract the report properties m_currentState.setName(m_tab1->findChild("m_editName")->text()); m_currentState.setComment(m_tab1->findChild("m_editComment")->text()); m_currentState.setConvertCurrency(m_tab1->findChild("m_checkCurrency")->isChecked()); m_currentState.setFavorite(m_tab1->findChild("m_checkFavorite")->isChecked()); m_currentState.setSkipZero(m_tab1->findChild("m_skipZero")->isChecked()); if (m_tab2) { MyMoneyReport::EDetailLevel dl[4] = { MyMoneyReport::eDetailAll, MyMoneyReport::eDetailTop, MyMoneyReport::eDetailGroup, MyMoneyReport::eDetailTotal }; m_currentState.setDetailLevel(dl[m_tab2->findChild("m_comboDetail")->currentIndex()]); // modify the rowtype only if the widget is enabled if (m_tab2->findChild("m_comboRows")->isEnabled()) { MyMoneyReport::ERowType rt[2] = { MyMoneyReport::eExpenseIncome, MyMoneyReport::eAssetLiability }; m_currentState.setRowType(rt[m_tab2->findChild("m_comboRows")->currentIndex()]); } m_currentState.setShowingRowTotals(false); if (m_tab2->findChild("m_comboRows")->currentIndex() == 0) m_currentState.setShowingRowTotals(m_tab2->findChild("m_checkTotalColumn")->isChecked()); m_currentState.setIncludingSchedules(m_tab2->findChild("m_checkScheduled")->isChecked()); m_currentState.setIncludingTransfers(m_tab2->findChild("m_checkTransfers")->isChecked()); m_currentState.setIncludingUnusedAccounts(m_tab2->findChild("m_checkUnused")->isChecked()); if (m_tab2->findChild("m_comboBudget")->isEnabled()) { m_currentState.setBudget(m_budgets[m_tab2->findChild("m_comboBudget")->currentItem()].id(), m_initialState.rowType() == MyMoneyReport::eBudgetActual); } else { m_currentState.setBudget(QString(), false); } //set moving average days if (m_tab2->findChild("m_movingAverageDays")->isEnabled()) { m_currentState.setMovingAverageDays(m_tab2->findChild("m_movingAverageDays")->value()); } } else if (m_tab3) { MyMoneyReport::ERowType rtq[8] = { MyMoneyReport::eCategory, MyMoneyReport::eTopCategory, MyMoneyReport::eTag, MyMoneyReport::ePayee, MyMoneyReport::eAccount, MyMoneyReport::eTopAccount, MyMoneyReport::eMonth, MyMoneyReport::eWeek }; m_currentState.setRowType(rtq[m_tab3->findChild("m_comboOrganizeBy")->currentIndex()]); unsigned qc = MyMoneyReport::eQCnone; if (m_currentState.queryColumns() & MyMoneyReport::eQCloan) // once a loan report, always a loan report qc = MyMoneyReport::eQCloan; if (m_tab3->findChild("m_checkNumber")->isChecked()) qc |= MyMoneyReport::eQCnumber; if (m_tab3->findChild("m_checkPayee")->isChecked()) qc |= MyMoneyReport::eQCpayee; if (m_tab3->findChild("m_checkTag")->isChecked()) qc |= MyMoneyReport::eQCtag; if (m_tab3->findChild("m_checkCategory")->isChecked()) qc |= MyMoneyReport::eQCcategory; if (m_tab3->findChild("m_checkMemo")->isChecked()) qc |= MyMoneyReport::eQCmemo; if (m_tab3->findChild("m_checkAccount")->isChecked()) qc |= MyMoneyReport::eQCaccount; if (m_tab3->findChild("m_checkReconciled")->isChecked()) qc |= MyMoneyReport::eQCreconciled; if (m_tab3->findChild("m_checkAction")->isChecked()) qc |= MyMoneyReport::eQCaction; if (m_tab3->findChild("m_checkShares")->isChecked()) qc |= MyMoneyReport::eQCshares; if (m_tab3->findChild("m_checkPrice")->isChecked()) qc |= MyMoneyReport::eQCprice; if (m_tab3->findChild("m_checkBalance")->isChecked()) qc |= MyMoneyReport::eQCbalance; m_currentState.setQueryColumns(static_cast(qc)); m_currentState.setTax(m_tab3->findChild("m_checkTax")->isChecked()); m_currentState.setInvestmentsOnly(m_tab3->findChild("m_checkInvestments")->isChecked()); m_currentState.setLoansOnly(m_tab3->findChild("m_checkLoans")->isChecked()); m_currentState.setDetailLevel(m_tab3->findChild("m_checkHideSplitDetails")->isChecked() ? MyMoneyReport::eDetailNone : MyMoneyReport::eDetailAll); + m_currentState.setHideTransactions(m_tab3->findChild("m_checkHideTransactions")->isChecked()); } if (m_tabChart) { MyMoneyReport::EChartType ct[5] = { MyMoneyReport::eChartLine, MyMoneyReport::eChartBar, MyMoneyReport::eChartStackedBar, MyMoneyReport::eChartPie, MyMoneyReport::eChartRing }; m_currentState.setChartType(ct[m_tabChart->findChild("m_comboType")->currentIndex()]); m_currentState.setChartCHGridLines(m_tabChart->findChild("m_checkCHGridLines")->isChecked()); m_currentState.setChartSVGridLines(m_tabChart->findChild("m_checkSVGridLines")->isChecked()); m_currentState.setChartDataLabels(m_tabChart->findChild("m_checkValues")->isChecked()); m_currentState.setChartByDefault(m_tabChart->findChild("m_checkShowChart")->isChecked()); m_currentState.setChartLineWidth(m_tabChart->findChild("m_lineWidth")->value()); m_currentState.setLogYAxis(m_tabChart->findChild("m_logYaxis")->isChecked()); } if (m_tabRange) { m_currentState.setDataRangeStart(m_tabRange->ui->m_dataRangeStart->text()); m_currentState.setDataRangeEnd(m_tabRange->ui->m_dataRangeEnd->text()); m_currentState.setDataMajorTick(m_tabRange->ui->m_dataMajorTick->text()); m_currentState.setDataMinorTick(m_tabRange->ui->m_dataMinorTick->text()); m_currentState.setDataFilter((MyMoneyReport::dataOptionE)m_tabRange->ui->m_dataLock->currentIndex()); MyMoneyReport::EColumnType ct[6] = { MyMoneyReport::eDays, MyMoneyReport::eWeeks, MyMoneyReport::eMonths, MyMoneyReport::eBiMonths, MyMoneyReport::eQuarters, MyMoneyReport::eYears }; bool dy[6] = { true, true, false, false, false, false }; m_currentState.setColumnType(ct[m_tabRange->ui->m_comboColumns->currentIndex()]); //TODO (Ace) This should be implicit in the call above. MMReport needs fixin' m_currentState.setColumnsAreDays(dy[m_tabRange->ui->m_comboColumns->currentIndex()]); } // setup the date lock MyMoneyTransactionFilter::dateOptionE range = m_dateRange->m_ui->m_dateRange->currentItem(); m_currentState.setDateFilter(range); done(true); } void KReportConfigurationFilterDlg::slotRowTypeChanged(int row) { m_tab2->findChild("m_checkTotalColumn")->setEnabled(row == 0); } void KReportConfigurationFilterDlg::slotColumnTypeChanged(int row) { if ((m_tab2->findChild("m_comboBudget")->isEnabled() && row < 2)) { m_tabRange->ui->m_comboColumns->setCurrentItem(i18nc("@item the columns will display monthly data", "Monthly"), false); } } void KReportConfigurationFilterDlg::slotUpdateColumnsCombo() { const int monthlyIndex = 2; const int incomeExpenseIndex = 0; const bool isIncomeExpenseForecast = m_currentState.isIncludingForecast() && m_tab2->findChild("m_comboRows")->currentIndex() == incomeExpenseIndex; if (isIncomeExpenseForecast && m_tabRange->ui->m_comboColumns->currentIndex() != monthlyIndex) { m_tabRange->ui->m_comboColumns->setCurrentItem(i18nc("@item the columns will display monthly data", "Monthly"), false); } } void KReportConfigurationFilterDlg::slotLogAxisChanged(int state) { if (state == Qt::Checked) m_tabRange->setRangeLogarythmic(true); else m_tabRange->setRangeLogarythmic(false); } void KReportConfigurationFilterDlg::slotReset() { // // Set up the widget from the initial filter // m_currentState = m_initialState; // // Report Properties // m_tab1->findChild("m_editName")->setText(m_initialState.name()); m_tab1->findChild("m_editComment")->setText(m_initialState.comment()); m_tab1->findChild("m_checkCurrency")->setChecked(m_initialState.isConvertCurrency()); m_tab1->findChild("m_checkFavorite")->setChecked(m_initialState.isFavorite()); if (m_initialState.isIncludingPrice() || m_initialState.isSkippingZero()) { m_tab1->findChild("m_skipZero")->setChecked(m_initialState.isSkippingZero()); } else { m_tab1->findChild("m_skipZero")->setEnabled(false); } if (m_tab2) { KComboBox *combo = m_tab2->findChild("m_comboDetail"); switch (m_initialState.detailLevel()) { case MyMoneyReport::eDetailNone: case MyMoneyReport::eDetailEnd: case MyMoneyReport::eDetailAll: combo->setCurrentItem(i18nc("All accounts", "All"), false); break; case MyMoneyReport::eDetailTop: combo->setCurrentItem(i18n("Top-Level"), false); break; case MyMoneyReport::eDetailGroup: combo->setCurrentItem(i18n("Groups"), false); break; case MyMoneyReport::eDetailTotal: combo->setCurrentItem(i18n("Totals"), false); break; } combo = m_tab2->findChild("m_comboRows"); switch (m_initialState.rowType()) { case MyMoneyReport::eExpenseIncome: case MyMoneyReport::eBudget: case MyMoneyReport::eBudgetActual: combo->setCurrentItem(i18n("Income & Expenses"), false); // income / expense break; default: combo->setCurrentItem(i18n("Assets & Liabilities"), false); // asset / liability break; } m_tab2->findChild("m_checkTotalColumn")->setChecked(m_initialState.isShowingRowTotals()); slotRowTypeChanged(combo->currentIndex()); //load budgets combo if (m_initialState.rowType() == MyMoneyReport::eBudget || m_initialState.rowType() == MyMoneyReport::eBudgetActual) { m_tab2->findChild("m_comboRows")->setEnabled(false); m_tab2->findChild("m_budgetFrame")->setEnabled(!m_budgets.empty()); int i = 0; for (QVector::const_iterator it_b = m_budgets.constBegin(); it_b != m_budgets.constEnd(); ++it_b) { m_tab2->findChild("m_comboBudget")->insertItem((*it_b).name(), i); //set the current selected item if ((m_initialState.budget() == "Any" && (*it_b).budgetStart().year() == QDate::currentDate().year()) || m_initialState.budget() == (*it_b).id()) m_tab2->findChild("m_comboBudget")->setCurrentItem(i); i++; } } //set moving average days spinbox QSpinBox *spinbox = m_tab2->findChild("m_movingAverageDays"); spinbox->setEnabled(m_initialState.isIncludingMovingAverage()); if (m_initialState.isIncludingMovingAverage()) { spinbox->setValue(m_initialState.movingAverageDays()); } m_tab2->findChild("m_checkScheduled")->setChecked(m_initialState.isIncludingSchedules()); m_tab2->findChild("m_checkTransfers")->setChecked(m_initialState.isIncludingTransfers()); m_tab2->findChild("m_checkUnused")->setChecked(m_initialState.isIncludingUnusedAccounts()); } else if (m_tab3) { KComboBox *combo = m_tab3->findChild("m_comboOrganizeBy"); switch (m_initialState.rowType()) { case MyMoneyReport::eNoColumns: case MyMoneyReport::eCategory: combo->setCurrentItem(i18n("Categories"), false); break; case MyMoneyReport::eTopCategory: combo->setCurrentItem(i18n("Top Categories"), false); break; case MyMoneyReport::eTag: combo->setCurrentItem(i18n("Tags"), false); break; case MyMoneyReport::ePayee: combo->setCurrentItem(i18n("Payees"), false); break; case MyMoneyReport::eAccount: combo->setCurrentItem(i18n("Accounts"), false); break; case MyMoneyReport::eTopAccount: combo->setCurrentItem(i18n("Top Accounts"), false); break; case MyMoneyReport::eMonth: combo->setCurrentItem(i18n("Month"), false); break; case MyMoneyReport::eWeek: combo->setCurrentItem(i18n("Week"), false); break; default: throw MYMONEYEXCEPTION("KReportConfigurationFilterDlg::slotReset(): QueryTable report has invalid rowtype"); } unsigned qc = m_initialState.queryColumns(); m_tab3->findChild("m_checkNumber")->setChecked(qc & MyMoneyReport::eQCnumber); m_tab3->findChild("m_checkPayee")->setChecked(qc & MyMoneyReport::eQCpayee); m_tab3->findChild("m_checkTag")->setChecked(qc & MyMoneyReport::eQCtag); m_tab3->findChild("m_checkCategory")->setChecked(qc & MyMoneyReport::eQCcategory); m_tab3->findChild("m_checkMemo")->setChecked(qc & MyMoneyReport::eQCmemo); m_tab3->findChild("m_checkAccount")->setChecked(qc & MyMoneyReport::eQCaccount); m_tab3->findChild("m_checkReconciled")->setChecked(qc & MyMoneyReport::eQCreconciled); m_tab3->findChild("m_checkAction")->setChecked(qc & MyMoneyReport::eQCaction); m_tab3->findChild("m_checkShares")->setChecked(qc & MyMoneyReport::eQCshares); m_tab3->findChild("m_checkPrice")->setChecked(qc & MyMoneyReport::eQCprice); m_tab3->findChild("m_checkBalance")->setChecked(qc & MyMoneyReport::eQCbalance); m_tab3->findChild("m_checkTax")->setChecked(m_initialState.isTax()); m_tab3->findChild("m_checkInvestments")->setChecked(m_initialState.isInvestmentsOnly()); m_tab3->findChild("m_checkLoans")->setChecked(m_initialState.isLoansOnly()); + m_tab3->findChild("m_checkHideTransactions")->setChecked(m_initialState.isHideTransactions()); + m_tab3->findChild("m_checkHideSplitDetails")->setEnabled(!m_initialState.isHideTransactions()); + m_tab3->findChild("m_checkHideSplitDetails")->setChecked - (m_initialState.detailLevel() == MyMoneyReport::eDetailNone); + (m_initialState.detailLevel() == MyMoneyReport::eDetailNone || m_initialState.isHideTransactions()); } if (m_tabChart) { KMyMoneyGeneralCombo* combo = m_tabChart->findChild("m_comboType"); switch (m_initialState.chartType()) { case MyMoneyReport::eChartNone: combo->setCurrentItem(MyMoneyReport::eChartLine); break; case MyMoneyReport::eChartLine: case MyMoneyReport::eChartBar: case MyMoneyReport::eChartStackedBar: case MyMoneyReport::eChartPie: case MyMoneyReport::eChartRing: combo->setCurrentItem(m_initialState.chartType()); break; case MyMoneyReport::eChartEnd: throw MYMONEYEXCEPTION("KReportConfigurationFilterDlg::slotReset(): Report has invalid charttype"); } m_tabChart->findChild("m_checkCHGridLines")->setChecked(m_initialState.isChartCHGridLines()); m_tabChart->findChild("m_checkSVGridLines")->setChecked(m_initialState.isChartSVGridLines()); m_tabChart->findChild("m_checkValues")->setChecked(m_initialState.isChartDataLabels()); m_tabChart->findChild("m_checkShowChart")->setChecked(m_initialState.isChartByDefault()); m_tabChart->findChild("m_lineWidth")->setValue(m_initialState.chartLineWidth()); m_tabChart->findChild("m_logYaxis")->setChecked(m_initialState.isLogYAxis()); } if (m_tabRange) { m_tabRange->ui->m_dataRangeStart->setText(m_initialState.dataRangeStart()); m_tabRange->ui->m_dataRangeEnd->setText(m_initialState.dataRangeEnd()); m_tabRange->ui->m_dataMajorTick->setText(m_initialState.dataMajorTick()); m_tabRange->ui->m_dataMinorTick->setText(m_initialState.dataMinorTick()); m_tabRange->ui->m_dataLock->setCurrentIndex((int)m_initialState.dataFilter()); KComboBox *combo = m_tabRange->ui->m_comboColumns; if (m_initialState.isColumnsAreDays()) { switch (m_initialState.columnType()) { case MyMoneyReport::eNoColumns: case MyMoneyReport::eDays: combo->setCurrentItem(i18nc("@item the columns will display daily data", "Daily"), false); break; case MyMoneyReport::eWeeks: combo->setCurrentItem(i18nc("@item the columns will display weekly data", "Weekly"), false); break; default: break; } } else { switch (m_initialState.columnType()) { case MyMoneyReport::eNoColumns: case MyMoneyReport::eMonths: combo->setCurrentItem(i18nc("@item the columns will display monthly data", "Monthly"), false); break; case MyMoneyReport::eBiMonths: combo->setCurrentItem(i18nc("@item the columns will display bi-monthly data", "Bi-Monthly"), false); break; case MyMoneyReport::eQuarters: combo->setCurrentItem(i18nc("@item the columns will display quarterly data", "Quarterly"), false); break; case MyMoneyReport::eYears: combo->setCurrentItem(i18nc("@item the columns will display yearly data", "Yearly"), false); break; default: break; } } } // // Text Filter // QRegExp textfilter; if (m_initialState.textFilter(textfilter)) { m_ui->m_textEdit->setText(textfilter.pattern()); m_ui->m_caseSensitive->setChecked(Qt::CaseSensitive == textfilter.caseSensitivity()); m_ui->m_regExp->setChecked(QRegExp::RegExp == textfilter.patternSyntax()); m_ui->m_textNegate->setCurrentIndex(m_initialState.isInvertingText()); } // // Type & State Filters // int type; if (m_initialState.firstType(type)) m_ui->m_typeBox->setCurrentIndex(type); int state; if (m_initialState.firstState(state)) m_ui->m_stateBox->setCurrentIndex(state); // // Number Filter // QString nrFrom, nrTo; if (m_initialState.numberFilter(nrFrom, nrTo)) { if (nrFrom == nrTo) { m_ui->m_nrEdit->setEnabled(true); m_ui->m_nrFromEdit->setEnabled(false); m_ui->m_nrToEdit->setEnabled(false); m_ui->m_nrEdit->setText(nrFrom); m_ui->m_nrFromEdit->setText(QString()); m_ui->m_nrToEdit->setText(QString()); m_ui->m_nrButton->setChecked(true); m_ui->m_nrRangeButton->setChecked(false); } else { m_ui->m_nrEdit->setEnabled(false); m_ui->m_nrFromEdit->setEnabled(true); m_ui->m_nrToEdit->setEnabled(false); m_ui->m_nrEdit->setText(QString()); m_ui->m_nrFromEdit->setText(nrFrom); m_ui->m_nrToEdit->setText(nrTo); m_ui->m_nrButton->setChecked(false); m_ui->m_nrRangeButton->setChecked(true); } } else { m_ui->m_nrEdit->setEnabled(true); m_ui->m_nrFromEdit->setEnabled(false); m_ui->m_nrToEdit->setEnabled(false); m_ui->m_nrEdit->setText(QString()); m_ui->m_nrFromEdit->setText(QString()); m_ui->m_nrToEdit->setText(QString()); m_ui->m_nrButton->setChecked(true); m_ui->m_nrRangeButton->setChecked(false); } // // Amount Filter // MyMoneyMoney from, to; if (m_initialState.amountFilter(from, to)) { // bool getAmountFilter(MyMoneyMoney&,MyMoneyMoney&); if (from == to) { m_ui->m_amountEdit->setEnabled(true); m_ui->m_amountFromEdit->setEnabled(false); m_ui->m_amountToEdit->setEnabled(false); m_ui->m_amountEdit->loadText(QString::number(from.toDouble())); m_ui->m_amountFromEdit->loadText(QString()); m_ui->m_amountToEdit->loadText(QString()); m_ui->m_amountButton->setChecked(true); m_ui->m_amountRangeButton->setChecked(false); } else { m_ui->m_amountEdit->setEnabled(false); m_ui->m_amountFromEdit->setEnabled(true); m_ui->m_amountToEdit->setEnabled(true); m_ui->m_amountEdit->loadText(QString()); m_ui->m_amountFromEdit->loadText(QString::number(from.toDouble())); m_ui->m_amountToEdit->loadText(QString::number(to.toDouble())); m_ui->m_amountButton->setChecked(false); m_ui->m_amountRangeButton->setChecked(true); } } else { m_ui->m_amountEdit->setEnabled(true); m_ui->m_amountFromEdit->setEnabled(false); m_ui->m_amountToEdit->setEnabled(false); m_ui->m_amountEdit->loadText(QString()); m_ui->m_amountFromEdit->loadText(QString()); m_ui->m_amountToEdit->loadText(QString()); m_ui->m_amountButton->setChecked(true); m_ui->m_amountRangeButton->setChecked(false); } // // Payees Filter // QStringList payees; if (m_initialState.payees(payees)) { if (payees.empty()) { m_ui->m_emptyPayeesButton->setChecked(true); } else { selectAllItems(m_ui->m_payeesView, false); selectItems(m_ui->m_payeesView, payees, true); } } else { selectAllItems(m_ui->m_payeesView, true); } // // Tags Filter // QStringList tags; if (m_initialState.tags(tags)) { if (tags.empty()) { m_ui->m_emptyTagsButton->setChecked(true); } else { selectAllItems(m_ui->m_tagsView, false); selectItems(m_ui->m_tagsView, tags, true); } } else { selectAllItems(m_ui->m_tagsView, true); } // // Accounts Filter // QStringList accounts; if (m_initialState.accounts(accounts)) { m_ui->m_accountsView->selectAllItems(false); m_ui->m_accountsView->selectItems(accounts, true); } else m_ui->m_accountsView->selectAllItems(true); // // Categories Filter // if (m_initialState.categories(accounts)) { m_ui->m_categoriesView->selectAllItems(false); m_ui->m_categoriesView->selectItems(accounts, true); } else m_ui->m_categoriesView->selectAllItems(true); // // Date Filter // // the following call implies a call to slotUpdateSelections, // that's why we call it last m_initialState.updateDateFilter(); QDate dateFrom, dateTo; if (m_initialState.dateFilter(dateFrom, dateTo)) { if (m_initialState.isDateUserDefined()) { m_dateRange->m_ui->m_dateRange->setCurrentItem(MyMoneyTransactionFilter::userDefined); m_dateRange->m_ui->m_fromDate->setDate(dateFrom); m_dateRange->m_ui->m_toDate->setDate(dateTo); } else { m_dateRange->m_ui->m_fromDate->setDate(dateFrom); m_dateRange->m_ui->m_toDate->setDate(dateTo); m_dateRange->slotDateChanged(); } } else { m_dateRange->m_ui->m_dateRange->setCurrentItem(MyMoneyTransactionFilter::allDates); m_dateRange->slotDateRangeChanged(MyMoneyTransactionFilter::allDates); } slotRightSize(); } void KReportConfigurationFilterDlg::slotDateChanged() { if (m_dateRange->m_ui->m_dateRange->currentItem() != MyMoneyTransactionFilter::userDefined) { m_dateRange->slotDateChanged(); } slotUpdateSelections(); } void KReportConfigurationFilterDlg::slotShowHelp() { KHelpClient::invokeHelp("details.reports.config"); } //TODO Fix the reports and engine to include transfers even if categories are filtered - bug #1523508 void KReportConfigurationFilterDlg::slotUpdateCheckTransfers() { QCheckBox* cb = m_tab2->findChild("m_checkTransfers"); if (!m_ui->m_categoriesView->allItemsSelected()) { cb->setChecked(false); cb->setDisabled(true); } else { cb->setEnabled(true); } } diff --git a/kmymoney/html/kmymoney.css b/kmymoney/html/kmymoney.css index ab63d5325..9ef96b0e7 100644 --- a/kmymoney/html/kmymoney.css +++ b/kmymoney/html/kmymoney.css @@ -1,370 +1,375 @@ @media screen { A.el { text-decoration: none; } A.elRef { font-weight: bold } A.code { text-decoration: none; font-weight: normal; color: #4C59A6 } A.codeRef { font-weight: normal; color: #4C59A6 } A:hover { text-decoration: none; font-weight: normal; color: #4C59A6 } body { background-color: Window; color:WindowText; font-family: verdana, arial, sans-serif; } .setcolor { /*sets color of some spacing elements (such as the column between assets and liabilities) to the desired color*/ background-color:Window; } body#summaryview { /* set body attributes that affect only the summary view (and not reports) */ background: url(./images/bg-texture.png) repeat fixed; } #vieweffect { /* creates a dropshadow at the top of the view creating a resessed effect */ background: url(./images/top-shadow.png) repeat-x top; margin:0px -10px 0px -10px; position:fixed; top:-5px; width:100%; height:20px; z-index:50; } #summarytitle { /* "your financial summary" title on summary page */ display:block; margin-bottom:6px; text-align: right; color:WindowText; Font-size:20px; padding:10px 15px 15px 0; } .shadow {/*wraps .displayblock -can be used for special decorative effects like a drop shadow */ background: url(./images/shadow.png) no-repeat bottom right; margin:0px 5px 30px 15px; } .displayblock {/*ties together a summary header and a table into a single content block*/ display:block; position:relative; top:-6px; left:-6px; background-color: Window; border-right: 1px solid gray; border-bottom: 1px solid gray; border-left: 1px solid lightgrey; /*border:1px solid WindowText;*/ padding: 0px; } .summaryheader { /*section labels over each table in the financial summary*/ background: HighLight url(./images/currencyflourish.png) no-repeat bottom right; color:WindowText; Font-size:1.2em; font-weight:bold; padding:5px 10px; } .summarytable { /*the tables in the financial summary */ padding:5px; } .summarytable td { /*style in the tables in the financial summary */ padding:5px 10px; border-left: medium solid Window; border-right: medium solid window; color:WindowText; } .itemtitle { /* -additional label for table headers. example "Assets" and "Liabilities"*/ color:HighLight; Font-weight:bold; } .itemtitle td { /* table data cells related to .itemtitle*/ padding:0px 10px 0px 10px; border-left: 0px; border-right: 0px; font-size:1.2em; } .item { /* -item labels (table headers) for sections in the financial summary */ font-weight:bold; color:WindowText; } .item td { /* table data cells related to .item*/ border-left: 0px; border-right: 0px; border-bottom:3px solid WindowText; } .warningtitle { /* -set warning background color -overdue payments -items of this class also belong to the class called "itemtitle"*/ color:red;/*set programatically, not by css*/ background-color: HighLight; } .warning { /* -set warning background color -items of this class also belong to the class called "item"*/ background-color: HighLight; } th.left, td.left {/*rule to align table header and table data cells*/ text-align: left; } th.right, td.right {/*rule to align table header and table data cells*/ text-align: right; } th.center, td.center {/*rule to align table header and table data cells*/ text-align: center; } .gap { /* used for spacing in financial summary and reports if needed -match to background color of body if you don't want it to show.*/ } /***********************************************************/ /* These affect only the reports found in the reports view */ h2.report { /* header -title on report pages */ font-size: 18px; font-family: verdana, arial, sans-serif; margin-right: 10px; margin-left: 10px; margin-top: 10px; margin-bottom: 10px; text-align: center; color:WindowText; } .itemheader { /*column labels in reports */ font-family: verdana, arial, helvetica, sans-serif; font-weight: bold; background-color: Window; color: WindowText; padding-top: 5px; padding-left: 20px; padding-bottom: 5px; } div.subtitle { /*subtitle of each report page*/ text-align: center; color:WindowText; } table.report {/*center the report*/ margin-left:auto; margin-right:auto; } table.report th {/*styles table header cells*/ padding: 0.5em 0.5em; } table.report td {/*styles table cells- but not background color*/ font-size: 9pt; padding: 0 0.5em; text-align: right; } table.report td.leftborder {/*does not appear to be in use*/ border-left: 1px solid; } table.report td.left {/*far left column*/ text-align: left; } table.report td.left0 {/*does not appear to be in use*/ text-align: left; } table.report td.left1 {/*does not appear to be in use*/ text-align: left; text-indent: 1.0em; } table.report td.left2 {/*does not appear to be in use*/ text-align: left; text-indent: 2.0em; } table.report tr#subtotal td {/*line separating row groups*/ border-bottom: 1px solid black; font-weight: normal; } table.report tr#solo td {/*line separating rows that are not groups*/ border-bottom: 1px solid black; font-weight: normal; } table.report tr#topparent td.left {/*parent label for each row group containing children*/ font-weight: bold; } table.report tr#solo td.left {/*label for each row group _not_ containing children*/ font-weight: bold; } table.report tr.sectionheader td { /* label (title) of each section -subtotals -for example 'Income' and 'Expenses' */ font-weight: bold; padding: 0.5em 0.5em 0 0.5em; color:WindowText; } + table.report tr.sectionfooterbasic td { /* totals for without top border */ + padding: 0 0.5em 0.5em 0.5em; + color:WindowText; + } + table.report tr.sectionfooter td { /* totals for each section -subtotals */ border-top: 1px solid black; padding: 0 0.5em 0.5em 0.5em; color:WindowText; } table.report tr.reportfooter td { /* "Grand Total" totals" */ border-bottom: 1px solid black; border-top: 1px solid black; padding: 0 0.5em 0 0.5em; color:WindowText; } table.report tr.reportfooter td.left { /* "Grand Total" label in the left column */ font-weight: bold; color:WindowText; } table.report tr.spacer td {/*used to make a table row act as a spacer when needed*/ font-size: 4pt; padding: 1em 0; } } @media print { body { background: white; margin: 0; padding: 0 } body { font-family: helvetica, arial; font-size: 10pt } td,th { font-family: helvetica, arial; font-size: 9pt } thead { display: table-header-group } tbody { display: table-row-group } tfoot { display: table-footer-group } tr { page-break-inside: avoid } div.gap { display: none } .spacer { display: none } h2.report, div.subtitle { margin: 6pt; padding: 0; text-align: center } div.subtitle { margin-bottom: 18pt } table { border-collapse: separate; border-spacing: 1px; } table { margin-left: auto; margin-right: auto } td { vertical-align: baseline } table.report {/*center the report*/ margin-left:auto; margin-right:auto; } table.report th {/*styles table header cells*/ padding: 0.5em 0.5em; } table.report td {/*styles table cells- but not background color*/ text-align: right; } table.report td.left {/*far left column*/ text-align: left; } table.report td.left0 {/*does not appear to be in use*/ text-align: left; } table.report td.left1 {/*does not appear to be in use*/ text-align: left; text-indent: 1.0em; } table.report td.left2 {/*does not appear to be in use*/ text-align: left; text-indent: 2.0em; } table.report tr#subtotal td {/*line separating row groups*/ border-bottom: 1px solid black; font-weight: normal; } table.report tr#solo td {/*line separating rows that are not groups*/ border-bottom: 1px solid black; font-weight: normal; } table.report tr#topparent td.left {/*parent label for each row group containing children*/ font-weight: bold; } table.report tr#solo td.left {/*label for each row group _not_ containing children*/ font-weight: bold; } th { border-bottom: 1pt solid black } /* th { background: #cccccc } */ tr.item0 td { background: #f2f2ff } tr.item1 td { background: #f2fff2 } tr.row-even td { background: #f2f2ff } tr.row-odd td { background: #f2fff2 } tr.item0 td, tr.item1 td, tr.itemA td, tr.itemZ td { font-style: italic } td.left0, td.left1, td.left2, td.left { text-align: left } td.center { text-align: center } td.right { text-align: right } td, th { padding: 2pt 4pt } tr.sectionheader td.left, tr.sectionfooter td.left, tr.sectionheader td.left0, tr.sectionfooter td.left0 { padding-top: 12pt; font-size: 1.1em; font-weight: bold } tr.sectionheader td.left1, tr.sectionfooter td.left1, tr.sectionheader td.left2, tr.sectionfooter td.left2 { padding-top: 6pt; font-size: 0.9em; font-weight: bold } tr.reportfooter td.left { padding-top: 12pt; font-size: 1.1em; font-weight: bold } #subtotal { font-style: italic } /* #topparent td, #solo td { border-top: 1px solid gray } */ } tr.item0 td,tr.item1 td,tr.itemA td,tr.itemZ td { font-style: italic; } tr.itemA td { border-bottom: 1px dotted gray; } tr.itemZ td { border-top: 1px dotted gray; } .item0 .value,.item1 .value { padding-right: 2em; } diff --git a/kmymoney/mymoney/mymoneyreport.cpp b/kmymoney/mymoney/mymoneyreport.cpp index 0fc1b04e6..204fa715c 100644 --- a/kmymoney/mymoney/mymoneyreport.cpp +++ b/kmymoney/mymoney/mymoneyreport.cpp @@ -1,833 +1,836 @@ /*************************************************************************** mymoneyreport.cpp ------------------- begin : Sun July 4 2004 copyright : (C) 2004-2005 by Ace Jones email : acejones@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "mymoneyreport.h" // ---------------------------------------------------------------------------- // QT Includes #include #include // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes #include "mymoneyfile.h" const QStringList MyMoneyReport::kRowTypeText = QString("none,assetliability,expenseincome,category,topcategory,account,tag,payee,month,week,topaccount,topaccount-account,equitytype,accounttype,institution,budget,budgetactual,schedule,accountinfo,accountloaninfo,accountreconcile,cashflow").split(','); const QStringList MyMoneyReport::kColumnTypeText = QString("none,months,bimonths,quarters,4,5,6,weeks,8,9,10,11,years").split(','); // if you add names here, don't forget to update the bitmap for EQueryColumns // and shift the bit for eQCend one position to the left const QStringList MyMoneyReport::kQueryColumnsText = QString("none,number,payee,category,tag,memo,account,reconcileflag,action,shares,price,performance,loan,balance,capitalgain").split(','); const MyMoneyReport::EReportType MyMoneyReport::kTypeArray[] = { eNoReport, ePivotTable, ePivotTable, eQueryTable, eQueryTable, eQueryTable, eQueryTable, eQueryTable, eQueryTable, eQueryTable, eQueryTable, eQueryTable, eQueryTable, eQueryTable, eQueryTable, ePivotTable, ePivotTable, eInfoTable, eInfoTable, eInfoTable, eQueryTable, eQueryTable, eNoReport }; const QStringList MyMoneyReport::kDetailLevelText = QString("none,all,top,group,total,invalid").split(','); const QStringList MyMoneyReport::kChartTypeText = QString("none,line,bar,pie,ring,stackedbar,invalid").split(','); // This should live in mymoney/mymoneytransactionfilter.h const QStringList kTypeText = QString("all,payments,deposits,transfers,none").split(','); const QStringList kStateText = QString("all,notreconciled,cleared,reconciled,frozen,none").split(','); const QStringList kDateLockText = QString("alldates,untiltoday,currentmonth,currentyear,monthtodate,yeartodate,yeartomonth,lastmonth,lastyear,last7days,last30days,last3months,last6months,last12months,next7days,next30days,next3months,next6months,next12months,userdefined,last3tonext3months,last11Months,currentQuarter,lastQuarter,nextQuarter,currentFiscalYear,lastFiscalYear,today,next18months").split(','); const QStringList kDataLockText = QString("automatic,userdefined").split(','); const QStringList kAccountTypeText = QString("unknown,checkings,savings,cash,creditcard,loan,certificatedep,investment,moneymarket,asset,liability,currency,income,expense,assetloan,stock,equity,invalid").split(','); MyMoneyReport::MyMoneyReport() : m_name("Unconfigured Pivot Table Report"), m_detailLevel(eDetailNone), m_convertCurrency(true), m_favorite(false), m_tax(false), m_investments(false), m_loans(false), + m_hideTransactions(false), m_reportType(kTypeArray[eExpenseIncome]), m_rowType(eExpenseIncome), m_columnType(eMonths), m_columnsAreDays(false), m_queryColumns(eQCnone), m_dateLock(MyMoneyTransactionFilter::userDefined), m_accountGroupFilter(false), m_chartType(eChartLine), m_chartDataLabels(true), m_chartCHGridLines(true), m_chartSVGridLines(true), m_chartByDefault(false), m_logYaxis(false), m_dataLock(MyMoneyReport::automatic), m_includeSchedules(false), m_includeTransfers(false), m_includeBudgetActuals(false), m_includeUnusedAccounts(false), m_showRowTotals(false), m_includeForecast(false), m_includeMovingAverage(false), m_movingAverageDays(0), m_includePrice(false), m_includeAveragePrice(false), m_mixedTime(false), m_currentDateColumn(0), m_skipZero(false) { m_chartLineWidth = m_lineWidth; } MyMoneyReport::MyMoneyReport(const QString& id, const MyMoneyReport& right) : MyMoneyObject(id), m_movingAverageDays(0), m_currentDateColumn(0) { *this = right; setId(id); } MyMoneyReport::MyMoneyReport(ERowType _rt, unsigned _ct, dateOptionE _dl, EDetailLevel _ss, const QString& _name, const QString& _comment) : m_name(_name), m_comment(_comment), m_detailLevel(_ss), m_convertCurrency(true), m_favorite(false), m_tax(false), m_investments(false), m_loans(false), + m_hideTransactions(false), m_reportType(kTypeArray[_rt]), m_rowType(_rt), m_columnsAreDays(false), m_queryColumns(eQCnone), m_dateLock(_dl), m_accountGroupFilter(false), m_chartType(eChartLine), m_chartDataLabels(true), m_chartCHGridLines(true), m_chartSVGridLines(true), m_chartByDefault(false), m_logYaxis(false), m_dataLock(MyMoneyReport::automatic), m_includeSchedules(false), m_includeTransfers(false), m_includeBudgetActuals(false), m_includeUnusedAccounts(false), m_showRowTotals(false), m_includeForecast(false), m_includeMovingAverage(false), m_movingAverageDays(0), m_includePrice(false), m_includeAveragePrice(false), m_mixedTime(false), m_currentDateColumn(0), m_skipZero(false) { //set initial values m_chartLineWidth = m_lineWidth; //set report type if (m_reportType == ePivotTable) m_columnType = static_cast(_ct); if (m_reportType == eQueryTable) m_queryColumns = static_cast(_ct); setDateFilter(_dl); //throw exception if the type is inconsistent if ((_rt > static_cast(sizeof(kTypeArray) / sizeof(kTypeArray[0]))) || (m_reportType == eNoReport)) throw MYMONEYEXCEPTION("Invalid report type"); //add the corresponding account groups if (_rt == MyMoneyReport::eAssetLiability) { addAccountGroup(MyMoneyAccount::Asset); addAccountGroup(MyMoneyAccount::Liability); m_showRowTotals = true; } if (_rt == MyMoneyReport::eExpenseIncome) { addAccountGroup(MyMoneyAccount::Expense); addAccountGroup(MyMoneyAccount::Income); m_showRowTotals = true; } //FIXME take this out once we have sorted out all issues regarding budget of assets and liabilities -- asoliverez@gmail.com if (_rt == MyMoneyReport::eBudget || _rt == MyMoneyReport::eBudgetActual) { addAccountGroup(MyMoneyAccount::Expense); addAccountGroup(MyMoneyAccount::Income); } if (_rt == MyMoneyReport::eAccountInfo) { addAccountGroup(MyMoneyAccount::Asset); addAccountGroup(MyMoneyAccount::Liability); } //cash flow reports show splits for all account groups if (_rt == MyMoneyReport::eCashFlow) { addAccountGroup(MyMoneyAccount::Expense); addAccountGroup(MyMoneyAccount::Income); addAccountGroup(MyMoneyAccount::Asset); addAccountGroup(MyMoneyAccount::Liability); } } MyMoneyReport::MyMoneyReport(const QDomElement& node) : MyMoneyObject(node), m_currentDateColumn(0) { // properly initialize the object before reading it *this = MyMoneyReport(); if (!read(node)) clearId(); } void MyMoneyReport::clear() { m_accountGroupFilter = false; m_accountGroups.clear(); MyMoneyTransactionFilter::clear(); } void MyMoneyReport::validDateRange(QDate& _db, QDate& _de) { _db = fromDate(); _de = toDate(); // if either begin or end date are invalid we have one of the following // possible date filters: // // a) begin date not set - first transaction until given end date // b) end date not set - from given date until last transaction // c) both not set - first transaction until last transaction // // If there is no transaction in the engine at all, we use the current // year as the filter criteria. if (!_db.isValid() || !_de.isValid()) { QList list = MyMoneyFile::instance()->transactionList(*this); QDate tmpBegin, tmpEnd; if (!list.isEmpty()) { qSort(list); // try to use the post dates tmpBegin = list.front().postDate(); tmpEnd = list.back().postDate(); // if the post dates are not valid try the entry dates if (!tmpBegin.isValid()) tmpBegin = list.front().entryDate(); if (!tmpEnd.isValid()) tmpEnd = list.back().entryDate(); } // make sure that we leave this function with valid dates no mather what if (!tmpBegin.isValid() || !tmpEnd.isValid() || tmpBegin > tmpEnd) { tmpBegin = QDate(QDate::currentDate().year(), 1, 1); // the first date in the file tmpEnd = QDate(QDate::currentDate().year(), 12, 31); // the last date in the file } if (!_db.isValid()) _db = tmpBegin; if (!_de.isValid()) _de = tmpEnd; } if (_db > _de) _db = _de; } void MyMoneyReport::setRowType(ERowType _rt) { m_rowType = _rt; m_reportType = kTypeArray[_rt]; m_accountGroupFilter = false; m_accountGroups.clear(); if (_rt == MyMoneyReport::eAssetLiability) { addAccountGroup(MyMoneyAccount::Asset); addAccountGroup(MyMoneyAccount::Liability); } if (_rt == MyMoneyReport::eExpenseIncome) { addAccountGroup(MyMoneyAccount::Expense); addAccountGroup(MyMoneyAccount::Income); } } bool MyMoneyReport::accountGroups(QList& list) const { bool result = m_accountGroupFilter; if (result) { QList::const_iterator it_group = m_accountGroups.begin(); while (it_group != m_accountGroups.end()) { list += (*it_group); ++it_group; } } return result; } void MyMoneyReport::addAccountGroup(MyMoneyAccount::accountTypeE type) { if (!m_accountGroups.isEmpty() && type != MyMoneyAccount::UnknownAccountType) { if (m_accountGroups.contains(type)) return; } m_accountGroupFilter = true; if (type != MyMoneyAccount::UnknownAccountType) m_accountGroups.push_back(type); } bool MyMoneyReport::includesAccountGroup(MyMoneyAccount::accountTypeE type) const { bool result = (! m_accountGroupFilter) || (isIncludingTransfers() && m_rowType == MyMoneyReport::eExpenseIncome) || m_accountGroups.contains(type); return result; } bool MyMoneyReport::includes(const MyMoneyAccount& acc) const { bool result = false; if (includesAccountGroup(acc.accountGroup())) { switch (acc.accountGroup()) { case MyMoneyAccount::Income: case MyMoneyAccount::Expense: if (isTax()) result = (acc.value("Tax") == "Yes") && includesCategory(acc.id()); else result = includesCategory(acc.id()); break; case MyMoneyAccount::Asset: case MyMoneyAccount::Liability: if (isLoansOnly()) result = acc.isLoan() && includesAccount(acc.id()); else if (isInvestmentsOnly()) result = acc.isInvest() && includesAccount(acc.id()); else if (isIncludingTransfers() && m_rowType == MyMoneyReport::eExpenseIncome) // If transfers are included, ONLY include this account if it is NOT // included in the report itself!! result = ! includesAccount(acc.id()); else result = includesAccount(acc.id()); break; default: result = includesAccount(acc.id()); } } return result; } void MyMoneyReport::write(QDomElement& e, QDomDocument *doc, bool anonymous) const { // No matter what changes, be sure to have a 'type' attribute. Only change // the major type if it becomes impossible to maintain compatibility with // older versions of the program as new features are added to the reports. // Feel free to change the minor type every time a change is made here. writeBaseXML(*doc, e); if (anonymous) { e.setAttribute("name", m_id); e.setAttribute("comment", QString(m_comment).fill('x')); } else { e.setAttribute("name", m_name); e.setAttribute("comment", m_comment); } e.setAttribute("group", m_group); e.setAttribute("convertcurrency", m_convertCurrency); e.setAttribute("favorite", m_favorite); e.setAttribute("tax", m_tax); e.setAttribute("investments", m_investments); e.setAttribute("loans", m_loans); + e.setAttribute("hidetransactions", m_hideTransactions); e.setAttribute("rowtype", kRowTypeText[m_rowType]); e.setAttribute("datelock", kDateLockText[m_dateLock]); e.setAttribute("datalock", kDataLockText[m_dataLock]); e.setAttribute("includeschedules", m_includeSchedules); e.setAttribute("columnsaredays", m_columnsAreDays); e.setAttribute("includestransfers", m_includeTransfers); if (!m_budgetId.isEmpty()) e.setAttribute("budget", m_budgetId); e.setAttribute("includesactuals", m_includeBudgetActuals); e.setAttribute("includeunused", m_includeUnusedAccounts); e.setAttribute("includesforecast", m_includeForecast); e.setAttribute("includesprice", m_includePrice); e.setAttribute("includesaverageprice", m_includeAveragePrice); e.setAttribute("mixedtime", m_mixedTime); e.setAttribute("includesmovingaverage", m_includeMovingAverage); if (m_includeMovingAverage) e.setAttribute("movingaveragedays", m_movingAverageDays); if (m_chartType < 0 || m_chartType >= kChartTypeText.size()) { qDebug("m_chartType out of bounds with %d on report of type %d. Default to none.", m_chartType, m_reportType); e.setAttribute("charttype", kChartTypeText[0]); } else { e.setAttribute("charttype", kChartTypeText[m_chartType]); } e.setAttribute("chartdatalabels", m_chartDataLabels); e.setAttribute("chartchgridlines", m_chartCHGridLines); e.setAttribute("chartsvgridlines", m_chartSVGridLines); e.setAttribute("chartbydefault", m_chartByDefault); e.setAttribute("chartlinewidth", m_chartLineWidth); e.setAttribute("logYaxis", m_logYaxis); e.setAttribute("dataRangeStart", m_dataRangeStart); e.setAttribute("dataRangeEnd", m_dataRangeEnd); e.setAttribute("dataMajorTick", m_dataMajorTick); e.setAttribute("dataMinorTick", m_dataMinorTick); e.setAttribute("dataLock", m_dataLock); e.setAttribute("skipZero", m_skipZero); + e.setAttribute("detail", kDetailLevelText[m_detailLevel]); if (m_reportType == ePivotTable) { e.setAttribute("type", "pivottable 1.15"); - e.setAttribute("detail", kDetailLevelText[m_detailLevel]); e.setAttribute("columntype", kColumnTypeText[m_columnType]); e.setAttribute("showrowtotals", m_showRowTotals); } else if (m_reportType == eQueryTable) { e.setAttribute("type", "querytable 1.14"); QStringList columns; unsigned qc = m_queryColumns; unsigned it_qc = eQCbegin; unsigned index = 1; while (it_qc != eQCend) { if (qc & it_qc) columns += kQueryColumnsText[index]; it_qc *= 2; index++; } e.setAttribute("querycolumns", columns.join(",")); } else if (m_reportType == eInfoTable) { e.setAttribute("type", "infotable 1.0"); - e.setAttribute("detail", kDetailLevelText[m_detailLevel]); e.setAttribute("showrowtotals", m_showRowTotals); } // // Text Filter // QRegExp textfilter; if (textFilter(textfilter)) { QDomElement f = doc->createElement("TEXT"); f.setAttribute("pattern", textfilter.pattern()); f.setAttribute("casesensitive", (textfilter.caseSensitivity() == Qt::CaseSensitive) ? 1 : 0); f.setAttribute("regex", (textfilter.patternSyntax() == QRegExp::Wildcard) ? 1 : 0); f.setAttribute("inverttext", m_invertText); e.appendChild(f); } // // Type & State Filters // QList typelist; if (types(typelist) && ! typelist.empty()) { // iterate over payees, and add each one QList::const_iterator it_type = typelist.constBegin(); while (it_type != typelist.constEnd()) { QDomElement p = doc->createElement("TYPE"); p.setAttribute("type", kTypeText[*it_type]); e.appendChild(p); ++it_type; } } QList statelist; if (states(statelist) && ! statelist.empty()) { // iterate over payees, and add each one QList::const_iterator it_state = statelist.constBegin(); while (it_state != statelist.constEnd()) { QDomElement p = doc->createElement("STATE"); p.setAttribute("state", kStateText[*it_state]); e.appendChild(p); ++it_state; } } // // Number Filter // QString nrFrom, nrTo; if (numberFilter(nrFrom, nrTo)) { QDomElement f = doc->createElement("NUMBER"); f.setAttribute("from", nrFrom); f.setAttribute("to", nrTo); e.appendChild(f); } // // Amount Filter // MyMoneyMoney from, to; if (amountFilter(from, to)) { // bool getAmountFilter(MyMoneyMoney&,MyMoneyMoney&); QDomElement f = doc->createElement("AMOUNT"); f.setAttribute("from", from.toString()); f.setAttribute("to", to.toString()); e.appendChild(f); } // // Payees Filter // QStringList payeelist; if (payees(payeelist)) { if (payeelist.empty()) { QDomElement p = doc->createElement("PAYEE"); e.appendChild(p); } else { // iterate over payees, and add each one QStringList::const_iterator it_payee = payeelist.constBegin(); while (it_payee != payeelist.constEnd()) { QDomElement p = doc->createElement("PAYEE"); p.setAttribute("id", *it_payee); e.appendChild(p); ++it_payee; } } } // // Tags Filter // QStringList taglist; if (tags(taglist)) { if (taglist.empty()) { QDomElement p = doc->createElement("TAG"); e.appendChild(p); } else { // iterate over tags, and add each one QStringList::const_iterator it_tag = taglist.constBegin(); while (it_tag != taglist.constEnd()) { QDomElement p = doc->createElement("TAG"); p.setAttribute("id", *it_tag); e.appendChild(p); ++it_tag; } } } // // Account Groups Filter // QList accountgrouplist; if (accountGroups(accountgrouplist)) { // iterate over accounts, and add each one QList::const_iterator it_group = accountgrouplist.constBegin(); while (it_group != accountgrouplist.constEnd()) { QDomElement p = doc->createElement("ACCOUNTGROUP"); p.setAttribute("group", kAccountTypeText[*it_group]); e.appendChild(p); ++it_group; } } // // Accounts Filter // QStringList accountlist; if (accounts(accountlist)) { // iterate over accounts, and add each one QStringList::const_iterator it_account = accountlist.constBegin(); while (it_account != accountlist.constEnd()) { QDomElement p = doc->createElement("ACCOUNT"); p.setAttribute("id", *it_account); e.appendChild(p); ++it_account; } } // // Categories Filter // accountlist.clear(); if (categories(accountlist)) { // iterate over accounts, and add each one QStringList::const_iterator it_account = accountlist.constBegin(); while (it_account != accountlist.constEnd()) { QDomElement p = doc->createElement("CATEGORY"); p.setAttribute("id", *it_account); e.appendChild(p); ++it_account; } } // // Date Filter // if (m_dateLock == MyMoneyTransactionFilter::userDefined) { QDate dateFrom, dateTo; if (dateFilter(dateFrom, dateTo)) { QDomElement f = doc->createElement("DATES"); if (dateFrom.isValid()) f.setAttribute("from", dateFrom.toString(Qt::ISODate)); if (dateTo.isValid()) f.setAttribute("to", dateTo.toString(Qt::ISODate)); e.appendChild(f); } } } bool MyMoneyReport::read(const QDomElement& e) { // The goal of this reading method is 100% backward AND 100% forward // compatibility. Any report ever created with any version of KMyMoney // should be able to be loaded by this method (as long as it's one of the // report types supported in this version, of course) bool result = false; if ( "REPORT" == e.tagName() && ( (e.attribute("type").indexOf("pivottable 1.") == 0) || (e.attribute("type").indexOf("querytable 1.") == 0) || (e.attribute("type").indexOf("infotable 1.") == 0) ) ) { result = true; clear(); int i; m_name = e.attribute("name"); m_comment = e.attribute("comment", "Extremely old report"); //set report type if (!e.attribute("type").indexOf("pivottable")) { m_reportType = MyMoneyReport::ePivotTable; } else if (!e.attribute("type").indexOf("querytable")) { m_reportType = MyMoneyReport::eQueryTable; } else if (!e.attribute("type").indexOf("infotable")) { m_reportType = MyMoneyReport::eInfoTable; } else { m_reportType = MyMoneyReport::eNoReport; } // Removed the line that screened out loading reports that are called // "Default Report". It's possible for the user to change the comment // to this, and we'd hate for it to break as a result. m_group = e.attribute("group"); m_id = e.attribute("id"); //check for reports with older settings which didn't have the detail attribute if (e.hasAttribute("detail")) { i = kDetailLevelText.indexOf(e.attribute("detail", "all")); if (i != -1) m_detailLevel = static_cast(i); } else if (e.attribute("showsubaccounts", "0").toUInt()) { //set to show all accounts m_detailLevel = eDetailAll; } else { //set to show the top level account instead m_detailLevel = eDetailTop; } m_convertCurrency = e.attribute("convertcurrency", "1").toUInt(); m_favorite = e.attribute("favorite", "0").toUInt(); m_tax = e.attribute("tax", "0").toUInt(); m_investments = e.attribute("investments", "0").toUInt(); m_loans = e.attribute("loans", "0").toUInt(); + m_hideTransactions = e.attribute("hidetransactions", "0").toUInt(); m_includeSchedules = e.attribute("includeschedules", "0").toUInt(); m_columnsAreDays = e.attribute("columnsaredays", "0").toUInt(); m_includeTransfers = e.attribute("includestransfers", "0").toUInt(); if (e.hasAttribute("budget")) m_budgetId = e.attribute("budget"); m_includeBudgetActuals = e.attribute("includesactuals", "0").toUInt(); m_includeUnusedAccounts = e.attribute("includeunused", "0").toUInt(); m_includeForecast = e.attribute("includesforecast", "0").toUInt(); m_includePrice = e.attribute("includesprice", "0").toUInt(); m_includeAveragePrice = e.attribute("includesaverageprice", "0").toUInt(); m_mixedTime = e.attribute("mixedtime", "0").toUInt(); m_includeMovingAverage = e.attribute("includesmovingaverage", "0").toUInt(); m_skipZero = e.attribute("skipZero", "0").toUInt(); if (m_includeMovingAverage) m_movingAverageDays = e.attribute("movingaveragedays", "1").toUInt(); //only load chart data if it is a pivot table m_chartType = static_cast(0); if (m_reportType == ePivotTable) { i = kChartTypeText.indexOf(e.attribute("charttype")); if (i >= 0) m_chartType = static_cast(i); // if it is invalid, set to first type if (m_chartType >= eChartEnd) m_chartType = eChartLine; m_chartDataLabels = e.attribute("chartdatalabels", "1").toUInt(); m_chartCHGridLines = e.attribute("chartchgridlines", "1").toUInt(); m_chartSVGridLines = e.attribute("chartsvgridlines", "1").toUInt(); m_chartByDefault = e.attribute("chartbydefault", "0").toUInt(); m_chartLineWidth = e.attribute("chartlinewidth", QString(m_lineWidth)).toUInt(); m_logYaxis = e.attribute("logYaxis", "0").toUInt(); m_dataRangeStart = e.attribute("dataRangeStart", "0"); m_dataRangeEnd = e.attribute("dataRangeEnd", "0"); m_dataMajorTick = e.attribute("dataMajorTick", "0"); m_dataMinorTick = e.attribute("dataMinorTick", "0"); } else { m_chartDataLabels = true; m_chartCHGridLines = true; m_chartSVGridLines = true; m_chartByDefault = false; m_chartLineWidth = 1; m_logYaxis = false; } QString datelockstr = e.attribute("datelock", "userdefined"); // Handle the pivot 1.2/query 1.1 case where the values were saved as // numbers bool ok = false; i = datelockstr.toUInt(&ok); if (!ok) { i = kDateLockText.indexOf(datelockstr); if (i == -1) i = MyMoneyTransactionFilter::userDefined; } setDateFilter(static_cast(i)); QString datalockstr = e.attribute("dataLock", "userdefined"); ok = false; i = datalockstr.toUInt(&ok); if (!ok) { i = kDataLockText.indexOf(datalockstr); if (i == -1) i = MyMoneyReport::userDefined; } setDataFilter(static_cast(i)); i = kRowTypeText.indexOf(e.attribute("rowtype", "expenseincome")); if (i != -1) { setRowType(static_cast(i)); // recent versions of KMyMoney always showed a total column for // income/expense reports. We turn it on for backward compatibility // here. If the total column is turned off, the flag will be reset // in the next step if (i == eExpenseIncome) m_showRowTotals = true; } if (e.hasAttribute("showrowtotals")) m_showRowTotals = e.attribute("showrowtotals").toUInt(); i = kColumnTypeText.indexOf(e.attribute("columntype", "months")); if (i != -1) setColumnType(static_cast(i)); unsigned qc = 0; QStringList columns = e.attribute("querycolumns", "none").split(','); QStringList::const_iterator it_column = columns.constBegin(); while (it_column != columns.constEnd()) { i = kQueryColumnsText.indexOf(*it_column); if (i > 0) qc |= (1 << (i - 1)); ++it_column; } setQueryColumns(static_cast(qc)); QDomNode child = e.firstChild(); while (!child.isNull() && child.isElement()) { QDomElement c = child.toElement(); if ("TEXT" == c.tagName() && c.hasAttribute("pattern")) { setTextFilter(QRegExp(c.attribute("pattern"), c.attribute("casesensitive", "1").toUInt() ? Qt::CaseSensitive : Qt::CaseInsensitive, c.attribute("regex", "1").toUInt() ? QRegExp::Wildcard : QRegExp::RegExp), c.attribute("inverttext", "0").toUInt()); } if ("TYPE" == c.tagName() && c.hasAttribute("type")) { i = kTypeText.indexOf(c.attribute("type")); if (i != -1) addType(i); } if ("STATE" == c.tagName() && c.hasAttribute("state")) { i = kStateText.indexOf(c.attribute("state")); if (i != -1) addState(i); } if ("NUMBER" == c.tagName()) { setNumberFilter(c.attribute("from"), c.attribute("to")); } if ("AMOUNT" == c.tagName()) { setAmountFilter(MyMoneyMoney(c.attribute("from", "0/100")), MyMoneyMoney(c.attribute("to", "0/100"))); } if ("DATES" == c.tagName()) { QDate from, to; if (c.hasAttribute("from")) from = QDate::fromString(c.attribute("from"), Qt::ISODate); if (c.hasAttribute("to")) to = QDate::fromString(c.attribute("to"), Qt::ISODate); MyMoneyTransactionFilter::setDateFilter(from, to); } if ("PAYEE" == c.tagName()) { addPayee(c.attribute("id")); } if ("TAG" == c.tagName()) { addTag(c.attribute("id")); } if ("CATEGORY" == c.tagName() && c.hasAttribute("id")) { addCategory(c.attribute("id")); } if ("ACCOUNT" == c.tagName() && c.hasAttribute("id")) { addAccount(c.attribute("id")); } if ("ACCOUNTGROUP" == c.tagName() && c.hasAttribute("group")) { i = kAccountTypeText.indexOf(c.attribute("group")); if (i != -1) addAccountGroup(static_cast(i)); } child = child.nextSibling(); } } return result; } void MyMoneyReport::writeXML(QDomDocument& document, QDomElement& parent) const { QDomElement el = document.createElement("REPORT"); write(el, &document, false); parent.appendChild(el); } bool MyMoneyReport::hasReferenceTo(const QString& id) const { QStringList list; // collect all ids accounts(list); categories(list); payees(list); tags(list); return (list.contains(id) > 0); } int MyMoneyReport::m_lineWidth = 2; void MyMoneyReport::setLineWidth(int width) { m_lineWidth = width; } diff --git a/kmymoney/mymoney/mymoneyreport.h b/kmymoney/mymoney/mymoneyreport.h index 3f0633f01..d690ea38a 100644 --- a/kmymoney/mymoney/mymoneyreport.h +++ b/kmymoney/mymoney/mymoneyreport.h @@ -1,770 +1,780 @@ /*************************************************************************** mymoneyreport.h ------------------- begin : Sun July 4 2004 copyright : (C) 2004-2005 by Ace Jones email : acejones@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef MYMONEYREPORT_H #define MYMONEYREPORT_H // ---------------------------------------------------------------------------- // QT Includes #include #include #include class QDomElement; class QDomDocument; // ---------------------------------------------------------------------------- // Project Includes #include #include #include #include /** * This class defines a report within the MyMoneyEngine. The report class * contains all the configuration parameters needed to run a report, plus * XML serialization. * * A report is a transactionfilter, so any report can specify which * transactions it's interested down to the most minute level of detail. * It extends the transactionfilter by providing identification (name, * comments, group type, etc) as well as layout information (what kind * of layout should be used, how the rows & columns should be presented, * currency converted, etc.) * * As noted above, this class only provides a report DEFINITION. The * generation and presentation of the report itself are left to higher * level classes. * * @author Ace Jones */ class KMM_MYMONEY_EXPORT MyMoneyReport: public MyMoneyObject, public MyMoneyTransactionFilter { public: // When adding a new row type, be sure to add a corresponding entry in kTypeArray enum ERowType { eNoRows = 0, eAssetLiability, eExpenseIncome, eCategory, eTopCategory, eAccount, eTag, ePayee, eMonth, eWeek, eTopAccount, eAccountByTopAccount, eEquityType, eAccountType, eInstitution, eBudget, eBudgetActual, eSchedule, eAccountInfo, eAccountLoanInfo, eAccountReconcile, eCashFlow}; enum EReportType { eNoReport = 0, ePivotTable, eQueryTable, eInfoTable }; enum EColumnType { eNoColumns = 0, eDays = 1, eMonths = 1, eBiMonths = 2, eQuarters = 3, eWeeks = 7, eYears = 12 }; // if you add bits to this bitmask, start with the value currently assigned to eQCend and update its value afterwards // also don't forget to add column names to kQueryColumnsText in mymoneyreport.cpp enum EQueryColumns { eQCnone = 0x0, eQCbegin = 0x1, eQCnumber = 0x1, eQCpayee = 0x2, eQCcategory = 0x4, eQCtag = 0x8, eQCmemo = 0x10, eQCaccount = 0x20, eQCreconciled = 0x40, eQCaction = 0x80, eQCshares = 0x100, eQCprice = 0x200, eQCperformance = 0x400, eQCloan = 0x800, eQCbalance = 0x1000, eQCcapitalgain = 0x2000, eQCend = 0x4000 }; enum EDetailLevel { eDetailNone = 0, eDetailAll, eDetailTop, eDetailGroup, eDetailTotal, eDetailEnd }; enum EChartType { eChartNone = 0, eChartLine, eChartBar, eChartPie, eChartRing, eChartStackedBar, eChartEnd }; enum dataOptionE { automatic = 0, userDefined, dataOptionCount }; static const QStringList kRowTypeText; static const QStringList kColumnTypeText; static const QStringList kQueryColumnsText; static const QStringList kDetailLevelText; static const QStringList kChartTypeText; static const EReportType kTypeArray[]; public: MyMoneyReport(); MyMoneyReport(ERowType _rt, unsigned _ct, dateOptionE _dl, EDetailLevel _ss, const QString& _name, const QString& _comment); MyMoneyReport(const QString& id, const MyMoneyReport& right); /** * This constructor creates an object based on the data found in the * QDomElement referenced by @p node. If problems arise, the @p id of * the object is cleared (see MyMoneyObject::clearId()). */ MyMoneyReport(const QDomElement& node); // Simple get operations const QString& name() const { return m_name; } bool isShowingRowTotals() const { return (m_showRowTotals); } EReportType reportType() const { return m_reportType; } ERowType rowType() const { return m_rowType; } EColumnType columnType() const { return m_columnType; } bool isRunningSum() const { return (m_rowType == eAssetLiability); } bool isConvertCurrency() const { return m_convertCurrency; } unsigned columnPitch() const { return static_cast(m_columnType); } bool isShowingColumnTotals() const { return m_convertCurrency; } const QString& comment() const { return m_comment; } EQueryColumns queryColumns() const { return m_queryColumns; } const QString& group() const { return m_group; } bool isFavorite() const { return m_favorite; } bool isTax() const { return m_tax; } bool isInvestmentsOnly() const { return m_investments; } bool isLoansOnly() const { return m_loans; } EDetailLevel detailLevel() const { return m_detailLevel; } + bool isHideTransactions() const { + return m_hideTransactions; + } EChartType chartType() const { return m_chartType; } bool isChartDataLabels() const { return m_chartDataLabels; } bool isChartCHGridLines() const { return m_chartCHGridLines; } bool isChartSVGridLines() const { return m_chartSVGridLines; } bool isChartByDefault() const { return m_chartByDefault; } uint chartLineWidth() const { return m_chartLineWidth; } bool isLogYAxis() const { return m_logYaxis; } const QString& dataRangeStart() const { return m_dataRangeStart; } const QString& dataRangeEnd() const { return m_dataRangeEnd; } const QString& dataMajorTick() const { return m_dataMajorTick; } const QString& dataMinorTick() const { return m_dataMinorTick; } bool isIncludingSchedules() const { return m_includeSchedules; } bool isColumnsAreDays() const { return m_columnsAreDays; } bool isIncludingTransfers() const { return m_includeTransfers; } bool isIncludingUnusedAccounts() const { return m_includeUnusedAccounts; } bool hasBudget() const { return !m_budgetId.isEmpty(); } const QString& budget() const { return m_budgetId; } bool isIncludingBudgetActuals() const { return m_includeBudgetActuals; } bool isIncludingForecast() const { return m_includeForecast; } bool isIncludingMovingAverage() const { return m_includeMovingAverage; } int movingAverageDays() const { return m_movingAverageDays; } bool isIncludingPrice() const { return m_includePrice; } bool isIncludingAveragePrice() const { return m_includeAveragePrice; } bool isDateUserDefined() const { return m_dateLock == MyMoneyTransactionFilter::userDefined; } bool isDataUserDefined() const { return m_dataLock == MyMoneyReport::userDefined; } bool isMixedTime() const { return m_mixedTime; } int currentDateColumn() const { return m_currentDateColumn; } /** * @see #m_skipZero */ bool isSkippingZero() const { return m_skipZero; } // Simple set operations void setName(const QString& _s) { m_name = _s; } void setConvertCurrency(bool _f) { m_convertCurrency = _f; } void setRowType(ERowType _rt); void setColumnType(EColumnType _ct) { m_columnType = _ct; } void setComment(const QString& _comment) { m_comment = _comment; } void setGroup(const QString& _group) { m_group = _group; } void setFavorite(bool _f) { m_favorite = _f; } void setQueryColumns(EQueryColumns _qc) { m_queryColumns = _qc; } void setTax(bool _f) { m_tax = _f; } void setInvestmentsOnly(bool _f) { m_investments = _f; if (_f) m_loans = false; } void setLoansOnly(bool _f) { m_loans = _f; if (_f) m_investments = false; } void setDetailLevel(EDetailLevel _detail) { m_detailLevel = _detail; } + void setHideTransactions(bool _f) { + m_hideTransactions = _f; + } void setChartType(EChartType _type) { m_chartType = _type; } void setChartDataLabels(bool _f) { m_chartDataLabels = _f; } void setChartCHGridLines(bool _f) { m_chartCHGridLines = _f; } void setChartSVGridLines(bool _f) { m_chartSVGridLines = _f; } void setChartByDefault(bool _f) { m_chartByDefault = _f; } void setChartLineWidth(uint _f) { m_chartLineWidth = _f; } void setLogYAxis(bool _f) { m_logYaxis = _f; } void setDataRangeStart(const QString& _f) { m_dataRangeStart = _f; } void setDataRangeEnd(const QString& _f) { m_dataRangeEnd = _f; } void setDataMajorTick(const QString& _f) { m_dataMajorTick = _f; } void setDataMinorTick(const QString& _f) { m_dataMinorTick = _f; } void setIncludingSchedules(bool _f) { m_includeSchedules = _f; } void setColumnsAreDays(bool _f) { m_columnsAreDays = _f; } void setIncludingTransfers(bool _f) { m_includeTransfers = _f; } void setIncludingUnusedAccounts(bool _f) { m_includeUnusedAccounts = _f; } void setShowingRowTotals(bool _f) { m_showRowTotals = _f; } void setIncludingBudgetActuals(bool _f) { m_includeBudgetActuals = _f; } void setIncludingForecast(bool _f) { m_includeForecast = _f; } void setIncludingMovingAverage(bool _f) { m_includeMovingAverage = _f; } void setMovingAverageDays(int _days) { m_movingAverageDays = _days; } void setIncludingPrice(bool _f) { m_includePrice = _f; } void setIncludingAveragePrice(bool _f) { m_includeAveragePrice = _f; } void setMixedTime(bool _f) { m_mixedTime = _f; } void setCurrentDateColumn(int _f) { m_currentDateColumn = _f; } /** * @see #m_skipZero */ void setSkipZero(int _f) { m_skipZero = _f; } /** * Sets the budget used for this report * * @param _budget The ID of the budget to use, or an empty string * to indicate a budget is NOT included * @param _fa Whether to display actual data alongside the budget. * Setting to false means the report displays ONLY the budget itself. * @warning For now, the budget ID is ignored. The budget id is * simply checked for any non-empty string, and if so, hasBudget() * will return true. */ void setBudget(const QString& _budget, bool _fa = true) { m_budgetId = _budget; m_includeBudgetActuals = _fa; } /** * This method allows you to clear the underlying transaction filter */ void clear(); /** * This method allows you to set the underlying transaction filter * * @param _filter The filter which should replace the existing transaction * filter. */ void assignFilter(const MyMoneyTransactionFilter& _filter) { MyMoneyTransactionFilter::operator=(_filter); } /** * Set the underlying date filter and LOCK that filter to the specified * range. For example, if @p _u is "CurrentMonth", this report should always * be updated to the current month no matter when the report is run. * * This updating is not entirely automatic, you should update it yourself by * calling updateDateFilter. * * @param _u The date range constant (MyMoneyTransactionFilter::dateRangeE) * which this report should be locked to. */ void setDateFilter(dateOptionE _u) { m_dateLock = _u; if (_u != MyMoneyTransactionFilter::userDefined) MyMoneyTransactionFilter::setDateFilter(_u); } void setDataFilter(dataOptionE _u) { m_dataLock = _u; } /** * Set the underlying date filter using the start and end dates provided. * Note that this does not LOCK to any range like setDateFilter(unsigned) * above. It is just a reimplementation of the MyMoneyTransactionFilter * version. * * @param _db The inclusive begin date of the date range * @param _de The inclusive end date of the date range */ void setDateFilter(const QDate& _db, const QDate& _de) { MyMoneyTransactionFilter::setDateFilter(_db, _de); } /** * Set the underlying date filter using the 'date lock' property. * * Always call this function before executing the report to be sure that * the date filters properly match the plain-language 'date lock'. * * For example, if the report is date-locked to "Current Month", and the * last time you loaded or ran the report was in August, but it's now * September, this function will update the date range to be September, * as is proper. */ void updateDateFilter() { if (m_dateLock != MyMoneyTransactionFilter::userDefined) MyMoneyTransactionFilter::setDateFilter(m_dateLock); } MyMoneyReport::dataOptionE dataFilter() { return m_dataLock; } /** * Retrieves a VALID beginning & ending date for this report. * * The underlying date filter can return en empty QDate() for either the * begin or end date or both. This is typically unacceptable for reports, * which need the REAL begin and end date. * * This function gets the underlying date filter range, and if either is * an empty QDate(), it determines the missing date from looking at all * the transactions which match the underlying filter, and returning the * date of the first or last transaction (as appropriate). * * @param _db The inclusive begin date of the date range * @param _de The inclusive end date of the date range */ void validDateRange(QDate& _db, QDate& _de); /** * This method turns on the account group filter and adds the * @p type to the list of allowed groups. * * Note that account group filtering is handled differently * than all the filters of the underlying class. This filter * is meant to be applied to individual splits of matched * transactions AFTER the underlying filter is used to find * the matching transactions. * * @param type the account group to add to the allowed groups list */ void addAccountGroup(MyMoneyAccount::accountTypeE type); /** * This method returns whether an account group filter has been set, * and if so, it returns all the account groups set in the filter. * * @param list list to append account groups into * @return return true if an account group filter has been set */ bool accountGroups(QList& list) const; /** * This method returns whether the specified account group * is allowed by the account groups filter. * * @param type group to append account groups into * @return return true if an account group filter has been set */ bool includesAccountGroup(MyMoneyAccount::accountTypeE type) const; /** * This method is used to test whether a specific account * passes the accountGroup test and either the Account or * Category test, depending on which sort of Account it is. * * The m_tax and m_investments properties are also considered. * * @param acc the account in question * @return true if account is in filter set, false otherwise */ bool includes(const MyMoneyAccount& acc) const; /** * This method writes this report to the DOM element @p e, * within the DOM document @p doc. * * @param e The element which should be populated with info from this report * @param doc The document which we can use to create new sub-elements * if needed * @param anonymous Whether the sensitive parts of the report should be * masked */ void write(QDomElement& e, QDomDocument *doc, bool anonymous = false) const; /** * This method reads a report from the DOM element @p e, and * populates this report with the results. * * @param e The element from which the report should be read * * @return bool True if a report was successfully loaded from the * element @p e. If false is returned, the contents of this report * object are undefined. */ bool read(const QDomElement& e); /** * This method creates a QDomElement for the @p document * under the parent node @p parent. (This version overwrites the * MMObject base class.) * * @param document reference to QDomDocument * @param parent reference to QDomElement parent node */ virtual void writeXML(QDomDocument& document, QDomElement& parent) const; /** * This method checks if a reference to the given object exists. It returns, * a @p true if the object is referencing the one requested by the * parameter @p id. If it does not, this method returns @p false. * * @param id id of the object to be checked for references * @retval true This object references object with id @p id. * @retval false This object does not reference the object with id @p id. */ virtual bool hasReferenceTo(const QString& id) const; /** * This method allows to modify the default lineWidth for graphs. * The default is 2. */ static void setLineWidth(int width); private: /** * The user-assigned name of the report */ QString m_name; /** * The user-assigned comment for the report, in case they want to make * additional notes for themselves about the report. */ QString m_comment; /** * Where to group this report amongst the others in the UI view. This * should be assigned by the UI system. */ QString m_group; /** * How much detail to show in the accounts */ enum EDetailLevel m_detailLevel; + /** + * Whether to show transactions or just totals. + */ + bool m_hideTransactions; /** * Whether to convert all currencies to the base currency of the file (true). * If this is false, it's up to the report generator to decide how to handle * the currency. */ bool m_convertCurrency; /** * Whether this is one of the users' favorite reports */ bool m_favorite; /** * Whether this report should only include categories marked as "Tax"="Yes" */ bool m_tax; /** * Whether this report should only include investment accounts */ bool m_investments; /** * Whether this report should only include loan accounts * Applies only to querytable reports. Mutually exclusive with * m_investments. */ bool m_loans; /** * What sort of algorithm should be used to run the report */ enum EReportType m_reportType; /** * What sort of values should show up on the ROWS of this report */ enum ERowType m_rowType; /** * What sort of values should show up on the COLUMNS of this report, * in the case of a 'PivotTable' report. Really this is used more as a * QUANTITY of months or days. Whether it's months or days is determined * by m_columnsAreDays. */ enum EColumnType m_columnType; /** * Whether the base unit of columns of this report is days. Only applies to * 'PivotTable' reports. If false, then columns are months or multiples thereof. */ bool m_columnsAreDays; /** * What sort of values should show up on the COLUMNS of this report, * in the case of a 'QueryTable' report */ enum EQueryColumns m_queryColumns; /** * The plain-language description of what the date range should be locked * to. 'userDefined' means NO locking, in any other case, the report * will be adjusted to match the date lock. So if the date lock is * 'currentMonth', the start and end dates of the underlying filter will * be updated to whatever the current month is. This updating happens * automatically when the report is loaded, and should also be done * manually by calling updateDateFilter() before generating the report */ dateOptionE m_dateLock; /** * Which account groups should be included in the report. This filter * is applied to the individual splits AFTER a transaction has been * matched using the underlying filter. */ QList m_accountGroups; /** * Whether an account group filter has been set (see m_accountGroups) */ bool m_accountGroupFilter; /** * What format should be used to draw this report as a chart */ enum EChartType m_chartType; /** * Whether the value of individual data points should be drawn on the chart */ bool m_chartDataLabels; /** * Whether grid lines should be drawn on the chart */ bool m_chartCHGridLines; bool m_chartSVGridLines; /** * Whether this report should be shown as a chart by default (otherwise it * should be shown as a textual report) */ bool m_chartByDefault; /** * Width of the chart lines */ uint m_chartLineWidth; /** * Whether Y axis is logarithmic or linear */ bool m_logYaxis; /** * Y data range */ QString m_dataRangeStart; QString m_dataRangeEnd; /** * Y data range division */ QString m_dataMajorTick; QString m_dataMinorTick; /** * Whether data range should be calculated automatically or is user defined */ dataOptionE m_dataLock; /** * Whether to include scheduled transactions */ bool m_includeSchedules; /** * Whether to include transfers. Only applies to Income/Expense reports */ bool m_includeTransfers; /** * The id of the budget associated with this report. */ QString m_budgetId; /** * Whether this report should print the actual data to go along with * the budget. This is only valid if the report has a budget. */ bool m_includeBudgetActuals; /** * Whether this report should include all accounts and not only * accounts with transactions. */ bool m_includeUnusedAccounts; /** * Whether this report should include columns for row totals */ bool m_showRowTotals; /** * Whether this report should include forecast balance */ bool m_includeForecast; /** * Whether this report should include moving average */ bool m_includeMovingAverage; /** * The amount of days that spans each moving average */ int m_movingAverageDays; /** * Whether this report should include prices */ bool m_includePrice; /** * Whether this report should include moving average prices */ bool m_includeAveragePrice; /** * Make the actual and forecast lines display as one */ bool m_mixedTime; /** * This stores the column for the current date * This value is calculated dinamically and thus it is not saved in the file */ int m_currentDateColumn; /** * This member keeps the current setting for line graphs lineWidth. * @sa setLineWidth() */ static int m_lineWidth; /** * This option is for investments reports only which * show prices instead of balances as all other reports do. *

* Select this option to include prices for the given period (week, month, * quarter, ...) only. *

*

* If this option is off the last existing price is shown for a period, if * it is on, in a table the value is '0' shown and in a chart a linear * interpolation for the missing values will be performed. *
Example: *
There are prices for January and March, but there is no price for * February. *

    *
  • OFF: shows the price for February as the last price of * January *
  • ON: in a table the value is '0', in a chart a linear * interpolation for the February-price will be performed * (so it makes a kind of average-value using the January- and the * March-price in the chart) *
*

*/ bool m_skipZero; }; /** * Make it possible to hold @ref MyMoneyReport objects inside @ref QVariant objects. */ Q_DECLARE_METATYPE(MyMoneyReport) #endif // MYMONEYREPORT_H diff --git a/kmymoney/reports/listtable.cpp b/kmymoney/reports/listtable.cpp index ba2b42bd8..d913fa831 100644 --- a/kmymoney/reports/listtable.cpp +++ b/kmymoney/reports/listtable.cpp @@ -1,562 +1,575 @@ /*************************************************************************** listtable.cpp ------------------- begin : Sat 28 jun 2008 copyright : (C) 2004-2005 by Ace Jones 2008 by Alvaro Soliverez (C) 2017 Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "listtable.h" // ---------------------------------------------------------------------------- // QT Includes #include #include #include #include // ---------------------------------------------------------------------------- // KDE Includes // This is just needed for i18n(). Once I figure out how to handle i18n // without using this macro directly, I'll be freed of KDE dependency. // ---------------------------------------------------------------------------- // Project Includes #include "mymoneyfile.h" #include "mymoneyreport.h" #include "mymoneyexception.h" #include "kmymoneyutils.h" #include "kmymoneyglobalsettings.h" #include "reportdebug.h" namespace reports { QStringList ListTable::TableRow::m_sortCriteria; // **************************************************************************** // // ListTable implementation // // **************************************************************************** bool ListTable::TableRow::operator< (const TableRow& _compare) const { bool result = false; QStringList::const_iterator it_criterion = m_sortCriteria.constBegin(); while (it_criterion != m_sortCriteria.constEnd()) { if (this->operator[](*it_criterion) < _compare[ *it_criterion ]) { result = true; break; } else if (this->operator[](*it_criterion) > _compare[ *it_criterion ]) break; ++it_criterion; } return result; } // needed for KDE < 3.2 implementation of qHeapSort bool ListTable::TableRow::operator<= (const TableRow& _compare) const { return (!(_compare < *this)); } bool ListTable::TableRow::operator== (const TableRow& _compare) const { return (!(*this < _compare) && !(_compare < *this)); } bool ListTable::TableRow::operator> (const TableRow& _compare) const { return (_compare < *this); } /** * TODO * * - Collapse 2- & 3- groups when they are identical * - Way more test cases (especially splits & transfers) * - Option to collapse splits * - Option to exclude transfers * */ ListTable::ListTable(const MyMoneyReport& _report): ReportTable(), m_config(_report) { } void ListTable::render(QString& result, QString& csv) const { MyMoneyFile* file = MyMoneyFile::instance(); result = ""; csv = ""; result += QString("

%1

\n").arg(m_config.name()); csv += "\"Report: " + m_config.name() + "\"\n"; //actual dates of the report result += QString("
"); if (!m_config.fromDate().isNull()) { result += i18nc("Report date range", "%1 through %2", QLocale().toString(m_config.fromDate(), QLocale::ShortFormat), QLocale().toString(m_config.toDate(), QLocale::ShortFormat)); result += QString("
\n"); result += QString("
 
\n"); csv += i18nc("Report date range", "%1 through %2", QLocale().toString(m_config.fromDate(), QLocale::ShortFormat), QLocale().toString(m_config.toDate(), QLocale::ShortFormat)); csv += QString("\n"); } result += QString("
"); if (m_config.isConvertCurrency()) { result += i18n("All currencies converted to %1" , file->baseCurrency().name()); csv += i18n("All currencies converted to %1\n" , file->baseCurrency().name()); } else { result += i18n("All values shown in %1 unless otherwise noted" , file->baseCurrency().name()); csv += i18n("All values shown in %1 unless otherwise noted\n" , file->baseCurrency().name()); } result += QString("
\n"); result += QString("
 
\n"); // retrieve the configuration parameters from the report definition. // the things that we care about for query reports are: // how to group the rows, what columns to display, and what field // to subtotal on QStringList groups = m_group.split(','); QStringList columns = m_columns.split(','); if (!m_subtotal.isEmpty() && m_subtotal.split(',').count() == 1) // constructPerformanceRow has subtotal columns already in columns columns += m_subtotal; QStringList postcolumns = m_postcolumns.split(','); if (!m_postcolumns.isEmpty()) // prevent creation of empty column columns += postcolumns; // // Table header // QMap i18nHeaders; i18nHeaders["postdate"] = i18n("Date"); i18nHeaders["value"] = i18n("Amount"); i18nHeaders["number"] = i18n("Num"); i18nHeaders["payee"] = i18n("Payee"); i18nHeaders["tag"] = i18n("Tags"); i18nHeaders["category"] = i18n("Category"); i18nHeaders["account"] = i18n("Account"); i18nHeaders["memo"] = i18n("Memo"); i18nHeaders["topcategory"] = i18n("Top Category"); i18nHeaders["categorytype"] = i18n("Category Type"); i18nHeaders["month"] = i18n("Month"); i18nHeaders["week"] = i18n("Week"); i18nHeaders["reconcileflag"] = i18n("Reconciled"); i18nHeaders["action"] = i18n("Action"); i18nHeaders["shares"] = i18n("Shares"); i18nHeaders["price"] = i18n("Price"); i18nHeaders["latestprice"] = i18n("Price"); i18nHeaders["netinvvalue"] = i18n("Net Value"); i18nHeaders["buys"] = i18n("Buys"); i18nHeaders["sells"] = i18n("Sells"); i18nHeaders["reinvestincome"] = i18n("Dividends Reinvested"); i18nHeaders["cashincome"] = i18n("Dividends Paid Out"); i18nHeaders["startingbal"] = i18n("Starting Balance"); i18nHeaders["endingbal"] = i18n("Ending Balance"); i18nHeaders["return"] = i18n("Annualized Return"); i18nHeaders["returninvestment"] = i18n("Return On Investment"); i18nHeaders["fees"] = i18n("Fees"); i18nHeaders["interest"] = i18n("Interest"); i18nHeaders["payment"] = i18n("Payment"); i18nHeaders["balance"] = i18n("Balance"); i18nHeaders["type"] = i18n("Type"); i18nHeaders["name"] = i18nc("Account name", "Name"); i18nHeaders["nextduedate"] = i18n("Next Due Date"); i18nHeaders["occurence"] = i18n("Occurrence"); // krazy:exclude=spelling i18nHeaders["paymenttype"] = i18n("Payment Method"); i18nHeaders["institution"] = i18n("Institution"); i18nHeaders["description"] = i18n("Description"); i18nHeaders["openingdate"] = i18n("Opening Date"); i18nHeaders["currencyname"] = i18n("Currency"); i18nHeaders["balancewarning"] = i18n("Balance Early Warning"); i18nHeaders["maxbalancelimit"] = i18n("Balance Max Limit"); i18nHeaders["creditwarning"] = i18n("Credit Early Warning"); i18nHeaders["maxcreditlimit"] = i18n("Credit Max Limit"); i18nHeaders["tax"] = i18n("Tax"); i18nHeaders["favorite"] = i18n("Preferred"); i18nHeaders["loanamount"] = i18n("Loan Amount"); i18nHeaders["interestrate"] = i18n("Interest Rate"); i18nHeaders["nextinterestchange"] = i18n("Next Interest Change"); i18nHeaders["periodicpayment"] = i18n("Periodic Payment"); i18nHeaders["finalpayment"] = i18n("Final Payment"); i18nHeaders["currentbalance"] = i18n("Current Balance"); i18nHeaders["capitalgain"] = i18n("Capital Gain"); // the list of columns which represent money, so we can display them correctly QStringList moneyColumns = QString("value,shares,price,latestprice,netinvvalue,buys,sells,cashincome,reinvestincome,startingbal,fees,interest,payment,balance,balancewarning,maxbalancelimit,creditwarning,maxcreditlimit,loanamount,periodicpayment,finalpayment,currentbalance,startingbal,endingbal,capitalgain").split(','); // the list of columns which represent shares, which is like money except the // transaction currency will not be displayed QStringList sharesColumns = QString("shares").split(','); // the list of columns which represent a percentage, so we can display them correctly QStringList percentColumns = QString("return,returninvestment,interestrate").split(','); // the list of columns which represent dates, so we can display them correctly QStringList dateColumns = QString("postdate,entrydate,nextduedate,openingdate,nextinterestchange").split(','); result += "\n"; QStringList::const_iterator it_column = columns.constBegin(); while (it_column != columns.constEnd()) { QString i18nName = i18nHeaders[*it_column]; if (i18nName.isEmpty()) i18nName = *it_column; result += ""; csv += i18nName + ','; ++it_column; } result += "\n"; csv = csv.left(csv.length() - 1); csv += '\n'; // initialize group names to empty, so any group will have to display its header QStringList prevGrpNames; for (int i = 0; i < groups.count(); ++i) { prevGrpNames.append(QString()); } // // Rows // bool row_odd = true; + bool isHigherGroupTotal = false; // hack to inform whether to put separator line or not // ***DV*** MyMoneyMoney startingBalance; MyMoneyMoney balanceChange = MyMoneyMoney(); for (QList::const_iterator it_row = m_rows.begin(); it_row != m_rows.end(); ++it_row) { // the standard fraction is the fraction of an non-cash account in the base currency // this could be overridden using the "fraction" element of a row for each row. // Currently (2008-02-21) this override is not used at all (ipwizard) int fraction = file->baseCurrency().smallestAccountFraction(); if ((*it_row).find("fraction") != (*it_row).end()) fraction = (*it_row)["fraction"].toInt(); // detect whether any of groups changed and display new group header in that case for (int i = 0; i < groups.count(); ++i) { if (prevGrpNames.at(i) != (*it_row)[groups.at(i)]) { - row_odd = true; - result += "" - "\n"; - csv += "\"" + (*it_row)[groups.at(i)] + "\"\n"; + // group header of lowest group doesn't bring any useful information + // if hide transaction is enabled, so don't display it + if (!m_config.isHideTransactions() || i != groups.count() - 1) { + row_odd = true; + result += "" + "\n"; + csv += "\"" + (*it_row)[groups.at(i)] + "\"\n"; + } + if (i == groups.count() - 1) // lowest group has been switched... + isHigherGroupTotal = false; // ...so expect lowest group total prevGrpNames.replace(i, (*it_row)[groups.at(i)]); } } // // Columns // - // skip the opening and closing balance row, - // if the balance column is not shown - // rank = 0 for opening balance, rank = 3 for closing balance - if ((columns.contains("balance") == 0) && ((*it_row)["rank"] == "0" || (*it_row)["rank"] == "3")) - continue; - bool need_label = true; QString tlink; // link information to account and transaction - // ***DV*** - if ((* it_row)["rank"] == "1") { - row_odd = ! row_odd; - tlink = QString("id=%1&tid=%2") - .arg((* it_row)["accountid"], (* it_row)["id"]); - } - if ((*it_row)["rank"] == "0" || (*it_row)["rank"] == "3") - result += QString("").arg((* it_row)["id"]); - else if ((* it_row)["rank"] == "2") - result += QString("").arg(row_odd ? "item1" : "item0"); - else if ((* it_row)["rank"] == "4") { - if (m_config.rowType() == MyMoneyReport::eTag || //If we order by Tags don't show the Grand total as we can have multiple tags per transaction - !m_config.isConvertCurrency() && std::next(it_row) == m_rows.end())// grand total may be invalid if multiple currencies are used, so don't display it - continue; - else - result += QString(""); + if (!m_config.isHideTransactions() || (*it_row)["rank"] == "4") { // if hide transaction is enabled display only total rows i.e. rank = 4 + if ((*it_row)["rank"] == "0" || (*it_row)["rank"] == "3") { + // skip the opening and closing balance row, + // if the balance column is not shown + // rank = 0 for opening balance, rank = 3 for closing balance + if (!columns.contains("balance")) + continue; + result += QString("").arg((* it_row)["id"]); + // ***DV*** + } else if ((* it_row)["rank"] == "1") { + row_odd = ! row_odd; + tlink = QString("id=%1&tid=%2") + .arg((* it_row)["accountid"], (* it_row)["id"]); + result += QString("").arg(row_odd ? "row-odd " : "row-even"); + } else if ((* it_row)["rank"] == "2") + result += QString("").arg(row_odd ? "item1" : "item0"); + else if ((* it_row)["rank"] == "4") { + if ((m_config.rowType() == MyMoneyReport::eTag) || //If we order by Tags don't show the Grand total as we can have multiple tags per transaction + (!m_config.isConvertCurrency() && std::next(it_row) == m_rows.end()))// grand total may be invalid if multiple currencies are used, so don't display it + continue; + // display special footer (i.e. without horizontal separator) only for lowest group totals + else if (m_config.isHideTransactions() && !isHigherGroupTotal && std::next(it_row) != m_rows.end()) { + result += QString(""); + isHigherGroupTotal = true; + } else + result += QString(""); + } else + result += QString("").arg(row_odd ? "row-odd " : "row-even"); } else - result += QString("").arg(row_odd ? "row-odd " : "row-even"); + continue; QStringList::const_iterator it_column = columns.constBegin(); while (it_column != columns.constEnd()) { QString data = (*it_row)[*it_column]; // ***DV*** if ((* it_row)["rank"] == "2") { if (* it_column == "value") data = (* it_row)["split"]; else if (*it_column == "postdate" || *it_column == "number" || *it_column == "payee" || *it_column == "tag" || *it_column == "action" || *it_column == "shares" || *it_column == "price" || *it_column == "nextduedate" || *it_column == "balance" || *it_column == "account" || *it_column == "name") data = ""; } // ***DV*** else if ((*it_row)["rank"] == "0" || (*it_row)["rank"] == "3") { if (*it_column == "balance") { data = (* it_row)["balance"]; if ((* it_row)["id"] == "A") { // opening balance? startingBalance = MyMoneyMoney(data); balanceChange = MyMoneyMoney(); } } if (need_label) { if ((*it_column == "payee") || (*it_column == "category") || (*it_column == "memo")) { if (!(*it_row)["shares"].isEmpty()) { data = ((* it_row)["id"] == "A") ? i18n("Initial Market Value") : i18n("Ending Market Value"); } else { data = ((* it_row)["id"] == "A") ? i18n("Opening Balance") : i18n("Closing Balance"); } need_label = false; } } } // The 'balance' column is calculated at render-time // but not printed on split lines else if (*it_column == "balance" && (* it_row)["rank"] == "1") { // Take the balance off the deepest group iterator balanceChange += MyMoneyMoney((*it_row).value("value", "0")); data = (balanceChange + startingBalance).toString(); } // display total title but only if first column doesn't contain any data else if (it_column == columns.constBegin() && data.isEmpty() && (*it_row)["rank"] == "4") { result += ""; else result += i18n("Grand Total") + ""; ++it_column; continue; } // Figure out how to render the value in this column, depending on // what its properties are. // // TODO: This and the i18n headings are handled // as a set of parallel vectors. Would be much better to make a single // vector of a properties class. QString tlinkBegin, tlinkEnd; if (!tlink.isEmpty()) { tlinkBegin = QString("").arg(tlink); tlinkEnd = QLatin1String(""); } if (sharesColumns.contains(*it_column)) { if (data.isEmpty()) { result += QString(""); csv += "\"\","; } else { result += QString("").arg(MyMoneyMoney(data).formatMoney("", 3), tlinkBegin, tlinkEnd); csv += "\"" + MyMoneyMoney(data).formatMoney("", 3, false) + "\","; } } else if (moneyColumns.contains(*it_column)) { if (data.isEmpty()) { result += QString("") .arg((*it_column == "value") ? " class=\"value\"" : ""); csv += "\"\","; } else if (MyMoneyMoney(data) == MyMoneyMoney::autoCalc) { result += QString("%3%2%4") .arg((*it_column == "value") ? " class=\"value\"" : "") .arg(i18n("Calculated"), tlinkBegin, tlinkEnd); csv += "\"" + i18n("Calculated") + "\","; } else if (*it_column == "price") { result += QString("") .arg(MyMoneyMoney(data).formatMoney(MyMoneyMoney::precToDenom(KMyMoneyGlobalSettings::pricePrecision())), tlinkBegin, tlinkEnd); csv += "\"" + (*it_row)["currency"] + " " + MyMoneyMoney(data).formatMoney(MyMoneyMoney::precToDenom(KMyMoneyGlobalSettings::pricePrecision()), false) + "\","; } else { result += QString("%4%2 %3%5") .arg((*it_column == "value") ? " class=\"value\"" : "") .arg((*it_row)["currency"]) .arg(MyMoneyMoney(data).formatMoney(fraction)) .arg(tlinkBegin, tlinkEnd); csv += "\"" + (*it_row)["currency"] + " " + MyMoneyMoney(data).formatMoney(fraction, false) + "\","; } } else if (percentColumns.contains(*it_column)) { if (data.isEmpty()) { result += QString(""); csv += "\"\","; } else { data = (MyMoneyMoney(data) * MyMoneyMoney(100, 1)).formatMoney(fraction); result += QString("").arg(data, tlinkBegin, tlinkEnd); csv += data + "%,"; } } else if (dateColumns.contains(*it_column)) { // do this before we possibly change data csv += "\"" + data + "\","; // if we have a locale() then use its date formatter if (!data.isEmpty()) { QDate qd = QDate::fromString(data, Qt::ISODate); data = QLocale().toString(qd, QLocale::ShortFormat); } result += QString("").arg(data, tlinkBegin, tlinkEnd); } else { result += QString("").arg(data, tlinkBegin, tlinkEnd); csv += "\"" + data + "\","; } ++it_column; tlink.clear(); } result += "\n"; csv = csv.left(csv.length() - 1); // remove final comma csv += '\n'; } result += "
" + i18nName + "
" + - (*it_row)[groups.at(i)] + "
" + + (*it_row)[groups.at(i)] + "
"; if (!(*it_row)["depth"].isEmpty()) result += i18nc("Total balance", "Total") + ' ' + prevGrpNames.at((*it_row)["depth"].toInt()) + "%2%1%3%2%1%3%2%1%%3%2%1%3%2%1%3
\n"; } QString ListTable::renderBody() const { QString html, csv; render(html, csv); return html; } QString ListTable::renderCSV() const { QString html, csv; render(html, csv); return csv; } void ListTable::dump(const QString& file, const QString& context) const { QFile g(file); g.open(QIODevice::WriteOnly | QIODevice::Text); if (! context.isEmpty()) QTextStream(&g) << context.arg(renderBody()); else QTextStream(&g) << renderBody(); g.close(); } void ListTable::includeInvestmentSubAccounts() { // if we're not in expert mode, we need to make sure // that all stock accounts for the selected investment // account are also selected. // In case we get called for a non investment only report we quit if (KMyMoneyGlobalSettings::expertMode() || !m_config.isInvestmentsOnly()) { return; } // get all investment subAccountsList but do not include those with zero balance // or those which had no transactions during the timeframe of the report QStringList accountIdList; QStringList subAccountsList; MyMoneyFile* file = MyMoneyFile::instance(); // get the report account filter if (!m_config.accounts(accountIdList) && m_config.isInvestmentsOnly()) { // this will only execute if this is an investment-only report QList accountList; file->accountList(accountList); QList::const_iterator it_ma; for (it_ma = accountList.constBegin(); it_ma != accountList.constEnd(); ++it_ma) { if ((*it_ma).accountType() == MyMoneyAccount::Investment) { accountIdList.append((*it_ma).id()); } } } QStringList::const_iterator it_a; for (it_a = accountIdList.constBegin(); it_a != accountIdList.constEnd(); ++it_a) { MyMoneyAccount acc = file->account(*it_a); if (acc.accountType() == MyMoneyAccount::Investment) { QStringList::const_iterator it_b; for (it_b = acc.accountList().constBegin(); it_b != acc.accountList().constEnd(); ++it_b) { if (!accountIdList.contains(*it_b)) { subAccountsList.append(*it_b); } } } } if (m_config.isInvestmentsOnly() && !m_config.isIncludingUnusedAccounts()) { // if the balance is not zero at the end, include the subaccount QStringList::iterator it_balance; for (it_balance = subAccountsList.begin(); it_balance != subAccountsList.end();) { if (!file->balance((*it_balance), m_config.toDate()).isZero()) { m_config.addAccount((*it_balance)); it_balance = subAccountsList.erase((it_balance)); } else { ++it_balance; } } // if there are transactions for that subaccount, include them MyMoneyTransactionFilter filter; filter.setDateFilter(m_config.fromDate(), m_config.toDate()); filter.addAccount(subAccountsList); filter.setReportAllSplits(false); QList transactions = file->transactionList(filter); QList::const_iterator it_t = transactions.constBegin(); //Check each split for a matching account for (; it_t != transactions.constEnd(); ++it_t) { const QList& splits = (*it_t).splits(); QList::const_iterator it_s = splits.begin(); for (; it_s != splits.end(); ++it_s) { const QString& accountId = (*it_s).accountId(); if (!(*it_s).shares().isZero() && subAccountsList.contains(accountId)) { subAccountsList.removeOne(accountId); m_config.addAccount(accountId); } } } } else { // if not an investment-only report or explicitly including unused accounts // add all investment subaccounts m_config.addAccount(subAccountsList); } } } diff --git a/kmymoney/widgets/kmymoneyreportconfigtab3decl.ui b/kmymoney/widgets/kmymoneyreportconfigtab3decl.ui index 853abcae3..f2c0ea907 100644 --- a/kmymoney/widgets/kmymoneyreportconfigtab3decl.ui +++ b/kmymoney/widgets/kmymoneyreportconfigtab3decl.ui @@ -1,460 +1,520 @@ - - - - - kMyMoneyReportConfigTab3Decl - - - - 0 - 0 - 617 - 267 - - - - - 1 - 1 - 0 - 0 - - - - Rows/Columns Tab - - - - - - <p>On this tab, you configure how you would like the rows and columns to be selected and organized.</p> - - - - - - - - - 1 - 0 - 0 - 0 - - - - - - - Organize by: - - - false - - - - - - - true - - - - 1 - 0 - 0 - 0 - - - - <p>Choose how to group the transactions in this report</p> - - - - Categories - - - - - Top Categories - - - - - Tags - - - - - Payees - - - - - Accounts - - - - - Top Accounts - - - - - Month - - - - - Week - - - - - - - - - 358 - 16 - - - - QSizePolicy::Expanding - - - Qt::Horizontal - - - - - - - - - - - true - - - - 1 - 0 - 0 - 0 - - - - Show Columns - - - <p>Choose which columns should be shown in the report.</p><p>The date and transaction amount are always shown.</p> - - - - 2 - - - - - - 0 - 0 - - - - Memo - - - <p>Select this option to show the Memo column</p> - - - buttonGroup1 - - - - - - - Shares - - - <p>Select this option to show the Shares column for investments</p> - - - buttonGroup1 - - - - - - - Price - - - <p>Select this option to show the Price column for investments</p> - - - buttonGroup1 - - - - - - - Reconciled - - - <p>Select this option to show the Reconciled column</p> - - - buttonGroup1 - - - - - - - Account - - - <p>Select this option to show the Account column</p> - - - buttonGroup1 - - - - - - - - 0 - 0 - - - - Number - - - <p>Select this option to show the Number column</p> - - - buttonGroup1 - - - - - - - - 0 - 0 - - - - Tag - - - <p>Select this option to show the Tag column</p> - - - buttonGroup1 - - - - - - - - 0 - 0 - - - - Payee - - - <p>Select this option to show the Payee column</p> - - - buttonGroup1 - - - - - - - - 0 - 0 - - - - Category - - - <p>Select this option to show the Category column</p> - - - buttonGroup1 - - - - - - - Action - - - <p>Select this option to show the Action column</p> - - - buttonGroup1 - - - - - - - Balance - - - <p>Select this option to show the Running balance column</p> - - - buttonGroup1 - - - - - - - - - - - 205 - 20 - - - - QSizePolicy::Expanding - - - Qt::Horizontal - - - - - - - - - - - Include only Loan accounts - - - - - - - Include only Investment accounts - - - <p>Check this box to include only those categories which have been marked to "Include on Tax Reports"</p> - - - - - - - Hide Split Transaction Details - - - Do not display the individual transactions that make up a split transaction - - - - - - - Include only Tax categories - - - <p>Check this box to include only those categories which have been marked to "Include on Tax Reports"</p> - - - - - - - - - - 20 - 16 - + + kMyMoneyReportConfigTab3Decl + + + + 0 + 0 + 730 + 267 + + + + + 0 + 0 + + + + Rows/Columns Tab + + + + + + <p>On this tab, you configure how you would like the rows and columns to be selected and organized.</p> + + + + + + + + + 0 + 0 + + + + + + + Organize by: + + + false + + + + + + + true + + + + 0 + 0 + + + + <p>Choose how to group the transactions in this report</p> + + + + Categories + + + + + Top Categories + + + + + Tags + + + + + Payees + + + + + Accounts + + + + + Top Accounts + + + + + Month + + + + + Week + + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 358 + 16 + + + + + + + + + + + + true + + + + 0 + 0 + + + + <p>Choose which columns should be shown in the report.</p><p>The date and transaction amount are always shown.</p> + + + Show Columns + + + + 2 + + + + + + 0 + 0 + + + + <p>Select this option to show the Memo column</p> + + + Memo + + + buttonGroup1 + + + + + + + <p>Select this option to show the Shares column for investments</p> + + + Shares + + + buttonGroup1 + + + + + + + <p>Select this option to show the Price column for investments</p> + + + Price + + + buttonGroup1 + + + + + + + <p>Select this option to show the Reconciled column</p> + + + Reconciled + + + buttonGroup1 + + + + + + + <p>Select this option to show the Account column</p> + + + Account + + + buttonGroup1 + + + + + + + + 0 + 0 + + + + <p>Select this option to show the Number column</p> - - QSizePolicy::Expanding + + Number - - Qt::Vertical + + buttonGroup1 + + + + + + + + 0 + 0 + - - + + <p>Select this option to show the Tag column</p> + + + Tag + + + buttonGroup1 + + + + + + + + 0 + 0 + + + + <p>Select this option to show the Payee column</p> + + + Payee + + + buttonGroup1 + + + + + + + + 0 + 0 + + + + <p>Select this option to show the Category column</p> + + + Category + + + buttonGroup1 + + + + + + + <p>Select this option to show the Action column</p> + + + Action + + + buttonGroup1 + + + + + + + <p>Select this option to show the Running balance column</p> + + + Balance + + + buttonGroup1 + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 205 + 20 + + + + + + + + + + + + Include only Loan accounts + + + + + + + <p>Check this box to include only those categories which have been marked to "Include on Tax Reports"</p> + + + Include only Investment accounts + + + + + + + Do not display the individual transactions that make up a split transaction + + + Hide Split Transaction Details + + + + + + + <p>Check this box to include only those categories which have been marked to "Include on Tax Reports"</p> + + + Include only Tax categories + + + + + + + Do not display the transactions, leaving only totals displayed. + + + Hide Transactions + + + - - - - - m_checkTax - toggled(bool) - m_checkInvestments - setDisabled(bool) - - - m_checkTax - toggled(bool) - m_checkLoans - setDisabled(bool) - - - m_checkInvestments - toggled(bool) - m_checkTax - setDisabled(bool) - - - m_checkInvestments - toggled(bool) - m_checkLoans - setDisabled(bool) - - - m_checkLoans - toggled(bool) - m_checkTax - setDisabled(bool) - - - m_checkLoans - toggled(bool) - m_checkInvestments - setDisabled(bool) - - - - - KComboBox - QComboBox -
kcombobox.h
-
-
- - - +
+ + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 16 + + + + + + + + + + KComboBox + QComboBox +
kcombobox.h
+
+
+ + + + m_checkTax + toggled(bool) + m_checkInvestments + setDisabled(bool) + + + 20 + 20 + + + 20 + 20 + + + + + m_checkTax + toggled(bool) + m_checkLoans + setDisabled(bool) + + + 20 + 20 + + + 20 + 20 + + + + + m_checkInvestments + toggled(bool) + m_checkTax + setDisabled(bool) + + + 20 + 20 + + + 20 + 20 + + + + + m_checkInvestments + toggled(bool) + m_checkLoans + setDisabled(bool) + + + 20 + 20 + + + 20 + 20 + + + + + m_checkLoans + toggled(bool) + m_checkTax + setDisabled(bool) + + + 20 + 20 + + + 20 + 20 + + + + + m_checkLoans + toggled(bool) + m_checkInvestments + setDisabled(bool) + + + 20 + 20 + + + 20 + 20 + + + + + + +
diff --git a/kmymoney/widgets/kmymoneyreportconfigtabimpl.cpp b/kmymoney/widgets/kmymoneyreportconfigtabimpl.cpp index c465994c0..0db2ef213 100644 --- a/kmymoney/widgets/kmymoneyreportconfigtabimpl.cpp +++ b/kmymoney/widgets/kmymoneyreportconfigtabimpl.cpp @@ -1,236 +1,244 @@ /* This file is part of the KDE project Copyright (C) 2009 Laurent Montel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kmymoneyreportconfigtabimpl.h" #include "kmymoneyglobalsettings.h" #include #include #include "ui_kmymoneyreportconfigtab1decl.h" #include "ui_kmymoneyreportconfigtab2decl.h" #include "ui_kmymoneyreportconfigtab3decl.h" #include "ui_kmymoneyreportconfigtabchartdecl.h" #include "ui_kmymoneyreportconfigtabrangedecl.h" #include #include "mymoney/mymoneyreport.h" kMyMoneyReportConfigTab1Decl::kMyMoneyReportConfigTab1Decl(QWidget *parent) : QWidget(parent) { ui = new Ui::kMyMoneyReportConfigTab1Decl; ui->setupUi(this); } kMyMoneyReportConfigTab1Decl::~kMyMoneyReportConfigTab1Decl() { delete ui; } kMyMoneyReportConfigTab2Decl::kMyMoneyReportConfigTab2Decl(QWidget *parent) : QWidget(parent) { ui = new Ui::kMyMoneyReportConfigTab2Decl; ui->setupUi(this); } kMyMoneyReportConfigTab2Decl::~kMyMoneyReportConfigTab2Decl() { delete ui; } kMyMoneyReportConfigTab3Decl::kMyMoneyReportConfigTab3Decl(QWidget *parent) : QWidget(parent) { ui = new Ui::kMyMoneyReportConfigTab3Decl; ui->setupUi(this); ui->buttonGroup1->setExclusive(false); ui->buttonGroup1->setId(ui->m_checkMemo, 0); ui->buttonGroup1->setId(ui->m_checkShares, 1); ui->buttonGroup1->setId(ui->m_checkPrice, 2); ui->buttonGroup1->setId(ui->m_checkReconciled, 3); ui->buttonGroup1->setId(ui->m_checkAccount, 4); ui->buttonGroup1->setId(ui->m_checkNumber, 5); ui->buttonGroup1->setId(ui->m_checkPayee, 6); ui->buttonGroup1->setId(ui->m_checkCategory, 7); ui->buttonGroup1->setId(ui->m_checkAction, 8); ui->buttonGroup1->setId(ui->m_checkBalance, 9); + connect(ui->m_checkHideTransactions, SIGNAL(toggled(bool)), this, SLOT(slotHideTransactionsChanged(bool))); +} + +void kMyMoneyReportConfigTab3Decl::slotHideTransactionsChanged(bool checked) +{ + if (checked) // toggle m_checkHideSplitDetails only if it's mandatory + ui->m_checkHideSplitDetails->setChecked(checked); + ui->m_checkHideSplitDetails->setEnabled(!checked); // hiding transactions without hiding splits isn't allowed } kMyMoneyReportConfigTab3Decl::~kMyMoneyReportConfigTab3Decl() { delete ui; } kMyMoneyReportConfigTabChartDecl::kMyMoneyReportConfigTabChartDecl(QWidget *parent) : QWidget(parent) { ui = new Ui::kMyMoneyReportConfigTabChartDecl; ui->setupUi(this); ui->m_comboType->addItem(i18nc("type of graphic chart", "Line"), MyMoneyReport::eChartLine); ui->m_comboType->addItem(i18nc("type of graphic chart", "Bar"), MyMoneyReport::eChartBar); ui->m_comboType->addItem(i18nc("type of graphic chart", "Stacked Bar"), MyMoneyReport::eChartStackedBar); ui->m_comboType->addItem(i18nc("type of graphic chart", "Pie"), MyMoneyReport::eChartPie); ui->m_comboType->addItem(i18nc("type of graphic chart", "Ring"), MyMoneyReport::eChartRing); connect(ui->m_comboType, SIGNAL(currentIndexChanged(int)), this, SLOT(slotChartTypeChanged(int))); emit ui->m_comboType->currentIndexChanged(ui->m_comboType->currentIndex()); } kMyMoneyReportConfigTabChartDecl::~kMyMoneyReportConfigTabChartDecl() { delete ui; } void kMyMoneyReportConfigTabChartDecl::slotChartTypeChanged(int index) { if (index == MyMoneyReport::EChartType::eChartPie || index == MyMoneyReport::EChartType::eChartRing) { ui->m_checkCHGridLines->setText(i18n("Show circular grid lines")); ui->m_checkSVGridLines->setText(i18n("Show sagittal grid lines")); ui->m_logYaxis->setChecked(false); ui->m_logYaxis->setEnabled(false); } else { ui->m_checkCHGridLines->setText(i18n("Show horizontal grid lines")); ui->m_checkSVGridLines->setText(i18n("Show vertical grid lines")); ui->m_logYaxis->setEnabled(true); } } kMyMoneyReportConfigTabRangeDecl::kMyMoneyReportConfigTabRangeDecl(QWidget *parent) : QWidget(parent) { ui = new Ui::kMyMoneyReportConfigTabRangeDecl; ui->setupUi(this); m_dateRange = new DateRangeDlg(this->parentWidget()); ui->dateRangeGrid->addWidget(m_dateRange,0,0,1,2); MyDoubleValidator *dblVal = new MyDoubleValidator(KMyMoneyGlobalSettings::pricePrecision()); ui->m_dataRangeStart->setValidator(dblVal); ui->m_dataRangeEnd->setValidator(dblVal); ui->m_dataMajorTick->setValidator(dblVal); ui->m_dataMinorTick->setValidator(dblVal); connect(ui->m_dataRangeStart, SIGNAL(editingFinished()), this, SLOT(slotEditingFinishedStart())); connect(ui->m_dataRangeEnd, SIGNAL(editingFinished()), this, SLOT(slotEditingFinishedEnd())); connect(ui->m_dataMajorTick, SIGNAL(editingFinished()), this, SLOT(slotEditingFinishedMajor())); connect(ui->m_dataMinorTick, SIGNAL(editingFinished()), this, SLOT(slotEditingFinishedMinor())); connect(ui->m_dataLock, SIGNAL(currentIndexChanged(int)), this, SLOT(slotDataLockChanged(int))); emit ui->m_dataLock->currentIndexChanged(ui->m_dataLock->currentIndex()); } kMyMoneyReportConfigTabRangeDecl::~kMyMoneyReportConfigTabRangeDecl() { delete ui; } void kMyMoneyReportConfigTabRangeDecl::setRangeLogarythmic(bool set) { // major and minor tick have no influence if axis is logarithmic so hide them if (set) { ui->lblDataMajorTick->hide(); ui->lblDataMinorTick->hide(); ui->m_dataMajorTick->hide(); ui->m_dataMinorTick->hide(); } else { ui->lblDataMajorTick->show(); ui->lblDataMinorTick->show(); ui->m_dataMajorTick->show(); ui->m_dataMinorTick->show(); } } void kMyMoneyReportConfigTabRangeDecl::slotEditingFinished(EDimension dim) { qreal dataRangeStart = locale().toDouble(ui->m_dataRangeStart->text()); qreal dataRangeEnd = locale().toDouble(ui->m_dataRangeEnd->text()); qreal dataMajorTick = locale().toDouble(ui->m_dataMajorTick->text()); qreal dataMinorTick = locale().toDouble(ui->m_dataMinorTick->text()); if (dataRangeEnd < dataRangeStart) { // end must be higher than start if (dim == eRangeEnd) { ui->m_dataRangeStart->setText(ui->m_dataRangeEnd->text()); dataRangeStart = dataRangeEnd; } else { ui->m_dataRangeEnd->setText(ui->m_dataRangeStart->text()); dataRangeEnd = dataRangeStart; } } if ((dataRangeStart != 0 || dataRangeEnd != 0)) { // if data range isn't going to be reset if ((dataRangeEnd - dataRangeStart) < dataMajorTick) // major tick cannot be greater than data range dataMajorTick = dataRangeEnd - dataRangeStart; if (dataMajorTick != 0 && // if major tick isn't going to be reset dataMajorTick < (dataRangeEnd - dataRangeStart) * 0.01) // constraint major tick to be greater or equal to 1% of data range dataMajorTick = (dataRangeEnd - dataRangeStart) * 0.01; // that should produce more than 256 Y labels in KReportChartView::slotNeedUpdate ui->m_dataMajorTick->setText(locale().toString(dataMajorTick, 'f', KMyMoneySettings::pricePrecision()).remove(locale().groupSeparator()).remove(QRegularExpression("0+$")).remove(QRegularExpression("\\" + locale().decimalPoint() + "$"))); } if (dataMajorTick < dataMinorTick) { // major tick must be higher than minor if (dim == eMinorTick) { ui->m_dataMajorTick->setText(ui->m_dataMinorTick->text()); dataMajorTick = dataMinorTick; } else { ui->m_dataMinorTick->setText(ui->m_dataMajorTick->text()); dataMinorTick = dataMajorTick; } } if (dataMinorTick < dataMajorTick * 0.1) { // constraint minor tick to be greater or equal to 10% of major tick dataMinorTick = dataMajorTick * 0.1; ui->m_dataMinorTick->setText(locale().toString(dataMinorTick, 'f', KMyMoneySettings::pricePrecision()).remove(locale().groupSeparator()).remove(QRegularExpression("0+$")).remove(QRegularExpression("\\" + locale().decimalPoint() + "$"))); } } void kMyMoneyReportConfigTabRangeDecl::slotEditingFinishedStart() { slotEditingFinished(eRangeStart); } void kMyMoneyReportConfigTabRangeDecl::slotEditingFinishedEnd() { slotEditingFinished(eRangeEnd); } void kMyMoneyReportConfigTabRangeDecl::slotEditingFinishedMajor() { slotEditingFinished(eMajorTick); } void kMyMoneyReportConfigTabRangeDecl::slotEditingFinishedMinor() { slotEditingFinished(eMinorTick); } void kMyMoneyReportConfigTabRangeDecl::slotDataLockChanged(int index) { if (index == MyMoneyReport::dataOptionE::automatic) { ui->m_dataRangeStart->setText(QStringLiteral("0")); ui->m_dataRangeEnd->setText(QStringLiteral("0")); ui->m_dataMajorTick->setText(QStringLiteral("0")); ui->m_dataMinorTick->setText(QStringLiteral("0")); ui->m_dataRangeStart->setEnabled(false); ui->m_dataRangeEnd->setEnabled(false); ui->m_dataMajorTick->setEnabled(false); ui->m_dataMinorTick->setEnabled(false); } else { ui->m_dataRangeStart->setEnabled(true); ui->m_dataRangeEnd->setEnabled(true); ui->m_dataMajorTick->setEnabled(true); ui->m_dataMinorTick->setEnabled(true); } } diff --git a/kmymoney/widgets/kmymoneyreportconfigtabimpl.h b/kmymoney/widgets/kmymoneyreportconfigtabimpl.h index 5034be234..ed2533cbc 100644 --- a/kmymoney/widgets/kmymoneyreportconfigtabimpl.h +++ b/kmymoney/widgets/kmymoneyreportconfigtabimpl.h @@ -1,131 +1,134 @@ /* This file is part of the KDE project Copyright (C) 2009 Laurent Montel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KMYMONEYREPORTCONFIGTABIMPL_H #define KMYMONEYREPORTCONFIGTABIMPL_H #include #include class DateRangeDlg; namespace Ui { class kMyMoneyReportConfigTab1Decl; class kMyMoneyReportConfigTab2Decl; class kMyMoneyReportConfigTab3Decl; class kMyMoneyReportConfigTabChartDecl; class kMyMoneyReportConfigTabRangeDecl; } class kMyMoneyReportConfigTab1Decl : public QWidget { public: kMyMoneyReportConfigTab1Decl(QWidget *parent); virtual ~kMyMoneyReportConfigTab1Decl(); private: Ui::kMyMoneyReportConfigTab1Decl* ui; }; class kMyMoneyReportConfigTab2Decl : public QWidget { public: kMyMoneyReportConfigTab2Decl(QWidget *parent); virtual ~kMyMoneyReportConfigTab2Decl(); private: Ui::kMyMoneyReportConfigTab2Decl* ui; }; class kMyMoneyReportConfigTab3Decl : public QWidget { + Q_OBJECT public: kMyMoneyReportConfigTab3Decl(QWidget *parent); virtual ~kMyMoneyReportConfigTab3Decl(); private: Ui::kMyMoneyReportConfigTab3Decl* ui; +private slots: + void slotHideTransactionsChanged(bool checked); }; class kMyMoneyReportConfigTabChartDecl : public QWidget { Q_OBJECT public: kMyMoneyReportConfigTabChartDecl(QWidget *parent); virtual ~kMyMoneyReportConfigTabChartDecl(); Ui::kMyMoneyReportConfigTabChartDecl* ui; private slots: void slotChartTypeChanged(int index); }; class kMyMoneyReportConfigTabRangeDecl : public QWidget { Q_OBJECT public: kMyMoneyReportConfigTabRangeDecl(QWidget *parent); virtual ~kMyMoneyReportConfigTabRangeDecl(); Ui::kMyMoneyReportConfigTabRangeDecl* ui; DateRangeDlg *m_dateRange; void setRangeLogarythmic(bool set); private: enum EDimension { eRangeStart = 0, eRangeEnd, eMajorTick, eMinorTick}; private slots: void slotEditingFinished(EDimension dim); void slotEditingFinishedStart(); void slotEditingFinishedEnd(); void slotEditingFinishedMajor(); void slotEditingFinishedMinor(); void slotDataLockChanged(int index); }; class MyDoubleValidator : public QDoubleValidator { public: MyDoubleValidator(int decimals, QObject * parent = 0) : QDoubleValidator(0, 0, decimals, parent) { } QValidator::State validate(QString &s, int &i) const { Q_UNUSED(i); if (s.isEmpty() || s == "-") { return QValidator::Intermediate; } QChar decimalPoint = locale().decimalPoint(); if(s.indexOf(decimalPoint) != -1) { int charsAfterPoint = s.length() - s.indexOf(decimalPoint) - 1; if (charsAfterPoint > decimals()) { return QValidator::Invalid; } } bool ok; locale().toDouble(s, &ok); if (ok) { return QValidator::Acceptable; } else { return QValidator::Invalid; } } }; #endif /* KMYMONEYREPORTCONFIGTABIMPL_H */