/* 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 "StatsPanel.hpp" StatsPanel::StatsPanel(KissCount* kiss, wxUI *parent) : KissPanel(kiss, parent) //, _plot(0), _chart(0) { QHBoxLayout *hbox = new QHBoxLayout(); QVBoxLayout *vbox = new QVBoxLayout(); _hbox2 = new QHBoxLayout(); _vbox2 = new QVBoxLayout(); int i; User* user = _kiss->GetUser(); std::vector::iterator accountIt; std::vector::iterator categoryIt; std::map > operations; std::map >::iterator it; int nbCategories; QListWidgetItem* item; 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); item->setCheckState (Qt::Checked); } 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); _statsGrid = new QTableWidget(this); _statsGrid->setRowCount(user->GetCategoriesNumber()+1); _statsGrid->setColumnCount(2); _statsGrid->verticalHeader()->setHidden(true); _statsGrid->horizontalHeader()->setHidden(true); _statsGrid->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); for(i=0; iGetCategoriesNumber(); i++) { if (i) { _statsGrid->setItem(i+1, 0, new QTableWidgetItem(_categories[i])); _statsGrid->item(i+1, 0)->setTextAlignment(Qt::AlignLeft|Qt::AlignVCenter); } else { _statsGrid->setItem(i, 0, new QTableWidgetItem(_categories[i])); _statsGrid->item(i, 0)->setTextAlignment(Qt::AlignLeft|Qt::AlignVCenter); } } _statsGrid->setItem(1, 0, new QTableWidgetItem(_("Non fix"))); _statsGrid->setItem(1, 1, new QTableWidgetItem("")); _statsGrid->item(1, 1)->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); _vbox2->addWidget(_account); _vbox2->addWidget(_statsGrid); nbCategories = (user->GetCategoriesNumber() <= wxUI::MAX_CATEGORY) ? user->GetCategoriesNumber() : wxUI::MAX_CATEGORY; // _dataset = new CategorySimpleDataset(_categories, nbCategories); // ColorScheme* colorScheme = new ColorScheme(wxUI::categoryColors, WXSIZEOF(wxUI::categoryColors)); _categoriesValues = new double[user->GetCategoriesNumber()]; for(i=0; iGetCategoriesNumber(); i++) _categoriesValues[i] = 0.0; _pie = new KDChart::Widget(); _pie->setType( KDChart::Widget::Pie ); QPen pen; pen.setWidth(2); pen.setColor(Qt::black); _pie->pieDiagram()->setPen(pen); _pie->addLegend(KDChart::Position::South); KDChart::Legend* legend = _pie->legend(); legend->setOrientation( Qt::Vertical ); legend->setTitleText( _("Cost repartition") ); QVector< double > vec; vec << 0.0; _categoriesValues = new double[nbCategories]; for(i=0; isetDataset( i, vec, _categories[i] ); _pie->pieDiagram()->setBrush(i, QBrush(wxUI::categoryColors[i])); legend->setText( i, _categories[i] ); } _pie->setMaximumSize( 200, 400 ); KDChart::TextAttributes legendTextAttr(legend->textAttributes()); legendTextAttr.setFontSize(64); legendTextAttr.setAutoShrink(true); legend->setTextAttributes(legendTextAttr); legendTextAttr = KDChart::TextAttributes(legend->titleTextAttributes()); legendTextAttr.setFontSize(64); legendTextAttr.setAutoShrink(true); legend->setTitleTextAttributes(legendTextAttr); vbox->addLayout(hbox); vbox->addLayout(_hbox2); OnRangeChange(0); layout(); } KissPanel* StatsPanel::CreatePanel() { return new StatsPanel(_kiss, _wxUI); } QPushButton* StatsPanel::GetButton() { if (!_KissButton) { _KissButton = new QPushButton(QIcon(STATS_ICON), "", this); _KissButton->setFixedSize(128, 128); _KissButton->setIconSize(QSize(128, 128)); } return _KissButton; } QString StatsPanel::GetToolTip() { return _("Statistics"); } void StatsPanel::UpdateStats(int monthFrom, int yearFrom, int monthTo, int yearTo) { std::map > > accountAmounts; std::map categories; std::map > operations; std::vector::iterator accountIt; std::map::iterator categoriesIt; std::map >::iterator accountYearIt; double total, non_fix; int account, size, i, a, b, percents, nbDays; double *amounts; QString value; User* user = _kiss->GetUser(); QDate date; bool failed; // if (_chart) { // _hbox2->removeWidget(_chart); _hbox2->removeItem(_vbox2); // _hbox2->removeWidget(_chartCategories); // delete _chart; } // first step: create plot // _plot = new XYPlot(); // create dataset // XYSimpleDataset *dataset = new XYSimpleDataset(); if (monthFrom == monthTo && yearFrom == yearTo) { date.setDate(yearFrom, monthFrom+1, 1); nbDays = date.daysInMonth(); _kiss->GetMonthStats(monthFrom, yearFrom, nbDays, &operations, &categories); // // Line on 0 all over the years // amounts = new double[nbDays*2]; // for (a=0; aAddSerie((double *) amounts, nbDays); // delete[] amounts; // for (account = 0, i = 0, accountIt = user->_accounts.begin(); accountIt != user->_accounts.end(); // account++, accountIt++, i++) // { // if (!_account->IsChecked(account)) // { // i-- ; // continue; // } // amounts = new double[nbDays*2]; // size = 0; // for (a=0; aid][a]; // } // dataset->AddSerie((double *) amounts, nbDays); // // set serie names to be displayed on legend // dataset->SetSerieName(i+1, user->GetAccountName(accountIt->id)); // delete[] amounts; // } } else { _kiss->GetStats(monthFrom, yearFrom, monthTo, yearTo, &accountAmounts, &categories); // // Line on 0 all over the years // size = ((yearTo - yearFrom) + 1) * 12; // amounts = new double[size*2]; // for (a=0; a<(size/12); a++) // { // for(b=0; b<12; b++) // { // amounts[a*12*2+b*2+0] = a*12+b; // amounts[a*12*2+b*2+1] = 0; // } // } // dataset->AddSerie((double *) amounts, size); // delete[] amounts; 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; } // size = accountAmounts[accountIt->id].size(); // amounts = new double[size*13*2]; // size = 0; // for(a = 0, accountYearIt = accountAmounts[accountIt->id].begin(); // accountYearIt != accountAmounts[accountIt->id].end(); // accountYearIt++, a++) // { // for(b = 0; b<=12; b++) // { // amounts[size*2+0] = a*12+b; // if (!accountAmounts[accountIt->id][accountYearIt->first].count(b)) // { // /* // If previously afiled, 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 // */ // amounts[size*2+1] = // accountAmounts[accountIt->id][accountYearIt->first][b-1] // + _kiss->CalcAccountAmount(accountIt->id, b-1, accountYearIt->first, 0); // failed = true; // } // else // { // amounts[size*2+1] = accountAmounts[accountIt->id][accountYearIt->first][b]; // failed = false; // } // size++; // } // } // dataset->AddSerie((double *) amounts, size); // // set serie names to be displayed on legend // dataset->SetSerieName(i+1, user->GetAccountName(accountIt->id)); // delete[] amounts; } } // // create line renderer and set it to dataset // XYLineRenderer *renderer = new XYLineRenderer(true, true); // dataset->SetRenderer(renderer); // // add our dataset to plot // _plot->AddDataset(dataset); // // create left and bottom number axes // NumberAxis *leftAxis = new NumberAxis(AXIS_LEFT); // NumberAxis *bottomAxis = new NumberAxis(AXIS_BOTTOM); // // add axes to plot // _plot->AddAxis(leftAxis); // _plot->AddAxis(bottomAxis); // // link axes and dataset // _plot->LinkDataVerticalAxis(0, 0); // _plot->LinkDataHorizontalAxis(0, 0); // // set legend // _plot->SetLegend(new Legend(wxCENTER, wxRIGHT)); // _chart = new wxChartPanel(this); // _chart->SetChart(new Chart(_plot, _("Accounts"))); // _chart->Fit(); // _chart->Layout(); // _chart->SetMinSize(// chart->GetSize() // wxSize(750,550)); // _hbox2->Add(_chart, 0, wxGROW|wxALL, 5); total = 0.0; for(categoriesIt = categories.begin(); categoriesIt != categories.end(); categoriesIt++) total += categoriesIt->second; for(i=0, categoriesIt = categories.begin(); categoriesIt != categories.end(); categoriesIt++, i++) { _categoriesValues[_categoriesIndexes[categoriesIt->first]] = categoriesIt->second; if (total) percents = ((double) (categoriesIt->second*100))/total; else percents = 0; value = value.sprintf("%0.2lf (%02d%%)", categoriesIt->second, percents); if (i) { _statsGrid->setItem(_categoriesIndexes[categoriesIt->first]+1, 1, new QTableWidgetItem(value)); _statsGrid->item(_categoriesIndexes[categoriesIt->first]+1, 1)->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); } else { _statsGrid->setItem(_categoriesIndexes[categoriesIt->first], 1, new QTableWidgetItem(value)); _statsGrid->item(_categoriesIndexes[categoriesIt->first], 1)->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); } QVector< double > vec; vec << _categoriesValues[i]; _pie->setDataset( i, vec, _categories[i] ); } non_fix = total - _categoriesValues[0]; if (total) percents = ((double) (non_fix*100))/total; else percents = 0; value = value.sprintf("%0.2lf (%02d%%)", non_fix, percents); _statsGrid->setItem(1, 1, new QTableWidgetItem(value)); _statsGrid->resizeColumnsToContents(); _hbox2->addLayout(_vbox2); _hbox2->addWidget(_pie); 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; } UpdateStats(monthFrom, yearFrom, monthTo, yearTo); } void StatsPanel::OnAccountChange(QListWidgetItem* item) { OnRangeChange(0); }