Browse Source

Merge pull request #24 from fiffty-50/develop-logbookwidget

Refactored Logbookwidget, on hold until completion of NewFlightDialog
Felix Turowsky 4 years ago
parent
commit
cd28d56a7f

+ 2 - 0
openPilotLog.pro

@@ -32,6 +32,7 @@ SOURCES += \
     src/experimental/aaircraftentry.cpp \
     src/experimental/adatabase.cpp \
     src/experimental/aentry.cpp \
+    src/experimental/aflightentry.cpp \
     src/experimental/apilotentry.cpp \
     src/experimental/atailentry.cpp \
     src/functions/acalc.cpp \
@@ -68,6 +69,7 @@ HEADERS += \
     src/experimental/aaircraftentry.h \
     src/experimental/adatabase.h \
     src/experimental/aentry.h \
+    src/experimental/aflightentry.h \
     src/experimental/apilotentry.h \
     src/experimental/atailentry.h \
     src/experimental/decl.h \

+ 9 - 1
src/database/adatabasesetup.cpp

@@ -234,6 +234,14 @@ const QString createViewTotals = "CREATE VIEW viewTotals AS "
         "CAST(SUM(toDay) AS INT) AS \"TO Day\", CAST(SUM(toNight) AS INT) AS \"TO Night\", "
         "CAST(SUM(ldgDay) AS INT) AS \"LDG Day\", CAST(SUM(ldgNight) AS INT) AS \"LDG Night\" "
         "FROM flights";
