From 0f01b0cbb6bb8fd0e2fac6c742e224769cff9b73 Mon Sep 17 00:00:00 2001
From: Automatic Release Builder <build@flightgear.org>
Date: Mon, 28 Sep 2020 16:19:24 +0100
Subject: [PATCH] Launcher: add help panel to instal aircraft

Based on some feedback on the tracker, when few aircraft are installed,
point users towards the 'browse' tab.
---
 src/GUI/AircraftItemModel.cxx    | 17 ++++++++++
 src/GUI/AircraftItemModel.hxx    |  5 +++
 src/GUI/LauncherController.hxx   |  2 ++
 src/GUI/qml/AircraftGridView.qml |  1 +
 src/GUI/qml/AircraftList.qml     | 58 +++++++++++++++++++++++++++++---
 src/GUI/qml/AircraftListView.qml |  1 +
 6 files changed, 79 insertions(+), 5 deletions(-)

diff --git a/src/GUI/AircraftItemModel.cxx b/src/GUI/AircraftItemModel.cxx
index 7ef4335dd..961e01301 100644
--- a/src/GUI/AircraftItemModel.cxx
+++ b/src/GUI/AircraftItemModel.cxx
@@ -98,6 +98,8 @@ protected:
         if (aReason == STATUS_SUCCESS) {
             m_model->installSucceeded(mi);
         }
+
+        m_model->installedAircraftCountChanged();
     }
 
     void availablePackagesChanged() override
@@ -116,6 +118,7 @@ protected:
     {
         QModelIndex mi(indexForPackage(pkg));
         m_model->dataChanged(mi, mi);
+        m_model->installedAircraftCountChanged();
     }
 
 private:
@@ -593,6 +596,17 @@ QString AircraftItemModel::nameForAircraftURI(QUrl uri) const
     return {};
 }
 
+int AircraftItemModel::installedAircraftCount() const
+{
+    int c = m_cachedLocalAircraftCount;
+
+    for (const auto& cat : m_packageRoot->catalogs()) {
+        c += static_cast<int>(cat->installedPackages().size());
+    }
+
+    return c;
+}
+
 void AircraftItemModel::onScanAddedItems(int addedCount)
 {
     Q_UNUSED(addedCount)
@@ -606,6 +620,7 @@ void AircraftItemModel::onScanAddedItems(int addedCount)
     m_cachedLocalAircraftCount += newItemCount;
     endInsertRows();
     emit contentsChanged();
+    emit installedAircraftCountChanged();
 }
 
 void AircraftItemModel::onLocalCacheCleared()
@@ -619,6 +634,8 @@ void AircraftItemModel::onLocalCacheCleared()
         m_cachedLocalAircraftCount = 0;
         endRemoveRows();
     }
+
+    emit installedAircraftCountChanged();
 }
 
 void AircraftItemModel::installFailed(QModelIndex index, simgear::pkg::Delegate::StatusCode reason)
