From 74c401c8c7e8e44ead4dbd9b1e9d63e1ce6504f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soutad=C3=A9?= Date: Tue, 17 Aug 2010 18:59:19 +0200 Subject: [PATCH] First version of statistics (very ugly code) --- TODO | 3 + src/controller/KissCount.cpp | 12 ++ src/controller/KissCount.h | 5 + src/model/Database.cpp | 55 ++++++++- src/model/Database.h | 4 + src/model/User.cpp | 2 +- src/model/User.h | 2 +- src/view/AccountPanel.cpp | 12 -- src/view/ButtonPanel.cpp | 6 + src/view/ButtonPanel.h | 1 + src/view/PreferencesPanel.cpp | 2 +- src/view/StatsPanel.cpp | 214 ++++++++++++++++++++++++++++++++++ src/view/StatsPanel.h | 71 +++++++++++ src/view/wxUI.cpp | 44 ++++++- src/view/wxUI.h | 5 + 15 files changed, 417 insertions(+), 21 deletions(-) create mode 100644 src/view/StatsPanel.cpp create mode 100644 src/view/StatsPanel.h diff --git a/TODO b/TODO index 6abc01c..69ed994 100644 --- a/TODO +++ b/TODO @@ -13,6 +13,8 @@ Better build system for wxFreeChart (hacked by me) Others translation Handle bad SQL return Category color/font +Button tooltip not translated +Do not consider account transferts into statistics =============================================================== Next version @@ -24,3 +26,4 @@ Undo/redo Database auto saving at startup Documentation Use caches for created panels (avoid destroying/creating panels for nothing) +Printing \ No newline at end of file diff --git a/src/controller/KissCount.cpp b/src/controller/KissCount.cpp index ab90172..157b530 100644 --- a/src/controller/KissCount.cpp +++ b/src/controller/KissCount.cpp @@ -336,3 +336,15 @@ bool KissCount::SearchPreviousOperation(Operation* res, wxString& description, i return true; } + +void KissCount::GetStats(int monthFrom, int yearFrom, int monthTo, int yearTo, + std::map > >* accountAmounts, + std::map* categories) +{ + wxString monthF = wxString::Format(wxT("%d"), monthFrom); + wxString monthT = wxString::Format(wxT("%d"), monthTo); + wxString yearF = wxString::Format(wxT("%d"), yearFrom); + wxString yearT = wxString::Format(wxT("%d"), yearTo); + + _db->GetStats(_user, monthF, yearF, monthT, yearT, accountAmounts, categories); +} diff --git a/src/controller/KissCount.h b/src/controller/KissCount.h index d2d6433..7e005b9 100644 --- a/src/controller/KissCount.h +++ b/src/controller/KissCount.h @@ -75,6 +75,11 @@ class KissCount std::vector categories, std::vector accounts); bool SearchPreviousOperation(Operation* res, wxString& description, int month, int year); + + void GetStats(int monthFrom, int yearFrom, int monthTo, int yearTo, + std::map > >* accountAmounts, + std::map* categories); + private: wxUI* _wxUI; Database* _db; diff --git a/src/model/Database.cpp b/src/model/Database.cpp index 0d6b33a..ec50936 100644 --- a/src/model/Database.cpp +++ b/src/model/Database.cpp @@ -365,7 +365,7 @@ void Database::UpdateOperation(Operation& op) req += wxT(", checked='1'"); else req += wxT(", checked='0'"); - req += wxT(", forumla='") + op.formula + wxT("'"); + req += wxT(", formula='") + op.formula + wxT("'"); req += wxT(" WHERE id='") + op.id + wxT("'"); EXECUTE_SQL_UPDATE(req, ); @@ -1056,3 +1056,56 @@ std::vector* Database::Search(User* user, wxString* description, wxDa return res; } + +void Database::GetStats(User* user, const wxString& monthFrom, const wxString& yearFrom, const wxString& monthTo, + const wxString& yearTo, std::map > >* accountAmounts, + std::map* categories) +{ + wxSQLite3ResultSet set; + wxString req; + std::vector::iterator accountIt; + std::vector::iterator categoryIt; + + if (!user->_accounts.empty()) + { + for (accountIt = user->_accounts.begin(); accountIt != user->_accounts.end(); accountIt++) + { + req = wxT("SELECT month, year, amount FROM account_amount WHERE account ='") + accountIt->id + wxT("'"); + + EXECUTE_SQL_QUERY(req, set, ); + + while (set.NextRow()) + { + (*accountAmounts)[accountIt->id][set.GetInt(wxT("year"))][set.GetInt(wxT("month"))] = set.GetInt(wxT("amount")); + } + set.Finalize(); + } + + for (categoryIt = user->_categories.begin(); categoryIt != user->_categories.end(); categoryIt++) + { + req = wxT("SELECT SUM(amount) as amount FROM operation WHERE category='") + categoryIt->id + wxT("'"); + accountIt = user->_accounts.begin(); + req += wxT(" AND (account IN('") + accountIt->id; + accountIt++; + for (;accountIt != user->_accounts.end(); accountIt++) + { + req += wxT("', '") + accountIt->id ; + } + req += wxT("')"); + req += wxT(" OR user='") + user->_id + wxT("')"); + + req += wxT(" AND (year > '") + yearFrom + wxT("' OR (year == '") + yearFrom + wxT("' AND month >= '") + monthFrom + wxT("'))"); + + req += wxT(" AND (year < '") + yearTo + wxT("' OR (year == '") + yearTo + wxT("' AND month <= '") + monthTo + wxT("'))"); + req += wxT(" AND amount < 0"); + + EXECUTE_SQL_QUERY(req, set, ); + + if (set.NextRow()) + { + (*categories)[categoryIt->id] = -set.GetDouble(wxT("amount")); + } + set.Finalize(); + } + } +} diff --git a/src/model/Database.h b/src/model/Database.h index ff66417..dc4dade 100644 --- a/src/model/Database.h +++ b/src/model/Database.h @@ -71,6 +71,10 @@ class Database std::vector* Search(User* user, wxString* description, wxDateTime* dateFrom, wxDateTime* dateTo, wxString* amountFrom, wxString* amountTo, std::vector categories, std::vector accounts); + + void GetStats(User* user, const wxString& monthFrom, const wxString& yearFrom, const wxString& monthTo, + const wxString& yearTo, std::map > >* accountAmounts, + std::map* categories); void KillMe(User* user); private: diff --git a/src/model/User.cpp b/src/model/User.cpp index 0d6c7a7..5bee18a 100644 --- a/src/model/User.cpp +++ b/src/model/User.cpp @@ -70,7 +70,7 @@ wxString User::GetCategoryId(wxString& catName) return wxT("0") ; } -wxString User::GetAccountName(wxString& accountId) +wxString User::GetAccountName(const wxString& accountId) { std::vector::iterator it; for (it=_accounts.begin(); it !=_accounts.end(); it++) diff --git a/src/model/User.h b/src/model/User.h index 037d661..75b64f3 100644 --- a/src/model/User.h +++ b/src/model/User.h @@ -45,7 +45,7 @@ class User Category GetCategory(wxString& catId); wxString GetCategoryName(wxString& catId); wxString GetCategoryId(wxString& catName); - wxString GetAccountName(wxString& accountId); + wxString GetAccountName(const wxString& accountId); wxString GetAccountId(wxString& accountName); int GetCategoriesNumber(); int GetAccountsNumber(); diff --git a/src/view/AccountPanel.cpp b/src/view/AccountPanel.cpp index 32a0e7f..aa07fa7 100644 --- a/src/view/AccountPanel.cpp +++ b/src/view/AccountPanel.cpp @@ -46,18 +46,6 @@ AccountPanel::AccountPanel(KissCount* kiss, wxUI *parent) : wxScrolledWindow(&(* User* user = _kiss->GetUser(); std::vector::iterator accountIt; std::vector::iterator categoryIt; - wxColour categoryColors[] = {wxColour(0x00, 0x45, 0x86), - wxColour(0xFF, 0x3E, 0x0E), - wxColour(0xFF, 0xD3, 0x20), - wxColour(0x58, 0x9D, 0x1B), - wxColour(0x7E, 0x00, 0x21), - wxColour(0x83, 0xCC, 0xFF), - wxColour(0x31, 0x40, 0x04), - wxColour(0xB0, 0xCF, 0x00), - wxColour(0x4B, 0x1F, 0x6F), - wxColour(0xFF, 0x93, 0x0E), - wxColour(0xC5, 0x00, 0x0D), - wxColour(0x00, 0x84, 0xD1)}; DEFAULT_FONT(font); SetSizer(hbox); diff --git a/src/view/ButtonPanel.cpp b/src/view/ButtonPanel.cpp index b56843a..015c734 100644 --- a/src/view/ButtonPanel.cpp +++ b/src/view/ButtonPanel.cpp @@ -23,6 +23,7 @@ enum {BUTTON_ACCOUNT_ID=1, BUTTON_STATS_ID, BUTTON_SEARCH_ID, BUTTON_PREFS_ID, B BEGIN_EVENT_TABLE(ButtonPanel, wxPanel) EVT_BUTTON(BUTTON_ACCOUNT_ID, ButtonPanel::OnButtonAccount) +EVT_BUTTON(BUTTON_STATS_ID, ButtonPanel::OnButtonStats) EVT_BUTTON(BUTTON_SEARCH_ID, ButtonPanel::OnButtonSearch) EVT_BUTTON(BUTTON_PREFS_ID, ButtonPanel::OnButtonPreferences) EVT_BUTTON(BUTTON_CHANGE_USER_ID, ButtonPanel::OnButtonChangeUser) @@ -76,6 +77,11 @@ void ButtonPanel::OnButtonAccount(wxCommandEvent& event) _wxUI->ShowAccount(); } +void ButtonPanel::OnButtonStats(wxCommandEvent& event) +{ + _wxUI->ShowStats(); +} + void ButtonPanel::OnButtonSearch(wxCommandEvent& event) { _wxUI->ShowSearch(); diff --git a/src/view/ButtonPanel.h b/src/view/ButtonPanel.h index 3fed829..4194de9 100644 --- a/src/view/ButtonPanel.h +++ b/src/view/ButtonPanel.h @@ -39,6 +39,7 @@ class ButtonPanel: public wxPanel ~ButtonPanel(); void OnButtonAccount(wxCommandEvent& event); + void OnButtonStats(wxCommandEvent& event); void OnButtonSearch(wxCommandEvent& event); void OnButtonPreferences(wxCommandEvent& event); void OnButtonChangeUser(wxCommandEvent& event); diff --git a/src/view/PreferencesPanel.cpp b/src/view/PreferencesPanel.cpp index 11715df..6e22535 100644 --- a/src/view/PreferencesPanel.cpp +++ b/src/view/PreferencesPanel.cpp @@ -571,7 +571,7 @@ void PreferencesPanel::OnLanguageChange(wxCommandEvent& event) void PreferencesPanel::OnShow(wxShowEvent& event) { - _wxUI->SetTitle(_kiss->GetUser()->_name + _(" - ") +_("Preferences")); + _wxUI->SetTitle(_kiss->GetUser()->_name + _(" - ") + _("Preferences")); } void PreferencesPanel::OnKillMe(wxCommandEvent& event) diff --git a/src/view/StatsPanel.cpp b/src/view/StatsPanel.cpp new file mode 100644 index 0000000..71abf23 --- /dev/null +++ b/src/view/StatsPanel.cpp @@ -0,0 +1,214 @@ +/* +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" + +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::iterator accountIt; + std::vector::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; iGetCategoriesNumber(); 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; 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)); + + UpdateStats(hbox2); + + vbox2->Add(chart); + + hbox2->Add(vbox2); + vbox->Add(hbox); + vbox->Add(hbox2); + + Fit(); + + Hide(); +} + +void StatsPanel::UpdateStats(wxBoxSizer *hbox2) +{ + std::map > > accountAmounts; + std::map categories; + std::map::iterator categoriesIt; + std::map > >::iterator accountIdIt; + std::map >::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")); +} + diff --git a/src/view/StatsPanel.h b/src/view/StatsPanel.h new file mode 100644 index 0000000..2ca6454 --- /dev/null +++ b/src/view/StatsPanel.h @@ -0,0 +1,71 @@ +/* +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 . +*/ + +#ifndef STATSPANEL_H +#define STATSPANEL_H + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "wxUI.h" +#include +#include "view.h" + +class wxUI; +class KissCount; + +class StatsPanel: public wxPanel //public wxScrolledWindow +{ + public: + StatsPanel(KissCount* kiss, wxUI *parent); + //~StatsPanel(); + + void OnShow(wxShowEvent& event); + + private: + KissCount* _kiss; + wxUI* _wxUI; + wxCalendarCtrl* _calendarFrom, *_calendarTo; + wxChoice* _monthFrom, *_yearFrom, *_monthTo, *_yearTo; + wxGrid *_statsGrid; + PiePlot* _pie; + double *_categoriesValues; + CategorySimpleDataset* _dataset; + XYPlot *_plot ; + wxString* _categories; + std::map _categoriesIndexes; + + void UpdateStats(wxBoxSizer *); + + //DECLARE_EVENT_TABLE(); + +}; + +#endif diff --git a/src/view/wxUI.cpp b/src/view/wxUI.cpp index 9a01fff..318f9f9 100644 --- a/src/view/wxUI.cpp +++ b/src/view/wxUI.cpp @@ -20,10 +20,22 @@ along with KissCount. If not, see . #include "wxUI.h" wxString months[12] ; +wxColour categoryColors[12] = {wxColour(0x00, 0x45, 0x86), + wxColour(0xFF, 0x3E, 0x0E), + wxColour(0xFF, 0xD3, 0x20), + wxColour(0x58, 0x9D, 0x1B), + wxColour(0x7E, 0x00, 0x21), + wxColour(0x83, 0xCC, 0xFF), + wxColour(0x31, 0x40, 0x04), + wxColour(0xB0, 0xCF, 0x00), + wxColour(0x4B, 0x1F, 0x6F), + wxColour(0xFF, 0x93, 0x0E), + wxColour(0xC5, 0x00, 0x0D), + wxColour(0x00, 0x84, 0xD1)}; wxUI::wxUI(KissCount* kiss, const wxString& title, const wxPoint& pos, const wxSize& size) - : wxFrame(NULL, wxID_ANY, title, pos, size), _kiss(kiss), _accountPanel(NULL), _searchPanel(NULL), _preferencesPanel(NULL), - _curPanel(NULL), _locale(NULL), _needReload(false) + : wxFrame(NULL, wxID_ANY, title, pos, size), _kiss(kiss), _accountPanel(NULL), _statsPanel(NULL), + _searchPanel(NULL), _preferencesPanel(NULL), _curPanel(NULL), _locale(NULL), _needReload(false) { _hbox = new wxBoxSizer(wxVERTICAL); ButtonPanel* buttons = new ButtonPanel(_kiss, this); @@ -51,6 +63,7 @@ wxUI::~wxUI() if (_accountPanel) delete _accountPanel; if (_preferencesPanel) delete _preferencesPanel; if (_searchPanel) delete _searchPanel; + if (_statsPanel) delete _statsPanel; if (_locale) delete _locale; } @@ -117,6 +130,11 @@ void wxUI::ShowSearch() ShowPanel(_searchPanel); } +void wxUI::ShowStats() +{ + ShowPanel(_statsPanel); +} + void wxUI::ShowPreferences() { ShowPanel(_preferencesPanel); @@ -147,10 +165,14 @@ void wxUI::LoadUser() if (_searchPanel) delete _searchPanel; + if (_statsPanel) + delete _statsPanel; + if (user->_preferences[wxT("language")] != wxT("")) SetLanguage(user->GetLanguage()); _accountPanel = new AccountPanel(_kiss, this); + _statsPanel = new StatsPanel(_kiss, this); _searchPanel = new SearchPanel(_kiss, this); _preferencesPanel = new PreferencesPanel(_kiss, this); @@ -159,7 +181,7 @@ void wxUI::LoadUser() void wxUI::ShowPanel(wxPanel* panel) { - int month, year, account=0, preferences=0, search=0; + int month, year, account=0, preferences=0, search=0, stats=0; wxShowEvent event; if (!panel) return; @@ -189,9 +211,15 @@ void wxUI::ShowPanel(wxPanel* panel) search = 1; } + if (panel == _statsPanel) + { + stats = 1; + } + delete _accountPanel; delete _preferencesPanel; delete _searchPanel; + delete _statsPanel; _accountPanel = new AccountPanel(_kiss, this); if (year != -1) @@ -201,22 +229,28 @@ void wxUI::ShowPanel(wxPanel* panel) } _preferencesPanel = new PreferencesPanel(_kiss, this); _searchPanel = new SearchPanel(_kiss, this); + _statsPanel = new StatsPanel(_kiss, this); if (account) { _accountPanel->OnShow(event); panel = _accountPanel; } - if (preferences) + else if (preferences) { _preferencesPanel->OnShow(event); panel = _preferencesPanel; } - if (search) + else if (search) { _searchPanel->OnShow(event); panel = _searchPanel; } + else if (stats) + { + _statsPanel->OnShow(event); + panel = _statsPanel; + } _needReload = false; } diff --git a/src/view/wxUI.h b/src/view/wxUI.h index 06ee60d..398ae95 100644 --- a/src/view/wxUI.h +++ b/src/view/wxUI.h @@ -27,13 +27,16 @@ along with KissCount. If not, see . #include "UsersDialog.h" #include "GenerateDialog.h" #include "SearchPanel.h" +#include "StatsPanel.h" #include class KissCount; class AccountPanel; class PreferencesPanel; +class StatsPanel; extern wxString months[12]; +extern wxColour categoryColors[12]; class wxUI: public wxFrame { @@ -48,6 +51,7 @@ class wxUI: public wxFrame void LoadUser(); void ShowAccount(); + void ShowStats(); void ShowSearch(); void ShowPreferences(); void GenerateMonth(int month, int year); @@ -63,6 +67,7 @@ class wxUI: public wxFrame KissCount *_kiss; wxBoxSizer *_hbox; AccountPanel *_accountPanel; + StatsPanel *_statsPanel; SearchPanel *_searchPanel; PreferencesPanel *_preferencesPanel; wxPanel *_curPanel;