domingo, 27 de julio de 2008

First public pre-alpha release of GQB (Graphical Query Builder) for pgAdmin




I have been working on improve my Google Summer of Code Project: http://wiki.postgresql.org/wiki/Gsoc08-querybuilder for a while, and today I'm going to release what I believe it's the first public pre-alpha release that I sent to pgadmin-hackers list, as you notice this release is for testing only an i'ts provided with no warranty :)

Now with the project you can:

0. Create a graphical model of a query sentence. (to add a table just double click on it on the left tree, tables are added at same place please move to other position by drag & drop from the title)
1. Create some simple queries involving joins (only equality joins right now), only drag and drop column from one table to another
2. Order the columns in the projection part of sentence (Select x,y,z...), and add columns alias in a grid
3. Add some restrictions (not validate content yet, a parser should be done in next days)
4. Create synonymous for tables just double click on table title an write synonymous on dialog.

I'm hoping for feedback, any ideas, suggestions or bug reporst are important to improve next releases.

Mini-FAQ
Where is located GQB inside pgAdmin?
At SQL Editor in a top tab you can choose between normal editor & gqb.


Can I try it without applying a patch and compiling it?
Yes, download binary (sorry binary for windows this time) at rapidshare:
http://rapidshare.com/files/132757130/prealpha-test-pgadmin-gqb-july-27.patch.zip.html


Where is located the patch?
http://svn.assembla.com/svn/vsqlbuilder/Jul/27/prealpha-test-gqb-july-27.patch

jueves, 10 de julio de 2008

First pre-pre-pre... alpha release of the GQB

I couldn't write in a while (violating my promise of write more :( ) but I have an announcement, today I finish what I think will be a good first pre-alpha release of the Graphical Query Builder for pgAdmin III, have a lot of bugs but it's usable.

I publish some screenshots too here:





I need people that test it & report me bugs (I detect a last minute bug on linux that crash pgAdmin after close GQB SQL Windows, I'm searching for causes because last releases don't have this behavior and in windows the error is not detected BUT YOU CAN TRY IT I WILL FIX THIS IN A FEW HOURS & PUBLISH A NEW PATCH

FIX:

Should comment this lines at the destructor gqbView::~gqbView():
/*if(projectionPanel)
delete projectionPanel;
if(criteriaPanel)
delete criteriaPanel;*/

of the file:gqbView.cpp


), you can download the patch here & report bugs to me, instructions are simple configure and build environment for pgAdmin III head version (follow instructions on page) and later apply my patch.

Note: on Linux, just watch out a .rej file at pgadmin/include/frm/frmQuery.h.rej open it look at the lines with a + symbol at begin (just headers lines of the .h), and add it to the frmQuery.h using your favorite text editor.

:)

martes, 17 de junio de 2008

A lot of time without writing but still working :)

My last post was about 1 month ago, this is a lot of time, but in this time I have done a lot of progress, and here I just resume most important completed goals:

1. The Graphical Query Builder Graphic part is working right now, with simple joins.
2. User can select what columns to include in select sentence.
3. A SQL sentence can be generated from the graphical model.

And in this process I try to create documentation that will be useful for future contributions to pgAdmin project, like:

Information about pgAdmin internal structure.
http://wiki.postgresql.org/wiki/PgAdmin_Internals

Information about my GQB internals
http://wiki.postgresql.org/wiki/Gsoc08-querybuilder-Internals

Right now, still there are a lot of works to do... but checking my proposal I'm on time:

I'm at deliverable 4, and the schedule for this it's about Jul 6 - 12,Jul 13 - 19 week 7,8

I hope this continue in this way.... and I'm going to try to create more posts on this blog...

Finally as an example of my work I publish two images of my progress using the dellstore sample database for postgresql



lunes, 12 de mayo de 2008

First protoype of user interface for the Graphical Query Builder of pgAdmin


