* Goup/Ungroup initial work

* Add INSTALL file
* Adapt KissCount to new resolution
This commit is contained in:
Grégory Soutadé 2010-09-22 21:02:29 +02:00
parent e7a2b0c988
commit 3eea053d54
15 changed files with 203 additions and 17 deletions

25
INSTALL Normal file
View File

@ -0,0 +1,25 @@
** Dependencies for compilation (on Debian) **
libsqlite3-dev
libwxgtk2.8-dev
g++
make
** Compilation of extra libraries **
cd lib/wxsqlite3-1.9.9
./configure
make
cd -
cd lib/freechart
make # wxFreechart is already configured
cd -
** Compilation of KissCount **
make
** Execution **
export LD_LIBRARY_PATH=$PWD/lib/freechart/lib:$PWD/lib/wxsqlite3-1.9.9/lib/
./kc

View File

@ -2,7 +2,7 @@ CREATE TABLE kisscount(db_version VARCHAR(20));
CREATE TABLE user (id INTEGER PRIMARY KEY, name VARCHAR(255), password VARCHAR(255));
CREATE TABLE account(id INTEGER PRIMARY KEY, user REFERENCES user(id), name VARCHAR(255), number VARCHAR(255), shared CHAR(1), default_account CHAR(1));
CREATE TABLE account_amount(id INTEGER PRIMARY KEY, account REFERENCES account(id), year INTEGER, month INTEGER, amount FLOAT);
CREATE TABLE operation(id INTEGER PRIMARY KEY, parent REFERENCES operation(id), user REFERENCES user(id), account REFERENCES account(id), year INTEGER, month INTEGER, day INTEGER, amount FLOAT, description VARCHAR(255), category REFERENCES category(id), fix_cost CHAR(1), checked CHAR(1), formula VARCHAR(255), transfert REFERENCES operation(id));
CREATE TABLE operation(id INTEGER PRIMARY KEY, parent REFERENCES operation(id), user REFERENCES user(id), account REFERENCES account(id), year INTEGER, month INTEGER, day INTEGER, amount FLOAT, description VARCHAR(255), category REFERENCES category(id), fix_cost CHAR(1), checked CHAR(1), formula VARCHAR(255), transfert REFERENCES operation(id), meta CHAR(1));
CREATE TABLE category(id INTEGER PRIMARY KEY, user REFERENCES user(id), parent REFERENCES category(id), name VARCHAR(255), backcolor VARCHAR(10), forecolor VARCHAR(10), font VARCHAR(255));
CREATE TABLE preference(id INTEGER PRIMARY KEY, user REFERENCES user(id), name VARCHAR(255), value VARCHAR(255));
INSERT INTO kisscount ("db_version") VALUES ("1");

View File

@ -21,7 +21,9 @@
KissCount::KissCount(const char* bdd_filename) : _user(NULL)
{
_wxUI = new wxUI(this, wxT("KissCount"), wxPoint(50, 50), wxSize(1024, 768));
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());
@ -218,6 +220,7 @@ std::map<int, std::vector<int> > KissCount::GetAllOperations()
void KissCount::GenerateMonth(int monthFrom, int yearFrom, int monthTo, int yearTo)
{
std::vector<Operation>::iterator it;
std::map<wxString, wxString> meta;
Operation op;
_db->GenerateMonth(_user, monthFrom, yearFrom, monthTo, yearTo);
@ -239,8 +242,20 @@ void KissCount::GenerateMonth(int monthFrom, int yearFrom, int monthTo, int year
op.year = yearTo;
op.checked = false;
op.id = AddOperation(op);
if (op.meta)
meta[it->id] = op.id;
(*_user->_operations[yearTo])[monthTo].push_back(op);
}
// Re Generate parents
for(it = (*_user->_operations[yearFrom])[monthFrom].begin();
it != (*_user->_operations[yearFrom])[monthFrom].end()
&& it->fix_cost;
it++)
{
if (it->parent.Length())
it->parent = meta[it->parent];
}
}
_wxUI->GenerateMonth(monthTo, yearTo);
}

View File

@ -27,6 +27,8 @@
#include <model/model.h>
#include <view/wxUI.h>
#include <wx/display.h>
#define APP_VERSION "v0.1 beta"
class wxUI;

View File

