From 1e1326d8f3edb41724517c4521ac2aebeedb50df Mon Sep 17 00:00:00 2001
From: James Turner <zakalawe@mac.com>
Date: Wed, 11 Mar 2015 23:20:18 +0000
Subject: [PATCH] Aircraft path support in the Qt launcher

- aircraft dirs are re-scanned when the paths change.
---
 src/GUI/AircraftModel.cxx |  30 +++++-
 src/GUI/AircraftModel.hxx |   8 ++
 src/GUI/Launcher.ui       | 213 ++++++++++++++++++++++++++------------
 src/GUI/QtLauncher.cxx    |  50 ++++++++-
 src/GUI/QtLauncher.hxx    |   8 +-
 5 files changed, 237 insertions(+), 72 deletions(-)

diff --git a/src/GUI/AircraftModel.cxx b/src/GUI/AircraftModel.cxx
index a5cac436a..0802767eb 100644
--- a/src/GUI/AircraftModel.cxx
+++ b/src/GUI/AircraftModel.cxx
@@ -283,9 +283,33 @@ private:
 
 AircraftItemModel::AircraftItemModel(QObject* pr, simgear::pkg::RootRef& rootRef) :
     QAbstractListModel(pr),
+    m_scanThread(NULL),
     m_packageRoot(rootRef)
 {
-    QStringList dirs;
+}
+
+AircraftItemModel::~AircraftItemModel()
+{
+    abandonCurrentScan();
+}
+
+void AircraftItemModel::setPaths(QStringList paths)
+{
+    m_paths = paths;
+}
+
+void AircraftItemModel::scanDirs()
+{
+    abandonCurrentScan();
+
+    beginResetModel();
+    qDeleteAll(m_items);
+    m_items.clear();
+    m_activeVariant.clear();
+    endResetModel();
+
+    QStringList dirs = m_paths;
+
     Q_FOREACH(std::string ap, globals->get_aircraft_paths()) {
         dirs << QString::fromStdString(ap);
     }
@@ -300,14 +324,16 @@ AircraftItemModel::AircraftItemModel(QObject* pr, simgear::pkg::RootRef& rootRef
     connect(m_scanThread, &AircraftScanThread::addedItems,
             this, &AircraftItemModel::onScanResults);
     m_scanThread->start();
+
 }
 
-AircraftItemModel::~AircraftItemModel()
+void AircraftItemModel::abandonCurrentScan()
 {
     if (m_scanThread) {
         m_scanThread->setDone();
         m_scanThread->wait(1000);
         delete m_scanThread;
+        m_scanThread = NULL;
     }
 }
 
diff --git a/src/GUI/AircraftModel.hxx b/src/GUI/AircraftModel.hxx
index 61322b09a..24236a281 100644
--- a/src/GUI/AircraftModel.hxx
+++ b/src/GUI/AircraftModel.hxx
@@ -25,6 +25,7 @@
 #include <QDateTime>
 #include <QDir>
 #include <QPixmap>
+#include <QStringList>
 
 #include <simgear/package/Root.hxx>
 
@@ -73,6 +74,10 @@ public:
 
     ~AircraftItemModel();
 
+    void setPaths(QStringList paths);
+
+    void scanDirs();
+
     virtual int rowCount(const QModelIndex& parent) const
     {
         return m_items.size();
@@ -90,6 +95,9 @@ private slots:
     void onScanFinished();
 
 private:
+    void abandonCurrentScan();
+
+    QStringList m_paths;
     AircraftScanThread* m_scanThread;
     QList<AircraftItem*> m_items;
     QList<quint32> m_activeVariant;
diff --git a/src/GUI/Launcher.ui b/src/GUI/Launcher.ui
index ab9af86ae..521938756 100644
--- a/src/GUI/Launcher.ui
+++ b/src/GUI/Launcher.ui
@@ -6,8 +6,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>700</width>
-    <height>700</height>
+    <width>667</width>
+    <height>821</height>
    </rect>
   </property>
   <property name="windowTitle">
@@ -373,15 +373,15 @@
       <attribute name="title">
        <string>Settings</string>
       </attribute>
-      <layout class="QGridLayout" name="gridLayout_4">
+      <layout class="QGridLayout" name="gridLayout_5">
        <property name="leftMargin">
-        <number>10</number>
+        <number>8</number>
        </property>
        <property name="rightMargin">
-        <number>10</number>
+        <number>8</number>
        </property>
        <property name="bottomMargin">
-        <number>10</number>
+        <number>8</number>
        </property>
        <item row="0" column="0">
         <layout class="QHBoxLayout" name="horizontalLayout_4">
@@ -441,6 +441,34 @@
          </item>
         </layout>
        </item>
+       <item row="0" column="1">
+        <layout class="QHBoxLayout" name="horizontalLayout_8">
+         <item>
+          <widget class="QLabel" name="label_7">
+           <property name="text">
+            <string>Season:</string>
+           </property>
+           <property name="alignment">
+            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QComboBox" name="seasonCombo">
+           <item>
+            <property name="text">
+             <string>Summer</string>
+            </property>
+           </item>
+           <item>
+            <property name="text">
+             <string>Winter</string>
+            </property>
+           </item>
+          </widget>
+         </item>
+        </layout>
+       </item>
        <item row="1" column="0">
         <widget class="QCheckBox" name="msaaCheckbox">
          <property name="text">
@@ -448,7 +476,7 @@
          </property>
         </widget>
        </item>
-       <item row="1" column="1" colspan="2">
+       <item row="1" column="1">
         <widget class="QCheckBox" name="rembrandtCheckbox">
          <property name="text">
           <string>Enable deferred rendering (Rembrandt)</string>
@@ -462,7 +490,7 @@
          </property>
         </widget>
        </item>
-       <item row="3" column="0" colspan="3">
+       <item row="3" column="0" colspan="2">
         <layout class="QHBoxLayout" name="horizontalLayout_7">
          <item>
           <spacer name="horizontalSpacer_2">
@@ -502,6 +530,13 @@
          </property>
         </widget>
        </item>
+       <item row="4" column="1">
+        <widget class="QCheckBox" name="fullScreenCheckbox">
+         <property name="text">
+          <string>Start full-screen</string>
+         </property>
+        </widget>
+       </item>
        <item row="5" column="0">
         <widget class="QCheckBox" name="startPausedCheck">
          <property name="text">
@@ -509,7 +544,28 @@
          </property>
         </widget>
        </item>
-       <item row="7" column="0" colspan="3">
+       <item row="6" column="0" colspan="2">
+        <layout class="QHBoxLayout" name="horizontalLayout_3" stretch="1,0">
+         <item>
+          <widget class="QLabel" name="customAircraftDirLabel">
+           <property name="text">
+            <string>Custom aircraft directory:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QPushButton" name="openAircraftDirButton">
+           <property name="text">
+            <string>Open in Finder</string>
+           </property>
+           <property name="autoDefault">
+            <bool>false</bool>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item row="7" column="0" colspan="2">
         <widget class="QGroupBox" name="groupBox">
          <property name="title">
           <string>Additional scenery locations</string>
@@ -530,9 +586,6 @@
           <property name="spacing">
            <number>0</number>
           </property>
-          <item row="0" column="0" colspan="3">
-           <widget class="QListWidget" name="sceneryPathsList"/>
-          </item>
           <item row="1" column="0">
            <spacer name="horizontalSpacer_3">
             <property name="orientation">
@@ -584,66 +637,91 @@
             </property>
            </widget>
           </item>
+          <item row="0" column="0" colspan="3">
+           <widget class="QListWidget" name="sceneryPathsList"/>
+          </item>
          </layout>
         </widget>
        </item>
-       <item row="0" column="1" colspan="2">
-        <layout class="QHBoxLayout" name="horizontalLayout_8">
-         <item>
-          <widget class="QLabel" name="label_7">
-           <property name="text">
-            <string>Season:</string>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <widget class="QComboBox" name="seasonCombo">
-           <item>
-            <property name="text">
-             <string>Summer</string>
-            </property>
-           </item>
-           <item>
-            <property name="text">
-             <string>Winter</string>
-            </property>
-           </item>
-          </widget>
-         </item>
-        </layout>
-       </item>
-       <item row="4" column="1" colspan="2">
-        <widget class="QCheckBox" name="fullScreenCheckbox">
-         <property name="text">
-          <string>Start full-screen</string>
+       <item row="8" column="0" colspan="2">
+        <widget class="QGroupBox" name="groupBox_3">
+         <property name="title">
+          <string>Additional aircraft locations</string>
          </property>
+         <layout class="QGridLayout" name="gridLayout_4">
+          <property name="leftMargin">
+           <number>8</number>
+          </property>
+          <property name="topMargin">
+           <number>8</number>
+          </property>
+          <property name="rightMargin">
+           <number>8</number>
+          </property>
+          <property name="bottomMargin">
+           <number>8</number>
+          </property>
+          <property name="spacing">
+           <number>0</number>
+          </property>
+          <item row="0" column="0" colspan="3">
+           <widget class="QListWidget" name="aircraftPathsList"/>
+          </item>
+          <item row="1" column="0">
+           <spacer name="horizontalSpacer_4">
+            <property name="orientation">
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="sizeHint" stdset="0">
+             <size>
+              <width>567</width>
+              <height>20</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+          <item row="1" column="2">
+           <widget class="QToolButton" name="removeAircraftPath">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="minimumSize">
+             <size>
+              <width>20</width>
+              <height>20</height>
+             </size>
+            </property>
+            <property name="text">
+             <string>-</string>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="1">
+           <widget class="QToolButton" name="addAircraftPath">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="minimumSize">
+             <size>
+              <width>20</width>
+              <height>20</height>
+             </size>
+            </property>
+            <property name="text">
+             <string>+</string>
+            </property>
+           </widget>
+          </item>
+         </layout>
         </widget>
        </item>
-       <item row="6" column="0" colspan="3">
-        <layout class="QHBoxLayout" name="horizontalLayout_3" stretch="1,0">
-         <item>
-          <widget class="QLabel" name="customAircraftDirLabel">
-           <property name="text">
-            <string>Custom aircraft directory:</string>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <widget class="QPushButton" name="openAircraftDirButton">
-           <property name="text">
-            <string>Open in Finder</string>
-           </property>
-           <property name="autoDefault">
-            <bool>false</bool>
-           </property>
-          </widget>
-         </item>
-        </layout>
-       </item>
-       <item row="8" column="0" colspan="3">
+       <item row="9" column="0" colspan="2">
         <widget class="QGroupBox" name="groupBox_2">
          <property name="title">
           <string>Additional options</string>
@@ -662,8 +740,7 @@
            <number>8</number>
           </property>
           <item>
-           <widget class="QPlainTextEdit" name="commandLineArgs">
-           </widget>
+           <widget class="QPlainTextEdit" name="commandLineArgs"/>
           </item>
          </layout>
         </widget>
diff --git a/src/GUI/QtLauncher.cxx b/src/GUI/QtLauncher.cxx
index b1fd032ee..86eb19e3a 100644
--- a/src/GUI/QtLauncher.cxx
+++ b/src/GUI/QtLauncher.cxx
@@ -411,7 +411,8 @@ QtLauncher::QtLauncher() :
     // will happen as normal
     http->init();
 
-    m_aircraftProxy->setSourceModel(new AircraftItemModel(this, r));
+    m_aircraftModel = new AircraftItemModel(this, r);
+    m_aircraftProxy->setSourceModel(m_aircraftModel);
 
     m_aircraftProxy->setFilterCaseSensitivity(Qt::CaseInsensitive);
     m_aircraftProxy->setSortCaseSensitivity(Qt::CaseInsensitive);
@@ -498,6 +499,15 @@ QtLauncher::QtLauncher() :
             this, &QtLauncher::onAddSceneryPath);
     connect(m_ui->removeSceneryPath, &QToolButton::clicked,
             this, &QtLauncher::onRemoveSceneryPath);
+
+    connect(m_ui->addAircraftPath, &QToolButton::clicked,
+            this, &QtLauncher::onAddAircraftPath);
+    connect(m_ui->removeAircraftPath, &QToolButton::clicked,
+            this, &QtLauncher::onRemoveAircraftPath);
+
+    QSettings settings;
+    m_aircraftModel->setPaths(settings.value("aircraft-paths").toStringList());
+    m_aircraftModel->scanDirs();
 }
 
 QtLauncher::~QtLauncher()
