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