1/*
2 SPDX-FileCopyrightText: 2022 Volker Krause <vkrause@kde.org>
3 SPDX-License-Identifier: LGPL-2.0-or-later
4*/
5
6#include "kwindowstatesaver.h"
7#include "ksharedconfig.h"
8#include "kwindowconfig.h"
9
10#include <QWindow>
11
12class KWindowStateSaverPrivate
13{
14public:
15 QWindow *window = nullptr;
16 KConfigGroup configGroup;
17 std::function<QWindow *()> windowHandleCallback;
18 int timerId = 0;
19
20 void init(KWindowStateSaver *q);
21 void initWidget(QObject *widget, KWindowStateSaver *q);
22};
23
24void KWindowStateSaverPrivate::init(KWindowStateSaver *q)
25{
26 if (!window) {
27 return;
28 }
29
30 KWindowConfig::restoreWindowSize(window, config: configGroup);
31 KWindowConfig::restoreWindowPosition(window, config: configGroup);
32
33 const auto saveSize = [q, this]() {
34 KWindowConfig::saveWindowSize(window, config&: configGroup);
35 if (!timerId) {
36 timerId = q->startTimer(time: std::chrono::seconds(30));
37 }
38 };
39 const auto savePosition = [q, this]() {
40 KWindowConfig::saveWindowPosition(window, config&: configGroup);
41 if (!timerId) {
42 timerId = q->startTimer(time: std::chrono::seconds(30));
43 }
44 };
45
46 QObject::connect(sender: window, signal: &QWindow::windowStateChanged, context: q, slot: saveSize);
47 QObject::connect(sender: window, signal: &QWindow::widthChanged, context: q, slot: saveSize);
48 QObject::connect(sender: window, signal: &QWindow::heightChanged, context: q, slot: saveSize);
49 QObject::connect(sender: window, signal: &QWindow::xChanged, context: q, slot: savePosition);
50 QObject::connect(sender: window, signal: &QWindow::yChanged, context: q, slot: savePosition);
51}
52
53void KWindowStateSaverPrivate::initWidget(QObject *widget, KWindowStateSaver *q)
54{
55 if (!window && windowHandleCallback) {
56 window = windowHandleCallback();
57 }
58 if (window) {
59 init(q);
60 } else {
61 widget->installEventFilter(filterObj: q);
62 }
63}
64
65KWindowStateSaver::KWindowStateSaver(QWindow *window, const KConfigGroup &configGroup)
66 : QObject(window)
67 , d(new KWindowStateSaverPrivate)
68{
69 Q_ASSERT(window);
70 d->window = window;
71 d->configGroup = configGroup;
72 d->init(q: this);
73}
74
75KWindowStateSaver::KWindowStateSaver(QWindow *window, const QString &configGroupName)
76 : QObject(window)
77 , d(new KWindowStateSaverPrivate)
78{
79 Q_ASSERT(window);
80 d->window = window;
81 d->configGroup = KConfigGroup(KSharedConfig::openStateConfig(), configGroupName);
82 d->init(q: this);
83}
84
85KWindowStateSaver::~KWindowStateSaver()
86{
87 delete d;
88}
89
90void KWindowStateSaver::timerEvent(QTimerEvent *event)
91{
92 killTimer(id: event->timerId());
93 d->configGroup.sync();
94 d->timerId = 0;
95}
96
97bool KWindowStateSaver::eventFilter(QObject *watched, QEvent *event)
98{
99 // QEvent::PlatformSurface would give us a valid window, but if there are
100 // initial resizings (explicitly or via layout constraints) those would then
101 // already overwrite our restored values. So wait until all that is done
102 // and only restore afterwards.
103 if (event->type() == QEvent::ShowToParent && !d->window) {
104 watched->removeEventFilter(obj: this);
105 d->window = d->windowHandleCallback();
106 d->init(q: this);
107 }
108
109 return QObject::eventFilter(watched, event);
110}
111
112void KWindowStateSaver::initWidget(QObject *widget, const std::function<QWindow *()> &windowHandleCallback, const KConfigGroup &configGroup)
113{
114 d = new KWindowStateSaverPrivate;
115 d->windowHandleCallback = windowHandleCallback;
116 d->configGroup = configGroup;
117 d->initWidget(widget, q: this);
118}
119
120void KWindowStateSaver::initWidget(QObject *widget, const std::function<QWindow *()> &windowHandleCallback, const QString &configGroupName)
121{
122 d = new KWindowStateSaverPrivate;
123 d->windowHandleCallback = windowHandleCallback;
124 d->configGroup = KConfigGroup(KSharedConfig::openStateConfig(), configGroupName);
125 d->initWidget(widget, q: this);
126}
127
128#include "moc_kwindowstatesaver.cpp"
129

source code of kconfig/src/gui/kwindowstatesaver.cpp