1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2017 The Qt Company Ltd. |
4 | ** Contact: http://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL3$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see http://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at http://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPLv3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or later as published by the Free |
28 | ** Software Foundation and appearing in the file LICENSE.GPL included in |
29 | ** the packaging of this file. Please review the following information to |
30 | ** ensure the GNU General Public License version 2.0 requirements will be |
31 | ** met: http://www.gnu.org/licenses/gpl-2.0.html. |
32 | ** |
33 | ** $QT_END_LICENSE$ |
34 | ** |
35 | ****************************************************************************/ |
36 | |
37 | #include "qquickpopupitem_p_p.h" |
38 | #include "qquickapplicationwindow_p.h" |
39 | #include "qquickshortcutcontext_p_p.h" |
40 | #include "qquickpage_p_p.h" |
41 | #include "qquickcontentitem_p.h" |
42 | #include "qquickpopup_p_p.h" |
43 | #include "qquickdeferredexecute_p_p.h" |
44 | |
45 | #if QT_CONFIG(shortcut) |
46 | # include <QtGui/private/qshortcutmap_p.h> |
47 | #endif |
48 | #include <QtGui/private/qguiapplication_p.h> |
49 | |
50 | #if QT_CONFIG(accessibility) |
51 | #include <QtQuick/private/qquickaccessibleattached_p.h> |
52 | #endif |
53 | |
54 | QT_BEGIN_NAMESPACE |
55 | |
56 | class : public QQuickPagePrivate |
57 | { |
58 | Q_DECLARE_PUBLIC(QQuickPopupItem) |
59 | |
60 | public: |
61 | QQuickPopupItemPrivate(QQuickPopup *); |
62 | |
63 | void implicitWidthChanged() override; |
64 | void implicitHeightChanged() override; |
65 | |
66 | void resolveFont() override; |
67 | void resolvePalette() override; |
68 | |
69 | QQuickItem *getContentItem() override; |
70 | |
71 | void cancelContentItem() override; |
72 | void executeContentItem(bool complete = false) override; |
73 | |
74 | void cancelBackground() override; |
75 | void executeBackground(bool complete = false) override; |
76 | |
77 | int = 0; |
78 | int = 0; |
79 | QQuickPopup * = nullptr; |
80 | }; |
81 | |
82 | QQuickPopupItemPrivate::(QQuickPopup *) |
83 | : popup(popup) |
84 | { |
85 | isTabFence = true; |
86 | } |
87 | |
88 | void QQuickPopupItemPrivate::() |
89 | { |
90 | QQuickPagePrivate::implicitWidthChanged(); |
91 | emit popup->implicitWidthChanged(); |
92 | } |
93 | |
94 | void QQuickPopupItemPrivate::() |
95 | { |
96 | QQuickPagePrivate::implicitHeightChanged(); |
97 | emit popup->implicitHeightChanged(); |
98 | } |
99 | |
100 | void QQuickPopupItemPrivate::() |
101 | { |
102 | if (QQuickApplicationWindow *window = qobject_cast<QQuickApplicationWindow *>(object: popup->window())) |
103 | inheritFont(font: window->font()); |
104 | else |
105 | inheritFont(font: QQuickTheme::font(scope: QQuickTheme::System)); |
106 | } |
107 | |
108 | void QQuickPopupItemPrivate::() |
109 | { |
110 | if (QQuickApplicationWindow *window = qobject_cast<QQuickApplicationWindow *>(object: popup->window())) |
111 | inheritPalette(palette: window->palette()); |
112 | else |
113 | inheritPalette(palette: QQuickTheme::palette(scope: QQuickTheme::System)); |
114 | } |
115 | |
116 | QQuickItem *QQuickPopupItemPrivate::() |
117 | { |
118 | Q_Q(QQuickPopupItem); |
119 | if (QQuickItem *item = QQuickPagePrivate::getContentItem()) |
120 | return item; |
121 | |
122 | return new QQuickContentItem(popup, q); |
123 | } |
124 | |
125 | static inline QString contentItemName() { return QStringLiteral("contentItem" ); } |
126 | |
127 | void QQuickPopupItemPrivate::() |
128 | { |
129 | quickCancelDeferred(object: popup, property: contentItemName()); |
130 | } |
131 | |
132 | void QQuickPopupItemPrivate::(bool complete) |
133 | { |
134 | if (contentItem.wasExecuted()) |
135 | return; |
136 | |
137 | if (!contentItem || complete) |
138 | quickBeginDeferred(object: popup, property: contentItemName(), delegate&: contentItem); |
139 | if (complete) |
140 | quickCompleteDeferred(object: popup, property: contentItemName(), delegate&: contentItem); |
141 | } |
142 | |
143 | static inline QString backgroundName() { return QStringLiteral("background" ); } |
144 | |
145 | void QQuickPopupItemPrivate::() |
146 | { |
147 | quickCancelDeferred(object: popup, property: backgroundName()); |
148 | } |
149 | |
150 | void QQuickPopupItemPrivate::(bool complete) |
151 | { |
152 | if (background.wasExecuted()) |
153 | return; |
154 | |
155 | if (!background || complete) |
156 | quickBeginDeferred(object: popup, property: backgroundName(), delegate&: background); |
157 | if (complete) |
158 | quickCompleteDeferred(object: popup, property: backgroundName(), delegate&: background); |
159 | } |
160 | |
161 | QQuickPopupItem::(QQuickPopup *) |
162 | : QQuickPage(*(new QQuickPopupItemPrivate(popup)), nullptr) |
163 | { |
164 | setParent(popup); |
165 | setFlag(flag: ItemIsFocusScope); |
166 | setAcceptedMouseButtons(Qt::AllButtons); |
167 | #if QT_CONFIG(quicktemplates2_multitouch) |
168 | setAcceptTouchEvents(true); |
169 | #endif |
170 | #if QT_CONFIG(cursor) |
171 | setCursor(Qt::ArrowCursor); |
172 | #endif |
173 | |
174 | #if QT_CONFIG(quicktemplates2_hover) |
175 | // TODO: switch to QStyleHints::useHoverEffects in Qt 5.8 |
176 | setHoverEnabled(true); |
177 | // setAcceptHoverEvents(QGuiApplication::styleHints()->useHoverEffects()); |
178 | // connect(QGuiApplication::styleHints(), &QStyleHints::useHoverEffectsChanged, this, &QQuickItem::setAcceptHoverEvents); |
179 | #endif |
180 | } |
181 | |
182 | void QQuickPopupItem::() |
183 | { |
184 | #if QT_CONFIG(shortcut) |
185 | Q_D(QQuickPopupItem); |
186 | QGuiApplicationPrivate *pApp = QGuiApplicationPrivate::instance(); |
187 | if (!d->backId) |
188 | d->backId = pApp->shortcutMap.addShortcut(owner: this, key: Qt::Key_Back, context: Qt::WindowShortcut, matcher: QQuickShortcutContext::matcher); |
189 | if (!d->escapeId) |
190 | d->escapeId = pApp->shortcutMap.addShortcut(owner: this, key: Qt::Key_Escape, context: Qt::WindowShortcut, matcher: QQuickShortcutContext::matcher); |
191 | #endif |
192 | } |
193 | |
194 | void QQuickPopupItem::() |
195 | { |
196 | #if QT_CONFIG(shortcut) |
197 | Q_D(QQuickPopupItem); |
198 | QGuiApplicationPrivate *pApp = QGuiApplicationPrivate::instance(); |
199 | if (d->backId) { |
200 | pApp->shortcutMap.removeShortcut(id: d->backId, owner: this); |
201 | d->backId = 0; |
202 | } |
203 | if (d->escapeId) { |
204 | pApp->shortcutMap.removeShortcut(id: d->escapeId, owner: this); |
205 | d->escapeId = 0; |
206 | } |
207 | #endif |
208 | } |
209 | |
210 | void QQuickPopupItem::() |
211 | { |
212 | Q_D(QQuickPopupItem); |
213 | return QQuickPopupPrivate::get(popup: d->popup)->reposition(); |
214 | } |
215 | |
216 | bool QQuickPopupItem::(QEvent *event) |
217 | { |
218 | #if QT_CONFIG(shortcut) |
219 | Q_D(QQuickPopupItem); |
220 | if (event->type() == QEvent::Shortcut) { |
221 | QShortcutEvent *se = static_cast<QShortcutEvent *>(event); |
222 | if (se->shortcutId() == d->escapeId || se->shortcutId() == d->backId) { |
223 | QQuickPopupPrivate *p = QQuickPopupPrivate::get(popup: d->popup); |
224 | if (p->interactive) { |
225 | p->closeOrReject(); |
226 | return true; |
227 | } |
228 | } |
229 | } |
230 | #endif |
231 | return QQuickItem::event(event); |
232 | } |
233 | |
234 | bool QQuickPopupItem::(QQuickItem *child, QEvent *event) |
235 | { |
236 | Q_D(QQuickPopupItem); |
237 | return d->popup->childMouseEventFilter(child, event); |
238 | } |
239 | |
240 | void QQuickPopupItem::(QFocusEvent *event) |
241 | { |
242 | Q_D(QQuickPopupItem); |
243 | d->popup->focusInEvent(event); |
244 | } |
245 | |
246 | void QQuickPopupItem::(QFocusEvent *event) |
247 | { |
248 | Q_D(QQuickPopupItem); |
249 | d->popup->focusOutEvent(event); |
250 | } |
251 | |
252 | void QQuickPopupItem::(QKeyEvent *event) |
253 | { |
254 | Q_D(QQuickPopupItem); |
255 | d->popup->keyPressEvent(event); |
256 | } |
257 | |
258 | void QQuickPopupItem::(QKeyEvent *event) |
259 | { |
260 | Q_D(QQuickPopupItem); |
261 | d->popup->keyReleaseEvent(event); |
262 | } |
263 | |
264 | void QQuickPopupItem::(QMouseEvent *event) |
265 | { |
266 | Q_D(QQuickPopupItem); |
267 | d->popup->mousePressEvent(event); |
268 | } |
269 | |
270 | void QQuickPopupItem::(QMouseEvent *event) |
271 | { |
272 | Q_D(QQuickPopupItem); |
273 | d->popup->mouseMoveEvent(event); |
274 | } |
275 | |
276 | void QQuickPopupItem::(QMouseEvent *event) |
277 | { |
278 | Q_D(QQuickPopupItem); |
279 | d->popup->mouseReleaseEvent(event); |
280 | } |
281 | |
282 | void QQuickPopupItem::(QMouseEvent *event) |
283 | { |
284 | Q_D(QQuickPopupItem); |
285 | d->popup->mouseDoubleClickEvent(event); |
286 | } |
287 | |
288 | void QQuickPopupItem::() |
289 | { |
290 | Q_D(QQuickPopupItem); |
291 | d->popup->mouseUngrabEvent(); |
292 | } |
293 | |
294 | #if QT_CONFIG(quicktemplates2_multitouch) |
295 | void QQuickPopupItem::(QTouchEvent *event) |
296 | { |
297 | Q_D(QQuickPopupItem); |
298 | d->popup->touchEvent(event); |
299 | } |
300 | |
301 | void QQuickPopupItem::() |
302 | { |
303 | Q_D(QQuickPopupItem); |
304 | d->popup->touchUngrabEvent(); |
305 | } |
306 | #endif |
307 | |
308 | #if QT_CONFIG(wheelevent) |
309 | void QQuickPopupItem::(QWheelEvent *event) |
310 | { |
311 | Q_D(QQuickPopupItem); |
312 | d->popup->wheelEvent(event); |
313 | } |
314 | #endif |
315 | |
316 | void QQuickPopupItem::(QQuickItem *newItem, QQuickItem *oldItem) |
317 | { |
318 | Q_D(QQuickPopupItem); |
319 | QQuickPage::contentItemChange(newItem, oldItem); |
320 | d->popup->contentItemChange(newItem, oldItem); |
321 | } |
322 | |
323 | void QQuickPopupItem::(const QSizeF &newSize, const QSizeF &oldSize) |
324 | { |
325 | Q_D(QQuickPopupItem); |
326 | QQuickPage::contentSizeChange(newSize, oldSize); |
327 | d->popup->contentSizeChange(newSize, oldSize); |
328 | } |
329 | |
330 | void QQuickPopupItem::(const QFont &newFont, const QFont &oldFont) |
331 | { |
332 | Q_D(QQuickPopupItem); |
333 | QQuickPage::fontChange(newFont, oldFont); |
334 | d->popup->fontChange(newFont, oldFont); |
335 | } |
336 | |
337 | void QQuickPopupItem::(const QRectF &newGeometry, const QRectF &oldGeometry) |
338 | { |
339 | Q_D(QQuickPopupItem); |
340 | QQuickPage::geometryChanged(newGeometry, oldGeometry); |
341 | d->popup->geometryChanged(newGeometry, oldGeometry); |
342 | } |
343 | |
344 | void QQuickPopupItem::(const QLocale &newLocale, const QLocale &oldLocale) |
345 | { |
346 | Q_D(QQuickPopupItem); |
347 | QQuickPage::localeChange(newLocale, oldLocale); |
348 | d->popup->localeChange(newLocale, oldLocale); |
349 | } |
350 | |
351 | void QQuickPopupItem::() |
352 | { |
353 | Q_D(QQuickPopupItem); |
354 | emit d->popup->mirroredChanged(); |
355 | } |
356 | |
357 | void QQuickPopupItem::(ItemChange change, const ItemChangeData &data) |
358 | { |
359 | Q_D(QQuickPopupItem); |
360 | QQuickPage::itemChange(change, value: data); |
361 | d->popup->itemChange(change, data); |
362 | } |
363 | |
364 | void QQuickPopupItem::(const QMarginsF &newPadding, const QMarginsF &oldPadding) |
365 | { |
366 | Q_D(QQuickPopupItem); |
367 | QQuickPage::paddingChange(newPadding, oldPadding); |
368 | d->popup->paddingChange(newPadding, oldPadding); |
369 | } |
370 | |
371 | void QQuickPopupItem::(const QPalette &newPalette, const QPalette &oldPalette) |
372 | { |
373 | Q_D(QQuickPopupItem); |
374 | QQuickPage::paletteChange(newPalette, oldPalette); |
375 | d->popup->paletteChange(newPalette, oldPalette); |
376 | } |
377 | |
378 | void QQuickPopupItem::() |
379 | { |
380 | Q_D(QQuickPopupItem); |
381 | // Just having QQuickPopup connect our QQuickItem::enabledChanged() signal |
382 | // to its enabledChanged() signal is enough for the enabled property to work, |
383 | // but we must also ensure that its paletteChanged() signal is emitted |
384 | // so that bindings to palette are re-evaluated, because QQuickControl::palette() |
385 | // returns a different palette depending on whether or not the control is enabled. |
386 | // To save a connection, we also emit enabledChanged here. |
387 | emit d->popup->enabledChanged(); |
388 | emit d->popup->paletteChanged(); |
389 | } |
390 | |
391 | QFont QQuickPopupItem::() const |
392 | { |
393 | Q_D(const QQuickPopupItem); |
394 | return d->popup->defaultFont(); |
395 | } |
396 | |
397 | QPalette QQuickPopupItem::() const |
398 | { |
399 | Q_D(const QQuickPopupItem); |
400 | return d->popup->defaultPalette(); |
401 | } |
402 | |
403 | #if QT_CONFIG(accessibility) |
404 | QAccessible::Role QQuickPopupItem::() const |
405 | { |
406 | Q_D(const QQuickPopupItem); |
407 | return d->popup->accessibleRole(); |
408 | } |
409 | |
410 | void QQuickPopupItem::(bool active) |
411 | { |
412 | Q_D(const QQuickPopupItem); |
413 | // Can't just use d->popup->accessibleName() here, because that refers to the accessible |
414 | // name of us, the popup item, which is not what we want. |
415 | const QQuickAccessibleAttached * = QQuickControlPrivate::accessibleAttached(object: d->popup); |
416 | const QString = popupAccessibleAttached ? popupAccessibleAttached->name() : QString(); |
417 | const bool = popupAccessibleAttached && popupAccessibleAttached->wasNameExplicitlySet(); |
418 | |
419 | QQuickPage::accessibilityActiveChanged(active); |
420 | |
421 | QQuickAccessibleAttached *accessibleAttached = QQuickControlPrivate::accessibleAttached(object: this); |
422 | const QString ourName = accessibleAttached ? accessibleAttached->name() : QString(); |
423 | if (wasNameExplicitlySetOnPopup && accessibleAttached && ourName != oldPopupName) { |
424 | // The user set Accessible.name on the Popup. Since the Popup and its popup item |
425 | // have different accessible attached properties, the popup item doesn't know that |
426 | // a name was set on the Popup by the user, and that it should use that, rather than |
427 | // whatever QQuickPage sets. That's why we need to do it here. |
428 | // To avoid it being overridden by the call to accessibilityActiveChanged() below, |
429 | // we set it explicitly. It's safe to do this as the popup item is an internal implementation detail. |
430 | accessibleAttached->setName(oldPopupName); |
431 | } |
432 | |
433 | // This allows the different popup types to set a name on their popup item accordingly. |
434 | // For example: Dialog uses its title and ToolTip uses its text. |
435 | d->popup->accessibilityActiveChanged(active); |
436 | } |
437 | #endif |
438 | |
439 | QT_END_NAMESPACE |
440 | |