Browse Source

Updated sql views

Updated SQL views to just retreive data. Processing / styling done in-app now.
Felix Turowsky 1 year ago
parent
commit
22cfd234da

+ 7 - 1
CMakeLists.txt

@@ -8,7 +8,7 @@ set(CMAKE_AUTOUIC ON)
 set(CMAKE_AUTOMOC ON)
 set(CMAKE_AUTORCC ON)
 
-set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD 20)
 set(CMAKE_CXX_STANDARD_REQUIRED ON)
 
 set(QT_MIN_VERSION "5.5.1")
@@ -84,6 +84,8 @@ set(PROJECT_SOURCES
     src/gui/widgets/tailtableeditwidget.cpp
     src/gui/widgets/airporttableeditwidget.h
     src/gui/widgets/airporttableeditwidget.cpp
+    src/gui/widgets/logbooktableeditwidget.h
+    src/gui/widgets/logbooktableeditwidget.cpp
 
     # Verification
     src/gui/verification/validationstate.h
@@ -133,6 +135,8 @@ set(PROJECT_SOURCES
     src/classes/styledpilotdelegate.cpp
     src/classes/styledregistrationdelegate.h
     src/classes/styledregistrationdelegate.cpp
+    src/classes/styledtypedelegate.h
+    src/classes/styledtypedelegate.cpp
 
     # Database Entries
     src/database/flightentry.h
@@ -174,6 +178,8 @@ set(PROJECT_SOURCES
     src/database/databasecache.h
     src/database/databasecache.cpp
 
+    src/database/views/logbookviewinfo.h
+
     # Ressources
     assets/icons.qrc
     assets/database/templates.qrc

+ 120 - 114
assets/database/database_schema.sql

@@ -135,133 +135,139 @@ CREATE TABLE 'previousExperience' (
         'autoland'	INTEGER
 );
 DROP VIEW IF EXISTS 'viewDefault';
-CREATE VIEW viewDefault AS  
+CREATE VIEW viewDefault AS
 SELECT 	flight_id,
-        doft as 'Date',
-        dept AS 'Dept',
-        printf('%02d',(tofb/60))||':'||printf('%02d',(tofb%60)) AS 'Time',
-        dest AS 'Dest', printf('%02d',(tonb/60))||':'||printf('%02d',(tonb%60)) AS 'Time ',
-        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',
-        CASE  WHEN variant IS NOT NULL THEN make||' '||model||'-'||variant  ELSE make||' '||model  END  AS 'Type',
-        registration AS 'Registration',
-        FlightNumber AS 'Flight #',
-        remarks AS 'Remarks'
-FROM flights  
+        doft,
+        dept,
+        tofb,
+        dest,
+        tonb,
+        tblk,
+        pilots.pilot_id,
+        tails.tail_id,
+        tails.registration,
+        flightNumber,
+        remarks
+FROM flights
 INNER JOIN pilots on flights.pic = pilots.pilot_id
 INNER JOIN tails on flights.acft = tails.tail_id
-ORDER BY date DESC;
+ORDER BY doft DESC
 
 DROP VIEW IF EXISTS 'viewDefaultSim';
-CREATE VIEW viewDefaultSim AS 
-SELECT 	flight_id AS 'rowid',
-        doft as 'Date',
-        dept AS 'Dept',
-        printf('%02d',(tofb/60))||':'||printf('%02d',(tofb%60)) AS 'Time',
-        dest AS 'Dest', printf('%02d',(tonb/60))||':'||printf('%02d',(tonb%60)) AS 'Time ',
-        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',
-        CASE  WHEN variant IS NOT NULL THEN make||' '||model||'-'||variant  ELSE make||' '||model  END  AS 'Type',
-        registration AS 'Registration',
-        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,
-        'SIM',
-        null,
-        aircraftType,
-        registration,
-        deviceType,
-        printf('%02d',(totalTime/60))||':'||printf('%02d',(totalTime%60)),
+CREATE VIEW viewDefaultSim AS
+SELECT 	flights.flight_id,
+        flights.doft,
+        flights.dept,
+        flights.tofb,
+        flights.dest,
+        flights.tonb,
+        flights.tblk,
+        pilots.pilot_id ,
+        tails.tail_id,
+        tails.registration,
+        null AS 'deviceType',
+        null AS 'SimTime',
+        flights.remarks
+FROM flights
+INNER JOIN pilots on flights.pic = pilots.pilot_id
+INNER JOIN tails on flights.acft = tails.tail_id
+UNION
+        SELECT (simulators.session_id * -1),
+        simulators.date,
+        null, null, null, null, null, null,
+        simulators.aircraftType,
+        simulators.registration,
+        simulators.deviceType,
+        simulators.totalTime,
         remarks
-FROM simulators 
-ORDER BY date DESC;
+FROM simulators
+ORDER BY date DESC
 
 DROP VIEW IF EXISTS 'viewEasa';
-CREATE VIEW viewEasa AS  SELECT  flight_id, 
-        doft as 'Date',
-        dept AS 'Dept',
-        printf('%02d',(tofb/60))||':'||printf('%02d',(tofb%60)) AS 'Time',
-        dest AS 'Dest',
-        printf('%02d',(tonb/60))||':'||printf('%02d',(tonb%60)) AS 'Time ',
-        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',
-        ldgDay AS 'L/D',
-        ldgNight AS 'L/N',
-        (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',
-        remarks AS 'Remarks'
-FROM flights  
-INNER JOIN pilots on flights.pic = pilots.pilot_id  
-INNER JOIN tails on flights.acft = tails.tail_id  ORDER BY date DESC;
+CREATE VIEW viewEasa AS
+SELECT
+        flight_id,
+        doft,
+        dept,
+        tofb,
+        dest,
+        tonb,
+        tail_id,
+        registration,
+        tSPSE,
+        tSPME,
+        tMP,
+        tblk,
+        pilot_id,
+        ldgDay,
+        ldgNight,
+        tNight,
+        tIFR,
+        tPIC,
+        tSIC,
+        tDUAL,
+        tFI,
+        remarks
+FROM flights
+INNER JOIN pilots on flights.pic = pilots.pilot_id
+INNER JOIN tails on flights.acft = tails.tail_id  ORDER BY doft DESC
 
 DROP VIEW IF EXISTS 'viewEasaSim';
-CREATE VIEW viewEasaSim AS  SELECT  flight_id, 
-        doft as 'Date',
-        dept AS 'Dept',
-        printf('%02d',(tofb/60))||':'||printf('%02d',(tofb%60)) AS 'Time',
-        dest AS 'Dest',
-        printf('%02d',(tonb/60))||':'||printf('%02d',(tonb%60)) AS 'Time ',
-        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',
-        ldgDay AS 'L/D',
-        ldgNight AS 'L/N',
-        (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),  
+CREATE VIEW viewEasaSim AS
+SELECT  flight_id,
+        flights.doft as 'Date',
+        flights.dept,
+        flights.tofb,
+        flights.dest,
+        flights.tonb,
+        tails.tail_id AS 'Type',
+        tails.registration AS 'Registration',
+        flights.tSPSE,
+        flights.tSPME,
+        flights.tMP,
+        flights.tblk,
+        pilots.pilot_id AS 'PIC',
+        flights.ldgDay,
+        flights.ldgNight,
+        flights.tNight,
+        flights.tIFR,
+        flights.tPIC,
+        flights.tSIC,
+        flights.tDual,
+        flights.tFI,
+        null AS 'deviceType',
+        null AS 'simTime',
+        flights.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),
+        simulators.date,
+        null, null, null, null,
+        simulators.aircraftType,
+        simulators.registration,
+        null, null, null, null,
+        null, null, null, null,
+        null, null, null, null,
+        null,
+        simulators.deviceType,
+        simulators.totalTime,
+        simulators.remarks
+FROM simulators
+ORDER BY date DESC
+
+DROP VIEW IF EXISTS 'viewSimulators';
+CREATE VIEW viewSimulators AS
+SELECT (session_id * -1),
         date,
-        null,  null,  null,  null,
-        aircraftType,
         registration,
-        null,  null,  null,
-        'SIM',
-        null,  null,  null,  null,  null,  null,  null,  null,  null,
-        deviceType,  printf('%02d',(totalTime/60))||':'||printf('%02d',(totalTime%60)),
+        aircraftType,
+        deviceType,
+        totalTime,
         remarks
-FROM simulators  
-ORDER BY date DESC;
-
-DROP VIEW IF EXISTS 'viewSimulators';
-CREATE VIEW viewSimulators AS SELECT (session_id * -1),  
-        date as 'Date',
-        registration AS 'Registration',
-        aircraftType AS 'Aircraft Type',
-        deviceType 'Sim Type',
-        printf('%02d',(totalTime/60))||':'||printf('%02d',(totalTime%60)) AS 'Time of Session',
-        remarks AS 'Remarks'
-FROM simulators  
-ORDER BY date DESC;
+FROM simulators
+ORDER BY date DESC
 
 DROP VIEW IF EXISTS 'viewTails';
 CREATE VIEW viewTails AS  

+ 2 - 1
mainwindow.cpp

@@ -18,6 +18,7 @@
 #include <QToolBar>
 #include "mainwindow.h"
 #include "src/gui/widgets/airporttableeditwidget.h"
+#include "src/gui/widgets/logbooktableeditwidget.h"
 #include "src/gui/widgets/pilottableeditwidget.h"
 #include "src/gui/widgets/tailtableeditwidget.h"
 #include "ui_mainwindow.h"
@@ -32,7 +33,7 @@
 // Quick and dirty Debug area
 void MainWindow::doDebugStuff()
 {
-    AirportTableEditWidget *widget = new AirportTableEditWidget(this);
+    LogbookTableEditWidget *widget = new LogbookTableEditWidget(this);
     widget->init();
     widget->setWindowFlags(Qt::Dialog);
     widget->show();

+ 0 - 1
src/classes/styledregistrationdelegate.cpp

@@ -10,5 +10,4 @@ StyledRegistrationDelegate::StyledRegistrationDelegate(QObject *parent)
 QString StyledRegistrationDelegate::displayText(const QVariant &value, const QLocale &locale) const
 {
     return DBCache->getTailsMap().value(value.toInt());
-
 }

+ 14 - 0
src/classes/styledtypedelegate.cpp

@@ -0,0 +1,14 @@
+#include "styledtypedelegate.h"
+#include "src/database/databasecache.h"
+
+StyledTypeDelegate::StyledTypeDelegate(QObject *parent)
+    : QStyledItemDelegate{parent}
+{
+
+}
+
+QString StyledTypeDelegate::displayText(const QVariant &value, const QLocale &locale) const
+{
+    Q_UNUSED(locale);
+    return DBCache->getTypesMap().value(value.toInt());
+}

+ 16 - 0
src/classes/styledtypedelegate.h

@@ -0,0 +1,16 @@
+#ifndef STYLEDTYPEDELEGATE_H
+#define STYLEDTYPEDELEGATE_H
+
+#include <QStyledItemDelegate>
+#include <QObject>
+
+class StyledTypeDelegate : public QStyledItemDelegate
+{
+    Q_OBJECT
+public:
+    explicit StyledTypeDelegate(QObject *parent = nullptr);
+
+    QString displayText(const QVariant &value, const QLocale &locale) const override;
+};
+
+#endif // STYLEDTYPEDELEGATE_H

+ 186 - 0
src/database/views/logbookviewinfo.h

@@ -0,0 +1,186 @@
+#ifndef LOGBOOKVIEWINFO_H
+#define LOGBOOKVIEWINFO_H
+
+#include "src/opl.h"
+#include <QtCore>
+
+namespace OPL {
+
+
+/*!
+ * \brief The LogbookViewInfo class is a base class for classes that encapsulate information
+ * about a LogbookView
+ * \details In the logbook display, SQL views are used instead of raw table data, since in
+ * some cases data is aggregated from different tables. Using views avoid
+ */
+class LogbookViewInfo : public QObject {
+    Q_OBJECT // enable tr()
+public:
+    
+    /*!
+     * \brief Return the column in the view which contains the date of flight
+     */
+    static constexpr int getDateColumn(LogbookView view)
+    {
+        return DATE_COLUMNS.at(static_cast<int>(view));
+    }
+
+    /*!
+     * \brief Return the column in the view which contains the aircrafts type
+     */
+    static constexpr int getTypeColumn(LogbookView view)
+    {
+        return TYPE_COLUMNS.at(static_cast<int>(view));
+    }
+    
+    /*!
+     * \brief Return the column(s) in the view which contain pilot names
+     */
+    static constexpr int getPicColumn(LogbookView view)
+    {
+        return PIC_COLUMNS.at(static_cast<int>(view));
+    }
+    
+    /*!
+     * \brief Return the column(s) in the view which contain Time entries
+     */
+    static constexpr std::vector<int> getTimeColumns(LogbookView view)
+    {
+        switch (view) {
+        case LogbookView::Default:
+            return { 3, 5, 6 };
+        case LogbookView::DefaultWithSim:
+            return { 3, 5, 6, 11 };
+        case LogbookView::Easa:
+            return { 3, 5, 8, 9, 10, 11, 15, 16, 17, 18, 19, 20 };
+        case LogbookView::EasaWithSim:
+            return { 3, 5, 8, 9, 10, 11, 15, 16, 17, 18, 19, 20, 22 };
+        default:
+            assert(((void)"View is not implemented", false));
+            return { 0 };
+        }
+    }
+
+    // translations need to be done at runtime
+    static const QStringList getTableHeaders(LogbookView view)
+    {
+        switch (view) {
+        case LogbookView::Default:
+            return {
+                QStringLiteral("flight_id"), // flight id column - hidden
+                tr("Date of Flight"),
+                tr("Dept"),
+                tr("Time"),
+                tr("Dest"),
+                tr("Time"),
+                tr("Total"),
+                tr("Name PIC"),
+                tr("Type"),
+                tr("Registration"),
+                tr("Flight Number"),
+                tr("Remarks"),
+            };
+        case LogbookView::DefaultWithSim:
+            return {
+                QStringLiteral("flight_id"), // flight id column - hidden
+                tr("Date of Flight"),
+                tr("Dept"),
+                tr("Time"),
+                tr("Dest"),
+                tr("Time"),
+                tr("Total"),
+                tr("Name PIC"),
+                tr("Type"),
+                tr("Registration"),
+                tr("Sim Type"),
+                tr("Time of Session"),
+                tr("Remarks"),
+            };
+        case LogbookView::Easa:
+            return {
+                QStringLiteral("flight_id"), // flight id column - hidden
+                tr("Date of Flight"),
+                tr("Dept"),
+                tr("Time"),
+                tr("Dest"),
+                tr("Time"),
+                tr("Type"),
+                tr("Registration"),
+                tr("SP SE"),
+                tr("SP ME"),
+                tr("MP"),
+                tr("Total"),
+                tr("Name PIC"),
+                tr("L/D"),
+                tr("L/N"),
+                tr("Night"),
+                tr("IFR"),
+                tr("PIC"),
+                tr("SIC"),
+                tr("Dual"),
+                tr("FI"),
+                tr("Remarks"),
+            };
+        case LogbookView::EasaWithSim:
+            return {
+                QStringLiteral("flight_id"), // flight id column - hidden
+                tr("Date of Flight"),
+                tr("Dept"),
+                tr("Time"),
+                tr("Dest"),
+                tr("Time"),
+                tr("Type"),
+                tr("Registration"),
+                tr("SP SE"),
+                tr("SP ME"),
+                tr("MP"),
+                tr("Total"),
+                tr("Name PIC"),
+                tr("L/D"),
+                tr("L/N"),
+                tr("Night"),
+                tr("IFR"),
+                tr("PIC"),
+                tr("SIC"),
+                tr("Dual"),
+                tr("FI"),
+                tr("Sim Type"),
+                tr("Time of Session"),
+                tr("Remarks"),
+            };
+        default:
+            assert(((void)"View is not implemented", false));
+            return {};
+        }
+    }
+
+private:
+
+    static constexpr std::array DATE_COLUMNS {
+        1, // Default
+        1, // Default With Sim
+        1, // Easa
+        1, // Easa With Sim
+        1, // Simulator Only
+    };
+
+    static constexpr std::array TYPE_COLUMNS {
+        8, // Default
+        8, // Default With Sim
+        6, // Easa
+        6, // Easa With Sim
+        1, // Simulator Only
+    };
+
+    static constexpr std::array PIC_COLUMNS {
+        7, // Default
+        7, // Default With Sim
+        12, // Easa
+        12, // Easa With Sim
+        -1, // Simulator Only
+    };
+
+};
+
+} // namespace OPL
+#endif // LOGBOOKVIEWINFO_H

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

@@ -40,7 +40,7 @@
 
 
 NewFlightDialog::NewFlightDialog(QWidget *parent)
-    : QDialog(parent),
+    : EntryEditDialog(parent),
       ui(new Ui::NewFlightDialog)
 {
     init();
@@ -51,7 +51,7 @@ NewFlightDialog::NewFlightDialog(QWidget *parent)
 }
 
 NewFlightDialog::NewFlightDialog(int row_id, QWidget *parent)
-    : QDialog(parent),
+    : EntryEditDialog(parent),
       ui(new Ui::NewFlightDialog)
 {
     init();

+ 15 - 1
src/gui/dialogues/newflightdialog.h

@@ -26,6 +26,7 @@
 
 #include "QtWidgets/qcalendarwidget.h"
 #include "src/database/flightentry.h"
+#include "src/gui/dialogues/entryeditdialog.h"
 #include "src/gui/verification/userinput.h"
 #include "src/opl.h"
 #include "src/gui/verification/validationstate.h"
@@ -59,7 +60,7 @@ class NewFlightDialog;
  * Once the user is satisfied with his entries, a final set of input verification is triggered and the entry is submitted to the database,
  * see on_buttonBox_accepted() and Database::commit()
  */
-class NewFlightDialog : public QDialog
+class NewFlightDialog : public EntryEditDialog
 {
     Q_OBJECT
 
@@ -76,6 +77,8 @@ public:
     explicit NewFlightDialog(int row_id, QWidget* parent = nullptr);
     ~NewFlightDialog();
 
+
+
 private:
     Ui::NewFlightDialog *ui;
     ValidationState validationState;
@@ -197,6 +200,17 @@ private slots:
 
 protected:
     bool eventFilter(QObject* object, QEvent* event) override;
+
+    // EntryEditDialog interface
+public:
+    virtual void loadEntry(int rowID) override
+    {
+        LOG << "Not implemented.";
+    }
+    virtual bool deleteEntry(int rowID) override
+    {
+        LOG << "Not implemented.";
+    }
 };
 
 

+ 19 - 19
src/gui/widgets/airporttableeditwidget.cpp

@@ -8,23 +8,23 @@ AirportTableEditWidget::AirportTableEditWidget(QWidget *parent)
 
 void AirportTableEditWidget::setupModelAndView()
 {
-    model = new QSqlTableModel(this, DB->database());
-    model->setTable(OPL::GLOBALS->getDbTableName(OPL::DbTable::Airports));
-    model->select();
+    m_model = new QSqlTableModel(this, DB->database());
+    m_model->setTable(OPL::GLOBALS->getDbTableName(OPL::DbTable::Airports));
+    m_model->select();
 
     for(int i = 0; i < HEADER_NAMES.size(); i++) {
-        model->setHeaderData(i + 1, Qt::Horizontal, HEADER_NAMES.at(i));
+        m_model->setHeaderData(i + 1, Qt::Horizontal, HEADER_NAMES.at(i));
     }
 
-    view->setModel(model);
-    view->setSelectionMode(QAbstractItemView::SingleSelection);
-    view->setSelectionBehavior(QAbstractItemView::SelectRows);
-    view->setEditTriggers(QAbstractItemView::NoEditTriggers);
-    view->horizontalHeader()->setStretchLastSection(QHeaderView::Stretch);
-    view->resizeColumnsToContents();
-    view->verticalHeader()->hide();
-    view->setAlternatingRowColors(true);
-    view->hideColumn(COL_ROWID);
+    m_view->setModel(m_model);
+    m_view->setSelectionMode(QAbstractItemView::SingleSelection);
+    m_view->setSelectionBehavior(QAbstractItemView::SelectRows);
+    m_view->setEditTriggers(QAbstractItemView::NoEditTriggers);
+    m_view->horizontalHeader()->setStretchLastSection(QHeaderView::Stretch);
+    m_view->resizeColumnsToContents();
+    m_view->verticalHeader()->hide();
+    m_view->setAlternatingRowColors(true);
+    m_view->hideColumn(COL_ROWID);
 
 }
 
@@ -34,10 +34,10 @@ void AirportTableEditWidget::setupUI()
     TableEditWidget::setupUI();
 
     // only need to set the table specific labels and combo box items
-    addNewEntryPushButton->setText(tr("Add New Airport"));
-    deleteEntryPushButton->setText(tr("Delete Selected Airport"));
+    m_addNewEntryPushButton->setText(tr("Add New Airport"));
+    m_deleteEntryPushButton->setText(tr("Delete Selected Airport"));
     for(const int i : FILTER_COLUMNS) {
-        filterSelectionComboBox->addItem(HEADER_NAMES.at(i));
+        m_filterSelectionComboBox->addItem(HEADER_NAMES.at(i));
     }
 }
 
@@ -64,16 +64,16 @@ EntryEditDialog *AirportTableEditWidget::getEntryEditDialog(QWidget *parent)
 void AirportTableEditWidget::filterTextChanged(const QString &filterString)
 {
     if(filterString.isEmpty()) {
-        model->setFilter(QString());
+        m_model->setFilter(QString());
         return;
     }
 
-    int i = filterSelectionComboBox->currentIndex();
+    int i = m_filterSelectionComboBox->currentIndex();
     const QString filter =
         QLatin1Char('\"')
         + HEADER_NAMES.at(FILTER_COLUMNS[i])
         + QLatin1String("\" LIKE '%")
         + filterString
         + QLatin1String("%'");
-    model->setFilter(filter);
+    m_model->setFilter(filter);
 }

+ 95 - 0
src/gui/widgets/logbooktableeditwidget.cpp

@@ -0,0 +1,95 @@
+#include "logbooktableeditwidget.h"
+#include "src/classes/settings.h"
+#include "src/classes/styleddatedelegate.h"
+#include "src/classes/styledpilotdelegate.h"
+#include "src/classes/styledregistrationdelegate.h"
+#include "src/classes/styledtimedelegate.h"
+#include "src/classes/styledtypedelegate.h"
+#include "src/database/database.h"
+#include "src/database/views/logbookviewinfo.h"
+#include "src/gui/dialogues/newflightdialog.h"
+
+LogbookTableEditWidget::LogbookTableEditWidget(QWidget *parent)
+    : TableEditWidget(Vertical, parent)
+{}
+
+
+// TableEditWidget implementation
+
+void LogbookTableEditWidget::setupModelAndView()
+{
+    m_logbookView = Settings::getLogbookView();
+    m_model = new QSqlTableModel(this, DB->database());
+    m_model->setTable(OPL::GLOBALS->getViewIdentifier(m_logbookView));
+    m_model->select();
+
+    const auto headers = OPL::LogbookViewInfo::getTableHeaders(m_logbookView);
+    for(int i = 0; i < headers.size(); i++) {
+        m_model->setHeaderData(i, Qt::Horizontal, headers[i]);
+    }
+
+    m_view->setModel(m_model);
+    m_view->setSelectionMode(QAbstractItemView::SingleSelection);
+    m_view->setSelectionBehavior(QAbstractItemView::SelectRows);
+    m_view->setEditTriggers(QAbstractItemView::NoEditTriggers);
+    m_view->horizontalHeader()->setStretchLastSection(QHeaderView::Stretch);
+    m_view->verticalHeader()->hide();
+    m_view->setAlternatingRowColors(true);
+    m_view->hideColumn(COL_ROWID);
+
+    setupDelegates();
+    m_view->resizeColumnsToContents();
+}
+
+void LogbookTableEditWidget::setupUI()
+{
+    TableEditWidget::setupUI();
+    m_addNewEntryPushButton->setText(tr("Add new Flight"));
+    m_deleteEntryPushButton->setText(tr("Delete selected Flight"));
+    TODO << "Set up filters";
+}
+
+QString LogbookTableEditWidget::deleteErrorString(int rowId)
+{
+    return "Not implemented";
+}
+
+QString LogbookTableEditWidget::confirmDeleteString(int rowId)
+{
+    return "Not implemented";
+}
+
+EntryEditDialog *LogbookTableEditWidget::getEntryEditDialog(QWidget *parent)
+{
+    return new NewFlightDialog(parent);
+}
+
+void LogbookTableEditWidget::filterTextChanged(const QString &filterString)
+{
+    LOG << "Not implemented.";
+}
+
+// private implementations
+
+void LogbookTableEditWidget::setupDelegates()
+{
+    // minutes to hh:mm
+    const auto timeDelegate = new StyledTimeDelegate(m_model);
+    m_view->setItemDelegateForColumn(-1, timeDelegate); // shut up ctidy
+    for(const auto col : OPL::LogbookViewInfo::getTimeColumns(m_logbookView)) {
+        m_view->setItemDelegateForColumn(col, timeDelegate);
+    }
+
+    // julian day to Date Format
+    const auto dateDelegate = new StyledDateDelegate(Settings::getDateFormat(), m_model);
+    m_view->setItemDelegateForColumn(OPL::LogbookViewInfo::getDateColumn(m_logbookView), dateDelegate);
+
+    // pilot_id to names
+    const auto pilotDelegate = new StyledPilotDelegate(m_model);
+    m_view->setItemDelegateForColumn(OPL::LogbookViewInfo::getPicColumn(m_logbookView), pilotDelegate);
+
+    // tail_id to aircraft type and registration
+    const auto typeDelegate = new StyledTypeDelegate(m_model);
+    m_view->setItemDelegateForColumn(OPL::LogbookViewInfo::getTypeColumn(m_logbookView), typeDelegate);
+
+}

+ 44 - 0
src/gui/widgets/logbooktableeditwidget.h

@@ -0,0 +1,44 @@
+#ifndef LOGBOOKTABLEEDITWIDGET_H
+#define LOGBOOKTABLEEDITWIDGET_H
+
+#include "tableeditwidget.h"
+#include "src/opl.h"
+#include <QObject>
+
+/*!
+ * \brief The LogbookTableEditWidget allows editing of logbook entries.
+ *
+ * \details This widget differs from the other TableEditWidget implementations in that
+ * instead of a table, it uses a [view](https://sqlite.org/lang_createview.html) as the source of the display model.
+ *
+ * The user can select a view from a list of available views in the SettingsWidget.
+ *
+ * Some of the selectable views aggregate data from the flights and simulators table. In those views, flight
+ * entries have positive row id's whereas the simulators have inverse (negative) row id's.
+ */
+class LogbookTableEditWidget : public TableEditWidget
+{
+    Q_OBJECT
+public:
+    LogbookTableEditWidget() = delete;
+    explicit LogbookTableEditWidget(QWidget *parent = nullptr);
+
+private:
+    OPL::LogbookView m_logbookView;
+    void setupDelegates();
+
+    static constexpr int COL_ROWID = 0;
+
+    // TableEditWidget interface
+public:
+    virtual void setupModelAndView() override;
+    virtual void setupUI() override;
+    virtual QString deleteErrorString(int rowId) override;
+    virtual QString confirmDeleteString(int rowId) override;
+    virtual EntryEditDialog *getEntryEditDialog(QWidget *parent) override;
+
+private slots:
+    virtual void filterTextChanged(const QString &filterString) override;
+};
+
+#endif // LOGBOOKTABLEEDITWIDGET_H

+ 22 - 22
src/gui/widgets/pilottableeditwidget.cpp

@@ -11,24 +11,24 @@ PilotTableEditWidget::PilotTableEditWidget(QWidget *parent)
 
 void PilotTableEditWidget::setupModelAndView()
 {
-    model = new QSqlTableModel(this, DB->database());
-    model->setTable(OPL::GLOBALS->getDbTableName(OPL::DbTable::Pilots));
-    model->select();
-    model->setHeaderData(COL_LASTNAME, Qt::Horizontal, tr("Last Name"));
-    model->setHeaderData(COL_FIRSTNAME, Qt::Horizontal, tr("First Name"));
-    model->setHeaderData(COL_COMPANY, Qt::Horizontal, tr("Company"));
-    model->setFilter(QStringLiteral("%1 > 1").arg(OPL::PilotEntry::ROWID)); // hide self
+    m_model = new QSqlTableModel(this, DB->database());
+    m_model->setTable(OPL::GLOBALS->getDbTableName(OPL::DbTable::Pilots));
+    m_model->select();
+    m_model->setHeaderData(COL_LASTNAME, Qt::Horizontal, tr("Last Name"));
+    m_model->setHeaderData(COL_FIRSTNAME, Qt::Horizontal, tr("First Name"));
+    m_model->setHeaderData(COL_COMPANY, Qt::Horizontal, tr("Company"));
+    m_model->setFilter(QStringLiteral("%1 > 1").arg(OPL::PilotEntry::ROWID)); // hide self
 
-    view->setModel(model);
-    view->setSelectionMode(QAbstractItemView::SingleSelection);
-    view->setSelectionBehavior(QAbstractItemView::SelectRows);
-    view->setEditTriggers(QAbstractItemView::NoEditTriggers);
-    view->horizontalHeader()->setStretchLastSection(QHeaderView::Stretch);
-    view->resizeColumnsToContents();
-    view->verticalHeader()->hide();
-    view->setAlternatingRowColors(true);
+    m_view->setModel(m_model);
+    m_view->setSelectionMode(QAbstractItemView::SingleSelection);
+    m_view->setSelectionBehavior(QAbstractItemView::SelectRows);
+    m_view->setEditTriggers(QAbstractItemView::NoEditTriggers);
+    m_view->horizontalHeader()->setStretchLastSection(QHeaderView::Stretch);
+    m_view->resizeColumnsToContents();
+    m_view->verticalHeader()->hide();
+    m_view->setAlternatingRowColors(true);
     for(const int i : COLS_TO_HIDE)
-        view->hideColumn(i);
+        m_view->hideColumn(i);
 
 }
 
@@ -38,9 +38,9 @@ void PilotTableEditWidget::setupUI()
     TableEditWidget::setupUI();
 
     // only need to set the table specific labels and combo box items
-    addNewEntryPushButton->setText(tr("Add New Pilot"));
-    deleteEntryPushButton->setText(tr("Delete Selected Pilot"));
-    filterSelectionComboBox->addItems(FILTER_COLUMNS);
+    m_addNewEntryPushButton->setText(tr("Add New Pilot"));
+    m_deleteEntryPushButton->setText(tr("Delete Selected Pilot"));
+    m_filterSelectionComboBox->addItems(FILTER_COLUMNS);
 }
 
 EntryEditDialog *PilotTableEditWidget::getEntryEditDialog(QWidget *parent)
@@ -93,11 +93,11 @@ QString PilotTableEditWidget::confirmDeleteString(int rowId)
 void PilotTableEditWidget::filterTextChanged(const QString &filterText)
 {
     if(filterText.isEmpty()) {
-        model->setFilter(QStringLiteral("%1 > 1").arg(OPL::PilotEntry::ROWID)); // hide self
+        m_model->setFilter(QStringLiteral("%1 > 1").arg(OPL::PilotEntry::ROWID)); // hide self
         return;
     }
 
-    int i = filterSelectionComboBox->currentIndex();
+    int i = m_filterSelectionComboBox->currentIndex();
     const QString filter =
         QLatin1Char('\"')
         + FILTER_COLUMN_NAMES.at(i)
@@ -106,7 +106,7 @@ void PilotTableEditWidget::filterTextChanged(const QString &filterText)
         + QLatin1String("%' AND ")
         + OPL::PilotEntry::ROWID
         + QLatin1String(" > 1");
-    model->setFilter(filter);
+    m_model->setFilter(filter);
 }
 
 

+ 52 - 50
src/gui/widgets/tableeditwidget.cpp

@@ -5,7 +5,7 @@
 #include <QLabel>
 
 TableEditWidget::TableEditWidget(Orientation orientation, QWidget *parent)
-    : QWidget{parent}, _orientation(orientation)
+    : QWidget{parent}, m_orientation(orientation)
 {}
 
 void TableEditWidget::init() {
@@ -17,11 +17,11 @@ void TableEditWidget::setupUI()
 {
     // Setting up the model and view is done in the derived class
     setupModelAndView();
-    _entryEditDialog = getEntryEditDialog(this);
-    stackedWidget->addWidget(_entryEditDialog);
+    m_entryEditDialog = getEntryEditDialog(this);
+    m_stackedWidget->addWidget(m_entryEditDialog);
 
     // set up the UI
-    switch (_orientation) {
+    switch (m_orientation) {
     case Horizontal:
         setupHorizontalUI();
         break;
@@ -36,7 +36,7 @@ void TableEditWidget::setupUI()
 void TableEditWidget::setupHorizontalUI()
 {
     // In the horizontal view, the editing widget is hidden on the right hand side
-    stackedWidget->hide();
+    m_stackedWidget->hide();
 
     // create a 2-column grid layout and fill the cells
     int colL = 0; // left column
@@ -46,16 +46,16 @@ void TableEditWidget::setupHorizontalUI()
 
     auto gridLayout = new QGridLayout(this);
 
-    gridLayout->addWidget(view, row, colL);
-    gridLayout->addWidget(stackedWidget, row, colR, allRowSpan, 1);
+    gridLayout->addWidget(m_view, row, colL);
+    gridLayout->addWidget(m_stackedWidget, row, colR, allRowSpan, 1);
     row++;
 
     setupButtonWidget();
-    gridLayout->addWidget(_buttonWidget);
+    gridLayout->addWidget(m_buttonWidget);
     row++;
 
     setupFilterWidget();
-    gridLayout->addWidget(_filterWidget, row, colL);
+    gridLayout->addWidget(m_filterWidget, row, colL);
 }
 
 void TableEditWidget::setupVerticalUI()
@@ -65,20 +65,20 @@ void TableEditWidget::setupVerticalUI()
     int row = 0;
     auto gridLayout = new QGridLayout(this);
 
-    gridLayout->addWidget(view, row, col);
+    gridLayout->addWidget(m_view, row, col);
     row++;
 
-    gridLayout->addWidget(stackedWidget, row, col);
+    gridLayout->addWidget(m_stackedWidget, row, col);
     row++;
 
     setupButtonWidget();
-    gridLayout->addWidget(_buttonWidget);
+    gridLayout->addWidget(m_buttonWidget);
     row++;
 
     setupFilterWidget();
-    stackedWidget->addWidget(_filterWidget);
-    stackedWidget->setCurrentWidget(_filterWidget);
-    gridLayout->addWidget(stackedWidget);
+    m_stackedWidget->addWidget(m_filterWidget);
+    m_stackedWidget->setCurrentWidget(m_filterWidget);
+    gridLayout->addWidget(m_stackedWidget);
 }
 
 void TableEditWidget::setupFilterWidget()
@@ -89,10 +89,10 @@ void TableEditWidget::setupFilterWidget()
 
     // one row, three columns
     layout->addWidget(new QLabel(tr("Filter"), this), 0, 0);
-    layout->addWidget(filterLineEdit,				  0, 1);
-    layout->addWidget(filterSelectionComboBox,		  0, 2);
+    layout->addWidget(m_filterLineEdit,				  0, 1);
+    layout->addWidget(m_filterSelectionComboBox,		  0, 2);
 
-    _filterWidget = widget;
+    m_filterWidget = widget;
 }
 
 void TableEditWidget::setupButtonWidget()
@@ -100,20 +100,19 @@ void TableEditWidget::setupButtonWidget()
     auto buttonWidget = new QWidget(this);
     auto buttonGridLayout = new QGridLayout(buttonWidget);
 
-    switch (_orientation) {
+    switch (m_orientation) {
     case Horizontal:
-        buttonGridLayout->addWidget(addNewEntryPushButton, 0, 0);
-        buttonGridLayout->addWidget(deleteEntryPushButton, 1, 0);
+        buttonGridLayout->addWidget(m_addNewEntryPushButton, 0, 0);
+        buttonGridLayout->addWidget(m_deleteEntryPushButton, 1, 0);
         break;
     case Vertical:
-        buttonGridLayout->addWidget(addNewEntryPushButton, 0, 0);
-        buttonGridLayout->addWidget(deleteEntryPushButton, 0, 1);
+        buttonGridLayout->addWidget(m_addNewEntryPushButton, 0, 0);
+        buttonGridLayout->addWidget(m_deleteEntryPushButton, 0, 1);
     default:
         break;
     }
 
-    buttonWidget->setLayout(buttonGridLayout);
-    _buttonWidget = buttonWidget;
+    m_buttonWidget = buttonWidget;
 }
 
 void TableEditWidget::setupSignalsAndSlots()
@@ -122,44 +121,42 @@ void TableEditWidget::setupSignalsAndSlots()
     QObject::connect(DB,             		   &OPL::Database::dataBaseUpdated,
                      this,     		 		   &TableEditWidget::databaseContentChanged);
     // filter the view
-    QObject::connect(filterLineEdit,  		   &QLineEdit::textChanged,
+    QObject::connect(m_filterLineEdit,  		   &QLineEdit::textChanged,
                      this,                     &TableEditWidget::filterTextChanged);
     // sort the view by column
-    QObject::connect(view->horizontalHeader(), &QHeaderView::sectionClicked,
+    QObject::connect(m_view->horizontalHeader(), &QHeaderView::sectionClicked,
                      this,                     &TableEditWidget::sortColumnChanged);
     // Edit an entry
-    QObject::connect(view,					   &QTableView::clicked,
+    QObject::connect(m_view,					   &QTableView::clicked,
                      this, 			    	   &TableEditWidget::editEntryRequested);
     // Add a new entry
-    QObject::connect(addNewEntryPushButton,    &QPushButton::clicked,
+    QObject::connect(m_addNewEntryPushButton,    &QPushButton::clicked,
                      this, 					   &TableEditWidget::addEntryRequested);
     // Delete a selected entry
-    QObject::connect(deleteEntryPushButton,    &QPushButton::clicked,
+    QObject::connect(m_deleteEntryPushButton,    &QPushButton::clicked,
                      this, 					   &TableEditWidget::deleteEntryRequested);
 }
 
 void TableEditWidget::addEntryRequested()
 {
-    auto editDialog = getEntryEditDialog(this);
-    editDialog->exec();
+    getEntryEditDialog(this)->exec();
 }
 
-
 void TableEditWidget::editEntryRequested(const QModelIndex &selectedIndex)
 {
-    int rowId = model->index(selectedIndex.row(), 0).data().toInt();
-    _entryEditDialog->loadEntry(rowId);
-    stackedWidget->setCurrentWidget(_entryEditDialog);
+    int rowId = m_model->index(selectedIndex.row(), 0).data().toInt();
+    m_entryEditDialog->loadEntry(rowId);
+    m_stackedWidget->setCurrentWidget(m_entryEditDialog);
 
-    switch (_orientation) {
+    switch (m_orientation) {
     case Horizontal:
-        stackedWidget->show();
-        _entryEditDialog->exec();
-        stackedWidget->hide();
+        m_stackedWidget->show();
+        m_entryEditDialog->exec();
+        m_stackedWidget->hide();
         break;
     case Vertical:
-        _entryEditDialog->exec();
-        stackedWidget->setCurrentWidget(_filterWidget);
+        m_entryEditDialog->exec();
+        m_stackedWidget->setCurrentWidget(m_filterWidget);
     default:
         break;
     }
@@ -167,16 +164,15 @@ void TableEditWidget::editEntryRequested(const QModelIndex &selectedIndex)
 
 void TableEditWidget::deleteEntryRequested()
 {
-    const QModelIndex selectedIndex = view->selectionModel()->currentIndex();
+    const QModelIndex selectedIndex = m_view->selectionModel()->currentIndex();
     if(!selectedIndex.isValid()) {
         WARN(tr("No entry selected."));
         return;
     }
+    m_stackedWidget->hide();
 
-    stackedWidget->hide();
-    //clearStackedWidget();
-    int rowId = model->index(selectedIndex.row(), 0).data().toInt();
-    view->selectionModel()->reset();
+    int rowId = m_model->index(selectedIndex.row(), 0).data().toInt();
+    m_view->selectionModel()->reset();
 
     // get user confirmation
     QMessageBox confirm(this);
@@ -191,15 +187,21 @@ void TableEditWidget::deleteEntryRequested()
         if(!editDialog->deleteEntry(rowId))
             WARN(deleteErrorString(rowId));
     }
+
+    // re-set stackedWidget for Vertical Layout
+    if(m_orientation == Vertical) {
+        m_stackedWidget->setCurrentWidget(m_filterWidget);
+        m_stackedWidget->show();
+    }
 }
 
 void TableEditWidget::sortColumnChanged(int newSortColumn)
 {
-    view->sortByColumn(newSortColumn, Qt::AscendingOrder);
+    m_view->sortByColumn(newSortColumn, Qt::AscendingOrder);
 }
 
 void TableEditWidget::databaseContentChanged()
 {
-    model->select();
-    view->resizeColumnsToContents();
+    m_model->select();
+    m_view->resizeColumnsToContents();
 }

+ 13 - 13
src/gui/widgets/tableeditwidget.h

@@ -95,19 +95,19 @@ public:
     virtual EntryEditDialog *getEntryEditDialog(QWidget *parent = nullptr) = 0;
 
 protected:
-    Orientation _orientation;
-    QSqlTableModel *model = nullptr;
-    QTableView *view = new QTableView(this);
-    QWidget *_filterWidget = nullptr;
-    QWidget *_buttonWidget = nullptr;
-    EntryEditDialog *_entryEditDialog = nullptr;
-
-    QPushButton *addNewEntryPushButton = new QPushButton(this);
-    QPushButton *deleteEntryPushButton = new QPushButton(this);
-
-    QStackedWidget *stackedWidget = new QStackedWidget(this);
-    QLineEdit *filterLineEdit = new QLineEdit(this);
-    QComboBox *filterSelectionComboBox = new QComboBox(this);
+    Orientation m_orientation;
+    QSqlTableModel *m_model = nullptr;
+    QTableView *m_view = new QTableView(this);
+    QWidget *m_filterWidget = nullptr;
+    QWidget *m_buttonWidget = nullptr;
+    EntryEditDialog *m_entryEditDialog = nullptr;
+
+    QPushButton *m_addNewEntryPushButton = new QPushButton(this);
+    QPushButton *m_deleteEntryPushButton = new QPushButton(this);
+
+    QStackedWidget *m_stackedWidget = new QStackedWidget(this);
+    QLineEdit *m_filterLineEdit = new QLineEdit(this);
+    QComboBox *m_filterSelectionComboBox = new QComboBox(this);
 
 private:
     void setupHorizontalUI();

+ 21 - 21
src/gui/widgets/tailtableeditwidget.cpp

@@ -8,23 +8,23 @@ TailTableEditWidget::TailTableEditWidget(QWidget *parent)
 
 void TailTableEditWidget::setupModelAndView()
 {
-    model = new QSqlTableModel(this, DB->database());
-    model->setTable(OPL::GLOBALS->getDbTableName(OPL::DbTable::Tails));
-    model->select();
-    model->setHeaderData(COL_REGISTRATION, Qt::Horizontal, COLUMN_NAME_REGISTRATION);
-    model->setHeaderData(COL_TYPE, Qt::Horizontal, COLUMN_NAME_TYPE);
-    model->setHeaderData(COL_COMPANY, Qt::Horizontal, COLUMN_NAME_COMPANY);
+    m_model = new QSqlTableModel(this, DB->database());
+    m_model->setTable(OPL::GLOBALS->getDbTableName(OPL::DbTable::Tails));
+    m_model->select();
+    m_model->setHeaderData(COL_REGISTRATION, Qt::Horizontal, COLUMN_NAME_REGISTRATION);
+    m_model->setHeaderData(COL_TYPE, Qt::Horizontal, COLUMN_NAME_TYPE);
+    m_model->setHeaderData(COL_COMPANY, Qt::Horizontal, COLUMN_NAME_COMPANY);
 
-    view->setModel(model);
-    view->setSelectionMode(QAbstractItemView::SingleSelection);
-    view->setSelectionBehavior(QAbstractItemView::SelectRows);
-    view->setEditTriggers(QAbstractItemView::NoEditTriggers);
-    view->horizontalHeader()->setStretchLastSection(QHeaderView::Stretch);
-    view->resizeColumnsToContents();
-    view->verticalHeader()->hide();
-    view->setAlternatingRowColors(true);
+    m_view->setModel(m_model);
+    m_view->setSelectionMode(QAbstractItemView::SingleSelection);
+    m_view->setSelectionBehavior(QAbstractItemView::SelectRows);
+    m_view->setEditTriggers(QAbstractItemView::NoEditTriggers);
+    m_view->horizontalHeader()->setStretchLastSection(QHeaderView::Stretch);
+    m_view->resizeColumnsToContents();
+    m_view->verticalHeader()->hide();
+    m_view->setAlternatingRowColors(true);
     for(const int i : COLS_TO_HIDE)
-        view->hideColumn(i);
+        m_view->hideColumn(i);
 }
 
 void TailTableEditWidget::setupUI()
@@ -33,9 +33,9 @@ void TailTableEditWidget::setupUI()
     TableEditWidget::setupUI();
 
     // only need to set the table specific labels and combo box items
-    addNewEntryPushButton->setText(tr("Add New Tail"));
-    deleteEntryPushButton->setText(tr("Delete Selected Tail"));
-    filterSelectionComboBox->addItems(FILTER_COLUMNS);
+    m_addNewEntryPushButton->setText(tr("Add New Tail"));
+    m_deleteEntryPushButton->setText(tr("Delete Selected Tail"));
+    m_filterSelectionComboBox->addItems(FILTER_COLUMNS);
 }
 
 QString TailTableEditWidget::deleteErrorString(int rowId)
@@ -96,16 +96,16 @@ EntryEditDialog *TailTableEditWidget::getEntryEditDialog(QWidget *parent)
 void TailTableEditWidget::filterTextChanged(const QString &filterString)
 {
     if(filterString.isEmpty()) {
-        model->setFilter(QString());
+        m_model->setFilter(QString());
         return;
     }
 
-    int i = filterSelectionComboBox->currentIndex();
+    int i = m_filterSelectionComboBox->currentIndex();
     const QString filter =
         QLatin1Char('\"')
         + FILTER_COLUMN_NAMES.at(i)
         + QLatin1String("\" LIKE '%")
         + filterString
         + QLatin1String("%'");
-    model->setFilter(filter);
+    m_model->setFilter(filter);
 }