Yesterday, I finish what I believe it's the first prototype for pgAdmin GQB (Graphical Query Builder) interface, I have some ideas from my other project in the same area but I need to test the prototypes looking for best usability performance and effectiveness, because I think that doing things good in a quickly way is better than do it in a good looking way but slower. Just as google searching tool: Not big graphics, not best user interface of the web, but usability and effectiveness it's the best one.



By the way, I was thinking about finishing vsqlbuilder after the GQB for pgadmin, I really believe that this two tools can be used for different segments of users:
  • pgAdmin (C++/WxWidgets): Database Administrators [it's my own opinion ;) ]
  • Visual SQL Builder (Java): Database End Users, because I want to include on it: the GQB, reporting tools, little CASE of simple transactional applications & more end user related thing. I just need some time to do it and by september I maybe start to coding something on it.

domingo, 11 de mayo de 2008

Design Patterns


I was thinking about the class hierarchy for my project and think about which design patterns could be useful for this goal, and a quick search on google bring to me, this very good resume about design patterns, useful for choosing one when programming:

http://www.mcdonaldland.info/files/designpatterns/designpatternscard.pdf

Update:
I found this wonderful book about Design Patterns: Head First Design Patterns

Wow it's the first time on my life that have been fun to read a technical book, this is one it's the best introduction to object-oriented programming that I have read. (It's for java but a lot of concepts can be used in other programming languages). And not only funny to read, the most important thing: you learn a lot with it.

You can read sample chapter at o'reilly.

Summer of Code 2008 Students and Mentors Geoposition (Google Map)


Today, Andrei Bautu announced on the gsoc students list, that create a google map containing all (authorized) gsoc students & mentors geoposition, (I assume joining together individual information from every project page at code.google.com/soc/) and put on this url:

http://fmc.anmb.ro/news/2008/google-code-summer-code-2008-students-and-mentors

It's very interesting.

jueves, 8 de mayo de 2008

Simple graphics with WxWidgets and Direct Context (WxDC)

UPDATE #1: Added a more "elegantly" version of this code inside of a class & allowing Scrolling.

Today I fix & improve the source code of the post wxogl-vs-wxdc-vs-wxart2d that I wrote last week, and now the same application can add until 10 tables (rectangles with text) inside the frame, then you can select only one at time (red line in the border) or move it with drag & drop in the frame.

This demo can help people (newbies) who wants to create a modeling tool of some kind with WxWidgets, is not great thing but have good ideas that can be used for larger applications:

- Diagram it's draw at the OnPaint event of the windows, because this there isn't need of a separate thread or something like that. And CPU usage of application it's low.

- It's easy to adapt the example to use a Model View Controller, only create data structures with base information for objects inside diagram, and a DrawAll function that can read that information and draw it, then Controller syncrhonize
all changes between the data and the image.

- Flicker have been eliminated.

- Don't use any complex third party library, this means no highly optimized rendering neither undo feature (by default) or complex document hierarchy, but for me best way of programa something always should follow this rule: "Simpler is better "

Source code:


Test.cpp
  1. #include "wx/wxprec.h"

  2. #define MAXRECTANGLES 10

  3. #ifdef __BORLANDC__

  4. #pragma hdrstop

  5. #endif


  6. #ifndef WX_PRECOMP


  7. #endif


  8. #include "wx/wx.h"

  9. #include "wx/dcbuffer.h"


  10. enum MenuItems

  11. {

  12. ID_Add = 2,


  13. ID_Quit = 1,

  14. ID_About = 0,


  15. };


  16. class MyApp: public wxApp

  17. {

  18. virtual bool OnInit();


  19. };



  20. IMPLEMENT_APP(MyApp)



  21. class MyCanvas; //Just a prototype


  22. class MyFrame: public wxFrame


  23. {

  24. public:


  25. MyFrame(const wxString& title,

  26. const wxPoint& pos, const wxSize& size);



  27. //Menu Events

  28. void OnQuit(wxCommandEvent& event);


  29. void OnAbout(wxCommandEvent& event);

  30. void OnAddRectangle(wxCommandEvent& event);



  31. //Global Class Variables

  32. MyCanvas *paintArea;

  33. DECLARE_EVENT_TABLE()


  34. };


  35. class MyCanvas: public wxScrolledWindow

  36. {

  37. public:

  38. MyCanvas::MyCanvas(MyFrame *parent, wxSize size);


  39. //MyCanvas Functions

  40. void MyCanvas::DrawAll(wxBufferedDC& bdc);


  41. int MyCanvas::GetIndexSelected();

  42. //MyCanvas Events


  43. void MyCanvas::OnPaint(wxPaintEvent& event);

  44. void MyCanvas::OnMotion(wxMouseEvent& event);


  45. void MyCanvas::OnErase(wxEraseEvent& event);

  46. void MyCanvas::OnEraseBackGround(wxEraseEvent& event);


  47. //Global Class Variables

  48. int rts[MAXRECTANGLES][2];


  49. int rts_Size;

  50. int pressed,posx,posy,selected;

  51. wxSize c_size;



  52. private:

  53. MyFrame *m_owner;

  54. DECLARE_EVENT_TABLE()


  55. };




  56. //**********************Begin implementations

  57. bool MyApp::OnInit()

  58. {

  59. MyFrame *frame = new MyFrame( wxT("Hello World Drawing in 2D"),


  60. wxPoint(50,50), wxSize(800,600) );


  61. frame->Show(TRUE);


  62. SetTopWindow(frame);

  63. //frame->SetScrollbar(wxVERTICAL,0,16,50);



  64. //initialize values

  65. frame->paintArea->rts_Size=0;


  66. for(int i=0;i<MAXRECTANGLES;i++){

  67. frame->paintArea->rts[i][0]=-1;


  68. frame->paintArea->rts[i][1]=-1;


  69. }

  70. frame->paintArea->pressed=-1; //No rectangle selected


  71. return TRUE;

  72. }



  73. //MyFrame Constructor

  74. MyFrame::MyFrame(const wxString& title,


  75. const wxPoint& pos, const wxSize& size)

  76. : wxFrame((wxFrame *)NULL, -1, title, pos, size)


  77. {

  78. wxMenu *menuFile = new wxMenu;

  79. menuFile->Append( ID_Add, wxT("&Add new Rectangle..." ));


  80. menuFile->Append( ID_About, wxT("A&bout..." ));

  81. menuFile->AppendSeparator();


  82. menuFile->Append( ID_Quit, wxT("E&xit" ));


  83. wxMenuBar *menuBar = new wxMenuBar;


  84. menuBar->Append( menuFile, wxT("&File") );


  85. SetMenuBar( menuBar );



  86. CreateStatusBar();

  87. SetStatusText(wxT("Proof of Concept drawing") );



  88. paintArea = new MyCanvas(this,wxSize(800,600));

  89. paintArea->SetScrollbars( 10, 10, 100, 240 );




  90. }



  91. //MyCanvas Constructor

  92. MyCanvas::MyCanvas(MyFrame *parent, wxSize size)


  93. : wxScrolledWindow(parent, wxID_ANY, wxDefaultPosition, size,

  94. wxHSCROLL | wxVSCROLL | wxBORDER | wxRETAINED)


  95. {

  96. m_owner = parent;

  97. c_size = size;


  98. }


  99. //Events Table Macros

  100. BEGIN_EVENT_TABLE(MyFrame, wxFrame)

  101. EVT_MENU(ID_Quit, MyFrame::OnQuit)

  102. EVT_MENU(ID_About, MyFrame::OnAbout)


  103. EVT_MENU(ID_Add, MyFrame::OnAddRectangle)

  104. END_EVENT_TABLE()


  105. BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow)

  106. EVT_PAINT(MyCanvas::OnPaint)


  107. EVT_MOTION(MyCanvas::OnMotion)

  108. EVT_LEFT_DOWN(MyCanvas::OnMotion)


  109. EVT_LEFT_UP(MyCanvas::OnMotion)

  110. EVT_ERASE_BACKGROUND(MyCanvas::OnEraseBackGround)
    //This erase flicker create by wxStaticText when erasing background but this is not needed


  111. END_EVENT_TABLE()



  112. //Events **************************


  113. //Overwrite and disable onEraseBackground Event to avoid Flicker

  114. void MyCanvas::OnEraseBackGround(wxEraseEvent& event) {};



  115. void MyCanvas::OnPaint(wxPaintEvent& event)

  116. {

  117. //Prepare Context for Buffered Draw

  118. wxPaintDC dcc(this);


  119. wxBufferedDC dc(&dcc, c_size );

  120. DrawAll(dc);

  121. }



  122. void MyCanvas::OnMotion(wxMouseEvent& event)


  123. {

  124. posx=event.GetPosition().x;

  125. posy=event.GetPosition().y;



  126. this->CalcUnscrolledPosition(posx,posy,&posx,&posy);


  127. if(event.ButtonDown()&&pressed==-1){


  128. pressed=GetIndexSelected();

  129. selected=pressed;


  130. }


  131. if(event.ButtonUp()){

  132. pressed=-1;


  133. }


  134. if (event.Dragging()&&pressed!=-1)

  135. {

  136. rts[pressed][0]=posx-25;


  137. rts[pressed][1]=posy-25;

  138. }



  139. this->Refresh();

  140. }



  141. //**************************Functions

  142. int MyCanvas::GetIndexSelected(){


  143. int index=-1;

  144. for(int i=0;i<rts_Size;i++){


  145. int x=rts[i][0];


  146. int y=rts[i][1];


  147. if( ((posx-x>0)&&(x+70>posx)) && ((posy-y>0)&&(y+70>posy)) ){


  148. return i;

  149. break;


  150. }

  151. }

  152. return index;


  153. }



  154. void MyCanvas::DrawAll(wxBufferedDC& bdc){

  155. bdc.SetBackground(*wxBLACK_BRUSH);


  156. wxFont f = wxFont(8, wxFONTFAMILY_ROMAN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);

  157. wxFont f2 = wxFont(10, wxFONTFAMILY_ROMAN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD);

  158. bdc.Clear();


  159. bdc.SetBrush(*wxWHITE_BRUSH);

  160. for(int i=(rts_Size-1);i>=0;i--){ //i-- to draw in order


  161. int x=rts[i][0];


  162. int y=rts[i][1];


  163. this->CalcScrolledPosition(x,y,&x,&y);

  164. if(x!=-1 && y!=-1){


  165. if(selected==i){


  166. bdc.SetPen(*wxRED_PEN);


  167. }else{

  168. bdc.SetPen(*wxBLACK_PEN);


  169. }

  170. bdc.DrawRectangle(wxRect(wxPoint(x,y), wxSize(70,70)));


  171. bdc.SetFont(f2);


  172. bdc.DrawText(wxT("TName"),x+5,y);


  173. bdc.SetFont(f);


  174. bdc.DrawText(wxT("CName 1"),x+10,y+12); //use font metrics here


  175. bdc.DrawText(wxT("CName 2"),x+10,y+24); //use font metrics here


  176. bdc.DrawText(wxT("CName 3"),x+10,y+36); //use font metrics here


  177. bdc.DrawText(wxT("CName ..."),x+10,y+36); //use font metrics here


  178. }

  179. else{


  180. break;

  181. }


  182. }

  183. }




  184. //**************************Menu Events

  185. void MyFrame::OnAddRectangle(wxCommandEvent& WXUNUSED(event))


  186. {

  187. if(paintArea->rts_Size < MAXRECTANGLES){

  188. paintArea->rts[paintArea->rts_Size][0]= paintArea->rts_Size*10+10;


  189. paintArea->rts[paintArea->rts_Size][1]= paintArea->rts_Size*10+10;


  190. paintArea->rts_Size++;

  191. }


  192. }

  193. void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))

  194. { Close(TRUE);


  195. }

  196. void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))

  197. { wxMessageBox(wxT("This is a Hello Direct Contex Application in wxWidgets"),


  198. wxT("About Hello DC"), wxOK | wxICON_INFORMATION, this);

  199. }