diff --git a/src/GUI/AircraftItemModel.hxx b/src/GUI/AircraftItemModel.hxx
index bee5134e5..d1cbeb49a 100644
--- a/src/GUI/AircraftItemModel.hxx
+++ b/src/GUI/AircraftItemModel.hxx
@@ -66,6 +66,8 @@ class AircraftItemModel : public QAbstractListModel
 {
     Q_OBJECT
 
+    Q_PROPERTY(int installedAircraftCount READ installedAircraftCount NOTIFY installedAircraftCountChanged)
+
 public:
 
     AircraftItemModel(QObject* pr);
@@ -107,12 +109,15 @@ public:
      */
     QString nameForAircraftURI(QUrl uri) const;
 
+    int installedAircraftCount() const;
 signals:
     void aircraftInstallFailed(QModelIndex index, QString errorMessage);
     
     void aircraftInstallCompleted(QModelIndex index);
     
     void contentsChanged();
+
+    void installedAircraftCountChanged();
 private slots:
     void onScanStarted();
     void onScanAddedItems(int count);
diff --git a/src/GUI/LauncherController.hxx b/src/GUI/LauncherController.hxx
index 915ccc1e9..8dfa15fb2 100644
--- a/src/GUI/LauncherController.hxx
+++ b/src/GUI/LauncherController.hxx
@@ -232,6 +232,8 @@ signals:
     void aircraftGridModeChanged(bool aircraftGridMode);
 
     void inAppChanged();
+    void installedAircraftCountChanged(int installedAircraftCount);
+
 public slots:
     void setSelectedAircraft(QUrl selectedAircraft);
 
diff --git a/src/GUI/qml/AircraftGridView.qml b/src/GUI/qml/AircraftGridView.qml
index ad499b540..7676e4a2d 100644
--- a/src/GUI/qml/AircraftGridView.qml
+++ b/src/GUI/qml/AircraftGridView.qml
@@ -8,6 +8,7 @@ Item {
 
     property alias model: view.model
     property alias header: view.header
+    property alias footer: view.footer
 
     signal showDetails(var uri);
 
diff --git a/src/GUI/qml/AircraftList.qml b/src/GUI/qml/AircraftList.qml
index 62a729a66..d693c0f37 100644
--- a/src/GUI/qml/AircraftList.qml
+++ b/src/GUI/qml/AircraftList.qml
@@ -8,6 +8,7 @@ FocusScope
 
     property var __model: null
     property Component __header: null
+    property Component __footer: null
     property string __lastState: "installed"
 
     function updateSelectionFromLauncher()
@@ -144,11 +145,47 @@ FocusScope
     }
 
     Component {
-        id: emptyHeader
+        id: searchHeader
+        Rectangle {
+            visible: _launcher.searchAircraftModel.count === 0
+            width: aircraftContent.width
+            height: Style.strutSize
+
+            StyledText {
+                anchors.fill: parent
+                text: qsTr("No aircraft match the search.")
+                wrapMode: Text.WordWrap
+                font.pixelSize: Style.headingFontPixelSize
+                horizontalAlignment: Text.AlignHCenter
+                verticalAlignment: Text.AlignVCenter
+            }
+        }
+    }
+
+    Component {
+        id: emptyHeaderFooter
         Item {
         }
     }
 
+    Component {
+        id: installMoreAircraftFooter
+        Rectangle {
+            visible: _launcher.baseAircraftModel.installedAircraftCount < 50
+            width: aircraftContent.width
+            height: Style.strutSize
+
+            StyledText {
+                anchors.fill: parent
+                text: qsTr("To install additional aircraft, click the the 'Browse' tab at the top of this page.")
+                wrapMode: Text.WordWrap
+                font.pixelSize: Style.headingFontPixelSize
+                horizontalAlignment: Text.AlignHCenter
+                verticalAlignment: Text.AlignVCenter
+            }
+        }
+    }
+
     Loader {
         id: aircraftContent
         // we use gridModeToggle vis to mean enabled, effectively
@@ -175,6 +212,12 @@ FocusScope
             value: root.__header
         }
 
+        Binding {
+            target: aircraftContent.item
+            property: "footer"
+            value: root.__footer
+        }
+
         Connections {
             target: aircraftContent.item
             onShowDetails: root.showDetails(uri)
@@ -202,7 +245,8 @@ FocusScope
             PropertyChanges {
                 target: root
                 __model: _launcher.installedAircraftModel
-                __header: emptyHeader
+                __header: emptyHeaderFooter
+                __footer: installMoreAircraftFooter
             }
 
             PropertyChanges {
@@ -215,7 +259,8 @@ FocusScope
             PropertyChanges {
                 target: root
                 __model: _launcher.searchAircraftModel
-                __header: emptyHeader
+                __header: searchHeader
+                __footer: emptyHeaderFooter
             }
 
             PropertyChanges {
@@ -229,6 +274,7 @@ FocusScope
                 target: root
                 __model: _launcher.browseAircraftModel
                 __header: _addOns.showNoOfficialHangar ? noDefaultCatalogHeader : ratingsHeader
+                __footer: emptyHeaderFooter
             }
 
             PropertyChanges {
@@ -241,7 +287,8 @@ FocusScope
             PropertyChanges {
                 target: root
                 __model: _launcher.aircraftWithUpdatesModel
-                __header: (_launcher.aircraftWithUpdatesModel.count > 0) ? updateAllHeader : emptyHeader
+                __header: (_launcher.aircraftWithUpdatesModel.count > 0) ? updateAllHeader : emptyHeaderFooter
+                __footer: emptyHeaderFooter
             }
 
             PropertyChanges {
@@ -255,7 +302,8 @@ FocusScope
             PropertyChanges {
                 target: root
                 __model: _launcher.favouriteAircraftModel
-                __header: emptyHeader
+                __header: emptyHeaderFooter
+                __footer: emptyHeaderFooter
             }
 
             PropertyChanges {
diff --git a/src/GUI/qml/AircraftListView.qml b/src/GUI/qml/AircraftListView.qml
index b9b91ec92..5303c338e 100644
--- a/src/GUI/qml/AircraftListView.qml
+++ b/src/GUI/qml/AircraftListView.qml
@@ -8,6 +8,7 @@ Item {
 
     property alias model: aircraftList.model
     property alias header: aircraftList.header
+    property alias footer: aircraftList.footer
 
     signal showDetails(var uri);