Browse Source

Added import from JSON

- ADatabaseSetup has a new function commitDataJson, which uses a QJsonArray instead of data obtained from a CSV file.
- AJson::exportDatabase and importDatabase implemented
Felix Turo 3 years ago
parent
commit
abfc7fba79

+ 51 - 9
src/classes/ajson.cpp

@@ -1,14 +1,32 @@
+/*
+ *openPilotLog - A FOSS Pilot Logbook Application
+ *Copyright (C) 2020-2021 Felix Turowsky
+ *
+ *This program is free software: you can redistribute it and/or modify
+ *it under the terms of the GNU General Public License as published by
+ *the Free Software Foundation, either version 3 of the License, or
+ *(at your option) any later version.
+ *
+ *This program is distributed in the hope that it will be useful,
+ *but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *GNU General Public License for more details.
+ *
+ *You should have received a copy of the GNU General Public License
+ *along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
 #include "ajson.h"
+#include "src/database/adatabasesetup.h"
+
+const QList<QPair<QLatin1String, 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()
 {
-    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);
@@ -19,6 +37,24 @@ void AJson::exportDatabase()
     }
 }
 
+void AJson::importDatabase()
+{
+    TODO << "Another function should do some checking here if data exists etc...";
+    // clear tables
+    QSqlQuery q;
+    // make sure flights is cleared first due to foreign key contstraints
+    q.prepare(QLatin1String("DELETE FROM FLIGHTS"));
+    q.exec();
+    for (const auto & pair : tables) {
+        q.prepare(QLatin1String("DELETE FROM ") + pair.first);
+        q.exec();
+        const auto doc = readJson(AStandardPaths::asChildOfDir(AStandardPaths::JSON,
+                                                               pair.first + QLatin1String(".json")));
+        ADataBaseSetup::commitDataJson(doc.array(), pair.first);
+
+    }
+}
+
 void AJson::writeJson(const QJsonDocument &doc, const QString &file_name)
 {
     QFile pilots_out(AStandardPaths::asChildOfDir(AStandardPaths::JSON,file_name));
@@ -27,7 +63,13 @@ void AJson::writeJson(const QJsonDocument &doc, const QString &file_name)
     pilots_out.close();
 }
 
-void AJson::readJson(const QString &file_name)
+QJsonDocument AJson::readJson(const QString &file_path)
 {
-    TODO << "implement..." << file_name;
+    QFile file(file_path);
+    file.open(QIODevice::ReadOnly | QIODevice::Text);
+    QString raw = file.readAll();
+    file.close();
+
+    QJsonDocument doc = QJsonDocument::fromJson(raw.toUtf8());
+    return doc;
 }

+ 27 - 1
src/classes/ajson.h

@@ -1,3 +1,20 @@
+/*
+ *openPilotLog - A FOSS Pilot Logbook Application
+ *Copyright (C) 2020-2021 Felix Turowsky
+ *
+ *This program is free software: you can redistribute it and/or modify
+ *it under the terms of the GNU General Public License as published by
+ *the Free Software Foundation, either version 3 of the License, or
+ *(at your option) any later version.
+ *
+ *This program is distributed in the hope that it will be useful,
+ *but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *GNU General Public License for more details.
+ *
+ *You should have received a copy of the GNU General Public License
+ *along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
 #ifndef AJSON_H
 #define AJSON_H
 #include "src/opl.h"
@@ -22,8 +39,17 @@ public:
      */
     static void exportDatabase();
 
+    /*!
+     * \brief importDatabase imports a dataset from JSON. Files need to be at AStanardPaths::JSON for now.
+     */
+    static void importDatabase();
+
 private:
 
+    /*!
+     * \brief holds the tables with userdata that need to be processed.
+     */
+    const static QList<QPair<QLatin1String, ADatabaseTable>> tables;
     /*!
      * \brief writes a QJsonDocument to a file
      */
@@ -32,7 +58,7 @@ private:
     /*!
      * \brief To Do - Reads a file into a QJasonDocument
      */
