diff --git a/src/controller/KissCount.cpp b/src/controller/KissCount.cpp index 476b19a..19104ef 100644 --- a/src/controller/KissCount.cpp +++ b/src/controller/KissCount.cpp @@ -190,8 +190,8 @@ void KissCount::UpdateAccount(Account& ac) _db->UpdateAccount(ac); _user->UpdateAccount(ac); - if (ac._default) - std::sort(_user->_accounts.begin(), _user->_accounts.end(), Account()); + // if (ac._default) + // std::sort(_user->_accounts.begin(), _user->_accounts.end(), Account()); } void KissCount::DeleteAccount(Account& ac, int replacement) diff --git a/src/model/Database.cpp b/src/model/Database.cpp index f2c7d79..b3bd7b6 100644 --- a/src/model/Database.cpp +++ b/src/model/Database.cpp @@ -856,6 +856,8 @@ void Database::AddSharedAccount(Account& ac, const QString& granted) req = QString("INSERT INTO shared_account ('account', 'user') VALUES ('%1', '%2')").arg(QString::number(ac.id), set.value("id").toString()); + query.clear(); + EXECUTE_SQL_UPDATE(req, ); if (!ac.shared) @@ -1638,7 +1640,7 @@ std::map Database::getSharedAccountOwners(int account) std::map res; QSqlRecord set, set2; QSqlQuery query(_db); - QString req; + QString req, user; req = QString("SELECT user FROM shared_account WHERE account='%1'").arg(account); @@ -1648,15 +1650,20 @@ std::map Database::getSharedAccountOwners(int account) { set = query.record(); + user = set.value("user").toString(); + req = QString("SELECT name FROM user WHERE id='%1'").arg(set.value("user").toString()); query.clear(); EXECUTE_SQL_QUERY(req, res); - set2 = query.record(); + if (query.next()) + { + set2 = query.record(); - res[set2.value("name").toString()] = set.value("user").toString(); + res[set2.value("name").toString()] = user; + } } return res; @@ -1682,9 +1689,12 @@ QString Database::getSharedAccountOwner(int account) EXECUTE_SQL_QUERY(req, ""); - set = query.record(); - - return set.value("name").toString(); + if (query.next()) + { + set = query.record(); + + return set.value("name").toString(); + } } return ""; diff --git a/src/model/User.cpp b/src/model/User.cpp index 12cd34a..b84d6d3 100644 --- a/src/model/User.cpp +++ b/src/model/User.cpp @@ -281,9 +281,8 @@ bool User::Group(std::vector* ops, const Operation& op) if (it->id == op.parent) { it2 = std::find(it->childs.begin(), it->childs.end(), op.id); - // Already into childs - if (it2 != it->childs.end()) return true; - it->childs.push_back(op.id); + if (it2 == it->childs.end()) + it->childs.push_back(op.id); return true; } } @@ -293,10 +292,14 @@ bool User::Group(std::vector* ops, const Operation& op) void User::Group(const Operation& op) { + std::vector::iterator it; + if (!Group(&(*_operations[op.year])[op.month], op) && _db->LoadOperation(this, op.parent)) { - (*_operations[op.year])[op.month][(*_operations[op.year])[op.month].size()-1].childs.push_back(op.id); + it = std::find ((*_operations[op.year])[op.month].begin(), (*_operations[op.year])[op.month].end(), op.parent); + if (it != (*_operations[op.year])[op.month].end()) + it->childs.push_back(op.id); } } diff --git a/src/view/AccountPanel.cpp b/src/view/AccountPanel.cpp index 3344342..f35f268 100644 --- a/src/view/AccountPanel.cpp +++ b/src/view/AccountPanel.cpp @@ -451,7 +451,6 @@ void AccountPanel::InitAccountsGrid(User* user, int month, int year) for(i=0; ihorizontalHeaderItem(i)->font(); _accountsGrid->horizontalHeaderItem(i)->setFont(font); } diff --git a/src/view/PreferencesPanel.cpp b/src/view/PreferencesPanel.cpp new file mode 100644 index 0000000..7a1466a --- /dev/null +++ b/src/view/PreferencesPanel.cpp @@ -0,0 +1,1008 @@ +/* + 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 "PasswordDialog.hpp" + +#include "PreferencesPanel.hpp" +#include "grid/StarDelegate.hpp" + +enum {ACCOUNT_NAME, ACCOUNT_NUMBER, ACCOUNT_DEFAULT, ACCOUNT_VIRTUAL, ACCOUNT_BLOCKED, ACCOUNT_DELETE, NUMBER_COLS_ACCOUNT}; +enum {CATEGORY_NAME, CATEGORY_BACKGROUND_COLOR, CATEGORY_FOREGROUND_COLOR, CATEGORY_FONT, CATEGORY_DELETE, NUMBER_COLS_CATEGORY}; + +PreferencesPanel::PreferencesPanel(KissCount* kiss, wxUI *parent) : KissPanel(kiss, parent), _sharedWith(0), _curAccountRow(-1), _defaultSignalMapper(this), _virtualSignalMapper(this), _blockedSignalMapper(this), _deleteAccountSignalMapper(this), _deleteCategorySignalMapper(this), _backgroundColorSignalMapper(this), _foregroundColorSignalMapper(this), _fontSignalMapper(this), _inModification(false) +{ + QVBoxLayout *vbox = new QVBoxLayout; + QHBoxLayout *hbox1 = new QHBoxLayout; + QHBoxLayout *hbox2 = new QHBoxLayout; + //QHBoxLayout *hbox = new QHBoxLayout; + QGroupBox* staticUser, *staticAccount, *staticCategories, *staticLanguage, *staticOperationOrder, *staticSharedWith; + User* user = _kiss->GetUser(); + QGridLayout *gridBagSizer; + QLabel* label; + QPushButton* buttonChangeName, *buttonChangePassword, *killMe; + QVBoxLayout * staticBoxSizer; + std::list users; + std::list::iterator it; + + setLayout(vbox); + + staticUser = new QGroupBox(_("User")); + staticAccount = new QGroupBox(_("Accounts")); + staticCategories = new QGroupBox(_("Categories")); + staticLanguage = new QGroupBox(_("Language")); + staticOperationOrder = new QGroupBox(_("Operation order")); + staticSharedWith = new QGroupBox(_("Shared with")); + + // User + staticBoxSizer = new QVBoxLayout (); + staticUser->setLayout(staticBoxSizer); + + gridBagSizer = new QGridLayout(); + + label = new QLabel(_("Name")); + gridBagSizer->addWidget(label, 0, 0); + + _name = new QLineEdit(user->_name); + gridBagSizer->addWidget(_name, 0, 1); + + buttonChangeName = new QPushButton(_("Change Name")); + buttonChangePassword = new QPushButton(_("Change Password")); + killMe = new QPushButton(_("Kill me")); + + gridBagSizer->addWidget(buttonChangeName, 1, 0); + gridBagSizer->addWidget(buttonChangePassword, 1, 1); + gridBagSizer->addWidget(killMe, 1, 2); + + staticBoxSizer->addLayout(gridBagSizer); + + vbox->addWidget(staticUser); + + connect(buttonChangeName, SIGNAL(clicked()), this, SLOT(OnChangeName())); + connect(buttonChangePassword, SIGNAL(clicked()), this, SLOT(OnChangePassword())); + connect(killMe, SIGNAL(clicked()), this, SLOT(OnKillMe())); + + // Account + staticBoxSizer = new QVBoxLayout (); + staticAccount->setLayout(staticBoxSizer); + + _accountsGrid = new QTableWidget(); + + StarDelegate* starDelegate = new StarDelegate(this, &user->_accounts); + _accountsGrid->setItemDelegateForColumn(ACCOUNT_NUMBER, starDelegate); + + InitAccounts(user); + + connect(_accountsGrid, SIGNAL(cellChanged(int, int)), this, SLOT(OnAccountModified(int, int))); + connect(_accountsGrid, SIGNAL(currentCellChanged(int, int, int, int)), this, SLOT(OnAccountCellChanged(int, int, int, int))); + + staticBoxSizer->addWidget(_accountsGrid); + + hbox1->addWidget(staticAccount); + + staticBoxSizer = new QVBoxLayout (); + staticSharedWith->setLayout(staticBoxSizer); + + _sharedWith = new QListWidget(); + + users = _kiss->GetUsers(); + + QListWidgetItem* item; + for(it=users.begin(); it!=users.end(); it++) + { + if (*it != user->_name) + { + item = new QListWidgetItem(*it); + item->setCheckState(Qt::Unchecked); + _sharedWith->addItem(item); + } + } + + _sharedWith->setEnabled(false); + + connect(_sharedWith, SIGNAL(itemChanged(QListWidgetItem *)), this, SLOT(OnSharedChange(QListWidgetItem *))); + + staticBoxSizer->addWidget(_sharedWith); + + hbox1->addWidget(staticSharedWith); + vbox->addLayout(hbox1); + + // Categories + staticBoxSizer = new QVBoxLayout (); + staticCategories->setLayout(staticBoxSizer); + + _categoriesGrid = new QTableWidget(); + + staticBoxSizer->addWidget(_categoriesGrid); + + InitCategories(user); + + vbox->addWidget(staticCategories); + + // Operation Order + staticBoxSizer = new QVBoxLayout (); + staticOperationOrder->setLayout(staticBoxSizer); + + _operationOrder = new QComboBox(); + //_operationOrder->SetWindowStyle(wxCB_READONLY); + + InitOperationOrder(user); + + staticBoxSizer->addWidget(_operationOrder); + + hbox2->addWidget(staticOperationOrder); + + connect(_operationOrder, SIGNAL(currentIndexChanged(int)), this, SLOT(OnOperationOrderChange(int))); + + // Language + staticBoxSizer = new QVBoxLayout (); + staticLanguage->setLayout(staticBoxSizer); + + _language = new QListWidget(); + //_language->SetWindowStyle(wxCB_READONLY); + + InitLanguage(user); + + staticBoxSizer->addWidget(_language); + + hbox2->addWidget(staticLanguage); + + vbox->addLayout(hbox2); + + connect(&_defaultSignalMapper, SIGNAL(mapped(int)), this, SLOT(OnAccountDefaultClicked(int))); + connect(&_virtualSignalMapper, SIGNAL(mapped(int)), this, SLOT(OnAccountVirtualClicked(int))); + connect(&_blockedSignalMapper, SIGNAL(mapped(int)), this, SLOT(OnAccountBlockedClicked(int))); + connect(&_deleteAccountSignalMapper, SIGNAL(mapped(int)), this, SLOT(OnAccountDeleteClicked(int))); + + connect(&_deleteCategorySignalMapper, SIGNAL(mapped(int)), this, SLOT(OnCategoryDeleteClicked(int))); + connect(&_backgroundColorSignalMapper, SIGNAL(mapped(int)), this, SLOT(OnBackgroundColorClicked(int))); + connect(&_foregroundColorSignalMapper, SIGNAL(mapped(int)), this, SLOT(OnForegroundClicked(int))); + connect(&_fontSignalMapper, SIGNAL(mapped(int)), this, SLOT(OnFontClicked(int))); + + layout(); +} + +KissPanel* PreferencesPanel::CreatePanel() +{ + return new PreferencesPanel(_kiss, _wxUI); +} + +QPushButton* PreferencesPanel::GetButton() +{ + if (!_KissButton) + { + _KissButton = new QPushButton(QIcon(PREFS_ICON), "", this); + _KissButton->setFixedSize(128, 128); + _KissButton->setIconSize(QSize(128, 128)); + } + + return _KissButton; +} + +QString PreferencesPanel::GetToolTip() +{ + return _("Preferences"); +} + +void PreferencesPanel::InitAccounts(User* user) +{ + std::vector::iterator it; + int curLine = 0; + Account account ; + DEFAULT_FONT(font); + + _accountsGrid->setColumnCount(NUMBER_COLS_ACCOUNT); + _accountsGrid->verticalHeader()->setHidden(true); + _accountsGrid->setFont(font); + + _accountsGrid->setHorizontalHeaderItem(ACCOUNT_NAME, new QTableWidgetItem(_("Name"))); + _accountsGrid->setHorizontalHeaderItem(ACCOUNT_NUMBER, new QTableWidgetItem(_("Number"))); + _accountsGrid->setHorizontalHeaderItem(ACCOUNT_DEFAULT, new QTableWidgetItem(_("Default"))); + _accountsGrid->setHorizontalHeaderItem(ACCOUNT_VIRTUAL, new QTableWidgetItem(_("Virtual"))); + _accountsGrid->setHorizontalHeaderItem(ACCOUNT_BLOCKED, new QTableWidgetItem(_("Blocked"))); + _accountsGrid->setHorizontalHeaderItem(ACCOUNT_DELETE, new QTableWidgetItem(_("Delete"))); + + font.setBold(true); + for(int i=0; ihorizontalHeaderItem(i)->setFont(font); + } + + _accountsGrid->setRowCount(user->GetAccountsNumber()+1); + + for (it = user->_accounts.begin(); it != user->_accounts.end(); it++, curLine++) + { + AddAccount(curLine, *it); + } + + account.id = 0; + AddAccount(curLine, account); +} + +#define SET_READ_ONLY(row, line) _accountsGrid->item(row, line)->setFlags(_accountsGrid->item(row, line)->flags() & ~Qt::ItemIsEditable); + +void PreferencesPanel::AddAccount(int line, Account ac) +{ + QCheckBox* checkBox; + + if (ac.id != 0) + { + _accountsGrid->setItem(line, ACCOUNT_NAME, new QTableWidgetItem(ac.name)); + if (ac.shared) + _accountsGrid->setItem(line, ACCOUNT_NUMBER, new QTableWidgetItem(ac.number + "*")); + else + _accountsGrid->setItem(line, ACCOUNT_NUMBER, new QTableWidgetItem(ac.number)); + + checkBox = new QCheckBox(); + checkBox->setCheckState((ac._default) ? Qt::Checked : Qt::Unchecked); + _accountsGrid->setCellWidget(line, ACCOUNT_DEFAULT, checkBox); + _defaultSignalMapper.setMapping(checkBox, ac.id); + connect(checkBox, SIGNAL(stateChanged(int)), &_defaultSignalMapper, SLOT(map())); + + checkBox = new QCheckBox(); + checkBox->setCheckState((ac._virtual) ? Qt::Checked : Qt::Unchecked); + _accountsGrid->setCellWidget(line, ACCOUNT_VIRTUAL, checkBox); + _virtualSignalMapper.setMapping(checkBox, ac.id); + connect(checkBox, SIGNAL(stateChanged(int)), &_virtualSignalMapper, SLOT(map())); + + checkBox = new QCheckBox(); + checkBox->setCheckState((ac.blocked) ? Qt::Checked : Qt::Unchecked); + _accountsGrid->setCellWidget(line, ACCOUNT_BLOCKED, checkBox); + _blockedSignalMapper.setMapping(checkBox, ac.id); + connect(checkBox, SIGNAL(stateChanged(int)), &_blockedSignalMapper, SLOT(map())); + + checkBox = new QCheckBox(); + checkBox->setCheckState(Qt::Unchecked); + _accountsGrid->setCellWidget(line, ACCOUNT_DELETE, checkBox); + _deleteAccountSignalMapper.setMapping(checkBox, ac.id); + connect(checkBox, SIGNAL(stateChanged(int)), &_deleteAccountSignalMapper, SLOT(map())); + + for(int i=0; iitem(line, i)) + _accountsGrid->setItem(line, i, new QTableWidgetItem("")); + // _accountsGrid->SetCellAlignment(line, ACCOUNT_DEFAULT, wxALIGN_CENTRE, wxALIGN_CENTRE); + // _accountsGrid->SetCellAlignment(line, ACCOUNT_VIRTUAL, wxALIGN_CENTRE, wxALIGN_CENTRE); + // _accountsGrid->SetCellAlignment(line, ACCOUNT_BLOCKED, wxALIGN_CENTRE, wxALIGN_CENTRE); + // _accountsGrid->SetCellAlignment(line, ACCOUNT_DELETE, wxALIGN_CENTRE, wxALIGN_CENTRE); + + if (!ac.is_owner) + { + SET_READ_ONLY(line, ACCOUNT_NAME); + SET_READ_ONLY(line, ACCOUNT_NUMBER); + SET_READ_ONLY(line, ACCOUNT_DEFAULT); + SET_READ_ONLY(line, ACCOUNT_VIRTUAL); + SET_READ_ONLY(line, ACCOUNT_BLOCKED); + } + else + { + SET_READ_ONLY(line, ACCOUNT_DEFAULT); + SET_READ_ONLY(line, ACCOUNT_VIRTUAL); + SET_READ_ONLY(line, ACCOUNT_BLOCKED); + SET_READ_ONLY(line, ACCOUNT_DELETE); + } + } + else + { + for(int i=0; iitem(line, i)) + _accountsGrid->setItem(line, i, new QTableWidgetItem("")); + + SET_READ_ONLY(line, ACCOUNT_DEFAULT); + SET_READ_ONLY(line, ACCOUNT_VIRTUAL); + SET_READ_ONLY(line, ACCOUNT_BLOCKED); + SET_READ_ONLY(line, ACCOUNT_DELETE); + } + _accountsGrid->resizeColumnsToContents(); +} + +#undef SET_READ_ONLY +#define SET_READ_ONLY(row, line) _categoriesGrid->item(row, line)->setFlags(_categoriesGrid->item(row, line)->flags() & ~Qt::ItemIsEditable); + +#define SET_ROW_COLOR(row, backcolor, forecolor) \ + for(int i=0; iitem(row, i)->setBackground(QBrush(backcolor)); \ + _categoriesGrid->item(row, i)->setForeground(QBrush(forecolor)); \ + } + +#define SET_ROW_FONT(row, font) \ + for(int i=0; iitem(row, i)->setFont(font); \ + } + +void PreferencesPanel::InitCategories(User* user) +{ + std::vector::iterator it; + int curLine = 0; + DEFAULT_FONT(font); + Category cat; + + _categoriesGrid->setColumnCount(NUMBER_COLS_CATEGORY); + _categoriesGrid->verticalHeader()->setHidden(true); + _categoriesGrid->setFont(font); + + _categoriesGrid->setHorizontalHeaderItem(CATEGORY_NAME, new QTableWidgetItem(_("Name"))); + _categoriesGrid->setHorizontalHeaderItem(CATEGORY_BACKGROUND_COLOR, new QTableWidgetItem(_("Background color"))); + _categoriesGrid->setHorizontalHeaderItem(CATEGORY_FOREGROUND_COLOR, new QTableWidgetItem(_("Foreground color"))); + _categoriesGrid->setHorizontalHeaderItem(CATEGORY_FONT, new QTableWidgetItem(_("Font"))); + _categoriesGrid->setHorizontalHeaderItem(CATEGORY_DELETE, new QTableWidgetItem(_("Delete"))); + + _categoriesGrid->setRowCount(user->GetCategoriesNumber()+1); + + font.setBold(true); + for(int i=0; ihorizontalHeaderItem(i)->setFont(font); + } + + for (it=user->_categories.begin(); it!=user->_categories.end(); it++, curLine++) + { + AddCategory(curLine, *it); + } + + for(int i=0; iitem(curLine, i)) + _categoriesGrid->setItem(curLine, i, new QTableWidgetItem("")); + + SET_READ_ONLY(curLine, CATEGORY_NAME); + SET_READ_ONLY(curLine, CATEGORY_DELETE); + + cat.id = 0; + AddCategory(curLine, cat); +} + +void PreferencesPanel::AddCategory(int line, Category cat) +{ + User* user = _kiss->GetUser(); + QCheckBox* checkBox; + QPushButton* button; + + if (cat.id != 0) + { + _categoriesGrid->setItem(line, CATEGORY_NAME, new QTableWidgetItem(_(cat.name.toStdString().c_str()))); + + if (line) + { + checkBox = new QCheckBox(); + checkBox->setCheckState(Qt::Unchecked); + _categoriesGrid->setCellWidget(line, CATEGORY_DELETE, checkBox); + _deleteCategorySignalMapper.setMapping(checkBox, cat.id); + connect(checkBox, SIGNAL(stateChanged(int)), &_deleteCategorySignalMapper, SLOT(map())); + } + + button = new QPushButton("..."); + _categoriesGrid->setCellWidget(line, CATEGORY_BACKGROUND_COLOR, button); + _backgroundColorSignalMapper.setMapping(button, cat.id); + connect(button, SIGNAL(clicked()), &_backgroundColorSignalMapper, SLOT(map())); + + button = new QPushButton("..."); + _categoriesGrid->setCellWidget(line, CATEGORY_FOREGROUND_COLOR, button); + _foregroundColorSignalMapper.setMapping(button, cat.id); + connect(button, SIGNAL(clicked()), &_foregroundColorSignalMapper, SLOT(map())); + + button = new QPushButton("..."); + _categoriesGrid->setCellWidget(line, CATEGORY_FONT, button); + _fontSignalMapper.setMapping(button, cat.id); + connect(button, SIGNAL(clicked()), &_fontSignalMapper, SLOT(map())); + + for(int i=0; iitem(line, i) == NULL) + _categoriesGrid->setItem(line, i, new QTableWidgetItem("")); + + SET_ROW_COLOR(line, cat.backcolor, cat.forecolor); + if (cat.font.size()) + { + QFont font = user->GetCategoryFont(cat.id); + SET_ROW_FONT(line, font); + } + + // _categoriesGrid->SetCellAlignment(line, CATEGORY_DELETE, wxALIGN_CENTRE, wxALIGN_CENTRE); + } + else + { + for(int i=0; iitem(line, i)) + _categoriesGrid->setItem(line, i, new QTableWidgetItem("")); + + SET_READ_ONLY(line, CATEGORY_BACKGROUND_COLOR); + SET_READ_ONLY(line, CATEGORY_FOREGROUND_COLOR); + SET_READ_ONLY(line, CATEGORY_FONT); + SET_READ_ONLY(line, CATEGORY_DELETE); + SET_ROW_COLOR(line, view::OWN_GREEN, Qt::black); + + _categoriesGrid->resizeColumnsToContents(); + } +} + +void PreferencesPanel::InitLanguage(User* user) +{ + int i, select=0; + + for (i=0; iaddItem(SupportedLanguages::languages[i].name); + //_language->setItemWidget(new QListWidgetItem(SupportedLanguages::languages[i].name), QIcon(SupportedLanguages::languages[i].icon)); + + if (SupportedLanguages::languages[i].language == _wxUI->_language) + select = i; + } + + _language->setCurrentItem(_language->item(select)); +} + +void PreferencesPanel::InitOperationOrder(User* user) +{ + _operationOrder->addItem(_("Ascending")); + _operationOrder->addItem(_("Descending")); + + if (user->_preferences["operation_order"] == "ASC") + _operationOrder->setCurrentIndex(0); + else + _operationOrder->setCurrentIndex(1); +} + +void PreferencesPanel::OnAccountDefaultClicked(int id) +{ + User* user = _kiss->GetUser(); + QCheckBox* checkBox = qobject_cast (_defaultSignalMapper.mapping(id)); + std::vector::iterator it; + int i, row; + Account account; + + if (_inModification) return; + + it = std::find(user->_accounts.begin(), user->_accounts.end(), id); + + if (it == user->_accounts.end()) return ; + + row = it-user->_accounts.begin(); + account = user->_accounts[row]; + + _inModification = true; + + if (account._default) + { + checkBox->setCheckState(Qt::Checked); + _inModification = false; + return; + } + + account._default = true; + _kiss->UpdateAccount(account); + + for (i=0; iGetAccountsNumber(); i++) + { + if (i != row) + { + account = user->_accounts[i]; + if (account._default) + { + account._default = false; + _kiss->UpdateAccount(account); + checkBox = qobject_cast(_accountsGrid->cellWidget(i, ACCOUNT_DEFAULT)); + checkBox->setCheckState(Qt::Unchecked); + break; + } + } + } + + account = user->_accounts[row]; + _inModification = false; +} + +void PreferencesPanel::OnAccountVirtualClicked(int id) +{ + User* user = _kiss->GetUser(); + QCheckBox* checkBox = qobject_cast (_virtualSignalMapper.mapping(id)); + std::vector::iterator it; + Account account; + int row; + + it = std::find(user->_accounts.begin(), user->_accounts.end(), id); + + if (it == user->_accounts.end()) return ; + + row = it-user->_accounts.begin(); + account = user->_accounts[row]; + + account._virtual = (checkBox->checkState() == Qt::Checked); + _kiss->UpdateAccount(account); +} + +void PreferencesPanel::OnAccountBlockedClicked(int id) +{ + User* user = _kiss->GetUser(); + QCheckBox* checkBox = qobject_cast (_blockedSignalMapper.mapping(id)); + std::vector::iterator it; + Account account; + int row; + + it = std::find(user->_accounts.begin(), user->_accounts.end(), id); + + if (it == user->_accounts.end()) return ; + + row = it-user->_accounts.begin(); + account = user->_accounts[row]; + + account.blocked = (checkBox->checkState() == Qt::Checked); + _kiss->UpdateAccount(account); +} + +void PreferencesPanel::OnAccountDeleteClicked(int id) +{ + User* user = _kiss->GetUser(); + std::vector::iterator it; + int i, row; + QStringList accounts; + QString res; + QCheckBox* checkBox = qobject_cast (_deleteAccountSignalMapper.mapping(id)); + Account account; + bool ok; + + if (user->GetAccountsNumber() == 1) + { + QMessageBox::critical(0, _("Error"), _("It must be at least one account !")); + checkBox->setCheckState(Qt::Unchecked); + return; + } + + it = std::find(user->_accounts.begin(), user->_accounts.end(), id); + + if (it == user->_accounts.end()) return ; + + if (_inModification) return; + + _inModification = true; + + row = it-user->_accounts.begin(); + account = user->_accounts[row]; + + accounts << _("None"); + for(i=0; i < user->GetAccountsNumber(); i++) + if (user->_accounts[i].id != id) + accounts << user->_accounts[i].name; + + res = QInputDialog::getItem(this, "KissCount", _("Wich account will replace this one ?"), accounts, 0, false, &ok); + + if (!ok) + { + checkBox->setCheckState(Qt::Unchecked); + _inModification = false; + return; + } + else + { + i = accounts.indexOf(res); + _kiss->DeleteAccount(account, (!i) ? 0 : user->GetAccountId(accounts[i])); + _accountsGrid->removeRow(row); + } + + if (user->_accounts.size() == 1) + { + user->_accounts[0]._default = true; + _kiss->UpdateAccount(user->_accounts[0]); + checkBox = qobject_cast (_defaultSignalMapper.mapping(id)); + checkBox->setCheckState(Qt::Checked); + } + + _inModification = false; + _wxUI->NeedReload(); +} + +void PreferencesPanel::OnCategoryDeleteClicked(int id) +{} + +void PreferencesPanel::OnBackgroundColorClicked(int id) +{} + +void PreferencesPanel::OnForegroundClicked(int id) +{} + +void PreferencesPanel::OnFontClicked(int id) +{} + +void PreferencesPanel::OnAccountModified(int row, int col) +{ + int op_complete = 1, new_id; + QString value ; + Account new_account, account; + User* user = _kiss->GetUser(); + + if (_inModification) return; + + _inModification = true; + + value = _accountsGrid->item(row, ACCOUNT_NAME)->text(); + if (value.size()) + { + new_account.name = value; + op_complete--; + } + + value = _accountsGrid->item(row, ACCOUNT_NUMBER)->text(); + if (value.size()) + { + new_account.number = value; + op_complete--; + } + + // Account modification + if (user->GetAccountsNumber() && row < user->GetAccountsNumber()) + { + new_account.id = user->_accounts[row].id; + new_account.shared = user->_accounts[row].shared; + new_account.is_owner = user->_accounts[row].is_owner; + + if (col == ACCOUNT_NAME) + { + new_id = user->GetAccountId(new_account.name); + if (new_id != 0 && new_id != new_account.id) + { + QMessageBox::critical(0, _("Error"), _("Account ")+new_account.name+_(" already exists")); + _accountsGrid->setItem(row, ACCOUNT_NAME, new QTableWidgetItem(user->_accounts[row].name)); + _inModification = false; + return ; + } + } + + _kiss->UpdateAccount(new_account); + } + // New account + else + { + if (op_complete) + { + _inModification = false; + return ; + } + + if (user->GetAccountId(new_account.name) != 0) + { + QMessageBox::critical(0, _("Error"), _("Account ")+new_account.name+_(" already exists")); + _inModification = false; + return ; + } + + new_account._default = false; + new_account.shared = false; + new_account.blocked = false; + new_account.is_owner = true; + new_account._virtual = false; + + AddAccount(row, new_account); + _kiss->AddAccount(new_account); + + new_account.id = 0; + + _accountsGrid->setRowCount(row+2); + AddAccount(row+1, new_account); + } + + _accountsGrid->resizeColumnsToContents(); + + _wxUI->NeedReload(); + _inModification = false; +} + +void PreferencesPanel::OnAccountCellChanged(int row, int col, int previousRow, int previousCol) +{ + User* user = _kiss->GetUser(); + std::map::iterator it; + int i; + bool own; + QString owner; + QListWidgetItem* item; + + if (!_sharedWith || _curAccountRow == row) + return ; + + _curAccountRow = row ; + + if (row >= (int) user->_accounts.size()) + { + for(i=0; i<(int)_sharedWith->count(); i++) + _sharedWith->item(i)->setCheckState(Qt::Unchecked); + own = false; + } + else + { + _sharedOwners = _kiss->getSharedAccountOwners(user->_accounts[row].id); + owner = _kiss->getSharedAccountOwner(user->_accounts[row].id); + for(i=0; i<(int)_sharedWith->count(); i++) + { + item = _sharedWith->item(i); + item->setCheckState((_sharedOwners[item->text()].size() > 0 || + item->text() == owner) ? Qt::Checked : Qt::Unchecked); + } + own = user->_accounts[row].is_owner; + } + + _sharedWith->setEnabled(own); +} + +void PreferencesPanel::OnSharedChange(QListWidgetItem *item) +{ + User* user = _kiss->GetUser(); + + if (_inModification) return; + + _inModification = true; + + if (item->checkState() == Qt::Checked) + { + if (!user->_accounts[_curAccountRow].shared) + _accountsGrid->setItem(_curAccountRow, ACCOUNT_NUMBER, + new QTableWidgetItem(user->_accounts[_curAccountRow].number + "*")); + + _kiss->AddSharedAccount(user->_accounts[_curAccountRow], item->text()); + } + else + { + _kiss->RemoveSharedAccount(user->_accounts[_curAccountRow], _sharedOwners[item->text()].toInt()); + + if (!user->_accounts[_curAccountRow].shared) + _accountsGrid->setItem(_curAccountRow, ACCOUNT_NUMBER, new QTableWidgetItem(user->_accounts[_curAccountRow].number)); + } + + _inModification = false; + + _wxUI->NeedReload(); +} + +void PreferencesPanel::OnCategoryModified() +{ + // int op_complete = 1; + // wxString value; + // User* user = _kiss->GetUser(); + // int row = event.GetRow(); + // int col = event.GetCol(); + // static bool _inModification = false ; + // Category new_cat, cat_tmp; + // int i, a; + + // if (_inModification) return; + + // _inModification = true; + + // if (event.GetCol() == CATEGORY_BACKGROUND_COLOR) + // { + // wxColourData color; + // color.SetColour(wxColor(user->_categories[row].backcolor)); + // wxColourDialog dial(this, &color); + + // if (dial.ShowModal() == wxID_OK) + // { + // user->_categories[row].backcolor = dial.GetColourData().GetColour(); + // _kiss->UpdateCategory(user->_categories[row]); + + // SET_ROW_COLOR(row, user->_categories[row].backcolor, user->_categories[row].forecolor); + // _wxUI->NeedReload(); + // } + + // _inModification = false ; + // return ; + // } + + // if (event.GetCol() == CATEGORY_FOREGROUND_COLOR) + // { + // wxColourData color; + // color.SetColour(wxColor(user->_categories[row].forecolor)); + // wxColourDialog dial(this, &color); + + // if (dial.ShowModal() == wxID_OK) + // { + // user->_categories[row].forecolor = dial.GetColourData().GetColour(); + // _kiss->UpdateCategory(user->_categories[row]); + + // SET_ROW_COLOR(row, user->_categories[row].backcolor, user->_categories[row].forecolor); + // _wxUI->NeedReload(); + // } + + // _inModification = false ; + // return ; + // } + + // if (event.GetCol() == CATEGORY_FONT) + // { + // wxFontData font; + // font.SetInitialFont(_kiss->ExtractFont(user->_categories[row].font)); + // wxFontDialog dial(this, font); + + // if (dial.ShowModal() == wxID_OK) + // { + // font = dial.GetFontData(); + + // user->_categories[row].font = _kiss->CompactFont(font.GetChosenFont()); + // _kiss->UpdateCategory(user->_categories[row]); + + // SET_ROW_FONT(row, font.GetChosenFont()); + // _wxUI->NeedReload(); + // } + + // _inModification = false ; + // return ; + // } + + // value = _categoriesGrid->GetCellValue(row, CATEGORY_NAME); + // if (value.Length()) + // { + // new_cat.name = value; + // op_complete--; + // } + + // new_cat.backcolor = _categoriesGrid->GetCellBackgroundColour(row, col); + // new_cat.forecolor = _categoriesGrid->GetCellTextColour(row, col); + // new_cat.font = wxT(""); + // new_cat.parent = wxT("0"); + + // // Categories modification + // if (user->GetCategoriesNumber() && row < user->GetCategoriesNumber()) + // { + // new_cat.id = user->_categories[row].id; + // new_cat.fix_cost = user->_categories[row].fix_cost; + // if (col == CATEGORY_DELETE) + // { + // wxString *categories = new wxString[user->GetCategoriesNumber()]; + // categories[0] = _("None"); + // a = 0; + // for(i=0; i < user->GetCategoriesNumber(); i++) + // if (user->_categories[i].id != new_cat.id) + // categories[++a] = wxGetTranslation(user->_categories[i].name); + // wxSingleChoiceDialog dialog(_wxUI, _("Wich category will replace this one ?"), wxT("KissCount"), user->GetCategoriesNumber(), categories); + // if (dialog.ShowModal() == wxID_CANCEL) + // { + // _categoriesGrid->setItem(row, col, wxT("0")); + // } + // else + // { + // _categoriesGrid->DeleteRows(row, 1); + // i = dialog.GetSelection(); + // _kiss->DeleteCategory(user->_categories[row], (!i) ? wxT("0") : user->GetCategoryId(categories[i])); + // Fit(); + // _wxUI->NeedReload(); + // } + // _inModification = false; + // return; + // } + + // value = user->GetCategoryId(new_cat.name); + // if (value != wxT("0") && value != new_cat.id) + // { + // wxMessageBox(_("Category ")+new_cat.name+_(" already exists"), _("Error"), wxICON_ERROR | wxOK ); + // _categoriesGrid->setItem(row, CATEGORY_NAME, user->_categories[row].name); + // _inModification = false; + // return ; + // } + + // _kiss->UpdateCategory(new_cat); + // } + // // New category + // else + // { + // if (op_complete) + // { + // _inModification = false; + // return ; + // } + + // if (user->GetCategoryId(new_cat.name) != wxT("0")) + // { + // wxMessageBox(_("Category ")+new_cat.name+_(" already exists"), _("Error"), wxICON_ERROR | wxOK ); + // _inModification = false; + // return ; + // } + + // new_cat.fix_cost = false; + + // _kiss->AddCategory(new_cat); + // AddCategory(row, new_cat); + + // _categoriesGrid->SetReadOnly(row, CATEGORY_BACKGROUND_COLOR, false); + // _categoriesGrid->SetReadOnly(row, CATEGORY_FOREGROUND_COLOR, false); + // _categoriesGrid->SetReadOnly(row, CATEGORY_FONT, false); + // _categoriesGrid->SetReadOnly(row, CATEGORY_DELETE, false); + + // new_cat.id = wxT("0"); + // _categoriesGrid->AppendRows(); + // AddCategory(++row, new_cat); + // } + + // Fit(); + // _wxUI->NeedReload(); + + // _inModification = false; + + // return; +} + +void PreferencesPanel::OnChangeName() +{ + User* user = _kiss->GetUser(); + QString name = _name->text(); + + if (name == user->_name) + return; + + if (!name.size()) + { + QMessageBox::critical(0, _("Error"), _("Invalid name !")); + return; + } + + if (_kiss->UserExists(name)) + { + QMessageBox::critical(0, _("Error"), _("User ") + name + _(" already exists")); + return; + } + + _kiss->ChangeName(name); + + QMessageBox::information(0, "KissCount", _("Name changed")); + _wxUI->NeedReload(); + OnShow(); +} + +void PreferencesPanel::OnChangePassword() +{ + // PasswordDialog p(_kiss, _wxUI); + // p.ShowModal(); +} + +void PreferencesPanel::OnOperationOrderChange(int index) +{ + if (index == 0) + _kiss->SetOperationOrder("ASC"); + else + _kiss->SetOperationOrder("DESC"); + + _wxUI->NeedReload(); +} + +void PreferencesPanel::OnLanguageChange() +{ + SupportedLanguages::wxLanguage language = SupportedLanguages::languages[_language->currentRow()].language; + QString name_lang = SupportedLanguages::languages[_language->currentRow()].name; + + if (_wxUI->SetLanguage(name_lang) || language == SupportedLanguages::wxLANGUAGE_ENGLISH) + { + _wxUI->NeedReload(); + _kiss->SetLanguage(name_lang); + QMessageBox::information(0, "KissCount", _("Language successfully changed, please go to another panel")); + } + else + QMessageBox::critical(0, _("Error"), _("Language not changed")); +} + +void PreferencesPanel::OnShow() +{ + _wxUI->setWindowTitle(_kiss->GetUser()->_name + " - " + _("Preferences")); +} + +void PreferencesPanel::OnKillMe() +{ + User* user = _kiss->GetUser(); + + if (QMessageBox::question(0, "KissCount", _("Are you sure want to delete ")+user->_name+_(" profil ?"), QMessageBox::Yes|QMessageBox::No) == QMessageBox::No) + { + return; + } + + _kiss->KillMe(); +} diff --git a/src/view/PreferencesPanel.hpp b/src/view/PreferencesPanel.hpp new file mode 100644 index 0000000..31b6ce6 --- /dev/null +++ b/src/view/PreferencesPanel.hpp @@ -0,0 +1,82 @@ +/* + 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 PREFERENCESPANEL_H +#define PREFERENCESPANEL_H + +#include + +#include "SupportedLanguages.hpp" +#include "view.hpp" +#include + +class PreferencesPanel: public KissPanel +{ + Q_OBJECT; + +public: + PreferencesPanel(KissCount* kiss, wxUI *parent); + + KissPanel* CreatePanel(); + QPushButton* GetButton(); + QString GetToolTip(); + void OnShow(); + + void ChangeUser(); + +private slots: + void OnAccountDefaultClicked(int id); + void OnAccountVirtualClicked(int id); + void OnAccountBlockedClicked(int id); + void OnAccountDeleteClicked(int id); + void OnCategoryDeleteClicked(int id); + void OnBackgroundColorClicked(int id); + void OnForegroundClicked(int id); + void OnFontClicked(int id); + void OnAccountModified(int row, int col); + void OnAccountCellChanged(int row, int col, int, int); + void OnSharedChange(QListWidgetItem *item); + void OnCategoryModified(); + void OnChangeName(); + void OnChangePassword(); + void OnOperationOrderChange(int index); + void OnLanguageChange(); + void OnKillMe(); + +private: + QTableWidget* _accountsGrid; + QTableWidget* _categoriesGrid; + QLineEdit* _name; + QListWidget* _language; + QComboBox* _operationOrder; + QListWidget* _sharedWith; + int _curAccountRow; + std::map _sharedOwners; + QSignalMapper _defaultSignalMapper, _virtualSignalMapper, _blockedSignalMapper, _deleteAccountSignalMapper, _deleteCategorySignalMapper, _backgroundColorSignalMapper, _foregroundColorSignalMapper, _fontSignalMapper; + bool _inModification; + void InitAccounts(User* user); + void InitCategories(User* user); + void InitLanguage(User* user); + void InitOperationOrder(User* user); + + void AddAccount(int line, Account ac); + void AddCategory(int line, Category cat); +}; + +#endif diff --git a/src/view/SearchPanel.cpp b/src/view/SearchPanel.cpp index e0065ee..3143771 100644 --- a/src/view/SearchPanel.cpp +++ b/src/view/SearchPanel.cpp @@ -143,6 +143,7 @@ void SearchPanel::OnButtonChangeAccount() res = QInputDialog::getItem(this, "KissCount", _("Choose a new account"), accounts, 0, false); + if (!res.size()) return ; a = (res.length()) ? accounts.indexOf(res) : 0; account = (a) ? user->_accounts[a-1].id : 0; diff --git a/src/view/SupportedLanguages.hpp b/src/view/SupportedLanguages.hpp index d50cbd7..9ab3fe5 100644 --- a/src/view/SupportedLanguages.hpp +++ b/src/view/SupportedLanguages.hpp @@ -23,6 +23,8 @@ namespace SupportedLanguages { #define ICONS_PATH RESSOURCES_ROOT "icons/" + enum wxLanguage {wxLANGUAGE_ENGLISH, wxLANGUAGE_FRENCH} ; + typedef struct { QString name; QString icon; diff --git a/src/view/grid/GridAccount.cpp b/src/view/grid/GridAccount.cpp index 0eb2b2d..cf96330 100644 --- a/src/view/grid/GridAccount.cpp +++ b/src/view/grid/GridAccount.cpp @@ -359,13 +359,13 @@ void GridAccount::InsertOperation(User* user, Operation& op, int line, bool fix, setItem(line, CATEGORY, new QTableWidgetItem(_(cat.name.toStdString().c_str()))); checkBox = new QCheckBox(); - checkBox->setTristate(false); + checkBox->setCheckState(Qt::Unchecked); setCellWidget(line, OP_DELETE, checkBox); _deleteSignalMapper.setMapping(checkBox, op.id); connect(checkBox, SIGNAL(stateChanged(int)), &_deleteSignalMapper, SLOT(map())); checkBox = new QCheckBox(); - checkBox->setTristate(false); + checkBox->setCheckState((op.checked) ? Qt::Checked : Qt::Unchecked); setCellWidget(line, CHECKED, checkBox); _checkSignalMapper.setMapping(checkBox, op.id); connect(checkBox, SIGNAL(stateChanged(int)), &_checkSignalMapper, SLOT(map())); @@ -389,7 +389,6 @@ void GridAccount::InsertOperation(User* user, Operation& op, int line, bool fix, 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); diff --git a/src/view/grid/StarDelegate.cpp b/src/view/grid/StarDelegate.cpp new file mode 100644 index 0000000..f285421 --- /dev/null +++ b/src/view/grid/StarDelegate.cpp @@ -0,0 +1,52 @@ +/* + 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 "StarDelegate.hpp" + +QWidget * StarDelegate::createEditor (QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index ) const +{ + return new QLineEdit(parent); +} + +void StarDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, + const QModelIndex &index) const +{ + QLineEdit *line = qobject_cast(editor); + QString value = line->text().trimmed(); + + if ((*_accounts)[index.row()].shared) + model->setData(index, qVariantFromValue(value+ "*")); + else + model->setData(index, qVariantFromValue(value)); +} + +void StarDelegate::setEditorData(QWidget *editor, + const QModelIndex &index) const +{ + QLineEdit* line = qobject_cast(editor); + QString s = qVariantValue(index.data()); + + if (s.endsWith("*")) + line->setText(s.left(s.size()-1)); + else + line->setText(s); +} diff --git a/src/view/grid/StarDelegate.hpp b/src/view/grid/StarDelegate.hpp new file mode 100644 index 0000000..f9d61cb --- /dev/null +++ b/src/view/grid/StarDelegate.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 STARDELEGATE_H +#define STARDELEGATE_H + +#include "TableViewDelegate.hpp" +#include + +class StarDelegate : public TableViewDelegate +{ + Q_OBJECT; + +public: + StarDelegate(QWidget *parent = 0, std::vector* accounts=0) : TableViewDelegate(parent), _accounts(accounts) {} + + 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: + std::vector* _accounts; +}; + +#endif diff --git a/src/view/wxUI.cpp b/src/view/wxUI.cpp index 3d3c411..5b7c3af 100644 --- a/src/view/wxUI.cpp +++ b/src/view/wxUI.cpp @@ -21,8 +21,8 @@ #include "AccountPanel.hpp" #include "SearchPanel.hpp" -/*#include "PreferencesPanel.hpp" -#include "UsersDialog.hpp" +#include "PreferencesPanel.hpp" +/*#include "UsersDialog.hpp" #include "StatsPanel.hpp" #include "ImportPanel.hpp" #include "ExportPanel.hpp" @@ -166,7 +166,7 @@ void wxUI::InitPanels() ADD_PANEL(AccountPanel); // ADD_PANEL(StatsPanel, 1); ADD_PANEL(SearchPanel); - // ADD_PANEL(PreferencesPanel, 3); + ADD_PANEL(PreferencesPanel); // ADD_PANEL(ImportPanel, 4); // ADD_PANEL(ExportPanel, 5); }