00001 #ifndef PROJECTSEDITOR_H
00002 #define PROJECTSEDITOR_H
00003
00004 #include <QDebug>
00005
00006 #include "baseeditor.h"
00007 #include "database.h"
00008 #include "global.h"
00009
00013 class PrivilegeEditor : public QTableView {
00014 public:
00015 PrivilegeEditor(QWidget *parent = 0) : QTableView(parent) {
00016 setWindowTitle("Privilege Editor");
00017
00018
00019 SqlTableModel *privModel = new SqlTableModel(this, Database::staticCon());
00020 privModel->setEditStrategy(QSqlTableModel::OnFieldChange);
00021 privModel->setTable("vew_project_privileges");
00022 setModel(privModel);
00023
00024
00025 privModel->setHeaderData(privModel->record().indexOf("rls_user_name"), Qt::Horizontal, "user", Qt::DisplayRole);
00026 privModel->setHeaderData(privModel->record().indexOf("proj_name"), Qt::Horizontal, "project", Qt::DisplayRole);
00027
00028 QString ownerToolTip("<body>Shows whether the user is the owner of (i.e. has made the) the project or not. Owners have full access to the project they own. They can also grant privileges to others for the projects they own.</body>");
00029 QString readToolTip("<body>Shows whether the user can see the project and it's dependencies: the setup and sensor data.</body>");
00030 QString writeToolTip("<body>Shows whether the user can adjust the projectdependant data: the project record, setup?, add data?</body>");
00031 QString deleteToolTip("<body>Shows whether the user can delete projectdependant data, such as the setup, the sensor data, but also the project itself? = miss best alleen de owner?</body>");
00032 privModel->setHeaderData(privModel->record().indexOf("owner"), Qt::Horizontal, ownerToolTip, Qt::ToolTipRole);
00033 privModel->setHeaderData(privModel->record().indexOf("read"), Qt::Horizontal, readToolTip, Qt::ToolTipRole);
00034 privModel->setHeaderData(privModel->record().indexOf("write"), Qt::Horizontal, writeToolTip, Qt::ToolTipRole);
00035 privModel->setHeaderData(privModel->record().indexOf("delete"), Qt::Horizontal, deleteToolTip, Qt::ToolTipRole);
00036 }
00037
00038 SqlTableModel *model() const {
00039 Q_ASSERT(QTableView::model());
00040 SqlTableModel *m = dynamic_cast<SqlTableModel*>(QTableView::model());
00041 Q_ASSERT(m);
00042 return m;
00043 }
00044
00045 void hideColumn(const QString &columnName) {
00046 hideColumn(model()->record().indexOf(columnName));
00047 }
00048
00049 void hideColumn(int column) {
00050 QTableView::hideColumn(column);
00051 }
00052
00053 void select() {
00054 model()->select();
00055 }
00056 };
00057
00058 #include <QGroupBox>
00059 #include <QSpacerItem>
00060 #include <QCheckBox>
00061 #include <QLabel>
00062 #include <QLineEdit>
00063
00069 class UserEditor : public MappedBaseEditor {
00070 Q_OBJECT
00071 public:
00072 UserEditor(QWidget *parent = 0) : MappedBaseEditor(parent), privView(new PrivilegeEditor(this)) {
00073 setObjectName("UserEditor");
00074 setWindowTitle("User editor");
00075
00076
00077 setTable("tbl_users", "user_name", Qt::AscendingOrder);
00078 model()->setRowIdentifierField("user_name");
00079
00080
00081 QLabel *name = new QLabel("&Name*:", this);
00082 QLabel *pwd = new QLabel("&Password:", this);
00083 QLabel *priv = new QLabel("Project &rights:", this);
00084 QLineEdit *nameEdit = new QLineEdit(this);
00085 QLineEdit *pwdEdit = new QLineEdit(this);
00086 pwdEdit->setReadOnly(true);
00087 name->setBuddy(nameEdit);
00088 priv->setBuddy(privView);
00089 pwd->setBuddy(pwdEdit);
00090
00091
00092 QGroupBox *privBox = new QGroupBox("Privileges", this);
00093 privBox->setLayout(new QVBoxLayout());
00094 QCheckBox *isAdmin = new QCheckBox("Admin", privBox);
00095 QCheckBox *canCreateProjects = new QCheckBox("Create projects", privBox);
00096 privBox->layout()->addWidget(isAdmin);
00097 privBox->layout()->addWidget(canCreateProjects);
00098 dynamic_cast<QBoxLayout*>(privBox->layout())->addStretch(0);
00099
00100
00101 privView->hideColumn("rls_user_name");
00102
00103
00104 addWidget(name, 0, 0, 1, 1);
00105 addWidget(nameEdit, 0, 1, 1, 1, "user_name");
00106 addWidget(pwd, 1, 0, 1, 1);
00107 addWidget(pwdEdit, 1, 1, 1, 1, "password");
00108 addWidget(priv, 2, 0, 1, 2);
00109 addWidget(privView, 3, 0, 1, 2);
00110 addWidget(privBox, 0, 3, 4, 1);
00111
00112
00113 addWidgetMapping(isAdmin, "isadmin");
00114 addWidgetMapping(canCreateProjects, "cancreateproject");
00115
00116
00117 connect(nameEdit, SIGNAL(textChanged(QString)), this, SLOT(updateButtons()));
00118 connect(isAdmin, SIGNAL(toggled(bool)), this, SLOT(updateButtons()));
00119 connect(canCreateProjects, SIGNAL(toggled(bool)), this, SLOT(updateButtons()));
00120
00121
00122 select();
00123 privView->select();
00124 }
00125
00126 protected:
00127 virtual void onCurrentRecordChange(int row){
00128 MappedBaseEditor::onCurrentRecordChange(row);
00129 updatePrivilegesView();
00130 }
00131
00132 private:
00133 void updatePrivilegesView(){
00134 Q_ASSERT(model()->record().indexOf("user_name") != -1);
00135 QString user_name = model()->index(currentMapperRow(), model()->record().indexOf("user_name")).data(Qt::DisplayRole).toString();
00136 privView->model()->setFilter("rls_user_name = '" + user_name + "'");
00137 }
00138
00139 private:
00140 PrivilegeEditor *privView;
00141 };
00142
00143 #include <QTextEdit>
00144
00153 class ProjectEditor : public MappedBaseEditor {
00154 Q_OBJECT
00155 public:
00156 ProjectEditor(QWidget *parent = 0) : MappedBaseEditor(parent), privView(new PrivilegeEditor(this)) {
00157 setObjectName("ProjectEditor");
00158 setWindowTitle("Project editor");
00159
00160
00161 setTable("tbl_projects", "proj_name", Qt::AscendingOrder);
00162
00163
00164 QLabel *name = new QLabel("&Name*:", this);
00165 QLabel *desc = new QLabel("&Description*:", this);
00166 QLabel *owner = new QLabel("&Owner:", this);
00167 QLabel *priv = new QLabel("User &rights:", this);
00168 QLineEdit *nameEdit = new QLineEdit(this);
00169 QTextEdit *descEdit = new QTextEdit(this);
00170 QComboBox *ownerEdit = new QComboBox(this);
00171 name->setBuddy(nameEdit);
00172 desc->setBuddy(descEdit);
00173 owner->setBuddy(ownerEdit);
00174 priv->setBuddy(privView);
00175
00176
00177 privView->hideColumn("proj_name");
00178 privView->hideColumn("owner");
00179
00180
00181 addWidget(name, 0, 0, 1, 1);
00182 addWidget(nameEdit, 0, 1, 1, 1, "proj_name");
00183 addWidget(owner, 1, 0, 1, 1);
00184 addWidget(ownerEdit, 1, 1, 1, 1, QSqlRelation("tbl_users", "user_name", "user_name"), "rls_owner");
00185 addWidget(desc, 2, 0, 1, 2);
00186 addWidget(descEdit, 3, 0, 1, 2, "proj_desc", "plainText");
00187 addWidget(priv, 0, 2, 1, 1);
00188 addWidget(privView, 1, 2, 3, 1);
00189
00190
00191 connect(nameEdit, SIGNAL(textChanged(QString)), this, SLOT(updateButtons()));
00192 connect(descEdit, SIGNAL(textChanged()), this, SLOT(updateButtons()));
00193 connect(ownerEdit, SIGNAL(currentIndexChanged(int)), this, SLOT(updateButtons()));
00194
00195
00196 select();
00197 privView->select();
00198 }
00199
00200 protected:
00201 virtual void onCurrentRecordChange(int row){
00202 MappedBaseEditor::onCurrentRecordChange(row);
00203 updatePrivilegesView();
00204 }
00205
00206 private:
00207 void updatePrivilegesView(){
00208 Q_ASSERT(model()->record().indexOf("proj_name") != -1);
00209 QString proj_name = model()->index(currentMapperRow(), model()->record().indexOf("proj_name")).data(Qt::DisplayRole).toString();
00210 privView->model()->setFilter("proj_name = '" + proj_name + "'");
00211 }
00212
00213 private:
00214 PrivilegeEditor *privView;
00215 };
00216
00222 class LocationEditor : public MappedBaseEditor {
00223 Q_OBJECT
00224 public:
00225 LocationEditor(QWidget *parent = 0) : MappedBaseEditor(parent) {
00226 setObjectName("LocationEditor");
00227 setWindowTitle("Location editor");
00228
00229
00230 setTable("tbl_locations", "loca_country", Qt::AscendingOrder);
00231
00232
00233 QLabel *country = new QLabel("&Country*:", this);
00234 QLabel *region = new QLabel("&City*:", this);
00235 QLabel *postalCode = new QLabel("&Postal code:", this);
00236 QLabel *address = new QLabel("&Address:", this);
00237 QLabel *phone = new QLabel("Phone &number:", this);
00238 QLabel *desc = new QLabel("Decription:", this);
00239 QLineEdit *countryEdit = new QLineEdit(this);
00240 QLineEdit *regionEdit = new QLineEdit(this);
00241 QLineEdit *postalCodeEdit = new QLineEdit(this);
00242 QTextEdit *addressEdit = new QTextEdit(this);
00243 QLineEdit *phoneEdit = new QLineEdit(this);
00244 QTextEdit *descEdit = new QTextEdit(this);
00245 country->setBuddy(countryEdit);
00246 region->setBuddy(regionEdit);
00247 postalCode->setBuddy(postalCodeEdit);
00248 address->setBuddy(addressEdit);
00249 phone->setBuddy(phoneEdit);
00250 desc->setBuddy(descEdit);
00251
00252 QSizePolicy policy(addressEdit->sizePolicy());
00253 policy.setVerticalStretch(1);
00254 addressEdit->setSizePolicy(policy);
00255 policy.setVerticalStretch(2);
00256 descEdit->setSizePolicy(policy);
00257
00258
00259 addWidget(country, 0, 0, 1, 1);
00260 addWidget(countryEdit, 0, 1, 1, 1, "loca_country");
00261 addWidget(region, 1, 0, 1, 1);
00262 addWidget(regionEdit, 1, 1, 1, 1, "loca_region");
00263 addWidget(postalCode, 2, 0, 1, 1);
00264 addWidget(postalCodeEdit, 2, 1, 1, 1, "loca_postalcode");
00265 addWidget(address, 3, 0, 1, 1);
00266 addWidget(addressEdit, 3, 1, 1, 1, "loca_address", "plainText");
00267 addWidget(phone, 4, 0, 1, 1);
00268 addWidget(phoneEdit, 4, 1, 1, 1, "loca_phone");
00269 addWidget(desc, 5, 0, 1, 1);
00270 addWidget(descEdit, 5, 1, 1, 1, "loca_desc", "plainText");
00271
00272
00273 connect(countryEdit, SIGNAL(textChanged(QString)), this, SLOT(updateButtons()));
00274 connect(regionEdit, SIGNAL(textChanged(QString)), this, SLOT(updateButtons()));
00275 connect(postalCodeEdit, SIGNAL(textChanged(QString)), this, SLOT(updateButtons()));
00276 connect(addressEdit, SIGNAL(textChanged()), this, SLOT(updateButtons()));
00277 connect(phoneEdit, SIGNAL(textChanged(QString)), this, SLOT(updateButtons()));
00278 connect(descEdit, SIGNAL(textChanged()), this, SLOT(updateButtons()));
00279
00280
00281 select();
00282 }
00283 };
00284
00290 class InstallationEditor : public MappedBaseEditor {
00291 Q_OBJECT
00292 public:
00293 InstallationEditor(QWidget *parent = 0) : MappedBaseEditor(parent) {
00294 setObjectName("InstallationEditor");
00295 setWindowTitle("Installation editor");
00296
00297
00298 setTable("tbl_installations", "inst_type", Qt::AscendingOrder);
00299
00300
00301 QLabel *type = new QLabel("&Type*:", this);
00302 QLabel *desc = new QLabel("&Description*:", this);
00303 QLineEdit *typeEdit = new QLineEdit(this);
00304 QTextEdit *descEdit = new QTextEdit(this);
00305 type->setBuddy(typeEdit);
00306 desc->setBuddy(descEdit);
00307
00308
00309 addWidget(type, 0, 0, 1, 1);
00310 addWidget(typeEdit, 0, 1, 1, 1, "inst_type");
00311 addWidget(desc, 1, 0, 1, 1);
00312 addWidget(descEdit, 2, 0, 1, 2, "inst_desc", "plainText");
00313
00314
00315 connect(typeEdit, SIGNAL(textChanged(QString)), this, SLOT(updateButtons()));
00316 connect(descEdit, SIGNAL(textChanged()), this, SLOT(updateButtons()));
00317
00318
00319 select();
00320 }
00321 };
00322
00328 class UnitEditor : public MappedBaseEditor {
00329 Q_OBJECT
00330 public:
00331 UnitEditor(QWidget *parent = 0) : MappedBaseEditor(parent) {
00332 setObjectName("UnitEditor");
00333 setWindowTitle("Unit editor");
00334
00335
00336 setTable("tbl_units", "unit_name", Qt::AscendingOrder);
00337
00338
00339 QLabel *name = new QLabel("&Name*:", this);
00340 QLabel *symbol = new QLabel("&Symbol*:", this);
00341 QLineEdit *nameEdit = new QLineEdit(this);
00342 QLineEdit *symbolEdit = new QLineEdit(this);
00343 name->setBuddy(nameEdit);
00344 symbol->setBuddy(symbolEdit);
00345
00346
00347 addWidget(name, 0, 0, 1, 1);
00348 addWidget(nameEdit, 0, 1, 1, 1, "unit_name");
00349 addWidget(symbol, 1, 0, 1, 1);
00350 addWidget(symbolEdit, 1, 1, 1, 1, "unit_symbol");
00351
00352
00353 connect(nameEdit, SIGNAL(textChanged(QString)), this, SLOT(updateButtons()));
00354 connect(symbolEdit, SIGNAL(textChanged(QString)), this, SLOT(updateButtons()));
00355
00356
00357 select();
00358 }
00359 };
00360
00366 class SensorCategoryEditor : public MappedBaseEditor {
00367 Q_OBJECT
00368 public:
00369 SensorCategoryEditor(QWidget *parent = 0) : MappedBaseEditor(parent) {
00370 setObjectName("SensorCategoryEditor");
00371 setWindowTitle("Sensor category editor");
00372
00373
00374 setTable("tbl_sensor_categories", "sens_cate_name", Qt::AscendingOrder);
00375
00376
00377 QLabel *name = new QLabel("&Name*:", this);
00378 QLabel *desc = new QLabel("&Description:", this);
00379 QLineEdit *nameEdit = new QLineEdit(this);
00380 QTextEdit *descEdit = new QTextEdit(this);
00381 name->setBuddy(nameEdit);
00382 desc->setBuddy(descEdit);
00383
00384
00385 addWidget(name, 0, 0, 1, 1);
00386 addWidget(nameEdit, 0, 1, 1, 1, "sens_cate_name");
00387 addWidget(desc, 1, 0, 1, 1);
00388 addWidget(descEdit, 2, 0, 1, 2, "sens_cate_desc", "plainText");
00389
00390
00391 connect(nameEdit, SIGNAL(textChanged(QString)), this, SLOT(updateButtons()));
00392 connect(descEdit, SIGNAL(textChanged()), this, SLOT(updateButtons()));
00393
00394
00395 select();
00396 }
00397 };
00398
00399 #include <QDateTimeEdit>
00405 class SensorChannelCalibrationEditor : public MappedBaseEditor {
00406 Q_OBJECT
00407 public:
00408 SensorChannelCalibrationEditor(int sens_id, int sens_chan_nr, int positionOnId = -1 , QWidget *parent = 0)
00409 : MappedBaseEditor(parent), m_sens_id(sens_id), m_sens_chan_nr(sens_chan_nr) {
00410 setObjectName("SensorChannelCalibrationEditor");
00411
00412
00413 QSqlRecord result = Database::execStaticR(QString("SELECT su.unit_symbol AS unit_from, scu.unit_symbol AS unit_to, s.unit_id, sc.sens_chan_cali_unit_id "
00414 "FROM tbl_sensors s "
00415 "INNER JOIN tbl_sensor_channels sc USING (sens_id) "
00416 "INNER JOIN tbl_units su ON (s.unit_id = su.unit_id) "
00417 "INNER JOIN tbl_units scu ON (sc.sens_chan_cali_unit_id = scu.unit_id) "
00418 "WHERE sens_id = %1 AND sens_chan_nr = %2")
00419 .arg(QString::number(m_sens_id), QString::number(m_sens_chan_nr)));
00420 bool ok;
00421 m_sens_unit_id = result.value("unit_id").toInt(&ok);
00422 Q_ASSERT(ok);
00423 m_sens_chan_cali_unit_id = result.value("sens_chan_cali_unit_id").toInt(&ok);
00424 Q_ASSERT(ok);
00425
00426
00427 Q_ASSERT(sens_id > 0);
00428 Q_ASSERT(sens_chan_nr > 0);
00429
00430
00431 const QString sens_id_str = QString::number(sens_id);
00432 const QString sens_chan_nr_str = QString::number(sens_chan_nr);
00433
00434
00435 static const QString baseQuery("SELECT sens_type || ' [SN: ' || sens_serialnr || '] Channel #' || sens_chan_nr "
00436 "FROM tbl_sensors s INNER JOIN tbl_sensor_channels sc USING (sens_id) "
00437 "WHERE sens_id = %1 AND sens_chan_nr = %2");
00438 const QString query(baseQuery.arg(sens_id_str, sens_chan_nr_str));
00439 const QString title = Database::execStaticR(query).value(0).toString();
00440
00441
00442 setWindowTitle(QString("Calibration editor for ").append(title));
00443
00444
00445 setTable("tbl_sensor_channel_calibrations", "sens_chan_cali_timestamp", Qt::DescendingOrder, "sens_id = " + sens_id_str + " AND sens_chan_nr = " + sens_chan_nr_str);
00446
00447
00448 QLabel *timestamp = new QLabel("&Timestamp*:", this);
00449 QLabel *formula = new QLabel(QString("&Formula* [%1]->[%2]:").arg(result.value("unit_from").toString(), result.value("unit_to").toString()), this);
00450 QLabel *desc = new QLabel("&Description:", this);
00451 QDateTimeEdit *timestampEdit = new QDateTimeEdit(this);
00452 QLineEdit *formulaEdit = new QLineEdit(this);
00453 QTextEdit *descEdit = new QTextEdit(this);
00454 timestamp->setBuddy(timestampEdit);
00455 formula->setBuddy(timestampEdit);
00456 desc->setBuddy(descEdit);
00457
00458
00459 timestampEdit->setCalendarPopup(true);
00460
00461
00462 addWidget(timestamp, 0, 0, 1, 1);
00463 addWidget(timestampEdit, 0, 1, 1, 1, "sens_chan_cali_timestamp");
00464 addWidget(formula, 1, 0, 1, 1);
00465 addWidget(formulaEdit, 1, 1, 1, 1, "sens_chan_cali_formula");
00466 addWidget(desc, 2, 0, 1, 1);
00467 addWidget(descEdit, 3, 0, 1, 2, "sens_chan_cali_desc", "plainText");
00468
00469
00470 connect(timestampEdit, SIGNAL(dateTimeChanged(QDateTime)), this, SLOT(updateButtons()));
00471 connect(formulaEdit, SIGNAL(textChanged(QString)), this, SLOT(updateButtons()));
00472 connect(descEdit, SIGNAL(textChanged()), this, SLOT(updateButtons()));
00473
00474
00475 QLabel *formulaNote = new QLabel(GlobalConst::CALI_FORMULA_HELP, this);
00476 formulaNote->setTextInteractionFlags(Qt::LinksAccessibleByMouse);
00477 formulaNote->setOpenExternalLinks(true);
00478 formulaNote->setWordWrap(true);
00479 bottomLayout()->addWidget(bottomLayout()->itemAtPosition(0, 0)->widget(), 1, 0);
00480 bottomLayout()->addWidget(formulaNote, 0, 0);
00481
00482
00483 select();
00484
00485
00486 if (positionOnId > 0) setCurrent("sens_chan_cali_id", QVariant::fromValue<int>(positionOnId));
00487 }
00488
00489 protected:
00490 virtual void onNewButtonPress(){
00491 MappedBaseEditor::onNewButtonPress();
00492 model()->setData(model()->index(model()->rowCount() - 1, model()->record().indexOf("sens_id")),
00493 QVariant::fromValue(m_sens_id));
00494 model()->setData(model()->index(model()->rowCount() - 1, model()->record().indexOf("sens_chan_nr")),
00495 QVariant::fromValue(m_sens_chan_nr));
00496 model()->setData(model()->index(model()->rowCount() - 1, model()->record().indexOf("sens_chan_cali_unit_from_id")),
00497 QVariant::fromValue(m_sens_unit_id));
00498 model()->setData(model()->index(model()->rowCount() - 1, model()->record().indexOf("sens_chan_cali_unit_to_id")),
00499 QVariant::fromValue(m_sens_chan_cali_unit_id));
00500 }
00501
00502 private:
00503 const int m_sens_id;
00504 const int m_sens_chan_nr;
00505 int m_sens_unit_id;
00506 int m_sens_chan_cali_unit_id;
00507 };
00508
00509 #include <QDialog>
00510 #include <QModelIndex>
00511 #include <QMouseEvent>
00512
00516 class CalibrationEditDialog : public QDialog {
00517 public:
00518 CalibrationEditDialog(int sens_id, int sens_chan_nr, int positionOnId , QWidget *parent = 0) : QDialog(parent) {
00519 SensorChannelCalibrationEditor *editor = new SensorChannelCalibrationEditor(sens_id, sens_chan_nr, positionOnId, this);
00520
00521 setWindowTitle(editor->windowTitle());
00522
00523 setLayout(new QVBoxLayout);
00524 layout()->addWidget(editor);
00525
00526 connect(editor, SIGNAL(closeRequested()),
00527 this, SLOT(close()));
00528 }
00529 };
00530
00531 #include <QSqlError>
00532
00536 class SensorChannelCalibrationsView : public QListView {
00537 public:
00538 SensorChannelCalibrationsView(int sens_id, int sens_chan_nr, QWidget *parent = 0) : QListView(parent) {
00539
00540 baseQuery = QString("SELECT '#' || row_number() OVER (PARTITION BY scc.sens_id, scc.sens_chan_nr ORDER BY scc.sens_chan_cali_timestamp ASC) || ' @ ' || sens_chan_cali_timestamp || ': ' || replace(sens_chan_cali_formula, '$1', 'RAW') || '' AS Calibrations, sens_chan_cali_id "
00541 "FROM tbl_sensor_channel_calibrations scc "
00542 "WHERE scc.sens_id = %1 AND scc.sens_chan_nr = %2 "
00543 "ORDER BY scc.sens_chan_cali_timestamp DESC");
00544
00545
00546 Q_ASSERT(sens_id > 0);
00547
00548
00549
00550 setModel(new SqlQueryModel(this));
00551 model()->setDependency("tbl_sensor_channel_calibrations");
00552
00553
00554 setConstraint(sens_id, sens_chan_nr);
00555 }
00556
00557 SqlQueryModel *model() const {
00558 Q_ASSERT(QListView::model());
00559 Q_ASSERT(dynamic_cast<SqlQueryModel*>(QListView::model()));
00560 return dynamic_cast<SqlQueryModel*>(QListView::model());
00561 }
00562
00563 void setConstraint(int sens_id, int sens_chan_nr){
00564
00565 Q_ASSERT(sens_id > 0);
00566 if (sens_chan_nr <= 0) return;
00567
00568 this->sens_id = sens_id;
00569 this->sens_chan_nr = sens_chan_nr;
00570
00571 model()->setQuery(Database::execStatic(baseQuery.arg(QString::number(sens_id), QString::number(sens_chan_nr))));
00572
00573 if (model()->query().lastError().isValid()) {
00574 qWarning() << "Unable to constrain SensorChannelCalibrationView with " << sens_id << " and " << sens_chan_nr;
00575 model()->clear();
00576 }
00577 }
00578
00579 protected:
00580 virtual void setModel(SqlQueryModel *model) {
00581 QListView::setModel(model);
00582 }
00583
00584 virtual void mouseDoubleClickEvent(QMouseEvent *event){
00585 QModelIndex idx = indexAt(event->pos());
00586 if (idx.isValid() || model()->rowCount() == 0) {
00587 Q_ASSERT(model()->record().indexOf("sens_chan_cali_id") != -1 || model()->rowCount() == 0);
00588 int sens_chan_cali_id = -1;
00589 if (model()->rowCount() != 0) {
00590 bool ok;
00591 sens_chan_cali_id = model()->index(idx.row(), model()->record().indexOf("sens_chan_cali_id")).data(Qt::DisplayRole).toInt(&ok);
00592 Q_ASSERT(ok);
00593 }
00594 Q_ASSERT(sens_id > 0);
00595 Q_ASSERT(sens_chan_nr > 0);
00596 CalibrationEditDialog e(sens_id, sens_chan_nr, sens_chan_cali_id, this);
00597 e.exec();
00598 }
00599 }
00600
00601 private:
00602 int sens_id;
00603 int sens_chan_nr;
00604 QString baseQuery;
00605 };
00606
00607 #include <QSpinBox>
00608
00614 class SensorChannelEditor : public MappedBaseEditor {
00615 Q_OBJECT
00616 public:
00617 SensorChannelEditor(QWidget *parent = 0, int sens_id = -1, int sens_chan_nr = -1) : MappedBaseEditor(parent) {
00618 setObjectName("SensorChannelEditor");
00619 setWindowTitle("Sensor channel editor");
00620
00621
00622 setTable("tbl_sensor_channels", "sens_chan_nr", Qt::AscendingOrder,
00623 sens_id != -1 ? QString::number(sens_id).prepend("sens_id = ") : QString());
00624
00625
00626 QLabel *name = new QLabel("&Name*:", this);
00627 QLabel *nr = new QLabel("Numbe&r* (>0):", this);
00628 QLabel *caliUnit = new QLabel("&Calibrated unit*:", this);
00629 QLabel *desc = new QLabel("&Description:", this);
00630 QLineEdit *nameEdit = new QLineEdit(this);
00631 QSpinBox *nrEdit = new QSpinBox(this);
00632 QComboBox *caliUnitEdit = new QComboBox(this);
00633 QTextEdit *descEdit = new QTextEdit(this);
00634 name->setBuddy(nameEdit);
00635 nr->setBuddy(nrEdit);
00636 caliUnit->setBuddy(caliUnitEdit);
00637 desc->setBuddy(descEdit);
00638
00639
00640 QLabel *cLabel = new QLabel("&Calibrations:", this);
00641 cView = new SensorChannelCalibrationsView(sens_id, sens_chan_nr, this);
00642 cView->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
00643 cLabel->setBuddy(cView);
00644
00645
00646 addWidget(name, 0, 0, 1, 1);
00647 addWidget(nameEdit, 0, 1, 1, 1, "sens_chan_name");
00648 addWidget(nr, 1, 0, 1, 1);
00649 addWidget(nrEdit, 1, 1, 1, 1, "sens_chan_nr");
00650 addWidget(caliUnit, 0, 2, 1, 1);
00651 addWidget(caliUnitEdit, 0, 3, 1, 1, QSqlRelation("tbl_units", "unit_id", "unit_symbol"), "sens_chan_cali_unit_id");
00652 addWidget(cLabel, 1, 2, 1, 2);
00653 addWidget(cView, 2, 2, 2, 2);
00654 addWidget(desc, 2, 0, 1, 1);
00655 addWidget(descEdit, 3, 0, 1, 2, "sens_chan_desc", "plainText");
00656
00657
00658 connect(nameEdit, SIGNAL(textChanged(QString)), this, SLOT(updateButtons()));
00659 connect(nrEdit, SIGNAL(valueChanged(int)), this, SLOT(updateButtons()));
00660 connect(descEdit, SIGNAL(textChanged()), this, SLOT(updateButtons()));
00661 connect(caliUnitEdit, SIGNAL(currentIndexChanged(int)), this, SLOT(updateButtons()));
00662
00663
00664 select();
00665
00666
00667 if (sens_chan_nr > 0) setCurrent("sens_chan_nr", QVariant::fromValue<int>(sens_chan_nr));
00668
00669
00670 if (sens_chan_nr > 0) cView->setConstraint(sens_id == -1 ? 0 : sens_id, sens_id == -1 ? 0 : sens_chan_nr);
00671 }
00672
00673 protected:
00674 virtual void onCurrentRecordChange(int row){
00675 MappedBaseEditor::onCurrentRecordChange(row);
00676 updateSensorChannelView();
00677 }
00678
00679 virtual void updateButtons(){
00680 MappedBaseEditor::updateButtons();
00681 cView->setDisabled(isCurrentRecordNew() || model()->rowCount() == 0);
00682 }
00683
00684 virtual void onNewButtonPress(){
00685 MappedBaseEditor::onNewButtonPress();
00686 bool ok;
00687 model()->setData(model()->index(model()->rowCount() - 1, model()->record().indexOf("sens_id")),
00688 QVariant::fromValue(model()->filter().remove("sens_id = ").toInt(&ok)));
00689 Q_ASSERT(ok);
00690 }
00691
00692 private:
00693 void updateSensorChannelView(){
00694 Q_ASSERT(cView);
00695 bool ok;
00696 int sens_id = model()->index(currentMapperRow(), model()->record().indexOf("sens_id")).data(Qt::DisplayRole).toInt(&ok);
00697 Q_ASSERT(ok);
00698 int sens_chan_nr = model()->index(currentMapperRow(), model()->record().indexOf("sens_chan_nr")).data(Qt::DisplayRole).toInt(&ok);
00699 Q_ASSERT(ok);
00700 if (!ok || sens_id == 0 || sens_id == -1 || sens_chan_nr == 0 || sens_chan_nr == -1){
00701 cView->model()->clear();
00702 } else {
00703 cView->setConstraint(sens_id, sens_chan_nr);
00704 }
00705 }
00706
00707 private:
00708 SensorChannelCalibrationsView *cView;
00709 };
00710
00711 #include <QDialog>
00712 #include <QVBoxLayout>
00713
00717 class SensorChannelEditDialog : public QDialog {
00718 public:
00719 SensorChannelEditDialog(int sens_id, int sens_chan_nr , QWidget *parent = 0) : QDialog(parent) {
00720 SensorChannelEditor *editor = new SensorChannelEditor(this, sens_id, sens_chan_nr);
00721 setWindowTitle(editor->windowTitle());
00722
00723 setLayout(new QVBoxLayout);
00724 layout()->addWidget(editor);
00725
00726 connect(editor, SIGNAL(closeRequested()),
00727 this, SLOT(close()));
00728 }
00729 };
00730
00731 #include <QSqlQueryModel>
00732
00736 class SensorChannelModel : public SqlQueryModel {
00737 Q_OBJECT
00738 public:
00739 enum Field {
00740 FieldSensorId = Qt::UserRole,
00741 FieldSensorChannelNr,
00742 FieldSensorCustomName
00743 };
00744
00745 SensorChannelModel(QObject *parent = 0) : SqlQueryModel(parent), sens_id(0){
00746 setDependency("tbl_sensor_channel_calibrations");
00747 setDependency("tbl_sensor_channels");
00748
00749 defaultQuery = QString("SELECT '#' || sens_chan_nr || ': ' || sens_chan_name || COALESCE(' [' || (SELECT count(*) || ' calibrations: last @ ' || max(sens_chan_cali_timestamp) || ']' FROM tbl_sensor_channel_calibrations scc WHERE scc.sens_id = c.sens_id AND scc.sens_chan_nr = c.sens_chan_nr)::text, ' [Never calibrated]'), "
00750 "sens_id, sens_chan_nr, "
00751 "sens_type || ' (' || sens_serialnr || ')' "
00752 "FROM tbl_sensor_channels c "
00753 "INNER JOIN tbl_sensors s USING (sens_id) ");
00754 unconstrain();
00755 }
00756
00757 QVariant data(const QModelIndex &index, int role) const {
00758 if (!index.isValid())
00759 return QVariant();
00760
00761 switch (role) {
00762 case SensorChannelModel::FieldSensorId:
00763 return QSqlQueryModel::data(this->index(index.row(), 1));
00764 case SensorChannelModel::FieldSensorChannelNr:
00765 return QSqlQueryModel::data(this->index(index.row(), 2));
00766 case SensorChannelModel::FieldSensorCustomName:
00767 return QSqlQueryModel::data(this->index(index.row(), 3));
00768 default:
00769 return QSqlQueryModel::data(index, role);
00770 }
00771 }
00772
00773 void setConstraint(const int &sens_id){
00774 this->sens_id = sens_id;
00775 setQuery(Database::execStatic(defaultQuery + QString(" WHERE sens_id = ") + QString::number(sens_id) + " ORDER BY sens_id, sens_chan_nr "));
00776
00777
00778 if (query().lastError().isValid()) {
00779 unconstrain();
00780 return;
00781 }
00782
00783 constrained = true;
00784 }
00785
00786 int constraint(){
00787 return sens_id;
00788 }
00789
00790 void unconstrain(){
00791 setQuery(Database::execStatic(defaultQuery + " ORDER BY sens_id, sens_chan_nr "));
00792 constrained = false;
00793 sens_id = 0;
00794 }
00795
00796 private slots:
00797 private:
00798 QString defaultQuery;
00799 bool constrained;
00800 int sens_id;
00801 };
00802
00803 #include <QListView>
00804 #include <QSqlQueryModel>
00805 #include <QMouseEvent>
00806
00810 class SensorChannelView : public QListView {
00811 Q_OBJECT
00812 public:
00813 SensorChannelView(QWidget *parent = 0) : QListView(parent) {
00814 setModel(new SensorChannelModel(this));
00815 }
00816
00817 SensorChannelModel *model(){
00818 Q_ASSERT(dynamic_cast<SensorChannelModel*>(QListView::model()));
00819 return dynamic_cast<SensorChannelModel*>(QListView::model());
00820 }
00821
00822 private slots:
00823 virtual void mouseDoubleClickEvent(QMouseEvent *event){
00824
00825
00826
00827 QModelIndex index = indexAt(event->pos());
00828 if (index.isValid() || model()->rowCount() == 0) {
00829 int sens_id = model()->constraint();
00830 int sens_chan_nr = index.data(SensorChannelModel::FieldSensorChannelNr).toInt();
00831 Q_ASSERT(sens_id);
00832 SensorChannelEditDialog e(sens_id, sens_chan_nr, this);
00833 e.exec();
00834 model()->reQuery();
00835 }
00836 }
00837 };
00838
00839 #include <QComboBox>
00840 #include <QSqlRelation>
00841
00847 class SensorEditor : public MappedBaseEditor {
00848 Q_OBJECT
00849 public:
00850 SensorEditor(QWidget *parent = 0) :
00851 MappedBaseEditor(parent), channelView(new SensorChannelView(this)) {
00852 setObjectName("SesnorEditor");
00853 setWindowTitle("Sensor editor");
00854
00855
00856 setTable("tbl_sensors");
00857
00858
00859 QLabel *type = new QLabel("&Type*:", this);
00860 QLabel *sn = new QLabel("&Serial number*:", this);
00861 QLabel *name = new QLabel("&Name:", this);
00862 QLabel *category = new QLabel("&Category*:", this);
00863 QLabel *unit = new QLabel("&Unit*:", this);
00864 QLabel *desc = new QLabel("Description:", this);
00865 QLineEdit *typeEdit = new QLineEdit(this);
00866 QLineEdit *snEdit = new QLineEdit(this);
00867 QLineEdit *nameEdit = new QLineEdit(this);
00868 QComboBox *categoryEdit = new QComboBox(this);
00869 QComboBox *unitEdit = new QComboBox(this);
00870 QTextEdit *descEdit = new QTextEdit(this);
00871 type->setBuddy(typeEdit);
00872 sn->setBuddy(snEdit);
00873 name->setBuddy(nameEdit);
00874 category->setBuddy(categoryEdit);
00875 unit->setBuddy(unitEdit);
00876 desc->setBuddy(descEdit);
00877
00878
00879 QLabel *channels = new QLabel("&Channels:\n(Doubleclick to edit/add/delete)", this);
00880 channels->setBuddy(channelView);
00881 channelView->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
00882
00883
00884 addWidget(type, 0, 0, 1, 1);
00885 addWidget(typeEdit, 0, 1, 1, 1, "sens_type");
00886 addWidget(sn, 1, 0, 1, 1);
00887 addWidget(snEdit, 1, 1, 1, 1, "sens_serialnr");
00888 addWidget(name, 2, 0, 1, 1);
00889 addWidget(nameEdit, 2, 1, 1, 1, "sens_name");
00890 addWidget(category, 3, 0, 1, 1);
00891 addWidget(categoryEdit, 3, 1, 1, 1, QSqlRelation("tbl_sensor_categories", "sens_cate_id", "sens_cate_name"));
00892 addWidget(unit, 4, 0, 1, 1);
00893 addWidget(unitEdit, 4, 1, 1, 1, QSqlRelation("vew_sensor_units", "unit_id", "unit_symbol"));
00894 addWidget(channels, 0, 2, 1, 1);
00895 addWidget(channelView, 1, 2, 4, 1);
00896 addWidget(desc, 5, 0, 1, 3);
00897 addWidget(descEdit, 6, 0, 1, 3, "sens_desc", "plainText");
00898
00899
00900 connect(typeEdit, SIGNAL(textChanged(QString)), this, SLOT(updateButtons()));
00901 connect(snEdit, SIGNAL(textChanged(QString)), this, SLOT(updateButtons()));
00902 connect(nameEdit, SIGNAL(textChanged(QString)), this, SLOT(updateButtons()));
00903 connect(categoryEdit, SIGNAL(currentIndexChanged(int)), this, SLOT(updateButtons()));
00904 connect(unitEdit, SIGNAL(currentIndexChanged(int)), this, SLOT(updateButtons()));
00905 connect(descEdit, SIGNAL(textChanged()), this, SLOT(updateButtons()));
00906
00907
00908 select();
00909 }
00910 protected:
00911 virtual void onCurrentRecordChange(int row){
00912 MappedBaseEditor::onCurrentRecordChange(row);
00913 updateSensorChannelView();
00914 }
00915
00916 virtual void updateButtons(){
00917 MappedBaseEditor::updateButtons();
00918 channelView->setDisabled(isCurrentRecordNew() || model()->rowCount() == 0);
00919 }
00920
00921 virtual void onQueryChange(){
00922 MappedBaseEditor::onQueryChange();
00923 updateSensorChannelView();
00924 }
00925
00926 private:
00927 void updateSensorChannelView(){
00928 Q_ASSERT(channelView);
00929 bool ok;
00930 int sens_id = currentPrimaryKey().value("sens_id").toInt(&ok);
00931 if (!ok || sens_id == 0 || sens_id == -1 ){
00932 channelView->model()->clear();
00933 } else {
00934 channelView->model()->setConstraint(sens_id);
00935 }
00936 }
00937
00938 private:
00939 SensorChannelView *channelView;
00940 };
00941
00942 #include "global.h"
00943 #include <QSqlField>
00944 #include <QListView>
00945 #include <QSqlQueryModel>
00946 #include <QPushButton>
00947
00953 class SensorUnitEditor : public BaseEditor {
00954 Q_OBJECT
00955 public:
00956 SensorUnitEditor(QWidget *parent = 0) : BaseEditor(parent) {
00957 setObjectName("SensorUnitEditor");
00958 setWindowTitle("Sensor unit editor");
00959
00960 m_model = new SqlQueryModel(this);
00961 m_model->setQuery(Database::execStatic("SELECT unit_name || ' (' || unit_symbol || ')' "
00962 "FROM tbl_sensor_units "
00963 "INNER JOIN tbl_units USING (unit_id) ORDER BY 1"));
00964 m_view = new QListView(this);
00965 m_view->setModel(m_model);
00966 m_view->setSelectionMode(QAbstractItemView::NoSelection);
00967
00968
00969 QVBoxLayout *buttonLayout = new QVBoxLayout();
00970 buttonLayout->addWidget(button(BaseEditor::ButtonAdd));
00971 buttonLayout->addStretch();
00972 buttonLayout->addWidget(button(BaseEditor::ButtonClose));
00973
00974 mainLayout()->addWidget(m_view, 0, 0, 1, 1);
00975 mainLayout()->addLayout(buttonLayout, 0, 1, 2, 1);
00976
00977 connect(button(BaseEditor::ButtonAdd), SIGNAL(clicked()), this, SLOT(onAddButtonPress()));
00978 }
00979
00980 virtual bool isDirty() const {return false;}
00981
00982 protected slots:
00983 void onAddButtonPress(){
00984 QSqlQueryModel model;
00985 model.setQuery(Database::execStatic("SELECT unit_name || ' (' || unit_symbol || ')', unit_id "
00986 "FROM "
00987 " ( "
00988 " SELECT unit_id FROM tbl_units "
00989 " EXCEPT "
00990 " SELECT unit_id FROM tbl_sensor_units "
00991 " ) "
00992 "AS e INNER JOIN tbl_units USING (unit_id) ORDER BY 1"));
00993 SimpleViewSelectionDialog d("Unit selector", &model, this);
00994 if (d.exec()){
00995 int row = d.selection().row();
00996 bool ok;
00997 int unit_id = model.index(row, 1).data(Qt::DisplayRole).toInt(&ok);
00998 Q_ASSERT(ok);
00999 Q_ASSERT(unit_id != 0);
01000 Q_ASSERT(unit_id != -1);
01001 Database::execStatic("INSERT INTO tbl_sensor_units VALUES (" + QString::number(unit_id) + ")");
01002 m_model->reQuery();
01003 }
01004 }
01005
01006 virtual void updateButtons(){};
01007
01008 virtual void onNewButtonPress(){};
01009
01010 virtual void onSubmitButtonPress(){};
01011
01012 virtual void onUndoButtonPress(){};
01013
01014 private:
01015 QListView *m_view;
01016 SqlQueryModel *m_model;
01017 };
01018
01019 #endif // PROJECTSEDITOR_H