1 ///////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxWindows database demo app
4 // Author: George Tasker
8 // Copyright: (c) 1998 Remstar International, Inc.
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
15 This sample program demonstrates the cross-platform ODBC database classes
16 donated by the development team at Remstar International.
18 The table this sample is based on is developer contact table, and shows
19 some of the simple uses of the database classes wxDb and wxDbTable.
25 #pragma implementation "dbtest.h"
28 #include "wx/wxprec.h"
42 #include <stdio.h> /* Included strictly for reading the text file with the database parameters */
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 */
47 extern wxDbList WXDLLEXPORT
*PtrBegDbList
; /* from db.cpp, used in getting back error results from db connections */
49 #include "dbtest.h" /* Header file for this demonstration program */
50 #include "listdb.h" /* Code to support the "Lookup" button on the editor dialog */
52 IMPLEMENT_APP(DatabaseDemoApp
)
54 extern char ListDB_Selection
[]; /* Used to return the first column value for the selected line from the listDB routines */
55 extern char ListDB_Selection2
[]; /* Used to return the second column value for the selected line from the listDB routines */
57 DatabaseDemoFrame
*DemoFrame
; /* Pointer to the main frame */
59 /* Pointer to the main database connection used in the program. This
60 * pointer would normally be used for doing things as database lookups
61 * for user login names and passwords, getting workstation settings, etc.
64 * For each database object created which uses this wxDb pointer
65 * connection to the database, when a CommitTrans() or RollBackTrans()
66 * will commit or rollback EVERY object which uses this wxDb pointer.
68 * To allow each table object (those derived from wxDbTable) to be
69 * individually committed or rolled back, you MUST use a different
70 * instance of wxDb in the constructor of the table. Doing so creates
71 * more overhead, and will use more database connections (some DBs have
72 * connection limits...), so use connections sparringly.
74 * It is recommended that one "main" database connection be created for
75 * the entire program to use for READ-ONLY database accesses, but for each
76 * table object which will do a CommitTrans() or RollbackTrans() that a
77 * new wxDb object be created and used for it.
83 * This function will return the exact string(s) from the database engine
84 * indicating all error conditions which have just occured during the
85 * last call to the database engine.
87 * This demo uses the returned string by displaying it in a wxMessageBox. The
88 * formatting therefore is not the greatest, but this is just a demo, not a
89 * finished product. :-) gt
91 * NOTE: The value returned by this function is for temporary use only and
92 * should be copied for long term use
94 char *GetExtendedDBErrorMsg(char *ErrFile
, int ErrLine
)
100 if (ErrFile
|| ErrLine
)
105 tStr
.Printf("%d",ErrLine
);
110 msg
.Append ("\nODBC errors:\n");
113 /* Scan through each database connection displaying
114 * any ODBC errors that have occured. */
116 for (pDbList
= PtrBegDbList
; pDbList
; pDbList
= pDbList
->PtrNext
)
118 // Skip over any free connections
121 // Display errors for this connection
123 for (i
= 0; i
< DB_MAX_ERROR_HISTORY
; i
++)
125 if (pDbList
->PtrDb
->errorList
[i
])
127 msg
.Append(pDbList
->PtrDb
->errorList
[i
]);
128 if (wxStrcmp(pDbList
->PtrDb
->errorList
[i
],"") != 0)
135 return (char*) (const char*) msg
;
136 } // GetExtendedDBErrorMsg
139 bool DatabaseDemoApp::OnInit()
141 // Create the main frame window
142 DemoFrame
= new DatabaseDemoFrame(NULL
, "wxWindows Database Demo", wxPoint(50, 50), wxSize(537, 480));
145 DemoFrame
->SetIcon(wxICON(db
));
148 wxMenu
*file_menu
= new wxMenu
;
149 file_menu
->Append(FILE_CREATE
, "&Create contact table");
150 file_menu
->Append(FILE_EXIT
, "E&xit");
152 wxMenu
*edit_menu
= new wxMenu
;
153 edit_menu
->Append(EDIT_PARAMETERS
, "&Parameters...");
155 wxMenu
*about_menu
= new wxMenu
;
156 about_menu
->Append(ABOUT_DEMO
, "&About");
158 wxMenuBar
*menu_bar
= new wxMenuBar
;
159 menu_bar
->Append(file_menu
, "&File");
160 menu_bar
->Append(edit_menu
, "&Edit");
161 menu_bar
->Append(about_menu
, "&About");
162 DemoFrame
->SetMenuBar(menu_bar
);
164 // Initialize the ODBC Environment for Database Operations
165 if (SQLAllocEnv(&DbConnectInf
.Henv
) != SQL_SUCCESS
)
167 wxMessageBox("A problem occured while trying to get a connection to the data source","DB CONNECTION ERROR",wxOK
| wxICON_EXCLAMATION
);
171 params
.ODBCSource
[0] = 0;
172 params
.UserName
[0] = 0;
173 params
.Password
[0] = 0;
174 params
.DirPath
[0] = 0;
177 if ((paramFile
= fopen(paramFilename
, "r")) == NULL
)
180 tStr
.Printf("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.",paramFilename
);
181 wxMessageBox(tStr
,"File I/O Error...",wxOK
| wxICON_EXCLAMATION
);
183 DemoFrame
->BuildParameterDialog(NULL
);
184 if ((paramFile
= fopen(paramFilename
, "r")) == NULL
)
189 fgets(buffer
, sizeof(params
.ODBCSource
), paramFile
);
190 buffer
[wxStrlen(buffer
)-1] = '\0';
191 wxStrcpy(params
.ODBCSource
,buffer
);
193 fgets(buffer
, sizeof(params
.UserName
), paramFile
);
194 buffer
[wxStrlen(buffer
)-1] = '\0';
195 wxStrcpy(params
.UserName
,buffer
);
197 fgets(buffer
, sizeof(params
.Password
), paramFile
);
198 buffer
[wxStrlen(buffer
)-1] = '\0';
199 wxStrcpy(params
.Password
,buffer
);
201 fgets(buffer
, sizeof(params
.DirPath
), paramFile
);
202 buffer
[wxStrlen(buffer
)-1] = '\0';
203 wxStrcpy(params
.DirPath
,buffer
);
207 // Connect to datasource
208 wxStrcpy(DbConnectInf
.Dsn
, params
.ODBCSource
); // ODBC data source name (created with ODBC Administrator under Win95/NT)
209 wxStrcpy(DbConnectInf
.Uid
, params
.UserName
); // database username - must already exist in the data source
210 wxStrcpy(DbConnectInf
.AuthStr
, params
.Password
); // password database username
211 wxStrcpy(DbConnectInf
.defaultDir
, params
.DirPath
); // path where the table exists (needed for dBase)
213 READONLY_DB
= wxDbGetConnection(&DbConnectInf
);
214 if (READONLY_DB
== 0)
216 wxMessageBox("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)", "DB CONNECTION ERROR...",wxOK
| wxICON_EXCLAMATION
);
217 DemoFrame
->BuildParameterDialog(NULL
);
218 wxStrcpy(DbConnectInf
.Dsn
, "");
219 wxStrcpy(DbConnectInf
.Uid
, "");
220 wxStrcpy(DbConnectInf
.AuthStr
, "");
221 wxMessageBox("Now exiting program.\n\nRestart program to try any new settings.","Notice...",wxOK
| wxICON_INFORMATION
);
225 DemoFrame
->BuildEditorDialog();
228 DemoFrame
->Show(TRUE
);
231 } // DatabaseDemoApp::OnInit()
233 BEGIN_EVENT_TABLE(DatabaseDemoFrame
, wxFrame
)
234 EVT_MENU(FILE_CREATE
, DatabaseDemoFrame::OnCreate
)
235 EVT_MENU(FILE_EXIT
, DatabaseDemoFrame::OnExit
)
236 EVT_MENU(EDIT_PARAMETERS
, DatabaseDemoFrame::OnEditParameters
)
237 EVT_MENU(ABOUT_DEMO
, DatabaseDemoFrame::OnAbout
)
238 EVT_CLOSE(DatabaseDemoFrame::OnCloseWindow
)
241 // DatabaseDemoFrame constructor
242 DatabaseDemoFrame::DatabaseDemoFrame(wxFrame
*frame
, const wxString
& title
,
243 const wxPoint
& pos
, const wxSize
& size
):
244 wxFrame(frame
, -1, title
, pos
, size
)
246 // Put any code in necessary for initializing the main frame here
249 void DatabaseDemoFrame::OnCreate(wxCommandEvent
& event
)
254 void DatabaseDemoFrame::OnExit(wxCommandEvent
& event
)
259 void DatabaseDemoFrame::OnEditParameters(wxCommandEvent
& event
)
261 if ((pEditorDlg
->mode
!= mCreate
) && (pEditorDlg
->mode
!= mEdit
))
262 BuildParameterDialog(this);
264 wxMessageBox("Cannot change database parameters while creating or editing a record","Notice...",wxOK
| wxICON_INFORMATION
);
267 void DatabaseDemoFrame::OnAbout(wxCommandEvent
& event
)
269 wxMessageBox("wxWindows sample program for database classes\n\nContributed on 27 July 1998","About...",wxOK
| wxICON_INFORMATION
);
272 void DatabaseDemoFrame::OnCloseWindow(wxCloseEvent
& event
)
274 // Put any additional checking necessary to make certain it is alright
275 // to close the program here that is not done elsewhere
278 if (pEditorDlg
->Close())
286 // Cleans up the environment space allocated for the SQL/ODBC connection handle
287 SQLFreeEnv(DbConnectInf
.Henv
);
291 } // DatabaseDemoFrame::OnCloseWindow()
294 void DatabaseDemoFrame::CreateDataTable()
296 bool Ok
= (wxMessageBox("Any data currently residing in the table will be erased.\n\nAre you sure?","Confirm",wxYES_NO
|wxICON_QUESTION
) == wxYES
);
305 Ccontact
*Contact
= new Ccontact();
309 wxMessageBox("Error allocating memory for 'Ccontact'object.\n\nTable was not created.","Error...",wxOK
| wxICON_EXCLAMATION
);
313 if (!Contact
->CreateTable(FALSE
))
317 tStr
= "Error creating CONTACTS table.\nTable was not created.\n\n";
318 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
319 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
324 if (!Contact
->CreateIndexes())
328 tStr
= "Error creating CONTACTS indexes.\nIndexes will be unavailable.\n\n";
329 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
330 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
340 wxMessageBox("Table and index(es) were successfully created.","Notice...",wxOK
| wxICON_INFORMATION
);
341 } // DatabaseDemoFrame::CreateDataTable()
344 void DatabaseDemoFrame::BuildEditorDialog()
346 pEditorDlg
= new CeditorDlg(this);
348 wxMessageBox("Unable to create the editor dialog for some reason","Error...",wxOK
| wxICON_EXCLAMATION
);
349 } // DatabaseDemoFrame::BuildEditorDialog()
352 void DatabaseDemoFrame::BuildParameterDialog(wxWindow
*parent
)
354 pParamDlg
= new CparameterDlg(parent
);
357 wxMessageBox("Unable to create the parameter dialog for some reason","Error...",wxOK
| wxICON_EXCLAMATION
);
358 } // DatabaseDemoFrame::BuildParameterDialog()
362 * Constructor note: If no wxDb object is passed in, a new connection to the database
363 * is created for this instance of Ccontact. This can be a slow process depending
364 * on the database engine being used, and some database engines have a limit on the
365 * number of connections (either hard limits, or license restricted) so care should
366 * be used to use as few connections as is necessary.
368 * IMPORTANT: Objects which share a wxDb pointer are ALL acted upon whenever a member
369 * function of pDb is called (i.e. CommitTrans() or RollbackTrans(), so if modifying
370 * or creating a table objects which use the same pDb, know that all the objects
371 * will be committed or rolled back when any of the objects has this function call made.
373 Ccontact::Ccontact (wxDb
*pwxDb
) : wxDbTable(pwxDb
? pwxDb
: wxDbGetConnection(&DbConnectInf
),CONTACT_TABLE_NAME
,CONTACT_NO_COLS
,NULL
,!wxDB_QUERY_ONLY
,DbConnectInf
.defaultDir
)
375 // This is used to represent whether the database connection should be released
376 // when this instance of the object is deleted. If using the same connection
377 // for multiple instance of database objects, then the connection should only be
378 // released when the last database instance using the connection is deleted
383 } // Ccontact Constructor
386 void Ccontact::Initialize()
395 JoinDate
.year
= 1980;
401 JoinDate
.fraction
= 0;
402 NativeLanguage
= langENGLISH
;
406 } // Ccontact::Initialize
409 Ccontact::~Ccontact()
413 if (!wxDbFreeConnection(GetDb()))
416 tStr
= "Unable to Free the Ccontact data table handle\n\n";
417 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
418 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
421 } // Ccontract destructor
425 * Handles setting up all the connections for the interface from the wxDbTable
426 * functions to interface to the data structure used to store records in
427 * memory, and for all the column definitions that define the table structure
429 void Ccontact::SetupColumns()
431 // NOTE: Columns now are 8 character names, as that is all dBase can support. Longer
432 // names can be used for other database engines
433 SetColDefs ( 0,"NAME", DB_DATA_TYPE_VARCHAR
, Name
, SQL_C_CHAR
, sizeof(Name
), TRUE
, TRUE
); // Primary index
434 SetColDefs ( 1,"ADDRESS1", DB_DATA_TYPE_VARCHAR
, Addr1
, SQL_C_CHAR
, sizeof(Addr1
), FALSE
,TRUE
);
435 SetColDefs ( 2,"ADDRESS2", DB_DATA_TYPE_VARCHAR
, Addr2
, SQL_C_CHAR
, sizeof(Addr2
), FALSE
,TRUE
);
436 SetColDefs ( 3,"CITY", DB_DATA_TYPE_VARCHAR
, City
, SQL_C_CHAR
, sizeof(City
), FALSE
,TRUE
);
437 SetColDefs ( 4,"STATE", DB_DATA_TYPE_VARCHAR
, State
, SQL_C_CHAR
, sizeof(State
), FALSE
,TRUE
);
438 SetColDefs ( 5,"POSTCODE", DB_DATA_TYPE_VARCHAR
, PostalCode
, SQL_C_CHAR
, sizeof(PostalCode
), FALSE
,TRUE
);
439 SetColDefs ( 6,"COUNTRY", DB_DATA_TYPE_VARCHAR
, Country
, SQL_C_CHAR
, sizeof(Country
), FALSE
,TRUE
);
440 SetColDefs ( 7,"JOINDATE", DB_DATA_TYPE_DATE
, &JoinDate
, SQL_C_TIMESTAMP
, sizeof(JoinDate
), FALSE
,TRUE
);
441 SetColDefs ( 8,"IS_DEV", DB_DATA_TYPE_INTEGER
, &IsDeveloper
, SQL_C_BOOLEAN(IsDeveloper
), sizeof(IsDeveloper
), FALSE
,TRUE
);
442 SetColDefs ( 9,"CONTRIBS", DB_DATA_TYPE_INTEGER
, &Contributions
, SQL_C_USHORT
, sizeof(Contributions
), FALSE
,TRUE
);
443 SetColDefs (10,"LINE_CNT", DB_DATA_TYPE_INTEGER
, &LinesOfCode
, SQL_C_ULONG
, sizeof(LinesOfCode
), FALSE
,TRUE
);
444 SetColDefs (11,"LANGUAGE", DB_DATA_TYPE_INTEGER
, &NativeLanguage
, SQL_C_ENUM
, sizeof(NativeLanguage
), FALSE
,TRUE
);
445 } // Ccontact::SetupColumns
448 bool Ccontact::CreateIndexes(void)
450 // This index could easily be accomplished with an "orderBy" clause,
451 // but is done to show how to construct a non-primary index.
453 wxDbIdxDef idxDef
[2];
457 wxStrcpy(idxDef
[0].ColName
, "IS_DEV");
458 idxDef
[0].Ascending
= TRUE
;
460 wxStrcpy(idxDef
[1].ColName
, "NAME");
461 idxDef
[1].Ascending
= TRUE
;
463 indexName
= GetTableName();
464 indexName
+= "_IDX1";
465 Ok
= CreateIndex(indexName
.c_str(), TRUE
, 2, idxDef
);
468 } // Ccontact::CreateIndexes()
472 * Having a function to do a query on the primary key (and possibly others) is
473 * very efficient and tighter coding so that it is available where ever the object
474 * is. Great for use with multiple tables when not using views or outer joins
476 bool Ccontact::FetchByName(char *name
)
478 whereStr
.Printf("NAME = '%s'",name
);
479 SetWhereClause(whereStr
.c_str());
480 SetOrderByClause("");
488 } // Ccontact::FetchByName()
493 * ************* DIALOGS ***************
498 /* CeditorDlg constructor
500 * Creates the dialog used for creating/editing/deleting/copying a Ccontact object.
501 * This dialog actually is drawn in the main frame of the program
503 * An instance of Ccontact is created - "Contact" - which is used to hold the Ccontact
504 * object that is currently being worked with.
507 BEGIN_EVENT_TABLE(CeditorDlg
, wxPanel
)
508 EVT_BUTTON(-1, CeditorDlg::OnButton
)
509 EVT_CLOSE(CeditorDlg::OnCloseWindow
)
512 CeditorDlg::CeditorDlg(wxWindow
*parent
) : wxPanel (parent
, 1, 1, 460, 455)
514 // Since the ::OnCommand() function is overridden, this prevents the widget
515 // detection in ::OnCommand() until all widgets have been initialized to prevent
516 // uninitialized pointers from crashing the program
517 widgetPtrsSet
= FALSE
;
519 // Create the data structure and a new database connection.
520 // (As there is not a pDb being passed in the constructor, a new database
521 // connection is created)
522 Contact
= new Ccontact();
526 wxMessageBox("Unable to instantiate an instance of Ccontact","Error...",wxOK
| wxICON_EXCLAMATION
);
530 // Check if the table exists or not. If it doesn't, ask the user if they want to
531 // create the table. Continue trying to create the table until it exists, or user aborts
532 while (!Contact
->GetDb()->TableExists((char *)CONTACT_TABLE_NAME
,DbConnectInf
.Uid
,DbConnectInf
.defaultDir
))
535 tStr
.Printf("Unable to open the table '%s'.\n\nTable may need to be created...?\n\n",CONTACT_TABLE_NAME
);
536 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
537 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
539 bool createTable
= (wxMessageBox("Do you wish to try to create/clear the CONTACTS table?","Confirm",wxYES_NO
|wxICON_QUESTION
) == wxYES
);
549 DemoFrame
->CreateDataTable();
552 // Tables must be "opened" before anything other than creating/deleting table can be done
553 if (!Contact
->Open())
555 // Table does exist, there was some problem opening it. Currently this should
556 // never fail, except in the case of the table not exisiting. Open() basically
557 // only sets up variable/pointer values, other than checking for table existence.
558 if (Contact
->GetDb()->TableExists((char *)CONTACT_TABLE_NAME
))
561 tStr
.Printf("Unable to open the table '%s'.\n\n",CONTACT_TABLE_NAME
);
562 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
563 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
573 (void)new wxStaticBox(this, EDITOR_DIALOG_FN_GROUP
, "", wxPoint(15, 1), wxSize(497, 69), 0, "FunctionGrp");
574 (void)new wxStaticBox(this, EDITOR_DIALOG_SEARCH_GROUP
, "", wxPoint(417, 1), wxSize(95, 242), 0, "SearchGrp");
576 pCreateBtn
= new wxButton(this, EDITOR_DIALOG_CREATE
, "&Create", wxPoint( 25, 21), wxSize( 70, 35), 0, wxDefaultValidator
, "CreateBtn");
577 pEditBtn
= new wxButton(this, EDITOR_DIALOG_EDIT
, "&Edit", wxPoint(102, 21), wxSize( 70, 35), 0, wxDefaultValidator
, "EditBtn");
578 pDeleteBtn
= new wxButton(this, EDITOR_DIALOG_DELETE
, "&Delete", wxPoint(179, 21), wxSize( 70, 35), 0, wxDefaultValidator
, "DeleteBtn");
579 pCopyBtn
= new wxButton(this, EDITOR_DIALOG_COPY
, "Cop&y", wxPoint(256, 21), wxSize( 70, 35), 0, wxDefaultValidator
, "CopyBtn");
580 pSaveBtn
= new wxButton(this, EDITOR_DIALOG_SAVE
, "&Save", wxPoint(333, 21), wxSize( 70, 35), 0, wxDefaultValidator
, "SaveBtn");
581 pCancelBtn
= new wxButton(this, EDITOR_DIALOG_CANCEL
, "C&ancel", wxPoint(430, 21), wxSize( 70, 35), 0, wxDefaultValidator
, "CancelBtn");
582 pPrevBtn
= new wxButton(this, EDITOR_DIALOG_PREV
, "<< &Prev", wxPoint(430, 81), wxSize( 70, 35), 0, wxDefaultValidator
, "PrevBtn");
583 pNextBtn
= new wxButton(this, EDITOR_DIALOG_NEXT
, "&Next >>", wxPoint(430, 121), wxSize( 70, 35), 0, wxDefaultValidator
, "NextBtn");
584 pQueryBtn
= new wxButton(this, EDITOR_DIALOG_QUERY
, "&Query", wxPoint(430, 161), wxSize( 70, 35), 0, wxDefaultValidator
, "QueryBtn");
585 pResetBtn
= new wxButton(this, EDITOR_DIALOG_RESET
, "&Reset", wxPoint(430, 200), wxSize( 70, 35), 0, wxDefaultValidator
, "ResetBtn");
586 pNameMsg
= new wxStaticText(this, EDITOR_DIALOG_NAME_MSG
, "Name:", wxPoint( 17, 80), wxSize( -1, -1), 0, "NameMsg");
587 pNameTxt
= new wxTextCtrl(this, EDITOR_DIALOG_NAME_TEXT
, "", wxPoint( 17, 97), wxSize(308, 25), 0, wxDefaultValidator
, "NameTxt");
588 pNameListBtn
= new wxButton(this, EDITOR_DIALOG_LOOKUP
, "&Lookup", wxPoint(333, 97), wxSize( 70, 24), 0, wxDefaultValidator
, "LookupBtn");
589 pAddress1Msg
= new wxStaticText(this, EDITOR_DIALOG_ADDRESS1_MSG
, "Address:", wxPoint( 17, 130), wxSize( -1, -1), 0, "Address1Msg");
590 pAddress1Txt
= new wxTextCtrl(this, EDITOR_DIALOG_ADDRESS2_TEXT
, "", wxPoint( 17, 147), wxSize(308, 25), 0, wxDefaultValidator
, "Address1Txt");
591 pAddress2Msg
= new wxStaticText(this, EDITOR_DIALOG_ADDRESS2_MSG
, "Address:", wxPoint( 17, 180), wxSize( -1, -1), 0, "Address2Msg");
592 pAddress2Txt
= new wxTextCtrl(this, EDITOR_DIALOG_ADDRESS2_TEXT
, "", wxPoint( 17, 197), wxSize(308, 25), 0, wxDefaultValidator
, "Address2Txt");
593 pCityMsg
= new wxStaticText(this, EDITOR_DIALOG_CITY_MSG
, "City:", wxPoint( 17, 230), wxSize( -1, -1), 0, "CityMsg");
594 pCityTxt
= new wxTextCtrl(this, EDITOR_DIALOG_CITY_TEXT
, "", wxPoint( 17, 247), wxSize(225, 25), 0, wxDefaultValidator
, "CityTxt");
595 pStateMsg
= new wxStaticText(this, EDITOR_DIALOG_STATE_MSG
, "State:", wxPoint(250, 230), wxSize( -1, -1), 0, "StateMsg");
596 pStateTxt
= new wxTextCtrl(this, EDITOR_DIALOG_STATE_TEXT
, "", wxPoint(250, 247), wxSize(153, 25), 0, wxDefaultValidator
, "StateTxt");
597 pCountryMsg
= new wxStaticText(this, EDITOR_DIALOG_COUNTRY_MSG
, "Country:", wxPoint( 17, 280), wxSize( -1, -1), 0, "CountryMsg");
598 pCountryTxt
= new wxTextCtrl(this, EDITOR_DIALOG_COUNTRY_TEXT
, "", wxPoint( 17, 297), wxSize(225, 25), 0, wxDefaultValidator
, "CountryTxt");
599 pPostalCodeMsg
= new wxStaticText(this, EDITOR_DIALOG_POSTAL_MSG
, "Postal Code:",wxPoint(250, 280), wxSize( -1, -1), 0, "PostalCodeMsg");
600 pPostalCodeTxt
= new wxTextCtrl(this, EDITOR_DIALOG_POSTAL_TEXT
, "", wxPoint(250, 297), wxSize(153, 25), 0, wxDefaultValidator
, "PostalCodeTxt");
602 wxString choice_strings
[5];
603 choice_strings
[0] = "English";
604 choice_strings
[1] = "French";
605 choice_strings
[2] = "German";
606 choice_strings
[3] = "Spanish";
607 choice_strings
[4] = "Other";
609 pNativeLangChoice
= new wxChoice(this, EDITOR_DIALOG_LANG_CHOICE
, wxPoint( 17, 346), wxSize(277, -1), 5, choice_strings
);
610 pNativeLangMsg
= new wxStaticText(this, EDITOR_DIALOG_LANG_MSG
, "Native language:", wxPoint( 17, 330), wxSize( -1, -1), 0, "NativeLangMsg");
612 wxString radio_strings
[2];
613 radio_strings
[0] = "No";
614 radio_strings
[1] = "Yes";
615 pDeveloperRadio
= new wxRadioBox(this,EDITOR_DIALOG_DEVELOPER
, "Developer:", wxPoint(303, 330), wxSize( -1, -1), 2, radio_strings
, 2, wxHORIZONTAL
);
616 pJoinDateMsg
= new wxStaticText(this, EDITOR_DIALOG_JOIN_MSG
, "Date joined:", wxPoint( 17, 380), wxSize( -1, -1), 0, "JoinDateMsg");
617 pJoinDateTxt
= new wxTextCtrl(this, EDITOR_DIALOG_JOIN_TEXT
, "", wxPoint( 17, 397), wxSize(150, 25), 0, wxDefaultValidator
, "JoinDateTxt");
618 pContribMsg
= new wxStaticText(this, EDITOR_DIALOG_CONTRIB_MSG
,"Contributions:", wxPoint(175, 380), wxSize( -1, -1), 0, "ContribMsg");
619 pContribTxt
= new wxTextCtrl(this, EDITOR_DIALOG_CONTRIB_TEXT
, "", wxPoint(175, 397), wxSize(120, 25), 0, wxDefaultValidator
, "ContribTxt");
620 pLinesMsg
= new wxStaticText(this, EDITOR_DIALOG_LINES_MSG
, "Lines of code:", wxPoint(303, 380), wxSize( -1, -1), 0, "LinesMsg");
621 pLinesTxt
= new wxTextCtrl(this, EDITOR_DIALOG_LINES_TEXT
, "", wxPoint(303, 397), wxSize(100, 25), 0, wxDefaultValidator
, "LinesTxt");
623 // Now that all the widgets on the panel are created, its safe to allow ::OnCommand() to
624 // handle all widget processing
625 widgetPtrsSet
= TRUE
;
627 // Setup the orderBy and where clauses to return back a single record as the result set,
628 // as there will only be one record being shown on the dialog at a time, this optimizes
629 // network traffic by only returning a one row result
631 Contact
->SetOrderByClause("NAME"); // field name to sort by
633 // The wxString "whereStr" is not a member of the wxDbTable object, it is a member variable
634 // specifically in the Ccontact class. It is used here for simpler construction of a varying
635 // length string, and then after the string is built, the wxDbTable member variable "where" is
636 // assigned the pointer to the constructed string.
638 // The constructed where clause below has a sub-query within it "SELECT MIN(NAME) FROM %s"
639 // to achieve a single row (in this case the first name in alphabetical order).
641 if (Contact
->GetDb()->Dbms() != dbmsPOSTGRES
)
643 Contact
->whereStr
.sprintf("NAME = (SELECT MIN(NAME) FROM %s)",Contact
->GetTableName());
644 // NOTE: (const char*) returns a pointer which may not be valid later, so this is short term use only
645 Contact
->SetWhereClause(Contact
->whereStr
.c_str());
648 Contact
->SetWhereClause("");
650 // Perform the Query to get the result set.
651 // NOTE: If there are no rows returned, that is a valid result, so Query() would return TRUE.
652 // Only if there is a database error will Query() come back as FALSE
653 if (!Contact
->Query())
656 tStr
= "ODBC error during Query()\n\n";
657 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
658 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
659 GetParent()->Close();
663 // Since Query succeeded, now get the row that was returned
664 if (!Contact
->GetNext())
665 // If the GetNext() failed at this point, then there are no rows to retrieve,
666 // so clear the values in the members of "Contact" so that PutData() blanks the
667 // widgets on the dialog
668 Contact
->Initialize();
674 } // CeditorDlg constructor
677 void CeditorDlg::OnCloseWindow(wxCloseEvent
& event
)
680 if ((mode
!= mCreate
) && (mode
!= mEdit
))
688 wxMessageBox("Must finish processing the current record being created/modified before exiting","Notice...",wxOK
| wxICON_INFORMATION
);
691 } // CeditorDlg::OnCloseWindow()
694 void CeditorDlg::OnButton( wxCommandEvent
&event
)
696 wxWindow
*win
= (wxWindow
*) event
.GetEventObject();
697 OnCommand( *win
, event
);
701 void CeditorDlg::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
705 widgetName
= win
.GetName();
710 if (widgetName
== pCreateBtn
->GetName())
712 Contact
->Initialize();
715 pNameTxt
->SetValue("");
716 pNameTxt
->SetFocus();
720 if (widgetName
== pEditBtn
->GetName())
722 saveName
= Contact
->Name
;
724 pNameTxt
->SetFocus();
728 if (widgetName
== pCopyBtn
->GetName())
731 pNameTxt
->SetValue("");
732 pNameTxt
->SetFocus();
737 if (widgetName
== pDeleteBtn
->GetName())
739 bool Ok
= (wxMessageBox("Are you sure?","Confirm",wxYES_NO
|wxICON_QUESTION
) == wxYES
);
744 if (Ok
&& Contact
->Delete())
746 // NOTE: Deletions are not finalized until a CommitTrans() is performed.
747 // If the commit were not performed, the program will continue to
748 // show the table contents as if they were deleted until this instance
749 // of Ccontact is deleted. If the Commit wasn't performed, the
750 // database will automatically Rollback the changes when the database
751 // connection is terminated
752 Contact
->GetDb()->CommitTrans();
754 // Try to get the row that followed the just deleted row in the orderBy sequence
757 // There was now row (in sequence) after the just deleted row, so get the
758 // row which preceded the just deleted row
761 // There are now no rows remaining, so clear the dialog widgets
762 Contact
->Initialize();
766 SetMode(mode
); // force reset of button enable/disable
770 Contact
->GetDb()->RollbackTrans();
776 if (widgetName
== pSaveBtn
->GetName())
782 if (widgetName
== pCancelBtn
->GetName())
784 bool Ok
= (wxMessageBox("Are you sure?","Confirm",wxYES_NO
|wxICON_QUESTION
) == wxYES
);
789 if (!wxStrcmp((const char*) saveName
,""))
791 Contact
->Initialize();
798 // Requery previous record
799 if (Contact
->FetchByName((char*) (const char*) saveName
))
807 // Previous record not available, retrieve first record in table
808 if (Contact
->GetDb()->Dbms() != dbmsPOSTGRES
)
810 Contact
->whereStr
= "NAME = (SELECT MIN(NAME) FROM ";
811 Contact
->whereStr
+= Contact
->GetTableName();
812 Contact
->whereStr
+= ")";
813 Contact
->SetWhereClause(Contact
->whereStr
.c_str());
816 Contact
->SetWhereClause("");
818 if (!Contact
->Query())
821 tStr
= "ODBC error during Query()\n\n";
822 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
823 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
827 if (Contact
->GetNext()) // Successfully read first record
833 // No contacts are available, clear dialog
834 Contact
->Initialize();
840 if (widgetName
== pPrevBtn
->GetName())
847 if (widgetName
== pNextBtn
->GetName())
854 if (widgetName
== pQueryBtn
->GetName())
856 // Display the query dialog box
857 char qryWhere
[DB_MAX_WHERE_CLAUSE_LEN
+1];
858 wxStrcpy(qryWhere
, (const char*) Contact
->qryWhereStr
);
859 char *tblName
[] = {(char *)CONTACT_TABLE_NAME
, 0};
860 new CqueryDlg(GetParent(), Contact
->GetDb(), tblName
, qryWhere
);
862 // Query the first record in the new record set and
863 // display it, if the query string has changed.
864 if (wxStrcmp(qryWhere
, (const char*) Contact
->qryWhereStr
))
867 Contact
->whereStr
= "";
868 Contact
->SetOrderByClause("NAME");
870 if (Contact
->GetDb()->Dbms() != dbmsPOSTGRES
)
872 Contact
->whereStr
= "NAME = (SELECT MIN(NAME) FROM ";
873 Contact
->whereStr
+= CONTACT_TABLE_NAME
;
876 // Append the query where string (if there is one)
877 Contact
->qryWhereStr
= qryWhere
;
878 if (wxStrlen(qryWhere
))
880 Contact
->whereStr
+= " WHERE ";
881 Contact
->whereStr
+= Contact
->qryWhereStr
;
883 // Close the expression with a right paren
884 Contact
->whereStr
+= ")";
886 Contact
->SetWhereClause(Contact
->whereStr
.c_str());
887 if (!Contact
->Query())
890 tStr
= "ODBC error during Query()\n\n";
891 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
892 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
895 // Display the first record from the query set
896 if (!Contact
->GetNext())
897 Contact
->Initialize();
901 // Enable/Disable the reset button
902 pResetBtn
->Enable(!Contact
->qryWhereStr
.IsEmpty());
908 if (widgetName
== pResetBtn
->GetName())
910 // Clear the additional where criteria established by the query feature
911 Contact
->qryWhereStr
= "";
912 Contact
->SetOrderByClause("NAME");
914 if (Contact
->GetDb()->Dbms() != dbmsPOSTGRES
)
916 Contact
->whereStr
= "NAME = (SELECT MIN(NAME) FROM ";
917 Contact
->whereStr
+= CONTACT_TABLE_NAME
;
918 Contact
->whereStr
+= ")";
921 Contact
->SetWhereClause(Contact
->whereStr
.c_str());
922 if (!Contact
->Query())
925 tStr
= "ODBC error during Query()\n\n";
926 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
927 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
930 if (!Contact
->GetNext())
931 Contact
->Initialize();
933 pResetBtn
->Enable(FALSE
);
939 if (widgetName
== pNameListBtn
->GetName())
941 new ClookUpDlg(/* wxWindow *parent */ this,
942 /* char *windowTitle */ "Select contact name",
943 /* char *tableName */ (char *) CONTACT_TABLE_NAME
,
944 /* char *dispCol1 */ "NAME",
945 /* char *dispCol2 */ "JOINDATE",
946 /* char *where */ "",
947 /* char *orderBy */ "NAME",
948 /* bool distinctValues */ TRUE
);
950 if (ListDB_Selection
&& wxStrlen(ListDB_Selection
))
952 wxString w
= "NAME = '";
953 w
+= ListDB_Selection
;
955 GetRec((char*) (const char*) w
);
961 } // CeditorDlg::OnCommand()
964 void CeditorDlg::FieldsEditable()
966 pNameTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
967 pAddress1Txt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
968 pAddress2Txt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
969 pCityTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
970 pStateTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
971 pPostalCodeTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
972 pCountryTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
974 pJoinDateTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
975 pContribTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
976 pLinesTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
977 pNativeLangChoice
->Enable((mode
== mCreate
) || (mode
== mEdit
));
978 pDeveloperRadio
->Enable((mode
== mCreate
) || (mode
== mEdit
));
980 } // CeditorDlg::FieldsEditable()
983 void CeditorDlg::SetMode(enum DialogModes m
)
1004 pCreateBtn
->Enable( !edit
);
1005 pEditBtn
->Enable( !edit
&& (wxStrcmp(Contact
->Name
,"")!=0) );
1006 pDeleteBtn
->Enable( !edit
&& (wxStrcmp(Contact
->Name
,"")!=0) );
1007 pCopyBtn
->Enable( !edit
&& (wxStrcmp(Contact
->Name
,"")!=0) );
1008 pSaveBtn
->Enable( edit
);
1009 pCancelBtn
->Enable( edit
);
1010 pPrevBtn
->Enable( !edit
);
1011 pNextBtn
->Enable( !edit
);
1012 pQueryBtn
->Enable( !edit
);
1013 pResetBtn
->Enable( !edit
&& !Contact
->qryWhereStr
.IsEmpty() );
1014 pNameListBtn
->Enable( !edit
);
1018 } // CeditorDlg::SetMode()
1021 bool CeditorDlg::PutData()
1025 pNameTxt
->SetValue(Contact
->Name
);
1026 pAddress1Txt
->SetValue(Contact
->Addr1
);
1027 pAddress2Txt
->SetValue(Contact
->Addr2
);
1028 pCityTxt
->SetValue(Contact
->City
);
1029 pStateTxt
->SetValue(Contact
->State
);
1030 pCountryTxt
->SetValue(Contact
->Country
);
1031 pPostalCodeTxt
->SetValue(Contact
->PostalCode
);
1033 tStr
.Printf("%d/%d/%d",Contact
->JoinDate
.month
,Contact
->JoinDate
.day
,Contact
->JoinDate
.year
);
1034 pJoinDateTxt
->SetValue(tStr
);
1036 tStr
.Printf("%d",Contact
->Contributions
);
1037 pContribTxt
->SetValue(tStr
);
1039 tStr
.Printf("%lu",Contact
->LinesOfCode
);
1040 pLinesTxt
->SetValue(tStr
);
1042 pNativeLangChoice
->SetSelection(Contact
->NativeLanguage
);
1044 pDeveloperRadio
->SetSelection(Contact
->IsDeveloper
);
1047 } // Ceditor::PutData()
1051 * Reads the data out of all the widgets on the dialog. Some data evaluation is done
1052 * to ensure that there is a name entered and that the date field is valid.
1054 * A return value of TRUE means that valid data was retrieved from the dialog, otherwise
1055 * invalid data was found (and a message was displayed telling the user what to fix), and
1056 * the data was not placed into the appropraite fields of Ccontact
1058 bool CeditorDlg::GetData()
1060 // Validate that the data currently entered into the widgets is valid data
1063 tStr
= pNameTxt
->GetValue();
1064 if (!wxStrcmp((const char*) tStr
,""))
1066 wxMessageBox("A name is required for entry into the contact table","Notice...",wxOK
| wxICON_INFORMATION
);
1070 bool invalid
= FALSE
;
1074 tStr
= pJoinDateTxt
->GetValue();
1075 if (tStr
.Freq('/') != 2)
1078 // Find the month, day, and year tokens
1081 first
= tStr
.First('/');
1082 second
= tStr
.Last('/');
1084 mm
= atoi(tStr
.SubString(0,first
));
1085 dd
= atoi(tStr
.SubString(first
+1,second
));
1086 yyyy
= atoi(tStr
.SubString(second
+1,tStr
.Length()-1));
1088 invalid
= !(mm
&& dd
&& yyyy
);
1091 // Force Year 2000 compliance
1092 if (!invalid
&& (yyyy
< 1000))
1095 // Check the token ranges for validity
1100 else if ((mm
< 1) || (mm
> 12))
1108 int days
[12] = {31,28,31,30,31,30,
1110 if (dd
> days
[mm
-1])
1113 if ((dd
== 29) && (mm
== 2))
1115 if (((yyyy
% 4) == 0) && (((yyyy
% 100) != 0) || ((yyyy
% 400) == 0)))
1125 Contact
->JoinDate
.month
= mm
;
1126 Contact
->JoinDate
.day
= dd
;
1127 Contact
->JoinDate
.year
= yyyy
;
1131 wxMessageBox("Improper date format. Please check the date\nspecified and try again.\n\nNOTE: Dates are in american format (MM/DD/YYYY)","Notice...",wxOK
| wxICON_INFORMATION
);
1135 tStr
= pNameTxt
->GetValue();
1136 wxStrcpy(Contact
->Name
,(const char*) tStr
);
1137 wxStrcpy(Contact
->Addr1
,pAddress1Txt
->GetValue());
1138 wxStrcpy(Contact
->Addr2
,pAddress2Txt
->GetValue());
1139 wxStrcpy(Contact
->City
,pCityTxt
->GetValue());
1140 wxStrcpy(Contact
->State
,pStateTxt
->GetValue());
1141 wxStrcpy(Contact
->Country
,pCountryTxt
->GetValue());
1142 wxStrcpy(Contact
->PostalCode
,pPostalCodeTxt
->GetValue());
1144 Contact
->Contributions
= atoi(pContribTxt
->GetValue());
1145 Contact
->LinesOfCode
= atol(pLinesTxt
->GetValue());
1147 Contact
->NativeLanguage
= (enum Language
) pNativeLangChoice
->GetSelection();
1148 Contact
->IsDeveloper
= pDeveloperRadio
->GetSelection() > 0;
1151 } // CeditorDlg::GetData()
1155 * Retrieve data from the dialog, verify the validity of the data, and if it is valid,
1156 * try to insert/update the data to the table based on the current 'mode' the dialog
1159 * A return value of TRUE means the insert/update was completed successfully, a return
1160 * value of FALSE means that Save() failed. If returning FALSE, then this function
1161 * has displayed a detailed error message for the user.
1163 bool CeditorDlg::Save()
1165 bool failed
= FALSE
;
1167 // Read the data in the widgets of the dialog to get the user's data
1171 // Perform any other required validations necessary before saving
1174 wxBeginBusyCursor();
1176 if (mode
== mCreate
)
1178 RETCODE result
= Contact
->Insert();
1180 failed
= (result
!= DB_SUCCESS
);
1183 // Some errors may be expected, like a duplicate key, so handle those instances with
1184 // specific error messages.
1185 if (result
== DB_ERR_INTEGRITY_CONSTRAINT_VIOL
)
1188 tStr
= "A duplicate key value already exists in the table.\nUnable to save record\n\n";
1189 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
1190 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
1194 // Some other unexpexted error occurred
1196 tStr
= "Database insert failed\n\n";
1197 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
1198 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
1202 else // mode == mEdit
1204 if (!Contact
->Update())
1207 tStr
= "Database update failed\n\n";
1208 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
1209 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
1216 Contact
->GetDb()->CommitTrans();
1217 SetMode(mView
); // Sets the dialog mode back to viewing after save is successful
1220 Contact
->GetDb()->RollbackTrans();
1226 } // CeditorDlg::Save()
1230 * Where this program is only showing a single row at a time in the dialog,
1231 * a special where clause must be built to find just the single row which,
1232 * in sequence, would follow the currently displayed row.
1234 bool CeditorDlg::GetNextRec()
1238 if (Contact
->GetDb()->Dbms() != dbmsPOSTGRES
)
1240 w
= "NAME = (SELECT MIN(NAME) FROM ";
1241 w
+= Contact
->GetTableName();
1242 w
+= " WHERE NAME > '";
1250 // If a query where string is currently set, append that criteria
1251 if (!Contact
->qryWhereStr
.IsEmpty())
1254 w
+= Contact
->qryWhereStr
;
1259 return(GetRec((char*) (const char*) w
));
1261 } // CeditorDlg::GetNextRec()
1265 * Where this program is only showing a single row at a time in the dialog,
1266 * a special where clause must be built to find just the single row which,
1267 * in sequence, would precede the currently displayed row.
1269 bool CeditorDlg::GetPrevRec()
1273 if (Contact
->GetDb()->Dbms() != dbmsPOSTGRES
)
1275 w
= "NAME = (SELECT MAX(NAME) FROM ";
1276 w
+= Contact
->GetTableName();
1277 w
+= " WHERE NAME < '";
1285 // If a query where string is currently set, append that criteria
1286 if (!Contact
->qryWhereStr
.IsEmpty())
1289 w
+= Contact
->qryWhereStr
;
1295 return(GetRec((char*) (const char*)w
));
1297 } // CeditorDlg::GetPrevRec()
1301 * This function is here to avoid duplicating this same code in both the
1302 * GetPrevRec() and GetNextRec() functions
1304 bool CeditorDlg::GetRec(char *whereStr
)
1306 Contact
->SetWhereClause(whereStr
);
1307 Contact
->SetOrderByClause("NAME");
1309 if (!Contact
->Query())
1312 tStr
= "ODBC error during Query()\n\n";
1313 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
1314 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
1319 if (Contact
->GetNext())
1326 } // CeditorDlg::GetRec()
1331 * CparameterDlg constructor
1334 BEGIN_EVENT_TABLE(CparameterDlg
, wxDialog
)
1335 EVT_BUTTON(PARAMETER_DIALOG_SAVE
, CparameterDlg::OnButton
)
1336 EVT_BUTTON(PARAMETER_DIALOG_CANCEL
, CparameterDlg::OnButton
)
1337 EVT_CLOSE(CparameterDlg::OnCloseWindow
)
1340 CparameterDlg::CparameterDlg(wxWindow
*parent
) : wxDialog (parent
, PARAMETER_DIALOG
, "ODBC parameter settings", wxPoint(-1, -1), wxSize(400, 325))
1342 // Since the ::OnCommand() function is overridden, this prevents the widget
1343 // detection in ::OnCommand() until all widgets have been initialized to prevent
1344 // uninitialized pointers from crashing the program
1345 widgetPtrsSet
= FALSE
;
1347 pParamODBCSourceMsg
= new wxStaticText(this, PARAMETER_DIALOG_SOURCE_MSG
, "ODBC data sources:", wxPoint( 10, 10), wxSize( -1, -1), 0, "ParamODBCSourceMsg");
1348 pParamODBCSourceList
= new wxListBox(this, PARAMETER_DIALOG_SOURCE_LISTBOX
, wxPoint( 10, 29), wxSize(285, 150), 0, 0, wxLB_SINGLE
|wxLB_ALWAYS_SB
, wxDefaultValidator
, "ParamODBCSourceList");
1349 pParamUserNameMsg
= new wxStaticText(this, PARAMETER_DIALOG_NAME_MSG
, "Database user name:", wxPoint( 10, 193), wxSize( -1, -1), 0, "ParamUserNameMsg");
1350 pParamUserNameTxt
= new wxTextCtrl(this, PARAMETER_DIALOG_NAME_TEXT
, "", wxPoint(10, 209), wxSize( 140, 25), 0, wxDefaultValidator
, "ParamUserNameTxt");
1351 pParamPasswordMsg
= new wxStaticText(this, PARAMETER_DIALOG_PASSWORD_MSG
, "Password:", wxPoint(156, 193), wxSize( -1, -1), 0, "ParamPasswordMsg");
1352 pParamPasswordTxt
= new wxTextCtrl(this, PARAMETER_DIALOG_PASSWORD_TEXT
, "", wxPoint(156, 209), wxSize( 140, 25), 0, wxDefaultValidator
, "ParamPasswordTxt");
1353 pParamDirPathMsg
= new wxStaticText(this, PARAMETER_DIALOG_DIRPATH_MSG
, "Directory:", wxPoint( 10, 243), wxSize( -1, -1), 0, "ParamDirPathMsg");
1354 pParamDirPathTxt
= new wxTextCtrl(this, PARAMETER_DIALOG_DIRPATH_TEXT
, "", wxPoint( 10, 259), wxSize(140, 25), 0, wxDefaultValidator
, "ParamDirPathTxt");
1355 pParamSaveBtn
= new wxButton(this, PARAMETER_DIALOG_SAVE
, "&Save", wxPoint(310, 21), wxSize( 70, 35), 0, wxDefaultValidator
, "ParamSaveBtn");
1356 pParamCancelBtn
= new wxButton(this, PARAMETER_DIALOG_CANCEL
, "C&ancel", wxPoint(310, 66), wxSize( 70, 35), 0, wxDefaultValidator
, "ParamCancelBtn");
1358 // Now that all the widgets on the panel are created, its safe to allow ::OnCommand() to
1359 // handle all widget processing
1360 widgetPtrsSet
= TRUE
;
1363 savedParamSettings
= wxGetApp().params
;
1368 } // CparameterDlg constructor
1371 void CparameterDlg::OnCloseWindow(wxCloseEvent
& event
)
1373 // Put any additional checking necessary to make certain it is alright
1374 // to close the program here that is not done elsewhere
1377 bool Ok
= (wxMessageBox("No changes have been saved.\n\nAre you sure you wish exit the parameter screen?","Confirm",wxYES_NO
|wxICON_QUESTION
) == wxYES
);
1385 wxGetApp().params
= savedParamSettings
;
1388 if (GetParent() != NULL
)
1389 GetParent()->SetFocus();
1392 } // Cparameter::OnCloseWindow()
1395 void CparameterDlg::OnButton( wxCommandEvent
&event
)
1397 wxWindow
*win
= (wxWindow
*) event
.GetEventObject();
1398 OnCommand( *win
, event
);
1401 void CparameterDlg::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
1403 wxString widgetName
;
1405 widgetName
= win
.GetName();
1410 if (widgetName
== pParamSaveBtn
->GetName())
1415 tStr
= "Database parameters have been saved.";
1416 if (GetParent() != NULL
) // The parameter dialog was not called during startup due to a missing cfg file
1417 tStr
+= "\nNew parameters will take effect the next time the program is started.";
1418 wxMessageBox(tStr
,"Notice...",wxOK
| wxICON_INFORMATION
);
1425 if (widgetName
== pParamCancelBtn
->GetName())
1430 } // CparameterDlg::OnCommand()
1433 bool CparameterDlg::PutData()
1435 // Fill the data source list box
1436 FillDataSourceList();
1438 // Fill in the fields from the params object
1439 if (wxGetApp().params
.ODBCSource
&& wxStrlen(wxGetApp().params
.ODBCSource
))
1440 pParamODBCSourceList
->SetStringSelection(wxGetApp().params
.ODBCSource
);
1441 pParamUserNameTxt
->SetValue(wxGetApp().params
.UserName
);
1442 pParamPasswordTxt
->SetValue(wxGetApp().params
.Password
);
1443 pParamDirPathTxt
->SetValue(wxGetApp().params
.DirPath
);
1445 } // CparameterDlg::PutData()
1448 bool CparameterDlg::GetData()
1451 if (pParamODBCSourceList
->GetStringSelection() != "")
1453 tStr
= pParamODBCSourceList
->GetStringSelection();
1454 if (tStr
.Length() > (sizeof(wxGetApp().params
.ODBCSource
)-1))
1457 errmsg
.Printf("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());
1458 wxMessageBox(errmsg
,"Internal program error...",wxOK
| wxICON_EXCLAMATION
);
1461 wxStrcpy(wxGetApp().params
.ODBCSource
, tStr
);
1466 tStr
= pParamUserNameTxt
->GetValue();
1467 if (tStr
.Length() > (sizeof(wxGetApp().params
.UserName
)-1))
1470 errmsg
.Printf("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());
1471 wxMessageBox(errmsg
,"Internal program error...",wxOK
| wxICON_EXCLAMATION
);
1474 wxStrcpy(wxGetApp().params
.UserName
, tStr
);
1476 tStr
= pParamPasswordTxt
->GetValue();
1477 if (tStr
.Length() > (sizeof(wxGetApp().params
.Password
)-1))
1480 errmsg
.Printf("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());
1481 wxMessageBox(errmsg
,"Internal program error...",wxOK
| wxICON_EXCLAMATION
);
1484 wxStrcpy(wxGetApp().params
.Password
,tStr
);
1486 tStr
= pParamDirPathTxt
->GetValue();
1487 tStr
.Replace("\\","/");
1488 if (tStr
.Length() > (sizeof(wxGetApp().params
.DirPath
)-1))
1491 errmsg
.Printf("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());
1492 wxMessageBox(errmsg
,"Internal program error...",wxOK
| wxICON_EXCLAMATION
);
1495 wxStrcpy(wxGetApp().params
.DirPath
,tStr
);
1497 } // CparameterDlg::GetData()
1500 bool CparameterDlg::Save()
1502 Cparameters saveParams
= wxGetApp().params
;
1505 wxGetApp().params
= saveParams
;
1510 if ((paramFile
= fopen(paramFilename
, "wt")) == NULL
)
1513 tStr
.Printf("Unable to write/overwrite '%s'.",paramFilename
);
1514 wxMessageBox(tStr
,"File I/O Error...",wxOK
| wxICON_EXCLAMATION
);
1518 fputs(wxGetApp().params
.ODBCSource
, paramFile
);
1519 fputc('\n', paramFile
);
1520 fputs(wxGetApp().params
.UserName
, paramFile
);
1521 fputc('\n', paramFile
);
1522 fputs(wxGetApp().params
.Password
, paramFile
);
1523 fputc('\n', paramFile
);
1524 fputs(wxGetApp().params
.DirPath
, paramFile
);
1525 fputc('\n', paramFile
);
1529 } // CparameterDlg::Save()
1532 void CparameterDlg::FillDataSourceList()
1534 char Dsn
[SQL_MAX_DSN_LENGTH
+ 1];
1536 wxStringList strList
;
1538 while (wxDbGetDataSource(DbConnectInf
.Henv
, Dsn
, SQL_MAX_DSN_LENGTH
+1, DsDesc
, 255))
1543 char **p
= strList
.ListToArray();
1546 for (i
= 0; wxStrlen(p
[i
]); i
++)
1547 pParamODBCSourceList
->Append(p
[i
]);
1548 } // CparameterDlg::CparameterDlg::FillDataSourceList()
1551 BEGIN_EVENT_TABLE(CqueryDlg
, wxDialog
)
1552 EVT_BUTTON(-1, CqueryDlg::OnButton
)
1553 EVT_CLOSE(CqueryDlg::OnCloseWindow
)
1556 // CqueryDlg() constructor
1557 CqueryDlg::CqueryDlg(wxWindow
*parent
, wxDb
*pDb
, char *tblName
[], char *pWhereArg
) : wxDialog (parent
, QUERY_DIALOG
, "Query", wxPoint(-1, -1), wxSize(480, 360))
1559 wxBeginBusyCursor();
1563 masterTableName
= tblName
[0];
1564 widgetPtrsSet
= FALSE
;
1567 // Initialize the WHERE clause from the string passed in
1568 pWhere
= pWhereArg
; // Save a pointer to the output buffer
1569 if (wxStrlen(pWhere
) > DB_MAX_WHERE_CLAUSE_LEN
) // Check the length of the buffer passed in
1572 s
.Printf("Maximum where clause length exceeded.\nLength must be less than %d", DB_MAX_WHERE_CLAUSE_LEN
+1);
1573 wxMessageBox(s
,"Error...",wxOK
| wxICON_EXCLAMATION
);
1578 pQueryCol1Msg
= new wxStaticText(this, QUERY_DIALOG_COL_MSG
, "Column 1:", wxPoint( 10, 10), wxSize( 69, 16), 0, "QueryCol1Msg");
1579 pQueryCol1Choice
= new wxChoice(this, QUERY_DIALOG_COL_CHOICE
, wxPoint( 10, 27), wxSize(250, 27), 0, 0, 0, wxDefaultValidator
, "QueryCol1Choice");
1580 pQueryNotMsg
= new wxStaticText(this, QUERY_DIALOG_NOT_MSG
, "NOT", wxPoint(268, 10), wxSize( -1, -1), 0, "QueryNotMsg");
1581 pQueryNotCheck
= new wxCheckBox(this, QUERY_DIALOG_NOT_CHECKBOX
, "", wxPoint(275, 37), wxSize( 20, 20), 0, wxDefaultValidator
, "QueryNotCheck");
1583 wxString choice_strings
[9];
1584 choice_strings
[0] = "=";
1585 choice_strings
[1] = "<";
1586 choice_strings
[2] = ">";
1587 choice_strings
[3] = "<=";
1588 choice_strings
[4] = ">=";
1589 choice_strings
[5] = "Begins";
1590 choice_strings
[6] = "Contains";
1591 choice_strings
[7] = "Like";
1592 choice_strings
[8] = "Between";
1594 pQueryOperatorMsg
= new wxStaticText(this, QUERY_DIALOG_OP_MSG
, "Operator:", wxPoint(305, 10), wxSize( -1, -1), 0, "QueryOperatorMsg");
1595 pQueryOperatorChoice
= new wxChoice(this, QUERY_DIALOG_OP_CHOICE
, wxPoint(305, 27), wxSize( 80, 27), 9, choice_strings
, 0, wxDefaultValidator
, "QueryOperatorChoice");
1596 pQueryCol2Msg
= new wxStaticText(this, QUERY_DIALOG_COL2_MSG
, "Column 2:", wxPoint( 10, 65), wxSize( 69, 16), 0, "QueryCol2Msg");
1597 pQueryCol2Choice
= new wxChoice(this, QUERY_DIALOG_COL2_CHOICE
, wxPoint( 10, 82), wxSize(250, 27), 0, 0, 0, wxDefaultValidator
, "QueryCol2Choice");
1598 pQuerySqlWhereMsg
= new wxStaticText(this, QUERY_DIALOG_WHERE_MSG
, "SQL where clause:", wxPoint( 10, 141), wxSize( -1, -1), 0, "QuerySqlWhereMsg");
1599 pQuerySqlWhereMtxt
= new wxTextCtrl(this, QUERY_DIALOG_WHERE_TEXT
, "", wxPoint( 10, 159), wxSize(377, 134), wxTE_MULTILINE
, wxDefaultValidator
, "QuerySqlWhereMtxt");
1600 pQueryAddBtn
= new wxButton(this, QUERY_DIALOG_ADD
, "&Add", wxPoint(406, 24), wxSize( 56, 26), 0, wxDefaultValidator
, "QueryAddBtn");
1601 pQueryAndBtn
= new wxButton(this, QUERY_DIALOG_AND
, "A&nd", wxPoint(406, 58), wxSize( 56, 26), 0, wxDefaultValidator
, "QueryAndBtn");
1602 pQueryOrBtn
= new wxButton(this, QUERY_DIALOG_OR
, "&Or", wxPoint(406, 92), wxSize( 56, 26), 0, wxDefaultValidator
, "QueryOrBtn");
1603 pQueryLParenBtn
= new wxButton(this, QUERY_DIALOG_LPAREN
, "(", wxPoint(406, 126), wxSize( 26, 26), 0, wxDefaultValidator
, "QueryLParenBtn");
1604 pQueryRParenBtn
= new wxButton(this, QUERY_DIALOG_RPAREN
, ")", wxPoint(436, 126), wxSize( 26, 26), 0, wxDefaultValidator
, "QueryRParenBtn");
1605 pQueryDoneBtn
= new wxButton(this, QUERY_DIALOG_DONE
, "&Done", wxPoint(406, 185), wxSize( 56, 26), 0, wxDefaultValidator
, "QueryDoneBtn");
1606 pQueryClearBtn
= new wxButton(this, QUERY_DIALOG_CLEAR
, "C&lear", wxPoint(406, 218), wxSize( 56, 26), 0, wxDefaultValidator
, "QueryClearBtn");
1607 pQueryCountBtn
= new wxButton(this, QUERY_DIALOG_COUNT
, "&Count", wxPoint(406, 252), wxSize( 56, 26), 0, wxDefaultValidator
, "QueryCountBtn");
1608 pQueryValue1Msg
= new wxStaticText(this, QUERY_DIALOG_VALUE1_MSG
, "Value:", wxPoint(277, 66), wxSize( -1, -1), 0, "QueryValue1Msg");
1609 pQueryValue1Txt
= new wxTextCtrl(this, QUERY_DIALOG_VALUE1_TEXT
, "", wxPoint(277, 83), wxSize(108, 25), 0, wxDefaultValidator
, "QueryValue1Txt");
1610 pQueryValue2Msg
= new wxStaticText(this, QUERY_DIALOG_VALUE2_MSG
, "AND", wxPoint(238, 126), wxSize( -1, -1), 0, "QueryValue2Msg");
1611 pQueryValue2Txt
= new wxTextCtrl(this, QUERY_DIALOG_VALUE2_TEXT
, "", wxPoint(277, 120), wxSize(108, 25), 0, wxDefaultValidator
, "QueryValue2Txt");
1612 pQueryHintGrp
= new wxStaticBox(this, QUERY_DIALOG_HINT_GROUP
, "", wxPoint( 10, 291), wxSize(377, 40), 0, "QueryHintGrp");
1613 pQueryHintMsg
= new wxStaticText(this, QUERY_DIALOG_HINT_MSG
, "", wxPoint( 16, 306), wxSize( -1, -1), 0, "QueryHintMsg");
1615 widgetPtrsSet
= TRUE
;
1616 // Initialize the dialog
1618 pQueryCol2Choice
->Append("VALUE -->");
1619 colInf
= pDB
->GetColumns(tblName
);
1625 tStr
= "ODBC error during GetColumns()\n\n";
1626 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
1627 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
1632 for (i
= 0; colInf
[i
].colName
&& wxStrlen(colInf
[i
].colName
); i
++)
1634 // If there is more than one table being queried, qualify
1635 // the column names with the table name prefix.
1636 if (tblName
[1] && wxStrlen(tblName
[1]))
1638 qualName
.Printf("%s.%s", colInf
[i
].tableName
, colInf
[i
].colName
);
1639 pQueryCol1Choice
->Append(qualName
);
1640 pQueryCol2Choice
->Append(qualName
);
1642 else // Single table query, append just the column names
1644 pQueryCol1Choice
->Append(colInf
[i
].colName
);
1645 pQueryCol2Choice
->Append(colInf
[i
].colName
);
1649 pQueryCol1Choice
->SetSelection(0);
1650 pQueryCol2Choice
->SetSelection(0);
1651 pQueryOperatorChoice
->SetSelection(0);
1653 pQueryValue2Msg
->Show(FALSE
);
1654 pQueryValue2Txt
->Show(FALSE
);
1656 pQueryHintMsg
->SetLabel(langQRY_EQ
);
1658 pQuerySqlWhereMtxt
->SetValue(pWhere
);
1662 // Display the dialog window
1666 } // CqueryDlg() constructor
1669 CqueryDlg::~CqueryDlg()
1671 } // CqueryDlg::~CqueryDlg() destructor
1674 void CqueryDlg::OnButton( wxCommandEvent
&event
)
1676 wxWindow
*win
= (wxWindow
*) event
.GetEventObject();
1677 OnCommand( *win
, event
);
1680 void CqueryDlg::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
1682 // Widget pointers won't be set when the dialog is constructed.
1683 // Control is passed through this function once for each widget on
1684 // a dialog as the dialog is constructed.
1688 wxString widgetName
= win
.GetName();
1690 // Operator choice box
1691 if (widgetName
== pQueryOperatorChoice
->GetName())
1693 // Set the help text
1694 switch((qryOp
) pQueryOperatorChoice
->GetSelection())
1697 pQueryHintMsg
->SetLabel(langQRY_EQ
);
1700 pQueryHintMsg
->SetLabel(langQRY_LT
);
1703 pQueryHintMsg
->SetLabel(langQRY_GT
);
1706 pQueryHintMsg
->SetLabel(langQRY_LE
);
1709 pQueryHintMsg
->SetLabel(langQRY_GE
);
1712 pQueryHintMsg
->SetLabel(langQRY_BEGINS
);
1715 pQueryHintMsg
->SetLabel(langQRY_CONTAINS
);
1718 pQueryHintMsg
->SetLabel(langQRY_LIKE
);
1721 pQueryHintMsg
->SetLabel(langQRY_BETWEEN
);
1725 // Hide the value2 widget
1726 pQueryValue2Msg
->Show(FALSE
); // BETWEEN will show this widget
1727 pQueryValue2Txt
->Show(FALSE
); // BETWEEN will show this widget
1729 // Disable the NOT operator for <, <=, >, >=
1730 switch((qryOp
) pQueryOperatorChoice
->GetSelection())
1736 pQueryNotCheck
->SetValue(0);
1737 pQueryNotCheck
->Enable(FALSE
);
1740 pQueryNotCheck
->Enable(TRUE
);
1744 // Manipulate the dialog to handle the selected operator
1745 switch((qryOp
) pQueryOperatorChoice
->GetSelection())
1752 pQueryCol2Choice
->Enable(TRUE
);
1753 if (pQueryCol2Choice
->GetSelection()) // Column name is highlighted
1755 pQueryValue1Msg
->Show(FALSE
);
1756 pQueryValue1Txt
->Show(FALSE
);
1758 else // "Value" is highlighted
1760 pQueryValue1Msg
->Show(TRUE
);
1761 pQueryValue1Txt
->Show(TRUE
);
1762 pQueryValue1Txt
->SetFocus();
1768 pQueryCol2Choice
->SetSelection(0);
1769 pQueryCol2Choice
->Enable(FALSE
);
1770 pQueryValue1Msg
->Show(TRUE
);
1771 pQueryValue1Txt
->Show(TRUE
);
1772 pQueryValue1Txt
->SetFocus();
1775 pQueryCol2Choice
->SetSelection(0);
1776 pQueryCol2Choice
->Enable(FALSE
);
1777 pQueryValue2Msg
->Show(TRUE
);
1778 pQueryValue2Txt
->Show(TRUE
);
1779 pQueryValue1Msg
->Show(TRUE
);
1780 pQueryValue1Txt
->Show(TRUE
);
1781 pQueryValue1Txt
->SetFocus();
1787 } // Operator choice box
1790 if (widgetName
== pQueryCol2Choice
->GetName())
1792 if (pQueryCol2Choice
->GetSelection()) // Column name is highlighted
1794 pQueryValue1Msg
->Show(FALSE
);
1795 pQueryValue1Txt
->Show(FALSE
);
1797 else // "Value" is highlighted
1799 pQueryValue1Msg
->Show(TRUE
);
1800 pQueryValue1Txt
->Show(TRUE
);
1801 pQueryValue1Txt
->SetFocus();
1805 } // Column 2 choice
1808 if (widgetName
== pQueryAddBtn
->GetName())
1816 if (widgetName
== pQueryAndBtn
->GetName())
1818 AppendToWhere(" AND\n");
1824 if (widgetName
== pQueryOrBtn
->GetName())
1826 AppendToWhere(" OR\n");
1831 // Left Paren button
1832 if (widgetName
== pQueryLParenBtn
->GetName())
1837 } // Left Paren button
1839 // Right paren button
1840 if (widgetName
== pQueryRParenBtn
->GetName())
1845 } // Right Paren button
1848 if (widgetName
== pQueryDoneBtn
->GetName())
1850 // Be sure the where clause will not overflow the output buffer
1851 if (wxStrlen(pQuerySqlWhereMtxt
->GetValue()) > DB_MAX_WHERE_CLAUSE_LEN
)
1854 s
.Printf("Maximum where clause length exceeded.\nLength must be less than %d", DB_MAX_WHERE_CLAUSE_LEN
+1);
1855 wxMessageBox(s
,"Error...",wxOK
| wxICON_EXCLAMATION
);
1858 // Validate the where clause for things such as matching parens
1859 if (!ValidateWhereClause())
1861 // Copy the where clause to the output buffer and exit
1862 wxStrcpy(pWhere
, pQuerySqlWhereMtxt
->GetValue());
1869 if (widgetName
== pQueryClearBtn
->GetName())
1871 bool Ok
= (wxMessageBox("Are you sure you wish to clear the Query?","Confirm",wxYES_NO
|wxICON_QUESTION
) == wxYES
);
1874 pQuerySqlWhereMtxt
->SetValue("");
1880 if (widgetName
== pQueryCountBtn
->GetName())
1882 wxBeginBusyCursor();
1889 } // CqueryDlg::OnCommand
1892 void CqueryDlg::OnCloseWindow(wxCloseEvent
& event
)
1907 GetParent()->SetFocus();
1914 } // CqueryDlg::OnCloseWindow()
1917 void CqueryDlg::AppendToWhere(char *s
)
1919 wxString whereStr
= pQuerySqlWhereMtxt
->GetValue();
1921 pQuerySqlWhereMtxt
->SetValue(whereStr
);
1923 } // CqueryDlg::AppendToWhere()
1926 void CqueryDlg::ProcessAddBtn()
1928 qryOp oper
= (qryOp
) pQueryOperatorChoice
->GetSelection();
1930 // Verify that eveything is filled in correctly
1931 if (pQueryCol2Choice
->GetSelection() == 0) // "Value" is selected
1933 // Verify that value 1 is filled in
1934 if (wxStrlen(pQueryValue1Txt
->GetValue()) == 0)
1937 pQueryValue1Txt
->SetFocus();
1940 // For the BETWEEN operator, value 2 must be filled in as well
1941 if (oper
== qryOpBETWEEN
&&
1942 wxStrlen(pQueryValue2Txt
->GetValue()) == 0)
1945 pQueryValue2Txt
->SetFocus();
1950 // Build the expression and append it to the where clause window
1951 wxString s
= pQueryCol1Choice
->GetStringSelection();
1953 if (pQueryNotCheck
->GetValue() && (oper
!= qryOpEQ
))
1959 if (pQueryNotCheck
->GetValue()) // NOT box is checked
1988 int col1Idx
= pQueryCol1Choice
->GetSelection();
1991 if (colInf
[col1Idx
].sqlDataType
== SQL_VARCHAR
||
1992 oper
== qryOpBEGINS
||
1993 oper
== qryOpCONTAINS
||
1997 if (pQueryCol2Choice
->GetSelection()) // Column name
1998 s
+= pQueryCol2Choice
->GetStringSelection();
1999 else // Column 2 is a "value"
2003 if (oper
== qryOpCONTAINS
)
2005 s
+= pQueryValue1Txt
->GetValue();
2006 if (oper
== qryOpCONTAINS
|| oper
== qryOpBEGINS
)
2012 if (oper
== qryOpBETWEEN
)
2017 s
+= pQueryValue2Txt
->GetValue();
2022 AppendToWhere((char*) (const char*) s
);
2024 } // CqueryDlg::ProcessAddBtn()
2027 void CqueryDlg::ProcessCountBtn()
2029 if (!ValidateWhereClause())
2032 if (dbTable
== 0) // wxDbTable object needs to be created and opened
2034 if (!(dbTable
= new wxDbTable(pDB
, masterTableName
, 0, NULL
, !wxDB_QUERY_ONLY
, DbConnectInf
.defaultDir
)))
2036 wxMessageBox("Memory allocation failed creating a wxDbTable object.","Error...",wxOK
| wxICON_EXCLAMATION
);
2039 if (!dbTable
->Open())
2042 tStr
= "ODBC error during Open()\n\n";
2043 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
2044 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
2049 // Count() with WHERE clause
2052 whereStr
= pQuerySqlWhereMtxt
->GetValue();
2053 dbTable
->SetWhereClause(whereStr
.c_str());
2054 ULONG whereCnt
= dbTable
->Count();
2056 // Count() of all records in the table
2057 dbTable
->SetWhereClause("");
2058 ULONG totalCnt
= dbTable
->Count();
2060 if (whereCnt
> 0 || totalCnt
== 0)
2063 tStr
.Printf("%lu of %lu records match the query criteria.",whereCnt
,totalCnt
);
2064 wxMessageBox(tStr
,"Notice...",wxOK
| wxICON_INFORMATION
);
2069 tStr
.Printf("%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
);
2070 wxMessageBox(tStr
,"Notice...",wxOK
| wxICON_INFORMATION
);
2073 // After a wxMessageBox, the focus does not necessarily return to the
2074 // window which was the focus when the message box popped up, so return
2075 // focus to the Query dialog for certain
2078 } // CqueryDlg::ProcessCountBtn()
2081 bool CqueryDlg::ValidateWhereClause()
2083 wxString where
= pQuerySqlWhereMtxt
->GetValue();
2085 if (where
.Freq('(') != where
.Freq(')'))
2087 wxMessageBox("There are mismatched parenthesis in the constructed where clause","Error...",wxOK
| wxICON_EXCLAMATION
);
2090 // After a wxMessageBox, the focus does not necessarily return to the
2091 // window which was the focus when the message box popped up, so return
2092 // focus to the Query dialog for certain
2097 } // CqueryDlg::ValidateWhereClause()
2103 TEST CODE FOR TESTING THE wxDbCreateDataSource() FUNCTION
2106 result = wxDbCreateDataSource("Microsoft Access Driver (*.mdb)","GLT-TEST2","GLT-Descrip",FALSE,"",this);
2109 // check for errors caused by ConfigDSN based functions
2112 wxChar errMsg[500+1];
2115 SQLInstallerError(1,&retcode,errMsg,500,&cb);
2117 wxMessageBox("FAILED creating data source","FAILED");
2120 wxMessageBox("SUCCEEDED creating data source","SUCCESS");