From d7bfee2414094fa2b70d1ae877040039acaaa78f Mon Sep 17 00:00:00 2001 From: Xavier Michelon Date: Tue, 28 Feb 2023 11:30:03 +0100 Subject: [PATCH] feat(GODT-2382): Added bridge-gui settings file with 'UseSoftwareRenderer' value. --- .../bridge-gui/bridge-gui/AppController.cpp | 37 +++++++++--- .../bridge-gui/bridge-gui/AppController.h | 19 +++---- .../bridge-gui/bridge-gui/CMakeLists.txt | 1 + .../bridge-gui/bridge-gui/Settings.cpp | 56 +++++++++++++++++++ .../frontend/bridge-gui/bridge-gui/Settings.h | 47 ++++++++++++++++ .../frontend/bridge-gui/bridge-gui/main.cpp | 6 +- 6 files changed, 145 insertions(+), 21 deletions(-) create mode 100644 internal/frontend/bridge-gui/bridge-gui/Settings.cpp create mode 100644 internal/frontend/bridge-gui/bridge-gui/Settings.h diff --git a/internal/frontend/bridge-gui/bridge-gui/AppController.cpp b/internal/frontend/bridge-gui/bridge-gui/AppController.cpp index 4152d7d9..e0df2a5a 100644 --- a/internal/frontend/bridge-gui/bridge-gui/AppController.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/AppController.cpp @@ -19,6 +19,7 @@ #include "AppController.h" #include "QMLBackend.h" #include "SentryUtils.h" +#include "Settings.h" #include #include #include @@ -32,6 +33,7 @@ namespace { QString const noWindowFlag = "--no-window"; ///< The no-window command-line flag. } + //**************************************************************************************************************************************************** /// \return The AppController instance. //**************************************************************************************************************************************************** @@ -47,10 +49,19 @@ AppController &app() { AppController::AppController() : backend_(std::make_unique()) , grpc_(std::make_unique()) - , log_(std::make_unique()) { + , log_(std::make_unique()) + , settings_(new Settings) { } + +//**************************************************************************************************************************************************** +// The following is in the implementation file because of unique pointers with incomplete types in headers. +// See https://stackoverflow.com/questions/6012157/is-stdunique-ptrt-required-to-know-the-full-definition-of-t +//**************************************************************************************************************************************************** +AppController::~AppController() = default; + + //**************************************************************************************************************************************************** /// \return The bridge worker, which can be null if the application was run in 'attach' mode (-a command-line switch). //**************************************************************************************************************************************************** @@ -70,15 +81,24 @@ ProcessMonitor *AppController::bridgeMonitor() const { } +//**************************************************************************************************************************************************** +/// \return A reference to the application settings. +//**************************************************************************************************************************************************** +Settings &AppController::settings() { + return *settings_; +} + + //**************************************************************************************************************************************************** /// \param[in] function The function that caught the exception. /// \param[in] message The error message. /// \param[in] details The details for the error. //**************************************************************************************************************************************************** -void AppController::onFatalError(QString const &function, QString const &message, QString const& details) { +void AppController::onFatalError(QString const &function, QString const &message, QString const &details) { QString fullMessage = QString("%1(): %2").arg(function, message); - if (!details.isEmpty()) + if (!details.isEmpty()) { fullMessage += "\n\nDetails:\n" + details; + } sentry_uuid_s const uuid = reportSentryException(SENTRY_LEVEL_ERROR, "AppController got notified of a fatal error", "Exception", fullMessage.toLocal8Bit()); QMessageBox::critical(nullptr, tr("Error"), message); @@ -87,20 +107,23 @@ void AppController::onFatalError(QString const &function, QString const &message qApp->exit(EXIT_FAILURE); } + void AppController::restart(bool isCrashing) { if (!launcher_.isEmpty()) { QProcess p; - log_->info(QString("Restarting - App : %1 - Args : %2").arg(launcher_,launcherArgs_.join(" "))); + log_->info(QString("Restarting - App : %1 - Args : %2").arg(launcher_, launcherArgs_.join(" "))); QStringList args = launcherArgs_; - if (isCrashing) + if (isCrashing) { args.append(noWindowFlag); + } p.startDetached(launcher_, args); p.waitForStarted(); } } -void AppController::setLauncherArgs(const QString& launcher, const QStringList& args){ + +void AppController::setLauncherArgs(const QString &launcher, const QStringList &args) { launcher_ = launcher; launcherArgs_ = args; -} \ No newline at end of file +} diff --git a/internal/frontend/bridge-gui/bridge-gui/AppController.h b/internal/frontend/bridge-gui/bridge-gui/AppController.h index cba3bebd..f8955dd5 100644 --- a/internal/frontend/bridge-gui/bridge-gui/AppController.h +++ b/internal/frontend/bridge-gui/bridge-gui/AppController.h @@ -20,21 +20,16 @@ #define BRIDGE_GUI_APP_CONTROLLER_H +//@formatter:off class QMLBackend; - - +class Settings; namespace bridgepp { class Log; - - class Overseer; - - class GRPCClient; - - class ProcessMonitor; } +//@formatter:on //**************************************************************************************************************************************************** @@ -47,7 +42,7 @@ Q_OBJECT public: // member functions. AppController(AppController const &) = delete; ///< Disabled copy-constructor. AppController(AppController &&) = delete; ///< Disabled assignment copy-constructor. - ~AppController() override = default; ///< Destructor. + ~AppController() override; ///< Destructor. AppController &operator=(AppController const &) = delete; ///< Disabled assignment operator. AppController &operator=(AppController &&) = delete; ///< Disabled move assignment operator. QMLBackend &backend() { return *backend_; } ///< Return a reference to the backend. @@ -55,10 +50,11 @@ public: // member functions. bridgepp::Log &log() { return *log_; } ///< Return a reference to the log. std::unique_ptr &bridgeOverseer() { return bridgeOverseer_; }; ///< Returns a reference the bridge overseer bridgepp::ProcessMonitor *bridgeMonitor() const; ///< Return the bridge worker. - void setLauncherArgs(const QString& launcher, const QStringList& args); + Settings &settings();; ///< Return the application settings. + void setLauncherArgs(const QString &launcher, const QStringList &args); public slots: - void onFatalError(QString const &function, QString const &message, QString const& details); ///< Handle fatal errors. + void onFatalError(QString const &function, QString const &message, QString const &details); ///< Handle fatal errors. private: // member functions AppController(); ///< Default constructor. @@ -69,6 +65,7 @@ private: // data members std::unique_ptr grpc_; ///< The RPC client. std::unique_ptr log_; ///< The log. std::unique_ptr bridgeOverseer_; ///< The overseer for the bridge monitor worker. + std::unique_ptr settings_; ///< The application settings. QString launcher_; QStringList launcherArgs_; }; diff --git a/internal/frontend/bridge-gui/bridge-gui/CMakeLists.txt b/internal/frontend/bridge-gui/bridge-gui/CMakeLists.txt index 58591bdf..e491356f 100644 --- a/internal/frontend/bridge-gui/bridge-gui/CMakeLists.txt +++ b/internal/frontend/bridge-gui/bridge-gui/CMakeLists.txt @@ -118,6 +118,7 @@ add_executable(bridge-gui QMLBackend.cpp QMLBackend.h UserList.cpp UserList.h SentryUtils.cpp SentryUtils.h + Settings.cpp Settings.h ${DOCK_ICON_SRC_FILE} MacOS/DockIcon.h ) diff --git a/internal/frontend/bridge-gui/bridge-gui/Settings.cpp b/internal/frontend/bridge-gui/bridge-gui/Settings.cpp new file mode 100644 index 00000000..e7acb259 --- /dev/null +++ b/internal/frontend/bridge-gui/bridge-gui/Settings.cpp @@ -0,0 +1,56 @@ +// Copyright (c) 2023 Proton AG +// +// This file is part of Proton Mail Bridge. +// +// Proton Mail Bridge is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Proton Mail Bridge is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Proton Mail Bridge. If not, see . + + +#include "Settings.h" +#include + + +using namespace bridgepp; + + +namespace { + + +QString const settingsFileName = "bridge-gui.ini"; ///< The name of the settings file. +QString const keyUseSoftwareRenderer = "UseSoftwareRenderer"; ///< The key for storing the 'Use software rendering' setting. + + +} + +//**************************************************************************************************************************************************** +// +//**************************************************************************************************************************************************** +Settings::Settings() + : settings_(QDir(userConfigDir()).absoluteFilePath("bridge-gui.ini"), QSettings::Format::IniFormat) { +} + + +//**************************************************************************************************************************************************** +/// \return The value for the 'Use software renderer' setting. +//**************************************************************************************************************************************************** +bool Settings::useSoftwareRenderer() const { + return settings_.value(keyUseSoftwareRenderer, false).toBool(); +} + + +//**************************************************************************************************************************************************** +/// \param[in] value The value for the 'Use software renderer' setting. +//**************************************************************************************************************************************************** +void Settings::setUseSoftwareRenderer(bool value) { + settings_.setValue(keyUseSoftwareRenderer, value); +} diff --git a/internal/frontend/bridge-gui/bridge-gui/Settings.h b/internal/frontend/bridge-gui/bridge-gui/Settings.h new file mode 100644 index 00000000..977fc6ba --- /dev/null +++ b/internal/frontend/bridge-gui/bridge-gui/Settings.h @@ -0,0 +1,47 @@ +// Copyright (c) 2023 Proton AG +// +// This file is part of Proton Mail Bridge. +// +// Proton Mail Bridge is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Proton Mail Bridge is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Proton Mail Bridge. If not, see . + + +#ifndef BRIDGE_GUI_SETTINGS_H +#define BRIDGE_GUI_SETTINGS_H + + +//**************************************************************************************************************************************************** +/// \brief Application settings class +//**************************************************************************************************************************************************** +class Settings { +public: // member functions. + Settings(Settings const&) = delete; ///< Disabled copy-constructor. + Settings(Settings&&) = delete; ///< Disabled assignment copy-constructor. + ~Settings() = default; ///< Destructor. + Settings& operator=(Settings const&) = delete; ///< Disabled assignment operator. + Settings& operator=(Settings&&) = delete; ///< Disabled move assignment operator. + + bool useSoftwareRenderer() const; ///< Get the 'Use software renderer' settings value. + void setUseSoftwareRenderer(bool value); ///< Set the 'Use software renderer' settings value. + +private: // member functions. + Settings(); ///< Default constructor. + +private: // data members. + QSettings settings_; ///< The settings. + + friend class AppController; +}; + + +#endif //BRIDGE_GUI_SETTINGS_H diff --git a/internal/frontend/bridge-gui/bridge-gui/main.cpp b/internal/frontend/bridge-gui/bridge-gui/main.cpp index 03cd64d1..35d0e14e 100644 --- a/internal/frontend/bridge-gui/bridge-gui/main.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/main.cpp @@ -16,13 +16,13 @@ // along with Proton Mail Bridge. If not, see . -#include "Pch.h" #include "BridgeApp.h" +#include "BuildConfig.h" #include "CommandLine.h" #include "LogUtils.h" #include "QMLBackend.h" #include "SentryUtils.h" -#include "BuildConfig.h" +#include "Settings.h" #include #include #include @@ -334,7 +334,7 @@ int main(int argc, char *argv[]) { // The following allows to render QML content in software with a 'Rendering Hardware Interface' (OpenGL, Vulkan, Metal, Direct3D...) // Note that it is different from the Qt::AA_UseSoftwareOpenGL attribute we use on some platforms that instruct Qt that we would like // to use a software-only implementation of OpenGL. - QQuickWindow::setSceneGraphBackend(cliOptions.useSoftwareRenderer ? "software" : "rhi"); + QQuickWindow::setSceneGraphBackend((app().settings().useSoftwareRenderer() || cliOptions.useSoftwareRenderer) ? "software" : "rhi"); log.info(QString("Qt Quick renderer: %1").arg(QQuickWindow::sceneGraphBackend())); QQmlApplicationEngine engine;