+
+/*const QString createViewPilotsTailsMap = "CREATE VIEW viewPilotsTailsMap AS "
+        "SELECT "
+        "pilot_id, piclastname, picfirstname, tail_id, registration "
+        "FROM pilots "
+        "LEFT JOIN tails "
+        "ON pilots.pilot_id = tails.tail_id";*/
+
 const QStringList tables = {
     createTablePilots,
     createTableTails,
@@ -248,7 +256,7 @@ const QStringList views = {
     createViewTails,
     createViewPilots,
     createViewTotals,
-    createViewQCompleter
+    createViewQCompleter,
 };
 const QStringList userTables = {
     "flights",

+ 77 - 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)
 {
@@ -288,6 +356,13 @@ AAircraftEntry ADataBase::getAircraftEntry(RowId row_id)
     return aircraft_entry;
 }
 
+AFlightEntry ADataBase::getFlightEntry(RowId row_id)
+{
+    AFlightEntry flight_entry(row_id);
+    flight_entry.setData(getEntryData(flight_entry.getPosition()));
+    return flight_entry;
+}
+
 const QStringList ADataBase::getCompletionList(ADataBase::CompleterTarget target)
 {
     QString statement;
@@ -374,6 +449,7 @@ QVector<QString> ADataBase::customQuery(QString statement, int return_values)
     if (!query.first()) {
         DEB("No result found. Check Query and Error.");
         DEB("Error: " << query.lastError().text());
+        DEB("Statement: " << statement);
         emit sqlError(query.lastError(), statement);
         return QVector<QString>();
     } else {

+ 18 - 0
src/experimental/adatabase.h

@@ -31,6 +31,7 @@
 #include "apilotentry.h"
 #include "atailentry.h"
 #include "aaircraftentry.h"
+#include "aflightentry.h"
 
 namespace experimental {
 
@@ -84,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,
@@ -106,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
      */
@@ -146,6 +154,16 @@ public:
      */
     AAircraftEntry getAircraftEntry(RowId row_id);
 
+    /*!
+     * \brief retreives a flight entry from the database.
+     *
+     * This function is a wrapper for DataBase::getEntry(DataPosition),
+     * where the table is already set and which returns an AFlightEntry
+     * instead of an AEntry. It allows for easy access to a flight entry
+     * with only the RowId required as input.
+     */
+    AFlightEntry getFlightEntry(RowId row_id);
+
     /*!
      * \brief getCompletionList returns a QStringList of values for a
      * QCompleter based on database values

+ 81 - 0
src/experimental/aflightentry.cpp

@@ -0,0 +1,81 @@
+#include "aflightentry.h"
+#include "src/experimental/adatabase.h"
+
+namespace experimental {
+
+AFlightEntry::AFlightEntry()
+    : AEntry::AEntry(DEFAULT_FLIGHT_POSITION)
+{}
+
+AFlightEntry::AFlightEntry(int row_id)
+    : AEntry::AEntry(DataPosition("flights", row_id))
+{}
+
+AFlightEntry::AFlightEntry(TableData table_data)
+    : AEntry::AEntry(DEFAULT_FLIGHT_POSITION, table_data)
+{}
+
+const QString AFlightEntry::summary()
+{
+    if(tableData.isEmpty())
+        return QString();
+
+    QString flight_summary;
+    flight_summary.append(tableData.value("doft") + " ");
+    flight_summary.append(tableData.value("dept") + " ");
+    flight_summary.append(ACalc::minutesToString(tableData.value("tofb")) + " ");
+    flight_summary.append(ACalc::minutesToString(tableData.value("tonb")) + " ");
+    flight_summary.append(tableData.value("dest") + " ");
+
+    return flight_summary;
+}
+
+const QString AFlightEntry::registration()
+{
+    QString tail_id = tableData.value("acft");
+    if(tail_id.isEmpty())
+        return QString();
+
+    QString statement = "SELECT registration "
+                        "FROM tails "
+                        "WHERE ROWID =" + tail_id;
+
+    auto tail_registration = aDB()->customQuery(statement, 1);
+
+    if(tail_registration.isEmpty()) {
+        return QString();
+    } else {
+        return tail_registration.first();
+    }
+}
+
+const QString AFlightEntry::pilotName(pilot pilot_)
+{
+    QString row_id;
+    switch (pilot_) {
+    case pilot::pic:
+        row_id = tableData.value("pic");
+        break;
+    case pilot::sic:
+        row_id = tableData.value("sic");
+        break;
+    case pilot::thirdPilot:
+        row_id = tableData.value("thirdPilot");
+        break;
+    }
+    if(row_id == QString())
+        return row_id;
+
+    QString statement = "SELECT piclastname||\", \"||picfirstname "
+                        "FROM pilots "
+                        "WHERE ROWID =" + row_id;
+
+    auto pilot_name = aDB()->customQuery(statement, 1);
+    if(pilot_name.isEmpty()) {
+        return QString();
+    } else {
+        return pilot_name.first();
+    }
+}
+
+} // namespace experimental

+ 39 - 0
src/experimental/aflightentry.h

@@ -0,0 +1,39 @@
+#ifndef AFLIGHTENTRY_H
+#define AFLIGHTENTRY_H
+
+#include "src/experimental/aentry.h"
+#include "src/functions/acalc.h"
+
+namespace experimental {
+
+class AFlightEntry : public AEntry {
+public:
+    AFlightEntry();
+    AFlightEntry(const AFlightEntry& pe) = default;
+    AFlightEntry& operator=(const AFlightEntry& pe) = default;
+    AFlightEntry(int row_id);
+    AFlightEntry(TableData table_data);
+
+    enum pilot {pic, sic, thirdPilot };
+
+    /*!
+     * \brief Returs a summary of the flight data
+     * \return "doft, dept, tofb, dest, tonb"
+     */
+    const QString summary();
+    /*!
+     * \brief Returns the tails' registration from the database.
+     */
+    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"
+     */
+    const QString pilotName(pilot);
+};
+
+} // namespace experimental
+
+#endif // AFLIGHTENTRY_H

+ 1 - 0
src/experimental/decl.h

@@ -40,6 +40,7 @@ struct DataPosition : QPair<TableName, RowId> {
 auto const DEFAULT_PILOT_POSITION = DataPosition("pilots", 0);
 auto const DEFAULT_TAIL_POSITION = DataPosition("tails", 0);
 auto const DEFAULT_AIRCRAFT_POSITION = DataPosition("aircraft", 0);
+auto const DEFAULT_FLIGHT_POSITION = DataPosition("flights", 0);
 
 }
 

+ 1 - 1
src/gui/widgets/aircraftwidget.cpp

@@ -68,6 +68,7 @@ void AircraftWidget::setupModelAndView()
     view->sortByColumn(sortColumn, Qt::DescendingOrder);
 
     view->show();
+    selection = view->selectionModel();
 
     QObject::connect(ui->tableView->selectionModel(), &QItemSelectionModel::selectionChanged,
                      this, &AircraftWidget::tableView_selectionChanged);
@@ -155,7 +156,6 @@ void AircraftWidget::tableView_selectionChanged()
         /// stack does not seem to solve the problem since the Dialog does not get destroyed
         /// until either accept() or reject() is emitted so I went for this solution.
     }
-    auto *selection = ui->tableView->selectionModel();
     selectedTails.clear();
 
     for (const auto& row : selection->selectedRows()) {

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

@@ -62,6 +62,8 @@ private:
 
     QTableView *view;
 
+    QItemSelectionModel* selection;
+
     qint32 sortColumn;
 
     QVector<qint32> selectedTails;

+ 1 - 24
src/gui/widgets/debugwidget.cpp

@@ -164,33 +164,10 @@ void DebugWidget::on_importCsvPushButton_clicked()
 
 void DebugWidget::on_debugPushButton_clicked()
 {
-    qlonglong number_of_runs = 5000;
-    long time1 = 0;
-    long time2 = 0;
-    using namespace experimental;
-    {
-        ATimer timer;
-        for (int i = 0; i < number_of_runs; i++) {
-            // first block, do stuff here...
-            aDB()->getEntry({"pilots", i});
-        }
-
-        time1 = timer.timeNow();
-    }
-    {
-        ATimer timer;
-        for (int i = 0; i < number_of_runs; i++) {
-            // second block, do stuff here...
-            aDB()->getPilotEntry(i);
-        }
-        time2 = timer.timeNow();
-    }
 
-    DEB("First block executed  " << number_of_runs << " times for a total of " << time1 << " milliseconds.");
-    DEB("Second block executed " << number_of_runs << " times for a total of " << time2 << " milliseconds.");
 }
 
-/*
+/* //Comparing two functions template
     qlonglong number_of_runs = 5000;
     long time1 = 0;
     long time2 = 0;

+ 140 - 90
src/gui/widgets/logbookwidget.cpp

@@ -19,13 +19,20 @@
 #include "ui_logbookwidget.h"
 #include "src/testing/adebug.h"
 
+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");
+
 LogbookWidget::LogbookWidget(QWidget *parent) :
     QWidget(parent),
     ui(new Ui::LogbookWidget)
 {
     ui->setupUi(this);
-    ui->filterDateEdit->setDate(QDate::currentDate());
-    ui->filterDateEdit_2->setDate(QDate::currentDate());
     ui->newFlightButton->setFocus();
 
     //customContextMenu for tablewidget
@@ -33,10 +40,11 @@ LogbookWidget::LogbookWidget(QWidget *parent) :
     menu->addAction(ui->actionEdit_Flight);
     menu->addAction(ui->actionDelete_Flight);
 
-    //message Box
-    nope = new QMessageBox(this);
+    //Initialise message Box
+    messageBox = new QMessageBox(this);
 
-    refreshView(ASettings::read("logbook/view").toInt());
+    prepareModelAndView(ASettings::read("logbook/view").toInt());
+    connectSignalsAndSlots();
 }
 
 LogbookWidget::~LogbookWidget()
@@ -48,40 +56,41 @@ LogbookWidget::~LogbookWidget()
  * Functions
  */
 
-void LogbookWidget::refreshView(int view_id)
+void LogbookWidget::prepareModelAndView(int view_id)
 {
     switch (view_id) {
     case 0:
-        defaultView();
+        setupDefaultView();
         break;
     case 1:
-        easaView();
+        setupEasaView();
         break;
     default:
-        defaultView();
+        setupDefaultView();
     }
-    QTableView *view = ui->tableView;
-    view->setSelectionBehavior(QAbstractItemView::SelectRows);
-    view->setSelectionMode(QAbstractItemView::ExtendedSelection);
-    view->setEditTriggers(QAbstractItemView::NoEditTriggers);
-    view->setContextMenuPolicy(Qt::CustomContextMenu);
-    view->horizontalHeader()->setStretchLastSection(QHeaderView::Stretch);
-    view->verticalHeader()->hide();
-    view->setAlternatingRowColors(true);
-    view->hideColumn(0);
-    connect(ui->tableView->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
-            this, SLOT(tableView_selectionChanged()));
 }
 
-void LogbookWidget::defaultView()
+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()
 {
     DEB("Loading Default View...");
-    QSqlTableModel *model = new QSqlTableModel;
-    model->setTable("viewDefault");
-    model->select();
+    displayModel = new QSqlTableModel;
+    displayModel->setTable("viewDefault");
+    displayModel->select();
 
-    QTableView *view = ui->tableView;
-    view->setModel(model);
+    view = ui->tableView;
+    view->setModel(displayModel);
 
     view->setColumnWidth(1, 120);
     view->setColumnWidth(2, 60);
@@ -94,18 +103,27 @@ void LogbookWidget::defaultView()
     view->setColumnWidth(9, 120);
     view->setColumnWidth(10, 90);
 
+    view->setSelectionBehavior(QAbstractItemView::SelectRows);
+    view->setSelectionMode(QAbstractItemView::ExtendedSelection);
+    view->setEditTriggers(QAbstractItemView::NoEditTriggers);
+    view->setContextMenuPolicy(Qt::CustomContextMenu);
+    view->horizontalHeader()->setStretchLastSection(QHeaderView::Stretch);
+    view->verticalHeader()->hide();
+    view->setAlternatingRowColors(true);
+    view->hideColumn(0);
+
     view->show();
 }
 
-void LogbookWidget::easaView()
+void LogbookWidget::setupEasaView()
 {
     DEB("Loading EASA View...");
-    QSqlTableModel *model = new QSqlTableModel;
-    model->setTable("viewEASA");
-    model->select();
+    displayModel = new QSqlTableModel;
+    displayModel->setTable("viewEASA");
+    displayModel->select();
 
-    QTableView *view = ui->tableView;
-    view->setModel(model);
+    view = ui->tableView;
+    view->setModel(displayModel);
 
     view->setColumnWidth(1,120);
     view->setColumnWidth(2,60);
@@ -129,6 +147,15 @@ void LogbookWidget::easaView()
     view->setColumnWidth(20,60);
     view->setColumnWidth(21,120);
 
+    view->setSelectionBehavior(QAbstractItemView::SelectRows);
+    view->setSelectionMode(QAbstractItemView::ExtendedSelection);
+    view->setEditTriggers(QAbstractItemView::NoEditTriggers);
+    view->setContextMenuPolicy(Qt::CustomContextMenu);
+    view->horizontalHeader()->setStretchLastSection(QHeaderView::Stretch);
+    view->verticalHeader()->hide();
+    view->setAlternatingRowColors(true);
+    view->hideColumn(0);
+
     view->show();
 }
 
@@ -136,13 +163,11 @@ void LogbookWidget::easaView()
  * Slots
  */
 
-void LogbookWidget::tableView_selectionChanged()//
+void LogbookWidget::flightsTableView_selectionChanged()//
 {
-    auto *selection = ui->tableView->selectionModel();
-
     selectedFlights.clear();
     for (const auto& row : selection->selectedRows()) {
-        selectedFlights << row.data().toInt();
+        selectedFlights.append(row.data().toInt());
         DEB("Selected Flight(s) with ID: " << selectedFlights);
     }
 }
@@ -152,7 +177,7 @@ void LogbookWidget::on_newFlightButton_clicked()
     auto nf = new NewFlightDialog(this, Db::createNew);
     nf->setAttribute(Qt::WA_DeleteOnClose);
     nf->exec();
-    refreshView(ASettings::read("logbook/view").toInt());
+    displayModel->select();
 }
 
 void LogbookWidget::on_editFlightButton_clicked()
@@ -161,33 +186,36 @@ void LogbookWidget::on_editFlightButton_clicked()
         auto ef = new NewFlightDialog(this,Flight(selectedFlights.first()), Db::editExisting);
         ef->setAttribute(Qt::WA_DeleteOnClose);
         ef->exec();
-        refreshView(ASettings::read("logbook/view").toInt());
+        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?");
@@ -200,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);
             }
