Browse Source

Cleaned table filling logic, impl createLocalBackup, added debug macros

Added INFO, WARN, CRIT macros that use qInfo, q... respectively for more fine tuned debugging. As a comment implies the convention of their use should b discussed.
George 4 years ago
parent
commit
020e4f1178

+ 58 - 0
src/database/adatabase.cpp

@@ -715,3 +715,61 @@ QMap<QString, QString> ADatabase::databaseSummary(const QString &db_path)
 
     return return_values;
 }
+
+/*!
+ * \brief ADatabase::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)
+{
+    INFO << "Backing up current database to: " << dest_file;
+    ADatabase::disconnect();
+    QFile file(databaseFile.absoluteFilePath());
+    DEB << "File:" << file;  // [G]: Check adebug.h got INFO WARN, ... additions and discuss convention of use.
+
+    if (!file.copy(dest_file)) {
+        WARN << "Unable to backup old database.";
+        DEB << file.errorString();
+        return false;
+    }
+
+    INFO << "Backed up old database as:" << dest_file;
+    ADatabase::connect();
+    return true;
+}
+
+/*!
+ * \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'
+ * \return
+ */
+bool ADatabase::restoreBackup(const QString& backup_file)
+{
+    INFO << "Restoring backup from file:" << backup_file;
+
+    ADatabase::disconnect();
+    QFile backup(backup_file);
+    QFile current_db(databaseFile.absoluteFilePath());
+
+    if(!backup.isWritable()) {
+        WARN << backup << "is not writtable check PERMISSIONS";
+        return false;
+    }
+
+    // [G]: Wrong permissions would end up making a inf loop
+    // So i go defensively by checking first
+    if (!backup.copy(databaseFile.absoluteFilePath()))
+    {
+        WARN << "Could not copy" << backup << "to" << databaseFile;
+        return false;
+    }
+
+    if (!current_db.remove(databaseFile.absoluteFilePath())) {
+        WARN << "Unable to restore backup. The following error has ocurred:" << current_db.errorString();
+        return false;
+    }
+
+    INFO << "Backup successfully restored!";
+    ADatabase::connect();
+    return true;
+}

+ 2 - 0
src/database/adatabase.h

@@ -287,6 +287,8 @@ public:
      */
     QMap<QString, QString> databaseSummary(const QString& db_path);
 
+    bool restoreBackup(const QString& backup_file);
+    bool createBackup(const QString& dest_file);
 
 
 signals:

+ 2 - 0
src/functions/alog.h

@@ -18,6 +18,8 @@
 #ifndef ALOG_H
 #define ALOG_H
 
+#include <QDebug>
+
 /* Use QTextStream to print status messages. These messages
  * are oriented towards end-users and will persist even when
  * compiling a release without enabling qDebug. As such, LOG

+ 56 - 28
src/gui/widgets/backupwidget.cpp

@@ -34,6 +34,9 @@ BackupWidget::BackupWidget(QWidget *parent) :
      */
 
 
+    model = new QStandardItemModel(this);
+    model->setHorizontalHeaderLabels(QStringList{"Backup File","Total Flights", "Total Tails",
+                                                 "Total Pilots", "Max Doft", "Total Time"});  // [G]: TODO make const but where?
     fillTableWithSampleData();
 }
 
@@ -43,28 +46,66 @@ BackupWidget::~BackupWidget()
 }
 
 
