diff --git a/kmymoney/mymoney/mymoneyreport.h b/kmymoney/mymoney/mymoneyreport.h --- a/kmymoney/mymoney/mymoneyreport.h +++ b/kmymoney/mymoney/mymoneyreport.h @@ -3,6 +3,7 @@ * Copyright 2006 Darren Gould * Copyright 2007-2010 Alvaro Soliverez * Copyright 2017-2018 Łukasz Wojniłowicz + * Copyright 2018 Michael Kiefer * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -169,6 +170,9 @@ bool isLogYAxis() const; void setLogYAxis(bool f); + bool isNegExpenses() const; + void setNegExpenses(bool f); + QString dataRangeStart() const; void setDataRangeStart(const QString& f); diff --git a/kmymoney/mymoney/mymoneyreport.cpp b/kmymoney/mymoney/mymoneyreport.cpp --- a/kmymoney/mymoney/mymoneyreport.cpp +++ b/kmymoney/mymoney/mymoneyreport.cpp @@ -3,6 +3,7 @@ * Copyright 2006 Darren Gould * Copyright 2007-2010 Alvaro Soliverez * Copyright 2017-2018 Łukasz Wojniłowicz + * Copyright 2018 Michael Kiefer * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -460,6 +461,18 @@ d->m_logYaxis = f; } +bool MyMoneyReport::isNegExpenses() const +{ + Q_D(const MyMoneyReport); + return d->m_negExpenses; +} + +void MyMoneyReport::setNegExpenses(bool f) +{ + Q_D(MyMoneyReport); + d->m_negExpenses = f; +} + QString MyMoneyReport::dataRangeStart() const { Q_D(const MyMoneyReport); diff --git a/kmymoney/mymoney/mymoneyreport_p.h b/kmymoney/mymoney/mymoneyreport_p.h --- a/kmymoney/mymoney/mymoneyreport_p.h +++ b/kmymoney/mymoney/mymoneyreport_p.h @@ -3,6 +3,7 @@ * Copyright 2006 Darren Gould * Copyright 2007-2010 Alvaro Soliverez * Copyright 2017-2018 Łukasz Wojniłowicz + * Copyright 2018 Michael Kiefer * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -67,6 +68,7 @@ m_chartByDefault(false), m_chartLineWidth(MyMoneyReport::m_lineWidth), m_logYaxis(false), + m_negExpenses(false), m_dataRangeStart('0'), m_dataRangeEnd('0'), m_dataMajorTick('0'), @@ -246,6 +248,11 @@ */ bool m_logYaxis; + /** + * Whether expenses should be plotted downwards + */ + bool m_negExpenses; + /** * Y data range */ diff --git a/kmymoney/plugins/views/reports/core/kreportchartview.h b/kmymoney/plugins/views/reports/core/kreportchartview.h --- a/kmymoney/plugins/views/reports/core/kreportchartview.h +++ b/kmymoney/plugins/views/reports/core/kreportchartview.h @@ -2,6 +2,7 @@ * Copyright 2005 Ace Jones * Copyright 2005-2018 Thomas Baumgart * Copyright 2017-2018 Łukasz Wojniłowicz + * Copyright 2018 Michael Kiefer * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -79,7 +80,7 @@ /** * Draw a PivotGridRow in a chart */ - int drawPivotGridRow(int rowNum, const PivotGridRow& gridRow, const QString& legendText, const int startColumn = 0, const int columnsToDraw = 0, const int precision = 2); + int drawPivotGridRow(int rowNum, const PivotGridRow& gridRow, const QString& legendText, const int startColumn = 0, const int columnsToDraw = 0, const int precision = 2, const bool invertValue = false); /** * Set cell data diff --git a/kmymoney/plugins/views/reports/core/kreportchartview.cpp b/kmymoney/plugins/views/reports/core/kreportchartview.cpp --- a/kmymoney/plugins/views/reports/core/kreportchartview.cpp +++ b/kmymoney/plugins/views/reports/core/kreportchartview.cpp @@ -2,6 +2,7 @@ * Copyright 2005 Ace Jones * Copyright 2005-2018 Thomas Baumgart * Copyright 2017-2018 Łukasz Wojniłowicz + * Copyright 2018 Michael Kiefer * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -292,6 +293,8 @@ // iterate over outer groups PivotGrid::const_iterator it_outergroup = grid.begin(); while (it_outergroup != grid.end()) { + //determine whether expenses should be displayed as negative + const bool invertValue = (config.isNegExpenses() && (*it_outergroup).m_inverted); // iterate over inner groups PivotOuterGroup::const_iterator it_innergroup = (*it_outergroup).begin(); while (it_innergroup != (*it_outergroup).end()) { @@ -333,7 +336,7 @@ //set the cell value and tooltip rowNum = drawPivotGridRow(rowNum, it_row.value().value(myRowTypeList.at(i)), config.isChartDataLabels() ? legendText : QString(), - 0, numberColumns, precision); + 0, numberColumns, precision, invertValue); } } ++it_row; @@ -349,7 +352,8 @@ // iterate over outer groups PivotGrid::const_iterator it_outergroup = grid.begin(); while (it_outergroup != grid.end()) { - + //determine whether expenses should be displayed as negative + const bool invertValue = (config.isNegExpenses() && (*it_outergroup).m_inverted); // iterate over inner groups PivotOuterGroup::const_iterator it_innergroup = (*it_outergroup).begin(); while (it_innergroup != (*it_outergroup).end()) { @@ -370,7 +374,7 @@ //set the cell value and tooltip rowNum = drawPivotGridRow(rowNum, (*it_innergroup).m_total.value(myRowTypeList.at(i)), config.isChartDataLabels() ? legendText : QString(), - 0, numberColumns, precision); + 0, numberColumns, precision, invertValue); } ++it_innergroup; } @@ -383,6 +387,8 @@ // iterate over outer groups PivotGrid::const_iterator it_outergroup = grid.begin(); while (it_outergroup != grid.end()) { + //determine whether expenses should be displayed as negative + const bool invertValue = (config.isNegExpenses() && (*it_outergroup).m_inverted); // iterate row types for (int i = 0 ; i < myRowTypeListSize; ++i) { QString legendText; @@ -400,7 +406,7 @@ //set the cell value and tooltip rowNum = drawPivotGridRow(rowNum, (*it_outergroup).m_total.value(myRowTypeList.at(i)), config.isChartDataLabels() ? legendText : QString(), - 0, numberColumns, precision); + 0, numberColumns, precision, invertValue); } ++it_outergroup; } @@ -424,7 +430,7 @@ //set the cell value and tooltip rowNum = drawPivotGridRow(rowNum, grid.m_total.value(myRowTypeList.at(i)), config.isChartDataLabels() ? legendText : QString(), - 0, numberColumns, precision); + 0, numberColumns, precision, false); } } } @@ -450,20 +456,20 @@ if (myRowTypeList.at(i) == eActual) rowNum = drawPivotGridRow(rowNum, grid.m_total.value(myRowTypeList.at(i)), config.isChartDataLabels() ? legendText : QString(), - 0, config.currentDateColumn(), precision); + 0, config.currentDateColumn(), precision, false); else if (myRowTypeList.at(i)== eForecast) { rowNum = drawPivotGridRow(rowNum, grid.m_total.value(myRowTypeList.at(i)), config.isChartDataLabels() ? legendText : QString(), - config.currentDateColumn(), numberColumns - config.currentDateColumn(), precision); + config.currentDateColumn(), numberColumns - config.currentDateColumn(), precision, false); } else rowNum = drawPivotGridRow(rowNum, grid.m_total.value(myRowTypeList.at(i)), config.isChartDataLabels() ? legendText : QString(), - 0, numberColumns, precision); + 0, numberColumns, precision, false); } else rowNum = drawPivotGridRow(rowNum, grid.m_total.value(myRowTypeList.at(i)), config.isChartDataLabels() ? legendText : QString(), - 0, numberColumns, precision); + 0, numberColumns, precision, false); } } @@ -642,7 +648,7 @@ barDiagram->axes().at(1)->setLabels(labels); } -int KReportChartView::drawPivotGridRow(int rowNum, const PivotGridRow& gridRow, const QString& legendText, const int startColumn, const int columnsToDraw, const int precision) +int reports::KReportChartView::drawPivotGridRow ( int rowNum, const reports::PivotGridRow& gridRow, const QString& legendText, const int startColumn, const int columnsToDraw, const int precision, const bool invertValue ) { // Columns const QString toolTip = QStringLiteral("

%1

%2
"); @@ -672,6 +678,8 @@ QStandardItem* item = new QStandardItem(); if (!m_skipZero || !gridRow.at(i).isZero()) { double value = gridRow.at(i).toDouble(); + if (invertValue) + value = -value; item->setData(QVariant(value), Qt::DisplayRole); if (isToolTip) item->setToolTip(toolTip.arg(legendText).arg(value, 0, 'f', precision)); diff --git a/kmymoney/plugins/views/reports/kreportconfigurationfilterdlg.h b/kmymoney/plugins/views/reports/kreportconfigurationfilterdlg.h --- a/kmymoney/plugins/views/reports/kreportconfigurationfilterdlg.h +++ b/kmymoney/plugins/views/reports/kreportconfigurationfilterdlg.h @@ -11,6 +11,7 @@ Kevin Tambascio Ace Jones (C) 2017, 2018 by Łukasz Wojniłowicz + 2018 by Michael Kiefer ***************************************************************************/ /*************************************************************************** @@ -66,6 +67,7 @@ void slotUpdateColumnsCombo(); void slotUpdateColumnsCombo(int idx); void slotLogAxisChanged(int state); + void slotNegExpensesChanged(int state); private: Q_DECLARE_PRIVATE(KReportConfigurationFilterDlg) diff --git a/kmymoney/plugins/views/reports/kreportconfigurationfilterdlg.cpp b/kmymoney/plugins/views/reports/kreportconfigurationfilterdlg.cpp --- a/kmymoney/plugins/views/reports/kreportconfigurationfilterdlg.cpp +++ b/kmymoney/plugins/views/reports/kreportconfigurationfilterdlg.cpp @@ -11,6 +11,7 @@ Kevin Tambascio Ace Jones (C) 2017, 2018 by Łukasz Wojniłowicz + 2018 by Michael Kiefer ***************************************************************************/ /*************************************************************************** @@ -165,6 +166,7 @@ connect(d->m_tabRange->ui->m_comboColumns, static_cast(&QComboBox::activated), this, static_cast(&KReportConfigurationFilterDlg::slotUpdateColumnsCombo)); } connect(d->m_tabChart->ui->m_logYaxis, &QCheckBox::stateChanged, this, &KReportConfigurationFilterDlg::slotLogAxisChanged); + connect(d->m_tabChart->ui->m_negExpenses, &QCheckBox::stateChanged, this, &KReportConfigurationFilterDlg::slotNegExpensesChanged); } else if (d->m_initialState.reportType() == eMyMoney::Report::ReportType::QueryTable) { // eInvestmentHoldings is a special-case report, and you cannot configure the // rows & columns of that report. @@ -310,6 +312,7 @@ d->m_currentState.setChartByDefault(d->m_tabChart->ui->m_checkShowChart->isChecked()); d->m_currentState.setChartLineWidth(d->m_tabChart->ui->m_lineWidth->value()); d->m_currentState.setLogYAxis(d->m_tabChart->ui->m_logYaxis->isChecked()); + d->m_currentState.setNegExpenses(d->m_tabChart->ui->m_negExpenses->isChecked()); } if (d->m_tabRange) { @@ -388,6 +391,12 @@ d->m_tabRange->setRangeLogarythmic(false); } +void KReportConfigurationFilterDlg::slotNegExpensesChanged(int state) +{ + Q_D(KReportConfigurationFilterDlg); + d->m_tabChart->setNegExpenses(state == Qt::Checked); +} + void KReportConfigurationFilterDlg::slotReset() { Q_D(KReportConfigurationFilterDlg); @@ -554,6 +563,7 @@ d->m_tabChart->ui->m_checkShowChart->setChecked(d->m_initialState.isChartByDefault()); d->m_tabChart->ui->m_lineWidth->setValue(d->m_initialState.chartLineWidth()); d->m_tabChart->ui->m_logYaxis->setChecked(d->m_initialState.isLogYAxis()); + d->m_tabChart->ui->m_negExpenses->setChecked(d->m_initialState.isNegExpenses()); } if (d->m_tabRange) { diff --git a/kmymoney/plugins/views/reports/kreportsview_p.h b/kmymoney/plugins/views/reports/kreportsview_p.h --- a/kmymoney/plugins/views/reports/kreportsview_p.h +++ b/kmymoney/plugins/views/reports/kreportsview_p.h @@ -11,6 +11,7 @@ Kevin Tambascio Ace Jones (C) 2017 Łukasz Wojniłowicz + 2018 Michael Kiefer ***************************************************************************/ /*************************************************************************** @@ -851,6 +852,19 @@ list.back().setChartType(eMyMoney::Report::ChartType::Line); list.back().setChartDataLabels(false); + list.push_back(MyMoneyReport( + eMyMoney::Report::RowType::ExpenseIncome, + static_cast(eMyMoney::Report::ColumnType::Months), + TransactionFilter::Date::Last12Months, + eMyMoney::Report::DetailLevel::Top, + i18n("Income and Expenses Bar Graph"), + i18n("Default Report") + )); + list.back().setChartByDefault(true); + list.back().setChartType(eMyMoney::Report::ChartType::StackedBar); + list.back().setChartDataLabels(false); + list.back().setNegExpenses(true); + list.push_back(MyMoneyReport( eMyMoney::Report::RowType::ExpenseIncome, static_cast(eMyMoney::Report::ColumnType::Months), diff --git a/kmymoney/plugins/views/reports/reporttabchart.ui b/kmymoney/plugins/views/reports/reporttabchart.ui --- a/kmymoney/plugins/views/reports/reporttabchart.ui +++ b/kmymoney/plugins/views/reports/reporttabchart.ui @@ -108,6 +108,13 @@ + + + + Plot expenses downwards + + + @@ -192,6 +199,7 @@ m_checkValues m_checkShowChart m_logYaxis + m_negExpenses m_lineWidth diff --git a/kmymoney/plugins/views/reports/reporttabimpl.h b/kmymoney/plugins/views/reports/reporttabimpl.h --- a/kmymoney/plugins/views/reports/reporttabimpl.h +++ b/kmymoney/plugins/views/reports/reporttabimpl.h @@ -1,6 +1,7 @@ /* This file is part of the KDE project Copyright (C) 2009 Laurent Montel (C) 2017 by Łukasz Wojniłowicz + 2018 by Michael Kiefer This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -83,6 +84,7 @@ ~ReportTabChart(); Ui::ReportTabChart* ui; + void setNegExpenses(bool set); private Q_SLOTS: void slotChartTypeChanged(int index); diff --git a/kmymoney/plugins/views/reports/reporttabimpl.cpp b/kmymoney/plugins/views/reports/reporttabimpl.cpp --- a/kmymoney/plugins/views/reports/reporttabimpl.cpp +++ b/kmymoney/plugins/views/reports/reporttabimpl.cpp @@ -1,6 +1,7 @@ /* This file is part of the KDE project Copyright (C) 2009 Laurent Montel (C) 2017 by Łukasz Wojniłowicz + Copyright 2018 Michael Kiefer This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -117,10 +118,24 @@ ui->m_checkSVGridLines->setText(i18n("Show sagittal grid lines")); ui->m_logYaxis->setChecked(false); ui->m_logYaxis->setEnabled(false); + ui->m_negExpenses->setChecked(false); + ui->m_negExpenses->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); + ui->m_negExpenses->setEnabled(true); + } +} + +void ReportTabChart::setNegExpenses(bool set) +{ + // logarithm on negative numbers does not make sense, so disable it + if (set) { + ui->m_logYaxis->setChecked(false); + ui->m_logYaxis->setEnabled(false); + } else { + ui->m_logYaxis->setEnabled(true); } } diff --git a/kmymoney/plugins/xmlhelper/xmlstoragehelper.cpp b/kmymoney/plugins/xmlhelper/xmlstoragehelper.cpp --- a/kmymoney/plugins/xmlhelper/xmlstoragehelper.cpp +++ b/kmymoney/plugins/xmlhelper/xmlstoragehelper.cpp @@ -3,6 +3,7 @@ * Copyright 2006 Darren Gould * Copyright 2007-2010 Alvaro Soliverez * Copyright 2017-2018 Łukasz Wojniłowicz + * Copyright 2018 Michael Kiefer * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -77,7 +78,8 @@ ColumnsAreDays, ChartType, ChartCHGridLines, ChartSVGridLines, ChartDataLabels, ChartByDefault, - LogYAxis, ChartLineWidth, ColumnType, RowType, + LogYAxis, NegExpenses, + ChartLineWidth, ColumnType, RowType, DataRangeStart, DataRangeEnd, DataMajorTick, DataMinorTick, YLabelsPrecision, QueryColumns, @@ -692,6 +694,7 @@ report.setChartDataLabels(node.attribute(attributeName(Attribute::Report::ChartDataLabels), "1").toUInt()); report.setChartByDefault(node.attribute(attributeName(Attribute::Report::ChartByDefault), "0").toUInt()); report.setLogYAxis(node.attribute(attributeName(Attribute::Report::LogYAxis), "0").toUInt()); + report.setNegExpenses(node.attribute(attributeName(Attribute::Report::NegExpenses), "0").toUInt()); report.setChartLineWidth(node.attribute(attributeName(Attribute::Report::ChartLineWidth), QString(MyMoneyReport::m_lineWidth)).toUInt()); // read range tab @@ -880,6 +883,7 @@ el.setAttribute(attributeName(Attribute::Report::ChartDataLabels), report.isChartDataLabels()); el.setAttribute(attributeName(Attribute::Report::ChartByDefault), report.isChartByDefault()); el.setAttribute(attributeName(Attribute::Report::LogYAxis), report.isLogYAxis()); + el.setAttribute(attributeName(Attribute::Report::NegExpenses), report.isNegExpenses()); el.setAttribute(attributeName(Attribute::Report::ChartLineWidth), report.chartLineWidth()); el.setAttribute(attributeName(Attribute::Report::ColumnType), reportNames(report.columnType())); el.setAttribute(attributeName(Attribute::Report::DataLock), reportNames(report.dataFilter()));