Browse Source

Merge pull request #87 from fiffty-50/develop-simulator

Develop simulator
Felix Turowsky 3 years ago
parent
commit
6369d92a03
50 changed files with 1548 additions and 643 deletions
  1. 82 55
      CMakeLists.txt
  2. 4 4
      main.cpp
  3. 61 23
      mainwindow.cpp
  4. 24 11
      mainwindow.h
  5. 13 2
      mainwindow.ui
  6. 3 3
      src/classes/aaircraftentry.cpp
  7. 4 4
      src/classes/acurrencyentry.cpp
  8. 2 0
      src/classes/aentry.h
  9. 13 13
      src/classes/aflightentry.cpp
  10. 4 4
      src/classes/ajson.cpp
  11. 6 6
      src/classes/apilotentry.cpp
  12. 18 0
      src/classes/asimulatorentry.cpp
  13. 38 0
      src/classes/asimulatorentry.h
  14. 57 11
      src/classes/astyle.cpp
  15. 6 0
      src/classes/astyle.h
  16. 10 10
      src/classes/atailentry.cpp
  17. 4 4
      src/classes/atranslator.cpp
  18. 2 2
      src/classes/atranslator.h
  19. 14 7
      src/database/adatabase.cpp
  20. 26 6
      src/database/adatabase.h
  21. 172 53
      src/database/adbsetup.cpp
  22. 20 20
      src/functions/acalc.cpp
  23. 16 11
      src/functions/adate.cpp
  24. 17 11
      src/functions/adate.h
  25. 3 3
      src/functions/adatetime.h
  26. 12 12
      src/functions/atime.h
  27. 12 10
      src/gui/dialogues/firstrundialog.cpp
  28. 1 12
      src/gui/dialogues/firstrundialog.ui
  29. 120 91
      src/gui/dialogues/newflightdialog.cpp
  30. 3 1
      src/gui/dialogues/newflightdialog.h
  31. 4 1
      src/gui/dialogues/newflightdialog.ui
  32. 3 3
      src/gui/dialogues/newpilot.ui
  33. 187 0
      src/gui/dialogues/newsimdialog.cpp
  34. 52 0
      src/gui/dialogues/newsimdialog.h
  35. 174 0
      src/gui/dialogues/newsimdialog.ui
  36. 8 8
      src/gui/dialogues/newtaildialog.cpp
  37. 2 2
      src/gui/widgets/backupwidget.cpp
  38. 4 2
      src/gui/widgets/homewidget.cpp
  39. 65 52
      src/gui/widgets/logbookwidget.cpp
  40. 17 6
      src/gui/widgets/logbookwidget.h
  41. 14 5
      src/gui/widgets/logbookwidget.ui
  42. 34 33
      src/gui/widgets/settingswidget.cpp
  43. 2 2
      src/gui/widgets/settingswidget.h
  44. 1 11
      src/gui/widgets/settingswidget.ui
  45. 40 0
      src/opl.cpp
  46. 127 82
      src/opl.h
  47. 2 2
      src/testing/importCrewlounge/importcrewlounge.cpp
  48. 13 13
      src/testing/importCrewlounge/processaircraft.cpp
  49. 25 25
      src/testing/importCrewlounge/processflights.cpp
  50. 7 7
      src/testing/importCrewlounge/processpilots.cpp

+ 82 - 55
CMakeLists.txt

