]> Shamusworld >> Repos - schematic/blob - src/mainwin.cpp
77ceed7d448c2e4a7692307523d7bd5cc3c95325
[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         scmWidget->currentUID = loggedInUID;
200         QString s = QString("User: %1 (%2)").arg(fullName).arg(login);
201         scmWidget->username->setText(s);
202         setCentralWidget(scmWidget);
203 }
204
205
206 void MainWindow::closeEvent(QCloseEvent * event)
207 {
208         WriteSettings();
209         event->accept(); // ignore() if can't close for some reason
210 }
211
212
213 void MainWindow::Open(void)
214 {
215 }
216
217
218 void MainWindow::ShowAboutWin(void)
219 {
220         aboutWin->show();
221 }
222
223
224 void MainWindow::HandleConfigDialog(void)
225 {
226         ConfigDialog dialog(this);
227         dialog.exec();
228 }
229
230
231 void MainWindow::HandleVendorClassDialog(void)
232 {
233         VendorClassDialog dialog(this);
234
235         if (!dialog.exec())
236                 return;
237 }
238
239
240 void MainWindow::HandleNewVendorDialog(void)
241 {
242         NewVendorDialog dialog(this);
243         FillVendorLevelCombo(dialog.combo1);
244         FillContactTypeCombo(dialog.contact->field1);
245         FillVendorClassList(dialog.list);
246
247         if (!dialog.exec())
248                 return;
249
250         // Presumably, the user has given us good data, so we try to populate the
251         // database with this new vendor data.
252
253         // First, see if there is anything missing from the dialog...
254         
255
256         // Create new vendor entry...
257         int vid = -1;
258         bool hasNDA = (dialog.checkbox1->checkState() == Qt::Checked ? true : false);
259         int vlid = dialog.combo1->itemData(dialog.combo1->currentIndex()).toInt();
260         QSqlQuery query;
261         query.prepare("INSERT INTO Vendor VALUES ('', ?, ?, ?)");
262         query.addBindValue(vlid);
263         query.addBindValue(hasNDA);
264         query.addBindValue(dialog.edit1->text());
265         query.exec();
266
267         // Get VID from record just inserted
268         query.prepare("SELECT vid FROM Vendor WHERE vlid=? AND signedNDA=? AND name=?");
269         query.addBindValue(vlid);
270         query.addBindValue(hasNDA);
271         query.addBindValue(dialog.edit1->text());
272         query.exec();
273         query.next();
274         vid = query.value(0).toInt();
275 //printf("NVD: New Vendor VID=%i\n", vid);
276
277         // Add primary address...
278         query.prepare("INSERT INTO Location VALUES ('', ?, ?, ?, ?, ?, ?)");
279         query.addBindValue(vid);
280         query.addBindValue(dialog.address->field1->text());
281         query.addBindValue(dialog.address->field2->text());
282         query.addBindValue(dialog.address->field3->text());
283         query.addBindValue(dialog.address->field4->text());
284         query.addBindValue(dialog.address->field5->text());
285         query.exec();
286
287         // Fix up primary contact type
288         int ctid = -1;
289
290         // -1 in currentIndex() means nothing was selected, so create new entry
291 //NOT SO FAST: Seems it defaults to whatever is found there. So need to fix that. >:-(
292 //      if (dialog.contact->field1->currentIndex() == -1)
293         if (dialog.contact->newContactType)
294         {
295                 query.prepare("INSERT INTO ContactType VALUES ('', ?)");
296                 query.addBindValue(dialog.contact->field1->currentText());
297                 query.exec();
298
299                 query.prepare("SELECT ctid FROM ContactType WHERE description=?");
300                 query.addBindValue(dialog.contact->field1->currentText());
301                 query.exec();
302                 query.next();
303                 ctid = query.value(0).toInt();
304         }
305         else
306         {
307                 ctid = dialog.contact->field1->itemData(dialog.contact->field1->currentIndex()).toInt();
308         }
309
310         // Add primary contact...
311         query.prepare("INSERT INTO Contact VALUES ('', ?, ?, ?, ?, ?, ?, ?, ?)");
312         query.addBindValue(vid);
313         query.addBindValue(ctid);
314         query.addBindValue(dialog.contact->field2->text());
315         query.addBindValue(dialog.contact->field3->text());
316         query.addBindValue(dialog.contact->field4->text());
317         query.addBindValue(dialog.contact->field5->text());
318         query.addBindValue(dialog.contact->field6->text());
319         query.addBindValue(dialog.contact->field7->text());
320         query.exec();
321
322         // Add vendor classes...
323         for(int i=0; i<dialog.list->count(); i++)
324         {
325                 QListWidgetItem * item = dialog.list->item(i);
326
327                 if (item->checkState() == Qt::Checked)
328                 {
329                         int vtid = item->data(Qt::UserRole).toInt();
330                         query.prepare("INSERT INTO VendorSpecificTypes VALUES (?, ?)");
331                         query.addBindValue(vid);
332                         query.addBindValue(vtid);
333                         query.exec();
334                 }
335         }
336
337         // Update UI
338         scmWidget->GetVendorIDs();
339         scmWidget->GetVendor(vid);
340
341 //printf("NVD: Contact Type index = %i\n", dialog.contact->field1->currentIndex());
342 //printf("NVD: Contact type ='%s'\n", dialog.contact->field1->currentText().toAscii().data());
343 //-1 means no contact selected; check currentText() to see if it has anything in it or not
344
345         // Tables to fill:
346 #if 0
347 Vendor
348 VID (P-key) | VLID | signedNDA | Name
349 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;
350
351 VendorType
352 VTID (P-key) | VGID | SeqNo | Description
353 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;
354
355 VendorSpecificTypes
356 VID (multi) | VTID (multi)
357 CREATE TABLE VendorSpecificTypes (vid INT, vtid INT, FOREIGN KEY (vid) REFERENCES Vendor(vid), FOREIGN KEY (vtid) REFERENCES VendorType(vtid)) ENGINE=INNODB;
358
359 Location
360 LID (P-key) | VID | Address | City | State | Country | Code
361 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;
362
363 Contact
364 CID (P-key) | VID | CTID | Name | Email | Address | Phone1 | Phone2 | Fax
365 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;
366
367 ContactType
368 CTID (P-key) | Description
369 CREATE TABLE ContactType (ctid INT NOT NULL PRIMARY KEY AUTO_INCREMENT, description VARCHAR(100)) ENGINE=INNODB;
370 #endif
371 }
372
373
374 void MainWindow::FillVendorLevelCombo(QComboBox * combo)
375 {
376         QSqlQuery query;
377         query.prepare("SELECT VLID, Description FROM VendorLevel");
378         query.exec();
379
380         while (query.next())
381         {
382                 int vlid = query.value(0).toInt();
383                 QString description = query.value(1).toString();
384
385                 combo->addItem(description, vlid);
386         }
387 }
388
389
390 void MainWindow::FillContactTypeCombo(QComboBox * combo)
391 {
392         QSqlQuery query;
393         query.prepare("SELECT CTID, Description FROM ContactType");
394         query.exec();
395
396         while (query.next())
397         {
398                 int ctid = query.value(0).toInt();
399                 QString description = query.value(1).toString();
400
401                 combo->addItem(description, ctid);
402         }
403 }
404
405
406 void MainWindow::FillVendorClassList(QListWidget * list)
407 {
408         std::vector<VendorType> groupList;
409
410         // Pull in definitions from DB for Vendor Classes/Groups
411         QSqlQuery query1;
412         query1.prepare("SELECT vgid, description FROM VendorGroup ORDER BY seqNo");
413         query1.exec();
414
415         while (query1.next())
416         {
417                 VendorType v;
418                 v.key         = query1.value(0).toInt();
419                 v.description = query1.value(1).toString();
420                 groupList.push_back(v);
421         }
422
423 //      QSqlQuery query2;
424         query1.prepare("SELECT vtid, vgid, description FROM VendorType ORDER BY seqNo");
425         query1.exec();
426
427         int previousID = -1, groupListIndex = 0;
428         QListWidgetItem * item;
429
430         while (query1.next())
431         {
432 //              VendorType v;
433                 int vtid            = query1.value(0).toInt();
434                 int vgid            = query1.value(1).toInt();
435                 QString description = query1.value(2).toString();
436
437                 // Check to see if we need to insert new header yet.
438                 // If we're not still in same group, push the next group header into the list
439                 // and continue
440                 if (previousID != vgid)
441                 {
442                         item  = new QListWidgetItem(groupList[groupListIndex].description);
443                         item->setData(Qt::UserRole, groupList[groupListIndex++].key);
444                         item->setFont(*boldFont);
445                         list->addItem(item);
446                         previousID = vgid;
447                 }
448
449                 item  = new QListWidgetItem(description);
450                 item->setData(Qt::UserRole, vtid);
451                 item->setCheckState(Qt::Unchecked);
452                 list->addItem(item);
453         }
454 }
455
456
457 void MainWindow::ReadSettings(void)
458 {
459         QSettings settings("Underground Software", "SCheMatic");
460         QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
461         QSize size = settings.value("size", QSize(400, 400)).toSize();
462         resize(size);
463         move(pos);
464 //      pos = settings.value("charWndPos", QPoint(0, 0)).toPoint();
465 //      size = settings.value("charWndSize", QSize(200, 200)).toSize();
466 //      ((TTEdit *)qApp)->charWnd->resize(size);
467 //      ((TTEdit *)qApp)->charWnd->move(pos);
468
469         dbDriver = settings.value("dbDriver", "myodbc-5.1").toString();
470         dbHostName = settings.value("dbHostName", "localhost").toString();
471         dbName = settings.value("dbName", "schematic").toString();
472         dbUserName = settings.value("dbUserName", "scm_user").toString();
473         dbPassword = settings.value("dbPassword", "scm_user").toString();
474 }
475
476
477 void MainWindow::WriteSettings(void)
478 {
479         QSettings settings("Underground Software", "SCheMatic");
480         settings.setValue("pos", pos());
481         settings.setValue("size", size());
482 //      settings.setValue("charWndPos", ((TTEdit *)qApp)->charWnd->pos());
483 //      settings.setValue("charWndSize", ((TTEdit *)qApp)->charWnd->size());
484
485         settings.setValue("dbDriver", dbDriver);
486         settings.setValue("dbHostName", dbHostName);
487         settings.setValue("dbName", dbName);
488         settings.setValue("dbUserName", dbUserName);
489         settings.setValue("dbPassword", dbPassword);
490 }
491