Explorar el Código

Migrated deleting to new DB architecture

Deleting flights in the logbookwidget is now done using the new DB architecture. Implemented signals and slots, did some preliminary testing.
Added a function for batch-deleting flights, optimised for larger selections. Used when deleting more than 10 flights at once.
Felix Turo hace 4 años
padre
commit
b38fe82260

+ 69 - 1
src/experimental/adatabase.cpp

@@ -108,6 +108,46 @@ bool ADataBase::remove(AEntry entry)
     }
 }
 
+bool ADataBase::removeMany(QList<DataPosition> data_position_list)
+{
+    int errorCount = 0;
+    QSqlQuery query;
+    query.prepare("BEGIN EXCLUSIVE TRANSACTION");
+    query.exec();
+
+    for (const auto data_position : data_position_list) {
+        if (!exists(data_position)) {
+            DEB("Error: Entry does not exist.");
+            errorCount++;
+        }
+        QString statement = "DELETE FROM " + data_position.first +
+                " WHERE ROWID=" + QString::number(data_position.second);
+
+        query.prepare(statement);
+        query.exec();
+
+        if (!(query.lastError().type() == QSqlError::NoError))
+            errorCount++;
+    }
+
+    if (errorCount == 0) {
+        query.prepare("COMMIT");
+        query.exec();
+        if(query.lastError().type() == QSqlError::NoError) {
+            emit sqlSuccessful();
+            return true;
+        } else {
+            emit sqlError(query.lastError(), "Transaction unsuccessful. Error count: " + QString::number(errorCount));
+            return false;
+        }
+    } else {
+        query.prepare("ROLLBACK");
+        query.exec();
+        emit sqlError(query.lastError(), "Transaction unsuccessful(rolled back). Error count: " + QString::number(errorCount));
+        return false;
+    }
+}
+
 bool ADataBase::exists(AEntry entry)
 {
     if(entry.getPosition().second == 0)
@@ -116,11 +156,11 @@ bool ADataBase::exists(AEntry entry)
     //Check database for row id
     QString statement = "SELECT COUNT(*) FROM " + entry.getPosition().tableName +
             " WHERE ROWID=" + QString::number(entry.getPosition().rowId);
-    //this returns either 1 or 0 since row ids are unique
     QSqlQuery query;
     query.prepare(statement);
     query.setForwardOnly(true);
     query.exec();
+    //this returns either 1 or 0 since row ids are unique
     if (!query.isActive()) {
         emit sqlError(query.lastError(), statement);
         DEB("Query Error: " << query.lastError().text() << statement);
@@ -136,6 +176,34 @@ bool ADataBase::exists(AEntry entry)
     }
 }
 
+bool ADataBase::exists(DataPosition data_position)
+{
+    if(data_position.second == 0)
+        return false;
+
+    //Check database for row id
+    QString statement = "SELECT COUNT(*) FROM " + data_position.first +
+            " WHERE ROWID=" + QString::number(data_position.second);
+    QSqlQuery query;
+    query.prepare(statement);
+    query.setForwardOnly(true);
+    query.exec();
+    //this returns either 1 or 0 since row ids are unique
+    if (!query.isActive()) {
+        emit sqlError(query.lastError(), statement);
+        DEB("Query Error: " << query.lastError().text() << statement);
+    }
+    query.next();
+    int rowId = query.value(0).toInt();
+    if (rowId) {
+        DEB("Entry exists at DataPosition: " << data_position);
+        return true;
+    } else {
+        DEB("No entry exists at DataPosition: " << data_position);
+        return false;
+    }
+}
+
 
 bool ADataBase::update(AEntry updated_entry)
 {

+ 7 - 0
src/experimental/adatabase.h

@@ -85,6 +85,7 @@ public:
      * \brief Checks if an entry exists in the database, based on position data
      */
     bool exists(AEntry entry);
+    bool exists(DataPosition data_position);
 
     /*!
      * \brief commits an entry to the database, calls either insert or update,
@@ -107,6 +108,12 @@ public:
      */
     bool remove(AEntry entry);
 
+    /*!
+     * \brief deletes a list of entries from the database. Optimised for speed when
+     * deleting many entries.
+     */
+    bool removeMany(QList<DataPosition>);
+
     /*!
      * \brief retreive entry data from the database to create an entry object
      */

+ 3 - 3
src/experimental/aflightentry.cpp

@@ -15,7 +15,7 @@ AFlightEntry::AFlightEntry(TableData table_data)
     : AEntry::AEntry(DEFAULT_FLIGHT_POSITION, table_data)
 {}
 
-QString AFlightEntry::summary()
+const QString AFlightEntry::summary()
 {
     if(tableData.isEmpty())
         return QString();
@@ -30,7 +30,7 @@ QString AFlightEntry::summary()
     return flight_summary;
 }
 
-QString AFlightEntry::registration()
+const QString AFlightEntry::registration()
 {
     QString tail_id = tableData.value("acft");
     if(tail_id.isEmpty())
@@ -49,7 +49,7 @@ QString AFlightEntry::registration()
     }
 }
 
