1 |
c137512e
|
Oto Šťáva
|
#include "dbbrowser.h"
|
2 |
|
|
#include "ui_dbbrowser.h"
|
3 |
|
|
#include "infodialog.h"
|
4 |
|
|
#include "../cv_stroj_3d/curvedialog.h"
|
5 |
|
|
|
6 |
|
|
#include <QLabel>
|
7 |
|
|
#include <QSqlQueryModel>
|
8 |
|
|
#include <QDate>
|
9 |
|
|
#include <QIntValidator>
|
10 |
|
|
#include <QList>
|
11 |
|
|
#include <QFile>
|
12 |
|
|
#include <QFileDialog>
|
13 |
|
|
#include <QTextStream>
|
14 |
|
|
|
15 |
|
|
#define PATIENTS_TAB 0
|
16 |
|
|
#define INDICATIONS_TAB 1
|
17 |
|
|
#define RESULTS_TAB 2
|
18 |
|
|
|
19 |
|
|
//! Konstruktor.
|
20 |
|
|
/*!
|
21 |
|
|
V kostruktoru se inicializuje uživatelské rozhraní a připojení k databázi
|
22 |
|
|
*/
|
23 |
|
|
dbBrowser::dbBrowser(QWidget *parent) :
|
24 |
|
|
QMainWindow(parent),
|
25 |
|
|
ui(new Ui::dbBrowser)
|
26 |
|
|
{
|
27 |
|
|
ui->setupUi(this);
|
28 |
|
|
db = new dbAccess();
|
29 |
|
|
|
30 |
|
|
dbConnected = db->connect("localhost", "embitron", "embitron", 5432, "Cviceni");
|
31 |
|
|
|
32 |
|
|
model = new QSqlQueryModel;
|
33 |
|
|
|
34 |
|
|
connect(ui->exitBtn, SIGNAL(clicked()), qApp, SLOT(quit()));
|
35 |
|
|
connect(ui->tabWidget, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int)));
|
36 |
|
|
connect(ui->addPatientBtn, SIGNAL(clicked()), this, SLOT(addPatientClicked()));
|
37 |
|
|
connect(ui->addIndicationBtn, SIGNAL(clicked()), this, SLOT(addIndicationClicked()));
|
38 |
|
|
|
39 |
|
|
/*connect(ui->resultBtn, SIGNAL(clicked()), this, SLOT(setResult()));*/
|
40 |
|
|
connect(ui->getResultsBtn, SIGNAL(clicked()), this, SLOT(getResult()));
|
41 |
|
|
connect(ui->saveResultsBtn, SIGNAL(clicked()), this, SLOT(saveResults()));
|
42 |
|
|
|
43 |
|
|
connect(ui->curveSelectBtn, SIGNAL(clicked()), this, SLOT(curveSelect()));
|
44 |
|
|
|
45 |
|
|
statusBarText = new QLabel;
|
46 |
|
|
statusBarText->setFixedSize(120,30);
|
47 |
|
|
QFont font;
|
48 |
|
|
font.setPixelSize(14);
|
49 |
|
|
statusBarText->setFont(font);
|
50 |
|
|
statusBarText->setAlignment(Qt::AlignCenter);
|
51 |
|
|
if (!dbConnected) {
|
52 |
|
|
statusBarText->setText(tr("DB not connected"));
|
53 |
|
|
statusBarText->setStyleSheet("background-color: rgb(255,0,0)");
|
54 |
|
|
} else {
|
55 |
|
|
statusBarText->setText(tr("DB connected"));
|
56 |
|
|
statusBarText->setStyleSheet("background-color: rgb(0,255,0)");
|
57 |
|
|
}
|
58 |
|
|
statusBar()->addPermanentWidget(statusBarText);
|
59 |
|
|
|
60 |
|
|
ui->tabWidget->setCurrentIndex(0);
|
61 |
|
|
ui->usersTableView->setSelectionMode(QAbstractItemView::SingleSelection);
|
62 |
|
|
ui->usersTableView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
63 |
|
|
ui->indicationsTableView->setSelectionMode(QAbstractItemView::SingleSelection);
|
64 |
|
|
ui->indicationsTableView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
65 |
|
|
|
66 |
|
|
db->getPatientsQueryModel(model);
|
67 |
|
|
ui->usersTableView->setModel(model);
|
68 |
|
|
ui->usersTableView->horizontalHeader()->resizeSections(QHeaderView::Stretch);
|
69 |
|
|
|
70 |
|
|
QStringList pNames;
|
71 |
|
|
QList<int> pId;
|
72 |
|
|
ui->patientNameCombo->clear();
|
73 |
|
|
ui->patientNameCombo->addItem(tr("---ALL---"), QVariant(0));
|
74 |
|
|
if (db->getAllPatientsName(&pId, &pNames)) {
|
75 |
|
|
for(int i=0; i<pId.size();i++) {
|
76 |
|
|
ui->patientNameCombo->addItem(pNames.at(i), QVariant(pId.at(i)));
|
77 |
|
|
}
|
78 |
|
|
}
|
79 |
|
|
ui->indNameCombo->clear();
|
80 |
|
|
ui->indNameCombo->addItem(tr("---ALL---"), QVariant(0));
|
81 |
|
|
ui->indNameCombo2->clear();
|
82 |
|
|
ui->indNameCombo2->addItem(tr("---ALL---"), QVariant(0));
|
83 |
|
|
pId.clear();pNames.clear();
|
84 |
|
|
if (db->getAllIndicationsName(&pId, &pNames)) {
|
85 |
|
|
for(int i=0; i<pId.size();i++) {
|
86 |
|
|
ui->indNameCombo->addItem(pNames.at(i), QVariant(pId.at(i)));
|
87 |
|
|
ui->indNameCombo2->addItem(pNames.at(i), QVariant(pId.at(i)));
|
88 |
|
|
}
|
89 |
|
|
}
|
90 |
|
|
|
91 |
|
|
QIntValidator *iv = new QIntValidator(0,999, this);
|
92 |
|
|
ui->timeEdit->setValidator(iv);
|
93 |
|
|
|
94 |
|
|
cName = "";
|
95 |
|
|
|
96 |
|
|
qsrand(QDateTime::currentMSecsSinceEpoch() / 1000);
|
97 |
|
|
}
|
98 |
|
|
|
99 |
|
|
//! Destruktor.
|
100 |
|
|
/*!
|
101 |
|
|
Slouží pro zrušení vytvořených objektů
|
102 |
|
|
*/
|
103 |
|
|
dbBrowser::~dbBrowser()
|
104 |
|
|
{
|
105 |
|
|
delete db;
|
106 |
|
|
delete ui;
|
107 |
|
|
}
|
108 |
|
|
|
109 |
|
|
//! Změna jazyka dialogu
|
110 |
|
|
/*!
|
111 |
|
|
Pokud se změní jazyk aplikace, funkce změní text v dialogu, aby odpovídal
|
112 |
|
|
nastavenému jazyku
|
113 |
|
|
\param *e Ukazatel na objekt, který obsahuje posílanou událost
|
114 |
|
|
*/
|
115 |
|
|
void dbBrowser::changeEvent(QEvent *e)
|
116 |
|
|
{
|
117 |
|
|
QMainWindow::changeEvent(e);
|
118 |
|
|
switch (e->type()) {
|
119 |
|
|
case QEvent::LanguageChange:
|
120 |
|
|
ui->retranslateUi(this);
|
121 |
|
|
break;
|
122 |
|
|
default:
|
123 |
|
|
break;
|
124 |
|
|
}
|
125 |
|
|
}
|
126 |
|
|
|
127 |
|
|
//! Info o změně zobrazované části dialogu
|
128 |
|
|
/*!
|
129 |
|
|
Informace o změně zobrazované části dialogu. Funkce připraví nová data,
|
130 |
|
|
aby zobrazované hodnoty odpovídaly požadavku.
|
131 |
|
|
\param index Pořadové číslo žádané časti dialogu, která se má zobrazit
|
132 |
|
|
*/
|
133 |
|
|
void dbBrowser::tabChanged(int index)
|
134 |
|
|
{
|
135 |
|
|
switch(index) {
|
136 |
|
|
case PATIENTS_TAB:
|
137 |
|
|
db->getPatientsQueryModel(model);
|
138 |
|
|
ui->usersTableView->setModel(model);
|
139 |
|
|
ui->usersTableView->horizontalHeader()->resizeSections(QHeaderView::Stretch);
|
140 |
|
|
break;
|
141 |
|
|
case INDICATIONS_TAB:
|
142 |
|
|
db->getIndicationsQueryModel(model);
|
143 |
|
|
ui->indicationsTableView->setModel(model);
|
144 |
|
|
ui->indicationsTableView->horizontalHeader()->resizeSections(QHeaderView::Stretch);
|
145 |
|
|
break;
|
146 |
|
|
case RESULTS_TAB:
|
147 |
|
|
getResult();
|
148 |
|
|
break;
|
149 |
|
|
}
|
150 |
|
|
}
|
151 |
|
|
|
152 |
|
|
//! Přidání pacienta do databáze
|
153 |
|
|
/*!
|
154 |
|
|
Funkce vyčte hodnoty z editačního okna, a tyto hodnoty uloží do databáze
|
155 |
|
|
jako nového pacienta
|
156 |
|
|
*/
|
157 |
|
|
void dbBrowser::addPatientClicked()
|
158 |
|
|
{
|
159 |
|
|
infoDialog dlg;
|
160 |
|
|
auto name = ui->nameEdit->text();
|
161 |
|
|
auto surname = ui->surnameEdit->text();
|
162 |
|
|
auto idNo = ui->idnumberEdit->text();
|
163 |
|
|
auto indId = ui->indNameCombo2->currentData().toString();
|
164 |
|
|
|
165 |
|
|
if (name.isEmpty() || surname.isEmpty() || idNo.isEmpty()) {
|
166 |
|
|
// err, one of items is empty
|
167 |
|
|
dlg.setInfoText(tr("Error"), tr("One item is empty. Please fill all items."));
|
168 |
|
|
dlg.exec();
|
169 |
|
|
return;
|
170 |
|
|
}
|
171 |
|
|
|
172 |
|
|
auto nRet = db->addNewPatient(name, surname, ui->birthdateEdit->date(), idNo, indId);
|
173 |
|
|
|
174 |
|
|
if (nRet != ALL_OK) {
|
175 |
|
|
dlg.setInfoText(tr("Error"), tr("Could not insert new patient data"));
|
176 |
|
|
} else {
|
177 |
|
|
dlg.setInfoText(tr("Success"), tr("OK. Patient data inserted succesfully"));
|
178 |
|
|
db->getPatientsQueryModel(model);
|
179 |
|
|
ui->usersTableView->setModel(model);
|
180 |
|
|
ui->usersTableView->horizontalHeader()->resizeSections(QHeaderView::Stretch);
|
181 |
|
|
|
182 |
|
|
QStringList pNames;
|
183 |
|
|
QList<int> pId;
|
184 |
|
|
ui->patientNameCombo->clear();
|
185 |
|
|
ui->patientNameCombo->addItem(tr("---ALL---"), QVariant(0));
|
186 |
|
|
if (db->getAllPatientsName(&pId, &pNames)) {
|
187 |
|
|
for(int i=0; i<pId.size();i++) {
|
188 |
|
|
ui->patientNameCombo->addItem(pNames.at(i), QVariant(pId.at(i)));
|
189 |
|
|
}
|
190 |
|
|
}
|
191 |
|
|
}
|
192 |
|
|
dlg.exec();
|
193 |
|
|
}
|
194 |
|
|
|
195 |
|
|
//! Přidání indikace do databáze
|
196 |
|
|
/*!
|
197 |
|
|
Funkce vyčte hodnoty z editačního okna, a tyto hodnoty uloží do databáze
|
198 |
|
|
jako novou indikaci
|
199 |
|
|
*/
|
200 |
|
|
void dbBrowser::addIndicationClicked()
|
201 |
|
|
{
|
202 |
|
|
infoDialog dlg;
|
203 |
|
|
auto name = ui->indNameEdit->text();
|
204 |
|
|
auto time = ui->timeEdit->text().toInt();
|
205 |
|
|
|
206 |
|
|
if (name.isEmpty() || cName.isEmpty()) {
|
207 |
|
|
// err, one of items is empty
|
208 |
|
|
dlg.setInfoText(tr("Error"), tr("One item is empty. Please fill all items."));
|
209 |
|
|
dlg.exec();
|
210 |
|
|
return;
|
211 |
|
|
}
|
212 |
|
|
|
213 |
|
|
auto nRet = db->addNewIndication(name, ui->descriptionEdit->text(), cName, time);
|
214 |
|
|
|
215 |
|
|
if (nRet != ALL_OK) {
|
216 |
|
|
dlg.setInfoText(tr("Error"), tr("Could not insert new indication data"));
|
217 |
|
|
} else {
|
218 |
|
|
dlg.setInfoText(tr("Success"), tr("OK. Indication data inserted succesfully"));
|
219 |
|
|
db->getIndicationsQueryModel(model);
|
220 |
|
|
ui->indicationsTableView->setModel(model);
|
221 |
|
|
ui->indicationsTableView->horizontalHeader()->resizeSections(QHeaderView::Stretch);
|
222 |
|
|
|
223 |
|
|
QStringList pNames;
|
224 |
|
|
QList<int> pId;
|
225 |
|
|
ui->indNameCombo->clear();
|
226 |
|
|
ui->indNameCombo->addItem(tr("---ALL---"), QVariant(0));
|
227 |
|
|
ui->indNameCombo2->clear();
|
228 |
|
|
ui->indNameCombo2->addItem(tr("---ALL---"), QVariant(0));
|
229 |
|
|
pId.clear();pNames.clear();
|
230 |
|
|
if (db->getAllIndicationsName(&pId, &pNames)) {
|
231 |
|
|
for(int i=0; i<pId.size();i++) {
|
232 |
|
|
ui->indNameCombo->addItem(pNames.at(i), QVariant(pId.at(i)));
|
233 |
|
|
ui->indNameCombo2->addItem(pNames.at(i), QVariant(pId.at(i)));
|
234 |
|
|
}
|
235 |
|
|
}
|
236 |
|
|
}
|
237 |
|
|
dlg.exec();
|
238 |
|
|
}
|
239 |
|
|
|
240 |
|
|
//! Výběr křivky pro novou indikaci
|
241 |
|
|
/*!
|
242 |
|
|
Funkce zobrazí dialog, který slouží k výběru křiky, kterou má pacient s
|
243 |
|
|
vytvářenou indikací cvičit.
|
244 |
|
|
*/
|
245 |
|
|
void dbBrowser::curveSelect()
|
246 |
|
|
{
|
247 |
|
|
curveDialog dlg;
|
248 |
|
|
int actCurveType, actCurveAngle, actCurveRot, pronSupVal;
|
249 |
|
|
|
250 |
|
|
if (dlg.exec() == QDialog::Accepted) {
|
251 |
|
|
dlg.getCurve(&actCurveType, &actCurveAngle, &actCurveRot, &pronSupVal);
|
252 |
|
|
cName = QString::number(actCurveType) + "_" + QString::number(actCurveAngle) +
|
253 |
|
|
"_" + QString::number(actCurveRot) + "_" + QString::number(pronSupVal);
|
254 |
|
|
switch(actCurveType) {
|
255 |
|
|
case CURVE_CIRCLE:
|
256 |
|
|
ui->curveSelectBtn->setText(tr("Circle"));
|
257 |
|
|
break;
|
258 |
|
|
case CURVE_ELLIPSE:
|
259 |
|
|
ui->curveSelectBtn->setText(tr("Ellipse"));
|
260 |
|
|
break;
|
261 |
|
|
case CURVE_KARD:
|
262 |
|
|
ui->curveSelectBtn->setText(tr("Cardiotide"));
|
263 |
|
|
break;
|
264 |
|
|
case CURVE_LEMN:
|
265 |
|
|
ui->curveSelectBtn->setText(tr("Lemniscate"));
|
266 |
|
|
break;
|
267 |
|
|
case CURVE_LINE:
|
268 |
|
|
ui->curveSelectBtn->setText(tr("Line"));
|
269 |
|
|
break;
|
270 |
|
|
case CURVE_NONE:
|
271 |
|
|
ui->curveSelectBtn->setText(tr("None"));
|
272 |
|
|
break;
|
273 |
|
|
case CURVE_EXTERN:
|
274 |
|
|
ui->curveSelectBtn->setText(tr("External"));
|
275 |
|
|
break;
|
276 |
|
|
default:
|
277 |
|
|
ui->curveSelectBtn->setText(tr(""));
|
278 |
|
|
}
|
279 |
|
|
}
|
280 |
|
|
}
|
281 |
|
|
|
282 |
|
|
//! Uložení výsledku
|
283 |
|
|
/*!
|
284 |
|
|
Pouze testovací funkce. Funkce je použitá při testování ukládání/zobrazování výsledků cvičení.
|
285 |
|
|
*/
|
286 |
|
|
void dbBrowser::setResult()
|
287 |
|
|
{
|
288 |
|
|
int res_count, cycles;
|
289 |
|
|
QStringList arr;
|
290 |
|
|
QList<int> intArr;
|
291 |
|
|
QString resVals, resultList;
|
292 |
|
|
infoDialog dlg;
|
293 |
|
|
int vals = qrand() % 101 + 200;
|
294 |
|
|
|
295 |
|
|
/*for(int i=0; i<vals; i++)
|
296 |
|
|
intArr.append(qrand()%30+40);
|
297 |
|
|
db->addResult(4, 2, 1,intArr);*/
|
298 |
|
|
db->getResultsNumber(2,2, &res_count);
|
299 |
|
|
while(db->getNextResult(&cycles, &resultList)) {
|
300 |
|
|
resultList.chop(1);resultList.remove(0,1); //remove '{' and '}' from result string
|
301 |
|
|
arr = resultList.split(",");
|
302 |
|
|
resVals = "Cycles: " + QString::number(cycles);
|
303 |
|
|
for(auto val: arr) {
|
304 |
|
|
resVals += " ," + val;
|
305 |
|
|
}
|
306 |
|
|
dlg.setInfoText("2,2", resVals);
|
307 |
|
|
dlg.exec();
|
308 |
|
|
}
|
309 |
|
|
db->getResultsNumber(2,0, &res_count);
|
310 |
|
|
while(db->getNextResult(&cycles, &resultList)) {
|
311 |
|
|
resultList.chop(1);resultList.remove(0,1); //remove '{' and '}' from result string
|
312 |
|
|
arr = resultList.split(",");
|
313 |
|
|
resVals = "Cycles: " + QString::number(cycles);
|
314 |
|
|
for(auto val: arr) {
|
315 |
|
|
resVals += " ," + val;
|
316 |
|
|
}
|
317 |
|
|
dlg.setInfoText("2,0", resVals);
|
318 |
|
|
dlg.exec();
|
319 |
|
|
}
|
320 |
|
|
db->getResultsNumber(0,1, &res_count);
|
321 |
|
|
while(db->getNextResult(&cycles, &resultList)) {
|
322 |
|
|
resultList.chop(1);resultList.remove(0,1); //remove '{' and '}' from result string
|
323 |
|
|
arr = resultList.split(",");
|
324 |
|
|
resVals = "Cycles: " + QString::number(cycles);
|
325 |
|
|
for(auto val: arr) {
|
326 |
|
|
resVals += " ," + val;
|
327 |
|
|
}
|
328 |
|
|
dlg.setInfoText("0,1", resVals);
|
329 |
|
|
dlg.exec();
|
330 |
|
|
}
|
331 |
|
|
db->getResultsNumber(0,0, &res_count);
|
332 |
|
|
while(db->getNextResult(&cycles, &resultList)) {
|
333 |
|
|
resultList.chop(1);resultList.remove(0,1); //remove '{' and '}' from result string
|
334 |
|
|
arr = resultList.split(",");
|
335 |
|
|
resVals = "Cycles: " + QString::number(cycles);
|
336 |
|
|
for(auto val: arr) {
|
337 |
|
|
resVals += " ," + val;
|
338 |
|
|
}
|
339 |
|
|
dlg.setInfoText("0,0", resVals);
|
340 |
|
|
dlg.exec();
|
341 |
|
|
}
|
342 |
|
|
}
|
343 |
|
|
|
344 |
|
|
//! Získání výsledků
|
345 |
|
|
/*!
|
346 |
|
|
Funkce je použitá při testování zobrazování výsledků cvičení. Funkce vyčte z dialogu
|
347 |
|
|
parametry, podle kterých je možno výsledky filtrovat.
|
348 |
|
|
*/
|
349 |
|
|
void dbBrowser::getResult()
|
350 |
|
|
{
|
351 |
|
|
int pId = ui->patientNameCombo->currentData().toInt();
|
352 |
|
|
int indId = ui->indNameCombo->currentData().toInt();
|
353 |
|
|
|
354 |
|
|
db->getResultsQueryModel(model, pId, indId);
|
355 |
|
|
ui->resultsTableView->setModel(model);
|
356 |
|
|
ui->resultsTableView->horizontalHeader()->resizeSections(QHeaderView::Stretch);
|
357 |
|
|
}
|
358 |
|
|
|
359 |
|
|
//! Uložení výsledků
|
360 |
|
|
/*!
|
361 |
|
|
Funkce je použitá pro uložení zobrazených výsledků cvičení. Uložený soubor
|
362 |
|
|
je ve formátu CSV.
|
363 |
|
|
*/
|
364 |
|
|
void dbBrowser::saveResults()
|
365 |
|
|
{
|
366 |
|
|
int size = ui->resultsTableView->model()->rowCount(),i;
|
367 |
|
|
QString res, date;
|
368 |
|
|
int pId, indId, cycles, series, resNo;
|
369 |
|
|
QString filename = QFileDialog::getSaveFileName(this, tr("Save CSV"), "", tr("CSV files (.csv)"));
|
370 |
|
|
if (!filename.endsWith("csv"))
|
371 |
|
|
filename += ".csv";
|
372 |
|
|
QFile data(filename);
|
373 |
|
|
|
374 |
|
|
if(data.open(QFile::WriteOnly |QFile::Truncate))
|
375 |
|
|
{
|
376 |
|
|
QTextStream output(&data);
|
377 |
|
|
output << "Patient ID; Indication ID; Series; Result number; Date; Cycles count; result\n";
|
378 |
|
|
|
379 |
|
|
for(i=0;i<size;i++) {
|
380 |
|
|
pId = ui->resultsTableView->model()->index(i,0).data().toInt();
|
381 |
|
|
indId = ui->resultsTableView->model()->index(i,1).data().toInt();
|
382 |
|
|
series = ui->resultsTableView->model()->index(i,2).data().toInt();
|
383 |
|
|
resNo = ui->resultsTableView->model()->index(i,3).data().toInt();
|
384 |
|
|
date = ui->resultsTableView->model()->index(i,4).data().toString();
|
385 |
|
|
cycles = ui->resultsTableView->model()->index(i,5).data().toInt();
|
386 |
|
|
res = ui->resultsTableView->model()->index(i,6).data().toString();
|
387 |
|
|
|
388 |
|
|
//remove '{' and '}' from result string
|
389 |
|
|
if (res.contains('{'))
|
390 |
|
|
res.remove(0,1);
|
391 |
|
|
if (res.contains('}'))
|
392 |
|
|
res.chop(1);
|
393 |
|
|
res.replace(',',';');
|
394 |
|
|
output << pId << ";" << indId << ";" << series << ";" << resNo << ";" << date <<";" << cycles << ";" << res << "\n";
|
395 |
|
|
}
|
396 |
|
|
data.close();
|
397 |
|
|
}
|
398 |
|
|
}
|