From 55d5a706564de4e22d4c1ed020fa8bdf3706f8e6 Mon Sep 17 00:00:00 2001 From: Marco Allegretti Date: Tue, 3 Feb 2026 11:22:11 +0100 Subject: [PATCH] Persist window size across restarts --- src/config.cpp | 85 ++++++++++++++++++++++++++++++++++++++++++++++++ src/config.h | 21 ++++++++++++ src/qml/Main.qml | 53 ++++++++++++++++++++++++++++++ 3 files changed, 159 insertions(+) diff --git a/src/config.cpp b/src/config.cpp index 3007377..8333ce4 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -279,6 +279,74 @@ void Config::setTheme(const QString &theme) } } +int Config::windowWidth() const +{ + return m_windowWidth; +} + +void Config::setWindowWidth(int width) +{ + width = qBound(0, width, 10000); + if (m_windowWidth != width) { + m_windowWidth = width; + save(); + Q_EMIT windowWidthChanged(); + } +} + +int Config::windowHeight() const +{ + return m_windowHeight; +} + +void Config::setWindowHeight(int height) +{ + height = qBound(0, height, 10000); + if (m_windowHeight != height) { + m_windowHeight = height; + save(); + Q_EMIT windowHeightChanged(); + } +} + +bool Config::windowMaximized() const +{ + return m_windowMaximized; +} + +void Config::setWindowMaximized(bool maximized) +{ + if (m_windowMaximized != maximized) { + m_windowMaximized = maximized; + save(); + Q_EMIT windowMaximizedChanged(); + } +} + +void Config::setWindowSize(int width, int height) +{ + width = qBound(0, width, 10000); + height = qBound(0, height, 10000); + + const bool widthChanged = m_windowWidth != width; + const bool heightChanged = m_windowHeight != height; + + if (!widthChanged && !heightChanged) { + return; + } + + m_windowWidth = width; + m_windowHeight = height; + save(); + + if (widthChanged) { + Q_EMIT windowWidthChanged(); + } + if (heightChanged) { + Q_EMIT windowHeightChanged(); + } +} + void Config::save() { const auto config = KSharedConfig::openConfig(QStringLiteral("alakarterc")); @@ -308,6 +376,11 @@ void Config::save() behaviorGroup.writeEntry(QStringLiteral("exitAfterLaunch"), m_exitAfterLaunch); behaviorGroup.writeEntry(QStringLiteral("coverLaunchesGame"), m_coverLaunchesGame); + KConfigGroup windowGroup(config, QStringLiteral("Window")); + windowGroup.writeEntry(QStringLiteral("width"), m_windowWidth); + windowGroup.writeEntry(QStringLiteral("height"), m_windowHeight); + windowGroup.writeEntry(QStringLiteral("maximized"), m_windowMaximized); + config->sync(); } @@ -339,6 +412,11 @@ void Config::load() m_animatedCovers = behaviorGroup.readEntry(QStringLiteral("animatedCovers"), false); m_exitAfterLaunch = behaviorGroup.readEntry(QStringLiteral("exitAfterLaunch"), false); m_coverLaunchesGame = behaviorGroup.readEntry(QStringLiteral("coverLaunchesGame"), false); + + const KConfigGroup windowGroup(config, QStringLiteral("Window")); + m_windowWidth = windowGroup.readEntry(QStringLiteral("width"), 0); + m_windowHeight = windowGroup.readEntry(QStringLiteral("height"), 0); + m_windowMaximized = windowGroup.readEntry(QStringLiteral("maximized"), false); } void Config::resetToDefaults() @@ -363,6 +441,10 @@ void Config::resetToDefaults() m_animatedCovers = false; m_theme.clear(); + m_windowWidth = 0; + m_windowHeight = 0; + m_windowMaximized = false; + save(); Q_EMIT viewModeChanged(); @@ -384,4 +466,7 @@ void Config::resetToDefaults() Q_EMIT highQualityImagesChanged(); Q_EMIT animatedCoversChanged(); Q_EMIT themeChanged(); + Q_EMIT windowWidthChanged(); + Q_EMIT windowHeightChanged(); + Q_EMIT windowMaximizedChanged(); } diff --git a/src/config.h b/src/config.h index 0ab65c0..4722065 100644 --- a/src/config.h +++ b/src/config.h @@ -30,6 +30,9 @@ class Config : public QObject Q_PROPERTY(bool animatedCovers READ animatedCovers WRITE setAnimatedCovers NOTIFY animatedCoversChanged) Q_PROPERTY(bool coverLaunchesGame READ coverLaunchesGame WRITE setCoverLaunchesGame NOTIFY coverLaunchesGameChanged) Q_PROPERTY(QString theme READ theme WRITE setTheme NOTIFY themeChanged) + Q_PROPERTY(int windowWidth READ windowWidth WRITE setWindowWidth NOTIFY windowWidthChanged) + Q_PROPERTY(int windowHeight READ windowHeight WRITE setWindowHeight NOTIFY windowHeightChanged) + Q_PROPERTY(bool windowMaximized READ windowMaximized WRITE setWindowMaximized NOTIFY windowMaximizedChanged) public: enum ViewMode { @@ -105,10 +108,21 @@ public: QString theme() const; void setTheme(const QString &theme); + int windowWidth() const; + void setWindowWidth(int width); + + int windowHeight() const; + void setWindowHeight(int height); + + bool windowMaximized() const; + void setWindowMaximized(bool maximized); + Q_INVOKABLE void save(); Q_INVOKABLE void load(); Q_INVOKABLE void resetToDefaults(); + Q_INVOKABLE void setWindowSize(int width, int height); + Q_SIGNALS: void viewModeChanged(); void uiModeChanged(); @@ -129,6 +143,9 @@ Q_SIGNALS: void animatedCoversChanged(); void coverLaunchesGameChanged(); void themeChanged(); + void windowWidthChanged(); + void windowHeightChanged(); + void windowMaximizedChanged(); private: ViewMode m_viewMode = GridView; @@ -150,4 +167,8 @@ private: bool m_highQualityImages = true; bool m_animatedCovers = false; QString m_theme; + + int m_windowWidth = 0; + int m_windowHeight = 0; + bool m_windowMaximized = false; }; diff --git a/src/qml/Main.qml b/src/qml/Main.qml index a879bc4..702dd4d 100644 --- a/src/qml/Main.qml +++ b/src/qml/Main.qml @@ -4,6 +4,7 @@ import QtQuick import QtQuick.Controls as QQC2 import QtQuick.Layouts +import QtQuick.Window import org.kde.kirigami as Kirigami import org.kde.kirigamiaddons.formcard as FormCard import org.kde.alakarte @@ -18,6 +19,45 @@ Kirigami.ApplicationWindow { width: Kirigami.Units.gridUnit * 55 height: Kirigami.Units.gridUnit * 40 + property bool windowGeometryRestored: false + + Timer { + id: windowGeometrySaveTimer + interval: 400 + repeat: false + onTriggered: { + if (!root.windowGeometryRestored) return + if (root.isMobile) return + if (root.visibility === Window.Maximized || root.visibility === Window.FullScreen) return + App.config.setWindowSize(root.width, root.height) + } + } + + onWidthChanged: { + if (!root.windowGeometryRestored) return + if (root.isMobile) return + windowGeometrySaveTimer.restart() + } + onHeightChanged: { + if (!root.windowGeometryRestored) return + if (root.isMobile) return + windowGeometrySaveTimer.restart() + } + + onVisibilityChanged: { + if (!root.windowGeometryRestored) return + if (root.isMobile) return + App.config.windowMaximized = root.visibility === Window.Maximized + } + + onClosing: function(close) { + if (root.isMobile) return + App.config.windowMaximized = root.visibility === Window.Maximized + if (root.visibility !== Window.Maximized && root.visibility !== Window.FullScreen) { + App.config.setWindowSize(root.width, root.height) + } + } + property var selectedGame: null property var pendingRemoveGame: null property string currentSource: "all" @@ -1980,6 +2020,19 @@ Kirigami.ApplicationWindow { } Component.onCompleted: { + if (!root.isMobile) { + const savedW = App.config.windowWidth + const savedH = App.config.windowHeight + if (savedW > 0) root.width = Math.max(root.minimumWidth, savedW) + if (savedH > 0) root.height = Math.max(root.minimumHeight, savedH) + root.windowGeometryRestored = true + if (App.config.windowMaximized) { + root.showMaximized() + } + } else { + root.windowGeometryRestored = true + } + if (App.gameModel.count === 0) { importSheet.open() }