From 14a74b84f8bf2bed4d77b333363a297962346395 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soutad=C3=A9?= Date: Wed, 14 Jul 2010 16:22:02 +0200 Subject: [PATCH] First version of SearchPanel (+ code migration for GridAccount) --- src/controller/KissCount.cpp | 8 ++ src/controller/KissCount.h | 4 + src/model/Database.cpp | 130 ++++++++++++++++++++++++ src/model/Database.h | 4 + src/view/GridAccount.cpp | 156 ++++++++++++++++++++++++++++ src/view/SearchPanel.cpp | 190 +++++++++++++++++++++++++++++++++++ src/view/SearchPanel.h | 63 ++++++++++++ src/view/view.h | 41 ++++++++ 8 files changed, 596 insertions(+) create mode 100644 src/view/GridAccount.cpp create mode 100644 src/view/SearchPanel.cpp create mode 100644 src/view/SearchPanel.h create mode 100644 src/view/view.h diff --git a/src/controller/KissCount.cpp b/src/controller/KissCount.cpp index 47e598a..d1a1715 100644 --- a/src/controller/KissCount.cpp +++ b/src/controller/KissCount.cpp @@ -285,3 +285,11 @@ void KissCount::SetLanguage(wxLanguage language) _db->SetLanguage(_user, language); _user->_preferences[wxT("language")] = wxString::Format(wxT("%d"), language) ; } + +std::vector* KissCount::Search(wxString* description, wxDateTime* dateFrom, wxDateTime* dateTo, + wxString* amountFrom, wxString* amountTo, + std::vector categories, std::vector accounts) +{ + + return _db->Search(_user, description, dateFrom, dateTo, amountFrom, amountTo, categories, accounts); +} diff --git a/src/controller/KissCount.h b/src/controller/KissCount.h index 87ee60d..282a720 100644 --- a/src/controller/KissCount.h +++ b/src/controller/KissCount.h @@ -66,6 +66,10 @@ class KissCount void KillMe(); void SetLanguage(wxLanguage language); + + std::vector* Search(wxString* description, wxDateTime* dateFrom, wxDateTime* dateTo, + wxString* amountFrom, wxString* amountTo, + std::vector categories, std::vector accounts); private: wxUI* _wxUI; Database* _db; diff --git a/src/model/Database.cpp b/src/model/Database.cpp index 9bc367c..f93a4dc 100644 --- a/src/model/Database.cpp +++ b/src/model/Database.cpp @@ -910,3 +910,133 @@ void Database::SetLanguage(User* user, wxLanguage language) return ; } } + +std::vector* Database::Search(User* user, wxString* description, wxDateTime* dateFrom, wxDateTime* dateTo, + wxString* amountFrom, wxString* amountTo, + std::vector categories, std::vector accounts) +{ + wxSQLite3ResultSet set; + wxString req; + bool firstCond = false; + std::vector::iterator it; + std::vector::iterator accountIt; + std::vector* res = new std::vector; + + req = wxT("SELECT * from operation WHERE "); + + if (description) + { + req += wxT("UPPER(description) LIKE '%") + description->MakeUpper() + wxT("%'"); + firstCond = true; + } + + if (dateFrom) + { + if (firstCond) req += wxT(" AND ") ; else firstCond = true; + req += wxT("("); + req += wxT(" year >= '") + wxString::Format(wxT("%d"), dateFrom->GetYear()) + wxT("'"); + req += wxT(" AND month >= '") + wxString::Format(wxT("%d"), dateFrom->GetMonth()) + wxT("'"); + // req += wxT(" AND day >= '") + wxString::Format(wxT("%d"), dateFrom->GetDay()) + wxT("'"); + req += wxT(")"); + } + + if (dateTo) + { + if (firstCond) req += wxT(" AND ") ; else firstCond = true; + req += wxT("("); + req += wxT(" year <= '") + wxString::Format(wxT("%d"), dateTo->GetYear()) + wxT("'"); + req += wxT(" AND month <= '") + wxString::Format(wxT("%d"), dateTo->GetMonth()) + wxT("'"); + // req += wxT(" AND day <= '") + wxString::Format(wxT("%d"), dateTo->GetDay()) + wxT("'"); + req += wxT(")"); + } + + if (amountFrom) + { + if (firstCond) req += wxT(" AND ") ; else firstCond = true; + req += wxT("amount >= '") + *amountFrom + wxT("'"); + } + + if (amountTo) + { + if (firstCond) req += wxT(" AND ") ; else firstCond = true; + req += wxT("amount <= '") + *amountTo + wxT("'"); + } + + if (categories.size()) + { + if (firstCond) req += wxT(" AND ") ; else firstCond = true; + req += wxT("category IN ('"); + it = categories.begin(); + req += *it; + it++; + + for (; it != categories.end(); it++) + req += wxT("', '") + *it ; + + req += wxT("')"); + } + + if (firstCond) req += wxT(" AND ") ; else firstCond = true; + + if (accounts.size()) + { + req += wxT("account IN ('"); + it = accounts.begin(); + req += *it; + it++; + + for (; it != categories.end(); it++) + req += wxT("', '") + *it ; + + req += wxT("')"); + } + else + { + req += wxT("account IN ('"); + accountIt = user->_accounts.begin(); + req += accountIt->id; + accountIt++; + for (;accountIt != user->_accounts.end(); accountIt++) + { + req += wxT("', '") + accountIt->id ; + } + req += wxT("')"); + } + + req += wxT(" ORDER BY year,month,day ASC"); + + // std::cout << req.mb_str() << "\n"; + + EXECUTE_SQL_QUERY(req, set, res); + + while (set.NextRow()) + { + Operation op; + op.id = set.GetAsString(wxT("id")); + op.account = set.GetAsString(wxT("account")); + op.day = set.GetInt(wxT("day")); + op.month = set.GetInt(wxT("month")); + op.year = set.GetInt(wxT("year")); + op.amount = set.GetDouble(wxT("amount")); + op.description = set.GetAsString(wxT("description")); + op.category = set.GetAsString(wxT("category")); + op.fix_cost = set.GetBool(wxT("fix_cost")); + op.checked = set.GetBool(wxT("checked")); + + if (dateFrom && + op.month == dateFrom->GetMonth() && + op.year == dateFrom->GetYear() && + op.day < dateFrom->GetDay()-1) + continue; + + if (dateTo && + op.month == dateTo->GetMonth() && + op.year == dateTo->GetYear() && + op.day > dateTo->GetDay()-1) + continue; + + res->push_back(op); + } + + return res; +} diff --git a/src/model/Database.h b/src/model/Database.h index 1fc473a..8a78259 100644 --- a/src/model/Database.h +++ b/src/model/Database.h @@ -68,6 +68,10 @@ class Database void SetLanguage(User* user, wxLanguage language); + std::vector* Search(User* user, wxString* description, wxDateTime* dateFrom, wxDateTime* dateTo, + wxString* amountFrom, wxString* amountTo, + std::vector categories, std::vector accounts); + void KillMe(User* user); private: wxSQLite3Database _db; diff --git a/src/view/GridAccount.cpp b/src/view/GridAccount.cpp new file mode 100644 index 0000000..64ebd99 --- /dev/null +++ b/src/view/GridAccount.cpp @@ -0,0 +1,156 @@ +#include "GridAccount.h" + +#define SET_ROW_COLOR(row, color) for(int i=0; iGetUser(); + std::vector::iterator accountIt; + std::vector::iterator categoryIt; + + CreateGrid(1, NUMBER_COLS_OPS); + SetColLabelSize(0); + SetRowLabelSize(0); + + SetColSize (0, GetColSize(0)*3); + SetDefaultCellFont(font); + + font.SetWeight(wxFONTWEIGHT_BOLD); + wxString colsName[] = {_("Description"), _("Date"), _("Debit"), _("Credit"), _("Category"), _("Account"), wxT(""), wxT("")}; + for(i=0; iGetAccountsNumber()]; + for (i=0, + accountIt = user->_accounts.begin(); + accountIt != user->_accounts.end(); + accountIt++, i++) + _accounts[i] = accountIt->name; + + _categories = new wxString[user->GetCategoriesNumber()] ; + for(i=0, categoryIt = user->_categories.begin(); + categoryIt != user->_categories.end(); + categoryIt++, i++) + { + _categories[i] = categoryIt->name ; + } + +} + +GridAccount::~GridAccount() +{ + delete[] _categories; + delete[] _accounts; +} + +wxPen GridAccount::GetColGridLinePen (int col) +{return wxPen(*wxBLACK, 1, wxSOLID);} + +wxPen GridAccount::GetRowGridLinePen (int row) { + if (row == 0 || row == _fixCosts || + row == _week1 || + row == _week2 || + row == _week3 || + row == _week4) + return wxPen(*wxBLACK, 1, wxSOLID); + + return GetCellBackgroundColour(row, 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; + } +} + +void GridAccount::InsertOperation(User* user, Operation* op, int line, bool fix, int curMonth, int curYear) +{ + std::vector::iterator it; + int r, g, b; + wxColour color; + + if (!op && !user->_accounts.size()) return; + + InsertRows(line, 1); + + SetCellEditor(line, DEBIT, new wxGridCellFloatEditor(-1, 2)); + SetCellEditor(line, CREDIT, new wxGridCellFloatEditor(-1, 2)); + wxGridCellChoiceEditor* accountEditor = new wxGridCellChoiceEditor(user->GetAccountsNumber(), _accounts, false); + SetCellEditor(line, ACCOUNT, accountEditor); + wxGridCellChoiceEditor* categoryEditor = new wxGridCellChoiceEditor(user->GetCategoriesNumber()-1, _categories+1, false); + SetCellEditor(line, CATEGORY, categoryEditor); + + if (fix) + { + SetCellValue(line, CATEGORY, _("Fix")); + SetReadOnly(line, CATEGORY); + } + + if (op) + { + SetCellEditor(line, DATE, new CalendarEditor(op->day, op->month, op->year)); + SetCellValue(line, DESCRIPTION, op->description); + SetCellValue(line, DATE, wxString::Format(wxT("%02d/%02d/%d"), op->day+1, op->month+1, op->year)); + if (op->amount < 0) + SetCellValue(line, DEBIT, wxString::Format(wxT("%.2lf"), -op->amount)); + else + SetCellValue(line, CREDIT, wxString::Format(wxT("%.2lf"), op->amount)); + SetCellValue(line, ACCOUNT, user->GetAccountName(op->account)); + if (!fix) + SetCellValue(line, CATEGORY, user->GetCategoryName(op->category)); + SetCellRenderer(line, DELETE, new wxGridCellBoolRenderer ()); + SetCellEditor(line, DELETE, new wxGridCellBoolEditor ()); + SetCellRenderer(line, CHECKED, new wxGridCellBoolRenderer ()); + SetCellEditor(line, CHECKED, new wxGridCellBoolEditor ()); + + color = user->GetCategory(op->category).color; + + 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.Set(r, g, b, color.Alpha()); + SetCellValue(line, CHECKED, wxT("1")); + } + + SET_ROW_COLOR(line, color); + } + else + { + SetCellEditor(line, DATE, new CalendarEditor(0, curMonth, curYear)); + if (fix) + SET_ROW_COLOR(line, OWN_YELLOW) + else + SET_ROW_COLOR(line, OWN_GREEN); + SetReadOnly(line, CHECKED, true); + SetReadOnly(line, DELETE, true); + } + + SetCellAlignment(line, DEBIT, wxALIGN_RIGHT, wxALIGN_CENTRE); + SetCellAlignment(line, CREDIT, wxALIGN_RIGHT, wxALIGN_CENTRE); + SetCellAlignment(line, DELETE, wxALIGN_CENTRE, wxALIGN_CENTRE); + SetCellAlignment(line, CHECKED, wxALIGN_CENTRE, wxALIGN_CENTRE); + + Layout(); + SetMinSize(GetMinSize()); +} diff --git a/src/view/SearchPanel.cpp b/src/view/SearchPanel.cpp new file mode 100644 index 0000000..63f8734 --- /dev/null +++ b/src/view/SearchPanel.cpp @@ -0,0 +1,190 @@ +/* +Copyright 2010 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 "AccountPanel.h" + +enum {SEARCH_ID, GRID_ID}; + +BEGIN_EVENT_TABLE(SearchPanel, wxPanel) +EVT_BUTTON(SEARCH_ID, SearchPanel::OnButtonSearch) +EVT_SHOW(SearchPanel::OnShow) +END_EVENT_TABLE() + +#define SET_ROW_COLOR(row, color) for(int i=0; iSetCellBackgroundColour(row, i, color); \ + } + +SearchPanel::SearchPanel(KissCount* kiss, wxUI *parent) : wxScrolledWindow(&(*parent)), _kiss(kiss), _wxUI(parent), _operations(NULL) +{ + wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL); + + DEFAULT_FONT(font); + User* user = _kiss->GetUser(); + std::vector::iterator accountIt; + std::vector::iterator categoryIt; + + SetSizer(vbox); + + _checkDescription = new wxCheckBox(this, wxID_ANY, _("Description")); + _checkDateFrom = new wxCheckBox(this, wxID_ANY, _("Date from")); + _checkDateTo = new wxCheckBox(this, wxID_ANY, _("Date to")); + _checkAmountFrom = new wxCheckBox(this, wxID_ANY, _("Amount from")); + _checkAmountTo = new wxCheckBox(this, wxID_ANY, _("Amount to")); + _checkCategory = new wxCheckBox(this, wxID_ANY, _("Category")); + _checkAccount = new wxCheckBox(this, wxID_ANY, _("Account")); + + wxGridBagSizer *gridBagSizer = new wxGridBagSizer(3, 9); + + _calendarFrom = new wxCalendarCtrl(this, wxID_ANY, wxDefaultDateTime, wxDefaultPosition, wxDefaultSize, + wxCAL_MONDAY_FIRST); + _calendarTo = new wxCalendarCtrl(this, wxID_ANY, wxDefaultDateTime, wxDefaultPosition, wxDefaultSize, + wxCAL_MONDAY_FIRST); + + + _description = new wxTextCtrl(this, wxID_ANY); + wxSize size = _description->GetSize(); + size.SetWidth(size.GetWidth()*2); + _description->SetMinSize(size); + _amountFrom = new wxTextCtrl(this, wxID_ANY); + _amountTo = new wxTextCtrl(this, wxID_ANY); + + _category = new wxCheckListBox(this, wxID_ANY); + for(categoryIt = user->_categories.begin(); categoryIt != user->_categories.end(); categoryIt++) + _category->Append(categoryIt->name); + _account = new wxCheckListBox(this, wxID_ANY); + for(accountIt = user->_accounts.begin(); accountIt != user->_accounts.end(); accountIt++) + _account->Append(accountIt->name); + + _searchButton = new wxButton(this, SEARCH_ID, _("Search")); + + gridBagSizer->Add(_checkDescription, wxGBPosition(0, 0)); + gridBagSizer->Add(_description, wxGBPosition(1, 0)); + gridBagSizer->Add(_checkDateFrom, wxGBPosition(0, 1)); + gridBagSizer->Add(_calendarFrom, wxGBPosition(1, 1)); + gridBagSizer->Add(_checkDateTo, wxGBPosition(0, 2)); + gridBagSizer->Add(_calendarTo, wxGBPosition(1, 2)); + gridBagSizer->Add(_checkAmountFrom, wxGBPosition(0, 3)); + gridBagSizer->Add(_amountFrom, wxGBPosition(1, 3)); + gridBagSizer->Add(_checkAmountTo, wxGBPosition(0, 4)); + gridBagSizer->Add(_amountTo, wxGBPosition(1, 4)); + gridBagSizer->Add(_checkCategory, wxGBPosition(0, 5)); + gridBagSizer->Add(_category, wxGBPosition(1, 5)); + gridBagSizer->Add(_checkAccount, wxGBPosition(0, 6)); + gridBagSizer->Add(_account, wxGBPosition(1, 6)); + gridBagSizer->Add(_searchButton, wxGBPosition(2, 0)); + + vbox->Add(gridBagSizer); + vbox->Add(-1, 20); + + _grid = new GridAccount(_kiss, this, GRID_ID); + + vbox->Add(_grid); + + Fit(); + + SetMinSize(wxSize(1024, 640)); + SetScrollbars(10, 10, 100/10, 100/10); + + Hide(); +} + +SearchPanel::~SearchPanel() +{ + if (_operations) delete _operations; +} + +void SearchPanel::OnButtonSearch(wxCommandEvent& event) +{ + wxString *description=NULL, *amountFrom=NULL, *amountTo=NULL; + std::vector categories, accounts; + wxDateTime *dateFrom=NULL, *dateTo=NULL, *dateTmp; + User* user= _kiss->GetUser(); + int i; + std::vector::iterator it; + + _grid->DeleteRows(1, _grid->GetNumberRows()-1); + + if (_checkDescription->IsChecked()) + { + description = new wxString; + *description = _description->GetLineText(0); + } + + if (_checkDateFrom->IsChecked()) + { + dateFrom = new wxDateTime; + *dateFrom = _calendarFrom->GetDate(); + } + + if (_checkDateTo->IsChecked()) + { + dateTo = new wxDateTime; + *dateTo = _calendarTo->GetDate(); + } + + if (dateFrom && dateTo && *dateFrom > *dateTo) + { + ; + } + + if (_checkAmountFrom->IsChecked()) + { + amountFrom = new wxString; + *amountFrom = _amountFrom->GetLineText(0); + } + + if (_checkAmountTo->IsChecked()) + { + amountTo = new wxString; + *amountTo = _amountTo->GetLineText(0); + } + + if (_checkCategory->IsChecked()) + { + for(i=0; iGetCategoriesNumber(); i++) + if (_category->IsChecked(i)) + categories.push_back(user->_categories[i].id); + } + + if (_checkAccount->IsChecked()) + { + for(i=0; iGetAccountsNumber(); i++) + if (_account->IsChecked(i)) + accounts.push_back(user->_accounts[i].id); + } + + if (_operations) + delete _operations; + + _operations = _kiss->Search(description, dateFrom, dateTo, amountFrom, amountTo, categories, accounts); + + for(i=1, it = _operations->begin(); it != _operations->end(); it++, i++) + { + _grid->InsertOperation(user, &(*it), i, false, 0, 0); + } + + _wxUI->Layout(); +} + +void SearchPanel::OnShow(wxShowEvent& event) +{ + _wxUI->SetTitle(_kiss->GetUser()->_name + wxT(" - ") + _("Search")); +} + diff --git a/src/view/SearchPanel.h b/src/view/SearchPanel.h new file mode 100644 index 0000000..766a472 --- /dev/null +++ b/src/view/SearchPanel.h @@ -0,0 +1,63 @@ +/* +Copyright 2010 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 SEARCHPANEL_H +#define SEARCHPANEL_H + +#include +#include +#include +#include +#include "CalendarEditor.h" +#include "wxGridCellBitmapRenderer.h" +#include "AccountPanel.h" +#include "GridAccount.h" +#include "view.h" + +#include +#include "wxUI.h" +#include + +class wxUI; +class KissCount; +class GridAccount; + +class SearchPanel: public wxScrolledWindow +{ + public: + SearchPanel(KissCount* kiss, wxUI *parent); + ~SearchPanel(); + + void OnButtonSearch(wxCommandEvent& event); + void OnShow(wxShowEvent& event); + + private: + KissCount* _kiss; + wxUI* _wxUI; + std::vector *_operations; + wxCalendarCtrl* _calendarFrom, *_calendarTo; + GridAccount *_grid; + wxCheckBox *_checkDescription, *_checkDateFrom, *_checkDateTo, *_checkAmountFrom, *_checkAmountTo, *_checkCategory, *_checkAccount; + wxTextCtrl* _description, *_amountFrom, *_amountTo; + wxCheckListBox* _category, *_account; + wxButton* _searchButton; + DECLARE_EVENT_TABLE(); +}; + +#endif diff --git a/src/view/view.h b/src/view/view.h new file mode 100644 index 0000000..163da1a --- /dev/null +++ b/src/view/view.h @@ -0,0 +1,41 @@ +/* +Copyright 2010 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 VIEW_H +#define VIEW_H + +#define OWN_CYAN wxColour(0x99, 0xCC, 0xFF) +#define OWN_YELLOW wxColour(0xFF, 0xFF, 0x99) +#define OWN_GREEN wxColour(0x3D, 0xEB, 0x3D) + +#define DEFAULT_FONT_NAME wxT("Liberation Sans") +#define DEFAULT_FONT_SIZE 12 +#define DEFAULT_FONT(font_name) wxFont font_name(DEFAULT_FONT_SIZE, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, DEFAULT_FONT_NAME); + +#define DELETE_ICON "ressources/icons/process-stop.png" +#define CHECKED_ICON "ressources/icons/tick-icon.png" +#define ACCOUNT_ICON "ressources/icons/administrator-icon.png" +#define STATS_ICON "ressources/icons/chart-icon.png" +#define SEARCH_ICON "ressources/icons/Search-icon.png" +#define PREFS_ICON "ressources/icons/options-icon.png" +#define CHANGE_USER_ICON "ressources/icons/Clients-icon.png" +#define ABOUT_ICON "ressources/icons/windows-users-icon.png" +#define QUIT_ICON "ressources/icons/system-log-out.png" + +#endif