/* Copyright 2010 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 "StatsPanel.h" enum {RANGE_ID=1, ACCOUNTS_ID}; BEGIN_EVENT_TABLE(StatsPanel, wxPanel) EVT_CHOICE(RANGE_ID, StatsPanel::OnRangeChange) EVT_CHECKLISTBOX(ACCOUNTS_ID, StatsPanel::OnAccountsChange) END_EVENT_TABLE() StatsPanel::StatsPanel(KissCount* kiss, wxUI *parent) : wxPanel(&(*parent)), _kiss(kiss), _wxUI(parent), _plot(NULL), _chart(NULL) { wxBoxSizer *hbox = new wxBoxSizer(wxHORIZONTAL); _hbox2 = new wxBoxSizer(wxHORIZONTAL); wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL); _vbox2 = new wxBoxSizer(wxVERTICAL); int i; User* user = _kiss->GetUser(); std::vector::iterator accountIt; std::vector::iterator categoryIt; std::map > operations; std::map >::iterator it; SetSizer(vbox); _monthFrom = new wxChoice (this, RANGE_ID, wxDefaultPosition, wxDefaultSize, 12, months); _yearFrom = new wxChoice (this, RANGE_ID); _monthTo = new wxChoice (this, RANGE_ID, wxDefaultPosition, wxDefaultSize, 12, months); _yearTo = new wxChoice (this, RANGE_ID); operations = _kiss->GetAllOperations(); for(i=0, it = operations.begin(); it != operations.end(); it++, i++) { _yearFrom->Append(wxString::Format(wxT("%d"), it->first)); _yearTo->Append(wxString::Format(wxT("%d"), it->first)); } _monthFrom->Select(0); _monthTo->Select(11); _yearFrom->Select(i); _yearTo->Select(i); wxStaticText* label = new wxStaticText(this, wxID_ANY, _("From")); hbox->Add(label); hbox->Add(-1, 10); hbox->Add(_monthFrom); hbox->Add(_yearFrom); hbox->Add(-1, 30); label = new wxStaticText(this, wxID_ANY, _("To")); hbox->Add(label); hbox->Add(-1, 10); hbox->Add(_monthTo); hbox->Add(_yearTo); _account = new wxCheckListBox(this, ACCOUNTS_ID); for(i=0, accountIt = user->_accounts.begin(); accountIt != user->_accounts.end(); accountIt++, i++) { _account->Append(accountIt->name); _account->Check(i); } _categories = new wxString[user->GetCategoriesNumber()] ; for(i=0, categoryIt = user->_categories.begin(); categoryIt != user->_categories.end(); categoryIt++, i++) { _categoriesIndexes[categoryIt->id] = i; _categories[i] = categoryIt->name ; } DEFAULT_FONT(font); _statsGrid = new wxGrid(this, wxID_ANY); _statsGrid->CreateGrid(user->GetCategoriesNumber(), 2); _statsGrid->SetColLabelSize(0); _statsGrid->SetRowLabelSize(0); _statsGrid->EnableEditing(false); _statsGrid->SetDefaultCellFont(font); _statsGrid->AutoSizeColumn(0, true); for(i=0; iGetCategoriesNumber(); i++) { _statsGrid->SetCellValue(i, 0, _categories[i]); _statsGrid->SetCellAlignment(i, 1, wxALIGN_RIGHT, wxALIGN_CENTRE); } _vbox2->Add(_account); _vbox2->Add(-1, 10); _vbox2->Add(_statsGrid); _pie = new PiePlot(); _dataset = new CategorySimpleDataset(_categories, user->GetCategoriesNumber()); ColorScheme* colorScheme = new ColorScheme(categoryColors, WXSIZEOF(categoryColors)); _categoriesValues = new double[user->GetCategoriesNumber()]; for(i=0; iGetCategoriesNumber(); i++) _categoriesValues[i] = 0.0; _dataset->AddSerie(_("Serie 1"), _categoriesValues, user->GetCategoriesNumber()); _dataset->SetRenderer(new CategoryRenderer(*colorScheme)); _pie->SetDataset(_dataset); _pie->SetColorScheme(colorScheme); _pie->SetLegend(new Legend(wxBOTTOM, wxCENTER)); wxChartPanel* chart = new wxChartPanel(this); chart->SetChart(new Chart(_pie, _("Cost repartition"))); chart->Fit(); chart->Layout(); chart->SetMinSize(// chart->GetSize() wxSize(200,250)); _vbox2->Add(-1, 10); _vbox2->Add(chart); vbox->Add(hbox); vbox->Add(_hbox2); wxCommandEvent event ; OnRangeChange(event); Fit(); Hide(); } void StatsPanel::UpdateStats(int monthFrom, int yearFrom, int monthTo, int yearTo) { std::map > > accountAmounts; std::map categories; std::map > operations; std::map >::iterator accountIdIt2; std::map::iterator categoriesIt; std::map > >::iterator accountIdIt; std::map >::iterator accountYearIt; double total; int size, i, a, b, percents, account, nbDays; double *amounts; wxString value; User* user = _kiss->GetUser(); wxDateTime date; if (_chart) { _hbox2->Detach(_chart); _hbox2->Detach(_vbox2); delete _chart; } // first step: create plot _plot = new XYPlot(); // create dataset XYSimpleDataset *dataset = new XYSimpleDataset(); if (monthFrom == monthTo && yearFrom == yearTo) { nbDays = date.GetLastMonthDay((wxDateTime::Month)monthFrom, yearFrom).GetDay(); _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, accountIdIt2 = operations.begin(); accountIdIt2 != operations.end(); accountIdIt2++, i++, account++) { if (!((wxCheckListBox*)_account)->IsChecked(account)) { i-- ; continue; } amounts = new double[nbDays*2]; size = 0; for (a=0; afirst][a]; } dataset->AddSerie((double *) amounts, nbDays); // set serie names to be displayed on legend dataset->SetSerieName(i+1, user->GetAccountName(accountIdIt2->first)); 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, accountIdIt = accountAmounts.begin(); accountIdIt != accountAmounts.end(); accountIdIt++, i++, account++) { if (!((wxCheckListBox*)_account)->IsChecked(account)) { i-- ; continue; } size = accountAmounts[accountIdIt->first].size(); amounts = new double[size*12*2]; size = 0; for(a = 0, accountYearIt = accountAmounts[accountIdIt->first].begin(); accountYearIt != accountAmounts[accountIdIt->first].end(); accountYearIt++, a++) { for(b = 0; b<12; b++) { if (!accountAmounts[accountIdIt->first][accountYearIt->first].count(b)) continue; amounts[size*2+0] = a*12+b; amounts[size*2+1] = accountAmounts[accountIdIt->first][accountYearIt->first][b]; size++; } } dataset->AddSerie((double *) amounts, size); // set serie names to be displayed on legend dataset->SetSerieName(i+1, user->GetAccountName(accountIdIt->first)); 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); total = 0.0; for(categoriesIt = categories.begin(); categoriesIt != categories.end(); categoriesIt++) total += categoriesIt->second; for(categoriesIt = categories.begin(); categoriesIt != categories.end(); categoriesIt++) { _categoriesValues[_categoriesIndexes[categoriesIt->first]] = categoriesIt->second; if (total) percents = ((double) (categoriesIt->second*100))/total; else percents = 0; value = wxString::Format(wxT("%0.2lf (%02d%%)"), categoriesIt->second, percents); _statsGrid->SetCellValue(_categoriesIndexes[categoriesIt->first], 1, value); } _statsGrid->AutoSizeColumn(0, true); _statsGrid->AutoSizeColumn(1, true); _pie->DatasetChanged(_dataset); _hbox2->Add(_vbox2); Layout(); } void StatsPanel::OnShow(wxShowEvent& event) { _wxUI->SetTitle(_kiss->GetUser()->_name + _(" - ") + _("Statistics")); } void StatsPanel::OnRangeChange(wxCommandEvent& event) { long monthFrom, monthTo, yearFrom, yearTo; if (!_yearFrom->GetStringSelection().Length() || !_yearTo->GetStringSelection().Length()) return; monthFrom = _monthFrom->GetCurrentSelection(); _yearFrom->GetStringSelection().ToLong(&yearFrom); monthTo = _monthTo->GetCurrentSelection(); _yearTo->GetStringSelection().ToLong(&yearTo); if (yearTo > yearFrom || (yearFrom == yearTo && monthFrom > monthTo)) { wxMessageBox(_("Invalide date range"), _("KissCount"), wxICON_ERROR | wxOK); return; } UpdateStats(monthFrom, yearFrom, monthTo, yearTo); } void StatsPanel::OnAccountsChange(wxCommandEvent& event) { OnRangeChange(event); }