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);