-QString AFlightEntry::pilotName(pilot pilot_)
+const QString AFlightEntry::pilotName(pilot pilot_)
 {
     QString row_id;
     switch (pilot_) {

+ 3 - 3
src/experimental/aflightentry.h

@@ -20,18 +20,18 @@ public:
      * \brief Returs a summary of the flight data
      * \return "doft, dept, tofb, dest, tonb"
      */
-    QString summary();
+    const QString summary();
     /*!
      * \brief Returns the tails' registration from the database.
      */
-    QString registration();
+    const QString registration();
     /*!
      * \brief Returns the pilots name from the Database
      *
      * \param pilot_number - 1=pic, 2=second Pilot, 3 = third Pilot
      * \return "Lastname, Firstname"
      */
-    QString pilotName(pilot);
+    const QString pilotName(pilot);
 };
 
 } // namespace experimental

+ 74 - 59
src/gui/widgets/logbookwidget.cpp

@@ -19,9 +19,12 @@
 #include "ui_logbookwidget.h"
 #include "src/testing/adebug.h"
 
-const QMap<int, QString> filterMap = {
-    {0, "Date LIKE \"%"}, {1, "Dept LIKE \"%"}, {2, "Dest LIKE \"%"},
-    {3, "Registration LIKE \"%"}, {4, "\"Name PIC\" LIKE \"%"}
+const QMap<int, QString> FILTER_MAP = {
+    {0, "Date LIKE \"%"},
+    {1, "Dept LIKE \"%"},
+    {2, "Dest LIKE \"%"},
+    {3, "Registration LIKE \"%"},
+    {4, "\"Name PIC\" LIKE \"%"}
 };
 const auto NON_WORD_CHAR = QRegularExpression("\\W");
 
@@ -38,7 +41,7 @@ LogbookWidget::LogbookWidget(QWidget *parent) :
     menu->addAction(ui->actionDelete_Flight);
 
     //Initialise message Box
-    nope = new QMessageBox(this);
+    messageBox = new QMessageBox(this);
 
     prepareModelAndView(ASettings::read("logbook/view").toInt());
     connectSignalsAndSlots();
@@ -72,6 +75,11 @@ void LogbookWidget::connectSignalsAndSlots()
     selection = view->selectionModel();
     QObject::connect(view->selectionModel(), &QItemSelectionModel::selectionChanged,
                      this, &LogbookWidget::flightsTableView_selectionChanged);
+    using namespace experimental;
+    QObject::connect(aDB(), &ADataBase::sqlSuccessful,
+                     this, &LogbookWidget::onDeletedSuccessfully);
+    QObject::connect(aDB(), &ADataBase::sqlError,
+                     this, &LogbookWidget::onDeleteUnsuccessful);
 }
 
 void LogbookWidget::setupDefaultView()