@@ -21,101 +21,117 @@ find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets Sql Network LinguistTools
 # find_package(OpenSSL REQUIRED) # Pending testing
 
 set(PROJECT_SOURCES
+
     main.cpp
+    src/opl.h
+    src/opl.cpp
+
+    # GUI
+    mainwindow.h
     mainwindow.cpp
-    src/classes/acompletiondata.cpp
-    src/classes/acurrencyentry.cpp
-    src/classes/astyle.cpp
-    src/classes/astandardpaths.cpp
-    src/classes/aaircraftentry.cpp
-    src/classes/adownload.cpp
-    src/classes/aentry.cpp
-    src/classes/aflightentry.cpp
-    src/classes/apilotentry.cpp
-    src/classes/arunguard.cpp
-    src/classes/asettings.cpp
-    src/classes/atailentry.cpp
-    src/classes/atranslator.cpp
-    src/classes/ajson.cpp
-    src/classes/ahash.cpp
-    src/database/adatabase.cpp
-    src/database/adbsetup.cpp
-    src/functions/acalc.cpp
-    src/functions/alog.cpp
-    src/functions/areadcsv.cpp
-    src/functions/astat.cpp
-    src/functions/adate.cpp
+    mainwindow.ui
+    # Dialogs
+    src/gui/dialogues/firstrundialog.h
     src/gui/dialogues/firstrundialog.cpp
+    src/gui/dialogues/firstrundialog.ui
+    src/gui/dialogues/newflightdialog.h
     src/gui/dialogues/newflightdialog.cpp
+    src/gui/dialogues/newflightdialog.ui
+    src/gui/dialogues/newpilotdialog.h
     src/gui/dialogues/newpilotdialog.cpp
+    src/gui/dialogues/newpilot.ui
+    src/gui/dialogues/newtaildialog.h
     src/gui/dialogues/newtaildialog.cpp
+    src/gui/dialogues/newtail.ui
+    src/gui/dialogues/newsimdialog.h
+    src/gui/dialogues/newsimdialog.cpp
+    src/gui/dialogues/newsimdialog.ui
+
+    # Widgets
+    src/gui/widgets/aircraftwidget.h
     src/gui/widgets/aircraftwidget.cpp
+    src/gui/widgets/aircraftwidget.ui
+    src/gui/widgets/backupwidget.h
     src/gui/widgets/backupwidget.cpp
+    src/gui/widgets/backupwidget.ui
+    src/gui/widgets/debugwidget.h
     src/gui/widgets/debugwidget.cpp
+    src/gui/widgets/debugwidget.ui
+    src/gui/widgets/homewidget.h
     src/gui/widgets/homewidget.cpp
+    src/gui/widgets/homewidget.ui
+    src/gui/widgets/logbookwidget.h
     src/gui/widgets/logbookwidget.cpp
+    src/gui/widgets/logbookwidget.ui
+    src/gui/widgets/pilotswidget.h
     src/gui/widgets/pilotswidget.cpp
+    src/gui/widgets/pilotswidget.ui
     src/gui/widgets/settingswidget.cpp
-    src/testing/atimer.cpp
-    
-    src/opl.h
-    mainwindow.h
+    src/gui/widgets/settingswidget.h
+    src/gui/widgets/settingswidget.ui
+
+    # Classes
     src/classes/acompletiondata.h
+    src/classes/acompletiondata.cpp
     src/classes/acurrencyentry.h
+    src/classes/acurrencyentry.cpp
     src/classes/astyle.h
+    src/classes/astyle.cpp
     src/classes/astandardpaths.h
+    src/classes/astandardpaths.cpp
     src/classes/aaircraftentry.h
+    src/classes/aaircraftentry.cpp
     src/classes/adownload.h
+    src/classes/adownload.cpp
     src/classes/aentry.h
+    src/classes/aentry.cpp
     src/classes/aflightentry.h
+    src/classes/aflightentry.cpp
     src/classes/apilotentry.h
+    src/classes/apilotentry.cpp
     src/classes/arunguard.h
+    src/classes/arunguard.cpp
     src/classes/asettings.h
+    src/classes/asettings.cpp
     src/classes/atailentry.h
+    src/classes/atailentry.cpp
     src/classes/atranslator.h
+    src/classes/atranslator.cpp
     src/classes/ajson.h
+    src/classes/ajson.cpp
     src/classes/ahash.h
-    src/database/adatabase.h
-    src/database/adbsetup.h
-    src/database/adatabasetypes.h
+    src/classes/ahash.cpp
+    src/classes/asimulatorentry.h
+    src/classes/asimulatorentry.cpp
+
+    # Namespaces
     src/functions/acalc.h
+    src/functions/acalc.cpp
     src/functions/adatetime.h
     src/functions/alog.h
+    src/functions/alog.cpp
     src/functions/areadcsv.h
+    src/functions/areadcsv.cpp
     src/functions/astat.h
+    src/functions/astat.cpp
     src/functions/adate.h
+    src/functions/adate.cpp
     src/functions/atime.h
-    src/gui/dialogues/firstrundialog.h
-    src/gui/dialogues/newflightdialog.h
-    src/gui/dialogues/newpilotdialog.h
-    src/gui/dialogues/newtaildialog.h
-    src/gui/widgets/aircraftwidget.h
-    src/gui/widgets/backupwidget.h
-    src/gui/widgets/debugwidget.h
-    src/gui/widgets/homewidget.h
-    src/gui/widgets/logbookwidget.h
-    src/gui/widgets/pilotswidget.h
-    src/gui/widgets/settingswidget.h
-    src/testing/atimer.h
-    
-    mainwindow.ui
-    src/gui/dialogues/firstrundialog.ui
-    src/gui/dialogues/newflightdialog.ui
-    src/gui/dialogues/newpilot.ui
-    src/gui/dialogues/newtail.ui
-    src/gui/widgets/aircraftwidget.ui
-    src/gui/widgets/backupwidget.ui
-    src/gui/widgets/debugwidget.ui
-    src/gui/widgets/homewidget.ui
-    src/gui/widgets/logbookwidget.ui
-    src/gui/widgets/pilotswidget.ui
-    src/gui/widgets/settingswidget.ui
 
+    # Database
+    src/database/adatabasetypes.h
+    src/database/adatabase.h
+    src/database/adatabase.cpp
+    src/database/adbsetup.h
+    src/database/adbsetup.cpp
+
+    # Ressources
     assets/icons.qrc
+    assets/templates.qrc
     assets/themes/stylesheets/breeze/breeze.qrc
     assets/themes/stylesheets/qdarkstyle/qdarkstyle.qrc
-    assets/templates.qrc
 
+    # Testing / Debug
     src/testing/importCrewlounge/importcrewlounge.h
     src/testing/importCrewlounge/importcrewlounge.cpp
     src/testing/importCrewlounge/processpilots.h
@@ -124,6 +140,8 @@ set(PROJECT_SOURCES
     src/testing/importCrewlounge/processaircraft.cpp
     src/testing/importCrewlounge/processflights.h
     src/testing/importCrewlounge/processflights.cpp
+    src/testing/atimer.h
+    src/testing/atimer.cpp
 )
 
 # This is currently a bit buggy, see
@@ -146,6 +164,15 @@ set(PROJECT_SOURCES
 #    endif(Qt5Widgets_VERSION VERSION_LESS 5.15.0)
 #endif(Qt5Widgets_FOUND)
 
+# Disable Debug output for Release Build
+if(CMAKE_BUILD_TYPE STREQUAL "Debug")
+    message("Build type: Debug")
+elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
+    message("Build type: Release")
+    add_definitions(-DQT_NO_DEBUG_OUTPUT)
+endif()
+
+
 if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
     qt_add_executable(openPilotLog
         ${PROJECT_SOURCES}

+ 4 - 4
main.cpp

@@ -64,7 +64,7 @@ void init()
     AStyle::setup();
     // Translations to be done at a later stage
     //LOG << "Installing translator...";
-    //ATranslator::installTranslator(Opl::Translations::English);
+    //ATranslator::installTranslator(OPL::Translations::English);
 }
 
 bool firstRun()
@@ -104,9 +104,9 @@ int main(int argc, char *argv[])
     // Create Main Window and set Window Icon acc. to Platform
     MainWindow w;
 #ifdef __linux__
-    w.setWindowIcon(QIcon(Opl::Assets::ICON_APPICON_LINUX));
+    w.setWindowIcon(QIcon(OPL::Assets::ICON_APPICON_LINUX));
 #elif defined(_WIN32) || defined(_WIN64)
-    w.setWindowIcon(QIcon(Opl::Assets::ICON_APPICON_WIN));
+    w.setWindowIcon(QIcon(OPL::Assets::ICON_APPICON_WIN));
 #elif __APPLE__
     #include <TargetConditionals.h>
     #if TARGET_IPHONE_SIMULATOR
@@ -114,7 +114,7 @@ int main(int argc, char *argv[])
     #elif TARGET_OS_IPHONE
         // iOS device
     #elif TARGET_OS_MAC
-    w.setWindowIcon(QIcon(Opl::Assets::ICON_APPICON_IOS));
+    w.setWindowIcon(QIcon(OPL::Assets::ICON_APPICON_IOS));
     #else
     #   error "Unknown Apple platform"
     #endif

+ 61 - 23
mainwindow.cpp

@@ -26,11 +26,12 @@
 #include "src/functions/adatetime.h"
 #include "src/classes/aentry.h"
 
-
+#include "src/gui/dialogues/newsimdialog.h"
 // Quick and dirty Debug area
 void MainWindow::doDebugStuff()
 {
-
+    auto nsd = new NewSimDialog(1, this);
+    nsd->exec();
 }
 
 MainWindow::MainWindow(QWidget *parent)
@@ -38,6 +39,9 @@ MainWindow::MainWindow(QWidget *parent)
     , ui(new Ui::MainWindow)
 {
     ui->setupUi(this);
+    setupToolbar();
+    setActionIcons(AStyle::getStyleType());
+
     // connect to the Database
     QFileInfo database_file(AStandardPaths::directory(AStandardPaths::Database).
                                          absoluteFilePath(QStringLiteral("logbook.db")));
@@ -45,8 +49,7 @@ MainWindow::MainWindow(QWidget *parent)
     if (!database_file.exists()) {
         WARN(tr("Error: Database file not found."));
         db_invalid = true;
-    }
-    if (database_file.size() == 0) { // To Do: Check for database errors instead of just checking for empty
+    } else if (database_file.size() == 0) { // To Do: Check for database errors instead of just checking for empty
         WARN(tr("Database file invalid."));
         db_invalid = true;
     }
@@ -84,42 +87,68 @@ MainWindow::MainWindow(QWidget *parent)
     // Startup Screen (Home Screen)
     ui->stackedWidget->setCurrentWidget(homeWidget);
 
+    // check database version (Debug)
+    if (aDB->dbRevision() < aDB->getMinimumDatabaseRevision()) {
+        QString message = tr("Your database is out of date."
+                             "Minimum required revision: %1<br>"
+                             "You have revision: %2<br>")
+                             .arg(aDB->getMinimumDatabaseRevision(), aDB->dbRevision());
+        WARN(message);
+    }
+}
+
+MainWindow::~MainWindow()
+{
+    delete ui;
+}
+
+void MainWindow::setupToolbar()
+{
     // Create and set up the toolbar
     auto *toolBar = new QToolBar(this);
 
-    ui->actionHome->setIcon(QIcon(Opl::Assets::ICON_TOOLBAR_HOME));
     toolBar->addAction(ui->actionHome);
-    ui->actionNewFlight->setIcon(QIcon(Opl::Assets::ICON_TOOLBAR_NEW_FLIGHT));
     toolBar->addAction(ui->actionNewFlight);
-    ui->actionLogbook->setIcon(QIcon(Opl::Assets::ICON_TOOLBAR_LOGBOOK));
+    toolBar->addAction(ui->actionNewSim);
     toolBar->addAction(ui->actionLogbook);
-    ui->actionAircraft->setIcon(QIcon(Opl::Assets::ICON_TOOLBAR_AIRCRAFT));
     toolBar->addAction(ui->actionAircraft);
-    ui->actionPilots->setIcon(QIcon(Opl::Assets::ICON_TOOLBAR_PILOT));
     toolBar->addAction(ui->actionPilots);
-    ui->actionBackup->setIcon(QIcon(Opl::Assets::ICON_TOOLBAR_BACKUP));
     toolBar->addAction(ui->actionBackup);
-    ui->actionSettings->setIcon(QIcon(Opl::Assets::ICON_TOOLBAR_SETTINGS));
     toolBar->addAction(ui->actionSettings);
-    ui->actionQuit->setIcon(QIcon(Opl::Assets::ICON_TOOLBAR_QUIT));
     toolBar->addAction(ui->actionQuit);
     toolBar->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
     toolBar->setMovable(false);
     addToolBar(Qt::ToolBarArea::LeftToolBarArea, toolBar);
-
-    // check database version (Debug)
-    if (aDB->dbRevision() < aDB->getMinimumDatabaseRevision()) {
-        QString message = tr("Your database is out of date."
-                             "Minimum required revision: %1<br>"
-                             "You have revision: %2<br>")
-                             .arg(aDB->getMinimumDatabaseRevision(), aDB->dbRevision());
-        WARN(message);
-    }
 }
 
-MainWindow::~MainWindow()
+void MainWindow::setActionIcons(StyleType style)
 {
-    delete ui;
+    switch (style){
+    case StyleType::Light:
+        LOG << "Setting Light Icon theme";
+        ui->actionHome->setIcon(QIcon(OPL::Assets::ICON_TOOLBAR_HOME));
+        ui->actionNewFlight->setIcon(QIcon(OPL::Assets::ICON_TOOLBAR_NEW_FLIGHT));
+        ui->actionNewSim->setIcon(QIcon(OPL::Assets::ICON_TOOLBAR_NEW_FLIGHT)); // pending seperate icon
+        ui->actionLogbook->setIcon(QIcon(OPL::Assets::ICON_TOOLBAR_LOGBOOK));
+        ui->actionAircraft->setIcon(QIcon(OPL::Assets::ICON_TOOLBAR_AIRCRAFT));
+        ui->actionPilots->setIcon(QIcon(OPL::Assets::ICON_TOOLBAR_PILOT));
+        ui->actionBackup->setIcon(QIcon(OPL::Assets::ICON_TOOLBAR_BACKUP));
+        ui->actionSettings->setIcon(QIcon(OPL::Assets::ICON_TOOLBAR_SETTINGS));
+        ui->actionQuit->setIcon(QIcon(OPL::Assets::ICON_TOOLBAR_QUIT));
+        break;
+    case StyleType::Dark:
+        LOG << "Setting Dark Icon theme";
+        ui->actionHome->setIcon(QIcon(OPL::Assets::ICON_TOOLBAR_HOME_DARK));
+        ui->actionNewFlight->setIcon(QIcon(OPL::Assets::ICON_TOOLBAR_NEW_FLIGHT_DARK));
+        ui->actionNewSim->setIcon(QIcon(OPL::Assets::ICON_TOOLBAR_NEW_FLIGHT_DARK)); // pending separate icon
+        ui->actionLogbook->setIcon(QIcon(OPL::Assets::ICON_TOOLBAR_LOGBOOK_DARK));
+        ui->actionAircraft->setIcon(QIcon(OPL::Assets::ICON_TOOLBAR_AIRCRAFT_DARK));
+        ui->actionPilots->setIcon(QIcon(OPL::Assets::ICON_TOOLBAR_PILOT_DARK));
+        ui->actionBackup->setIcon(QIcon(OPL::Assets::ICON_TOOLBAR_BACKUP_DARK));
+        ui->actionSettings->setIcon(QIcon(OPL::Assets::ICON_TOOLBAR_SETTINGS_DARK));
+        ui->actionQuit->setIcon(QIcon(OPL::Assets::ICON_TOOLBAR_QUIT_DARK));
+        break;
+    }
 }
 
 void MainWindow::nope()
@@ -155,6 +184,8 @@ void MainWindow::connectWidgets()
                      pilotsWidget,   &PilotsWidget::onPilotsWidget_databaseUpdated);
     QObject::connect(settingsWidget, &SettingsWidget::settingChanged,
                      pilotsWidget,   &PilotsWidget::onPilotsWidget_settingChanged);
+    QObject::connect(settingsWidget, &SettingsWidget::settingChanged,
+                     this,           &MainWindow::onStyleChanged);
 
     QObject::connect(aDB,             &ADatabase::connectionReset,
                      logbookWidget,   &LogbookWidget::repopulateModel);
@@ -255,3 +286,10 @@ void MainWindow::on_actionDebug_triggered()
 {
     ui->stackedWidget->setCurrentWidget(debugWidget);
 }
+
+void MainWindow::on_actionNewSim_triggered()
+{
+    auto nsd = NewSimDialog(this);
+    nsd.exec();
+}
+

+ 24 - 11
mainwindow.h

@@ -42,8 +42,9 @@
 #include "src/classes/arunguard.h"
 #include "src/classes/acompletiondata.h"
 #include "src/testing/atimer.h"
+#include "src/classes/astyle.h"
 
-
+enum Style {Light, Dark};
 QT_BEGIN_NAMESPACE
 namespace Ui {
 class MainWindow;
@@ -55,32 +56,32 @@ QT_END_NAMESPACE
  * \details The Tool bar contains shortcuts to the different widgets, which are on selection set active on the stacked main widget.
  * For a detailed description of what each widget does, please refer to the documentation for each widget. This is only a short synopsis:
  *
- * # HomeWidget
+ * ## HomeWidget
  *
  * The home widget displays the total amount of hours for all logged flights, seperated into different categories. It also enables keeping track
  * of currencies and license expiries
  *
- * # New Flight
+ * ## New Flight
  *
  * Opens a NewFlightDialog which can be used to submit a new flight to the database.
  *
- * # Logboook
+ * ## Logboook
  *
  * Shows a view of the logbook table in a QTableView and enables editing the entries by spawning a child NewFlightDialog with the details for a selected flight.
  *
- * # Aircraft
+ * ## Aircraft
  *
  * Shows a view of the tails table in a QTableView and enables editing the entries by spawning a child NewTailDialog with the details for a selected tail.
  *
- * # Pilots
+ * ## Pilots
  *
  * Shows a view of the pilots table in a QTableView and enables editing the entries by spawning a child NewPilotDialog with the details for a selected pilot.
  *
- * # Backup
+ * ## Backup
  *
  * Enables backing up and restoring the database.
  *
- * # Settings
+ * ## Settings
  *
  * Enables changing application settings
 */
@@ -92,6 +93,12 @@ public:
     MainWindow(QWidget *parent = nullptr);
     ~MainWindow();
 
+public slots:
+    void onStyleChanged(SettingsWidget::SettingSignal signal){
+        if (signal == SettingsWidget::MainWindow)
+            setActionIcons(AStyle::getStyleType());
+    }
+
 private slots:
 
     void on_actionHome_triggered();
@@ -112,6 +119,8 @@ private slots:
 
     void on_actionDebug_triggered();
 
+    void on_actionNewSim_triggered();
+
 private:
     Ui::MainWindow *ui;
 
@@ -132,6 +141,9 @@ private:
     // Completion Data for QCompleters and Mapping
     ACompletionData completionData;
 
+    void setupToolbar();
+    void setActionIcons(StyleType style = StyleType::Light);
+
     void nope();
 
     void connectWidgets();
@@ -163,11 +175,12 @@ protected:
      */
     void resizeEvent(QResizeEvent *event) override
     {
+        //DEB << "SIZE:" << this->size();
         int icon_size;
-        if (this->height() < 780)
-            icon_size = (this->height() / 13);
+        if (this->height() < 760)
+            icon_size = (this->height() / 16);
         else
-            icon_size = (this->height() / 12);
+            icon_size = (this->height() / 14);
 
         auto tool_bar = this->findChild<QToolBar*>();
         tool_bar->setIconSize(QSize(icon_size, icon_size));

+ 13 - 2
mainwindow.ui

@@ -29,7 +29,7 @@
    </size>
   </property>
   <property name="windowTitle">
-   <string>openPilotLog v0.6</string>
+   <string>openPilotLog</string>
   </property>
   <property name="toolButtonStyle">
    <enum>Qt::ToolButtonTextUnderIcon</enum>
@@ -48,7 +48,7 @@
   <widget class="QStatusBar" name="statusbar"/>
   <action name="actionNewFlight">
    <property name="text">
-    <string>NewFlight</string>
+    <string>New Flight</string>
    </property>
    <property name="toolTip">
     <string>Add a new flight to the logbook</string>
@@ -152,6 +152,17 @@
     <string>Ctrl+B</string>
    </property>
   </action>
+  <action name="actionNewSim">
+   <property name="text">
+    <string>New Sim</string>
+   </property>
+   <property name="toolTip">
+    <string>Add a new simulator sesion to the logbook</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+S</string>
+   </property>
+  </action>
  </widget>
  <resources/>
  <connections/>

+ 3 - 3
src/classes/aaircraftentry.cpp

@@ -19,13 +19,13 @@
 #include "src/opl.h"
 
 AAircraftEntry::AAircraftEntry()
-    : AEntry::AEntry(Opl::Db::DEFAULT_AIRCRAFT_POSITION)
+    : AEntry::AEntry(DataPosition(OPL::Db::TABLE_AIRCRAFT, 0))
 {}
 
 AAircraftEntry::AAircraftEntry(RowId_T row_id)
-    : AEntry::AEntry(DataPosition(Opl::Db::TABLE_AIRCRAFT, row_id))
+    : AEntry::AEntry(DataPosition(OPL::Db::TABLE_AIRCRAFT, row_id))
 {}
 
 AAircraftEntry::AAircraftEntry(RowData_T table_data)
-    : AEntry::AEntry(Opl::Db::DEFAULT_AIRCRAFT_POSITION, table_data)
+    : AEntry::AEntry(DataPosition(OPL::Db::TABLE_AIRCRAFT, 0), table_data)
 {}

+ 4 - 4
src/classes/acurrencyentry.cpp

@@ -12,14 +12,14 @@
  * CurrencyName, which maps to the static row id for the currency.
  */
 ACurrencyEntry::ACurrencyEntry(ACurrencyEntry::CurrencyName currency_name)
-    : AEntry::AEntry(DataPosition(Opl::Db::TABLE_CURRENCIES, static_cast<int>(currency_name)))
+    : AEntry::AEntry(DataPosition(OPL::Db::TABLE_CURRENCIES, static_cast<int>(currency_name)))
 {}
 
 ACurrencyEntry::ACurrencyEntry(ACurrencyEntry::CurrencyName currency_name, QDate expiration_date)
-    : AEntry::AEntry(DataPosition(Opl::Db::TABLE_CURRENCIES, static_cast<int>(currency_name)))
+    : AEntry::AEntry(DataPosition(OPL::Db::TABLE_CURRENCIES, static_cast<int>(currency_name)))
 {
     if (expiration_date.isValid()) {
-        tableData.insert(Opl::Db::CURRENCIES_EXPIRYDATE, expiration_date.toString(Qt::ISODate));
+        tableData.insert(OPL::Db::CURRENCIES_EXPIRYDATE, expiration_date.toString(Qt::ISODate));
     } else {
         DEB << "Invalid Date.";
     }
@@ -34,6 +34,6 @@ ACurrencyEntry::ACurrencyEntry(ACurrencyEntry::CurrencyName currency_name, QDate
 bool ACurrencyEntry::isValid() const
 {
     return QDate::fromString(
-                tableData.value(Opl::Db::CURRENCIES_EXPIRYDATE).toString(), Qt::ISODate
+                tableData.value(OPL::Db::CURRENCIES_EXPIRYDATE).toString(), Qt::ISODate
                 ).isValid();
 }

+ 2 - 0
src/classes/aentry.h

@@ -47,6 +47,8 @@ public:
     void setPosition(DataPosition position_);
 
     const DataPosition& getPosition() const;
+    const TableName_T &getTableName() const { return position.tableName; }
+    const RowId_T &getRowId() const { return position.rowId; }
     const RowData_T& getData() const;
 
     /*!

+ 13 - 13
src/classes/aflightentry.cpp

@@ -22,15 +22,15 @@
 #include "src/classes/asettings.h"
 
 AFlightEntry::AFlightEntry()
-    : AEntry::AEntry(Opl::Db::DEFAULT_FLIGHT_POSITION)
+    : AEntry::AEntry(DataPosition(OPL::Db::TABLE_FLIGHTS, 0))
 {}
 
 AFlightEntry::AFlightEntry(RowId_T row_id)
-    : AEntry::AEntry(DataPosition(Opl::Db::TABLE_FLIGHTS, row_id))
+    : AEntry::AEntry(DataPosition(OPL::Db::TABLE_FLIGHTS, row_id))
 {}
 
 AFlightEntry::AFlightEntry(RowData_T table_data)
-    : AEntry::AEntry(Opl::Db::DEFAULT_FLIGHT_POSITION, table_data)
+    : AEntry::AEntry(DataPosition(OPL::Db::TABLE_FLIGHTS, 0), table_data)
 {}
 
 const QString AFlightEntry::summary()
@@ -39,21 +39,21 @@ const QString AFlightEntry::summary()
         return QString();
 
     QString flight_summary;
-    auto space = QStringLiteral(" ");
-    flight_summary.append(tableData.value(Opl::Db::FLIGHTS_DOFT).toString() + space);
-    flight_summary.append(tableData.value(Opl::Db::FLIGHTS_DEPT).toString() + space);
-    flight_summary.append(ATime::toString(tableData.value(Opl::Db::FLIGHTS_TOFB).toInt())
+    auto space = QLatin1Char(' ');
+    flight_summary.append(tableData.value(OPL::Db::FLIGHTS_DOFT).toString() + space);
+    flight_summary.append(tableData.value(OPL::Db::FLIGHTS_DEPT).toString() + space);
+    flight_summary.append(ATime::toString(tableData.value(OPL::Db::FLIGHTS_TOFB).toInt())
                           + space);
-    flight_summary.append(ATime::toString(tableData.value(Opl::Db::FLIGHTS_TONB).toInt())
+    flight_summary.append(ATime::toString(tableData.value(OPL::Db::FLIGHTS_TONB).toInt())
                           + space);
-    flight_summary.append(tableData.value(Opl::Db::FLIGHTS_DEST).toString());
+    flight_summary.append(tableData.value(OPL::Db::FLIGHTS_DEST).toString());
 
     return flight_summary;
 }
 
 const QString AFlightEntry::getRegistration()
 {
-    ATailEntry acft = aDB->resolveForeignTail(tableData.value(Opl::Db::FLIGHTS_ACFT).toInt());
+    ATailEntry acft = aDB->resolveForeignTail(tableData.value(OPL::Db::FLIGHTS_ACFT).toInt());
     return acft.registration();
 }
 
@@ -61,16 +61,16 @@ const QString AFlightEntry::getPilotName(pilotPosition pilot_)
 {
     switch (pilot_) {
     case pilotPosition::pic: {
-        auto foreign_pilot = aDB->resolveForeignPilot(tableData.value(Opl::Db::FLIGHTS_PIC).toInt());
+        auto foreign_pilot = aDB->resolveForeignPilot(tableData.value(OPL::Db::FLIGHTS_PIC).toInt());
         return foreign_pilot.name();
         break;
     }
     case pilotPosition::secondPilot: {
-        auto foreign_pilot = aDB->resolveForeignPilot(tableData.value(Opl::Db::FLIGHTS_SECONDPILOT).toInt());
+        auto foreign_pilot = aDB->resolveForeignPilot(tableData.value(OPL::Db::FLIGHTS_SECONDPILOT).toInt());
         return foreign_pilot.name();
     }
     case pilotPosition::thirdPilot: {
-        auto foreign_pilot = aDB->resolveForeignPilot(tableData.value(Opl::Db::FLIGHTS_THIRDPILOT).toInt());
+        auto foreign_pilot = aDB->resolveForeignPilot(tableData.value(OPL::Db::FLIGHTS_THIRDPILOT).toInt());
         return foreign_pilot.name();
         break;
     } // case scope

+ 4 - 4
src/classes/ajson.cpp

@@ -19,10 +19,10 @@
 #include "src/database/adbsetup.h"
 
 const QList<QPair<TableName_T, ADatabaseTable>> AJson::tables {
-    qMakePair(Opl::Db::TABLE_TAILS, ADatabaseTable::tails),
-    qMakePair(Opl::Db::TABLE_PILOTS, ADatabaseTable::pilots),
-    qMakePair(Opl::Db::TABLE_CURRENCIES, ADatabaseTable::currencies),
-    qMakePair(Opl::Db::TABLE_FLIGHTS, ADatabaseTable::flights),
+    qMakePair(OPL::Db::TABLE_TAILS, ADatabaseTable::tails),
+    qMakePair(OPL::Db::TABLE_PILOTS, ADatabaseTable::pilots),
+    qMakePair(OPL::Db::TABLE_CURRENCIES, ADatabaseTable::currencies),
+    qMakePair(OPL::Db::TABLE_FLIGHTS, ADatabaseTable::flights),
 };
 
 void AJson::exportDatabase()

+ 6 - 6
src/classes/apilotentry.cpp

@@ -19,15 +19,15 @@
 #include "src/opl.h"
 
 APilotEntry::APilotEntry()
-    : AEntry::AEntry(Opl::Db::DEFAULT_PILOT_POSITION)
+    : AEntry::AEntry(DataPosition(OPL::Db::TABLE_PILOTS, 0))
 {}
 
 APilotEntry::APilotEntry(RowId_T row_id)
-    : AEntry::AEntry(DataPosition(Opl::Db::TABLE_PILOTS, row_id))
+    : AEntry::AEntry(DataPosition(OPL::Db::TABLE_PILOTS, row_id))
 {}
 
 APilotEntry::APilotEntry(RowData_T table_data)
-    : AEntry::AEntry(Opl::Db::DEFAULT_PILOT_POSITION, table_data)
+    : AEntry::AEntry(DataPosition(OPL::Db::TABLE_PILOTS, 0), table_data)
 {}
 
 const QString APilotEntry::name()
@@ -35,7 +35,7 @@ const QString APilotEntry::name()
     if (tableData.isEmpty())
         return QString();
 
-    return tableData.value(Opl::Db::PILOTS_LASTNAME).toString() + ", "
-           //+tableData.value(Opl::Db::PILOTS_FIRSTNAME).toString().left(1) + '.';
-           +tableData.value(Opl::Db::PILOTS_FIRSTNAME).toString();
+    return tableData.value(OPL::Db::PILOTS_LASTNAME).toString() + ", "
+           //+tableData.value(OPL::Db::PILOTS_FIRSTNAME).toString().left(1) + '.';
+           +tableData.value(OPL::Db::PILOTS_FIRSTNAME).toString();
 }

+ 18 - 0
src/classes/asimulatorentry.cpp

@@ -0,0 +1,18 @@
+/*
+ *openPilotLog - A FOSS Pilot Logbook Application
+ *Copyright (C) 2020-2021 Felix Turowsky
+ *
+ *This program is free software: you can redistribute it and/or modify
+ *it under the terms of the GNU General Public License as published by
+ *the Free Software Foundation, either version 3 of the License, or
+ *(at your option) any later version.
+ *
+ *This program is distributed in the hope that it will be useful,
+ *but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *GNU General Public License for more details.
+ *
+ *You should have received a copy of the GNU General Public License
+ *along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+#include "asimulatorentry.h"

+ 38 - 0
src/classes/asimulatorentry.h

@@ -0,0 +1,38 @@
+/*
+ *openPilotLog - A FOSS Pilot Logbook Application
+ *Copyright (C) 2020-2021 Felix Turowsky
+ *
+ *This program is free software: you can redistribute it and/or modify
+ *it under the terms of the GNU General Public License as published by
+ *the Free Software Foundation, either version 3 of the License, or
+ *(at your option) any later version.
+ *
+ *This program is distributed in the hope that it will be useful,
+ *but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *GNU General Public License for more details.
+ *
+ *You should have received a copy of the GNU General Public License
+ *along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+#ifndef ASIMULATORENTRY_H
+#define ASIMULATORENTRY_H
+
+#include "aentry.h"
+#include "src/opl.h"
+
+class ASimulatorEntry : public AEntry
+{
+public:
+    ASimulatorEntry()
+        : AEntry::AEntry(DataPosition(OPL::Db::TABLE_SIMULATORS, 0)){};
+    ASimulatorEntry(RowId_T row_id)
+        : AEntry::AEntry(DataPosition(OPL::Db::TABLE_SIMULATORS, row_id)){};
+    ASimulatorEntry(RowData_T table_data)
+        : AEntry::AEntry(DataPosition(OPL::Db::TABLE_SIMULATORS, 0), table_data){};
+
+    ASimulatorEntry(const ASimulatorEntry& pe) = default;
+    ASimulatorEntry& operator=(const ASimulatorEntry& pe) = default;
+};
+
+#endif // ASIMULATORENTRY_H

+ 57 - 11
src/classes/astyle.cpp

@@ -14,11 +14,16 @@
  *
  *You should have received a copy of the GNU General Public License
  *along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-/*
- * Stylesheets used (c) Alexander Huszagh
+ *
+ * Breeze Stylesheets (c) Alexander Huszagh
  * https://github.com/Alexhuszagh/BreezeStyleSheets
+ *
+ * QDarksStyle Stylesheet (c) Colin Duquesnoy
+ * https://github.com/ColinDuquesnoy/QDarkStyleSheet
+ *
+ * Dark Palette (c) 2017 by Juergen Skrotzky
+ * https://github.com/Jorgen-VikingGod/Qt-Frameless-Window-DarkStyle
+ *
  */
 #include "astyle.h"
 #include "src/opl.h"
@@ -40,7 +45,7 @@ const QList<StyleSheet> AStyle::styleSheets = {
 };
 
 QString AStyle::currentStyle = defaultStyle;
-
+QLatin1String AStyle::DARK_PALETTE = QLatin1String("Dark-Palette");
 /*!
  * \brief Setup Application style by reading from openPilotLog.ini
  */
@@ -58,7 +63,7 @@ void AStyle::setup()
     // Set style, stylesheet or palette
     QString style_setting = ASettings::read(ASettings::Main::Style).toString();
 
-    if (style_setting == QLatin1String("Dark-Palette")) {
+    if (style_setting == DARK_PALETTE) {
         AStyle::setStyle(AStyle::darkPalette());
         ASettings::write(ASettings::Main::Style, style_setting);
         return;
@@ -107,26 +112,67 @@ void AStyle::setStyle(const QPalette &palette)
 {
     resetStyle();
     LOG << "Setting Colour Palette...";
+    currentStyle = DARK_PALETTE;
     qApp->setPalette(palette);
 }
 
+StyleType AStyle::getStyleType()
+{
+    const QStringList darkStyles = {
+        QStringLiteral("Breeze-Dark"),
+        QStringLiteral("QDarkStyle"),
+        DARK_PALETTE,
+    };
+
+    if (darkStyles.contains(currentStyle))
+        return StyleType::Dark;
+    else
+        return StyleType::Light;
+}
+
 QPalette AStyle::darkPalette()
 {
     auto palette = QPalette();
+    //palette.setColor(QPalette::Window, QColor(53, 53, 53));
+    //palette.setColor(QPalette::WindowText, Qt::white);
+    //palette.setColor(QPalette::Base, QColor(25, 25, 25));
+    //palette.setColor(QPalette::AlternateBase, QColor(53, 53, 53));
+    //palette.setColor(QPalette::ToolTipBase, Qt::black);
+    //palette.setColor(QPalette::ToolTipText, Qt::white);
+    //palette.setColor(QPalette::Text, Qt::white);
+    //palette.setColor(QPalette::Button, QColor(53, 53, 53));
+    //palette.setColor(QPalette::ButtonText, Qt::white);
+    //palette.setColor(QPalette::BrightText, Qt::red);
+    //palette.setColor(QPalette::Link, QColor(42, 130, 218));
+    //palette.setColor(QPalette::Highlight, QColor(42, 130, 218));
+    //palette.setColor(QPalette::HighlightedText, Qt::black);
+
     palette.setColor(QPalette::Window, QColor(53, 53, 53));
     palette.setColor(QPalette::WindowText, Qt::white);
-    palette.setColor(QPalette::Base, QColor(25, 25, 25));
-    palette.setColor(QPalette::AlternateBase, QColor(53, 53, 53));
-    palette.setColor(QPalette::ToolTipBase, Qt::black);
-    palette.setColor(QPalette::ToolTipText, Qt::white);
+    palette.setColor(QPalette::Disabled, QPalette::WindowText,
+                     QColor(127, 127, 127));
+    palette.setColor(QPalette::Base, QColor(42, 42, 42));
+    palette.setColor(QPalette::AlternateBase, QColor(66, 66, 66));
+    palette.setColor(QPalette::ToolTipBase, Qt::white);
+    palette.setColor(QPalette::ToolTipText, QColor(53, 53, 53));
     palette.setColor(QPalette::Text, Qt::white);
+    palette.setColor(QPalette::Disabled, QPalette::Text, QColor(127, 127, 127));
+    palette.setColor(QPalette::Dark, QColor(35, 35, 35));
+    palette.setColor(QPalette::Shadow, QColor(20, 20, 20));
     palette.setColor(QPalette::Button, QColor(53, 53, 53));
     palette.setColor(QPalette::ButtonText, Qt::white);
+    palette.setColor(QPalette::Disabled, QPalette::ButtonText,
+                     QColor(127, 127, 127));
     palette.setColor(QPalette::BrightText, Qt::red);
     palette.setColor(QPalette::Link, QColor(42, 130, 218));
     palette.setColor(QPalette::Highlight, QColor(42, 130, 218));
-    palette.setColor(QPalette::HighlightedText, Qt::black);
+    palette.setColor(QPalette::Disabled, QPalette::Highlight, QColor(80, 80, 80));
+    palette.setColor(QPalette::HighlightedText, Qt::white);
+    palette.setColor(QPalette::Disabled, QPalette::HighlightedText,
+                     QColor(127, 127, 127));
+
     return palette;
+
 }
 
 const QString& AStyle::style()

+ 6 - 0
src/classes/astyle.h

@@ -23,6 +23,8 @@
 #include <QTextStream>
 #include <QComboBox>
 
+enum class StyleType {Light, Dark};
+
 /*!
  * \brief The StyleSheet struct holds the Display Name and File Name (in the
  * resource system) for the available stylesheets.
@@ -51,6 +53,7 @@ class AStyle
 {
 private:
     static QString currentStyle;
+    static QLatin1String DARK_PALETTE;
     static void resetStyle();
 public:
     static const QStringList styles;
@@ -61,10 +64,13 @@ public:
     static void setStyle(const QString &style_key);
     static void setStyle(const StyleSheet &style_sheet);
     static void setStyle(const QPalette &palette);
+    static QString getCurrentStyle() {return currentStyle;}
+    static StyleType getStyleType();
     static QPalette darkPalette();
     static const QString& style();
 
     static inline void loadStylesComboBox(QComboBox *combo_box){
+        const QSignalBlocker blocker(combo_box);
         combo_box->addItems(AStyle::styles);
         for (const auto &style_sheet : AStyle::styleSheets) {
             combo_box->addItem(style_sheet.styleSheetName);

+ 10 - 10
src/classes/atailentry.cpp

@@ -19,31 +19,31 @@
 #include "src/opl.h"
 
 ATailEntry::ATailEntry()
-    : AEntry::AEntry(Opl::Db::DEFAULT_TAIL_POSITION)
+    : AEntry::AEntry(DataPosition(OPL::Db::TABLE_TAILS, 0))
 {}
 
 ATailEntry::ATailEntry(RowId_T row_id)
-    : AEntry::AEntry(DataPosition(Opl::Db::TABLE_TAILS, row_id))
+    : AEntry::AEntry(DataPosition(OPL::Db::TABLE_TAILS, row_id))
 {}
 
 ATailEntry::ATailEntry(RowData_T table_data)
-    : AEntry::AEntry(Opl::Db::DEFAULT_TAIL_POSITION, table_data)
+    : AEntry::AEntry(DataPosition(OPL::Db::TABLE_TAILS, 0), table_data)
 {}
 
 const QString ATailEntry::registration()
 {
-    return getData().value(Opl::Db::TAILS_REGISTRATION).toString();
+    return getData().value(OPL::Db::TAILS_REGISTRATION).toString();
 }
 
 const QString ATailEntry::type()
 {
     QString type_string;
-    if (!tableData.value(Opl::Db::TAILS_MAKE).toString().isEmpty())
-        type_string.append(getData().value(Opl::Db::TAILS_MAKE).toString() + ' ');
-    if (!tableData.value(Opl::Db::TAILS_MODEL).toString().isEmpty())
-        type_string.append(getData().value(Opl::Db::TAILS_MODEL).toString());
-    if (!tableData.value(Opl::Db::TAILS_VARIANT).toString().isEmpty())
-        type_string.append('-' + getData().value(Opl::Db::TAILS_VARIANT).toString());
+    if (!tableData.value(OPL::Db::TAILS_MAKE).toString().isEmpty())
+        type_string.append(getData().value(OPL::Db::TAILS_MAKE).toString() + ' ');
+    if (!tableData.value(OPL::Db::TAILS_MODEL).toString().isEmpty())
+        type_string.append(getData().value(OPL::Db::TAILS_MODEL).toString());
+    if (!tableData.value(OPL::Db::TAILS_VARIANT).toString().isEmpty())
+        type_string.append('-' + getData().value(OPL::Db::TAILS_VARIANT).toString());
 
     return type_string;
 }

+ 4 - 4
src/classes/atranslator.cpp

@@ -2,13 +2,13 @@
 
 QTranslator* ATranslator::translator;
 
-void ATranslator::installTranslator(Opl::Translations language)
+void ATranslator::installTranslator(OPL::Translation language)
 {
     translator = new QTranslator();
-    if (translator->load(Opl::L10N_FILES[language]))
-        LOG << "Translations loaded. Selected language: " << Opl::L10N_FILES[language].right(2);
+    if (translator->load(OPL::GLOBALS->getLanguageFilePath(language)))
+        LOG << "Translations loaded. Selected language: " << OPL::GLOBALS->getLanguageFilePath(language);
     else
-        LOG << "Loading translations has failed. Selected language: " << Opl::L10N_FILES[language].right(2);
+        LOG << "Loading translations has failed. Selected language: " << OPL::GLOBALS->getLanguageFilePath(language);
 
 
     if (qApp->installTranslator(translator))

+ 2 - 2
src/classes/atranslator.h

@@ -10,7 +10,7 @@
  * Long story short, make sure to use a version of CMake that is 3.16 or earlier, or 3.19.2 or later.
  *
  * The translation source files (.ts) are located at /l10n and once compiled, the translation binaries
- * are at `$BINDIR/l10n/` and can be accessed via `Opl::L10N_FILES`.
+ * are at `$BINDIR/l10n/` and can be accessed via `OPL::L10N_FILES`.
  *
  * When a QTranslator is installed, the UI is updated through [QWidget::changeEvent()](https://doc.qt.io/qt-5/qwidget.html#changeEvent).
  *
@@ -21,7 +21,7 @@ public:
     /*!
      * \brief Installs a QTranslator with the selected language. Defaults to English. Call this function before constructing the Main Window.
      */
-    static void installTranslator(Opl::Translations language = Opl::Translations::English);
+    static void installTranslator(OPL::Translation language = OPL::Translation::English);
 
 private:
     static QTranslator *translator;

+ 14 - 7
src/database/adatabase.cpp

@@ -493,6 +493,13 @@ AFlightEntry ADatabase::getFlightEntry(RowId_T row_id)
     return flight_entry;
 }
 
+ASimulatorEntry ADatabase::getSimEntry(RowId_T row_id)
+{
+    ASimulatorEntry sim_entry(row_id);
+    sim_entry.setData(getEntryData(sim_entry.getPosition()));
+    return sim_entry;
+}
+
 ACurrencyEntry ADatabase::getCurrencyEntry(ACurrencyEntry::CurrencyName currency_name)
 {
     ACurrencyEntry currency_entry(currency_name);
@@ -603,13 +610,13 @@ RowId_T ADatabase::getLastEntry(ADatabaseTable table)
 
     switch (table) {
     case ADatabaseTable::pilots:
-        statement.append(Opl::Db::TABLE_PILOTS);
+        statement.append(OPL::Db::TABLE_PILOTS);
         break;
     case ADatabaseTable::aircraft:
-        statement.append(Opl::Db::TABLE_AIRCRAFT);
+        statement.append(OPL::Db::TABLE_AIRCRAFT);
         break;
     case ADatabaseTable::tails:
-        statement.append(Opl::Db::TABLE_TAILS);
+        statement.append(OPL::Db::TABLE_TAILS);
         break;
     default:
         DEB << "Not a valid completer target for this function.";
@@ -801,16 +808,16 @@ QVector<RowData_T> ADatabase::getTable(ADatabaseTable table_name)
     auto query_str = QStringLiteral("SELECT * FROM ");
     switch (table_name) {
     case ADatabaseTable::pilots:
-        query_str.append(Opl::Db::TABLE_PILOTS);
+        query_str.append(OPL::Db::TABLE_PILOTS);
         break;
     case ADatabaseTable::tails:
-        query_str.append(Opl::Db::TABLE_TAILS);
+        query_str.append(OPL::Db::TABLE_TAILS);
         break;
     case ADatabaseTable::flights:
-        query_str.append(Opl::Db::TABLE_FLIGHTS);
+        query_str.append(OPL::Db::TABLE_FLIGHTS);
         break;
     case ADatabaseTable::currencies:
-        query_str.append(Opl::Db::TABLE_CURRENCIES);
+        query_str.append(OPL::Db::TABLE_CURRENCIES);
     default:
         break;
     }

+ 26 - 6
src/database/adatabase.h

@@ -39,6 +39,7 @@
 #include "src/classes/aflightentry.h"
 #include "src/classes/astandardpaths.h"
 #include "src/classes/acurrencyentry.h"
+#include "src/classes/asimulatorentry.h"
 
 #define SQLITE_DRIVER QStringLiteral("QSQLITE")
 
@@ -68,13 +69,22 @@ enum class ADatabaseTarget
     aircraft
 };
 
+/*!
+ * \brief enumarates the tables in the database
+ */
 enum class ADatabaseTable
 {
-    tails,
-    flights,
-    currencies,
-    aircraft,
-    pilots,
+    // user tables
+    tails = 0,
+    pilots = 1,
+    flights = 2,
+    simulators = 3,
+    currencies = 4,
+
+    // template tables
+    aircraft = 4,
+    airports = 5,
+    changelog = 7,
 };
 
 /*!
@@ -133,9 +143,9 @@ public:
  * to hot database data.
  */
 class ADatabase : public QObject {
-    Q_OBJECT
 
 private:
+    Q_OBJECT
     static ADatabase* self;
     TableNames_T tableNames;
     TableColumns_T tableColumns;
@@ -306,6 +316,16 @@ public:
      */
     AFlightEntry getFlightEntry(RowId_T row_id);
 
+    /*!
+     * \brief retreives a Simulator entry from the database.
+     *
+     * This function is a wrapper for DataBase::getEntry(DataPosition),
+     * where the table is already set and which returns an ASimEntry
+     * instead of an AEntry. It allows for easy access to a Simulator entry
+     * with only the RowId required as input.
+     */
+    ASimulatorEntry getSimEntry(RowId_T row_id);
+
     /*!
      * \brief Retreives a currency entry from the database.
      */

+ 172 - 53
src/database/adbsetup.cpp

@@ -24,23 +24,24 @@
 namespace aDbSetup {
 
 // const auto TEMPLATE_URL = QStringLiteral("https://raw.githubusercontent.com/fiffty-50/openpilotlog/tree/main/assets/database/templates/");
-const auto TEMPLATE_URL = QStringLiteral("https://raw.githubusercontent.com/fiffty-50/openpilotlog/develop/assets/database/templates/");
+const static auto TEMPLATE_URL = QStringLiteral("https://raw.githubusercontent.com/fiffty-50/openpilotlog/develop/assets/database/templates/");
 
 
-const auto CREATE_TABLE_PILOTS = QLatin1String("CREATE TABLE pilots ( "
-            " pilot_id       INTEGER NOT NULL, "
+const static auto CREATE_TABLE_PILOTS = QStringLiteral("CREATE TABLE pilots ( "
+            " pilot_id       INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "
             " lastname       TEXT    NOT NULL, "
             " firstname      TEXT, "
             " alias          TEXT, "
             " company        TEXT, "
             " employeeid     TEXT, "
             " phone          TEXT, "
-            " email          TEXT, "
-            " PRIMARY KEY(pilot_id AUTOINCREMENT)"
-            ")");
+            " email          TEXT "
+//            " PRIMARY KEY(pilot_id AUTOINCREMENT)"
+            ")"
+                                                       );
 
-const auto CREATE_TABLE_TAILS = QLatin1String("CREATE TABLE tails ("
-            " tail_id        INTEGER NOT NULL,"
+const static auto CREATE_TABLE_TAILS = QStringLiteral("CREATE TABLE tails ("
+            " tail_id        INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
             " registration   TEXT NOT NULL,"
             " company        TEXT,"
             " make           TEXT,"
@@ -49,12 +50,13 @@ const auto CREATE_TABLE_TAILS = QLatin1String("CREATE TABLE tails ("
             " multipilot     INTEGER,"
             " multiengine    INTEGER,"
             " engineType     INTEGER,"
-            " weightClass    INTEGER,"
-            " PRIMARY KEY(tail_id AUTOINCREMENT)"
-            ")");
+            " weightClass    INTEGER"
+//            " PRIMARY KEY(tail_id AUTOINCREMENT)"
+            ")"
+                                                      );
 
-const auto CREATE_TABLE_FLIGHTS = QLatin1String("CREATE TABLE flights ("
-            " flight_id      INTEGER NOT NULL, "
+const static auto CREATE_TABLE_FLIGHTS = QStringLiteral("CREATE TABLE flights ("
+            " flight_id      INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "
             " doft           NUMERIC NOT NULL, "
             " dept           TEXT NOT NULL, "
             " dest           TEXT NOT NULL, "
@@ -86,12 +88,13 @@ const auto CREATE_TABLE_FLIGHTS = QLatin1String("CREATE TABLE flights ("
             " flightNumber   TEXT, "
             " remarks        TEXT, "
             " FOREIGN KEY(pic)  REFERENCES pilots(pilot_id) ON DELETE RESTRICT, "
-            " FOREIGN KEY(acft) REFERENCES tails(tail_id)   ON DELETE RESTRICT, "
-            " PRIMARY KEY(flight_id    AUTOINCREMENT) "
-        ")");
+            " FOREIGN KEY(acft) REFERENCES tails(tail_id)   ON DELETE RESTRICT "
+//            " PRIMARY KEY(flight_id    AUTOINCREMENT) "
+        ")"
+                                                        );
 
-const auto CREATE_TABLE_AIRPORTS = QLatin1String("CREATE TABLE airports ( "
-            " airport_id     INTEGER NOT NULL, "
+const static auto CREATE_TABLE_AIRPORTS = QStringLiteral("CREATE TABLE airports ( "
+            " airport_id     INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "
             " icao           TEXT NOT NULL, "
             " iata           TEXT, "
             " name           TEXT, "
@@ -100,12 +103,13 @@ const auto CREATE_TABLE_AIRPORTS = QLatin1String("CREATE TABLE airports ( "
             " country        TEXT, "
             " alt            INTEGER, "
             " utcoffset      INTEGER, "
-            " tzolson        TEXT, "
-            " PRIMARY KEY(airport_id AUTOINCREMENT) "
-            ")");
+            " tzolson        TEXT "
+ //           " PRIMARY KEY(airport_id AUTOINCREMENT) "
+            ")"
+                                                         );
 
-const auto CREATE_TABLE_AIRCRAFT = QLatin1String("CREATE TABLE aircraft ("
-            " aircraft_id   INTEGER NOT NULL,"
+const static auto CREATE_TABLE_AIRCRAFT = QStringLiteral("CREATE TABLE aircraft ("
+            " aircraft_id   INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
             " make          TEXT,"
             " model         TEXT,"
             " variant       TEXT,"
@@ -115,26 +119,39 @@ const auto CREATE_TABLE_AIRCRAFT = QLatin1String("CREATE TABLE aircraft ("
             " multipilot    INTEGER,"
             " multiengine   INTEGER,"
             " engineType    INTEGER,"
-            " weightClass   INTEGER,"
-            " PRIMARY KEY(aircraft_id AUTOINCREMENT)"
-            ")");
+            " weightClass   INTEGER"
+//            " PRIMARY KEY(aircraft_id AUTOINCREMENT)"
+            ")"
+                                                         );
 
-const auto CREATE_TABLE_CHANGELOG = QLatin1String("CREATE TABLE changelog ( "
-            " revision   INTEGER NOT NULL, "
+const static auto CREATE_TABLE_CHANGELOG = QStringLiteral("CREATE TABLE changelog ( "
+            " revision   INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "
             " comment    TEXT, "
-            " date       NUMERIC, "
-            " PRIMARY KEY(revision) "
-            ")");
+            " date       NUMERIC "
+//            " PRIMARY KEY(revision) "
+            ")"
+                                                          );
 
-const auto CREATE_TABLE_CURRENCIES = QLatin1String("CREATE TABLE currencies ( "
-            " currency_id	INTEGER PRIMARY KEY AUTOINCREMENT, "
+const static auto CREATE_TABLE_CURRENCIES = QStringLiteral("CREATE TABLE currencies ( "
+            " currency_id	INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "
             " description	TEXT, "
             " expiryDate     NUMERIC "
             ")"
-            );
+                                                           );
+
+const static auto CREATE_TABLE_SIMULATORS = QStringLiteral("CREATE TABLE simulators ( "
+                                                       " session_id	INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "
+                                                       " date	NUMERIC NOT NULL, "
+                                                       " totalTime	INTEGER NOT NULL, "
+                                                       " deviceType	TEXT NOT NULL, "
+                                                       " aircraftType	TEXT, "
+                                                       " registration	TEXT, "
+                                                       " remarks	TEXT "
+                                                       ")"
+                                                   );
 
 // Statements for creation of views in the database
-const auto CREATE_VIEW_DEFAULT = QLatin1String("CREATE VIEW viewDefault AS "
+const static auto CREATE_VIEW_DEFAULT = QStringLiteral("CREATE VIEW viewDefault AS "
         " SELECT flight_id, doft as 'Date', "
         " dept AS 'Dept', "
         " printf('%02d',(tofb/60))||':'||printf('%02d',(tofb%60)) AS 'Time', "
@@ -158,7 +175,39 @@ const auto CREATE_VIEW_DEFAULT = QLatin1String("CREATE VIEW viewDefault AS "
         " INNER JOIN tails on flights.acft = tails.tail_id "
         " ORDER BY date DESC ");
 
-const auto CREATE_VIEW_EASA = QLatin1String("CREATE VIEW viewEASA AS "
+const static auto CREATE_VIEW_DEFAULT_SIM = QStringLiteral( "CREATE VIEW viewDefaultSim AS SELECT flight_id AS 'rowid',  "
+        " doft as 'Date',  "
+        " dept AS 'Dept',  "
+        " printf('%02d',(tofb/60))||':'||printf('%02d',(tofb%60)) AS 'Time',  "
+        " dest AS 'Dest', printf('%02d',(tonb/60))||':'||printf('%02d',(tonb%60)) AS 'Time ',  "
+        " printf('%02d',(tblk/60))||':'||printf('%02d',(tblk%60)) AS 'Total',  "
+        " CASE  WHEN pilot_id = 1 THEN alias  ELSE lastname||', '||substr(firstname, 1, 1)||'.'  END  AS 'Name PIC',  "
+        " CASE  WHEN variant IS NOT NULL THEN make||' '||model||'-'||variant  ELSE make||' '||model  END  AS 'Type',  "
+        " registration AS 'Registration',   "
+        " null AS 'Sim Type',"
+        " null AS 'Time of Session',"
+        " remarks AS 'Remarks'"
+        " FROM flights  "
+        " INNER JOIN pilots on flights.pic = pilots.pilot_id  INNER JOIN tails on flights.acft = tails.tail_id  "
+        " UNION"
+        " SELECT (session_id * -1),"
+        " date,"
+        " null,"
+        " null,"
+        " null,"
+        " null,"
+        " 'SIM',"
+        " null,"
+        " aircraftType,"
+        " registration,"
+        " deviceType,"
+        " printf('%02d',(totalTime/60))||':'||printf('%02d',(totalTime%60)),"
+        " remarks"
+        " FROM simulators"
+        " ORDER BY date DESC"
+            );
+
+const static auto CREATE_VIEW_EASA = QStringLiteral("CREATE VIEW viewEasa AS "
         " SELECT "
         " flight_id, doft as 'Date', "
         " dept AS 'Dept', "
@@ -191,9 +240,75 @@ const auto CREATE_VIEW_EASA = QLatin1String("CREATE VIEW viewEASA AS "
         " FROM flights "
         " INNER JOIN pilots on flights.pic = pilots.pilot_id "
         " INNER JOIN tails on flights.acft = tails.tail_id "
-        " ORDER BY date DESC");
+        " ORDER BY date DESC"
+                                                    );
+
+const static auto CREATE_VIEW_EASA_SIM = QStringLiteral(" CREATE VIEW viewEasaSim AS "
+            " SELECT  flight_id, doft as 'Date',   "
+            " dept AS 'Dept',  printf('%02d',(tofb/60))||':'||printf('%02d',(tofb%60)) AS 'Time',   "
+            " dest AS 'Dest', printf('%02d',(tonb/60))||':'||printf('%02d',(tonb%60)) AS 'Time ',   "
+            " CASE  WHEN variant IS NOT NULL THEN make||' '||model||'-'||variant  ELSE make||' '||model  END  AS 'Type',   "
+            " registration AS 'Registration',   "
+            " (SELECT printf('%02d',(tSPSE/60))||':'||printf('%02d',(tSPSE%60)) WHERE tSPSE IS NOT NULL) AS 'SP SE',   "
+            " (SELECT printf('%02d',(tSPME/60))||':'||printf('%02d',(tSPME%60)) WHERE tSPME IS NOT NULL) AS 'SP ME',   "
+            " (SELECT printf('%02d',(tMP/60))||':'||printf('%02d',(tMP%60)) WHERE tMP IS NOT NULL) AS 'MP',   "
+            " printf('%02d',(tblk/60))||':'||printf('%02d',(tblk%60)) AS 'Total',   "
+            " CASE  WHEN pilot_id = 1 THEN alias  ELSE lastname||', '||substr(firstname, 1, 1)||'.'  END  AS 'Name PIC',   "
+            " ldgDay AS 'L/D',   "
+            " ldgNight AS 'L/N',   "
+            " (SELECT printf('%02d',(tNight/60))||':'||printf('%02d',(tNight%60)) WHERE tNight IS NOT NULL)  AS 'Night',   "
+            " (SELECT printf('%02d',(tIFR/60))||':'||printf('%02d',(tIFR%60)) WHERE tIFR IS NOT NULL)  AS 'IFR',   "
+            " (SELECT printf('%02d',(tPIC/60))||':'||printf('%02d',(tPIC%60)) WHERE tPIC IS NOT NULL)  AS 'PIC',   "
+            " (SELECT printf('%02d',(tSIC/60))||':'||printf('%02d',(tSIC%60)) WHERE tSIC IS NOT NULL)  AS 'SIC',   "
+            " (SELECT printf('%02d',(tDual/60))||':'||printf('%02d',(tDual%60)) WHERE tDual IS NOT NULL)  AS 'Dual',   "
+            " (SELECT printf('%02d',(tFI/60))||':'||printf('%02d',(tFI%60)) WHERE tFI IS NOT NULL)  AS 'FI', "
+            " null AS 'Sim Type', "
+            " null AS 'Time of Session', "
+            " remarks AS 'Remarks'   "
+            " FROM flights   "
+            " INNER JOIN pilots on flights.pic = pilots.pilot_id   "
+            " INNER JOIN tails on flights.acft = tails.tail_id   "
+            " UNION "
+            " SELECT (session_id * -1), "
+            " date, "
+            " null, "
+            " null, "
+            " null, "
+            " null, "
+            " aircraftType, "
+            " registration, "
+            " null, "
+            " null, "
+            " null, "
+            " 'SIM', "
+            " null, "
+            " null, "
+            " null, "
+            " null, "
+            " null, "
+            " null, "
+            " null, "
+            " null, "
+            " null, "
+            " deviceType, "
+            " printf('%02d',(totalTime/60))||':'||printf('%02d',(totalTime%60)), "
+            " remarks "
+            " FROM simulators "
+            " ORDER BY date DESC "
+            );
+
+const static auto CREATE_VIEW_SIMULATORS = QStringLiteral (" CREATE VIEW viewSimulators AS SELECT (session_id * -1), "
+                                                           " date as 'Date', "
+                                                           " registration AS 'Registration',  "
+                                                           " aircraftType AS 'Aircraft Type',  "
+                                                           " deviceType 'Sim Type', "
+                                                           " printf('%02d',(totalTime/60))||':'||printf('%02d',(totalTime%60)) AS 'Time of Session', "
+                                                           " remarks AS 'Remarks' "
+                                                           " FROM simulators "
+                                                           " ORDER BY date DESC "
+            );
 
-const auto CREATE_VIEW_TAILS = QLatin1String("CREATE VIEW viewTails AS "
+const static auto CREATE_VIEW_TAILS = QStringLiteral("CREATE VIEW viewTails AS "
         " SELECT "
         " tail_id AS 'ID', "
         " registration AS 'Registration', "
@@ -208,7 +323,7 @@ const auto CREATE_VIEW_TAILS = QLatin1String("CREATE VIEW viewTails AS "
         " company AS 'Company' "
         " FROM tails WHERE variant IS NOT NULL");
 
-const auto CREATE_VIEW_PILOTS = QLatin1String("CREATE VIEW viewPilots AS "
+const static auto CREATE_VIEW_PILOTS = QStringLiteral("CREATE VIEW viewPilots AS "
         " SELECT "
         " pilot_id AS 'ID', "
         " lastname AS 'Last Name', "
@@ -216,14 +331,14 @@ const auto CREATE_VIEW_PILOTS = QLatin1String("CREATE VIEW viewPilots AS "
         " company AS 'Company' "
         " FROM pilots");
 
-const auto CREATE_VIEW_QCOMPLETER = QLatin1String("CREATE VIEW viewQCompleter AS "
+const static auto CREATE_VIEW_QCOMPLETER = QStringLiteral("CREATE VIEW viewQCompleter AS "
         " SELECT airport_id, icao, iata, tail_id, registration, pilot_id, "
         " lastname||', '||firstname AS 'pilot_name', alias "
         " FROM airports "
         " LEFT JOIN tails ON airports.airport_id = tails.tail_id "
         " LEFT JOIN pilots ON airports.airport_id = pilots.pilot_id");
 
-const auto CREATE_VIEW_TOTALS = QLatin1String("CREATE VIEW viewTotals AS "
+const static auto CREATE_VIEW_TOTALS = QStringLiteral("CREATE VIEW viewTotals AS "
         " SELECT "
         " printf(\"%02d\",CAST(SUM(tblk) AS INT)/60)||\":\"||printf(\"%02d\",CAST(SUM(tblk) AS INT)%60) AS \"TOTAL\", "
         " printf(\"%02d\",CAST(SUM(tSPSE) AS INT)/60)||\":\"||printf(\"%02d\",CAST(SUM(tSPSE) AS INT)%60) AS \"SP SE\", "
@@ -241,34 +356,38 @@ const auto CREATE_VIEW_TOTALS = QLatin1String("CREATE VIEW viewTotals AS "
         " CAST(SUM(ldgDay) AS INT) AS \"LDG Day\", CAST(SUM(ldgNight) AS INT) AS \"LDG Night\" "
         " FROM flights");
 
-const QList<QLatin1String> DATABASE_TABLES = {
+const static QStringList DATABASE_TABLES = {
     CREATE_TABLE_PILOTS,
     CREATE_TABLE_TAILS,
     CREATE_TABLE_FLIGHTS,
     CREATE_TABLE_AIRCRAFT,
     CREATE_TABLE_AIRPORTS,
     CREATE_TABLE_CURRENCIES,
-    CREATE_TABLE_CHANGELOG
+    CREATE_TABLE_CHANGELOG,
+    CREATE_TABLE_SIMULATORS,
 };
-const QList<QLatin1String> DATABASE_VIEWS = {
+const static QStringList DATABASE_VIEWS = {
     CREATE_VIEW_DEFAULT,
+    CREATE_VIEW_DEFAULT_SIM,
     CREATE_VIEW_EASA,
+    CREATE_VIEW_EASA_SIM,
+    CREATE_VIEW_SIMULATORS,
     CREATE_VIEW_TAILS,
     CREATE_VIEW_PILOTS,
     CREATE_VIEW_TOTALS,
     CREATE_VIEW_QCOMPLETER,
 };
 
-const QList<QLatin1String> USER_TABLES = {
-    QLatin1String("flights"),
-    QLatin1String("pilots"),
-    QLatin1String("tails")
+const static QStringList USER_TABLES = {
+    QStringLiteral("flights"),
+    QStringLiteral("pilots"),
+    QStringLiteral("tails")
 };
-const QList<QLatin1String> TEMPLATE_TABLES= {
-    QLatin1String("aircraft"),
-    QLatin1String("airports"),
-    QLatin1String("currencies"),
-    QLatin1String("changelog")
+const static QStringList TEMPLATE_TABLES= {
+    QStringLiteral("aircraft"),
+    QStringLiteral("airports"),
+    QStringLiteral("currencies"),
+    QStringLiteral("changelog")
 };
 
 bool createDatabase()

+ 20 - 20
src/functions/acalc.cpp

@@ -319,23 +319,23 @@ void ACalc::updateAutoTimes(int acft_id)
         auto flight = aDB->getFlightEntry(item.toInt());
         auto flight_data = flight.getData();
 
-        if(acft_data.value(Opl::Db::TAILS_MULTIPILOT).toInt() == 0
-                && acft_data.value(Opl::Db::TAILS_MULTIENGINE) == 0) {
+        if(acft_data.value(OPL::Db::TAILS_MULTIPILOT).toInt() == 0
+                && acft_data.value(OPL::Db::TAILS_MULTIENGINE) == 0) {
             DEB << "SPSE";
-            flight_data.insert(Opl::Db::FLIGHTS_TSPSE, flight_data.value(Opl::Db::FLIGHTS_TBLK));
-            flight_data.insert(Opl::Db::FLIGHTS_TSPME, QString());
-            flight_data.insert(Opl::Db::FLIGHTS_TMP, QString());
-        } else if ((acft_data.value(Opl::Db::TAILS_MULTIPILOT) == 0
-                    && acft.getData().value(Opl::Db::TAILS_MULTIENGINE) == 1)) {
+            flight_data.insert(OPL::Db::FLIGHTS_TSPSE, flight_data.value(OPL::Db::FLIGHTS_TBLK));
+            flight_data.insert(OPL::Db::FLIGHTS_TSPME, QString());
+            flight_data.insert(OPL::Db::FLIGHTS_TMP, QString());
+        } else if ((acft_data.value(OPL::Db::TAILS_MULTIPILOT) == 0
+                    && acft.getData().value(OPL::Db::TAILS_MULTIENGINE) == 1)) {
             DEB << "SPME";
-            flight_data.insert(Opl::Db::FLIGHTS_TSPME, flight_data.value(Opl::Db::FLIGHTS_TBLK));
-            flight_data.insert(Opl::Db::FLIGHTS_TSPSE, QString());
-            flight_data.insert(Opl::Db::FLIGHTS_TMP, QString());
-        } else if ((acft_data.value(Opl::Db::TAILS_MULTIPILOT) == 1)) {
+            flight_data.insert(OPL::Db::FLIGHTS_TSPME, flight_data.value(OPL::Db::FLIGHTS_TBLK));
+            flight_data.insert(OPL::Db::FLIGHTS_TSPSE, QString());
+            flight_data.insert(OPL::Db::FLIGHTS_TMP, QString());
+        } else if ((acft_data.value(OPL::Db::TAILS_MULTIPILOT) == 1)) {
             DEB << "MPME";
-            flight_data.insert(Opl::Db::FLIGHTS_TMP, flight_data.value(Opl::Db::FLIGHTS_TBLK));
-            flight_data.insert(Opl::Db::FLIGHTS_TSPSE, QString());
-            flight_data.insert(Opl::Db::FLIGHTS_TSPME, QString());
+            flight_data.insert(OPL::Db::FLIGHTS_TMP, flight_data.value(OPL::Db::FLIGHTS_TBLK));
+            flight_data.insert(OPL::Db::FLIGHTS_TSPSE, QString());
+            flight_data.insert(OPL::Db::FLIGHTS_TSPME, QString());
         }
         flight.setData(flight_data);
         aDB->commit(flight);
@@ -363,14 +363,14 @@ void ACalc::updateNightTimes()
 
         auto flt = aDB->getFlightEntry(item.toInt());
         auto data = flt.getData();
-        auto dateTime = QDateTime(QDate::fromString(data.value(Opl::Db::FLIGHTS_DOFT).toString(), Qt::ISODate),
-                                  QTime().addSecs(data.value(Opl::Db::FLIGHTS_TOFB).toInt() * 60),
+        auto dateTime = QDateTime(QDate::fromString(data.value(OPL::Db::FLIGHTS_DOFT).toString(), Qt::ISODate),
+                                  QTime().addSecs(data.value(OPL::Db::FLIGHTS_TOFB).toInt() * 60),
                                   Qt::UTC);
-        data.insert(Opl::Db::FLIGHTS_TNIGHT,
-                    calculateNightTime(data.value(Opl::Db::FLIGHTS_DEPT).toString(),
-                                       data.value(Opl::Db::FLIGHTS_DEST).toString(),
+        data.insert(OPL::Db::FLIGHTS_TNIGHT,
+                    calculateNightTime(data.value(OPL::Db::FLIGHTS_DEPT).toString(),
+                                       data.value(OPL::Db::FLIGHTS_DEST).toString(),
                                        dateTime,
-                                       data.value(Opl::Db::FLIGHTS_TBLK).toInt(),
+                                       data.value(OPL::Db::FLIGHTS_TBLK).toInt(),
                                        night_angle));
         flt.setData(data);
         aDB->commit(flt);

+ 16 - 11
src/functions/adate.cpp

@@ -1,6 +1,6 @@
 #include "adate.h"
 
-QDate ADate::parseInput(QString &io_user_input, Opl::Date::ADateFormat format)
+QDate ADate::parseInput(QString &io_user_input, OPL::DateFormat format)
 {
     // Try input string
     const QString &format_string = ADATEFORMATSMAP.value(format);
@@ -14,7 +14,7 @@ QDate ADate::parseInput(QString &io_user_input, Opl::Date::ADateFormat format)
     return  QDate::fromString(io_user_input, format_string);
 }
 
-void ADate::tryToFix(QString &io_user_input, Opl::Date::ADateFormat format)
+void ADate::tryToFix(QString &io_user_input, OPL::DateFormat format)
 {
 
     if (io_user_input.length() < 10) {
@@ -33,10 +33,10 @@ void ADate::tryToFix(QString &io_user_input, Opl::Date::ADateFormat format)
 }
 
 // Input contains seperators and is of length 8
-void ADate::padCentury(QString &io_user_input, Opl::Date::ADateFormat format)
+void ADate::padCentury(QString &io_user_input, OPL::DateFormat format)
 {
     switch (format) {
-    case Opl::Date::ADateFormat::ISODate: {
+    case OPL::DateFormat::ISODate: {
         int year = io_user_input.left(2).toInt();
         if (year > 50)
             io_user_input.prepend(QStringLiteral("19"));
@@ -44,7 +44,7 @@ void ADate::padCentury(QString &io_user_input, Opl::Date::ADateFormat format)
             io_user_input.prepend(QStringLiteral("20"));
         break;
     }
-    case Opl::Date::ADateFormat::DE: {
+    case OPL::DateFormat::DE: {
         int year = io_user_input.right(2).toInt();
         if (year > 50)
             io_user_input.insert(6, QStringLiteral("19"));
@@ -52,7 +52,7 @@ void ADate::padCentury(QString &io_user_input, Opl::Date::ADateFormat format)
             io_user_input.insert(6, QStringLiteral("20"));
         break;
     }
-    case Opl::Date::ADateFormat::EN: {
+    case OPL::DateFormat::EN: {
         int year = io_user_input.right(2).toInt();
         if (year > 50)
             io_user_input.insert(6, QStringLiteral("19"));
@@ -84,10 +84,10 @@ void ADate::padZeroes(QString &io_user_input)
     DEB << "Padded zeroes: " << io_user_input;
 }
 // 10.10.2020
-void ADate::addSeperators(QString &io_user_input, const Opl::Date::ADateFormat &format)
+void ADate::addSeperators(QString &io_user_input, const OPL::DateFormat &format)
 {
     switch (format) {
-    case Opl::Date::ADateFormat::ISODate:
+    case OPL::DateFormat::ISODate:
         if (io_user_input.length() > 7) {
             io_user_input.insert(4, QLatin1Char('-'));
             io_user_input.insert(7, QLatin1Char('-'));
@@ -96,11 +96,11 @@ void ADate::addSeperators(QString &io_user_input, const Opl::Date::ADateFormat &
             io_user_input.insert(5, QLatin1Char('-'));
         }
         break;
-    case Opl::Date::ADateFormat::DE:
+    case OPL::DateFormat::DE:
             io_user_input.insert(2, QLatin1Char('.'));
             io_user_input.insert(5, QLatin1Char('.'));
         break;
-    case Opl::Date::ADateFormat::EN:
+    case OPL::DateFormat::EN:
             io_user_input.insert(2, QLatin1Char('/'));
             io_user_input.insert(5, QLatin1Char('/'));
         break;
@@ -127,8 +127,13 @@ const QStringList& ADate::getDisplayNames()
     return DISPLAY_NAMES;
 }
 
-const QString ADate::getFormatString(Opl::Date::ADateFormat format)
+const QString ADate::getFormatString(OPL::DateFormat format)
 {
     return ADATEFORMATSMAP.value(format);
 }
 
+const QString ADate::currentDate()
+{
+    return QDate::currentDate().toString(Qt::ISODate);
+}
+

+ 17 - 11
src/functions/adate.h

@@ -6,10 +6,10 @@ const static auto ISO = QStringLiteral("yyyy-MM-dd");
 const static auto DE = QStringLiteral("dd.MM.yyyy");
 const static auto EN = QStringLiteral("MM/dd/yyyy");
 
-const static QHash<Opl::Date::ADateFormat, QString> ADATEFORMATSMAP = {
-    {Opl::Date::ADateFormat::ISODate, ISO},
-    {Opl::Date::ADateFormat::DE,      DE },
-    {Opl::Date::ADateFormat::EN,      EN },
+const static QMap<OPL::DateFormat, QString> ADATEFORMATSMAP = {
+    {OPL::DateFormat::ISODate, ISO},
+    {OPL::DateFormat::DE,      DE },
+    {OPL::DateFormat::EN,      EN },
 
 };
 
@@ -30,35 +30,41 @@ public:
      * \brief takes a user-provided input and tries to convert it to a (valid) QDate.
      * \return QDate (invalid if input not recognized)
      */
-    static QDate parseInput(QString &io_user_input, Opl::Date::ADateFormat format);
+    static QDate parseInput(QString &io_user_input, OPL::DateFormat format);
 
-    static void tryToFix(QString &io_user_input, Opl::Date::ADateFormat format);
+    static void tryToFix(QString &io_user_input, OPL::DateFormat format);
 
     /*!
      * \brief padCentury adds the century to a date where it was omitted
      */
-    static void padCentury(QString &io_user_input, Opl::Date::ADateFormat format);
+    static void padCentury(QString &io_user_input, OPL::DateFormat format);
 
     /*!
      * \brief pads a user-provided date string with 0s to facilitate conversion to QDate
      */
     static void padZeroes(QString &io_user_input);
 
-    static void addSeperators(QString &io_user_input, const Opl::Date::ADateFormat &format);
+    static void addSeperators(QString &io_user_input, const OPL::DateFormat &format);
 
     static bool containsSeperator(const QString &user_input);
 
     /*!
-     * \brief Reimplements QDate::toString to accept Opl::Date::ADateFormat enums
+     * \brief Reimplements QDate::toString to accept OPL::Date::ADateFormat enums
      */
-    inline static QString toString(const QDate &date, Opl::Date::ADateFormat format = Opl::Date::ADateFormat::ISODate)
+    inline static QString toString(const QDate &date, OPL::DateFormat format = OPL::DateFormat::ISODate)
     {
         return date.toString(ADATEFORMATSMAP.value(format));
     };
 
     static const QStringList& getDisplayNames();
 
-    static const QString getFormatString(Opl::Date::ADateFormat format);
+    static const QString getFormatString(OPL::DateFormat format);
+
+    /*!
+     * \brief today Returns a string containing the current date in ISO format
+     * \return
+     */
+    static const QString currentDate();
 
 };
 

+ 3 - 3
src/functions/adatetime.h

@@ -26,11 +26,11 @@ namespace ADateTime {
  * \brief toString formats a QDateTime object into a string in a uniform way.
  * \return
  */
-inline const QString toString (const QDateTime& date_time, Opl::Datetime::DateTimeFormat format) {
+inline const QString toString (const QDateTime& date_time, OPL::DateTimeFormat format) {
     switch (format) {
-    case Opl::Datetime::Default:
+    case OPL::DateTimeFormat::Default:
         return date_time.toString(Qt::ISODate);
-    case Opl::Datetime::Backup:
+    case OPL::DateTimeFormat::Backup:
         return date_time.toString(QStringLiteral("yyyy_MM_dd_T_hh_mm"));
     default:
         return QString();

+ 12 - 12
src/functions/atime.h

@@ -28,13 +28,13 @@ namespace ATime {
 /*!
  * \brief Converts a QTime to a String to be used in the UI
  */
-inline const QString toString(const QTime &time, Opl::Time::FlightTimeFormat format = Opl::Time::Default)
+inline const QString toString(const QTime &time, OPL::FlightTimeFormat format = OPL::FlightTimeFormat::Default)
 {
     switch (format) {
-    case Opl::Time::Default:
+    case OPL::FlightTimeFormat::Default:
         return time.toString(QStringLiteral("hh:mm"));
         break;
-    case Opl::Time::Decimal:
+    case OPL::FlightTimeFormat::Decimal:
         return QString::number(((time.hour() * 60 + time.minute() )/60.0), 'f', 2);
         break;
     default:
@@ -45,10 +45,10 @@ inline const QString toString(const QTime &time, Opl::Time::FlightTimeFormat for
 /*!
  * \brief Converts an integer of minutes as received from the Datbase to a String
  */
-inline const QString toString(int minutes_in, Opl::Time::FlightTimeFormat format = Opl::Time::Default)
+inline const QString toString(int minutes_in, OPL::FlightTimeFormat format = OPL::FlightTimeFormat::Default)
 {
     switch (format) {
-    case Opl::Time::Default:
+    case OPL::FlightTimeFormat::Default:
     {
         QString hour = QString::number(minutes_in / 60);
         if (hour.size() < 2) {
@@ -60,7 +60,7 @@ inline const QString toString(int minutes_in, Opl::Time::FlightTimeFormat format
         }
         return hour + ':' + minute;
     }
-    case Opl::Time::Decimal:
+    case OPL::FlightTimeFormat::Decimal:
     {
         int hour = minutes_in / 60;
         double minute = (minutes_in % 60) / 60.0;
@@ -84,13 +84,13 @@ inline QTime qTimefromMinutes(int total_minutes)
     return QTime(hour, minute, 0);
 }
 
-inline const QTime fromString(QString time_string, Opl::Time::FlightTimeFormat format = Opl::Time::Default)
+inline const QTime fromString(QString time_string, OPL::FlightTimeFormat format = OPL::FlightTimeFormat::Default)
 {
     switch (format) {
-    case Opl::Time::Default:
+    case OPL::FlightTimeFormat::Default:
         return QTime::fromString(time_string, QStringLiteral("hh:mm"));
         break;
-    case Opl::Time::Decimal:
+    case OPL::FlightTimeFormat::Decimal:
     {
         double decimal_time = time_string.toDouble();
         int hour = decimal_time;
@@ -103,13 +103,13 @@ inline const QTime fromString(QString time_string, Opl::Time::FlightTimeFormat f
     }
 }
 
-inline const QTime fromString(const char* time_string, Opl::Time::FlightTimeFormat format = Opl::Time::Default)
+inline const QTime fromString(const char* time_string, OPL::FlightTimeFormat format = OPL::FlightTimeFormat::Default)
 {
     switch (format) {
-    case Opl::Time::Default:
+    case OPL::FlightTimeFormat::Default:
         return QTime::fromString(time_string, QStringLiteral("hh:mm"));
         break;
-    case Opl::Time::Decimal:
+    case OPL::FlightTimeFormat::Decimal:
     {
         double decimal_time = QString(time_string).toDouble();
         int hour = decimal_time;

+ 12 - 10
src/gui/dialogues/firstrundialog.cpp

@@ -41,11 +41,13 @@ FirstRunDialog::FirstRunDialog(QWidget *parent) :
     ui->stackedWidget->setCurrentIndex(0);
     ui->lastnameLineEdit->setFocus();
     ui->previousPushButton->setEnabled(false);
-    ui->logoLabel->setPixmap(QPixmap(Opl::Assets::LOGO));
+    ui->logoLabel->setPixmap(QPixmap(OPL::Assets::LOGO));
 
     // Approach Combo Box and Function Combo Box
-    Opl::loadApproachTypes(ui->approachComboBox);
-    Opl::loadPilotFunctios(ui->functionComboBox);
+    OPL::GLOBALS->loadApproachTypes(ui->approachComboBox);
+    OPL::GLOBALS->loadPilotFunctios(ui->functionComboBox);
+    OPL::GLOBALS->fillViewNamesComboBox(ui->logbookViewComboBox);
+
 
     // Style combo box
     const QSignalBlocker style_blocker(ui->styleComboBox);
@@ -55,7 +57,7 @@ FirstRunDialog::FirstRunDialog(QWidget *parent) :
     // Prepare Date Edits
     const auto date_edits = this->findChildren<QDateEdit *>();
     for (const auto &date_edit : date_edits) {
-        date_edit->setDisplayFormat(ADate::getFormatString(Opl::Date::ADateFormat::ISODate));
+        date_edit->setDisplayFormat(ADate::getFormatString(OPL::DateFormat::ISODate));
         date_edit->setDate(QDate::currentDate());
     }
     // Debug - use ctrl + t to enable branchLineEdit to select from which git branch the templates are pulled
@@ -317,12 +319,12 @@ bool FirstRunDialog::setupDatabase()
 bool FirstRunDialog::createUserEntry()
 {
     QHash<QString, QVariant> data;
-    data.insert(Opl::Db::PILOTS_LASTNAME,   ui->lastnameLineEdit->text());
-    data.insert(Opl::Db::PILOTS_FIRSTNAME,  ui->firstnameLineEdit->text());
-    data.insert(Opl::Db::PILOTS_ALIAS,      QStringLiteral("self"));
-    data.insert(Opl::Db::PILOTS_EMPLOYEEID, ui->employeeidLineEdit->text());
-    data.insert(Opl::Db::PILOTS_PHONE,      ui->phoneLineEdit->text());
-    data.insert(Opl::Db::PILOTS_EMAIL,      ui->emailLineEdit->text());
+    data.insert(OPL::Db::PILOTS_LASTNAME,   ui->lastnameLineEdit->text());
+    data.insert(OPL::Db::PILOTS_FIRSTNAME,  ui->firstnameLineEdit->text());
+    data.insert(OPL::Db::PILOTS_ALIAS,      QStringLiteral("self"));
+    data.insert(OPL::Db::PILOTS_EMPLOYEEID, ui->employeeidLineEdit->text());
+    data.insert(OPL::Db::PILOTS_PHONE,      ui->phoneLineEdit->text());
+    data.insert(OPL::Db::PILOTS_EMAIL,      ui->emailLineEdit->text());
 
     auto pilot = APilotEntry(1);
     pilot.setData(data);

+ 1 - 12
src/gui/dialogues/firstrundialog.ui

@@ -24,7 +24,7 @@
    <item row="2" column="0" colspan="2">
     <widget class="QStackedWidget" name="stackedWidget">
      <property name="currentIndex">
-      <number>4</number>
+      <number>3</number>
      </property>
      <widget class="QWidget" name="personalDataPage">
       <layout class="QGridLayout" name="gridLayout_9">
@@ -147,7 +147,6 @@
         <widget class="QLabel" name="importLabel">
          <property name="font">
           <font>
-           <weight>75</weight>
            <bold>true</bold>
           </font>
          </property>
@@ -740,16 +739,6 @@
            <property name="toolTip">
             <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Determines how your logbook is displayed in the logbook tab. This has no influence on what details are logged, just on what is displayed by default.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
            </property>
-           <item>
-            <property name="text">
-             <string>Default</string>
-            </property>
-           </item>
-           <item>
-            <property name="text">
-             <string>EASA Part-FCL</string>
-            </property>
-           </item>
           </widget>
          </item>
         </layout>

+ 120 - 91
src/gui/dialogues/newflightdialog.cpp

@@ -39,18 +39,18 @@ NewFlightDialog::NewFlightDialog(ACompletionData &completion_data,
     flightEntry = AFlightEntry();
     // Set up UI (New Flight)
     LOG << ASettings::read(ASettings::FlightLogging::Function);
-    if(ASettings::read(ASettings::FlightLogging::Function).toInt() == Opl::PIC){
+    if(ASettings::read(ASettings::FlightLogging::Function).toInt() == OPL::PIC){
         ui->picNameLineEdit->setText(self);
         ui->functionComboBox->setCurrentIndex(0);
         emit ui->picNameLineEdit->editingFinished();
     }
-    if (ASettings::read(ASettings::FlightLogging::Function).toInt() == Opl::SIC) {
+    if (ASettings::read(ASettings::FlightLogging::Function).toInt() == OPL::SIC) {
         ui->sicNameLineEdit->setText(self);
         ui->functionComboBox->setCurrentIndex(2);
         emit ui->sicNameLineEdit->editingFinished();
     }
 
-    ui->doftLineEdit->setText(QDate::currentDate().toString(Qt::ISODate));
+    ui->doftLineEdit->setText(ADate::currentDate());
     emit ui->doftLineEdit->editingFinished();
 }
 
@@ -89,8 +89,8 @@ void NewFlightDialog::init()
     for (const auto& line_edit : *mandatoryLineEdits)
         line_edit->installEventFilter(this);
     // Approach Combo Box and Function Combo Box
-    Opl::loadApproachTypes(ui->approachComboBox);
-    Opl::loadPilotFunctios(ui->functionComboBox);
+    OPL::GLOBALS->loadApproachTypes(ui->approachComboBox);
+    OPL::GLOBALS->loadPilotFunctios(ui->functionComboBox);
 
     setupRawInputValidation();
     setupSignalsAndSlots();
@@ -197,55 +197,52 @@ void NewFlightDialog::fillWithEntryData()
     DEB << flightEntry;
 
     // Date of Flight
-    ui->doftLineEdit->setText(flightEntry.getData().value(Opl::Db::FLIGHTS_DOFT).toString());
+    ui->doftLineEdit->setText(flightEntry.getData().value(OPL::Db::FLIGHTS_DOFT).toString());
     // Location
-    ui->deptLocationLineEdit->setText(flightEntry.getData().value(Opl::Db::FLIGHTS_DEPT).toString());
-    ui->destLocationLineEdit->setText(flightEntry.getData().value(Opl::Db::FLIGHTS_DEST).toString());
+    ui->deptLocationLineEdit->setText(flightEntry.getData().value(OPL::Db::FLIGHTS_DEPT).toString());
+    ui->destLocationLineEdit->setText(flightEntry.getData().value(OPL::Db::FLIGHTS_DEST).toString());
     // Times
-    ui->tofbTimeLineEdit->setText(ATime::toString(flightEntry.getData().value(Opl::Db::FLIGHTS_TOFB).toInt()));
-    ui->tonbTimeLineEdit->setText(ATime::toString(flightEntry.getData().value(Opl::Db::FLIGHTS_TONB).toInt()));
-    ui->acftLineEdit->setText(completionData.tailsIdMap.value(flightEntry.getData().value(Opl::Db::FLIGHTS_ACFT).toInt()));
-    ui->picNameLineEdit->setText(completionData.pilotsIdMap.value(flightEntry.getData().value(Opl::Db::FLIGHTS_PIC).toInt()));
-    ui->sicNameLineEdit->setText(completionData.pilotsIdMap.value(flightEntry.getData().value(Opl::Db::FLIGHTS_SECONDPILOT).toInt()));
-    ui->thirdPilotNameLineEdit->setText(completionData.pilotsIdMap.value(flightEntry.getData().value(Opl::Db::FLIGHTS_THIRDPILOT).toInt()));
-
-    for (const auto& le : *mandatoryLineEdits)
-        emit le->editingFinished();
+    ui->tofbTimeLineEdit->setText(ATime::toString(flightEntry.getData().value(OPL::Db::FLIGHTS_TOFB).toInt()));
+    ui->tonbTimeLineEdit->setText(ATime::toString(flightEntry.getData().value(OPL::Db::FLIGHTS_TONB).toInt()));
+    ui->acftLineEdit->setText(completionData.tailsIdMap.value(flightEntry.getData().value(OPL::Db::FLIGHTS_ACFT).toInt()));
+    ui->picNameLineEdit->setText(completionData.pilotsIdMap.value(flightEntry.getData().value(OPL::Db::FLIGHTS_PIC).toInt()));
+    ui->sicNameLineEdit->setText(completionData.pilotsIdMap.value(flightEntry.getData().value(OPL::Db::FLIGHTS_SECONDPILOT).toInt()));
+    ui->thirdPilotNameLineEdit->setText(completionData.pilotsIdMap.value(flightEntry.getData().value(OPL::Db::FLIGHTS_THIRDPILOT).toInt()));
 
     //Function
     const QHash<int, QString> functions = {
-        {0, Opl::Db::FLIGHTS_TPIC},
-        {1, Opl::Db::FLIGHTS_TPICUS},
-        {2, Opl::Db::FLIGHTS_TSIC},
-        {3, Opl::Db::FLIGHTS_TDUAL},
-        {4, Opl::Db::FLIGHTS_TFI},
+        {0, OPL::Db::FLIGHTS_TPIC},
+        {1, OPL::Db::FLIGHTS_TPICUS},
+        {2, OPL::Db::FLIGHTS_TSIC},
+        {3, OPL::Db::FLIGHTS_TDUAL},
+        {4, OPL::Db::FLIGHTS_TFI},
     };
     for (int i = 0; i < 5; i++) { // QHash::iterator not guarenteed to be in ordetr
         if(flightEntry.getData().value(functions.value(i)).toInt() != 0)
             ui->functionComboBox->setCurrentIndex(i);
     }
     // Approach ComboBox
-    const QString& app = flightEntry.getData().value(Opl::Db::FLIGHTS_APPROACHTYPE).toString();
+    const QString& app = flightEntry.getData().value(OPL::Db::FLIGHTS_APPROACHTYPE).toString();
     if(app != QString()){
         ui->approachComboBox->setCurrentText(app);
     }
     // Task
-    bool PF = flightEntry.getData().value(Opl::Db::FLIGHTS_PILOTFLYING).toBool();
+    bool PF = flightEntry.getData().value(OPL::Db::FLIGHTS_PILOTFLYING).toBool();
     ui->pilotFlyingCheckBox->setChecked(PF);
     // Flight Rules
-    bool time_ifr = flightEntry.getData().value(Opl::Db::FLIGHTS_TIFR).toBool();
+    bool time_ifr = flightEntry.getData().value(OPL::Db::FLIGHTS_TIFR).toBool();
     ui->ifrCheckBox->setChecked(time_ifr);
     // Take-Off and Landing
-    int TO = flightEntry.getData().value(Opl::Db::FLIGHTS_TODAY).toInt()
-            + flightEntry.getData().value(Opl::Db::FLIGHTS_TONIGHT).toInt();
-    int LDG = flightEntry.getData().value(Opl::Db::FLIGHTS_LDGDAY).toInt()
-            + flightEntry.getData().value(Opl::Db::FLIGHTS_LDGNIGHT).toInt();
+    int TO = flightEntry.getData().value(OPL::Db::FLIGHTS_TODAY).toInt()
+            + flightEntry.getData().value(OPL::Db::FLIGHTS_TONIGHT).toInt();
+    int LDG = flightEntry.getData().value(OPL::Db::FLIGHTS_LDGDAY).toInt()
+            + flightEntry.getData().value(OPL::Db::FLIGHTS_LDGNIGHT).toInt();
     ui->takeOffSpinBox->setValue(TO);
     ui->landingSpinBox->setValue(LDG);
     // Remarks
-    ui->remarksLineEdit->setText(flightEntry.getData().value(Opl::Db::FLIGHTS_REMARKS).toString());
+    ui->remarksLineEdit->setText(flightEntry.getData().value(OPL::Db::FLIGHTS_REMARKS).toString());
     // Flight Number
-    ui->flightNumberLineEdit->setText(flightEntry.getData().value(Opl::Db::FLIGHTS_FLIGHTNUMBER).toString());
+    ui->flightNumberLineEdit->setText(flightEntry.getData().value(OPL::Db::FLIGHTS_FLIGHTNUMBER).toString());
 
     for(const auto &line_edit : *mandatoryLineEdits)
         emit line_edit->editingFinished();
@@ -264,13 +261,12 @@ void NewFlightDialog::onGoodInputReceived(QLineEdit *line_edit)
         if (validationState.nightDataValid())
             updateNightCheckBoxes();
     }
-        validationState.printValidationStatus();
 }
 
 void NewFlightDialog::onBadInputReceived(QLineEdit *line_edit)
 {
     DEB << line_edit->objectName() << " - Bad input received - " << line_edit->text();
-    line_edit->setStyleSheet(QStringLiteral("border: 1px solid red"));
+    line_edit->setStyleSheet(OPL::Styles::RED_BORDER);
     line_edit->setText(QString());
 
     if (mandatoryLineEdits->contains(line_edit))
@@ -377,51 +373,51 @@ RowData_T NewFlightDialog::prepareFlightEntryData()
     const auto night_time_data = ACalc::NightTimeValues(ui->deptLocationLineEdit->text(), ui->destLocationLineEdit->text(),
                            departure_date_time, block_minutes, ASettings::read(ASettings::FlightLogging::NightAngle).toInt());
     // Mandatory data
-    new_data.insert(Opl::Db::FLIGHTS_DOFT, ui->doftLineEdit->text());
-    new_data.insert(Opl::Db::FLIGHTS_DEPT, ui->deptLocationLineEdit->text());
-    new_data.insert(Opl::Db::FLIGHTS_TOFB, ATime::toMinutes(ui->tofbTimeLineEdit->text()));
-    new_data.insert(Opl::Db::FLIGHTS_DEST, ui->destLocationLineEdit->text());
-    new_data.insert(Opl::Db::FLIGHTS_TONB, ATime::toMinutes(ui->tonbTimeLineEdit->text()));
-    new_data.insert(Opl::Db::FLIGHTS_TBLK, block_minutes);
+    new_data.insert(OPL::Db::FLIGHTS_DOFT, ui->doftLineEdit->text());
+    new_data.insert(OPL::Db::FLIGHTS_DEPT, ui->deptLocationLineEdit->text());
+    new_data.insert(OPL::Db::FLIGHTS_TOFB, ATime::toMinutes(ui->tofbTimeLineEdit->text()));
+    new_data.insert(OPL::Db::FLIGHTS_DEST, ui->destLocationLineEdit->text());
+    new_data.insert(OPL::Db::FLIGHTS_TONB, ATime::toMinutes(ui->tonbTimeLineEdit->text()));
+    new_data.insert(OPL::Db::FLIGHTS_TBLK, block_minutes);
     // Night
-    new_data.insert(Opl::Db::FLIGHTS_TNIGHT, night_time_data.nightMinutes);
+    new_data.insert(OPL::Db::FLIGHTS_TNIGHT, night_time_data.nightMinutes);
     // Aircraft
     int acft_id = completionData.tailsIdMap.key(ui->acftLineEdit->text());
-    new_data.insert(Opl::Db::FLIGHTS_ACFT, acft_id);
+    new_data.insert(OPL::Db::FLIGHTS_ACFT, acft_id);
     const ATailEntry acft_data = aDB->getTailEntry(acft_id);
-    bool multi_pilot = acft_data.getData().value(Opl::Db::TAILS_MULTIPILOT).toBool();
-    bool multi_engine = acft_data.getData().value(Opl::Db::TAILS_MULTIENGINE).toBool();
+    bool multi_pilot = acft_data.getData().value(OPL::Db::TAILS_MULTIPILOT).toBool();
+    bool multi_engine = acft_data.getData().value(OPL::Db::TAILS_MULTIENGINE).toBool();
 
     if (multi_pilot) {
-        new_data.insert(Opl::Db::FLIGHTS_TMP, block_minutes);
-        new_data.insert(Opl::Db::FLIGHTS_TSPSE, QString());
-        new_data.insert(Opl::Db::FLIGHTS_TSPME, QString());
+        new_data.insert(OPL::Db::FLIGHTS_TMP, block_minutes);
+        new_data.insert(OPL::Db::FLIGHTS_TSPSE, QString());
+        new_data.insert(OPL::Db::FLIGHTS_TSPME, QString());
     } else if (!multi_pilot && !multi_engine) {
-        new_data.insert(Opl::Db::FLIGHTS_TMP, QString());
-        new_data.insert(Opl::Db::FLIGHTS_TSPSE, block_minutes);
-        new_data.insert(Opl::Db::FLIGHTS_TSPME, QString());
+        new_data.insert(OPL::Db::FLIGHTS_TMP, QString());
+        new_data.insert(OPL::Db::FLIGHTS_TSPSE, block_minutes);
+        new_data.insert(OPL::Db::FLIGHTS_TSPME, QString());
     } else if (!multi_pilot && multi_engine) {
-        new_data.insert(Opl::Db::FLIGHTS_TMP, QString());
-        new_data.insert(Opl::Db::FLIGHTS_TSPSE, QString());
-        new_data.insert(Opl::Db::FLIGHTS_TSPME, block_minutes);
+        new_data.insert(OPL::Db::FLIGHTS_TMP, QString());
+        new_data.insert(OPL::Db::FLIGHTS_TSPSE, QString());
+        new_data.insert(OPL::Db::FLIGHTS_TSPME, block_minutes);
     }
     // Pilots
-    new_data.insert(Opl::Db::FLIGHTS_PIC, completionData.pilotsIdMap.key(ui->picNameLineEdit->text()));
-    new_data.insert(Opl::Db::FLIGHTS_SECONDPILOT, completionData.pilotsIdMap.key(ui->sicNameLineEdit->text()));
-    new_data.insert(Opl::Db::FLIGHTS_THIRDPILOT, completionData.pilotsIdMap.key(ui->thirdPilotNameLineEdit->text()));
+    new_data.insert(OPL::Db::FLIGHTS_PIC, completionData.pilotsIdMap.key(ui->picNameLineEdit->text()));
+    new_data.insert(OPL::Db::FLIGHTS_SECONDPILOT, completionData.pilotsIdMap.key(ui->sicNameLineEdit->text()));
+    new_data.insert(OPL::Db::FLIGHTS_THIRDPILOT, completionData.pilotsIdMap.key(ui->thirdPilotNameLineEdit->text()));
     // IFR time
     if (ui->ifrCheckBox->isChecked()) {
-        new_data.insert(Opl::Db::FLIGHTS_TIFR, block_minutes);
+        new_data.insert(OPL::Db::FLIGHTS_TIFR, block_minutes);
     } else {
-        new_data.insert(Opl::Db::FLIGHTS_TIFR, QString());
+        new_data.insert(OPL::Db::FLIGHTS_TIFR, QString());
     }
     // Function Times
     QStringList function_times = {
-        Opl::Db::FLIGHTS_TPIC,
-        Opl::Db::FLIGHTS_TPICUS,
-        Opl::Db::FLIGHTS_TSIC,
-        Opl::Db::FLIGHTS_TDUAL,
-        Opl::Db::FLIGHTS_TFI,
+        OPL::Db::FLIGHTS_TPIC,
+        OPL::Db::FLIGHTS_TPICUS,
+        OPL::Db::FLIGHTS_TSIC,
+        OPL::Db::FLIGHTS_TDUAL,
+        OPL::Db::FLIGHTS_TFI,
     };
 
     // Determine function times, zero out all values except one
@@ -429,6 +425,7 @@ RowData_T NewFlightDialog::prepareFlightEntryData()
     const int& function_index = ui->functionComboBox->currentIndex();
     switch (function_index) {
     case 4:
+        LOG << "Function FI";
         for (int i = 0; i < 5; i++){
             if(i == 0 || i == 4)
                 new_data.insert(function_times[i], block_minutes);
@@ -446,29 +443,29 @@ RowData_T NewFlightDialog::prepareFlightEntryData()
         break;
     }
     // Pilot flying / Pilot monitoring
-    new_data.insert(Opl::Db::FLIGHTS_PILOTFLYING, ui->pilotFlyingCheckBox->isChecked());
+    new_data.insert(OPL::Db::FLIGHTS_PILOTFLYING, ui->pilotFlyingCheckBox->isChecked());
     // Take-Off and Landing
     if (ui->toNightCheckBox->isChecked()) {
-        new_data.insert(Opl::Db::FLIGHTS_TONIGHT, ui->takeOffSpinBox->value());
-        new_data.insert(Opl::Db::FLIGHTS_TODAY, 0);
+        new_data.insert(OPL::Db::FLIGHTS_TONIGHT, ui->takeOffSpinBox->value());
+        new_data.insert(OPL::Db::FLIGHTS_TODAY, 0);
     } else {
-        new_data.insert(Opl::Db::FLIGHTS_TONIGHT, 0);
-        new_data.insert(Opl::Db::FLIGHTS_TODAY, ui->takeOffSpinBox->value());
+        new_data.insert(OPL::Db::FLIGHTS_TONIGHT, 0);
+        new_data.insert(OPL::Db::FLIGHTS_TODAY, ui->takeOffSpinBox->value());
     }
     if (ui->ldgNightCheckBox->isChecked()) {
-        new_data.insert(Opl::Db::FLIGHTS_LDGNIGHT, ui->landingSpinBox->value());
-        new_data.insert(Opl::Db::FLIGHTS_LDGDAY, 0);
+        new_data.insert(OPL::Db::FLIGHTS_LDGNIGHT, ui->landingSpinBox->value());
+        new_data.insert(OPL::Db::FLIGHTS_LDGDAY, 0);
     } else {
-        new_data.insert(Opl::Db::FLIGHTS_LDGNIGHT, 0);
-        new_data.insert(Opl::Db::FLIGHTS_LDGDAY, ui->landingSpinBox->value());
+        new_data.insert(OPL::Db::FLIGHTS_LDGNIGHT, 0);
+        new_data.insert(OPL::Db::FLIGHTS_LDGDAY, ui->landingSpinBox->value());
     }
-    if (ui->approachComboBox->currentText() == Opl::APPROACH_TYPES[3]) // ILS CAT III
-        new_data.insert(Opl::Db::FLIGHTS_AUTOLAND, ui->landingSpinBox->value());
+    if (ui->approachComboBox->currentText() == OPL::GLOBALS->getApproachTypes()[3]) // ILS CAT III
+        new_data.insert(OPL::Db::FLIGHTS_AUTOLAND, ui->landingSpinBox->value());
 
     // Additional Data
-    new_data.insert(Opl::Db::FLIGHTS_APPROACHTYPE, ui->approachComboBox->currentText());
-    new_data.insert(Opl::Db::FLIGHTS_FLIGHTNUMBER, ui->flightNumberLineEdit->text());
-    new_data.insert(Opl::Db::FLIGHTS_REMARKS, ui->remarksLineEdit->text());
+    new_data.insert(OPL::Db::FLIGHTS_APPROACHTYPE, ui->approachComboBox->currentText());
+    new_data.insert(OPL::Db::FLIGHTS_FLIGHTNUMBER, ui->flightNumberLineEdit->text());
+    new_data.insert(OPL::Db::FLIGHTS_REMARKS, ui->remarksLineEdit->text());
     return new_data;
 }
 
@@ -537,23 +534,19 @@ void NewFlightDialog::onPilotNameLineEdit_editingFinshed()
     auto line_edit = this->findChild<QLineEdit*>(sender()->objectName());
     DEB << line_edit->objectName() << "Editing Finished -" << line_edit->text();
 
+    int pilot_id = 0;
+
+    // Check for self and try mapping to rowid
     if(line_edit->text().contains(self, Qt::CaseInsensitive)) {
         DEB << "self recognized.";
         line_edit->setText(completionData.pilotsIdMap.value(1));
-        if (line_edit->objectName() == QLatin1String("picNameLineEdit"))
-            ui->functionComboBox->setCurrentIndex(0);
-        else if (line_edit->objectName() == QLatin1String("sicNameLineEdit"))
-            ui->functionComboBox->setCurrentIndex(2);
+        pilot_id = 1;
+    } else
+        pilot_id = completionData.pilotsIdMap.key(line_edit->text());
 
-        onGoodInputReceived(line_edit);
-        return;
-    }
 
-    int pilot_id = completionData.pilotsIdMap.key(line_edit->text());
     if(pilot_id != 0) {
         DEB << "Mapped: " << line_edit->text() << pilot_id;
-        if (line_edit->objectName() == QLatin1String("picNameLineEdit") && pilot_id == 1)
-            ui->functionComboBox->setCurrentIndex(0);
         onGoodInputReceived(line_edit);
         return;
     }
@@ -571,6 +564,7 @@ void NewFlightDialog::onPilotNameLineEdit_editingFinshed()
         return;
     }
 
+    // Fall through to adding new pilot to database
     if(!addNewPilot(*line_edit))
         onBadInputReceived(line_edit);
 }
@@ -638,7 +632,7 @@ void NewFlightDialog::on_doftLineEdit_editingFinished()
     auto label = ui->doftDisplayLabel;
 
     TODO << "Non-default Date formats not implemented yet.";
-    Opl::Date::ADateFormat date_format = Opl::Date::ADateFormat::ISODate;
+    OPL::DateFormat date_format = OPL::DateFormat::ISODate;
     auto date = ADate::parseInput(text, date_format);
     if (date.isValid()) {
         label->setText(date.toString(Qt::TextDate));
@@ -675,13 +669,14 @@ void NewFlightDialog::on_approachComboBox_currentTextChanged(const QString &arg1
  */
 void NewFlightDialog::on_functionComboBox_currentIndexChanged(int index)
 {
-    if (index == 0) {
+    DEB << "Current Index: " << index;
+    if (index == OPL::PilotFunction::PIC) {
         ui->picNameLineEdit->setText(self);
         emit ui->picNameLineEdit->editingFinished();
         if (completionData.pilotsIdMap.key(ui->picNameLineEdit->text())
          == completionData.pilotsIdMap.key(ui->sicNameLineEdit->text()))
                 ui->sicNameLineEdit->setText(QString());
-    } else if (index == 2) {
+    } else if (index == OPL::PilotFunction::SIC) {
         ui->sicNameLineEdit->setText(self);
         emit ui->sicNameLineEdit->editingFinished();
         if (completionData.pilotsIdMap.key(ui->picNameLineEdit->text())
@@ -690,6 +685,37 @@ void NewFlightDialog::on_functionComboBox_currentIndexChanged(int index)
     }
 }
 
+/*!
+ * \brief NewFlightDialog::checkPilotFunctionsValid checks if there are incompatible selections made on Pilot Function.
+ * \details Checks for 2 cases in which there might be a discrepancy between the PilotNameLineEdit and the functionComboBox:
+ * - If the pilotNameLineEdit's value is self, but the functionComboBox has been manually selected to be different from either
+ * PIC or FI
+ * - If the functionComboBox has been set to PIC but the pilotNameLineEdit is not self
+ * \param error_msg - the error string displayed to the user
+ * \return
+ */
+bool NewFlightDialog::checkPilotFunctionsValid()
+{
+    int pic_id = completionData.pilotsIdMap.key(ui->picNameLineEdit->text());
+    int function_index = ui->functionComboBox->currentIndex();
+
+    if (pic_id == 1) {
+        if (!(function_index == OPL::PilotFunction::PIC || function_index == OPL::PilotFunction::FI)) {
+            INFO(tr("The PIC is set to %1 but the Pilot Function is set to %2")
+                    .arg(ui->picNameLineEdit->text(), ui->functionComboBox->currentText()));
+            return false;
+        }
+    } else {
+        if (function_index == OPL::PilotFunction::PIC || function_index == OPL::PilotFunction::FI) {
+            INFO(tr("The Pilot Function is set to %1, but the PIC is set to %2")
+                    .arg(ui->functionComboBox->currentText(), ui->picNameLineEdit->text()));
+            return false;
+        }
+    }
+
+    return true;
+}
+
 /*!
  * \brief NewFlightDialog::on_buttonBox_accepted - checks for validity and commits the form data to the database
  * \details When the user is ready to submit a flight entry, a final check for valid entries is made, and the user
@@ -699,8 +725,8 @@ void NewFlightDialog::on_functionComboBox_currentIndexChanged(int index)
  */
 void NewFlightDialog::on_buttonBox_accepted()
 {
-    for (const auto& line_edit : *mandatoryLineEdits)
-        emit line_edit->editingFinished();
+    // Debug
+    validationState.printValidationStatus();
     // If input verification is passed, continue, otherwise prompt user to correct
     if (!validationState.allValid()) {
         const auto display_names = QHash<ValidationItem, QString> {
@@ -725,6 +751,9 @@ void NewFlightDialog::on_buttonBox_accepted()
         return;
     }
 
+    if(!checkPilotFunctionsValid())
+        return;
+
     // If input verification passed, collect input and submit to database
     auto newData = prepareFlightEntryData();
     DEB << "Old Data: ";

+ 3 - 1
src/gui/dialogues/newflightdialog.h

@@ -173,13 +173,15 @@ private:
      */
     void onBadInputReceived(QLineEdit *line_edit);
 
+    void updateBlockTimeLabel();
     void updateNightCheckBoxes();
     void setNightCheckboxes();
-    void updateBlockTimeLabel();
 
     bool addNewTail(QLineEdit& parent_line_edit);
     bool addNewPilot(QLineEdit& parent_line_edit);
 
+
+    bool checkPilotFunctionsValid();
     RowData_T prepareFlightEntryData();
 
 

+ 4 - 1
src/gui/dialogues/newflightdialog.ui

@@ -11,7 +11,7 @@
    </rect>
   </property>
   <property name="windowTitle">
-   <string>Dialog</string>
+   <string>Add New Flight</string>
   </property>
   <layout class="QGridLayout" name="gridLayout_4">
    <item row="0" column="0">
@@ -155,6 +155,9 @@
            <height>16777215</height>
           </size>
          </property>
+         <property name="placeholderText">
+          <string>YYYY-MM-DD</string>
+         </property>
         </widget>
        </item>
        <item row="2" column="0">

+ 3 - 3
src/gui/dialogues/newpilot.ui

@@ -6,12 +6,12 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>230</width>
-    <height>252</height>
+    <width>250</width>
+    <height>260</height>
    </rect>
   </property>
   <property name="windowTitle">
-   <string>Dialog</string>
+   <string>Add New Pilot</string>
   </property>
   <layout class="QGridLayout" name="gridLayout">
    <item row="0" column="0">

+ 187 - 0
src/gui/dialogues/newsimdialog.cpp

@@ -0,0 +1,187 @@
+#include "newsimdialog.h"
+#include "ui_newsimdialog.h"
+#include "src/opl.h"
+#include "src/functions/atime.h"
+#include "src/functions/adate.h"
+#include <QCompleter>
+/*!
+ * \brief create a NewSimDialog to add a new Simulator Entry to the database
+ */
+NewSimDialog::NewSimDialog(QWidget *parent) :
+    QDialog(parent),
+    ui(new Ui::NewSimDialog)
+{
+    entry = ASimulatorEntry();
+    ui->setupUi(this);
+    ui->dateLineEdit->setText(ADate::currentDate());
+    init();
+}
+/*!
+ * \brief create a NewSimDialog to edit an existing Simulator Entry
+ * \param row_id of the entry to be edited
+ */
+NewSimDialog::NewSimDialog(RowId_T row_id, QWidget *parent) :
+    QDialog(parent),
+    ui(new Ui::NewSimDialog)
+{
+
+    ui->setupUi(this);
+    entry = aDB->getSimEntry(row_id);
+    init();
+    fillEntryData();
+}
+
+/*!
+ * \brief set up the UI with Combo Box entries and QCompleter
+ */
+void NewSimDialog::init()
+{
+    OPL::GLOBALS->loadSimulatorTypes(ui->deviceTypeComboBox);
+
+    const QStringList aircraft_list = aDB->getCompletionList(ADatabaseTarget::aircraft);
+    auto completer = new QCompleter(aircraft_list, ui->aircraftTypeLineEdit);
+    completer->setCaseSensitivity(Qt::CaseInsensitive);
+    completer->setCompletionMode(QCompleter::PopupCompletion);
+    completer->setFilterMode(Qt::MatchContains);
+    ui->aircraftTypeLineEdit->setCompleter(completer);
+}
+
+/*!
+ * \brief fills the UI with data retreived from an existing entry.
+ */
+void NewSimDialog::fillEntryData()
+{
+    const auto& data = entry.getData();
+    ui->dateLineEdit->setText(data.value(OPL::Db::SIMULATORS_DATE).toString());
+    ui->totalTimeLineEdit->setText(ATime::toString(data.value(OPL::Db::SIMULATORS_TIME).toInt()));
+    ui->deviceTypeComboBox->setCurrentIndex(data.value(OPL::Db::SIMULATORS_TYPE).toInt());
+    ui->aircraftTypeLineEdit->setText(data.value(OPL::Db::SIMULATORS_ACFT).toString());
+    ui->registrationLineEdit->setText(data.value(OPL::Db::SIMULATORS_REG).toString());
+    ui->remarksLineEdit->setText(data.value(OPL::Db::SIMULATORS_REMARKS).toString());
+}
+
+NewSimDialog::~NewSimDialog()
+{
+    delete ui;
+}
+
+void NewSimDialog::on_dateLineEdit_editingFinished()
+{
+    auto text = ui->dateLineEdit->text();
+
+    OPL::DateFormat date_format = OPL::DateFormat::ISODate;
+    auto date = ADate::parseInput(text, date_format);
+    if (date.isValid()) {
+        ui->dateLineEdit->setText(ADate::toString(date, date_format));
+        ui->dateLineEdit->setStyleSheet(QString());
+        return;
+    } else {
+        ui->dateLineEdit->setText(QString());
+        ui->dateLineEdit->setStyleSheet(OPL::Styles::RED_BORDER);
+    }
+}
+
+
+void NewSimDialog::on_totalTimeLineEdit_editingFinished()
+{
+    const QString time_string = ATime::formatTimeInput(ui->totalTimeLineEdit->text());
+    const QTime time = ATime::fromString(time_string);
+
+    if (time.isValid()) {
+        ui->totalTimeLineEdit->setText(time_string);
+        ui->totalTimeLineEdit->setStyleSheet(QString());
+    } else {
+        ui->totalTimeLineEdit->setText(QString());
+        ui->totalTimeLineEdit->setStyleSheet(OPL::Styles::RED_BORDER);
+    }
+}
+
+void NewSimDialog::on_registrationLineEdit_textChanged(const QString &arg1)
+{
+    ui->registrationLineEdit->setText(arg1.toUpper());
+}
+
+void NewSimDialog::on_helpPushButton_clicked()
+{
+    INFO(tr("<br>"
+         "For  any  FSTD  enter  the  type  of  aircraft  and  qualification "
+         "number  of  the  device.  For  other  flight  training  devices  enter "
+         "either FNPT I or FNPT II as appropriate<br><br>"
+         "Total time of session includes all exercises carried out in the "
+         "device, including pre- and after-flight checks<br><br>"
+         "Enter the type of exercise performed in the ‘remarks’ field "
+            "for example operator proficiency check, revalidation."));
+}
+
+bool NewSimDialog::verifyInput(QString& error_msg)
+{
+    // Date
+    auto text = ui->dateLineEdit->text();
+    OPL::DateFormat date_format = OPL::DateFormat::ISODate;
+    const auto date = ADate::parseInput(text, date_format);
+
+    if (!date.isValid()) {
+        ui->dateLineEdit->setStyleSheet(OPL::Styles::RED_BORDER);
+        ui->dateLineEdit->setText(QString());
+        error_msg = tr("Invalid Date");
+        return false;
+    }
+    // Time
+    const QString time_string = ATime::formatTimeInput(ui->totalTimeLineEdit->text());
+    const QTime time = ATime::fromString(time_string);
+
+    if (!time.isValid()) {
+        ui->totalTimeLineEdit->setStyleSheet(OPL::Styles::RED_BORDER);
+        ui->totalTimeLineEdit->setText(QString());
+        error_msg = tr("Invalid time");
+        return false;
+    }
+
+    // Device Type - for FSTD, aircraft info is required
+    if (ui->deviceTypeComboBox->currentIndex() == OPL::SimulatorType::FSTD
+            && ui->aircraftTypeLineEdit->text() == QString()) {
+        error_msg = tr("For FSTD, please enter the aircraft type.");
+        return false;
+    }
+
+    return true;
+}
+
+RowData_T NewSimDialog::collectInput()
+{
+    RowData_T new_entry;
+    // Date
+    new_entry.insert(OPL::Db::SIMULATORS_DATE, ui->dateLineEdit->text());
+    // Time
+    new_entry.insert(OPL::Db::SIMULATORS_TIME, ATime::toMinutes(ui->totalTimeLineEdit->text()));
+    // Device Type
+    new_entry.insert(OPL::Db::SIMULATORS_TYPE, ui->deviceTypeComboBox->currentText());
+    // Aircraft Type
+    new_entry.insert(OPL::Db::SIMULATORS_ACFT, ui->aircraftTypeLineEdit->text());
+    // Registration
+    if (!ui->registrationLineEdit->text().isEmpty())
+        new_entry.insert(OPL::Db::SIMULATORS_REG, ui->registrationLineEdit->text());
+    // Remarks
+    if (!ui->remarksLineEdit->text().isEmpty())
+        new_entry.insert(OPL::Db::FLIGHTS_REMARKS, ui->remarksLineEdit->text());
+
+    return new_entry;
+}
+
+void NewSimDialog::on_buttonBox_accepted()
+{
+    QString error_msg;
+    if (!verifyInput(error_msg)) {
+        INFO(error_msg);
+        return;
+    }
+
+    entry.setData(collectInput());
+
+    DEB << entry;
+
+    if(aDB->commit(entry))
+        QDialog::accept();
+    else
+        WARN(tr("Unable to commit entry to database. The following error has ocurred <br><br>%1").arg(aDB->lastError.text()));
+}

+ 52 - 0
src/gui/dialogues/newsimdialog.h

@@ -0,0 +1,52 @@
+#ifndef NEWSIMDIALOG_H
+#define NEWSIMDIALOG_H
+
+#include <QDialog>
+#include "src/classes/asimulatorentry.h"
+#include "src/database/adatabase.h"
+#include "src/classes/acompletiondata.h"
+
+namespace Ui {
+class NewSimDialog;
+}
+
+/*!
+ * \brief The NewSimDialog class enables adding a new Simulator Session to the database or editing an existing one.
+ * \details The NewSimDialog offers two constructors, one is used to create a new Simulator Entry
+ * from scratch, while the other one is used to edit an existing entry. The existing entry
+ * is identified by its ROW ID in the database and is then retreived, its data being used
+ * to pre-fill the UI to enable editing the existing data.
+ *
+ * A QCompleter provides in-line completion for the aircraft type field.
+ */
+class NewSimDialog : public QDialog
+{
+    Q_OBJECT
+
+public:
+    explicit NewSimDialog(QWidget *parent = nullptr);
+    explicit NewSimDialog(RowId_T row_id, QWidget *parent = nullptr);
+    ~NewSimDialog();
+
+private slots:
+    void on_buttonBox_accepted();
+
+    void on_dateLineEdit_editingFinished();
+
+    void on_totalTimeLineEdit_editingFinished();
+
+    void on_helpPushButton_clicked();
+
+    void on_registrationLineEdit_textChanged(const QString &arg1);
+
+private:
+    Ui::NewSimDialog *ui;
+    void init();
+    void fillEntryData();
+    bool verifyInput(QString &error_msg);
+    RowData_T collectInput();
+
+    ASimulatorEntry entry;
+};
+
+#endif // NEWSIMDIALOG_H

+ 174 - 0
src/gui/dialogues/newsimdialog.ui

@@ -0,0 +1,174 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>NewSimDialog</class>
+ <widget class="QDialog" name="NewSimDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Add New Simulator Session</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="2" column="0">
+    <widget class="QLabel" name="typeLabel">
+     <property name="text">
+      <string>Simulator Type</string>
+     </property>
+    </widget>
+   </item>
+   <item row="5" column="0">
+    <widget class="QLabel" name="remarksLabel">
+     <property name="text">
+      <string>Remarks</string>
+     </property>
+    </widget>
+   </item>
+   <item row="3" column="0">
+    <widget class="QLabel" name="acftLabel">
+     <property name="text">
+      <string>Aircraft Type</string>
+     </property>
+    </widget>
+   </item>
+   <item row="4" column="0">
+    <widget class="QLabel" name="registrationLabel">
+     <property name="text">
+      <string>Registration</string>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="1">
+    <widget class="QComboBox" name="deviceTypeComboBox">
+     <property name="minimumSize">
+      <size>
+       <width>160</width>
+       <height>0</height>
+      </size>
+     </property>
+    </widget>
+   </item>
+   <item row="4" column="1">
+    <widget class="QLineEdit" name="registrationLineEdit">
+     <property name="minimumSize">
+      <size>
+       <width>160</width>
+       <height>0</height>
+      </size>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="1">
+    <widget class="QLineEdit" name="totalTimeLineEdit">
+     <property name="minimumSize">
+      <size>
+       <width>160</width>
+       <height>0</height>
+      </size>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="0">
+    <widget class="QLabel" name="timeLabel">
+     <property name="text">
+      <string>Total Time of Session</string>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="1">
+    <widget class="QLineEdit" name="dateLineEdit">
+     <property name="minimumSize">
+      <size>
+       <width>160</width>
+       <height>0</height>
+      </size>
+     </property>
+    </widget>
+   </item>
+   <item row="3" column="1">
+    <widget class="QLineEdit" name="aircraftTypeLineEdit">
+     <property name="minimumSize">
+      <size>
+       <width>160</width>
+       <height>0</height>
+      </size>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="0">
+    <widget class="QLabel" name="dateLabel">
+     <property name="text">
+      <string>Date</string>
+     </property>
+    </widget>
+   </item>
+   <item row="5" column="1">
+    <widget class="QLineEdit" name="remarksLineEdit">
+     <property name="minimumSize">
+      <size>
+       <width>160</width>
+       <height>0</height>
+      </size>
+     </property>
+    </widget>
+   </item>
+   <item row="6" column="0">
+    <widget class="QPushButton" name="helpPushButton">
+     <property name="maximumSize">
+      <size>
+       <width>20</width>
+       <height>16777215</height>
+      </size>
+     </property>
+     <property name="text">
+      <string>?</string>
+     </property>
+    </widget>
+   </item>
+   <item row="6" column="1">
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="layoutDirection">
+      <enum>Qt::LeftToRight</enum>
+     </property>
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <tabstops>
+  <tabstop>dateLineEdit</tabstop>
+  <tabstop>totalTimeLineEdit</tabstop>
+  <tabstop>deviceTypeComboBox</tabstop>
+  <tabstop>aircraftTypeLineEdit</tabstop>
+  <tabstop>registrationLineEdit</tabstop>
+  <tabstop>remarksLineEdit</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>NewSimDialog</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>

+ 8 - 8
src/gui/dialogues/newtaildialog.cpp

@@ -123,10 +123,10 @@ void NewTailDialog::fillForm(AEntry entry, bool is_template)
         le->setText(data.value(key).toString());
     }
 
-    ui->operationComboBox->setCurrentIndex(data.value(Opl::Db::TAILS_MULTIPILOT).toInt() + 1);
-    ui->ppNumberComboBox ->setCurrentIndex(data.value(Opl::Db::TAILS_MULTIENGINE).toInt() + 1);
-    ui->ppTypeComboBox->setCurrentIndex(data.value(Opl::Db::TAILS_ENGINETYPE).toInt() + 1);
-    ui->weightComboBox->setCurrentIndex(data.value(Opl::Db::TAILS_WEIGHTCLASS).toInt() + 1);
+    ui->operationComboBox->setCurrentIndex(data.value(OPL::Db::TAILS_MULTIPILOT).toInt() + 1);
+    ui->ppNumberComboBox ->setCurrentIndex(data.value(OPL::Db::TAILS_MULTIENGINE).toInt() + 1);
+    ui->ppTypeComboBox->setCurrentIndex(data.value(OPL::Db::TAILS_ENGINETYPE).toInt() + 1);
+    ui->weightComboBox->setCurrentIndex(data.value(OPL::Db::TAILS_WEIGHTCLASS).toInt() + 1);
 }
 
 /*!
@@ -188,16 +188,16 @@ void NewTailDialog::submitForm()
     }
 
     if (ui->operationComboBox->currentIndex() != 0) { // bool Multipilot
-        new_data.insert(Opl::Db::TAILS_MULTIPILOT, ui->operationComboBox->currentIndex() - 1);
+        new_data.insert(OPL::Db::TAILS_MULTIPILOT, ui->operationComboBox->currentIndex() - 1);
     }
     if (ui->ppNumberComboBox->currentIndex() != 0) { // bool MultiEngine
-        new_data.insert(Opl::Db::TAILS_MULTIENGINE, ui->ppNumberComboBox->currentIndex() - 1);
+        new_data.insert(OPL::Db::TAILS_MULTIENGINE, ui->ppNumberComboBox->currentIndex() - 1);
     }
     if (ui->ppTypeComboBox->currentIndex() != 0) { // int 0=unpowered,....4=jet
-        new_data.insert(Opl::Db::TAILS_ENGINETYPE, ui->ppTypeComboBox->currentIndex() - 1);
+        new_data.insert(OPL::Db::TAILS_ENGINETYPE, ui->ppTypeComboBox->currentIndex() - 1);
     }
     if (ui->weightComboBox->currentIndex() != 0) { // int 0=light...3=super
-        new_data.insert(Opl::Db::TAILS_WEIGHTCLASS, ui->weightComboBox->currentIndex() - 1);
+        new_data.insert(OPL::Db::TAILS_WEIGHTCLASS, ui->weightComboBox->currentIndex() - 1);
     }
 
     //create db object

+ 2 - 2
src/gui/widgets/backupwidget.cpp

@@ -80,7 +80,7 @@ void BackupWidget::refresh()
 const QString BackupWidget::absoluteBackupPath()
 {
     const QString backup_name = QLatin1String("logbook_backup_")
-            + ADateTime::toString(QDateTime::currentDateTime(), Opl::Datetime::Backup)
+            + ADateTime::toString(QDateTime::currentDateTime(), OPL::DateTimeFormat::Backup)
             + QLatin1String(".db");
     return AStandardPaths::asChildOfDir(AStandardPaths::Backup, backup_name);
 }
@@ -88,7 +88,7 @@ const QString BackupWidget::absoluteBackupPath()
 const QString BackupWidget::backupName()
 {
     return  QLatin1String("logbook_backup_")
-            + ADateTime::toString(QDateTime::currentDateTime(), Opl::Datetime::Backup)
+            + ADateTime::toString(QDateTime::currentDateTime(), OPL::DateTimeFormat::Backup)
             + QLatin1String(".db");
 }
 

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

@@ -39,7 +39,7 @@ HomeWidget::HomeWidget(QWidget *parent) :
     today = QDate::currentDate();
     ftlWarningThreshold = ASettings::read(ASettings::UserData::FtlWarningThreshold).toDouble();
     currWarningThreshold = ASettings::read(ASettings::UserData::CurrWarningThreshold).toInt();
-    auto logo = QPixmap(Opl::Assets::LOGO);
+    auto logo = QPixmap(OPL::Assets::LOGO);
     ui->logoLabel->setPixmap(logo);
     ui->welcomeLabel->setText(tr("Welcome to openPilotLog, %1!").arg(userName()));
 
@@ -100,7 +100,7 @@ void HomeWidget::fillCurrency(ACurrencyEntry::CurrencyName currency_name, QLabel
     auto currency_entry = aDB->getCurrencyEntry(currency_name);
     if (currency_entry.isValid()) {
         auto currency_date = QDate::fromString(currency_entry.tableData.value(
-                                                   Opl::Db::CURRENCIES_EXPIRYDATE).toString(),
+                                                   OPL::Db::CURRENCIES_EXPIRYDATE).toString(),
                                                Qt::ISODate);
         display_label->setText(currency_date.toString(Qt::TextDate));
         setLabelColour(display_label, Colour::None);
@@ -160,6 +160,8 @@ void HomeWidget::fillSelectedCurrencies()
 void HomeWidget::fillCurrencyTakeOffLanding()
 {
     const auto takeoff_landings = AStat::countTakeOffLanding();
+    if(takeoff_landings.isEmpty())
+        return;
 
     ui->TakeOffDisplayLabel->setText(takeoff_landings[0].toString());
     if (takeoff_landings[0].toUInt() < 3)

+ 65 - 52
src/gui/widgets/logbookwidget.cpp

@@ -22,6 +22,7 @@
 #include "src/database/adatabase.h"
 #include "src/classes/asettings.h"
 #include "src/gui/dialogues/newflightdialog.h"
+#include "src/gui/dialogues/newsimdialog.h"
 #include "src/functions/alog.h"
 #include "src/functions/alog.h"
 
@@ -41,6 +42,8 @@ LogbookWidget::LogbookWidget(ACompletionData& completion_data, QWidget *parent)
 {
     ui->setupUi(this);
 
+    OPL::GLOBALS->fillViewNamesComboBox(ui->viewsComboBox);
+
     //customContextMenu for tablewidget
     menu  = new QMenu(this);
     menu->addAction(ui->actionEdit_Flight);
@@ -71,33 +74,19 @@ LogbookWidget::~LogbookWidget()
  */
 void LogbookWidget::setupModelAndView(int view_id)
 {
-    switch (view_id) {
-    case 0:
-        LOG << "Loading Default View...";
-        displayModel->setTable(QStringLiteral("viewDefault"));
-        displayModel->select();
-        break;
-    case 1:
-        LOG << "Loading EASA View...";
-        displayModel->setTable(QStringLiteral("viewEASA"));
-        displayModel->select();
-        break;
-    default:
-        LOG << "Loading Default View...";
-        displayModel->setTable(QStringLiteral("viewDefault"));
-        displayModel->select();
-    }
+    displayModel->setTable(OPL::GLOBALS->getViewIdentifier(OPL::DbViewName(view_id)));
+    displayModel->select();
 
     view->setModel(displayModel);
     view->setSelectionBehavior(QAbstractItemView::SelectRows);
     view->setSelectionMode(QAbstractItemView::ExtendedSelection);
     view->setEditTriggers(QAbstractItemView::NoEditTriggers);
     view->setContextMenuPolicy(Qt::CustomContextMenu);
+    view->resizeColumnsToContents();
     view->horizontalHeader()->setStretchLastSection(QHeaderView::Stretch);
     view->verticalHeader()->hide();
     view->setAlternatingRowColors(true);
     view->hideColumn(0);
-    view->resizeColumnsToContents();
     view->show();
 }
 
@@ -114,9 +103,6 @@ void LogbookWidget::changeEvent(QEvent *event)
         if(event->type() == QEvent::LanguageChange)
             ui->retranslateUi(this);
 }
-/*
- * Slots
- */
 
 /*!
  * \brief LogbookWidget::flightsTableView_selectionChanged saves the selected row(s)
@@ -124,13 +110,17 @@ void LogbookWidget::changeEvent(QEvent *event)
  */
 void LogbookWidget::flightsTableView_selectionChanged()
 {
-    selectedFlights.clear();
+    selectedEntries.clear();
     for (const auto& row : selectionModel->selectedRows()) {
-        selectedFlights.append(row.data().toInt());
-        DEB << "Selected Flight(s) with ID: " << selectedFlights;
+        selectedEntries.append(row.data().toInt());
+        DEB << "Selected Flight(s) with ID: " << selectedEntries;
+    }
+    if (selectedEntries.length() == 1) {
+        if (isFlight(selectedEntries.first()))
+            on_actionEdit_Flight_triggered();
+        else
+            on_actionEdit_Sim_triggered();
     }
-    if (selectedFlights.length() == 1)
-        on_actionEdit_Flight_triggered();
 }
 
 /*!
@@ -139,14 +129,14 @@ void LogbookWidget::flightsTableView_selectionChanged()
  */
 void LogbookWidget::on_actionDelete_Flight_triggered()
 {
-    DEB << "Flights selected: " << selectedFlights.length();
-    if (selectedFlights.length() == 0) {
+    DEB << "Flights selected: " << selectedEntries.length();
+    if (selectedEntries.length() == 0) {
         WARN(tr("<br>No flight selected.<br>"));
         return;
-    } else if (selectedFlights.length() > 0 && selectedFlights.length() <= 10) {
+    } else if (selectedEntries.length() > 0 && selectedEntries.length() <= 10) {
         QVector<AFlightEntry> flights_list;
 
-        for (const auto &flight_id : qAsConst(selectedFlights)) {
+        for (const auto &flight_id : qAsConst(selectedEntries)) {
             flights_list.append(aDB->getFlightEntry(flight_id));
         }
 
@@ -176,10 +166,10 @@ void LogbookWidget::on_actionDelete_Flight_triggered()
                 }
             }
             INFO(tr("%1 flights have been deleted successfully."
-                                   ).arg(QString::number(selectedFlights.length())));
+                                   ).arg(QString::number(selectedEntries.length())));
             displayModel->select();
         }
-    } else if (selectedFlights.length() > 10) {
+    } else if (selectedEntries.length() > 10) {
         QMessageBox confirm;
         confirm.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
         confirm.setDefaultButton(QMessageBox::No);
@@ -188,10 +178,10 @@ void LogbookWidget::on_actionDelete_Flight_triggered()
         confirm.setText(tr("You have selected %1 flights.<br><br>"
                            "Deleting flights is irreversible.<br><br>"
                            "Are you sure you want to proceed?"
-                           ).arg(QString::number(selectedFlights.length())));
+                           ).arg(QString::number(selectedEntries.length())));
         if(confirm.exec() == QMessageBox::Yes) {
             QList<DataPosition> selected_flights;
-            for (const auto& flight_id : qAsConst(selectedFlights)) {
+            for (const auto& flight_id : qAsConst(selectedEntries)) {
                 selected_flights.append({QStringLiteral("flights"), flight_id});
             }
             if (!aDB->removeMany(selected_flights)) {
@@ -199,7 +189,7 @@ void LogbookWidget::on_actionDelete_Flight_triggered()
                 return;
             }
             INFO(tr("%1 flights have been deleted successfully."
-                                   ).arg(QString::number(selectedFlights.length())));
+                                   ).arg(QString::number(selectedEntries.length())));
             displayModel->select();
         }
         displayModel->select();
@@ -212,24 +202,6 @@ void LogbookWidget::on_tableView_customContextMenuRequested(const QPoint &pos)
     menu->popup(ui->tableView->viewport()->mapToGlobal(pos));
 }
 
-void LogbookWidget::on_actionEdit_Flight_triggered()
-{
-    completionData.update();
-    if(selectedFlights.length() == 1){
-        NewFlightDialog nff(completionData,selectedFlights.first(), this);
-        ui->stackedWidget->addWidget(&nff);
-        ui->stackedWidget->setCurrentWidget(&nff);
-        nff.setWindowFlag(Qt::Widget);
-        nff.exec();
-        displayModel->select();
-    } else if (selectedFlights.isEmpty()) {
-        WARN(tr("<br>No flight selected.<br>"));
-    } else {
-        WARN(tr("<br>More than one flight selected."
-                               "<br><br>Editing multiple entries is not yet supported."));
-    }
-}
-
 void LogbookWidget::on_tableView_doubleClicked()
 {
     on_actionEdit_Flight_triggered();
@@ -304,3 +276,44 @@ void LogbookWidget::repopulateModel()
     setupModelAndView(ASettings::read(ASettings::Main::LogbookView).toInt());
     connectSignalsAndSlots();
 }
+
+void LogbookWidget::on_viewsComboBox_currentIndexChanged(int index)
+{
+    setupModelAndView(index);
+}
+
+void LogbookWidget::on_actionEdit_Flight_triggered()
+{
+    completionData.update();
+    if(selectedEntries.length() == 1){
+        NewFlightDialog nff(completionData,selectedEntries.first(), this);
+        ui->stackedWidget->addWidget(&nff);
+        ui->stackedWidget->setCurrentWidget(&nff);
+        nff.setWindowFlag(Qt::Widget);
+        nff.exec();
+        displayModel->select();
+    } else if (selectedEntries.isEmpty()) {
+        WARN(tr("<br>No flight selected.<br>"));
+    } else {
+        WARN(tr("<br>More than one flight selected."
+                               "<br><br>Editing multiple entries is not yet supported."));
+    }
+}
+
+void LogbookWidget::on_actionEdit_Sim_triggered()
+{
+    if (selectedEntries.length() == 1) {
+        NewSimDialog nsd((selectedEntries.first() * -1), this);
+        ui->stackedWidget->addWidget(&nsd);
+        ui->stackedWidget->setCurrentWidget(&nsd);
+        nsd.setWindowFlag(Qt::Widget);
+        nsd.exec();
+        displayModel->select();
+    } else if (selectedEntries.isEmpty()) {
+        WARN(tr("<br>No flight selected.<br>"));
+    } else {
+        WARN(tr("<br>More than one flight selected."
+                               "<br><br>Editing multiple entries is not yet supported."));
+    }
+}
+

+ 17 - 6
src/gui/widgets/logbookwidget.h

@@ -27,6 +27,7 @@
 #include <QTableView>
 #include "src/gui/widgets/settingswidget.h"
 #include "src/classes/acompletiondata.h"
+#include "src/opl.h"
 
 namespace Ui {
 class LogbookWidget;
@@ -52,18 +53,19 @@ public:
     ~LogbookWidget();
 
 private slots:
-    //void on_newFlightButton_clicked();
-    //void on_editFlightButton_clicked();
-    //void on_deleteFlightPushButton_clicked();
-    //void on_showAllButton_clicked();
     void flightsTableView_selectionChanged();
     void on_tableView_customContextMenuRequested(const QPoint &pos);
     void on_actionDelete_Flight_triggered();
-    void on_actionEdit_Flight_triggered();
+
     void on_tableView_doubleClicked();
     void on_flightSearchLlineEdit_textChanged(const QString &arg1);
     void on_flightSearchComboBox_currentIndexChanged(int);
 
+    void on_viewsComboBox_currentIndexChanged(int index);
+
+    void on_actionEdit_Flight_triggered();
+    void on_actionEdit_Sim_triggered();
+
 public slots:
     void refresh();
     void onLogbookWidget_viewSelectionChanged(SettingsWidget::SettingSignal signal);
@@ -80,13 +82,22 @@ private:
 
     QMenu* menu;
 
-    QVector<qint32> selectedFlights;
+    QVector<qint32> selectedEntries;
 
     void setupModelAndView(int view_id);
     void connectSignalsAndSlots();
 
     ACompletionData completionData;
 
+    /*!
+     * \brief isFlight Determines whether an entry shown in a view is a Flight or a Simulator.
+     * \param model_row_id the row id in the QSqlTableModel used for displaying
+     * \details In the composite views (SQL UNION) with Simulators included, the row_id of the
+     * simulator entries is inverted to a negative value. A positive row id is thus a row id from
+     * the flights table, whereas a negative rowid is a row id from the simulators table.
+     */
+    inline bool isFlight(int model_row_id) { return model_row_id > 0; }
+
 protected:
     /*!
      * \brief Handles change events, like updating the UI to new localisation

+ 14 - 5
src/gui/widgets/logbookwidget.ui

@@ -14,12 +14,10 @@
    <string>Form</string>
   </property>
   <layout class="QGridLayout" name="gridLayout">
-   <item row="0" column="0">
+   <item row="1" column="0">
     <widget class="QTableView" name="tableView">
      <property name="font">
-      <font>
-       <family>Cantarell</family>
-      </font>
+      <font/>
      </property>
      <property name="styleSheet">
       <string notr="true"/>
@@ -32,7 +30,7 @@
      </property>
     </widget>
    </item>
-   <item row="1" column="0">
+   <item row="2" column="0">
     <widget class="QStackedWidget" name="stackedWidget">
      <widget class="QWidget" name="defaultPage">
       <layout class="QGridLayout" name="gridLayout_2">
@@ -121,6 +119,9 @@
      </widget>
     </widget>
    </item>
+   <item row="0" column="0">
+    <widget class="QComboBox" name="viewsComboBox"/>
+   </item>
   </layout>
   <widget class="QLabel" name="spacerLabel">
    <property name="geometry">
@@ -154,6 +155,14 @@
     <string>Delete Flight</string>
    </property>
   </action>
+  <action name="actionEdit_Sim">
+   <property name="text">
+    <string>Edit_Sim</string>
+   </property>
+   <property name="toolTip">
+    <string>Edit an existing Simulator Entry</string>
+   </property>
+  </action>
  </widget>
  <resources/>
  <connections/>

+ 34 - 33
src/gui/widgets/settingswidget.cpp

@@ -53,18 +53,12 @@ void SettingsWidget::changeEvent(QEvent *event)
 
 void SettingsWidget::setupComboBoxes(){
     {
-        // Style combo box
-        const QSignalBlocker style_blocker(ui->styleComboBox);
+        // Set up Combo Boxes
         AStyle::loadStylesComboBox(ui->styleComboBox);
-        // Approach Combo Box and Function Combo Box
-        const QSignalBlocker approach_blocker(ui->approachComboBox);
-        Opl::loadApproachTypes(ui->approachComboBox);
-        const QSignalBlocker function_blocker(ui->functionComboBox);
-        Opl::loadPilotFunctios(ui->functionComboBox);
-
-        // Language Combo Box
-        for (const auto &lang : Opl::L10N_NAMES)
-            ui->languageComboBox->addItem(lang);
+        OPL::GLOBALS->loadApproachTypes(ui->approachComboBox);
+        OPL::GLOBALS->loadPilotFunctios(ui->functionComboBox);
+        OPL::GLOBALS->fillViewNamesComboBox(ui->logbookViewComboBox);
+        OPL::GLOBALS->fillLanguageComboBox(ui->languageComboBox);
     }
 }
 
@@ -74,7 +68,7 @@ void SettingsWidget::setupDateEdits()
     // Read Display Format Setting
     int date_format_index = ASettings::read(ASettings::Main::DateFormat).toInt();
     const QString date_format_string = ADate::getFormatString(
-                static_cast<Opl::Date::ADateFormat>(date_format_index));
+                static_cast<OPL::DateFormat>(date_format_index));
     const auto date_edits = this->findChildren<QDateEdit*>();
     for (const auto &date_edit : date_edits) {
         date_edit->setDisplayFormat(date_format_string);
@@ -93,7 +87,7 @@ void SettingsWidget::setupDateEdits()
         const auto entry = aDB->getCurrencyEntry(pair.first);
         if (entry.isValid()) { // set date
             const auto date = QDate::fromString(
-                        entry.tableData.value(Opl::Db::CURRENCIES_EXPIRYDATE).toString(),
+                        entry.tableData.value(OPL::Db::CURRENCIES_EXPIRYDATE).toString(),
                         Qt::ISODate);
             pair.second->setDate(date);
         } else { // set current date
@@ -111,12 +105,12 @@ void SettingsWidget::readSettings()
 
     // Personal Data Tab
     auto user_data = aDB->getPilotEntry(1).getData();
-    ui->lastnameLineEdit->setText(user_data.value(Opl::Db::PILOTS_LASTNAME).toString());
-    ui->firstnameLineEdit->setText(user_data.value(Opl::Db::PILOTS_FIRSTNAME).toString());
-    ui->companyLineEdit->setText(user_data.value(Opl::Db::PILOTS_COMPANY).toString());
-    ui->employeeidLineEdit->setText(user_data.value(Opl::Db::PILOTS_EMPLOYEEID).toString());
-    ui->phoneLineEdit->setText(user_data.value(Opl::Db::PILOTS_PHONE).toString());
-    ui->emailLineEdit->setText(user_data.value(Opl::Db::PILOTS_EMAIL).toString());
+    ui->lastnameLineEdit->setText(user_data.value(OPL::Db::PILOTS_LASTNAME).toString());
+    ui->firstnameLineEdit->setText(user_data.value(OPL::Db::PILOTS_FIRSTNAME).toString());
+    ui->companyLineEdit->setText(user_data.value(OPL::Db::PILOTS_COMPANY).toString());
+    ui->employeeidLineEdit->setText(user_data.value(OPL::Db::PILOTS_EMPLOYEEID).toString());
+    ui->phoneLineEdit->setText(user_data.value(OPL::Db::PILOTS_PHONE).toString());
+    ui->emailLineEdit->setText(user_data.value(OPL::Db::PILOTS_EMAIL).toString());
 
     // FLight Logging Tab
     ui->functionComboBox->setCurrentIndex(ASettings::read(ASettings::FlightLogging::Function).toInt());
@@ -188,10 +182,10 @@ void SettingsWidget::updatePersonalDetails()
     RowData_T user_data;
     switch (ui->aliasComboBox->currentIndex()) {
     case 0:
-        user_data.insert(Opl::Db::PILOTS_ALIAS, QStringLiteral("self"));
+        user_data.insert(OPL::Db::PILOTS_ALIAS, QStringLiteral("self"));
         break;
     case 1:
-        user_data.insert(Opl::Db::PILOTS_ALIAS, QStringLiteral("SELF"));
+        user_data.insert(OPL::Db::PILOTS_ALIAS, QStringLiteral("SELF"));
         break;
     case 2:{
         QString name;
@@ -199,18 +193,18 @@ void SettingsWidget::updatePersonalDetails()
         name.append(QLatin1String(", "));
         name.append(ui->firstnameLineEdit->text().left(1));
         name.append(QLatin1Char('.'));
-        user_data.insert(Opl::Db::PILOTS_ALIAS, name);
+        user_data.insert(OPL::Db::PILOTS_ALIAS, name);
     }
         break;
     default:
         break;
     }
-    user_data.insert(Opl::Db::PILOTS_LASTNAME, ui->lastnameLineEdit->text());
-    user_data.insert(Opl::Db::PILOTS_FIRSTNAME, ui->firstnameLineEdit->text());
-    user_data.insert(Opl::Db::PILOTS_COMPANY, ui->companyLineEdit->text());
-    user_data.insert(Opl::Db::PILOTS_EMPLOYEEID, ui->employeeidLineEdit->text());
-    user_data.insert(Opl::Db::PILOTS_PHONE, ui->phoneLineEdit->text());
-    user_data.insert(Opl::Db::PILOTS_EMAIL, ui->emailLineEdit->text());
+    user_data.insert(OPL::Db::PILOTS_LASTNAME, ui->lastnameLineEdit->text());
+    user_data.insert(OPL::Db::PILOTS_FIRSTNAME, ui->firstnameLineEdit->text());
+    user_data.insert(OPL::Db::PILOTS_COMPANY, ui->companyLineEdit->text());
+    user_data.insert(OPL::Db::PILOTS_EMPLOYEEID, ui->employeeidLineEdit->text());
+    user_data.insert(OPL::Db::PILOTS_PHONE, ui->phoneLineEdit->text());
+    user_data.insert(OPL::Db::PILOTS_EMAIL, ui->emailLineEdit->text());
 
     auto user = APilotEntry(1);
     user.setData(user_data);
@@ -329,12 +323,12 @@ void SettingsWidget::on_acftSortComboBox_currentIndexChanged(int index)
 void SettingsWidget::on_aboutPushButton_clicked()
 {
     QMessageBox message_box(this);
-    QPixmap icon = QPixmap(Opl::Assets::ICON_MAIN);
+    QPixmap icon = QPixmap(OPL::Assets::ICON_MAIN);
     message_box.setIconPixmap(icon.scaledToWidth(64, Qt::TransformationMode::SmoothTransformation));
     QString SQLITE_VERSION = aDB->sqliteVersion();
     QString text = QMessageBox::tr(
 
-                       "<h3><center>About openPilotLog</center></h3>"
+                       "<h3><center>About</center></h3>"
                        "<br>"
                        "&#169; 2020 - 2022 Felix Turowsky"
                        "<br>"
@@ -355,12 +349,16 @@ void SettingsWidget::on_aboutPushButton_clicked()
                        "along with this program.  If not, "
                        "please click <a href=\"https://%2\">here</a>.</p>"
 
+                       "<br>"
+                       "You are using openPilotLog version %3."
                        "<br>"
 
-                       "<p>This program uses <a href=\"http://%3/\">Qt</a> version %4 and "
-                       "<a href=\"https://%5/\">SQLite</a> version %6</p>"
-                   ).arg(QStringLiteral("github.com/fiffty-50/openpilotlog"),
+                       "<p>This program uses <a href=\"http://%4/\">Qt</a> version %5 and "
+                       "<a href=\"https://%6/\">SQLite</a> version %7</p>"
+                   ).arg(
+                         QStringLiteral("github.com/fiffty-50/openpilotlog"),
                          QStringLiteral("gnu.org/licenses/"),
+                         OPL_VERSION_STRING,
                          QStringLiteral("qt.io"),
                          QT_VERSION_STR,
                          QStringLiteral("sqlite.org/about.html"),
@@ -374,12 +372,14 @@ void SettingsWidget::on_styleComboBox_currentTextChanged(const QString& new_styl
     if (new_style_setting == QLatin1String("Dark-Palette")) {
         AStyle::setStyle(AStyle::darkPalette());
         ASettings::write(ASettings::Main::Style, new_style_setting);
+        emit settingChanged(MainWindow);
         return;
     }
     for (const auto &style_name : AStyle::styles) {
         if (new_style_setting == style_name) {
             AStyle::setStyle(style_name);
             ASettings::write(ASettings::Main::Style, new_style_setting);
+            emit settingChanged(MainWindow);
             return;
         }
     }
@@ -388,6 +388,7 @@ void SettingsWidget::on_styleComboBox_currentTextChanged(const QString& new_styl
         if (new_style_setting == style_sheet.styleSheetName) {
             AStyle::setStyle(style_sheet);
             ASettings::write(ASettings::Main::Style, new_style_setting);
+            emit settingChanged(MainWindow);
             return;
         }
     }

+ 2 - 2
src/gui/widgets/settingswidget.h

@@ -48,7 +48,7 @@ public:
     /*!
      * \brief enumerates Widgets that need to receive a signal when a setting is updated.
      */
-    enum SettingSignal {LogbookWidget, HomeWidget, AircraftWidget, PilotsWidget};
+    enum SettingSignal {LogbookWidget, HomeWidget, AircraftWidget, PilotsWidget, MainWindow};
 
 private slots:
 
@@ -111,7 +111,7 @@ signals:
      * \brief settingChanged is emitted when a setting change occurs that needs to trigger
      * an update (repaint) to another widget.
      */
-    void settingChanged(SettingSignal widget);
+    void settingChanged(SettingsWidget::SettingSignal widget);
 
 protected:
     /*!

+ 1 - 11
src/gui/widgets/settingswidget.ui

@@ -17,7 +17,7 @@
    <item row="0" column="0">
     <widget class="QTabWidget" name="tabWidget">
      <property name="currentIndex">
-      <number>4</number>
+      <number>3</number>
      </property>
      <widget class="QWidget" name="personalTab">
       <attribute name="title">
@@ -926,16 +926,6 @@
          <property name="toolTip">
           <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Determines how your logbook is displayed in the logbook tab. This has no influence on what details are logged, just on what is displayed by default.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
          </property>
-         <item>
-          <property name="text">
-           <string>Default</string>
-          </property>
-         </item>
-         <item>
-          <property name="text">
-           <string>EASA Part-FCL</string>
-          </property>
-         </item>
         </widget>
        </item>
        <item row="5" column="0">

+ 40 - 0
src/opl.cpp

@@ -0,0 +1,40 @@
+#include "opl.h"
+
+namespace OPL {
+
+void OplGlobals::fillLanguageComboBox(QComboBox *combo_box) const
+{
+    QSignalBlocker blocker(combo_box);
+    for (const auto &language : L10N_DisplayNames)
+        combo_box->addItem(language);
+}
+
+void OplGlobals::fillViewNamesComboBox(QComboBox *combo_box) const
+{
+    const QSignalBlocker blocker(combo_box);
+    for (int i = DbViewName::Default; i < DATABASE_VIEW_DISPLAY_NAMES.size(); i++)
+        combo_box->addItem(DATABASE_VIEW_DISPLAY_NAMES.value(DbViewName(i)));
+}
+
+void OplGlobals::loadPilotFunctios(QComboBox *combo_box) const
+{
+    const QSignalBlocker blocker(combo_box);
+    for (int i = PilotFunction::PIC; i < PILOT_FUNCTIONS.size(); i++)
+        combo_box->addItem(PILOT_FUNCTIONS.value(PilotFunction(i)));
+}
+
+void OplGlobals::loadSimulatorTypes(QComboBox *combo_box) const
+{
+    const QSignalBlocker blocker(combo_box);
+    for (int i = SimulatorType::FNPTI; i < SIMULATOR_TYPES.size(); i++)
+        combo_box->addItem(SIMULATOR_TYPES.value(SimulatorType(i)));
+}
+
+void OplGlobals::loadApproachTypes(QComboBox *combo_box) const
+{
+    const QSignalBlocker blocker(combo_box);
+    for (const auto &approach : APPROACH_TYPES)
+        combo_box->addItem(approach);
+}
+
+} // namespace Opl

+ 127 - 82
src/opl.h

@@ -37,7 +37,11 @@
  *  The db namespace contains constants for programatically accessing the database in a fast
  *  and uniform manner.
  */
-namespace Opl {
+namespace OPL {
+
+#define OPL_VERSION 0
+#define OPL_SUBVERSION 1
+#define OPL_VERSION_STRING QString(QString::number(OPL_VERSION) + "." + QString::number(OPL_SUBVERSION))
 
 #if defined(__GNUC__) || defined(__clang__)
     #define FUNC_IDENT __PRETTY_FUNCTION__
@@ -51,9 +55,9 @@ namespace Opl {
 #define LOG qInfo()                             // Use for logging milestones (silently, will be written to log file and console out only)
 #define TODO qCritical() << "TO DO:\t"
 
-#define INFO(msg) Opl::ANotificationHandler::info(msg, this)  // Use for messages of interest to the user (will be displayed in GUI)
-#define WARN(msg) Opl::ANotificationHandler::warn(msg, this)  // Use for warnings (will be displayed in GUI)
-#define CRIT(msg) Opl::ANotificationHandler::crit(msg, this)  // Use for critical warnings (will be displayed in GUI)
+#define INFO(msg) OPL::ANotificationHandler::info(msg, this)  // Use for messages of interest to the user (will be displayed in GUI)
+#define WARN(msg) OPL::ANotificationHandler::warn(msg, this)  // Use for warnings (will be displayed in GUI)
+#define CRIT(msg) OPL::ANotificationHandler::crit(msg, this)  // Use for critical warnings (will be displayed in GUI)
 
 /*!
  * \brief The ANotificationHandler class handles displaying of user-directed messages. It displays
@@ -80,18 +84,15 @@ public:
     };
 }; // class ANotificationHandler
 
-enum class Translations {English, German, Spanish};
+/*!
+ * \brief ADateFormats enumerates the accepted date formats for QDateEdits
+ * \todo At the moment, only ISODate is accepet as a valid date format.
+ */
+enum class DateFormat {ISODate, DE, EN };
+
+enum class FlightTimeFormat {Default, Decimal};
 
-const static QMap<Opl::Translations, QString> L10N_FILES {
-    {Opl::Translations::English, QStringLiteral("l10n/openpilotlog_en")},
-    {Opl::Translations::German,  QStringLiteral("l10n/openpilotlog_de")},
-    {Opl::Translations::Spanish, QStringLiteral("l10n/openpilotlog_es")},
-};
-static const QMap<Translations, QString> L10N_NAMES {
-    {Opl::Translations::English, QStringLiteral("English")},
-    {Opl::Translations::German,  QStringLiteral("Deutsch")},
-    {Opl::Translations::Spanish, QStringLiteral("Español")},
-};
+enum class DateTimeFormat {Default, Backup};
 
 /*!
  * \brief PilotFunction
@@ -99,79 +100,113 @@ static const QMap<Translations, QString> L10N_NAMES {
  */
 enum PilotFunction {PIC = 0, PICUS = 1, SIC = 2, DUAL = 3, FI = 4};
 
-static const QMap<PilotFunction, QLatin1String> PILOT_FUNCTIONS = {
-    {PilotFunction::PIC, QLatin1String("PIC")},
-    {PilotFunction::PICUS, QLatin1String("PICUS")},
-    {PilotFunction::SIC, QLatin1String("SIC")},
-    {PilotFunction::DUAL, QLatin1String("DUAL")},
-    {PilotFunction::FI, QLatin1String("FI")},
-};
-
-inline void loadPilotFunctios(QComboBox *combo_box)
-{
-    for (int i = 0; i < Opl::PILOT_FUNCTIONS.size(); i++)
-        combo_box->addItem(Opl::PILOT_FUNCTIONS.value(Opl::PilotFunction(i)));
-};
-
-static const QList<QLatin1String> APPROACH_TYPES = {
-        QLatin1String("VISUAL"),
-        QLatin1String("ILS CAT I"),
-        QLatin1String("ILS CAT II"),
-        QLatin1String("ILS CAT III"),
-        QLatin1String("GLS"),
-        QLatin1String("MLS"),
-        QLatin1String("LOC"),
-        QLatin1String("LOC/DME"),
-        QLatin1String("RNAV"),
-        QLatin1String("RNAV (LNAV)"),
-        QLatin1String("RNAV (LNAV/VNAV)"),
-        QLatin1String("RNAV (LPV)"),
-        QLatin1String("RNAV (RNP)"),
-        QLatin1String("RNAV (RNP-AR)"),
-        QLatin1String("VOR"),
-        QLatin1String("VOR/DME"),
-        QLatin1String("NDB"),
-        QLatin1String("NDB/DME"),
-        QLatin1String("TACAN"),
-        QLatin1String("SRA"),
-        QLatin1String("PAR"),
-        QLatin1String("OTHER")
-};
-
-inline void loadApproachTypes(QComboBox *combo_box)
-{
-    for (const auto & approach : Opl::APPROACH_TYPES)
-        combo_box->addItem(approach);
-};
-
-namespace Date {
-
 /*!
- * \brief ADateFormats enumerates the accepted date formats for QDateEdits
- * \todo At the moment, only ISODate is accepet as a valid date format.
+ * \brief Enumerates the available translations
  */
-enum ADateFormat {ISODate, DE, EN };
+enum Translation {English, German, Spanish};
 
-} // namespace opl::date
+/*!
+ * \brief Enumerates the available SQL views in the database
+ */
+enum DbViewName {Default, DefaultWithSim, Easa, EasaWithSim, SimulatorOnly};
 
-namespace Time {
+/*!
+ * \brief Enumerates the Simulator Types: Flight and Navigation Procedures Trainer 1/2, Flight Simulation Training Device
+ */
+enum SimulatorType {FNPTI = 0, FNPTII = 1, FSTD = 2};
 
-enum FlightTimeFormat {Default, Decimal};
+/*!
+ * \brief The OplGlobals class encapsulates non-POD globals to avoid making them static. It is available
+ * as a global static object via the OPL::GLOBAL makro and may be used as if it were a pointer, guaranteed to be initialized exactly once.
+ * For more information, see (Q_GLOBAL_STATIC)[https://doc.qt.io/qt-5/qglobalstatic.html#details]
+ */
+class OplGlobals : public QObject {
+public:
+    OplGlobals() = default;
 
-} // namespace opl::time
+    void fillLanguageComboBox(QComboBox *combo_box) const;
+    void fillViewNamesComboBox(QComboBox *combo_box) const;
+    void loadPilotFunctios(QComboBox *combo_box) const;
+    void loadSimulatorTypes(QComboBox *combo_box) const;
+    void loadApproachTypes(QComboBox *combo_box) const;
 
-namespace Datetime {
+    inline const QStringList &getApproachTypes() const {return APPROACH_TYPES;}
+    inline const QString getLanguageFilePath(Translation language) const {return L10N_FilePaths.value(language);}
+    inline const QString getViewIdentifier(DbViewName view_name) const {return DATABASE_VIEWS.value(view_name);}
 
-enum DateTimeFormat {Default, Backup};
+private:
+    Q_OBJECT
 
-} // namespace opl::datetime
+    const QMap<Translation, QString> L10N_FilePaths {
+        {Translation::English, QStringLiteral("l10n/openpilotlog_en")},
+        {Translation::German,  QStringLiteral("l10n/openpilotlog_de")},
+        {Translation::Spanish, QStringLiteral("l10n/openpilotlog_es")},
+    };
+    const QMap<Translation, QString> L10N_DisplayNames {
+        {Translation::English, tr("English")},
+        {Translation::German,  tr("Deutsch")},
+        {Translation::Spanish, tr("Español")},
+    };
+    const QMap<DbViewName, QString> DATABASE_VIEWS = {
+        {Default,        QStringLiteral("viewDefault")},
+        {DefaultWithSim, QStringLiteral("viewDefaultSim")},
+        {Easa,           QStringLiteral("viewEasa")},
+        {EasaWithSim,    QStringLiteral("viewEasaSim")},
+        {SimulatorOnly,  QStringLiteral("viewSimulators")},
+    };
+    const QMap<DbViewName, QString> DATABASE_VIEW_DISPLAY_NAMES = {
+        {Default,        tr("Default")},
+        {DefaultWithSim, tr("Default with Simulator")},
+        {Easa,           tr("EASA-FCL")},
+        {EasaWithSim,    tr("EASA-FCL with Simulator")},
+        {SimulatorOnly,  tr("Simulator Sessions Only")},
+    };
+    const QMap<PilotFunction, QLatin1String> PILOT_FUNCTIONS = {
+        {PilotFunction::PIC,   QLatin1String("PIC")},
+        {PilotFunction::PICUS, QLatin1String("PICUS")},
+        {PilotFunction::SIC,   QLatin1String("SIC")},
+        {PilotFunction::DUAL,  QLatin1String("DUAL")},
+        {PilotFunction::FI,    QLatin1String("FI")},
+    };
+    const QMap<SimulatorType, QString> SIMULATOR_TYPES = {
+        {FNPTI,  QStringLiteral("FNPT I")},
+        {FNPTII, QStringLiteral("FNPT II")},
+        {FSTD,   QStringLiteral("FSTD")},
+    };
+    const QStringList APPROACH_TYPES = {
+            QStringLiteral("VISUAL"),
+            QStringLiteral("ILS CAT I"),
+            QStringLiteral("ILS CAT II"),
+            QStringLiteral("ILS CAT III"),
+            QStringLiteral("GLS"),
+            QStringLiteral("MLS"),
+            QStringLiteral("LOC"),
+            QStringLiteral("LOC/DME"),
+            QStringLiteral("RNAV"),
+            QStringLiteral("RNAV (LNAV)"),
+            QStringLiteral("RNAV (LNAV/VNAV)"),
+            QStringLiteral("RNAV (LPV)"),
+            QStringLiteral("RNAV (RNP)"),
+            QStringLiteral("RNAV (RNP-AR)"),
+            QStringLiteral("VOR"),
+            QStringLiteral("VOR/DME"),
+            QStringLiteral("NDB"),
+            QStringLiteral("NDB/DME"),
+            QStringLiteral("TACAN"),
+            QStringLiteral("SRA"),
+            QStringLiteral("PAR"),
+            QStringLiteral("OTHER")
+    };
+};
+//Make available as a global static
+Q_GLOBAL_STATIC(OplGlobals, GLOBALS)
 
 /*!
- *  The opl::db namespace provides string literals to programatically access the database
+ *  The OPL::db namespace provides string literals to programatically access the database
  *
  *  Example usage, do:
- *  newData.insert(opl::db::FLIGHTS_DEP, ui->deptLocLineEdit->text());
- *  newData.value(opl::db::AIRCRAFT_MULTIPILOT);
+ *  newData.insert(OPL::db::FLIGHTS_DEP, ui->deptLocLineEdit->text());
+ *  newData.value(OPL::db::AIRCRAFT_MULTIPILOT);
  *
  *  instead of:
  *  newData.insert("dept", ui->deptLocLineEdit->text());
@@ -191,6 +226,7 @@ static const auto TABLE_TAILS            = QStringLiteral("tails");
 static const auto TABLE_AIRCRAFT         = QStringLiteral("aircraft");
 static const auto TABLE_AIRPORTS         = QStringLiteral("airports");
 static const auto TABLE_CURRENCIES       = QStringLiteral("currencies");
+static const auto TABLE_SIMULATORS       = QStringLiteral("simulators");
 
 // Flights table columns
 static const auto FLIGHTS_ROWID          = QStringLiteral("flight_id");
@@ -253,16 +289,20 @@ static const auto PILOTS_EMAIL           = QStringLiteral("email");
 static const auto CURRENCIES_EXPIRYDATE  = QStringLiteral("expiryDate");
 static const auto CURRENCIES_DESCRIPTION = QStringLiteral("description");
 
+// Simulators table
+static const auto SIMULATORS_ROWID       = QStringLiteral("session_id");
+static const auto SIMULATORS_DATE        = QStringLiteral("date");
+static const auto SIMULATORS_TIME        = QStringLiteral("totalTime");
+static const auto SIMULATORS_TYPE        = QStringLiteral("deviceType");
+static const auto SIMULATORS_ACFT        = QStringLiteral("aircraftType");
+static const auto SIMULATORS_REG         = QStringLiteral("registration");
+static const auto SIMULATORS_REMARKS     = QStringLiteral("remarks");
+
 // all tables
-static const auto ROWID                  = QStringLiteral("ROWID");
+static const auto ROWID                  = QStringLiteral("rowid");
 static const auto NULL_TIME_hhmm         = QStringLiteral("00:00");
 
-static const auto DEFAULT_FLIGHT_POSITION   = DataPosition(TABLE_FLIGHTS, 0);
-static const auto DEFAULT_PILOT_POSITION    = DataPosition(TABLE_PILOTS, 0);
-static const auto DEFAULT_TAIL_POSITION     = DataPosition(TABLE_TAILS, 0);
-static const auto DEFAULT_AIRCRAFT_POSITION = DataPosition(TABLE_AIRCRAFT, 0);
-
-} // namespace opl::db
+} // namespace OPL::db
 
 namespace Assets {
 
@@ -294,6 +334,11 @@ static const auto ICON_TOOLBAR_BACKUP_DARK      = QStringLiteral(":/icons/opl-ic
 
 }
 
+namespace Styles {
+
+static const auto RED_BORDER = QStringLiteral("border: 1px solid red");
+} // namespace Styles
+
 } // namespace opl
 
 #endif // OPLCONSTANTS_H

+ 2 - 2
src/testing/importCrewlounge/importcrewlounge.cpp

@@ -30,7 +30,7 @@ void exec(const QString &csv_file_path)
 
     for (const auto & pilot : p_maps) {
         APilotEntry pe(pilot);
-        pe.setPosition(DataPosition(Opl::Db::TABLE_PILOTS, pilot.value(Opl::Db::PILOTS_ROWID).toInt()));
+        pe.setPosition(DataPosition(OPL::Db::TABLE_PILOTS, pilot.value(OPL::Db::PILOTS_ROWID).toInt()));
         aDB->commit(pe);
     }
 
@@ -41,7 +41,7 @@ void exec(const QString &csv_file_path)
 
     for (const auto& tail : t_maps) {
         ATailEntry te(tail);
-        te.setPosition(DataPosition(Opl::Db::TABLE_TAILS, tail.value(Opl::Db::PILOTS_ROWID).toInt()));
+        te.setPosition(DataPosition(OPL::Db::TABLE_TAILS, tail.value(OPL::Db::PILOTS_ROWID).toInt()));
         aDB->commit(te);
     }
 

+ 13 - 13
src/testing/importCrewlounge/processaircraft.cpp

@@ -23,31 +23,31 @@ void ProcessAircraft::processParsedData()
 
     QHash<QString, QVariant> new_tail_data;
     for (const auto &list : qAsConst(unique_tails)) {
-        new_tail_data.insert(Opl::Db::TAILS_REGISTRATION, list[0]);
-        new_tail_data.insert(Opl::Db::TAILS_COMPANY, list[1]);
-        new_tail_data.insert(Opl::Db::TAILS_MAKE, list[2]);
-        new_tail_data.insert(Opl::Db::TAILS_MODEL, list[3]);
-        new_tail_data.insert(Opl::Db::TAILS_VARIANT, list[4]);
+        new_tail_data.insert(OPL::Db::TAILS_REGISTRATION, list[0]);
+        new_tail_data.insert(OPL::Db::TAILS_COMPANY, list[1]);
+        new_tail_data.insert(OPL::Db::TAILS_MAKE, list[2]);
+        new_tail_data.insert(OPL::Db::TAILS_MODEL, list[3]);
+        new_tail_data.insert(OPL::Db::TAILS_VARIANT, list[4]);
 
         if (list[5] == "TRUE")
-            new_tail_data.insert(Opl::Db::TAILS_MULTIPILOT, 1);
+            new_tail_data.insert(OPL::Db::TAILS_MULTIPILOT, 1);
         else
-            new_tail_data.insert(Opl::Db::TAILS_MULTIPILOT, 0);
+            new_tail_data.insert(OPL::Db::TAILS_MULTIPILOT, 0);
 
         if (list[6] == "TRUE")
-            new_tail_data.insert(Opl::Db::TAILS_MULTIENGINE, 1);
+            new_tail_data.insert(OPL::Db::TAILS_MULTIENGINE, 1);
         else
-            new_tail_data.insert(Opl::Db::TAILS_MULTIENGINE, 0);
+            new_tail_data.insert(OPL::Db::TAILS_MULTIENGINE, 0);
 
         if (list[7] == "Piston") // other values need to be added as needed, do later
-            new_tail_data.insert(Opl::Db::TAILS_ENGINETYPE, 1);
+            new_tail_data.insert(OPL::Db::TAILS_ENGINETYPE, 1);
         else if (list[7] == "Turbine (jet-fan)")
-            new_tail_data.insert(Opl::Db::TAILS_ENGINETYPE, 3);
+            new_tail_data.insert(OPL::Db::TAILS_ENGINETYPE, 3);
 
         if (list[8] == "TRUE") // this is a above 7.5t switch in MCC, so default to medium for now
-            new_tail_data.insert(Opl::Db::TAILS_WEIGHTCLASS, 1);
+            new_tail_data.insert(OPL::Db::TAILS_WEIGHTCLASS, 1);
         else
-            new_tail_data.insert(Opl::Db::TAILS_WEIGHTCLASS, 0);
+            new_tail_data.insert(OPL::Db::TAILS_WEIGHTCLASS, 0);
 
         new_tail_data.insert(QStringLiteral("tail_id"), unique_tail_id);
 

+ 25 - 25
src/testing/importCrewlounge/processflights.cpp

@@ -23,57 +23,57 @@ void ProcessFlights::processParsedData()
 
     for (const auto &row : qAsConst(rawFlightData)) {
         // insert values that don't require editing
-        new_flight_data.insert(Opl::Db::FLIGHTS_FLIGHTNUMBER, row[1]);
-        new_flight_data.insert(Opl::Db::FLIGHTS_DEPT, row[2]);
-        new_flight_data.insert(Opl::Db::FLIGHTS_DEST, row[3]);
-        new_flight_data.insert(Opl::Db::FLIGHTS_TBLK, row[6]);
-        new_flight_data.insert(Opl::Db::FLIGHTS_TPIC, row[7]);
-        new_flight_data.insert(Opl::Db::FLIGHTS_TSIC, row[8]);
-        new_flight_data.insert(Opl::Db::FLIGHTS_TDUAL, row[9]);
-        new_flight_data.insert(Opl::Db::FLIGHTS_TPICUS, row[10]);
-        new_flight_data.insert(Opl::Db::FLIGHTS_TFI, row[11]);
-        new_flight_data.insert(Opl::Db::FLIGHTS_TNIGHT, row[12]);
-        new_flight_data.insert(Opl::Db::FLIGHTS_TODAY, row[16]);
-        new_flight_data.insert(Opl::Db::FLIGHTS_TONIGHT, row[17]);
-        new_flight_data.insert(Opl::Db::FLIGHTS_LDGDAY, row[18]);
-        new_flight_data.insert(Opl::Db::FLIGHTS_LDGNIGHT, row[19]);
-        new_flight_data.insert(Opl::Db::FLIGHTS_APPROACHTYPE, row[21]);
-        new_flight_data.insert(Opl::Db::FLIGHTS_REMARKS, row[22]);
+        new_flight_data.insert(OPL::Db::FLIGHTS_FLIGHTNUMBER, row[1]);
+        new_flight_data.insert(OPL::Db::FLIGHTS_DEPT, row[2]);
+        new_flight_data.insert(OPL::Db::FLIGHTS_DEST, row[3]);
+        new_flight_data.insert(OPL::Db::FLIGHTS_TBLK, row[6]);
+        new_flight_data.insert(OPL::Db::FLIGHTS_TPIC, row[7]);
+        new_flight_data.insert(OPL::Db::FLIGHTS_TSIC, row[8]);
+        new_flight_data.insert(OPL::Db::FLIGHTS_TDUAL, row[9]);
+        new_flight_data.insert(OPL::Db::FLIGHTS_TPICUS, row[10]);
+        new_flight_data.insert(OPL::Db::FLIGHTS_TFI, row[11]);
+        new_flight_data.insert(OPL::Db::FLIGHTS_TNIGHT, row[12]);
+        new_flight_data.insert(OPL::Db::FLIGHTS_TODAY, row[16]);
+        new_flight_data.insert(OPL::Db::FLIGHTS_TONIGHT, row[17]);
+        new_flight_data.insert(OPL::Db::FLIGHTS_LDGDAY, row[18]);
+        new_flight_data.insert(OPL::Db::FLIGHTS_LDGNIGHT, row[19]);
+        new_flight_data.insert(OPL::Db::FLIGHTS_APPROACHTYPE, row[21]);
+        new_flight_data.insert(OPL::Db::FLIGHTS_REMARKS, row[22]);
 
         // PF
         if (row[20] == QLatin1String("TRUE"))
-            new_flight_data.insert(Opl::Db::FLIGHTS_PILOTFLYING, 1);
+            new_flight_data.insert(OPL::Db::FLIGHTS_PILOTFLYING, 1);
         else
-            new_flight_data.insert(Opl::Db::FLIGHTS_PILOTFLYING, 0);
+            new_flight_data.insert(OPL::Db::FLIGHTS_PILOTFLYING, 0);
 
         // Convert Date and Time
         const QDate doft = QDate::fromString(row[0],QStringLiteral("dd/MM/yyyy"));
-        new_flight_data.insert(Opl::Db::FLIGHTS_DOFT, doft.toString(Qt::ISODate));
+        new_flight_data.insert(OPL::Db::FLIGHTS_DOFT, doft.toString(Qt::ISODate));
 
         auto time_off = QTime::fromString(row[4], QStringLiteral("hh:mm"));
         if (!time_off.isValid())
             time_off = QTime::fromString(row[4], QStringLiteral("h:mm"));
         int tofb = ATime::toMinutes(time_off);
-        new_flight_data.insert(Opl::Db::FLIGHTS_TOFB, tofb);
+        new_flight_data.insert(OPL::Db::FLIGHTS_TOFB, tofb);
 
         auto time_on = QTime::fromString(row[5], QStringLiteral("hh:mm"));
         if (!time_on.isValid())
             time_on = QTime::fromString(row[5], QStringLiteral("h:mm"));
 
         int tonb = ATime::toMinutes(time_on);
-        new_flight_data.insert(Opl::Db::FLIGHTS_TONB, tonb);
+        new_flight_data.insert(OPL::Db::FLIGHTS_TONB, tonb);
 
         // map pilots
         int pic = processedPilotsIds.value(row[13]);
-        new_flight_data.insert(Opl::Db::FLIGHTS_PIC, pic);
+        new_flight_data.insert(OPL::Db::FLIGHTS_PIC, pic);
         int second_pilot = processedPilotsIds.value(row[14]);
-        new_flight_data.insert(Opl::Db::FLIGHTS_SECONDPILOT, second_pilot);
+        new_flight_data.insert(OPL::Db::FLIGHTS_SECONDPILOT, second_pilot);
         int third_pilot = processedPilotsIds.value(row[15]);
-        new_flight_data.insert(Opl::Db::FLIGHTS_THIRDPILOT, third_pilot);
+        new_flight_data.insert(OPL::Db::FLIGHTS_THIRDPILOT, third_pilot);
 
         // map tail
         int acft = processedTailsIds.value(row[23]);
-        new_flight_data.insert(Opl::Db::FLIGHTS_ACFT, acft);
+        new_flight_data.insert(OPL::Db::FLIGHTS_ACFT, acft);
 
         // set id, fix opl to include alias
         new_flight_data.insert(QStringLiteral("flight_id"), flight_id);

+ 7 - 7
src/testing/importCrewlounge/processpilots.cpp

@@ -51,21 +51,21 @@ void ProcessPilots::processParsedData()
         // process name [1]
         auto temp_list = pair.first[1].split(QLatin1Char(' '));
         if (!temp_list.isEmpty()) {
-            new_pilot_data.insert(Opl::Db::PILOTS_LASTNAME, temp_list.first());
+            new_pilot_data.insert(OPL::Db::PILOTS_LASTNAME, temp_list.first());
             temp_list.pop_front();
 
             if (!temp_list.isEmpty())
-                new_pilot_data.insert(Opl::Db::PILOTS_FIRSTNAME, temp_list.join(QLatin1Char(' ')));
+                new_pilot_data.insert(OPL::Db::PILOTS_FIRSTNAME, temp_list.join(QLatin1Char(' ')));
         } else {
-            new_pilot_data.insert(Opl::Db::PILOTS_LASTNAME, QStringLiteral("UNKNOWN"));
+            new_pilot_data.insert(OPL::Db::PILOTS_LASTNAME, QStringLiteral("UNKNOWN"));
         }
 
         // add additional data
-        new_pilot_data.insert(Opl::Db::PILOTS_EMPLOYEEID, pair.first[0]);
-        new_pilot_data.insert(Opl::Db::PILOTS_PHONE, pair.first[2]);
-        new_pilot_data.insert(Opl::Db::PILOTS_EMAIL, pair.first[3]);
+        new_pilot_data.insert(OPL::Db::PILOTS_EMPLOYEEID, pair.first[0]);
+        new_pilot_data.insert(OPL::Db::PILOTS_PHONE, pair.first[2]);
+        new_pilot_data.insert(OPL::Db::PILOTS_EMAIL, pair.first[3]);
 
-        // add pilot_id (workaround with literal until Opl::Db is updated)
+        // add pilot_id (workaround with literal until OPL::Db is updated)
         new_pilot_data.insert(QStringLiteral("pilot_id"), pair.second);
 
         processedPilotHashes.insert(pair.first[1], new_pilot_data);