Browse Source

First draft of JSON interface

Started work on JSON interface to import/export to/from the database, shall replace CSV once it's 
ready.

AJson class handles import/export. New Dir in Astandardpaths and DB functionality extended.
Felix Turo 3 years ago
parent
commit
e226c320af

+ 2 - 0
CMakeLists.txt

@@ -35,6 +35,7 @@ set(PROJECT_SOURCES
     src/classes/asettings.cpp
     src/classes/atailentry.cpp
     src/classes/atranslator.cpp
+    src/classes/ajson.cpp
     src/database/adatabase.cpp
     src/database/adatabasesetup.cpp
     src/functions/acalc.cpp
@@ -69,6 +70,7 @@ set(PROJECT_SOURCES
     src/classes/asettings.h
     src/classes/atailentry.h
     src/classes/atranslator.h
+    src/classes/ajson.h
     src/database/adatabase.h
     src/database/adatabasesetup.h
     src/database/adatabasetypes.h

+ 2 - 0
openPilotLog.pro

@@ -32,6 +32,7 @@ SOURCES += \
     src/classes/asettings.cpp \
     src/classes/atailentry.cpp \
     src/classes/atranslator.cpp \
+    src/classes/ajson.cpp \
     src/database/adatabase.cpp \
     src/database/adatabasesetup.cpp \
     src/functions/acalc.cpp \
@@ -68,6 +69,7 @@ HEADERS += \
     src/classes/atailentry.h \
     src/database/adatabase.h \
     src/classes/atranslator.h \
+    src/classes/ajson.h \
     src/database/adatabasesetup.h \
     src/database/adatabasetypes.h \
     src/functions/acalc.h \

+ 33 - 0
src/classes/ajson.cpp

@@ -0,0 +1,33 @@
+#include "ajson.h"
+
+void AJson::exportDatabase()
+{
+    const QList<QPair<QLatin1String, ADatabaseTables>> tables {
+        qMakePair(Opl::Db::TABLE_TAILS, ADatabaseTables::tails),
+        qMakePair(Opl::Db::TABLE_PILOTS, ADatabaseTables::pilots),
+        qMakePair(Opl::Db::TABLE_CURRENCIES, ADatabaseTables::currencies),
+        qMakePair(Opl::Db::TABLE_FLIGHTS, ADatabaseTables::flights),
+    };
+
+    for (const auto &pair : tables){
+        QJsonArray arr;
+        const auto rows = aDB->getTable(pair.second);
+        for (const auto & row : rows)
+            arr.append(QJsonObject::fromVariantMap(row));
+        QJsonDocument doc(arr);
+        writeJson(doc, pair.first + QLatin1String(".json"));
+    }
+}
+
+void AJson::writeJson(const QJsonDocument &doc, const QString &file_name)
+{
+    QFile pilots_out(AStandardPaths::asChildOfDir(AStandardPaths::JSON,file_name));
+    pilots_out.open(QFile::WriteOnly);
+    pilots_out.write(doc.toJson());
+    pilots_out.close();
+}
+
+void AJson::readJson(const QString &file_name)
+{
+    TODO << "implement..." << file_name;
+}

+ 38 - 0
src/classes/ajson.h

@@ -0,0 +1,38 @@
+#ifndef AJSON_H
+#define AJSON_H
+#include "src/opl.h"
+#include "src/database/adatabase.h"
+#include <QJsonDocument>
+#include <QJsonValue>
+#include <QJsonObject>
+
+
+
+/*!
+ * \brief The AJSON class is responsible for parsing the database (sqlite) to and from JSON.
+ */
+class AJson
+{
+public:
+    AJson();
+    AJson(QFileInfo database_file);
+
+    /*!
+     * \brief exportDatabase exports the currently active database to JSON. Files are created at AStandardPaths::JSON.
+     */
+    static void exportDatabase();
+
+private:
+
+    /*!
+     * \brief writes a QJsonDocument to a file
+     */
+    static void writeJson(const QJsonDocument &doc, const QString& file_name);
+
+    /*!
+     * \brief To Do - Reads a file into a QJasonDocument
+     */
+    static void readJson(const QString& file_name);
+};
+
+#endif // AJSON_H

+ 3 - 1
src/classes/astandardpaths.cpp

@@ -30,7 +30,9 @@ bool AStandardPaths::setup()
         {Backup, QDir(QStandardPaths::writableLocation(data_location)
          + QLatin1String("/backup"))},
         {Log, QDir(QStandardPaths::writableLocation(data_location)
-         + QLatin1String("/log"))}
+         + QLatin1String("/log"))},
+        {JSON, QDir(QStandardPaths::writableLocation(data_location)
+         + QLatin1String("/json"))}
     };
     if (scan_directories())
         return true;

+ 2 - 1
src/classes/astandardpaths.h

@@ -33,7 +33,8 @@ public:
         Database,
         Templates,
         Backup,
-        Log
+        Log,
+        JSON
     };
 private:
     static QMap<Directories, QDir> directories;