@ -371,9 +371,11 @@ void Database::LoadYear(User* user, int year)
op.checked = set.GetBool(wxT("checked"));
op.transfert = set.GetAsString(wxT("transfert"));
op.formula = set.GetAsString(wxT("formula"));
op.meta = set.GetBool(wxT("meta"));
(*user->_operations[op.year])[op.month].push_back(op);
}
user->ResolveGroups(year);
set.Finalize();
}
@ -427,6 +429,7 @@ bool Database::GetOperation(const wxString& id, Operation* op)
op->checked = set.GetBool(wxT("checked"));
op->transfert = set.GetAsString(wxT("transfert"));
op->formula = set.GetAsString(wxT("formula"));
op->meta = set.GetBool(wxT("meta"));
return true;
}
@ -506,6 +509,10 @@ void Database::UpdateOperation(Operation& op)
else
req += wxT(", checked='0'");
req += wxT(", transfert='") + op.transfert + wxT("'");
if (op.meta)
req += wxT(", meta='1'");
else
req += wxT(", meta='0'");
req += wxT(", formula='") + op.formula + wxT("'");
req += wxT(" WHERE id='") + op.id + wxT("'");
@ -521,7 +528,7 @@ wxString Database::AddOperation(User* user, Operation& op)
ESCAPE_CHARS(op.description);
req = wxT("INSERT INTO operation ('user', 'parent', 'account', 'year', 'month', 'day', 'amount', 'description', 'category', 'fix_cost', 'formula', 'transfert') VALUES ('") ;
req = wxT("INSERT INTO operation ('user', 'parent', 'account', 'year', 'month', 'day', 'amount', 'description', 'category', 'fix_cost', 'formula', 'transfert', 'meta') VALUES ('") ;
req += user->_id + wxT("'");
req += wxT(", '") + op.parent + wxT("'");
req += wxT(", '") + op.account + wxT("'");
@ -537,6 +544,10 @@ wxString Database::AddOperation(User* user, Operation& op)
req += wxT(", '0'") ;
req += wxT(", '") + op.formula + wxT("'");
req += wxT(", '") + op.transfert + wxT("'");
if (op.meta)
req += wxT(", '1'") ;
else
req += wxT(", '0'") ;
req += wxT(")");
EXECUTE_SQL_UPDATE(req, wxT("0"));
@ -850,6 +861,7 @@ void Database::GenerateMonth(User* user, int monthFrom, int yearFrom, int monthT
req += wxT(" account='") + it->id + wxT("'");
req += wxT(" AND year='") + wxString::Format(wxT("%d"), yearFrom) + wxT("'");
req += wxT(" AND month='") + wxString::Format(wxT("%d"), monthFrom) + wxT("'");
req += wxT(" AND meta='0'");
EXECUTE_SQL_QUERY(req, set, );
@ -1194,6 +1206,7 @@ void Database::GetStats(User* user, const wxString& monthFrom, const wxString& y
req += wxT(" AND (year < '") + yearTo + wxT("' OR (year == '") + yearTo + wxT("' AND month <= '") + monthTo + wxT("'))");
req += wxT(" AND (transfert='' OR transfert IS NULL)");
req += wxT(" AND amount < 0");
req += wxT(" AND meta='0'");
EXECUTE_SQL_QUERY(req, set, );
@ -1217,6 +1230,7 @@ std::vector<Account>::iterator accountIt;
{
req = wxT("SELECT SUM(amount) AS amount FROM operation WHERE account='") + accountIt->id + wxT("'");
req += wxT(" AND checked='0'");
req += wxT(" AND meta='0'");
req += wxT(" AND (year < '") + wxString::Format(wxT("%d"), year) + wxT("'") ;
req += wxT(" OR (year == '") + wxString::Format(wxT("%d"), year) + wxT("'") ;
req += wxT(" AND month < '") + wxString::Format(wxT("%d"), month) + wxT("'") ;

View File

@ -35,6 +35,8 @@ public:
bool checked;
wxString transfert;
wxString formula;
bool meta;
std::vector<Operation*> childs;
} ;
#endif

View File

@ -160,3 +160,56 @@ void User::LinkOrUnlinkOperation(Operation& op)
op.transfert = wxT("");
}
}
void User::Group(Operation* op)
{
std::vector<Operation>::iterator it;
std::vector<Operation*>::iterator it2;
for (it = (*_operations[op->year])[op->month].begin(); it != (*_operations[op->year])[op->month].end(); it++)
{
if (it->id == op->parent)
{
for (it2 = it->childs.begin(); it2 != it->childs.end(); it2++)
if ((*it2)->id == op->id)
break;
// Already into childs
if (it2 != it->childs.end()) return;
it->childs.push_back(op);
break;
}
}
}
void User::UnGroup(Operation* op)
{
std::vector<Operation>::iterator it;
std::vector<Operation*>::iterator it2;
for (it = (*_operations[op->year])[op->month].begin(); it != (*_operations[op->year])[op->month].end(); it++)
{
if (it->id == op->parent)
{
for (it2 = it->childs.begin(); it2 != it->childs.end(); it2++)
if ((*it2)->id == op->id)
{
it->childs.erase(it2);
return;
}
break;
}
}
}
void User::ResolveGroups(int year)
{
unsigned int i;
std::map<unsigned int, std::vector<Operation> >::iterator it;
for (it = _operations[year]->begin(); it != _operations[year]->end(); it++)
{
for (i=0; i<it->second.size(); i++)
if (it->second[i].parent.Length())
Group(&((*_operations[year])[it->first])[i]);
}
}