@@ -598,6 +608,9 @@ void QtLauncher::restoreSettings()
     QStringList sceneryPaths = settings.value("scenery-paths").toStringList();
     m_ui->sceneryPathsList->addItems(sceneryPaths);
 
+    QStringList aircraftPaths = settings.value("aircraft-paths").toStringList();
+    m_ui->aircraftPathsList->addItems(aircraftPaths);
+
     m_ui->commandLineArgs->setPlainText(settings.value("additional-args").toString());
 }
 
@@ -622,6 +635,13 @@ void QtLauncher::saveSettings()
     }
 
     settings.setValue("scenery-paths", paths);
+    paths.clear();
+
+    for (int i=0; i<m_ui->aircraftPathsList->count(); ++i) {
+        paths.append(m_ui->aircraftPathsList->item(i)->text());
+    }
+
+    settings.setValue("aircraft-paths", paths);
     settings.setValue("additional-args", m_ui->commandLineArgs->toPlainText());
 }
 
@@ -712,6 +732,12 @@ void QtLauncher::onRun()
         opt->addOption("fg-scenery", path.toStdString());
     }
 
+    // aircraft paths
+    for (int i=0; i<m_ui->aircraftPathsList->count(); ++i) {
+        QString path = m_ui->aircraftPathsList->item(i)->text();
+        opt->addOption("fg-aircraft", path.toStdString());
+    }
+
     // additional arguments
     ArgumentsTokenizer tk;
     Q_FOREACH(ArgumentsTokenizer::Arg a, tk.tokenize(m_ui->commandLineArgs->toPlainText())) {
@@ -1043,6 +1069,28 @@ void QtLauncher::onRemoveSceneryPath()
     }
 }
 
