소스 검색

Merge pull request #18 from fiffty-50/devel-db-getEntryData

Devel db get entry data
Felix Turowsky 4 년 전
부모
커밋
447654634b

+ 3 - 1
main.cpp

@@ -22,6 +22,7 @@
 #include <QProcess>
 #include <QSettings>
 #include <QFileInfo>
+#include "src/experimental/DataBase.h"
 
 const auto DATA_DIR = QLatin1String("data");
 /*!
@@ -50,7 +51,8 @@ int main(int argc, char *argv[])
     QSettings::setDefaultFormat(QSettings::IniFormat);
     QSettings settings;
 
-    Db::connect();
+//    Db::connect();
+    experimental::DB()->connect();
 
     QApplication openPilotLog(argc, argv);
     if(!setup()){

+ 5 - 0
mainwindow.cpp

@@ -139,5 +139,10 @@ void MainWindow::on_actionNewAircraft_triggered()
 void MainWindow::on_actionNewPilot_triggered()
 {
     NewPilotDialog np =NewPilotDialog(Db::createNew, this);
+    using namespace experimental;
+    QObject::connect(DB(), &DataBase::commitSuccessful,
+                     &np, &NewPilotDialog::onCommitSuccessful);
+    QObject::connect(DB(), &DataBase::commitUnsuccessful,
+                     &np, &NewPilotDialog::onCommitUnsuccessful);
     np.exec();
 }

+ 1 - 0
mainwindow.h

@@ -36,6 +36,7 @@
 #include "src/gui/dialogues/newtaildialog.h"
 #include "src/gui/dialogues/newpilotdialog.h"
 #include "src/classes/runguard.h"
+#include "src/experimental/DataBase.h"
 
 QT_BEGIN_NAMESPACE
 namespace Ui {

+ 120 - 1
src/experimental/DataBase.cpp

@@ -2,6 +2,11 @@
 
 namespace experimental {
 
+/// [F] suggestions for signals:
+///
+/// commitSuccessful()
+/// commitUnSuccessful(QString sqlError, QString statement)
+
 DataBase* DataBase::instance = nullptr;
 
 DataBase* DataBase::getInstance()
@@ -38,9 +43,23 @@ bool DataBase::connect()
             tableColumns.insert(table, columnNames);
         }
     }
+    DEB("Database Tables: " << tableNames);
     return true;
 }
 
+void DataBase::disconnect()
+{
+    auto db = DataBase::database();
+    db.close();
+    db.removeDatabase(db.connectionName());
+    DEB("Database connection closed.");
+}
+
+QSqlDatabase DataBase::database()
+{
+    return QSqlDatabase::database("qt_sql_default_connection");
+}
+
 bool DataBase::commit(Entry entry)
 {
     if (exists(entry)) {
@@ -86,7 +105,7 @@ bool DataBase::exists(Entry entry)
     q.next();
     int rowId = q.value(0).toInt();
     if (rowId) {
-        DEB("Entry exists with row ID: " << rowId);
+        DEB("Entry " << entry.position << " exists.");
         return true;
     } else {
         DEB("Entry does not exist.");
@@ -115,11 +134,15 @@ bool DataBase::update(Entry updated_entry)
     if (q.lastError().type() == QSqlError::NoError)
     {
         DEB("Entry successfully committed.");
+        emit commitSuccessful();
+        /// [F] emit DB(), &DataBase::commitSuccessful, NewPilotDialog, &NewPilotDialog::onCommitSuccessful);
         return true;
     } else {
         DEB("Unable to commit.");
         DEB("Query: " << statement);
         DEB("Query Error: " << q.lastError().text());
+        emit commitUnsuccessful(q.lastError().text(), statement);
+        /// [F] emit DB(), &DataBase::commitSuccessful, NewPilotDialog, &NewPilotDialog::onCommitSuccessful);
         return false;
     }
 }
@@ -146,16 +169,112 @@ bool DataBase::insert(Entry newEntry)
     if (q.lastError().type() == QSqlError::NoError)
     {
         DEB("Entry successfully committed.");
+        emit commitSuccessful();
+        /// [F] emit DB(), &DataBase::commitSuccessful, NewPilotDialog, &NewPilotDialog::onCommitSuccessful);
         return true;
     } else {
         DEB("Unable to commit.");
         DEB("Query: " << statement);
         DEB("Query Error: " << q.lastError().text());
+        emit commitUnsuccessful(q.lastError().text(), statement);
+        /// [F] emit DB(), &DataBase::commitSuccessful, NewPilotDialog, &NewPilotDialog::onCommitSuccessful);
         return false;
     }
 
 }
 
+TableData DataBase::getEntryData(DataPosition dataPosition)
+{
+    // check table exists
+    if (!tableNames.contains(dataPosition.first)) {
+        DEB(dataPosition.first << " not a table in the database. Unable to retreive Entry data.");
+        return TableData();
+    }
+
+    //Check Database for rowId
+    QString statement = "SELECT COUNT(*) FROM " + dataPosition.first
+                      + " WHERE _rowid_=" + QString::number(dataPosition.second);
+    QSqlQuery checkQuery(statement);
+
+    if (checkQuery.lastError().type() != QSqlError::NoError) {
+        DEB("SQL error: " << checkQuery.lastError().text());
+        DEB("Statement: " << statement);
+        return TableData();
+    }
+
+    checkQuery.next();
+    if (checkQuery.value(0).toInt() == 0) {
+        DEB("No Entry found for row id: " << dataPosition.second );
+        return TableData();
+    }
+
+    // Retreive TableData
+    DEB("Retreiving data for row id: " << dataPosition.second);
+    statement = "SELECT * FROM " + dataPosition.first
+              + " WHERE _rowid_=" + QString::number(dataPosition.second);
+
+    QSqlQuery selectQuery(statement);
+    if (selectQuery.lastError().type() != QSqlError::NoError) {
+        DEB("SQL error: " << selectQuery.lastError().text());
+        DEB("Statement: " << statement);
+        return TableData();
+    }
+
+    selectQuery.next();
+    TableData entryData;
+
+    for (const auto &column : tableColumns.value(dataPosition.first)) {
+        entryData.insert(column, selectQuery.value(column).toString());
+    }
+    return entryData;
+}
+
+/// does the same as geteEntryData, but slower
+/*TableData DataBase::getEntryDataQsqlTableModel(DataPosition dataPosition)
+{
+    // check table exists
+    if (!tableNames.contains(dataPosition.first)) {
+        DEB(dataPosition.first << " not a table in the database. Unable to retreive Entry data.");
+        // emit databaseError
+        return TableData();
+    }
+
+    QSqlTableModel model;
+    model.setTable(dataPosition.first);
+    model.setFilter("_rowid_=" + QString::number(dataPosition.second));
+    model.select();
+
+    if (model.rowCount() == 0) {
+        DEB("No Entry found for row id: " << dataPosition.second );
+        // emit databaseError("No Entry found for row id: " + dataPosition.second)
+        return TableData();
+    } else if (model.lastError().type() != QSqlError::NoError) {
+        DEB("SQL error: " << model.lastError().text());
+        // emit sqlError(selectQuery.lastError().text(), statement)
+        return TableData();
+    }
+
+    TableData entryData;
+    for (const auto column : tableColumns.value(dataPosition.first)) {
+        entryData.insert(column, model.record(0).value(column).toString());
+    }
+    return entryData;
+}*/
+
+Entry DataBase::getEntry(DataPosition dataPosition)
+{
+    Entry entry(dataPosition);
+    entry.setData(DataBase::getEntryData(dataPosition));
+    return entry;
+}
+
+PilotEntry DataBase::getPilotEntry(RowId rowId)
+{
+    PilotEntry pilotEntry(rowId);
+    pilotEntry.setData(DataBase::getEntryData(pilotEntry.position));
+    return pilotEntry;
+}
+
 DataBase* DB() { return DataBase::getInstance(); }
 
 }

