1 | /* |
2 | * SPDX-FileCopyrightText: 2023 ivan tkachenko <me@ratijas.tk> |
3 | * |
4 | * SPDX-License-Identifier: LGPL-2.0-or-later |
5 | */ |
6 | |
7 | #ifndef OVERLAYZSTACKINGATTACHED_H |
8 | #define OVERLAYZSTACKINGATTACHED_H |
9 | |
10 | #include <QObject> |
11 | #include <QQmlEngine> |
12 | |
13 | #include <qqmlregistration.h> |
14 | |
15 | class QQuickItem; |
16 | |
17 | /** |
18 | * This attached property manages z-index for stacking overlays relative to each other. |
19 | * |
20 | * When a popup is about to show, OverlayZStacking object kicks in, searches for the |
21 | * next nearest popup in the QtQuick hierarchy of items, and sets its z value to the |
22 | * biggest of two: current stacking value for its layer, or parent's z index + 1. |
23 | * This way OverlayZStacking algorithm ensures that a popup is always stacked higher |
24 | * than its logical parent popup, but also no lower than its siblings on the same |
25 | * logical layer. |
26 | * |
27 | * @code |
28 | * import QtQuick.Controls as QQC2 |
29 | * import org.kde.kirigami as Kirigami |
30 | * |
31 | * QQC2.Popup { |
32 | * Kirigami.OverlayZStacking.layer: Kirigami.OverlayZStacking.ToolTip |
33 | * z: Kirigami.OverlayZStacking.z |
34 | * } |
35 | * @endcode |
36 | * |
37 | * @since 6.0 |
38 | */ |
39 | class OverlayZStackingAttached : public QObject |
40 | { |
41 | Q_OBJECT |
42 | QML_ELEMENT |
43 | QML_NAMED_ELEMENT(OverlayZStacking) |
44 | QML_UNCREATABLE("Cannot create objects of type OverlayZStacking, use it as an attached property" ) |
45 | QML_ATTACHED(OverlayZStackingAttached) |
46 | /** |
47 | * An optimal z-index that attachee popup should bind to. |
48 | */ |
49 | Q_PROPERTY(qreal z READ z NOTIFY zChanged FINAL) |
50 | |
51 | /** |
52 | * The logical stacking layer of attachee popup, akin to window manager's layers. |
53 | */ |
54 | Q_PROPERTY(Layer layer READ layer WRITE setLayer NOTIFY layerChanged FINAL) |
55 | |
56 | public: |
57 | enum Layer { |
58 | DefaultLowest = 0, |
59 | Drawer, |
60 | FullScreen, |
61 | Dialog, |
62 | , |
63 | Notification, |
64 | ToolTip, |
65 | }; |
66 | Q_ENUM(Layer) |
67 | |
68 | explicit OverlayZStackingAttached(QObject *parent = nullptr); |
69 | ~OverlayZStackingAttached() override; |
70 | |
71 | qreal z() const; |
72 | |
73 | Layer layer() const; |
74 | void setLayer(Layer layer); |
75 | |
76 | // QML attached property |
77 | static OverlayZStackingAttached *qmlAttachedProperties(QObject *object); |
78 | |
79 | Q_SIGNALS: |
80 | void zChanged(); |
81 | void layerChanged(); |
82 | |
83 | private Q_SLOTS: |
84 | // Popup shall not change z index while being open, so if changes arrive, we defer it until closed. |
85 | void enqueueSignal(); |
86 | void dispatchPendingSignal(); |
87 | |
88 | void (); |
89 | |
90 | private: |
91 | void (); |
92 | void (QObject *); |
93 | qreal () const; |
94 | static bool isVisible(const QObject *); |
95 | static bool (const QObject *object); |
96 | static QObject *(const QObject *); |
97 | static QQuickItem *(const QObject *); |
98 | static Layer (const QObject *); |
99 | static qreal defaultZForLayer(Layer layer); |
100 | |
101 | Layer m_layer = Layer::DefaultLowest; |
102 | QPointer<QObject> ; |
103 | bool m_pending; |
104 | }; |
105 | |
106 | QML_DECLARE_TYPEINFO(OverlayZStackingAttached, QML_HAS_ATTACHED_PROPERTIES) |
107 | |
108 | #endif // OVERLAYZSTACKINGATTACHED_H |
109 | |