/* 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 . */ #include #include #include #include #include #include "StatsPanel.hpp" using namespace QtCharts; StatsPanel::StatsPanel(KissCount* kiss, wxUI *parent, bool lowResolution) : KissPanel(kiss, parent, lowResolution), _chartView(0) { QHBoxLayout *hbox = new QHBoxLayout(); QVBoxLayout *vbox = new QVBoxLayout(); _hbox2 = new QHBoxLayout(); _vbox2 = new QVBoxLayout(); _vbox3 = new QVBoxLayout(); int i, nbCategories; User* user = _kiss->GetUser(); std::vector::iterator accountIt; std::vector::iterator categoryIt; std::map > operations; std::map >::iterator it; QListWidgetItem* item; _icons[KissPanel::LOW_RES_ICON] = STATS_LOW_ICON; _icons[KissPanel::HIGH_RES_ICON] = STATS_ICON; 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")); hbox->addWidget(label); hbox->addWidget(_monthFrom); hbox->addWidget(_yearFrom); label = new QLabel(_("To")); hbox->addWidget(label); hbox->addWidget(_monthTo); hbox->addWidget(_yearTo); 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); if (accountIt->hidden) item->setCheckState (Qt::Unchecked); else item->setCheckState (Qt::Checked); } _account->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); 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); _costRepartitionBanner = new CostRepartitionBanner(_kiss, this, _categories); _vbox3->addWidget(_account); nbCategories = user->GetCategoriesNumber(); _categoriesValues = new int[nbCategories]; for(i=0; iaddWidget(_costRepartitionBanner); _vbox2->addLayout(hbox); _hbox2->addLayout(_vbox2); vbox->addLayout(_hbox2); _hbox2->addLayout(_vbox3); OnRangeChange(0); layout(); } KissPanel* StatsPanel::CreatePanel() { return new StatsPanel(_kiss, _wxUI, _lowResolution); } QString StatsPanel::GetToolTip() { return _("Statistics"); } void StatsPanel::UpdateStats(int monthFrom, int yearFrom, int monthTo, int yearTo) { std::map > > accountAmounts; std::map categories; std::map tags; std::map > operations; std::vector::iterator accountIt; std::map::iterator categoriesIt; std::map >::iterator accountYearIt; int total; int account, size, i, a, b, nbDays; QString value, v; User* user = _kiss->GetUser(); QDate date; bool failed; QLineSeries * series = new QLineSeries(); QLineSeries * series0 = series; QDateTimeAxis *axisX = new QDateTimeAxis; QDateTime xValue; if (_chartView) { _vbox2->removeWidget(_chartView); delete _chartView; } _plot = new QChart(); _plot->createDefaultAxes(); if (monthFrom == monthTo && yearFrom == yearTo) { date.setDate(yearFrom, monthFrom+1, 1); nbDays = date.daysInMonth(); _kiss->GetMonthStats(monthFrom, yearFrom, nbDays, &operations, &categories, &tags); // Line on 0 all over the years for (a=0; aappend(xValue.toMSecsSinceEpoch(), 0.0); } series->setName(_("0 line")); series->setColor(Qt::red); axisX->setFormat("dd"); _plot->addSeries(series); i=0; for (account = 0, i = 0, accountIt = user->_accounts.begin(); accountIt != user->_accounts.end(); account++, accountIt++) { if (_account->item(account)->checkState() != Qt::Checked) continue; series = new QLineSeries(); for (a=0; aappend(xValue.toMSecsSinceEpoch(), (double) operations[accountIt->id][a] / 100); } series->setName(user->GetAccountName(accountIt->id)); _plot->addSeries(series); } } else { _kiss->GetStats(monthFrom, yearFrom, monthTo, yearTo, &accountAmounts, &categories, &tags); // 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++) { date = QDate(yearFrom+a, monthFrom+b+1, 1); xValue.setDate(date); series->append(xValue.toMSecsSinceEpoch(), 0.0); } } axisX->setLabelsAngle(-60); axisX->setLineVisible(true); axisX->setFormat("MM yyyy"); series->setName(_("0 line")); series->setColor(Qt::red); _plot->addSeries(series); 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; } series = new QLineSeries(); for(a = 0, accountYearIt = accountAmounts[accountIt->id].begin(); accountYearIt != accountAmounts[accountIt->id].end(); accountYearIt++, a++) { for(b = 0; b<=12; b++) { date = QDate(yearFrom+a, b+1, 1); xValue.setDate(date); 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 */ *series << QPointF(xValue.toMSecsSinceEpoch(), (double) (accountAmounts[accountIt->id][accountYearIt->first][b-1] + _kiss->CalcAccountAmount(accountIt->id, b-1, accountYearIt->first, 0)) / 100); failed = true; } else { *series << QPointF(xValue.toMSecsSinceEpoch(), (double) accountAmounts[accountIt->id][accountYearIt->first][b] / 100); failed = false; } size++; } } series->setName(user->GetAccountName(accountIt->id)); _plot->addSeries(series); } } // yAxis->setTitleText (_("Amount")); QLegend* legend = _plot->legend(); legend->setAlignment(Qt::AlignRight); _plot->createDefaultAxes(); _plot->setAxisX(axisX, series0); _chartView = new QChartView(_plot); _chartView->setRenderHint(QPainter::Antialiasing); _vbox2->addWidget(_chartView); total = 0.0; for(i=0, categoriesIt = categories.begin(); categoriesIt != categories.end(); categoriesIt++, i++) { _categoriesValues[_categoriesIndexes[categoriesIt->first]] = categoriesIt->second; total += categoriesIt->second; } _costRepartitionBanner->UpdateCosts(_categoriesValues, total); 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; } _costRepartitionBanner->Reset(); UpdateStats(monthFrom, yearFrom, monthTo, yearTo); } void StatsPanel::OnAccountChange(QListWidgetItem* item) { OnRangeChange(0); }