]> git.mxchange.org Git - flightgear.git/commitdiff
Prompt the user when the default hangar is missing.
authorJames Turner <zakalawe@mac.com>
Fri, 15 Apr 2016 16:06:53 +0000 (17:06 +0100)
committerJames Turner <zakalawe@mac.com>
Fri, 15 Apr 2016 16:06:53 +0000 (17:06 +0100)
In the Qt launcher, when the default hangar isn’t found, show
a hint in the aircraft list.

src/GUI/AircraftItemDelegate.cxx
src/GUI/AircraftModel.cxx
src/GUI/AircraftModel.hxx
src/GUI/CMakeLists.txt
src/GUI/NoOfficialHangar.ui [new file with mode: 0644]
src/GUI/PathsDialog.cxx
src/GUI/PathsDialog.hxx
src/GUI/QtLauncher.cxx
src/GUI/QtLauncher_private.hxx

index 0e293bc1929ef792772ea6ff0aafa1f9ab3c5994..6945645b1490b36a166a31cb0b3822e9de6c6b16 100644 (file)
@@ -43,7 +43,21 @@ AircraftItemDelegate::AircraftItemDelegate(QListView* view) :
 void AircraftItemDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option,
     const QModelIndex & index) const
 {
-    painter->setRenderHint(QPainter::Antialiasing);
+    QRect contentRect = option.rect.adjusted(MARGIN, MARGIN, -MARGIN, -MARGIN);
+
+    QVariant v = index.data(AircraftPackageStatusRole);
+    AircraftItemStatus status = static_cast<AircraftItemStatus>(v.toInt());
+    if (status == NoOfficialCatalogMessage) {
+        painter->setPen(QColor(0x7f, 0x7f, 0x7f));
+        painter->setBrush(Qt::NoBrush);
+
+        // draw bottom dividing line
+        painter->drawLine(contentRect.left(), contentRect.bottom() + MARGIN,
+                          contentRect.right(), contentRect.bottom() + MARGIN);
+
+        return;
+    }
+
     // selection feedback rendering
     if (option.state & QStyle::State_Selected) {
         QLinearGradient grad(option.rect.topLeft(), option.rect.bottomLeft());
@@ -57,7 +71,6 @@ void AircraftItemDelegate::paint(QPainter * painter, const QStyleOptionViewItem
         painter->drawLine(option.rect.topLeft(), option.rect.topRight());
     }
 
-    QRect contentRect = option.rect.adjusted(MARGIN, MARGIN, -MARGIN, -MARGIN);
 
     QPixmap thumbnail = index.data(Qt::DecorationRole).value<QPixmap>();
     quint32 yPos = contentRect.center().y() - (thumbnail.height() / 2);
@@ -130,6 +143,8 @@ void AircraftItemDelegate::paint(QPainter * painter, const QStyleOptionViewItem
     r.moveLeft(r.right());
     r.setHeight(qMax(24, smallMetrics.height() + MARGIN));
 
+    painter->setRenderHint(QPainter::Antialiasing, true);
+
     if (index.data(AircraftHasRatingsRole).toBool()) {
         drawRating(painter, "Flight model:", r, index.data(AircraftRatingRole).toInt());
         r.moveTop(r.bottom());
@@ -142,8 +157,6 @@ void AircraftItemDelegate::paint(QPainter * painter, const QStyleOptionViewItem
         drawRating(painter, "Exterior:", r, index.data(AircraftRatingRole + 3).toInt());
     }
 
-    QVariant v = index.data(AircraftPackageStatusRole);
-    AircraftItemStatus status = static_cast<AircraftItemStatus>(v.toInt());
     double downloadFraction = 0.0;
     
     if (status != PackageInstalled) {
@@ -205,10 +218,22 @@ void AircraftItemDelegate::paint(QPainter * painter, const QStyleOptionViewItem
         painter->setPen(Qt::black);
         painter->drawText(infoTextRect, Qt::AlignLeft | Qt::AlignVCenter, infoText);
     } // of update / install / download status
+
+    painter->setRenderHint(QPainter::Antialiasing, false);
+
 }
 
 QSize AircraftItemDelegate::sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const
 {
+    QVariant v = index.data(AircraftPackageStatusRole);
+    AircraftItemStatus status = static_cast<AircraftItemStatus>(v.toInt());
+
+    if (status == NoOfficialCatalogMessage) {
+        QSize r = option.rect.size();
+        r.setHeight(100);
+        return r;
+    }
+
     QRect contentRect = option.rect.adjusted(MARGIN, MARGIN, -MARGIN, -MARGIN);
 
     QSize thumbnailSize = index.data(AircraftThumbnailSizeRole).toSize();
index 92934790fcb6b5d2b19c95a50637d06263318948..4c0b59886fe11bdbeb28f7168481bcfe17f96c91 100644 (file)
@@ -434,7 +434,8 @@ private:
 
 AircraftItemModel::AircraftItemModel(QObject* pr ) :
     QAbstractListModel(pr),
-    m_scanThread(NULL)
+    m_scanThread(NULL),
+    m_showOfficialHangarMessage(false)
 {
 }
 
@@ -465,14 +466,48 @@ void AircraftItemModel::setPaths(QStringList paths)
     m_paths = paths;
 }
 
+void AircraftItemModel::setOfficialHangarMessageVisible(bool vis)
+{
+    if (m_showOfficialHangarMessage == vis) {
+        return;
+    }
+
+    m_showOfficialHangarMessage = vis;
+
+    if (vis) {
+        beginInsertRows(QModelIndex(), 0, 0);
+        m_items.prepend(AircraftItemPtr(new AircraftItem));
+        m_activeVariant.prepend(0);
+        endInsertRows();
+    } else {
+        beginRemoveRows(QModelIndex(), 0, 0);
+        m_items.removeAt(0);
+        m_activeVariant.removeAt(0);
+        endRemoveRows();
+    }
+}
+
+QModelIndex AircraftItemModel::officialHangarMessageIndex() const
+{
+    if (!m_showOfficialHangarMessage) {
+        return QModelIndex();
+    }
+
+    return index(0);
+}
+
 void AircraftItemModel::scanDirs()
 {
     abandonCurrentScan();
 
-    beginResetModel();
-    m_items.clear();
-    m_activeVariant.clear();
-    endResetModel();
+    int firstRow = (m_showOfficialHangarMessage ? 1 : 0);
+    int numToRemove = m_items.size() - firstRow;
+    int lastRow = firstRow + numToRemove - 1;
+
+    beginRemoveRows(QModelIndex(), firstRow, lastRow);
+    m_items.remove(firstRow, numToRemove);
+    m_activeVariant.remove(firstRow, numToRemove);
+    endRemoveRows();
 
     QStringList dirs = m_paths;
 
@@ -504,10 +539,34 @@ void AircraftItemModel::abandonCurrentScan()
 
 void AircraftItemModel::refreshPackages()
 {
-    beginResetModel();
-    m_packages = m_packageRoot->allPackages();
-    m_packageVariant.resize(m_packages.size());
-    endResetModel();
+    simgear::pkg::PackageList newPkgs = m_packageRoot->allPackages();
+    int firstRow = m_items.size();
+    int newSize = newPkgs.size();
+
+    if (m_packages.size() != newPkgs.size()) {
+        int oldSize = m_packages.size();
+        if (newSize > oldSize) {
+            // growing
+            int firstNewRow = firstRow + oldSize;
+            int lastNewRow = firstRow + newSize - 1;
+            beginInsertRows(QModelIndex(), firstNewRow, lastNewRow);
+            m_packages = newPkgs;
+            m_packageVariant.resize(newSize);
+            endInsertRows();
+        } else {
+            // shrinking
+            int firstOldRow = firstRow + newSize;
+            int lastOldRow = firstRow + oldSize - 1;
+            beginRemoveRows(QModelIndex(), firstOldRow, lastOldRow);
+            m_packages = newPkgs;
+            m_packageVariant.resize(newSize);
+            endRemoveRows();
+        }
+    } else {
+        m_packages = newPkgs;
+    }
+
+    emit dataChanged(index(firstRow), index(firstRow + newSize - 1));
 }
 
 int AircraftItemModel::rowCount(const QModelIndex& parent) const
@@ -517,8 +576,19 @@ int AircraftItemModel::rowCount(const QModelIndex& parent) const
 
 QVariant AircraftItemModel::data(const QModelIndex& index, int role) const
 {
-    if (index.row() >= m_items.size()) {
-        quint32 packageIndex = index.row() - m_items.size();
+    int row = index.row();
+    if (m_showOfficialHangarMessage) {
+        if (row == 0) {
+            if (role == AircraftPackageStatusRole) {
+                return NoOfficialCatalogMessage;
+            }
+
+            return QVariant();
+        }
+    }
+
+    if (row >= m_items.size()) {
+        quint32 packageIndex = row - m_items.size();
 
         if (role == AircraftVariantRole) {
             return m_packageVariant.at(packageIndex);
@@ -537,11 +607,11 @@ QVariant AircraftItemModel::data(const QModelIndex& index, int role) const
         return dataFromPackage(pkg, variantIndex, role);
     } else {
         if (role == AircraftVariantRole) {
-            return m_activeVariant.at(index.row());
+            return m_activeVariant.at(row);
         }
 
-        quint32 variantIndex = m_activeVariant.at(index.row());
-        const AircraftItemPtr item(m_items.at(index.row()));
+        quint32 variantIndex = m_activeVariant.at(row);
+        const AircraftItemPtr item(m_items.at(row));
         return dataFromItem(item, variantIndex, role);
     }
 }
@@ -761,6 +831,10 @@ bool AircraftItemModel::setData(const QModelIndex &index, const QVariant &value,
 
 QModelIndex AircraftItemModel::indexOfAircraftURI(QUrl uri) const
 {
+    if (uri.isEmpty()) {
+        return QModelIndex();
+    }
+
     if (uri.isLocalFile()) {
         QString path = uri.toLocalFile();
         for (int row=0; row <m_items.size(); ++row) {
@@ -778,11 +852,13 @@ QModelIndex AircraftItemModel::indexOfAircraftURI(QUrl uri) const
         }
     } else if (uri.scheme() == "package") {
         QString ident = uri.path();
+        int rowOffset = m_items.size();
+
         PackageRef pkg = m_packageRoot->getPackageById(ident.toStdString());
         if (pkg) {
             for (size_t i=0; i < m_packages.size(); ++i) {
                 if (m_packages[i] == pkg) {
-                    return index(m_items.size() + i);
+                    return index(rowOffset + i);
                 }
             } // of linear package scan
         }
@@ -820,8 +896,6 @@ void AircraftItemModel::onScanFinished()
 
 void AircraftItemModel::installFailed(QModelIndex index, simgear::pkg::Delegate::StatusCode reason)
 {
-    Q_ASSERT(index.row() >= m_items.size());
-
     QString msg;
     switch (reason) {
         case Delegate::FAIL_CHECKSUM:
index 90c243ceb41a06df2b422cd8b35209a088ed7ed3..96ea5aab6059ffa89edea6ae7f335aa3d03dea14 100644 (file)
@@ -94,7 +94,8 @@ enum AircraftItemStatus {
     PackageInstalled,
     PackageUpdateAvailable,
     PackageQueued,
-    PackageDownloading
+    PackageDownloading,
+    NoOfficialCatalogMessage
 };
 
 class AircraftItemModel : public QAbstractListModel
@@ -130,6 +131,14 @@ public:
      */
     bool isIndexRunnable(const QModelIndex& index) const;
 
+    /**
+     * should we show the prompt about the official hangar not being installed
+     * or not?
+     */
+    void setOfficialHangarMessageVisible(bool vis);
+
+    QModelIndex officialHangarMessageIndex() const;
+
     /**
      * @helper to determine if a particular path is likely to contain
      * aircraft or not. Checks for -set.xml files one level down in the tree.
@@ -157,7 +166,7 @@ private:
                              quint32 variantIndex, int role) const;
 
     QVariant packageThumbnail(simgear::pkg::PackageRef p, int index, bool download = true) const;
-    
+
     void abandonCurrentScan();
     void refreshPackages();
     
@@ -168,7 +177,8 @@ private:
     AircraftScanThread* m_scanThread;
     QVector<AircraftItemPtr> m_items;
     PackageDelegate* m_delegate;
-    
+    bool m_showOfficialHangarMessage;
+
     QVector<quint32> m_activeVariant;
     QVector<quint32> m_packageVariant;
     
index 18d42495deef7e82a8d793db829e3a09a259d251..226e08b8f4c54ecb32195a57eb225c443be11735 100644 (file)
@@ -75,7 +75,8 @@ if (HAVE_QT)
                             SetupRootDialog.ui
                             AddCatalogDialog.ui
                             PathsDialog.ui
-                            LocationWidget.ui)
+                            LocationWidget.ui
+                            NoOfficialHanagar.ui)
     qt5_add_resources(qrc_sources resources.qrc)
 
 
diff --git a/src/GUI/NoOfficialHangar.ui b/src/GUI/NoOfficialHangar.ui
new file mode 100644 (file)
index 0000000..d5bd60f
--- /dev/null
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>NoOfficialHangarMessage</class>
+ <widget class="QWidget" name="NoOfficialHangarMessage">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>607</width>
+    <height>134</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <property name="autoFillBackground">
+   <bool>false</bool>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QLabel" name="label">
+     <property name="text">
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The official FlightGear aircraft hangar is not selected, so only the default aircraft will be available. You can add the official hangar by &lt;a href=&quot;action:add-official&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;clicking here&lt;/span&gt;&lt;/a&gt;, or go to the 'add-ons' page to add other hangars or aircraft folders.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;action:hide&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;Click here&lt;/span&gt;&lt;/a&gt; to permanently hide this message.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+     </property>
+     <property name="textFormat">
+      <enum>Qt::RichText</enum>
+     </property>
+     <property name="wordWrap">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
index 9ded69d401b2353a75c962b225fcc64a4ca27a5b..4dcb6a042761f6e3c6eb28ced36d1761e0189a9a 100644 (file)
@@ -190,20 +190,25 @@ void AddOnsPage::onAddCatalog()
 }
 
 void AddOnsPage::onAddDefaultCatalog()
+{
+    addDefaultCatalog(this);
+
+    m_catalogsModel->refresh();
+    updateUi();
+}
+
+void AddOnsPage::addDefaultCatalog(QWidget* pr)
 {
     // check it's not a duplicate somehow
     FGHTTPClient* http = globals->get_subsystem<FGHTTPClient>();
     if (http->isDefaultCatalogInstalled())
         return;
 
-     QScopedPointer<AddCatalogDialog> dlg(new AddCatalogDialog(this, m_packageRoot));
-     QUrl url(QString::fromStdString(http->getDefaultCatalogUrl()));
-     dlg->setUrlAndDownload(url);
-     dlg->exec();
-     if (dlg->result() == QDialog::Accepted) {
-         m_catalogsModel->refresh();
-         updateUi();
-     }
+    QScopedPointer<AddCatalogDialog> dlg(new AddCatalogDialog(pr, globals->packageRoot()));
+    QUrl url(QString::fromStdString(http->getDefaultCatalogUrl()));
+    dlg->setUrlAndDownload(url);
+    dlg->exec();
+
 }
 
 void AddOnsPage::onRemoveCatalog()
index b6303421ec6a2b37a121ee95e3d0a49ab3dad41c..749bb9318dcc25c5f566f5f4e3e33729aae460ee 100644 (file)
@@ -20,6 +20,8 @@ public:
     explicit AddOnsPage(QWidget *parent, simgear::pkg::RootRef root);
     ~AddOnsPage();
 
+    static void addDefaultCatalog(QWidget* pr);
+    
 signals:
     void downloadDirChanged();
     void sceneryPathsChanged();
index 59da6532bb0ae04ed61144b27858d9c6dcbd3b95..c82e7e2151e916a1e721ef3bfad3e856d8a853c3 100644 (file)
@@ -59,6 +59,8 @@
 #include <simgear/package/Install.hxx>
 
 #include "ui_Launcher.h"
+#include "ui_NoOfficialHangar.h"
+
 #include "EditRatingsFilterDialog.hxx"
 #include "AircraftItemDelegate.hxx"
 #include "AircraftModel.hxx"
@@ -293,12 +295,18 @@ public slots:
 protected:
     bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
     {
+        QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
+        QVariant v = index.data(AircraftPackageStatusRole);
+        AircraftItemStatus status = static_cast<AircraftItemStatus>(v.toInt());
+        if (status == NoOfficialCatalogMessage) {
+            return true;
+        }
+        
         if (!QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent)) {
             return false;
         }
 
         if (m_onlyShowInstalled) {
-            QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
             QVariant v = index.data(AircraftPackageStatusRole);
             AircraftItemStatus status = static_cast<AircraftItemStatus>(v.toInt());
             if (status == PackageNotInstalled) {
@@ -307,7 +315,6 @@ protected:
         }
 
         if (!m_onlyShowInstalled && m_ratingsFilter) {
-            QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
             for (int i=0; i<4; ++i) {
                 if (m_ratings[i] > index.data(AircraftRatingRole + i).toInt()) {
                     return false;
@@ -324,6 +331,26 @@ private:
     int m_ratings[4];
 };
 
+class NoOfficialHangarMessage : public QWidget
+{
+    Q_OBJECT
+public:
+    NoOfficialHangarMessage() :
+        m_ui(new Ui::NoOfficialHangarMessage)
+    {
+        m_ui->setupUi(this);
+        // proxy this signal upwards
+        connect(m_ui->label, &QLabel::linkActivated,
+                this, &NoOfficialHangarMessage::linkActivated);
+    }
+
+Q_SIGNALS:
+    void linkActivated(QUrl link);
+
+private:
+    Ui::NoOfficialHangarMessage* m_ui;
+};
+
 static void initQtResources()
 {
     Q_INIT_RESOURCE(resources);
@@ -593,6 +620,7 @@ QtLauncher::QtLauncher() :
     m_aircraftModel->setPackageRoot(globals->packageRoot());
     m_aircraftModel->scanDirs();
 
+    checkOfficialCatalogMessage();
     restoreSettings();
 }
 
@@ -1163,6 +1191,7 @@ void QtLauncher::onSubsytemIdleTimeout()
 
 void QtLauncher::onDownloadDirChanged()
 {
+
     // replace existing package root
     globals->get_subsystem<FGHTTPClient>()->shutdown();
     globals->setPackageRoot(simgear::pkg::RootRef());
@@ -1172,16 +1201,50 @@ void QtLauncher::onDownloadDirChanged()
 
     globals->get_subsystem<FGHTTPClient>()->init();
 
-    // re-scan the aircraft list
     QSettings settings;
+    // re-scan the aircraft list
     m_aircraftModel->setPackageRoot(globals->packageRoot());
     m_aircraftModel->setPaths(settings.value("aircraft-paths").toStringList());
     m_aircraftModel->scanDirs();
 
+    checkOfficialCatalogMessage();
+    
     // re-set scenery dirs
     setSceneryPaths();
 }
 
+void QtLauncher::checkOfficialCatalogMessage()
+{
+    QSettings settings;
+    bool showOfficialCatalogMesssage = !globals->get_subsystem<FGHTTPClient>()->isDefaultCatalogInstalled();
+    if (settings.value("hide-official-catalog-message").toBool()) {
+        showOfficialCatalogMesssage = false;
+    }
+
+    m_aircraftModel->setOfficialHangarMessageVisible(showOfficialCatalogMesssage);
+    if (showOfficialCatalogMesssage) {
+        NoOfficialHangarMessage* messageWidget = new NoOfficialHangarMessage;
+        connect(messageWidget, &NoOfficialHangarMessage::linkActivated,
+                this, &QtLauncher::onOfficialCatalogMessageLink);
+
+        QModelIndex index = m_aircraftProxy->mapFromSource(m_aircraftModel->officialHangarMessageIndex());
+        m_ui->aircraftList->setIndexWidget(index, messageWidget);
+    }
+}
+
+void QtLauncher::onOfficialCatalogMessageLink(QUrl link)
+{
+    QString s = link.toString();
+    if (s == "action:hide") {
+        QSettings settings;
+        settings.setValue("hide-official-catalog-message", true);
+    } else if (s == "action:add-official") {
+        AddOnsPage::addDefaultCatalog(this);
+    }
+
+    checkOfficialCatalogMessage();
+}
+
 simgear::pkg::PackageRef QtLauncher::packageForAircraftURI(QUrl uri) const
 {
     if (uri.scheme() != "package") {
index 58dc053fe7519a7713ab3d83d385dcf2185e4adf..e53c7ba19d96f0d789c535c44929202042642431 100644 (file)
@@ -115,6 +115,9 @@ private:
 
     simgear::pkg::PackageRef packageForAircraftURI(QUrl uri) const;
 
+    void checkOfficialCatalogMessage();
+    void onOfficialCatalogMessageLink(QUrl link);
+
     // need to wait after a model reset before restoring selection and
     // scrolling, to give the view time it seems.
     void delayedAircraftModelReset();