View File

@ -54,6 +54,9 @@ public:
int GetOperationsNumber(int month, int year);
wxLanguage GetLanguage();
void LinkOrUnlinkOperation(Operation& op);
void Group(Operation* op);
void UnGroup(Operation* op);
void ResolveGroups(int year);
};
#endif

View File

@ -21,7 +21,7 @@
enum {ACCOUNT_NUMBER, ACCOUNT_NAME, ACCOUNT_INIT, ACCOUNT_CUR, ACCOUNT_FINAL, NUMBER_COLS_ACCOUNTS};
enum {CUR_CREDIT, CUR_DEBIT, TOTAL_CREDIT, TOTAL_DEBIT, REMAINS, STATS_ROW, CATS_STATS};
enum {CALENDAR_TREE_ID=1, OPS_GRID_ID, CALENDAR_ID, ACCOUNTS_GRID_ID, MENU_GENERATE_ID, MENU_DELETE_ID, CHECK_MODE_ID};
enum {CALENDAR_TREE_ID=1, OPS_GRID_ID, CALENDAR_ID, ACCOUNTS_GRID_ID, MENU_GENERATE_ID, MENU_DELETE_ID, CHECK_MODE_ID, GROUP_ID, UNGROUP_ID};
BEGIN_EVENT_TABLE(AccountPanel, wxPanel)
EVT_GRID_CMD_CELL_CHANGE(OPS_GRID_ID, AccountPanel::OnOperationModified)
@ -34,6 +34,8 @@ EVT_MENU(MENU_DELETE_ID, AccountPanel::OnMenuDelete)
EVT_SHOW(AccountPanel::OnShow)
EVT_CALENDAR_SEL_CHANGED(CALENDAR_ID, AccountPanel::OnCalendarChange)
EVT_CHECKBOX(CHECK_MODE_ID, AccountPanel::OnCheckMode)
EVT_BUTTON(GROUP_ID, AccountPanel::OnGroup)
EVT_BUTTON(UNGROUP_ID, AccountPanel::OnUnGroup)
END_EVENT_TABLE()
AccountPanel::AccountPanel(KissCount* kiss, wxUI *parent) : wxScrolledWindow(&(*parent)), _curMonth(-1), _curYear(-1), _kiss(kiss), _wxUI(parent), _tree(this, CALENDAR_TREE_ID, wxDefaultPosition, wxDefaultSize, wxTR_HIDE_ROOT)
@ -42,12 +44,14 @@ AccountPanel::AccountPanel(KissCount* kiss, wxUI *parent) : wxScrolledWindow(&(*
wxBoxSizer *hbox2 = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL);
wxBoxSizer *vbox2 = new wxBoxSizer(wxVERTICAL);
wxBoxSizer *vbox3 = new wxBoxSizer(wxVERTICAL);
wxChartPanel* chart ;
int i ;
User* user = _kiss->GetUser();
std::vector<Account>::iterator accountIt;
std::vector<Category>::iterator categoryIt;
DEFAULT_FONT(font);
wxRect rect = wxDisplay().GetGeometry();
SetSizer(hbox);
@ -119,7 +123,16 @@ AccountPanel::AccountPanel(KissCount* kiss, wxUI *parent) : wxScrolledWindow(&(*
_tree.SetIndent(5);
hbox->Add(&_tree, 0);
wxButton* buttonGroup = new wxButton(this, GROUP_ID, _("Group"));
wxButton* buttonUnGroup = new wxButton(this, GROUP_ID, _("UnGroup"));
vbox3->Add(&_tree, 0);
vbox3->Add(-1, 30);
vbox3->Add(buttonGroup, 0);
vbox3->Add(-1, 10);
vbox3->Add(buttonUnGroup, 0);
hbox->Add(vbox3, 0);
hbox2->Add(_accountsGrid, 0);
hbox2->Add(_calendar, 0);
vbox2->Add(hbox2, 0);
@ -138,7 +151,7 @@ AccountPanel::AccountPanel(KissCount* kiss, wxUI *parent) : wxScrolledWindow(&(*
Fit();
SetMinSize(wxSize(1024, 640));
SetMinSize(wxSize(rect.width-rect.x, rect.height-rect.y-128));
SetScrollbars(10, 10, 100/10, 100/10);
}
@ -808,3 +821,13 @@ void AccountPanel::OnCheckMode(wxCommandEvent& event)
{
UpdateStats();
}
void AccountPanel::OnGroup(wxCommandEvent& event)
{
_grid->Group();
}
void AccountPanel::OnUnGroup(wxCommandEvent& event)
{
_grid->UnGroup();
}

View File

@ -58,6 +58,9 @@ public:
void OnMenuDelete(wxCommandEvent& event);
void OnShow(wxShowEvent& event);
void OnCalendarChange(wxCalendarEvent& event);
void OnCheckMode(wxCommandEvent& event);
void OnGroup(wxCommandEvent& event);
void OnUnGroup(wxCommandEvent& event);
int _curMonth, _curYear;
@ -83,7 +86,6 @@ private:
void UpdateStats();
void InsertOperation(User* user, Operation* op, int line, bool fix);
void GetTreeSelection(int* month, int* year);
void OnCheckMode(wxCommandEvent& event);
DECLARE_EVENT_TABLE();
};

View File

@ -41,6 +41,7 @@ SearchPanel::SearchPanel(KissCount* kiss, wxUI *parent) : wxScrolledWindow(&(*pa
std::vector<Account>::iterator accountIt;
std::vector<Category>::iterator categoryIt;
wxDateTime firstOfMonth;
wxRect rect = wxDisplay().GetGeometry();
wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL);
SetSizer(vbox);
@ -108,7 +109,7 @@ SearchPanel::SearchPanel(KissCount* kiss, wxUI *parent) : wxScrolledWindow(&(*pa
Fit();
SetMinSize(wxSize(1024, 640));
SetMinSize(wxSize(rect.width-rect.x, rect.height-rect.y-128));
SetScrollbars(10, 10, 100/10, 100/10);
Hide();

View File

@ -133,15 +133,15 @@ StatsPanel::StatsPanel(KissCount* kiss, wxUI *parent) : wxPanel(&(*parent)), _ki
chart->SetMinSize(// chart->GetSize()
wxSize(200,250));
wxCommandEvent event ;
OnRangeChange(event);
_vbox2->Add(-1, 10);
_vbox2->Add(chart);
vbox->Add(hbox);
vbox->Add(_hbox2);
wxCommandEvent event ;
OnRangeChange(event);
Fit();
Hide();
@ -284,16 +284,21 @@ void StatsPanel::OnShow(wxShowEvent& event)
void StatsPanel::OnRangeChange(wxCommandEvent& event)
{
int monthFrom, monthTo, yearFrom, yearTo;
long monthFrom, monthTo, yearFrom, yearTo;
if (!_yearFrom->GetStringSelection().Length() ||
!_yearTo->GetStringSelection().Length())
return;
monthFrom = _monthFrom->GetCurrentSelection();
_yearFrom->GetStringSelection().ToLong((long*)&yearFrom);
_yearFrom->GetStringSelection().ToLong(&yearFrom);
monthTo = _monthTo->GetCurrentSelection();
_yearTo->GetStringSelection().ToLong((long*)&yearTo);
_yearTo->GetStringSelection().ToLong(&yearTo);
if (yearTo > yearFrom ||
(yearFrom == yearTo && monthFrom >= monthTo))
{
std::cout << monthFrom << " " << monthTo << " " << _yearFrom->GetStringSelection().mb_str() << " " << yearFrom << " " << yearTo << "\n" ;
wxMessageBox(_("Invalide date range"), _("KissCount"), wxICON_ERROR | wxOK);
return;
}

View File

@ -88,6 +88,13 @@ GridAccount::GridAccount(KissCount* kiss, wxWindow *parent, wxWindowID id) : wxG
}
Connect(id, wxEVT_GRID_CELL_CHANGE, wxGridEventHandler(GridAccount::OnOperationModified), NULL, this);
AutoSizeColumn(TREE, false);
AutoSizeColumn(CATEGORY, false);
AutoSizeColumn(DATE, false);
AutoSizeColumn(ACCOUNT, false);
AutoSizeColumn(DELETE, false);
AutoSizeColumn(CHECKED, false);
}
GridAccount::~GridAccount()
@ -141,19 +148,27 @@ void GridAccount::LoadOperations(std::vector<Operation>* operations, bool canAdd
it = _operations->begin();
for (;it != _operations->end() && it->fix_cost; it++)
{
if (it->parent.Length()) continue;
if (setWeek)
InsertOperationWithWeek(user, &(*it), ++curLine, true, it->month, it->year);
else
InsertOperation(user, &(*it), ++curLine, true, it->month, it->year);
}
if (canAddOperation)
InsertOperation(user, NULL, ++curLine, true, month, year);
for (; it != _operations->end(); it++)
{
if (it->parent.Length()) continue;
if (setWeek)
InsertOperationWithWeek(user, &(*it), ++curLine, false, it->month, it->year);
else
InsertOperation(user, &(*it), ++curLine, false, it->month, it->year);
}
if (canAddOperation)
InsertOperation(user, NULL, ++curLine, false, month, year);
@ -224,8 +239,20 @@ void GridAccount::InsertOperation(User* user, Operation* op, int line, bool fix,
InsertRows(line, 1);
SetCellRenderer(line, TREE, new wxGridCellTreeButtonRenderer());
SetCellEditor(line, TREE, new wxGridCellTreeButtonEditor());
if (op && op->meta)
{
SetCellRenderer(line, TREE, new wxGridCellTreeButtonRenderer());
SetCellEditor(line, TREE, new wxGridCellTreeButtonEditor());
SetReadOnly(line, DATE, true);
SetReadOnly(line, CREDIT, true);
SetReadOnly(line, DEBIT, true);
SetReadOnly(line, CATEGORY, true);
SetReadOnly(line, ACCOUNT, true);
}
else
SetReadOnly(line, TREE, true);
SetCellEditor(line, DEBIT, new wxGridCellFloatEditor(wxID_ANY, 2));
SetCellEditor(line, CREDIT, new wxGridCellFloatEditor(wxID_ANY, 2));
wxGridCellChoiceEditor* accountEditor = new wxGridCellChoiceEditor(user->GetAccountsNumber(), _accounts, false);
@ -304,6 +331,7 @@ void GridAccount::InsertOperation(User* user, Operation* op, int line, bool fix,
SetReadOnly(line, DELETE, true);
}
SetCellAlignment(line, DATE, wxALIGN_CENTRE, wxALIGN_CENTRE);
SetCellAlignment(line, DEBIT, wxALIGN_RIGHT, wxALIGN_CENTRE);
SetCellAlignment(line, CREDIT, wxALIGN_RIGHT, wxALIGN_CENTRE);
SetCellAlignment(line, DELETE, wxALIGN_CENTRE, wxALIGN_CENTRE);
@ -626,3 +654,13 @@ void GridAccount::OnOperationModified(wxGridEvent& event)
inModification = false ;
event.Skip();
}
void GridAccount::Group()
{
}
void GridAccount::UnGroup()
{
}

View File

@ -47,6 +47,9 @@ public:
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 Group();
void UnGroup();
void OnCellLeftClick(wxGridEvent& evt);
void OnOperationModified(wxGridEvent& event);

View File

@ -188,7 +188,7 @@ void wxUI::ShowPanel(wxPanel* panel)
int month, year=-1, account=0, preferences=0, search=0, stats=0;
wxShowEvent event;
if (!panel || panel == _curPanel) return;
if (!panel || (panel == _curPanel && !_needReload)) return;
if (_curPanel)
{