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());
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);
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());
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) {
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();
AircraftItemModel::AircraftItemModel(QObject* pr ) :
QAbstractListModel(pr),
- m_scanThread(NULL)
+ m_scanThread(NULL),
+ m_showOfficialHangarMessage(false)
{
}
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;
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
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);
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);
}
}
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) {
}
} 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
}
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:
PackageInstalled,
PackageUpdateAvailable,
PackageQueued,
- PackageDownloading
+ PackageDownloading,
+ NoOfficialCatalogMessage
};
class AircraftItemModel : public QAbstractListModel
*/
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.
quint32 variantIndex, int role) const;
QVariant packageThumbnail(simgear::pkg::PackageRef p, int index, bool download = true) const;
-
+
void abandonCurrentScan();
void refreshPackages();
AircraftScanThread* m_scanThread;
QVector<AircraftItemPtr> m_items;
PackageDelegate* m_delegate;
-
+ bool m_showOfficialHangarMessage;
+
QVector<quint32> m_activeVariant;
QVector<quint32> m_packageVariant;
SetupRootDialog.ui
AddCatalogDialog.ui
PathsDialog.ui
- LocationWidget.ui)
+ LocationWidget.ui
+ NoOfficialHanagar.ui)
qt5_add_resources(qrc_sources resources.qrc)
--- /dev/null
+<?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><html><head/><body><p>The official FlightGear aircraft hangar is not selected, so only the default aircraft will be available. You can add the official hangar by <a href="action:add-official"><span style=" text-decoration: underline; color:#0000ff;">clicking here</span></a>, or go to the 'add-ons' page to add other hangars or aircraft folders.</p><p><a href="action:hide"><span style=" text-decoration: underline; color:#0000ff;">Click here</span></a> to permanently hide this message.</p></body></html></string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::RichText</enum>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
}
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()
explicit AddOnsPage(QWidget *parent, simgear::pkg::RootRef root);
~AddOnsPage();
+ static void addDefaultCatalog(QWidget* pr);
+
signals:
void downloadDirChanged();
void sceneryPathsChanged();
#include <simgear/package/Install.hxx>
#include "ui_Launcher.h"
+#include "ui_NoOfficialHangar.h"
+
#include "EditRatingsFilterDialog.hxx"
#include "AircraftItemDelegate.hxx"
#include "AircraftModel.hxx"
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) {
}
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;
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);
m_aircraftModel->setPackageRoot(globals->packageRoot());
m_aircraftModel->scanDirs();
+ checkOfficialCatalogMessage();
restoreSettings();
}
void QtLauncher::onDownloadDirChanged()
{
+
// replace existing package root
globals->get_subsystem<FGHTTPClient>()->shutdown();
globals->setPackageRoot(simgear::pkg::RootRef());
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") {
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();