File indexing completed on 2024-05-12 03:54:29

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     /**
0063      * Create a new window state saver for @p widget.
0064      * Use this for widgets that aren't shown yet and would still return @c nullptr from windowHandle().
0065      * @param configGroup A KConfigGroup that holds the window state.
0066      */
0067     template<typename Widget>
0068     explicit inline KWindowStateSaver(Widget *widget, const KConfigGroup &configGroup);
0069     /**
0070      * Create a new window state saver for @p widget.
0071      * Use this for widgets that aren't shown yet and would still return @c nullptr from windowHandle().
0072      * @param configGroupName The name of a KConfigGroup in the default state
0073      * configuration (see KSharedConfig::openStateConfig) that holds the window state.
0074      */
0075     template<typename Widget>
0076     explicit inline KWindowStateSaver(Widget *widget, const QString &configGroupName);
0077 
0078     ~KWindowStateSaver();
0079 
0080 private:
0081     void timerEvent(QTimerEvent *event) override;
0082     bool eventFilter(QObject *watched, QEvent *event) override;
0083 
0084     // API used by template code, so technically part of the ABI
0085     void initWidget(QObject *widget, const std::function<QWindow *()> &windowHandleCallback, const KConfigGroup &configGroup);
0086     void initWidget(QObject *widget, const std::function<QWindow *()> &windowHandleCallback, const QString &configGroupName);
0087 
0088     // cannot use std::unique_ptr due to the template ctors
0089     // not seeing the full private class
0090     KWindowStateSaverPrivate *d = nullptr;
0091 };
0092 
0093 template<typename Widget>
0094 KWindowStateSaver::KWindowStateSaver(Widget *widget, const KConfigGroup &configGroup)
0095     : QObject(widget)
0096 {
0097     initWidget(
0098         widget,
0099         [widget]() {
0100             return widget->windowHandle();
0101         },
0102         configGroup);
0103 }
0104 
0105 template<typename Widget>
0106 KWindowStateSaver::KWindowStateSaver(Widget *widget, const QString &configGroupName)
0107     : QObject(widget)
0108 {
0109     initWidget(
0110         widget,
0111         [widget]() {
0112             return widget->windowHandle();
0113         },
0114         configGroupName);
0115 }
0116 
0117 #endif // KWINDOWSTATESAVER_H