Launcher: basic aircraft state selection
Automatic selection in the launcher is disabled for now, since it needs more testing before release, but the basic UI for selection is straightforward enough to throw in.
This commit is contained in:
parent
a05cdce793
commit
234320fe9d
7 changed files with 438 additions and 85 deletions
|
@ -251,23 +251,59 @@
|
|||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="summaryPage">
|
||||
<layout class="QGridLayout" name="gridLayout_3" rowstretch="0,0,0,0,0,0,0,0,0,1" columnstretch="0,0,0,1,0">
|
||||
<layout class="QGridLayout" name="gridLayout_3" rowstretch="0,0,0,0,0,0,0,0,0,0,0,0" columnstretch="0,0,0,1,0">
|
||||
<item row="0" column="3" colspan="2">
|
||||
<widget class="QLabel" name="appTitleLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>48</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>FlightGear 2017.1.0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="4">
|
||||
<widget class="QPushButton" name="aircraftHistory">
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<widget class="QLabel" name="stateLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Location:</string>
|
||||
<string>State:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing</set>
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="2">
|
||||
<item row="3" column="3">
|
||||
<widget class="QLabel" name="aircraftName">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>aircraft</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="2">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="font">
|
||||
<font>
|
||||
|
@ -282,13 +318,6 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="4">
|
||||
<widget class="QPushButton" name="locationHistory">
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="font">
|
||||
|
@ -304,14 +333,41 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="4">
|
||||
<widget class="QPushButton" name="aircraftHistory">
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
<item row="7" column="3">
|
||||
<widget class="QLabel" name="locationDescription">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>location</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="3" colspan="2">
|
||||
<item row="2" column="3" colspan="2">
|
||||
<widget class="QLabel" name="thumbnail">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>171</width>
|
||||
<height>128</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="3" colspan="2">
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
|
@ -339,37 +395,55 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="3">
|
||||
<widget class="QLabel" name="locationDescription">
|
||||
<item row="5" column="3" colspan="2">
|
||||
<widget class="QComboBox" name="stateCombo"/>
|
||||
</item>
|
||||
<item row="1" column="3" colspan="2">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>©2017 FlightGear contributors. Licensed under the GNU Public License. See <a href="http://www.flightgear.org"><span style=" text-decoration: underline; color:#0000ff;">here</span></a> for more information</p></body></html></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="2">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>location</string>
|
||||
<string>Location:</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<widget class="QLabel" name="aircraftName">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<item row="0" column="2" rowspan="2">
|
||||
<widget class="QLabel" name="logoIcon">
|
||||
<property name="text">
|
||||
<string>aircraft</string>
|
||||
<string/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="resources.qrc">:/app-icon-large</pixmap>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="3" colspan="2">
|
||||
<item row="7" column="4">
|
||||
<widget class="QPushButton" name="locationHistory">
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="3" colspan="2">
|
||||
<widget class="QLabel" name="settingsDescription">
|
||||
<property name="font">
|
||||
<font>
|
||||
|
@ -387,59 +461,15 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3" colspan="2">
|
||||
<widget class="QLabel" name="thumbnail">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>171</width>
|
||||
<height>128</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3" colspan="2">
|
||||
<widget class="QLabel" name="appTitleLabel">
|
||||
<item row="6" column="3" colspan="2">
|
||||
<widget class="QLabel" name="stateDescription">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>48</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>FlightGear 2017.1.0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3" colspan="2">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>©2017 FlightGear contributors. Licensed under the GNU Public License. See <a href="http://www.flightgear.org"><span style=" text-decoration: underline; color:#0000ff;">here</span></a> for more information</p></body></html></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" rowspan="2">
|
||||
<widget class="QLabel" name="logoIcon">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="resources.qrc">:/app-icon-large</pixmap>
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
@ -106,6 +106,17 @@ LauncherMainWindow::LauncherMainWindow() :
|
|||
m_serversModel = new MPServersModel(this);
|
||||
m_serversModel->refresh();
|
||||
|
||||
// keep the description QLabel in sync as the current item changes
|
||||
connect(m_ui->stateCombo,
|
||||
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
||||
[this](int)
|
||||
{
|
||||
auto v = m_ui->stateCombo->currentData(QmlAircraftInfo::StateDescriptionRole);
|
||||
m_ui->stateDescription->setText(v.toString());
|
||||
m_ui->stateDescription->setVisible(!v.toString().isEmpty());
|
||||
});
|
||||
|
||||
m_selectedAircraftInfo = new QmlAircraftInfo(this);
|
||||
initQML();
|
||||
|
||||
m_subsystemIdleTimer = new QTimer(this);
|
||||
|
@ -457,6 +468,27 @@ void LauncherMainWindow::onRun()
|
|||
m_recentAircraft.pop_back();
|
||||
}
|
||||
|
||||
if (m_ui->stateCombo->isVisible()) {
|
||||
// apply state setting
|
||||
std::string tag = m_ui->stateCombo->currentData(QmlAircraftInfo::StateTagRole).
|
||||
toString().toStdString();
|
||||
|
||||
// implicit auto behaviour disabled for 2018.1, since it
|
||||
// needs a bit more work
|
||||
#if 0
|
||||
if (tag == "auto") {
|
||||
bool isExplictAuto = m_ui->stateCombo->currentData(QmlAircraftInfo::StateExplicitRole).toBool();
|
||||
if (!isExplictAuto) {
|
||||
tag = selectStateAutomatically();
|
||||
qInfo() << "automatic state selection: picked:" << QString::fromStdString(tag);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (!tag.empty() && (tag != "__default__")) {
|
||||
m_config->setArg("state", tag);
|
||||
}
|
||||
} // of applying state selection
|
||||
|
||||
// aircraft paths
|
||||
QSettings settings;
|
||||
updateLocationHistory();
|
||||
|
@ -490,6 +522,20 @@ void LauncherMainWindow::onRun()
|
|||
qApp->exit(1);
|
||||
}
|
||||
|
||||
std::string LauncherMainWindow::selectStateAutomatically()
|
||||
{
|
||||
if (m_ui->location->isAirborneLocation()) {
|
||||
return "approach";
|
||||
}
|
||||
|
||||
if (m_ui->location->isParkedLocation()) {
|
||||
return "parked";
|
||||
} else {
|
||||
return "take-off";
|
||||
}
|
||||
|
||||
return {}; // failed to compute, give up
|
||||
}
|
||||
|
||||
void LauncherMainWindow::onApply()
|
||||
{
|
||||
|
@ -621,6 +667,7 @@ void LauncherMainWindow::maybeUpdateSelectedAircraft(QModelIndex index)
|
|||
|
||||
void LauncherMainWindow::updateSelectedAircraft()
|
||||
{
|
||||
m_selectedAircraftInfo->setUri(m_selectedAircraft);
|
||||
QModelIndex index = m_aircraftModel->indexOfAircraftURI(m_selectedAircraft);
|
||||
if (index.isValid()) {
|
||||
QPixmap pm = index.data(Qt::DecorationRole).value<QPixmap>();
|
||||
|
@ -648,10 +695,24 @@ void LauncherMainWindow::updateSelectedAircraft()
|
|||
}
|
||||
|
||||
m_ui->location->setAircraftType(aircraftType);
|
||||
|
||||
const bool hasStates = m_selectedAircraftInfo->hasStates();
|
||||
m_ui->stateCombo->setVisible(hasStates);
|
||||
m_ui->stateLabel->setVisible(hasStates);
|
||||
m_ui->stateDescription->setVisible(false);
|
||||
if (hasStates) {
|
||||
m_ui->stateCombo->setModel(m_selectedAircraftInfo->statesModel());
|
||||
m_ui->stateDescription->setText(m_ui->stateCombo->currentData(QmlAircraftInfo::StateDescriptionRole).toString());
|
||||
// hiden when no description is present
|
||||
m_ui->stateDescription->setVisible(!m_ui->stateDescription->text().isEmpty());
|
||||
}
|
||||
} else {
|
||||
m_ui->thumbnail->setPixmap(QPixmap());
|
||||
m_ui->aircraftName->setText("");
|
||||
m_ui->aircraftDescription->hide();
|
||||
m_ui->stateCombo->hide();
|
||||
m_ui->stateLabel->hide();
|
||||
m_ui->stateDescription->hide();
|
||||
m_ui->flyButton->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
@ -812,6 +873,11 @@ QPointF LauncherMainWindow::mapToGlobal(QQuickItem *item, const QPointF &pos) co
|
|||
return m_ui->aircraftList->mapToGlobal(scenePos.toPoint());
|
||||
}
|
||||
|
||||
QmlAircraftInfo *LauncherMainWindow::selectedAircraftInfo() const
|
||||
{
|
||||
return m_selectedAircraftInfo;
|
||||
}
|
||||
|
||||
void LauncherMainWindow::setSelectedAircraft(QUrl selectedAircraft)
|
||||
{
|
||||
if (m_selectedAircraft == selectedAircraft)
|
||||
|
|
|
@ -47,6 +47,7 @@ class ExtraSettingsSection;
|
|||
class ViewCommandLinePage;
|
||||
class MPServersModel;
|
||||
class QQuickItem;
|
||||
class QmlAircraftInfo;
|
||||
|
||||
class LauncherMainWindow : public QMainWindow
|
||||
{
|
||||
|
@ -61,6 +62,8 @@ class LauncherMainWindow : public QMainWindow
|
|||
Q_PROPERTY(AircraftItemModel* baseAircraftModel MEMBER m_aircraftModel CONSTANT)
|
||||
|
||||
Q_PROPERTY(QUrl selectedAircraft READ selectedAircraft WRITE setSelectedAircraft NOTIFY selectedAircraftChanged)
|
||||
|
||||
Q_PROPERTY(QmlAircraftInfo* selectedAircraftInfo READ selectedAircraftInfo NOTIFY selectedAircraftChanged)
|
||||
public:
|
||||
LauncherMainWindow();
|
||||
virtual ~LauncherMainWindow();
|
||||
|
@ -89,6 +92,8 @@ public:
|
|||
|
||||
// work around the fact, that this is not available on QQuickItem until 5.7
|
||||
Q_INVOKABLE QPointF mapToGlobal(QQuickItem* item, const QPointF& pos) const;
|
||||
|
||||
QmlAircraftInfo* selectedAircraftInfo() const;
|
||||
public slots:
|
||||
void setSelectedAircraft(QUrl selectedAircraft);
|
||||
|
||||
|
@ -156,6 +161,8 @@ private:
|
|||
void collectAircraftArgs();
|
||||
void initQML();
|
||||
|
||||
std::string selectStateAutomatically();
|
||||
|
||||
QScopedPointer<Ui::Launcher> m_ui;
|
||||
AircraftProxyModel* m_installedAircraftModel;
|
||||
AircraftItemModel* m_aircraftModel;
|
||||
|
@ -175,6 +182,7 @@ private:
|
|||
LaunchConfig* m_config = nullptr;
|
||||
ExtraSettingsSection* m_extraSettings = nullptr;
|
||||
ViewCommandLinePage* m_viewCommandLinePage = nullptr;
|
||||
QmlAircraftInfo* m_selectedAircraftInfo = nullptr;
|
||||
};
|
||||
|
||||
#endif // of LAUNCHER_MAIN_WINDOW_HXX
|
||||
|
|
|
@ -441,6 +441,45 @@ void LocationWidget::restoreSettings()
|
|||
onShowHistory();
|
||||
}
|
||||
|
||||
bool LocationWidget::isParkedLocation() const
|
||||
{
|
||||
if (FGPositioned::isAirportType(m_location.ptr())) {
|
||||
if (m_ui->parkingRadio->isChecked()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// treat all other ground starts as taxi or on runway, i.e engines
|
||||
// running if possible
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LocationWidget::isAirborneLocation() const
|
||||
{
|
||||
const int altitude = m_ui->altitudeSpinbox->value();
|
||||
const bool altIsPositive = (altitude > 0);
|
||||
const bool offsetSet = m_ui->offsetGroup->isChecked();
|
||||
|
||||
if (m_locationIsLatLon) {
|
||||
return altIsPositive;
|
||||
}
|
||||
|
||||
if (FGPositioned::isAirportType(m_location.ptr())) {
|
||||
if (m_ui->runwayRadio->isChecked() && offsetSet) {
|
||||
// in this case no altitude migth be set, but we assume
|
||||
// it's still an airborne pos
|
||||
return true;
|
||||
}
|
||||
|
||||
// this allows for people using offsets from a parking position or
|
||||
// similar weirdness :)
|
||||
return altIsPositive;
|
||||
}
|
||||
|
||||
// relative to a navaid or fix - base off altitude.
|
||||
return altIsPositive;
|
||||
}
|
||||
|
||||
void LocationWidget::restoreLocation(QVariantMap l)
|
||||
{
|
||||
if (l.contains("location-lat")) {
|
||||
|
|
|
@ -61,6 +61,12 @@ public:
|
|||
QVariantMap saveLocation() const;
|
||||
|
||||
void restoreSettings();
|
||||
|
||||
/// used to automatically select aircraft state
|
||||
bool isParkedLocation() const;
|
||||
|
||||
/// used to automatically select aircraft state
|
||||
bool isAirborneLocation() const;
|
||||
Q_SIGNALS:
|
||||
void descriptionChanged(QString t);
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <simgear/package/Install.hxx>
|
||||
#include <simgear/package/Root.hxx>
|
||||
#include <simgear/structure/exception.hxx>
|
||||
#include <simgear/props/props_io.hxx>
|
||||
|
||||
#include <Include/version.h>
|
||||
#include <Main/globals.hxx>
|
||||
|
@ -14,6 +15,10 @@
|
|||
|
||||
using namespace simgear::pkg;
|
||||
|
||||
const int QmlAircraftInfo::StateTagRole = Qt::UserRole + 1;
|
||||
const int QmlAircraftInfo::StateDescriptionRole = Qt::UserRole + 2;
|
||||
const int QmlAircraftInfo::StateExplicitRole = Qt::UserRole + 3;
|
||||
|
||||
class QmlAircraftInfo::Delegate : public simgear::pkg::Delegate
|
||||
{
|
||||
public:
|
||||
|
@ -51,6 +56,7 @@ protected:
|
|||
{
|
||||
Q_UNUSED(aReason);
|
||||
if (aInstall->package() == p->packageRef()) {
|
||||
p->checkForStates();
|
||||
p->infoChanged();
|
||||
}
|
||||
}
|
||||
|
@ -75,6 +81,145 @@ private:
|
|||
QmlAircraftInfo* p;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
struct StateInfo
|
||||
{
|
||||
std::string tag; // internal XML name
|
||||
QString name; // human-readable name, or blank if we auto-generate this
|
||||
QString description; // human-readable description
|
||||
};
|
||||
|
||||
using AircraftStateVec = std::vector<StateInfo>;
|
||||
|
||||
static AircraftStateVec readAircraftStates(const SGPath& setXMLPath)
|
||||
{
|
||||
SGPropertyNode_ptr root(new SGPropertyNode);
|
||||
try {
|
||||
readProperties(setXMLPath, root);
|
||||
} catch (sg_exception&) {
|
||||
// malformed include or XML, just bail
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!root->getNode("sim/state")) {
|
||||
return {};
|
||||
}
|
||||
|
||||
auto nodes = root->getNode("sim")->getChildren("state");
|
||||
AircraftStateVec result;
|
||||
result.reserve(nodes.size());
|
||||
for (auto cn : nodes) {
|
||||
result.push_back({cn->getStringValue("name"),
|
||||
QString::fromStdString(cn->getStringValue("readable-name")),
|
||||
QString::fromStdString(cn->getStringValue("description"))
|
||||
});
|
||||
|
||||
qInfo() << QString::fromStdString(result.back().tag) << result.back().description;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QString humanNameFromStateTag(const std::string& tag)
|
||||
{
|
||||
if (tag == "approach") return QObject::tr("On approach");
|
||||
if (tag == "take-off") return QObject::tr("Ready for Take-off");
|
||||
if ((tag == "parking") || (tag == "cold-and-dark"))
|
||||
return QObject::tr("Parked, cold & dark");
|
||||
if (tag == "auto")
|
||||
return QObject::tr("Automatic");
|
||||
if (tag == "cruise")
|
||||
return QObject::tr("Cruise");
|
||||
|
||||
qWarning() << Q_FUNC_INFO << "add for" << QString::fromStdString(tag);
|
||||
// no mapping, let's use the tag directly
|
||||
return QString::fromStdString(tag);
|
||||
}
|
||||
|
||||
class StatesModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
StatesModel(const AircraftStateVec& states) :
|
||||
_data(states)
|
||||
{
|
||||
// sort which places 'auto' item at the front if it exists
|
||||
std::sort(_data.begin(), _data.end(), [](const StateInfo& a, const StateInfo& b) {
|
||||
if (a.tag == "auto") return true;
|
||||
if (b.tag == "auto") return false;
|
||||
return a.tag < b.tag;
|
||||
});
|
||||
|
||||
if (_data.front().tag == "auto") {
|
||||
// track if the aircraft supplied an 'auto' state, in which case
|
||||
// we will not run our own selection logic
|
||||
_explicitAutoState = true;
|
||||
} else {
|
||||
// disabling this code for 2018.1, since it needs more testing
|
||||
#if 0
|
||||
_data.insert(_data.begin(), {"auto", {}, tr("Select state based on startup position.")});
|
||||
#else
|
||||
_data.insert(_data.begin(), {"__default__", tr("Parked"), tr("Default state for the aircraft (usually cold and dark)")});
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
int indexForTag(const std::string &tag) const
|
||||
{
|
||||
auto it = std::find_if(_data.begin(), _data.end(), [tag](const StateInfo& i) {
|
||||
return i.tag == tag;
|
||||
});
|
||||
|
||||
if (it == _data.end())
|
||||
return -1;
|
||||
|
||||
return std::distance(_data.begin(), it);
|
||||
}
|
||||
|
||||
int rowCount(const QModelIndex &parent) const override
|
||||
{
|
||||
return _data.size();
|
||||
}
|
||||
|
||||
QVariant data(const QModelIndex &index, int role) const override
|
||||
{
|
||||
const StateInfo& s = _data.at(index.row());
|
||||
// qInfo() << index.row() << s.name << QString::fromStdString(s.tag);
|
||||
if (role == Qt::DisplayRole) {
|
||||
if (s.name.isEmpty()) {
|
||||
return humanNameFromStateTag(s.tag);
|
||||
}
|
||||
return s.name;
|
||||
} else if (role == QmlAircraftInfo::StateTagRole) {
|
||||
return QString::fromStdString(s.tag);
|
||||
} else if (role == QmlAircraftInfo::StateDescriptionRole) {
|
||||
return s.description;
|
||||
} else if (role == QmlAircraftInfo::StateExplicitRole) {
|
||||
if (s.tag == "auto")
|
||||
return _explicitAutoState;
|
||||
return true;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> roleNames() const override
|
||||
{
|
||||
auto result = QAbstractListModel::roleNames();
|
||||
result[Qt::DisplayRole] = "name";
|
||||
result[QmlAircraftInfo::StateTagRole] = "tag";
|
||||
result[QmlAircraftInfo::StateDescriptionRole] = "description";
|
||||
return result;
|
||||
}
|
||||
private:
|
||||
AircraftStateVec _data;
|
||||
bool _explicitAutoState = false;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
QmlAircraftInfo::QmlAircraftInfo(QObject *parent)
|
||||
: QObject(parent)
|
||||
, _delegate(new Delegate(this))
|
||||
|
@ -297,6 +442,26 @@ AircraftItemPtr QmlAircraftInfo::resolveItem() const
|
|||
return _item;
|
||||
}
|
||||
|
||||
void QmlAircraftInfo::checkForStates()
|
||||
{
|
||||
QString path = pathOnDisk();
|
||||
if (path.isEmpty()) {
|
||||
_statesModel.reset();
|
||||
emit infoChanged();
|
||||
return;
|
||||
}
|
||||
|
||||
auto states = readAircraftStates(SGPath::fromUtf8(path.toUtf8().toStdString()));
|
||||
if (states.empty()) {
|
||||
_statesModel.reset();
|
||||
emit infoChanged();
|
||||
return;
|
||||
}
|
||||
|
||||
_statesModel.reset(new StatesModel(states));
|
||||
emit infoChanged();
|
||||
}
|
||||
|
||||
void QmlAircraftInfo::setUri(QUrl u)
|
||||
{
|
||||
if (uri() == u)
|
||||
|
@ -304,9 +469,16 @@ void QmlAircraftInfo::setUri(QUrl u)
|
|||
|
||||
_item.clear();
|
||||
_package.clear();
|
||||
_statesModel.reset();
|
||||
|
||||
if (u.isLocalFile()) {
|
||||
_item = LocalAircraftCache::instance()->findItemWithUri(u);
|
||||
if (!_item) {
|
||||
// scan still active or aircraft not found, let's bail out
|
||||
// and rely on caller to try again
|
||||
return;
|
||||
}
|
||||
|
||||
int vindex = _item->indexOfVariant(u);
|
||||
// we need to offset the variant index to allow for the different
|
||||
// indexing schemes here (primary included) and in the cache (primary
|
||||
|
@ -322,6 +494,8 @@ void QmlAircraftInfo::setUri(QUrl u)
|
|||
}
|
||||
}
|
||||
|
||||
checkForStates();
|
||||
|
||||
emit uriChanged();
|
||||
emit infoChanged();
|
||||
emit downloadChanged();
|
||||
|
@ -341,6 +515,8 @@ void QmlAircraftInfo::setVariant(int variant)
|
|||
return;
|
||||
|
||||
_variant = variant;
|
||||
checkForStates();
|
||||
|
||||
emit infoChanged();
|
||||
emit variantChanged(_variant);
|
||||
}
|
||||
|
@ -412,7 +588,7 @@ PackageRef QmlAircraftInfo::packageRef() const
|
|||
void QmlAircraftInfo::setDownloadBytes(int bytes)
|
||||
{
|
||||
_downloadBytes = bytes;
|
||||
emit downloadChanged();;
|
||||
emit downloadChanged();
|
||||
}
|
||||
|
||||
QStringList QmlAircraftInfo::variantNames() const
|
||||
|
@ -441,3 +617,14 @@ bool QmlAircraftInfo::isPackaged() const
|
|||
{
|
||||
return _package != PackageRef();
|
||||
}
|
||||
|
||||
QAbstractListModel *QmlAircraftInfo::statesModel()
|
||||
{
|
||||
if (!hasStates())
|
||||
return nullptr;
|
||||
|
||||
return _statesModel.data();
|
||||
}
|
||||
|
||||
#include "QmlAircraftInfo.moc"
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <QObject>
|
||||
#include <QUrl>
|
||||
#include <QSharedPointer>
|
||||
#include <QAbstractListModel>
|
||||
|
||||
#include <simgear/package/Catalog.hxx>
|
||||
#include <simgear/package/Package.hxx>
|
||||
|
@ -54,6 +55,10 @@ class QmlAircraftInfo : public QObject
|
|||
|
||||
Q_PROPERTY(bool isPackaged READ isPackaged NOTIFY infoChanged)
|
||||
|
||||
Q_PROPERTY(bool hasStates READ hasStates NOTIFY infoChanged)
|
||||
|
||||
Q_PROPERTY(QAbstractListModel* statesModel READ statesModel NOTIFY infoChanged)
|
||||
|
||||
public:
|
||||
explicit QmlAircraftInfo(QObject *parent = nullptr);
|
||||
virtual ~QmlAircraftInfo();
|
||||
|
@ -95,6 +100,17 @@ public:
|
|||
QStringList variantNames() const;
|
||||
|
||||
bool isPackaged() const;
|
||||
|
||||
bool hasStates() const
|
||||
{
|
||||
return !_statesModel.isNull();
|
||||
}
|
||||
|
||||
static const int StateTagRole;
|
||||
static const int StateDescriptionRole;
|
||||
static const int StateExplicitRole;
|
||||
|
||||
QAbstractListModel* statesModel();
|
||||
signals:
|
||||
void uriChanged();
|
||||
void infoChanged();
|
||||
|
@ -108,6 +124,9 @@ public slots:
|
|||
void setVariant(int variant);
|
||||
|
||||
private:
|
||||
AircraftItemPtr resolveItem() const;
|
||||
void checkForStates();
|
||||
|
||||
class Delegate;
|
||||
std::unique_ptr<Delegate> _delegate;
|
||||
|
||||
|
@ -115,9 +134,7 @@ private:
|
|||
AircraftItemPtr _item;
|
||||
int _variant = 0;
|
||||
int _downloadBytes = 0;
|
||||
|
||||
AircraftItemPtr resolveItem() const;
|
||||
int m_variant;
|
||||
QScopedPointer<QAbstractListModel> _statesModel;
|
||||
};
|
||||
|
||||
#endif // QMLAIRCRAFTINFO_HXX
|
||||
|
|
Loading…
Add table
Reference in a new issue