-            refreshView(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);
@@ -223,45 +246,37 @@ 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});
             }
-            refreshView(ASettings::read("logbook/view").toInt());
+            experimental::aDB()->removeMany(selected_flights);
+            displayModel->select();
         }
     }
 }
 
-void LogbookWidget::on_filterFlightsByDateButton_clicked()
+void LogbookWidget::on_tableView_customContextMenuRequested(const QPoint &pos)
 {
-    QDate date(ui->filterDateEdit->date());
-    QString startdate = date.toString("yyyy-MM-dd");
-    date = ui->filterDateEdit_2->date();
-    QString enddate = date.toString("yyyy-MM-dd");
-    QString datefilter = "Date BETWEEN '" + startdate + "' AND '" + enddate + QLatin1Char('\'');
-
-    QSqlTableModel *DateFilteredModel = new QSqlTableModel;
-    DateFilteredModel ->setTable("Logbook");
-    DateFilteredModel ->setFilter(datefilter);
-    DateFilteredModel->select();
-
-    ui->tableView->setModel(DateFilteredModel);
+    menu->popup(ui->tableView->viewport()->mapToGlobal(pos));
 }
 
-void LogbookWidget::on_showAllButton_clicked()
+void LogbookWidget::on_actionDelete_Flight_triggered()
 {
-    refreshView(ASettings::read("logbook/view").toInt());
+    emit ui->deleteFlightPushButton->clicked();
 }
 
