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

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