-    static void readJson(const QString& file_name);
+    static QJsonDocument readJson(const QString& file_name);
 };
 
 #endif // AJSON_H

+ 12 - 12
src/database/adatabase.cpp

@@ -565,18 +565,18 @@ QMap<QString, RowId_T> ADatabase::getIdMap(ADatabaseTarget target)
     return id_map;
 }
 
-int ADatabase::getLastEntry(ADatabaseTables table)
+int ADatabase::getLastEntry(ADatabaseTable table)
 {
     QString statement = QLatin1String("SELECT MAX(ROWID) FROM ");
 
     switch (table) {
-    case ADatabaseTables::pilots:
+    case ADatabaseTable::pilots:
         statement.append(Opl::Db::TABLE_PILOTS);
         break;
-    case ADatabaseTables::aircraft:
+    case ADatabaseTable::aircraft:
         statement.append(Opl::Db::TABLE_AIRCRAFT);
         break;
-    case ADatabaseTables::tails:
+    case ADatabaseTable::tails:
         statement.append(Opl::Db::TABLE_TAILS);
         break;
     default:
@@ -593,15 +593,15 @@ int ADatabase::getLastEntry(ADatabaseTables table)
     }
 }
 
-QList<RowId_T> ADatabase::getForeignKeyConstraints(RowId_T foreign_row_id, ADatabaseTables target)
+QList<RowId_T> ADatabase::getForeignKeyConstraints(RowId_T foreign_row_id, ADatabaseTable target)
 {
     QString statement = QLatin1String("SELECT ROWID FROM flights WHERE ");
 
     switch (target) {
-    case ADatabaseTables::pilots:
+    case ADatabaseTable::pilots:
         statement.append(QLatin1String("pic=?"));
         break;
-    case ADatabaseTables::tails:
+    case ADatabaseTable::tails:
         statement.append(QLatin1String("acft=?"));
         break;
     default:
@@ -762,20 +762,20 @@ bool ADatabase::createBackup(const QString& dest_file)
     return true;
 }
 
-QVector<RowData_T> ADatabase::getTable(ADatabaseTables table_name)
+QVector<RowData_T> ADatabase::getTable(ADatabaseTable table_name)
 {
     auto query_str = QStringLiteral("SELECT * FROM ");
     switch (table_name) {
-    case ADatabaseTables::pilots:
+    case ADatabaseTable::pilots:
         query_str.append(Opl::Db::TABLE_PILOTS);
         break;
-    case ADatabaseTables::tails:
+    case ADatabaseTable::tails:
         query_str.append(Opl::Db::TABLE_TAILS);
         break;
-    case ADatabaseTables::flights:
+    case ADatabaseTable::flights:
         query_str.append(Opl::Db::TABLE_FLIGHTS);
         break;
-    case ADatabaseTables::currencies:
+    case ADatabaseTable::currencies:
         query_str.append(Opl::Db::TABLE_CURRENCIES);
     default:
         break;

+ 4 - 4
src/database/adatabase.h

@@ -68,7 +68,7 @@ enum class ADatabaseTarget
     aircraft
 };
 
-enum class ADatabaseTables
+enum class ADatabaseTable
 {
     tails,
     flights,
@@ -284,13 +284,13 @@ public:
     /*!
      * \brief returns the ROWID for the newest entry in the respective database.
      */
-    int getLastEntry(ADatabaseTables table);
+    int getLastEntry(ADatabaseTable 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, ADatabaseTables target);
+    QList<RowId_T> getForeignKeyConstraints(RowId_T foreign_row_id, ADatabaseTable target);
 
     /*!
      * \brief Resolves the foreign key in a flight entry
@@ -326,7 +326,7 @@ public:
      * \brief getTable returns all contents of a given table from the database
      * \return
      */
-    QVector<RowData_T> getTable(ADatabaseTables table_name);
+    QVector<RowData_T> getTable(ADatabaseTable table_name);
 
 
 signals:

+ 43 - 0
src/database/adatabasesetup.cpp

@@ -310,6 +310,8 @@ bool ADataBaseSetup::downloadTemplates()
     }
     return true;
 }
+
+QT_DEPRECATED
 bool ADataBaseSetup::backupOldData()
 {
     LOG << "Backing up old database...";
@@ -502,3 +504,44 @@ bool ADataBaseSetup::commitData(QVector<QStringList> from_csv, const QString &ta
         return true;
     }
 }
+
+bool ADataBaseSetup::commitDataJson(const QJsonArray &json_arr, const QString &table_name)
+{
+    aDB->updateLayout();
+    QSqlQuery q;
+
+    // create insert statement
+    QString statement = QLatin1String("INSERT INTO ") + table_name + QLatin1String(" (");
+    QString placeholder = QStringLiteral(") VALUES (");
+    for (const auto &column_name : aDB->getTableColumns(table_name)) {
+        statement += column_name + ',';
+        placeholder.append(QLatin1Char(':') + column_name + QLatin1Char(','));
+    }
+
+    statement.chop(1);
+    placeholder.chop(1);
+    placeholder.append(')');
+    statement.append(placeholder);
+
+    q.prepare(QStringLiteral("BEGIN EXCLUSIVE TRANSACTION"));
+    q.exec();
+    //DEB << statement;
+    for (const auto &entry : json_arr) {
+        q.prepare(statement);
+
+        auto object = entry.toObject();
+        const auto keys = object.keys();
+        for (const auto &key : keys){
+            object.value(key).isNull() ? q.bindValue(key, QVariant(QVariant::String)) :
+                                         q.bindValue(QLatin1Char(':') + key, object.value(key).toVariant());
+        }
+
+        q.exec();
+    }
+
+    q.prepare(QStringLiteral("COMMIT"));
+    if (q.exec())
+        return true;
+    else
+        return false;
+}

+ 7 - 0
src/database/adatabasesetup.h

@@ -51,6 +51,13 @@ public:
 
     static bool commitData(QVector<QStringList> from_csv, const QString &table_name);
 
+    /*!
+     * \brief commitDataJson Commits data read from a JSON array to the database.
+     * \param json_arr
+     * \param table_name The table that will be written to
+     */
+    static bool commitDataJson(const QJsonArray &json_arr, const QString &table_name);
+
 private:
 
     static bool createSchemata(const QStringList &statements);

+ 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(ADatabaseTables::tails);
+        DEB << "New Entry added. Id:" << aDB->getLastEntry(ADatabaseTable::tails);
         DEB << "AC Map: " << tailsIdMap;
 
-        parent_line_edit->setText(tailsIdMap.key(aDB->getLastEntry(ADatabaseTables::tails)));
+        parent_line_edit->setText(tailsIdMap.key(aDB->getLastEntry(ADatabaseTable::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(ADatabaseTables::pilots));
-        parent_line_edit->setText(pilotsIdMap.key(aDB->getLastEntry(ADatabaseTables::pilots)));
+        DEB << "Setting new entry: " << pilotsIdMap.key(aDB->getLastEntry(ADatabaseTable::pilots));
+        parent_line_edit->setText(pilotsIdMap.key(aDB->getLastEntry(ADatabaseTable::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(),
-                                                                       ADatabaseTables::tails);
+                                                                       ADatabaseTable::tails);
     QList<AFlightEntry> constrained_flights;
     for (const auto &row_id : qAsConst(foreign_key_constraints)) {
         constrained_flights.append(aDB->getFlightEntry(row_id));

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

@@ -31,7 +31,9 @@
 #include "src/classes/ajson.h"
 void DebugWidget::on_debugPushButton_clicked()
 {
-    DEB << aDB->getEntryData(DataPosition("tails",1));
+    //AJson::exportDatabase();
+    AJson::importDatabase();
+    emit aDB->dataBaseUpdated();
 }
 
 DebugWidget::DebugWidget(QWidget *parent) :

+ 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(),
-                                                                       ADatabaseTables::pilots);
+                                                                       ADatabaseTable::pilots);
     QList<AFlightEntry> constrained_flights;
     for (const auto &row_id : foreign_key_constraints) {
         constrained_flights.append(aDB->getFlightEntry(row_id));