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