Browse Source

Database rework and simplification

Database now part of the OPL namespace. Moved ACompletionData into OPL::DbCompletionData and the summary functionality into OPL::DbSummary.

aDB makro adjusted to DB.
Felix Turo 2 years ago
parent
commit
c518e2f127
54 changed files with 949 additions and 963 deletions
  1. 9 9
      CMakeLists.txt
  2. 1 1
      deprecated/acurrencyentry.h
  3. 2 2
      deprecated/adatabasesetup.h
  4. 0 0
      deprecated/adatabasetypes.h
  5. 1 1
      deprecated/aentry.h
  6. 1 1
      deprecated/apilotentry.h
  7. 1 1
      deprecated/atailentry.h
  8. 1 1
      deprecated/oldnewflightdialog.h
  9. 7 7
      docs/man/man3/ADataBaseSetup.3
  10. 35 35
      docs/man/man3/ADatabase.3
  11. 5 5
      docs/man/man3/ADatabaseError.3
  12. 1 1
      docs/man/man3/NewFlightDialog.3
  13. 1 1
      docs/man/man3/UserDataState.3
  14. 17 17
      docs/man/man3/experimental_ADatabase.3
  15. 4 4
      docs/man/man3/experimental_ADatabaseError.3
  16. 1 1
      main.cpp
  17. 25 25
      mainwindow.cpp
  18. 2 2
      mainwindow.h
  19. 1 1
      src/classes/aaircraftentry.h
  20. 17 17
      src/classes/acompletiondata.cpp
  21. 6 6
      src/classes/acompletiondata.h
  22. 10 14
      src/classes/ajson.cpp
  23. 7 2
      src/classes/ajson.h
  24. 158 446
      src/database/database.cpp
  25. 85 171
      src/database/database.h
  26. 141 0
      src/database/dbcompletiondata.cpp
  27. 76 0
      src/database/dbcompletiondata.h
  28. 80 0
      src/database/dbsummary.cpp
  29. 56 0
      src/database/dbsummary.h
  30. 1 1
      src/database/row.cpp
  31. 1 0
      src/database/row.h
  32. 11 11
      src/functions/acalc.cpp
  33. 3 3
      src/functions/astat.cpp
  34. 33 29
      src/gui/dialogues/firstrundialog.cpp
  35. 11 11
      src/gui/dialogues/newflightdialog.cpp
  36. 7 7
      src/gui/dialogues/newflightdialog.h
  37. 7 6
      src/gui/dialogues/newpilotdialog.cpp
  38. 1 1
      src/gui/dialogues/newpilotdialog.h
  39. 5 5
      src/gui/dialogues/newsimdialog.cpp
  40. 4 4
      src/gui/dialogues/newsimdialog.h
  41. 7 6
      src/gui/dialogues/newtaildialog.cpp
  42. 3 3
      src/gui/dialogues/newtaildialog.h
  43. 8 8
      src/gui/widgets/aircraftwidget.cpp
  44. 20 19
      src/gui/widgets/backupwidget.cpp
  45. 20 19
      src/gui/widgets/debugwidget.cpp
  46. 2 2
      src/gui/widgets/debugwidget.h
  47. 4 4
      src/gui/widgets/homewidget.cpp
  48. 1 1
      src/gui/widgets/homewidget.h
  49. 8 12
      src/gui/widgets/logbookwidget.cpp
  50. 4 4
      src/gui/widgets/logbookwidget.h
  51. 8 8
      src/gui/widgets/pilotswidget.cpp
  52. 19 19
      src/gui/widgets/settingswidget.cpp
  53. 3 2
      src/opl.h
  54. 7 7
      src/testing/importCrewlounge/importcrewlounge.cpp

+ 9 - 9
CMakeLists.txt

