Prompt the user when the default hangar is missing.
In the Qt launcher, when the default hangar isn’t found, show a hint in the aircraft list.
This commit is contained in:
parent
c15e4753ac
commit
6095646a62
9 changed files with 256 additions and 36 deletions
|
@ -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();
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
37
src/GUI/NoOfficialHangar.ui
Normal file
37
src/GUI/NoOfficialHangar.ui
Normal file
|
@ -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><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>
|
|
@ -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()
|
||||
|
|
|
@ -20,6 +20,8 @@ public:
|
|||
explicit AddOnsPage(QWidget *parent, simgear::pkg::RootRef root);
|
||||
~AddOnsPage();
|
||||
|
||||
static void addDefaultCatalog(QWidget* pr);
|
||||
|
||||
signals:
|
||||
void downloadDirChanged();
|
||||
void sceneryPathsChanged();
|
||||
|
|
|
@ -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") {
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Add table
Reference in a new issue