From 70a6972b7ebef17b88e24a6d71539b63612c4f91 Mon Sep 17 00:00:00 2001 From: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> Date: Tue, 11 Jan 2022 13:38:57 -0500 Subject: [PATCH] mainwindow: save/restore window geometry Save virtual desktop geometry and window visibility state settings and set them for the application window when loading. Gitlab: #604 Change-Id: I053716d9c7b5d23e1bd7f33a1c41aedefb6cf9c8 --- src/MainApplicationWindow.qml | 78 ++++++++++++++++++++++++----------- src/appsettingsmanager.cpp | 5 ++- src/appsettingsmanager.h | 12 +++--- src/lrcinstance.cpp | 1 - src/mainapplication.cpp | 6 ++- src/mainapplication.h | 3 ++ src/qmlregister.cpp | 3 +- src/qmlregister.h | 3 +- 8 files changed, 77 insertions(+), 34 deletions(-) diff --git a/src/MainApplicationWindow.qml b/src/MainApplicationWindow.qml index 17e3a9d09..7808b21aa 100644 --- a/src/MainApplicationWindow.qml +++ b/src/MainApplicationWindow.qml @@ -52,6 +52,8 @@ ApplicationWindow { appContainer: appContainer } + property bool windowSettingsLoaded: false + function checkLoadedSource() { var sourceString = mainApplicationLoader.source.toString() @@ -80,35 +82,20 @@ ApplicationWindow { // is set, then we can quit if (force || !UtilsAdapter.getAppValue(Settings.MinimizeOnClose) || !UtilsAdapter.getAccountListSize()) { + // Save the window geometry and state before quitting. + var geometry = Qt.rect(appWindow.x, appWindow.y, + appWindow.width, appWindow.height) + AppSettingsManager.setValue(Settings.WindowGeometry, geometry) + AppSettingsManager.setValue(Settings.WindowState, appWindow.visibility) Qt.quit() - } else + } else { hide() + } } title: JamiStrings.appTitle - width: { - if (checkLoadedSource() === MainApplicationWindow.LoadedSource.WizardView) - return JamiTheme.wizardViewMinWidth - return JamiTheme.mainViewPreferredWidth - } - height: { - if (checkLoadedSource() === MainApplicationWindow.LoadedSource.WizardView) - return JamiTheme.wizardViewMinHeight - return JamiTheme.mainViewPreferredHeight - } - minimumWidth: { - if (checkLoadedSource() === MainApplicationWindow.LoadedSource.WizardView) - return JamiTheme.wizardViewMinWidth - return JamiTheme.mainViewMinWidth - } - minimumHeight: { - if (checkLoadedSource() === MainApplicationWindow.LoadedSource.WizardView) - return JamiTheme.wizardViewMinHeight - return JamiTheme.mainViewMinHeight - } - - visible: mainApplicationLoader.status === Loader.Ready + visible: mainApplicationLoader.status === Loader.Ready && windowSettingsLoaded // To facilitate reparenting of the callview during // fullscreen mode, we need QQuickItem based object. @@ -143,10 +130,47 @@ ApplicationWindow { } } + // Set `visible = false` when loading a new QML file. + onSourceChanged: windowSettingsLoaded = false + onLoaded: { if (UtilsAdapter.getAppValue(Settings.StartMinimized)) { showMinimized() + } else { + if (checkLoadedSource() === MainApplicationWindow.LoadedSource.WizardView) { + appWindow.width = JamiTheme.wizardViewMinWidth + appWindow.height = JamiTheme.wizardViewMinHeight + appWindow.minimumWidth = JamiTheme.wizardViewMinWidth + appWindow.minimumHeight = JamiTheme.wizardViewMinHeight + } else { + // Main window, load settings if possible. + var geometry = AppSettingsManager.getValue(Settings.WindowGeometry) + + // Position. + if (!isNaN(geometry.x) && !isNaN(geometry.y)) { + appWindow.x = geometry.x + appWindow.y = geometry.y + } + + // Dimensions. + appWindow.width = geometry.width ? + geometry.width : + JamiTheme.mainViewPreferredWidth + appWindow.height = geometry.height ? + geometry.height : + JamiTheme.mainViewPreferredHeight + appWindow.minimumWidth = JamiTheme.mainViewMinWidth + appWindow.minimumHeight = JamiTheme.mainViewMinHeight + + // State. + const visibilityStr = AppSettingsManager.getValue(Settings.WindowState) + appWindow.visibility = parseInt(visibilityStr) + } } + + // This will trigger `visible = true`. + windowSettingsLoaded = true + // Quiet check for updates on start if set to. if (UtilsAdapter.getAppValue(Settings.AutoUpdate)) { UpdateManager.checkForUpdates(true) @@ -170,6 +194,14 @@ ApplicationWindow { } } + Connections { + target: MainApplication + + function onCloseRequested() { + close(true) + } + } + Connections { target: { if (Qt.platform.os !== "windows" && Qt.platform.os !== "macos") diff --git a/src/appsettingsmanager.cpp b/src/appsettingsmanager.cpp index e719a19f6..614a027c8 100644 --- a/src/appsettingsmanager.cpp +++ b/src/appsettingsmanager.cpp @@ -1,4 +1,4 @@ -/*! +/* * Copyright (C) 2021-2022 Savoir-faire Linux Inc. * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> * @@ -20,6 +20,9 @@ #include "appsettingsmanager.h" +const QString defaultDownloadPath = QStandardPaths::writableLocation( + QStandardPaths::DownloadLocation); + AppSettingsManager::AppSettingsManager(QObject* parent) : QObject(parent) , settings_(new QSettings("jami.net", "Jami", this)) diff --git a/src/appsettingsmanager.h b/src/appsettingsmanager.h index b18e02dd5..5c6586b19 100644 --- a/src/appsettingsmanager.h +++ b/src/appsettingsmanager.h @@ -1,4 +1,4 @@ -/*! +/* * Copyright (C) 2020-2022 Savoir-faire Linux Inc. * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> * @@ -26,9 +26,9 @@ #include <QObject> #include <QString> #include <QStandardPaths> +#include <QWindow> // for QWindow::AutomaticVisibility -const QString defaultDownloadPath = QStandardPaths::writableLocation( - QStandardPaths::DownloadLocation); +extern const QString defaultDownloadPath; // clang-format off #define KEYS \ @@ -44,11 +44,13 @@ const QString defaultDownloadPath = QStandardPaths::writableLocation( X(EnableDarkTheme, false) \ X(AutoUpdate, true) \ X(StartMinimized, false) \ - X(NeverShowMeAgain, false) + X(NeverShowMeAgain, false) \ + X(WindowGeometry, QRectF(qQNaN(), qQNaN(), 0., 0.)) \ + X(WindowState, QWindow::AutomaticVisibility) /* * A class to expose settings keys in both c++ and QML. - * Note: this using a non-constructable class instead of a + * Note: this is using a non-constructable class instead of a * namespace allows for QML enum auto-completion in QtCreator. * This works well when there is only one enum class. Otherwise, * to prevent element name collision when defining multiple enums, diff --git a/src/lrcinstance.cpp b/src/lrcinstance.cpp index d5b52c80e..2318d37cf 100644 --- a/src/lrcinstance.cpp +++ b/src/lrcinstance.cpp @@ -25,7 +25,6 @@ #include <QObject> #include <QPixmap> #include <QRegularExpression> -#include <QSettings> #include <QtConcurrent/QtConcurrent> LRCInstance::LRCInstance(migrateCallback willMigrateCb, diff --git a/src/mainapplication.cpp b/src/mainapplication.cpp index 27aa5f4c9..918200bad 100644 --- a/src/mainapplication.cpp +++ b/src/mainapplication.cpp @@ -248,7 +248,8 @@ MainApplication::init() initQmlLayer(); - settingsManager_->setValue(Settings::Key::StartMinimized, results[opts::STARTMINIMIZED].toBool()); + settingsManager_->setValue(Settings::Key::StartMinimized, + results[opts::STARTMINIMIZED].toBool()); initSystray(); @@ -441,13 +442,14 @@ MainApplication::initSystray() #endif QAction* quitAction = new QAction(quitString, this); - connect(quitAction, &QAction::triggered, this, &MainApplication::cleanup); + connect(quitAction, &QAction::triggered, this, &MainApplication::closeRequested); QAction* restoreAction = new QAction(tr("&Show Jami"), this); connect(restoreAction, &QAction::triggered, this, &MainApplication::restoreApp); connect(systemTray_.get(), &QSystemTrayIcon::activated, + this, [this](QSystemTrayIcon::ActivationReason reason) { if (reason != QSystemTrayIcon::ActivationReason::Context) { #ifdef Q_OS_WINDOWS diff --git a/src/mainapplication.h b/src/mainapplication.h index 2c0baf50a..53a1ceb07 100644 --- a/src/mainapplication.h +++ b/src/mainapplication.h @@ -65,6 +65,9 @@ public: bool init(); void restoreApp(); +Q_SIGNALS: + void closeRequested(); + private: void vsConsoleDebug(); void fileDebug(QFile* debugFile); diff --git a/src/qmlregister.cpp b/src/qmlregister.cpp index 9375c8d07..fd4dab122 100644 --- a/src/qmlregister.cpp +++ b/src/qmlregister.cpp @@ -103,7 +103,7 @@ registerTypes(QQmlEngine* engine, AppSettingsManager* settingsManager, PreviewEngine* previewEngine, ScreenInfo* screenInfo, - QObject* parent) + MainApplication* parent) { // setup the adapters (their lifetimes are that of MainApplication) auto callAdapter = new CallAdapter(systemTray, lrcInstance, parent); @@ -180,6 +180,7 @@ registerTypes(QQmlEngine* engine, QML_REGISTERSINGLETONTYPE_URL(NS_CONSTANTS, "qrc:/src/constant/JamiResources.qml", JamiResources); QML_REGISTERSINGLETONTYPE_URL(NS_CONSTANTS, "qrc:/src/constant/MsgSeq.qml", MsgSeq); + QML_REGISTERSINGLETONTYPE_POBJECT(NS_CONSTANTS, parent, "MainApplication") QML_REGISTERSINGLETONTYPE_POBJECT(NS_CONSTANTS, screenInfo, "CurrentScreenInfo") QML_REGISTERSINGLETONTYPE_POBJECT(NS_CONSTANTS, lrcInstance, "LRCInstance") QML_REGISTERSINGLETONTYPE_POBJECT(NS_CONSTANTS, settingsManager, "AppSettingsManager") diff --git a/src/qmlregister.h b/src/qmlregister.h index 31eded091..38bfd091e 100644 --- a/src/qmlregister.h +++ b/src/qmlregister.h @@ -35,6 +35,7 @@ class LRCInstance; class AppSettingsManager; class PreviewEngine; class ScreenInfo; +class MainApplication; // Hack for QtCreator autocomplete (part 1) // https://bugreports.qt.io/browse/QTCREATORBUG-20569 @@ -66,5 +67,5 @@ void registerTypes(QQmlEngine* engine, AppSettingsManager* appSettingsManager, PreviewEngine* previewEngine, ScreenInfo* screenInfo, - QObject* parent); + MainApplication* parent); } -- GitLab