1 | /* |
2 | * SPDX-FileCopyrightText: 2023 Marco Martin <mart@kde.org> |
3 | * SPDX-FileCopyrightText: 2023 ivan tkachenko <me@ratijas.tk> |
4 | * |
5 | * SPDX-License-Identifier: LGPL-2.0-or-later |
6 | */ |
7 | |
8 | #include "headerfooterlayout.h" |
9 | |
10 | #include <QDebug> |
11 | #include <QTimer> |
12 | |
13 | HeaderFooterLayout::(QQuickItem *parent) |
14 | : QQuickItem(parent) |
15 | , m_isDirty(false) |
16 | , m_performingLayout(false) |
17 | { |
18 | } |
19 | |
20 | HeaderFooterLayout::() |
21 | { |
22 | disconnectItem(item: m_header); |
23 | disconnectItem(item: m_contentItem); |
24 | disconnectItem(item: m_footer); |
25 | }; |
26 | |
27 | void HeaderFooterLayout::(QQuickItem *item) |
28 | { |
29 | if (m_header == item) { |
30 | return; |
31 | } |
32 | |
33 | if (m_header) { |
34 | disconnectItem(item: m_header); |
35 | m_header->setParentItem(nullptr); |
36 | } |
37 | |
38 | m_header = item; |
39 | |
40 | if (m_header) { |
41 | m_header->setParentItem(this); |
42 | if (m_header->z() == 0) { |
43 | m_header->setZ(1); |
44 | } |
45 | |
46 | connect(sender: m_header, signal: &QQuickItem::implicitWidthChanged, context: this, slot: &HeaderFooterLayout::markAsDirty); |
47 | connect(sender: m_header, signal: &QQuickItem::implicitHeightChanged, context: this, slot: &HeaderFooterLayout::markAsDirty); |
48 | connect(sender: m_header, signal: &QQuickItem::visibleChanged, context: this, slot: &HeaderFooterLayout::markAsDirty); |
49 | |
50 | if (m_header->inherits(classname: "QQuickTabBar" ) || m_header->inherits(classname: "QQuickToolBar" ) || m_header->inherits(classname: "QQuickDialogButtonBox" )) { |
51 | // Assume 0 is Header for all 3 types |
52 | m_header->setProperty(name: "position" , value: 0); |
53 | } |
54 | } |
55 | |
56 | markAsDirty(); |
57 | |
58 | Q_EMIT headerChanged(); |
59 | } |
60 | |
61 | QQuickItem *HeaderFooterLayout::() |
62 | { |
63 | return m_header; |
64 | } |
65 | |
66 | void HeaderFooterLayout::(QQuickItem *item) |
67 | { |
68 | if (m_contentItem == item) { |
69 | return; |
70 | } |
71 | |
72 | if (m_contentItem) { |
73 | disconnectItem(item: m_contentItem); |
74 | m_contentItem->setParentItem(nullptr); |
75 | } |
76 | |
77 | m_contentItem = item; |
78 | |
79 | if (m_contentItem) { |
80 | m_contentItem->setParentItem(this); |
81 | connect(sender: m_contentItem, signal: &QQuickItem::implicitWidthChanged, context: this, slot: &HeaderFooterLayout::markAsDirty); |
82 | connect(sender: m_contentItem, signal: &QQuickItem::implicitHeightChanged, context: this, slot: &HeaderFooterLayout::markAsDirty); |
83 | connect(sender: m_contentItem, signal: &QQuickItem::visibleChanged, context: this, slot: &HeaderFooterLayout::markAsDirty); |
84 | } |
85 | |
86 | markAsDirty(); |
87 | |
88 | Q_EMIT contentItemChanged(); |
89 | } |
90 | |
91 | QQuickItem *HeaderFooterLayout::() |
92 | { |
93 | return m_contentItem; |
94 | } |
95 | |
96 | void HeaderFooterLayout::(QQuickItem *item) |
97 | { |
98 | if (m_footer == item) { |
99 | return; |
100 | } |
101 | |
102 | if (m_footer) { |
103 | disconnectItem(item: m_footer); |
104 | m_footer->setParentItem(nullptr); |
105 | } |
106 | |
107 | m_footer = item; |
108 | |
109 | if (m_footer) { |
110 | m_footer->setParentItem(this); |
111 | if (m_footer->z() == 0) { |
112 | m_footer->setZ(1); |
113 | } |
114 | |
115 | connect(sender: m_footer, signal: &QQuickItem::implicitWidthChanged, context: this, slot: &HeaderFooterLayout::markAsDirty); |
116 | connect(sender: m_footer, signal: &QQuickItem::implicitHeightChanged, context: this, slot: &HeaderFooterLayout::markAsDirty); |
117 | connect(sender: m_footer, signal: &QQuickItem::visibleChanged, context: this, slot: &HeaderFooterLayout::markAsDirty); |
118 | |
119 | if (m_footer->inherits(classname: "QQuickTabBar" ) || m_footer->inherits(classname: "QQuickToolBar" ) || m_footer->inherits(classname: "QQuickDialogButtonBox" )) { |
120 | // Assume 1 is Footer for all 3 types |
121 | m_footer->setProperty(name: "position" , value: 1); |
122 | } |
123 | } |
124 | |
125 | markAsDirty(); |
126 | |
127 | Q_EMIT footerChanged(); |
128 | } |
129 | |
130 | QQuickItem *HeaderFooterLayout::() |
131 | { |
132 | return m_footer; |
133 | } |
134 | |
135 | void HeaderFooterLayout::() |
136 | { |
137 | updatePolish(); |
138 | } |
139 | |
140 | void HeaderFooterLayout::(const QRectF &newGeometry, const QRectF &oldGeometry) |
141 | { |
142 | if (newGeometry != oldGeometry) { |
143 | markAsDirty(); |
144 | } |
145 | |
146 | QQuickItem::geometryChange(newGeometry, oldGeometry); |
147 | } |
148 | |
149 | void HeaderFooterLayout::() |
150 | { |
151 | QQuickItem::componentComplete(); |
152 | if (m_isDirty) { |
153 | performLayout(); |
154 | } |
155 | } |
156 | |
157 | void HeaderFooterLayout::() |
158 | { |
159 | if (m_isDirty) { |
160 | performLayout(); |
161 | } |
162 | } |
163 | |
164 | void HeaderFooterLayout::() |
165 | { |
166 | if (!m_isDirty) { |
167 | m_isDirty = true; |
168 | polish(); |
169 | } |
170 | } |
171 | |
172 | void HeaderFooterLayout::() |
173 | { |
174 | if (!isComponentComplete() || m_performingLayout) { |
175 | return; |
176 | } |
177 | |
178 | m_isDirty = false; |
179 | m_performingLayout = true; |
180 | |
181 | // Implicit size has to be updated first, as it may propagate to the |
182 | // actual size which will be used below during layouting. |
183 | updateImplicitSize(); |
184 | |
185 | const QSizeF newSize = size(); |
186 | qreal = 0; |
187 | qreal = 0; |
188 | |
189 | if (m_header) { |
190 | m_header->setWidth(newSize.width()); |
191 | if (m_header->isVisible()) { |
192 | headerHeight = m_header->height(); |
193 | } |
194 | } |
195 | if (m_footer) { |
196 | m_footer->setY(newSize.height() - m_footer->height()); |
197 | m_footer->setWidth(newSize.width()); |
198 | if (m_footer->isVisible()) { |
199 | footerHeight = m_footer->height(); |
200 | } |
201 | } |
202 | if (m_contentItem) { |
203 | m_contentItem->setY(headerHeight); |
204 | m_contentItem->setWidth(newSize.width()); |
205 | m_contentItem->setHeight(newSize.height() - headerHeight - footerHeight); |
206 | } |
207 | |
208 | m_performingLayout = false; |
209 | } |
210 | |
211 | void HeaderFooterLayout::() |
212 | { |
213 | qreal impWidth = 0; |
214 | qreal impHeight = 0; |
215 | |
216 | if (m_header && m_header->isVisible()) { |
217 | impWidth = std::max(a: impWidth, b: m_header->implicitWidth()); |
218 | impHeight += m_header->implicitHeight(); |
219 | } |
220 | if (m_footer && m_footer->isVisible()) { |
221 | impWidth = std::max(a: impWidth, b: m_footer->implicitWidth()); |
222 | impHeight += m_footer->implicitHeight(); |
223 | } |
224 | if (m_contentItem && m_contentItem->isVisible()) { |
225 | impWidth = std::max(a: impWidth, b: m_contentItem->implicitWidth()); |
226 | impHeight += m_contentItem->implicitHeight(); |
227 | } |
228 | setImplicitSize(impWidth, impHeight); |
229 | } |
230 | |
231 | void HeaderFooterLayout::(QQuickItem *item) |
232 | { |
233 | if (item) { |
234 | disconnect(sender: item, signal: &QQuickItem::implicitWidthChanged, receiver: this, slot: &HeaderFooterLayout::markAsDirty); |
235 | disconnect(sender: item, signal: &QQuickItem::implicitHeightChanged, receiver: this, slot: &HeaderFooterLayout::markAsDirty); |
236 | disconnect(sender: item, signal: &QQuickItem::visibleChanged, receiver: this, slot: &HeaderFooterLayout::markAsDirty); |
237 | } |
238 | } |
239 | |
240 | #include "moc_headerfooterlayout.cpp" |
241 | |