File indexing completed on 2024-05-12 15:34:14

0001 /*
0002     SPDX-FileCopyrightText: 2022 Volker Krause <vkrause@kde.org>
0003     SPDX-License-Identifier: LGPL-2.0-or-later
0004 */
0005 
0006 #ifndef KWINDOWSTATESAVER_H
0007 #define KWINDOWSTATESAVER_H
0008 
0009 #include <kconfiggroup.h>
0010 #include <kconfiggui_export.h>
0011 
0012 #include <QObject>
0013 
0014 class QWindow;
0015 class KWindowStateSaverPrivate;
0016 
0017 /**
0018  * Saves and restores a window size and (when possible) position.
0019  *
0020  * This is useful for retrofitting persisting window geometry on existing windows or dialogs,
0021  * without having to modify those classes themselves, or having to inherit from them.
0022  * For this, create a new instance of KWindowStateSaver for every window that should have it's
0023  * state persisted, and pass it the window or widget as well as the config group the state
0024  * should be stored in. The KWindowStateSaver will restore an existing state and then monitor
0025  * the window for subsequent changes to persist. It will delete itself once the window is
0026  * deleted.
0027  *
0028  * @code
0029  * QPrintPreviewDialog dlg = ...
0030  * new KWindowStateSaver(&dlg, "printPreviewDialogState");
0031  * ...
0032  * dlg.exec();
0033  * @endcode
0034  *
0035  * Note that freshly created top-level QWidgets (such as the dialog in the above example)
0036  * do not have an associated QWindow yet (ie. windowHandle() return @c nullptr). KWindowStateSaver
0037  * supports this with its QWidget constructors which will monitor the widget for having
0038  * its associated QWindow created before continuing with that.
0039  *
0040  * When implementing your own windows/dialogs, using KWindowConfig directly can be an
0041  * alternative.
0042  *
0043  * @see KWindowConfig
0044  * @since 5.92
0045  */
0046 class KCONFIGGUI_EXPORT KWindowStateSaver : public QObject
0047 {
0048     Q_OBJECT
0049 public:
0050     /**
0051      * Create a new window state saver for @p window.
0052      * @param configGroup A KConfigGroup that holds the window state.
0053      */
0054     explicit KWindowStateSaver(QWindow *window, const KConfigGroup &configGroup);
0055     /**
0056      * Create a new window state saver for @p window.
0057      * @param configGroupName The name of a KConfigGroup in the default state
0058      * configuration (see KSharedConfig::openStateConfig) that holds the window state.
0059      */
0060     explicit KWindowStateSaver(QWindow *window, const QString &configGroupName);
0061     /**
0062      * Create a new window state saver for @p window.
0063      * @param configGroupName The name of a KConfigGroup in the default state
0064      * configuration (see KSharedConfig::openStateConfig) that holds the window state.
0065      */
0066     explicit KWindowStateSaver(QWindow *window, const char *configGroupName);
0067 
0068     /**
0069      * Create a new window state saver for @p widget.
0070      * Use this for widgets that aren't shown yet and would still return @c nullptr from windowHandle().
0071      * @param configGroup A KConfigGroup that holds the window state.
0072      */
0073     template<typename Widget>
0074     explicit inline KWindowStateSaver(Widget *widget, const KConfigGroup &configGroup);
0075     /**
0076      * Create a new window state saver for @p widget.
0077      * Use this for widgets that aren't shown yet and would still return @c nullptr from windowHandle().
0078      * @param configGroupName The name of a KConfigGroup in the default state
0079      * configuration (see KSharedConfig::openStateConfig) that holds the window state.
0080      */
0081     template<typename Widget>
0082     explicit inline KWindowStateSaver(Widget *widget, const QString &configGroupName);
0083     /**
0084      * Create a new window state saver for @p widget.
0085      * Use this for widgets that aren't shown yet and would still return @c nullptr from windowHandle().
0086      * @param configGroupName The name of a KConfigGroup in the default state
0087      * configuration (see KSharedConfig::openStateConfig) that holds the window state.
0088      */
0089     template<typename Widget>
0090     explicit inline KWindowStateSaver(Widget *widget, const char *configGroupName);
0091 
0092     ~KWindowStateSaver();
0093 
0094 private:
0095     void timerEvent(QTimerEvent *event) override;
0096     bool eventFilter(QObject *watched, QEvent *event) override;
0097 
0098     // API used by template code, so technically part of the ABI
0099     void initWidget(QObject *widget, const std::function<QWindow *()> &windowHandleCallback, const KConfigGroup &configGroup);
0100     void initWidget(QObject *widget, const std::function<QWindow *()> &windowHandleCallback, const QString &configGroupName);
0101     void initWidget(QObject *widget, const std::function<QWindow *()> &windowHandleCallback, const char *configGroupName);
0102 
0103     // cannot use std::unique_ptr due to the template ctors
0104     // not seeing the full private class
0105     KWindowStateSaverPrivate *d = nullptr;
0106 };
0107 
0108 template<typename Widget>
0109 KWindowStateSaver::KWindowStateSaver(Widget *widget, const KConfigGroup &configGroup)
0110     : QObject(widget)
0111 {
0112     initWidget(
0113         widget,
0114         [widget]() {
0115             return widget->windowHandle();
0116         },
0117         configGroup);
0118 }
0119 
0120 template<typename Widget>
0121 KWindowStateSaver::KWindowStateSaver(Widget *widget, const QString &configGroupName)
0122     : QObject(widget)
0123 {
0124     initWidget(
0125         widget,
0126         [widget]() {
0127             return widget->windowHandle();
0128         },
0129         configGroupName);
0130 }
0131 
0132 template<typename Widget>
0133 KWindowStateSaver::KWindowStateSaver(Widget *widget, const char *configGroupName)
0134     : QObject(widget)
0135 {
0136     initWidget(
0137         widget,
0138         [widget]() {
0139             return widget->windowHandle();
0140         },
0141         configGroupName);
0142 }
0143 
0144 #endif // KWINDOWSTATESAVER_H