2012-02-05 15:54:09 +01:00
|
|
|
/*
|
|
|
|
Copyright 2010-2012 Grégory Soutadé
|
|
|
|
|
|
|
|
This file is part of KissCount.
|
|
|
|
|
|
|
|
KissCount 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 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
KissCount 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 General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with KissCount. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <QMessageBox>
|
2017-10-15 11:36:27 +02:00
|
|
|
#include <QLabel>
|
|
|
|
#include <QtCharts/QLineSeries>
|
|
|
|
#include <QtCharts/QCategoryAxis>
|
|
|
|
#include <QtCharts/QDateTimeAxis>
|
2012-02-05 15:54:09 +01:00
|
|
|
#include "StatsPanel.hpp"
|
|
|
|
|
2017-10-15 11:36:27 +02:00
|
|
|
using namespace QtCharts;
|
|
|
|
|
2012-06-29 20:33:33 +02:00
|
|
|
StatsPanel::StatsPanel(KissCount* kiss, wxUI *parent, bool lowResolution) :
|
2017-10-15 11:36:27 +02:00
|
|
|
KissPanel(kiss, parent, lowResolution), _chartView(0)
|
2012-02-05 15:54:09 +01:00
|
|
|
{
|
|
|
|
QHBoxLayout *hbox = new QHBoxLayout();
|
2017-10-15 11:36:27 +02:00
|
|
|
QHBoxLayout *hbox1 = new QHBoxLayout();
|
2012-02-05 15:54:09 +01:00
|
|
|
QVBoxLayout *vbox = new QVBoxLayout();
|
|
|
|
_hbox2 = new QHBoxLayout();
|
|
|
|
_vbox2 = new QVBoxLayout();
|
2012-02-11 11:40:09 +01:00
|
|
|
_vbox3 = new QVBoxLayout();
|
2013-02-26 15:34:52 +01:00
|
|
|
int i, nbCategories;
|
2012-02-05 15:54:09 +01:00
|
|
|
User* user = _kiss->GetUser();
|
|
|
|
std::vector<Account>::iterator accountIt;
|
|
|
|
std::vector<Category>::iterator categoryIt;
|
|
|
|
std::map<int, std::vector<int> > operations;
|
|
|
|
std::map<int, std::vector<int> >::iterator it;
|
|
|
|
QListWidgetItem* item;
|
|
|
|
|
2012-06-29 20:33:33 +02:00
|
|
|
_icons[KissPanel::LOW_RES_ICON] = STATS_LOW_ICON;
|
|
|
|
_icons[KissPanel::HIGH_RES_ICON] = STATS_ICON;
|
|
|
|
|
2012-02-05 15:54:09 +01:00
|
|
|
setLayout(vbox);
|
|
|
|
|
|
|
|
_monthFrom = new QComboBox(parent);
|
|
|
|
for(i=0; i<12; i++)
|
|
|
|
_monthFrom->addItem(wxUI::months[i]);
|
|
|
|
_yearFrom = new QComboBox(parent);
|
|
|
|
|
|
|
|
_monthTo = new QComboBox(parent);
|
|
|
|
for(i=0; i<12; i++)
|
|
|
|
_monthTo->addItem(wxUI::months[i]);
|
|
|
|
_yearTo = new QComboBox(parent);
|
|
|
|
|
|
|
|
operations = _kiss->GetAllOperations();
|
|
|
|
|
|
|
|
for(i=0, it = operations.begin(); it != operations.end(); it++, i++)
|
|
|
|
{
|
|
|
|
_yearFrom->addItem(QString::number(it->first));
|
|
|
|
_yearTo->addItem(QString::number(it->first));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i) i--;
|
|
|
|
|
|
|
|
_yearFrom->setCurrentIndex(i);
|
|
|
|
_yearTo->setCurrentIndex(i);
|
|
|
|
_monthFrom->setCurrentIndex(0);
|
|
|
|
_monthTo->setCurrentIndex(11);
|
|
|
|
|
|
|
|
QLabel* label = new QLabel(_("From"));
|
2017-10-15 11:36:27 +02:00
|
|
|
label->setAlignment(Qt::AlignRight);
|
|
|
|
hbox->addWidget(label, 1);
|
|
|
|
hbox->addWidget(_monthFrom, 2);
|
|
|
|
hbox->addWidget(_yearFrom, 2);
|
|
|
|
|
|
|
|
hbox->addStretch(1);
|
2012-02-05 15:54:09 +01:00
|
|
|
|
|
|
|
label = new QLabel(_("To"));
|
2017-10-15 11:36:27 +02:00
|
|
|
label->setAlignment(Qt::AlignRight);
|
|
|
|
hbox->addWidget(label, 1);
|
|
|
|
hbox->addWidget(_monthTo, 2);
|
|
|
|
hbox->addWidget(_yearTo, 2);
|
|
|
|
|
|
|
|
hbox->addStretch(1);
|
2012-02-05 15:54:09 +01:00
|
|
|
|
|
|
|
connect(_yearFrom, SIGNAL(currentIndexChanged(int)), this, SLOT(OnRangeChange(int)));
|
|
|
|
connect(_monthFrom, SIGNAL(currentIndexChanged(int)), this, SLOT(OnRangeChange(int)));
|
|
|
|
connect(_yearTo, SIGNAL(currentIndexChanged(int)), this, SLOT(OnRangeChange(int)));
|
|
|
|
connect(_monthTo, SIGNAL(currentIndexChanged(int)), this, SLOT(OnRangeChange(int)));
|
|
|
|
|
|
|
|
_account = new QListWidget(this);
|
|
|
|
for(i=0, accountIt = user->_accounts.begin(); accountIt != user->_accounts.end(); accountIt++, i++)
|
|
|
|
{
|
|
|
|
item = new QListWidgetItem(accountIt->name, _account);
|
2012-02-26 08:59:59 +01:00
|
|
|
if (accountIt->hidden)
|
|
|
|
item->setCheckState (Qt::Unchecked);
|
|
|
|
else
|
|
|
|
item->setCheckState (Qt::Checked);
|
2012-02-05 15:54:09 +01:00
|
|
|
}
|
|
|
|
|
2012-02-11 10:47:09 +01:00
|
|
|
_account->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
2017-10-15 11:36:27 +02:00
|
|
|
_account->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
|
2012-02-11 10:47:09 +01:00
|
|
|
|
2012-02-05 15:54:09 +01:00
|
|
|
connect(_account, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(OnAccountChange(QListWidgetItem*)));
|
|
|
|
|
|
|
|
_categories = new QString[user->GetCategoriesNumber()] ;
|
|
|
|
for(i=0, categoryIt = user->_categories.begin();
|
|
|
|
categoryIt != user->_categories.end();
|
|
|
|
categoryIt++, i++)
|
|
|
|
{
|
|
|
|
_categoriesIndexes[categoryIt->id] = i;
|
|
|
|
_categories[i] = _(categoryIt->name.toStdString().c_str()) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEFAULT_FONT(font);
|
|
|
|
|
2013-02-26 15:34:52 +01:00
|
|
|
_costRepartitionBanner = new CostRepartitionBanner(_kiss, this, _categories);
|
2012-02-05 15:54:09 +01:00
|
|
|
|
2017-10-15 11:36:27 +02:00
|
|
|
hbox1->addStretch(1);
|
|
|
|
hbox1->addWidget(_account, 2);
|
|
|
|
hbox1->addStretch(1);
|
|
|
|
_vbox3->addLayout(hbox1, 1);
|
2012-02-05 15:54:09 +01:00
|
|
|
|
2012-02-20 21:27:51 +01:00
|
|
|
nbCategories = user->GetCategoriesNumber();
|
2012-02-05 15:54:09 +01:00
|
|
|
|
2012-04-30 21:15:51 +02:00
|
|
|
_categoriesValues = new int[nbCategories];
|
2012-02-05 15:54:09 +01:00
|
|
|
for(i=0; i<nbCategories; i++)
|
2013-02-26 15:34:52 +01:00
|
|
|
_categoriesValues[i] = 0.0;
|
|
|
|
|
2017-10-15 11:36:27 +02:00
|
|
|
_vbox3->addWidget(_costRepartitionBanner, 3);
|
2012-02-05 15:54:09 +01:00
|
|
|
|
2012-02-11 11:40:09 +01:00
|
|
|
_vbox2->addLayout(hbox);
|
|
|
|
_hbox2->addLayout(_vbox2);
|
2012-02-05 15:54:09 +01:00
|
|
|
vbox->addLayout(_hbox2);
|
|
|
|
|
2012-02-26 14:23:49 +01:00
|
|
|
_hbox2->addLayout(_vbox3);
|
|
|
|
|
2017-10-15 11:36:27 +02:00
|
|
|
_hbox2->setStretch(0, 4);
|
|
|
|
_hbox2->setStretch(1, 1);
|
|
|
|
|
2012-02-05 15:54:09 +01:00
|
|
|
OnRangeChange(0);
|
|
|
|
|
|
|
|
layout();
|
|
|
|
}
|
|
|
|
|
|
|
|
KissPanel* StatsPanel::CreatePanel()
|
|
|
|
{
|
2012-06-29 20:33:33 +02:00
|
|
|
return new StatsPanel(_kiss, _wxUI, _lowResolution);
|
2012-02-05 15:54:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
QString StatsPanel::GetToolTip()
|
|
|
|
{
|
|
|
|
return _("Statistics");
|
|
|
|
}
|
|
|
|
|
|
|
|
void StatsPanel::UpdateStats(int monthFrom, int yearFrom, int monthTo, int yearTo)
|
|
|
|
{
|
2012-04-30 21:15:51 +02:00
|
|
|
std::map<int, std::map<int, std::map<int, int> > > accountAmounts;
|
|
|
|
std::map<int, int> categories;
|
2014-11-10 11:54:28 +01:00
|
|
|
std::map<int, int> tags;
|
2012-04-30 21:15:51 +02:00
|
|
|
std::map<int, std::vector<int> > operations;
|
2012-02-05 15:54:09 +01:00
|
|
|
std::vector<Account>::iterator accountIt;
|
2012-04-30 21:15:51 +02:00
|
|
|
std::map<int, int>::iterator categoriesIt;
|
|
|
|
std::map<int, std::map<int, int> >::iterator accountYearIt;
|
2013-02-26 15:34:52 +01:00
|
|
|
int total;
|
|
|
|
int account, size, i, a, b, nbDays;
|
2012-02-20 21:27:51 +01:00
|
|
|
QString value, v;
|
2012-02-05 15:54:09 +01:00
|
|
|
User* user = _kiss->GetUser();
|
|
|
|
QDate date;
|
|
|
|
bool failed;
|
2017-10-15 11:36:27 +02:00
|
|
|
QLineSeries * series = new QLineSeries();
|
|
|
|
QLineSeries * series0 = series;
|
|
|
|
QDateTimeAxis *axisX = new QDateTimeAxis;
|
|
|
|
QDateTime xValue;
|
2012-02-05 15:54:09 +01:00
|
|
|
|
2017-10-15 11:36:27 +02:00
|
|
|
if (_chartView)
|
2012-02-05 15:54:09 +01:00
|
|
|
{
|
2017-10-15 11:36:27 +02:00
|
|
|
_vbox2->removeWidget(_chartView);
|
|
|
|
delete _chartView;
|
2012-02-05 15:54:09 +01:00
|
|
|
}
|
|
|
|
|
2017-10-15 11:36:27 +02:00
|
|
|
_plot = new QChart();
|
|
|
|
_plot->createDefaultAxes();
|
2012-02-05 15:54:09 +01:00
|
|
|
|
|
|
|
if (monthFrom == monthTo && yearFrom == yearTo)
|
|
|
|
{
|
|
|
|
date.setDate(yearFrom, monthFrom+1, 1);
|
|
|
|
nbDays = date.daysInMonth();
|
|
|
|
|
2014-11-10 11:54:28 +01:00
|
|
|
_kiss->GetMonthStats(monthFrom, yearFrom, nbDays, &operations, &categories, &tags);
|
2012-02-05 15:54:09 +01:00
|
|
|
|
2012-02-11 10:47:09 +01:00
|
|
|
// Line on 0 all over the years
|
|
|
|
for (a=0; a<nbDays; a++)
|
2017-10-15 11:36:27 +02:00
|
|
|
{
|
|
|
|
date = QDate(yearFrom, monthFrom+1, a+1);
|
|
|
|
xValue.setDate(date);
|
|
|
|
series->append(xValue.toMSecsSinceEpoch(), 0.0);
|
|
|
|
}
|
2012-02-11 10:47:09 +01:00
|
|
|
|
2017-10-15 11:36:27 +02:00
|
|
|
series->setName(_("0 line"));
|
|
|
|
series->setColor(Qt::red);
|
|
|
|
axisX->setFormat("dd");
|
|
|
|
_plot->addSeries(series);
|
2012-02-11 10:47:09 +01:00
|
|
|
|
2012-03-11 17:54:42 +01:00
|
|
|
i=0;
|
2012-02-11 10:47:09 +01:00
|
|
|
for (account = 0, i = 0, accountIt = user->_accounts.begin(); accountIt != user->_accounts.end();
|
2012-03-16 13:08:15 +01:00
|
|
|
account++, accountIt++)
|
2012-02-11 10:47:09 +01:00
|
|
|
{
|
|
|
|
if (_account->item(account)->checkState() != Qt::Checked)
|
|
|
|
continue;
|
|
|
|
|
2017-10-15 11:36:27 +02:00
|
|
|
series = new QLineSeries();
|
2012-03-11 17:54:42 +01:00
|
|
|
for (a=0; a<nbDays; a++)
|
2017-10-15 11:36:27 +02:00
|
|
|
{
|
|
|
|
date = QDate(yearFrom, monthFrom+1, a+1);
|
|
|
|
xValue.setDate(date);
|
|
|
|
series->append(xValue.toMSecsSinceEpoch(),
|
|
|
|
(double) operations[accountIt->id][a] / 100);
|
|
|
|
}
|
2012-02-11 10:47:09 +01:00
|
|
|
|
2017-10-15 11:36:27 +02:00
|
|
|
series->setName(user->GetAccountName(accountIt->id));
|
|
|
|
_plot->addSeries(series);
|
2012-02-11 10:47:09 +01:00
|
|
|
}
|
2012-02-05 15:54:09 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-11-10 11:54:28 +01:00
|
|
|
_kiss->GetStats(monthFrom, yearFrom, monthTo, yearTo, &accountAmounts, &categories, &tags);
|
2012-02-05 15:54:09 +01:00
|
|
|
|
2012-02-11 10:47:09 +01:00
|
|
|
// Line on 0 all over the years
|
|
|
|
nbDays = ((yearTo - yearFrom) + 1) * 12;
|
|
|
|
for (a=0; a<(nbDays/12); a++)
|
|
|
|
{
|
|
|
|
for(b=0; b<12; b++)
|
|
|
|
{
|
2017-10-15 11:36:27 +02:00
|
|
|
date = QDate(yearFrom+a, monthFrom+b+1, 1);
|
|
|
|
xValue.setDate(date);
|
|
|
|
series->append(xValue.toMSecsSinceEpoch(), 0.0);
|
2012-02-11 10:47:09 +01:00
|
|
|
}
|
|
|
|
}
|
2017-10-15 11:36:27 +02:00
|
|
|
|
|
|
|
axisX->setLabelsAngle(-60);
|
|
|
|
axisX->setLineVisible(true);
|
|
|
|
axisX->setFormat("MM yyyy");
|
|
|
|
series->setName(_("0 line"));
|
|
|
|
series->setColor(Qt::red);
|
|
|
|
_plot->addSeries(series);
|
2012-02-05 15:54:09 +01:00
|
|
|
|
|
|
|
for (account = 0, i = 0, accountIt = user->_accounts.begin(); accountIt != user->_accounts.end();
|
|
|
|
account++, accountIt++, i++)
|
|
|
|
{
|
|
|
|
if (_account->item(account)->checkState() != Qt::Checked)
|
|
|
|
{
|
|
|
|
i-- ;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2017-10-15 11:36:27 +02:00
|
|
|
series = new QLineSeries();
|
2012-02-11 10:47:09 +01:00
|
|
|
for(a = 0, accountYearIt = accountAmounts[accountIt->id].begin();
|
|
|
|
accountYearIt != accountAmounts[accountIt->id].end();
|
|
|
|
accountYearIt++, a++)
|
|
|
|
{
|
|
|
|
for(b = 0; b<=12; b++)
|
|
|
|
{
|
2017-10-15 11:36:27 +02:00
|
|
|
date = QDate(yearFrom+a, b+1, 1);
|
|
|
|
xValue.setDate(date);
|
2012-02-11 10:47:09 +01:00
|
|
|
if (!accountAmounts[accountIt->id][accountYearIt->first].count(b))
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
If previously failed, continue to avoid to set
|
|
|
|
account to 0 (only for display)
|
|
|
|
*/
|
|
|
|
if (!b || failed) continue;
|
|
|
|
/*
|
|
|
|
Compute cur month value (if there are operations)
|
|
|
|
as next month value
|
|
|
|
*/
|
2017-10-15 11:36:27 +02:00
|
|
|
*series << QPointF(xValue.toMSecsSinceEpoch(),
|
|
|
|
(double) (accountAmounts[accountIt->id][accountYearIt->first][b-1]
|
|
|
|
+ _kiss->CalcAccountAmount(accountIt->id, b-1, accountYearIt->first, 0)) / 100);
|
2012-02-11 10:47:09 +01:00
|
|
|
failed = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-10-15 11:36:27 +02:00
|
|
|
*series << QPointF(xValue.toMSecsSinceEpoch(),
|
|
|
|
(double) accountAmounts[accountIt->id][accountYearIt->first][b] / 100);
|
2012-02-11 10:47:09 +01:00
|
|
|
failed = false;
|
|
|
|
}
|
|
|
|
size++;
|
|
|
|
}
|
|
|
|
}
|
2017-10-15 11:36:27 +02:00
|
|
|
series->setName(user->GetAccountName(accountIt->id));
|
|
|
|
_plot->addSeries(series);
|
2012-02-05 15:54:09 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-15 11:36:27 +02:00
|
|
|
// yAxis->setTitleText (_("Amount"));
|
|
|
|
|
|
|
|
QLegend* legend = _plot->legend();
|
|
|
|
legend->setAlignment(Qt::AlignRight);
|
2012-02-05 15:54:09 +01:00
|
|
|
|
2017-10-15 11:36:27 +02:00
|
|
|
_plot->createDefaultAxes();
|
|
|
|
_plot->setAxisX(axisX, series0);
|
|
|
|
_chartView = new QChartView(_plot);
|
|
|
|
_chartView->setRenderHint(QPainter::Antialiasing);
|
|
|
|
_vbox2->addWidget(_chartView);
|
2012-02-05 15:54:09 +01:00
|
|
|
|
|
|
|
total = 0.0;
|
|
|
|
for(i=0, categoriesIt = categories.begin(); categoriesIt != categories.end(); categoriesIt++, i++)
|
|
|
|
{
|
|
|
|
_categoriesValues[_categoriesIndexes[categoriesIt->first]] = categoriesIt->second;
|
2013-02-26 15:34:52 +01:00
|
|
|
total += categoriesIt->second;
|
2012-02-05 15:54:09 +01:00
|
|
|
}
|
|
|
|
|
2013-02-26 15:34:52 +01:00
|
|
|
_costRepartitionBanner->UpdateCosts(_categoriesValues, total);
|
2012-02-05 15:54:09 +01:00
|
|
|
|
|
|
|
layout();
|
|
|
|
}
|
|
|
|
|
|
|
|
void StatsPanel::OnShow()
|
|
|
|
{
|
|
|
|
_wxUI->setWindowTitle(_kiss->GetUser()->_name + _(" - ") + _("Statistics"));
|
|
|
|
}
|
|
|
|
|
|
|
|
void StatsPanel::OnRangeChange(int index)
|
|
|
|
{
|
|
|
|
int monthFrom, monthTo, yearFrom, yearTo;
|
|
|
|
|
|
|
|
monthFrom = _monthFrom->currentIndex();
|
|
|
|
yearFrom = _yearFrom->currentText().toInt();
|
|
|
|
monthTo = _monthTo->currentIndex();
|
|
|
|
yearTo = _yearTo->currentText().toInt();
|
|
|
|
|
|
|
|
if (yearTo < yearFrom ||
|
|
|
|
(yearFrom == yearTo && monthFrom > monthTo))
|
|
|
|
{
|
|
|
|
QMessageBox::critical(0, _("Error"), _("Invalide date range"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-02-26 15:34:52 +01:00
|
|
|
_costRepartitionBanner->Reset();
|
2012-02-05 15:54:09 +01:00
|
|
|
UpdateStats(monthFrom, yearFrom, monthTo, yearTo);
|
|
|
|
}
|
|
|
|
|
|
|
|
void StatsPanel::OnAccountChange(QListWidgetItem* item)
|
|
|
|
{
|
|
|
|
OnRangeChange(0);
|
|
|
|
}
|