1// Copyright (C) 2021 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 "qquickitem.h"
5
6#include "qquickwindow.h"
7#include "qquickrendercontrol.h"
8#include <QtQml/qjsengine.h>
9#include "qquickwindow_p.h"
10
11#include "qquickevents_p_p.h"
12#include "qquickscreen_p.h"
13
14#include <QtQml/qqmlengine.h>
15#include <QtQml/qqmlcomponent.h>
16#include <QtQml/qqmlinfo.h>
17#include <QtGui/qpen.h>
18#include <QtGui/qguiapplication.h>
19#include <QtGui/qstylehints.h>
20#include <QtGui/private/qeventpoint_p.h>
21#include <QtGui/private/qguiapplication_p.h>
22#include <QtGui/private/qpointingdevice_p.h>
23#include <QtGui/qinputmethod.h>
24#include <QtCore/qcoreevent.h>
25#include <QtCore/private/qnumeric_p.h>
26#include <QtGui/qpa/qplatformtheme.h>
27#include <QtCore/qloggingcategory.h>
28#include <QtCore/private/qduplicatetracker_p.h>
29
30#include <private/qqmlglobal_p.h>
31#include <private/qqmlengine_p.h>
32#include <QtQuick/private/qquickstategroup_p.h>
33#include <private/qqmlopenmetaobject_p.h>
34#include <QtQuick/private/qquickstate_p.h>
35#include <private/qquickitem_p.h>
36#include <QtQuick/private/qquickaccessibleattached_p.h>
37#include <QtQuick/private/qquickhoverhandler_p.h>
38#include <QtQuick/private/qquickpointerhandler_p.h>
39#include <QtQuick/private/qquickpointerhandler_p_p.h>
40
41#include <private/qv4engine_p.h>
42#include <private/qv4object_p.h>
43#include <private/qv4qobjectwrapper_p.h>
44#include <private/qdebug_p.h>
45#include <private/qqmlvaluetypewrapper_p.h>
46
47#if QT_CONFIG(cursor)
48# include <QtGui/qcursor.h>
49#endif
50
51#include <QtCore/qpointer.h>
52
53#include <algorithm>
54#include <limits>
55
56// XXX todo Check that elements that create items handle memory correctly after visual ownership change
57
58QT_BEGIN_NAMESPACE
59
60Q_DECLARE_LOGGING_CATEGORY(lcMouseTarget)
61Q_DECLARE_LOGGING_CATEGORY(lcHoverTrace)
62Q_DECLARE_LOGGING_CATEGORY(lcPtr)
63Q_DECLARE_LOGGING_CATEGORY(lcTransient)
64Q_LOGGING_CATEGORY(lcHandlerParent, "qt.quick.handler.parent")
65Q_LOGGING_CATEGORY(lcVP, "qt.quick.viewport")
66Q_LOGGING_CATEGORY(lcChangeListeners, "qt.quick.item.changelisteners")
67
68// after 100ms, a mouse/non-mouse cursor conflict is resolved in favor of the mouse handler
69static const quint64 kCursorOverrideTimeout = 100;
70
71void debugFocusTree(QQuickItem *item, QQuickItem *scope = nullptr, int depth = 1)
72{
73 if (lcFocus().isEnabled(type: QtDebugMsg)) {
74 qCDebug(lcFocus)
75 << QByteArray(depth, '\t').constData()
76 << (scope && QQuickItemPrivate::get(item: scope)->subFocusItem == item ? '*' : ' ')
77 << item->hasFocus()
78 << item->hasActiveFocus()
79 << item->isFocusScope()
80 << item;
81 const auto childItems = item->childItems();
82 for (QQuickItem *child : childItems) {
83 debugFocusTree(
84 item: child,
85 scope: item->isFocusScope() || !scope ? item : scope,
86 depth: item->isFocusScope() || !scope ? depth + 1 : depth);
87 }
88 }
89}
90
91static void setActiveFocus(QQuickItem *item, Qt::FocusReason reason)
92{
93 QQuickItemPrivate *d = QQuickItemPrivate::get(item);
94 if (d->subFocusItem && d->window && d->flags & QQuickItem::ItemIsFocusScope)
95 QQuickWindowPrivate::get(c: d->window)->clearFocusInScope(scope: item, item: d->subFocusItem, reason);
96 item->forceActiveFocus(reason);
97}
98
99/*!
100 \qmltype Transform
101 \nativetype QQuickTransform
102 \inqmlmodule QtQuick
103 \ingroup qtquick-visual-transforms
104 \brief For specifying advanced transformations on Items.
105
106 The Transform type is a base type which cannot be instantiated directly.
107 The following concrete Transform types are available:
108
109 \list
110 \li \l Rotation
111 \li \l Scale
112 \li \l Translate
113 \li \l Matrix4x4
114 \endlist
115
116 The Transform types let you create and control advanced transformations that can be configured
117 independently using specialized properties.
118
119 You can assign any number of Transforms to an \l Item. Each Transform is applied in order,
120 one at a time.
121*/
122QQuickTransformPrivate::QQuickTransformPrivate()
123{
124}
125
126QQuickTransform::QQuickTransform(QObject *parent)
127: QObject(*(new QQuickTransformPrivate), parent)
128{
129}
130
131QQuickTransform::QQuickTransform(QQuickTransformPrivate &dd, QObject *parent)
132: QObject(dd, parent)
133{
134}
135
136QQuickTransform::~QQuickTransform()
137{
138 Q_D(QQuickTransform);
139 for (int ii = 0; ii < d->items.size(); ++ii) {
140 QQuickItemPrivate *p = QQuickItemPrivate::get(item: d->items.at(i: ii));
141 p->transforms.removeOne(t: this);
142 p->dirty(QQuickItemPrivate::Transform);
143 }
144}
145
146void QQuickTransform::update()
147{
148 Q_D(QQuickTransform);
149 for (int ii = 0; ii < d->items.size(); ++ii) {
150 QQuickItemPrivate *p = QQuickItemPrivate::get(item: d->items.at(i: ii));
151 p->dirty(QQuickItemPrivate::Transform);
152 }
153}
154
155QQuickContents::QQuickContents(QQuickItem *item)
156: m_item(item)
157{
158}
159
160QQuickContents::~QQuickContents()
161{
162 QList<QQuickItem *> children = m_item->childItems();
163 for (int i = 0; i < children.size(); ++i) {
164 QQuickItem *child = children.at(i);
165 QQuickItemPrivate::get(item: child)->removeItemChangeListener(this, types: QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed);
166 }
167}
168
169bool QQuickContents::calcHeight(QQuickItem *changed)
170{
171 qreal oldy = m_contents.y();
172 qreal oldheight = m_contents.height();
173
174 if (changed) {
175 qreal top = oldy;
176 qreal bottom = oldy + oldheight;
177 qreal y = changed->y();
178 if (y + changed->height() > bottom)
179 bottom = y + changed->height();
180 if (y < top)
181 top = y;
182 m_contents.setY(top);
183 m_contents.setHeight(bottom - top);
184 } else {
185 qreal top = std::numeric_limits<qreal>::max();
186 qreal bottom = -std::numeric_limits<qreal>::max();
187 QList<QQuickItem *> children = m_item->childItems();
188 for (int i = 0; i < children.size(); ++i) {
189 QQuickItem *child = children.at(i);
190 qreal y = child->y();
191 if (y + child->height() > bottom)
192 bottom = y + child->height();
193 if (y < top)
194 top = y;
195 }
196 if (!children.isEmpty())
197 m_contents.setY(top);
198 m_contents.setHeight(qMax(a: bottom - top, b: qreal(0.0)));
199 }
200
201 return (m_contents.height() != oldheight || m_contents.y() != oldy);
202}
203
204bool QQuickContents::calcWidth(QQuickItem *changed)
205{
206 qreal oldx = m_contents.x();
207 qreal oldwidth = m_contents.width();
208
209 if (changed) {
210 qreal left = oldx;
211 qreal right = oldx + oldwidth;
212 qreal x = changed->x();
213 if (x + changed->width() > right)
214 right = x + changed->width();
215 if (x < left)
216 left = x;
217 m_contents.setX(left);
218 m_contents.setWidth(right - left);
219 } else {
220 qreal left = std::numeric_limits<qreal>::max();
221 qreal right = -std::numeric_limits<qreal>::max();
222 QList<QQuickItem *> children = m_item->childItems();
223 for (int i = 0; i < children.size(); ++i) {
224 QQuickItem *child = children.at(i);
225 qreal x = child->x();
226 if (x + child->width() > right)
227 right = x + child->width();
228 if (x < left)
229 left = x;
230 }
231 if (!children.isEmpty())
232 m_contents.setX(left);
233 m_contents.setWidth(qMax(a: right - left, b: qreal(0.0)));
234 }
235
236 return (m_contents.width() != oldwidth || m_contents.x() != oldx);
237}
238
239void QQuickContents::complete()
240{
241 QQuickItemPrivate::get(item: m_item)->addItemChangeListener(listener: this, types: QQuickItemPrivate::Children);
242
243 QList<QQuickItem *> children = m_item->childItems();
244 for (int i = 0; i < children.size(); ++i) {
245 QQuickItem *child = children.at(i);
246 QQuickItemPrivate::get(item: child)->addItemChangeListener(listener: this, types: QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed);
247 //###what about changes to visibility?
248 }
249 calcGeometry();
250}
251
252void QQuickContents::updateRect()
253{
254 QQuickItemPrivate::get(item: m_item)->emitChildrenRectChanged(rect: rectF());
255}
256
257void QQuickContents::itemGeometryChanged(QQuickItem *changed, QQuickGeometryChange change, const QRectF &)
258{
259 Q_UNUSED(changed);
260 bool wChanged = false;
261 bool hChanged = false;
262 //### we can only pass changed if the left edge has moved left, or the right edge has moved right
263 if (change.horizontalChange())
264 wChanged = calcWidth(/*changed*/);
265 if (change.verticalChange())
266 hChanged = calcHeight(/*changed*/);
267 if (wChanged || hChanged)
268 updateRect();
269}
270
271void QQuickContents::itemDestroyed(QQuickItem *item)
272{
273 if (item)
274 QQuickItemPrivate::get(item)->removeItemChangeListener(this, types: QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed);
275 calcGeometry();
276}
277
278void QQuickContents::itemChildRemoved(QQuickItem *, QQuickItem *item)
279{
280 if (item)
281 QQuickItemPrivate::get(item)->removeItemChangeListener(this, types: QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed);
282 calcGeometry();
283}
284
285void QQuickContents::itemChildAdded(QQuickItem *, QQuickItem *item)
286{
287 if (item)
288 QQuickItemPrivate::get(item)->addItemChangeListener(listener: this, types: QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed);
289 calcGeometry(changed: item);
290}
291
292QQuickItemKeyFilter::QQuickItemKeyFilter(QQuickItem *item)
293: m_processPost(false), m_next(nullptr)
294{
295 QQuickItemPrivate *p = item?QQuickItemPrivate::get(item):nullptr;
296 if (p) {
297 m_next = p->extra.value().keyHandler;
298 p->extra->keyHandler = this;
299 }
300}
301
302QQuickItemKeyFilter::~QQuickItemKeyFilter()
303{
304}
305
306void QQuickItemKeyFilter::keyPressed(QKeyEvent *event, bool post)
307{
308 if (m_next) m_next->keyPressed(event, post);
309}
310
311void QQuickItemKeyFilter::keyReleased(QKeyEvent *event, bool post)
312{
313 if (m_next) m_next->keyReleased(event, post);
314}
315
316#if QT_CONFIG(im)
317void QQuickItemKeyFilter::inputMethodEvent(QInputMethodEvent *event, bool post)
318{
319 if (m_next)
320 m_next->inputMethodEvent(event, post);
321 else
322 event->ignore();
323}
324
325QVariant QQuickItemKeyFilter::inputMethodQuery(Qt::InputMethodQuery query) const
326{
327 if (m_next) return m_next->inputMethodQuery(query);
328 return QVariant();
329}
330#endif // im
331
332void QQuickItemKeyFilter::shortcutOverrideEvent(QKeyEvent *event)
333{
334 if (m_next)
335 m_next->shortcutOverrideEvent(event);
336 else
337 event->ignore();
338}
339
340void QQuickItemKeyFilter::componentComplete()
341{
342 if (m_next) m_next->componentComplete();
343}
344/*!
345 \qmltype KeyNavigation
346 \nativetype QQuickKeyNavigationAttached
347 \inqmlmodule QtQuick
348 \ingroup qtquick-input-handlers
349 \brief Supports key navigation by arrow keys.
350
351 Key-based user interfaces commonly allow the use of arrow keys to navigate between
352 focusable items. The KeyNavigation attached property enables this behavior by providing a
353 convenient way to specify the item that should gain focus when an arrow or tab key is pressed.
354
355 The following example provides key navigation for a 2x2 grid of items:
356
357 \snippet qml/keynavigation.qml 0
358
359 The top-left item initially receives focus by setting \l {Item::}{focus} to
360 \c true. When an arrow key is pressed, the focus will move to the
361 appropriate item, as defined by the value that has been set for
362 the KeyNavigation \l left, \l right, \l up or \l down properties.
363
364 Note that if a KeyNavigation attached property receives the key press and release
365 events for a requested arrow or tab key, the event is accepted and does not
366 propagate any further.
367
368 By default, KeyNavigation receives key events after the item to which it is attached.
369 If the item accepts the key event, the KeyNavigation attached property will not
370 receive an event for that key. Setting the \l priority property to
371 \c KeyNavigation.BeforeItem allows the event to be used for key navigation
372 before the item, rather than after.
373
374 If the item to which the focus is switching is not enabled or visible, an attempt will
375 be made to skip this item and focus on the next. This is possible if there are
376 a chain of items with the same KeyNavigation handler. If multiple items in a row are not enabled
377 or visible, they will also be skipped.
378
379 KeyNavigation will implicitly set the other direction to return focus to this item. So if you set
380 \l left to another item, \l right will be set on that item's KeyNavigation to set focus back to this
381 item. However, if that item's KeyNavigation has had right explicitly set then no change will occur.
382 This means that the example above could achieve the same behavior without specifying
383 KeyNavigation.right or KeyNavigation.down for any of the items.
384
385 \sa {Keys}{Keys attached property}
386*/
387
388/*!
389 \qmlattachedproperty Item QtQuick::KeyNavigation::left
390
391 This property holds the item to assign focus to
392 when the left cursor key is pressed.
393*/
394
395/*!
396 \qmlattachedproperty Item QtQuick::KeyNavigation::right
397
398 This property holds the item to assign focus to
399 when the right cursor key is pressed.
400*/
401
402/*!
403 \qmlattachedproperty Item QtQuick::KeyNavigation::up
404
405 This property holds the item to assign focus to
406 when the up cursor key is pressed.
407*/
408
409/*!
410 \qmlattachedproperty Item QtQuick::KeyNavigation::down
411
412 This property holds the item to assign focus to
413 when the down cursor key is pressed.
414*/
415
416/*!
417 \qmlattachedproperty Item QtQuick::KeyNavigation::tab
418
419 This property holds the item to assign focus to
420 when the Tab key is pressed.
421*/
422
423/*!
424 \qmlattachedproperty Item QtQuick::KeyNavigation::backtab
425
426 This property holds the item to assign focus to
427 when the Shift+Tab key combination (Backtab) is pressed.
428*/
429
430QQuickKeyNavigationAttached::QQuickKeyNavigationAttached(QObject *parent)
431: QObject(*(new QQuickKeyNavigationAttachedPrivate), parent),
432 QQuickItemKeyFilter(qmlobject_cast<QQuickItem*>(object: parent))
433{
434 m_processPost = true;
435}
436
437QQuickKeyNavigationAttached *
438QQuickKeyNavigationAttached::qmlAttachedProperties(QObject *obj)
439{
440 return new QQuickKeyNavigationAttached(obj);
441}
442
443QQuickItem *QQuickKeyNavigationAttached::left() const
444{
445 Q_D(const QQuickKeyNavigationAttached);
446 return d->left;
447}
448
449void QQuickKeyNavigationAttached::setLeft(QQuickItem *i)
450{
451 Q_D(QQuickKeyNavigationAttached);
452 if (d->leftSet && d->left == i)
453 return;
454 d->leftSet = d->left != i;
455 d->left = i;
456 QQuickKeyNavigationAttached* other =
457 qobject_cast<QQuickKeyNavigationAttached*>(object: qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(obj: i));
458 if (other && !other->d_func()->rightSet){
459 other->d_func()->right = qobject_cast<QQuickItem*>(o: parent());
460 emit other->rightChanged();
461 }
462 emit leftChanged();
463}
464
465QQuickItem *QQuickKeyNavigationAttached::right() const
466{
467 Q_D(const QQuickKeyNavigationAttached);
468 return d->right;
469}
470
471void QQuickKeyNavigationAttached::setRight(QQuickItem *i)
472{
473 Q_D(QQuickKeyNavigationAttached);
474 if (d->rightSet && d->right == i)
475 return;
476 d->rightSet = d->right != i;
477 d->right = i;
478 QQuickKeyNavigationAttached* other =
479 qobject_cast<QQuickKeyNavigationAttached*>(object: qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(obj: i));
480 if (other && !other->d_func()->leftSet){
481 other->d_func()->left = qobject_cast<QQuickItem*>(o: parent());
482 emit other->leftChanged();
483 }
484 emit rightChanged();
485}
486
487QQuickItem *QQuickKeyNavigationAttached::up() const
488{
489 Q_D(const QQuickKeyNavigationAttached);
490 return d->up;
491}
492
493void QQuickKeyNavigationAttached::setUp(QQuickItem *i)
494{
495 Q_D(QQuickKeyNavigationAttached);
496 if (d->upSet && d->up == i)
497 return;
498 d->upSet = d->up != i;
499 d->up = i;
500 QQuickKeyNavigationAttached* other =
501 qobject_cast<QQuickKeyNavigationAttached*>(object: qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(obj: i));
502 if (other && !other->d_func()->downSet){
503 other->d_func()->down = qobject_cast<QQuickItem*>(o: parent());
504 emit other->downChanged();
505 }
506 emit upChanged();
507}
508
509QQuickItem *QQuickKeyNavigationAttached::down() const
510{
511 Q_D(const QQuickKeyNavigationAttached);
512 return d->down;
513}
514
515void QQuickKeyNavigationAttached::setDown(QQuickItem *i)
516{
517 Q_D(QQuickKeyNavigationAttached);
518 if (d->downSet && d->down == i)
519 return;
520 d->downSet = d->down != i;
521 d->down = i;
522 QQuickKeyNavigationAttached* other =
523 qobject_cast<QQuickKeyNavigationAttached*>(object: qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(obj: i));
524 if (other && !other->d_func()->upSet) {
525 other->d_func()->up = qobject_cast<QQuickItem*>(o: parent());
526 emit other->upChanged();
527 }
528 emit downChanged();
529}
530
531QQuickItem *QQuickKeyNavigationAttached::tab() const
532{
533 Q_D(const QQuickKeyNavigationAttached);
534 return d->tab;
535}
536
537void QQuickKeyNavigationAttached::setTab(QQuickItem *i)
538{
539 Q_D(QQuickKeyNavigationAttached);
540 if (d->tabSet && d->tab == i)
541 return;
542 d->tabSet = d->tab != i;
543 d->tab = i;
544 QQuickKeyNavigationAttached* other =
545 qobject_cast<QQuickKeyNavigationAttached*>(object: qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(obj: i));
546 if (other && !other->d_func()->backtabSet) {
547 other->d_func()->backtab = qobject_cast<QQuickItem*>(o: parent());
548 emit other->backtabChanged();
549 }
550 emit tabChanged();
551}
552
553QQuickItem *QQuickKeyNavigationAttached::backtab() const
554{
555 Q_D(const QQuickKeyNavigationAttached);
556 return d->backtab;
557}
558
559void QQuickKeyNavigationAttached::setBacktab(QQuickItem *i)
560{
561 Q_D(QQuickKeyNavigationAttached);
562 if (d->backtabSet && d->backtab == i)
563 return;
564 d->backtabSet = d->backtab != i;
565 d->backtab = i;
566 QQuickKeyNavigationAttached* other =
567 qobject_cast<QQuickKeyNavigationAttached*>(object: qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(obj: i));
568 if (other && !other->d_func()->tabSet) {
569 other->d_func()->tab = qobject_cast<QQuickItem*>(o: parent());
570 emit other->tabChanged();
571 }
572 emit backtabChanged();
573}
574
575/*!
576 \qmlattachedproperty enumeration QtQuick::KeyNavigation::priority
577
578 This property determines whether the keys are processed before
579 or after the attached item's own key handling.
580
581 \value KeyNavigation.BeforeItem process the key events before normal
582 item key processing. If the event is used for key navigation, it will be accepted and
583 will not be passed on to the item.
584 \value KeyNavigation.AfterItem (default) process the key events after normal item key
585 handling. If the item accepts the key event it will not be
586 handled by the KeyNavigation attached property handler.
587*/
588QQuickKeyNavigationAttached::Priority QQuickKeyNavigationAttached::priority() const
589{
590 return m_processPost ? AfterItem : BeforeItem;
591}
592
593void QQuickKeyNavigationAttached::setPriority(Priority order)
594{
595 bool processPost = order == AfterItem;
596 if (processPost != m_processPost) {
597 m_processPost = processPost;
598 emit priorityChanged();
599 }
600}
601
602void QQuickKeyNavigationAttached::keyPressed(QKeyEvent *event, bool post)
603{
604 Q_D(QQuickKeyNavigationAttached);
605 event->ignore();
606
607 if (post != m_processPost) {
608 QQuickItemKeyFilter::keyPressed(event, post);
609 return;
610 }
611
612 bool mirror = false;
613 switch (event->key()) {
614 case Qt::Key_Left: {
615 if (QQuickItem *parentItem = qobject_cast<QQuickItem*>(o: parent()))
616 mirror = QQuickItemPrivate::get(item: parentItem)->effectiveLayoutMirror;
617 QQuickItem* leftItem = mirror ? d->right : d->left;
618 if (leftItem) {
619 setFocusNavigation(currentItem: leftItem, dir: mirror ? "right" : "left", reason: mirror ? Qt::TabFocusReason : Qt::BacktabFocusReason);
620 event->accept();
621 }
622 break;
623 }
624 case Qt::Key_Right: {
625 if (QQuickItem *parentItem = qobject_cast<QQuickItem*>(o: parent()))
626 mirror = QQuickItemPrivate::get(item: parentItem)->effectiveLayoutMirror;
627 QQuickItem* rightItem = mirror ? d->left : d->right;
628 if (rightItem) {
629 setFocusNavigation(currentItem: rightItem, dir: mirror ? "left" : "right", reason: mirror ? Qt::BacktabFocusReason : Qt::TabFocusReason);
630 event->accept();
631 }
632 break;
633 }
634 case Qt::Key_Up:
635 if (d->up) {
636 setFocusNavigation(currentItem: d->up, dir: "up", reason: Qt::BacktabFocusReason);
637 event->accept();
638 }
639 break;
640 case Qt::Key_Down:
641 if (d->down) {
642 setFocusNavigation(currentItem: d->down, dir: "down", reason: Qt::TabFocusReason);
643 event->accept();
644 }
645 break;
646 case Qt::Key_Tab:
647 if (d->tab) {
648 setFocusNavigation(currentItem: d->tab, dir: "tab", reason: Qt::TabFocusReason);
649 event->accept();
650 }
651 break;
652 case Qt::Key_Backtab:
653 if (d->backtab) {
654 setFocusNavigation(currentItem: d->backtab, dir: "backtab", reason: Qt::BacktabFocusReason);
655 event->accept();
656 }
657 break;
658 default:
659 break;
660 }
661
662 if (!event->isAccepted()) QQuickItemKeyFilter::keyPressed(event, post);
663}
664
665void QQuickKeyNavigationAttached::keyReleased(QKeyEvent *event, bool post)
666{
667 Q_D(QQuickKeyNavigationAttached);
668 event->ignore();
669
670 if (post != m_processPost) {
671 QQuickItemKeyFilter::keyReleased(event, post);
672 return;
673 }
674
675 bool mirror = false;
676 switch (event->key()) {
677 case Qt::Key_Left:
678 if (QQuickItem *parentItem = qobject_cast<QQuickItem*>(o: parent()))
679 mirror = QQuickItemPrivate::get(item: parentItem)->effectiveLayoutMirror;
680 if (mirror ? d->right : d->left)
681 event->accept();
682 break;
683 case Qt::Key_Right:
684 if (QQuickItem *parentItem = qobject_cast<QQuickItem*>(o: parent()))
685 mirror = QQuickItemPrivate::get(item: parentItem)->effectiveLayoutMirror;
686 if (mirror ? d->left : d->right)
687 event->accept();
688 break;
689 case Qt::Key_Up:
690 if (d->up) {
691 event->accept();
692 }
693 break;
694 case Qt::Key_Down:
695 if (d->down) {
696 event->accept();
697 }
698 break;
699 case Qt::Key_Tab:
700 if (d->tab) {
701 event->accept();
702 }
703 break;
704 case Qt::Key_Backtab:
705 if (d->backtab) {
706 event->accept();
707 }
708 break;
709 default:
710 break;
711 }
712
713 if (!event->isAccepted()) QQuickItemKeyFilter::keyReleased(event, post);
714}
715
716void QQuickKeyNavigationAttached::setFocusNavigation(QQuickItem *currentItem, const char *dir,
717 Qt::FocusReason reason)
718{
719 QQuickItem *initialItem = currentItem;
720 bool isNextItem = false;
721 QVector<QQuickItem *> visitedItems;
722 do {
723 isNextItem = false;
724 if (currentItem->isVisible() && currentItem->isEnabled()) {
725 currentItem->forceActiveFocus(reason);
726 } else {
727 QObject *attached =
728 qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(obj: currentItem, create: false);
729 if (attached) {
730 QQuickItem *tempItem = qvariant_cast<QQuickItem*>(v: attached->property(name: dir));
731 if (tempItem) {
732 visitedItems.append(t: currentItem);
733 currentItem = tempItem;
734 isNextItem = true;
735 }
736 }
737 }
738 }
739 while (currentItem != initialItem && isNextItem && !visitedItems.contains(t: currentItem));
740}
741
742struct SigMap {
743 int key;
744 const char *sig;
745};
746
747const SigMap sigMap[] = {
748 { .key: Qt::Key_Left, .sig: "leftPressed" },
749 { .key: Qt::Key_Right, .sig: "rightPressed" },
750 { .key: Qt::Key_Up, .sig: "upPressed" },
751 { .key: Qt::Key_Down, .sig: "downPressed" },
752 { .key: Qt::Key_Tab, .sig: "tabPressed" },
753 { .key: Qt::Key_Backtab, .sig: "backtabPressed" },
754 { .key: Qt::Key_Asterisk, .sig: "asteriskPressed" },
755 { .key: Qt::Key_NumberSign, .sig: "numberSignPressed" },
756 { .key: Qt::Key_Escape, .sig: "escapePressed" },
757 { .key: Qt::Key_Return, .sig: "returnPressed" },
758 { .key: Qt::Key_Enter, .sig: "enterPressed" },
759 { .key: Qt::Key_Delete, .sig: "deletePressed" },
760 { .key: Qt::Key_Space, .sig: "spacePressed" },
761 { .key: Qt::Key_Back, .sig: "backPressed" },
762 { .key: Qt::Key_Cancel, .sig: "cancelPressed" },
763 { .key: Qt::Key_Select, .sig: "selectPressed" },
764 { .key: Qt::Key_Yes, .sig: "yesPressed" },
765 { .key: Qt::Key_No, .sig: "noPressed" },
766 { .key: Qt::Key_Context1, .sig: "context1Pressed" },
767 { .key: Qt::Key_Context2, .sig: "context2Pressed" },
768 { .key: Qt::Key_Context3, .sig: "context3Pressed" },
769 { .key: Qt::Key_Context4, .sig: "context4Pressed" },
770 { .key: Qt::Key_Call, .sig: "callPressed" },
771 { .key: Qt::Key_Hangup, .sig: "hangupPressed" },
772 { .key: Qt::Key_Flip, .sig: "flipPressed" },
773 { .key: Qt::Key_Menu, .sig: "menuPressed" },
774 { .key: Qt::Key_VolumeUp, .sig: "volumeUpPressed" },
775 { .key: Qt::Key_VolumeDown, .sig: "volumeDownPressed" },
776 { .key: 0, .sig: nullptr }
777};
778
779QByteArray QQuickKeysAttached::keyToSignal(int key)
780{
781 QByteArray keySignal;
782 if (key >= Qt::Key_0 && key <= Qt::Key_9) {
783 keySignal = "digit0Pressed";
784 keySignal[5] = '0' + (key - Qt::Key_0);
785 } else {
786 int i = 0;
787 while (sigMap[i].key && sigMap[i].key != key)
788 ++i;
789 keySignal = sigMap[i].sig;
790 }
791 return keySignal;
792}
793
794bool QQuickKeysAttached::isConnected(const char *signalName) const
795{
796 Q_D(const QQuickKeysAttached);
797 int signal_index = d->signalIndex(signalName);
798 return d->isSignalConnected(signalIdx: signal_index);
799}
800
801/*!
802 \qmltype Keys
803 \nativetype QQuickKeysAttached
804 \inqmlmodule QtQuick
805 \ingroup qtquick-input-handlers
806 \brief Provides key handling to Items.
807
808 All visual primitives support key handling via the Keys
809 attached property. Keys can be handled via the onPressed
810 and onReleased signal properties.
811
812 The signal properties have a \l KeyEvent parameter, named
813 \e event which contains details of the event. If a key is
814 handled \e event.accepted should be set to true to prevent the
815 event from propagating up the item hierarchy.
816
817 \section1 Example Usage
818
819 The following example shows how the general onPressed handler can
820 be used to test for a certain key; in this case, the left cursor
821 key:
822
823 \snippet qml/keys/keys-pressed.qml key item
824
825 Some keys may alternatively be handled via specific signal properties,
826 for example \e onSelectPressed. These handlers automatically set
827 \e event.accepted to true.
828
829 \snippet qml/keys/keys-handler.qml key item
830
831 See \l{Qt::Key}{Qt.Key} for the list of keyboard codes.
832
833 \section1 Key Handling Priorities
834
835 The Keys attached property can be configured to handle key events
836 before or after the item it is attached to. This makes it possible
837 to intercept events in order to override an item's default behavior,
838 or act as a fallback for keys not handled by the item.
839
840 If \l priority is Keys.BeforeItem (default) the order of key event processing is:
841
842 \list 1
843 \li Items specified in \c forwardTo
844 \li specific key handlers, e.g. onReturnPressed
845 \li onPressed, onReleased handlers
846 \li Item specific key handling, e.g. TextInput key handling
847 \li parent item
848 \endlist
849
850 If priority is Keys.AfterItem the order of key event processing is:
851
852 \list 1
853 \li Item specific key handling, e.g. TextInput key handling
854 \li Items specified in \c forwardTo
855 \li specific key handlers, e.g. onReturnPressed
856 \li onPressed, onReleased handlers
857 \li parent item
858 \endlist
859
860 If the event is accepted during any of the above steps, key
861 propagation stops.
862
863 \sa KeyEvent, {KeyNavigation}{KeyNavigation attached property}
864*/
865
866/*!
867 \qmlproperty bool QtQuick::Keys::enabled
868
869 This flags enables key handling if true (default); otherwise
870 no key handlers will be called.
871*/
872
873/*!
874 \qmlproperty enumeration QtQuick::Keys::priority
875
876 This property determines whether the keys are processed before
877 or after the attached item's own key handling.
878
879 \value Keys.BeforeItem (default) process the key events before normal item key processing.
880 If the event is accepted, it will not be passed on to the item.
881 \value Keys.AfterItem process the key events after normal item key handling. If the item
882 accepts the key event, it will not be handled by the
883 Keys attached property handler.
884
885 \sa {Key Handling Priorities}
886*/
887
888/*!
889 \qmlproperty list<Item> QtQuick::Keys::forwardTo
890
891 This property provides a way to forward key presses, key releases, and keyboard input
892 coming from input methods to other items. This can be useful when you want
893 one item to handle some keys (e.g. the up and down arrow keys), and another item to
894 handle other keys (e.g. the left and right arrow keys). Once an item that has been
895 forwarded keys accepts the event it is no longer forwarded to items later in the
896 list.
897
898 This example forwards key events to two lists:
899 \qml
900 Item {
901 ListView {
902 id: list1
903 // ...
904 }
905 ListView {
906 id: list2
907 // ...
908 }
909 Keys.forwardTo: [list1, list2]
910 focus: true
911 }
912 \endqml
913
914 To see the order in which events are received when using forwardTo, see
915 \l {Key Handling Priorities}.
916*/
917
918/*!
919 \qmlsignal QtQuick::Keys::pressed(KeyEvent event)
920
921 This signal is emitted when a key has been pressed. The \a event
922 parameter provides information about the event.
923*/
924
925/*!
926 \qmlsignal QtQuick::Keys::released(KeyEvent event)
927
928 This signal is emitted when a key has been released. The \a event
929 parameter provides information about the event.
930*/
931
932/*!
933 \qmlsignal QtQuick::Keys::shortcutOverride(KeyEvent event)
934 \since 5.9
935
936 This signal is emitted when a key has been pressed that could potentially
937 be used as a shortcut. The \a event parameter provides information about
938 the event.
939
940 Set \c event.accepted to \c true if you wish to prevent the pressed key
941 from being used as a shortcut by other types, such as \l Shortcut. For
942 example:
943
944 \code
945 Item {
946 id: escapeItem
947 focus: true
948
949 // Ensure that we get escape key press events first.
950 Keys.onShortcutOverride: (event)=> event.accepted = (event.key === Qt.Key_Escape)
951
952 Keys.onEscapePressed: {
953 console.log("escapeItem is handling escape");
954 // event.accepted is set to true by default for the specific key handlers
955 }
956 }
957
958 Shortcut {
959 sequence: "Escape"
960 onActivated: console.log("Shortcut is handling escape")
961 }
962 \endcode
963
964 As with the other signals, \c shortcutOverride will only be emitted for an
965 item if that item has \l {Item::}{activeFocus}.
966
967 \sa Shortcut
968*/
969
970/*!
971 \qmlsignal QtQuick::Keys::digit0Pressed(KeyEvent event)
972
973 This signal is emitted when the digit '0' has been pressed. The \a event
974 parameter provides information about the event.
975*/
976
977/*!
978 \qmlsignal QtQuick::Keys::digit1Pressed(KeyEvent event)
979
980 This signal is emitted when the digit '1' has been pressed. The \a event
981 parameter provides information about the event.
982*/
983
984/*!
985 \qmlsignal QtQuick::Keys::digit2Pressed(KeyEvent event)
986
987 This signal is emitted when the digit '2' has been pressed. The \a event
988 parameter provides information about the event.
989*/
990
991/*!
992 \qmlsignal QtQuick::Keys::digit3Pressed(KeyEvent event)
993
994 This signal is emitted when the digit '3' has been pressed. The \a event
995 parameter provides information about the event.
996*/
997
998/*!
999 \qmlsignal QtQuick::Keys::digit4Pressed(KeyEvent event)
1000
1001 This signal is emitted when the digit '4' has been pressed. The \a event
1002 parameter provides information about the event.
1003*/
1004
1005/*!
1006 \qmlsignal QtQuick::Keys::digit5Pressed(KeyEvent event)
1007
1008 This signal is emitted when the digit '5' has been pressed. The \a event
1009 parameter provides information about the event.
1010*/
1011
1012/*!
1013 \qmlsignal QtQuick::Keys::digit6Pressed(KeyEvent event)
1014
1015 This signal is emitted when the digit '6' has been pressed. The \a event
1016 parameter provides information about the event.
1017*/
1018
1019/*!
1020 \qmlsignal QtQuick::Keys::digit7Pressed(KeyEvent event)
1021
1022 This signal is emitted when the digit '7' has been pressed. The \a event
1023 parameter provides information about the event.
1024*/
1025
1026/*!
1027 \qmlsignal QtQuick::Keys::digit8Pressed(KeyEvent event)
1028
1029 This signal is emitted when the digit '8' has been pressed. The \a event
1030 parameter provides information about the event.
1031*/
1032
1033/*!
1034 \qmlsignal QtQuick::Keys::digit9Pressed(KeyEvent event)
1035
1036 This signal is emitted when the digit '9' has been pressed. The \a event
1037 parameter provides information about the event.
1038*/
1039
1040/*!
1041 \qmlsignal QtQuick::Keys::leftPressed(KeyEvent event)
1042
1043 This signal is emitted when the Left arrow has been pressed. The \a event
1044 parameter provides information about the event.
1045*/
1046
1047/*!
1048 \qmlsignal QtQuick::Keys::rightPressed(KeyEvent event)
1049
1050 This signal is emitted when the Right arrow has been pressed. The \a event
1051 parameter provides information about the event.
1052*/
1053
1054/*!
1055 \qmlsignal QtQuick::Keys::upPressed(KeyEvent event)
1056
1057 This signal is emitted when the Up arrow has been pressed. The \a event
1058 parameter provides information about the event.
1059*/
1060
1061/*!
1062 \qmlsignal QtQuick::Keys::downPressed(KeyEvent event)
1063
1064 This signal is emitted when the Down arrow has been pressed. The \a event
1065 parameter provides information about the event.
1066*/
1067
1068/*!
1069 \qmlsignal QtQuick::Keys::tabPressed(KeyEvent event)
1070
1071 This signal is emitted when the Tab key has been pressed. The \a event
1072 parameter provides information about the event.
1073*/
1074
1075/*!
1076 \qmlsignal QtQuick::Keys::backtabPressed(KeyEvent event)
1077
1078 This signal is emitted when the Shift+Tab key combination (Backtab) has
1079 been pressed. The \a event parameter provides information about the event.
1080*/
1081
1082/*!
1083 \qmlsignal QtQuick::Keys::asteriskPressed(KeyEvent event)
1084
1085 This signal is emitted when the Asterisk '*' has been pressed. The \a event
1086 parameter provides information about the event.
1087*/
1088
1089/*!
1090 \qmlsignal QtQuick::Keys::escapePressed(KeyEvent event)
1091
1092 This signal is emitted when the Escape key has been pressed. The \a event
1093 parameter provides information about the event.
1094*/
1095
1096/*!
1097 \qmlsignal QtQuick::Keys::returnPressed(KeyEvent event)
1098
1099 This signal is emitted when the Return key has been pressed. The \a event
1100 parameter provides information about the event.
1101*/
1102
1103/*!
1104 \qmlsignal QtQuick::Keys::enterPressed(KeyEvent event)
1105
1106 This signal is emitted when the Enter key has been pressed. The \a event
1107 parameter provides information about the event.
1108*/
1109
1110/*!
1111 \qmlsignal QtQuick::Keys::deletePressed(KeyEvent event)
1112
1113 This signal is emitted when the Delete key has been pressed. The \a event
1114 parameter provides information about the event.
1115*/
1116
1117/*!
1118 \qmlsignal QtQuick::Keys::spacePressed(KeyEvent event)
1119
1120 This signal is emitted when the Space key has been pressed. The \a event
1121 parameter provides information about the event.
1122*/
1123
1124/*!
1125 \qmlsignal QtQuick::Keys::backPressed(KeyEvent event)
1126
1127 This signal is emitted when the Back key has been pressed. The \a event
1128 parameter provides information about the event.
1129*/
1130
1131/*!
1132 \qmlsignal QtQuick::Keys::cancelPressed(KeyEvent event)
1133
1134 This signal is emitted when the Cancel key has been pressed. The \a event
1135 parameter provides information about the event.
1136*/
1137
1138/*!
1139 \qmlsignal QtQuick::Keys::selectPressed(KeyEvent event)
1140
1141 This signal is emitted when the Select key has been pressed. The \a event
1142 parameter provides information about the event.
1143*/
1144
1145/*!
1146 \qmlsignal QtQuick::Keys::yesPressed(KeyEvent event)
1147
1148 This signal is emitted when the Yes key has been pressed. The \a event
1149 parameter provides information about the event.
1150*/
1151
1152/*!
1153 \qmlsignal QtQuick::Keys::noPressed(KeyEvent event)
1154
1155 This signal is emitted when the No key has been pressed. The \a event
1156 parameter provides information about the event.
1157*/
1158
1159/*!
1160 \qmlsignal QtQuick::Keys::context1Pressed(KeyEvent event)
1161
1162 This signal is emitted when the Context1 key has been pressed. The \a event
1163 parameter provides information about the event.
1164*/
1165
1166/*!
1167 \qmlsignal QtQuick::Keys::context2Pressed(KeyEvent event)
1168
1169 This signal is emitted when the Context2 key has been pressed. The \a event
1170 parameter provides information about the event.
1171*/
1172
1173/*!
1174 \qmlsignal QtQuick::Keys::context3Pressed(KeyEvent event)
1175
1176 This signal is emitted when the Context3 key has been pressed. The \a event
1177 parameter provides information about the event.
1178*/
1179
1180/*!
1181 \qmlsignal QtQuick::Keys::context4Pressed(KeyEvent event)
1182
1183 This signal is emitted when the Context4 key has been pressed. The \a event
1184 parameter provides information about the event.
1185*/
1186
1187/*!
1188 \qmlsignal QtQuick::Keys::callPressed(KeyEvent event)
1189
1190 This signal is emitted when the Call key has been pressed. The \a event
1191 parameter provides information about the event.
1192*/
1193
1194/*!
1195 \qmlsignal QtQuick::Keys::hangupPressed(KeyEvent event)
1196
1197 This signal is emitted when the Hangup key has been pressed. The \a event
1198 parameter provides information about the event.
1199*/
1200
1201/*!
1202 \qmlsignal QtQuick::Keys::flipPressed(KeyEvent event)
1203
1204 This signal is emitted when the Flip key has been pressed. The \a event
1205 parameter provides information about the event.
1206*/
1207
1208/*!
1209 \qmlsignal QtQuick::Keys::menuPressed(KeyEvent event)
1210
1211 This signal is emitted when the Menu key has been pressed. The \a event
1212 parameter provides information about the event.
1213*/
1214
1215/*!
1216 \qmlsignal QtQuick::Keys::volumeUpPressed(KeyEvent event)
1217
1218 This signal is emitted when the VolumeUp key has been pressed. The \a event
1219 parameter provides information about the event.
1220*/
1221
1222/*!
1223 \qmlsignal QtQuick::Keys::volumeDownPressed(KeyEvent event)
1224
1225 This signal is emitted when the VolumeDown key has been pressed. The \a event
1226 parameter provides information about the event.
1227*/
1228
1229QQuickKeysAttached::QQuickKeysAttached(QObject *parent)
1230: QObject(*(new QQuickKeysAttachedPrivate), parent),
1231 QQuickItemKeyFilter(qmlobject_cast<QQuickItem*>(object: parent))
1232{
1233 Q_D(QQuickKeysAttached);
1234 m_processPost = false;
1235 d->item = qmlobject_cast<QQuickItem*>(object: parent);
1236 if (d->item != parent)
1237 qWarning() << "Could not attach Keys property to: " << parent << " is not an Item";
1238}
1239
1240QQuickKeysAttached::~QQuickKeysAttached()
1241{
1242}
1243
1244QQuickKeysAttached::Priority QQuickKeysAttached::priority() const
1245{
1246 return m_processPost ? AfterItem : BeforeItem;
1247}
1248
1249void QQuickKeysAttached::setPriority(Priority order)
1250{
1251 bool processPost = order == AfterItem;
1252 if (processPost != m_processPost) {
1253 m_processPost = processPost;
1254 emit priorityChanged();
1255 }
1256}
1257
1258void QQuickKeysAttached::componentComplete()
1259{
1260#if QT_CONFIG(im)
1261 Q_D(QQuickKeysAttached);
1262 if (d->item) {
1263 for (int ii = 0; ii < d->targets.size(); ++ii) {
1264 QQuickItem *targetItem = d->targets.at(i: ii);
1265 if (targetItem && (targetItem->flags() & QQuickItem::ItemAcceptsInputMethod)) {
1266 d->item->setFlag(flag: QQuickItem::ItemAcceptsInputMethod);
1267 break;
1268 }
1269 }
1270 }
1271#endif
1272}
1273
1274void QQuickKeysAttached::keyPressed(QKeyEvent *event, bool post)
1275{
1276 Q_D(QQuickKeysAttached);
1277 if (post != m_processPost || !d->enabled || d->inPress) {
1278 event->ignore();
1279 QQuickItemKeyFilter::keyPressed(event, post);
1280 return;
1281 }
1282
1283 // first process forwards
1284 if (d->item && d->item->window()) {
1285 d->inPress = true;
1286 for (int ii = 0; ii < d->targets.size(); ++ii) {
1287 QQuickItem *i = d->targets.at(i: ii);
1288 if (i && i->isVisible()) {
1289 event->accept();
1290 QCoreApplication::sendEvent(receiver: i, event);
1291 if (event->isAccepted()) {
1292 d->inPress = false;
1293 return;
1294 }
1295 }
1296 }
1297 d->inPress = false;
1298 }
1299
1300 QQuickKeyEvent &ke = d->theKeyEvent;
1301 ke.reset(ke: *event);
1302 QByteArray keySignal = keyToSignal(key: event->key());
1303 if (!keySignal.isEmpty()) {
1304 keySignal += "(QQuickKeyEvent*)";
1305 if (isConnected(signalName: keySignal)) {
1306 // If we specifically handle a key then default to accepted
1307 ke.setAccepted(true);
1308 int idx = QQuickKeysAttached::staticMetaObject.indexOfSignal(signal: keySignal);
1309 metaObject()->method(index: idx).invoke(obj: this, c: Qt::DirectConnection, Q_ARG(QQuickKeyEvent*, &ke));
1310 }
1311 }
1312 if (!ke.isAccepted())
1313 emit pressed(event: &ke);
1314 event->setAccepted(ke.isAccepted());
1315
1316 if (!event->isAccepted()) QQuickItemKeyFilter::keyPressed(event, post);
1317}
1318
1319void QQuickKeysAttached::keyReleased(QKeyEvent *event, bool post)
1320{
1321 Q_D(QQuickKeysAttached);
1322 if (post != m_processPost || !d->enabled || d->inRelease) {
1323 event->ignore();
1324 QQuickItemKeyFilter::keyReleased(event, post);
1325 return;
1326 }
1327
1328 if (d->item && d->item->window()) {
1329 d->inRelease = true;
1330 for (int ii = 0; ii < d->targets.size(); ++ii) {
1331 QQuickItem *i = d->targets.at(i: ii);
1332 if (i && i->isVisible()) {
1333 event->accept();
1334 QCoreApplication::sendEvent(receiver: i, event);
1335 if (event->isAccepted()) {
1336 d->inRelease = false;
1337 return;
1338 }
1339 }
1340 }
1341 d->inRelease = false;
1342 }
1343
1344 QQuickKeyEvent &ke = d->theKeyEvent;
1345 ke.reset(ke: *event);
1346 emit released(event: &ke);
1347 event->setAccepted(ke.isAccepted());
1348
1349 if (!event->isAccepted()) QQuickItemKeyFilter::keyReleased(event, post);
1350}
1351
1352#if QT_CONFIG(im)
1353void QQuickKeysAttached::inputMethodEvent(QInputMethodEvent *event, bool post)
1354{
1355 Q_D(QQuickKeysAttached);
1356 if (post == m_processPost && d->item && !d->inIM && d->item->window()) {
1357 d->inIM = true;
1358 for (int ii = 0; ii < d->targets.size(); ++ii) {
1359 QQuickItem *targetItem = d->targets.at(i: ii);
1360 if (targetItem && targetItem->isVisible() && (targetItem->flags() & QQuickItem::ItemAcceptsInputMethod)) {
1361 QCoreApplication::sendEvent(receiver: targetItem, event);
1362 if (event->isAccepted()) {
1363 d->imeItem = targetItem;
1364 d->inIM = false;
1365 return;
1366 }
1367 }
1368 }
1369 d->inIM = false;
1370 }
1371 QQuickItemKeyFilter::inputMethodEvent(event, post);
1372}
1373
1374QVariant QQuickKeysAttached::inputMethodQuery(Qt::InputMethodQuery query) const
1375{
1376 Q_D(const QQuickKeysAttached);
1377 if (d->item) {
1378 for (int ii = 0; ii < d->targets.size(); ++ii) {
1379 QQuickItem *i = d->targets.at(i: ii);
1380 if (i && i->isVisible() && (i->flags() & QQuickItem::ItemAcceptsInputMethod) && i == d->imeItem) {
1381 //### how robust is i == d->imeItem check?
1382 QVariant v = i->inputMethodQuery(query);
1383 if (v.userType() == QMetaType::QRectF)
1384 v = d->item->mapRectFromItem(item: i, rect: v.toRectF()); //### cost?
1385 return v;
1386 }
1387 }
1388 }
1389 return QQuickItemKeyFilter::inputMethodQuery(query);
1390}
1391#endif // im
1392
1393void QQuickKeysAttached::shortcutOverrideEvent(QKeyEvent *event)
1394{
1395 Q_D(QQuickKeysAttached);
1396 QQuickKeyEvent &keyEvent = d->theKeyEvent;
1397 keyEvent.reset(ke: *event);
1398 emit shortcutOverride(event: &keyEvent);
1399
1400 event->setAccepted(keyEvent.isAccepted());
1401}
1402
1403QQuickKeysAttached *QQuickKeysAttached::qmlAttachedProperties(QObject *obj)
1404{
1405 return new QQuickKeysAttached(obj);
1406}
1407
1408/*!
1409 \qmltype LayoutMirroring
1410 \nativetype QQuickLayoutMirroringAttached
1411 \inqmlmodule QtQuick
1412 \ingroup qtquick-positioners
1413 \ingroup qml-utility-elements
1414 \brief Property used to mirror layout behavior.
1415
1416 The LayoutMirroring attached property is used to horizontally mirror \l {anchor-layout}{Item anchors},
1417 \l{Item Positioners}{positioner} types (such as \l Row and \l Grid)
1418 and views (such as \l GridView and horizontal \l ListView). Mirroring is a visual change: left
1419 anchors become right anchors, and positioner types like \l Grid and \l Row reverse the
1420 horizontal layout of child items.
1421
1422 Mirroring is enabled for an item by setting the \l enabled property to true. By default, this
1423 only affects the item itself; setting the \l childrenInherit property to true propagates the mirroring
1424 behavior to all child items as well. If the \c LayoutMirroring attached property has not been defined
1425 for an item, mirroring is not enabled.
1426
1427 \note Since Qt 5.8, \c LayoutMirroring can be attached to a \l Window. In practice, it is the same as
1428 attaching \c LayoutMirroring to the window's \c contentItem.
1429
1430 The following example shows mirroring in action. The \l Row below is specified as being anchored
1431 to the left of its parent. However, since mirroring has been enabled, the anchor is horizontally
1432 reversed and it is now anchored to the right. Also, since items in a \l Row are positioned
1433 from left to right by default, they are now positioned from right to left instead, as demonstrated
1434 by the numbering and opacity of the items:
1435
1436 \snippet qml/layoutmirroring.qml 0
1437
1438 \image layoutmirroring.png
1439
1440 Layout mirroring is useful when it is necessary to support both left-to-right and right-to-left
1441 layout versions of an application to target different language areas. The \l childrenInherit
1442 property allows layout mirroring to be applied without manually setting layout configurations
1443 for every item in an application. Keep in mind, however, that mirroring does not affect any
1444 positioning that is defined by the \l Item \l {Item::}{x} coordinate value, so even with
1445 mirroring enabled, it will often be necessary to apply some layout fixes to support the
1446 desired layout direction. Also, it may be necessary to disable the mirroring of individual
1447 child items (by setting \l {enabled}{LayoutMirroring.enabled} to false for such items) if
1448 mirroring is not the desired behavior, or if the child item already implements mirroring in
1449 some custom way.
1450
1451 To set the layout direction based on the \l {Default Layout Direction}{default layout direction}
1452 of the application, use the following code:
1453
1454 \code
1455 LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft
1456 \endcode
1457
1458 See \l {Right-to-left User Interfaces} for further details on using \c LayoutMirroring and
1459 other related features to implement right-to-left support for an application.
1460*/
1461
1462/*!
1463 \qmlproperty bool QtQuick::LayoutMirroring::enabled
1464
1465 This property holds whether the item's layout is mirrored horizontally. Setting this to true
1466 horizontally reverses \l {anchor-layout}{anchor} settings such that left anchors become right,
1467 and right anchors become left. For \l{Item Positioners}{positioner} types
1468 (such as \l Row and \l Grid) and view types (such as \l {GridView}{GridView} and \l {ListView}{ListView})
1469 this also mirrors the horizontal layout direction of the item.
1470
1471 The default value is false.
1472*/
1473
1474/*!
1475 \qmlproperty bool QtQuick::LayoutMirroring::childrenInherit
1476
1477 This property holds whether the \l {enabled}{LayoutMirroring.enabled} value for this item
1478 is inherited by its children.
1479
1480 The default value is false.
1481*/
1482
1483
1484QQuickLayoutMirroringAttached::QQuickLayoutMirroringAttached(QObject *parent) : QObject(parent), itemPrivate(nullptr)
1485{
1486 if (QQuickItem *item = qobject_cast<QQuickItem *>(o: parent))
1487 itemPrivate = QQuickItemPrivate::get(item);
1488 else if (QQuickWindow *window = qobject_cast<QQuickWindow *>(object: parent))
1489 itemPrivate = QQuickItemPrivate::get(item: window->contentItem());
1490
1491 if (itemPrivate)
1492 itemPrivate->extra.value().layoutDirectionAttached = this;
1493 else
1494 qmlWarning(me: parent) << tr(s: "LayoutMirroring attached property only works with Items and Windows");
1495}
1496
1497QQuickLayoutMirroringAttached * QQuickLayoutMirroringAttached::qmlAttachedProperties(QObject *object)
1498{
1499 return new QQuickLayoutMirroringAttached(object);
1500}
1501
1502bool QQuickLayoutMirroringAttached::enabled() const
1503{
1504 return itemPrivate ? itemPrivate->effectiveLayoutMirror : false;
1505}
1506
1507void QQuickLayoutMirroringAttached::setEnabled(bool enabled)
1508{
1509 if (!itemPrivate)
1510 return;
1511
1512 itemPrivate->isMirrorImplicit = false;
1513 if (enabled != itemPrivate->effectiveLayoutMirror) {
1514 itemPrivate->setLayoutMirror(enabled);
1515 if (itemPrivate->inheritMirrorFromItem)
1516 itemPrivate->resolveLayoutMirror();
1517 }
1518}
1519
1520void QQuickLayoutMirroringAttached::resetEnabled()
1521{
1522 if (itemPrivate && !itemPrivate->isMirrorImplicit) {
1523 itemPrivate->isMirrorImplicit = true;
1524 itemPrivate->resolveLayoutMirror();
1525 }
1526}
1527
1528bool QQuickLayoutMirroringAttached::childrenInherit() const
1529{
1530 return itemPrivate ? itemPrivate->inheritMirrorFromItem : false;
1531}
1532
1533void QQuickLayoutMirroringAttached::setChildrenInherit(bool childrenInherit) {
1534 if (itemPrivate && childrenInherit != itemPrivate->inheritMirrorFromItem) {
1535 itemPrivate->inheritMirrorFromItem = childrenInherit;
1536 itemPrivate->resolveLayoutMirror();
1537 childrenInheritChanged();
1538 }
1539}
1540
1541void QQuickItemPrivate::resolveLayoutMirror()
1542{
1543 Q_Q(QQuickItem);
1544 if (QQuickItem *parentItem = q->parentItem()) {
1545 QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(item: parentItem);
1546 setImplicitLayoutMirror(mirror: parentPrivate->inheritedLayoutMirror, inherit: parentPrivate->inheritMirrorFromParent);
1547 } else {
1548 setImplicitLayoutMirror(mirror: isMirrorImplicit ? false : effectiveLayoutMirror, inherit: inheritMirrorFromItem);
1549 }
1550}
1551
1552void QQuickItemPrivate::setImplicitLayoutMirror(bool mirror, bool inherit)
1553{
1554 inherit = inherit || inheritMirrorFromItem;
1555 if (!isMirrorImplicit && inheritMirrorFromItem)
1556 mirror = effectiveLayoutMirror;
1557 if (mirror == inheritedLayoutMirror && inherit == inheritMirrorFromParent)
1558 return;
1559
1560 inheritMirrorFromParent = inherit;
1561 inheritedLayoutMirror = inheritMirrorFromParent ? mirror : false;
1562
1563 if (isMirrorImplicit)
1564 setLayoutMirror(inherit ? inheritedLayoutMirror : false);
1565 for (int i = 0; i < childItems.size(); ++i) {
1566 if (QQuickItem *child = qmlobject_cast<QQuickItem *>(object: childItems.at(i))) {
1567 QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(item: child);
1568 childPrivate->setImplicitLayoutMirror(mirror: inheritedLayoutMirror, inherit: inheritMirrorFromParent);
1569 }
1570 }
1571}
1572
1573void QQuickItemPrivate::setLayoutMirror(bool mirror)
1574{
1575 if (mirror != effectiveLayoutMirror) {
1576 effectiveLayoutMirror = mirror;
1577 if (_anchors) {
1578 QQuickAnchorsPrivate *anchor_d = QQuickAnchorsPrivate::get(o: _anchors);
1579 anchor_d->fillChanged();
1580 anchor_d->centerInChanged();
1581 anchor_d->updateHorizontalAnchors();
1582 }
1583 mirrorChange();
1584 if (extra.isAllocated() && extra->layoutDirectionAttached) {
1585 emit extra->layoutDirectionAttached->enabledChanged();
1586 }
1587 }
1588}
1589
1590/*!
1591 \qmltype EnterKey
1592 \nativetype QQuickEnterKeyAttached
1593 \inqmlmodule QtQuick
1594 \ingroup qtquick-input
1595 \since 5.6
1596 \brief Provides a property to manipulate the appearance of Enter key on
1597 an on-screen keyboard.
1598
1599 The EnterKey attached property is used to manipulate the appearance and
1600 behavior of the Enter key on an on-screen keyboard.
1601*/
1602
1603/*!
1604 \qmlattachedproperty enumeration QtQuick::EnterKey::type
1605
1606 Holds the type of the Enter key.
1607
1608 \note Not all of these values are supported on all platforms. For
1609 unsupported values the default key is used instead.
1610
1611 \value Qt.EnterKeyDefault The default Enter key. This can be either a
1612 button to accept the input and close the
1613 keyboard, or a \e Return button to enter a
1614 newline in case of a multi-line input field.
1615
1616 \value Qt.EnterKeyReturn Show a \e Return button that inserts a
1617 newline.
1618
1619 \value Qt.EnterKeyDone Show a \e {"Done"} button. Typically, the
1620 keyboard is expected to close when the button
1621 is pressed.
1622
1623 \value Qt.EnterKeyGo Show a \e {"Go"} button. Typically used in an
1624 address bar when entering a URL.
1625
1626 \value Qt.EnterKeySend Show a \e {"Send"} button.
1627
1628 \value Qt.EnterKeySearch Show a \e {"Search"} button.
1629
1630 \value Qt.EnterKeyNext Show a \e {"Next"} button. Typically used in a
1631 form to allow navigating to the next input
1632 field without the keyboard closing.
1633
1634 \value Qt.EnterKeyPrevious Show a \e {"Previous"} button.
1635*/
1636
1637QQuickEnterKeyAttached::QQuickEnterKeyAttached(QObject *parent)
1638 : QObject(parent), itemPrivate(nullptr), keyType(Qt::EnterKeyDefault)
1639{
1640 if (QQuickItem *item = qobject_cast<QQuickItem*>(o: parent)) {
1641 itemPrivate = QQuickItemPrivate::get(item);
1642 itemPrivate->extra.value().enterKeyAttached = this;
1643 } else
1644 qmlWarning(me: parent) << tr(s: "EnterKey attached property only works with Items");
1645}
1646
1647QQuickEnterKeyAttached *QQuickEnterKeyAttached::qmlAttachedProperties(QObject *object)
1648{
1649 return new QQuickEnterKeyAttached(object);
1650}
1651
1652Qt::EnterKeyType QQuickEnterKeyAttached::type() const
1653{
1654 return keyType;
1655}
1656
1657void QQuickEnterKeyAttached::setType(Qt::EnterKeyType type)
1658{
1659 if (keyType != type) {
1660 keyType = type;
1661#if QT_CONFIG(im)
1662 if (itemPrivate && itemPrivate->activeFocus)
1663 QGuiApplication::inputMethod()->update(queries: Qt::ImEnterKeyType);
1664#endif
1665 typeChanged();
1666 }
1667}
1668
1669void QQuickItemPrivate::setAccessible()
1670{
1671 isAccessible = true;
1672}
1673
1674/*!
1675Clears all sub focus items from \a scope.
1676If \a focus is true, sets the scope's subFocusItem
1677to be this item.
1678*/
1679void QQuickItemPrivate::updateSubFocusItem(QQuickItem *scope, bool focus)
1680{
1681 Q_Q(QQuickItem);
1682 Q_ASSERT(scope);
1683
1684 QQuickItemPrivate *scopePrivate = QQuickItemPrivate::get(item: scope);
1685
1686 QQuickItem *oldSubFocusItem = scopePrivate->subFocusItem;
1687 // Correct focus chain in scope
1688 if (oldSubFocusItem) {
1689 QQuickItem *sfi = scopePrivate->subFocusItem->parentItem();
1690 while (sfi && sfi != scope) {
1691 QQuickItemPrivate::get(item: sfi)->subFocusItem = nullptr;
1692 sfi = sfi->parentItem();
1693 }
1694 }
1695
1696 if (focus) {
1697 scopePrivate->subFocusItem = q;
1698 QQuickItem *sfi = scopePrivate->subFocusItem->parentItem();
1699 while (sfi && sfi != scope) {
1700 QQuickItemPrivate::get(item: sfi)->subFocusItem = q;
1701 sfi = sfi->parentItem();
1702 }
1703 } else {
1704 scopePrivate->subFocusItem = nullptr;
1705 }
1706}
1707
1708
1709bool QQuickItemPrivate::setFocusIfNeeded(QEvent::Type eventType)
1710{
1711 Q_Q(QQuickItem);
1712 const bool setFocusOnRelease = QGuiApplication::styleHints()->setFocusOnTouchRelease();
1713 Qt::FocusPolicy policy = Qt::ClickFocus;
1714
1715 switch (eventType) {
1716 case QEvent::MouseButtonPress:
1717 case QEvent::MouseButtonDblClick:
1718 case QEvent::TouchBegin:
1719 if (setFocusOnRelease)
1720 return false;
1721 break;
1722 case QEvent::MouseButtonRelease:
1723 case QEvent::TouchEnd:
1724 if (!setFocusOnRelease)
1725 return false;
1726 break;
1727 case QEvent::Wheel:
1728 policy = Qt::WheelFocus;
1729 break;
1730 default:
1731 break;
1732 }
1733
1734 if ((focusPolicy & policy) == policy) {
1735 setActiveFocus(item: q, reason: Qt::MouseFocusReason);
1736 return true;
1737 }
1738
1739 return false;
1740}
1741
1742Qt::FocusReason QQuickItemPrivate::lastFocusChangeReason() const
1743{
1744 return static_cast<Qt::FocusReason>(focusReason);
1745}
1746
1747bool QQuickItemPrivate::setLastFocusChangeReason(Qt::FocusReason reason)
1748{
1749 if (focusReason == reason)
1750 return false;
1751
1752 focusReason = reason;
1753 return true;
1754}
1755
1756/*!
1757 \class QQuickItem
1758 \brief The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
1759 \inmodule QtQuick
1760
1761 All visual items in Qt Quick inherit from QQuickItem. Although a QQuickItem
1762 instance has no visual appearance, it defines all the attributes that are
1763 common across visual items, such as x and y position, width and height,
1764 \l {Positioning with Anchors}{anchoring} and key handling support.
1765
1766 You can subclass QQuickItem to provide your own custom visual item
1767 that inherits these features.
1768
1769 \section1 Custom Scene Graph Items
1770
1771 All visual QML items are rendered using the scene graph, the
1772 default implementation of which is a low-level, high-performance
1773 rendering stack, closely tied to accelerated graphics APIs, such
1774 as OpenGL, Vulkan, Metal, or Direct 3D. It is possible for
1775 subclasses of QQuickItem to add their own custom content into the
1776 scene graph by setting the QQuickItem::ItemHasContents flag and
1777 reimplementing the QQuickItem::updatePaintNode() function.
1778
1779 \warning It is crucial that graphics operations and interaction with
1780 the scene graph happens exclusively on the rendering thread,
1781 primarily during the updatePaintNode() call. The best rule of
1782 thumb is to only use classes with the "QSG" prefix inside the
1783 QQuickItem::updatePaintNode() function.
1784
1785 \note All classes with QSG prefix should be used solely on the scene graph's
1786 rendering thread. See \l {Scene Graph and Rendering} for more information.
1787
1788 \section2 Graphics Resource Handling
1789
1790 The preferred way to handle cleanup of graphics resources used in
1791 the scene graph, is to rely on the automatic cleanup of nodes. A
1792 QSGNode returned from QQuickItem::updatePaintNode() is
1793 automatically deleted on the right thread at the right time. Trees
1794 of QSGNode instances are managed through the use of
1795 QSGNode::OwnedByParent, which is set by default. So, for the
1796 majority of custom scene graph items, no extra work will be
1797 required.
1798
1799 Implementations that store graphics resources outside the node
1800 tree, such as an item implementing QQuickItem::textureProvider(),
1801 will need to take care in cleaning it up correctly depending on
1802 how the item is used in QML. The situations to handle are:
1803
1804 \list
1805
1806 \li The scene graph is invalidated; This can happen, depending on
1807 the platform and QQuickWindow configuration, when the window is
1808 hidden using QQuickWindow::hide(), or when it is closed. If the
1809 item class implements a \c slot named \c invalidateSceneGraph(),
1810 this slot will be called on the rendering thread while the GUI
1811 thread is blocked. This is equivalent to connecting to
1812 QQuickWindow::sceneGraphInvalidated(). When rendering through
1813 OpenGL, the OpenGL context of this item's window will be bound
1814 when this slot is called. The only exception is if the native
1815 OpenGL has been destroyed outside Qt's control, for instance
1816 through \c EGL_CONTEXT_LOST.
1817
1818 \li The item is removed from the scene; If an item is taken out of
1819 the scene, for instance because it's parent was set to \c null or
1820 an item in another window, the QQuickItem::releaseResources() will
1821 be called on the GUI thread. QQuickWindow::scheduleRenderJob()
1822 should be used to schedule cleanup of rendering resources.
1823
1824 \li The item is deleted; When the destructor if an item runs, it
1825 should delete any graphics resources it has. If neither of the two
1826 conditions above were already met, the item will be part of a
1827 window and it is possible to use QQuickWindow::scheduleRenderJob()
1828 to have them cleaned up. If an implementation ignores the call to
1829 QQuickItem::releaseResources(), the item will in many cases no
1830 longer have access to a QQuickWindow and thus no means of
1831 scheduling cleanup.
1832
1833 \endlist
1834
1835 When scheduling cleanup of graphics resources using
1836 QQuickWindow::scheduleRenderJob(), one should use either
1837 QQuickWindow::BeforeSynchronizingStage or
1838 QQuickWindow::AfterSynchronizingStage. The \l {Scene Graph and
1839 Rendering}{synchronization stage} is where the scene graph is
1840 changed as a result of changes to the QML tree. If cleanup is
1841 scheduled at any other time, it may result in other parts of the
1842 scene graph referencing the newly deleted objects as these parts
1843 have not been updated.
1844
1845 \note Use of QObject::deleteLater() to clean up graphics resources
1846 is strongly discouraged as this will make the \c delete operation
1847 run at an arbitrary time and it is unknown if there will be an
1848 OpenGL context bound when the deletion takes place.
1849
1850 \section1 Custom QPainter Items
1851
1852 The QQuickItem provides a subclass, QQuickPaintedItem, which
1853 allows the users to render content using QPainter.
1854
1855 \warning Using QQuickPaintedItem uses an indirect 2D surface to
1856 render its content, using software rasterization, so the rendering
1857 is a two-step operation. First rasterize the surface, then draw
1858 the surface. Using scene graph API directly is always
1859 significantly faster.
1860
1861 \section1 Behavior Animations
1862
1863 If your Item uses the \l Behavior type to define animations for property
1864 changes, you should always use either QObject::setProperty(),
1865 QQmlProperty(), or QMetaProperty::write() when you need to modify those
1866 properties from C++. This ensures that the QML engine knows about the
1867 property change. Otherwise, the engine won't be able to carry out your
1868 requested animation.
1869 Note that these functions incur a slight performance penalty. For more
1870 details, see \l {Accessing Members of a QML Object Type from C++}.
1871
1872 \sa QQuickWindow, QQuickPaintedItem
1873*/
1874
1875/*!
1876 \qmltype Item
1877 \nativetype QQuickItem
1878 \inherits QtObject
1879 \inqmlmodule QtQuick
1880 \ingroup qtquick-visual
1881 \brief A basic visual QML type.
1882
1883 The Item type is the base type for all visual items in Qt Quick.
1884
1885 All visual items in Qt Quick inherit from Item. Although an Item
1886 object has no visual appearance, it defines all the attributes that are
1887 common across visual items, such as x and y position, width and height,
1888 \l {Positioning with Anchors}{anchoring} and key handling support.
1889
1890 The Item type can be useful for grouping several items under a single
1891 root visual item. For example:
1892
1893 \qml
1894 import QtQuick 2.0
1895
1896 Item {
1897 Image {
1898 source: "tile.png"
1899 }
1900 Image {
1901 x: 80
1902 width: 100
1903 height: 100
1904 source: "tile.png"
1905 }
1906 Image {
1907 x: 190
1908 width: 100
1909 height: 100
1910 fillMode: Image.Tile
1911 source: "tile.png"
1912 }
1913 }
1914 \endqml
1915
1916
1917 \section2 Event Handling
1918
1919 All Item-based visual types can use \l {Qt Quick Input Handlers}{Input Handlers}
1920 to handle incoming input events (subclasses of QInputEvent), such as mouse,
1921 touch and key events. This is the preferred declarative way to handle events.
1922
1923 An alternative way to handle touch events is to subclass QQuickItem, call
1924 setAcceptTouchEvents() in the constructor, and override touchEvent().
1925 \l {QEvent::setAccepted()}{Accept} the entire event to stop delivery to
1926 items underneath, and to exclusively grab for all the event's touch points.
1927 Use QPointerEvent::setExclusiveGrabber() to grab only certain touchpoints,
1928 and allow the event to be delivered further.
1929
1930 Likewise, a QQuickItem subclass can call setAcceptedMouseButtons()
1931 to register to receive mouse button events, setAcceptHoverEvents()
1932 to receive hover events (mouse movements while no button is pressed),
1933 and override the virtual functions mousePressEvent(), mouseMoveEvent(), and
1934 mouseReleaseEvent(). Those can also accept the event to prevent further
1935 delivery and get an implicit grab at the same time; or explicitly
1936 \l {QPointerEvent::setExclusiveGrabber()}{grab} the single QEventPoint
1937 that the QMouseEvent carries.
1938
1939 Key handling is available to all Item-based visual types via the \l Keys
1940 attached property. The \e Keys attached property provides basic signals
1941 such as \l {Keys::}{pressed} and \l {Keys::}{released}, as well as
1942 signals for specific keys, such as \l {Keys::}{spacePressed}. The
1943 example below assigns \l {Keyboard Focus in Qt Quick}{keyboard focus} to
1944 the item and handles the left key via the general \c onPressed handler
1945 and the return key via the \c onReturnPressed handler:
1946
1947 \qml
1948 import QtQuick 2.0
1949
1950 Item {
1951 focus: true
1952 Keys.onPressed: (event)=> {
1953 if (event.key == Qt.Key_Left) {
1954 console.log("move left");
1955 event.accepted = true;
1956 }
1957 }
1958 Keys.onReturnPressed: console.log("Pressed return");
1959 }
1960 \endqml
1961
1962 See the \l Keys attached property for detailed documentation.
1963
1964 \section2 Layout Mirroring
1965
1966 Item layouts can be mirrored using the \l LayoutMirroring attached
1967 property. This causes \l{anchors.top}{anchors} to be horizontally
1968 reversed, and also causes items that lay out or position their children
1969 (such as ListView or \l Row) to horizontally reverse the direction of
1970 their layouts.
1971
1972 See LayoutMirroring for more details.
1973
1974 \section1 Item Layers
1975
1976 An Item will normally be rendered directly into the window it
1977 belongs to. However, by setting \l layer.enabled, it is possible
1978 to delegate the item and its entire subtree into an offscreen
1979 surface. Only the offscreen surface, a texture, will be then drawn
1980 into the window.
1981
1982 If it is desired to have a texture size different from that of the
1983 item, this is possible using \l layer.textureSize. To render only
1984 a section of the item into the texture, use \l
1985 layer.sourceRect. It is also possible to specify \l
1986 layer.sourceRect so it extends beyond the bounds of the item. In
1987 this case, the exterior will be padded with transparent pixels.
1988
1989 The item will use linear interpolation for scaling if
1990 \l layer.smooth is set to \c true and will use mipmap for
1991 downsampling if \l layer.mipmap is set to \c true. Mipmapping may
1992 improve visual quality of downscaled items. For mipmapping of
1993 single Image items, prefer Image::mipmap.
1994
1995 \section2 Layer Opacity vs Item Opacity
1996
1997 When applying \l opacity to an item hierarchy the opacity is
1998 applied to each item individually. This can lead to undesired
1999 visual results when the opacity is applied to a subtree. Consider
2000 the following example:
2001
2002 \table
2003 \row
2004 \li \inlineimage qml-blending-nonlayered.png
2005 \li \b {Non-layered Opacity} \snippet qml/layerblending.qml non-layered
2006 \endtable
2007
2008 A layer is rendered with the root item's opacity being 1, and then
2009 the root item's opacity is applied to the texture when it is
2010 drawn. This means that fading in a large item hierarchy from
2011 transparent to opaque, or vice versa, can be done without the
2012 overlap artifacts that the normal item by item alpha blending
2013 has. Here is the same example with layer enabled:
2014
2015 \table
2016 \row
2017 \li \image qml-blending-layered.png
2018 \li \b {Layered Opacity} \snippet qml/layerblending.qml layered
2019 \endtable
2020
2021 \section2 Combined with ShaderEffects
2022
2023 Setting \l layer.enabled to true will turn the item into a \l
2024 {QQuickItem::isTextureProvider}{texture provider}, making it
2025 possible to use the item directly as a texture, for instance
2026 in combination with the ShaderEffect type.
2027
2028 It is possible to apply an effect on a layer at runtime using
2029 layer.effect:
2030
2031 \qml
2032 Item {
2033 id: layerRoot
2034 layer.enabled: true
2035 layer.effect: ShaderEffect {
2036 fragmentShader: "effect.frag.qsb"
2037 }
2038 }
2039 \endqml
2040
2041 See ShaderEffect for more information about using effects.
2042
2043 \note \l layer.enabled is actually just a more convenient way of using
2044 ShaderEffectSource.
2045
2046
2047 \section2 Memory and Performance
2048
2049 When an item's layer is enabled, the scene graph will allocate memory
2050 in the GPU equal to \c {width x height x 4}. In memory constrained
2051 configurations, large layers should be used with care.
2052
2053 In the QPainter / QWidget world, it is sometimes favorable to
2054 cache complex content in a pixmap, image or texture. In Qt Quick,
2055 because of the techniques already applied by the \l {Qt Quick
2056 Scene Graph Default Renderer} {scene graph renderer}, this will in most
2057 cases not be the case. Excessive draw calls are already reduced
2058 because of batching and a cache will in most cases end up blending
2059 more pixels than the original content. The overhead of rendering
2060 to an offscreen and the blending involved with drawing the
2061 resulting texture is therefore often more costly than simply
2062 letting the item and its children be drawn normally.
2063
2064 Also, an item using a layer can not be \l {Batching} {batched} during
2065 rendering. This means that a scene with many layered items may
2066 have performance problems.
2067
2068 Layering can be convenient and useful for visual effects, but
2069 should in most cases be enabled for the duration of the effect and
2070 disabled afterwards.
2071
2072*/
2073
2074/*!
2075 \enum QQuickItem::Flag
2076
2077 This enum type is used to specify various item properties.
2078
2079 \value ItemClipsChildrenToShape Indicates this item should visually clip
2080 its children so that they are rendered only within the boundaries of this
2081 item.
2082 \value ItemAcceptsInputMethod Indicates the item supports text input
2083 methods.
2084 \value ItemIsFocusScope Indicates the item is a focus scope. See
2085 \l {Keyboard Focus in Qt Quick} for more information.
2086 \value ItemHasContents Indicates the item has visual content and should be
2087 rendered by the scene graph.
2088 \value ItemAcceptsDrops Indicates the item accepts drag and drop events.
2089 \value ItemIsViewport Indicates that the item defines a viewport for its children.
2090 \value ItemObservesViewport Indicates that the item wishes to know the
2091 viewport bounds when any ancestor has the ItemIsViewport flag set.
2092
2093 \sa setFlag(), setFlags(), flags()
2094*/
2095
2096/*!
2097 \enum QQuickItem::ItemChange
2098 \brief Used in conjunction with QQuickItem::itemChange() to notify
2099 the item about certain types of changes.
2100
2101 \value ItemChildAddedChange A child was added. ItemChangeData::item contains
2102 the added child.
2103
2104 \value ItemChildRemovedChange A child was removed. ItemChangeData::item
2105 contains the removed child.
2106
2107 \value ItemSceneChange The item was added to or removed from a scene. The
2108 QQuickWindow rendering the scene is specified in using ItemChangeData::window.
2109 The window parameter is null when the item is removed from a scene.
2110
2111 \value ItemVisibleHasChanged The item's visibility has changed.
2112 ItemChangeData::boolValue contains the new visibility.
2113
2114 \value ItemParentHasChanged The item's parent has changed.
2115 ItemChangeData::item contains the new parent.
2116
2117 \value ItemOpacityHasChanged The item's opacity has changed.
2118 ItemChangeData::realValue contains the new opacity.
2119
2120 \value ItemActiveFocusHasChanged The item's focus has changed.
2121 ItemChangeData::boolValue contains whether the item has focus or not.
2122
2123 \value ItemRotationHasChanged The item's rotation has changed.
2124 ItemChangeData::realValue contains the new rotation.
2125
2126 \value ItemDevicePixelRatioHasChanged The device pixel ratio of the screen
2127 the item is on has changed. ItemChangedData::realValue contains the new
2128 device pixel ratio.
2129
2130 \value ItemAntialiasingHasChanged The antialiasing has changed. The current
2131 (boolean) value can be found in QQuickItem::antialiasing.
2132
2133 \value ItemEnabledHasChanged The item's enabled state has changed.
2134 ItemChangeData::boolValue contains the new enabled state. (since Qt 5.10)
2135*/
2136
2137/*!
2138 \class QQuickItem::ItemChangeData
2139 \inmodule QtQuick
2140 \brief Adds supplementary information to the QQuickItem::itemChange()
2141 function.
2142
2143 The meaning of each member of this class is defined by the change type.
2144
2145 \sa QQuickItem::ItemChange
2146*/
2147
2148/*!
2149 \fn QQuickItem::ItemChangeData::ItemChangeData(QQuickItem *)
2150 \internal
2151 */
2152
2153/*!
2154 \fn QQuickItem::ItemChangeData::ItemChangeData(QQuickWindow *)
2155 \internal
2156 */
2157
2158/*!
2159 \fn QQuickItem::ItemChangeData::ItemChangeData(qreal)
2160 \internal
2161 */
2162
2163/*!
2164 \fn QQuickItem::ItemChangeData::ItemChangeData(bool)
2165 \internal
2166 */
2167
2168/*!
2169 \variable QQuickItem::ItemChangeData::realValue
2170 The numeric value that has changed: \l {QQuickItem::opacity()}{opacity},
2171 \l {QQuickItem::rotation()}{rotation}, or
2172 \l {QScreen::devicePixelRatio}{device pixel ratio}.
2173 \sa QQuickItem::ItemChange
2174 */
2175
2176/*!
2177 \variable QQuickItem::ItemChangeData::boolValue
2178 The boolean value that has changed: \l {QQuickItem::isVisible()}{visible},
2179 \l {QQuickItem::isEnabled()}{enabled}, \l {QQuickItem::hasActiveFocus()}{activeFocus},
2180 or \l {QQuickItem::antialiasing()}{antialiasing}.
2181 \sa QQuickItem::ItemChange
2182 */
2183
2184/*!
2185 \variable QQuickItem::ItemChangeData::item
2186 The item that has been added or removed as a \l{QQuickItem::childItems()}{child},
2187 or the new \l{QQuickItem::parentItem()}{parent}.
2188 \sa QQuickItem::ItemChange
2189 */
2190
2191/*!
2192 \variable QQuickItem::ItemChangeData::window
2193 The \l{QQuickWindow}{window} in which the item has been shown, or \c nullptr
2194 if the item has been removed from a window.
2195 \sa QQuickItem::ItemChange
2196 */
2197
2198/*!
2199 \enum QQuickItem::TransformOrigin
2200
2201 Controls the point about which simple transforms like scale apply.
2202
2203 \value TopLeft The top-left corner of the item.
2204 \value Top The center point of the top of the item.
2205 \value TopRight The top-right corner of the item.
2206 \value Left The left most point of the vertical middle.
2207 \value Center The center of the item.
2208 \value Right The right most point of the vertical middle.
2209 \value BottomLeft The bottom-left corner of the item.
2210 \value Bottom The center point of the bottom of the item.
2211 \value BottomRight The bottom-right corner of the item.
2212
2213 \sa transformOrigin(), setTransformOrigin()
2214*/
2215
2216/*!
2217 \fn void QQuickItem::childrenRectChanged(const QRectF &)
2218 \internal
2219*/
2220
2221/*!
2222 \fn void QQuickItem::baselineOffsetChanged(qreal)
2223 \internal
2224*/
2225
2226/*!
2227 \fn void QQuickItem::stateChanged(const QString &state)
2228 \internal
2229*/
2230
2231/*!
2232 \fn void QQuickItem::parentChanged(QQuickItem *)
2233 \internal
2234*/
2235
2236/*!
2237 \fn void QQuickItem::smoothChanged(bool)
2238 \internal
2239*/
2240
2241/*!
2242 \fn void QQuickItem::antialiasingChanged(bool)
2243 \internal
2244*/
2245
2246/*!
2247 \fn void QQuickItem::clipChanged(bool)
2248 \internal
2249*/
2250
2251/*!
2252 \fn void QQuickItem::transformOriginChanged(TransformOrigin)
2253 \internal
2254*/
2255
2256/*!
2257 \fn void QQuickItem::focusChanged(bool)
2258 \internal
2259*/
2260
2261/*!
2262 \fn void QQuickItem::activeFocusChanged(bool)
2263 \internal
2264*/
2265
2266/*!
2267 \fn void QQuickItem::focusPolicyChanged(Qt::FocusPolicy)
2268 \internal
2269*/
2270
2271/*!
2272 \fn void QQuickItem::activeFocusOnTabChanged(bool)
2273 \internal
2274*/
2275
2276/*!
2277 \fn void QQuickItem::childrenChanged()
2278 \internal
2279*/
2280
2281/*!
2282 \fn void QQuickItem::opacityChanged()
2283 \internal
2284*/
2285
2286/*!
2287 \fn void QQuickItem::enabledChanged()
2288 \internal
2289*/
2290
2291/*!
2292 \fn void QQuickItem::visibleChanged()
2293 \internal
2294*/
2295
2296/*!
2297 \fn void QQuickItem::visibleChildrenChanged()
2298 \internal
2299*/
2300
2301/*!
2302 \fn void QQuickItem::rotationChanged()
2303 \internal
2304*/
2305
2306/*!
2307 \fn void QQuickItem::scaleChanged()
2308 \internal
2309*/
2310
2311/*!
2312 \fn void QQuickItem::xChanged()
2313 \internal
2314*/
2315
2316/*!
2317 \fn void QQuickItem::yChanged()
2318 \internal
2319*/
2320
2321/*!
2322 \fn void QQuickItem::widthChanged()
2323 \internal
2324*/
2325
2326/*!
2327 \fn void QQuickItem::heightChanged()
2328 \internal
2329*/
2330
2331/*!
2332 \fn void QQuickItem::zChanged()
2333 \internal
2334*/
2335
2336/*!
2337 \fn void QQuickItem::implicitWidthChanged()
2338 \internal
2339*/
2340
2341/*!
2342 \fn void QQuickItem::implicitHeightChanged()
2343 \internal
2344*/
2345
2346/*!
2347 \fn QQuickItem::QQuickItem(QQuickItem *parent)
2348
2349 Constructs a QQuickItem with the given \a parent.
2350
2351 The \c parent will be used as both the \l {setParentItem()}{visual parent}
2352 and the \l QObject parent.
2353*/
2354QQuickItem::QQuickItem(QQuickItem* parent)
2355: QObject(*(new QQuickItemPrivate), parent)
2356{
2357 Q_D(QQuickItem);
2358 d->init(parent);
2359}
2360
2361/*! \internal
2362*/
2363QQuickItem::QQuickItem(QQuickItemPrivate &dd, QQuickItem *parent)
2364: QObject(dd, parent)
2365{
2366 Q_D(QQuickItem);
2367 d->init(parent);
2368}
2369
2370/*!
2371 Destroys the QQuickItem.
2372*/
2373QQuickItem::~QQuickItem()
2374{
2375 Q_D(QQuickItem);
2376 d->inDestructor = true;
2377
2378 if (d->windowRefCount > 1)
2379 d->windowRefCount = 1; // Make sure window is set to null in next call to derefWindow().
2380 if (d->parentItem)
2381 setParentItem(nullptr);
2382 else if (d->window)
2383 d->derefWindow();
2384
2385 for (QQuickItem *child : std::as_const(t&: d->childItems))
2386 child->setParentItem(nullptr);
2387 d->childItems.clear();
2388
2389 d->notifyChangeListeners(changeTypes: QQuickItemPrivate::AllChanges, function: [this](const QQuickItemPrivate::ChangeListener &change){
2390 QQuickAnchorsPrivate *anchor = change.listener->anchorPrivate();
2391 if (anchor)
2392 anchor->clearItem(this);
2393 });
2394 /*
2395 update item anchors that depended on us unless they are our child (and will also be destroyed),
2396 or our sibling, and our parent is also being destroyed.
2397 */
2398 d->notifyChangeListeners(changeTypes: QQuickItemPrivate::AllChanges, function: [this](const QQuickItemPrivate::ChangeListener &change){
2399 QQuickAnchorsPrivate *anchor = change.listener->anchorPrivate();
2400 if (anchor && anchor->item && anchor->item->parentItem() && anchor->item->parentItem() != this)
2401 anchor->update();
2402 });
2403 d->notifyChangeListeners(changeTypes: QQuickItemPrivate::Destroyed, function: &QQuickItemChangeListener::itemDestroyed, args: this);
2404 d->changeListeners.clear();
2405
2406 /*
2407 Remove any references our transforms have to us, in case they try to
2408 remove themselves from our list of transforms when that list has already
2409 been destroyed after ~QQuickItem() has run.
2410 */
2411 for (int ii = 0; ii < d->transforms.size(); ++ii) {
2412 QQuickTransform *t = d->transforms.at(i: ii);
2413 QQuickTransformPrivate *tp = QQuickTransformPrivate::get(transform: t);
2414 tp->items.removeOne(t: this);
2415 }
2416
2417 if (d->extra.isAllocated()) {
2418 delete d->extra->contents; d->extra->contents = nullptr;
2419#if QT_CONFIG(quick_shadereffect)
2420 delete d->extra->layer; d->extra->layer = nullptr;
2421#endif
2422 }
2423
2424 delete d->_anchors; d->_anchors = nullptr;
2425 delete d->_stateGroup; d->_stateGroup = nullptr;
2426
2427 d->isQuickItem = false;
2428}
2429
2430/*!
2431 \internal
2432*/
2433bool QQuickItemPrivate::canAcceptTabFocus(QQuickItem *item)
2434{
2435 if (!item->window())
2436 return false;
2437
2438 if (item == item->window()->contentItem())
2439 return true;
2440
2441 const auto tabFocus = QGuiApplication::styleHints()->tabFocusBehavior();
2442 if (tabFocus == Qt::NoTabFocus)
2443 return false;
2444 if (tabFocus == Qt::TabFocusAllControls)
2445 return true;
2446
2447 QVariant editable = item->property(name: "editable");
2448 if (editable.isValid())
2449 return editable.toBool();
2450
2451 QVariant readonly = item->property(name: "readOnly");
2452 if (readonly.isValid())
2453 return !readonly.toBool() && item->property(name: "text").isValid();
2454
2455#if QT_CONFIG(accessibility)
2456 QAccessible::Role role = QQuickItemPrivate::get(item)->effectiveAccessibleRole();
2457 if (role == QAccessible::EditableText || role == QAccessible::Table || role == QAccessible::List) {
2458 return true;
2459 } else if (role == QAccessible::ComboBox || role == QAccessible::SpinBox) {
2460 if (QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(item))
2461 return iface->state().editable;
2462 }
2463#endif
2464
2465 return false;
2466}
2467
2468/*!
2469 \internal
2470 \brief QQuickItemPrivate::focusNextPrev focuses the next/prev item in the tab-focus-chain
2471 \param item The item that currently has the focus
2472 \param forward The direction
2473 \return Whether the next item in the focus chain is found or not
2474
2475 If \a next is true, the next item visited will be in depth-first order relative to \a item.
2476 If \a next is false, the next item visited will be in reverse depth-first order relative to \a item.
2477*/
2478bool QQuickItemPrivate::focusNextPrev(QQuickItem *item, bool forward)
2479{
2480 QQuickWindow *window = item->window();
2481 const bool wrap = !window || window->isTopLevel();
2482
2483 QQuickItem *next = QQuickItemPrivate::nextPrevItemInTabFocusChain(item, forward, wrap);
2484
2485 if (next == item)
2486 return false;
2487
2488 const auto reason = forward ? Qt::TabFocusReason : Qt::BacktabFocusReason;
2489
2490 if (!wrap && !next) {
2491 // Focus chain wrapped and we are not top-level window
2492 // Give focus to parent window
2493 Q_ASSERT(window);
2494 Q_ASSERT(window->parent());
2495
2496
2497 qt_window_private(window: window->parent())->setFocusToTarget(
2498 forward ? QWindowPrivate::FocusTarget::Next
2499 : QWindowPrivate::FocusTarget::Prev,
2500 reason);
2501 window->parent()->requestActivate();
2502 return true;
2503 }
2504
2505 next->forceActiveFocus(reason);
2506
2507 return true;
2508}
2509
2510QQuickItem *QQuickItemPrivate::nextTabChildItem(const QQuickItem *item, int start)
2511{
2512 if (!item) {
2513 qWarning() << "QQuickItemPrivate::nextTabChildItem called with null item.";
2514 return nullptr;
2515 }
2516 const QList<QQuickItem *> &children = item->childItems();
2517 const int count = children.size();
2518 if (start < 0 || start >= count) {
2519 qWarning() << "QQuickItemPrivate::nextTabChildItem: Start index value out of range for item" << item;
2520 return nullptr;
2521 }
2522 while (start < count) {
2523 QQuickItem *child = children.at(i: start);
2524 if (!child->d_func()->isTabFence)
2525 return child;
2526 ++start;
2527 }
2528 return nullptr;
2529}
2530
2531QQuickItem *QQuickItemPrivate::prevTabChildItem(const QQuickItem *item, int start)
2532{
2533 if (!item) {
2534 qWarning() << "QQuickItemPrivate::prevTabChildItem called with null item.";
2535 return nullptr;
2536 }
2537 const QList<QQuickItem *> &children = item->childItems();
2538 const int count = children.size();
2539 if (start == -1)
2540 start = count - 1;
2541 if (start < 0 || start >= count) {
2542 qWarning() << "QQuickItemPrivate::prevTabChildItem: Start index value out of range for item" << item;
2543 return nullptr;
2544 }
2545 while (start >= 0) {
2546 QQuickItem *child = children.at(i: start);
2547 if (!child->d_func()->isTabFence)
2548 return child;
2549 --start;
2550 }
2551 return nullptr;
2552}
2553
2554QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, bool forward, bool wrap)
2555{
2556 Q_ASSERT(item);
2557 qCDebug(lcFocus) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: item:" << item << ", forward:" << forward;
2558
2559 if (!item->window())
2560 return item;
2561 const QQuickItem * const contentItem = item->window()->contentItem();
2562 if (!contentItem)
2563 return item;
2564
2565 QQuickItem *from = nullptr;
2566 bool isTabFence = item->d_func()->isTabFence;
2567 if (forward) {
2568 if (!isTabFence)
2569 from = item->parentItem();
2570 } else {
2571 if (!item->childItems().isEmpty())
2572 from = item->d_func()->childItems.constFirst();
2573 else if (!isTabFence)
2574 from = item->parentItem();
2575 }
2576 bool skip = false;
2577
2578 QQuickItem *startItem = item;
2579 QQuickItem *originalStartItem = startItem;
2580 // Protect from endless loop:
2581 // If we start on an invisible item we will not find it again.
2582 // If there is no other item which can become the focus item, we have a forever loop,
2583 // since the protection only works if we encounter the first item again.
2584 while (startItem && !startItem->isVisible()) {
2585 startItem = startItem->parentItem();
2586 }
2587 if (!startItem)
2588 return item;
2589
2590 QQuickItem *firstFromItem = from;
2591 QQuickItem *current = item;
2592 qCDebug(lcFocus) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: startItem:" << startItem;
2593 qCDebug(lcFocus) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: firstFromItem:" << firstFromItem;
2594 QDuplicateTracker<QQuickItem *> cycleDetector;
2595 do {
2596 qCDebug(lcFocus) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: current:" << current;
2597 qCDebug(lcFocus) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: from:" << from;
2598 skip = false;
2599 QQuickItem *last = current;
2600
2601 bool hasChildren = !current->childItems().isEmpty() && current->isEnabled() && current->isVisible();
2602 QQuickItem *firstChild = nullptr;
2603 QQuickItem *lastChild = nullptr;
2604 if (hasChildren) {
2605 firstChild = nextTabChildItem(item: current, start: 0);
2606 if (!firstChild)
2607 hasChildren = false;
2608 else
2609 lastChild = prevTabChildItem(item: current, start: -1);
2610 }
2611 isTabFence = current->d_func()->isTabFence;
2612 if (isTabFence && !hasChildren)
2613 return current;
2614
2615 // coming from parent: check children
2616 if (hasChildren && from == current->parentItem()) {
2617 if (forward) {
2618 current = firstChild;
2619 } else {
2620 current = lastChild;
2621 if (!current->childItems().isEmpty())
2622 skip = true;
2623 }
2624 } else if (hasChildren && forward && from != lastChild) {
2625 // not last child going forwards
2626 int nextChild = current->childItems().indexOf(t: from) + 1;
2627 current = nextTabChildItem(item: current, start: nextChild);
2628 } else if (hasChildren && !forward && from != firstChild) {
2629 // not first child going backwards
2630 int prevChild = current->childItems().indexOf(t: from) - 1;
2631 current = prevTabChildItem(item: current, start: prevChild);
2632 if (!current->childItems().isEmpty())
2633 skip = true;
2634 // back to the parent
2635 } else if (QQuickItem *parent = !isTabFence ? current->parentItem() : nullptr) {
2636 // we would evaluate the parent twice, thus we skip
2637 if (forward) {
2638 skip = true;
2639 } else if (QQuickItem *firstSibling = !forward ? nextTabChildItem(item: parent, start: 0) : nullptr) {
2640 if (last != firstSibling
2641 || (parent->isFocusScope() && parent->activeFocusOnTab() && parent->hasActiveFocus()))
2642 skip = true;
2643 }
2644 current = parent;
2645 } else if (hasChildren) {
2646 if (!wrap) {
2647 qCDebug(lcFocus) << "QQuickItemPrivate::nextPrevItemInTabFocusChain:"
2648 << "Focus chain about to wrap but wrapping was set to false."
2649 << "Returning.";
2650 return nullptr;
2651 }
2652
2653 // Wrap around after checking all items forward
2654 if (forward) {
2655 current = firstChild;
2656 } else {
2657 current = lastChild;
2658 if (!current->childItems().isEmpty())
2659 skip = true;
2660 }
2661 }
2662 from = last;
2663 // if [from] item is equal to [firstFromItem], means we have traversed one path and
2664 // jump back to parent of the chain, and then we have to check whether we have
2665 // traversed all of the chain (by compare the [current] item with [startItem])
2666 // Since the [startItem] might be promoted to its parent if it is invisible,
2667 // we still have to check [current] item with original start item
2668 // We might also run into a cycle before we reach firstFromItem again
2669 // but note that we have to ignore current if we are meant to skip it
2670 if (((current == startItem || current == originalStartItem) && from == firstFromItem) ||
2671 (!skip && cycleDetector.hasSeen(s: current))) {
2672 // wrapped around, avoid endless loops
2673 if (item == contentItem) {
2674 qCDebug(lcFocus) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: looped, return contentItem";
2675 return item;
2676 } else {
2677 qCDebug(lcFocus) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: looped, return " << startItem;
2678 return startItem;
2679 }
2680 }
2681 if (!firstFromItem) {
2682 if (startItem->d_func()->isTabFence) {
2683 if (current == startItem)
2684 firstFromItem = from;
2685 } else { //start from root
2686 startItem = current;
2687 firstFromItem = from;
2688 }
2689 }
2690 } while (skip || !current->activeFocusOnTab() || !current->isEnabled() || !current->isVisible()
2691 || !(QQuickItemPrivate::canAcceptTabFocus(item: current)));
2692
2693 return current;
2694}
2695
2696/*!
2697 \qmlproperty Item QtQuick::Item::parent
2698 This property holds the visual parent of the item.
2699
2700 \note The concept of the \e {visual parent} differs from that of the
2701 \e {QObject parent}. An item's visual parent may not necessarily be the
2702 same as its object parent. See \l {Concepts - Visual Parent in Qt Quick}
2703 for more details.
2704*/
2705/*!
2706 \property QQuickItem::parent
2707 This property holds the visual parent of the item.
2708
2709 \note The concept of the \e {visual parent} differs from that of the
2710 \e {QObject parent}. An item's visual parent may not necessarily be the
2711 same as its object parent. See \l {Concepts - Visual Parent in Qt Quick}
2712 for more details.
2713
2714 \note The notification signal for this property gets emitted during destruction
2715 of the visual parent. C++ signal handlers cannot assume that items in the
2716 visual parent hierarchy are still fully constructed. Use \l qobject_cast to
2717 verify that items in the parent hierarchy can be used safely as the expected
2718 type.
2719*/
2720QQuickItem *QQuickItem::parentItem() const
2721{
2722 Q_D(const QQuickItem);
2723 return d->parentItem;
2724}
2725
2726void QQuickItem::setParentItem(QQuickItem *parentItem)
2727{
2728 Q_D(QQuickItem);
2729 if (parentItem == d->parentItem)
2730 return;
2731
2732 if (parentItem) {
2733 QQuickItem *itemAncestor = parentItem;
2734 while (itemAncestor != nullptr) {
2735 if (Q_UNLIKELY(itemAncestor == this)) {
2736 qWarning() << "QQuickItem::setParentItem: Parent" << parentItem << "is already part of the subtree of" << this;
2737 return;
2738 }
2739 itemAncestor = itemAncestor->parentItem();
2740 }
2741 auto engine = qmlEngine(this);
2742 if (engine) {
2743 QV4::ExecutionEngine *v4 = engine->handle();
2744 QV4::WriteBarrier::markCustom(engine: v4, markFunction: [this](QV4::MarkStack *ms){
2745 QV4::QObjectWrapper::markWrapper(object: this, markStack: ms);
2746 });
2747 }
2748 }
2749
2750 d->removeFromDirtyList();
2751
2752 QQuickItem *oldParentItem = d->parentItem;
2753 QQuickItem *scopeFocusedItem = nullptr;
2754
2755 if (oldParentItem) {
2756 QQuickItemPrivate *op = QQuickItemPrivate::get(item: oldParentItem);
2757
2758 QQuickItem *scopeItem = nullptr;
2759
2760 if (hasFocus() || op->subFocusItem == this)
2761 scopeFocusedItem = this;
2762 else if (!isFocusScope() && d->subFocusItem)
2763 scopeFocusedItem = d->subFocusItem;
2764
2765 if (scopeFocusedItem) {
2766 scopeItem = oldParentItem;
2767 while (!scopeItem->isFocusScope() && scopeItem->parentItem())
2768 scopeItem = scopeItem->parentItem();
2769 if (d->window) {
2770 if (QQuickDeliveryAgentPrivate *da = d->deliveryAgentPrivate()) {
2771 da->clearFocusInScope(scope: scopeItem, item: scopeFocusedItem, reason: Qt::OtherFocusReason,
2772 QQuickDeliveryAgentPrivate::DontChangeFocusProperty);
2773 }
2774 if (scopeFocusedItem != this)
2775 QQuickItemPrivate::get(item: scopeFocusedItem)->updateSubFocusItem(scope: this, focus: true);
2776 } else {
2777 QQuickItemPrivate::get(item: scopeFocusedItem)->updateSubFocusItem(scope: scopeItem, focus: false);
2778 }
2779 }
2780
2781 const bool wasVisible = isVisible();
2782 op->removeChild(this);
2783 if (wasVisible && !op->inDestructor)
2784 emit oldParentItem->visibleChildrenChanged();
2785 } else if (d->window) {
2786 QQuickWindowPrivate::get(c: d->window)->parentlessItems.remove(value: this);
2787 }
2788
2789 QQuickWindow *parentWindow = parentItem ? QQuickItemPrivate::get(item: parentItem)->window : nullptr;
2790 bool alreadyAddedChild = false;
2791 if (d->window == parentWindow) {
2792 // Avoid freeing and reallocating resources if the window stays the same.
2793 d->parentItem = parentItem;
2794 } else {
2795 auto oldParentItem = d->parentItem;
2796 d->parentItem = parentItem;
2797 if (d->parentItem) {
2798 QQuickItemPrivate::get(item: d->parentItem)->addChild(this);
2799 alreadyAddedChild = true;
2800 }
2801 if (d->window) {
2802 d->derefWindow();
2803 // as we potentially changed d->parentWindow above
2804 // the check in derefWindow could not work
2805 // thus, we redo it here with the old parent
2806 // Also, the window may have been deleted by derefWindow()
2807 if (!oldParentItem && d->window) {
2808 QQuickWindowPrivate::get(c: d->window)->parentlessItems.remove(value: this);
2809 }
2810 }
2811 if (parentWindow)
2812 d->refWindow(parentWindow);
2813 }
2814
2815 d->dirty(QQuickItemPrivate::ParentChanged);
2816
2817 if (d->parentItem && !alreadyAddedChild)
2818 QQuickItemPrivate::get(item: d->parentItem)->addChild(this);
2819 else if (d->window && !alreadyAddedChild)
2820 QQuickWindowPrivate::get(c: d->window)->parentlessItems.insert(value: this);
2821
2822 d->setEffectiveVisibleRecur(d->calcEffectiveVisible());
2823 d->setEffectiveEnableRecur(scope: nullptr, d->calcEffectiveEnable());
2824
2825 if (d->parentItem) {
2826 if (!scopeFocusedItem) {
2827 if (hasFocus())
2828 scopeFocusedItem = this;
2829 else if (!isFocusScope() && d->subFocusItem)
2830 scopeFocusedItem = d->subFocusItem;
2831 }
2832
2833 if (scopeFocusedItem) {
2834 // We need to test whether this item becomes scope focused
2835 QQuickItem *scopeItem = d->parentItem;
2836 while (!scopeItem->isFocusScope() && scopeItem->parentItem())
2837 scopeItem = scopeItem->parentItem();
2838
2839 if (QQuickItemPrivate::get(item: scopeItem)->subFocusItem
2840 || (!scopeItem->isFocusScope() && scopeItem->hasFocus())) {
2841 if (scopeFocusedItem != this)
2842 QQuickItemPrivate::get(item: scopeFocusedItem)->updateSubFocusItem(scope: this, focus: false);
2843 QQuickItemPrivate::get(item: scopeFocusedItem)->focus = false;
2844 emit scopeFocusedItem->focusChanged(false);
2845 } else {
2846 if (d->window) {
2847 if (QQuickDeliveryAgentPrivate *da = d->deliveryAgentPrivate()) {
2848 da->setFocusInScope(scope: scopeItem, item: scopeFocusedItem, reason: Qt::OtherFocusReason,
2849 QQuickDeliveryAgentPrivate::DontChangeFocusProperty);
2850 }
2851 } else {
2852 QQuickItemPrivate::get(item: scopeFocusedItem)->updateSubFocusItem(scope: scopeItem, focus: true);
2853 }
2854 }
2855 }
2856 }
2857
2858 if (d->parentItem)
2859 d->resolveLayoutMirror();
2860
2861 d->itemChange(ItemParentHasChanged, d->parentItem);
2862
2863 if (!d->inDestructor)
2864 emit parentChanged(d->parentItem);
2865 if (isVisible() && d->parentItem && !QQuickItemPrivate::get(item: d->parentItem)->inDestructor)
2866 emit d->parentItem->visibleChildrenChanged();
2867}
2868
2869/*!
2870 Moves the specified \a sibling item to the index before this item
2871 within the list of children. The order of children affects both the
2872 visual stacking order and tab focus navigation order.
2873
2874 Assuming the z values of both items are the same, this will cause \a
2875 sibling to be rendered above this item.
2876
2877 If both items have activeFocusOnTab set to \c true, this will also cause
2878 the tab focus order to change, with \a sibling receiving focus after this
2879 item.
2880
2881 The given \a sibling must be a sibling of this item; that is, they must
2882 have the same immediate \l parent.
2883
2884 \sa {Concepts - Visual Parent in Qt Quick}
2885*/
2886void QQuickItem::stackBefore(const QQuickItem *sibling)
2887{
2888 Q_D(QQuickItem);
2889 if (!sibling || sibling == this || !d->parentItem || d->parentItem != QQuickItemPrivate::get(item: sibling)->parentItem) {
2890 qWarning().nospace() << "QQuickItem::stackBefore: Cannot stack "
2891 << this << " before " << sibling << ", which must be a sibling";
2892 return;
2893 }
2894
2895 QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(item: d->parentItem);
2896
2897 int myIndex = parentPrivate->childItems.lastIndexOf(t: this);
2898 int siblingIndex = parentPrivate->childItems.lastIndexOf(t: const_cast<QQuickItem *>(sibling));
2899
2900 Q_ASSERT(myIndex != -1 && siblingIndex != -1);
2901
2902 if (myIndex == siblingIndex - 1)
2903 return;
2904
2905 parentPrivate->childItems.move(from: myIndex, to: myIndex < siblingIndex ? siblingIndex - 1 : siblingIndex);
2906
2907 parentPrivate->markSortedChildrenDirty(child: this);
2908 parentPrivate->dirty(QQuickItemPrivate::ChildrenStackingChanged);
2909
2910 for (int ii = qMin(a: siblingIndex, b: myIndex); ii < parentPrivate->childItems.size(); ++ii)
2911 QQuickItemPrivate::get(item: parentPrivate->childItems.at(i: ii))->siblingOrderChanged();
2912}
2913
2914/*!
2915 Moves the specified \a sibling item to the index after this item
2916 within the list of children. The order of children affects both the
2917 visual stacking order and tab focus navigation order.
2918
2919 Assuming the z values of both items are the same, this will cause \a
2920 sibling to be rendered below this item.
2921
2922 If both items have activeFocusOnTab set to \c true, this will also cause
2923 the tab focus order to change, with \a sibling receiving focus before this
2924 item.
2925
2926 The given \a sibling must be a sibling of this item; that is, they must
2927 have the same immediate \l parent.
2928
2929 \sa {Concepts - Visual Parent in Qt Quick}
2930*/
2931void QQuickItem::stackAfter(const QQuickItem *sibling)
2932{
2933 Q_D(QQuickItem);
2934 if (!sibling || sibling == this || !d->parentItem || d->parentItem != QQuickItemPrivate::get(item: sibling)->parentItem) {
2935 qWarning().nospace() << "QQuickItem::stackAfter: Cannot stack "
2936 << this << " after " << sibling << ", which must be a sibling";
2937 return;
2938 }
2939
2940 QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(item: d->parentItem);
2941
2942 int myIndex = parentPrivate->childItems.lastIndexOf(t: this);
2943 int siblingIndex = parentPrivate->childItems.lastIndexOf(t: const_cast<QQuickItem *>(sibling));
2944
2945 Q_ASSERT(myIndex != -1 && siblingIndex != -1);
2946
2947 if (myIndex == siblingIndex + 1)
2948 return;
2949
2950 parentPrivate->childItems.move(from: myIndex, to: myIndex > siblingIndex ? siblingIndex + 1 : siblingIndex);
2951
2952 parentPrivate->markSortedChildrenDirty(child: this);
2953 parentPrivate->dirty(QQuickItemPrivate::ChildrenStackingChanged);
2954
2955 for (int ii = qMin(a: myIndex, b: siblingIndex + 1); ii < parentPrivate->childItems.size(); ++ii)
2956 QQuickItemPrivate::get(item: parentPrivate->childItems.at(i: ii))->siblingOrderChanged();
2957}
2958
2959/*! \fn void QQuickItem::windowChanged(QQuickWindow *window)
2960 This signal is emitted when the item's \a window changes.
2961*/
2962
2963/*!
2964 Returns the window in which this item is rendered.
2965
2966 The item does not have a window until it has been assigned into a scene. The
2967 \l windowChanged() signal provides a notification both when the item is entered
2968 into a scene and when it is removed from a scene.
2969 */
2970QQuickWindow *QQuickItem::window() const
2971{
2972 Q_D(const QQuickItem);
2973 return d->window;
2974}
2975
2976static bool itemZOrder_sort(QQuickItem *lhs, QQuickItem *rhs)
2977{
2978 return lhs->z() < rhs->z();
2979}
2980
2981QList<QQuickItem *> QQuickItemPrivate::paintOrderChildItems() const
2982{
2983 if (sortedChildItems)
2984 return *sortedChildItems;
2985
2986 // If none of the items have set Z then the paint order list is the same as
2987 // the childItems list. This is by far the most common case.
2988 bool haveZ = false;
2989 for (int i = 0; i < childItems.size(); ++i) {
2990 if (QQuickItemPrivate::get(item: childItems.at(i))->z() != 0.) {
2991 haveZ = true;
2992 break;
2993 }
2994 }
2995 if (haveZ) {
2996 sortedChildItems = new QList<QQuickItem*>(childItems);
2997 std::stable_sort(first: sortedChildItems->begin(), last: sortedChildItems->end(), comp: itemZOrder_sort);
2998 return *sortedChildItems;
2999 }
3000
3001 sortedChildItems = const_cast<QList<QQuickItem*>*>(&childItems);
3002
3003 return childItems;
3004}
3005
3006void QQuickItemPrivate::addChild(QQuickItem *child)
3007{
3008 Q_Q(QQuickItem);
3009
3010 Q_ASSERT(!childItems.contains(child));
3011
3012 childItems.append(t: child);
3013
3014 QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(item: child);
3015
3016#if QT_CONFIG(cursor)
3017 // if the added child has a cursor and we do not currently have any children
3018 // with cursors, bubble the notification up
3019 if (childPrivate->subtreeCursorEnabled && !subtreeCursorEnabled)
3020 setHasCursorInChild(true);
3021#endif
3022
3023 if (childPrivate->subtreeHoverEnabled && !subtreeHoverEnabled)
3024 setHasHoverInChild(true);
3025
3026 childPrivate->recursiveRefFromEffectItem(refs: extra.value().recursiveEffectRefCount);
3027 markSortedChildrenDirty(child);
3028 dirty(QQuickItemPrivate::ChildrenChanged);
3029
3030 itemChange(QQuickItem::ItemChildAddedChange, child);
3031
3032 emit q->childrenChanged();
3033}
3034
3035void QQuickItemPrivate::removeChild(QQuickItem *child)
3036{
3037 Q_Q(QQuickItem);
3038
3039 Q_ASSERT(child);
3040 if (!inDestructor) {
3041 // if we are getting destroyed, then the destructor will clear the list
3042 Q_ASSERT(childItems.contains(child));
3043 childItems.removeOne(t: child);
3044 Q_ASSERT(!childItems.contains(child));
3045 }
3046
3047 QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(item: child);
3048
3049#if QT_CONFIG(cursor)
3050 // turn it off, if nothing else is using it
3051 if (childPrivate->subtreeCursorEnabled && subtreeCursorEnabled)
3052 setHasCursorInChild(false);
3053#endif
3054
3055 if (childPrivate->subtreeHoverEnabled && subtreeHoverEnabled)
3056 setHasHoverInChild(false);
3057
3058 childPrivate->recursiveRefFromEffectItem(refs: -extra.value().recursiveEffectRefCount);
3059 if (!inDestructor) {
3060 markSortedChildrenDirty(child);
3061 dirty(QQuickItemPrivate::ChildrenChanged);
3062 }
3063
3064 itemChange(QQuickItem::ItemChildRemovedChange, child);
3065
3066 if (!inDestructor)
3067 emit q->childrenChanged();
3068}
3069
3070void QQuickItemPrivate::refWindow(QQuickWindow *c)
3071{
3072 // An item needs a window if it is referenced by another item which has a window.
3073 // Typically the item is referenced by a parent, but can also be referenced by a
3074 // ShaderEffect or ShaderEffectSource. 'windowRefCount' counts how many items with
3075 // a window is referencing this item. When the reference count goes from zero to one,
3076 // or one to zero, the window of this item is updated and propagated to the children.
3077 // As long as the reference count stays above zero, the window is unchanged.
3078 // refWindow() increments the reference count.
3079 // derefWindow() decrements the reference count.
3080
3081 Q_Q(QQuickItem);
3082 Q_ASSERT((window != nullptr) == (windowRefCount > 0));
3083 Q_ASSERT(c);
3084 if (++windowRefCount > 1) {
3085 if (c != window)
3086 qWarning(msg: "QQuickItem: Cannot use same item on different windows at the same time.");
3087 return; // Window already set.
3088 }
3089
3090 Q_ASSERT(window == nullptr);
3091 window = c;
3092
3093 if (polishScheduled)
3094 QQuickWindowPrivate::get(c: window)->itemsToPolish.append(t: q);
3095
3096 if (!parentItem)
3097 QQuickWindowPrivate::get(c: window)->parentlessItems.insert(value: q);
3098
3099 for (int ii = 0; ii < childItems.size(); ++ii) {
3100 QQuickItem *child = childItems.at(i: ii);
3101 QQuickItemPrivate::get(item: child)->refWindow(c);
3102 }
3103
3104 dirty(Window);
3105
3106 if (extra.isAllocated() && extra->screenAttached)
3107 extra->screenAttached->windowChanged(c);
3108 itemChange(QQuickItem::ItemSceneChange, c);
3109}
3110
3111void QQuickItemPrivate::derefWindow()
3112{
3113 Q_Q(QQuickItem);
3114 Q_ASSERT((window != nullptr) == (windowRefCount > 0));
3115
3116 if (!window)
3117 return; // This can happen when destroying recursive shader effect sources.
3118
3119 if (--windowRefCount > 0)
3120 return; // There are still other references, so don't set window to null yet.
3121
3122 q->releaseResources();
3123 removeFromDirtyList();
3124 QQuickWindowPrivate *c = QQuickWindowPrivate::get(c: window);
3125 if (polishScheduled)
3126 c->itemsToPolish.removeOne(t: q);
3127#if QT_CONFIG(cursor)
3128 if (c->cursorItem == q) {
3129 c->cursorItem = nullptr;
3130 window->unsetCursor();
3131 }
3132#endif
3133 if (itemNodeInstance)
3134 c->cleanup(itemNodeInstance);
3135 if (!parentItem)
3136 c->parentlessItems.remove(value: q);
3137
3138 window = nullptr;
3139
3140 itemNodeInstance = nullptr;
3141
3142 if (extra.isAllocated()) {
3143 extra->opacityNode = nullptr;
3144 extra->clipNode = nullptr;
3145 extra->rootNode = nullptr;
3146 }
3147
3148 paintNode = nullptr;
3149
3150 for (int ii = 0; ii < childItems.size(); ++ii) {
3151 if (QQuickItem *child = childItems.at(i: ii))
3152 QQuickItemPrivate::get(item: child)->derefWindow();
3153 }
3154
3155 dirty(Window);
3156
3157 if (extra.isAllocated() && extra->screenAttached)
3158 extra->screenAttached->windowChanged(nullptr);
3159 itemChange(QQuickItem::ItemSceneChange, (QQuickWindow *)nullptr);
3160}
3161
3162
3163/*!
3164 Returns a transform that maps points from window space into item space.
3165*/
3166QTransform QQuickItemPrivate::windowToItemTransform() const
3167{
3168 // XXX todo - optimize
3169 return itemToWindowTransform().inverted();
3170}
3171
3172/*!
3173 Returns a transform that maps points from item space into window space.
3174*/
3175QTransform QQuickItemPrivate::itemToWindowTransform() const
3176{
3177 // item's parent must not be itself, otherwise calling itemToWindowTransform() on it is infinite recursion
3178 Q_ASSERT(!parentItem || QQuickItemPrivate::get(parentItem) != this);
3179 QTransform rv = parentItem ? QQuickItemPrivate::get(item: parentItem)->itemToWindowTransform() : QTransform();
3180 itemToParentTransform(&rv);
3181 return rv;
3182}
3183
3184/*!
3185 Modifies \a t with this item's local transform relative to its parent.
3186*/
3187void QQuickItemPrivate::itemToParentTransform(QTransform *t) const
3188{
3189 /* Read the current x and y values. As this is an internal method,
3190 we don't care about it being usable in bindings. Instead, we
3191 care about performance here, and thus we read the value with
3192 valueBypassingBindings. This avoids any checks whether we are
3193 in a binding (which sholdn't be too expensive, but can add up).
3194 */
3195
3196 qreal x = this->x.valueBypassingBindings();
3197 qreal y = this->y.valueBypassingBindings();
3198 if (x || y)
3199 t->translate(dx: x, dy: y);
3200
3201 if (!transforms.isEmpty()) {
3202 QMatrix4x4 m(*t);
3203 for (int ii = transforms.size() - 1; ii >= 0; --ii)
3204 transforms.at(i: ii)->applyTo(matrix: &m);
3205 *t = m.toTransform();
3206 }
3207
3208 if (scale() != 1. || rotation() != 0.) {
3209 QPointF tp = computeTransformOrigin();
3210 t->translate(dx: tp.x(), dy: tp.y());
3211 t->scale(sx: scale(), sy: scale());
3212 t->rotate(a: rotation());
3213 t->translate(dx: -tp.x(), dy: -tp.y());
3214 }
3215}
3216
3217/*!
3218 Returns true if construction of the QML component is complete; otherwise
3219 returns false.
3220
3221 It is often desirable to delay some processing until the component is
3222 completed.
3223
3224 \sa componentComplete()
3225*/
3226bool QQuickItem::isComponentComplete() const
3227{
3228 Q_D(const QQuickItem);
3229 return d->componentComplete;
3230}
3231
3232QQuickItemPrivate::QQuickItemPrivate()
3233 : _anchors(nullptr)
3234 , _stateGroup(nullptr)
3235 , flags(0)
3236 , widthValidFlag(false)
3237 , heightValidFlag(false)
3238 , componentComplete(true)
3239 , keepMouse(false)
3240 , keepTouch(false)
3241 , hoverEnabled(false)
3242 , smooth(true)
3243 , antialiasing(false)
3244 , focus(false)
3245 , activeFocus(false)
3246 , notifiedFocus(false)
3247 , notifiedActiveFocus(false)
3248 , filtersChildMouseEvents(false)
3249 , explicitVisible(true)
3250 , effectiveVisible(true)
3251 , explicitEnable(true)
3252 , effectiveEnable(true)
3253 , polishScheduled(false)
3254 , inheritedLayoutMirror(false)
3255 , effectiveLayoutMirror(false)
3256 , isMirrorImplicit(true)
3257 , inheritMirrorFromParent(false)
3258 , inheritMirrorFromItem(false)
3259 , isAccessible(false)
3260 , culled(false)
3261 , hasCursor(false)
3262 , subtreeCursorEnabled(false)
3263 , subtreeHoverEnabled(false)
3264 , activeFocusOnTab(false)
3265 , implicitAntialiasing(false)
3266 , antialiasingValid(false)
3267 , isTabFence(false)
3268 , replayingPressEvent(false)
3269 , touchEnabled(false)
3270 , hasCursorHandler(false)
3271 , maybeHasSubsceneDeliveryAgent(true)
3272 , subtreeTransformChangedEnabled(true)
3273 , inDestructor(false)
3274 , focusReason(Qt::OtherFocusReason)
3275 , focusPolicy(Qt::NoFocus)
3276 , dirtyAttributes(0)
3277 , nextDirtyItem(nullptr)
3278 , prevDirtyItem(nullptr)
3279 , window(nullptr)
3280 , windowRefCount(0)
3281 , parentItem(nullptr)
3282 , sortedChildItems(&childItems)
3283 , subFocusItem(nullptr)
3284 , x(0)
3285 , y(0)
3286 , width(0)
3287 , height(0)
3288 , implicitWidth(0)
3289 , implicitHeight(0)
3290 , baselineOffset(0)
3291 , itemNodeInstance(nullptr)
3292 , paintNode(nullptr)
3293 , szPolicy(QLayoutPolicy::Fixed, QLayoutPolicy::Fixed)
3294{
3295}
3296
3297QQuickItemPrivate::~QQuickItemPrivate()
3298{
3299 if (sortedChildItems != &childItems)
3300 delete sortedChildItems;
3301}
3302
3303void QQuickItemPrivate::init(QQuickItem *parent)
3304{
3305 Q_Q(QQuickItem);
3306
3307 isQuickItem = true;
3308
3309 baselineOffset = 0.0;
3310
3311 if (parent) {
3312 q->setParentItem(parent);
3313 QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(item: parent);
3314 setImplicitLayoutMirror(mirror: parentPrivate->inheritedLayoutMirror, inherit: parentPrivate->inheritMirrorFromParent);
3315 }
3316}
3317
3318QLayoutPolicy QQuickItemPrivate::sizePolicy() const
3319{
3320 return szPolicy;
3321}
3322
3323void QQuickItemPrivate::setSizePolicy(const QLayoutPolicy::Policy& horizontalPolicy, const QLayoutPolicy::Policy& verticalPolicy)
3324{
3325 szPolicy.setHorizontalPolicy(horizontalPolicy);
3326 szPolicy.setVerticalPolicy(verticalPolicy);
3327}
3328
3329void QQuickItemPrivate::data_append(QQmlListProperty<QObject> *prop, QObject *o)
3330{
3331 if (!o)
3332 return;
3333
3334 QQuickItem *that = static_cast<QQuickItem *>(prop->object);
3335
3336 if (QQuickItem *item = qmlobject_cast<QQuickItem *>(object: o)) {
3337 item->setParentItem(that);
3338 } else if (QQuickPointerHandler *pointerHandler = qmlobject_cast<QQuickPointerHandler *>(object: o)) {
3339 if (pointerHandler->parent() != that) {
3340 qCDebug(lcHandlerParent) << "reparenting handler" << pointerHandler << ":" << pointerHandler->parent() << "->" << that;
3341 pointerHandler->setParent(that);
3342 }
3343 QQuickItemPrivate::get(item: that)->addPointerHandler(h: pointerHandler);
3344 } else {
3345 o->setParent(that);
3346 resources_append(prop, o);
3347 }
3348}
3349
3350/*!
3351 \qmlproperty list<QtObject> QtQuick::Item::data
3352 \qmldefault
3353
3354 The data property allows you to freely mix visual children and resources
3355 in an item. If you assign a visual item to the data list it becomes
3356 a child and if you assign any other object type, it is added as a resource.
3357
3358 So you can write:
3359 \qml
3360 Item {
3361 Text {}
3362 Rectangle {}
3363 Timer {}
3364 }
3365 \endqml
3366
3367 instead of:
3368 \qml
3369 Item {
3370 children: [
3371 Text {},
3372 Rectangle {}
3373 ]
3374 resources: [
3375 Timer {}
3376 ]
3377 }
3378 \endqml
3379
3380 It should not generally be necessary to refer to the \c data property,
3381 as it is the default property for Item and thus all child items are
3382 automatically assigned to this property.
3383 */
3384
3385qsizetype QQuickItemPrivate::data_count(QQmlListProperty<QObject> *property)
3386{
3387 QQuickItem *item = static_cast<QQuickItem*>(property->object);
3388 QQuickItemPrivate *privateItem = QQuickItemPrivate::get(item);
3389 QQmlListProperty<QObject> resourcesProperty = privateItem->resources();
3390 QQmlListProperty<QQuickItem> childrenProperty = privateItem->children();
3391
3392 return resources_count(&resourcesProperty) + children_count(&childrenProperty);
3393}
3394
3395QObject *QQuickItemPrivate::data_at(QQmlListProperty<QObject> *property, qsizetype i)
3396{
3397 QQuickItem *item = static_cast<QQuickItem*>(property->object);
3398 QQuickItemPrivate *privateItem = QQuickItemPrivate::get(item);
3399 QQmlListProperty<QObject> resourcesProperty = privateItem->resources();
3400 QQmlListProperty<QQuickItem> childrenProperty = privateItem->children();
3401
3402 qsizetype resourcesCount = resources_count(&resourcesProperty);
3403 if (i < resourcesCount)
3404 return resources_at(&resourcesProperty, i);
3405 const qsizetype j = i - resourcesCount;
3406 if (j < children_count(&childrenProperty))
3407 return children_at(&childrenProperty, j);
3408 return nullptr;
3409}
3410
3411void QQuickItemPrivate::data_clear(QQmlListProperty<QObject> *property)
3412{
3413 QQuickItem *item = static_cast<QQuickItem*>(property->object);
3414 QQuickItemPrivate *privateItem = QQuickItemPrivate::get(item);
3415 QQmlListProperty<QObject> resourcesProperty = privateItem->resources();
3416 QQmlListProperty<QQuickItem> childrenProperty = privateItem->children();
3417
3418 resources_clear(&resourcesProperty);
3419 children_clear(&childrenProperty);
3420}
3421
3422void QQuickItemPrivate::data_removeLast(QQmlListProperty<QObject> *property)
3423{
3424 QQuickItem *item = static_cast<QQuickItem*>(property->object);
3425 QQuickItemPrivate *privateItem = QQuickItemPrivate::get(item);
3426
3427 QQmlListProperty<QQuickItem> childrenProperty = privateItem->children();
3428 if (children_count(&childrenProperty) > 0) {
3429 children_removeLast(&childrenProperty);
3430 return;
3431 }
3432
3433 QQmlListProperty<QObject> resourcesProperty = privateItem->resources();
3434 if (resources_count(&resourcesProperty) > 0)
3435 resources_removeLast(&resourcesProperty);
3436}
3437
3438QObject *QQuickItemPrivate::resources_at(QQmlListProperty<QObject> *prop, qsizetype index)
3439{
3440 QQuickItemPrivate *quickItemPrivate = QQuickItemPrivate::get(item: static_cast<QQuickItem *>(prop->object));
3441 return quickItemPrivate->extra.isAllocated() ? quickItemPrivate->extra->resourcesList.value(i: index) : 0;
3442}
3443
3444void QQuickItemPrivate::resources_append(QQmlListProperty<QObject> *prop, QObject *object)
3445{
3446 QQuickItem *quickItem = static_cast<QQuickItem *>(prop->object);
3447 QQuickItemPrivate *quickItemPrivate = QQuickItemPrivate::get(item: quickItem);
3448 if (!quickItemPrivate->extra.value().resourcesList.contains(t: object)) {
3449 quickItemPrivate->extra.value().resourcesList.append(t: object);
3450 qmlobject_connect(object, QObject, SIGNAL(destroyed(QObject*)),
3451 quickItem, QQuickItem, SLOT(_q_resourceObjectDeleted(QObject*)));
3452 }
3453}
3454
3455qsizetype QQuickItemPrivate::resources_count(QQmlListProperty<QObject> *prop)
3456{
3457 QQuickItemPrivate *quickItemPrivate = QQuickItemPrivate::get(item: static_cast<QQuickItem *>(prop->object));
3458 return quickItemPrivate->extra.isAllocated() ? quickItemPrivate->extra->resourcesList.size() : 0;
3459}
3460
3461void QQuickItemPrivate::resources_clear(QQmlListProperty<QObject> *prop)
3462{
3463 QQuickItem *quickItem = static_cast<QQuickItem *>(prop->object);
3464 QQuickItemPrivate *quickItemPrivate = QQuickItemPrivate::get(item: quickItem);
3465 if (quickItemPrivate->extra.isAllocated()) {//If extra is not allocated resources is empty.
3466 for (QObject *object : std::as_const(t&: quickItemPrivate->extra->resourcesList)) {
3467 qmlobject_disconnect(object, QObject, SIGNAL(destroyed(QObject*)),
3468 quickItem, QQuickItem, SLOT(_q_resourceObjectDeleted(QObject*)));
3469 }
3470 quickItemPrivate->extra->resourcesList.clear();
3471 }
3472}
3473
3474void QQuickItemPrivate::resources_removeLast(QQmlListProperty<QObject> *prop)
3475{
3476 QQuickItem *quickItem = static_cast<QQuickItem *>(prop->object);
3477 QQuickItemPrivate *quickItemPrivate = QQuickItemPrivate::get(item: quickItem);
3478 if (quickItemPrivate->extra.isAllocated()) {//If extra is not allocated resources is empty.
3479 QList<QObject *> *resources = &quickItemPrivate->extra->resourcesList;
3480 if (resources->isEmpty())
3481 return;
3482
3483 qmlobject_disconnect(resources->last(), QObject, SIGNAL(destroyed(QObject*)),
3484 quickItem, QQuickItem, SLOT(_q_resourceObjectDeleted(QObject*)));
3485 resources->removeLast();
3486 }
3487}
3488
3489QQuickItem *QQuickItemPrivate::children_at(QQmlListProperty<QQuickItem> *prop, qsizetype index)
3490{
3491 QQuickItemPrivate *p = QQuickItemPrivate::get(item: static_cast<QQuickItem *>(prop->object));
3492 if (index >= p->childItems.size() || index < 0)
3493 return nullptr;
3494 else
3495 return p->childItems.at(i: index);
3496}
3497
3498void QQuickItemPrivate::children_append(QQmlListProperty<QQuickItem> *prop, QQuickItem *o)
3499{
3500 if (!o)
3501 return;
3502
3503 QQuickItem *that = static_cast<QQuickItem *>(prop->object);
3504 if (o->parentItem() == that)
3505 o->setParentItem(nullptr);
3506
3507 o->setParentItem(that);
3508}
3509
3510qsizetype QQuickItemPrivate::children_count(QQmlListProperty<QQuickItem> *prop)
3511{
3512 QQuickItemPrivate *p = QQuickItemPrivate::get(item: static_cast<QQuickItem *>(prop->object));
3513 return p->childItems.size();
3514}
3515
3516void QQuickItemPrivate::children_clear(QQmlListProperty<QQuickItem> *prop)
3517{
3518 QQuickItem *that = static_cast<QQuickItem *>(prop->object);
3519 QQuickItemPrivate *p = QQuickItemPrivate::get(item: that);
3520 while (!p->childItems.isEmpty())
3521 p->childItems.at(i: 0)->setParentItem(nullptr);
3522}
3523
3524void QQuickItemPrivate::children_removeLast(QQmlListProperty<QQuickItem> *prop)
3525{
3526 QQuickItem *that = static_cast<QQuickItem *>(prop->object);
3527 QQuickItemPrivate *p = QQuickItemPrivate::get(item: that);
3528 if (!p->childItems.isEmpty())
3529 p->childItems.last()->setParentItem(nullptr);
3530}
3531
3532qsizetype QQuickItemPrivate::visibleChildren_count(QQmlListProperty<QQuickItem> *prop)
3533{
3534 QQuickItemPrivate *p = QQuickItemPrivate::get(item: static_cast<QQuickItem *>(prop->object));
3535 qsizetype visibleCount = 0;
3536 qsizetype c = p->childItems.size();
3537 while (c--) {
3538 if (p->childItems.at(i: c)->isVisible()) visibleCount++;
3539 }
3540
3541 return visibleCount;
3542}
3543
3544QQuickItem *QQuickItemPrivate::visibleChildren_at(QQmlListProperty<QQuickItem> *prop, qsizetype index)
3545{
3546 QQuickItemPrivate *p = QQuickItemPrivate::get(item: static_cast<QQuickItem *>(prop->object));
3547 const qsizetype childCount = p->childItems.size();
3548 if (index >= childCount || index < 0)
3549 return nullptr;
3550
3551 qsizetype visibleCount = -1;
3552 for (qsizetype i = 0; i < childCount; i++) {
3553 if (p->childItems.at(i)->isVisible()) visibleCount++;
3554 if (visibleCount == index) return p->childItems.at(i);
3555 }
3556 return nullptr;
3557}
3558
3559qsizetype QQuickItemPrivate::transform_count(QQmlListProperty<QQuickTransform> *prop)
3560{
3561 QQuickItem *that = static_cast<QQuickItem *>(prop->object);
3562 QQuickItemPrivate *p = QQuickItemPrivate::get(item: that);
3563
3564 return p->transforms.size();
3565}
3566
3567void QQuickTransform::appendToItem(QQuickItem *item)
3568{
3569 Q_D(QQuickTransform);
3570 if (!item)
3571 return;
3572
3573 QQuickItemPrivate *p = QQuickItemPrivate::get(item);
3574
3575 if (!d->items.isEmpty() && !p->transforms.isEmpty() && p->transforms.contains(t: this)) {
3576 p->transforms.removeOne(t: this);
3577 p->transforms.append(t: this);
3578 } else {
3579 p->transforms.append(t: this);
3580 d->items.append(t: item);
3581 }
3582
3583 p->dirty(QQuickItemPrivate::Transform);
3584}
3585
3586void QQuickTransform::prependToItem(QQuickItem *item)
3587{
3588 Q_D(QQuickTransform);
3589 if (!item)
3590 return;
3591
3592 QQuickItemPrivate *p = QQuickItemPrivate::get(item);
3593
3594 if (!d->items.isEmpty() && !p->transforms.isEmpty() && p->transforms.contains(t: this)) {
3595 p->transforms.removeOne(t: this);
3596 p->transforms.prepend(t: this);
3597 } else {
3598 p->transforms.prepend(t: this);
3599 d->items.append(t: item);
3600 }
3601
3602 p->dirty(QQuickItemPrivate::Transform);
3603}
3604
3605void QQuickItemPrivate::transform_append(QQmlListProperty<QQuickTransform> *prop, QQuickTransform *transform)
3606{
3607 if (!transform)
3608 return;
3609
3610 QQuickItem *that = static_cast<QQuickItem *>(prop->object);
3611 transform->appendToItem(item: that);
3612}
3613
3614QQuickTransform *QQuickItemPrivate::transform_at(QQmlListProperty<QQuickTransform> *prop, qsizetype idx)
3615{
3616 QQuickItem *that = static_cast<QQuickItem *>(prop->object);
3617 QQuickItemPrivate *p = QQuickItemPrivate::get(item: that);
3618
3619 if (idx < 0 || idx >= p->transforms.size())
3620 return nullptr;
3621 else
3622 return p->transforms.at(i: idx);
3623}
3624
3625void QQuickItemPrivate::transform_clear(QQmlListProperty<QQuickTransform> *prop)
3626{
3627 QQuickItem *that = static_cast<QQuickItem *>(prop->object);
3628 QQuickItemPrivate *p = QQuickItemPrivate::get(item: that);
3629
3630 for (qsizetype ii = 0; ii < p->transforms.size(); ++ii) {
3631 QQuickTransform *t = p->transforms.at(i: ii);
3632 QQuickTransformPrivate *tp = QQuickTransformPrivate::get(transform: t);
3633 tp->items.removeOne(t: that);
3634 }
3635
3636 p->transforms.clear();
3637
3638 p->dirty(QQuickItemPrivate::Transform);
3639}
3640
3641void QQuickItemPrivate::_q_resourceObjectDeleted(QObject *object)
3642{
3643 if (extra.isAllocated() && extra->resourcesList.contains(t: object))
3644 extra->resourcesList.removeAll(t: object);
3645}
3646
3647/*!
3648 \qmlpropertygroup QtQuick::Item::anchors
3649 \qmlproperty AnchorLine QtQuick::Item::anchors.top
3650 \qmlproperty AnchorLine QtQuick::Item::anchors.bottom
3651 \qmlproperty AnchorLine QtQuick::Item::anchors.left
3652 \qmlproperty AnchorLine QtQuick::Item::anchors.right
3653 \qmlproperty AnchorLine QtQuick::Item::anchors.horizontalCenter
3654 \qmlproperty AnchorLine QtQuick::Item::anchors.verticalCenter
3655 \qmlproperty AnchorLine QtQuick::Item::anchors.baseline
3656
3657 \qmlproperty Item QtQuick::Item::anchors.fill
3658 \qmlproperty Item QtQuick::Item::anchors.centerIn
3659
3660 \qmlproperty real QtQuick::Item::anchors.margins
3661 \qmlproperty real QtQuick::Item::anchors.topMargin
3662 \qmlproperty real QtQuick::Item::anchors.bottomMargin
3663 \qmlproperty real QtQuick::Item::anchors.leftMargin
3664 \qmlproperty real QtQuick::Item::anchors.rightMargin
3665 \qmlproperty real QtQuick::Item::anchors.horizontalCenterOffset
3666 \qmlproperty real QtQuick::Item::anchors.verticalCenterOffset
3667 \qmlproperty real QtQuick::Item::anchors.baselineOffset
3668
3669 \qmlproperty bool QtQuick::Item::anchors.alignWhenCentered
3670
3671 Anchors provide a way to position an item by specifying its
3672 relationship with other items.
3673
3674 Margins apply to top, bottom, left, right, and fill anchors.
3675 The \l anchors.margins property can be used to set all of the various margins at once, to the same value.
3676 It will not override a specific margin that has been previously set; to clear an explicit margin
3677 set its value to \c undefined.
3678 Note that margins are anchor-specific and are not applied if an item does not
3679 use anchors.
3680
3681 Offsets apply for horizontal center, vertical center, and baseline anchors.
3682
3683 \table
3684 \row
3685 \li \image declarative-anchors_example.png
3686 \li Text anchored to Image, horizontally centered and vertically below, with a margin.
3687 \qml
3688 Item {
3689 Image {
3690 id: pic
3691 // ...
3692 }
3693 Text {
3694 id: label
3695 anchors.horizontalCenter: pic.horizontalCenter
3696 anchors.top: pic.bottom
3697 anchors.topMargin: 5
3698 // ...
3699 }
3700 }
3701 \endqml
3702 \row
3703 \li \image declarative-anchors_example2.png
3704 \li
3705 Left of Text anchored to right of Image, with a margin. The y
3706 property of both defaults to 0.
3707
3708 \qml
3709 Item {
3710 Image {
3711 id: pic
3712 // ...
3713 }
3714 Text {
3715 id: label
3716 anchors.left: pic.right
3717 anchors.leftMargin: 5
3718 // ...
3719 }
3720 }
3721 \endqml
3722 \endtable
3723
3724 \l anchors.fill provides a convenient way for one item to have the
3725 same geometry as another item, and is equivalent to connecting all
3726 four directional anchors.
3727
3728 To clear an anchor value, set it to \c undefined.
3729
3730 \l anchors.alignWhenCentered (default \c true) forces centered anchors to align to a
3731 whole pixel; if the item being centered has an odd \l width or \l height, the item
3732 will be positioned on a whole pixel rather than being placed on a half-pixel.
3733 This ensures the item is painted crisply. There are cases where this is not
3734 desirable, for example when rotating the item jitters may be apparent as the
3735 center is rounded.
3736
3737 \note You can only anchor an item to siblings or a parent.
3738
3739 For more information see \l {anchor-layout}{Anchor Layouts}.
3740*/
3741QQuickAnchors *QQuickItemPrivate::anchors() const
3742{
3743 if (!_anchors) {
3744 Q_Q(const QQuickItem);
3745 _anchors = new QQuickAnchors(const_cast<QQuickItem *>(q));
3746 if (!componentComplete)
3747 _anchors->classBegin();
3748 }
3749 return _anchors;
3750}
3751
3752void QQuickItemPrivate::siblingOrderChanged()
3753{
3754 Q_Q(QQuickItem);
3755 notifyChangeListeners(changeTypes: QQuickItemPrivate::SiblingOrder, function: &QQuickItemChangeListener::itemSiblingOrderChanged, args: q);
3756}
3757
3758QQmlListProperty<QObject> QQuickItemPrivate::data()
3759{
3760 // Do not synthesize replace().
3761 // It would be extremely expensive and wouldn't work with most methods.
3762 QQmlListProperty<QObject> result;
3763 result.object = q_func();
3764 result.append = QQuickItemPrivate::data_append;
3765 result.count = QQuickItemPrivate::data_count;
3766 result.at = QQuickItemPrivate::data_at;
3767 result.clear = QQuickItemPrivate::data_clear;
3768 result.removeLast = QQuickItemPrivate::data_removeLast;
3769 return result;
3770}
3771
3772/*!
3773 \qmlpropertygroup QtQuick::Item::childrenRect
3774 \qmlproperty real QtQuick::Item::childrenRect.x
3775 \qmlproperty real QtQuick::Item::childrenRect.y
3776 \qmlproperty real QtQuick::Item::childrenRect.width
3777 \qmlproperty real QtQuick::Item::childrenRect.height
3778 \readonly
3779
3780 This read-only property holds the collective position and size of the item's
3781 children.
3782
3783 This property is useful if you need to access the collective geometry
3784 of an item's children in order to correctly size the item.
3785
3786 The geometry that is returned is local to the item. For example:
3787
3788 \snippet qml/item/childrenRect.qml local
3789*/
3790/*!
3791 \property QQuickItem::childrenRect
3792
3793 This property holds the collective position and size of the item's
3794 children.
3795
3796 This property is useful if you need to access the collective geometry
3797 of an item's children in order to correctly size the item.
3798
3799 The geometry that is returned is local to the item. For example:
3800
3801 \snippet qml/item/childrenRect.qml local
3802*/
3803QRectF QQuickItem::childrenRect()
3804{
3805 Q_D(QQuickItem);
3806 if (!d->extra.isAllocated() || !d->extra->contents) {
3807 d->extra.value().contents = new QQuickContents(this);
3808 if (d->componentComplete)
3809 d->extra->contents->complete();
3810 }
3811 return d->extra->contents->rectF();
3812}
3813
3814/*!
3815 Returns the children of this item.
3816 */
3817QList<QQuickItem *> QQuickItem::childItems() const
3818{
3819 Q_D(const QQuickItem);
3820 return d->childItems;
3821}
3822
3823/*!
3824 \qmlproperty bool QtQuick::Item::clip
3825 This property holds whether clipping is enabled. The default clip value is \c false.
3826
3827 If clipping is enabled, an item will clip its own painting, as well
3828 as the painting of its children, to its bounding rectangle.
3829
3830 \note Clipping can affect rendering performance. See \l {Clipping} for more
3831 information.
3832*/
3833/*!
3834 \property QQuickItem::clip
3835 This property holds whether clipping is enabled. The default clip value is \c false.
3836
3837 If clipping is enabled, an item will clip its own painting, as well
3838 as the painting of its children, to its bounding rectangle. If you set
3839 clipping during an item's paint operation, remember to re-set it to
3840 prevent clipping the rest of your scene.
3841
3842 \note Clipping can affect rendering performance. See \l {Clipping} for more
3843 information.
3844
3845 \note For the sake of QML, setting clip to \c true also sets the
3846 \l ItemIsViewport flag, which sometimes acts as an optimization: child items
3847 that have the \l ItemObservesViewport flag may forego creating scene graph nodes
3848 that fall outside the viewport. But the \c ItemIsViewport flag can also be set
3849 independently.
3850*/
3851bool QQuickItem::clip() const
3852{
3853 return flags() & ItemClipsChildrenToShape;
3854}
3855
3856void QQuickItem::setClip(bool c)
3857{
3858 if (clip() == c)
3859 return;
3860
3861 setFlag(flag: ItemClipsChildrenToShape, enabled: c);
3862 if (c)
3863 setFlag(flag: ItemIsViewport);
3864 else if (!(inherits(classname: "QQuickFlickable") || inherits(classname: "QQuickRootItem")))
3865 setFlag(flag: ItemIsViewport, enabled: false);
3866
3867 emit clipChanged(c);
3868}
3869
3870/*!
3871 \since 6.0
3872
3873 This function is called to handle this item's changes in
3874 geometry from \a oldGeometry to \a newGeometry. If the two
3875 geometries are the same, it doesn't do anything.
3876
3877 Derived classes must call the base class method within their implementation.
3878 */
3879void QQuickItem::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
3880{
3881 Q_D(QQuickItem);
3882
3883 if (d->_anchors)
3884 QQuickAnchorsPrivate::get(o: d->_anchors)->updateMe();
3885
3886 QQuickGeometryChange change;
3887 change.setXChange(newGeometry.x() != oldGeometry.x());
3888 change.setYChange(newGeometry.y() != oldGeometry.y());
3889 change.setWidthChange(newGeometry.width() != oldGeometry.width());
3890 change.setHeightChange(newGeometry.height() != oldGeometry.height());
3891
3892 d->notifyChangeListeners(changeTypes: QQuickItemPrivate::Geometry, function: [&](const QQuickItemPrivate::ChangeListener &listener){
3893 if (change.matches(other: listener.gTypes))
3894 listener.listener->itemGeometryChanged(this, change, oldGeometry);
3895 });
3896
3897 // The notify method takes care of emitting the signal, and also notifies any
3898 // property observers.
3899 if (change.xChange())
3900 d->x.notify();
3901 if (change.yChange())
3902 d->y.notify();
3903 if (change.widthChange())
3904 d->width.notify();
3905 if (change.heightChange())
3906 d->height.notify();
3907#if QT_CONFIG(accessibility)
3908 if (d->isAccessible && QAccessible::isActive() && d->effectiveVisible) {
3909 QAccessibleEvent ev(this, QAccessible::LocationChanged);
3910 QAccessible::updateAccessibility(event: &ev);
3911 }
3912#endif
3913}
3914
3915/*!
3916 Called on the render thread when it is time to sync the state
3917 of the item with the scene graph.
3918
3919 The function is called as a result of QQuickItem::update(), if
3920 the user has set the QQuickItem::ItemHasContents flag on the item.
3921
3922 The function should return the root of the scene graph subtree for
3923 this item. Most implementations will return a single
3924 QSGGeometryNode containing the visual representation of this item.
3925 \a oldNode is the node that was returned the last time the
3926 function was called. \a updatePaintNodeData provides a pointer to
3927 the QSGTransformNode associated with this QQuickItem.
3928
3929 \code
3930 QSGNode *MyItem::updatePaintNode(QSGNode *node, UpdatePaintNodeData *)
3931 {
3932 QSGSimpleRectNode *n = static_cast<QSGSimpleRectNode *>(node);
3933 if (!n) {
3934 n = new QSGSimpleRectNode();
3935 n->setColor(Qt::red);
3936 }
3937 n->setRect(boundingRect());
3938 return n;
3939 }
3940 \endcode
3941
3942 The main thread is blocked while this function is executed so it is safe to read
3943 values from the QQuickItem instance and other objects in the main thread.
3944
3945 If no call to QQuickItem::updatePaintNode() result in actual scene graph
3946 changes, like QSGNode::markDirty() or adding and removing nodes, then
3947 the underlying implementation may decide to not render the scene again as
3948 the visual outcome is identical.
3949
3950 \warning It is crucial that graphics operations and interaction with
3951 the scene graph happens exclusively on the render thread,
3952 primarily during the QQuickItem::updatePaintNode() call. The best
3953 rule of thumb is to only use classes with the "QSG" prefix inside
3954 the QQuickItem::updatePaintNode() function.
3955
3956 \warning This function is called on the render thread. This means any
3957 QObjects or thread local storage that is created will have affinity to the
3958 render thread, so apply caution when doing anything other than rendering
3959 in this function. Similarly for signals, these will be emitted on the render
3960 thread and will thus often be delivered via queued connections.
3961
3962 \note All classes with QSG prefix should be used solely on the scene graph's
3963 rendering thread. See \l {Scene Graph and Rendering} for more information.
3964
3965 \sa QSGMaterial, QSGGeometryNode, QSGGeometry,
3966 QSGFlatColorMaterial, QSGTextureMaterial, QSGNode::markDirty(), {Graphics Resource Handling}
3967 */
3968
3969QSGNode *QQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData)
3970{
3971 Q_UNUSED(updatePaintNodeData);
3972 delete oldNode;
3973 return nullptr;
3974}
3975
3976QQuickItem::UpdatePaintNodeData::UpdatePaintNodeData()
3977: transformNode(nullptr)
3978{
3979}
3980
3981/*!
3982 This function is called when an item should release graphics
3983 resources which are not already managed by the nodes returned from
3984 QQuickItem::updatePaintNode().
3985
3986 This happens when the item is about to be removed from the window it
3987 was previously rendering to. The item is guaranteed to have a
3988 \l {QQuickItem::window()}{window} when the function is called.
3989
3990 The function is called on the GUI thread and the state of the
3991 rendering thread, when it is used, is unknown. Objects should
3992 not be deleted directly, but instead scheduled for cleanup
3993 using QQuickWindow::scheduleRenderJob().
3994
3995 \sa {Graphics Resource Handling}
3996 */
3997
3998void QQuickItem::releaseResources()
3999{
4000}
4001
4002QSGTransformNode *QQuickItemPrivate::createTransformNode()
4003{
4004 return new QSGTransformNode;
4005}
4006
4007/*!
4008 This function should perform any layout as required for this item.
4009
4010 When polish() is called, the scene graph schedules a polish event for this
4011 item. When the scene graph is ready to render this item, it calls
4012 updatePolish() to do any item layout as required before it renders the
4013 next frame.
4014
4015 \sa ensurePolished()
4016 */
4017void QQuickItem::updatePolish()
4018{
4019}
4020
4021#define PRINT_LISTENERS() \
4022do { \
4023 qDebug().nospace() << q_func() << " (" << this \
4024 << ") now has the following listeners:"; \
4025 for (const auto &listener : std::as_const(changeListeners)) { \
4026 const auto objectPrivate = dynamic_cast<QObjectPrivate*>(listener.listener); \
4027 qDebug().nospace() << "- " << listener << " (QObject: " << (objectPrivate ? objectPrivate->q_func() : nullptr) << ")"; \
4028 } \
4029} \
4030while (false)
4031
4032void QQuickItemPrivate::addItemChangeListener(QQuickItemChangeListener *listener, ChangeTypes types)
4033{
4034 changeListeners.append(t: ChangeListener(listener, types));
4035
4036 if (lcChangeListeners().isDebugEnabled())
4037 PRINT_LISTENERS();
4038}
4039
4040void QQuickItemPrivate::updateOrAddItemChangeListener(QQuickItemChangeListener *listener, ChangeTypes types)
4041{
4042 const ChangeListener changeListener(listener, types);
4043 const int index = changeListeners.indexOf(t: changeListener);
4044 if (index > -1)
4045 changeListeners[index].types = changeListener.types;
4046 else
4047 changeListeners.append(t: changeListener);
4048
4049 if (lcChangeListeners().isDebugEnabled())
4050 PRINT_LISTENERS();
4051}
4052
4053void QQuickItemPrivate::removeItemChangeListener(QQuickItemChangeListener *listener, ChangeTypes types)
4054{
4055 ChangeListener change(listener, types);
4056 changeListeners.removeOne(t: change);
4057
4058 if (lcChangeListeners().isDebugEnabled())
4059 PRINT_LISTENERS();
4060}
4061
4062void QQuickItemPrivate::updateOrAddGeometryChangeListener(QQuickItemChangeListener *listener,
4063 QQuickGeometryChange types)
4064{
4065 ChangeListener change(listener, types);
4066 int index = changeListeners.indexOf(t: change);
4067 if (index > -1)
4068 changeListeners[index].gTypes = change.gTypes; //we may have different GeometryChangeTypes
4069 else
4070 changeListeners.append(t: change);
4071
4072 if (lcChangeListeners().isDebugEnabled())
4073 PRINT_LISTENERS();
4074}
4075
4076void QQuickItemPrivate::updateOrRemoveGeometryChangeListener(QQuickItemChangeListener *listener,
4077 QQuickGeometryChange types)
4078{
4079 ChangeListener change(listener, types);
4080 if (types.noChange()) {
4081 changeListeners.removeOne(t: change);
4082 } else {
4083 int index = changeListeners.indexOf(t: change);
4084 if (index > -1)
4085 changeListeners[index].gTypes = change.gTypes; //we may have different GeometryChangeTypes
4086 }
4087
4088 if (lcChangeListeners().isDebugEnabled())
4089 PRINT_LISTENERS();
4090}
4091
4092/*!
4093 This event handler can be reimplemented in a subclass to receive key
4094 press events for an item. The event information is provided by the
4095 \a event parameter.
4096
4097 \input item.qdocinc accepting-events
4098 */
4099void QQuickItem::keyPressEvent(QKeyEvent *event)
4100{
4101 event->ignore();
4102}
4103
4104/*!
4105 This event handler can be reimplemented in a subclass to receive key
4106 release events for an item. The event information is provided by the
4107 \a event parameter.
4108
4109 \input item.qdocinc accepting-events
4110 */
4111void QQuickItem::keyReleaseEvent(QKeyEvent *event)
4112{
4113 event->ignore();
4114}
4115
4116#if QT_CONFIG(im)
4117/*!
4118 This event handler can be reimplemented in a subclass to receive input
4119 method events for an item. The event information is provided by the
4120 \a event parameter.
4121
4122 \input item.qdocinc accepting-events
4123 */
4124void QQuickItem::inputMethodEvent(QInputMethodEvent *event)
4125{
4126 event->ignore();
4127}
4128#endif // im
4129
4130/*!
4131 This event handler can be reimplemented in a subclass to receive focus-in
4132 events for an item. The event information is provided by the \a event
4133 parameter.
4134
4135 \input item.qdocinc accepting-events
4136
4137 If you do reimplement this function, you should call the base class
4138 implementation.
4139 */
4140void QQuickItem::focusInEvent(QFocusEvent *event)
4141{
4142 Q_D(QQuickItem);
4143#if QT_CONFIG(accessibility)
4144 if (QAccessible::isActive()) {
4145 if (QObject *acc = QQuickAccessibleAttached::findAccessible(object: this)) {
4146 QAccessibleEvent ev(acc, QAccessible::Focus);
4147 QAccessible::updateAccessibility(event: &ev);
4148 }
4149 }
4150#endif
4151 d->setLastFocusChangeReason(event->reason());
4152}
4153
4154/*!
4155 This event handler can be reimplemented in a subclass to receive focus-out
4156 events for an item. The event information is provided by the \a event
4157 parameter.
4158
4159 \input item.qdocinc accepting-events
4160 */
4161void QQuickItem::focusOutEvent(QFocusEvent *event)
4162{
4163 Q_D(QQuickItem);
4164 d->setLastFocusChangeReason(event->reason());
4165}
4166
4167/*!
4168 This event handler can be reimplemented in a subclass to receive mouse
4169 press events for an item. The event information is provided by the
4170 \a event parameter.
4171
4172 In order to receive mouse press events, \l acceptedMouseButtons() must
4173 return the relevant mouse button.
4174
4175 \input item.qdocinc accepting-events
4176 */
4177void QQuickItem::mousePressEvent(QMouseEvent *event)
4178{
4179 event->ignore();
4180}
4181
4182/*!
4183 This event handler can be reimplemented in a subclass to receive mouse
4184 move events for an item. The event information is provided by the
4185 \a event parameter.
4186
4187 In order to receive mouse movement events, the preceding mouse press event
4188 must be accepted (by overriding \l mousePressEvent(), for example) and
4189 \l acceptedMouseButtons() must return the relevant mouse button.
4190
4191 \input item.qdocinc accepting-events
4192 */
4193void QQuickItem::mouseMoveEvent(QMouseEvent *event)
4194{
4195 event->ignore();
4196}
4197
4198/*!
4199 This event handler can be reimplemented in a subclass to receive mouse
4200 release events for an item. The event information is provided by the
4201 \a event parameter.
4202
4203 In order to receive mouse release events, the preceding mouse press event
4204 must be accepted (by overriding \l mousePressEvent(), for example) and
4205 \l acceptedMouseButtons() must return the relevant mouse button.
4206
4207 \input item.qdocinc accepting-events
4208 */
4209void QQuickItem::mouseReleaseEvent(QMouseEvent *event)
4210{
4211 event->ignore();
4212}
4213
4214/*!
4215 This event handler can be reimplemented in a subclass to receive mouse
4216 double-click events for an item. The event information is provided by the
4217 \a event parameter.
4218
4219 \input item.qdocinc accepting-events
4220 */
4221void QQuickItem::mouseDoubleClickEvent(QMouseEvent *event)
4222{
4223 event->ignore();
4224}
4225
4226/*!
4227 This event handler can be reimplemented in a subclass to be notified
4228 when a mouse ungrab event has occurred on this item.
4229 */
4230void QQuickItem::mouseUngrabEvent()
4231{
4232 // XXX todo
4233}
4234
4235/*!
4236 This event handler can be reimplemented in a subclass to be notified
4237 when a touch ungrab event has occurred on this item.
4238 */
4239void QQuickItem::touchUngrabEvent()
4240{
4241 // XXX todo
4242}
4243
4244#if QT_CONFIG(wheelevent)
4245/*!
4246 This event handler can be reimplemented in a subclass to receive
4247 wheel events for an item. The event information is provided by the
4248 \a event parameter.
4249
4250 \input item.qdocinc accepting-events
4251 */
4252void QQuickItem::wheelEvent(QWheelEvent *event)
4253{
4254 event->ignore();
4255}
4256#endif
4257
4258/*!
4259 This event handler can be reimplemented in a subclass to receive touch
4260 events for an item. The event information is provided by the
4261 \a event parameter.
4262
4263 \input item.qdocinc accepting-events
4264 */
4265void QQuickItem::touchEvent(QTouchEvent *event)
4266{
4267 event->ignore();
4268}
4269
4270/*!
4271 This event handler can be reimplemented in a subclass to receive hover-enter
4272 events for an item. The event information is provided by the
4273 \a event parameter.
4274
4275 Hover events are only provided if acceptHoverEvents() is true.
4276
4277 \input item.qdocinc accepting-events
4278 */
4279void QQuickItem::hoverEnterEvent(QHoverEvent *event)
4280{
4281 event->ignore();
4282}
4283
4284/*!
4285 This event handler can be reimplemented in a subclass to receive hover-move
4286 events for an item. The event information is provided by the
4287 \a event parameter.
4288
4289 Hover events are only provided if acceptHoverEvents() is true.
4290
4291 \input item.qdocinc accepting-events
4292 */
4293void QQuickItem::hoverMoveEvent(QHoverEvent *event)
4294{
4295 event->ignore();
4296}
4297
4298/*!
4299 This event handler can be reimplemented in a subclass to receive hover-leave
4300 events for an item. The event information is provided by the
4301 \a event parameter.
4302
4303 Hover events are only provided if acceptHoverEvents() is true.
4304
4305 \input item.qdocinc accepting-events
4306 */
4307void QQuickItem::hoverLeaveEvent(QHoverEvent *event)
4308{
4309 event->ignore();
4310}
4311
4312#if QT_CONFIG(quick_draganddrop)
4313/*!
4314 This event handler can be reimplemented in a subclass to receive drag-enter
4315 events for an item. The event information is provided by the
4316 \a event parameter.
4317
4318 Drag and drop events are only provided if the ItemAcceptsDrops flag
4319 has been set for this item.
4320
4321 \input item.qdocinc accepting-events
4322
4323 \sa Drag, {Drag and Drop}
4324 */
4325void QQuickItem::dragEnterEvent(QDragEnterEvent *event)
4326{
4327 Q_UNUSED(event);
4328}
4329
4330/*!
4331 This event handler can be reimplemented in a subclass to receive drag-move
4332 events for an item. The event information is provided by the
4333 \a event parameter.
4334
4335 Drag and drop events are only provided if the ItemAcceptsDrops flag
4336 has been set for this item.
4337
4338 \input item.qdocinc accepting-events
4339
4340 \sa Drag, {Drag and Drop}
4341 */
4342void QQuickItem::dragMoveEvent(QDragMoveEvent *event)
4343{
4344 Q_UNUSED(event);
4345}
4346
4347/*!
4348 This event handler can be reimplemented in a subclass to receive drag-leave
4349 events for an item. The event information is provided by the
4350 \a event parameter.
4351
4352 Drag and drop events are only provided if the ItemAcceptsDrops flag
4353 has been set for this item.
4354
4355 \input item.qdocinc accepting-events
4356
4357 \sa Drag, {Drag and Drop}
4358 */
4359void QQuickItem::dragLeaveEvent(QDragLeaveEvent *event)
4360{
4361 Q_UNUSED(event);
4362}
4363
4364/*!
4365 This event handler can be reimplemented in a subclass to receive drop
4366 events for an item. The event information is provided by the
4367 \a event parameter.
4368
4369 Drag and drop events are only provided if the ItemAcceptsDrops flag
4370 has been set for this item.
4371
4372 \input item.qdocinc accepting-events
4373
4374 \sa Drag, {Drag and Drop}
4375 */
4376void QQuickItem::dropEvent(QDropEvent *event)
4377{
4378 Q_UNUSED(event);
4379}
4380#endif // quick_draganddrop
4381
4382/*!
4383 Reimplement this method to filter the pointer events that are received by
4384 this item's children.
4385
4386 This method will only be called if filtersChildMouseEvents() is \c true.
4387
4388 Return \c true if the specified \a event should not be passed on to the
4389 specified child \a item, and \c false otherwise. If you return \c true, you
4390 should also \l {QEvent::accept()}{accept} or \l {QEvent::ignore()}{ignore}
4391 the \a event, to signal if event propagation should stop or continue.
4392 The \a event will, however, always be sent to all childMouseEventFilters
4393 up the parent chain.
4394
4395 \note Despite the name, this function filters all QPointerEvent instances
4396 during delivery to all children (typically mouse, touch, and tablet
4397 events). When overriding this function in a subclass, we suggest writing
4398 generic event-handling code using only the accessors found in
4399 QPointerEvent. Alternatively you can switch on \c event->type() and/or
4400 \c event->device()->type() to handle different event types in different ways.
4401
4402 \note Filtering is just one way to share responsibility in case of gestural
4403 ambiguity (for example on press, you don't know whether the user will tap
4404 or drag). Another way is to call QPointerEvent::addPassiveGrabber() on
4405 press, so as to non-exclusively monitor the progress of the QEventPoint.
4406 In either case, the item or pointer handler that is monitoring can steal
4407 the exclusive grab later on, when it becomes clear that the gesture fits
4408 the pattern that it is expecting.
4409
4410 \sa setFiltersChildMouseEvents()
4411 */
4412bool QQuickItem::childMouseEventFilter(QQuickItem *item, QEvent *event)
4413{
4414 Q_UNUSED(item);
4415 Q_UNUSED(event);
4416 return false;
4417}
4418
4419#if QT_CONFIG(im)
4420/*!
4421 This method is only relevant for input items.
4422
4423 If this item is an input item, this method should be reimplemented to
4424 return the relevant input method flags for the given \a query.
4425
4426 \sa QWidget::inputMethodQuery()
4427 */
4428QVariant QQuickItem::inputMethodQuery(Qt::InputMethodQuery query) const
4429{
4430 Q_D(const QQuickItem);
4431 QVariant v;
4432
4433 switch (query) {
4434 case Qt::ImEnabled:
4435 v = (bool)(flags() & ItemAcceptsInputMethod);
4436 break;
4437 case Qt::ImHints:
4438 case Qt::ImAnchorRectangle:
4439 case Qt::ImCursorRectangle:
4440 case Qt::ImFont:
4441 case Qt::ImCursorPosition:
4442 case Qt::ImSurroundingText:
4443 case Qt::ImCurrentSelection:
4444 case Qt::ImMaximumTextLength:
4445 case Qt::ImAnchorPosition:
4446 case Qt::ImPreferredLanguage:
4447 case Qt::ImReadOnly:
4448 if (d->extra.isAllocated() && d->extra->keyHandler)
4449 v = d->extra->keyHandler->inputMethodQuery(query);
4450 break;
4451 case Qt::ImEnterKeyType:
4452 if (d->extra.isAllocated() && d->extra->enterKeyAttached)
4453 v = d->extra->enterKeyAttached->type();
4454 break;
4455 case Qt::ImInputItemClipRectangle:
4456 if (!(!window() ||!isVisible() || qFuzzyIsNull(d: opacity()))) {
4457 QRectF rect = QRectF(0,0, width(), height());
4458 const QQuickItem *par = this;
4459 while (QQuickItem *parpar = par->parentItem()) {
4460 rect = parpar->mapRectFromItem(item: par, rect);
4461 if (parpar->clip())
4462 rect = rect.intersected(r: parpar->clipRect());
4463 par = parpar;
4464 }
4465 rect = par->mapRectToScene(rect);
4466 // once we have the rect in scene coordinates, clip to window
4467 rect = rect.intersected(r: QRectF(QPoint(0,0), window()->size()));
4468 // map it back to local coordinates
4469 v = mapRectFromScene(rect);
4470 }
4471 break;
4472 default:
4473 break;
4474 }
4475
4476 return v;
4477}
4478#endif // im
4479
4480QQuickAnchorLine QQuickItemPrivate::left() const
4481{
4482 Q_Q(const QQuickItem);
4483 return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchors::LeftAnchor);
4484}
4485
4486QQuickAnchorLine QQuickItemPrivate::right() const
4487{
4488 Q_Q(const QQuickItem);
4489 return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchors::RightAnchor);
4490}
4491
4492QQuickAnchorLine QQuickItemPrivate::horizontalCenter() const
4493{
4494 Q_Q(const QQuickItem);
4495 return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchors::HCenterAnchor);
4496}
4497
4498QQuickAnchorLine QQuickItemPrivate::top() const
4499{
4500 Q_Q(const QQuickItem);
4501 return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchors::TopAnchor);
4502}
4503
4504QQuickAnchorLine QQuickItemPrivate::bottom() const
4505{
4506 Q_Q(const QQuickItem);
4507 return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchors::BottomAnchor);
4508}
4509
4510QQuickAnchorLine QQuickItemPrivate::verticalCenter() const
4511{
4512 Q_Q(const QQuickItem);
4513 return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchors::VCenterAnchor);
4514}
4515
4516QQuickAnchorLine QQuickItemPrivate::baseline() const
4517{
4518 Q_Q(const QQuickItem);
4519 return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchors::BaselineAnchor);
4520}
4521
4522/*!
4523 \qmlproperty int QtQuick::Item::baselineOffset
4524
4525 Specifies the position of the item's baseline in local coordinates.
4526
4527 The baseline of a \l Text item is the imaginary line on which the text
4528 sits. Controls containing text usually set their baseline to the
4529 baseline of their text.
4530
4531 For non-text items, a default baseline offset of 0 is used.
4532*/
4533/*!
4534 \property QQuickItem::baselineOffset
4535
4536 Specifies the position of the item's baseline in local coordinates.
4537
4538 The baseline of a \l Text item is the imaginary line on which the text
4539 sits. Controls containing text usually set their baseline to the
4540 baseline of their text.
4541
4542 For non-text items, a default baseline offset of 0 is used.
4543*/
4544qreal QQuickItem::baselineOffset() const
4545{
4546 Q_D(const QQuickItem);
4547 return d->baselineOffset;
4548}
4549
4550void QQuickItem::setBaselineOffset(qreal offset)
4551{
4552 Q_D(QQuickItem);
4553 if (offset == d->baselineOffset)
4554 return;
4555
4556 d->baselineOffset = offset;
4557
4558 d->notifyChangeListeners(changeTypes: QQuickItemPrivate::Geometry, function: [](const QQuickItemPrivate::ChangeListener &change){
4559 QQuickAnchorsPrivate *anchor = change.listener->anchorPrivate();
4560 if (anchor)
4561 anchor->updateVerticalAnchors();
4562 });
4563
4564 if (d->_anchors && (d->_anchors->usedAnchors() & QQuickAnchors::BaselineAnchor))
4565 QQuickAnchorsPrivate::get(o: d->_anchors)->updateVerticalAnchors();
4566
4567 emit baselineOffsetChanged(offset);
4568}
4569
4570
4571/*!
4572 * Schedules a call to updatePaintNode() for this item.
4573 *
4574 * The call to QQuickItem::updatePaintNode() will always happen if the
4575 * item is showing in a QQuickWindow.
4576 *
4577 * Only items which specify QQuickItem::ItemHasContents are allowed
4578 * to call QQuickItem::update().
4579 */
4580void QQuickItem::update()
4581{
4582 Q_D(QQuickItem);
4583 if (!(flags() & ItemHasContents)) {
4584#ifndef QT_NO_DEBUG
4585 qWarning() << metaObject()->className() << ": Update called for a item without content";
4586#endif
4587 return;
4588 }
4589 d->dirty(QQuickItemPrivate::Content);
4590}
4591
4592/*!
4593 Schedules a polish event for this item.
4594
4595 When the scene graph processes the request, it will call updatePolish()
4596 on this item.
4597
4598 \sa updatePolish(), QQuickTest::qIsPolishScheduled(), ensurePolished()
4599 */
4600void QQuickItem::polish()
4601{
4602 Q_D(QQuickItem);
4603 if (!d->polishScheduled) {
4604 d->polishScheduled = true;
4605 if (d->window) {
4606 QQuickWindowPrivate *p = QQuickWindowPrivate::get(c: d->window);
4607 bool maybeupdate = p->itemsToPolish.isEmpty();
4608 p->itemsToPolish.append(t: this);
4609 if (maybeupdate) d->window->maybeUpdate();
4610 }
4611 }
4612}
4613
4614/*!
4615 \since 6.3
4616
4617 Calls updatePolish()
4618
4619 This can be useful for items such as Layouts (or Positioners) which delay calculation of
4620 their implicitWidth and implicitHeight until they receive a PolishEvent.
4621
4622 Normally, if e.g. a child item is added or removed to a Layout, the implicit size is not
4623 immediately calculated (this is an optimization). In some cases it might be desirable to
4624 query the implicit size of the layout right after a child item has been added.
4625 If this is the case, use this function right before querying the implicit size.
4626
4627 \sa updatePolish(), polish()
4628 */
4629void QQuickItem::ensurePolished()
4630{
4631 updatePolish();
4632}
4633
4634#if QT_DEPRECATED_SINCE(6, 5)
4635static bool unwrapMapFromToFromItemArgs(QQmlV4FunctionPtr args, const QQuickItem *itemForWarning, const QString &functionNameForWarning,
4636 QQuickItem **itemObj, qreal *x, qreal *y, qreal *w, qreal *h, bool *isRect)
4637{
4638 QV4::ExecutionEngine *v4 = args->v4engine();
4639 if (args->length() != 2 && args->length() != 3 && args->length() != 5) {
4640 v4->throwTypeError();
4641 return false;
4642 }
4643
4644 QV4::Scope scope(v4);
4645 QV4::ScopedValue item(scope, (*args)[0]);
4646
4647 *itemObj = nullptr;
4648 if (!item->isNull()) {
4649 QV4::Scoped<QV4::QObjectWrapper> qobjectWrapper(scope, item->as<QV4::QObjectWrapper>());
4650 if (qobjectWrapper)
4651 *itemObj = qobject_cast<QQuickItem*>(o: qobjectWrapper->object());
4652 }
4653
4654 if (!(*itemObj) && !item->isNull()) {
4655 qmlWarning(me: itemForWarning) << functionNameForWarning << " given argument \"" << item->toQStringNoThrow()
4656 << "\" which is neither null nor an Item";
4657 v4->throwTypeError();
4658 return false;
4659 }
4660
4661 *isRect = false;
4662
4663 if (args->length() == 2) {
4664 QV4::ScopedValue sv(scope, (*args)[1]);
4665 if (sv->isNull()) {
4666 qmlWarning(me: itemForWarning) << functionNameForWarning << "given argument \"" << sv->toQStringNoThrow()
4667 << "\" which is neither a point nor a rect";
4668 v4->throwTypeError();
4669 return false;
4670 }
4671 const QV4::Scoped<QV4::QQmlValueTypeWrapper> variantWrapper(scope, sv->as<QV4::QQmlValueTypeWrapper>());
4672 const QVariant v = variantWrapper ? variantWrapper->toVariant() : QVariant();
4673 if (v.canConvert<QPointF>()) {
4674 const QPointF p = v.toPointF();
4675 *x = p.x();
4676 *y = p.y();
4677 } else if (v.canConvert<QRectF>()) {
4678 const QRectF r = v.toRectF();
4679 *x = r.x();
4680 *y = r.y();
4681 *w = r.width();
4682 *h = r.height();
4683 *isRect = true;
4684 } else {
4685 qmlWarning(me: itemForWarning) << functionNameForWarning << "given argument \"" << sv->toQStringNoThrow()
4686 << "\" which is neither a point nor a rect";
4687 v4->throwTypeError();
4688 return false;
4689 }
4690 } else {
4691 QV4::ScopedValue vx(scope, (*args)[1]);
4692 QV4::ScopedValue vy(scope, (*args)[2]);
4693
4694 if (!vx->isNumber() || !vy->isNumber()) {
4695 v4->throwTypeError();
4696 return false;
4697 }
4698
4699 *x = vx->asDouble();
4700 *y = vy->asDouble();
4701
4702 if (args->length() > 3) {
4703 QV4::ScopedValue vw(scope, (*args)[3]);
4704 QV4::ScopedValue vh(scope, (*args)[4]);
4705 if (!vw->isNumber() || !vh->isNumber()) {
4706 v4->throwTypeError();
4707 return false;
4708 }
4709 *w = vw->asDouble();
4710 *h = vh->asDouble();
4711 *isRect = true;
4712 }
4713 }
4714
4715 return true;
4716}
4717#endif
4718
4719/*!
4720 \qmlmethod point QtQuick::Item::mapFromItem(Item item, real x, real y)
4721 \qmlmethod point QtQuick::Item::mapFromItem(Item item, point p)
4722 \qmlmethod rect QtQuick::Item::mapFromItem(Item item, real x, real y, real width, real height)
4723 \qmlmethod rect QtQuick::Item::mapFromItem(Item item, rect r)
4724
4725 Maps the point (\a x, \a y) or rect (\a x, \a y, \a width, \a height), which is in \a
4726 item's coordinate system, to this item's coordinate system, and returns a \l point or \l rect
4727 matching the mapped coordinate.
4728
4729 \input item.qdocinc mapping
4730
4731 If \a item is a \c null value, this maps the point or rect from the coordinate system of
4732 the \l{Scene Coordinates}{scene}.
4733
4734 The versions accepting point and rect are since Qt 5.15.
4735*/
4736
4737#if QT_DEPRECATED_SINCE(6, 5)
4738/*!
4739 \internal
4740 */
4741void QQuickItem::mapFromItem(QQmlV4FunctionPtr args) const
4742{
4743 QV4::ExecutionEngine *v4 = args->v4engine();
4744 QV4::Scope scope(v4);
4745
4746 qreal x, y, w, h;
4747 bool isRect;
4748 QQuickItem *itemObj;
4749 if (!unwrapMapFromToFromItemArgs(args, itemForWarning: this, QStringLiteral("mapFromItem()"), itemObj: &itemObj, x: &x, y: &y, w: &w, h: &h, isRect: &isRect))
4750 return;
4751
4752 const QVariant result = isRect ? QVariant(mapRectFromItem(item: itemObj, rect: QRectF(x, y, w, h)))
4753 : QVariant(mapFromItem(item: itemObj, point: QPointF(x, y)));
4754
4755 QV4::ScopedObject rv(scope, v4->fromVariant(result));
4756 args->setReturnValue(rv.asReturnedValue());
4757}
4758#endif
4759
4760/*!
4761 \internal
4762 */
4763QTransform QQuickItem::itemTransform(QQuickItem *other, bool *ok) const
4764{
4765 Q_D(const QQuickItem);
4766
4767 // XXX todo - we need to be able to handle common parents better and detect
4768 // invalid cases
4769 if (ok) *ok = true;
4770
4771 QTransform t = d->itemToWindowTransform();
4772 if (other) t *= QQuickItemPrivate::get(item: other)->windowToItemTransform();
4773
4774 return t;
4775}
4776
4777/*!
4778 \qmlmethod point QtQuick::Item::mapToItem(Item item, real x, real y)
4779 \qmlmethod point QtQuick::Item::mapToItem(Item item, point p)
4780 \qmlmethod rect QtQuick::Item::mapToItem(Item item, real x, real y, real width, real height)
4781 \qmlmethod rect QtQuick::Item::mapToItem(Item item, rect r)
4782
4783 Maps the point (\a x, \a y) or rect (\a x, \a y, \a width, \a height), which is in this
4784 item's coordinate system, to \a item's coordinate system, and returns a \l point or \l rect
4785 matching the mapped coordinate.
4786
4787 \input item.qdocinc mapping
4788
4789 If \a item is a \c null value, this maps the point or rect to the coordinate system of the
4790 \l{Scene Coordinates}{scene}.
4791
4792 The versions accepting point and rect are since Qt 5.15.
4793*/
4794
4795#if QT_DEPRECATED_SINCE(6, 5)
4796/*!
4797 \internal
4798 */
4799void QQuickItem::mapToItem(QQmlV4FunctionPtr args) const
4800{
4801 QV4::ExecutionEngine *v4 = args->v4engine();
4802 QV4::Scope scope(v4);
4803
4804 qreal x, y, w, h;
4805 bool isRect;
4806 QQuickItem *itemObj;
4807 if (!unwrapMapFromToFromItemArgs(args, itemForWarning: this, QStringLiteral("mapToItem()"), itemObj: &itemObj, x: &x, y: &y, w: &w, h: &h, isRect: &isRect))
4808 return;
4809
4810 const QVariant result = isRect ? QVariant(mapRectToItem(item: itemObj, rect: QRectF(x, y, w, h)))
4811 : QVariant(mapToItem(item: itemObj, point: QPointF(x, y)));
4812
4813 QV4::ScopedObject rv(scope, v4->fromVariant(result));
4814 args->setReturnValue(rv.asReturnedValue());
4815}
4816
4817static bool unwrapMapFromToFromGlobalArgs(QQmlV4FunctionPtr args, const QQuickItem *itemForWarning, const QString &functionNameForWarning, qreal *x, qreal *y)
4818{
4819 QV4::ExecutionEngine *v4 = args->v4engine();
4820 if (args->length() != 1 && args->length() != 2) {
4821 v4->throwTypeError();
4822 return false;
4823 }
4824
4825 QV4::Scope scope(v4);
4826
4827 if (args->length() == 1) {
4828 QV4::ScopedValue sv(scope, (*args)[0]);
4829 if (sv->isNull()) {
4830 qmlWarning(me: itemForWarning) << functionNameForWarning << "given argument \"" << sv->toQStringNoThrow()
4831 << "\" which is not a point";
4832 v4->throwTypeError();
4833 return false;
4834 }
4835 const QV4::Scoped<QV4::QQmlValueTypeWrapper> variantWrapper(scope, sv->as<QV4::QQmlValueTypeWrapper>());
4836 const QVariant v = variantWrapper ? variantWrapper->toVariant() : QVariant();
4837 if (v.canConvert<QPointF>()) {
4838 const QPointF p = v.toPointF();
4839 *x = p.x();
4840 *y = p.y();
4841 } else {
4842 qmlWarning(me: itemForWarning) << functionNameForWarning << "given argument \"" << sv->toQStringNoThrow()
4843 << "\" which is not a point";
4844 v4->throwTypeError();
4845 return false;
4846 }
4847 } else {
4848 QV4::ScopedValue vx(scope, (*args)[0]);
4849 QV4::ScopedValue vy(scope, (*args)[1]);
4850
4851 if (!vx->isNumber() || !vy->isNumber()) {
4852 v4->throwTypeError();
4853 return false;
4854 }
4855
4856 *x = vx->asDouble();
4857 *y = vy->asDouble();
4858 }
4859
4860 return true;
4861}
4862
4863/*!
4864 \since 5.7
4865 \qmlmethod point QtQuick::Item::mapFromGlobal(real x, real y)
4866
4867 Maps the point (\a x, \a y), which is in the global coordinate system, to the
4868 item's coordinate system, and returns a \l point matching the mapped coordinate.
4869
4870 \input item.qdocinc mapping
4871*/
4872/*!
4873 \internal
4874 */
4875void QQuickItem::mapFromGlobal(QQmlV4FunctionPtr args) const
4876{
4877 QV4::ExecutionEngine *v4 = args->v4engine();
4878 QV4::Scope scope(v4);
4879
4880 qreal x, y;
4881 if (!unwrapMapFromToFromGlobalArgs(args, itemForWarning: this, QStringLiteral("mapFromGlobal()"), x: &x, y: &y))
4882 return;
4883
4884 QVariant result = mapFromGlobal(point: QPointF(x, y));
4885
4886 QV4::ScopedObject rv(scope, v4->fromVariant(result));
4887 args->setReturnValue(rv.asReturnedValue());
4888}
4889#endif
4890
4891/*!
4892 \since 5.7
4893 \qmlmethod point QtQuick::Item::mapToGlobal(real x, real y)
4894
4895 Maps the point (\a x, \a y), which is in this item's coordinate system, to the
4896 global coordinate system, and returns a \l point matching the mapped coordinate.
4897
4898 \input item.qdocinc mapping
4899*/
4900
4901#if QT_DEPRECATED_SINCE(6, 5)
4902/*!
4903 \internal
4904 */
4905void QQuickItem::mapToGlobal(QQmlV4FunctionPtr args) const
4906{
4907 QV4::ExecutionEngine *v4 = args->v4engine();
4908 QV4::Scope scope(v4);
4909
4910 qreal x, y;
4911 if (!unwrapMapFromToFromGlobalArgs(args, itemForWarning: this, QStringLiteral("mapFromGlobal()"), x: &x, y: &y))
4912 return;
4913
4914 QVariant result = mapToGlobal(point: QPointF(x, y));
4915
4916 QV4::ScopedObject rv(scope, v4->fromVariant(result));
4917 args->setReturnValue(rv.asReturnedValue());
4918}
4919#endif
4920
4921/*!
4922 \qmlmethod QtQuick::Item::forceActiveFocus()
4923
4924 Forces active focus on the item.
4925
4926 This method sets focus on the item and ensures that all ancestor
4927 FocusScope objects in the object hierarchy are also given \l focus.
4928
4929 The reason for the focus change will be \l [CPP] Qt::OtherFocusReason. Use
4930 the overloaded method to specify the focus reason to enable better
4931 handling of the focus change.
4932
4933 \sa activeFocus
4934*/
4935/*!
4936 Forces active focus on the item.
4937
4938 This method sets focus on the item and ensures that all ancestor
4939 FocusScope objects in the object hierarchy are also given \l focus.
4940
4941 The reason for the focus change will be \l [CPP] Qt::OtherFocusReason. Use
4942 the overloaded method to specify the focus reason to enable better
4943 handling of the focus change.
4944
4945 \sa activeFocus
4946*/
4947void QQuickItem::forceActiveFocus()
4948{
4949 forceActiveFocus(reason: Qt::OtherFocusReason);
4950}
4951
4952/*!
4953 \qmlmethod QtQuick::Item::forceActiveFocus(Qt::FocusReason reason)
4954 \overload
4955
4956 Forces active focus on the item with the given \a reason.
4957
4958 This method sets focus on the item and ensures that all ancestor
4959 FocusScope objects in the object hierarchy are also given \l focus.
4960
4961 \since 5.1
4962
4963 \sa activeFocus, Qt::FocusReason
4964*/
4965/*!
4966 \overload
4967 Forces active focus on the item with the given \a reason.
4968
4969 This method sets focus on the item and ensures that all ancestor
4970 FocusScope objects in the object hierarchy are also given \l focus.
4971
4972 \since 5.1
4973
4974 \sa activeFocus, Qt::FocusReason
4975*/
4976
4977void QQuickItem::forceActiveFocus(Qt::FocusReason reason)
4978{
4979 setFocus(focus: true, reason);
4980 QQuickItem *parent = parentItem();
4981 QQuickItem *scope = nullptr;
4982 while (parent) {
4983 if (parent->flags() & QQuickItem::ItemIsFocusScope) {
4984 parent->setFocus(focus: true, reason);
4985 if (!scope)
4986 scope = parent;
4987 }
4988 parent = parent->parentItem();
4989 }
4990}
4991
4992/*!
4993 \qmlmethod QtQuick::Item::nextItemInFocusChain(bool forward)
4994
4995 \since 5.1
4996
4997 Returns the item in the focus chain which is next to this item.
4998 If \a forward is \c true, or not supplied, it is the next item in
4999 the forwards direction. If \a forward is \c false, it is the next
5000 item in the backwards direction.
5001*/
5002/*!
5003 Returns the item in the focus chain which is next to this item.
5004 If \a forward is \c true, or not supplied, it is the next item in
5005 the forwards direction. If \a forward is \c false, it is the next
5006 item in the backwards direction.
5007*/
5008
5009QQuickItem *QQuickItem::nextItemInFocusChain(bool forward)
5010{
5011 return QQuickItemPrivate::nextPrevItemInTabFocusChain(item: this, forward);
5012}
5013
5014/*!
5015 \qmlmethod QtQuick::Item::childAt(real x, real y)
5016
5017 Returns the first visible child item found at point (\a x, \a y) within
5018 the coordinate system of this item.
5019
5020 Returns \c null if there is no such item.
5021*/
5022/*!
5023 Returns the first visible child item found at point (\a x, \a y) within
5024 the coordinate system of this item.
5025
5026 Returns \nullptr if there is no such item.
5027*/
5028QQuickItem *QQuickItem::childAt(qreal x, qreal y) const
5029{
5030 const QList<QQuickItem *> children = childItems();
5031 for (int i = children.size()-1; i >= 0; --i) {
5032 QQuickItem *child = children.at(i);
5033 // Map coordinates to the child element's coordinate space
5034 QPointF point = mapToItem(item: child, point: QPointF(x, y));
5035 if (child->isVisible() && child->contains(point))
5036 return child;
5037 }
5038 return nullptr;
5039}
5040
5041/*!
5042 \qmlmethod QtQuick::Item::dumpItemTree()
5043
5044 Dumps some details about the
5045 \l {Concepts - Visual Parent in Qt Quick}{visual tree of Items} starting
5046 with this item and its children, recursively.
5047
5048 The output looks similar to that of this QML code:
5049
5050 \qml
5051 function dump(object, indent) {
5052 console.log(indent + object)
5053 for (const i in object.children)
5054 dump(object.children[i], indent + " ")
5055 }
5056
5057 dump(myItem, "")
5058 \endqml
5059
5060 So if you want more details, you can implement your own function and add
5061 extra output to the console.log, such as values of specific properties.
5062
5063 \sa QObject::dumpObjectTree()
5064 \since 6.3
5065*/
5066/*!
5067 Dumps some details about the
5068 \l {Concepts - Visual Parent in Qt Quick}{visual tree of Items} starting
5069 with this item, recursively.
5070
5071 \note QObject::dumpObjectTree() dumps a similar tree; but, as explained
5072 in \l {Concepts - Visual Parent in Qt Quick}, an item's QObject::parent()
5073 sometimes differs from its QQuickItem::parentItem(). You can dump
5074 both trees to see the difference.
5075
5076 \note The exact output format may change in future versions of Qt.
5077
5078 \since 6.3
5079 \sa {Debugging Techniques}
5080 \sa {https://doc.qt.io/GammaRay/gammaray-qtquick2-inspector.html}{GammaRay's Qt Quick Inspector}
5081*/
5082void QQuickItem::dumpItemTree() const
5083{
5084 Q_D(const QQuickItem);
5085 d->dumpItemTree(indent: 0);
5086}
5087
5088void QQuickItemPrivate::dumpItemTree(int indent) const
5089{
5090 Q_Q(const QQuickItem);
5091
5092 const auto indentStr = QString(indent * 4, QLatin1Char(' '));
5093 qDebug().nospace().noquote() << indentStr <<
5094#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
5095 const_cast<QQuickItem *>(q);
5096#else
5097 q;
5098#endif
5099 if (extra.isAllocated()) {
5100 for (const auto handler : extra->pointerHandlers)
5101 qDebug().nospace().noquote() << indentStr << u" \u26ee " << handler;
5102 }
5103 for (const QQuickItem *ch : childItems) {
5104 auto itemPriv = QQuickItemPrivate::get(item: ch);
5105 itemPriv->dumpItemTree(indent: indent + 1);
5106 }
5107}
5108
5109QQmlListProperty<QObject> QQuickItemPrivate::resources()
5110{
5111 // Do not synthesize replace().
5112 // It would be extremely expensive and wouldn't work with most methods.
5113 QQmlListProperty<QObject> result;
5114 result.object = q_func();
5115 result.append = QQuickItemPrivate::resources_append;
5116 result.count = QQuickItemPrivate::resources_count;
5117 result.at = QQuickItemPrivate::resources_at;
5118 result.clear = QQuickItemPrivate::resources_clear;
5119 result.removeLast = QQuickItemPrivate::resources_removeLast;
5120 return result;
5121}
5122
5123/*!
5124 \qmlproperty list<Item> QtQuick::Item::children
5125 \qmlproperty list<QtObject> QtQuick::Item::resources
5126
5127 The children property contains the list of visual children of this item.
5128 The resources property contains non-visual resources that you want to
5129 reference by name.
5130
5131 It is not generally necessary to refer to these properties when adding
5132 child items or resources, as the default \l data property will
5133 automatically assign child objects to the \c children and \c resources
5134 properties as appropriate. See the \l data documentation for details.
5135*/
5136/*!
5137 \property QQuickItem::children
5138 \internal
5139*/
5140QQmlListProperty<QQuickItem> QQuickItemPrivate::children()
5141{
5142 // Do not synthesize replace().
5143 // It would be extremely expensive and wouldn't work with most methods.
5144 QQmlListProperty<QQuickItem> result;
5145 result.object = q_func();
5146 result.append = QQuickItemPrivate::children_append;
5147 result.count = QQuickItemPrivate::children_count;
5148 result.at = QQuickItemPrivate::children_at;
5149 result.clear = QQuickItemPrivate::children_clear;
5150 result.removeLast = QQuickItemPrivate::children_removeLast;
5151 return result;
5152}
5153
5154/*!
5155 \qmlproperty list<Item> QtQuick::Item::visibleChildren
5156 This read-only property lists all of the item's children that are currently visible.
5157 Note that a child's visibility may have changed explicitly, or because the visibility
5158 of this (it's parent) item or another grandparent changed.
5159*/
5160/*!
5161 \property QQuickItem::visibleChildren
5162 \internal
5163*/
5164QQmlListProperty<QQuickItem> QQuickItemPrivate::visibleChildren()
5165{
5166 return QQmlListProperty<QQuickItem>(q_func(),
5167 nullptr,
5168 QQuickItemPrivate::visibleChildren_count,
5169 QQuickItemPrivate::visibleChildren_at);
5170
5171}
5172
5173/*!
5174 \qmlproperty list<State> QtQuick::Item::states
5175
5176 This property holds the list of possible states for this item. To change
5177 the state of this item, set the \l state property to one of these states,
5178 or set the \l state property to an empty string to revert the item to its
5179 default state.
5180
5181 This property is specified as a list of \l State objects. For example,
5182 below is an item with "red_color" and "blue_color" states:
5183
5184 \qml
5185 import QtQuick 2.0
5186
5187 Rectangle {
5188 id: root
5189 width: 100; height: 100
5190
5191 states: [
5192 State {
5193 name: "red_color"
5194 PropertyChanges { root.color: "red" }
5195 },
5196 State {
5197 name: "blue_color"
5198 PropertyChanges { root.color: "blue" }
5199 }
5200 ]
5201 }
5202 \endqml
5203
5204 See \l{Qt Quick States} and \l{Animation and Transitions in Qt Quick} for
5205 more details on using states and transitions.
5206
5207 \sa transitions
5208*/
5209/*!
5210 \property QQuickItem::states
5211 \internal
5212 */
5213QQmlListProperty<QQuickState> QQuickItemPrivate::states()
5214{
5215 return _states()->statesProperty();
5216}
5217
5218/*!
5219 \qmlproperty list<Transition> QtQuick::Item::transitions
5220
5221 This property holds the list of transitions for this item. These define the
5222 transitions to be applied to the item whenever it changes its \l state.
5223
5224 This property is specified as a list of \l Transition objects. For example:
5225
5226 \qml
5227 import QtQuick 2.0
5228
5229 Item {
5230 transitions: [
5231 Transition {
5232 //...
5233 },
5234 Transition {
5235 //...
5236 }
5237 ]
5238 }
5239 \endqml
5240
5241 See \l{Qt Quick States} and \l{Animation and Transitions in Qt Quick} for
5242 more details on using states and transitions.
5243
5244 \sa states
5245*/
5246/*!
5247 \property QQuickItem::transitions
5248 \internal
5249 */
5250QQmlListProperty<QQuickTransition> QQuickItemPrivate::transitions()
5251{
5252 return _states()->transitionsProperty();
5253}
5254
5255QString QQuickItemPrivate::state() const
5256{
5257 if (!_stateGroup)
5258 return QString();
5259 else
5260 return _stateGroup->state();
5261}
5262
5263void QQuickItemPrivate::setState(const QString &state)
5264{
5265 _states()->setState(state);
5266}
5267
5268/*!
5269 \qmlproperty string QtQuick::Item::state
5270
5271 This property holds the name of the current state of the item.
5272
5273 If the item is in its default state, that is, no explicit state has been
5274 set, then this property holds an empty string. Likewise, you can return
5275 an item to its default state by setting this property to an empty string.
5276
5277 \sa {Qt Quick States}
5278*/
5279/*!
5280 \property QQuickItem::state
5281
5282 This property holds the name of the current state of the item.
5283
5284 If the item is in its default state, that is, no explicit state has been
5285 set, then this property holds an empty string. Likewise, you can return
5286 an item to its default state by setting this property to an empty string.
5287
5288 \sa {Qt Quick States}
5289*/
5290QString QQuickItem::state() const
5291{
5292 Q_D(const QQuickItem);
5293 return d->state();
5294}
5295
5296void QQuickItem::setState(const QString &state)
5297{
5298 Q_D(QQuickItem);
5299 d->setState(state);
5300}
5301
5302/*!
5303 \qmlproperty list<Transform> QtQuick::Item::transform
5304 This property holds the list of transformations to apply.
5305
5306 For more information see \l Transform.
5307*/
5308/*!
5309 \property QQuickItem::transform
5310 \internal
5311 */
5312/*!
5313 \internal
5314 */
5315QQmlListProperty<QQuickTransform> QQuickItem::transform()
5316{
5317 return QQmlListProperty<QQuickTransform>(this, nullptr, QQuickItemPrivate::transform_append,
5318 QQuickItemPrivate::transform_count,
5319 QQuickItemPrivate::transform_at,
5320 QQuickItemPrivate::transform_clear);
5321}
5322
5323/*!
5324 \reimp
5325 Derived classes should call the base class method before adding their own action to
5326 perform at classBegin.
5327*/
5328void QQuickItem::classBegin()
5329{
5330 Q_D(QQuickItem);
5331 d->componentComplete = false;
5332 if (d->_stateGroup)
5333 d->_stateGroup->classBegin();
5334 if (d->_anchors)
5335 d->_anchors->classBegin();
5336#if QT_CONFIG(quick_shadereffect)
5337 if (d->extra.isAllocated() && d->extra->layer)
5338 d->extra->layer->classBegin();
5339#endif
5340}
5341
5342/*!
5343 \reimp
5344 Derived classes should call the base class method before adding their own actions to
5345 perform at componentComplete.
5346*/
5347void QQuickItem::componentComplete()
5348{
5349 Q_D(QQuickItem);
5350 d->componentComplete = true;
5351 if (d->_stateGroup)
5352 d->_stateGroup->componentComplete();
5353 if (d->_anchors) {
5354 d->_anchors->componentComplete();
5355 QQuickAnchorsPrivate::get(o: d->_anchors)->updateOnComplete();
5356 }
5357
5358 if (d->extra.isAllocated()) {
5359#if QT_CONFIG(quick_shadereffect)
5360 if (d->extra->layer)
5361 d->extra->layer->componentComplete();
5362#endif
5363
5364 if (d->extra->keyHandler)
5365 d->extra->keyHandler->componentComplete();
5366
5367 if (d->extra->contents)
5368 d->extra->contents->complete();
5369 }
5370
5371 if (d->window && d->dirtyAttributes) {
5372 d->addToDirtyList();
5373 QQuickWindowPrivate::get(c: d->window)->dirtyItem(this);
5374 }
5375
5376#if QT_CONFIG(accessibility)
5377 if (d->isAccessible && d->effectiveVisible) {
5378 QAccessibleEvent ev(this, QAccessible::ObjectShow);
5379 QAccessible::updateAccessibility(event: &ev);
5380 }
5381#endif
5382}
5383
5384QQuickStateGroup *QQuickItemPrivate::_states()
5385{
5386 Q_Q(QQuickItem);
5387 if (!_stateGroup) {
5388 _stateGroup = new QQuickStateGroup;
5389 if (!componentComplete)
5390 _stateGroup->classBegin();
5391 qmlobject_connect(_stateGroup, QQuickStateGroup, SIGNAL(stateChanged(QString)),
5392 q, QQuickItem, SIGNAL(stateChanged(QString)));
5393 }
5394
5395 return _stateGroup;
5396}
5397
5398QPointF QQuickItemPrivate::computeTransformOrigin() const
5399{
5400 switch (origin()) {
5401 default:
5402 case QQuickItem::TopLeft:
5403 return QPointF(0, 0);
5404 case QQuickItem::Top:
5405 return QPointF(width / 2., 0);
5406 case QQuickItem::TopRight:
5407 return QPointF(width, 0);
5408 case QQuickItem::Left:
5409 return QPointF(0, height / 2.);
5410 case QQuickItem::Center:
5411 return QPointF(width / 2., height / 2.);
5412 case QQuickItem::Right:
5413 return QPointF(width, height / 2.);
5414 case QQuickItem::BottomLeft:
5415 return QPointF(0, height);
5416 case QQuickItem::Bottom:
5417 return QPointF(width / 2., height);
5418 case QQuickItem::BottomRight:
5419 return QPointF(width, height);
5420 }
5421}
5422
5423/*!
5424 \internal
5425 QQuickItemPrivate::dirty() calls transformChanged(q) to inform this item and
5426 all its children that its transform has changed, with \a transformedItem always
5427 being the parent item that caused the change. Override to react, e.g. to
5428 call update() if the item needs to re-generate SG nodes based on visible extents.
5429 If you override in a subclass, you must also call this (superclass) function
5430 and return the value from it.
5431
5432 This function recursively visits all children as long as
5433 subtreeTransformChangedEnabled is true, returns \c true if any of those
5434 children still has the ItemObservesViewport flag set, but otherwise
5435 turns subtreeTransformChangedEnabled off, if no children are observing.
5436*/
5437bool QQuickItemPrivate::transformChanged(QQuickItem *transformedItem)
5438{
5439 Q_Q(QQuickItem);
5440
5441 bool childWantsIt = false;
5442 if (subtreeTransformChangedEnabled) {
5443 // Inform the children in paint order: by the time we visit leaf items,
5444 // they can see any consequences in their parents
5445 const auto children = paintOrderChildItems();
5446 for (QQuickItem *child : children)
5447 childWantsIt |= QQuickItemPrivate::get(item: child)->transformChanged(transformedItem);
5448 }
5449
5450#if QT_CONFIG(quick_shadereffect)
5451 if (q == transformedItem) {
5452 if (extra.isAllocated() && extra->layer)
5453 extra->layer->updateMatrix();
5454 }
5455#endif
5456 const bool thisWantsIt = q->flags().testFlag(flag: QQuickItem::ItemObservesViewport);
5457 const bool ret = childWantsIt || thisWantsIt;
5458 if (!ret && componentComplete && subtreeTransformChangedEnabled) {
5459 qCDebug(lcVP) << "turned off subtree transformChanged notification after checking all children of" << q;
5460 subtreeTransformChangedEnabled = false;
5461 }
5462 // If ItemObservesViewport, clipRect() calculates the intersection with the viewport;
5463 // so each time the item moves in the viewport, its clipnode needs to be updated.
5464 if (thisWantsIt && q->clip() && !(dirtyAttributes & QQuickItemPrivate::Clip))
5465 dirty(QQuickItemPrivate::Clip);
5466 return ret;
5467}
5468
5469/*! \internal
5470 Returns the new position (proposed values for the x and y properties)
5471 to which this item should be moved to compensate for the given change
5472 in scale from \a startScale to \a activeScale and in rotation from
5473 \a startRotation to \a activeRotation. \a centroidParentPos is the
5474 point that we wish to hold in place (and then apply \a activeTranslation to),
5475 in this item's parent's coordinate system. \a startPos is this item's
5476 position in its parent's coordinate system when the gesture began.
5477 \a activeTranslation is the amount of translation that should be added to
5478 the return value, i.e. the displacement by which the centroid is expected
5479 to move.
5480
5481 If \a activeTranslation is \c (0, 0) the centroid is to be held in place.
5482 If \a activeScale is \c 1, it means scale is intended to be held constant,
5483 the same as \a startScale. If \a activeRotation is \c 0, it means rotation
5484 is intended to be held constant, the same as \a startRotation.
5485*/
5486QPointF QQuickItemPrivate::adjustedPosForTransform(const QPointF &centroidParentPos,
5487 const QPointF &startPos,
5488 const QVector2D &activeTranslation,
5489 qreal startScale,
5490 qreal activeScale,
5491 qreal startRotation,
5492 qreal activeRotation)
5493{
5494 Q_Q(QQuickItem);
5495 QVector3D xformOrigin(q->transformOriginPoint());
5496 QMatrix4x4 startMatrix;
5497 startMatrix.translate(x: float(startPos.x()), y: float(startPos.y()));
5498 startMatrix.translate(vector: xformOrigin);
5499 startMatrix.scale(factor: float(startScale));
5500 startMatrix.rotate(angle: float(startRotation), x: 0, y: 0, z: -1);
5501 startMatrix.translate(vector: -xformOrigin);
5502
5503 const QVector3D centroidParentVector(centroidParentPos);
5504 QMatrix4x4 mat;
5505 mat.translate(vector: centroidParentVector);
5506 mat.rotate(angle: float(activeRotation), x: 0, y: 0, z: 1);
5507 mat.scale(factor: float(activeScale));
5508 mat.translate(vector: -centroidParentVector);
5509 mat.translate(vector: QVector3D(activeTranslation));
5510
5511 mat = mat * startMatrix;
5512
5513 QPointF xformOriginPoint = q->transformOriginPoint();
5514 QPointF pos = mat.map(point: xformOriginPoint);
5515 pos -= xformOriginPoint;
5516
5517 return pos;
5518}
5519
5520/*! \internal
5521 Returns the delivery agent for the narrowest subscene containing this item,
5522 but falls back to QQuickWindowPrivate::deliveryAgent if there are no subscenes.
5523
5524 If this item is not sure whether it's in a subscene (as by default), we need to
5525 explore the parents to find out.
5526
5527 If this item is in a subscene, we will find that DA during the exploration,
5528 and return it.
5529
5530 If we find the root item without finding a DA, then we know that this item
5531 does NOT belong to a subscene, so we remember that by setting
5532 maybeHasSubsceneDeliveryAgent to false, so that exploration of the parents
5533 can be avoided next time.
5534
5535 In the usual case in normal 2D scenes without subscenes,
5536 maybeHasSubsceneDeliveryAgent gets set to false here.
5537
5538 \note When a Qt Quick scene is shown in the usual way in its own window,
5539 subscenes are ignored, and QQuickWindowPrivate::deliveryAgent is used.
5540 Subscene delivery agents are used only in QtQuick 3D so far.
5541*/
5542QQuickDeliveryAgent *QQuickItemPrivate::deliveryAgent()
5543{
5544 Q_Q(QQuickItem);
5545 if (maybeHasSubsceneDeliveryAgent) {
5546 QQuickItemPrivate *p = this;
5547 do {
5548 if (qmlobject_cast<QQuickRootItem *>(object: p->q_ptr)) {
5549 // found the root item without finding a different DA:
5550 // it means we don't need to repeat this search next time.
5551 // TODO maybe optimize further: make this function recursive, and
5552 // set it to false on each item that we visit in the tail
5553 maybeHasSubsceneDeliveryAgent = false;
5554 break;
5555 }
5556 if (p->extra.isAllocated()) {
5557 if (auto da = p->extra->subsceneDeliveryAgent)
5558 return da;
5559 }
5560 p = p->parentItem ? QQuickItemPrivate::get(item: p->parentItem) : nullptr;
5561 } while (p);
5562 // arriving here is somewhat unexpected: a detached root can easily be created (just set an item's parent to null),
5563 // but why would we deliver events to that subtree? only if root got detached while an item in that subtree still has a grab?
5564 qCDebug(lcPtr) << "detached root of" << q << "is not a QQuickRootItem and also does not have its own DeliveryAgent";
5565 }
5566 if (window)
5567 return QQuickWindowPrivate::get(c: window)->deliveryAgent;
5568 return nullptr;
5569}
5570
5571QQuickDeliveryAgentPrivate *QQuickItemPrivate::deliveryAgentPrivate()
5572{
5573 auto da = deliveryAgent();
5574 return da ? static_cast<QQuickDeliveryAgentPrivate *>(QQuickDeliveryAgentPrivate::get(o: da)) : nullptr;
5575}
5576
5577/*! \internal
5578 Ensures that this item, presumably the root of a subscene (e.g. because it
5579 is mapped onto a 3D object in Qt Quick 3D), has a delivery agent to be used
5580 when delivering events to the subscene: i.e. when the viewport delivers an
5581 event to the subscene, or when the outer delivery agent delivers an update
5582 to an item that grabbed during a previous subscene delivery. Creates a new
5583 agent if it was not already created, and returns a pointer to the instance.
5584*/
5585QQuickDeliveryAgent *QQuickItemPrivate::ensureSubsceneDeliveryAgent()
5586{
5587 Q_Q(QQuickItem);
5588 // We are (about to be) sure that it has one now; but just to save space,
5589 // we avoid storing a DA pointer in each item; so deliveryAgent() always needs to
5590 // go up the hierarchy to find it. maybeHasSubsceneDeliveryAgent tells it to do that.
5591 maybeHasSubsceneDeliveryAgent = true;
5592 if (extra.isAllocated() && extra->subsceneDeliveryAgent)
5593 return extra->subsceneDeliveryAgent;
5594 extra.value().subsceneDeliveryAgent = new QQuickDeliveryAgent(q);
5595 qCDebug(lcPtr) << "created new" << extra->subsceneDeliveryAgent;
5596 // every subscene root needs to be a focus scope so that when QQuickItem::forceActiveFocus()
5597 // goes up the parent hierarchy, it finds the subscene root and calls setFocus() on it
5598 q->setFlag(flag: QQuickItem::ItemIsFocusScope);
5599 return extra->subsceneDeliveryAgent;
5600}
5601
5602bool QQuickItemPrivate::filterKeyEvent(QKeyEvent *e, bool post)
5603{
5604 if (!extra.isAllocated() || !extra->keyHandler)
5605 return false;
5606
5607 if (post)
5608 e->accept();
5609
5610 if (e->type() == QEvent::KeyPress)
5611 extra->keyHandler->keyPressed(event: e, post);
5612 else
5613 extra->keyHandler->keyReleased(event: e, post);
5614
5615 return e->isAccepted();
5616}
5617
5618void QQuickItemPrivate::deliverPointerEvent(QEvent *event)
5619{
5620 Q_Q(QQuickItem);
5621 const auto eventType = event->type();
5622 const bool focusAccepted = setFocusIfNeeded(eventType);
5623
5624 switch (eventType) {
5625 case QEvent::MouseButtonPress:
5626 q->mousePressEvent(event: static_cast<QMouseEvent *>(event));
5627 break;
5628 case QEvent::MouseButtonRelease:
5629 q->mouseReleaseEvent(event: static_cast<QMouseEvent *>(event));
5630 break;
5631 case QEvent::MouseButtonDblClick:
5632 q->mouseDoubleClickEvent(event: static_cast<QMouseEvent *>(event));
5633 break;
5634#if QT_CONFIG(wheelevent)
5635 case QEvent::Wheel:
5636 q->wheelEvent(event: static_cast<QWheelEvent*>(event));
5637 break;
5638#endif
5639 case QEvent::TouchBegin:
5640 case QEvent::TouchUpdate:
5641 case QEvent::TouchEnd:
5642 case QEvent::TouchCancel:
5643 q->touchEvent(event: static_cast<QTouchEvent *>(event));
5644 break;
5645 default:
5646 break;
5647 }
5648
5649 if (focusAccepted)
5650 event->accept();
5651}
5652
5653void QQuickItemPrivate::deliverKeyEvent(QKeyEvent *e)
5654{
5655 Q_Q(QQuickItem);
5656
5657 Q_ASSERT(e->isAccepted());
5658 if (filterKeyEvent(e, post: false))
5659 return;
5660 else
5661 e->accept();
5662
5663 if (e->type() == QEvent::KeyPress)
5664 q->keyPressEvent(event: e);
5665 else
5666 q->keyReleaseEvent(event: e);
5667
5668 if (e->isAccepted())
5669 return;
5670
5671 if (filterKeyEvent(e, post: true) || !q->window())
5672 return;
5673
5674 //only care about KeyPress now
5675 if (e->type() == QEvent::KeyPress &&
5676 (q == q->window()->contentItem() || q->activeFocusOnTab())) {
5677 bool res = false;
5678 if (!(e->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) { //### Add MetaModifier?
5679 if (e->key() == Qt::Key_Backtab
5680 || (e->key() == Qt::Key_Tab && (e->modifiers() & Qt::ShiftModifier)))
5681 res = QQuickItemPrivate::focusNextPrev(item: q, forward: false);
5682 else if (e->key() == Qt::Key_Tab)
5683 res = QQuickItemPrivate::focusNextPrev(item: q, forward: true);
5684 if (res)
5685 e->setAccepted(true);
5686 }
5687 }
5688}
5689
5690#if QT_CONFIG(im)
5691void QQuickItemPrivate::deliverInputMethodEvent(QInputMethodEvent *e)
5692{
5693 Q_Q(QQuickItem);
5694
5695 Q_ASSERT(e->isAccepted());
5696 if (extra.isAllocated() && extra->keyHandler) {
5697 extra->keyHandler->inputMethodEvent(event: e, post: false);
5698
5699 if (e->isAccepted())
5700 return;
5701 else
5702 e->accept();
5703 }
5704
5705 q->inputMethodEvent(event: e);
5706
5707 if (e->isAccepted())
5708 return;
5709
5710 if (extra.isAllocated() && extra->keyHandler) {
5711 e->accept();
5712
5713 extra->keyHandler->inputMethodEvent(event: e, post: true);
5714 }
5715}
5716#endif // im
5717
5718void QQuickItemPrivate::deliverShortcutOverrideEvent(QKeyEvent *event)
5719{
5720 if (extra.isAllocated() && extra->keyHandler)
5721 extra->keyHandler->shortcutOverrideEvent(event);
5722 else
5723 event->ignore();
5724}
5725
5726bool QQuickItemPrivate::anyPointerHandlerWants(const QPointerEvent *event, const QEventPoint &point) const
5727{
5728 if (!hasPointerHandlers())
5729 return false;
5730 for (QQuickPointerHandler *handler : extra->pointerHandlers) {
5731 if (handler->wantsEventPoint(event, point))
5732 return true;
5733 }
5734 return false;
5735}
5736
5737/*!
5738 \internal
5739 Deliver the \a event to all this item's PointerHandlers, but skip
5740 HoverHandlers if the event is a QMouseEvent or QWheelEvent (they are visited
5741 in QQuickDeliveryAgentPrivate::deliverHoverEventToItem()), and skip handlers
5742 that are in QQuickPointerHandlerPrivate::deviceDeliveryTargets().
5743 If \a avoidGrabbers is true, also skip delivery to any handler that
5744 is exclusively or passively grabbing any point within \a event
5745 (because delivery to grabbers is handled separately).
5746*/
5747bool QQuickItemPrivate::handlePointerEvent(QPointerEvent *event, bool avoidGrabbers)
5748{
5749 bool delivered = false;
5750 if (extra.isAllocated()) {
5751 for (QQuickPointerHandler *handler : extra->pointerHandlers) {
5752 bool avoidThisHandler = false;
5753 if (QQuickDeliveryAgentPrivate::isMouseOrWheelEvent(ev: event) &&
5754 qmlobject_cast<const QQuickHoverHandler *>(object: handler)) {
5755 avoidThisHandler = true;
5756 } else if (avoidGrabbers) {
5757 for (auto &p : event->points()) {
5758 if (event->exclusiveGrabber(point: p) == handler || event->passiveGrabbers(point: p).contains(t: handler)) {
5759 avoidThisHandler = true;
5760 break;
5761 }
5762 }
5763 }
5764 if (!avoidThisHandler &&
5765 !QQuickPointerHandlerPrivate::deviceDeliveryTargets(device: event->device()).contains(t: handler)) {
5766 handler->handlePointerEvent(event);
5767 delivered = true;
5768 }
5769 }
5770 }
5771 return delivered;
5772}
5773
5774/*!
5775 Called when \a change occurs for this item.
5776
5777 \a value contains extra information relating to the change, when
5778 applicable.
5779
5780 If you re-implement this method in a subclass, be sure to call
5781 \code
5782 QQuickItem::itemChange(change, value);
5783 \endcode
5784 typically at the end of your implementation, to ensure the
5785 \l windowChanged() signal will be emitted.
5786 */
5787void QQuickItem::itemChange(ItemChange change, const ItemChangeData &value)
5788{
5789 if (change == ItemSceneChange)
5790 emit windowChanged(window: value.window);
5791}
5792
5793#if QT_CONFIG(im)
5794/*!
5795 Notify input method on updated query values if needed. \a queries indicates
5796 the changed attributes.
5797*/
5798void QQuickItem::updateInputMethod(Qt::InputMethodQueries queries)
5799{
5800 if (hasActiveFocus())
5801 QGuiApplication::inputMethod()->update(queries);
5802}
5803#endif // im
5804
5805/*!
5806 Returns the extents of the item in its own coordinate system:
5807 a rectangle from \c{0, 0} to \l width() and \l height().
5808*/
5809QRectF QQuickItem::boundingRect() const
5810{
5811 Q_D(const QQuickItem);
5812 return QRectF(0, 0, d->width, d->height);
5813}
5814
5815/*!
5816 Returns the rectangular area within this item that is currently visible in
5817 \l viewportItem(), if there is a viewport and the \l ItemObservesViewport
5818 flag is set; otherwise, the extents of this item in its own coordinate
5819 system: a rectangle from \c{0, 0} to \l width() and \l height(). This is
5820 the region intended to remain visible if \l clip is \c true. It can also be
5821 used in updatePaintNode() to limit the graphics added to the scene graph.
5822
5823 For example, a large drawing or a large text document might be shown in a
5824 Flickable that occupies only part of the application's Window: in that
5825 case, Flickable is the viewport item, and a custom content-rendering item
5826 may choose to omit scene graph nodes that fall outside the area that is
5827 currently visible. If the \l ItemObservesViewport flag is set, this area
5828 will change each time the user scrolls the content in the Flickable.
5829
5830 In case of nested viewport items, clipRect() is the intersection of the
5831 \c {boundingRect}s of all ancestors that have the \l ItemIsViewport flag set,
5832 mapped to the coordinate system of \e this item.
5833
5834 \sa boundingRect()
5835*/
5836QRectF QQuickItem::clipRect() const
5837{
5838 Q_D(const QQuickItem);
5839 QRectF ret(0, 0, d->width, d->height);
5840 if (flags().testFlag(flag: QQuickItem::ItemObservesViewport)) {
5841 if (QQuickItem *viewport = viewportItem()) {
5842 // if the viewport is already "this", there's nothing to intersect;
5843 // and don't call clipRect() again, to avoid infinite recursion
5844 if (viewport == this)
5845 return ret;
5846 const auto mappedViewportRect = mapRectFromItem(item: viewport, rect: viewport->clipRect());
5847 qCDebug(lcVP) << this << "intersecting" << viewport << mappedViewportRect << ret << "->" << mappedViewportRect.intersected(r: ret);
5848 return mappedViewportRect.intersected(r: ret);
5849 }
5850 }
5851 return ret;
5852}
5853
5854/*!
5855 If the \l ItemObservesViewport flag is set,
5856 returns the nearest parent with the \l ItemIsViewport flag.
5857 Returns the window's contentItem if the flag is not set,
5858 or if no other viewport item is found.
5859
5860 Returns \nullptr only if there is no viewport item and this item is not
5861 shown in a window.
5862
5863 \sa clipRect()
5864*/
5865QQuickItem *QQuickItem::viewportItem() const
5866{
5867 if (flags().testFlag(flag: ItemObservesViewport)) {
5868 QQuickItem *par = parentItem();
5869 while (par) {
5870 if (par->flags().testFlag(flag: QQuickItem::ItemIsViewport))
5871 return par;
5872 par = par->parentItem();
5873 }
5874 }
5875 return (window() ? window()->contentItem() : nullptr);
5876}
5877
5878/*!
5879 \qmlproperty enumeration QtQuick::Item::transformOrigin
5880 This property holds the origin point around which scale and rotation transform.
5881
5882 Nine transform origins are available, as shown in the image below.
5883 The default transform origin is \c Item.Center.
5884
5885 \image declarative-transformorigin.png
5886
5887 This example rotates an image around its bottom-right corner.
5888 \qml
5889 Image {
5890 source: "myimage.png"
5891 transformOrigin: Item.BottomRight
5892 rotation: 45
5893 }
5894 \endqml
5895
5896 To set an arbitrary transform origin point use the \l Scale or \l Rotation
5897 transform types with \l transform.
5898*/
5899/*!
5900 \property QQuickItem::transformOrigin
5901 This property holds the origin point around which scale and rotation transform.
5902
5903 Nine transform origins are available, as shown in the image below.
5904 The default transform origin is \c Item.Center.
5905
5906 \image declarative-transformorigin.png
5907*/
5908QQuickItem::TransformOrigin QQuickItem::transformOrigin() const
5909{
5910 Q_D(const QQuickItem);
5911 return d->origin();
5912}
5913
5914void QQuickItem::setTransformOrigin(TransformOrigin origin)
5915{
5916 Q_D(QQuickItem);
5917 if (origin == d->origin())
5918 return;
5919
5920 d->extra.value().origin = origin;
5921 d->dirty(QQuickItemPrivate::TransformOrigin);
5922
5923 emit transformOriginChanged(d->origin());
5924}
5925
5926/*!
5927 \property QQuickItem::transformOriginPoint
5928 \internal
5929 */
5930/*!
5931 \internal
5932 */
5933QPointF QQuickItem::transformOriginPoint() const
5934{
5935 Q_D(const QQuickItem);
5936 if (d->extra.isAllocated() && !d->extra->userTransformOriginPoint.isNull())
5937 return d->extra->userTransformOriginPoint;
5938 return d->computeTransformOrigin();
5939}
5940
5941/*!
5942 \internal
5943 */
5944void QQuickItem::setTransformOriginPoint(const QPointF &point)
5945{
5946 Q_D(QQuickItem);
5947 if (d->extra.value().userTransformOriginPoint == point)
5948 return;
5949
5950 d->extra->userTransformOriginPoint = point;
5951 d->dirty(QQuickItemPrivate::TransformOrigin);
5952}
5953
5954/*!
5955 \qmlproperty real QtQuick::Item::z
5956
5957 Sets the stacking order of sibling items. By default the stacking order is 0.
5958
5959 Items with a higher stacking value are drawn on top of siblings with a
5960 lower stacking order. Items with the same stacking value are drawn
5961 bottom up in the order they appear. Items with a negative stacking
5962 value are drawn under their parent's content.
5963
5964 The following example shows the various effects of stacking order.
5965
5966 \table
5967 \row
5968 \li \image declarative-item_stacking1.png
5969 \li Same \c z - later children above earlier children:
5970 \qml
5971 Item {
5972 Rectangle {
5973 color: "red"
5974 width: 100; height: 100
5975 }
5976 Rectangle {
5977 color: "blue"
5978 x: 50; y: 50; width: 100; height: 100
5979 }
5980 }
5981 \endqml
5982 \row
5983 \li \image declarative-item_stacking2.png
5984 \li Higher \c z on top:
5985 \qml
5986 Item {
5987 Rectangle {
5988 z: 1
5989 color: "red"
5990 width: 100; height: 100
5991 }
5992 Rectangle {
5993 color: "blue"
5994 x: 50; y: 50; width: 100; height: 100
5995 }
5996 }
5997 \endqml
5998 \row
5999 \li \image declarative-item_stacking3.png
6000 \li Same \c z - children above parents:
6001 \qml
6002 Item {
6003 Rectangle {
6004 color: "red"
6005 width: 100; height: 100
6006 Rectangle {
6007 color: "blue"
6008 x: 50; y: 50; width: 100; height: 100
6009 }
6010 }
6011 }
6012 \endqml
6013 \row
6014 \li \image declarative-item_stacking4.png
6015 \li Lower \c z below:
6016 \qml
6017 Item {
6018 Rectangle {
6019 color: "red"
6020 width: 100; height: 100
6021 Rectangle {
6022 z: -1
6023 color: "blue"
6024 x: 50; y: 50; width: 100; height: 100
6025 }
6026 }
6027 }
6028 \endqml
6029 \endtable
6030 */
6031/*!
6032 \property QQuickItem::z
6033
6034 Sets the stacking order of sibling items. By default the stacking order is 0.
6035
6036 Items with a higher stacking value are drawn on top of siblings with a
6037 lower stacking order. Items with the same stacking value are drawn
6038 bottom up in the order they appear. Items with a negative stacking
6039 value are drawn under their parent's content.
6040
6041 The following example shows the various effects of stacking order.
6042
6043 \table
6044 \row
6045 \li \image declarative-item_stacking1.png
6046 \li Same \c z - later children above earlier children:
6047 \qml
6048 Item {
6049 Rectangle {
6050 color: "red"
6051 width: 100; height: 100
6052 }
6053 Rectangle {
6054 color: "blue"
6055 x: 50; y: 50; width: 100; height: 100
6056 }
6057 }
6058 \endqml
6059 \row
6060 \li \image declarative-item_stacking2.png
6061 \li Higher \c z on top:
6062 \qml
6063 Item {
6064 Rectangle {
6065 z: 1
6066 color: "red"
6067 width: 100; height: 100
6068 }
6069 Rectangle {
6070 color: "blue"
6071 x: 50; y: 50; width: 100; height: 100
6072 }
6073 }
6074 \endqml
6075 \row
6076 \li \image declarative-item_stacking3.png
6077 \li Same \c z - children above parents:
6078 \qml
6079 Item {
6080 Rectangle {
6081 color: "red"
6082 width: 100; height: 100
6083 Rectangle {
6084 color: "blue"
6085 x: 50; y: 50; width: 100; height: 100
6086 }
6087 }
6088 }
6089 \endqml
6090 \row
6091 \li \image declarative-item_stacking4.png
6092 \li Lower \c z below:
6093 \qml
6094 Item {
6095 Rectangle {
6096 color: "red"
6097 width: 100; height: 100
6098 Rectangle {
6099 z: -1
6100 color: "blue"
6101 x: 50; y: 50; width: 100; height: 100
6102 }
6103 }
6104 }
6105 \endqml
6106 \endtable
6107 */
6108qreal QQuickItem::z() const
6109{
6110 Q_D(const QQuickItem);
6111 return d->z();
6112}
6113
6114void QQuickItem::setZ(qreal v)
6115{
6116 Q_D(QQuickItem);
6117 if (d->z() == v)
6118 return;
6119
6120 d->extra.value().z = v;
6121
6122 d->dirty(QQuickItemPrivate::ZValue);
6123 if (d->parentItem) {
6124 QQuickItemPrivate::get(item: d->parentItem)->markSortedChildrenDirty(child: this);
6125 QQuickItemPrivate::get(item: d->parentItem)->dirty(QQuickItemPrivate::ChildrenStackingChanged);
6126 }
6127
6128 emit zChanged();
6129
6130#if QT_CONFIG(quick_shadereffect)
6131 if (d->extra.isAllocated() && d->extra->layer)
6132 d->extra->layer->updateZ();
6133#endif
6134}
6135
6136/*!
6137 \qmlproperty real QtQuick::Item::rotation
6138 This property holds the rotation of the item in degrees clockwise around
6139 its transformOrigin.
6140
6141 The default value is 0 degrees (that is, no rotation).
6142
6143 \table
6144 \row
6145 \li \image declarative-rotation.png
6146 \li
6147 \qml
6148 Rectangle {
6149 color: "blue"
6150 width: 100; height: 100
6151 Rectangle {
6152 color: "red"
6153 x: 25; y: 25; width: 50; height: 50
6154 rotation: 30
6155 }
6156 }
6157 \endqml
6158 \endtable
6159
6160 \sa Transform, Rotation
6161*/
6162/*!
6163 \property QQuickItem::rotation
6164 This property holds the rotation of the item in degrees clockwise around
6165 its transformOrigin.
6166
6167 The default value is 0 degrees (that is, no rotation).
6168
6169 \table
6170 \row
6171 \li \image declarative-rotation.png
6172 \li
6173 \qml
6174 Rectangle {
6175 color: "blue"
6176 width: 100; height: 100
6177 Rectangle {
6178 color: "red"
6179 x: 25; y: 25; width: 50; height: 50
6180 rotation: 30
6181 }
6182 }
6183 \endqml
6184 \endtable
6185
6186 \sa Transform, Rotation
6187 */
6188qreal QQuickItem::rotation() const
6189{
6190 Q_D(const QQuickItem);
6191 return d->rotation();
6192}
6193
6194void QQuickItem::setRotation(qreal r)
6195{
6196 Q_D(QQuickItem);
6197 if (d->rotation() == r)
6198 return;
6199
6200 d->extra.value().rotation = r;
6201
6202 d->dirty(QQuickItemPrivate::BasicTransform);
6203
6204 d->itemChange(ItemRotationHasChanged, r);
6205
6206 emit rotationChanged();
6207}
6208
6209/*!
6210 \qmlproperty real QtQuick::Item::scale
6211 This property holds the scale factor for this item.
6212
6213 A scale of less than 1.0 causes the item to be rendered at a smaller
6214 size, and a scale greater than 1.0 renders the item at a larger size.
6215 A negative scale causes the item to be mirrored when rendered.
6216
6217 The default value is 1.0.
6218
6219 Scaling is applied from the transformOrigin.
6220
6221 \table
6222 \row
6223 \li \image declarative-scale.png
6224 \li
6225 \qml
6226 import QtQuick 2.0
6227
6228 Rectangle {
6229 color: "blue"
6230 width: 100; height: 100
6231
6232 Rectangle {
6233 color: "green"
6234 width: 25; height: 25
6235 }
6236
6237 Rectangle {
6238 color: "red"
6239 x: 25; y: 25; width: 50; height: 50
6240 scale: 1.4
6241 transformOrigin: Item.TopLeft
6242 }
6243 }
6244 \endqml
6245 \endtable
6246
6247 \sa Transform, Scale
6248*/
6249/*!
6250 \property QQuickItem::scale
6251 This property holds the scale factor for this item.
6252
6253 A scale of less than 1.0 causes the item to be rendered at a smaller
6254 size, and a scale greater than 1.0 renders the item at a larger size.
6255 A negative scale causes the item to be mirrored when rendered.
6256
6257 The default value is 1.0.
6258
6259 Scaling is applied from the transformOrigin.
6260
6261 \table
6262 \row
6263 \li \image declarative-scale.png
6264 \li
6265 \qml
6266 import QtQuick 2.0
6267
6268 Rectangle {
6269 color: "blue"
6270 width: 100; height: 100
6271
6272 Rectangle {
6273 color: "green"
6274 width: 25; height: 25
6275 }
6276
6277 Rectangle {
6278 color: "red"
6279 x: 25; y: 25; width: 50; height: 50
6280 scale: 1.4
6281 }
6282 }
6283 \endqml
6284 \endtable
6285
6286 \sa Transform, Scale
6287 */
6288qreal QQuickItem::scale() const
6289{
6290 Q_D(const QQuickItem);
6291 return d->scale();
6292}
6293
6294void QQuickItem::setScale(qreal s)
6295{
6296 Q_D(QQuickItem);
6297 if (d->scale() == s)
6298 return;
6299
6300 d->extra.value().scale = s;
6301
6302 d->dirty(QQuickItemPrivate::BasicTransform);
6303
6304 emit scaleChanged();
6305}
6306
6307/*!
6308 \qmlproperty real QtQuick::Item::opacity
6309
6310 This property holds the opacity of the item. Opacity is specified as a
6311 number between 0.0 (fully transparent) and 1.0 (fully opaque). The default
6312 value is 1.0.
6313
6314 When this property is set, the specified opacity is also applied
6315 individually to child items. This may have an unintended effect in some
6316 circumstances. For example in the second set of rectangles below, the red
6317 rectangle has specified an opacity of 0.5, which affects the opacity of
6318 its blue child rectangle even though the child has not specified an opacity.
6319
6320 \table
6321 \row
6322 \li \image declarative-item_opacity1.png
6323 \li
6324 \qml
6325 Item {
6326 Rectangle {
6327 color: "red"
6328 width: 100; height: 100
6329 Rectangle {
6330 color: "blue"
6331 x: 50; y: 50; width: 100; height: 100
6332 }
6333 }
6334 }
6335 \endqml
6336 \row
6337 \li \image declarative-item_opacity2.png
6338 \li
6339 \qml
6340 Item {
6341 Rectangle {
6342 opacity: 0.5
6343 color: "red"
6344 width: 100; height: 100
6345 Rectangle {
6346 color: "blue"
6347 x: 50; y: 50; width: 100; height: 100
6348 }
6349 }
6350 }
6351 \endqml
6352 \endtable
6353
6354 Changing an item's opacity does not affect whether the item receives user
6355 input events. (In contrast, setting \l visible property to \c false stops
6356 mouse events, and setting the \l enabled property to \c false stops mouse
6357 and keyboard events, and also removes active focus from the item.)
6358
6359 \sa visible
6360*/
6361/*!
6362 \property QQuickItem::opacity
6363
6364 This property holds the opacity of the item. Opacity is specified as a
6365 number between 0.0 (fully transparent) and 1.0 (fully opaque). The default
6366 value is 1.0.
6367
6368 When this property is set, the specified opacity is also applied
6369 individually to child items. This may have an unintended effect in some
6370 circumstances. For example in the second set of rectangles below, the red
6371 rectangle has specified an opacity of 0.5, which affects the opacity of
6372 its blue child rectangle even though the child has not specified an opacity.
6373
6374 Values outside the range of 0 to 1 will be clamped.
6375
6376 \table
6377 \row
6378 \li \image declarative-item_opacity1.png
6379 \li
6380 \qml
6381 Item {
6382 Rectangle {
6383 color: "red"
6384 width: 100; height: 100
6385 Rectangle {
6386 color: "blue"
6387 x: 50; y: 50; width: 100; height: 100
6388 }
6389 }
6390 }
6391 \endqml
6392 \row
6393 \li \image declarative-item_opacity2.png
6394 \li
6395 \qml
6396 Item {
6397 Rectangle {
6398 opacity: 0.5
6399 color: "red"
6400 width: 100; height: 100
6401 Rectangle {
6402 color: "blue"
6403 x: 50; y: 50; width: 100; height: 100
6404 }
6405 }
6406 }
6407 \endqml
6408 \endtable
6409
6410 Changing an item's opacity does not affect whether the item receives user
6411 input events. (In contrast, setting \l visible property to \c false stops
6412 mouse events, and setting the \l enabled property to \c false stops mouse
6413 and keyboard events, and also removes active focus from the item.)
6414
6415 \sa visible
6416*/
6417qreal QQuickItem::opacity() const
6418{
6419 Q_D(const QQuickItem);
6420 return d->opacity();
6421}
6422
6423void QQuickItem::setOpacity(qreal newOpacity)
6424{
6425 Q_D(QQuickItem);
6426 qreal o = qBound<qreal>(min: 0, val: newOpacity, max: 1);
6427 if (d->opacity() == o)
6428 return;
6429
6430 d->extra.value().opacity = o;
6431
6432 d->dirty(QQuickItemPrivate::OpacityValue);
6433
6434 d->itemChange(ItemOpacityHasChanged, o);
6435
6436 emit opacityChanged();
6437}
6438
6439/*!
6440 \qmlproperty bool QtQuick::Item::visible
6441
6442 This property holds whether the item is visible. By default this is true.
6443
6444 Setting this property directly affects the \c visible value of child
6445 items. When set to \c false, the \c visible values of all child items also
6446 become \c false. When set to \c true, the \c visible values of child items
6447 are returned to \c true, unless they have explicitly been set to \c false.
6448
6449 (Because of this flow-on behavior, using the \c visible property may not
6450 have the intended effect if a property binding should only respond to
6451 explicit property changes. In such cases it may be better to use the
6452 \l opacity property instead.)
6453
6454 If this property is set to \c false, the item will no longer receive mouse
6455 events, but will continue to receive key events and will retain the keyboard
6456 \l focus if it has been set. (In contrast, setting the \l enabled property
6457 to \c false stops both mouse and keyboard events, and also removes focus
6458 from the item.)
6459
6460 \note This property's value is only affected by changes to this property or
6461 the parent's \c visible property. It does not change, for example, if this
6462 item moves off-screen, or if the \l opacity changes to 0.
6463
6464 \sa opacity, enabled
6465*/
6466/*!
6467 \property QQuickItem::visible
6468
6469 This property holds whether the item is visible. By default this is true.
6470
6471 Setting this property directly affects the \c visible value of child
6472 items. When set to \c false, the \c visible values of all child items also
6473 become \c false. When set to \c true, the \c visible values of child items
6474 are returned to \c true, unless they have explicitly been set to \c false.
6475
6476 (Because of this flow-on behavior, using the \c visible property may not
6477 have the intended effect if a property binding should only respond to
6478 explicit property changes. In such cases it may be better to use the
6479 \l opacity property instead.)
6480
6481 If this property is set to \c false, the item will no longer receive mouse
6482 events, but will continue to receive key events and will retain the keyboard
6483 \l focus if it has been set. (In contrast, setting the \l enabled property
6484 to \c false stops both mouse and keyboard events, and also removes focus
6485 from the item.)
6486
6487 \note This property's value is only affected by changes to this property or
6488 the parent's \c visible property. It does not change, for example, if this
6489 item moves off-screen, or if the \l opacity changes to 0. However, for
6490 historical reasons, this property is true after the item's construction, even
6491 if the item hasn't been added to a scene yet. Changing or reading this
6492 property of an item that has not been added to a scene might not produce
6493 the expected results.
6494
6495 \note The notification signal for this property gets emitted during destruction
6496 of the visual parent. C++ signal handlers cannot assume that items in the
6497 visual parent hierarchy are still fully constructed. Use \l qobject_cast to
6498 verify that items in the parent hierarchy can be used safely as the expected
6499 type.
6500
6501 \sa opacity, enabled
6502*/
6503bool QQuickItem::isVisible() const
6504{
6505 Q_D(const QQuickItem);
6506 return d->effectiveVisible;
6507}
6508
6509void QQuickItemPrivate::setVisible(bool visible)
6510{
6511 if (visible == explicitVisible)
6512 return;
6513
6514 explicitVisible = visible;
6515 if (!visible)
6516 dirty(QQuickItemPrivate::Visible);
6517
6518 const bool childVisibilityChanged = setEffectiveVisibleRecur(calcEffectiveVisible());
6519 if (childVisibilityChanged && parentItem)
6520 emit parentItem->visibleChildrenChanged(); // signal the parent, not this!
6521}
6522
6523void QQuickItem::setVisible(bool v)
6524{
6525 Q_D(QQuickItem);
6526 d->setVisible(v);
6527}
6528
6529/*!
6530 \qmlproperty bool QtQuick::Item::enabled
6531
6532 This property holds whether the item receives mouse and keyboard events.
6533 By default this is true.
6534
6535 Setting this property directly affects the \c enabled value of child
6536 items. When set to \c false, the \c enabled values of all child items also
6537 become \c false. When set to \c true, the \c enabled values of child items
6538 are returned to \c true, unless they have explicitly been set to \c false.
6539
6540 Setting this property to \c false automatically causes \l activeFocus to be
6541 set to \c false, and this item will no longer receive keyboard events.
6542
6543 \sa visible
6544*/
6545/*!
6546 \property QQuickItem::enabled
6547
6548 This property holds whether the item receives mouse and keyboard events.
6549 By default this is true.
6550
6551 Setting this property directly affects the \c enabled value of child
6552 items. When set to \c false, the \c enabled values of all child items also
6553 become \c false. When set to \c true, the \c enabled values of child items
6554 are returned to \c true, unless they have explicitly been set to \c false.
6555
6556 Setting this property to \c false automatically causes \l activeFocus to be
6557 set to \c false, and this item will longer receive keyboard events.
6558
6559 \note Hover events are enabled separately by \l setAcceptHoverEvents().
6560 Thus, a disabled item can continue to receive hover events, even when this
6561 property is \c false. This makes it possible to show informational feedback
6562 (such as \l ToolTip) even when an interactive item is disabled.
6563 The same is also true for any \l {HoverHandler}{HoverHandlers}
6564 added as children of the item. A HoverHandler can, however, be
6565 \l {PointerHandler::enabled}{disabled} explicitly, or for example
6566 be bound to the \c enabled state of the item.
6567
6568 \sa visible
6569*/
6570bool QQuickItem::isEnabled() const
6571{
6572 Q_D(const QQuickItem);
6573 return d->effectiveEnable;
6574}
6575
6576void QQuickItem::setEnabled(bool e)
6577{
6578 Q_D(QQuickItem);
6579 if (e == d->explicitEnable)
6580 return;
6581
6582 d->explicitEnable = e;
6583
6584 QQuickItem *scope = parentItem();
6585 while (scope && !scope->isFocusScope())
6586 scope = scope->parentItem();
6587
6588 d->setEffectiveEnableRecur(scope, d->calcEffectiveEnable());
6589}
6590
6591bool QQuickItemPrivate::calcEffectiveVisible() const
6592{
6593 // An item is visible if it is a child of a visible parent, and not explicitly hidden.
6594 return explicitVisible && parentItem && QQuickItemPrivate::get(item: parentItem)->effectiveVisible;
6595}
6596
6597bool QQuickItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible)
6598{
6599 Q_Q(QQuickItem);
6600
6601 if (newEffectiveVisible && !explicitVisible) {
6602 // This item locally overrides visibility
6603 return false; // effective visibility didn't change
6604 }
6605
6606 if (newEffectiveVisible == effectiveVisible) {
6607 // No change necessary
6608 return false; // effective visibility didn't change
6609 }
6610
6611 effectiveVisible = newEffectiveVisible;
6612 dirty(Visible);
6613 if (parentItem)
6614 QQuickItemPrivate::get(item: parentItem)->dirty(ChildrenStackingChanged);
6615 if (window) {
6616 if (auto agent = deliveryAgentPrivate())
6617 agent->removeGrabber(grabber: q, mouse: true, touch: true, cancel: true);
6618 }
6619
6620 bool childVisibilityChanged = false;
6621 for (int ii = 0; ii < childItems.size(); ++ii)
6622 childVisibilityChanged |= QQuickItemPrivate::get(item: childItems.at(i: ii))->setEffectiveVisibleRecur(newEffectiveVisible);
6623
6624 itemChange(QQuickItem::ItemVisibleHasChanged, bool(effectiveVisible));
6625#if QT_CONFIG(accessibility)
6626 if (isAccessible) {
6627 QAccessibleEvent ev(q, effectiveVisible ? QAccessible::ObjectShow : QAccessible::ObjectHide);
6628 QAccessible::updateAccessibility(event: &ev);
6629 }
6630#endif
6631 if (!inDestructor) {
6632 emit q->visibleChanged();
6633 if (childVisibilityChanged)
6634 emit q->visibleChildrenChanged();
6635 }
6636
6637 return true; // effective visibility DID change
6638}
6639
6640bool QQuickItemPrivate::calcEffectiveEnable() const
6641{
6642 // XXX todo - Should the effective enable of an element with no parent just be the current
6643 // effective enable? This would prevent pointless re-processing in the case of an element
6644 // moving to/from a no-parent situation, but it is different from what graphics view does.
6645 return explicitEnable && (!parentItem || QQuickItemPrivate::get(item: parentItem)->effectiveEnable);
6646}
6647
6648void QQuickItemPrivate::setEffectiveEnableRecur(QQuickItem *scope, bool newEffectiveEnable)
6649{
6650 Q_Q(QQuickItem);
6651
6652 if (newEffectiveEnable && !explicitEnable) {
6653 // This item locally overrides enable
6654 return;
6655 }
6656
6657 if (newEffectiveEnable == effectiveEnable) {
6658 // No change necessary
6659 return;
6660 }
6661
6662 effectiveEnable = newEffectiveEnable;
6663
6664 QQuickDeliveryAgentPrivate *da = deliveryAgentPrivate();
6665 if (da) {
6666 da->removeGrabber(grabber: q, mouse: true, touch: true, cancel: true);
6667 if (scope && !effectiveEnable && activeFocus) {
6668 da->clearFocusInScope(scope, item: q, reason: Qt::OtherFocusReason,
6669 QQuickDeliveryAgentPrivate::DontChangeFocusProperty |
6670 QQuickDeliveryAgentPrivate::DontChangeSubFocusItem);
6671 }
6672 }
6673
6674 for (int ii = 0; ii < childItems.size(); ++ii) {
6675 QQuickItemPrivate::get(item: childItems.at(i: ii))->setEffectiveEnableRecur(
6676 scope: (flags & QQuickItem::ItemIsFocusScope) && scope ? q : scope, newEffectiveEnable);
6677 }
6678
6679 if (scope && effectiveEnable && focus && da) {
6680 da->setFocusInScope(scope, item: q, reason: Qt::OtherFocusReason,
6681 QQuickDeliveryAgentPrivate::DontChangeFocusProperty |
6682 QQuickDeliveryAgentPrivate::DontChangeSubFocusItem);
6683 }
6684
6685 itemChange(QQuickItem::ItemEnabledHasChanged, bool(effectiveEnable));
6686#if QT_CONFIG(accessibility)
6687 if (isAccessible) {
6688 QAccessible::State changedState;
6689 changedState.disabled = true;
6690 changedState.focusable = true;
6691 QAccessibleStateChangeEvent ev(q, changedState);
6692 QAccessible::updateAccessibility(event: &ev);
6693 }
6694#endif
6695 emit q->enabledChanged();
6696}
6697
6698bool QQuickItemPrivate::isTransparentForPositioner() const
6699{
6700 return extra.isAllocated() && extra.value().transparentForPositioner;
6701}
6702
6703void QQuickItemPrivate::setTransparentForPositioner(bool transparent)
6704{
6705 extra.value().transparentForPositioner = transparent;
6706}
6707
6708
6709QString QQuickItemPrivate::dirtyToString() const
6710{
6711#define DIRTY_TO_STRING(value) if (dirtyAttributes & value) { \
6712 if (!rv.isEmpty()) \
6713 rv.append(QLatin1Char('|')); \
6714 rv.append(QLatin1String(#value)); \
6715}
6716
6717// QString rv = QLatin1String("0x") + QString::number(dirtyAttributes, 16);
6718 QString rv;
6719
6720 DIRTY_TO_STRING(TransformOrigin);
6721 DIRTY_TO_STRING(Transform);
6722 DIRTY_TO_STRING(BasicTransform);
6723 DIRTY_TO_STRING(Position);
6724 DIRTY_TO_STRING(Size);
6725 DIRTY_TO_STRING(ZValue);
6726 DIRTY_TO_STRING(Content);
6727 DIRTY_TO_STRING(Smooth);
6728 DIRTY_TO_STRING(OpacityValue);
6729 DIRTY_TO_STRING(ChildrenChanged);
6730 DIRTY_TO_STRING(ChildrenStackingChanged);
6731 DIRTY_TO_STRING(ParentChanged);
6732 DIRTY_TO_STRING(Clip);
6733 DIRTY_TO_STRING(Window);
6734 DIRTY_TO_STRING(EffectReference);
6735 DIRTY_TO_STRING(Visible);
6736 DIRTY_TO_STRING(HideReference);
6737 DIRTY_TO_STRING(Antialiasing);
6738
6739 return rv;
6740}
6741
6742void QQuickItemPrivate::dirty(DirtyType type)
6743{
6744 Q_Q(QQuickItem);
6745 if (!(dirtyAttributes & type) || (window && !prevDirtyItem)) {
6746 dirtyAttributes |= type;
6747 if (window && componentComplete) {
6748 addToDirtyList();
6749 QQuickWindowPrivate::get(c: window)->dirtyItem(q);
6750 }
6751 }
6752 if (type & (TransformOrigin | Transform | BasicTransform | Position | Size | Clip))
6753 transformChanged(transformedItem: q);
6754}
6755
6756void QQuickItemPrivate::addToDirtyList()
6757{
6758 Q_Q(QQuickItem);
6759
6760 Q_ASSERT(window);
6761 if (!prevDirtyItem) {
6762 Q_ASSERT(!nextDirtyItem);
6763
6764 QQuickWindowPrivate *p = QQuickWindowPrivate::get(c: window);
6765 nextDirtyItem = p->dirtyItemList;
6766 if (nextDirtyItem) QQuickItemPrivate::get(item: nextDirtyItem)->prevDirtyItem = &nextDirtyItem;
6767 prevDirtyItem = &p->dirtyItemList;
6768 p->dirtyItemList = q;
6769 p->dirtyItem(q);
6770 }
6771 Q_ASSERT(prevDirtyItem);
6772}
6773
6774void QQuickItemPrivate::removeFromDirtyList()
6775{
6776 if (prevDirtyItem) {
6777 if (nextDirtyItem) QQuickItemPrivate::get(item: nextDirtyItem)->prevDirtyItem = prevDirtyItem;
6778 *prevDirtyItem = nextDirtyItem;
6779 prevDirtyItem = nullptr;
6780 nextDirtyItem = nullptr;
6781 }
6782 Q_ASSERT(!prevDirtyItem);
6783 Q_ASSERT(!nextDirtyItem);
6784}
6785
6786void QQuickItemPrivate::refFromEffectItem(bool hide)
6787{
6788 ++extra.value().effectRefCount;
6789 if (extra->effectRefCount == 1) {
6790 dirty(type: EffectReference);
6791 if (parentItem)
6792 QQuickItemPrivate::get(item: parentItem)->dirty(type: ChildrenStackingChanged);
6793 }
6794 if (hide) {
6795 if (++extra->hideRefCount == 1)
6796 dirty(type: HideReference);
6797 }
6798 recursiveRefFromEffectItem(refs: 1);
6799}
6800
6801void QQuickItemPrivate::recursiveRefFromEffectItem(int refs)
6802{
6803 Q_Q(QQuickItem);
6804 if (!refs)
6805 return;
6806 extra.value().recursiveEffectRefCount += refs;
6807 for (int ii = 0; ii < childItems.size(); ++ii) {
6808 QQuickItem *child = childItems.at(i: ii);
6809 QQuickItemPrivate::get(item: child)->recursiveRefFromEffectItem(refs);
6810 }
6811 // Polish may rely on the effect ref count so trigger one, if item is not visible
6812 // (if visible, it will be triggered automatically).
6813 if (!effectiveVisible && refs > 0 && extra.value().recursiveEffectRefCount == 1) // it wasn't referenced, now it's referenced
6814 q->polish();
6815}
6816
6817void QQuickItemPrivate::derefFromEffectItem(bool unhide)
6818{
6819 Q_ASSERT(extra->effectRefCount);
6820 --extra->effectRefCount;
6821 if (extra->effectRefCount == 0) {
6822 dirty(type: EffectReference);
6823 if (parentItem)
6824 QQuickItemPrivate::get(item: parentItem)->dirty(type: ChildrenStackingChanged);
6825 }
6826 if (unhide) {
6827 if (--extra->hideRefCount == 0)
6828 dirty(type: HideReference);
6829 }
6830 recursiveRefFromEffectItem(refs: -1);
6831}
6832
6833void QQuickItemPrivate::setCulled(bool cull)
6834{
6835 if (cull == culled)
6836 return;
6837
6838 culled = cull;
6839 if ((cull && ++extra.value().hideRefCount == 1) || (!cull && --extra.value().hideRefCount == 0))
6840 dirty(type: HideReference);
6841}
6842
6843void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data)
6844{
6845 Q_Q(QQuickItem);
6846 switch (change) {
6847 case QQuickItem::ItemChildAddedChange: {
6848 q->itemChange(change, value: data);
6849 // The newly added child or any of its descendants may have
6850 // ItemObservesViewport set, in which case we need to both
6851 // inform the item that the transform has changed, and re-apply
6852 // subtreeTransformChangedEnabled to both this item and its
6853 // ancestors.
6854 if (QQuickItemPrivate::get(item: data.item)->transformChanged(transformedItem: q)) {
6855 if (!subtreeTransformChangedEnabled) {
6856 qCDebug(lcVP) << "turned on transformChanged notification for subtree of" << q;
6857 subtreeTransformChangedEnabled = true;
6858 }
6859 enableSubtreeChangeNotificationsForParentHierachy();
6860 }
6861 notifyChangeListeners(changeTypes: QQuickItemPrivate::Children, function: &QQuickItemChangeListener::itemChildAdded, args: q, args: data.item);
6862 break;
6863 }
6864 case QQuickItem::ItemChildRemovedChange: {
6865 q->itemChange(change, value: data);
6866 notifyChangeListeners(changeTypes: QQuickItemPrivate::Children, function: &QQuickItemChangeListener::itemChildRemoved, args: q, args: data.item);
6867 break;
6868 }
6869 case QQuickItem::ItemSceneChange:
6870 q->itemChange(change, value: data);
6871 break;
6872 case QQuickItem::ItemVisibleHasChanged: {
6873 q->itemChange(change, value: data);
6874 notifyChangeListeners(changeTypes: QQuickItemPrivate::Visibility, function: &QQuickItemChangeListener::itemVisibilityChanged, args: q);
6875 break;
6876 }
6877 case QQuickItem::ItemEnabledHasChanged: {
6878 q->itemChange(change, value: data);
6879 notifyChangeListeners(changeTypes: QQuickItemPrivate::Enabled, function: &QQuickItemChangeListener::itemEnabledChanged, args: q);
6880 break;
6881 }
6882 case QQuickItem::ItemParentHasChanged: {
6883 q->itemChange(change, value: data);
6884 notifyChangeListeners(changeTypes: QQuickItemPrivate::Parent, function: &QQuickItemChangeListener::itemParentChanged, args: q, args: data.item);
6885 break;
6886 }
6887 case QQuickItem::ItemOpacityHasChanged: {
6888 q->itemChange(change, value: data);
6889 notifyChangeListeners(changeTypes: QQuickItemPrivate::Opacity, function: &QQuickItemChangeListener::itemOpacityChanged, args: q);
6890 break;
6891 }
6892 case QQuickItem::ItemActiveFocusHasChanged:
6893 q->itemChange(change, value: data);
6894 break;
6895 case QQuickItem::ItemRotationHasChanged: {
6896 q->itemChange(change, value: data);
6897 notifyChangeListeners(changeTypes: QQuickItemPrivate::Rotation, function: &QQuickItemChangeListener::itemRotationChanged, args: q);
6898 break;
6899 }
6900 case QQuickItem::ItemAntialiasingHasChanged:
6901 // fall through
6902 case QQuickItem::ItemDevicePixelRatioHasChanged:
6903 q->itemChange(change, value: data);
6904 break;
6905 }
6906}
6907
6908/*!
6909 \qmlproperty bool QtQuick::Item::smooth
6910
6911 Primarily used in image based items to decide if the item should use smooth
6912 sampling or not. Smooth sampling is performed using linear interpolation, while
6913 non-smooth is performed using nearest neighbor.
6914
6915 In Qt Quick 2.0, this property has minimal impact on performance.
6916
6917 By default, this property is set to \c true.
6918*/
6919/*!
6920 \property QQuickItem::smooth
6921 \brief Specifies whether the item is smoothed or not
6922
6923 Primarily used in image based items to decide if the item should use smooth
6924 sampling or not. Smooth sampling is performed using linear interpolation, while
6925 non-smooth is performed using nearest neighbor.
6926
6927 In Qt Quick 2.0, this property has minimal impact on performance.
6928
6929 By default, this property is set to \c true.
6930*/
6931bool QQuickItem::smooth() const
6932{
6933 Q_D(const QQuickItem);
6934 return d->smooth;
6935}
6936void QQuickItem::setSmooth(bool smooth)
6937{
6938 Q_D(QQuickItem);
6939 if (d->smooth == smooth)
6940 return;
6941
6942 d->smooth = smooth;
6943 d->dirty(type: QQuickItemPrivate::Smooth);
6944
6945 emit smoothChanged(smooth);
6946}
6947
6948/*!
6949 \qmlproperty bool QtQuick::Item::activeFocusOnTab
6950
6951 This property holds whether the item wants to be in the tab focus
6952 chain. By default, this is set to \c false.
6953
6954 The tab focus chain traverses elements by first visiting the
6955 parent, and then its children in the order they occur in the
6956 children property. Pressing the tab key on an item in the tab
6957 focus chain will move keyboard focus to the next item in the
6958 chain. Pressing BackTab (normally Shift+Tab) will move focus
6959 to the previous item.
6960
6961 To set up a manual tab focus chain, see \l KeyNavigation. Tab
6962 key events used by Keys or KeyNavigation have precedence over
6963 focus chain behavior; ignore the events in other key handlers
6964 to allow it to propagate.
6965
6966 \note {QStyleHints::tabFocusBehavior}{tabFocusBehavior} can further limit focus
6967 to only specific types of controls, such as only text or list controls. This is
6968 the case on macOS, where focus to particular controls may be restricted based on
6969 system settings.
6970
6971 \sa QStyleHints::tabFocusBehavior, focusPolicy
6972*/
6973/*!
6974 \property QQuickItem::activeFocusOnTab
6975
6976 This property holds whether the item wants to be in the tab focus
6977 chain. By default, this is set to \c false.
6978
6979 \note {QStyleHints::tabFocusBehavior}{tabFocusBehavior} can further limit focus
6980 to only specific types of controls, such as only text or list controls. This is
6981 the case on macOS, where focus to particular controls may be restricted based on
6982 system settings.
6983
6984 \sa QStyleHints::tabFocusBehavior, focusPolicy
6985*/
6986// TODO FOCUS: Deprecate
6987bool QQuickItem::activeFocusOnTab() const
6988{
6989 Q_D(const QQuickItem);
6990 return d->activeFocusOnTab;
6991}
6992void QQuickItem::setActiveFocusOnTab(bool activeFocusOnTab)
6993{
6994 Q_D(QQuickItem);
6995 if (d->activeFocusOnTab == activeFocusOnTab)
6996 return;
6997
6998 if (window()) {
6999 if ((this == window()->activeFocusItem()) && this != window()->contentItem() && !activeFocusOnTab) {
7000 qWarning(msg: "QQuickItem: Cannot set activeFocusOnTab to false once item is the active focus item.");
7001 return;
7002 }
7003 }
7004
7005 d->activeFocusOnTab = activeFocusOnTab;
7006
7007 emit activeFocusOnTabChanged(activeFocusOnTab);
7008}
7009
7010/*!
7011 \qmlproperty bool QtQuick::Item::antialiasing
7012
7013 Used by visual elements to decide if the item should use antialiasing or not.
7014 In some cases items with antialiasing require more memory and are potentially
7015 slower to render (see \l {Antialiasing} for more details).
7016
7017 The default is false, but may be overridden by derived elements.
7018*/
7019/*!
7020 \property QQuickItem::antialiasing
7021 \brief Specifies whether the item is antialiased or not
7022
7023 Used by visual elements to decide if the item should use antialiasing or not.
7024 In some cases items with antialiasing require more memory and are potentially
7025 slower to render (see \l {Antialiasing} for more details).
7026
7027 The default is false, but may be overridden by derived elements.
7028*/
7029bool QQuickItem::antialiasing() const
7030{
7031 Q_D(const QQuickItem);
7032 return d->antialiasingValid ? d->antialiasing : d->implicitAntialiasing;
7033}
7034
7035void QQuickItem::setAntialiasing(bool aa)
7036{
7037 Q_D(QQuickItem);
7038
7039 if (!d->antialiasingValid) {
7040 d->antialiasingValid = true;
7041 d->antialiasing = d->implicitAntialiasing;
7042 }
7043
7044 if (aa == d->antialiasing)
7045 return;
7046
7047 d->antialiasing = aa;
7048 d->dirty(type: QQuickItemPrivate::Antialiasing);
7049
7050 d->itemChange(change: ItemAntialiasingHasChanged, data: bool(d->antialiasing));
7051
7052 emit antialiasingChanged(antialiasing());
7053}
7054
7055void QQuickItem::resetAntialiasing()
7056{
7057 Q_D(QQuickItem);
7058 if (!d->antialiasingValid)
7059 return;
7060
7061 d->antialiasingValid = false;
7062
7063 if (d->implicitAntialiasing != d->antialiasing)
7064 emit antialiasingChanged(antialiasing());
7065}
7066
7067void QQuickItemPrivate::setImplicitAntialiasing(bool antialiasing)
7068{
7069 Q_Q(QQuickItem);
7070 bool prev = q->antialiasing();
7071 implicitAntialiasing = antialiasing;
7072 if (componentComplete && (q->antialiasing() != prev))
7073 emit q->antialiasingChanged(q->antialiasing());
7074}
7075
7076/*!
7077 Returns the item flags for this item.
7078
7079 \sa setFlag()
7080 */
7081QQuickItem::Flags QQuickItem::flags() const
7082{
7083 Q_D(const QQuickItem);
7084 return (QQuickItem::Flags)d->flags;
7085}
7086
7087/*!
7088 Enables the specified \a flag for this item if \a enabled is true;
7089 if \a enabled is false, the flag is disabled.
7090
7091 These provide various hints for the item; for example, the
7092 ItemClipsChildrenToShape flag indicates that all children of this
7093 item should be clipped to fit within the item area.
7094 */
7095void QQuickItem::setFlag(Flag flag, bool enabled)
7096{
7097 Q_D(QQuickItem);
7098 if (enabled)
7099 setFlags((Flags)(d->flags | (quint32)flag));
7100 else
7101 setFlags((Flags)(d->flags & ~(quint32)flag));
7102
7103 // We don't return early if the flag did not change. That's useful in case
7104 // we need to intentionally trigger this parent-chain traversal again.
7105 if (enabled && flag == ItemObservesViewport)
7106 d->enableSubtreeChangeNotificationsForParentHierachy();
7107}
7108
7109void QQuickItemPrivate::enableSubtreeChangeNotificationsForParentHierachy()
7110{
7111 Q_Q(QQuickItem);
7112
7113 QQuickItem *par = q->parentItem();
7114 while (par) {
7115 auto parPriv = QQuickItemPrivate::get(item: par);
7116 if (!parPriv->subtreeTransformChangedEnabled)
7117 qCDebug(lcVP) << "turned on transformChanged notification for subtree of" << par;
7118 parPriv->subtreeTransformChangedEnabled = true;
7119 par = par->parentItem();
7120 }
7121}
7122
7123/*!
7124 Enables the specified \a flags for this item.
7125
7126 \sa setFlag()
7127 */
7128void QQuickItem::setFlags(Flags flags)
7129{
7130 Q_D(QQuickItem);
7131
7132 if (int(flags & ItemIsFocusScope) != int(d->flags & ItemIsFocusScope)) {
7133 if (flags & ItemIsFocusScope && !d->childItems.isEmpty() && d->window) {
7134 qWarning(msg: "QQuickItem: Cannot set FocusScope once item has children and is in a window.");
7135 flags &= ~ItemIsFocusScope;
7136 } else if (d->flags & ItemIsFocusScope) {
7137 qWarning(msg: "QQuickItem: Cannot unset FocusScope flag.");
7138 flags |= ItemIsFocusScope;
7139 }
7140 }
7141
7142 if (int(flags & ItemClipsChildrenToShape) != int(d->flags & ItemClipsChildrenToShape))
7143 d->dirty(type: QQuickItemPrivate::Clip);
7144
7145 d->flags = flags;
7146}
7147
7148/*!
7149 \qmlproperty real QtQuick::Item::x
7150 \qmlproperty real QtQuick::Item::y
7151 \qmlproperty real QtQuick::Item::width
7152 \qmlproperty real QtQuick::Item::height
7153
7154 Defines the item's position and size.
7155 The default value is \c 0.
7156
7157 The (x,y) position is relative to the \l parent.
7158
7159 \qml
7160 Item { x: 100; y: 100; width: 100; height: 100 }
7161 \endqml
7162 */
7163/*!
7164 \property QQuickItem::x
7165
7166 Defines the item's x position relative to its parent.
7167 */
7168/*!
7169 \property QQuickItem::y
7170
7171 Defines the item's y position relative to its parent.
7172 */
7173qreal QQuickItem::x() const
7174{
7175 Q_D(const QQuickItem);
7176 return d->x;
7177}
7178
7179qreal QQuickItem::y() const
7180{
7181 Q_D(const QQuickItem);
7182 return d->y;
7183}
7184
7185/*!
7186 \internal
7187 */
7188QPointF QQuickItem::position() const
7189{
7190 Q_D(const QQuickItem);
7191 return QPointF(d->x, d->y);
7192}
7193
7194void QQuickItem::setX(qreal v)
7195{
7196 Q_D(QQuickItem);
7197 /* There are two ways in which this function might be called:
7198 a) Either directly by the user, or
7199 b) when a binding has evaluated to a new value and it writes
7200 the value back
7201 In the first case, we want to remove an existing binding, in
7202 the second case, we don't want to remove the binding which
7203 just wrote the value.
7204 removeBindingUnlessInWrapper takes care of this.
7205 */
7206 d->x.removeBindingUnlessInWrapper();
7207 if (qt_is_nan(d: v))
7208 return;
7209
7210 const qreal oldx = d->x.valueBypassingBindings();
7211 if (oldx == v)
7212 return;
7213
7214 d->x.setValueBypassingBindings(v);
7215
7216 d->dirty(type: QQuickItemPrivate::Position);
7217
7218 const qreal y = d->y.valueBypassingBindings();
7219 const qreal w = d->width.valueBypassingBindings();
7220 const qreal h = d->height.valueBypassingBindings();
7221 geometryChange(newGeometry: QRectF(v, y, w, h), oldGeometry: QRectF(oldx, y, w, h));
7222}
7223
7224void QQuickItem::setY(qreal v)
7225{
7226 Q_D(QQuickItem);
7227 d->y.removeBindingUnlessInWrapper();
7228 if (qt_is_nan(d: v))
7229 return;
7230
7231 const qreal oldy = d->y.valueBypassingBindings();
7232 if (oldy == v)
7233 return;
7234
7235 d->y.setValueBypassingBindings(v);
7236
7237 d->dirty(type: QQuickItemPrivate::Position);
7238
7239 // we use v instead of d->y, as that avoid a method call
7240 // and we have v anyway in scope
7241 const qreal x = d->x.valueBypassingBindings();
7242 const qreal w = d->width.valueBypassingBindings();
7243 const qreal h = d->height.valueBypassingBindings();
7244 geometryChange(newGeometry: QRectF(x, v, w, h), oldGeometry: QRectF(x, oldy, w, h));
7245}
7246
7247/*!
7248 \internal
7249 */
7250void QQuickItem::setPosition(const QPointF &pos)
7251{
7252 Q_D(QQuickItem);
7253
7254 const qreal oldx = d->x.valueBypassingBindings();
7255 const qreal oldy = d->y.valueBypassingBindings();
7256
7257 if (QPointF(oldx, oldy) == pos)
7258 return;
7259
7260 /* This preserves the bindings, because that was what the code used to do
7261 The effect of this is that you can have
7262 Item {
7263 Rectangle {
7264 x: someValue; y: someValue
7265 DragHandler {}
7266 }
7267 }
7268 and you can move the rectangle around; once someValue changes, the position gets
7269 reset again (even when a drag is currently ongoing).
7270 Whether we want this is up to discussion.
7271 */
7272
7273 d->x.setValueBypassingBindings(pos.x()); //TODO: investigate whether to break binding here or not
7274 d->y.setValueBypassingBindings(pos.y());
7275
7276 d->dirty(type: QQuickItemPrivate::Position);
7277
7278 const qreal w = d->width.valueBypassingBindings();
7279 const qreal h = d->height.valueBypassingBindings();
7280 geometryChange(newGeometry: QRectF(pos.x(), pos.y(), w, h), oldGeometry: QRectF(oldx, oldy, w, h));
7281}
7282
7283/* The bindable methods return an object which supports inspection (hasBinding) and
7284 modification (setBinding, removeBinding) of the properties bindable state.
7285*/
7286QBindable<qreal> QQuickItem::bindableX()
7287{
7288 return QBindable<qreal>(&d_func()->x);
7289}
7290
7291QBindable<qreal> QQuickItem::bindableY()
7292{
7293 return QBindable<qreal>(&d_func()->y);
7294}
7295
7296/*!
7297 \property QQuickItem::width
7298
7299 This property holds the width of this item.
7300 */
7301qreal QQuickItem::width() const
7302{
7303 Q_D(const QQuickItem);
7304 return d->width;
7305}
7306
7307void QQuickItem::setWidth(qreal w)
7308{
7309 Q_D(QQuickItem);
7310 d->width.removeBindingUnlessInWrapper();
7311 if (qt_is_nan(d: w))
7312 return;
7313
7314 d->widthValidFlag = true;
7315 const qreal oldWidth = d->width.valueBypassingBindings();
7316 if (oldWidth == w)
7317 return;
7318
7319 d->width.setValueBypassingBindings(w);
7320
7321 d->dirty(type: QQuickItemPrivate::Size);
7322
7323 const qreal x = d->x.valueBypassingBindings();
7324 const qreal y = d->y.valueBypassingBindings();
7325 const qreal h = d->height.valueBypassingBindings();
7326 geometryChange(newGeometry: QRectF(x, y, w, h), oldGeometry: QRectF(x, y, oldWidth, h));
7327}
7328
7329void QQuickItem::resetWidth()
7330{
7331 Q_D(QQuickItem);
7332 d->width.takeBinding();
7333 d->widthValidFlag = false;
7334 setImplicitWidth(implicitWidth());
7335}
7336
7337void QQuickItemPrivate::implicitWidthChanged()
7338{
7339 Q_Q(QQuickItem);
7340 notifyChangeListeners(changeTypes: QQuickItemPrivate::ImplicitWidth, function: &QQuickItemChangeListener::itemImplicitWidthChanged, args: q);
7341 emit q->implicitWidthChanged();
7342}
7343
7344qreal QQuickItemPrivate::getImplicitWidth() const
7345{
7346 return implicitWidth;
7347}
7348/*!
7349 Returns the width of the item that is implied by other properties that determine the content.
7350*/
7351qreal QQuickItem::implicitWidth() const
7352{
7353 Q_D(const QQuickItem);
7354 return d->getImplicitWidth();
7355}
7356
7357QBindable<qreal> QQuickItem::bindableWidth()
7358{
7359 return QBindable<qreal>(&d_func()->width);
7360}
7361
7362/*!
7363 \qmlproperty real QtQuick::Item::implicitWidth
7364 \qmlproperty real QtQuick::Item::implicitHeight
7365
7366 Defines the preferred width or height of the Item.
7367
7368 If \l width or \l height is not specified, an item's effective size will be
7369 determined by its \l implicitWidth or \l implicitHeight.
7370
7371 However, if an item is the child of a \l {Qt Quick Layouts}{layout}, the
7372 layout will determine the item's preferred size using its implicit size.
7373 In such a scenario, the explicit \l width or \l height will be ignored.
7374
7375 The default implicit size for most items is 0x0, however some items have an inherent
7376 implicit size which cannot be overridden, for example, \l [QML] Image and \l [QML] Text.
7377
7378 Setting the implicit size is useful for defining components that have a preferred size
7379 based on their content, for example:
7380
7381 \qml
7382 // Label.qml
7383 import QtQuick 2.0
7384
7385 Item {
7386 property alias icon: image.source
7387 property alias label: text.text
7388 implicitWidth: text.implicitWidth + image.implicitWidth
7389 implicitHeight: Math.max(text.implicitHeight, image.implicitHeight)
7390 Image { id: image }
7391 Text {
7392 id: text
7393 wrapMode: Text.Wrap
7394 anchors.left: image.right; anchors.right: parent.right
7395 anchors.verticalCenter: parent.verticalCenter
7396 }
7397 }
7398 \endqml
7399
7400 \note Using implicitWidth of \l [QML] Text or \l [QML] TextEdit and setting the width explicitly
7401 incurs a performance penalty as the text must be laid out twice.
7402*/
7403/*!
7404 \property QQuickItem::implicitWidth
7405 \property QQuickItem::implicitHeight
7406
7407 Defines the preferred width or height of the Item.
7408
7409 If \l width or \l height is not specified, an item's effective size will be
7410 determined by its \l implicitWidth or \l implicitHeight.
7411
7412 However, if an item is the child of a \l {Qt Quick Layouts}{layout}, the
7413 layout will determine the item's preferred size using its implicit size.
7414 In such a scenario, the explicit \l width or \l height will be ignored.
7415
7416 The default implicit size for most items is 0x0, however some items have an inherent
7417 implicit size which cannot be overridden, for example, \l [QML] Image and \l [QML] Text.
7418
7419 Setting the implicit size is useful for defining components that have a preferred size
7420 based on their content, for example:
7421
7422 \qml
7423 // Label.qml
7424 import QtQuick 2.0
7425
7426 Item {
7427 property alias icon: image.source
7428 property alias label: text.text
7429 implicitWidth: text.implicitWidth + image.implicitWidth
7430 implicitHeight: Math.max(text.implicitHeight, image.implicitHeight)
7431 Image { id: image }
7432 Text {
7433 id: text
7434 wrapMode: Text.Wrap
7435 anchors.left: image.right; anchors.right: parent.right
7436 anchors.verticalCenter: parent.verticalCenter
7437 }
7438 }
7439 \endqml
7440
7441 \note Using implicitWidth of \l [QML] Text or \l [QML] TextEdit and setting the width explicitly
7442 incurs a performance penalty as the text must be laid out twice.
7443*/
7444void QQuickItem::setImplicitWidth(qreal w)
7445{
7446 Q_D(QQuickItem);
7447 bool changed = w != d->implicitWidth;
7448 d->implicitWidth = w;
7449 // this uses valueBypassingBindings simply to avoid repeated "am I in a binding" checks
7450 if (d->width.valueBypassingBindings() == w || widthValid()) {
7451 if (changed)
7452 d->implicitWidthChanged();
7453 if (d->width.valueBypassingBindings() == w || widthValid())
7454 return;
7455 changed = false;
7456 }
7457
7458 const qreal oldWidth = d->width.valueBypassingBindings();
7459 Q_ASSERT(!d->width.hasBinding() || QQmlPropertyBinding::isUndefined(d->width.binding()));
7460 // we need to keep the binding if its undefined (therefore we can't use operator=/setValue)
7461 d->width.setValueBypassingBindings(w);
7462
7463 d->dirty(type: QQuickItemPrivate::Size);
7464
7465 const qreal x = d->x.valueBypassingBindings();
7466 const qreal y = d->y.valueBypassingBindings();
7467 const qreal width = w;
7468 const qreal height = d->height.valueBypassingBindings();
7469 geometryChange(newGeometry: QRectF(x, y, width, height), oldGeometry: QRectF(x, y, oldWidth, height));
7470
7471 if (changed)
7472 d->implicitWidthChanged();
7473}
7474
7475/*!
7476 Returns whether the width property has been set explicitly.
7477*/
7478bool QQuickItem::widthValid() const
7479{
7480 Q_D(const QQuickItem);
7481 /* Logic: The width is valid if we assigned a value
7482 or a binding to it. Note that a binding evaluation to
7483 undefined (and thus calling resetWidth) is detached [1];
7484 hasBinding will thus return false for it, which is
7485 what we want here, as resetting width should mean that
7486 width is invalid (until the binding evaluates to a
7487 non-undefined value again).
7488
7489 [1]: A detached binding is a binding which is not set on a property.
7490 In the case of QQmlPropertyBinding and resettable properties, it
7491 still gets reevaluated when it was detached due to the binding
7492 returning undefined, and it gets re-attached, once the binding changes
7493 to a non-undefined value (unless another binding has beenset in the
7494 meantime).
7495 See QQmlPropertyBinding::isUndefined and handleUndefinedAssignment
7496 */
7497
7498 return d->widthValid();
7499}
7500
7501/*!
7502 \property QQuickItem::height
7503
7504 This property holds the height of this item.
7505 */
7506qreal QQuickItem::height() const
7507{
7508 Q_D(const QQuickItem);
7509 return d->height;
7510}
7511
7512void QQuickItem::setHeight(qreal h)
7513{
7514 Q_D(QQuickItem);
7515 // Note that we call removeUnlessInWrapper before returning in the
7516 // NaN and equal value cases; that ensures that an explicit setHeight
7517 // always removes the binding
7518 d->height.removeBindingUnlessInWrapper();
7519 if (qt_is_nan(d: h))
7520 return;
7521
7522 d->heightValidFlag = true;
7523 const qreal oldHeight = d->height.valueBypassingBindings();
7524 if (oldHeight == h)
7525 return;
7526
7527 d->height.setValueBypassingBindings(h);
7528
7529 d->dirty(type: QQuickItemPrivate::Size);
7530
7531 const qreal x = d->x.valueBypassingBindings();
7532 const qreal y = d->y.valueBypassingBindings();
7533 const qreal w = d->width.valueBypassingBindings();
7534 geometryChange(newGeometry: QRectF(x, y, w, h), oldGeometry: QRectF(x, y, w, oldHeight));
7535}
7536
7537void QQuickItem::resetHeight()
7538{
7539 Q_D(QQuickItem);
7540 // using takeBinding, we remove any existing binding from the
7541 // property, but preserve the existing value (and avoid some overhead
7542 // compared to calling setHeight(height())
7543 d->height.takeBinding();
7544 d->heightValidFlag = false;
7545 setImplicitHeight(implicitHeight());
7546}
7547
7548void QQuickItemPrivate::implicitHeightChanged()
7549{
7550 Q_Q(QQuickItem);
7551 notifyChangeListeners(changeTypes: QQuickItemPrivate::ImplicitHeight, function: &QQuickItemChangeListener::itemImplicitHeightChanged, args: q);
7552 emit q->implicitHeightChanged();
7553}
7554
7555qreal QQuickItemPrivate::getImplicitHeight() const
7556{
7557 return implicitHeight;
7558}
7559
7560qreal QQuickItem::implicitHeight() const
7561{
7562 Q_D(const QQuickItem);
7563 return d->getImplicitHeight();
7564}
7565
7566QBindable<qreal> QQuickItem::bindableHeight()
7567{
7568 return QBindable<qreal>(&d_func()->height);
7569}
7570
7571void QQuickItem::setImplicitHeight(qreal h)
7572{
7573 Q_D(QQuickItem);
7574 bool changed = h != d->implicitHeight;
7575 d->implicitHeight = h;
7576 if (d->height.valueBypassingBindings() == h || heightValid()) {
7577 if (changed)
7578 d->implicitHeightChanged();
7579 if (d->height.valueBypassingBindings() == h || heightValid())
7580 return;
7581 changed = false;
7582 }
7583
7584 const qreal oldHeight = d->height.valueBypassingBindings();
7585 Q_ASSERT(!d->height.hasBinding() || QQmlPropertyBinding::isUndefined(d->height.binding()));
7586 // we need to keep the binding if its undefined (therefore we can't use operator=/setValue)
7587 d->height.setValueBypassingBindings(h);
7588
7589 d->dirty(type: QQuickItemPrivate::Size);
7590
7591 const qreal x = d->x.valueBypassingBindings();
7592 const qreal y = d->y.valueBypassingBindings();
7593 const qreal width = d->width.valueBypassingBindings();
7594 const qreal height = d->height.valueBypassingBindings();
7595 geometryChange(newGeometry: QRectF(x, y, width, height),
7596 oldGeometry: QRectF(x, y, width, oldHeight));
7597
7598 if (changed)
7599 d->implicitHeightChanged();
7600}
7601
7602/*!
7603 \internal
7604 */
7605void QQuickItem::setImplicitSize(qreal w, qreal h)
7606{
7607 Q_D(QQuickItem);
7608 bool wChanged = w != d->implicitWidth;
7609 bool hChanged = h != d->implicitHeight;
7610
7611 d->implicitWidth = w;
7612 d->implicitHeight = h;
7613
7614 bool wDone = false;
7615 bool hDone = false;
7616 qreal width = d->width.valueBypassingBindings();
7617 qreal height = d->height.valueBypassingBindings();
7618 if (width == w || widthValid()) {
7619 if (wChanged)
7620 d->implicitWidthChanged();
7621 wDone = width == w || widthValid();
7622 wChanged = false;
7623 }
7624 if (height == h || heightValid()) {
7625 if (hChanged)
7626 d->implicitHeightChanged();
7627 hDone = height == h || heightValid();
7628 hChanged = false;
7629 }
7630 if (wDone && hDone)
7631 return;
7632
7633 const qreal oldWidth = width;
7634 const qreal oldHeight = height;
7635 if (!wDone) {
7636 width = w;
7637 d->width.setValueBypassingBindings(w);
7638 }
7639 if (!hDone) {
7640 height = h;
7641 d->height.setValueBypassingBindings(h);
7642 }
7643
7644 d->dirty(type: QQuickItemPrivate::Size);
7645
7646 const qreal x = d->x.valueBypassingBindings();
7647 const qreal y = d->y.valueBypassingBindings();
7648 geometryChange(newGeometry: QRectF(x, y, width, height),
7649 oldGeometry: QRectF(x, y, oldWidth, oldHeight));
7650
7651 if (!wDone && wChanged)
7652 d->implicitWidthChanged();
7653 if (!hDone && hChanged)
7654 d->implicitHeightChanged();
7655}
7656
7657/*!
7658 Returns whether the height property has been set explicitly.
7659*/
7660bool QQuickItem::heightValid() const
7661{
7662 Q_D(const QQuickItem);
7663 return d->heightValid();
7664}
7665
7666/*!
7667 \since 5.10
7668
7669 Returns the size of the item.
7670
7671 \sa setSize, width, height
7672 */
7673
7674QSizeF QQuickItem::size() const
7675{
7676 Q_D(const QQuickItem);
7677 return QSizeF(d->width, d->height);
7678}
7679
7680
7681/*!
7682 \since 5.10
7683
7684 Sets the size of the item to \a size.
7685 This methods preserves any existing binding on width and height;
7686 thus any change that triggers the binding to execute again will
7687 override the set values.
7688
7689 \sa size, setWidth, setHeight
7690 */
7691void QQuickItem::setSize(const QSizeF &size)
7692{
7693 Q_D(QQuickItem);
7694 d->heightValidFlag = true;
7695 d->widthValidFlag = true;
7696
7697 const qreal oldHeight = d->height.valueBypassingBindings();
7698 const qreal oldWidth = d->width.valueBypassingBindings();
7699
7700 if (oldWidth == size.width() && oldHeight == size.height())
7701 return;
7702
7703 d->height.setValueBypassingBindings(size.height());
7704 d->width.setValueBypassingBindings(size.width());
7705
7706 d->dirty(type: QQuickItemPrivate::Size);
7707
7708 const qreal x = d->x.valueBypassingBindings();
7709 const qreal y = d->y.valueBypassingBindings();
7710 geometryChange(newGeometry: QRectF(x, y, size.width(), size.height()), oldGeometry: QRectF(x, y, oldWidth, oldHeight));
7711}
7712
7713/*!
7714 \qmlproperty bool QtQuick::Item::activeFocus
7715 \readonly
7716
7717 This read-only property indicates whether the item has active focus.
7718
7719 If activeFocus is true, either this item is the one that currently
7720 receives keyboard input, or it is a FocusScope ancestor of the item
7721 that currently receives keyboard input.
7722
7723 Usually, activeFocus is gained by setting \l focus on an item and its
7724 enclosing FocusScope objects. In the following example, the \c input
7725 and \c focusScope objects will have active focus, while the root
7726 rectangle object will not.
7727
7728 \qml
7729 import QtQuick 2.0
7730
7731 Rectangle {
7732 width: 100; height: 100
7733
7734 FocusScope {
7735 id: focusScope
7736 focus: true
7737
7738 TextInput {
7739 id: input
7740 focus: true
7741 }
7742 }
7743 }
7744 \endqml
7745
7746 \sa focus, {Keyboard Focus in Qt Quick}
7747*/
7748/*!
7749 \property QQuickItem::activeFocus
7750 \readonly
7751
7752 This read-only property indicates whether the item has active focus.
7753
7754 If activeFocus is true, either this item is the one that currently
7755 receives keyboard input, or it is a FocusScope ancestor of the item
7756 that currently receives keyboard input.
7757
7758 Usually, activeFocus is gained by setting \l focus on an item and its
7759 enclosing FocusScope objects. In the following example, the \c input
7760 and \c focusScope objects will have active focus, while the root
7761 rectangle object will not.
7762
7763 \qml
7764 import QtQuick 2.0
7765
7766 Rectangle {
7767 width: 100; height: 100
7768
7769 FocusScope {
7770 focus: true
7771
7772 TextInput {
7773 id: input
7774 focus: true
7775 }
7776 }
7777 }
7778 \endqml
7779
7780 \sa focus, {Keyboard Focus in Qt Quick}
7781*/
7782bool QQuickItem::hasActiveFocus() const
7783{
7784 Q_D(const QQuickItem);
7785 return d->activeFocus;
7786}
7787
7788/*!
7789 \qmlproperty bool QtQuick::Item::focus
7790
7791 This property holds whether the item has focus within the enclosing
7792 FocusScope. If true, this item will gain active focus when the
7793 enclosing FocusScope gains active focus.
7794
7795 In the following example, \c input will be given active focus when
7796 \c scope gains active focus:
7797
7798 \qml
7799 import QtQuick 2.0
7800
7801 Rectangle {
7802 width: 100; height: 100
7803
7804 FocusScope {
7805 id: scope
7806
7807 TextInput {
7808 id: input
7809 focus: true
7810 }
7811 }
7812 }
7813 \endqml
7814
7815 For the purposes of this property, the scene as a whole is assumed
7816 to act like a focus scope. On a practical level, that means the
7817 following QML will give active focus to \c input on startup.
7818
7819 \qml
7820 Rectangle {
7821 width: 100; height: 100
7822
7823 TextInput {
7824 id: input
7825 focus: true
7826 }
7827 }
7828 \endqml
7829
7830 \sa activeFocus, {Keyboard Focus in Qt Quick}
7831*/
7832/*!
7833 \property QQuickItem::focus
7834
7835 This property holds whether the item has focus within the enclosing
7836 FocusScope. If true, this item will gain active focus when the
7837 enclosing FocusScope gains active focus.
7838
7839 In the following example, \c input will be given active focus when
7840 \c scope gains active focus:
7841
7842 \qml
7843 import QtQuick 2.0
7844
7845 Rectangle {
7846 width: 100; height: 100
7847
7848 FocusScope {
7849 id: scope
7850
7851 TextInput {
7852 id: input
7853 focus: true
7854 }
7855 }
7856 }
7857 \endqml
7858
7859 For the purposes of this property, the scene as a whole is assumed
7860 to act like a focus scope. On a practical level, that means the
7861 following QML will give active focus to \c input on startup.
7862
7863 \qml
7864 Rectangle {
7865 width: 100; height: 100
7866
7867 TextInput {
7868 id: input
7869 focus: true
7870 }
7871 }
7872 \endqml
7873
7874 \sa activeFocus, {Keyboard Focus in Qt Quick}
7875*/
7876bool QQuickItem::hasFocus() const
7877{
7878 Q_D(const QQuickItem);
7879 return d->focus;
7880}
7881
7882void QQuickItem::setFocus(bool focus)
7883{
7884 setFocus(focus, reason: Qt::OtherFocusReason);
7885}
7886
7887void QQuickItem::setFocus(bool focus, Qt::FocusReason reason)
7888{
7889 Q_D(QQuickItem);
7890 // Need to find our nearest focus scope
7891 QQuickItem *scope = parentItem();
7892 while (scope && !scope->isFocusScope() && scope->parentItem())
7893 scope = scope->parentItem();
7894
7895 if (d->focus == focus && (!focus || !scope || QQuickItemPrivate::get(item: scope)->subFocusItem == this))
7896 return;
7897
7898 bool notifyListeners = false;
7899 if (d->window || d->parentItem) {
7900 if (d->window) {
7901 auto da = d->deliveryAgentPrivate();
7902 Q_ASSERT(da);
7903 if (focus)
7904 da->setFocusInScope(scope, item: this, reason);
7905 else
7906 da->clearFocusInScope(scope, item: this, reason);
7907 } else {
7908 // do the focus changes from setFocusInScope/clearFocusInScope that are
7909 // unrelated to a window
7910 QVarLengthArray<QQuickItem *, 20> changed;
7911 QQuickItem *oldSubFocusItem = QQuickItemPrivate::get(item: scope)->subFocusItem;
7912 if (oldSubFocusItem) {
7913 QQuickItemPrivate::get(item: oldSubFocusItem)->updateSubFocusItem(scope, focus: false);
7914 QQuickItemPrivate::get(item: oldSubFocusItem)->focus = false;
7915 changed << oldSubFocusItem;
7916 } else if (!scope->isFocusScope() && scope->hasFocus()) {
7917 QQuickItemPrivate::get(item: scope)->focus = false;
7918 changed << scope;
7919 }
7920 d->updateSubFocusItem(scope, focus);
7921
7922 d->focus = focus;
7923 changed << this;
7924 notifyListeners = true;
7925 emit focusChanged(focus);
7926
7927 QQuickDeliveryAgentPrivate::notifyFocusChangesRecur(item: changed.data(), remaining: changed.size() - 1, reason);
7928 }
7929 } else {
7930 QVarLengthArray<QQuickItem *, 20> changed;
7931 QQuickItem *oldSubFocusItem = d->subFocusItem;
7932 if (!isFocusScope() && oldSubFocusItem) {
7933 QQuickItemPrivate::get(item: oldSubFocusItem)->updateSubFocusItem(scope: this, focus: false);
7934 QQuickItemPrivate::get(item: oldSubFocusItem)->focus = false;
7935 changed << oldSubFocusItem;
7936 }
7937
7938 d->focus = focus;
7939 changed << this;
7940 notifyListeners = true;
7941 emit focusChanged(focus);
7942
7943 QQuickDeliveryAgentPrivate::notifyFocusChangesRecur(item: changed.data(), remaining: changed.size() - 1, reason);
7944 }
7945 if (notifyListeners)
7946 d->notifyChangeListeners(changeTypes: QQuickItemPrivate::Focus, function: &QQuickItemChangeListener::itemFocusChanged, args: this, args&: reason);
7947}
7948
7949/*!
7950 Returns true if this item is a focus scope, and false otherwise.
7951 */
7952bool QQuickItem::isFocusScope() const
7953{
7954 return flags() & ItemIsFocusScope;
7955}
7956
7957/*!
7958 If this item is a focus scope, this returns the item in its focus chain
7959 that currently has focus.
7960
7961 Returns \nullptr if this item is not a focus scope.
7962 */
7963QQuickItem *QQuickItem::scopedFocusItem() const
7964{
7965 Q_D(const QQuickItem);
7966 if (!isFocusScope())
7967 return nullptr;
7968 else
7969 return d->subFocusItem;
7970}
7971
7972/*!
7973 \qmlproperty enumeration QtQuick::Item::focusPolicy
7974 \since 6.7
7975
7976 This property determines the way the item accepts focus.
7977
7978 \value Qt.TabFocus The item accepts focus by tabbing.
7979 \value Qt.ClickFocus The item accepts focus by clicking.
7980 \value Qt.StrongFocus The item accepts focus by both tabbing and clicking.
7981 \value Qt.WheelFocus The item accepts focus by tabbing, clicking, and using the mouse wheel.
7982 \value Qt.NoFocus The item does not accept focus.
7983
7984 \note This property was a member of the \l[QML]{Control} QML type in Qt 6.6 and earlier.
7985*/
7986/*!
7987 \property QQuickItem::focusPolicy
7988 \since 6.7
7989
7990 This property determines the way the item accepts focus.
7991
7992*/
7993Qt::FocusPolicy QQuickItem::focusPolicy() const
7994{
7995 Q_D(const QQuickItem);
7996 uint policy = d->focusPolicy;
7997 if (activeFocusOnTab())
7998 policy |= Qt::TabFocus;
7999 return static_cast<Qt::FocusPolicy>(policy);
8000}
8001
8002/*!
8003 Sets the focus policy of this item to \a policy.
8004
8005 \sa focusPolicy()
8006*/
8007void QQuickItem::setFocusPolicy(Qt::FocusPolicy policy)
8008{
8009 Q_D(QQuickItem);
8010 if (d->focusPolicy == policy)
8011 return;
8012
8013 d->focusPolicy = policy;
8014 setActiveFocusOnTab(policy & Qt::TabFocus);
8015 emit focusPolicyChanged(policy);
8016}
8017
8018/*!
8019 Returns \c true if this item is an ancestor of \a child (i.e., if this item
8020 is \a child's parent, or one of \a child's parent's ancestors).
8021
8022 \since 5.7
8023
8024 \sa parentItem()
8025 */
8026bool QQuickItem::isAncestorOf(const QQuickItem *child) const
8027{
8028 if (!child || child == this)
8029 return false;
8030 const QQuickItem *ancestor = child;
8031 while ((ancestor = ancestor->parentItem())) {
8032 if (ancestor == this)
8033 return true;
8034 }
8035 return false;
8036}
8037
8038/*!
8039 Returns the mouse buttons accepted by this item.
8040
8041 The default value is Qt::NoButton; that is, no mouse buttons are accepted.
8042
8043 If an item does not accept the mouse button for a particular mouse event,
8044 the mouse event will not be delivered to the item and will be delivered
8045 to the next item in the item hierarchy instead.
8046
8047 \sa acceptTouchEvents()
8048*/
8049Qt::MouseButtons QQuickItem::acceptedMouseButtons() const
8050{
8051 Q_D(const QQuickItem);
8052 return d->acceptedMouseButtons();
8053}
8054
8055/*!
8056 Sets the mouse buttons accepted by this item to \a buttons.
8057
8058 \note In Qt 5, calling setAcceptedMouseButtons() implicitly caused
8059 an item to receive touch events as well as mouse events; but it was
8060 recommended to call setAcceptTouchEvents() to subscribe for them.
8061 In Qt 6, it is necessary to call setAcceptTouchEvents() to continue
8062 to receive them.
8063*/
8064void QQuickItem::setAcceptedMouseButtons(Qt::MouseButtons buttons)
8065{
8066 Q_D(QQuickItem);
8067 d->extra.setTag(d->extra.tag().setFlag(flag: QQuickItemPrivate::LeftMouseButtonAccepted, on: buttons & Qt::LeftButton));
8068
8069 buttons &= ~Qt::LeftButton;
8070 if (buttons || d->extra.isAllocated()) {
8071 d->extra.value().acceptedMouseButtonsWithoutHandlers = buttons;
8072 d->extra.value().acceptedMouseButtons = d->extra->pointerHandlers.isEmpty() ? buttons : Qt::AllButtons;
8073 }
8074}
8075
8076/*!
8077 Returns whether pointer events intended for this item's children should be
8078 filtered through this item.
8079
8080 If both this item and a child item have acceptTouchEvents() \c true, then
8081 when a touch interaction occurs, this item will filter the touch event.
8082 But if either this item or the child cannot handle touch events,
8083 childMouseEventFilter() will be called with a synthesized mouse event.
8084
8085 \sa setFiltersChildMouseEvents(), childMouseEventFilter()
8086 */
8087bool QQuickItem::filtersChildMouseEvents() const
8088{
8089 Q_D(const QQuickItem);
8090 return d->filtersChildMouseEvents;
8091}
8092
8093/*!
8094 Sets whether pointer events intended for this item's children should be
8095 filtered through this item.
8096
8097 If \a filter is true, childMouseEventFilter() will be called when
8098 a pointer event is triggered for a child item.
8099
8100 \sa filtersChildMouseEvents()
8101 */
8102void QQuickItem::setFiltersChildMouseEvents(bool filter)
8103{
8104 Q_D(QQuickItem);
8105 d->filtersChildMouseEvents = filter;
8106}
8107
8108/*!
8109 \internal
8110 */
8111bool QQuickItem::isUnderMouse() const
8112{
8113 Q_D(const QQuickItem);
8114 if (!d->window)
8115 return false;
8116
8117 // QQuickWindow handles QEvent::Leave to reset the lastMousePosition
8118 // FIXME: Using QPointF() as the reset value means an item will not be
8119 // under the mouse if the mouse is at 0,0 of the window.
8120 if (const_cast<QQuickItemPrivate *>(d)->deliveryAgentPrivate()->lastMousePosition == QPointF())
8121 return false;
8122
8123 QPointF cursorPos = QGuiApplicationPrivate::lastCursorPosition;
8124 return contains(point: mapFromScene(point: d->window->mapFromGlobal(pos: cursorPos)));
8125}
8126
8127/*!
8128 Returns whether hover events are accepted by this item.
8129
8130 The default value is false.
8131
8132 If this is false, then the item will not receive any hover events through
8133 the hoverEnterEvent(), hoverMoveEvent() and hoverLeaveEvent() functions.
8134*/
8135bool QQuickItem::acceptHoverEvents() const
8136{
8137 Q_D(const QQuickItem);
8138 return d->hoverEnabled;
8139}
8140
8141/*!
8142 If \a enabled is true, this sets the item to accept hover events;
8143 otherwise, hover events are not accepted by this item.
8144
8145 \sa acceptHoverEvents()
8146*/
8147void QQuickItem::setAcceptHoverEvents(bool enabled)
8148{
8149 Q_D(QQuickItem);
8150 d->hoverEnabled = enabled;
8151 d->setHasHoverInChild(enabled);
8152 // The DA needs to resolve which items and handlers should now be hovered or unhovered.
8153 // Marking this item dirty ensures that flushFrameSynchronousEvents() will be called from the render loop,
8154 // even if this change is not in response to a mouse event and no item has already marked itself dirty.
8155 d->dirty(type: QQuickItemPrivate::Content);
8156}
8157
8158/*!
8159 Returns whether touch events are accepted by this item.
8160
8161 The default value is \c false.
8162
8163 If this is \c false, then the item will not receive any touch events through
8164 the touchEvent() function.
8165
8166 \since 5.10
8167*/
8168bool QQuickItem::acceptTouchEvents() const
8169{
8170 Q_D(const QQuickItem);
8171 return d->touchEnabled;
8172}
8173
8174/*!
8175 If \a enabled is true, this sets the item to accept touch events;
8176 otherwise, touch events are not accepted by this item.
8177
8178 \since 5.10
8179
8180 \sa acceptTouchEvents()
8181*/
8182void QQuickItem::setAcceptTouchEvents(bool enabled)
8183{
8184 Q_D(QQuickItem);
8185 d->touchEnabled = enabled;
8186}
8187
8188void QQuickItemPrivate::setHasCursorInChild(bool hc)
8189{
8190#if QT_CONFIG(cursor)
8191 Q_Q(QQuickItem);
8192
8193 // if we're asked to turn it off (because of an unsetcursor call, or a node
8194 // removal) then we should make sure it's really ok to turn it off.
8195 if (!hc && subtreeCursorEnabled) {
8196 if (hasCursor)
8197 return; // nope! sorry, I have a cursor myself
8198 for (QQuickItem *otherChild : std::as_const(t&: childItems)) {
8199 QQuickItemPrivate *otherChildPrivate = QQuickItemPrivate::get(item: otherChild);
8200 if (otherChildPrivate->subtreeCursorEnabled || otherChildPrivate->hasCursor)
8201 return; // nope! sorry, something else wants it kept on.
8202 }
8203 }
8204
8205 subtreeCursorEnabled = hc;
8206 QQuickItem *parent = q->parentItem();
8207 if (parent) {
8208 QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(item: parent);
8209 parentPrivate->setHasCursorInChild(hc);
8210 }
8211#else
8212 Q_UNUSED(hc);
8213#endif
8214}
8215
8216void QQuickItemPrivate::setHasHoverInChild(bool hasHover)
8217{
8218 Q_Q(QQuickItem);
8219
8220 // if we're asked to turn it off (because of a setAcceptHoverEvents call, or a node
8221 // removal) then we should make sure it's really ok to turn it off.
8222 if (!hasHover && subtreeHoverEnabled) {
8223 if (hoverEnabled)
8224 return; // nope! sorry, I need hover myself
8225 if (hasEnabledHoverHandlers())
8226 return; // nope! sorry, this item has enabled HoverHandlers
8227
8228 for (QQuickItem *otherChild : std::as_const(t&: childItems)) {
8229 QQuickItemPrivate *otherChildPrivate = QQuickItemPrivate::get(item: otherChild);
8230 if (otherChildPrivate->subtreeHoverEnabled || otherChildPrivate->hoverEnabled)
8231 return; // nope! sorry, something else wants it kept on.
8232 if (otherChildPrivate->hasEnabledHoverHandlers())
8233 return; // nope! sorry, we have pointer handlers which are interested.
8234 }
8235 }
8236
8237 qCDebug(lcHoverTrace) << q << subtreeHoverEnabled << "->" << hasHover;
8238 subtreeHoverEnabled = hasHover;
8239 QQuickItem *parent = q->parentItem();
8240 if (parent) {
8241 QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(item: parent);
8242 parentPrivate->setHasHoverInChild(hasHover);
8243 }
8244}
8245
8246#if QT_CONFIG(cursor)
8247
8248/*!
8249 Returns the cursor shape for this item.
8250
8251 The mouse cursor will assume this shape when it is over this
8252 item, unless an override cursor is set.
8253 See the \l{Qt::CursorShape}{list of predefined cursor objects} for a
8254 range of useful shapes.
8255
8256 If no cursor shape has been set this returns a cursor with the Qt::ArrowCursor shape, however
8257 another cursor shape may be displayed if an overlapping item has a valid cursor.
8258
8259 \sa setCursor(), unsetCursor()
8260*/
8261
8262QCursor QQuickItem::cursor() const
8263{
8264 Q_D(const QQuickItem);
8265 return d->extra.isAllocated()
8266 ? d->extra->cursor
8267 : QCursor();
8268}
8269
8270/*!
8271 Sets the \a cursor shape for this item.
8272
8273 \sa cursor(), unsetCursor()
8274*/
8275
8276void QQuickItem::setCursor(const QCursor &cursor)
8277{
8278 Q_D(QQuickItem);
8279
8280 Qt::CursorShape oldShape = d->extra.isAllocated() ? d->extra->cursor.shape() : Qt::ArrowCursor;
8281 qCDebug(lcHoverTrace) << oldShape << "->" << cursor.shape();
8282
8283 if (oldShape != cursor.shape() || oldShape >= Qt::LastCursor || cursor.shape() >= Qt::LastCursor) {
8284 d->extra.value().cursor = cursor;
8285 if (d->window) {
8286 QWindow *renderWindow = QQuickRenderControl::renderWindowFor(win: d->window);
8287 QWindow *window = renderWindow ? renderWindow : d->window; // this may not be a QQuickWindow
8288 if (QQuickWindowPrivate::get(c: d->window)->cursorItem == this)
8289 window->setCursor(cursor);
8290 }
8291 }
8292
8293 QPointF updateCursorPos;
8294 if (!d->hasCursor) {
8295 d->hasCursor = true;
8296 if (d->window) {
8297 QWindow *renderWindow = QQuickRenderControl::renderWindowFor(win: d->window);
8298 QWindow *window = renderWindow ? renderWindow : d->window;
8299 QPointF pos = window->mapFromGlobal(pos: QGuiApplicationPrivate::lastCursorPosition);
8300 if (contains(point: mapFromScene(point: pos)))
8301 updateCursorPos = pos;
8302 }
8303 }
8304 d->setHasCursorInChild(d->hasCursor || d->hasCursorHandler);
8305 if (!updateCursorPos.isNull())
8306 QQuickWindowPrivate::get(c: d->window)->updateCursor(scenePos: updateCursorPos);
8307}
8308
8309/*!
8310 Clears the cursor shape for this item.
8311
8312 \sa cursor(), setCursor()
8313*/
8314
8315void QQuickItem::unsetCursor()
8316{
8317 Q_D(QQuickItem);
8318 qCDebug(lcHoverTrace) << "clearing cursor";
8319 if (!d->hasCursor)
8320 return;
8321 d->hasCursor = false;
8322 d->setHasCursorInChild(d->hasCursorHandler);
8323 if (d->extra.isAllocated())
8324 d->extra->cursor = QCursor();
8325
8326 if (d->window) {
8327 QQuickWindowPrivate *windowPrivate = QQuickWindowPrivate::get(c: d->window);
8328 if (windowPrivate->cursorItem == this) {
8329 QPointF pos = d->window->mapFromGlobal(pos: QGuiApplicationPrivate::lastCursorPosition);
8330 windowPrivate->updateCursor(scenePos: pos);
8331 }
8332 }
8333}
8334
8335/*!
8336 \internal
8337 Returns the cursor that should actually be shown, allowing the given
8338 \a handler to override the Item cursor if it is active or hovered.
8339
8340 \sa cursor(), setCursor(), QtQuick::PointerHandler::cursor
8341*/
8342QCursor QQuickItemPrivate::effectiveCursor(const QQuickPointerHandler *handler) const
8343{
8344 Q_Q(const QQuickItem);
8345 if (!handler)
8346 return q->cursor();
8347 bool hoverCursorSet = false;
8348 QCursor hoverCursor;
8349 bool activeCursorSet = false;
8350 QCursor activeCursor;
8351 if (const QQuickHoverHandler *hoverHandler = qobject_cast<const QQuickHoverHandler *>(object: handler)) {
8352 hoverCursorSet = hoverHandler->isCursorShapeExplicitlySet();
8353 hoverCursor = hoverHandler->cursorShape();
8354 } else if (handler->active()) {
8355 activeCursorSet = handler->isCursorShapeExplicitlySet();
8356 activeCursor = handler->cursorShape();
8357 }
8358 if (activeCursorSet)
8359 return activeCursor;
8360 if (hoverCursorSet)
8361 return hoverCursor;
8362 return q->cursor();
8363}
8364
8365/*!
8366 \internal
8367 Returns the Pointer Handler that is currently attempting to set the cursor shape,
8368 or null if there is no such handler.
8369
8370 If there are multiple handlers attempting to set the cursor:
8371 \list
8372 \li an active handler has the highest priority (e.g. a DragHandler being dragged)
8373 \li any HoverHandler that is reacting to a non-mouse device has priority for
8374 kCursorOverrideTimeout ms (a tablet stylus is jittery so that's enough)
8375 \li otherwise a HoverHandler that is reacting to the mouse, if any
8376 \endlist
8377
8378 Within each category, if there are multiple handlers, the last-added one wins
8379 (the one that is declared at the bottom wins, because users may intuitively
8380 think it's "on top" even though there is no Z-order; or, one that is added
8381 in a specific use case overrides an imported component).
8382
8383 \sa QtQuick::PointerHandler::cursor
8384*/
8385QQuickPointerHandler *QQuickItemPrivate::effectiveCursorHandler() const
8386{
8387 if (!hasPointerHandlers())
8388 return nullptr;
8389 QQuickPointerHandler* activeHandler = nullptr;
8390 QQuickPointerHandler* mouseHandler = nullptr;
8391 QQuickPointerHandler* nonMouseHandler = nullptr;
8392 for (QQuickPointerHandler *h : extra->pointerHandlers) {
8393 if (!h->isCursorShapeExplicitlySet())
8394 continue;
8395 QQuickHoverHandler *hoverHandler = qmlobject_cast<QQuickHoverHandler *>(object: h);
8396 // Prioritize any HoverHandler that is reacting to a non-mouse device.
8397 // Otherwise, choose the first hovered handler that is found.
8398 // TODO maybe: there was an idea to add QPointerDevice* as argument to this function
8399 // and check the device type, but why? HoverHandler already does that.
8400 if (!activeHandler && hoverHandler && hoverHandler->isHovered()) {
8401 qCDebug(lcHoverTrace) << hoverHandler << hoverHandler->acceptedDevices() << "wants to set cursor" << hoverHandler->cursorShape();
8402 if (hoverHandler->acceptedDevices().testFlag(flag: QPointingDevice::DeviceType::Mouse)) {
8403 // If there's a conflict, the last-added HoverHandler wins. Maybe the user is overriding a default...
8404 if (mouseHandler && mouseHandler->cursorShape() != hoverHandler->cursorShape()) {
8405 qCDebug(lcHoverTrace) << "mouse cursor conflict:" << mouseHandler << "wants" << mouseHandler->cursorShape()
8406 << "but" << hoverHandler << "wants" << hoverHandler->cursorShape();
8407 }
8408 mouseHandler = hoverHandler;
8409 } else {
8410 // If there's a conflict, the last-added HoverHandler wins.
8411 if (nonMouseHandler && nonMouseHandler->cursorShape() != hoverHandler->cursorShape()) {
8412 qCDebug(lcHoverTrace) << "non-mouse cursor conflict:" << nonMouseHandler << "wants" << nonMouseHandler->cursorShape()
8413 << "but" << hoverHandler << "wants" << hoverHandler->cursorShape();
8414 }
8415 nonMouseHandler = hoverHandler;
8416 }
8417 }
8418 if (!hoverHandler && h->active())
8419 activeHandler = h;
8420 }
8421 if (activeHandler) {
8422 qCDebug(lcHoverTrace) << "active handler choosing cursor" << activeHandler << activeHandler->cursorShape();
8423 return activeHandler;
8424 }
8425 // Mouse events are often synthetic; so if a HoverHandler for a non-mouse device wanted to set the cursor,
8426 // let it win, unless more than kCursorOverrideTimeout ms have passed
8427 // since the last time the non-mouse handler actually reacted to an event.
8428 // We could miss the fact that a tablet stylus has left proximity, because we don't deliver proximity events to windows.
8429 if (nonMouseHandler) {
8430 if (mouseHandler) {
8431 const bool beforeTimeout =
8432 QQuickPointerHandlerPrivate::get(q: mouseHandler)->lastEventTime <
8433 QQuickPointerHandlerPrivate::get(q: nonMouseHandler)->lastEventTime + kCursorOverrideTimeout;
8434 QQuickPointerHandler *winner = (beforeTimeout ? nonMouseHandler : mouseHandler);
8435 qCDebug(lcHoverTrace) << "non-mouse handler reacted last time:" << QQuickPointerHandlerPrivate::get(q: nonMouseHandler)->lastEventTime
8436 << "and mouse handler reacted at time:" << QQuickPointerHandlerPrivate::get(q: mouseHandler)->lastEventTime
8437 << "choosing cursor according to" << winner << winner->cursorShape();
8438 return winner;
8439 }
8440 qCDebug(lcHoverTrace) << "non-mouse handler choosing cursor" << nonMouseHandler << nonMouseHandler->cursorShape();
8441 return nonMouseHandler;
8442 }
8443 if (mouseHandler)
8444 qCDebug(lcHoverTrace) << "mouse handler choosing cursor" << mouseHandler << mouseHandler->cursorShape();
8445 return mouseHandler;
8446}
8447
8448#endif
8449
8450/*!
8451 \deprecated Use QPointerEvent::setExclusiveGrabber().
8452
8453 Grabs the mouse input.
8454
8455 This item will receive all mouse events until ungrabMouse() is called.
8456 Usually this function should not be called, since accepting for example
8457 a mouse press event makes sure that the following events are delivered
8458 to the item.
8459 If an item wants to take over mouse events from the current receiver,
8460 it needs to call this function.
8461
8462 \warning This function should be used with caution.
8463 */
8464void QQuickItem::grabMouse()
8465{
8466 Q_D(QQuickItem);
8467 if (!d->window)
8468 return;
8469 auto da = d->deliveryAgentPrivate();
8470 Q_ASSERT(da);
8471 auto eventInDelivery = da->eventInDelivery();
8472 if (!eventInDelivery) {
8473 qWarning() << "cannot grab mouse: no event is currently being delivered";
8474 return;
8475 }
8476 auto epd = da->mousePointData();
8477 eventInDelivery->setExclusiveGrabber(point: epd->eventPoint, exclusiveGrabber: this);
8478}
8479
8480/*!
8481 \deprecated Use QPointerEvent::setExclusiveGrabber().
8482
8483 Releases the mouse grab following a call to grabMouse().
8484
8485 Note that this function should only be called when the item wants
8486 to stop handling further events. There is no need to call this function
8487 after a release or cancel event since no future events will be received
8488 in any case. No move or release events will be delivered after this
8489 function was called.
8490*/
8491void QQuickItem::ungrabMouse()
8492{
8493 Q_D(QQuickItem);
8494 if (!d->window)
8495 return;
8496 auto da = d->deliveryAgentPrivate();
8497 Q_ASSERT(da);
8498 auto eventInDelivery = da->eventInDelivery();
8499 if (!eventInDelivery) {
8500 // do it the expensive way
8501 da->removeGrabber(grabber: this);
8502 return;
8503 }
8504 const auto &eventPoint = da->mousePointData()->eventPoint;
8505 if (eventInDelivery->exclusiveGrabber(point: eventPoint) == this)
8506 eventInDelivery->setExclusiveGrabber(point: eventPoint, exclusiveGrabber: nullptr);
8507}
8508
8509/*!
8510 Returns whether mouse input should exclusively remain with this item.
8511
8512 \sa setKeepMouseGrab(), QEvent::accept(), QEvent::ignore()
8513 */
8514bool QQuickItem::keepMouseGrab() const
8515{
8516 Q_D(const QQuickItem);
8517 return d->keepMouse;
8518}
8519
8520/*!
8521 Sets whether the mouse input should remain exclusively with this item.
8522
8523 This is useful for items that wish to grab and keep mouse
8524 interaction following a predefined gesture. For example,
8525 an item that is interested in horizontal mouse movement
8526 may set keepMouseGrab to true once a threshold has been
8527 exceeded. Once keepMouseGrab has been set to true, filtering
8528 items will not react to mouse events.
8529
8530 If \a keep is false, a filtering item may steal the grab. For example,
8531 \l Flickable may attempt to steal a mouse grab if it detects that the
8532 user has begun to move the viewport.
8533
8534 \sa keepMouseGrab()
8535 */
8536void QQuickItem::setKeepMouseGrab(bool keep)
8537{
8538 Q_D(QQuickItem);
8539 d->keepMouse = keep;
8540}
8541
8542/*!
8543 \deprecated Use QPointerEvent::setExclusiveGrabber().
8544 Grabs the touch points specified by \a ids.
8545
8546 These touch points will be owned by the item until
8547 they are released. Alternatively, the grab can be stolen
8548 by a filtering item like Flickable. Use setKeepTouchGrab()
8549 to prevent the grab from being stolen.
8550*/
8551void QQuickItem::grabTouchPoints(const QList<int> &ids)
8552{
8553 Q_D(QQuickItem);
8554 auto event = d->deliveryAgentPrivate()->eventInDelivery();
8555 if (Q_UNLIKELY(!event)) {
8556 qWarning() << "cannot grab: no event is currently being delivered";
8557 return;
8558 }
8559 for (auto pt : event->points()) {
8560 if (ids.contains(t: pt.id()))
8561 event->setExclusiveGrabber(point: pt, exclusiveGrabber: this);
8562 }
8563}
8564
8565/*!
8566 \deprecated Use QEventPoint::setExclusiveGrabber() instead.
8567 Ungrabs the touch points owned by this item.
8568*/
8569void QQuickItem::ungrabTouchPoints()
8570{
8571 Q_D(QQuickItem);
8572 if (!d->window)
8573 return;
8574 if (QQuickDeliveryAgentPrivate *da = d->deliveryAgentPrivate())
8575 da->removeGrabber(grabber: this, mouse: false, touch: true);
8576}
8577
8578/*!
8579 Returns whether the touch points grabbed by this item should exclusively
8580 remain with this item.
8581
8582 \sa setKeepTouchGrab(), keepMouseGrab(), QEvent::accept(), QEvent::ignore()
8583*/
8584bool QQuickItem::keepTouchGrab() const
8585{
8586 Q_D(const QQuickItem);
8587 return d->keepTouch;
8588}
8589
8590/*!
8591 Sets whether the touch points grabbed by this item should remain
8592 exclusively with this item.
8593
8594 This is useful for items that wish to grab and keep specific touch
8595 points following a predefined gesture. For example,
8596 an item that is interested in horizontal touch point movement
8597 may set setKeepTouchGrab to true once a threshold has been
8598 exceeded. Once setKeepTouchGrab has been set to true, filtering
8599 items will not react to the relevant touch points.
8600
8601 If \a keep is false, a filtering item may steal the grab. For example,
8602 \l Flickable may attempt to steal a touch point grab if it detects that the
8603 user has begun to move the viewport.
8604
8605 \sa keepTouchGrab(), setKeepMouseGrab()
8606 */
8607void QQuickItem::setKeepTouchGrab(bool keep)
8608{
8609 Q_D(QQuickItem);
8610 d->keepTouch = keep;
8611}
8612
8613/*!
8614 \qmlmethod bool QtQuick::Item::contains(point point)
8615
8616 Returns \c true if this item contains \a point, which is in local coordinates;
8617 returns \c false otherwise. This is the same check that is used for
8618 hit-testing a QEventPoint during event delivery, and is affected by
8619 \l containmentMask if it is set.
8620*/
8621/*!
8622 Returns \c true if this item contains \a point, which is in local coordinates;
8623 returns \c false otherwise.
8624
8625 This function can be overridden in order to handle point collisions in items
8626 with custom shapes. The default implementation checks whether the point is inside
8627 \l containmentMask() if it is set, or inside the bounding box otherwise.
8628
8629 \note This method is used for hit-testing each QEventPoint during event
8630 delivery, so the implementation should be kept as lightweight as possible.
8631*/
8632bool QQuickItem::contains(const QPointF &point) const
8633{
8634 Q_D(const QQuickItem);
8635 if (d->extra.isAllocated() && d->extra->mask) {
8636 if (auto quickMask = qobject_cast<QQuickItem *>(o: d->extra->mask))
8637 return quickMask->contains(point: point - quickMask->position());
8638
8639 bool res = false;
8640 QMetaMethod maskContains = d->extra->mask->metaObject()->method(index: d->extra->maskContainsIndex);
8641 maskContains.invoke(obj: d->extra->mask,
8642 c: Qt::DirectConnection,
8643 Q_RETURN_ARG(bool, res),
8644 Q_ARG(QPointF, point));
8645 return res;
8646 }
8647
8648 qreal x = point.x();
8649 qreal y = point.y();
8650 return x >= 0 && y >= 0 && x < d->width && y < d->height;
8651}
8652
8653/*!
8654 \qmlproperty QObject* QtQuick::Item::containmentMask
8655 \since 5.11
8656 This property holds an optional mask for the Item to be used in the
8657 \l contains() method. Its main use is currently to determine
8658 whether a \l {QPointerEvent}{pointer event} has landed into the item or not.
8659
8660 By default the \c contains() method will return true for any point
8661 within the Item's bounding box. \c containmentMask allows for
8662 more fine-grained control. For example, if a custom C++
8663 QQuickItem subclass with a specialized contains() method
8664 is used as containmentMask:
8665
8666 \code
8667 Item { id: item; containmentMask: AnotherItem { id: anotherItem } }
8668 \endcode
8669
8670 \e{item}'s contains method would then return \c true only if
8671 \e{anotherItem}'s contains() implementation returns \c true.
8672
8673 A \l Shape can be used as a mask, to make an item react to
8674 \l {QPointerEvent}{pointer events} only within a non-rectangular region:
8675
8676 \table
8677 \row
8678 \li \image containmentMask-shape.gif
8679 \li \snippet qml/item/containmentMask-shape.qml 0
8680 \endtable
8681
8682 It is also possible to define the contains method in QML. For example,
8683 to create a circular item that only responds to events within its
8684 actual bounds:
8685
8686 \table
8687 \row
8688 \li \image containmentMask-circle.gif
8689 \li \snippet qml/item/containmentMask-circle-js.qml 0
8690 \endtable
8691
8692 \sa {Qt Quick Examples - Shapes}
8693*/
8694/*!
8695 \property QQuickItem::containmentMask
8696 \since 5.11
8697 This property holds an optional mask to be used in the contains() method,
8698 which is mainly used for hit-testing each \l QPointerEvent.
8699
8700 By default, \l contains() will return \c true for any point
8701 within the Item's bounding box. But any QQuickItem, or any QObject
8702 that implements a function of the form
8703 \code
8704 Q_INVOKABLE bool contains(const QPointF &point) const;
8705 \endcode
8706 can be used as a mask, to defer hit-testing to that object.
8707
8708 \note contains() is called frequently during event delivery.
8709 Deferring hit-testing to another object slows it down somewhat.
8710 containmentMask() can cause performance problems if that object's
8711 contains() method is not efficient. If you implement a custom
8712 QQuickItem subclass, you can alternatively override contains().
8713
8714 \sa contains()
8715*/
8716QObject *QQuickItem::containmentMask() const
8717{
8718 Q_D(const QQuickItem);
8719 if (!d->extra.isAllocated())
8720 return nullptr;
8721 return d->extra->mask.data();
8722}
8723
8724void QQuickItem::setContainmentMask(QObject *mask)
8725{
8726 Q_D(QQuickItem);
8727 const bool extraDataExists = d->extra.isAllocated();
8728 // an Item can't mask itself (to prevent infinite loop in contains())
8729 if (mask == static_cast<QObject *>(this))
8730 return;
8731 // mask is null, and we had no mask
8732 if (!extraDataExists && !mask)
8733 return;
8734 // mask is non-null and the same
8735 if (extraDataExists && d->extra->mask == mask)
8736 return;
8737
8738 QQuickItem *quickMask = d->extra.isAllocated() ? qobject_cast<QQuickItem *>(o: d->extra->mask)
8739 : nullptr;
8740 if (quickMask) {
8741 QQuickItemPrivate *maskPrivate = QQuickItemPrivate::get(item: quickMask);
8742 maskPrivate->registerAsContainmentMask(this, false); // removed from use as my mask
8743 }
8744
8745 if (!extraDataExists)
8746 d->extra.value(); // ensure extra exists
8747 if (mask) {
8748 int methodIndex = mask->metaObject()->indexOfMethod(QByteArrayLiteral("contains(QPointF)"));
8749 if (methodIndex < 0) {
8750 qmlWarning(me: this) << QStringLiteral("QQuickItem: Object set as mask does not have an invokable contains method, ignoring it.");
8751 return;
8752 }
8753 d->extra->maskContainsIndex = methodIndex;
8754 }
8755 d->extra->mask = mask;
8756 quickMask = qobject_cast<QQuickItem *>(o: mask);
8757 if (quickMask) {
8758 QQuickItemPrivate *maskPrivate = QQuickItemPrivate::get(item: quickMask);
8759 maskPrivate->registerAsContainmentMask(this, true); // telling maskPrivate that "this" is using it as mask
8760 }
8761 emit containmentMaskChanged();
8762}
8763
8764/*!
8765 Maps the given \a point in this item's coordinate system to the equivalent
8766 point within \a item's coordinate system, and returns the mapped
8767 coordinate.
8768
8769 \input item.qdocinc mapping
8770
8771 If \a item is \nullptr, this maps \a point to the coordinate system of the
8772 scene.
8773
8774 \sa {Concepts - Visual Coordinates in Qt Quick}
8775*/
8776QPointF QQuickItem::mapToItem(const QQuickItem *item, const QPointF &point) const
8777{
8778 QPointF p = mapToScene(point);
8779 if (item) {
8780 const auto *itemWindow = item->window();
8781 const auto *thisWindow = window();
8782 if (thisWindow && itemWindow && itemWindow != thisWindow)
8783 p = itemWindow->mapFromGlobal(pos: thisWindow->mapToGlobal(pos: p));
8784
8785 p = item->mapFromScene(point: p);
8786 }
8787 return p;
8788}
8789
8790/*!
8791 Maps the given \a point in this item's coordinate system to the equivalent
8792 point within the scene's coordinate system, and returns the mapped
8793 coordinate.
8794
8795 \input item.qdocinc mapping
8796
8797 \sa {Concepts - Visual Coordinates in Qt Quick}
8798*/
8799QPointF QQuickItem::mapToScene(const QPointF &point) const
8800{
8801 Q_D(const QQuickItem);
8802 return d->itemToWindowTransform().map(p: point);
8803}
8804
8805/*!
8806 Maps the given \a point in this item's coordinate system to the equivalent
8807 point within global screen coordinate system, and returns the mapped
8808 coordinate.
8809
8810 \input item.qdocinc mapping
8811
8812 For example, this may be helpful to add a popup to a Qt Quick component.
8813
8814 \note Window positioning is done by the window manager and this value is
8815 treated only as a hint. So, the resulting window position may differ from
8816 what is expected.
8817
8818 \since 5.7
8819
8820 \sa {Concepts - Visual Coordinates in Qt Quick}
8821*/
8822QPointF QQuickItem::mapToGlobal(const QPointF &point) const
8823{
8824 Q_D(const QQuickItem);
8825
8826 if (Q_UNLIKELY(d->window == nullptr))
8827 return mapToScene(point);
8828
8829 QPoint renderOffset;
8830 QWindow *renderWindow = QQuickRenderControl::renderWindowFor(win: d->window, offset: &renderOffset);
8831 QWindow *effectiveWindow = renderWindow ? renderWindow : d->window;
8832 return effectiveWindow->mapToGlobal(pos: (mapToScene(point) + renderOffset));
8833}
8834
8835/*!
8836 Maps the given \a rect in this item's coordinate system to the equivalent
8837 rectangular area within \a item's coordinate system, and returns the mapped
8838 rectangle value.
8839
8840 \input item.qdocinc mapping
8841
8842 If \a item is \nullptr, this maps \a rect to the coordinate system of the
8843 scene.
8844
8845 \sa {Concepts - Visual Coordinates in Qt Quick}
8846*/
8847QRectF QQuickItem::mapRectToItem(const QQuickItem *item, const QRectF &rect) const
8848{
8849 Q_D(const QQuickItem);
8850 QTransform t = d->itemToWindowTransform();
8851 if (item)
8852 t *= QQuickItemPrivate::get(item)->windowToItemTransform();
8853 return t.mapRect(rect);
8854}
8855
8856/*!
8857 Maps the given \a rect in this item's coordinate system to the equivalent
8858 rectangular area within the scene's coordinate system, and returns the mapped
8859 rectangle value.
8860
8861 \input item.qdocinc mapping
8862
8863 \sa {Concepts - Visual Coordinates in Qt Quick}
8864*/
8865QRectF QQuickItem::mapRectToScene(const QRectF &rect) const
8866{
8867 Q_D(const QQuickItem);
8868 return d->itemToWindowTransform().mapRect(rect);
8869}
8870
8871/*!
8872 Maps the given \a point in \a item's coordinate system to the equivalent
8873 point within this item's coordinate system, and returns the mapped
8874 coordinate.
8875
8876 \input item.qdocinc mapping
8877
8878 If \a item is \nullptr, this maps \a point from the coordinate system of the
8879 scene.
8880
8881 \sa {Concepts - Visual Coordinates in Qt Quick}
8882*/
8883QPointF QQuickItem::mapFromItem(const QQuickItem *item, const QPointF &point) const
8884{
8885 QPointF p = point;
8886 if (item) {
8887 p = item->mapToScene(point);
8888 const auto *itemWindow = item->window();
8889 const auto *thisWindow = window();
8890 if (thisWindow && itemWindow && itemWindow != thisWindow)
8891 p = thisWindow->mapFromGlobal(pos: itemWindow->mapToGlobal(pos: p));
8892 }
8893 return mapFromScene(point: p);
8894}
8895
8896/*!
8897 Maps the given \a point in the scene's coordinate system to the equivalent
8898 point within this item's coordinate system, and returns the mapped
8899 coordinate.
8900
8901 \input item.qdocinc mapping
8902
8903 \sa {Concepts - Visual Coordinates in Qt Quick}
8904*/
8905QPointF QQuickItem::mapFromScene(const QPointF &point) const
8906{
8907 Q_D(const QQuickItem);
8908 return d->windowToItemTransform().map(p: point);
8909}
8910
8911/*!
8912 Maps the given \a point in the global screen coordinate system to the
8913 equivalent point within this item's coordinate system, and returns the
8914 mapped coordinate.
8915
8916 \input item.qdocinc mapping
8917
8918 For example, this may be helpful to add a popup to a Qt Quick component.
8919
8920 \note Window positioning is done by the window manager and this value is
8921 treated only as a hint. So, the resulting window position may differ from
8922 what is expected.
8923
8924 \note If this item is in a subscene, e.g. mapped onto a 3D
8925 \l [QtQuick3D QML] {Model}{Model} object, the UV mapping is incorporated
8926 into this transformation, so that it really goes from screen coordinates to
8927 this item's coordinates, as long as \a point is actually within this item's bounds.
8928 The other mapping functions do not yet work that way.
8929
8930 \since 5.7
8931
8932 \sa {Concepts - Visual Coordinates in Qt Quick}
8933*/
8934QPointF QQuickItem::mapFromGlobal(const QPointF &point) const
8935{
8936 Q_D(const QQuickItem);
8937
8938 QPointF scenePoint;
8939 if (Q_LIKELY(d->window)) {
8940 QPoint renderOffset;
8941 QWindow *renderWindow = QQuickRenderControl::renderWindowFor(win: d->window, offset: &renderOffset);
8942 QWindow *effectiveWindow = renderWindow ? renderWindow : d->window;
8943 scenePoint = effectiveWindow->mapFromGlobal(pos: point) - renderOffset;
8944 } else {
8945 scenePoint = point;
8946 }
8947
8948 if (auto da = QQuickDeliveryAgentPrivate::currentOrItemDeliveryAgent(item: this)) {
8949 if (auto sceneTransform = da->sceneTransform())
8950 scenePoint = sceneTransform->map(point: scenePoint);
8951 }
8952 return mapFromScene(point: scenePoint);
8953}
8954
8955/*!
8956 Maps the given \a rect in \a item's coordinate system to the equivalent
8957 rectangular area within this item's coordinate system, and returns the mapped
8958 rectangle value.
8959
8960 \input item.qdocinc mapping
8961
8962 If \a item is \nullptr, this maps \a rect from the coordinate system of the
8963 scene.
8964
8965 \sa {Concepts - Visual Coordinates in Qt Quick}
8966*/
8967QRectF QQuickItem::mapRectFromItem(const QQuickItem *item, const QRectF &rect) const
8968{
8969 Q_D(const QQuickItem);
8970 QTransform t = item?QQuickItemPrivate::get(item)->itemToWindowTransform():QTransform();
8971 t *= d->windowToItemTransform();
8972 return t.mapRect(rect);
8973}
8974
8975/*!
8976 Maps the given \a rect in the scene's coordinate system to the equivalent
8977 rectangular area within this item's coordinate system, and returns the mapped
8978 rectangle value.
8979
8980 \input item.qdocinc mapping
8981
8982 \sa {Concepts - Visual Coordinates in Qt Quick}
8983*/
8984QRectF QQuickItem::mapRectFromScene(const QRectF &rect) const
8985{
8986 Q_D(const QQuickItem);
8987 return d->windowToItemTransform().mapRect(rect);
8988}
8989
8990/*!
8991 \property QQuickItem::anchors
8992 \internal
8993*/
8994
8995/*!
8996 \property QQuickItem::left
8997 \internal
8998*/
8999
9000/*!
9001 \property QQuickItem::right
9002 \internal
9003*/
9004
9005/*!
9006 \property QQuickItem::horizontalCenter
9007 \internal
9008*/
9009
9010/*!
9011 \property QQuickItem::top
9012 \internal
9013*/
9014
9015/*!
9016 \property QQuickItem::bottom
9017 \internal
9018*/
9019
9020/*!
9021 \property QQuickItem::verticalCenter
9022 \internal
9023*/
9024
9025/*!
9026 \property QQuickItem::baseline
9027 \internal
9028*/
9029
9030/*!
9031 \property QQuickItem::data
9032 \internal
9033*/
9034
9035/*!
9036 \property QQuickItem::resources
9037 \internal
9038*/
9039
9040/*!
9041 \reimp
9042 */
9043bool QQuickItem::event(QEvent *ev)
9044{
9045 Q_D(QQuickItem);
9046
9047 switch (ev->type()) {
9048#if QT_CONFIG(im)
9049 case QEvent::InputMethodQuery: {
9050 QInputMethodQueryEvent *query = static_cast<QInputMethodQueryEvent *>(ev);
9051 Qt::InputMethodQueries queries = query->queries();
9052 for (uint i = 0; i < 32; ++i) {
9053 Qt::InputMethodQuery q = (Qt::InputMethodQuery)(int)(queries & (1<<i));
9054 if (q) {
9055 QVariant v = inputMethodQuery(query: q);
9056 query->setValue(query: q, value: v);
9057 }
9058 }
9059 query->accept();
9060 break;
9061 }
9062 case QEvent::InputMethod:
9063 inputMethodEvent(event: static_cast<QInputMethodEvent *>(ev));
9064 break;
9065#endif // im
9066 case QEvent::TouchBegin:
9067 case QEvent::TouchUpdate:
9068 case QEvent::TouchEnd:
9069 case QEvent::TouchCancel:
9070 case QEvent::MouseButtonPress:
9071 case QEvent::MouseButtonRelease:
9072 case QEvent::MouseButtonDblClick:
9073#if QT_CONFIG(wheelevent)
9074 case QEvent::Wheel:
9075#endif
9076 d->deliverPointerEvent(event: ev);
9077 break;
9078 case QEvent::StyleAnimationUpdate:
9079 if (isVisible()) {
9080 ev->accept();
9081 update();
9082 }
9083 break;
9084 case QEvent::HoverEnter:
9085 hoverEnterEvent(event: static_cast<QHoverEvent*>(ev));
9086 break;
9087 case QEvent::HoverLeave:
9088 hoverLeaveEvent(event: static_cast<QHoverEvent*>(ev));
9089 break;
9090 case QEvent::HoverMove:
9091 hoverMoveEvent(event: static_cast<QHoverEvent*>(ev));
9092 break;
9093 case QEvent::KeyPress:
9094 case QEvent::KeyRelease:
9095 d->deliverKeyEvent(e: static_cast<QKeyEvent*>(ev));
9096 break;
9097 case QEvent::ShortcutOverride:
9098 d->deliverShortcutOverrideEvent(event: static_cast<QKeyEvent*>(ev));
9099 break;
9100 case QEvent::FocusIn:
9101 focusInEvent(event: static_cast<QFocusEvent*>(ev));
9102 break;
9103 case QEvent::FocusOut:
9104 focusOutEvent(event: static_cast<QFocusEvent*>(ev));
9105 break;
9106 case QEvent::MouseMove:
9107 mouseMoveEvent(event: static_cast<QMouseEvent*>(ev));
9108 break;
9109#if QT_CONFIG(quick_draganddrop)
9110 case QEvent::DragEnter:
9111 dragEnterEvent(event: static_cast<QDragEnterEvent*>(ev));
9112 break;
9113 case QEvent::DragLeave:
9114 dragLeaveEvent(event: static_cast<QDragLeaveEvent*>(ev));
9115 break;
9116 case QEvent::DragMove:
9117 dragMoveEvent(event: static_cast<QDragMoveEvent*>(ev));
9118 break;
9119 case QEvent::Drop:
9120 dropEvent(event: static_cast<QDropEvent*>(ev));
9121 break;
9122#endif // quick_draganddrop
9123#if QT_CONFIG(gestures)
9124 case QEvent::NativeGesture:
9125 ev->ignore();
9126 break;
9127#endif // gestures
9128 case QEvent::LanguageChange:
9129 case QEvent::LocaleChange:
9130 for (QQuickItem *item : std::as_const(t&: d->childItems))
9131 QCoreApplication::sendEvent(receiver: item, event: ev);
9132 break;
9133 case QEvent::WindowActivate:
9134 case QEvent::WindowDeactivate:
9135 if (d->providesPalette())
9136 d->setCurrentColorGroup();
9137 for (QQuickItem *item : std::as_const(t&: d->childItems))
9138 QCoreApplication::sendEvent(receiver: item, event: ev);
9139 break;
9140 case QEvent::ApplicationPaletteChange:
9141 for (QQuickItem *item : std::as_const(t&: d->childItems))
9142 QCoreApplication::sendEvent(receiver: item, event: ev);
9143 break;
9144 default:
9145 return QObject::event(event: ev);
9146 }
9147
9148 return true;
9149}
9150
9151#ifndef QT_NO_DEBUG_STREAM
9152QDebug operator<<(QDebug debug,
9153#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0)
9154 const
9155#endif
9156 QQuickItem *item)
9157{
9158 QDebugStateSaver saver(debug);
9159 debug.nospace();
9160 if (!item) {
9161 debug << "QQuickItem(nullptr)";
9162 return debug;
9163 }
9164
9165 const QRectF rect(item->position(), QSizeF(item->width(), item->height()));
9166
9167 debug << item->metaObject()->className() << '(' << static_cast<void *>(item);
9168
9169 // Deferred properties will cause recursion when calling nameForObject
9170 // before the component is completed, so guard against this situation.
9171 if (item->isComponentComplete()) {
9172 if (QQmlContext *context = qmlContext(item)) {
9173 const auto objectId = context->nameForObject(item);
9174 if (!objectId.isEmpty())
9175 debug << ", id=" << objectId;
9176 }
9177 }
9178 if (!item->objectName().isEmpty())
9179 debug << ", name=" << item->objectName();
9180 debug << ", parent=" << static_cast<void *>(item->parentItem())
9181 << ", geometry=";
9182 QtDebugUtils::formatQRect(debug, rect);
9183 if (const qreal z = item->z())
9184 debug << ", z=" << z;
9185 if (item->flags().testFlag(flag: QQuickItem::ItemIsViewport))
9186 debug << " \U0001f5bc"; // frame with picture
9187 if (item->flags().testFlag(flag: QQuickItem::ItemObservesViewport))
9188 debug << " \u23ff"; // observer eye
9189 debug << ')';
9190 return debug;
9191}
9192#endif // QT_NO_DEBUG_STREAM
9193
9194/*!
9195 \fn bool QQuickItem::isTextureProvider() const
9196
9197 Returns true if this item is a texture provider. The default
9198 implementation returns false.
9199
9200 This function can be called from any thread.
9201 */
9202
9203bool QQuickItem::isTextureProvider() const
9204{
9205#if QT_CONFIG(quick_shadereffect)
9206 Q_D(const QQuickItem);
9207 return d->extra.isAllocated() && d->extra->layer && d->extra->layer->effectSource() ?
9208 d->extra->layer->effectSource()->isTextureProvider() : false;
9209#else
9210 return false;
9211#endif
9212}
9213
9214/*!
9215 \fn QSGTextureProvider *QQuickItem::textureProvider() const
9216
9217 Returns the texture provider for an item. The default implementation
9218 returns \nullptr.
9219
9220 This function may only be called on the rendering thread.
9221 */
9222
9223QSGTextureProvider *QQuickItem::textureProvider() const
9224{
9225#if QT_CONFIG(quick_shadereffect)
9226 Q_D(const QQuickItem);
9227 return d->extra.isAllocated() && d->extra->layer && d->extra->layer->effectSource() ?
9228 d->extra->layer->effectSource()->textureProvider() : nullptr;
9229#else
9230 return 0;
9231#endif
9232}
9233
9234/*!
9235 \since 6.0
9236 \qmlproperty Palette QtQuick::Item::palette
9237
9238 This property holds the palette currently set for the item.
9239
9240 This property describes the item's requested palette. The palette is used by the item's style
9241 when rendering all controls, and is available as a means to ensure that custom controls can
9242 maintain consistency with the native platform's native look and feel. It's common that
9243 different platforms, or different styles, define different palettes for an application.
9244
9245 The default palette depends on the system environment. ApplicationWindow maintains a
9246 system/theme palette which serves as a default for all controls. There may also be special
9247 palette defaults for certain types of controls. You can also set the default palette for
9248 controls by either:
9249
9250 \list
9251 \li passing a custom palette to QGuiApplication::setPalette(), before loading any QML; or
9252 \li specifying the colors in the \l {Qt Quick Controls 2 Configuration File}
9253 {qtquickcontrols2.conf file}.
9254 \endlist
9255
9256 Items propagate explicit palette properties from parents to children. If you change a specific
9257 property on a items's palette, that property propagates to all of the item's children,
9258 overriding any system defaults for that property.
9259
9260 \code
9261 Item {
9262 palette {
9263 buttonText: "maroon"
9264 button: "lavender"
9265 }
9266
9267 Button {
9268 text: "Click Me"
9269 }
9270 }
9271 \endcode
9272
9273 \sa Window::palette, Popup::palette, ColorGroup, Palette, SystemPalette
9274*/
9275
9276#if QT_CONFIG(quick_shadereffect)
9277/*!
9278 \property QQuickItem::layer
9279 \internal
9280 */
9281QQuickItemLayer *QQuickItemPrivate::layer() const
9282{
9283 if (!extra.isAllocated() || !extra->layer) {
9284 extra.value().layer = new QQuickItemLayer(const_cast<QQuickItem *>(q_func()));
9285 if (!componentComplete)
9286 extra->layer->classBegin();
9287 }
9288 return extra->layer;
9289}
9290#endif
9291
9292/*!
9293 \internal
9294 Create a modified copy of the given \a event intended for delivery to this
9295 item, containing pointers to only the QEventPoint instances that are
9296 relevant to this item, and transforming their positions to this item's
9297 coordinate system.
9298
9299 Returns an invalid event with type \l QEvent::None if all points are
9300 stationary; or there are no points inside the item; or none of the points
9301 were pressed inside, neither the item nor any of its handlers is grabbing
9302 any of them, and \a isFiltering is false.
9303
9304 When \a isFiltering is true, it is assumed that the item cares about all
9305 points which are inside its bounds, because most filtering items need to
9306 monitor eventpoint movements until a drag threshold is exceeded or the
9307 requirements for a gesture to be recognized are met in some other way.
9308*/
9309void QQuickItemPrivate::localizedTouchEvent(const QTouchEvent *event, bool isFiltering, QMutableTouchEvent *localized)
9310{
9311 Q_Q(QQuickItem);
9312 QList<QEventPoint> touchPoints;
9313 QEventPoint::States eventStates;
9314
9315 bool anyPressOrReleaseInside = false;
9316 bool anyGrabber = false;
9317 for (auto &p : event->points()) {
9318 if (p.isAccepted())
9319 continue;
9320
9321 // include points where item is the grabber, or if any of its handlers is the grabber while some parent is filtering
9322 auto pointGrabber = event->exclusiveGrabber(point: p);
9323 bool isGrabber = (pointGrabber == q);
9324 if (!isGrabber && pointGrabber && isFiltering) {
9325 auto handlerGrabber = qmlobject_cast<QQuickPointerHandler *>(object: pointGrabber);
9326 if (handlerGrabber && handlerGrabber->parentItem() == q)
9327 isGrabber = true;
9328 }
9329 if (isGrabber)
9330 anyGrabber = true;
9331
9332 // include points inside the bounds if no other item is the grabber or if the item is filtering
9333 const auto localPos = q->mapFromScene(point: p.scenePosition());
9334 bool isInside = q->contains(point: localPos);
9335 bool hasAnotherGrabber = pointGrabber && pointGrabber != q;
9336 // if there's no exclusive grabber, look for passive grabbers during filtering
9337 if (isFiltering && !pointGrabber) {
9338 const auto pg = event->passiveGrabbers(point: p);
9339 if (!pg.isEmpty()) {
9340 // It seems unlikely to have multiple passive grabbers of one eventpoint with different grandparents.
9341 // So hopefully if we start from one passive grabber and go up the parent chain from there,
9342 // we will find any filtering parent items that exist.
9343 auto handler = qmlobject_cast<QQuickPointerHandler *>(object: pg.constFirst());
9344 if (handler)
9345 pointGrabber = handler->parentItem();
9346 }
9347 }
9348
9349 // filtering: (childMouseEventFilter) include points that are grabbed by children of the target item
9350 bool grabberIsChild = false;
9351 auto parent = qobject_cast<QQuickItem*>(o: pointGrabber);
9352 while (isFiltering && parent) {
9353 if (parent == q) {
9354 grabberIsChild = true;
9355 break;
9356 }
9357 parent = parent->parentItem();
9358 }
9359
9360 bool filterRelevant = isFiltering && grabberIsChild;
9361 if (!(isGrabber || (isInside && (!hasAnotherGrabber || isFiltering)) || filterRelevant))
9362 continue;
9363 if ((p.state() == QEventPoint::State::Pressed || p.state() == QEventPoint::State::Released) && isInside)
9364 anyPressOrReleaseInside = true;
9365 QEventPoint pCopy(p);
9366 eventStates |= p.state();
9367 if (p.state() == QEventPoint::State::Released)
9368 QMutableEventPoint::detach(p&: pCopy);
9369 QMutableEventPoint::setPosition(p&: pCopy, arg: localPos);
9370 touchPoints.append(t: std::move(pCopy));
9371 }
9372
9373 // Now touchPoints will have only points which are inside the item.
9374 // But if none of them were just pressed inside, and the item has no other reason to care, ignore them anyway.
9375 if (touchPoints.isEmpty() || (!anyPressOrReleaseInside && !anyGrabber && !isFiltering)) {
9376 *localized = QMutableTouchEvent(QEvent::None);
9377 return;
9378 }
9379
9380 // if all points have the same state, set the event type accordingly
9381 QEvent::Type eventType = event->type();
9382 switch (eventStates) {
9383 case QEventPoint::State::Pressed:
9384 eventType = QEvent::TouchBegin;
9385 break;
9386 case QEventPoint::State::Released:
9387 eventType = QEvent::TouchEnd;
9388 break;
9389 default:
9390 eventType = QEvent::TouchUpdate;
9391 break;
9392 }
9393
9394 QMutableTouchEvent ret(eventType, event->pointingDevice(), event->modifiers(), touchPoints);
9395 ret.setTarget(q);
9396 ret.setTimestamp(event->timestamp());
9397 ret.accept();
9398 *localized = ret;
9399}
9400
9401bool QQuickItemPrivate::hasPointerHandlers() const
9402{
9403 return extra.isAllocated() && !extra->pointerHandlers.isEmpty();
9404}
9405
9406bool QQuickItemPrivate::hasEnabledHoverHandlers() const
9407{
9408 if (!hasPointerHandlers())
9409 return false;
9410 for (QQuickPointerHandler *h : extra->pointerHandlers)
9411 if (auto *hh = qmlobject_cast<QQuickHoverHandler *>(object: h); hh && hh->enabled())
9412 return true;
9413 return false;
9414}
9415
9416void QQuickItemPrivate::addPointerHandler(QQuickPointerHandler *h)
9417{
9418 Q_ASSERT(h);
9419 Q_Q(QQuickItem);
9420 // Accept all buttons, and leave filtering to pointerEvent() and/or user JS,
9421 // because there can be multiple handlers...
9422 extra.value().acceptedMouseButtons = Qt::AllButtons;
9423 auto &handlers = extra.value().pointerHandlers;
9424 if (!handlers.contains(t: h))
9425 handlers.prepend(t: h);
9426 auto &res = extra.value().resourcesList;
9427 if (!res.contains(t: h)) {
9428 res.append(t: h);
9429 QObject::connect(sender: h, signal: &QObject::destroyed, context: q, slot: [this](QObject *o) {
9430 _q_resourceObjectDeleted(object: o);
9431 });
9432 }
9433}
9434
9435void QQuickItemPrivate::removePointerHandler(QQuickPointerHandler *h)
9436{
9437 Q_ASSERT(h);
9438 Q_Q(QQuickItem);
9439 auto &handlers = extra.value().pointerHandlers;
9440 handlers.removeOne(t: h);
9441 auto &res = extra.value().resourcesList;
9442 res.removeOne(t: h);
9443 QObject::disconnect(sender: h, signal: &QObject::destroyed, receiver: q, zero: nullptr);
9444 if (handlers.isEmpty())
9445 extra.value().acceptedMouseButtons = extra.value().acceptedMouseButtonsWithoutHandlers;
9446}
9447
9448#if QT_CONFIG(quick_shadereffect)
9449QQuickItemLayer::QQuickItemLayer(QQuickItem *item)
9450 : m_item(item)
9451 , m_enabled(false)
9452 , m_mipmap(false)
9453 , m_smooth(false)
9454 , m_live(true)
9455 , m_componentComplete(true)
9456 , m_wrapMode(QQuickShaderEffectSource::ClampToEdge)
9457 , m_format(QQuickShaderEffectSource::RGBA8)
9458 , m_name("source")
9459 , m_effectComponent(nullptr)
9460 , m_effect(nullptr)
9461 , m_effectSource(nullptr)
9462 , m_textureMirroring(QQuickShaderEffectSource::MirrorVertically)
9463 , m_samples(0)
9464{
9465}
9466
9467QQuickItemLayer::~QQuickItemLayer()
9468{
9469 delete m_effectSource;
9470 delete m_effect;
9471}
9472
9473/*!
9474 \qmlproperty bool QtQuick::Item::layer.enabled
9475
9476 Holds whether the item is layered or not. Layering is disabled by default.
9477
9478 A layered item is rendered into an offscreen surface and cached until
9479 it is changed. Enabling layering for complex QML item hierarchies can
9480 sometimes be an optimization.
9481
9482 None of the other layer properties have any effect when the layer
9483 is disabled.
9484
9485 \sa {Item Layers}
9486 */
9487void QQuickItemLayer::setEnabled(bool e)
9488{
9489 if (e == m_enabled)
9490 return;
9491 m_enabled = e;
9492 if (m_componentComplete) {
9493 if (m_enabled)
9494 activate();
9495 else
9496 deactivate();
9497 }
9498
9499 emit enabledChanged(enabled: e);
9500}
9501
9502void QQuickItemLayer::classBegin()
9503{
9504 Q_ASSERT(!m_effectSource);
9505 Q_ASSERT(!m_effect);
9506 m_componentComplete = false;
9507}
9508
9509void QQuickItemLayer::componentComplete()
9510{
9511 Q_ASSERT(!m_componentComplete);
9512 m_componentComplete = true;
9513 if (m_enabled)
9514 activate();
9515}
9516
9517void QQuickItemLayer::activate()
9518{
9519 Q_ASSERT(!m_effectSource);
9520 m_effectSource = new QQuickShaderEffectSource();
9521 QQuickItemPrivate::get(item: m_effectSource)->setTransparentForPositioner(true);
9522
9523 QQuickItem *parentItem = m_item->parentItem();
9524 if (parentItem) {
9525 m_effectSource->setParentItem(parentItem);
9526 m_effectSource->stackAfter(sibling: m_item);
9527 }
9528
9529 m_effectSource->setSourceItem(m_item);
9530 m_effectSource->setHideSource(true);
9531 m_effectSource->setSmooth(m_smooth);
9532 m_effectSource->setLive(m_live);
9533 m_effectSource->setTextureSize(m_size);
9534 m_effectSource->setSourceRect(m_sourceRect);
9535 m_effectSource->setMipmap(m_mipmap);
9536 m_effectSource->setWrapMode(m_wrapMode);
9537 m_effectSource->setFormat(m_format);
9538 m_effectSource->setTextureMirroring(m_textureMirroring);
9539 m_effectSource->setSamples(m_samples);
9540
9541 if (m_effectComponent)
9542 activateEffect();
9543
9544 m_effectSource->setVisible(m_item->isVisible() && !m_effect);
9545
9546 updateZ();
9547 updateGeometry();
9548 updateOpacity();
9549 updateMatrix();
9550
9551 QQuickItemPrivate *id = QQuickItemPrivate::get(item: m_item);
9552 id->addItemChangeListener(listener: this, types: QQuickItemPrivate::Geometry | QQuickItemPrivate::Opacity | QQuickItemPrivate::Parent | QQuickItemPrivate::Visibility | QQuickItemPrivate::SiblingOrder);
9553}
9554
9555void QQuickItemLayer::deactivate()
9556{
9557 Q_ASSERT(m_effectSource);
9558
9559 if (m_effectComponent)
9560 deactivateEffect();
9561
9562 delete m_effectSource;
9563 m_effectSource = nullptr;
9564
9565 QQuickItemPrivate *id = QQuickItemPrivate::get(item: m_item);
9566 id->removeItemChangeListener(listener: this, types: QQuickItemPrivate::Geometry | QQuickItemPrivate::Opacity | QQuickItemPrivate::Parent | QQuickItemPrivate::Visibility | QQuickItemPrivate::SiblingOrder);
9567}
9568
9569void QQuickItemLayer::activateEffect()
9570{
9571 Q_ASSERT(m_effectSource);
9572 Q_ASSERT(m_effectComponent);
9573 Q_ASSERT(!m_effect);
9574
9575 QObject *created = m_effectComponent->beginCreate(m_effectComponent->creationContext());
9576 m_effect = qobject_cast<QQuickItem *>(o: created);
9577 if (!m_effect) {
9578 qWarning(msg: "Item: layer.effect is not a QML Item.");
9579 m_effectComponent->completeCreate();
9580 delete created;
9581 return;
9582 }
9583 QQuickItem *parentItem = m_item->parentItem();
9584 if (parentItem) {
9585 m_effect->setParentItem(parentItem);
9586 m_effect->stackAfter(sibling: m_effectSource);
9587 }
9588 m_effect->setVisible(m_item->isVisible());
9589 m_effect->setProperty(name: m_name, value: QVariant::fromValue<QObject *>(value: m_effectSource));
9590 QQuickItemPrivate::get(item: m_effect)->setTransparentForPositioner(true);
9591 m_effectComponent->completeCreate();
9592}
9593
9594void QQuickItemLayer::deactivateEffect()
9595{
9596 Q_ASSERT(m_effectSource);
9597 Q_ASSERT(m_effectComponent);
9598
9599 delete m_effect;
9600 m_effect = nullptr;
9601}
9602
9603
9604/*!
9605 \qmlproperty Component QtQuick::Item::layer.effect
9606
9607 Holds the effect that is applied to this layer.
9608
9609 The effect is typically a \l ShaderEffect component, although any \l Item component can be
9610 assigned. The effect should have a source texture property with a name matching \l layer.samplerName.
9611
9612 \sa layer.samplerName, {Item Layers}
9613 */
9614
9615void QQuickItemLayer::setEffect(QQmlComponent *component)
9616{
9617 if (component == m_effectComponent)
9618 return;
9619
9620 bool updateNeeded = false;
9621 if (m_effectSource && m_effectComponent) {
9622 deactivateEffect();
9623 updateNeeded = true;
9624 }
9625
9626 m_effectComponent = component;
9627
9628 if (m_effectSource && m_effectComponent) {
9629 activateEffect();
9630 updateNeeded = true;
9631 }
9632
9633 if (updateNeeded) {
9634 updateZ();
9635 updateGeometry();
9636 updateOpacity();
9637 updateMatrix();
9638 m_effectSource->setVisible(m_item->isVisible() && !m_effect);
9639 }
9640
9641 emit effectChanged(component);
9642}
9643
9644
9645/*!
9646 \qmlproperty bool QtQuick::Item::layer.mipmap
9647
9648 If this property is true, mipmaps are generated for the texture.
9649
9650 \note Some OpenGL ES 2 implementations do not support mipmapping of
9651 non-power-of-two textures.
9652
9653 \sa {Item Layers}
9654 */
9655
9656void QQuickItemLayer::setMipmap(bool mipmap)
9657{
9658 if (mipmap == m_mipmap)
9659 return;
9660 m_mipmap = mipmap;
9661
9662 if (m_effectSource)
9663 m_effectSource->setMipmap(m_mipmap);
9664
9665 emit mipmapChanged(mipmap);
9666}
9667
9668
9669/*!
9670 \qmlproperty enumeration QtQuick::Item::layer.format
9671
9672 This property defines the format of the backing texture.
9673 Modifying this property makes most sense when the \a layer.effect is also
9674 specified.
9675
9676 \value ShaderEffectSource.RGBA8
9677 \value ShaderEffectSource.RGBA16F
9678 \value ShaderEffectSource.RGBA32F
9679 \value ShaderEffectSource.Alpha Starting with Qt 6.0, this value is not in use and has the same effect as \c RGBA8 in practice.
9680 \value ShaderEffectSource.RGB Starting with Qt 6.0, this value is not in use and has the same effect as \c RGBA8 in practice.
9681 \value ShaderEffectSource.RGBA Starting with Qt 6.0, this value is not in use and has the same effect as \c RGBA8 in practice.
9682
9683 \sa {Item Layers}
9684 */
9685
9686void QQuickItemLayer::setFormat(QQuickShaderEffectSource::Format f)
9687{
9688 if (f == m_format)
9689 return;
9690 m_format = f;
9691
9692 if (m_effectSource)
9693 m_effectSource->setFormat(m_format);
9694
9695 emit formatChanged(format: m_format);
9696}
9697
9698
9699/*!
9700 \qmlproperty rect QtQuick::Item::layer.sourceRect
9701
9702 This property defines the rectangular area of the item that should be
9703 rendered into the texture. The source rectangle can be larger than
9704 the item itself. If the rectangle is null, which is the default,
9705 then the whole item is rendered to the texture.
9706
9707 \sa {Item Layers}
9708 */
9709
9710void QQuickItemLayer::setSourceRect(const QRectF &sourceRect)
9711{
9712 if (sourceRect == m_sourceRect)
9713 return;
9714 m_sourceRect = sourceRect;
9715
9716 if (m_effectSource)
9717 m_effectSource->setSourceRect(m_sourceRect);
9718
9719 emit sourceRectChanged(sourceRect);
9720}
9721
9722/*!
9723 \qmlproperty bool QtQuick::Item::layer.smooth
9724
9725 Holds whether the layer is smoothly transformed. When enabled, sampling the
9726 layer's texture is performed using \c linear interpolation, while
9727 non-smooth results in using the \c nearest filtering mode.
9728
9729 By default, this property is set to \c false.
9730
9731 \sa {Item Layers}
9732 */
9733
9734void QQuickItemLayer::setSmooth(bool s)
9735{
9736 if (m_smooth == s)
9737 return;
9738 m_smooth = s;
9739
9740 if (m_effectSource)
9741 m_effectSource->setSmooth(m_smooth);
9742
9743 emit smoothChanged(smooth: s);
9744}
9745
9746/*!
9747 \qmlproperty bool QtQuick::Item::layer.live
9748 \since 6.5
9749
9750 When this property is true the layer texture is updated whenever the
9751 item updates. Otherwise it will always be a frozen image.
9752
9753 By default, this property is set to \c true.
9754
9755 \sa {Item Layers}
9756 */
9757
9758void QQuickItemLayer::setLive(bool live)
9759{
9760 if (m_live == live)
9761 return;
9762 m_live = live;
9763
9764 if (m_effectSource)
9765 m_effectSource->setLive(m_live);
9766
9767 emit liveChanged(live);
9768}
9769
9770/*!
9771 \qmlproperty size QtQuick::Item::layer.textureSize
9772
9773 This property holds the requested pixel size of the layers texture. If it is empty,
9774 which is the default, the size of the item is used.
9775
9776 \note Some platforms have a limit on how small framebuffer objects can be,
9777 which means the actual texture size might be larger than the requested
9778 size.
9779
9780 \sa {Item Layers}
9781 */
9782
9783void QQuickItemLayer::setSize(const QSize &size)
9784{
9785 if (size == m_size)
9786 return;
9787 m_size = size;
9788
9789 if (m_effectSource)
9790 m_effectSource->setTextureSize(size);
9791
9792 emit sizeChanged(size);
9793}
9794
9795/*!
9796 \qmlproperty enumeration QtQuick::Item::layer.wrapMode
9797
9798 This property defines the wrap modes associated with the texture.
9799 Modifying this property makes most sense when the \a layer.effect is
9800 specified.
9801
9802 \value ShaderEffectSource.ClampToEdge GL_CLAMP_TO_EDGE both horizontally and vertically
9803 \value ShaderEffectSource.RepeatHorizontally GL_REPEAT horizontally, GL_CLAMP_TO_EDGE vertically
9804 \value ShaderEffectSource.RepeatVertically GL_CLAMP_TO_EDGE horizontally, GL_REPEAT vertically
9805 \value ShaderEffectSource.Repeat GL_REPEAT both horizontally and vertically
9806
9807 \note Some OpenGL ES 2 implementations do not support the GL_REPEAT
9808 wrap mode with non-power-of-two textures.
9809
9810 \sa {Item Layers}
9811 */
9812
9813void QQuickItemLayer::setWrapMode(QQuickShaderEffectSource::WrapMode mode)
9814{
9815 if (mode == m_wrapMode)
9816 return;
9817 m_wrapMode = mode;
9818
9819 if (m_effectSource)
9820 m_effectSource->setWrapMode(m_wrapMode);
9821
9822 emit wrapModeChanged(mode);
9823}
9824
9825/*!
9826 \qmlproperty enumeration QtQuick::Item::layer.textureMirroring
9827 \since 5.6
9828
9829 This property defines how the generated texture should be mirrored.
9830 The default value is \c{ShaderEffectSource.MirrorVertically}.
9831 Custom mirroring can be useful if the generated texture is directly accessed by custom shaders,
9832 such as those specified by ShaderEffect. If no effect is specified for the layered
9833 item, mirroring has no effect on the UI representation of the item.
9834
9835 \value ShaderEffectSource.NoMirroring No mirroring
9836 \value ShaderEffectSource.MirrorHorizontally The generated texture is flipped along X-axis.
9837 \value ShaderEffectSource.MirrorVertically The generated texture is flipped along Y-axis.
9838 */
9839
9840void QQuickItemLayer::setTextureMirroring(QQuickShaderEffectSource::TextureMirroring mirroring)
9841{
9842 if (mirroring == m_textureMirroring)
9843 return;
9844 m_textureMirroring = mirroring;
9845
9846 if (m_effectSource)
9847 m_effectSource->setTextureMirroring(m_textureMirroring);
9848
9849 emit textureMirroringChanged(mirroring);
9850}
9851
9852/*!
9853 \qmlproperty enumeration QtQuick::Item::layer.samples
9854 \since 5.10
9855
9856 This property allows requesting multisampled rendering in the layer.
9857
9858 By default multisampling is enabled whenever multisampling is
9859 enabled for the entire window, assuming the scenegraph renderer in
9860 use and the underlying graphics API supports this.
9861
9862 By setting the value to 2, 4, etc. multisampled rendering can be requested
9863 for a part of the scene without enabling multisampling for the entire
9864 scene. This way multisampling is applied only to a given subtree, which can
9865 lead to significant performance gains since multisampling is not applied to
9866 other parts of the scene.
9867
9868 \note Enabling multisampling can be potentially expensive regardless of the
9869 layer's size, as it incurs a hardware and driver dependent performance and
9870 memory cost.
9871
9872 \note This property is only functional when support for multisample
9873 renderbuffers and framebuffer blits is available. Otherwise the value is
9874 silently ignored.
9875 */
9876
9877void QQuickItemLayer::setSamples(int count)
9878{
9879 if (m_samples == count)
9880 return;
9881
9882 m_samples = count;
9883
9884 if (m_effectSource)
9885 m_effectSource->setSamples(m_samples);
9886
9887 emit samplesChanged(count);
9888}
9889
9890/*!
9891 \qmlproperty string QtQuick::Item::layer.samplerName
9892
9893 Holds the name of the effect's source texture property.
9894
9895 This value must match the name of the effect's source texture property
9896 so that the Item can pass the layer's offscreen surface to the effect correctly.
9897
9898 \sa layer.effect, ShaderEffect, {Item Layers}
9899 */
9900
9901void QQuickItemLayer::setName(const QByteArray &name) {
9902 if (m_name == name)
9903 return;
9904 if (m_effect) {
9905 m_effect->setProperty(name: m_name, value: QVariant());
9906 m_effect->setProperty(name, value: QVariant::fromValue<QObject *>(value: m_effectSource));
9907 }
9908 m_name = name;
9909 emit nameChanged(name);
9910}
9911
9912void QQuickItemLayer::itemOpacityChanged(QQuickItem *item)
9913{
9914 Q_UNUSED(item);
9915 updateOpacity();
9916}
9917
9918void QQuickItemLayer::itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &)
9919{
9920 updateGeometry();
9921}
9922
9923void QQuickItemLayer::itemParentChanged(QQuickItem *item, QQuickItem *parent)
9924{
9925 Q_UNUSED(item);
9926 Q_ASSERT(item == m_item);
9927 Q_ASSERT(parent != m_effectSource);
9928 Q_ASSERT(parent == nullptr || parent != m_effect);
9929
9930 m_effectSource->setParentItem(parent);
9931 if (parent)
9932 m_effectSource->stackAfter(sibling: m_item);
9933
9934 if (m_effect) {
9935 m_effect->setParentItem(parent);
9936 if (parent)
9937 m_effect->stackAfter(sibling: m_effectSource);
9938 }
9939}
9940
9941void QQuickItemLayer::itemSiblingOrderChanged(QQuickItem *)
9942{
9943 m_effectSource->stackAfter(sibling: m_item);
9944 if (m_effect)
9945 m_effect->stackAfter(sibling: m_effectSource);
9946}
9947
9948void QQuickItemLayer::itemVisibilityChanged(QQuickItem *)
9949{
9950 QQuickItem *l = m_effect ? (QQuickItem *) m_effect : (QQuickItem *) m_effectSource;
9951 if (!l)
9952 return;
9953 l->setVisible(m_item->isVisible());
9954}
9955
9956void QQuickItemLayer::updateZ()
9957{
9958 if (!m_componentComplete || !m_enabled)
9959 return;
9960 QQuickItem *l = m_effect ? (QQuickItem *) m_effect : (QQuickItem *) m_effectSource;
9961 if (!l)
9962 return;
9963 l->setZ(m_item->z());
9964}
9965
9966void QQuickItemLayer::updateOpacity()
9967{
9968 QQuickItem *l = m_effect ? (QQuickItem *) m_effect : (QQuickItem *) m_effectSource;
9969 if (!l)
9970 return;
9971 l->setOpacity(m_item->opacity());
9972}
9973
9974void QQuickItemLayer::updateGeometry()
9975{
9976 QQuickItem *l = m_effect ? (QQuickItem *) m_effect : (QQuickItem *) m_effectSource;
9977 if (!l)
9978 return;
9979 // Avoid calling QQuickImage::boundingRect() or other overrides
9980 // which may not be up-to-date at this time (QTBUG-104442, 104536)
9981 QRectF bounds = m_item->QQuickItem::boundingRect();
9982 l->setSize(bounds.size());
9983 l->setPosition(bounds.topLeft() + m_item->position());
9984}
9985
9986void QQuickItemLayer::updateMatrix()
9987{
9988 // Called directly from transformChanged(), so needs some extra
9989 // checks.
9990 if (!m_componentComplete || !m_enabled)
9991 return;
9992 QQuickItem *l = m_effect ? (QQuickItem *) m_effect : (QQuickItem *) m_effectSource;
9993 if (!l)
9994 return;
9995 QQuickItemPrivate *ld = QQuickItemPrivate::get(item: l);
9996 l->setScale(m_item->scale());
9997 l->setRotation(m_item->rotation());
9998 ld->transforms = QQuickItemPrivate::get(item: m_item)->transforms;
9999 if (ld->origin() != QQuickItemPrivate::get(item: m_item)->origin())
10000 ld->extra.value().origin = QQuickItemPrivate::get(item: m_item)->origin();
10001 ld->dirty(type: QQuickItemPrivate::Transform);
10002}
10003#endif // quick_shadereffect
10004
10005QQuickItemPrivate::ExtraData::ExtraData()
10006: z(0), scale(1), rotation(0), opacity(1),
10007 contents(nullptr), screenAttached(nullptr), layoutDirectionAttached(nullptr),
10008 enterKeyAttached(nullptr),
10009 keyHandler(nullptr),
10010#if QT_CONFIG(quick_shadereffect)
10011 layer(nullptr),
10012#endif
10013 effectRefCount(0), hideRefCount(0),
10014 recursiveEffectRefCount(0),
10015 opacityNode(nullptr), clipNode(nullptr), rootNode(nullptr),
10016 origin(QQuickItem::Center),
10017 transparentForPositioner(false)
10018{
10019}
10020
10021
10022#if QT_CONFIG(accessibility)
10023QAccessible::Role QQuickItemPrivate::effectiveAccessibleRole() const
10024{
10025 Q_Q(const QQuickItem);
10026 auto *attached = qmlAttachedPropertiesObject<QQuickAccessibleAttached>(obj: q, create: false);
10027 auto role = QAccessible::NoRole;
10028 if (auto *accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(object: attached))
10029 role = accessibleAttached->role();
10030 if (role == QAccessible::NoRole)
10031 role = accessibleRole();
10032 return role;
10033}
10034
10035QAccessible::Role QQuickItemPrivate::accessibleRole() const
10036{
10037 return QAccessible::NoRole;
10038}
10039#endif
10040
10041// helper code to let a visual parent mark its visual children for the garbage collector
10042
10043namespace QV4 {
10044namespace Heap {
10045struct QQuickItemWrapper : public QObjectWrapper {
10046 static void markObjects(QV4::Heap::Base *that, QV4::MarkStack *markStack);
10047};
10048}
10049}
10050
10051struct QQuickItemWrapper : public QV4::QObjectWrapper {
10052 V4_OBJECT2(QQuickItemWrapper, QV4::QObjectWrapper)
10053};
10054
10055DEFINE_OBJECT_VTABLE(QQuickItemWrapper);
10056
10057void QV4::Heap::QQuickItemWrapper::markObjects(QV4::Heap::Base *that, QV4::MarkStack *markStack)
10058{
10059 QObjectWrapper *This = static_cast<QObjectWrapper *>(that);
10060 if (QQuickItem *item = static_cast<QQuickItem*>(This->object())) {
10061 for (QQuickItem *child : std::as_const(t&: QQuickItemPrivate::get(item)->childItems))
10062 QV4::QObjectWrapper::markWrapper(object: child, markStack);
10063 }
10064 QObjectWrapper::markObjects(that, markStack);
10065}
10066
10067quint64 QQuickItemPrivate::_q_createJSWrapper(QQmlV4ExecutionEnginePtr engine)
10068{
10069 return (engine->memoryManager->allocate<QQuickItemWrapper>(args: q_func()))->asReturnedValue();
10070}
10071
10072QDebug operator<<(QDebug debug, const QQuickItemPrivate::ChangeListener &listener)
10073{
10074 QDebugStateSaver stateSaver(debug);
10075 debug.nospace() << "ChangeListener listener=" << listener.listener << " types=" << listener.types;
10076 return debug;
10077}
10078
10079//! \internal
10080QPointF QQuickItem::mapFromItem(const QQuickItem *item, qreal x, qreal y)
10081{ return mapFromItem(item, point: QPointF(x, y) ); }
10082
10083//! \internal
10084QRectF QQuickItem::mapFromItem(const QQuickItem *item, const QRectF &rect) const
10085{ return mapRectFromItem(item, rect); }
10086
10087//! \internal
10088QRectF QQuickItem::mapFromItem(const QQuickItem *item, qreal x, qreal y, qreal width, qreal height) const
10089{ return mapFromItem(item, rect: QRectF(x, y, width, height)); }
10090
10091//! \internal
10092QPointF QQuickItem::mapToItem(const QQuickItem *item, qreal x, qreal y)
10093{ return mapToItem(item, point: QPointF(x, y)); }
10094
10095//! \internal
10096QRectF QQuickItem::mapToItem(const QQuickItem *item, const QRectF &rect) const
10097{ return mapRectToItem(item, rect); }
10098
10099//! \internal
10100QRectF QQuickItem::mapToItem(const QQuickItem *item, qreal x, qreal y, qreal width, qreal height) const
10101{ return mapToItem(item, rect: QRectF(x, y, width, height)); }
10102
10103//! \internal
10104QPointF QQuickItem::mapToGlobal(qreal x, qreal y) const
10105{ return mapToGlobal(point: QPointF(x, y)); }
10106
10107//! \internal
10108QPointF QQuickItem::mapFromGlobal(qreal x, qreal y) const
10109{ return mapFromGlobal(point: QPointF(x, y)); }
10110
10111//! \internal
10112QQuickItemChangeListener::~QQuickItemChangeListener() = default;
10113
10114QT_END_NAMESPACE
10115
10116#include <moc_qquickitem.cpp>
10117
10118#include "moc_qquickitem_p.cpp"
10119

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of qtdeclarative/src/quick/items/qquickitem.cpp