/* 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}; 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) 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); wxChartPanel* chart ; int i ; User* user = _kiss->GetUser(); std::vector::iterator accountIt; std::vector::iterator categoryIt; DEFAULT_FONT(font); 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)); hbox->Add(&_tree, 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); hbox->Add(vbox, 0); ChangeUser(); Fit(); SetMinSize(wxSize(1024, 640)); 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")); _statsGrid->AutoSizeColumn(0, false); for(i=0; iGetCategoriesNumber(); i++) { _statsGrid->SetCellValue(CATS_STATS+i, 0, _categories[i]); _statsGrid->SetCellAlignment(CATS_STATS+i, 1, wxALIGN_RIGHT, wxALIGN_CENTRE); } 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(); 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); } } 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(); } #define SET_ROW_COLOR(row, color) for(int i=0; iSetCellBackgroundColour(row, i, color); \ } void AccountPanel::ShowMonth(int month, int year) { std::vector operations; std::vector::iterator it; _fixCosts = 0; int curLine = 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]); it = _curOperations->begin(); for (;it != _curOperations->end() && it->fix_cost; it++) InsertOperation(user, &(*it), ++curLine, true); InsertOperation(user, NULL, ++curLine, true); _grid->_fixCosts = _fixCosts--; for (; it != _curOperations->end(); it++) InsertOperation(user, &(*it), ++curLine, false); InsertOperation(user, NULL, ++curLine, false); _grid->AutoSizeColumn(CATEGORY, false); _grid->AutoSizeColumn(DATE, false); _grid->AutoSizeColumn(ACCOUNT, false); _grid->AutoSizeColumn(DELETE, false); _grid->AutoSizeColumn(CHECKED, false); 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::InsertOperation(User* user, Operation* op, int line, bool fix) { std::vector::iterator it; int curLine, curWeek, week, i; _grid->InsertOperation(user, op, line, fix, _curMonth, _curYear); if (fix) _fixCosts++; if (op && !fix) { for (it = _curOperations->begin(), curLine=1; it->fix_cost && it != _curOperations->end(); it++, curLine++) ; if (it == _curOperations->end()) return; curLine++; curWeek = wxDateTime(it->day+1, (wxDateTime::Month)it->month, it->year).GetWeekOfMonth(); for (i=1, it++; it != _curOperations->end(); it++, curLine++) { week = wxDateTime(it->day+1, (wxDateTime::Month)it->month, it->year).GetWeekOfMonth(); if (week != curWeek) { _grid->SetWeek(i++, curLine); curWeek = week; } } } _wxUI->Layout(); } 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(); _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, percents; std::map curAccountAmount, finalAccountAmount; std::map::iterator doubleIt; std::map::iterator intIt; std::vector::iterator accountIt; unsigned int day; day = _calendar->GetDate().GetDay()-1; curCredit = curDebit = totalCredit = totalDebit = 0.0; 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->amount > 0) { if (day >= it->day) { curCredit += it->amount; curAccountAmount[it->account] += it->amount; } totalCredit += it->amount; finalAccountAmount[it->account] += it->amount; } else { _categoriesValues[_categoriesIndexes[user->GetCategoryName(it->category)]] += -it->amount ; if (day >= it->day) { curDebit += -it->amount; curAccountAmount[it->account] += it->amount; } totalDebit += -it->amount; finalAccountAmount[it->account] += it->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++) { percents = ((double) (_categoriesValues[i]*100))/totalDebit; _statsGrid->SetCellValue(CATS_STATS+i, 1, wxString::Format(wxT("%.2lf (%d %%)"), _categoriesValues[i], (int)percents)); } for (i=0, accountIt=user->_accounts.begin(); accountIt!=user->_accounts.end(); accountIt++, i++) { 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)); } _statsGrid->AutoSizeColumn(1, true); _pie->DatasetChanged(_dataset); } void AccountPanel::OnOperationModified(wxGridEvent& event) { User* user = _kiss->GetUser(); int row = event.GetRow()-1; int col = event.GetCol(); Operation new_op, cur_op, op_tmp; int op_complete = 6, i; wxString value ; wxDateTime date; bool need_insertion = false, fix_op=false; static bool inModification = false ; wxColour color ; unsigned char r, g, b; // Avoid recursives calls if (inModification) return; inModification = true ; if (event.GetCol() == DEBIT) _grid->SetCellValue(event.GetRow(), CREDIT, wxT("")); else if (event.GetCol() == CREDIT) _grid->SetCellValue(event.GetRow(), DEBIT, wxT("")); value = _grid->GetCellValue(event.GetRow(), DESCRIPTION); if (value != wxT("")) { new_op.description = value; op_complete--; } value = _grid->GetCellValue(event.GetRow(), DATE); if (value != wxT("")) { date.ParseFormat(value, wxT("%d/%m/%Y")); new_op.day = date.GetDay()-1; new_op.month = date.GetMonth(); new_op.year = date.GetYear(); op_complete--; } value = _grid->GetCellValue(event.GetRow(), DEBIT); if (value != wxT("")) { value.ToDouble(&new_op.amount); new_op.amount *= -1.0; op_complete--; } value = _grid->GetCellValue(event.GetRow(), CREDIT); if (value != wxT("")) { value.ToDouble(&new_op.amount); op_complete--; } value = _grid->GetCellValue(event.GetRow(), CATEGORY); if (value != wxT("")) { new_op.category = user->GetCategoryId(value); op_complete--; } value = _grid->GetCellValue(event.GetRow(), ACCOUNT); if (value != wxT("")) { new_op.account = user->GetAccountId(value); op_complete--; } value = _grid->GetCellValue(event.GetRow(), CHECKED); if (value != wxT("") && value != wxT("0")) new_op.checked = true; else new_op.checked = false; op_complete--; if (event.GetCol() == DESCRIPTION && _grid->GetCellValue(event.GetRow(), CATEGORY) == wxT("") && _grid->GetCellValue(event.GetRow(), ACCOUNT) == wxT("")) { if (_kiss->SearchPreviousOperation(&op_tmp, new_op.description, _curMonth-3, _curYear)) { new_op.category = op_tmp.category; new_op.account = op_tmp.account; _grid->SetCellValue(event.GetRow(), CATEGORY, user->GetCategoryName(new_op.category)); _grid->SetCellValue(event.GetRow(), ACCOUNT, user->GetAccountName(new_op.account)); op_complete -= 2; } } if (col == CHECKED || col == CATEGORY) { color = user->GetCategory(new_op.category).color; if (new_op.checked) { r = ((color.Red()*1.5) >= 0xFF) ? 0xFF : color.Red()*1.5 ; g = ((color.Green()*1.5) >= 0xFF) ? 0xFF : color.Green()*1.5 ; b = ((color.Blue()*1.5) >= 0xFF) ? 0xFF : color.Blue()*1.5 ; color.Set(r, g, b, color.Alpha()); } SET_ROW_COLOR(event.GetRow(), color); } if (col == DELETE) { wxMessageDialog dialog(_wxUI, _("Are you sure want to delete : \n")+new_op.description, wxT("KissCount"), wxYES_NO); if (dialog.ShowModal() == wxID_NO) { _grid->SetCellValue(event.GetRow(), event.GetCol(), wxT("0")); inModification = false; return; } } // Penser au fix implosif // Modify a fix operation if (row < _fixCosts) { cur_op = (*_curOperations)[row] ; if (col == DELETE) { _grid->DeleteRows(event.GetRow(), 1); _curOperations->erase(_curOperations->begin()+row); _kiss->DeleteOperation(cur_op); _grid->_fixCosts = _fixCosts--; UpdateStats(); inModification = false ; return ; } new_op.id = cur_op.id; new_op.fix_cost = true; if (cur_op.day != new_op.day) { need_insertion = true; _grid->DeleteRows(event.GetRow(), 1); _curOperations->erase(_curOperations->begin()+row); _fixCosts--; } else (*_curOperations)[row] = new_op; _kiss->UpdateOperation(new_op); fix_op = true; } // Add a fixCost else if (row == _fixCosts) { if (op_complete) { inModification = false ; return ; } need_insertion = true; fix_op = true; new_op.fix_cost = true; for(i=0; iSetCellValue(event.GetRow(), i, wxT("")); } new_op.id = _kiss->AddOperation(new_op); } // Modify an operation else if (row <= user->GetOperationsNumber(_curMonth, _curYear)) { row--; cur_op = (*_curOperations)[row] ; new_op.id = cur_op.id; new_op.fix_cost = false; if (col == DELETE) { _grid->DeleteRows(event.GetRow(), 1); _curOperations->erase(_curOperations->begin()+row); _kiss->DeleteOperation(cur_op); UpdateStats(); inModification = false ; return ; } if (cur_op.day != new_op.day) { need_insertion = true; _grid->DeleteRows(event.GetRow(), 1); _curOperations->erase(_curOperations->begin()+row); } else (*_curOperations)[row] = new_op; _kiss->UpdateOperation(new_op); } // Add an operation else { row--; if (op_complete) { inModification = false ; return ; } need_insertion = true; fix_op = false; new_op.fix_cost = false; for(i=0; iSetCellValue(event.GetRow(), i, wxT("")); } new_op.id = _kiss->AddOperation(new_op); } if (need_insertion) { for(i=0; i<(int)_curOperations->size(); i++) { if ((*_curOperations)[i].fix_cost && !fix_op) continue; if (!(*_curOperations)[i].fix_cost && fix_op) break; if (user->_preferences[wxT("operation_order")] == wxT("ASC")) { if ((*_curOperations)[i].day > new_op.day) break; } else { if ((*_curOperations)[i].day < new_op.day) break; } } _curOperations->insert(_curOperations->begin()+i ,new_op); i++; // For header if (!fix_op) i++; InsertOperation(user, &new_op, i, fix_op); if (fix_op) _grid->_fixCosts = _fixCosts+1; } UpdateStats(); inModification = false ; } void AccountPanel::OnAccountModified(wxGridEvent& event) { User* user = _kiss->GetUser(); int row = event.GetRow(); double amount; wxString id = user->GetAccountId(_accounts[row]); _accountsGrid->GetCellValue(row, event.GetCol()).ToDouble(&amount); _kiss->SetAccountAmount(_curMonth, _curYear, id, amount); _accountsInitValues[id] = amount; UpdateStats(); } 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) { 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(); }