1
0
Fork 0
flightgear/src/GUI/LauncherMainWindow.cxx
James Turner cec9ab5039 Launcher: convert most icons to masked.
Still need to add SVG support, but this improves feedback (eg hover)
for many icons in the launcher. Will remove the redundant PNGs in
another commit once other pieces are done.
2021-04-01 12:14:22 +01:00

240 lines
8.2 KiB
C++
Executable file

#include "config.h"
#include "LauncherMainWindow.hxx"
// Qt headers
#include <QMessageBox>
#include <QSettings>
#include <QDebug>
#include <QMenu>
#include <QMenuBar>
#include <QOpenGLContext>
#include <QQmlComponent>
#include <QQmlContext>
#include <QQmlEngine>
#include <QQmlError>
#include <QQmlFileSelector>
#include <QQuickItem>
// launcher headers
#include "AddOnsController.hxx"
#include "AircraftItemModel.hxx"
#include "DefaultAircraftLocator.hxx"
#include "GettingStartedTip.hxx"
#include "LaunchConfig.hxx"
#include "LauncherController.hxx"
#include "LauncherNotificationsController.hxx"
#include "LauncherPackageDelegate.hxx"
#include "LocalAircraftCache.hxx"
#include "LocationController.hxx"
#include "QmlColoredImageProvider.hxx"
#include "QtLauncher.hxx"
#include "UpdateChecker.hxx"
#include <Main/sentryIntegration.hxx>
//////////////////////////////////////////////////////////////////////////////
LauncherMainWindow::LauncherMainWindow(bool inSimMode) : QQuickView()
{
setTitle("FlightGear " FLIGHTGEAR_VERSION);
m_controller = new LauncherController(this, this);
int styleTypeId = 0;
m_controller->initQML(styleTypeId);
// 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);
m_coloredIconProvider = new QmlColoredImageProvider;
engine()->addImageProvider("colored-icon", m_coloredIconProvider);
if (!inSimMode) {
#if defined(Q_OS_MAC)
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);
#endif
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);
}
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'"));
}
m_coloredIconProvider->loadStyleColors(engine(), styleTypeId);
connect(this, &QQuickView::statusChanged, this, &LauncherMainWindow::onQuickStatusChanged);
m_controller->initialRestoreSettings();
////////////
#if defined(Q_OS_WIN)
const QString osName("win");
#elif defined(Q_OS_MAC)
const QString osName("mac");
#else
const QString osName("unix");
#endif
setResizeMode(QQuickView::SizeRootObjectToView);
engine()->addImportPath("qrc:///");
QQmlContext* ctx = rootContext();
ctx->setContextProperty("_launcher", m_controller);
ctx->setContextProperty("_config", m_controller->config());
ctx->setContextProperty("_location", m_controller->location());
ctx->setContextProperty("_osName", osName);
auto updater = new UpdateChecker(this);
ctx->setContextProperty("_updates", updater);
auto packageDelegate = new LauncherPackageDelegate(this);
ctx->setContextProperty("_packages", packageDelegate);
auto notifications = new LauncherNotificationsController{this, engine()};
ctx->setContextProperty("_notifications", notifications);
if (!inSimMode) {
auto addOnsCtl = new AddOnsController(this, m_controller->config());
ctx->setContextProperty("_addOns", addOnsCtl);
}
auto weatherScenariosModel = new flightgear::WeatherScenariosModel(this);
ctx->setContextProperty("_weatherScenarios", weatherScenariosModel);
setSource(QUrl("qrc:///qml/Launcher.qml"));
}
void LauncherMainWindow::onQuickStatusChanged(QQuickView::Status status)
{
if (status == QQuickView::Error) {
QString errorString;
Q_FOREACH (auto err, errors()) {
errorString.append("\n" + err.toString());
}
QMessageBox::critical(nullptr, "UI loading failures.",
tr("Problems occurred loading the user interface. This is usually due to missing modules on your system. "
"Please report this error to the FlightGear developer list or forum, and take care to mention your system "
"distribution, etc. Please also include the information provided below.\n") +
errorString);
}
}
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;
}
LauncherMainWindow::~LauncherMainWindow()
{
}
bool LauncherMainWindow::event(QEvent *event)
{
if (event->type() == QEvent::Close) {
m_controller->saveSettings();
}
return QQuickView::event(event);
}
bool LauncherMainWindow::execInApp()
{
m_controller->setInAppMode();
show();
while (m_controller->keepRunningInAppMode()) {
qApp->processEvents();
}
return m_controller->inAppResult();
}
// 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
}