]> git.saurik.com Git - wxWidgets.git/blame - samples/db/listdb.cpp
wxFileSelector should have file name only, not path, passed to 3rd arg
[wxWidgets.git] / samples / db / listdb.cpp
CommitLineData
108106cf
JS
1///////////////////////////////////////////////////////////////////////////////
2// Name: listdb.cpp
3// Purpose: Data table lookup listbox code
4// Author: George Tasker/Doug Card
5// Modified by:
6// Created: 1996
7// RCS-ID: $Id$
8// Copyright: (c) 1996 Remstar International, Inc.
9// Licence: wxWindows licence
10///////////////////////////////////////////////////////////////////////////////
11
12/*
13// SYNOPSIS START
14
15 Member functions for the classes defined in LISTDB.H
16
e70e8f4c
GT
17 This class is used to present a generic ListBox lookup window for
18 use with any of the object creation/selection choice widgets. This
19 dialog window will present a (possibly) scrolling list of values
20 that come from a data table source. Based on the object type passed
21 in the constructor, a ListBox is built to present the user with a
22 single selection listbox.
23
24 The string selected from the list box is stored in the Global variable
94613352 25 "ListDB_Selection", and will remain set until another interation of this
e70e8f4c
GT
26 routine is called.
27
28 For each object (database) type that is to be used, an overridden
29 constructor should be written to appropriately link to the proper
30 data table/object for building the list.
31
108106cf 32 The data table record access is all handled through the routines
f6bcfd97 33 in this module, interfacing with the methods defined in wxDbTable.
108106cf 34
e70e8f4c
GT
35 All objects which use data table access must be initialized and
36 have opened the table prior to passing them in the dialog
37 constructor, and the 'where' query should already have been set
38 and performed before creating this dialog instance.
108106cf
JS
39
40// SYNOPSIS STOP
41*/
42
43#ifdef __GNUG__
44#pragma implementation "listdb.h"
45#endif
46
47#include "wx/wxprec.h"
48
49#ifdef __BORLANDC__
50#pragma hdrstop
51#endif //__BORLANDC__
52
53#ifndef WX_PRECOMP
54#include <wx/wx.h>
55#endif //WX_PRECOMP
56
57#include <wx/dbtable.h>
58
3f755e2d 59extern wxDbList WXDLLEXPORT *PtrBegDbList; /* from db.cpp, used in getting back error results from db connections */
65d7ddc4 60
108106cf 61#include "listdb.h"
049977d0 62//#include "dbtest.h"
108106cf
JS
63
64// Used for passing the selected listbox selection back to the calling
65// routine. This variable must be declared as 'extern' in the calling
66// source module
94613352 67wxChar ListDB_Selection[LOOKUP_COL_LEN+1];
108106cf
JS
68
69// If the listbox contains two columns of data, the second column is
70// returned in this variable.
94613352 71wxChar ListDB_Selection2[LOOKUP_COL_LEN+1];
108106cf
JS
72
73// Constants
5b077d48 74const int LISTDB_NO_SPACES_BETWEEN_COLS = 3;
108106cf
JS
75
76
049977d0
GT
77extern wxApp *DatabaseDemoApp;
78
65d7ddc4
GT
79
80/*
81 * This function will return the exact string(s) from the database engine
82 * indicating all error conditions which have just occured during the
83 * last call to the database engine.
84 *
85 * This demo uses the returned string by displaying it in a wxMessageBox. The
86 * formatting therefore is not the greatest, but this is just a demo, not a
87 * finished product. :-) gt
88 *
89 * NOTE: The value returned by this function is for temporary use only and
90 * should be copied for long term use
91 */
94613352 92const wxChar *GetExtendedDBErrorMsg2(wxChar *ErrFile, int ErrLine)
65d7ddc4 93{
e70e8f4c 94 static wxString msg;
94613352 95 msg.Empty();
e70e8f4c
GT
96
97 wxString tStr;
98
99 if (ErrFile || ErrLine)
100 {
94613352 101 msg += wxT("File: ");
e70e8f4c 102 msg += ErrFile;
94613352
GT
103 msg += wxT(" Line: ");
104 tStr.Printf(wxT("%d"),ErrLine);
105 msg += tStr;
106 msg += wxT("\n");
e70e8f4c
GT
107 }
108
94613352
GT
109 msg.Append (wxT("\nODBC errors:\n"));
110 msg += wxT("\n");
e70e8f4c
GT
111
112 /* Scan through each database connection displaying
113 * any ODBC errors that have occured. */
3f755e2d
GT
114 wxDbList *pDbList;
115 for (pDbList = PtrBegDbList; pDbList; pDbList = pDbList->PtrNext)
e70e8f4c
GT
116 {
117 // Skip over any free connections
118 if (pDbList->Free)
119 continue;
120 // Display errors for this connection
121 for (int i = 0; i < DB_MAX_ERROR_HISTORY; i++)
122 {
123 if (pDbList->PtrDb->errorList[i])
124 {
125 msg.Append(pDbList->PtrDb->errorList[i]);
94613352
GT
126 if (wxStrcmp(pDbList->PtrDb->errorList[i],wxT("")) != 0)
127 msg.Append(wxT("\n"));
3ca6a5f0
BP
128 // Clear the errmsg buffer so the next error will not
129 // end up showing the previous error that have occurred
94613352 130 wxStrcpy(pDbList->PtrDb->errorList[i],wxT(""));
e70e8f4c
GT
131 }
132 }
133 }
94613352 134 msg += wxT("\n");
e70e8f4c 135
94613352 136 return /*(wxChar*) (const wxChar*) msg*/msg.c_str();
65d7ddc4
GT
137} // GetExtendedDBErrorMsg
138
139
140
108106cf 141// Clookup constructor
049977d0
GT
142Clookup::Clookup(wxChar *tblName, wxChar *colName, wxDb *pDb, const wxString &defDir)
143 : wxDbTable(pDb, tblName, 1, wxT(""), !wxDB_QUERY_ONLY,
144 defDir)
108106cf
JS
145{
146
e70e8f4c 147 SetColDefs (0, colName, DB_DATA_TYPE_VARCHAR, lookupCol, SQL_C_CHAR, LOOKUP_COL_LEN+1, FALSE, FALSE);
108106cf
JS
148
149} // Clookup()
150
151
152// Clookup2 constructor
049977d0
GT
153Clookup2::Clookup2(wxChar *tblName, wxChar *colName1, wxChar *colName2,
154 wxDb *pDb, const wxString &defDir)
155 : wxDbTable(pDb, tblName, (1 + (wxStrlen(colName2) > 0)), wxT(""),
156 !wxDB_QUERY_ONLY, defDir)
108106cf 157{
049977d0
GT
158 wxASSERT(pDb);
159 wxASSERT(tblName);
160 wxASSERT(colName1);
161 wxASSERT(colName2);
162
e70e8f4c 163 int i = 0;
108106cf 164
e70e8f4c 165 SetColDefs (i, colName1, DB_DATA_TYPE_VARCHAR, lookupCol1, SQL_C_CHAR, LOOKUP_COL_LEN+1, FALSE, FALSE);
108106cf 166
f6bcfd97 167 if (wxStrlen(colName2) > 0)
e70e8f4c 168 SetColDefs (++i, colName2, DB_DATA_TYPE_VARCHAR, lookupCol2, SQL_C_CHAR, LOOKUP_COL_LEN+1, FALSE, FALSE);
108106cf
JS
169
170} // Clookup2()
171
172
65d7ddc4 173BEGIN_EVENT_TABLE(ClookUpDlg, wxDialog)
65d7ddc4
GT
174 EVT_BUTTON(LOOKUP_DIALOG_OK, ClookUpDlg::OnButton)
175 EVT_BUTTON(LOOKUP_DIALOG_CANCEL, ClookUpDlg::OnButton)
176 EVT_CLOSE(ClookUpDlg::OnClose)
177END_EVENT_TABLE()
178
049977d0 179
108106cf 180// This is a generic lookup constructor that will work with any table and any column
049977d0
GT
181ClookUpDlg::ClookUpDlg(wxWindow *parent, wxChar *windowTitle, wxChar *tableName,
182 wxChar *colName, wxChar *where, wxChar *orderBy,
183 wxDb *pDb, const wxString &defDir)
184 : wxDialog (parent, LOOKUP_DIALOG, wxT("Select..."), wxPoint(-1, -1), wxSize(400, 290))
108106cf 185{
e70e8f4c
GT
186 wxBeginBusyCursor();
187
94613352 188 wxStrcpy(ListDB_Selection,wxT(""));
e70e8f4c
GT
189 widgetPtrsSet = FALSE;
190 lookup = 0;
191 lookup2 = 0;
192 noDisplayCols = 1;
193 col1Len = 0;
194
049977d0
GT
195 pLookUpSelectList = new wxListBox(this, LOOKUP_DIALOG_SELECT, wxPoint( 5, 15), wxSize(384, 195), 0, 0, wxLB_SINGLE|wxLB_ALWAYS_SB, wxDefaultValidator, wxT("LookUpSelectList"));
196 pLookUpOkBtn = new wxButton(this, LOOKUP_DIALOG_OK, wxT("&Ok"), wxPoint(113, 222), wxSize( 70, 35), 0, wxDefaultValidator, wxT("LookUpOkBtn"));
197 pLookUpCancelBtn = new wxButton(this, LOOKUP_DIALOG_CANCEL, wxT("C&ancel"), wxPoint(212, 222), wxSize( 70, 35), 0, wxDefaultValidator, wxT("LookUpCancelBtn"));
e70e8f4c
GT
198
199 widgetPtrsSet = TRUE;
200
201 // Query the lookup table and display the result set
049977d0 202 if (!(lookup = new Clookup(tableName, colName, pDb, defDir)))
e70e8f4c 203 {
94613352 204 wxMessageBox(wxT("Error allocating memory for 'Clookup'object."),wxT("Error..."));
e70e8f4c
GT
205 Close();
206 return;
207 }
208
209 if (!lookup->Open())
210 {
211 wxString tStr;
94613352
GT
212 tStr.Printf(wxT("Unable to open the table '%s'."),tableName);
213 wxMessageBox(tStr,wxT("ODBC Error..."));
e70e8f4c
GT
214 Close();
215 return;
216 }
217
f6bcfd97
BP
218 lookup->SetOrderByClause(orderBy);
219 lookup->SetWhereClause(where);
e70e8f4c
GT
220 if (!lookup->Query())
221 {
94613352 222 wxMessageBox(wxT("ODBC error during Query()"),wxT("ODBC Error..."));
e70e8f4c
GT
223 Close();
224 return;
225 }
226
227 // Fill in the list box from the query result set
228 while (lookup->GetNext())
229 pLookUpSelectList->Append(lookup->lookupCol);
230
231 // Highlight the first list item
232 pLookUpSelectList->SetSelection(0);
233
234 // Make the OK activate by pressing Enter
235 if (pLookUpSelectList->Number())
236 pLookUpOkBtn->SetDefault();
237 else
238 {
239 pLookUpCancelBtn->SetDefault();
240 pLookUpOkBtn->Enable(FALSE);
241 }
242
243 // Display the dialog window
244 SetTitle(windowTitle);
245 Centre(wxBOTH);
246 wxEndBusyCursor();
247 ShowModal();
108106cf
JS
248
249} // Generic lookup constructor
250
251
252//
253// This is a generic lookup constructor that will work with any table and any column.
254// It extends the capabilites of the lookup dialog in the following ways:
255//
e70e8f4c 256// 1) 2 columns rather than one
108106cf
JS
257// 2) The ability to select DISTINCT column values
258//
259// Only set distinctValues equal to true if necessary. In many cases, the constraints
260// of the index(es) will enforce this uniqueness. Selecting DISTINCT does require
261// overhead by the database to ensure that all values returned are distinct. Therefore,
262// use this ONLY when you need it.
263//
264// For complicated queries, you can pass in the sql select statement. This would be
265// necessary if joins are involved since by default both columns must come from the
266// same table.
267//
268// If you do query by sql statement, you must pass in the maximum lenght of column1,
269// since it cannot be derived when you query using your own sql statement.
270//
271// The optional database connection can be used if you'd like the lookup class
049977d0 272// to use a database pointer other than wxGetApp().READONLY_DB. This is necessary if
108106cf
JS
273// records are being saved, but not committed to the db, yet should be included
274// in the lookup window.
275//
94613352 276ClookUpDlg::ClookUpDlg(wxWindow *parent, wxChar *windowTitle, wxChar *tableName,
049977d0
GT
277 wxChar *dispCol1, wxChar *dispCol2, wxChar *where, wxChar *orderBy,
278 wxDb *pDb, const wxString &defDir, bool distinctValues,
279 wxChar *selectStmt, int maxLenCol1, bool allowOk)
280 : wxDialog (parent, LOOKUP_DIALOG, wxT("Select..."), wxPoint(-1, -1), wxSize(400, 290))
108106cf 281{
e70e8f4c
GT
282 wxBeginBusyCursor();
283
94613352
GT
284 wxStrcpy(ListDB_Selection,wxT(""));
285 wxStrcpy(ListDB_Selection2,wxT(""));
e70e8f4c
GT
286 widgetPtrsSet = FALSE;
287 lookup = 0;
288 lookup2 = 0;
f6bcfd97 289 noDisplayCols = (wxStrlen(dispCol2) ? 2 : 1);
e70e8f4c
GT
290 col1Len = 0;
291
292 wxFont fixedFont(12,wxMODERN,wxNORMAL,wxNORMAL);
293
294 // this is done with fixed font so that the second column (if any) will be left
295 // justified in the second column
94613352 296 pLookUpSelectList = new wxListBox(this, LOOKUP_DIALOG_SELECT, wxPoint(5, 15), wxSize(384, 195), 0, 0, wxLB_SINGLE|wxLB_ALWAYS_SB, wxDefaultValidator, wxT("LookUpSelectList"));
1fc5dd6f
JS
297
298 pLookUpSelectList->SetFont(fixedFont);
299
94613352
GT
300 pLookUpOkBtn = new wxButton(this, LOOKUP_DIALOG_OK, wxT("&Ok"), wxPoint(113, 222), wxSize(70, 35), 0, wxDefaultValidator, wxT("LookUpOkBtn"));
301 pLookUpCancelBtn = new wxButton(this, LOOKUP_DIALOG_CANCEL, wxT("C&ancel"), wxPoint(212, 222), wxSize(70, 35), 0, wxDefaultValidator, wxT("LookUpCancelBtn"));
e70e8f4c
GT
302
303 widgetPtrsSet = TRUE;
304
305 // Query the lookup table and display the result set
049977d0 306 if (!(lookup2 = new Clookup2(tableName, dispCol1, dispCol2, pDb, defDir)))
e70e8f4c 307 {
94613352 308 wxMessageBox(wxT("Error allocating memory for 'Clookup2' object."),wxT("Error..."));
e70e8f4c
GT
309 Close();
310 return;
311 }
312
313 if (!lookup2->Open())
314 {
315 wxString tStr;
94613352 316 tStr.Printf(wxT("Unable to open the table '%s'."),tableName);
e70e8f4c 317 tStr += GetExtendedDBErrorMsg2(__FILE__,__LINE__);
94613352 318 wxMessageBox(tStr,wxT("ODBC Error..."));
e70e8f4c
GT
319 Close();
320 return;
321 }
322
323 // If displaying 2 columns, determine the maximum length of column1
324 int maxColLen;
325 if (maxLenCol1)
326 maxColLen = col1Len = maxLenCol1; // user passed in max col length for column 1
327 else
328 {
329 maxColLen = LOOKUP_COL_LEN;
f6bcfd97 330 if (wxStrlen(dispCol2))
e70e8f4c 331 {
94613352 332 wxString q = wxT("SELECT MAX({fn LENGTH(");
e70e8f4c 333 q += dispCol1;
94613352
GT
334 q += wxT(")}), NULL");
335 q += wxT(" FROM ");
e70e8f4c 336 q += tableName;
f6bcfd97 337 if (wxStrlen(where))
e70e8f4c 338 {
94613352 339 q += wxT(" WHERE ");
e70e8f4c
GT
340 q += where;
341 }
94613352 342 if (!lookup2->QueryBySqlStmt(q))
e70e8f4c 343 {
94613352 344 wxMessageBox(wxT("ODBC error during QueryBySqlStmt()"),wxT("ODBC Error..."));
e70e8f4c
GT
345 Close();
346 return;
347 }
348 if (lookup2->GetNext())
349 maxColLen = col1Len = atoi(lookup2->lookupCol1);
350 else
94613352 351 wxMessageBox(wxT("ODBC error during GetNext()"),wxT("ODBC Error..."));
e70e8f4c
GT
352 }
353 }
354
355 // Query the actual record set
f6bcfd97 356 if (selectStmt && wxStrlen(selectStmt)) // Query by sql stmt passed in
e70e8f4c
GT
357 {
358 if (!lookup2->QueryBySqlStmt(selectStmt))
359 {
94613352 360 wxMessageBox(wxT("ODBC error during QueryBySqlStmt()"),wxT("ODBC Error..."));
e70e8f4c
GT
361 Close();
362 return;
363 }
364 }
365 else // Query using where and order by clauses
366 {
f6bcfd97
BP
367 lookup2->SetOrderByClause(orderBy);
368 lookup2->SetWhereClause(where);
e70e8f4c
GT
369 if (!lookup2->Query(FALSE, distinctValues))
370 {
94613352 371 wxMessageBox(wxT("ODBC error during Query()"),wxT("ODBC Error..."));
e70e8f4c
GT
372 Close();
373 return;
374 }
375 }
376
377 // Fill in the list box from the query result set
378 wxString s;
379 while (lookup2->GetNext())
380 {
381 s = lookup2->lookupCol1;
f6bcfd97 382 if (wxStrlen(dispCol2)) // Append the optional column 2
e70e8f4c 383 {
94613352 384 s.Append(wxT(' '), (maxColLen + LISTDB_NO_SPACES_BETWEEN_COLS - wxStrlen(lookup2->lookupCol1)));
e70e8f4c
GT
385 s.Append(lookup2->lookupCol2);
386 }
387 pLookUpSelectList->Append(s);
388 }
389
390 // Highlight the first list item
391 pLookUpSelectList->SetSelection(0);
392
393 // Make the OK activate by pressing Enter
394 if (pLookUpSelectList->Number())
395 pLookUpOkBtn->SetDefault();
396 else
397 {
398 pLookUpCancelBtn->SetDefault();
399 pLookUpOkBtn->Enable(FALSE);
400 }
401
402 pLookUpOkBtn->Enable(allowOk);
403
404 // Display the dialog window
405 SetTitle(windowTitle);
406 Centre(wxBOTH);
407 wxEndBusyCursor();
408 ShowModal();
108106cf
JS
409
410} // Generic lookup constructor 2
411
412
65d7ddc4 413void ClookUpDlg::OnClose(wxCloseEvent& event)
108106cf 414{
e70e8f4c
GT
415 widgetPtrsSet = FALSE;
416 GetParent()->Enable(TRUE);
108106cf 417
e70e8f4c
GT
418 if (lookup)
419 delete lookup;
420 if (lookup2)
421 delete lookup2;
108106cf 422
3ca6a5f0
BP
423 SetReturnCode(1);
424
e70e8f4c 425 while (wxIsBusy()) wxEndBusyCursor();
3ca6a5f0 426 event.Skip();
65d7ddc4 427
e70e8f4c 428// return TRUE;
108106cf
JS
429
430} // ClookUpDlg::OnClose
431
432
65d7ddc4
GT
433void ClookUpDlg::OnButton( wxCommandEvent &event )
434{
435 wxWindow *win = (wxWindow*) event.GetEventObject();
436 OnCommand( *win, event );
437}
438
439
108106cf
JS
440void ClookUpDlg::OnCommand(wxWindow& win, wxCommandEvent& event)
441{
e70e8f4c
GT
442 wxString widgetName = win.GetName();
443
444 if (widgetPtrsSet)
445 {
446 // OK Button
447 if (widgetName == pLookUpOkBtn->GetName())
448 {
449 if (pLookUpSelectList->GetSelection() != -1)
450 {
451 if (noDisplayCols == 1)
f6bcfd97 452 wxStrcpy (ListDB_Selection, pLookUpSelectList->GetStringSelection());
e70e8f4c
GT
453 else // 2 display columns
454 {
455 wxString s = pLookUpSelectList->GetStringSelection();
456 // Column 1
457 s = s.SubString(0, col1Len-1);
458 s = s.Strip();
f6bcfd97 459 wxStrcpy(ListDB_Selection, s);
e70e8f4c
GT
460 // Column 2
461 s = pLookUpSelectList->GetStringSelection();
462 s = s.Mid(col1Len + LISTDB_NO_SPACES_BETWEEN_COLS);
463 s = s.Strip();
f6bcfd97 464 wxStrcpy(ListDB_Selection2, s);
e70e8f4c
GT
465 }
466 }
467 else
468 {
94613352
GT
469 wxStrcpy(ListDB_Selection,wxT(""));
470 wxStrcpy(ListDB_Selection2,wxT(""));
e70e8f4c
GT
471 }
472 Close();
473 } // OK Button
474
475 // Cancel Button
476 if (widgetName == pLookUpCancelBtn->GetName())
477 {
94613352
GT
478 wxStrcpy (ListDB_Selection,wxT(""));
479 wxStrcpy (ListDB_Selection2,wxT(""));
e70e8f4c
GT
480 Close();
481 } // Cancel Button
482 }
108106cf
JS
483
484}; // ClookUpDlg::OnCommand
485
486// *********************************** listdb.cpp **********************************