@@ -26,7 +26,7 @@ set(PROJECT_SOURCES
     src/opl.h
     src/opl.cpp
 
-    # GUI
+    ##  GUI
     mainwindow.h
     mainwindow.cpp
     mainwindow.ui
@@ -49,7 +49,6 @@ set(PROJECT_SOURCES
     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
@@ -78,10 +77,6 @@ set(PROJECT_SOURCES
 
 
     # Classes
-    src/classes/row.h
-    src/classes/row.cpp
-    src/classes/acompletiondata.h
-    src/classes/acompletiondata.cpp
     src/classes/astyle.h
     src/classes/astyle.cpp
     src/classes/astandardpaths.h
@@ -114,9 +109,14 @@ set(PROJECT_SOURCES
     src/functions/atime.h
 
     # Database
-    src/database/adatabasetypes.h
-    src/database/adatabase.h
-    src/database/adatabase.cpp
+    src/database/database.h
+    src/database/database.cpp
+    src/database/row.h
+    src/database/row.cpp
+    src/database/dbcompletiondata.h
+    src/database/dbcompletiondata.cpp
+    src/database/dbsummary.h
+    src/database/dbsummary.cpp
 
     # Ressources
     assets/icons.qrc

+ 1 - 1
deprecated/acurrencyentry.h

@@ -1,7 +1,7 @@
 #ifndef ACURRENCYENTRY_H
 #define ACURRENCYENTRY_H
 
-#include "src/database/adatabasetypes.h"
+#include "src/database/databasetypes.h"
 
 /*!
  * \brief The Entry class encapsulates table metadata(table name, row id)

+ 2 - 2
deprecated/adatabasesetup.h

@@ -28,12 +28,12 @@ const auto TEMPLATE_URL = QStringLiteral("https://raw.githubusercontent.com/fiff
 
 
 /*!
- * \brief The ADataBaseSetup class is responsible for the inital setup of the database when
+ * \brief The DataBaseSetup class is responsible for the inital setup of the database when
  * the application is first launched. It creates the database in the specified default
  * location and creates all required tables and views. It can also be used to reset the
  * database currently used
  */
-class ADataBaseSetup
+class DataBaseSetup
 {
 public:
     static void debug();

+ 0 - 0
src/database/adatabasetypes.h → deprecated/adatabasetypes.h


+ 1 - 1
deprecated/aentry.h

@@ -24,7 +24,7 @@
 #include <QPair>
 #include <QVariant>
 
-#include "src/database/adatabasetypes.h"
+#include "src/database/databasetypes.h"
 
 /*!
  * \brief The Entry class encapsulates table metadata(table name, row id)

+ 1 - 1
deprecated/apilotentry.h

@@ -19,7 +19,7 @@
 #define APILOTENTRY_H
 
 #include "src/classes/aentry.h"
-#include "src/database/adatabasetypes.h"
+#include "src/database/databasetypes.h"
 
 struct APilotEntry : public AEntry {
 public:

+ 1 - 1
deprecated/atailentry.h

@@ -19,7 +19,7 @@
 #define ATAILENTRY_H
 
 #include "src/classes/aentry.h"
-#include "src/database/adatabasetypes.h"
+#include "src/database/databasetypes.h"
 
 struct ATailEntry : public AEntry {
 public:

+ 1 - 1
deprecated/oldnewflightdialog.h

@@ -36,7 +36,7 @@
 #include "src/classes/aflightentry.h"
 #include "src/classes/apilotentry.h"
 #include "src/classes/atailentry.h"
-#include "src/database/adatabase.h"
+#include "src/database/database.h"
 #include "src/classes/acompletiondata.h"
 
 namespace Ui {

+ 7 - 7
docs/man/man3/ADataBaseSetup.3

@@ -1,14 +1,14 @@
-.TH "ADataBaseSetup" 3 "Tue Jul 27 2021" "openPilotLog" \" -*- nroff -*-
+.TH "DataBaseSetup" 3 "Tue Jul 27 2021" "openPilotLog" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-ADataBaseSetup \- The \fBADataBaseSetup\fP class is responsible for the inital setup of the database when the application is first launched\&. It creates the database in the specified default location and creates all required tables and views\&. It can also be used to reset the database currently used\&.  
+DataBaseSetup \- The \fBDataBaseSetup\fP class is responsible for the inital setup of the database when the application is first launched\&. It creates the database in the specified default location and creates all required tables and views\&. It can also be used to reset the database currently used\&.  
 
 .SH SYNOPSIS
 .br
 .PP
 .PP
-\fC#include <adatabasesetup\&.h>\fP
+\fC#include <databasesetup\&.h>\fP
 .SS "Static Public Member Functions"
 
 .in +1c
@@ -46,10 +46,10 @@ ADataBaseSetup \- The \fBADataBaseSetup\fP class is responsible for the inital s
 .in -1c
 .SH "Detailed Description"
 .PP 
-The \fBADataBaseSetup\fP class is responsible for the inital setup of the database when the application is first launched\&. It creates the database in the specified default location and creates all required tables and views\&. It can also be used to reset the database currently used\&. 
+The \fBDataBaseSetup\fP class is responsible for the inital setup of the database when the application is first launched\&. It creates the database in the specified default location and creates all required tables and views\&. It can also be used to reset the database currently used\&. 
 .SH "Member Function Documentation"
 .PP 
-.SS "QT_DEPRECATED bool ADataBaseSetup::commitData (QVector< QStringList > from_csv, const QString & table_name)\fC [static]\fP"
+.SS "QT_DEPRECATED bool DataBaseSetup::commitData (QVector< QStringList > from_csv, const QString & table_name)\fC [static]\fP"
 
 .PP
 DbSetup::commitData inserts the data parsed from a csv file into the database\&. The first line of the csv file has to contain the column names of the corresponding table in the database\&. 
@@ -66,7 +66,7 @@ DbSetup::commitData inserts the data parsed from a csv file into the database\&.
 .RE
 .PP
 
-.SS "QT_DEPRECATED bool ADataBaseSetup::commitDataJson (const QJsonArray & json_arr, const QString & table_name)\fC [static]\fP"
+.SS "QT_DEPRECATED bool DataBaseSetup::commitDataJson (const QJsonArray & json_arr, const QString & table_name)\fC [static]\fP"
 
 .PP
 commitDataJson Commits data read from a JSON array to the database\&. 
@@ -79,7 +79,7 @@ commitDataJson Commits data read from a JSON array to the database\&.
 .RE
 .PP
 
-.SS "QT_DEPRECATED bool ADataBaseSetup::resetToDefault ()\fC [static]\fP"
+.SS "QT_DEPRECATED bool DataBaseSetup::resetToDefault ()\fC [static]\fP"
 
 .PP
 DbSetup::resetToDefault Empties all user-generated content in the database\&. 

+ 35 - 35
docs/man/man3/ADatabase.3

@@ -1,14 +1,14 @@
-.TH "ADatabase" 3 "Fri Mar 4 2022" "openPilotLog" \" -*- nroff -*-
+.TH "Database" 3 "Fri Mar 4 2022" "openPilotLog" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-ADatabase \- The DB class encapsulates the SQL database by providing fast access to hot database data\&.  
+Database \- The DB class encapsulates the SQL database by providing fast access to hot database data\&.  
 
 .SH SYNOPSIS
 .br
 .PP
 .PP
-\fC#include <adatabase\&.h>\fP
+\fC#include <database\&.h>\fP
 .PP
 Inherits QObject\&.
 .SS "Signals"
@@ -27,10 +27,10 @@ Inherits QObject\&.
 
 .in +1c
 .ti -1c
-.RI "\fBADatabase\fP (const \fBADatabase\fP &)=delete"
+.RI "\fBDatabase\fP (const \fBDatabase\fP &)=delete"
 .br
 .ti -1c
-.RI "void \fBoperator=\fP (const \fBADatabase\fP &)=delete"
+.RI "void \fBoperator=\fP (const \fBDatabase\fP &)=delete"
 .br
 .ti -1c
 .RI "int \fBdbRevision\fP () const"
@@ -51,7 +51,7 @@ Inherits QObject\&.
 .ti -1c
 .RI "const QString \fBsqliteVersion\fP () const"
 .br
-.RI "\fBADatabase::sqliteVersion\fP returns the database sqlite version\&. See also \fBdbRevision()\fP "
+.RI "\fBDatabase::sqliteVersion\fP returns the database sqlite version\&. See also \fBdbRevision()\fP "
 .ti -1c
 .RI "bool \fBconnect\fP ()"
 .br
@@ -124,19 +124,19 @@ Inherits QObject\&.
 .br
 .RI "Retreives a currency entry from the database\&. "
 .ti -1c
-.RI "const QStringList \fBgetCompletionList\fP (ADatabaseTarget target)"
+.RI "const QStringList \fBgetCompletionList\fP (DatabaseTarget target)"
 .br
 .RI "getCompletionList returns a QStringList of values for a QCompleter based on database values "
 .ti -1c
-.RI "const QHash< RowId_T, QString > \fBgetIdMap\fP (ADatabaseTarget target)"
+.RI "const QHash< RowId_T, QString > \fBgetIdMap\fP (DatabaseTarget target)"
 .br
 .RI "returns a QHash of a human-readable database value and its row id\&. Used in the Dialogs to map user input to unique database entries\&. "
 .ti -1c
-.RI "RowId_T \fBgetLastEntry\fP (ADatabaseTable table)"
+.RI "RowId_T \fBgetLastEntry\fP (DatabaseTable table)"
 .br
 .RI "returns the ROWID for the newest entry in the respective database\&. "
 .ti -1c
-.RI "QList< RowId_T > \fBgetForeignKeyConstraints\fP (RowId_T foreign_row_id, ADatabaseTable target)"
+.RI "QList< RowId_T > \fBgetForeignKeyConstraints\fP (RowId_T foreign_row_id, DatabaseTable target)"
 .br
 .RI "returns a list of ROWID's in the flights table for which foreign key constraints exist\&. "
 .ti -1c
@@ -148,7 +148,7 @@ Inherits QObject\&.
 .br
 .RI "Resolves the foreign key in a flight entry\&. "
 .ti -1c
-.RI "QMap< ADatabaseSummaryKey, QString > \fBdatabaseSummary\fP (const QString &db_path)"
+.RI "QMap< DatabaseSummaryKey, QString > \fBdatabaseSummary\fP (const QString &db_path)"
 .br
 .RI "Return a summary of a database\&. "
 .ti -1c
@@ -158,13 +158,13 @@ Inherits QObject\&.
 .ti -1c
 .RI "bool \fBrestoreBackup\fP (const QString &backup_file)"
 .br
-.RI "\fBADatabase::restoreBackup\fP restores the database from a given backup file and replaces the currently active database\&. "
+.RI "\fBDatabase::restoreBackup\fP restores the database from a given backup file and replaces the currently active database\&. "
 .ti -1c
 .RI "bool \fBcreateBackup\fP (const QString &dest_file)"
 .br
-.RI "\fBADatabase::createBackup\fP copies the currently used database to an external backup location provided by the user\&. "
+.RI "\fBDatabase::createBackup\fP copies the currently used database to an external backup location provided by the user\&. "
 .ti -1c
-.RI "QVector< RowData_T > \fBgetTable\fP (ADatabaseTable table_name)"
+.RI "QVector< RowData_T > \fBgetTable\fP (DatabaseTable table_name)"
 .br
 .RI "getTable returns all contents of a given table from the database "
 .ti -1c
@@ -184,7 +184,7 @@ Inherits QObject\&.
 
 .in +1c
 .ti -1c
-.RI "static \fBADatabase\fP * \fBinstance\fP ()"
+.RI "static \fBDatabase\fP * \fBinstance\fP ()"
 .br
 .ti -1c
 .RI "static QSqlDatabase \fBdatabase\fP ()"
@@ -211,10 +211,10 @@ Inherits QObject\&.
 The DB class encapsulates the SQL database by providing fast access to hot database data\&. 
 .SH "Member Function Documentation"
 .PP 
-.SS "bool ADatabase::createBackup (const QString & dest_file)"
+.SS "bool Database::createBackup (const QString & dest_file)"
 
 .PP
-\fBADatabase::createBackup\fP copies the currently used database to an external backup location provided by the user\&. 
+\fBDatabase::createBackup\fP copies the currently used database to an external backup location provided by the user\&. 
 .PP
 \fBParameters\fP
 .RS 4
@@ -222,7 +222,7 @@ The DB class encapsulates the SQL database by providing fast access to hot datab
 .RE
 .PP
 
-.SS "QVector< QVariant > ADatabase::customQuery (QString statement, int return_values)"
+.SS "QVector< QVariant > Database::customQuery (QString statement, int return_values)"
 
 .PP
 Can be used to send a complex query to the database\&. 
@@ -235,7 +235,7 @@ Can be used to send a complex query to the database\&.
 .RE
 .PP
 
-.SS "QSqlDatabase ADatabase::database ()\fC [static]\fP"
+.SS "QSqlDatabase Database::database ()\fC [static]\fP"
 
 .PP
 Can be used to access the database connection\&. 
@@ -246,11 +246,11 @@ The QSqlDatabase object pertaining to the connection\&.
 .RE
 .PP
 
-.SS "QMap< ADatabaseSummaryKey, QString > ADatabase::databaseSummary (const QString & db_path)"
+.SS "QMap< DatabaseSummaryKey, QString > Database::databaseSummary (const QString & db_path)"
 
 .PP
-Return a summary of a database\&. Creates a summary of the database giving a quick overview of the relevant contents\&. The function runs several specialised SQL queries to create a QHash<ADatabaseSummaryKey, QString> containing Total Flight Time, Number of unique aircraft and pilots, as well as the date of last flight\&. Uses a temporary database connection separate from the default connection in order to not tamper with the currently active database connection\&. 
-.SS "int ADatabase::dbRevision () const"
+Return a summary of a database\&. Creates a summary of the database giving a quick overview of the relevant contents\&. The function runs several specialised SQL queries to create a QHash<DatabaseSummaryKey, QString> containing Total Flight Time, Number of unique aircraft and pilots, as well as the date of last flight\&. Uses a temporary database connection separate from the default connection in order to not tamper with the currently active database connection\&. 
+.SS "int Database::dbRevision () const"
 
 .PP
 dbRevision returns the database Revision Number\&. The Revision refers to what iteration of the database layout is used\&. For the sqlite version of the database refer to \fBsqliteVersion()\fP 
@@ -261,19 +261,19 @@ dbRevision returns the database Revision Number\&. The Revision refers to what i
 .RE
 .PP
 
-.SS "\fBAAircraftEntry\fP ADatabase::getAircraftEntry (RowId_T row_id)"
+.SS "\fBAAircraftEntry\fP Database::getAircraftEntry (RowId_T row_id)"
 
 .PP
 retreives a TailEntry from the database\&. This function is a wrapper for DataBase::getEntry(DataPosition), where the table is already set and which returns an \fBAAircraftEntry\fP instead of an \fBAEntry\fP\&. It allows for easy access to an aircraft entry with only the RowId required as input\&. 
-.SS "\fBAFlightEntry\fP ADatabase::getFlightEntry (RowId_T row_id)"
+.SS "\fBAFlightEntry\fP Database::getFlightEntry (RowId_T row_id)"
 
 .PP
 retreives a flight entry from the database\&. This function is a wrapper for DataBase::getEntry(DataPosition), where the table is already set and which returns an \fBAFlightEntry\fP instead of an \fBAEntry\fP\&. It allows for easy access to a flight entry with only the RowId required as input\&. 
-.SS "\fBAPilotEntry\fP ADatabase::getPilotEntry (RowId_T row_id)"
+.SS "\fBAPilotEntry\fP Database::getPilotEntry (RowId_T row_id)"
 
 .PP
 retreives a PilotEntry from the database\&. This function is a wrapper for DataBase::getEntry(DataPosition), where the table is already set and which returns a PilotEntry instead of an Entry\&. It allows for easy access to a pilot entry with only the RowId required as input\&. 
-.SS "QVector< RowData_T > ADatabase::getTable (ADatabaseTable table_name)"
+.SS "QVector< RowData_T > Database::getTable (DatabaseTable table_name)"
 
 .PP
 getTable returns all contents of a given table from the database 
@@ -284,11 +284,11 @@ getTable returns all contents of a given table from the database
 .RE
 .PP
 
-.SS "\fBATailEntry\fP ADatabase::getTailEntry (RowId_T row_id)"
+.SS "\fBATailEntry\fP Database::getTailEntry (RowId_T row_id)"
 
 .PP
 retreives a TailEntry from the database\&. This function is a wrapper for DataBase::getEntry(DataPosition), where the table is already set and which returns a TailEntry instead of an Entry\&. It allows for easy access to a tail entry with only the RowId required as input\&. 
-.SS "\fBUserDataState\fP ADatabase::getUserDataState ()"
+.SS "\fBUserDataState\fP Database::getUserDataState ()"
 
 .PP
 getUserDataState returns a struct containing the current amount of entries in the tails and pilots tables\&. 
@@ -299,7 +299,7 @@ getUserDataState returns a struct containing the current amount of entries in th
 .RE
 .PP
 
-.SS "\fBAPilotEntry\fP ADatabase::resolveForeignPilot (RowId_T foreign_key)"
+.SS "\fBAPilotEntry\fP Database::resolveForeignPilot (RowId_T foreign_key)"
 
 .PP
 Resolves the foreign key in a flight entry\&. 
@@ -310,7 +310,7 @@ The Pilot Entry referencted by the foreign key\&.
 .RE
 .PP
 
-.SS "\fBATailEntry\fP ADatabase::resolveForeignTail (RowId_T foreign_key)"
+.SS "\fBATailEntry\fP Database::resolveForeignTail (RowId_T foreign_key)"
 
 .PP
 Resolves the foreign key in a flight entry\&. 
@@ -321,10 +321,10 @@ The Tail Entry referencted by the foreign key\&.
 .RE
 .PP
 
-.SS "bool ADatabase::restoreBackup (const QString & backup_file)"
+.SS "bool Database::restoreBackup (const QString & backup_file)"
 
 .PP
-\fBADatabase::restoreBackup\fP restores the database from a given backup file and replaces the currently active database\&. 
+\fBDatabase::restoreBackup\fP restores the database from a given backup file and replaces the currently active database\&. 
 .PP
 \fBParameters\fP
 .RS 4
@@ -332,10 +332,10 @@ The Tail Entry referencted by the foreign key\&.
 .RE
 .PP
 
-.SS "const QString ADatabase::sqliteVersion () const"
+.SS "const QString Database::sqliteVersion () const"
 
 .PP
-\fBADatabase::sqliteVersion\fP returns the database sqlite version\&. See also \fBdbRevision()\fP 
+\fBDatabase::sqliteVersion\fP returns the database sqlite version\&. See also \fBdbRevision()\fP 
 .PP
 \fBReturns\fP
 .RS 4
@@ -345,7 +345,7 @@ sqlite version string
 
 .SH "Member Data Documentation"
 .PP 
-.SS "QSqlError ADatabase::lastError"
+.SS "QSqlError Database::lastError"
 
 .PP
 Holds information about the last error that ocurred during a SQL operation\&. If the error type is QSqlError::UnknownError, the error is related to data from the database (entry not found,\&.\&.\&.), otherwise the error is related to SQL execution\&. In this case error\&.type() provides further information\&. If the error type is QSqlError::NoError, the last executed database query was successful\&. 

+ 5 - 5
docs/man/man3/ADatabaseError.3

@@ -1,27 +1,27 @@
-.TH "ADatabaseError" 3 "Fri Mar 4 2022" "openPilotLog" \" -*- nroff -*-
+.TH "DatabaseError" 3 "Fri Mar 4 2022" "openPilotLog" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-ADatabaseError \- Custom Database Error derived from QSqlError\&. Extends text() adding 'Database Error: ' before the text\&. Errors that are related to SQL are assigned their respective error codes\&. Errors that occur with data in the database are handled with the error code 'opl' and QSqlError::UnknownError\&.  
+DatabaseError \- Custom Database Error derived from QSqlError\&. Extends text() adding 'Database Error: ' before the text\&. Errors that are related to SQL are assigned their respective error codes\&. Errors that occur with data in the database are handled with the error code 'opl' and QSqlError::UnknownError\&.  
 
 .SH SYNOPSIS
 .br
 .PP
 .PP
-\fC#include <adatabase\&.h>\fP
+\fC#include <database\&.h>\fP
 .PP
 Inherits QSqlError\&.
 .SS "Public Member Functions"
 
 .in +1c
 .ti -1c
-.RI "\fBADatabaseError\fP (QString msg)"
+.RI "\fBDatabaseError\fP (QString msg)"
 .br
 .ti -1c
 .RI "QString \fBtext\fP () const"
 .br
 .ti -1c
-.RI "\fBADatabaseError\fP (QSqlError)"
+.RI "\fBDatabaseError\fP (QSqlError)"
 .br
 .in -1c
 .SH "Detailed Description"

+ 1 - 1
docs/man/man3/NewFlightDialog.3

@@ -43,7 +43,7 @@ To ensure only good data is written to the database, the \fBValidationState\fP c
 .PP
 Inputs from the user are verified with a two-step process\&. The first level of verification is accomplished by QRegularExpressionValidator, which limits the user to only inputting generally acceptable data (like numbers for date or time, or characters for airport identifiers)\&. If the input passes this sanity check, the line edits emit the editingFinished() signal, which triggers a more granular and sophisticated set of input verification, broadly based on cross-checking the entered data against known good values\&. The \fBACompletionData\fP class is used to provide QHashs of known good values from the database and their respective ROW_IDs\&. If user-entered data has been matched to a known good database value, the data is considered acceptable\&. This means that in order to, for example, log a flight with a certain Pilot, that this pilot already has to exist in the pilots table\&. If this is not the case, the user is prompted to add a new pilot (or aircraft) to the database before proceeding\&. In order to make this matching process seamless for the user, the completionData also contains a set of QStringLists for each of the database tables which are used to create QCompleters that provide pop-up completion on the respective QLineEdits\&.
 .PP
-Once the user is satisfied with his entries, a final set of input verification is triggered and the entry is submitted to the database, see on_buttonBox_accepted() and \fBADatabase::commit()\fP 
+Once the user is satisfied with his entries, a final set of input verification is triggered and the entry is submitted to the database, see on_buttonBox_accepted() and \fBDatabase::commit()\fP 
 .SH "Constructor & Destructor Documentation"
 .PP 
 .SS "NewFlightDialog::NewFlightDialog (\fBACompletionData\fP & completion_data, QWidget * parent = \fCnullptr\fP)\fC [explicit]\fP"

+ 1 - 1
docs/man/man3/UserDataState.3

@@ -8,7 +8,7 @@ UserDataState \- The UserDateState struct caches the current number of entries i
 .br
 .PP
 .PP
-\fC#include <adatabase\&.h>\fP
+\fC#include <database\&.h>\fP
 .SS "Public Member Functions"
 
 .in +1c

+ 17 - 17
docs/man/man3/experimental_ADatabase.3

@@ -1,14 +1,14 @@
-.TH "experimental::ADatabase" 3 "Sun Dec 27 2020" "openPilotLog" \" -*- nroff -*-
+.TH "experimental::Database" 3 "Sun Dec 27 2020" "openPilotLog" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-experimental::ADatabase \- The DB class encapsulates the SQL database by providing fast access to hot database data\&.  
+experimental::Database \- The DB class encapsulates the SQL database by providing fast access to hot database data\&.  
 
 .SH SYNOPSIS
 .br
 .PP
 .PP
-\fC#include <adatabase\&.h>\fP
+\fC#include <database\&.h>\fP
 .PP
 Inherits QObject\&.
 .SS "Signals"
@@ -23,10 +23,10 @@ Inherits QObject\&.
 
 .in +1c
 .ti -1c
-.RI "\fBADatabase\fP (const \fBADatabase\fP &)=delete"
+.RI "\fBDatabase\fP (const \fBDatabase\fP &)=delete"
 .br
 .ti -1c
-.RI "void \fBoperator=\fP (const \fBADatabase\fP &)=delete"
+.RI "void \fBoperator=\fP (const \fBDatabase\fP &)=delete"
 .br
 .ti -1c
 .RI "bool \fBconnect\fP ()"
@@ -92,19 +92,19 @@ Inherits QObject\&.
 .br
 .RI "retreives a flight entry from the database\&. "
 .ti -1c
-.RI "const QStringList \fBgetCompletionList\fP (\fBADatabaseTarget\fP)"
+.RI "const QStringList \fBgetCompletionList\fP (\fBDatabaseTarget\fP)"
 .br
 .RI "getCompletionList returns a QStringList of values for a QCompleter based on database values "
 .ti -1c
-.RI "const QHash< QString, int > \fBgetIdMap\fP (\fBADatabaseTarget\fP)"
+.RI "const QHash< QString, int > \fBgetIdMap\fP (\fBDatabaseTarget\fP)"
 .br
 .RI "returns a QHash<QString, int> of a human-readable database value and its row id\&. Used in the Dialogs to map user input to unique database entries\&. "
 .ti -1c
-.RI "int \fBgetLastEntry\fP (\fBADatabaseTarget\fP)"
+.RI "int \fBgetLastEntry\fP (\fBDatabaseTarget\fP)"
 .br
 .RI "returns the ROWID for the newest entry in the respective database\&. "
 .ti -1c
-.RI "QList< int > \fBgetForeignKeyConstraints\fP (int foreign_row_id, \fBADatabaseTarget\fP target)"
+.RI "QList< int > \fBgetForeignKeyConstraints\fP (int foreign_row_id, \fBDatabaseTarget\fP target)"
 .br
 .RI "returns a list of ROWID's in the flights table for which foreign key constraints exist\&. "
 .in -1c
@@ -112,7 +112,7 @@ Inherits QObject\&.
 
 .in +1c
 .ti -1c
-.RI "static \fBADatabase\fP * \fBgetInstance\fP ()"
+.RI "static \fBDatabase\fP * \fBgetInstance\fP ()"
 .br
 .ti -1c
 .RI "static QSqlDatabase \fBdatabase\fP ()"
@@ -123,7 +123,7 @@ Inherits QObject\&.
 
 .in +1c
 .ti -1c
-.RI "\fBADatabaseError\fP \fBlastError\fP"
+.RI "\fBDatabaseError\fP \fBlastError\fP"
 .br
 .in -1c
 .SH "Detailed Description"
@@ -131,7 +131,7 @@ Inherits QObject\&.
 The DB class encapsulates the SQL database by providing fast access to hot database data\&. 
 .SH "Member Function Documentation"
 .PP 
-.SS "QVector< QString > experimental::ADatabase::customQuery (QString statement, int return_values)"
+.SS "QVector< QString > experimental::Database::customQuery (QString statement, int return_values)"
 
 .PP
 Can be used to send a complex query to the database\&. 
@@ -144,7 +144,7 @@ Can be used to send a complex query to the database\&.
 .RE
 .PP
 
-.SS "QSqlDatabase experimental::ADatabase::database ()\fC [static]\fP"
+.SS "QSqlDatabase experimental::Database::database ()\fC [static]\fP"
 
 .PP
 Can be used to access the database connection\&. 
@@ -155,19 +155,19 @@ The QSqlDatabase object pertaining to the connection\&.
 .RE
 .PP
 
-.SS "\fBAAircraftEntry\fP experimental::ADatabase::getAircraftEntry (RowId row_id)"
+.SS "\fBAAircraftEntry\fP experimental::Database::getAircraftEntry (RowId row_id)"
 
 .PP
 retreives a TailEntry from the database\&. This function is a wrapper for DataBase::getEntry(DataPosition), where the table is already set and which returns an \fBAAircraftEntry\fP instead of an \fBAEntry\fP\&. It allows for easy access to an aircraft entry with only the RowId required as input\&. 
-.SS "\fBAFlightEntry\fP experimental::ADatabase::getFlightEntry (RowId row_id)"
+.SS "\fBAFlightEntry\fP experimental::Database::getFlightEntry (RowId row_id)"
 
 .PP
 retreives a flight entry from the database\&. This function is a wrapper for DataBase::getEntry(DataPosition), where the table is already set and which returns an \fBAFlightEntry\fP instead of an \fBAEntry\fP\&. It allows for easy access to a flight entry with only the RowId required as input\&. 
-.SS "\fBAPilotEntry\fP experimental::ADatabase::getPilotEntry (RowId row_id)"
+.SS "\fBAPilotEntry\fP experimental::Database::getPilotEntry (RowId row_id)"
 
 .PP
 retreives a PilotEntry from the database\&. This function is a wrapper for DataBase::getEntry(DataPosition), where the table is already set and which returns a PilotEntry instead of an Entry\&. It allows for easy access to a pilot entry with only the RowId required as input\&. 
-.SS "\fBATailEntry\fP experimental::ADatabase::getTailEntry (RowId row_id)"
+.SS "\fBATailEntry\fP experimental::Database::getTailEntry (RowId row_id)"
 
 .PP
 retreives a TailEntry from the database\&. This function is a wrapper for DataBase::getEntry(DataPosition), where the table is already set and which returns a TailEntry instead of an Entry\&. It allows for easy access to a tail entry with only the RowId required as input\&. 

+ 4 - 4
docs/man/man3/experimental_ADatabaseError.3

@@ -1,21 +1,21 @@
-.TH "experimental::ADatabaseError" 3 "Sun Dec 27 2020" "openPilotLog" \" -*- nroff -*-
+.TH "experimental::DatabaseError" 3 "Sun Dec 27 2020" "openPilotLog" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-experimental::ADatabaseError \- Custom Database Error derived from QSqlError\&. Extends text() adding 'Database Error: ' before the text\&.  
+experimental::DatabaseError \- Custom Database Error derived from QSqlError\&. Extends text() adding 'Database Error: ' before the text\&.  
 
 .SH SYNOPSIS
 .br
 .PP
 .PP
-\fC#include <adatabase\&.h>\fP
+\fC#include <database\&.h>\fP
 .PP
 Inherits QSqlError\&.
 .SS "Public Member Functions"
 
 .in +1c
 .ti -1c
-.RI "\fBADatabaseError\fP (QString msg)"
+.RI "\fBDatabaseError\fP (QString msg)"
 .br
 .ti -1c
 .RI "QString \fBtext\fP () const"

+ 1 - 1
main.cpp

@@ -20,7 +20,7 @@
 #include "src/functions/alog.h"
 #include "src/gui/dialogues/firstrundialog.h"
 #include "src/classes/arunguard.h"
-#include "src/database/adatabase.h"
+#include "src/database/database.h"
 #include "src/classes/asettings.h"
 #include "src/classes/astandardpaths.h"
 #include "src/classes/asettings.h"

+ 25 - 25
mainwindow.cpp

@@ -19,12 +19,12 @@
 #include "mainwindow.h"
 #include "ui_mainwindow.h"
 #include "src/functions/alog.h"
-#include "src/database/adatabase.h"
+#include "src/database/database.h"
 #include "src/classes/astyle.h"
 #include "src/gui/dialogues/firstrundialog.h"
 #include "src/gui/dialogues/newflightdialog.h"
 #include "src/functions/adatetime.h"
-#include "src/classes/row.h"
+#include "src/database/row.h"
 #include "src/gui/dialogues/newsimdialog.h"
 // Quick and dirty Debug area
 void MainWindow::doDebugStuff()
@@ -39,8 +39,8 @@ void MainWindow::doDebugStuff()
     //
     //for (int i = 1; i < 1000; i++) {
     //    DataPosition dp("airports", i);
-    //    auto entry = aDB->getEntry(dp);
-    //    //auto entry = aDB->(i);
+    //    auto entry = DB->getEntry(dp);
+    //    //auto entry = DB->(i);
     //}
     //DEB << "getEntry completed";
     //}
@@ -49,18 +49,18 @@ void MainWindow::doDebugStuff()
     //ATimer timer;
     //
     //for (int i = 1; i < 1000; i++) {
-    //    auto row = aDB->getRow(OPL::DbTable::Airports, i);
+    //    auto row = DB->getRow(OPL::DbTable::Airports, i);
     //}
     //DEB << "getRow completed";
     //}
     //OPL::Row new_row(OPL::DbTable::Aircraft, 4, entry.getData());
     //DEB << new_row;
-    //DEB << aDB->commit(new_row);
-    //DEB << aDB->getAircraftEntry(4);
+    //DEB << DB->commit(new_row);
+    //DEB << DB->getAircraftEntry(4);
 
-    auto row = aDB->getRow(OPL::DbTable::Flights, 2);
+    auto row = DB->getRow(OPL::DbTable::Flights, 2);
     DEB << row;
-    auto row_2 = aDB->getRow(OPL::DbTable::Flights, 500);
+    auto row_2 = DB->getRow(OPL::DbTable::Flights, 500);
     DEB << row_2;
 
 }
@@ -80,7 +80,7 @@ MainWindow::MainWindow(QWidget *parent)
     if (database_file.size() == 0)
         onDatabaseInvalid();
 
-    if(!aDB->connect()){
+    if(!DB->connect()){
         WARN(tr("Error establishing database connection."));
     }
 
@@ -110,13 +110,13 @@ MainWindow::MainWindow(QWidget *parent)
     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);
-    }
+    //if (DB->dbRevision() < DB->getMinimumDatabaseRevision()) {
+    //    QString message = tr("Your database is out of date."
+    //                         "Minimum required revision: %1<br>"
+    //                         "You have revision: %2<br>")
+    //                         .arg(DB->getMinimumDatabaseRevision(), DB->dbRevision());
+    //    WARN(message);
+    //}
 }
 
 MainWindow::~MainWindow()
@@ -187,33 +187,33 @@ void MainWindow::nope()
  */
 void MainWindow::connectWidgets()
 {
-    QObject::connect(aDB,            &ADatabase::dataBaseUpdated,
+    QObject::connect(DB,             &OPL::Database::dataBaseUpdated,
                      homeWidget,     &HomeWidget::refresh);
     QObject::connect(settingsWidget, &SettingsWidget::settingChanged,
                      homeWidget,     &HomeWidget::refresh);
 
-    QObject::connect(aDB,            &ADatabase::dataBaseUpdated,
+    QObject::connect(DB,             &OPL::Database::dataBaseUpdated,
                      logbookWidget,  &LogbookWidget::refresh);
     QObject::connect(settingsWidget, &SettingsWidget::settingChanged,
                      logbookWidget,  &LogbookWidget::onLogbookWidget_viewSelectionChanged);
 
-    QObject::connect(aDB,            &ADatabase::dataBaseUpdated,
+    QObject::connect(DB,             &OPL::Database::dataBaseUpdated,
                      aircraftWidget, &AircraftWidget::onAircraftWidget_dataBaseUpdated);
     QObject::connect(settingsWidget, &SettingsWidget::settingChanged,
                      aircraftWidget, &AircraftWidget::onAircraftWidget_settingChanged);
 
-    QObject::connect(aDB, &ADatabase::dataBaseUpdated,
+    QObject::connect(DB,             &OPL::Database::dataBaseUpdated,
                      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,
+    QObject::connect(DB,              &OPL::Database::connectionReset,
                      logbookWidget,   &LogbookWidget::repopulateModel);
-    QObject::connect(aDB,             &ADatabase::connectionReset,
+    QObject::connect(DB,              &OPL::Database::connectionReset,
                      pilotsWidget,    &PilotsWidget::repopulateModel);
-    QObject::connect(aDB,             &ADatabase::connectionReset,
+    QObject::connect(DB,              &OPL::Database::connectionReset,
                      aircraftWidget,  &AircraftWidget::repopulateModel);
 }
 
@@ -240,7 +240,7 @@ void MainWindow::onDatabaseInvalid()
                                                        AStandardPaths::directory(AStandardPaths::Backup).canonicalPath(),
                                                        tr("Database file (*.db)"));
         if (!db_path.isEmpty()) {
-            if(!aDB->restoreBackup(db_path)) {
+            if(!DB->restoreBackup(db_path)) {
                WARN(tr("Unable to restore Backup file: %1").arg(db_path));
                on_actionQuit_triggered();
             } else {

+ 2 - 2
mainwindow.h

@@ -41,9 +41,9 @@
 #include "src/gui/dialogues/newpilotdialog.h"
 #include "src/gui/dialogues/newflightdialog.h"
 #include "src/classes/arunguard.h"
-#include "src/classes/acompletiondata.h"
 #include "src/testing/atimer.h"
 #include "src/classes/astyle.h"
+#include "src/database/dbcompletiondata.h"
 
 enum Style {Light, Dark};
 QT_BEGIN_NAMESPACE
@@ -140,7 +140,7 @@ private:
     DebugWidget* debugWidget;
 
     // Completion Data for QCompleters and Mapping
-    ACompletionData completionData;
+    OPL::DbCompletionData completionData;
 
     void setupToolbar();
     void setActionIcons(StyleType style = StyleType::Light);

+ 1 - 1
src/classes/aaircraftentry.h

@@ -19,7 +19,7 @@
 #define AAIRCRAFTENTRY_H
 
 #include "src/classes/aentry.h"
-#include "src/database/adatabasetypes.h"
+#include "src/database/databasetypes.h"
 
 struct AAircraftEntry : public AEntry {
 public:

+ 17 - 17
src/classes/acompletiondata.cpp

@@ -3,13 +3,13 @@
 void ACompletionData::init()
 {
     // retreive user modifiable data
-    pilotsIdMap = aDB->getIdMap(ADatabaseTarget::pilots);
-    tailsIdMap  = aDB->getIdMap(ADatabaseTarget::tails);
-    pilotList   = aDB->getCompletionList(ADatabaseTarget::pilots);
-    tailsList   = aDB->getCompletionList(ADatabaseTarget::registrations);
+    pilotsIdMap = aDB->getIdMap(DatabaseTarget::PilotNames);
+    tailsIdMap  = aDB->getIdMap(DatabaseTarget::Registrations);
+    pilotList   = aDB->getCompletionList(DatabaseTarget::PilotNames);
+    tailsList   = aDB->getCompletionList(DatabaseTarget::Registrations);
 
     // For tails, also provide completion for registration stripped of the '-' character
-    QStringList tails_list = aDB->getCompletionList(ADatabaseTarget::registrations);
+    QStringList tails_list = aDB->getCompletionList(DatabaseTarget::Registrations);
     for (auto &reg : tails_list) {
         if(reg.contains(QLatin1Char('-'))) { // check to avoid duplication if reg has no '-'
             QString copy = reg;
@@ -20,10 +20,10 @@ void ACompletionData::init()
     tailsList   = tails_list;
 
     // retreive default data
-    airportIcaoIdMap = aDB->getIdMap(ADatabaseTarget::airport_identifier_icao);
-    airportIataIdMap = aDB->getIdMap(ADatabaseTarget::airport_identifier_iata);
-    airportNameIdMap = aDB->getIdMap(ADatabaseTarget::airport_names);
-    airportList      = aDB->getCompletionList(ADatabaseTarget::airport_identifier_all);
+    airportIcaoIdMap = aDB->getIdMap(DatabaseTarget::AirportIdentifierICAO);
+    airportIataIdMap = aDB->getIdMap(DatabaseTarget::AirportIdentifierIATA);
+    airportNameIdMap = aDB->getIdMap(DatabaseTarget::AirportNames);
+    airportList      = aDB->getCompletionList(DatabaseTarget::AirportIdentifier);
 
     current_state = aDB->getUserDataState();
 }
@@ -32,10 +32,10 @@ void ACompletionData::update()
 {
     if (current_state != aDB->getUserDataState()) {
         // retreive user modifiable data
-        pilotList   = aDB->getCompletionList(ADatabaseTarget::pilots);
-        tailsList   = aDB->getCompletionList(ADatabaseTarget::registrations);
-        pilotsIdMap = aDB->getIdMap(ADatabaseTarget::pilots);
-        tailsIdMap  = aDB->getIdMap(ADatabaseTarget::tails);
+        pilotList   = aDB->getCompletionList(DatabaseTarget::PilotNames);
+        tailsList   = aDB->getCompletionList(DatabaseTarget::Registrations);
+        pilotsIdMap = aDB->getIdMap(DatabaseTarget::PilotNames);
+        tailsIdMap  = aDB->getIdMap(DatabaseTarget::Registrations);
 
         current_state = aDB->getUserDataState();
     }
@@ -43,12 +43,12 @@ void ACompletionData::update()
 
 void ACompletionData::updateTails()
 {
-    tailsIdMap  = aDB->getIdMap(ADatabaseTarget::tails);
-    tailsList   = aDB->getCompletionList(ADatabaseTarget::registrations);
+    tailsIdMap  = aDB->getIdMap(DatabaseTarget::Registrations);
+    tailsList   = aDB->getCompletionList(DatabaseTarget::Registrations);
 }
 
 void ACompletionData::updatePilots()
 {
-    pilotsIdMap  = aDB->getIdMap(ADatabaseTarget::pilots);
-    pilotList    = aDB->getCompletionList(ADatabaseTarget::pilots);
+    pilotsIdMap  = aDB->getIdMap(DatabaseTarget::PilotNames);
+    pilotList    = aDB->getCompletionList(DatabaseTarget::PilotNames);
 }

+ 6 - 6
src/classes/acompletiondata.h

@@ -1,6 +1,6 @@
 #ifndef ACOMPLETIONDATA_H
 #define ACOMPLETIONDATA_H
-#include "src/database/adatabase.h"
+#include "src/database/database.h"
 
 /*!
  * \brief The ACompletionData class provides data to QCompleters and QHashs used
@@ -25,11 +25,11 @@ public:
 
 
     // Maps for input mapping DB key - user input
-    QHash<RowId_T, QString> pilotsIdMap;
-    QHash<RowId_T, QString> tailsIdMap;
-    QHash<RowId_T, QString> airportIcaoIdMap;
-    QHash<RowId_T, QString> airportIataIdMap;
-    QHash<RowId_T, QString> airportNameIdMap;
+    QHash<int, QString> pilotsIdMap;
+    QHash<int, QString> tailsIdMap;
+    QHash<int, QString> airportIcaoIdMap;
+    QHash<int, QString> airportIataIdMap;
+    QHash<int, QString> airportNameIdMap;
     // Lists for QCompleter
     QStringList pilotList;
     QStringList tailsList;

+ 10 - 14
src/classes/ajson.cpp

@@ -16,26 +16,21 @@
  *along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 #include "ajson.h"
-#include "src/database/adatabase.h"
+#include "src/database/database.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),
-};
 
 void AJson::exportDatabase()
 {
-    for (const auto &pair : tables){
+    for (const auto &table : TABLES){
         QJsonArray array;
-        const auto rows = aDB->getTable(pair.second);
+        const auto rows = DB->getTable(table);
 
         for (const auto &row : rows)
             array.append(QJsonObject::fromVariantHash(row));
 
         QJsonDocument doc(array);
-        writeDocToFile(doc, pair.first + QLatin1String(".json"));
+        writeDocToFile(doc, OPL::GLOBALS->getDbTableName(table) + QLatin1String(".json"));
     }
 }
 
@@ -48,12 +43,13 @@ void AJson::importDatabase()
     // make sure flights is cleared first due to foreign key contstraints
     q.prepare(QStringLiteral("DELETE FROM FLIGHTS"));
     q.exec();
-    for (const auto & pair : tables) {
-        q.prepare(QLatin1String("DELETE FROM ") + pair.first);
+    for (const auto & table : TABLES) {
+        const QString table_name = OPL::GLOBALS->getDbTableName(table);
+        q.prepare(QLatin1String("DELETE FROM ") + table_name);
         q.exec();
         const auto doc = readFileToDoc(AStandardPaths::asChildOfDir(AStandardPaths::JSON,
-                                                               pair.first + QLatin1String(".json")));
-        aDB->commit(doc.array(), pair.first);
+                                                               table_name + QLatin1String(".json")));
+        DB->commit(doc.array(), table);
     }
 }
 

+ 7 - 2
src/classes/ajson.h

@@ -18,7 +18,7 @@
 #ifndef AJSON_H
 #define AJSON_H
 #include "src/opl.h"
-#include "src/database/adatabase.h"
+#include "src/database/database.h"
 #include <QJsonDocument>
 #include <QJsonValue>
 #include <QJsonObject>
@@ -62,7 +62,12 @@ private:
     /*!
      * \brief holds the tables with userdata that need to be processed.
      */
-    const static QList<QPair<TableName_T, ADatabaseTable>> tables;
+    const static inline QList<OPL::DbTable> TABLES = {
+        OPL::DbTable::Tails,
+        OPL::DbTable::Pilots,
+        OPL::DbTable::Currencies,
+        OPL::DbTable::Flights,
+    };
 
 };
 

+ 158 - 446
src/database/adatabase.cpp → src/database/database.cpp

@@ -15,62 +15,41 @@
  *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 "adatabase.h"
+#include "database.h"
 #include "src/functions/alog.h"
 #include "src/classes/astandardpaths.h"
 #include "src/opl.h"
 #include "src/functions/alog.h"
 #include "src/classes/ajson.h"
 
-const int ADatabase::minimumDatabaseRevision = 0;
+namespace OPL {
 
-const QStringList ADatabase::userTableNames = {
-    QStringLiteral("flights"),
-    QStringLiteral("pilots"),
-    QStringLiteral("tails")
-};
-const QStringList ADatabase::templateTableNames = {
-    QStringLiteral("aircraft"),
-    QStringLiteral("airports"),
-    QStringLiteral("currencies"),
-    QStringLiteral("changelog")
-};
 
-ADatabase* ADatabase::self = nullptr;
+Database* Database::self = nullptr;
 
-ADatabase::ADatabase()
+Database::Database()
     : databaseFile(QFileInfo(AStandardPaths::directory(AStandardPaths::Database).
                              absoluteFilePath(QStringLiteral("logbook.db"))))
 {}
 
-int ADatabase::dbRevision() const
-{
-    return databaseRevision;
-}
-
-int ADatabase::checkDbVersion() const
+const QString Database::version() const
 {
     QSqlQuery query(QStringLiteral("SELECT COUNT(*) FROM changelog"));
     query.next();
-    return query.value(0).toInt();
+    return QStringLiteral("OPL Database Revision: ") + QString::number(query.value(0).toInt());
 }
 
-int ADatabase::getMinimumDatabaseRevision()
+const QList<OPL::DbTable> &Database::getTemplateTables() const
 {
-    return minimumDatabaseRevision;
+    return TEMPLATE_TABLES;
 }
 
-const QStringList &ADatabase::getTemplateTableNames() const
+const QList<OPL::DbTable> &Database::getUserTables() const
 {
-    return templateTableNames;
+    return USER_TABLES;
 }
 
-const QStringList& ADatabase::getUserTableNames() const
-{
-    return userTableNames;
-}
-
-UserDataState ADatabase::getUserDataState()
+const UserDataState Database::getUserDataState() const
 {
     QSqlQuery q;
     q.prepare(QStringLiteral("SELECT COUNT (*) FROM tails"));
@@ -86,37 +65,24 @@ UserDataState ADatabase::getUserDataState()
     return UserDataState(tails, pilots);
 }
 
-bool ADatabase::resetUserData()
-{
-    QSqlQuery query;
-    for (const auto& table : userTableNames) {
-        query.prepare(QLatin1String("DELETE FROM ") + table);
-        if (!query.exec()) {
-            DEB << "Error: " << query.lastError().text();
-            return false;
-        }
-    }
-    return true;
-}
-
-const ColumnNames_T ADatabase::getTableColumns(TableName_T table_name) const
+const QStringList Database::getTableColumns(OPL::DbTable table_name) const
 {
-    return tableColumns.value(table_name);
+    return tableColumns.value(OPL::GLOBALS->getDbTableName(table_name));
 }
 
-const TableNames_T ADatabase::getTableNames() const
+const QStringList Database::getTableNames() const
 {
     return tableNames;
 }
 
-void ADatabase::updateLayout()
+void Database::updateLayout()
 {
-    auto db = ADatabase::database();
+    auto db = Database::database();
     tableNames = db.tables();
 
     tableColumns.clear();
     for (const auto &table_name : qAsConst(tableNames)) {
-        ColumnNames_T table_columns;
+        QStringList table_columns;
         QSqlRecord fields = db.record(table_name);
         for (int i = 0; i < fields.count(); i++) {
             table_columns.append(fields.field(i).name());
@@ -126,86 +92,15 @@ void ADatabase::updateLayout()
     emit dataBaseUpdated();
 }
 
-ADatabase* ADatabase::instance()
+Database* Database::instance()
 {
     if(!self)
-        self = new ADatabase();
+        self = new Database();
 
     return self;
 }
 
-bool ADatabase::createSchema()
-{
-    // Read Database layout from sql file
-    QFile f(OPL::Assets::DATABASE_SCHEMA);
-    f.open(QIODevice::ReadOnly);
-    QByteArray filedata = f.readAll();
-    // create individual queries for each table/view
-    auto list = filedata.split(';');
-
-    // Create Tables
-    QSqlQuery q;
-    QVector<QSqlError> errors;
-    for (const auto &query_string : list) {
-        q.prepare(query_string);
-        if (!q.exec()) {
-            errors.append(q.lastError());
-            LOG << "Unable to execute query: ";
-            LOG << q.lastQuery();
-            LOG << q.lastError();
-        }
-    }
-    updateLayout();
-
-    if (errors.isEmpty()) {
-        LOG << "Database succesfully created.";
-        return true;
-    } else {
-        LOG << "Database creation has failed. The following error(s) have ocurred: ";
-        for (const auto &error : qAsConst(errors)) {
-            LOG << error.type() << error.text();
-        }
-        return false;
-    }
-}
-
-bool ADatabase::importTemplateData(bool use_local_ressources)
-{
-    for (const auto& table_name : templateTableNames) {
-
-        //clear table
-        QSqlQuery q;
-        q.prepare(QLatin1String("DELETE FROM ") + table_name);
-        if (!q.exec()) {
-            LOG << "Error clearing tables: " << q.lastError().text();
-            return false;
-        }
-
-        //Prepare data
-        QJsonArray data_to_commit;
-        QString error_message("Error importing data ");
-
-        if (use_local_ressources) {
-            data_to_commit = AJson::readFileToDoc(QLatin1String(":database/templates/")
-                                      + table_name + QLatin1String(".json")).array();
-            error_message.append(QLatin1String(" (ressource) "));
-        } else {
-            data_to_commit = AJson::readFileToDoc(AStandardPaths::directory(
-                                          AStandardPaths::Templates).absoluteFilePath(
-                                          table_name + QLatin1String(".json"))).array();
-            error_message.append(QLatin1String(" (downloaded) "));
-        }
-
-        // commit Data from Array
-        if (!commit(data_to_commit, table_name)) {
-            LOG << error_message;
-            return false;
-        }
-    } // for table_name
-    return true;
-}
-
-const QString ADatabase::sqliteVersion() const
+const QString Database::sqliteVersion() const
 {
     QSqlQuery query;
     query.prepare(QStringLiteral("SELECT sqlite_version()"));
@@ -214,7 +109,7 @@ const QString ADatabase::sqliteVersion() const
     return query.value(0).toString();
 }
 
-bool ADatabase::connect()
+bool Database::connect()
 {
     if (!QSqlDatabase::isDriverAvailable(SQLITE_DRIVER)) {
         LOG << "Error: No SQLITE Driver availabe.";
@@ -238,24 +133,23 @@ bool ADatabase::connect()
     query.prepare(QStringLiteral("PRAGMA foreign_keys = ON;"));
     query.exec();
     updateLayout();
-    databaseRevision = checkDbVersion();
     return true;
 }
 
-void ADatabase::disconnect()
+void Database::disconnect()
 {
-    auto db = ADatabase::database();
+    auto db = Database::database();
     db.close();
     db.removeDatabase(db.connectionName());
     LOG << "Database connection closed.";
 }
 
-QSqlDatabase ADatabase::database()
+QSqlDatabase Database::database()
 {
     return QSqlDatabase::database(QStringLiteral("qt_sql_default_connection"));
 }
 
-//bool ADatabase::commit(const AEntry &entry)
+//bool Database::commit(const AEntry &entry)
 //{
 //    if (exists(entry)) {
 //        return update(entry);
@@ -264,7 +158,7 @@ QSqlDatabase ADatabase::database()
 //    }
 //}
 
-bool ADatabase::commit(const OPL::Row &row)
+bool Database::commit(const OPL::Row &row)
 {
     if (!row.isValid())
         return false;
@@ -275,12 +169,13 @@ bool ADatabase::commit(const OPL::Row &row)
         return insert(row);
 }
 
-bool ADatabase::commit(const QJsonArray &json_arr, const QString &table_name)
+bool Database::commit(const QJsonArray &json_arr, const OPL::DbTable table)
 {
     // create statement
+    const QString table_name = OPL::GLOBALS->getDbTableName(table);
     QString statement = QLatin1String("INSERT INTO ") + table_name + QLatin1String(" (");
     QString placeholder = QStringLiteral(") VALUES (");
-    for (const auto &column_name : aDB->getTableColumns(table_name)) {
+    for (const auto &column_name : DB->getTableColumns(table)) {
         statement += column_name + ',';
         placeholder.append(QLatin1Char(':') + column_name + QLatin1Char(','));
     }
@@ -312,7 +207,7 @@ bool ADatabase::commit(const QJsonArray &json_arr, const QString &table_name)
         return false;
 }
 
-//bool ADatabase::remove(const AEntry &entry)
+//bool Database::remove(const AEntry &entry)
 //{
 //    if (!exists(entry)) {
 //        LOG << "Error: Database entry not found.";
@@ -340,7 +235,7 @@ bool ADatabase::commit(const QJsonArray &json_arr, const QString &table_name)
 //    }
 //}
 
-bool ADatabase::remove(const OPL::Row &row)
+bool Database::remove(const OPL::Row &row)
 {
     if (!exists(row)) {
         LOG << "Error: Database entry not found.";
@@ -369,22 +264,21 @@ bool ADatabase::remove(const OPL::Row &row)
     }
 }
 
-bool ADatabase::removeMany(const QList<DataPosition> &position_list)
+bool Database::removeMany(OPL::DbTable table, const QList<int> &row_id_list)
 {
+    const QString table_name = OPL::GLOBALS->getDbTableName(table);
     int errorCount = 0;
+
     QSqlQuery query;
     query.prepare(QStringLiteral("BEGIN EXCLUSIVE TRANSACTION"));
     query.exec();
 
-    for (const auto& data_position : position_list) {
-        if (!exists(data_position)) {
-            errorCount++;
-        }
-        QString statement = QLatin1String("DELETE FROM ") + data_position.tableName +
+    for (const auto row_id : row_id_list) {
+        const QString statement = QLatin1String("DELETE FROM ") + table_name +
                 QLatin1String(" WHERE ROWID=?");
 
         query.prepare(statement);
-        query.addBindValue(data_position.rowId);
+        query.addBindValue(row_id);
 
         if (!query.exec())
             errorCount++;
@@ -412,35 +306,7 @@ bool ADatabase::removeMany(const QList<DataPosition> &position_list)
     }
 }
 
-bool ADatabase::exists(const DataPosition &data_position)
-{
-    if(data_position.rowId == 0)
-        return false;
-
-    //Check database for row id
-    QString statement = QLatin1String("SELECT COUNT(*) FROM ") + data_position.tableName
-            + QLatin1String(" WHERE ROWID=?");
-    QSqlQuery query;
-    query.prepare(statement);
-    query.addBindValue(data_position.rowId);
-    query.setForwardOnly(true);
-    query.exec();
-    //this returns either 1 or 0 since row ids are unique
-    if (!query.isActive()) {
-        lastError = query.lastError();
-        LOG << "Query Error: " << query.lastError().text() << statement;
-    }
-    query.next();
-    int rowId = query.value(0).toInt();
-    if (rowId) {
-        return true;
-    } else {
-        LOG << "No entry exists at DataPosition: " << data_position.tableName << data_position.rowId;
-        return false;
-    }
-}
-
-bool ADatabase::exists(const OPL::Row &row)
+bool Database::exists(const OPL::Row &row)
 {
     if (row.getRowId() == 0)
         return false;
@@ -469,12 +335,12 @@ bool ADatabase::exists(const OPL::Row &row)
     }
 }
 
-bool ADatabase::clear()
+bool Database::clear()
 {
     QSqlQuery q;
 
-    for (const auto &table_name : userTableNames) {
-        q.prepare(QLatin1String("DELETE FROM ") + table_name);
+    for (const auto &table : USER_TABLES) {
+        q.prepare(QLatin1String("DELETE FROM ") + OPL::GLOBALS->getDbTableName(table));
         if (!q.exec()) {
             DEB << "Error: " << q.lastError().text();
             lastError = q.lastError();
@@ -484,10 +350,11 @@ bool ADatabase::clear()
     return true;
 }
 
-bool ADatabase::update(const OPL::Row &updated_row)
+bool Database::update(const OPL::Row &updated_row)
 {
     QString statement = QLatin1String("UPDATE ") + OPL::GLOBALS->getDbTableName(updated_row.getTableName()) + QLatin1String(" SET ");
-    for (auto i = updated_row.getData().constBegin(); i != updated_row.getData().constEnd(); ++i) {
+    const auto& data = updated_row.getData();
+    for (auto i = data.constBegin(); i != data.constEnd(); ++i) {
         statement.append(i.key() + "=?,");
     }
     statement.chop(1);
@@ -495,7 +362,7 @@ bool ADatabase::update(const OPL::Row &updated_row)
     QSqlQuery query;
     query.prepare(statement);
     DEB << "Statement: " << statement;
-    for (auto i = updated_row.getData().constBegin(); i != updated_row.getData().constEnd(); ++i) {
+    for (auto i = data.constBegin(); i != data.constEnd(); ++i) {
         if (i.value() == QVariant(QString()) || i.value() == 0) {
             query.addBindValue(QVariant(QVariant::String));
         } else {
@@ -519,11 +386,12 @@ bool ADatabase::update(const OPL::Row &updated_row)
     }
 }
 
-bool ADatabase::insert(const OPL::Row &new_row)
+bool Database::insert(const OPL::Row &new_row)
 {
     QString statement = QLatin1String("INSERT INTO ") + OPL::GLOBALS->getDbTableName(new_row.getTableName()) + QLatin1String(" (");
+    const auto& data = new_row.getData();
     QHash<QString, QVariant>::const_iterator i;
-    for (i = new_row.getData().constBegin(); i != new_row.getData().constEnd(); ++i) {
+    for (i = data.constBegin(); i != data.constEnd(); ++i) {
         statement.append(i.key() + QLatin1Char(','));
     }
     statement.chop(1);
@@ -538,7 +406,7 @@ bool ADatabase::insert(const OPL::Row &new_row)
     QSqlQuery query;
     query.prepare(statement);
 
-    for (i = new_row.getData().constBegin(); i != new_row.getData().constEnd(); ++i) {
+    for (i = data.constBegin(); i != data.constEnd(); ++i) {
         if (i.value() == QVariant(QString()) || i.value() == 0) {
             query.addBindValue(QVariant(QVariant::String));
         } else {
@@ -561,64 +429,7 @@ bool ADatabase::insert(const OPL::Row &new_row)
     }
 }
 
-RowData_T ADatabase::getEntryData(const DataPosition &data_position)
-{
-    // check table exists
-    if (!getTableNames().contains(data_position.tableName)) {
-        DEB << data_position.tableName << " not a table in the database. Unable to retreive Entry data.";
-        return RowData_T();
-    }
-
-    //Check Database for rowId
-    QString statement = QLatin1String("SELECT COUNT(*) FROM ") + data_position.tableName
-                      + QLatin1String(" WHERE ROWID=?");
-    QSqlQuery check_query;
-    check_query.prepare(statement);
-    check_query.addBindValue(data_position.rowId);
-    check_query.setForwardOnly(true);
-
-    if (!check_query.exec()) {
-        DEB << "SQL error: " << check_query.lastError().text();
-        DEB << "Statement: " << statement;
-        lastError = check_query.lastError();
-        return RowData_T();
-    }
-    check_query.next();
-    if (check_query.value(0).toInt() == 0) {
-        LOG << "No Entry found for row id: " << data_position.rowId;
-        return RowData_T();
-    }
-
-    // Retreive TableData
-    statement = QLatin1String("SELECT * FROM ") + data_position.tableName
-              + QLatin1String(" WHERE ROWID=?");
-
-    QSqlQuery select_query;
-    select_query.prepare(statement);
-    select_query.addBindValue(data_position.rowId);
-    select_query.setForwardOnly(true);
-
-
-    if (!select_query.exec()) {
-        DEB << "SQL error: " << select_query.lastError().text();
-        DEB << "Statement: " << select_query.lastQuery();
-        lastError = select_query.lastError();
-        return {};
-    }
-
-    RowData_T entry_data;
-    if(select_query.next()) { // retreive records
-        auto r = select_query.record();
-        for (int i = 0; i < r.count(); i++){
-            if(!r.value(i).isNull()) {
-                entry_data.insert(r.fieldName(i), r.value(i));
-            }
-        }
-    }
-    return entry_data;
-}
-
-OPL::Row ADatabase::getRow(const OPL::DbTable table, const int row_id)
+OPL::Row Database::getRow(const OPL::DbTable table, const int row_id)
 {
     QString statement = QLatin1String("SELECT * FROM ") + OPL::GLOBALS->getDbTableName(table)
             + QLatin1String(" WHERE ROWID=?");
@@ -650,7 +461,7 @@ OPL::Row ADatabase::getRow(const OPL::DbTable table, const int row_id)
     return OPL::Row(table, row_id, entry_data);
 }
 
-RowData_T ADatabase::getRowData(const OPL::DbTable table, const int row_id)
+RowData_T Database::getRowData(const OPL::DbTable table, const int row_id)
 {
     QString statement = QLatin1String("SELECT * FROM ") + OPL::GLOBALS->getDbTableName(table)
             + QLatin1String(" WHERE ROWID=?");
@@ -682,120 +493,10 @@ RowData_T ADatabase::getRowData(const OPL::DbTable table, const int row_id)
     return entry_data;
 }
 
-const QStringList ADatabase::getCompletionList(ADatabaseTarget target)
-{
-    QString statement;
-
-    switch (target) {
-    case ADatabaseTarget::pilots:
-        statement.append(QStringLiteral("SELECT lastname||', '||firstname FROM pilots"));
-        break;
-    case ADatabaseTarget::aircraft:
-        statement.append(QStringLiteral("SELECT make||' '||model FROM aircraft WHERE model IS NOT NULL AND variant IS NULL "
-                         "UNION "
-                         "SELECT make||' '||model||'-'||variant FROM aircraft WHERE variant IS NOT NULL"));
-        break;
-    case ADatabaseTarget::airport_identifier_all:
-        statement.append(QStringLiteral("SELECT icao FROM airports UNION SELECT iata FROM airports"));
-        break;
-    case ADatabaseTarget::registrations:
-        statement.append(QStringLiteral("SELECT registration FROM tails"));
-        break;
-    case ADatabaseTarget::companies:
-        statement.append(QStringLiteral("SELECT company FROM pilots"));
-        break;
-    default:
-        DEB << "Not a valid completer target for this function.";
-        return QStringList();
-    }
-
-    QSqlQuery query;
-    query.prepare(statement);
-    query.setForwardOnly(true);
-    query.exec();
-
-    if(!query.isActive()) {
-        lastError = query.lastError();
-        return QStringList();
-    }
-
-    QStringList completer_list;
-    while (query.next())
-        completer_list.append(query.value(0).toString());
-
-    completer_list.sort();
-    completer_list.removeAll(QString());
-    completer_list.removeDuplicates();
-
-    return completer_list;
-}
-
-const QHash<RowId_T, QString> ADatabase::getIdMap(ADatabaseTarget target)
+int Database::getLastEntry(OPL::DbTable table)
 {
-    QString statement;
-
-    switch (target) {
-    case ADatabaseTarget::pilots:
-        statement.append(QStringLiteral("SELECT ROWID, lastname||', '||firstname FROM pilots"));
-        break;
-    case ADatabaseTarget::aircraft:
-        statement.append(QStringLiteral("SELECT ROWID, make||' '||model FROM aircraft WHERE model IS NOT NULL AND variant IS NULL "
-                         "UNION "
-                         "SELECT ROWID, make||' '||model||'-'||variant FROM aircraft WHERE variant IS NOT NULL"));
-        break;
-    case ADatabaseTarget::airport_identifier_icao:
-        statement.append(QStringLiteral("SELECT ROWID, icao FROM airports"));
-        break;
-    case ADatabaseTarget::airport_identifier_iata:
-        statement.append(QStringLiteral("SELECT ROWID, iata FROM airports WHERE iata NOT NULL"));
-        break;
-    case ADatabaseTarget::airport_names:
-        statement.append(QStringLiteral("SELECT ROWID, name FROM airports"));
-        break;
-    case ADatabaseTarget::tails:
-        statement.append(QStringLiteral("SELECT ROWID, registration FROM tails"));
-        break;
-    default:
-        DEB << "Not a valid completer target for this function.";
-        return {};
-    }
-
-    QSqlQuery query;
-    query.setForwardOnly(true);
-    query.prepare(statement);
-    query.exec();
-    //auto query = QSqlQuery(statement);
-    if (!query.isActive()) {
-        DEB << "No result found. Check Query and Error.";
-        DEB << "Query: " << statement;
-        DEB << "Error: " << query.lastError().text();
-        lastError = query.lastError();
-        return {};
-    }
-    auto id_map = QHash<RowId_T, QString>();
-    while (query.next())
-        id_map.insert(query.value(0).toInt(), query.value(1).toString());
-    return id_map;
-}
+    QString statement = QLatin1String("SELECT MAX(ROWID) FROM ") + OPL::GLOBALS->getDbTableName(table);
 
-RowId_T ADatabase::getLastEntry(ADatabaseTable table)
-{
-    QString statement = QLatin1String("SELECT MAX(ROWID) FROM ");
-
-    switch (table) {
-    case ADatabaseTable::pilots:
-        statement.append(OPL::Db::TABLE_PILOTS);
-        break;
-    case ADatabaseTable::aircraft:
-        statement.append(OPL::Db::TABLE_AIRCRAFT);
-        break;
-    case ADatabaseTable::tails:
-        statement.append(OPL::Db::TABLE_TAILS);
-        break;
-    default:
-        DEB << "Not a valid completer target for this function.";
-        return 0;
-    }
     auto query = QSqlQuery(statement);
     if (query.first()) {
         return query.value(0).toInt();
@@ -805,15 +506,15 @@ RowId_T ADatabase::getLastEntry(ADatabaseTable table)
     }
 }
 
-QList<RowId_T> ADatabase::getForeignKeyConstraints(RowId_T foreign_row_id, ADatabaseTable target)
+QList<int> Database::getForeignKeyConstraints(int foreign_row_id, OPL::DbTable table)
 {
     QString statement = QLatin1String("SELECT ROWID FROM flights WHERE ");
 
-    switch (target) {
-    case ADatabaseTable::pilots:
+    switch (table) {
+    case OPL::DbTable::Pilots:
         statement.append(QLatin1String("pic=?"));
         break;
-    case ADatabaseTable::tails:
+    case OPL::DbTable::Tails:
         statement.append(QLatin1String("acft=?"));
         break;
     default:
@@ -842,7 +543,7 @@ QList<RowId_T> ADatabase::getForeignKeyConstraints(RowId_T foreign_row_id, AData
     return row_ids;
 }
 
-QVector<QVariant> ADatabase::customQuery(QString statement, int return_values)
+QVector<QVariant> Database::customQuery(QString statement, int return_values)
 {
     QSqlQuery query(statement);
     if(!query.exec()) {
@@ -870,89 +571,14 @@ QVector<QVariant> ADatabase::customQuery(QString statement, int return_values)
     }
 }
 
-QMap<ADatabaseSummaryKey, QString> ADatabase::databaseSummary(const QString &db_path)
-{
-    const QString connection_name = QStringLiteral("summary_connection");
-    QMap<ADatabaseSummaryKey, QString> return_values;
-    { // scope for a temporary database connection, ensures proper cleanup when removeDatabase() is called.
-        //DEB << "Adding temporary connection to database:" << db_path;
-        QSqlDatabase temp_database = QSqlDatabase::addDatabase(SQLITE_DRIVER, connection_name); // Don't use default connection
-        temp_database.setDatabaseName(db_path);
-        if (!temp_database.open())
-            return {};
-
-        QSqlQuery query(temp_database); // Query object using the temporary connection
-        ADatabaseSummaryKey key;  // Used among the queries for verbosity... and sanity
-
-        const QVector<QPair<ADatabaseSummaryKey, QString>> key_table_pairs = {
-            {ADatabaseSummaryKey::total_flights, QStringLiteral("flights")},
-            {ADatabaseSummaryKey::total_tails, QStringLiteral("tails")},
-            {ADatabaseSummaryKey::total_pilots, QStringLiteral("pilots")}
-        };
-        // retreive amount of flights, tails and pilots
-        for (const auto & pair : key_table_pairs) {
-            query.prepare(QLatin1String("SELECT COUNT (*) FROM ") + pair.second);
-            query.exec();
-            key = pair.first;
-            if (query.first()){
-                return_values[key] = query.value(0).toString();
-            }
-            else{
-                return_values[key] = QString();
-            }
-        }
-        // retreive date of last flight
-        query.prepare(QStringLiteral("SELECT MAX(doft) FROM flights"));
-        query.exec();
-        key = ADatabaseSummaryKey::last_flight;
-        if (query.first()){
-            return_values[key] = query.value(0).toString();
-        }
-        else {
-            return_values[key] = QString();
-        }
-        // retreive total flight time as a string "hh:mm"
-        query.prepare(QStringLiteral("SELECT "
-                                     "printf(\"%02d\",CAST(SUM(tblk) AS INT)/60)"
-                                     "||':'||"
-                                     "printf(\"%02d\",CAST(SUM(tblk) AS INT)%60) FROM flights"));
-        key = ADatabaseSummaryKey::total_time;
-        query.exec();
-        if (query.first()){
-            return_values[key] = query.value(0).toString();
-        }
-        else {
-            return_values[key] = QString();
-        }
-    }
-
-    QSqlDatabase::removeDatabase(connection_name); // cleanly removes temp connection without leaks since query+db are out of scope
-
-    return return_values;
-}
-
-const QString ADatabase::databaseSummaryString(const QString &db_path)
-{
-    auto summary_map = databaseSummary(db_path);
-    QString out = QLatin1String("<table>");
-    out.append(tr("<tr><td>Total Time: </td><td>%1</td>").arg(summary_map[ADatabaseSummaryKey::total_time]));
-    out.append(tr("<tr><td>Last Flight: </td><td>%1</td>").arg(summary_map[ADatabaseSummaryKey::last_flight]));
-    out.append(tr("<tr><td>Number of flights: </td><td>%1</td>").arg(summary_map[ADatabaseSummaryKey::total_flights]));
-    out.append(tr("<tr><td>Number of aircraft: </td><td>%1</td>").arg(summary_map[ADatabaseSummaryKey::total_tails]));
-    out.append(tr("<tr><td>Number of Pilots: </td><td>%1</td>").arg(summary_map[ADatabaseSummaryKey::total_pilots]));
-    out.append("</table>");
-
-    return out;
-}
-
 /*!
- * \brief ADatabase::createBackup copies the currently used database to an external backup location provided by the user
+ * \brief Database::createBackup copies the currently used database to an external backup location provided by the user
  * \param dest_file This is the full path and filename of where the backup will be created, e.g. 'home/Sully/myBackups/backupFromOpl.db'
  */
-bool ADatabase::createBackup(const QString& dest_file)
+bool Database::createBackup(const QString& dest_file)
 {
     LOG << "Backing up current database to: " << dest_file;
-    ADatabase::disconnect();
+    Database::disconnect();
     QFile db_file(databaseFile.absoluteFilePath());
     //DEB << "File to Overwrite:" << db_file;
 
@@ -962,25 +588,25 @@ bool ADatabase::createBackup(const QString& dest_file)
     }
 
     LOG << "Backed up old database as:" << dest_file;
-    ADatabase::connect();
+    Database::connect();
     emit connectionReset();
     return true;
 }
 
-QVector<RowData_T> ADatabase::getTable(ADatabaseTable table_name)
+QVector<RowData_T> Database::getTable(OPL::DbTable table)
 {
     auto query_str = QStringLiteral("SELECT * FROM ");
-    switch (table_name) {
-    case ADatabaseTable::pilots:
+    switch (table) {
+    case OPL::DbTable::Pilots:
         query_str.append(OPL::Db::TABLE_PILOTS);
         break;
-    case ADatabaseTable::tails:
+    case OPL::DbTable::Tails:
         query_str.append(OPL::Db::TABLE_TAILS);
         break;
-    case ADatabaseTable::flights:
+    case OPL::DbTable::Flights:
         query_str.append(OPL::Db::TABLE_FLIGHTS);
         break;
-    case ADatabaseTable::currencies:
+    case OPL::DbTable::Currencies:
         query_str.append(OPL::Db::TABLE_CURRENCIES);
     default:
         break;
@@ -1013,16 +639,16 @@ QVector<RowData_T> ADatabase::getTable(ADatabaseTable table_name)
 }
 
 /*!
- * \brief ADatabase::restoreBackup restores the database from a given backup file and replaces the currently active database.
+ * \brief Database::restoreBackup restores the database from a given backup file and replaces the currently active database.
  * \param backup_file This is the full path and filename of the backup, e.g. 'home/Sully/myBackups/backupFromOpl.db'
  */
-bool ADatabase::restoreBackup(const QString& backup_file)
+bool Database::restoreBackup(const QString& backup_file)
 {
     LOG << "Restoring backup from file:" << backup_file;
 
     QString default_loc = databaseFile.absoluteFilePath();
 
-    ADatabase::disconnect();
+    Database::disconnect();
     QFile backup(backup_file);
     QFile current_db(default_loc);
 
@@ -1042,8 +668,94 @@ bool ADatabase::restoreBackup(const QString& backup_file)
     // backup has been restored, clean up the previously moved file
     current_db.remove();
     LOG << "Backup successfully restored!";
-    ADatabase::connect();
+    Database::connect();
     emit connectionReset();
     return true;
 }
 
+bool Database::createSchema()
+{
+    // Read Database layout from sql file
+    QFile f(OPL::Assets::DATABASE_SCHEMA);
+    f.open(QIODevice::ReadOnly);
+    QByteArray filedata = f.readAll();
+    // create individual queries for each table/view
+    auto list = filedata.split(';');
+
+    // Create Tables
+    QSqlQuery q;
+    QVector<QSqlError> errors;
+    for (const auto &query_string : list) {
+        q.prepare(query_string);
+        if (!q.exec()) {
+            errors.append(q.lastError());
+            LOG << "Unable to execute query: ";
+            LOG << q.lastQuery();
+            LOG << q.lastError();
+        }
+    }
+    DB->updateLayout();
+
+    if (errors.isEmpty()) {
+        LOG << "Database succesfully created.";
+        return true;
+    } else {
+        LOG << "Database creation has failed. The following error(s) have ocurred: ";
+        for (const auto &error : qAsConst(errors)) {
+            LOG << error.type() << error.text();
+        }
+        return false;
+    }
+}
+
+bool Database::importTemplateData(bool use_local_ressources)
+{
+    for (const auto& table : DB->getTemplateTables()) {
+        const QString table_name = OPL::GLOBALS->getDbTableName(table);
+
+        //clear table
+        QSqlQuery q;
+        q.prepare(QLatin1String("DELETE FROM ") + table_name);
+        if (!q.exec()) {
+            LOG << "Error clearing tables: " << q.lastError().text();
+            return false;
+        }
+
+        //Prepare data
+        QJsonArray data_to_commit;
+        QString error_message("Error importing data ");
+
+        if (use_local_ressources) {
+            data_to_commit = AJson::readFileToDoc(QLatin1String(":database/templates/")
+                                      + table_name + QLatin1String(".json")).array();
+            error_message.append(QLatin1String(" (ressource) "));
+        } else {
+            data_to_commit = AJson::readFileToDoc(AStandardPaths::directory(
+                                          AStandardPaths::Templates).absoluteFilePath(
+                                          table_name + QLatin1String(".json"))).array();
+            error_message.append(QLatin1String(" (downloaded) "));
+        }
+
+        // commit Data from Array
+        if (!DB->commit(data_to_commit, table)) {
+            LOG << error_message;
+            return false;
+        }
+    } // for table_name
+    return true;
+}
+
+bool Database::resetUserData()
+{
+    QSqlQuery query;
+    for (const auto& table : DB->getUserTables()) {
+        query.prepare(QLatin1String("DELETE FROM ") + OPL::GLOBALS->getDbTableName(table));
+        if (!query.exec()) {
+            DEB << "Error: " << query.lastError().text();
+            return false;
+        }
+    }
+    return true;
+}
+
+} // namespace OPL

+ 85 - 171
src/database/adatabase.h → src/database/database.h

@@ -15,8 +15,8 @@
  *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 ADATABASE_H
-#define ADATABASE_H
+#ifndef DATABASE_H
+#define DATABASE_H
 
 #include <QPair>
 #include <QHash>
@@ -31,67 +31,22 @@
 #include <QSqlRecord>
 #include <QSqlField>
 
-#include "src/database/adatabasetypes.h"
-#include "src/classes/row.h"
-
+#include "src/opl.h"
+#include "src/database/row.h"
 #include "src/classes/astandardpaths.h"
 
-#define SQLITE_DRIVER QStringLiteral("QSQLITE")
+using RowData_T = QHash<QString, QVariant>;
+
+namespace OPL {
 
 /*!
  * \brief Convenience macro that returns instance of DataBase.
  * Instead of this:
  * DataBase::getInstance().commit(...)
  * Write this:
- * aDB->commit(...)
- */
-#define aDB ADatabase::instance()
-
-/*!
- * \brief The DBTarget enum lists database items that are
- * used by completers, for content matching or need to be accessed programatically.
- */
-enum class ADatabaseTarget
-{
-    airport_identifier_icao,
-    airport_identifier_iata,
-    airport_identifier_all,
-    airport_names,
-    registrations,
-    companies,
-    tails,
-    pilots,
-    aircraft
-};
-
-/*!
- * \brief enumarates the tables in the database
+ * DB->commit(...)
  */
-enum class ADatabaseTable
-{
-    // user tables
-    tails = 0,
-    pilots = 1,
-    flights = 2,
-    simulators = 3,
-    currencies = 4,
-
-    // template tables
-    aircraft = 4,
-    airports = 5,
-    changelog = 7,
-};
-
-/*!
- * \brief Enumerates the QHash keys used when summarising a database
- */
-enum class ADatabaseSummaryKey {
-    total_flights,
-    total_tails,
-    total_pilots,
-    last_flight,
-    total_time,
-};
+#define DB OPL::Database::instance()
 
 /*!
  * \brief The UserDateState struct caches the current number of entries in relevant database tables
@@ -118,45 +73,50 @@ struct UserDataState {
     int numPilots;
 };
 
-/*!
- * \brief Custom Database Error derived from QSqlError.
- * Extends text() adding "Database Error: " before the text.
- * Errors that are related to SQL are assigned their respective error codes.
- * Errors that occur with data in the database are handled with the error code "opl"
- * and QSqlError::UnknownError
- */
-class ADatabaseError : public QSqlError {
-public:
-    ADatabaseError() = default;
-    ADatabaseError(QString msg);
-    QString text() const;
-    ADatabaseError(QSqlError);
-};
+
 
 /*!
  * \brief The DB class encapsulates the SQL database by providing fast access
  * to hot database data.
  */
-class ADatabase : public QObject {
+class Database : public QObject {
 
 private:
     Q_OBJECT
-    static ADatabase* self;
-    TableNames_T tableNames;
-    TableColumns_T tableColumns;
-    int databaseRevision;
-
-    ADatabase();
-    int checkDbVersion() const;
+    Database();
+    static Database* self;
+    QStringList tableNames;
+    QHash<QString, QStringList> tableColumns;
+
+    inline const static QString SQLITE_DRIVER  = QStringLiteral("QSQLITE");
+    inline const static QList<OPL::DbTable> USER_TABLES = {
+        OPL::DbTable::Flights,
+        OPL::DbTable::Pilots,
+        OPL::DbTable::Tails
+    };
+    inline const static QList<OPL::DbTable> TEMPLATE_TABLES = {
+        OPL::DbTable::Aircraft,
+        OPL::DbTable::Airports,
+        OPL::DbTable::Currencies,
+        OPL::DbTable::Changelog
+    };
 
-    const static QStringList userTableNames;
-    const static QStringList templateTableNames;
-    const static int minimumDatabaseRevision;
 
 public:
-    ADatabase(const ADatabase&) = delete;
-    void operator=(const ADatabase&) = delete;
-    static ADatabase* instance();
+    Database(const Database&) = delete;
+    void operator=(const Database&) = delete;
+    static Database* instance();
+
+    /*!
+     * \brief Return the database revision number (not the sqlite version number).
+     */
+    const QString version() const;
+
+    /*!
+     * \brief Database::sqliteVersion returns the database sqlite version. See also dbRevision()
+     * \return sqlite version string
+     */
+    const QString sqliteVersion() const;
 
     /*!
      * \brief Holds information about the last error that ocurred during
@@ -170,41 +130,15 @@ public:
 
     const QFileInfo databaseFile;
 
-
-
-    /*!
-     * \brief Create or restore the database to its ready-to-use but empty state
-     * \details The SQL code for the database creation is stored in a .sql file which is available as a ressource.
-     * This file gets read, and the querys executed. If errors occur, returns false.
-     */
-    bool createSchema();
-
-    /*!
-     * \brief importTemplateData fills an empty database with the template
-     * data (Aircraft, Airports, currencies, changelog) as read from the JSON
-     * templates.
-     * \param use_local_ressources determines whether the included ressource files
-     * or a previously downloaded file should be used.
-     * \return
-     */
-    bool importTemplateData(bool use_local_ressources = true);
-
-    /*!
-     * \brief dbRevision returns the database Revision Number. The Revision refers to what iteration
-     * of the database layout is used. For the sqlite version of the database refer to sqliteVersion()
-     * \return
-     */
-    int dbRevision() const;
-
     /*!
      * \brief Return the names of all tables in the database
      */
-    const TableNames_T getTableNames() const;
+    const QStringList getTableNames() const;
 
     /*!
      * \brief Return the names of a given table in the database.
      */
-    const ColumnNames_T getTableColumns(TableName_T table_name) const;
+    const QStringList getTableColumns(OPL::DbTable table_name) const;
 
     /*!
      * \brief Updates the member variables tableNames and tableColumns with up-to-date layout information
@@ -212,11 +146,7 @@ public:
      */
     void updateLayout();
 
-    /*!
-     * \brief ADatabase::sqliteVersion returns the database sqlite version. See also dbRevision()
-     * \return sqlite version string
-     */
-    const QString sqliteVersion() const;
+
 
     /*!
      * \brief Connect to the database and populate database information.
@@ -245,7 +175,6 @@ public:
      * \brief Checks if an entry exists in the database, based on position data
      */
     bool exists(const OPL::Row &row);
-    bool exists(const DataPosition &position);
 
     /*!
      * \brief clear resets the database, i.e. deletes all content in the tables containing
@@ -264,7 +193,7 @@ public:
      * \details This function is used to import values to the databases which are held in JSON documents.
      * These entries are pre-filled data used for providing completion data, such as Airport or Aircraft Type Data.
      */
-    bool commit(const QJsonArray &json_arr, const QString &table_name);
+    bool commit(const QJsonArray &json_arr, const OPL::DbTable table);
 
     /*!
      * \brief Create new entry in the databse based on UserInput
@@ -288,15 +217,10 @@ public:
     bool remove(const OPL::Row &row);
 
     /*!
-     * \brief deletes a list of entries from the database. Optimised for speed when
-     * deleting many entries.
+     * \brief deletes a batch of entries from the database. Optimised for speed when
+     * deleting many entries. The entries are identified using their row id
      */
-    bool removeMany(const QList<DataPosition> &position_list);
-
-    /*!
-     * \brief retreive entry data from the database to create an entry object
-     */
-    RowData_T getEntryData(const DataPosition &data_position);
+    bool removeMany(OPL::DbTable table, const QList<int> &row_id_list);
 
     /*!
      * \brief retreive a Row from the database
@@ -316,7 +240,7 @@ public:
      * instead of an Entry. It allows for easy access to a pilot entry
      * with only the RowId required as input.
      */
-    inline OPL::PilotEntry getPilotEntry(RowId_T row_id)
+    inline OPL::PilotEntry getPilotEntry(int row_id)
     {
         const auto data = getRowData(OPL::DbTable::Pilots, row_id);
         return OPL::PilotEntry(row_id, data);
@@ -330,7 +254,7 @@ public:
      * instead of an Entry. It allows for easy access to a tail entry
      * with only the RowId required as input.
      */
-    inline OPL::TailEntry getTailEntry(RowId_T row_id)
+    inline OPL::TailEntry getTailEntry(int row_id)
     {
         const auto data = getRowData(OPL::DbTable::Tails, row_id);
         return OPL::TailEntry(row_id, data);
@@ -344,7 +268,7 @@ public:
      * instead of an AEntry. It allows for easy access to an aircraft entry
      * with only the RowId required as input.
      */
-    inline OPL::AircraftEntry getAircraftEntry(RowId_T row_id)
+    inline OPL::AircraftEntry getAircraftEntry(int row_id)
     {
         const auto data = getRowData(OPL::DbTable::Aircraft, row_id);
         return OPL::AircraftEntry(row_id, data);
@@ -358,7 +282,7 @@ public:
      * instead of an AEntry. It allows for easy access to a flight entry
      * with only the RowId required as input.
      */
-    inline OPL::FlightEntry getFlightEntry(RowId_T row_id)
+    inline OPL::FlightEntry getFlightEntry(int row_id)
     {
         const auto data = getRowData(OPL::DbTable::Flights, row_id);
         return OPL::FlightEntry(row_id, data);
@@ -372,7 +296,7 @@ public:
      * instead of an AEntry. It allows for easy access to a Simulator entry
      * with only the RowId required as input.
      */
-    inline OPL::SimulatorEntry getSimEntry(RowId_T row_id)
+    inline OPL::SimulatorEntry getSimEntry(int row_id)
     {
         const auto data = getRowData(OPL::DbTable::Simulators, row_id);
         return OPL::SimulatorEntry(row_id, data);
@@ -381,49 +305,22 @@ public:
     /*!
      * \brief Retreives a currency entry from the database.
      */
-    inline OPL::CurrencyEntry getCurrencyEntry(RowId_T row_id)
+    inline OPL::CurrencyEntry getCurrencyEntry(int row_id)
     {
         const auto data = getRowData(OPL::DbTable::Currencies, row_id);
         return OPL::CurrencyEntry(row_id, data);
     }
 
-    /*!
-     * \brief getCompletionList returns a QStringList of values for a
-     * QCompleter based on database values
-     */
-    const QStringList getCompletionList(ADatabaseTarget target);
-
-    /*!
-     * \brief returns a QHash of a human-readable database value and
-     * its row id. Used in the Dialogs to map user input to unique database entries.
-     */
-    const QHash<RowId_T, QString> getIdMap(ADatabaseTarget target);
-
     /*!
      * \brief returns the ROWID for the newest entry in the respective database.
      */
-    RowId_T getLastEntry(ADatabaseTable table);
+    int getLastEntry(OPL::DbTable table);
 
     /*!
      * \brief returns a list of ROWID's in the flights table for which foreign key constraints
      * exist.
      */
-    QList<RowId_T> getForeignKeyConstraints(RowId_T foreign_row_id, ADatabaseTable target);
-
-    /*!
-     * \brief Return a summary of a database
-     * \details Creates a summary of the database giving a quick overview of the relevant contents. The
-     * function runs several specialised SQL queries to create a QHash<ADatabaseSummaryKey, QString> containing
-     * Total Flight Time, Number of unique aircraft and pilots, as well as the date of last flight. Uses a temporary
-     * database connection separate from the default connection in order to not tamper with the currently active
-     * database connection.
-     */
-    QMap<ADatabaseSummaryKey, QString> databaseSummary(const QString& db_path);
-
-    /*!
-     * \brief returns a short summary string of the database, containing total time and date of last flight.
-     */
-    const QString databaseSummaryString(const QString& db_path);
+    QList<int> getForeignKeyConstraints(int foreign_row_id, OPL::DbTable table);
 
     bool restoreBackup(const QString& backup_file);
     bool createBackup(const QString& dest_file);
@@ -432,36 +329,51 @@ public:
      * \brief getTable returns all contents of a given table from the database
      * \return
      */
-    QVector<RowData_T> getTable(ADatabaseTable table_name);
+    QVector<RowData_T> getTable(OPL::DbTable table);
 
     /*!
-     * \brief getUserTableNames returns a list of the table names of tables that contain user-created data
+     * \brief getUserTables returns a list of the of the tables that contain user-created data
      * (flights, pilots,..)
      */
-    const QStringList &getUserTableNames() const;
+    const QList<OPL::DbTable> &getUserTables() const;
 
     /*!
-     * \brief getTemplateTableNames returns a list of the table names of tables that contain template data
+     * \brief getTemplateTables returns a list of the tables that contain template data
      * (aiports, aircraft,..)
      */
-    const QStringList &getTemplateTableNames() const;
+    const QList<OPL::DbTable> &getTemplateTables() const;
 
     /*!
      * \brief getUserDataState returns a struct containing the current amount of entries in the tails and
      * pilots tables.
      * \return
      */
-    UserDataState getUserDataState();
+    const UserDataState getUserDataState() const;
+
+    // Maintenance and setup
 
     /*!
-     * \brief Delete all rows from the user data tables (flights, pliots, tails)
+     * \brief Create or restore the database to its ready-to-use but empty state
+     * \details The SQL code for the database creation is stored in a .sql file which is available as a ressource.
+     * This file gets read, and the querys executed. If errors occur, returns false.
      */
-    bool resetUserData();
+    bool createSchema();
+    /*!
+     * \brief importTemplateData fills an empty database with the template
+     * data (Aircraft, Airports, currencies, changelog) as read from the JSON
+     * templates.
+     * \param use_local_ressources determines whether the included ressource files
+     * or a previously downloaded file should be used.
+     * \return
+     */
+    bool importTemplateData(bool use_local_ressources);
 
     /*!
-     * \brief getMinimumDatabaseRevision returns the minimum required database revision number required by the application.
+     * \brief Delete all rows from the user data tables (flights, pliots, tails)
      */
-    static int getMinimumDatabaseRevision();
+    bool resetUserData();
+
+
 
 signals:
     /*!
@@ -478,4 +390,6 @@ signals:
     void connectionReset();
 };
 
-#endif // ADATABASE_H
+} // namespace OPL
+
+#endif // DATABASE_H

+ 141 - 0
src/database/dbcompletiondata.cpp

@@ -0,0 +1,141 @@
+#include "dbcompletiondata.h"
+
+namespace OPL {
+
+void DbCompletionData::init()
+{
+    // retreive user modifiable data
+    pilotsIdMap = getIdMap(CompleterTarget::PilotNames);
+    tailsIdMap  = getIdMap(CompleterTarget::Registrations);
+    pilotList   = getCompletionList(CompleterTarget::PilotNames);
+    tailsList   = getCompletionList(CompleterTarget::Registrations);
+
+    // For tails, also provide completion for registration stripped of the '-' character
+    QStringList tails_list = getCompletionList(CompleterTarget::Registrations);
+    for (auto &reg : tails_list) {
+        if(reg.contains(QLatin1Char('-'))) { // check to avoid duplication if reg has no '-'
+            QString copy = reg;
+            reg.remove(QLatin1Char('-'));
+            reg = copy + " (" + reg + QLatin1Char(')');
+        }
+    }
+    tailsList   = tails_list;
+
+    // retreive default data
+    airportIcaoIdMap = getIdMap(CompleterTarget::AirportIdentifierICAO);
+    airportIataIdMap = getIdMap(CompleterTarget::AirportIdentifierIATA);
+    airportNameIdMap = getIdMap(CompleterTarget::AirportNames);
+    airportList      = getCompletionList(CompleterTarget::AirportIdentifier);
+
+    current_state = DB->getUserDataState();
+}
+
+void DbCompletionData::update()
+{
+    if (current_state != DB->getUserDataState()) {
+        // retreive user modifiable data
+        pilotList   = getCompletionList(CompleterTarget::PilotNames);
+        tailsList   = getCompletionList(CompleterTarget::Registrations);
+        pilotsIdMap = getIdMap(CompleterTarget::PilotNames);
+        tailsIdMap  = getIdMap(CompleterTarget::Registrations);
+
+        current_state = DB->getUserDataState();
+    }
+}
+
+void DbCompletionData::updateTails()
+{
+    tailsIdMap  = getIdMap(CompleterTarget::Registrations);
+    tailsList   = getCompletionList(CompleterTarget::Registrations);
+}
+
+void DbCompletionData::updatePilots()
+{
+    pilotsIdMap  = getIdMap(CompleterTarget::PilotNames);
+    pilotList    = getCompletionList(CompleterTarget::PilotNames);
+}
+
+const QStringList DbCompletionData::getCompletionList(CompleterTarget target)
+{
+    QString statement;
+
+    switch (target) {
+    case CompleterTarget::PilotNames:
+        statement.append(QStringLiteral("SELECT lastname||', '||firstname FROM pilots"));
+        break;
+    case CompleterTarget::AircraftTypes:
+        statement.append(QStringLiteral("SELECT make||' '||model FROM aircraft WHERE model IS NOT NULL AND variant IS NULL "
+                         "UNION "
+                         "SELECT make||' '||model||'-'||variant FROM aircraft WHERE variant IS NOT NULL"));
+        break;
+    case CompleterTarget::AirportIdentifier:
+        statement.append(QStringLiteral("SELECT icao FROM airports UNION SELECT iata FROM airports"));
+        break;
+    case CompleterTarget::Registrations:
+        statement.append(QStringLiteral("SELECT registration FROM tails"));
+        break;
+    case CompleterTarget::Companies:
+        statement.append(QStringLiteral("SELECT company FROM pilots"));
+        break;
+    default:
+        DEB << "Not a valid completer target for this function.";
+        return QStringList();
+    }
+
+    QSqlQuery query;
+    query.prepare(statement);
+    query.setForwardOnly(true);
+    query.exec();
+
+    QStringList completer_list;
+    while (query.next())
+        completer_list.append(query.value(0).toString());
+
+    completer_list.sort();
+    completer_list.removeAll(QString());
+    completer_list.removeDuplicates();
+
+    return completer_list;
+}
+
+const QHash<int, QString> DbCompletionData::getIdMap(CompleterTarget target)
+{
+    QString statement;
+
+    switch (target) {
+    case CompleterTarget::PilotNames:
+        statement.append(QStringLiteral("SELECT ROWID, lastname||', '||firstname FROM pilots"));
+        break;
+    case CompleterTarget::AircraftTypes:
+        statement.append(QStringLiteral("SELECT ROWID, make||' '||model FROM aircraft WHERE model IS NOT NULL AND variant IS NULL "
+                         "UNION "
+                         "SELECT ROWID, make||' '||model||'-'||variant FROM aircraft WHERE variant IS NOT NULL"));
+        break;
+    case CompleterTarget::AirportIdentifierICAO:
+        statement.append(QStringLiteral("SELECT ROWID, icao FROM airports"));
+        break;
+    case CompleterTarget::AirportIdentifierIATA:
+        statement.append(QStringLiteral("SELECT ROWID, iata FROM airports WHERE iata NOT NULL"));
+        break;
+    case CompleterTarget::AirportNames:
+        statement.append(QStringLiteral("SELECT ROWID, name FROM airports"));
+        break;
+    case CompleterTarget::Registrations:
+        statement.append(QStringLiteral("SELECT ROWID, registration FROM tails"));
+        break;
+    default:
+        return {};
+    }
+
+    QSqlQuery query;
+    query.setForwardOnly(true);
+    query.prepare(statement);
+    query.exec();
+
+    auto id_map = QHash<int, QString>();
+    while (query.next())
+        id_map.insert(query.value(0).toInt(), query.value(1).toString());
+    return id_map;
+}
+
+} // namespace OPL

+ 76 - 0
src/database/dbcompletiondata.h

@@ -0,0 +1,76 @@
+#ifndef DBCOMPLETIONDATA_H
+#define DBCOMPLETIONDATA_H
+
+#include "src/database/database.h"
+
+namespace OPL {
+
+/*!
+ * \brief The DatabaseTarget enum lists database items that are
+ * used by completers, for content matching or need to be accessed programatically.
+ */
+enum class CompleterTarget
+{
+    AirportIdentifierICAO,
+    AirportIdentifierIATA,
+    AirportIdentifier,
+    AirportNames,
+    Registrations,
+    Companies,
+    PilotNames,
+    AircraftTypes
+};
+
+/*!
+ * \brief Provides data for QCompleters and QHashs
+ *
+ * \details QCompleters and QHashes are used for mapping user input to database keys.
+ * The required data is retreived from the database and cached for fast access without the
+ * need to query the database. The DbCompletionData class holds the last state of the database
+ * (state of user-modifiable data) in order to intelligently refresh the completion data when needed.
+ */
+class DbCompletionData
+{
+public:
+    /*!
+     * \brief init Retrieves Data and populates Lists and Maps
+     */
+    void init();
+
+    /*!
+     * \brief updates data from the user modifiable tables
+     */
+    void update();
+    void updateTails();
+    void updatePilots();
+
+
+    // Maps for input mapping DB key - user input
+    QHash<int, QString> pilotsIdMap;
+    QHash<int, QString> tailsIdMap;
+    QHash<int, QString> airportIcaoIdMap;
+    QHash<int, QString> airportIataIdMap;
+    QHash<int, QString> airportNameIdMap;
+    // Lists for QCompleter
+    QStringList pilotList;
+    QStringList tailsList;
+    QStringList airportList;
+    // User Data State to trigger update if needed
+    UserDataState current_state;
+
+    /*!
+     * \brief getCompletionList returns a QStringList of values for a
+     * QCompleter based on database values
+     */
+    static const QStringList getCompletionList(CompleterTarget target);
+
+    /*!
+     * \brief returns a QHash of a human-readable database value and
+     * its row id. Used in the Dialogs to map user input to unique database entries.
+     */
+    static const QHash<int, QString> getIdMap(CompleterTarget target);
+};
+
+} // namespace OPL
+
+#endif // DBCOMPLETIONDATA_H

+ 80 - 0
src/database/dbsummary.cpp

@@ -0,0 +1,80 @@
+#include "dbsummary.h"
+
+namespace OPL {
+
+const QMap<DbSummaryKey, QString> DbSummary::databaseSummary(const QString &db_path)
+{
+    const QString connection_name = QStringLiteral("summary_connection");
+    QMap<DbSummaryKey, QString> return_values;
+    { // scope for a temporary database connection, ensures proper cleanup when removeDatabase() is called.
+        //DEB << "Adding temporary connection to database:" << db_path;
+        QSqlDatabase temp_database = QSqlDatabase::addDatabase(SQLITE_DRIVER, connection_name); // Don't use default connection
+        temp_database.setDatabaseName(db_path);
+        if (!temp_database.open())
+            return {};
+
+        QSqlQuery query(temp_database); // Query object using the temporary connection
+        DbSummaryKey key;  // Used among the queries for verbosity... and sanity
+
+        const QVector<QPair<DbSummaryKey, QString>> key_table_pairs = {
+            {DbSummaryKey::total_flights, QStringLiteral("flights")},
+            {DbSummaryKey::total_tails, QStringLiteral("tails")},
+            {DbSummaryKey::total_pilots, QStringLiteral("pilots")}
+        };
+        // retreive amount of flights, tails and pilots
+        for (const auto & pair : key_table_pairs) {
+            query.prepare(QLatin1String("SELECT COUNT (*) FROM ") + pair.second);
+            query.exec();
+            key = pair.first;
+            if (query.first()){
+                return_values[key] = query.value(0).toString();
+            }
+            else{
+                return_values[key] = QString();
+            }
+        }
+        // retreive date of last flight
+        query.prepare(QStringLiteral("SELECT MAX(doft) FROM flights"));
+        query.exec();
+        key = DbSummaryKey::last_flight;
+        if (query.first()){
+            return_values[key] = query.value(0).toString();
+        }
+        else {
+            return_values[key] = QString();
+        }
+        // retreive total flight time as a string "hh:mm"
+        query.prepare(QStringLiteral("SELECT "
+                                     "printf(\"%02d\",CAST(SUM(tblk) AS INT)/60)"
+                                     "||':'||"
+                                     "printf(\"%02d\",CAST(SUM(tblk) AS INT)%60) FROM flights"));
+        key = DbSummaryKey::total_time;
+        query.exec();
+        if (query.first()){
+            return_values[key] = query.value(0).toString();
+        }
+        else {
+            return_values[key] = QString();
+        }
+    }
+
+    QSqlDatabase::removeDatabase(connection_name); // cleanly removes temp connection without leaks since query+db are out of scope
+
+    return return_values;
+}
+
+const QString DbSummary::summaryString(const QString &db_path)
+{
+    auto summary_map = databaseSummary(db_path);
+    QString out = QLatin1String("<table>");
+    out.append(tr("<tr><td>Total Time: </td><td>%1</td>").arg(summary_map[DbSummaryKey::total_time]));
+    out.append(tr("<tr><td>Last Flight: </td><td>%1</td>").arg(summary_map[DbSummaryKey::last_flight]));
+    out.append(tr("<tr><td>Number of flights: </td><td>%1</td>").arg(summary_map[DbSummaryKey::total_flights]));
+    out.append(tr("<tr><td>Number of aircraft: </td><td>%1</td>").arg(summary_map[DbSummaryKey::total_tails]));
+    out.append(tr("<tr><td>Number of Pilots: </td><td>%1</td>").arg(summary_map[DbSummaryKey::total_pilots]));
+    out.append("</table>");
+
+    return out;
+}
+
+} // namespace OPL

+ 56 - 0
src/database/dbsummary.h

@@ -0,0 +1,56 @@
+#ifndef DBSUMMARY_H
+#define DBSUMMARY_H
+
+#include "src/database/database.h"
+
+namespace OPL {
+
+/*!
+ * \brief Enumerates the QHash keys used when summarising a database
+ */
+enum class DbSummaryKey {
+    total_flights,
+    total_tails,
+    total_pilots,
+    last_flight,
+    total_time,
+};
+
+/*!
+ * \brief The DbSummary class collects summaries of entries and relevant data from the database.
+ *
+ * \details Summaries are used mainly in the BackupWidget to give the user a quick overview about the
+ * contents of a database so they can decide which backup to delete/restore. This class is a helper class
+ * to avoid interfacing with the database directly. It uses a separate database connection in order to not
+ * interfere with the currently active database.
+ */
+class DbSummary : public QObject
+{
+public:
+    DbSummary() = default;
+
+    /*!
+     * \brief Return a summary of a database
+     * \details Creates a summary of the database giving a quick overview of the relevant contents. The
+     * function runs several specialised SQL queries to create a QHash<DatabaseSummaryKey, QString> containing
+     * Total Flight Time, Number of unique aircraft and pilots, as well as the date of last flight. Uses a temporary
+     * database connection separate from the default connection in order to not tamper with the currently active
+     * database connection. The full path to the database to be summarized has to be provided.
+     */
+    static const QMap<DbSummaryKey, QString> databaseSummary(const QString& db_path);
+
+    /*!
+     * \brief returns a short summary string of the database, containing total time and date of last flight.
+     */
+    static const QString summaryString(const QString& db_path);
+
+private:
+    Q_OBJECT
+    inline const static QString SQLITE_DRIVER  = QStringLiteral("QSQLITE");
+
+};
+
+
+} // namespace OPL
+
+#endif // DBSUMMARY_H

+ 1 - 1
src/classes/row.cpp → src/database/row.cpp

@@ -54,7 +54,7 @@ OPL::Row::operator QString() const
     }
     QString out("\033[32m[Entry Data]:\t\033[m\n");
     int item_count = 0;
-    QHash<ColName_T, ColData_T>::const_iterator i;
+    QHash<QString, QVariant>::const_iterator i;
     for (i = rowData.constBegin(); i!= rowData.constEnd(); ++i) {
         QString spacer(":");
         int spaces = (14 - i.key().length());

+ 1 - 0
src/classes/row.h → src/database/row.h

@@ -2,6 +2,7 @@
 #define ROW_H
 #include "src/opl.h"
 
+
 namespace OPL {
 
 /*!

+ 11 - 11
src/functions/acalc.cpp

@@ -17,7 +17,7 @@
  */
 #include "acalc.h"
 #include "src/functions/alog.h"
-#include "src/database/adatabase.h"
+#include "src/database/database.h"
 #include "src/classes/asettings.h"
 #include "src/opl.h"
 #include "src/functions/atime.h"
@@ -111,7 +111,7 @@ double ACalc::greatCircleDistanceBetweenAirports(const QString &dept, const QStr
             + QLatin1String("' OR icao = '")
             + dest
             + QLatin1String("'");
-    auto lat_lon = aDB->customQuery(statement, 2);
+    auto lat_lon = DB->customQuery(statement, 2);
 
     if (lat_lon.length() != 4) {
         DEB << "Invalid input. Aborting.";
@@ -234,7 +234,7 @@ int ACalc::calculateNightTime(const QString &dept, const QString &dest, QDateTim
             + dept
             + QLatin1String("' OR icao = '") + dest
             + QLatin1String("'");
-    auto lat_lon = aDB->customQuery(statement, 2);
+    auto lat_lon = DB->customQuery(statement, 2);
 
     double dept_lat;
     double dept_lon;
@@ -278,7 +278,7 @@ bool ACalc::isNight(const QString &icao, QDateTime event_time, int night_angle)
     const QString statement = QLatin1String("SELECT lat, long FROM airports WHERE icao = '")
             + icao
             + QLatin1String("'");
-    auto lat_lon = aDB->customQuery(statement, 2);
+    auto lat_lon = DB->customQuery(statement, 2);
 
     if (lat_lon.length() != 2) {
         DEB << "Invalid input. Aborting.";
@@ -306,17 +306,17 @@ void ACalc::updateAutoTimes(int acft_id)
 {
     //find all flights for aircraft
     const QString statement = QStringLiteral("SELECT flight_id FROM flights WHERE acft = ") + QString::number(acft_id);
-    auto flight_list = aDB->customQuery(statement, 1);
+    auto flight_list = DB->customQuery(statement, 1);
     if (flight_list.isEmpty()) {
         DEB << "No flights for this tail found.";
         return;
     }
     DEB << "Updating " << flight_list.length() << " flights with this aircraft.";
 
-    auto acft = aDB->getTailEntry(acft_id);
+    auto acft = DB->getTailEntry(acft_id);
     auto acft_data = acft.getData();
     for (const auto& item : flight_list) {
-        auto flight = aDB->getFlightEntry(item.toInt());
+        auto flight = DB->getFlightEntry(item.toInt());
         auto flight_data = flight.getData();
 
         if(acft_data.value(OPL::Db::TAILS_MULTIPILOT).toInt() == 0
@@ -338,7 +338,7 @@ void ACalc::updateAutoTimes(int acft_id)
             flight_data.insert(OPL::Db::FLIGHTS_TSPME, QString());
         }
         flight.setData(flight_data);
-        aDB->commit(flight);
+        DB->commit(flight);
     }
 }
 /*!
@@ -351,7 +351,7 @@ void ACalc::updateNightTimes()
 
     //find all flights for aircraft
     auto statement = QStringLiteral("SELECT ROWID FROM flights");
-    auto flight_list = aDB->customQuery(statement, 1);
+    auto flight_list = DB->customQuery(statement, 1);
 
     if (flight_list.isEmpty()) {
         DEB << "No flights found.";
@@ -361,7 +361,7 @@ void ACalc::updateNightTimes()
 
     for (const auto& item : flight_list) {
 
-        auto flt = aDB->getFlightEntry(item.toInt());
+        auto flt = DB->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),
@@ -373,6 +373,6 @@ void ACalc::updateNightTimes()
                                        data.value(OPL::Db::FLIGHTS_TBLK).toInt(),
                                        night_angle));
         flt.setData(data);
-        aDB->commit(flt);
+        DB->commit(flt);
     }
 }

+ 3 - 3
src/functions/astat.cpp

@@ -16,7 +16,7 @@
  *along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 #include "astat.h"
-#include "src/database/adatabase.h"
+#include "src/database/database.h"
 #include "src/functions/alog.h"
 
 /*!
@@ -57,7 +57,7 @@ int AStat::totalTime(TimeFrame time_frame)
         break;
     }
 
-    auto db_return = aDB->customQuery(statement, 1);
+    auto db_return = DB->customQuery(statement, 1);
 
     if (!db_return.isEmpty())
         return db_return.first().toInt();
@@ -84,7 +84,7 @@ QVector<QVariant> AStat::countTakeOffLanding(int days)
                                       " FROM flights "
                                       " WHERE doft >=") + startdate;
 
-    QVector<QVariant> result = aDB->customQuery(statement, 2);
+    QVector<QVariant> result = DB->customQuery(statement, 2);
     // make sure a value is returned instead of NULL
     for (const auto &var : result) {
         if (var.isNull())

+ 33 - 29
src/gui/dialogues/firstrundialog.cpp

@@ -19,9 +19,10 @@
 #include "ui_firstrundialog.h"
 #include "src/opl.h"
 #include "src/functions/alog.h"
-#include "src/database/adatabase.h"
+#include "src/database/database.h"
+#include "src/database/dbsummary.h"
 #include "src/gui/widgets/backupwidget.h"
-#include "src/classes/row.h"
+#include "src/database/row.h"
 #include "src/classes/adownload.h"
 #include "src/classes/asettings.h"
 #include "src/functions/adate.h"
@@ -151,7 +152,7 @@ bool FirstRunDialog::finishSetup()
         }
     } // if database file exists
 
-    if (!aDB->connect()) {
+    if (!DB->connect()) {
         QMessageBox message_box(QMessageBox::Critical, tr("Database setup failed"),
                                 tr("Errors have ocurred creating the database."
                                    "Without a working database The application will not be usable.<br>"
@@ -166,7 +167,7 @@ bool FirstRunDialog::finishSetup()
                                 tr("Errors have ocurred creating the database."
                                    "Without a working database The application will not be usable.<br>"
                                    "The following error has ocurred:<br>%1"
-                                   ).arg(aDB->lastError.text()));
+                                   ).arg(DB->lastError.text()));
         message_box.exec();
         return false;
     }
@@ -175,7 +176,7 @@ bool FirstRunDialog::finishSetup()
         QMessageBox message_box(QMessageBox::Critical, tr("Database setup failed"),
                                 tr("Unable to execute database query<br>"
                                    "The following error has occured:<br>%1"
-                                   ).arg(aDB->lastError.text()));
+                                   ).arg(DB->lastError.text()));
         message_box.exec();
         return false;
     }
@@ -184,11 +185,11 @@ bool FirstRunDialog::finishSetup()
         QMessageBox message_box(QMessageBox::Critical, tr("Database setup failed"),
                                 tr("Unable to execute database query<br>"
                                    "The following error has occured:<br>%1"
-                                   ).arg(aDB->lastError.text()));
+                                   ).arg(DB->lastError.text()));
         message_box.exec();
         return false;
     }
-    aDB->disconnect(); // connection will be re-established by main()
+    DB->disconnect(); // connection will be re-established by main()
     return true;
 }
 
@@ -201,38 +202,40 @@ bool FirstRunDialog::downloadTemplates(QString branch_name)
 
     QDir template_dir(AStandardPaths::directory(AStandardPaths::Templates));
 
-    const auto template_tables = aDB->getTemplateTableNames();
+    QStringList template_table_names;
+    for (const auto table : DB->getTemplateTables())
+        template_table_names.append(OPL::GLOBALS->getDbTableName(table));
     // Download json files
-    for (const auto& table : template_tables) {
+    for (const auto& table_name : template_table_names) {
         QEventLoop loop;
         ADownload* dl = new ADownload;
         QObject::connect(dl, &ADownload::done, &loop, &QEventLoop::quit );
-        dl->setTarget(QUrl(template_url_string + table + QLatin1String(".json")));
-        dl->setFileName(template_dir.absoluteFilePath(table + QLatin1String(".json")));
-        DEB << "Downloading: " << template_url_string + table + QLatin1String(".json");
+        dl->setTarget(QUrl(template_url_string + table_name + QLatin1String(".json")));
+        dl->setFileName(template_dir.absoluteFilePath(table_name + QLatin1String(".json")));
+        DEB << "Downloading: " << template_url_string + table_name + QLatin1String(".json");
         dl->download();
         dl->deleteLater();
         loop.exec(); // event loop waits for download done signal before allowing loop to continue
 
-        QFileInfo downloaded_file(template_dir.filePath(table + QLatin1String(".json")));
+        QFileInfo downloaded_file(template_dir.filePath(table_name + QLatin1String(".json")));
         if (downloaded_file.size() == 0)
             return false; // ssl/network error
     }
     // Download checksum files
-    for (const auto& table : template_tables) {
+    for (const auto& table_name : template_table_names) {
         QEventLoop loop;
         ADownload* dl = new ADownload;
         QObject::connect(dl, &ADownload::done, &loop, &QEventLoop::quit );
-        dl->setTarget(QUrl(template_url_string + table + QLatin1String(".md5")));
-        dl->setFileName(template_dir.absoluteFilePath(table + QLatin1String(".md5")));
+        dl->setTarget(QUrl(template_url_string + table_name + QLatin1String(".md5")));
+        dl->setFileName(template_dir.absoluteFilePath(table_name + QLatin1String(".md5")));
 
-        LOG << "Downloading: " << template_url_string + table + QLatin1String(".md5");
+        LOG << "Downloading: " << template_url_string + table_name + QLatin1String(".md5");
 
         dl->download();
         dl->deleteLater();
         loop.exec(); // event loop waits for download done signal before allowing loop to continue
 
-        QFileInfo downloaded_file(template_dir.filePath(table + QLatin1String(".md5")));
+        QFileInfo downloaded_file(template_dir.filePath(table_name + QLatin1String(".md5")));
         if (downloaded_file.size() == 0)
             return false; // ssl/network error
     }
@@ -241,9 +244,10 @@ bool FirstRunDialog::downloadTemplates(QString branch_name)
 }
 
 bool FirstRunDialog::verifyTemplates()
-{
-    const auto table_names = aDB->getTemplateTableNames();
-    for (const auto &table_name : table_names) {
+{QStringList template_table_names;
+    for (const auto table : DB->getTemplateTables())
+        template_table_names.append(OPL::GLOBALS->getDbTableName(table));
+    for (const auto &table_name : template_table_names) {
         const QString path = AStandardPaths::asChildOfDir(AStandardPaths::Templates, table_name);
 
         QFileInfo check_file(path + QLatin1String(".json"));
@@ -300,15 +304,15 @@ bool FirstRunDialog::setupDatabase()
         useRessourceData = true;
     }
 
-    if(!aDB->createSchema()) {
+    if(!DB->createSchema()) {
         WARN(tr("Database creation has been unsuccessful. The following error has ocurred:<br><br>%1")
-             .arg(aDB->lastError.text()));
+             .arg(DB->lastError.text()));
         return false;
     }
 
-    if(!aDB->importTemplateData(useRessourceData)) {
+    if(!DB->importTemplateData(useRessourceData)) {
         WARN(tr("Database creation has been unsuccessful. Unable to fill template data.<br><br>%1")
-             .arg(aDB->lastError.text()));
+             .arg(DB->lastError.text()));
         return false;
     }
     return true;
@@ -326,7 +330,7 @@ bool FirstRunDialog::createUserEntry()
 
     auto pilot = OPL::PilotEntry(1, data);
 
-    return aDB->commit(pilot);
+    return DB->commit(pilot);
 }
 
 bool FirstRunDialog::writeCurrencies()
@@ -351,7 +355,7 @@ bool FirstRunDialog::writeCurrencies()
                 row_data.insert(OPL::Db::CURRENCIES_CURRENCYNAME, ui->currCustom2LineEdit->text());
 
             OPL::CurrencyEntry entry(static_cast<int>(pair.first), row_data);
-            if (!aDB->commit(entry))
+            if (!DB->commit(entry))
                 return false;
         }
     }
@@ -435,9 +439,9 @@ void FirstRunDialog::on_importPushButton_clicked()
     confirm.setText(tr("The following database will be imported:<br><br><b><tt>"
                        "%1<br></b></tt>"
                        "<br>Is this correct?"
-                       ).arg(aDB->databaseSummaryString(filename)));
+                       ).arg(OPL::DbSummary::summaryString(filename)));
     if (confirm.exec() == QMessageBox::Yes) {
-        if(!aDB->restoreBackup(filename)) {
+        if(!DB->restoreBackup(filename)) {
             WARN(tr("Unable to import database file:").arg(filename));
             return;
         }

+ 11 - 11
src/gui/dialogues/newflightdialog.cpp

@@ -31,7 +31,7 @@
 
 const auto CAT_3 = QLatin1String(OPL::GLOBALS->getApproachTypes()[3].toLatin1());
 
-NewFlightDialog::NewFlightDialog(ACompletionData &completion_data,
+NewFlightDialog::NewFlightDialog(OPL::DbCompletionData &completion_data,
                                        QWidget *parent)
     : QDialog(parent),
       ui(new Ui::NewFlightDialog),
@@ -56,13 +56,13 @@ NewFlightDialog::NewFlightDialog(ACompletionData &completion_data,
     emit ui->doftLineEdit->editingFinished();
 }
 
-NewFlightDialog::NewFlightDialog(ACompletionData &completion_data, RowId_T row_id, QWidget *parent)
+NewFlightDialog::NewFlightDialog(OPL::DbCompletionData &completion_data, int row_id, QWidget *parent)
     : QDialog(parent),
       ui(new Ui::NewFlightDialog),
       completionData(completion_data)
 {
     init();
-    flightEntry = aDB->getFlightEntry(row_id);
+    flightEntry = DB->getFlightEntry(row_id);
     fillWithEntryData();
 }
 
@@ -304,7 +304,7 @@ bool NewFlightDialog::addNewTail(QLineEdit& parent_line_edit)
         // update map and list, set line edit
         if (ret == QDialog::Accepted) {
             DEB << "New Tail Entry added:";
-            DEB << aDB->getTailEntry(aDB->getLastEntry(ADatabaseTable::tails));
+            DEB << DB->getTailEntry(DB->getLastEntry(OPL::DbTable::Tails));
 
             // update completion Data and Completer
             completionData.updateTails();
@@ -312,7 +312,7 @@ bool NewFlightDialog::addNewTail(QLineEdit& parent_line_edit)
             parent_line_edit.completer()->setModel(new_model); //setModel deletes old model if it has the completer as parent
 
             // update Line Edit
-            parent_line_edit.setText(completionData.tailsIdMap.value(aDB->getLastEntry(ADatabaseTable::tails)));
+            parent_line_edit.setText(completionData.tailsIdMap.value(DB->getLastEntry(OPL::DbTable::Tails)));
             return true;
         } else {
             return false;
@@ -343,14 +343,14 @@ bool NewFlightDialog::addNewPilot(QLineEdit& parent_line_edit)
         // update map and list, set line edit
         if (ret == QDialog::Accepted) {
             DEB << "New Pilot Entry added:";
-            DEB << aDB->getPilotEntry(aDB->getLastEntry(ADatabaseTable::pilots));
+            DEB << DB->getPilotEntry(DB->getLastEntry(OPL::DbTable::Pilots));
             // update completion Data and Completer
             completionData.updatePilots();
             auto new_model = new QStringListModel(completionData.pilotList, parent_line_edit.completer());
             parent_line_edit.completer()->setModel(new_model); //setModel deletes old model if it has the completer as parent
 
             // update Line Edit
-            parent_line_edit.setText(completionData.pilotsIdMap.value(aDB->getLastEntry(ADatabaseTable::pilots)));
+            parent_line_edit.setText(completionData.pilotsIdMap.value(DB->getLastEntry(OPL::DbTable::Pilots)));
             return true;
         } else {
             return false;
@@ -387,7 +387,7 @@ RowData_T NewFlightDialog::prepareFlightEntryData()
     // Aircraft
     int acft_id = completionData.tailsIdMap.key(ui->acftLineEdit->text());
     new_data.insert(OPL::Db::FLIGHTS_ACFT, acft_id);
-    const OPL::TailEntry acft_data = aDB->getTailEntry(acft_id);
+    const OPL::TailEntry acft_data = DB->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();
 
@@ -735,7 +735,7 @@ bool NewFlightDialog::checkPilotFunctionsValid()
  * \details When the user is ready to submit a flight entry, a final check for valid entries is made, and the user
  * is prompted to correct unsatisfactory inputs. When this is done, prepareFlightEntryData() collects the input from
  * the user interface and converts it to database format. The data is then stored in a QHash<QString, QVariant>.
- * This data is then used to create a AFlightEntry object, which is then commited to the database by ADatabase::commit()
+ * This data is then used to create a AFlightEntry object, which is then commited to the database by Database::commit()
  */
 void NewFlightDialog::on_buttonBox_accepted()
 {
@@ -779,11 +779,11 @@ void NewFlightDialog::on_buttonBox_accepted()
     flightEntry.setData(newData);
     DEB << "Committing: ";
     DEB << flightEntry;
-    if (!aDB->commit(flightEntry)) {
+    if (!DB->commit(flightEntry)) {
         WARN(tr("The following error has ocurred:"
                                "<br><br>%1<br><br>"
                                "The entry has not been saved."
-                               ).arg(aDB->lastError.text()));
+                               ).arg(DB->lastError.text()));
         return;
     } else {
         QDialog::accept();

+ 7 - 7
src/gui/dialogues/newflightdialog.h

@@ -25,10 +25,10 @@
 #include <QBitArray>
 
 #include "src/functions/atime.h"
-#include "src/classes/acompletiondata.h"
-#include "src/database/adatabase.h"
+#include "src/database/database.h"
+#include "src/database/dbcompletiondata.h"
 #include "src/opl.h"
-#include "src/classes/row.h"
+#include "src/database/row.h"
 
 /*!
  * \brief The ValidationItem enum contains the items that are mandatory for logging a flight:
@@ -100,7 +100,7 @@ class NewFlightDialog;
  * for each of the database tables which are used to create QCompleters that provide pop-up completion on the respective QLineEdits.
  *
  * Once the user is satisfied with his entries, a final set of input verification is triggered and the entry is submitted to the database,
- * see on_buttonBox_accepted() and ADatabase::commit()
+ * see on_buttonBox_accepted() and Database::commit()
  */
 class NewFlightDialog : public QDialog
 {
@@ -112,18 +112,18 @@ public:
      * \brief NewFlightDialog - Creates a NewFlightDialog that can be used to add a new flight entry to the logbook
      * \param completion_data - contains QStringLists for the QCompleter to autocomplete Airport Codes, Pilot Names and aircraft registrationsn
      */
-    explicit NewFlightDialog(ACompletionData& completion_data, QWidget *parent = nullptr);
+    explicit NewFlightDialog(OPL::DbCompletionData& completion_data, QWidget *parent = nullptr);
     /*!
      * \brief NewFlightDialog - Creates a NewFlightDialog that can be used to edit an existing entry in the logbook
      * \param completion_data - contains QStringLists for the QCompleter to autocomplete Airport Codes, Pilot Names and aircraft registrationsn
      * \param row_id - The database ROW ID of the entry to be edited
      */
-    explicit NewFlightDialog(ACompletionData& completion_data, RowId_T row_id, QWidget* parent = nullptr);
+    explicit NewFlightDialog(OPL::DbCompletionData& completion_data, int row_id, QWidget* parent = nullptr);
     ~NewFlightDialog();
 
 private:
     Ui::NewFlightDialog *ui;
-    ACompletionData completionData;
+    OPL::DbCompletionData completionData;
     ValidationState validationState;
 
     /*!

+ 7 - 6
src/gui/dialogues/newpilotdialog.cpp

@@ -19,8 +19,9 @@
 #include "ui_newpilot.h"
 #include "src/opl.h"
 
-#include "src/database/adatabase.h"
-#include "src/classes/row.h"
+#include "src/database/database.h"
+#include "src/database/dbcompletiondata.h"
+#include "src/database/row.h"
 #include "src/functions/alog.h"
 
 /*!
@@ -46,7 +47,7 @@ NewPilotDialog::NewPilotDialog(int rowId, QWidget *parent) :
 {
     setup();
 
-    pilotEntry = aDB->getPilotEntry(rowId);
+    pilotEntry = DB->getPilotEntry(rowId);
     DEB << "Editing Pilot: " << pilotEntry;
     formFiller();
     ui->lastnameLineEdit->setFocus();
@@ -61,7 +62,7 @@ void NewPilotDialog::setup()
 {
     ui->setupUi(this);
 
-    auto completer = new QCompleter(aDB->getCompletionList(ADatabaseTarget::companies), ui->companyLineEdit);
+    auto completer = new QCompleter(OPL::DbCompletionData::getCompletionList(OPL::CompleterTarget::Companies), ui->companyLineEdit);
     completer->setCompletionMode(QCompleter::InlineCompletion);
     completer->setCaseSensitivity(Qt::CaseSensitive);
     ui->companyLineEdit->setCompleter(completer);
@@ -101,12 +102,12 @@ void NewPilotDialog::submitForm()
     pilotEntry.setData(new_data);
     DEB << "Submitting Pilot:";
     DEB << pilotEntry;
-    if (!aDB->commit(pilotEntry)) {
+    if (!DB->commit(pilotEntry)) {
         QMessageBox message_box(this);
         message_box.setText(tr("The following error has ocurred:"
                                "<br><br>%1<br><br>"
                                "The entry has not been saved."
-                               ).arg(aDB->lastError.text()));
+                               ).arg(DB->lastError.text()));
         message_box.exec();
         return;
     } else {

+ 1 - 1
src/gui/dialogues/newpilotdialog.h

@@ -23,7 +23,7 @@
 #include <QRegularExpression>
 #include <QRegularExpressionValidator>
 #include <QCompleter>
-#include "src/classes/row.h"
+#include "src/database/row.h"
 
 namespace Ui {
 class NewPilot;

+ 5 - 5
src/gui/dialogues/newsimdialog.cpp

@@ -20,13 +20,13 @@ NewSimDialog::NewSimDialog(QWidget *parent) :
  * \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) :
+NewSimDialog::NewSimDialog(int row_id, QWidget *parent) :
     QDialog(parent),
     ui(new Ui::NewSimDialog)
 {
 
     ui->setupUi(this);
-    entry = aDB->getSimEntry(row_id);
+    entry = DB->getSimEntry(row_id);
     init();
     fillEntryData();
 }
@@ -38,7 +38,7 @@ void NewSimDialog::init()
 {
     OPL::GLOBALS->loadSimulatorTypes(ui->deviceTypeComboBox);
 
-    const QStringList aircraft_list = aDB->getCompletionList(ADatabaseTarget::aircraft);
+    const QStringList aircraft_list = OPL::DbCompletionData::getCompletionList(OPL::CompleterTarget::AircraftTypes);
     auto completer = new QCompleter(aircraft_list, ui->aircraftTypeLineEdit);
     completer->setCaseSensitivity(Qt::CaseInsensitive);
     completer->setCompletionMode(QCompleter::PopupCompletion);
@@ -180,8 +180,8 @@ void NewSimDialog::on_buttonBox_accepted()
 
     DEB << entry;
 
-    if(aDB->commit(entry))
+    if(DB->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()));
+        WARN(tr("Unable to commit entry to database. The following error has ocurred <br><br>%1").arg(DB->lastError.text()));
 }

+ 4 - 4
src/gui/dialogues/newsimdialog.h

@@ -2,9 +2,9 @@
 #define NEWSIMDIALOG_H
 
 #include <QDialog>
-#include "src/classes/row.h"
-#include "src/database/adatabase.h"
-#include "src/classes/acompletiondata.h"
+#include "src/database/row.h"
+#include "src/database/database.h"
+#include "src/database/dbcompletiondata.h"
 
 namespace Ui {
 class NewSimDialog;
@@ -25,7 +25,7 @@ class NewSimDialog : public QDialog
 
 public:
     explicit NewSimDialog(QWidget *parent = nullptr);
-    explicit NewSimDialog(RowId_T row_id, QWidget *parent = nullptr);
+    explicit NewSimDialog(int row_id, QWidget *parent = nullptr);
     ~NewSimDialog();
 
 private slots:

+ 7 - 6
src/gui/dialogues/newtaildialog.cpp

@@ -19,6 +19,7 @@
 #include "ui_newtail.h"
 #include "src/functions/alog.h"
 #include "src/opl.h"
+#include "src/database/dbcompletiondata.h"
 
 NewTailDialog::NewTailDialog(const QString &new_registration, QWidget *parent) :
     QDialog(parent),
@@ -47,7 +48,7 @@ NewTailDialog::NewTailDialog(int row_id, QWidget *parent) :
     ui->line->hide();
 
     setupValidators();
-    entry = aDB->getTailEntry(row_id);
+    entry = DB->getTailEntry(row_id);
     LOG << "Editing: " << entry;
     fillForm(entry, false);
 }
@@ -65,8 +66,8 @@ NewTailDialog::~NewTailDialog()
  */
 void NewTailDialog::setupCompleter()
 {
-    idMap = aDB->getIdMap(ADatabaseTarget::aircraft);
-    aircraftList = aDB->getCompletionList(ADatabaseTarget::aircraft);
+    idMap = OPL::DbCompletionData::getIdMap(OPL::CompleterTarget::AircraftTypes);
+    aircraftList = OPL::DbCompletionData::getCompletionList(OPL::CompleterTarget::AircraftTypes);
 
     QCompleter *completer = new QCompleter(aircraftList, ui->searchLineEdit);
     completer->setCaseSensitivity(Qt::CaseInsensitive);
@@ -204,12 +205,12 @@ void NewTailDialog::submitForm()
 
     entry.setData(new_data);
     LOG << "Commiting: " << entry;
-    if (!aDB->commit(entry)) {
+    if (!DB->commit(entry)) {
         QMessageBox message_box(this);
         message_box.setText(tr("The following error has ocurred:"
                                "<br><br>%1<br><br>"
                                "The entry has not been saved."
-                               ).arg(aDB->lastError.text()));
+                               ).arg(DB->lastError.text()));
         message_box.exec();
         return;
     } else {
@@ -273,7 +274,7 @@ void NewTailDialog::onSearchCompleterActivated()
 
             DEB << "Template Selected. aircraft_id is: " << idMap.key(text);
             //call autofiller for dialog
-            fillForm(aDB->getAircraftEntry(idMap.key(text)), true);
+            fillForm(DB->getAircraftEntry(idMap.key(text)), true);
             ui->searchLineEdit->setStyleSheet(QStringLiteral("border: 1px solid green"));
             ui->searchLabel->setText(text);
         } else {

+ 3 - 3
src/gui/dialogues/newtaildialog.h

@@ -26,8 +26,8 @@
 
 #include "src/classes/asettings.h"
 #include "src/functions/acalc.h"
-#include "src/database/adatabase.h"
-#include "src/classes/row.h"
+#include "src/database/database.h"
+#include "src/database/row.h"
 
 namespace Ui {
 class NewTail;
@@ -84,7 +84,7 @@ private:
 
     QStringList aircraftList;
 
-    QHash<RowId_T, QString> idMap;
+    QHash<int, QString> idMap;
 
     void setupCompleter();
     void setupValidators();

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

@@ -19,8 +19,8 @@
 #include "ui_aircraftwidget.h"
 #include "src/opl.h"
 #include "src/classes/asettings.h"
-#include "src/database/adatabase.h"
-#include "src/classes/row.h"
+#include "src/database/database.h"
+#include "src/database/row.h"
 #include "src/functions/alog.h"
 
 AircraftWidget::AircraftWidget(QWidget *parent) :
@@ -180,7 +180,7 @@ void AircraftWidget::on_deleteAircraftButton_clicked()
         /// I think batch-editing should be implemented at some point, but batch-deleting should not.
 
     } else if (selectedTails.length() == 1) {
-        auto entry = aDB->getTailEntry(selectedTails.first());
+        auto entry = DB->getTailEntry(selectedTails.first());
         QMessageBox message_box(this);
         message_box.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
         message_box.setDefaultButton(QMessageBox::No);
@@ -192,7 +192,7 @@ void AircraftWidget::on_deleteAircraftButton_clicked()
                                      getAircraftTypeString(entry)));
 
         if (message_box.exec() == QMessageBox::Yes) {
-            if(!aDB->remove(entry))
+            if(!DB->remove(entry))
                 onDeleteUnsuccessful();
         }
     }
@@ -212,17 +212,17 @@ void AircraftWidget::on_deleteAircraftButton_clicked()
  */
 void AircraftWidget::onDeleteUnsuccessful()
 {
-    QList<int> foreign_key_constraints = aDB->getForeignKeyConstraints(selectedTails.first(),
-                                                                       ADatabaseTable::tails);
+    QList<int> foreign_key_constraints = DB->getForeignKeyConstraints(selectedTails.first(),
+                                                                       OPL::DbTable::Tails);
     QList<OPL::FlightEntry> constrained_flights;
     for (const auto &row_id : qAsConst(foreign_key_constraints)) {
-        constrained_flights.append(aDB->getFlightEntry(row_id));
+        constrained_flights.append(DB->getFlightEntry(row_id));
     }
 
     QMessageBox message_box(this);
     if (constrained_flights.isEmpty()) {
         message_box.setText(tr("<br>Unable to delete.<br><br>The following error has ocurred: %1"
-                               ).arg(aDB->lastError.text()));
+                               ).arg(DB->lastError.text()));
         message_box.exec();
         return;
     } else {

+ 20 - 19
src/gui/widgets/backupwidget.cpp

@@ -20,8 +20,9 @@
 #include "src/opl.h"
 #include "src/classes/astandardpaths.h"
 #include "src/functions/alog.h"
-#include "src/database/adatabase.h"
+#include "src/database/database.h"
 #include "src/functions/adatetime.h"
+#include "src/database/dbsummary.h"
 
 #include <QListView>
 #include <QStandardItemModel>
@@ -63,13 +64,13 @@ void BackupWidget::refresh()
 
     // Get summary of each db file and populate lists (columns) of data
     for (const auto &entry : entries) {
-        QMap<ADatabaseSummaryKey, QString> summary = aDB->databaseSummary(backup_dir.absoluteFilePath(entry));
+        QMap<OPL::DbSummaryKey, QString> summary = OPL::DbSummary::databaseSummary(backup_dir.absoluteFilePath(entry));
         model->appendRow({new AFileStandardItem(provider.icon(QFileIconProvider::File), entry, AStandardPaths::Backup),
-                          new QStandardItem(summary[ADatabaseSummaryKey::total_flights]),
-                          new QStandardItem(summary[ADatabaseSummaryKey::total_tails]),
-                          new QStandardItem(summary[ADatabaseSummaryKey::total_pilots]),
-                          new QStandardItem(summary[ADatabaseSummaryKey::last_flight]),
-                          new QStandardItem(summary[ADatabaseSummaryKey::total_time])
+                          new QStandardItem(summary[OPL::DbSummaryKey::total_flights]),
+                          new QStandardItem(summary[OPL::DbSummaryKey::total_tails]),
+                          new QStandardItem(summary[OPL::DbSummaryKey::total_pilots]),
+                          new QStandardItem(summary[OPL::DbSummaryKey::last_flight]),
+                          new QStandardItem(summary[OPL::DbSummaryKey::total_time])
                          });
     }
 
@@ -103,7 +104,7 @@ void BackupWidget::on_createLocalPushButton_clicked()
     QString filename = absoluteBackupPath();
     DEB << filename;
 
-    if(!aDB->createBackup(filename)) {
+    if(!DB->createBackup(filename)) {
         WARN(tr("Could not create local file: %1").arg(filename));
         return;
     } else {
@@ -111,13 +112,13 @@ void BackupWidget::on_createLocalPushButton_clicked()
     }
 
     QFileIconProvider provider;
-    QMap<ADatabaseSummaryKey, QString> summary = aDB->databaseSummary(filename);
+    QMap<OPL::DbSummaryKey, QString> summary = OPL::DbSummary::databaseSummary(filename);
     model->insertRow(0, {new AFileStandardItem(provider.icon(QFileIconProvider::File), QFileInfo(filename)),
-                      new QStandardItem(summary[ADatabaseSummaryKey::total_flights]),
-                      new QStandardItem(summary[ADatabaseSummaryKey::total_tails]),
-                      new QStandardItem(summary[ADatabaseSummaryKey::total_pilots]),
-                      new QStandardItem(summary[ADatabaseSummaryKey::last_flight]),
-                      new QStandardItem(summary[ADatabaseSummaryKey::total_time])
+                      new QStandardItem(summary[OPL::DbSummaryKey::total_flights]),
+                      new QStandardItem(summary[OPL::DbSummaryKey::total_tails]),
+                      new QStandardItem(summary[OPL::DbSummaryKey::total_pilots]),
+                      new QStandardItem(summary[OPL::DbSummaryKey::last_flight]),
+                      new QStandardItem(summary[OPL::DbSummaryKey::total_time])
                      });
 }
 
@@ -141,11 +142,11 @@ void BackupWidget::on_restoreLocalPushButton_clicked()
     confirm.setText(tr("The following backup will be restored:<br><br><b><tt>"
                        "%1</b></tt><br><br>"
                        "This will replace your currently active database with the backup.<br>This action is irreversible.<br><br>Are you sure?"
-                       ).arg(aDB->databaseSummaryString(backup_name)));
+                       ).arg(OPL::DbSummary::summaryString(backup_name)));
     if (confirm.exec() == QMessageBox::No)
         return;
 
-    if(!aDB->restoreBackup(backup_name)) {
+    if(!DB->restoreBackup(backup_name)) {
        WARN(tr("Unable to restore Backup file: %1").arg(backup_name));
     } else {
         INFO(tr("Backup successfully restored."));
@@ -212,7 +213,7 @@ void BackupWidget::on_createExternalPushButton_clicked()
         filename.append(".db");
     }
 
-    if(!aDB->createBackup(filename)) {
+    if(!DB->createBackup(filename)) {
         WARN(tr("Unable to backup file:").arg(filename));
         return;
     } else {
@@ -243,9 +244,9 @@ void BackupWidget::on_restoreExternalPushButton_clicked()
     confirm.setText(tr("The following database will be imported:<br><br><b><tt>"
                        "%1<br></b></tt>"
                        "<br>Is this correct?"
-                       ).arg(aDB->databaseSummaryString(filename)));
+                       ).arg(OPL::DbSummary::summaryString(filename)));
     if (confirm.exec() == QMessageBox::Yes) {
-        if(!aDB->restoreBackup(filename)) {
+        if(!DB->restoreBackup(filename)) {
             WARN(tr("Unable to import database file:").arg(filename));
             return;
         }

+ 20 - 19
src/gui/widgets/debugwidget.cpp

@@ -59,7 +59,7 @@ DebugWidget::DebugWidget(QWidget *parent) :
     ui(new Ui::DebugWidget)
 {
     ui->setupUi(this);
-    for (const auto& table : aDB->getTableNames()) {
+    for (const auto& table : DB->getTableNames()) {
         if( table != "sqlite_sequence") {
             ui->tableComboBox->addItem(table);
         }
@@ -74,9 +74,9 @@ DebugWidget::~DebugWidget()
 void DebugWidget::on_resetUserTablesPushButton_clicked()
 {
     ATimer timer(this);
-    if (aDB->resetUserData()){
+    if (DB->resetUserData()){
         LOG << "Database successfully reset";
-        emit aDB->dataBaseUpdated();
+        emit DB->dataBaseUpdated();
     } else
         LOG <<"Errors have occurred. Check console for Debug output. ";
 }
@@ -84,7 +84,7 @@ void DebugWidget::on_resetUserTablesPushButton_clicked()
 void DebugWidget::on_resetDatabasePushButton_clicked()
 {
     // disconnect and remove old database
-    aDB->disconnect();
+    DB->disconnect();
     QFile db_file(AStandardPaths::directory(AStandardPaths::Database).absoluteFilePath(QStringLiteral("logbook.db")));
     if (!db_file.remove()) {
         WARN(tr("Unable to delete existing database file."));
@@ -101,26 +101,27 @@ void DebugWidget::on_resetDatabasePushButton_clicked()
     template_url_string.append(QLatin1String("/assets/database/templates/"));
 
     QDir template_dir(AStandardPaths::directory(AStandardPaths::Templates));
-
-    const auto template_tables = aDB->getTemplateTableNames();
+    QStringList template_table_names;
+    for (const auto table : DB->getTemplateTables())
+        template_table_names.append(OPL::GLOBALS->getDbTableName(table));
     // Download json files
-    for (const auto& table : template_tables) {
+    for (const auto& table_name : template_table_names) {
         QEventLoop loop;
         ADownload* dl = new ADownload;
         QObject::connect(dl, &ADownload::done, &loop, &QEventLoop::quit );
-        dl->setTarget(QUrl(template_url_string + table + QLatin1String(".json")));
-        dl->setFileName(template_dir.absoluteFilePath(table + QLatin1String(".json")));
-        DEB << "Downloading: " << template_url_string + table + QLatin1String(".json");
+        dl->setTarget(QUrl(template_url_string + table_name + QLatin1String(".json")));
+        dl->setFileName(template_dir.absoluteFilePath(table_name + QLatin1String(".json")));
+        DEB << "Downloading: " << template_url_string + table_name + QLatin1String(".json");
         dl->download();
         dl->deleteLater();
         loop.exec(); // event loop waits for download done signal before allowing loop to continue
 
-        QFileInfo downloaded_file(template_dir.filePath(table + QLatin1String(".json")));
+        QFileInfo downloaded_file(template_dir.filePath(table_name + QLatin1String(".json")));
         if (downloaded_file.size() == 0)
             LOG << "ssl/network error";
     }
     // Download checksum files
-    for (const auto& table : template_tables) {
+    for (const auto& table : template_table_names) {
         QEventLoop loop;
         ADownload* dl = new ADownload;
         QObject::connect(dl, &ADownload::done, &loop, &QEventLoop::quit );
@@ -138,20 +139,20 @@ void DebugWidget::on_resetDatabasePushButton_clicked()
             LOG << "ssl/network error";
     }
     // Create Database
-    if (!aDB->createSchema()) {
-        WARN(QString("Unable to create database.<br>%1").arg(aDB->lastError.text()));
+    if (!DB->createSchema()) {
+        WARN(QString("Unable to create database.<br>%1").arg(DB->lastError.text()));
         return;
     }
 
     // Load ressources
     bool use_ressource_data = false; // do not use local data, download from github
-    if(!aDB->importTemplateData(use_ressource_data)) {
+    if(!DB->importTemplateData(use_ressource_data)) {
         WARN(tr("Database creation has been unsuccessful. Unable to fill template data.<br><br>%1")
-             .arg(aDB->lastError.text()));
+             .arg(DB->lastError.text()));
         return ;
     }
 
-    aDB->connect();
+    DB->connect();
 
 }
 
@@ -200,7 +201,7 @@ void DebugWidget::on_fillUserDataPushButton_clicked()
 
     message_box.setText("User tables successfully populated.");
     message_box.exec();
-    emit aDB->dataBaseUpdated();
+    emit DB->dataBaseUpdated();
     */
 }
 
@@ -223,7 +224,7 @@ void DebugWidget::on_importCsvPushButton_clicked()
 
     if (file.exists() && file.isFile()) {
 
-        if (ADataBaseSetup::commitData(aReadCsv(file.absoluteFilePath()), ui->tableComboBox->currentText())) {
+        if (DataBaseSetup::commitData(aReadCsv(file.absoluteFilePath()), ui->tableComboBox->currentText())) {
             QMessageBox message_box(this);
             message_box.setText("Data inserted successfully.");
             message_box.exec();

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

@@ -28,8 +28,8 @@
 #include "src/classes/adownload.h"
 #include "src/functions/areadcsv.h"
 
-#include "src/database/adatabase.h"
-#include "src/classes/row.h"
+#include "src/database/database.h"
+#include "src/database/row.h"
 
 #include "src/testing/atimer.h"
 #include "src/functions/alog.h"

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

@@ -18,10 +18,10 @@
 #include "homewidget.h"
 #include "ui_homewidget.h"
 #include "src/functions/alog.h"
-#include "src/database/adatabase.h"
+#include "src/database/database.h"
 #include "src/functions/atime.h"
 #include "src/classes/asettings.h"
-#include "src/classes/row.h"
+#include "src/database/row.h"
 
 // EASA FTL Limitations in minutes
 // 100 hours per 28 days
@@ -98,7 +98,7 @@ void HomeWidget::fillTotals()
 
 void HomeWidget::fillCurrency(OPL::CurrencyName currency_name, QLabel* display_label)
 {
-    const auto currency_entry = aDB->getCurrencyEntry(static_cast<int>(currency_name));
+    const auto currency_entry = DB->getCurrencyEntry(static_cast<int>(currency_name));
 
     if (currency_name == OPL::CurrencyName::Custom1) {
         ui->currCustom1Label->setText(currency_entry.getData().value(OPL::Db::CURRENCIES_CURRENCYNAME).toString());
@@ -219,7 +219,7 @@ void HomeWidget::fillLimitations()
 const QString HomeWidget::userName()
 {
     const auto statement = QStringLiteral("SELECT firstname FROM pilots WHERE ROWID=1");
-    const auto name = aDB->customQuery(statement, 1);
+    const auto name = DB->customQuery(statement, 1);
     if (!name.isEmpty())
         return name.first().toString();
 

+ 1 - 1
src/gui/widgets/homewidget.h

@@ -24,7 +24,7 @@
 #include <QLineEdit>
 #include <QSettings>
 #include "src/functions/astat.h"
-#include "src/database/adatabase.h"
+#include "src/database/database.h"
 #include "src/classes/asettings.h"
 
 namespace Ui {

+ 8 - 12
src/gui/widgets/logbookwidget.cpp

@@ -18,8 +18,8 @@
 #include "logbookwidget.h"
 #include "ui_logbookwidget.h"
 
-#include "src/classes/row.h"
-#include "src/database/adatabase.h"
+#include "src/database/row.h"
+#include "src/database/database.h"
 #include "src/classes/asettings.h"
 #include "src/gui/dialogues/newflightdialog.h"
 #include "src/gui/dialogues/newsimdialog.h"
@@ -35,7 +35,7 @@ const QHash<int, QString> FILTER_MAP = {
 };
 const auto NON_WORD_CHAR = QRegularExpression("\\W");
 
-LogbookWidget::LogbookWidget(ACompletionData& completion_data, QWidget *parent) :
+LogbookWidget::LogbookWidget(OPL::DbCompletionData& completion_data, QWidget *parent) :
     QWidget(parent),
     ui(new Ui::LogbookWidget),
     completionData(completion_data)
@@ -156,7 +156,7 @@ void LogbookWidget::on_actionDelete_Flight_triggered()
         QVector<OPL::FlightEntry> flights_list;
 
         for (const auto &flight_id : qAsConst(selectedEntries)) {
-            flights_list.append(aDB->getFlightEntry(flight_id));
+            flights_list.append(DB->getFlightEntry(flight_id));
         }
 
         QString flights_list_string;
@@ -178,9 +178,9 @@ void LogbookWidget::on_actionDelete_Flight_triggered()
         if (confirm.exec() == QMessageBox::Yes) {
             for (auto& flight : flights_list) {
                 DEB << "Deleting flight: " << flight;
-                if(!aDB->remove(flight)) {
+                if(!DB->remove(flight)) {
                     WARN(tr("<br>Unable to delete.<br><br>The following error has ocurred: %1"
-                                       ).arg(aDB->lastError.text()));
+                                       ).arg(DB->lastError.text()));
                     return;
                 }
             }
@@ -199,12 +199,8 @@ void LogbookWidget::on_actionDelete_Flight_triggered()
                            "Are you sure you want to proceed?"
                            ).arg(QString::number(selectedEntries.length())));
         if(confirm.exec() == QMessageBox::Yes) {
-            QList<DataPosition> selected_flights;
-            for (const auto& flight_id : qAsConst(selectedEntries)) {
-                selected_flights.append({QStringLiteral("flights"), flight_id});
-            }
-            if (!aDB->removeMany(selected_flights)) {
-                WARN(tr("Unable to delete. The following error has ocurred:<br><br>%1").arg(aDB->lastError.text()));
+            if (!DB->removeMany(OPL::DbTable::Flights, selectedEntries)) {
+                WARN(tr("Unable to delete. No changes have been made to the database. The following error has ocurred:<br><br>%1").arg(DB->lastError.text()));
                 return;
             }
             INFO(tr("%1 flights have been deleted successfully."

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

@@ -26,7 +26,7 @@
 #include <QMenu>
 #include <QTableView>
 #include "src/gui/widgets/settingswidget.h"
-#include "src/classes/acompletiondata.h"
+#include "src/database/dbcompletiondata.h"
 #include "src/opl.h"
 
 namespace Ui {
@@ -49,7 +49,7 @@ class LogbookWidget : public QWidget
     Q_OBJECT
 
 public:
-    explicit LogbookWidget(ACompletionData &completion_data, QWidget *parent = nullptr);
+    explicit LogbookWidget(OPL::DbCompletionData &completion_data, QWidget *parent = nullptr);
     ~LogbookWidget();
 
 private slots:
@@ -82,14 +82,14 @@ private:
 
     QMenu* menu;
 
-    QVector<qint32> selectedEntries;
+    QList<int> selectedEntries;
 
     void setupModelAndView(int view_id);
     void connectSignalsAndSlots();
 
     const QString getFlightSummary(const OPL::FlightEntry &flight) const;
 
-    ACompletionData completionData;
+    OPL::DbCompletionData completionData;
 
     /*!
      * \brief isFlight Determines whether an entry shown in a view is a Flight or a Simulator.

+ 8 - 8
src/gui/widgets/pilotswidget.cpp

@@ -19,8 +19,8 @@
 #include "ui_pilotswidget.h"
 #include "src/opl.h"
 #include "src/functions/alog.h"
-#include "src/database/adatabase.h"
-#include "src/classes/row.h"
+#include "src/database/database.h"
+#include "src/database/row.h"
 
 PilotsWidget::PilotsWidget(QWidget *parent) :
     QWidget(parent),
@@ -165,7 +165,7 @@ void PilotsWidget::on_deletePilotButton_clicked()
         /// I think batch-editing should be implemented at some point, but batch-deleting should not.
 
     } else if (selectedPilots.length() == 1) {
-        auto entry = aDB->getPilotEntry(selectedPilots.first());
+        auto entry = DB->getPilotEntry(selectedPilots.first());
         QMessageBox confirm(this);
         confirm.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
         confirm.setDefaultButton(QMessageBox::No);
@@ -175,7 +175,7 @@ void PilotsWidget::on_deletePilotButton_clicked()
         confirm.setText(tr("You are deleting the following pilot:<br><br><b><tt>"
                                "%1</b></tt><br><br>Are you sure?").arg(getPilotName(entry)));
         if (confirm.exec() == QMessageBox::Yes) {
-            if(!aDB->remove(entry))
+            if(!DB->remove(entry))
                 onDeleteUnsuccessful();
         }
     }
@@ -195,16 +195,16 @@ void PilotsWidget::on_deletePilotButton_clicked()
  */
 void PilotsWidget::onDeleteUnsuccessful()
 {
-    const QList<int> foreign_key_constraints = aDB->getForeignKeyConstraints(selectedPilots.first(),
-                                                                       ADatabaseTable::pilots);
+    const QList<int> foreign_key_constraints = DB->getForeignKeyConstraints(selectedPilots.first(),
+                                                                       OPL::DbTable::Pilots);
     QList<OPL::FlightEntry> constrained_flights;
     for (const auto &row_id : foreign_key_constraints) {
-        constrained_flights.append(aDB->getFlightEntry(row_id));
+        constrained_flights.append(DB->getFlightEntry(row_id));
     }
 
     if (constrained_flights.isEmpty()) {
         WARN(tr("<br>Unable to delete.<br><br>The following error has ocurred:<br>%1"
-                               ).arg(aDB->lastError.text()));
+                               ).arg(DB->lastError.text()));
         return;
     } else {
         QString constrained_flights_string;

+ 19 - 19
src/gui/widgets/settingswidget.cpp

@@ -20,8 +20,8 @@
 #include "src/functions/alog.h"
 #include "src/classes/astyle.h"
 #include "src/classes/asettings.h"
-#include "src/database/adatabase.h"
-#include "src/classes/row.h"
+#include "src/database/database.h"
+#include "src/database/row.h"
 #include "src/opl.h"
 #include "src/functions/adate.h"
 
@@ -84,7 +84,7 @@ void SettingsWidget::setupDateEdits()
     };
     for (const auto &pair : currencies_list) {
         const QSignalBlocker signal_blocker(pair.second);
-        const auto entry = aDB->getCurrencyEntry(static_cast<int>(pair.first));
+        const auto entry = DB->getCurrencyEntry(static_cast<int>(pair.first));
         if (entry.isValid()) { // set date
             const auto date = QDate::fromString(
                         entry.getData().value(OPL::Db::CURRENCIES_EXPIRYDATE).toString(),
@@ -105,7 +105,7 @@ void SettingsWidget::readSettings()
     //const QSignalBlocker blocker(this); // don't emit editing finished for setting these values
 
     // Personal Data Tab
-    auto user_data = aDB->getPilotEntry(1).getData();
+    auto user_data = DB->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());
@@ -212,8 +212,8 @@ void SettingsWidget::updatePersonalDetails()
     TODO << "Changing DB does not currently refresh logbook view";
     TODO << "Check for empty line edits (First, last name should not be empty...validators not a good way because it gives no user feedback)";
 
-    if(!aDB->commit(user))
-        WARN(tr("Unable to update Database:<br>") + aDB->lastError.text());
+    if(!DB->commit(user))
+        WARN(tr("Unable to update Database:<br>") + DB->lastError.text());
     else
         LOG << "User updated successfully.";
 
@@ -333,7 +333,7 @@ void SettingsWidget::on_aboutPushButton_clicked()
     QMessageBox message_box(this);
     QPixmap icon = QPixmap(OPL::Assets::ICON_MAIN);
     message_box.setIconPixmap(icon.scaledToWidth(64, Qt::TransformationMode::SmoothTransformation));
-    QString SQLITE_VERSION = aDB->sqliteVersion();
+    QString SQLITE_VERSION = DB->sqliteVersion();
     QString text = QMessageBox::tr(
 
                        "<h3><center>About</center></h3>"
@@ -475,8 +475,8 @@ void SettingsWidget::on_currLicDateEdit_userDateChanged(const QDate &date)
 {
     const RowData_T row_data = {{OPL::Db::CURRENCIES_EXPIRYDATE, date.toString(Qt::ISODate)}};
     const OPL::CurrencyEntry entry(static_cast<int>(OPL::CurrencyName::Licence), row_data);
-    if (!aDB->commit(entry))
-        WARN(tr("Unable to update currency. The following error has ocurred:<br>%1").arg(aDB->lastError.text()));
+    if (!DB->commit(entry))
+        WARN(tr("Unable to update currency. The following error has ocurred:<br>%1").arg(DB->lastError.text()));
 
     emit settingChanged(HomeWidget);
 }
@@ -485,8 +485,8 @@ void SettingsWidget::on_currTrDateEdit_userDateChanged(const QDate &date)
 {
     const RowData_T row_data = {{OPL::Db::CURRENCIES_EXPIRYDATE, date.toString(Qt::ISODate)}};
     const OPL::CurrencyEntry entry(static_cast<int>(OPL::CurrencyName::TypeRating), row_data);
-    if (!aDB->commit(entry))
-        WARN(tr("Unable to update currency. The following error has ocurred:<br>%1").arg(aDB->lastError.text()));
+    if (!DB->commit(entry))
+        WARN(tr("Unable to update currency. The following error has ocurred:<br>%1").arg(DB->lastError.text()));
 
     emit settingChanged(HomeWidget);
 }
@@ -495,8 +495,8 @@ void SettingsWidget::on_currLckDateEdit_userDateChanged(const QDate &date)
 {
     const RowData_T row_data = {{OPL::Db::CURRENCIES_EXPIRYDATE, date.toString(Qt::ISODate)}};
     const OPL::CurrencyEntry entry(static_cast<int>(OPL::CurrencyName::LineCheck), row_data);
-    if (!aDB->commit(entry))
-        WARN(tr("Unable to update currency. The following error has ocurred:<br>%1").arg(aDB->lastError.text()));
+    if (!DB->commit(entry))
+        WARN(tr("Unable to update currency. The following error has ocurred:<br>%1").arg(DB->lastError.text()));
 
     emit settingChanged(HomeWidget);
 }
@@ -505,8 +505,8 @@ void SettingsWidget::on_currMedDateEdit_userDateChanged(const QDate &date)
 {
     const RowData_T row_data = {{OPL::Db::CURRENCIES_EXPIRYDATE, date.toString(Qt::ISODate)}};
     const OPL::CurrencyEntry entry(static_cast<int>(OPL::CurrencyName::Medical), row_data);
-    if (!aDB->commit(entry))
-        WARN(tr("Unable to update currency. The following error has ocurred:<br>%1").arg(aDB->lastError.text()));
+    if (!DB->commit(entry))
+        WARN(tr("Unable to update currency. The following error has ocurred:<br>%1").arg(DB->lastError.text()));
 
     emit settingChanged(HomeWidget);
 }
@@ -517,8 +517,8 @@ void SettingsWidget::on_currCustom1DateEdit_userDateChanged(const QDate &date)
                                 {OPL::Db::CURRENCIES_CURRENCYNAME, ui->currCustom1LineEdit->text()}};
     const OPL::CurrencyEntry entry(static_cast<int>(OPL::CurrencyName::Custom1), row_data);
     DEB << entry;
-    if (!aDB->commit(entry))
-        WARN(tr("Unable to update currency. The following error has ocurred:<br><br>%1").arg(aDB->lastError.text()));
+    if (!DB->commit(entry))
+        WARN(tr("Unable to update currency. The following error has ocurred:<br><br>%1").arg(DB->lastError.text()));
 
     emit settingChanged(HomeWidget);
 }
@@ -528,8 +528,8 @@ void SettingsWidget::on_currCustom2DateEdit_userDateChanged(const QDate &date)
     const RowData_T row_data = {{OPL::Db::CURRENCIES_EXPIRYDATE, date.toString(Qt::ISODate)},
                                 {OPL::Db::CURRENCIES_CURRENCYNAME, ui->currCustom2LineEdit->text()}};
     const OPL::CurrencyEntry entry(static_cast<int>(OPL::CurrencyName::Custom2), row_data);
-    if (!aDB->commit(entry))
-        WARN(tr("Unable to update currency. The following error has ocurred:<br><br>%1").arg(aDB->lastError.text()));
+    if (!DB->commit(entry))
+        WARN(tr("Unable to update currency. The following error has ocurred:<br><br>%1").arg(DB->lastError.text()));
 
     emit settingChanged(HomeWidget);
 }

+ 3 - 2
src/opl.h

@@ -21,7 +21,6 @@
 #include <QtCore>
 #include <QMessageBox>
 #include <QComboBox>
-#include "src/database/adatabasetypes.h"
 
 /*!
  *  \brief A namespace to collect constants and enums used throughout the application.
@@ -84,6 +83,8 @@ public:
     };
 }; // class ANotificationHandler
 
+using RowData_T = QHash<QString, QVariant>;
+
 /*!
  * \brief ADateFormats enumerates the accepted date formats for QDateEdits
  * \todo At the moment, only ISODate is accepet as a valid date format.
@@ -118,7 +119,7 @@ enum class SimulatorType {FNPTI = 0, FNPTII = 1, FSTD = 2};
 /*!
  * \brief Enumerates the tables in the database
  */
-enum class DbTable {Flights, Simulators, Pilots, Tails, Aircraft, Airports, Currencies};
+enum class DbTable {Flights, Simulators, Pilots, Tails, Aircraft, Airports, Currencies, Changelog};
 
 /*!
  * \brief Enumerates the currency names

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

@@ -1,7 +1,7 @@
 #include "importcrewlounge.h"
-#include "src/database/adatabase.h"
+#include "src/database/database.h"
 #include "src/opl.h"
-#include "src/classes/row.h"
+#include "src/database/row.h"
 #include "src/testing/importCrewlounge/processpilots.h"
 #include "src/testing/importCrewlounge/processaircraft.h"
 #include "src/testing/importCrewlounge/processflights.h"
@@ -13,7 +13,7 @@ namespace ImportCrewlounge
 void exec(const QString &csv_file_path)
 {
     // Inhibit HomeWindow Updating
-    QSignalBlocker blocker(aDB);
+    QSignalBlocker blocker(DB);
 
     // Prepare database and set up exclusive transaction for mass commit
     QSqlQuery q;
@@ -31,7 +31,7 @@ void exec(const QString &csv_file_path)
 
     for (const auto & pilot_data : p_maps) {
         OPL::PilotEntry pe(pilot_data.value(OPL::Db::PILOTS_ROWID).toInt(), pilot_data);
-        aDB->commit(pe);
+        DB->commit(pe);
     }
 
     // Process Tails
@@ -41,7 +41,7 @@ void exec(const QString &csv_file_path)
 
     for (const auto& tail_data : t_maps) {
         OPL::TailEntry te(tail_data.value(OPL::Db::PILOTS_ROWID).toInt(), tail_data);
-        aDB->commit(te);
+        DB->commit(te);
     }
 
     auto proc_flights = ProcessFlights(raw_csv_data,
@@ -54,7 +54,7 @@ void exec(const QString &csv_file_path)
 
     for (const auto &flight_data : flights) {
         OPL::FlightEntry fe(flight_data);
-        aDB->commit(fe);
+        DB->commit(fe);
     }
 
     // Commit the exclusive transaction
@@ -63,6 +63,6 @@ void exec(const QString &csv_file_path)
 
     // destroy blocker
     blocker.unblock();
-    emit aDB->dataBaseUpdated();
+    emit DB->dataBaseUpdated();
 }
 }// namespace ImportCrewLongue