/* 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 "AccountPanel.h" enum {ACCOUNT_NUMBER, ACCOUNT_NAME, ACCOUNT_INIT, ACCOUNT_CUR, ACCOUNT_FINAL, NUMBER_COLS_ACCOUNTS}; enum {CUR_CREDIT, CUR_DEBIT, TOTAL_CREDIT, TOTAL_DEBIT, REMAINS, STATS_ROW, CATS_STATS}; enum {CALENDAR_TREE_ID=1, OPS_GRID_ID, CALENDAR_ID, ACCOUNTS_GRID_ID, MENU_GENERATE_ID, MENU_DELETE_ID, CHECK_MODE_ID, GROUP_ID, UNGROUP_ID}; BEGIN_EVENT_TABLE(AccountPanel, wxPanel) EVT_GRID_CMD_CELL_CHANGE(OPS_GRID_ID, AccountPanel::OnOperationModified) EVT_GRID_CMD_CELL_CHANGE(ACCOUNTS_GRID_ID, AccountPanel::OnAccountModified) EVT_TREE_ITEM_RIGHT_CLICK(CALENDAR_TREE_ID, AccountPanel::OnTreeRightClick) EVT_TREE_SEL_CHANGED(CALENDAR_TREE_ID, AccountPanel::OnTreeChange) EVT_TREE_KEY_DOWN(CALENDAR_TREE_ID, AccountPanel::OnTreeChange) EVT_MENU(MENU_GENERATE_ID, AccountPanel::OnMenuGenerate) EVT_MENU(MENU_DELETE_ID, AccountPanel::OnMenuDelete) EVT_SHOW(AccountPanel::OnShow) EVT_CALENDAR_SEL_CHANGED(CALENDAR_ID, AccountPanel::OnCalendarChange) EVT_CHECKBOX(CHECK_MODE_ID, AccountPanel::OnCheckMode) EVT_BUTTON(GROUP_ID, AccountPanel::OnGroup) EVT_BUTTON(UNGROUP_ID, AccountPanel::OnUnGroup) END_EVENT_TABLE() AccountPanel::AccountPanel(KissCount* kiss, wxUI *parent) : wxScrolledWindow(&(*parent)), _curMonth(-1), _curYear(-1), _kiss(kiss), _wxUI(parent), _tree(this, CALENDAR_TREE_ID, wxDefaultPosition, wxDefaultSize, wxTR_HIDE_ROOT) { wxBoxSizer *hbox = new wxBoxSizer(wxHORIZONTAL); wxBoxSizer *hbox2 = new wxBoxSizer(wxHORIZONTAL); wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL); wxBoxSizer *vbox2 = new wxBoxSizer(wxVERTICAL); wxBoxSizer *vbox3 = new wxBoxSizer(wxVERTICAL); wxChartPanel* chart ; int i ; User* user = _kiss->GetUser(); std::vector::iterator accountIt; std::vector::iterator categoryIt; DEFAULT_FONT(font); wxRect rect = wxDisplay().GetGeometry(); SetSizer(hbox); ColorScheme* colorScheme = new ColorScheme(categoryColors, WXSIZEOF(categoryColors)); _pie = new PiePlot(); _calendar = new wxCalendarCtrl(this, CALENDAR_ID, wxDefaultDateTime, wxDefaultPosition, wxDefaultSize, wxCAL_MONDAY_FIRST | wxCAL_NO_MONTH_CHANGE | wxCAL_SEQUENTIAL_MONTH_SELECTION); _calendar->EnableMonthChange(false); _calendar->EnableYearChange(false); _calendar->EnableHolidayDisplay(false); _calendar->Enable(false); _accounts = new wxString[user->GetAccountsNumber()]; for (i=0, accountIt = user->_accounts.begin(); accountIt != user->_accounts.end(); accountIt++, i++) _accounts[i] = accountIt->name; _categories = new wxString[user->GetCategoriesNumber()] ; for(i=0, categoryIt = user->_categories.begin(); categoryIt != user->_categories.end(); categoryIt++, i++) { _categories[i] = categoryIt->name ; _categoriesIndexes[categoryIt->name] = i; } _dataset = new CategorySimpleDataset(_categories, user->GetCategoriesNumber()); _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)); _grid = new GridAccount(_kiss, this, OPS_GRID_ID); _accountsGrid = new wxGrid(this, ACCOUNTS_GRID_ID); _accountsGrid->CreateGrid(0, NUMBER_COLS_ACCOUNTS); _accountsGrid->SetRowLabelSize(0); _accountsGrid->SetDefaultCellFont(font); _accountsGrid->SetColLabelValue(ACCOUNT_NUMBER, _("Account number")); _accountsGrid->SetColLabelValue(ACCOUNT_NAME, _("Account name")); _accountsGrid->SetColLabelValue(ACCOUNT_INIT, _("Initial value")); _accountsGrid->SetColLabelValue(ACCOUNT_CUR, _("Current value")); _accountsGrid->SetColLabelValue(ACCOUNT_FINAL, _("Final value")); _accountsGrid->AutoSizeColumns(true); _statsGrid = new wxGrid(this, wxID_ANY); chart = new wxChartPanel(this); chart->SetChart(new Chart(_pie, _("Cost repartition"))); chart->Fit(); chart->Layout(); chart->SetMinSize(// chart->GetSize() wxSize(200,250)); _checkCheckMode = new wxCheckBox(this, CHECK_MODE_ID, _("Check mode")); _tree.SetIndent(5); wxButton* buttonGroup = new wxButton(this, GROUP_ID, _("Group")); wxButton* buttonUnGroup = new wxButton(this, UNGROUP_ID, _("UnGroup")); vbox3->Add(&_tree, 0); vbox3->Add(-1, 30); vbox3->Add(buttonGroup, 0); vbox3->Add(-1, 10); vbox3->Add(buttonUnGroup, 0); hbox->Add(vbox3, 0); hbox2->Add(_accountsGrid, 0); hbox2->Add(_calendar, 0); vbox2->Add(hbox2, 0); vbox2->Add(-1, 10); vbox2->Add(_grid, 0); hbox->Add(vbox2, 0); vbox->Add(_statsGrid, 0); vbox->Add(-1, 10); vbox->Add(chart, 0); hbox->Add(-1, 10); vbox->Add(_checkCheckMode, 0); hbox->Add(-1, 10); hbox->Add(vbox, 0); ChangeUser(); Fit(); SetMinSize(wxSize(rect.width-rect.x, rect.height-rect.y-128)); SetScrollbars(10, 10, 100/10, 100/10); } AccountPanel::~AccountPanel() { delete[] _categoriesValues; delete[] _categories; delete[] _accounts; } void AccountPanel::InitStatsGrid(User* user) { int i; DEFAULT_FONT(font); if (!_statsGrid->GetNumberRows()) { _statsGrid->CreateGrid(user->GetCategoriesNumber()+6, 2); _statsGrid->SetColLabelSize(0); _statsGrid->SetRowLabelSize(0); _statsGrid->EnableEditing(false); } else { _statsGrid->DeleteRows(0, _statsGrid->GetNumberRows()); _statsGrid->InsertRows(0, user->GetCategoriesNumber()+6); } _statsGrid->SetDefaultCellFont(font); _statsGrid->SetCellValue(TOTAL_CREDIT, 0, _("Total Credit")); _statsGrid->SetCellValue(TOTAL_DEBIT, 0, _("Total Debit")); for(i=0; iGetCategoriesNumber(); i++) { _statsGrid->SetCellValue(CATS_STATS+i, 0, _categories[i]); _statsGrid->SetCellAlignment(CATS_STATS+i, 1, wxALIGN_RIGHT, wxALIGN_CENTRE); } _statsGrid->AutoSizeColumn(0, false); font.SetWeight(wxFONTWEIGHT_BOLD); _statsGrid->SetCellFont(CUR_CREDIT, 0, font); _statsGrid->SetCellFont(CUR_DEBIT, 0, font); _statsGrid->SetCellFont(REMAINS, 0, font); _statsGrid->SetCellFont(REMAINS, 1, font); _statsGrid->SetCellValue(CUR_CREDIT, 0, _("Cur Credit")); _statsGrid->SetCellValue(CUR_DEBIT, 0, _("Cur Debit")); _statsGrid->SetCellValue(REMAINS, 0, _("Remains")); _statsGrid->SetCellAlignment(CUR_DEBIT, 1, wxALIGN_RIGHT, wxALIGN_CENTRE); _statsGrid->SetCellAlignment(CUR_CREDIT, 1, wxALIGN_RIGHT, wxALIGN_CENTRE); _statsGrid->SetCellAlignment(TOTAL_DEBIT, 1, wxALIGN_RIGHT, wxALIGN_CENTRE); _statsGrid->SetCellAlignment(TOTAL_CREDIT, 1, wxALIGN_RIGHT, wxALIGN_CENTRE); _statsGrid->SetCellAlignment(REMAINS, 1, wxALIGN_RIGHT, wxALIGN_CENTRE); } void AccountPanel::ChangeUser() { User* user = _kiss->GetUser(); int curYear = -1; wxDateTime curDate; wxTreeItemId rootNode, curNode; std::map > ops; std::map >::iterator it; ops = _kiss->GetAllOperations(); InitStatsGrid(user); _tree.DeleteAllItems(); rootNode = _tree.AddRoot(wxT("")); curDate.SetToCurrent(); if (ops.size()) { for(it = ops.begin(); it != ops.end(); it++) { if ((int)it->first <= curDate.GetYear()) { curYear = it->first; curNode = _tree.AppendItem(rootNode, wxString::Format(wxT("%d"), it->first)); } else _tree.AppendItem(rootNode, wxString::Format(wxT("%d"), it->first)); } Fit(); if (curYear != -1) { _tree.SelectItem(curNode, true); LoadYear(curYear); } } else { curNode = _tree.AppendItem(rootNode, wxString::Format(wxT("%d"), curDate.GetYear())); _tree.AppendItem(curNode, months[(int)curDate.GetYear()]); Fit(); } } void AccountPanel::LoadYear(int year, bool showMonth) { User* user = _kiss->GetUser(); int curMonth = -1; wxDateTime curDate; wxTreeItemId parentNode, curMonthNode; std::map > ops ; std::vector::iterator it; if (user->_operations[year] && _tree.GetChildrenCount(_tree.GetSelection(), true)) { if (showMonth) ShowMonth(-1, year); return; } _curYear = year ; _kiss->LoadYear(year); ops = _kiss->GetAllOperations(); curDate.SetToCurrent(); parentNode = _tree.GetSelection(); for (it = ops[year].begin(); it != ops[year].end(); it++) { if (curMonth == -1 || (year == curDate.GetYear() && *it <= curDate.GetMonth())) { curMonth = *it; curMonthNode = _tree.AppendItem(parentNode, months[*it]); } else _tree.AppendItem(parentNode, months[*it]); } _tree.Expand(parentNode); Fit(); if (showMonth) { _tree.SelectItem(curMonthNode, true); ShowMonth(curMonth, year); } _wxUI->Layout(); } void AccountPanel::ShowMonth(int month, int year) { std::vector operations; _fixCosts = 0; User* user = _kiss->GetUser(); DEFAULT_FONT(font); std::vector::iterator categoryIt; std::map >::iterator monthIt; wxDateTime curDate; curDate.SetToCurrent(); if (month == -1) { // Near month if (year == curDate.GetYear()) { for (monthIt = user->_operations[year]->begin(); monthIt != user->_operations[year]->end(); monthIt++) { if ((int)monthIt->first <= curDate.GetMonth()) { month = monthIt->first; } } } // First month if (month == -1) { monthIt = user->_operations[year]->begin(); if (user->_operations[year]->size() == 0 && year == curDate.GetYear()) month = curDate.GetMonth(); else month = monthIt->first; } } _curYear = year; _curMonth = month; _wxUI->SetTitle(user->_name + wxT(" - ") + months[month] + wxT(" ") + wxString::Format(wxT("%d"), year)); _calendar->Enable(true); if (_grid->GetNumberRows() > 1) _grid->DeleteRows(1, _grid->GetNumberRows()-1); // Operations are ordered _curOperations = &((*user->_operations[year])[month]); _grid->LoadOperations(_curOperations, true, true, _curMonth, _curYear); InitAccountsGrid(user, month, year); _calendar->EnableMonthChange(true); _calendar->EnableYearChange(true); if (curDate.GetMonth() == month && curDate.GetYear() == year) _calendar->SetDate(curDate) ; else if (curDate.GetMonth() > month || curDate.GetYear() > year) _calendar->SetDate(curDate.GetLastMonthDay((wxDateTime::Month)month, year)); else if (curDate.GetMonth() < month || curDate.GetYear() < year) _calendar->SetDate(wxDateTime(1, (wxDateTime::Month)month, year)); _calendar->EnableMonthChange(false); _calendar->EnableYearChange(false); _calendar->SetSize(_calendar->GetMinSize()); UpdateStats(); Fit(); // SetMinSize(GetSize()); } void AccountPanel::InitAccountsGrid(User* user, int month, int year) { std::vector::iterator it; int curLine = 0; double value; int i, a; DEFAULT_FONT(font); if (_accountsGrid->GetNumberRows()) _accountsGrid->DeleteRows(0, _accountsGrid->GetNumberRows()); font.SetWeight(wxFONTWEIGHT_BOLD); for (i=0, it = user->_accounts.begin(); it != user->_accounts.end(); i++, it++, curLine++) { _accountsGrid->AppendRows(); if (it->shared) _accountsGrid->SetCellValue(curLine, ACCOUNT_NUMBER, it->number + wxT("*")); else _accountsGrid->SetCellValue(curLine, ACCOUNT_NUMBER, it->number); _accountsGrid->SetCellValue(curLine, ACCOUNT_NAME, it->name); value = _kiss->GetAccountAmount(it->id, month, year); _accountsGrid->SetCellEditor(curLine, ACCOUNT_INIT, new wxGridCellFloatEditor(-1, 2)); _accountsGrid->SetCellValue(curLine, ACCOUNT_INIT, wxString::Format(wxT("%.2lf"), value)); for (a=0; aSetReadOnly(curLine, a, a != ACCOUNT_INIT); _accountsGrid->SetCellFont(curLine, ACCOUNT_CUR, font); _accountsInitValues[it->id] = value; _accountsGrid->SetCellAlignment(curLine, ACCOUNT_INIT, wxALIGN_RIGHT, wxALIGN_CENTRE); _accountsGrid->SetCellAlignment(curLine, ACCOUNT_CUR, wxALIGN_RIGHT, wxALIGN_CENTRE); _accountsGrid->SetCellAlignment(curLine, ACCOUNT_FINAL, wxALIGN_RIGHT, wxALIGN_CENTRE); } _accountsGrid->AutoSizeColumns(true); } void AccountPanel::UpdateStats() { int i; User* user = _kiss->GetUser(); std::vector::iterator it; double curCredit, curDebit, totalCredit, totalDebit, remains, value, value2, percents; std::map curAccountAmount, finalAccountAmount; std::map::iterator doubleIt; std::map::iterator intIt; std::vector::iterator accountIt; unsigned int day; bool checkMode = _checkCheckMode->IsChecked(); std::map* notChecked = NULL; Account account; Operation op; bool blocked_account ; curCredit = curDebit = totalCredit = totalDebit = percents = 0.0; if (checkMode) { notChecked = _kiss->GetNotChecked(_curMonth, _curYear); } day = _calendar->GetDate().GetDay()-1; for (i=0; iGetCategoriesNumber(); i++) _categoriesValues[i] = 0.0; for (doubleIt=_accountsInitValues.begin(); doubleIt!=_accountsInitValues.end(); doubleIt++) { curAccountAmount[doubleIt->first] = _accountsInitValues[doubleIt->first]; finalAccountAmount[doubleIt->first] = _accountsInitValues[doubleIt->first]; } for (it=_curOperations->begin(); it!=_curOperations->end(); it++) { if (it->meta) continue; op = *it; blocked_account = false; // A credit on a blocked account must be considered as a debit if (op.transfert.Length() && op.amount > 0) { account = user->GetAccount(op.account); if (account.blocked) { op.amount = -op.amount; op.transfert = wxT(""); blocked_account = true; } } if (op.amount >= 0) { if (!op.transfert.Length()) totalCredit += op.amount; if (day >= op.day) { if (!op.transfert.Length()) curCredit += op.amount; if (!checkMode || (checkMode && op.checked)) curAccountAmount[op.account] += op.amount; } if (!checkMode || (checkMode && op.checked)) finalAccountAmount[op.account] += op.amount; } else { if (!op.transfert.Length()) _categoriesValues[_categoriesIndexes[user->GetCategoryName(op.category)]] += -op.amount ; if (!op.transfert.Length()) totalDebit += -op.amount; if (blocked_account) op.amount = -op.amount; if (day >= op.day) { if (!op.transfert.Length()) curDebit += -op.amount; if (!checkMode || (checkMode && op.checked)) curAccountAmount[op.account] += op.amount; } if (!checkMode || (checkMode && op.checked)) finalAccountAmount[op.account] += op.amount; } } remains = totalCredit - totalDebit; _statsGrid->SetCellValue(CUR_CREDIT, 1, wxString::Format(wxT("%.2lf"), curCredit)); _statsGrid->SetCellValue(CUR_DEBIT, 1, wxString::Format(wxT("%.2lf"), curDebit)); _statsGrid->SetCellValue(TOTAL_CREDIT, 1, wxString::Format(wxT("%.2lf"), totalCredit)); _statsGrid->SetCellValue(TOTAL_DEBIT, 1, wxString::Format(wxT("%.2lf"), totalDebit)); _statsGrid->SetCellTextColour(REMAINS, 1, (remains >= 0) ? wxColor(0x00, 0xFF, 0x00) : wxColor(0xFF, 0x00, 0x00)); _statsGrid->SetCellValue(REMAINS, 1, wxString::Format(wxT("%.2lf"), remains)); for(i=0; iGetCategoriesNumber()+1; i++) { if (totalDebit != 0) percents = ((double) (_categoriesValues[i]*100))/totalDebit; else percents = 0.0; _statsGrid->SetCellValue(CATS_STATS+i, 1, wxString::Format(wxT("%.2lf (%02d %%)"), _categoriesValues[i], (int)percents)); } for (i=0, accountIt=user->_accounts.begin(); accountIt!=user->_accounts.end(); accountIt++, i++) { if (!checkMode || !notChecked) { value = _accountsInitValues[accountIt->id]; _accountsGrid->SetCellValue(i, ACCOUNT_INIT, wxString::Format(wxT("%.2lf"), value)); value = curAccountAmount[accountIt->id]; _accountsGrid->SetCellValue(i, ACCOUNT_CUR, wxString::Format(wxT("%.2lf"), value)); _accountsGrid->SetCellTextColour(i, ACCOUNT_CUR, (value >= 0.0) ? wxColor(0x00, 0x00, 0x00) : wxColor(0xFF, 0x00, 0x00)); value = finalAccountAmount[accountIt->id]; _accountsGrid->SetCellValue(i, ACCOUNT_FINAL, wxString::Format(wxT("%.2lf"), value)); } else { value = _accountsInitValues[accountIt->id]; value2 = (*notChecked)[accountIt->id]; _accountsGrid->SetCellValue(i, ACCOUNT_INIT, wxString::Format(wxT("%.2lf (%.2lf)"), value, value-value2)); value = curAccountAmount[accountIt->id]; _accountsGrid->SetCellValue(i, ACCOUNT_CUR, wxString::Format(wxT("%.2lf (%.2lf)"), value, value-value2)); _accountsGrid->SetCellTextColour(i, ACCOUNT_CUR, (value >= 0.0) ? wxColor(0x00, 0x00, 0x00) : wxColor(0xFF, 0x00, 0x00)); value = finalAccountAmount[accountIt->id]; _accountsGrid->SetCellValue(i, ACCOUNT_FINAL, wxString::Format(wxT("%.2lf (%.2lf)"), value, value-value2)); } } _accountsGrid->AutoSizeColumn(ACCOUNT_INIT, true); _accountsGrid->AutoSizeColumn(ACCOUNT_CUR, true); _accountsGrid->AutoSizeColumn(ACCOUNT_FINAL, true); if (notChecked) delete notChecked; _statsGrid->AutoSizeColumn(1, true); _pie->DatasetChanged(_dataset); Layout(); } void AccountPanel::OnOperationModified(wxGridEvent& event) { UpdateStats(); } void AccountPanel::OnAccountModified(wxGridEvent& event) { User* user = _kiss->GetUser(); int row = event.GetRow(); double amount; wxString id = user->GetAccountId(_accounts[row]); static bool inModification = false; if (inModification) return ; inModification = true; _accountsGrid->GetCellValue(row, event.GetCol()).ToDouble(&amount); _kiss->SetAccountAmount(_curMonth, _curYear, id, amount); _accountsInitValues[id] = amount; UpdateStats(); inModification = false; } void AccountPanel::OnTreeRightClick(wxTreeEvent& event) { wxMenu menu(0); menu.Append(MENU_GENERATE_ID, _("Generate month")); menu.AppendSeparator(); if (_tree.GetCount() > 1) menu.Append(MENU_DELETE_ID, _("Delete")); PopupMenu(&menu, event.GetPoint()); } void AccountPanel::OnTreeChange(wxTreeEvent& event) { int month=-1, year; int i; wxString monthString; static bool inModification = false ; if (inModification) return; inModification = true; monthString = _tree.GetItemText(event.GetItem()); for (i=0; i<12; i++) if (monthString == months[i]) { month = i; break; } if (month == -1) { year = wxAtoi(monthString); // Error if (year == 0) { inModification = false; return; } if (year == _curYear) { inModification = false; return; } // _tree.CollapseAll(); // _tree.Expand(event.GetItem()); LoadYear(year, false); } else { year = wxAtoi(_tree.GetItemText(_tree.GetItemParent(event.GetItem()))); // Error if (year == 0) { inModification = false; return; } if (year != _curYear || month != _curMonth) { ShowMonth(month, year); } } inModification = false; } void AccountPanel::GetTreeSelection(int* month, int* year) { wxString monthString; int i; *month = -1; *year = -1; monthString = _tree.GetItemText(_tree.GetSelection()); for (i=0; i<12; i++) if (monthString == months[i]) { *month = i; break; } if (*month == -1) { *year = wxAtoi(monthString); // Error if (year == 0) { *month = -1; *year = -1; return; } } else { *year = wxAtoi(_tree.GetItemText(_tree.GetItemParent(_tree.GetSelection()))); // Error if (year == 0) { *month = -1; *year = -1; return; } } } void AccountPanel::OnMenuGenerate(wxCommandEvent& event) { int month, year; wxDateTime curDate; curDate.SetToCurrent(); GetTreeSelection(&month, &year); if (month == -1 && year == curDate.GetYear()) { month = _curMonth; } GenerateDialog g(_kiss, _wxUI, month, year); g.ShowModal(); } void AccountPanel::OnMenuDelete(wxCommandEvent& event) { int month, year; wxString message; wxTreeItemId curNode, node ; std::map > ops ; GetTreeSelection(&month, &year); ops = _kiss->GetAllOperations(); if (ops.size() == 1 && (ops[year].size() == 1 || month == -1)) { wxMessageBox(_("It must be at least one month !"), _("Error"), wxICON_ERROR | wxOK); return; } message = _("Are you sure want to delete "); if (month != -1) message += months[month] + wxT(" "); message += wxString::Format(wxT("%d"), year); message += _(" operations ?"); wxMessageDialog dialog(_wxUI, message, wxT("KissCount"), wxYES_NO); if (dialog.ShowModal() == wxID_NO) return; curNode = _tree.GetSelection(); if (ops[year].size() == 1 && month != -1) curNode = _tree.GetItemParent(curNode); _kiss->DeleteOperations(month, year); node = _tree.GetNextSibling(curNode); if (!node.IsOk()) node = _tree.GetPrevSibling(curNode); _tree.Delete(curNode); if (!node.IsOk()) ChangeUser(); else { _tree.SelectItem(node); GetTreeSelection(&month, &year); if (month == -1) month = ops[year][0]; ShowMonth(month, year); } } void AccountPanel::GenerateMonth(int month, int year) { wxTreeItemId root, years, node ; wxTreeItemIdValue cookie; wxString monthString, yearString; std::map > ops ; std::vector::iterator it ; int i; root = _tree.GetRootItem(); yearString = wxString::Format(wxT("%d"), year); monthString = months[month]; ops = _kiss->GetAllOperations(); if (_tree.GetChildrenCount(root, true) < 1) { node = _tree.AppendItem(root, yearString); node = _tree.AppendItem(node, monthString); _tree.SelectItem(node, true); ShowMonth(month, year); return ; } years = _tree.GetFirstChild(root, cookie); while (years.IsOk()) { if (_tree.GetItemText(years) == yearString) break; if (wxAtoi(_tree.GetItemText(years)) > year) { years = _tree.GetPrevSibling(years); if (!years.IsOk()) years = _tree.PrependItem(root, yearString); else years = _tree.InsertItem(root, years, yearString); break; } years = _tree.GetNextSibling(years); } if (!years.IsOk()) { years = _tree.GetFirstChild(root, cookie); if (wxAtoi(_tree.GetItemText(years)) > year) years = _tree.PrependItem(root, yearString); else years = _tree.AppendItem(root, yearString); } if (!_tree.GetChildrenCount(years, true)) node = _tree.AppendItem(years, monthString); else { for(i=0, it = ops[year].begin(); it != ops[year].end(); it++, i++) { if (*it > month) break; } if (it == ops[year].end()) years = _tree.AppendItem(years, monthString); else years = _tree.InsertItem(years, i-1, monthString); } _tree.SelectItem(node, true); ShowMonth(month, year); } void AccountPanel::OnShow(wxShowEvent& event) { if (_curMonth != -1) _wxUI->SetTitle(_kiss->GetUser()->_name + wxT(" - ") + months[_curMonth] + wxT(" ") + wxString::Format(wxT("%d"), _curYear)); else _wxUI->SetTitle(_kiss->GetUser()->_name); } void AccountPanel::OnCalendarChange(wxCalendarEvent& event) { UpdateStats(); } void AccountPanel::OnCheckMode(wxCommandEvent& event) { UpdateStats(); } void AccountPanel::OnGroup(wxCommandEvent& event) { _grid->Group(); } void AccountPanel::OnUnGroup(wxCommandEvent& event) { _grid->UnGroup(); }