Mercurial > hg > syntilista
comparison main.cpp @ 0:fec4d0c461f2
Initial import of the post-prototyping phase code.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Thu, 30 Mar 2017 03:20:08 +0300 |
parents | |
children | db8f47446713 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:fec4d0c461f2 |
---|---|
1 // | |
2 // Syntilista - velkalistasovellus Kampus-kahvilaan | |
3 // Programmed and designed by Matti Hämäläinen <ccr@tnsp.org> | |
4 // (C) Copyright 2017 Tecnic Software productions (TNSP) | |
5 // | |
6 #include <QApplication> | |
7 #include <QMessageBox> | |
8 #include <QSettings> | |
9 #include "main.h" | |
10 #include "ui_mainwindow.h" | |
11 #include "ui_editperson.h" | |
12 | |
13 static QString query_Person = | |
14 "SELECT id,last_name,first_name," | |
15 "(SELECT SUM(value) FROM transactions WHERE transactions.person=people.id) AS balance," | |
16 "updated FROM people"; | |
17 | |
18 | |
19 | |
20 void appError(QString title, QString msg) | |
21 { | |
22 QMessageBox::critical(0, title, msg, QMessageBox::Ok); | |
23 QApplication::exit(); | |
24 } | |
25 | |
26 | |
27 double moneyStrToValue(const QString &str) | |
28 { | |
29 QString str2 = str; | |
30 return str2.replace(",", ".").toDouble(); | |
31 } | |
32 | |
33 | |
34 QString moneyValueToStr(double val) | |
35 { | |
36 return QStringLiteral("%1").arg(val, 1, 'f', 2); | |
37 } | |
38 | |
39 | |
40 QString cleanupStr(const QString &str) | |
41 { | |
42 return str.simplified().trimmed(); | |
43 } | |
44 | |
45 | |
46 const QString dateTimeToStr(const QDateTime &val) | |
47 { | |
48 QDateTime tmp = val; | |
49 tmp.setOffsetFromUtc(0); | |
50 return tmp.toLocalTime().toString(QStringLiteral("yyyy-MM-dd hh:mm")); | |
51 } | |
52 | |
53 | |
54 bool checkAndReportSQLError(const QString where, const QSqlError &err) | |
55 { | |
56 if (err.isValid()) | |
57 { | |
58 printf("SQL Error in %s: %s\n", | |
59 where.toUtf8().constData(), | |
60 err.text().toUtf8().constData()); | |
61 return true; | |
62 } | |
63 else | |
64 return false; | |
65 } | |
66 | |
67 | |
68 int main(int argc, char *argv[]) | |
69 { | |
70 QApplication sapp(argc, argv); | |
71 | |
72 // | |
73 // Initialize / open SQL database connection | |
74 // | |
75 QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); | |
76 db.setDatabaseName(qApp->applicationDirPath() + QDir::separator() + "syntilista.sqlite3"); | |
77 | |
78 if (!db.open()) | |
79 { | |
80 appError( | |
81 "Cannot open database", | |
82 "Unable to establish a database connection.\n" | |
83 "This example needs SQLite support. Please read " | |
84 "the Qt SQL driver documentation for information how " | |
85 "to build it." | |
86 ); | |
87 return false; | |
88 } | |
89 | |
90 QSqlQuery query; | |
91 query.exec( | |
92 "CREATE TABLE people (id INTEGER PRIMARY KEY, " | |
93 "first_name VARCHAR(128) NOT NULL, " | |
94 "last_name VARCHAR(128) NOT NULL, " | |
95 "extra_info VARCHAR(2048), " | |
96 "added DATETIME NOT NULL, " | |
97 "updated DATETIME NOT NULL)"); | |
98 | |
99 checkAndReportSQLError("CREATE TABLE people", query.lastError()); | |
100 | |
101 query.exec( | |
102 "CREATE TABLE transactions (" | |
103 "id INTEGER PRIMARY KEY, " | |
104 "person INT NOT NULL, " | |
105 "value REAL, " | |
106 "added DATETIME NOT NULL)"); | |
107 | |
108 checkAndReportSQLError("CREATE TABLE transactions", query.lastError()); | |
109 | |
110 SyntilistaMainWindow swin; | |
111 swin.show(); | |
112 return sapp.exec(); | |
113 } | |
114 | |
115 | |
116 // | |
117 // Main application window code | |
118 // | |
119 SyntilistaMainWindow::SyntilistaMainWindow(QWidget *parent) : | |
120 QMainWindow(parent), | |
121 ui(new Ui::SyntilistaMainWindow) | |
122 { | |
123 ui->setupUi(this); | |
124 ui->edit_Amount->setValidator(new QDoubleValidator(0, 1000, 2, this)); | |
125 | |
126 readSettings(); | |
127 | |
128 peopleSortIndex = 1; | |
129 peopleSortOrder = Qt::AscendingOrder; | |
130 peopleFilter = ""; | |
131 | |
132 model_People = new PersonSQLModel(); | |
133 updatePersonList(); | |
134 | |
135 ui->tableview_People->setModel(model_People); | |
136 ui->tableview_People->setColumnHidden(0, true); | |
137 ui->tableview_People->setItemDelegate(new QSqlRelationalDelegate(ui->tableview_People)); | |
138 ui->tableview_People->verticalHeader()->setVisible(false); | |
139 ui->tableview_People->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); | |
140 ui->tableview_People->setSortingEnabled(true); | |
141 | |
142 connect(ui->tableview_People->selectionModel(), | |
143 SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), | |
144 this, SLOT(selectedPersonChanged(const QModelIndex &, const QModelIndex &))); | |
145 | |
146 connect(ui->tableview_People->horizontalHeader(), | |
147 SIGNAL(sortIndicatorChanged(int, Qt::SortOrder)), | |
148 this, | |
149 SLOT(updateSortOrder(int, Qt::SortOrder))); | |
150 | |
151 ui->tableview_People->horizontalHeader()->setSortIndicator(1, Qt::AscendingOrder); | |
152 | |
153 model_Latest = new TransactionSQLModel(); | |
154 ui->tableview_Latest->setModel(model_Latest); | |
155 ui->tableview_Latest->setItemDelegate(new QSqlRelationalDelegate(ui->tableview_Latest)); | |
156 ui->tableview_Latest->verticalHeader()->setVisible(false); | |
157 ui->tableview_Latest->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); | |
158 | |
159 setActivePerson(-1); | |
160 } | |
161 | |
162 | |
163 SyntilistaMainWindow::~SyntilistaMainWindow() | |
164 { | |
165 printf("QUITTAUS\n"); | |
166 | |
167 saveSettings(); | |
168 | |
169 delete ui; | |
170 delete model_People; | |
171 delete model_Latest; | |
172 } | |
173 | |
174 | |
175 void SyntilistaMainWindow::statusMsg(const QString &msg) | |
176 { | |
177 ui->statusbar->showMessage(msg); | |
178 } | |
179 | |
180 | |
181 void SyntilistaMainWindow::readSettings() | |
182 { | |
183 QSettings settings(APP_VENDOR, APP_NAME); | |
184 move(settings.value("pos", QPoint(100, 100)).toPoint()); | |
185 resize(settings.value("size", QSize(1000, 600)).toSize()); | |
186 } | |
187 | |
188 | |
189 void SyntilistaMainWindow::saveSettings() | |
190 { | |
191 QSettings settings(APP_VENDOR, APP_NAME); | |
192 settings.setValue("pos", pos()); | |
193 settings.setValue("size", size()); | |
194 } | |
195 | |
196 | |
197 void SyntilistaMainWindow::selectedPersonChanged(const QModelIndex &curr, const QModelIndex &prev) | |
198 { | |
199 (void) prev; | |
200 int row = curr.row(); | |
201 if (row >= 0) | |
202 { | |
203 const QAbstractItemModel *model = curr.model(); | |
204 setActivePerson(model->data(model->index(row, 0)).toInt()); | |
205 } | |
206 else | |
207 setActivePerson(-1); | |
208 } | |
209 | |
210 | |
211 void SyntilistaMainWindow::updateSortOrder(int index, Qt::SortOrder order) | |
212 { | |
213 peopleSortIndex = index; | |
214 peopleSortOrder = order; | |
215 updatePersonList(); | |
216 } | |
217 | |
218 | |
219 void SyntilistaMainWindow::setActivePerson(qint64 id) | |
220 { | |
221 personID = id; | |
222 | |
223 if (id >= 0) | |
224 { | |
225 QSqlQuery person; | |
226 person.prepare(query_Person +" WHERE id=?"); | |
227 person.addBindValue(id); | |
228 person.exec(); | |
229 checkAndReportSQLError("SELECT in setActivePerson()", person.lastError()); | |
230 | |
231 if (!person.next()) | |
232 { | |
233 statusMsg(tr("ERROR! No person with ID #%1").arg(id)); | |
234 } | |
235 else | |
236 { | |
237 ui->personGB->setEnabled(true); | |
238 ui->label_PersonName->setText(person.value(1).toString() +", "+ person.value(2).toString()); | |
239 | |
240 double balance = person.value(3).toDouble(); | |
241 ui->label_BalanceValue->setText(moneyValueToStr(balance)); | |
242 ui->label_BalanceValue->setStyleSheet(balance < 0 ? "color: red;" : "color: green;"); | |
243 | |
244 QSqlQuery query; | |
245 query.prepare("SELECT id,value,added FROM transactions WHERE person=? ORDER BY added DESC LIMIT 5"); | |
246 query.addBindValue(id); | |
247 query.exec(); | |
248 checkAndReportSQLError("SELECT transactions for tableview_Latest", query.lastError()); | |
249 | |
250 model_Latest->setQuery(query); | |
251 | |
252 model_Latest->setHeaderData(0, Qt::Horizontal, "ID"); | |
253 model_Latest->setHeaderData(1, Qt::Horizontal, "Summa"); | |
254 model_Latest->setHeaderData(2, Qt::Horizontal, "Aika"); | |
255 | |
256 ui->tableview_Latest->setModel(model_Latest); | |
257 ui->tableview_Latest->setColumnHidden(0, true); | |
258 ui->tableview_Latest->verticalHeader()->setVisible(false); | |
259 ui->tableview_Latest->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); | |
260 | |
261 return; // Ugly | |
262 } | |
263 } | |
264 | |
265 // In case of id < 0 or errors .. | |
266 ui->personGB->setEnabled(false); | |
267 ui->edit_Amount->clear(); | |
268 ui->label_BalanceValue->setText("--"); | |
269 ui->label_BalanceValue->setStyleSheet(NULL); | |
270 ui->label_PersonName->setText("???"); | |
271 ui->tableview_Latest->setModel(NULL); | |
272 } | |
273 | |
274 | |
275 // | |
276 // Widget slot handlers | |
277 // | |
278 void SyntilistaMainWindow::on_button_Quit_clicked() | |
279 { | |
280 close(); | |
281 } | |
282 | |
283 | |
284 void SyntilistaMainWindow::on_button_AddPerson_clicked() | |
285 { | |
286 EditPerson *person = new EditPerson(this); | |
287 person->setPerson(-1); | |
288 } | |
289 | |
290 | |
291 void SyntilistaMainWindow::on_button_EditPerson_clicked() | |
292 { | |
293 EditPerson *person = new EditPerson(this); | |
294 person->setPerson(personID); | |
295 } | |
296 | |
297 | |
298 void SyntilistaMainWindow::on_tableview_People_doubleClicked(const QModelIndex &curr) | |
299 { | |
300 int row = curr.row(); | |
301 if (row >= 0) | |
302 { | |
303 const QAbstractItemModel *model = curr.model(); | |
304 setActivePerson(model->data(model->index(row, 0)).toInt()); | |
305 | |
306 EditPerson *person = new EditPerson(this); | |
307 person->setPerson(personID); | |
308 } | |
309 else | |
310 setActivePerson(-1); | |
311 } | |
312 | |
313 | |
314 void SyntilistaMainWindow::on_button_ClearFilter_clicked() | |
315 { | |
316 ui->edit_PersonFilter->clear(); | |
317 } | |
318 | |
319 | |
320 void SyntilistaMainWindow::updatePersonData(qint64 id) | |
321 { | |
322 printf("updatePersonData(%lld)\n", id); | |
323 if (id == personID) | |
324 setActivePerson(id); | |
325 | |
326 model_People->updateModel(); | |
327 } | |
328 | |
329 | |
330 void SyntilistaMainWindow::updatePersonList() | |
331 { | |
332 QSqlQuery query; | |
333 QString queryDir, querySort = QStringLiteral(""); | |
334 | |
335 if (peopleSortOrder == Qt::AscendingOrder) | |
336 queryDir = QStringLiteral("ASC"); | |
337 else | |
338 queryDir = QStringLiteral("DESC"); | |
339 | |
340 switch (peopleSortIndex) | |
341 { | |
342 case 1: | |
343 case 2: | |
344 querySort = QStringLiteral(" ORDER BY last_name ") + queryDir + QStringLiteral(",first_name ") + queryDir; | |
345 break; | |
346 | |
347 case 3: | |
348 querySort = QStringLiteral(" ORDER BY balance ") + queryDir; | |
349 break; | |
350 | |
351 case 4: | |
352 querySort = QStringLiteral(" ORDER BY updated ") + queryDir; | |
353 break; | |
354 } | |
355 | |
356 if (peopleFilter != "") | |
357 { | |
358 QString tmp = "%"+ peopleFilter +"%"; | |
359 query.prepare(query_Person +" WHERE first_name LIKE ? OR last_name LIKE ?" + querySort); | |
360 | |
361 query.addBindValue(tmp); | |
362 query.addBindValue(tmp); | |
363 } | |
364 else | |
365 { | |
366 query.prepare(query_Person + querySort); | |
367 } | |
368 | |
369 checkAndReportSQLError("updatePersonList() before exec", query.lastError()); | |
370 query.exec(); | |
371 checkAndReportSQLError("updatePersonList() after exec", query.lastError()); | |
372 | |
373 model_People->setQuery(query); | |
374 | |
375 model_People->setHeaderData(0, Qt::Horizontal, "ID"); | |
376 model_People->setHeaderData(1, Qt::Horizontal, "Sukunimi"); | |
377 model_People->setHeaderData(2, Qt::Horizontal, "Etunimi"); | |
378 model_People->setHeaderData(3, Qt::Horizontal, "Tase"); | |
379 model_People->setHeaderData(4, Qt::Horizontal, "Muutettu"); | |
380 } | |
381 | |
382 | |
383 void SyntilistaMainWindow::on_edit_PersonFilter_textChanged(const QString &str) | |
384 { | |
385 peopleFilter = cleanupStr(str); | |
386 updatePersonList(); | |
387 } | |
388 | |
389 | |
390 void SyntilistaMainWindow::on_button_XXX_clicked() | |
391 { | |
392 // printf("XXX-namiskaa painettu!\n"); | |
393 } | |
394 | |
395 | |
396 bool SyntilistaMainWindow::addTransaction(bool debt, double value) | |
397 { | |
398 if (personID <= 0) | |
399 return false; | |
400 | |
401 QSqlQuery person; | |
402 person.prepare("SELECT * FROM people WHERE id=?"); | |
403 person.addBindValue(personID); | |
404 person.exec(); | |
405 person.next(); | |
406 | |
407 if (value != 0) | |
408 { | |
409 QSqlQuery query; | |
410 query.prepare("INSERT INTO transactions (person,value,added) VALUES (?,?,?)"); | |
411 query.addBindValue(personID); | |
412 query.addBindValue(debt ? -value : value); | |
413 query.addBindValue(QDateTime::currentDateTimeUtc()); | |
414 query.exec(); | |
415 checkAndReportSQLError("addTransaction()", query.lastError()); | |
416 | |
417 query.prepare("UPDATE people SET updated=? WHERE id=?"); | |
418 query.addBindValue(QDateTime::currentDateTimeUtc()); | |
419 query.addBindValue(personID); | |
420 query.exec(); | |
421 checkAndReportSQLError("addTransaction update timestamp", query.lastError()); | |
422 | |
423 QSqlDatabase::database().commit(); | |
424 | |
425 ui->edit_Amount->clear(); | |
426 updatePersonData(personID); | |
427 | |
428 QString str; | |
429 if (debt) | |
430 { | |
431 str = tr("Lisättiin velkaa %1 EUR henkilölle '%2 %3' (#%4)."). | |
432 arg(value, 1, 'f', 2). | |
433 arg(person.value(1).toString()). | |
434 arg(person.value(2).toString()). | |
435 arg(person.value(0).toInt()); | |
436 } | |
437 else | |
438 { | |
439 str = tr("Vähennettiin velkaa %1 EUR henkilöltä '%2 %3' (#%4)."). | |
440 arg(value, 1, 'f', 2). | |
441 arg(person.value(1).toString()). | |
442 arg(person.value(2).toString()). | |
443 arg(person.value(0).toInt()); | |
444 } | |
445 | |
446 | |
447 statusMsg(str); | |
448 return true; | |
449 } | |
450 else | |
451 { | |
452 QString tmp = (debt ? "lisätty" : "vähennetty"); | |
453 statusMsg("Velkaa ei "+ tmp +" koska summaa ei määritetty."); | |
454 return false; | |
455 } | |
456 } | |
457 | |
458 | |
459 void SyntilistaMainWindow::on_button_AddDebt_clicked() | |
460 { | |
461 addTransaction(true, moneyStrToValue(ui->edit_Amount->text())); | |
462 } | |
463 | |
464 | |
465 void SyntilistaMainWindow::on_button_SubDebt_clicked() | |
466 { | |
467 addTransaction(false, moneyStrToValue(ui->edit_Amount->text())); | |
468 } | |
469 | |
470 | |
471 // | |
472 // Edit person dialog | |
473 // | |
474 EditPerson::EditPerson(QWidget *parent) : | |
475 QDialog(parent), | |
476 ui(new Ui::EditPerson) | |
477 { | |
478 ui->setupUi(this); | |
479 | |
480 setModal(true); | |
481 setAttribute(Qt::WA_DeleteOnClose); | |
482 show(); | |
483 activateWindow(); | |
484 raise(); | |
485 setFocus(); | |
486 | |
487 model_Transactions = new TransactionSQLModel(); | |
488 ui->tableview_Transactions->setModel(model_Transactions); | |
489 ui->tableview_Transactions->setItemDelegate(new QSqlRelationalDelegate(ui->tableview_Transactions)); | |
490 ui->tableview_Transactions->verticalHeader()->setVisible(false); | |
491 ui->tableview_Transactions->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); | |
492 | |
493 validateForm(); | |
494 } | |
495 | |
496 | |
497 EditPerson::~EditPerson() | |
498 { | |
499 delete ui; | |
500 delete model_Transactions; | |
501 } | |
502 | |
503 | |
504 void EditPerson::statusMsg(const QString &msg) | |
505 { | |
506 dynamic_cast<SyntilistaMainWindow *>(parent())->statusMsg(msg); | |
507 } | |
508 | |
509 | |
510 bool EditPerson::validateForm(PersonInfo &info) | |
511 { | |
512 info.firstName = cleanupStr(ui->edit_FirstName->text()); | |
513 info.lastName = cleanupStr(ui->edit_LastName->text()); | |
514 | |
515 ui->edit_FirstName->setStyleSheet(info.firstName == "" ? "background-color: red;" : NULL); | |
516 ui->edit_LastName->setStyleSheet(info.lastName == "" ? "background-color: red;" : NULL); | |
517 | |
518 return info.firstName != "" && info.lastName != ""; | |
519 } | |
520 | |
521 | |
522 bool EditPerson::validateForm() | |
523 { | |
524 PersonInfo info; | |
525 return validateForm(info); | |
526 } | |
527 | |
528 | |
529 void EditPerson::on_button_Cancel_clicked() | |
530 { | |
531 close(); | |
532 } | |
533 | |
534 | |
535 void EditPerson::on_button_OK_clicked() | |
536 { | |
537 PersonInfo info; | |
538 info.id = personID; | |
539 info.extraInfo = ui->textedit_ExtraInfo->document()->toPlainText(); | |
540 | |
541 if (!validateForm(info)) | |
542 return; | |
543 | |
544 if (info.id >= 0) | |
545 { | |
546 QSqlQuery person; | |
547 person.prepare("SELECT * FROM people WHERE id <> ? AND first_name=? AND last_name=?"); | |
548 person.addBindValue(info.id); | |
549 person.addBindValue(info.firstName); | |
550 person.addBindValue(info.lastName); | |
551 person.exec(); | |
552 | |
553 checkAndReportSQLError("SELECT check for existing person by same name (UPDATE)", person.lastError()); | |
554 | |
555 if (person.next()) | |
556 { | |
557 statusMsg(tr("Ei pysty! Samalla nimellä on jo henkilö!")); | |
558 return; | |
559 } | |
560 | |
561 dynamic_cast<SyntilistaMainWindow *>(parent())->model_People->updatePerson(QModelIndex(), info); | |
562 | |
563 statusMsg(tr("Päivitettiin henkilö '%1 %2' (#%3)."). | |
564 arg(info.firstName).arg(info.lastName).arg(info.id)); | |
565 } | |
566 else | |
567 { | |
568 QSqlQuery person; | |
569 person.prepare("SELECT * FROM people WHERE first_name=? AND last_name=?"); | |
570 person.addBindValue(info.firstName); | |
571 person.addBindValue(info.lastName); | |
572 person.exec(); | |
573 | |
574 checkAndReportSQLError("SELECT check for existing person by same name (ADD)", person.lastError()); | |
575 | |
576 if (person.next()) | |
577 { | |
578 statusMsg(tr("Ei pysty! Samalla nimellä on jo henkilö!")); | |
579 return; | |
580 } | |
581 | |
582 dynamic_cast<SyntilistaMainWindow *>(parent())->model_People->addPerson(info); | |
583 dynamic_cast<SyntilistaMainWindow *>(parent())->updatePersonList(); | |
584 | |
585 statusMsg(tr("Lisättiin uusi henkilö '%1 %2'."). | |
586 arg(info.firstName).arg(info.lastName)); | |
587 } | |
588 | |
589 close(); | |
590 } | |
591 | |
592 | |
593 void EditPerson::on_edit_FirstName_textChanged(const QString &arg1) | |
594 { | |
595 (void) arg1; | |
596 validateForm(); | |
597 } | |
598 | |
599 | |
600 void EditPerson::on_edit_LastName_textChanged(const QString &arg1) | |
601 { | |
602 (void) arg1; | |
603 validateForm(); | |
604 } | |
605 | |
606 | |
607 void EditPerson::clearForm() | |
608 { | |
609 ui->edit_FirstName->clear(); | |
610 ui->edit_LastName->clear(); | |
611 ui->textedit_ExtraInfo->document()->clear(); | |
612 ui->edit_FirstName->setFocus(); | |
613 } | |
614 | |
615 | |
616 void EditPerson::setPerson(qint64 id) | |
617 { | |
618 personID = id; | |
619 | |
620 if (id >= 0) | |
621 { | |
622 QSqlQuery person; | |
623 person.prepare("SELECT * FROM people WHERE id=?"); | |
624 person.addBindValue(id); | |
625 person.exec(); | |
626 checkAndReportSQLError("SELECT in EditPerson::setPerson()", person.lastError()); | |
627 | |
628 if (!person.next()) | |
629 { | |
630 statusMsg(tr("ERROR! No person with ID #%1").arg(id)); | |
631 } | |
632 else | |
633 { | |
634 ui->edit_FirstName->setText(person.value(1).toString()); | |
635 ui->edit_LastName->setText(person.value(2).toString()); | |
636 ui->textedit_ExtraInfo->document()->setPlainText(person.value(3).toString()); | |
637 | |
638 QSqlQuery query; | |
639 query.prepare("SELECT id,value,added FROM transactions WHERE person=? ORDER BY added DESC"); | |
640 query.addBindValue(id); | |
641 query.exec(); | |
642 checkAndReportSQLError("SELECT transactions for tableview_Transactions", query.lastError()); | |
643 | |
644 model_Transactions->setQuery(query); | |
645 | |
646 model_Transactions->setHeaderData(0, Qt::Horizontal, "ID"); | |
647 model_Transactions->setHeaderData(1, Qt::Horizontal, "Summa"); | |
648 model_Transactions->setHeaderData(2, Qt::Horizontal, "Aika"); | |
649 | |
650 ui->tableview_Transactions->setModel(model_Transactions); | |
651 ui->tableview_Transactions->setColumnHidden(0, true); | |
652 | |
653 return; // Ugly | |
654 } | |
655 } | |
656 | |
657 // In case of id < 0 or errors .. | |
658 clearForm(); | |
659 ui->tableview_Transactions->setModel(NULL); | |
660 } | |
661 | |
662 | |
663 // | |
664 // Custom SQL models | |
665 // | |
666 PersonSQLModel::PersonSQLModel(QObject *parent) : QSqlQueryModel(parent) | |
667 { | |
668 } | |
669 | |
670 | |
671 QVariant PersonSQLModel::data(const QModelIndex &index, int role) const | |
672 { | |
673 QVariant value = QSqlQueryModel::data(index, role); | |
674 | |
675 if (value.isValid() && role == Qt::DisplayRole) | |
676 { | |
677 switch (index.column()) | |
678 { | |
679 case 3: | |
680 return moneyValueToStr(value.toDouble()); | |
681 | |
682 case 4: | |
683 return dateTimeToStr(value.toDateTime()); | |
684 } | |
685 } | |
686 | |
687 if (index.column() == 3 && role == Qt::ForegroundRole) | |
688 { | |
689 double val = QSqlQueryModel::data(index, Qt::DisplayRole).toDouble(); | |
690 if (val < 0) | |
691 return QVariant::fromValue(QColor(Qt::red)); | |
692 else | |
693 return QVariant::fromValue(QColor(Qt::green)); | |
694 } | |
695 | |
696 return value; | |
697 } | |
698 | |
699 | |
700 void PersonSQLModel::updatePerson(const QModelIndex &item, const PersonInfo &person) | |
701 { | |
702 QSqlQuery query; | |
703 query.prepare("UPDATE people SET first_name=?,last_name=?,extra_info=?,updated=? WHERE id=?"); | |
704 query.addBindValue(person.firstName); | |
705 query.addBindValue(person.lastName); | |
706 query.addBindValue(person.extraInfo); | |
707 query.addBindValue(QDateTime::currentDateTimeUtc()); | |
708 query.addBindValue(person.id); | |
709 query.exec(); | |
710 | |
711 checkAndReportSQLError("PersonSQLModel::updatePerson()", query.lastError()); | |
712 QSqlDatabase::database().commit(); | |
713 | |
714 updateModel(); | |
715 } | |
716 | |
717 | |
718 void PersonSQLModel::addPerson(const PersonInfo &person) | |
719 { | |
720 // beginInsertRows(QModelIndex(), rowCount(), rowCount()); | |
721 | |
722 QSqlQuery np; | |
723 np.prepare("INSERT INTO people (first_name,last_name,extra_info,added,updated) VALUES (?,?,?,?,?)"); | |
724 np.addBindValue(person.firstName); | |
725 np.addBindValue(person.lastName); | |
726 np.addBindValue(person.extraInfo); | |
727 np.addBindValue(QDateTime::currentDateTimeUtc()); | |
728 np.addBindValue(QDateTime::currentDateTimeUtc()); | |
729 np.exec(); | |
730 | |
731 checkAndReportSQLError("PersonSQLModel::addPerson()", np.lastError()); | |
732 QSqlDatabase::database().commit(); | |
733 | |
734 // endInsertRows(); | |
735 updateModel(); | |
736 } | |
737 | |
738 | |
739 void PersonSQLModel::updateModel() | |
740 { | |
741 printf("PersonSQLModel::updateModelInfo()\n"); | |
742 query().exec(); | |
743 emit dataChanged(index(0, 0), index(rowCount(), columnCount())); | |
744 } | |
745 | |
746 | |
747 TransactionSQLModel::TransactionSQLModel(QObject *parent) : QSqlQueryModel(parent) | |
748 { | |
749 } | |
750 | |
751 | |
752 QVariant TransactionSQLModel::data(const QModelIndex &index, int role) const | |
753 { | |
754 QVariant value = QSqlQueryModel::data(index, role); | |
755 | |
756 if (value.isValid() && role == Qt::DisplayRole) | |
757 { | |
758 switch (index.column()) | |
759 { | |
760 case 1: | |
761 return moneyValueToStr(value.toDouble()); | |
762 | |
763 case 2: | |
764 return dateTimeToStr(value.toDateTime()); | |
765 } | |
766 } | |
767 | |
768 if (index.column() == 1 && role == Qt::ForegroundRole) | |
769 { | |
770 double val = QSqlQueryModel::data(index, Qt::DisplayRole).toDouble(); | |
771 if (val < 0) | |
772 return QVariant::fromValue(QColor(Qt::red)); | |
773 else | |
774 return QVariant::fromValue(QColor(Qt::green)); | |
775 } | |
776 | |
777 return value; | |
778 } | |
779 | |
780 | |
781 void TransactionSQLModel::updateModel() | |
782 { | |
783 printf("TransactionSQLModel::updateModelInfo()\n"); | |
784 query().exec(); | |
785 emit dataChanged(QModelIndex(), QModelIndex()); | |
786 } |