From dbe576e47035109c70b760ccb547bf6e54b8c9ef Mon Sep 17 00:00:00 2001 From: Marek Malevic Date: Mon, 9 Apr 2007 19:48:03 +0200 Subject: [PATCH] *sqlite engine wrapper changed *register db dialog done *stdoutput can show message boxes *unregister db done *actions checking done *db connecting/disconnecting done *object model tree in progress Signed-off-by: Marek Malevic --- icons/action_connect_db.png | Bin 0 -> 1167 bytes icons/action_disconnect_db.png | Bin 0 -> 1086 bytes icons/{exit.png => action_exit.png} | Bin icons/action_register_db.png | Bin 0 -> 724 bytes icons/action_unregister_db.png | Bin 0 -> 729 bytes icons/icons.qrc | 10 +- icons/object_type_registered_db_connected.png | Bin 0 -> 650 bytes icons/object_type_registered_db_disconnected.png | Bin 0 -> 563 bytes icons/object_type_registered_relational_dbs.png | Bin 0 -> 1668 bytes icons/object_type_unknown.png | Bin 0 -> 374 bytes include/core/actions.h | 5 + include/core/appl.h | 13 +- include/core/database.h | 113 ++++++ include/core/glob.h | 47 +++ include/core/object_tree_model.h | 91 ++++- include/core/query.h | 133 ++++++ include/core/sqlengine.h | 128 ------ include/core/stdoutput.h | 8 +- include/core/utils.h | 18 + include/gui/{frm_main_ui.h => frm_main.h} | 58 ++- include/gui/frm_reg.h | 51 +++ include/gui/gui.h | 2 +- include/gui/w_object_tree.h | 33 +- sqool.pro | 15 +- src/core/appl.cpp | 424 +++++++++---------- src/core/database.cpp | 282 +++++++++++++ src/core/main.cpp | 7 +- src/core/object_tree_model.cpp | 336 +++++++++++++++ src/core/query.cpp | 496 +++++++++++++++++++++++ src/core/sqlengine.cpp | 270 ------------ src/core/stdoutput.cpp | 32 +- src/core/utils.cpp | 8 + src/gui/frm_main.cpp | 385 ++++++++++++++++++ src/gui/frm_main_ui.cpp | 180 -------- src/gui/frm_reg.cpp | 201 +++++++++ src/gui/w_object_tree.cpp | 136 +++++++ 36 files changed, 2640 insertions(+), 842 deletions(-) create mode 100644 icons/action_connect_db.png create mode 100644 icons/action_disconnect_db.png rename icons/{exit.png => action_exit.png} (100%) create mode 100644 icons/action_register_db.png create mode 100644 icons/action_unregister_db.png create mode 100644 icons/object_type_registered_db_connected.png create mode 100644 icons/object_type_registered_db_disconnected.png create mode 100644 icons/object_type_registered_relational_dbs.png create mode 100644 icons/object_type_unknown.png create mode 100644 include/core/database.h create mode 100644 include/core/glob.h create mode 100644 include/core/query.h delete mode 100644 include/core/sqlengine.h create mode 100644 include/core/utils.h rename include/gui/{frm_main_ui.h => frm_main.h} (89%) create mode 100644 include/gui/frm_reg.h rewrite src/core/appl.cpp (67%) create mode 100644 src/core/database.cpp create mode 100644 src/core/query.cpp delete mode 100644 src/core/sqlengine.cpp create mode 100644 src/core/utils.cpp create mode 100644 src/gui/frm_main.cpp delete mode 100644 src/gui/frm_main_ui.cpp create mode 100644 src/gui/frm_reg.cpp diff --git a/icons/action_connect_db.png b/icons/action_connect_db.png new file mode 100644 index 0000000000000000000000000000000000000000..dd788c040fbf5c05ca9c7c39c1928bc47451adce GIT binary patch literal 1167 zcwPaI1aSL_P)WFU8GbZ8({Xk{QrNlj4iWF>9@00Z+$L_t(o!_AjnOk712 z$A2^T&VImBb__T*sn|o*OnREVg&YYR^ zhyS>V^$Ip!bZQRoNO(Q6Q|bA#_CT+ZGJvLwPE;gRZu3uc09YJ_=*o=LqmOp$E!FM5 z1w%-NTfPLqpIw$;y}x}lDF984C7Q!G8Wzeruj@*ax&^707+nQ`Tr$>s>HXUt5w!<; zXd58wg7w!@XcVFovU{dA%4eDD~`oKDxdhZgw?)06o0%Q&Nhn{i?@5$7J(?k!o|*?@!3bJAQ2!x5wKs`^qokP>_6RVyX?cG6MJyk*b%_Hkx+qwWunqK6&lR;*E zp*3X#a|S2A$Y*G(ZgT*rv{LHN>|thw@uv`Z+RjD+j> z;mQd5lGD(Zrt`+LccMwb;8=iX>U;3|m(RP_4+G;>IP)4)^T01X#Tdr&OQCwN15HL( z{_)qNOnE|auaQ6dN>UHO&}3%JSf-xf9d&P1uAY_DVea(=cZ) z3=y6;uxIF;c*%*?lH8fL=B&c)?zrQ#-Y_=?y#VaaH*@T8Zj4N>V=8q3HLiYyh+k9u z*0l)kP^}%iZLxR~0`7A5rVb!Sp5@W~1@SlN)#-)rbC=z?y^)1}_NS3fI4Hz?W6#*jLj&y>XV`szc>t{2i_n%CjRg=v8pBsU7XZ_?U8?4xp73UoQ=z0Nv&{^5 hu7jMeO2z(n?O&$sCr5Frs0jc7002ovPDHLkV1f~BB((ql literal 0 HcwPel00001 diff --git a/icons/action_disconnect_db.png b/icons/action_disconnect_db.png new file mode 100644 index 0000000000000000000000000000000000000000..35a22fb72f51c4a7f3820d682981ba55d6dcc7ce GIT binary patch literal 1086 zcwPZM1i|}>P)WFU8GbZ8({Xk{QrNlj4iWF>9@00W{)L_t(o!_Ak^PaIVo zz(4Q%-kX{I0cD{D3T@M_TZxEh3{@hv+SbIsz@+wOy?gLv>cLafm_`#d9!%7W#&A*( z9;(vVSbCrklZLdWmZA{pmSQa+ur52h<6$Wa0?V?yL|-zQdGo&W{eI^AW8Qq>KOU-7 z!Tt+z9h<-Hmm+&V(jteCj|LS3^k0Z$bD8#NYU&z*7u$=mE@JYBUOJ0?F!uVm!pIFuDPNthhIN@xuomQHPI@u4~6^1Q1(D z`Y45v)8)qZ;0v!4C>@M^e=gYQWu>@^pyDLc+7u15Y_olQf3fJgDYlpu3z;-x+_H?{ z?0a`pnW6wXmqA&NOllUG1t8j(DB`ey@qy2l=kcSjVciHf&Yvw0ARnUu3DxGkU|ilko%n*fx9BPY4{@i?iUzQQUGD=t<%9C5MQBh=Y}_v-Vod#K7GP!^kdh0!;^ zW_Iw(`rn5D{NbCVPY=NL=SqIJk^o$Ll998YlbxU6TsXZ*_MOX+e7ZUSHhhp|?% zxzYoh&JcWZ2WYMwKr-Fj8~AbS>3w|+#`jbXFh7!mARlzMshRp`k0P#9NDom+G>mR( z#I`3;PGODVDpbMZ{oL|(ZRe9ba^^h(-zPga2Lb4C80A<{ifnR@(`)t#~J_V1FU#U$LbG}v!el{RKa(hRVc%(Tw-U>vCTCF5X{akCoGR2 zfY!0f0sPc&?0%^QQ(ISh35HzMsRm%GLI9OdslU^`Bu<~e?ARPag+rJ(x?$H~UV&2O z11JQg1jv!GpAtXwBC#V!P_m9vQP`(CaNq8N#3hsjC=ry>^ zupTxX$L4y-+|cl+MwG$sa&R7VkcL|*HItWL>J@(Z?i>pZZLvc=SEsk!84Z2g+!IPq z_uFvYGQhw8gjO~u`RhV+a_fipVPALr(I+ncT6S-Exo>|>-NKz&fKdHD^eUrk0dhz% zG5Cc7n2zqTJ;z4;YBi_IifW7gHSu!^&FO}%*#B<)196-36pezbQvd(}07*qoM6N<$ Ef)(!hN&o-= literal 0 HcwPel00001 diff --git a/icons/exit.png b/icons/action_exit.png similarity index 100% rename from icons/exit.png rename to icons/action_exit.png diff --git a/icons/action_register_db.png b/icons/action_register_db.png new file mode 100644 index 0000000000000000000000000000000000000000..01905e1c7a4679cc0576157caea1c329d94c579e GIT binary patch literal 724 zcwPb20xSKAP)sJ5(03CEi zSad^gZEa<4bO1wgWnpw>WFU8GbZ8({Xk{QrNlj4iWF>9@00KBkL_t(o!|hi=YZE~f z{@$AzHfc7{sLdftupts6J@jBjwAg6z?oG@e5HH^R1s*&I-s@FbJbIEUDMXA1(Thl_ z+R{TIrnHBaHr*gec043)vXb4@O>BC|gJI|GK4!jo?|VD%0Rt8~u3=#*AtX^cTrPg= zX1f!L@$~Gv?ioN~DFJ0yFPoL^Wf6{UD`|{LWq@U4h~|^kp&o!HM)Aul06^tjDt6`i z*OD&)h1|G^Sfv`NU|mWjSO&nVZBrKj-1e?kuUQ)(=0HK zh2QuZMrb5?=dq3){BjKkdoQ7TCYcb@GtAs4j=IW^#i#HMpiUBXVpJ=8zBXUYJxBcJ zLr)v&={~y((gFyM;`ja*0KkkUJp!h&@#*D}p1Ac0$_V)f&~T9k!v=@P0BNASwdQGm ze(FAy5o%D&08TIjGn(v>hJlvO|FmQ`68?V~0vG}qH~`n2xwkp)&|hCFpS%aM zGZ|!OGD8lW3=#+3{0vhY6N{}AZYkcRX5e8cS)_YBIm;yYBv&yBHp|HunG^cqR^^0*+Fwy*m=p zfDP8g&kFe`B(I{5<$zlS5P)WFU8GbZ8({Xk{QrNlj4iWF>9@00KQpL_t(o!|j*PYZE~f z$G`8*Om1@SB*MbeY;Aoe0s z@kgmr8iOtPgKpEN`^&>7O;)qpW)rDM28MYv@9n(L&YRhN1MG95y&9J1@ zIJ@w&Atww7?t@)0D#Ry z<0F%2Usn?WluKhGTdO*x4!BY(!BPjSHm4B)+&1R8PHp-5{q*(ETS zYv&(J_ja|31rVMMQaT`Y)Yn%507kA56EGjkFCXmm^A~PFX&Jnqy^{;J52R4TR zsli%ZjI}>}>ME3$2~LQRy{*8XFa#r4=x_}6R-e0?a<@(R_sala05AX;0PH)!&Ue$g zoDTo|XPScDs8&e*^Y+R90ssIei+g)&e)c~MLBHRuYXIX(EtG#PJl1^>!r5+nR@_Y4 zh+4@T{Vufhi9$eN5HUamB5KIN7!d>9NftrNjY=XJz(#6l!eh32UE+67ZzTgbUHtlX zOBzLYv!z7KqOb{9ByCO>gyixTJEFG{1PLC$qe$ZIK?DhQ>AQnB{ik&qfZuwQxg zkO1I^aYUWFxajoja!QJ6+)%0W`1WZg%Fa4CcGR}(D^XXmf3Exjs)dQo2%hmm00000 LNkvXXu0mjf3jIHt literal 0 HcwPel00001 diff --git a/icons/icons.qrc b/icons/icons.qrc index ef2683d..a38e978 100644 --- a/icons/icons.qrc +++ b/icons/icons.qrc @@ -1,5 +1,13 @@ - exit.png + action_connect_db.png + action_disconnect_db.png + action_exit.png + action_register_db.png + action_unregister_db.png + object_type_unknown.png + object_type_registered_db_connected.png + object_type_registered_db_disconnected.png + object_type_registered_relational_dbs.png \ No newline at end of file diff --git a/icons/object_type_registered_db_connected.png b/icons/object_type_registered_db_connected.png new file mode 100644 index 0000000000000000000000000000000000000000..f0e573f9c5e3c341d71442ee79d61750675e738a GIT binary patch literal 650 zcwPaD0(Jd~P)WFU8GbZ8({Xk{QrNlj4iWF>9@00HhvL_t(o!|j*7P8&fG z$Nw|C%bn%p<4EL!B#2lL#H7S)~X@XUY(+&XKa#mPhYD9$6nL=AXvJ-$^DY+m5!xLfO_u0$0&?I#J^P=wb zu^fDb?)fJZLIyrF-?D$W?s=eI1}ST-fa)KxG(tJw&%VFXCJ;b)Rgf}Kb;n5{(!lTIe4zcK>DN$3+|LjpdyByTFa#?x z-X;yr=AN&0kk&p&Fur7Z2NC0qZJyvrs^6pJFr=*xt k*018XE}GMht=PRA7nebDO`MuwyZ`_I07*qoM6N<$f^!lO(*OVf literal 0 HcwPel00001 diff --git a/icons/object_type_registered_db_disconnected.png b/icons/object_type_registered_db_disconnected.png new file mode 100644 index 0000000000000000000000000000000000000000..f5bf3ae8f0966b1f3f08645357317049f766bfc1 GIT binary patch literal 563 zcwPZB0?hr1P)WFU8GbZ8({Xk{QrNlj4iWF>9@00EatL_t(o!|j*NYQjJi zh0mQcGZ93g0XJQCQ)pfI02O>J3F1nE4;3UE_d#g;2;E8PN+gr%rb&Njt;UKJav_VG zIWQl0<_`Brzu(6>L+>k$qKMA9d><`I700pPM=QH35JeFH+&Jg%0ifIMLTe3U3`oLS z3lV{}w#tj5z-qMu0CYN?%gJQ&R107{9@BfDlXS)yk_5?L0Z2kA1#2yq%Vk*+iR1XN zBkfAWRfDfQ{!M_svA>dLP+fQa0B?~g8Vk|b!i z+ZP7|%;)n5l6TIz+M6#H3-o%utLb$5T+5oh*|Uyw?xnP5#+Yi}v({GQS?QR(_dd%q z0RUr+nayT-ZEyGmL`Yt5x7)`(Cg~roSZ#n)#Vd6zYy0Sl8=(LI002ovPDHLkV1nr_ B=kEXj literal 0 HcwPel00001 diff --git a/icons/object_type_registered_relational_dbs.png b/icons/object_type_registered_relational_dbs.png new file mode 100644 index 0000000000000000000000000000000000000000..c24f0a3d8ef294b5569062104a0c74bfa05ba710 GIT binary patch literal 1668 zcwPa727CF5P)Va1`$a_ zK~z}7#aB&i6v-9-s``JL@z{6<#X=N?{lV48!Oe$4&@= zQVLNNK}rdw6r_}0W2F?7QV>EwO1bPf&WTc~^!GjjD=RC%2!g;}SXe+5MF0S;HI!1D zJ^>{2PLE?~tx+fxuz&ylk=51Jp8)750D!!C^9IFY5rmLrF%A%ajjN~Ok!fhP2ClTi z3M*nc+>0oR5^uNLUGtfl85}rpplj=U2|!ATFbvlvkRpG>XzBq5{VJRtS(xqsEO!8w zH-I+(2j(lE;l=Ft@$c~c1XN0y5Rp=%H|hHbD5W+eFrNJcrkw&c2m6xA%M|c~pADe! z-e>-^V#^8yK>$Js2q9gG zM4+LyLYvj0BY}uDAj~CD(*ZSY?8to&sp0SR5s*?s2!SvRHz%OA-cSJmpwxirq+xlP zt{gDEwJ~da4aQgk9D`S@Rk*JE?m4g>>mf}qA9xf+`28P8 z@$1R2@S`90AFWnx0gwMOi{E_0AVhyF)>=adv3&xamy5bk`0b4>EK}i^KVSHt#2R=x zW8sTgtLvW7n*&=SP%IX)XV0Ga_R{5@s(kv_d=flfD-^oFymMO#A()t$*t`_yayeYQ zcrmF1hGD=o&1ByBjIV8--EO0Cyp^2ujR`awjc2xPALE?EvaAHivaAHK(=E$N2=v~5 zVvn~mZg7k-CWLsIsM9IQvuDp}v)RmRw(TpW zQt2b#_c1p&7ruV|`lqI8D$nzz@B7iv&`^}kW}|dEtpMl_H5$i`9Shba5Zm?Z*U7zm z_l)`Zd51CPMN#A$hT&ble0jW7D*bqPc=&y-^{GOkP;gxrGcz-gQr>U3+Y7U^vtQi4 zef#t2>FH&|FqmaoY+zuZH9kJxK7IPMI&Z2uTucaBvWdi;GLAPM!Lo)oRr!rGahRf$O?r z_wL>8OP4N17cN}TN!{JMcdxcAOH)cUrBo6^Bmh;ZRF>xF=do+oF68rhIF19(If5WS z5Co{#>)@PYWn~4Nb9kPIe17dx`uzFxrVv5_kc1FPDb_-9;(Qx~^+@o(J2uK`BK#oklK~Lnf1f zZQE!x8hG*I#n-oP-MUvUmw#8U*T1rDyYBmbn9Jq(i4!N<4;C=wFCRU6 z^iRVu>YnGVj*gD9qeqX*bLY;fiHQkp*y%R&YuB!kv9U2bo6YV>r_(!Asnl-I^9ru( zzUO(~i0}KkOeT{V85!{oA3khOO-*enF8P0c&+pv1L*nXr{P^*A3iMy;<-`Cp|Ew<>&kweS&mCaN{RdLE})QXiEBiObAE1aYF-J0b5UwyNotBh zd1gt5LP$ocg1e`0!21-{JfOl`o-U3d5r^MSUC6~0DB#-P?dkYN?BK76gZUr0-$ZR) zbx_4ejCHpCqO(~B5pw#!c*QO*T5xoOO+-QY&AUd+&!#5m8H=-txCTy{wDQm86qP>} zm)LhOhd*G*nR_EzirJCvG4BF)9mZ^x9P!Kp%URcaGAUqO<{-X;(br+myt+Kej+3su z6)sDb3rFjJVo6?aCq9i)`61H{mnGlzdpcJxli0`hOzNg6_EfDuzhpwX$oDC8Zg_<;JKmHIVD9?Fx;sVZ@cnC*(Li4^ Nc)I$ztaD0e0s!~gi0c3V literal 0 HcwPel00001 diff --git a/include/core/actions.h b/include/core/actions.h index d785bb1..af41a26 100644 --- a/include/core/actions.h +++ b/include/core/actions.h @@ -14,4 +14,9 @@ QAction *actExit; +QAction *actRegisterDB; +QAction *actUnRegisterDB; +QAction *actConnectDB; +QAction *actDisConnectDB; + #endif diff --git a/include/core/appl.h b/include/core/appl.h index 4490cd5..9927597 100644 --- a/include/core/appl.h +++ b/include/core/appl.h @@ -2,7 +2,7 @@ /*! @author Marek Malevic - @brief General application constants and functions + @brief General application functions @date 2006-2007 */ @@ -10,15 +10,6 @@ #ifndef H_APPL #define H_APPL -#define APP_NAME "Sqool" -#define APP_VERSION "0.0.0" - -#define APP_CONFIG_PATH "sqool" - -/* Global sqool constants */ -#define CONST_OK 0 -#define CONST_ERROR -1 - /* it's a Qt application */ #include @@ -37,6 +28,6 @@ const int configGetValue(const std::string name, const int default_value); /* Sets the configuration value. If succesfull returns CONST_OK*/ const int configSetValue(const std::string name, const std::string value); -const int configSetValue(const std::string name, const int value); +const int configSetValue(const std::string name, const int value); #endif diff --git a/include/core/database.h b/include/core/database.h new file mode 100644 index 0000000..1502670 --- /dev/null +++ b/include/core/database.h @@ -0,0 +1,113 @@ +#ifndef _DATABASE_H_SQLITE +#define _DATABASE_H_SQLITE + +#include +#include +#include +#include +#include + +#ifdef SQLITEW_NAMESPACE +namespace SQLITEW_NAMESPACE { +#endif + + +class classQuery; +class Mutex; + + +/** Connection information and pool. */ +class classDatabase +{ +public: + /** Mutex container class, used by Lock. + \ingroup threading */ + class Mutex { + public: + Mutex(); + ~Mutex(); + void Lock(); + void Unlock(); + private: + pthread_mutex_t m_mutex; + }; +private: + /** Mutex helper class. */ + class Lock { + public: + Lock(Mutex& mutex,bool use); + ~Lock(); + private: + Mutex& m_mutex; + bool m_b_use; + }; +public: + /** Connection pool struct. */ + struct OPENDB { + OPENDB() : busy(false) {} + sqlite3 *db; + bool busy; + }; + typedef std::list opendb_v; + +public: + /** Use file */ + classDatabase(const std::string& database); + + /** Use file + thread safe */ + classDatabase(Mutex& ,const std::string& database); + + virtual ~classDatabase(); + + /** try to establish connection with given host */ + bool Connected(); + + void error(classQuery&,const char *format, ...); + void error(classQuery&,const std::string& ); + + /** Request a database connection. +The "grabdb" method is used by the classQuery class, so that each object instance of classQuery gets a unique +database connection. I will reimplement your connection check logic in the classQuery class, as that's where +the database connection is really used. +It should be used something like this. +{ + classQuery q(db); + if (!q.Connected()) + return false; + q.execute("delete * from user"); // well maybe not +} + +When the classQuery object is deleted, then "freedb" is called - the database connection stays open in the +m_opendbs vector. New classQuery objects can then reuse old connections. + */ + OPENDB *grabdb(); + void freedb(OPENDB *odb); + + /** Escape string - change all ' to ''. */ + std::string safestr(const std::string& ); + /** Make string xml safe. */ + std::string xmlsafestr(const std::string& ); + + /** Convert string to 64-bit integer. */ + int64_t a2bigint(const std::string& ); + /** Convert string to unsigned 64-bit integer. */ + uint64_t a2ubigint(const std::string& ); + +private: + classDatabase(const classDatabase& ) : m_mutex(m_mutex) {} + classDatabase& operator=(const classDatabase& ) { return *this; } + void error(const char *format, ...); + // + std::string database; + opendb_v m_opendbs; + bool m_embedded; + Mutex& m_mutex; + bool m_b_use_mutex; +}; + + +#ifdef SQLITEW_NAMESPACE +} // namespace SQLITEW_NAMESPACE { +#endif + +#endif // _DATABASE_H diff --git a/include/core/glob.h b/include/core/glob.h new file mode 100644 index 0000000..74f9ada --- /dev/null +++ b/include/core/glob.h @@ -0,0 +1,47 @@ +// License: GPL 2 - se the COPYING file in the root directory + +/*! + @author Marek Malevic + @brief General application constants + @date 2007 +*/ + + +#ifndef H_GLOB +#define H_GLOB + +#define APP_NAME "Sqool" +#define APP_VERSION "0.0.0" + +#define APP_CONFIG_PATH "sqool" + +/* Global sqool constants */ +#define CONST_OK 0 +#define CONST_ERROR -1 + +/* tree object types */ + + /* relational db root */ +#define IT_ROOT_DB 1000 + 0x001 + /* reserved for sqlite olap system */ +#define IT_ROOT_OLAP 1000 + 0x002 + /* relational db */ +#define IT_DB 1000 + 0x011 + +#define NOT_EXPANDED 0 +#define EXPANDED 1 +#define NOT_CONNECTED 0 +#define CONNECTED 1 + + +/* database types */ +#define DT_NONE 0 +#define DT_DB 1 +#define DT_OLAP 2 + +/* DB registration results */ +#define RDB_OK CONST_OK +#define RDB_DB_REGISTERED 3 +#define RDB_TITLE_USED 4 + +#endif diff --git a/include/core/object_tree_model.h b/include/core/object_tree_model.h index 7e362b2..c8fdaa8 100644 --- a/include/core/object_tree_model.h +++ b/include/core/object_tree_model.h @@ -11,14 +11,10 @@ #ifndef H_DBOBJECT_TREE_MODEL #define H_DBOBJECT_TREE_MODEL -#include "sqlengine.h" +#include +#include "database.h" +#include "query.h" -typedef enum { -/* relational db root */ - IT_ROOT_DB = 0x001, -/* reserved for sqlite olap system */ - IT_ROOT_OLAP = 0x002 -} ITEM_TYPE ; class classDBObjectTreeModel { @@ -35,11 +31,88 @@ class classDBObjectTreeModel */ virtual ~classDBObjectTreeModel(); + + /*! + returns the list of object children ids sorted by name + */ + int getKids( + const int parent_id, + std::list &li, + classQuery &qdb + ); + + /*! + get the object info + @sa objectID() + */ + int objectInfo( + int object_id, uint &object_type, + int &parent_id, std::string &caption, + uint &expanded, int &db_type, std::string &parental_db, + classQuery &qdb + ); + + int + objectInfo( + int object_id, uint &object_type, + int &parent_id, std::string &caption, + uint &expanded, int &db_type, std::string &parental_db, + std::string &db_path, std::string &title, int &connected, + classQuery &qdb + ); + + /*! + Returns or sets the db connection state. + @sa objectInfo() + */ + int dbConnected( + int db_type, std::string db_path, classQuery &qdb + ); + int dbConnected( + const int i_connected, int db_type, std::string db_path, classQuery &qdb + ); + + /*! + registers the sqlite db + @sa unregisterDB + */ + int + registerDB( + std::string s_path, std::string s_title, + std::string &s_path_used, std::string &s_title_used, + const int db_type, classQuery &qdb + ); + + /*! + unregisters the sqlite db + @sa registerDB + */ + int + unregisterDB( + std::string s_path, const int db_type, classQuery &qdb + ); + private: + + /*! + adds an object to the model tree + */ + void addObject( + const uint object_type, const int parent_id, + const std::string caption, const uint expanded, + std::string parental_db, int db_type, classQuery &qdb + ); + /* void addObject(const uint object_type, const int parent_id, + const uint expanded,classQuery &qdb + ); +*/ /*! - memmory database for the model information + Gets the object id for given object type. + The first object's id of such type is returned. + If there is no such object, CONST_ERROR is returned. + @sa objectInfo() */ - classSqlengine *model_db; + int objectTypeToID( const uint object_type ,classQuery &qdb ); }; diff --git a/include/core/query.h b/include/core/query.h new file mode 100644 index 0000000..cd451ea --- /dev/null +++ b/include/core/query.h @@ -0,0 +1,133 @@ +#ifndef _QUERY_H_SQLITE +#define _QUERY_H_SQLITE + +#include +#include +#include + + +#ifdef SQLITEW_NAMESPACE +namespace SQLITEW_NAMESPACE { +#endif + + +/** SQL Statement execute / result. */ +class classQuery +{ +public: + /** Constructor accepting reference to database object. */ + classQuery(classDatabase& dbin); + /** Constructor accepting reference to database object + and query string to execute. */ + classQuery(classDatabase& dbin,const std::string& sql); + ~classQuery(); + + /** Check if database object is connectable. */ + bool Connected(); + /** Return reference to database object. */ + classDatabase& GetDatabase() const; + /** Return string containing last query executed. */ + const std::string& GetLastQuery(); + + /** execute() returns true if query is successful, + does not store result. */ + bool execute(const std::string& sql); + /** Execute query and store result. */ + sqlite3_stmt *get_result(const std::string& sql); + /** Free stored result, must be called after get_result() before calling + execute()/get_result() again. */ + void free_result(); + /** Fetch next result row. + \return false if there was no row to fetch (end of rows) */ + bool fetch_row(); + /** Get id of last insert. */ + sqlite_int64 insert_id(); + /** Returns 0 if there are no rows to fetch. */ + long num_rows(); + /** Last error string. */ + std::string GetError(); + /** Last error code. */ + int GetErrno(); + + /** Execute query and return first result as a string. */ + const char *get_string(const std::string& sql); + /** Execute query and return first result as a long integer. */ + long get_count(const std::string& sql); + /** Execute query and return first result as a double. */ + double get_num(const std::string& sql); + + /** Check if column x in current row is null. */ + bool is_null(int x); + + /** Return column named x as a string value. */ + const char *getstr(const std::string& x); + /** Return column x as a string value. */ + const char *getstr(int x); + /** Return next column as a string value - see rowcount. */ + const char *getstr(); + + /** Return column named x as a long integer. */ + long getval(const std::string& x); + /** Return column x as a long integer. */ + long getval(int x); + /** Return next column as a long integer - see rowcount. */ + long getval(); + + /** Return column named x as an unsigned long integer. */ + unsigned long getuval(const std::string& x); + /** Return column x as an unsigned long integer. */ + unsigned long getuval(int x); + /** Return next column as an unsigned long integer. */ + unsigned long getuval(); + + /** Return column named x as a 64-bit integer value. */ + int64_t getbigint(const std::string& x); + /** Return column x as a 64-bit integer value. */ + int64_t getbigint(int x); + /** Return next column as a 64-bit integer value. */ + int64_t getbigint(); + + /** Return column named x as an unsigned 64-bit integer value. */ + uint64_t getubigint(const std::string& x); + /** Return column x as an unsigned 64-bit integer value. */ + uint64_t getubigint(int x); + /** Return next column as an unsigned 64-bit integer value. */ + uint64_t getubigint(); + + /** Return column named x as a double. */ + double getnum(const std::string& x); + /** Return column x as a double. */ + double getnum(int x); + /** Return next column as a double. */ + double getnum(); + +private: + /** Hide the copy constructor. */ + classQuery(const classQuery& q) : m_db(q.GetDatabase()) {} + /** Hide the assignment operator. */ + classQuery& operator=(const classQuery& ) { return *this; } + /** Print current result to stdout. */ + void ViewRes(); + /** Print error to debug class. */ + void error(const std::string& ); + classDatabase& m_db; ///< Reference to database object + classDatabase::OPENDB *odb; ///< Connection pool handle + sqlite3_stmt *res; ///< Stored result + bool row; ///< true if fetch_row succeeded + short rowcount; ///< Current column pointer in result + std::string m_tmpstr; ///< Used to store result in get_string() call + std::string m_last_query; ///< Last query executed + int cache_rc; ///< Cached result after call to get_result() + bool cache_rc_valid; ///< Indicates cache_rc is valid + int m_row_count; ///< 0 if get_result() returned no rows + // + std::map m_nmap; ///< map translating column names to index + int m_num_cols; ///< number of columns in result +}; + + +#ifdef SQLITEW_NAMESPACE +} // namespace SQLITEW_NAMESPACE { +#endif + +#endif // _QUERY_H diff --git a/include/core/sqlengine.h b/include/core/sqlengine.h deleted file mode 100644 index f81bbd9..0000000 --- a/include/core/sqlengine.h +++ /dev/null @@ -1,128 +0,0 @@ -// License: GPL 2 - se the COPYING file in the root directory - -/*! - The class manages basic sql operations on the sqlite engine. - @author Marek Malevic - @brief The sqlite engine wrapper - @class classSqlengine - @date 2006-2007 -*/ - -#ifndef H_SQLENGINE -#define H_SQLENGINE - -#include -#include "sqlite3.h" -#include "stdoutput.h" - -#define SQLENGINE_TIMEOUT_MS 1000 - -class classSqlengine{ -public: - /*! - creates the db engine object - @param s_dbfile sqlite3 database file path - @sa ~classSqlengine() - */ - classSqlengine(std::string s_dbfile); - - /*! - destroys the db engine object - @sa classSqlengine(std::string s_dbfile) - */ - ~classSqlengine(); - - /*! - returns the state of the SQL engine - @return CONST_OK or CONST_ERROR if broken - @sa sql_setEngineState(int new_state), classSqlengine(std::string s_dbfile) and ~classSqlengine() - */ - int sql_getEngineState(); - - /*! - executes SQL code on active engine - @param s_sql SQL code to run - @return if successful returns CONST_OK else CONST_ERROR - @sa sql_getEngineState() and sql_getEngineState() - */ - int sql_execute(std::string s_sql); - - /*! - prepares the rowset and sets the cursor to the forst row if any - @param s_sql SQL code to run - @return if successful returns CONST_OK else CONST_ERROR - @sa sql_countFields() - */ - int sql_query(std::string s_sql); - - /*! - gets the number of columns from active resultset - @return if successful returns the number of columns else CONST_ERROR - @sa sql_query(std::string s_sql) - */ - int sql_countFields(); - - /*! - gets value of the column from the active row - @note resultset->row->column[nIndex].value - @param nIndex column index - @return if successful returns the field value else NULL - @sa sql_query(std::string s_sql), sql_countFields() and sql_getFieldValueText(std::string str_col) - */ - std::string - sql_getFieldValueText(uint nIndex); - - /*! - gets value of the column from the active row - @note resultset->row->column[str_col].value - @param str_col column name - @return if successful returns the field value else NULL - @sa sql_query(std::string s_sql), sql_countFields() and sql_getFieldValueText(uint nIndex) - */ - std::string - sql_getFieldValueText(std::string str_col); - - /*! - returns the column index according to its name - @param s_field column name - @return if successful returns CONST_OK else CONST_ERROR - @sa sql_query(std::string s_sql), sql_countFields() and sql_getFieldValueText(uint nIndex) - */ - int fieldIndex(std::string s_field); - - /*! - goes to the next row of the resultset - @return if successful returns CONST_OK else CONST_ERROR - @sa sql_getEof(), sql_query(std::string s_sql), sql_countFields() - */ - int sql_nextRow(); - - /*! - get the state of the EOF flag - @return if no other row in the resultset returns "true" - @sa sql_query(std::string s_sql), sql_countFields() and sql_nextRow() - */ - bool sql_getEof(); - -private: - /* contains the engine state - CONST_OK or CONST_ERROR if broken */ - int engine_state; - - /* just a wrapper for engine_state */ - void sql_setEngineState(int new_state); - - /* this step returns the error code directly - - inspired by the sqlite3 api documentation */ - int sqlite3_step_extended(sqlite3_stmt *virtualMachine); - - /* contains the dbpath */ - std::string s_db; - sqlite3* db_handle; - /* result set */ - sqlite3_stmt* virtualMachine; - /* contains the eof flag for the result set */ - bool sql_eof; - -}; - -#endif diff --git a/include/core/stdoutput.h b/include/core/stdoutput.h index a5d2324..396be98 100644 --- a/include/core/stdoutput.h +++ b/include/core/stdoutput.h @@ -60,7 +60,7 @@ public: Warning(std::string s_message), Info(std::string s_message) */ - void Advice(std::string s_message); + void Advice(std::string s_message, bool show_msgbox = 0); /*! sends a message to std::cerr if the verbosity mode is at least V_MODE_ERROR @@ -71,7 +71,7 @@ public: Advice(std::string s_message), Info(std::string s_message) */ - void Error(std::string s_message, int erro_code = 0); + void Error(std::string s_message, bool show_msgbox = 0); /*! sends a message to std::cout if the verbosity mode is at least V_MODE_INFO @@ -81,7 +81,7 @@ public: Warning(std::string s_message), Advice(std::string s_message), */ - void Info(std::string s_message); + void Info(std::string s_message, bool show_msgbox = 0); /*! sends a message to std::clog if the verbosity mode is at least V_MODE_WARNING @@ -91,7 +91,7 @@ public: Advice(std::string s_message), Info(std::string s_message) */ - void Warning(std::string s_message); + void Warning(std::string s_message, bool show_msgbox = 0); private: unsigned int verbosity_mode; diff --git a/include/core/utils.h b/include/core/utils.h new file mode 100644 index 0000000..a993e37 --- /dev/null +++ b/include/core/utils.h @@ -0,0 +1,18 @@ +// License: GPL 2 - se the COPYING file in the root directory + +/*! + @author Marek Malevic + @brief Useful not only conversion functions + @date 2007 +*/ + + +#ifndef H_UTILS +#define H_UTILS + +#include + +std::string toString(const int value); + + +#endif diff --git a/include/gui/frm_main_ui.h b/include/gui/frm_main.h similarity index 89% rename from include/gui/frm_main_ui.h rename to include/gui/frm_main.h index 67ce075..44bf321 100644 --- a/include/gui/frm_main_ui.h +++ b/include/gui/frm_main.h @@ -8,8 +8,8 @@ @date 2006 */ -#ifndef H_FRMMAIN_UI -#define H_FRMMAIN_UI +#ifndef H_FRMMAIN +#define H_FRMMAIN #include #include @@ -17,6 +17,7 @@ #include #include "w_tab_workplace.h" #include "w_object_tree.h" +#include "frm_reg.h" /* minimum window size */ #define FRMMAIN_UI_WMINW 640 @@ -40,6 +41,13 @@ class classMainForm : public QMainWindow virtual ~classMainForm(); /*! + Database object tree + @sa classDBObjectTree(); + */ + classDBObjectTree + *dbOTree; + + /*! gets the window state code @sa setWindowStateInt(); */ @@ -56,14 +64,6 @@ class classMainForm : public QMainWindow private: /*! - Database object tree - @sa classDBObjectTree(); - */ - classDBObjectTree - *dbOTree; - - - /*! Tabbed workplace (central widget) @sa classTabWorkplace(); */ @@ -87,12 +87,46 @@ class classMainForm : public QMainWindow Window main menu - File */ QMenu - *fileMenu; + *fileMenu; /*! Window main menu - Database */ QMenu - *databaseMenu; + *databaseMenu; + + /*! + Db registration dialog + */ + classRegForm *frmReg; + + public slots: + + /*! + Connects selected db + */ + void connectDb(); + + /*! + Disconnects selected db + */ + void disconnectDb(); + + /*! + Opens the register db dialog + */ + void registerDb(); + + /*! + Asks and unregisters the db + */ + void unregisterDb(); + + /*! + Enables/disables actions according + to the application state. + */ + void checkActions(); + }; #endif diff --git a/include/gui/frm_reg.h b/include/gui/frm_reg.h new file mode 100644 index 0000000..5acb133 --- /dev/null +++ b/include/gui/frm_reg.h @@ -0,0 +1,51 @@ +#ifndef H_FRMREG +#define H_FRMREG + +#include +#include +#include +#include +#include +#include +#include + +#define FRM_REG_WIDTH 600 +#define FRM_REG_HEIGHT 200 + +#define FRM_REG_SIZE_CONSTS_TOP 10 +#define FRM_REG_SIZE_CONSTS_LEFT 15 +#define FRM_REG_SIZE_CONSTS_BUTTON_WIDTH 90 + +//#include "configuration.h" + +class classRegForm : public QWidget +{ + Q_OBJECT + + public: + classRegForm(QWidget *parent = 0); + virtual ~classRegForm(); +/* + signals: + void signalReloadRegisteredDBs(); +*/ + private: + QFileDialog *file_dialog; + QPushButton *button_select_db; + QPushButton *button_ok; + QPushButton *button_cancel; + QLineEdit *db_path; + QLabel *path_label; + QLineEdit *db_title; + QLabel *title_label; + + void connectFileDialog(); + + private slots: + void fillPath(); + void regDBOK(); + void checkButtons(); + +}; + +#endif diff --git a/include/gui/gui.h b/include/gui/gui.h index db39b3d..20a98e1 100644 --- a/include/gui/gui.h +++ b/include/gui/gui.h @@ -6,6 +6,6 @@ #define H_GUI /* Main window */ -#include "frm_main_ui.h" +#include "frm_main.h" #endif diff --git a/include/gui/w_object_tree.h b/include/gui/w_object_tree.h index f3e7d15..6e62a26 100644 --- a/include/gui/w_object_tree.h +++ b/include/gui/w_object_tree.h @@ -31,9 +31,40 @@ class classDBObjectTree : public QTreeWidget */ virtual ~classDBObjectTree(); - private: + /*! + @sa classDBObjectTreeModel() + */ classDBObjectTreeModel *model; + + /*! + returns ID of the selected object + */ + int selectedObjectID(); + + /*! + redraws the tree according to the model object + @sa classDBObjectTree() + */ + int redrawTree(); + + + private: + + /*! + draw object + @param object_id model id of the object + @param parent object to draw the kid under + @param kid returns the kid object + */ + int drawObject(int object_id, QTreeWidgetItem *parent, QTreeWidgetItem *&kid,classQuery &qdb); + + /*! + draws all objects under the object_id object found in object model db + @param object_id model id of the starting object + @param parent object to draw the kids under + */ + int drawKids(int object_id, QTreeWidgetItem *parent,classQuery &qdb); }; diff --git a/sqool.pro b/sqool.pro index 97b1b04..85193cc 100644 --- a/sqool.pro +++ b/sqool.pro @@ -1,19 +1,26 @@ HEADERS += include/core/appl.h \ + include/core/glob.h \ + include/core/utils.h \ include/core/actions.h \ include/core/object_tree_model.h \ - include/core/sqlengine.h \ + include/core/database.h \ + include/core/query.h \ include/core/stdoutput.h \ - include/gui/frm_main_ui.h \ + include/gui/frm_main.h \ + include/gui/frm_reg.h \ include/gui/w_object_tree.h \ include/gui/w_tab_workplace.h \ include/gui/gui.h SOURCES += src/core/appl.cpp \ + src/core/utils.cpp \ src/core/main.cpp \ - src/core/sqlengine.cpp \ src/core/stdoutput.cpp \ src/core/object_tree_model.cpp \ - src/gui/frm_main_ui.cpp \ + src/core/database.cpp \ + src/core/query.cpp \ + src/gui/frm_main.cpp \ + src/gui/frm_reg.cpp \ src/gui/w_object_tree.cpp \ src/gui/w_tab_workplace.cpp diff --git a/src/core/appl.cpp b/src/core/appl.cpp dissimilarity index 67% index 79ab30f..c737d00 100644 --- a/src/core/appl.cpp +++ b/src/core/appl.cpp @@ -1,208 +1,216 @@ -/* - Author: Marek Malevic - License: GPL 2 -*/ - -#include -#include -#include -#include "../../include/core/appl.h" -#include "../../include/core/sqlengine.h" - -/* joins the standard output machine */ -extern classStdoutput::classStdoutput say; - -std::string - configurationFile() -{ - return QFSFileEngine::homePath().toStdString() + "/.config/" + APP_CONFIG_PATH + "/configuration"; -} - -const int - checkConfigurationPath() -{ - QDir fs; - QString qs_ConfigPath(QFSFileEngine::homePath() + "/.config/" + APP_CONFIG_PATH); - return fs.mkpath(qs_ConfigPath) ? CONST_OK : CONST_ERROR; -} - -const int - checkConfigurationStructure() -{ - - classSqlengine::classSqlengine cdb(configurationFile()); - - if (cdb.sql_getEngineState() == CONST_OK) { - - std::string s_sql = "" - "CREATE TABLE IF NOT EXISTS" - " t_config_records (" - " name TEXT PRIMARY KEY," - " value TEXT" - ")"; - if (cdb.sql_execute(s_sql) == CONST_OK){ - s_sql = "" - "CREATE TABLE IF NOT EXISTS" - " t_registered_dbs (" - " db_path TEXT PRIMARY KEY," - " title TEXT," - " connected INTEGER DEFAULT 0" - ")"; - if (cdb.sql_execute(s_sql) == CONST_OK) { - return CONST_OK; - } else { - say.Error("The db registrator table could not be created."); - return CONST_ERROR; - }; - } else { - say.Error("The configuration table could not be created."); - return CONST_ERROR; - }; - - } else { - return CONST_ERROR; - }; -} - - -/* Gets the configuration value. If there is no record it returns the default_value. */ -const std::string - configGetValue(const std::string name, const std::string default_value) -{ - - classSqlengine::classSqlengine cdb(configurationFile()); - - if (cdb.sql_getEngineState() == CONST_OK) { - - std::string s_sql = "" - "SELECT " - " value " - "FROM t_config_records " - "WHERE " - " name = '" + name + "'"; - if (cdb.sql_execute(s_sql) == CONST_OK){ - std::string s(cdb.sql_getEof() ? default_value : cdb.sql_getFieldValueText("value")); - say.Info(name + " is set to: " + s); - return s; - } else { - say.Warning("Cannot read from the configuration table."); - return default_value; - }; - - } else { - return default_value; - }; -} - -const int - configGetValue(const std::string name, const int default_value) -{ - - classSqlengine::classSqlengine cdb(configurationFile()); - - if (cdb.sql_getEngineState() == CONST_OK) { - - std::string s_sql = "" - "SELECT " - " value " - "FROM t_config_records " - "WHERE " - " name = '" + name + "'"; - //say.Info(s_sql); - if (cdb.sql_query(s_sql) == CONST_OK){ - - const int i = (cdb.sql_getEof() ? default_value : atoi(cdb.sql_getFieldValueText("value").c_str())); - std::stringstream s; - s << i; - if (cdb.sql_getEof()){ - say.Info(name + " is has been set to the default value: " + s.str()); - return i; - } else { - say.Info(name + " is has been set to: " + s.str()); - return i; - } - - } else { - say.Warning("Cannot read from the configuration table."); - return default_value; - }; - - } else { - say.Warning("Cannot read from the configuration table."); - return default_value; - }; -} - - -/* Sets the configuration value. If succesfull returns CONST_OK*/ -const int - configSetValue(const std::string name, const std::string value) -{ - classSqlengine::classSqlengine cdb(configurationFile()); - - if (cdb.sql_getEngineState() == CONST_OK) { - - std::string s_sql = "" - "DELETE " - "FROM t_config_records " - "WHERE " - " name = '" + name + "'"; - if (cdb.sql_execute(s_sql) == CONST_OK){ - s_sql = "INSERT INTO t_config_records VALUES ('" + name + "', '" + value + "')"; - if (cdb.sql_execute(s_sql) == CONST_OK){ - say.Info(name + " has been updated"); - return CONST_OK; - } else { - say.Warning("Cannot update the configuration table."); - return CONST_ERROR; - } - } else { - say.Warning("Cannot update the configuration table."); - return CONST_ERROR; - }; - - } else { - say.Warning("Cannot update the configuration table."); - return CONST_ERROR; - }; - - return CONST_OK; -} - -const int - configSetValue(const std::string name, const int value) -{ - classSqlengine::classSqlengine cdb(configurationFile()); - - if (cdb.sql_getEngineState() == CONST_OK) { - - std::string s_sql = "" - "DELETE " - "FROM t_config_records " - "WHERE " - " name = '" + name + "'"; - if (cdb.sql_execute(s_sql) == CONST_OK){ - std::stringstream s; - s << value; - s_sql = "INSERT INTO t_config_records VALUES ('" + name + "', '" + s.str() + "')"; - //say.Info(s_sql); - if (cdb.sql_execute(s_sql) == CONST_OK){ - say.Info(name + " has been updated"); - return CONST_OK; - } else { - say.Warning("Cannot update the configuration table."); - return CONST_ERROR; - } - } else { - say.Warning("Cannot update the configuration table."); - return CONST_ERROR; - }; - - } else { - say.Warning("Cannot update the configuration table."); - return CONST_ERROR; - }; - - return CONST_OK; -} - +/* + Author: Marek Malevic + License: GPL 2 +*/ + +#include +#include +#include +#include "../../include/core/appl.h" +#include "../../include/core/database.h" +#include "../../include/core/query.h" +#include "../../include/core/stdoutput.h" +#include "../../include/core/utils.h" +#include "../../include/core/glob.h" + +/* joins the standard output machine */ +extern classStdoutput::classStdoutput say; + +std::string + configurationFile() +{ + return QFSFileEngine::homePath().toStdString() + "/.config/" + APP_CONFIG_PATH + "/configuration_ng"; +} + +const int + checkConfigurationPath() +{ + QDir fs; + QString qs_ConfigPath(QFSFileEngine::homePath() + "/.config/" + APP_CONFIG_PATH); + return fs.mkpath(qs_ConfigPath) ? CONST_OK : CONST_ERROR; +} + +const int + checkConfigurationStructure() +{ + classDatabase cdb(configurationFile()); + + if (!cdb.Connected()) { + return CONST_ERROR; + }; + + classQuery qdb(cdb); + + std::string s_sql = "" + "CREATE TABLE IF NOT EXISTS" + " t_config_records (" + " name TEXT PRIMARY KEY," + " value TEXT" + ")"; + if (!qdb.execute(s_sql)) { + say.Error("The configuration table could not be created."); + return CONST_ERROR; + }; + + + s_sql = "" + "CREATE TABLE IF NOT EXISTS" + " t_registered_dbs (" + " db_path TEXT PRIMARY KEY," + " db_type INTEGER DEFAULT " + toString(DT_DB) + "," + " title TEXT," + " connected INTEGER DEFAULT 0" + ")"; + if (!qdb.execute(s_sql)) { + say.Error("The db registrator table could not be created."); + return CONST_ERROR; + }; + + + s_sql = "" + "CREATE TABLE IF NOT EXISTS" + " t_tree_model (" + " object_id INTEGER PRIMARY KEY AUTOINCREMENT," + " object_type INTEGER," + " parent_id INTEGER," + " parental_db TEXT," + " db_type INTEGER," + " caption TEXT," + " expanded INTEGER" + ")"; + if (!qdb.execute(s_sql)) { + say.Error("The object tree model table could not be created."); + return CONST_ERROR; + }; + + + s_sql = "SELECT COUNT(*) FROM t_tree_model WHERE object_type = " + toString(IT_ROOT_DB) + " "; + if (qdb.get_count(s_sql)==0) { + + s_sql = "" + "INSERT INTO " + " t_tree_model (" + " object_type," + " parent_id," + " expanded, " + " db_type " + ") VALUES ( " + toString(IT_ROOT_DB) + " " + ", -1, " + " " + toString(EXPANDED) + "," + " " + toString(DT_NONE) + " )"; + + if (!qdb.execute(s_sql)) { + say.Error("The initial model tree object record could not be inserted."); + return CONST_ERROR; + }; + }; + + return CONST_OK; + +} + + +/* Gets the configuration value. If there is no record it returns the default_value. */ +const std::string + configGetValue(const std::string name, const std::string default_value) +{ + std::string retval = default_value; + + classDatabase cdb(configurationFile()); + + if (cdb.Connected()) { + classQuery qdb(cdb); + + std::string s_sql = "" + "SELECT " + " value " + "FROM t_config_records " + "WHERE " + " name = '" + name + "'"; + + qdb.get_result(s_sql); + + while (qdb.fetch_row()) { + retval = qdb.getstr(); + } + + qdb.free_result(); + }; + + return retval; +} + +const int + configGetValue(const std::string name, const int default_value) +{ + int retval = default_value; + + classDatabase cdb(configurationFile()); + + if (cdb.Connected()) { + classQuery qdb(cdb); + + std::string s_sql = "" + "SELECT " + " value " + "FROM t_config_records " + "WHERE " + " name = '" + name + "'"; + + qdb.get_result(s_sql); + + while (qdb.fetch_row()) { + retval = qdb.getval(); + } + qdb.free_result(); + }; + + return retval; +} + + +/* Sets the configuration value. If succesfull returns CONST_OK*/ +const int + configSetValue(const std::string name, const std::string value) +{ + classDatabase cdb(configurationFile()); + if (!cdb.Connected()) { + return CONST_ERROR; + }; + + classQuery qdb(cdb); + if (!qdb.execute("BEGIN TRANSACTION")) { + say.Error("Cannot start new transaction. No configuration value update is going to be done."); + return CONST_ERROR; + }; + + std::string s_sql = "" + "DELETE " + "FROM t_config_records " + "WHERE " + " name = '" + name + "'"; + if (!qdb.execute(s_sql)) { + say.Warning("Cannot clean the previous configuration value."); + }; + + s_sql = "INSERT INTO t_config_records VALUES ('" + name + "', '" + value + "')"; + if (!qdb.execute(s_sql)) { + say.Error("Cannot update the configuration value."); + }; + + if (qdb.execute("COMMIT TRANSACTION")) { + say.Info(name + " value has been updated"); + return CONST_OK; + } else { + say.Error("Cannot update the configuration value."); + return CONST_ERROR; + }; + +} + +const int + configSetValue(const std::string name, const int value) +{ + return configSetValue(name, toString(value)); +} + diff --git a/src/core/database.cpp b/src/core/database.cpp new file mode 100644 index 0000000..4a44412 --- /dev/null +++ b/src/core/database.cpp @@ -0,0 +1,282 @@ +#include + +#include +#include +#include +#include +#include +#include + +#include "../../include/core/database.h" +#include "../../include/core/query.h" +#include "../../include/core/stdoutput.h" + +/* joins the standard output machine */ +extern classStdoutput::classStdoutput say; + + +#ifdef SQLITEW_NAMESPACE +namespace SQLITEW_NAMESPACE { +#endif + + +classDatabase::classDatabase(const std::string& d) +:database(d) +,m_embedded(true) +,m_mutex(m_mutex) +,m_b_use_mutex(false) +{ +} + + +classDatabase::classDatabase(Mutex& m,const std::string& d) +:database(d) +,m_embedded(true) +,m_mutex(m) +,m_b_use_mutex(true) +{ +} + + +classDatabase::~classDatabase() +{ + for (opendb_v::iterator it = m_opendbs.begin(); it != m_opendbs.end(); it++) + { + OPENDB *p = *it; + sqlite3_close(p -> db); + } + while (m_opendbs.size()) + { + opendb_v::iterator it = m_opendbs.begin(); + OPENDB *p = *it; + if (p -> busy) + { + error("destroying classDatabase object before classQuery object"); + } + delete p; + m_opendbs.erase(it); + } +} + + +classDatabase::OPENDB *classDatabase::grabdb() +{ + Lock lck(m_mutex, m_b_use_mutex); + OPENDB *odb = NULL; + + for (opendb_v::iterator it = m_opendbs.begin(); it != m_opendbs.end(); it++) + { + odb = *it; + if (!odb -> busy) + { + break; + } + else + { + odb = NULL; + } + } + if (!odb) + { + odb = new OPENDB; + if (!odb) + { + error("grabdb: OPENDB struct couldn't be created"); + return NULL; + } + int rc = sqlite3_open(database.c_str(), &odb -> db); + if (rc) + { + error("Can't open database: %s\n", sqlite3_errmsg(odb -> db)); + sqlite3_close(odb -> db); + delete odb; + return NULL; + } + odb -> busy = true; + m_opendbs.push_back(odb); + } + else + { + odb -> busy = true; + } + return odb; +} + + +void classDatabase::freedb(classDatabase::OPENDB *odb) +{ + Lock lck(m_mutex, m_b_use_mutex); + if (odb) + { + odb -> busy = false; + } +} + + +void classDatabase::error(const char *format, ...) +{ + va_list ap; + char errstr[5000]; + va_start(ap, format); + vsnprintf(errstr, 5000, format, ap); + va_end(ap); + say.Error(errstr); +} + + +void classDatabase::error(classQuery& q,const char *format, ...) +{ + + va_list ap; + char errstr[5000]; + va_start(ap, format); + vsnprintf(errstr, 5000, format, ap); + va_end(ap); + say.Error(errstr); + say.Error("QUERY: \"" + q.GetLastQuery() + "\""); +} + + +void classDatabase::error(classQuery& q,const std::string& msg) +{ + say.Error(msg); + say.Error("QUERY: \"" + q.GetLastQuery() + "\""); +} + + +bool classDatabase::Connected() +{ + OPENDB *odb = grabdb(); + if (!odb) + { + return false; + } + freedb(odb); + return true; +} + + +classDatabase::Lock::Lock(Mutex& mutex,bool use) : m_mutex(mutex),m_b_use(use) +{ + if (m_b_use) + { + m_mutex.Lock(); + } +} + + +classDatabase::Lock::~Lock() +{ + if (m_b_use) + { + m_mutex.Unlock(); + } +} + + +classDatabase::Mutex::Mutex() +{ + pthread_mutex_init(&m_mutex, NULL); +} + + +classDatabase::Mutex::~Mutex() +{ + pthread_mutex_destroy(&m_mutex); +} + + +void classDatabase::Mutex::Lock() +{ + pthread_mutex_lock(&m_mutex); +} + + +void classDatabase::Mutex::Unlock() +{ + pthread_mutex_unlock(&m_mutex); +} + + +std::string classDatabase::safestr(const std::string& str) +{ + std::string str2; + for (size_t i = 0; i < str.size(); i++) + { + switch (str[i]) + { + case '\'': + case '\\': + case 34: + str2 += '\''; + default: + str2 += str[i]; + } + } + return str2; +} + + +std::string classDatabase::xmlsafestr(const std::string& str) +{ + std::string str2; + for (size_t i = 0; i < str.size(); i++) + { + switch (str[i]) + { + case '&': + str2 += "&"; + break; + case '<': + str2 += "<"; + break; + case '>': + str2 += ">"; + break; + case '"': + str2 += """; + break; + case '\'': + str2 += "'"; + break; + default: + str2 += str[i]; + } + } + return str2; +} + + +int64_t classDatabase::a2bigint(const std::string& str) +{ + int64_t val = 0; + bool sign = false; + size_t i = 0; + if (str[i] == '-') + { + sign = true; + i++; + } + for (; i < str.size(); i++) + { + val = val * 10 + (str[i] - 48); + } + return sign ? -val : val; +} + + +uint64_t classDatabase::a2ubigint(const std::string& str) +{ + uint64_t val = 0; + for (size_t i = 0; i < str.size(); i++) + { + val = val * 10 + (str[i] - 48); + } + return val; +} + + +#ifdef SQLITEW_NAMESPACE +} // namespace SQLITEW_NAMESPACE { +#endif + diff --git a/src/core/main.cpp b/src/core/main.cpp index bdf4b07..a2865c0 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -26,6 +26,7 @@ #include "../../include/core/appl.h" #include "../../include/core/stdoutput.h" #include "../../include/gui/gui.h" +#include "../../include/core/glob.h" /* Standard output engine initialization */ classStdoutput::classStdoutput say; @@ -39,13 +40,17 @@ int main(int argc, char *argv[]){ say.Error("configuration directory not created"); say.Advice("Please, check your '~/.config' write rights."); return CONST_ERROR; + } else { + say.Info("Configuration db is ready to be used."); }; if (checkConfigurationStructure() != CONST_OK) { say.Error("configuration db not initialized"); say.Advice("The structure of your configuration db (" - + configurationFile() + ") may be broken. If your rights are OK removing the file could help."); + + configurationFile() + ") might be broken. If your rights are OK removing the file could help."); return CONST_ERROR; + } else { + say.Info("Configuration db structure is OK."); }; QApplication diff --git a/src/core/object_tree_model.cpp b/src/core/object_tree_model.cpp index d101589..c997cc4 100644 --- a/src/core/object_tree_model.cpp +++ b/src/core/object_tree_model.cpp @@ -3,20 +3,356 @@ License: GPL 2 */ +#include + +#include "../../include/core/appl.h" #include "../../include/core/object_tree_model.h" #include "../../include/core/stdoutput.h" +#include "../../include/core/utils.h" +#include "../../include/core/glob.h" +#include "../../include/core/query.h" /* joins the standard output machine */ extern classStdoutput::classStdoutput say; classDBObjectTreeModel::classDBObjectTreeModel() { + say.Info("Object tree model has been initialized."); } classDBObjectTreeModel::~classDBObjectTreeModel() { + say.Info("Object tree model has been destroyed."); } + + +void + classDBObjectTreeModel::addObject( + const uint object_type, const int parent_id, + const std::string caption, const uint expanded, + const std::string parental_db, int db_type, classQuery &qdb + ) +{ + std::string s_sql = "" + "INSERT INTO" + " t_tree_model( " + " object_type, parent_id, caption, expanded, parental_db, db_type) " + "VALUES ( " + " " + toString(object_type) + "," + " " + toString(parent_id) + "," + " '" + caption + "'," + " " + toString(expanded) + "," + " '" + parental_db + "'," + " " + toString(db_type) + "" + " )"; + if (!qdb.execute(s_sql)) { + say.Error("Object tree model object could not be added."); + }; + +} + +/* +void + classDBObjectTreeModel::addObject( + const uint object_type, const int parent_id, + const uint expanded, classQuery &qdb + ) +{ + addObject(object_type, parent_id, "", expanded, "", qdb); +} +*/ + +int + classDBObjectTreeModel::getKids( + const int parent_id, + std::list &li, + classQuery &qdb + ) +{ + + std::string s_sql = "SELECT object_id FROM t_tree_model " + "WHERE parent_id = " + toString(parent_id) + " " + "ORDER BY caption"; + + if (qdb.get_result(s_sql)) + { + while (qdb.fetch_row()) { + li.push_back(qdb.getval()); + } + qdb.free_result(); + } else { + say.Info("Unable to read object kids."); + return CONST_ERROR; + }; + + return CONST_OK; +} + +int + classDBObjectTreeModel::objectInfo( + int object_id, uint &object_type, + int &parent_id, std::string &caption, + uint &expanded, int &db_type, std::string &parental_db, + std::string &db_path, std::string &title, int &connected, + classQuery &qdb + ) +{ + std::string + s_sql = " SELECT" + " tm.object_type," + " tm.parent_id," + " tm.parental_db," + " tm.db_type," + " tm.caption," + " tm.expanded," + " rd.db_path," + " rd.title," + " rd.connected" + " FROM" + " t_tree_model AS tm" + " LEFT JOIN" + " t_registered_dbs AS rd" + " ON (rd.db_path = tm.parental_db) AND (rd.db_type = tm.db_type)" + " WHERE object_id = " + toString(object_id) + "" + " ORDER BY caption;"; + + if (qdb.get_result(s_sql)) + { + if (qdb.fetch_row()) + { + object_type = qdb.getuval(); + parent_id = qdb.getval(); + parental_db = qdb.getstr(); + db_type = qdb.getuval(); + caption = qdb.getstr(); + expanded = qdb.getuval(); + db_path = qdb.getstr(); + title = qdb.getstr(); + connected = qdb.getval(); + qdb.free_result(); + } else { + say.Warning("No object with id " + toString(object_id) + " found."); + qdb.free_result(); + return CONST_ERROR; + }; + } else { + say.Error("Unable to read object kids."); + return CONST_ERROR; + }; + + return CONST_OK; + +} + +int + classDBObjectTreeModel::objectInfo( + int object_id, uint &object_type, + int &parent_id, std::string &caption, + uint &expanded, int &db_type, std::string &parental_db, + classQuery &qdb + ) +{ + + std::string s_sql = "SELECT object_type, parent_id, caption," + " expanded, db_type, parental_db " + "FROM t_tree_model " + "WHERE object_id = " + toString(object_id) + " " + "ORDER BY caption"; + + if (qdb.get_result(s_sql)) + { + if (qdb.fetch_row()) + { + object_type = qdb.getuval(); + parent_id = qdb.getval(); + caption = qdb.getstr(); + expanded = qdb.getuval(); + db_type = qdb.getuval(); + parental_db = qdb.getstr(); + qdb.free_result(); + } else { + say.Warning("No object with id " + toString(object_id) + " found."); + qdb.free_result(); + return CONST_ERROR; + }; + } else { + say.Error("Unable to read object kids."); + return CONST_ERROR; + }; + + return CONST_OK; + +} + +int + classDBObjectTreeModel::objectTypeToID( const uint object_type, classQuery &qdb ) +{ + + std::string s_sql = "SELECT object_id FROM t_tree_model " + "WHERE object_type = " + toString(object_type) + " " + "ORDER BY object_id"; + + int i_res = CONST_ERROR; + + if (qdb.get_result(s_sql)) + { + if (qdb.fetch_row()) + { + i_res = qdb.getval(); + } else { + say.Warning("No object of type " + toString(object_type) + " found."); + }; + qdb.free_result(); + } else { + say.Error("Unable to read objects."); + }; + + return i_res; + +} + +int + classDBObjectTreeModel::registerDB( + std::string s_path, std::string s_title, + std::string &s_path_used, std::string &s_title_used, + const int db_type, classQuery &qdb + ) +{ + int i_back = RDB_OK; + std::string s_sql = "SELECT db_path, title FROM t_registered_dbs" + " WHERE db_path ='" + s_path + "'" + " OR title='" + s_title + "'"; + + std::string s_t; + std::string s_p; + + if (qdb.get_result(s_sql)) + { + + while (qdb.fetch_row()) + { + s_p = qdb.getstr(); + s_t = qdb.getstr(); + i_back = ( s_p == s_path ? i_back | RDB_DB_REGISTERED : i_back); + i_back = ( s_t == s_title ? i_back | RDB_TITLE_USED : i_back); + if (s_p == s_path) { s_title_used = s_t; }; + if (s_t == s_title) { s_path_used = s_p; }; + }; + qdb.free_result(); + + + } else { + say.Error("Unable to check registered dbs"); + return CONST_ERROR; + }; + + if (i_back==RDB_OK) { + if (!qdb.execute("INSERT INTO t_registered_dbs(db_path, db_type, title, connected)" + " VALUES('" + s_path + "', " + toString(db_type) + + ",'" + s_title + "', " + toString(NOT_CONNECTED) + ")") + ) + { + say.Error("Unable to register the db"); + return CONST_ERROR; + } else { + say.Info("Database " + s_title + " has been registered"); + addObject(IT_DB, objectTypeToID(IT_ROOT_DB, qdb), s_title, EXPANDED, s_path, DT_DB, qdb); + }; + } + + return i_back; +} + +int + classDBObjectTreeModel::unregisterDB( + std::string s_path, const int db_type, classQuery &qdb + ) +{ + + if (!qdb.execute("BEGIN TRANSACTION")){ + say.Error("Transaction cannot be started"); + return CONST_ERROR; + }; + + std::string s_sql = "DELETE FROM t_registered_dbs" + " WHERE db_path ='" + s_path + "'" + " AND db_type=" + toString(db_type) + ""; + + if (!qdb.execute(s_sql)){ + qdb.execute("END TRANSACTION"); + say.Error("Cannot delete the database from the registration list"); + return CONST_ERROR; + }; + + + s_sql = "DELETE FROM t_tree_model" + " WHERE parental_db ='" + s_path + "'" + " AND db_type=" + toString(db_type) + ""; + + if (!qdb.execute(s_sql)){ + qdb.execute("END TRANSACTION"); + say.Error("Cannot delete the database objects."); + return CONST_ERROR; + }; + + if (!qdb.execute("COMMIT TRANSACTION")){ + say.Error("Transaction cannot be started"); + return CONST_ERROR; + }; + + return CONST_OK; +} + +int + classDBObjectTreeModel::dbConnected( + int db_type, std::string db_path, classQuery &qdb + ) +{ + + std::string s_sql = "SELECT connected " + "FROM t_registered_dbs " + "WHERE db_path = '" + db_path + "' " + "AND db_type = " + toString(db_type) + " ;"; + + if (qdb.get_result(s_sql)) + { + if (qdb.fetch_row()) + { + int i_ret = qdb.getval(); + qdb.free_result(); + return i_ret; + } else { + qdb.free_result(); + say.Warning("No database '" + db_path + "' of type " + toString(db_type) + " has been found."); + return CONST_ERROR; + }; + } else { + say.Warning("Unable to read the list of registered databases."); + return CONST_ERROR; + }; + +} + +int + classDBObjectTreeModel::dbConnected( + const int i_connected, int db_type, std::string db_path, classQuery &qdb + ) +{ + + std::string s_sql = "UPDATE t_registered_dbs " + "SET connected = " + toString(i_connected) + " " + "WHERE db_path = '" + db_path + "' " + "AND db_type = " + toString(db_type) + " ;"; + + if (!qdb.execute(s_sql)) { + say.Error("Unable to change the db connected state."); + return CONST_ERROR; + } else { + return CONST_OK; + }; + +} diff --git a/src/core/query.cpp b/src/core/query.cpp new file mode 100644 index 0000000..9148aa4 --- /dev/null +++ b/src/core/query.cpp @@ -0,0 +1,496 @@ +#include +#include +#include +#include +#include +#include + +#include "../../include/core/database.h" +#include "../../include/core/query.h" + +#ifdef SQLITEW_NAMESPACE +namespace SQLITEW_NAMESPACE { +#endif + + +classQuery::classQuery(classDatabase& dbin) +: m_db(dbin) +,odb(dbin.grabdb()) +,res(NULL) +,row(false) +,cache_rc(0) +,cache_rc_valid(false) +,m_row_count(0) +,m_num_cols(0) +{ +} + + +classQuery::classQuery(classDatabase& dbin,const std::string& sql) +: m_db(dbin) +,odb(dbin.grabdb()) +,res(NULL) +,row(false) +,cache_rc(0) +,cache_rc_valid(false) +,m_row_count(0) +,m_num_cols(0) +{ + execute(sql); +} + + +classQuery::~classQuery() +{ + if (res) + { + GetDatabase().error(*this, "sqlite3_finalize in destructor"); + sqlite3_finalize(res); + } + if (odb) + { + m_db.freedb(odb); + } +} + + +classDatabase& classQuery::GetDatabase() const +{ + return m_db; +} + + +/* +The sqlite3_finalize() routine deallocates a prepared SQL statement. +All prepared statements must be finalized before the database can be closed. +*/ +bool classQuery::execute(const std::string& sql) +{ // query, no result + m_last_query = sql; + if (odb && res) + { + GetDatabase().error(*this, "execute: query busy"); + } + if (odb && !res) + { + const char *s = NULL; + int rc = sqlite3_prepare(odb -> db, sql.c_str(), sql.size(), &res, &s); + if (rc != SQLITE_OK) + { + GetDatabase().error(*this, "execute: prepare query failed"); + return false; + } + if (!res) + { + GetDatabase().error(*this, "execute: query failed"); + return false; + } + rc = sqlite3_step(res); // execute + sqlite3_finalize(res); // deallocate statement + res = NULL; + switch (rc) + { + case SQLITE_BUSY: + GetDatabase().error(*this, "execute: database busy"); + return false; + case SQLITE_DONE: + case SQLITE_ROW: + return true; + case SQLITE_ERROR: + GetDatabase().error(*this, sqlite3_errmsg(odb -> db)); + return false; + case SQLITE_MISUSE: + GetDatabase().error(*this, "execute: database misuse"); + return false; + } + GetDatabase().error(*this, "execute: unknown result code"); + } + return false; +} + + + +// methods using db specific api calls + +sqlite3_stmt *classQuery::get_result(const std::string& sql) +{ // query, result + if (odb && res) + { + GetDatabase().error(*this, "get_result: query busy"); + } + if (odb && !res) + { + const char *s = NULL; + int rc = sqlite3_prepare(odb -> db, sql.c_str(), sql.size(), &res, &s); + if (rc != SQLITE_OK) + { + GetDatabase().error(*this, "get_result: prepare query failed"); + return NULL; + } + if (!res) + { + GetDatabase().error(*this, "get_result: query failed"); + return NULL; + } + // get column names from result + { + int i = 0; + do + { + const char *p = sqlite3_column_name(res, i); + if (!p) + break; + m_nmap[p] = ++i; + } while (true); + m_num_cols = i + 1; + } + cache_rc = sqlite3_step(res); + cache_rc_valid = true; + m_row_count = (cache_rc == SQLITE_ROW) ? 1 : 0; + } + return res; +} + + +void classQuery::free_result() +{ + if (odb && res) + { + sqlite3_finalize(res); + res = NULL; + row = false; + cache_rc_valid = false; + } + // clear column names + while (m_nmap.size()) + { + std::map::iterator it = m_nmap.begin(); + m_nmap.erase(it); + } +} + + +bool classQuery::fetch_row() +{ + rowcount = 0; + row = false; + if (odb && res) + { + int rc = cache_rc_valid ? cache_rc : sqlite3_step(res); // execute + cache_rc_valid = false; + switch (rc) + { + case SQLITE_BUSY: + GetDatabase().error(*this, "execute: database busy"); + return false; + case SQLITE_DONE: + return false; + case SQLITE_ROW: + row = true; + return true; + case SQLITE_ERROR: + GetDatabase().error(*this, sqlite3_errmsg(odb -> db)); + return false; + case SQLITE_MISUSE: + GetDatabase().error(*this, "execute: database misuse"); + return false; + } + GetDatabase().error(*this, "execute: unknown result code"); + } + return false; +} + + +sqlite_int64 classQuery::insert_id() +{ + if (odb) + { + return sqlite3_last_insert_rowid(odb -> db); + } + else + { + return 0; + } +} + + +long classQuery::num_rows() +{ + return odb && res ? m_row_count : 0; +} + + +bool classQuery::is_null(int x) +{ + if (odb && res && row) + { + if (sqlite3_column_type(res, x) == SQLITE_NULL) + return true; + } + return false; // ... +} + + +const char *classQuery::getstr(const std::string& x) +{ + int index = m_nmap[x] - 1; + if (index >= 0) + return getstr(index); + error("Column name lookup failure: " + x); + return ""; +} + + +const char *classQuery::getstr(int x) +{ + if (odb && res && row && x < sqlite3_column_count(res) ) + { + const unsigned char *tmp = sqlite3_column_text(res, x); + return tmp ? (const char *)tmp : ""; + } + return ""; +} + + +const char *classQuery::getstr() +{ + return getstr(rowcount++); +} + + +double classQuery::getnum(const std::string& x) +{ + int index = m_nmap[x] - 1; + if (index >= 0) + return getnum(index); + error("Column name lookup failure: " + x); + return 0; +} + + +double classQuery::getnum(int x) +{ + if (odb && res && row) + { + return sqlite3_column_double(res, x); + } + return 0; +} + + +long classQuery::getval(const std::string& x) +{ + int index = m_nmap[x] - 1; + if (index >= 0) + return getval(index); + error("Column name lookup failure: " + x); + return 0; +} + + +long classQuery::getval(int x) +{ + if (odb && res && row) + { + return sqlite3_column_int(res, x); + } + return 0; +} + + +double classQuery::getnum() +{ + return getnum(rowcount++); +} + + +long classQuery::getval() +{ + return getval(rowcount++); +} + + +unsigned long classQuery::getuval(const std::string& x) +{ + int index = m_nmap[x] - 1; + if (index >= 0) + return getuval(index); + error("Column name lookup failure: " + x); + return 0; +} + + +unsigned long classQuery::getuval(int x) +{ + unsigned long l = 0; + if (odb && res && row) + { + l = sqlite3_column_int(res, x); + } + return l; +} + + +unsigned long classQuery::getuval() +{ + return getuval(rowcount++); +} + + +int64_t classQuery::getbigint(const std::string& x) +{ + int index = m_nmap[x] - 1; + if (index >= 0) + return getbigint(index); + error("Column name lookup failure: " + x); + return 0; +} + + +int64_t classQuery::getbigint(int x) +{ + if (odb && res && row) + { + return sqlite3_column_int64(res, x); + } + return 0; +} + + +int64_t classQuery::getbigint() +{ + return getbigint(rowcount++); +} + + +uint64_t classQuery::getubigint(const std::string& x) +{ + int index = m_nmap[x] - 1; + if (index >= 0) + return getubigint(index); + error("Column name lookup failure: " + x); + return 0; +} + + +uint64_t classQuery::getubigint(int x) +{ + uint64_t l = 0; + if (odb && res && row) + { + l = sqlite3_column_int64(res, x); + } + return l; +} + + +uint64_t classQuery::getubigint() +{ + return getubigint(rowcount++); +} + + +double classQuery::get_num(const std::string& sql) +{ + double l = 0; + if (get_result(sql)) + { + if (fetch_row()) + { + l = getnum(); + } + free_result(); + } + return l; +} + + +long classQuery::get_count(const std::string& sql) +{ + long l = 0; + if (get_result(sql)) + { + if (fetch_row()) + l = getval(); + free_result(); + } + return l; +} + + +const char *classQuery::get_string(const std::string& sql) +{ + bool found = false; + m_tmpstr = ""; + if (get_result(sql)) + { + if (fetch_row()) + { + m_tmpstr = getstr(); + found = true; + } + free_result(); + } + return m_tmpstr.c_str(); // %! changed from 1.0 which didn't return NULL on failed query +} + + +const std::string& classQuery::GetLastQuery() +{ + return m_last_query; +} + + +std::string classQuery::GetError() +{ + if (odb) + return sqlite3_errmsg(odb -> db); + return ""; +} + + +int classQuery::GetErrno() +{ + if (odb) + return sqlite3_errcode(odb -> db); + return 0; +} + + +bool classQuery::Connected() +{ + return odb ? true : false; +} + + + + +void classQuery::ViewRes() +{ + if (!res) + { + printf("no result stored\n"); + return; + } + printf("result column count = %d\n", sqlite3_column_count(res)); + for (int i = 0; i < sqlite3_column_count(res); i++) + { + printf(" %2d type %d name '%s'", i, sqlite3_column_type(res, i), sqlite3_column_name(res, i)); + printf(" / '%s'", (char *)sqlite3_column_text(res, i)); + printf(" / %d", sqlite3_column_int(res, i)); + printf(" / %f", sqlite3_column_double(res, i)); + printf("\n"); + } +} + + +void classQuery::error(const std::string& msg) +{ + GetDatabase().error(*this, msg); +} + + +#ifdef SQLITEW_NAMESPACE +} // namespace SQLITEW_NAMESPACE { +#endif + diff --git a/src/core/sqlengine.cpp b/src/core/sqlengine.cpp deleted file mode 100644 index 1e8937f..0000000 --- a/src/core/sqlengine.cpp +++ /dev/null @@ -1,270 +0,0 @@ -/* - Author: Marek Malevic - License: GPL 2 -*/ - - -#include "../../include/core/sqlengine.h" -#include "../../include/core/appl.h" - -/* joins the standard output machine */ -extern classStdoutput::classStdoutput say; - -classSqlengine::classSqlengine(std::string s_dbfile) -{ - //don't forget the filename - s_db = s_dbfile; - - //set timeout to 60min - sqlite3_busy_timeout(0, 1000*60*60); - - int nRet; - nRet = sqlite3_open(s_db.c_str(), &db_handle); - - virtualMachine = 0; - - switch(nRet){ - case SQLITE_OK: - say.Info("The sql engine has been succesfully initialized on '" + s_db + "'"); - sql_setEngineState(CONST_OK); - break; - default: - say.Error("sql engine not initialized '" + s_db + "'", nRet); - sql_setEngineState(CONST_ERROR); - break; - } -} - -classSqlengine::~classSqlengine() -{ - int nRet; - if (virtualMachine != 0) - { - sqlite3_finalize(virtualMachine); - }; - nRet = sqlite3_close(db_handle); - switch(nRet){ - case SQLITE_OK: - say.Info("The sql engine has been succesfully closed."); - sql_setEngineState(CONST_OK); - break; - case SQLITE_BUSY: - sql_setEngineState(CONST_ERROR); - say.Warning("The sql engine is too busy to be closed."); - break; - default: - say.Error("sql engine not closed '" + s_db + "'", nRet); - sql_setEngineState(CONST_ERROR); - break; - } - -} - -int - classSqlengine::sqlite3_step_extended(sqlite3_stmt *virtualMachine) -{ - int nRet = sqlite3_step(virtualMachine); - return ( ( nRet == SQLITE_ERROR ) ? sqlite3_finalize(virtualMachine) : nRet ); -} - -int - classSqlengine::sql_execute(std::string s_sql) -{ - char* szError=0; - - int nRet = sqlite3_exec(db_handle, s_sql.c_str(), NULL, 0, &szError); - - switch (nRet){ - case SQLITE_OK: - return CONST_OK; - break; - case SQLITE_BUSY: - say.Error("sql engine is busy", nRet); - return CONST_ERROR; - break; - default: - std::string s_err(szError); - say.Error("sql engine error: " + s_err, nRet); - sqlite3_free(szError); - return CONST_ERROR; - break; - }; - return CONST_ERROR; -} - - -int - classSqlengine::sql_query(std::string s_sql) -{ - const char* pzTail = 0; - - if (virtualMachine != 0) - { - sqlite3_finalize(virtualMachine); - virtualMachine = 0; - }; - - int nRet = sqlite3_prepare( db_handle, - s_sql.c_str(), -1, &virtualMachine, &pzTail ); - switch (nRet){ - case SQLITE_OK: - if (virtualMachine == NULL) { - sqlite3_finalize(virtualMachine); - virtualMachine = 0; - } else { - - nRet = sqlite3_step_extended(virtualMachine); - switch (nRet){ - case SQLITE_BUSY: - say.Error("sql engine is busy", nRet); - return CONST_ERROR; - break; - case SQLITE_DONE: - sql_eof = true; - return CONST_OK; - break; - case SQLITE_ROW: - sql_eof = false; - return CONST_OK; - break; - case SQLITE_ERROR: - say.Error("sql engine error", nRet); - return CONST_ERROR; - break; - case SQLITE_MISUSE: - sql_setEngineState(CONST_ERROR); - say.Error("sql routine called inappropriately", nRet); - return CONST_ERROR; - break; - }; - - }; - break; - case SQLITE_BUSY: - say.Error("sql engine is busy", nRet); - return CONST_ERROR; - break; - default: - say.Error("sql engine error", nRet); - if (virtualMachine == NULL) - { - sqlite3_finalize(virtualMachine); - virtualMachine = 0; - }; - return CONST_ERROR; - break; - }; - return CONST_ERROR; -} - -int - classSqlengine::sql_countFields() -{ - if (virtualMachine != 0){ - return sqlite3_column_count(virtualMachine); - } else { - say.Warning("No active query"); - return CONST_ERROR; - }; -} - -std::string - classSqlengine::sql_getFieldValueText(uint nIndex) -{ - int nCols = sql_countFields(); - - if ((signed int) nIndex < nCols) - { - std::string s_ret((const char*) sqlite3_column_text(virtualMachine, nIndex)); - return s_ret; - } else { - say.Warning("Column index too high for actual query result."); - return NULL; - }; -} - -std::string - classSqlengine::sql_getFieldValueText(std::string str_col) -{ - int nIndex = fieldIndex(str_col.c_str()); - if (nIndex != CONST_ERROR) - { - std::string s_ret((const char*) sqlite3_column_text(virtualMachine, nIndex)); - return s_ret; - } else { - say.Warning("There is no column named '" + str_col + "'."); - return NULL; - }; -} - -int - classSqlengine::fieldIndex(std::string s_field) -{ - if (virtualMachine == 0){ - say.Warning("No active query"); - return CONST_ERROR; - }; - - int nCols = sql_countFields(); - for (int nField = 0; nField < nCols; nField++) - { - const char* szTemp = sqlite3_column_name(virtualMachine, nField); - - if (strcmp(s_field.c_str(), szTemp) == 0) - { - return nField; - }; - }; - return CONST_ERROR; -} - -int - classSqlengine::sql_nextRow() -{ - if (virtualMachine != 0){ - - if (sql_getEof() == true) - { - say.Warning("sql_eof flag means no more rows currently"); - return CONST_ERROR; - } else { - int nRet = sqlite3_step_extended(virtualMachine); - if (nRet == SQLITE_DONE) - { - sql_eof = true; - return CONST_OK; - } - else if (nRet == SQLITE_ROW) - { - return CONST_OK; - } - else - { - nRet = sqlite3_finalize(virtualMachine); - virtualMachine = 0; - return CONST_ERROR; - }; - }; - } else { - say.Warning("No active query"); - return CONST_ERROR; - }; -} - -void - classSqlengine::sql_setEngineState(int new_state) -{ - engine_state = new_state; -} - -int - classSqlengine::sql_getEngineState() -{ - return engine_state; -} - -bool - classSqlengine::sql_getEof() -{ - return sql_eof; -} diff --git a/src/core/stdoutput.cpp b/src/core/stdoutput.cpp index 7b23e0b..7ed3181 100644 --- a/src/core/stdoutput.cpp +++ b/src/core/stdoutput.cpp @@ -5,6 +5,9 @@ #include "../../include/core/stdoutput.h" #include "../../include/core/appl.h" +#include "../../include/core/glob.h" + +#include classStdoutput::classStdoutput(VER_MODE v_mode) { @@ -17,41 +20,46 @@ classStdoutput::~classStdoutput() } void - classStdoutput::Error(std::string s_message, int error_code) + classStdoutput::Error(std::string s_message, bool show_msgbox) { if (verbosity_mode > V_MODE_MUTE){ - switch (error_code){ - case 0: - std::cerr << STRING_ERROR " " << s_message << std::endl; - break; - default: - std::cerr << STRING_ERROR << " #" << error_code << " " << s_message << std::endl; - break; - }; + std::cerr << STRING_ERROR " " << s_message << std::endl; + }; + if (show_msgbox){ + QMessageBox::critical(0, QString(APP_NAME " " APP_VERSION), QString(s_message.c_str())); }; } void - classStdoutput::Warning(std::string s_message) + classStdoutput::Warning(std::string s_message, bool show_msgbox) { if (verbosity_mode > V_MODE_ERRORS){ std::clog << STRING_WARNING << " " << s_message << std::endl; }; + if (show_msgbox){ + QMessageBox::warning(0, QString(APP_NAME " " APP_VERSION), QString(s_message.c_str())); + }; } void - classStdoutput::Info(std::string s_message) + classStdoutput::Info(std::string s_message, bool show_msgbox) { if (verbosity_mode > V_MODE_ADVICE){ std::cout << STRING_INFO << " " << s_message << std::endl; }; + if (show_msgbox){ + QMessageBox::information(0, QString(APP_NAME " " APP_VERSION), QString(s_message.c_str())); + }; } void - classStdoutput::Advice(std::string s_message) + classStdoutput::Advice(std::string s_message, bool show_msgbox) { if (verbosity_mode > V_MODE_WARNINGS){ std::cout << STRING_ADVICE << " " << s_message << std::endl; }; + if (show_msgbox){ + QMessageBox::information(0, QString(APP_NAME " " APP_VERSION), QString(s_message.c_str())); + }; } diff --git a/src/core/utils.cpp b/src/core/utils.cpp new file mode 100644 index 0000000..4363bdf --- /dev/null +++ b/src/core/utils.cpp @@ -0,0 +1,8 @@ +#include "../../include/core/utils.h" + +std::string toString(int value) +{ + std::stringstream ss; + ss << value; + return ss.str(); +} diff --git a/src/gui/frm_main.cpp b/src/gui/frm_main.cpp new file mode 100644 index 0000000..83189fd --- /dev/null +++ b/src/gui/frm_main.cpp @@ -0,0 +1,385 @@ +/* + Application main window code (GUI) + Author: Marek Malevic + License: GPL 2 +*/ + +#include "../../include/gui/frm_main.h" +#include "../../include/core/appl.h" +#include "../../include/core/actions.h" +#include "../../include/core/stdoutput.h" +#include "../../include/core/query.h" +#include "../../include/core/database.h" +#include "../../include/core/glob.h" +#include "../../include/core/utils.h" + +/* joins the standard output machine */ +extern classStdoutput::classStdoutput say; + +classMainForm::classMainForm() +{ + // window geometry + setMinimumSize(FRMMAIN_UI_WMINW, FRMMAIN_UI_WMINH); + setWindowTitle(tr("%1 version %2").arg(APP_NAME).arg(APP_VERSION)); + setWindowFlags(Qt::Window); + resize(configGetValue("MainWindowWidth",800),configGetValue("MainWindowHeight",600)); + setWindowStateInt(configGetValue("MainWindowState",0)); + + // central widget + tabWorkplace = new classTabWorkplace(); + setCentralWidget(tabWorkplace); + + //database objects tree + dbOTree = new classDBObjectTree(); + + //docking + QDockWidget *dock = new QDockWidget("", this); + dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); + dock->setFeatures(QDockWidget::DockWidgetMovable); + + dock->setWidget(dbOTree); + + addDockWidget(Qt::LeftDockWidgetArea, dock); + + //actions + createActions(); + checkActions(); + + //menus + createMenus(); + + +/* + TabWorkplace = new QTabWidget(this); + QPushButton *CornerButton = new QPushButton("", TabWorkplace); + CornerButton->setIcon(QIcon(":/icons/tab_remove.png")); + CornerButton->setFlat(true); + TabWorkplace->setCornerWidget(CornerButton); + + + setCentralWidget(TabWorkplace); + + connect(TabWorkplace, SIGNAL(currentChanged(int)), this, SLOT(slotTabChanged())); + connect(CornerButton, SIGNAL(clicked()), this, SLOT(slotCloseCurrentTab())); + + CreateActions(); + CreateMenus(); + CreateToolBars(); + CreateDockWindows(); +*/ + say.Info("Main window has been initialized."); + +} + +classMainForm::~classMainForm() +{ + + delete dbOTree; + delete tabWorkplace; + + configSetValue("MainWindowWidth", width()); + configSetValue("MainWindowHeight", height()); + + unsigned short int ws = getWindowStateInt(); + //we do not want to start minimized, do we? so, no 0x01 + ws &= 0x6; + configSetValue("MainWindowState", ws); + + say.Info("Good bye!"); +} + +unsigned short int classMainForm::getWindowStateInt() +{ + unsigned short int i_winstate = 0x0; + const Qt::WindowStates ws = windowState(); + + if (ws & Qt::WindowMinimized) + { + i_winstate |= 0x1; + }; + + if (ws & Qt::WindowMaximized) + { + i_winstate |= 0x2; + }; + + if (ws & Qt::WindowFullScreen) + { + i_winstate |= 0x4; + }; + + return i_winstate; +} + +void classMainForm::setWindowStateInt(const int i_winstate) +{ + Qt::WindowStates ws = Qt::WindowNoState; + + if (i_winstate & 0x1) + { + ws |= Qt::WindowMinimized; + }; + + if (i_winstate & 0x2) + { + ws |= Qt::WindowMaximized; + }; + + if (i_winstate & 0x4) + { + ws |= Qt::WindowFullScreen; + }; + setWindowState(ws); +} + +void classMainForm::createMenus() +{ + + say.Info("Creating main menu"); + fileMenu = menuBar()->addMenu(tr("&File")); + fileMenu->addAction(actExit); + + databaseMenu = menuBar()->addMenu(tr("&Database")); + databaseMenu->addAction(actRegisterDB); + databaseMenu->addAction(actUnRegisterDB); + databaseMenu->addSeparator(); + databaseMenu->addAction(actConnectDB); + databaseMenu->addAction(actDisConnectDB); + +} + +void classMainForm::createActions() +{ + actExit = new QAction(tr("E&xit"), this); + actExit->setShortcut(tr("Ctrl+Q")); + actExit->setStatusTip(tr("Exit the application")); + actExit->setIcon(QIcon(":action_exit.png")); + connect(actExit, SIGNAL(triggered()), this, SLOT(close())); + + actRegisterDB = new QAction(tr("R&egister"), this); + actRegisterDB->setShortcut(tr("Ctrl+R")); + actRegisterDB->setStatusTip(tr("Register the database")); + actRegisterDB->setIcon(QIcon(":action_register_db.png")); + connect(actRegisterDB, SIGNAL(triggered()), this, SLOT(registerDb())); + + actUnRegisterDB = new QAction(tr("&Unregister"), this); + actUnRegisterDB->setStatusTip(tr("Unregister the database")); + actUnRegisterDB->setIcon(QIcon(":action_unregister_db.png")); + connect(actUnRegisterDB, SIGNAL(triggered()), this, SLOT(unregisterDb())); + + actConnectDB = new QAction(tr("&Connect"), this); + actConnectDB->setShortcut(tr("Ctrl+P")); + actConnectDB->setStatusTip(tr("Connect the database")); + actConnectDB->setIcon(QIcon(":action_connect_db.png")); + connect(actConnectDB, SIGNAL(triggered()), this, SLOT(connectDb())); + + actDisConnectDB = new QAction(tr("&Disconnect"), this); + actDisConnectDB->setShortcut(tr("Ctrl+D")); + actDisConnectDB->setStatusTip(tr("Disconnect the database")); + actDisConnectDB->setIcon(QIcon(":action_disconnect_db.png")); + connect(actDisConnectDB, SIGNAL(triggered()), this, SLOT(disconnectDb())); + + connect(dbOTree, SIGNAL(itemSelectionChanged()), this, SLOT(checkActions())); +} + +void classMainForm::checkActions() +{ + + uint object_type; + int parent_id; + std::string caption; + uint expanded; + int db_type; + std::string parental_db; + std::string db_path; + std::string title; + int connected; + int o_id = 0; + + bool bAnyDBObjectSelected = (dbOTree->currentItem() != NULL); + + if (bAnyDBObjectSelected) { + classDatabase cdb(configurationFile()); + if (!cdb.Connected()) + { + say.Error("Unable to connect to the configuration db for reading the object tree information.", TRUE); + bAnyDBObjectSelected = FALSE; + } else { + classQuery qdb(cdb); + o_id = dbOTree->selectedObjectID(); + if (dbOTree->model->objectInfo(o_id, object_type, parent_id, caption, + expanded, db_type, parental_db, db_path, + title, connected, qdb) == CONST_ERROR) + { + if (o_id != CONST_ERROR) { + say.Error("Unable to check actions.",TRUE); + }; + bAnyDBObjectSelected = FALSE; + }; + }; + }; + +/* + say.Info("any selected: " + toString(bAnyDBObjectSelected) + + " db selected: " + toString(bDBSelected) + + " object id: " + toString(o_id) + + " object type: " + toString(object_type) + + " caption: " + caption + ); +*/ + + actExit->setEnabled(TRUE); + actRegisterDB->setEnabled(TRUE); + actUnRegisterDB->setEnabled(bAnyDBObjectSelected && (object_type == IT_DB)); + actConnectDB->setEnabled(bAnyDBObjectSelected && (object_type == IT_DB) && (connected == NOT_CONNECTED)); + actDisConnectDB->setEnabled(bAnyDBObjectSelected && (object_type == IT_DB) && (connected == CONNECTED)); + +} + +void classMainForm::registerDb() +{ + frmReg = new classRegForm(this); + frmReg->setWindowModality(Qt::ApplicationModal); + frmReg->show(); +} + +void classMainForm::unregisterDb() +{ + + uint object_type; + int parent_id; + std::string caption; + uint expanded; + int db_type; + std::string parental_db; + + classDatabase cdb(configurationFile()); + if (!cdb.Connected()) + { + say.Error("Unable to connect the configuration db for reading the object tree."); + return; + }; + + classQuery qdb(cdb); + + dbOTree->model->objectInfo(dbOTree->selectedObjectID(),object_type, + parent_id, caption, + expanded, db_type, parental_db, + qdb); + + if ( + QMessageBox::question(0,APP_NAME, + tr("Do you really want to unregister the database '%1' (%2)?").arg( + QString(caption.c_str()) + ).arg( + QString(parental_db.c_str())) + , QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::Yes + ) { + if (dbOTree->model->unregisterDB(parental_db, db_type, qdb)==CONST_OK) + { + dbOTree->redrawTree(); + say.Info("Database unregistered."); + checkActions(); + }; + }; +} + + +void classMainForm::connectDb() +{ + uint object_type; + int parent_id; + std::string caption; + uint expanded; + int db_type; + std::string parental_db; + + classDatabase cdb(configurationFile()); + if (!cdb.Connected()) + { + say.Error("Unable to connect the configuration db for reading the object tree."); + return; + }; + + classQuery qdb(cdb); + + dbOTree->model->objectInfo(dbOTree->selectedObjectID(),object_type, + parent_id, caption, + expanded, db_type, parental_db, + qdb); + + if (dbOTree->model->dbConnected(CONNECTED,db_type,parental_db, qdb)==CONST_OK) + { + dbOTree->redrawTree(); + say.Info("Database " + parental_db + " connected."); + checkActions(); + } else { + say.Error("The database could not be connected."); + }; +} + +void classMainForm::disconnectDb() +{ + uint object_type; + int parent_id; + std::string caption; + uint expanded; + int db_type; + std::string parental_db; + + classDatabase cdb(configurationFile()); + if (!cdb.Connected()) + { + say.Error("Unable to disconnect the configuration db for reading the object tree."); + return; + }; + + classQuery qdb(cdb); + + dbOTree->model->objectInfo(dbOTree->selectedObjectID(),object_type, + parent_id, caption, + expanded, db_type, parental_db, + qdb); + + if (dbOTree->model->dbConnected(NOT_CONNECTED,db_type,parental_db, qdb)==CONST_OK) + { + dbOTree->redrawTree(); + say.Info("Database " + parental_db + " disconnected."); + checkActions(); + } else { + say.Error("The database could not be disconnected."); + }; +} + +/* +void CMainForm::CreateDockWindows() +{ + QDockWidget *dock = new QDockWidget("", this); + dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); + dock->setFeatures(QDockWidget::DockWidgetMovable); + + dbTree = new QTreeWidget(dock); + dbTree->setColumnCount(2); + dbTree->setColumnHidden(1, true); + dbTree->setContextMenuPolicy(Qt::CustomContextMenu); + QStringList headers; + headers << ""; + dbTree->setHeaderLabels(headers); + + dock->setWidget(dbTree); + + QTreeWidgetItem *rdb = new QTreeWidgetItem(dbTree); + rdb->setText(0, tr("registered databases")); + rdb->setText(1, QVariant(IT_CATEGORY_DB).toString()); + rdb->setIcon(0, QIcon(":icons/registered_dbs.png")); + + connect(this, SIGNAL(signalReloadRegisteredDBs()), this, SLOT(slotReloadRegisteredDBs())); + connect(dbTree, SIGNAL(itemSelectionChanged()),this,SLOT(slotTreeWidgetClicked())); + connect(dbTree, SIGNAL(customContextMenuRequested(const QPoint)), this, SLOT(slotTreeWidgetRightClicked(const QPoint))); + connect(dbTree, SIGNAL(itemDoubleClicked( QTreeWidgetItem *, int )),this,SLOT(slotConnectDBonDblClick(QTreeWidgetItem*, int))); + + emit signalReloadRegisteredDBs(); + + addDockWidget(Qt::LeftDockWidgetArea, dock); +} +*/ diff --git a/src/gui/frm_main_ui.cpp b/src/gui/frm_main_ui.cpp deleted file mode 100644 index 73aeef5..0000000 --- a/src/gui/frm_main_ui.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/* - Application main window code (GUI) - Author: Marek Malevic - License: GPL 2 -*/ - -#include "../../include/gui/frm_main_ui.h" -#include "../../include/core/appl.h" -#include "../../include/core/actions.h" -#include "../../include/core/stdoutput.h" - -/* joins the standard output machine */ -extern classStdoutput::classStdoutput say; - -classMainForm::classMainForm() -{ - // window geometry - setMinimumSize(FRMMAIN_UI_WMINW, FRMMAIN_UI_WMINH); - setWindowTitle(tr("%1 version %2").arg(APP_NAME).arg(APP_VERSION)); - setWindowFlags(Qt::Window); - resize(configGetValue("MainWindowWidth",800),configGetValue("MainWindowHeight",600)); - setWindowStateInt(configGetValue("MainWindowState",0)); - - // central widget - tabWorkplace = new classTabWorkplace(); - setCentralWidget(tabWorkplace); - - //database objects tree - dbOTree = new classDBObjectTree(); - - //docking - QDockWidget *dock = new QDockWidget("", this); - dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); - dock->setFeatures(QDockWidget::DockWidgetMovable); - - dock->setWidget(dbOTree); - - addDockWidget(Qt::LeftDockWidgetArea, dock); - - //actions - createActions(); - - //menus - createMenus(); - - -/* - TabWorkplace = new QTabWidget(this); - QPushButton *CornerButton = new QPushButton("", TabWorkplace); - CornerButton->setIcon(QIcon(":/icons/tab_remove.png")); - CornerButton->setFlat(true); - TabWorkplace->setCornerWidget(CornerButton); - - - setCentralWidget(TabWorkplace); - - connect(TabWorkplace, SIGNAL(currentChanged(int)), this, SLOT(slotTabChanged())); - connect(CornerButton, SIGNAL(clicked()), this, SLOT(slotCloseCurrentTab())); - - CreateActions(); - CreateMenus(); - CreateToolBars(); - CreateDockWindows(); -*/ - say.Info("Main window has been initialized."); - -} - -classMainForm::~classMainForm() -{ - - delete dbOTree; - delete tabWorkplace; - - configSetValue("MainWindowWidth", width()); - configSetValue("MainWindowHeight", height()); - - unsigned short int ws = getWindowStateInt(); - //we do not want to start minimized, do we? so, no 0x01 - ws &= 0x6; - configSetValue("MainWindowState", ws); - - say.Info("Good bye!"); -} - -unsigned short int classMainForm::getWindowStateInt() -{ - unsigned short int i_winstate = 0x0; - const Qt::WindowStates ws = windowState(); - - if (ws & Qt::WindowMinimized) - { - i_winstate |= 0x1; - }; - - if (ws & Qt::WindowMaximized) - { - i_winstate |= 0x2; - }; - - if (ws & Qt::WindowFullScreen) - { - i_winstate |= 0x4; - }; - - return i_winstate; -} - -void classMainForm::setWindowStateInt(const int i_winstate) -{ - Qt::WindowStates ws = Qt::WindowNoState; - - if (i_winstate & 0x1) - { - ws |= Qt::WindowMinimized; - }; - - if (i_winstate & 0x2) - { - ws |= Qt::WindowMaximized; - }; - - if (i_winstate & 0x4) - { - ws |= Qt::WindowFullScreen; - }; - setWindowState(ws); -} - -void classMainForm::createMenus() -{ - - say.Info("Creating main menu"); - fileMenu = menuBar()->addMenu(tr("&File")); - fileMenu->addAction(actExit); - - databaseMenu = menuBar()->addMenu(tr("&Database")); - -} - -void classMainForm::createActions() -{ - actExit = new QAction(tr("E&xit"), this); - actExit->setShortcut(tr("Ctrl+Q")); - actExit->setStatusTip(tr("Exit the application")); - actExit->setIcon(QIcon(":exit.png")); - connect(actExit, SIGNAL(triggered()), this, SLOT(close())); -} -/* -void CMainForm::CreateDockWindows() -{ - QDockWidget *dock = new QDockWidget("", this); - dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); - dock->setFeatures(QDockWidget::DockWidgetMovable); - - dbTree = new QTreeWidget(dock); - dbTree->setColumnCount(2); - dbTree->setColumnHidden(1, true); - dbTree->setContextMenuPolicy(Qt::CustomContextMenu); - QStringList headers; - headers << ""; - dbTree->setHeaderLabels(headers); - - dock->setWidget(dbTree); - - QTreeWidgetItem *rdb = new QTreeWidgetItem(dbTree); - rdb->setText(0, tr("registered databases")); - rdb->setText(1, QVariant(IT_CATEGORY_DB).toString()); - rdb->setIcon(0, QIcon(":icons/registered_dbs.png")); - - connect(this, SIGNAL(signalReloadRegisteredDBs()), this, SLOT(slotReloadRegisteredDBs())); - connect(dbTree, SIGNAL(itemSelectionChanged()),this,SLOT(slotTreeWidgetClicked())); - connect(dbTree, SIGNAL(customContextMenuRequested(const QPoint)), this, SLOT(slotTreeWidgetRightClicked(const QPoint))); - connect(dbTree, SIGNAL(itemDoubleClicked( QTreeWidgetItem *, int )),this,SLOT(slotConnectDBonDblClick(QTreeWidgetItem*, int))); - - emit signalReloadRegisteredDBs(); - - addDockWidget(Qt::LeftDockWidgetArea, dock); -} -*/ diff --git a/src/gui/frm_reg.cpp b/src/gui/frm_reg.cpp new file mode 100644 index 0000000..8878618 --- /dev/null +++ b/src/gui/frm_reg.cpp @@ -0,0 +1,201 @@ + +#include "../../include/gui/frm_reg.h" +#include "../../include/core/glob.h" +#include "../../include/core/appl.h" +#include "../../include/gui/frm_main.h" +#include "../../include/core/stdoutput.h" + +/* joins the standard output machine */ +extern classStdoutput::classStdoutput say; + +classRegForm::classRegForm(QWidget *parent) + : QWidget(parent) +{ + + + Qt::WindowFlags flags = 0; + + setFixedSize(FRM_REG_WIDTH, FRM_REG_HEIGHT); + setWindowTitle(tr("Register new database")); + + setWindowFlags(Qt::Dialog); + setAttribute(Qt::WA_DeleteOnClose); + move( + parent->x() + (parent->width()/2) - (width()/2), + parent->y() + (parent->height()/2) - (height()/2) + ); + + path_label = new QLabel( + tr( "Select an SQLite3 database file to be registered. " + "If the database does not exist, " + "it will be created later while connecting." + ), + this + ); + path_label->setWordWrap(true); + path_label->resize(width()-FRM_REG_SIZE_CONSTS_LEFT*2, FRM_REG_SIZE_CONSTS_TOP+20); + path_label->move(FRM_REG_SIZE_CONSTS_LEFT, FRM_REG_SIZE_CONSTS_TOP); + path_label->setAlignment(Qt::AlignBottom); + + db_path = new QLineEdit(this); + db_path->move( + FRM_REG_SIZE_CONSTS_LEFT, + FRM_REG_SIZE_CONSTS_TOP + path_label->y() + path_label->height() + ); + db_path->resize(width()-115,25); + + title_label = new QLabel( + tr( "The title used by the application instead of " + "the whole db path."), + this + ); + title_label->setWordWrap(true); + title_label->resize(width()-FRM_REG_SIZE_CONSTS_LEFT*2, FRM_REG_SIZE_CONSTS_TOP+10); + title_label->move(FRM_REG_SIZE_CONSTS_LEFT, + db_path->y() + db_path->height() + 2*FRM_REG_SIZE_CONSTS_TOP + ); + title_label->setAlignment(Qt::AlignBottom); + + db_title = new QLineEdit(this); + db_title->move( + FRM_REG_SIZE_CONSTS_LEFT, + FRM_REG_SIZE_CONSTS_TOP + title_label->y() + title_label->height() + ); + db_title->resize( 200, 25 ); + + button_select_db = new QPushButton(tr("o&pen"),this); + button_select_db->move(FRM_REG_SIZE_CONSTS_LEFT+db_path->width()+ + FRM_REG_SIZE_CONSTS_LEFT-5, + db_path->y() + ); + button_select_db->resize(width()-FRM_REG_SIZE_CONSTS_LEFT*2 - + (FRM_REG_SIZE_CONSTS_LEFT-5) - db_path->width(), + db_path->height() + ); + button_select_db->setAutoDefault(true); + + button_cancel = new QPushButton(tr("&cancel"),this); + button_cancel->resize(FRM_REG_SIZE_CONSTS_BUTTON_WIDTH,db_path->height()); + button_cancel->move(width() - FRM_REG_SIZE_CONSTS_BUTTON_WIDTH + - FRM_REG_SIZE_CONSTS_LEFT, + height() - FRM_REG_SIZE_CONSTS_TOP - button_cancel->height() + ); + button_cancel->setAutoDefault(true); + + button_ok = new QPushButton(tr("&OK"),this); + button_ok->resize(FRM_REG_SIZE_CONSTS_BUTTON_WIDTH, db_path->height()); + button_ok->move(button_cancel->x() - FRM_REG_SIZE_CONSTS_LEFT - button_ok->width(), + button_cancel->y() + ); + button_ok->setEnabled(false); + button_ok->setAutoDefault(true); + + file_dialog = new QFileDialog(this); + file_dialog->setFileMode(QFileDialog::AnyFile); + file_dialog->setAcceptMode(QFileDialog::AcceptOpen); + + setTabOrder(button_ok, button_cancel); + setTabOrder(button_cancel, db_path); + setTabOrder(db_path,button_select_db); + setTabOrder(button_select_db, db_title); + + say.Info("Connecting signals to slots"); + connect(button_select_db,SIGNAL(clicked()),file_dialog,SLOT(exec())); + connect(button_cancel, SIGNAL(clicked()),this,SLOT(close())); + connect(button_ok, SIGNAL(clicked()),this,SLOT(regDBOK())); + connect(db_path, SIGNAL(textChanged(QString)),this,SLOT(checkButtons())); + connect(db_title, SIGNAL(textChanged(QString)),this,SLOT(checkButtons())); + + say.Info("Connecting the file dialog"); + connectFileDialog(); + + say.Info("The 'register db' dialog has been created."); +} + +void classRegForm::connectFileDialog() +{ + connect(file_dialog,SIGNAL(accepted()),this,SLOT(fillPath())); +} + +void classRegForm::fillPath() +{ + QStringList list = file_dialog->selectedFiles(); + QStringList::Iterator it = list.begin(); + + QString s = *it; + QFileInfo fi(s); + + db_path->setText(s); + db_title->setText(fi.baseName().toUpper()); + button_ok->setFocus(); +} + +void classRegForm::checkButtons() +{ + bool b = true; + b &= !db_path->text().isEmpty(); + b &= !db_title->text().isEmpty(); + + button_ok->setEnabled(b); +} + +void classRegForm::regDBOK() +{ + QString s_path = db_path->text(); + QString s_title = db_title->text(); + std::string s_used_path; + std::string s_used_title; + + classDatabase cdb(configurationFile()); + if (!cdb.Connected()) { + say.Error("Error occured while connectiong to the configuration database.", TRUE); + return; + }; + + classQuery qdb(cdb); + int i = ((classMainForm*)parentWidget())->dbOTree->model->registerDB( + s_path.toStdString(), + s_title.toStdString(), + s_used_path, + s_used_title, + DT_DB, + qdb + ); + switch(i){ + case(RDB_DB_REGISTERED | RDB_TITLE_USED):{ + if ((s_used_path == s_path.toStdString()) && (s_used_title == s_title.toStdString())) + { + QMessageBox::warning(this, APP_NAME,tr("This database has already been registered. You cannot register it again.")); + } else { + QString s_arg1(s_used_title.c_str()); + QString s_arg2(s_used_path.c_str()); + QMessageBox::warning(this, APP_NAME,tr("This database has already been registered with the title '%1'." + " You cannot register it again.\n\nAlso the title you've selected has already been used - " + "it's a titleQWidget *parent of the db '%2'.").arg(s_arg1).arg(s_arg2)); + }; + break;} + case(RDB_TITLE_USED):{ + QString s_arg1(s_used_path.c_str()); + QMessageBox::warning(this, APP_NAME,tr("The title you've selected has already been used - " + "it's a title of the db '%1'.\n\nPlease, choose another title.").arg(s_arg1)); + break;} + case(RDB_DB_REGISTERED):{ + QString s_arg1(s_used_title.c_str()); + QMessageBox::warning(this, APP_NAME,tr("This database has already been registered with the title '%1'." + "\n\nYou cannot register this db again.").arg(s_arg1)); + break;} + case(RDB_OK):{ + ((classMainForm*)parentWidget())->dbOTree->redrawTree(); + close(); + break;} + } + + +} + +classRegForm::~classRegForm() +{ + say.Info("Destroying the 'register db' dialog"); +} + + diff --git a/src/gui/w_object_tree.cpp b/src/gui/w_object_tree.cpp index f563faa..bf7a265 100644 --- a/src/gui/w_object_tree.cpp +++ b/src/gui/w_object_tree.cpp @@ -4,8 +4,15 @@ License: GPL 2 */ +#include + #include "../../include/gui/w_object_tree.h" +#include "../../include/core/appl.h" +#include "../../include/core/database.h" +#include "../../include/core/query.h" #include "../../include/core/stdoutput.h" +#include "../../include/core/glob.h" +#include "../../include/core/utils.h" /* joins the standard output machine */ extern classStdoutput::classStdoutput say; @@ -14,8 +21,13 @@ classDBObjectTree::classDBObjectTree() { // QStringList headers(""); setHeaderLabels((QStringList) ""); + // setColumnCount(2); model = new classDBObjectTreeModel(); + if (redrawTree() != CONST_OK) { + say.Error("Unable to redraw the object tree."); + }; + say.Info("DB Object Tree has been initialized."); } @@ -26,3 +38,127 @@ classDBObjectTree::~classDBObjectTree() say.Info("DB Object Tree has been destroyed."); } +int + classDBObjectTree::drawObject(int object_id, QTreeWidgetItem *parent, QTreeWidgetItem *&kid, classQuery &qdb) +{ + + uint object_type; + int parent_id; + std::string + caption; + std::string + parental_db; + uint expanded; + int db_type; + + if (model->objectInfo(object_id, object_type, parent_id, caption, expanded, db_type, parental_db, qdb) != CONST_OK) { + say.Error("Cannot get the object info."); + return CONST_ERROR; + } else { + say.Info("Object id: '" + toString(object_id) + + "' object type: '" + toString(object_type) + + "' object parent id: '" + toString(parent_id) + + "' caption: '" + caption + "'" + + "' db_type: '" + toString(db_type) + "'" + ); + }; + + if (parent_id == -1) { kid = new QTreeWidgetItem(this, object_type); } + else { kid = new QTreeWidgetItem(parent, object_type); }; + switch (object_type) { + case IT_ROOT_DB: /* registered relational databases root*/ + kid->setIcon(0, QIcon(":object_type_registered_relational_dbs.png")); + kid->setText(0, tr("databases")); + kid->setText(1, QString(toString(object_id).c_str())); + kid->setExpanded(expanded); + break; + + case IT_DB: /* registered relational database*/ + kid->setIcon(0, + ( + (model->dbConnected(db_type, parental_db, qdb)!=NOT_CONNECTED) ? + QIcon(":object_type_registered_db_connected.png") : + QIcon(":object_type_registered_db_disconnected.png") + ) + ); + kid->setText(0, QString(caption.c_str())); + kid->setText(1, QString(toString(object_id).c_str())); + kid->setExpanded(expanded); + break; + + default: /* unknown object type */ + say.Warning("Unknown object type " + toString(object_type)); + kid->setIcon(0, QIcon(":object_type_unknown.png")); + kid->setText(0, QString(caption.c_str())); + kid->setText(1, QString(toString(object_id).c_str())); + kid->setExpanded(expanded); + break; + }; + + return CONST_OK; +} + +int + classDBObjectTree::drawKids(int object_id, QTreeWidgetItem *parent, classQuery &qdb) +{ + std::list li; + + model->getKids(object_id, li, qdb); + for (std::list::iterator kid = li.begin(); kid != li.end(); ++kid) + { + QTreeWidgetItem *new_kid; + int ret = drawObject(*kid, parent, new_kid, qdb); + if (ret!=CONST_OK) + { + say.Error("Object #" + toString(*kid) + " drawing failed."); + QMessageBox::critical(this, APP_NAME " " APP_VERSION, + tr("Error while drawing the object tree model."), + QMessageBox::Ok); + } else { + drawKids(*kid, new_kid, qdb); + }; + } + return CONST_OK; +}; + +int + classDBObjectTree::redrawTree() +{ + /* first read all root elements (parent -1 is root)*/ + say.Info("Redrawing the object tree."); + int i_id = selectedObjectID(); + say.Info("Caused by " + toString(i_id)); + setCurrentItem(NULL); + clear(); + classDatabase cdb(configurationFile()); + if (!cdb.Connected()) + { + say.Error("Unable to connect the configuration db for redrawing the object tree."); + return CONST_ERROR; + }; + + classQuery qdb(cdb); + + int i_ret = drawKids(-1, NULL, qdb); + + if ((i_id != CONST_ERROR) && (i_ret != CONST_ERROR)) { + QTreeWidgetItemIterator it(this); + while (*it) { + // say.Info((*it)->text(1).toStdString()); + if ((*it)->text(1).toInt() == i_id) + setCurrentItem(*it); + setItemSelected(*it, true); + ++it; + } + } + + return i_ret; + +} + +int + classDBObjectTree::selectedObjectID() +{ + if (currentItem()==NULL) {return CONST_ERROR;}; + return selectedItems()[0]->text(1).toInt(); +} -- 2.11.4.GIT