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
);
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
[strlen(buffer
)-1] = '\0';
191 strcpy(params
.ODBCSource
,buffer
);
193 fgets(buffer
, sizeof(params
.UserName
), paramFile
);
194 buffer
[strlen(buffer
)-1] = '\0';
195 strcpy(params
.UserName
,buffer
);
197 fgets(buffer
, sizeof(params
.Password
), paramFile
);
198 buffer
[strlen(buffer
)-1] = '\0';
199 strcpy(params
.Password
,buffer
);
201 fgets(buffer
, sizeof(params
.DirPath
), paramFile
);
202 buffer
[strlen(buffer
)-1] = '\0';
203 strcpy(params
.DirPath
,buffer
);
207 // Connect to datasource
208 strcpy(DbConnectInf
.Dsn
, params
.ODBCSource
); // ODBC data source name (created with ODBC Administrator under Win95/NT)
209 strcpy(DbConnectInf
.Uid
, params
.UserName
); // database username - must already exist in the data source
210 strcpy(DbConnectInf
.AuthStr
, params
.Password
); // password database username
211 strcpy(DbConnectInf
.defaultDir
,params
.DirPath
); // path where the table exists (needed for dBase)
213 READONLY_DB
= GetDbConnection(&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 strcpy(DbConnectInf
.Dsn
, "");
219 strcpy(DbConnectInf
.Uid
, "");
220 strcpy(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 } // DatabaseDemoFrame::OnCloseWindow()
281 void DatabaseDemoFrame::CreateDataTable()
283 bool Ok
= (wxMessageBox("Any data currently residing in the table will be erased.\n\nAre you sure?","Confirm",wxYES_NO
|wxICON_QUESTION
) == wxYES
);
292 Ccontact
*Contact
= new Ccontact();
296 wxMessageBox("Error allocating memory for 'Ccontact'object.\n\nTable was not created.","Error...",wxOK
| wxICON_EXCLAMATION
);
300 if (!Contact
->CreateTable(FALSE
))
304 tStr
= "Error creating CONTACTS table.\nTable was not created.\n\n";
305 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
306 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
311 if (!Contact
->CreateIndexes())
315 tStr
= "Error creating CONTACTS indexes.\nIndexes will be unavailable.\n\n";
316 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
317 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
327 wxMessageBox("Table and index(es) were successfully created.","Notice...",wxOK
| wxICON_INFORMATION
);
328 } // DatabaseDemoFrame::CreateDataTable()
331 void DatabaseDemoFrame::BuildEditorDialog()
333 pEditorDlg
= new CeditorDlg(this);
335 wxMessageBox("Unable to create the editor dialog for some reason","Error...",wxOK
| wxICON_EXCLAMATION
);
336 } // DatabaseDemoFrame::BuildEditorDialog()
339 void DatabaseDemoFrame::BuildParameterDialog(wxWindow
*parent
)
341 pParamDlg
= new CparameterDlg(parent
);
344 wxMessageBox("Unable to create the parameter dialog for some reason","Error...",wxOK
| wxICON_EXCLAMATION
);
345 } // DatabaseDemoFrame::BuildParameterDialog()
349 * Constructor note: If no wxDB object is passed in, a new connection to the database
350 * is created for this instance of Ccontact. This can be a slow process depending
351 * on the database engine being used, and some database engines have a limit on the
352 * number of connections (either hard limits, or license restricted) so care should
353 * be used to use as few connections as is necessary.
354 * IMPORTANT: Objects which share a wxDB pointer are ALL acted upon whenever a member
355 * function of pDb is called (i.e. CommitTrans() or RollbackTrans(), so if modifying
356 * or creating a table objects which use the same pDb, know that all the objects
357 * will be committed or rolled back when any of the objects has this function call made.
359 Ccontact::Ccontact (wxDB
*pwxDB
) : wxTable(pwxDB
? pwxDB
: GetDbConnection(&DbConnectInf
),CONTACT_TABLE_NAME
,CONTACT_NO_COLS
,NULL
,!QUERY_ONLY
,DbConnectInf
.defaultDir
)
361 // This is used to represent whether the database connection should be released
362 // when this instance of the object is deleted. If using the same connection
363 // for multiple instance of database objects, then the connection should only be
364 // released when the last database instance using the connection is deleted
369 } // Ccontact Constructor
372 void Ccontact::Initialize()
381 JoinDate
.year
= 1980;
387 JoinDate
.fraction
= 0;
388 NativeLanguage
= langENGLISH
;
392 } // Ccontact::Initialize
395 Ccontact::~Ccontact()
399 if (!FreeDbConnection(pDb
))
402 tStr
= "Unable to Free the Ccontact data table handle\n\n";
403 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
404 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
407 } // Ccontract destructor
411 * Handles setting up all the connections for the interface from the wxTable
412 * functions to interface to the data structure used to store records in
413 * memory, and for all the column definitions that define the table structure
415 void Ccontact::SetupColumns()
417 // NOTE: Columns now are 8 character names, as that is all dBase can support. Longer
418 // names can be used for other database engines
419 SetColDefs ( 0,"NAME", DB_DATA_TYPE_VARCHAR
, Name
, SQL_C_CHAR
, sizeof(Name
), TRUE
, TRUE
); // Primary index
420 SetColDefs ( 1,"ADDRESS1", DB_DATA_TYPE_VARCHAR
, Addr1
, SQL_C_CHAR
, sizeof(Addr1
), FALSE
,TRUE
);
421 SetColDefs ( 2,"ADDRESS2", DB_DATA_TYPE_VARCHAR
, Addr2
, SQL_C_CHAR
, sizeof(Addr2
), FALSE
,TRUE
);
422 SetColDefs ( 3,"CITY", DB_DATA_TYPE_VARCHAR
, City
, SQL_C_CHAR
, sizeof(City
), FALSE
,TRUE
);
423 SetColDefs ( 4,"STATE", DB_DATA_TYPE_VARCHAR
, State
, SQL_C_CHAR
, sizeof(State
), FALSE
,TRUE
);
424 SetColDefs ( 5,"POSTCODE", DB_DATA_TYPE_VARCHAR
, PostalCode
, SQL_C_CHAR
, sizeof(PostalCode
), FALSE
,TRUE
);
425 SetColDefs ( 6,"COUNTRY", DB_DATA_TYPE_VARCHAR
, Country
, SQL_C_CHAR
, sizeof(Country
), FALSE
,TRUE
);
426 SetColDefs ( 7,"JOINDATE", DB_DATA_TYPE_DATE
, &JoinDate
, SQL_C_TIMESTAMP
, sizeof(JoinDate
), FALSE
,TRUE
);
427 SetColDefs ( 8,"IS_DEV", DB_DATA_TYPE_INTEGER
, &IsDeveloper
, SQL_C_BOOLEAN(IsDeveloper
),sizeof(IsDeveloper
), FALSE
,TRUE
);
428 SetColDefs ( 9,"CONTRIBS", DB_DATA_TYPE_INTEGER
, &Contributions
, SQL_C_USHORT
, sizeof(Contributions
), FALSE
,TRUE
);
429 SetColDefs (10,"LINE_CNT", DB_DATA_TYPE_INTEGER
, &LinesOfCode
, SQL_C_ULONG
, sizeof(LinesOfCode
), FALSE
,TRUE
);
430 SetColDefs (11,"LANGUAGE", DB_DATA_TYPE_INTEGER
, &NativeLanguage
, SQL_C_ENUM
, sizeof(NativeLanguage
), FALSE
,TRUE
);
431 } // Ccontact::SetupColumns
434 bool Ccontact::CreateIndexes(void)
436 // This index could easily be accomplished with an "orderBy" clause,
437 // but is done to show how to construct a non-primary index.
443 strcpy(idxDef
[0].ColName
, "IS_DEV");
444 idxDef
[0].Ascending
= TRUE
;
446 strcpy(idxDef
[1].ColName
, "NAME");
447 idxDef
[1].Ascending
= TRUE
;
449 indexName
= CONTACT_TABLE_NAME
;
450 indexName
+= "_IDX1";
451 Ok
= CreateIndex((char*) (const char*) indexName
, TRUE
, 2, idxDef
);
454 } // Ccontact::CreateIndexes()
458 * Having a function to do a query on the primary key (and possibly others) is
459 * very efficient and tighter coding so that it is available where ever the object
460 * is. Great for use with multiple tables when not using views or outer joins
462 bool Ccontact::FetchByName(char *name
)
464 whereStr
.Printf("NAME = '%s'",name
);
465 where
= (char*) (const char*) this->whereStr
;
474 } // Ccontact::FetchByName()
479 * ************* DIALOGS ***************
484 /* CeditorDlg constructor
486 * Creates the dialog used for creating/editing/deleting/copying a Ccontact object.
487 * This dialog actually is drawn in the main frame of the program
489 * An instance of Ccontact is created - "Contact" - which is used to hold the Ccontact
490 * object that is currently being worked with.
493 BEGIN_EVENT_TABLE(CeditorDlg
, wxPanel
)
494 EVT_BUTTON(-1, CeditorDlg::OnButton
)
497 CeditorDlg::CeditorDlg(wxWindow
*parent
) : wxPanel (parent
, 1, 1, 460, 455)
499 // Since the ::OnCommand() function is overridden, this prevents the widget
500 // detection in ::OnCommand() until all widgets have been initialized to prevent
501 // uninitialized pointers from crashing the program
502 widgetPtrsSet
= FALSE
;
504 // Create the data structure and a new database connection.
505 // (As there is not a pDb being passed in the constructor, a new database
506 // connection is created)
507 Contact
= new Ccontact();
511 wxMessageBox("Unable to instantiate an instance of Ccontact","Error...",wxOK
| wxICON_EXCLAMATION
);
515 // Check if the table exists or not. If it doesn't, ask the user if they want to
516 // create the table. Continue trying to create the table until it exists, or user aborts
517 while (!Contact
->pDb
->TableExists((char *)CONTACT_TABLE_NAME
,DbConnectInf
.Uid
,DbConnectInf
.defaultDir
))
520 tStr
.Printf("Unable to open the table '%s'.\n\nTable may need to be created...?\n\n",CONTACT_TABLE_NAME
);
521 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
522 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
524 bool createTable
= (wxMessageBox("Do you wish to try to create/clear the CONTACTS table?","Confirm",wxYES_NO
|wxICON_QUESTION
) == wxYES
);
534 DemoFrame
->CreateDataTable();
537 // Tables must be "opened" before anything other than creating/deleting table can be done
538 if (!Contact
->Open())
540 // Table does exist, there was some problem opening it. Currently this should
541 // never fail, except in the case of the table not exisiting. Open() basically
542 // only sets up variable/pointer values, other than checking for table existence.
543 if (Contact
->pDb
->TableExists((char *)CONTACT_TABLE_NAME
))
546 tStr
.Printf("Unable to open the table '%s'.\n\n",CONTACT_TABLE_NAME
);
547 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
548 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
558 (void)new wxStaticBox(this, EDITOR_DIALOG_FN_GROUP
, "", wxPoint(15, 1), wxSize(497, 69), 0, "FunctionGrp");
559 (void)new wxStaticBox(this, EDITOR_DIALOG_SEARCH_GROUP
, "", wxPoint(417, 1), wxSize(95, 242), 0, "SearchGrp");
561 pCreateBtn
= new wxButton(this, EDITOR_DIALOG_CREATE
, "&Create", wxPoint(25, 21), wxSize(70, 35), 0, wxDefaultValidator
, "CreateBtn");
562 pEditBtn
= new wxButton(this, EDITOR_DIALOG_EDIT
, "&Edit", wxPoint(102, 21), wxSize(70, 35), 0, wxDefaultValidator
, "EditBtn");
563 pDeleteBtn
= new wxButton(this, EDITOR_DIALOG_DELETE
, "&Delete", wxPoint(179, 21), wxSize(70, 35), 0, wxDefaultValidator
, "DeleteBtn");
564 pCopyBtn
= new wxButton(this, EDITOR_DIALOG_COPY
, "Cop&y", wxPoint(256, 21), wxSize(70, 35), 0, wxDefaultValidator
, "CopyBtn");
565 pSaveBtn
= new wxButton(this, EDITOR_DIALOG_SAVE
, "&Save", wxPoint(333, 21), wxSize(70, 35), 0, wxDefaultValidator
, "SaveBtn");
566 pCancelBtn
= new wxButton(this, EDITOR_DIALOG_CANCEL
, "C&ancel", wxPoint(430, 21), wxSize(70, 35), 0, wxDefaultValidator
, "CancelBtn");
568 pPrevBtn
= new wxButton(this, EDITOR_DIALOG_PREV
, "<< &Prev", wxPoint(430, 81), wxSize(70, 35), 0, wxDefaultValidator
, "PrevBtn");
569 pNextBtn
= new wxButton(this, EDITOR_DIALOG_NEXT
, "&Next >>", wxPoint(430, 121), wxSize(70, 35), 0, wxDefaultValidator
, "NextBtn");
570 pQueryBtn
= new wxButton(this, EDITOR_DIALOG_QUERY
, "&Query", wxPoint(430, 161), wxSize(70, 35), 0, wxDefaultValidator
, "QueryBtn");
571 pResetBtn
= new wxButton(this, EDITOR_DIALOG_RESET
, "&Reset", wxPoint(430, 200), wxSize(70, 35), 0, wxDefaultValidator
, "ResetBtn");
573 pNameMsg
= new wxStaticText(this, EDITOR_DIALOG_NAME_MSG
, "Name:", wxPoint(17, 80), wxSize(-1, -1), 0, "NameMsg");
574 pNameTxt
= new wxTextCtrl(this, EDITOR_DIALOG_NAME_TEXT
, "", wxPoint(17, 97), wxSize(308, 25), 0, wxDefaultValidator
, "NameTxt");
575 pNameListBtn
= new wxButton(this, EDITOR_DIALOG_LOOKUP
, "&Lookup", wxPoint(333, 99), wxSize(70, 24), 0, wxDefaultValidator
, "LookupBtn");
577 pAddress1Msg
= new wxStaticText(this, EDITOR_DIALOG_ADDRESS1_MSG
, "Address:", wxPoint(17, 130), wxSize(-1, -1), 0, "Address1Msg");
578 pAddress1Txt
= new wxTextCtrl(this, EDITOR_DIALOG_ADDRESS2_TEXT
, "", wxPoint(17, 147), wxSize(308, 25), 0, wxDefaultValidator
, "Address1Txt");
580 pAddress2Msg
= new wxStaticText(this, EDITOR_DIALOG_ADDRESS2_MSG
, "Address:", wxPoint(17, 180), wxSize(-1, -1), 0, "Address2Msg");
581 pAddress2Txt
= new wxTextCtrl(this, EDITOR_DIALOG_ADDRESS2_TEXT
, "", wxPoint(17, 197), wxSize(308, 25), 0, wxDefaultValidator
, "Address2Txt");
583 pCityMsg
= new wxStaticText(this, EDITOR_DIALOG_CITY_MSG
, "City:", wxPoint(17, 230), wxSize(-1, -1), 0, "CityMsg");
584 pCityTxt
= new wxTextCtrl(this, EDITOR_DIALOG_CITY_TEXT
, "", wxPoint(17, 247), wxSize(225, 25), 0, wxDefaultValidator
, "CityTxt");
586 pStateMsg
= new wxStaticText(this, EDITOR_DIALOG_STATE_MSG
, "State:", wxPoint(250, 230), wxSize(-1, -1), 0, "StateMsg");
587 pStateTxt
= new wxTextCtrl(this, EDITOR_DIALOG_STATE_TEXT
, "", wxPoint(250, 247), wxSize(153, 25), 0, wxDefaultValidator
, "StateTxt");
589 pCountryMsg
= new wxStaticText(this, EDITOR_DIALOG_COUNTRY_MSG
, "Country:", wxPoint(17, 280), wxSize(-1, -1), 0, "CountryMsg");
590 pCountryTxt
= new wxTextCtrl(this, EDITOR_DIALOG_COUNTRY_TEXT
, "", wxPoint(17, 297), wxSize(225, 25), 0, wxDefaultValidator
, "CountryTxt");
592 pPostalCodeMsg
= new wxStaticText(this, EDITOR_DIALOG_POSTAL_MSG
, "Postal Code:", wxPoint(250, 280), wxSize(-1, -1), 0, "PostalCodeMsg");
593 pPostalCodeTxt
= new wxTextCtrl(this, EDITOR_DIALOG_POSTAL_TEXT
, "", wxPoint(250, 297), wxSize(153, 25), 0, wxDefaultValidator
, "PostalCodeTxt");
595 wxString choice_strings
[5];
596 choice_strings
[0] = "English";
597 choice_strings
[1] = "French";
598 choice_strings
[2] = "German";
599 choice_strings
[3] = "Spanish";
600 choice_strings
[4] = "Other";
601 pNativeLangChoice
= new wxChoice(this, EDITOR_DIALOG_LANG_CHOICE
, wxPoint(17, 346), wxSize(277, -1), 5, choice_strings
);
602 pNativeLangMsg
= new wxStaticText(this, EDITOR_DIALOG_LANG_MSG
, "Native language:", wxPoint(17, 330), wxSize(-1, -1), 0, "NativeLangMsg");
604 wxString radio_strings
[2];
605 radio_strings
[0] = "No";
606 radio_strings
[1] = "Yes";
607 pDeveloperRadio
= new wxRadioBox(this,EDITOR_DIALOG_DEVELOPER
,"Developer:",wxPoint(303,330),wxSize(-1,-1),2,radio_strings
,2,wxHORIZONTAL
);
609 pJoinDateMsg
= new wxStaticText(this, EDITOR_DIALOG_JOIN_MSG
, "Date joined:", wxPoint(17, 380), wxSize(-1, -1), 0, "JoinDateMsg");
610 pJoinDateTxt
= new wxTextCtrl(this, EDITOR_DIALOG_JOIN_TEXT
, "", wxPoint(17, 397), wxSize(150, 25), 0, wxDefaultValidator
, "JoinDateTxt");
612 pContribMsg
= new wxStaticText(this, EDITOR_DIALOG_CONTRIB_MSG
, "Contributions:", wxPoint(175, 380), wxSize(-1, -1), 0, "ContribMsg");
613 pContribTxt
= new wxTextCtrl(this, EDITOR_DIALOG_CONTRIB_TEXT
, "", wxPoint(175, 397), wxSize(120, 25), 0, wxDefaultValidator
, "ContribTxt");
615 pLinesMsg
= new wxStaticText(this, EDITOR_DIALOG_LINES_MSG
, "Lines of code:", wxPoint(303, 380), wxSize(-1, -1), 0, "LinesMsg");
616 pLinesTxt
= new wxTextCtrl(this, EDITOR_DIALOG_LINES_TEXT
, "", wxPoint(303, 397), wxSize(100, 25), 0, wxDefaultValidator
, "LinesTxt");
618 // Now that all the widgets on the panel are created, its safe to allow ::OnCommand() to
619 // handle all widget processing
620 widgetPtrsSet
= TRUE
;
622 // Setup the orderBy and where clauses to return back a single record as the result set,
623 // as there will only be one record being shown on the dialog at a time, this optimizes
624 // network traffic by only returning a one row result
626 Contact
->orderBy
= "NAME"; // field name to sort by
628 // The wxString "whereStr" is not a member of the wxTable object, it is a member variable
629 // specifically in the Ccontact class. It is used here for simpler construction of a varying
630 // length string, and then after the string is built, the wxTable member variable "where" is
631 // assigned the pointer to the constructed string.
633 // The constructed where clause below has a sub-query within it "SELECT MIN(NAME) FROM %s"
634 // to achieve a single row (in this case the first name in alphabetical order).
636 // commented out because PostgreSQL can't do this
637 if (Contact
->pDb
->Dbms() != dbmsPOSTGRES
)
639 Contact
->whereStr
.sprintf("NAME = (SELECT MIN(NAME) FROM %s)",Contact
->tableName
);
640 // NOTE: (const char*) returns a pointer which may not be valid later, so this is short term use only
641 Contact
->where
= (char*) (const char*) Contact
->whereStr
;
646 // Perform the Query to get the result set.
647 // NOTE: If there are no rows returned, that is a valid result, so Query() would return TRUE.
648 // Only if there is a database error will Query() come back as FALSE
649 if (!Contact
->Query())
652 tStr
= "ODBC error during Query()\n\n";
653 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
654 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
655 GetParent()->Close();
659 // Since Query succeeded, now get the row that was returned
660 if (!Contact
->GetNext())
661 // If the GetNext() failed at this point, then there are no rows to retrieve,
662 // so clear the values in the members of "Contact" so that PutData() blanks the
663 // widgets on the dialog
664 Contact
->Initialize();
670 } // CeditorDlg constructor
673 void CeditorDlg::OnCloseWindow(wxCloseEvent
& event
)
676 if ((mode
!= mCreate
) && (mode
!= mEdit
))
684 wxMessageBox("Must finish processing the current record being created/modified before exiting","Notice...",wxOK
| wxICON_INFORMATION
);
687 } // CeditorDlg::OnCloseWindow()
690 void CeditorDlg::OnButton( wxCommandEvent
&event
)
692 wxWindow
*win
= (wxWindow
*) event
.GetEventObject();
693 OnCommand( *win
, event
);
697 void CeditorDlg::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
701 widgetName
= win
.GetName();
706 if (widgetName
== pCreateBtn
->GetName())
708 Contact
->Initialize();
711 pNameTxt
->SetValue("");
712 pNameTxt
->SetFocus();
716 if (widgetName
== pEditBtn
->GetName())
718 saveName
= Contact
->Name
;
720 pNameTxt
->SetFocus();
724 if (widgetName
== pCopyBtn
->GetName())
727 pNameTxt
->SetValue("");
728 pNameTxt
->SetFocus();
732 if (widgetName
== pDeleteBtn
->GetName())
734 bool Ok
= (wxMessageBox("Are you sure?","Confirm",wxYES_NO
|wxICON_QUESTION
) == wxYES
);
739 if (Ok
&& Contact
->Delete())
741 // NOTE: Deletions are not finalized until a CommitTrans() is performed.
742 // If the commit were not performed, the program will continue to
743 // show the table contents as if they were deleted until this instance
744 // of Ccontact is deleted. If the Commit wasn't performed, the
745 // database will automatically Rollback the changes when the database
746 // connection is terminated
747 Contact
->pDb
->CommitTrans();
749 // Try to get the row that followed the just deleted row in the orderBy sequence
752 // There was now row (in sequence) after the just deleted row, so get the
753 // row which preceded the just deleted row
756 // There are now no rows remaining, so clear the dialog widgets
757 Contact
->Initialize();
761 SetMode(mode
); // force reset of button enable/disable
765 Contact
->pDb
->RollbackTrans();
771 if (widgetName
== pSaveBtn
->GetName())
777 if (widgetName
== pCancelBtn
->GetName())
779 bool Ok
= (wxMessageBox("Are you sure?","Confirm",wxYES_NO
|wxICON_QUESTION
) == wxYES
);
784 if (!strcmp((const char*) saveName
,""))
786 Contact
->Initialize();
793 // Requery previous record
794 if (Contact
->FetchByName((char*) (const char*) saveName
))
802 // Previous record not available, retrieve first record in table
803 if (Contact
->pDb
->Dbms() != dbmsPOSTGRES
)
805 // PostgreSQL can't do this
806 Contact
->whereStr
= "NAME = (SELECT MIN(NAME) FROM ";
807 Contact
->whereStr
+= Contact
->tableName
;
808 Contact
->whereStr
+= ")";
809 Contact
->where
= (char*) (const char*) Contact
->whereStr
;
814 if (!Contact
->Query())
817 tStr
= "ODBC error during Query()\n\n";
818 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
819 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
823 if (Contact
->GetNext()) // Successfully read first record
829 // No contacts are available, clear dialog
830 Contact
->Initialize();
836 if (widgetName
== pPrevBtn
->GetName())
843 if (widgetName
== pNextBtn
->GetName())
850 if (widgetName
== pQueryBtn
->GetName())
852 // Display the query dialog box
853 char qryWhere
[DB_MAX_WHERE_CLAUSE_LEN
+1];
854 strcpy(qryWhere
, (const char*) Contact
->qryWhereStr
);
855 char *tblName
[] = {(char *)CONTACT_TABLE_NAME
, 0};
856 new CqueryDlg(GetParent(), Contact
->pDb
, tblName
, qryWhere
);
858 // Query the first record in the new record set and
859 // display it, if the query string has changed.
860 if (strcmp(qryWhere
, (const char*) Contact
->qryWhereStr
))
863 // commented out because PostgreSQL can't do this
864 Contact
->whereStr
= "";
865 //Contact->orderBy = "NAME";
866 //Contact->whereStr = "NAME = (SELECT MIN(NAME) FROM ";
867 //Contact->whereStr += CONTACT_TABLE_NAME;
869 // Append the query where string (if there is one)
870 Contact
->qryWhereStr
= qryWhere
;
871 if (strlen(qryWhere
))
873 Contact
->whereStr
+= " WHERE ";
874 Contact
->whereStr
+= Contact
->qryWhereStr
;
876 // Close the expression with a right paren
877 // Contact->whereStr += ")";
879 Contact
->where
= (char*) (const char*) Contact
->whereStr
;
880 if (!Contact
->Query())
883 tStr
= "ODBC error during Query()\n\n";
884 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
885 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
888 // Display the first record from the query set
889 if (!Contact
->GetNext())
890 Contact
->Initialize();
894 // Enable/Disable the reset button
895 pResetBtn
->Enable(!Contact
->qryWhereStr
.IsEmpty());
901 if (widgetName
== pResetBtn
->GetName())
903 // Clear the additional where criteria established by the query feature
904 Contact
->qryWhereStr
= "";
906 // Query the first record in the table
907 Contact
->orderBy
= "NAME";
909 // commented out because PostgreSQL can't do this
910 //Contact->whereStr = "NAME = (SELECT MIN(NAME) FROM ";
911 //Contact->whereStr += CONTACT_TABLE_NAME;
912 //Contact->whereStr += ")";
914 Contact
->where
= (char*) (const char*) Contact
->whereStr
;
915 if (!Contact
->Query())
918 tStr
= "ODBC error during Query()\n\n";
919 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
920 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
923 if (!Contact
->GetNext())
924 Contact
->Initialize();
926 pResetBtn
->Enable(FALSE
);
932 if (widgetName
== pNameListBtn
->GetName())
934 new ClookUpDlg(/* wxWindow *parent */ this,
935 /* char *windowTitle */ "Select contact name",
936 /* char *tableName */ (char *) CONTACT_TABLE_NAME
,
937 /* char *dispCol1 */ "NAME",
938 /* char *dispCol2 */ "JOINDATE",
939 /* char *where */ "",
940 /* char *orderBy */ "NAME",
941 /* bool distinctValues */ TRUE
);
943 if (ListDB_Selection
&& strlen(ListDB_Selection
))
945 wxString w
= "NAME = '";
946 w
+= ListDB_Selection
;
948 GetRec((char*) (const char*) w
);
954 } // CeditorDlg::OnCommand()
957 void CeditorDlg::FieldsEditable()
959 pNameTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
960 pAddress1Txt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
961 pAddress2Txt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
962 pCityTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
963 pStateTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
964 pPostalCodeTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
965 pCountryTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
967 pJoinDateTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
968 pContribTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
969 pLinesTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
970 pNativeLangChoice
->Enable((mode
== mCreate
) || (mode
== mEdit
));
971 pDeveloperRadio
->Enable((mode
== mCreate
) || (mode
== mEdit
));
973 } // CeditorDlg::FieldsEditable()
976 void CeditorDlg::SetMode(enum DialogModes m
)
997 pCreateBtn
->Enable( !edit
);
998 pEditBtn
->Enable( !edit
&& (strcmp(Contact
->Name
,"")!=0) );
999 pDeleteBtn
->Enable( !edit
&& (strcmp(Contact
->Name
,"")!=0) );
1000 pCopyBtn
->Enable( !edit
&& (strcmp(Contact
->Name
,"")!=0) );
1001 pSaveBtn
->Enable( edit
);
1002 pCancelBtn
->Enable( edit
);
1003 pPrevBtn
->Enable( !edit
);
1004 pNextBtn
->Enable( !edit
);
1005 pQueryBtn
->Enable( !edit
);
1006 pResetBtn
->Enable( !edit
&& !Contact
->qryWhereStr
.IsEmpty() );
1007 pNameListBtn
->Enable( !edit
);
1011 } // CeditorDlg::SetMode()
1014 bool CeditorDlg::PutData()
1018 pNameTxt
->SetValue(Contact
->Name
);
1019 pAddress1Txt
->SetValue(Contact
->Addr1
);
1020 pAddress2Txt
->SetValue(Contact
->Addr2
);
1021 pCityTxt
->SetValue(Contact
->City
);
1022 pStateTxt
->SetValue(Contact
->State
);
1023 pCountryTxt
->SetValue(Contact
->Country
);
1024 pPostalCodeTxt
->SetValue(Contact
->PostalCode
);
1026 tStr
.Printf("%d/%d/%d",Contact
->JoinDate
.month
,Contact
->JoinDate
.day
,Contact
->JoinDate
.year
);
1027 pJoinDateTxt
->SetValue(tStr
);
1029 tStr
.Printf("%d",Contact
->Contributions
);
1030 pContribTxt
->SetValue(tStr
);
1032 tStr
.Printf("%lu",Contact
->LinesOfCode
);
1033 pLinesTxt
->SetValue(tStr
);
1035 pNativeLangChoice
->SetSelection(Contact
->NativeLanguage
);
1037 pDeveloperRadio
->SetSelection(Contact
->IsDeveloper
);
1040 } // Ceditor::PutData()
1044 * Reads the data out of all the widgets on the dialog. Some data evaluation is done
1045 * to ensure that there is a name entered and that the date field is valid.
1047 * A return value of TRUE means that valid data was retrieved from the dialog, otherwise
1048 * invalid data was found (and a message was displayed telling the user what to fix), and
1049 * the data was not placed into the appropraite fields of Ccontact
1051 bool CeditorDlg::GetData()
1053 // Validate that the data currently entered into the widgets is valid data
1056 tStr
= pNameTxt
->GetValue();
1057 if (!strcmp((const char*) tStr
,""))
1059 wxMessageBox("A name is required for entry into the contact table","Notice...",wxOK
| wxICON_INFORMATION
);
1063 bool invalid
= FALSE
;
1067 tStr
= pJoinDateTxt
->GetValue();
1068 if (tStr
.Freq('/') != 2)
1071 // Find the month, day, and year tokens
1074 first
= tStr
.First('/');
1075 second
= tStr
.Last('/');
1077 mm
= atoi(tStr
.SubString(0,first
));
1078 dd
= atoi(tStr
.SubString(first
+1,second
));
1079 yyyy
= atoi(tStr
.SubString(second
+1,tStr
.Length()-1));
1081 invalid
= !(mm
&& dd
&& yyyy
);
1084 // Force Year 2000 compliance
1085 if (!invalid
&& (yyyy
< 1000))
1088 // Check the token ranges for validity
1093 else if ((mm
< 1) || (mm
> 12))
1101 int days
[12] = {31,28,31,30,31,30,
1103 if (dd
> days
[mm
-1])
1106 if ((dd
== 29) && (mm
== 2))
1108 if (((yyyy
% 4) == 0) && (((yyyy
% 100) != 0) || ((yyyy
% 400) == 0)))
1118 Contact
->JoinDate
.month
= mm
;
1119 Contact
->JoinDate
.day
= dd
;
1120 Contact
->JoinDate
.year
= yyyy
;
1124 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
);
1128 tStr
= pNameTxt
->GetValue();
1129 strcpy(Contact
->Name
,(const char*) tStr
);
1130 strcpy(Contact
->Addr1
,pAddress1Txt
->GetValue());
1131 strcpy(Contact
->Addr2
,pAddress2Txt
->GetValue());
1132 strcpy(Contact
->City
,pCityTxt
->GetValue());
1133 strcpy(Contact
->State
,pStateTxt
->GetValue());
1134 strcpy(Contact
->Country
,pCountryTxt
->GetValue());
1135 strcpy(Contact
->PostalCode
,pPostalCodeTxt
->GetValue());
1137 Contact
->Contributions
= atoi(pContribTxt
->GetValue());
1138 Contact
->LinesOfCode
= atol(pLinesTxt
->GetValue());
1140 Contact
->NativeLanguage
= (enum Language
) pNativeLangChoice
->GetSelection();
1141 Contact
->IsDeveloper
= pDeveloperRadio
->GetSelection() > 0;
1144 } // CeditorDlg::GetData()
1148 * Retrieve data from the dialog, verify the validity of the data, and if it is valid,
1149 * try to insert/update the data to the table based on the current 'mode' the dialog
1152 * A return value of TRUE means the insert/update was completed successfully, a return
1153 * value of FALSE means that Save() failed. If returning FALSE, then this function
1154 * has displayed a detailed error message for the user.
1156 bool CeditorDlg::Save()
1158 bool failed
= FALSE
;
1160 // Read the data in the widgets of the dialog to get the user's data
1164 // Perform any other required validations necessary before saving
1167 wxBeginBusyCursor();
1169 if (mode
== mCreate
)
1171 RETCODE result
= Contact
->Insert();
1173 failed
= (result
!= DB_SUCCESS
);
1176 // Some errors may be expected, like a duplicate key, so handle those instances with
1177 // specific error messages.
1178 if (result
== DB_ERR_INTEGRITY_CONSTRAINT_VIOL
)
1181 tStr
= "A duplicate key value already exists in the table.\nUnable to save record\n\n";
1182 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
1183 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
1187 // Some other unexpexted error occurred
1189 tStr
= "Database insert failed\n\n";
1190 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
1191 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
1195 else // mode == mEdit
1197 if (!Contact
->Update())
1200 tStr
= "Database update failed\n\n";
1201 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
1202 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
1209 Contact
->pDb
->CommitTrans();
1210 SetMode(mView
); // Sets the dialog mode back to viewing after save is successful
1213 Contact
->pDb
->RollbackTrans();
1219 } // CeditorDlg::Save()
1223 * Where this program is only showing a single row at a time in the dialog,
1224 * a special where clause must be built to find just the single row which,
1225 * in sequence, would follow the currently displayed row.
1227 bool CeditorDlg::GetNextRec()
1231 if (Contact
->pDb
->Dbms() != dbmsPOSTGRES
)
1233 // PostgreSQL can't do this
1234 w
= "NAME = (SELECT MIN(NAME) FROM ";
1235 w
+= Contact
->tableName
;
1236 w
+= " WHERE NAME > '";
1244 // If a query where string is currently set, append that criteria
1245 if (!Contact
->qryWhereStr
.IsEmpty())
1248 w
+= Contact
->qryWhereStr
;
1253 return(GetRec((char*) (const char*) w
));
1255 } // CeditorDlg::GetNextRec()
1259 * Where this program is only showing a single row at a time in the dialog,
1260 * a special where clause must be built to find just the single row which,
1261 * in sequence, would precede the currently displayed row.
1263 bool CeditorDlg::GetPrevRec()
1267 if (Contact
->pDb
->Dbms() != dbmsPOSTGRES
)
1269 // PostgreSQL can't do this
1270 w
= "NAME = (SELECT MAX(NAME) FROM ";
1271 w
+= Contact
->tableName
;
1272 w
+= " WHERE NAME < '";
1280 // If a query where string is currently set, append that criteria
1281 if (!Contact
->qryWhereStr
.IsEmpty())
1284 w
+= Contact
->qryWhereStr
;
1290 return(GetRec((char*) (const char*)w
));
1292 } // CeditorDlg::GetPrevRec()
1296 * This function is here to avoid duplicating this same code in both the
1297 * GetPrevRec() and GetNextRec() functions
1299 bool CeditorDlg::GetRec(char *whereStr
)
1301 Contact
->where
= whereStr
;
1302 Contact
->orderBy
= "NAME";
1304 if (!Contact
->Query())
1307 tStr
= "ODBC error during Query()\n\n";
1308 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
1309 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
1314 if (Contact
->GetNext())
1321 } // CeditorDlg::GetRec()
1326 * CparameterDlg constructor
1329 BEGIN_EVENT_TABLE(CparameterDlg
, wxDialog
)
1330 EVT_BUTTON(PARAMETER_DIALOG_SAVE
, CparameterDlg::OnButton
)
1331 EVT_BUTTON(PARAMETER_DIALOG_CANCEL
, CparameterDlg::OnButton
)
1332 EVT_CLOSE(CparameterDlg::OnCloseWindow
)
1335 CparameterDlg::CparameterDlg(wxWindow
*parent
) : wxDialog (parent
, PARAMETER_DIALOG
, "ODBC parameter settings", wxPoint(-1, -1), wxSize(400, 325))
1337 // Since the ::OnCommand() function is overridden, this prevents the widget
1338 // detection in ::OnCommand() until all widgets have been initialized to prevent
1339 // uninitialized pointers from crashing the program
1340 widgetPtrsSet
= FALSE
;
1342 pParamODBCSourceMsg
= new wxStaticText(this, PARAMETER_DIALOG_SOURCE_MSG
, "ODBC data sources:", wxPoint(10, 10), wxSize(-1, -1), 0, "ParamODBCSourceMsg");
1343 pParamODBCSourceList
= new wxListBox(this, PARAMETER_DIALOG_SOURCE_LISTBOX
, wxPoint(10, 29), wxSize(285, 150), 0, 0, wxLB_SINGLE
|wxLB_ALWAYS_SB
, wxDefaultValidator
, "ParamODBCSourceList");
1345 pParamUserNameMsg
= new wxStaticText(this, PARAMETER_DIALOG_NAME_MSG
, "Database user name:", wxPoint(10, 193), wxSize(-1, -1), 0, "ParamUserNameMsg");
1346 pParamUserNameTxt
= new wxTextCtrl(this, PARAMETER_DIALOG_NAME_TEXT
, "", wxPoint(10, 209), wxSize(140, 25), 0, wxDefaultValidator
, "ParamUserNameTxt");
1348 pParamPasswordMsg
= new wxStaticText(this, PARAMETER_DIALOG_PASSWORD_MSG
, "Password:", wxPoint(156, 193), wxSize(-1, -1), 0, "ParamPasswordMsg");
1349 pParamPasswordTxt
= new wxTextCtrl(this, PARAMETER_DIALOG_PASSWORD_TEXT
, "", wxPoint(156, 209), wxSize(140, 25), 0, wxDefaultValidator
, "ParamPasswordTxt");
1351 pParamDirPathMsg
= new wxStaticText(this, PARAMETER_DIALOG_DIRPATH_MSG
, "Directory:", wxPoint(10, 243), wxSize(-1, -1), 0, "ParamDirPathMsg");
1352 pParamDirPathTxt
= new wxTextCtrl(this, PARAMETER_DIALOG_DIRPATH_TEXT
, "", wxPoint(10, 259), wxSize(140, 25), 0, wxDefaultValidator
, "ParamDirPathTxt");
1354 pParamSaveBtn
= new wxButton(this, PARAMETER_DIALOG_SAVE
, "&Save", wxPoint(310, 21), wxSize(70, 35), 0, wxDefaultValidator
, "ParamSaveBtn");
1355 pParamCancelBtn
= new wxButton(this, PARAMETER_DIALOG_CANCEL
, "C&ancel", wxPoint(310, 66), wxSize(70, 35), 0, wxDefaultValidator
, "ParamCancelBtn");
1357 // Now that all the widgets on the panel are created, its safe to allow ::OnCommand() to
1358 // handle all widget processing
1359 widgetPtrsSet
= TRUE
;
1362 savedParamSettings
= wxGetApp().params
;
1367 } // CparameterDlg constructor
1370 void CparameterDlg::OnCloseWindow(wxCloseEvent
& event
)
1372 // Put any additional checking necessary to make certain it is alright
1373 // to close the program here that is not done elsewhere
1376 bool Ok
= (wxMessageBox("No changes have been saved.\n\nAre you sure you wish exit the parameter screen?","Confirm",wxYES_NO
|wxICON_QUESTION
) == wxYES
);
1384 wxGetApp().params
= savedParamSettings
;
1387 if (GetParent() != NULL
)
1388 GetParent()->SetFocus();
1391 } // Cparameter::OnCloseWindow()
1394 void CparameterDlg::OnButton( wxCommandEvent
&event
)
1396 wxWindow
*win
= (wxWindow
*) event
.GetEventObject();
1397 OnCommand( *win
, event
);
1400 void CparameterDlg::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
1402 wxString widgetName
;
1404 widgetName
= win
.GetName();
1409 if (widgetName
== pParamSaveBtn
->GetName())
1414 tStr
= "Database parameters have been saved.";
1415 if (GetParent() != NULL
) // The parameter dialog was not called during startup due to a missing cfg file
1416 tStr
+= "\nNew parameters will take effect the next time the program is started.";
1417 wxMessageBox(tStr
,"Notice...",wxOK
| wxICON_INFORMATION
);
1424 if (widgetName
== pParamCancelBtn
->GetName())
1429 } // CparameterDlg::OnCommand()
1432 bool CparameterDlg::PutData()
1434 // Fill the data source list box
1435 FillDataSourceList();
1437 // Fill in the fields from the params object
1438 if (wxGetApp().params
.ODBCSource
&& wxStrlen(wxGetApp().params
.ODBCSource
))
1439 pParamODBCSourceList
->SetStringSelection(wxGetApp().params
.ODBCSource
);
1440 pParamUserNameTxt
->SetValue(wxGetApp().params
.UserName
);
1441 pParamPasswordTxt
->SetValue(wxGetApp().params
.Password
);
1442 pParamDirPathTxt
->SetValue(wxGetApp().params
.DirPath
);
1444 } // CparameterDlg::PutData()
1447 bool CparameterDlg::GetData()
1450 if (pParamODBCSourceList
->GetStringSelection())
1452 tStr
= pParamODBCSourceList
->GetStringSelection();
1453 if (tStr
.Length() > (sizeof(wxGetApp().params
.ODBCSource
)-1))
1456 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());
1457 wxMessageBox(errmsg
,"Internal program error...",wxOK
| wxICON_EXCLAMATION
);
1460 strcpy(wxGetApp().params
.ODBCSource
, tStr
);
1465 tStr
= pParamUserNameTxt
->GetValue();
1466 if (tStr
.Length() > (sizeof(wxGetApp().params
.UserName
)-1))
1469 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());
1470 wxMessageBox(errmsg
,"Internal program error...",wxOK
| wxICON_EXCLAMATION
);
1473 strcpy(wxGetApp().params
.UserName
, tStr
);
1475 tStr
= pParamPasswordTxt
->GetValue();
1476 if (tStr
.Length() > (sizeof(wxGetApp().params
.Password
)-1))
1479 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());
1480 wxMessageBox(errmsg
,"Internal program error...",wxOK
| wxICON_EXCLAMATION
);
1483 strcpy(wxGetApp().params
.Password
,tStr
);
1485 tStr
= pParamDirPathTxt
->GetValue();
1486 tStr
.Replace("\\","/");
1487 if (tStr
.Length() > (sizeof(wxGetApp().params
.DirPath
)-1))
1490 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());
1491 wxMessageBox(errmsg
,"Internal program error...",wxOK
| wxICON_EXCLAMATION
);
1494 strcpy(wxGetApp().params
.DirPath
,tStr
);
1496 } // CparameterDlg::GetData()
1499 bool CparameterDlg::Save()
1501 Cparameters saveParams
= wxGetApp().params
;
1504 wxGetApp().params
= saveParams
;
1509 if ((paramFile
= fopen(paramFilename
, "wt")) == NULL
)
1512 tStr
.Printf("Unable to write/overwrite '%s'.",paramFilename
);
1513 wxMessageBox(tStr
,"File I/O Error...",wxOK
| wxICON_EXCLAMATION
);
1517 fputs(wxGetApp().params
.ODBCSource
, paramFile
);
1518 fputc('\n', paramFile
);
1519 fputs(wxGetApp().params
.UserName
, paramFile
);
1520 fputc('\n', paramFile
);
1521 fputs(wxGetApp().params
.Password
, paramFile
);
1522 fputc('\n', paramFile
);
1523 fputs(wxGetApp().params
.DirPath
, paramFile
);
1524 fputc('\n', paramFile
);
1528 } // CparameterDlg::Save()
1531 void CparameterDlg::FillDataSourceList()
1533 char Dsn
[SQL_MAX_DSN_LENGTH
+ 1];
1535 wxStringList strList
;
1537 while(GetDataSource(DbConnectInf
.Henv
, Dsn
, SQL_MAX_DSN_LENGTH
+1, DsDesc
, 255))
1542 char **p
= strList
.ListToArray();
1544 for (int i
= 0; strlen(p
[i
]); i
++)
1545 pParamODBCSourceList
->Append(p
[i
]);
1546 } // CparameterDlg::CparameterDlg::FillDataSourceList()
1549 BEGIN_EVENT_TABLE(CqueryDlg
, wxDialog
)
1550 EVT_BUTTON(-1, CqueryDlg::OnButton
)
1551 EVT_CLOSE(CqueryDlg::OnCloseWindow
)
1554 // CqueryDlg() constructor
1555 CqueryDlg::CqueryDlg(wxWindow
*parent
, wxDB
*pDb
, char *tblName
[], char *pWhereArg
) : wxDialog (parent
, QUERY_DIALOG
, "Query", wxPoint(-1, -1), wxSize(480, 360))
1557 wxBeginBusyCursor();
1561 masterTableName
= tblName
[0];
1562 widgetPtrsSet
= FALSE
;
1565 // Initialize the WHERE clause from the string passed in
1566 pWhere
= pWhereArg
; // Save a pointer to the output buffer
1567 if (strlen(pWhere
) > DB_MAX_WHERE_CLAUSE_LEN
) // Check the length of the buffer passed in
1570 s
.Printf("Maximum where clause length exceeded.\nLength must be less than %d", DB_MAX_WHERE_CLAUSE_LEN
+1);
1571 wxMessageBox(s
,"Error...",wxOK
| wxICON_EXCLAMATION
);
1576 pQueryCol1Msg
= new wxStaticText(this, QUERY_DIALOG_COL_MSG
, "Column 1:", wxPoint(10, 10), wxSize(69, 16), 0, "QueryCol1Msg");
1577 pQueryCol1Choice
= new wxChoice(this, QUERY_DIALOG_COL_CHOICE
, wxPoint(10, 27), wxSize(250, 27), 0, 0, 0, wxDefaultValidator
, "QueryCol1Choice");
1579 pQueryNotMsg
= new wxStaticText(this, QUERY_DIALOG_NOT_MSG
, "NOT", wxPoint(268, 10), wxSize(-1, -1), 0, "QueryNotMsg");
1580 pQueryNotCheck
= new wxCheckBox(this, QUERY_DIALOG_NOT_CHECKBOX
, "", wxPoint(275, 37), wxSize(20, 20), 0, wxDefaultValidator
, "QueryNotCheck");
1582 wxString choice_strings
[9];
1583 choice_strings
[0] = "=";
1584 choice_strings
[1] = "<";
1585 choice_strings
[2] = ">";
1586 choice_strings
[3] = "<=";
1587 choice_strings
[4] = ">=";
1588 choice_strings
[5] = "Begins";
1589 choice_strings
[6] = "Contains";
1590 choice_strings
[7] = "Like";
1591 choice_strings
[8] = "Between";
1592 pQueryOperatorMsg
= new wxStaticText(this, QUERY_DIALOG_OP_MSG
, "Operator:", wxPoint(305, 10), wxSize(-1, -1), 0, "QueryOperatorMsg");
1593 pQueryOperatorChoice
= new wxChoice(this, QUERY_DIALOG_OP_CHOICE
, wxPoint(305, 27), wxSize(80, 27), 9, choice_strings
, 0, wxDefaultValidator
, "QueryOperatorChoice");
1595 pQueryCol2Msg
= new wxStaticText(this, QUERY_DIALOG_COL2_MSG
, "Column 2:", wxPoint(10, 65), wxSize(69, 16), 0, "QueryCol2Msg");
1596 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");
1601 pQueryAddBtn
= new wxButton(this, QUERY_DIALOG_ADD
, "&Add", wxPoint(406, 24), wxSize(56, 26), 0, wxDefaultValidator
, "QueryAddBtn");
1602 pQueryAndBtn
= new wxButton(this, QUERY_DIALOG_AND
, "A&nd", wxPoint(406, 58), wxSize(56, 26), 0, wxDefaultValidator
, "QueryAndBtn");
1603 pQueryOrBtn
= new wxButton(this, QUERY_DIALOG_OR
, "&Or", wxPoint(406, 92), wxSize(56, 26), 0, wxDefaultValidator
, "QueryOrBtn");
1605 pQueryLParenBtn
= new wxButton(this, QUERY_DIALOG_LPAREN
, "(", wxPoint(406, 126), wxSize(26, 26), 0, wxDefaultValidator
, "QueryLParenBtn");
1606 pQueryRParenBtn
= new wxButton(this, QUERY_DIALOG_RPAREN
, ")", wxPoint(436, 126), wxSize(26, 26), 0, wxDefaultValidator
, "QueryRParenBtn");
1608 pQueryDoneBtn
= new wxButton(this, QUERY_DIALOG_DONE
, "&Done", wxPoint(406, 185), wxSize(56, 26), 0, wxDefaultValidator
, "QueryDoneBtn");
1609 pQueryClearBtn
= new wxButton(this, QUERY_DIALOG_CLEAR
, "C&lear", wxPoint(406, 218), wxSize(56, 26), 0, wxDefaultValidator
, "QueryClearBtn");
1610 pQueryCountBtn
= new wxButton(this, QUERY_DIALOG_COUNT
, "&Count", wxPoint(406, 252), wxSize(56, 26), 0, wxDefaultValidator
, "QueryCountBtn");
1612 pQueryValue1Msg
= new wxStaticText(this, QUERY_DIALOG_VALUE1_MSG
, "Value:", wxPoint(277, 66), wxSize(-1, -1), 0, "QueryValue1Msg");
1613 pQueryValue1Txt
= new wxTextCtrl(this, QUERY_DIALOG_VALUE1_TEXT
, "", wxPoint(277, 83), wxSize(108, 25), 0, wxDefaultValidator
, "QueryValue1Txt");
1615 pQueryValue2Msg
= new wxStaticText(this, QUERY_DIALOG_VALUE2_MSG
, "AND", wxPoint(238, 126), wxSize(-1, -1), 0, "QueryValue2Msg");
1616 pQueryValue2Txt
= new wxTextCtrl(this, QUERY_DIALOG_VALUE2_TEXT
, "", wxPoint(277, 120), wxSize(108, 25), 0, wxDefaultValidator
, "QueryValue2Txt");
1618 pQueryHintGrp
= new wxStaticBox(this, QUERY_DIALOG_HINT_GROUP
, "", wxPoint(10, 291), wxSize(377, 40), 0, "QueryHintGrp");
1619 pQueryHintMsg
= new wxStaticText(this, QUERY_DIALOG_HINT_MSG
, "", wxPoint(16, 306), wxSize(-1, -1), 0, "QueryHintMsg");
1621 widgetPtrsSet
= TRUE
;
1622 // Initialize the dialog
1624 pQueryCol2Choice
->Append("VALUE -->");
1625 colInf
= pDB
->GetColumns(tblName
);
1631 tStr
= "ODBC error during GetColumns()\n\n";
1632 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
1633 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
1637 for (int i
= 0; colInf
[i
].colName
&& strlen(colInf
[i
].colName
); i
++)
1639 // If there is more than one table being queried, qualify
1640 // the column names with the table name prefix.
1641 if (tblName
[1] && strlen(tblName
[1]))
1643 qualName
.Printf("%s.%s", colInf
[i
].tableName
, colInf
[i
].colName
);
1644 pQueryCol1Choice
->Append(qualName
);
1645 pQueryCol2Choice
->Append(qualName
);
1647 else // Single table query, append just the column names
1649 pQueryCol1Choice
->Append(colInf
[i
].colName
);
1650 pQueryCol2Choice
->Append(colInf
[i
].colName
);
1654 pQueryCol1Choice
->SetSelection(0);
1655 pQueryCol2Choice
->SetSelection(0);
1656 pQueryOperatorChoice
->SetSelection(0);
1658 pQueryValue2Msg
->Show(FALSE
);
1659 pQueryValue2Txt
->Show(FALSE
);
1661 pQueryHintMsg
->SetLabel(langQRY_EQ
);
1663 pQuerySqlWhereMtxt
->SetValue(pWhere
);
1667 // Display the dialog window
1671 } // CqueryDlg() constructor
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 (strlen(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 strcpy(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();
1913 } // CqueryDlg::OnCloseWindow()
1916 bool CqueryDlg::SetWidgetPtrs()
1920 abort = abort || !(pQueryCol1Choice = (wxChoice *)GetWidgetPtr("QueryCol1Choice",this));
1921 abort = abort || !(pQueryNotCheck = (wxCheckBox *)GetWidgetPtr("QueryNotCheck",this));
1922 abort = abort || !(pQueryOperatorChoice = (wxChoice *)GetWidgetPtr("QueryOperatorChoice",this));
1923 abort = abort || !(pQueryCol2Choice = (wxChoice *)GetWidgetPtr("QueryCol2Choice",this));
1924 abort = abort || !(pQueryValue1Txt = (wxTextCtrl *)GetWidgetPtr("QueryValue1Txt",this));
1925 abort = abort || !(pQueryValue2Txt = (wxTextCtrl *)GetWidgetPtr("QueryValue2Txt",this));
1926 abort = abort || !(pQuerySqlWhereMtxt = (wxMultiText *)GetWidgetPtr("QuerySqlWhereMtxt",this));
1927 abort = abort || !(pQueryAddBtn = (wxButton *)GetWidgetPtr("QueryAddBtn",this));
1928 abort = abort || !(pQueryAndBtn = (wxButton *)GetWidgetPtr("QueryAndBtn",this));
1929 abort = abort || !(pQueryOrBtn = (wxButton *)GetWidgetPtr("QueryOrBtn",this));
1930 abort = abort || !(pQueryLParenBtn = (wxButton *)GetWidgetPtr("QueryLParenBtn",this));
1931 abort = abort || !(pQueryRParenBtn = (wxButton *)GetWidgetPtr("QueryRParenBtn",this));
1932 abort = abort || !(pQueryDoneBtn = (wxButton *)GetWidgetPtr("QueryDoneBtn",this));
1933 abort = abort || !(pQueryClearBtn = (wxButton *)GetWidgetPtr("QueryClearBtn",this));
1934 abort = abort || !(pQueryCountBtn = (wxButton *)GetWidgetPtr("QueryCountBtn",this));
1935 abort = abort || !(pQueryHelpBtn = (wxButton *)GetWidgetPtr("QueryHelpBtn",this));
1936 abort = abort || !(pQueryHintMsg = (wxStaticText *)GetWidgetPtr("QueryHintMsg",this));
1940 return(widgetPtrsSet = !abort);
1942 } // CqueryDlg::SetWidgetPtrs
1945 void CqueryDlg::AppendToWhere(char *s
)
1947 wxString whereStr
= pQuerySqlWhereMtxt
->GetValue();
1949 pQuerySqlWhereMtxt
->SetValue(whereStr
);
1951 } // CqueryDlg::AppendToWhere()
1954 void CqueryDlg::ProcessAddBtn()
1956 qryOp oper
= (qryOp
) pQueryOperatorChoice
->GetSelection();
1958 // Verify that eveything is filled in correctly
1959 if (pQueryCol2Choice
->GetSelection() == 0) // "Value" is selected
1961 // Verify that value 1 is filled in
1962 if (strlen(pQueryValue1Txt
->GetValue()) == 0)
1965 pQueryValue1Txt
->SetFocus();
1968 // For the BETWEEN operator, value 2 must be filled in as well
1969 if (oper
== qryOpBETWEEN
&&
1970 strlen(pQueryValue2Txt
->GetValue()) == 0)
1973 pQueryValue2Txt
->SetFocus();
1978 // Build the expression and append it to the where clause window
1979 wxString s
= pQueryCol1Choice
->GetStringSelection();
1981 if (pQueryNotCheck
->GetValue() && (oper
!= qryOpEQ
))
1987 if (pQueryNotCheck
->GetValue()) // NOT box is checked
2016 int col1Idx
= pQueryCol1Choice
->GetSelection();
2019 if (colInf
[col1Idx
].sqlDataType
== SQL_VARCHAR
||
2020 oper
== qryOpBEGINS
||
2021 oper
== qryOpCONTAINS
||
2025 if (pQueryCol2Choice
->GetSelection()) // Column name
2026 s
+= pQueryCol2Choice
->GetStringSelection();
2027 else // Column 2 is a "value"
2031 if (oper
== qryOpCONTAINS
)
2033 s
+= pQueryValue1Txt
->GetValue();
2034 if (oper
== qryOpCONTAINS
|| oper
== qryOpBEGINS
)
2040 if (oper
== qryOpBETWEEN
)
2045 s
+= pQueryValue2Txt
->GetValue();
2050 AppendToWhere((char*) (const char*) s
);
2052 } // CqueryDlg::ProcessAddBtn()
2055 void CqueryDlg::ProcessCountBtn()
2057 if (!ValidateWhereClause())
2060 if (dbTable
== 0) // wxTable object needs to be created and opened
2062 if (!(dbTable
= new wxTable(pDB
, masterTableName
, 0, NULL
, !QUERY_ONLY
, DbConnectInf
.defaultDir
)))
2064 wxMessageBox("Memory allocation failed creating a wxTable object.","Error...",wxOK
| wxICON_EXCLAMATION
);
2067 if (!dbTable
->Open())
2070 tStr
= "ODBC error during Open()\n\n";
2071 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
2072 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
2077 // Count() with WHERE clause
2078 dbTable
->where
= (char*) (const char*) pQuerySqlWhereMtxt
->GetValue();
2079 ULONG whereCnt
= dbTable
->Count();
2081 // Count() of all records in the table
2083 ULONG totalCnt
= dbTable
->Count();
2085 if (whereCnt
> 0 || totalCnt
== 0)
2088 tStr
.Printf("%lu of %lu records match the query criteria.",whereCnt
,totalCnt
);
2089 wxMessageBox(tStr
,"Notice...",wxOK
| wxICON_INFORMATION
);
2094 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
);
2095 wxMessageBox(tStr
,"Notice...",wxOK
| wxICON_INFORMATION
);
2098 // After a wxMessageBox, the focus does not necessarily return to the
2099 // window which was the focus when the message box popped up, so return
2100 // focus to the Query dialog for certain
2103 } // CqueryDlg::ProcessCountBtn()
2106 bool CqueryDlg::ValidateWhereClause()
2108 wxString where
= pQuerySqlWhereMtxt
->GetValue();
2110 if (where
.Freq('(') != where
.Freq(')'))
2112 wxMessageBox("There are mismatched parenthesis in the constructed where clause","Error...",wxOK
| wxICON_EXCLAMATION
);
2115 // After a wxMessageBox, the focus does not necessarily return to the
2116 // window which was the focus when the message box popped up, so return
2117 // focus to the Query dialog for certain
2122 } // CqueryDlg::ValidateWhereClause()