#include "AccountPanel.h" static wxString colsName[] = {_("Description"), _("Date"), _("Debit"), _("Credit"), _("Category"), _("Account"), _("")}; BEGIN_EVENT_TABLE(AccountPanel, wxPanel) EVT_GRID_CMD_CELL_CHANGE(OPS_GRID_ID, AccountPanel::OnOperationModified) END_EVENT_TABLE() AccountPanel::AccountPanel(KissCount* kiss, wxUI *parent) : wxPanel(&(*parent)), _kiss(kiss), _wxUI(parent), _tree(this, CALENDAR_TREE_ID) { wxBoxSizer *hbox = new wxBoxSizer(wxHORIZONTAL); wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL); wxBoxSizer *vbox2 = new wxBoxSizer(wxVERTICAL); wxChartPanel* chart ; int i ; DEFAULT_FONT(font); User* user = _kiss->GetUser(); std::map::iterator accountIt; std::map::iterator it; 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)}; SetSizer(hbox); ColorScheme* colorScheme = new ColorScheme(categoryColors, WXSIZEOF(categoryColors)); _pie = new PiePlot(); _accounts = new wxString[user->_accounts.size()+1]; _accounts[0] = _("Unknown"); for (i=1, accountIt = user->_accounts.begin(); accountIt != user->_accounts.end(); accountIt++, i++) _accounts[i] = user->_accounts[accountIt->first].name; _categories = new wxString[user->GetCategoriesNumber()+1] ; _categories[0] = _("Unknown"); _categoriesIndexes[_("Unknown")] = 0; for(i=1, it = user->_preferences._categories.begin(); it != user->_preferences._categories.end(); it++, i++) { _categories[i] = it->second ; _categoriesIndexes[it->second] = i; } _dataset = new CategorySimpleDataset(_categories, user->GetCategoriesNumber()+1); _categoriesValues = new double[user->GetCategoriesNumber()+1]; for(i=0; iGetCategoriesNumber()+1; i++) _categoriesValues[i] = 0.0; _dataset->AddSerie(_("Serie 1"), _categoriesValues, user->GetCategoriesNumber()+1); _dataset->SetRenderer(new CategoryRenderer(*colorScheme)); _pie->SetDataset(_dataset); _pie->SetColorScheme(colorScheme); _pie->SetLegend(new Legend(wxBOTTOM, wxCENTER)); _grid = new GridAccount(this, OPS_GRID_ID); _grid->CreateGrid(1, NUMBER_COLS_OPS); _grid->SetColLabelSize(0); _grid->SetRowLabelSize(0); _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, -1); _statsGrid->CreateGrid(user->GetCategoriesNumber()+1+6, 2); _statsGrid->SetColLabelSize(0); _statsGrid->SetRowLabelSize(0); _statsGrid->EnableEditing(false); InitStatsGrid(user); 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); vbox2->Add(_accountsGrid, 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(GetSize()); } AccountPanel::~AccountPanel() { delete[] _categoriesValues; delete[] _categories; delete[] _accounts; } void AccountPanel::InitStatsGrid(User* user) { int i; DEFAULT_FONT(font); _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()+1; i++) _statsGrid->SetCellValue(CATS_STATS+i, 0, _categories[i]); 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")); } void AccountPanel::ChangeUser() { User* user = _kiss->GetUser(); int curYear = -1; std::map >* >::iterator it; wxDateTime curDate; curDate.SetToCurrent(); for(it = user->_operations.begin(); it != user->_operations.end(); it++) { if ((int)it->first <= curDate.GetYear()) curYear = it->first; _tree.AddRoot(wxString::Format(wxT("%d"), it->first)); } if (curYear != -1) LoadYear(curYear); } void AccountPanel::LoadYear(int year) { User* user = _kiss->GetUser(); int curMonth = -1; std::map >::iterator it; wxDateTime curDate; wxTreeItemId parentNode, curMonthNode; _curYear = year ; if (user->_operations[year] != NULL) { ShowMonth(year, 0); return; } _kiss->LoadYear(year); curDate.SetToCurrent(); parentNode = _tree.GetSelection(); for (it = user->_operations[year]->begin(); it != user->_operations[year]->end(); it++) { if (year == curDate.GetYear() && (int)it->first <= curDate.GetMonth()) { curMonth = it->first; curMonthNode = _tree.AppendItem(parentNode, months[it->first]); } else if(curMonth == -1) { curMonthNode = _tree.AppendItem(parentNode, months[it->first]); curMonth++; } else _tree.AppendItem(parentNode, months[it->first]); } _tree.Expand(parentNode); _tree.SelectItem(curMonthNode, true); ShowMonth(year, curMonth); } #define SET_ROW_COLOR(row, color) for(int i=0; iSetCellBackgroundColour(row, i, color);\ } void AccountPanel::ShowMonth(int year, int month) { std::vector operations; std::vector::iterator it; _fixCosts = 0; int curLine = 0; User* user = _kiss->GetUser(); DEFAULT_FONT(font); std::map::iterator categoryIt; wxGridCellChoiceEditor* categoryEditor, *accountEditor; int i; _curMonth = month; _wxUI->SetTitle(user->_name + _(" - ") + months[month] + _(" ") + wxString::Format(wxT("%d"), year)); // Operations are ordered _curOperations = &((*user->_operations[year])[month]); //_grid->Clear(); _grid->CreateGrid(1, NUMBER_COLS_OPS); // Creating headers _grid->SetColSize (0, _grid->GetColSize(0)*3); _grid->SetDefaultCellFont(font); font.SetWeight(wxFONTWEIGHT_BOLD); for(i=0; iSetCellValue(0, i, colsName[i]); _grid->SetCellBackgroundColour(0, i, OWN_CYAN); _grid->SetCellFont(0, i, font); _grid->SetReadOnly(0, i, true); } // SetCellBackgroundColour (int row, int col, const wxColour &colour); // SetCellFont (int row, int col, const wxFont &font); // SetCellValue (int row, int col, const wxString &s); // GetColSize (int col) const ; // SetColSize (int col, int width); // AppendRows (int numRows=1, bool updateLabels=true); // InsertRows (int pos=0, int numRows=1, bool updateLabels=true); // SetReadOnly(row, col, bool) it = _curOperations->begin(); /* struct operation { wxString id; unsigned int day; unsigned int month; unsigned int year; int amount; wxString description; wxString category; bool fix_cost; enum {DESCRIPTION, DATE, DEBIT, CREDIT, CATEGORY, ACCOUNT, VIEW, NUMBER_COLS_OPS}; } ; */ for (;it->fix_cost && it != _curOperations->end(); it++) { curLine++; _fixCosts++; _grid->AppendRows(); SET_ROW_COLOR(curLine, OWN_YELLOW); _grid->SetCellValue(curLine, DESCRIPTION, it->description); _grid->SetCellValue(curLine, DATE, wxString::Format(wxT("%02d/%02d/%d"), it->day+1, it->month+1, it->year)); _grid->SetCellEditor(curLine, DATE, new CalendarEditor(it->day, it->month, it->year)); if (it->amount < 0) _grid->SetCellValue(curLine, DEBIT, wxString::Format(wxT("%.2lf"), -it->amount)); else _grid->SetCellValue(curLine, CREDIT, wxString::Format(wxT("%.2lf"), it->amount)); _grid->SetCellEditor(curLine, DEBIT, new wxGridCellFloatEditor(-1, 2)); _grid->SetCellEditor(curLine, CREDIT, new wxGridCellFloatEditor(-1, 2)); _grid->SetCellValue(curLine, CATEGORY, _("Fixe")); _grid->SetReadOnly(curLine, CATEGORY); accountEditor = new wxGridCellChoiceEditor(user->_accounts.size()+1, _accounts, false); _grid->SetCellEditor(curLine, ACCOUNT, accountEditor); _grid->SetCellValue(curLine, ACCOUNT, user->GetAccountName(it->account)); } _grid->AppendRows(); curLine++; SET_ROW_COLOR(curLine, OWN_YELLOW); _grid->SetCellValue(curLine, CATEGORY, _("Fixe")); _grid->SetReadOnly(curLine, CATEGORY); _grid->SetCellEditor(curLine, DATE, new CalendarEditor(it->day, it->month, it->year)); _grid->SetCellEditor(curLine, DEBIT, new wxGridCellFloatEditor(-1, 2)); _grid->SetCellEditor(curLine, CREDIT, new wxGridCellFloatEditor(-1, 2)); accountEditor = new wxGridCellChoiceEditor(user->_accounts.size()+1, _accounts, false); _grid->SetCellEditor(curLine, ACCOUNT, accountEditor); _grid->_fixCosts = _fixCosts+1; for (; it != _curOperations->end(); it++) { curLine++; _grid->AppendRows(); SET_ROW_COLOR(curLine, OWN_GREEN); _grid->SetCellValue(curLine, DESCRIPTION, it->description); _grid->SetCellValue(curLine, DATE, wxString::Format(wxT("%02d/%02d/%d"), it->day+1, it->month+1, it->year)); _grid->SetCellEditor(curLine, DATE, new CalendarEditor(it->day, it->month, it->year)); if (it->amount < 0) _grid->SetCellValue(curLine, DEBIT, wxString::Format(wxT("%.2lf"), -it->amount)); else _grid->SetCellValue(curLine, CREDIT, wxString::Format(wxT("%.2lf"), it->amount)); _grid->SetCellEditor(curLine, DEBIT, new wxGridCellFloatEditor(-1, 2)); _grid->SetCellEditor(curLine, CREDIT, new wxGridCellFloatEditor(-1, 2)); categoryEditor = new wxGridCellChoiceEditor(user->GetCategoriesNumber()+1, _categories, false); _grid->SetCellEditor(curLine, CATEGORY, categoryEditor); _grid->SetCellValue(curLine, CATEGORY, user->GetCategoryName(it->category)); accountEditor = new wxGridCellChoiceEditor(user->_accounts.size()+1, _accounts, false); _grid->SetCellEditor(curLine, ACCOUNT, accountEditor); _grid->SetCellValue(curLine, ACCOUNT, user->GetAccountName(it->account)); } _grid->AppendRows(); curLine++; SET_ROW_COLOR(curLine, OWN_GREEN); categoryEditor = new wxGridCellChoiceEditor(user->_preferences._categories.size()+1, _categories, false); _grid->SetCellEditor(curLine, CATEGORY, categoryEditor); _grid->SetCellEditor(curLine, DATE, new CalendarEditor(it->day, it->month, it->year)); _grid->SetCellEditor(curLine, DEBIT, new wxGridCellFloatEditor(-1, 2)); _grid->SetCellEditor(curLine, CREDIT, new wxGridCellFloatEditor(-1, 2)); accountEditor = new wxGridCellChoiceEditor(user->_accounts.size()+1, _accounts, false); _grid->SetCellEditor(curLine, ACCOUNT, accountEditor); _grid->AutoSizeColumn(CATEGORY, false); _grid->AutoSizeColumn(ACCOUNT, false); InitAccountsGrid(user, month, year); UpdateStats(); Fit(); SetMinSize(GetSize()); } void AccountPanel::InsertOperation(User* user, operation* op, int line, bool fix) { _grid->InsertRows(line, 1); _grid->SetCellEditor(curLine, DATE, new CalendarEditor(it->day, it->month, it->year)); _grid->SetCellEditor(curLine, DEBIT, new wxGridCellFloatEditor(-1, 2)); _grid->SetCellEditor(curLine, CREDIT, new wxGridCellFloatEditor(-1, 2)); accountEditor = new wxGridCellChoiceEditor(user->_accounts.size()+1, _accounts, false); if (fix) { _fixCosts++; SET_ROW_COLOR(curLine, OWN_YELLOW); _grid->SetCellValue(curLine, CATEGORY, _("Fixe")); _grid->SetReadOnly(curLine, CATEGORY); } else { SET_ROW_COLOR(curLine, OWN_GREEN); } if (op) { _grid->SetCellValue(curLine, DESCRIPTION, it->description); _grid->SetCellValue(curLine, DATE, wxString::Format(wxT("%02d/%02d/%d"), it->day+1, it->month+1, it->year)); if (it->amount < 0) _grid->SetCellValue(curLine, DEBIT, wxString::Format(wxT("%.2lf"), -it->amount)); else _grid->SetCellValue(curLine, CREDIT, wxString::Format(wxT("%.2lf"), it->amount)); _grid->SetCellEditor(curLine, ACCOUNT, accountEditor); _grid->SetCellValue(curLine, ACCOUNT, user->GetAccountName(it->account)); } } void AccountPanel::InitAccountsGrid(User* user, int month, int year) { std::map::iterator it; int curLine = 0; Account account ; double value; int i, a; DEFAULT_FONT(font); font.SetWeight(wxFONTWEIGHT_BOLD); for (i=0, it = user->_accounts.begin(); it != user->_accounts.end(); i++, it++, curLine++) { _accountsGrid->AppendRows(); account = user->_accounts[it->first]; _accountsGrid->SetCellValue(curLine, ACCOUNT_NUMBER, account.number); _accountsGrid->SetCellValue(curLine, ACCOUNT_NAME, account.name); value = _kiss->GetAccountAmount(it->first, month, year); _accountsGrid->SetCellValue(curLine, ACCOUNT_INIT, wxString::Format(wxT("%.2lf"), value)); _accountsGrid->SetCellEditor(curLine, ACCOUNT_INIT, new wxGridCellFloatEditor(-1, 2)); for (a=0; aSetReadOnly(curLine, a, a != ACCOUNT_INIT); _accountsGrid->SetCellFont(curLine, ACCOUNT_CUR, font); _accountsIndexes[it->first] = i; _accountsInitValues[it->first] = value; } } void AccountPanel::UpdateStats() { int i; User* user = _kiss->GetUser(); std::vector::iterator it; double curCredit, curDebit, totalCredit, totalDebit, remains, value; wxDateTime curDate; std::map curAccountAmount, finalAccountAmount; std::map::iterator doubleIt; std::map::iterator intIt; curDate.SetToCurrent(); curCredit = curDebit = totalCredit = totalDebit = 0.0; for (i=0; iGetCategoriesNumber()+1; 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 (curDate.GetDay() >= it->day && curDate.GetMonth() >= (int)it->month && curDate.GetYear() >= (int)it->year) { 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 (curDate.GetDay() >= it->day && curDate.GetMonth() >= (int)it->month && curDate.GetYear() >= (int)it->year) { 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++) _statsGrid->SetCellValue(CATS_STATS+i, 1, wxString::Format(wxT("%.2lf"), _categoriesValues[i])); for (intIt=_accountsIndexes.begin(); intIt!=_accountsIndexes.end(); intIt++) { i = _accountsIndexes[intIt->first]; value = curAccountAmount[intIt->first]; _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[intIt->first]; _accountsGrid->SetCellValue(i, ACCOUNT_FINAL, wxString::Format(wxT("%.2lf"), value)); } _pie->DatasetChanged(_dataset); } void AccountPanel::OnOperationModified(wxGridEvent& event) { User* user = _kiss->GetUser(); int row = event.GetRow()-1; struct operation new_op, cur_op; int op_complete = 5; wxString value ; wxDateTime date; bool need_insertion = false; if (event.GetCol() == DEBIT) _grid->SetCellValue(event.GetRow(), CREDIT, _("")); else if (event.GetCol() == CREDIT) _grid->SetCellValue(event.GetRow(), DEBIT, _("")); value = _grid->GetCellValue(event.GetRow(), DESCRIPTION); if (value != _("")) { new_op.description = value; op_complete--; } value = _grid->GetCellValue(event.GetRow(), DATE); if (value != _("")) { date.ParseFormat(value, _("%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 != _("")) { value.ToDouble(&new_op.amount); new_op.amount *= -1.0; op_complete--; } value = _grid->GetCellValue(event.GetRow(), CREDIT); if (value != _("")) { value.ToDouble(&new_op.amount); op_complete--; } value = _grid->GetCellValue(event.GetRow(), CATEGORY); if (value != _("")) { new_op.category = user->GetCategoryId(value); op_complete--; } value = _grid->GetCellValue(event.GetRow(), ACCOUNT); if (value != _("")) { new_op.account = user->GetAccountId(value); op_complete--; } // Penser au fix // Modify a fix operation if (row < _fixCosts) { cur_op = (*_curOperations)[row] ; new_op.id = cur_op.id; if (cur_op.day != new_op.day) { need_insertion = true; _grid->DeleteRows(row, 1); _curOperations->erase(_curOperations->begin()+row); } else (*_curOperations)[row] = new_op; _kiss->UpdateOperation(new_op); } // Add a fixCost else if (row == _fixCosts) { if (op_complete) return ; need_insertion = true; } // Modify an operation else if (row <= user->GetOperationsNumber(_curMonth, _curYear)) { row--; cur_op = (*_curOperations)[row] ; new_op.id = cur_op.id; if (cur_op.day != new_op.day) { need_insertion = true; _grid->DeleteRows(row+1, 1); _curOperations->erase(_curOperations->begin()+row); } else (*_curOperations)[row] = new_op; _kiss->UpdateOperation(new_op); } // Add an operation else { row--; if (op_complete) return ; need_insertion = true; } UpdateStats(); }