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 wxTable.
27 #pragma implementation "dbtest.h"
30 #include "wx/wxprec.h"
44 #include <stdio.h> /* Included strictly for reading the text file with the database parameters */
46 #include <wx/db.h> /* Required in the file which will get the data source connection */
47 #include <wx/dbtable.h> /* Has the wxTable object from which all data objects will inherit their data table functionality */
49 extern DbList
* WXDLLEXPORT PtrBegDbList
; /* from db.cpp, used in getting back error results from db connections */
51 #include "dbtest.h" /* Header file for this demonstration program */
52 #include "listdb.h" /* Code to support the "Lookup" button on the editor dialog */
54 IMPLEMENT_APP(DatabaseDemoApp
)
56 extern char ListDB_Selection
[]; /* Used to return the first column value for the selected line from the listDB routines */
57 extern char ListDB_Selection2
[]; /* Used to return the second column value for the selected line from the listDB routines */
59 DatabaseDemoFrame
*DemoFrame
; /* Pointer to the main frame */
61 /* Pointer to the main database connection used in the program. This
62 * pointer would normally be used for doing things as database lookups
63 * for user login names and passwords, getting workstation settings, etc.
66 * For each database object created which uses this wxDB pointer
67 * connection to the database, when a CommitTrans() or RollBackTrans()
68 * will commit or rollback EVERY object which uses this wxDB pointer.
70 * To allow each table object (those derived from wxTable) to be
71 * individually committed or rolled back, you MUST use a different
72 * instance of wxDB in the constructor of the table. Doing so creates
73 * more overhead, and will use more database connections (some DBs have
74 * connection limits...), so use connections sparringly.
76 * It is recommended that one "main" database connection be created for
77 * the entire program to use for READ-ONLY database accesses, but for each
78 * table object which will do a CommitTrans() or RollbackTrans() that a
79 * new wxDB object be created and used for it.
85 * This function will return the exact string(s) from the database engine
86 * indicating all error conditions which have just occured during the
87 * last call to the database engine.
89 * This demo uses the returned string by displaying it in a wxMessageBox. The
90 * formatting therefore is not the greatest, but this is just a demo, not a
91 * finished product. :-) gt
93 * NOTE: The value returned by this function is for temporary use only and
94 * should be copied for long term use
96 char *GetExtendedDBErrorMsg(char *ErrFile
, int ErrLine
)
102 if (ErrFile
|| ErrLine
)
107 tStr
.Printf("%d",ErrLine
);
108 msg
+= tStr
.GetData();
112 msg
.Append ("\nODBC errors:\n");
115 /* Scan through each database connection displaying
116 * any ODBC errors that have occured. */
117 for (DbList
*pDbList
= PtrBegDbList
; pDbList
; pDbList
= pDbList
->PtrNext
)
119 // Skip over any free connections
122 // Display errors for this connection
123 for (int i
= 0; i
< DB_MAX_ERROR_HISTORY
; i
++)
125 if (pDbList
->PtrDb
->errorList
[i
])
127 msg
.Append(pDbList
->PtrDb
->errorList
[i
]);
128 if (strcmp(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
);
172 if ((paramFile
= fopen(paramFilename
, "r")) == NULL
)
175 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
);
176 wxMessageBox(tStr
,"File I/O Error...",wxOK
| wxICON_EXCLAMATION
);
177 DemoFrame
->BuildParameterDialog(NULL
);
178 if ((paramFile
= fopen(paramFilename
, "r")) == NULL
)
183 fgets(buffer
, sizeof(params
.ODBCSource
), paramFile
);
184 buffer
[strlen(buffer
)-1] = '\0';
185 strcpy(params
.ODBCSource
,buffer
);
187 fgets(buffer
, sizeof(params
.UserName
), paramFile
);
188 buffer
[strlen(buffer
)-1] = '\0';
189 strcpy(params
.UserName
,buffer
);
191 fgets(buffer
, sizeof(params
.Password
), paramFile
);
192 buffer
[strlen(buffer
)-1] = '\0';
193 strcpy(params
.Password
,buffer
);
195 fgets(buffer
, sizeof(params
.DirPath
), paramFile
);
196 buffer
[strlen(buffer
)-1] = '\0';
197 strcpy(params
.DirPath
,buffer
);
201 // Connect to datasource
202 strcpy(DbConnectInf
.Dsn
, params
.ODBCSource
); // ODBC data source name (created with ODBC Administrator under Win95/NT)
203 strcpy(DbConnectInf
.Uid
, params
.UserName
); // database username - must already exist in the data source
204 strcpy(DbConnectInf
.AuthStr
, params
.Password
); // password database username
205 strcpy(DbConnectInf
.defaultDir
,params
.DirPath
); // path where the table exists (needed for dBase)
207 READONLY_DB
= GetDbConnection(&DbConnectInf
);
208 if (READONLY_DB
== 0)
210 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
);
211 DemoFrame
->BuildParameterDialog(NULL
);
212 strcpy(DbConnectInf
.Dsn
, "");
213 strcpy(DbConnectInf
.Uid
, "");
214 strcpy(DbConnectInf
.AuthStr
, "");
215 wxMessageBox("Now exiting program.\n\nRestart program to try any new settings.","Notice...",wxOK
| wxICON_INFORMATION
);
219 DemoFrame
->BuildEditorDialog();
222 DemoFrame
->Show(TRUE
);
225 } // DatabaseDemoApp::OnInit()
227 BEGIN_EVENT_TABLE(DatabaseDemoFrame
, wxFrame
)
228 EVT_MENU(FILE_CREATE
, DatabaseDemoFrame::OnCreate
)
229 EVT_MENU(FILE_EXIT
, DatabaseDemoFrame::OnExit
)
230 EVT_MENU(EDIT_PARAMETERS
, DatabaseDemoFrame::OnEditParameters
)
231 EVT_MENU(ABOUT_DEMO
, DatabaseDemoFrame::OnAbout
)
232 EVT_CLOSE(DatabaseDemoFrame::OnCloseWindow
)
235 // DatabaseDemoFrame constructor
236 DatabaseDemoFrame::DatabaseDemoFrame(wxFrame
*frame
, const wxString
& title
,
237 const wxPoint
& pos
, const wxSize
& size
):
238 wxFrame(frame
, -1, title
, pos
, size
)
240 // Put any code in necessary for initializing the main frame here
243 void DatabaseDemoFrame::OnCreate(wxCommandEvent
& event
)
248 void DatabaseDemoFrame::OnExit(wxCommandEvent
& event
)
253 void DatabaseDemoFrame::OnEditParameters(wxCommandEvent
& event
)
255 if ((pEditorDlg
->mode
!= mCreate
) && (pEditorDlg
->mode
!= mEdit
))
256 BuildParameterDialog(this);
258 wxMessageBox("Cannot change database parameters while creating or editing a record","Notice...",wxOK
| wxICON_INFORMATION
);
261 void DatabaseDemoFrame::OnAbout(wxCommandEvent
& event
)
263 wxMessageBox("wxWindows sample program for database classes\n\nContributed on 27 July 1998","About...",wxOK
| wxICON_INFORMATION
);
266 void DatabaseDemoFrame::OnCloseWindow(wxCloseEvent
& event
)
268 // Put any additional checking necessary to make certain it is alright
269 // to close the program here that is not done elsewhere
272 } // DatabaseDemoFrame::OnCloseWindow()
275 void DatabaseDemoFrame::CreateDataTable()
277 bool Ok
= (wxMessageBox("Any data currently residing in the table will be erased.\n\nAre you sure?","Confirm",wxYES_NO
|wxICON_QUESTION
) == wxYES
);
286 Ccontact
*Contact
= new Ccontact();
290 wxMessageBox("Error allocating memory for 'Ccontact'object.\n\nTable was not created.","Error...",wxOK
| wxICON_EXCLAMATION
);
294 if (!Contact
->CreateTable(FALSE
))
298 tStr
= "Error creating CONTACTS table.\nTable was not created.\n\n";
299 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
300 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
305 if (!Contact
->CreateIndexes())
309 tStr
= "Error creating CONTACTS indexes.\nIndexes will be unavailable.\n\n";
310 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
311 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
321 wxMessageBox("Table and index(es) were successfully created.","Notice...",wxOK
| wxICON_INFORMATION
);
322 } // DatabaseDemoFrame::CreateDataTable()
325 void DatabaseDemoFrame::BuildEditorDialog()
327 pEditorDlg
= new CeditorDlg(this);
329 wxMessageBox("Unable to create the editor dialog for some reason","Error...",wxOK
| wxICON_EXCLAMATION
);
330 } // DatabaseDemoFrame::BuildEditorDialog()
333 void DatabaseDemoFrame::BuildParameterDialog(wxWindow
*parent
)
335 pParamDlg
= new CparameterDlg(parent
);
338 wxMessageBox("Unable to create the parameter dialog for some reason","Error...",wxOK
| wxICON_EXCLAMATION
);
339 } // DatabaseDemoFrame::BuildParameterDialog()
343 * Constructor note: If no wxDB object is passed in, a new connection to the database
344 * is created for this instance of Ccontact. This can be a slow process depending
345 * on the database engine being used, and some database engines have a limit on the
346 * number of connections (either hard limits, or license restricted) so care should
347 * be used to use as few connections as is necessary.
348 * IMPORTANT: Objects which share a wxDB pointer are ALL acted upon whenever a member
349 * function of pDb is called (i.e. CommitTrans() or RollbackTrans(), so if modifying
350 * or creating a table objects which use the same pDb, know that all the objects
351 * will be committed or rolled back when any of the objects has this function call made.
353 Ccontact::Ccontact (wxDB
*pwxDB
) : wxTable(pwxDB
? pwxDB
: GetDbConnection(&DbConnectInf
),CONTACT_TABLE_NAME
,CONTACT_NO_COLS
,NULL
,!QUERY_ONLY
,DbConnectInf
.defaultDir
)
355 // This is used to represent whether the database connection should be released
356 // when this instance of the object is deleted. If using the same connection
357 // for multiple instance of database objects, then the connection should only be
358 // released when the last database instance using the connection is deleted
363 } // Ccontact Constructor
366 void Ccontact::Initialize()
375 JoinDate
.year
= 1980;
381 JoinDate
.fraction
= 0;
382 NativeLanguage
= langENGLISH
;
386 } // Ccontact::Initialize
389 Ccontact::~Ccontact()
393 if (!FreeDbConnection(pDb
))
396 tStr
= "Unable to Free the Ccontact data table handle\n\n";
397 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
398 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
401 } // Ccontract destructor
405 * Handles setting up all the connections for the interface from the wxTable
406 * functions to interface to the data structure used to store records in
407 * memory, and for all the column definitions that define the table structure
409 void Ccontact::SetupColumns()
411 // NOTE: Columns now are 8 character names, as that is all dBase can support. Longer
412 // names can be used for other database engines
413 SetColDefs ( 0,"NAME", DB_DATA_TYPE_VARCHAR
, Name
, SQL_C_CHAR
, sizeof(Name
), TRUE
, TRUE
); // Primary index
414 SetColDefs ( 1,"ADDRESS1", DB_DATA_TYPE_VARCHAR
, Addr1
, SQL_C_CHAR
, sizeof(Addr1
), FALSE
,TRUE
);
415 SetColDefs ( 2,"ADDRESS2", DB_DATA_TYPE_VARCHAR
, Addr2
, SQL_C_CHAR
, sizeof(Addr2
), FALSE
,TRUE
);
416 SetColDefs ( 3,"CITY", DB_DATA_TYPE_VARCHAR
, City
, SQL_C_CHAR
, sizeof(City
), FALSE
,TRUE
);
417 SetColDefs ( 4,"STATE", DB_DATA_TYPE_VARCHAR
, State
, SQL_C_CHAR
, sizeof(State
), FALSE
,TRUE
);
418 SetColDefs ( 5,"POSTCODE", DB_DATA_TYPE_VARCHAR
, PostalCode
, SQL_C_CHAR
, sizeof(PostalCode
), FALSE
,TRUE
);
419 SetColDefs ( 6,"COUNTRY", DB_DATA_TYPE_VARCHAR
, Country
, SQL_C_CHAR
, sizeof(Country
), FALSE
,TRUE
);
420 SetColDefs ( 7,"JOINDATE", DB_DATA_TYPE_DATE
, &JoinDate
, SQL_C_TIMESTAMP
, sizeof(JoinDate
), FALSE
,TRUE
);
421 SetColDefs ( 8,"IS_DEV", DB_DATA_TYPE_INTEGER
, &IsDeveloper
, SQL_C_BOOLEAN(IsDeveloper
),sizeof(IsDeveloper
), FALSE
,TRUE
);
422 SetColDefs ( 9,"CONTRIBS", DB_DATA_TYPE_INTEGER
, &Contributions
, SQL_C_USHORT
, sizeof(Contributions
), FALSE
,TRUE
);
423 SetColDefs (10,"LINE_CNT", DB_DATA_TYPE_INTEGER
, &LinesOfCode
, SQL_C_ULONG
, sizeof(LinesOfCode
), FALSE
,TRUE
);
424 SetColDefs (11,"LANGUAGE", DB_DATA_TYPE_INTEGER
, &NativeLanguage
, SQL_C_ENUM
, sizeof(NativeLanguage
), FALSE
,TRUE
);
425 } // Ccontact::SetupColumns
428 bool Ccontact::CreateIndexes(void)
430 // This index could easily be accomplished with an "orderBy" clause,
431 // but is done to show how to construct a non-primary index.
437 strcpy(idxDef
[0].ColName
, "IS_DEVELOPER");
438 idxDef
[0].Ascending
= TRUE
;
440 strcpy(idxDef
[1].ColName
, "NAME");
441 idxDef
[1].Ascending
= TRUE
;
443 indexName
= CONTACT_TABLE_NAME
;
444 indexName
+= "_IDX1";
445 Ok
= CreateIndex((char*) (const char*) indexName
, TRUE
, 2, idxDef
);
448 } // Ccontact::CreateIndexes()
452 * Having a function to do a query on the primary key (and possibly others) is
453 * very efficient and tighter coding so that it is available where ever the object
454 * is. Great for use with multiple tables when not using views or outer joins
456 bool Ccontact::FetchByName(char *name
)
458 whereStr
.Printf("NAME = '%s'",name
);
459 where
= (char*) (const char*) this->whereStr
;
468 } // Ccontact::FetchByName()
473 * ************* DIALOGS ***************
478 /* CeditorDlg constructor
480 * Creates the dialog used for creating/editing/deleting/copying a Ccontact object.
481 * This dialog actually is drawn in the main frame of the program
483 * An instance of Ccontact is created - "Contact" - which is used to hold the Ccontact
484 * object that is currently being worked with.
487 BEGIN_EVENT_TABLE(CeditorDlg
, wxPanel
)
488 EVT_BUTTON(-1, CeditorDlg::OnButton
)
491 CeditorDlg::CeditorDlg(wxWindow
*parent
) : wxPanel (parent
, 1, 1, 460, 455)
493 // Since the ::OnCommand() function is overridden, this prevents the widget
494 // detection in ::OnCommand() until all widgets have been initialized to prevent
495 // uninitialized pointers from crashing the program
496 widgetPtrsSet
= FALSE
;
498 // Create the data structure and a new database connection.
499 // (As there is not a pDb being passed in the constructor, a new database
500 // connection is created)
501 Contact
= new Ccontact();
505 wxMessageBox("Unable to instantiate an instance of Ccontact","Error...",wxOK
| wxICON_EXCLAMATION
);
509 // Check if the table exists or not. If it doesn't, ask the user if they want to
510 // create the table. Continue trying to create the table until it exists, or user aborts
511 while (!Contact
->pDb
->TableExists((char *)CONTACT_TABLE_NAME
,DbConnectInf
.Uid
,DbConnectInf
.defaultDir
))
514 tStr
.Printf("Unable to open the table '%s'.\n\nTable may need to be created...?\n\n",CONTACT_TABLE_NAME
);
515 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
516 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
518 bool createTable
= (wxMessageBox("Do you wish to try to create/clear the CONTACTS table?","Confirm",wxYES_NO
|wxICON_QUESTION
) == wxYES
);
528 DemoFrame
->CreateDataTable();
531 // Tables must be "opened" before anything other than creating/deleting table can be done
532 if (!Contact
->Open())
534 // Table does exist, there was some problem opening it. Currently this should
535 // never fail, except in the case of the table not exisiting. Open() basically
536 // only sets up variable/pointer values, other than checking for table existence.
537 if (Contact
->pDb
->TableExists((char *)CONTACT_TABLE_NAME
))
540 tStr
.Printf("Unable to open the table '%s'.\n\n",CONTACT_TABLE_NAME
);
541 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
542 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
552 (void)new wxStaticBox(this, EDITOR_DIALOG_FN_GROUP
, "", wxPoint(15, 1), wxSize(497, 69), 0, "FunctionGrp");
553 (void)new wxStaticBox(this, EDITOR_DIALOG_SEARCH_GROUP
, "", wxPoint(417, 1), wxSize(95, 242), 0, "SearchGrp");
555 pCreateBtn
= new wxButton(this, EDITOR_DIALOG_CREATE
, "&Create", wxPoint(25, 21), wxSize(70, 35), 0, wxDefaultValidator
, "CreateBtn");
556 pEditBtn
= new wxButton(this, EDITOR_DIALOG_EDIT
, "&Edit", wxPoint(102, 21), wxSize(70, 35), 0, wxDefaultValidator
, "EditBtn");
557 pDeleteBtn
= new wxButton(this, EDITOR_DIALOG_DELETE
, "&Delete", wxPoint(179, 21), wxSize(70, 35), 0, wxDefaultValidator
, "DeleteBtn");
558 pCopyBtn
= new wxButton(this, EDITOR_DIALOG_COPY
, "Cop&y", wxPoint(256, 21), wxSize(70, 35), 0, wxDefaultValidator
, "CopyBtn");
559 pSaveBtn
= new wxButton(this, EDITOR_DIALOG_SAVE
, "&Save", wxPoint(333, 21), wxSize(70, 35), 0, wxDefaultValidator
, "SaveBtn");
560 pCancelBtn
= new wxButton(this, EDITOR_DIALOG_CANCEL
, "C&ancel", wxPoint(430, 21), wxSize(70, 35), 0, wxDefaultValidator
, "CancelBtn");
562 pPrevBtn
= new wxButton(this, EDITOR_DIALOG_PREV
, "<< &Prev", wxPoint(430, 81), wxSize(70, 35), 0, wxDefaultValidator
, "PrevBtn");
563 pNextBtn
= new wxButton(this, EDITOR_DIALOG_NEXT
, "&Next >>", wxPoint(430, 121), wxSize(70, 35), 0, wxDefaultValidator
, "NextBtn");
564 pQueryBtn
= new wxButton(this, EDITOR_DIALOG_QUERY
, "&Query", wxPoint(430, 161), wxSize(70, 35), 0, wxDefaultValidator
, "QueryBtn");
565 pResetBtn
= new wxButton(this, EDITOR_DIALOG_RESET
, "&Reset", wxPoint(430, 200), wxSize(70, 35), 0, wxDefaultValidator
, "ResetBtn");
567 pNameMsg
= new wxStaticText(this, EDITOR_DIALOG_NAME_MSG
, "Name:", wxPoint(17, 80), wxSize(-1, -1), 0, "NameMsg");
568 pNameTxt
= new wxTextCtrl(this, EDITOR_DIALOG_NAME_TEXT
, "", wxPoint(17, 97), wxSize(308, 25), 0, wxDefaultValidator
, "NameTxt");
569 pNameListBtn
= new wxButton(this, EDITOR_DIALOG_LOOKUP
, "&Lookup", wxPoint(333, 99), wxSize(70, 24), 0, wxDefaultValidator
, "LookupBtn");
571 pAddress1Msg
= new wxStaticText(this, EDITOR_DIALOG_ADDRESS1_MSG
, "Address:", wxPoint(17, 130), wxSize(-1, -1), 0, "Address1Msg");
572 pAddress1Txt
= new wxTextCtrl(this, EDITOR_DIALOG_ADDRESS2_TEXT
, "", wxPoint(17, 147), wxSize(308, 25), 0, wxDefaultValidator
, "Address1Txt");
574 pAddress2Msg
= new wxStaticText(this, EDITOR_DIALOG_ADDRESS2_MSG
, "Address:", wxPoint(17, 180), wxSize(-1, -1), 0, "Address2Msg");
575 pAddress2Txt
= new wxTextCtrl(this, EDITOR_DIALOG_ADDRESS2_TEXT
, "", wxPoint(17, 197), wxSize(308, 25), 0, wxDefaultValidator
, "Address2Txt");
577 pCityMsg
= new wxStaticText(this, EDITOR_DIALOG_CITY_MSG
, "City:", wxPoint(17, 230), wxSize(-1, -1), 0, "CityMsg");
578 pCityTxt
= new wxTextCtrl(this, EDITOR_DIALOG_CITY_TEXT
, "", wxPoint(17, 247), wxSize(225, 25), 0, wxDefaultValidator
, "CityTxt");
580 pStateMsg
= new wxStaticText(this, EDITOR_DIALOG_STATE_MSG
, "State:", wxPoint(250, 230), wxSize(-1, -1), 0, "StateMsg");
581 pStateTxt
= new wxTextCtrl(this, EDITOR_DIALOG_STATE_TEXT
, "", wxPoint(250, 247), wxSize(153, 25), 0, wxDefaultValidator
, "StateTxt");
583 pCountryMsg
= new wxStaticText(this, EDITOR_DIALOG_COUNTRY_MSG
, "Country:", wxPoint(17, 280), wxSize(-1, -1), 0, "CountryMsg");
584 pCountryTxt
= new wxTextCtrl(this, EDITOR_DIALOG_COUNTRY_TEXT
, "", wxPoint(17, 297), wxSize(225, 25), 0, wxDefaultValidator
, "CountryTxt");
586 pPostalCodeMsg
= new wxStaticText(this, EDITOR_DIALOG_POSTAL_MSG
, "Postal Code:", wxPoint(250, 280), wxSize(-1, -1), 0, "PostalCodeMsg");
587 pPostalCodeTxt
= new wxTextCtrl(this, EDITOR_DIALOG_POSTAL_TEXT
, "", wxPoint(250, 297), wxSize(153, 25), 0, wxDefaultValidator
, "PostalCodeTxt");
589 wxString choice_strings
[5];
590 choice_strings
[0] = "English";
591 choice_strings
[1] = "French";
592 choice_strings
[2] = "German";
593 choice_strings
[3] = "Spanish";
594 choice_strings
[4] = "Other";
595 pNativeLangChoice
= new wxChoice(this, EDITOR_DIALOG_LANG_CHOICE
, wxPoint(17, 346), wxSize(277, -1), 5, choice_strings
);
596 pNativeLangMsg
= new wxStaticText(this, EDITOR_DIALOG_LANG_MSG
, "Native language:", wxPoint(17, 330), wxSize(-1, -1), 0, "NativeLangMsg");
598 wxString radio_strings
[2];
599 radio_strings
[0] = "No";
600 radio_strings
[1] = "Yes";
601 pDeveloperRadio
= new wxRadioBox(this,EDITOR_DIALOG_DEVELOPER
,"Developer:",wxPoint(303,330),wxSize(-1,-1),2,radio_strings
,2,wxHORIZONTAL
);
603 pJoinDateMsg
= new wxStaticText(this, EDITOR_DIALOG_JOIN_MSG
, "Date joined:", wxPoint(17, 380), wxSize(-1, -1), 0, "JoinDateMsg");
604 pJoinDateTxt
= new wxTextCtrl(this, EDITOR_DIALOG_JOIN_TEXT
, "", wxPoint(17, 397), wxSize(150, 25), 0, wxDefaultValidator
, "JoinDateTxt");
606 pContribMsg
= new wxStaticText(this, EDITOR_DIALOG_CONTRIB_MSG
, "Contributions:", wxPoint(175, 380), wxSize(-1, -1), 0, "ContribMsg");
607 pContribTxt
= new wxTextCtrl(this, EDITOR_DIALOG_CONTRIB_TEXT
, "", wxPoint(175, 397), wxSize(120, 25), 0, wxDefaultValidator
, "ContribTxt");
609 pLinesMsg
= new wxStaticText(this, EDITOR_DIALOG_LINES_MSG
, "Lines of code:", wxPoint(303, 380), wxSize(-1, -1), 0, "LinesMsg");
610 pLinesTxt
= new wxTextCtrl(this, EDITOR_DIALOG_LINES_TEXT
, "", wxPoint(303, 397), wxSize(100, 25), 0, wxDefaultValidator
, "LinesTxt");
612 // Now that all the widgets on the panel are created, its safe to allow ::OnCommand() to
613 // handle all widget processing
614 widgetPtrsSet
= TRUE
;
616 // Setup the orderBy and where clauses to return back a single record as the result set,
617 // as there will only be one record being shown on the dialog at a time, this optimizes
618 // network traffic by only returning a one row result
620 Contact
->orderBy
= "NAME"; // field name to sort by
622 // The wxString "whereStr" is not a member of the wxTable object, it is a member variable
623 // specifically in the Ccontact class. It is used here for simpler construction of a varying
624 // length string, and then after the string is built, the wxTable member variable "where" is
625 // assigned the pointer to the constructed string.
627 // The constructed where clause below has a sub-query within it "SELECT MIN(NAME) FROM %s"
628 // to achieve a single row (in this case the first name in alphabetical order).
630 // commented out because PostgreSQL can't do this
631 if (Contact
->pDb
->Dbms() != dbmsPOSTGRES
)
633 Contact
->whereStr
.sprintf("NAME = (SELECT MIN(NAME) FROM %s)",Contact
->tableName
);
634 // NOTE: (const char*) returns a pointer which may not be valid later, so this is short term use only
635 Contact
->where
= (char*) (const char*) Contact
->whereStr
;
640 // Perform the Query to get the result set.
641 // NOTE: If there are no rows returned, that is a valid result, so Query() would return TRUE.
642 // Only if there is a database error will Query() come back as FALSE
643 if (!Contact
->Query())
646 tStr
= "ODBC error during Query()\n\n";
647 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
648 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
649 GetParent()->Close();
653 // Since Query succeeded, now get the row that was returned
654 if (!Contact
->GetNext())
655 // If the GetNext() failed at this point, then there are no rows to retrieve,
656 // so clear the values in the members of "Contact" so that PutData() blanks the
657 // widgets on the dialog
658 Contact
->Initialize();
664 } // CeditorDlg constructor
667 void CeditorDlg::OnCloseWindow(wxCloseEvent
& event
)
670 if ((mode
!= mCreate
) && (mode
!= mEdit
))
678 wxMessageBox("Must finish processing the current record being created/modified before exiting","Notice...",wxOK
| wxICON_INFORMATION
);
681 } // CeditorDlg::OnCloseWindow()
684 void CeditorDlg::OnButton( wxCommandEvent
&event
)
686 wxWindow
*win
= (wxWindow
*) event
.GetEventObject();
687 OnCommand( *win
, event
);
691 void CeditorDlg::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
695 widgetName
= win
.GetName();
700 if (widgetName
== pCreateBtn
->GetName())
702 Contact
->Initialize();
705 pNameTxt
->SetValue("");
706 pNameTxt
->SetFocus();
710 if (widgetName
== pEditBtn
->GetName())
712 saveName
= Contact
->Name
;
714 pNameTxt
->SetFocus();
718 if (widgetName
== pCopyBtn
->GetName())
721 pNameTxt
->SetValue("");
722 pNameTxt
->SetFocus();
726 if (widgetName
== pDeleteBtn
->GetName())
728 bool Ok
= (wxMessageBox("Are you sure?","Confirm",wxYES_NO
|wxICON_QUESTION
) == wxYES
);
733 if (Ok
&& Contact
->Delete())
735 // NOTE: Deletions are not finalized until a CommitTrans() is performed.
736 // If the commit were not performed, the program will continue to
737 // show the table contents as if they were deleted until this instance
738 // of Ccontact is deleted. If the Commit wasn't performed, the
739 // database will automatically Rollback the changes when the database
740 // connection is terminated
741 Contact
->pDb
->CommitTrans();
743 // Try to get the row that followed the just deleted row in the orderBy sequence
746 // There was now row (in sequence) after the just deleted row, so get the
747 // row which preceded the just deleted row
750 // There are now no rows remaining, so clear the dialog widgets
751 Contact
->Initialize();
755 SetMode(mode
); // force reset of button enable/disable
759 Contact
->pDb
->RollbackTrans();
765 if (widgetName
== pSaveBtn
->GetName())
771 if (widgetName
== pCancelBtn
->GetName())
773 bool Ok
= (wxMessageBox("Are you sure?","Confirm",wxYES_NO
|wxICON_QUESTION
) == wxYES
);
778 if (!strcmp((const char*) saveName
,""))
780 Contact
->Initialize();
787 // Requery previous record
788 if (Contact
->FetchByName((char*) (const char*) saveName
))
796 // Previous record not available, retrieve first record in table
797 if (Contact
->pDb
->Dbms() != dbmsPOSTGRES
)
799 // PostgreSQL can't do this
800 Contact
->whereStr
= "NAME = (SELECT MIN(NAME) FROM ";
801 Contact
->whereStr
+= Contact
->tableName
;
802 Contact
->whereStr
+= ")";
803 Contact
->where
= (char*) (const char*) Contact
->whereStr
;
808 if (!Contact
->Query())
811 tStr
= "ODBC error during Query()\n\n";
812 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
813 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
817 if (Contact
->GetNext()) // Successfully read first record
823 // No contacts are available, clear dialog
824 Contact
->Initialize();
830 if (widgetName
== pPrevBtn
->GetName())
837 if (widgetName
== pNextBtn
->GetName())
844 if (widgetName
== pQueryBtn
->GetName())
846 // Display the query dialog box
847 char qryWhere
[DB_MAX_WHERE_CLAUSE_LEN
+1];
848 strcpy(qryWhere
, (const char*) Contact
->qryWhereStr
);
849 char *tblName
[] = {(char *)CONTACT_TABLE_NAME
, 0};
850 new CqueryDlg(GetParent(), Contact
->pDb
, tblName
, qryWhere
);
852 // Query the first record in the new record set and
853 // display it, if the query string has changed.
854 if (strcmp(qryWhere
, (const char*) Contact
->qryWhereStr
))
857 // commented out because PostgreSQL can't do this
858 Contact
->whereStr
= "";
859 //Contact->orderBy = "NAME";
860 //Contact->whereStr = "NAME = (SELECT MIN(NAME) FROM ";
861 //Contact->whereStr += CONTACT_TABLE_NAME;
863 // Append the query where string (if there is one)
864 Contact
->qryWhereStr
= qryWhere
;
865 if (strlen(qryWhere
))
867 Contact
->whereStr
+= " WHERE ";
868 Contact
->whereStr
+= Contact
->qryWhereStr
;
870 // Close the expression with a right paren
871 // Contact->whereStr += ")";
873 Contact
->where
= (char*) (const char*) Contact
->whereStr
;
874 if (!Contact
->Query())
877 tStr
= "ODBC error during Query()\n\n";
878 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
879 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
882 // Display the first record from the query set
883 if (!Contact
->GetNext())
884 Contact
->Initialize();
888 // Enable/Disable the reset button
889 pResetBtn
->Enable(!Contact
->qryWhereStr
.IsEmpty());
895 if (widgetName
== pResetBtn
->GetName())
897 // Clear the additional where criteria established by the query feature
898 Contact
->qryWhereStr
= "";
900 // Query the first record in the table
901 Contact
->orderBy
= "NAME";
903 // commented out because PostgreSQL can't do this
904 //Contact->whereStr = "NAME = (SELECT MIN(NAME) FROM ";
905 //Contact->whereStr += CONTACT_TABLE_NAME;
906 //Contact->whereStr += ")";
908 Contact
->where
= (char*) (const char*) Contact
->whereStr
;
909 if (!Contact
->Query())
912 tStr
= "ODBC error during Query()\n\n";
913 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
914 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
917 if (!Contact
->GetNext())
918 Contact
->Initialize();
920 pResetBtn
->Enable(FALSE
);
926 if (widgetName
== pNameListBtn
->GetName())
928 new ClookUpDlg(/* wxWindow *parent */ this,
929 /* char *windowTitle */ "Select contact name",
930 /* char *tableName */ (char *) CONTACT_TABLE_NAME
,
931 /* char *dispCol1 */ "NAME",
932 /* char *dispCol2 */ "JOINDATE",
933 /* char *where */ "",
934 /* char *orderBy */ "NAME",
935 /* bool distinctValues */ TRUE
);
937 if (ListDB_Selection
&& strlen(ListDB_Selection
))
939 wxString w
= "NAME = '";
940 w
+= ListDB_Selection
;
942 GetRec((char*) (const char*) w
);
948 } // CeditorDlg::OnCommand()
951 void CeditorDlg::FieldsEditable()
953 pNameTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
954 pAddress1Txt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
955 pAddress2Txt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
956 pCityTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
957 pStateTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
958 pPostalCodeTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
959 pCountryTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
961 pJoinDateTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
962 pContribTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
963 pLinesTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
964 pNativeLangChoice
->Enable((mode
== mCreate
) || (mode
== mEdit
));
965 pDeveloperRadio
->Enable((mode
== mCreate
) || (mode
== mEdit
));
967 } // CeditorDlg::FieldsEditable()
970 void CeditorDlg::SetMode(enum DialogModes m
)
991 pCreateBtn
->Enable( !edit
);
992 pEditBtn
->Enable( !edit
&& (strcmp(Contact
->Name
,"")!=0) );
993 pDeleteBtn
->Enable( !edit
&& (strcmp(Contact
->Name
,"")!=0) );
994 pCopyBtn
->Enable( !edit
&& (strcmp(Contact
->Name
,"")!=0) );
995 pSaveBtn
->Enable( edit
);
996 pCancelBtn
->Enable( edit
);
997 pPrevBtn
->Enable( !edit
);
998 pNextBtn
->Enable( !edit
);
999 pQueryBtn
->Enable( !edit
);
1000 pResetBtn
->Enable( !edit
&& !Contact
->qryWhereStr
.IsEmpty() );
1001 pNameListBtn
->Enable( !edit
);
1005 } // CeditorDlg::SetMode()
1008 bool CeditorDlg::PutData()
1012 pNameTxt
->SetValue(Contact
->Name
);
1013 pAddress1Txt
->SetValue(Contact
->Addr1
);
1014 pAddress2Txt
->SetValue(Contact
->Addr2
);
1015 pCityTxt
->SetValue(Contact
->City
);
1016 pStateTxt
->SetValue(Contact
->State
);
1017 pCountryTxt
->SetValue(Contact
->Country
);
1018 pPostalCodeTxt
->SetValue(Contact
->PostalCode
);
1020 tStr
.Printf("%d/%d/%d",Contact
->JoinDate
.month
,Contact
->JoinDate
.day
,Contact
->JoinDate
.year
);
1021 pJoinDateTxt
->SetValue(tStr
);
1023 tStr
.Printf("%d",Contact
->Contributions
);
1024 pContribTxt
->SetValue(tStr
);
1026 tStr
.Printf("%lu",Contact
->LinesOfCode
);
1027 pLinesTxt
->SetValue(tStr
);
1029 pNativeLangChoice
->SetSelection(Contact
->NativeLanguage
);
1031 pDeveloperRadio
->SetSelection(Contact
->IsDeveloper
);
1034 } // Ceditor::PutData()
1038 * Reads the data out of all the widgets on the dialog. Some data evaluation is done
1039 * to ensure that there is a name entered and that the date field is valid.
1041 * A return value of TRUE means that valid data was retrieved from the dialog, otherwise
1042 * invalid data was found (and a message was displayed telling the user what to fix), and
1043 * the data was not placed into the appropraite fields of Ccontact
1045 bool CeditorDlg::GetData()
1047 // Validate that the data currently entered into the widgets is valid data
1050 tStr
= pNameTxt
->GetValue();
1051 if (!strcmp((const char*) tStr
,""))
1053 wxMessageBox("A name is required for entry into the contact table","Notice...",wxOK
| wxICON_INFORMATION
);
1057 bool invalid
= FALSE
;
1061 tStr
= pJoinDateTxt
->GetValue();
1062 if (tStr
.Freq('/') != 2)
1065 // Find the month, day, and year tokens
1068 first
= tStr
.First('/');
1069 second
= tStr
.Last('/');
1071 mm
= atoi(tStr
.SubString(0,first
));
1072 dd
= atoi(tStr
.SubString(first
+1,second
));
1073 yyyy
= atoi(tStr
.SubString(second
+1,tStr
.Length()-1));
1075 invalid
= !(mm
&& dd
&& yyyy
);
1078 // Force Year 2000 compliance
1079 if (!invalid
&& (yyyy
< 1000))
1082 // Check the token ranges for validity
1087 else if ((mm
< 1) || (mm
> 12))
1095 int days
[12] = {31,28,31,30,31,30,
1097 if (dd
> days
[mm
-1])
1100 if ((dd
== 29) && (mm
== 2))
1102 if (((yyyy
% 4) == 0) && (((yyyy
% 100) != 0) || ((yyyy
% 400) == 0)))
1112 Contact
->JoinDate
.month
= mm
;
1113 Contact
->JoinDate
.day
= dd
;
1114 Contact
->JoinDate
.year
= yyyy
;
1118 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
);
1122 tStr
= pNameTxt
->GetValue();
1123 strcpy(Contact
->Name
,(const char*) tStr
);
1124 strcpy(Contact
->Addr1
,pAddress1Txt
->GetValue());
1125 strcpy(Contact
->Addr2
,pAddress2Txt
->GetValue());
1126 strcpy(Contact
->City
,pCityTxt
->GetValue());
1127 strcpy(Contact
->State
,pStateTxt
->GetValue());
1128 strcpy(Contact
->Country
,pCountryTxt
->GetValue());
1129 strcpy(Contact
->PostalCode
,pPostalCodeTxt
->GetValue());
1131 Contact
->Contributions
= atoi(pContribTxt
->GetValue());
1132 Contact
->LinesOfCode
= atol(pLinesTxt
->GetValue());
1134 Contact
->NativeLanguage
= (enum Language
) pNativeLangChoice
->GetSelection();
1135 Contact
->IsDeveloper
= pDeveloperRadio
->GetSelection() > 0;
1138 } // CeditorDlg::GetData()
1142 * Retrieve data from the dialog, verify the validity of the data, and if it is valid,
1143 * try to insert/update the data to the table based on the current 'mode' the dialog
1146 * A return value of TRUE means the insert/update was completed successfully, a return
1147 * value of FALSE means that Save() failed. If returning FALSE, then this function
1148 * has displayed a detailed error message for the user.
1150 bool CeditorDlg::Save()
1152 bool failed
= FALSE
;
1154 // Read the data in the widgets of the dialog to get the user's data
1158 // Perform any other required validations necessary before saving
1161 wxBeginBusyCursor();
1163 if (mode
== mCreate
)
1165 RETCODE result
= Contact
->Insert();
1167 failed
= (result
!= DB_SUCCESS
);
1170 // Some errors may be expected, like a duplicate key, so handle those instances with
1171 // specific error messages.
1172 if (result
== DB_ERR_INTEGRITY_CONSTRAINT_VIOL
)
1175 tStr
= "A duplicate key value already exists in the table.\nUnable to save record\n\n";
1176 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
1177 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
1181 // Some other unexpexted error occurred
1183 tStr
= "Database insert failed\n\n";
1184 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
1185 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
1189 else // mode == mEdit
1191 if (!Contact
->Update())
1194 tStr
= "Database update failed\n\n";
1195 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
1196 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
1203 Contact
->pDb
->CommitTrans();
1204 SetMode(mView
); // Sets the dialog mode back to viewing after save is successful
1207 Contact
->pDb
->RollbackTrans();
1213 } // CeditorDlg::Save()
1217 * Where this program is only showing a single row at a time in the dialog,
1218 * a special where clause must be built to find just the single row which,
1219 * in sequence, would follow the currently displayed row.
1221 bool CeditorDlg::GetNextRec()
1225 if (Contact
->pDb
->Dbms() != dbmsPOSTGRES
)
1227 // PostgreSQL can't do this
1228 w
= "NAME = (SELECT MIN(NAME) FROM ";
1229 w
+= Contact
->tableName
;
1230 w
+= " WHERE NAME > '";
1238 // If a query where string is currently set, append that criteria
1239 if (!Contact
->qryWhereStr
.IsEmpty())
1242 w
+= Contact
->qryWhereStr
;
1247 return(GetRec((char*) (const char*) w
));
1249 } // CeditorDlg::GetNextRec()
1253 * Where this program is only showing a single row at a time in the dialog,
1254 * a special where clause must be built to find just the single row which,
1255 * in sequence, would precede the currently displayed row.
1257 bool CeditorDlg::GetPrevRec()
1261 if (Contact
->pDb
->Dbms() != dbmsPOSTGRES
)
1263 // PostgreSQL can't do this
1264 w
= "NAME = (SELECT MAX(NAME) FROM ";
1265 w
+= Contact
->tableName
;
1266 w
+= " WHERE NAME < '";
1274 // If a query where string is currently set, append that criteria
1275 if (!Contact
->qryWhereStr
.IsEmpty())
1278 w
+= Contact
->qryWhereStr
;
1284 return(GetRec((char*) (const char*)w
));
1286 } // CeditorDlg::GetPrevRec()
1290 * This function is here to avoid duplicating this same code in both the
1291 * GetPrevRec() and GetNextRec() functions
1293 bool CeditorDlg::GetRec(char *whereStr
)
1295 Contact
->where
= whereStr
;
1296 Contact
->orderBy
= "NAME";
1298 if (!Contact
->Query())
1301 tStr
= "ODBC error during Query()\n\n";
1302 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
1303 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
1308 if (Contact
->GetNext())
1315 } // CeditorDlg::GetRec()
1320 * CparameterDlg constructor
1323 BEGIN_EVENT_TABLE(CparameterDlg
, wxDialog
)
1324 EVT_BUTTON(PARAMETER_DIALOG_SAVE
, CparameterDlg::OnButton
)
1325 EVT_BUTTON(PARAMETER_DIALOG_CANCEL
, CparameterDlg::OnButton
)
1326 EVT_CLOSE(CparameterDlg::OnCloseWindow
)
1329 CparameterDlg::CparameterDlg(wxWindow
*parent
) : wxDialog (parent
, PARAMETER_DIALOG
, "ODBC parameter settings", wxPoint(-1, -1), wxSize(400, 325))
1331 // Since the ::OnCommand() function is overridden, this prevents the widget
1332 // detection in ::OnCommand() until all widgets have been initialized to prevent
1333 // uninitialized pointers from crashing the program
1334 widgetPtrsSet
= FALSE
;
1336 pParamODBCSourceMsg
= new wxStaticText(this, PARAMETER_DIALOG_SOURCE_MSG
, "ODBC data sources:", wxPoint(10, 10), wxSize(-1, -1), 0, "ParamODBCSourceMsg");
1337 pParamODBCSourceList
= new wxListBox(this, PARAMETER_DIALOG_SOURCE_LISTBOX
, wxPoint(10, 29), wxSize(285, 150), 0, 0, wxLB_SINGLE
|wxLB_ALWAYS_SB
, wxDefaultValidator
, "ParamODBCSourceList");
1339 pParamUserNameMsg
= new wxStaticText(this, PARAMETER_DIALOG_NAME_MSG
, "Database user name:", wxPoint(10, 193), wxSize(-1, -1), 0, "ParamUserNameMsg");
1340 pParamUserNameTxt
= new wxTextCtrl(this, PARAMETER_DIALOG_NAME_TEXT
, "", wxPoint(10, 209), wxSize(140, 25), 0, wxDefaultValidator
, "ParamUserNameTxt");
1342 pParamPasswordMsg
= new wxStaticText(this, PARAMETER_DIALOG_PASSWORD_MSG
, "Password:", wxPoint(156, 193), wxSize(-1, -1), 0, "ParamPasswordMsg");
1343 pParamPasswordTxt
= new wxTextCtrl(this, PARAMETER_DIALOG_PASSWORD_TEXT
, "", wxPoint(156, 209), wxSize(140, 25), 0, wxDefaultValidator
, "ParamPasswordTxt");
1345 pParamDirPathMsg
= new wxStaticText(this, PARAMETER_DIALOG_DIRPATH_MSG
, "Directory:", wxPoint(10, 243), wxSize(-1, -1), 0, "ParamDirPathMsg");
1346 pParamDirPathTxt
= new wxTextCtrl(this, PARAMETER_DIALOG_DIRPATH_TEXT
, "", wxPoint(10, 259), wxSize(140, 25), 0, wxDefaultValidator
, "ParamDirPathTxt");
1348 pParamSaveBtn
= new wxButton(this, PARAMETER_DIALOG_SAVE
, "&Save", wxPoint(310, 21), wxSize(70, 35), 0, wxDefaultValidator
, "ParamSaveBtn");
1349 pParamCancelBtn
= new wxButton(this, PARAMETER_DIALOG_CANCEL
, "C&ancel", wxPoint(310, 66), wxSize(70, 35), 0, wxDefaultValidator
, "ParamCancelBtn");
1351 // Now that all the widgets on the panel are created, its safe to allow ::OnCommand() to
1352 // handle all widget processing
1353 widgetPtrsSet
= TRUE
;
1356 savedParamSettings
= wxGetApp().params
;
1361 } // CparameterDlg constructor
1364 void CparameterDlg::OnCloseWindow(wxCloseEvent
& event
)
1366 // Put any additional checking necessary to make certain it is alright
1367 // to close the program here that is not done elsewhere
1370 bool Ok
= (wxMessageBox("No changes have been saved.\n\nAre you sure you wish exit the parameter screen?","Confirm",wxYES_NO
|wxICON_QUESTION
) == wxYES
);
1378 wxGetApp().params
= savedParamSettings
;
1381 if (GetParent() != NULL
)
1382 GetParent()->SetFocus();
1385 } // Cparameter::OnCloseWindow()
1388 void CparameterDlg::OnButton( wxCommandEvent
&event
)
1390 wxWindow
*win
= (wxWindow
*) event
.GetEventObject();
1391 OnCommand( *win
, event
);
1394 void CparameterDlg::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
1396 wxString widgetName
;
1398 widgetName
= win
.GetName();
1403 if (widgetName
== pParamSaveBtn
->GetName())
1408 tStr
= "Database parameters have been saved.";
1409 if (GetParent() != NULL
) // The parameter dialog was not called during startup due to a missing cfg file
1410 tStr
+= "\nNew parameters will take effect the next time the program is started.";
1411 wxMessageBox(tStr
,"Notice...",wxOK
| wxICON_INFORMATION
);
1418 if (widgetName
== pParamCancelBtn
->GetName())
1423 } // CparameterDlg::OnCommand()
1426 bool CparameterDlg::PutData()
1428 // Fill the data source list box
1429 FillDataSourceList();
1431 // Fill in the fields from the params object
1432 pParamODBCSourceList
->SetStringSelection(wxGetApp().params
.ODBCSource
);
1433 pParamUserNameTxt
->SetValue(wxGetApp().params
.UserName
);
1434 pParamPasswordTxt
->SetValue(wxGetApp().params
.Password
);
1435 pParamDirPathTxt
->SetValue(wxGetApp().params
.DirPath
);
1437 } // CparameterDlg::PutData()
1440 bool CparameterDlg::GetData()
1443 if (pParamODBCSourceList
->GetStringSelection())
1445 tStr
= pParamODBCSourceList
->GetStringSelection();
1446 if (tStr
.Length() > (sizeof(wxGetApp().params
.ODBCSource
)-1))
1449 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());
1450 wxMessageBox(errmsg
,"Internal program error...",wxOK
| wxICON_EXCLAMATION
);
1453 strcpy(wxGetApp().params
.ODBCSource
, tStr
);
1458 tStr
= pParamUserNameTxt
->GetValue();
1459 if (tStr
.Length() > (sizeof(wxGetApp().params
.UserName
)-1))
1462 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());
1463 wxMessageBox(errmsg
,"Internal program error...",wxOK
| wxICON_EXCLAMATION
);
1466 strcpy(wxGetApp().params
.UserName
, tStr
);
1468 tStr
= pParamPasswordTxt
->GetValue();
1469 if (tStr
.Length() > (sizeof(wxGetApp().params
.Password
)-1))
1472 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());
1473 wxMessageBox(errmsg
,"Internal program error...",wxOK
| wxICON_EXCLAMATION
);
1476 strcpy(wxGetApp().params
.Password
,tStr
);
1478 tStr
= pParamDirPathTxt
->GetValue();
1479 tStr
.Replace("\\","/");
1480 if (tStr
.Length() > (sizeof(wxGetApp().params
.DirPath
)-1))
1483 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());
1484 wxMessageBox(errmsg
,"Internal program error...",wxOK
| wxICON_EXCLAMATION
);
1487 strcpy(wxGetApp().params
.DirPath
,tStr
);
1489 } // CparameterDlg::GetData()
1492 bool CparameterDlg::Save()
1494 Cparameters saveParams
= wxGetApp().params
;
1497 wxGetApp().params
= saveParams
;
1502 if ((paramFile
= fopen(paramFilename
, "wt")) == NULL
)
1505 tStr
.Printf("Unable to write/overwrite '%s'.",paramFilename
);
1506 wxMessageBox(tStr
,"File I/O Error...",wxOK
| wxICON_EXCLAMATION
);
1510 fputs(wxGetApp().params
.ODBCSource
, paramFile
);
1511 fputc('\n', paramFile
);
1512 fputs(wxGetApp().params
.UserName
, paramFile
);
1513 fputc('\n', paramFile
);
1514 fputs(wxGetApp().params
.Password
, paramFile
);
1515 fputc('\n', paramFile
);
1516 fputs(wxGetApp().params
.DirPath
, paramFile
);
1517 fputc('\n', paramFile
);
1521 } // CparameterDlg::Save()
1524 void CparameterDlg::FillDataSourceList()
1526 char Dsn
[SQL_MAX_DSN_LENGTH
+ 1];
1528 wxStringList strList
;
1530 while(GetDataSource(DbConnectInf
.Henv
, Dsn
, SQL_MAX_DSN_LENGTH
+1, DsDesc
, 255))
1535 char **p
= strList
.ListToArray();
1537 for (int i
= 0; strlen(p
[i
]); i
++)
1538 pParamODBCSourceList
->Append(p
[i
]);
1539 } // CparameterDlg::CparameterDlg::FillDataSourceList()
1542 BEGIN_EVENT_TABLE(CqueryDlg
, wxDialog
)
1543 EVT_BUTTON(-1, CqueryDlg::OnButton
)
1544 EVT_CLOSE(CqueryDlg::OnCloseWindow
)
1547 // CqueryDlg() constructor
1548 CqueryDlg::CqueryDlg(wxWindow
*parent
, wxDB
*pDb
, char *tblName
[], char *pWhereArg
) : wxDialog (parent
, QUERY_DIALOG
, "Query", wxPoint(-1, -1), wxSize(480, 360))
1550 wxBeginBusyCursor();
1554 masterTableName
= tblName
[0];
1555 widgetPtrsSet
= FALSE
;
1558 // Initialize the WHERE clause from the string passed in
1559 pWhere
= pWhereArg
; // Save a pointer to the output buffer
1560 if (strlen(pWhere
) > DB_MAX_WHERE_CLAUSE_LEN
) // Check the length of the buffer passed in
1563 s
.Printf("Maximum where clause length exceeded.\nLength must be less than %d", DB_MAX_WHERE_CLAUSE_LEN
+1);
1564 wxMessageBox(s
,"Error...",wxOK
| wxICON_EXCLAMATION
);
1569 pQueryCol1Msg
= new wxStaticText(this, QUERY_DIALOG_COL_MSG
, "Column 1:", wxPoint(10, 10), wxSize(69, 16), 0, "QueryCol1Msg");
1570 pQueryCol1Choice
= new wxChoice(this, QUERY_DIALOG_COL_CHOICE
, wxPoint(10, 27), wxSize(250, 27), 0, 0, 0, wxDefaultValidator
, "QueryCol1Choice");
1572 pQueryNotMsg
= new wxStaticText(this, QUERY_DIALOG_NOT_MSG
, "NOT", wxPoint(268, 10), wxSize(-1, -1), 0, "QueryNotMsg");
1573 pQueryNotCheck
= new wxCheckBox(this, QUERY_DIALOG_NOT_CHECKBOX
, "", wxPoint(275, 37), wxSize(20, 20), 0, wxDefaultValidator
, "QueryNotCheck");
1575 wxString choice_strings
[9];
1576 choice_strings
[0] = "=";
1577 choice_strings
[1] = "<";
1578 choice_strings
[2] = ">";
1579 choice_strings
[3] = "<=";
1580 choice_strings
[4] = ">=";
1581 choice_strings
[5] = "Begins";
1582 choice_strings
[6] = "Contains";
1583 choice_strings
[7] = "Like";
1584 choice_strings
[8] = "Between";
1585 pQueryOperatorMsg
= new wxStaticText(this, QUERY_DIALOG_OP_MSG
, "Operator:", wxPoint(305, 10), wxSize(-1, -1), 0, "QueryOperatorMsg");
1586 pQueryOperatorChoice
= new wxChoice(this, QUERY_DIALOG_OP_CHOICE
, wxPoint(305, 27), wxSize(80, 27), 9, choice_strings
, 0, wxDefaultValidator
, "QueryOperatorChoice");
1588 pQueryCol2Msg
= new wxStaticText(this, QUERY_DIALOG_COL2_MSG
, "Column 2:", wxPoint(10, 65), wxSize(69, 16), 0, "QueryCol2Msg");
1589 pQueryCol2Choice
= new wxChoice(this, QUERY_DIALOG_COL2_CHOICE
, wxPoint(10, 82), wxSize(250, 27), 0, 0, 0, wxDefaultValidator
, "QueryCol2Choice");
1591 pQuerySqlWhereMsg
= new wxStaticText(this, QUERY_DIALOG_WHERE_MSG
, "SQL where clause:", wxPoint(10, 141), wxSize(-1, -1), 0, "QuerySqlWhereMsg");
1592 pQuerySqlWhereMtxt
= new wxTextCtrl(this, QUERY_DIALOG_WHERE_TEXT
, "", wxPoint(10, 159), wxSize(377, 134), wxTE_MULTILINE
, wxDefaultValidator
, "QuerySqlWhereMtxt");
1594 pQueryAddBtn
= new wxButton(this, QUERY_DIALOG_ADD
, "&Add", wxPoint(406, 24), wxSize(56, 26), 0, wxDefaultValidator
, "QueryAddBtn");
1595 pQueryAndBtn
= new wxButton(this, QUERY_DIALOG_AND
, "A&nd", wxPoint(406, 58), wxSize(56, 26), 0, wxDefaultValidator
, "QueryAndBtn");
1596 pQueryOrBtn
= new wxButton(this, QUERY_DIALOG_OR
, "&Or", wxPoint(406, 92), wxSize(56, 26), 0, wxDefaultValidator
, "QueryOrBtn");
1598 pQueryLParenBtn
= new wxButton(this, QUERY_DIALOG_LPAREN
, "(", wxPoint(406, 126), wxSize(26, 26), 0, wxDefaultValidator
, "QueryLParenBtn");
1599 pQueryRParenBtn
= new wxButton(this, QUERY_DIALOG_RPAREN
, ")", wxPoint(436, 126), wxSize(26, 26), 0, wxDefaultValidator
, "QueryRParenBtn");
1601 pQueryDoneBtn
= new wxButton(this, QUERY_DIALOG_DONE
, "&Done", wxPoint(406, 185), wxSize(56, 26), 0, wxDefaultValidator
, "QueryDoneBtn");
1602 pQueryClearBtn
= new wxButton(this, QUERY_DIALOG_CLEAR
, "C&lear", wxPoint(406, 218), wxSize(56, 26), 0, wxDefaultValidator
, "QueryClearBtn");
1603 pQueryCountBtn
= new wxButton(this, QUERY_DIALOG_COUNT
, "&Count", wxPoint(406, 252), wxSize(56, 26), 0, wxDefaultValidator
, "QueryCountBtn");
1605 pQueryValue1Msg
= new wxStaticText(this, QUERY_DIALOG_VALUE1_MSG
, "Value:", wxPoint(277, 66), wxSize(-1, -1), 0, "QueryValue1Msg");
1606 pQueryValue1Txt
= new wxTextCtrl(this, QUERY_DIALOG_VALUE1_TEXT
, "", wxPoint(277, 83), wxSize(108, 25), 0, wxDefaultValidator
, "QueryValue1Txt");
1608 pQueryValue2Msg
= new wxStaticText(this, QUERY_DIALOG_VALUE2_MSG
, "AND", wxPoint(238, 126), wxSize(-1, -1), 0, "QueryValue2Msg");
1609 pQueryValue2Txt
= new wxTextCtrl(this, QUERY_DIALOG_VALUE2_TEXT
, "", wxPoint(277, 120), wxSize(108, 25), 0, wxDefaultValidator
, "QueryValue2Txt");
1611 pQueryHintGrp
= new wxStaticBox(this, QUERY_DIALOG_HINT_GROUP
, "", wxPoint(10, 291), wxSize(377, 40), 0, "QueryHintGrp");
1612 pQueryHintMsg
= new wxStaticText(this, QUERY_DIALOG_HINT_MSG
, "", wxPoint(16, 306), wxSize(-1, -1), 0, "QueryHintMsg");
1614 widgetPtrsSet
= TRUE
;
1615 // Initialize the dialog
1617 pQueryCol2Choice
->Append("VALUE -->");
1618 colInf
= pDB
->GetColumns(tblName
);
1624 tStr
= "ODBC error during GetColumns()\n\n";
1625 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
1626 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
1630 for (int i
= 0; colInf
[i
].colName
&& strlen(colInf
[i
].colName
); i
++)
1632 // If there is more than one table being queried, qualify
1633 // the column names with the table name prefix.
1634 if (tblName
[1] && strlen(tblName
[1]))
1636 qualName
.Printf("%s.%s", colInf
[i
].tableName
, colInf
[i
].colName
);
1637 pQueryCol1Choice
->Append(qualName
);
1638 pQueryCol2Choice
->Append(qualName
);
1640 else // Single table query, append just the column names
1642 pQueryCol1Choice
->Append(colInf
[i
].colName
);
1643 pQueryCol2Choice
->Append(colInf
[i
].colName
);
1647 pQueryCol1Choice
->SetSelection(0);
1648 pQueryCol2Choice
->SetSelection(0);
1649 pQueryOperatorChoice
->SetSelection(0);
1651 pQueryValue2Msg
->Show(FALSE
);
1652 pQueryValue2Txt
->Show(FALSE
);
1654 pQueryHintMsg
->SetLabel(langQRY_EQ
);
1656 pQuerySqlWhereMtxt
->SetValue(pWhere
);
1660 // Display the dialog window
1664 } // CqueryDlg() constructor
1667 void CqueryDlg::OnButton( wxCommandEvent
&event
)
1669 wxWindow
*win
= (wxWindow
*) event
.GetEventObject();
1670 OnCommand( *win
, event
);
1673 void CqueryDlg::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
1675 // Widget pointers won't be set when the dialog is constructed.
1676 // Control is passed through this function once for each widget on
1677 // a dialog as the dialog is constructed.
1681 wxString widgetName
= win
.GetName();
1683 // Operator choice box
1684 if (widgetName
== pQueryOperatorChoice
->GetName())
1686 // Set the help text
1687 switch((qryOp
) pQueryOperatorChoice
->GetSelection())
1690 pQueryHintMsg
->SetLabel(langQRY_EQ
);
1693 pQueryHintMsg
->SetLabel(langQRY_LT
);
1696 pQueryHintMsg
->SetLabel(langQRY_GT
);
1699 pQueryHintMsg
->SetLabel(langQRY_LE
);
1702 pQueryHintMsg
->SetLabel(langQRY_GE
);
1705 pQueryHintMsg
->SetLabel(langQRY_BEGINS
);
1708 pQueryHintMsg
->SetLabel(langQRY_CONTAINS
);
1711 pQueryHintMsg
->SetLabel(langQRY_LIKE
);
1714 pQueryHintMsg
->SetLabel(langQRY_BETWEEN
);
1718 // Hide the value2 widget
1719 pQueryValue2Msg
->Show(FALSE
); // BETWEEN will show this widget
1720 pQueryValue2Txt
->Show(FALSE
); // BETWEEN will show this widget
1722 // Disable the NOT operator for <, <=, >, >=
1723 switch((qryOp
) pQueryOperatorChoice
->GetSelection())
1729 pQueryNotCheck
->SetValue(0);
1730 pQueryNotCheck
->Enable(FALSE
);
1733 pQueryNotCheck
->Enable(TRUE
);
1737 // Manipulate the dialog to handle the selected operator
1738 switch((qryOp
) pQueryOperatorChoice
->GetSelection())
1745 pQueryCol2Choice
->Enable(TRUE
);
1746 if (pQueryCol2Choice
->GetSelection()) // Column name is highlighted
1748 pQueryValue1Msg
->Show(FALSE
);
1749 pQueryValue1Txt
->Show(FALSE
);
1751 else // "Value" is highlighted
1753 pQueryValue1Msg
->Show(TRUE
);
1754 pQueryValue1Txt
->Show(TRUE
);
1755 pQueryValue1Txt
->SetFocus();
1761 pQueryCol2Choice
->SetSelection(0);
1762 pQueryCol2Choice
->Enable(FALSE
);
1763 pQueryValue1Msg
->Show(TRUE
);
1764 pQueryValue1Txt
->Show(TRUE
);
1765 pQueryValue1Txt
->SetFocus();
1768 pQueryCol2Choice
->SetSelection(0);
1769 pQueryCol2Choice
->Enable(FALSE
);
1770 pQueryValue2Msg
->Show(TRUE
);
1771 pQueryValue2Txt
->Show(TRUE
);
1772 pQueryValue1Msg
->Show(TRUE
);
1773 pQueryValue1Txt
->Show(TRUE
);
1774 pQueryValue1Txt
->SetFocus();
1780 } // Operator choice box
1783 if (widgetName
== pQueryCol2Choice
->GetName())
1785 if (pQueryCol2Choice
->GetSelection()) // Column name is highlighted
1787 pQueryValue1Msg
->Show(FALSE
);
1788 pQueryValue1Txt
->Show(FALSE
);
1790 else // "Value" is highlighted
1792 pQueryValue1Msg
->Show(TRUE
);
1793 pQueryValue1Txt
->Show(TRUE
);
1794 pQueryValue1Txt
->SetFocus();
1798 } // Column 2 choice
1801 if (widgetName
== pQueryAddBtn
->GetName())
1809 if (widgetName
== pQueryAndBtn
->GetName())
1811 AppendToWhere(" AND\n");
1817 if (widgetName
== pQueryOrBtn
->GetName())
1819 AppendToWhere(" OR\n");
1824 // Left Paren button
1825 if (widgetName
== pQueryLParenBtn
->GetName())
1830 } // Left Paren button
1832 // Right paren button
1833 if (widgetName
== pQueryRParenBtn
->GetName())
1838 } // Right Paren button
1841 if (widgetName
== pQueryDoneBtn
->GetName())
1843 // Be sure the where clause will not overflow the output buffer
1844 if (strlen(pQuerySqlWhereMtxt
->GetValue()) > DB_MAX_WHERE_CLAUSE_LEN
)
1847 s
.Printf("Maximum where clause length exceeded.\nLength must be less than %d", DB_MAX_WHERE_CLAUSE_LEN
+1);
1848 wxMessageBox(s
,"Error...",wxOK
| wxICON_EXCLAMATION
);
1851 // Validate the where clause for things such as matching parens
1852 if (!ValidateWhereClause())
1854 // Copy the where clause to the output buffer and exit
1855 strcpy(pWhere
, pQuerySqlWhereMtxt
->GetValue());
1862 if (widgetName
== pQueryClearBtn
->GetName())
1864 bool Ok
= (wxMessageBox("Are you sure you wish to clear the Query?","Confirm",wxYES_NO
|wxICON_QUESTION
) == wxYES
);
1867 pQuerySqlWhereMtxt
->SetValue("");
1873 if (widgetName
== pQueryCountBtn
->GetName())
1875 wxBeginBusyCursor();
1882 } // CqueryDlg::OnCommand
1885 void CqueryDlg::OnCloseWindow(wxCloseEvent
& event
)
1900 GetParent()->SetFocus();
1906 } // CqueryDlg::OnCloseWindow()
1909 bool CqueryDlg::SetWidgetPtrs()
1913 abort = abort || !(pQueryCol1Choice = (wxChoice *)GetWidgetPtr("QueryCol1Choice",this));
1914 abort = abort || !(pQueryNotCheck = (wxCheckBox *)GetWidgetPtr("QueryNotCheck",this));
1915 abort = abort || !(pQueryOperatorChoice = (wxChoice *)GetWidgetPtr("QueryOperatorChoice",this));
1916 abort = abort || !(pQueryCol2Choice = (wxChoice *)GetWidgetPtr("QueryCol2Choice",this));
1917 abort = abort || !(pQueryValue1Txt = (wxTextCtrl *)GetWidgetPtr("QueryValue1Txt",this));
1918 abort = abort || !(pQueryValue2Txt = (wxTextCtrl *)GetWidgetPtr("QueryValue2Txt",this));
1919 abort = abort || !(pQuerySqlWhereMtxt = (wxMultiText *)GetWidgetPtr("QuerySqlWhereMtxt",this));
1920 abort = abort || !(pQueryAddBtn = (wxButton *)GetWidgetPtr("QueryAddBtn",this));
1921 abort = abort || !(pQueryAndBtn = (wxButton *)GetWidgetPtr("QueryAndBtn",this));
1922 abort = abort || !(pQueryOrBtn = (wxButton *)GetWidgetPtr("QueryOrBtn",this));
1923 abort = abort || !(pQueryLParenBtn = (wxButton *)GetWidgetPtr("QueryLParenBtn",this));
1924 abort = abort || !(pQueryRParenBtn = (wxButton *)GetWidgetPtr("QueryRParenBtn",this));
1925 abort = abort || !(pQueryDoneBtn = (wxButton *)GetWidgetPtr("QueryDoneBtn",this));
1926 abort = abort || !(pQueryClearBtn = (wxButton *)GetWidgetPtr("QueryClearBtn",this));
1927 abort = abort || !(pQueryCountBtn = (wxButton *)GetWidgetPtr("QueryCountBtn",this));
1928 abort = abort || !(pQueryHelpBtn = (wxButton *)GetWidgetPtr("QueryHelpBtn",this));
1929 abort = abort || !(pQueryHintMsg = (wxStaticText *)GetWidgetPtr("QueryHintMsg",this));
1933 return(widgetPtrsSet = !abort);
1935 } // CqueryDlg::SetWidgetPtrs
1938 void CqueryDlg::AppendToWhere(char *s
)
1940 wxString whereStr
= pQuerySqlWhereMtxt
->GetValue();
1942 pQuerySqlWhereMtxt
->SetValue(whereStr
);
1944 } // CqueryDlg::AppendToWhere()
1947 void CqueryDlg::ProcessAddBtn()
1949 qryOp oper
= (qryOp
) pQueryOperatorChoice
->GetSelection();
1951 // Verify that eveything is filled in correctly
1952 if (pQueryCol2Choice
->GetSelection() == 0) // "Value" is selected
1954 // Verify that value 1 is filled in
1955 if (strlen(pQueryValue1Txt
->GetValue()) == 0)
1958 pQueryValue1Txt
->SetFocus();
1961 // For the BETWEEN operator, value 2 must be filled in as well
1962 if (oper
== qryOpBETWEEN
&&
1963 strlen(pQueryValue2Txt
->GetValue()) == 0)
1966 pQueryValue2Txt
->SetFocus();
1971 // Build the expression and append it to the where clause window
1972 wxString s
= pQueryCol1Choice
->GetStringSelection();
1974 if (pQueryNotCheck
->GetValue() && (oper
!= qryOpEQ
))
1980 if (pQueryNotCheck
->GetValue()) // NOT box is checked
2009 int col1Idx
= pQueryCol1Choice
->GetSelection();
2012 if (colInf
[col1Idx
].sqlDataType
== SQL_VARCHAR
||
2013 oper
== qryOpBEGINS
||
2014 oper
== qryOpCONTAINS
||
2018 if (pQueryCol2Choice
->GetSelection()) // Column name
2019 s
+= pQueryCol2Choice
->GetStringSelection();
2020 else // Column 2 is a "value"
2024 if (oper
== qryOpCONTAINS
)
2026 s
+= pQueryValue1Txt
->GetValue();
2027 if (oper
== qryOpCONTAINS
|| oper
== qryOpBEGINS
)
2033 if (oper
== qryOpBETWEEN
)
2038 s
+= pQueryValue2Txt
->GetValue();
2043 AppendToWhere((char*) (const char*) s
);
2045 } // CqueryDlg::ProcessAddBtn()
2048 void CqueryDlg::ProcessCountBtn()
2050 if (!ValidateWhereClause())
2053 if (dbTable
== 0) // wxTable object needs to be created and opened
2055 if (!(dbTable
= new wxTable(pDB
, masterTableName
, 0, NULL
, !QUERY_ONLY
, DbConnectInf
.defaultDir
)))
2057 wxMessageBox("Memory allocation failed creating a wxTable object.","Error...",wxOK
| wxICON_EXCLAMATION
);
2060 if (!dbTable
->Open())
2063 tStr
= "ODBC error during Open()\n\n";
2064 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
2065 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
2070 // Count() with WHERE clause
2071 dbTable
->where
= (char*) (const char*) pQuerySqlWhereMtxt
->GetValue();
2072 ULONG whereCnt
= dbTable
->Count();
2074 // Count() of all records in the table
2076 ULONG totalCnt
= dbTable
->Count();
2078 if (whereCnt
> 0 || totalCnt
== 0)
2081 tStr
.Printf("%lu of %lu records match the query criteria.",whereCnt
,totalCnt
);
2082 wxMessageBox(tStr
,"Notice...",wxOK
| wxICON_INFORMATION
);
2087 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
);
2088 wxMessageBox(tStr
,"Notice...",wxOK
| wxICON_INFORMATION
);
2091 // After a wxMessageBox, the focus does not necessarily return to the
2092 // window which was the focus when the message box popped up, so return
2093 // focus to the Query dialog for certain
2096 } // CqueryDlg::ProcessCountBtn()
2099 bool CqueryDlg::ValidateWhereClause()
2101 wxString where
= pQuerySqlWhereMtxt
->GetValue();
2103 if (where
.Freq('(') != where
.Freq(')'))
2105 wxMessageBox("There are mismatched parenthesis in the constructed where clause","Error...",wxOK
| wxICON_EXCLAMATION
);
2108 // After a wxMessageBox, the focus does not necessarily return to the
2109 // window which was the focus when the message box popped up, so return
2110 // focus to the Query dialog for certain
2115 } // CqueryDlg::ValidateWhereClause()