/* Copyright 2010-2012 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 #include #include #include #include "AccountPanel.hpp" #include "grid/FloatDelegate.hpp" #include "GenerateDialog.hpp" #include "SnapshotsDialog.hpp" enum {ACCOUNT_NUMBER, ACCOUNT_NAME, ACCOUNT_INIT, ACCOUNT_CUR, ACCOUNT_FINAL, NUMBER_COLS_ACCOUNTS}; enum {CUR_CREDIT, CUR_DEBIT, TOTAL_CREDIT, TOTAL_DEBIT, BALANCE, CATS_STATS}; enum {VIRTUAL_MODE=0, REAL_MODE, CHECK_MODE}; AccountPanel::AccountPanel(KissCount* kiss, wxUI *parent, bool lowResolution) : KissPanel(kiss, parent, lowResolution), _curMonth(-1), _curYear(-1), _inModification(false) { Init(kiss, parent, 0); } AccountPanel::AccountPanel(KissCount* kiss, wxUI *parent, bool lowResolution, int month=-1, int year=-1, int mode=VIRTUAL_MODE) : KissPanel(kiss, parent, lowResolution), _curMonth(month), _curYear(year), _inModification(false) { Init(kiss, parent, mode); } void AccountPanel::Init(KissCount* kiss, wxUI *parent, int curMode) { QHBoxLayout *hbox = new QHBoxLayout; QHBoxLayout *hbox2 = new QHBoxLayout; QHBoxLayout *hbox3 = new QHBoxLayout; QHBoxLayout *hbox4 = new QHBoxLayout; QVBoxLayout *vbox = new QVBoxLayout; QVBoxLayout *vbox2 = new QVBoxLayout; QVBoxLayout *vbox3 = new QVBoxLayout; int i; User* user = _kiss->GetUser(); std::vector::iterator accountIt; std::vector::iterator categoryIt; std::vector::iterator tagIt; _icons[KissPanel::LOW_RES_ICON] = USER_LOW_ICON; _icons[KissPanel::HIGH_RES_ICON] = USER_ICON; setLayout(hbox); _tree = new QTreeWidget(this); _tree->headerItem()->setHidden(true); _tree->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); connect(_tree, SIGNAL(itemClicked(QTreeWidgetItem*, int)), this, SLOT(OnTreeChange(QTreeWidgetItem*, int))); _tree->setContextMenuPolicy(Qt::CustomContextMenu); connect(_tree, SIGNAL(customContextMenuRequested ( const QPoint & )), this, SLOT(OnTreeRightClick(const QPoint &))); _calendar = new QCalendarWidget(this); _calendar->setGridVisible(false); _calendar->setFirstDayOfWeek(Qt::Monday); _calendar->setNavigationBarVisible(false); _calendar->setVerticalHeaderFormat(QCalendarWidget::NoVerticalHeader); _calendar->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::MinimumExpanding); connect(_calendar, SIGNAL(selectionChanged ()), this, SLOT(OnCalendarChange())); _accounts = new QString[user->GetAccountsNumber()]; for (i=0, accountIt = user->_accounts.begin(); accountIt != user->_accounts.end(); accountIt++, i++) _accounts[i] = accountIt->name; _categories = new QString[user->GetCategoriesNumber()] ; for(i=0, categoryIt = user->_categories.begin(); categoryIt != user->_categories.end(); categoryIt++, i++) { _categories[i] = _(categoryIt->name.toStdString().c_str()) ; _categoriesIndexes[categoryIt->name] = i; } _categoriesValues = new int[user->GetCategoriesNumber()]; _tags = new QString[user->GetTagsNumber()] ; for(i=0, tagIt = user->_tags.begin(); tagIt != user->_tags.end(); tagIt++, i++) { _tags[i] = _(tagIt->name.toStdString().c_str()) ; _tagsIndexes[tagIt->name] = i; } _tagsValues = new int[user->GetTagsNumber()]; _grid = new GridAccount(_kiss, this, true, true, true); _grid->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); _grid->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents); _accountsGrid = new QTableWidget(this); _accountsGrid->setColumnCount(NUMBER_COLS_ACCOUNTS); _accountsGrid->setRowCount(0); _accountsGrid->verticalHeader()->setHidden(true); _accountsGrid->resizeColumnsToContents(); _accountsGrid->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding); _accountsGrid->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents); connect(_accountsGrid, SIGNAL(cellChanged(int, int)), this, SLOT(OnAccountModified(int, int))); _statsGrid = new QTableWidget(this); _statsGrid->verticalHeader()->setHidden(true); _statsGrid->horizontalHeader()->setHidden(true); _statsGrid->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); _statsGrid->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents); _costRepartitionBanner = new CostRepartitionBanner(_kiss, this, _categories); QGroupBox *groupBox = new QGroupBox(_("Mode")); _virtual = new QRadioButton(_("Virtual")); _real = new QRadioButton(_("Real")); _check = new QRadioButton(_("Check")); switch(curMode) { case VIRTUAL_MODE: _virtual->setChecked(true); break; case REAL_MODE: _real->setChecked(true); break; case CHECK_MODE: _check->setChecked(true); break; default: _virtual->setChecked(true); break; } { QVBoxLayout *vbox = new QVBoxLayout; vbox->addWidget(_virtual); vbox->addWidget(_real); vbox->addWidget(_check); groupBox->setLayout(vbox); } connect(_virtual, SIGNAL(clicked()), this, SLOT(OnModeChange())); connect(_real, SIGNAL(clicked()), this, SLOT(OnModeChange())); connect(_check, SIGNAL(clicked()), this, SLOT(OnModeChange())); // _tree.SetIndent(5); QPushButton* buttonGroup = new QPushButton(_("Group")); QPushButton* buttonUnGroup = new QPushButton(_("UnGroup")); QPushButton* buttonUpdateNextMonths = new QPushButton(_("Update next months")); QPushButton* buttonSnapshots = new QPushButton(_("Snapshots")); connect(buttonGroup, SIGNAL(clicked()), this, SLOT(OnGroup())); connect(buttonUnGroup, SIGNAL(clicked()), this, SLOT(OnUnGroup())); connect(buttonUpdateNextMonths, SIGNAL(clicked()), this, SLOT(OnUpdateNextMonths())); connect(buttonSnapshots, SIGNAL(clicked()), this, SLOT(OnSnapshots())); vbox3->addWidget(_tree); vbox3->addWidget(buttonUpdateNextMonths); vbox3->addStretch(1); vbox3->addWidget(_calendar); vbox3->addStretch(1); vbox3->addWidget(buttonGroup); vbox3->addWidget(buttonUnGroup); vbox3->addStretch(1); vbox3->addWidget(buttonSnapshots); vbox3->addStretch(1); vbox3->addWidget(groupBox); hbox->addLayout(vbox3); hbox2->addStretch(3); hbox2->addWidget(_accountsGrid, 2); hbox2->addStretch(3); vbox2->addLayout(hbox2); hbox4->addStretch(); hbox4->addWidget(_grid); hbox4->addStretch(); vbox2->addLayout(hbox4, 1); hbox->addLayout(vbox2); hbox3->addStretch(0); hbox3->addWidget(_statsGrid); hbox3->addStretch(0); vbox->addLayout(hbox3); vbox->addWidget(_costRepartitionBanner); hbox->addLayout(vbox); hbox->setStretch(0, 1.5); hbox->setStretch(1, 4); hbox->setStretch(2, 1.5); ChangeUser(); layout(); } AccountPanel::~AccountPanel() { delete[] _categoriesValues; delete[] _categories; if (_tagsValues) delete[] _tagsValues; if (_tags) delete[] _tags; delete[] _accounts; } KissPanel* AccountPanel::CreatePanel() { int mode; if (_virtual->isChecked()) mode = VIRTUAL_MODE; else if (_real->isChecked()) mode = REAL_MODE; else if (_check->isChecked()) mode = CHECK_MODE; return new AccountPanel(_kiss, _wxUI, _lowResolution, _curMonth, _curYear, mode); } QString AccountPanel::GetToolTip() { return _("Operations"); } void AccountPanel::InitStatsGrid(User* user) { DEFAULT_FONT(font); if (!_statsGrid->rowCount()) { _statsGrid->setColumnCount(2); //_statsGrid->EnableEditing(false); } else { _statsGrid->clear(); } _statsGrid->setRowCount(CATS_STATS); // Headers _statsGrid->setItem(TOTAL_CREDIT, 0, new QTableWidgetItem(_("Total Credit"))); _statsGrid->setItem(TOTAL_DEBIT, 0, new QTableWidgetItem(_("Total Debit"))); font.setBold(true); _statsGrid->setItem(CUR_CREDIT, 0, new QTableWidgetItem(_("Cur Credit"))); _statsGrid->setItem(CUR_DEBIT, 0, new QTableWidgetItem(_("Cur Debit"))); _statsGrid->setItem(TOTAL_CREDIT, 0, new QTableWidgetItem(_("Total Credit"))); _statsGrid->setItem(TOTAL_DEBIT, 0, new QTableWidgetItem(_("Total Debit"))); _statsGrid->setItem(BALANCE, 0, new QTableWidgetItem(_("Balance"))); _statsGrid->setItem(CUR_CREDIT, 1, new QTableWidgetItem("")); _statsGrid->setItem(CUR_DEBIT, 1, new QTableWidgetItem("")); _statsGrid->setItem(TOTAL_CREDIT, 1, new QTableWidgetItem("")); _statsGrid->setItem(TOTAL_DEBIT, 1, new QTableWidgetItem("")); _statsGrid->setItem(BALANCE, 1, new QTableWidgetItem("")); _statsGrid->item(CUR_DEBIT, 0)->setFont(font); _statsGrid->item(CUR_CREDIT, 0)->setFont(font); _statsGrid->item(BALANCE, 0)->setFont(font); _statsGrid->item(BALANCE, 1)->setFont(font); _statsGrid->item(CUR_CREDIT, 1)->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); _statsGrid->item(CUR_DEBIT, 1)->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); _statsGrid->item(TOTAL_CREDIT, 1)->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); _statsGrid->item(TOTAL_DEBIT, 1)->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); _statsGrid->item(BALANCE, 1)->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); _statsGrid->resizeColumnToContents(0); _costRepartitionBanner->Reset(); } void AccountPanel::ChangeUser() { User* user = _kiss->GetUser(); int curYear = -1, year; QDate curDate = QDate::currentDate(); QTreeWidgetItem* curNode=0, *node; std::map > ops; std::map >::iterator it; ops = _kiss->GetAllOperations(); InitStatsGrid(user); _tree->clear(); if (ops.size()) { year = (_curYear == -1) ? curDate.year() : _curYear; for(it = ops.begin(); it != ops.end(); it++) { node = new QTreeWidgetItem(QStringList(QString::number(it->first))); if ((int)it->first <= year) { curYear = it->first; curNode = node; } _tree->addTopLevelItem(node); } if (curYear != -1) { _tree->setCurrentItem(curNode); LoadYear(curYear, true); } } else { curNode = new QTreeWidgetItem(QStringList(QString::number(curDate.year()))); _tree->addTopLevelItem(curNode); } layout(); } void AccountPanel::LoadYear(int year, bool showMonth) { User* user = _kiss->GetUser(); int lastMonth = -1, month; QTreeWidgetItem* parentNode, *curMonthNode = 0, *lastMonthNode = 0; std::map > ops ; std::vector::iterator it; QDate curDate = QDate::currentDate(); if (user->_operations[year] && _tree->currentItem()->childCount()) { if (showMonth) ShowMonth(-1, year); return; } _inModification = true; _curYear = year ; _kiss->LoadYear(year); ops = _kiss->GetAllOperations(); parentNode = _tree->currentItem(); if (!parentNode) parentNode = _tree->topLevelItem(0); if (_curYear == curDate.year()) month = curDate.month()-1; else month = 11; for (it = ops[year].begin(); it != ops[year].end(); it++) { lastMonthNode = new QTreeWidgetItem(QStringList(wxUI::months[*it])); if (year == _curYear && *it == month) curMonthNode = lastMonthNode; lastMonth = *it; parentNode->addChild(lastMonthNode); } _tree->expandItem(parentNode); layout(); if (showMonth) { if (curMonthNode) { _tree->setCurrentItem(curMonthNode); ShowMonth(month, year); } else { _tree->setCurrentItem(lastMonthNode); ShowMonth(lastMonth, year); } } _wxUI->layout(); _inModification = false; } void AccountPanel::ShowMonth(int month, int year) { // std::vector operations; // _fixCosts = 0; User* user = _kiss->GetUser(); // std::vector::iterator categoryIt; std::map >::iterator monthIt; QDate curDate = QDate::currentDate(); QDate dateStart = QDate::currentDate(); QDate dateEnd = QDate::currentDate(); if (month == -1) { // Near month if (year == curDate.year()) { for (monthIt = user->_operations[year]->begin(); monthIt != user->_operations[year]->end(); monthIt++) { if ((int)monthIt->first+1 <= curDate.month()) { month = monthIt->first; } } } // First month if (month == -1) { monthIt = user->_operations[year]->begin(); if (user->_operations[year]->size() == 0 && year == curDate.year()) month = curDate.month(); else month = monthIt->first; } } _curYear = year; _curMonth = month; _wxUI->setWindowTitle(user->_name + " - " + wxUI::months[month] + " " + QString::number(year)); // if (_grid->GetNumberRows() > 1) // _grid->DeleteRows(1, _grid->GetNumberRows()-1); // Operations are ordered _curOperations = &((*user->_operations[year])[month]); _grid->LoadOperations(_curOperations, _curMonth, _curYear); disconnect(_accountsGrid, SIGNAL(cellChanged(int, int)), this, SLOT(OnAccountModified(int, int))); InitAccountsGrid(user, month, year); connect(_accountsGrid, SIGNAL(cellChanged(int, int)), this, SLOT(OnAccountModified(int, int))); dateStart.setDate(_curYear, _curMonth+1, 1); dateEnd.setDate(_curYear, _curMonth+1, dateStart.daysInMonth()); _calendar->setDateRange(dateStart, dateEnd); if (curDate.month() == (_curMonth+1) && curDate.year() == year) _calendar->setSelectedDate (curDate) ; else if ((curDate.month()-1) > month || curDate.year() > year) _calendar->setSelectedDate (dateEnd) ; else if ((curDate.month()-1) < month || curDate.year() < year) _calendar->setSelectedDate(dateStart) ; UpdateStats(); layout(); } void AccountPanel::InitAccountsGrid(User* user, int month, int year) { std::vector::iterator it; int curLine = 0; int value; int i, nbAccounts; QTableWidgetItem* item; QString v; DEFAULT_FONT(font); font.setBold(true); if (_accountsGrid->rowCount()) _accountsGrid->clear(); _accountsGrid->setHorizontalHeaderItem(ACCOUNT_NUMBER, new QTableWidgetItem(_("Account number"))); _accountsGrid->setHorizontalHeaderItem(ACCOUNT_NAME, new QTableWidgetItem(_("Account name"))); _accountsGrid->setHorizontalHeaderItem(ACCOUNT_INIT, new QTableWidgetItem(_("Initial value"))); _accountsGrid->setHorizontalHeaderItem(ACCOUNT_CUR, new QTableWidgetItem(_("Current value"))); _accountsGrid->setHorizontalHeaderItem(ACCOUNT_FINAL, new QTableWidgetItem(_("Final value"))); for(i=0; ihorizontalHeaderItem(i)->setFont(font); } FloatDelegate* floatEditor = new FloatDelegate(_accountsGrid); _accountsGrid->setItemDelegateForColumn(ACCOUNT_INIT, floatEditor); nbAccounts = 0; for (it = user->_accounts.begin(); it != user->_accounts.end(); it++) { if (!it->hidden && it->validAt(month, year)) nbAccounts++; } _accountsGrid->setRowCount(nbAccounts); for (it = user->_accounts.begin(); it != user->_accounts.end(); it++, curLine++) { if (it->hidden || !it->validAt(month, year)) { value = _kiss->GetAccountAmount(it->id, month, year); _accountsInitValues[it->id] = value; curLine--; continue; } if (it->shared) _accountsGrid->setItem(curLine, ACCOUNT_NUMBER, new QTableWidgetItem(it->number + "*")); else _accountsGrid->setItem(curLine, ACCOUNT_NUMBER, new QTableWidgetItem(it->number)); _accountsGrid->setItem(curLine, ACCOUNT_NAME, new QTableWidgetItem(it->name)); value = _kiss->GetAccountAmount(it->id, month, year); _accountsGrid->setItem(curLine, ACCOUNT_INIT, new QTableWidgetItem(v.sprintf("%.2lf", (double)value/100))); _accountsGrid->setItem(curLine, ACCOUNT_CUR, new QTableWidgetItem("")); _accountsGrid->setItem(curLine, ACCOUNT_FINAL, new QTableWidgetItem("")); for (i=0; iitem(curLine, i); if (i != ACCOUNT_INIT) item->setFlags(item->flags() & ~Qt::ItemIsEditable); if (i == ACCOUNT_CUR) item->setFont(font); } _accountsInitValues[it->id] = value; _accountsGrid->item(curLine, ACCOUNT_INIT)->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); _accountsGrid->item(curLine, ACCOUNT_CUR)->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); _accountsGrid->item(curLine, ACCOUNT_FINAL)->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); } _accountsGrid->resizeColumnsToContents(); } void AccountPanel::UpdateStats() { int i, nbDays, minimalValue; User* user = _kiss->GetUser(); std::vector::iterator it; int curCredit, curDebit, totalCredit, totalDebit, balance, value, value2, percents; std::map finalAccountAmount; std::map* curAccountAmounts; // For each day std::map::iterator intIt; std::vector::iterator accountIt; unsigned int day; int mode; std::map* notChecked = 0; std::map* virtuals = 0; Account account; Operation op; bool force_debit; QString v; QDate selectedDate; QTextCharFormat textFormat; QBrush brush; int minStartAccount = 0; _inModification = true; if (_virtual->isChecked()) mode = VIRTUAL_MODE; else if (_real->isChecked()) mode = REAL_MODE; else if (_check->isChecked()) mode = CHECK_MODE; curCredit = curDebit = totalCredit = totalDebit = percents = 0.0; if (mode == CHECK_MODE) notChecked = _kiss->GetNotChecked(_curMonth, _curYear); if (mode == REAL_MODE || mode == CHECK_MODE) virtuals = _kiss->GetVirtualAmount(_curMonth, _curYear); selectedDate = _calendar->selectedDate(); day = selectedDate.day()-1; nbDays = selectedDate.daysInMonth(); curAccountAmounts = new std::map[nbDays]; for (i=0; iGetCategoriesNumber(); i++) _categoriesValues[i] = 0.0; for (intIt=_accountsInitValues.begin(); intIt!=_accountsInitValues.end(); intIt++) { finalAccountAmount[intIt->first] = _accountsInitValues[intIt->first]; for(i=0; ifirst] = _accountsInitValues[intIt->first]; if (mode == REAL_MODE || mode == CHECK_MODE) { for(i=0; ifirst] += -(*virtuals)[intIt->first]; finalAccountAmount[intIt->first] += -(*virtuals)[intIt->first]; } } for (it=_curOperations->begin(); it!=_curOperations->end(); it++) { if (it->meta) continue; op = *it; force_debit = false; if ((mode == REAL_MODE || mode == CHECK_MODE) && op._virtual) continue; if (mode == CHECK_MODE && !op.checked) continue; account = user->GetAccount(op.account); if (account.blocked) { if (op.transfert && op.amount > 0) { // A Transfert on a blocked account must be considered as a debit op.amount = -op.amount; // op.transfert = 0; force_debit = true; } // else // continue; } if (op.amount >= 0) { if (!op.transfert && !account.blocked) { totalCredit += op.amount; if (day >= op.day) curCredit += op.amount; } } else { if ((!op.transfert || force_debit) && user->GetCategoryName(op.category) != _("Unknown")) { if (op.fix_cost && op.category != 1) _categoriesValues[0] += -op.amount ; _categoriesValues[_categoriesIndexes[user->GetCategoryName(op.category)]] += -op.amount ; } if (!op.transfert || force_debit) { totalDebit += -op.amount; if (day >= op.day) curDebit += -op.amount; } if (force_debit) op.amount = -op.amount; } finalAccountAmount[op.account] += op.amount; for(i=op.day; iGetAccount(intIt->first).hidden && !user->GetAccount(intIt->first)._virtual) { minStartAccount = intIt->first; break; } } } for(i=0; idateTextFormat(QDate(_curYear, _curMonth+1, i+1)); if (mode != CHECK_MODE) { minimalValue = curAccountAmounts[i][minStartAccount]; for (intIt=curAccountAmounts[i].begin(); intIt!=curAccountAmounts[i].end(); intIt++) { account = user->GetAccount(intIt->first); if (account.hidden || account._virtual || !account.validAt(i, _curMonth, _curYear)) continue; if (curAccountAmounts[i][intIt->first] < minimalValue) minimalValue = curAccountAmounts[i][intIt->first]; } if (minimalValue <= 0) { brush.setColor(Qt::red); textFormat.setBackground(brush); QDate date(_curYear, _curMonth+1, i+1); if (date.dayOfWeek() == 6 || date.dayOfWeek() == 7) { brush.setColor(Qt::black); textFormat.setForeground(brush); } } else if (minimalValue <= user->GetAccountLimitValue()*100) { brush.setColor(user->GetAccountLimitColor()); textFormat.setBackground(brush); } else { textFormat.clearBackground(); } } else { textFormat.clearBackground(); } _calendar->setDateTextFormat(QDate(_curYear, _curMonth+1, i+1), textFormat); } balance = totalCredit - totalDebit; _statsGrid->item(CUR_CREDIT, 1)->setText(v.sprintf("%.2lf", (double)curCredit/100)); _statsGrid->item(CUR_DEBIT, 1)->setText(v.sprintf("%.2lf", (double)curDebit/100)); _statsGrid->item(TOTAL_CREDIT, 1)->setText(v.sprintf("%.2lf", (double)totalCredit/100)); _statsGrid->item(TOTAL_DEBIT, 1)->setText(v.sprintf("%.2lf", (double)totalDebit/100)); _statsGrid->item(BALANCE, 1)->setText(v.sprintf("%.2lf", (double)balance/100)); _statsGrid->item(BALANCE, 1)->setForeground((balance >= 0) ? QBrush(Qt::green) : QBrush(Qt::red)); for (i=0, accountIt=user->_accounts.begin(); accountIt!=user->_accounts.end(); accountIt++, i++) { if (accountIt->hidden || !accountIt->validAt(_curMonth, _curYear)) { i--; continue; } if (mode != CHECK_MODE) { value = _accountsInitValues[accountIt->id]; if (mode == REAL_MODE) value -= (*virtuals)[accountIt->id]; _accountsGrid->item(i, ACCOUNT_INIT)->setText(v.sprintf("%.2lf", (double)value/100)); _accountsGrid->item(i, ACCOUNT_INIT)->setForeground((value >= 0) ? QBrush(Qt::black) : QBrush(Qt::red)); value = curAccountAmounts[day][accountIt->id]; _accountsGrid->item(i, ACCOUNT_CUR)->setText(v.sprintf("%.2lf", (double)value/100)); _accountsGrid->item(i, ACCOUNT_CUR)->setForeground((value >= 0) ? QBrush(Qt::black) : QBrush(Qt::red)); value = finalAccountAmount[accountIt->id]; _accountsGrid->item(i, ACCOUNT_FINAL)->setText(v.sprintf("%.2lf", (double)value/100)); _accountsGrid->item(i, ACCOUNT_FINAL)->setForeground((value >= 0) ? QBrush(Qt::black) : QBrush(Qt::red)); } else { value = _accountsInitValues[accountIt->id] - (*virtuals)[accountIt->id]; value2 = (*notChecked)[accountIt->id]; _accountsGrid->item(i, ACCOUNT_INIT)->setText(v.sprintf("%.2lf (%.2lf)", (double)value/100, (double)(value-value2)/100)); _accountsGrid->item(i, ACCOUNT_INIT)->setForeground((value >= 0) ? QBrush(Qt::black) : QBrush(Qt::red)); value = curAccountAmounts[day][accountIt->id]; _accountsGrid->item(i, ACCOUNT_CUR)->setText(v.sprintf("%.2lf (%.2lf)", (double)value/100, (double)(value-value2)/100)); _accountsGrid->item(i, ACCOUNT_CUR)->setForeground((value >= 0) ? QBrush(Qt::black) : QBrush(Qt::red)); value = finalAccountAmount[accountIt->id]; _accountsGrid->item(i, ACCOUNT_FINAL)->setText(v.sprintf("%.2lf (%.2lf)", (double)value/100, (double)(value-value2)/100)); _accountsGrid->item(i, ACCOUNT_FINAL)->setForeground((value >= 0) ? QBrush(Qt::black) : QBrush(Qt::red)); } } _costRepartitionBanner->UpdateCosts(_categoriesValues, totalDebit); _accountsGrid->resizeColumnToContents(ACCOUNT_INIT); _accountsGrid->resizeColumnToContents(ACCOUNT_CUR); _accountsGrid->resizeColumnToContents(ACCOUNT_FINAL); if (notChecked) delete notChecked; if (virtuals) delete virtuals; delete[] curAccountAmounts; _statsGrid->resizeColumnToContents(1); layout(); _inModification = false; } void AccountPanel::OnOperationModified() { UpdateStats(); } void AccountPanel::OnAccountModified(int row, int column) { User* user = _kiss->GetUser(); int amount; int id = user->GetAccountId(_accountsGrid->item(row, ACCOUNT_NAME)->text()); if (_inModification || column != ACCOUNT_INIT) return; amount = _accountsGrid->item(row, column)->text().replace(".", "").toInt(); _kiss->SetAccountAmount(id, _curMonth, _curYear, amount); _accountsInitValues[id] = amount; UpdateStats(); NeedReload(); } void AccountPanel::OnTreeRightClick(const QPoint & pos) { QMenu menu(this); menu.addAction(_("Generate month"), this, SLOT(OnMenuGenerate())); menu.addSeparator(); if (_tree->columnCount() >= 1) menu.addAction(_("Delete"), this, SLOT(OnMenuDelete())); menu.exec(QCursor::pos()); } void AccountPanel::OnTreeChange (QTreeWidgetItem * item, int column) { int month=-1, year; int i; QString monthString; if (_inModification) return; item = _tree->currentItem (); if (!item) return; monthString = item->text(column); for (i=0; i<12; i++) { if (monthString == wxUI::months[i]) { month = i; break; } } if (month == -1) { year = monthString.toInt(); // Error if (year == 0) { return; } if (year == _curYear) { return; } // _tree.CollapseAll(); // _tree.Expand(event.GetItem()); LoadYear(year, true); } else { item = item->parent(); year = item->text(column).toInt(); // Error if (year == 0) { return; } if (year != _curYear || month != _curMonth) { ShowMonth(month, year); } } } void AccountPanel::GetTreeSelection(int* month, int* year) { QString monthString; int i; bool ok; *month = -1; *year = -1; monthString = _tree->currentItem()->text(0); for (i=0; i<12; i++) if (monthString == wxUI::months[i]) { *month = i; break; } if (*month == -1) { *year = monthString.toInt(&ok); // Error if (!ok) { *month = -1; *year = -1; return; } } else { *year = _tree->currentItem()->parent()->text(0).toInt(&ok); // Error if (!ok) { *month = -1; *year = -1; return; } } } void AccountPanel::OnMenuGenerate() { int month, year; QDate curDate = QDate::currentDate(); GetTreeSelection(&month, &year); if (month == -1 && year == curDate.year()) { month = _curMonth; } _wxUI->setEnabled(false); GenerateDialog g(_kiss, _wxUI, month, year); g.setModal(true); g.exec(); _wxUI->setEnabled(true); NeedReload(); } void AccountPanel::OnMenuDelete() { int month, year, i; QString message; QTreeWidgetItem* curNode, *node ; std::map > ops ; GetTreeSelection(&month, &year); ops = _kiss->GetAllOperations(); if (ops.size() == 1 && (ops[year].size() == 1 || month == -1)) { QMessageBox::critical(0, _("Error"), _("It must be at least one month !")); return; } message = _("Are you sure want to delete "); if (month != -1) message += wxUI::months[month] + " "; message += QString::number(year); message += _(" operations ?"); if (QMessageBox::question(0, "KissCount", message, QMessageBox::Yes|QMessageBox::No) == QMessageBox::No) return; curNode = _tree->currentItem(); if (ops[year].size() == 1 && month != -1) curNode = curNode->parent(); _kiss->DeleteOperations(month, year); i = _tree->indexOfTopLevelItem(curNode); if (i == -1) { node = _tree->itemBelow(curNode); if (!node) node = _tree->itemAbove(curNode); curNode->parent()->removeChild(curNode); _tree->setCurrentItem(node); } else { delete _tree->takeTopLevelItem(i); if (i) i--; _tree->setCurrentItem(_tree->topLevelItem(i)); curNode = _tree->topLevelItem(i); if (!curNode->childCount()) LoadYear(curNode->text(0).toInt()); _tree->setCurrentItem(curNode->child(curNode->childCount()-1)); } if (!node) ChangeUser(); else { GetTreeSelection(&month, &year); if (month == -1) month = ops[year][0]; ShowMonth(month, year); } NeedReload(); } void AccountPanel::GenerateMonth(int month, int year) { QString s; const QString syear = s.sprintf("%d", year); QList items = _tree->findItems(syear, Qt::MatchExactly|Qt::MatchRecursive); QTreeWidgetItem *root, *itemYear = 0, *itemMonth; std::map > ops ; std::vector::iterator it ; int i; ops = _kiss->GetAllOperations(); // Year not found if (items.size() == 0) { for(i=0; i<_tree->topLevelItemCount(); i++) { root = _tree->topLevelItem(i); if (root->text(0).toInt() > year) break; } itemYear = new QTreeWidgetItem(QStringList(syear)); _tree->insertTopLevelItem(i, itemYear); _tree->setCurrentItem(itemYear); } else itemYear = items[0]; for(i=0, it = ops[year].begin(); it != ops[year].end(); it++, i++) { if (*it > month) break; } if (i) i--; itemMonth = new QTreeWidgetItem(QStringList(wxUI::months[month])); itemYear->insertChild(i, itemMonth); _tree->setCurrentItem(itemMonth); ShowMonth(month, year); NeedReload(); } void AccountPanel::OnShow() { User* user = _kiss->GetUser(); if (_curMonth != -1) _wxUI->setWindowTitle(user->_name + " - " + wxUI::months[_curMonth] + " " + QString::number(_curYear)); else _wxUI->setWindowTitle(user->_name); } void AccountPanel::OnCalendarChange() { UpdateStats(); } void AccountPanel::OnModeChange() { UpdateStats(); } void AccountPanel::OnGroup() { if (_grid) _grid->Group(); } void AccountPanel::OnUnGroup() { if (_grid) _grid->UnGroup(); } void AccountPanel::OnUpdateNextMonths() { int *cur_amounts, amount, i; User* user = _kiss->GetUser(); bool has_values, accounts_updated = false; int cur_month = 0, cur_year = 0, delta_computed = 0; int last_month, last_year; bool *valid_account; cur_amounts = new int[user->_accounts.size()] ; valid_account = new bool[user->_accounts.size()] ; cur_month = _curMonth; cur_year = _curYear; for (i=0; i<(int)user->_accounts.size(); i++) { cur_amounts[i] = _kiss->GetAccountAmount(user->_accounts[i].id, cur_month, cur_year, &has_values, false); valid_account[i] = has_values; } while (1) { delta_computed = 0; for (i=0; i<(int)user->_accounts.size(); i++) { if (!valid_account[i]) continue; cur_amounts[i] += _kiss->CalcAccountAmount(user->_accounts[i].id, cur_month, cur_year, &has_values); if (has_values) delta_computed++; } if (!delta_computed) break; if (cur_month == 11) { cur_month = 0; cur_year++; } else cur_month++; for (i=0; i<(int)user->_accounts.size(); i++) { if (!valid_account[i]) continue; amount = _kiss->GetAccountAmount(user->_accounts[i].id, cur_month, cur_year, &has_values, false); if (!has_values) { valid_account[i] = false; continue; } if (amount != cur_amounts[i]) { accounts_updated = true; _kiss->SetAccountAmount(user->_accounts[i].id, cur_month, cur_year, cur_amounts[i]); last_month = cur_month; last_year = cur_year; } } } if (accounts_updated) { QString message = _("Accounts updated until ") + wxUI::months[last_month] + " " + QString::number(last_year); QMessageBox::information(0, "KissCount", message); } else QMessageBox::information(0, "KissCount", _("Any account updated !")); NeedReload(); delete[] cur_amounts; } void AccountPanel::OnSnapshots() { SnapshotsDialog u(_kiss, _wxUI); u.exec(); }