Răsfoiți Sursa

Added export to CSV Dialog

Added a Dialog which exports the database to a CSV file
Felix Turowsky 2 ani în urmă
părinte
comite
444dd6bf33

+ 3 - 0
CMakeLists.txt

@@ -49,6 +49,9 @@ set(PROJECT_SOURCES
     src/gui/dialogues/newsimdialog.h
     src/gui/dialogues/newsimdialog.cpp
     src/gui/dialogues/newsimdialog.ui
+    src/gui/dialogues/exporttocsvdialog.h
+    src/gui/dialogues/exporttocsvdialog.cpp
+    src/gui/dialogues/exporttocsvdialog.ui
     # Widgets
     src/gui/widgets/tailswidget.h
     src/gui/widgets/tailswidget.cpp

+ 45 - 0
assets/database/database_schema.sql

@@ -283,4 +283,49 @@ CAST(SUM(toDay) AS INT) AS 'TO Day',
 CAST(SUM(toNight) AS INT) AS 'TO Night',  
 CAST(SUM(ldgDay) AS INT) AS 'LDG Day', 
 CAST(SUM(ldgNight) AS INT) AS 'LDG Night'  
+FROM flights;
+
+DROP VIEW IF EXISTS 'viewExport';
+CREATE VIEW viewExport AS
+SELECT  flight_id,
+doft as 'Date',
+dept AS 'Dept',
+printf('%02d',(tofb/60))||':'||printf('%02d',(tofb%60)) AS 'Time Out',
+dest AS 'Dest',
+printf('%02d',(tonb/60))||':'||printf('%02d',(tonb%60)) AS 'Time In ',
+CASE  WHEN variant IS NOT NULL THEN make||' '||model||'-'||variant  ELSE make||' '||model  END  AS 'Type',
+registration AS 'Registration',
+(SELECT printf('%02d',(tSPSE/60))||':'||printf('%02d',(tSPSE%60)) WHERE tSPSE IS NOT NULL) AS 'SP SE',
+(SELECT printf('%02d',(tSPME/60))||':'||printf('%02d',(tSPME%60)) WHERE tSPME IS NOT NULL) AS 'SP ME',
+(SELECT printf('%02d',(tMP/60))||':'||printf('%02d',(tMP%60)) WHERE tMP IS NOT NULL) AS 'MP',
+printf('%02d',(tblk/60))||':'||printf('%02d',(tblk%60)) AS 'Total',
+CASE  WHEN pilot_id = 1 THEN alias  ELSE lastname||', '||substr(firstname, 1, 1)||'.'  END  AS 'Name PIC',
+toDay AS 'Take-Off Day',
+ldgDay AS 'Landings Day',
+toNight AS 'Take-Off Night',
+ldgNight AS 'Landings Night',
+(SELECT printf('%02d',(tNight/60))||':'||printf('%02d',(tNight%60)) WHERE tNight IS NOT NULL)  AS 'Night',
+(SELECT printf('%02d',(tIFR/60))||':'||printf('%02d',(tIFR%60)) WHERE tIFR IS NOT NULL)  AS 'IFR',
+(SELECT printf('%02d',(tPIC/60))||':'||printf('%02d',(tPIC%60)) WHERE tPIC IS NOT NULL)  AS 'PIC',
+(SELECT printf('%02d',(tSIC/60))||':'||printf('%02d',(tSIC%60)) WHERE tSIC IS NOT NULL)  AS 'SIC',
+(SELECT printf('%02d',(tDual/60))||':'||printf('%02d',(tDual%60)) WHERE tDual IS NOT NULL)  AS 'Dual',
+(SELECT printf('%02d',(tFI/60))||':'||printf('%02d',(tFI%60)) WHERE tFI IS NOT NULL)  AS 'FI',
+null AS 'Sim Type',
+null AS 'Time of Session',
+remarks AS 'Remarks'
 FROM flights
+INNER JOIN pilots on flights.pic = pilots.pilot_id
+INNER JOIN tails on flights.acft = tails.tail_id
+UNION
+SELECT (session_id * -1),
+date,
+null,  null,  null,  null,
+aircraftType,
+registration,
+null,  null,  null,
+'SIM',
+null,  null,  null,  null,  null,  null,  null,  null,  null,  null, null,
+deviceType,  printf('%02d',(totalTime/60))||':'||printf('%02d',(totalTime%60)),
+remarks
+FROM simulators
+ORDER BY date DESC;

+ 24 - 0
src/functions/readcsv.h

@@ -18,6 +18,7 @@
 #ifndef READCSV_H
 #define READCSV_H
 
+#include "src/opl.h"
 #include<QtCore>
 
 namespace CSV {
@@ -75,6 +76,29 @@ static inline QVector<QStringList> readCsvAsRows(const QString &file_name)
     return csv_rows;
 }
 
+/*!
+ * \brief writeCsv write to a CSV file
+ * \param output file Path
+ * \param rows
+ * \return
+ */
+static inline bool writeCsv(const QString &fileName, const QVector<QVector<QString>> &rows)
+{
+    QFile csvFile(fileName);
+    if(!csvFile.open(QIODevice::ReadWrite | QFile::Text))
+        return false;
+    QTextStream stream(&csvFile);
+
+    // write each line
+    for(const auto &line : rows) {
+        for(int i = 0; i < line.size() - 1; i++) {
+            stream << line[i] + QLatin1Char(',');
+        }
+        stream << line.last() + QStringLiteral("\n");
+    }
+    return true;
+}
+
 } // namespace CSV
 
 #endif // READCSV_H

