215 lines
6.4 KiB
C++
215 lines
6.4 KiB
C++
|
/*
|
||
|
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 <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
#include "StatsPanel.h"
|
||
|
|
||
|
StatsPanel::StatsPanel(KissCount* kiss, wxUI *parent) : wxPanel(&(*parent)), _kiss(kiss), _wxUI(parent)
|
||
|
{
|
||
|
wxBoxSizer *hbox = new wxBoxSizer(wxHORIZONTAL);
|
||
|
wxBoxSizer *hbox2 = new wxBoxSizer(wxHORIZONTAL);
|
||
|
wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL);
|
||
|
wxBoxSizer *vbox2 = new wxBoxSizer(wxVERTICAL);
|
||
|
int i;
|
||
|
User* user = _kiss->GetUser();
|
||
|
std::vector<Account>::iterator accountIt;
|
||
|
std::vector<Category>::iterator categoryIt;
|
||
|
|
||
|
SetSizer(vbox);
|
||
|
|
||
|
_monthFrom = new wxChoice (this, -1, wxDefaultPosition, wxDefaultSize, 12, months);
|
||
|
_monthTo = new wxChoice (this, -1, wxDefaultPosition, wxDefaultSize, 12, months);
|
||
|
|
||
|
hbox->Add(_monthFrom);
|
||
|
hbox->Add(_monthTo);
|
||
|
|
||
|
_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; i<user->GetCategoriesNumber(); i++)
|
||
|
{
|
||
|
_statsGrid->SetCellValue(i, 0, _categories[i]);
|
||
|
_statsGrid->SetCellAlignment(i, 1, wxALIGN_RIGHT, wxALIGN_CENTRE);
|
||
|
}
|
||
|
|
||
|
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; i<user->GetCategoriesNumber(); 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));
|
||
|
|
||
|
UpdateStats(hbox2);
|
||
|
|
||
|
vbox2->Add(chart);
|
||
|
|
||
|
hbox2->Add(vbox2);
|
||
|
vbox->Add(hbox);
|
||
|
vbox->Add(hbox2);
|
||
|
|
||
|
Fit();
|
||
|
|
||
|
Hide();
|
||
|
}
|
||
|
|
||
|
void StatsPanel::UpdateStats(wxBoxSizer *hbox2)
|
||
|
{
|
||
|
std::map<wxString, std::map<int, std::map<int, double> > > accountAmounts;
|
||
|
std::map<wxString, double> categories;
|
||
|
std::map<wxString, double>::iterator categoriesIt;
|
||
|
std::map<wxString, std::map<int, std::map<int, double> > >::iterator accountIdIt;
|
||
|
std::map<int, std::map<int, double> >::iterator accountYearIt;
|
||
|
double total;
|
||
|
int size, i, a, b, percents;
|
||
|
double *amounts;
|
||
|
User* user = _kiss->GetUser();
|
||
|
wxString value;
|
||
|
|
||
|
_kiss->GetStats(0, 2010, 11, 2010, &accountAmounts, &categories);
|
||
|
|
||
|
// first step: create plot
|
||
|
_plot = new XYPlot();
|
||
|
|
||
|
// create dataset
|
||
|
XYSimpleDataset *dataset = new XYSimpleDataset();
|
||
|
|
||
|
// add two series
|
||
|
for (i = 0, accountIdIt = accountAmounts.begin(); accountIdIt != accountAmounts.end(); accountIdIt++, i++)
|
||
|
{
|
||
|
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, user->GetAccountName(accountIdIt->first));
|
||
|
delete[] amounts;
|
||
|
}
|
||
|
|
||
|
// create line renderer and set it to dataset
|
||
|
XYLineRenderer *renderer = new XYLineRenderer();
|
||
|
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);
|
||
|
|
||
|
// create line marker
|
||
|
LineMarker *lineMarker = new LineMarker(wxColour(255, 0, 0), 2);
|
||
|
|
||
|
// set value to be marked, in our case horizontal value 15
|
||
|
lineMarker->SetHorizontalLine(25);
|
||
|
|
||
|
// and add marker to dataset
|
||
|
dataset->AddMarker(lineMarker);
|
||
|
|
||
|
// set legend
|
||
|
_plot->SetLegend(new Legend(wxCENTER, wxRIGHT));
|
||
|
|
||
|
wxChartPanel* 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;
|
||
|
percents = ((double) (categoriesIt->second*100))/total;
|
||
|
value = wxString::Format(wxT("%0.2lf (%d%%)"), categoriesIt->second, percents);
|
||
|
_statsGrid->SetCellValue(_categoriesIndexes[categoriesIt->first], 1, value);
|
||
|
}
|
||
|
|
||
|
_statsGrid->AutoSizeColumn(0, true);
|
||
|
_statsGrid->AutoSizeColumn(1, true);
|
||
|
|
||
|
_pie->DatasetChanged(_dataset);
|
||
|
}
|
||
|
|
||
|
void StatsPanel::OnShow(wxShowEvent& event)
|
||
|
{
|
||
|
_wxUI->SetTitle(_kiss->GetUser()->_name + _(" - ") + _("Statistics"));
|
||
|
}
|
||
|
|