+ 56 - 10
src/database/adatabase.cpp

@@ -52,12 +52,12 @@ int ADatabase::checkDbVersion() const
     return query.value(0).toInt();
 }
 
-ColumnNames_T ADatabase::getTableColumns(TableName_T table_name) const
+const ColumnNames_T ADatabase::getTableColumns(TableName_T table_name) const
 {
     return tableColumns.value(table_name);
 }
 
-TableNames_T ADatabase::getTableNames() const
+const TableNames_T ADatabase::getTableNames() const
 {
     return tableNames;
 }
@@ -562,18 +562,18 @@ QMap<QString, RowId_T> ADatabase::getIdMap(ADatabaseTarget target)
     return id_map;
 }
 
-int ADatabase::getLastEntry(ADatabaseTarget target)
+int ADatabase::getLastEntry(ADatabaseTables table)
 {
     QString statement = QLatin1String("SELECT MAX(ROWID) FROM ");
 
-    switch (target) {
-    case ADatabaseTarget::pilots:
+    switch (table) {
+    case ADatabaseTables::pilots:
         statement.append(Opl::Db::TABLE_PILOTS);
         break;
-    case ADatabaseTarget::aircraft:
+    case ADatabaseTables::aircraft:
         statement.append(Opl::Db::TABLE_AIRCRAFT);
         break;
-    case ADatabaseTarget::tails:
+    case ADatabaseTables::tails:
         statement.append(Opl::Db::TABLE_TAILS);
         break;
     default:
@@ -590,15 +590,15 @@ int ADatabase::getLastEntry(ADatabaseTarget target)
     }
 }
 
-QList<RowId_T> ADatabase::getForeignKeyConstraints(RowId_T foreign_row_id, ADatabaseTarget target)
+QList<RowId_T> ADatabase::getForeignKeyConstraints(RowId_T foreign_row_id, ADatabaseTables target)
 {
     QString statement = QLatin1String("SELECT ROWID FROM flights WHERE ");
 
     switch (target) {
-    case ADatabaseTarget::pilots:
+    case ADatabaseTables::pilots:
         statement.append(QLatin1String("pic=?"));
         break;
-    case ADatabaseTarget::tails:
+    case ADatabaseTables::tails:
         statement.append(QLatin1String("acft=?"));
         break;
     default:
@@ -759,6 +759,52 @@ bool ADatabase::createBackup(const QString& dest_file)
     return true;
 }
 
+QVector<RowData_T> ADatabase::getTable(ADatabaseTables table_name)
+{
+    auto query_str = QStringLiteral("SELECT * FROM ");
+    switch (table_name) {
+    case ADatabaseTables::pilots:
+        query_str.append(Opl::Db::TABLE_PILOTS);
+        break;
+    case ADatabaseTables::tails:
+        query_str.append(Opl::Db::TABLE_TAILS);
+        break;
+    case ADatabaseTables::flights:
+        query_str.append(Opl::Db::TABLE_FLIGHTS);
+        break;
+    case ADatabaseTables::currencies:
+        query_str.append(Opl::Db::TABLE_CURRENCIES);
+    default:
+        break;
+    }
+
+    QSqlQuery q;
+    q.prepare(query_str);
+    q.setForwardOnly(true);
+    q.exec();
+
+    if (q.lastError().type() != QSqlError::NoError) {
+        LOG << "SQL error: " << q.lastError().text();
+        LOG << "Statement: " << query_str;
+        lastError = q.lastError().text();
+        return {};
+    }
+
+    QVector<RowData_T> entry_data;
+    while(q.next()) { // iterate through records
+        auto r = q.record();
+        //DEB << r;
+        RowData_T row;
+        for (int i = 0; i < r.count(); i++){
+            if(!r.value(i).isNull()) {
+                row.insert(r.fieldName(i), r.value(i));
+            }
+        }
+        entry_data.append(row);
+    }
+    return entry_data;
+}
+
 /*!
  * \brief ADatabase::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'

+ 23 - 7
src/database/adatabase.h

@@ -57,15 +57,25 @@
  */
 enum class ADatabaseTarget
 {
-    aircraft,
+
     airport_identifier_icao,
     airport_identifier_iata,
     airport_identifier_all,
     airport_names,
-    pilots,
     registrations,
     companies,
-    tails
+    tails,
+    pilots,
+    aircraft
+};
+
+enum class ADatabaseTables
+{
+    tails,
+    flights,
+    currencies,
+    aircraft,
+    pilots,
 };
 
 /*!
@@ -129,12 +139,12 @@ public:
     /*!
      * \brief Return the names of all tables in the database
      */
-    TableNames_T getTableNames() const;
+    const TableNames_T getTableNames() const;
 
     /*!
      * \brief Return the names of a given table in the database.
      */
-    ColumnNames_T getTableColumns(TableName_T table_name) const;
+    const ColumnNames_T getTableColumns(TableName_T table_name) const;
 
     /*!
      * \brief Updates the member variables tableNames and tableColumns with up-to-date layout information
@@ -275,13 +285,13 @@ public:
     /*!
      * \brief returns the ROWID for the newest entry in the respective database.
      */
-    int getLastEntry(ADatabaseTarget target);
+    int getLastEntry(ADatabaseTables 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, ADatabaseTarget target);
+    QList<RowId_T> getForeignKeyConstraints(RowId_T foreign_row_id, ADatabaseTables target);
 
     /*!
      * \brief Resolves the foreign key in a flight entry
@@ -313,6 +323,12 @@ public:
     bool restoreBackup(const QString& backup_file);
     bool createBackup(const QString& dest_file);
 
+    /*!
+     * \brief getTable returns all contents of a given table from the database
+     * \return
+     */
+    QVector<RowData_T> getTable(ADatabaseTables table_name);
+
 
 signals:
     /*!

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

@@ -808,10 +808,10 @@ void NewFlightDialog::addNewTail(QLineEdit *parent_line_edit)
         tailsIdMap  = aDB->getIdMap(ADatabaseTarget::tails);
         tailsList   = aDB->getCompletionList(ADatabaseTarget::registrations);
 
-        DEB << "New Entry added. Id:" << aDB->getLastEntry(ADatabaseTarget::tails);
+        DEB << "New Entry added. Id:" << aDB->getLastEntry(ADatabaseTables::tails);
         DEB << "AC Map: " << tailsIdMap;
 
-        parent_line_edit->setText(tailsIdMap.key(aDB->getLastEntry(ADatabaseTarget::tails)));
+        parent_line_edit->setText(tailsIdMap.key(aDB->getLastEntry(ADatabaseTables::tails)));
         emit parent_line_edit->editingFinished();
     } else {
         parent_line_edit->setText(QString());
@@ -840,8 +840,8 @@ void NewFlightDialog::addNewPilot(QLineEdit *parent_line_edit)
         // update map and list, set line edit
         pilotsIdMap  = aDB->getIdMap(ADatabaseTarget::pilots);
         pilotList    = aDB->getCompletionList(ADatabaseTarget::pilots);
-        DEB << "Setting new entry: " << pilotsIdMap.key(aDB->getLastEntry(ADatabaseTarget::pilots));
-        parent_line_edit->setText(pilotsIdMap.key(aDB->getLastEntry(ADatabaseTarget::pilots)));
+        DEB << "Setting new entry: " << pilotsIdMap.key(aDB->getLastEntry(ADatabaseTables::pilots));
+        parent_line_edit->setText(pilotsIdMap.key(aDB->getLastEntry(ADatabaseTables::pilots)));
         emit parent_line_edit->editingFinished();
     } else {
         parent_line_edit->setText(QString());

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

@@ -213,7 +213,7 @@ void AircraftWidget::on_deleteAircraftButton_clicked()
 void AircraftWidget::onDeleteUnsuccessful()
 {
     QList<int> foreign_key_constraints = aDB->getForeignKeyConstraints(selectedTails.first(),
-                                                                       ADatabaseTarget::tails);
+                                                                       ADatabaseTables::tails);
     QList<AFlightEntry> constrained_flights;
     for (const auto &row_id : qAsConst(foreign_key_constraints)) {
         constrained_flights.append(aDB->getFlightEntry(row_id));

+ 8 - 9
src/gui/widgets/debugwidget.cpp

@@ -28,6 +28,14 @@
 #include "src/classes/acurrencyentry.h"
 #include "src/classes/atranslator.h"
 
+#include "src/classes/ajson.h"
+void DebugWidget::on_debugPushButton_clicked()
+{
+
+    AJson::exportDatabase();
+    DEB << AStandardPaths::asChildOfDir(AStandardPaths::JSON,"file_name");
+}
+
 DebugWidget::DebugWidget(QWidget *parent) :
     QWidget(parent),
     ui(new Ui::DebugWidget)
@@ -185,15 +193,6 @@ void DebugWidget::on_importCsvPushButton_clicked()
     }
 }
 
-#include "src/functions/adate.h"
-void DebugWidget::on_debugPushButton_clicked()
-{
-    //auto frdl = new FirstRunDialog(this);
-    //frdl->exec();
-    ATranslator::installTranslator(Opl::Translations::Spanish);
-    //ui->retranslateUi(this);
-}
-
 void DebugWidget::changeEvent(QEvent *event)
 {
     if (event != nullptr)

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

@@ -194,7 +194,7 @@ void PilotsWidget::on_deletePilotButton_clicked()
 void PilotsWidget::onDeleteUnsuccessful()
 {
     const QList<int> foreign_key_constraints = aDB->getForeignKeyConstraints(selectedPilots.first(),
-                                                                       ADatabaseTarget::pilots);
+                                                                       ADatabaseTables::pilots);
     QList<AFlightEntry> constrained_flights;
     for (const auto &row_id : foreign_key_constraints) {
         constrained_flights.append(aDB->getFlightEntry(row_id));