1// Copyright (C) 2017 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qquickpopupitem_p_p.h"
5#include "qquickapplicationwindow_p.h"
6#include "qquickpage_p_p.h"
7#include "qquickcontentitem_p.h"
8#include "qquickpopup_p_p.h"
9#include "qquickdeferredexecute_p_p.h"
10
11#if QT_CONFIG(accessibility)
12#include <QtQuick/private/qquickaccessibleattached_p.h>
13#endif
14
15QT_BEGIN_NAMESPACE
16
17Q_LOGGING_CATEGORY(lcPopupItem, "qt.quick.controls.popupitem")
18
19QQuickPopupItemPrivate::QQuickPopupItemPrivate(QQuickPopup *popup)
20 : popup(popup)
21{
22 isTabFence = true;
23}
24
25QQuickPopupItemPrivate *QQuickPopupItemPrivate::get(QQuickPopupItem *popupItem)
26{
27 return popupItem->d_func();
28}
29
30void QQuickPopupItemPrivate::implicitWidthChanged()
31{
32 qCDebug(lcPopupItem).nospace() << "implicitWidthChanged called on " << q_func() << "; new implicitWidth is " << implicitWidth;
33 QQuickPagePrivate::implicitWidthChanged();
34 emit popup->implicitWidthChanged();
35}
36
37void QQuickPopupItemPrivate::implicitHeightChanged()
38{
39 qCDebug(lcPopupItem).nospace() << "implicitHeightChanged called on " << q_func() << "; new implicitHeight is " << implicitHeight;
40 QQuickPagePrivate::implicitHeightChanged();
41 emit popup->implicitHeightChanged();
42}
43
44void QQuickPopupItemPrivate::resolveFont()
45{
46 if (QQuickApplicationWindow *window = qobject_cast<QQuickApplicationWindow *>(object: popup->window()))
47 inheritFont(font: window->font());
48 else
49 inheritFont(font: QQuickTheme::font(scope: QQuickTheme::System));
50}
51
52QQuickItem *QQuickPopupItemPrivate::getContentItem()
53{
54 Q_Q(QQuickPopupItem);
55 if (QQuickItem *item = QQuickPagePrivate::getContentItem())
56 return item;
57
58 return new QQuickContentItem(popup, q);
59}
60
61static inline QString contentItemName() { return QStringLiteral("contentItem"); }
62
63void QQuickPopupItemPrivate::cancelContentItem()
64{
65 quickCancelDeferred(object: popup, property: contentItemName());
66}
67
68void QQuickPopupItemPrivate::executeContentItem(bool complete)
69{
70 if (contentItem.wasExecuted())
71 return;
72
73 if (!contentItem || complete)
74 quickBeginDeferred(object: popup, property: contentItemName(), delegate&: contentItem);
75 if (complete)
76 quickCompleteDeferred(object: popup, property: contentItemName(), delegate&: contentItem);
77}
78
79void QQuickPopupItemPrivate::cancelBackground()
80{
81 quickCancelDeferred(object: popup, property: backgroundName());
82}
83
84void QQuickPopupItemPrivate::executeBackground(bool complete)
85{
86 if (background.wasExecuted())
87 return;
88
89 if (!background || complete)
90 quickBeginDeferred(object: popup, property: backgroundName(), delegate&: background);
91 if (complete)
92 quickCompleteDeferred(object: popup, property: backgroundName(), delegate&: background);
93}
94
95QQuickPopupItem::QQuickPopupItem(QQuickPopup *popup)
96 : QQuickPage(*(new QQuickPopupItemPrivate(popup)), nullptr)
97{
98 setParent(popup);
99 setFlag(flag: ItemIsFocusScope);
100 setAcceptedMouseButtons(Qt::AllButtons);
101#if QT_CONFIG(quicktemplates2_multitouch)
102 setAcceptTouchEvents(true);
103#endif
104#if QT_CONFIG(cursor)
105 setCursor(Qt::ArrowCursor);
106#endif
107
108 connect(sender: popup, signal: &QQuickPopup::paletteChanged, context: this, slot: &QQuickItem::paletteChanged);
109 connect(sender: popup, signal: &QQuickPopup::paletteCreated, context: this, slot: &QQuickItem::paletteCreated);
110
111#if QT_CONFIG(quicktemplates2_hover)
112 // TODO: switch to QStyleHints::useHoverEffects in Qt 5.8
113 setHoverEnabled(true);
114 // setAcceptHoverEvents(QGuiApplication::styleHints()->useHoverEffects());
115 // connect(QGuiApplication::styleHints(), &QStyleHints::useHoverEffectsChanged, this, &QQuickItem::setAcceptHoverEvents);
116#endif
117}
118
119QQuickPalette *QQuickPopupItemPrivate::palette() const
120{
121 return QQuickPopupPrivate::get(popup)->palette();
122}
123
124void QQuickPopupItemPrivate::setPalette(QQuickPalette *p)
125{
126 QQuickPopupPrivate::get(popup)->setPalette(p);
127}
128
129void QQuickPopupItemPrivate::resetPalette()
130{
131 QQuickPopupPrivate::get(popup)->resetPalette();
132}
133
134QPalette QQuickPopupItemPrivate::defaultPalette() const
135{
136 return QQuickPopupPrivate::get(popup)->defaultPalette();
137}
138
139bool QQuickPopupItemPrivate::providesPalette() const
140{
141 return QQuickPopupPrivate::get(popup)->providesPalette();
142}
143
144QPalette QQuickPopupItemPrivate::parentPalette(const QPalette &fallbackPalette) const
145{
146 return QQuickPopupPrivate::get(popup)->parentPalette(fallbackPalette);
147}
148
149void QQuickPopupItem::updatePolish()
150{
151 Q_D(QQuickPopupItem);
152 return QQuickPopupPrivate::get(popup: d->popup)->reposition();
153}
154
155bool QQuickPopupItem::childMouseEventFilter(QQuickItem *child, QEvent *event)
156{
157 Q_D(QQuickPopupItem);
158 return d->popup->childMouseEventFilter(child, event);
159}
160
161void QQuickPopupItem::focusInEvent(QFocusEvent *event)
162{
163 Q_D(QQuickPopupItem);
164 d->popup->focusInEvent(event);
165}
166
167void QQuickPopupItem::focusOutEvent(QFocusEvent *event)
168{
169 Q_D(QQuickPopupItem);
170 d->popup->focusOutEvent(event);
171}
172
173void QQuickPopupItem::keyPressEvent(QKeyEvent *event)
174{
175 Q_D(QQuickPopupItem);
176 d->popup->keyPressEvent(event);
177}
178
179void QQuickPopupItem::keyReleaseEvent(QKeyEvent *event)
180{
181 Q_D(QQuickPopupItem);
182 d->popup->keyReleaseEvent(event);
183}
184
185void QQuickPopupItem::mousePressEvent(QMouseEvent *event)
186{
187 Q_D(QQuickPopupItem);
188 d->popup->mousePressEvent(event);
189}
190
191void QQuickPopupItem::mouseMoveEvent(QMouseEvent *event)
192{
193 Q_D(QQuickPopupItem);
194 d->popup->mouseMoveEvent(event);
195}
196
197void QQuickPopupItem::mouseReleaseEvent(QMouseEvent *event)
198{
199 Q_D(QQuickPopupItem);
200 d->popup->mouseReleaseEvent(event);
201}
202
203void QQuickPopupItem::mouseDoubleClickEvent(QMouseEvent *event)
204{
205 Q_D(QQuickPopupItem);
206 d->popup->mouseDoubleClickEvent(event);
207}
208
209void QQuickPopupItem::mouseUngrabEvent()
210{
211 Q_D(QQuickPopupItem);
212 d->popup->mouseUngrabEvent();
213}
214
215#if QT_CONFIG(quicktemplates2_multitouch)
216void QQuickPopupItem::touchEvent(QTouchEvent *event)
217{
218 Q_D(QQuickPopupItem);
219 d->popup->touchEvent(event);
220}
221
222void QQuickPopupItem::touchUngrabEvent()
223{
224 Q_D(QQuickPopupItem);
225 d->popup->touchUngrabEvent();
226}
227#endif
228
229#if QT_CONFIG(wheelevent)
230void QQuickPopupItem::wheelEvent(QWheelEvent *event)
231{
232 Q_D(QQuickPopupItem);
233 d->popup->wheelEvent(event);
234}
235#endif
236
237void QQuickPopupItem::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem)
238{
239 Q_D(QQuickPopupItem);
240 QQuickPage::contentItemChange(newItem, oldItem);
241 d->popup->contentItemChange(newItem, oldItem);
242}
243
244void QQuickPopupItem::contentSizeChange(const QSizeF &newSize, const QSizeF &oldSize)
245{
246 Q_D(QQuickPopupItem);
247 qCDebug(lcPopupItem) << "contentSizeChange called on" << this << "newSize" << newSize << "oldSize" << oldSize;
248 QQuickPage::contentSizeChange(newSize, oldSize);
249 d->popup->contentSizeChange(newSize, oldSize);
250}
251
252void QQuickPopupItem::fontChange(const QFont &newFont, const QFont &oldFont)
253{
254 Q_D(QQuickPopupItem);
255 QQuickPage::fontChange(newFont, oldFont);
256 d->popup->fontChange(newFont, oldFont);
257}
258
259void QQuickPopupItem::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
260{
261 Q_D(QQuickPopupItem);
262 qCDebug(lcPopupItem) << "geometryChange called on" << this << "newGeometry" << newGeometry << "oldGeometry" << oldGeometry;
263 QQuickPage::geometryChange(newGeometry, oldGeometry);
264 d->popup->geometryChange(newGeometry, oldGeometry);
265}
266
267void QQuickPopupItem::localeChange(const QLocale &newLocale, const QLocale &oldLocale)
268{
269 Q_D(QQuickPopupItem);
270 QQuickPage::localeChange(newLocale, oldLocale);
271 d->popup->localeChange(newLocale, oldLocale);
272}
273
274void QQuickPopupItem::mirrorChange()
275{
276 Q_D(QQuickPopupItem);
277 emit d->popup->mirroredChanged();
278}
279
280void QQuickPopupItem::itemChange(ItemChange change, const ItemChangeData &data)
281{
282 Q_D(QQuickPopupItem);
283 QQuickPage::itemChange(change, value: data);
284 d->popup->itemChange(change, data);
285}
286
287void QQuickPopupItem::paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding)
288{
289 Q_D(QQuickPopupItem);
290 QQuickPage::paddingChange(newPadding, oldPadding);
291 d->popup->paddingChange(newPadding, oldPadding);
292}
293
294void QQuickPopupItem::enabledChange()
295{
296 Q_D(QQuickPopupItem);
297 // Just having QQuickPopup connect our QQuickItem::enabledChanged() signal
298 // to its enabledChanged() signal is enough for the enabled property to work,
299 // but we must also ensure that its paletteChanged() signal is emitted
300 // so that bindings to palette are re-evaluated, because QQuickControl::palette()
301 // returns a different palette depending on whether or not the control is enabled.
302 // To save a connection, we also emit enabledChanged here.
303 emit d->popup->enabledChanged();
304}
305
306QFont QQuickPopupItem::defaultFont() const
307{
308 Q_D(const QQuickPopupItem);
309 return d->popup->defaultFont();
310}
311
312#if QT_CONFIG(accessibility)
313QAccessible::Role QQuickPopupItem::accessibleRole() const
314{
315 Q_D(const QQuickPopupItem);
316 return d->popup->effectiveAccessibleRole();
317}
318
319void QQuickPopupItem::accessibilityActiveChanged(bool active)
320{
321 Q_D(const QQuickPopupItem);
322 // Can't just use d->popup->accessibleName() here, because that refers to the accessible
323 // name of us, the popup item, which is not what we want.
324 const QQuickAccessibleAttached *popupAccessibleAttached = QQuickControlPrivate::accessibleAttached(object: d->popup);
325 const QString oldPopupName = popupAccessibleAttached ? popupAccessibleAttached->name() : QString();
326 const bool wasNameExplicitlySetOnPopup = popupAccessibleAttached && popupAccessibleAttached->wasNameExplicitlySet();
327
328 QQuickPage::accessibilityActiveChanged(active);
329
330 QQuickAccessibleAttached *accessibleAttached = QQuickControlPrivate::accessibleAttached(object: this);
331 const QString ourName = accessibleAttached ? accessibleAttached->name() : QString();
332 if (wasNameExplicitlySetOnPopup && accessibleAttached && ourName != oldPopupName) {
333 // The user set Accessible.name on the Popup. Since the Popup and its popup item
334 // have different accessible attached properties, the popup item doesn't know that
335 // a name was set on the Popup by the user, and that it should use that, rather than
336 // whatever QQuickPage sets. That's why we need to do it here.
337 // To avoid it being overridden by the call to accessibilityActiveChanged() below,
338 // we set it explicitly. It's safe to do this as the popup item is an internal implementation detail.
339 accessibleAttached->setName(oldPopupName);
340 }
341
342 // This allows the different popup types to set a name on their popup item accordingly.
343 // For example: Dialog uses its title and ToolTip uses its text.
344 d->popup->accessibilityActiveChanged(active);
345}
346#endif
347
348QT_END_NAMESPACE
349
350#include "moc_qquickpopupitem_p_p.cpp"
351

source code of qtdeclarative/src/quicktemplates/qquickpopupitem.cpp