1 /*
2 / ResultSetView.cpp
3 / a panel to show SQL query results
4 /
5 / version 1.7, 2013 May 8
6 /
7 / Author: Sandro Furieri a-furieri@lqt.it
8 /
9 / Copyright (C) 2008-2013  Alessandro Furieri
10 /
11 /    This program is free software: you can redistribute it and/or modify
12 /    it under the terms of the GNU General Public License as published by
13 /    the Free Software Foundation, either version 3 of the License, or
14 /    (at your option) any later version.
15 /
16 /    This program is distributed in the hope that it will be useful,
17 /    but WITHOUT ANY WARRANTY; without even the implied warranty of
18 /    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 /    GNU General Public License for more details.
20 /
21 /    You should have received a copy of the GNU General Public License
22 /    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 /
24 */
25 
26 #include "Classdef.h"
27 
28 #include "wx/clipbrd.h"
29 #include "wx/filename.h"
30 
31 #include "gaiagraphics.h"
32 
33 #ifdef _WIN32
34 #include <windows.h>
35 #include <process.h>
36 #include <io.h>
37 #else
38 #include <pthread.h>
39 #include <unistd.h>
40 #endif
41 
42 //
43 // ICONs in XPM format [universally portable]
44 //
45 #include "icons/rs_first.xpm"
46 #include "icons/rs_last.xpm"
47 #include "icons/rs_next.xpm"
48 #include "icons/rs_previous.xpm"
49 #include "icons/refresh.xpm"
50 
51 #if defined(_WIN32) || defined (__MINGW32__)
52 #define FORMAT_64	"%I64d"
53 #else
54 #define FORMAT_64	"%lld"
55 #endif
56 
MyResultSetView(MyFrame * parent,wxWindowID id)57 MyResultSetView::MyResultSetView(MyFrame * parent, wxWindowID id):
58 wxPanel(parent, id, wxDefaultPosition, wxSize(440, 480), wxBORDER_SUNKEN)
59 {
60 //
61 // constructor: a frame for SQL Result Sets
62 //
63   RsBlock = 500;                // the ResultSet block size
64   RowIds = new sqlite3_int64[RsBlock];
65   ReadOnly = true;
66   InsertRow = NULL;
67   MainFrame = parent;
68   BtnRsFirst =
69     new wxBitmapButton(this, ID_RS_FIRST, wxBitmap(rs_first_xpm),
70                        wxPoint(5, 400), wxSize(32, 32));
71   BtnRsFirst->SetToolTip(wxT("ResultSet: go to first row"));
72   BtnRsPrevious =
73     new wxBitmapButton(this, ID_RS_PREVIOUS, wxBitmap(rs_previous_xpm),
74                        wxPoint(55, 400), wxSize(32, 32));
75   BtnRsPrevious->SetToolTip(wxT("ResultSet: go to previous block"));
76   BtnRefresh =
77     new wxBitmapButton(this, ID_REFRESH, wxBitmap(refresh_xpm),
78                        wxPoint(55, 400), wxSize(32, 32));
79   BtnRefresh->SetToolTip(wxT("ResultSet: refresh"));
80   BtnRsNext =
81     new wxBitmapButton(this, ID_RS_NEXT, wxBitmap(rs_next_xpm),
82                        wxPoint(105, 400), wxSize(32, 32));
83   BtnRsNext->SetToolTip(wxT("ResultSet: go to next block"));
84   BtnRsLast =
85     new wxBitmapButton(this, ID_RS_LAST, wxBitmap(rs_last_xpm),
86                        wxPoint(155, 400), wxSize(32, 32));
87   BtnRsLast->SetToolTip(wxT("ResultSet: go to last row"));
88   RsCurrentBlock =
89     new wxStaticText(this, ID_RS_BLOCK, wxT(""), wxPoint(210, 400),
90                      wxSize(200, 18));
91   TableView = NULL;
92   TableBlobs = NULL;
93   TableValues = NULL;
94   CurrentBlob = NULL;
95 // setting up event handlers
96   Connect(ID_RS_FIRST, wxEVT_COMMAND_BUTTON_CLICKED,
97           (wxObjectEventFunction) & MyResultSetView::OnRsFirst);
98   Connect(ID_RS_PREVIOUS, wxEVT_COMMAND_BUTTON_CLICKED,
99           (wxObjectEventFunction) & MyResultSetView::OnRsPrevious);
100   Connect(ID_RS_NEXT, wxEVT_COMMAND_BUTTON_CLICKED,
101           (wxObjectEventFunction) & MyResultSetView::OnRsNext);
102   Connect(ID_RS_LAST, wxEVT_COMMAND_BUTTON_CLICKED,
103           (wxObjectEventFunction) & MyResultSetView::OnRsLast);
104   Connect(ID_REFRESH, wxEVT_COMMAND_BUTTON_CLICKED,
105           (wxObjectEventFunction) & MyResultSetView::OnRefresh);
106   Connect(ID_RS_THREAD_FINISHED, wxEVT_COMMAND_BUTTON_CLICKED,
107           (wxObjectEventFunction) & MyResultSetView::OnThreadFinished);
108   Connect(ID_RS_STATS_UPDATE, wxEVT_COMMAND_BUTTON_CLICKED,
109           (wxObjectEventFunction) & MyResultSetView::OnStatsUpdate);
110   Connect(wxID_ANY, wxEVT_SIZE,
111           (wxObjectEventFunction) & MyResultSetView::OnSize);
112   Connect(wxID_ANY, wxEVT_GRID_SELECT_CELL,
113           (wxObjectEventFunction) & MyResultSetView::OnCellSelected);
114   Connect(wxID_ANY, wxEVT_GRID_CELL_RIGHT_CLICK,
115           (wxObjectEventFunction) & MyResultSetView::OnRightClick);
116   Connect(wxID_ANY, wxEVT_GRID_CELL_CHANGE,
117           (wxObjectEventFunction) & MyResultSetView::OnCellChanged);
118   Connect(Grid_Delete, wxEVT_COMMAND_MENU_SELECTED,
119           (wxObjectEventFunction) & MyResultSetView::OnCmdDelete);
120   Connect(Grid_Insert, wxEVT_COMMAND_MENU_SELECTED,
121           (wxObjectEventFunction) & MyResultSetView::OnCmdInsert);
122   Connect(Grid_Abort, wxEVT_COMMAND_MENU_SELECTED,
123           (wxObjectEventFunction) & MyResultSetView::OnCmdAbort);
124   Connect(Grid_Clear, wxEVT_COMMAND_MENU_SELECTED,
125           (wxObjectEventFunction) & MyResultSetView::OnCmdClearSelection);
126   Connect(Grid_All, wxEVT_COMMAND_MENU_SELECTED,
127           (wxObjectEventFunction) & MyResultSetView::OnCmdSelectAll);
128   Connect(Grid_Row, wxEVT_COMMAND_MENU_SELECTED,
129           (wxObjectEventFunction) & MyResultSetView::OnCmdSelectRow);
130   Connect(Grid_Column, wxEVT_COMMAND_MENU_SELECTED,
131           (wxObjectEventFunction) & MyResultSetView::OnCmdSelectColumn);
132   Connect(Grid_Copy, wxEVT_COMMAND_MENU_SELECTED,
133           (wxObjectEventFunction) & MyResultSetView::OnCmdCopy);
134   Connect(Grid_Blob, wxEVT_COMMAND_MENU_SELECTED,
135           (wxObjectEventFunction) & MyResultSetView::OnCmdBlob);
136   Connect(Grid_BlobIn, wxEVT_COMMAND_MENU_SELECTED,
137           (wxObjectEventFunction) & MyResultSetView::OnCmdBlobIn);
138   Connect(Grid_BlobOut, wxEVT_COMMAND_MENU_SELECTED,
139           (wxObjectEventFunction) & MyResultSetView::OnCmdBlobOut);
140   Connect(Grid_BlobNull, wxEVT_COMMAND_MENU_SELECTED,
141           (wxObjectEventFunction) & MyResultSetView::OnCmdBlobNull);
142   Connect(Grid_XmlBlobIn, wxEVT_COMMAND_MENU_SELECTED,
143           (wxObjectEventFunction) & MyResultSetView::OnCmdXmlBlobIn);
144   Connect(Grid_XmlBlobOut, wxEVT_COMMAND_MENU_SELECTED,
145           (wxObjectEventFunction) & MyResultSetView::OnCmdXmlBlobOut);
146   Connect(Grid_XmlBlobOutIndented, wxEVT_COMMAND_MENU_SELECTED,
147           (wxObjectEventFunction) & MyResultSetView::OnCmdXmlBlobOutIndented);
148   Connect(Grid_ExpTxtTab, wxEVT_COMMAND_MENU_SELECTED,
149           (wxObjectEventFunction) & MyResultSetView::OnCmdExpTxtTab);
150   Connect(Grid_ExpCsv, wxEVT_COMMAND_MENU_SELECTED,
151           (wxObjectEventFunction) & MyResultSetView::OnCmdExpCsv);
152   Connect(Grid_ExpHtml, wxEVT_COMMAND_MENU_SELECTED,
153           (wxObjectEventFunction) & MyResultSetView::OnCmdExpHtml);
154   Connect(Grid_ExpShp, wxEVT_COMMAND_MENU_SELECTED,
155           (wxObjectEventFunction) & MyResultSetView::OnCmdExpShp);
156   Connect(Grid_ExpDif, wxEVT_COMMAND_MENU_SELECTED,
157           (wxObjectEventFunction) & MyResultSetView::OnCmdExpDif);
158   Connect(Grid_ExpSylk, wxEVT_COMMAND_MENU_SELECTED,
159           (wxObjectEventFunction) & MyResultSetView::OnCmdExpSylk);
160   Connect(Grid_ExpDbf, wxEVT_COMMAND_MENU_SELECTED,
161           (wxObjectEventFunction) & MyResultSetView::OnCmdExpDbf);
162 }
163 
~MyResultSetView()164 MyResultSetView::~MyResultSetView()
165 {
166 // destructor
167   if (RowIds)
168     delete[]RowIds;
169   if (InsertRow)
170     delete InsertRow;
171   if (TableBlobs)
172     delete TableBlobs;
173   if (TableValues)
174     delete TableValues;
175 }
176 
ShowControls()177 void MyResultSetView::ShowControls()
178 {
179 //
180 // making all ResultSet controls to be visible
181 //
182   BtnRsFirst->Show(true);
183   BtnRsPrevious->Show(true);
184   BtnRsNext->Show(true);
185   BtnRsLast->Show(true);
186   BtnRefresh->Show(true);
187 }
188 
HideControls()189 void MyResultSetView::HideControls()
190 {
191 //
192 // making all controls to be invisible
193 //
194   BtnRsFirst->Show(false);
195   BtnRsPrevious->Show(false);
196   BtnRsNext->Show(false);
197   BtnRsLast->Show(false);
198   BtnRefresh->Show(false);
199 }
200 
EditTable(wxString & sql,int * primaryKeys,int * blobCols,wxString & table)201 void MyResultSetView::EditTable(wxString & sql, int *primaryKeys, int *blobCols,
202                                 wxString & table)
203 {
204 //
205 // starting the edit table sequence
206 //
207   int i;
208   for (i = 0; i < 1024; i++)
209     {
210       PrimaryKeys[i] = *(primaryKeys + i);
211       BlobColumns[i] = *(blobCols + i);
212     }
213   ReadOnly = false;
214   TableName = table;
215   MainFrame->GetQueryView()->GetSqlCtrl()->SetValue(sql);
216   if (ExecuteSqlPre(sql, 0, ReadOnly) == false)
217     wxMessageBox(SqlErrorMsg, wxT("spatialite_gui"), wxOK | wxICON_ERROR,
218                  MainFrame);
219 }
220 
FormatElapsedTime(double seconds,char * elapsed,bool simple)221 void MyResultSetView::FormatElapsedTime(double seconds, char *elapsed,
222                                         bool simple)
223 {
224 /* well formatting elapsed time */
225   int int_time = (int) seconds;
226   int millis = (int) ((seconds - (double) int_time) * 1000.0);
227   int secs = int_time % 60;
228   int_time /= 60;
229   int mins = int_time % 60;
230   int_time /= 60;
231   int hh = int_time;
232   if (simple == true)
233     {
234       if (hh == 0 && mins == 0)
235         sprintf(elapsed, "%d.%03d", secs, millis);
236       else if (hh == 0)
237         sprintf(elapsed, "%d:%02d.%03d", mins, secs, millis);
238       else
239         sprintf(elapsed, "%d:%02d:%02d.%03d", hh, mins, secs, millis);
240   } else
241     sprintf(elapsed, "%02d:%02d:%02d.%03d", hh, mins, secs, millis);
242 }
243 
Reset(void)244 void SqlThreadParams::Reset(void)
245 {
246 //
247 // thread params: resetting to empty state
248 //
249   Mother = NULL;
250   Sql = wxT("");
251   Stmt = NULL;
252   FromRow = 0;
253   EndRow = 0;
254   MaxRow = 0;
255   List.Reset();
256   Sqlite = NULL;
257   Start = 0;
258   LastGuiUpdate = 0;
259   Error = false;
260   FetchedRows = 0;
261   StatFullscanStep = 0;
262   StatSort = 0;
263   StatAutoindex = 0;
264   ElapsedTime = 0.0;
265   AbortRequested = false;
266   Valid = false;
267 }
268 
Initialize(MyResultSetView * mother,wxString & sql,sqlite3_stmt * stmt,int from,sqlite3 * sqlite,clock_t start)269 void SqlThreadParams::Initialize(MyResultSetView * mother, wxString & sql,
270                                  sqlite3_stmt * stmt, int from,
271                                  sqlite3 * sqlite, clock_t start)
272 {
273 //
274 // thread params: initializing
275 //
276   Reset();
277   Mother = mother;
278   Sql = sql;
279   Stmt = stmt;
280   FromRow = from;
281   EndRow = 0;
282   MaxRow = 0;
283   Sqlite = sqlite;
284   Start = start;
285   LastGuiUpdate = start;
286   Error = false;
287   FetchedRows = 0;
288   StatFullscanStep = 0;
289   StatSort = 0;
290   StatAutoindex = 0;
291   ElapsedTime = 0.0;
292   AbortRequested = false;
293   Valid = true;
294 }
295 
UpdateStats(int fullscan,int sort,int autoindex,clock_t now)296 void SqlThreadParams::UpdateStats(int fullscan, int sort, int autoindex,
297                                   clock_t now)
298 {
299 //
300 // updading Stats (SQL query progress handler callback)
301 //
302   StatFullscanStep = fullscan;
303   StatSort = sort;
304   StatAutoindex = autoindex;
305   ElapsedTime = (double) (now - Start) / (double) CLOCKS_PER_SEC;
306 }
307 
GuiHasToBeUpdated(clock_t now,int millisecs)308 bool SqlThreadParams::GuiHasToBeUpdated(clock_t now, int millisecs)
309 {
310 //
311 // checking if a GUI update is required (Stats)
312 //
313   double interval = (double) (now - LastGuiUpdate) / (double) CLOCKS_PER_SEC;
314   if (interval >= ((double) millisecs / 1000.0))
315     return true;
316   return false;
317 }
318 
SqlProgressCallback(void * arg)319 int SqlProgressCallback(void *arg)
320 {
321 //
322 // SQL query progress handler callback function
323 //
324   int fullscan;
325   int sort;
326   int autoindex;
327   clock_t clock_end;
328   wxString currentBlock;
329   SqlThreadParams *params = (SqlThreadParams *) arg;
330 
331   if (params->IsValid() == false)
332     return 0;
333 
334   if (params->IsAbortRequested() == true)
335     {
336       // aborting the SQL query
337       sqlite3_interrupt(params->GetSqlite());
338       return 0;
339     }
340 // updating query stats
341   fullscan =
342     sqlite3_stmt_status(params->GetStmt(), SQLITE_STMTSTATUS_FULLSCAN_STEP, 0);
343   sort = sqlite3_stmt_status(params->GetStmt(), SQLITE_STMTSTATUS_SORT, 0);
344 #ifdef OMIT_SQLITE_STMTSTATUS_AUTOINXED
345   autoindex = -1;
346 #else
347   autoindex =
348     sqlite3_stmt_status(params->GetStmt(), SQLITE_STMTSTATUS_AUTOINDEX, 0);
349 #endif
350   clock_end = clock();
351   params->UpdateStats(fullscan, sort, autoindex, clock_end);
352   if (params->GuiHasToBeUpdated(clock_end, 500) == true)
353     {
354       // requesting a GUI update
355       wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, ID_RS_STATS_UPDATE);
356       params->GetMother()->GetEventHandler()->AddPendingEvent(event);
357       params->SetLastGuiUpdate(clock_end);
358     }
359   return 0;
360 }
361 
362 #ifdef _WIN32
DoExecuteSqlThread(void * arg)363 DWORD WINAPI DoExecuteSqlThread(void *arg)
364 #else
365 void *DoExecuteSqlThread(void *arg)
366 #endif
367 {
368 //
369 // threaded function: processing an SQL query
370 //
371   int ret;
372   int i_col;
373   int i_row = 0;
374   int end_row = 0;
375   int columns;
376   char err_msg[2048];
377 
378 // setting up the sqlite's progress handler callback
379   SqlThreadParams *params = (SqlThreadParams *) arg;
380   sqlite3_progress_handler(params->GetSqlite(), 1000, SqlProgressCallback, arg);
381 
382   while (1)
383     {
384       //
385       // fetching the result set rows
386       //
387       if (params->IsValid() == false)
388         goto error;
389       ret = sqlite3_step(params->GetStmt());
390       if (ret == SQLITE_DONE)
391         break;                  // end of result set
392       if (ret == SQLITE_ROW)
393         {
394           //
395           // fetching a row
396           //
397           if (params->IsAbortRequested() == true)
398             {
399               // aborting the SQL query
400               sqlite3_interrupt(params->GetSqlite());
401               continue;
402             }
403 
404           params->FetchedRow();
405           if ((params->GetFetchedRows() % 1000) == 0)
406             SqlProgressCallback(params);
407           if (i_row < params->GetFromRow())
408             {
409               i_row++;
410               continue;
411             }
412           if ((i_row - params->GetFromRow()) >=
413               params->GetMother()->GetRsBlock())
414             {
415               i_row++;
416               continue;
417             }
418           end_row = i_row;
419           columns = sqlite3_column_count(params->GetStmt());
420           MyRowVariant *rowVariant = params->GetList()->Add(columns);
421           for (i_col = 0; i_col < columns; i_col++)
422             {
423               sqlite3_int64 int_value;
424               double dbl_value;
425               const unsigned char *txt_value;
426               const void *blob_value;
427               int blobSize;
428               params->GetList()->SetColumnName(i_col,
429                                                sqlite3_column_name
430                                                (params->GetStmt(), i_col));
431               switch (sqlite3_column_type(params->GetStmt(), i_col))
432                 {
433                   case SQLITE_INTEGER:
434                     int_value = sqlite3_column_int64(params->GetStmt(), i_col);
435                     rowVariant->Set(i_col, int_value);
436                     break;
437                   case SQLITE_FLOAT:
438                     dbl_value = sqlite3_column_double(params->GetStmt(), i_col);
439                     rowVariant->Set(i_col, dbl_value);
440                     break;
441                   case SQLITE_TEXT:
442                     txt_value = sqlite3_column_text(params->GetStmt(), i_col);
443                     rowVariant->Set(i_col, txt_value);
444                     break;
445                   case SQLITE_BLOB:
446                     blob_value = sqlite3_column_blob(params->GetStmt(), i_col);
447                     blobSize = sqlite3_column_bytes(params->GetStmt(), i_col);
448                     rowVariant->Set(i_col, blob_value, blobSize);
449                     break;
450                   case SQLITE_NULL:
451                   default:
452                     break;
453                 };
454             }
455           i_row++;
456       } else
457         {
458           sprintf(err_msg, "SQL error: %s",
459                   sqlite3_errmsg(params->GetSqlite()));
460           sqlite3_finalize(params->GetStmt());
461           wxString msg = wxString::FromUTF8(err_msg);
462           params->GetMother()->SetSqlErrorMsg(msg);
463           goto error;
464         }
465     }
466   sqlite3_finalize(params->GetStmt());
467   params->SetEndRow(end_row);
468   params->SetMaxRow(i_row);
469   goto ok;
470 error:
471   params->SetError();
472 ok:
473   wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, ID_RS_THREAD_FINISHED);
474   params->GetMother()->GetEventHandler()->AddPendingEvent(event);
475 #ifdef _WIN32
476   return 0;
477 #else
478   pthread_exit(NULL);
479 #endif
480 }
481 
AbortRequested()482 void MyResultSetView::AbortRequested()
483 {
484 //
485 // attempting to abort the current SQL query
486 //
487   if (ThreadParams.IsValid() == true)
488     ThreadParams.Abort();
489 }
490 
ExecuteSqlPre(wxString & sql,int from,bool read_only)491 bool MyResultSetView::ExecuteSqlPre(wxString & sql, int from, bool read_only)
492 {
493 //
494 // executing some SQL statement
495 //
496   ReadOnly = read_only;
497   char *xSql = NULL;
498   char err_msg[2048];
499   int i_row;
500   clock_t clock_start;
501   sqlite3_stmt *stmt;
502   sqlite3 *sqlite = MainFrame->GetSqlite();
503   SqlErrorMsg = wxT("");
504   if (TableView)
505     TableView->Destroy();
506   TableView = NULL;
507   if (TableBlobs)
508     delete TableBlobs;
509   if (TableValues)
510     delete TableValues;
511   TableBlobs = NULL;
512   TableValues = NULL;
513   CurrentBlob = NULL;
514   HideControls();
515   RsBeginRow = 0;
516   RsEndRow = 0;
517   RsMaxRow = 0;
518 #ifdef _WIN32
519   HANDLE thread_handle;
520   DWORD dwThreadId;
521 #else
522   pthread_t thread_id;
523 #endif
524   for (i_row = 0; i_row < RsBlock; i_row++)
525     RowIds[i_row] = -1;
526   i_row = 0;
527   xSql = new char[65536];
528   strcpy(xSql, sql.ToUTF8());
529 
530   clock_start = clock();
531   int ret = sqlite3_prepare_v2(sqlite, xSql, strlen(xSql), &stmt, NULL);
532   delete[]xSql;
533   if (ret != SQLITE_OK)
534     {
535       sprintf(err_msg, "SQL error: %s", sqlite3_errmsg(sqlite));
536       SqlErrorMsg = wxString::FromUTF8(err_msg);
537       ::wxEndBusyCursor();
538       return false;
539     }
540   CreateStatsGrid();
541   ::wxBeginBusyCursor();
542 
543   ThreadParams.Initialize(this, sql, stmt, from, sqlite, clock_start);
544 #ifdef _WIN32
545   thread_handle =
546     CreateThread(NULL, 0, DoExecuteSqlThread, &ThreadParams, 0, &dwThreadId);
547   SetThreadPriority(thread_handle, THREAD_PRIORITY_IDLE);
548 #else
549   int ok_prior = 0;
550   int policy;
551   int min_prio;
552   pthread_attr_t attr;
553   struct sched_param sp;
554   pthread_attr_init(&attr);
555   if (pthread_attr_setschedpolicy(&attr, SCHED_RR) == 0)
556     {
557       // attempting to set the lowest priority
558       if (pthread_attr_getschedpolicy(&attr, &policy) == 0)
559         {
560           min_prio = sched_get_priority_min(policy);
561           sp.sched_priority = min_prio;
562           if (pthread_attr_setschedparam(&attr, &sp) == 0)
563             {
564               // ok, setting the lowest priority
565               ok_prior = 1;
566               pthread_create(&thread_id, &attr, DoExecuteSqlThread,
567                              &ThreadParams);
568             }
569         }
570     }
571   if (!ok_prior)
572     {
573       // failure: using standard priority
574       pthread_create(&thread_id, NULL, DoExecuteSqlThread, &ThreadParams);
575     }
576 #endif
577   MainFrame->GetQueryView()->EnableAbortButton();
578   return true;
579 }
580 
ExecuteSqlPost()581 bool MyResultSetView::ExecuteSqlPost()
582 {
583   char dummy[1024];
584   int i_col;
585   int i_row;
586   double seconds;
587   clock_t clock_end;
588   char elapsed[64];
589   MyRowVariant *row;
590   MyVariant *value;
591   wxString blobType;
592   int type;
593   wxString cellValue;
594   wxString currentBlock;
595   MyVariantList *list;
596 
597   MainFrame->GetQueryView()->DisableAbortButton();
598   if (TableView)
599     TableView->Destroy();
600   TableView = NULL;
601   if (TableBlobs)
602     delete TableBlobs;
603   if (TableValues)
604     delete TableValues;
605   TableBlobs = NULL;
606   TableValues = NULL;
607   CurrentBlob = NULL;
608 
609   if (ThreadParams.IsValid() == false)
610     {
611       if (SqlErrorMsg.Len() > 0)
612         {
613           wxMessageBox(SqlErrorMsg, wxT("spatialite_gui"), wxOK | wxICON_ERROR,
614                        MainFrame);
615           ::wxEndBusyCursor();
616           ThreadParams.Reset();
617           return true;
618         }
619       goto error;
620     }
621   if (ThreadParams.IsError() == true)
622     {
623       if (SqlErrorMsg.Len() > 0)
624         {
625           wxMessageBox(SqlErrorMsg, wxT("spatialite_gui"), wxOK | wxICON_ERROR,
626                        MainFrame);
627           ::wxEndBusyCursor();
628           ThreadParams.Reset();
629           return true;
630         }
631       goto error;
632     }
633 
634   list = ThreadParams.GetList();
635   clock_end = clock();
636   seconds =
637     (double) (clock_end - ThreadParams.GetStart()) / (double) CLOCKS_PER_SEC;
638   RsBeginRow = ThreadParams.GetFromRow();
639   RsEndRow = ThreadParams.GetEndRow();
640   RsMaxRow = ThreadParams.GetMaxRow();
641   if (list->GetRows() == 0)
642     {
643       //
644       // this one is an EMPTY Result Set
645       //
646       if (ReadOnly == false)
647         {
648           // preparing the insert row
649           int numCols = 0;
650           wxString *colNames = MainFrame->GetColumnNames(TableName, &numCols);
651           CreateGrid(0, numCols + 1);
652           TableView->SetColLabelValue(0, wxT("ROWID"));
653           for (i_col = 0; i_col < numCols; i_col++)
654             TableView->SetColLabelValue(i_col + 1, *(colNames + i_col));
655           TableView->EnableEditing(true);
656           delete[]colNames;
657       } else
658         {
659           // simply showing a warning message
660           CreateGrid(1, 1);
661           TableView->SetColLabelValue(0, wxT("Message"));
662           TableView->SetRowLabelValue(0, wxT("Message"));
663           TableView->SetCellValue(0, 0,
664                                   wxT
665                                   ("SQL query returned an empty ResultSet\n\nThis is not an error"));
666         }
667   } else
668     {
669       //
670       // preparing the Grid to show the result set
671       //
672       CreateGrid(list->GetRows(), list->GetColumns());
673       if (ReadOnly == true)
674         TableView->EnableEditing(false);
675       else
676         TableView->EnableEditing(true);
677       for (i_col = 0; i_col < list->GetColumns(); i_col++)
678         TableView->SetColLabelValue(i_col, list->GetColumnName(i_col));
679       if (ReadOnly == false)
680         TableView->SetColLabelValue(0, wxT("ROWID"));
681       i_row = 0;
682       row = list->GetFirst();
683       while (row)
684         {
685           sprintf(dummy, "%d", i_row + RsBeginRow + 1);
686           cellValue = wxString::FromUTF8(dummy);
687           TableView->SetRowLabelValue(i_row, cellValue);
688           if (ReadOnly == false)
689             {
690               // storing the ROWID value into the RowIds array
691               value = row->GetColumn(0);
692               if (value->GetType() == MY_INT_VARIANT)
693                 RowIds[i_row] = value->GetIntValue();
694             }
695           for (i_col = 0; i_col < row->GetNumCols(); i_col++)
696             {
697               value = row->GetColumn(i_col);
698               if (value)
699                 {
700                   switch (value->GetType())
701                     {
702                       case MY_INT_VARIANT:
703                         sprintf(dummy, FORMAT_64, value->GetIntValue());
704                         cellValue = wxString::FromUTF8(dummy);
705                         TableView->SetCellValue(i_row, i_col, cellValue);
706                         if (ReadOnly == false)
707                           TableValues->SetValue(i_row, i_col,
708                                                 value->GetIntValue());
709                         TableView->SetCellAlignment(i_row, i_col, wxALIGN_RIGHT,
710                                                     wxALIGN_TOP);
711                         break;
712                       case MY_DBL_VARIANT:
713                         sprintf(dummy, "%1.6f", value->GetDblValue());
714                         cellValue = wxString::FromUTF8(dummy);
715                         TableView->SetCellValue(i_row, i_col, cellValue);
716                         if (ReadOnly == false)
717                           TableValues->SetValue(i_row, i_col,
718                                                 value->GetDblValue());
719                         TableView->SetCellAlignment(i_row, i_col, wxALIGN_RIGHT,
720                                                     wxALIGN_TOP);
721                         break;
722                       case MY_TXT_VARIANT:
723                         TableView->SetCellValue(i_row, i_col,
724                                                 value->GetTxtValue());
725                         if (ReadOnly == false)
726                           TableValues->SetValue(i_row, i_col,
727                                                 value->GetTxtValue());
728                         break;
729                       case MY_BLOB_VARIANT:
730                         blobType = wxT("UNKNOWN type");
731                         type =
732                           gaiaGuessBlobType(value->GetBlob(),
733                                             value->GetBlobSize());
734                         switch (type)
735                           {
736                             case GAIA_GEOMETRY_BLOB:
737                               blobType = wxT("GEOMETRY");
738                               break;
739                             case GAIA_XML_BLOB:
740                               blobType = wxT("XmlBLOB");
741                               break;
742                             case GAIA_JPEG_BLOB:
743                               blobType = wxT("JPEG image");
744                               break;
745                             case GAIA_EXIF_BLOB:
746                               blobType = wxT("JPEG-EXIF image");
747                               break;
748                             case GAIA_EXIF_GPS_BLOB:
749                               blobType = wxT("JPEG-EXIF-GPS image");
750                               break;
751                             case GAIA_PNG_BLOB:
752                               blobType = wxT("PNG image");
753                               break;
754                             case GAIA_GIF_BLOB:
755                               blobType = wxT("GIF image");
756                               break;
757                             case GAIA_TIFF_BLOB:
758                               blobType = wxT("TIFF image");
759                               break;
760                             case GAIA_PDF_BLOB:
761                               blobType = wxT("PDF document");
762                               break;
763                             case GAIA_ZIP_BLOB:
764                               blobType = wxT("ZIP archive");
765                               break;
766                             default:
767                               if (gGraphIsRawImage
768                                   (value->GetBlob(),
769                                    value->GetBlobSize()) == GGRAPH_OK)
770                                 blobType = wxT("RasterLite RAW image");
771                               break;
772                           };
773                         if (type == GAIA_XML_BLOB)
774                           {
775 #ifdef ENABLE_LIBXML2           /* only if LIBXML2 is enabled */
776 
777                             int doc_size =
778                               gaiaXmlBlobGetDocumentSize(value->GetBlob(),
779                                                          value->GetBlobSize());
780                             if (gaiaIsSvgXmlBlob
781                                 (value->GetBlob(), value->GetBlobSize()))
782                               sprintf(dummy, "XmlBLOB-SVG sz=%d (XMLsz=%d) ",
783                                       value->GetBlobSize(), doc_size);
784                             else if (gaiaIsIsoMetadataXmlBlob
785                                      (value->GetBlob(), value->GetBlobSize()))
786                               sprintf(dummy,
787                                       "XmlBLOB-ISOmetadata sz=%d (XMLsz=%d) ",
788                                       value->GetBlobSize(), doc_size);
789                             else
790                               if (gaiaIsSldSeVectorStyleXmlBlob
791                                   (value->GetBlob(), value->GetBlobSize()))
792                               sprintf(dummy,
793                                       "XmlBLOB-VectorStyle sz=%d (XMLsz=%d) ",
794                                       value->GetBlobSize(), doc_size);
795                             else
796                               if (gaiaIsSldSeRasterStyleXmlBlob
797                                   (value->GetBlob(), value->GetBlobSize()))
798                               sprintf(dummy,
799                                       "XmlBLOB-RasterStyle sz=%d (XMLsz=%d) ",
800                                       value->GetBlobSize(), doc_size);
801                             else
802                               sprintf(dummy, "XmlBLOB sz=%d (XMLsz=%d) ",
803                                       value->GetBlobSize(), doc_size);
804                             cellValue = wxString::FromUTF8(dummy);
805                             if (gaiaIsSchemaValidatedXmlBlob
806                                 (value->GetBlob(), value->GetBlobSize()))
807                               cellValue += wxT(" SchemaValidated");
808 
809 #endif /* end LIBXML2 conditionals */
810                         } else
811                           {
812                             sprintf(dummy, "BLOB sz=%d ", value->GetBlobSize());
813                             cellValue = wxString::FromUTF8(dummy);
814                             cellValue += blobType;
815                           }
816                         TableView->SetCellValue(i_row, i_col, cellValue);
817                         TableView->SetReadOnly(i_row, i_col);
818                         TableBlobs->SetBlob(i_row, i_col, value);
819                         break;
820                       case MY_NULL_VARIANT:
821                       default:
822                         TableView->SetCellValue(i_row, i_col, wxT("NULL"));
823                         break;
824                     };
825               } else
826                 TableView->SetCellValue(i_row, i_col, wxT("NULL"));
827               if (ReadOnly == false)
828                 {
829                   if (IsPrimaryKey(i_col) == true)
830                     TableView->SetReadOnly(i_row, i_col);
831                   if (IsBlobColumn(i_col) == true)
832                     TableView->SetReadOnly(i_row, i_col);
833                 }
834             }
835           i_row++;
836           row = row->GetNext();
837         }
838     }
839   if (ReadOnly == false)
840     {
841       // prepearing the insert row
842       TableView->SetRowLabelValue(TableView->GetNumberRows() - 1,
843                                   wxT("Insert row"));
844       InsertPending = false;
845       for (i_col = 0; i_col < TableView->GetNumberCols(); i_col++)
846         {
847           TableView->SetCellValue(TableView->GetNumberRows() - 1, i_col,
848                                   wxT(""));
849           TableView->SetCellBackgroundColour(TableView->GetNumberRows() - 1,
850                                              i_col, wxColour(0, 0, 0));
851           TableView->SetReadOnly(TableView->GetNumberRows() - 1, i_col);
852         }
853     }
854   TableView->SetRowLabelSize(wxGRID_AUTOSIZE);
855   TableView->AutoSize();
856   ResizeView();
857   FormatElapsedTime(seconds, elapsed);
858   sprintf(dummy, "current block: %d / %d [%d rows]    [fetched in %s]",
859           RsBeginRow + 1, RsEndRow + 1, RsMaxRow, elapsed);
860   currentBlock = wxString::FromUTF8(dummy);
861   RsCurrentBlock->SetLabel(currentBlock);
862   ShowControls();
863   MainFrame->GetQueryView()->AddToHistory(ThreadParams.GetSql());
864   ThreadParams.Reset();
865   ::wxEndBusyCursor();
866   return true;
867 error:
868   ::wxEndBusyCursor();
869   ThreadParams.Reset();
870   return false;
871 }
872 
IsPrimaryKey(int column)873 bool MyResultSetView::IsPrimaryKey(int column)
874 {
875 //
876 // checks if this column is a Primary Key one
877 //
878   int i;
879   for (i = 0; i < 1024; i++)
880     {
881       if (PrimaryKeys[i] == column)
882         return true;
883     }
884   return false;
885 }
886 
IsBlobColumn(int column)887 bool MyResultSetView::IsBlobColumn(int column)
888 {
889 //
890 // checks if this column is a BLOB-type column
891 //
892   int i;
893   for (i = 0; i < 1024; i++)
894     {
895       if (BlobColumns[i] == column)
896         return true;
897     }
898   return false;
899 }
900 
CreateGrid(int rows,int cols)901 void MyResultSetView::CreateGrid(int rows, int cols)
902 {
903 //
904 // creating a new Grid to show the result set
905 //
906   int extra = 0;
907   if (ReadOnly == false)
908     extra = 1;
909   TableView = new wxGrid(this, wxID_ANY, wxPoint(5, 5), wxSize(200, 200));
910   TableView->Show(false);
911   TableView->CreateGrid(rows + extra, cols);
912   TableBlobs = new MyBlobs(rows, cols);
913   if (ReadOnly == false)
914     TableValues = new MyValues(rows, cols);
915 }
916 
CreateStatsGrid()917 void MyResultSetView::CreateStatsGrid()
918 {
919 //
920 // creating a new Grid to show the SQL query stats (progress handler)
921 //
922   wxSize sz = GetClientSize();
923   TableView = new wxGrid(this, wxID_ANY, wxPoint(5, 5), wxSize(200, 200));
924   TableView->Show(false);
925   TableView->CreateGrid(5, 2);
926   TableView->EnableEditing(false);
927   TableView->SetColLabelValue(0, wxT("Progress Counter"));
928   TableView->SetColLabelValue(1, wxT("Current Value"));
929   TableView->SetCellValue(0, 0, wxT("FullscanStep"));
930   TableView->SetCellValue(1, 0, wxT("Sort"));
931   TableView->SetCellValue(2, 0, wxT("Autoindex"));
932   TableView->SetCellValue(3, 0, wxT("FetchedRows"));
933   TableView->SetCellValue(4, 0, wxT("ElapsedTime"));
934   TableView->SetCellBackgroundColour(4, 0, wxColour(128, 255, 128));
935   TableView->SetCellValue(0, 1, wxT("0"));
936   TableView->SetCellAlignment(0, 1, wxALIGN_RIGHT, wxALIGN_CENTRE);
937   TableView->SetCellValue(1, 1, wxT("0"));
938   TableView->SetCellAlignment(1, 1, wxALIGN_RIGHT, wxALIGN_CENTRE);
939   TableView->SetCellValue(2, 1, wxT("0"));
940   TableView->SetCellAlignment(2, 1, wxALIGN_RIGHT, wxALIGN_CENTRE);
941   TableView->SetCellValue(3, 1, wxT("0"));
942   TableView->SetCellAlignment(3, 1, wxALIGN_RIGHT, wxALIGN_CENTRE);
943   TableView->SetCellValue(4, 1, wxT("0"));
944   TableView->SetCellAlignment(4, 1, wxALIGN_RIGHT, wxALIGN_CENTRE);
945   TableView->SetRowLabelSize(wxGRID_AUTOSIZE);
946   TableView->AutoSize();
947   TableView->SetSize(sz.GetWidth() - 10, sz.GetHeight() - 45);
948   TableView->Show(true);
949   TableView->Disable();
950   wxString msg = wxT("... wait please: SQL query in progress ...");
951   RsCurrentBlock->SetLabel(msg);
952 }
953 
ResizeView()954 void MyResultSetView::ResizeView()
955 {
956 //
957 // resizing the Grid to show the result set
958 //
959   wxSize sz = GetClientSize();
960   if (TableView)
961     {
962       TableView->SetSize(sz.GetWidth() - 10, sz.GetHeight() - 45);
963       TableView->Show(true);
964     }
965 }
966 
OnSize(wxSizeEvent & WXUNUSED (event))967 void MyResultSetView::OnSize(wxSizeEvent & WXUNUSED(event))
968 {
969 //
970 // this window has changed its size
971 //
972   wxSize sz = GetClientSize();
973   if (TableView)
974     TableView->SetSize(sz.GetWidth() - 10, sz.GetHeight() - 45);
975   BtnRsFirst->Move(5, sz.GetHeight() - 35);
976   BtnRsPrevious->Move(40, sz.GetHeight() - 35);
977   BtnRefresh->Move(75, sz.GetHeight() - 35);
978   BtnRsNext->Move(110, sz.GetHeight() - 35);
979   BtnRsLast->Move(145, sz.GetHeight() - 35);
980   RsCurrentBlock->Move(180, sz.GetHeight() - 25);
981 }
982 
OnRsFirst(wxCommandEvent & WXUNUSED (event))983 void MyResultSetView::OnRsFirst(wxCommandEvent & WXUNUSED(event))
984 {
985 //
986 // scrolling to the result set beginning
987 //
988   wxString sql = MainFrame->GetQueryView()->GetSqlCtrl()->GetValue();
989   if (ExecuteSqlPre(sql, 0, ReadOnly) == false)
990     wxMessageBox(SqlErrorMsg, wxT("spatialite_gui"), wxOK | wxICON_ERROR,
991                  MainFrame);
992 }
993 
OnRsPrevious(wxCommandEvent & WXUNUSED (event))994 void MyResultSetView::OnRsPrevious(wxCommandEvent & WXUNUSED(event))
995 {
996 //
997 // scrolling to the result set previous block
998 //
999   wxString sql = MainFrame->GetQueryView()->GetSqlCtrl()->GetValue();
1000   int start = RsBeginRow - RsBlock;
1001   if (start < 0)
1002     start = 0;
1003   if (ExecuteSqlPre(sql, start, ReadOnly) == false)
1004     wxMessageBox(SqlErrorMsg, wxT("spatialite_gui"), wxOK | wxICON_ERROR,
1005                  MainFrame);
1006 }
1007 
OnRsNext(wxCommandEvent & WXUNUSED (event))1008 void MyResultSetView::OnRsNext(wxCommandEvent & WXUNUSED(event))
1009 {
1010 //
1011 // scrolling to the result set next block
1012 //
1013   wxString sql = MainFrame->GetQueryView()->GetSqlCtrl()->GetValue();
1014   int start = RsEndRow + 1;
1015   if (ExecuteSqlPre(sql, start, ReadOnly) == false)
1016     wxMessageBox(SqlErrorMsg, wxT("spatialite_gui"), wxOK | wxICON_ERROR,
1017                  MainFrame);
1018 }
1019 
OnRsLast(wxCommandEvent & WXUNUSED (event))1020 void MyResultSetView::OnRsLast(wxCommandEvent & WXUNUSED(event))
1021 {
1022 //
1023 // scrolling to the result set ending
1024 //
1025   wxString sql = MainFrame->GetQueryView()->GetSqlCtrl()->GetValue();
1026   int start = RsMaxRow - RsBlock;
1027   if (start < 0)
1028     start = 0;
1029   if (ExecuteSqlPre(sql, start, ReadOnly) == false)
1030     wxMessageBox(SqlErrorMsg, wxT("spatialite_gui"), wxOK | wxICON_ERROR,
1031                  MainFrame);
1032 }
1033 
OnRefresh(wxCommandEvent & WXUNUSED (event))1034 void MyResultSetView::OnRefresh(wxCommandEvent & WXUNUSED(event))
1035 {
1036 //
1037 // refreshing the result set
1038 //
1039   wxString sql = MainFrame->GetQueryView()->GetSqlCtrl()->GetValue();
1040   int start = RsBeginRow;
1041   if (ExecuteSqlPre(sql, start, ReadOnly) == false)
1042     wxMessageBox(SqlErrorMsg, wxT("spatialite_gui"), wxOK | wxICON_ERROR,
1043                  MainFrame);
1044 }
1045 
OnThreadFinished(wxCommandEvent & WXUNUSED (event))1046 void MyResultSetView::OnThreadFinished(wxCommandEvent & WXUNUSED(event))
1047 {
1048 //
1049 // the SQL thread signals termination
1050 //
1051   if (ExecuteSqlPost() == false)
1052     wxMessageBox(wxT("An error occurred while showing the ResultSet"),
1053                  wxT("spatialite_gui"), wxOK | wxICON_ERROR, MainFrame);
1054 }
1055 
OnStatsUpdate(wxCommandEvent & WXUNUSED (event))1056 void MyResultSetView::OnStatsUpdate(wxCommandEvent & WXUNUSED(event))
1057 {
1058 //
1059 // updating SQL stats (progress handler)
1060 //
1061   char elapsed[64];
1062   char dummy[1024];
1063   wxString cellValue;
1064   if (ThreadParams.IsValid() == false)
1065     return;
1066   FormatElapsedTime(ThreadParams.GetElapsedTime(), elapsed, true);
1067   sprintf(dummy, "%d", ThreadParams.GetStatFullscanStep());
1068   cellValue = wxString::FromUTF8(dummy);
1069   TableView->SetCellValue(0, 1, cellValue);
1070   sprintf(dummy, "%d", ThreadParams.GetStatSort());
1071   cellValue = wxString::FromUTF8(dummy);
1072   TableView->SetCellValue(1, 1, cellValue);
1073   sprintf(dummy, "%d", ThreadParams.GetStatAutoindex());
1074   cellValue = wxString::FromUTF8(dummy);
1075   TableView->SetCellValue(2, 1, cellValue);
1076   sprintf(dummy, "%d", ThreadParams.GetFetchedRows());
1077   cellValue = wxString::FromUTF8(dummy);
1078   TableView->SetCellValue(3, 1, cellValue);
1079   sprintf(dummy, "%s", elapsed);
1080   cellValue = wxString::FromUTF8(dummy);
1081   TableView->SetCellValue(4, 1, cellValue);
1082   TableView->ForceRefresh();
1083 }
1084 
OnRightClick(wxGridEvent & event)1085 void MyResultSetView::OnRightClick(wxGridEvent & event)
1086 {
1087 //
1088 // right click on some cell [mouse action]
1089 //
1090   int blob_type;
1091   MyVariant *blobVar;
1092   wxMenu *menu = new wxMenu();
1093   wxMenuItem *menuItem;
1094   wxPoint pt = event.GetPosition();
1095   if (ReadOnly == false && event.GetRow() == TableView->GetNumberRows() - 1)
1096     {
1097       // this is the INSERT ROW
1098       if (InsertPending == true)
1099         {
1100           menuItem =
1101             new wxMenuItem(menu, Grid_Insert, wxT("&Confirm insertion"));
1102           menu->Append(menuItem);
1103           menuItem = new wxMenuItem(menu, Grid_Abort, wxT("&Abort insertion"));
1104           menu->Append(menuItem);
1105       } else
1106         {
1107           menuItem = new wxMenuItem(menu, Grid_Insert, wxT("&Insert new row"));
1108           menu->Append(menuItem);
1109         }
1110       TableView->PopupMenu(menu, pt);
1111       return;
1112     }
1113   CurrentEvtRow = event.GetRow();
1114   CurrentEvtColumn = event.GetCol();
1115   blobVar = TableBlobs->GetBlob(CurrentEvtRow, CurrentEvtColumn);
1116   if (blobVar)
1117     {
1118       // this one is a BLOB cell
1119       if (ReadOnly == false)
1120         {
1121           MyRowVariant *varRow = TableValues->GetRow(CurrentEvtRow);
1122           if (varRow->IsDeleted() == false)
1123             {
1124               menuItem = new wxMenuItem(menu, Grid_Delete, wxT("&Delete row"));
1125               menu->Append(menuItem);
1126               menuItem =
1127                 new wxMenuItem(menu, Grid_Insert, wxT("&Insert new row"));
1128               menu->Append(menuItem);
1129               menu->AppendSeparator();
1130             }
1131         }
1132       menuItem = new wxMenuItem(menu, Grid_Blob, wxT("BLOB &explore"));
1133       menu->Append(menuItem);
1134       blob_type = gaiaGuessBlobType(blobVar->GetBlob(), blobVar->GetBlobSize());
1135       if (blob_type == GAIA_GEOMETRY_BLOB)
1136         ;
1137       else if (blob_type == GAIA_XML_BLOB)
1138         {
1139           menu->AppendSeparator();
1140           menuItem =
1141             new wxMenuItem(menu, Grid_XmlBlobIn, wxT("XmlBLOB &import"));
1142           menu->Append(menuItem);
1143           menuItem =
1144             new wxMenuItem(menu, Grid_XmlBlobOut,
1145                            wxT("XmlBLOB &export (not indented)"));
1146           menu->Append(menuItem);
1147           menuItem =
1148             new wxMenuItem(menu, Grid_XmlBlobOutIndented,
1149                            wxT("XmlBLOB export (i&ndented)"));
1150           menu->Append(menuItem);
1151           menuItem =
1152             new wxMenuItem(menu, Grid_BlobNull, wxT("Set BLOB as &NULL"));
1153           menu->Append(menuItem);
1154       } else
1155         {
1156           menu->AppendSeparator();
1157           menuItem = new wxMenuItem(menu, Grid_BlobIn, wxT("BLOB &import"));
1158           menu->Append(menuItem);
1159           menuItem = new wxMenuItem(menu, Grid_BlobOut, wxT("BLOB &export"));
1160           menu->Append(menuItem);
1161           menuItem =
1162             new wxMenuItem(menu, Grid_BlobNull, wxT("Set BLOB as &NULL"));
1163           menu->Append(menuItem);
1164         }
1165       CurrentBlob = blobVar;
1166   } else
1167     {
1168       // this one is an ordinary cell
1169       CurrentBlob = NULL;
1170       if (ReadOnly == false)
1171         {
1172           MyRowVariant *varRow = TableValues->GetRow(CurrentEvtRow);
1173           if (varRow->IsDeleted() == false)
1174             {
1175               menuItem = new wxMenuItem(menu, Grid_Delete, wxT("&Delete row"));
1176               menu->Append(menuItem);
1177               menuItem =
1178                 new wxMenuItem(menu, Grid_Insert, wxT("&Insert new row"));
1179               menu->Append(menuItem);
1180               if (IsBlobColumn(CurrentEvtColumn) == true)
1181                 {
1182                   menu->AppendSeparator();
1183                   menuItem =
1184                     new wxMenuItem(menu, Grid_BlobIn, wxT("BLOB &import"));
1185                   menu->Append(menuItem);
1186                 }
1187               menu->AppendSeparator();
1188             }
1189         }
1190       menuItem = new wxMenuItem(menu, Grid_Clear, wxT("&Clear selection"));
1191       menu->Append(menuItem);
1192       menuItem = new wxMenuItem(menu, Grid_All, wxT("Select &all"));
1193       menu->Append(menuItem);
1194       menuItem = new wxMenuItem(menu, Grid_Row, wxT("Select &row"));
1195       menu->Append(menuItem);
1196       menuItem = new wxMenuItem(menu, Grid_Column, wxT("&Select column"));
1197       menu->Append(menuItem);
1198       menu->AppendSeparator();
1199       menuItem = new wxMenuItem(menu, Grid_Copy, wxT("&Copy"));
1200       menu->Append(menuItem);
1201       if (TableView->IsSelection() == false)
1202         menuItem->Enable(false);
1203     }
1204   menu->AppendSeparator();
1205   wxMenu *exportMenu = new wxMenu();
1206   menuItem = new wxMenuItem(exportMenu, Grid_ExpTxtTab, wxT("as &Txt/Tab"));
1207   exportMenu->Append(menuItem);
1208   menuItem = new wxMenuItem(exportMenu, Grid_ExpCsv, wxT("as &CSV"));
1209   exportMenu->Append(menuItem);
1210   menuItem = new wxMenuItem(exportMenu, Grid_ExpHtml, wxT("as &HTML"));
1211   exportMenu->Append(menuItem);
1212   menuItem = new wxMenuItem(exportMenu, Grid_ExpShp, wxT("as &Shapefile"));
1213   exportMenu->Append(menuItem);
1214   menuItem =
1215     new wxMenuItem(exportMenu, Grid_ExpDif, wxT("as &DIF spreadsheet"));
1216   exportMenu->Append(menuItem);
1217   menuItem =
1218     new wxMenuItem(exportMenu, Grid_ExpSylk, wxT("as &SYLK spreadsheet"));
1219   exportMenu->Append(menuItem);
1220   menuItem = new wxMenuItem(exportMenu, Grid_ExpDbf, wxT("as &DBF archive"));
1221   exportMenu->Append(menuItem);
1222   menu->AppendSubMenu(exportMenu, wxT("&Export ResultSet"));
1223   TableView->PopupMenu(menu, pt);
1224 }
1225 
OnCellSelected(wxGridEvent & event)1226 void MyResultSetView::OnCellSelected(wxGridEvent & event)
1227 {
1228 //
1229 // cell selection changed
1230 //
1231   if (InsertPending == true)
1232     {
1233       // an INSERT row is still pending
1234       if (event.GetRow() != TableView->GetNumberRows() - 1)
1235         DoInsert(false);
1236     }
1237   event.Skip();
1238 }
1239 
OnCellChanged(wxGridEvent & event)1240 void MyResultSetView::OnCellChanged(wxGridEvent & event)
1241 {
1242 //
1243 // user changed value in some cell
1244 //
1245   MyVariant *oldValue;
1246   MyVariant *insValue;
1247   wxString value;
1248   wxString numValue;
1249   wxString newValue = wxT("NULL");
1250   wxString sql;
1251   wxString rowid;
1252   char *errMsg = NULL;
1253   bool error = false;
1254   sqlite3_int64 int64_value;
1255   long long_value;
1256   bool okIntValue = false;
1257   double dbl_value;
1258   bool okDblValue = false;
1259   int ret;
1260   char dummy[256];
1261   int row = event.GetRow();
1262   int column = event.GetCol();
1263   char xname[1024];
1264   value = TableView->GetCellValue(row, column);
1265   if (InsertPending == true)
1266     {
1267       // an INSERT row is still pending
1268       insValue = InsertRow->GetColumn(column);
1269       numValue = value;
1270       numValue.Replace(wxT(","), wxT("."));
1271       okIntValue = numValue.ToLong(&long_value);
1272       okDblValue = numValue.ToDouble(&dbl_value);
1273       if (okIntValue == true)
1274         {
1275           int64_value = long_value;
1276           insValue->Set(int64_value);
1277       } else if (okDblValue == true)
1278         insValue->Set(dbl_value);
1279       else
1280         insValue->Set(value);
1281       if (row != TableView->GetNumberRows() - 1)
1282         DoInsert(false);
1283       return;
1284     }
1285   if (value.Len() > 0)
1286     {
1287       numValue = value;
1288       numValue.Replace(wxT(","), wxT("."));
1289       okIntValue = numValue.ToLong(&long_value);
1290       okDblValue = numValue.ToDouble(&dbl_value);
1291       if (okIntValue == true)
1292         {
1293           int64_value = long_value;
1294           sprintf(dummy, FORMAT_64, int64_value);
1295           newValue = wxString::FromUTF8(dummy);
1296       } else if (okDblValue == true)
1297         {
1298           sprintf(dummy, "%1.6f", dbl_value);
1299           newValue = wxString::FromUTF8(dummy);
1300       } else
1301         {
1302           value.Replace(wxT("'"), wxT("''"));
1303           newValue = wxT("'") + value + wxT("'");
1304         }
1305     }
1306   oldValue = TableValues->GetValue(row, 0);
1307   sprintf(dummy, FORMAT_64, oldValue->GetIntValue());
1308   rowid = wxString::FromUTF8(dummy);
1309   sql = wxT("UPDATE ");
1310   strcpy(xname, TableName.ToUTF8());
1311   MainFrame->DoubleQuotedSql(xname);
1312   sql += wxString::FromUTF8(xname);
1313   sql += wxT(" SET ");
1314   strcpy(xname, TableView->GetColLabelValue(column).ToUTF8());
1315   MainFrame->DoubleQuotedSql(xname);
1316   sql += wxString::FromUTF8(xname);
1317   sql += wxT(" = ") + newValue + wxT(" WHERE ROWID = ") + rowid;
1318   ret = sqlite3_exec(MainFrame->GetSqlite(), sql.ToUTF8(), NULL, NULL, &errMsg);
1319   if (ret != SQLITE_OK)
1320     {
1321       wxMessageBox(wxT("SQLite SQL error: ") + wxString::FromUTF8(errMsg),
1322                    wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
1323       sqlite3_free(errMsg);
1324       error = true;
1325     }
1326   oldValue = TableValues->GetValue(row, column);
1327   if (error == true)
1328     {
1329       // update failed; restorig old cell value
1330       value = wxT("NULL");
1331       if (oldValue)
1332         {
1333           if (oldValue->GetType() == MY_INT_VARIANT)
1334             {
1335               sprintf(dummy, FORMAT_64, oldValue->GetIntValue());
1336               value = wxString::FromUTF8(dummy);
1337             }
1338           if (oldValue->GetType() == MY_DBL_VARIANT)
1339             {
1340               sprintf(dummy, "%1.6f", oldValue->GetDblValue());
1341               value = wxString::FromUTF8(dummy);
1342             }
1343           if (oldValue->GetType() == MY_TXT_VARIANT)
1344             value = oldValue->GetTxtValue();
1345         }
1346       TableView->SetCellValue(row, column, value);
1347       TableView->ForceRefresh();
1348   } else
1349     {
1350       // marking cell as modified
1351       TableView->SetCellTextColour(row, column, wxColour(0, 0, 192));
1352       TableView->SetCellBackgroundColour(row, column, wxColour(255, 255, 204));
1353       TableView->ForceRefresh();
1354     }
1355 }
1356 
DoInsert(bool confirmed)1357 void MyResultSetView::DoInsert(bool confirmed)
1358 {
1359 //
1360 // performing actual row INSERT
1361 //
1362   int i;
1363   int ret;
1364   MyVariant *var;
1365   wxString value;
1366   wxString strValue;
1367   wxString sql;
1368   char dummy[256];
1369   char *errMsg = NULL;
1370   char xname[1024];
1371   if (confirmed == false)
1372     {
1373       ret =
1374         wxMessageBox(wxT("A new row is ready for insertion\n\nConfirm ?"),
1375                      wxT("spatialite_gui"), wxYES_NO | wxICON_QUESTION, this);
1376       if (ret != wxYES)
1377         goto close_insert;
1378     }
1379   sql = wxT("INSERT INTO ");
1380   strcpy(xname, TableName.ToUTF8());
1381   MainFrame->DoubleQuotedSql(xname);
1382   sql += wxString::FromUTF8(xname);
1383   sql += wxT(" (");
1384   for (i = 1; i < TableView->GetNumberCols(); i++)
1385     {
1386       if (i > 1)
1387         sql += wxT(", ");
1388       strcpy(xname, TableView->GetColLabelValue(i).ToUTF8());
1389       MainFrame->DoubleQuotedSql(xname);
1390       sql += wxString::FromUTF8(xname);
1391     }
1392   sql += wxT(") VALUES (");
1393   for (i = 1; i < InsertRow->GetNumCols(); i++)
1394     {
1395       if (i > 1)
1396         sql += wxT(", ");
1397       var = InsertRow->GetColumn(i);
1398       value = wxT("NULL");
1399       if (var->GetType() == MY_INT_VARIANT)
1400         {
1401           sprintf(dummy, FORMAT_64, var->GetIntValue());
1402           value = wxString::FromUTF8(dummy);
1403         }
1404       if (var->GetType() == MY_DBL_VARIANT)
1405         {
1406           sprintf(dummy, "%1.6f", var->GetDblValue());
1407           value = wxString::FromUTF8(dummy);
1408         }
1409       if (var->GetType() == MY_TXT_VARIANT)
1410         {
1411           strValue = var->GetTxtValue();
1412           strValue.Replace(wxT("'"), wxT("''"));
1413           value = wxT("'") + strValue + wxT("'");
1414         }
1415       sql += value;
1416     }
1417   sql += wxT(")");
1418   ret = sqlite3_exec(MainFrame->GetSqlite(), sql.ToUTF8(), NULL, NULL, &errMsg);
1419   if (ret != SQLITE_OK)
1420     {
1421       wxMessageBox(wxT("SQLite SQL error: ") + wxString::FromUTF8(errMsg),
1422                    wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
1423       sqlite3_free(errMsg);
1424     }
1425 close_insert:
1426 //
1427 // closing insert row
1428 //
1429   InsertPending = false;
1430   delete InsertRow;
1431   InsertRow = NULL;
1432   for (i = 0; i < TableView->GetNumberCols(); i++)
1433     {
1434       TableView->SetCellValue(TableView->GetNumberRows() - 1, i, wxT(""));
1435       TableView->SetCellBackgroundColour(TableView->GetNumberRows() - 1, i,
1436                                          wxColour(0, 0, 0));
1437       TableView->SetReadOnly(TableView->GetNumberRows() - 1, i);
1438     }
1439 }
1440 
OnCmdDelete(wxCommandEvent & WXUNUSED (event))1441 void MyResultSetView::OnCmdDelete(wxCommandEvent & WXUNUSED(event))
1442 {
1443 //
1444 // user required row deletion
1445 //
1446   char *errMsg = NULL;
1447   bool error = false;
1448   int ret;
1449   int i;
1450   wxString sql;
1451   wxString rowid;
1452   MyVariant *value;
1453   char dummy[256];
1454   char xname[1024];
1455   MyRowVariant *varRow = TableValues->GetRow(CurrentEvtRow);
1456   if (varRow->IsDeleted() == true)
1457     return;
1458   value = TableValues->GetValue(CurrentEvtRow, 0);
1459   sprintf(dummy, FORMAT_64, value->GetIntValue());
1460   rowid = wxString::FromUTF8(dummy);
1461   ret =
1462     wxMessageBox(wxT("Requested deletion for row identified by RowId = ")
1463                  + rowid + wxT("\n\nConfirm ?"), wxT("spatialite_gui"),
1464                  wxYES_NO | wxICON_QUESTION, this);
1465   if (ret != wxYES)
1466     return;
1467   strcpy(xname, TableName.ToUTF8());
1468   MainFrame->DoubleQuotedSql(xname);
1469   sql =
1470     wxT("DELETE FROM ") + wxString::FromUTF8(xname) + wxT(" WHERE ROWID = ") +
1471     rowid;
1472   ret = sqlite3_exec(MainFrame->GetSqlite(), sql.ToUTF8(), NULL, NULL, &errMsg);
1473   if (ret != SQLITE_OK)
1474     {
1475       wxMessageBox(wxT("SQLite SQL error: ") + wxString::FromUTF8(errMsg),
1476                    wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
1477       sqlite3_free(errMsg);
1478       error = true;
1479     }
1480   if (error == false)
1481     {
1482       // marking row as deleted
1483       varRow->SetDeleted();
1484       for (i = 0; i < TableView->GetNumberCols(); i++)
1485         {
1486           TableView->SetCellTextColour(CurrentEvtRow, i, wxColour(0, 0, 0));
1487           TableView->SetCellBackgroundColour(CurrentEvtRow, i,
1488                                              wxColour(128, 128, 128));
1489           TableView->SetReadOnly(CurrentEvtRow, i);
1490         }
1491       TableView->ForceRefresh();
1492     }
1493 }
1494 
OnCmdInsert(wxCommandEvent & WXUNUSED (event))1495 void MyResultSetView::OnCmdInsert(wxCommandEvent & WXUNUSED(event))
1496 {
1497 //
1498 // user required row insertion
1499 //
1500   int i;
1501   if (ReadOnly == true)
1502     return;
1503   if (InsertPending == true)
1504     {
1505       // an INSERT is still pending, and the user required actual insertion
1506       DoInsert(true);
1507       return;
1508     }
1509   InsertRow = new MyRowVariant(TableView->GetNumberCols());
1510   TableView->MakeCellVisible(TableView->GetNumberRows() - 1, 1);
1511   InsertPending = true;
1512   for (i = 1; i < TableView->GetNumberCols(); i++)
1513     {
1514       TableView->SetCellValue(TableView->GetNumberRows() - 1, i, wxT(""));
1515       TableView->SetCellBackgroundColour(TableView->GetNumberRows() - 1, i,
1516                                          wxColour(255, 255, 255));
1517       TableView->SetReadOnly(TableView->GetNumberRows() - 1, i, false);
1518     }
1519 }
1520 
OnCmdAbort(wxCommandEvent & WXUNUSED (event))1521 void MyResultSetView::OnCmdAbort(wxCommandEvent & WXUNUSED(event))
1522 {
1523 //
1524 // user cancelled current row insertion
1525 //
1526   int i;
1527   if (InsertPending)
1528     {
1529       InsertPending = false;
1530       delete InsertRow;
1531       InsertRow = NULL;
1532       for (i = 0; i < TableView->GetNumberCols(); i++)
1533         {
1534           TableView->SetCellValue(TableView->GetNumberRows() - 1, i, wxT(""));
1535           TableView->SetCellBackgroundColour(TableView->GetNumberRows() - 1, i,
1536                                              wxColour(0, 0, 0));
1537           TableView->SetReadOnly(TableView->GetNumberRows() - 1, i);
1538         }
1539     }
1540 }
1541 
OnCmdClearSelection(wxCommandEvent & WXUNUSED (event))1542 void MyResultSetView::OnCmdClearSelection(wxCommandEvent & WXUNUSED(event))
1543 {
1544 //
1545 // clearing current selection
1546 //
1547   TableView->ClearSelection();
1548 }
1549 
OnCmdSelectAll(wxCommandEvent & WXUNUSED (event))1550 void MyResultSetView::OnCmdSelectAll(wxCommandEvent & WXUNUSED(event))
1551 {
1552 //
1553 // selecting all
1554 //
1555   TableView->SelectAll();
1556 }
1557 
OnCmdSelectRow(wxCommandEvent & WXUNUSED (event))1558 void MyResultSetView::OnCmdSelectRow(wxCommandEvent & WXUNUSED(event))
1559 {
1560 //
1561 // selecting the current row
1562 //
1563   TableView->SelectRow(CurrentEvtRow);
1564 }
1565 
OnCmdSelectColumn(wxCommandEvent & WXUNUSED (event))1566 void MyResultSetView::OnCmdSelectColumn(wxCommandEvent & WXUNUSED(event))
1567 {
1568 //
1569 // selecting column
1570 //
1571   TableView->SelectCol(CurrentEvtColumn);
1572 }
1573 
OnCmdCopy(wxCommandEvent & WXUNUSED (event))1574 void MyResultSetView::OnCmdCopy(wxCommandEvent & WXUNUSED(event))
1575 {
1576 //
1577 // copying the selection into the clipboard
1578 //
1579   wxString copyData;
1580   int row;
1581   int col;
1582   bool newRow;
1583   bool firstRow = true;
1584   for (row = 0; row < TableView->GetNumberRows(); row++)
1585     {
1586       newRow = true;
1587       for (col = 0; col < TableView->GetNumberCols(); col++)
1588         {
1589           if (TableView->IsInSelection(row, col) == true)
1590             {
1591               // ok, this cell is included into the selection to copy
1592               if (firstRow == true)
1593                 {
1594                   newRow = false;
1595                   firstRow = false;
1596               } else if (newRow == true)
1597                 {
1598                   newRow = false;
1599                   copyData += wxT("\n");
1600               } else
1601                 copyData += wxT("\t");
1602               copyData += TableView->GetCellValue(row, col);
1603             }
1604         }
1605     }
1606   if (wxTheClipboard->Open())
1607     {
1608       wxTheClipboard->SetData(new wxTextDataObject(copyData));
1609       wxTheClipboard->Close();
1610     }
1611 }
1612 
OnCmdBlob(wxCommandEvent & WXUNUSED (event))1613 void MyResultSetView::OnCmdBlob(wxCommandEvent & WXUNUSED(event))
1614 {
1615 //
1616 // exploring some BLOB value
1617 //
1618   if (!CurrentBlob)
1619     return;
1620   BlobExplorerDialog dlg;
1621   dlg.Create(MainFrame, CurrentBlob->GetBlobSize(), CurrentBlob->GetBlob());
1622   dlg.ShowModal();
1623 }
1624 
OnCmdBlobIn(wxCommandEvent & WXUNUSED (event))1625 void MyResultSetView::OnCmdBlobIn(wxCommandEvent & WXUNUSED(event))
1626 {
1627 // importing an external file into a BLOB-value
1628   FILE *in = NULL;
1629   char path[2048];
1630   int rd;
1631   int maxSize = 1024 * 1024;    // limit BLOB size to 1MB
1632   wxString fileList;
1633   wxString rowid;
1634   wxString sql;
1635   wxString blobValue;
1636   wxString hex;
1637   MyVariant *value;
1638   char dummy[1024];
1639   bool error = false;
1640   unsigned char *buffer = NULL;
1641   int ret;
1642   char *errMsg = NULL;
1643   wxString lastDir;
1644   char xname[1024];
1645   fileList =
1646     wxT
1647     ("BLOB Document (*.jpg;*.jpeg;*.png;*.gif;*.tif;*.pdf;*.zip)|*.jpg;*.jpeg;*.png;*.gif;*.tif;*.pdf;*.zip|");
1648   fileList +=
1649     wxT
1650     ("Image (*.jpg;*.jpeg;*.png;*.gif;*.tif)|*.jpg;*.jpeg;*.png;*.gif;*.tif|");
1651   fileList +=
1652     wxT
1653     ("JPEG Image (*.jpg;*.jpeg)|*.jpg;*.jpeg|PNG Image (*.png)|*.png|GIF Image (*.gif)|*.gif|TIFF Image (*.tif)|*.tif|");
1654   fileList +=
1655     wxT("PDF Document (*.pdf)|*.pdf|ZIP Archive|(*.zip)|All files (*.*)|*.*");
1656   wxFileDialog fileDialog(this, wxT("loading a BLOB value"),
1657                           wxT(""), wxT(""), fileList,
1658                           wxFD_OPEN | wxFD_FILE_MUST_EXIST,
1659                           wxDefaultPosition, wxDefaultSize, wxT("filedlg"));
1660   lastDir = MainFrame->GetLastDirectory();
1661   if (lastDir.Len() >= 1)
1662     fileDialog.SetDirectory(lastDir);
1663   ret = fileDialog.ShowModal();
1664   if (ret == wxID_OK)
1665     {
1666       strcpy(path, fileDialog.GetPath().ToUTF8());
1667       in = fopen(path, "rb");
1668       if (!in)
1669         {
1670           wxMessageBox(wxT("Cannot open '") + fileDialog.GetPath() +
1671                        wxT("' for reading"), wxT("spatialite_gui"),
1672                        wxOK | wxICON_ERROR, this);
1673           return;
1674         }
1675       wxFileName file(fileDialog.GetPath());
1676       lastDir = file.GetPath();
1677       MainFrame->SetLastDirectory(lastDir);
1678       ::wxBeginBusyCursor();
1679       buffer = new unsigned char[maxSize];
1680       rd = fread(buffer, 1, maxSize, in);
1681       if (rd == maxSize && !(feof(in)))
1682         {
1683           // exceding 1MB; it's too big for a BLOB
1684           wxMessageBox(wxT
1685                        ("Selected file excedes 1MB; cowardly refusing to load it as a BLOB value ..."),
1686                        wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
1687           goto end;
1688         }
1689       if (ferror(in))
1690         {
1691           // I/O error
1692           wxMessageBox(wxT("an I/O error occurred"), wxT("spatialite_gui"),
1693                        wxOK | wxICON_ERROR, this);
1694           goto end;
1695         }
1696       //
1697       // preparing  the SQL UPDATE statement
1698       //
1699       value = TableValues->GetValue(CurrentEvtRow, 0);
1700       sprintf(dummy, FORMAT_64, value->GetIntValue());
1701       rowid = wxString::FromUTF8(dummy);
1702       HexBlobValue(buffer, rd, hex);
1703       sql = wxT("UPDATE ");
1704       strcpy(xname, TableName.ToUTF8());
1705       MainFrame->DoubleQuotedSql(xname);
1706       sql += wxString::FromUTF8(xname);
1707       sql += wxT(" SET ");
1708       strcpy(xname, TableView->GetColLabelValue(CurrentEvtColumn).ToUTF8());
1709       MainFrame->DoubleQuotedSql(xname);
1710       sql += wxString::FromUTF8(xname);
1711       sql += wxT(" = ") + hex + wxT(" WHERE ROWID = ") + rowid;
1712       ret =
1713         sqlite3_exec(MainFrame->GetSqlite(), sql.ToUTF8(), NULL, NULL, &errMsg);
1714       if (ret != SQLITE_OK)
1715         {
1716           wxMessageBox(wxT("SQLite SQL error: ") + wxString::FromUTF8(errMsg),
1717                        wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
1718           sqlite3_free(errMsg);
1719           error = true;
1720         }
1721       value = TableValues->GetValue(CurrentEvtRow, CurrentEvtColumn);
1722       if (error == false)
1723         {
1724           // updating the Grid cell
1725           sprintf(dummy, "BLOB sz=%d ", rd);
1726           blobValue = wxString::FromUTF8(dummy);
1727           switch (gaiaGuessBlobType(buffer, rd))
1728             {
1729               case GAIA_JPEG_BLOB:
1730                 blobValue += wxT("JPEG image");
1731                 break;
1732               case GAIA_EXIF_BLOB:
1733                 blobValue += wxT("JPEG-EXIF image");
1734                 break;
1735               case GAIA_EXIF_GPS_BLOB:
1736                 blobValue += wxT("JPEG-EXIF-GPS image");
1737                 break;
1738               case GAIA_PNG_BLOB:
1739                 blobValue += wxT("PNG image");
1740                 break;
1741               case GAIA_GIF_BLOB:
1742                 blobValue += wxT("GIF image");
1743                 break;
1744               case GAIA_TIFF_BLOB:
1745                 blobValue += wxT("TIFF image");
1746                 break;
1747               case GAIA_PDF_BLOB:
1748                 blobValue += wxT("PDF document");
1749                 break;
1750               case GAIA_ZIP_BLOB:
1751                 blobValue += wxT("ZIP archive");
1752                 break;
1753               default:
1754                 blobValue += wxT("UNKNOWN type");
1755                 break;
1756             };
1757           TableView->SetCellValue(CurrentEvtRow, CurrentEvtColumn, blobValue);
1758           TableView->SetCellTextColour(CurrentEvtRow, CurrentEvtColumn,
1759                                        wxColour(0, 0, 192));
1760           TableView->SetCellBackgroundColour(CurrentEvtRow, CurrentEvtColumn,
1761                                              wxColour(255, 255, 204));
1762           TableView->ForceRefresh();
1763         }
1764     }
1765 end:
1766 // clean-up
1767   ::wxEndBusyCursor();
1768   if (in)
1769     fclose(in);
1770   if (buffer)
1771     delete[]buffer;
1772 }
1773 
HexBlobValue(unsigned char * blob,int size,wxString & hex)1774 void MyResultSetView::HexBlobValue(unsigned char *blob, int size,
1775                                    wxString & hex)
1776 {
1777 //
1778 // builds the HEX BLOB as X'01234567890abcdef'
1779 //
1780   int i;
1781   char digit[16];
1782   hex = wxT("X'");
1783   for (i = 0; i < size; i++)
1784     {
1785       sprintf(digit, "%02x", *(blob + i));
1786       hex += wxString::FromUTF8(digit);
1787     }
1788   hex += wxT("'");
1789 }
1790 
OnCmdBlobOut(wxCommandEvent & WXUNUSED (event))1791 void MyResultSetView::OnCmdBlobOut(wxCommandEvent & WXUNUSED(event))
1792 {
1793 // exporting to external file a BLOB-value
1794   int blobType;
1795   wxString fileName;
1796   wxString fileType;
1797   int ret;
1798   wxString path;
1799   FILE *out = NULL;
1800   char xpath[2048];
1801   int wr;
1802   wxString lastDir;
1803   if (!CurrentBlob)
1804     return;
1805   blobType =
1806     gaiaGuessBlobType(CurrentBlob->GetBlob(), CurrentBlob->GetBlobSize());
1807   switch (blobType)
1808     {
1809       case GAIA_JPEG_BLOB:
1810       case GAIA_EXIF_BLOB:
1811       case GAIA_EXIF_GPS_BLOB:
1812         fileName = wxT("image.jpg");
1813         fileType = wxT("File JPEG (*.jpg;*.jpeg)|*.jpg");
1814         break;
1815       case GAIA_PNG_BLOB:
1816         fileName = wxT("image.png");
1817         fileType = wxT("File PNG (*.png)|*.png");
1818         break;
1819       case GAIA_GIF_BLOB:
1820         fileName = wxT("image.gif");
1821         fileType = wxT("File GIF (*.gif)|*.gif");
1822         break;
1823       case GAIA_TIFF_BLOB:
1824         fileName = wxT("image.tiff");
1825         fileType = wxT("File TIFF (*.tif)|*.tif");
1826         break;
1827       case GAIA_PDF_BLOB:
1828         fileName = wxT("document.pdf");
1829         fileType = wxT("PDF document (*.pdf)|*.pdf");
1830         break;
1831       case GAIA_ZIP_BLOB:
1832         fileName = wxT("archive.zip");
1833         fileType = wxT("ZIP Archive (*.zip)|*.zip");
1834         break;
1835       default:
1836         fileName = wxT("file");
1837     };
1838   fileType += wxT("|All files (*.*)|*.*");
1839   wxFileDialog fileDialog(this, wxT("exporting a BLOB value to file"),
1840                           wxT(""), fileName, fileType,
1841                           wxFD_SAVE | wxFD_OVERWRITE_PROMPT, wxDefaultPosition,
1842                           wxDefaultSize, wxT("filedlg"));
1843   lastDir = MainFrame->GetLastDirectory();
1844   if (lastDir.Len() >= 1)
1845     fileDialog.SetDirectory(lastDir);
1846   ret = fileDialog.ShowModal();
1847   if (ret == wxID_OK)
1848     {
1849       wxFileName file(fileDialog.GetPath());
1850       path = file.GetPath();
1851       path += file.GetPathSeparator();
1852       path += file.GetName();
1853       switch (blobType)
1854         {
1855           case GAIA_JPEG_BLOB:
1856           case GAIA_EXIF_BLOB:
1857           case GAIA_EXIF_GPS_BLOB:
1858             path += wxT(".jpg");
1859             break;
1860           case GAIA_PNG_BLOB:
1861             path += wxT(".png");
1862             break;
1863           case GAIA_GIF_BLOB:
1864             path += wxT(".gif");
1865             break;
1866           case GAIA_TIFF_BLOB:
1867             path += wxT(".tif");
1868             break;
1869           case GAIA_PDF_BLOB:
1870             path += wxT(".pdf");
1871             break;
1872           case GAIA_ZIP_BLOB:
1873             path += wxT(".zip");
1874             break;
1875           default:
1876             path += file.GetExt();
1877         };
1878       strcpy(xpath, path.ToUTF8());
1879       out = fopen(xpath, "wb");
1880       if (!out)
1881         {
1882           wxMessageBox(wxT("Cannot open '") + path + wxT("' for writing"),
1883                        wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
1884           return;
1885         }
1886       lastDir = file.GetPath();
1887       MainFrame->SetLastDirectory(lastDir);
1888       ::wxBeginBusyCursor();
1889       wr = fwrite(CurrentBlob->GetBlob(), 1, CurrentBlob->GetBlobSize(), out);
1890       if (wr != CurrentBlob->GetBlobSize())
1891         {
1892           wxMessageBox(wxT("an I/O error occurred"), wxT("spatialite_gui"),
1893                        wxOK | wxICON_ERROR, this);
1894         }
1895       fclose(out);
1896       ::wxEndBusyCursor();
1897     }
1898 }
1899 
OnCmdXmlBlobIn(wxCommandEvent & WXUNUSED (event))1900 void MyResultSetView::OnCmdXmlBlobIn(wxCommandEvent & WXUNUSED(event))
1901 {
1902 // importing an external XMLDocument into an XmlBLOB-value
1903 #ifdef ENABLE_LIBXML2           /* only if LIBXML2 is enabled */
1904   FILE *in = NULL;
1905   char path[2048];
1906   int rd;
1907   int maxSize = 1024 * 1024;    // limit XmlBLOB size to 1MB
1908   wxString fileList;
1909   wxString rowid;
1910   wxString sql;
1911   wxString blobValue;
1912   wxString hex;
1913   MyVariant *value;
1914   char dummy[1024];
1915   bool error = false;
1916   unsigned char *buffer = NULL;
1917   int ret;
1918   char *errMsg = NULL;
1919   wxString lastDir;
1920   char xname[1024];
1921   unsigned char *xml = NULL;
1922   int xml_size;
1923   int compressed;
1924   char *schemaURI;
1925   char xschema[8192];
1926   fileList = wxT("XML Document (*.xml)|*.xml|All files (*.*)|*.*");
1927   wxFileDialog fileDialog(this, wxT("loading an XmlBLOB value"),
1928                           wxT(""), wxT(""), fileList,
1929                           wxFD_OPEN | wxFD_FILE_MUST_EXIST,
1930                           wxDefaultPosition, wxDefaultSize, wxT("filedlg"));
1931   lastDir = MainFrame->GetLastDirectory();
1932   if (lastDir.Len() >= 1)
1933     fileDialog.SetDirectory(lastDir);
1934   ret = fileDialog.ShowModal();
1935   if (ret == wxID_OK)
1936     {
1937       strcpy(path, fileDialog.GetPath().ToUTF8());
1938       in = fopen(path, "rb");
1939       if (!in)
1940         {
1941           wxMessageBox(wxT("Cannot open '") + fileDialog.GetPath() +
1942                        wxT("' for reading"), wxT("spatialite_gui"),
1943                        wxOK | wxICON_ERROR, this);
1944           return;
1945         }
1946       wxFileName file(fileDialog.GetPath());
1947       lastDir = file.GetPath();
1948       MainFrame->SetLastDirectory(lastDir);
1949       ::wxBeginBusyCursor();
1950       buffer = new unsigned char[maxSize];
1951       rd = fread(buffer, 1, maxSize, in);
1952       if (rd == maxSize && !(feof(in)))
1953         {
1954           // exceding 1MB; it's too big for a BLOB
1955           wxMessageBox(wxT
1956                        ("Selected file excedes 1MB; cowardly refusing to load it as an XmlBLOB value ..."),
1957                        wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
1958           goto end;
1959         }
1960       if (ferror(in))
1961         {
1962           // I/O error
1963           wxMessageBox(wxT("an I/O error occurred"), wxT("spatialite_gui"),
1964                        wxOK | wxICON_ERROR, this);
1965           goto end;
1966         }
1967 
1968       LoadXmlDialog dlg;
1969       wxString inPath = fileDialog.GetPath();
1970       dlg.Create(MainFrame, inPath);
1971       ret = dlg.ShowModal();
1972       if (ret == wxID_OK)
1973         {
1974           if (dlg.IsCompressed() == true)
1975             compressed = 1;
1976           else
1977             compressed = 0;
1978           wxString schema = dlg.GetSchemaURI();
1979           if (schema.Len() == 0)
1980             schemaURI = NULL;
1981           else
1982             {
1983               strcpy(xschema, schema.ToUTF8());
1984               schemaURI = xschema;
1985             }
1986       } else
1987         goto end;
1988 
1989 // attempting to parse (and possibly validate) the XML
1990       gaiaXmlToBlob(MainFrame->GetInternalCache(), buffer, rd, compressed,
1991                     schemaURI, &xml, &xml_size, NULL, NULL);
1992       if (xml == NULL)
1993         {
1994           wxMessageBox(wxT("Invalid XML ... unable to parse or validate"),
1995                        wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
1996           goto end;
1997         }
1998 //
1999 // preparing  the SQL UPDATE statement
2000 //
2001       value = TableValues->GetValue(CurrentEvtRow, 0);
2002       sprintf(dummy, FORMAT_64, value->GetIntValue());
2003       rowid = wxString::FromUTF8(dummy);
2004       HexBlobValue(xml, xml_size, hex);
2005       sql = wxT("UPDATE ");
2006       strcpy(xname, TableName.ToUTF8());
2007       MainFrame->DoubleQuotedSql(xname);
2008       sql += wxString::FromUTF8(xname);
2009       sql += wxT(" SET ");
2010       strcpy(xname, TableView->GetColLabelValue(CurrentEvtColumn).ToUTF8());
2011       MainFrame->DoubleQuotedSql(xname);
2012       sql += wxString::FromUTF8(xname);
2013       sql += wxT(" = ") + hex + wxT(" WHERE ROWID = ") + rowid;
2014       ret =
2015         sqlite3_exec(MainFrame->GetSqlite(), sql.ToUTF8(), NULL, NULL, &errMsg);
2016       if (ret != SQLITE_OK)
2017         {
2018           wxMessageBox(wxT("SQLite SQL error: ") + wxString::FromUTF8(errMsg),
2019                        wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
2020           sqlite3_free(errMsg);
2021           error = true;
2022         }
2023       value = TableValues->GetValue(CurrentEvtRow, CurrentEvtColumn);
2024       if (error == false)
2025         {
2026           // updating the Grid cell
2027           int doc_size = gaiaXmlBlobGetDocumentSize(xml, xml_size);
2028           sprintf(dummy, "XmlBLOB sz=%d (XMLsz=%d) ", xml_size, doc_size);
2029           blobValue = wxString::FromUTF8(dummy);
2030           if (gaiaIsSchemaValidatedXmlBlob(xml, xml_size))
2031             blobValue += wxT(" SchemaValidated");
2032           TableView->SetCellValue(CurrentEvtRow, CurrentEvtColumn, blobValue);
2033           TableView->SetCellTextColour(CurrentEvtRow, CurrentEvtColumn,
2034                                        wxColour(0, 0, 192));
2035           TableView->SetCellBackgroundColour(CurrentEvtRow, CurrentEvtColumn,
2036                                              wxColour(255, 255, 204));
2037           TableView->ForceRefresh();
2038         }
2039     }
2040 end:
2041 // clean-up
2042   ::wxEndBusyCursor();
2043   if (in)
2044     fclose(in);
2045   if (buffer)
2046     delete[]buffer;
2047   if (xml)
2048     free(xml);
2049 
2050 #else
2051 
2052   wxMessageBox(wxT
2053                ("Sorry, spatialite_gui was built disabling LIBXML2\n\nUnsupported operation"),
2054                wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
2055 
2056 #endif /* end LIBXML2 conditionals */
2057 }
2058 
XmlBlobOut(bool indented)2059 void MyResultSetView::XmlBlobOut(bool indented)
2060 {
2061 // exporting to external file an XmlBLOB-value
2062 #ifdef ENABLE_LIBXML2           /* only if LIBXML2 is enabled */
2063   wxString fileName;
2064   wxString fileType;
2065   int ret;
2066   wxString path;
2067   FILE *out = NULL;
2068   char xpath[2048];
2069   int wr;
2070   wxString lastDir;
2071   unsigned char *xml;
2072   int xml_size;
2073   wxString title = wxT("exporting an XmlBLOB value to file ");
2074   if (!CurrentBlob)
2075     return;
2076   if (indented)
2077     {
2078       title += wxT("(not indented)");
2079       gaiaXmlFromBlob(CurrentBlob->GetBlob(), CurrentBlob->GetBlobSize(), 0,
2080                       &xml, &xml_size);
2081   } else
2082     {
2083       title += wxT("(indented)");
2084       gaiaXmlFromBlob(CurrentBlob->GetBlob(), CurrentBlob->GetBlobSize(), 1,
2085                       &xml, &xml_size);
2086     }
2087   if (xml == NULL)
2088     return;
2089   fileName = wxT("document.xml");
2090   fileType = wxT("XML Document (*.xml)|*.xml");
2091   fileType += wxT("|All files (*.*)|*.*");
2092   wxFileDialog fileDialog(this, title,
2093                           wxT(""), fileName, fileType,
2094                           wxFD_SAVE | wxFD_OVERWRITE_PROMPT, wxDefaultPosition,
2095                           wxDefaultSize, wxT("filedlg"));
2096   lastDir = MainFrame->GetLastDirectory();
2097   if (lastDir.Len() >= 1)
2098     fileDialog.SetDirectory(lastDir);
2099   ret = fileDialog.ShowModal();
2100   if (ret == wxID_OK)
2101     {
2102       wxFileName file(fileDialog.GetPath());
2103       path = file.GetPath();
2104       path += file.GetPathSeparator();
2105       path += file.GetName();
2106       path += wxT(".xml");
2107       strcpy(xpath, path.ToUTF8());
2108       out = fopen(xpath, "wb");
2109       if (!out)
2110         {
2111           wxMessageBox(wxT("Cannot open '") + path + wxT("' for writing"),
2112                        wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
2113           free(xml);
2114           return;
2115         }
2116       lastDir = file.GetPath();
2117       MainFrame->SetLastDirectory(lastDir);
2118       ::wxBeginBusyCursor();
2119       wr = fwrite(xml, 1, xml_size, out);
2120       if (wr != xml_size)
2121         {
2122           wxMessageBox(wxT("an I/O error occurred"), wxT("spatialite_gui"),
2123                        wxOK | wxICON_ERROR, this);
2124         }
2125       fclose(out);
2126       ::wxEndBusyCursor();
2127     }
2128   free(xml);
2129 
2130 #else
2131 
2132   wxMessageBox(wxT
2133                ("Sorry, spatialite_gui was built disabling LIBXML2\n\nUnsupported operation"),
2134                wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
2135 
2136 #endif /* end LIBXML2 conditionals */
2137 }
2138 
OnCmdXmlBlobOut(wxCommandEvent & WXUNUSED (event))2139 void MyResultSetView::OnCmdXmlBlobOut(wxCommandEvent & WXUNUSED(event))
2140 {
2141 // exporting to external file an XmlBLOB-value (not indented)
2142   XmlBlobOut(false);
2143 }
2144 
OnCmdXmlBlobOutIndented(wxCommandEvent & WXUNUSED (event))2145 void MyResultSetView::OnCmdXmlBlobOutIndented(wxCommandEvent & WXUNUSED(event))
2146 {
2147 // exporting to external file an XmlBLOB-value (indented)
2148   XmlBlobOut(true);
2149 }
2150 
OnCmdBlobNull(wxCommandEvent & WXUNUSED (event))2151 void MyResultSetView::OnCmdBlobNull(wxCommandEvent & WXUNUSED(event))
2152 {
2153 // setting to NULL a BLOB-value
2154   wxString rowid;
2155   wxString sql;
2156   int ret;
2157   char *errMsg = NULL;
2158   bool error = false;
2159   MyVariant *value;
2160   char dummy[256];
2161   char xname[1024];
2162   value = TableValues->GetValue(CurrentEvtRow, 0);
2163   sprintf(dummy, FORMAT_64, value->GetIntValue());
2164   rowid = wxString::FromUTF8(dummy);
2165   sql = wxT("UPDATE ");
2166   strcpy(xname, TableName.ToUTF8());
2167   MainFrame->DoubleQuotedSql(xname);
2168   sql += wxString::FromUTF8(xname);
2169   sql += wxT(" SET ");
2170   strcpy(xname, TableView->GetColLabelValue(CurrentEvtColumn).ToUTF8());
2171   MainFrame->DoubleQuotedSql(xname);
2172   sql += wxString::FromUTF8(xname);
2173   sql += wxT(" = NULL WHERE ROWID = ") + rowid;
2174   ret = sqlite3_exec(MainFrame->GetSqlite(), sql.ToUTF8(), NULL, NULL, &errMsg);
2175   if (ret != SQLITE_OK)
2176     {
2177       wxMessageBox(wxT("SQLite SQL error: ") + wxString::FromUTF8(errMsg),
2178                    wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
2179       sqlite3_free(errMsg);
2180       error = true;
2181     }
2182   if (error == false)
2183     {
2184       // updating the Grid cell
2185       TableView->SetCellValue(CurrentEvtRow, CurrentEvtColumn, wxT("NULL"));
2186       TableView->SetCellTextColour(CurrentEvtRow, CurrentEvtColumn,
2187                                    wxColour(0, 0, 192));
2188       TableView->SetCellBackgroundColour(CurrentEvtRow, CurrentEvtColumn,
2189                                          wxColour(255, 255, 204));
2190       TableView->ForceRefresh();
2191     }
2192 }
2193 
OnCmdExpTxtTab(wxCommandEvent & WXUNUSED (event))2194 void MyResultSetView::OnCmdExpTxtTab(wxCommandEvent & WXUNUSED(event))
2195 {
2196 //
2197 // exporting the ResultSet as TXT-TAB
2198 //
2199   int ret;
2200   wxString path;
2201   wxString lastDir;
2202   wxString target;
2203   wxString sql = MainFrame->GetQueryView()->GetSqlCtrl()->GetValue();
2204   wxFileDialog fileDialog(this, wxT("Exporting the ResultSet as Txt/Tab file"),
2205                           wxT(""), wxT("result_set.txt"),
2206                           wxT("Txt/Tab file (*.txt)|*.txt|All files (*.*)|*.*"),
2207                           wxFD_SAVE | wxFD_OVERWRITE_PROMPT,
2208                           wxDefaultPosition, wxDefaultSize, wxT("filedlg"));
2209   lastDir = MainFrame->GetLastDirectory();
2210   if (lastDir.Len() >= 1)
2211     fileDialog.SetDirectory(lastDir);
2212   ret = fileDialog.ShowModal();
2213   if (ret == wxID_OK)
2214     {
2215       wxFileName file(fileDialog.GetPath());
2216       path = file.GetPath();
2217       path += file.GetPathSeparator();
2218       path += file.GetName();
2219       path += wxT(".txt");
2220       lastDir = file.GetPath();
2221       if (MainFrame->IsSetAskCharset() == false)
2222         {
2223           // using the default output charset
2224           MainFrame->SetLastDirectory(lastDir);
2225           ::wxBeginBusyCursor();
2226           MainFrame->ExportResultSetAsTxtTab(path, sql,
2227                                              MainFrame->GetDefaultCharset());
2228           ::wxEndBusyCursor();
2229       } else
2230         {
2231           // asking the charset to be used
2232           DumpTxtDialog dlg;
2233           target = wxT("TXT / TAB");
2234           dlg.Create(MainFrame, path, target, MainFrame->GetDefaultCharset());
2235           ret = dlg.ShowModal();
2236           if (ret == wxID_OK)
2237             {
2238               MainFrame->SetLastDirectory(lastDir);
2239               ::wxBeginBusyCursor();
2240               MainFrame->ExportResultSetAsTxtTab(path, sql, dlg.GetCharset());
2241               ::wxEndBusyCursor();
2242             }
2243         }
2244     }
2245 }
2246 
OnCmdExpCsv(wxCommandEvent & WXUNUSED (event))2247 void MyResultSetView::OnCmdExpCsv(wxCommandEvent & WXUNUSED(event))
2248 {
2249 //
2250 // exporting the ResultSet as CSV
2251 //
2252   int ret;
2253   wxString path;
2254   wxString lastDir;
2255   wxString target;
2256   wxString sql = MainFrame->GetQueryView()->GetSqlCtrl()->GetValue();
2257   wxFileDialog fileDialog(this, wxT("Exporting the ResultSet as CSV"),
2258                           wxT(""), wxT("result_set.csv"),
2259                           wxT("CSV file (*.csv)|*.csv|All files (*.*)|*.*"),
2260                           wxFD_SAVE | wxFD_OVERWRITE_PROMPT,
2261                           wxDefaultPosition, wxDefaultSize, wxT("filedlg"));
2262   lastDir = MainFrame->GetLastDirectory();
2263   if (lastDir.Len() >= 1)
2264     fileDialog.SetDirectory(lastDir);
2265   ret = fileDialog.ShowModal();
2266   if (ret == wxID_OK)
2267     {
2268       wxFileName file(fileDialog.GetPath());
2269       path = file.GetPath();
2270       path += file.GetPathSeparator();
2271       path += file.GetName();
2272       path += wxT(".csv");
2273       lastDir = file.GetPath();
2274       if (MainFrame->IsSetAskCharset() == false)
2275         {
2276           // using the default output charset
2277           MainFrame->SetLastDirectory(lastDir);
2278           ::wxBeginBusyCursor();
2279           MainFrame->ExportResultSetAsCsv(path, sql,
2280                                           MainFrame->GetDefaultCharset());
2281           ::wxEndBusyCursor();
2282       } else
2283         {
2284           // asking the charset to be used
2285           DumpTxtDialog dlg;
2286           target = wxT("CSV");
2287           dlg.Create(MainFrame, path, target, MainFrame->GetDefaultCharset());
2288           ret = dlg.ShowModal();
2289           if (ret == wxID_OK)
2290             {
2291               MainFrame->SetLastDirectory(lastDir);
2292               ::wxBeginBusyCursor();
2293               MainFrame->ExportResultSetAsCsv(path, sql, dlg.GetCharset());
2294               ::wxEndBusyCursor();
2295             }
2296         }
2297     }
2298 }
2299 
OnCmdExpHtml(wxCommandEvent & WXUNUSED (event))2300 void MyResultSetView::OnCmdExpHtml(wxCommandEvent & WXUNUSED(event))
2301 {
2302 //
2303 // exporting the ResultSet as HTML
2304 //
2305   int ret;
2306   wxString path;
2307   wxString lastDir;
2308   wxString target;
2309   wxString sql = MainFrame->GetQueryView()->GetSqlCtrl()->GetValue();
2310   wxFileDialog fileDialog(this, wxT("Exporting the ResultSet as HTML"),
2311                           wxT(""), wxT("result_set.html"),
2312                           wxT
2313                           ("HTML web page (*.html)|*.html|All files (*.*)|*.*"),
2314                           wxFD_SAVE | wxFD_OVERWRITE_PROMPT, wxDefaultPosition,
2315                           wxDefaultSize, wxT("filedlg"));
2316   lastDir = MainFrame->GetLastDirectory();
2317   if (lastDir.Len() >= 1)
2318     fileDialog.SetDirectory(lastDir);
2319   ret = fileDialog.ShowModal();
2320   if (ret == wxID_OK)
2321     {
2322       wxFileName file(fileDialog.GetPath());
2323       path = file.GetPath();
2324       path += file.GetPathSeparator();
2325       path += file.GetName();
2326       path += wxT(".html");
2327       lastDir = file.GetPath();
2328       if (MainFrame->IsSetAskCharset() == false)
2329         {
2330           // using the default output charset
2331           MainFrame->SetLastDirectory(lastDir);
2332           ::wxBeginBusyCursor();
2333           MainFrame->ExportResultSetAsHtml(path, sql,
2334                                            MainFrame->GetSqlitePath(),
2335                                            MainFrame->GetDefaultCharset());
2336           ::wxEndBusyCursor();
2337       } else
2338         {
2339           // asking the charset to be used
2340           DumpTxtDialog dlg;
2341           target = wxT("HTML");
2342           dlg.Create(MainFrame, path, target, MainFrame->GetDefaultCharset());
2343           ret = dlg.ShowModal();
2344           if (ret == wxID_OK)
2345             {
2346               MainFrame->SetLastDirectory(lastDir);
2347               ::wxBeginBusyCursor();
2348               MainFrame->ExportResultSetAsHtml(path, sql,
2349                                                MainFrame->GetSqlitePath(),
2350                                                dlg.GetCharset());
2351               ::wxEndBusyCursor();
2352             }
2353         }
2354     }
2355 }
2356 
OnCmdExpShp(wxCommandEvent & WXUNUSED (event))2357 void MyResultSetView::OnCmdExpShp(wxCommandEvent & WXUNUSED(event))
2358 {
2359 //
2360 // exporting the ResultSet as Shapefile
2361 //
2362   int ret;
2363   wxString path;
2364   wxString lastDir;
2365   wxString target;
2366   wxString sql = MainFrame->GetQueryView()->GetSqlCtrl()->GetValue();
2367   wxFileDialog fileDialog(this, wxT("Exporting the ResultSet as Shapefile"),
2368                           wxT(""), wxT("shapefile.shp"),
2369                           wxT
2370                           ("Shapefile (*.shp)|*.shp|All files (*.*)|*.*"),
2371                           wxFD_SAVE | wxFD_OVERWRITE_PROMPT,
2372                           wxDefaultPosition, wxDefaultSize, wxT("filedlg"));
2373   lastDir = MainFrame->GetLastDirectory();
2374   if (lastDir.Len() >= 1)
2375     fileDialog.SetDirectory(lastDir);
2376   ret = fileDialog.ShowModal();
2377   if (ret == wxID_OK)
2378     {
2379 
2380       wxFileName file(fileDialog.GetPath());
2381       path = file.GetPath();
2382       path += file.GetPathSeparator();
2383       path += file.GetName();
2384       lastDir = file.GetPath();
2385       if (MainFrame->IsSetAskCharset() == false)
2386         {
2387           // using the default output charset
2388           MainFrame->SetLastDirectory(lastDir);
2389           ::wxBeginBusyCursor();
2390           MainFrame->ExportResultSetAsShp(path, sql,
2391                                           MainFrame->GetDefaultCharset());
2392           ::wxEndBusyCursor();
2393       } else
2394         {
2395           // asking the charset to be used
2396           DumpTxtDialog dlg;
2397           target = wxT("Shapefile");
2398           dlg.Create(MainFrame, path, target, MainFrame->GetDefaultCharset());
2399           ret = dlg.ShowModal();
2400           if (ret == wxID_OK)
2401             {
2402               MainFrame->SetLastDirectory(lastDir);
2403               ::wxBeginBusyCursor();
2404               MainFrame->ExportResultSetAsShp(path, sql, dlg.GetCharset());
2405               ::wxEndBusyCursor();
2406             }
2407         }
2408     }
2409 }
2410 
OnCmdExpDif(wxCommandEvent & WXUNUSED (event))2411 void MyResultSetView::OnCmdExpDif(wxCommandEvent & WXUNUSED(event))
2412 {
2413 //
2414 // exporting the ResultSet as DIF spreadsheet
2415 //
2416   int ret;
2417   wxString path;
2418   wxString lastDir;
2419   wxString target;
2420   wxString sql = MainFrame->GetQueryView()->GetSqlCtrl()->GetValue();
2421 // asking Decimal Point / Date-Times params
2422   DumpSpreadsheetDialog sheet_dlg;
2423   char decimal_point;
2424   bool date_times;
2425   sheet_dlg.Create(MainFrame);
2426   ret = sheet_dlg.ShowModal();
2427   if (ret == wxID_OK)
2428     {
2429       decimal_point = sheet_dlg.GetDecimalPoint();
2430       date_times = sheet_dlg.IsDateTimes();
2431   } else
2432     return;
2433   wxFileDialog fileDialog(this,
2434                           wxT("Exporting the ResultSet as DIF spreadsheet"),
2435                           wxT(""), wxT("spreadsheet.dif"),
2436                           wxT
2437                           ("DIF spreadsheet document (*.dif)|*.dif|All files (*.*)|*.*"),
2438                           wxFD_SAVE | wxFD_OVERWRITE_PROMPT, wxDefaultPosition,
2439                           wxDefaultSize, wxT("filedlg"));
2440   lastDir = MainFrame->GetLastDirectory();
2441   if (lastDir.Len() >= 1)
2442     fileDialog.SetDirectory(lastDir);
2443   ret = fileDialog.ShowModal();
2444   if (ret == wxID_OK)
2445     {
2446 
2447       wxFileName file(fileDialog.GetPath());
2448       path = file.GetPath();
2449       path += file.GetPathSeparator();
2450       path += file.GetName();
2451       path += wxT(".dif");
2452       lastDir = file.GetPath();
2453       if (MainFrame->IsSetAskCharset() == false)
2454         {
2455           // using the default output charset
2456           MainFrame->SetLastDirectory(lastDir);
2457           ::wxBeginBusyCursor();
2458           MainFrame->ExportResultSetAsDif(path, sql,
2459                                           MainFrame->GetDefaultCharset(),
2460                                           decimal_point, date_times);
2461           ::wxEndBusyCursor();
2462       } else
2463         {
2464           // asking the charset to be used
2465           DumpTxtDialog dlg;
2466           target = wxT("DIF spreadsheet");
2467           dlg.Create(MainFrame, path, target, MainFrame->GetDefaultCharset());
2468           ret = dlg.ShowModal();
2469           if (ret == wxID_OK)
2470             {
2471               MainFrame->SetLastDirectory(lastDir);
2472               ::wxBeginBusyCursor();
2473               MainFrame->ExportResultSetAsDif(path, sql, dlg.GetCharset(),
2474                                               decimal_point, date_times);
2475               ::wxEndBusyCursor();
2476             }
2477         }
2478     }
2479 }
2480 
OnCmdExpSylk(wxCommandEvent & WXUNUSED (event))2481 void MyResultSetView::OnCmdExpSylk(wxCommandEvent & WXUNUSED(event))
2482 {
2483 //
2484 // exporting the ResultSet as SYLK spreadsheet
2485 //
2486   int ret;
2487   wxString path;
2488   wxString lastDir;
2489   wxString target;
2490   wxString sql = MainFrame->GetQueryView()->GetSqlCtrl()->GetValue();
2491 // asking Decimal Point / Date-Times params
2492   DumpSpreadsheetDialog sheet_dlg;
2493   bool date_times;
2494   sheet_dlg.Create(MainFrame);
2495   ret = sheet_dlg.ShowModal();
2496   if (ret == wxID_OK)
2497     date_times = sheet_dlg.IsDateTimes();
2498   else
2499     return;
2500   wxFileDialog fileDialog(this,
2501                           wxT("Exporting the ResultSet as SYLK spreadsheet"),
2502                           wxT(""), wxT("spreadsheet.slk"),
2503                           wxT
2504                           ("SYLK spreadsheet document (*.slk)|*.slk|All files (*.*)|*.*"),
2505                           wxFD_SAVE | wxFD_OVERWRITE_PROMPT, wxDefaultPosition,
2506                           wxDefaultSize, wxT("filedlg"));
2507   lastDir = MainFrame->GetLastDirectory();
2508   if (lastDir.Len() >= 1)
2509     fileDialog.SetDirectory(lastDir);
2510   ret = fileDialog.ShowModal();
2511   if (ret == wxID_OK)
2512     {
2513 
2514       wxFileName file(fileDialog.GetPath());
2515       path = file.GetPath();
2516       path += file.GetPathSeparator();
2517       path += file.GetName();
2518       path += wxT(".slk");
2519       lastDir = file.GetPath();
2520       if (MainFrame->IsSetAskCharset() == false)
2521         {
2522           // using the default output charset
2523           MainFrame->SetLastDirectory(lastDir);
2524           ::wxBeginBusyCursor();
2525           MainFrame->ExportResultSetAsSylk(path, sql,
2526                                            MainFrame->GetDefaultCharset(),
2527                                            date_times);
2528           ::wxEndBusyCursor();
2529       } else
2530         {
2531           // asking the charset to be used
2532           DumpTxtDialog dlg;
2533           target = wxT("SYLK spreadsheet");
2534           dlg.Create(MainFrame, path, target, MainFrame->GetDefaultCharset());
2535           ret = dlg.ShowModal();
2536           if (ret == wxID_OK)
2537             {
2538               MainFrame->SetLastDirectory(lastDir);
2539               ::wxBeginBusyCursor();
2540               MainFrame->ExportResultSetAsSylk(path, sql, dlg.GetCharset(),
2541                                                date_times);
2542               ::wxEndBusyCursor();
2543             }
2544         }
2545     }
2546 }
2547 
OnCmdExpDbf(wxCommandEvent & WXUNUSED (event))2548 void MyResultSetView::OnCmdExpDbf(wxCommandEvent & WXUNUSED(event))
2549 {
2550 //
2551 // exporting the ResultSet as DBF archive
2552 //
2553   int ret;
2554   wxString path;
2555   wxString lastDir;
2556   wxString target;
2557   wxString sql = MainFrame->GetQueryView()->GetSqlCtrl()->GetValue();
2558   wxFileDialog fileDialog(this, wxT("Exporting the ResultSet as DBF archive"),
2559                           wxT(""), wxT("archive.dbf"),
2560                           wxT
2561                           ("DBF archive (*.dbf)|*.dbf|All files (*.*)|*.*"),
2562                           wxFD_SAVE | wxFD_OVERWRITE_PROMPT,
2563                           wxDefaultPosition, wxDefaultSize, wxT("filedlg"));
2564   lastDir = MainFrame->GetLastDirectory();
2565   if (lastDir.Len() >= 1)
2566     fileDialog.SetDirectory(lastDir);
2567   ret = fileDialog.ShowModal();
2568   if (ret == wxID_OK)
2569     {
2570 
2571       wxFileName file(fileDialog.GetPath());
2572       path = file.GetPath();
2573       path += file.GetPathSeparator();
2574       path += file.GetName();
2575       path += wxT(".dbf");
2576       lastDir = file.GetPath();
2577       if (MainFrame->IsSetAskCharset() == false)
2578         {
2579           // using the default output charset
2580           MainFrame->SetLastDirectory(lastDir);
2581           ::wxBeginBusyCursor();
2582           MainFrame->ExportResultSetAsDbf(path, sql,
2583                                           MainFrame->GetDefaultCharset());
2584           ::wxEndBusyCursor();
2585       } else
2586         {
2587           // asking the charset to be used
2588           DumpTxtDialog dlg;
2589           target = wxT("DBF archive");
2590           dlg.Create(MainFrame, path, target, MainFrame->GetDefaultCharset());
2591           ret = dlg.ShowModal();
2592           if (ret == wxID_OK)
2593             {
2594               MainFrame->SetLastDirectory(lastDir);
2595               ::wxBeginBusyCursor();
2596               MainFrame->ExportResultSetAsDbf(path, sql, dlg.GetCharset());
2597               ::wxEndBusyCursor();
2598             }
2599         }
2600     }
2601 }
2602