-void LogbookWidget::on_tableView_customContextMenuRequested(const QPoint &pos)
+void LogbookWidget::onDeletedSuccessfully()
 {
-    menu->popup(ui->tableView->viewport()->mapToGlobal(pos));
+    messageBox->setText(QString::number(selectedFlights.length()) + " flights have been deleted.");
+    messageBox->exec();
 }
 
-void LogbookWidget::on_actionDelete_Flight_triggered()
+void LogbookWidget::onDeleteUnsuccessful(const QSqlError error)
 {
-    emit ui->deleteFlightPushButton->clicked();
+    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()
@@ -273,3 +288,38 @@ 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) {
+        displayModel->setFilter("");
+        displayModel->select();
+        return;
+    }
+
+    if (ui->flightSearchComboBox->currentIndex() < 3) {
+        displayModel->setFilter(FILTER_MAP.value(ui->flightSearchComboBox->currentIndex())
+                                + arg1 + "%\"");
+        return;
+    } else if (ui->flightSearchComboBox->currentIndex() == 3) { // registration
+        displayModel->setFilter(FILTER_MAP.value(ui->flightSearchComboBox->currentIndex())
+                                + arg1 + "%\"");
+        return;
+    } else if (ui->flightSearchComboBox->currentIndex() == 4) { // Name Pic
+        displayModel->setFilter(FILTER_MAP.value(ui->flightSearchComboBox->currentIndex())
+                                + arg1 + "%\"");
+        return;
+    }
+}