@@ -180,31 +188,34 @@ void LogbookWidget::on_editFlightButton_clicked()
         ef->exec();
         displayModel->select();
     } else if (selectedFlights.isEmpty()) {
-        nope->setText("No flight selected.\n");
-        nope->exec();
+        messageBox->setText("No flight selected.\n");
+        messageBox->exec();
     } else {
-        nope->setText("More than one flight selected.\n\nEditing multiple entries is not yet supported.");
-        nope->exec();
+        messageBox->setText("More than one flight selected.\n\nEditing multiple entries is not yet supported.");
+        messageBox->exec();
     }
 }
 
 void LogbookWidget::on_deleteFlightPushButton_clicked()
 {
     DEB("Flights selected: " << selectedFlights.length());
-    if (selectedFlights.length() > 0 && selectedFlights.length() < 11) {
-        QVector<QString> columns = {
-            "doft", "dept", "dest"
-        };
-        QVector<QString> details;
+    if (selectedFlights.length() == 0) {
+        messageBox->setIcon(QMessageBox::Information);
+        messageBox->setText("No Flight Selected.");
+        messageBox->exec();
+        return;
+    } else if (selectedFlights.length() > 0 && selectedFlights.length() < 11) {
+        QList<experimental::AFlightEntry> flights_list;
+
+        for (const auto &flight_id : selectedFlights) {
+            flights_list.append(experimental::aDB()->getFlightEntry(flight_id));
+        }
+
         QString warningMsg = "The following flight(s) will be deleted:<br><br><b><tt>";
-        for(const auto& selectedFlight : selectedFlights){
-            details = Db::multiSelect(columns, "flights", "flight_id",
-                                       QString::number(selectedFlight), Db::exactMatch);
-            for (const auto &item : details) {
-                warningMsg.append(item);
-                warningMsg.append(' ');
-            }
-            warningMsg.append("<br>");
+
+        for (auto &flight : flights_list) {
+            warningMsg.append(flight.summary());
+            warningMsg.append(QLatin1String("&nbsp;&nbsp;&nbsp;&nbsp;<br>"));
         }
         warningMsg.append("</b></tt><br>Deleting Flights is irreversible."
                           "<br>Do you want to proceed?");
@@ -217,21 +228,16 @@ void LogbookWidget::on_deleteFlightPushButton_clicked()
         confirm.setText(warningMsg);
         int reply = confirm.exec();
         if (reply == QMessageBox::Yes) {
-            for (const auto& selectedFlight : selectedFlights) {
-                DEB("Deleting flight with ID# " << selectedFlight);
-                auto entry = Flight(selectedFlight);
-                entry.remove();
+            for (auto& flight : flights_list) {
+                DEB("Deleting flight: " << flight.summary());
+                experimental::aDB()->remove(flight);
             }
-            prepareModelAndView(ASettings::read("logbook/view").toInt());
+            displayModel->select();
         }
-    } else if (selectedFlights.length() == 0) {
-        nope->setIcon(QMessageBox::Information);
-        nope->setText("No Flight Selected.");
-        nope->exec();
     } else if (selectedFlights.length() > 10) {
         auto& warningMsg = "You have selected " + QString::number(selectedFlights.length())
-                         + " flights.\n\n Deleting these flights is irreversible.\n\n"
-                           "Are you sure you want to proceed?";
+                + " flights.\n\n Deleting flights is irreversible.\n\n"
+                  "Are you sure you want to proceed?";
         QMessageBox confirm;
         confirm.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
         confirm.setDefaultButton(QMessageBox::No);
@@ -240,23 +246,16 @@ void LogbookWidget::on_deleteFlightPushButton_clicked()
         confirm.setText(warningMsg);
         int reply = confirm.exec();
         if(reply == QMessageBox::Yes) {
-            for (const auto& selectedFlight : selectedFlights) {
-                DEB("Deleting flight with ID# " << selectedFlight);
-                auto entry = Flight(selectedFlight);
-                entry.remove();
+            QList<experimental::DataPosition> selected_flights;
+            for (const auto& flight_id : selectedFlights) {
+                selected_flights.append({"flights", flight_id});
             }
-            prepareModelAndView(ASettings::read("logbook/view").toInt());
+            experimental::aDB()->removeMany(selected_flights);
+            displayModel->select();
         }
     }
 }
 
-void LogbookWidget::on_showAllButton_clicked()
-{
-    ui->flightSearchLlineEdit->setText(QString());
-    displayModel->setFilter(QString());
-    displayModel->select();
-}
-
 void LogbookWidget::on_tableView_customContextMenuRequested(const QPoint &pos)
 {
     menu->popup(ui->tableView->viewport()->mapToGlobal(pos));
@@ -267,6 +266,19 @@ void LogbookWidget::on_actionDelete_Flight_triggered()
     emit ui->deleteFlightPushButton->clicked();
 }
 
+void LogbookWidget::onDeletedSuccessfully()
+{
+    messageBox->setText(QString::number(selectedFlights.length()) + " flights have been deleted.");
+    messageBox->exec();
+}
+
+void LogbookWidget::onDeleteUnsuccessful(const QSqlError error)
+{
+    messageBox->setText("Error deleting " + QString::number(selectedFlights.length())
+                        + " flights.\n\nThe following error has ocurred:\n\n" + error.text());
+    messageBox->exec();
+}
+
 void LogbookWidget::on_actionEdit_Flight_triggered()
 {
     emit ui->editFlightButton->clicked();
@@ -277,34 +289,37 @@ void LogbookWidget::on_tableView_doubleClicked()
     emit ui->editFlightButton->clicked();
 }
 
+void LogbookWidget::on_flightSearchComboBox_currentIndexChanged()
+{
+    emit ui->showAllButton->clicked();
+}
+
+void LogbookWidget::on_showAllButton_clicked()
+{
+    ui->flightSearchLlineEdit->setText(QString());
+    displayModel->setFilter(QString());
+    displayModel->select();
+}
+
 void LogbookWidget::on_flightSearchLlineEdit_textChanged(const QString &arg1)
 {
     if(arg1.length() == 0) {
-        DEB("Resetting filter...");
         displayModel->setFilter("");
         displayModel->select();
         return;
     }
 
     if (ui->flightSearchComboBox->currentIndex() < 3) {
-        displayModel->setFilter(filterMap.value(ui->flightSearchComboBox->currentIndex())
-                         + arg1 + "%\"");
-        //DEB("display model filter:" << displayModel->filter());
+        displayModel->setFilter(FILTER_MAP.value(ui->flightSearchComboBox->currentIndex())
+                                + arg1 + "%\"");
         return;
     } else if (ui->flightSearchComboBox->currentIndex() == 3) { // registration
-        displayModel->setFilter(filterMap.value(ui->flightSearchComboBox->currentIndex())
-                         + arg1 + "%\"");
-        //DEB("display model filter:" << displayModel->filter());
+        displayModel->setFilter(FILTER_MAP.value(ui->flightSearchComboBox->currentIndex())
+                                + arg1 + "%\"");
         return;
     } else if (ui->flightSearchComboBox->currentIndex() == 4) { // Name Pic
-        displayModel->setFilter(filterMap.value(ui->flightSearchComboBox->currentIndex())
-                         + arg1 + "%\"");
-        //DEB("display model filter:" << displayModel->filter());
+        displayModel->setFilter(FILTER_MAP.value(ui->flightSearchComboBox->currentIndex())
+                                + arg1 + "%\"");
         return;
     }
 }
-
-void LogbookWidget::on_flightSearchComboBox_currentIndexChanged()
-{
-    ui->flightSearchLlineEdit->setText(QString());
-}

+ 4 - 1
src/gui/widgets/logbookwidget.h

@@ -60,6 +60,9 @@ private slots:
 
     void on_actionDelete_Flight_triggered();
 
+    void onDeletedSuccessfully();
+    void onDeleteUnsuccessful(const QSqlError);
+
     void on_actionEdit_Flight_triggered();
 
     void on_tableView_doubleClicked();
@@ -79,7 +82,7 @@ private:
 
     QMenu* menu;
 
-    QMessageBox* nope;
+    QMessageBox* messageBox;
 
     QVector<qint32> selectedFlights;
 

+ 4 - 1
src/gui/widgets/logbookwidget.ui

@@ -63,9 +63,12 @@
    </item>
    <item row="1" column="2">
     <widget class="QLineEdit" name="flightSearchLlineEdit">
-     <property name="whatsThis">
+     <property name="toolTip">
       <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Enter the searchterm you want to filter your flights by.&lt;/p&gt;&lt;p&gt;For dates, make sure to use the format YYYY-MM-DD&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
      </property>
+     <property name="whatsThis">
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+     </property>
     </widget>
    </item>
    <item row="2" column="2" rowspan="2">