+ 35 - 7
src/experimental/DataBase.h

@@ -6,6 +6,7 @@
 #include <QString>
 #include <QSqlQuery>
 #include <QSqlError>
+#include <QSqlTableModel>
 #include "src/database/dbinfo.h"
 #include "debug.h"
 
@@ -13,16 +14,12 @@
 
 namespace experimental {
 
-// [F] ideas for functions of db class:
-// https://github.com/fiffty-50/openpilotlog/wiki/New-DB-class-brainstorming
-
 /*!
  * \brief The DB class encapsulates the SQL database by providing fast access
  * to hot database data.
  */
-
-
-class DataBase {
+class DataBase : public QObject {
+    Q_OBJECT
 private:
     TableNames tableNames;
     TableColumns tableColumns;
@@ -42,7 +39,13 @@ public:
     /*!
      * \brief closes the database connection.
      */
-    bool disconnect();
+    void disconnect();
+
+    /*!
+     * \brief Can be used to access the database connection.
+     * \return The QSqlDatabase object pertaining to the connection.
+     */
+    static QSqlDatabase database();
 
     /*!
      * \brief Checks if an entry exists in the database, based on position data
@@ -70,6 +73,31 @@ public:
      */
     bool remove(Entry entry);
 
+    /*!
+     * \brief retreive entry data from the database to create an entry object
+     */
+    TableData getEntryData(DataPosition);
+
+    /*!
+     * \brief retreive an Entry from the database.
+     */
+    Entry getEntry(DataPosition);
+
+    /*!
+     * \brief retreives a PilotEntry from the database.
+     *
+     * This function is a wrapper for DataBase::getEntry(DataPosition),
+     * where the table is already set and which returns a PilotEntry
+     * instead of an Entry. It allows for easy access to a pilot entry
+     * with only the RowId required as input.
+     */
+    PilotEntry getPilotEntry(RowId);
+    ///[F] the same can easily be implemented for tails/flights
+signals:
+    void commitSuccessful();
+
+    void commitUnsuccessful(const QString &sqlError, const QString &sqlStatement);
+
 };
 
 /*!

+ 31 - 42
src/gui/dialogues/newpilotdialog.cpp

@@ -55,45 +55,35 @@ static const auto LINE_EDIT_VALIDATORS = QVector({FIRSTNAME_VALID, LASTNAME_VALI
                                            PHONE_VALID,     EMAIL_VALID,
                                            COMPANY_VALID,     EMPLOYEENR_VALID});
 // For creating a new entry
-NewPilotDialog::NewPilotDialog(Db::editRole edRole, QWidget *parent) :
+NewPilotDialog::NewPilotDialog(QWidget *parent) :
     QDialog(parent),
     ui(new Ui::NewPilot)
 {
     DEB("New NewPilotDialog\n");
-    role = edRole;
     ui->setupUi(this);
-
     setupValidators();
     setupCompleter();
+
+    using namespace experimental;
+    pilotEntry = PilotEntry();
+    ui->piclastnameLineEdit->setFocus();
 }
-// For editing an existing entry
-NewPilotDialog::NewPilotDialog(Pilot existingEntry, Db::editRole edRole, QWidget *parent) :
+
+NewPilotDialog::NewPilotDialog(int rowId, QWidget *parent) :
     QDialog(parent),
     ui(new Ui::NewPilot)
 {
-    DEB("New NewPilotDialog\n");
-    oldEntry = existingEntry;
-    role = edRole;
     ui->setupUi(this);
-
     setupValidators();
     setupCompleter();
 
+    using namespace experimental;
+    pilotEntry = DB()->getPilotEntry(rowId);
+    DEB("Pilot Entry position: " << pilotEntry.position);
     formFiller();
     ui->piclastnameLineEdit->setFocus();
 }
 
-NewPilotDialog::NewPilotDialog(experimental::PilotEntry oldEntry, Db::editRole, QWidget *parent) :
-    QDialog(parent),
-    ui(new Ui::NewPilot)
-{
-    using namespace experimental;
-//    connect(DB(), &DataBase::commitUnsuccessful,
-//            this, &NewPilotDialog::onCommitUnsuccessful);
-    oldPilotEntry = oldEntry;
-    //to do
-}
-
 NewPilotDialog::~NewPilotDialog()
 {
     DEB("Deleting New NewPilotDialog\n");
@@ -108,10 +98,21 @@ void NewPilotDialog::on_buttonBox_accepted()
         mb.show();
     } else {
         submitForm();
-        accept();
     }
 }
 
+void NewPilotDialog::onCommitSuccessful()
+{
+    accept();
+}
+
+void NewPilotDialog::onCommitUnsuccessful(const QString &sqlError, const QString &)
+{
+    auto mb = QMessageBox(this);
+    mb.setText("The following error has ocurred. Your entry has not been saved./n/n"
+               + sqlError);
+}
+
 void NewPilotDialog::setupValidators()
 {
     DEB("Setting up Validators...");
@@ -141,16 +142,12 @@ void NewPilotDialog::setupCompleter()
 void NewPilotDialog::formFiller()
 {
     DEB("Filling Form...");
-    DEB(oldEntry);
-    auto line_edits = parent()->findChildren<QLineEdit *>();
+    auto line_edits = this->findChildren<QLineEdit *>();
 
     for (const auto &le : line_edits) {
-        QString key = le->objectName();
-        key.chop(8);//remove "LineEdit"
-        QString value = oldEntry.data.value(key);
-        if (!value.isEmpty()) {
-            le->setText(value);
-        }
+        QString key = le->objectName().remove("LineEdit");
+        QString value = pilotEntry.getData().value(key);
+        le->setText(value);
     }
 }
 
@@ -172,20 +169,12 @@ void NewPilotDialog::submitForm()
     displayName.append(QLatin1String(", "));
     displayName.append(ui->picfirstnameLineEdit->text().left(1));
     displayName.append(QLatin1Char('.'));
-    newData.insert("displayname",displayName);
+    newData.insert("displayname", displayName);
 
     using namespace experimental;
 
-    switch (role) {
-    case Db::editExisting:
-        oldEntry.setData(newData);
-        DB()->commit(oldPilotEntry);
-        // to do: handle unsuccessful commit
-        break;
-    case Db::createNew:
-        auto newEntry = PilotEntry(newData);
-        experimental::DB()->commit(oldPilotEntry);
-        // to do: handle unsuccessful commit
-        break;
-    }
+    pilotEntry.setData(newData);
+    DEB("Pilot entry position: " << pilotEntry.position);
+    DEB("Pilot entry data: " << pilotEntry.getData());
+    DB()->commit(pilotEntry);
 }

+ 11 - 9
src/gui/dialogues/newpilotdialog.h

@@ -27,8 +27,8 @@
 #include "src/classes/completionlist.h"
 
 #include "src/experimental/DataBase.h"
-//#include "src/experimental/Entry.h"
-//#include "src/experimental/Decl.h"
+#include "src/experimental/Entry.h"
+#include "src/experimental/Decl.h"
 
 namespace Ui {
 class NewPilot;
@@ -38,19 +38,21 @@ class NewPilotDialog : public QDialog
 {
     Q_OBJECT
 public:
-    explicit NewPilotDialog(Db::editRole, QWidget *parent = nullptr);
-    explicit NewPilotDialog(Pilot, Db::editRole, QWidget *parent = nullptr);
-    explicit NewPilotDialog(experimental::PilotEntry oldEntry, Db::editRole, QWidget *parent = nullptr);
+    explicit NewPilotDialog(QWidget *parent = nullptr);
+    explicit NewPilotDialog(int rowId, QWidget *parent = nullptr);
     ~NewPilotDialog();
 private slots:
     void on_buttonBox_accepted();
+
+public slots:
+
+    void onCommitSuccessful();
+
+    void onCommitUnsuccessful(const QString &sqlError, const QString &);
 private:
     Ui::NewPilot *ui;
 
-    Db::editRole role;
-    Pilot oldEntry;
-
-    experimental::PilotEntry oldPilotEntry;
+    experimental::PilotEntry pilotEntry;
 
     void setupValidators();
 

+ 1 - 2
src/gui/widgets/homewidget.cpp

@@ -38,6 +38,5 @@ HomeWidget::~HomeWidget()
 
 void HomeWidget::on_pushButton_clicked()
 {
-    NewFlightDialog nf(this, Flight(11), Db::editExisting);
-    nf.exec();
+    // do debug stuff
 }

+ 2 - 0
src/gui/widgets/homewidget.h

@@ -34,6 +34,8 @@
 #include "src/gui/dialogues/firstrundialog.h"
 #include "src/gui/dialogues/newflightdialog.h"
 
+#include "src/experimental/DataBase.h"
+#include "src/experimental/Decl.h"
 
 namespace Ui {
 class HomeWidget;

+ 15 - 5
src/gui/widgets/pilotswidget.cpp

@@ -39,12 +39,17 @@ void PilotsWidget::tableView_selectionChanged()//const QItemSelection &index, co
     selectedPilots.clear();
 
     for (const auto& row : selection->selectedRows()) {
-        selectedPilots << row.data().toInt();
+        selectedPilots.append(row.data().toInt());
         DEB("Selected Tails(s) with ID: " << selectedPilots);
     }
     if(selectedPilots.length() == 1) {
 
-        NewPilotDialog* np = new NewPilotDialog(Pilot(selectedPilots.first()), Db::editExisting, this);
+        NewPilotDialog* np = new NewPilotDialog(selectedPilots.first(), this);
+        using namespace experimental;
+        QObject::connect(DB(), &DataBase::commitSuccessful,
+                         np,   &NewPilotDialog::onCommitSuccessful);
+        QObject::connect(DB(), &DataBase::commitUnsuccessful,
+                         np,   &NewPilotDialog::onCommitUnsuccessful);
         connect(np, SIGNAL(accepted()), this, SLOT(pilot_editing_finished()));
         connect(np, SIGNAL(rejected()), this, SLOT(pilot_editing_finished()));
         np->setWindowFlag(Qt::Widget);
@@ -63,10 +68,15 @@ void PilotsWidget::tableView_headerClicked(int column)
 
 void PilotsWidget::on_newButton_clicked()
 {
-    NewPilotDialog* np = new NewPilotDialog(Db::createNew, this);
+    NewPilotDialog* np = new NewPilotDialog(this);
     np->setAttribute(Qt::WA_DeleteOnClose);
-    connect(np, SIGNAL(accepted()),
-            this, SLOT(pilot_editing_finished()));
+    connect(np, SIGNAL(accepted()), this, SLOT(pilot_editing_finished()));
+    connect(np, SIGNAL(rejected()), this, SLOT(pilot_editing_finished()));
+    using namespace experimental;
+    QObject::connect(DB(), &DataBase::commitSuccessful,
+                     np,   &NewPilotDialog::onCommitSuccessful);
+    QObject::connect(DB(), &DataBase::commitUnsuccessful,
+                     np,   &NewPilotDialog::onCommitUnsuccessful);
     np->exec();
 }