QML-driven settings UI.
This commit is contained in:
parent
5c713a6b55
commit
3732930269
59 changed files with 2768 additions and 2011 deletions
|
@ -311,7 +311,7 @@ endif (USE_DBUS)
|
|||
## Qt5 setup setup
|
||||
if (ENABLE_QT)
|
||||
message(STATUS "Qt launcher enabled, checking for Qt 5.1 / qmake")
|
||||
find_package(Qt5 5.1 COMPONENTS Widgets Network)
|
||||
find_package(Qt5 5.1 COMPONENTS Widgets Network Qml)
|
||||
if (Qt5Widgets_FOUND)
|
||||
message(STATUS "Will enable Qt launcher GUI")
|
||||
message(STATUS " Qt5Widgets version: ${Qt5Widgets_VERSION_STRING}")
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
#include "AdditionalSettings.h"
|
||||
|
||||
#include "ui_AdditionalSettings.h"
|
||||
|
||||
AdditionalSettings::AdditionalSettings(QWidget *parent) :
|
||||
SettingsSection(parent),
|
||||
ui(new Ui::AdditionalSettings)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
insertSettingsHeader();
|
||||
}
|
||||
|
||||
AdditionalSettings::~AdditionalSettings()
|
||||
{
|
||||
delete ui;
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
#ifndef ADDITIONAL_SETTINGS_H
|
||||
#define ADDITIONAL_SETTINGS_H
|
||||
|
||||
#include <GUI/settingssection.h>
|
||||
|
||||
namespace Ui {
|
||||
class AdditionalSettings;
|
||||
}
|
||||
|
||||
class AdditionalSettings : public SettingsSection
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AdditionalSettings(QWidget *parent = 0);
|
||||
~AdditionalSettings();
|
||||
|
||||
private:
|
||||
Ui::AdditionalSettings *ui;
|
||||
};
|
||||
|
||||
#endif // ADDITIONAL_SETTINGS_H
|
|
@ -1,52 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AdditionalSettings</class>
|
||||
<widget class="SettingsSection" name="AdditionalSettings">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>771</width>
|
||||
<height>331</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<property name="title" stdset="0">
|
||||
<string>Additional settings</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Additional settings can be entered here. For information on available settings see <this page></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="help" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="plainTextEdit">
|
||||
<property name="placeholderText">
|
||||
<string>--prop:foo=42</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>SettingsSection</class>
|
||||
<extends>QWidget</extends>
|
||||
<header location="global">GUI/settingssection.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -78,14 +78,7 @@ if (HAVE_QT)
|
|||
LocationWidget.ui
|
||||
NoOfficialHangar.ui
|
||||
InstallSceneryDialog.ui
|
||||
EditCustomMPServerDialog.ui
|
||||
UpdateAllAircraft.ui
|
||||
RenderingSettings.ui
|
||||
ViewSettings.ui
|
||||
MPSettings.ui
|
||||
DownloadSettings.ui
|
||||
EnvironmentPage.ui
|
||||
AdditionalSettings.ui
|
||||
)
|
||||
qt5_add_resources(qrc_sources resources.qrc)
|
||||
|
||||
|
@ -102,6 +95,8 @@ if (HAVE_QT)
|
|||
NavaidDiagram.hxx
|
||||
EditRatingsFilterDialog.cxx
|
||||
EditRatingsFilterDialog.hxx
|
||||
ExtraSettingsSection.cxx
|
||||
ExtraSettingsSection.hxx
|
||||
SetupRootDialog.cxx
|
||||
SetupRootDialog.hxx
|
||||
AircraftItemDelegate.hxx
|
||||
|
@ -122,40 +117,37 @@ if (HAVE_QT)
|
|||
QtFileDialog.hxx
|
||||
InstallSceneryDialog.hxx
|
||||
InstallSceneryDialog.cxx
|
||||
EditCustomMPServerDialog.cxx
|
||||
EditCustomMPServerDialog.hxx
|
||||
previewwindow.cpp
|
||||
previewwindow.h
|
||||
SettingsSection.cpp
|
||||
SettingsSection.h
|
||||
renderingsettings.cpp
|
||||
renderingsettings.h
|
||||
ViewSettings.cpp
|
||||
ViewSettings.h
|
||||
MPSettings.cpp
|
||||
MPSettings.h
|
||||
SettingsSectionQML.cxx
|
||||
SettingsSectionQML.hxx
|
||||
AdvancedSettingsButton.h
|
||||
AdvancedSettingsButton.cpp
|
||||
DownloadSettings.cpp
|
||||
DownloadSettings.h
|
||||
ToolboxButton.cpp
|
||||
ToolboxButton.h
|
||||
EnvironmentPage.cpp
|
||||
EnvironmentPage.h
|
||||
AdditionalSettings.cpp
|
||||
AdditionalSettings.h
|
||||
LauncherArgumentTokenizer.cxx
|
||||
LauncherArgumentTokenizer.hxx
|
||||
AircraftSearchFilterModel.cxx
|
||||
AircraftSearchFilterModel.hxx
|
||||
DefaultAircraftLocator.cxx
|
||||
DefaultAircraftLocator.hxx
|
||||
SettingsWidgets.cxx
|
||||
SettingsWidgets.hxx
|
||||
LaunchConfig.cxx
|
||||
LaunchConfig.hxx
|
||||
ViewCommandLinePage.cxx
|
||||
ViewCommandLinePage.hxx
|
||||
MPServersModel.cpp
|
||||
MPServersModel.h
|
||||
${uic_sources}
|
||||
${qrc_sources})
|
||||
|
||||
set_property(TARGET fglauncher PROPERTY AUTOMOC ON)
|
||||
target_link_libraries(fglauncher Qt5::Core Qt5::Widgets Qt5::Network SimGearCore)
|
||||
target_link_libraries(fglauncher Qt5::Core Qt5::Widgets Qt5::Network Qt5::Qml SimGearCore)
|
||||
target_include_directories(fglauncher PRIVATE ${PROJECT_BINARY_DIR}/src/GUI)
|
||||
target_include_directories(fglauncher PRIVATE ${Qt5Qml_PRIVATE_INCLUDE_DIRS})
|
||||
|
||||
|
||||
endif()
|
||||
|
|
|
@ -65,4 +65,82 @@ DefaultAircraftLocator::visit(const SGPath& p)
|
|||
return VISIT_CONTINUE;
|
||||
}
|
||||
|
||||
WeatherScenariosModel::WeatherScenariosModel(QObject *pr) :
|
||||
QAbstractListModel(pr)
|
||||
{
|
||||
SGPropertyNode_ptr root = loadXMLDefaults();
|
||||
if (root) {
|
||||
SGPropertyNode_ptr scenarios = root->getNode("environment/weather-scenarios");
|
||||
Q_ASSERT(scenarios);
|
||||
int nChildren = scenarios->nChildren();
|
||||
for (int i = 0; i < nChildren; i++) {
|
||||
SGPropertyNode_ptr scenario = scenarios->getChild(i);
|
||||
if (strcmp(scenario->getName(), "scenario") != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (scenario->getStringValue("local-weather/tile-type") == std::string("live")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
WeatherScenario ws;
|
||||
ws.name = QString::fromStdString(scenario->getStringValue("name"));
|
||||
ws.description = QString::fromStdString(scenario->getStringValue("description")).simplified();
|
||||
ws.metar = QString::fromStdString(scenario->getStringValue("metar"));
|
||||
m_scenarios.push_back(ws);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int WeatherScenariosModel::rowCount(const QModelIndex &index) const
|
||||
{
|
||||
return m_scenarios.size();
|
||||
}
|
||||
|
||||
QVariant WeatherScenariosModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
const int row = index.row();
|
||||
if ((row < 0) || (row >= m_scenarios.size())) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
const WeatherScenario& scenario(m_scenarios.at(row));
|
||||
if ((role == Qt::DisplayRole) || (role == NameRole)) {
|
||||
return scenario.name;
|
||||
} else if (role == DescriptionRole) {
|
||||
return scenario.description;
|
||||
} else if (role == MetarRole) {
|
||||
return scenario.metar;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> WeatherScenariosModel::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> result;
|
||||
result[NameRole] = "name";
|
||||
result[DescriptionRole] = "description";
|
||||
result[MetarRole] = "metar";
|
||||
return result;
|
||||
}
|
||||
|
||||
QString WeatherScenariosModel::metarForItem(int index) const
|
||||
{
|
||||
if ((index < 0) || (index >= m_scenarios.size())) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
return m_scenarios.at(index).metar;
|
||||
}
|
||||
|
||||
QString WeatherScenariosModel::descriptionForItem(int index) const
|
||||
{
|
||||
if ((index < 0) || (index >= m_scenarios.size())) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
return m_scenarios.at(index).description;
|
||||
}
|
||||
|
||||
} // of namespace flightgear
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
#include <Main/AircraftDirVisitorBase.hxx>
|
||||
|
||||
#include <QAbstractListModel>
|
||||
|
||||
namespace flightgear
|
||||
{
|
||||
|
||||
|
@ -30,6 +32,38 @@ private:
|
|||
SGPath _foundPath;
|
||||
};
|
||||
|
||||
class WeatherScenariosModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
WeatherScenariosModel(QObject* pr = nullptr);
|
||||
|
||||
int rowCount(const QModelIndex& index) const override;
|
||||
|
||||
QVariant data(const QModelIndex& index, int role) const override;
|
||||
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
Q_INVOKABLE QString metarForItem(int index) const;
|
||||
|
||||
Q_INVOKABLE QString descriptionForItem(int index) const;
|
||||
private:
|
||||
struct WeatherScenario
|
||||
{
|
||||
QString name;
|
||||
QString description;
|
||||
QString metar;
|
||||
};
|
||||
|
||||
std::vector<WeatherScenario> m_scenarios;
|
||||
|
||||
enum {
|
||||
NameRole = Qt::UserRole + 1,
|
||||
DescriptionRole,
|
||||
MetarRole
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // DEFAULTAIRCRAFTLOCATOR_HXX
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
#include "DownloadSettings.h"
|
||||
#include "ui_DownloadSettings.h"
|
||||
|
||||
DownloadSettings::DownloadSettings(QWidget *parent) :
|
||||
SettingsSection(parent),
|
||||
ui(new Ui::DownloadSettings)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
insertSettingsHeader();
|
||||
}
|
||||
|
||||
DownloadSettings::~DownloadSettings()
|
||||
{
|
||||
delete ui;
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
#ifndef DOWNLOAD_SETTINGS_H
|
||||
#define DOWNLOAD_SETTINGS_H
|
||||
|
||||
#include <GUI/settingssection.h>
|
||||
|
||||
namespace Ui {
|
||||
class DownloadSettings;
|
||||
}
|
||||
|
||||
class DownloadSettings : public SettingsSection
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DownloadSettings(QWidget *parent = 0);
|
||||
~DownloadSettings();
|
||||
|
||||
private:
|
||||
Ui::DownloadSettings *ui;
|
||||
};
|
||||
|
||||
#endif // DOWNLOAD_SETTINGS_H
|
36
src/GUI/DownloadSettings.qml
Normal file
36
src/GUI/DownloadSettings.qml
Normal file
|
@ -0,0 +1,36 @@
|
|||
import FlightGear.Launcher 1.0
|
||||
|
||||
Section {
|
||||
id: downloadSettings
|
||||
title: "Downloads"
|
||||
|
||||
Checkbox {
|
||||
id: terrasync
|
||||
label: "Download scenery automatically"
|
||||
description: "FlightGear can automatically download scenery as needed, and check for updates to "
|
||||
+ "the scenery. If you disable this option, you will need to download & install scenery "
|
||||
+ "using an alternative method."
|
||||
keywords: ["terrasync", "download"]
|
||||
option: "terrasync"
|
||||
}
|
||||
|
||||
// file path chooser for downloads directory
|
||||
|
||||
PathChooser {
|
||||
id: downloadDir
|
||||
label: "Download location"
|
||||
description: "FlightGear stores downloaded files (scenery and aircraft) in this location. "
|
||||
+ "Depending on your settings, it may grow to a considerable size (many gigabytes)."
|
||||
+ "If you change the download location, files will need to be downloaded again."
|
||||
advanced: true
|
||||
chooseDirectory: true
|
||||
defaultPath: _config.defaultDownloadDir
|
||||
option: "download-dir"
|
||||
dialogPrompt: "Choose a location to store download files."
|
||||
}
|
||||
|
||||
onApply: {
|
||||
}
|
||||
|
||||
summary: terrasync.checked ? "scenery downloads;" : ""
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>DownloadSettings</class>
|
||||
<widget class="SettingsSection" name="DownloadSettings">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>771</width>
|
||||
<height>94</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<property name="title" stdset="0">
|
||||
<string>Downloads</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox">
|
||||
<property name="text">
|
||||
<string>Download scenery automatically</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>FlightGear can automatically download and update scenery wherever you fly in the world. This can take some time depening on your Internet connection's speed, but is faster than download the entire world's scenery.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="help" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>SettingsSection</class>
|
||||
<extends>QWidget</extends>
|
||||
<header location="global">GUI/settingssection.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -1,48 +0,0 @@
|
|||
#include "EditCustomMPServerDialog.hxx"
|
||||
#include "ui_EditCustomMPServerDialog.h"
|
||||
|
||||
#include <QSettings>
|
||||
#include <QComboBox>
|
||||
|
||||
#include "Main/fg_props.hxx"
|
||||
|
||||
EditCustomMPServerDialog::EditCustomMPServerDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::EditCustomMPServerDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
QSettings settings;
|
||||
ui->mpServer->setText(settings.value("mp-custom-host").toString());
|
||||
ui->port->setText(settings.value("mp-custom-port").toString());
|
||||
}
|
||||
|
||||
EditCustomMPServerDialog::~EditCustomMPServerDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
QString EditCustomMPServerDialog::hostname() const
|
||||
{
|
||||
return ui->mpServer->text();
|
||||
}
|
||||
|
||||
void EditCustomMPServerDialog::accept()
|
||||
{
|
||||
QSettings settings;
|
||||
settings.setValue("mp-custom-host", ui->mpServer->text());
|
||||
settings.setValue("mp-custom-port", ui->port->text());
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void EditCustomMPServerDialog::addCustomItem(QComboBox* combo)
|
||||
{
|
||||
QSettings settings;
|
||||
QString customMPHost = settings.value("mp-custom-host").toString();
|
||||
|
||||
if (customMPHost.isEmpty()) {
|
||||
combo->addItem(tr("Custom server..."), "custom");
|
||||
return;
|
||||
}
|
||||
|
||||
combo->addItem(tr("Custom - %1").arg(customMPHost), "custom");
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
#ifndef EDITCUSTOMMPSERVERDIALOG_HXX
|
||||
#define EDITCUSTOMMPSERVERDIALOG_HXX
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace Ui {
|
||||
class EditCustomMPServerDialog;
|
||||
}
|
||||
|
||||
class QComboBox;
|
||||
|
||||
class EditCustomMPServerDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit EditCustomMPServerDialog(QWidget *parent = 0);
|
||||
~EditCustomMPServerDialog();
|
||||
|
||||
QString hostname() const;
|
||||
|
||||
virtual void accept();
|
||||
|
||||
static void addCustomItem(QComboBox* combo);
|
||||
private:
|
||||
Ui::EditCustomMPServerDialog *ui;
|
||||
};
|
||||
|
||||
#endif // EDITCUSTOMMPSERVERDIALOG_HXX
|
|
@ -1,120 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>EditCustomMPServerDialog</class>
|
||||
<widget class="QDialog" name="EditCustomMPServerDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>369</width>
|
||||
<height>172</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Enter custom server</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/app-icon-large</normaloff>:/app-icon-large</iconset>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout" columnstretch="1,1">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Enter the host name and optional port of the multi-player server you wish to connect to.</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Server:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="mpServer">
|
||||
<property name="placeholderText">
|
||||
<string>flightgear.example.com</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Port:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="port">
|
||||
<property name="text">
|
||||
<string>5000</string>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>5000</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="resources.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>EditCustomMPServerDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>EditCustomMPServerDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
|
@ -1,17 +0,0 @@
|
|||
#include "EnvironmentPage.h"
|
||||
#include "ui_EnvironmentPage.h"
|
||||
|
||||
EnvironmentPage::EnvironmentPage(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::EnvironmentPage)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->weatherSection->insertSettingsHeader();
|
||||
ui->timeSection->insertSettingsHeader();
|
||||
}
|
||||
|
||||
EnvironmentPage::~EnvironmentPage()
|
||||
{
|
||||
delete ui;
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
#ifndef ENVIRONMENTPAGE_H
|
||||
#define ENVIRONMENTPAGE_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
namespace Ui {
|
||||
class EnvironmentPage;
|
||||
}
|
||||
|
||||
class EnvironmentPage : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit EnvironmentPage(QWidget *parent = 0);
|
||||
~EnvironmentPage();
|
||||
|
||||
private:
|
||||
Ui::EnvironmentPage *ui;
|
||||
};
|
||||
|
||||
#endif // ENVIRONMENTPAGE_H
|
|
@ -1,262 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>EnvironmentPage</class>
|
||||
<widget class="QWidget" name="EnvironmentPage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>728</width>
|
||||
<height>580</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="SettingsSection" name="timeSection" native="true">
|
||||
<property name="title" stdset="0">
|
||||
<string>Time and Date</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QRadioButton" name="radioButton">
|
||||
<property name="text">
|
||||
<string>Predefined time</string>
|
||||
</property>
|
||||
<property name="advanced" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QRadioButton" name="radioButton_2">
|
||||
<property name="text">
|
||||
<string>Manually selected date and time</string>
|
||||
</property>
|
||||
<property name="advanced" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QComboBox" name="comboBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Current local time</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Dawn</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Morning</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Noon</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Dusk</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Midnight</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QDateTimeEdit" name="dateTimeEdit">
|
||||
<property name="advanced" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Time of day:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="simple" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>By default the simulator uses your computer's local time as the local time at your chosen startup location. You can select a standard time of day, or enter an exact time and date.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="help" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="SettingsSection" name="weatherSection" native="true">
|
||||
<property name="title" stdset="0">
|
||||
<string>Weather</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Weather:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBox_3">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Real-world weather</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Clear and calm</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Thunderstorm</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Choose a standard weather scenario, or download weather reports (METAR) automatically online, from the closest airports.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="help" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Season:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBox_2">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Summer</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Winter</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Changing the season affects which textures are used for scenery, but otherwise has no effect.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="help" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<zorder>timeSection</zorder>
|
||||
<zorder>label_2</zorder>
|
||||
<zorder>comboBox_2</zorder>
|
||||
<zorder>weatherSection</zorder>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>SettingsSection</class>
|
||||
<extends>QWidget</extends>
|
||||
<header location="global">GUI/SettingsSection.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
79
src/GUI/ExtraSettingsSection.cxx
Normal file
79
src/GUI/ExtraSettingsSection.cxx
Normal file
|
@ -0,0 +1,79 @@
|
|||
#include "ExtraSettingsSection.hxx"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QTextEdit>
|
||||
#include <QVBoxLayout>
|
||||
#include <QSettings>
|
||||
|
||||
#include "LauncherArgumentTokenizer.hxx"
|
||||
#include "LaunchConfig.hxx"
|
||||
#include "AdvancedSettingsButton.h"
|
||||
|
||||
ExtraSettingsSection::ExtraSettingsSection(QWidget* pr) :
|
||||
SettingsSection(pr)
|
||||
{
|
||||
setTitle(tr("Additional Settings"));
|
||||
|
||||
QVBoxLayout* topLevelVBox = qobject_cast<QVBoxLayout*>(layout());
|
||||
QLabel* prompt = new QLabel(this);
|
||||
prompt->setText("Enter additional command-line arguments if any are required. "
|
||||
"See <a href=\"http://flightgear.sourceforge.net/getstart-en/getstart-enpa2.html#x5-450004.5\">here</a> "
|
||||
"for documentation on possible arguments.");
|
||||
prompt->setWordWrap(true);
|
||||
prompt->setOpenExternalLinks(true);
|
||||
|
||||
topLevelVBox->addWidget(prompt);
|
||||
m_argsEdit = new QTextEdit(this);
|
||||
m_argsEdit->setAcceptRichText(false);
|
||||
|
||||
#if QT_VERSION >= 0x050300
|
||||
// don't require Qt 5.3
|
||||
m_argsEdit->setPlaceholderText("--option=value --prop:/sim/name=value");
|
||||
#endif
|
||||
topLevelVBox->addWidget(m_argsEdit);
|
||||
|
||||
insertSettingsHeader();
|
||||
setShowAdvanced(false);
|
||||
m_advancedModeToggle->setVisible(false);
|
||||
}
|
||||
|
||||
QString ExtraSettingsSection::argsText() const
|
||||
{
|
||||
return m_argsEdit->toPlainText();
|
||||
}
|
||||
|
||||
void ExtraSettingsSection::setLaunchConfig(LaunchConfig* config)
|
||||
{
|
||||
m_config = config;
|
||||
SettingsSection::setLaunchConfig(config);
|
||||
}
|
||||
|
||||
void ExtraSettingsSection::doApply()
|
||||
{
|
||||
LauncherArgumentTokenizer tk;
|
||||
|
||||
Q_FOREACH(auto arg, tk.tokenize(m_argsEdit->toPlainText())) {
|
||||
m_config->setArg(arg.arg, arg.value);
|
||||
}
|
||||
}
|
||||
|
||||
void ExtraSettingsSection::saveState(QSettings &settings) const
|
||||
{
|
||||
settings.setValue("extra-args", m_argsEdit->toPlainText());
|
||||
}
|
||||
|
||||
void ExtraSettingsSection::restoreState(QSettings &settings)
|
||||
{
|
||||
m_argsEdit->setText(settings.value("extra-args").toString());
|
||||
}
|
||||
|
||||
QString ExtraSettingsSection::summary() const
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
|
||||
void ExtraSettingsSection::validateText()
|
||||
{
|
||||
|
||||
}
|
||||
|
36
src/GUI/ExtraSettingsSection.hxx
Normal file
36
src/GUI/ExtraSettingsSection.hxx
Normal file
|
@ -0,0 +1,36 @@
|
|||
#ifndef EXTRASETTINGSSECTION_HXX
|
||||
#define EXTRASETTINGSSECTION_HXX
|
||||
|
||||
#include "settingssection.h"
|
||||
|
||||
class QTextEdit;
|
||||
class LaunchConfig;
|
||||
|
||||
class ExtraSettingsSection : public SettingsSection
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ExtraSettingsSection(QWidget* pr = nullptr);
|
||||
|
||||
QString argsText() const;
|
||||
|
||||
void setLaunchConfig(LaunchConfig* config) override;
|
||||
|
||||
virtual void doApply() override;
|
||||
|
||||
void saveState(QSettings &settings) const override;
|
||||
|
||||
void restoreState(QSettings &settings) override;
|
||||
|
||||
QString summary() const;
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
void validateText();
|
||||
|
||||
QTextEdit* m_argsEdit;
|
||||
LaunchConfig* m_config;
|
||||
};
|
||||
|
||||
#endif // EXTRASETTINGSSECTION_HXX
|
32
src/GUI/GeneralSettings.qml
Normal file
32
src/GUI/GeneralSettings.qml
Normal file
|
@ -0,0 +1,32 @@
|
|||
import FlightGear.Launcher 1.0
|
||||
|
||||
Section {
|
||||
id: generalSettings
|
||||
title: "General"
|
||||
|
||||
Checkbox {
|
||||
id: startPaused
|
||||
label: "Start paused"
|
||||
description: "Automatically pause the simulator when launching. This is useful "
|
||||
+ "when starting in the air."
|
||||
keywords: ["pause", "freeze"]
|
||||
}
|
||||
|
||||
Checkbox {
|
||||
id: autoCoordination
|
||||
label: "Enable auto-coordination"
|
||||
description: "When flying with the mouse, or a joystick lacking a rudder axis, "
|
||||
+ "it's difficult to manually coordinate aileron and rudder movements during "
|
||||
+ "turn. This option automatically commands the rudder to maintain zero "
|
||||
+ "slip angle when banking";
|
||||
advanced: true
|
||||
keywords: ["input", "mouse", "control", "rudder"]
|
||||
option: "auto-coordination"
|
||||
}
|
||||
|
||||
onApply: {
|
||||
if (startPaused.checked) {
|
||||
_config.setArg("enable-freeze")
|
||||
}
|
||||
}
|
||||
}
|
53
src/GUI/LaunchConfig.cxx
Normal file
53
src/GUI/LaunchConfig.cxx
Normal file
|
@ -0,0 +1,53 @@
|
|||
#include "LaunchConfig.hxx"
|
||||
|
||||
#include <Main/options.hxx>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
|
||||
LaunchConfig::LaunchConfig(QObject* parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void LaunchConfig::reset()
|
||||
{
|
||||
m_values.clear();
|
||||
}
|
||||
|
||||
void LaunchConfig::applyToOptions() const
|
||||
{
|
||||
flightgear::Options* options = flightgear::Options::sharedInstance();
|
||||
std::for_each(m_values.begin(), m_values.end(), [options](const Arg& arg)
|
||||
{
|
||||
options->addOption(arg.arg.toStdString(), arg.value.toStdString());
|
||||
});
|
||||
}
|
||||
|
||||
void LaunchConfig::setArg(QString name, QString value)
|
||||
{
|
||||
m_values.push_back(Arg(name, value));
|
||||
}
|
||||
|
||||
void LaunchConfig::setArg(const std::string &name, const std::string &value)
|
||||
{
|
||||
setArg(QString::fromStdString(name), QString::fromStdString(value));
|
||||
}
|
||||
|
||||
void LaunchConfig::setProperty(QString path, QVariant value)
|
||||
{
|
||||
m_values.push_back(Arg("prop", path + "=" + value.toString()));
|
||||
}
|
||||
|
||||
void LaunchConfig::setEnableDisableOption(QString name, bool value)
|
||||
{
|
||||
m_values.push_back(Arg((value ? "enable-" : "disable-") + name));
|
||||
}
|
||||
|
||||
QString LaunchConfig::defaultDownloadDir() const
|
||||
{
|
||||
return QString::fromStdString(flightgear::defaultDownloadDir().utf8Str());
|
||||
}
|
||||
|
||||
auto LaunchConfig::values() const -> std::vector<Arg>
|
||||
{
|
||||
return m_values;
|
||||
}
|
54
src/GUI/LaunchConfig.hxx
Normal file
54
src/GUI/LaunchConfig.hxx
Normal file
|
@ -0,0 +1,54 @@
|
|||
#ifndef FG_GUI_LAUNCHCONFIG_HXX
|
||||
#define FG_GUI_LAUNCHCONFIG_HXX
|
||||
|
||||
#include <QObject>
|
||||
#include <QVariant>
|
||||
|
||||
namespace flightgear { class Options; }
|
||||
|
||||
class LaunchConfig : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QString defaultDownloadDir READ defaultDownloadDir CONSTANT)
|
||||
public:
|
||||
class Arg
|
||||
{
|
||||
public:
|
||||
explicit Arg(QString k, QString v = QString()) : arg(k), value(v) {}
|
||||
|
||||
QString arg;
|
||||
QString value;
|
||||
};
|
||||
|
||||
|
||||
LaunchConfig(QObject* parent = nullptr);
|
||||
|
||||
void reset();
|
||||
void applyToOptions() const;
|
||||
|
||||
std::vector<Arg> values() const;
|
||||
|
||||
Q_INVOKABLE void setArg(QString name, QString value = QString());
|
||||
|
||||
Q_INVOKABLE void setArg(const std::string& name, const std::string& value = std::string());
|
||||
|
||||
Q_INVOKABLE void setProperty(QString path, QVariant value);
|
||||
|
||||
Q_INVOKABLE void setEnableDisableOption(QString name, bool value);
|
||||
|
||||
// ensure a property is /not/ set?
|
||||
|
||||
// save and restore API?
|
||||
|
||||
QString defaultDownloadDir() const;
|
||||
|
||||
signals:
|
||||
void collect();
|
||||
|
||||
private:
|
||||
std::vector<Arg> m_values;
|
||||
QString m_defaultDownloadDir;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -198,6 +198,20 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="ToolboxButton" name="addOnsButton">
|
||||
<property name="text">
|
||||
<string>Add-ons</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/toolbox-addons</normaloff>:/toolbox-addons</iconset>
|
||||
</property>
|
||||
<property name="pageIndex" stdset="0">
|
||||
<number>5</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
|
@ -227,6 +241,9 @@
|
|||
</item>
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="stack">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
|
@ -403,11 +420,14 @@
|
|||
<item row="1" column="3" colspan="2">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>©2017, Curtis L Olson. Licensed under the GNU Public License (GPL) version 2. See <here> for more information</string>
|
||||
<string><html><head/><body><p>©2017 FlightGear contributiors. 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">
|
||||
|
@ -428,16 +448,16 @@
|
|||
<number>4</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>2</number>
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>2</number>
|
||||
<number>4</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
|
@ -526,7 +546,39 @@
|
|||
</layout>
|
||||
</widget>
|
||||
<widget class="LocationWidget" name="location"/>
|
||||
<widget class="EnvironmentPage" name="environmentPage"/>
|
||||
<widget class="QWidget" name="environmentPage">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<property name="leftMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QScrollArea" name="scrollArea_2">
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="environmentScrollContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>643</width>
|
||||
<height>644</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="newSettingsPage">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
|
@ -551,8 +603,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>173</width>
|
||||
<height>28</height>
|
||||
<width>643</width>
|
||||
<height>644</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
|
@ -598,7 +650,7 @@
|
|||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineEdit">
|
||||
<widget class="QLineEdit" name="settingsSearchEdit">
|
||||
<property name="placeholderText">
|
||||
<string>Search...</string>
|
||||
</property>
|
||||
|
@ -629,12 +681,6 @@
|
|||
<extends>QPushButton</extends>
|
||||
<header location="global">GUI/ToolboxButton.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>EnvironmentPage</class>
|
||||
<extends>QWidget</extends>
|
||||
<header location="global">GUI/EnvironmentPage.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="resources.qrc"/>
|
||||
|
|
|
@ -5,12 +5,19 @@
|
|||
#include <QSettings>
|
||||
#include <QDebug>
|
||||
#include <QMenu>
|
||||
#include <QMenuBar>
|
||||
#include <QMenu>
|
||||
|
||||
#include <QQmlEngine>
|
||||
#include <QQmlComponent>
|
||||
#include <QQmlContext>
|
||||
|
||||
#include <private/qqmlglobal_p.h>
|
||||
|
||||
// simgear headers
|
||||
#include <simgear/package/Install.hxx>
|
||||
|
||||
// FlightGear headers
|
||||
#include <Network/RemoteXMLRequest.hxx>
|
||||
#include <Network/HTTPClient.hxx>
|
||||
#include <Main/globals.hxx>
|
||||
#include <Airports/airport.hxx>
|
||||
|
@ -20,19 +27,19 @@
|
|||
|
||||
// launcher headers
|
||||
#include "QtLauncher.hxx"
|
||||
#include "renderingsettings.h"
|
||||
#include "ViewSettings.h"
|
||||
#include "MPSettings.h"
|
||||
#include "DownloadSettings.h"
|
||||
#include "AdditionalSettings.h"
|
||||
#include "EditRatingsFilterDialog.hxx"
|
||||
#include "AircraftItemDelegate.hxx"
|
||||
#include "AircraftModel.hxx"
|
||||
#include "PathsDialog.hxx"
|
||||
#include "EditCustomMPServerDialog.hxx"
|
||||
#include "LauncherArgumentTokenizer.hxx"
|
||||
#include "AircraftSearchFilterModel.hxx"
|
||||
#include "DefaultAircraftLocator.hxx"
|
||||
#include "SettingsWidgets.hxx"
|
||||
#include "previewwindow.h"
|
||||
#include "LaunchConfig.hxx"
|
||||
#include "SettingsSectionQML.hxx"
|
||||
#include "ExtraSettingsSection.hxx"
|
||||
#include "ViewCommandLinePage.hxx"
|
||||
#include "MPServersModel.h"
|
||||
|
||||
#include "ui_Launcher.h"
|
||||
#include "ui_NoOfficialHangar.h"
|
||||
|
@ -86,29 +93,52 @@ private:
|
|||
|
||||
#include "LauncherMainWindow.moc"
|
||||
|
||||
QQmlPrivate::AutoParentResult launcher_autoParent(QObject* thing, QObject* parent)
|
||||
{
|
||||
SettingsSection* ss = qobject_cast<SettingsSection*>(parent);
|
||||
SettingsControl* sc = qobject_cast<SettingsControl*>(thing);
|
||||
if (ss && sc) {
|
||||
qInfo() << "let's do this!" << ss << sc;
|
||||
sc->setParent(ss);
|
||||
return QQmlPrivate::Parented;
|
||||
}
|
||||
|
||||
qWarning() << "Unsuitable" << thing << parent;
|
||||
return QQmlPrivate::IncompatibleObject;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LauncherMainWindow::LauncherMainWindow() :
|
||||
QMainWindow(),
|
||||
m_ui(NULL),
|
||||
m_subsystemIdleTimer(NULL),
|
||||
m_doRestoreMPServer(false)
|
||||
m_subsystemIdleTimer(NULL)
|
||||
{
|
||||
m_ui.reset(new Ui::Launcher);
|
||||
m_ui->setupUi(this);
|
||||
|
||||
#if QT_VERSION >= 0x050300
|
||||
// don't require Qt 5.3
|
||||
//m_ui->commandLineArgs->setPlaceholderText("--option=value --prop:/sim/name=value");
|
||||
#endif
|
||||
QMenuBar* mb = menuBar();
|
||||
QMenu* toolsMenu = mb->addMenu(tr("Tools"));
|
||||
QAction* restoreDefaultsAction = toolsMenu->addAction(tr("Restore defaults..."));
|
||||
connect(restoreDefaultsAction, &QAction::triggered,
|
||||
this, &LauncherMainWindow::onRestoreDefaults);
|
||||
|
||||
QAction* changeDataAction = toolsMenu->addAction(tr("Select data files location..."));
|
||||
connect(changeDataAction, &QAction::triggered,
|
||||
this, &LauncherMainWindow::onChangeDataDir);
|
||||
|
||||
QAction* viewCommandLineAction = toolsMenu->addAction(tr("View command-line"));
|
||||
connect(viewCommandLineAction, &QAction::triggered,
|
||||
this, &LauncherMainWindow::onViewCommandLine);
|
||||
|
||||
#if QT_VERSION >= 0x050200
|
||||
m_ui->aircraftFilter->setClearButtonEnabled(true);
|
||||
#endif
|
||||
|
||||
for (int i=0; i<4; ++i) {
|
||||
m_ratingFilters[i] = 3;
|
||||
}
|
||||
m_serversModel = new MPServersModel(this);
|
||||
m_serversModel->refresh();
|
||||
|
||||
initQML();
|
||||
|
||||
m_subsystemIdleTimer = new QTimer(this);
|
||||
m_subsystemIdleTimer->setInterval(0);
|
||||
|
@ -134,9 +164,7 @@ LauncherMainWindow::LauncherMainWindow() :
|
|||
connect(m_ui->locationButton, &QAbstractButton::clicked, this, &LauncherMainWindow::onClickToolboxButton);
|
||||
connect(m_ui->environmentButton, &QAbstractButton::clicked, this, &LauncherMainWindow::onClickToolboxButton);
|
||||
connect(m_ui->settingsButton, &QAbstractButton::clicked, this, &LauncherMainWindow::onClickToolboxButton);
|
||||
|
||||
|
||||
// connect(m_ui->quitButton, SIGNAL(clicked()), this, SLOT(onQuit()));
|
||||
connect(m_ui->addOnsButton, &QAbstractButton::clicked, this, &LauncherMainWindow::onClickToolboxButton);
|
||||
|
||||
connect(m_ui->aircraftHistory, &QPushButton::clicked,
|
||||
this, &LauncherMainWindow::onPopupAircraftHistory);
|
||||
|
@ -160,39 +188,6 @@ LauncherMainWindow::LauncherMainWindow() :
|
|||
m_ui->aircraftHistory->setIcon(historyIcon);
|
||||
m_ui->locationHistory->setIcon(historyIcon);
|
||||
|
||||
#if 0
|
||||
connect(m_ui->timeOfDayCombo, SIGNAL(currentIndexChanged(int)),
|
||||
this, SLOT(updateSettingsSummary()));
|
||||
connect(m_ui->seasonCombo, SIGNAL(currentIndexChanged(int)),
|
||||
this, SLOT(updateSettingsSummary()));
|
||||
connect(m_ui->fetchRealWxrCheckbox, SIGNAL(toggled(bool)),
|
||||
this, SLOT(updateSettingsSummary()));
|
||||
connect(m_ui->rembrandtCheckbox, SIGNAL(toggled(bool)),
|
||||
this, SLOT(updateSettingsSummary()));
|
||||
connect(m_ui->terrasyncCheck, SIGNAL(toggled(bool)),
|
||||
this, SLOT(updateSettingsSummary()));
|
||||
connect(m_ui->startPausedCheck, SIGNAL(toggled(bool)),
|
||||
this, SLOT(updateSettingsSummary()));
|
||||
connect(m_ui->msaaCheckbox, SIGNAL(toggled(bool)),
|
||||
this, SLOT(updateSettingsSummary()));
|
||||
|
||||
connect(m_ui->mpBox, SIGNAL(toggled(bool)),
|
||||
this, SLOT(updateSettingsSummary()));
|
||||
connect(m_ui->mpCallsign, SIGNAL(textChanged(QString)),
|
||||
this, SLOT(updateSettingsSummary()));
|
||||
|
||||
connect(m_ui->rembrandtCheckbox, SIGNAL(toggled(bool)),
|
||||
this, SLOT(onRembrandtToggled(bool)));
|
||||
connect(m_ui->terrasyncCheck, &QCheckBox::toggled,
|
||||
this, &LauncherMainWindow::onToggleTerrasync);
|
||||
#endif
|
||||
|
||||
updateSettingsSummary();
|
||||
|
||||
#if 0
|
||||
connect(m_ui->mpServerCombo, SIGNAL(activated(int)),
|
||||
this, SLOT(onMPServerActivated(int)));
|
||||
#endif
|
||||
m_aircraftModel = new AircraftItemModel(this);
|
||||
m_aircraftProxy->setSourceModel(m_aircraftModel);
|
||||
|
||||
|
@ -216,6 +211,8 @@ LauncherMainWindow::LauncherMainWindow() :
|
|||
this, &LauncherMainWindow::onRequestPackageUninstall);
|
||||
connect(delegate, &AircraftItemDelegate::cancelDownload,
|
||||
this, &LauncherMainWindow::onCancelDownload);
|
||||
connect(delegate, &AircraftItemDelegate::showPreviews,
|
||||
this, &LauncherMainWindow::onShowPreviews);
|
||||
|
||||
connect(m_aircraftModel, &AircraftItemModel::aircraftInstallCompleted,
|
||||
this, &LauncherMainWindow::onAircraftInstalledCompleted);
|
||||
|
@ -223,18 +220,14 @@ LauncherMainWindow::LauncherMainWindow() :
|
|||
this, &LauncherMainWindow::onAircraftInstallFailed);
|
||||
connect(m_aircraftModel, &AircraftItemModel::scanCompleted,
|
||||
this, &LauncherMainWindow::updateSelectedAircraft);
|
||||
#if 0
|
||||
connect(m_ui->restoreDefaultsButton, &QPushButton::clicked,
|
||||
this, &LauncherMainWindow::onRestoreDefaults);
|
||||
#endif
|
||||
|
||||
AddOnsPage* addOnsPage = new AddOnsPage(NULL, globals->packageRoot());
|
||||
connect(addOnsPage, &AddOnsPage::downloadDirChanged,
|
||||
this, &LauncherMainWindow::onDownloadDirChanged);
|
||||
connect(addOnsPage, &AddOnsPage::sceneryPathsChanged,
|
||||
this, &LauncherMainWindow::setSceneryPaths);
|
||||
connect(addOnsPage, &AddOnsPage::aircraftPathsChanged,
|
||||
this, &LauncherMainWindow::onAircraftPathsChanged);
|
||||
m_ui->stack->addWidget(addOnsPage);
|
||||
|
||||
// m_ui->tabWidget->addTab(addOnsPage, tr("Add-ons"));
|
||||
// after any kind of reset, try to restore selection and scroll
|
||||
// to match the m_selectedAircraft. This needs to be delayed
|
||||
// fractionally otherwise the scrollTo seems to be ignored,
|
||||
|
@ -247,49 +240,120 @@ LauncherMainWindow::LauncherMainWindow() :
|
|||
m_aircraftModel->setPackageRoot(globals->packageRoot());
|
||||
m_aircraftModel->scanDirs();
|
||||
|
||||
buildSettingsSections();
|
||||
buildEnvironmentSections();
|
||||
|
||||
m_viewCommandLinePage = new ViewCommandLinePage;
|
||||
m_viewCommandLinePage->setLaunchConfig(m_config);
|
||||
m_ui->stack->addWidget(m_viewCommandLinePage);
|
||||
|
||||
checkOfficialCatalogMessage();
|
||||
restoreSettings();
|
||||
updateSettingsSummary();
|
||||
}
|
||||
|
||||
onRefreshMPServers();
|
||||
void LauncherMainWindow::initQML()
|
||||
{
|
||||
QQmlPrivate::RegisterAutoParent autoparent = { 0, &launcher_autoParent };
|
||||
QQmlPrivate::qmlregister(QQmlPrivate::AutoParentRegistration, &autoparent);
|
||||
|
||||
RenderingSettings* renderSettings = new RenderingSettings(m_ui->settingsScrollContents);
|
||||
qmlRegisterType<SettingsSectionQML>("FlightGear.Launcher", 1, 0, "Section");
|
||||
qmlRegisterType<SettingsCheckbox>("FlightGear.Launcher", 1, 0, "Checkbox");
|
||||
qmlRegisterType<SettingsComboBox>("FlightGear.Launcher", 1, 0, "Combo");
|
||||
qmlRegisterType<SettingsIntSpinbox>("FlightGear.Launcher", 1, 0, "Spinbox");
|
||||
qmlRegisterType<SettingsText>("FlightGear.Launcher", 1, 0, "LineEdit");
|
||||
qmlRegisterType<SettingsDateTime>("FlightGear.Launcher", 1, 0, "DateTime");
|
||||
qmlRegisterType<SettingsPath>("FlightGear.Launcher", 1, 0, "PathChooser");
|
||||
qmlRegisterUncreatableType<QAbstractItemModel>("FlightGear.Launcher", 1, 0, "QAIM", "no");
|
||||
|
||||
qmlRegisterUncreatableType<SettingsControl>("FlightGear.Launcher", 1, 0, "Control", "Base class");
|
||||
qmlRegisterUncreatableType<LaunchConfig>("FlightGear.Launcher", 1, 0, "LaunchConfig", "Singleton API");
|
||||
|
||||
m_config = new LaunchConfig(this);
|
||||
connect(m_config, &LaunchConfig::collect, this, &LauncherMainWindow::collectAircraftArgs);
|
||||
m_ui->location->setLaunchConfig(m_config);
|
||||
|
||||
m_qmlEngine = new QQmlEngine(this);
|
||||
m_qmlEngine->rootContext()->setContextProperty("_config", m_config);
|
||||
m_qmlEngine->rootContext()->setContextProperty("_launcher", this);
|
||||
m_qmlEngine->rootContext()->setContextProperty("_mpServers", m_serversModel);
|
||||
|
||||
flightgear::WeatherScenariosModel* weatherScenariosModel = new flightgear::WeatherScenariosModel(this);
|
||||
m_qmlEngine->rootContext()->setContextProperty("_weatherScenarios", weatherScenariosModel);
|
||||
}
|
||||
|
||||
void LauncherMainWindow::buildSettingsSections()
|
||||
{
|
||||
QVBoxLayout* settingsVBox = static_cast<QVBoxLayout*>(m_ui->settingsScrollContents->layout());
|
||||
settingsVBox->addWidget(renderSettings);
|
||||
|
||||
ViewSettings* viewSettings = new ViewSettings(m_ui->settingsScrollContents);
|
||||
settingsVBox->addWidget(viewSettings);
|
||||
QStringList sections = QStringList() << "general" << "mp" << "downloads" << "view" << "render";
|
||||
Q_FOREACH (QString section, sections) {
|
||||
QQmlComponent* comp = new QQmlComponent(m_qmlEngine, "qrc:/settings/" + section, this);
|
||||
if (comp->isError()) {
|
||||
qWarning() << "Errors parsing settings section:" << section << "\n" << comp->errorString();
|
||||
} else {
|
||||
SettingsSection* ss = qobject_cast<SettingsSection*>(comp->create());
|
||||
if (!ss) {
|
||||
qWarning() << "failed to create settings section from" << section;
|
||||
} else {
|
||||
ss->insertSettingsHeader();
|
||||
ss->setLaunchConfig(m_config);
|
||||
ss->setParent(m_ui->settingsScrollContents);
|
||||
settingsVBox->addWidget(ss);
|
||||
connect(ss, &SettingsSection::summaryChanged,
|
||||
this, &LauncherMainWindow::updateSettingsSummary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MPSettings* mpSettings = new MPSettings(m_ui->settingsScrollContents);
|
||||
settingsVBox->addWidget(mpSettings);
|
||||
m_extraSettings = new ExtraSettingsSection(m_ui->settingsScrollContents);
|
||||
m_extraSettings->setLaunchConfig(m_config);
|
||||
settingsVBox->addWidget(m_extraSettings);
|
||||
settingsVBox->addStretch(1);
|
||||
|
||||
DownloadSettings* downloadSettings = new DownloadSettings(m_ui->settingsScrollContents);
|
||||
settingsVBox->addWidget(downloadSettings);
|
||||
// disable search for the moment, not implemented
|
||||
m_ui->settingsSearchEdit->hide();
|
||||
}
|
||||
|
||||
AdditionalSettings* addSettings = new AdditionalSettings(m_ui->settingsScrollContents);
|
||||
settingsVBox->addWidget(addSettings);
|
||||
void LauncherMainWindow::buildEnvironmentSections()
|
||||
{
|
||||
QVBoxLayout* settingsVBox = new QVBoxLayout;
|
||||
m_ui->environmentScrollContents->setLayout(settingsVBox);
|
||||
|
||||
QStringList sections = QStringList() << "time" << "weather";
|
||||
Q_FOREACH (QString section, sections) {
|
||||
QQmlComponent* comp = new QQmlComponent(m_qmlEngine, "qrc:/environment/" + section, this);
|
||||
if (comp->isError()) {
|
||||
qWarning() << "Errors parsing environment section:" << section << "\n" << comp->errorString();
|
||||
} else {
|
||||
SettingsSection* ss = qobject_cast<SettingsSection*>(comp->create());
|
||||
if (!ss) {
|
||||
qWarning() << "failed to create environment section from" << section;
|
||||
} else {
|
||||
ss->insertSettingsHeader();
|
||||
ss->setLaunchConfig(m_config);
|
||||
ss->setParent(m_ui->environmentScrollContents);
|
||||
settingsVBox->addWidget(ss);
|
||||
connect(ss, &SettingsSection::summaryChanged,
|
||||
this, &LauncherMainWindow::updateSettingsSummary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
settingsVBox->addStretch(1);
|
||||
}
|
||||
|
||||
LauncherMainWindow::~LauncherMainWindow()
|
||||
{
|
||||
// if we don't cancel this now, it may complete after we are gone,
|
||||
// causing a crash when the SGCallback fires (SGCallbacks don't clean up
|
||||
// when their subject is deleted)
|
||||
globals->get_subsystem<FGHTTPClient>()->client()->cancelRequest(m_mpServerRequest);
|
||||
}
|
||||
|
||||
bool LauncherMainWindow::execInApp()
|
||||
{
|
||||
m_inAppMode = true;
|
||||
// m_ui->tabWidget->removeTab(3);
|
||||
// m_ui->tabWidget->removeTab(3);
|
||||
|
||||
// m_ui->runButton->setText(tr("Apply"));
|
||||
// m_ui->quitButton->setText(tr("Cancel"));
|
||||
|
||||
disconnect(m_ui->flyButton, SIGNAL(clicked()), this, SLOT(onRun()));
|
||||
connect(m_ui->flyButton, SIGNAL(clicked()), this, SLOT(onApply()));
|
||||
m_inAppMode = true;
|
||||
m_ui->addOnsButton->hide();
|
||||
m_ui->settingsButton->hide();
|
||||
disconnect(m_ui->flyButton, SIGNAL(clicked()), this, SLOT(onRun()));
|
||||
connect(m_ui->flyButton, SIGNAL(clicked()), this, SLOT(onApply()));
|
||||
m_runInApp = true;
|
||||
|
||||
show();
|
||||
|
@ -307,16 +371,6 @@ void LauncherMainWindow::restoreSettings()
|
|||
|
||||
restoreGeometry(settings.value("window-geometry").toByteArray());
|
||||
|
||||
#if 0
|
||||
m_ui->rembrandtCheckbox->setChecked(settings.value("enable-rembrandt", false).toBool());
|
||||
m_ui->terrasyncCheck->setChecked(settings.value("enable-terrasync", true).toBool());
|
||||
m_ui->fullScreenCheckbox->setChecked(settings.value("start-fullscreen", false).toBool());
|
||||
m_ui->msaaCheckbox->setChecked(settings.value("enable-msaa", false).toBool());
|
||||
m_ui->fetchRealWxrCheckbox->setChecked(settings.value("enable-realwx", true).toBool());
|
||||
m_ui->startPausedCheck->setChecked(settings.value("start-paused", false).toBool());
|
||||
m_ui->timeOfDayCombo->setCurrentIndex(settings.value("timeofday", 0).toInt());
|
||||
m_ui->seasonCombo->setCurrentIndex(settings.value("season", 0).toInt());
|
||||
#endif
|
||||
// full paths to -set.xml files
|
||||
m_recentAircraft = QUrl::fromStringList(settings.value("recent-aircraft").toStringList());
|
||||
|
||||
|
@ -373,15 +427,13 @@ void LauncherMainWindow::restoreSettings()
|
|||
|
||||
updateSelectedAircraft();
|
||||
maybeRestoreAircraftSelection();
|
||||
#if 0
|
||||
m_ui->commandLineArgs->setPlainText(settings.value("additional-args").toString());
|
||||
|
||||
m_ui->mpBox->setChecked(settings.value("mp-enabled").toBool());
|
||||
m_ui->mpCallsign->setText(settings.value("mp-callsign").toString());
|
||||
#endif
|
||||
// don't restore MP server here, we do it after a refresh
|
||||
m_doRestoreMPServer = true;
|
||||
}
|
||||
Q_FOREACH(SettingsSection* ss, findChildren<SettingsSection*>()) {
|
||||
ss->restoreState(settings);
|
||||
}
|
||||
|
||||
m_serversModel->requestRestore();
|
||||
}
|
||||
|
||||
void LauncherMainWindow::delayedAircraftModelReset()
|
||||
{
|
||||
|
@ -407,40 +459,16 @@ void LauncherMainWindow::maybeRestoreAircraftSelection()
|
|||
void LauncherMainWindow::saveSettings()
|
||||
{
|
||||
QSettings settings;
|
||||
#if 0
|
||||
settings.setValue("enable-rembrandt", m_ui->rembrandtCheckbox->isChecked());
|
||||
settings.setValue("enable-terrasync", m_ui->terrasyncCheck->isChecked());
|
||||
settings.setValue("enable-msaa", m_ui->msaaCheckbox->isChecked());
|
||||
settings.setValue("start-fullscreen", m_ui->fullScreenCheckbox->isChecked());
|
||||
settings.setValue("enable-realwx", m_ui->fetchRealWxrCheckbox->isChecked());
|
||||
settings.setValue("start-paused", m_ui->startPausedCheck->isChecked());
|
||||
#endif
|
||||
|
||||
settings.setValue("ratings-filter", m_ui->ratingsFilterCheck->isChecked());
|
||||
settings.setValue("only-show-installed", m_ui->onlyShowInstalledCheck->isChecked());
|
||||
settings.setValue("recent-aircraft", QUrl::toStringList(m_recentAircraft));
|
||||
settings.setValue("recent-location-sets", m_recentLocations);
|
||||
|
||||
#if 0
|
||||
settings.setValue("timeofday", m_ui->timeOfDayCombo->currentIndex());
|
||||
settings.setValue("season", m_ui->seasonCombo->currentIndex());
|
||||
settings.setValue("additional-args", m_ui->commandLineArgs->toPlainText());
|
||||
|
||||
settings.setValue("mp-callsign", m_ui->mpCallsign->text());
|
||||
settings.setValue("mp-server", m_ui->mpServerCombo->currentData());
|
||||
settings.setValue("mp-enabled", m_ui->mpBox->isChecked());
|
||||
#endif
|
||||
settings.setValue("window-geometry", saveGeometry());
|
||||
}
|
||||
|
||||
void LauncherMainWindow::setEnableDisableOptionFromCheckbox(QCheckBox* cbox, QString name) const
|
||||
{
|
||||
flightgear::Options* opt = flightgear::Options::sharedInstance();
|
||||
std::string stdName(name.toStdString());
|
||||
if (cbox->isChecked()) {
|
||||
opt->addOption("enable-" + stdName, "");
|
||||
} else {
|
||||
opt->addOption("disable-" + stdName, "");
|
||||
Q_FOREACH(SettingsSection* ss, findChildren<SettingsSection*>()) {
|
||||
ss->saveState(settings);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -449,53 +477,35 @@ void LauncherMainWindow::closeEvent(QCloseEvent *event)
|
|||
qApp->exit(-1);
|
||||
}
|
||||
|
||||
void LauncherMainWindow::onRun()
|
||||
void LauncherMainWindow::collectAircraftArgs()
|
||||
{
|
||||
flightgear::Options* opt = flightgear::Options::sharedInstance();
|
||||
#if 0
|
||||
setEnableDisableOptionFromCheckbox(m_ui->terrasyncCheck, "terrasync");
|
||||
setEnableDisableOptionFromCheckbox(m_ui->fetchRealWxrCheckbox, "real-weather-fetch");
|
||||
setEnableDisableOptionFromCheckbox(m_ui->rembrandtCheckbox, "rembrandt");
|
||||
setEnableDisableOptionFromCheckbox(m_ui->fullScreenCheckbox, "fullscreen");
|
||||
// setEnableDisableOptionFromCheckbox(m_ui->startPausedCheck, "freeze");
|
||||
|
||||
bool startPaused = m_ui->startPausedCheck->isChecked() ||
|
||||
m_ui->location->shouldStartPaused();
|
||||
if (startPaused) {
|
||||
opt->addOption("enable-freeze", "");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
// MSAA is more complex
|
||||
if (!m_ui->rembrandtCheckbox->isChecked()) {
|
||||
if (m_ui->msaaCheckbox->isChecked()) {
|
||||
globals->get_props()->setIntValue("/sim/rendering/multi-sample-buffers", 1);
|
||||
globals->get_props()->setIntValue("/sim/rendering/multi-samples", 4);
|
||||
} else {
|
||||
globals->get_props()->setIntValue("/sim/rendering/multi-sample-buffers", 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// aircraft
|
||||
if (!m_selectedAircraft.isEmpty()) {
|
||||
if (m_selectedAircraft.isLocalFile()) {
|
||||
QFileInfo setFileInfo(m_selectedAircraft.toLocalFile());
|
||||
opt->addOption("aircraft-dir", setFileInfo.dir().absolutePath().toStdString());
|
||||
m_config->setArg("aircraft-dir", setFileInfo.dir().absolutePath());
|
||||
QString setFile = setFileInfo.fileName();
|
||||
Q_ASSERT(setFile.endsWith("-set.xml"));
|
||||
setFile.truncate(setFile.count() - 8); // drop the '-set.xml' portion
|
||||
opt->addOption("aircraft", setFile.toStdString());
|
||||
m_config->setArg("aircraft", setFile);
|
||||
} else if (m_selectedAircraft.scheme() == "package") {
|
||||
QString qualifiedId = m_selectedAircraft.path();
|
||||
// no need to set aircraft-dir, handled by the corresponding code
|
||||
// in fgInitAircraft
|
||||
opt->addOption("aircraft", qualifiedId.toStdString());
|
||||
m_config->setArg("aircraft", m_selectedAircraft.path());
|
||||
} else {
|
||||
qWarning() << "unsupported aircraft launch URL" << m_selectedAircraft;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LauncherMainWindow::onRun()
|
||||
{
|
||||
flightgear::Options* opt = flightgear::Options::sharedInstance();
|
||||
m_config->reset();
|
||||
m_config->collect();
|
||||
|
||||
// aircraft
|
||||
if (!m_selectedAircraft.isEmpty()) {
|
||||
// manage aircraft history
|
||||
if (m_recentAircraft.contains(m_selectedAircraft))
|
||||
m_recentAircraft.removeOne(m_selectedAircraft);
|
||||
|
@ -504,46 +514,9 @@ void LauncherMainWindow::onRun()
|
|||
m_recentAircraft.pop_back();
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (m_ui->mpBox->isChecked()) {
|
||||
std::string callSign = m_ui->mpCallsign->text().toStdString();
|
||||
if (!callSign.empty()) {
|
||||
opt->addOption("callsign", callSign);
|
||||
}
|
||||
|
||||
QString host = m_ui->mpServerCombo->currentData().toString();
|
||||
int port = DEFAULT_MP_PORT;
|
||||
if (host == "custom") {
|
||||
QSettings settings;
|
||||
host = settings.value("mp-custom-host").toString();
|
||||
} else {
|
||||
port = findMPServerPort(host.toStdString());
|
||||
}
|
||||
|
||||
if (port == 0) {
|
||||
port = DEFAULT_MP_PORT;
|
||||
}
|
||||
globals->get_props()->setStringValue("/sim/multiplay/txhost", host.toStdString());
|
||||
globals->get_props()->setIntValue("/sim/multiplay/txport", port);
|
||||
}
|
||||
#endif
|
||||
|
||||
m_ui->location->setLocationProperties();
|
||||
// m_ui->location->setLocationProperties();
|
||||
updateLocationHistory();
|
||||
|
||||
#if 0
|
||||
// time of day
|
||||
if (m_ui->timeOfDayCombo->currentIndex() != 0) {
|
||||
QString dayval = m_ui->timeOfDayCombo->currentText().toLower();
|
||||
opt->addOption("timeofday", dayval.toStdString());
|
||||
}
|
||||
|
||||
if (m_ui->seasonCombo->currentIndex() != 0) {
|
||||
QString seasonName = m_ui->seasonCombo->currentText().toLower();
|
||||
opt->addOption("season", seasonName.toStdString());
|
||||
}
|
||||
#endif
|
||||
|
||||
QSettings settings;
|
||||
QString downloadDir = settings.value("download-dir").toString();
|
||||
if (!downloadDir.isEmpty()) {
|
||||
|
@ -560,8 +533,6 @@ void LauncherMainWindow::onRun()
|
|||
d.mkpath(downloadDir);
|
||||
}
|
||||
}
|
||||
|
||||
opt->addOption("download-dir", downloadDir.toStdString());
|
||||
}
|
||||
|
||||
// scenery paths
|
||||
|
@ -575,24 +546,12 @@ void LauncherMainWindow::onRun()
|
|||
globals->append_aircraft_path(path.toStdString());
|
||||
}
|
||||
|
||||
// additional arguments
|
||||
#if 0
|
||||
ArgumentsTokenizer tk;
|
||||
Q_FOREACH(ArgumentsTokenizer::Arg a, tk.tokenize(m_ui->commandLineArgs->toPlainText())) {
|
||||
if (a.arg.startsWith("prop:")) {
|
||||
QString v = a.arg.mid(5) + "=" + a.value;
|
||||
opt->addOption("prop", v.toStdString());
|
||||
} else {
|
||||
opt->addOption(a.arg.toStdString(), a.value.toStdString());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (settings.contains("restore-defaults-on-run")) {
|
||||
settings.remove("restore-defaults-on-run");
|
||||
opt->addOption("restore-defaults", "");
|
||||
}
|
||||
|
||||
m_config->applyToOptions();
|
||||
saveSettings();
|
||||
|
||||
// set a positive value here so we can detect this case in runLauncherDialog
|
||||
|
@ -667,6 +626,7 @@ void LauncherMainWindow::onQuit()
|
|||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
void LauncherMainWindow::onToggleTerrasync(bool enabled)
|
||||
{
|
||||
if (enabled) {
|
||||
|
@ -695,6 +655,7 @@ void LauncherMainWindow::onToggleTerrasync(bool enabled)
|
|||
}
|
||||
} // of is enabled
|
||||
}
|
||||
#endif
|
||||
|
||||
void LauncherMainWindow::onAircraftInstalledCompleted(QModelIndex index)
|
||||
{
|
||||
|
@ -766,6 +727,14 @@ void LauncherMainWindow::onRequestPackageUninstall(const QModelIndex& index)
|
|||
}
|
||||
}
|
||||
|
||||
void LauncherMainWindow::onShowPreviews(const QModelIndex &index)
|
||||
{
|
||||
QVariant urls = index.data(AircraftPreviewsRole);
|
||||
|
||||
PreviewWindow* previewWindow = new PreviewWindow;
|
||||
previewWindow->setUrls(urls.toList());
|
||||
}
|
||||
|
||||
void LauncherMainWindow::onCancelDownload(const QModelIndex& index)
|
||||
{
|
||||
QString pkg = index.data(AircraftPackageIdRole).toString();
|
||||
|
@ -798,6 +767,15 @@ void LauncherMainWindow::onRestoreDefaults()
|
|||
flightgear::restartTheApp();
|
||||
}
|
||||
|
||||
void LauncherMainWindow::onViewCommandLine()
|
||||
{
|
||||
m_ui->stack->setCurrentIndex(6);
|
||||
Q_FOREACH (ToolboxButton* tb, findChildren<ToolboxButton*>()) {
|
||||
tb->setChecked(false);
|
||||
}
|
||||
m_viewCommandLinePage->update();
|
||||
}
|
||||
|
||||
void LauncherMainWindow::maybeUpdateSelectedAircraft(QModelIndex index)
|
||||
{
|
||||
QUrl u = index.data(AircraftURIRole).toUrl();
|
||||
|
@ -860,6 +838,7 @@ void LauncherMainWindow::onClickToolboxButton()
|
|||
Q_FOREACH (ToolboxButton* tb, findChildren<ToolboxButton*>()) {
|
||||
tb->setChecked(tb->property("pageIndex").toInt() == pageIndex);
|
||||
}
|
||||
saveSettings();
|
||||
}
|
||||
|
||||
void LauncherMainWindow::setSceneryPaths()
|
||||
|
@ -952,47 +931,18 @@ void LauncherMainWindow::onEditRatingsFilter()
|
|||
void LauncherMainWindow::updateSettingsSummary()
|
||||
{
|
||||
QStringList summary;
|
||||
#if 0
|
||||
if (m_ui->timeOfDayCombo->currentIndex() > 0) {
|
||||
summary.append(QString(m_ui->timeOfDayCombo->currentText().toLower()));
|
||||
}
|
||||
|
||||
if (m_ui->seasonCombo->currentIndex() > 0) {
|
||||
summary.append(QString(m_ui->seasonCombo->currentText().toLower()));
|
||||
}
|
||||
|
||||
if (m_ui->rembrandtCheckbox->isChecked()) {
|
||||
summary.append("Rembrandt enabled");
|
||||
} else if (m_ui->msaaCheckbox->isChecked()) {
|
||||
summary.append("anti-aliasing");
|
||||
}
|
||||
|
||||
if (m_ui->fetchRealWxrCheckbox->isChecked()) {
|
||||
summary.append("live weather");
|
||||
}
|
||||
|
||||
if (m_ui->terrasyncCheck->isChecked()) {
|
||||
summary.append("automatic scenery downloads");
|
||||
}
|
||||
|
||||
if (m_ui->startPausedCheck->isChecked()) {
|
||||
summary.append("paused");
|
||||
}
|
||||
|
||||
if (m_ui->mpBox->isChecked()) {
|
||||
summary.append(tr("multiplayer: %1").arg(m_ui->mpCallsign->text()));
|
||||
Q_FOREACH(SettingsSection* ss, findChildren<SettingsSection*>()) {
|
||||
QString s = ss->summary();
|
||||
if (!s.isEmpty()) {
|
||||
QStringList pieces = s.split(';', QString::SkipEmptyParts);
|
||||
summary.append(pieces);
|
||||
}
|
||||
}
|
||||
|
||||
QString s = summary.join(", ");
|
||||
s[0] = s[0].toUpper();
|
||||
m_ui->settingsDescription->setText(s);
|
||||
#endif
|
||||
}
|
||||
|
||||
void LauncherMainWindow::onRembrandtToggled(bool b)
|
||||
{
|
||||
// Rembrandt and multi-sample are exclusive
|
||||
// m_ui->msaaCheckbox->setEnabled(!b);
|
||||
}
|
||||
|
||||
void LauncherMainWindow::onShowInstalledAircraftToggled(bool b)
|
||||
|
@ -1060,7 +1010,7 @@ void LauncherMainWindow::onOfficialCatalogMessageLink(QUrl link)
|
|||
QSettings settings;
|
||||
settings.setValue("hide-official-catalog-message", true);
|
||||
} else if (s == "action:add-official") {
|
||||
AddOnsPage::addDefaultCatalog(this);
|
||||
AddOnsPage::addDefaultCatalog(this, false /* not silent */);
|
||||
}
|
||||
|
||||
checkOfficialCatalogMessage();
|
||||
|
@ -1084,110 +1034,6 @@ void LauncherMainWindow::checkUpdateAircraft()
|
|||
}
|
||||
}
|
||||
|
||||
void LauncherMainWindow::onRefreshMPServers()
|
||||
{
|
||||
if (m_mpServerRequest.get()) {
|
||||
return; // in-progress
|
||||
}
|
||||
|
||||
string url(fgGetString("/sim/multiplay/serverlist-url",
|
||||
"http://liveries.flightgear.org/mpstatus/mpservers.xml"));
|
||||
|
||||
if (url.empty()) {
|
||||
SG_LOG(SG_IO, SG_ALERT, "do_multiplayer.refreshserverlist: no URL given");
|
||||
return;
|
||||
}
|
||||
|
||||
SGPropertyNode *targetnode = fgGetNode("/sim/multiplay/server-list", true);
|
||||
m_mpServerRequest.reset(new RemoteXMLRequest(url, targetnode));
|
||||
m_mpServerRequest->done(this, &LauncherMainWindow::onRefreshMPServersDone);
|
||||
m_mpServerRequest->fail(this, &LauncherMainWindow::onRefreshMPServersFailed);
|
||||
globals->get_subsystem<FGHTTPClient>()->makeRequest(m_mpServerRequest);
|
||||
}
|
||||
|
||||
void LauncherMainWindow::onRefreshMPServersDone(simgear::HTTP::Request*)
|
||||
{
|
||||
#if 0
|
||||
// parse the properties
|
||||
SGPropertyNode *targetnode = fgGetNode("/sim/multiplay/server-list", true);
|
||||
m_ui->mpServerCombo->clear();
|
||||
|
||||
for (int i=0; i<targetnode->nChildren(); ++i) {
|
||||
SGPropertyNode* c = targetnode->getChild(i);
|
||||
if (c->getName() != std::string("server")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c->getBoolValue("online") != true) {
|
||||
// only list online servers
|
||||
continue;
|
||||
}
|
||||
|
||||
QString name = QString::fromStdString(c->getStringValue("name"));
|
||||
QString loc = QString::fromStdString(c->getStringValue("location"));
|
||||
QString host = QString::fromStdString(c->getStringValue("hostname"));
|
||||
m_ui->mpServerCombo->addItem(tr("%1 - %2").arg(name,loc), host);
|
||||
}
|
||||
|
||||
EditCustomMPServerDialog::addCustomItem(m_ui->mpServerCombo);
|
||||
restoreMPServerSelection();
|
||||
#endif
|
||||
m_mpServerRequest.clear();
|
||||
}
|
||||
|
||||
void LauncherMainWindow::onRefreshMPServersFailed(simgear::HTTP::Request*)
|
||||
{
|
||||
qWarning() << "refreshing MP servers failed:" << QString::fromStdString(m_mpServerRequest->responseReason());
|
||||
m_mpServerRequest.clear();
|
||||
#if 0
|
||||
EditCustomMPServerDialog::addCustomItem(m_ui->mpServerCombo);
|
||||
restoreMPServerSelection();
|
||||
#endif
|
||||
}
|
||||
|
||||
void LauncherMainWindow::restoreMPServerSelection()
|
||||
{
|
||||
#if 0
|
||||
if (m_doRestoreMPServer) {
|
||||
QSettings settings;
|
||||
int index = m_ui->mpServerCombo->findData(settings.value("mp-server"));
|
||||
if (index >= 0) {
|
||||
m_ui->mpServerCombo->setCurrentIndex(index);
|
||||
}
|
||||
m_doRestoreMPServer = false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void LauncherMainWindow::onMPServerActivated(int index)
|
||||
{
|
||||
#if 0
|
||||
if (m_ui->mpServerCombo->itemData(index) == "custom") {
|
||||
EditCustomMPServerDialog dlg(this);
|
||||
dlg.exec();
|
||||
if (dlg.result() == QDialog::Accepted) {
|
||||
m_ui->mpServerCombo->setItemText(index, tr("Custom - %1").arg(dlg.hostname()));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int LauncherMainWindow::findMPServerPort(const std::string& host)
|
||||
{
|
||||
SGPropertyNode *targetnode = fgGetNode("/sim/multiplay/server-list", true);
|
||||
for (int i=0; i<targetnode->nChildren(); ++i) {
|
||||
SGPropertyNode* c = targetnode->getChild(i);
|
||||
if (c->getName() != std::string("server")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c->getStringValue("hostname") == host) {
|
||||
return c->getIntValue("port");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
simgear::pkg::PackageRef LauncherMainWindow::packageForAircraftURI(QUrl uri) const
|
||||
{
|
||||
|
@ -1206,3 +1052,40 @@ void LauncherMainWindow::onAircraftPathsChanged()
|
|||
m_aircraftModel->setPaths(settings.value("aircraft-paths").toStringList());
|
||||
m_aircraftModel->scanDirs();
|
||||
}
|
||||
|
||||
void LauncherMainWindow::onChangeDataDir()
|
||||
{
|
||||
QString currentLocText;
|
||||
QSettings settings;
|
||||
QString root = settings.value("fg-root").toString();
|
||||
if (root.isNull()) {
|
||||
currentLocText = tr("Currently the built-in data files are being used");
|
||||
} else {
|
||||
currentLocText = tr("Currently using location: %1").arg(root);
|
||||
}
|
||||
|
||||
QMessageBox mbox(this);
|
||||
mbox.setText(tr("Change the data files used by FlightGear?"));
|
||||
mbox.setInformativeText(tr("FlightGear requires additional files to operate. "
|
||||
"(Also called the base package, or fg-data) "
|
||||
"You can restart FlightGear and choose a "
|
||||
"different data files location, or restore the default setting. %1").arg(currentLocText));
|
||||
QPushButton* quitButton = mbox.addButton(tr("Restart FlightGear now"), QMessageBox::YesRole);
|
||||
mbox.addButton(QMessageBox::Cancel);
|
||||
mbox.setDefaultButton(QMessageBox::Cancel);
|
||||
mbox.setIconPixmap(QPixmap(":/app-icon-large"));
|
||||
|
||||
mbox.exec();
|
||||
if (mbox.clickedButton() != quitButton) {
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
QSettings settings;
|
||||
// set the option to the magic marker value
|
||||
settings.setValue("fg-root", "!ask");
|
||||
} // scope the ensure settings are written nicely
|
||||
|
||||
flightgear::restartTheApp();
|
||||
}
|
||||
|
|
@ -41,7 +41,11 @@ class AircraftProxyModel;
|
|||
class AircraftItemModel;
|
||||
class QCheckBox;
|
||||
class CatalogListModel;
|
||||
class RemoteXMLRequest;
|
||||
class QQmlEngine;
|
||||
class LaunchConfig;
|
||||
class ExtraSettingsSection;
|
||||
class ViewCommandLinePage;
|
||||
class MPServersModel;
|
||||
|
||||
class LauncherMainWindow : public QMainWindow
|
||||
{
|
||||
|
@ -67,7 +71,6 @@ private slots:
|
|||
|
||||
void onQuit();
|
||||
|
||||
|
||||
void onAircraftSelected(const QModelIndex& index);
|
||||
void onRequestPackageInstall(const QModelIndex& index);
|
||||
void onRequestPackageUninstall(const QModelIndex& index);
|
||||
|
@ -81,10 +84,6 @@ private slots:
|
|||
|
||||
void updateSettingsSummary();
|
||||
|
||||
|
||||
void onRembrandtToggled(bool b);
|
||||
void onToggleTerrasync(bool enabled);
|
||||
|
||||
void onSubsytemIdleTimeout();
|
||||
|
||||
void onAircraftInstalledCompleted(QModelIndex index);
|
||||
|
@ -95,11 +94,9 @@ private slots:
|
|||
void maybeRestoreAircraftSelection();
|
||||
|
||||
void onRestoreDefaults();
|
||||
void onViewCommandLine();
|
||||
|
||||
void onDownloadDirChanged();
|
||||
|
||||
void onRefreshMPServers();
|
||||
void onMPServerActivated(int index);
|
||||
Q_INVOKABLE void onDownloadDirChanged();
|
||||
|
||||
void onUpdateAllAircraft();
|
||||
|
||||
|
@ -109,6 +106,8 @@ private slots:
|
|||
|
||||
void setSceneryPaths();
|
||||
void onAircraftPathsChanged();
|
||||
|
||||
void onChangeDataDir();
|
||||
private:
|
||||
|
||||
/**
|
||||
|
@ -124,20 +123,12 @@ private:
|
|||
QModelIndex proxyIndexForAircraftURI(QUrl uri) const;
|
||||
QModelIndex sourceIndexForAircraftURI(QUrl uri) const;
|
||||
|
||||
void setEnableDisableOptionFromCheckbox(QCheckBox* cbox, QString name) const;
|
||||
|
||||
simgear::pkg::PackageRef packageForAircraftURI(QUrl uri) const;
|
||||
|
||||
void checkOfficialCatalogMessage();
|
||||
void onOfficialCatalogMessageLink(QUrl link);
|
||||
|
||||
void checkUpdateAircraft();
|
||||
|
||||
void onRefreshMPServersDone(simgear::HTTP::Request*);
|
||||
void onRefreshMPServersFailed(simgear::HTTP::Request*);
|
||||
int findMPServerPort(const std::string& host);
|
||||
void restoreMPServerSelection();
|
||||
|
||||
// need to wait after a model reset before restoring selection and
|
||||
// scrolling, to give the view time it seems.
|
||||
void delayedAircraftModelReset();
|
||||
|
@ -146,9 +137,15 @@ private:
|
|||
void updateLocationHistory();
|
||||
bool shouldShowOfficialCatalogMessage() const;
|
||||
|
||||
void buildSettingsSections();
|
||||
void buildEnvironmentSections();
|
||||
void collectAircraftArgs();
|
||||
void initQML();
|
||||
|
||||
QScopedPointer<Ui::Launcher> m_ui;
|
||||
AircraftProxyModel* m_aircraftProxy;
|
||||
AircraftItemModel* m_aircraftModel;
|
||||
MPServersModel* m_serversModel = nullptr;
|
||||
|
||||
QUrl m_selectedAircraft;
|
||||
QList<QUrl> m_recentAircraft;
|
||||
|
@ -156,13 +153,12 @@ private:
|
|||
bool m_inAppMode = false;
|
||||
bool m_runInApp = false;
|
||||
bool m_accepted = false;
|
||||
|
||||
int m_ratingFilters[4];
|
||||
|
||||
SGSharedPtr<RemoteXMLRequest> m_mpServerRequest;
|
||||
bool m_doRestoreMPServer;
|
||||
|
||||
int m_ratingFilters[4] = {3, 3, 3, 3};
|
||||
QVariantList m_recentLocations;
|
||||
QQmlEngine* m_qmlEngine = nullptr;
|
||||
LaunchConfig* m_config = nullptr;
|
||||
ExtraSettingsSection* m_extraSettings = nullptr;
|
||||
ViewCommandLinePage* m_viewCommandLinePage = nullptr;
|
||||
};
|
||||
|
||||
#endif // of LAUNCHER_MAIN_WINDOW_HXX
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
#include "AirportDiagram.hxx"
|
||||
#include "NavaidDiagram.hxx"
|
||||
#include "LaunchConfig.hxx"
|
||||
|
||||
#include <Airports/airport.hxx>
|
||||
#include <Airports/groundnetwork.hxx>
|
||||
|
@ -423,6 +424,12 @@ LocationWidget::~LocationWidget()
|
|||
delete m_ui;
|
||||
}
|
||||
|
||||
void LocationWidget::setLaunchConfig(LaunchConfig *config)
|
||||
{
|
||||
m_config = config;
|
||||
connect(m_config, &LaunchConfig::collect, this, &LocationWidget::onCollectConfig);
|
||||
}
|
||||
|
||||
void LocationWidget::restoreSettings()
|
||||
{
|
||||
QSettings settings;
|
||||
|
@ -489,8 +496,6 @@ bool LocationWidget::shouldStartPaused() const
|
|||
// navaid, start paused
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QVariantMap LocationWidget::saveLocation() const
|
||||
|
@ -646,42 +651,120 @@ void LocationWidget::setLocationProperties()
|
|||
|
||||
void LocationWidget::applyPositionOffset()
|
||||
{
|
||||
fgSetDouble("/sim/presets/altitude-ft", m_ui->altitudeSpinbox->value());
|
||||
fgSetBool("/sim/presets/on-ground", m_ui->altitudeSpinbox->value() > 0);
|
||||
if (m_ui->altitudeSpinbox->value() > 0) {
|
||||
m_config->setArg("altitude", QString::number(m_ui->altitudeSpinbox->value()));
|
||||
}
|
||||
|
||||
fgSetString("/sim/presets/speed-set", "knots");
|
||||
fgSetDouble("/sim/presets/airspeed-kt", m_ui->airspeedSpinbox->value());
|
||||
|
||||
fgSetDouble("/sim/presets/heading-deg", m_ui->headingSpinbox->value());
|
||||
m_config->setArg("vc", QString::number(m_ui->airspeedSpinbox->value()));
|
||||
m_config->setArg("heading", QString::number(m_ui->headingSpinbox->value()));
|
||||
|
||||
if (m_ui->offsetGroup->isChecked()) {
|
||||
// flip direction of azimuth to balance the flip done in fgApplyStartOffset
|
||||
// I don't know why that flip exists but changing it there will break
|
||||
// command-line compatability so compensating here instead
|
||||
int offsetAzimuth = m_ui->offsetBearingSpinbox->value() - 180;
|
||||
|
||||
fgSetDouble("/sim/presets/offset-azimuth-deg", offsetAzimuth);
|
||||
fgSetDouble("/sim/presets/offset-distance-nm", m_ui->offsetNmSpinbox->value());
|
||||
m_config->setArg("offset-azimuth", QString::number(offsetAzimuth));
|
||||
m_config->setArg("offset-distance", QString::number(m_ui->offsetNmSpinbox->value()));
|
||||
}
|
||||
}
|
||||
|
||||
void LocationWidget::onCollectConfig()
|
||||
{
|
||||
if (m_locationIsLatLon) {
|
||||
m_config->setArg("lat", QString::number(m_geodLocation.getLatitudeDeg()));
|
||||
m_config->setArg("lon", QString::number(m_geodLocation.getLongitudeDeg()));
|
||||
applyPositionOffset();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_location) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (FGAirport::isAirportType(m_location.ptr())) {
|
||||
FGAirport* apt = static_cast<FGAirport*>(m_location.ptr());
|
||||
m_config->setArg("airport", QString::fromStdString(apt->ident()));
|
||||
|
||||
if (m_ui->runwayRadio->isChecked()) {
|
||||
if (apt->type() == FGPositioned::AIRPORT) {
|
||||
int index = m_ui->runwayCombo->itemData(m_ui->runwayCombo->currentIndex()).toInt();
|
||||
if (index >= 0) {
|
||||
// explicit runway choice
|
||||
FGRunwayRef runway = apt->getRunwayByIndex(index);
|
||||
m_config->setArg("runway", QString::fromStdString(runway->ident()));
|
||||
|
||||
// set nav-radio 1 based on selected runway
|
||||
if (runway->ILS()) {
|
||||
double mhz = runway->ILS()->get_freq() / 100.0;
|
||||
m_config->setArg("nav1", QString("%1:%2").arg(runway->headingDeg()).arg(mhz));
|
||||
}
|
||||
}
|
||||
|
||||
if (m_ui->onFinalCheckbox->isChecked()) {
|
||||
m_config->setArg("glideslope", std::string("3.0"));
|
||||
m_config->setArg("offset-distance", QString::number(m_ui->approachDistanceSpin->value()));
|
||||
m_config->setArg("on-ground", std::string("false"));
|
||||
}
|
||||
} else if (apt->type() == FGPositioned::HELIPORT) {
|
||||
int index = m_ui->runwayCombo->itemData(m_ui->runwayCombo->currentIndex()).toInt();
|
||||
if (index >= 0) {
|
||||
// explicit pad choice
|
||||
FGHelipadRef pad = apt->getHelipadByIndex(index);
|
||||
m_config->setArg("runway", pad->ident());
|
||||
}
|
||||
} else {
|
||||
qWarning() << Q_FUNC_INFO << "implement me";
|
||||
}
|
||||
|
||||
} else if (m_ui->parkingRadio->isChecked()) {
|
||||
// parking selection
|
||||
m_config->setArg("parkpos", m_ui->parkingCombo->currentText());
|
||||
}
|
||||
// of location is an airport
|
||||
} else {
|
||||
// location is a navaid
|
||||
// note setting the ident here is ambigious, we really only need and
|
||||
// want the 'navaid-id' property. However setting the 'real' option
|
||||
// gives a better UI experience (eg existing Position in Air dialog)
|
||||
FGPositioned::Type ty = m_location->type();
|
||||
switch (ty) {
|
||||
case FGPositioned::VOR:
|
||||
m_config->setArg("vor", m_location->ident());
|
||||
setNavRadioOption();
|
||||
break;
|
||||
|
||||
case FGPositioned::NDB:
|
||||
m_config->setArg("ndb", m_location->ident());
|
||||
setNavRadioOption();
|
||||
break;
|
||||
|
||||
case FGPositioned::FIX:
|
||||
m_config->setArg("fix", m_location->ident());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
// set disambiguation property
|
||||
m_config->setProperty("/sim/presets/navaid-id", QString::number(m_location->guid()));
|
||||
applyPositionOffset();
|
||||
} // of navaid location
|
||||
}
|
||||
|
||||
void LocationWidget::setNavRadioOption()
|
||||
{
|
||||
flightgear::Options* opt = flightgear::Options::sharedInstance();
|
||||
|
||||
if (m_location->type() == FGPositioned::VOR) {
|
||||
FGNavRecordRef nav(static_cast<FGNavRecord*>(m_location.ptr()));
|
||||
double mhz = nav->get_freq() / 100.0;
|
||||
int heading = 0; // add heading support
|
||||
QString navOpt = QString("%1:%2").arg(heading).arg(mhz);
|
||||
opt->addOption("nav1", navOpt.toStdString());
|
||||
m_config->setArg("nav1", navOpt);
|
||||
} else {
|
||||
FGNavRecordRef nav(static_cast<FGNavRecord*>(m_location.ptr()));
|
||||
int khz = nav->get_freq() / 100;
|
||||
int heading = 0;
|
||||
QString adfOpt = QString("%1:%2").arg(heading).arg(khz);
|
||||
qDebug() << "ADF opt is:" << adfOpt;
|
||||
opt->addOption("adf1", adfOpt.toStdString());
|
||||
m_config->setArg("adf1", adfOpt);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <Navaids/positioned.hxx>
|
||||
#include <Airports/airports_fwd.hxx>
|
||||
|
||||
#include "LaunchConfig.hxx"
|
||||
#include "QtLauncher_fwd.hxx"
|
||||
|
||||
namespace Ui {
|
||||
|
@ -44,6 +45,8 @@ public:
|
|||
explicit LocationWidget(QWidget *parent = 0);
|
||||
~LocationWidget();
|
||||
|
||||
void setLaunchConfig(LaunchConfig* config);
|
||||
|
||||
QString locationDescription() const;
|
||||
|
||||
void setBaseLocation(FGPositionedRef ref);
|
||||
|
@ -66,6 +69,8 @@ private Q_SLOTS:
|
|||
void onLocationChanged();
|
||||
void onOffsetDataChanged();
|
||||
void onHeadingChanged();
|
||||
|
||||
void onCollectConfig();
|
||||
private:
|
||||
|
||||
void onSearch();
|
||||
|
@ -98,6 +103,8 @@ private:
|
|||
|
||||
FGPositionedList m_recentLocations;
|
||||
LauncherAircraftType m_aircraftType;
|
||||
|
||||
LaunchConfig* m_config = nullptr;
|
||||
};
|
||||
|
||||
#endif // LOCATIONWIDGET_H
|
||||
|
|
184
src/GUI/MPServersModel.cpp
Normal file
184
src/GUI/MPServersModel.cpp
Normal file
|
@ -0,0 +1,184 @@
|
|||
#include "MPServersModel.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QSettings>
|
||||
|
||||
#include <Network/RemoteXMLRequest.hxx>
|
||||
#include <Network/HTTPClient.hxx>
|
||||
|
||||
#include <Main/fg_props.hxx>
|
||||
#include <Main/globals.hxx>
|
||||
|
||||
#include "LaunchConfig.hxx"
|
||||
|
||||
const int IsCustomIndexRole = Qt::UserRole + 1;
|
||||
|
||||
MPServersModel::MPServersModel(QObject* parent) :
|
||||
QAbstractListModel(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
MPServersModel::~MPServersModel()
|
||||
{
|
||||
// if we don't cancel this now, it may complete after we are gone,
|
||||
// causing a crash when the SGCallback fires (SGCallbacks don't clean up
|
||||
// when their subject is deleted)
|
||||
globals->get_subsystem<FGHTTPClient>()->client()->cancelRequest(m_mpServerRequest);
|
||||
}
|
||||
|
||||
int MPServersModel::rowCount(const QModelIndex&) const
|
||||
{
|
||||
return m_servers.size() + 1;
|
||||
}
|
||||
|
||||
QVariant MPServersModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
int row = index.row();
|
||||
if ((row < 0) || (row > m_servers.size())) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
if (row == m_servers.size()) {
|
||||
if (role == Qt::DisplayRole) {
|
||||
return tr("Custom server");
|
||||
} else if (role == IsCustomIndexRole) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
const ServerInfo& sv(m_servers.at(row));
|
||||
if (role == Qt::DisplayRole) {
|
||||
return tr("%1 - %2").arg(sv.name).arg(sv.location);
|
||||
} else if (role == IsCustomIndexRole) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> MPServersModel::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> result;
|
||||
result[IsCustomIndexRole] = "isCustomIndex";
|
||||
return result;
|
||||
}
|
||||
|
||||
void MPServersModel::refresh()
|
||||
{
|
||||
if (m_mpServerRequest.get()) {
|
||||
return; // in-progress
|
||||
}
|
||||
|
||||
string url(fgGetString("/sim/multiplay/serverlist-url",
|
||||
"http://liveries.flightgear.org/mpstatus/mpservers.xml"));
|
||||
|
||||
if (url.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
SGPropertyNode *targetnode = fgGetNode("/sim/multiplay/server-list", true);
|
||||
m_mpServerRequest.reset(new RemoteXMLRequest(url, targetnode));
|
||||
m_mpServerRequest->done(this, &MPServersModel::onRefreshMPServersDone);
|
||||
m_mpServerRequest->fail(this, &MPServersModel::onRefreshMPServersFailed);
|
||||
globals->get_subsystem<FGHTTPClient>()->makeRequest(m_mpServerRequest);
|
||||
}
|
||||
|
||||
void MPServersModel::onRefreshMPServersDone(simgear::HTTP::Request*)
|
||||
{
|
||||
beginResetModel();
|
||||
// parse the properties
|
||||
SGPropertyNode *targetnode = fgGetNode("/sim/multiplay/server-list", true);
|
||||
m_servers.clear();
|
||||
|
||||
for (int i=0; i<targetnode->nChildren(); ++i) {
|
||||
SGPropertyNode* c = targetnode->getChild(i);
|
||||
if (c->getName() != std::string("server")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c->getBoolValue("online") != true) {
|
||||
// only list online servers
|
||||
continue;
|
||||
}
|
||||
|
||||
QString name = QString::fromStdString(c->getStringValue("name"));
|
||||
QString loc = QString::fromStdString(c->getStringValue("location"));
|
||||
QString host = QString::fromStdString(c->getStringValue("hostname"));
|
||||
int port = c->getIntValue("port");
|
||||
m_servers.push_back(ServerInfo(name, loc, host, port));
|
||||
}
|
||||
endResetModel();
|
||||
|
||||
restoreMPServerSelection();
|
||||
m_mpServerRequest.clear();
|
||||
}
|
||||
|
||||
void MPServersModel::onRefreshMPServersFailed(simgear::HTTP::Request*)
|
||||
{
|
||||
qWarning() << "refreshing MP servers failed:" << QString::fromStdString(m_mpServerRequest->responseReason());
|
||||
m_mpServerRequest.clear();
|
||||
beginResetModel();
|
||||
m_servers.clear();
|
||||
endResetModel();
|
||||
restoreMPServerSelection();
|
||||
}
|
||||
|
||||
void MPServersModel::restoreMPServerSelection()
|
||||
{
|
||||
if (m_doRestoreMPServer) {
|
||||
QSettings settings;
|
||||
settings.beginGroup("mpSettings");
|
||||
QString host = settings.value("mp-server").toString();
|
||||
if (host == "__custom__") {
|
||||
emit restoreIndex(m_servers.size());
|
||||
} else {
|
||||
// restore a built-in server
|
||||
auto it = std::find_if(m_servers.begin(), m_servers.end(), [host](const ServerInfo& info)
|
||||
{ return (info.host == host); });
|
||||
|
||||
if (it != m_servers.end()) {
|
||||
emit restoreIndex(std::distance(m_servers.begin(), it));
|
||||
}
|
||||
}
|
||||
|
||||
m_doRestoreMPServer = false;
|
||||
}
|
||||
}
|
||||
|
||||
void MPServersModel::requestRestore()
|
||||
{
|
||||
m_doRestoreMPServer = true;
|
||||
}
|
||||
|
||||
QString MPServersModel::serverForIndex(int index) const
|
||||
{
|
||||
if ((index < 0) || (index > m_servers.size())) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
if (index == m_servers.size()) {
|
||||
return "__custom__";
|
||||
}
|
||||
|
||||
return m_servers.at(index).host;
|
||||
}
|
||||
|
||||
int MPServersModel::portForIndex(int index) const
|
||||
{
|
||||
if ((index < 0) || (index >= m_servers.size())) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return m_servers.at(index).port;
|
||||
}
|
||||
|
||||
MPServersModel::ServerInfo::ServerInfo(QString n, QString l, QString h, int p)
|
||||
{
|
||||
name = n;
|
||||
location = l;
|
||||
host = h;
|
||||
port = p;
|
||||
}
|
53
src/GUI/MPServersModel.h
Normal file
53
src/GUI/MPServersModel.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
#ifndef MPSERVERSMODEL_H
|
||||
#define MPSERVERSMODEL_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
|
||||
#include <Network/RemoteXMLRequest.hxx>
|
||||
|
||||
|
||||
class MPServersModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MPServersModel(QObject* parent = nullptr);
|
||||
~MPServersModel();
|
||||
|
||||
int rowCount(const QModelIndex& index) const override;
|
||||
|
||||
QVariant data(const QModelIndex& index, int role) const override;
|
||||
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
void onRefreshMPServersDone(simgear::HTTP::Request*);
|
||||
void onRefreshMPServersFailed(simgear::HTTP::Request*);
|
||||
int findMPServerPort(const std::string& host);
|
||||
void restoreMPServerSelection();
|
||||
|
||||
void refresh();
|
||||
|
||||
void requestRestore();
|
||||
|
||||
Q_INVOKABLE QString serverForIndex(int index) const;
|
||||
Q_INVOKABLE int portForIndex(int index) const;
|
||||
signals:
|
||||
void restoreIndex(int index);
|
||||
|
||||
private:
|
||||
|
||||
SGSharedPtr<RemoteXMLRequest> m_mpServerRequest;
|
||||
bool m_doRestoreMPServer = false;
|
||||
|
||||
struct ServerInfo
|
||||
{
|
||||
ServerInfo(QString n, QString l, QString h, int port);
|
||||
|
||||
QString name, location, host;
|
||||
int port = 0;
|
||||
};
|
||||
|
||||
std::vector<ServerInfo> m_servers;
|
||||
};
|
||||
|
||||
#endif // MPSERVERSMODEL_H
|
|
@ -1,15 +0,0 @@
|
|||
#include "MPSettings.h"
|
||||
#include "ui_MPSettings.h"
|
||||
|
||||
MPSettings::MPSettings(QWidget *parent) :
|
||||
SettingsSection(parent),
|
||||
ui(new Ui::MPSettings)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
insertSettingsHeader();
|
||||
}
|
||||
|
||||
MPSettings::~MPSettings()
|
||||
{
|
||||
delete ui;
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
#ifndef MP_SETTINGS_H
|
||||
#define MP_SETTINGS_H
|
||||
|
||||
#include <GUI/settingssection.h>
|
||||
|
||||
namespace Ui {
|
||||
class MPSettings;
|
||||
}
|
||||
|
||||
class MPSettings : public SettingsSection
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MPSettings(QWidget *parent = 0);
|
||||
~MPSettings();
|
||||
|
||||
private:
|
||||
Ui::MPSettings *ui;
|
||||
};
|
||||
|
||||
#endif // MP_SETTINGS_H
|
88
src/GUI/MPSettings.qml
Normal file
88
src/GUI/MPSettings.qml
Normal file
|
@ -0,0 +1,88 @@
|
|||
import FlightGear.Launcher 1.0
|
||||
import QtQml 2.0
|
||||
|
||||
Section {
|
||||
// note this id is used, hard-coded, in MPServersModel
|
||||
id: mpSettings
|
||||
title: "Multi-player"
|
||||
|
||||
Checkbox {
|
||||
id: enableMP
|
||||
label: "Connect to the multi-player network"
|
||||
description: "Flightgear supporters maintain a network of server to enable global multi-user "
|
||||
+ "flight. This requires a moderately fast Inernet connection to be usable. Your aircraft "
|
||||
+ "will be visible to other users online, and you will see their aircraft."
|
||||
keywords: ["network", "mp"]
|
||||
}
|
||||
|
||||
LineEdit {
|
||||
id: callSign
|
||||
enabled: enableMP.checked
|
||||
label: "Call-sign"
|
||||
description: "Enter a call-sign you will use online. This is visible to all users and is " +
|
||||
"how ATC services and other pilots will refer to you. " +
|
||||
"(Maximum of ten charatcers permitted)"
|
||||
placeholder: "D-FGFS"
|
||||
}
|
||||
|
||||
Combo {
|
||||
id: mpServer
|
||||
label: "Server"
|
||||
enabled: enableMP.checked
|
||||
description: "Select a server close to you for better responsiveness and reduced lag when flying online."
|
||||
model: _mpServers
|
||||
|
||||
readonly property bool currentIsCustom: (model.serverForIndex(selectedIndex) == "__custom__")
|
||||
}
|
||||
|
||||
Connections
|
||||
{
|
||||
target: _mpServers
|
||||
onRestoreIndex: {
|
||||
mpServer.selectedIndex = index
|
||||
}
|
||||
}
|
||||
|
||||
LineEdit {
|
||||
id: mpCustomServer
|
||||
enabled: enableMP.checked
|
||||
label: "Custom server"
|
||||
visible: mpServer.currentIsCustom
|
||||
description: "Enter a server hostname or IP address, and a port number. For example 'localhost:5001'"
|
||||
placeholder: "localhost:5001"
|
||||
}
|
||||
|
||||
onApply: {
|
||||
if (enableMP.checked) {
|
||||
if (mpServer.currentIsCustom) {
|
||||
var pieces = mpCustomServer.value.split(':')
|
||||
_config.setProperty("/sim/multiplay/txhost", pieces[0]);
|
||||
_config.setProperty("/sim/multiplay/txport", pieces[1]);
|
||||
} else {
|
||||
var sel = mpServer.selectedIndex
|
||||
_config.setProperty("/sim/multiplay/txhost", _mpServers.serverForIndex(sel));
|
||||
var port = _mpServers.portForIndex(sel);
|
||||
if (port == 0) {
|
||||
port = 5000; // default MP port
|
||||
}
|
||||
|
||||
_config.setProperty("/sim/multiplay/txport", port);
|
||||
}
|
||||
|
||||
if (callSign.value.length > 0) {
|
||||
_config.setArg("callsign", callSign.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onRestore: {
|
||||
// nothing to do, restoration is done by the C++ code
|
||||
// in MPServersModel::restoreMPServerSelection
|
||||
}
|
||||
|
||||
onSave: {
|
||||
saveSetting("mp-server", _mpServers.serverForIndex(mpServer.selectedIndex));
|
||||
}
|
||||
|
||||
summary: enableMP.checked ? "multi-player;" : ""
|
||||
}
|
|
@ -1,160 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MPSettings</class>
|
||||
<widget class="SettingsSection" name="MPSettings">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>771</width>
|
||||
<height>331</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<property name="title" stdset="0">
|
||||
<string>Multi-player</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox">
|
||||
<property name="text">
|
||||
<string>Connect to the multi-player network</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Fly with hundreds of other pilots around the world.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="help" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="0,0,0">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Callsign:</string>
|
||||
</property>
|
||||
<property name="advanced" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineEdit"/>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Your call-sign identifies you to other pliots and controllers on the network. Callsigns are limited to ten characters.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="help" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Server:</string>
|
||||
</property>
|
||||
<property name="advanced" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBox_3">
|
||||
<property name="advanced" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Automatic</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Thread for culling and drawing</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Separate threads for culling and drawing</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Choose a specific multiplayer server, or enter a custom server</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="advanced" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="help" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>SettingsSection</class>
|
||||
<extends>QWidget</extends>
|
||||
<header location="global">GUI/settingssection.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -53,26 +53,12 @@ AddOnsPage::AddOnsPage(QWidget *parent, simgear::pkg::RootRef root) :
|
|||
connect(m_ui->removeAircraftPath, &QToolButton::clicked,
|
||||
this, &AddOnsPage::onRemoveAircraftPath);
|
||||
|
||||
connect(m_ui->changeDownloadDir, &QPushButton::clicked,
|
||||
this, &AddOnsPage::onChangeDownloadDir);
|
||||
|
||||
connect(m_ui->clearDownloadDir, &QPushButton::clicked,
|
||||
this, &AddOnsPage::onClearDownloadDir);
|
||||
|
||||
connect(m_ui->changeDataDir, &QPushButton::clicked,
|
||||
this, &AddOnsPage::onChangeDataDir);
|
||||
connect(m_ui->installSceneryButton, &QPushButton::clicked,
|
||||
this, &AddOnsPage::onInstallScenery);
|
||||
|
||||
m_ui->sceneryPathsList->setToolTip(
|
||||
tr("After changing this list, please restart the launcher to avoid "
|
||||
"possibly inconsistent behavior."));
|
||||
m_ui->changeDownloadDir->setToolTip(
|
||||
tr("After changing this location, you may have to restart the launcher "
|
||||
"to avoid inconsistent behavior."));
|
||||
m_ui->clearDownloadDir->setToolTip(
|
||||
tr("If you use this button, you may have to restart the launcher "
|
||||
"to avoid inconsistent behavior."));
|
||||
m_ui->installSceneryButton->setToolTip(
|
||||
tr("After installing scenery, you may have to restart the launcher "
|
||||
"to avoid inconsistent behavior."));
|
||||
|
@ -85,11 +71,6 @@ AddOnsPage::AddOnsPage(QWidget *parent, simgear::pkg::RootRef root) :
|
|||
QStringList aircraftPaths = settings.value("aircraft-paths").toStringList();
|
||||
m_ui->aircraftPathsList->addItems(aircraftPaths);
|
||||
|
||||
QVariant downloadDir = settings.value("download-dir");
|
||||
if (downloadDir.isValid()) {
|
||||
m_downloadDir = downloadDir.toString();
|
||||
}
|
||||
|
||||
updateUi();
|
||||
}
|
||||
|
||||
|
@ -294,76 +275,11 @@ void AddOnsPage::onRemoveCatalog()
|
|||
updateUi();
|
||||
}
|
||||
|
||||
void AddOnsPage::onChangeDownloadDir()
|
||||
{
|
||||
QString path = QFileDialog::getExistingDirectory(this,
|
||||
tr("Choose downloads folder"),
|
||||
m_downloadDir);
|
||||
if (path.isEmpty()) {
|
||||
return; // user cancelled
|
||||
}
|
||||
|
||||
m_downloadDir = path;
|
||||
setDownloadDir();
|
||||
}
|
||||
|
||||
void AddOnsPage::onClearDownloadDir()
|
||||
{
|
||||
// does this need an 'are you sure'?
|
||||
m_downloadDir.clear();
|
||||
|
||||
setDownloadDir();
|
||||
}
|
||||
|
||||
void AddOnsPage::setDownloadDir()
|
||||
{
|
||||
QSettings settings;
|
||||
if (m_downloadDir.isEmpty()) {
|
||||
settings.remove("download-dir");
|
||||
} else {
|
||||
settings.setValue("download-dir", m_downloadDir);
|
||||
}
|
||||
|
||||
if (m_downloadDir.isEmpty()) {
|
||||
flightgear::Options::sharedInstance()->clearOption("download-dir");
|
||||
} else {
|
||||
flightgear::Options::sharedInstance()->setOption("download-dir", m_downloadDir.toStdString());
|
||||
}
|
||||
|
||||
emit downloadDirChanged();
|
||||
updateUi();
|
||||
}
|
||||
|
||||
void AddOnsPage::onChangeDataDir()
|
||||
{
|
||||
QMessageBox mbox(this);
|
||||
mbox.setText(tr("Change the data files used by FlightGear?"));
|
||||
mbox.setInformativeText(tr("FlightGear requires additional files to operate. "
|
||||
"(Also called the base package, or fg-data) "
|
||||
"You can restart FlightGear and choose a "
|
||||
"different data files location, or restore the default setting."));
|
||||
QPushButton* quitButton = mbox.addButton(tr("Restart FlightGear now"), QMessageBox::YesRole);
|
||||
mbox.addButton(QMessageBox::Cancel);
|
||||
mbox.setDefaultButton(QMessageBox::Cancel);
|
||||
mbox.setIconPixmap(QPixmap(":/app-icon-large"));
|
||||
|
||||
mbox.exec();
|
||||
if (mbox.clickedButton() != quitButton) {
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
QSettings settings;
|
||||
// set the option to the magic marker value
|
||||
settings.setValue("fg-root", "!ask");
|
||||
} // scope the ensure settings are written nicely
|
||||
|
||||
flightgear::restartTheApp();
|
||||
}
|
||||
|
||||
void AddOnsPage::onInstallScenery()
|
||||
{
|
||||
InstallSceneryDialog dlg(this, m_downloadDir);
|
||||
QSettings settings;
|
||||
QString downloadDir = settings.value("download-dir").toString();
|
||||
InstallSceneryDialog dlg(this, downloadDir);
|
||||
if (dlg.exec() == QDialog::Accepted) {
|
||||
if (!haveSceneryPath(dlg.sceneryPath())) {
|
||||
m_ui->sceneryPathsList->addItem(dlg.sceneryPath());
|
||||
|
@ -374,30 +290,6 @@ void AddOnsPage::onInstallScenery()
|
|||
|
||||
void AddOnsPage::updateUi()
|
||||
{
|
||||
QString s = m_downloadDir;
|
||||
if (s.isEmpty()) {
|
||||
s = QString::fromStdString(flightgear::defaultDownloadDir().utf8Str());
|
||||
s.append(tr(" (default)"));
|
||||
m_ui->clearDownloadDir->setEnabled(false);
|
||||
} else {
|
||||
m_ui->clearDownloadDir->setEnabled(true);
|
||||
}
|
||||
|
||||
QString m = tr("Download location: %1").arg(s);
|
||||
m_ui->downloadLocation->setText(m);
|
||||
|
||||
QString dataLoc;
|
||||
QSettings settings;
|
||||
QString root = settings.value("fg-root").toString();
|
||||
if (root.isNull()) {
|
||||
dataLoc = tr("built-in");
|
||||
} else {
|
||||
dataLoc = root;
|
||||
}
|
||||
|
||||
m_ui->dataLocation->setText(tr("Data location: %1").arg(dataLoc));
|
||||
|
||||
|
||||
FGHTTPClient* http = globals->get_subsystem<FGHTTPClient>();
|
||||
m_ui->addDefaultCatalogButton->setEnabled(!http->isDefaultCatalogInstalled());
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ public:
|
|||
static void addDefaultCatalog(QWidget* pr, bool silent);
|
||||
|
||||
signals:
|
||||
void downloadDirChanged();
|
||||
void sceneryPathsChanged();
|
||||
void aircraftPathsChanged();
|
||||
|
||||
|
@ -38,14 +37,9 @@ private slots:
|
|||
void onRemoveCatalog();
|
||||
void onAddDefaultCatalog();
|
||||
|
||||
void onChangeDownloadDir();
|
||||
void onClearDownloadDir();
|
||||
|
||||
void onChangeDataDir();
|
||||
void onInstallScenery();
|
||||
private:
|
||||
void updateUi();
|
||||
void setDownloadDir();
|
||||
|
||||
void saveAircraftPaths();
|
||||
void saveSceneryPaths();
|
||||
|
@ -54,7 +48,6 @@ private:
|
|||
Ui::AddOnsPage* m_ui;
|
||||
CatalogListModel* m_catalogsModel;
|
||||
simgear::pkg::RootRef m_packageRoot;
|
||||
QString m_downloadDir;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -29,108 +29,6 @@
|
|||
<property name="bottomMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="dataLocation">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="0,1,0">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>16</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>FlightGear needs certain files (sometimes called 'fg-data') to function - these are included as part of stable releases.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="changeDataDir">
|
||||
<property name="text">
|
||||
<string>Change...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="downloadLocation">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,1,0,0">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>16</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Aircraft hangars and automatic scenery downloads may cause this location to contain large numbers of files. Changing this location will cause files to be downloaded again.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="changeDownloadDir">
|
||||
<property name="text">
|
||||
<string>Change...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="clearDownloadDir">
|
||||
<property name="text">
|
||||
<string>Use default</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
|
|
54
src/GUI/RenderSettings.qml
Normal file
54
src/GUI/RenderSettings.qml
Normal file
|
@ -0,0 +1,54 @@
|
|||
import FlightGear.Launcher 1.0
|
||||
|
||||
Section {
|
||||
id: renderingSetttings
|
||||
title: "Rendering"
|
||||
|
||||
readonly property bool rembrandt: (renderer.selectedIndex == 2)
|
||||
readonly property bool alsEnabled: (renderer.selectedIndex == 1)
|
||||
readonly property bool msaaEnabled: !rembrandt && (msaa.selectedIndex > 0)
|
||||
|
||||
Combo {
|
||||
id: renderer
|
||||
label: "Renderer"
|
||||
choices: ["Default", "Atmospheric Light-Scattering", "Rembrandt"]
|
||||
description: descriptions[selectedIndex]
|
||||
defaultIndex: 0
|
||||
|
||||
readonly property var descriptions: [
|
||||
"The default renderer provides standard visuals with maximum compatability",
|
||||
"The ALS renderer uses a sophisticated physical atmospheric model and several " +
|
||||
"other effects to give realistic rendering of large distances.",
|
||||
"Rembrandt is a configurable multi-pass renderer which supports shadow-maps, cinematic " +
|
||||
"effects and more. However, not all aircraft appear correctly and performance will " +
|
||||
"depend greatly on your system hardware."
|
||||
]
|
||||
}
|
||||
|
||||
Combo {
|
||||
id: msaa
|
||||
label: "Anti-aliasing"
|
||||
description: "Anti-aliasing improves the appearance of high-contrast edges and lines." +
|
||||
"This is especially noticeable on sloping or diagonal egdes. " +
|
||||
"Higher settings can reduce performance."
|
||||
keywords: ["msaa"]
|
||||
choices: ["Off", "2x", "4x"]
|
||||
enabled: !rembrandt
|
||||
property var data: [0, 2, 4];
|
||||
defaultIndex: 0
|
||||
}
|
||||
|
||||
onApply: {
|
||||
_config.setProperty("/sim/rendering/multi-sample-buffers", msaaEnabled)
|
||||
_config.setProperty("/sim/rendering/multi-samples", msaa.data[msaa.selectedIndex])
|
||||
|
||||
_config.setEnableDisableOption("rembrandt", rembrandt);
|
||||
|
||||
if (alsEnabled) {
|
||||
_config.setProperty("/sim/rendering/shaders/skydome", true);
|
||||
}
|
||||
}
|
||||
|
||||
summary: (rembrandt ? "Rembrandt;" : (alsEnabled ? "ALS;" : ""))
|
||||
+ (msaaEnabled ? "anti-aliasing;" : "")
|
||||
}
|
161
src/GUI/SettingsSectionQML.cxx
Normal file
161
src/GUI/SettingsSectionQML.cxx
Normal file
|
@ -0,0 +1,161 @@
|
|||
#include "SettingsSectionQML.hxx"
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QSettings>
|
||||
#include <QQmlEngine>
|
||||
#include <QQmlContext>
|
||||
#include <QDebug>
|
||||
|
||||
#include "AdvancedSettingsButton.h"
|
||||
#include "SettingsWidgets.hxx"
|
||||
#include "LaunchConfig.hxx"
|
||||
|
||||
SettingsSectionQML::SettingsSectionQML()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SettingsSectionQML::internalUpdateAdvanced()
|
||||
{
|
||||
Q_FOREACH (SettingsControl* w, controls()) {
|
||||
if (w->advanced()) {
|
||||
w->setVisible(m_showAdvanced);
|
||||
}
|
||||
|
||||
if (w->property("simple").toBool()) {
|
||||
w->setVisible(!m_showAdvanced);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsSectionQML::controls_append(QQmlListProperty<QObject> *prop, QObject *item)
|
||||
{
|
||||
SettingsSectionQML* self = qobject_cast<SettingsSectionQML*>(prop->object);
|
||||
QVBoxLayout* topLevelVBox = qobject_cast<QVBoxLayout*>(self->layout());
|
||||
self->m_controls.append(item);
|
||||
|
||||
SettingsControl* control = qobject_cast<SettingsControl*>(item);
|
||||
if (control) {
|
||||
// following two lines would not be needed if the custom
|
||||
// setParent function was working :(
|
||||
control->setParent(nullptr);
|
||||
control->setParent(self);
|
||||
topLevelVBox->addWidget(control);
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsSectionQML::controls_clear(QQmlListProperty<QObject> *prop)
|
||||
{
|
||||
SettingsSectionQML* self = qobject_cast<SettingsSectionQML*>(prop->object);
|
||||
QVBoxLayout* topLevelVBox = qobject_cast<QVBoxLayout*>(self->layout());
|
||||
|
||||
Q_FOREACH (QObject* c, self->m_controls) {
|
||||
SettingsControl* control = qobject_cast<SettingsControl*>(c);
|
||||
if (control) {
|
||||
topLevelVBox->removeWidget(control);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int SettingsSectionQML::controls_count(QQmlListProperty<QObject> *prop)
|
||||
{
|
||||
SettingsSectionQML* self = qobject_cast<SettingsSectionQML*>(prop->object);
|
||||
return self->m_controls.count();
|
||||
}
|
||||
|
||||
QObject *SettingsSectionQML::control_at(QQmlListProperty<QObject> *prop, int index)
|
||||
{
|
||||
SettingsSectionQML* self = qobject_cast<SettingsSectionQML*>(prop->object);
|
||||
return self->m_controls.at(index);
|
||||
}
|
||||
|
||||
QQmlListProperty<QObject> SettingsSectionQML::qmlControls()
|
||||
{
|
||||
return QQmlListProperty<QObject>(this, nullptr,
|
||||
&SettingsSectionQML::controls_append,
|
||||
&SettingsSectionQML::controls_count,
|
||||
&SettingsSectionQML::control_at,
|
||||
&SettingsSectionQML::controls_clear);
|
||||
}
|
||||
|
||||
QList<SettingsControl *> SettingsSectionQML::controls() const
|
||||
{
|
||||
return findChildren<SettingsControl*>();
|
||||
}
|
||||
|
||||
void SettingsSectionQML::updateShowAdvanced()
|
||||
{
|
||||
bool needsShowAdvanced = false;
|
||||
Q_FOREACH (SettingsControl* w, controls()) {
|
||||
needsShowAdvanced |= w->advanced();
|
||||
}
|
||||
|
||||
m_advancedModeToggle->setVisible(needsShowAdvanced);
|
||||
}
|
||||
|
||||
void SettingsSectionQML::saveState(QSettings &settings) const
|
||||
{
|
||||
QQmlContext* context = QQmlEngine::contextForObject(this);
|
||||
QString s = context->nameForObject(const_cast<SettingsSectionQML*>(this));
|
||||
settings.beginGroup(s);
|
||||
Q_FOREACH (SettingsControl* control, controls()) {
|
||||
control->saveState(settings);
|
||||
}
|
||||
const_cast<SettingsSectionQML*>(this)->save();
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
void SettingsSectionQML::restoreState(QSettings &settings)
|
||||
{
|
||||
QQmlContext* context = QQmlEngine::contextForObject(this);
|
||||
QString s = context->nameForObject(const_cast<SettingsSectionQML*>(this));
|
||||
settings.beginGroup(s);
|
||||
Q_FOREACH (SettingsControl* control, controls()) {
|
||||
control->restoreState(settings);
|
||||
}
|
||||
settings.endGroup();
|
||||
emit restore();
|
||||
}
|
||||
|
||||
void SettingsSectionQML::doApply()
|
||||
{
|
||||
LaunchConfig* config = qobject_cast<LaunchConfig*>(sender());
|
||||
Q_FOREACH (SettingsControl* control, controls()) {
|
||||
control->apply(config);
|
||||
}
|
||||
emit apply();
|
||||
}
|
||||
|
||||
QString SettingsSectionQML::summary() const
|
||||
{
|
||||
return m_summary;
|
||||
}
|
||||
|
||||
void SettingsSectionQML::saveSetting(QString key, QVariant value)
|
||||
{
|
||||
QSettings settings;
|
||||
QQmlContext* context = QQmlEngine::contextForObject(this);
|
||||
QString s = context->nameForObject(const_cast<SettingsSectionQML*>(this));
|
||||
settings.beginGroup(s);
|
||||
settings.setValue(key, value);
|
||||
}
|
||||
|
||||
QVariant SettingsSectionQML::restoreSetting(QString key)
|
||||
{
|
||||
QSettings settings;
|
||||
QQmlContext* context = QQmlEngine::contextForObject(this);
|
||||
QString s = context->nameForObject(const_cast<SettingsSectionQML*>(this));
|
||||
settings.beginGroup(s);
|
||||
return settings.value(key);
|
||||
}
|
||||
|
||||
void SettingsSectionQML::setSummary(QString summary)
|
||||
{
|
||||
if (m_summary == summary)
|
||||
return;
|
||||
|
||||
m_summary = summary;
|
||||
emit qmlSummaryChanged(summary);
|
||||
emit summaryChanged(summary);
|
||||
}
|
68
src/GUI/SettingsSectionQML.hxx
Normal file
68
src/GUI/SettingsSectionQML.hxx
Normal file
|
@ -0,0 +1,68 @@
|
|||
#ifndef SETTINGSSECTIONQML_HXX
|
||||
#define SETTINGSSECTIONQML_HXX
|
||||
|
||||
#include "settingssection.h"
|
||||
|
||||
#include <QQmlListProperty>
|
||||
|
||||
class SettingsControl;
|
||||
|
||||
class SettingsSectionQML : public SettingsSection
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
Q_PROPERTY(QQmlListProperty<QObject> controls READ qmlControls)
|
||||
Q_PROPERTY(QString summary READ summary WRITE setSummary NOTIFY qmlSummaryChanged)
|
||||
|
||||
Q_CLASSINFO("DefaultProperty", "controls")
|
||||
public:
|
||||
SettingsSectionQML();
|
||||
|
||||
QQmlListProperty<QObject> qmlControls();
|
||||
|
||||
QList<SettingsControl*> controls() const;
|
||||
|
||||
void saveState(QSettings& settings) const override;
|
||||
|
||||
void restoreState(QSettings& settings) override;
|
||||
|
||||
void doApply() override;
|
||||
|
||||
virtual QString summary() const override;
|
||||
|
||||
Q_INVOKABLE void saveSetting(QString key, QVariant value);
|
||||
Q_INVOKABLE QVariant restoreSetting(QString key);
|
||||
public slots:
|
||||
void setSummary(QString summary);
|
||||
|
||||
signals:
|
||||
void controlsChanged();
|
||||
|
||||
/**
|
||||
* @brief apply - change the launch configuration according to the values
|
||||
* in this settings section.
|
||||
*/
|
||||
void apply();
|
||||
|
||||
void save();
|
||||
|
||||
void restore();
|
||||
|
||||
void qmlSummaryChanged(QString summary);
|
||||
|
||||
private:
|
||||
|
||||
static void controls_append( QQmlListProperty<QObject>* prop,
|
||||
QObject* item );
|
||||
static void controls_clear( QQmlListProperty<QObject>* prop );
|
||||
static int controls_count( QQmlListProperty<QObject>* prop );
|
||||
static QObject* control_at( QQmlListProperty<QObject>* prop, int index );
|
||||
|
||||
void internalUpdateAdvanced() override;
|
||||
void updateShowAdvanced() override;
|
||||
QString m_summary;
|
||||
QObjectList m_controls;
|
||||
};
|
||||
|
||||
#endif // SETTINGSSECTIONQML_HXX
|
627
src/GUI/SettingsWidgets.cxx
Normal file
627
src/GUI/SettingsWidgets.cxx
Normal file
|
@ -0,0 +1,627 @@
|
|||
#include "SettingsWidgets.hxx"
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QCheckBox>
|
||||
#include <QLabel>
|
||||
#include <QComboBox>
|
||||
#include <QSpinBox>
|
||||
#include <QSettings>
|
||||
#include <QLineEdit>
|
||||
#include <QDebug>
|
||||
#include <QPushButton>
|
||||
#include <QFileDialog>
|
||||
#include <QQmlEngine>
|
||||
#include <QQmlContext>
|
||||
#include <QDateTimeEdit>
|
||||
|
||||
#include "LaunchConfig.hxx"
|
||||
|
||||
SettingsCheckbox::SettingsCheckbox(QWidget* parent) :
|
||||
SettingsControl(parent)
|
||||
{
|
||||
QVBoxLayout* vbox = new QVBoxLayout(this);
|
||||
setLayout(vbox);
|
||||
m_check = new QCheckBox(this);
|
||||
vbox->addWidget(m_check);
|
||||
createDescription();
|
||||
vbox->addWidget(m_description);
|
||||
connect(m_check, &QCheckBox::toggled, this, &SettingsCheckbox::checkedChanged);
|
||||
}
|
||||
|
||||
QString SettingsCheckbox::label() const
|
||||
{
|
||||
return m_check->text();
|
||||
}
|
||||
|
||||
bool SettingsCheckbox::isChecked() const
|
||||
{
|
||||
return m_check->isChecked();
|
||||
}
|
||||
|
||||
void SettingsCheckbox::setChecked(bool checked)
|
||||
{
|
||||
if (checked == isChecked()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_check->setChecked(checked);
|
||||
emit checkedChanged(checked);
|
||||
}
|
||||
|
||||
void SettingsCheckbox::setLabel(QString label)
|
||||
{
|
||||
m_check->setText(label);
|
||||
}
|
||||
|
||||
void SettingsCheckbox::apply(LaunchConfig* lconfig) const
|
||||
{
|
||||
if (option().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
lconfig->setEnableDisableOption(option(), isChecked());
|
||||
}
|
||||
|
||||
void SettingsCheckbox::saveState(QSettings &settings) const
|
||||
{
|
||||
settings.setValue(qmlName(), isChecked());
|
||||
}
|
||||
|
||||
void SettingsCheckbox::restoreState(QSettings &settings)
|
||||
{
|
||||
setChecked(settings.value(qmlName(), isChecked()).toBool());
|
||||
}
|
||||
|
||||
QString SettingsControl::label() const
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString SettingsControl::description() const
|
||||
{
|
||||
if (m_description) {
|
||||
return m_description->text();
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
QStringList SettingsControl::keywords() const
|
||||
{
|
||||
return m_keywords;
|
||||
}
|
||||
|
||||
QString SettingsControl::option() const
|
||||
{
|
||||
return m_option;
|
||||
}
|
||||
|
||||
void SettingsControl::setAdvanced(bool advanced)
|
||||
{
|
||||
if (m_advanced == advanced)
|
||||
return;
|
||||
|
||||
m_advanced = advanced;
|
||||
emit advancedChanged(advanced);
|
||||
}
|
||||
|
||||
void SettingsControl::setDescription(QString desc)
|
||||
{
|
||||
if (m_description) {
|
||||
m_description->setText(desc);
|
||||
}
|
||||
emit descriptionChanged();
|
||||
}
|
||||
|
||||
void SettingsControl::apply(LaunchConfig *lconfig) const
|
||||
{
|
||||
Q_UNUSED(lconfig)
|
||||
}
|
||||
|
||||
void SettingsControl::setKeywords(QStringList keywords)
|
||||
{
|
||||
if (m_keywords == keywords)
|
||||
return;
|
||||
|
||||
m_keywords = keywords;
|
||||
emit keywordsChanged(keywords);
|
||||
}
|
||||
|
||||
void SettingsControl::setOption(QString option)
|
||||
{
|
||||
if (m_option == option)
|
||||
return;
|
||||
|
||||
m_option = option;
|
||||
emit optionChanged(option);
|
||||
}
|
||||
|
||||
SettingsControl::SettingsControl(QWidget *pr) :
|
||||
QWidget(pr)
|
||||
{
|
||||
}
|
||||
|
||||
void SettingsControl::createDescription()
|
||||
{
|
||||
m_description = new QLabel(this);
|
||||
m_description->setWordWrap(true);
|
||||
QFont f = m_description->font();
|
||||
f.setPointSize(f.pointSize() - 2);
|
||||
m_description->setFont(f);
|
||||
}
|
||||
|
||||
QString SettingsControl::qmlName() const
|
||||
{
|
||||
QQmlContext* context = QQmlEngine::contextForObject(this);
|
||||
QString s = context->nameForObject(const_cast<SettingsControl*>(this));
|
||||
return s;
|
||||
}
|
||||
|
||||
SettingsComboBox::SettingsComboBox(QWidget *pr) :
|
||||
SettingsControl(pr)
|
||||
{
|
||||
QVBoxLayout* vbox = new QVBoxLayout(this);
|
||||
setLayout(vbox);
|
||||
|
||||
QHBoxLayout* hbox = new QHBoxLayout;
|
||||
vbox->addLayout(hbox);
|
||||
m_combo = new QComboBox(this);
|
||||
|
||||
m_label = new QLabel(this);
|
||||
hbox->addWidget(m_label);
|
||||
hbox->addWidget(m_combo);
|
||||
hbox->addStretch(1);
|
||||
|
||||
createDescription();
|
||||
vbox->addWidget(m_description);
|
||||
|
||||
connect(m_combo, SIGNAL(currentIndexChanged(int)),
|
||||
this, SIGNAL(selectedIndexChanged(int)));
|
||||
}
|
||||
|
||||
QStringList SettingsComboBox::choices() const
|
||||
{
|
||||
QStringList result;
|
||||
for (int i=0; i < m_combo->count(); ++i) {
|
||||
result.append(m_combo->itemText(i));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int SettingsComboBox::selectedIndex() const
|
||||
{
|
||||
return m_combo->currentIndex();
|
||||
}
|
||||
|
||||
void SettingsComboBox::saveState(QSettings &settings) const
|
||||
{
|
||||
// if selected index is custom, need to save something else?
|
||||
if (selectedIndex() == m_defaultIndex) {
|
||||
settings.remove(qmlName());
|
||||
} else {
|
||||
settings.setValue(qmlName(), selectedIndex());
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsComboBox::restoreState(QSettings &settings)
|
||||
{
|
||||
QString id = qmlName();
|
||||
setSelectedIndex(settings.value(id, m_defaultIndex).toInt());
|
||||
}
|
||||
|
||||
void SettingsComboBox::setChoices(QStringList aChoices)
|
||||
{
|
||||
if (choices() == aChoices)
|
||||
return;
|
||||
|
||||
m_combo->clear();
|
||||
Q_FOREACH (QString choice, aChoices) {
|
||||
m_combo->addItem(choice);
|
||||
}
|
||||
|
||||
emit choicesChanged(aChoices);
|
||||
}
|
||||
|
||||
void SettingsComboBox::setSelectedIndex(int selectedIndex)
|
||||
{
|
||||
if (m_combo->currentIndex() == selectedIndex)
|
||||
return;
|
||||
|
||||
m_combo->setCurrentIndex(selectedIndex);
|
||||
emit selectedIndexChanged(selectedIndex);
|
||||
}
|
||||
|
||||
void SettingsComboBox::setLabel(QString label)
|
||||
{
|
||||
m_label->setText(label);
|
||||
emit labelChanged();
|
||||
}
|
||||
|
||||
|
||||
QAbstractItemModel *SettingsComboBox::model() const
|
||||
{
|
||||
return m_combo->model();
|
||||
}
|
||||
|
||||
int SettingsComboBox::defaultIndex() const
|
||||
{
|
||||
return m_defaultIndex;
|
||||
}
|
||||
|
||||
void SettingsComboBox::setModel(QAbstractItemModel *model)
|
||||
{
|
||||
if (model == m_combo->model()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_combo->setModel(model);
|
||||
emit modelChanged(model);
|
||||
}
|
||||
|
||||
void SettingsComboBox::setDefaultIndex(int defaultIndex)
|
||||
{
|
||||
if (m_defaultIndex == defaultIndex)
|
||||
return;
|
||||
|
||||
m_defaultIndex = defaultIndex;
|
||||
emit defaultIndexChanged(defaultIndex);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SettingsIntSpinbox::SettingsIntSpinbox(QWidget *pr) :
|
||||
SettingsControl(pr)
|
||||
{
|
||||
QVBoxLayout* vbox = new QVBoxLayout(this);
|
||||
setLayout(vbox);
|
||||
|
||||
QHBoxLayout* hbox = new QHBoxLayout;
|
||||
vbox->addLayout(hbox);
|
||||
m_spin = new QSpinBox(this);
|
||||
|
||||
m_label = new QLabel(this);
|
||||
hbox->addWidget(m_label);
|
||||
hbox->addWidget(m_spin);
|
||||
hbox->addStretch(1);
|
||||
|
||||
createDescription();
|
||||
vbox->addWidget(m_description);
|
||||
|
||||
connect(m_spin, SIGNAL(valueChanged(int)), this, SIGNAL(valueChanged(int)));
|
||||
}
|
||||
|
||||
int SettingsIntSpinbox::value() const
|
||||
{
|
||||
return m_spin->value();
|
||||
}
|
||||
|
||||
int SettingsIntSpinbox::min() const
|
||||
{
|
||||
return m_spin->minimum();
|
||||
}
|
||||
|
||||
int SettingsIntSpinbox::max() const
|
||||
{
|
||||
return m_spin->maximum();
|
||||
}
|
||||
|
||||
void SettingsIntSpinbox::apply(LaunchConfig *lconfig) const
|
||||
{
|
||||
if (option().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
lconfig->setArg(option(), QString::number(value()));
|
||||
}
|
||||
|
||||
void SettingsIntSpinbox::saveState(QSettings &settings) const
|
||||
{
|
||||
settings.setValue(qmlName(), value());
|
||||
}
|
||||
|
||||
void SettingsIntSpinbox::restoreState(QSettings &settings)
|
||||
{
|
||||
setValue(settings.value(qmlName(), value()).toInt());
|
||||
}
|
||||
|
||||
void SettingsIntSpinbox::setValue(int aValue)
|
||||
{
|
||||
if (value() == aValue)
|
||||
return;
|
||||
|
||||
m_spin->setValue(aValue);
|
||||
emit valueChanged(aValue);
|
||||
}
|
||||
|
||||
void SettingsIntSpinbox::setMin(int aMin)
|
||||
{
|
||||
if (min() == aMin)
|
||||
return;
|
||||
|
||||
m_spin->setMinimum(aMin);
|
||||
emit minChanged(aMin);
|
||||
}
|
||||
|
||||
void SettingsIntSpinbox::setMax(int aMax)
|
||||
{
|
||||
if (max() == aMax)
|
||||
return;
|
||||
|
||||
m_spin->setMaximum(aMax);
|
||||
emit maxChanged(aMax);
|
||||
}
|
||||
|
||||
void SettingsIntSpinbox::setLabel(QString label)
|
||||
{
|
||||
m_label->setText(label);
|
||||
emit labelChanged();
|
||||
}
|
||||
|
||||
SettingsText::SettingsText(QWidget *pr) :
|
||||
SettingsControl(pr)
|
||||
{
|
||||
QVBoxLayout* vbox = new QVBoxLayout(this);
|
||||
setLayout(vbox);
|
||||
|
||||
QHBoxLayout* hbox = new QHBoxLayout;
|
||||
vbox->addLayout(hbox);
|
||||
m_edit = new QLineEdit(this);
|
||||
|
||||
m_label = new QLabel(this);
|
||||
hbox->addWidget(m_label);
|
||||
hbox->addWidget(m_edit, 1);
|
||||
// hbox->addStretch(1);
|
||||
|
||||
createDescription();
|
||||
vbox->addWidget(m_description);
|
||||
|
||||
connect(m_edit, &QLineEdit::textChanged, this, &SettingsText::valueChanged);
|
||||
}
|
||||
|
||||
QString SettingsText::value() const
|
||||
{
|
||||
return m_edit->text();
|
||||
}
|
||||
|
||||
void SettingsText::apply(LaunchConfig *lconfig) const
|
||||
{
|
||||
if (option().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
lconfig->setArg(option(), value());
|
||||
}
|
||||
|
||||
void SettingsText::saveState(QSettings &settings) const
|
||||
{
|
||||
settings.setValue(qmlName(), value());
|
||||
}
|
||||
|
||||
void SettingsText::restoreState(QSettings &settings)
|
||||
{
|
||||
setValue(settings.value(qmlName(), value()).toString());
|
||||
}
|
||||
|
||||
void SettingsText::setLabel(QString label)
|
||||
{
|
||||
m_label->setText(label);
|
||||
}
|
||||
|
||||
void SettingsText::setValue(QString newVal)
|
||||
{
|
||||
if (value() == newVal)
|
||||
return;
|
||||
|
||||
m_edit->setText(newVal);
|
||||
emit valueChanged(newVal);
|
||||
}
|
||||
|
||||
QString SettingsText::placeholder() const
|
||||
{
|
||||
#if QT_VERSION >= 0x050300
|
||||
return m_edit->placeholderText();
|
||||
#else
|
||||
return QString();
|
||||
#endif
|
||||
}
|
||||
|
||||
void SettingsText::setPlaceholder(QString hold)
|
||||
{
|
||||
if (placeholder() == hold)
|
||||
return;
|
||||
|
||||
#if QT_VERSION >= 0x050300
|
||||
// don't require Qt 5.3
|
||||
m_edit->setPlaceholderText(hold);
|
||||
#endif
|
||||
emit placeholderChanged(hold);
|
||||
}
|
||||
|
||||
SettingsPath::SettingsPath(QWidget *pr) :
|
||||
SettingsControl(pr)
|
||||
{
|
||||
QVBoxLayout* vbox = new QVBoxLayout(this);
|
||||
setLayout(vbox);
|
||||
|
||||
QHBoxLayout* hbox = new QHBoxLayout;
|
||||
vbox->addLayout(hbox);
|
||||
|
||||
m_changeButton = new QPushButton(tr("Change"), this);
|
||||
connect(m_changeButton, &QPushButton::clicked, this, &SettingsPath::choosePath);
|
||||
|
||||
m_defaultButton = new QPushButton(tr("Default"), this);
|
||||
connect(m_defaultButton, &QPushButton::clicked, this, &SettingsPath::restoreDefaultPath);
|
||||
|
||||
m_label = new QLabel(this);
|
||||
hbox->addWidget(m_label, 1);
|
||||
hbox->addWidget(m_changeButton);
|
||||
hbox->addWidget(m_defaultButton);
|
||||
|
||||
createDescription();
|
||||
vbox->addWidget(m_description);
|
||||
}
|
||||
|
||||
QString SettingsPath::path() const
|
||||
{
|
||||
return m_path;
|
||||
}
|
||||
|
||||
void SettingsPath::setPath(QString path)
|
||||
{
|
||||
if (m_path == path)
|
||||
return;
|
||||
|
||||
m_path = path;
|
||||
emit pathChanged(path);
|
||||
updateLabel();
|
||||
}
|
||||
|
||||
void SettingsPath::setLabel(QString label)
|
||||
{
|
||||
m_labelPrefix = label;
|
||||
updateLabel();
|
||||
}
|
||||
|
||||
void SettingsPath::apply(LaunchConfig *lconfig) const
|
||||
{
|
||||
if (m_option.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_path.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
lconfig->setArg(option(), path());
|
||||
}
|
||||
|
||||
void SettingsPath::setDefaultPath(QString path)
|
||||
{
|
||||
if (m_defaultPath == path)
|
||||
return;
|
||||
|
||||
m_defaultPath = path;
|
||||
m_defaultButton->setVisible(!m_defaultPath.isEmpty());
|
||||
emit defaultPathChanged(path);
|
||||
updateLabel();
|
||||
}
|
||||
|
||||
void SettingsPath::setChooseDirectory(bool chooseDirectory)
|
||||
{
|
||||
if (m_chooseDirectory == chooseDirectory)
|
||||
return;
|
||||
|
||||
m_chooseDirectory = chooseDirectory;
|
||||
emit chooseDirectoryChanged(chooseDirectory);
|
||||
}
|
||||
|
||||
void SettingsPath::choosePath()
|
||||
{
|
||||
QString path;
|
||||
if (m_chooseDirectory) {
|
||||
path = QFileDialog::getExistingDirectory(this,
|
||||
m_dialogPrompt,
|
||||
m_path);
|
||||
} else {
|
||||
// if we're going to use this, add filter support
|
||||
path = QFileDialog::getOpenFileName(this, m_dialogPrompt, m_path);
|
||||
}
|
||||
|
||||
if (path.isEmpty()) {
|
||||
return; // user cancelled
|
||||
}
|
||||
setPath(path);
|
||||
}
|
||||
|
||||
void SettingsPath::restoreDefaultPath()
|
||||
{
|
||||
setPath(QString());
|
||||
}
|
||||
|
||||
void SettingsPath::setDialogPrompt(QString dialogPrompt)
|
||||
{
|
||||
if (m_dialogPrompt == dialogPrompt)
|
||||
return;
|
||||
|
||||
m_dialogPrompt = dialogPrompt;
|
||||
emit dialogPromptChanged(dialogPrompt);
|
||||
}
|
||||
|
||||
void SettingsPath::setOption(QString option)
|
||||
{
|
||||
if (m_option == option)
|
||||
return;
|
||||
|
||||
m_option = option;
|
||||
emit optionChanged(option);
|
||||
}
|
||||
|
||||
void SettingsPath::updateLabel()
|
||||
{
|
||||
const bool isDefault = (m_path.isEmpty());
|
||||
QString s = isDefault ? tr("%1: %2 (default)") : tr("%1: %2");
|
||||
QString path = isDefault ? defaultPath() : m_path;
|
||||
m_label->setText(s.arg(m_labelPrefix).arg(path));
|
||||
m_defaultButton->setEnabled(!isDefault);
|
||||
}
|
||||
|
||||
void SettingsPath::saveState(QSettings &settings) const
|
||||
{
|
||||
settings.setValue(qmlName(), m_path);
|
||||
}
|
||||
|
||||
void SettingsPath::restoreState(QSettings &settings)
|
||||
{
|
||||
QString s = settings.value(qmlName(), QString()).toString();
|
||||
setPath(s);
|
||||
}
|
||||
|
||||
SettingsDateTime::SettingsDateTime(QWidget *pr) :
|
||||
SettingsControl(pr)
|
||||
{
|
||||
QVBoxLayout* vbox = new QVBoxLayout(this);
|
||||
setLayout(vbox);
|
||||
|
||||
QHBoxLayout* hbox = new QHBoxLayout;
|
||||
vbox->addLayout(hbox);
|
||||
|
||||
m_edit = new QDateTimeEdit;
|
||||
m_label = new QLabel(this);
|
||||
hbox->addWidget(m_label);
|
||||
hbox->addWidget(m_edit);
|
||||
hbox->addStretch(1);
|
||||
|
||||
createDescription();
|
||||
vbox->addWidget(m_description);
|
||||
}
|
||||
|
||||
void SettingsDateTime::saveState(QSettings &settings) const
|
||||
{
|
||||
settings.setValue(qmlName(), value());
|
||||
}
|
||||
|
||||
void SettingsDateTime::restoreState(QSettings &settings)
|
||||
{
|
||||
m_edit->setDateTime(settings.value(qmlName()).toDateTime());
|
||||
}
|
||||
|
||||
void SettingsDateTime::setLabel(QString label)
|
||||
{
|
||||
m_label->setText(label);
|
||||
}
|
||||
|
||||
QDateTime SettingsDateTime::value() const
|
||||
{
|
||||
return m_edit->dateTime();
|
||||
}
|
||||
|
||||
void SettingsDateTime::setValue(QDateTime value)
|
||||
{
|
||||
if (m_edit->dateTime() == value) {
|
||||
|
||||
}
|
||||
|
||||
emit valueChanged(value);
|
||||
}
|
||||
|
352
src/GUI/SettingsWidgets.hxx
Normal file
352
src/GUI/SettingsWidgets.hxx
Normal file
|
@ -0,0 +1,352 @@
|
|||
#ifndef SETTINGSWIDGETS_HXX
|
||||
#define SETTINGSWIDGETS_HXX
|
||||
|
||||
#include <QWidget>
|
||||
#include <QDateTime>
|
||||
|
||||
class QCheckBox;
|
||||
class QComboBox;
|
||||
class QSpinBox;
|
||||
class QLineEdit;
|
||||
class QLabel;
|
||||
class QSettings;
|
||||
class LaunchConfig;
|
||||
class QPushButton;
|
||||
class QAbstractItemModel;
|
||||
class QDateTimeEdit;
|
||||
|
||||
class SettingsControl : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(bool advanced READ advanced WRITE setAdvanced NOTIFY advancedChanged)
|
||||
Q_PROPERTY(QString label READ label WRITE setLabel NOTIFY labelChanged)
|
||||
Q_PROPERTY(QString description READ description WRITE setDescription NOTIFY descriptionChanged)
|
||||
Q_PROPERTY(QStringList keywords READ keywords WRITE setKeywords NOTIFY keywordsChanged)
|
||||
Q_PROPERTY(QString option READ option WRITE setOption NOTIFY optionChanged)
|
||||
public:
|
||||
|
||||
bool advanced() const
|
||||
{
|
||||
return m_advanced;
|
||||
}
|
||||
|
||||
virtual QString label() const;
|
||||
virtual QString description() const;
|
||||
|
||||
QStringList keywords() const;
|
||||
|
||||
QString option() const;
|
||||
|
||||
virtual void saveState(QSettings& settings) const = 0;
|
||||
|
||||
virtual void restoreState(QSettings& settings) = 0;
|
||||
|
||||
|
||||
public slots:
|
||||
void setAdvanced(bool advanced);
|
||||
|
||||
virtual void setDescription(QString desc);
|
||||
virtual void setLabel(QString label) = 0;
|
||||
|
||||
virtual void apply(LaunchConfig* lconfig) const;
|
||||
|
||||
void setKeywords(QStringList keywords);
|
||||
|
||||
void setOption(QString option);
|
||||
|
||||
signals:
|
||||
void advancedChanged(bool advanced);
|
||||
void labelChanged();
|
||||
void descriptionChanged();
|
||||
void keywordsChanged(QStringList keywords);
|
||||
void optionChanged(QString option);
|
||||
|
||||
protected:
|
||||
SettingsControl(QWidget* pr = nullptr);
|
||||
|
||||
void createDescription();
|
||||
|
||||
QString qmlName() const;
|
||||
|
||||
QLabel* m_description = nullptr;
|
||||
private:
|
||||
bool m_advanced = false;
|
||||
QStringList m_keywords;
|
||||
QString m_option;
|
||||
};
|
||||
|
||||
class SettingsCheckbox : public SettingsControl
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(bool checked READ isChecked WRITE setChecked NOTIFY checkedChanged)
|
||||
|
||||
bool isChecked() const;
|
||||
|
||||
public:
|
||||
SettingsCheckbox(QWidget* pr = nullptr);
|
||||
|
||||
virtual QString label() const override;
|
||||
|
||||
virtual void setLabel(QString label) override;
|
||||
|
||||
virtual void apply(LaunchConfig* lconfig) const override;
|
||||
|
||||
virtual void saveState(QSettings& settings) const override;
|
||||
|
||||
virtual void restoreState(QSettings& settings) override;
|
||||
public slots:
|
||||
void setChecked(bool checked);
|
||||
|
||||
signals:
|
||||
void checkedChanged(bool checked);
|
||||
|
||||
private:
|
||||
QCheckBox* m_check;
|
||||
};
|
||||
|
||||
class SettingsComboBox : public SettingsControl
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(int selectedIndex READ selectedIndex WRITE setSelectedIndex NOTIFY selectedIndexChanged)
|
||||
Q_PROPERTY(QStringList choices READ choices WRITE setChoices NOTIFY choicesChanged)
|
||||
Q_PROPERTY(QAbstractItemModel* model READ model WRITE setModel NOTIFY modelChanged)
|
||||
Q_PROPERTY(int defaultIndex READ defaultIndex WRITE setDefaultIndex NOTIFY defaultIndexChanged)
|
||||
public:
|
||||
SettingsComboBox(QWidget* pr = nullptr);
|
||||
|
||||
QStringList choices() const;
|
||||
|
||||
int selectedIndex() const;
|
||||
|
||||
virtual void saveState(QSettings& settings) const override;
|
||||
|
||||
virtual void restoreState(QSettings& settings) override;
|
||||
|
||||
QAbstractItemModel* model() const;
|
||||
|
||||
int defaultIndex() const;
|
||||
|
||||
public slots:
|
||||
void setChoices(QStringList choices);
|
||||
|
||||
void setSelectedIndex(int selectedIndex);
|
||||
|
||||
void setModel(QAbstractItemModel* model);
|
||||
|
||||
void setDefaultIndex(int defaultIndex);
|
||||
|
||||
signals:
|
||||
void choicesChanged(QStringList choices);
|
||||
|
||||
void selectedIndexChanged(int selectedIndex);
|
||||
|
||||
void modelChanged(QAbstractItemModel* model);
|
||||
|
||||
void defaultIndexChanged(int defaultIndex);
|
||||
|
||||
protected:
|
||||
virtual void setLabel(QString label) override;
|
||||
|
||||
private:
|
||||
QLabel* m_label;
|
||||
QComboBox* m_combo;
|
||||
QStringList m_choices;
|
||||
int m_selectedIndex = 0;
|
||||
int m_defaultIndex = -1;
|
||||
};
|
||||
|
||||
class SettingsIntSpinbox : public SettingsControl
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged)
|
||||
Q_PROPERTY(int min READ min WRITE setMin NOTIFY minChanged)
|
||||
Q_PROPERTY(int max READ max WRITE setMax NOTIFY maxChanged)
|
||||
|
||||
// suffix / wrap information
|
||||
|
||||
public:
|
||||
SettingsIntSpinbox(QWidget* pr = nullptr);
|
||||
|
||||
int value() const;
|
||||
int min() const;
|
||||
int max() const;
|
||||
|
||||
virtual void apply(LaunchConfig* lconfig) const override;
|
||||
|
||||
virtual void saveState(QSettings& settings) const override;
|
||||
|
||||
virtual void restoreState(QSettings& settings) override;
|
||||
public slots:
|
||||
void setValue(int value);
|
||||
void setMin(int min);
|
||||
void setMax(int max);
|
||||
|
||||
signals:
|
||||
void valueChanged(int value);
|
||||
void minChanged(int min);
|
||||
void maxChanged(int max);
|
||||
|
||||
protected:
|
||||
virtual void setLabel(QString label) override;
|
||||
|
||||
private:
|
||||
QSpinBox* m_spin;
|
||||
QLabel* m_label;
|
||||
int m_value;
|
||||
int m_min;
|
||||
int m_max;
|
||||
};
|
||||
|
||||
class SettingsText : public SettingsControl
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QString value READ value WRITE setValue NOTIFY valueChanged)
|
||||
Q_PROPERTY(QString placeholder READ placeholder WRITE setPlaceholder NOTIFY placeholderChanged)
|
||||
public:
|
||||
SettingsText(QWidget *pr = nullptr);
|
||||
|
||||
QString value() const;
|
||||
|
||||
virtual void apply(LaunchConfig* lconfig) const override;
|
||||
|
||||
virtual void saveState(QSettings& settings) const override;
|
||||
|
||||
virtual void restoreState(QSettings& settings) override;
|
||||
|
||||
virtual void setLabel(QString label) override;
|
||||
|
||||
QString placeholder() const;
|
||||
|
||||
public slots:
|
||||
void setValue(QString value);
|
||||
|
||||
void setPlaceholder(QString placeholder);
|
||||
|
||||
signals:
|
||||
void valueChanged(QString value);
|
||||
|
||||
void placeholderChanged(QString placeholder);
|
||||
|
||||
private:
|
||||
QLineEdit* m_edit;
|
||||
QLabel* m_label;
|
||||
};
|
||||
|
||||
class SettingsPath : public SettingsControl
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged)
|
||||
Q_PROPERTY(QString defaultPath READ defaultPath WRITE setDefaultPath
|
||||
NOTIFY defaultPathChanged)
|
||||
Q_PROPERTY(bool chooseDirectory READ chooseDirectory
|
||||
WRITE setChooseDirectory NOTIFY chooseDirectoryChanged)
|
||||
Q_PROPERTY(QString dialogPrompt READ dialogPrompt
|
||||
WRITE setDialogPrompt NOTIFY dialogPromptChanged)
|
||||
Q_PROPERTY(QString option READ option WRITE setOption NOTIFY optionChanged)
|
||||
|
||||
|
||||
public:
|
||||
SettingsPath(QWidget *pr = nullptr);
|
||||
|
||||
QString path() const;
|
||||
|
||||
virtual void saveState(QSettings& settings) const override;
|
||||
|
||||
virtual void restoreState(QSettings& settings) override;
|
||||
|
||||
virtual void setLabel(QString label) override;
|
||||
|
||||
virtual void apply(LaunchConfig* lconfig) const override;
|
||||
|
||||
QString defaultPath() const
|
||||
{
|
||||
return m_defaultPath;
|
||||
}
|
||||
|
||||
bool chooseDirectory() const
|
||||
{
|
||||
return m_chooseDirectory;
|
||||
}
|
||||
|
||||
QString dialogPrompt() const
|
||||
{
|
||||
return m_dialogPrompt;
|
||||
}
|
||||
|
||||
QString option() const
|
||||
{
|
||||
return m_option;
|
||||
}
|
||||
|
||||
public slots:
|
||||
void setPath(QString path);
|
||||
void setDefaultPath(QString path);
|
||||
|
||||
void setChooseDirectory(bool chooseDirectory);
|
||||
|
||||
void choosePath();
|
||||
void restoreDefaultPath();
|
||||
void setDialogPrompt(QString dialogPrompt);
|
||||
|
||||
void setOption(QString option);
|
||||
|
||||
signals:
|
||||
void defaultPathChanged(QString defaultPath);
|
||||
|
||||
void pathChanged(QString path);
|
||||
|
||||
void chooseDirectoryChanged(bool chooseDirectory);
|
||||
|
||||
void dialogPromptChanged(QString dialogPrompt);
|
||||
|
||||
void optionChanged(QString option);
|
||||
|
||||
private:
|
||||
void updateLabel();
|
||||
|
||||
QPushButton* m_changeButton;
|
||||
QPushButton* m_defaultButton;
|
||||
QString m_path;
|
||||
QString m_defaultPath;
|
||||
QLabel* m_label;
|
||||
QString m_labelPrefix;
|
||||
bool m_chooseDirectory = false;
|
||||
QString m_dialogPrompt;
|
||||
QString m_option;
|
||||
};
|
||||
|
||||
class SettingsDateTime : public SettingsControl
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QDateTime value READ value WRITE setValue NOTIFY valueChanged)
|
||||
public:
|
||||
SettingsDateTime(QWidget *pr = nullptr);
|
||||
|
||||
virtual void saveState(QSettings& settings) const override;
|
||||
virtual void restoreState(QSettings& settings) override;
|
||||
|
||||
virtual void setLabel(QString label) override;
|
||||
|
||||
QDateTime value() const;
|
||||
|
||||
public slots:
|
||||
|
||||
void setValue(QDateTime value);
|
||||
|
||||
signals:
|
||||
void valueChanged(QDateTime value);
|
||||
|
||||
private:
|
||||
QDateTimeEdit* m_edit;
|
||||
QLabel* m_label;
|
||||
QDateTime m_value;
|
||||
};
|
||||
|
||||
#endif // SETTINGSWIDGETS_HXX
|
72
src/GUI/TimeSettings.qml
Normal file
72
src/GUI/TimeSettings.qml
Normal file
|
@ -0,0 +1,72 @@
|
|||
import FlightGear.Launcher 1.0
|
||||
|
||||
Section {
|
||||
id: timeSettings
|
||||
title: "Time & Date"
|
||||
|
||||
Combo {
|
||||
id: timeOfDay
|
||||
label: "Time of day"
|
||||
description: "Select the time of day used when the simulator starts, or enter a "
|
||||
+ "custom date and time."
|
||||
choices: ["Current time", "Dawn", "Morning", "Noon", "Afternoon",
|
||||
"Dusk", "Evening", "Midnight", "Custom time & date"]
|
||||
defaultIndex: 0
|
||||
|
||||
readonly property var args: ["", "dawn", "morning", "noon", "afternoon",
|
||||
"dusk", "evening", "midnight"]
|
||||
|
||||
readonly property bool isCustom: (selectedIndex == 8)
|
||||
readonly property bool isDefault: (selectedIndex == 0)
|
||||
|
||||
function summary()
|
||||
{
|
||||
if (!timeOfDay.isCustom && !timeOfDay.isDefault) {
|
||||
return choices[selectedIndex].toLowerCase() + ";";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
DateTime {
|
||||
id: customTime
|
||||
label: "Enter custom time & date"
|
||||
visible: timeOfDay.isCustom
|
||||
// description: "Enter a date and time."
|
||||
}
|
||||
|
||||
Checkbox {
|
||||
id: customTimeIsGMT
|
||||
label: "Custom time is GMT / UTC"
|
||||
visible: timeOfDay.isCustom
|
||||
}
|
||||
|
||||
Combo {
|
||||
id: season
|
||||
label: "Season"
|
||||
description: "Select if normal (summer) or winter textures are used for the scenery. "
|
||||
+ "This does not affect other aspects of the simulation at present."
|
||||
keywords: ["season", "scenery", "texture", "winter"]
|
||||
choices: ["Summer (default)", "Winter"]
|
||||
defaultIndex: 0
|
||||
readonly property var args: ["summer", "winter"]
|
||||
}
|
||||
|
||||
onApply: {
|
||||
if (timeOfDay.isCustom) {
|
||||
var timeString = Qt.formatDateTime(customTime.value, "yyyy:MM:dd:hh:mm:ss");
|
||||
if (customTimeIsGMT.checked) {
|
||||
_config.setArg("start-date-gmt", timeString)
|
||||
} else {
|
||||
_config.setArg("start-date-sys", timeString)
|
||||
}
|
||||
} else if (timeOfDay.selectedIndex > 0) {
|
||||
_config.setArg("timeofday", timeOfDay.args[timeOfDay.selectedIndex])
|
||||
}
|
||||
|
||||
_config.setArg("season", season.args[season.selectedIndex])
|
||||
}
|
||||
|
||||
summary: timeOfDay.summary()
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
class ToolboxButton : public QAbstractButton
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ToolboxButton(QWidget* pr = nullptr);
|
||||
|
||||
|
|
73
src/GUI/ViewCommandLinePage.cxx
Normal file
73
src/GUI/ViewCommandLinePage.cxx
Normal file
|
@ -0,0 +1,73 @@
|
|||
#include "ViewCommandLinePage.hxx"
|
||||
|
||||
#include <QTextEdit>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include <Main/options.hxx>
|
||||
|
||||
#include "LaunchConfig.hxx"
|
||||
|
||||
#if 0
|
||||
#include "ExtraSettingsSection.hxx"
|
||||
#include "LauncherArgumentTokenizer.hxx"
|
||||
#endif
|
||||
|
||||
ViewCommandLinePage::ViewCommandLinePage(QWidget *parent) : QWidget(parent)
|
||||
{
|
||||
QVBoxLayout* vbox = new QVBoxLayout(this);
|
||||
setLayout(vbox);
|
||||
m_browser = new QTextEdit(this);
|
||||
m_browser->setReadOnly(true);
|
||||
vbox->addWidget(m_browser);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void ViewCommandLinePage::setExtraSettingsSection(ExtraSettingsSection *ess)
|
||||
{
|
||||
m_extraSettings = ess;
|
||||
}
|
||||
#endif
|
||||
|
||||
void ViewCommandLinePage::setLaunchConfig(LaunchConfig *config)
|
||||
{
|
||||
m_config = config;
|
||||
}
|
||||
|
||||
void ViewCommandLinePage::update()
|
||||
{
|
||||
QString html;
|
||||
string_list commandLineOpts = flightgear::Options::sharedInstance()->extractOptions();
|
||||
if (!commandLineOpts.empty()) {
|
||||
html += "<p>Options passed on the command line:</p>\n";
|
||||
html += "<ul>\n";
|
||||
for (auto opt : commandLineOpts) {
|
||||
html += QString("<li>--") + QString::fromStdString(opt) + "</li>\n";
|
||||
}
|
||||
html += "</ul>\n";
|
||||
}
|
||||
#if 0
|
||||
if (m_extraSettings) {
|
||||
LauncherArgumentTokenizer tk;
|
||||
Q_FOREACH(auto arg, tk.tokenize(m_extraSettings->argsText())) {
|
||||
// m_config->setArg(arg.arg, arg.value);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
m_config->reset();
|
||||
m_config->collect();
|
||||
|
||||
html += "<p>Options set in the launcher:</p>\n";
|
||||
html += "<ul>\n";
|
||||
for (auto arg : m_config->values()) {
|
||||
if (arg.value.isEmpty()) {
|
||||
html += QString("<li>--") + arg.arg + "</li>\n";
|
||||
} else if (arg.arg == "prop") {
|
||||
html += QString("<li>--") + arg.arg + ":" + arg.value + "</li>\n";
|
||||
} else {
|
||||
html += QString("<li>--") + arg.arg + "=" + arg.value + "</li>\n";
|
||||
}
|
||||
}
|
||||
html += "</ul>\n";
|
||||
|
||||
m_browser->setHtml(html);
|
||||
}
|
27
src/GUI/ViewCommandLinePage.hxx
Normal file
27
src/GUI/ViewCommandLinePage.hxx
Normal file
|
@ -0,0 +1,27 @@
|
|||
#ifndef VIEWCOMMANDLINEPAGE_HXX
|
||||
#define VIEWCOMMANDLINEPAGE_HXX
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class QTextEdit;
|
||||
class LaunchConfig;
|
||||
|
||||
class ViewCommandLinePage : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ViewCommandLinePage(QWidget *parent = 0);
|
||||
|
||||
void setLaunchConfig(LaunchConfig* config);
|
||||
|
||||
void update();
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
|
||||
private:
|
||||
QTextEdit* m_browser;
|
||||
LaunchConfig* m_config = nullptr;
|
||||
};
|
||||
|
||||
#endif // VIEWCOMMANDLINEPAGE_HXX
|
|
@ -1,15 +0,0 @@
|
|||
#include "ViewSettings.h"
|
||||
#include "ui_ViewSettings.h"
|
||||
|
||||
ViewSettings::ViewSettings(QWidget *parent) :
|
||||
SettingsSection(parent),
|
||||
ui(new Ui::ViewSettings)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
insertSettingsHeader();
|
||||
}
|
||||
|
||||
ViewSettings::~ViewSettings()
|
||||
{
|
||||
delete ui;
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
#ifndef VIEWSETTINGS_H
|
||||
#define VIEWSETTINGS_H
|
||||
|
||||
#include <GUI/settingssection.h>
|
||||
|
||||
namespace Ui {
|
||||
class ViewSettings;
|
||||
}
|
||||
|
||||
class ViewSettings : public SettingsSection
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ViewSettings(QWidget *parent = 0);
|
||||
~ViewSettings();
|
||||
|
||||
private:
|
||||
Ui::ViewSettings *ui;
|
||||
};
|
||||
|
||||
#endif // VIEWSETTINGS_H
|
33
src/GUI/ViewSettings.qml
Normal file
33
src/GUI/ViewSettings.qml
Normal file
|
@ -0,0 +1,33 @@
|
|||
import FlightGear.Launcher 1.0
|
||||
|
||||
Section {
|
||||
id: viewSettings
|
||||
title: "View & Window"
|
||||
|
||||
Checkbox {
|
||||
id: fullscreen
|
||||
label: "Start full-screen"
|
||||
description: "Start the simulator in full-screen mode"
|
||||
keywords: ["window", "full", "screen"]
|
||||
option: "fullscreen"
|
||||
}
|
||||
|
||||
Combo {
|
||||
id: windowSize
|
||||
enabled: !fullscreen.checked
|
||||
label: "Window size"
|
||||
description: "Select the initial size of the window. (This has no effct in full-screen mode)"
|
||||
advanced: true
|
||||
choices: ["640x480", "800x600", "1024x768", "1920x1080", "2560x1600" ]
|
||||
defaultIndex: 2
|
||||
readonly property bool isDefault: selectedIndex == defaultIndex
|
||||
}
|
||||
|
||||
onApply: {
|
||||
if (!windowSize.isDefault) {
|
||||
_config.setArg("geometry", windowSize.choices[windowSize.selectedIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
summary: fullscreen.checked ? "full-screen;" : ""
|
||||
}
|
|
@ -1,157 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ViewSettings</class>
|
||||
<widget class="SettingsSection" name="ViewSettings">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>740</width>
|
||||
<height>338</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<property name="title" stdset="0">
|
||||
<string>View</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox">
|
||||
<property name="text">
|
||||
<string>Start full-screen</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Full-screen mode can be toggled inside the simulator by pressing F10.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="help" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Window size:</string>
|
||||
</property>
|
||||
<property name="advanced" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBox">
|
||||
<property name="advanced" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>800 x 600</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>1024 x 768</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Custom size...</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Field-of-view angle:</string>
|
||||
</property>
|
||||
<property name="advanced" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinBox">
|
||||
<property name="maximum">
|
||||
<number>180</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>90</number>
|
||||
</property>
|
||||
<property name="advanced" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Field-of-view depends on your monitor size. It can be adjusted in the simulator using the x/X keys</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="advanced" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="help" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>SettingsSection</class>
|
||||
<extends>QWidget</extends>
|
||||
<header location="global">GUI/settingssection.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
44
src/GUI/Weather.qml
Normal file
44
src/GUI/Weather.qml
Normal file
|
@ -0,0 +1,44 @@
|
|||
import FlightGear.Launcher 1.0
|
||||
|
||||
Section {
|
||||
id: weatherSettings
|
||||
title: "Weather"
|
||||
|
||||
Checkbox {
|
||||
id: fetchMetar
|
||||
label: "Real-world weather"
|
||||
description: "Download real-world weather from the NOAA servers based on location."
|
||||
option: "real-weather-fetch"
|
||||
}
|
||||
|
||||
Combo {
|
||||
id: weatherScenario
|
||||
enabled: !fetchMetar.checked
|
||||
label: "Weather scenario"
|
||||
model: _weatherScenarios
|
||||
readonly property bool isCustomMETAR: (selectedIndex == 0);
|
||||
description: _weatherScenarios.descriptionForItem(selectedIndex)
|
||||
defaultIndex: 1
|
||||
}
|
||||
|
||||
LineEdit {
|
||||
id: customMETAR
|
||||
visible: weatherScenario.isCustomMETAR
|
||||
enabled: !fetchMetar.checked
|
||||
label: "METAR"
|
||||
placeholder: "XXXX 012345Z 28035G50KT 250V300 9999 TSRA SCT022CB BKN030 13/09 Q1005"
|
||||
description: "Enter a custom METAR string"
|
||||
}
|
||||
|
||||
onApply: {
|
||||
if (!fetchMetar.checked) {
|
||||
if (weatherScenario.isCustomMETAR) {
|
||||
_config.setArg("metar", customMETAR.value)
|
||||
} else {
|
||||
_config.setArg("metar", _weatherScenarios.metarForItem(weatherScenario.selectedIndex))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
summary: fetchMetar.checked ? "real-world weather;" : ""
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
#include "renderingsettings.h"
|
||||
#include "ui_renderingsettings.h"
|
||||
|
||||
RenderingSettings::RenderingSettings(QWidget *parent) :
|
||||
SettingsSection(parent),
|
||||
ui(new Ui::RenderingSettings)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
insertSettingsHeader();
|
||||
}
|
||||
|
||||
RenderingSettings::~RenderingSettings()
|
||||
{
|
||||
delete ui;
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
#ifndef RENDERINGSETTINGS_H
|
||||
#define RENDERINGSETTINGS_H
|
||||
|
||||
#include <GUI/settingssection.h>
|
||||
|
||||
namespace Ui {
|
||||
class RenderingSettings;
|
||||
}
|
||||
|
||||
class RenderingSettings : public SettingsSection
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit RenderingSettings(QWidget *parent = 0);
|
||||
~RenderingSettings();
|
||||
|
||||
private:
|
||||
Ui::RenderingSettings *ui;
|
||||
};
|
||||
|
||||
#endif // RENDERINGSETTINGS_H
|
|
@ -1,229 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>RenderingSettings</class>
|
||||
<widget class="SettingsSection" name="RenderingSettings">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>771</width>
|
||||
<height>331</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<property name="title" stdset="0">
|
||||
<string>Rendering</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Renderer:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>ALS</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Rembrandt</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Default</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Lots of information about which renderer is selcted</string>
|
||||
</property>
|
||||
<property name="help" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox">
|
||||
<property name="text">
|
||||
<string>Enable multi-sample anti-aliasingg</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Multi-sample anti-aliasing (MSAA) reduces the appearance of jagged edges. Depending on your graphics card, this may reduce framerates</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="help" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="0,0,0">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Multi-sampling setting:</string>
|
||||
</property>
|
||||
<property name="advanced" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBox_2">
|
||||
<property name="advanced" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>2x</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>4x</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>8x</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>16x</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Custom...</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Renderer threading model:</string>
|
||||
</property>
|
||||
<property name="advanced" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBox_3">
|
||||
<property name="advanced" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Automatic</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Thread for culling and drawing</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Separate threads for culling and drawing</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Choose how the rendering code uses multiple CPU cores to get the best performance. Automatic selection is usually recommended, and some settings can lead to problems including crashes.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="advanced" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="help" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>SettingsSection</class>
|
||||
<extends>QWidget</extends>
|
||||
<header location="global">GUI/settingssection.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -27,10 +27,22 @@
|
|||
<file alias="toolbox-location">toolbox-location.png</file>
|
||||
<file alias="toolbox-settings">toolbox-settings.png</file>
|
||||
<file alias="toolbox-summary">toolbox-summary.png</file>
|
||||
<file alias="toolbox-addons">toolbox-addons.png</file>
|
||||
</qresource>
|
||||
<qresource prefix="/preview">
|
||||
<file alias="close-icon">preview-close.png</file>
|
||||
<file alias="left-arrow-icon">preview-left-arrow.png</file>
|
||||
<file alias="right-arrow-icon">preview-right-arrow.png</file>
|
||||
</qresource>
|
||||
<qresource prefix="/settings">
|
||||
<file alias="downloads">DownloadSettings.qml</file>
|
||||
<file alias="general">GeneralSettings.qml</file>
|
||||
<file alias="mp">MPSettings.qml</file>
|
||||
<file alias="render">RenderSettings.qml</file>
|
||||
<file alias="view">ViewSettings.qml</file>
|
||||
</qresource>
|
||||
<qresource prefix="/environment">
|
||||
<file alias="time">TimeSettings.qml</file>
|
||||
<file alias="weather">Weather.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -6,8 +6,12 @@
|
|||
#include <QPalette>
|
||||
#include <QPushButton>
|
||||
#include <QVariant>
|
||||
#include <QDebug>
|
||||
#include <QSettings>
|
||||
|
||||
#include "AdvancedSettingsButton.h"
|
||||
#include "SettingsWidgets.hxx"
|
||||
#include "LaunchConfig.hxx"
|
||||
|
||||
SettingsSection::SettingsSection(QWidget* pr) :
|
||||
QFrame(pr)
|
||||
|
@ -21,6 +25,16 @@ SettingsSection::SettingsSection(QWidget* pr) :
|
|||
QPalette pal = palette();
|
||||
pal.setColor(QPalette::Normal, QPalette::WindowText, Qt::white);
|
||||
m_titleLabel->setPalette(pal);
|
||||
|
||||
if (!layout()) {
|
||||
QVBoxLayout* vbox = new QVBoxLayout(this);
|
||||
setLayout(vbox);
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsSection::setLaunchConfig(LaunchConfig* config)
|
||||
{
|
||||
connect(config, &LaunchConfig::collect, this, &SettingsSection::doApply);
|
||||
}
|
||||
|
||||
void SettingsSection::setShowAdvanced(bool showAdvanced)
|
||||
|
@ -76,34 +90,25 @@ void SettingsSection::insertSettingsHeader()
|
|||
|
||||
m_advancedModeToggle = new AdvancedSettingsButton;
|
||||
connect(m_advancedModeToggle, &QPushButton::toggled, this, &SettingsSection::toggleShowAdvanced);
|
||||
|
||||
hbox->addWidget(m_advancedModeToggle);
|
||||
|
||||
QFont helpLabelFont;
|
||||
helpLabelFont.setPointSize(helpLabelFont.pointSize() - 1);
|
||||
|
||||
QPalette pal = palette();
|
||||
pal.setColor(QPalette::Normal, QPalette::WindowText, QColor(0x3f, 0x3f, 0x3f));
|
||||
|
||||
Q_FOREACH(QLabel* w, findChildren<QLabel*>()) {
|
||||
if (w->property("help").toBool()) {
|
||||
w->setFont(helpLabelFont);
|
||||
w->setPalette(pal);
|
||||
}
|
||||
}
|
||||
|
||||
updateShowAdvanced();
|
||||
internalUpdateAdvanced();
|
||||
}
|
||||
|
||||
void SettingsSection::internalUpdateAdvanced()
|
||||
{
|
||||
Q_FOREACH(QWidget* w, findChildren<QWidget*>()) {
|
||||
if (w->property("advanced").toBool()) {
|
||||
w->setVisible(m_showAdvanced);
|
||||
}
|
||||
|
||||
if (w->property("simple").toBool()) {
|
||||
w->setVisible(!m_showAdvanced);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SettingsSection::saveState(QSettings &settings) const
|
||||
{
|
||||
}
|
||||
|
||||
void SettingsSection::restoreState(QSettings &settings)
|
||||
{
|
||||
}
|
||||
|
||||
void SettingsSection::updateShowAdvanced()
|
||||
{
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include <QLabel>
|
||||
|
||||
class AdvancedSettingsButton;
|
||||
class QSettings;
|
||||
class LaunchConfig;
|
||||
|
||||
class SettingsSection : public QFrame
|
||||
{
|
||||
|
@ -17,6 +19,8 @@ class SettingsSection : public QFrame
|
|||
public:
|
||||
SettingsSection(QWidget* pr = nullptr);
|
||||
|
||||
virtual void setLaunchConfig(LaunchConfig* config);
|
||||
|
||||
bool showAdvanced() const
|
||||
{
|
||||
return m_showAdvanced;
|
||||
|
@ -29,19 +33,31 @@ public:
|
|||
|
||||
void insertSettingsHeader();
|
||||
|
||||
virtual void saveState(QSettings& settings) const;
|
||||
|
||||
virtual void restoreState(QSettings& settings);
|
||||
|
||||
virtual void doApply() = 0;
|
||||
|
||||
virtual QString summary() const = 0;
|
||||
|
||||
public slots:
|
||||
void setShowAdvanced(bool showAdvanced);
|
||||
|
||||
void setTitle(QString title);
|
||||
|
||||
void toggleShowAdvanced();
|
||||
|
||||
signals:
|
||||
void showAdvancedChanged(bool showAdvanced);
|
||||
|
||||
void titleChanged(QString title);
|
||||
|
||||
private:
|
||||
void internalUpdateAdvanced();
|
||||
void summaryChanged(QString summary);
|
||||
|
||||
protected:
|
||||
virtual void internalUpdateAdvanced();
|
||||
virtual void updateShowAdvanced();
|
||||
|
||||
QString m_title;
|
||||
bool m_showAdvanced = false;
|
||||
|
|
BIN
src/GUI/toolbox-addons.png
Normal file
BIN
src/GUI/toolbox-addons.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
|
@ -2773,10 +2773,31 @@ SGPath Options::platformDefaultRoot() const
|
|||
#else
|
||||
SGPath Options::platformDefaultRoot() const
|
||||
{
|
||||
return SGPath::fromUtf8(PKGLIBDIR);
|
||||
return SGPath::fromUtf8(PKGLIBDIR);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
string_list Options::extractOptions() const
|
||||
{
|
||||
string_list result;
|
||||
for (auto opt : p->values) {
|
||||
if (opt.desc == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(opt.desc->option,"prop")) {
|
||||
result.push_back("prop:" + opt.value);
|
||||
} else if (opt.value.empty()) {
|
||||
result.push_back(opt.desc->option);
|
||||
} else {
|
||||
result.push_back(std::string(opt.desc->option) + "=" + opt.value);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Options::setupRoot(int argc, char **argv)
|
||||
{
|
||||
SGPath root;
|
||||
|
|
|
@ -156,6 +156,14 @@ public:
|
|||
static bool checkForArg(int argc, char* argv[], const char* arg);
|
||||
|
||||
SGPath platformDefaultRoot() const;
|
||||
|
||||
/**
|
||||
* @brief extractOptions - extract the currently set options as
|
||||
* a string array. This can be used to examine what options were
|
||||
* requested / set so far.
|
||||
* @return
|
||||
*/
|
||||
string_list extractOptions() const;
|
||||
private:
|
||||
void showUsage() const;
|
||||
void showVersion() const;
|
||||
|
|
Loading…
Reference in a new issue