+ 24 - 12
src/gui/widgets/logbookwidget.h

@@ -25,29 +25,26 @@
 #include <chrono>
 #include <QDebug>
 #include <QMenu>
+#include <QTableView>
 
 #include "src/classes/asettings.h"
 #include "src/database/db.h"
 #include "src/classes/flight.h"
 #include "src/gui/dialogues/newflightdialog.h"
+#include "src/experimental/aflightentry.h"
 
 namespace Ui {
 class LogbookWidget;
 }
 
-
-
 class LogbookWidget : public QWidget
 {
     Q_OBJECT
 
-
 public:
     explicit LogbookWidget(QWidget *parent = nullptr);
     ~LogbookWidget();
 
-    QVector<qint32> selectedFlights;
-
 private slots:
     void on_newFlightButton_clicked();
 
@@ -55,32 +52,47 @@ private slots:
 
     void on_deleteFlightPushButton_clicked();
 
-    void on_filterFlightsByDateButton_clicked();
-
     void on_showAllButton_clicked();
 
-    void tableView_selectionChanged();
+    void flightsTableView_selectionChanged();
 
     void on_tableView_customContextMenuRequested(const QPoint &pos);
 
     void on_actionDelete_Flight_triggered();
 
+    void onDeletedSuccessfully();
+    void onDeleteUnsuccessful(const QSqlError);
+
     void on_actionEdit_Flight_triggered();
 
     void on_tableView_doubleClicked();
 
+    void on_flightSearchLlineEdit_textChanged(const QString &arg1);
+
+    void on_flightSearchComboBox_currentIndexChanged();
+
 private:
     Ui::LogbookWidget *ui;
 
+    QTableView* view;
+
+    QSqlTableModel* displayModel;
+
+    QItemSelectionModel* selection;
+
     QMenu* menu;
 
-    QMessageBox* nope;
+    QMessageBox* messageBox;
+
+    QVector<qint32> selectedFlights;
+
+    void prepareModelAndView(int view_id);
 
-    void refreshView(int view_id);
+    void setupDefaultView();
 
-    void defaultView();
+    void setupEasaView();
 
-    void easaView();
+    void connectSignalsAndSlots();
 
 
 };

