2020-05-19 21:22:04 +00:00
|
|
|
#include "config.h"
|
|
|
|
|
2017-02-20 00:19:13 +00:00
|
|
|
#include "LauncherMainWindow.hxx"
|
|
|
|
|
|
|
|
// Qt headers
|
|
|
|
#include <QMessageBox>
|
|
|
|
#include <QSettings>
|
|
|
|
#include <QDebug>
|
|
|
|
#include <QMenu>
|
2017-02-21 11:01:06 +00:00
|
|
|
#include <QMenuBar>
|
|
|
|
|
2020-12-27 17:37:06 +00:00
|
|
|
#include <QOpenGLContext>
|
2017-02-21 11:01:06 +00:00
|
|
|
#include <QQmlComponent>
|
|
|
|
#include <QQmlContext>
|
2020-12-27 17:37:06 +00:00
|
|
|
#include <QQmlEngine>
|
2018-03-20 16:32:31 +00:00
|
|
|
#include <QQmlError>
|
2018-07-03 08:36:30 +00:00
|
|
|
#include <QQmlFileSelector>
|
2020-12-27 17:37:06 +00:00
|
|
|
#include <QQuickItem>
|
2017-02-21 11:01:06 +00:00
|
|
|
|
2017-02-20 00:19:13 +00:00
|
|
|
// launcher headers
|
2020-10-04 18:16:08 +00:00
|
|
|
#include "AddOnsController.hxx"
|
2020-10-29 16:26:36 +00:00
|
|
|
#include "AircraftItemModel.hxx"
|
2018-03-16 22:01:21 +00:00
|
|
|
#include "DefaultAircraftLocator.hxx"
|
2021-03-29 14:13:27 +00:00
|
|
|
#include "GettingStartedTip.hxx"
|
2018-03-16 22:01:21 +00:00
|
|
|
#include "LaunchConfig.hxx"
|
2018-03-22 12:24:57 +00:00
|
|
|
#include "LauncherController.hxx"
|
2020-10-25 18:24:33 +00:00
|
|
|
#include "LauncherNotificationsController.hxx"
|
|
|
|
#include "LauncherPackageDelegate.hxx"
|
|
|
|
#include "LocalAircraftCache.hxx"
|
2018-05-07 15:41:10 +00:00
|
|
|
#include "LocationController.hxx"
|
2021-03-29 14:13:27 +00:00
|
|
|
#include "QmlColoredImageProvider.hxx"
|
2020-10-25 18:24:33 +00:00
|
|
|
#include "QtLauncher.hxx"
|
2020-10-03 14:35:22 +00:00
|
|
|
#include "UpdateChecker.hxx"
|
2017-02-20 00:19:13 +00:00
|
|
|
|
2020-12-27 17:37:06 +00:00
|
|
|
#include <Main/sentryIntegration.hxx>
|
|
|
|
|
2017-02-20 00:19:13 +00:00
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2020-07-30 11:30:23 +00:00
|
|
|
LauncherMainWindow::LauncherMainWindow(bool inSimMode) : QQuickView()
|
2017-02-20 00:19:13 +00:00
|
|
|
{
|
2018-06-22 11:09:35 +00:00
|
|
|
setTitle("FlightGear " FLIGHTGEAR_VERSION);
|
2017-04-13 12:01:29 +00:00
|
|
|
|
2018-06-22 11:09:35 +00:00
|
|
|
m_controller = new LauncherController(this, this);
|
2021-03-29 14:13:27 +00:00
|
|
|
|
|
|
|
int styleTypeId = 0;
|
|
|
|
m_controller->initQML(styleTypeId);
|
2018-03-22 12:24:57 +00:00
|
|
|
|
2020-12-27 17:37:06 +00:00
|
|
|
// use a direct connection to be notified synchronously when the render thread
|
|
|
|
// starts OpenGL. We use this to log the OpenGL information from the
|
|
|
|
// context at that time, for tracing purposes.
|
|
|
|
connect(this, &QQuickWindow::sceneGraphInitialized,
|
|
|
|
this, &LauncherMainWindow::renderTheadSceneGraphInitialized,
|
|
|
|
Qt::DirectConnection);
|
|
|
|
|
2021-03-29 14:13:27 +00:00
|
|
|
m_coloredIconProvider = new QmlColoredImageProvider;
|
|
|
|
engine()->addImageProvider("colored-icon", m_coloredIconProvider);
|
|
|
|
|
2020-07-30 11:30:23 +00:00
|
|
|
if (!inSimMode) {
|
2018-06-22 11:09:35 +00:00
|
|
|
#if defined(Q_OS_MAC)
|
2020-07-30 11:30:23 +00:00
|
|
|
QMenuBar* mb = new QMenuBar();
|
|
|
|
|
|
|
|
QMenu* fileMenu = mb->addMenu(tr("File"));
|
|
|
|
QAction* openAction = new QAction(tr("Open saved configuration..."));
|
|
|
|
openAction->setMenuRole(QAction::NoRole);
|
|
|
|
connect(openAction, &QAction::triggered,
|
|
|
|
m_controller, &LauncherController::openConfig);
|
|
|
|
|
|
|
|
QAction* saveAction = new QAction(tr("Save configuration as..."));
|
|
|
|
saveAction->setMenuRole(QAction::NoRole);
|
|
|
|
connect(saveAction, &QAction::triggered,
|
|
|
|
m_controller, &LauncherController::saveConfigAs);
|
|
|
|
|
|
|
|
fileMenu->addAction(openAction);
|
|
|
|
fileMenu->addAction(saveAction);
|
|
|
|
|
|
|
|
QMenu* toolsMenu = mb->addMenu(tr("Tools"));
|
|
|
|
QAction* restoreDefaultsAction = new QAction(tr("Restore defaults..."));
|
|
|
|
restoreDefaultsAction->setMenuRole(QAction::NoRole);
|
|
|
|
connect(restoreDefaultsAction, &QAction::triggered,
|
|
|
|
m_controller, &LauncherController::requestRestoreDefaults);
|
|
|
|
|
|
|
|
QAction* changeDataAction = new QAction(tr("Select data files location..."));
|
|
|
|
changeDataAction->setMenuRole(QAction::NoRole);
|
|
|
|
connect(changeDataAction, &QAction::triggered,
|
|
|
|
m_controller, &LauncherController::requestChangeDataPath);
|
|
|
|
|
|
|
|
QAction* viewCommandLineAction = new QAction(tr("View command-line"));
|
|
|
|
connect(viewCommandLineAction, &QAction::triggered,
|
|
|
|
m_controller, &LauncherController::viewCommandLine);
|
|
|
|
|
|
|
|
toolsMenu->addAction(restoreDefaultsAction);
|
|
|
|
toolsMenu->addAction(changeDataAction);
|
|
|
|
toolsMenu->addAction(viewCommandLineAction);
|
2018-06-22 11:09:35 +00:00
|
|
|
#endif
|
2017-02-20 00:19:13 +00:00
|
|
|
|
2020-07-30 11:30:23 +00:00
|
|
|
QAction* qa = new QAction(this);
|
|
|
|
qa->setMenuRole(QAction::QuitRole); // will be addeed accordingly
|
|
|
|
qa->setShortcut(QKeySequence("Ctrl+Q"));
|
|
|
|
connect(qa, &QAction::triggered, m_controller, &LauncherController::quit);
|
|
|
|
}
|
2018-03-22 12:24:57 +00:00
|
|
|
|
2020-10-29 21:21:00 +00:00
|
|
|
if (!checkQQC2Availability()) {
|
|
|
|
QMessageBox::critical(nullptr, "Missing required component",
|
|
|
|
tr("Your system is missing a required UI component (QtQuick Controls 2). "
|
|
|
|
"This normally occurs on Linux platforms where Qt is split into many small packages. "
|
|
|
|
"On Ubuntu/Debian systems, the package is called 'qml-module-qtquick-controls2'"));
|
|
|
|
}
|
|
|
|
|
2021-03-29 14:13:27 +00:00
|
|
|
m_coloredIconProvider->loadStyleColors(engine(), styleTypeId);
|
|
|
|
|
2020-10-25 18:24:33 +00:00
|
|
|
connect(this, &QQuickView::statusChanged, this, &LauncherMainWindow::onQuickStatusChanged);
|
|
|
|
|
2018-06-27 22:06:39 +00:00
|
|
|
m_controller->initialRestoreSettings();
|
2018-03-16 22:01:21 +00:00
|
|
|
|
2018-03-22 12:24:57 +00:00
|
|
|
////////////
|
|
|
|
#if defined(Q_OS_WIN)
|
|
|
|
const QString osName("win");
|
|
|
|
#elif defined(Q_OS_MAC)
|
|
|
|
const QString osName("mac");
|
|
|
|
#else
|
|
|
|
const QString osName("unix");
|
|
|
|
#endif
|
2018-03-11 11:49:38 +00:00
|
|
|
|
2018-06-22 11:09:35 +00:00
|
|
|
setResizeMode(QQuickView::SizeRootObjectToView);
|
|
|
|
engine()->addImportPath("qrc:///");
|
2018-03-20 16:32:31 +00:00
|
|
|
|
2018-06-22 11:09:35 +00:00
|
|
|
QQmlContext* ctx = rootContext();
|
|
|
|
ctx->setContextProperty("_launcher", m_controller);
|
|
|
|
ctx->setContextProperty("_config", m_controller->config());
|
|
|
|
ctx->setContextProperty("_location", m_controller->location());
|
|
|
|
ctx->setContextProperty("_osName", osName);
|
2018-03-11 11:49:38 +00:00
|
|
|
|
2020-10-03 14:35:22 +00:00
|
|
|
auto updater = new UpdateChecker(this);
|
|
|
|
ctx->setContextProperty("_updates", updater);
|
|
|
|
|
2020-10-25 18:24:33 +00:00
|
|
|
auto packageDelegate = new LauncherPackageDelegate(this);
|
|
|
|
ctx->setContextProperty("_packages", packageDelegate);
|
|
|
|
|
|
|
|
auto notifications = new LauncherNotificationsController{this, engine()};
|
|
|
|
ctx->setContextProperty("_notifications", notifications);
|
|
|
|
|
2020-07-30 11:30:23 +00:00
|
|
|
if (!inSimMode) {
|
|
|
|
auto addOnsCtl = new AddOnsController(this, m_controller->config());
|
|
|
|
ctx->setContextProperty("_addOns", addOnsCtl);
|
|
|
|
}
|
|
|
|
|
2018-06-22 11:09:35 +00:00
|
|
|
auto weatherScenariosModel = new flightgear::WeatherScenariosModel(this);
|
|
|
|
ctx->setContextProperty("_weatherScenarios", weatherScenariosModel);
|
2017-02-20 00:19:13 +00:00
|
|
|
|
2018-06-22 11:09:35 +00:00
|
|
|
setSource(QUrl("qrc:///qml/Launcher.qml"));
|
2017-02-21 11:01:06 +00:00
|
|
|
}
|
2017-02-20 00:19:13 +00:00
|
|
|
|
2020-10-25 18:24:33 +00:00
|
|
|
void LauncherMainWindow::onQuickStatusChanged(QQuickView::Status status)
|
2018-03-20 16:32:31 +00:00
|
|
|
{
|
2020-10-25 18:24:33 +00:00
|
|
|
if (status == QQuickView::Error) {
|
2018-03-20 16:32:31 +00:00
|
|
|
QString errorString;
|
|
|
|
|
2020-10-25 18:24:33 +00:00
|
|
|
Q_FOREACH (auto err, errors()) {
|
2018-03-20 16:32:31 +00:00
|
|
|
errorString.append("\n" + err.toString());
|
|
|
|
}
|
|
|
|
|
2020-10-25 18:24:33 +00:00
|
|
|
QMessageBox::critical(nullptr, "UI loading failures.",
|
|
|
|
tr("Problems occurred loading the user interface. This is usually due to missing modules on your system. "
|
2018-03-20 16:32:31 +00:00
|
|
|
"Please report this error to the FlightGear developer list or forum, and take care to mention your system "
|
2020-10-25 18:24:33 +00:00
|
|
|
"distribution, etc. Please also include the information provided below.\n") +
|
|
|
|
errorString);
|
2018-03-20 16:32:31 +00:00
|
|
|
}
|
|
|
|
}
|
2018-03-22 09:32:30 +00:00
|
|
|
|
2020-10-29 21:21:00 +00:00
|
|
|
bool LauncherMainWindow::checkQQC2Availability()
|
|
|
|
{
|
|
|
|
QQmlComponent comp(engine());
|
|
|
|
comp.setData(R"(
|
|
|
|
import QtQuick.Controls 2.0
|
|
|
|
ScrollBar {
|
|
|
|
}
|
|
|
|
)",
|
|
|
|
{});
|
|
|
|
if (comp.isError()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
auto item = comp.create();
|
|
|
|
const bool haveQQC2 = (item != nullptr);
|
|
|
|
if (item)
|
|
|
|
item->deleteLater();
|
|
|
|
return haveQQC2;
|
|
|
|
}
|
|
|
|
|
2018-03-22 12:24:57 +00:00
|
|
|
LauncherMainWindow::~LauncherMainWindow()
|
|
|
|
{
|
2017-02-20 00:19:13 +00:00
|
|
|
}
|
|
|
|
|
2019-12-17 22:47:50 +00:00
|
|
|
bool LauncherMainWindow::event(QEvent *event)
|
|
|
|
{
|
|
|
|
if (event->type() == QEvent::Close) {
|
|
|
|
m_controller->saveSettings();
|
|
|
|
}
|
|
|
|
return QQuickView::event(event);
|
|
|
|
}
|
|
|
|
|
2017-02-20 00:19:13 +00:00
|
|
|
bool LauncherMainWindow::execInApp()
|
|
|
|
{
|
2018-06-23 16:55:39 +00:00
|
|
|
m_controller->setInAppMode();
|
|
|
|
|
2017-02-20 00:19:13 +00:00
|
|
|
show();
|
|
|
|
|
2018-06-23 16:55:39 +00:00
|
|
|
while (m_controller->keepRunningInAppMode()) {
|
2017-02-20 00:19:13 +00:00
|
|
|
qApp->processEvents();
|
|
|
|
}
|
|
|
|
|
2018-06-23 16:55:39 +00:00
|
|
|
return m_controller->inAppResult();
|
2017-02-20 00:19:13 +00:00
|
|
|
}
|
|
|
|
|
2020-12-27 17:37:06 +00:00
|
|
|
// this slot runs in the context of the render thread. Don't modify
|
|
|
|
void LauncherMainWindow::renderTheadSceneGraphInitialized()
|
|
|
|
{
|
|
|
|
auto qContext = QOpenGLContext::currentContext();
|
|
|
|
if (!qContext) {
|
|
|
|
qWarning() << Q_FUNC_INFO << "No current OpenGL context";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string renderer = (char*)glGetString(GL_RENDERER);
|
|
|
|
// capture this to help with debugging this crash:
|
|
|
|
// https://sentry.io/share/issue/f98e38dceb4241dbaeed944d6ce4d746/
|
|
|
|
// https://bugreports.qt.io/browse/QTBUG-69703
|
|
|
|
flightgear::addSentryTag("qt-gl-vendor", (char*)glGetString(GL_VENDOR));
|
|
|
|
flightgear::addSentryTag("qt-gl-renderer", renderer.c_str());
|
|
|
|
flightgear::addSentryTag("qt-gl-version", (char*)glGetString(GL_VERSION));
|
|
|
|
flightgear::addSentryTag("qt-glsl-version", (char*)glGetString(GL_SHADING_LANGUAGE_VERSION));
|
|
|
|
|
|
|
|
const char* gltype[] = {"Desktop", "GLES 2", "GLES 1"};
|
|
|
|
flightgear::addSentryTag("qt-gl-module-type", gltype[QOpenGLContext::openGLModuleType()]);
|
|
|
|
|
|
|
|
// if necessary, borrow more code from:
|
|
|
|
// https://code.qt.io/cgit/qt/qtbase.git/tree/examples/opengl/contextinfo/widget.cpp?h=5.15#n358
|
|
|
|
// to expand what this reports
|
|
|
|
}
|