+ 81 - 0
src/gui/dialogues/exporttocsvdialog.cpp

@@ -0,0 +1,81 @@
+#include "exporttocsvdialog.h"
+#include "QtSql/qsqlfield.h"
+#include "QtSql/qsqlrecord.h"
+#include "QtSql/qsqltablemodel.h"
+#include "QtWidgets/qfiledialog.h"
+#include "ui_exporttocsvdialog.h"
+#include "src/functions/readcsv.h"
+
+ExportToCsvDialog::ExportToCsvDialog(QWidget *parent) :
+    QDialog(parent),
+    ui(new Ui::ExportToCsvDialog)
+{
+    ui->setupUi(this);
+    init();
+}
+
+ExportToCsvDialog::~ExportToCsvDialog()
+{
+    delete ui;
+}
+
+void ExportToCsvDialog::on_exportPushButton_clicked()
+{
+    selectRows();
+    // File Dialog where to save
+    QString filePath = QFileDialog::getSaveFileName(this, tr("Select Location"));
+    if(!filePath.endsWith(QStringLiteral(".csv")))
+        filePath += ".csv";
+    DEB << filePath;
+    if(!selectedRows.isEmpty()) {
+        if(CSV::writeCsv(filePath, selectedRows)) {
+            INFO("Database successfully exported.");
+            QDialog::accept();
+        } else {
+            WARN("Unable to save csv file.");
+        }
+    }
+}
+
+void ExportToCsvDialog::init()
+{
+    OPL::GLOBALS->fillViewNamesComboBox(ui->viewComboBox);
+    ui->viewComboBox->addItem(tr("Default - Export"));
+    ui->viewComboBox->setCurrentIndex(5);
+}
+
+void ExportToCsvDialog::selectRows()
+{
+    selectedRows.clear();
+    // create a QSqlTableModel based on the selected views
+    const auto model = new QSqlTableModel(this);
+    if(ui->viewComboBox->currentIndex() < 4)
+        model->setTable(OPL::GLOBALS->getViewIdentifier(OPL::DbViewName(ui->viewComboBox->currentIndex())));
+    else
+        model->setTable(exportView);
+    model->select();
+
+    int columns = model->record().count();
+    // check model is usable
+    if(model->rowCount() == 0 || columns == 0) {
+        WARN("Invalid Model, unable to parse CSV");
+        return;
+    }
+    QVector<QString> newRow;
+
+    // extract headers
+    for(int i = 0; i < columns; i++)
+        newRow.append(model->headerData(i, Qt::Horizontal).toString());
+    selectedRows.append(newRow);
+    newRow.clear();
+
+    // add column data
+    for(int i = 0; i < model->rowCount(); i++) {
+        const auto record = model->record(i);
+        for(int i = 0; i < columns; i++)
+            newRow.append(record.field(i).value().toString());
+        selectedRows.append(newRow);
+        newRow.clear();
+    }
+}
+

