HomeBudget
Demonstrates using of GridCtrl and Sqlite3 database

HomeBudget.h
#ifndef _HomeBudget_HomeBudget_h
#define _HomeBudget_HomeBudget_h
class HomeBudgetHelp : public HelpWindow
{
public:
HomeBudgetHelp();
virtual Topic AcquireTopic(const String& topic);
};
class HomeBudget : public WithHomeBudgetLayout<TopWindow>
{
public:
typedef HomeBudget CLASSNAME;
GridCtrl groups;
GridCtrl categories;
GridCtrl money;
GridCtrl mostpr;
GridCtrl mostcat;
Splitter spl;
DropDate dt;
DropGrid dlpm, category, months, yesno, plusminus;
EditDouble defval, val;
EditStringNotNull eg, ec;
EditString es;
int dtid;
int lang;
HomeBudget();
void NewGroup();
void NewCategory();
void InsertGroup();
void UpdateGroup();
void RemoveGroup();
void ChangeGroup();
void InsertCategory();
void UpdateCategory();
void RemoveCategory();
void LoadCategories(int group_id);
void UpdateCategories();
void InsertMoney();
void UpdateMoney();
void RemoveMoney();
void InsertDate();
void UpdateDate();
void RemoveDate();
void ChangeDate();
void NewDate();
void AcceptedDate();
void LoadDates();
void LoadGroups();
void UpdateSummary();
void ClearSummary();
void UpdateValue();
void GenMonthList(int year);
void Serialize(Stream &s);
void Options();
void About();
void Setup();
void Help();
void SetRest(StaticText &rest, float r);
int GetCategorySign();
void ClearAll();
void LoadMoney(int did);
void EnableMoney(int cnt = -1);
};
#endif
HomeBudget.cpp
#include <CtrlLib/CtrlLib.h>
#include <DropGrid/DropGrid.h>
#include <GridCtrl/GridCtrl.h>
#include <plugin/sqlite3/Sqlite3.h>
using namespace Upp;
#define IMAGEFILE <HomeBudget/HomeBudget.iml>
#define IMAGECLASS Images
#include <Draw/iml.h>
#define SCHEMADIALECT <plugin/sqlite3/Sqlite3Schema.h>
#define MODEL <HomeBudget/HomeBudget.sch>
#include <Sql/sch_schema.h>
#include <Sql/sch_header.h>
#include <Sql/sch_source.h>
#define LAYOUTFILE <HomeBudget/HomeBudget.lay>
#include <CtrlCore/lay.h>
#define TOPICFILE <HomeBudget/src.tpp/all.i>
#include <Core/topic_group.h>
#define TOPICFILE <HomeBudget/help.tpp/all.i>
#include <Core/topic_group.h>
#define TFILE <HomeBudget/HomeBudget.t>
#include <Core/t.h>
#include "HomeBudget.h"
struct ConvMonth : Convert
{
Value Format(const Value &q) const
{
Date dt = (Date) q;
return q.IsNull() ? "" : UPP::Format("%Month %.4d", dt.month, dt.year);
}
};
struct ConvDouble : Convert
{
Value Format(const Value &q) const
{
return q.IsNull() ? Null : UPP::Format("%.2f", q);
}
};
struct DispPM : GridDisplay
{
virtual void Paint(Draw &w, int x, int y, int cx, int cy, const Value &val, dword style,
Color &fg, Color &bg, Font &fnt, bool found, int fs, int fe)
{
if(!val.IsNull())
{
int t = int(val) < 0 ? 0 : 1;
SetCenterImage(t ? Images::Plus : Images::Minus);
}
else
SetCenterImage(Null);
GridDisplay::Paint(w, x, y, cx, cy, Value(""), style, fg, bg, fnt, found, fs, fe);
}
};
HomeBudget::HomeBudget()
{
lang = 0;
}
void HomeBudget::Setup()
{
CtrlLayout(*this, String(t_("Home budget")) + " 1.0");
Icon(Images::SmallIcon());
LargeIcon(Images::LargeIcon());
tab.Add(money.SizePos(), t_("Expenses"));
tab.Add(spl.Horz(groups, categories), t_("Categories"));
spl.SetPos(2000);
money.AddIndex(ID);
money.AddColumn(CAT_ID, t_("Category")).Edit(category).SetConvert(category);
money.AddColumn(PM, t_("Plus / Minus")).SetDisplay(Single<DispPM>()).Edit(plusminus);
money.AddColumn(VALUE, t_("Value")).Edit(val).Default(0).SetConvert(Single<ConvDouble>());
money.AddColumn(DT, t_("When")).Edit(dt).Default(GetSysDate());
money.AddColumn(DESC, t_("Describe")).Edit(es);
money.Appending().Removing().Editing().Accepting().Canceling();
money.RejectNullRow();
money.WhenInsertRow = THISBACK(InsertMoney);
money.WhenUpdateRow = THISBACK(UpdateMoney);
money.WhenRemoveRow = THISBACK(RemoveMoney);
money.SetToolBar();
Date dt = GetSysDate();
dt.day = 1;
month.AddIndex(ID);
month.AddColumn(DT, t_("Month")).Edit(months).SetConvert(Single<ConvMonth>()).Default(dt);
month.Appending().Removing().Editing().Accepting().Canceling();
month.WhenInsertRow = THISBACK(InsertDate);
month.WhenUpdateRow = THISBACK(UpdateDate);
month.WhenRemoveRow = THISBACK(RemoveDate);
month.WhenChangeRow = THISBACK(ChangeDate);
month.WhenAcceptedRow = THISBACK(AcceptedDate);
month.WhenNewRow = THISBACK(NewDate);
month.SetToolBar();
groups.AddIndex(ID);
groups.AddColumn(NAME, t_("Name")).Edit(eg);
groups.Appending().Removing().Editing().Accepting().Canceling();
groups.RejectNullRow();
groups.SetToolBar();
groups.WhenInsertRow = THISBACK(InsertGroup);
groups.WhenUpdateRow = THISBACK(UpdateGroup);
groups.WhenRemoveRow = THISBACK(RemoveGroup);
groups.WhenChangeRow = THISBACK(ChangeGroup);
categories.AddIndex(ID);
categories.AddColumn(NAME, t_("Name")).Edit(ec);
categories.AddColumn(DEFVALUE, t_("Default value")).Edit(defval).SetConvert(Single<ConvDouble>());
categories.AddColumn(PM, t_("Plus / Minus")).Edit(dlpm).SetConvert(dlpm).Default(-1);
categories.AddColumn(INNEWMONTH, t_("Default for a new month")).Edit(yesno).SetConvert(yesno).Default(0);
categories.WhenInsertRow = THISBACK(InsertCategory);
categories.WhenUpdateRow = THISBACK(UpdateCategory);
categories.WhenRemoveRow = THISBACK(RemoveCategory);
categories.WhenAcceptedRow = THISBACK(UpdateCategories);
categories.Appending().Removing().Editing();
categories.RejectNullRow();
categories.SetToolBar();
mostpr.AddColumn(t_("Name"));
mostpr.AddColumn(t_("Amount")).SetConvert(Single<ConvDouble>()).AlignCenter();
mostcat.AddColumn(t_("Name"));
mostcat.AddColumn(t_("Amount")).SetConvert(Single<ConvDouble>()).AlignCenter();
tabmost.Add(mostpr.SizePos(), t_("Product"));
tabmost.Add(mostcat.SizePos(), t_("Category"));
dlpm.Add(-1, t_("Minus")).Add(1, t_("Plus"));
plusminus.Add(-1, t_("Minus")).Add(1, t_("Plus"));
yesno.Add(0, t_("No")).Add(1, t_("Yes"));
GenMonthList(dt.year);
SQL * Delete(MONEY).Where(IsNull(CAT_ID));
LoadDates();
LoadGroups();
UpdateCategories();
if(month.GetCount() > 0)
{
month.GoEnd();
UpdateSummary();
}
EnableMoney();
Sizeable().Zoomable();
category <<= THISBACK(UpdateValue);
exit <<= THISBACK(Close);
options <<= THISBACK(Options);
about <<= THISBACK(About);
help <<= THISBACK(Help);
category.Resizeable(false).Header(false);
category.AddPlus(THISBACK(NewCategory));
}
void HomeBudget::Serialize(Stream &s)
{
int version = 1;
s / version;
SerializePlacement(s);
s % spl;
s % lang;
//s % categories;
//s % money;
}
void HomeBudget::GenMonthList(int year)
{
months.Clear();
int curr_year = GetSysDate().year;
int max_year = max(year,curr_year);
for(int scan_year = min(year, curr_year) - 1; scan_year <= max_year; scan_year++)
for(int i = 0; i < 12; i++)
months.Add(Date(scan_year, i + 1, 1), Format("%Month %.4d", i + 1, scan_year));
}
void HomeBudget::LoadMoney(int dtid)
{
money.Clear();
SQL * Select(ID, CAT_ID, PM, VALUE, DT, DESC).From(MONEY).Where(DT_ID == dtid);
while(SQL.Fetch())
{
money.Add();
money(ID) = SQL[ID];
money(CAT_ID) = SQL[CAT_ID];
money(PM) = SQL[PM];
money(VALUE) = SQL[VALUE];
money(DT) = SQL[DT];
money(DESC) = SQL[DESC];
}
}
void HomeBudget::LoadDates()
{
month.Clear();
SQL * Select(ID, DT).From(DATES);
while(SQL.Fetch())
month.Add(SQL);
}
void HomeBudget::LoadGroups()
{
groups.Clear();
SQL * Select(ID, NAME).From(GROUPS);
while(SQL.Fetch())
groups.Add(SQL);
if(!groups.IsEmpty())
groups.SetCursor(0);
else
categories.Disable();
}
void HomeBudget::LoadCategories(int group_id)
{
categories.Clear();
SQL * Select(ID, NAME, DEFVALUE, PM, INNEWMONTH).From(CATEGORIES).Where(GR_ID == group_id);
while(SQL.Fetch())
categories.Add(SQL);
}
int HomeBudget::GetCategorySign()
{
SQL * Select(PM).From(CATEGORIES).Where(ID == money.Get(CAT_ID));
Value v = SQL.Fetch() ? SQL[0] : Value(0);
return v;
}
void HomeBudget::UpdateCategories()
{
category.Clear();
SQL & Select(ID.Of(CATEGORIES), NAME.Of(CATEGORIES), NAME.Of(GROUPS))
.From(CATEGORIES, GROUPS)
.Where(GR_ID == ID.Of(GROUPS))
.OrderBy(NAME.Of(GROUPS), NAME.Of(CATEGORIES));
while(SQL.Fetch())
category.Add(SQL[0], Format("%s - %s", SQL[2], SQL[1]));
}
void HomeBudget::InsertGroup()
{
try
{
SQL & Insert(GROUPS)
(NAME, groups(1));
groups(0) = SQL.GetInsertedId();
categories.Clear();
categories.Enable();
}
catch(SqlExc &e)
{
groups.CancelInsert();
Exclamation("[* " + DeQtfLf(e) + "]");
}
}
void HomeBudget::UpdateGroup()
{
try
{
SQL & ::Update(GROUPS)
(NAME, groups(1))
.Where(ID == groups(0));
}
catch(SqlExc &e)
{
groups.CancelUpdate();
Exclamation("[* " + DeQtfLf(e) + "]");
}
}
void HomeBudget::RemoveGroup()
{
if(categories.IsEmpty())
{
SQL & Delete(GROUPS).Where(ID == groups(ID));
if(groups.GetCount() == 1)
categories.Disable();
}
else
{
PromptOK(t_("You can't remove this group. It is not empty."));
groups.CancelRemove();
}
}
struct AddNewCat : WithNewCategoryLayout<TopWindow>
{
typedef AddNewCat CLASSNAME;
bool newgroup;
AddNewCat()
{
newgroup = false;
CtrlLayoutOKCancel(*this, t_("New item"));
addgroup.SetImage(Images::SmallPlus());
addgroup <<= THISBACK(NewGroup);
groups <<= THISBACK(SelGroup);
addgroup.NoWantFocus();
int cnt = 0;
SQL * Select(ID, NAME).From(GROUPS);
while(SQL.Fetch())
{
groups.Add(SQL[ID], SQL[NAME]);
cnt++;
}
bool isgroup = cnt > 0;
if(isgroup)
groups.SetIndex(0);
else
ok.Disable();
pm = 1;
}
void SelGroup()
{
ok.Enable();
}
void NewGroup()
{
WithNewGroupLayout<TopWindow> dlg;
CtrlLayoutOKCancel(dlg, t_("New category"));
if(dlg.Execute() == IDOK)
{
try
{
SQL & Insert(GROUPS)(NAME, ~dlg.name);
int64 id = SQL.GetInsertedId();
groups.Add(id, ~dlg.name);
groups <<= id;
ok.Enable();
newgroup = true;
}
catch(SqlExc &e)
{
Exclamation("[* " + DeQtfLf(e) + "]");
}
}
}
bool IsNewGroup() { return newgroup; }
};
void HomeBudget::NewCategory()
{
AddNewCat dlg;
if(dlg.Execute() == IDOK)
{
try
{
SQL & Insert(CATEGORIES)
(GR_ID, ~dlg.groups)
(NAME, ~dlg.name)
(DEFVALUE, 0)
(PM, dlg.pm == 0 ? 1 : -1)
(INNEWMONTH, 0);
int64 id = SQL.GetInsertedId();
UpdateCategories();
money.Set(CAT_ID, id);
UpdateValue();
int gid = ~dlg.groups;
if(dlg.IsNewGroup())
{
groups.Add(Value(gid), dlg.groups.GetValue());
groups.GoEnd();
categories.Enable();
}
int c = groups.GetCursor();
if(c >= 0 && gid == groups(c, 0))
LoadCategories(gid);
}
catch(SqlExc &e)
{
Exclamation("[* " + DeQtfLf(e) + "]");
}
}
}
void HomeBudget::InsertCategory()
{
try
{
SQL & Insert(CATEGORIES)
(GR_ID, groups(ID))
(NAME, categories(NAME))
(DEFVALUE, categories(DEFVALUE))
(PM, categories(PM))
(INNEWMONTH, categories(INNEWMONTH));
categories(0) = SQL.GetInsertedId();
}
catch(SqlExc &e)
{
categories.CancelInsert();
Exclamation("[* " + DeQtfLf(e) + "]");
}
}
void HomeBudget::UpdateCategory()
{
try
{
SQL & ::Update(CATEGORIES)
(NAME, categories(NAME))
(DEFVALUE, categories(DEFVALUE))
(PM, categories(PM))
(INNEWMONTH, categories(INNEWMONTH))
.Where(ID == categories(ID));
UpdateSummary();
}
catch(SqlExc &e)
{
categories.CancelUpdate();
Exclamation("[* " + DeQtfLf(e) + "]");
}
}
void HomeBudget::ChangeGroup()
{
LoadCategories(groups(ID));
}
void HomeBudget::RemoveCategory()
{
try
{
SQL * Select(CAT_ID, NAME)
.From(MONEY, CATEGORIES)
.Where(CAT_ID == categories(ID) && ID.Of(CATEGORIES) == categories(ID))
.Limit(1);
if(SQL.Fetch())
{
PromptOK(Format(t_("Item '%s' can't be removed. It is used in calculations."), AsString(SQL[1])));
categories.CancelRemove();
}
else
{
SQL & Delete(CATEGORIES).Where(ID == categories(ID));
UpdateCategories();
}
}
catch(SqlExc &e)
{
categories.CancelRemove();
Exclamation("[* " + DeQtfLf(e) + "]");
}
}
void HomeBudget::InsertMoney()
{
try
{
SQL & Insert(MONEY)
(DT_ID, dtid)
(CAT_ID, money(CAT_ID))
(PM, money(PM))
(VALUE, money(VALUE))
(DT, money(DT))
(DESC, money(DESC));
money(ID) = SQL.GetInsertedId();
UpdateSummary();
}
catch(SqlExc &e)
{
money.CancelInsert();
Exclamation("[* " + DeQtfLf(e) + "]");
}
}
void HomeBudget::UpdateMoney()
{
try
{
SQL & ::Update(MONEY)
(DT_ID, dtid)
(CAT_ID, money(CAT_ID))
(PM, money(PM))
(VALUE, money(VALUE))
(DT, money(DT))
(DESC, money(DESC))
.Where(ID == money(ID));
UpdateSummary();
}
catch(SqlExc &e)
{
money.CancelUpdate();
Exclamation("[* " + DeQtfLf(e) + "]");
}
}
void HomeBudget::RemoveMoney()
{
try
{
SQL & Delete(MONEY).Where(ID == money(ID));
UpdateSummary();
}
catch(SqlExc &e)
{
money.CancelRemove();
Exclamation("[* " + DeQtfLf(e) + "]");
}
}
void HomeBudget::InsertDate()
{
try
{
SQL & Insert(DATES)(DT, month(DT));
month(ID) = dtid = (int) SQL.GetInsertedId();
EnableMoney();
}
catch(SqlExc &e)
{
month.CancelInsert();
Exclamation("[* " + DeQtfLf(e) + "]");
}
}
void HomeBudget::EnableMoney(int cnt)
{
money.Enable(cnt < 0 ? month.GetCount() > 0 : cnt);
}
void HomeBudget::UpdateDate()
{
try
{
SQL & ::Update(DATES)(DT, month(DT)).Where(ID == month(ID));
}
catch(SqlExc &e)
{
month.CancelUpdate();
Exclamation("[* " + DeQtfLf(e) + "]");
}
}
void HomeBudget::RemoveDate()
{
try
{
SQL.Begin();
SQL & Delete(MONEY).Where(DT_ID == month(ID));
SQL & Delete(DATES).Where(ID == month(ID));
SQL.Commit();
bool en = month.GetCount() <= 1 ? false : true;
EnableMoney(en);
if(!en)
money.Clear();
}
catch(SqlExc &e)
{
SQL.Rollback();
month.CancelRemove();
Exclamation("[* " + DeQtfLf(e) + "]");
}
}
void HomeBudget::ChangeDate()
{
dtid = month(ID);
LoadMoney(dtid);
EnableMoney();
UpdateSummary();
GenMonthList(((Date) month(DT)).year);
}
void HomeBudget::NewDate()
{
money.Clear();
money.Disable();
UpdateSummary();
}
void HomeBudget::AcceptedDate()
{
if(!month.IsNewRow())
return;
Sql q;
SQL.Begin();
SQL * Select(ID, DEFVALUE, PM).From(CATEGORIES).Where(INNEWMONTH == 1);
while(SQL.Fetch())
{
money.Add();
money(CAT_ID) = SQL[ID];
money(VALUE) = SQL[DEFVALUE];
money(PM) = SQL[PM];
q * Insert(MONEY)
(DT_ID, dtid)
(CAT_ID, money(CAT_ID))
(PM, money(PM))
(VALUE, money(VALUE))
(DT, money(DT))
(DESC, money(DESC));
money(ID) = SQL.GetInsertedId();
money.RefreshNewRow();
}
SQL.Commit();
UpdateSummary();
}
void HomeBudget::UpdateSummary()
{
if(!month.IsCursor())
return;
float p = 0, tp = 0;
float m = 0, tm = 0;
float r = 0, tr = 0;
mostcat.Clear();
mostpr.Clear();
try
{
SQL & Select(PM, SqlSum(VALUE))
.From(MONEY, DATES)
.Where(DT.Of(DATES) < month(DT) && DT_ID == ID.Of(DATES) && NotNull(VALUE))
.GroupBy(PM);
while(SQL.Fetch())
{
int pm = SQL[PM];
float v = (float) int(SQL[1]);
if(pm < 0)
tm = v;
else
tp = v;
}
tr = tp - tm;
SQL & Select(PM, SqlSum(VALUE))
.From(MONEY)
.Where(DT_ID == dtid && NotNull(VALUE))
.GroupBy(PM);
while(SQL.Fetch())
{
int pm = SQL[PM];
float v = (float) int(SQL[1]);
if(pm < 0)
m = v;
else
p = v;
}
SQL & Select(NAME, SqlId("sum(value) as val"))
.From(MONEY, CATEGORIES)
.Where(DT_ID == dtid && CAT_ID == ID.Of(CATEGORIES) && PM.Of(MONEY) < 0)
.GroupBy(CAT_ID)
.OrderBy(Descending(SqlId("val")));
while(SQL.Fetch())
mostpr.Add(SQL);
SQL & Select(NAME.Of(GROUPS), SqlId("sum(value) as val"))
.From(MONEY, GROUPS, CATEGORIES)
.Where(DT_ID == dtid && PM.Of(MONEY) < 0 && CAT_ID == ID.Of(CATEGORIES) && GR_ID == ID.Of(GROUPS))
.GroupBy(GR_ID)
.OrderBy(Descending(SqlId("val")));
while(SQL.Fetch())
mostcat.Add(SQL);
}
catch(SqlExc &e)
{
Exclamation("[* " + DeQtfLf(e) + "]");
}
r = p - m;
plus.SetText(Format("%.2f", p));
minus.SetText(Format("%.2f", m));
SetRest(rest, r);
SetRest(prev_month, tr);
SetRest(real_rest, r + tr);
}
void HomeBudget::ClearSummary()
{
plus.SetText("");
minus.SetText("");
rest.SetText("");
prev_month.SetText("");
real_rest.SetText("");
mostpr.Clear();
mostcat.Clear();
}
void HomeBudget::SetRest(StaticText &rest, float r)
{
if(r == 0)
{
rest.SetText("0.00");
rest.SetInk(Black);
}
else if(r > 0)
{
rest.SetText(Format("+%.2f", r));
rest.SetInk(Green);
}
else
{
rest.SetText(Format("%.2f", r));
rest.SetInk(LtRed);
}
}
void HomeBudget::UpdateValue()
{
if(money.IsEmpty())
return;
try
{
SQL & Select(DEFVALUE, PM).From(CATEGORIES).Where(ID == money.Get(CAT_ID));
Value v = SQL.Fetch() ? SQL[0] : Value(0);
Value s = SQL.Fetch() ? SQL[1] : Value(-1);
if(IsNull(money.Get(VALUE)))
money.Set(VALUE, v);
if(IsNull(money.Get(PM)))
money.Set(PM, s);
}
catch(SqlExc &e)
{
Exclamation("[* " + DeQtfLf(e) + "]");
}
}
void HomeBudget::Options()
{
WithOptionsLayout<TopWindow> dlg;
CtrlLayoutOK(dlg, t_("Options"));
dlg.lang.Add(0, "English")
.Add(1, "Česky")
.Add(2, "Polski")
.SetIndex(lang);
dlg.clear <<= THISBACK(ClearAll);
if(dlg.Execute() != IDOK)
return;
lang = ~dlg.lang;
}
void HomeBudget::ClearAll()
{
try
{
SQL & Delete(CATEGORIES);
SQL & Delete(GROUPS);
SQL & Delete(MONEY);
SQL & Delete(DATES);
//SQL.ExecuteX("VACUUM");
LoadDates();
LoadGroups();
UpdateCategories();
money.Clear();
categories.Clear();
EnableMoney();
PromptOK(t_("Database was cleared"));
}
catch(SqlExc &e)
{
Exclamation("[* " + DeQtfLf(e) + "]");
}
}
void HomeBudget::About()
{
WithAboutLayout<TopWindow> dlg;
CtrlLayoutCancel(dlg, t_("About"));
dlg.info.NoSb();
dlg.info.SetQTF(GetTopic(String("HomeBudget/src/About$") + (lang == 0 ? "en-us" : "pl-pl")), Zoom(150, 1400));
dlg.info.SetZoom(Zoom(1, 1));
dlg.Execute();
}
void HomeBudget::Help()
{
PromptOK(t_("No help available yet"));
/* HomeBudgetHelp dlg;
dlg.AddTree(0, Images::Plus(), "HomeBudget/help/Introduction$pl-pl", "Wprowadzenie");
dlg.AddTree(0, Images::Plus(), "HomeBudget/help/T0$pl-pl", "Instrukcja");
dlg.AddTree(0, Images::Plus(), "HomeBudget/src/About$pl-pl", "ala");
dlg.Execute();
*/
}
HomeBudgetHelp::HomeBudgetHelp()
{
}
Topic HomeBudgetHelp::AcquireTopic(const String& topic)
{
Topic t;
t = GetTopic(topic);
t.text = (const char *) GetTopic(topic);
//String path = topic;
//if(FileExists(path))
// t.text = ReadTopic(LoadFile(path)) .text;
return t;
}
GUI_APP_MAIN
{
bool nodb = false;
Sqlite3Session db;
db.LogErrors(true);
#ifdef flagDEBUG
db.SetTrace();
nodb = true;
#endif
FileIn fi("HomeBudget.db3");
if(fi.IsError() || fi.GetSize() <= 0)
nodb = true;
fi.Close();
if(!db.Open(ConfigFile("HomeBudget.db3")))
{
Exclamation(t_("Can't create or open database file"));
return;
}
SQL = db;
if(nodb)
{
SqlSchema sch(SQLITE3);
StdStatementExecutor se(db);
All_Tables(sch);
if(sch.ScriptChanged(SqlSchema::UPGRADE))
Sqlite3PerformScript(sch.Upgrade(), se);
if(sch.ScriptChanged(SqlSchema::ATTRIBUTES))
{
Sqlite3PerformScript(sch.Attributes(), se);
}
if(sch.ScriptChanged(SqlSchema::CONFIG))
{
Sqlite3PerformScript(sch.ConfigDrop(), se);
Sqlite3PerformScript(sch.Config(), se);
}
sch.SaveNormal();
}
HomeBudget hb;
LoadFromFile(hb);
switch(hb.lang) {
case 1:
SetLanguage(LNGC_('C','S','C','Z', CHARSET_UNICODE));
break;
case 2:
SetLanguage(LNGC_('P','L','P','L', CHARSET_UNICODE));
break;
default:
SetLanguage(LNGC_('E','N','U','S', CHARSET_UNICODE));
break;
}
hb.Setup();
hb.Run();
StoreToFile(hb);
}
HomeBudget.lay
LAYOUT(HomeBudgetLayout, 748, 400)
ITEM(Upp::GridCtrl, month, LeftPosZ(4, 124).VSizePosZ(4, 34))
ITEM(Upp::TabCtrl, tab, HSizePosZ(132, 2).VSizePosZ(4, 186))
ITEM(Upp::Button, about, SetLabel(t_("About")).LeftPosZ(4, 76).BottomPosZ(4, 26))
ITEM(Upp::Button, help, SetLabel(t_("Help")).LeftPosZ(84, 76).BottomPosZ(4, 26))
ITEM(Upp::Button, options, SetLabel(t_("Options")).LeftPosZ(164, 76).BottomPosZ(4, 26))
ITEM(Upp::Button, exit, SetLabel(t_("Exit")).RightPosZ(6, 76).BottomPosZ(4, 26))
ITEM(Upp::LabelBox, dv___6, SetLabel(t_("Summary")).HSizePosZ(132, 224).BottomPosZ(34, 148))
ITEM(Upp::StaticText, dv___7, SetText(t_("Income:")).SetFont(Upp::StdFontZ(18).Bold()).LeftPosZ(140, 88).BottomPosZ(144, 22))
ITEM(Upp::StaticText, plus, SetFont(Upp::StdFontZ(18).Bold()).HSizePosZ(232, 376).BottomPosZ(144, 22))
ITEM(Upp::StaticText, dv___9, SetText(t_("Spent:")).SetFont(Upp::StdFontZ(18).Bold()).LeftPosZ(140, 88).BottomPosZ(118, 24))
ITEM(Upp::StaticText, minus, SetFont(Upp::StdFontZ(18).Bold()).HSizePosZ(232, 376).BottomPosZ(120, 22))
ITEM(Upp::StaticText, rest_label, SetText(t_("Rest:")).SetFont(Upp::StdFontZ(18).Bold()).LeftPosZ(140, 88).BottomPosZ(96, 22))
ITEM(Upp::StaticText, rest, SetFont(Upp::StdFontZ(18).Bold()).HSizePosZ(232, 376).BottomPosZ(96, 22))
ITEM(Upp::StaticText, dv___13, SetText(t_("Amount from prev. month:")).SetFont(Upp::StdFontZ(18).Bold()).LeftPosZ(140, 268).BottomPosZ(72, 22))
ITEM(Upp::StaticText, prev_month, SetFont(Upp::StdFontZ(18).Bold()).HSizePosZ(412, 232).BottomPosZ(72, 22))
ITEM(Upp::StaticText, dv___15, SetText(t_("Final rest:")).SetFont(Upp::StdFontZ(18).Bold()).LeftPosZ(140, 268).BottomPosZ(48, 22))
ITEM(Upp::StaticText, real_rest, SetFont(Upp::StdFontZ(18).Bold()).HSizePosZ(412, 232).BottomPosZ(48, 22))
ITEM(Upp::LabelBox, dv___17, SetLabel(t_("Most expensive")).RightPosZ(4, 216).BottomPosZ(34, 148))
ITEM(Upp::TabCtrl, tabmost, RightPosZ(12, 200).BottomPosZ(42, 124))
END_LAYOUT
LAYOUT(OptionsLayout, 216, 86)
ITEM(Upp::StaticText, dv___0, SetText(t_("Language")).LeftPosZ(4, 60).TopPosZ(4, 18))
ITEM(Upp::DropList, lang, LeftPosZ(68, 144).TopPosZ(4, 19))
ITEM(Upp::Button, ok, SetLabel(t_("OK")).RightPosZ(4, 74).BottomPosZ(4, 24))
ITEM(Upp::Button, clear, SetLabel(t_("Clear all data from database")).RightPosZ(4, 208).BottomPosZ(34, 24))
END_LAYOUT
LAYOUT(AboutLayout, 456, 288)
ITEM(Upp::RichTextView, info, SetFrame(Upp::BlackFrame()).HSizePosZ(4, 4).TopPosZ(4, 252))
ITEM(Upp::Button, cancel, SetLabel(t_("OK")).HCenterPosZ(72, 0).TopPosZ(260, 24))
END_LAYOUT
LAYOUT(NewCategoryLayout, 244, 108)
ITEM(Upp::StaticText, dv___0, SetText(t_("Category")).LeftPosZ(4, 60).TopPosZ(4, 19))
ITEM(Upp::DropList, groups, LeftPosZ(68, 146).TopPosZ(4, 20))
ITEM(Upp::Button, addgroup, LeftPosZ(218, 20).TopPosZ(4, 20))
ITEM(Upp::StaticText, dv___3, SetText(t_("Name")).LeftPosZ(4, 60).TopPosZ(26, 19))
ITEM(Upp::EditString, name, LeftPosZ(68, 172).TopPosZ(26, 19))
ITEM(Upp::Switch, pm, SetLabel(t_("Plus\nMinus")).LeftPosZ(68, 100).TopPosZ(50, 15))
ITEM(Upp::Button, ok, SetLabel(t_("OK")).LeftPosZ(88, 74).TopPosZ(80, 24))
ITEM(Upp::Button, cancel, SetLabel(t_("Cancel")).LeftPosZ(166, 74).TopPosZ(80, 24))
END_LAYOUT
LAYOUT(NewGroupLayout, 204, 56)
ITEM(Upp::StaticText, dv___0, SetText(t_("Name")).LeftPosZ(4, 60).TopPosZ(4, 19))
ITEM(Upp::EditString, name, LeftPosZ(68, 130).TopPosZ(4, 19))
ITEM(Upp::Button, ok, SetLabel(t_("OK")).LeftPosZ(48, 74).TopPosZ(28, 24))
ITEM(Upp::Button, cancel, SetLabel(t_("Cancel")).LeftPosZ(126, 74).TopPosZ(28, 24))
END_LAYOUT
HomeBudget.sch
TABLE_(DATES)
INT_ (ID) PRIMARY_KEY
DATE_ (DT)
END_TABLE
TABLE_(GROUPS)
INT (ID) PRIMARY_KEY
STRING_ (NAME, 500)
END_TABLE
TABLE_(CATEGORIES)
INT (ID) PRIMARY_KEY
INT_ (GR_ID) INDEX
STRING (NAME, 500)
DOUBLE_ (DEFVALUE)
INT_ (PM)
INT_ (INNEWMONTH)
END_TABLE
TABLE_(MONEY)
INT (ID) PRIMARY_KEY
INT_ (DT_ID) INDEX
INT_ (CAT_ID) INDEX
INT (PM)
DOUBLE_ (VALUE)
DATE (DT)
STRING_ (DESC, 1024)
END_TABLE
|