/* 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 "KissCount.h" std::vector * KissCount::_importEngines; std::vector * KissCount::_exportEngines; KissCount::KissCount(const char* bdd_filename) : _user(0) { wxRect rect = wxDisplay().GetGeometry(); _wxUI = new wxUI(this, wxT("KissCount"), wxPoint(50, 50), wxSize(rect.width-rect.x, rect.height-rect.y)); _wxUI->SetLanguage(wxLocale::GetSystemLanguage()); _wxUI->Show(true); _wxUI->Centre(); _wxUI->Disable(); try { _db = new Database(bdd_filename, this); } catch (std::string s) { _wxUI->Close(true); throw s; } _wxUI->ChangeUser(); _wxUI->Enable(); } KissCount::~KissCount() { delete _db; delete _wxUI; delete _importEngines; delete _exportEngines; if (_user) delete _user; } std::list KissCount::GetUsers() { return _db->GetUsers(); } bool KissCount::IsValidUser(const wxString& user, const wxString& password) { return _db->IsValidUser(user, password) ; } void KissCount::LoadUser(const wxString& user) { if (_user) delete _user; _user = _db->LoadUser(user) ; if (_user) _wxUI->LoadUser(); } void KissCount::LoadYear(int year, bool force) { if (!force && _user->_operations[year] != 0) return; if (_user->_operations[year] != 0) { delete _user->_operations[year]; _user->_operations[year] = 0; } _db->LoadYear(_user, year); } User* KissCount::GetUser() { return _user; } double KissCount::GetAccountAmount(const wxString& id, int month, int year) { return _db->GetAccountAmount(id, month, year); } double KissCount::CalcAccountAmount(const wxString& id, int month, int year, bool* had_values) { return _db->CalcAccountAmount(id, month, year, had_values); } void KissCount::UpdateOperation(Operation& op, bool checkTransfert) { // Unlink if (checkTransfert) { op.transfert = wxT(""); _user->LinkOrUnlinkOperation(op); } _db->UpdateOperation(_user, op, checkTransfert); // Link if (checkTransfert) _user->LinkOrUnlinkOperation(op); } wxString KissCount::AddOperation(Operation& op, bool checkTransfert) { wxString ret = _db->AddOperation(_user, op, checkTransfert); if (checkTransfert && op.transfert.Length()) _user->LinkOrUnlinkOperation(op); return ret; } void KissCount::DeleteOperation(Operation& op) { if (op.transfert.Length()) { op.transfert = wxT(""); _user->LinkOrUnlinkOperation(op); } _db->DeleteOperation(_user, op); } void KissCount::DeleteOperations(int month, int year) { _db->DeleteOperations(_user, month, year); if (month != -1) (*_user->_operations[year]).erase(month); if (month == -1 || !_user->_operations[year]->size()) { delete _user->_operations[year]; _user->_operations.erase(year); } } double KissCount::MetaAmount(const wxString& id) { return _db->MetaAmount(id); } double KissCount::MetaPositiveAmount(const wxString& id) { return _db->MetaPositiveAmount(id); } void KissCount::SetAccountAmount(const wxString& accountId, int month, int year, double amount) { _db->SetAccountAmount(accountId, month, year, amount); } wxString KissCount::AddAccount(Account& ac) { wxDateTime curDate; ac.id = _db->AddAccount(_user, ac); _user->_accounts.push_back(ac); curDate.SetToCurrent(); SetAccountAmount(ac.id, (int)curDate.GetMonth(), curDate.GetYear(), 0.0); return ac.id; } void KissCount::UpdateAccount(Account& ac) { std::vector::iterator it; int i; _db->UpdateAccount(ac); for (i=0, it=_user->_accounts.begin(); it !=_user->_accounts.end(); it++, i++) if (it->id == ac.id) _user->_accounts[i] = ac; if (ac._default) std::sort(_user->_accounts.begin(), _user->_accounts.end(), Account()); } void KissCount::DeleteAccount(Account& ac, const wxString& replacement) { std::vector::iterator it; int i; std::map >* >::iterator it2; _db->DeleteAccount(_user, ac, replacement); for (i=0, it=_user->_accounts.begin(); it !=_user->_accounts.end(); it++, i++) if (it->id == ac.id) { _user->_accounts.erase(_user->_accounts.begin()+i); break; } for (it2= _user->_operations.begin(); it2 != _user->_operations.end(); it2++) LoadYear(it2->first, true); } void KissCount::AddSharedAccount(Account& ac, const wxString& granted) { _db->AddSharedAccount(ac, granted); } void KissCount::RemoveSharedAccount(Account& ac, const wxString& granted) { _db->RemoveSharedAccount(ac, granted); } std::map KissCount::getSharedAccountOwners(const wxString& account) { return _db->getSharedAccountOwners(account); } wxString KissCount::getSharedAccountOwner(const wxString& account) { return _db->getSharedAccountOwner(account); } wxString KissCount::AddCategory(Category& category) { wxString id; id = _db->AddCategory(_user, category); category.id = id; _user->_categories.push_back(category); _user->_categoriesFonts.push_back(ExtractFont(wxT(""))); return id; } void KissCount::UpdateCategory(Category& category) { _db->UpdateCategory(category); for (int i=0; i<_user->GetCategoriesNumber();i++) if (_user->_categories[i].id == category.id) { _user->_categories[i] = category; _user->_categoriesFonts[i] = ExtractFont(category.font); break; } } void KissCount::DeleteCategory(Category& category, const wxString& replacement) { std::map >* >::iterator it; _db->DeleteCategory(_user, category, replacement); for (int i=0; i<_user->GetCategoriesNumber();i++) if (_user->_categories[i].id == category.id) { _user->_categories.erase(_user->_categories.begin()+i); _user->_categoriesFonts.erase(_user->_categoriesFonts.begin()+i); break; } for (it= _user->_operations.begin(); it != _user->_operations.end(); it++) LoadYear(it->first, true); } std::map > KissCount::GetAllOperations() { return _db->GetAllOperations(_user); } void KissCount::GenerateMonth(int monthFrom, int yearFrom, int monthTo, int yearTo) { std::vector::iterator it, it2; std::map meta; Operation op; _db->GenerateMonth(_user, monthFrom, yearFrom, monthTo, yearTo); if (!_user->_operations[yearTo]) _user->_operations[yearTo] = new std::map >(); if (monthFrom != -1 && yearFrom != -1) { LoadYear(yearFrom, false); for(it = (*_user->_operations[yearFrom])[monthFrom].begin(); it != (*_user->_operations[yearFrom])[monthFrom].end(); it++) { if (!it->fix_cost) continue; op = *it; op.month = monthTo; op.year = yearTo; op.checked = false; op.id = AddOperation(op); op.childs.clear(); op._virtual = false; if (op.meta) meta[it->id] = op.id; (*_user->_operations[yearTo])[monthTo].push_back(op); } // Re Generate parents for(it = (*_user->_operations[yearTo])[monthTo].begin(); it != (*_user->_operations[yearTo])[monthTo].end(); it++) { if (it->parent.Length()) { it->parent = meta[it->parent]; UpdateOperation(*it); for(it2 = (*_user->_operations[yearTo])[monthTo].begin(); it2 != (*_user->_operations[yearTo])[monthTo].end(); it2++) if (it2->id == it->parent) { it2->childs.push_back(it->id); break; } } } } _wxUI->GenerateMonth(monthTo, yearTo); } void KissCount::ChangePassword(const wxString& password) { _db->ChangePassword(_user, password); } bool KissCount::UserExists(const wxString& name) { return _db->UserExists(name); } void KissCount::ChangeName(const wxString& name) { _db->ChangeName(_user, name); _user->_name = name; } // To enable translation during xgettext wxString default_cats[] = { _("Fix"), _("Groceries"), _("Hobbies"), _("Car"), _("Unexpected"), _("Other") }; void KissCount::NewUser(const wxString& name) { wxDateTime curDate; Account ac = { /*.id = */wxT(""), /*.name = */_("Account 1"), /*.number = */wxT(""), /*.shared = */false, /*.blocked = */false, /*._default = */true, /*.is_owner = */true}; Category cat ; _db->NewUser(name); if (_user) delete _user; _user = _db->LoadUser(name) ; curDate.SetToCurrent(); AddAccount(ac); cat.parent = wxT("0") ; cat.name = wxT("Fix") ; cat.backcolor = OWN_YELLOW ; cat.forecolor = *wxBLACK; cat.fix_cost = true; AddCategory(cat); cat.parent = wxT("0") ; cat.name = wxT("Groceries") ; cat.backcolor = OWN_GREEN; cat.forecolor = *wxBLACK; cat.fix_cost = false; AddCategory(cat); cat.parent = wxT("0") ; cat.name = wxT("Hobbies") ; cat.backcolor = OWN_GREEN; cat.forecolor = *wxBLACK; cat.fix_cost = false; AddCategory(cat); cat.parent = wxT("0") ; cat.name = wxT("Car") ; cat.backcolor = OWN_GREEN; cat.forecolor = *wxBLACK; cat.fix_cost = false; AddCategory(cat); cat.parent = wxT("0") ; cat.name = wxT("Unexpected") ; cat.backcolor = OWN_GREEN; cat.forecolor = *wxBLACK; cat.fix_cost = false; AddCategory(cat); cat.parent = wxT("0") ; cat.name = wxT("Other") ; cat.backcolor = OWN_GREEN; cat.forecolor = *wxBLACK; cat.fix_cost = false; AddCategory(cat); SetOperationOrder(wxT("ASC")); _db->GenerateMonth(_user, -1, -1, (int)curDate.GetMonth(), curDate.GetYear()); } void KissCount::KillMe() { _wxUI->KillMe(); _db->KillMe(_user); delete _user; _user = 0; _wxUI->ChangeUser(); } void KissCount::SetLanguage(wxLanguage language) { _user->_preferences[wxT("language")] = wxString::Format(wxT("%d"), language) ; _db->UpdatePreference(_user, wxT("language")); } /* ASC (default) or DESC */ void KissCount::SetOperationOrder(const wxString& order) { _user->_preferences[wxT("operation_order")] = order; _db->UpdatePreference(_user, wxT("operation_order")); } const wxString& KissCount::GetOperationOrder() { return _user->_preferences[wxT("operation_order")] ; } std::vector* KissCount::Search(wxString* description, wxDateTime* dateFrom, wxDateTime* dateTo, wxString* amountFrom, wxString* amountTo, std::vector categories, int types, std::vector accounts) { return _db->Search(_user, description, dateFrom, dateTo, amountFrom, amountTo, categories, types, accounts, true); } bool KissCount::SearchPreviousOperation(Operation* res, Operation& op, int month, int year, bool limitToType) { std::vector* operations; wxDateTime* date ; //wxDateSpan threeMonths(0, 3); Not working :( std::vector v; int i; month -= 3; if (month < 0) { year -= 1; month += 12; } date = new wxDateTime(0, (wxDateTime::Month)month, year); if (limitToType) operations = _db->Search(_user, &op.description, date, 0, 0, 0, v, op.fix_cost ? FIX_OP : NON_FIX_OP, v, false); else operations = _db->Search(_user, &op.description, date, 0, 0, 0, v, ALL_OP, v, false); delete date; if (!operations->size()) { delete operations; return false; } for(i=operations->size()-1; i>=0; i--) if (!(*operations)[i].meta) { *res = (*operations)[i]; delete operations; return true; } delete operations; return false; } void KissCount::GetStats(int monthFrom, int yearFrom, int monthTo, int yearTo, std::map > >* accountAmounts, std::map* categories) { wxString monthF = wxString::Format(wxT("%d"), monthFrom); wxString monthT = wxString::Format(wxT("%d"), monthTo); wxString yearF = wxString::Format(wxT("%d"), yearFrom); wxString yearT = wxString::Format(wxT("%d"), yearTo); _db->GetStats(_user, monthF, yearF, monthT, yearT, accountAmounts, categories); } void KissCount::GetMonthStats(int month, int year, int nbDays, std::map >* operations, std::map* categories) { wxString monthS = wxString::Format(wxT("%d"), month); wxString yearS = wxString::Format(wxT("%d"), year); _db->GetMonthStats(_user, monthS, yearS, nbDays, operations, categories); } std::map* KissCount::GetNotChecked(int month, int year) { return _db->GetNotChecked(_user, month, year); } std::map* KissCount::GetVirtualAmount(int month, int year) { return _db->GetVirtualAmount(_user, month, year); } wxFont KissCount::ExtractFont(wxString strFont) { long int pos, pointSize, family, style, weight; wxString faceName; if (!strFont.Length()) { DEFAULT_FONT(f); return f; } pos = strFont.Find(wxT(";")); if (pos != -1) { strFont.SubString(0, pos).ToLong(&pointSize); strFont = strFont.SubString(pos+1, strFont.Length()); } pos = strFont.Find(wxT(";")); if (pos != -1) { strFont.SubString(0, pos).ToLong(&family); strFont = strFont.SubString(pos+1, strFont.Length()); } pos = strFont.Find(wxT(";")); if (pos != -1) { strFont.SubString(0, pos).ToLong(&style); strFont = strFont.SubString(pos+1, strFont.Length()); } pos = strFont.Find(wxT(";")); if (pos != -1) { strFont.SubString(0, pos).ToLong(&weight); strFont = strFont.SubString(pos+1, strFont.Length()); } faceName = strFont; return wxFont(pointSize, family, style, weight, false, faceName) ; } wxString KissCount::CompactFont(const wxFont& font) { wxString res = wxString::Format(wxT("%d;%d;%d;%d;"), font.GetPointSize(), font.GetFamily(), font.GetStyle(), font.GetWeight()); res += font.GetFaceName(); return res; } void KissCount::UnRegisterImportEngine(ImportEngine* engine) { std::vector::iterator it; std::vector* importEngines = KissCount::GetImportEngines(); for(it=importEngines->begin(); it!=importEngines->end(); it++) if (*it == engine) { importEngines->erase(it); break; } } void KissCount::RegisterImportEngine(ImportEngine* engine) { std::vector* importEngines = KissCount::GetImportEngines(); importEngines->push_back(engine); } wxString KissCount::GetImportEngineExtensions() { wxString res; std::vector::iterator it; int i; std::vector* importEngines = KissCount::GetImportEngines(); for(i=0; i<(int)importEngines->size()-1; i++) res = res + (*importEngines)[i]->GetFileExt() + wxT("|") ; if (importEngines->size()) res = res + (*importEngines)[i]->GetFileExt(); return res; } ImportEngine* KissCount::GetImportEngine(wxString path) { std::vector::iterator it; std::vector* importEngines = KissCount::GetImportEngines(); for(it=importEngines->begin(); it!=importEngines->end(); it++) if ((*it)->HandleFile(path, _user, _db, this)) return *it; return 0; } void KissCount::UpdateImportPattern() { _db->UpdateImportPattern(_user); } void KissCount::UnRegisterExportEngine(ExportEngine* engine) { std::vector::iterator it; std::vector* exportEngines = KissCount::GetExportEngines(); for(it=exportEngines->begin(); it!=exportEngines->end(); it++) if (*it == engine) { exportEngines->erase(it); break; } } void KissCount::RegisterExportEngine(ExportEngine* engine) { std::vector* exportEngines = KissCount::GetExportEngines(); exportEngines->push_back(engine); } wxString KissCount::GetExportEngineExtensions() { wxString res; std::vector::iterator it; int i; std::vector* exportEngines = KissCount::GetExportEngines(); for(i=0; i<(int)exportEngines->size()-1; i++) res = res + (*exportEngines)[i]->GetFileExt() + wxT("|") ; if (exportEngines->size()) res = res + (*exportEngines)[i]->GetFileExt(); return res; } ExportEngine* KissCount::GetExportEngine(wxString path) { std::vector::iterator it; std::vector* exportEngines = KissCount::GetExportEngines(); for(it=exportEngines->begin(); it!=exportEngines->end(); it++) if ((*it)->HandleFile(path, _user, _db, this)) return *it; return 0; } std::vector* KissCount::GetImportEngines() { if (!_importEngines) _importEngines = new std::vector; return _importEngines; } std::vector* KissCount::GetExportEngines() { if (!_exportEngines) _exportEngines = new std::vector; return _exportEngines; }