]> Shamusworld >> Repos - schematic/blob - src/mainwin.cpp
Move DB access to NoteDialog class, new AlertDialog class.
[schematic] / src / mainwin.cpp
1 //
2 // mainwin.cpp - The Supply Chain Manager-O-Matic
3 // by James Hammons
4 // (C) 2012 Underground Software
5 //
6 // JLH = James Hammons <jlhamm@acm.org>
7 //
8 // Who  When        What
9 // ---  ----------  -------------------------------------------------------------
10 // JLH  09/14/2012  Created this file
11 //
12
13 // Uncomment this for debugging...
14 //#define DEBUG
15 //#define DEBUGFOO                              // Various tool debugging...
16 //#define DEBUGTP                               // Toolpalette debugging...
17
18 #include "mainwin.h"
19 #include "about.h"
20 #include "configdialog.h"
21 #include "logindialog.h"
22 #include "newvendordialog.h"
23 #include "scmwidget.h"
24 #include "sqlsettingsdialog.h"
25 #include "vendorclassdialog.h"
26
27
28 MainWindow::MainWindow(): aboutWin(new AboutWindow(this)),
29         boldFont(new QFont),
30         loggedInUID(0)
31 {
32         setWindowIcon(QIcon(":/res/schematic.png"));
33         setWindowTitle("SCheMatic");
34
35         setUnifiedTitleAndToolBarOnMac(true);
36
37         // Create actions
38
39         quitAppAct = new QAction(tr("E&xit"), this);
40         quitAppAct->setShortcut(QKeySequence(tr("Ctrl+q")));
41         quitAppAct->setStatusTip(tr("Quit SCheMatic"));
42         connect(quitAppAct, SIGNAL(triggered()), this, SLOT(close()));
43
44         aboutAct = new QAction(QIcon(":/res/schematic.png"), tr("&About..."), this);
45         aboutAct->setStatusTip(tr("Blatant self-promotion"));
46         connect(aboutAct, SIGNAL(triggered()), this, SLOT(ShowAboutWin()));
47
48         configAct = new QAction(QIcon(":/res/schematic.png"), tr("&Configure..."), this);
49         configAct->setStatusTip(tr("Configure SCheMatic"));
50         connect(configAct, SIGNAL(triggered()), this, SLOT(HandleConfigDialog()));
51
52         vendorClassAct = new QAction(QIcon(":/res/schematic.png"), tr("&Edit Vendor Classes..."), this);
53         vendorClassAct->setStatusTip(tr("Edit Vendor Classes"));
54         connect(vendorClassAct, SIGNAL(triggered()), this, SLOT(HandleVendorClassDialog()));
55
56         newVendorAct = new QAction(QIcon(":/res/schematic.png"), tr("&Add Vendor..."), this);
57         newVendorAct->setStatusTip(tr("Create a new vendor"));
58         connect(newVendorAct, SIGNAL(triggered()), this, SLOT(HandleNewVendorDialog()));
59
60 //      helpAct = new QAction(QIcon(":/res/vj-icon.png"), tr("&Contents..."), this);
61 //      helpAct->setStatusTip(tr("Help is available, if you should need it"));
62 //      connect(helpAct, SIGNAL(triggered()), this, SLOT(ShowHelpWin()));
63
64         // Create menus & toolbars
65
66         QMenu * menu = menuBar()->addMenu(tr("&File"));
67 //      fileMenu->addAction(powerAct);
68 //      fileMenu->addAction(pauseAct);
69 //      fileMenu->addAction(frameAdvanceAct);
70 //      fileMenu->addAction(filePickAct);
71 //      fileMenu->addAction(useCDAct);
72 //      fileMenu->addAction(configAct);
73         menu->addAction(quitAppAct);
74
75         menu = menuBar()->addMenu(tr("&Edit"));
76         menu->addAction(configAct);
77         menu->addAction(vendorClassAct);
78         menu->addAction(newVendorAct);
79
80         menu = menuBar()->addMenu(tr("&Help"));
81 //      menu->addAction(helpAct);
82         menu->addAction(aboutAct);
83
84         QToolBar * toolbar = addToolBar(tr("Stuff"));
85 //      toolbar->addAction(powerAct);
86 //      toolbar->addAction(pauseAct);
87 //      toolbar->addAction(filePickAct);
88 //      toolbar->addAction(useCDAct);
89 //      toolbar->addSeparator();
90 //      toolbar->addAction(x1Act);
91 //      toolbar->addAction(x2Act);
92 //      toolbar->addAction(x3Act);
93 //      toolbar->addSeparator();
94 //      toolbar->addAction(ntscAct);
95 //      toolbar->addAction(palAct);
96 //      toolbar->addSeparator();
97 //      toolbar->addAction(blurAct);
98 //      toolbar->addAction(fullScreenAct);
99
100         //      Create status bar
101         statusBar()->showMessage(tr("Ready"));
102
103         ReadSettings();
104         boldFont->setBold(true);
105
106         // Finally, set up database connection
107
108         db = QSqlDatabase::addDatabase("QODBC");
109         bool ok = false;
110
111         // Prime the SQL Settings dialog (in case we need it)
112
113         SQLSettingsDialog sqlSettings;
114         sqlSettings.edit1->setText(dbDriver);
115         sqlSettings.edit2->setText(dbHostName);
116         sqlSettings.edit3->setText(dbName);
117         sqlSettings.edit4->setText(dbUserName);
118         sqlSettings.edit5->setText(dbPassword);
119
120         do
121         {
122                 // Set up the ODBC DB connection with saved settings
123                 // NB: For this to work properly on 64-bit Windows, you need to use the 32-bit driver!
124                 QString odbc = QString("DRIVER={%1};DATABASE=%2;SERVER=%3;UID=%4;PASSWORD=%5")
125                         .arg(dbDriver).arg(dbName).arg(dbHostName).arg(dbUserName).arg(dbPassword);
126                 db.setDatabaseName(odbc);
127                 ok = db.open();
128
129                 // If unsuccessful, run the SQL settings/test dialog
130                 if (!ok)
131                 {
132                         sqlSettings.error1->setText(db.lastError().databaseText());
133                         sqlSettings.error2->setText(db.lastError().driverText());
134
135                         if (sqlSettings.exec())
136                         {
137                                 // User thinks this will work (hit OK button), so prime the variables
138                                 // for the next attempt
139                                 dbDriver = sqlSettings.edit1->text();
140                                 dbHostName = sqlSettings.edit2->text();
141                                 dbName = sqlSettings.edit3->text();
142                                 dbUserName = sqlSettings.edit4->text();
143                                 dbPassword = sqlSettings.edit5->text();
144                         }
145                         else
146                                 return;                                         // User cancelled the dialog, so quit
147                 }
148         }
149         while (!ok);
150
151         // Check to see how many users are in the system; if less than 2, we don't do a login
152         QSqlQuery query;
153         query.prepare("SELECT COUNT(*) FROM User");
154         query.exec();
155         query.next();
156
157         if (query.value(0).toInt() > 1)
158         {
159                 // Do Login dialog
160                 LoginDialog loginDlg;
161                 bool done = false;
162
163                 do
164                 {
165                         bool accept = loginDlg.exec();
166
167                         // Check to see if user cancelled out
168                         if (!accept)
169                                 done = true;
170                         else
171                         {
172                                 // Search DB for this username/login pair
173                                 QSqlQuery query;
174                                 query.prepare("SELECT UID, name, login FROM User WHERE Login=? AND Password=?");
175                                 query.addBindValue(loginDlg.edit1->text());
176                                 query.addBindValue(loginDlg.edit2->text());
177                                 query.exec();
178
179                                 while (query.next())
180                                 {
181                                         // We have a winner!
182                                         loggedInUID = query.value(0).toInt();
183                                         fullName = query.value(1).toString();
184                                         login = query.value(2).toString();
185                                         done = true;
186                                 }
187                         }
188                 }
189                 while (!done);
190         }
191         else
192         {
193                 fullName = "Administrator";
194                 login = "admin";
195                 loggedInUID = 1;
196         }
197
198         scmWidget = new SCMWidget(this);
199         QString s = QString("User: %1 (%2)").arg(fullName).arg(login);
200         scmWidget->username->setText(s);
201         scmWidget->currentUID = loggedInUID;
202         scmWidget->UpdateNotes();
203         setCentralWidget(scmWidget);
204 }
205
206
207 void MainWindow::closeEvent(QCloseEvent * event)
208 {
209         WriteSettings();
210         event->accept(); // ignore() if can't close for some reason
211 }
212
213
214 void MainWindow::Open(void)
215 {
216 }
217
218
219 void MainWindow::ShowAboutWin(void)
220 {
221         aboutWin->show();
222 }
223
224
225 void MainWindow::HandleConfigDialog(void)
226 {
227         ConfigDialog dialog(this);
228         dialog.exec();
229 }
230
231
232 void MainWindow::HandleVendorClassDialog(void)
233 {
234         VendorClassDialog dialog(this);
235
236         if (!dialog.exec())
237                 return;
238 }
239
240
241 void MainWindow::HandleNewVendorDialog(void)
242 {
243         NewVendorDialog dialog(this);
244         FillVendorLevelCombo(dialog.combo1);
245         FillContactTypeCombo(dialog.contact->field1);
246         FillVendorClassList(dialog.list);
247
248         if (!dialog.exec())
249                 return;
250
251         // Presumably, the user has given us good data, so we try to populate the
252         // database with this new vendor data.
253
254         // First, see if there is anything missing from the dialog...
255         
256
257         // Create new vendor entry...
258         int vid = -1;
259         bool hasNDA = (dialog.checkbox1->checkState() == Qt::Checked ? true : false);
260         int vlid = dialog.combo1->itemData(dialog.combo1->currentIndex()).toInt();
261         QSqlQuery query;
262         query.prepare("INSERT INTO Vendor VALUES ('', ?, ?, ?)");
263         query.addBindValue(vlid);
264         query.addBindValue(hasNDA);
265         query.addBindValue(dialog.edit1->text());
266         query.exec();
267
268         // Get VID from record just inserted
269         query.prepare("SELECT vid FROM Vendor WHERE vlid=? AND signedNDA=? AND name=?");
270         query.addBindValue(vlid);
271         query.addBindValue(hasNDA);
272         query.addBindValue(dialog.edit1->text());
273         query.exec();
274         query.next();
275         vid = query.value(0).toInt();
276 //printf("NVD: New Vendor VID=%i\n", vid);
277
278         // Add primary address...
279         query.prepare("INSERT INTO Location VALUES ('', ?, ?, ?, ?, ?, ?)");
280         query.addBindValue(vid);
281         query.addBindValue(dialog.address->field1->text());
282         query.addBindValue(dialog.address->field2->text());
283         query.addBindValue(dialog.address->field3->text());
284         query.addBindValue(dialog.address->field4->text());
285         query.addBindValue(dialog.address->field5->text());
286         query.exec();
287
288         // Fix up primary contact type
289         int ctid = -1;
290
291         // -1 in currentIndex() means nothing was selected, so create new entry
292 //NOT SO FAST: Seems it defaults to whatever is found there. So need to fix that. >:-(
293 //      if (dialog.contact->field1->currentIndex() == -1)
294         if (dialog.contact->newContactType)
295         {
296                 query.prepare("INSERT INTO ContactType VALUES ('', ?)");
297                 query.addBindValue(dialog.contact->field1->currentText());
298                 query.exec();
299
300                 query.prepare("SELECT ctid FROM ContactType WHERE description=?");
301                 query.addBindValue(dialog.contact->field1->currentText());
302                 query.exec();
303                 query.next();
304                 ctid = query.value(0).toInt();
305         }
306         else
307         {
308                 ctid = dialog.contact->field1->itemData(dialog.contact->field1->currentIndex()).toInt();
309         }
310
311         // Add primary contact...
312         query.prepare("INSERT INTO Contact VALUES ('', ?, ?, ?, ?, ?, ?, ?, ?)");
313         query.addBindValue(vid);
314         query.addBindValue(ctid);
315         query.addBindValue(dialog.contact->field2->text());
316         query.addBindValue(dialog.contact->field3->text());
317         query.addBindValue(dialog.contact->field4->text());
318         query.addBindValue(dialog.contact->field5->text());
319         query.addBindValue(dialog.contact->field6->text());
320         query.addBindValue(dialog.contact->field7->text());
321         query.exec();
322
323         // Add vendor classes...
324         for(int i=0; i<dialog.list->count(); i++)
325         {
326                 QListWidgetItem * item = dialog.list->item(i);
327
328                 if (item->checkState() == Qt::Checked)
329                 {
330                         int vtid = item->data(Qt::UserRole).toInt();
331                         query.prepare("INSERT INTO VendorSpecificTypes VALUES (?, ?)");
332                         query.addBindValue(vid);
333                         query.addBindValue(vtid);
334                         query.exec();
335                 }
336         }
337
338         // Update UI
339         scmWidget->GetVendorIDs();
340         scmWidget->GetVendor(vid);
341
342 //printf("NVD: Contact Type index = %i\n", dialog.contact->field1->currentIndex());
343 //printf("NVD: Contact type ='%s'\n", dialog.contact->field1->currentText().toAscii().data());
344 //-1 means no contact selected; check currentText() to see if it has anything in it or not
345
346         // Tables to fill:
347 #if 0
348 Vendor
349 VID (P-key) | VLID | signedNDA | Name
350 CREATE TABLE Vendor (vid INT NOT NULL PRIMARY KEY AUTO_INCREMENT, vlid INT, signedNDA TINYINT(1) NOT NULL DEFAULT 0, name VARCHAR(100), FOREIGN KEY (vlid) REFERENCES VendorLevel(vlid)) ENGINE=INNODB;
351
352 VendorType
353 VTID (P-key) | VGID | SeqNo | Description
354 CREATE TABLE VendorType (vtid INT NOT NULL PRIMARY KEY AUTO_INCREMENT, vgid INT, seqNo INT(4) NOT NULL, description VARCHAR(100), FOREIGN KEY (vgid) REFERENCES VendorGroup(vgid)) ENGINE=INNODB;
355
356 VendorSpecificTypes
357 VID (multi) | VTID (multi)
358 CREATE TABLE VendorSpecificTypes (vid INT, vtid INT, FOREIGN KEY (vid) REFERENCES Vendor(vid), FOREIGN KEY (vtid) REFERENCES VendorType(vtid)) ENGINE=INNODB;
359
360 Location
361 LID (P-key) | VID | Address | City | State | Country | Code
362 CREATE TABLE Location (lid INT NOT NULL PRIMARY KEY AUTO_INCREMENT, vid INT, address VARCHAR(100), city VARCHAR(64), state VARCHAR(64), country VARCHAR(64), code VARCHAR(32), FOREIGN KEY (vid) REFERENCES Vendor(vid)) ENGINE=INNODB;
363
364 Contact
365 CID (P-key) | VID | CTID | Name | Email | Address | Phone1 | Phone2 | Fax
366 CREATE TABLE Contact (cid INT NOT NULL PRIMARY KEY AUTO_INCREMENT, vid INT, CTID int, name VARCHAR(64), email VARCHAR(64), address VARCHAR(200), phone1 VARCHAR(32), phone2 VARCHAR(32), fax VARCHAR(32), FOREIGN KEY (vid) REFERENCES Vendor(vid), FOREIGN KEY (ctid) REFERENCES ContactType(ctid)) ENGINE=INNODB;
367
368 ContactType
369 CTID (P-key) | Description
370 CREATE TABLE ContactType (ctid INT NOT NULL PRIMARY KEY AUTO_INCREMENT, description VARCHAR(100)) ENGINE=INNODB;
371 #endif
372 }
373
374
375 void MainWindow::FillVendorLevelCombo(QComboBox * combo)
376 {
377         QSqlQuery query;
378         query.prepare("SELECT VLID, Description FROM VendorLevel");
379         query.exec();
380
381         while (query.next())
382         {
383                 int vlid = query.value(0).toInt();
384                 QString description = query.value(1).toString();
385
386                 combo->addItem(description, vlid);
387         }
388 }
389
390
391 void MainWindow::FillContactTypeCombo(QComboBox * combo)
392 {
393         QSqlQuery query;
394         query.prepare("SELECT CTID, Description FROM ContactType");
395         query.exec();
396
397         while (query.next())
398         {
399                 int ctid = query.value(0).toInt();
400                 QString description = query.value(1).toString();
401
402                 combo->addItem(description, ctid);
403         }
404 }
405
406
407 void MainWindow::FillVendorClassList(QListWidget * list)
408 {
409         std::vector<VendorType> groupList;
410
411         // Pull in definitions from DB for Vendor Classes/Groups
412         QSqlQuery query1;
413         query1.prepare("SELECT vgid, description FROM VendorGroup ORDER BY seqNo");
414         query1.exec();
415
416         while (query1.next())
417         {
418                 VendorType v;
419                 v.key         = query1.value(0).toInt();
420                 v.description = query1.value(1).toString();
421                 groupList.push_back(v);
422         }
423
424 //      QSqlQuery query2;
425         query1.prepare("SELECT vtid, vgid, description FROM VendorType ORDER BY seqNo");
426         query1.exec();
427
428         int previousID = -1, groupListIndex = 0;
429         QListWidgetItem * item;
430
431         while (query1.next())
432         {
433 //              VendorType v;
434                 int vtid            = query1.value(0).toInt();
435                 int vgid            = query1.value(1).toInt();
436                 QString description = query1.value(2).toString();
437
438                 // Check to see if we need to insert new header yet.
439                 // If we're not still in same group, push the next group header into the list
440                 // and continue
441                 if (previousID != vgid)
442                 {
443                         item  = new QListWidgetItem(groupList[groupListIndex].description);
444                         item->setData(Qt::UserRole, groupList[groupListIndex++].key);
445                         item->setFont(*boldFont);
446                         list->addItem(item);
447                         previousID = vgid;
448                 }
449
450                 item  = new QListWidgetItem(description);
451                 item->setData(Qt::UserRole, vtid);
452                 item->setCheckState(Qt::Unchecked);
453                 list->addItem(item);
454         }
455 }
456
457
458 void MainWindow::ReadSettings(void)
459 {
460         QSettings settings("Underground Software", "SCheMatic");
461         QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
462         QSize size = settings.value("size", QSize(400, 400)).toSize();
463         resize(size);
464         move(pos);
465 //      pos = settings.value("charWndPos", QPoint(0, 0)).toPoint();
466 //      size = settings.value("charWndSize", QSize(200, 200)).toSize();
467 //      ((TTEdit *)qApp)->charWnd->resize(size);
468 //      ((TTEdit *)qApp)->charWnd->move(pos);
469
470         dbDriver = settings.value("dbDriver", "myodbc-5.1").toString();
471         dbHostName = settings.value("dbHostName", "localhost").toString();
472         dbName = settings.value("dbName", "schematic").toString();
473         dbUserName = settings.value("dbUserName", "scm_user").toString();
474         dbPassword = settings.value("dbPassword", "scm_user").toString();
475 }
476
477
478 void MainWindow::WriteSettings(void)
479 {
480         QSettings settings("Underground Software", "SCheMatic");
481         settings.setValue("pos", pos());
482         settings.setValue("size", size());
483 //      settings.setValue("charWndPos", ((TTEdit *)qApp)->charWnd->pos());
484 //      settings.setValue("charWndSize", ((TTEdit *)qApp)->charWnd->size());
485
486         settings.setValue("dbDriver", dbDriver);
487         settings.setValue("dbHostName", dbHostName);
488         settings.setValue("dbName", dbName);
489         settings.setValue("dbUserName", dbUserName);
490         settings.setValue("dbPassword", dbPassword);
491 }
492