commit ee8d4c0c8fff0e201b33fdea322a7f3ff1161e4a Author: Grégory Soutadé Date: Fri May 14 15:04:01 2010 +0200 Initial commit A good base to start working diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..72cdba9 --- /dev/null +++ b/Makefile @@ -0,0 +1,26 @@ +CXXFLAGS=`wx-config --cxxflags` -Wall -I. -ggdb +CXXFLAGS+=-I./lib/wxsqlite3-1.9.9/include +CXXFLAGS+=-I./lib/freechart/include + +LDFLAGS=`wx-config --libs` +LDFLAGS+=-L./lib/wxsqlite3-1.9.9/lib/ -lwxcode_gtk2u_wxsqlite3-2.8 +LDFLAGS+=-L./lib/freechart/lib -lwxcode_gtk2u_freechart-2.8 + +CXX=g++ + +SOURCES=$(wildcard model/*.cpp) +SOURCES+=$(wildcard view/*.cpp) +SOURCES+=$(wildcard controller/*.cpp) +SOURCES+=main.cpp sha1.cpp +HEADERS=$(wildcard model/*.h) +HEADERS+=$(wildcard view/*.h) +HEADERS+=$(wildcard controller/*.h) +HEADERS+=main.h sha1.h + +all: kc + +clean: + rm -f *.o + +kc: $(SOURCES) $(HEADERS) + $(CXX) $(CXXFLAGS) $(SOURCES) -o $@ $(LDFLAGS) \ No newline at end of file diff --git a/controller/KissCount.cpp b/controller/KissCount.cpp new file mode 100644 index 0000000..a806522 --- /dev/null +++ b/controller/KissCount.cpp @@ -0,0 +1,44 @@ +#include "KissCount.h" + +KissCount::KissCount() +{ + _wxUI = new wxUI(this, _("KissCount"), wxPoint(50, 50), wxSize(1024, 768)); + + _wxUI->Show(true); + _wxUI->Centre(); + _wxUI->Disable(); + + try + { + _db = new Database(); + } + catch (std::string s) + { + _wxUI->Close(true); + throw s; + } + + _wxUI->ChangeUser(); + _wxUI->Enable(); +} + +KissCount::~KissCount() +{ + delete _db; + delete _wxUI; +} + +std::list KissCount::GetUsers() +{ + return _db->GetUsers(); +} + +bool KissCount::IsValidUser(wxString user, wxString password) +{ + return _db->IsValidUser(user, password) ; +} + +void KissCount::LoadUser(wxString user) +{ + +} diff --git a/controller/KissCount.h b/controller/KissCount.h new file mode 100644 index 0000000..74166eb --- /dev/null +++ b/controller/KissCount.h @@ -0,0 +1,29 @@ +#ifndef KISSCOUNT_H +#define KISSCOUNT_H + +#include +#include +#include + +#include +#include +#include +#include + +class wxUI; +class KissCount +{ + public: + KissCount(); + ~KissCount(); + + std::list GetUsers(); + bool IsValidUser(wxString user, wxString password); + void LoadUser(wxString user); + + private: + wxUI* _wxUI; + Database* _db; +}; + +#endif diff --git a/init.sql b/init.sql new file mode 100644 index 0000000..dadb70c --- /dev/null +++ b/init.sql @@ -0,0 +1,10 @@ +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 CHAR(1)); +CREATE TABLE operation(id INTEGER PRIMARY KEY, account REFERENCES account(id), year INTEGER, month INTEGER, day INTEGER, description VARCHAR(255), category VARCHAR(255), fix_cost CHAR(1)); +CREATE TABLE preference(id INTEGER PRIMARY KEY, user REFERENCES user(id), type VARCHAR(255), name VARCHAR(255), value VARCHAR(255)); +CREATE TABLE default_preference(id INTEGER PRIMARY KEY, type VARCHAR(255), name VARCHAR(255), value VARCHAR(255)); +INSERT INTO default_preference ("type", "value") VALUES ("category", "Fixe"); +INSERT INTO default_preference ("type", "value") VALUES ("category", "Courses"); +INSERT INTO default_preference ("type", "value") VALUES ("category", "Loisirs"); +INSERT INTO default_preference ("type", "value") VALUES ("category", "Frais de fonctionnement"); +INSERT INTO default_preference ("type", "value") VALUES ("category", "Exceptionnel"); \ No newline at end of file diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..11d22b1 --- /dev/null +++ b/main.cpp @@ -0,0 +1,46 @@ +#include "main.h" + +class MyApp: public wxApp +{ + virtual bool OnInit() + { + try + { + new KissCount(); + } + catch (std::string s) + { + std::cerr << "Error " << s << "\n"; + return false; + } + + return true; + } +}; + +IMPLEMENT_APP(MyApp); + +// bool MyApp::OnInit() +// { +// Main app; + +// MyFrame *frame = new MyFrame( _("Hello World"), wxPoint(50, 50), wxSize(1024, 768) ); +// AccountPanel* f = new AccountPanel(frame); +// frame->Show(true); +// SetTopWindow(frame); + +// frame->Centre(); +// frame->Disable(); + +// try +// { +// app.Init(); +// } +// catch (std::string s) +// { +// std::cout << "Error " << s << "\n"; +// frame->Close(true); +// } +// frame->Enable(); +// return true; +// } diff --git a/main.h b/main.h new file mode 100644 index 0000000..dad0173 --- /dev/null +++ b/main.h @@ -0,0 +1,7 @@ +#ifndef MAIN_H +#define MAIN_H + +#include +#include + +#endif diff --git a/model/Account.h b/model/Account.h new file mode 100644 index 0000000..42b60f0 --- /dev/null +++ b/model/Account.h @@ -0,0 +1,28 @@ +#ifndef ACCOUNT_H +#define ACCOUNT_H + +#include +#include + + +struct operation { + unsigned int day; + unsigned int month; + unsigned int year; + unsigned int amount; + std::string description; + std::string category; + bool fix_cost; +} ; + +class Account +{ +private: + std::string _name; + std::string _number; + std::map > > _operations; + bool _shared; + bool _default; +}; + +#endif diff --git a/model/Database.cpp b/model/Database.cpp new file mode 100644 index 0000000..2a34f74 --- /dev/null +++ b/model/Database.cpp @@ -0,0 +1,115 @@ +#include "Database.h" + + +Database::Database() +{ + std::ifstream bdd_file; + + bdd_file.open(BDD_FILE); + + if (!bdd_file) + { + CreateDatabase(); + } + else + _db.Open(_(BDD_FILE)); + + bdd_file.close(); +} + +void Database::CreateDatabase() +{ + std::ifstream init_script; + std::string line; + + wxMessageBox(_("No database found, creating a new one"), _("KissCount"), wxICON_EXCLAMATION | wxOK ); + + init_script.open(INIT_SCRIPT); + + if (!init_script) + { + wxMessageBox(_(INIT_SCRIPT " not found, aborting"), _("Error"), wxICON_ERROR | wxOK ); + throw "init.sql not found, aborting"; + } + + _db.Open(_(BDD_FILE)); + + do + { + getline(init_script, line); + if (!_db.CheckSyntax(line.data())) + { + std::cout << line << " is invalid !\n" ; + continue; + } + try + { + _db.ExecuteUpdate(line.data()); + } + catch (...) + { + wxMessageBox(_("Error creating original database"), _("Error"), wxICON_ERROR | wxOK ); + throw line; + } + } while (init_script); + + init_script.close(); +} + +std::list Database::GetUsers() +{ + std::list res; + + // Check whether value exists in table + wxSQLite3ResultSet set ; + try + { + set = _db.ExecuteQuery(wxT("SELECT name FROM user")); + } + catch (wxSQLite3Exception e) + { + std::cerr << e.GetMessage().mb_str() << "\n" ; + return res; + } + + while (set.NextRow()) + { + res.push_front(set.GetAsString(0)); + } + set.Finalize(); + + return res; +} + +bool Database::IsValidUser(wxString user, wxString password) + { + bool res; + blk_SHA_CTX sha_ctx; + unsigned char sha[20]; + wxString req, wxSHA; + wxSQLite3ResultSet set; + + blk_SHA1_Init(&sha_ctx); + blk_SHA1_Update(&sha_ctx, password.c_str(), password.Length()); + blk_SHA1_Final(sha, &sha_ctx); + + for(int i=0; i<20; i++) + wxSHA += wxString::Format(wxT("%02F"), (int)sha[i]); + req = _("SELECT name FROM user WHERE name='") + user + _("' AND password='") + wxSHA + _("'"); + + // Check whether value exists in table + try + { + set = _db.ExecuteQuery(req); + } + catch (wxSQLite3Exception e) + { + std::cerr << e.GetMessage().mb_str() << "\n" ; + return false; + } + + res = set.NextRow() ; + set.Finalize(); + + return res; +} diff --git a/model/Database.h b/model/Database.h new file mode 100644 index 0000000..78252ae --- /dev/null +++ b/model/Database.h @@ -0,0 +1,26 @@ +#ifndef DATABASE_H +#define DATABASE_H + +#include +#include +#include +#include +#include + +#define BDD_FILE "kc.bdd" +#define INIT_SCRIPT "init.sql" + +class Database +{ + public: + Database(); + + std::list GetUsers(); + bool IsValidUser(wxString user, wxString password); + private: + wxSQLite3Database _db; + + void CreateDatabase(); +}; + +#endif diff --git a/model/Preferences.h b/model/Preferences.h new file mode 100644 index 0000000..ada5868 --- /dev/null +++ b/model/Preferences.h @@ -0,0 +1,13 @@ +#ifndef PREFERENCES_H +#define PREFERENCES_H + +#include +#include + +class Preferences +{ +private: + std::map _colors; +}; + +#endif diff --git a/model/User.h b/model/User.h new file mode 100644 index 0000000..9a4db61 --- /dev/null +++ b/model/User.h @@ -0,0 +1,17 @@ +#ifndef USER_H +#define USER_H + +#include + +#include "Account.h" + +class User +{ +private: + unsigned int _id; + wxString _name; + wxString _password; + std::list _accounts; +}; + +#endif diff --git a/ressources/Clients-icon.png b/ressources/Clients-icon.png new file mode 100644 index 0000000..7f813f4 Binary files /dev/null and b/ressources/Clients-icon.png differ diff --git a/ressources/administrator-icon.png b/ressources/administrator-icon.png new file mode 100644 index 0000000..1c32321 Binary files /dev/null and b/ressources/administrator-icon.png differ diff --git a/ressources/chart-icon.png b/ressources/chart-icon.png new file mode 100644 index 0000000..3e7b386 Binary files /dev/null and b/ressources/chart-icon.png differ diff --git a/ressources/options-icon.png b/ressources/options-icon.png new file mode 100644 index 0000000..18c6f75 Binary files /dev/null and b/ressources/options-icon.png differ diff --git a/sha1.cpp b/sha1.cpp new file mode 100644 index 0000000..0b5f398 --- /dev/null +++ b/sha1.cpp @@ -0,0 +1,283 @@ +/* + * SHA1 routine optimized to do word accesses rather than byte accesses, + * and to avoid unnecessary copies into the context array. + * + * This was initially based on the Mozilla SHA1 implementation, although + * none of the original Mozilla code remains. + */ + +/* this is only to get definitions for memcpy(), ntohl() and htonl() */ +//#include "../git-compat-util.h" +#include +#include +#include "sha1.h" + +#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) + +/* + * Force usage of rol or ror by selecting the one with the smaller constant. + * It _can_ generate slightly smaller code (a constant of 1 is special), but + * perhaps more importantly it's possibly faster on any uarch that does a + * rotate with a loop. + */ + +#define SHA_ASM(op, x, n) ({ unsigned int __res; __asm__(op " %1,%0":"=r" (__res):"i" (n), "0" (x)); __res; }) +#define SHA_ROL(x,n) SHA_ASM("rol", x, n) +#define SHA_ROR(x,n) SHA_ASM("ror", x, n) + +#else + +#define SHA_ROT(X,l,r) (((X) << (l)) | ((X) >> (r))) +#define SHA_ROL(X,n) SHA_ROT(X,n,32-(n)) +#define SHA_ROR(X,n) SHA_ROT(X,32-(n),n) + +#endif + +/* + * If you have 32 registers or more, the compiler can (and should) + * try to change the array[] accesses into registers. However, on + * machines with less than ~25 registers, that won't really work, + * and at least gcc will make an unholy mess of it. + * + * So to avoid that mess which just slows things down, we force + * the stores to memory to actually happen (we might be better off + * with a 'W(t)=(val);asm("":"+m" (W(t))' there instead, as + * suggested by Artur Skawina - that will also make gcc unable to + * try to do the silly "optimize away loads" part because it won't + * see what the value will be). + * + * Ben Herrenschmidt reports that on PPC, the C version comes close + * to the optimized asm with this (ie on PPC you don't want that + * 'volatile', since there are lots of registers). + * + * On ARM we get the best code generation by forcing a full memory barrier + * between each SHA_ROUND, otherwise gcc happily get wild with spilling and + * the stack frame size simply explode and performance goes down the drain. + */ + +#if defined(__i386__) || defined(__x86_64__) + #define setW(x, val) (*(volatile unsigned int *)&W(x) = (val)) +#elif defined(__GNUC__) && defined(__arm__) + #define setW(x, val) do { W(x) = (val); __asm__("":::"memory"); } while (0) +#else + #define setW(x, val) (W(x) = (val)) +#endif + +/* + * Performance might be improved if the CPU architecture is OK with + * unaligned 32-bit loads and a fast ntohl() is available. + * Otherwise fall back to byte loads and shifts which is portable, + * and is faster on architectures with memory alignment issues. + */ + +#if defined(__i386__) || defined(__x86_64__) || \ + defined(__ppc__) || defined(__ppc64__) || \ + defined(__powerpc__) || defined(__powerpc64__) || \ + defined(__s390__) || defined(__s390x__) + +#define get_be32(p) ntohl(*(unsigned int *)(p)) +#define put_be32(p, v) do { *(unsigned int *)(p) = htonl(v); } while (0) + +#else + +#define get_be32(p) ( \ + (*((unsigned char *)(p) + 0) << 24) | \ + (*((unsigned char *)(p) + 1) << 16) | \ + (*((unsigned char *)(p) + 2) << 8) | \ + (*((unsigned char *)(p) + 3) << 0) ) +#define put_be32(p, v) do { \ + unsigned int __v = (v); \ + *((unsigned char *)(p) + 0) = __v >> 24; \ + *((unsigned char *)(p) + 1) = __v >> 16; \ + *((unsigned char *)(p) + 2) = __v >> 8; \ + *((unsigned char *)(p) + 3) = __v >> 0; } while (0) + +#endif + +/* This "rolls" over the 512-bit array */ +#define W(x) (array[(x)&15]) + +/* + * Where do we get the source from? The first 16 iterations get it from + * the input data, the next mix it from the 512-bit array. + */ +#define SHA_SRC(t) get_be32(data + t) +#define SHA_MIX(t) SHA_ROL(W(t+13) ^ W(t+8) ^ W(t+2) ^ W(t), 1) + +#define SHA_ROUND(t, input, fn, constant, A, B, C, D, E) do { \ + unsigned int TEMP = input(t); setW(t, TEMP); \ + E += TEMP + SHA_ROL(A,5) + (fn) + (constant); \ + B = SHA_ROR(B, 2); } while (0) + +#define T_0_15(t, A, B, C, D, E) SHA_ROUND(t, SHA_SRC, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E ) +#define T_16_19(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E ) +#define T_20_39(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (B^C^D) , 0x6ed9eba1, A, B, C, D, E ) +#define T_40_59(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, ((B&C)+(D&(B^C))) , 0x8f1bbcdc, A, B, C, D, E ) +#define T_60_79(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (B^C^D) , 0xca62c1d6, A, B, C, D, E ) + +static void blk_SHA1_Block(blk_SHA_CTX *ctx, const unsigned int *data) +{ + unsigned int A,B,C,D,E; + unsigned int array[16]; + + A = ctx->H[0]; + B = ctx->H[1]; + C = ctx->H[2]; + D = ctx->H[3]; + E = ctx->H[4]; + + /* Round 1 - iterations 0-16 take their input from 'data' */ + T_0_15( 0, A, B, C, D, E); + T_0_15( 1, E, A, B, C, D); + T_0_15( 2, D, E, A, B, C); + T_0_15( 3, C, D, E, A, B); + T_0_15( 4, B, C, D, E, A); + T_0_15( 5, A, B, C, D, E); + T_0_15( 6, E, A, B, C, D); + T_0_15( 7, D, E, A, B, C); + T_0_15( 8, C, D, E, A, B); + T_0_15( 9, B, C, D, E, A); + T_0_15(10, A, B, C, D, E); + T_0_15(11, E, A, B, C, D); + T_0_15(12, D, E, A, B, C); + T_0_15(13, C, D, E, A, B); + T_0_15(14, B, C, D, E, A); + T_0_15(15, A, B, C, D, E); + + /* Round 1 - tail. Input from 512-bit mixing array */ + T_16_19(16, E, A, B, C, D); + T_16_19(17, D, E, A, B, C); + T_16_19(18, C, D, E, A, B); + T_16_19(19, B, C, D, E, A); + + /* Round 2 */ + T_20_39(20, A, B, C, D, E); + T_20_39(21, E, A, B, C, D); + T_20_39(22, D, E, A, B, C); + T_20_39(23, C, D, E, A, B); + T_20_39(24, B, C, D, E, A); + T_20_39(25, A, B, C, D, E); + T_20_39(26, E, A, B, C, D); + T_20_39(27, D, E, A, B, C); + T_20_39(28, C, D, E, A, B); + T_20_39(29, B, C, D, E, A); + T_20_39(30, A, B, C, D, E); + T_20_39(31, E, A, B, C, D); + T_20_39(32, D, E, A, B, C); + T_20_39(33, C, D, E, A, B); + T_20_39(34, B, C, D, E, A); + T_20_39(35, A, B, C, D, E); + T_20_39(36, E, A, B, C, D); + T_20_39(37, D, E, A, B, C); + T_20_39(38, C, D, E, A, B); + T_20_39(39, B, C, D, E, A); + + /* Round 3 */ + T_40_59(40, A, B, C, D, E); + T_40_59(41, E, A, B, C, D); + T_40_59(42, D, E, A, B, C); + T_40_59(43, C, D, E, A, B); + T_40_59(44, B, C, D, E, A); + T_40_59(45, A, B, C, D, E); + T_40_59(46, E, A, B, C, D); + T_40_59(47, D, E, A, B, C); + T_40_59(48, C, D, E, A, B); + T_40_59(49, B, C, D, E, A); + T_40_59(50, A, B, C, D, E); + T_40_59(51, E, A, B, C, D); + T_40_59(52, D, E, A, B, C); + T_40_59(53, C, D, E, A, B); + T_40_59(54, B, C, D, E, A); + T_40_59(55, A, B, C, D, E); + T_40_59(56, E, A, B, C, D); + T_40_59(57, D, E, A, B, C); + T_40_59(58, C, D, E, A, B); + T_40_59(59, B, C, D, E, A); + + /* Round 4 */ + T_60_79(60, A, B, C, D, E); + T_60_79(61, E, A, B, C, D); + T_60_79(62, D, E, A, B, C); + T_60_79(63, C, D, E, A, B); + T_60_79(64, B, C, D, E, A); + T_60_79(65, A, B, C, D, E); + T_60_79(66, E, A, B, C, D); + T_60_79(67, D, E, A, B, C); + T_60_79(68, C, D, E, A, B); + T_60_79(69, B, C, D, E, A); + T_60_79(70, A, B, C, D, E); + T_60_79(71, E, A, B, C, D); + T_60_79(72, D, E, A, B, C); + T_60_79(73, C, D, E, A, B); + T_60_79(74, B, C, D, E, A); + T_60_79(75, A, B, C, D, E); + T_60_79(76, E, A, B, C, D); + T_60_79(77, D, E, A, B, C); + T_60_79(78, C, D, E, A, B); + T_60_79(79, B, C, D, E, A); + + ctx->H[0] += A; + ctx->H[1] += B; + ctx->H[2] += C; + ctx->H[3] += D; + ctx->H[4] += E; +} + +void blk_SHA1_Init(blk_SHA_CTX *ctx) +{ + ctx->size = 0; + + /* Initialize H with the magic constants (see FIPS180 for constants) */ + ctx->H[0] = 0x67452301; + ctx->H[1] = 0xefcdab89; + ctx->H[2] = 0x98badcfe; + ctx->H[3] = 0x10325476; + ctx->H[4] = 0xc3d2e1f0; +} + +void blk_SHA1_Update(blk_SHA_CTX *ctx, const void *data, unsigned long len) +{ + int lenW = ctx->size & 63; + + ctx->size += len; + + /* Read the data into W and process blocks as they get full */ + if (lenW) { + unsigned long left = 64 - lenW; + if (len < left) + left = len; + memcpy(lenW + (char *)ctx->W, data, left); + lenW = (lenW + left) & 63; + len -= left; + data = ((const char *)data + left); + if (lenW) + return; + blk_SHA1_Block(ctx, ctx->W); + } + while (len >= 64) { + blk_SHA1_Block(ctx, (const unsigned int*) data); + data = ((const char *)data + 64); + len -= 64; + } + if (len) + memcpy(ctx->W, data, len); +} + +void blk_SHA1_Final(unsigned char hashout[20], blk_SHA_CTX *ctx) +{ + static const unsigned char pad[64] = { 0x80 }; + unsigned int padlen[2]; + int i; + + /* Pad with a binary 1 (ie 0x80), then zeroes, then length */ + padlen[0] = htonl(ctx->size >> 29); + padlen[1] = htonl(ctx->size << 3); + + i = ctx->size & 63; + blk_SHA1_Update(ctx, pad, 1+ (63 & (55 - i))); + blk_SHA1_Update(ctx, padlen, 8); + + /* Output hash */ + for (i = 0; i < 5; i++) + put_be32(hashout + i*4, ctx->H[i]); +} diff --git a/sha1.h b/sha1.h new file mode 100644 index 0000000..b864df6 --- /dev/null +++ b/sha1.h @@ -0,0 +1,22 @@ +/* + * SHA1 routine optimized to do word accesses rather than byte accesses, + * and to avoid unnecessary copies into the context array. + * + * This was initially based on the Mozilla SHA1 implementation, although + * none of the original Mozilla code remains. + */ + +typedef struct { + unsigned long long size; + unsigned int H[5]; + unsigned int W[16]; +} blk_SHA_CTX; + +void blk_SHA1_Init(blk_SHA_CTX *ctx); +void blk_SHA1_Update(blk_SHA_CTX *ctx, const void *dataIn, unsigned long len); +void blk_SHA1_Final(unsigned char hashout[20], blk_SHA_CTX *ctx); + +#define git_SHA_CTX blk_SHA_CTX +#define git_SHA1_Init blk_SHA1_Init +#define git_SHA1_Update blk_SHA1_Update +#define git_SHA1_Final blk_SHA1_Final diff --git a/view/AccountPanel.cpp b/view/AccountPanel.cpp new file mode 100644 index 0000000..89c73f0 --- /dev/null +++ b/view/AccountPanel.cpp @@ -0,0 +1,21 @@ +#include "AccountPanel.h" + + +AccountPanel::AccountPanel(KissCount* kiss, wxUI *parent) : wxPanel(&(*parent)), _kiss(kiss), _wxUI(parent), _tree(this, -1), _grid(this, -1) +{ + wxBoxSizer *hbox = new wxBoxSizer(wxHORIZONTAL); + wxChartPanel* chart ; + SetSizer(hbox); + + _pie = new PiePlot(); + _grid.CreateGrid(10, 7); + + chart = new wxChartPanel(this); + chart->SetChart(new Chart(_pie, _("Cost repartition"))); + hbox->Add(&_tree, 0); + hbox->Add(&_grid, 0); + hbox->Add(chart, 0); + + Fit(); + SetMinSize(GetSize()); +} diff --git a/view/AccountPanel.h b/view/AccountPanel.h new file mode 100644 index 0000000..aa5e2f0 --- /dev/null +++ b/view/AccountPanel.h @@ -0,0 +1,30 @@ +#ifndef ACCOUNTPANEL_H +#define ACCOUNTPANEL_H + +#include +#include +#include +#include +#include + +#include +#include "wxUI.h" + +class wxUI; +class KissCount; + +class AccountPanel: public wxPanel +{ +public: + + AccountPanel(KissCount* kiss, wxUI *parent); + +private: + KissCount* _kiss; + wxUI* _wxUI; + wxTreeCtrl _tree; + wxGrid _grid; + PiePlot* _pie; +}; + +#endif diff --git a/view/ButtonPanel.cpp b/view/ButtonPanel.cpp new file mode 100644 index 0000000..8337bf2 --- /dev/null +++ b/view/ButtonPanel.cpp @@ -0,0 +1,39 @@ +#include "ButtonPanel.h" + +enum {ID_BUTTON_ACCOUNT=1, ID_BUTTON_STATS, ID_BUTTON_PREFS, ID_BUTTON_CHANGE_USER}; + +BEGIN_EVENT_TABLE(ButtonPanel, wxPanel) +EVT_BUTTON(ID_BUTTON_CHANGE_USER, ButtonPanel::OnChangeUser) +END_EVENT_TABLE() + +ButtonPanel::ButtonPanel(KissCount* kiss, wxUI *parent) : wxPanel(&(*parent)), _kiss(kiss), _wxUI(parent) +{ + wxBoxSizer *hbox = new wxBoxSizer(wxHORIZONTAL); + _account = new wxBitmapButton(this, ID_BUTTON_ACCOUNT, wxBitmap(_(ACCOUNT_ICON))); + _stats = new wxBitmapButton(this, ID_BUTTON_STATS, wxBitmap(_(STATS_ICON))); + _prefs = new wxBitmapButton(this, ID_BUTTON_PREFS, wxBitmap(_(PREFS_ICON))); + _changeUser = new wxBitmapButton(this, ID_BUTTON_CHANGE_USER, wxBitmap(_(CHANGE_USER_ICON))); + + SetSizer(hbox); + + hbox->Add(_account); + hbox->Add(_stats); + hbox->Add(_prefs); + hbox->Add(_changeUser); + + Fit(); + SetMinSize(GetSize()); +} + +ButtonPanel::~ButtonPanel() +{ + delete _account; + delete _stats; + delete _prefs; + delete _changeUser; +} + +void ButtonPanel::OnChangeUser(wxCommandEvent& event) +{ + _wxUI->ChangeUser(); +} diff --git a/view/ButtonPanel.h b/view/ButtonPanel.h new file mode 100644 index 0000000..822c39e --- /dev/null +++ b/view/ButtonPanel.h @@ -0,0 +1,38 @@ +#ifndef BUTTONPANEL_H +#define BUTTONPANEL_H + +#include +#include + +#include +#include "wxUI.h" + +#define ACCOUNT_ICON "ressources/administrator-icon.png" +#define STATS_ICON "ressources/chart-icon.png" +#define PREFS_ICON "ressources/options-icon.png" +#define CHANGE_USER_ICON "ressources/Clients-icon.png" + +class KissCount; +class wxUI; + +class ButtonPanel: public wxPanel +{ +public: + + ButtonPanel(KissCount* kiss, wxUI *parent); + ~ButtonPanel(); + + void OnChangeUser(wxCommandEvent& event); + +private: + KissCount* _kiss; + wxUI* _wxUI; + wxBitmapButton* _account; + wxBitmapButton* _stats; + wxBitmapButton* _prefs; + wxBitmapButton* _changeUser; + + DECLARE_EVENT_TABLE(); +}; + +#endif diff --git a/view/UsersDialog.cpp b/view/UsersDialog.cpp new file mode 100644 index 0000000..78895ba --- /dev/null +++ b/view/UsersDialog.cpp @@ -0,0 +1,73 @@ +#include "UsersDialog.h" + +enum {ID_BUTTON_OK=1, ID_BUTTON_CANCEL}; + +BEGIN_EVENT_TABLE(UsersDialog, wxDialog) +EVT_BUTTON(ID_BUTTON_OK, UsersDialog::OnOK) +EVT_BUTTON(ID_BUTTON_CANCEL, UsersDialog::OnCancel) +END_EVENT_TABLE() + +UsersDialog::UsersDialog(KissCount* kiss, wxUI *parent) : wxDialog(&(*parent), -1, _("Users")), _kiss(kiss), _wxUI(parent) +{ + wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL); + wxBoxSizer *hbox = new wxBoxSizer(wxHORIZONTAL); + wxBoxSizer *vbox1 = new wxBoxSizer(wxVERTICAL); + wxBoxSizer *hbox1 = new wxBoxSizer(wxHORIZONTAL); + + _users = new wxChoice(this, wxID_ANY); + _password = new wxTextCtrl(this, wxID_ANY); + + _password->SetWindowStyle(wxTE_PASSWORD); + + wxButton* ok = new wxButton(this, ID_BUTTON_OK, _("OK")); + wxButton* cancel = new wxButton(this, ID_BUTTON_CANCEL, _("Cancel")); + + std::list users_list = _kiss->GetUsers(); + + for(std::list::iterator i = users_list.begin(); i != users_list.end(); i++) + { + _users->Append(*i); + } + + vbox1->Add(_users); + vbox1->Add(-1, 10); + vbox1->Add(_password); + hbox->Add(vbox1, 0, wxEXPAND, 10); + + hbox1->Add(ok); + hbox1->Add(-1, 10); + hbox1->Add(cancel); + + vbox->Add(hbox, 0, wxALIGN_RIGHT | wxRIGHT | wxTOP, 10); + vbox->Add(-1, 40); + vbox->Add(hbox1, 0, wxALIGN_RIGHT | wxRIGHT | wxBOTTOM, 10); + + Center(); + SetSizer(vbox); + + Layout(); +} + +void UsersDialog::OnOK(wxCommandEvent& event) +{ + // No users in database + if (!_users->GetStringSelection().Length()) + { + Close(); + } + + if (!_kiss->IsValidUser(_users->GetStringSelection(), _password->GetLineText(0))) + { + wxMessageBox(_("Invalid password"), _("Error"), wxICON_ERROR | wxOK ); + } + else + { + _kiss->LoadUser(_users->GetStringSelection()); + Close(); + } +} + +void UsersDialog::OnCancel(wxCommandEvent& event) +{ + Close(); +} diff --git a/view/UsersDialog.h b/view/UsersDialog.h new file mode 100644 index 0000000..97bab8e --- /dev/null +++ b/view/UsersDialog.h @@ -0,0 +1,32 @@ +#ifndef USERSDIALOG_H +#define USERSDIALOG_H + +#include + +#include +#include +#include +#include +#include "wxUI.h" + +class wxUI; +class KissCount; + +class UsersDialog : public wxDialog +{ +public: + UsersDialog(KissCount* kiss, wxUI *parent); + + void OnOK(wxCommandEvent& event); + void OnCancel(wxCommandEvent& event); + +private: + KissCount* _kiss; + wxUI* _wxUI; + wxChoice* _users; + wxTextCtrl* _password; + +DECLARE_EVENT_TABLE() + +}; +#endif diff --git a/view/wxUI.cpp b/view/wxUI.cpp new file mode 100644 index 0000000..cf005b9 --- /dev/null +++ b/view/wxUI.cpp @@ -0,0 +1,65 @@ +#include "wxUI.h" + +BEGIN_EVENT_TABLE(wxUI, wxFrame) + EVT_MENU(ID_Quit, wxUI::OnQuit) + EVT_MENU(ID_About, wxUI::OnAbout) +END_EVENT_TABLE() + +wxUI::wxUI(KissCount* kiss, const wxString& title, const wxPoint& pos, const wxSize& size) + : wxFrame(NULL, -1, title, pos, size), _kiss(kiss) +{ + _hbox = new wxBoxSizer(wxVERTICAL); + ButtonPanel* buttons = new ButtonPanel(_kiss, this); + wxMenu *menuFile = new wxMenu; + + menuFile->Append( ID_About, _("&About...") ); + menuFile->AppendSeparator(); + menuFile->Append( ID_Quit, _("E&xit") ); + + wxMenuBar *menuBar = new wxMenuBar; + menuBar->Append( menuFile, _("&File") ); + + SetMenuBar( menuBar ); + + CreateStatusBar(); + SetStatusText( _("Welcome to wxWidgets!") ); + + SetSizer(_hbox); + + _hbox->Add(buttons); +} + +wxUI::~wxUI() +{ + if (_accountPanel) delete _accountPanel; +} + +void wxUI::OnQuit(wxCommandEvent& WXUNUSED(event)) +{ + Close(true); +} + +void wxUI::OnAbout(wxCommandEvent& WXUNUSED(event)) +{ + wxMessageBox( _("This is a wxWidgets Hello world sample"), + _("About Hello World"), + wxOK | wxICON_INFORMATION, this ); +} + +void wxUI::ChangeUser() +{ + UsersDialog u(_kiss, this); + u.ShowModal(); +} + +void wxUI::LoadUser() +{ + if (_accountPanel) + { + _hbox->Detach(_accountPanel); + delete _accountPanel; + } + _accountPanel = new AccountPanel(_kiss, this); + _hbox->Add(_accountPanel); + Layout(); +} diff --git a/view/wxUI.h b/view/wxUI.h new file mode 100644 index 0000000..853d0cd --- /dev/null +++ b/view/wxUI.h @@ -0,0 +1,39 @@ +#ifndef WXUI_H +#define WXUI_H + +#include +#include "AccountPanel.h" +#include "ButtonPanel.h" +#include "UsersDialog.h" +#include + +class KissCount; +class AccountPanel; + +class wxUI: public wxFrame +{ +public: + + wxUI(KissCount* kiss, const wxString& title, const wxPoint& pos, const wxSize& size); + ~wxUI(); + + void OnQuit(wxCommandEvent& event); + void OnAbout(wxCommandEvent& event); + + void ChangeUser(); + void LoadUser(); + DECLARE_EVENT_TABLE(); + +private: + wxBoxSizer *_hbox; + AccountPanel *_accountPanel; + KissCount *_kiss; +}; + +enum +{ + ID_Quit = 1, + ID_About, +}; + +#endif