浏览代码

Merge pull request #41 from fiffty-50/develop-firstrundialog-rework

ASettings mass refactor
Felix Turowsky 4 年之前
父节点
当前提交
64e984754f

+ 15 - 9
main.cpp

@@ -20,7 +20,7 @@
 #include "src/classes/arunguard.h"
 #include "src/database/adatabase.h"
 #include "src/classes/asettings.h"
-#include "src/astandardpaths.h"
+#include "src/classes/astandardpaths.h"
 #include "src/classes/asettings.h"
 #include <QApplication>
 #include <QProcess>
@@ -41,8 +41,8 @@ int main(int argc, char *argv[])
     QCoreApplication::setApplicationName(APPNAME);
 
     AStandardPaths::setup();
-    AStandardPaths::scan_paths();
-    if(!AStandardPaths::validate_paths()){
+    AStandardPaths::scan_dirs();
+    if(!AStandardPaths::validate_dirs()){
         DEB << "Standard paths not valid.";
         return 1;
     }
@@ -50,14 +50,20 @@ int main(int argc, char *argv[])
     ASettings::setup();
 
     aDB()->connect();
-
-    if (!ASettings::read("setup/setup_complete").toBool()) {
+    if (!ASettings::read(ASettings::Setup::SetupComplete).toBool()) {
         FirstRunDialog dialog;
-        dialog.exec();
+        if(dialog.exec() == QDialog::Rejected){
+            DEB "First run not accepted. Exiting.";
+            return 1;
+        }
+        ASettings::write(ASettings::Setup::SetupComplete, true);
+        DEB << "Wrote setup_commplete?";
+        qApp->quit();
+        QProcess::startDetached(qApp->arguments()[0], qApp->arguments());
     }
 
     //Theming
-    switch (ASettings::read("main/theme").toInt()) {
+    switch (ASettings::read(ASettings::Main::Theme).toInt()) {
     case 1:{
         DEB << "main :: Loading light theme";
         QFile file(":light.qss");
@@ -79,10 +85,10 @@ int main(int argc, char *argv[])
     }
 
     //sqlite does not deal well with multiple connections, ensure only one instance is running
-    ARunGuard guard("opl_single_key");
+    ARunGuard guard(QStringLiteral("opl_single_key"));
         if ( !guard.tryToRun() ){
             DEB << "Another Instance is already running. Exiting.";
-            return 0;
+            return 2;
         }
 
     MainWindow w;

+ 2 - 2
openPilotLog.pro

@@ -18,7 +18,7 @@ DEFINES += QT_DEPRECATED_WARNINGS
 SOURCES += \
     main.cpp \
     mainwindow.cpp \
-    src/astandardpaths.cpp \
+    src/classes/astandardpaths.cpp \
     src/classes/aaircraftentry.cpp \
     src/classes/adownload.cpp \
     src/classes/aentry.cpp \
@@ -48,7 +48,7 @@ SOURCES += \
 
 HEADERS += \
     mainwindow.h \
-    src/astandardpaths.h \
+    src/classes/astandardpaths.h \
     src/classes/aaircraftentry.h \
     src/classes/adownload.h \
     src/classes/aentry.h \

+ 0 - 45
src/astandardpaths.cpp

@@ -1,45 +0,0 @@
-#include "src/astandardpaths.h"
-
-QMap<QStandardPaths::StandardLocation, QString> AStandardPaths::paths;
-
-void AStandardPaths::setup()
-{
-    auto settings_location = QStandardPaths::AppConfigLocation;
-    auto data_location = QStandardPaths::AppDataLocation;
-    paths = {
-        {settings_location, QStandardPaths::writableLocation(settings_location)},
-        {data_location, QStandardPaths::writableLocation(data_location)},
-    };
-}
-
-QString AStandardPaths::getPath(QStandardPaths::StandardLocation loc)
-{
-    return paths[loc];
-}
-
-QMap<QStandardPaths::StandardLocation, QString> AStandardPaths::getPaths()
-{
-    return paths;
-}
-
-void AStandardPaths::scan_paths()
-{
-    for(auto& path : paths.values()){
-        auto dir = QDir(path);
-        DEB << "Scanning " << dir.path();
-        if(!dir.exists()) {
-            DEB <<"Creating " << dir.path();
-            dir.mkpath(path);
-        }
-    }
-}
-
-bool AStandardPaths::validate_paths()
-{
-    for(auto& path : paths.values()){
-        DEB << "Validating " << path;
-        if(false)  // determine path as valid (scan contents and parse for correctness)
-            return false;
-    }
-    return true;
-}

+ 0 - 34
src/astandardpaths.h

@@ -1,34 +0,0 @@
-#ifndef ASTANDARDPATHS_H
-#define ASTANDARDPATHS_H
-
-#include "src/testing/adebug.h"
-#include <QStandardPaths>
-#include <QString>
-#include <QMap>
-#include <QDir>
-
-/*!
- * \brief The AStandardAppPaths class encapsulates a static QMap holding
- * the standard paths of the application. Setup should be called after
- * `QCoreApplication::setWhateverName`.
- */
-class AStandardPaths{
-private:
-    static
-    QMap<QStandardPaths::StandardLocation, QString> paths;
-public:
-    /// Initialise paths with corresponding StandardLocation paths
-    static void setup();
-
-    static QString getPath(QStandardPaths::StandardLocation loc);
-    static QMap<QStandardPaths::StandardLocation, QString> getPaths();
-
-    /// Ensure standard app paths exist, if not mkdir them.
-    static void scan_paths();
-
-    /// Validate standard app paths are valid in structure and contents.
-    static bool validate_paths();
-};
-
-
-#endif // ASTANDARDPATHS_H

+ 130 - 12
src/classes/asettings.cpp

@@ -16,26 +16,144 @@
  *along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 #include "asettings.h"
-#include "src/astandardpaths.h"
+#include "astandardpaths.h"
 #include <QSettings>
 
+
+QMap<ASettings::Main, QString> ASettings::mainMap = {
+    {Main::Theme,   QStringLiteral("theme")},
+};
+
+QMap<ASettings::LogBook, QString> ASettings::logBookMap = {
+    {LogBook::View, QStringLiteral("view")},
+};
+
+QMap<ASettings::UserData, QString> ASettings::userDataMap = {
+    {UserData::LastName,          QStringLiteral("lastname")},
+    {UserData::FirstName,         QStringLiteral("firstname") },
+    {UserData::Company,           QStringLiteral("company")},
+    {UserData::EmployeeID,        QStringLiteral("employeeid")},
+    {UserData::Phone,             QStringLiteral("phone")},
+    {UserData::Email,             QStringLiteral("email")},
+    {UserData::DisplaySelfAs,     QStringLiteral("displayselfas")},
+    {UserData::Alias,             QStringLiteral("alias")},
+    {UserData::AcSortColumn,      QStringLiteral("acSortColumn")},  // [G]: inconsistent naming
+    {UserData::PilSortColumn,     QStringLiteral("pilSortColumn")},
+    {UserData::AcAllowIncomplete, QStringLiteral("acAllowIncomplete")},
+};
+
+QMap<ASettings::FlightLogging, QString> ASettings::flightLoggingMap = {
+    {FlightLogging::Function,           QStringLiteral("function")},
+    {FlightLogging::Approach,           QStringLiteral("approach")},
+    {FlightLogging::NightLogging,       QStringLiteral("nightlogging")},
+    {FlightLogging::LogIFR,             QStringLiteral("logIfr")},
+    {FlightLogging::FlightNumberPrefix, QStringLiteral("flightnumberPrefix")},
+    {FlightLogging::NumberTakeoffs,     QStringLiteral("numberTakeoffs")},
+    {FlightLogging::NumberLandings,     QStringLiteral("numberLandings")},
+    {FlightLogging::PopupCalendar,      QStringLiteral("popupCalendar")},
+    {FlightLogging::PilotFlying,        QStringLiteral("pilotFlying")},
+    {FlightLogging::NightAngle,         QStringLiteral("nightangle")},
+    {FlightLogging::Rules,              QStringLiteral("rules")},
+};
+
+QMap<ASettings::Setup, QString> ASettings::setupMap = {
+    {Setup::SetupComplete, QStringLiteral("setup_complete")},  // inconsistent naming
+};
+
+QMap<ASettings::NewFlight, QString> ASettings::newFlightMap = {
+    {NewFlight::FunctionComboBox, QStringLiteral("FunctionComboBox")},  // inconsistent naming
+    {NewFlight::CalendarCheckBox, QStringLiteral("calendarCheckBox")},
+};
+
 void ASettings::setup()
 {
     QSettings::setDefaultFormat(QSettings::IniFormat);
     QSettings();
 }
 
-QVariant ASettings::read(const QString &key)
-{
-    return QSettings().value(key);
-}
+//
+// Read/Write
+//
+
+QVariant ASettings::read(const FlightLogging key)
+{ return QSettings().value(groupOfKey(key)); }
+
+void ASettings::write(const FlightLogging key, const QVariant &val)
+{ QSettings().setValue(groupOfKey(key), val); }
+
+QVariant ASettings::read(const LogBook key)
+{ return QSettings().value(groupOfKey(key)); }
+
+void ASettings::write(const LogBook key, const QVariant &val)
+{ QSettings().setValue(groupOfKey(key), val); }
+
+QVariant ASettings::read(const Main key)
+{ return QSettings().value(groupOfKey(key)); }
+
+void ASettings::write(const Main key, const QVariant &val)
+{ QSettings().setValue(groupOfKey(key), val); }
+
+QVariant ASettings::read(const Setup key)
+{ return QSettings().value(groupOfKey(key)); }
+
+void ASettings::write(const Setup key, const QVariant &val)
+{ QSettings().setValue(groupOfKey(key), val); }
+
+QVariant ASettings::read(const NewFlight key)
+{ return QSettings().value(groupOfKey(key)); }
+
+void ASettings::write(const NewFlight key, const QVariant &val)
+{ QSettings().setValue(groupOfKey(key), val); }
+
+QVariant ASettings::read(const UserData key)
+{ return QSettings().value(groupOfKey(key)); }
+
+void ASettings::write(const UserData key, const QVariant &val)
+{ QSettings().setValue(groupOfKey(key), val); }
+
+//
+// QString conversion PATH
+//
+QString ASettings::groupOfKey (const ASettings::FlightLogging key)
+{ return QStringLiteral("flightlogging/") + flightLoggingMap[key]; }
+
+QString ASettings::groupOfKey (const ASettings::LogBook key)
+{ return QStringLiteral("logbook/") + logBookMap[key]; }
+
+QString ASettings::groupOfKey (const ASettings::Main key)
+{ return QStringLiteral("main/") + mainMap[key]; }
+
+QString ASettings::groupOfKey (const ASettings::NewFlight key)
+{ return QStringLiteral("NewFlight/") + newFlightMap[key]; }
+
+QString ASettings::groupOfKey (const ASettings::Setup key)
+{ return QStringLiteral("setup/") + setupMap[key]; }
+
+QString ASettings::groupOfKey (const ASettings::UserData key)
+{ return QStringLiteral("userdata/") + userDataMap[key]; }
+
+//
+// QString conversion ONLY KEY
+//
+QString ASettings::stringOfKey (const ASettings::FlightLogging key)
+{ return  flightLoggingMap[key]; }
+
+QString ASettings::stringOfKey (const ASettings::LogBook key)
+{ return  logBookMap[key]; }
+
+QString ASettings::stringOfKey (const ASettings::Main key)
+{ return  mainMap[key]; }
+
+QString ASettings::stringOfKey (const ASettings::NewFlight key)
+{ return  newFlightMap[key]; }
+
+QString ASettings::stringOfKey (const ASettings::Setup key)
+{ return  setupMap[key]; }
+
+QString ASettings::stringOfKey (const ASettings::UserData key)
+{ return  userDataMap[key]; }
+
 
-void ASettings::write(const QString &key, const QVariant &val)
-{
-    QSettings().setValue(key, val);
-}
 
 QSettings ASettings::settings()
-{
-    return QSettings();
-}
+{ return QSettings(); }

+ 170 - 10
src/classes/asettings.h

@@ -24,20 +24,180 @@
  * \brief Thin (namespace) wrapper for the QSettings class,
  * simplifying reading and writing of settings.
  */
-namespace ASettings
-{
+class ASettings {
+public:
+    enum class Setup {
+        SetupComplete,
+    };
 
-/*!
- * \brief Should be called after QCoreApplication::set...Name have been called.
- */
-void setup();
+    enum class Main {
+        Theme,
+    };
+
+    enum class LogBook {
+        View,
+    };
+
+    enum class UserData {
+        LastName,
+        FirstName,
+        Company,
+        EmployeeID,
+        Phone,
+        Email,
+        DisplaySelfAs,
+        Alias,
+        AcSortColumn, // not sure what ac is
+        PilSortColumn,
+        AcAllowIncomplete,
+    };
+
+    enum class FlightLogging {
+        Function,
+        Approach,
+        NightLogging,
+        LogIFR,
+        FlightNumberPrefix,
+        NumberTakeoffs,
+        NumberLandings,
+        PopupCalendar,
+        PilotFlying,
+        NightAngle,
+        Rules,
+    };
+
+    enum class NewFlight {
+        FunctionComboBox,
+        CalendarCheckBox,
+    };
+
+    /*!
+     * \brief Should be called after QCoreApplication::set...Name have been called.
+     */
+    static void setup();
+
+    static QVariant read(const Setup key);
+    static void write(const Setup key, const QVariant &val);
+
+    static QVariant read(const LogBook key);
+    static void write(const LogBook key, const QVariant &val);
+
+    static QVariant read(const Main key);
+    static void write(const Main key, const QVariant &val);
+
+    static QVariant read(const FlightLogging key);
+    static void write(const UserData key, const QVariant &val);
+
+    static QVariant read(const UserData key);
+    static void write(const FlightLogging key, const QVariant &val);
+
+    static QVariant read(const NewFlight key);
+    static void write(const NewFlight key, const QVariant &val);
+
+    // [G]: enum class may be making it abit too strict perhaps?
+    // a workaround is to use plain enums and have one function takes an int
+    // All enums should be unique of course thats easy. See At the end of the file
+    // for details
+    /*!
+     * \brief Return string representation of group of key: "ini_header/key"
+     */
+    static QString groupOfKey(const Main key);
+    static QString groupOfKey(const LogBook key);
+    static QString groupOfKey(const NewFlight key);
+    static QString groupOfKey(const FlightLogging key);
+    static QString groupOfKey(const Setup key);
+    static QString groupOfKey(const UserData key);
+
+    /*!
+     * \brief Return string representation of key
+     */
+    static QString stringOfKey(const Main key);
+    static QString stringOfKey(const LogBook key);
+    static QString stringOfKey(const NewFlight key);
+    static QString stringOfKey(const FlightLogging key);
+    static QString stringOfKey(const Setup key);
+    static QString stringOfKey(const UserData key);
+
+    static QSettings settings();
+
+private:
+    static QMap<Main, QString> mainMap;
+    static QMap<LogBook, QString> logBookMap;
+    static QMap<UserData, QString> userDataMap;
+    static QMap<FlightLogging, QString> flightLoggingMap;
+    static QMap<Setup, QString> setupMap;
+    static QMap<NewFlight, QString> newFlightMap;
+
+#define FOR_CURRENT_VERSION 0
+#if (FOR_CURRENT_VERSION)
+    /* By default unless specified each enum is + 1.
+       If we are interested in doing multiple returns at once then
+       we should make them so that the can be OR-ed.
+
+        That means that in binary this means that
+        every new enum has only 1 bit on
+        that bit is always moving to the left
+    */
+    enum Setup2 {
+        SetupComplete       = 0x00'00'00'01,  // If this makes no sense look up hexadecimals
+    };                                        // the ' is legal in numbers it is ignored
+                                              // used only for reader convinience
+    enum Main2 {
+        Theme               = 0x00'00'00'02,
+        ThemeID             = 0x00'00'00'04,
+    };
+
+    enum LogBook2 {
+        View                = 0x00'00'00'08,
+    };
+
+    enum UserData2 {
+        LastName            = 0x00'00'00'10,
+        FirstName           = 0x00'00'00'20,
+        Company             = 0x00'00'00'40,
+        EmployeeID          = 0x00'00'00'80,
+        Phone               = 0x00'00'01'00,
+        Email               = 0x00'00'02'00,
+        DisplaySelfAs       = 0x00'00'04'00,
+        Alias               = 0x00'00'08'00,
+        AcSortColumn        = 0x00'00'10'00,
+        PilSortColumn       = 0x00'00'20'00,
+        AcAllowIncomplete   = 0x00'00'40'00,
+    };
+
+    enum FlightLogging2 {
+        Function            = 0x00'00'80'00,
+        Approach            = 0x00'01'00'00,
+        NightLogging        = 0x00'02'00'00,
+        LogIFR              = 0x00'04'00'00,
+        FlightNumberPrefix  = 0x00'08'00'00,
+        NumberTakeoffs      = 0x00'10'00'00,
+        NumberLandings      = 0x00'20'00'00,
+        PopupCalendar       = 0x00'40'00'00,
+        PilotFlying         = 0x00'80'00'00,
+        NightAngle          = 0x01'00'00'00,
+        Rules               = 0x02'00'00'00,
+    };
 
-QVariant read(const QString &key);
+    enum NewFlight2 {
+        FunctionComboBox    = 0x04'00'00'00,
+        CalendarCheckBox    = 0x08'00'00'00,
+    };
 
-void write(const QString &key, const QVariant &val);
+    using Key = int;
+    using Keys = int;
+    /*
+     * Used like QMessageBox buttons;
+     *
+     * auto str = stringOfKey2(ASettings::Setup);
+     * auto strlist = stringOfKeys2(ASettings::Setup | ASettings::Function)
+     */
+    QString stringOfKey2(Key k);
+    QStringList stringOfKeys2(Keys ks);
 
-QSettings settings();
+#endif
+#undef FOR_CURRENT_VERSION
 
-}
+};
 
 #endif // ASETTINGS_H

+ 49 - 0
src/classes/astandardpaths.cpp

@@ -0,0 +1,49 @@
+#include "src/classes/astandardpaths.h"
+
+//QMap<QStandardPaths::StandardLocation, QString> AStandardPaths::paths;
+QMap<AStandardPaths::Dirs, QString> AStandardPaths::dirs;
+
+void AStandardPaths::setup()
+{
+    auto settings_location = QStandardPaths::AppConfigLocation;
+    auto data_location = QStandardPaths::AppDataLocation;
+    dirs = {  // [G]: potential rename to `dirs`
+        {Database, QStandardPaths::writableLocation(data_location)},
+        {Templates, QDir(QStandardPaths::writableLocation(data_location)).filePath("templates")},
+        {Settings, QStandardPaths::writableLocation(settings_location)},
+        {DatabaseBackup, QDir(QStandardPaths::writableLocation(data_location)).filePath("backup")}
+    };
+    DEB << "Paths created: " << dirs;
+}
+
+const QString& AStandardPaths::absPathOf(Dirs loc)
+{
+    return dirs[loc];
+}
+
+const QMap<AStandardPaths::Dirs, QString>& AStandardPaths::allPaths()
+{
+    return dirs;
+}
+
+void AStandardPaths::scan_dirs()
+{
+    for(auto& dir : dirs){
+        auto d = QDir(dir);
+        DEB << "Scanning " << d.path();
+        if(!d.exists()) {
+            DEB <<"Creating " << d.path();
+            d.mkpath(dir);
+        }
+    }
+}
+
+bool AStandardPaths::validate_dirs()
+{
+    for(auto& dir : dirs){
+        DEB << "Validating " << dir;
+        if(false)  // determine path as valid (scan contents and parse for correctness)
+            return false;
+    }
+    return true;
+}

+ 44 - 0
src/classes/astandardpaths.h

@@ -0,0 +1,44 @@
+#ifndef ASTANDARDPATHS_H
+#define ASTANDARDPATHS_H
+
+#include "src/testing/adebug.h"
+#include <QStandardPaths>
+#include <QString>
+#include <QMap>
+#include <QDir>
+
+/*!
+ * \brief The AStandardAppPaths class encapsulates a static QMap holding
+ * the standard paths of the application. Setup should be called after
+ * `QCoreApplication::setWhateverName`.
+ */
+class AStandardPaths{
+public:
+    enum Dirs {
+        Database,
+        Templates,
+        Settings,
+        DatabaseBackup
+    };
+private:
+    static QMap<Dirs, QString> dirs;
+public:
+    /// Initialise paths with corresponding StandardLocation paths
+    static void setup();
+
+    // [G]: Subjective opinion:
+    // We should move away from getThis getThat functions.
+    // I believe we can give better namings while avoiding this
+    // OOP cliche of getEverything
+    static const QString& absPathOf(Dirs loc);
+    static const QMap<Dirs, QString>& allPaths();
+
+    /// Ensure standard app directories exist, if not mkpath them.
+    static void scan_dirs();
+
+    /// Validate standard app directories are valid in structure and contents.
+    static bool validate_dirs();
+};
+
+
+#endif // ASTANDARDPATHS_H

+ 7 - 6
src/database/adatabase.cpp

@@ -17,7 +17,7 @@
  */
 #include "adatabase.h"
 #include "src/testing/adebug.h"
-#include "src/astandardpaths.h"
+#include "src/classes/astandardpaths.h"
 
 #define DATABASE_VERSION 15
 const auto SQL_DRIVER = QStringLiteral("QSQLITE");
@@ -50,6 +50,11 @@ ADatabase* ADatabase::getInstance()
     return instance;
 }
 
+ADatabase::ADatabase()
+    : databaseDir(QDir(AStandardPaths::absPathOf(AStandardPaths::Database))),
+      databaseFile(QFileInfo(databaseDir.filePath(QStringLiteral("logbook.db"))))
+{}
+
 /*!
  * \brief ADatabase::sqliteVersion returns database sqlite version.
  * \return sqlite version string
@@ -68,12 +73,8 @@ bool ADatabase::connect()
     if (!QSqlDatabase::isDriverAvailable(SQL_DRIVER))
         return false;
 
-    QString path = AStandardPaths::getPath(QStandardPaths::AppDataLocation);
-    QDir directory(path);
-    // [G]: Where would it make sense to define the database file?. In the class perhaps?
-    QString databaseLocation = directory.filePath(QStringLiteral("logbook.db"));
     QSqlDatabase db = QSqlDatabase::addDatabase(SQL_DRIVER);
-    db.setDatabaseName(databaseLocation);
+    db.setDatabaseName(databaseFile.absoluteFilePath());
 
     if (!db.open())
         return false;

+ 4 - 1
src/database/adatabase.h

@@ -37,6 +37,7 @@
 #include "src/classes/atailentry.h"
 #include "src/classes/aaircraftentry.h"
 #include "src/classes/aflightentry.h"
+#include "src/classes/astandardpaths.h"
 
 /*!
  * \brief The DBTarget enum lists database items that are
@@ -79,7 +80,7 @@ private:
     TableNames tableNames;
     TableColumns tableColumns;
     static ADatabase* instance;
-    ADatabase() = default;
+    ADatabase();
 public:
     // Ensure DB is not copiable or assignable
     ADatabase(const ADatabase&) = delete;
@@ -90,6 +91,8 @@ public:
     const QString sqliteVersion();
 
     ADatabaseError lastError;
+    const QDir databaseDir;
+    const QFileInfo databaseFile;
 
     /*!
      * \brief Connect to the database and populate database information.

+ 48 - 9
src/database/adatabasesetup.cpp

@@ -19,7 +19,8 @@
 #include "src/database/adatabase.h"
 #include "src/testing/adebug.h"
 #include "src/functions/areadcsv.h"
-
+#include "src/classes/astandardpaths.h"
+#include "src/classes/adownload.h"
 
 // Statements for creation of database tables, Revision 15
 
@@ -278,6 +279,42 @@ bool ADataBaseSetup::createDatabase()
     return true;
 }
 
+bool ADataBaseSetup::downloadTemplates()
+{
+    QDir template_dir(AStandardPaths::absPathOf(AStandardPaths::Templates));
+    DEB << template_dir;
+    for (const auto& table : templateTables) {
+        QEventLoop loop;
+        ADownload* dl = new ADownload;
+        QObject::connect(dl, &ADownload::done, &loop, &QEventLoop::quit );
+        dl->setTarget(QUrl(TEMPLATE_URL % table % QStringLiteral(".csv")));
+        dl->setFileName(template_dir.filePath(table % QStringLiteral(".csv")));
+        dl->download();
+        loop.exec(); // event loop waits for download done signal before allowing loop to continue
+        dl->deleteLater();
+    }
+    return true;
+}
+bool ADataBaseSetup::backupOldData()
+{
+    auto database_file = aDB()->databaseFile;
+    if(!database_file.exists()) {
+        DEB << "No Database to backup, returning.";
+        return true;
+    }
+
+    auto date_string = QDateTime::currentDateTime().toString(Qt::ISODate);
+    auto backup_dir = QDir(AStandardPaths::absPathOf(AStandardPaths::DatabaseBackup));
+    auto backup_name = database_file.baseName() + "-backup-" + date_string + ".bak";
+    auto file = QFile(aDB()->databaseFile.absoluteFilePath());
+
+    if (!file.rename(backup_dir.absolutePath() + '/' + backup_name)) {
+        DEB << "Unable to backup old database.";
+        return false;
+    }
+    DEB << "Backed up old database as: " << backup_name;
+    return true;
+}
 
 bool ADataBaseSetup::importDefaultData()
 {
@@ -290,7 +327,10 @@ bool ADataBaseSetup::importDefaultData()
             DEB << "Error: " << query.lastError().text();
         }
         //fill with data from csv
-        if (!commitData(aReadCsv("data/templates/" + table + ".csv"), table)) {
+        if (!commitData(aReadCsv(AStandardPaths::absPathOf(AStandardPaths::Templates)
+                                 % QLatin1Char('/')
+                                 % table % QStringLiteral(".csv")),
+                        table)) {
             DEB << "Error importing data.";
             return false;
         }
@@ -352,21 +392,20 @@ bool ADataBaseSetup::createSchemata(const QStringList &statements)
         if(!query.isActive()) {
             errors << statement.section(QLatin1Char(' '),2,2) + " ERROR - " + query.lastError().text();
             DEB << "Query: " << query.lastQuery();
-        } else {
-            DEB << "Schema added: " << statement.section(QLatin1Char(' '),2,2);
+            continue;
         }
+        DEB << "Schema added: " << statement.section(QLatin1Char(' '), 2, 2);
     }
 
     if (!errors.isEmpty()) {
-        DEB << "The following errors have ocurred: ";
+        DEB_SRC << "The following errors have ocurred: ";
         for (const auto& error : errors) {
-            DEB << error;
+            DEB_RAW << error;
         }
         return false;
-    } else {
-        DEB << "All schemas added successfully";
-        return true;
     }
+    DEB << "All schemas added successfully";
+    return true;
 }
 /*!
  * \brief DbSetup::commitData inserts the data parsed from a csv file into the

+ 8 - 0
src/database/adatabasesetup.h

@@ -19,6 +19,10 @@
 #define DBSETUP_H
 
 #include <QCoreApplication>
+#include <QStringBuilder>
+#include <QEventLoop>
+
+const auto TEMPLATE_URL = QStringLiteral("https://raw.githubusercontent.com/fiffty-50/openpilotlog/develop/assets/database/templates/");
 
 /*!
  * \brief The ADataBaseSetup class is responsible for the inital setup of the database when
@@ -33,6 +37,10 @@ public:
 
     static bool createDatabase();
 
+    static bool downloadTemplates();
+
+    static bool backupOldData();
+
     static bool fillTemplates();
 
     static bool importDefaultData();

+ 1 - 1
src/functions/acalc.cpp

@@ -303,7 +303,7 @@ void ACalc::updateAutoTimes(int acft_id)
  */
 void ACalc::updateNightTimes()
 {
-    const int night_angle = ASettings::read(QStringLiteral("flightlogging/nightangle")).toInt();
+    const int night_angle = ASettings::read(ASettings::FlightLogging::NightAngle).toInt();
 
     //find all flights for aircraft
     auto statement = "SELECT ROWID FROM flights";

+ 116 - 122
src/gui/dialogues/firstrundialog.cpp

@@ -6,15 +6,17 @@
 #include "src/classes/apilotentry.h"
 #include "src/classes/adownload.h"
 #include "src/classes/asettings.h"
-const auto TEMPLATE_URL = QLatin1String("https://raw.githubusercontent.com/fiffty-50/openpilotlog/develop/assets/database/templates/");
+#include "src/classes/astandardpaths.h"
+#include <QErrorMessage>
 
 FirstRunDialog::FirstRunDialog(QWidget *parent) :
     QDialog(parent),
     ui(new Ui::FirstRunDialog)
 {
     ui->setupUi(this);
-    ui->tabWidget->setCurrentIndex(0);
+    ui->stackedWidget->setCurrentIndex(0);
     ui->lastnameLineEdit->setFocus();
+    ui->previousPushButton->setEnabled(false);
     ui->nightComboBox->setCurrentIndex(1);
 
     auto *themeGroup = new QButtonGroup;
@@ -33,149 +35,141 @@ FirstRunDialog::~FirstRunDialog()
 
 void FirstRunDialog::on_previousPushButton_clicked()
 {
-    if(ui->tabWidget->currentIndex()>0)
-        ui->tabWidget->setCurrentIndex(ui->tabWidget->currentIndex()-1);
+    auto current_idx = ui->stackedWidget->currentIndex();
+    switch (current_idx) {
+    case 0:
+        return;
+    case 1:
+        ui->previousPushButton->setEnabled(false);
+        break;
+    case 2:
+        ui->nextPushButton->setText(QStringLiteral("Next"));
+        break;
+    }
+    ui->stackedWidget->setCurrentIndex(current_idx - 1);
+
 }
 
 void FirstRunDialog::on_nextPushButton_clicked()
 {
-    if(ui->tabWidget->currentIndex()<2){
-        ui->tabWidget->setCurrentIndex(ui->tabWidget->currentIndex()+1);
-    } else {
-        emit ui->finishButton->clicked();
+    auto current_idx = ui->stackedWidget->currentIndex();
+    // [G]: per index do appropriate error handling
+    switch (current_idx) {
+    case 0:
+        if(ui->firstnameLineEdit->text().isEmpty()
+           || ui->lastnameLineEdit->text().isEmpty())
+        {
+            QMessageBox(QMessageBox::Warning, QStringLiteral("Error"),
+                        QStringLiteral("Please enter first and last name")
+                        ).exec();
+            return;
+        }
+        ui->previousPushButton->setEnabled(true);
+        break;
+    case 1:
+        ui->nextPushButton->setText(QStringLiteral("Done"));
+        break;
+    case 2:
+        if(!finish())
+            QDialog::reject();
+        else
+            QDialog::accept();
+        return;
     }
-
+    ui->stackedWidget->setCurrentIndex(current_idx + 1);
 }
 
 void FirstRunDialog::on_themeGroup_toggled(int id)
 {
-    ASettings::write("main/theme", id);
+    ASettings::write(ASettings::Main::Theme, id);
 }
 
-void FirstRunDialog::on_finishButton_clicked()
+bool FirstRunDialog::finish()
 {
-    if(ui->lastnameLineEdit->text().isEmpty() || ui->firstnameLineEdit->text().isEmpty()){
-        auto mb = new QMessageBox(this);
-        mb->setText("You have to enter a valid first and last name for the logbook.");
-        mb->show();
-    } else {
-        ASettings::write("userdata/lastname", ui->lastnameLineEdit->text());
-        ASettings::write("userdata/firstname", ui->firstnameLineEdit->text());
-        ASettings::write("userdata/employeeid", ui->employeeidLineEdit->text());
-        ASettings::write("userdata/phone", ui->phoneLineEdit->text());
-        ASettings::write("userdata/email", ui->emailLineEdit->text());
-
-        ASettings::write("flightlogging/function", ui->functionComboBox->currentText());
-        ASettings::write("flightlogging/approach", ui->approachComboBox->currentText());
-        ASettings::write("flightlogging/nightlogging", ui->nightComboBox->currentIndex());
-        ASettings::write("flightlogging/logIfr", ui->rulesComboBox->currentIndex());
-        ASettings::write("flightlogging/flightnumberPrefix", ui->prefixLineEdit->text());
-
-        ASettings::write("flightlogging/numberTakeoffs", 1);
-        ASettings::write("flightlogging/numberLandings", 1);
-        ASettings::write("flightlogging/popupCalendar", true);
-        ASettings::write("flightlogging/pilotFlying", true);
-
-
-        QMap<QString, QVariant> data;
-        switch (ui->aliasComboBox->currentIndex()) {
-        case 0:
-            ASettings::write("userdata/displayselfas", ui->aliasComboBox->currentIndex());
-            break;
-        case 1:
-            ASettings::write("userdata/displayselfas", ui->aliasComboBox->currentIndex());
-            break;
-        case 2:{
-            ASettings::write("userdata/displayselfas", ui->aliasComboBox->currentIndex());
-        }
-            break;
-        default:
-            break;
-        }
-        data.insert("lastname", ui->lastnameLineEdit->text());
-        data.insert("firstname", ui->firstnameLineEdit->text());
-        data.insert("alias", "self");
-        data.insert("employeeid", ui->employeeidLineEdit->text());
-        data.insert("phone", ui->phoneLineEdit->text());
-        data.insert("email", ui->emailLineEdit->text());
-
-        if (!finishSetup()) {
-            QMessageBox message_box(this);
-            message_box.setText("Errors have ocurred creating the database. Without a working database The application will not be usable.");
-        }
-        ASettings::write("setup/setup_complete", true);
-        aDB()->disconnect(); // reset db connection to refresh layout after initial setup.
-        aDB()->connect();
-        auto pilot = APilotEntry(1);
-        pilot.setData(data);
-        if (aDB()->commit(pilot)) {
-            qApp->quit();
-            QProcess::startDetached(qApp->arguments()[0], qApp->arguments());
-        } else {
-            QMessageBox message_box(this);
-            message_box.setText("Errors have ocurred creating the database. Without a working database The application will not be usable.");
-        }
+    ASettings::write(ASettings::UserData::LastName, ui->lastnameLineEdit->text());
+    ASettings::write(ASettings::UserData::FirstName, ui->firstnameLineEdit->text());
+    ASettings::write(ASettings::UserData::EmployeeID, ui->employeeidLineEdit->text());
+    ASettings::write(ASettings::UserData::Phone, ui->phoneLineEdit->text());
+    ASettings::write(ASettings::UserData::Email, ui->emailLineEdit->text());
+
+    ASettings::write(ASettings::FlightLogging::Function, ui->functionComboBox->currentText());
+    ASettings::write(ASettings::FlightLogging::Approach, ui->approachComboBox->currentText());
+    ASettings::write(ASettings::FlightLogging::NightLogging, ui->nightComboBox->currentIndex());
+    ASettings::write(ASettings::FlightLogging::LogIFR, ui->rulesComboBox->currentIndex());
+    ASettings::write(ASettings::FlightLogging::FlightNumberPrefix, ui->prefixLineEdit->text());
+    ASettings::write(ASettings::FlightLogging::NumberTakeoffs, 1);
+    ASettings::write(ASettings::FlightLogging::NumberLandings, 1);
+    ASettings::write(ASettings::FlightLogging::PopupCalendar, true);
+    ASettings::write(ASettings::FlightLogging::PilotFlying, true);
+
+    QMap<QString, QVariant> data;
+    ASettings::write(ASettings::UserData::DisplaySelfAs, ui->aliasComboBox->currentIndex());
+    data.insert(ASettings::stringOfKey(ASettings::UserData::LastName), ui->lastnameLineEdit->text());
+    data.insert(ASettings::stringOfKey(ASettings::UserData::FirstName), ui->firstnameLineEdit->text());
+    data.insert(ASettings::stringOfKey(ASettings::UserData::Alias), "self");
+    data.insert(ASettings::stringOfKey(ASettings::UserData::EmployeeID), ui->employeeidLineEdit->text());
+    data.insert(ASettings::stringOfKey(ASettings::UserData::Phone), ui->phoneLineEdit->text());
+    data.insert(ASettings::stringOfKey(ASettings::UserData::Email), ui->emailLineEdit->text());
+
+    auto db_fail_msg_box = QMessageBox(QMessageBox::Critical, QStringLiteral("Database setup failed"),
+                                       QStringLiteral("Errors have ocurred creating the database."
+                                                      "Without a working database The application will not be usable."));
+    // [G]: Im abit confused on the logic here
+    // why do you write setup complete twice?
+    if (!setupDatabase()) {
+        db_fail_msg_box.exec();
+        return false;
+    }
+    aDB()->disconnect(); // reset db connection to refresh layout after initial setup.
+    aDB()->connect();
 
+    auto pilot = APilotEntry(1);
+    pilot.setData(data);
+    if(!aDB()->commit(pilot)){
+        db_fail_msg_box.exec();
+        return false;
     }
+    return true;
 }
 
-bool FirstRunDialog::finishSetup()
+bool FirstRunDialog::setupDatabase()
 {
-
-    //check if template dir exists and create if needed.
-    QDir dir("data/templates");
-    DEB << dir.path();
-    if (!dir.exists())
-        dir.mkpath(".");
-
-    QMessageBox confirm;
-    confirm.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
+    auto confirm = QMessageBox(QMessageBox::Question, QStringLiteral("Create Database"),
+                               QStringLiteral("We are now going to create the database.<br>"  // [G]: Why both <br> and \n ?
+                                              "Would you like to download the latest database information?"
+                                              "<br>(Recommended, Internet connection required)"),
+                               QMessageBox::Yes | QMessageBox::No, this);
     confirm.setDefaultButton(QMessageBox::No);
-    confirm.setIcon(QMessageBox::Question);
-    confirm.setWindowTitle("Create Database");
-    confirm.setText("We are now going to create the database. Would you like to download the latest database information?\n(Recommended, Internet connection required)\n");
-    int reply = confirm.exec();
-    if (reply == QMessageBox::Yes) {
-        // download latest csv
-        QStringList templateTables = {"aircraft", "airports", "changelog"};
-        QString linkStub = TEMPLATE_URL;
-        for (const auto& table : templateTables) {
-            QEventLoop loop;
-            ADownload* dl = new ADownload;
-            connect(dl, &ADownload::done, &loop, &QEventLoop::quit );
-            dl->setTarget(QUrl(linkStub + table + ".csv"));
-            dl->setFileName("data/templates/" + table + ".csv");
-            dl->download();
-            loop.exec(); // event loop waits for download done signal before allowing loop to continue
-            dl->deleteLater();
-        }
-    }
 
-    //close database connection
-    aDB()->disconnect();
+    if (confirm.exec() == QMessageBox::Yes)
+        ADataBaseSetup::downloadTemplates();
 
-    // back up old database
-    auto oldDatabase = QFile("data/logbook.db");
-    if (oldDatabase.exists()) {
-        auto dateString = QDateTime::currentDateTime().toString(Qt::ISODate);
-        DEB << "Backing up old database as: " << "logbook-backup-" + dateString;
-        if (!oldDatabase.rename("data/logbook-backup-" + dateString)) {
-            DEB << "Warning: Creating backup of old database has failed.";
-        }
-    }
-    // re-connect and create new database
+    aDB()->disconnect();
+    ADataBaseSetup::backupOldData();
     aDB()->connect();
 
-    if (ADataBaseSetup::createDatabase()) {
-        if (ADataBaseSetup::importDefaultData()) {
-            ASettings::write("setup/setup_complete", true);
-            return true;
-        } else {
-            return false;
-        }
-    } else {
+    // [F]: todo: handle unsuccessful steps
+    // [G]: only two / for comments
+    // three are shorthand for documentation
+    if(!ADataBaseSetup::createDatabase())
         return false;
-    }
+    if(!ADataBaseSetup::importDefaultData())
+        return false;
+    return true;
 }
 
+void FirstRunDialog::reject()
+{
+    auto confirm = QMessageBox(QMessageBox::Critical,
+                               QStringLiteral("Setup incomplete"),
+                               QStringLiteral("Without completing the initial setup"
+                                              " you cannot use the application.<br><br>"
+                                              "Quit anyway?"),
+                               QMessageBox::Yes | QMessageBox::No, this);
+    confirm.setDefaultButton(QMessageBox::No);
 
+    if (confirm.exec() == QMessageBox::Yes) {
+        DEB << "rejected.";
+        QDialog::reject();
+    }
+}

+ 8 - 4
src/gui/dialogues/firstrundialog.h

@@ -4,6 +4,7 @@
 #include <QDialog>
 #include <QButtonGroup>
 #include <QMessageBox>
+#include <QStringBuilder>
 
 namespace Ui {
 class FirstRunDialog;
@@ -25,12 +26,15 @@ private slots:
 
     void on_themeGroup_toggled(int id);
 
-    void on_finishButton_clicked();
-
-    bool finishSetup();
-
 private:
     Ui::FirstRunDialog *ui;
+    // [G]: finish is the old signal.
+    // finishSetup does something with template of database which
+    // goes over my head but everything works for now. Better naming needed
+
+    void reject() override;
+    bool setupDatabase();
+    bool finish();
 
 };
 

+ 33 - 62
src/gui/dialogues/firstrundialog.ui

@@ -14,15 +14,23 @@
    <string>Dialog</string>
   </property>
   <layout class="QGridLayout" name="gridLayout">
-   <item row="0" column="0" colspan="2">
-    <widget class="QTabWidget" name="tabWidget">
-     <property name="currentIndex">
-      <number>0</number>
+   <item row="1" column="0">
+    <widget class="QPushButton" name="previousPushButton">
+     <property name="text">
+      <string>Previous</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="1">
+    <widget class="QPushButton" name="nextPushButton">
+     <property name="text">
+      <string>Next</string>
      </property>
-     <widget class="QWidget" name="tab_1">
-      <attribute name="title">
-       <string>General</string>
-      </attribute>
+    </widget>
+   </item>
+   <item row="0" column="0" colspan="2">
+    <widget class="QStackedWidget" name="stackedWidget">
+     <widget class="QWidget" name="stackedWidgetPage1">
       <layout class="QGridLayout" name="gridLayout_2">
        <item row="0" column="1">
         <widget class="QLabel" name="label">
@@ -130,10 +138,7 @@
        </item>
       </layout>
      </widget>
-     <widget class="QWidget" name="tab_2">
-      <attribute name="title">
-       <string>Flight Logging</string>
-      </attribute>
+     <widget class="QWidget" name="stackedWidgetPage2">
       <layout class="QGridLayout" name="gridLayout_3">
        <item row="0" column="1">
         <widget class="QLabel" name="label_2">
@@ -387,11 +392,22 @@
        </item>
       </layout>
      </widget>
-     <widget class="QWidget" name="tab_3">
-      <attribute name="title">
-       <string>Finish</string>
-      </attribute>
+     <widget class="QWidget" name="stackedWidgetPage3">
       <layout class="QGridLayout" name="gridLayout_4">
+       <item row="2" column="1">
+        <widget class="QCheckBox" name="lightThemeCheckBox">
+         <property name="text">
+          <string>Light Theme</string>
+         </property>
+        </widget>
+       </item>
+       <item row="3" column="1">
+        <widget class="QCheckBox" name="darkThemeCheckBox">
+         <property name="text">
+          <string>Dark Theme</string>
+         </property>
+        </widget>
+       </item>
        <item row="0" column="0" colspan="2">
         <widget class="QLabel" name="label_4">
          <property name="text">
@@ -422,54 +438,10 @@
          </property>
         </widget>
        </item>
-       <item row="2" column="1">
-        <widget class="QCheckBox" name="lightThemeCheckBox">
-         <property name="text">
-          <string>Light Theme</string>
-         </property>
-        </widget>
-       </item>
-       <item row="3" column="1">
-        <widget class="QCheckBox" name="darkThemeCheckBox">
-         <property name="text">
-          <string>Dark Theme</string>
-         </property>
-        </widget>
-       </item>
-       <item row="4" column="0" colspan="2">
-        <widget class="QPushButton" name="finishButton">
-         <property name="minimumSize">
-          <size>
-           <width>0</width>
-           <height>60</height>
-          </size>
-         </property>
-         <property name="styleSheet">
-          <string notr="true">background-color:rgb(78, 154, 6)</string>
-         </property>
-         <property name="text">
-          <string>Finish Setup</string>
-         </property>
-        </widget>
-       </item>
       </layout>
      </widget>
     </widget>
    </item>
-   <item row="1" column="0">
-    <widget class="QPushButton" name="previousPushButton">
-     <property name="text">
-      <string>Previous</string>
-     </property>
-    </widget>
-   </item>
-   <item row="1" column="1">
-    <widget class="QPushButton" name="nextPushButton">
-     <property name="text">
-      <string>Next</string>
-     </property>
-    </widget>
-   </item>
   </layout>
  </widget>
  <tabstops>
@@ -489,8 +461,7 @@
   <tabstop>systemThemeCheckBox</tabstop>
   <tabstop>lightThemeCheckBox</tabstop>
   <tabstop>darkThemeCheckBox</tabstop>
-  <tabstop>finishButton</tabstop>
-  <tabstop>tabWidget</tabstop>
+  <tabstop>stackedWidget</tabstop>
  </tabstops>
  <resources/>
  <connections/>

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

@@ -107,11 +107,11 @@ NewFlightDialog::NewFlightDialog(QWidget *parent) :
     ui->setupUi(this);
     flightEntry = AFlightEntry();
     setup();
-    if (ASettings::read("NewFlight/FunctionComboBox").toString() == "SIC") {
+    if (ASettings::read(ASettings::NewFlight::FunctionComboBox).toString() == "SIC") {
         ui->picNameLineEdit->setText(DB_NULL);
         ui->secondPilotNameLineEdit->setText("self");
     }
-    if(ASettings::read("NewFlight/FunctionComboBox").toString() == "PIC"){
+    if(ASettings::read(ASettings::NewFlight::FunctionComboBox).toString() == "PIC"){
         ui->picNameLineEdit->setText("self");
         emit ui->picNameLineEdit->editingFinished();
     }
@@ -160,26 +160,26 @@ void NewFlightDialog::readSettings()
 {
     DEB << "Reading Settings...";
     QSettings settings;
-    ui->FunctionComboBox->setCurrentText(ASettings::read("flightlogging/function").toString());
-    ui->ApproachComboBox->setCurrentText(ASettings::read("flightlogging/approach").toString());
+    ui->FunctionComboBox->setCurrentText(ASettings::read(ASettings::FlightLogging::Function).toString());
+    ui->ApproachComboBox->setCurrentText(ASettings::read(ASettings::FlightLogging::Approach).toString());
 
-    ASettings::read("flightlogging/pilotFlying").toBool() ? ui->PilotFlyingCheckBox->setChecked(true)
+    ASettings::read(ASettings::FlightLogging::PilotFlying).toBool() ? ui->PilotFlyingCheckBox->setChecked(true)
                                                           : ui->PilotMonitoringCheckBox->setChecked(true);
 
-    ui->TakeoffSpinBox->setValue(ASettings::read("flightlogging/numberTakeoffs").toInt());
+    ui->TakeoffSpinBox->setValue(ASettings::read(ASettings::FlightLogging::NumberTakeoffs).toInt());
     ui->TakeoffSpinBox->value() > 0 ? ui->TakeoffCheckBox->setChecked(true)
                                     : ui->TakeoffCheckBox->setChecked(false);
-    ui->LandingSpinBox->setValue(ASettings::read("flightlogging/numberLandings").toInt());
+    ui->LandingSpinBox->setValue(ASettings::read(ASettings::FlightLogging::NumberLandings).toInt());
     ui->LandingSpinBox->value() > 0 ? ui->LandingCheckBox->setChecked(true)
                                     : ui->LandingCheckBox->setChecked(false);
-    if (ASettings::read("flightlogging/logIfr").toBool()) {
+    if (ASettings::read(ASettings::FlightLogging::LogIFR).toBool()) {
         ui->IfrCheckBox->setChecked(true);
     } else {
         ui->VfrCheckBox->setChecked(true);
     }
 
-    ui->FlightNumberLineEdit->setText(ASettings::read("flightlogging/flightnumberPrefix").toString());
-    ui->calendarCheckBox->setChecked(ASettings::read("flightlogging/popupCalendar").toBool());
+    ui->FlightNumberLineEdit->setText(ASettings::read(ASettings::FlightLogging::FlightNumberPrefix).toString());
+    ui->calendarCheckBox->setChecked(ASettings::read(ASettings::FlightLogging::PopupCalendar).toBool());
 
 }
 
@@ -187,13 +187,13 @@ void NewFlightDialog::writeSettings()
 {
     DEB << "Writing Settings...";
 
-    ASettings::write("flightlogging/function", ui->FunctionComboBox->currentText());
-    ASettings::write("flightlogging/approach", ui->ApproachComboBox->currentText());
-    ASettings::write("flightlogging/pilotFlying", ui->PilotFlyingCheckBox->isChecked());
-    ASettings::write("flightlogging/numberTakeoffs", ui->TakeoffSpinBox->value());
-    ASettings::write("flightlogging/numberLandings", ui->LandingSpinBox->value());
-    ASettings::write("flightlogging/logIfr", ui->IfrCheckBox->isChecked());
-    ASettings::write("flightlogging/popupCalendar", ui->calendarCheckBox->isChecked());
+    ASettings::write(ASettings::FlightLogging::Function, ui->FunctionComboBox->currentText());
+    ASettings::write(ASettings::FlightLogging::Approach, ui->ApproachComboBox->currentText());
+    ASettings::write(ASettings::FlightLogging::PilotFlying, ui->PilotFlyingCheckBox->isChecked());
+    ASettings::write(ASettings::FlightLogging::NumberTakeoffs, ui->TakeoffSpinBox->value());
+    ASettings::write(ASettings::FlightLogging::NumberLandings, ui->LandingSpinBox->value());
+    ASettings::write(ASettings::FlightLogging::LogIFR, ui->IfrCheckBox->isChecked());
+    ASettings::write(ASettings::FlightLogging::PopupCalendar, ui->calendarCheckBox->isChecked());
 }
 
 void NewFlightDialog::setupButtonGroups()
@@ -442,7 +442,7 @@ void NewFlightDialog::fillDeductibleData()
     QString dept_date = ui->doftLineEdit->text() + 'T' + tofb.toString(TIME_FORMAT);
     QDateTime dept_date_time = QDateTime::fromString(dept_date,"yyyy-MM-ddThh:mm");
     int tblk = block_minutes.toInt();
-    const int night_angle = ASettings::read("flightlogging/nightangle").toInt();
+    const int night_angle = ASettings::read(ASettings::FlightLogging::NightAngle).toInt();
     QString night_minutes = QString::number(
                 ACalc::calculateNightTime(
                     ui->deptLocLineEdit->text(),
@@ -530,7 +530,7 @@ RowData NewFlightDialog::collectInput()
     const auto dept_date = ui->doftLineEdit->text() + QStringLiteral("T") + tofb.toString(TIME_FORMAT);
     const auto dept_date_time = QDateTime::fromString(dept_date, QStringLiteral("yyyy-MM-ddThh:mm"));
 
-    const auto night_angle = ASettings::read("flightlogging/nightangle").toInt();
+    const auto night_angle = ASettings::read(ASettings::FlightLogging::NightAngle).toInt();
     const auto night_minutes = ACalc::calculateNightTime(
                     ui->deptLocLineEdit->text(),
                     ui->destLocLineEdit->text(),
@@ -1063,7 +1063,7 @@ void NewFlightDialog::onDoftLineEdit_entered()
 
 void NewFlightDialog::on_calendarCheckBox_stateChanged(int arg1)
 {
-    ASettings::write("NewFlight/calendarCheckBox", ui->calendarCheckBox->isChecked());
+    ASettings::write(ASettings::NewFlight::CalendarCheckBox, ui->calendarCheckBox->isChecked());
     DEB << "Calendar check box state changed.";
     switch (arg1) {
     case 0: // unchecked

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

@@ -263,7 +263,7 @@ void NewTailDialog::on_buttonBox_accepted()
     }
 
     if (!verify()) {
-        if (!ASettings::read("userdata/acAllowIncomplete").toInt()) {
+        if (!ASettings::read(ASettings::UserData::AcAllowIncomplete).toInt()) {
             auto nope = QMessageBox(this);
             nope.setIcon(QMessageBox::Warning);
             nope.setText("Some or all recommended fields are empty.\nPlease go back and "

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

@@ -48,7 +48,7 @@ AircraftWidget::~AircraftWidget()
 
 void AircraftWidget::setupModelAndView()
 {
-    sortColumn = ASettings::read("userdata/acSortColumn").toInt();
+    sortColumn = ASettings::read(ASettings::UserData::AcSortColumn).toInt();
 
     model = new QSqlTableModel(this);
     model->setTable("viewTails");
@@ -199,7 +199,7 @@ void AircraftWidget::tableView_selectionChanged()
 void AircraftWidget::tableView_headerClicked(int column)
 {
     sortColumn = column;
-    ASettings::write("userdata/acSortColumn", column);
+    ASettings::write(ASettings::UserData::AcSortColumn, column);
 }
 
 void AircraftWidget::acft_editing_finished()

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

@@ -1,6 +1,6 @@
 #include "debugwidget.h"
 #include "ui_debugwidget.h"
-#include "src/astandardpaths.h"
+#include "src/classes/astandardpaths.h"
 
 DebugWidget::DebugWidget(QWidget *parent) :
     QWidget(parent),
@@ -169,7 +169,7 @@ void DebugWidget::on_importCsvPushButton_clicked()
 
 void DebugWidget::on_debugPushButton_clicked()
 {
-    DEB << AStandardPaths::getPaths()[QStandardPaths::AppDataLocation];
+    DEB << AStandardPaths::allPaths()[AStandardPaths::Database	];
 }
 
 /* //Comparing two functions template

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

@@ -48,7 +48,7 @@ LogbookWidget::LogbookWidget(QWidget *parent) :
     //Initialise message Box
     messageBox = new QMessageBox(this);
 
-    prepareModelAndView(ASettings::read("logbook/view").toInt());
+    prepareModelAndView(ASettings::read(ASettings::LogBook::View).toInt());
     connectSignalsAndSlots();
 }
 

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

@@ -37,7 +37,7 @@ PilotsWidget::~PilotsWidget()
 
 void PilotsWidget::setupModelAndView()
 {
-    sortColumn = ASettings::read("userdata/pilSortColumn").toInt();
+    sortColumn = ASettings::read(ASettings::UserData::PilSortColumn).toInt();
 
     model = new QSqlTableModel(this);
     model->setTable("viewPilots");
@@ -115,7 +115,7 @@ void PilotsWidget::tableView_selectionChanged()//const QItemSelection &index, co
 void PilotsWidget::tableView_headerClicked(int column)
 {
     sortColumn = column;
-    ASettings::write("userdata/pilSortColumn", column);
+    ASettings::write(ASettings::UserData::PilSortColumn, column);
 }
 
 void PilotsWidget::on_newPilotButton_clicked()

+ 41 - 40
src/gui/widgets/settingswidget.cpp

@@ -73,25 +73,26 @@ void SettingsWidget::readSettings()
     /*
      * Personal Tab
      */
-    ui->lastnameLineEdit->setText(ASettings::read("userdata/lastname").toString());
-    ui->firstnameLineEdit->setText(ASettings::read("userdata/firstname").toString());
-    ui->companyLineEdit->setText(ASettings::read("userdata/company").toString());
-    ui->employeeidLineEdit->setText(ASettings::read("userdata/employeeid").toString());
-    ui->phoneLineEdit->setText(ASettings::read("userdata/phone").toString());
-    ui->emailLineEdit->setText(ASettings::read("userdata/email").toString());
+    ui->lastnameLineEdit->setText(ASettings::read(ASettings::UserData::LastName).toString());
+    ui->firstnameLineEdit->setText(ASettings::read(ASettings::UserData::FirstName).toString());
+    ui->companyLineEdit->setText(ASettings::read(ASettings::UserData::Company).toString());
+    ui->employeeidLineEdit->setText(ASettings::read(ASettings::UserData::EmployeeID).toString());
+    ui->phoneLineEdit->setText(ASettings::read(ASettings::UserData::Phone).toString());
+    ui->emailLineEdit->setText(ASettings::read(ASettings::UserData::Email).toString());
     /*
      * Flight Logging Tab
      */
-    ui->aliasComboBox->setCurrentIndex(ASettings::read("userdata/displayselfas").toInt());
-    ui->functionComboBox->setCurrentText(ASettings::read("flightlogging/function").toString());
-    ui->rulesComboBox->setCurrentText(ASettings::read("flightlogging/rules").toString());
-    ui->approachComboBox->setCurrentText(ASettings::read("flightlogging/approach").toString());
-    ui->nightComboBox->setCurrentIndex(ASettings::read("flightlogging/nightlogging").toInt());
-    ui->prefixLineEdit->setText(ASettings::read("flightlogging/flightnumberPrefix").toString());
+    ui->aliasComboBox->setCurrentIndex(ASettings::read(ASettings::UserData::DisplaySelfAs).toInt());
+    ui->functionComboBox->setCurrentText(ASettings::read(ASettings::FlightLogging::Function).toString());
+    ui->rulesComboBox->setCurrentText(ASettings::read(ASettings::FlightLogging::Rules).toString());
+    ui->approachComboBox->setCurrentText(ASettings::read(ASettings::FlightLogging::Approach).toString());
+    ui->nightComboBox->setCurrentIndex(ASettings::read(ASettings::FlightLogging::NightLogging).toInt());
+    ui->prefixLineEdit->setText(ASettings::read(ASettings::FlightLogging::FlightNumberPrefix).toString());
+
     /*
      * Misc Tab
      */
-    switch (ASettings::read("main/theme").toInt()) {
+    switch (ASettings::read(ASettings::Main::Theme).toInt()) {
     case 0:
         ui->systemThemeCheckBox->setChecked(true);
         break;
@@ -101,13 +102,13 @@ void SettingsWidget::readSettings()
     case 2:
         ui->darkThemeCheckBox->setChecked(true);
     }
-    ui->logbookViewComboBox->setCurrentIndex(ASettings::read("logbook/view").toInt());
+    ui->logbookViewComboBox->setCurrentIndex(ASettings::read(ASettings::LogBook::View).toInt());
     /*
      * Aircraft Tab
      */
-    ui->acSortComboBox->setCurrentIndex(ASettings::read("userdata/acSortColumn").toInt());
-    ui->pilotSortComboBox->setCurrentIndex(ASettings::read("userdata/pilSortColumn").toInt());
-    ui->acAllowIncompleteComboBox->setCurrentIndex(ASettings::read("userdata/acAllowIncomplete").toInt());
+    ui->acSortComboBox->setCurrentIndex(ASettings::read(ASettings::UserData::AcSortColumn).toInt());
+    ui->pilotSortComboBox->setCurrentIndex(ASettings::read(ASettings::UserData::PilSortColumn).toInt());
+    ui->acAllowIncompleteComboBox->setCurrentIndex(ASettings::read(ASettings::UserData::AcAllowIncomplete).toInt());
 }
 
 void SettingsWidget::setupValidators()
@@ -172,10 +173,10 @@ void SettingsWidget::updatePersonalDetails()
 void SettingsWidget::on_lastnameLineEdit_editingFinished()
 {
     if(ui->lastnameLineEdit->text().isEmpty()){
-        ui->lastnameLineEdit->setText(ASettings::read("userdata/lastname").toString());
+        ui->lastnameLineEdit->setText(ASettings::read(ASettings::UserData::LastName).toString());
         ui->lastnameLineEdit->setFocus();
     } else {
-        ASettings::write("userdata/lastname",ui->lastnameLineEdit->text());
+        ASettings::write(ASettings::UserData::LastName, ui->lastnameLineEdit->text());
         updatePersonalDetails();
     }
 }
@@ -183,35 +184,35 @@ void SettingsWidget::on_lastnameLineEdit_editingFinished()
 void SettingsWidget::on_firstnameLineEdit_editingFinished()
 {
     if(ui->firstnameLineEdit->text().isEmpty()){
-        ui->firstnameLineEdit->setText(ASettings::read("userdata/firstname").toString());
+        ui->firstnameLineEdit->setText(ASettings::read(ASettings::UserData::FirstName).toString());
         ui->firstnameLineEdit->setFocus();
     } else {
-        ASettings::write("userdata/firstname",ui->firstnameLineEdit->text());
+        ASettings::write(ASettings::UserData::FirstName,ui->firstnameLineEdit->text());
         updatePersonalDetails();
     }
 }
 
 void SettingsWidget::on_companyLineEdit_editingFinished()
 {
-    ASettings::write("userdata/company", ui->companyLineEdit->text());
+    ASettings::write(ASettings::UserData::Company, ui->companyLineEdit->text());
     updatePersonalDetails();
 }
 
 void SettingsWidget::on_employeeidLineEdit_editingFinished()
 {
-    ASettings::write("userdata/employeeid", ui->employeeidLineEdit->text());
+    ASettings::write(ASettings::UserData::EmployeeID, ui->employeeidLineEdit->text());
     updatePersonalDetails();
 }
 
 void SettingsWidget::on_emailLineEdit_editingFinished()
 {
-    ASettings::write("userdata/email", ui->emailLineEdit->text());
+    ASettings::write(ASettings::UserData::Email, ui->emailLineEdit->text());
     updatePersonalDetails();
 }
 
 void SettingsWidget::on_phoneLineEdit_editingFinished()
 {
-    ASettings::write("userdata/phone", ui->phoneLineEdit->text());
+    ASettings::write(ASettings::UserData::Phone, ui->phoneLineEdit->text());
     updatePersonalDetails();
 }
 
@@ -221,43 +222,43 @@ void SettingsWidget::on_phoneLineEdit_editingFinished()
 
 void SettingsWidget::on_aliasComboBox_currentIndexChanged(int index)
 {
-    ASettings::write("userdata/displayselfas", index);
+    ASettings::write(ASettings::UserData::DisplaySelfAs, index);
     updatePersonalDetails();
 }
 
 void SettingsWidget::on_functionComboBox_currentIndexChanged(const QString &arg1)
 {
-    ASettings::write("flightlogging/function", arg1);
+    ASettings::write(ASettings::FlightLogging::Function, arg1);
 }
 
 void SettingsWidget::on_rulesComboBox_currentIndexChanged(const QString &arg1)
 {
-    ASettings::write("flightlogging/rules", arg1);
+    ASettings::write(ASettings::FlightLogging::Rules, arg1);
 }
 
 void SettingsWidget::on_approachComboBox_currentIndexChanged(const QString &arg1)
 {
-    ASettings::write("flightlogging/approach", arg1);
+    ASettings::write(ASettings::FlightLogging::Approach, arg1);
 }
 
 void SettingsWidget::on_nightComboBox_currentIndexChanged(int index)
 {
-    ASettings::write("flightlogging/nightlogging", index);
+    ASettings::write(ASettings::FlightLogging::NightLogging, index);
     switch (index) {
     case 1:
-        ASettings::write("flightlogging/nightangle", -6);
+        ASettings::write(ASettings::FlightLogging::NightAngle, -6);
         break;
     case 2:
-        ASettings::write("flightlogging/nightangle", 0);
+        ASettings::write(ASettings::FlightLogging::NightAngle, 0);
         break;
     default:
-        ASettings::write("flightlogging/nightangle", -6);
+        ASettings::write(ASettings::FlightLogging::NightAngle, -6);
     }
 }
 
 void SettingsWidget::on_prefixLineEdit_textChanged(const QString &arg1)
 {
-    ASettings::write("flightlogging/flightnumberPrefix", arg1);
+    ASettings::write(ASettings::FlightLogging::FlightNumberPrefix, arg1);
 
 }
 
@@ -266,7 +267,7 @@ void SettingsWidget::on_prefixLineEdit_textChanged(const QString &arg1)
  */
 void SettingsWidget::onThemeGroup_buttonClicked(int theme_id)
 {
-    ASettings::write("main/theme", theme_id);
+    ASettings::write(ASettings::Main::Theme, theme_id);
 
     QMessageBox::StandardButton reply;
     reply = QMessageBox::question(this, "Changing Themes",
@@ -284,22 +285,22 @@ void SettingsWidget::onThemeGroup_buttonClicked(int theme_id)
 }
 void SettingsWidget::on_logbookViewComboBox_currentIndexChanged(int index)
 {
-    ASettings::write("logbook/view", index);
+    ASettings::write(ASettings::LogBook::View, index);
     emit viewSelectionChanged(index);
 }
 void SettingsWidget::on_pilotSortComboBox_currentIndexChanged(int index)
 {
-    ASettings::write("userdata/pilSortColumn", index);
+    ASettings::write(ASettings::UserData::PilSortColumn, index);
 }
 
 void SettingsWidget::on_acSortComboBox_currentIndexChanged(int index)
 {
-    ASettings::write("userdata/acSortColumn", index);
+    ASettings::write(ASettings::UserData::AcSortColumn, index);
 }
 
 void SettingsWidget::on_acAllowIncompleteComboBox_currentIndexChanged(int index)
 {
-    ASettings::write("userdata/acAllowIncomplete", index);
+    ASettings::write(ASettings::UserData::AcAllowIncomplete, index);
     if (index) {
         QMessageBox::StandardButton reply;
         reply = QMessageBox::warning(this, "Warning",
@@ -311,7 +312,7 @@ void SettingsWidget::on_acAllowIncompleteComboBox_currentIndexChanged(int index)
                                       "Are you sure you want to proceed?",
                                       QMessageBox::Yes | QMessageBox::No);
         if (reply == QMessageBox::Yes) {
-            ASettings::write("userdata/acAllowIncomplete", index);
+            ASettings::write(ASettings::UserData::AcAllowIncomplete, index);
         } else {
             ui->acAllowIncompleteComboBox->setCurrentIndex(0);
         }

+ 11 - 1
src/testing/adebug.h

@@ -3,7 +3,17 @@
 
 #include <QDebug>
 
-#define DEB qDebug() << __PRETTY_FUNCTION__ << "\t"
+#if defined(__GNUC__) || defined(__clang__)
+    #define FUNC_IDENT __PRETTY_FUNCTION__
+#elif defined(_MSC_VER)
+    #define FUNC_IDENT __FUNCSIG__
+#else
+    #define FUNC_IDENT __func__
+#endif
+
+#define DEB qDebug() << FUNC_IDENT << "\n\t"
+#define DEB_SRC DEB
+#define DEB_RAW qDebug() << '\t'
 
 /*!
  * Representation macro for custom classes.