Launcher converted to QQ2
This simplifies the launcher's rendering since the widget-based code is gone, various things get hooked up as a result. Styling fixes everywhere as well. Menubar on Linux/Windows needs to be re-added.
This commit is contained in:
parent
78882621e9
commit
1bf52662ae
29 changed files with 613 additions and 393 deletions
|
@ -51,7 +51,7 @@ QStringList AddOnsController::sceneryPaths() const
|
|||
|
||||
QString AddOnsController::addAircraftPath() const
|
||||
{
|
||||
QString path = QFileDialog::getExistingDirectory(m_launcher, tr("Choose aircraft folder"));
|
||||
QString path = QFileDialog::getExistingDirectory(nullptr, tr("Choose aircraft folder"));
|
||||
if (path.isEmpty()) {
|
||||
return {};
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ QString AddOnsController::addAircraftPath() const
|
|||
|
||||
QString AddOnsController::addSceneryPath() const
|
||||
{
|
||||
QString path = QFileDialog::getExistingDirectory(m_launcher, tr("Choose scenery folder"));
|
||||
QString path = QFileDialog::getExistingDirectory(nullptr, tr("Choose scenery folder"));
|
||||
if (path.isEmpty()) {
|
||||
return {};
|
||||
|
||||
|
@ -128,7 +128,7 @@ QString AddOnsController::installCustomScenery()
|
|||
{
|
||||
QSettings settings;
|
||||
QString downloadDir = settings.value("download-dir").toString();
|
||||
InstallSceneryDialog dlg(m_launcher, downloadDir);
|
||||
InstallSceneryDialog dlg(nullptr, downloadDir);
|
||||
if (dlg.exec() == QDialog::Accepted) {
|
||||
return dlg.sceneryPath();
|
||||
}
|
||||
|
|
|
@ -47,6 +47,45 @@ void LaunchConfig::setEnableDisableOption(QString name, bool value)
|
|||
m_values.push_back(Arg((value ? "enable-" : "disable-") + name));
|
||||
}
|
||||
|
||||
QString LaunchConfig::htmlForCommandLine()
|
||||
{
|
||||
QString html;
|
||||
string_list commandLineOpts = flightgear::Options::sharedInstance()->extractOptions();
|
||||
if (!commandLineOpts.empty()) {
|
||||
html += tr("<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
|
||||
reset();
|
||||
collect();
|
||||
|
||||
html += tr("<p>Options set in the launcher:</p>\n");
|
||||
html += "<ul>\n";
|
||||
for (auto arg : 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";
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
QVariant LaunchConfig::getValueForKey(QString group, QString key, QVariant defaultValue) const
|
||||
{
|
||||
QSettings settings;
|
||||
|
|
|
@ -38,6 +38,7 @@ public:
|
|||
|
||||
Q_INVOKABLE void setEnableDisableOption(QString name, bool value);
|
||||
|
||||
Q_INVOKABLE QString htmlForCommandLine();
|
||||
|
||||
|
||||
// ensure a property is /not/ set?
|
||||
|
|
|
@ -49,8 +49,9 @@
|
|||
using namespace simgear::pkg;
|
||||
|
||||
|
||||
LauncherController::LauncherController(QObject *parent) :
|
||||
QObject(parent)
|
||||
LauncherController::LauncherController(QObject *parent, QWindow* window) :
|
||||
QObject(parent),
|
||||
m_window(window)
|
||||
{
|
||||
m_serversModel = new MPServersModel(this);
|
||||
m_location = new LocationController(this);
|
||||
|
@ -91,6 +92,19 @@ LauncherController::LauncherController(QObject *parent) :
|
|||
LocalAircraftCache::instance()->scanDirs();
|
||||
m_aircraftModel->setPackageRoot(globals->packageRoot());
|
||||
|
||||
m_subsystemIdleTimer = new QTimer(this);
|
||||
m_subsystemIdleTimer->setInterval(0);
|
||||
connect(m_subsystemIdleTimer, &QTimer::timeout, []()
|
||||
{globals->get_subsystem_mgr()->update(0.0);});
|
||||
m_subsystemIdleTimer->start();
|
||||
|
||||
QRect winRect= settings.value("window-geometry").toRect();
|
||||
if (winRect.isValid()) {
|
||||
m_window->setGeometry(winRect);
|
||||
} else {
|
||||
m_window->setWidth(600);
|
||||
m_window->setHeight(800);
|
||||
}
|
||||
}
|
||||
|
||||
void LauncherController::initQML()
|
||||
|
@ -171,6 +185,9 @@ void LauncherController::saveSettings()
|
|||
{
|
||||
emit requestSaveState();
|
||||
|
||||
QSettings settings;
|
||||
settings.setValue("window-geometry", m_window->geometry());
|
||||
|
||||
m_aircraftHistory->saveToSettings();
|
||||
m_locationHistory->saveToSettings();
|
||||
}
|
||||
|
@ -448,6 +465,12 @@ void LauncherController::setEnvironmentSummary(QStringList environmentSummary)
|
|||
emit summaryChanged();
|
||||
}
|
||||
|
||||
void LauncherController::fly()
|
||||
{
|
||||
doRun();
|
||||
qApp->exit(1);
|
||||
}
|
||||
|
||||
QStringList LauncherController::combinedSummary() const
|
||||
{
|
||||
return m_settingsSummary + m_environmentSummary;
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
#include <simgear/package/Catalog.hxx>
|
||||
|
||||
// forward decls
|
||||
class QTimer;
|
||||
class QWindow;
|
||||
class AircraftProxyModel;
|
||||
class QmlAircraftInfo;
|
||||
class RecentAircraftModel;
|
||||
|
@ -74,7 +76,7 @@ class LauncherController : public QObject
|
|||
|
||||
Q_PROPERTY(AircraftType aircraftType READ aircraftType NOTIFY selectedAircraftChanged)
|
||||
public:
|
||||
explicit LauncherController(QObject *parent);
|
||||
explicit LauncherController(QObject *parent, QWindow* win);
|
||||
|
||||
void initQML();
|
||||
|
||||
|
@ -174,6 +176,9 @@ signals:
|
|||
* state to persistent storage
|
||||
*/
|
||||
void requestSaveState();
|
||||
|
||||
void viewCommandLine();
|
||||
|
||||
public slots:
|
||||
void setSelectedAircraft(QUrl selectedAircraft);
|
||||
|
||||
|
@ -183,6 +188,8 @@ public slots:
|
|||
|
||||
void setEnvironmentSummary(QStringList environmentSummary);
|
||||
|
||||
void fly();
|
||||
|
||||
private slots:
|
||||
|
||||
void onAircraftInstalledCompleted(QModelIndex index);
|
||||
|
@ -206,6 +213,8 @@ private:
|
|||
void collectAircraftArgs();
|
||||
|
||||
private:
|
||||
QWindow* m_window = nullptr;
|
||||
|
||||
AircraftProxyModel* m_installedAircraftModel;
|
||||
AircraftItemModel* m_aircraftModel;
|
||||
AircraftProxyModel* m_aircraftSearchModel;
|
||||
|
@ -222,6 +231,8 @@ private:
|
|||
QStringList m_settingsSummary, m_environmentSummary;
|
||||
RecentAircraftModel* m_aircraftHistory = nullptr;
|
||||
RecentLocationsModel* m_locationHistory = nullptr;
|
||||
|
||||
QTimer* m_subsystemIdleTimer = nullptr;
|
||||
};
|
||||
|
||||
#endif // LAUNCHERCONTROLLER_HXX
|
||||
|
|
|
@ -6,10 +6,7 @@
|
|||
#include <QDebug>
|
||||
#include <QMenu>
|
||||
#include <QMenuBar>
|
||||
#include <QMenu>
|
||||
|
||||
#include <QPushButton>
|
||||
#include <QDesktopServices>
|
||||
|
||||
#include <QQuickItem>
|
||||
#include <QQmlEngine>
|
||||
|
@ -17,104 +14,51 @@
|
|||
#include <QQmlContext>
|
||||
#include <QQmlError>
|
||||
|
||||
// simgear headers
|
||||
#include <simgear/package/Install.hxx>
|
||||
#include <simgear/environment/metar.hxx>
|
||||
#include <simgear/structure/exception.hxx>
|
||||
|
||||
// FlightGear headers
|
||||
#include <Network/HTTPClient.hxx>
|
||||
#include <Main/globals.hxx>
|
||||
#include <Airports/airport.hxx>
|
||||
#include <Main/options.hxx>
|
||||
#include <Main/fg_init.hxx>
|
||||
#include <Main/fg_props.hxx>
|
||||
#include "version.h"
|
||||
|
||||
// launcher headers
|
||||
#include "QtLauncher.hxx"
|
||||
#include "AircraftModel.hxx"
|
||||
#include "AircraftSearchFilterModel.hxx"
|
||||
#include "DefaultAircraftLocator.hxx"
|
||||
#include "LaunchConfig.hxx"
|
||||
#include "ViewCommandLinePage.hxx"
|
||||
#include "AircraftModel.hxx"
|
||||
#include "LocalAircraftCache.hxx"
|
||||
#include "LauncherController.hxx"
|
||||
#include "DefaultAircraftLocator.hxx"
|
||||
#include "AddOnsController.hxx"
|
||||
#include "CatalogListModel.hxx"
|
||||
#include "LocationController.hxx"
|
||||
|
||||
#include "ui_Launcher.h"
|
||||
|
||||
|
||||
extern void restartTheApp(QStringList fgArgs);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LauncherMainWindow::LauncherMainWindow() :
|
||||
QMainWindow(),
|
||||
m_subsystemIdleTimer(NULL)
|
||||
QQuickView()
|
||||
{
|
||||
m_ui.reset(new Ui::Launcher);
|
||||
m_ui->setupUi(this);
|
||||
setTitle("FlightGear " FLIGHTGEAR_VERSION);
|
||||
|
||||
QMenuBar* mb = menuBar();
|
||||
|
||||
#if !defined(Q_OS_MAC)
|
||||
QMenu* fileMenu = mb->addMenu(tr("File"));
|
||||
QAction* quitAction = fileMenu->addAction(tr("Exit"));
|
||||
connect(quitAction, &QAction::triggered,
|
||||
this, &LauncherMainWindow::onQuit);
|
||||
|
||||
#endif
|
||||
|
||||
m_controller = new LauncherController(this);
|
||||
m_controller = new LauncherController(this, this);
|
||||
m_controller->initQML();
|
||||
|
||||
connect(m_controller, &LauncherController::canFlyChanged,
|
||||
this, &LauncherMainWindow::onCanFlyChanged);
|
||||
#if defined(Q_OS_MAC)
|
||||
QMenuBar* mb = new QMenuBar();
|
||||
|
||||
QMenu* toolsMenu = mb->addMenu(tr("Tools"));
|
||||
QAction* restoreDefaultsAction = toolsMenu->addAction(tr("Restore defaults..."));
|
||||
connect(restoreDefaultsAction, &QAction::triggered,
|
||||
this, &LauncherMainWindow::onRestoreDefaults);
|
||||
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* 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);
|
||||
|
||||
|
||||
m_subsystemIdleTimer = new QTimer(this);
|
||||
m_subsystemIdleTimer->setInterval(0);
|
||||
connect(m_subsystemIdleTimer, &QTimer::timeout,
|
||||
this, &LauncherMainWindow::onSubsytemIdleTimeout);
|
||||
m_subsystemIdleTimer->start();
|
||||
|
||||
connect(m_ui->flyButton, SIGNAL(clicked()), this, SLOT(onRun()));
|
||||
connect(m_ui->summaryButton, &QAbstractButton::clicked, this, &LauncherMainWindow::onClickToolboxButton);
|
||||
connect(m_ui->aircraftButton, &QAbstractButton::clicked, this, &LauncherMainWindow::onClickToolboxButton);
|
||||
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->addOnsButton, &QAbstractButton::clicked, this, &LauncherMainWindow::onClickToolboxButton);
|
||||
QAction* viewCommandLineAction = toolsMenu->addAction(tr("View command-line"));
|
||||
connect(viewCommandLineAction, &QAction::triggered,
|
||||
m_controller, &LauncherController::viewCommandLine);
|
||||
#endif
|
||||
|
||||
QAction* qa = new QAction(this);
|
||||
qa->setShortcut(QKeySequence("Ctrl+Q"));
|
||||
connect(qa, &QAction::triggered, this, &LauncherMainWindow::onQuit);
|
||||
addAction(qa);
|
||||
|
||||
m_viewCommandLinePage = new ViewCommandLinePage;
|
||||
m_viewCommandLinePage->setLaunchConfig(m_controller->config());
|
||||
m_ui->stack->addWidget(m_viewCommandLinePage);
|
||||
|
||||
QSettings settings;
|
||||
restoreGeometry(settings.value("window-geometry").toByteArray());
|
||||
|
||||
m_controller->restoreSettings();
|
||||
flightgear::launcherSetSceneryPaths();
|
||||
|
@ -130,83 +74,23 @@ LauncherMainWindow::LauncherMainWindow() :
|
|||
const QString osName("unix");
|
||||
#endif
|
||||
|
||||
/////////////
|
||||
// aircraft
|
||||
m_ui->aircraftList->setResizeMode(QQuickWidget::SizeRootObjectToView);
|
||||
setResizeMode(QQuickView::SizeRootObjectToView);
|
||||
engine()->addImportPath("qrc:///");
|
||||
|
||||
m_ui->aircraftList->engine()->addImportPath("qrc:///");
|
||||
m_ui->aircraftList->engine()->rootContext()->setContextProperty("_launcher", m_controller);
|
||||
m_ui->aircraftList->engine()->rootContext()->setContextProperty("_addOns", addOnsCtl);
|
||||
QQmlContext* ctx = rootContext();
|
||||
ctx->setContextProperty("_launcher", m_controller);
|
||||
ctx->setContextProperty("_addOns", addOnsCtl);
|
||||
ctx->setContextProperty("_config", m_controller->config());
|
||||
ctx->setContextProperty("_location", m_controller->location());
|
||||
ctx->setContextProperty("_osName", osName);
|
||||
|
||||
connect( m_ui->aircraftList, &QQuickWidget::statusChanged,
|
||||
this, &LauncherMainWindow::onQuickStatusChanged);
|
||||
m_ui->aircraftList->setSource(QUrl("qrc:///qml/AircraftList.qml"));
|
||||
|
||||
/////////////
|
||||
// location
|
||||
m_ui->location->setResizeMode(QQuickWidget::SizeRootObjectToView);
|
||||
m_ui->location->engine()->addImportPath("qrc:///");
|
||||
m_ui->location->engine()->rootContext()->setContextProperty("_launcher", m_controller);
|
||||
m_ui->location->engine()->rootContext()->setContextProperty("_config", m_controller->config());
|
||||
m_ui->location->engine()->rootContext()->setContextProperty("_location", m_controller->location());
|
||||
connect( m_ui->location, &QQuickWidget::statusChanged,
|
||||
this, &LauncherMainWindow::onQuickStatusChanged);
|
||||
m_ui->location->setSource(QUrl("qrc:///qml/Location.qml"));
|
||||
|
||||
/////////////
|
||||
// settings
|
||||
m_ui->settings->engine()->addImportPath("qrc:///");
|
||||
QQmlContext* settingsContext = m_ui->settings->engine()->rootContext();
|
||||
settingsContext->setContextProperty("_launcher", m_controller);
|
||||
settingsContext->setContextProperty("_osName", osName);
|
||||
settingsContext->setContextProperty("_config", m_controller->config());
|
||||
|
||||
m_ui->settings->setResizeMode(QQuickWidget::SizeRootObjectToView);
|
||||
connect( m_ui->settings, &QQuickWidget::statusChanged,
|
||||
this, &LauncherMainWindow::onQuickStatusChanged);
|
||||
m_ui->settings->setSource(QUrl("qrc:///qml/Settings.qml"));
|
||||
|
||||
// environemnt
|
||||
m_ui->environmentPage->engine()->addImportPath("qrc:///");
|
||||
m_ui->environmentPage->engine()->rootContext()->setContextProperty("_launcher", m_controller);
|
||||
auto weatherScenariosModel = new flightgear::WeatherScenariosModel(this);
|
||||
m_ui->environmentPage->engine()->rootContext()->setContextProperty("_weatherScenarios", weatherScenariosModel);
|
||||
m_ui->environmentPage->engine()->rootContext()->setContextProperty("_config", m_controller->config());
|
||||
|
||||
m_ui->environmentPage->setResizeMode(QQuickWidget::SizeRootObjectToView);
|
||||
|
||||
connect( m_ui->environmentPage, &QQuickWidget::statusChanged,
|
||||
this, &LauncherMainWindow::onQuickStatusChanged);
|
||||
m_ui->environmentPage->setSource(QUrl("qrc:///qml/Environment.qml"));
|
||||
|
||||
// summary
|
||||
m_ui->summary->engine()->addImportPath("qrc:///");
|
||||
m_ui->summary->engine()->rootContext()->setContextProperty("_launcher", m_controller);
|
||||
m_ui->summary->engine()->rootContext()->setContextProperty("_config", m_controller->config());
|
||||
|
||||
m_ui->summary->setResizeMode(QQuickWidget::SizeRootObjectToView);
|
||||
|
||||
connect( m_ui->summary, &QQuickWidget::statusChanged,
|
||||
this, &LauncherMainWindow::onQuickStatusChanged);
|
||||
m_ui->summary->setSource(QUrl("qrc:///qml/Summary.qml"));
|
||||
|
||||
|
||||
// addOns
|
||||
m_ui->addOns->engine()->addImportPath("qrc:///");
|
||||
m_ui->addOns->engine()->rootContext()->setContextProperty("_launcher", m_controller);
|
||||
m_ui->addOns->engine()->rootContext()->setContextProperty("_addOns", addOnsCtl);
|
||||
m_ui->addOns->setResizeMode(QQuickWidget::SizeRootObjectToView);
|
||||
m_ui->addOns->setSource(QUrl("qrc:///qml/AddOns.qml"));
|
||||
//////////////////////////
|
||||
ctx->setContextProperty("_weatherScenarios", weatherScenariosModel);
|
||||
|
||||
setSource(QUrl("qrc:///qml/Launcher.qml"));
|
||||
}
|
||||
|
||||
void LauncherMainWindow::saveSettings()
|
||||
{
|
||||
QSettings settings;
|
||||
settings.setValue("window-geometry", saveGeometry());
|
||||
}
|
||||
|
||||
#if 0
|
||||
void LauncherMainWindow::onQuickStatusChanged(QQuickWidget::Status status)
|
||||
{
|
||||
if (status == QQuickWidget::Error) {
|
||||
|
@ -224,11 +108,7 @@ void LauncherMainWindow::onQuickStatusChanged(QQuickWidget::Status status)
|
|||
+ errorString);
|
||||
}
|
||||
}
|
||||
|
||||
void LauncherMainWindow::onCanFlyChanged()
|
||||
{
|
||||
m_ui->flyButton->setEnabled(m_controller->canFly());
|
||||
}
|
||||
#endif
|
||||
|
||||
LauncherMainWindow::~LauncherMainWindow()
|
||||
{
|
||||
|
@ -236,6 +116,7 @@ LauncherMainWindow::~LauncherMainWindow()
|
|||
|
||||
bool LauncherMainWindow::execInApp()
|
||||
{
|
||||
#if 0
|
||||
m_inAppMode = true;
|
||||
m_ui->addOnsButton->hide();
|
||||
m_ui->settingsButton->hide();
|
||||
|
@ -250,22 +131,10 @@ bool LauncherMainWindow::execInApp()
|
|||
}
|
||||
|
||||
return m_accepted;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LauncherMainWindow::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
qApp->exit(-1);
|
||||
}
|
||||
|
||||
|
||||
void LauncherMainWindow::onRun()
|
||||
{
|
||||
m_controller->doRun();
|
||||
saveSettings();
|
||||
qApp->exit(1);
|
||||
}
|
||||
#if 0
|
||||
|
||||
void LauncherMainWindow::onApply()
|
||||
{
|
||||
|
@ -274,6 +143,7 @@ void LauncherMainWindow::onApply()
|
|||
m_accepted = true;
|
||||
m_runInApp = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
void LauncherMainWindow::onQuit()
|
||||
{
|
||||
|
@ -286,7 +156,7 @@ void LauncherMainWindow::onQuit()
|
|||
|
||||
void LauncherMainWindow::onRestoreDefaults()
|
||||
{
|
||||
QMessageBox mbox(this);
|
||||
QMessageBox mbox;
|
||||
mbox.setText(tr("Restore all settings to defaults?"));
|
||||
mbox.setInformativeText(tr("Restoring settings to their defaults may affect available add-ons such as scenery or aircraft."));
|
||||
QPushButton* quitButton = mbox.addButton(tr("Restore and restart now"), QMessageBox::YesRole);
|
||||
|
@ -308,30 +178,6 @@ 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::onClickToolboxButton()
|
||||
{
|
||||
int pageIndex = sender()->property("pageIndex").toInt();
|
||||
m_ui->stack->setCurrentIndex(pageIndex);
|
||||
Q_FOREACH (ToolboxButton* tb, findChildren<ToolboxButton*>()) {
|
||||
tb->setChecked(tb->property("pageIndex").toInt() == pageIndex);
|
||||
}
|
||||
saveSettings();
|
||||
}
|
||||
|
||||
void LauncherMainWindow::onSubsytemIdleTimeout()
|
||||
{
|
||||
globals->get_subsystem_mgr()->update(0.0);
|
||||
}
|
||||
|
||||
void LauncherMainWindow::onChangeDataDir()
|
||||
{
|
||||
|
@ -344,7 +190,7 @@ void LauncherMainWindow::onChangeDataDir()
|
|||
currentLocText = tr("Currently using location: %1").arg(root);
|
||||
}
|
||||
|
||||
QMessageBox mbox(this);
|
||||
QMessageBox mbox;
|
||||
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) "
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
//
|
||||
// Written by James Turner, started October 2015.
|
||||
//
|
||||
// Copyright (C) 2015 James Turner <zakalawe@mac.com>
|
||||
// Copyright (C) 2018 James Turner <james@flightgear.org>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
|
@ -21,18 +21,13 @@
|
|||
#ifndef LAUNCHER_MAIN_WINDOW_HXX
|
||||
#define LAUNCHER_MAIN_WINDOW_HXX
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QScopedPointer>
|
||||
#include <QStringList>
|
||||
#include <QModelIndex>
|
||||
#include <QTimer>
|
||||
#include <QUrl>
|
||||
#include <QQuickWidget>
|
||||
#include <QQuickView>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class Launcher;
|
||||
}
|
||||
|
||||
class QModelIndex;
|
||||
class QQmlEngine;
|
||||
|
@ -41,7 +36,7 @@ class ViewCommandLinePage;
|
|||
class QQuickItem;
|
||||
class LauncherController;
|
||||
|
||||
class LauncherMainWindow : public QMainWindow
|
||||
class LauncherMainWindow : public QQuickView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
@ -54,47 +49,25 @@ public:
|
|||
|
||||
|
||||
protected:
|
||||
virtual void closeEvent(QCloseEvent *event) override;
|
||||
|
||||
private slots:
|
||||
// run is used when the launcher is invoked before the main app is
|
||||
// started
|
||||
void onRun();
|
||||
|
||||
// apply is used in-app, where we must set properties and trigger
|
||||
// a reset; setting command line options won't help us.
|
||||
void onApply();
|
||||
|
||||
void onQuit();
|
||||
|
||||
void onSubsytemIdleTimeout();
|
||||
|
||||
|
||||
void onRestoreDefaults();
|
||||
void onViewCommandLine();
|
||||
// void onViewCommandLine();
|
||||
|
||||
void onClickToolboxButton();
|
||||
void onQuit();
|
||||
|
||||
|
||||
void onQuickStatusChanged(QQuickWidget::Status status);
|
||||
|
||||
void onCanFlyChanged();
|
||||
// void onQuickStatusChanged(QQuickWidget::Status status);
|
||||
|
||||
void onChangeDataDir();
|
||||
|
||||
private:
|
||||
|
||||
LauncherController* m_controller;
|
||||
QScopedPointer<Ui::Launcher> m_ui;
|
||||
QTimer* m_subsystemIdleTimer;
|
||||
|
||||
bool m_inAppMode = false;
|
||||
bool m_runInApp = false;
|
||||
bool m_accepted = false;
|
||||
|
||||
ViewCommandLinePage* m_viewCommandLinePage = nullptr;
|
||||
|
||||
void restoreSettings();
|
||||
void saveSettings();
|
||||
};
|
||||
|
||||
#endif // of LAUNCHER_MAIN_WINDOW_HXX
|
||||
|
|
|
@ -370,6 +370,8 @@ LocationController::LocationController(QObject *parent) :
|
|||
m_searchModel = new NavSearchModel;
|
||||
|
||||
m_detailQml = new QmlPositioned(this);
|
||||
m_baseQml = new QmlPositioned(this);
|
||||
|
||||
// chain location and offset updated to description
|
||||
connect(this, &LocationController::baseLocationChanged,
|
||||
this, &LocationController::descriptionChanged);
|
||||
|
@ -453,11 +455,23 @@ void LocationController::setBaseGeod(QmlGeod geod)
|
|||
|
||||
void LocationController::setBaseLocation(QmlPositioned* pos)
|
||||
{
|
||||
if (!pos) {
|
||||
m_location.clear();
|
||||
m_detailLocation.clear();
|
||||
m_detailQml->setGuid(0);
|
||||
m_baseQml->setGuid(0);
|
||||
m_airportLocation.clear();
|
||||
m_locationIsLatLon = false;
|
||||
emit baseLocationChanged();
|
||||
return;
|
||||
}
|
||||
|
||||
if (pos->inner() == m_location)
|
||||
return;
|
||||
|
||||
m_locationIsLatLon = false;
|
||||
m_location = pos->inner();
|
||||
m_baseQml->setGuid(pos->guid());
|
||||
m_detailLocation.clear();
|
||||
m_detailQml->setGuid(0);
|
||||
|
||||
|
@ -610,6 +624,11 @@ QmlPositioned *LocationController::detail() const
|
|||
return m_detailQml;
|
||||
}
|
||||
|
||||
QmlPositioned *LocationController::baseLocation() const
|
||||
{
|
||||
return m_baseQml;
|
||||
}
|
||||
|
||||
void LocationController::setOffsetRadial(int offsetRadial)
|
||||
{
|
||||
if (m_offsetRadial == offsetRadial)
|
||||
|
@ -679,6 +698,7 @@ void LocationController::restoreLocation(QVariantMap l)
|
|||
if (FGPositioned::isAirportType(m_location.ptr())) {
|
||||
m_airportLocation = static_cast<FGAirport*>(m_location.ptr());
|
||||
}
|
||||
m_baseQml->setInner(m_location);
|
||||
}
|
||||
|
||||
if (l.contains("altitude-type")) {
|
||||
|
@ -716,6 +736,10 @@ void LocationController::restoreLocation(QVariantMap l)
|
|||
m_detailLocation = m_airportLocation->groundNetwork()->findParkingByName(parking.toStdString());
|
||||
}
|
||||
|
||||
if (m_detailLocation) {
|
||||
m_detailQml->setInner(m_detailLocation);
|
||||
}
|
||||
|
||||
m_onFinal = l.value("location-on-final").toBool();
|
||||
m_offsetNm = l.value("location-apt-final-distance").toInt();
|
||||
} // of location is an airport
|
||||
|
|
|
@ -67,7 +67,9 @@ class LocationController : public QObject
|
|||
Q_PROPERTY(bool tuneNAV1 READ tuneNAV1 WRITE setTuneNAV1 NOTIFY configChanged)
|
||||
Q_PROPERTY(QmlGeod baseGeod READ baseGeod WRITE setBaseGeod NOTIFY baseLocationChanged)
|
||||
|
||||
Q_PROPERTY(QmlPositioned* base READ baseLocation CONSTANT)
|
||||
Q_PROPERTY(QmlPositioned* detail READ detail CONSTANT)
|
||||
Q_PROPERTY(bool isBaseLatLon READ isBaseLatLon NOTIFY baseLocationChanged)
|
||||
public:
|
||||
explicit LocationController(QObject *parent = nullptr);
|
||||
~LocationController();
|
||||
|
@ -152,11 +154,18 @@ public:
|
|||
|
||||
QmlPositioned* detail() const;
|
||||
|
||||
QmlPositioned* baseLocation() const;
|
||||
|
||||
bool useAvailableParking() const
|
||||
{
|
||||
return m_useAvailableParking;
|
||||
}
|
||||
|
||||
bool isBaseLatLon() const
|
||||
{
|
||||
return m_locationIsLatLon;
|
||||
}
|
||||
|
||||
public slots:
|
||||
void setOffsetRadial(int offsetRadial);
|
||||
|
||||
|
@ -203,6 +212,7 @@ private:
|
|||
FGPositionedList m_recentLocations;
|
||||
LaunchConfig* m_config = nullptr;
|
||||
QmlPositioned* m_detailQml = nullptr;
|
||||
QmlPositioned* m_baseQml = nullptr;
|
||||
|
||||
bool m_offsetEnabled = false;
|
||||
int m_offsetRadial = 0;
|
||||
|
|
|
@ -10,9 +10,17 @@ Rectangle {
|
|||
|
||||
readonly property bool isActive: (state != "start")
|
||||
Behavior on height {
|
||||
enabled: false // disable to prevent animation on load
|
||||
id: heightBehaviour
|
||||
NumberAnimation { duration: 200; }
|
||||
}
|
||||
|
||||
Timer { // ugly: timer to enable the animation after loading is done
|
||||
onTriggered: heightBehaviour.enabled = true;
|
||||
running: true
|
||||
interval: 5
|
||||
}
|
||||
|
||||
Column {
|
||||
id: column
|
||||
width: parent.width
|
||||
|
|
|
@ -36,14 +36,14 @@ Item {
|
|||
anchors.rightMargin: Style.margin
|
||||
spacing: Style.margin
|
||||
|
||||
Text {
|
||||
StyledText {
|
||||
font.pixelSize: Style.subHeadingFontPixelSize
|
||||
font.bold: true
|
||||
width: parent.width
|
||||
text: model.name
|
||||
}
|
||||
|
||||
Text {
|
||||
StyledText {
|
||||
visible: model.status === CatalogListModel.Ok
|
||||
width: parent.width
|
||||
text: model.description
|
||||
|
@ -62,7 +62,7 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
StyledText {
|
||||
width: parent.width
|
||||
text: model.url
|
||||
}
|
||||
|
@ -119,33 +119,12 @@ Item {
|
|||
//////////////////////////////////////////////////////////////////
|
||||
// catalogs //////////////////////////////////////////////////////
|
||||
|
||||
Item {
|
||||
id: catalogHeaderItem
|
||||
width: parent.width
|
||||
height: catalogHeadingText.height + catalogDescriptionText.height + Style.margin
|
||||
|
||||
Text {
|
||||
id: catalogHeadingText
|
||||
text: qsTr("Aircraft hangars")
|
||||
font.pixelSize: Style.headingFontPixelSize
|
||||
width: parent.width
|
||||
}
|
||||
|
||||
Text {
|
||||
id: catalogDescriptionText
|
||||
text: qsTr("Aircraft hangars are managed collections of aircraft, which can be " +
|
||||
"downloaded, installed and updated inside FlightGear.")
|
||||
anchors {
|
||||
top: catalogHeadingText.bottom
|
||||
topMargin: Style.margin
|
||||
}
|
||||
|
||||
width: parent.width
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
|
||||
} // of catalogs header item
|
||||
AddOnsHeader {
|
||||
id: catalogHeader
|
||||
title: qsTr("Aircraft hangars")
|
||||
description: qsTr("Aircraft hangars are managed collections of aircraft, which can be " +
|
||||
"downloaded, installed and updated inside FlightGear.")
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
|
@ -191,49 +170,19 @@ Item {
|
|||
height: Style.margin * 2
|
||||
}
|
||||
|
||||
Item {
|
||||
id: aircraftHeaderItem
|
||||
width: parent.width
|
||||
height: aircraftHeading.height + aircraftDescriptionText.height + Style.margin
|
||||
|
||||
Text {
|
||||
id: aircraftHeading
|
||||
text: qsTr("Additional aircraft folders")
|
||||
font.pixelSize: Style.headingFontPixelSize
|
||||
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: addAircraftPathButton.left
|
||||
rightMargin: Style.margin
|
||||
AddOnsHeader {
|
||||
id: aircraftHeader
|
||||
title: qsTr("Additional aircraft folders")
|
||||
description: qsTr("To use aircraft you download yourself, FlightGear needs to " +
|
||||
"know the folder(s) containing the aircraft data.")
|
||||
showAddButton: true
|
||||
onAdd: {
|
||||
var newPath =_addOns.addAircraftPath();
|
||||
if (newPath !== "") {
|
||||
_addOns.aircraftPaths.push(newPath)
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
id: aircraftDescriptionText
|
||||
text: qsTr("To use aircraft you download yourself, FlightGear needs to " +
|
||||
"know the folder(s) containing the aircraft data.")
|
||||
anchors {
|
||||
top: aircraftHeading.bottom
|
||||
topMargin: Style.margin
|
||||
left: parent.left
|
||||
right: addAircraftPathButton.left
|
||||
rightMargin: Style.margin
|
||||
}
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
AddButton {
|
||||
id: addAircraftPathButton
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
onClicked: {
|
||||
var newPath =_addOns.addAircraftPath();
|
||||
if (newPath !== "") {
|
||||
_addOns.aircraftPaths.push(newPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
} // of aircraft header item
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
|
@ -270,7 +219,7 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
StyledText {
|
||||
visible: (aircraftPathsRepeater.count == 0)
|
||||
width: parent.width
|
||||
text : qsTr("No custom aircraft paths are configured.");
|
||||
|
@ -288,51 +237,20 @@ Item {
|
|||
height: Style.margin * 2
|
||||
}
|
||||
|
||||
Item {
|
||||
id: sceneryHeaderItem
|
||||
width: parent.width
|
||||
height: sceneryHeading.height + sceneryDescriptionText.height + Style.margin
|
||||
|
||||
Text {
|
||||
id: sceneryHeading
|
||||
text: qsTr("Additional scenery folders")
|
||||
font.pixelSize: Style.headingFontPixelSize
|
||||
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: addSceneryPathButton.left
|
||||
rightMargin: Style.margin
|
||||
AddOnsHeader {
|
||||
id: sceneryHeader
|
||||
title: qsTr("Additional scenery folders")
|
||||
description: qsTr("To use scenery you download yourself, FlightGear needs " +
|
||||
"to know the folders containing the scenery data. " +
|
||||
"Adjust the order of the list to control which scenery is used in a region.");
|
||||
showAddButton: true
|
||||
onAdd: {
|
||||
var newPath =_addOns.addSceneryPath();
|
||||
if (newPath !== "") {
|
||||
_addOns.sceneryPaths.push(newPath)
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
id: sceneryDescriptionText
|
||||
text: qsTr("To use scenery you download yourself, FlightGear needs " +
|
||||
"to know the folders containing the scenery data. " +
|
||||
"Adjust the order of the list to control which scenery is used in a region.");
|
||||
anchors {
|
||||
top: sceneryHeading.bottom
|
||||
topMargin: Style.margin
|
||||
left: parent.left
|
||||
right: addSceneryPathButton.left
|
||||
rightMargin: Style.margin
|
||||
}
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
AddButton {
|
||||
id: addSceneryPathButton
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
onClicked: {
|
||||
var newPath =_addOns.addSceneryPath();
|
||||
if (newPath !== "") {
|
||||
_addOns.sceneryPaths.push(newPath)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} // of aircraft header item
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
|
@ -370,7 +288,7 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
StyledText {
|
||||
visible: (sceneryPathsRepeater.count == 0)
|
||||
width: parent.width
|
||||
text : qsTr("No custom scenery paths are configured.");
|
||||
|
@ -400,7 +318,7 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
StyledText {
|
||||
id: installTarballText
|
||||
anchors {
|
||||
left: installTarballButton.right
|
||||
|
|
53
src/GUI/qml/AddOnsHeader.qml
Normal file
53
src/GUI/qml/AddOnsHeader.qml
Normal file
|
@ -0,0 +1,53 @@
|
|||
import QtQuick 2.4
|
||||
import "."
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property bool showAddButton: false
|
||||
|
||||
property alias title: headerTitle.text
|
||||
property alias description: description.text
|
||||
signal add();
|
||||
|
||||
implicitWidth: parent.width
|
||||
implicitHeight: headerRect.height + Style.margin + description.height
|
||||
|
||||
Rectangle {
|
||||
id: headerRect
|
||||
width: parent.width
|
||||
height: headerTitle.height + (Style.margin * 2)
|
||||
|
||||
color: Style.themeColor
|
||||
border.width: 1
|
||||
border.color: Style.frameColor
|
||||
|
||||
Text {
|
||||
id: headerTitle
|
||||
color: "white"
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
font.bold: true
|
||||
font.pixelSize: Style.subHeadingFontPixelSize
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: Style.inset
|
||||
|
||||
}
|
||||
|
||||
AddButton {
|
||||
id: addButton
|
||||
visible: root.showAddButton
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: Style.margin
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
onClicked: root.add()
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
id: description
|
||||
width: parent.width
|
||||
anchors.top: headerRect.bottom
|
||||
anchors.topMargin: Style.margin
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
}
|
|
@ -6,6 +6,10 @@ Item
|
|||
{
|
||||
id: root
|
||||
|
||||
Component.onCompleted: {
|
||||
aircraftList.updateSelectionFromLauncher();
|
||||
}
|
||||
|
||||
Rectangle
|
||||
{
|
||||
id: tabBar
|
||||
|
|
|
@ -8,6 +8,7 @@ Text {
|
|||
property bool clickable: true
|
||||
property color baseTextColor: Style.baseTextColor
|
||||
color: mouse.containsMouse ? Style.themeColor : baseTextColor
|
||||
font.pixelSize: Style.baseFontPixelSize
|
||||
|
||||
MouseArea {
|
||||
id: mouse
|
||||
|
|
117
src/GUI/qml/Launcher.qml
Normal file
117
src/GUI/qml/Launcher.qml
Normal file
|
@ -0,0 +1,117 @@
|
|||
import QtQuick 2.4
|
||||
import "."
|
||||
|
||||
Item {
|
||||
id: root
|
||||
// order of this model sets the order of buttons in the sidebar
|
||||
ListModel {
|
||||
id: pagesModel
|
||||
ListElement { title: qsTr("Summary"); pageSource: "qrc:///qml/Summary.qml"; iconPath: "qrc:///toolbox-summary"; state:"loader" }
|
||||
ListElement { title: qsTr("Aircraft"); pageSource: "qrc:///qml/AircraftList.qml"; iconPath: "qrc:///toolbox-aircraft"; state:"loader" }
|
||||
ListElement { title: qsTr("Location"); pageSource: "qrc:///qml/Location.qml"; iconPath: "qrc:///toolbox-location"; state:"loader" }
|
||||
|
||||
// due to some design stupidity by James, we can't use the Loader mechanism for these pages; they need to exist
|
||||
// permanently so that collecting args works. So we instantiate them down below, and toggle the visiblity
|
||||
// of them and the loader using a state.
|
||||
|
||||
ListElement { title: qsTr("Environment"); pageSource: ""; iconPath: "qrc:///toolbox-environment"; state:"environment" }
|
||||
ListElement { title: qsTr("Settings"); pageSource: ""; iconPath: "qrc:///toolbox-settings"; state:"settings" }
|
||||
|
||||
ListElement { title: qsTr("Add-ons"); pageSource: "qrc:///qml/AddOns.qml"; iconPath: "qrc:///toolbox-addons"; state:"loader" }
|
||||
|
||||
}
|
||||
|
||||
states: [
|
||||
State {
|
||||
name: "loader"
|
||||
PropertyChanges { target: pageLoader; visible: true }
|
||||
PropertyChanges { target: settings; visible: false }
|
||||
PropertyChanges { target: environment; visible: false }
|
||||
},
|
||||
|
||||
State {
|
||||
name: "settings"
|
||||
PropertyChanges { target: pageLoader; visible: false }
|
||||
PropertyChanges { target: settings; visible: true }
|
||||
PropertyChanges { target: environment; visible: false }
|
||||
},
|
||||
|
||||
State {
|
||||
name: "environment"
|
||||
PropertyChanges { target: pageLoader; visible: false }
|
||||
PropertyChanges { target: settings; visible: false }
|
||||
PropertyChanges { target: environment; visible: true }
|
||||
}
|
||||
]
|
||||
|
||||
Connections {
|
||||
target: _launcher
|
||||
onViewCommandLine: {
|
||||
sidebar.selectedPage = -1;
|
||||
pageLoader.source = "qrc:///qml/ViewCommandLine.qml"
|
||||
root.state = "loader";
|
||||
}
|
||||
}
|
||||
|
||||
Sidebar {
|
||||
id: sidebar
|
||||
width: Style.strutSize * 2
|
||||
height: parent.height
|
||||
z: 1
|
||||
pagesModel: pagesModel
|
||||
selectedPage: 0 // open on the summary page
|
||||
|
||||
onSelectPage: {
|
||||
pageLoader.source = pageSource
|
||||
root.state = pagesModel.get(selectedPage).state
|
||||
}
|
||||
}
|
||||
|
||||
Settings {
|
||||
id: settings
|
||||
|
||||
height: parent.height
|
||||
anchors {
|
||||
left: sidebar.right
|
||||
right: parent.right
|
||||
}
|
||||
}
|
||||
|
||||
Environment {
|
||||
id: environment
|
||||
|
||||
height: parent.height
|
||||
anchors {
|
||||
left: sidebar.right
|
||||
right: parent.right
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: pageLoader
|
||||
height: parent.height
|
||||
anchors {
|
||||
left: sidebar.right
|
||||
right: parent.right
|
||||
}
|
||||
|
||||
source: "qrc:///qml/Summary.qml"
|
||||
}
|
||||
|
||||
function selectPage(index)
|
||||
{
|
||||
sidebar.setSelectedPage(index);
|
||||
var page = pagesModel.get(index);
|
||||
pageLoader.source = page.pageSource
|
||||
root.state = page.state
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: pageLoader.item
|
||||
ignoreUnknownSignals: true
|
||||
onShowSelectedAircraft: root.selectPage(1)
|
||||
onShowSelectedLocation: root.selectPage(2)
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -12,6 +12,7 @@ Item {
|
|||
function backToSearch()
|
||||
{
|
||||
detailLoader.sourceComponent = null
|
||||
_location.setBaseLocation(null)
|
||||
}
|
||||
|
||||
function selectLocation(guid, type)
|
||||
|
@ -28,7 +29,21 @@ Item {
|
|||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
_location.showHistoryInSearchModel()
|
||||
// important so we can leave the location page and return to it,
|
||||
// preserving the state
|
||||
if (_location.base.valid) {
|
||||
selectedLocation.guid = _location.base.guid;
|
||||
|
||||
if (selectedLocation.isAirportType) {
|
||||
detailLoader.sourceComponent = airportDetails
|
||||
} else {
|
||||
detailLoader.sourceComponent = navaidDetails
|
||||
}
|
||||
} else if (_location.isBaseLatLon) {
|
||||
detailLoader.sourceComponent = navaidDetails
|
||||
} else {
|
||||
_location.showHistoryInSearchModel();
|
||||
}
|
||||
}
|
||||
|
||||
Positioned {
|
||||
|
@ -42,7 +57,6 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
Component {
|
||||
id: navaidDetails
|
||||
LocationNavaidView {
|
||||
|
@ -94,7 +108,7 @@ Item {
|
|||
image: model.icon
|
||||
}
|
||||
|
||||
Text {
|
||||
StyledText {
|
||||
id: delegateText
|
||||
anchors.right: parent.right
|
||||
anchors.left: delegateIcon.right
|
||||
|
@ -131,11 +145,21 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
id: headerText
|
||||
text: qsTr("Location")
|
||||
font.pixelSize: Style.headingFontPixelSize
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: Style.inset
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: Style.margin
|
||||
}
|
||||
|
||||
SearchButton {
|
||||
id: searchButton
|
||||
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.top: headerText.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.margins: Style.margin
|
||||
|
||||
|
@ -151,7 +175,6 @@ Item {
|
|||
|
||||
var geod = _location.parseStringAsGeod(term)
|
||||
if (geod.valid) {
|
||||
console.info("REMOVE-ME: Setting lat-lon location")
|
||||
_location.baseGeod = geod
|
||||
selectedLocation.guid = 0;
|
||||
detailLoader.sourceComponent = navaidDetails
|
||||
|
@ -163,7 +186,7 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
StyledText {
|
||||
id: searchHelpText
|
||||
anchors.right: parent.right
|
||||
anchors.top: searchButton.bottom
|
||||
|
@ -248,14 +271,12 @@ Item {
|
|||
}
|
||||
|
||||
Button {
|
||||
id: backButton
|
||||
|
||||
anchors { left: parent.left; top: parent.top; margins: Style.margin }
|
||||
width: Style.strutSize
|
||||
visible: detailLoader.visible
|
||||
|
||||
id: backButton
|
||||
text: "< Back"
|
||||
onClicked: {
|
||||
root.backToSearch();
|
||||
}
|
||||
onClicked: root.backToSearch();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,6 +77,7 @@ Item {
|
|||
color: "white"
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
font.bold: true
|
||||
font.pixelSize: Style.subHeadingFontPixelSize
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: Style.inset
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@ SettingControl {
|
|||
// value
|
||||
property bool setIfDefault: false
|
||||
|
||||
implicitHeight: toggle.height + Style.margin + description.height
|
||||
|
||||
ToggleSwitch {
|
||||
id: toggle
|
||||
label: root.label
|
||||
|
@ -37,4 +39,9 @@ SettingControl {
|
|||
_config.setEnableDisableOption(option, checked)
|
||||
}
|
||||
}
|
||||
|
||||
function setValue(newValue)
|
||||
{
|
||||
toggle.setValue(newValue)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,8 +15,8 @@ Item {
|
|||
// define a new visiblity property so we can control built-in 'visible' ourselves
|
||||
property bool hidden: false
|
||||
|
||||
implicitHeight: childrenRect.height
|
||||
implicitWidth: parent.width // which is assumed to be the section
|
||||
|
||||
visible: {
|
||||
// override so advanced items show up in searches
|
||||
if (_launcher.isSearchActive && _launcher.matchesSearch(_launcher.settingsSearchTerm, keywords)) {
|
||||
|
@ -86,8 +86,13 @@ Item {
|
|||
var rawValue = _config.getValueForKey("", root.setting, defaultValue);
|
||||
// console.warn("restoring state for " + root.setting + ", got raw value " + rawValue + " with type " + typeof(rawValue))
|
||||
if (rawValue !== undefined) {
|
||||
// root["value"] = rawValue
|
||||
this.value = rawValue
|
||||
setValue(rawValue);
|
||||
}
|
||||
}
|
||||
|
||||
function setValue(newValue)
|
||||
{
|
||||
// hook method so controls can override
|
||||
this.value = newValue
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,8 @@ import "."
|
|||
|
||||
SettingControl {
|
||||
id: root
|
||||
implicitHeight: childrenRect.height
|
||||
|
||||
implicitHeight: edit.height + Style.margin + description.height
|
||||
|
||||
property alias placeholder: edit.placeholder
|
||||
property alias validation: edit.validator
|
||||
|
|
|
@ -5,7 +5,7 @@ import "."
|
|||
|
||||
SettingControl {
|
||||
id: root
|
||||
implicitHeight: childrenRect.height
|
||||
implicitHeight: defaultButton.height + Style.margin + description.height
|
||||
|
||||
property alias label: label.text
|
||||
property string path
|
||||
|
|
|
@ -3,6 +3,7 @@ import FlightGear.Launcher 1.0
|
|||
import "."
|
||||
|
||||
Item {
|
||||
id: settings
|
||||
Rectangle {
|
||||
// search 'dimming' rectangle
|
||||
visible: _launcher.isSearchActive
|
||||
|
@ -21,14 +22,21 @@ Item {
|
|||
|
||||
Connections {
|
||||
target: _launcher
|
||||
onRequestSaveState: {
|
||||
mpSettings.saveState();
|
||||
downloadSettings.saveState();
|
||||
generalSettings.saveState();
|
||||
renderSection.saveState();
|
||||
extraArgsSection.saveState();
|
||||
windowSettings.saveState();
|
||||
}
|
||||
onRequestSaveState: settings.saveState();
|
||||
}
|
||||
|
||||
Component.onDestruction: {
|
||||
settings.saveState();
|
||||
}
|
||||
|
||||
function saveState()
|
||||
{
|
||||
mpSettings.saveState();
|
||||
downloadSettings.saveState();
|
||||
generalSettings.saveState();
|
||||
renderSection.saveState();
|
||||
extraArgsSection.saveState();
|
||||
windowSettings.saveState();
|
||||
}
|
||||
|
||||
Flickable {
|
||||
|
@ -57,7 +65,7 @@ Item {
|
|||
Text {
|
||||
id: headerText
|
||||
text: qsTr("Settings")
|
||||
font.pixelSize: Style.strutSize / 2
|
||||
font.pixelSize: Style.headingFontPixelSize
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: Style.inset
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ SettingControl {
|
|||
property alias value: popup.currentIndex
|
||||
property alias defaultValue: root.defaultIndex
|
||||
|
||||
implicitHeight: childrenRect.height
|
||||
implicitHeight: popup.height + Style.margin + description.height
|
||||
|
||||
PopupChoice {
|
||||
id: popup
|
||||
|
|
50
src/GUI/qml/Sidebar.qml
Normal file
50
src/GUI/qml/Sidebar.qml
Normal file
|
@ -0,0 +1,50 @@
|
|||
import QtQuick 2.4
|
||||
|
||||
import "."
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
color: Style.themeColor
|
||||
|
||||
property alias pagesModel: buttonRepeater.model
|
||||
property int selectedPage: 0
|
||||
|
||||
signal selectPage(var pageSource);
|
||||
|
||||
function setSelectedPage(index)
|
||||
{
|
||||
selectedPage = index
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent.width
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: Style.margin
|
||||
anchors.bottom: flyButton.top
|
||||
|
||||
Repeater {
|
||||
id: buttonRepeater
|
||||
|
||||
delegate: SidebarButton {
|
||||
icon: model.iconPath
|
||||
label: model.title
|
||||
onClicked: {
|
||||
root.selectedPage = model.index
|
||||
root.selectPage(model.pageSource);
|
||||
}
|
||||
|
||||
selected: (model.index === root.selectedPage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SidebarButton {
|
||||
id: flyButton
|
||||
label: qsTr("Fly!")
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: Style.margin
|
||||
enabled: _launcher.canFly
|
||||
icon: "qrc:///toolbox-fly"
|
||||
onClicked: _launcher.fly();
|
||||
}
|
||||
}
|
49
src/GUI/qml/SidebarButton.qml
Normal file
49
src/GUI/qml/SidebarButton.qml
Normal file
|
@ -0,0 +1,49 @@
|
|||
import QtQuick 2.4
|
||||
import "."
|
||||
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
width: Style.strutSize * 2
|
||||
height: Style.strutSize * 2
|
||||
|
||||
property alias icon: iconImage.source
|
||||
property alias label: label.text
|
||||
|
||||
signal clicked()
|
||||
|
||||
property bool selected: false
|
||||
property bool enabled: true
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
visible: root.enabled & (root.selected | mouse.containsMouse)
|
||||
color: Style.activeColor
|
||||
}
|
||||
|
||||
Image {
|
||||
id: iconImage
|
||||
anchors.centerIn: parent
|
||||
opacity: root.enabled ? 1.0 : 0.5
|
||||
}
|
||||
|
||||
Text {
|
||||
id: label
|
||||
color: "white"
|
||||
// enabled appearance is done via opacity to match the icon
|
||||
opacity: root.enabled ? 1.0 : 0.5
|
||||
width: parent.width
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
anchors.top: iconImage.bottom
|
||||
anchors.topMargin: Style.margin
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouse
|
||||
enabled: root.enabled
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: root.clicked();
|
||||
}
|
||||
}
|
|
@ -5,6 +5,9 @@ import "."
|
|||
Item {
|
||||
id: root
|
||||
|
||||
signal showSelectedAircraft();
|
||||
signal showSelectedLocation();
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "#7f7f7f"
|
||||
|
@ -12,19 +15,6 @@ Item {
|
|||
|
||||
readonly property string __aircraftDescription: _launcher.selectedAircraftInfo.description
|
||||
|
||||
// base image when preview not available
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "magenta"
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: _launcher
|
||||
onAircraftTypeChanged: {
|
||||
console.info("Aircraft type is now:" + _launcher.aircraftType)
|
||||
}
|
||||
}
|
||||
|
||||
PreviewImage {
|
||||
id: preview
|
||||
anchors.centerIn: parent
|
||||
|
@ -101,6 +91,7 @@ Item {
|
|||
style: Text.Outline
|
||||
styleColor: "black"
|
||||
font.bold: true
|
||||
font.pixelSize: Style.subHeadingFontPixelSize
|
||||
|
||||
onClicked: {
|
||||
_launcher.launchUrl("http://home.flightgear.org/about/");
|
||||
|
@ -114,6 +105,7 @@ Item {
|
|||
color: "transparent"
|
||||
border.width: 1
|
||||
border.color: Style.frameColor
|
||||
clip: true
|
||||
|
||||
anchors {
|
||||
left: parent.left
|
||||
|
@ -149,7 +141,7 @@ Item {
|
|||
}
|
||||
|
||||
// aircraft name row
|
||||
Text {
|
||||
StyledText {
|
||||
text: qsTr("Aircraft:")
|
||||
horizontalAlignment: Text.AlignRight
|
||||
font.pixelSize: Style.headingFontPixelSize
|
||||
|
@ -157,10 +149,13 @@ Item {
|
|||
|
||||
// TODO - make clickable, jump to to the aircraft in the installed
|
||||
// aircraft list
|
||||
Text {
|
||||
ClickableText {
|
||||
text: _launcher.selectedAircraftInfo.name === "" ?
|
||||
qsTr("No aircraft selected") : _launcher.selectedAircraftInfo.name
|
||||
enabled: _launcher.selectedAircraftInfo.name !== ""
|
||||
font.pixelSize: Style.headingFontPixelSize
|
||||
|
||||
onClicked: root.showSelectedAircraft();
|
||||
}
|
||||
|
||||
HistoryPopup {
|
||||
|
@ -189,7 +184,7 @@ Item {
|
|||
maximumSize.height: 128
|
||||
}
|
||||
|
||||
Text {
|
||||
StyledText {
|
||||
id: aircraftDescriptionText
|
||||
anchors {
|
||||
left: thumbnail.right
|
||||
|
@ -229,7 +224,7 @@ Item {
|
|||
width: parent.width
|
||||
}
|
||||
|
||||
Text {
|
||||
StyledText {
|
||||
id: stateDescriptionText
|
||||
wrapMode: Text.WordWrap
|
||||
maximumLineCount: 5
|
||||
|
@ -264,18 +259,18 @@ Item {
|
|||
}
|
||||
|
||||
// location summary row
|
||||
Text {
|
||||
StyledText {
|
||||
id: locationLabel
|
||||
text: qsTr("Location:")
|
||||
horizontalAlignment: Text.AlignRight
|
||||
font.pixelSize: Style.headingFontPixelSize
|
||||
}
|
||||
|
||||
// TODO - make clickable, jump to the location page
|
||||
Text {
|
||||
ClickableText {
|
||||
text: _launcher.location.description
|
||||
font.pixelSize: Style.headingFontPixelSize
|
||||
width: summaryGrid.middleColumnWidth
|
||||
onClicked: root.showSelectedLocation()
|
||||
}
|
||||
|
||||
HistoryPopup {
|
||||
|
@ -288,13 +283,13 @@ Item {
|
|||
}
|
||||
|
||||
// settings summary row
|
||||
Text {
|
||||
StyledText {
|
||||
text: qsTr("Settings:")
|
||||
horizontalAlignment: Text.AlignRight
|
||||
font.pixelSize: Style.headingFontPixelSize
|
||||
}
|
||||
|
||||
Text {
|
||||
StyledText {
|
||||
text: _launcher.combinedSummary.join(", ")
|
||||
font.pixelSize: Style.headingFontPixelSize
|
||||
wrapMode: Text.WordWrap
|
||||
|
|
|
@ -9,6 +9,14 @@ Item {
|
|||
implicitWidth: track.width + label.width + 16
|
||||
implicitHeight: Math.max(label.height, thumb.height)
|
||||
|
||||
// helepr to set the value without an animation
|
||||
function setValue(newCheck)
|
||||
{
|
||||
sliderBehaviour.enabled = false;
|
||||
checked = newCheck
|
||||
sliderBehaviour.enabled = true;
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: track
|
||||
width: height * 2
|
||||
|
@ -34,6 +42,7 @@ Item {
|
|||
x: checked ? parent.width - (track.radius + radius) : (track.radius - radius)
|
||||
|
||||
Behavior on x {
|
||||
id: sliderBehaviour
|
||||
NumberAnimation {
|
||||
duration: 250
|
||||
}
|
||||
|
|
41
src/GUI/qml/ViewCommandLine.qml
Normal file
41
src/GUI/qml/ViewCommandLine.qml
Normal file
|
@ -0,0 +1,41 @@
|
|||
import QtQuick 2.4
|
||||
import FlightGear.Launcher 1.0
|
||||
import "."
|
||||
|
||||
|
||||
Item {
|
||||
|
||||
Flickable {
|
||||
id: flick
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: scrollbar.right
|
||||
top: parent.top
|
||||
bottom: parent.bottom
|
||||
margins: Style.margin
|
||||
}
|
||||
|
||||
contentHeight: contents.implicitHeight
|
||||
|
||||
TextEdit {
|
||||
id: contents
|
||||
width: parent.width
|
||||
selectByMouse: true
|
||||
|
||||
textFormat: TextEdit.RichText
|
||||
readOnly: true
|
||||
|
||||
wrapMode: TextEdit.Wrap
|
||||
|
||||
text: _config.htmlForCommandLine();
|
||||
}
|
||||
}
|
||||
|
||||
Scrollbar {
|
||||
id: scrollbar
|
||||
anchors.right: parent.right
|
||||
height: flick.height
|
||||
flickable: flick
|
||||
visible: flick.contentHeight > flick.height
|
||||
}
|
||||
}
|
|
@ -94,6 +94,11 @@
|
|||
<file>qml/IntegerSpinbox.qml</file>
|
||||
<file>qml/DoubleSpinbox.qml</file>
|
||||
<file>qml/StyledText.qml</file>
|
||||
<file>qml/Launcher.qml</file>
|
||||
<file>qml/Sidebar.qml</file>
|
||||
<file>qml/SidebarButton.qml</file>
|
||||
<file>qml/ViewCommandLine.qml</file>
|
||||
<file>qml/AddOnsHeader.qml</file>
|
||||
</qresource>
|
||||
<qresource prefix="/preview">
|
||||
<file alias="close-icon">preview-close.png</file>
|
||||
|
|
Loading…
Add table
Reference in a new issue