+void QtLauncher::onAddAircraftPath()
+{
+    QString path = QFileDialog::getExistingDirectory(this, tr("Choose aircraft folder"));
+    if (!path.isEmpty()) {
+        m_ui->aircraftPathsList->addItem(path);
+        saveSettings();
+
+        // re-scan the aircraft list
+        QSettings settings;
+        m_aircraftModel->setPaths(settings.value("aircraft-paths").toStringList());
+        m_aircraftModel->scanDirs();
+    }
+}
+
+void QtLauncher::onRemoveAircraftPath()
+{
+    if (m_ui->aircraftPathsList->currentItem()) {
+        delete m_ui->aircraftPathsList->currentItem();
+        saveSettings();
+    }
+}
+
 void QtLauncher::onRembrandtToggled(bool b)
 {
     // Rembrandt and multi-sample are exclusive
diff --git a/src/GUI/QtLauncher.hxx b/src/GUI/QtLauncher.hxx
index e4557cb54..43e4602b7 100644
--- a/src/GUI/QtLauncher.hxx
+++ b/src/GUI/QtLauncher.hxx
@@ -37,6 +37,7 @@ namespace Ui
 class AirportSearchModel;
 class QModelIndex;
 class AircraftProxyModel;
+class AircraftItemModel;
 class QCheckBox;
 
 class QtLauncher : public QDialog
@@ -76,6 +77,10 @@ private slots:
     void onAddSceneryPath();
     void onRemoveSceneryPath();
 
+    void onAddAircraftPath();
+    void onRemoveAircraftPath();
+
+
     void onRembrandtToggled(bool b);
 
     void onSubsytemIdleTimeout();
@@ -94,7 +99,8 @@ private:
     QScopedPointer<Ui::Launcher> m_ui;
     AirportSearchModel* m_airportsModel;
     AircraftProxyModel* m_aircraftProxy;
-
+    AircraftItemModel* m_aircraftModel;
+    
     FGAirportRef m_selectedAirport;
 
     QString m_selectedAircraft;