+ 118 - 73
src/gui/widgets/logbookwidget.ui

@@ -6,114 +6,159 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>1353</width>
-    <height>613</height>
+    <width>1280</width>
+    <height>720</height>
    </rect>
   </property>
   <property name="windowTitle">
    <string>Form</string>
   </property>
   <layout class="QGridLayout" name="gridLayout">
-   <item row="2" column="0">
-    <widget class="QPushButton" name="editFlightButton">
-     <property name="text">
-      <string>Edit Flight</string>
+   <item row="0" column="0" colspan="3">
+    <widget class="QTableView" name="tableView">
+     <property name="font">
+      <font>
+       <family>Cantarell</family>
+      </font>
+     </property>
+     <property name="styleSheet">
+      <string notr="true"/>
+     </property>
+     <property name="selectionMode">
+      <enum>QAbstractItemView::SingleSelection</enum>
+     </property>
+     <property name="selectionBehavior">
+      <enum>QAbstractItemView::SelectRows</enum>
      </property>
     </widget>
    </item>
-   <item row="3" column="0">
-    <widget class="QPushButton" name="deleteFlightPushButton">
+   <item row="1" column="0" rowspan="2">
+    <widget class="QPushButton" name="newFlightButton">
+     <property name="minimumSize">
+      <size>
+       <width>200</width>
+       <height>0</height>
+      </size>
+     </property>
      <property name="text">
-      <string>Delete Flight</string>
+      <string>New Flight</string>
      </property>
     </widget>
    </item>
    <item row="1" column="1">
-    <widget class="QDateEdit" name="filterDateEdit">
-     <property name="dateTime">
-      <datetime>
-       <hour>23</hour>
-       <minute>0</minute>
-       <second>0</second>
-       <year>1900</year>
-       <month>1</month>
-       <day>1</day>
-      </datetime>
-     </property>
-     <property name="displayFormat">
-      <string>yyyy-MM-dd</string>
-     </property>
-     <property name="calendarPopup">
-      <bool>true</bool>
-     </property>
-     <property name="timeSpec">
-      <enum>Qt::UTC</enum>
-     </property>
-     <property name="date">
-      <date>
-       <year>1900</year>
-       <month>1</month>
-       <day>1</day>
-      </date>
+    <widget class="QLabel" name="flightSearchLabel">
+     <property name="minimumSize">
+      <size>
+       <width>200</width>
+       <height>0</height>
+      </size>
+     </property>
+     <property name="text">
+      <string>Search Flight</string>
+     </property>
+     <property name="alignment">
+      <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
      </property>
     </widget>
    </item>
    <item row="1" column="2">
