From 5bea328b8dd0724838caee52c0840a982be93b43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soutad=C3=A9?= Date: Thu, 20 Oct 2011 11:11:59 +0200 Subject: [PATCH] First work on grid --- Makefile | 3 +- src/controller/KissCount.hpp | 4 +- src/view/AccountPanel.cpp | 21 +- src/view/AccountPanel.hpp | 4 +- src/view/grid/ChoiceDelegate.cpp | 50 + src/view/grid/ChoiceDelegate.hpp | 43 + src/view/grid/DateDelegate.cpp | 54 ++ src/view/grid/DateDelegate.hpp | 42 + src/view/grid/FloatDelegate.cpp | 43 + src/view/grid/FloatDelegate.hpp | 39 + src/view/grid/GridAccount.cpp | 1540 ++++++++++++++++++++++++++++++ src/view/grid/GridAccount.hpp | 104 ++ 12 files changed, 1928 insertions(+), 19 deletions(-) create mode 100644 src/view/grid/ChoiceDelegate.cpp create mode 100644 src/view/grid/ChoiceDelegate.hpp create mode 100644 src/view/grid/DateDelegate.cpp create mode 100644 src/view/grid/DateDelegate.hpp create mode 100644 src/view/grid/FloatDelegate.cpp create mode 100644 src/view/grid/FloatDelegate.hpp create mode 100644 src/view/grid/GridAccount.cpp create mode 100644 src/view/grid/GridAccount.hpp diff --git a/Makefile b/Makefile index ed9e175..fd74491 100644 --- a/Makefile +++ b/Makefile @@ -26,7 +26,8 @@ MOCS_OBJS=$(MOC_HEADERS:.hpp=.moc) all: mojito kc clean: - find src -type f -name '*.[o~]' -exec rm -f \{\} \; + find src -type f -name '*.o' -exec rm -f \{\} \; + find src -type f -name '*~' -exec rm -f \{\} \; find src -type f -name '*.moc' -exec rm -f \{\} \; find src -type f -name '*.objs' -exec rm -f \{\} \; rm -f kc diff --git a/src/controller/KissCount.hpp b/src/controller/KissCount.hpp index c5c0fbf..b4b5932 100644 --- a/src/controller/KissCount.hpp +++ b/src/controller/KissCount.hpp @@ -32,7 +32,7 @@ #define APP_VERSION "0.3" -#define ESCAPE_CHARS(s) s.replace("\"", "\\\""); +#define ESCAPE_CHARS(s) s = s.replace("\"", "\\\""); /*{ \ if (s.Find(wxT("\\\"")) == wxNOT_FOUND) \ s.Replace(wxT("\""), wxT("\\\""), true); \ @@ -40,7 +40,7 @@ s.Replace(wxT("\'"), wxT("\\\'"), true); \ } */ -#define UNESCAPE_CHARS(s) s.replace("\\\"", "\""); +#define UNESCAPE_CHARS(s) s = s.replace("\\\"", "\""); /*{ \ s.Replace(wxT("\\\""), wxT("\""), true); \ s.Replace(wxT("\\\'"), wxT("\'"), true); \ diff --git a/src/view/AccountPanel.cpp b/src/view/AccountPanel.cpp index c10866f..d393de9 100644 --- a/src/view/AccountPanel.cpp +++ b/src/view/AccountPanel.cpp @@ -87,18 +87,12 @@ AccountPanel::AccountPanel(KissCount* kiss, wxUI *parent) : KissPanel(kiss, pare _dataset->setData(_dataset->index(i, 1, QModelIndex()), 0.0); _dataset->setData(_dataset->index(i, 0, QModelIndex()), wxUI::categoryColors[i], Qt::DecorationRole); } - // _dataset = new CategorySimpleDataset(_categories, nbCategories); - // _dataset->AddSerie(_("Serie 1"), _categoriesValues, nbCategories); - // _dataset->SetRenderer(new CategoryRenderer(*colorScheme)); - // _pie->SetDataset(_dataset); - // _pie->SetColorScheme(colorScheme); _pie->setModel(_dataset); _pie->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); - // _pie->SetLegend(new Legend(wxBOTTOM, wxCENTER)); - - // _grid = new GridAccount(_kiss, this, OPS_GRID_ID, true, true, true); + _grid = new GridAccount(_kiss, this, true, true, true); + _grid->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); _accountsGrid = new QTableWidget(this); _accountsGrid->setColumnCount(NUMBER_COLS_ACCOUNTS); @@ -112,7 +106,7 @@ AccountPanel::AccountPanel(KissCount* kiss, wxUI *parent) : KissPanel(kiss, pare _accountsGrid->setHorizontalHeaderItem(ACCOUNT_FINAL, new QTableWidgetItem(_("Final value"))); _accountsGrid->resizeColumnsToContents(); - _accountsGrid->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); + _accountsGrid->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); for(i=0; iverticalHeader()->setHidden(true); _statsGrid->horizontalHeader()->setHidden(true); - _statsGrid->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding); + _statsGrid->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); // chart = new wxChartPanel(this); // chart->SetChart(new Chart(_pie, _("Cost repartition"))); @@ -171,7 +165,7 @@ AccountPanel::AccountPanel(KissCount* kiss, wxUI *parent) : KissPanel(kiss, pare hbox2->addWidget(_accountsGrid, 2); hbox2->addWidget(_calendar); vbox2->addLayout(hbox2); - // vbox2->Add(_grid, 0, wxGROW|wxALL, 2); + vbox2->addWidget(_grid, 1); hbox->addLayout(vbox2); vbox->addWidget(_statsGrid); vbox->addWidget(_pie); @@ -309,7 +303,6 @@ void AccountPanel::ChangeUser() curNode = new QTreeWidgetItem(QStringList(QString::number(it->first))); _tree->addTopLevelItem(curNode); } - layout(); if (curYear != -1) { _tree->setCurrentItem(curNode); @@ -320,8 +313,8 @@ void AccountPanel::ChangeUser() { curNode = new QTreeWidgetItem(QStringList(QString::number(curDate.year()))); _tree->addTopLevelItem(curNode); - layout(); } + layout(); } void AccountPanel::LoadYear(int year, bool showMonth) @@ -416,7 +409,7 @@ void AccountPanel::ShowMonth(int month, int year) // Operations are ordered _curOperations = &((*user->_operations[year])[month]); - // _grid->LoadOperations(_curOperations, _curMonth, _curYear); + _grid->LoadOperations(_curOperations, _curMonth, _curYear); InitAccountsGrid(user, month, year); diff --git a/src/view/AccountPanel.hpp b/src/view/AccountPanel.hpp index 034848d..486b9d1 100644 --- a/src/view/AccountPanel.hpp +++ b/src/view/AccountPanel.hpp @@ -37,7 +37,7 @@ #include "view.hpp" #include -// #include "grid/GridAccount.hpp" +#include "grid/GridAccount.hpp" // #include "grid/CalendarEditor.hpp" // #include @@ -79,7 +79,7 @@ private slots: private: QTreeWidget *_tree; QCalendarWidget* _calendar; - // GridAccount* _grid; + GridAccount* _grid; QTableWidget* _accountsGrid, *_statsGrid; PieView* _pie; double *_categoriesValues; diff --git a/src/view/grid/ChoiceDelegate.cpp b/src/view/grid/ChoiceDelegate.cpp new file mode 100644 index 0000000..3f27a50 --- /dev/null +++ b/src/view/grid/ChoiceDelegate.cpp @@ -0,0 +1,50 @@ +/* + Copyright 2010-2011 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 "ChoiceDelegate.hpp" + +#include + +QWidget * ChoiceDelegate::createEditor (QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index ) const +{ + QComboBox* combo = new QComboBox(parent); + + for(int i=0; i<_nbValues; i++) + combo->addItem(_values[i]); + + return combo; +} + +void ChoiceDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, + const QModelIndex &index) const +{ + QComboBox *combo = qobject_cast(editor); + model->setData(index, qVariantFromValue(combo->currentText())); +} + +void ChoiceDelegate::setEditorData(QWidget *editor, + const QModelIndex &index) const + { + QComboBox* combo = qobject_cast(editor); + int i = combo->findText(qVariantValue(index.data())); + + if (i != -1) combo->setCurrentIndex(i); + } diff --git a/src/view/grid/ChoiceDelegate.hpp b/src/view/grid/ChoiceDelegate.hpp new file mode 100644 index 0000000..d097e6d --- /dev/null +++ b/src/view/grid/ChoiceDelegate.hpp @@ -0,0 +1,43 @@ +/* + Copyright 2010-2011 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 . +*/ + +#ifndef CHOICEDELEGATE_H +#define CHOICEDELEGATE_H + +#include +#include + +class ChoiceDelegate : public QItemDelegate +{ + Q_OBJECT; + +public: + ChoiceDelegate(QWidget *parent = 0, QString* values=0, int nbValues=0) : QItemDelegate(parent), _values(values), _nbValues(nbValues) {} + + QWidget * createEditor ( QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index ) const; + void setEditorData(QWidget *editor, const QModelIndex &index) const; + void setModelData(QWidget *editor, QAbstractItemModel *model, + const QModelIndex &index) const; + +private: + QString* _values; + int _nbValues; +}; + +#endif diff --git a/src/view/grid/DateDelegate.cpp b/src/view/grid/DateDelegate.cpp new file mode 100644 index 0000000..4c8d0aa --- /dev/null +++ b/src/view/grid/DateDelegate.cpp @@ -0,0 +1,54 @@ +/* + Copyright 2010-2011 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 "DateDelegate.hpp" + +#include + +QWidget * DateDelegate::createEditor (QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index ) const +{ + QComboBox* combo = new QComboBox(parent); + QDate date(_year, _month, _day); + QString s; + + for(int i=0; iaddItem(s.sprintf("%d", i+1)); + + return combo; +} + +void DateDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, + const QModelIndex &index) const +{ + QComboBox *combo = qobject_cast(editor); + QString s ; + + s = s.sprintf("%02d/%02d/%04d", combo->currentIndex()+1, _month+1, _year); + + model->setData(index, qVariantFromValue(s)); +} + +void DateDelegate::setEditorData(QWidget *editor, + const QModelIndex &index) const +{ + QComboBox* combo = qobject_cast(editor); + combo->setCurrentIndex(qVariantValue(index.data()).left(2).toInt()-1); +} diff --git a/src/view/grid/DateDelegate.hpp b/src/view/grid/DateDelegate.hpp new file mode 100644 index 0000000..68d7405 --- /dev/null +++ b/src/view/grid/DateDelegate.hpp @@ -0,0 +1,42 @@ +/* + Copyright 2010-2011 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 . +*/ + +#ifndef DATEDELEGATE_H +#define DATEDELEGATE_H + +#include +#include + +class DateDelegate : public QItemDelegate +{ + Q_OBJECT; + +public: + DateDelegate(QWidget *parent = 0, int month=0, int year=0) : QItemDelegate(parent), _day(1), _month(month), _year(year) {} + + QWidget * createEditor ( QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index ) const; + void setEditorData(QWidget *editor, const QModelIndex &index) const; + void setModelData(QWidget *editor, QAbstractItemModel *model, + const QModelIndex &index) const; + +private: + int _day, _month, _year; +}; + +#endif diff --git a/src/view/grid/FloatDelegate.cpp b/src/view/grid/FloatDelegate.cpp new file mode 100644 index 0000000..e4b1cd9 --- /dev/null +++ b/src/view/grid/FloatDelegate.cpp @@ -0,0 +1,43 @@ +/* + Copyright 2010-2011 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 "FloatDelegate.hpp" + +QWidget * FloatDelegate::createEditor (QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index ) const +{ + return new QLineEdit(parent); +} + +void FloatDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, + const QModelIndex &index) const +{ + QLineEdit *line = qobject_cast(editor); + QString s ; + double value = line->text().toDouble(); + model->setData(index, qVariantFromValue(s.sprintf("%.2lf", value))); +} + +void FloatDelegate::setEditorData(QWidget *editor, + const QModelIndex &index) const +{ + QLineEdit* line = qobject_cast(editor); + line->setText(qVariantValue(index.data())); +} diff --git a/src/view/grid/FloatDelegate.hpp b/src/view/grid/FloatDelegate.hpp new file mode 100644 index 0000000..7d94a8d --- /dev/null +++ b/src/view/grid/FloatDelegate.hpp @@ -0,0 +1,39 @@ +/* + Copyright 2010-2011 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 . +*/ + +#ifndef FLOATDELEGATE_H +#define FLOATDELEGATE_H + +#include +#include + +class FloatDelegate : public QItemDelegate +{ + Q_OBJECT; + +public: + FloatDelegate(QWidget *parent = 0) : QItemDelegate(parent) {} + + QWidget * createEditor ( QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index ) const; + void setEditorData(QWidget *editor, const QModelIndex &index) const; + void setModelData(QWidget *editor, QAbstractItemModel *model, + const QModelIndex &index) const; +}; + +#endif diff --git a/src/view/grid/GridAccount.cpp b/src/view/grid/GridAccount.cpp new file mode 100644 index 0000000..b04e345 --- /dev/null +++ b/src/view/grid/GridAccount.cpp @@ -0,0 +1,1540 @@ +/* + Copyright 2010-2011 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 "GridAccount.hpp" +#include "ChoiceDelegate.hpp" +#include "DateDelegate.hpp" +#include "FloatDelegate.hpp" + +#define SET_ROW_COLOR(row, backcolor, forecolor) for(int i=0; iitem(row, i)) setItem(row, i, new QTableWidgetItem("")); \ + this->item(row, i)->setBackground(backcolor); \ + this->item(row, i)->setForeground(forecolor); \ + } + +#define SET_ROW_FONT(row, font) for(int i=0; iitem(row, i)) setItem(row, i, new QTableWidgetItem("")); \ + this->item(row, i)->setFont(font); \ + } + +#define SET_READ_ONLY(item) item->setFlags(item->flags() & ~Qt::ItemIsEditable); + +GridAccount::GridAccount(KissCount* kiss, QWidget *parent, + bool canAddOperation, bool setWeek, bool synchronizeWithDatabase) + : QTableWidget(parent), _fixCosts(0), _week1(0), + _week2(0), _week3(0), _week4(0), _parent(parent), _kiss(kiss), + _canAddOperation(canAddOperation), _setWeek(setWeek), + _databaseSynchronization(synchronizeWithDatabase), _loadOperations(false), + _curMonth(0), _curYear(0) +{ + //wxBitmap deleteBitmap(wxT(DELETE_ICON), wxBITMAP_TYPE_PNG); + //wxBitmap checkedBitmap(wxT(CHECKED_ICON), wxBITMAP_TYPE_PNG); + //DEFAULT_FONT(font); + QFont font; + int i; + User* user = _kiss->GetUser(); + std::vector::iterator accountIt; + std::vector::iterator categoryIt; + QTableWidgetItem* item; + + setColumnCount(NUMBER_COLS_OPS); + setRowCount(1); + verticalHeader()->setHidden(true); + horizontalHeader()->setHidden(true); + + setColumnWidth (DESCRIPTION, columnWidth(DESCRIPTION)*3); + //SetDefaultCellFont(font); + + QString colsName[] = {"", _("Description"), _("Date"), _("Debit"), _("Credit"), _("Category"), _("Account"), "", ""}; + for(i=0; isetText(colsName[i]); + item->setBackground(view::OWN_CYAN); + font = item->font(); + font.setBold(true); + item->setFont(font); + SET_READ_ONLY(item); + item->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter); + setItem(0, i, item); + } + //SetCellRenderer(0, OP_DELETE, new wxGridCellBitmapRenderer(deleteBitmap)); + //SetCellRenderer(0, CHECKED, new wxGridCellBitmapRenderer(checkedBitmap)); + + _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 ; + } + + // Connect(id, wxEVT_GRID_CELL_CHANGE, wxGridEventHandler(GridAccount::OnOperationModified), 0, this); + resizeColumnToContents(TREE); + resizeColumnToContents(CATEGORY); + resizeColumnToContents(OP_DATE); + resizeColumnToContents(ACCOUNT); + resizeColumnToContents(OP_DELETE); + resizeColumnToContents(CHECKED); +} + +GridAccount::~GridAccount() +{ + delete[] _categories; + delete[] _accounts; +} + +// wxPen GridAccount::GetColGridLinePen (int col) +// {return wxPen(*wxBLACK, 1, wxSOLID);} + +// wxPen GridAccount::GetRowGridLinePen (int row) { +// if (_canAddOperation) +// { +// if (row == 0 || row == _fixCosts || +// row == _week1 || +// row == _week2 || +// row == _week3 || +// row == _week4) +// return wxPen(*wxBLACK, 1, wxSOLID); +// } +// else +// if (row == 0) +// return wxPen(*wxBLACK, 1, wxSOLID); + +// return GetCellBackgroundColour(row, 0); +// } + +void GridAccount::ResetWeeks() +{ + _week1 = _week2 = _week3 = _week4 = 0; +} + +void GridAccount::SetWeek(int week, int line) { + switch (week) { + case 1: _week1 = line; break; + case 2: _week2 = line; break; + case 3: _week3 = line; break; + case 4: _week4 = line; break; + } +} + +Operation& GridAccount::GetOperation(int id) throw (OperationNotFound) +{ + std::vector::iterator it = std::find(_operations->begin(), _operations->end(), id); + + if (it != _operations->end()) return *it; + + throw OperationNotFound(); +} + +void GridAccount::UpdateOperation(Operation& op) +{ + std::vector::iterator it = std::find(_operations->begin(), _operations->end(), op.id); + + if (it != _operations->end()) + { + if (_databaseSynchronization) + _kiss->UpdateOperation(op); + *it = op; + } +} + +int GridAccount::GetDisplayedRow(int id) +{ + std::vector::iterator it = std::find(_displayedOperations.begin(), _displayedOperations.end(), id); + + if (it != _displayedOperations.end()) return it-_displayedOperations.begin(); + + return -1; +} + +void GridAccount::ClearGrid() +{ + std::vector operations; + + LoadOperations(&operations, 0, 0); +} + +void GridAccount::LoadOperations(std::vector* operations, int month, int year) +{ + std::vector::iterator it; + User* user = _kiss->GetUser(); + int curLine = 0; + Operation NULLop; + + NULLop.id = 0; + + _loadOperations = true; + _operations = operations; + _curMonth = month; + _curYear = year; + _displayedOperations.clear(); + _displayedOperations.push_back(NULLop); // Header + _fixCosts = 0; + it = _operations->begin(); + + if (rowCount() > 1) + clear(); + + ChoiceDelegate* categoryEditor = new ChoiceDelegate(this, _categories, user->GetCategoriesNumber()); + setItemDelegateForColumn(CATEGORY, categoryEditor); + ChoiceDelegate* accountEditor = new ChoiceDelegate(this, _accounts, user->GetAccountsNumber()); + setItemDelegateForColumn(ACCOUNT, accountEditor); + + DateDelegate* dateEditor = new DateDelegate(this, month+1, year); + setItemDelegateForColumn(OP_DATE, dateEditor); + + FloatDelegate* floatEditor = new FloatDelegate(this); + setItemDelegateForColumn(DEBIT, floatEditor); + setItemDelegateForColumn(CREDIT, floatEditor); + + if (_canAddOperation) + { + for (;it != _operations->end() && it->fix_cost; it++) + { + if (it->parent) continue; + + if (_setWeek) + InsertOperationWithWeek(user, *it, ++curLine, true, it->month, it->year); + else + InsertOperation(user, *it, ++curLine, true, it->month, it->year); + } + + InsertOperation(user, NULLop, ++curLine, true, month, year); + + for (; it != _operations->end(); it++) + { + if (it->parent) continue; + + if (_setWeek) + InsertOperationWithWeek(user, *it, ++curLine, false, it->month, it->year); + else + InsertOperation(user, *it, ++curLine, false, it->month, it->year); + } + + InsertOperation(user, NULLop, ++curLine, false, month, year); + } + else + { + for (;it != _operations->end(); it++) + { + if (it->parent) continue; + + InsertOperation(user, *it, ++curLine, it->fix_cost, it->month, it->year); + } + } + + resizeColumnToContents(TREE); + resizeColumnToContents(CATEGORY); + resizeColumnToContents(OP_DATE); + resizeColumnToContents(ACCOUNT); + resizeColumnToContents(OP_DELETE); + resizeColumnToContents(CHECKED); + + _loadOperations = false; +} + +void GridAccount::ComputeWeeks() +{ + std::vector::iterator it; + int curLine, curWeek, week, i; + + if (!_canAddOperation) return; + + for (it = _displayedOperations.begin(), curLine=0; + it != _displayedOperations.end(); + it++, curLine++) + { + if (it->id && !it->fix_cost) break; + } + + if (it == _displayedOperations.end()) return; + + ResetWeeks(); + + // curWeek = wxDateTime(it->day+1, (wxDateTime::Month)it->month, it->year).GetWeekOfMonth(); + // it++; + // for (i=1; it != _displayedOperations.end(); it++, curLine++) + // { + // if (!it->id || it->parent) continue; + // week = wxDateTime(it->day+1, (wxDateTime::Month)it->month, it->year).GetWeekOfMonth(); + // if (week != curWeek) + // { + // SetWeek(i++, curLine); + // curWeek = week; + // } + // } +} + +void GridAccount::InsertOperationWithWeek(User* user, Operation& op, int line, bool fix, int month, int year) +{ + InsertOperation(user, op, line, fix, month, year); + + if (op.id && !fix) + ComputeWeeks(); +} +#include + +void GridAccount::InsertOperation(User* user, Operation& op, int line, bool fix, int month, int year) +{ + std::vector::iterator it; + std::vector::iterator it2; + int r, g, b, i; + double amount; + QColor color; + QDate curDate = QDate::currentDate(); + QString description, v; + QFont font; + Category cat ; + Operation op2; + QTableWidgetItem* item; + QCheckBox* checkBox; + + // // First is header + // if (op) + _displayedOperations.insert(_displayedOperations.begin()+line, op); + + if (!user->_accounts.size()) return; + + insertRow(line); + + // SetCellEditor(line, DEBIT, new wxGridCellFloatEditor(wxID_ANY, 2)); + // SetCellEditor(line, CREDIT, new wxGridCellFloatEditor(wxID_ANY, 2)); + + if (fix) + { + item = new QTableWidgetItem(_("Fix")); + setItem(line, CATEGORY, item); + SET_READ_ONLY(item); + _fixCosts++; + } + + //SetCellEditor(line, DEBIT, new wxGridCellFormulaEditor(op.formula)); + //SetCellEditor(line, CREDIT, new wxGridCellFormulaEditor(op.formula)); + + if (op.id) + { + cat = user->GetCategory(op.category); + + //SetCellEditor(line, OP_DATE, new CalendarEditor(op.day, month, year)); + description = op.description; + UNESCAPE_CHARS(description); + setItem(line, DESCRIPTION, new QTableWidgetItem(description)); + item = new QTableWidgetItem(); + setItem(line, OP_DATE, new QTableWidgetItem(v.sprintf("%02d/%02d/%d", op.day+1, month+1, year))); + if (op.amount < 0) + setItem(line, DEBIT, new QTableWidgetItem(v.sprintf("%.2lf", -op.amount))); + else + setItem(line, CREDIT, new QTableWidgetItem(v.sprintf("%.2lf", op.amount))); + + if (!op.meta) + setItem(line, ACCOUNT, new QTableWidgetItem(user->GetAccountName(op.account))); + if (!fix && !op.meta) + setItem(line, CATEGORY, new QTableWidgetItem(cat.name)); + + checkBox = new QCheckBox(); + checkBox->setTristate(false); + setCellWidget(line, CHECKED, checkBox); + // SetCellRenderer(line, OP_DELETE, new wxGridCellBoolRenderer ()); + // SetCellEditor(line, OP_DELETE, new wxGridCellBoolEditor ()); + + if (op.meta && !op.amount) + { + amount = _kiss->MetaPositiveAmount(op.id); + + setItem(line, DEBIT, new QTableWidgetItem(v.sprintf("%.2lf", amount))); + setItem(line, CREDIT, new QTableWidgetItem(v.sprintf("%.2lf", amount))); + } + + if (op.category) + color = cat.backcolor; + else + color = view::OWN_GREEN; + + if (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.setRgb(r, g, b, color.alpha()); + checkBox->setCheckState(Qt::Checked); + } + + SET_ROW_COLOR(line, color, cat.forecolor); + if (op.category && cat.font.length()) + { + font = user->GetCategoryFont(cat.id); + SET_ROW_FONT(line, font); + } + + if (!_loadOperations) + { + if (op.meta) + resizeColumnToContents(TREE); + resizeColumnToContents(CATEGORY); + resizeColumnToContents(ACCOUNT); + } + } + else + { + //SetCellEditor(line, OP_DATE, new CalendarEditor(0, month, year)); + if (curDate.month() == month && + curDate.year() == year) + { + if (!fix) + setItem(line, OP_DATE, new QTableWidgetItem(v.sprintf("%02d/%02d/%d", curDate.day(), month+1, year))); + //SetCellEditor(line, OP_DATE, new CalendarEditor(curDate.GetDay()-1, month, year)); + } + else + ; + //SetCellEditor(line, OP_DATE, new CalendarEditor(0, month, year)); + + if (fix) + { + SET_ROW_COLOR(line, view::OWN_YELLOW, Qt::black); + } + else + { + SET_ROW_COLOR(line, view::OWN_GREEN, Qt::black); + } + + SET_READ_ONLY(this->item(line, CHECKED)); + SET_READ_ONLY(this->item(line, OP_DELETE)); + } + + this->item(line, OP_DATE)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter); + this->item(line, DEBIT)->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); + this->item(line, CREDIT)->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); + this->item(line, OP_DELETE)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter); + this->item(line, CHECKED)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter); + + if (op.id && op.meta) + { + // SetCellRenderer(line, TREE, new wxGridCellTreeButtonRenderer()); + // SetCellEditor(line, TREE, new wxGridCellTreeButtonEditor()); + + SET_READ_ONLY(this->item(line, OP_DATE)); + SET_READ_ONLY(this->item(line, CREDIT)); + SET_READ_ONLY(this->item(line, DEBIT)); + SET_READ_ONLY(this->item(line, CATEGORY)); + SET_READ_ONLY(this->item(line, ACCOUNT)); + } + else + SET_READ_ONLY(this->item(line, TREE)); + + resizeRowToContents(line); + + layout(); +} + +void GridAccount::DeleteOperation(const Operation& op) +{ + std::vector::iterator it = std::find(_operations->begin(), _operations->end(), op.id); + + if (it != _operations->end()) _operations->erase(it); +} + +void GridAccount::InsertIntoGrid(Operation& op) +{ + int i, a, start; + User* user = _kiss->GetUser(); + Operation parent; + + // No previous fix operations + if (op.fix_cost && !_displayedOperations[1].id) + i = 1; + else + { + if (op.parent) + start = GetDisplayedRow(op.parent); + else + start = 0; + + for(i=start; i<(int)_displayedOperations.size(); i++) + { + if (!_displayedOperations[i].id) continue; + if (_displayedOperations[i].parent) continue; + if ((_displayedOperations)[i].fix_cost && !op.fix_cost) continue; + if (!(_displayedOperations)[i].fix_cost && op.fix_cost) break; + if (user->_preferences["operation_order"] == "ASC") + { + if ((_displayedOperations)[i].day > op.day) + break; + } + else + { + if ((_displayedOperations)[i].day < op.day) + break; + } + } + + if (op.parent) + { + parent = GetOperation(op.parent); + if ((i-start) > (int)(parent.childs.size())) + i = start + parent.childs.size(); + if (parent.day >= op.day) + i = start + 1; + } + else if (i == (int)_displayedOperations.size() || + i == _fixCosts) + i--; + else if (!(_displayedOperations)[i].fix_cost && op.fix_cost) + i --; + } + + for (a=0; a<(int)_operations->size(); a++) + { + if ((*_operations)[a].fix_cost && !op.fix_cost) continue; + if (!(*_operations)[a].fix_cost && op.fix_cost) + { + a--; + break; + } + if ((*_operations)[a].day > op.day) + { + a--; + break; + } + } + + if (a < 0) a = 0; + _operations->insert(_operations->begin()+a, op); + + InsertOperationWithWeek(user, (*_operations)[a], i, op.fix_cost, _curMonth, _curYear); +} + +int GridAccount::RemoveMeta(Operation op, int line, bool removeRoot, bool deleteOp) +{ + // std::vector::iterator it, it2; + // wxGridCellTreeButtonRenderer* treeRenderer; + // int i, deletedOperations = 0; + // Operation op2; + + // treeRenderer = (wxGridCellTreeButtonRenderer*) GetCellRenderer(line, TREE); + + // for(i=0; i<(int)op.childs.size(); i++) + // { + // op2 = GetOperation(op.childs[i]); + // if (op2.meta) + // RemoveMeta(op2, line+1, true, deleteOp); + // else + // { + // if (treeRenderer->IsCollapsed()) + // { + // DeleteRows(line+1, 1); + // deletedOperations++; + // if (op2.fix_cost) _fixCosts--; + // _displayedOperations.erase(_displayedOperations.begin()+line+1); + // } + + // if (deleteOp) + // { + // DeleteOperation(op2); + // if (_databaseSynchronization) + // _kiss->DeleteOperation(op2); + // } + // } + // } + + // op.childs.clear(); + + // if (removeRoot) + // { + // DeleteRows(line, 1); + // _displayedOperations.erase(_displayedOperations.begin()+line); + // if (op.fix_cost) _fixCosts--; + // if (deleteOp) + // { + // DeleteOperation(op); + // if (_databaseSynchronization) + // _kiss->DeleteOperation(op); + // } + // deletedOperations++; + // } + + // treeRenderer->DecRef(); + + // return deletedOperations; + return 0; +} + +void GridAccount::CheckMeta(Operation& op, int line, bool check) +{ + // std::vector::iterator it, it2; + // wxGridCellTreeButtonRenderer* treeRenderer; + // int i; + // Operation op2; + // wxColour color ; + // unsigned char r, g, b; + // User* user = _kiss->GetUser(); + + // treeRenderer = (wxGridCellTreeButtonRenderer*) GetCellRenderer(line, TREE); + + // for(i=0; i<(int)op.childs.size(); i++) + // { + // op2 = GetOperation(op.childs[i]); + // op2.checked = check; + // UpdateOperation(op2); + + // if (op2.meta) + // CheckMeta(op2, line+1, check); + + // if (treeRenderer->IsCollapsed()) + // { + // SetCellValue(line+i+1, CHECKED, check ? wxT("1") : wxT("0")); + // color = user->GetCategory(op2.category).backcolor; + + // if (check) + // { + // 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(line+i+1, color, user->GetCategory(op2.category).forecolor); + // } + // } + + // treeRenderer->DecRef(); +} + +void GridAccount::OnOperationModified() +{ + // User* user = _kiss->GetUser(); + // int row = event.GetRow(); + // int col = event.GetCol(); + // Operation new_op, cur_op, op_tmp, op_tmp2; + // int op_complete = 6, i, last_day; + // wxString value ; + // wxDateTime date; + // bool need_insertion = false; + // static bool inModification = false ; + // wxColour color ; + // unsigned char r, g, b; + // wxGridCellTreeButtonRenderer* treeRenderer; + // std::vector::iterator it; + // Operation op, op2; + // double amount; + // wxFont font; + // Category cat ; + + // // Avoid recursives calls + // if (inModification || _loadOperations) return; + + // inModification = true ; + + // if (col == TREE) + // { + // treeRenderer = (wxGridCellTreeButtonRenderer*) GetCellRenderer(row, col); + + // op = _displayedOperations[row]; + + // if (!treeRenderer->IsCollapsed()) + // { + // for (i=1, it=op.childs.begin(); it!=op.childs.end(); it++, i++) + // { + // op2 = GetOperation(*it); + // InsertOperationWithWeek(user, op2, row+i, op2.fix_cost, op2.month, op2.year); + // } + // } + // else + // { + // RemoveMeta(op, row, false, false); + // } + + // treeRenderer->DecRef(); + + // ComputeWeeks(); + // inModification = false; + // _parent->Fit(); + // return; + // } + + // if (col == DEBIT) + // SetCellValue(row, CREDIT, ""); + // else if (col == CREDIT) + // SetCellValue(row, DEBIT, ""); + + // value = GetCellValue(row, DESCRIPTION); + // if (value) + // { + // new_op.description = value; + // op_complete--; + // } + + // value = GetCellValue(row, OP_DATE); + // if (value) + // { + // 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--; + // } + + // if (col == DESCRIPTION && + // (!GetCellValue(row, CATEGORY) || + // !GetCellValue(row, ACCOUNT))) + // { + // new_op.fix_cost = (row <= _fixCosts); + // if (_kiss->SearchPreviousOperation(&op_tmp, new_op, _curMonth, _curYear, _canAddOperation)) + // { + // if (!GetCellValue(row, CATEGORY)) + // { + // new_op.category = op_tmp.category; + // SetCellValue(row, CATEGORY, wxGetTranslation(user->GetCategoryName(new_op.category))); + // op_complete--; + // } + + // if (!GetCellValue(row, ACCOUNT)) + // { + // new_op.account = op_tmp.account; + // SetCellValue(row, ACCOUNT, user->GetAccountName(new_op.account)); + // op_complete--; + // } + + // col = CATEGORY; + // new_op.fix_cost = (new_op.category == user->GetCategoryId(wxT("Fix"))); + // } + // } + + // value = GetCellValue(row, DEBIT); + // if (value) + // { + // value.ToDouble(&new_op.amount); + // if (new_op.amount < 0) + // { + // new_op.amount *= -1.0; + // SetCellValue(row, DEBIT, wxString::Format(wxT("%.2lf"), new_op.amount)); + // } + // if (new_op.amount != 0.0) new_op.amount *= -1.0; + // op_complete--; + // wxGridCellFormulaEditor* pEditor = (wxGridCellFormulaEditor*) GetCellEditor(row, DEBIT); + // new_op.formula = pEditor->GetFormula(); + // pEditor->DecRef(); + // } + + // value = GetCellValue(row, CREDIT); + // if (value) + // { + // value.ToDouble(&new_op.amount); + // if (new_op.amount < 0) + // { + // new_op.amount *= -1.0; + // SetCellValue(row, CREDIT, wxString::Format(wxT("%.2lf"), new_op.amount)); + // } + // op_complete--; + // wxGridCellFormulaEditor* pEditor = (wxGridCellFormulaEditor*) GetCellEditor(row, CREDIT); + // new_op.formula = pEditor->GetFormula(); + // pEditor->DecRef(); + // } + + // value = GetCellValue(row, CATEGORY); + // if (value) + // { + // new_op.category = user->GetCategoryId(value); + // op_complete--; + // } + + // value = GetCellValue(row, ACCOUNT); + // if (value) + // { + // new_op.account = user->GetAccountId(value); + // op_complete--; + // } + + // value = GetCellValue(row, CHECKED); + // if (value && value != wxT("0")) + // new_op.checked = true; + // else + // new_op.checked = false; + // op_complete--; + + // cur_op = (_displayedOperations)[row] ; + + // if (col == CHECKED || col == CATEGORY) + // { + // color = user->GetCategory(new_op.category).backcolor; + + // 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(row, color, user->GetCategory(new_op.category).forecolor); + // SET_ROW_FONT(row, user->GetCategoryFont(new_op.category)); + + // if (col == CHECKED) + // { + // cur_op.checked = new_op.checked; + // UpdateOperation(cur_op); + // inModification = false; + // if (cur_op.meta) + // CheckMeta(cur_op, row, cur_op.checked); + // else + // { + // if (cur_op.parent) + // { + // op2 = GetOperation(cur_op.parent); + // UpdateMeta(op2); + // int row2 = GetDisplayedRow(op2.id); + // SetCellValue(row2, CHECKED, op2.checked ? wxT("1") : wxT("0")); + + // color = user->GetCategory(op2.category).backcolor; + + // if (op2.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(row2, color, user->GetCategory(op2.category).forecolor); + // } + // } + // event.Skip(); + // return; + // } + // } + + // if (col == OP_DELETE) + // { + // wxMessageDialog dialog(this, _("Are you sure want to delete : \n")+new_op.description, wxT("KissCount"), wxYES_NO); + // if (dialog.ShowModal() == wxID_NO) + // { + // SetCellValue(row, col, wxT("0")); + // inModification = false; + // return; + // } + // } + + // // Modify a fix operation + // if (row < _fixCosts || !_canAddOperation) + // { + // if (col == OP_DELETE) + // { + // if (cur_op.parent) + // user->UnGroup(_displayedOperations[row]); + + // if (cur_op.meta) + // RemoveMeta(_displayedOperations[row], row, true, true); + // else + // { + // if (cur_op.parent) + // { + // op_tmp = GetOperation(cur_op.parent); + // for (int a=0; a<(int)op_tmp.childs.size(); a++) + // if (op_tmp.childs[a] == op.id) + // { + // op2.childs.erase(op_tmp.childs.begin()+a); + // break; + // } + // } + + // DeleteRows(row, 1); + // DeleteOperation(cur_op); + // if (_databaseSynchronization) + // _kiss->DeleteOperation(cur_op); + // _displayedOperations.erase(_displayedOperations.begin()+row); + + // if (cur_op.parent && op_tmp.childs.size() < 2) + // { + // if (op_tmp.childs.size() == 1) + // { + // op_tmp2 = GetOperation(op_tmp.childs[0]); + // op_tmp2.parent = ""; + // UpdateOperation(op_tmp2); + // row = GetDisplayedRow(op_tmp2.id); + // _displayedOperations[row] = op_tmp2; + // } + // row = GetDisplayedRow(cur_op.parent); + // DeleteRows(row, 1); + // DeleteOperation(op_tmp); + // if (_databaseSynchronization) + // _kiss->DeleteOperation(op_tmp); + // _displayedOperations.erase(_displayedOperations.begin()+row); + // _fixCosts--; + // } + // _fixCosts--; + // ComputeWeeks(); + // } + // inModification = false ; + // event.Skip(); + // return ; + // } + + // new_op.id = cur_op.id; + // new_op.fix_cost = true; + // new_op.transfert = cur_op.transfert; + // new_op.meta = cur_op.meta; + // new_op.parent = cur_op.parent; + // new_op.childs = cur_op.childs; + // new_op._virtual = cur_op._virtual; + + // if (cur_op.day != new_op.day) + // { + // need_insertion = true; + // DeleteRows(row, 1); + // DeleteOperation(cur_op); + // _displayedOperations.erase(_displayedOperations.begin()+row); + // _fixCosts--; + // } + // else + // { + // UpdateOperation(new_op); + // (_displayedOperations)[row] = new_op; + // } + // } + // // Add a fixCost + // else if (row == _fixCosts) + // { + // if (op_complete) { + // inModification = false ; + // return ; + // } + // need_insertion = true; + // new_op.fix_cost = true; + // new_op.meta = false; + // new_op._virtual = false; + + // for(i=0; iAddOperation(new_op); + // } + // // Modify an operation + // else if (row < (int)(_displayedOperations.size()-1)) + // { + // new_op.id = cur_op.id; + // new_op.fix_cost = false; + // new_op.transfert = cur_op.transfert; + // new_op.meta = cur_op.meta; + // new_op.parent = cur_op.parent; + // new_op.childs = cur_op.childs; + // new_op._virtual = cur_op._virtual; + + // if (col == OP_DELETE) + // { + // if (cur_op.parent) + // user->UnGroup(_displayedOperations[row]); + + // if (cur_op.meta) + // RemoveMeta(_displayedOperations[row], row, true, true); + // else + // { + // if (cur_op.parent) + // { + // op_tmp = GetOperation(cur_op.parent); + // for (int a=0; a<(int)op_tmp.childs.size(); a++) + // if (op_tmp.childs[a] == op.id) + // { + // op2.childs.erase(op_tmp.childs.begin()+a); + // break; + // } + // } + + // DeleteRows(row, 1); + // DeleteOperation(cur_op); + // _displayedOperations.erase(_displayedOperations.begin()+row); + // if (_databaseSynchronization) + // _kiss->DeleteOperation(cur_op); + + // if (cur_op.parent && op_tmp.childs.size() <= 1) + // { + // if (op_tmp.childs.size() == 1) + // { + // op_tmp2 = GetOperation(op_tmp.childs[0]); + // op_tmp2.parent = ""; + // UpdateOperation(op_tmp2); + // row = GetDisplayedRow(op_tmp2.id); + // _displayedOperations[row] = op_tmp2; + // } + // row = GetDisplayedRow(cur_op.parent); + // DeleteRows(row, 1); + // DeleteOperation(op_tmp); + // if (_databaseSynchronization) + // _kiss->DeleteOperation(op_tmp); + // _displayedOperations.erase(_displayedOperations.begin()+row); + // } + + // ComputeWeeks(); + // } + // inModification = false ; + // event.Skip(); + // return ; + // } + + // if (cur_op.day != new_op.day) + // { + // need_insertion = true; + // DeleteRows(row, 1); + // DeleteOperation(cur_op); + // _displayedOperations.erase(_displayedOperations.begin()+row); + // } + // else + // { + // UpdateOperation(new_op); + // (_displayedOperations)[row] = new_op; + // } + // } + // // Add an operation + // else + // { + // if (op_complete) { + // inModification = false ; + // return ; + // } + // need_insertion = true; + // new_op.fix_cost = false; + // new_op.meta = false; + // new_op._virtual = false; + + // for(i=0; iAddOperation(new_op); + // } + + // if (user->GetAccount(new_op.account).blocked && new_op.amount < 0) + // wxMessageBox(_("You made a debit on a blocked account"), _("Warning"), wxICON_WARNING | wxOK); + + // if (need_insertion) + // { + // InsertIntoGrid(new_op); + // UpdateOperation(new_op); + // } + + // if (new_op.parent) + // { + // row = GetDisplayedRow(new_op.parent); + + // new_op = _displayedOperations[row]; + + // last_day = new_op.day; + + // UpdateMeta(new_op); + + // _displayedOperations[row] = new_op; + + // cat = user->GetCategory(new_op.category); + + // if (new_op.category) + // color = cat.backcolor; + // else + // color = view::OWN_GREEN; + + // 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()); + // SetCellValue(row, CHECKED, wxT("1")); + // } + // else + // SetCellValue(row, CHECKED, wxT("0")); + + + // SET_ROW_COLOR(row, color, cat.forecolor); + + // if (new_op.category && cat.font) + // { + // font = user->GetCategoryFont(cat.id); + // SET_ROW_FONT(row, font); + // } + + // SetCellValue(row, OP_DATE, wxString::Format(wxT("%02d/%02d/%d"), new_op.day+1, _curMonth+1, _curYear)); + + // if (!_displayedOperations[row].amount) + // { + // amount = _kiss->MetaPositiveAmount(new_op.id); + + // SetCellValue(row, DEBIT, wxString::Format(wxT("%.2lf"), amount)); + // SetCellValue(row, CREDIT, wxString::Format(wxT("%.2lf"), amount)); + // } + // else + // { + // if (_displayedOperations[row].amount < 0) + // { + // SetCellValue(row, DEBIT, wxString::Format(wxT("%.2lf"), -new_op.amount)); + // SetCellValue(row, CREDIT, ""); + // } + // else + // { + // SetCellValue(row, DEBIT, ""); + // SetCellValue(row, CREDIT, wxString::Format(wxT("%.2lf"), new_op.amount)); + // } + // } + + // // Move updated meta + // if ((int)new_op.day != last_day) + // { + // int i; + // RemoveMeta(new_op, row, true, false); + // InsertIntoGrid(new_op); + // row = GetDisplayedRow(new_op.id); + // for (i=1, it=new_op.childs.begin(); it!=new_op.childs.end(); it++, i++) + // { + // op2 = GetOperation(*it); + // InsertOperationWithWeek(user, op2, row+i, op2.fix_cost, _curMonth, _curYear); + // } + // treeRenderer = (wxGridCellTreeButtonRenderer*) GetCellRenderer(row, 0); + // treeRenderer->Invert(); + // treeRenderer->DecRef(); + // } + // } + + // inModification = false ; + + // event.Skip(); +} + +void GridAccount::UpdateMeta(Operation& meta) +{ + std::vector::iterator it; + Operation op ; + int category = 0; + bool updateCat = false ; + + if (!meta.childs.size()) return ; + + meta.category = 0; + meta.checked = true; + meta.amount = 0; + + for(it=meta.childs.begin(); it!=meta.childs.end(); it++) + { + op = GetOperation(*it); + if (op.year <= meta.year && op.month <= meta.month && op.day < meta.day) + { + meta.year = op.year; + meta.month = op.month; + meta.day = op.day; + } + meta.checked &= op.checked; + if (!meta.description.length() && op.description.length()) + meta.description = op.description; + if (!category) + { + if (op.category) + { + category = op.category; + updateCat = true; + } + } + else + { + if (op.category && op.category != category) + updateCat = false; + } + op.parent = meta.id; + } + + if (updateCat) + meta.category = category; + + meta.amount = _kiss->MetaAmount(meta.id); + + UpdateOperation(meta); +} + + +void GridAccount::GetSelectedOperations(std::vector* rows) +{ + // std::vector::iterator it; + + // rows->clear(); + + // // Blocks. We always expect btl and bbr to have the same size, since their + // // entries are supposed to correspond. + // const wxGridCellCoordsArray& btl(GetSelectionBlockTopLeft()); + // const wxGridCellCoordsArray& bbr(GetSelectionBlockBottomRight()); + // size_t blockCount = btl.size(); + + // if (blockCount == bbr.size()) + // { + // for (size_t i = 0; i < blockCount; ++i) + // { + // const wxGridCellCoords& tl = btl[i]; + // const wxGridCellCoords& br = bbr[i]; + // for (int row = tl.GetRow(); row <= br.GetRow(); ++row) + // { + // it = std::find(rows->begin(), rows->end(), row); + + // if (it != rows->end() || !row) continue; + + // rows->push_back(row); + // } + // } + // } + + // // Singly selected cells. + // const wxGridCellCoordsArray& cells(GetSelectedCells()); + // for (size_t i = 0; i < cells.size(); ++i) + // { + // int row = cells[i].GetRow(); + + // if (!row) continue; + + // it = std::find(rows->begin(), rows->end(), row); + + // if (it != rows->end()) continue; + + // rows->push_back(row); + // } +} + +void GridAccount::Group() +{ + // std::vector selected, rows; + // std::vector::iterator it; + // std::vector ops; + // std::vector::iterator it2; + // std::vector::iterator it3; + // wxString parent = ""; + // Operation op, op2; + // int fix = -1, i, a, row; + + // GetSelectedOperations(&selected); + + // for (size_t i = 0; i < selected.size(); ++i) + // { + // op = _displayedOperations[selected[i]] ; + + // if (op.id) + // { + // if (!parent) + // { + // if (op.parent) + // { + // parent = op.parent; + // continue; + // } + // else if(op.meta) + // parent = op.id; + // } + // else + // { + // if ((parent && op.parent && op.parent != parent)) + // { + // wxMessageBox(_("Cannot group these operations"), _("Error"), wxICON_ERROR | wxOK); + // return ; + // } + // } + + // if (fix != -1 && ((!fix && op.fix_cost) || (fix && !op.fix_cost))) + // { + // wxMessageBox(_("Cannot group these operations"), _("Error"), wxICON_ERROR | wxOK); + // return ; + // } + + // if (fix == -1) + // fix = op.fix_cost ? 1 : 0; + + // ops.push_back(op); + // rows.push_back(selected[i]); + // } + // } + + // if (!ops.size()) return; + + // if (!parent) + // { + // if (rows.size() < 2) return; + + // op.parent = ""; + // op.day = ops[0].day; + // op.month = ops[0].month; + // op.year = ops[0].year; + // op.amount = 0; + // op.description = ""; + // op.category = ""; + // op.fix_cost = fix; + // op.account = ""; + // op.checked = false; + // op.transfert = ""; + // op.formula = ""; + // op.meta = true; + // op.childs.clear(); + + // op.id = _kiss->AddOperation(op); + // } + // else + // { + // if (rows.size() < 1) return; + + // row = GetDisplayedRow(parent); + // op = _displayedOperations[row]; + + // //if (op.id) return; + // } + + // std::sort(rows.begin(), rows.end()); + + // for(i=0; i<(int)rows.size(); i++) + // { + // if (ops[i].meta) + // RemoveMeta(ops[i], rows[i], true, false); + // else + // { + // if (ops[i].fix_cost) _fixCosts--; + // DeleteRows(rows[i], 1); + // _displayedOperations.erase(_displayedOperations.begin()+rows[i]); + + // for(a=i+1; a<(int)rows.size(); a++) + // if (rows[a] >= rows[i]) + // rows[a]--; + // } + // } + + // for(it2=ops.begin(); it2!=ops.end(); it2++) + // { + // if (it2->id == parent) continue; + + // for (i=0, it3=op.childs.begin(); it3!=op.childs.end(); it3++, i++) + // { + // op2 = GetOperation(*it3); + // if (*it3 == it2->id || + // op2.day > it2->day) + // break; + // } + + // if (i) i--; + + // if (it3 == op.childs.end()) + // op.childs.push_back(it2->id); + // else if (*it3 == it2->id) + // continue; + // else + // op.childs.insert(op.childs.begin()+i, it2->id); + + // it2->parent = op.id; + // UpdateOperation(*it2); + // } + + // UpdateMeta(op); + + // InsertIntoGrid(op); + + // UpdateOperation(op); +} + + +void GridAccount::UnGroup() +{ +// std::vector rows, selected; +// std::vector::iterator it; +// std::vector ops; +// std::vector ops2; +// std::vector::iterator it2; +// std::vector::iterator it3; +// wxString parent = ""; +// Operation op, op2; +// int fix = -1, i, a, line; + +// GetSelectedOperations(&selected); + +// for (size_t i = 0; i < selected.size(); ++i) +// { +// op = _displayedOperations[selected[i]] ; + +// if (op.id) +// { +// if ((parent && op.parent != parent) +// || (!op.parent && !op.meta)) +// { +// wxMessageBox(_("Cannot ungroup these operations"), _("Error"), wxICON_ERROR | wxOK); +// return ; +// } + +// if (fix != -1 && ((!fix && op.fix_cost) || (fix && !op.fix_cost))) +// { +// wxMessageBox(_("Cannot ungroup these operations"), _("Error"), wxICON_ERROR | wxOK); +// return ; +// } + +// if (fix == -1) +// fix = op.fix_cost ? 1 : 0; + +// if(op.meta) +// { +// parent = op.id; +// continue; +// } + +// if (!parent && op.parent) +// parent = op.parent; + +// ops.push_back(op); +// rows.push_back(selected[i]); +// } +// } + +// if (!ops.size() && !parent) return; + +// removeLastGroup: +// // Only one meta is selected +// if (!ops.size()) +// { +// line = GetDisplayedRow(parent); +// op = _displayedOperations[line]; +// ops2 = op.childs; +// RemoveMeta(op, line, true, false); + +// for(i=0; i<(int)ops2.size(); i++) +// { +// op2 = GetOperation(ops2[i]); +// op2.parent = ""; +// UpdateOperation(op2); +// InsertIntoGrid(op2); +// } + +// _kiss->DeleteOperation(op); +// DeleteOperation(op); +// } +// else +// { +// if (!parent) return; + +// line = GetDisplayedRow(parent); +// op2 = _displayedOperations[line]; + +// for(i=0; i<(int)ops.size(); i++) +// { +// op = ops[i]; +// op.parent = 0; +// UpdateOperation(op); +// line = GetDisplayedRow(op.id); +// DeleteRows(line, 1); +// _displayedOperations.erase(_displayedOperations.begin()+line); +// InsertIntoGrid(GetOperation(op.id)); +// if (op.fix_cost) _fixCosts--; +// for (a=0; a<(int)op2.childs.size(); a++) +// if (op2.childs[a] == op.id) +// { +// op2.childs.erase(op2.childs.begin()+a); +// break; +// } +// UpdateMeta(op2); +// UpdateOperation(op2); +// } + +// line = GetDisplayedRow(parent); +// _displayedOperations[line] = op2; + +// if (op2.childs.size() < 2) +// { +// ops.clear(); +// // Sorry ... +// goto removeLastGroup; +// } + +// UpdateOperation(op2); +// } + +// ComputeWeeks(); +} + +void GridAccount::MassUpdate(std::vector& rows, updateOperationFunc func, void** params) +{ + // int i, b; + // std::vector::iterator it; + // Operation op, op2; + + // _parent->Disable(); + + // _parent->SetCursor(wxCursor(wxCURSOR_WAIT)); + + // _parent->Update(); + + // if (rows.size()) + // { + // for(i=0; i<(int)rows.size(); i++) + // { + // op = _displayedOperations[rows[i]]; + + // func (&op, params); + + // UpdateOperation(op); + + // if (op.meta) + // { + // for(b=0; b<(int)op.childs.size(); b++) + // { + // op2 = GetOperation(op.childs[b]); + // func (&op2, params); + // UpdateOperation(op2); + // } + // } + // } + // } + // else + // { + // for(it=_operations->begin(); it!=_operations->end(); it++) + // { + // func (&(*it), params); + // if (_databaseSynchronization) + // _kiss->UpdateOperation(*it); + // } + // } + + // ClearGrid(); + + // LoadOperations(_operations, 0, 0); + + // Layout(); + + // _parent->Enable(); + + // _parent->SetCursor(wxNullCursor); +} diff --git a/src/view/grid/GridAccount.hpp b/src/view/grid/GridAccount.hpp new file mode 100644 index 0000000..297f3a0 --- /dev/null +++ b/src/view/grid/GridAccount.hpp @@ -0,0 +1,104 @@ +/* + Copyright 2010-2011 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 . +*/ + +#ifndef GRIDACCOUNT_H +#define GRIDACCOUNT_H + +// #include +// #include +#include +#include +#include +#include +#include +#include +// #include "wxGridCellFastBoolEditor.hpp" +// #include "wxGridCellTreeButtonRenderer.hpp" +// #include "wxGridCellTreeButtonEditor.hpp" +// #include "wxGridCellBitmapRenderer.hpp" +// #include "wxGridCellFormulaEditor.hpp" +// #include "wxGridCellTabStringRenderer.hpp" + +#include + +class KissCount; + +enum {TREE, DESCRIPTION, OP_DATE, DEBIT, CREDIT, CATEGORY, ACCOUNT, OP_DELETE, CHECKED, NUMBER_COLS_OPS}; + +typedef void (*updateOperationFunc)(Operation* op, void** params); + +class GridAccount : public QTableWidget +{ + Q_OBJECT; + +public: + class OperationNotFound {}; + + GridAccount(KissCount* kiss, QWidget *parent, + bool canAddOperation, bool setWeek, bool synchronizeWithDatabase); + ~GridAccount(); + + // wxPen GetColGridLinePen (int col); + // wxPen GetRowGridLinePen (int row); + + virtual void ClearGrid(); + void LoadOperations(std::vector* operations, int month, int year); + void InsertOperationWithWeek(User* user, Operation& op, int line, bool fix, int month, int year) ; + void InsertOperation(User* user, Operation& op, int line, bool fix, int month, int year) ; + + void GetSelectedOperations(std::vector* rows); + + void MassUpdate(std::vector& rows, updateOperationFunc func, void** params); + + void Group(); + void UnGroup(); + + int _fixCosts; + int _week1, _week2, _week3, _week4; + std::vector _displayedOperations; + +private slots: + void OnOperationModified(); + +private: + QWidget* _parent; + KissCount* _kiss; + bool _displayLines; + bool _canAddOperation, _setWeek; + bool _databaseSynchronization; + QString* _categories, *_accounts; + std::vector* _operations; + bool _loadOperations; + int _curMonth, _curYear; + + void SetWeek(int week, int line); + void ResetWeeks(); + void ComputeWeeks(); + + void InsertIntoGrid(Operation& op); + void DeleteOperation(const Operation& op); + void UpdateMeta(Operation& op); + int RemoveMeta(Operation op, int line, bool removeRoot, bool deleteOp); + void CheckMeta(Operation& op, int line, bool check); + + Operation& GetOperation(int id) throw(OperationNotFound); + void UpdateOperation(Operation& op); + int GetDisplayedRow(int id); +}; +#endif