-void BackupWidget::on_tableView_clicked(const QModelIndex &index) {
-    selected = model->item(index.row(), 0);
-    DEB << "Item at row:" << index.row() << "->" << selected->data(Qt::DisplayRole);
+void BackupWidget::on_tableView_clicked(const QModelIndex &index)
+{
+    selectedBackupName = model->item(index.row(), 0);
+    DEB << "Item at row:" << index.row() << "->" << selectedBackupName->data(Qt::DisplayRole);
 }
 
 void BackupWidget::on_createLocalPushButton_clicked()
 {
-    // Copy database to backupdir
+    NOT_IMPLEMENTED
+    QString filename = QFileDialog::getSaveFileName(
+                this,
+                "Choose destination file",
+                AStandardPaths::directory(AStandardPaths::Backup).absolutePath(),
+                "*.db"
+    );
+
+    if(filename.endsWith(".db") == false) {  // [G]: clunky im sure it can be enforced by QFileDialog
+        filename.append(".db");
+    }
+
+    if(aDB->createBackup(filename) == false) {
+        WARN << "Could not create local file:" << filename;
+    }
+
+    // [G] TODO: propably make a function out of this for future tweaks
+    QFileIconProvider provider;
+    QMap<QString, QString> summary = aDB->databaseSummary(filename);
+    model->appendRow({new QStandardItem(provider.icon(QFileIconProvider::File), QFileInfo(filename).baseName()),
+                      new QStandardItem(summary["total_flights"]),
+                      new QStandardItem(summary["total_tails"]),
+                      new QStandardItem(summary["total_pilots"]),
+                      new QStandardItem(summary["max_doft"]),
+                      new QStandardItem(summary["total_time"])
+                     });
 }
 
 void BackupWidget::on_restoreLocalPushButton_clicked()
 {
-    // Restore the selected entry from the list
+    if(selectedBackupName == nullptr) {
+        INFO << "No backup selected";
+        return;
+    }
+    QString backup_name = selectedBackupName->data(Qt::DisplayRole).toString();
+    if(aDB->restoreBackup(backup_name) == false) {
+        WARN << "Couldnt restore" << backup_name;
+    }
 }
 
 void BackupWidget::on_deleteSelectedPushButton_clicked()
 {
-    DEB << "deleting:" << selected->data(Qt::DisplayRole);
+    if(selectedBackupName == nullptr) {
+        INFO << "No backup was selected";
+        return;
+    }
+    DEB << "deleting:" << selectedBackupName->data(Qt::DisplayRole);
 }
 
 void BackupWidget::on_createExternalPushButton_clicked()
 {
+    NOT_IMPLEMENTED
     QString filename = QFileDialog::getSaveFileName(
                 this,
                 "Choose destination file",
@@ -78,6 +119,7 @@ void BackupWidget::on_createExternalPushButton_clicked()
 
 void BackupWidget::on_restoreExternalPushButton_clicked()
 {
+    NOT_IMPLEMENTED
     QString filename = QFileDialog::getSaveFileName(
                 this,
                 "Choose backup file",
@@ -106,42 +148,28 @@ void BackupWidget::fillTableWithSampleData()
     // First column in table, would be created by listing the files in backupdir
     QDir backup_dir = QDir(AStandardPaths::directory(AStandardPaths::Backup));
     QStringList entries = backup_dir.entryList(QStringList{"*.db"}, QDir::Files, QDir::Time);
-    QList<QStandardItem*> filenames;
     QFileIconProvider provider;
 
-    for(auto& entry : entries) {
-        auto item = new QStandardItem(entry);
-        item->setIcon(provider.icon(QFileIconProvider::File));
-        filenames.append(item);
-    }
-
     // [G]: works but a bit too hardcoded perhaps? The aviation industry wont change overnight
     // but still it could be worthwile to at least have the names a bit more encapsulated in the
     // database so we have them more "centralised" at least.
 
     // Get summary of each db file and populate lists (columns) of data
-    QList<QStandardItem *> total_flights, total_tails, total_pilots, max_doft, total_time;
     for (const auto &entry : entries) {
         QMap<QString, QString> summary = aDB->databaseSummary(backup_dir.absoluteFilePath(entry));
-        total_flights.append(new QStandardItem(summary["total_flights"]));
-        total_tails.append(new QStandardItem(summary["total_tails"]));
-        total_pilots.append(new QStandardItem(summary["total_pilots"]));
-        max_doft.append(new QStandardItem(summary["max_doft"]));
-        total_time.append(new QStandardItem(summary["total_time"]));
+
+        model->appendRow({new QStandardItem(provider.icon(QFileIconProvider::File), entry),
+                          new QStandardItem(summary["total_flights"]),
+                          new QStandardItem(summary["total_tails"]),
+                          new QStandardItem(summary["total_pilots"]),
+                          new QStandardItem(summary["max_doft"]),
+                          new QStandardItem(summary["total_time"])
+                         });
     }
 
     // [G]: Sort entries? based on what? the files are abit inconsistent in their naming atm
     // but i assume we could sort based on the time in the file name?
 
-    model = new QStandardItemModel(this);
-    model->insertColumn(0, filenames);
-    model->insertColumn(1, total_flights);  // flight
-    model->insertColumn(2, total_tails);  // tails
-    model->insertColumn(3, total_pilots);  // pilots
-    model->insertColumn(4, max_doft);  // doft
-    model->insertColumn(5, total_time);  // time
-    model->setHorizontalHeaderLabels(QStringList{"Backup File","Total Flights", "Total Tails",
-                                                 "Total Pilots", "Max Doft", "Total Time"});  // [G]: TODO make const but where?
     ui->tableView->setModel(model);
     ui->tableView->resizeColumnsToContents();  // [G]: Bit hacky couldnt do it by default
 }

+ 2 - 1
src/gui/widgets/backupwidget.h

@@ -38,7 +38,8 @@ private:
     Ui::BackupWidget *ui;
 
     QStandardItemModel *model;
-    QStandardItem *selected;
+    QStandardItem *selectedBackupName = nullptr;  // The QStandardItemModel returns QStandardItem
+                                                  // even for single cells
 
     void fillTableWithSampleData();
 };

+ 16 - 0
src/testing/adebug.h

@@ -11,10 +11,26 @@
     #define FUNC_IDENT __func__
 #endif
 
+// CAUTION: qDebug() doesnt print for non-DEBUG builds
 #define DEB qDebug() << FUNC_IDENT << "\n\t"
 #define DEB_SRC DEB
 #define DEB_RAW qDebug() << '\t'
 
+
+// [G]: TODO study cross platform terminal coloring
+// might be silly but coloring specific words does increase
+// ease of reading debug output. We dont have to go overboard
+// start with the header.
+// DRAFT:
+// info -> white
+// warning -> yellow
+// critical -> red
+// there is also fatal which even kills the program and could be purple.
+#define INFO qInfo() << "info:"
+#define WARN qWarning() << "warning:"
+#define CRIT qCritical() << "critical:"
+#define NOT_IMPLEMENTED qCritical() << FUNC_IDENT << "\n\t" << "~~ NOT IMPLEMENTED ~~";
+
 /*!
  * Representation macro for custom classes.
  *