-    <widget class="QDateEdit" name="filterDateEdit_2">
-     <property name="dateTime">
-      <datetime>
-       <hour>23</hour>
-       <minute>0</minute>
-       <second>0</second>
-       <year>2019</year>
-       <month>12</month>
-       <day>13</day>
-      </datetime>
-     </property>
-     <property name="displayFormat">
-      <string>yyyy-MM-dd</string>
-     </property>
-     <property name="calendarPopup">
-      <bool>true</bool>
-     </property>
-     <property name="timeSpec">
-      <enum>Qt::UTC</enum>
+    <widget class="QLineEdit" name="flightSearchLlineEdit">
+     <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="1" colspan="2">
-    <widget class="QPushButton" name="filterFlightsByDateButton">
+   <item row="2" column="2" rowspan="2">
+    <widget class="QComboBox" name="flightSearchComboBox">
+     <item>
+      <property name="text">
+       <string>Date of Flight</string>
+      </property>
+     </item>
+     <item>
+      <property name="text">
+       <string>Departure Airport</string>
+      </property>
+     </item>
+     <item>
+      <property name="text">
+       <string>Destination Airport</string>
+      </property>
+     </item>
+     <item>
+      <property name="text">
+       <string>Aircraft Registration</string>
+      </property>
+     </item>
+     <item>
+      <property name="text">
+       <string>Pilot Name</string>
+      </property>
+     </item>
+    </widget>
+   </item>
+   <item row="3" column="0">
+    <widget class="QPushButton" name="editFlightButton">
+     <property name="minimumSize">
+      <size>
+       <width>200</width>
+       <height>0</height>
+      </size>
+     </property>
      <property name="text">
-      <string>Filter Flights by Date</string>
+      <string>Edit Flight</string>
      </property>
     </widget>
    </item>
-   <item row="1" column="0">
-    <widget class="QPushButton" name="newFlightButton">
+   <item row="3" column="1">
+    <widget class="QLabel" name="flightSearchInLabel">
+     <property name="minimumSize">
+      <size>
+       <width>200</width>
+       <height>0</height>
+      </size>
+     </property>
      <property name="text">
-      <string>New Flight</string>
+      <string>Search in</string>
+     </property>
+     <property name="alignment">
+      <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
      </property>
     </widget>
    </item>
-   <item row="0" column="0" colspan="3">
-    <widget class="QTableView" name="tableView">
-     <property name="font">
-      <font>
-       <family>Cantarell</family>
-      </font>
+   <item row="4" column="0">
+    <widget class="QPushButton" name="deleteFlightPushButton">
+     <property name="minimumSize">
+      <size>
+       <width>200</width>
+       <height>0</height>
+      </size>
      </property>
-     <property name="styleSheet">
-      <string notr="true"/>
+     <property name="text">
+      <string>Delete Flight</string>
      </property>
-     <property name="selectionMode">
-      <enum>QAbstractItemView::SingleSelection</enum>
+    </widget>
+   </item>
+   <item row="4" column="1">
+    <widget class="QLabel" name="spacerLabel">
+     <property name="minimumSize">
+      <size>
+       <width>200</width>
+       <height>0</height>
+      </size>
      </property>
-     <property name="selectionBehavior">
-      <enum>QAbstractItemView::SelectRows</enum>
+     <property name="text">
+      <string/>
+     </property>
+     <property name="alignment">
+      <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
      </property>
     </widget>
    </item>
-   <item row="3" column="1" colspan="2">
+   <item row="4" column="2">
     <widget class="QPushButton" name="showAllButton">
      <property name="text">
       <string>Show All Flights</string>

+ 3 - 0
src/gui/widgets/pilotswidget.cpp

@@ -57,6 +57,9 @@ void PilotsWidget::setupModelAndView()
     view->setSortingEnabled(true);
     view->sortByColumn(sortColumn, Qt::AscendingOrder);
 
+    view->show();
+    selection = view->selectionModel();
+
     QObject::connect(ui->pilotsTableView->selectionModel(), &QItemSelectionModel::selectionChanged,
                      this, &PilotsWidget::tableView_selectionChanged);
     QObject::connect(ui->pilotsTableView->horizontalHeader(), &QHeaderView::sectionClicked,

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

@@ -62,6 +62,8 @@ private:
 
     QTableView *view;
 
+    QItemSelectionModel* selection;
+
     qint32 sortColumn;
 
     QVector<qint32> selectedPilots;