+ 33 - 0
src/gui/dialogues/exporttocsvdialog.h

@@ -0,0 +1,33 @@
+#ifndef EXPORTTOCSVDIALOG_H
+#define EXPORTTOCSVDIALOG_H
+
+#include <QDialog>
+
+namespace Ui {
+class ExportToCsvDialog;
+}
+
+class ExportToCsvDialog : public QDialog
+{
+    Q_OBJECT
+
+public:
+    explicit ExportToCsvDialog(QWidget *parent = nullptr);
+    ~ExportToCsvDialog();
+
+private slots:
+    void on_exportPushButton_clicked();
+
+private:
+    Ui::ExportToCsvDialog *ui;
+    QVector<QVector<QString>> selectedRows;
+    const static inline QString exportView = "viewExport";
+
+    void init();
+    /*!
+     * \brief fill the selectedRows vector with data based on the selected view
+     */
+    void selectRows();
+};
+
+#endif // EXPORTTOCSVDIALOG_H

+ 38 - 0
src/gui/dialogues/exporttocsvdialog.ui

@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ExportToCsvDialog</class>
+ <widget class="QDialog" name="ExportToCsvDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Dialog</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="0" column="0">
+    <widget class="QLabel" name="label">
+     <property name="text">
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Here you can export your logbook to print it with an online service or import it to another logbook software.&lt;br&gt;The logbook will be exported to a comma-seperated values file.&lt;br/&gt;&lt;/p&gt;&lt;p&gt;You can select a logbook style which you want to export.&lt;br/&gt;If you are not sure what to choose, select Default - Export.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="0">
+    <widget class="QComboBox" name="viewComboBox"/>
+   </item>
+   <item row="2" column="0">
+    <widget class="QPushButton" name="exportPushButton">
+     <property name="text">
+      <string>Export</string>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>

+ 8 - 0
src/gui/widgets/settingswidget.cpp

@@ -16,6 +16,7 @@
  *along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 #include "settingswidget.h"
+#include "src/gui/dialogues/exporttocsvdialog.h"
 #include "ui_settingswidget.h"
 #include "src/classes/style.h"
 #include "src/classes/settings.h"
@@ -690,3 +691,10 @@ void SettingsWidget::on_languageComboBox_activated(int arg1)
     }
 }
 
+
+void SettingsWidget::on_exportPushButton_clicked()
+{
+    auto exp = new ExportToCsvDialog(this);
+    exp->exec();
+}
+

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

@@ -90,8 +90,7 @@ private slots:
     void on_currCustom1LineEdit_editingFinished();
     void on_currCustom2LineEdit_editingFinished();
     void on_languageComboBox_activated(int arg1);
-
-
+    void on_exportPushButton_clicked();
 
 private:
     Ui::SettingsWidget *ui;

+ 13 - 6
src/gui/widgets/settingswidget.ui

@@ -984,10 +984,10 @@
        <string>Help</string>
       </attribute>
       <layout class="QGridLayout" name="gridLayout_8">
-       <item row="0" column="1">
-        <widget class="QPushButton" name="aboutPushButton">
+       <item row="1" column="1">
+        <widget class="QPushButton" name="aboutBackupsPushButton">
          <property name="text">
-          <string>About openPilotLog</string>
+          <string>About Backups</string>
          </property>
         </widget>
        </item>
@@ -1004,6 +1004,13 @@
          </property>
         </spacer>
        </item>
+       <item row="0" column="1">
+        <widget class="QPushButton" name="aboutPushButton">
+         <property name="text">
+          <string>About openPilotLog</string>
+         </property>
+        </widget>
+       </item>
        <item row="0" column="0">
         <spacer name="horizontalSpacer_7">
          <property name="orientation">
@@ -1017,10 +1024,10 @@
          </property>
         </spacer>
        </item>
-       <item row="1" column="1">
-        <widget class="QPushButton" name="aboutBackupsPushButton">
+       <item row="2" column="1">
+        <widget class="QPushButton" name="exportPushButton">
          <property name="text">
-          <string>About Backups</string>
+          <string>Export Database</string>
          </property>
         </widget>
        </item>