/* 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 #include "AccountPanel.hpp" #include "grid/FloatDelegate.hpp" #include "GenerateDialog.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, STATS_ROW, CATS_STATS, NON_FIX}; enum {VIRTUAL_MODE=0, REAL_MODE, CHECK_MODE}; AccountPanel::AccountPanel(KissCount* kiss, wxUI *parent) : KissPanel(kiss, parent), _curMonth(-1), _curYear(-1), _inModification(false) { QHBoxLayout *hbox = new QHBoxLayout; QHBoxLayout *hbox2 = new QHBoxLayout; QVBoxLayout *vbox = new QVBoxLayout; QVBoxLayout *vbox2 = new QVBoxLayout; QVBoxLayout *vbox3 = new QVBoxLayout; // wxChartPanel* chart ; int i ; User* user = _kiss->GetUser(); std::vector::iterator accountIt; std::vector::iterator categoryIt; int nbCategories; 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 &))); // ColorScheme* colorScheme = new ColorScheme(wxUI::categoryColors, WXSIZEOF(wxUI::categoryColors)); _calendar = new QCalendarWidget(this); _calendar->setGridVisible(false); _calendar->setFirstDayOfWeek(Qt::Monday); _calendar->setNavigationBarVisible(false); _calendar->setVerticalHeaderFormat(QCalendarWidget::NoVerticalHeader); _calendar->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); 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; } nbCategories = (user->GetCategoriesNumber() <= wxUI::MAX_CATEGORY) ? user->GetCategoriesNumber() : wxUI::MAX_CATEGORY; _pie = new KDChart::Widget(); _pie->setType( KDChart::Widget::Pie ); QPen pen; pen.setWidth(2); pen.setColor(Qt::black); _pie->pieDiagram()->setPen(pen); _pie->addLegend(KDChart::Position::South); KDChart::Legend* legend = _pie->legend(); // legend->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); legend->setOrientation( Qt::Vertical ); legend->setTitleText( _("Cost repartition") ); QVector< double > vec; vec << 0.0; _dataset = new QStandardItemModel(nbCategories, 2, this); _categoriesValues = new double[nbCategories]; for(i=0; isetDataset( i, vec, _categories[i] ); _pie->pieDiagram()->setBrush(i, QBrush(wxUI::categoryColors[i])); legend->setText( i, _categories[i] ); _dataset->setData(_dataset->index(i, 0, QModelIndex()), _categories[i]); _dataset->setData(_dataset->index(i, 1, QModelIndex()), 0.0); _dataset->setData(_dataset->index(i, 0, QModelIndex()), wxUI::categoryColors[i], Qt::DecorationRole); } _pie->setMaximumSize( 200, 400 ); KDChart::TextAttributes legendTextAttr(legend->textAttributes()); legendTextAttr.setFontSize(64); legendTextAttr.setAutoShrink(true); legend->setTextAttributes(legendTextAttr); legendTextAttr = KDChart::TextAttributes(legend->titleTextAttributes()); legendTextAttr.setFontSize(64); legendTextAttr.setAutoShrink(true); legend->setTitleTextAttributes(legendTextAttr); _grid = new GridAccount(_kiss, this, true, true, true); _grid->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); _accountsGrid = new QTableWidget(this); _accountsGrid->setColumnCount(NUMBER_COLS_ACCOUNTS); _accountsGrid->setRowCount(0); _accountsGrid->verticalHeader()->setHidden(true); _accountsGrid->resizeColumnsToContents(); _accountsGrid->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); 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::MinimumExpanding); QGroupBox *groupBox = new QGroupBox(_("Mode")); _virtual = new QRadioButton(_("Virtual")); _real = new QRadioButton(_("Real")); _check = new QRadioButton(_("Check")); _virtual->setChecked(true); { 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")); connect(buttonGroup, SIGNAL(clicked()), this, SLOT(OnGroup())); connect(buttonUnGroup, SIGNAL(clicked()), this, SLOT(OnUnGroup())); connect(buttonUpdateNextMonths, SIGNAL(clicked()), this, SLOT(OnUpdateNextMonths())); vbox3->addWidget(_tree); vbox3->addWidget(buttonUpdateNextMonths); vbox3->addStretch(1); vbox3->addWidget(buttonGroup); vbox3->addWidget(buttonUnGroup); vbox3->addStretch(1); vbox3->addWidget(groupBox); hbox->addLayout(vbox3); hbox2->addWidget(_accountsGrid, 2); hbox2->addWidget(_calendar); vbox2->addLayout(hbox2); vbox2->addWidget(_grid, 1); hbox->addLayout(vbox2); vbox->addWidget(_statsGrid); vbox->addWidget(_pie); hbox->addLayout(vbox); ChangeUser(); layout(); QSize s = legend->sizeHint(); legend->setMaximumSize(s.width(), s.height()/3); } AccountPanel::~AccountPanel() { delete[] _categoriesValues; delete[] _categories; delete[] _accounts; } KissPanel* AccountPanel::CreatePanel() { return new AccountPanel(_kiss, _wxUI); } QPushButton* AccountPanel::GetButton() { if (!_KissButton) { _KissButton = new QPushButton(QIcon(ACCOUNT_ICON), "", this); _KissButton->setFixedSize(128, 128); _KissButton->setIconSize(QSize(128, 128)); } return _KissButton; } QString AccountPanel::GetToolTip() { return _("Operations"); } void AccountPanel::InitStatsGrid(User* user) { int i; int nb_categories = user->GetCategoriesNumber(); DEFAULT_FONT(font); if (!_statsGrid->rowCount()) { _statsGrid->setColumnCount(2); //_statsGrid->EnableEditing(false); } else { _statsGrid->clear(); } _statsGrid->setRowCount(nb_categories+CATS_STATS+1); // Headers + blank + categories + non fix _statsGrid->setItem(TOTAL_CREDIT, 0, new QTableWidgetItem(_("Total Credit"))); _statsGrid->setItem(TOTAL_DEBIT, 0, new QTableWidgetItem(_("Total Debit"))); for(i=0; isetItem(CATS_STATS+i+1, 0, new QTableWidgetItem(_categories[i])); _statsGrid->setItem(CATS_STATS+i+1, 1, new QTableWidgetItem("")); _statsGrid->item(CATS_STATS+i+1, 1)->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); } else { _statsGrid->setItem(CATS_STATS+i, 0, new QTableWidgetItem(_categories[i])); _statsGrid->setItem(CATS_STATS+i, 1, new QTableWidgetItem("")); _statsGrid->item(CATS_STATS+i, 1)->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); } } 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(NON_FIX, 0, new QTableWidgetItem(_("Non fix"))); _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->setItem(NON_FIX, 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->item(NON_FIX, 1)->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); _accountsGrid->resizeColumnToContents(0); } void AccountPanel::ChangeUser() { User* user = _kiss->GetUser(); int curYear = -1; QDate curDate = QDate::currentDate(); QTreeWidgetItem* curNode=NULL, *node; std::map > ops; std::map >::iterator it; ops = _kiss->GetAllOperations(); InitStatsGrid(user); _tree->clear(); if (ops.size()) { for(it = ops.begin(); it != ops.end(); it++) { node = new QTreeWidgetItem(QStringList(QString::number(it->first))); if ((int)it->first <= curDate.year()) { curYear = it->first; curNode = node; } _tree->addTopLevelItem(node); } if (curYear != -1) { _tree->setCurrentItem(curNode); LoadYear(curYear); } } 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 curMonth = -1; QTreeWidgetItem* parentNode, *curMonthNode = 0; std::map > ops ; std::vector::iterator it; if (user->_operations[year] && _tree->currentItem()->childCount()) { if (showMonth) ShowMonth(-1, year); return; } _curYear = year ; _kiss->LoadYear(year); ops = _kiss->GetAllOperations(); parentNode = _tree->currentItem(); if (!parentNode) parentNode = _tree->topLevelItem(0); for (it = ops[year].begin(); it != ops[year].end(); it++) { if (!curMonthNode) { curMonth = *it; curMonthNode = new QTreeWidgetItem(QStringList(wxUI::months[*it])); parentNode->addChild(curMonthNode); } else parentNode->addChild(new QTreeWidgetItem(QStringList(wxUI::months[*it]))); } _tree->expandItem(parentNode); layout(); if (showMonth) { _tree->setCurrentItem(curMonthNode); ShowMonth(curMonth, year); } _wxUI->layout(); } 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 <= 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()-1) == month && curDate.year() == year) _calendar->showToday(); 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; double 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) nbAccounts++; } _accountsGrid->setRowCount(nbAccounts); for (it = user->_accounts.begin(); it != user->_accounts.end(); it++, curLine++) { if (it->hidden) { 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", value))); _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; User* user = _kiss->GetUser(); std::vector::iterator it; double curCredit, curDebit, totalCredit, totalDebit, balance, value, value2, percents; std::map curAccountAmount, finalAccountAmount; std::map::iterator doubleIt; 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 blocked_account ; QString v; _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); day = _calendar->selectedDate().day()-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]; if (mode == REAL_MODE || mode == CHECK_MODE) { curAccountAmount[doubleIt->first] += -(*virtuals)[doubleIt->first]; finalAccountAmount[doubleIt->first] += -(*virtuals)[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 && op.amount > 0) { account = user->GetAccount(op.account); if (account.blocked) { op.amount = -op.amount; op.transfert = 0; blocked_account = true; } } switch(mode) { case VIRTUAL_MODE: if (op.amount >= 0) { if (!op.transfert) totalCredit += op.amount; if (day >= op.day) { if (!op.transfert) curCredit += op.amount; curAccountAmount[op.account] += op.amount; } finalAccountAmount[op.account] += op.amount; } else { if (!op.transfert && user->GetCategoryName(op.category) != _("Unknown")) _categoriesValues[_categoriesIndexes[user->GetCategoryName(op.category)]] += -op.amount ; if (!op.transfert) totalDebit += -op.amount; if (blocked_account) op.amount = -op.amount; if (day >= op.day) { if (!op.transfert) curDebit += -op.amount; curAccountAmount[op.account] += op.amount; } finalAccountAmount[op.account] += op.amount; } break; case REAL_MODE: if (op.amount >= 0) { if (!op.transfert) totalCredit += op.amount; if (day >= op.day) { if (!op.transfert) curCredit += op.amount; if (!op._virtual) curAccountAmount[op.account] += op.amount; } if (!op._virtual) finalAccountAmount[op.account] += op.amount; } else { if (!op.transfert && user->GetCategoryName(op.category) != _("Unknown")) _categoriesValues[_categoriesIndexes[user->GetCategoryName(op.category)]] += -op.amount ; if (!op.transfert && !op._virtual) totalDebit += -op.amount; if (blocked_account) op.amount = -op.amount; if (day >= op.day) { if (!op.transfert && !op._virtual) curDebit += -op.amount; if (!op._virtual) curAccountAmount[op.account] += op.amount; } if (!op._virtual) finalAccountAmount[op.account] += op.amount; } break; case CHECK_MODE: if (op.amount >= 0) { if (!op.transfert && !op._virtual) totalCredit += op.amount; if (day >= op.day) { if (!op.transfert && !op._virtual) curCredit += op.amount; if (op.checked && !op._virtual) curAccountAmount[op.account] += op.amount; } if (op.checked && !op._virtual) finalAccountAmount[op.account] += op.amount; } else { if (!op.transfert && user->GetCategoryName(op.category) != _("Unknown")) _categoriesValues[_categoriesIndexes[user->GetCategoryName(op.category)]] += -op.amount ; if (!op.transfert && !op._virtual) totalDebit += -op.amount; if (blocked_account) op.amount = -op.amount; if (day >= op.day) { if (!op.transfert && !op._virtual) curDebit += -op.amount; if (op.checked && !op._virtual) curAccountAmount[op.account] += op.amount; } if (op.checked && !op._virtual) finalAccountAmount[op.account] += op.amount; } break; } } balance = totalCredit - totalDebit; _statsGrid->item(CUR_CREDIT, 1)->setText(v.sprintf("%.2lf", curCredit)); _statsGrid->item(CUR_DEBIT, 1)->setText(v.sprintf("%.2lf", curDebit)); _statsGrid->item(TOTAL_CREDIT, 1)->setText(v.sprintf("%.2lf", totalCredit)); _statsGrid->item(TOTAL_DEBIT, 1)->setText(v.sprintf("%.2lf", totalDebit)); _statsGrid->item(BALANCE, 1)->setText(v.sprintf("%.2lf", balance)); _statsGrid->item(BALANCE, 1)->setForeground((balance >= 0) ? QBrush(Qt::green) : QBrush(Qt::red)); KDChart::Legend* legend = _pie->legend(); for(i=0; iGetCategoriesNumber(); i++) { if (totalDebit != 0) percents = ((double) (_categoriesValues[i]*100))/totalDebit; else percents = 0.0; if (i) _statsGrid->item(CATS_STATS+i+1, 1)->setText(v.sprintf("%.2lf (%02d %%)", _categoriesValues[i], (int)percents)); else _statsGrid->item(CATS_STATS+i, 1)->setText(v.sprintf("%.2lf (%02d %%)", _categoriesValues[i], (int)percents)); QVector< double > vec; vec << _categoriesValues[i]; _pie->setDataset( i, vec, _categories[i] ); if (_categoriesValues[i] == 0.0) legend->setDatasetHidden(i, true); else legend->setDatasetHidden(i, false); // _dataset->setData(_dataset->index(i, 1, QModelIndex()), _categoriesValues[i]); } value = totalDebit - _categoriesValues[0]; if (totalDebit != 0) percents = ((double) (value*100))/totalDebit; else percents = 0.0; _statsGrid->item(NON_FIX, 1)->setText(v.sprintf("%.2lf (%02d %%)", value, (int)percents)); for (i=0, accountIt=user->_accounts.begin(); accountIt!=user->_accounts.end(); accountIt++, i++) { if (accountIt->hidden) { 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", value)); value = curAccountAmount[accountIt->id]; _accountsGrid->item(i, ACCOUNT_CUR)->setText(v.sprintf("%.2lf", value)); _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", value)); } else { value = _accountsInitValues[accountIt->id] - (*virtuals)[accountIt->id]; value2 = (*notChecked)[accountIt->id]; _accountsGrid->item(i, ACCOUNT_INIT)->setText(v.sprintf("%.2lf (%.2lf)", value, value-value2)); value = curAccountAmount[accountIt->id]; _accountsGrid->item(i, ACCOUNT_CUR)->setText(v.sprintf("%.2lf (%.2lf)", value, value-value2)); _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)", value, value-value2)); } } _accountsGrid->resizeColumnToContents(ACCOUNT_INIT); _accountsGrid->resizeColumnToContents(ACCOUNT_CUR); _accountsGrid->resizeColumnToContents(ACCOUNT_FINAL); if (notChecked) delete notChecked; if (virtuals) delete virtuals; _statsGrid->resizeColumnToContents(1); layout(); _inModification = false; } void AccountPanel::OnOperationModified() { UpdateStats(); layout(); } void AccountPanel::OnAccountModified(int row, int column) { User* user = _kiss->GetUser(); double amount; int id = user->GetAccountId(_accounts[row]); if (_inModification || column != ACCOUNT_INIT) return; amount = _accountsGrid->item(row, column)->text().toDouble(); _kiss->SetAccountAmount(id, _curMonth, _curYear, amount); _accountsInitValues[id] = amount; UpdateStats(); } 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; 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); } 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); _wxUI->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 = NULL, *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); _wxUI->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() { double* deltas, *cur_amounts, amount; int i, a; User* user = _kiss->GetUser(); bool had_values, accounts_updated = false; int last_month = 0, last_year = 0, account_updated = 0; std::map > operations; deltas = new double[user->_accounts.size()] ; cur_amounts = new double[user->_accounts.size()] ; operations = _kiss->GetAllOperations(); if (_curMonth == 11) { last_month = 0; last_year = _curYear+1; } else { last_month = _curMonth+1; last_year = _curYear; } for (i=0; i<(int)user->_accounts.size(); i++) { deltas[i] = _kiss->GetAccountAmount(user->_accounts[i].id, _curMonth, _curYear); cur_amounts[i] = deltas[i] += _kiss->CalcAccountAmount(user->_accounts[i].id, _curMonth, _curYear, &had_values); for (a=0; a<(int)operations[last_year].size(); a++) if (operations[last_year][a] == last_month) break; if (a == (int)operations[last_year].size()) { deltas[i] = 0; continue; } amount = _kiss->GetAccountAmount(user->_accounts[i].id, last_month, last_year); deltas[i] -= amount; account_updated++; } if (!account_updated) goto end; last_month = _curMonth; last_year = _curYear; while (1) { account_updated = 0; if (last_month == 11) { last_month = 0; last_year = last_year+1; } else last_month++; for (i=0; i<(int)user->_accounts.size(); i++) { if (deltas[i] == 0.0) continue; amount = _kiss->GetAccountAmount(user->_accounts[i].id, last_month, last_year); if ((cur_amounts[i] - amount) != deltas[i]) continue; cur_amounts[i] = amount + deltas[i]; _kiss->SetAccountAmount(user->_accounts[i].id, last_month, last_year, cur_amounts[i]); cur_amounts[i] += _kiss->CalcAccountAmount(user->_accounts[i].id, last_month, last_year, &had_values); account_updated++; } if (!account_updated) break; accounts_updated = true; } if (last_month == 0) { last_month = 11; last_year--; } else last_month--; end: 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 !")); delete[] deltas; delete[] cur_amounts; }