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