]> git.saurik.com Git - wxWidgets.git/blame - samples/db/dbtest.cpp
layout improvement on mac
[wxWidgets.git] / samples / db / dbtest.cpp
CommitLineData
108106cf
JS
1///////////////////////////////////////////////////////////////////////////////
2// Name: dbtest.cpp
3// Purpose: wxWindows database demo app
4// Author: George Tasker
5// Modified by:
6// Created: 1998
7// RCS-ID: $Id$
8// Copyright: (c) 1998 Remstar International, Inc.
9// Licence: wxWindows licence
10///////////////////////////////////////////////////////////////////////////////
11
12/*
e70e8f4c 13 * SYNOPSIS START
108106cf 14
e70e8f4c
GT
15 This sample program demonstrates the cross-platform ODBC database classes
16 donated by the development team at Remstar International.
108106cf 17
e70e8f4c 18 The table this sample is based on is developer contact table, and shows
f6bcfd97 19 some of the simple uses of the database classes wxDb and wxDbTable.
108106cf 20
e70e8f4c 21 * SYNOPSIS END
108106cf
JS
22 */
23
24#ifdef __GNUG__
25#pragma implementation "dbtest.h"
26#endif
27
28#include "wx/wxprec.h"
29
30#ifdef __BORLANDC__
31#pragma hdrstop
32#endif //__BORLANDC__
33
34#ifndef WX_PRECOMP
35#include <wx/wx.h>
36#endif //WX_PRECOMP
37
618f2efa 38#if defined(__WXGTK__) || defined(__WXX11__)
7e616b10
RR
39#include "db.xpm"
40#endif
41
5b077d48 42#include <stdio.h> /* Included strictly for reading the text file with the database parameters */
108106cf 43
3fe813a9
GT
44//#include <wx/db.h> /* Required in the file which will get the data source connection */
45//#include <wx/dbtable.h> /* Has the wxDbTable object from which all data objects will inherit their data table functionality */
108106cf 46
3fe813a9 47//extern wxDbList WXDLLEXPORT *PtrBegDbList; /* from db.cpp, used in getting back error results from db connections */
108106cf 48
f21b2fd8
GT
49#if wxUSE_NEW_GRID
50#include <wx/grid.h>
51#include <wx/generic/gridctrl.h>
52#include <wx/dbgrid.h>
53
54#define CHOICEINT
55#endif
56
5b077d48
RR
57#include "dbtest.h" /* Header file for this demonstration program */
58#include "listdb.h" /* Code to support the "Lookup" button on the editor dialog */
1fc5dd6f
JS
59
60IMPLEMENT_APP(DatabaseDemoApp)
61
049977d0
GT
62extern wxChar ListDB_Selection[]; /* Used to return the first column value for the selected line from the listDB routines */
63extern wxChar ListDB_Selection2[]; /* Used to return the second column value for the selected line from the listDB routines */
108106cf 64
5d59e67a
GT
65
66#if !wxUSE_ODBC
67 #error Sample cannot be compiled unless setup.h has wxUSE_ODBC set to 1
68#endif
69
70
3fe813a9
GT
71bool DataTypeSupported(wxDb *pDb, SWORD datatype)
72{
73 wxDbSqlTypeInfo sqlTypeInfo;
74
a4054ad1 75 bool breakpoint = FALSE;
3fe813a9
GT
76
77 if (pDb->GetDataTypeInfo(datatype, sqlTypeInfo))
a4054ad1 78 breakpoint = TRUE;
3fe813a9
GT
79
80 return breakpoint;
81
82} // GetDataTypesSupported();
83
84
85
86void CheckSupportForAllDataTypes(wxDb *pDb)
87{
3f030b48 88 wxLogMessage("\nThe following datatypes are supported by the\ndatabase you are currently connected to:");
3fe813a9 89#ifdef SQL_C_BINARY
3f030b48
GT
90 if (DataTypeSupported(pDb,SQL_C_BINARY))
91 wxLogMessage("SQL_C_BINARY");
3fe813a9
GT
92#endif
93#ifdef SQL_C_BIT
3f030b48
GT
94 if (DataTypeSupported(pDb,SQL_C_BIT))
95 wxLogMessage("SQL_C_BIT");
3fe813a9
GT
96#endif
97#ifdef SQL_C_BOOKMARK
3f030b48
GT
98 if (DataTypeSupported(pDb,SQL_C_BOOKMARK))
99 wxLogMessage("SQL_C_BOOKMARK");
3fe813a9
GT
100#endif
101#ifdef SQL_C_CHAR
3f030b48
GT
102 if (DataTypeSupported(pDb,SQL_C_CHAR))
103 wxLogMessage("SQL_C_CHAR");
3fe813a9
GT
104#endif
105#ifdef SQL_C_DATE
3f030b48
GT
106 if (DataTypeSupported(pDb,SQL_C_DATE))
107 wxLogMessage("SQL_C_DATE");
3fe813a9
GT
108#endif
109#ifdef SQL_C_DEFAULT
3f030b48
GT
110 if (DataTypeSupported(pDb,SQL_C_DEFAULT))
111 wxLogMessage("SQL_C_DEFAULT");
3fe813a9
GT
112#endif
113#ifdef SQL_C_DOUBLE
3f030b48
GT
114 if (DataTypeSupported(pDb,SQL_C_DOUBLE))
115 wxLogMessage("SQL_C_DOUBLE");
3fe813a9
GT
116#endif
117#ifdef SQL_C_FLOAT
3f030b48
GT
118 if (DataTypeSupported(pDb,SQL_C_FLOAT))
119 wxLogMessage("SQL_C_FLOAT");
3fe813a9
GT
120#endif
121#ifdef SQL_C_GUID
3f030b48
GT
122 if (DataTypeSupported(pDb,SQL_C_GUID))
123 wxLogMessage("SQL_C_GUID");
3fe813a9
GT
124#endif
125#ifdef SQL_C_INTERVAL_DAY
3f030b48
GT
126 if (DataTypeSupported(pDb,SQL_C_INTERVAL_DAY))
127 wxLogMessage("SQL_C_INTERVAL_DAY");
3fe813a9
GT
128#endif
129#ifdef SQL_C_INTERVAL_DAY_TO_HOUR
3f030b48
GT
130 if (DataTypeSupported(pDb,SQL_C_INTERVAL_DAY_TO_HOUR))
131 wxLogMessage("SQL_C_INTERVAL_DAY_TO_HOUR");
3fe813a9
GT
132#endif
133#ifdef SQL_C_INTERVAL_DAY_TO_MINUTE
3f030b48
GT
134 if (DataTypeSupported(pDb,SQL_C_INTERVAL_DAY_TO_MINUTE))
135 wxLogMessage("SQL_C_INTERVAL_DAY_TO_MINUTE");
3fe813a9
GT
136#endif
137#ifdef SQL_C_INTERVAL_DAY_TO_SECOND
3f030b48
GT
138 if (DataTypeSupported(pDb,SQL_C_INTERVAL_DAY_TO_SECOND))
139 wxLogMessage("SQL_C_INTERVAL_DAY_TO_SECOND");
3fe813a9
GT
140#endif
141#ifdef SQL_C_INTERVAL_HOUR
3f030b48
GT
142 if (DataTypeSupported(pDb,SQL_C_INTERVAL_HOUR))
143 wxLogMessage("SQL_C_INTERVAL_HOUR");
3fe813a9
GT
144#endif
145#ifdef SQL_C_INTERVAL_HOUR_TO_MINUTE
3f030b48
GT
146 if (DataTypeSupported(pDb,SQL_C_INTERVAL_HOUR_TO_MINUTE))
147 wxLogMessage("SQL_C_INTERVAL_HOUR_TO_MINUTE");
3fe813a9
GT
148#endif
149#ifdef SQL_C_INTERVAL_HOUR_TO_SECOND
3f030b48
GT
150 if (DataTypeSupported(pDb,SQL_C_INTERVAL_HOUR_TO_SECOND))
151 wxLogMessage("SQL_C_INTERVAL_HOUR_TO_SECOND");
3fe813a9
GT
152#endif
153#ifdef SQL_C_INTERVAL_MINUTE
3f030b48
GT
154 if (DataTypeSupported(pDb,SQL_C_INTERVAL_MINUTE))
155 wxLogMessage("SQL_C_INTERVAL_MINUTE");
3fe813a9
GT
156#endif
157#ifdef SQL_C_INTERVAL_MINUTE_TO_SECOND
3f030b48
GT
158 if (DataTypeSupported(pDb,SQL_C_INTERVAL_MINUTE_TO_SECOND))
159 wxLogMessage("SQL_C_INTERVAL_MINUTE_TO_SECOND");
3fe813a9
GT
160#endif
161#ifdef SQL_C_INTERVAL_MONTH
3f030b48
GT
162 if (DataTypeSupported(pDb,SQL_C_INTERVAL_MONTH))
163 wxLogMessage("SQL_C_INTERVAL_MONTH");
3fe813a9
GT
164#endif
165#ifdef SQL_C_INTERVAL_SECOND
3f030b48
GT
166 if (DataTypeSupported(pDb,SQL_C_INTERVAL_SECOND))
167 wxLogMessage("SQL_C_INTERVAL_SECOND");
3fe813a9
GT
168#endif
169#ifdef SQL_C_INTERVAL_YEAR
3f030b48
GT
170 if (DataTypeSupported(pDb,SQL_C_INTERVAL_YEAR))
171 wxLogMessage("SQL_C_INTERVAL_YEAR");
3fe813a9
GT
172#endif
173#ifdef SQL_C_INTERVAL_YEAR_TO_MONTH
3f030b48
GT
174 if (DataTypeSupported(pDb,SQL_C_INTERVAL_YEAR_TO_MONTH))
175 wxLogMessage("SQL_C_INTERVAL_YEAR_TO_MONTH");
3fe813a9
GT
176#endif
177#ifdef SQL_C_LONG
3f030b48
GT
178 if (DataTypeSupported(pDb,SQL_C_LONG))
179 wxLogMessage("SQL_C_LONG");
3fe813a9
GT
180#endif
181#ifdef SQL_C_NUMERIC
3f030b48
GT
182 if (DataTypeSupported(pDb,SQL_C_NUMERIC))
183 wxLogMessage("SQL_C_NUMERIC");
3fe813a9
GT
184#endif
185#ifdef SQL_C_SBIGINT
3f030b48
GT
186 if (DataTypeSupported(pDb,SQL_C_SBIGINT))
187 wxLogMessage("SQL_C_SBIGINT");
3fe813a9
GT
188#endif
189#ifdef SQL_C_SHORT
3f030b48
GT
190 if (DataTypeSupported(pDb,SQL_C_SHORT))
191 wxLogMessage("SQL_C_SHORT");
3fe813a9
GT
192#endif
193#ifdef SQL_C_SLONG
3f030b48
GT
194 if (DataTypeSupported(pDb,SQL_C_SLONG))
195 wxLogMessage("SQL_C_SLONG");
3fe813a9
GT
196#endif
197#ifdef SQL_C_SSHORT
3f030b48
GT
198 if (DataTypeSupported(pDb,SQL_C_SSHORT))
199 wxLogMessage("SQL_C_SSHORT");
3fe813a9
GT
200#endif
201#ifdef SQL_C_STINYINT
3f030b48
GT
202 if (DataTypeSupported(pDb,SQL_C_STINYINT))
203 wxLogMessage("SQL_C_STINYINT");
3fe813a9
GT
204#endif
205#ifdef SQL_C_TIME
3f030b48
GT
206 if (DataTypeSupported(pDb,SQL_C_TIME))
207 wxLogMessage("SQL_C_TIME");
3fe813a9
GT
208#endif
209#ifdef SQL_C_TIMESTAMP
3f030b48
GT
210 if (DataTypeSupported(pDb,SQL_C_TIMESTAMP))
211 wxLogMessage("SQL_C_TIMESTAMP");
3fe813a9
GT
212#endif
213#ifdef SQL_C_TINYINT
3f030b48
GT
214 if (DataTypeSupported(pDb,SQL_C_TINYINT))
215 wxLogMessage("SQL_C_TINYINT");
3fe813a9
GT
216#endif
217#ifdef SQL_C_TYPE_DATE
3f030b48
GT
218 if (DataTypeSupported(pDb,SQL_C_TYPE_DATE))
219 wxLogMessage("SQL_C_TYPE_DATE");
3fe813a9
GT
220#endif
221#ifdef SQL_C_TYPE_TIME
3f030b48
GT
222 if (DataTypeSupported(pDb,SQL_C_TYPE_TIME))
223 wxLogMessage("SQL_C_TYPE_TIME");
3fe813a9
GT
224#endif
225#ifdef SQL_C_TYPE_TIMESTAMP
3f030b48
GT
226 if (DataTypeSupported(pDb,SQL_C_TYPE_TIMESTAMP))
227 wxLogMessage("SQL_C_TYPE_TIMESTAMP");
3fe813a9
GT
228#endif
229#ifdef SQL_C_UBIGINT
3f030b48
GT
230 if (DataTypeSupported(pDb,SQL_C_UBIGINT))
231 wxLogMessage("SQL_C_UBIGINT");
3fe813a9
GT
232#endif
233#ifdef SQL_C_ULONG
3f030b48
GT
234 if (DataTypeSupported(pDb,SQL_C_ULONG))
235 wxLogMessage("SQL_C_ULONG");
3fe813a9
GT
236#endif
237#ifdef SQL_C_USHORT
3f030b48
GT
238 if (DataTypeSupported(pDb,SQL_C_USHORT))
239 wxLogMessage("SQL_C_USHORT");
3fe813a9
GT
240#endif
241#ifdef SQL_C_UTINYINT
3f030b48
GT
242 if (DataTypeSupported(pDb,SQL_C_UTINYINT))
243 wxLogMessage("SQL_C_UTINYINT");
3fe813a9
GT
244#endif
245#ifdef SQL_C_VARBOOKMARK
3f030b48
GT
246 if (DataTypeSupported(pDb,SQL_C_VARBOOKMARK))
247 wxLogMessage("SQL_C_VARBOOKMARK");
3fe813a9
GT
248#endif
249
250// Extended SQL types
251#ifdef SQL_DATE
3f030b48
GT
252 if (DataTypeSupported(pDb,SQL_DATE))
253 wxLogMessage("SQL_DATE");
3fe813a9
GT
254#endif
255#ifdef SQL_INTERVAL
3f030b48
GT
256 if (DataTypeSupported(pDb,SQL_INTERVAL))
257 wxLogMessage("SQL_INTERVAL");
3fe813a9
GT
258#endif
259#ifdef SQL_TIME
3f030b48
GT
260 if (DataTypeSupported(pDb,SQL_TIME))
261 wxLogMessage("SQL_TIME");
3fe813a9
GT
262#endif
263#ifdef SQL_TIMESTAMP
3f030b48
GT
264 if (DataTypeSupported(pDb,SQL_TIMESTAMP))
265 wxLogMessage("SQL_TIMESTAMP");
3fe813a9
GT
266#endif
267#ifdef SQL_LONGVARCHAR
3f030b48
GT
268 if (DataTypeSupported(pDb,SQL_LONGVARCHAR))
269 wxLogMessage("SQL_LONGVARCHAR");
3fe813a9
GT
270#endif
271#ifdef SQL_BINARY
3f030b48
GT
272 if (DataTypeSupported(pDb,SQL_BINARY))
273 wxLogMessage("SQL_BINARY");
3fe813a9
GT
274#endif
275#ifdef SQL_VARBINARY
3f030b48
GT
276 if (DataTypeSupported(pDb,SQL_VARBINARY))
277 wxLogMessage("SQL_VARBINARY");
3fe813a9
GT
278#endif
279#ifdef SQL_LONGVARBINARY
3f030b48
GT
280 if (DataTypeSupported(pDb,SQL_LONGVARBINARY))
281 wxLogMessage("SQL_LONGVARBINARY");
3fe813a9
GT
282#endif
283#ifdef SQL_BIGINT
3f030b48
GT
284 if (DataTypeSupported(pDb,SQL_BIGINT))
285 wxLogMessage("SQL_BIGINT");
3fe813a9
GT
286#endif
287#ifdef SQL_TINYINT
3f030b48
GT
288 if (DataTypeSupported(pDb,SQL_TINYINT))
289 wxLogMessage("SQL_TINYINT");
3fe813a9
GT
290#endif
291#ifdef SQL_BIT
3f030b48
GT
292 if (DataTypeSupported(pDb,SQL_BIT))
293 wxLogMessage("SQL_BIT");
3fe813a9
GT
294#endif
295#ifdef SQL_GUID
3f030b48
GT
296 if (DataTypeSupported(pDb,SQL_GUID))
297 wxLogMessage("SQL_GUID");
3fe813a9
GT
298#endif
299
300#ifdef SQL_CHAR
3f030b48
GT
301 if (DataTypeSupported(pDb,SQL_CHAR))
302 wxLogMessage("SQL_CHAR");
3fe813a9
GT
303#endif
304#ifdef SQL_INTEGER
3f030b48
GT
305 if (DataTypeSupported(pDb,SQL_INTEGER))
306 wxLogMessage("SQL_INTEGER");
3fe813a9
GT
307#endif
308#ifdef SQL_SMALLINT
3f030b48
GT
309 if (DataTypeSupported(pDb,SQL_SMALLINT))
310 wxLogMessage("SQL_SMALLINT");
3fe813a9
GT
311#endif
312#ifdef SQL_REAL
3f030b48
GT
313 if (DataTypeSupported(pDb,SQL_REAL))
314 wxLogMessage("SQL_REAL");
3fe813a9
GT
315#endif
316#ifdef SQL_DOUBLE
3f030b48
GT
317 if (DataTypeSupported(pDb,SQL_DOUBLE))
318 wxLogMessage("SQL_DOUBLE");
3fe813a9
GT
319#endif
320#ifdef SQL_NUMERIC
3f030b48
GT
321 if (DataTypeSupported(pDb,SQL_NUMERIC))
322 wxLogMessage("SQL_NUMERIC");
3fe813a9
GT
323#endif
324#ifdef SQL_DATE
3f030b48
GT
325 if (DataTypeSupported(pDb,SQL_DATE))
326 wxLogMessage("SQL_DATE");
3fe813a9
GT
327#endif
328#ifdef SQL_TIME
3f030b48
GT
329 if (DataTypeSupported(pDb,SQL_TIME))
330 wxLogMessage("SQL_TIME");
3fe813a9
GT
331#endif
332#ifdef SQL_TIMESTAMP
3f030b48
GT
333 if (DataTypeSupported(pDb,SQL_TIMESTAMP))
334 wxLogMessage("SQL_TIMESTAMP");
3fe813a9
GT
335#endif
336#ifdef SQL_VARCHAR
3f030b48
GT
337 if (DataTypeSupported(pDb,SQL_VARCHAR))
338 wxLogMessage("SQL_VARCHAR");
3fe813a9
GT
339#endif
340
3fe813a9
GT
341// UNICODE
342#ifdef SQL_C_TCHAR
3f030b48
GT
343 if (DataTypeSupported(pDb,SQL_C_TCHAR))
344 wxLogMessage("SQL_C_TCHAR (Unicode support is possible)");
3fe813a9 345#endif
3f030b48
GT
346
347 wxLogMessage("\n");
3fe813a9
GT
348} // CheckSupportForAllDataTypes()
349
350
1fc5dd6f 351bool DatabaseDemoApp::OnInit()
108106cf 352{
ea24eeb2
GT
353 DbConnectInf = NULL;
354 Contact = NULL;
049977d0 355
e70e8f4c 356 // Create the main frame window
94613352 357 DemoFrame = new DatabaseDemoFrame(NULL, wxT("wxWindows Database Demo"), wxPoint(50, 50), wxSize(537, 480));
e70e8f4c
GT
358
359 // Give it an icon
360 DemoFrame->SetIcon(wxICON(db));
361
362 // Make a menubar
363 wxMenu *file_menu = new wxMenu;
94613352
GT
364 file_menu->Append(FILE_CREATE, wxT("&Create CONTACT table"));
365 file_menu->Append(FILE_RECREATE_TABLE, wxT("&Recreate CONTACT table"));
366 file_menu->Append(FILE_RECREATE_INDEXES, wxT("&Recreate CONTACT indexes"));
f21b2fd8
GT
367#if wxUSE_NEW_GRID
368 file_menu->Append(FILE_DBGRID_TABLE, wxT("&Open DB Grid example"));
369#endif
94613352 370 file_menu->Append(FILE_EXIT, wxT("E&xit"));
e70e8f4c
GT
371
372 wxMenu *edit_menu = new wxMenu;
94613352 373 edit_menu->Append(EDIT_PARAMETERS, wxT("&Parameters..."));
e70e8f4c 374
ea24eeb2
GT
375 wxMenu *help_menu = new wxMenu;
376 help_menu->Append(HELP_ABOUT, wxT("&About"));
e70e8f4c
GT
377
378 wxMenuBar *menu_bar = new wxMenuBar;
94613352
GT
379 menu_bar->Append(file_menu, wxT("&File"));
380 menu_bar->Append(edit_menu, wxT("&Edit"));
ea24eeb2 381 menu_bar->Append(help_menu, wxT("&Help"));
e70e8f4c
GT
382 DemoFrame->SetMenuBar(menu_bar);
383
e70e8f4c
GT
384 params.ODBCSource[0] = 0;
385 params.UserName[0] = 0;
386 params.Password[0] = 0;
387 params.DirPath[0] = 0;
388
3ca6a5f0 389 // Show the frame
a4054ad1 390 DemoFrame->Show(TRUE);
3ca6a5f0 391
049977d0
GT
392 // Passing NULL for the SQL environment handle causes
393 // the wxDbConnectInf constructor to obtain a handle
394 // for you.
395 //
396 // WARNING: Be certain that you do not free this handle
397 // directly with SQLFreeEnv(). Use either the
398 // method ::FreeHenv() or delete the DbConnectInf.
399 DbConnectInf = new wxDbConnectInf(NULL, params.ODBCSource, params.UserName,
400 params.Password, params.DirPath);
401
402 if (!DbConnectInf || !DbConnectInf->GetHenv())
403 {
404 wxMessageBox(wxT("Unable to define data source connection info."), wxT("DB CONNECTION ERROR..."),wxOK | wxICON_EXCLAMATION);
ea24eeb2 405 wxDELETE(DbConnectInf);
049977d0
GT
406 }
407
3fe813a9
GT
408 if (!ReadParamFile(params))
409 DemoFrame->BuildParameterDialog(NULL);
410
411 if (!wxStrlen(params.ODBCSource))
412 {
ea24eeb2 413 wxDELETE(DbConnectInf);
a4054ad1 414 return(FALSE);
3fe813a9
GT
415 }
416
417 DbConnectInf->SetDsn(params.ODBCSource);
418 DbConnectInf->SetUserID(params.UserName);
419 DbConnectInf->SetPassword(params.Password);
420 DbConnectInf->SetDefaultDir(params.DirPath);
421
049977d0
GT
422 READONLY_DB = wxDbGetConnection(DbConnectInf);
423 if (READONLY_DB == 0)
424 {
425 wxMessageBox(wxT("Unable to connect to the data source.\n\nCheck the name of your data source to verify it has been correctly entered/spelled.\n\nWith some databases, the user name and password must\nbe created with full rights to the CONTACT table prior to making a connection\n(using tools provided by the database manufacturer)"), wxT("DB CONNECTION ERROR..."),wxOK | wxICON_EXCLAMATION);
426 DemoFrame->BuildParameterDialog(NULL);
ea24eeb2 427 wxDELETE(DbConnectInf);
049977d0 428 wxMessageBox(wxT("Now exiting program.\n\nRestart program to try any new settings."),wxT("Notice..."),wxOK | wxICON_INFORMATION);
a4054ad1 429 return(FALSE);
049977d0
GT
430 }
431
432 DemoFrame->BuildEditorDialog();
433
434 // Show the frame
435 DemoFrame->Refresh();
436
a4054ad1 437 return TRUE;
049977d0
GT
438} // DatabaseDemoApp::OnInit()
439
440
f369dd4f
GT
441/*
442* Remove CR or CR/LF from a character string.
443*/
444char* wxRemoveLineTerminator(char* aString)
445{
446 int len = strlen(aString);
447 while (len > 0 && (aString[len-1] == '\r' || aString[len-1] == '\n')) {
448 aString[len-1] = '\0';
449 len--;
450 }
451 return aString;
452}
453
454
049977d0
GT
455bool DatabaseDemoApp::ReadParamFile(Cparameters &params)
456{
e70e8f4c 457 FILE *paramFile;
049977d0 458 if ((paramFile = fopen(PARAM_FILENAME, wxT("r"))) == NULL)
e70e8f4c
GT
459 {
460 wxString tStr;
049977d0 461 tStr.Printf(wxT("Unable to open the parameter file '%s' for reading.\n\nYou must specify the data source, user name, and\npassword that will be used and save those settings."),PARAM_FILENAME);
94613352 462 wxMessageBox(tStr,wxT("File I/O Error..."),wxOK | wxICON_EXCLAMATION);
e70e8f4c 463
a4054ad1 464 return FALSE;
e70e8f4c
GT
465 }
466
94613352 467 wxChar buffer[1000+1];
e70e8f4c 468 fgets(buffer, sizeof(params.ODBCSource), paramFile);
f369dd4f 469 wxRemoveLineTerminator(buffer);
f6bcfd97 470 wxStrcpy(params.ODBCSource,buffer);
e70e8f4c
GT
471
472 fgets(buffer, sizeof(params.UserName), paramFile);
f369dd4f 473 wxRemoveLineTerminator(buffer);
f6bcfd97 474 wxStrcpy(params.UserName,buffer);
e70e8f4c
GT
475
476 fgets(buffer, sizeof(params.Password), paramFile);
f369dd4f 477 wxRemoveLineTerminator(buffer);
f6bcfd97 478 wxStrcpy(params.Password,buffer);
e70e8f4c
GT
479
480 fgets(buffer, sizeof(params.DirPath), paramFile);
f369dd4f 481 wxRemoveLineTerminator(buffer);
f6bcfd97 482 wxStrcpy(params.DirPath,buffer);
e70e8f4c
GT
483
484 fclose(paramFile);
485
a4054ad1 486 return TRUE;
049977d0 487} // DatabaseDemoApp::ReadParamFile()
e70e8f4c 488
049977d0
GT
489
490bool DatabaseDemoApp::WriteParamFile(Cparameters &params)
491{
492 FILE *paramFile;
493 if ((paramFile = fopen(PARAM_FILENAME, wxT("wt"))) == NULL)
e70e8f4c 494 {
049977d0
GT
495 wxString tStr;
496 tStr.Printf(wxT("Unable to write/overwrite '%s'."),PARAM_FILENAME);
497 wxMessageBox(tStr,wxT("File I/O Error..."),wxOK | wxICON_EXCLAMATION);
a4054ad1 498 return FALSE;
e70e8f4c
GT
499 }
500
049977d0
GT
501 fputs(wxGetApp().params.ODBCSource, paramFile);
502 fputc(wxT('\n'), paramFile);
503 fputs(wxGetApp().params.UserName, paramFile);
504 fputc(wxT('\n'), paramFile);
505 fputs(wxGetApp().params.Password, paramFile);
506 fputc(wxT('\n'), paramFile);
507 fputs(wxGetApp().params.DirPath, paramFile);
508 fputc(wxT('\n'), paramFile);
509 fclose(paramFile);
108106cf 510
a4054ad1 511 return TRUE;
049977d0
GT
512} // DatabaseDemoApp::WriteParamFile()
513
514
515void DatabaseDemoApp::CreateDataTable(bool recreate)
516{
a4054ad1 517 bool Ok = TRUE;
049977d0
GT
518 if (recreate)
519 Ok = (wxMessageBox(wxT("Any data currently residing in the table will be erased.\n\nAre you sure?"),wxT("Confirm"),wxYES_NO|wxICON_QUESTION) == wxYES);
520
521 if (!Ok)
522 return;
523
524 wxBeginBusyCursor();
525
a4054ad1 526 bool success = TRUE;
049977d0 527
ea24eeb2 528 Contact->GetDb()->RollbackTrans(); // Make sure the current cursor is in a known/stable state
049977d0
GT
529
530 if (!Contact->CreateTable(recreate))
531 {
532 wxEndBusyCursor();
533 wxString tStr;
f21b2fd8
GT
534 tStr = wxT("Error creating CONTACTS table.\nTable was not created.\n\n");
535 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),Contact->GetDb(),__FILE__,__LINE__),
536 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
537
a4054ad1 538 success = FALSE;
049977d0
GT
539 }
540 else
541 {
69a2b59d 542 if (!Contact->CreateIndexes(recreate))
049977d0
GT
543 {
544 wxEndBusyCursor();
545 wxString tStr;
f21b2fd8
GT
546 tStr = wxT("Error creating CONTACTS indexes.\nIndexes will be unavailable.\n\n");
547 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),Contact->GetDb(),__FILE__,__LINE__),
548 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
549
a4054ad1 550 success = FALSE;
049977d0
GT
551 }
552 }
553 while (wxIsBusy())
554 wxEndBusyCursor();
555
049977d0
GT
556 if (success)
557 wxMessageBox(wxT("Table and index(es) were successfully created."),wxT("Notice..."),wxOK | wxICON_INFORMATION);
558} // DatabaseDemoApp::CreateDataTable()
108106cf 559
3ca6a5f0 560
1fc5dd6f
JS
561BEGIN_EVENT_TABLE(DatabaseDemoFrame, wxFrame)
562 EVT_MENU(FILE_CREATE, DatabaseDemoFrame::OnCreate)
3ca6a5f0
BP
563 EVT_MENU(FILE_RECREATE_TABLE, DatabaseDemoFrame::OnRecreateTable)
564 EVT_MENU(FILE_RECREATE_INDEXES, DatabaseDemoFrame::OnRecreateIndexes)
f21b2fd8
GT
565#if wxUSE_NEW_GRID
566 EVT_MENU(FILE_DBGRID_TABLE, DatabaseDemoFrame::OnDbGridTable)
567#endif
1fc5dd6f
JS
568 EVT_MENU(FILE_EXIT, DatabaseDemoFrame::OnExit)
569 EVT_MENU(EDIT_PARAMETERS, DatabaseDemoFrame::OnEditParameters)
ea24eeb2 570 EVT_MENU(HELP_ABOUT, DatabaseDemoFrame::OnAbout)
1fc5dd6f
JS
571 EVT_CLOSE(DatabaseDemoFrame::OnCloseWindow)
572END_EVENT_TABLE()
108106cf 573
3ca6a5f0 574
108106cf 575// DatabaseDemoFrame constructor
1fc5dd6f 576DatabaseDemoFrame::DatabaseDemoFrame(wxFrame *frame, const wxString& title,
3ca6a5f0
BP
577 const wxPoint& pos, const wxSize& size):
578 wxFrame(frame, -1, title, pos, size)
108106cf 579{
3ca6a5f0
BP
580 // Put any code in necessary for initializing the main frame here
581 pEditorDlg = NULL;
582 pParamDlg = NULL;
3f030b48
GT
583
584 delete wxLog::SetActiveTarget(new wxLogStderr);
585
3ca6a5f0
BP
586} // DatabaseDemoFrame constructor
587
3f030b48
GT
588DatabaseDemoFrame::~DatabaseDemoFrame()
589{
590 delete wxLog::SetActiveTarget(NULL);
591} // DatabaseDemoFrame destructor
592
108106cf 593
1fc5dd6f
JS
594void DatabaseDemoFrame::OnCreate(wxCommandEvent& event)
595{
a4054ad1 596 wxGetApp().CreateDataTable(FALSE);
3ca6a5f0
BP
597} // DatabaseDemoFrame::OnCreate()
598
599
600void DatabaseDemoFrame::OnRecreateTable(wxCommandEvent& event)
601{
a4054ad1 602 wxGetApp().CreateDataTable(TRUE);
3ca6a5f0
BP
603} // DatabaseDemoFrame::OnRecreate()
604
605
606void DatabaseDemoFrame::OnRecreateIndexes(wxCommandEvent& event)
607{
69a2b59d
GT
608 wxGetApp().Contact->GetDb()->RollbackTrans(); // Make sure the current cursor is in a known/stable state
609
a4054ad1 610 if (!wxGetApp().Contact->CreateIndexes(TRUE))
3ca6a5f0 611 {
ea24eeb2
GT
612 while (wxIsBusy())
613 wxEndBusyCursor();
614 wxString tStr;
f21b2fd8
GT
615 tStr = wxT("Error creating CONTACTS indexes.\nNew indexes will be unavailable.\n\n");
616 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__FILE__,__LINE__),
617 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
618
3ca6a5f0 619 }
69a2b59d 620 else
ea24eeb2 621 wxMessageBox(wxT("Index(es) were successfully recreated."),wxT("Notice..."),wxOK | wxICON_INFORMATION);
3ca6a5f0 622
3ca6a5f0 623} // DatabaseDemoFrame::OnRecreateIndexes()
108106cf 624
ea24eeb2 625
f21b2fd8
GT
626#if wxUSE_NEW_GRID
627void DatabaseDemoFrame::OnDbGridTable(wxCommandEvent& )
628{
629 DbGridFrame *frame = new DbGridFrame(this);
630 if (frame->Initialize())
631 {
632 frame->Show();
633 }
634}
635#endif
636
1fc5dd6f 637void DatabaseDemoFrame::OnExit(wxCommandEvent& event)
108106cf 638{
3f755e2d 639 Close();
3ca6a5f0
BP
640} // DatabaseDemoFrame::OnExit()
641
108106cf 642
1fc5dd6f
JS
643void DatabaseDemoFrame::OnEditParameters(wxCommandEvent& event)
644{
e70e8f4c
GT
645 if ((pEditorDlg->mode != mCreate) && (pEditorDlg->mode != mEdit))
646 BuildParameterDialog(this);
647 else
94613352 648 wxMessageBox(wxT("Cannot change database parameters while creating or editing a record"),wxT("Notice..."),wxOK | wxICON_INFORMATION);
3ca6a5f0
BP
649} // DatabaseDemoFrame::OnEditParameters()
650
1fc5dd6f
JS
651
652void DatabaseDemoFrame::OnAbout(wxCommandEvent& event)
653{
94613352 654 wxMessageBox(wxT("wxWindows sample program for database classes\n\nContributed on 27 July 1998"),wxT("About..."),wxOK | wxICON_INFORMATION);
3ca6a5f0
BP
655} // DatabaseDemoFrame::OnAbout()
656
108106cf 657
049977d0
GT
658// Put any additional checking necessary to make certain it is alright
659// to close the program here that is not done elsewhere
1fc5dd6f 660void DatabaseDemoFrame::OnCloseWindow(wxCloseEvent& event)
108106cf 661{
3f755e2d 662 // Clean up time
3ca6a5f0 663 if (pEditorDlg && pEditorDlg->Close())
3f755e2d
GT
664 pEditorDlg = NULL;
665 else
f6bcfd97 666 {
3ca6a5f0
BP
667 if (pEditorDlg)
668 {
669 event.Veto();
670 return;
671 }
f6bcfd97
BP
672 }
673
ea24eeb2
GT
674 wxDELETE(wxGetApp().Contact);
675
3ca6a5f0
BP
676 // This function will close all the connections to the database that have been
677 // previously cached.
678 wxDbCloseConnections();
679
049977d0
GT
680 // Deletion of the wxDbConnectInf instance must be the LAST thing done that
681 // has anything to do with the database. Deleting this before disconnecting,
682 // freeing/closing connections, etc will result in a crash!
ea24eeb2 683 wxDELETE(wxGetApp().DbConnectInf);
3f755e2d 684
1fc5dd6f 685 this->Destroy();
3f755e2d 686
e3065973 687} // DatabaseDemoFrame::OnCloseWindow()
108106cf
JS
688
689
108106cf
JS
690void DatabaseDemoFrame::BuildEditorDialog()
691{
3ca6a5f0 692 pEditorDlg = NULL;
e70e8f4c 693 pEditorDlg = new CeditorDlg(this);
3ca6a5f0
BP
694 if (pEditorDlg)
695 {
696 pEditorDlg->Initialize();
697 if (!pEditorDlg->initialized)
698 {
699 pEditorDlg->Close();
973f2539 700 pEditorDlg = NULL;
94613352 701 wxMessageBox(wxT("Unable to initialize the editor dialog for some reason"),wxT("Error..."),wxOK | wxICON_EXCLAMATION);
049977d0 702 Close();
3ca6a5f0
BP
703 }
704 }
705 else
706 {
94613352 707 wxMessageBox(wxT("Unable to create the editor dialog for some reason"),wxT("Error..."),wxOK | wxICON_EXCLAMATION);
049977d0 708 Close();
3ca6a5f0 709 }
108106cf
JS
710} // DatabaseDemoFrame::BuildEditorDialog()
711
712
713void DatabaseDemoFrame::BuildParameterDialog(wxWindow *parent)
714{
e70e8f4c 715 pParamDlg = new CparameterDlg(parent);
108106cf 716
e70e8f4c 717 if (!pParamDlg)
94613352 718 wxMessageBox(wxT("Unable to create the parameter dialog for some reason"),wxT("Error..."),wxOK | wxICON_EXCLAMATION);
108106cf
JS
719} // DatabaseDemoFrame::BuildParameterDialog()
720
721
722/*
f6bcfd97 723 * Constructor note: If no wxDb object is passed in, a new connection to the database
108106cf
JS
724 * is created for this instance of Ccontact. This can be a slow process depending
725 * on the database engine being used, and some database engines have a limit on the
726 * number of connections (either hard limits, or license restricted) so care should
727 * be used to use as few connections as is necessary.
e70e8f4c 728 *
f6bcfd97 729 * IMPORTANT: Objects which share a wxDb pointer are ALL acted upon whenever a member
108106cf
JS
730 * function of pDb is called (i.e. CommitTrans() or RollbackTrans(), so if modifying
731 * or creating a table objects which use the same pDb, know that all the objects
732 * will be committed or rolled back when any of the objects has this function call made.
733 */
049977d0
GT
734Ccontact::Ccontact (wxDb *pwxDb) : wxDbTable(pwxDb ? pwxDb : wxDbGetConnection(wxGetApp().DbConnectInf),
735 CONTACT_TABLE_NAME, CONTACT_NO_COLS, wxT(""),
736 !wxDB_QUERY_ONLY, wxGetApp().DbConnectInf->GetDefaultDir())
108106cf 737{
e70e8f4c
GT
738 // This is used to represent whether the database connection should be released
739 // when this instance of the object is deleted. If using the same connection
740 // for multiple instance of database objects, then the connection should only be
741 // released when the last database instance using the connection is deleted
f6bcfd97 742 freeDbConn = !pwxDb;
e70e8f4c 743
3fe813a9
GT
744 if (GetDb())
745 GetDb()->SetSqlLogging(sqlLogON);
746
e70e8f4c 747 SetupColumns();
108106cf
JS
748
749} // Ccontact Constructor
750
751
752void Ccontact::Initialize()
753{
e70e8f4c
GT
754 Name[0] = 0;
755 Addr1[0] = 0;
756 Addr2[0] = 0;
757 City[0] = 0;
758 State[0] = 0;
759 PostalCode[0] = 0;
760 Country[0] = 0;
761 JoinDate.year = 1980;
762 JoinDate.month = 1;
763 JoinDate.day = 1;
764 JoinDate.hour = 0;
765 JoinDate.minute = 0;
766 JoinDate.second = 0;
767 JoinDate.fraction = 0;
768 NativeLanguage = langENGLISH;
a4054ad1 769 IsDeveloper = FALSE;
e70e8f4c
GT
770 Contributions = 0;
771 LinesOfCode = 0L;
108106cf
JS
772} // Ccontact::Initialize
773
774
775Ccontact::~Ccontact()
776{
e70e8f4c
GT
777 if (freeDbConn)
778 {
f6bcfd97 779 if (!wxDbFreeConnection(GetDb()))
e70e8f4c
GT
780 {
781 wxString tStr;
f21b2fd8
GT
782 tStr = wxT("Unable to Free the Ccontact data table handle\n\n");
783
784 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__FILE__,__LINE__),
785 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
e70e8f4c
GT
786 }
787 }
108106cf
JS
788} // Ccontract destructor
789
790
791/*
f6bcfd97 792 * Handles setting up all the connections for the interface from the wxDbTable
108106cf
JS
793 * functions to interface to the data structure used to store records in
794 * memory, and for all the column definitions that define the table structure
795 */
f21b2fd8 796void Ccontact::SetupColumns()
108106cf 797{
e70e8f4c
GT
798 // NOTE: Columns now are 8 character names, as that is all dBase can support. Longer
799 // names can be used for other database engines
a4054ad1
GT
800 SetColDefs ( 0,wxT("NAME"), DB_DATA_TYPE_VARCHAR, Name, SQL_C_CHAR, sizeof(Name), TRUE, TRUE); // Primary index
801 SetColDefs ( 1,wxT("ADDRESS1"), DB_DATA_TYPE_VARCHAR, Addr1, SQL_C_CHAR, sizeof(Addr1), FALSE,TRUE);
802 SetColDefs ( 2,wxT("ADDRESS2"), DB_DATA_TYPE_VARCHAR, Addr2, SQL_C_CHAR, sizeof(Addr2), FALSE,TRUE);
803 SetColDefs ( 3,wxT("CITY"), DB_DATA_TYPE_VARCHAR, City, SQL_C_CHAR, sizeof(City), FALSE,TRUE);
804 SetColDefs ( 4,wxT("STATE"), DB_DATA_TYPE_VARCHAR, State, SQL_C_CHAR, sizeof(State), FALSE,TRUE);
805 SetColDefs ( 5,wxT("POSTCODE"), DB_DATA_TYPE_VARCHAR, PostalCode, SQL_C_CHAR, sizeof(PostalCode), FALSE,TRUE);
806 SetColDefs ( 6,wxT("COUNTRY"), DB_DATA_TYPE_VARCHAR, Country, SQL_C_CHAR, sizeof(Country), FALSE,TRUE);
807 SetColDefs ( 7,wxT("JOINDATE"), DB_DATA_TYPE_DATE, &JoinDate, SQL_C_TIMESTAMP, sizeof(JoinDate), FALSE,TRUE);
808 SetColDefs ( 8,wxT("IS_DEV"), DB_DATA_TYPE_INTEGER, &IsDeveloper, SQL_C_BOOLEAN(IsDeveloper), sizeof(IsDeveloper), FALSE,TRUE);
809 SetColDefs ( 9,wxT("CONTRIBS"), DB_DATA_TYPE_INTEGER, &Contributions, SQL_C_UTINYINT, sizeof(Contributions), FALSE,TRUE);
810 SetColDefs (10,wxT("LINE_CNT"), DB_DATA_TYPE_INTEGER, &LinesOfCode, SQL_C_ULONG, sizeof(LinesOfCode), FALSE,TRUE);
811 SetColDefs (11,wxT("LANGUAGE"), DB_DATA_TYPE_INTEGER, &NativeLanguage, SQL_C_ENUM, sizeof(NativeLanguage), FALSE,TRUE);
3fe813a9 812#if wxODBC_BLOB_EXPERIMENT > 0
a4054ad1 813 SetColDefs (12,wxT("PICTURE"), DB_DATA_TYPE_BLOB, Picture, SQL_LONGVARBINARY, sizeof(Picture), FALSE,TRUE);
3fe813a9 814#endif
108106cf
JS
815} // Ccontact::SetupColumns
816
817
69a2b59d 818bool Ccontact::CreateIndexes(bool recreate)
108106cf 819{
e70e8f4c
GT
820 // This index could easily be accomplished with an "orderBy" clause,
821 // but is done to show how to construct a non-primary index.
822 wxString indexName;
f6bcfd97 823 wxDbIdxDef idxDef[2];
108106cf 824
a4054ad1 825 bool Ok = TRUE;
108106cf 826
f6bcfd97 827 wxStrcpy(idxDef[0].ColName, "IS_DEV");
a4054ad1 828 idxDef[0].Ascending = TRUE;
108106cf 829
f6bcfd97 830 wxStrcpy(idxDef[1].ColName, "NAME");
a4054ad1 831 idxDef[1].Ascending = TRUE;
108106cf 832
f6bcfd97 833 indexName = GetTableName();
e70e8f4c 834 indexName += "_IDX1";
a4054ad1 835 Ok = CreateIndex(indexName.c_str(), TRUE, 2, idxDef, recreate);
108106cf 836
e70e8f4c 837 return Ok;
108106cf
JS
838} // Ccontact::CreateIndexes()
839
840
841/*
842 * Having a function to do a query on the primary key (and possibly others) is
843 * very efficient and tighter coding so that it is available where ever the object
844 * is. Great for use with multiple tables when not using views or outer joins
845 */
049977d0 846bool Ccontact::FetchByName(const wxString &name)
108106cf 847{
24e2b35d 848 whereStr.Printf(wxT("NAME = '%s'"),name.c_str());
f6bcfd97 849 SetWhereClause(whereStr.c_str());
94613352 850 SetOrderByClause(wxT(""));
108106cf 851
e70e8f4c 852 if (!Query())
a4054ad1 853 return(FALSE);
108106cf 854
e70e8f4c
GT
855 // Fetch the record
856 return(GetNext());
108106cf
JS
857
858} // Ccontact::FetchByName()
859
860
861/*
862 *
863 * ************* DIALOGS ***************
864 *
865 */
866
867
868/* CeditorDlg constructor
869 *
870 * Creates the dialog used for creating/editing/deleting/copying a Ccontact object.
871 * This dialog actually is drawn in the main frame of the program
872 *
873 * An instance of Ccontact is created - "Contact" - which is used to hold the Ccontact
874 * object that is currently being worked with.
875 */
f6fcbb63
RR
876
877BEGIN_EVENT_TABLE(CeditorDlg, wxPanel)
878 EVT_BUTTON(-1, CeditorDlg::OnButton)
3f755e2d 879 EVT_CLOSE(CeditorDlg::OnCloseWindow)
f6fcbb63
RR
880END_EVENT_TABLE()
881
3ca6a5f0 882CeditorDlg::CeditorDlg(wxWindow *parent) : wxPanel (parent, 0, 0, 537, 480)
108106cf 883{
e70e8f4c
GT
884 // Since the ::OnCommand() function is overridden, this prevents the widget
885 // detection in ::OnCommand() until all widgets have been initialized to prevent
886 // uninitialized pointers from crashing the program
a4054ad1 887 widgetPtrsSet = FALSE;
e70e8f4c 888
a4054ad1 889 initialized = FALSE;
e70e8f4c 890
3fe813a9
GT
891 SetMode(mView);
892
a4054ad1 893 Show(FALSE);
108106cf
JS
894} // CeditorDlg constructor
895
896
e3065973 897void CeditorDlg::OnCloseWindow(wxCloseEvent& event)
108106cf 898{
e70e8f4c 899 // Clean up time
3f755e2d 900 if ((mode != mCreate) && (mode != mEdit))
e70e8f4c 901 {
e70e8f4c
GT
902 this->Destroy();
903 }
904 else
905 {
94613352 906 wxMessageBox(wxT("Must finish processing the current record being created/modified before exiting"),wxT("Notice..."),wxOK | wxICON_INFORMATION);
e70e8f4c
GT
907 event.Veto();
908 }
e3065973 909} // CeditorDlg::OnCloseWindow()
108106cf
JS
910
911
3ca6a5f0 912void CeditorDlg::OnButton(wxCommandEvent &event)
f6fcbb63 913{
3ca6a5f0
BP
914 wxWindow *win = (wxWindow*) event.GetEventObject();
915 OnCommand( *win, event );
916} // CeditorDlg::OnButton()
f6fcbb63 917
65d7ddc4 918
108106cf
JS
919void CeditorDlg::OnCommand(wxWindow& win, wxCommandEvent& event)
920{
e70e8f4c
GT
921 wxString widgetName;
922
923 widgetName = win.GetName();
924
925 if (!widgetPtrsSet)
926 return;
927
928 if (widgetName == pCreateBtn->GetName())
929 {
ea24eeb2 930 wxGetApp().Contact->Initialize();
e70e8f4c
GT
931 PutData();
932 SetMode( mCreate );
94613352 933 pNameTxt->SetValue(wxT(""));
e70e8f4c
GT
934 pNameTxt->SetFocus();
935 return;
936 }
937
938 if (widgetName == pEditBtn->GetName())
939 {
ea24eeb2 940 saveName = wxGetApp().Contact->Name;
e70e8f4c
GT
941 SetMode( mEdit );
942 pNameTxt->SetFocus();
943 return;
944 }
945
946 if (widgetName == pCopyBtn->GetName())
947 {
948 SetMode(mCreate);
94613352 949 pNameTxt->SetValue(wxT(""));
e70e8f4c
GT
950 pNameTxt->SetFocus();
951 return;
952 }
953
954 if (widgetName == pDeleteBtn->GetName())
955 {
94613352 956 bool Ok = (wxMessageBox(wxT("Are you sure?"),wxT("Confirm"),wxYES_NO|wxICON_QUESTION) == wxYES);
e70e8f4c
GT
957
958 if (!Ok)
959 return;
960
ea24eeb2 961 if (Ok && wxGetApp().Contact->Delete())
e70e8f4c
GT
962 {
963 // NOTE: Deletions are not finalized until a CommitTrans() is performed.
964 // If the commit were not performed, the program will continue to
965 // show the table contents as if they were deleted until this instance
966 // of Ccontact is deleted. If the Commit wasn't performed, the
967 // database will automatically Rollback the changes when the database
968 // connection is terminated
ea24eeb2 969 wxGetApp().Contact->GetDb()->CommitTrans();
e70e8f4c
GT
970
971 // Try to get the row that followed the just deleted row in the orderBy sequence
972 if (!GetNextRec())
973 {
974 // There was now row (in sequence) after the just deleted row, so get the
975 // row which preceded the just deleted row
976 if (!GetPrevRec())
977 {
978 // There are now no rows remaining, so clear the dialog widgets
ea24eeb2 979 wxGetApp().Contact->Initialize();
e70e8f4c
GT
980 PutData();
981 }
982 }
983 SetMode(mode); // force reset of button enable/disable
984 }
985 else
986 // Delete failed
ea24eeb2 987 wxGetApp().Contact->GetDb()->RollbackTrans();
e70e8f4c
GT
988
989 SetMode(mView);
990 return;
991 }
992
993 if (widgetName == pSaveBtn->GetName())
994 {
995 Save();
996 return;
997 }
998
999 if (widgetName == pCancelBtn->GetName())
1000 {
94613352 1001 bool Ok = (wxMessageBox(wxT("Are you sure?"),wxT("Confirm"),wxYES_NO|wxICON_QUESTION) == wxYES);
e70e8f4c
GT
1002
1003 if (!Ok)
1004 return;
1005
94613352 1006 if (saveName.IsEmpty())
e70e8f4c 1007 {
ea24eeb2 1008 wxGetApp().Contact->Initialize();
e70e8f4c
GT
1009 PutData();
1010 SetMode(mView);
1011 return;
1012 }
1013 else
1014 {
1015 // Requery previous record
ea24eeb2 1016 if (wxGetApp().Contact->FetchByName(saveName))
e70e8f4c
GT
1017 {
1018 PutData();
1019 SetMode(mView);
1020 return;
1021 }
1022 }
1023
1024 // Previous record not available, retrieve first record in table
ea24eeb2
GT
1025 if (wxGetApp().Contact->GetDb()->Dbms() != dbmsPOSTGRES &&
1026 wxGetApp().Contact->GetDb()->Dbms() != dbmsMY_SQL)
e70e8f4c 1027 {
ea24eeb2
GT
1028 wxGetApp().Contact->whereStr = wxT("NAME = (SELECT MIN(NAME) FROM ");
1029 wxGetApp().Contact->whereStr += wxGetApp().Contact->GetTableName();
1030 wxGetApp().Contact->whereStr += wxT(")");
1031 wxGetApp().Contact->SetWhereClause(wxGetApp().Contact->whereStr.c_str());
e70e8f4c
GT
1032 }
1033 else
ea24eeb2 1034 wxGetApp().Contact->SetWhereClause(wxT(""));
e70e8f4c 1035
ea24eeb2 1036 if (!wxGetApp().Contact->Query())
e70e8f4c
GT
1037 {
1038 wxString tStr;
f21b2fd8
GT
1039 tStr = wxT("ODBC error during Query()\n\n");
1040 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__FILE__,__LINE__),
1041 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
1042
e70e8f4c
GT
1043 SetMode(mView);
1044 return;
1045 }
ea24eeb2 1046 if (wxGetApp().Contact->GetNext()) // Successfully read first record
e70e8f4c
GT
1047 {
1048 PutData();
1049 SetMode(mView);
1050 return;
1051 }
1052 // No contacts are available, clear dialog
ea24eeb2 1053 wxGetApp().Contact->Initialize();
e70e8f4c
GT
1054 PutData();
1055 SetMode(mView);
1056 return;
1057 } // Cancel Button
1058
1059 if (widgetName == pPrevBtn->GetName())
1060 {
1061 if (!GetPrevRec())
1062 wxBell();
1063 return;
1064 } // Prev Button
1065
1066 if (widgetName == pNextBtn->GetName())
1067 {
1068 if (!GetNextRec())
1069 wxBell();
1070 return;
1071 } // Next Button
1072
1073 if (widgetName == pQueryBtn->GetName())
1074 {
1075 // Display the query dialog box
94613352 1076 wxChar qryWhere[DB_MAX_WHERE_CLAUSE_LEN+1];
ea24eeb2 1077 wxStrcpy(qryWhere, (const wxChar*) wxGetApp().Contact->qryWhereStr);
94613352 1078 wxChar *tblName[] = {(wxChar *)CONTACT_TABLE_NAME, 0};
ea24eeb2 1079 new CqueryDlg(GetParent(), wxGetApp().Contact->GetDb(), tblName, qryWhere);
e70e8f4c
GT
1080
1081 // Query the first record in the new record set and
1082 // display it, if the query string has changed.
ea24eeb2 1083 if (wxStrcmp(qryWhere, (const wxChar*) wxGetApp().Contact->qryWhereStr))
e70e8f4c 1084 {
ea24eeb2
GT
1085 wxGetApp().Contact->whereStr.Empty();
1086 wxGetApp().Contact->SetOrderByClause("NAME");
e70e8f4c 1087
ea24eeb2
GT
1088 if (wxGetApp().Contact->GetDb()->Dbms() != dbmsPOSTGRES &&
1089 wxGetApp().Contact->GetDb()->Dbms() != dbmsMY_SQL)
e70e8f4c 1090 {
ea24eeb2
GT
1091 wxGetApp().Contact->whereStr = wxT("NAME = (SELECT MIN(NAME) FROM ");
1092 wxGetApp().Contact->whereStr += CONTACT_TABLE_NAME;
e70e8f4c
GT
1093 }
1094
1095 // Append the query where string (if there is one)
ea24eeb2 1096 wxGetApp().Contact->qryWhereStr = qryWhere;
f6bcfd97 1097 if (wxStrlen(qryWhere))
e70e8f4c 1098 {
ea24eeb2
GT
1099 wxGetApp().Contact->whereStr += wxT(" WHERE ");
1100 wxGetApp().Contact->whereStr += wxGetApp().Contact->qryWhereStr;
e70e8f4c
GT
1101 }
1102 // Close the expression with a right paren
ea24eeb2 1103 wxGetApp().Contact->whereStr += wxT(")");
e70e8f4c 1104 // Requery the table
ea24eeb2
GT
1105 wxGetApp().Contact->SetWhereClause(wxGetApp().Contact->whereStr.c_str());
1106 if (!wxGetApp().Contact->Query())
e70e8f4c
GT
1107 {
1108 wxString tStr;
f21b2fd8
GT
1109 tStr = wxT("ODBC error during Query()\n\n");
1110 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__FILE__,__LINE__),
1111 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
1112
e70e8f4c
GT
1113 return;
1114 }
1115 // Display the first record from the query set
ea24eeb2
GT
1116 if (!wxGetApp().Contact->GetNext())
1117 wxGetApp().Contact->Initialize();
e70e8f4c
GT
1118 PutData();
1119 }
1120
1121 // Enable/Disable the reset button
ea24eeb2 1122 pResetBtn->Enable(!wxGetApp().Contact->qryWhereStr.IsEmpty());
e70e8f4c
GT
1123
1124 return;
1125 } // Query button
1126
1127
1128 if (widgetName == pResetBtn->GetName())
1129 {
1130 // Clear the additional where criteria established by the query feature
ea24eeb2
GT
1131 wxGetApp().Contact->qryWhereStr = wxT("");
1132 wxGetApp().Contact->SetOrderByClause(wxT("NAME"));
e70e8f4c 1133
ea24eeb2
GT
1134 if (wxGetApp().Contact->GetDb()->Dbms() != dbmsPOSTGRES &&
1135 wxGetApp().Contact->GetDb()->Dbms() != dbmsMY_SQL)
e70e8f4c 1136 {
ea24eeb2
GT
1137 wxGetApp().Contact->whereStr = wxT("NAME = (SELECT MIN(NAME) FROM ");
1138 wxGetApp().Contact->whereStr += CONTACT_TABLE_NAME;
1139 wxGetApp().Contact->whereStr += wxT(")");
e70e8f4c
GT
1140 }
1141
ea24eeb2
GT
1142 wxGetApp().Contact->SetWhereClause(wxGetApp().Contact->whereStr.c_str());
1143 if (!wxGetApp().Contact->Query())
e70e8f4c
GT
1144 {
1145 wxString tStr;
f21b2fd8
GT
1146 tStr = wxT("ODBC error during Query()\n\n");
1147 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__FILE__,__LINE__),
1148 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
e70e8f4c
GT
1149 return;
1150 }
ea24eeb2
GT
1151 if (!wxGetApp().Contact->GetNext())
1152 wxGetApp().Contact->Initialize();
e70e8f4c 1153 PutData();
a4054ad1 1154 pResetBtn->Enable(FALSE);
e70e8f4c
GT
1155
1156 return;
1157 } // Reset button
1158
1159
1160 if (widgetName == pNameListBtn->GetName())
1161 {
049977d0 1162 new ClookUpDlg(/* wxWindow *parent */ this,
94613352
GT
1163 /* wxChar *windowTitle */ wxT("Select contact name"),
1164 /* wxChar *tableName */ (wxChar *) CONTACT_TABLE_NAME,
1165 /* wxChar *dispCol1 */ wxT("NAME"),
1166 /* wxChar *dispCol2 */ wxT("JOINDATE"),
1167 /* wxChar *where */ wxT(""),
1168 /* wxChar *orderBy */ wxT("NAME"),
049977d0
GT
1169 /* wxDb *pDb */ wxGetApp().READONLY_DB,
1170 /* const wxString &defDir */ wxGetApp().DbConnectInf->GetDefaultDir(),
a4054ad1 1171 /* bool distinctValues */ TRUE);
e70e8f4c 1172
f6bcfd97 1173 if (ListDB_Selection && wxStrlen(ListDB_Selection))
e70e8f4c 1174 {
94613352 1175 wxString w = wxT("NAME = '");
e70e8f4c 1176 w += ListDB_Selection;
94613352 1177 w += wxT("'");
049977d0 1178 GetRec(w);
e70e8f4c
GT
1179 }
1180
1181 return;
1182 }
3f030b48
GT
1183
1184 if (widgetName == pDataTypesBtn->GetName())
1185 {
1186 CheckSupportForAllDataTypes(wxGetApp().READONLY_DB);
69a2b59d 1187 wxMessageBox("Support datatypes was dumped to stdout.");
3f030b48
GT
1188 return;
1189 } // Data types Button
1190
1191 if (widgetName == pDbDiagsBtn->GetName())
1192 {
1193 DisplayDbDiagnostics(wxGetApp().READONLY_DB);
69a2b59d
GT
1194 wxMessageBox("Diagnostics info was dumped to stdout.");
1195 return;
1196 }
1197
1198 if (widgetName == pCatalogBtn->GetName())
1199 {
1200 if (wxGetApp().Contact->GetDb()->Catalog("","catalog.txt"))
1201 wxMessageBox("The file 'catalog.txt' was created.");
1202 else
1203 wxMessageBox("Creation of the file 'catalog.txt' was failed.");
3f030b48
GT
1204 return;
1205 }
1206
108106cf
JS
1207} // CeditorDlg::OnCommand()
1208
1209
3ca6a5f0
BP
1210bool CeditorDlg::Initialize()
1211{
1212 // Create the data structure and a new database connection.
1213 // (As there is not a pDb being passed in the constructor, a new database
1214 // connection is created)
ea24eeb2 1215 wxGetApp().Contact = new Ccontact();
3ca6a5f0 1216
ea24eeb2 1217 if (!wxGetApp().Contact)
3ca6a5f0 1218 {
94613352 1219 wxMessageBox(wxT("Unable to instantiate an instance of Ccontact"),wxT("Error..."),wxOK | wxICON_EXCLAMATION);
a4054ad1 1220 return FALSE;
3ca6a5f0
BP
1221 }
1222
1223 // Check if the table exists or not. If it doesn't, ask the user if they want to
1224 // create the table. Continue trying to create the table until it exists, or user aborts
ea24eeb2 1225 while (!wxGetApp().Contact->GetDb()->TableExists((wxChar *)CONTACT_TABLE_NAME,
049977d0
GT
1226 wxGetApp().DbConnectInf->GetUserID(),
1227 wxGetApp().DbConnectInf->GetDefaultDir()))
3ca6a5f0
BP
1228 {
1229 wxString tStr;
f21b2fd8
GT
1230 tStr.Printf(wxT("Unable to open the table '%s'. The table may\nneed to be created.\n\nDo you wish to try to create/clear the table?\n\n"),CONTACT_TABLE_NAME);
1231 bool createTable = (wxMessageBox(tStr.c_str(),wxT("Confirm"),wxYES_NO|wxICON_QUESTION) == wxYES);
3ca6a5f0
BP
1232
1233 if (!createTable)
1234 {
1235// Close();
a4054ad1 1236 return FALSE;
3ca6a5f0
BP
1237 }
1238 else
a4054ad1 1239 wxGetApp().CreateDataTable(FALSE);
3ca6a5f0
BP
1240 }
1241
1242 // Tables must be "opened" before anything other than creating/deleting table can be done
ea24eeb2 1243 if (!wxGetApp().Contact->Open())
3ca6a5f0
BP
1244 {
1245 // Table does exist, or there was some problem opening it. Currently this should
973f2539 1246 // never fail, except in the case of the table not exisiting or the current
3ca6a5f0 1247 // user has insufficent privileges to access the table
3fe813a9 1248#if 1
3ca6a5f0
BP
1249// This code is experimenting with a new function that will hopefully be available
1250// in the 2.4 release. This check will determine whether the open failing was due
1251// to the table not existing, or the users privileges being insufficient to
1252// open the table.
ea24eeb2
GT
1253 if (!wxGetApp().Contact->GetDb()->TablePrivileges(CONTACT_TABLE_NAME, wxT("SELECT"),
1254 wxGetApp().Contact->GetDb()->GetUsername(),
69a2b59d
GT
1255 wxGetApp().Contact->GetDb()->GetUsername(),
1256 wxGetApp().DbConnectInf->GetDefaultDir()))
3ca6a5f0
BP
1257 {
1258 wxString tStr;
3fe813a9 1259 tStr.Printf(wxT("Unable to open the table '%s' (likely due to\ninsufficient privileges of the logged in user).\n\n"),CONTACT_TABLE_NAME);
f21b2fd8
GT
1260
1261 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__FILE__,__LINE__),
1262 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
3ca6a5f0
BP
1263 }
1264 else
1265#endif
ea24eeb2
GT
1266 if (!wxGetApp().Contact->GetDb()->TableExists(CONTACT_TABLE_NAME,
1267 wxGetApp().Contact->GetDb()->GetUsername(),
3fe813a9 1268 wxGetApp().DbConnectInf->GetDefaultDir()))
3ca6a5f0
BP
1269 {
1270 wxString tStr;
3fe813a9 1271 tStr.Printf(wxT("Unable to open the table '%s' as the table\ndoes not appear to exist in the tablespace available\nto the currently logged in user.\n\n"),CONTACT_TABLE_NAME);
f21b2fd8
GT
1272 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__FILE__,__LINE__),
1273 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
3ca6a5f0
BP
1274 }
1275
a4054ad1 1276 return FALSE;
3ca6a5f0
BP
1277 }
1278
1279 // Build the dialog
1280
94613352
GT
1281 (void)new wxStaticBox(this, EDITOR_DIALOG_FN_GROUP, wxT(""), wxPoint(15, 1), wxSize(497, 69), 0, wxT("FunctionGrp"));
1282 (void)new wxStaticBox(this, EDITOR_DIALOG_SEARCH_GROUP, wxT(""), wxPoint(417, 1), wxSize(95, 242), 0, wxT("SearchGrp"));
1283
1284 pCreateBtn = new wxButton(this, EDITOR_DIALOG_CREATE, wxT("&Create"), wxPoint( 25, 21), wxSize( 70, 35), 0, wxDefaultValidator, wxT("CreateBtn"));
1285 pEditBtn = new wxButton(this, EDITOR_DIALOG_EDIT, wxT("&Edit"), wxPoint(102, 21), wxSize( 70, 35), 0, wxDefaultValidator, wxT("EditBtn"));
1286 pDeleteBtn = new wxButton(this, EDITOR_DIALOG_DELETE, wxT("&Delete"), wxPoint(179, 21), wxSize( 70, 35), 0, wxDefaultValidator, wxT("DeleteBtn"));
1287 pCopyBtn = new wxButton(this, EDITOR_DIALOG_COPY, wxT("Cop&y"), wxPoint(256, 21), wxSize( 70, 35), 0, wxDefaultValidator, wxT("CopyBtn"));
1288 pSaveBtn = new wxButton(this, EDITOR_DIALOG_SAVE, wxT("&Save"), wxPoint(333, 21), wxSize( 70, 35), 0, wxDefaultValidator, wxT("SaveBtn"));
1289 pCancelBtn = new wxButton(this, EDITOR_DIALOG_CANCEL, wxT("C&ancel"), wxPoint(430, 21), wxSize( 70, 35), 0, wxDefaultValidator, wxT("CancelBtn"));
1290 pPrevBtn = new wxButton(this, EDITOR_DIALOG_PREV, wxT("<< &Prev"), wxPoint(430, 81), wxSize( 70, 35), 0, wxDefaultValidator, wxT("PrevBtn"));
1291 pNextBtn = new wxButton(this, EDITOR_DIALOG_NEXT, wxT("&Next >>"), wxPoint(430, 121), wxSize( 70, 35), 0, wxDefaultValidator, wxT("NextBtn"));
1292 pQueryBtn = new wxButton(this, EDITOR_DIALOG_QUERY, wxT("&Query"), wxPoint(430, 161), wxSize( 70, 35), 0, wxDefaultValidator, wxT("QueryBtn"));
1293 pResetBtn = new wxButton(this, EDITOR_DIALOG_RESET, wxT("&Reset"), wxPoint(430, 200), wxSize( 70, 35), 0, wxDefaultValidator, wxT("ResetBtn"));
1294 pNameMsg = new wxStaticText(this, EDITOR_DIALOG_NAME_MSG, wxT("Name:"), wxPoint( 17, 80), wxSize( -1, -1), 0, wxT("NameMsg"));
1295 pNameTxt = new wxTextCtrl(this, EDITOR_DIALOG_NAME_TEXT, wxT(""), wxPoint( 17, 97), wxSize(308, 25), 0, wxDefaultValidator, wxT("NameTxt"));
1296 pNameListBtn = new wxButton(this, EDITOR_DIALOG_LOOKUP, wxT("&Lookup"), wxPoint(333, 97), wxSize( 70, 24), 0, wxDefaultValidator, wxT("LookupBtn"));
1297 pAddress1Msg = new wxStaticText(this, EDITOR_DIALOG_ADDRESS1_MSG, wxT("Address:"), wxPoint( 17, 130), wxSize( -1, -1), 0, wxT("Address1Msg"));
1298 pAddress1Txt = new wxTextCtrl(this, EDITOR_DIALOG_ADDRESS2_TEXT, wxT(""), wxPoint( 17, 147), wxSize(308, 25), 0, wxDefaultValidator, wxT("Address1Txt"));
1299 pAddress2Msg = new wxStaticText(this, EDITOR_DIALOG_ADDRESS2_MSG, wxT("Address:"), wxPoint( 17, 180), wxSize( -1, -1), 0, wxT("Address2Msg"));
1300 pAddress2Txt = new wxTextCtrl(this, EDITOR_DIALOG_ADDRESS2_TEXT, wxT(""), wxPoint( 17, 197), wxSize(308, 25), 0, wxDefaultValidator, wxT("Address2Txt"));
1301 pCityMsg = new wxStaticText(this, EDITOR_DIALOG_CITY_MSG, wxT("City:"), wxPoint( 17, 230), wxSize( -1, -1), 0, wxT("CityMsg"));
1302 pCityTxt = new wxTextCtrl(this, EDITOR_DIALOG_CITY_TEXT, wxT(""), wxPoint( 17, 247), wxSize(225, 25), 0, wxDefaultValidator, wxT("CityTxt"));
1303 pStateMsg = new wxStaticText(this, EDITOR_DIALOG_STATE_MSG, wxT("State:"), wxPoint(250, 230), wxSize( -1, -1), 0, wxT("StateMsg"));
1304 pStateTxt = new wxTextCtrl(this, EDITOR_DIALOG_STATE_TEXT, wxT(""), wxPoint(250, 247), wxSize(153, 25), 0, wxDefaultValidator, wxT("StateTxt"));
1305 pCountryMsg = new wxStaticText(this, EDITOR_DIALOG_COUNTRY_MSG, wxT("Country:"), wxPoint( 17, 280), wxSize( -1, -1), 0, wxT("CountryMsg"));
1306 pCountryTxt = new wxTextCtrl(this, EDITOR_DIALOG_COUNTRY_TEXT, wxT(""), wxPoint( 17, 297), wxSize(225, 25), 0, wxDefaultValidator, wxT("CountryTxt"));
1307 pPostalCodeMsg = new wxStaticText(this, EDITOR_DIALOG_POSTAL_MSG, wxT("Postal Code:"),wxPoint(250, 280), wxSize( -1, -1), 0, wxT("PostalCodeMsg"));
1308 pPostalCodeTxt = new wxTextCtrl(this, EDITOR_DIALOG_POSTAL_TEXT, wxT(""), wxPoint(250, 297), wxSize(153, 25), 0, wxDefaultValidator, wxT("PostalCodeTxt"));
3ca6a5f0
BP
1309
1310 wxString choice_strings[5];
94613352
GT
1311 choice_strings[0] = wxT("English");
1312 choice_strings[1] = wxT("French");
1313 choice_strings[2] = wxT("German");
1314 choice_strings[3] = wxT("Spanish");
1315 choice_strings[4] = wxT("Other");
3ca6a5f0 1316
94613352
GT
1317 pNativeLangChoice = new wxChoice(this, EDITOR_DIALOG_LANG_CHOICE, wxPoint( 17, 346), wxSize(277, -1), 5, choice_strings);
1318 pNativeLangMsg = new wxStaticText(this, EDITOR_DIALOG_LANG_MSG, wxT("Native language:"), wxPoint( 17, 330), wxSize( -1, -1), 0, wxT("NativeLangMsg"));
3ca6a5f0
BP
1319
1320 wxString radio_strings[2];
94613352
GT
1321 radio_strings[0] = wxT("No");
1322 radio_strings[1] = wxT("Yes");
1323 pDeveloperRadio = new wxRadioBox(this,EDITOR_DIALOG_DEVELOPER, wxT("Developer:"), wxPoint(303, 330), wxSize( -1, -1), 2, radio_strings, 2, wxHORIZONTAL);
1324 pJoinDateMsg = new wxStaticText(this, EDITOR_DIALOG_JOIN_MSG, wxT("Date joined:"), wxPoint( 17, 380), wxSize( -1, -1), 0, wxT("JoinDateMsg"));
1325 pJoinDateTxt = new wxTextCtrl(this, EDITOR_DIALOG_JOIN_TEXT, wxT(""), wxPoint( 17, 397), wxSize(150, 25), 0, wxDefaultValidator, wxT("JoinDateTxt"));
1326 pContribMsg = new wxStaticText(this, EDITOR_DIALOG_CONTRIB_MSG,wxT("Contributions:"), wxPoint(175, 380), wxSize( -1, -1), 0, wxT("ContribMsg"));
1327 pContribTxt = new wxTextCtrl(this, EDITOR_DIALOG_CONTRIB_TEXT, wxT(""), wxPoint(175, 397), wxSize(120, 25), 0, wxDefaultValidator, wxT("ContribTxt"));
1328 pLinesMsg = new wxStaticText(this, EDITOR_DIALOG_LINES_MSG, wxT("Lines of code:"), wxPoint(303, 380), wxSize( -1, -1), 0, wxT("LinesMsg"));
1329 pLinesTxt = new wxTextCtrl(this, EDITOR_DIALOG_LINES_TEXT, wxT(""), wxPoint(303, 397), wxSize(100, 25), 0, wxDefaultValidator, wxT("LinesTxt"));
3ca6a5f0 1330
69a2b59d 1331 pCatalogBtn = new wxButton(this, EDITOR_DIALOG_CATALOG, wxT("Catalo&g"), wxPoint(430, 287), wxSize( 70, 35), 0, wxDefaultValidator, wxT("CatalogBtn"));
3f030b48
GT
1332 pDataTypesBtn = new wxButton(this, EDITOR_DIALOG_DATATYPES, wxT("Data&types"), wxPoint(430, 337), wxSize( 70, 35), 0, wxDefaultValidator, wxT("DataTypesBtn"));
1333 pDbDiagsBtn = new wxButton(this, EDITOR_DIALOG_DB_DIAGS, wxT("DB Dia&gs"), wxPoint(430, 387), wxSize( 70, 35), 0, wxDefaultValidator, wxT("DbDiagsBtn"));
1334
3ca6a5f0
BP
1335 // Now that all the widgets on the panel are created, its safe to allow ::OnCommand() to
1336 // handle all widget processing
a4054ad1 1337 widgetPtrsSet = TRUE;
3ca6a5f0
BP
1338
1339 // Setup the orderBy and where clauses to return back a single record as the result set,
1340 // as there will only be one record being shown on the dialog at a time, this optimizes
1341 // network traffic by only returning a one row result
1342
ea24eeb2 1343 wxGetApp().Contact->SetOrderByClause(wxT("NAME")); // field name to sort by
3ca6a5f0
BP
1344
1345 // The wxString "whereStr" is not a member of the wxDbTable object, it is a member variable
1346 // specifically in the Ccontact class. It is used here for simpler construction of a varying
1347 // length string, and then after the string is built, the wxDbTable member variable "where" is
1348 // assigned the pointer to the constructed string.
1349 //
1350 // The constructed where clause below has a sub-query within it "SELECT MIN(NAME) FROM %s"
1351 // to achieve a single row (in this case the first name in alphabetical order).
1352
ea24eeb2
GT
1353 if (wxGetApp().Contact->GetDb()->Dbms() != dbmsPOSTGRES &&
1354 wxGetApp().Contact->GetDb()->Dbms() != dbmsMY_SQL)
3ca6a5f0 1355 {
ea24eeb2
GT
1356 wxGetApp().Contact->whereStr.Printf(wxT("NAME = (SELECT MIN(NAME) FROM %s)"),
1357 wxGetApp().Contact->GetTableName().c_str());
94613352 1358 // NOTE: (const wxChar*) returns a pointer which may not be valid later, so this is short term use only
ea24eeb2 1359 wxGetApp().Contact->SetWhereClause(wxGetApp().Contact->whereStr);
3ca6a5f0
BP
1360 }
1361 else
ea24eeb2 1362 wxGetApp().Contact->SetWhereClause(wxT(""));
3ca6a5f0
BP
1363
1364 // Perform the Query to get the result set.
a4054ad1
GT
1365 // NOTE: If there are no rows returned, that is a valid result, so Query() would return TRUE.
1366 // Only if there is a database error will Query() come back as FALSE
ea24eeb2 1367 if (!wxGetApp().Contact->Query())
3ca6a5f0
BP
1368 {
1369 wxString tStr;
f21b2fd8
GT
1370 tStr = wxT("ODBC error during Query()\n\n");
1371 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__FILE__,__LINE__),
1372 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
a4054ad1 1373 return FALSE;
3ca6a5f0
BP
1374 }
1375
1376 // Since Query succeeded, now get the row that was returned
ea24eeb2 1377 if (!wxGetApp().Contact->GetNext())
3ca6a5f0
BP
1378 // If the GetNext() failed at this point, then there are no rows to retrieve,
1379 // so clear the values in the members of "Contact" so that PutData() blanks the
1380 // widgets on the dialog
ea24eeb2
GT
1381 wxGetApp().Contact->Initialize();
1382/*
1383 wxGetApp().Contact->GetDb()->RollbackTrans();
1384*/
3ca6a5f0
BP
1385 SetMode(mView);
1386 PutData();
1387
a4054ad1 1388 Show(TRUE);
3ca6a5f0 1389
a4054ad1
GT
1390 initialized = TRUE;
1391 return TRUE;
3ca6a5f0
BP
1392} // CeditorDlg::Initialize()
1393
1394
108106cf
JS
1395void CeditorDlg::FieldsEditable()
1396{
3fe813a9
GT
1397 if (!widgetPtrsSet)
1398 return;
1399
e70e8f4c
GT
1400 pNameTxt->Enable((mode == mCreate) || (mode == mEdit));
1401 pAddress1Txt->Enable((mode == mCreate) || (mode == mEdit));
1402 pAddress2Txt->Enable((mode == mCreate) || (mode == mEdit));
1403 pCityTxt->Enable((mode == mCreate) || (mode == mEdit));
1404 pStateTxt->Enable((mode == mCreate) || (mode == mEdit));
1405 pPostalCodeTxt->Enable((mode == mCreate) || (mode == mEdit));
1406 pCountryTxt->Enable((mode == mCreate) || (mode == mEdit));
1407
1408 pJoinDateTxt->Enable((mode == mCreate) || (mode == mEdit));
1409 pContribTxt->Enable((mode == mCreate) || (mode == mEdit));
1410 pLinesTxt->Enable((mode == mCreate) || (mode == mEdit));
1411 pNativeLangChoice->Enable((mode == mCreate) || (mode == mEdit));
1412 pDeveloperRadio->Enable((mode == mCreate) || (mode == mEdit));
108106cf
JS
1413
1414} // CeditorDlg::FieldsEditable()
1415
1416
1417void CeditorDlg::SetMode(enum DialogModes m)
1418{
a4054ad1 1419 bool edit = FALSE;
e70e8f4c
GT
1420
1421 mode = m;
1422 switch (mode)
1423 {
1424 case mCreate:
1425 case mEdit:
a4054ad1 1426 edit = TRUE;
e70e8f4c
GT
1427 break;
1428 case mView:
1429 case mSearch:
a4054ad1 1430 edit = FALSE;
e70e8f4c
GT
1431 break;
1432 default:
1433 break;
1434 };
1435
1436 if (widgetPtrsSet)
1437 {
1438 pCreateBtn->Enable( !edit );
ea24eeb2
GT
1439 pEditBtn->Enable( !edit && (wxStrcmp(wxGetApp().Contact->Name,wxT(""))!=0) );
1440 pDeleteBtn->Enable( !edit && (wxStrcmp(wxGetApp().Contact->Name,wxT(""))!=0) );
1441 pCopyBtn->Enable( !edit && (wxStrcmp(wxGetApp().Contact->Name,wxT(""))!=0) );
e70e8f4c
GT
1442 pSaveBtn->Enable( edit );
1443 pCancelBtn->Enable( edit );
1444 pPrevBtn->Enable( !edit );
1445 pNextBtn->Enable( !edit );
1446 pQueryBtn->Enable( !edit );
ea24eeb2 1447 pResetBtn->Enable( !edit && !wxGetApp().Contact->qryWhereStr.IsEmpty() );
e70e8f4c
GT
1448 pNameListBtn->Enable( !edit );
1449 }
1450
1451 FieldsEditable();
108106cf
JS
1452} // CeditorDlg::SetMode()
1453
1454
1fc5dd6f 1455bool CeditorDlg::PutData()
108106cf 1456{
e70e8f4c 1457 wxString tStr;
108106cf 1458
ea24eeb2
GT
1459 pNameTxt->SetValue(wxGetApp().Contact->Name);
1460 pAddress1Txt->SetValue(wxGetApp().Contact->Addr1);
1461 pAddress2Txt->SetValue(wxGetApp().Contact->Addr2);
1462 pCityTxt->SetValue(wxGetApp().Contact->City);
1463 pStateTxt->SetValue(wxGetApp().Contact->State);
1464 pCountryTxt->SetValue(wxGetApp().Contact->Country);
1465 pPostalCodeTxt->SetValue(wxGetApp().Contact->PostalCode);
108106cf 1466
ea24eeb2 1467 tStr.Printf(wxT("%d/%d/%d"),wxGetApp().Contact->JoinDate.month,wxGetApp().Contact->JoinDate.day,wxGetApp().Contact->JoinDate.year);
e70e8f4c 1468 pJoinDateTxt->SetValue(tStr);
108106cf 1469
ea24eeb2 1470 tStr.Printf(wxT("%d"),wxGetApp().Contact->Contributions);
e70e8f4c 1471 pContribTxt->SetValue(tStr);
108106cf 1472
ea24eeb2 1473 tStr.Printf(wxT("%lu"),wxGetApp().Contact->LinesOfCode);
e70e8f4c 1474 pLinesTxt->SetValue(tStr);
108106cf 1475
ea24eeb2 1476 pNativeLangChoice->SetSelection(wxGetApp().Contact->NativeLanguage);
108106cf 1477
ea24eeb2 1478 pDeveloperRadio->SetSelection(wxGetApp().Contact->IsDeveloper);
108106cf 1479
a4054ad1 1480 return TRUE;
108106cf
JS
1481} // Ceditor::PutData()
1482
1483
1484/*
1485 * Reads the data out of all the widgets on the dialog. Some data evaluation is done
1486 * to ensure that there is a name entered and that the date field is valid.
1487 *
a4054ad1 1488 * A return value of TRUE means that valid data was retrieved from the dialog, otherwise
108106cf
JS
1489 * invalid data was found (and a message was displayed telling the user what to fix), and
1490 * the data was not placed into the appropraite fields of Ccontact
1491 */
1fc5dd6f 1492bool CeditorDlg::GetData()
108106cf 1493{
e70e8f4c
GT
1494 // Validate that the data currently entered into the widgets is valid data
1495
1496 wxString tStr;
1497 tStr = pNameTxt->GetValue();
94613352 1498 if (!wxStrcmp((const wxChar*) tStr,wxT("")))
e70e8f4c 1499 {
94613352 1500 wxMessageBox(wxT("A name is required for entry into the contact table"),wxT("Notice..."),wxOK | wxICON_INFORMATION);
a4054ad1 1501 return FALSE;
e70e8f4c
GT
1502 }
1503
a4054ad1 1504 bool invalid = FALSE;
f369dd4f 1505 int mm = 1,dd = 1,yyyy = 2001;
e70e8f4c
GT
1506 int first, second;
1507
1508 tStr = pJoinDateTxt->GetValue();
94613352 1509 if (tStr.Freq(wxT('/')) != 2)
a4054ad1 1510 invalid = TRUE;
e70e8f4c
GT
1511
1512 // Find the month, day, and year tokens
1513 if (!invalid)
1514 {
94613352
GT
1515 first = tStr.First(wxT('/'));
1516 second = tStr.Last(wxT('/'));
e70e8f4c
GT
1517
1518 mm = atoi(tStr.SubString(0,first));
1519 dd = atoi(tStr.SubString(first+1,second));
1520 yyyy = atoi(tStr.SubString(second+1,tStr.Length()-1));
1521
1522 invalid = !(mm && dd && yyyy);
1523 }
1524
1525 // Force Year 2000 compliance
1526 if (!invalid && (yyyy < 1000))
a4054ad1 1527 invalid = TRUE;
e70e8f4c
GT
1528
1529 // Check the token ranges for validity
1530 if (!invalid)
1531 {
1532 if (yyyy > 9999)
a4054ad1 1533 invalid = TRUE;
e70e8f4c 1534 else if ((mm < 1) || (mm > 12))
a4054ad1 1535 invalid = TRUE;
e70e8f4c
GT
1536 else
1537 {
1538 if (dd < 1)
a4054ad1 1539 invalid = TRUE;
e70e8f4c
GT
1540 else
1541 {
1542 int days[12] = {31,28,31,30,31,30,
1543 31,31,30,31,30,31};
1544 if (dd > days[mm-1])
1545 {
a4054ad1 1546 invalid = TRUE;
e70e8f4c
GT
1547 if ((dd == 29) && (mm == 2))
1548 {
1549 if (((yyyy % 4) == 0) && (((yyyy % 100) != 0) || ((yyyy % 400) == 0)))
a4054ad1 1550 invalid = FALSE;
e70e8f4c
GT
1551 }
1552 }
1553 }
1554 }
1555 }
1556
1557 if (!invalid)
1558 {
ea24eeb2
GT
1559 wxGetApp().Contact->JoinDate.month = mm;
1560 wxGetApp().Contact->JoinDate.day = dd;
1561 wxGetApp().Contact->JoinDate.year = yyyy;
e70e8f4c
GT
1562 }
1563 else
1564 {
94613352 1565 wxMessageBox(wxT("Improper date format. Please check the date\nspecified and try again.\n\nNOTE: Dates are in american format (MM/DD/YYYY)"),wxT("Notice..."),wxOK | wxICON_INFORMATION);
a4054ad1 1566 return FALSE;
e70e8f4c
GT
1567 }
1568
1569 tStr = pNameTxt->GetValue();
ea24eeb2
GT
1570 wxStrcpy(wxGetApp().Contact->Name,(const wxChar*) tStr);
1571 wxStrcpy(wxGetApp().Contact->Addr1,pAddress1Txt->GetValue());
1572 wxStrcpy(wxGetApp().Contact->Addr2,pAddress2Txt->GetValue());
1573 wxStrcpy(wxGetApp().Contact->City,pCityTxt->GetValue());
1574 wxStrcpy(wxGetApp().Contact->State,pStateTxt->GetValue());
1575 wxStrcpy(wxGetApp().Contact->Country,pCountryTxt->GetValue());
1576 wxStrcpy(wxGetApp().Contact->PostalCode,pPostalCodeTxt->GetValue());
e70e8f4c 1577
ea24eeb2
GT
1578 wxGetApp().Contact->Contributions = atoi(pContribTxt->GetValue());
1579 wxGetApp().Contact->LinesOfCode = atol(pLinesTxt->GetValue());
e70e8f4c 1580
ea24eeb2
GT
1581 wxGetApp().Contact->NativeLanguage = (enum Language) pNativeLangChoice->GetSelection();
1582 wxGetApp().Contact->IsDeveloper = pDeveloperRadio->GetSelection() > 0;
e70e8f4c 1583
a4054ad1 1584 return TRUE;
108106cf
JS
1585} // CeditorDlg::GetData()
1586
1587
1588/*
1589 * Retrieve data from the dialog, verify the validity of the data, and if it is valid,
1590 * try to insert/update the data to the table based on the current 'mode' the dialog
1591 * is set to.
1592 *
a4054ad1
GT
1593 * A return value of TRUE means the insert/update was completed successfully, a return
1594 * value of FALSE means that Save() failed. If returning FALSE, then this function
108106cf
JS
1595 * has displayed a detailed error message for the user.
1596 */
1fc5dd6f 1597bool CeditorDlg::Save()
108106cf 1598{
a4054ad1 1599 bool failed = FALSE;
e70e8f4c
GT
1600
1601 // Read the data in the widgets of the dialog to get the user's data
1602 if (!GetData())
a4054ad1 1603 failed = TRUE;
e70e8f4c
GT
1604
1605 // Perform any other required validations necessary before saving
1606 if (!failed)
1607 {
1608 wxBeginBusyCursor();
1609
1610 if (mode == mCreate)
1611 {
ea24eeb2 1612 RETCODE result = wxGetApp().Contact->Insert();
e70e8f4c
GT
1613
1614 failed = (result != DB_SUCCESS);
1615 if (failed)
1616 {
1617 // Some errors may be expected, like a duplicate key, so handle those instances with
1618 // specific error messages.
1619 if (result == DB_ERR_INTEGRITY_CONSTRAINT_VIOL)
1620 {
1621 wxString tStr;
f21b2fd8
GT
1622 tStr = wxT("A duplicate key value already exists in the table.\nUnable to save record\n\n");
1623 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__FILE__,__LINE__),
1624 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
e70e8f4c
GT
1625 }
1626 else
1627 {
5d59e67a 1628 // Some other unexpected error occurred
e70e8f4c 1629 wxString tStr;
f21b2fd8
GT
1630 tStr = wxT("Database insert failed\n\n");
1631 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__FILE__,__LINE__),
1632 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
e70e8f4c
GT
1633 }
1634 }
1635 }
1636 else // mode == mEdit
1637 {
5d59e67a 1638 wxGetApp().Contact->GetDb()->RollbackTrans();
ea24eeb2
GT
1639 wxGetApp().Contact->whereStr.Printf("NAME = '%s'",saveName.c_str());
1640 if (!wxGetApp().Contact->UpdateWhere(wxGetApp().Contact->whereStr))
e70e8f4c
GT
1641 {
1642 wxString tStr;
f21b2fd8
GT
1643 tStr = wxT("Database update failed\n\n");
1644 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__FILE__,__LINE__),
1645 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
a4054ad1 1646 failed = TRUE;
e70e8f4c
GT
1647 }
1648 }
1649
1650 if (!failed)
1651 {
ea24eeb2 1652 wxGetApp().Contact->GetDb()->CommitTrans();
e70e8f4c
GT
1653 SetMode(mView); // Sets the dialog mode back to viewing after save is successful
1654 }
1655 else
ea24eeb2 1656 wxGetApp().Contact->GetDb()->RollbackTrans();
e70e8f4c
GT
1657
1658 wxEndBusyCursor();
1659 }
1660
1661 return !failed;
108106cf
JS
1662} // CeditorDlg::Save()
1663
1664
1665/*
1666 * Where this program is only showing a single row at a time in the dialog,
1667 * a special where clause must be built to find just the single row which,
1668 * in sequence, would follow the currently displayed row.
1669 */
1fc5dd6f 1670bool CeditorDlg::GetNextRec()
108106cf 1671{
e70e8f4c
GT
1672 wxString w;
1673
ea24eeb2
GT
1674 if (wxGetApp().Contact->GetDb()->Dbms() != dbmsPOSTGRES &&
1675 wxGetApp().Contact->GetDb()->Dbms() != dbmsMY_SQL)
e70e8f4c 1676 {
94613352 1677 w = wxT("NAME = (SELECT MIN(NAME) FROM ");
ea24eeb2 1678 w += wxGetApp().Contact->GetTableName();
94613352 1679 w += wxT(" WHERE NAME > '");
e70e8f4c
GT
1680 }
1681 else
94613352 1682 w = wxT("(NAME > '");
e70e8f4c 1683
ea24eeb2 1684 w += wxGetApp().Contact->Name;
94613352 1685 w += wxT("'");
e70e8f4c
GT
1686
1687 // If a query where string is currently set, append that criteria
ea24eeb2 1688 if (!wxGetApp().Contact->qryWhereStr.IsEmpty())
e70e8f4c 1689 {
94613352 1690 w += wxT(" AND (");
ea24eeb2 1691 w += wxGetApp().Contact->qryWhereStr;
94613352 1692 w += wxT(")");
e70e8f4c
GT
1693 }
1694
94613352 1695 w += wxT(")");
049977d0 1696 return(GetRec(w));
108106cf
JS
1697
1698} // CeditorDlg::GetNextRec()
1699
1700
1701/*
1702 * Where this program is only showing a single row at a time in the dialog,
1703 * a special where clause must be built to find just the single row which,
1704 * in sequence, would precede the currently displayed row.
1705 */
1fc5dd6f 1706bool CeditorDlg::GetPrevRec()
108106cf 1707{
e70e8f4c 1708 wxString w;
108106cf 1709
ea24eeb2
GT
1710 if (wxGetApp().Contact->GetDb()->Dbms() != dbmsPOSTGRES &&
1711 wxGetApp().Contact->GetDb()->Dbms() != dbmsMY_SQL)
e70e8f4c 1712 {
94613352 1713 w = wxT("NAME = (SELECT MAX(NAME) FROM ");
ea24eeb2 1714 w += wxGetApp().Contact->GetTableName();
94613352 1715 w += wxT(" WHERE NAME < '");
e70e8f4c
GT
1716 }
1717 else
94613352 1718 w = wxT("(NAME < '");
65d7ddc4 1719
ea24eeb2 1720 w += wxGetApp().Contact->Name;
94613352 1721 w += wxT("'");
108106cf 1722
e70e8f4c 1723 // If a query where string is currently set, append that criteria
ea24eeb2 1724 if (!wxGetApp().Contact->qryWhereStr.IsEmpty())
e70e8f4c 1725 {
94613352 1726 w += wxT(" AND (");
ea24eeb2 1727 w += wxGetApp().Contact->qryWhereStr;
94613352 1728 w += wxT(")");
e70e8f4c 1729 }
108106cf 1730
94613352 1731 w += wxT(")");
108106cf 1732
049977d0 1733 return(GetRec(w));
108106cf
JS
1734
1735} // CeditorDlg::GetPrevRec()
1736
1737
1738/*
1739 * This function is here to avoid duplicating this same code in both the
1740 * GetPrevRec() and GetNextRec() functions
1741 */
049977d0 1742bool CeditorDlg::GetRec(const wxString &whereStr)
108106cf 1743{
ea24eeb2
GT
1744 wxGetApp().Contact->SetWhereClause(whereStr);
1745 wxGetApp().Contact->SetOrderByClause(wxT("NAME"));
e70e8f4c 1746
ea24eeb2 1747 if (!wxGetApp().Contact->Query())
e70e8f4c
GT
1748 {
1749 wxString tStr;
f21b2fd8
GT
1750 tStr = wxT("ODBC error during Query()\n\n");
1751 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__FILE__,__LINE__),
1752 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
e70e8f4c 1753
a4054ad1 1754 return(FALSE);
e70e8f4c
GT
1755 }
1756
ea24eeb2 1757 if (wxGetApp().Contact->GetNext())
e70e8f4c
GT
1758 {
1759 PutData();
a4054ad1 1760 return(TRUE);
e70e8f4c
GT
1761 }
1762 else
a4054ad1 1763 return(FALSE);
108106cf
JS
1764} // CeditorDlg::GetRec()
1765
1766
1767
1768/*
1769 * CparameterDlg constructor
1770 */
e3065973
JS
1771
1772BEGIN_EVENT_TABLE(CparameterDlg, wxDialog)
65d7ddc4
GT
1773 EVT_BUTTON(PARAMETER_DIALOG_SAVE, CparameterDlg::OnButton)
1774 EVT_BUTTON(PARAMETER_DIALOG_CANCEL, CparameterDlg::OnButton)
e3065973
JS
1775 EVT_CLOSE(CparameterDlg::OnCloseWindow)
1776END_EVENT_TABLE()
1777
94613352 1778CparameterDlg::CparameterDlg(wxWindow *parent) : wxDialog (parent, PARAMETER_DIALOG, wxT("ODBC parameter settings"), wxPoint(-1, -1), wxSize(400, 325))
108106cf 1779{
e70e8f4c
GT
1780 // Since the ::OnCommand() function is overridden, this prevents the widget
1781 // detection in ::OnCommand() until all widgets have been initialized to prevent
1782 // uninitialized pointers from crashing the program
a4054ad1 1783 widgetPtrsSet = FALSE;
e70e8f4c 1784
94613352
GT
1785 pParamODBCSourceMsg = new wxStaticText(this, PARAMETER_DIALOG_SOURCE_MSG, wxT("ODBC data sources:"), wxPoint( 10, 10), wxSize( -1, -1), 0, wxT("ParamODBCSourceMsg"));
1786 pParamODBCSourceList = new wxListBox(this, PARAMETER_DIALOG_SOURCE_LISTBOX, wxPoint( 10, 29), wxSize(285, 150), 0, 0, wxLB_SINGLE|wxLB_ALWAYS_SB, wxDefaultValidator, wxT("ParamODBCSourceList"));
1787 pParamUserNameMsg = new wxStaticText(this, PARAMETER_DIALOG_NAME_MSG, wxT("Database user name:"), wxPoint( 10, 193), wxSize( -1, -1), 0, wxT("ParamUserNameMsg"));
1788 pParamUserNameTxt = new wxTextCtrl(this, PARAMETER_DIALOG_NAME_TEXT, wxT(""), wxPoint(10, 209), wxSize( 140, 25), 0, wxDefaultValidator, wxT("ParamUserNameTxt"));
1789 pParamPasswordMsg = new wxStaticText(this, PARAMETER_DIALOG_PASSWORD_MSG, wxT("Password:"), wxPoint(156, 193), wxSize( -1, -1), 0, wxT("ParamPasswordMsg"));
1790 pParamPasswordTxt = new wxTextCtrl(this, PARAMETER_DIALOG_PASSWORD_TEXT, wxT(""), wxPoint(156, 209), wxSize( 140, 25), 0, wxDefaultValidator, wxT("ParamPasswordTxt"));
1791 pParamDirPathMsg = new wxStaticText(this, PARAMETER_DIALOG_DIRPATH_MSG, wxT("Directory:"), wxPoint( 10, 243), wxSize( -1, -1), 0, wxT("ParamDirPathMsg"));
1792 pParamDirPathTxt = new wxTextCtrl(this, PARAMETER_DIALOG_DIRPATH_TEXT, wxT(""), wxPoint( 10, 259), wxSize(140, 25), 0, wxDefaultValidator, wxT("ParamDirPathTxt"));
1793 pParamSaveBtn = new wxButton(this, PARAMETER_DIALOG_SAVE, wxT("&Save"), wxPoint(310, 21), wxSize( 70, 35), 0, wxDefaultValidator, wxT("ParamSaveBtn"));
1794 pParamCancelBtn = new wxButton(this, PARAMETER_DIALOG_CANCEL, wxT("C&ancel"), wxPoint(310, 66), wxSize( 70, 35), 0, wxDefaultValidator, wxT("ParamCancelBtn"));
e70e8f4c
GT
1795
1796 // Now that all the widgets on the panel are created, its safe to allow ::OnCommand() to
1797 // handle all widget processing
a4054ad1 1798 widgetPtrsSet = TRUE;
e70e8f4c 1799
a4054ad1 1800 saved = FALSE;
e70e8f4c
GT
1801 savedParamSettings = wxGetApp().params;
1802
1803 Centre(wxBOTH);
1804 PutData();
1805 ShowModal();
108106cf
JS
1806} // CparameterDlg constructor
1807
1808
e3065973 1809void CparameterDlg::OnCloseWindow(wxCloseEvent& event)
108106cf 1810{
e70e8f4c
GT
1811 // Put any additional checking necessary to make certain it is alright
1812 // to close the program here that is not done elsewhere
1813 if (!saved)
1814 {
94613352 1815 bool Ok = (wxMessageBox(wxT("No changes have been saved.\n\nAre you sure you wish exit the parameter screen?"),wxT("Confirm"),wxYES_NO|wxICON_QUESTION) == wxYES);
3ca6a5f0 1816
e70e8f4c 1817 if (!Ok)
e3065973
JS
1818 {
1819 event.Veto();
e70e8f4c 1820 return;
e3065973 1821 }
3ca6a5f0 1822
e70e8f4c
GT
1823 wxGetApp().params = savedParamSettings;
1824 }
108106cf 1825
e70e8f4c
GT
1826 if (GetParent() != NULL)
1827 GetParent()->SetFocus();
e3065973 1828
3ca6a5f0
BP
1829 while (wxIsBusy())
1830 wxEndBusyCursor();
1831
a4054ad1 1832 Show(FALSE);
3ca6a5f0
BP
1833 SetReturnCode(0); // added so BoundsChecker would not report use of uninitialized variable
1834
1835 this->Destroy();
1836} // CparameterDlg::OnCloseWindow()
108106cf
JS
1837
1838
65d7ddc4
GT
1839void CparameterDlg::OnButton( wxCommandEvent &event )
1840{
e70e8f4c
GT
1841 wxWindow *win = (wxWindow*) event.GetEventObject();
1842 OnCommand( *win, event );
65d7ddc4
GT
1843}
1844
3ca6a5f0 1845
108106cf
JS
1846void CparameterDlg::OnCommand(wxWindow& win, wxCommandEvent& event)
1847{
e70e8f4c
GT
1848 wxString widgetName;
1849
1850 widgetName = win.GetName();
1851
1852 if (!widgetPtrsSet)
1853 return;
1854
1855 if (widgetName == pParamSaveBtn->GetName())
1856 {
1857 if (Save())
1858 {
1859 wxString tStr;
94613352 1860 tStr = wxT("Database parameters have been saved.");
e70e8f4c 1861 if (GetParent() != NULL) // The parameter dialog was not called during startup due to a missing cfg file
94613352
GT
1862 tStr += wxT("\nNew parameters will take effect the next time the program is started.");
1863 wxMessageBox(tStr,wxT("Notice..."),wxOK | wxICON_INFORMATION);
a4054ad1 1864 saved = TRUE;
e70e8f4c
GT
1865 Close();
1866 }
1867 return;
1868 }
1869
1870 if (widgetName == pParamCancelBtn->GetName())
1871 {
1872 Close();
1873 return;
1874 }
108106cf
JS
1875} // CparameterDlg::OnCommand()
1876
1877
1fc5dd6f 1878bool CparameterDlg::PutData()
108106cf 1879{
e70e8f4c
GT
1880 // Fill the data source list box
1881 FillDataSourceList();
1882
1883 // Fill in the fields from the params object
1884 if (wxGetApp().params.ODBCSource && wxStrlen(wxGetApp().params.ODBCSource))
f369dd4f
GT
1885 {
1886 int index = pParamODBCSourceList->FindString(wxGetApp().params.ODBCSource);
1887 if (index != -1)
1888 pParamODBCSourceList->SetSelection(index);
1889 }
e70e8f4c
GT
1890 pParamUserNameTxt->SetValue(wxGetApp().params.UserName);
1891 pParamPasswordTxt->SetValue(wxGetApp().params.Password);
1892 pParamDirPathTxt->SetValue(wxGetApp().params.DirPath);
a4054ad1 1893 return TRUE;
108106cf
JS
1894} // CparameterDlg::PutData()
1895
1896
1fc5dd6f 1897bool CparameterDlg::GetData()
108106cf 1898{
e70e8f4c 1899 wxString tStr;
94613352 1900 if (pParamODBCSourceList->GetStringSelection() != wxT(""))
e70e8f4c
GT
1901 {
1902 tStr = pParamODBCSourceList->GetStringSelection();
1903 if (tStr.Length() > (sizeof(wxGetApp().params.ODBCSource)-1))
1904 {
1905 wxString errmsg;
94613352
GT
1906 errmsg.Printf(wxT("ODBC Data source name is longer than the data structure to hold it.\n'Cparameter.ODBCSource' must have a larger character array\nto handle a data source with this long of a name\n\nThe data source currently selected is %d characters long."),tStr.Length());
1907 wxMessageBox(errmsg,wxT("Internal program error..."),wxOK | wxICON_EXCLAMATION);
a4054ad1 1908 return FALSE;
e70e8f4c 1909 }
f6bcfd97 1910 wxStrcpy(wxGetApp().params.ODBCSource, tStr);
e70e8f4c
GT
1911 }
1912 else
a4054ad1 1913 return FALSE;
e70e8f4c
GT
1914
1915 tStr = pParamUserNameTxt->GetValue();
1916 if (tStr.Length() > (sizeof(wxGetApp().params.UserName)-1))
1917 {
1918 wxString errmsg;
94613352
GT
1919 errmsg.Printf(wxT("User name is longer than the data structure to hold it.\n'Cparameter.UserName' must have a larger character array\nto handle a data source with this long of a name\n\nThe user name currently specified is %d characters long."),tStr.Length());
1920 wxMessageBox(errmsg,wxT("Internal program error..."),wxOK | wxICON_EXCLAMATION);
a4054ad1 1921 return FALSE;
e70e8f4c 1922 }
f6bcfd97 1923 wxStrcpy(wxGetApp().params.UserName, tStr);
e70e8f4c
GT
1924
1925 tStr = pParamPasswordTxt->GetValue();
1926 if (tStr.Length() > (sizeof(wxGetApp().params.Password)-1))
1927 {
1928 wxString errmsg;
94613352
GT
1929 errmsg.Printf(wxT("Password is longer than the data structure to hold it.\n'Cparameter.Password' must have a larger character array\nto handle a data source with this long of a name\n\nThe password currently specified is %d characters long."),tStr.Length());
1930 wxMessageBox(errmsg,wxT("Internal program error..."),wxOK | wxICON_EXCLAMATION);
a4054ad1 1931 return FALSE;
e70e8f4c 1932 }
f6bcfd97 1933 wxStrcpy(wxGetApp().params.Password,tStr);
e70e8f4c
GT
1934
1935 tStr = pParamDirPathTxt->GetValue();
94613352 1936 tStr.Replace(wxT("\\"),wxT("/"));
e70e8f4c
GT
1937 if (tStr.Length() > (sizeof(wxGetApp().params.DirPath)-1))
1938 {
1939 wxString errmsg;
94613352
GT
1940 errmsg.Printf(wxT("DirPath is longer than the data structure to hold it.\n'Cparameter.DirPath' must have a larger character array\nto handle a data source with this long of a name\n\nThe password currently specified is %d characters long."),tStr.Length());
1941 wxMessageBox(errmsg,wxT("Internal program error..."),wxOK | wxICON_EXCLAMATION);
a4054ad1 1942 return FALSE;
e70e8f4c 1943 }
f6bcfd97 1944 wxStrcpy(wxGetApp().params.DirPath,tStr);
a4054ad1 1945 return TRUE;
108106cf
JS
1946} // CparameterDlg::GetData()
1947
1948
1fc5dd6f 1949bool CparameterDlg::Save()
108106cf 1950{
049977d0
GT
1951 // Copy the current params in case user cancels changing
1952 // the params, so that we can reset them.
e70e8f4c
GT
1953 if (!GetData())
1954 {
049977d0 1955 wxGetApp().params = savedParamSettings;
a4054ad1 1956 return FALSE;
e70e8f4c
GT
1957 }
1958
049977d0 1959 wxGetApp().WriteParamFile(wxGetApp().params);
e70e8f4c 1960
a4054ad1 1961 return TRUE;
108106cf
JS
1962} // CparameterDlg::Save()
1963
1964
1965void CparameterDlg::FillDataSourceList()
1966{
94613352
GT
1967 wxChar Dsn[SQL_MAX_DSN_LENGTH + 1];
1968 wxChar DsDesc[255];
e70e8f4c 1969 wxStringList strList;
108106cf 1970
049977d0
GT
1971 while (wxDbGetDataSource(wxGetApp().DbConnectInf->GetHenv(), Dsn,
1972 SQL_MAX_DSN_LENGTH+1, DsDesc, 255))
e70e8f4c 1973 strList.Add(Dsn);
108106cf 1974
e70e8f4c 1975 strList.Sort();
94613352
GT
1976 strList.Add(wxT(""));
1977 wxChar **p = strList.ListToArray();
108106cf 1978
e70e8f4c 1979 int i;
f6bcfd97 1980 for (i = 0; wxStrlen(p[i]); i++)
e70e8f4c 1981 pParamODBCSourceList->Append(p[i]);
3ca6a5f0 1982
ea24eeb2 1983 wxDELETEA(p);
3fe813a9 1984} // CparameterDlg::FillDataSourceList()
108106cf
JS
1985
1986
f6fcbb63
RR
1987BEGIN_EVENT_TABLE(CqueryDlg, wxDialog)
1988 EVT_BUTTON(-1, CqueryDlg::OnButton)
e3065973 1989 EVT_CLOSE(CqueryDlg::OnCloseWindow)
f6fcbb63 1990END_EVENT_TABLE()
3ca6a5f0 1991
f6fcbb63 1992
108106cf 1993// CqueryDlg() constructor
d3358961
GT
1994CqueryDlg::CqueryDlg(wxWindow *parent, wxDb *pDb, wxChar *tblName[],
1995 const wxString &pWhereArg) :
1996 wxDialog (parent, QUERY_DIALOG, wxT("Query"), wxPoint(-1, -1), wxSize(480, 360))
108106cf 1997{
e70e8f4c
GT
1998 wxBeginBusyCursor();
1999
2000 colInf = 0;
2001 dbTable = 0;
2002 masterTableName = tblName[0];
a4054ad1 2003 widgetPtrsSet = FALSE;
e70e8f4c
GT
2004 pDB = pDb;
2005
2006 // Initialize the WHERE clause from the string passed in
d3358961
GT
2007 pWhere = pWhereArg; // Save a pointer to the output buffer
2008 if (pWhere.Length() > (unsigned int)DB_MAX_WHERE_CLAUSE_LEN) // Check the length of the buffer passed in
e70e8f4c
GT
2009 {
2010 wxString s;
94613352
GT
2011 s.Printf(wxT("Maximum where clause length exceeded.\nLength must be less than %d"), DB_MAX_WHERE_CLAUSE_LEN+1);
2012 wxMessageBox(s,wxT("Error..."),wxOK | wxICON_EXCLAMATION);
e70e8f4c
GT
2013 Close();
2014 return;
2015 }
2016
94613352
GT
2017 pQueryCol1Msg = new wxStaticText(this, QUERY_DIALOG_COL_MSG, wxT("Column 1:"), wxPoint( 10, 10), wxSize( 69, 16), 0, wxT("QueryCol1Msg"));
2018 pQueryCol1Choice = new wxChoice(this, QUERY_DIALOG_COL_CHOICE, wxPoint( 10, 27), wxSize(250, 27), 0, 0, 0, wxDefaultValidator, wxT("QueryCol1Choice"));
2019 pQueryNotMsg = new wxStaticText(this, QUERY_DIALOG_NOT_MSG, wxT("NOT"), wxPoint(268, 10), wxSize( -1, -1), 0, wxT("QueryNotMsg"));
2020 pQueryNotCheck = new wxCheckBox(this, QUERY_DIALOG_NOT_CHECKBOX, wxT(""), wxPoint(275, 37), wxSize( 20, 20), 0, wxDefaultValidator, wxT("QueryNotCheck"));
e70e8f4c
GT
2021
2022 wxString choice_strings[9];
94613352
GT
2023 choice_strings[0] = wxT("=");
2024 choice_strings[1] = wxT("<");
2025 choice_strings[2] = wxT(">");
2026 choice_strings[3] = wxT("<=");
2027 choice_strings[4] = wxT(">=");
2028 choice_strings[5] = wxT("Begins");
2029 choice_strings[6] = wxT("Contains");
2030 choice_strings[7] = wxT("Like");
2031 choice_strings[8] = wxT("Between");
2032
2033 pQueryOperatorMsg = new wxStaticText(this, QUERY_DIALOG_OP_MSG, wxT("Operator:"), wxPoint(305, 10), wxSize( -1, -1), 0, wxT("QueryOperatorMsg"));
2034 pQueryOperatorChoice = new wxChoice(this, QUERY_DIALOG_OP_CHOICE, wxPoint(305, 27), wxSize( 80, 27), 9, choice_strings, 0, wxDefaultValidator, wxT("QueryOperatorChoice"));
2035 pQueryCol2Msg = new wxStaticText(this, QUERY_DIALOG_COL2_MSG, wxT("Column 2:"), wxPoint( 10, 65), wxSize( 69, 16), 0, wxT("QueryCol2Msg"));
2036 pQueryCol2Choice = new wxChoice(this, QUERY_DIALOG_COL2_CHOICE, wxPoint( 10, 82), wxSize(250, 27), 0, 0, 0, wxDefaultValidator, wxT("QueryCol2Choice"));
2037 pQuerySqlWhereMsg = new wxStaticText(this, QUERY_DIALOG_WHERE_MSG, wxT("SQL where clause:"), wxPoint( 10, 141), wxSize( -1, -1), 0, wxT("QuerySqlWhereMsg"));
2038 pQuerySqlWhereMtxt = new wxTextCtrl(this, QUERY_DIALOG_WHERE_TEXT, wxT(""), wxPoint( 10, 159), wxSize(377, 134), wxTE_MULTILINE, wxDefaultValidator, wxT("QuerySqlWhereMtxt"));
2039 pQueryAddBtn = new wxButton(this, QUERY_DIALOG_ADD, wxT("&Add"), wxPoint(406, 24), wxSize( 56, 26), 0, wxDefaultValidator, wxT("QueryAddBtn"));
2040 pQueryAndBtn = new wxButton(this, QUERY_DIALOG_AND, wxT("A&nd"), wxPoint(406, 58), wxSize( 56, 26), 0, wxDefaultValidator, wxT("QueryAndBtn"));
2041 pQueryOrBtn = new wxButton(this, QUERY_DIALOG_OR, wxT("&Or"), wxPoint(406, 92), wxSize( 56, 26), 0, wxDefaultValidator, wxT("QueryOrBtn"));
2042 pQueryLParenBtn = new wxButton(this, QUERY_DIALOG_LPAREN, wxT("("), wxPoint(406, 126), wxSize( 26, 26), 0, wxDefaultValidator, wxT("QueryLParenBtn"));
2043 pQueryRParenBtn = new wxButton(this, QUERY_DIALOG_RPAREN, wxT(")"), wxPoint(436, 126), wxSize( 26, 26), 0, wxDefaultValidator, wxT("QueryRParenBtn"));
2044 pQueryDoneBtn = new wxButton(this, QUERY_DIALOG_DONE, wxT("&Done"), wxPoint(406, 185), wxSize( 56, 26), 0, wxDefaultValidator, wxT("QueryDoneBtn"));
2045 pQueryClearBtn = new wxButton(this, QUERY_DIALOG_CLEAR, wxT("C&lear"), wxPoint(406, 218), wxSize( 56, 26), 0, wxDefaultValidator, wxT("QueryClearBtn"));
2046 pQueryCountBtn = new wxButton(this, QUERY_DIALOG_COUNT, wxT("&Count"), wxPoint(406, 252), wxSize( 56, 26), 0, wxDefaultValidator, wxT("QueryCountBtn"));
2047 pQueryValue1Msg = new wxStaticText(this, QUERY_DIALOG_VALUE1_MSG, wxT("Value:"), wxPoint(277, 66), wxSize( -1, -1), 0, wxT("QueryValue1Msg"));
2048 pQueryValue1Txt = new wxTextCtrl(this, QUERY_DIALOG_VALUE1_TEXT, wxT(""), wxPoint(277, 83), wxSize(108, 25), 0, wxDefaultValidator, wxT("QueryValue1Txt"));
2049 pQueryValue2Msg = new wxStaticText(this, QUERY_DIALOG_VALUE2_MSG, wxT("AND"), wxPoint(238, 126), wxSize( -1, -1), 0, wxT("QueryValue2Msg"));
2050 pQueryValue2Txt = new wxTextCtrl(this, QUERY_DIALOG_VALUE2_TEXT, wxT(""), wxPoint(277, 120), wxSize(108, 25), 0, wxDefaultValidator, wxT("QueryValue2Txt"));
2051 pQueryHintGrp = new wxStaticBox(this, QUERY_DIALOG_HINT_GROUP, wxT(""), wxPoint( 10, 291), wxSize(377, 40), 0, wxT("QueryHintGrp"));
2052 pQueryHintMsg = new wxStaticText(this, QUERY_DIALOG_HINT_MSG, wxT(""), wxPoint( 16, 306), wxSize( -1, -1), 0, wxT("QueryHintMsg"));
e70e8f4c 2053
a4054ad1 2054 widgetPtrsSet = TRUE;
e70e8f4c
GT
2055 // Initialize the dialog
2056 wxString qualName;
94613352 2057 pQueryCol2Choice->Append(wxT("VALUE -->"));
e70e8f4c
GT
2058 colInf = pDB->GetColumns(tblName);
2059
2060 if (!colInf)
2061 {
2062 wxEndBusyCursor();
2063 wxString tStr;
f21b2fd8
GT
2064 tStr = wxT("ODBC error during GetColumns()\n\n");
2065 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__FILE__,__LINE__),
2066 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
e70e8f4c
GT
2067 return;
2068 }
2069
2070 int i;
f6bcfd97 2071 for (i = 0; colInf[i].colName && wxStrlen(colInf[i].colName); i++)
e70e8f4c
GT
2072 {
2073 // If there is more than one table being queried, qualify
2074 // the column names with the table name prefix.
f6bcfd97 2075 if (tblName[1] && wxStrlen(tblName[1]))
e70e8f4c 2076 {
94613352 2077 qualName.Printf(wxT("%s.%s"), colInf[i].tableName, colInf[i].colName);
e70e8f4c
GT
2078 pQueryCol1Choice->Append(qualName);
2079 pQueryCol2Choice->Append(qualName);
2080 }
2081 else // Single table query, append just the column names
2082 {
2083 pQueryCol1Choice->Append(colInf[i].colName);
2084 pQueryCol2Choice->Append(colInf[i].colName);
2085 }
2086 }
2087
2088 pQueryCol1Choice->SetSelection(0);
2089 pQueryCol2Choice->SetSelection(0);
2090 pQueryOperatorChoice->SetSelection(0);
2091
a4054ad1
GT
2092 pQueryValue2Msg->Show(FALSE);
2093 pQueryValue2Txt->Show(FALSE);
e70e8f4c
GT
2094
2095 pQueryHintMsg->SetLabel(langQRY_EQ);
2096
d3358961 2097 pQuerySqlWhereMtxt->SetValue(pWhere.c_str());
e70e8f4c
GT
2098
2099 wxEndBusyCursor();
2100
2101 // Display the dialog window
2102 Centre(wxBOTH);
2103 ShowModal();
108106cf
JS
2104} // CqueryDlg() constructor
2105
2106
4c4a393f
GT
2107CqueryDlg::~CqueryDlg()
2108{
2109} // CqueryDlg::~CqueryDlg() destructor
2110
2111
3ca6a5f0 2112void CqueryDlg::OnButton(wxCommandEvent &event)
f6fcbb63
RR
2113{
2114 wxWindow *win = (wxWindow*) event.GetEventObject();
2115 OnCommand( *win, event );
3ca6a5f0
BP
2116} // CqueryDlg::OnButton()
2117
f6fcbb63 2118
108106cf
JS
2119void CqueryDlg::OnCommand(wxWindow& win, wxCommandEvent& event)
2120{
e70e8f4c
GT
2121 // Widget pointers won't be set when the dialog is constructed.
2122 // Control is passed through this function once for each widget on
2123 // a dialog as the dialog is constructed.
2124 if (!widgetPtrsSet)
2125 return;
2126
2127 wxString widgetName = win.GetName();
2128
2129 // Operator choice box
2130 if (widgetName == pQueryOperatorChoice->GetName())
2131 {
2132 // Set the help text
2133 switch((qryOp) pQueryOperatorChoice->GetSelection())
2134 {
3ca6a5f0
BP
2135 case qryOpEQ:
2136 pQueryHintMsg->SetLabel(langQRY_EQ);
2137 break;
2138 case qryOpLT:
2139 pQueryHintMsg->SetLabel(langQRY_LT);
2140 break;
2141 case qryOpGT:
2142 pQueryHintMsg->SetLabel(langQRY_GT);
2143 break;
2144 case qryOpLE:
2145 pQueryHintMsg->SetLabel(langQRY_LE);
2146 break;
2147 case qryOpGE:
2148 pQueryHintMsg->SetLabel(langQRY_GE);
2149 break;
2150 case qryOpBEGINS:
2151 pQueryHintMsg->SetLabel(langQRY_BEGINS);
2152 break;
2153 case qryOpCONTAINS:
2154 pQueryHintMsg->SetLabel(langQRY_CONTAINS);
2155 break;
2156 case qryOpLIKE:
2157 pQueryHintMsg->SetLabel(langQRY_LIKE);
2158 break;
2159 case qryOpBETWEEN:
2160 pQueryHintMsg->SetLabel(langQRY_BETWEEN);
2161 break;
e70e8f4c
GT
2162 }
2163
2164 // Hide the value2 widget
a4054ad1
GT
2165 pQueryValue2Msg->Show(FALSE); // BETWEEN will show this widget
2166 pQueryValue2Txt->Show(FALSE); // BETWEEN will show this widget
e70e8f4c
GT
2167
2168 // Disable the NOT operator for <, <=, >, >=
2169 switch((qryOp) pQueryOperatorChoice->GetSelection())
2170 {
3ca6a5f0
BP
2171 case qryOpLT:
2172 case qryOpGT:
2173 case qryOpLE:
2174 case qryOpGE:
2175 pQueryNotCheck->SetValue(0);
a4054ad1 2176 pQueryNotCheck->Enable(FALSE);
3ca6a5f0
BP
2177 break;
2178 default:
a4054ad1 2179 pQueryNotCheck->Enable(TRUE);
3ca6a5f0 2180 break;
e70e8f4c
GT
2181 }
2182
2183 // Manipulate the dialog to handle the selected operator
2184 switch((qryOp) pQueryOperatorChoice->GetSelection())
2185 {
3ca6a5f0
BP
2186 case qryOpEQ:
2187 case qryOpLT:
2188 case qryOpGT:
2189 case qryOpLE:
2190 case qryOpGE:
a4054ad1 2191 pQueryCol2Choice->Enable(TRUE);
3ca6a5f0
BP
2192 if (pQueryCol2Choice->GetSelection()) // Column name is highlighted
2193 {
a4054ad1
GT
2194 pQueryValue1Msg->Show(FALSE);
2195 pQueryValue1Txt->Show(FALSE);
3ca6a5f0
BP
2196 }
2197 else // "Value" is highlighted
2198 {
a4054ad1
GT
2199 pQueryValue1Msg->Show(TRUE);
2200 pQueryValue1Txt->Show(TRUE);
3ca6a5f0
BP
2201 pQueryValue1Txt->SetFocus();
2202 }
2203 break;
2204 case qryOpBEGINS:
2205 case qryOpCONTAINS:
2206 case qryOpLIKE:
2207 pQueryCol2Choice->SetSelection(0);
a4054ad1
GT
2208 pQueryCol2Choice->Enable(FALSE);
2209 pQueryValue1Msg->Show(TRUE);
2210 pQueryValue1Txt->Show(TRUE);
e70e8f4c 2211 pQueryValue1Txt->SetFocus();
3ca6a5f0
BP
2212 break;
2213 case qryOpBETWEEN:
2214 pQueryCol2Choice->SetSelection(0);
a4054ad1
GT
2215 pQueryCol2Choice->Enable(FALSE);
2216 pQueryValue2Msg->Show(TRUE);
2217 pQueryValue2Txt->Show(TRUE);
2218 pQueryValue1Msg->Show(TRUE);
2219 pQueryValue1Txt->Show(TRUE);
3ca6a5f0
BP
2220 pQueryValue1Txt->SetFocus();
2221 break;
e70e8f4c
GT
2222 }
2223
2224 return;
2225
2226 } // Operator choice box
2227
2228 // Column 2 choice
2229 if (widgetName == pQueryCol2Choice->GetName())
2230 {
2231 if (pQueryCol2Choice->GetSelection()) // Column name is highlighted
2232 {
a4054ad1
GT
2233 pQueryValue1Msg->Show(FALSE);
2234 pQueryValue1Txt->Show(FALSE);
e70e8f4c
GT
2235 }
2236 else // "Value" is highlighted
2237 {
a4054ad1
GT
2238 pQueryValue1Msg->Show(TRUE);
2239 pQueryValue1Txt->Show(TRUE);
e70e8f4c
GT
2240 pQueryValue1Txt->SetFocus();
2241 }
2242 return;
e70e8f4c
GT
2243 } // Column 2 choice
2244
2245 // Add button
2246 if (widgetName == pQueryAddBtn->GetName())
2247 {
2248 ProcessAddBtn();
2249 return;
e70e8f4c
GT
2250 } // Add button
2251
2252 // And button
2253 if (widgetName == pQueryAndBtn->GetName())
2254 {
94613352 2255 AppendToWhere(wxT(" AND\n"));
e70e8f4c 2256 return;
e70e8f4c
GT
2257 } // And button
2258
2259 // Or button
2260 if (widgetName == pQueryOrBtn->GetName())
2261 {
94613352 2262 AppendToWhere(wxT(" OR\n"));
e70e8f4c 2263 return;
e70e8f4c
GT
2264 } // Or button
2265
2266 // Left Paren button
2267 if (widgetName == pQueryLParenBtn->GetName())
2268 {
94613352 2269 AppendToWhere(wxT("("));
e70e8f4c 2270 return;
e70e8f4c
GT
2271 } // Left Paren button
2272
2273 // Right paren button
2274 if (widgetName == pQueryRParenBtn->GetName())
2275 {
94613352 2276 AppendToWhere(wxT(")"));
e70e8f4c 2277 return;
e70e8f4c
GT
2278 } // Right Paren button
2279
2280 // Done button
2281 if (widgetName == pQueryDoneBtn->GetName())
2282 {
2283 // Be sure the where clause will not overflow the output buffer
3ca6a5f0 2284 if (wxStrlen(pQuerySqlWhereMtxt->GetValue()) > (unsigned int)DB_MAX_WHERE_CLAUSE_LEN)
e70e8f4c
GT
2285 {
2286 wxString s;
94613352
GT
2287 s.Printf(wxT("Maximum where clause length exceeded.\nLength must be less than %d"), DB_MAX_WHERE_CLAUSE_LEN+1);
2288 wxMessageBox(s,wxT("Error..."),wxOK | wxICON_EXCLAMATION);
e70e8f4c
GT
2289 return;
2290 }
2291 // Validate the where clause for things such as matching parens
2292 if (!ValidateWhereClause())
2293 return;
2294 // Copy the where clause to the output buffer and exit
d3358961 2295 pWhere = pQuerySqlWhereMtxt->GetValue();
e70e8f4c
GT
2296 Close();
2297 return;
e70e8f4c
GT
2298 } // Done button
2299
2300 // Clear button
2301 if (widgetName == pQueryClearBtn->GetName())
2302 {
94613352 2303 bool Ok = (wxMessageBox(wxT("Are you sure you wish to clear the Query?"),wxT("Confirm"),wxYES_NO|wxICON_QUESTION) == wxYES);
e70e8f4c
GT
2304
2305 if (Ok)
94613352 2306 pQuerySqlWhereMtxt->SetValue(wxT(""));
e70e8f4c 2307 return;
e70e8f4c
GT
2308 } // Clear button
2309
2310 // Count button
2311 if (widgetName == pQueryCountBtn->GetName())
2312 {
2313 wxBeginBusyCursor();
2314 ProcessCountBtn();
2315 wxEndBusyCursor();
2316 return;
e70e8f4c 2317 } // Count button
108106cf
JS
2318
2319} // CqueryDlg::OnCommand
2320
2321
e3065973 2322void CqueryDlg::OnCloseWindow(wxCloseEvent& event)
108106cf 2323{
e70e8f4c 2324 // Clean up
ea24eeb2 2325 wxDELETEA(colInf);
e70e8f4c 2326
ea24eeb2 2327 wxDELETE(dbTable);
e70e8f4c
GT
2328
2329 GetParent()->SetFocus();
2330 while (wxIsBusy())
2331 wxEndBusyCursor();
108106cf 2332
a4054ad1 2333 Show(FALSE);
3ca6a5f0 2334 SetReturnCode(1); // added so BoundsChecker would not report use of uninitialized variable
e3065973 2335
3ca6a5f0 2336 this->Destroy();
e3065973 2337} // CqueryDlg::OnCloseWindow()
108106cf 2338
108106cf 2339
94613352 2340void CqueryDlg::AppendToWhere(wxChar *s)
108106cf 2341{
3ca6a5f0
BP
2342 wxString whereStr = pQuerySqlWhereMtxt->GetValue();
2343 whereStr += s;
2344 pQuerySqlWhereMtxt->SetValue(whereStr);
108106cf
JS
2345} // CqueryDlg::AppendToWhere()
2346
2347
2348void CqueryDlg::ProcessAddBtn()
2349{
e70e8f4c
GT
2350 qryOp oper = (qryOp) pQueryOperatorChoice->GetSelection();
2351
2352 // Verify that eveything is filled in correctly
2353 if (pQueryCol2Choice->GetSelection() == 0) // "Value" is selected
2354 {
2355 // Verify that value 1 is filled in
f6bcfd97 2356 if (wxStrlen(pQueryValue1Txt->GetValue()) == 0)
e70e8f4c
GT
2357 {
2358 wxBell();
2359 pQueryValue1Txt->SetFocus();
2360 return;
2361 }
2362 // For the BETWEEN operator, value 2 must be filled in as well
2363 if (oper == qryOpBETWEEN &&
f6bcfd97 2364 wxStrlen(pQueryValue2Txt->GetValue()) == 0)
e70e8f4c
GT
2365 {
2366 wxBell();
2367 pQueryValue2Txt->SetFocus();
2368 return;
2369 }
2370 }
2371
2372 // Build the expression and append it to the where clause window
2373 wxString s = pQueryCol1Choice->GetStringSelection();
2374
2375 if (pQueryNotCheck->GetValue() && (oper != qryOpEQ))
94613352 2376 s += wxT(" NOT");
e70e8f4c
GT
2377
2378 switch(oper)
2379 {
2380 case qryOpEQ:
2381 if (pQueryNotCheck->GetValue()) // NOT box is checked
94613352 2382 s += wxT(" <>");
e70e8f4c 2383 else
94613352 2384 s += wxT(" =");
e70e8f4c
GT
2385 break;
2386 case qryOpLT:
94613352 2387 s += wxT(" <");
e70e8f4c
GT
2388 break;
2389 case qryOpGT:
94613352 2390 s += wxT(" >");
e70e8f4c
GT
2391 break;
2392 case qryOpLE:
94613352 2393 s += wxT(" <=");
e70e8f4c
GT
2394 break;
2395 case qryOpGE:
94613352 2396 s += wxT(" >=");
e70e8f4c
GT
2397 break;
2398 case qryOpBEGINS:
2399 case qryOpCONTAINS:
2400 case qryOpLIKE:
94613352 2401 s += wxT(" LIKE");
e70e8f4c
GT
2402 break;
2403 case qryOpBETWEEN:
94613352 2404 s += wxT(" BETWEEN");
e70e8f4c
GT
2405 break;
2406 }
2407
94613352 2408 s += wxT(" ");
e70e8f4c
GT
2409
2410 int col1Idx = pQueryCol1Choice->GetSelection();
2411
a4054ad1 2412 bool quote = FALSE;
e70e8f4c
GT
2413 if (colInf[col1Idx].sqlDataType == SQL_VARCHAR ||
2414 oper == qryOpBEGINS ||
2415 oper == qryOpCONTAINS ||
2416 oper == qryOpLIKE)
a4054ad1 2417 quote = TRUE;
e70e8f4c
GT
2418
2419 if (pQueryCol2Choice->GetSelection()) // Column name
2420 s += pQueryCol2Choice->GetStringSelection();
2421 else // Column 2 is a "value"
2422 {
2423 if (quote)
94613352 2424 s += wxT("'");
e70e8f4c 2425 if (oper == qryOpCONTAINS)
94613352 2426 s += wxT("%");
e70e8f4c
GT
2427 s += pQueryValue1Txt->GetValue();
2428 if (oper == qryOpCONTAINS || oper == qryOpBEGINS)
94613352 2429 s += wxT("%");
e70e8f4c 2430 if (quote)
94613352 2431 s += wxT("'");
e70e8f4c
GT
2432 }
2433
2434 if (oper == qryOpBETWEEN)
2435 {
94613352 2436 s += wxT(" AND ");
e70e8f4c 2437 if (quote)
94613352 2438 s += wxT("'");
e70e8f4c
GT
2439 s += pQueryValue2Txt->GetValue();
2440 if (quote)
94613352 2441 s += wxT("'");
e70e8f4c
GT
2442 }
2443
94613352 2444 AppendToWhere((wxChar*) (const wxChar*) s);
108106cf
JS
2445
2446} // CqueryDlg::ProcessAddBtn()
2447
2448
2449void CqueryDlg::ProcessCountBtn()
2450{
e70e8f4c
GT
2451 if (!ValidateWhereClause())
2452 return;
2453
3fe813a9 2454 if (!dbTable) // wxDbTable object needs to be created and opened
e70e8f4c 2455 {
3fe813a9
GT
2456 dbTable = new wxDbTable(pDB, masterTableName, 0, wxT(""),
2457 !wxDB_QUERY_ONLY,
2458 wxGetApp().DbConnectInf->GetDefaultDir());
2459 if (!dbTable)
e70e8f4c 2460 {
94613352 2461 wxMessageBox(wxT("Memory allocation failed creating a wxDbTable object."),wxT("Error..."),wxOK | wxICON_EXCLAMATION);
e70e8f4c
GT
2462 return;
2463 }
2464 if (!dbTable->Open())
2465 {
2466 wxString tStr;
f21b2fd8
GT
2467 tStr = wxT("ODBC error during Open()\n\n");
2468 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__FILE__,__LINE__),
2469 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
e70e8f4c
GT
2470 return;
2471 }
2472 }
2473
2474 // Count() with WHERE clause
f6bcfd97 2475 wxString whereStr;
4c4a393f
GT
2476
2477 whereStr = pQuerySqlWhereMtxt->GetValue();
f6bcfd97 2478 dbTable->SetWhereClause(whereStr.c_str());
94613352 2479
e70e8f4c
GT
2480 ULONG whereCnt = dbTable->Count();
2481
2482 // Count() of all records in the table
94613352 2483 dbTable->SetWhereClause(wxT(""));
e70e8f4c
GT
2484 ULONG totalCnt = dbTable->Count();
2485
2486 if (whereCnt > 0 || totalCnt == 0)
2487 {
2488 wxString tStr;
94613352
GT
2489 tStr.Printf(wxT("%lu of %lu records match the query criteria."),whereCnt,totalCnt);
2490 wxMessageBox(tStr,wxT("Notice..."),wxOK | wxICON_INFORMATION);
e70e8f4c
GT
2491 }
2492 else
2493 {
2494 wxString tStr;
94613352
GT
2495 tStr.Printf(wxT("%lu of %lu records match the query criteria.\n\nEither the criteria entered produced a result set\nwith no records, or there was a syntactical error\nin the clause you entered.\n\nPress the details button to see if any database errors were reported."),whereCnt,totalCnt);
2496 wxMessageBox(tStr,wxT("Notice..."),wxOK | wxICON_INFORMATION);
e70e8f4c
GT
2497 }
2498
2499 // After a wxMessageBox, the focus does not necessarily return to the
2500 // window which was the focus when the message box popped up, so return
2501 // focus to the Query dialog for certain
2502 SetFocus();
108106cf
JS
2503
2504} // CqueryDlg::ProcessCountBtn()
2505
2506
1fc5dd6f 2507bool CqueryDlg::ValidateWhereClause()
108106cf 2508{
e70e8f4c
GT
2509 wxString where = pQuerySqlWhereMtxt->GetValue();
2510
94613352 2511 if (where.Freq(wxT('(')) != where.Freq(wxT(')')))
e70e8f4c 2512 {
94613352 2513 wxMessageBox(wxT("There are mismatched parenthesis in the constructed where clause"),wxT("Error..."),wxOK | wxICON_EXCLAMATION);
a4054ad1 2514 return(FALSE);
e70e8f4c
GT
2515 }
2516 // After a wxMessageBox, the focus does not necessarily return to the
2517 // window which was the focus when the message box popped up, so return
2518 // focus to the Query dialog for certain
2519 SetFocus();
2520
a4054ad1 2521 return(TRUE);
108106cf
JS
2522
2523} // CqueryDlg::ValidateWhereClause()
3f755e2d
GT
2524
2525
2526
3f030b48
GT
2527void DisplayDbDiagnostics(wxDb *pDb)
2528{
69a2b59d 2529 wxString s, t;
a4054ad1 2530 bool comma = FALSE;
69a2b59d
GT
2531
2532 s = langDBINF_DB_NAME;
2533 s += pDb->dbInf.dbmsName;
2534 s += "\n";
2535
2536 s += langDBINF_DB_VER;
2537 s += pDb->dbInf.dbmsVer;
2538 s += "\n";
2539
2540 s += langDBINF_DRIVER_NAME;
2541 s += pDb->dbInf.driverName;
2542 s += "\n";
2543
2544 s += langDBINF_DRIVER_ODBC_VER;
2545 s += pDb->dbInf.odbcVer;
2546 s += "\n";
2547
2548 s += langDBINF_DRIVER_MGR_ODBC_VER;
2549 s += pDb->dbInf.drvMgrOdbcVer;
2550 s += "\n";
2551
2552 s += langDBINF_DRIVER_VER;
2553 s += pDb->dbInf.driverVer;
2554 s += "\n";
2555
2556 s += langDBINF_SERVER_NAME;
2557 s += pDb->dbInf.serverName;
2558 s += "\n";
2559
2560 s += langDBINF_FILENAME;
2561 s += pDb->dbInf.databaseName;
2562 s += "\n";
2563
2564 s += langDBINF_OUTER_JOINS;
2565 s += pDb->dbInf.outerJoins;
2566 s += "\n";
2567
2568 s += langDBINF_STORED_PROC;
2569 s += pDb->dbInf.procedureSupport;
2570 s += "\n";
2571
2572 if (pDb->dbInf.maxConnections)
2573 t.sprintf("%s%d\n", langDBINF_MAX_HDBC, pDb->dbInf.maxConnections);
2574 else
2575 t.sprintf("%s%s\n", langDBINF_MAX_HDBC, langDBINF_UNLIMITED);
2576 s += t;
2577
2578 if (pDb->dbInf.maxStmts)
2579 t.sprintf("%s%d\n", langDBINF_MAX_HSTMT, pDb->dbInf.maxStmts);
2580 else
2581 t.sprintf("%s%s\n", langDBINF_MAX_HSTMT, langDBINF_UNLIMITED);
2582 s += t;
2583
2584 s += langDBINF_API_LVL;
2585 switch(pDb->dbInf.apiConfLvl)
2586 {
2587 case SQL_OAC_NONE: s += langDBINF_NONE; break;
2588 case SQL_OAC_LEVEL1: s += langDBINF_LEVEL1; break;
2589 case SQL_OAC_LEVEL2: s += langDBINF_LEVEL2; break;
2590 }
2591 s += "\n";
2592
2593 s += langDBINF_CLI_LVL;
2594 switch(pDb->dbInf.cliConfLvl)
2595 {
2596 case SQL_OSCC_NOT_COMPLIANT: s += langDBINF_NOT_COMPLIANT; break;
2597 case SQL_OSCC_COMPLIANT: s += langDBINF_COMPLIANT; break;
2598 }
2599 s += "\n";
2600
2601 s += langDBINF_SQL_LVL;
2602 switch(pDb->dbInf.sqlConfLvl)
2603 {
2604 case SQL_OSC_MINIMUM: s += langDBINF_MIN_GRAMMAR; break;
2605 case SQL_OSC_CORE: s += langDBINF_CORE_GRAMMAR; break;
2606 case SQL_OSC_EXTENDED: s += langDBINF_EXT_GRAMMAR; break;
2607 }
2608 s += "\n";
2609
2610 s += langDBINF_COMMIT_BEHAVIOR;
2611 switch(pDb->dbInf.cursorCommitBehavior)
2612 {
2613 case SQL_CB_DELETE: s += langDBINF_DELETE_CURSORS; break;
2614 case SQL_CB_CLOSE: s += langDBINF_CLOSE_CURSORS; break;
2615 case SQL_CB_PRESERVE: s += langDBINF_PRESERVE_CURSORS; break;
2616 }
2617 s += "\n";
2618
2619 s += langDBINF_ROLLBACK_BEHAVIOR;
2620 switch(pDb->dbInf.cursorRollbackBehavior)
2621 {
2622 case SQL_CB_DELETE: s += langDBINF_DELETE_CURSORS; break;
2623 case SQL_CB_CLOSE: s += langDBINF_CLOSE_CURSORS; break;
2624 case SQL_CB_PRESERVE: s += langDBINF_PRESERVE_CURSORS; break;
2625 }
2626 s += "\n";
2627
2628 s += langDBINF_SUPP_NOT_NULL;
2629 switch(pDb->dbInf.supportNotNullClause)
2630 {
2631 case SQL_NNC_NULL: s += langNO; break;
2632 case SQL_NNC_NON_NULL: s += langYES; break;
2633 }
2634 s += "\n";
2635
2636 s += langDBINF_SUPP_IEF;
2637 s += pDb->dbInf.supportIEF;
2638 s += "\n";
2639
2640 // DEFAULT setting for "Transaction Isolation Level"
2641 s += langDBINF_TXN_ISOLATION;
2642 switch(pDb->dbInf.txnIsolation)
2643 {
2644 case SQL_TXN_READ_UNCOMMITTED: s += langDBINF_READ_UNCOMMITTED; break;
2645 case SQL_TXN_READ_COMMITTED: s += langDBINF_READ_COMMITTED; break;
2646 case SQL_TXN_REPEATABLE_READ: s += langDBINF_REPEATABLE_READ; break;
2647 case SQL_TXN_SERIALIZABLE: s += langDBINF_SERIALIZABLE; break;
3f030b48 2648#ifdef ODBC_V20
69a2b59d
GT
2649 case SQL_TXN_VERSIONING: s += langDBINF_VERSIONING; break;
2650#endif
2651 }
2652 s += "\n";
2653
2654 // CURRENT setting for "Transaction Isolation Level"
2655 long txnIsoLvl;
2656 s += langDBINF_TXN_ISOLATION_CURR;
2657 if (SQLGetConnectOption(pDb->GetHDBC(),SQL_TXN_ISOLATION,&txnIsoLvl) == SQL_SUCCESS)
2658 {
2659 switch(txnIsoLvl)
2660 {
2661 case SQL_TXN_READ_UNCOMMITTED: s += langDBINF_READ_UNCOMMITTED; break;
2662 case SQL_TXN_READ_COMMITTED: s += langDBINF_READ_COMMITTED; break;
2663 case SQL_TXN_REPEATABLE_READ: s += langDBINF_REPEATABLE_READ; break;
2664 case SQL_TXN_SERIALIZABLE: s += langDBINF_SERIALIZABLE; break;
3f030b48 2665#ifdef ODBC_V20
69a2b59d
GT
2666 case SQL_TXN_VERSIONING: s += langDBINF_VERSIONING; break;
2667#endif
2668 }
2669 }
2670 s += "\n";
2671
abfcca57
JJ
2672#ifdef __VMS__
2673#pragma message disable incboodep
2674#endif
a4054ad1 2675 comma = FALSE;
69a2b59d
GT
2676 s += langDBINF_TXN_ISOLATION_OPTS;
2677 if (pDb->dbInf.txnIsolationOptions & SQL_TXN_READ_UNCOMMITTED)
2678 {s += langDBINF_READ_UNCOMMITTED; comma++;}
2679 if (pDb->dbInf.txnIsolationOptions & SQL_TXN_READ_COMMITTED)
2680 {if (comma++) s += ", "; s += langDBINF_READ_COMMITTED;}
2681 if (pDb->dbInf.txnIsolationOptions & SQL_TXN_REPEATABLE_READ)
2682 {if (comma++) s += ", "; s += langDBINF_REPEATABLE_READ;}
2683 if (pDb->dbInf.txnIsolationOptions & SQL_TXN_SERIALIZABLE)
2684 {if (comma++) s += ", "; s += langDBINF_SERIALIZABLE;}
3f030b48 2685#ifdef ODBC_V20
69a2b59d
GT
2686 if (pDb->dbInf.txnIsolationOptions & SQL_TXN_VERSIONING)
2687 {if (comma++) s += ", "; s += langDBINF_VERSIONING;}
2688#endif
2689 s += "\n";
2690
a4054ad1 2691 comma = FALSE;
69a2b59d
GT
2692 s += langDBINF_FETCH_DIRS;
2693 if (pDb->dbInf.fetchDirections & SQL_FD_FETCH_NEXT)
2694 {s += langDBINF_NEXT; comma++;}
2695 if (pDb->dbInf.fetchDirections & SQL_FD_FETCH_PRIOR)
2696 {if (comma++) s += ", "; s += langDBINF_PREV;}
2697 if (pDb->dbInf.fetchDirections & SQL_FD_FETCH_FIRST)
2698 {if (comma++) s += ", "; s += langDBINF_FIRST;}
2699 if (pDb->dbInf.fetchDirections & SQL_FD_FETCH_LAST)
2700 {if (comma++) s += ", "; s += langDBINF_LAST;}
2701 if (pDb->dbInf.fetchDirections & SQL_FD_FETCH_ABSOLUTE)
2702 {if (comma++) s += ", "; s += langDBINF_ABSOLUTE;}
2703 if (pDb->dbInf.fetchDirections & SQL_FD_FETCH_RELATIVE)
2704 {if (comma++) s += ", "; s += langDBINF_RELATIVE;}
3f030b48 2705#ifdef ODBC_V20
69a2b59d
GT
2706 if (pDb->dbInf.fetchDirections & SQL_FD_FETCH_RESUME)
2707 {if (comma++) s += ", "; s += langDBINF_RESUME;}
2708#endif
2709 if (pDb->dbInf.fetchDirections & SQL_FD_FETCH_BOOKMARK)
2710 {if (comma++) s += ", "; s += langDBINF_BOOKMARK;}
2711 s += "\n";
2712
a4054ad1 2713 comma = FALSE;
69a2b59d
GT
2714 s += langDBINF_LOCK_TYPES;
2715 if (pDb->dbInf.lockTypes & SQL_LCK_NO_CHANGE)
2716 {s += langDBINF_NO_CHANGE; comma++;}
2717 if (pDb->dbInf.lockTypes & SQL_LCK_EXCLUSIVE)
2718 {if (comma++) s += ", "; s += langDBINF_EXCLUSIVE;}
2719 if (pDb->dbInf.lockTypes & SQL_LCK_UNLOCK)
2720 {if (comma++) s += ", "; s += langDBINF_UNLOCK;}
2721 s += "\n";
2722
a4054ad1 2723 comma = FALSE;
69a2b59d
GT
2724 s += langDBINF_POS_OPERS;
2725 if (pDb->dbInf.posOperations & SQL_POS_POSITION)
2726 {s += langDBINF_POSITION; comma++;}
2727 if (pDb->dbInf.posOperations & SQL_POS_REFRESH)
2728 {if (comma++) s += ", "; s += langDBINF_REFRESH;}
2729 if (pDb->dbInf.posOperations & SQL_POS_UPDATE)
2730 {if (comma++) s += ", "; s += langDBINF_UPD;}
2731 if (pDb->dbInf.posOperations & SQL_POS_DELETE)
2732 {if (comma++) s += ", "; s += langDBINF_DEL;}
2733 if (pDb->dbInf.posOperations & SQL_POS_ADD)
2734 {if (comma++) s += ", "; s += langDBINF_ADD;}
2735 s += "\n";
2736
a4054ad1 2737 comma = FALSE;
69a2b59d
GT
2738 s += langDBINF_POS_STMTS;
2739 if (pDb->dbInf.posStmts & SQL_PS_POSITIONED_DELETE)
2740 {s += langDBINF_POS_DEL; comma++;}
2741 if (pDb->dbInf.posStmts & SQL_PS_POSITIONED_UPDATE)
2742 {if (comma++) s += ", "; s += langDBINF_POS_UPD;}
2743 if (pDb->dbInf.posStmts & SQL_PS_SELECT_FOR_UPDATE)
2744 {if (comma++) s += ", "; s += langDBINF_SELECT_FOR_UPD;}
2745 s += "\n";
2746
a4054ad1 2747 comma = FALSE;
69a2b59d
GT
2748 s += langDBINF_SCROLL_CONCURR;
2749 if (pDb->dbInf.scrollConcurrency & SQL_SCCO_READ_ONLY)
2750 {s += langDBINF_READ_ONLY; comma++;}
2751 if (pDb->dbInf.scrollConcurrency & SQL_SCCO_LOCK)
2752 {if (comma++) s += ", "; s += langDBINF_LOCK;}
2753 if (pDb->dbInf.scrollConcurrency & SQL_SCCO_OPT_ROWVER)
2754 {if (comma++) s += ", "; s += langDBINF_OPT_ROWVER;}
2755 if (pDb->dbInf.scrollConcurrency & SQL_SCCO_OPT_VALUES)
2756 {if (comma++) s += ", "; s += langDBINF_OPT_VALUES;}
2757 s += "\n";
2758
a4054ad1 2759 comma = FALSE;
69a2b59d
GT
2760 s += langDBINF_SCROLL_OPTS;
2761 if (pDb->dbInf.scrollOptions & SQL_SO_FORWARD_ONLY)
2762 {s += langDBINF_FWD_ONLY; comma++;}
2763 if (pDb->dbInf.scrollOptions & SQL_SO_STATIC)
2764 {if (comma++) s += ", "; s += langDBINF_STATIC;}
2765 if (pDb->dbInf.scrollOptions & SQL_SO_KEYSET_DRIVEN)
2766 {if (comma++) s += ", "; s += langDBINF_KEYSET_DRIVEN;}
2767 if (pDb->dbInf.scrollOptions & SQL_SO_DYNAMIC)
2768 {if (comma++) s += ", "; s += langDBINF_DYNAMIC;}
2769 if (pDb->dbInf.scrollOptions & SQL_SO_MIXED)
2770 {if (comma++) s += ", "; s += langDBINF_MIXED;}
2771 s += "\n";
2772
a4054ad1 2773 comma = FALSE;
69a2b59d
GT
2774 s += langDBINF_STATIC_SENS;
2775 if (pDb->dbInf.staticSensitivity & SQL_SS_ADDITIONS)
2776 {s += langDBINF_ADDITIONS; comma++;}
2777 if (pDb->dbInf.staticSensitivity & SQL_SS_DELETIONS)
2778 {if (comma++) s += ", "; s += langDBINF_DELETIONS;}
2779 if (pDb->dbInf.staticSensitivity & SQL_SS_UPDATES)
2780 {if (comma++) s += ", "; s += langDBINF_UPDATES;}
2781 s += "\n";
abfcca57
JJ
2782#ifdef __VMS__
2783#pragma message enable incboodep
2784#endif
69a2b59d
GT
2785
2786
2787 s += langDBINF_TXN_CAPABLE;
2788 switch(pDb->dbInf.txnCapable)
2789 {
2790 case SQL_TC_NONE: s += langNO; break;
2791 case SQL_TC_DML: s += langDBINF_DML_ONLY; break;
2792 case SQL_TC_DDL_COMMIT: s += langDBINF_DDL_COMMIT; break;
2793 case SQL_TC_DDL_IGNORE: s += langDBINF_DDL_IGNORE; break;
2794 case SQL_TC_ALL: s += langDBINF_DDL_AND_DML; break;
2795 }
2796 s += "\n";
2797
2798 t.sprintf("%s%d\n", langDBINF_LOGIN_TIMEOUT, pDb->dbInf.loginTimeout);
2799 s += t;
2800
2801 // Oracle specific information
2802 if (pDb->Dbms() == dbmsORACLE)
2803 {
2804 s += "\n";
2805 s += langDBINF_ORACLE_BANNER;
2806 s += "\n";
2807
2808 // Oracle cache hit ratio
2809 SDWORD cb;
2810 ULONG dbBlockGets;
2811 pDb->ExecSql("SELECT VALUE FROM V$SYSSTAT WHERE NAME = 'db block gets'");
2812 pDb->GetNext();
2813 if (pDb->GetData(1, SQL_C_ULONG, &dbBlockGets, 0, &cb))
2814 {
2815 t.sprintf("%s: %lu\n", langDBINF_DB_BLOCK_GETS, dbBlockGets);
2816 s += t;
2817 }
2818
2819 ULONG consistentGets;
2820 pDb->ExecSql("SELECT VALUE FROM V$SYSSTAT WHERE NAME = 'consistent gets'");
2821 pDb->GetNext();
2822 if (pDb->GetData(1, SQL_C_ULONG, &consistentGets, 0, &cb))
2823 {
2824 t.sprintf("%s: %lu\n", langDBINF_CONSISTENT_GETS, consistentGets);
2825 s += t;
2826 }
2827
2828 ULONG physReads;
2829 pDb->ExecSql("SELECT VALUE FROM V$SYSSTAT WHERE NAME = 'physical reads'");
2830 pDb->GetNext();
2831 if (pDb->GetData(1, SQL_C_ULONG, &physReads, 0, &cb))
2832 {
2833 t.sprintf("%s: %lu\n", langDBINF_PHYSICAL_READS, physReads);
2834 s += t;
2835 }
2836
2837 ULONG hitRatio = (ULONG)((1.00 - ((float)physReads / (float)(dbBlockGets + consistentGets))) * 100.00);
2838 t.sprintf("*** %s: %lu%%\n", langDBINF_CACHE_HIT_RATIO, hitRatio);
2839 s += t;
2840
2841 // Tablespace information
2842 s += "\n";
2843 s += langDBINF_TABLESPACE_IO;
2844 s += "\n";
2845 ULONG physWrites;
2846 char tablespaceName[257];
2847 pDb->ExecSql("SELECT NAME,PHYRDS,PHYWRTS FROM V$DATAFILE, V$FILESTAT WHERE V$DATAFILE.FILE# = V$FILESTAT.FILE#");
2848 while (pDb->GetNext())
2849 {
2850 pDb->GetData(1, SQL_C_CHAR, tablespaceName, 257, &cb);
2851 pDb->GetData(2, SQL_C_ULONG, &physReads, 0, &cb);
2852 pDb->GetData(3, SQL_C_ULONG, &physWrites, 0, &cb);
2853 t.sprintf("%s\n\t%s: %lu\t%s: %lu\n", tablespaceName,
2854 langDBINF_PHYSICAL_READS, physReads, langDBINF_PHYSICAL_WRITES, physWrites);
2855 s += t;
2856 }
2857
2858 s += "\n";
2859 }
3f030b48
GT
2860
2861 wxLogMessage(s);
2862
2863} // DisplayDbDiagnostics()
2864
f21b2fd8
GT
2865#if wxUSE_NEW_GRID
2866
2867BEGIN_EVENT_TABLE(DbGridFrame, wxFrame)
2868 // EVT_CLOSE(DbGridFrame::OnCloseWindow)
2869END_EVENT_TABLE()
2870
2871
2872DbGridFrame::DbGridFrame(wxWindow *parent)
2873 : wxFrame (parent, -1, wxT("Database Table"),
2f6c54eb 2874 wxDefaultPosition, wxSize(400, 325))
f21b2fd8 2875{
a4054ad1 2876 initialized = FALSE;
f21b2fd8
GT
2877}
2878
2879
2880void DbGridFrame::OnCloseWindow(wxCloseEvent& event)
2881{
2882 this->Destroy();
2883}
2884
2885
2886bool DbGridFrame::Initialize()
2887{
2888 wxGrid *grid = new wxGrid(this, -1, wxDefaultPosition);
2889
2890 grid->RegisterDataType(wxGRID_VALUE_DATETIME,
2891 new wxGridCellDateTimeRenderer(_T("%d %b %Y")),
2892 new wxGridCellTextEditor);
2893#ifdef CHOICEINT
2894 grid->RegisterDataType(wxGRID_VALUE_CHOICEINT,
2895 new wxGridCellEnumRenderer,
2896 new wxGridCellEnumEditor);
2897
2898 wxString NativeLangChoice( wxString::Format("%s:%s,%s,%s,%s,%s",wxGRID_VALUE_CHOICEINT,
2899 wxT("English"),
2900 wxT("French"),
2901 wxT("German"),
2902 wxT("Spanish"),
2903 wxT("Other") ));
2904#endif
2905
2906 // Columns must match the sequence specified in SetColDef() calls
2907 wxDbGridColInfo* cols =
2908 new wxDbGridColInfo( 0,wxGRID_VALUE_STRING,wxT("Name"),
2909 new wxDbGridColInfo( 1,wxGRID_VALUE_STRING,wxT("Address 1"),
2910 new wxDbGridColInfo( 2,wxGRID_VALUE_STRING,wxT("Address 2"),
2911 new wxDbGridColInfo( 3,wxGRID_VALUE_STRING,wxT("City"),
2912 new wxDbGridColInfo( 4,wxGRID_VALUE_STRING,wxT("State"),
2913 new wxDbGridColInfo( 5,wxGRID_VALUE_STRING,wxT("PostCode"),
2914 new wxDbGridColInfo( 6,wxGRID_VALUE_STRING,wxT("Country"),
2915 new wxDbGridColInfo( 7,wxGRID_VALUE_DBAUTO,wxT("Join Date"),
2916 new wxDbGridColInfo( 8,wxGRID_VALUE_BOOL, wxT("Developer"),
2917 new wxDbGridColInfo( 9,wxGRID_VALUE_NUMBER,wxT("Contributions"),
2918 new wxDbGridColInfo(10,wxGRID_VALUE_NUMBER,wxT("Lines Of Code"),
2919#ifdef CHOICEINT
2920 new wxDbGridColInfo(11,NativeLangChoice, wxT("Native Language"),NULL))))))))))));
2921#else
2922 new wxDbGridColInfo(11,wxGRID_VALUE_NUMBER,wxT("Native Language"),NULL))))))))))));
2923#endif
2924
2925 Ccontact *Contact = new Ccontact();
2926 //wxGetApp().Contact
2927
2928 if (!Contact)
2929 {
2930 wxMessageBox(wxT("Unable to instantiate an instance of Ccontact"), wxT("Error..."), wxOK | wxICON_EXCLAMATION);
a4054ad1 2931 return FALSE;
f21b2fd8
GT
2932 }
2933
2934 if (!Contact->Open())
2935 {
2936 if (Contact->GetDb()->TableExists(CONTACT_TABLE_NAME, Contact->GetDb()->GetUsername(),
2937 wxGetApp().DbConnectInf->GetDefaultDir()))
2938 {
2939 wxString tStr;
2940 tStr.Printf(wxT("Unable to open the table '%s'.\n\n"),CONTACT_TABLE_NAME);
2941 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__FILE__,__LINE__),
2942 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
2943 }
2944
a4054ad1 2945 return FALSE;
f21b2fd8
GT
2946 }
2947
2948 // Execute the following query using the cursor designated
2949 // for full table query
2950 Contact->SetRowMode(wxDbTable::WX_ROW_MODE_QUERY);
2951
2952 if (!Contact->Query())
2953 {
2954 wxString tStr;
2955 tStr = wxT("ODBC error during Query()\n\n");
2956 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__FILE__,__LINE__),
2957 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
a4054ad1 2958 return FALSE;
f21b2fd8
GT
2959 }
2960
2961 // No data has been read in from the database yet, so
2962 // we need to initialize the data members to valid values
2963 // so Fit() can correctly size the grid
2964 Contact->Initialize();
2965
a4054ad1 2966 wxDbGridTableBase* db = new wxDbGridTableBase(Contact, cols, wxUSE_QUERY, TRUE);
f21b2fd8
GT
2967
2968 delete cols;
2969
a4054ad1 2970 grid->SetTable(db,TRUE);
f21b2fd8 2971 grid->SetMargins(0, 0);
3f030b48 2972
f21b2fd8
GT
2973 grid->Fit();
2974 wxSize size = grid->GetSize();
2975 size.x += 10;
2976 size.y += 10;
2977 SetClientSize(size);
a4054ad1
GT
2978 initialized = TRUE;
2979 return TRUE;
f21b2fd8 2980} // DbGridFrame::Initialize()
3f030b48 2981
f21b2fd8 2982#endif // #if wxUSE_NEW_GRID
3f755e2d
GT
2983
2984/*
2985 TEST CODE FOR TESTING THE wxDbCreateDataSource() FUNCTION
2986
2987 int result = 0;
a4054ad1 2988 result = wxDbCreateDataSource(wxT("Microsoft Access Driver (*.mdb)"),wxT("GLT-TEST2"),wxT("GLT-Descrip"),FALSE,wxT(""),this);
3f755e2d
GT
2989 if (!result)
2990 {
2991 // check for errors caused by ConfigDSN based functions
2992 DWORD retcode = 0;
2993 WORD cb;
2994 wxChar errMsg[500+1];
94613352 2995 errMsg[0] = wxT('\0');
3f755e2d
GT
2996
2997 SQLInstallerError(1,&retcode,errMsg,500,&cb);
2998
94613352 2999 wxMessageBox(wxT("FAILED creating data source"),wxT("FAILED"));
3f755e2d
GT
3000 }
3001 else
94613352 3002 wxMessageBox(wxT("SUCCEEDED creating data source"),wxT("SUCCESS"));
3f755e2d
GT
3003*/
3004
3005