aboutsummaryrefslogtreecommitdiff
path: root/src/gui/kwindowstatesaver.h
blob: 47b6ae950b09eec1ff147385bbab0e045567fb82 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/*
    SPDX-FileCopyrightText: 2022 Volker Krause <vkrause@kde.org>
    SPDX-License-Identifier: LGPL-2.0-or-later
*/

#ifndef KWINDOWSTATESAVER_H
#define KWINDOWSTATESAVER_H

#include <kconfiggroup.h>
#include <kconfiggui_export.h>

#include <QObject>

class QWindow;
class KWindowStateSaverPrivate;

/**
 * Saves and restores a window size and (when possible) position.
 *
 * This is useful for retrofitting persisting window geometry on existing windows or dialogs,
 * without having to modify those classes themselves, or having to inherit from them.
 * For this, create a new instance of KWindowStateSaver for every window that should have it's
 * state persisted, and pass it the window or widget as well as the config group the state
 * should be stored in. The KWindowStateSaver will restore an existing state and then monitor
 * the window for subsequent changes to persist. It will delete itself once the window is
 * deleted.
 *
 * @code
 * QPrintPreviewDialog dlg = ...
 * new KWindowStateSaver(&dlg, "printPreviewDialogState");
 * ...
 * dlg.exec();
 * @endcode
 *
 * Note that freshly created top-level QWidgets (such as the dialog in the above example)
 * do not have an associated QWindow yet (ie. windowHandle() return @c nullptr). KWindowStateSaver
 * supports this with its QWidget constructors which will monitor the widget for having
 * its associated QWindow created before continuing with that.
 *
 * When implementing your own windows/dialogs, using KWindowConfig directly can be an
 * alternative.
 *
 * @see KWindowConfig
 * @since 5.92
 */
class KCONFIGGUI_EXPORT KWindowStateSaver : public QObject
{
    Q_OBJECT
public:
    /**
     * Create a new window state saver for @p window.
     * @param configGroup A KConfigGroup that holds the window state.
     */
    explicit KWindowStateSaver(QWindow *window, const KConfigGroup &configGroup);
    /**
     * Create a new window state saver for @p window.
     * @param configGroupName The name of a KConfigGroup in the default state
     * configuration (see KSharedConfig::openStateConfig) that holds the window state.
     */
    explicit KWindowStateSaver(QWindow *window, const QString &configGroupName);
    /**
     * Create a new window state saver for @p window.
     * @param configGroupName The name of a KConfigGroup in the default state
     * configuration (see KSharedConfig::openStateConfig) that holds the window state.
     */
    explicit KWindowStateSaver(QWindow *window, const char *configGroupName);

    /**
     * Create a new window state saver for @p widget.
     * Use this for widgets that aren't shown yet and would still return @c nullptr from windowHandle().
     * @param configGroup A KConfigGroup that holds the window state.
     */
    template<typename Widget>
    explicit inline KWindowStateSaver(Widget *widget, const KConfigGroup &configGroup);
    /**
     * Create a new window state saver for @p widget.
     * Use this for widgets that aren't shown yet and would still return @c nullptr from windowHandle().
     * @param configGroupName The name of a KConfigGroup in the default state
     * configuration (see KSharedConfig::openStateConfig) that holds the window state.
     */
    template<typename Widget>
    explicit inline KWindowStateSaver(Widget *widget, const QString &configGroupName);
    /**
     * Create a new window state saver for @p widget.
     * Use this for widgets that aren't shown yet and would still return @c nullptr from windowHandle().
     * @param configGroupName The name of a KConfigGroup in the default state
     * configuration (see KSharedConfig::openStateConfig) that holds the window state.
     */
    template<typename Widget>
    explicit inline KWindowStateSaver(Widget *widget, const char *configGroupName);

    ~KWindowStateSaver();

private:
    void timerEvent(QTimerEvent *event) override;
    bool eventFilter(QObject *watched, QEvent *event) override;

    // API used by template code, so technically part of the ABI
    void initWidget(QObject *widget, const std::function<QWindow *()> &windowHandleCallback, const KConfigGroup &configGroup);
    void initWidget(QObject *widget, const std::function<QWindow *()> &windowHandleCallback, const QString &configGroupName);
    void initWidget(QObject *widget, const std::function<QWindow *()> &windowHandleCallback, const char *configGroupName);

    // cannot use std::unique_ptr due to the template ctors
    // not seeing the full private class
    KWindowStateSaverPrivate *d = nullptr;
};

template<typename Widget>
KWindowStateSaver::KWindowStateSaver(Widget *widget, const KConfigGroup &configGroup)
    : QObject(widget)
{
    initWidget(
        widget,
        [widget]() {
            return widget->windowHandle();
        },
        configGroup);
}

template<typename Widget>
KWindowStateSaver::KWindowStateSaver(Widget *widget, const QString &configGroupName)
    : QObject(widget)
{
    initWidget(
        widget,
        [widget]() {
            return widget->windowHandle();
        },
        configGroupName);
}

template<typename Widget>
KWindowStateSaver::KWindowStateSaver(Widget *widget, const char *configGroupName)
    : QObject(widget)
{
    initWidget(
        widget,
        [widget]() {
            return widget->windowHandle();
        },
        configGroupName);
}

#endif // KWINDOWSTATESAVER_H