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 return itemToWindowTransform().inverted();
3205}
3206
3207/*!
3208 Returns a transform that maps points from item space into window space.
3209*/
3210QTransform QQuickItemPrivate::itemToWindowTransform() const
3211{
3212 // item's parent must not be itself, otherwise calling itemToWindowTransform() on it is infinite recursion
3213 Q_ASSERT(!parentItem || QQuickItemPrivate::get(parentItem) != this);
3214 QTransform rv = parentItem ? QQuickItemPrivate::get(parentItem)->itemToWindowTransform() : QTransform();
3215 itemToParentTransform(&rv);
3216 return rv;
3217}
3218
3219/*!
3220 Modifies \a t with this item's local transform relative to its parent.
3221*/
3222void QQuickItemPrivate::itemToParentTransform(QTransform *t) const
3223{
3224 /* Read the current x and y values. As this is an internal method,
3225 we don't care about it being usable in bindings. Instead, we
3226 care about performance here, and thus we read the value with
3227 valueBypassingBindings. This avoids any checks whether we are
3228 in a binding (which sholdn't be too expensive, but can add up).
3229 */
3230
3231 qreal x = this->x.valueBypassingBindings();
3232 qreal y = this->y.valueBypassingBindings();
3233 if (x || y)
3234 t->translate(x, y);
3235
3236 if (!transforms.isEmpty()) {
3237 QMatrix4x4 m(*t);
3238 for (int ii = transforms.size() - 1; ii >= 0; --ii)
3239 transforms.at(ii)->applyTo(&m);
3240 *t = m.toTransform();
3241 }
3242
3243 if (scale() != 1. || rotation() != 0.) {
3244 QPointF tp = computeTransformOrigin();
3245 t->translate(tp.x(), tp.y());
3246 t->scale(scale(), scale());
3247 t->rotate(rotation());
3248 t->translate(-tp.x(), -tp.y());
3249 }
3250}
3251
3252/*!
3253 Returns true if construction of the QML component is complete; otherwise
3254 returns false.
3255
3256 It is often desirable to delay some processing until the component is
3257 completed.
3258
3259 \sa componentComplete()
3260*/
3261bool QQuickItem::isComponentComplete() const
3262{
3263 Q_D(const QQuickItem);
3264 return d->componentComplete;
3265}
3266
3267QQuickItemPrivate::QQuickItemPrivate()
3268 : _anchors(nullptr)
3269 , _stateGroup(nullptr)
3270 , flags(0)
3271 , widthValidFlag(false)
3272 , heightValidFlag(false)
3273 , componentComplete(true)
3274 , keepMouse(false)
3275 , keepTouch(false)
3276 , hoverEnabled(false)
3277 , smooth(true)
3278 , antialiasing(false)
3279 , focus(false)
3280 , activeFocus(false)
3281 , notifiedFocus(false)
3282 , notifiedActiveFocus(false)
3283 , filtersChildMouseEvents(false)
3284 , explicitVisible(true)
3285 , effectiveVisible(true)
3286 , explicitEnable(true)
3287 , effectiveEnable(true)
3288 , polishScheduled(false)
3289 , inheritedLayoutMirror(false)
3290 , effectiveLayoutMirror(false)
3291 , isMirrorImplicit(true)
3292 , inheritMirrorFromParent(false)
3293 , inheritMirrorFromItem(false)
3294 , isAccessible(false)
3295 , culled(false)
3296 , hasCursor(false)
3297 , subtreeCursorEnabled(false)
3298 , subtreeHoverEnabled(false)
3299 , activeFocusOnTab(false)
3300 , implicitAntialiasing(false)
3301 , antialiasingValid(false)
3302 , isTabFence(false)
3303 , replayingPressEvent(false)
3304 , touchEnabled(false)
3305 , hasCursorHandler(false)
3306 , maybeHasSubsceneDeliveryAgent(true)
3307 , subtreeTransformChangedEnabled(true)
3308 , inDestructor(false)
3309 , focusReason(Qt::OtherFocusReason)
3310 , focusPolicy(Qt::NoFocus)
3311 , dirtyAttributes(0)
3312 , nextDirtyItem(nullptr)
3313 , prevDirtyItem(nullptr)
3314 , window(nullptr)
3315 , windowRefCount(0)
3316 , parentItem(nullptr)
3317 , sortedChildItems(&childItems)
3318 , subFocusItem(nullptr)
3319 , x(0)
3320 , y(0)
3321 , width(0)
3322 , height(0)
3323 , implicitWidth(0)
3324 , implicitHeight(0)
3325 , baselineOffset(0)
3326 , itemNodeInstance(nullptr)
3327 , paintNode(nullptr)
3328 , szPolicy(QLayoutPolicy::Fixed, QLayoutPolicy::Fixed)
3329{
3330}
3331
3332QQuickItemPrivate::~QQuickItemPrivate()
3333{
3334 if (sortedChildItems != &childItems)
3335 delete sortedChildItems;
3336}
3337
3338void QQuickItemPrivate::init(QQuickItem *parent)
3339{
3340 Q_Q(QQuickItem);
3341
3342 isQuickItem = true;
3343
3344 baselineOffset = 0.0;
3345
3346 if (parent) {
3347 q->setParentItem(parent);
3348 QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(parent);
3349 setImplicitLayoutMirror(parentPrivate->inheritedLayoutMirror, parentPrivate->inheritMirrorFromParent);
3350 }
3351}
3352
3353QLayoutPolicy QQuickItemPrivate::sizePolicy() const
3354{
3355 return szPolicy;
3356}
3357
3358void QQuickItemPrivate::setSizePolicy(const QLayoutPolicy::Policy& horizontalPolicy, const QLayoutPolicy::Policy& verticalPolicy)
3359{
3360 szPolicy.setHorizontalPolicy(horizontalPolicy);
3361 szPolicy.setVerticalPolicy(verticalPolicy);
3362}
3363
3364void QQuickItemPrivate::data_append(QQmlListProperty<QObject> *prop, QObject *o)
3365{
3366 if (!o)
3367 return;
3368
3369 QQuickItem *that = static_cast<QQuickItem *>(prop->object);
3370
3371 if (QQuickItem *item = qmlobject_cast<QQuickItem *>(o)) {
3372 item->setParentItem(that);
3373 } else if (QQuickPointerHandler *pointerHandler = qmlobject_cast<QQuickPointerHandler *>(o)) {
3374 if (pointerHandler->parent() != that) {
3375 qCDebug(lcHandlerParent) << "reparenting handler" << pointerHandler << ":" << pointerHandler->parent() << "->" << that;
3376 pointerHandler->setParent(that);
3377 }
3378 QQuickItemPrivate::get(that)->addPointerHandler(pointerHandler);
3379 } else {
3380 o->setParent(that);
3381 resources_append(prop, o);
3382 }
3383}
3384
3385/*!
3386 \qmlproperty list<QtObject> QtQuick::Item::data
3387 \qmldefault
3388
3389 The data property allows you to freely mix visual children and resources
3390 in an item. If you assign a visual item to the data list it becomes
3391 a child and if you assign any other object type, it is added as a resource.
3392
3393 So you can write:
3394 \qml
3395 Item {
3396 Text {}
3397 Rectangle {}
3398 Timer {}
3399 }
3400 \endqml
3401
3402 instead of:
3403 \qml
3404 Item {
3405 children: [
3406 Text {},
3407 Rectangle {}
3408 ]
3409 resources: [
3410 Timer {}
3411 ]
3412 }
3413 \endqml
3414
3415 It should not generally be necessary to refer to the \c data property,
3416 as it is the default property for Item and thus all child items are
3417 automatically assigned to this property.
3418 */
3419
3420qsizetype QQuickItemPrivate::data_count(QQmlListProperty<QObject> *property)
3421{
3422 QQuickItem *item = static_cast<QQuickItem*>(property->object);
3423 QQuickItemPrivate *privateItem = QQuickItemPrivate::get(item);
3424 QQmlListProperty<QObject> resourcesProperty = privateItem->resources();
3425 QQmlListProperty<QQuickItem> childrenProperty = privateItem->children();
3426
3427 return resources_count(&resourcesProperty) + children_count(&childrenProperty);
3428}
3429
3430QObject *QQuickItemPrivate::data_at(QQmlListProperty<QObject> *property, qsizetype i)
3431{
3432 QQuickItem *item = static_cast<QQuickItem*>(property->object);
3433 QQuickItemPrivate *privateItem = QQuickItemPrivate::get(item);
3434 QQmlListProperty<QObject> resourcesProperty = privateItem->resources();
3435 QQmlListProperty<QQuickItem> childrenProperty = privateItem->children();
3436
3437 qsizetype resourcesCount = resources_count(&resourcesProperty);
3438 if (i < resourcesCount)
3439 return resources_at(&resourcesProperty, i);
3440 const qsizetype j = i - resourcesCount;
3441 if (j < children_count(&childrenProperty))
3442 return children_at(&childrenProperty, j);
3443 return nullptr;
3444}
3445
3446void QQuickItemPrivate::data_clear(QQmlListProperty<QObject> *property)
3447{
3448 QQuickItem *item = static_cast<QQuickItem*>(property->object);
3449 QQuickItemPrivate *privateItem = QQuickItemPrivate::get(item);
3450 QQmlListProperty<QObject> resourcesProperty = privateItem->resources();
3451 QQmlListProperty<QQuickItem> childrenProperty = privateItem->children();
3452
3453 resources_clear(&resourcesProperty);
3454 children_clear(&childrenProperty);
3455}
3456
3457void QQuickItemPrivate::data_removeLast(QQmlListProperty<QObject> *property)
3458{
3459 QQuickItem *item = static_cast<QQuickItem*>(property->object);
3460 QQuickItemPrivate *privateItem = QQuickItemPrivate::get(item);
3461
3462 QQmlListProperty<QQuickItem> childrenProperty = privateItem->children();
3463 if (children_count(&childrenProperty) > 0) {
3464 children_removeLast(&childrenProperty);
3465 return;
3466 }
3467
3468 QQmlListProperty<QObject> resourcesProperty = privateItem->resources();
3469 if (resources_count(&resourcesProperty) > 0)
3470 resources_removeLast(&resourcesProperty);
3471}
3472
3473QObject *QQuickItemPrivate::resources_at(QQmlListProperty<QObject> *prop, qsizetype index)
3474{
3475 QQuickItemPrivate *quickItemPrivate = QQuickItemPrivate::get(static_cast<QQuickItem *>(prop->object));
3476 return quickItemPrivate->extra.isAllocated() ? quickItemPrivate->extra->resourcesList.value(index) : 0;
3477}
3478
3479void QQuickItemPrivate::resources_append(QQmlListProperty<QObject> *prop, QObject *object)
3480{
3481 QQuickItem *quickItem = static_cast<QQuickItem *>(prop->object);
3482 QQuickItemPrivate *quickItemPrivate = QQuickItemPrivate::get(quickItem);
3483 if (!quickItemPrivate->extra.value().resourcesList.contains(object)) {
3484 quickItemPrivate->extra.value().resourcesList.append(object);
3485 qmlobject_connect(object, QObject, SIGNAL(destroyed(QObject*)),
3486 quickItem, QQuickItem, SLOT(_q_resourceObjectDeleted(QObject*)));
3487 }
3488}
3489
3490qsizetype QQuickItemPrivate::resources_count(QQmlListProperty<QObject> *prop)
3491{
3492 QQuickItemPrivate *quickItemPrivate = QQuickItemPrivate::get(static_cast<QQuickItem *>(prop->object));
3493 return quickItemPrivate->extra.isAllocated() ? quickItemPrivate->extra->resourcesList.size() : 0;
3494}
3495
3496void QQuickItemPrivate::resources_clear(QQmlListProperty<QObject> *prop)
3497{
3498 QQuickItem *quickItem = static_cast<QQuickItem *>(prop->object);
3499 QQuickItemPrivate *quickItemPrivate = QQuickItemPrivate::get(quickItem);
3500 if (quickItemPrivate->extra.isAllocated()) {//If extra is not allocated resources is empty.
3501 for (QObject *object : std::as_const(quickItemPrivate->extra->resourcesList)) {
3502 qmlobject_disconnect(object, QObject, SIGNAL(destroyed(QObject*)),
3503 quickItem, QQuickItem, SLOT(_q_resourceObjectDeleted(QObject*)));
3504 }
3505 quickItemPrivate->extra->resourcesList.clear();
3506 }
3507}
3508
3509void QQuickItemPrivate::resources_removeLast(QQmlListProperty<QObject> *prop)
3510{
3511 QQuickItem *quickItem = static_cast<QQuickItem *>(prop->object);
3512 QQuickItemPrivate *quickItemPrivate = QQuickItemPrivate::get(quickItem);
3513 if (quickItemPrivate->extra.isAllocated()) {//If extra is not allocated resources is empty.
3514 QList<QObject *> *resources = &quickItemPrivate->extra->resourcesList;
3515 if (resources->isEmpty())
3516 return;
3517
3518 qmlobject_disconnect(resources->last(), QObject, SIGNAL(destroyed(QObject*)),
3519 quickItem, QQuickItem, SLOT(_q_resourceObjectDeleted(QObject*)));
3520 resources->removeLast();
3521 }
3522}
3523
3524QQuickItem *QQuickItemPrivate::children_at(QQmlListProperty<QQuickItem> *prop, qsizetype index)
3525{
3526 QQuickItemPrivate *p = QQuickItemPrivate::get(static_cast<QQuickItem *>(prop->object));
3527 if (index >= p->childItems.size() || index < 0)
3528 return nullptr;
3529 else
3530 return p->childItems.at(index);
3531}
3532
3533void QQuickItemPrivate::children_append(QQmlListProperty<QQuickItem> *prop, QQuickItem *o)
3534{
3535 if (!o)
3536 return;
3537
3538 QQuickItem *that = static_cast<QQuickItem *>(prop->object);
3539 if (o->parentItem() == that)
3540 o->setParentItem(nullptr);
3541
3542 o->setParentItem(that);
3543}
3544
3545qsizetype QQuickItemPrivate::children_count(QQmlListProperty<QQuickItem> *prop)
3546{
3547 QQuickItemPrivate *p = QQuickItemPrivate::get(static_cast<QQuickItem *>(prop->object));
3548 return p->childItems.size();
3549}
3550
3551void QQuickItemPrivate::children_clear(QQmlListProperty<QQuickItem> *prop)
3552{
3553 QQuickItem *that = static_cast<QQuickItem *>(prop->object);
3554 QQuickItemPrivate *p = QQuickItemPrivate::get(that);
3555 while (!p->childItems.isEmpty())
3556 p->childItems.at(0)->setParentItem(nullptr);
3557}
3558
3559void QQuickItemPrivate::children_removeLast(QQmlListProperty<QQuickItem> *prop)
3560{
3561 QQuickItem *that = static_cast<QQuickItem *>(prop->object);
3562 QQuickItemPrivate *p = QQuickItemPrivate::get(that);
3563 if (!p->childItems.isEmpty())
3564 p->childItems.last()->setParentItem(nullptr);
3565}
3566
3567qsizetype QQuickItemPrivate::visibleChildren_count(QQmlListProperty<QQuickItem> *prop)
3568{
3569 QQuickItemPrivate *p = QQuickItemPrivate::get(static_cast<QQuickItem *>(prop->object));
3570 qsizetype visibleCount = 0;
3571 qsizetype c = p->childItems.size();
3572 while (c--) {
3573 if (p->childItems.at(c)->isVisible()) visibleCount++;
3574 }
3575
3576 return visibleCount;
3577}
3578
3579QQuickItem *QQuickItemPrivate::visibleChildren_at(QQmlListProperty<QQuickItem> *prop, qsizetype index)
3580{
3581 QQuickItemPrivate *p = QQuickItemPrivate::get(static_cast<QQuickItem *>(prop->object));
3582 const qsizetype childCount = p->childItems.size();
3583 if (index >= childCount || index < 0)
3584 return nullptr;
3585
3586 qsizetype visibleCount = -1;
3587 for (qsizetype i = 0; i < childCount; i++) {
3588 if (p->childItems.at(i)->isVisible()) visibleCount++;
3589 if (visibleCount == index) return p->childItems.at(i);
3590 }
3591 return nullptr;
3592}
3593
3594qsizetype QQuickItemPrivate::transform_count(QQmlListProperty<QQuickTransform> *prop)
3595{
3596 QQuickItem *that = static_cast<QQuickItem *>(prop->object);
3597 QQuickItemPrivate *p = QQuickItemPrivate::get(that);
3598
3599 return p->transforms.size();
3600}
3601
3602void QQuickTransform::appendToItem(QQuickItem *item)
3603{
3604 Q_D(QQuickTransform);
3605 if (!item)
3606 return;
3607
3608 QQuickItemPrivate *p = QQuickItemPrivate::get(item);
3609
3610 if (!d->items.isEmpty() && !p->transforms.isEmpty() && p->transforms.contains(this)) {
3611 p->transforms.removeOne(this);
3612 p->transforms.append(this);
3613 } else {
3614 p->transforms.append(this);
3615 d->items.append(item);
3616 }
3617
3618 p->dirty(QQuickItemPrivate::Transform);
3619}
3620
3621void QQuickTransform::prependToItem(QQuickItem *item)
3622{
3623 Q_D(QQuickTransform);
3624 if (!item)
3625 return;
3626
3627 QQuickItemPrivate *p = QQuickItemPrivate::get(item);
3628
3629 if (!d->items.isEmpty() && !p->transforms.isEmpty() && p->transforms.contains(this)) {
3630 p->transforms.removeOne(this);
3631 p->transforms.prepend(this);
3632 } else {
3633 p->transforms.prepend(this);
3634 d->items.append(item);
3635 }
3636
3637 p->dirty(QQuickItemPrivate::Transform);
3638}
3639
3640void QQuickItemPrivate::transform_append(QQmlListProperty<QQuickTransform> *prop, QQuickTransform *transform)
3641{
3642 if (!transform)
3643 return;
3644
3645 QQuickItem *that = static_cast<QQuickItem *>(prop->object);
3646 transform->appendToItem(that);
3647}
3648
3649QQuickTransform *QQuickItemPrivate::transform_at(QQmlListProperty<QQuickTransform> *prop, qsizetype idx)
3650{
3651 QQuickItem *that = static_cast<QQuickItem *>(prop->object);
3652 QQuickItemPrivate *p = QQuickItemPrivate::get(that);
3653
3654 if (idx < 0 || idx >= p->transforms.size())
3655 return nullptr;
3656 else
3657 return p->transforms.at(idx);
3658}
3659
3660void QQuickItemPrivate::transform_clear(QQmlListProperty<QQuickTransform> *prop)
3661{
3662 QQuickItem *that = static_cast<QQuickItem *>(prop->object);
3663 QQuickItemPrivate *p = QQuickItemPrivate::get(that);
3664
3665 for (qsizetype ii = 0; ii < p->transforms.size(); ++ii) {
3666 QQuickTransform *t = p->transforms.at(ii);
3667 QQuickTransformPrivate *tp = QQuickTransformPrivate::get(t);
3668 tp->items.removeOne(that);
3669 }
3670
3671 p->transforms.clear();
3672
3673 p->dirty(QQuickItemPrivate::Transform);
3674}
3675
3676void QQuickItemPrivate::_q_resourceObjectDeleted(QObject *object)
3677{
3678 if (extra.isAllocated() && extra->resourcesList.contains(object))
3679 extra->resourcesList.removeAll(object);
3680}
3681
3682/*!
3683 \qmlpropertygroup QtQuick::Item::anchors
3684 \qmlproperty AnchorLine QtQuick::Item::anchors.top
3685 \qmlproperty AnchorLine QtQuick::Item::anchors.bottom
3686 \qmlproperty AnchorLine QtQuick::Item::anchors.left
3687 \qmlproperty AnchorLine QtQuick::Item::anchors.right
3688 \qmlproperty AnchorLine QtQuick::Item::anchors.horizontalCenter
3689 \qmlproperty AnchorLine QtQuick::Item::anchors.verticalCenter
3690 \qmlproperty AnchorLine QtQuick::Item::anchors.baseline
3691
3692 \qmlproperty Item QtQuick::Item::anchors.fill
3693 \qmlproperty Item QtQuick::Item::anchors.centerIn
3694
3695 \qmlproperty real QtQuick::Item::anchors.margins
3696 \qmlproperty real QtQuick::Item::anchors.topMargin
3697 \qmlproperty real QtQuick::Item::anchors.bottomMargin
3698 \qmlproperty real QtQuick::Item::anchors.leftMargin
3699 \qmlproperty real QtQuick::Item::anchors.rightMargin
3700 \qmlproperty real QtQuick::Item::anchors.horizontalCenterOffset
3701 \qmlproperty real QtQuick::Item::anchors.verticalCenterOffset
3702 \qmlproperty real QtQuick::Item::anchors.baselineOffset
3703
3704 \qmlproperty bool QtQuick::Item::anchors.alignWhenCentered
3705
3706 Anchors provide a way to position an item by specifying its
3707 relationship with other items.
3708
3709 Margins apply to top, bottom, left, right, and fill anchors.
3710 The \l anchors.margins property can be used to set all of the various margins at once, to the same value.
3711 It will not override a specific margin that has been previously set; to clear an explicit margin
3712 set its value to \c undefined.
3713 Note that margins are anchor-specific and are not applied if an item does not
3714 use anchors.
3715
3716 Offsets apply for horizontal center, vertical center, and baseline anchors.
3717
3718 \table
3719 \row
3720 \li \image declarative-anchors_example.png
3721 \li Text anchored to Image, horizontally centered and vertically below, with a margin.
3722 \qml
3723 Item {
3724 Image {
3725 id: pic
3726 // ...
3727 }
3728 Text {
3729 id: label
3730 anchors.horizontalCenter: pic.horizontalCenter
3731 anchors.top: pic.bottom
3732 anchors.topMargin: 5
3733 // ...
3734 }
3735 }
3736 \endqml
3737 \row
3738 \li \image declarative-anchors_example2.png
3739 \li
3740 Left of Text anchored to right of Image, with a margin. The y
3741 property of both defaults to 0.
3742
3743 \qml
3744 Item {
3745 Image {
3746 id: pic
3747 // ...
3748 }
3749 Text {
3750 id: label
3751 anchors.left: pic.right
3752 anchors.leftMargin: 5
3753 // ...
3754 }
3755 }
3756 \endqml
3757 \endtable
3758
3759 \l anchors.fill provides a convenient way for one item to have the
3760 same geometry as another item, and is equivalent to connecting all
3761 four directional anchors.
3762
3763 To clear an anchor value, set it to \c undefined.
3764
3765 \l anchors.alignWhenCentered (default \c true) forces centered anchors to align to a
3766 whole pixel; if the item being centered has an odd \l width or \l height, the item
3767 will be positioned on a whole pixel rather than being placed on a half-pixel.
3768 This ensures the item is painted crisply. There are cases where this is not
3769 desirable, for example when rotating the item jitters may be apparent as the
3770 center is rounded.
3771
3772 \note You can only anchor an item to siblings or a parent.
3773
3774 For more information see \l {anchor-layout}{Anchor Layouts}.
3775*/
3776QQuickAnchors *QQuickItemPrivate::anchors() const
3777{
3778 if (!_anchors) {
3779 Q_Q(const QQuickItem);
3780 _anchors = new QQuickAnchors(const_cast<QQuickItem *>(q));
3781 if (!componentComplete)
3782 _anchors->classBegin();
3783 }
3784 return _anchors;
3785}
3786
3787void QQuickItemPrivate::siblingOrderChanged()
3788{
3789 Q_Q(QQuickItem);
3790 notifyChangeListeners(QQuickItemPrivate::SiblingOrder, &QQuickItemChangeListener::itemSiblingOrderChanged, q);
3791}
3792
3793QQmlListProperty<QObject> QQuickItemPrivate::data()
3794{
3795 // Do not synthesize replace().
3796 // It would be extremely expensive and wouldn't work with most methods.
3797 QQmlListProperty<QObject> result;
3798 result.object = q_func();
3799 result.append = QQuickItemPrivate::data_append;
3800 result.count = QQuickItemPrivate::data_count;
3801 result.at = QQuickItemPrivate::data_at;
3802 result.clear = QQuickItemPrivate::data_clear;
3803 result.removeLast = QQuickItemPrivate::data_removeLast;
3804 return result;
3805}
3806
3807/*!
3808 \qmlpropertygroup QtQuick::Item::childrenRect
3809 \qmlproperty real QtQuick::Item::childrenRect.x
3810 \qmlproperty real QtQuick::Item::childrenRect.y
3811 \qmlproperty real QtQuick::Item::childrenRect.width
3812 \qmlproperty real QtQuick::Item::childrenRect.height
3813 \readonly
3814
3815 This read-only property holds the collective position and size of the item's
3816 children.
3817
3818 This property is useful if you need to access the collective geometry
3819 of an item's children in order to correctly size the item.
3820
3821 The geometry that is returned is local to the item. For example:
3822
3823 \snippet qml/item/childrenRect.qml local
3824*/
3825/*!
3826 \property QQuickItem::childrenRect
3827
3828 This property holds the collective position and size of the item's
3829 children.
3830
3831 This property is useful if you need to access the collective geometry
3832 of an item's children in order to correctly size the item.
3833
3834 The geometry that is returned is local to the item. For example:
3835
3836 \snippet qml/item/childrenRect.qml local
3837*/
3838QRectF QQuickItem::childrenRect()
3839{
3840 Q_D(QQuickItem);
3841 if (!d->extra.isAllocated() || !d->extra->contents) {
3842 d->extra.value().contents = new QQuickContents(this);
3843 if (d->componentComplete)
3844 d->extra->contents->complete();
3845 }
3846 return d->extra->contents->rectF();
3847}
3848
3849/*!
3850 Returns the children of this item.
3851 */
3852QList<QQuickItem *> QQuickItem::childItems() const
3853{
3854 Q_D(const QQuickItem);
3855 return d->childItems;
3856}
3857
3858/*!
3859 \qmlproperty bool QtQuick::Item::clip
3860 This property holds whether clipping is enabled. The default clip value is \c false.
3861
3862 If clipping is enabled, an item will clip its own painting, as well
3863 as the painting of its children, to its bounding rectangle.
3864
3865 \note Clipping can affect rendering performance. See \l {Clipping} for more
3866 information.
3867*/
3868/*!
3869 \property QQuickItem::clip
3870 This property holds whether clipping is enabled. The default clip value is \c false.
3871
3872 If clipping is enabled, an item will clip its own painting, as well
3873 as the painting of its children, to its bounding rectangle. If you set
3874 clipping during an item's paint operation, remember to re-set it to
3875 prevent clipping the rest of your scene.
3876
3877 \note Clipping can affect rendering performance. See \l {Clipping} for more
3878 information.
3879
3880 \note For the sake of QML, setting clip to \c true also sets the
3881 \l ItemIsViewport flag, which sometimes acts as an optimization: child items
3882 that have the \l ItemObservesViewport flag may forego creating scene graph nodes
3883 that fall outside the viewport. But the \c ItemIsViewport flag can also be set
3884 independently.
3885*/
3886bool QQuickItem::clip() const
3887{
3888 return flags() & ItemClipsChildrenToShape;
3889}
3890
3891void QQuickItem::setClip(bool c)
3892{
3893 if (clip() == c)
3894 return;
3895
3896 setFlag(ItemClipsChildrenToShape, c);
3897 if (c)
3898 setFlag(ItemIsViewport);
3899 else if (!(inherits("QQuickFlickable") || inherits("QQuickRootItem")))
3900 setFlag(ItemIsViewport, false);
3901
3902 emit clipChanged(c);
3903}
3904
3905/*!
3906 \since 6.0
3907
3908 This function is called to handle this item's changes in
3909 geometry from \a oldGeometry to \a newGeometry. If the two
3910 geometries are the same, it doesn't do anything.
3911
3912 Derived classes must call the base class method within their implementation.
3913 */
3914void QQuickItem::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
3915{
3916 Q_D(QQuickItem);
3917
3918 if (d->_anchors)
3919 QQuickAnchorsPrivate::get(d->_anchors)->updateMe();
3920
3921 QQuickGeometryChange change;
3922 change.setXChange(newGeometry.x() != oldGeometry.x());
3923 change.setYChange(newGeometry.y() != oldGeometry.y());
3924 change.setWidthChange(newGeometry.width() != oldGeometry.width());
3925 change.setHeightChange(newGeometry.height() != oldGeometry.height());
3926
3927 d->notifyChangeListeners(QQuickItemPrivate::Geometry, [&](const QQuickItemPrivate::ChangeListener &listener){
3928 if (change.matches(listener.gTypes))
3929 listener.listener->itemGeometryChanged(this, change, oldGeometry);
3930 });
3931
3932 // The notify method takes care of emitting the signal, and also notifies any
3933 // property observers.
3934 if (change.xChange())
3935 d->x.notify();
3936 if (change.yChange())
3937 d->y.notify();
3938 if (change.widthChange())
3939 d->width.notify();
3940 if (change.heightChange())
3941 d->height.notify();
3942#if QT_CONFIG(accessibility)
3943 if (d->isAccessible && QAccessible::isActive() && d->effectiveVisible) {
3944 QAccessibleEvent ev(this, QAccessible::LocationChanged);
3945 QAccessible::updateAccessibility(&ev);
3946 }
3947#endif
3948}
3949
3950/*!
3951 Called on the render thread when it is time to sync the state
3952 of the item with the scene graph.
3953
3954 The function is called as a result of QQuickItem::update(), if
3955 the user has set the QQuickItem::ItemHasContents flag on the item.
3956
3957 The function should return the root of the scene graph subtree for
3958 this item. Most implementations will return a single
3959 QSGGeometryNode containing the visual representation of this item.
3960 \a oldNode is the node that was returned the last time the
3961 function was called. \a updatePaintNodeData provides a pointer to
3962 the QSGTransformNode associated with this QQuickItem.
3963
3964 \code
3965 QSGNode *MyItem::updatePaintNode(QSGNode *node, UpdatePaintNodeData *)
3966 {
3967 QSGSimpleRectNode *n = static_cast<QSGSimpleRectNode *>(node);
3968 if (!n) {
3969 n = new QSGSimpleRectNode();
3970 n->setColor(Qt::red);
3971 }
3972 n->setRect(boundingRect());
3973 return n;
3974 }
3975 \endcode
3976
3977 The main thread is blocked while this function is executed so it is safe to read
3978 values from the QQuickItem instance and other objects in the main thread.
3979
3980 If no call to QQuickItem::updatePaintNode() result in actual scene graph
3981 changes, like QSGNode::markDirty() or adding and removing nodes, then
3982 the underlying implementation may decide to not render the scene again as
3983 the visual outcome is identical.
3984
3985 \warning It is crucial that graphics operations and interaction with
3986 the scene graph happens exclusively on the render thread,
3987 primarily during the QQuickItem::updatePaintNode() call. The best
3988 rule of thumb is to only use classes with the "QSG" prefix inside
3989 the QQuickItem::updatePaintNode() function.
3990
3991 \warning This function is called on the render thread. This means any
3992 QObjects or thread local storage that is created will have affinity to the
3993 render thread, so apply caution when doing anything other than rendering
3994 in this function. Similarly for signals, these will be emitted on the render
3995 thread and will thus often be delivered via queued connections.
3996
3997 \note All classes with QSG prefix should be used solely on the scene graph's
3998 rendering thread. See \l {Scene Graph and Rendering} for more information.
3999
4000 \sa QSGMaterial, QSGGeometryNode, QSGGeometry,
4001 QSGFlatColorMaterial, QSGTextureMaterial, QSGNode::markDirty(), {Graphics Resource Handling}
4002 */
4003
4004QSGNode *QQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData)
4005{
4006 Q_UNUSED(updatePaintNodeData);
4007 delete oldNode;
4008 return nullptr;
4009}
4010
4011QQuickItem::UpdatePaintNodeData::UpdatePaintNodeData()
4012: transformNode(nullptr)
4013{
4014}
4015
4016/*!
4017 This function is called when an item should release graphics
4018 resources which are not already managed by the nodes returned from
4019 QQuickItem::updatePaintNode().
4020
4021 This happens when the item is about to be removed from the window it
4022 was previously rendering to. The item is guaranteed to have a
4023 \l {QQuickItem::window()}{window} when the function is called.
4024
4025 The function is called on the GUI thread and the state of the
4026 rendering thread, when it is used, is unknown. Objects should
4027 not be deleted directly, but instead scheduled for cleanup
4028 using QQuickWindow::scheduleRenderJob().
4029
4030 \sa {Graphics Resource Handling}
4031 */
4032
4033void QQuickItem::releaseResources()
4034{
4035}
4036
4037QSGTransformNode *QQuickItemPrivate::createTransformNode()
4038{
4039 return new QSGTransformNode;
4040}
4041
4042/*!
4043 This function should perform any layout as required for this item.
4044
4045 When polish() is called, the scene graph schedules a polish event for this
4046 item. When the scene graph is ready to render this item, it calls
4047 updatePolish() to do any item layout as required before it renders the
4048 next frame.
4049
4050 \sa ensurePolished()
4051 */
4052void QQuickItem::updatePolish()
4053{
4054}
4055
4056#define PRINT_LISTENERS() do
4057 {
4058 qDebug().nospace() << q_func() << " (" << this
4059 << ") now has the following listeners:";
4060 for (const auto &listener : std::as_const(changeListeners)) {
4061 const auto objectPrivate = dynamic_cast<QObjectPrivate*>(listener.listener);
4062 qDebug().nospace() << "- " << listener << " (QObject: " << (objectPrivate ? objectPrivate->q_func() : nullptr) << ")";
4063 } \
4064}while
4065 (false)
4066
4067void QQuickItemPrivate::addItemChangeListener(QQuickItemChangeListener *listener, ChangeTypes types)
4068{
4069 Q_Q(QQuickItem);
4070 changeListeners.append(ChangeListener(listener, types));
4071 listener->addSourceItem(q);
4072
4073 if (lcChangeListeners().isDebugEnabled())
4075}
4076
4077void QQuickItemPrivate::updateOrAddItemChangeListener(QQuickItemChangeListener *listener, ChangeTypes types)
4078{
4079 Q_Q(QQuickItem);
4080
4081 const ChangeListener changeListener(listener, types);
4082 const int index = changeListeners.indexOf(changeListener);
4083 if (index > -1) {
4084 changeListeners[index].types = changeListener.types;
4085 } else {
4086 changeListeners.append(changeListener);
4087 listener->addSourceItem(q);
4088 }
4089
4090 if (lcChangeListeners().isDebugEnabled())
4092}
4093
4094void QQuickItemPrivate::removeItemChangeListener(QQuickItemChangeListener *listener, ChangeTypes types)
4095{
4096 Q_Q(QQuickItem);
4097
4098 ChangeListener change(listener, types);
4099 changeListeners.removeOne(change);
4100 listener->removeSourceItem(q);
4101
4102 if (lcChangeListeners().isDebugEnabled())
4104}
4105
4106void QQuickItemPrivate::updateOrAddGeometryChangeListener(QQuickItemChangeListener *listener,
4107 QQuickGeometryChange types)
4108{
4109 Q_Q(QQuickItem);
4110
4111 ChangeListener change(listener, types);
4112 int index = changeListeners.indexOf(change);
4113 if (index > -1) {
4114 changeListeners[index].gTypes = change.gTypes; //we may have different GeometryChangeTypes
4115 } else {
4116 changeListeners.append(change);
4117 listener->addSourceItem(q);
4118 }
4119
4120 if (lcChangeListeners().isDebugEnabled())
4122}
4123
4124void QQuickItemPrivate::updateOrRemoveGeometryChangeListener(QQuickItemChangeListener *listener,
4125 QQuickGeometryChange types)
4126{
4127 Q_Q(QQuickItem);
4128
4129 ChangeListener change(listener, types);
4130 if (types.noChange()) {
4131 changeListeners.removeOne(change);
4132 listener->removeSourceItem(q);
4133 } else {
4134 int index = changeListeners.indexOf(change);
4135 if (index > -1)
4136 changeListeners[index].gTypes = change.gTypes; //we may have different GeometryChangeTypes
4137 }
4138
4139 if (lcChangeListeners().isDebugEnabled())
4141}
4142
4143/*!
4144 This event handler can be reimplemented in a subclass to receive key
4145 press events for an item. The event information is provided by the
4146 \a event parameter.
4147
4148 \input item.qdocinc accepting-events
4149 */
4150void QQuickItem::keyPressEvent(QKeyEvent *event)
4151{
4152 event->ignore();
4153}
4154
4155/*!
4156 This event handler can be reimplemented in a subclass to receive key
4157 release 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::keyReleaseEvent(QKeyEvent *event)
4163{
4164 event->ignore();
4165}
4166
4167#if QT_CONFIG(im)
4168/*!
4169 This event handler can be reimplemented in a subclass to receive input
4170 method events for an item. The event information is provided by the
4171 \a event parameter.
4172
4173 \input item.qdocinc accepting-events
4174 */
4175void QQuickItem::inputMethodEvent(QInputMethodEvent *event)
4176{
4177 event->ignore();
4178}
4179#endif // im
4180
4181/*!
4182 This event handler can be reimplemented in a subclass to receive focus-in
4183 events for an item. The event information is provided by the \a event
4184 parameter.
4185
4186 \input item.qdocinc accepting-events
4187
4188 If you do reimplement this function, you should call the base class
4189 implementation.
4190 */
4191void QQuickItem::focusInEvent(QFocusEvent *event)
4192{
4193 Q_D(QQuickItem);
4194#if QT_CONFIG(accessibility)
4195 if (QAccessible::isActive()) {
4196 if (QObject *acc = QQuickAccessibleAttached::findAccessible(this)) {
4197 QAccessibleEvent ev(acc, QAccessible::Focus);
4198 QAccessible::updateAccessibility(&ev);
4199 }
4200 }
4201#endif
4202 d->setLastFocusChangeReason(event->reason());
4203}
4204
4205/*!
4206 This event handler can be reimplemented in a subclass to receive focus-out
4207 events for an item. The event information is provided by the \a event
4208 parameter.
4209
4210 \input item.qdocinc accepting-events
4211 */
4212void QQuickItem::focusOutEvent(QFocusEvent *event)
4213{
4214 Q_D(QQuickItem);
4215 d->setLastFocusChangeReason(event->reason());
4216}
4217
4218/*!
4219 This event handler can be reimplemented in a subclass to receive mouse
4220 press events for an item. The event information is provided by the
4221 \a event parameter.
4222
4223 In order to receive mouse press events, \l acceptedMouseButtons() must
4224 return the relevant mouse button.
4225
4226 \input item.qdocinc accepting-events
4227 */
4228void QQuickItem::mousePressEvent(QMouseEvent *event)
4229{
4230 event->ignore();
4231}
4232
4233/*!
4234 This event handler can be reimplemented in a subclass to receive mouse
4235 move events for an item. The event information is provided by the
4236 \a event parameter.
4237
4238 In order to receive mouse movement events, the preceding mouse press event
4239 must be accepted (by overriding \l mousePressEvent(), for example) and
4240 \l acceptedMouseButtons() must return the relevant mouse button.
4241
4242 \input item.qdocinc accepting-events
4243 */
4244void QQuickItem::mouseMoveEvent(QMouseEvent *event)
4245{
4246 event->ignore();
4247}
4248
4249/*!
4250 This event handler can be reimplemented in a subclass to receive mouse
4251 release events for an item. The event information is provided by the
4252 \a event parameter.
4253
4254 In order to receive mouse release events, the preceding mouse press event
4255 must be accepted (by overriding \l mousePressEvent(), for example) and
4256 \l acceptedMouseButtons() must return the relevant mouse button.
4257
4258 \input item.qdocinc accepting-events
4259 */
4260void QQuickItem::mouseReleaseEvent(QMouseEvent *event)
4261{
4262 event->ignore();
4263}
4264
4265/*!
4266 This event handler can be reimplemented in a subclass to receive mouse
4267 double-click events for an item. The event information is provided by the
4268 \a event parameter.
4269
4270 \input item.qdocinc accepting-events
4271 */
4272void QQuickItem::mouseDoubleClickEvent(QMouseEvent *event)
4273{
4274 event->ignore();
4275}
4276
4277/*!
4278 This event handler can be reimplemented in a subclass to be notified
4279 when a mouse ungrab event has occurred on this item.
4280 */
4281void QQuickItem::mouseUngrabEvent()
4282{
4283 // XXX todo
4284}
4285
4286/*!
4287 This event handler can be reimplemented in a subclass to be notified
4288 when a touch ungrab event has occurred on this item.
4289 */
4290void QQuickItem::touchUngrabEvent()
4291{
4292 // XXX todo
4293}
4294
4295#if QT_CONFIG(wheelevent)
4296/*!
4297 This event handler can be reimplemented in a subclass to receive
4298 wheel events for an item. The event information is provided by the
4299 \a event parameter.
4300
4301 \input item.qdocinc accepting-events
4302 */
4303void QQuickItem::wheelEvent(QWheelEvent *event)
4304{
4305 event->ignore();
4306}
4307#endif
4308
4309/*!
4310 This event handler can be reimplemented in a subclass to receive touch
4311 events for an item. The event information is provided by the
4312 \a event parameter.
4313
4314 \input item.qdocinc accepting-events
4315 */
4316void QQuickItem::touchEvent(QTouchEvent *event)
4317{
4318 event->ignore();
4319}
4320
4321/*!
4322 This event handler can be reimplemented in a subclass to receive hover-enter
4323 events for an item. The event information is provided by the
4324 \a event parameter.
4325
4326 Hover events are only provided if acceptHoverEvents() is true.
4327
4328 \input item.qdocinc accepting-events
4329 */
4330void QQuickItem::hoverEnterEvent(QHoverEvent *event)
4331{
4332 event->ignore();
4333}
4334
4335/*!
4336 This event handler can be reimplemented in a subclass to receive hover-move
4337 events for an item. The event information is provided by the
4338 \a event parameter.
4339
4340 Hover events are only provided if acceptHoverEvents() is true.
4341
4342 \input item.qdocinc accepting-events
4343 */
4344void QQuickItem::hoverMoveEvent(QHoverEvent *event)
4345{
4346 event->ignore();
4347}
4348
4349/*!
4350 This event handler can be reimplemented in a subclass to receive hover-leave
4351 events for an item. The event information is provided by the
4352 \a event parameter.
4353
4354 Hover events are only provided if acceptHoverEvents() is true.
4355
4356 \input item.qdocinc accepting-events
4357 */
4358void QQuickItem::hoverLeaveEvent(QHoverEvent *event)
4359{
4360 event->ignore();
4361}
4362
4363#if QT_CONFIG(quick_draganddrop)
4364/*!
4365 This event handler can be reimplemented in a subclass to receive drag-enter
4366 events for an item. The event information is provided by the
4367 \a event parameter.
4368
4369 Drag and drop events are only provided if the ItemAcceptsDrops flag
4370 has been set for this item.
4371
4372 \input item.qdocinc accepting-events
4373
4374 \sa Drag, {Drag and Drop}
4375 */
4376void QQuickItem::dragEnterEvent(QDragEnterEvent *event)
4377{
4378 Q_UNUSED(event);
4379}
4380
4381/*!
4382 This event handler can be reimplemented in a subclass to receive drag-move
4383 events for an item. The event information is provided by the
4384 \a event parameter.
4385
4386 Drag and drop events are only provided if the ItemAcceptsDrops flag
4387 has been set for this item.
4388
4389 \input item.qdocinc accepting-events
4390
4391 \sa Drag, {Drag and Drop}
4392 */
4393void QQuickItem::dragMoveEvent(QDragMoveEvent *event)
4394{
4395 Q_UNUSED(event);
4396}
4397
4398/*!
4399 This event handler can be reimplemented in a subclass to receive drag-leave
4400 events for an item. The event information is provided by the
4401 \a event parameter.
4402
4403 Drag and drop events are only provided if the ItemAcceptsDrops flag
4404 has been set for this item.
4405
4406 \input item.qdocinc accepting-events
4407
4408 \sa Drag, {Drag and Drop}
4409 */
4410void QQuickItem::dragLeaveEvent(QDragLeaveEvent *event)
4411{
4412 Q_UNUSED(event);
4413}
4414
4415/*!
4416 This event handler can be reimplemented in a subclass to receive drop
4417 events for an item. The event information is provided by the
4418 \a event parameter.
4419
4420 Drag and drop events are only provided if the ItemAcceptsDrops flag
4421 has been set for this item.
4422
4423 \input item.qdocinc accepting-events
4424
4425 \sa Drag, {Drag and Drop}
4426 */
4427void QQuickItem::dropEvent(QDropEvent *event)
4428{
4429 Q_UNUSED(event);
4430}
4431#endif // quick_draganddrop
4432
4433/*!
4434 Reimplement this method to filter the pointer events that are received by
4435 this item's children.
4436
4437 This method will only be called if filtersChildMouseEvents() is \c true.
4438
4439 Return \c true if the specified \a event should not be passed on to the
4440 specified child \a item, and \c false otherwise. If you return \c true, you
4441 should also \l {QEvent::accept()}{accept} or \l {QEvent::ignore()}{ignore}
4442 the \a event, to signal if event propagation should stop or continue.
4443 The \a event will, however, always be sent to all childMouseEventFilters
4444 up the parent chain.
4445
4446 \note Despite the name, this function filters all QPointerEvent instances
4447 during delivery to all children (typically mouse, touch, and tablet
4448 events). When overriding this function in a subclass, we suggest writing
4449 generic event-handling code using only the accessors found in
4450 QPointerEvent. Alternatively you can switch on \c event->type() and/or
4451 \c event->device()->type() to handle different event types in different ways.
4452
4453 \note Filtering is just one way to share responsibility in case of gestural
4454 ambiguity (for example on press, you don't know whether the user will tap
4455 or drag). Another way is to call QPointerEvent::addPassiveGrabber() on
4456 press, so as to non-exclusively monitor the progress of the QEventPoint.
4457 In either case, the item or pointer handler that is monitoring can steal
4458 the exclusive grab later on, when it becomes clear that the gesture fits
4459 the pattern that it is expecting.
4460
4461 \sa setFiltersChildMouseEvents()
4462 */
4463bool QQuickItem::childMouseEventFilter(QQuickItem *item, QEvent *event)
4464{
4465 Q_UNUSED(item);
4466 Q_UNUSED(event);
4467 return false;
4468}
4469
4470#if QT_CONFIG(im)
4471/*!
4472 This method is only relevant for input items.
4473
4474 If this item is an input item, this method should be reimplemented to
4475 return the relevant input method flags for the given \a query.
4476
4477 \sa QWidget::inputMethodQuery()
4478 */
4479QVariant QQuickItem::inputMethodQuery(Qt::InputMethodQuery query) const
4480{
4481 Q_D(const QQuickItem);
4482 QVariant v;
4483
4484 switch (query) {
4485 case Qt::ImEnabled:
4486 v = (bool)(flags() & ItemAcceptsInputMethod);
4487 break;
4488 case Qt::ImHints:
4489 case Qt::ImAnchorRectangle:
4490 case Qt::ImCursorRectangle:
4491 case Qt::ImFont:
4492 case Qt::ImCursorPosition:
4493 case Qt::ImSurroundingText:
4494 case Qt::ImCurrentSelection:
4495 case Qt::ImMaximumTextLength:
4496 case Qt::ImAnchorPosition:
4497 case Qt::ImPreferredLanguage:
4498 case Qt::ImReadOnly:
4499 if (d->extra.isAllocated() && d->extra->keyHandler)
4500 v = d->extra->keyHandler->inputMethodQuery(query);
4501 break;
4502 case Qt::ImEnterKeyType:
4503 if (d->extra.isAllocated() && d->extra->enterKeyAttached)
4504 v = d->extra->enterKeyAttached->type();
4505 break;
4506 case Qt::ImInputItemClipRectangle:
4507 if (!(!window() ||!isVisible() || qFuzzyIsNull(opacity()))) {
4508 QRectF rect = QRectF(0,0, width(), height());
4509 const QQuickItem *par = this;
4510 while (QQuickItem *parpar = par->parentItem()) {
4511 rect = parpar->mapRectFromItem(par, rect);
4512 if (parpar->clip())
4513 rect = rect.intersected(parpar->clipRect());
4514 par = parpar;
4515 }
4516 rect = par->mapRectToScene(rect);
4517 // once we have the rect in scene coordinates, clip to window
4518 rect = rect.intersected(QRectF(QPoint(0,0), window()->size()));
4519 // map it back to local coordinates
4520 v = mapRectFromScene(rect);
4521 }
4522 break;
4523 default:
4524 break;
4525 }
4526
4527 return v;
4528}
4529#endif // im
4530
4531QQuickAnchorLine QQuickItemPrivate::left() const
4532{
4533 Q_Q(const QQuickItem);
4534 return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchors::LeftAnchor);
4535}
4536
4537QQuickAnchorLine QQuickItemPrivate::right() const
4538{
4539 Q_Q(const QQuickItem);
4540 return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchors::RightAnchor);
4541}
4542
4543QQuickAnchorLine QQuickItemPrivate::horizontalCenter() const
4544{
4545 Q_Q(const QQuickItem);
4546 return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchors::HCenterAnchor);
4547}
4548
4549QQuickAnchorLine QQuickItemPrivate::top() const
4550{
4551 Q_Q(const QQuickItem);
4552 return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchors::TopAnchor);
4553}
4554
4555QQuickAnchorLine QQuickItemPrivate::bottom() const
4556{
4557 Q_Q(const QQuickItem);
4558 return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchors::BottomAnchor);
4559}
4560
4561QQuickAnchorLine QQuickItemPrivate::verticalCenter() const
4562{
4563 Q_Q(const QQuickItem);
4564 return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchors::VCenterAnchor);
4565}
4566
4567QQuickAnchorLine QQuickItemPrivate::baseline() const
4568{
4569 Q_Q(const QQuickItem);
4570 return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchors::BaselineAnchor);
4571}
4572
4573/*!
4574 \qmlproperty int QtQuick::Item::baselineOffset
4575
4576 Specifies the position of the item's baseline in local coordinates.
4577
4578 The baseline of a \l Text item is the imaginary line on which the text
4579 sits. Controls containing text usually set their baseline to the
4580 baseline of their text.
4581
4582 For non-text items, a default baseline offset of 0 is used.
4583*/
4584/*!
4585 \property QQuickItem::baselineOffset
4586
4587 Specifies the position of the item's baseline in local coordinates.
4588
4589 The baseline of a \l Text item is the imaginary line on which the text
4590 sits. Controls containing text usually set their baseline to the
4591 baseline of their text.
4592
4593 For non-text items, a default baseline offset of 0 is used.
4594*/
4595qreal QQuickItem::baselineOffset() const
4596{
4597 Q_D(const QQuickItem);
4598 return d->baselineOffset;
4599}
4600
4601void QQuickItem::setBaselineOffset(qreal offset)
4602{
4603 Q_D(QQuickItem);
4604 if (offset == d->baselineOffset)
4605 return;
4606
4607 d->baselineOffset = offset;
4608
4609 d->notifyChangeListeners(QQuickItemPrivate::Geometry, [](const QQuickItemPrivate::ChangeListener &change){
4610 QQuickAnchorsPrivate *anchor = change.listener->anchorPrivate();
4611 if (anchor)
4612 anchor->updateVerticalAnchors();
4613 });
4614
4615 if (d->_anchors && (d->_anchors->usedAnchors() & QQuickAnchors::BaselineAnchor))
4616 QQuickAnchorsPrivate::get(d->_anchors)->updateVerticalAnchors();
4617
4618 emit baselineOffsetChanged(offset);
4619}
4620
4621
4622/*!
4623 * Schedules a call to updatePaintNode() for this item.
4624 *
4625 * The call to QQuickItem::updatePaintNode() will always happen if the
4626 * item is showing in a QQuickWindow.
4627 *
4628 * Only items which specify QQuickItem::ItemHasContents are allowed
4629 * to call QQuickItem::update().
4630 */
4631void QQuickItem::update()
4632{
4633 Q_D(QQuickItem);
4634 if (!(flags() & ItemHasContents)) {
4635#ifndef QT_NO_DEBUG
4636 qWarning() << metaObject()->className() << ": Update called for a item without content";
4637#endif
4638 return;
4639 }
4640 d->dirty(QQuickItemPrivate::Content);
4641}
4642
4643/*!
4644 Schedules a polish event for this item.
4645
4646 When the scene graph processes the request, it will call updatePolish()
4647 on this item.
4648
4649 \sa updatePolish(), QQuickTest::qIsPolishScheduled(), ensurePolished()
4650 */
4651void QQuickItem::polish()
4652{
4653 Q_D(QQuickItem);
4654 if (!d->polishScheduled) {
4655 d->polishScheduled = true;
4656 if (d->window) {
4657 QQuickWindowPrivate *p = QQuickWindowPrivate::get(d->window);
4658 bool maybeupdate = p->itemsToPolish.isEmpty();
4659 p->itemsToPolish.append(this);
4660 if (maybeupdate) d->window->maybeUpdate();
4661 }
4662 }
4663}
4664
4665/*!
4666 \since 6.3
4667
4668 Calls updatePolish()
4669
4670 This can be useful for items such as Layouts (or Positioners) which delay calculation of
4671 their implicitWidth and implicitHeight until they receive a PolishEvent.
4672
4673 Normally, if e.g. a child item is added or removed to a Layout, the implicit size is not
4674 immediately calculated (this is an optimization). In some cases it might be desirable to
4675 query the implicit size of the layout right after a child item has been added.
4676 If this is the case, use this function right before querying the implicit size.
4677
4678 \sa updatePolish(), polish()
4679 */
4680void QQuickItem::ensurePolished()
4681{
4682 updatePolish();
4683}
4684
4685#if QT_DEPRECATED_SINCE(6, 5)
4686static bool unwrapMapFromToFromItemArgs(QQmlV4FunctionPtr args, const QQuickItem *itemForWarning, const QString &functionNameForWarning,
4687 QQuickItem **itemObj, qreal *x, qreal *y, qreal *w, qreal *h, bool *isRect)
4688{
4689 QV4::ExecutionEngine *v4 = args->v4engine();
4690 if (args->length() != 2 && args->length() != 3 && args->length() != 5) {
4691 v4->throwTypeError();
4692 return false;
4693 }
4694
4695 QV4::Scope scope(v4);
4696 QV4::ScopedValue item(scope, (*args)[0]);
4697
4698 *itemObj = nullptr;
4699 if (!item->isNull()) {
4700 QV4::Scoped<QV4::QObjectWrapper> qobjectWrapper(scope, item->as<QV4::QObjectWrapper>());
4701 if (qobjectWrapper)
4702 *itemObj = qobject_cast<QQuickItem*>(qobjectWrapper->object());
4703 }
4704
4705 if (!(*itemObj) && !item->isNull()) {
4706 qmlWarning(itemForWarning) << functionNameForWarning << " given argument \"" << item->toQStringNoThrow()
4707 << "\" which is neither null nor an Item";
4708 v4->throwTypeError();
4709 return false;
4710 }
4711
4712 *isRect = false;
4713
4714 if (args->length() == 2) {
4715 QV4::ScopedValue sv(scope, (*args)[1]);
4716 if (sv->isNull()) {
4717 qmlWarning(itemForWarning) << functionNameForWarning << "given argument \"" << sv->toQStringNoThrow()
4718 << "\" which is neither a point nor a rect";
4719 v4->throwTypeError();
4720 return false;
4721 }
4722 const QV4::Scoped<QV4::QQmlValueTypeWrapper> variantWrapper(scope, sv->as<QV4::QQmlValueTypeWrapper>());
4723 const QVariant v = variantWrapper ? variantWrapper->toVariant() : QVariant();
4724 if (v.canConvert<QPointF>()) {
4725 const QPointF p = v.toPointF();
4726 *x = p.x();
4727 *y = p.y();
4728 } else if (v.canConvert<QRectF>()) {
4729 const QRectF r = v.toRectF();
4730 *x = r.x();
4731 *y = r.y();
4732 *w = r.width();
4733 *h = r.height();
4734 *isRect = true;
4735 } else {
4736 qmlWarning(itemForWarning) << functionNameForWarning << "given argument \"" << sv->toQStringNoThrow()
4737 << "\" which is neither a point nor a rect";
4738 v4->throwTypeError();
4739 return false;
4740 }
4741 } else {
4742 QV4::ScopedValue vx(scope, (*args)[1]);
4743 QV4::ScopedValue vy(scope, (*args)[2]);
4744
4745 if (!vx->isNumber() || !vy->isNumber()) {
4746 v4->throwTypeError();
4747 return false;
4748 }
4749
4750 *x = vx->asDouble();
4751 *y = vy->asDouble();
4752
4753 if (args->length() > 3) {
4754 QV4::ScopedValue vw(scope, (*args)[3]);
4755 QV4::ScopedValue vh(scope, (*args)[4]);
4756 if (!vw->isNumber() || !vh->isNumber()) {
4757 v4->throwTypeError();
4758 return false;
4759 }
4760 *w = vw->asDouble();
4761 *h = vh->asDouble();
4762 *isRect = true;
4763 }
4764 }
4765
4766 return true;
4767}
4768#endif
4769
4770/*!
4771 \qmlmethod point QtQuick::Item::mapFromItem(Item item, real x, real y)
4772 \qmlmethod point QtQuick::Item::mapFromItem(Item item, point p)
4773 \qmlmethod rect QtQuick::Item::mapFromItem(Item item, real x, real y, real width, real height)
4774 \qmlmethod rect QtQuick::Item::mapFromItem(Item item, rect r)
4775
4776 Maps the point (\a x, \a y) or rect (\a x, \a y, \a width, \a height), which is in \a
4777 item's coordinate system, to this item's coordinate system, and returns a \l point or \l rect
4778 matching the mapped coordinate.
4779
4780 \input item.qdocinc mapping
4781
4782 If \a item is a \c null value, this maps the point or rect from the coordinate system of
4783 the \l{Scene Coordinates}{scene}.
4784
4785 The versions accepting point and rect are since Qt 5.15.
4786*/
4787
4788#if QT_DEPRECATED_SINCE(6, 5)
4789/*!
4790 \internal
4791 */
4792void QQuickItem::mapFromItem(QQmlV4FunctionPtr args) const
4793{
4794 QV4::ExecutionEngine *v4 = args->v4engine();
4795 QV4::Scope scope(v4);
4796
4797 qreal x, y, w, h;
4798 bool isRect;
4799 QQuickItem *itemObj;
4800 if (!unwrapMapFromToFromItemArgs(args, this, QStringLiteral("mapFromItem()"), &itemObj, &x, &y, &w, &h, &isRect))
4801 return;
4802
4803 const QVariant result = isRect ? QVariant(mapRectFromItem(itemObj, QRectF(x, y, w, h)))
4804 : QVariant(mapFromItem(itemObj, QPointF(x, y)));
4805
4806 QV4::ScopedObject rv(scope, v4->fromVariant(result));
4807 args->setReturnValue(rv.asReturnedValue());
4808}
4809#endif
4810
4811/*!
4812 \internal
4813 */
4814QTransform QQuickItem::itemTransform(QQuickItem *other, bool *ok) const
4815{
4816 Q_D(const QQuickItem);
4817
4818 // XXX todo - we need to be able to handle common parents better and detect
4819 // invalid cases
4820 if (ok) *ok = true;
4821
4822 QTransform t = d->itemToWindowTransform();
4823 if (other) t *= QQuickItemPrivate::get(other)->windowToItemTransform();
4824
4825 return t;
4826}
4827
4828/*!
4829 \qmlmethod point QtQuick::Item::mapToItem(Item item, real x, real y)
4830 \qmlmethod point QtQuick::Item::mapToItem(Item item, point p)
4831 \qmlmethod rect QtQuick::Item::mapToItem(Item item, real x, real y, real width, real height)
4832 \qmlmethod rect QtQuick::Item::mapToItem(Item item, rect r)
4833
4834 Maps the point (\a x, \a y) or rect (\a x, \a y, \a width, \a height), which is in this
4835 item's coordinate system, to \a item's coordinate system, and returns a \l point or \l rect
4836 matching the mapped coordinate.
4837
4838 \input item.qdocinc mapping
4839
4840 If \a item is a \c null value, this maps the point or rect to the coordinate system of the
4841 \l{Scene Coordinates}{scene}.
4842
4843 The versions accepting point and rect are since Qt 5.15.
4844*/
4845
4846#if QT_DEPRECATED_SINCE(6, 5)
4847/*!
4848 \internal
4849 */
4850void QQuickItem::mapToItem(QQmlV4FunctionPtr args) const
4851{
4852 QV4::ExecutionEngine *v4 = args->v4engine();
4853 QV4::Scope scope(v4);
4854
4855 qreal x, y, w, h;
4856 bool isRect;
4857 QQuickItem *itemObj;
4858 if (!unwrapMapFromToFromItemArgs(args, this, QStringLiteral("mapToItem()"), &itemObj, &x, &y, &w, &h, &isRect))
4859 return;
4860
4861 const QVariant result = isRect ? QVariant(mapRectToItem(itemObj, QRectF(x, y, w, h)))
4862 : QVariant(mapToItem(itemObj, QPointF(x, y)));
4863
4864 QV4::ScopedObject rv(scope, v4->fromVariant(result));
4865 args->setReturnValue(rv.asReturnedValue());
4866}
4867
4868static bool unwrapMapFromToFromGlobalArgs(QQmlV4FunctionPtr args, const QQuickItem *itemForWarning, const QString &functionNameForWarning, qreal *x, qreal *y)
4869{
4870 QV4::ExecutionEngine *v4 = args->v4engine();
4871 if (args->length() != 1 && args->length() != 2) {
4872 v4->throwTypeError();
4873 return false;
4874 }
4875
4876 QV4::Scope scope(v4);
4877
4878 if (args->length() == 1) {
4879 QV4::ScopedValue sv(scope, (*args)[0]);
4880 if (sv->isNull()) {
4881 qmlWarning(itemForWarning) << functionNameForWarning << "given argument \"" << sv->toQStringNoThrow()
4882 << "\" which is not a point";
4883 v4->throwTypeError();
4884 return false;
4885 }
4886 const QV4::Scoped<QV4::QQmlValueTypeWrapper> variantWrapper(scope, sv->as<QV4::QQmlValueTypeWrapper>());
4887 const QVariant v = variantWrapper ? variantWrapper->toVariant() : QVariant();
4888 if (v.canConvert<QPointF>()) {
4889 const QPointF p = v.toPointF();
4890 *x = p.x();
4891 *y = p.y();
4892 } else {
4893 qmlWarning(itemForWarning) << functionNameForWarning << "given argument \"" << sv->toQStringNoThrow()
4894 << "\" which is not a point";
4895 v4->throwTypeError();
4896 return false;
4897 }
4898 } else {
4899 QV4::ScopedValue vx(scope, (*args)[0]);
4900 QV4::ScopedValue vy(scope, (*args)[1]);
4901
4902 if (!vx->isNumber() || !vy->isNumber()) {
4903 v4->throwTypeError();
4904 return false;
4905 }
4906
4907 *x = vx->asDouble();
4908 *y = vy->asDouble();
4909 }
4910
4911 return true;
4912}
4913
4914/*!
4915 \since 5.7
4916 \qmlmethod point QtQuick::Item::mapFromGlobal(real x, real y)
4917
4918 Maps the point (\a x, \a y), which is in the global coordinate system, to the
4919 item's coordinate system, and returns a \l point matching the mapped coordinate.
4920
4921 \input item.qdocinc mapping
4922*/
4923/*!
4924 \internal
4925 */
4926void QQuickItem::mapFromGlobal(QQmlV4FunctionPtr args) const
4927{
4928 QV4::ExecutionEngine *v4 = args->v4engine();
4929 QV4::Scope scope(v4);
4930
4931 qreal x, y;
4932 if (!unwrapMapFromToFromGlobalArgs(args, this, QStringLiteral("mapFromGlobal()"), &x, &y))
4933 return;
4934
4935 QVariant result = mapFromGlobal(QPointF(x, y));
4936
4937 QV4::ScopedObject rv(scope, v4->fromVariant(result));
4938 args->setReturnValue(rv.asReturnedValue());
4939}
4940#endif
4941
4942/*!
4943 \since 5.7
4944 \qmlmethod point QtQuick::Item::mapToGlobal(real x, real y)
4945
4946 Maps the point (\a x, \a y), which is in this item's coordinate system, to the
4947 global coordinate system, and returns a \l point matching the mapped coordinate.
4948
4949 \input item.qdocinc mapping
4950*/
4951
4952#if QT_DEPRECATED_SINCE(6, 5)
4953/*!
4954 \internal
4955 */
4956void QQuickItem::mapToGlobal(QQmlV4FunctionPtr args) const
4957{
4958 QV4::ExecutionEngine *v4 = args->v4engine();
4959 QV4::Scope scope(v4);
4960
4961 qreal x, y;
4962 if (!unwrapMapFromToFromGlobalArgs(args, this, QStringLiteral("mapFromGlobal()"), &x, &y))
4963 return;
4964
4965 QVariant result = mapToGlobal(QPointF(x, y));
4966
4967 QV4::ScopedObject rv(scope, v4->fromVariant(result));
4968 args->setReturnValue(rv.asReturnedValue());
4969}
4970#endif
4971
4972/*!
4973 \qmlmethod QtQuick::Item::forceActiveFocus()
4974
4975 Forces active focus on the item.
4976
4977 This method sets focus on the item and ensures that all ancestor
4978 FocusScope objects in the object hierarchy are also given \l focus.
4979
4980 The reason for the focus change will be \l [CPP] Qt::OtherFocusReason. Use
4981 the overloaded method to specify the focus reason to enable better
4982 handling of the focus change.
4983
4984 \sa activeFocus
4985*/
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*/
4998void QQuickItem::forceActiveFocus()
4999{
5000 forceActiveFocus(Qt::OtherFocusReason);
5001}
5002
5003/*!
5004 \qmlmethod QtQuick::Item::forceActiveFocus(Qt::FocusReason reason)
5005 \overload
5006
5007 Forces active focus on the item with the given \a reason.
5008
5009 This method sets focus on the item and ensures that all ancestor
5010 FocusScope objects in the object hierarchy are also given \l focus.
5011
5012 \since 5.1
5013
5014 \sa activeFocus, Qt::FocusReason
5015*/
5016/*!
5017 \overload
5018 Forces active focus on the item with the given \a reason.
5019
5020 This method sets focus on the item and ensures that all ancestor
5021 FocusScope objects in the object hierarchy are also given \l focus.
5022
5023 \since 5.1
5024
5025 \sa activeFocus, Qt::FocusReason
5026*/
5027
5028void QQuickItem::forceActiveFocus(Qt::FocusReason reason)
5029{
5030 setFocus(true, reason);
5031 QQuickItem *parent = parentItem();
5032 QQuickItem *scope = nullptr;
5033 while (parent) {
5034 if (parent->flags() & QQuickItem::ItemIsFocusScope) {
5035 parent->setFocus(true, reason);
5036 if (!scope)
5037 scope = parent;
5038 }
5039 parent = parent->parentItem();
5040 }
5041}
5042
5043/*!
5044 \qmlmethod Item QtQuick::Item::nextItemInFocusChain(bool forward)
5045
5046 \since 5.1
5047
5048 Returns the item in the focus chain which is next to this item.
5049 If \a forward is \c true, or not supplied, it is the next item in
5050 the forwards direction. If \a forward is \c false, it is the next
5051 item in the backwards direction.
5052*/
5053/*!
5054 Returns the item in the focus chain which is next to this item.
5055 If \a forward is \c true, or not supplied, it is the next item in
5056 the forwards direction. If \a forward is \c false, it is the next
5057 item in the backwards direction.
5058*/
5059
5060QQuickItem *QQuickItem::nextItemInFocusChain(bool forward)
5061{
5062 return QQuickItemPrivate::nextPrevItemInTabFocusChain(this, forward);
5063}
5064
5065/*!
5066 \qmlmethod Item QtQuick::Item::childAt(real x, real y)
5067
5068 Returns the first visible child item found at point (\a x, \a y) within
5069 the coordinate system of this item.
5070
5071 Returns \c null if there is no such item.
5072*/
5073/*!
5074 Returns the first visible child item found at point (\a x, \a y) within
5075 the coordinate system of this item.
5076
5077 Returns \nullptr if there is no such item.
5078*/
5079QQuickItem *QQuickItem::childAt(qreal x, qreal y) const
5080{
5081 const QList<QQuickItem *> children = childItems();
5082 for (int i = children.size()-1; i >= 0; --i) {
5083 QQuickItem *child = children.at(i);
5084 // Map coordinates to the child element's coordinate space
5085 QPointF point = mapToItem(child, QPointF(x, y));
5086 if (child->isVisible() && child->contains(point))
5087 return child;
5088 }
5089 return nullptr;
5090}
5091
5092/*!
5093 \qmlmethod QtQuick::Item::dumpItemTree()
5094
5095 Dumps some details about the
5096 \l {Concepts - Visual Parent in Qt Quick}{visual tree of Items} starting
5097 with this item and its children, recursively.
5098
5099 The output looks similar to that of this QML code:
5100
5101 \qml
5102 function dump(object, indent) {
5103 console.log(indent + object)
5104 for (const i in object.children)
5105 dump(object.children[i], indent + " ")
5106 }
5107
5108 dump(myItem, "")
5109 \endqml
5110
5111 So if you want more details, you can implement your own function and add
5112 extra output to the console.log, such as values of specific properties.
5113
5114 \sa QObject::dumpObjectTree()
5115 \since 6.3
5116*/
5117/*!
5118 Dumps some details about the
5119 \l {Concepts - Visual Parent in Qt Quick}{visual tree of Items} starting
5120 with this item, recursively.
5121
5122 \note QObject::dumpObjectTree() dumps a similar tree; but, as explained
5123 in \l {Concepts - Visual Parent in Qt Quick}, an item's QObject::parent()
5124 sometimes differs from its QQuickItem::parentItem(). You can dump
5125 both trees to see the difference.
5126
5127 \note The exact output format may change in future versions of Qt.
5128
5129 \since 6.3
5130 \sa {Debugging Techniques}
5131 \sa {https://doc.qt.io/GammaRay/gammaray-qtquick2-inspector.html}{GammaRay's Qt Quick Inspector}
5132*/
5133void QQuickItem::dumpItemTree() const
5134{
5135 Q_D(const QQuickItem);
5136 d->dumpItemTree(0);
5137}
5138
5139void QQuickItemPrivate::dumpItemTree(int indent) const
5140{
5141 Q_Q(const QQuickItem);
5142
5143 const auto indentStr = QString(indent * 4, QLatin1Char(' '));
5144 qDebug().nospace().noquote() << indentStr <<
5145#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
5146 const_cast<QQuickItem *>(q);
5147#else
5148 q;
5149#endif
5150 if (extra.isAllocated()) {
5151 for (const auto handler : extra->pointerHandlers)
5152 qDebug().nospace().noquote() << indentStr << u" \u26ee " << handler;
5153 }
5154 for (const QQuickItem *ch : childItems) {
5155 auto itemPriv = QQuickItemPrivate::get(ch);
5156 itemPriv->dumpItemTree(indent + 1);
5157 }
5158}
5159
5160QQmlListProperty<QObject> QQuickItemPrivate::resources()
5161{
5162 // Do not synthesize replace().
5163 // It would be extremely expensive and wouldn't work with most methods.
5164 QQmlListProperty<QObject> result;
5165 result.object = q_func();
5166 result.append = QQuickItemPrivate::resources_append;
5167 result.count = QQuickItemPrivate::resources_count;
5168 result.at = QQuickItemPrivate::resources_at;
5169 result.clear = QQuickItemPrivate::resources_clear;
5170 result.removeLast = QQuickItemPrivate::resources_removeLast;
5171 return result;
5172}
5173
5174/*!
5175 \qmlproperty list<Item> QtQuick::Item::children
5176 \qmlproperty list<QtObject> QtQuick::Item::resources
5177
5178 The children property contains the list of visual children of this item.
5179 The resources property contains non-visual resources that you want to
5180 reference by name.
5181
5182 It is not generally necessary to refer to these properties when adding
5183 child items or resources, as the default \l data property will
5184 automatically assign child objects to the \c children and \c resources
5185 properties as appropriate. See the \l data documentation for details.
5186*/
5187/*!
5188 \property QQuickItem::children
5189 \internal
5190*/
5191QQmlListProperty<QQuickItem> QQuickItemPrivate::children()
5192{
5193 // Do not synthesize replace().
5194 // It would be extremely expensive and wouldn't work with most methods.
5195 QQmlListProperty<QQuickItem> result;
5196 result.object = q_func();
5197 result.append = QQuickItemPrivate::children_append;
5198 result.count = QQuickItemPrivate::children_count;
5199 result.at = QQuickItemPrivate::children_at;
5200 result.clear = QQuickItemPrivate::children_clear;
5201 result.removeLast = QQuickItemPrivate::children_removeLast;
5202 return result;
5203}
5204
5205/*!
5206 \qmlproperty list<Item> QtQuick::Item::visibleChildren
5207 This read-only property lists all of the item's children that are currently visible.
5208 Note that a child's visibility may have changed explicitly, or because the visibility
5209 of this (it's parent) item or another grandparent changed.
5210*/
5211/*!
5212 \property QQuickItem::visibleChildren
5213 \internal
5214*/
5215QQmlListProperty<QQuickItem> QQuickItemPrivate::visibleChildren()
5216{
5217 return QQmlListProperty<QQuickItem>(q_func(),
5218 nullptr,
5219 QQuickItemPrivate::visibleChildren_count,
5220 QQuickItemPrivate::visibleChildren_at);
5221
5222}
5223
5224/*!
5225 \qmlproperty list<State> QtQuick::Item::states
5226
5227 This property holds the list of possible states for this item. To change
5228 the state of this item, set the \l state property to one of these states,
5229 or set the \l state property to an empty string to revert the item to its
5230 default state.
5231
5232 This property is specified as a list of \l State objects. For example,
5233 below is an item with "red_color" and "blue_color" states:
5234
5235 \qml
5236 import QtQuick 2.0
5237
5238 Rectangle {
5239 id: root
5240 width: 100; height: 100
5241
5242 states: [
5243 State {
5244 name: "red_color"
5245 PropertyChanges { root.color: "red" }
5246 },
5247 State {
5248 name: "blue_color"
5249 PropertyChanges { root.color: "blue" }
5250 }
5251 ]
5252 }
5253 \endqml
5254
5255 See \l{Qt Quick States} and \l{Animation and Transitions in Qt Quick} for
5256 more details on using states and transitions.
5257
5258 \sa transitions
5259*/
5260/*!
5261 \property QQuickItem::states
5262 \internal
5263 */
5264QQmlListProperty<QQuickState> QQuickItemPrivate::states()
5265{
5266 return _states()->statesProperty();
5267}
5268
5269/*!
5270 \qmlproperty list<Transition> QtQuick::Item::transitions
5271
5272 This property holds the list of transitions for this item. These define the
5273 transitions to be applied to the item whenever it changes its \l state.
5274
5275 This property is specified as a list of \l Transition objects. For example:
5276
5277 \qml
5278 import QtQuick 2.0
5279
5280 Item {
5281 transitions: [
5282 Transition {
5283 //...
5284 },
5285 Transition {
5286 //...
5287 }
5288 ]
5289 }
5290 \endqml
5291
5292 See \l{Qt Quick States} and \l{Animation and Transitions in Qt Quick} for
5293 more details on using states and transitions.
5294
5295 \sa states
5296*/
5297/*!
5298 \property QQuickItem::transitions
5299 \internal
5300 */
5301QQmlListProperty<QQuickTransition> QQuickItemPrivate::transitions()
5302{
5303 return _states()->transitionsProperty();
5304}
5305
5306QString QQuickItemPrivate::state() const
5307{
5308 if (!_stateGroup)
5309 return QString();
5310 else
5311 return _stateGroup->state();
5312}
5313
5314void QQuickItemPrivate::setState(const QString &state)
5315{
5316 _states()->setState(state);
5317}
5318
5319/*!
5320 \qmlproperty string QtQuick::Item::state
5321
5322 This property holds the name of the current state of the item.
5323
5324 If the item is in its default state, that is, no explicit state has been
5325 set, then this property holds an empty string. Likewise, you can return
5326 an item to its default state by setting this property to an empty string.
5327
5328 \sa {Qt Quick States}
5329*/
5330/*!
5331 \property QQuickItem::state
5332
5333 This property holds the name of the current state of the item.
5334
5335 If the item is in its default state, that is, no explicit state has been
5336 set, then this property holds an empty string. Likewise, you can return
5337 an item to its default state by setting this property to an empty string.
5338
5339 \sa {Qt Quick States}
5340*/
5341QString QQuickItem::state() const
5342{
5343 Q_D(const QQuickItem);
5344 return d->state();
5345}
5346
5347void QQuickItem::setState(const QString &state)
5348{
5349 Q_D(QQuickItem);
5350 d->setState(state);
5351}
5352
5353/*!
5354 \qmlproperty list<Transform> QtQuick::Item::transform
5355
5356 This property holds the list of transformations to apply.
5357
5358 This property is specified as a list of \l {Transform}-derived objects.
5359 For example:
5360
5361 \snippet qml/two-transforms.qml entire
5362
5363 For more information see \l Transform.
5364*/
5365/*!
5366 \property QQuickItem::transform
5367 \internal
5368 */
5369/*!
5370 \internal
5371 */
5372QQmlListProperty<QQuickTransform> QQuickItem::transform()
5373{
5374 return QQmlListProperty<QQuickTransform>(this, nullptr, QQuickItemPrivate::transform_append,
5375 QQuickItemPrivate::transform_count,
5376 QQuickItemPrivate::transform_at,
5377 QQuickItemPrivate::transform_clear);
5378}
5379
5380/*!
5381 \reimp
5382 Derived classes should call the base class method before adding their own action to
5383 perform at classBegin.
5384*/
5385void QQuickItem::classBegin()
5386{
5387 Q_D(QQuickItem);
5388 d->componentComplete = false;
5389 if (d->_stateGroup)
5390 d->_stateGroup->classBegin();
5391 if (d->_anchors)
5392 d->_anchors->classBegin();
5393#if QT_CONFIG(quick_shadereffect)
5394 if (d->extra.isAllocated() && d->extra->layer)
5395 d->extra->layer->classBegin();
5396#endif
5397}
5398
5399/*!
5400 \reimp
5401 Derived classes should call the base class method before adding their own actions to
5402 perform at componentComplete.
5403*/
5404void QQuickItem::componentComplete()
5405{
5406 Q_D(QQuickItem);
5407 d->componentComplete = true;
5408 if (d->_stateGroup)
5409 d->_stateGroup->componentComplete();
5410 if (d->_anchors) {
5411 d->_anchors->componentComplete();
5412 QQuickAnchorsPrivate::get(d->_anchors)->updateOnComplete();
5413 }
5414
5415 if (auto *safeArea = findChild<QQuickSafeArea*>(Qt::FindDirectChildrenOnly))
5416 safeArea->updateSafeArea();
5417
5418 if (d->extra.isAllocated()) {
5419#if QT_CONFIG(quick_shadereffect)
5420 if (d->extra->layer)
5421 d->extra->layer->componentComplete();
5422#endif
5423
5424 if (d->extra->keyHandler)
5425 d->extra->keyHandler->componentComplete();
5426
5427 if (d->extra->contents)
5428 d->extra->contents->complete();
5429 }
5430
5431 if (d->window && d->dirtyAttributes) {
5432 d->addToDirtyList();
5433 QQuickWindowPrivate::get(d->window)->dirtyItem(this);
5434 }
5435
5436#if QT_CONFIG(accessibility)
5437 if (d->isAccessible && d->effectiveVisible) {
5438 QAccessibleEvent ev(this, QAccessible::ObjectShow);
5439 QAccessible::updateAccessibility(&ev);
5440 }
5441#endif
5442}
5443
5444QQuickStateGroup *QQuickItemPrivate::_states()
5445{
5446 Q_Q(QQuickItem);
5447 if (!_stateGroup) {
5448 _stateGroup = new QQuickStateGroup;
5449 if (!componentComplete)
5450 _stateGroup->classBegin();
5451 qmlobject_connect(_stateGroup, QQuickStateGroup, SIGNAL(stateChanged(QString)),
5452 q, QQuickItem, SIGNAL(stateChanged(QString)));
5453 }
5454
5455 return _stateGroup;
5456}
5457
5458QPointF QQuickItemPrivate::computeTransformOrigin() const
5459{
5460 switch (origin()) {
5461 default:
5462 case QQuickItem::TopLeft:
5463 return QPointF(0, 0);
5464 case QQuickItem::Top:
5465 return QPointF(width / 2., 0);
5466 case QQuickItem::TopRight:
5467 return QPointF(width, 0);
5468 case QQuickItem::Left:
5469 return QPointF(0, height / 2.);
5470 case QQuickItem::Center:
5471 return QPointF(width / 2., height / 2.);
5472 case QQuickItem::Right:
5473 return QPointF(width, height / 2.);
5474 case QQuickItem::BottomLeft:
5475 return QPointF(0, height);
5476 case QQuickItem::Bottom:
5477 return QPointF(width / 2., height);
5478 case QQuickItem::BottomRight:
5479 return QPointF(width, height);
5480 }
5481}
5482
5483/*!
5484 \internal
5485 QQuickItemPrivate::dirty() calls transformChanged(q) to inform this item and
5486 all its children that its transform has changed, with \a transformedItem always
5487 being the parent item that caused the change. Override to react, e.g. to
5488 call update() if the item needs to re-generate SG nodes based on visible extents.
5489 If you override in a subclass, you must also call this (superclass) function
5490 and return the value from it.
5491
5492 This function recursively visits all children as long as
5493 subtreeTransformChangedEnabled is true, returns \c true if any of those
5494 children still has the ItemObservesViewport flag set, but otherwise
5495 turns subtreeTransformChangedEnabled off, if no children are observing.
5496*/
5497bool QQuickItemPrivate::transformChanged(QQuickItem *transformedItem)
5498{
5499 Q_Q(QQuickItem);
5500
5501#if QT_CONFIG(quick_shadereffect)
5502 if (q == transformedItem) {
5503 if (extra.isAllocated() && extra->layer)
5504 extra->layer->updateMatrix();
5505 }
5506#endif
5507
5508 itemChange(QQuickItem::ItemTransformHasChanged, transformedItem);
5509
5510 bool childWantsIt = false;
5511 if (subtreeTransformChangedEnabled) {
5512 // Inform the children in paint order: by the time we visit leaf items,
5513 // they can see any consequences in their parents
5514 const auto children = paintOrderChildItems();
5515 for (QQuickItem *child : children)
5516 childWantsIt |= QQuickItemPrivate::get(child)->transformChanged(transformedItem);
5517 }
5518
5519 const bool thisWantsIt = q->flags().testFlag(QQuickItem::ItemObservesViewport);
5520 const bool ret = childWantsIt || thisWantsIt;
5521 if (!ret && componentComplete && subtreeTransformChangedEnabled) {
5522 qCDebug(lcVP) << "turned off subtree transformChanged notification after checking all children of" << q;
5523 subtreeTransformChangedEnabled = false;
5524 }
5525 // If ItemObservesViewport, clipRect() calculates the intersection with the viewport;
5526 // so each time the item moves in the viewport, its clipnode needs to be updated.
5527 if (thisWantsIt && q->clip() && !(dirtyAttributes & QQuickItemPrivate::Clip))
5528 dirty(QQuickItemPrivate::Clip);
5529
5530 return ret;
5531}
5532
5533/*! \internal
5534 Returns the new position (proposed values for the x and y properties)
5535 to which this item should be moved to compensate for the given change
5536 in scale from \a startScale to \a activeScale and in rotation from
5537 \a startRotation to \a activeRotation. \a centroidParentPos is the
5538 point that we wish to hold in place (and then apply \a activeTranslation to),
5539 in this item's parent's coordinate system. \a startPos is this item's
5540 position in its parent's coordinate system when the gesture began.
5541 \a activeTranslation is the amount of translation that should be added to
5542 the return value, i.e. the displacement by which the centroid is expected
5543 to move.
5544
5545 If \a activeTranslation is \c (0, 0) the centroid is to be held in place.
5546 If \a activeScale is \c 1, it means scale is intended to be held constant,
5547 the same as \a startScale. If \a activeRotation is \c 0, it means rotation
5548 is intended to be held constant, the same as \a startRotation.
5549*/
5550QPointF QQuickItemPrivate::adjustedPosForTransform(const QPointF &centroidParentPos,
5551 const QPointF &startPos,
5552 const QVector2D &activeTranslation,
5553 qreal startScale,
5554 qreal activeScale,
5555 qreal startRotation,
5556 qreal activeRotation)
5557{
5558 Q_Q(QQuickItem);
5559 QVector3D xformOrigin(q->transformOriginPoint());
5560 QMatrix4x4 startMatrix;
5561 startMatrix.translate(float(startPos.x()), float(startPos.y()));
5562 startMatrix.translate(xformOrigin);
5563 startMatrix.scale(float(startScale));
5564 startMatrix.rotate(float(startRotation), 0, 0, -1);
5565 startMatrix.translate(-xformOrigin);
5566
5567 const QVector3D centroidParentVector(centroidParentPos);
5568 QMatrix4x4 mat;
5569 mat.translate(centroidParentVector);
5570 mat.rotate(float(activeRotation), 0, 0, 1);
5571 mat.scale(float(activeScale));
5572 mat.translate(-centroidParentVector);
5573 mat.translate(QVector3D(activeTranslation));
5574
5575 mat = mat * startMatrix;
5576
5577 QPointF xformOriginPoint = q->transformOriginPoint();
5578 QPointF pos = mat.map(xformOriginPoint);
5579 pos -= xformOriginPoint;
5580
5581 return pos;
5582}
5583
5584/*! \internal
5585 Returns the delivery agent for the narrowest subscene containing this item,
5586 but falls back to QQuickWindowPrivate::deliveryAgent if there are no subscenes.
5587
5588 If this item is not sure whether it's in a subscene (as by default), we need to
5589 explore the parents to find out.
5590
5591 If this item is in a subscene, we will find that DA during the exploration,
5592 and return it.
5593
5594 If we find the root item without finding a DA, then we know that this item
5595 does NOT belong to a subscene, so we remember that by setting
5596 maybeHasSubsceneDeliveryAgent to false, so that exploration of the parents
5597 can be avoided next time.
5598
5599 In the usual case in normal 2D scenes without subscenes,
5600 maybeHasSubsceneDeliveryAgent gets set to false here.
5601
5602 \note When a Qt Quick scene is shown in the usual way in its own window,
5603 subscenes are ignored, and QQuickWindowPrivate::deliveryAgent is used.
5604 Subscene delivery agents are used only in QtQuick 3D so far.
5605*/
5606QQuickDeliveryAgent *QQuickItemPrivate::deliveryAgent()
5607{
5608 Q_Q(QQuickItem);
5609 if (maybeHasSubsceneDeliveryAgent) {
5610 QQuickItemPrivate *p = this;
5611 do {
5612 if (qmlobject_cast<QQuickRootItem *>(p->q_ptr)) {
5613 // found the root item without finding a different DA:
5614 // it means we don't need to repeat this search next time.
5615 // TODO maybe optimize further: make this function recursive, and
5616 // set it to false on each item that we visit in the tail
5617 maybeHasSubsceneDeliveryAgent = false;
5618 break;
5619 }
5620 if (p->extra.isAllocated()) {
5621 if (auto da = p->extra->subsceneDeliveryAgent)
5622 return da;
5623 }
5624 p = p->parentItem ? QQuickItemPrivate::get(p->parentItem) : nullptr;
5625 } while (p);
5626 // arriving here is somewhat unexpected: a detached root can easily be created (just set an item's parent to null),
5627 // but why would we deliver events to that subtree? only if root got detached while an item in that subtree still has a grab?
5628 qCDebug(lcPtr) << "detached root of" << q << "is not a QQuickRootItem and also does not have its own DeliveryAgent";
5629 }
5630 if (window)
5631 return QQuickWindowPrivate::get(window)->deliveryAgent;
5632 return nullptr;
5633}
5634
5635QQuickDeliveryAgentPrivate *QQuickItemPrivate::deliveryAgentPrivate()
5636{
5637 auto da = deliveryAgent();
5638 return da ? static_cast<QQuickDeliveryAgentPrivate *>(QQuickDeliveryAgentPrivate::get(da)) : nullptr;
5639}
5640
5641/*! \internal
5642 Ensures that this item, presumably the root of a subscene (e.g. because it
5643 is mapped onto a 3D object in Qt Quick 3D), has a delivery agent to be used
5644 when delivering events to the subscene: i.e. when the viewport delivers an
5645 event to the subscene, or when the outer delivery agent delivers an update
5646 to an item that grabbed during a previous subscene delivery. Creates a new
5647 agent if it was not already created, and returns a pointer to the instance.
5648*/
5649QQuickDeliveryAgent *QQuickItemPrivate::ensureSubsceneDeliveryAgent()
5650{
5651 Q_Q(QQuickItem);
5652 // We are (about to be) sure that it has one now; but just to save space,
5653 // we avoid storing a DA pointer in each item; so deliveryAgent() always needs to
5654 // go up the hierarchy to find it. maybeHasSubsceneDeliveryAgent tells it to do that.
5655 maybeHasSubsceneDeliveryAgent = true;
5656 if (extra.isAllocated() && extra->subsceneDeliveryAgent)
5657 return extra->subsceneDeliveryAgent;
5658 extra.value().subsceneDeliveryAgent = new QQuickDeliveryAgent(q);
5659 qCDebug(lcPtr) << "created new" << extra->subsceneDeliveryAgent;
5660 // every subscene root needs to be a focus scope so that when QQuickItem::forceActiveFocus()
5661 // goes up the parent hierarchy, it finds the subscene root and calls setFocus() on it
5662 q->setFlag(QQuickItem::ItemIsFocusScope);
5663 return extra->subsceneDeliveryAgent;
5664}
5665
5666bool QQuickItemPrivate::filterKeyEvent(QKeyEvent *e, bool post)
5667{
5668 if (!extra.isAllocated() || !extra->keyHandler)
5669 return false;
5670
5671 if (post)
5672 e->accept();
5673
5674 if (e->type() == QEvent::KeyPress)
5675 extra->keyHandler->keyPressed(e, post);
5676 else
5677 extra->keyHandler->keyReleased(e, post);
5678
5679 return e->isAccepted();
5680}
5681
5682void QQuickItemPrivate::deliverPointerEvent(QEvent *event)
5683{
5684 Q_Q(QQuickItem);
5685 const auto eventType = event->type();
5686 const bool focusAccepted = setFocusIfNeeded(eventType);
5687
5688 switch (eventType) {
5689 case QEvent::MouseButtonPress:
5690 q->mousePressEvent(static_cast<QMouseEvent *>(event));
5691 break;
5692 case QEvent::MouseButtonRelease:
5693 q->mouseReleaseEvent(static_cast<QMouseEvent *>(event));
5694 break;
5695 case QEvent::MouseButtonDblClick:
5696 q->mouseDoubleClickEvent(static_cast<QMouseEvent *>(event));
5697 break;
5698#if QT_CONFIG(wheelevent)
5699 case QEvent::Wheel:
5700 q->wheelEvent(static_cast<QWheelEvent*>(event));
5701 break;
5702#endif
5703 case QEvent::TouchBegin:
5704 case QEvent::TouchUpdate:
5705 case QEvent::TouchEnd:
5706 case QEvent::TouchCancel:
5707 q->touchEvent(static_cast<QTouchEvent *>(event));
5708 break;
5709 default:
5710 break;
5711 }
5712
5713 if (focusAccepted)
5714 event->accept();
5715}
5716
5717void QQuickItemPrivate::deliverKeyEvent(QKeyEvent *e)
5718{
5719 Q_Q(QQuickItem);
5720
5721 Q_ASSERT(e->isAccepted());
5722 if (filterKeyEvent(e, false))
5723 return;
5724 else
5725 e->accept();
5726
5727 if (e->type() == QEvent::KeyPress)
5728 q->keyPressEvent(e);
5729 else
5730 q->keyReleaseEvent(e);
5731
5732 if (e->isAccepted())
5733 return;
5734
5735 if (filterKeyEvent(e, true) || !q->window())
5736 return;
5737
5738 //only care about KeyPress now
5739 if (e->type() == QEvent::KeyPress &&
5740 (q == q->window()->contentItem() || q->activeFocusOnTab())) {
5741 bool res = false;
5742 if (!(e->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) { //### Add MetaModifier?
5743 if (e->key() == Qt::Key_Backtab
5744 || (e->key() == Qt::Key_Tab && (e->modifiers() & Qt::ShiftModifier)))
5745 res = QQuickItemPrivate::focusNextPrev(q, false);
5746 else if (e->key() == Qt::Key_Tab)
5747 res = QQuickItemPrivate::focusNextPrev(q, true);
5748 if (res)
5749 e->setAccepted(true);
5750 }
5751 }
5752}
5753
5754#if QT_CONFIG(im)
5755void QQuickItemPrivate::deliverInputMethodEvent(QInputMethodEvent *e)
5756{
5757 Q_Q(QQuickItem);
5758
5759 Q_ASSERT(e->isAccepted());
5760 if (extra.isAllocated() && extra->keyHandler) {
5761 extra->keyHandler->inputMethodEvent(e, false);
5762
5763 if (e->isAccepted())
5764 return;
5765 else
5766 e->accept();
5767 }
5768
5769 q->inputMethodEvent(e);
5770
5771 if (e->isAccepted())
5772 return;
5773
5774 if (extra.isAllocated() && extra->keyHandler) {
5775 e->accept();
5776
5777 extra->keyHandler->inputMethodEvent(e, true);
5778 }
5779}
5780#endif // im
5781
5782void QQuickItemPrivate::deliverShortcutOverrideEvent(QKeyEvent *event)
5783{
5784 if (extra.isAllocated() && extra->keyHandler)
5785 extra->keyHandler->shortcutOverrideEvent(event);
5786 else
5787 event->ignore();
5788}
5789
5790bool QQuickItemPrivate::anyPointerHandlerWants(const QPointerEvent *event, const QEventPoint &point) const
5791{
5792 if (!hasPointerHandlers())
5793 return false;
5794 for (QQuickPointerHandler *handler : extra->pointerHandlers) {
5795 if (handler->wantsEventPoint(event, point))
5796 return true;
5797 }
5798 return false;
5799}
5800
5801/*!
5802 \internal
5803 Deliver the \a event to all this item's PointerHandlers, but skip
5804 HoverHandlers if the event is a QMouseEvent or QWheelEvent (they are visited
5805 in QQuickDeliveryAgentPrivate::deliverHoverEventToItem()), and skip handlers
5806 that are in QQuickPointerHandlerPrivate::deviceDeliveryTargets().
5807 However if the event is a QTabletEvent, we do NOT skip delivery here:
5808 this is the means by which HoverHandler can change the cursor when the
5809 tablet stylus hovers over its parent item.
5810
5811 If \a avoidGrabbers is true, also skip delivery to any handler that
5812 is exclusively or passively grabbing any point within \a event
5813 (because delivery to grabbers is handled separately).
5814*/
5815bool QQuickItemPrivate::handlePointerEvent(QPointerEvent *event, bool avoidGrabbers)
5816{
5817 bool delivered = false;
5818 if (extra.isAllocated()) {
5819 for (QQuickPointerHandler *handler : extra->pointerHandlers) {
5820 bool avoidThisHandler = false;
5821 if (QQuickDeliveryAgentPrivate::isMouseOrWheelEvent(event) &&
5822 qmlobject_cast<const QQuickHoverHandler *>(handler)) {
5823 avoidThisHandler = true;
5824 } else if (avoidGrabbers) {
5825 for (auto &p : event->points()) {
5826 if (event->exclusiveGrabber(p) == handler || event->passiveGrabbers(p).contains(handler)) {
5827 avoidThisHandler = true;
5828 break;
5829 }
5830 }
5831 }
5832 if (!avoidThisHandler &&
5833 !QQuickPointerHandlerPrivate::deviceDeliveryTargets(event->device()).contains(handler)) {
5834 handler->handlePointerEvent(event);
5835 delivered = true;
5836 }
5837 }
5838 }
5839 return delivered;
5840}
5841
5842#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
5843bool QQuickItemPrivate::handleContextMenuEvent(QContextMenuEvent *event)
5844#else
5845bool QQuickItem::contextMenuEvent(QContextMenuEvent *event)
5846#endif
5847{
5848 if (extra.isAllocated() && extra->contextMenu)
5849 return extra->contextMenu->event(event);
5850 event->ignore();
5851 return false;
5852}
5853
5854/*!
5855 Called when \a change occurs for this item.
5856
5857 \a value contains extra information relating to the change, when
5858 applicable.
5859
5860 If you re-implement this method in a subclass, be sure to call
5861 \code
5862 QQuickItem::itemChange(change, value);
5863 \endcode
5864 typically at the end of your implementation, to ensure the
5865 \l windowChanged() signal will be emitted.
5866 */
5867void QQuickItem::itemChange(ItemChange change, const ItemChangeData &value)
5868{
5869 if (change == ItemSceneChange)
5870 emit windowChanged(value.window);
5871}
5872
5873#if QT_CONFIG(im)
5874/*!
5875 Notify input method on updated query values if needed. \a queries indicates
5876 the changed attributes.
5877*/
5878void QQuickItem::updateInputMethod(Qt::InputMethodQueries queries)
5879{
5880 if (hasActiveFocus())
5881 QGuiApplication::inputMethod()->update(queries);
5882}
5883#endif // im
5884
5885/*!
5886 Returns the extents of the item in its own coordinate system:
5887 a rectangle from \c{0, 0} to \l width() and \l height().
5888*/
5889QRectF QQuickItem::boundingRect() const
5890{
5891 Q_D(const QQuickItem);
5892 return QRectF(0, 0, d->width, d->height);
5893}
5894
5895/*!
5896 Returns the rectangular area within this item that is currently visible in
5897 \l viewportItem(), if there is a viewport and the \l ItemObservesViewport
5898 flag is set; otherwise, the extents of this item in its own coordinate
5899 system: a rectangle from \c{0, 0} to \l width() and \l height(). This is
5900 the region intended to remain visible if \l clip is \c true. It can also be
5901 used in updatePaintNode() to limit the graphics added to the scene graph.
5902
5903 For example, a large drawing or a large text document might be shown in a
5904 Flickable that occupies only part of the application's Window: in that
5905 case, Flickable is the viewport item, and a custom content-rendering item
5906 may choose to omit scene graph nodes that fall outside the area that is
5907 currently visible. If the \l ItemObservesViewport flag is set, this area
5908 will change each time the user scrolls the content in the Flickable.
5909
5910 In case of nested viewport items, clipRect() is the intersection of the
5911 \c {boundingRect}s of all ancestors that have the \l ItemIsViewport flag set,
5912 mapped to the coordinate system of \e this item.
5913
5914 \sa boundingRect()
5915*/
5916QRectF QQuickItem::clipRect() const
5917{
5918 Q_D(const QQuickItem);
5919 QRectF ret(0, 0, d->width, d->height);
5920 if (flags().testFlag(QQuickItem::ItemObservesViewport)) {
5921 if (QQuickItem *viewport = viewportItem()) {
5922 // if the viewport is already "this", there's nothing to intersect;
5923 // and don't call clipRect() again, to avoid infinite recursion
5924 if (viewport == this)
5925 return ret;
5926 const auto mappedViewportRect = mapRectFromItem(viewport, viewport->clipRect());
5927 qCDebug(lcVP) << this << "intersecting" << viewport << mappedViewportRect << ret << "->" << mappedViewportRect.intersected(ret);
5928 return mappedViewportRect.intersected(ret);
5929 }
5930 }
5931 return ret;
5932}
5933
5934/*!
5935 If the \l ItemObservesViewport flag is set,
5936 returns the nearest parent with the \l ItemIsViewport flag.
5937 Returns the window's contentItem if the flag is not set,
5938 or if no other viewport item is found.
5939
5940 Returns \nullptr only if there is no viewport item and this item is not
5941 shown in a window.
5942
5943 \sa clipRect()
5944*/
5945QQuickItem *QQuickItem::viewportItem() const
5946{
5947 if (flags().testFlag(ItemObservesViewport)) {
5948 QQuickItem *par = parentItem();
5949 while (par) {
5950 if (par->flags().testFlag(QQuickItem::ItemIsViewport))
5951 return par;
5952 par = par->parentItem();
5953 }
5954 }
5955 return (window() ? window()->contentItem() : nullptr);
5956}
5957
5958/*!
5959 \qmlproperty enumeration QtQuick::Item::transformOrigin
5960 This property holds the origin point around which scale and rotation transform.
5961
5962 Nine transform origins are available, as shown in the image below.
5963 The default transform origin is \c Item.Center.
5964
5965 \image declarative-transformorigin.png
5966
5967 This example rotates an image around its bottom-right corner.
5968 \qml
5969 Image {
5970 source: "myimage.png"
5971 transformOrigin: Item.BottomRight
5972 rotation: 45
5973 }
5974 \endqml
5975
5976 To set an arbitrary transform origin point use the \l Scale or \l Rotation
5977 transform types with \l transform.
5978*/
5979/*!
5980 \property QQuickItem::transformOrigin
5981 This property holds the origin point around which scale and rotation transform.
5982
5983 Nine transform origins are available, as shown in the image below.
5984 The default transform origin is \c Item.Center.
5985
5986 \image declarative-transformorigin.png
5987*/
5988QQuickItem::TransformOrigin QQuickItem::transformOrigin() const
5989{
5990 Q_D(const QQuickItem);
5991 return d->origin();
5992}
5993
5994void QQuickItem::setTransformOrigin(TransformOrigin origin)
5995{
5996 Q_D(QQuickItem);
5997 if (origin == d->origin())
5998 return;
5999
6000 d->extra.value().origin = origin;
6001 d->dirty(QQuickItemPrivate::TransformOrigin);
6002
6003 emit transformOriginChanged(d->origin());
6004}
6005
6006/*!
6007 \property QQuickItem::transformOriginPoint
6008 \internal
6009 */
6010/*!
6011 \internal
6012 */
6013QPointF QQuickItem::transformOriginPoint() const
6014{
6015 Q_D(const QQuickItem);
6016 if (d->extra.isAllocated() && !d->extra->userTransformOriginPoint.isNull())
6017 return d->extra->userTransformOriginPoint;
6018 return d->computeTransformOrigin();
6019}
6020
6021/*!
6022 \internal
6023 */
6024void QQuickItem::setTransformOriginPoint(const QPointF &point)
6025{
6026 Q_D(QQuickItem);
6027 if (d->extra.value().userTransformOriginPoint == point)
6028 return;
6029
6030 d->extra->userTransformOriginPoint = point;
6031 d->dirty(QQuickItemPrivate::TransformOrigin);
6032}
6033
6034/*!
6035 \qmlproperty real QtQuick::Item::z
6036
6037 Sets the stacking order of sibling items. By default the stacking order is 0.
6038
6039 Items with a higher stacking value are drawn on top of siblings with a
6040 lower stacking order. Items with the same stacking value are drawn
6041 bottom up in the order they appear. Items with a negative stacking
6042 value are drawn under their parent's content.
6043
6044 The following example shows the various effects of stacking order.
6045
6046 \table
6047 \row
6048 \li \image declarative-item_stacking1.png
6049 \li Same \c z - later children above earlier children:
6050 \qml
6051 Item {
6052 Rectangle {
6053 color: "red"
6054 width: 100; height: 100
6055 }
6056 Rectangle {
6057 color: "blue"
6058 x: 50; y: 50; width: 100; height: 100
6059 }
6060 }
6061 \endqml
6062 \row
6063 \li \image declarative-item_stacking2.png
6064 \li Higher \c z on top:
6065 \qml
6066 Item {
6067 Rectangle {
6068 z: 1
6069 color: "red"
6070 width: 100; height: 100
6071 }
6072 Rectangle {
6073 color: "blue"
6074 x: 50; y: 50; width: 100; height: 100
6075 }
6076 }
6077 \endqml
6078 \row
6079 \li \image declarative-item_stacking3.png
6080 \li Same \c z - children above parents:
6081 \qml
6082 Item {
6083 Rectangle {
6084 color: "red"
6085 width: 100; height: 100
6086 Rectangle {
6087 color: "blue"
6088 x: 50; y: 50; width: 100; height: 100
6089 }
6090 }
6091 }
6092 \endqml
6093 \row
6094 \li \image declarative-item_stacking4.png
6095 \li Lower \c z below:
6096 \qml
6097 Item {
6098 Rectangle {
6099 color: "red"
6100 width: 100; height: 100
6101 Rectangle {
6102 z: -1
6103 color: "blue"
6104 x: 50; y: 50; width: 100; height: 100
6105 }
6106 }
6107 }
6108 \endqml
6109 \endtable
6110 */
6111/*!
6112 \property QQuickItem::z
6113
6114 Sets the stacking order of sibling items. By default the stacking order is 0.
6115
6116 Items with a higher stacking value are drawn on top of siblings with a
6117 lower stacking order. Items with the same stacking value are drawn
6118 bottom up in the order they appear. Items with a negative stacking
6119 value are drawn under their parent's content.
6120
6121 The following example shows the various effects of stacking order.
6122
6123 \table
6124 \row
6125 \li \image declarative-item_stacking1.png
6126 \li Same \c z - later children above earlier children:
6127 \qml
6128 Item {
6129 Rectangle {
6130 color: "red"
6131 width: 100; height: 100
6132 }
6133 Rectangle {
6134 color: "blue"
6135 x: 50; y: 50; width: 100; height: 100
6136 }
6137 }
6138 \endqml
6139 \row
6140 \li \image declarative-item_stacking2.png
6141 \li Higher \c z on top:
6142 \qml
6143 Item {
6144 Rectangle {
6145 z: 1
6146 color: "red"
6147 width: 100; height: 100
6148 }
6149 Rectangle {
6150 color: "blue"
6151 x: 50; y: 50; width: 100; height: 100
6152 }
6153 }
6154 \endqml
6155 \row
6156 \li \image declarative-item_stacking3.png
6157 \li Same \c z - children above parents:
6158 \qml
6159 Item {
6160 Rectangle {
6161 color: "red"
6162 width: 100; height: 100
6163 Rectangle {
6164 color: "blue"
6165 x: 50; y: 50; width: 100; height: 100
6166 }
6167 }
6168 }
6169 \endqml
6170 \row
6171 \li \image declarative-item_stacking4.png
6172 \li Lower \c z below:
6173 \qml
6174 Item {
6175 Rectangle {
6176 color: "red"
6177 width: 100; height: 100
6178 Rectangle {
6179 z: -1
6180 color: "blue"
6181 x: 50; y: 50; width: 100; height: 100
6182 }
6183 }
6184 }
6185 \endqml
6186 \endtable
6187 */
6188qreal QQuickItem::z() const
6189{
6190 Q_D(const QQuickItem);
6191 return d->z();
6192}
6193
6194void QQuickItem::setZ(qreal v)
6195{
6196 Q_D(QQuickItem);
6197 if (d->z() == v)
6198 return;
6199
6200 d->extra.value().z = v;
6201
6202 d->dirty(QQuickItemPrivate::ZValue);
6203 if (d->parentItem) {
6204 QQuickItemPrivate::get(d->parentItem)->markSortedChildrenDirty(this);
6205 QQuickItemPrivate::get(d->parentItem)->dirty(QQuickItemPrivate::ChildrenStackingChanged);
6206 }
6207
6208 emit zChanged();
6209
6210#if QT_CONFIG(quick_shadereffect)
6211 if (d->extra.isAllocated() && d->extra->layer)
6212 d->extra->layer->updateZ();
6213#endif
6214}
6215
6216/*!
6217 \qmlproperty real QtQuick::Item::rotation
6218 This property holds the rotation of the item in degrees clockwise around
6219 its transformOrigin.
6220
6221 The default value is 0 degrees (that is, no rotation).
6222
6223 \table
6224 \row
6225 \li \image declarative-rotation.png
6226 \li
6227 \qml
6228 Rectangle {
6229 color: "blue"
6230 width: 100; height: 100
6231 Rectangle {
6232 color: "red"
6233 x: 25; y: 25; width: 50; height: 50
6234 rotation: 30
6235 }
6236 }
6237 \endqml
6238 \endtable
6239
6240 \sa Transform, Rotation
6241*/
6242/*!
6243 \property QQuickItem::rotation
6244 This property holds the rotation of the item in degrees clockwise around
6245 its transformOrigin.
6246
6247 The default value is 0 degrees (that is, no rotation).
6248
6249 \table
6250 \row
6251 \li \image declarative-rotation.png
6252 \li
6253 \qml
6254 Rectangle {
6255 color: "blue"
6256 width: 100; height: 100
6257 Rectangle {
6258 color: "red"
6259 x: 25; y: 25; width: 50; height: 50
6260 rotation: 30
6261 }
6262 }
6263 \endqml
6264 \endtable
6265
6266 \sa Transform, Rotation
6267 */
6268qreal QQuickItem::rotation() const
6269{
6270 Q_D(const QQuickItem);
6271 return d->rotation();
6272}
6273
6274void QQuickItem::setRotation(qreal r)
6275{
6276 Q_D(QQuickItem);
6277 if (d->rotation() == r)
6278 return;
6279
6280 d->extra.value().rotation = r;
6281
6282 d->dirty(QQuickItemPrivate::BasicTransform);
6283
6284 d->itemChange(ItemRotationHasChanged, r);
6285
6286 emit rotationChanged();
6287}
6288
6289/*!
6290 \qmlproperty real QtQuick::Item::scale
6291 This property holds the scale factor for this item.
6292
6293 A scale of less than 1.0 causes the item to be rendered at a smaller
6294 size, and a scale greater than 1.0 renders the item at a larger size.
6295 A negative scale causes the item to be mirrored when rendered.
6296
6297 The default value is 1.0.
6298
6299 Scaling is applied from the transformOrigin.
6300
6301 \table
6302 \row
6303 \li \image declarative-scale.png
6304 \li
6305 \qml
6306 import QtQuick 2.0
6307
6308 Rectangle {
6309 color: "blue"
6310 width: 100; height: 100
6311
6312 Rectangle {
6313 color: "green"
6314 width: 25; height: 25
6315 }
6316
6317 Rectangle {
6318 color: "red"
6319 x: 25; y: 25; width: 50; height: 50
6320 scale: 1.4
6321 transformOrigin: Item.TopLeft
6322 }
6323 }
6324 \endqml
6325 \endtable
6326
6327 \sa Transform, Scale
6328*/
6329/*!
6330 \property QQuickItem::scale
6331 This property holds the scale factor for this item.
6332
6333 A scale of less than 1.0 causes the item to be rendered at a smaller
6334 size, and a scale greater than 1.0 renders the item at a larger size.
6335 A negative scale causes the item to be mirrored when rendered.
6336
6337 The default value is 1.0.
6338
6339 Scaling is applied from the transformOrigin.
6340
6341 \table
6342 \row
6343 \li \image declarative-scale.png
6344 \li
6345 \qml
6346 import QtQuick 2.0
6347
6348 Rectangle {
6349 color: "blue"
6350 width: 100; height: 100
6351
6352 Rectangle {
6353 color: "green"
6354 width: 25; height: 25
6355 }
6356
6357 Rectangle {
6358 color: "red"
6359 x: 25; y: 25; width: 50; height: 50
6360 scale: 1.4
6361 }
6362 }
6363 \endqml
6364 \endtable
6365
6366 \sa Transform, Scale
6367 */
6368qreal QQuickItem::scale() const
6369{
6370 Q_D(const QQuickItem);
6371 return d->scale();
6372}
6373
6374void QQuickItem::setScale(qreal s)
6375{
6376 Q_D(QQuickItem);
6377 if (d->scale() == s)
6378 return;
6379
6380 d->extra.value().scale = s;
6381
6382 d->dirty(QQuickItemPrivate::BasicTransform);
6383
6384 d->itemChange(ItemScaleHasChanged, s);
6385
6386 emit scaleChanged();
6387}
6388
6389/*!
6390 \qmlproperty real QtQuick::Item::opacity
6391
6392 This property holds the opacity of the item. Opacity is specified as a
6393 number between 0.0 (fully transparent) and 1.0 (fully opaque). The default
6394 value is 1.0.
6395
6396 When this property is set, the specified opacity is also applied
6397 individually to child items. This may have an unintended effect in some
6398 circumstances. For example in the second set of rectangles below, the red
6399 rectangle has specified an opacity of 0.5, which affects the opacity of
6400 its blue child rectangle even though the child has not specified an opacity.
6401
6402 \table
6403 \row
6404 \li \image declarative-item_opacity1.png
6405 \li
6406 \qml
6407 Item {
6408 Rectangle {
6409 color: "red"
6410 width: 100; height: 100
6411 Rectangle {
6412 color: "blue"
6413 x: 50; y: 50; width: 100; height: 100
6414 }
6415 }
6416 }
6417 \endqml
6418 \row
6419 \li \image declarative-item_opacity2.png
6420 \li
6421 \qml
6422 Item {
6423 Rectangle {
6424 opacity: 0.5
6425 color: "red"
6426 width: 100; height: 100
6427 Rectangle {
6428 color: "blue"
6429 x: 50; y: 50; width: 100; height: 100
6430 }
6431 }
6432 }
6433 \endqml
6434 \endtable
6435
6436 Changing an item's opacity does not affect whether the item receives user
6437 input events. (In contrast, setting \l visible property to \c false stops
6438 mouse events, and setting the \l enabled property to \c false stops mouse
6439 and keyboard events, and also removes active focus from the item.)
6440
6441 \sa visible
6442*/
6443/*!
6444 \property QQuickItem::opacity
6445
6446 This property holds the opacity of the item. Opacity is specified as a
6447 number between 0.0 (fully transparent) and 1.0 (fully opaque). The default
6448 value is 1.0.
6449
6450 When this property is set, the specified opacity is also applied
6451 individually to child items. This may have an unintended effect in some
6452 circumstances. For example in the second set of rectangles below, the red
6453 rectangle has specified an opacity of 0.5, which affects the opacity of
6454 its blue child rectangle even though the child has not specified an opacity.
6455
6456 Values outside the range of 0 to 1 will be clamped.
6457
6458 \table
6459 \row
6460 \li \image declarative-item_opacity1.png
6461 \li
6462 \qml
6463 Item {
6464 Rectangle {
6465 color: "red"
6466 width: 100; height: 100
6467 Rectangle {
6468 color: "blue"
6469 x: 50; y: 50; width: 100; height: 100
6470 }
6471 }
6472 }
6473 \endqml
6474 \row
6475 \li \image declarative-item_opacity2.png
6476 \li
6477 \qml
6478 Item {
6479 Rectangle {
6480 opacity: 0.5
6481 color: "red"
6482 width: 100; height: 100
6483 Rectangle {
6484 color: "blue"
6485 x: 50; y: 50; width: 100; height: 100
6486 }
6487 }
6488 }
6489 \endqml
6490 \endtable
6491
6492 Changing an item's opacity does not affect whether the item receives user
6493 input events. (In contrast, setting \l visible property to \c false stops
6494 mouse events, and setting the \l enabled property to \c false stops mouse
6495 and keyboard events, and also removes active focus from the item.)
6496
6497 \sa visible
6498*/
6499qreal QQuickItem::opacity() const
6500{
6501 Q_D(const QQuickItem);
6502 return d->opacity();
6503}
6504
6505void QQuickItem::setOpacity(qreal newOpacity)
6506{
6507 Q_D(QQuickItem);
6508 qreal o = std::clamp(newOpacity, qreal(0.0), qreal(1.0));
6509 if (d->opacity() == o)
6510 return;
6511
6512 d->extra.value().opacity = o;
6513
6514 d->dirty(QQuickItemPrivate::OpacityValue);
6515
6516 d->itemChange(ItemOpacityHasChanged, o);
6517
6518 emit opacityChanged();
6519}
6520
6521/*!
6522 \qmlproperty bool QtQuick::Item::visible
6523
6524 This property holds whether the item is visible. By default this is true.
6525
6526 Setting this property directly affects the \c visible value of child
6527 items. When set to \c false, the \c visible values of all child items also
6528 become \c false. When set to \c true, the \c visible values of child items
6529 are returned to \c true, unless they have explicitly been set to \c false.
6530
6531 (Because of this flow-on behavior, using the \c visible property may not
6532 have the intended effect if a property binding should only respond to
6533 explicit property changes. In such cases it may be better to use the
6534 \l opacity property instead.)
6535
6536 If this property is set to \c false, the item will no longer receive mouse
6537 events, but will continue to receive key events and will retain the keyboard
6538 \l focus if it has been set. (In contrast, setting the \l enabled property
6539 to \c false stops both mouse and keyboard events, and also removes focus
6540 from the item.)
6541
6542 \note This property's value is only affected by changes to this property or
6543 the parent's \c visible property. It does not change, for example, if this
6544 item moves off-screen, or if the \l opacity changes to 0.
6545
6546 \sa opacity, enabled
6547*/
6548/*!
6549 \property QQuickItem::visible
6550
6551 This property holds whether the item is visible. By default this is true.
6552
6553 Setting this property directly affects the \c visible value of child
6554 items. When set to \c false, the \c visible values of all child items also
6555 become \c false. When set to \c true, the \c visible values of child items
6556 are returned to \c true, unless they have explicitly been set to \c false.
6557
6558 (Because of this flow-on behavior, using the \c visible property may not
6559 have the intended effect if a property binding should only respond to
6560 explicit property changes. In such cases it may be better to use the
6561 \l opacity property instead.)
6562
6563 If this property is set to \c false, the item will no longer receive mouse
6564 events, but will continue to receive key events and will retain the keyboard
6565 \l focus if it has been set. (In contrast, setting the \l enabled property
6566 to \c false stops both mouse and keyboard events, and also removes focus
6567 from the item.)
6568
6569 \note This property's value is only affected by changes to this property or
6570 the parent's \c visible property. It does not change, for example, if this
6571 item moves off-screen, or if the \l opacity changes to 0. However, for
6572 historical reasons, this property is true after the item's construction, even
6573 if the item hasn't been added to a scene yet. Changing or reading this
6574 property of an item that has not been added to a scene might not produce
6575 the expected results.
6576
6577 \note The notification signal for this property gets emitted during destruction
6578 of the visual parent. C++ signal handlers cannot assume that items in the
6579 visual parent hierarchy are still fully constructed. Use \l qobject_cast to
6580 verify that items in the parent hierarchy can be used safely as the expected
6581 type.
6582
6583 \sa opacity, enabled
6584*/
6585bool QQuickItem::isVisible() const
6586{
6587 Q_D(const QQuickItem);
6588 return d->effectiveVisible;
6589}
6590
6591void QQuickItemPrivate::setVisible(bool visible)
6592{
6593 if (visible == explicitVisible)
6594 return;
6595
6596 explicitVisible = visible;
6597 if (!visible)
6598 dirty(QQuickItemPrivate::Visible);
6599
6600 const bool childVisibilityChanged = setEffectiveVisibleRecur(calcEffectiveVisible());
6601 if (childVisibilityChanged && parentItem)
6602 emit parentItem->visibleChildrenChanged(); // signal the parent, not this!
6603}
6604
6605void QQuickItem::setVisible(bool v)
6606{
6607 Q_D(QQuickItem);
6608 d->setVisible(v);
6609}
6610
6611/*!
6612 \qmlproperty bool QtQuick::Item::enabled
6613
6614 This property holds whether the item receives mouse and keyboard events.
6615 By default, this is \c true.
6616
6617 When set to \c false, the item does not receive keyboard or pointing device
6618 events, such as press, release, or click, but can still receive hover
6619 events.
6620
6621 \note In Qt 5, setting \c enabled to \c false also blocked hover events.
6622 This was changed in Qt 6 to allow \l {QtQuick.Controls::ToolTip}{tooltips}
6623 and similar features to work on disabled items.
6624
6625 Setting this property directly affects the \c enabled value of child
6626 items. When set to \c false, the \c enabled values of all child items also
6627 become \c false. When set to \c true, the \c enabled values of child items
6628 are returned to \c true, unless they have explicitly been set to \c false.
6629
6630 Setting this property to \c false automatically causes \l activeFocus to be
6631 set to \c false, and this item will no longer receive keyboard events.
6632
6633 \sa visible
6634*/
6635/*!
6636 \property QQuickItem::enabled
6637
6638 This property holds whether the item receives mouse and keyboard events.
6639 By default this is true.
6640
6641 Setting this property directly affects the \c enabled value of child
6642 items. When set to \c false, the \c enabled values of all child items also
6643 become \c false. When set to \c true, the \c enabled values of child items
6644 are returned to \c true, unless they have explicitly been set to \c false.
6645
6646 Setting this property to \c false automatically causes \l activeFocus to be
6647 set to \c false, and this item will longer receive keyboard events.
6648
6649 \note Hover events are enabled separately by \l setAcceptHoverEvents().
6650 Thus, a disabled item can continue to receive hover events, even when this
6651 property is \c false. This makes it possible to show informational feedback
6652 (such as \l ToolTip) even when an interactive item is disabled.
6653 The same is also true for any \l {HoverHandler}{HoverHandlers}
6654 added as children of the item. A HoverHandler can, however, be
6655 \l {PointerHandler::enabled}{disabled} explicitly, or for example
6656 be bound to the \c enabled state of the item.
6657
6658 \sa visible
6659*/
6660bool QQuickItem::isEnabled() const
6661{
6662 Q_D(const QQuickItem);
6663 return d->effectiveEnable;
6664}
6665
6666void QQuickItem::setEnabled(bool e)
6667{
6668 Q_D(QQuickItem);
6669 if (e == d->explicitEnable)
6670 return;
6671
6672 d->explicitEnable = e;
6673
6674 QQuickItem *scope = parentItem();
6675 while (scope && !scope->isFocusScope())
6676 scope = scope->parentItem();
6677
6678 d->setEffectiveEnableRecur(scope, d->calcEffectiveEnable());
6679}
6680
6681bool QQuickItemPrivate::calcEffectiveVisible() const
6682{
6683 // An item is visible if it is a child of a visible parent, and not explicitly hidden.
6684 return explicitVisible && parentItem && QQuickItemPrivate::get(parentItem)->effectiveVisible;
6685}
6686
6687bool QQuickItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible)
6688{
6689 Q_Q(QQuickItem);
6690
6691 if (newEffectiveVisible && !explicitVisible) {
6692 // This item locally overrides visibility
6693 return false; // effective visibility didn't change
6694 }
6695
6696 if (newEffectiveVisible == effectiveVisible) {
6697 // No change necessary
6698 return false; // effective visibility didn't change
6699 }
6700
6701 effectiveVisible = newEffectiveVisible;
6702 dirty(Visible);
6703 if (parentItem)
6704 QQuickItemPrivate::get(parentItem)->dirty(ChildrenStackingChanged);
6705 if (window) {
6706 if (auto agent = deliveryAgentPrivate())
6707 agent->removeGrabber(q, true, true, true);
6708 }
6709
6710 bool childVisibilityChanged = false;
6711 for (int ii = 0; ii < childItems.size(); ++ii)
6712 childVisibilityChanged |= QQuickItemPrivate::get(childItems.at(ii))->setEffectiveVisibleRecur(newEffectiveVisible);
6713
6714 itemChange(QQuickItem::ItemVisibleHasChanged, bool(effectiveVisible));
6715#if QT_CONFIG(accessibility)
6716 if (isAccessible) {
6717 QAccessibleEvent ev(q, effectiveVisible ? QAccessible::ObjectShow : QAccessible::ObjectHide);
6718 QAccessible::updateAccessibility(&ev);
6719 }
6720#endif
6721 if (!inDestructor) {
6722 emit q->visibleChanged();
6723 if (childVisibilityChanged)
6724 emit q->visibleChildrenChanged();
6725 }
6726
6727 return true; // effective visibility DID change
6728}
6729
6730bool QQuickItemPrivate::calcEffectiveEnable() const
6731{
6732 // XXX todo - Should the effective enable of an element with no parent just be the current
6733 // effective enable? This would prevent pointless re-processing in the case of an element
6734 // moving to/from a no-parent situation, but it is different from what graphics view does.
6735 return explicitEnable && (!parentItem || QQuickItemPrivate::get(parentItem)->effectiveEnable);
6736}
6737
6738void QQuickItemPrivate::setEffectiveEnableRecur(QQuickItem *scope, bool newEffectiveEnable)
6739{
6740 Q_Q(QQuickItem);
6741
6742 if (newEffectiveEnable && !explicitEnable) {
6743 // This item locally overrides enable
6744 return;
6745 }
6746
6747 if (newEffectiveEnable == effectiveEnable) {
6748 // No change necessary
6749 return;
6750 }
6751
6752 effectiveEnable = newEffectiveEnable;
6753
6754 QQuickDeliveryAgentPrivate *da = deliveryAgentPrivate();
6755 if (da) {
6756 da->removeGrabber(q, true, true, true);
6757 if (scope && !effectiveEnable && activeFocus) {
6758 da->clearFocusInScope(scope, q, Qt::OtherFocusReason,
6759 QQuickDeliveryAgentPrivate::DontChangeFocusProperty |
6760 QQuickDeliveryAgentPrivate::DontChangeSubFocusItem);
6761 }
6762 }
6763
6764 for (int ii = 0; ii < childItems.size(); ++ii) {
6765 QQuickItemPrivate::get(childItems.at(ii))->setEffectiveEnableRecur(
6766 (flags & QQuickItem::ItemIsFocusScope) && scope ? q : scope, newEffectiveEnable);
6767 }
6768
6769 if (scope && effectiveEnable && focus && da) {
6770 da->setFocusInScope(scope, q, Qt::OtherFocusReason,
6771 QQuickDeliveryAgentPrivate::DontChangeFocusProperty |
6772 QQuickDeliveryAgentPrivate::DontChangeSubFocusItem);
6773 }
6774
6775 itemChange(QQuickItem::ItemEnabledHasChanged, bool(effectiveEnable));
6776#if QT_CONFIG(accessibility)
6777 if (isAccessible) {
6778 QAccessible::State changedState;
6779 changedState.disabled = true;
6780 changedState.focusable = true;
6781 QAccessibleStateChangeEvent ev(q, changedState);
6782 QAccessible::updateAccessibility(&ev);
6783 }
6784#endif
6785 emit q->enabledChanged();
6786}
6787
6788bool QQuickItemPrivate::isTransparentForPositioner() const
6789{
6790 return extra.isAllocated() && extra.value().transparentForPositioner;
6791}
6792
6793void QQuickItemPrivate::setTransparentForPositioner(bool transparent)
6794{
6795 extra.value().transparentForPositioner = transparent;
6796}
6797
6798
6799QString QQuickItemPrivate::dirtyToString() const
6800{
6801#define DIRTY_TO_STRING(value) if (dirtyAttributes & value) {
6802 if (!rv.isEmpty())
6803 rv.append(QLatin1Char('|'));
6804 rv.append(QLatin1String(#value)); \
6805}
6806
6807// QString rv = QLatin1String("0x") + QString::number(dirtyAttributes, 16);
6808 QString rv;
6809
6810 DIRTY_TO_STRING(TransformOrigin);
6811 DIRTY_TO_STRING(Transform);
6812 DIRTY_TO_STRING(BasicTransform);
6813 DIRTY_TO_STRING(Position);
6814 DIRTY_TO_STRING(Size);
6815 DIRTY_TO_STRING(ZValue);
6816 DIRTY_TO_STRING(Content);
6817 DIRTY_TO_STRING(Smooth);
6818 DIRTY_TO_STRING(OpacityValue);
6819 DIRTY_TO_STRING(ChildrenChanged);
6820 DIRTY_TO_STRING(ChildrenStackingChanged);
6821 DIRTY_TO_STRING(ParentChanged);
6822 DIRTY_TO_STRING(Clip);
6823 DIRTY_TO_STRING(Window);
6824 DIRTY_TO_STRING(EffectReference);
6825 DIRTY_TO_STRING(Visible);
6826 DIRTY_TO_STRING(HideReference);
6827 DIRTY_TO_STRING(Antialiasing);
6828
6829 return rv;
6830}
6831
6832void QQuickItemPrivate::dirty(DirtyType type)
6833{
6834 Q_Q(QQuickItem);
6835 if (!(dirtyAttributes & type) || (window && !prevDirtyItem)) {
6836 dirtyAttributes |= type;
6837 if (window && componentComplete) {
6838 addToDirtyList();
6839 QQuickWindowPrivate::get(window)->dirtyItem(q);
6840 }
6841 }
6842 if (type & (TransformOrigin | Transform | BasicTransform | Position | Size | Clip))
6843 transformChanged(q);
6844}
6845
6846void QQuickItemPrivate::addToDirtyList()
6847{
6848 Q_Q(QQuickItem);
6849
6850 Q_ASSERT(window);
6851 if (!prevDirtyItem) {
6852 Q_ASSERT(!nextDirtyItem);
6853
6854 QQuickWindowPrivate *p = QQuickWindowPrivate::get(window);
6855 nextDirtyItem = p->dirtyItemList;
6856 if (nextDirtyItem) QQuickItemPrivate::get(nextDirtyItem)->prevDirtyItem = &nextDirtyItem;
6857 prevDirtyItem = &p->dirtyItemList;
6858 p->dirtyItemList = q;
6859 p->dirtyItem(q);
6860 }
6861 Q_ASSERT(prevDirtyItem);
6862}
6863
6864void QQuickItemPrivate::removeFromDirtyList()
6865{
6866 if (prevDirtyItem) {
6867 if (nextDirtyItem) QQuickItemPrivate::get(nextDirtyItem)->prevDirtyItem = prevDirtyItem;
6868 *prevDirtyItem = nextDirtyItem;
6869 prevDirtyItem = nullptr;
6870 nextDirtyItem = nullptr;
6871 }
6872 Q_ASSERT(!prevDirtyItem);
6873 Q_ASSERT(!nextDirtyItem);
6874}
6875
6876void QQuickItemPrivate::refFromEffectItem(bool hide)
6877{
6878 ++extra.value().effectRefCount;
6879 if (extra->effectRefCount == 1) {
6880 dirty(EffectReference);
6881 if (parentItem)
6882 QQuickItemPrivate::get(parentItem)->dirty(ChildrenStackingChanged);
6883 }
6884 if (hide) {
6885 if (++extra->hideRefCount == 1)
6886 dirty(HideReference);
6887 }
6888 recursiveRefFromEffectItem(1);
6889}
6890
6891void QQuickItemPrivate::recursiveRefFromEffectItem(int refs)
6892{
6893 Q_Q(QQuickItem);
6894 if (!refs)
6895 return;
6896 extra.value().recursiveEffectRefCount += refs;
6897 for (int ii = 0; ii < childItems.size(); ++ii) {
6898 QQuickItem *child = childItems.at(ii);
6899 QQuickItemPrivate::get(child)->recursiveRefFromEffectItem(refs);
6900 }
6901 // Polish may rely on the effect ref count so trigger one, if item is not visible
6902 // (if visible, it will be triggered automatically).
6903 if (!effectiveVisible && refs > 0 && extra.value().recursiveEffectRefCount == 1) // it wasn't referenced, now it's referenced
6904 q->polish();
6905}
6906
6907void QQuickItemPrivate::derefFromEffectItem(bool unhide)
6908{
6909 Q_ASSERT(extra->effectRefCount);
6910 --extra->effectRefCount;
6911 if (extra->effectRefCount == 0) {
6912 dirty(EffectReference);
6913 if (parentItem)
6914 QQuickItemPrivate::get(parentItem)->dirty(ChildrenStackingChanged);
6915 }
6916 if (unhide) {
6917 if (--extra->hideRefCount == 0)
6918 dirty(HideReference);
6919 }
6920 recursiveRefFromEffectItem(-1);
6921}
6922
6923void QQuickItemPrivate::setCulled(bool cull)
6924{
6925 if (cull == culled)
6926 return;
6927
6928 culled = cull;
6929 if ((cull && ++extra.value().hideRefCount == 1) || (!cull && --extra.value().hideRefCount == 0))
6930 dirty(HideReference);
6931}
6932
6933void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data)
6934{
6935 Q_Q(QQuickItem);
6936 switch (change) {
6937 case QQuickItem::ItemChildAddedChange: {
6938 q->itemChange(change, data);
6939 // The newly added child or any of its descendants may have
6940 // ItemObservesViewport set, in which case we need to both
6941 // inform the item that the transform has changed, and re-apply
6942 // subtreeTransformChangedEnabled to both this item and its
6943 // ancestors.
6944 if (QQuickItemPrivate::get(data.item)->transformChanged(q)) {
6945 if (!subtreeTransformChangedEnabled) {
6946 qCDebug(lcVP) << "turned on transformChanged notification for subtree of" << q;
6947 subtreeTransformChangedEnabled = true;
6948 }
6949 enableSubtreeChangeNotificationsForParentHierachy();
6950 }
6951 notifyChangeListeners(QQuickItemPrivate::Children, &QQuickItemChangeListener::itemChildAdded, q, data.item);
6952 break;
6953 }
6954 case QQuickItem::ItemChildRemovedChange: {
6955 q->itemChange(change, data);
6956 notifyChangeListeners(QQuickItemPrivate::Children, &QQuickItemChangeListener::itemChildRemoved, q, data.item);
6957 break;
6958 }
6959 case QQuickItem::ItemSceneChange:
6960 q->itemChange(change, data);
6961 break;
6962 case QQuickItem::ItemVisibleHasChanged: {
6963 q->itemChange(change, data);
6964 notifyChangeListeners(QQuickItemPrivate::Visibility, &QQuickItemChangeListener::itemVisibilityChanged, q);
6965 break;
6966 }
6967 case QQuickItem::ItemEnabledHasChanged: {
6968 q->itemChange(change, data);
6969 notifyChangeListeners(QQuickItemPrivate::Enabled, &QQuickItemChangeListener::itemEnabledChanged, q);
6970 break;
6971 }
6972 case QQuickItem::ItemParentHasChanged: {
6973 q->itemChange(change, data);
6974 notifyChangeListeners(QQuickItemPrivate::Parent, &QQuickItemChangeListener::itemParentChanged, q, data.item);
6975 break;
6976 }
6977 case QQuickItem::ItemOpacityHasChanged: {
6978 q->itemChange(change, data);
6979 notifyChangeListeners(QQuickItemPrivate::Opacity, &QQuickItemChangeListener::itemOpacityChanged, q);
6980 break;
6981 }
6982 case QQuickItem::ItemActiveFocusHasChanged:
6983 q->itemChange(change, data);
6984 break;
6985 case QQuickItem::ItemRotationHasChanged: {
6986 q->itemChange(change, data);
6987 notifyChangeListeners(QQuickItemPrivate::Rotation, &QQuickItemChangeListener::itemRotationChanged, q);
6988 break;
6989 }
6990 case QQuickItem::ItemScaleHasChanged: {
6991 q->itemChange(change, data);
6992 notifyChangeListeners(QQuickItemPrivate::Scale, &QQuickItemChangeListener::itemScaleChanged, q);
6993 break;
6994 }
6995 case QQuickItem::ItemTransformHasChanged: {
6996 q->itemChange(change, data);
6997 notifyChangeListeners(QQuickItemPrivate::Matrix, &QQuickItemChangeListener::itemTransformChanged, q, data.item);
6998 break;
6999 }
7000 case QQuickItem::ItemAntialiasingHasChanged:
7001 // fall through
7002 case QQuickItem::ItemDevicePixelRatioHasChanged:
7003 q->itemChange(change, data);
7004 break;
7005 }
7006}
7007
7008/*!
7009 \qmlproperty bool QtQuick::Item::smooth
7010
7011 Primarily used in image based items to decide if the item should use smooth
7012 sampling or not. Smooth sampling is performed using linear interpolation, while
7013 non-smooth is performed using nearest neighbor.
7014
7015 In Qt Quick 2.0, this property has minimal impact on performance.
7016
7017 By default, this property is set to \c true.
7018*/
7019/*!
7020 \property QQuickItem::smooth
7021 \brief Specifies whether the item is smoothed or not
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*/
7031bool QQuickItem::smooth() const
7032{
7033 Q_D(const QQuickItem);
7034 return d->smooth;
7035}
7036void QQuickItem::setSmooth(bool smooth)
7037{
7038 Q_D(QQuickItem);
7039 if (d->smooth == smooth)
7040 return;
7041
7042 d->smooth = smooth;
7043 d->dirty(QQuickItemPrivate::Smooth);
7044
7045 emit smoothChanged(smooth);
7046}
7047
7048/*!
7049 \qmlproperty bool QtQuick::Item::activeFocusOnTab
7050
7051 This property holds whether the item wants to be in the tab focus
7052 chain. By default, this is set to \c false.
7053
7054 The tab focus chain traverses elements by first visiting the
7055 parent, and then its children in the order they occur in the
7056 children property. Pressing the tab key on an item in the tab
7057 focus chain will move keyboard focus to the next item in the
7058 chain. Pressing BackTab (normally Shift+Tab) will move focus
7059 to the previous item.
7060
7061 To set up a manual tab focus chain, see \l KeyNavigation. Tab
7062 key events used by Keys or KeyNavigation have precedence over
7063 focus chain behavior; ignore the events in other key handlers
7064 to allow it to propagate.
7065
7066 \note {QStyleHints::tabFocusBehavior}{tabFocusBehavior} can further limit focus
7067 to only specific types of controls, such as only text or list controls. This is
7068 the case on macOS, where focus to particular controls may be restricted based on
7069 system settings.
7070
7071 \sa QStyleHints::tabFocusBehavior, focusPolicy
7072*/
7073/*!
7074 \property QQuickItem::activeFocusOnTab
7075
7076 This property holds whether the item wants to be in the tab focus
7077 chain. By default, this is set to \c false.
7078
7079 \note {QStyleHints::tabFocusBehavior}{tabFocusBehavior} can further limit focus
7080 to only specific types of controls, such as only text or list controls. This is
7081 the case on macOS, where focus to particular controls may be restricted based on
7082 system settings.
7083
7084 \sa QStyleHints::tabFocusBehavior, focusPolicy
7085*/
7086// TODO FOCUS: Deprecate
7087bool QQuickItem::activeFocusOnTab() const
7088{
7089 Q_D(const QQuickItem);
7090 return d->activeFocusOnTab;
7091}
7092void QQuickItem::setActiveFocusOnTab(bool activeFocusOnTab)
7093{
7094 Q_D(QQuickItem);
7095 if (d->activeFocusOnTab == activeFocusOnTab)
7096 return;
7097
7098 if (window()) {
7099 if ((this == window()->activeFocusItem()) && this != window()->contentItem() && !activeFocusOnTab) {
7100 qWarning("QQuickItem: Cannot set activeFocusOnTab to false once item is the active focus item.");
7101 return;
7102 }
7103 }
7104
7105 d->activeFocusOnTab = activeFocusOnTab;
7106
7107 emit activeFocusOnTabChanged(activeFocusOnTab);
7108}
7109
7110/*!
7111 \qmlproperty bool QtQuick::Item::antialiasing
7112
7113 Used by visual elements to decide if the item should use antialiasing or not.
7114 In some cases items with antialiasing require more memory and are potentially
7115 slower to render (see \l {Antialiasing} for more details).
7116
7117 The default is false, but may be overridden by derived elements.
7118*/
7119/*!
7120 \property QQuickItem::antialiasing
7121 \brief Specifies whether the item is antialiased or not
7122
7123 Used by visual elements to decide if the item should use antialiasing or not.
7124 In some cases items with antialiasing require more memory and are potentially
7125 slower to render (see \l {Antialiasing} for more details).
7126
7127 The default is false, but may be overridden by derived elements.
7128*/
7129bool QQuickItem::antialiasing() const
7130{
7131 Q_D(const QQuickItem);
7132 return d->antialiasingValid ? d->antialiasing : d->implicitAntialiasing;
7133}
7134
7135void QQuickItem::setAntialiasing(bool aa)
7136{
7137 Q_D(QQuickItem);
7138
7139 if (!d->antialiasingValid) {
7140 d->antialiasingValid = true;
7141 d->antialiasing = d->implicitAntialiasing;
7142 }
7143
7144 if (aa == d->antialiasing)
7145 return;
7146
7147 d->antialiasing = aa;
7148 d->dirty(QQuickItemPrivate::Antialiasing);
7149
7150 d->itemChange(ItemAntialiasingHasChanged, bool(d->antialiasing));
7151
7152 emit antialiasingChanged(antialiasing());
7153}
7154
7155void QQuickItem::resetAntialiasing()
7156{
7157 Q_D(QQuickItem);
7158 if (!d->antialiasingValid)
7159 return;
7160
7161 d->antialiasingValid = false;
7162
7163 if (d->implicitAntialiasing != d->antialiasing)
7164 emit antialiasingChanged(antialiasing());
7165}
7166
7167void QQuickItemPrivate::setImplicitAntialiasing(bool antialiasing)
7168{
7169 Q_Q(QQuickItem);
7170 bool prev = q->antialiasing();
7171 implicitAntialiasing = antialiasing;
7172 if (componentComplete && (q->antialiasing() != prev))
7173 emit q->antialiasingChanged(q->antialiasing());
7174}
7175
7176/*!
7177 Returns the item flags for this item.
7178
7179 \sa setFlag()
7180 */
7181QQuickItem::Flags QQuickItem::flags() const
7182{
7183 Q_D(const QQuickItem);
7184 return (QQuickItem::Flags)d->flags;
7185}
7186
7187/*!
7188 Enables the specified \a flag for this item if \a enabled is true;
7189 if \a enabled is false, the flag is disabled.
7190
7191 These provide various hints for the item; for example, the
7192 ItemClipsChildrenToShape flag indicates that all children of this
7193 item should be clipped to fit within the item area.
7194 */
7195void QQuickItem::setFlag(Flag flag, bool enabled)
7196{
7197 Q_D(QQuickItem);
7198 if (enabled)
7199 setFlags((Flags)(d->flags | (quint32)flag));
7200 else
7201 setFlags((Flags)(d->flags & ~(quint32)flag));
7202
7203 // We don't return early if the flag did not change. That's useful in case
7204 // we need to intentionally trigger this parent-chain traversal again.
7205 if (enabled && flag == ItemObservesViewport)
7206 d->enableSubtreeChangeNotificationsForParentHierachy();
7207}
7208
7209void QQuickItemPrivate::enableSubtreeChangeNotificationsForParentHierachy()
7210{
7211 Q_Q(QQuickItem);
7212
7213 QQuickItem *par = q->parentItem();
7214 while (par) {
7215 auto parPriv = QQuickItemPrivate::get(par);
7216 if (!parPriv->subtreeTransformChangedEnabled)
7217 qCDebug(lcVP) << "turned on transformChanged notification for subtree of" << par;
7218 parPriv->subtreeTransformChangedEnabled = true;
7219 par = par->parentItem();
7220 }
7221}
7222
7223/*!
7224 Enables the specified \a flags for this item.
7225
7226 \sa setFlag()
7227 */
7228void QQuickItem::setFlags(Flags flags)
7229{
7230 Q_D(QQuickItem);
7231
7232 if (int(flags & ItemIsFocusScope) != int(d->flags & ItemIsFocusScope)) {
7233 if (flags & ItemIsFocusScope && !d->childItems.isEmpty() && d->window) {
7234 qWarning("QQuickItem: Cannot set FocusScope once item has children and is in a window.");
7235 flags &= ~ItemIsFocusScope;
7236 } else if (d->flags & ItemIsFocusScope) {
7237 qWarning("QQuickItem: Cannot unset FocusScope flag.");
7238 flags |= ItemIsFocusScope;
7239 }
7240 }
7241
7242 if (int(flags & ItemClipsChildrenToShape) != int(d->flags & ItemClipsChildrenToShape))
7243 d->dirty(QQuickItemPrivate::Clip);
7244
7245 d->flags = flags;
7246}
7247
7248/*!
7249 \qmlproperty real QtQuick::Item::x
7250 \qmlproperty real QtQuick::Item::y
7251 \qmlproperty real QtQuick::Item::width
7252 \qmlproperty real QtQuick::Item::height
7253
7254 Defines the item's position and size.
7255 The default value is \c 0.
7256
7257 The (x,y) position is relative to the \l parent.
7258
7259 \qml
7260 Item { x: 100; y: 100; width: 100; height: 100 }
7261 \endqml
7262 */
7263/*!
7264 \property QQuickItem::x
7265
7266 Defines the item's x position relative to its parent.
7267 */
7268/*!
7269 \property QQuickItem::y
7270
7271 Defines the item's y position relative to its parent.
7272 */
7273qreal QQuickItem::x() const
7274{
7275 Q_D(const QQuickItem);
7276 return d->x;
7277}
7278
7279qreal QQuickItem::y() const
7280{
7281 Q_D(const QQuickItem);
7282 return d->y;
7283}
7284
7285/*!
7286 \internal
7287 */
7288QPointF QQuickItem::position() const
7289{
7290 Q_D(const QQuickItem);
7291 return QPointF(d->x, d->y);
7292}
7293
7294void QQuickItem::setX(qreal v)
7295{
7296 Q_D(QQuickItem);
7297 /* There are two ways in which this function might be called:
7298 a) Either directly by the user, or
7299 b) when a binding has evaluated to a new value and it writes
7300 the value back
7301 In the first case, we want to remove an existing binding, in
7302 the second case, we don't want to remove the binding which
7303 just wrote the value.
7304 removeBindingUnlessInWrapper takes care of this.
7305 */
7306 d->x.removeBindingUnlessInWrapper();
7307 if (qt_is_nan(v))
7308 return;
7309
7310 const qreal oldx = d->x.valueBypassingBindings();
7311 if (oldx == v)
7312 return;
7313
7314 d->x.setValueBypassingBindings(v);
7315
7316 d->dirty(QQuickItemPrivate::Position);
7317
7318 const qreal y = d->y.valueBypassingBindings();
7319 const qreal w = d->width.valueBypassingBindings();
7320 const qreal h = d->height.valueBypassingBindings();
7321 geometryChange(QRectF(v, y, w, h), QRectF(oldx, y, w, h));
7322}
7323
7324void QQuickItem::setY(qreal v)
7325{
7326 Q_D(QQuickItem);
7327 d->y.removeBindingUnlessInWrapper();
7328 if (qt_is_nan(v))
7329 return;
7330
7331 const qreal oldy = d->y.valueBypassingBindings();
7332 if (oldy == v)
7333 return;
7334
7335 d->y.setValueBypassingBindings(v);
7336
7337 d->dirty(QQuickItemPrivate::Position);
7338
7339 // we use v instead of d->y, as that avoid a method call
7340 // and we have v anyway in scope
7341 const qreal x = d->x.valueBypassingBindings();
7342 const qreal w = d->width.valueBypassingBindings();
7343 const qreal h = d->height.valueBypassingBindings();
7344 geometryChange(QRectF(x, v, w, h), QRectF(x, oldy, w, h));
7345}
7346
7347/*!
7348 \internal
7349 */
7350void QQuickItem::setPosition(const QPointF &pos)
7351{
7352 Q_D(QQuickItem);
7353
7354 const qreal oldx = d->x.valueBypassingBindings();
7355 const qreal oldy = d->y.valueBypassingBindings();
7356
7357 if (QPointF(oldx, oldy) == pos)
7358 return;
7359
7360 /* This preserves the bindings, because that was what the code used to do
7361 The effect of this is that you can have
7362 Item {
7363 Rectangle {
7364 x: someValue; y: someValue
7365 DragHandler {}
7366 }
7367 }
7368 and you can move the rectangle around; once someValue changes, the position gets
7369 reset again (even when a drag is currently ongoing).
7370 Whether we want this is up to discussion.
7371 */
7372
7373 d->x.setValueBypassingBindings(pos.x()); //TODO: investigate whether to break binding here or not
7374 d->y.setValueBypassingBindings(pos.y());
7375
7376 d->dirty(QQuickItemPrivate::Position);
7377
7378 const qreal w = d->width.valueBypassingBindings();
7379 const qreal h = d->height.valueBypassingBindings();
7380 geometryChange(QRectF(pos.x(), pos.y(), w, h), QRectF(oldx, oldy, w, h));
7381}
7382
7383/* The bindable methods return an object which supports inspection (hasBinding) and
7384 modification (setBinding, removeBinding) of the properties bindable state.
7385*/
7386QBindable<qreal> QQuickItem::bindableX()
7387{
7388 return QBindable<qreal>(&d_func()->x);
7389}
7390
7391QBindable<qreal> QQuickItem::bindableY()
7392{
7393 return QBindable<qreal>(&d_func()->y);
7394}
7395
7396/*!
7397 \property QQuickItem::width
7398
7399 This property holds the width of this item.
7400 */
7401qreal QQuickItem::width() const
7402{
7403 Q_D(const QQuickItem);
7404 return d->width;
7405}
7406
7407void QQuickItem::setWidth(qreal w)
7408{
7409 Q_D(QQuickItem);
7410 d->width.removeBindingUnlessInWrapper();
7411 if (qt_is_nan(w))
7412 return;
7413
7414 d->widthValidFlag = true;
7415 const qreal oldWidth = d->width.valueBypassingBindings();
7416 if (oldWidth == w)
7417 return;
7418
7419 d->width.setValueBypassingBindings(w);
7420
7421 d->dirty(QQuickItemPrivate::Size);
7422
7423 const qreal x = d->x.valueBypassingBindings();
7424 const qreal y = d->y.valueBypassingBindings();
7425 const qreal h = d->height.valueBypassingBindings();
7426 geometryChange(QRectF(x, y, w, h), QRectF(x, y, oldWidth, h));
7427}
7428
7429void QQuickItem::resetWidth()
7430{
7431 Q_D(QQuickItem);
7432 d->width.takeBinding();
7433 d->widthValidFlag = false;
7434 setImplicitWidth(implicitWidth());
7435}
7436
7437void QQuickItemPrivate::implicitWidthChanged()
7438{
7439 Q_Q(QQuickItem);
7440 notifyChangeListeners(QQuickItemPrivate::ImplicitWidth, &QQuickItemChangeListener::itemImplicitWidthChanged, q);
7441 emit q->implicitWidthChanged();
7442}
7443
7444qreal QQuickItemPrivate::getImplicitWidth() const
7445{
7446 return implicitWidth;
7447}
7448/*!
7449 Returns the width of the item that is implied by other properties that determine the content.
7450*/
7451qreal QQuickItem::implicitWidth() const
7452{
7453 Q_D(const QQuickItem);
7454 return d->getImplicitWidth();
7455}
7456
7457QBindable<qreal> QQuickItem::bindableWidth()
7458{
7459 return QBindable<qreal>(&d_func()->width);
7460}
7461
7462/*!
7463 \qmlproperty real QtQuick::Item::implicitWidth
7464 \qmlproperty real QtQuick::Item::implicitHeight
7465
7466 Defines the preferred width or height of the Item.
7467
7468 If \l width or \l height is not specified, an item's effective size will be
7469 determined by its \l implicitWidth or \l implicitHeight.
7470
7471 However, if an item is the child of a \l {Qt Quick Layouts}{layout}, the
7472 layout will determine the item's preferred size using its implicit size.
7473 In such a scenario, the explicit \l width or \l height will be ignored.
7474
7475 The default implicit size for most items is 0x0, however some items have an inherent
7476 implicit size which cannot be overridden, for example, \l [QML] Image and \l [QML] Text.
7477
7478 Setting the implicit size is useful for defining components that have a preferred size
7479 based on their content, for example:
7480
7481 \qml
7482 // Label.qml
7483 import QtQuick 2.0
7484
7485 Item {
7486 property alias icon: image.source
7487 property alias label: text.text
7488 implicitWidth: text.implicitWidth + image.implicitWidth
7489 implicitHeight: Math.max(text.implicitHeight, image.implicitHeight)
7490 Image { id: image }
7491 Text {
7492 id: text
7493 wrapMode: Text.Wrap
7494 anchors.left: image.right; anchors.right: parent.right
7495 anchors.verticalCenter: parent.verticalCenter
7496 }
7497 }
7498 \endqml
7499
7500 \note Using implicitWidth of \l [QML] Text or \l [QML] TextEdit and setting the width explicitly
7501 incurs a performance penalty as the text must be laid out twice.
7502*/
7503/*!
7504 \property QQuickItem::implicitWidth
7505 \property QQuickItem::implicitHeight
7506
7507 Defines the preferred width or height of the Item.
7508
7509 If \l width or \l height is not specified, an item's effective size will be
7510 determined by its \l implicitWidth or \l implicitHeight.
7511
7512 However, if an item is the child of a \l {Qt Quick Layouts}{layout}, the
7513 layout will determine the item's preferred size using its implicit size.
7514 In such a scenario, the explicit \l width or \l height will be ignored.
7515
7516 The default implicit size for most items is 0x0, however some items have an inherent
7517 implicit size which cannot be overridden, for example, \l [QML] Image and \l [QML] Text.
7518
7519 Setting the implicit size is useful for defining components that have a preferred size
7520 based on their content, for example:
7521
7522 \qml
7523 // Label.qml
7524 import QtQuick 2.0
7525
7526 Item {
7527 property alias icon: image.source
7528 property alias label: text.text
7529 implicitWidth: text.implicitWidth + image.implicitWidth
7530 implicitHeight: Math.max(text.implicitHeight, image.implicitHeight)
7531 Image { id: image }
7532 Text {
7533 id: text
7534 wrapMode: Text.Wrap
7535 anchors.left: image.right; anchors.right: parent.right
7536 anchors.verticalCenter: parent.verticalCenter
7537 }
7538 }
7539 \endqml
7540
7541 \note Using implicitWidth of \l [QML] Text or \l [QML] TextEdit and setting the width explicitly
7542 incurs a performance penalty as the text must be laid out twice.
7543*/
7544void QQuickItem::setImplicitWidth(qreal w)
7545{
7546 Q_D(QQuickItem);
7547 bool changed = w != d->implicitWidth;
7548 d->implicitWidth = w;
7549 // this uses valueBypassingBindings simply to avoid repeated "am I in a binding" checks
7550 if (d->width.valueBypassingBindings() == w || widthValid()) {
7551 if (changed)
7552 d->implicitWidthChanged();
7553 if (d->width.valueBypassingBindings() == w || widthValid())
7554 return;
7555 changed = false;
7556 }
7557
7558 const qreal oldWidth = d->width.valueBypassingBindings();
7559 Q_ASSERT(!d->width.hasBinding() || QQmlPropertyBinding::isUndefined(d->width.binding()));
7560 // we need to keep the binding if its undefined (therefore we can't use operator=/setValue)
7561 d->width.setValueBypassingBindings(w);
7562
7563 d->dirty(QQuickItemPrivate::Size);
7564
7565 const qreal x = d->x.valueBypassingBindings();
7566 const qreal y = d->y.valueBypassingBindings();
7567 const qreal width = w;
7568 const qreal height = d->height.valueBypassingBindings();
7569 geometryChange(QRectF(x, y, width, height), QRectF(x, y, oldWidth, height));
7570
7571 if (changed)
7572 d->implicitWidthChanged();
7573}
7574
7575/*!
7576 Returns whether the width property has been set explicitly.
7577*/
7578bool QQuickItem::widthValid() const
7579{
7580 Q_D(const QQuickItem);
7581 /* Logic: The width is valid if we assigned a value
7582 or a binding to it. Note that a binding evaluation to
7583 undefined (and thus calling resetWidth) is detached [1];
7584 hasBinding will thus return false for it, which is
7585 what we want here, as resetting width should mean that
7586 width is invalid (until the binding evaluates to a
7587 non-undefined value again).
7588
7589 [1]: A detached binding is a binding which is not set on a property.
7590 In the case of QQmlPropertyBinding and resettable properties, it
7591 still gets reevaluated when it was detached due to the binding
7592 returning undefined, and it gets re-attached, once the binding changes
7593 to a non-undefined value (unless another binding has beenset in the
7594 meantime).
7595 See QQmlPropertyBinding::isUndefined and handleUndefinedAssignment
7596 */
7597
7598 return d->widthValid();
7599}
7600
7601/*!
7602 \property QQuickItem::height
7603
7604 This property holds the height of this item.
7605 */
7606qreal QQuickItem::height() const
7607{
7608 Q_D(const QQuickItem);
7609 return d->height;
7610}
7611
7612void QQuickItem::setHeight(qreal h)
7613{
7614 Q_D(QQuickItem);
7615 // Note that we call removeUnlessInWrapper before returning in the
7616 // NaN and equal value cases; that ensures that an explicit setHeight
7617 // always removes the binding
7618 d->height.removeBindingUnlessInWrapper();
7619 if (qt_is_nan(h))
7620 return;
7621
7622 d->heightValidFlag = true;
7623 const qreal oldHeight = d->height.valueBypassingBindings();
7624 if (oldHeight == h)
7625 return;
7626
7627 d->height.setValueBypassingBindings(h);
7628
7629 d->dirty(QQuickItemPrivate::Size);
7630
7631 const qreal x = d->x.valueBypassingBindings();
7632 const qreal y = d->y.valueBypassingBindings();
7633 const qreal w = d->width.valueBypassingBindings();
7634 geometryChange(QRectF(x, y, w, h), QRectF(x, y, w, oldHeight));
7635}
7636
7637void QQuickItem::resetHeight()
7638{
7639 Q_D(QQuickItem);
7640 // using takeBinding, we remove any existing binding from the
7641 // property, but preserve the existing value (and avoid some overhead
7642 // compared to calling setHeight(height())
7643 d->height.takeBinding();
7644 d->heightValidFlag = false;
7645 setImplicitHeight(implicitHeight());
7646}
7647
7648void QQuickItemPrivate::implicitHeightChanged()
7649{
7650 Q_Q(QQuickItem);
7651 notifyChangeListeners(QQuickItemPrivate::ImplicitHeight, &QQuickItemChangeListener::itemImplicitHeightChanged, q);
7652 emit q->implicitHeightChanged();
7653}
7654
7655qreal QQuickItemPrivate::getImplicitHeight() const
7656{
7657 return implicitHeight;
7658}
7659
7660qreal QQuickItem::implicitHeight() const
7661{
7662 Q_D(const QQuickItem);
7663 return d->getImplicitHeight();
7664}
7665
7666QBindable<qreal> QQuickItem::bindableHeight()
7667{
7668 return QBindable<qreal>(&d_func()->height);
7669}
7670
7671void QQuickItem::setImplicitHeight(qreal h)
7672{
7673 Q_D(QQuickItem);
7674 bool changed = h != d->implicitHeight;
7675 d->implicitHeight = h;
7676 if (d->height.valueBypassingBindings() == h || heightValid()) {
7677 if (changed)
7678 d->implicitHeightChanged();
7679 if (d->height.valueBypassingBindings() == h || heightValid())
7680 return;
7681 changed = false;
7682 }
7683
7684 const qreal oldHeight = d->height.valueBypassingBindings();
7685 Q_ASSERT(!d->height.hasBinding() || QQmlPropertyBinding::isUndefined(d->height.binding()));
7686 // we need to keep the binding if its undefined (therefore we can't use operator=/setValue)
7687 d->height.setValueBypassingBindings(h);
7688
7689 d->dirty(QQuickItemPrivate::Size);
7690
7691 const qreal x = d->x.valueBypassingBindings();
7692 const qreal y = d->y.valueBypassingBindings();
7693 const qreal width = d->width.valueBypassingBindings();
7694 const qreal height = d->height.valueBypassingBindings();
7695 geometryChange(QRectF(x, y, width, height),
7696 QRectF(x, y, width, oldHeight));
7697
7698 if (changed)
7699 d->implicitHeightChanged();
7700}
7701
7702/*!
7703 \internal
7704 */
7705void QQuickItem::setImplicitSize(qreal w, qreal h)
7706{
7707 Q_D(QQuickItem);
7708 bool wChanged = w != d->implicitWidth;
7709 bool hChanged = h != d->implicitHeight;
7710
7711 d->implicitWidth = w;
7712 d->implicitHeight = h;
7713
7714 bool wDone = false;
7715 bool hDone = false;
7716 qreal width = d->width.valueBypassingBindings();
7717 qreal height = d->height.valueBypassingBindings();
7718 if (width == w || widthValid()) {
7719 if (wChanged)
7720 d->implicitWidthChanged();
7721 wDone = width == w || widthValid();
7722 wChanged = false;
7723 }
7724 if (height == h || heightValid()) {
7725 if (hChanged)
7726 d->implicitHeightChanged();
7727 hDone = height == h || heightValid();
7728 hChanged = false;
7729 }
7730 if (wDone && hDone)
7731 return;
7732
7733 const qreal oldWidth = width;
7734 const qreal oldHeight = height;
7735 if (!wDone) {
7736 width = w;
7737 d->width.setValueBypassingBindings(w);
7738 }
7739 if (!hDone) {
7740 height = h;
7741 d->height.setValueBypassingBindings(h);
7742 }
7743
7744 d->dirty(QQuickItemPrivate::Size);
7745
7746 const qreal x = d->x.valueBypassingBindings();
7747 const qreal y = d->y.valueBypassingBindings();
7748 geometryChange(QRectF(x, y, width, height),
7749 QRectF(x, y, oldWidth, oldHeight));
7750
7751 if (!wDone && wChanged)
7752 d->implicitWidthChanged();
7753 if (!hDone && hChanged)
7754 d->implicitHeightChanged();
7755}
7756
7757/*!
7758 Returns whether the height property has been set explicitly.
7759*/
7760bool QQuickItem::heightValid() const
7761{
7762 Q_D(const QQuickItem);
7763 return d->heightValid();
7764}
7765
7766/*!
7767 \since 5.10
7768
7769 Returns the size of the item.
7770
7771 \sa setSize, width, height
7772 */
7773
7774QSizeF QQuickItem::size() const
7775{
7776 Q_D(const QQuickItem);
7777 return QSizeF(d->width, d->height);
7778}
7779
7780
7781/*!
7782 \since 5.10
7783
7784 Sets the size of the item to \a size.
7785 This methods preserves any existing binding on width and height;
7786 thus any change that triggers the binding to execute again will
7787 override the set values.
7788
7789 \sa size, setWidth, setHeight
7790 */
7791void QQuickItem::setSize(const QSizeF &size)
7792{
7793 Q_D(QQuickItem);
7794 d->heightValidFlag = true;
7795 d->widthValidFlag = true;
7796
7797 const qreal oldHeight = d->height.valueBypassingBindings();
7798 const qreal oldWidth = d->width.valueBypassingBindings();
7799
7800 if (oldWidth == size.width() && oldHeight == size.height())
7801 return;
7802
7803 d->height.setValueBypassingBindings(size.height());
7804 d->width.setValueBypassingBindings(size.width());
7805
7806 d->dirty(QQuickItemPrivate::Size);
7807
7808 const qreal x = d->x.valueBypassingBindings();
7809 const qreal y = d->y.valueBypassingBindings();
7810 geometryChange(QRectF(x, y, size.width(), size.height()), QRectF(x, y, oldWidth, oldHeight));
7811}
7812
7813/*!
7814 \qmlproperty bool QtQuick::Item::activeFocus
7815 \readonly
7816
7817 This read-only property indicates whether the item has active focus.
7818
7819 If activeFocus is true, either this item is the one that currently
7820 receives keyboard input, or it is a FocusScope ancestor of the item
7821 that currently receives keyboard input.
7822
7823 Usually, activeFocus is gained by setting \l focus on an item and its
7824 enclosing FocusScope objects. In the following example, the \c input
7825 and \c focusScope objects will have active focus, while the root
7826 rectangle object will not.
7827
7828 \qml
7829 import QtQuick 2.0
7830
7831 Rectangle {
7832 width: 100; height: 100
7833
7834 FocusScope {
7835 id: focusScope
7836 focus: true
7837
7838 TextInput {
7839 id: input
7840 focus: true
7841 }
7842 }
7843 }
7844 \endqml
7845
7846 \sa focus, {Keyboard Focus in Qt Quick}
7847*/
7848/*!
7849 \property QQuickItem::activeFocus
7850 \readonly
7851
7852 This read-only property indicates whether the item has active focus.
7853
7854 If activeFocus is true, either this item is the one that currently
7855 receives keyboard input, or it is a FocusScope ancestor of the item
7856 that currently receives keyboard input.
7857
7858 Usually, activeFocus is gained by setting \l focus on an item and its
7859 enclosing FocusScope objects. In the following example, the \c input
7860 and \c focusScope objects will have active focus, while the root
7861 rectangle object will not.
7862
7863 \qml
7864 import QtQuick 2.0
7865
7866 Rectangle {
7867 width: 100; height: 100
7868
7869 FocusScope {
7870 focus: true
7871
7872 TextInput {
7873 id: input
7874 focus: true
7875 }
7876 }
7877 }
7878 \endqml
7879
7880 \sa focus, {Keyboard Focus in Qt Quick}
7881*/
7882bool QQuickItem::hasActiveFocus() const
7883{
7884 Q_D(const QQuickItem);
7885 return d->activeFocus;
7886}
7887
7888/*!
7889 \qmlproperty bool QtQuick::Item::focus
7890
7891 This property holds whether the item has focus within the enclosing
7892 FocusScope. If true, this item will gain active focus when the
7893 enclosing FocusScope gains active focus.
7894
7895 In the following example, \c input will be given active focus when
7896 \c scope gains active focus:
7897
7898 \qml
7899 import QtQuick 2.0
7900
7901 Rectangle {
7902 width: 100; height: 100
7903
7904 FocusScope {
7905 id: scope
7906
7907 TextInput {
7908 id: input
7909 focus: true
7910 }
7911 }
7912 }
7913 \endqml
7914
7915 For the purposes of this property, the scene as a whole is assumed
7916 to act like a focus scope. On a practical level, that means the
7917 following QML will give active focus to \c input on startup.
7918
7919 \qml
7920 Rectangle {
7921 width: 100; height: 100
7922
7923 TextInput {
7924 id: input
7925 focus: true
7926 }
7927 }
7928 \endqml
7929
7930 \sa activeFocus, {Keyboard Focus in Qt Quick}
7931*/
7932/*!
7933 \property QQuickItem::focus
7934
7935 This property holds whether the item has focus within the enclosing
7936 FocusScope. If true, this item will gain active focus when the
7937 enclosing FocusScope gains active focus.
7938
7939 In the following example, \c input will be given active focus when
7940 \c scope gains active focus:
7941
7942 \qml
7943 import QtQuick 2.0
7944
7945 Rectangle {
7946 width: 100; height: 100
7947
7948 FocusScope {
7949 id: scope
7950
7951 TextInput {
7952 id: input
7953 focus: true
7954 }
7955 }
7956 }
7957 \endqml
7958
7959 For the purposes of this property, the scene as a whole is assumed
7960 to act like a focus scope. On a practical level, that means the
7961 following QML will give active focus to \c input on startup.
7962
7963 \qml
7964 Rectangle {
7965 width: 100; height: 100
7966
7967 TextInput {
7968 id: input
7969 focus: true
7970 }
7971 }
7972 \endqml
7973
7974 \sa activeFocus, {Keyboard Focus in Qt Quick}
7975*/
7976bool QQuickItem::hasFocus() const
7977{
7978 Q_D(const QQuickItem);
7979 return d->focus;
7980}
7981
7982void QQuickItem::setFocus(bool focus)
7983{
7984 setFocus(focus, Qt::OtherFocusReason);
7985}
7986
7987void QQuickItem::setFocus(bool focus, Qt::FocusReason reason)
7988{
7989 Q_D(QQuickItem);
7990 // Need to find our nearest focus scope
7991 QQuickItem *scope = parentItem();
7992 while (scope && !scope->isFocusScope() && scope->parentItem())
7993 scope = scope->parentItem();
7994
7995 if (d->focus == focus && (!focus || !scope || QQuickItemPrivate::get(scope)->subFocusItem == this))
7996 return;
7997
7998 bool notifyListeners = false;
7999 if (d->window || d->parentItem) {
8000 if (d->window) {
8001 auto da = d->deliveryAgentPrivate();
8002 Q_ASSERT(da);
8003 if (focus)
8004 da->setFocusInScope(scope, this, reason);
8005 else
8006 da->clearFocusInScope(scope, this, reason);
8007 } else {
8008 // do the focus changes from setFocusInScope/clearFocusInScope that are
8009 // unrelated to a window
8010 QVarLengthArray<QQuickItem *, 20> changed;
8011 QQuickItem *oldSubFocusItem = QQuickItemPrivate::get(scope)->subFocusItem;
8012 if (oldSubFocusItem) {
8013 QQuickItemPrivate::get(oldSubFocusItem)->updateSubFocusItem(scope, false);
8014 QQuickItemPrivate::get(oldSubFocusItem)->focus = false;
8015 changed << oldSubFocusItem;
8016 } else if (!scope->isFocusScope() && scope->hasFocus()) {
8017 QQuickItemPrivate::get(scope)->focus = false;
8018 changed << scope;
8019 }
8020 d->updateSubFocusItem(scope, focus);
8021
8022 d->focus = focus;
8023 changed << this;
8024 notifyListeners = true;
8025 emit focusChanged(focus);
8026
8027 QQuickDeliveryAgentPrivate::notifyFocusChangesRecur(changed.data(), changed.size() - 1, reason);
8028 }
8029 } else {
8030 QVarLengthArray<QQuickItem *, 20> changed;
8031 QQuickItem *oldSubFocusItem = d->subFocusItem;
8032 if (!isFocusScope() && oldSubFocusItem) {
8033 QQuickItemPrivate::get(oldSubFocusItem)->updateSubFocusItem(this, false);
8034 QQuickItemPrivate::get(oldSubFocusItem)->focus = false;
8035 changed << oldSubFocusItem;
8036 }
8037
8038 d->focus = focus;
8039 changed << this;
8040 notifyListeners = true;
8041 emit focusChanged(focus);
8042
8043 QQuickDeliveryAgentPrivate::notifyFocusChangesRecur(changed.data(), changed.size() - 1, reason);
8044 }
8045 if (notifyListeners)
8046 d->notifyChangeListeners(QQuickItemPrivate::Focus, &QQuickItemChangeListener::itemFocusChanged, this, reason);
8047}
8048
8049/*!
8050 Returns true if this item is a focus scope, and false otherwise.
8051 */
8052bool QQuickItem::isFocusScope() const
8053{
8054 return flags() & ItemIsFocusScope;
8055}
8056
8057/*!
8058 If this item is a focus scope, this returns the item in its focus chain
8059 that currently has focus.
8060
8061 Returns \nullptr if this item is not a focus scope.
8062 */
8063QQuickItem *QQuickItem::scopedFocusItem() const
8064{
8065 Q_D(const QQuickItem);
8066 if (!isFocusScope())
8067 return nullptr;
8068 else
8069 return d->subFocusItem;
8070}
8071
8072/*!
8073 \qmlproperty enumeration QtQuick::Item::focusPolicy
8074 \since 6.7
8075
8076 This property determines the way the item accepts focus.
8077
8078 \value Qt.TabFocus The item accepts focus by tabbing.
8079 \value Qt.ClickFocus The item accepts focus by clicking.
8080 \value Qt.StrongFocus The item accepts focus by both tabbing and clicking.
8081 \value Qt.WheelFocus The item accepts focus by tabbing, clicking, and using the mouse wheel.
8082 \value Qt.NoFocus The item does not accept focus.
8083
8084 \note This property was a member of the \l[QML]{Control} QML type in Qt 6.6 and earlier.
8085*/
8086/*!
8087 \property QQuickItem::focusPolicy
8088 \since 6.7
8089
8090 This property determines the way the item accepts focus.
8091
8092*/
8093Qt::FocusPolicy QQuickItem::focusPolicy() const
8094{
8095 Q_D(const QQuickItem);
8096 uint policy = d->focusPolicy;
8097 if (activeFocusOnTab())
8098 policy |= Qt::TabFocus;
8099 return static_cast<Qt::FocusPolicy>(policy);
8100}
8101
8102/*!
8103 Sets the focus policy of this item to \a policy.
8104
8105 \sa focusPolicy()
8106*/
8107void QQuickItem::setFocusPolicy(Qt::FocusPolicy policy)
8108{
8109 Q_D(QQuickItem);
8110 if (d->focusPolicy == policy)
8111 return;
8112
8113 d->focusPolicy = policy;
8114 setActiveFocusOnTab(policy & Qt::TabFocus);
8115 emit focusPolicyChanged(policy);
8116}
8117
8118/*!
8119 Returns \c true if this item is an ancestor of \a child (i.e., if this item
8120 is \a child's parent, or one of \a child's parent's ancestors).
8121
8122 \since 5.7
8123
8124 \sa parentItem()
8125 */
8126bool QQuickItem::isAncestorOf(const QQuickItem *child) const
8127{
8128 if (!child || child == this)
8129 return false;
8130 const QQuickItem *ancestor = child;
8131 while ((ancestor = ancestor->parentItem())) {
8132 if (ancestor == this)
8133 return true;
8134 }
8135 return false;
8136}
8137
8138/*!
8139 Returns the mouse buttons accepted by this item.
8140
8141 The default value is Qt::NoButton; that is, no mouse buttons are accepted.
8142
8143 If an item does not accept the mouse button for a particular mouse event,
8144 the mouse event will not be delivered to the item and will be delivered
8145 to the next item in the item hierarchy instead.
8146
8147 \sa acceptTouchEvents()
8148*/
8149Qt::MouseButtons QQuickItem::acceptedMouseButtons() const
8150{
8151 Q_D(const QQuickItem);
8152 return d->acceptedMouseButtons();
8153}
8154
8155/*!
8156 Sets the mouse buttons accepted by this item to \a buttons.
8157
8158 \note In Qt 5, calling setAcceptedMouseButtons() implicitly caused
8159 an item to receive touch events as well as mouse events; but it was
8160 recommended to call setAcceptTouchEvents() to subscribe for them.
8161 In Qt 6, it is necessary to call setAcceptTouchEvents() to continue
8162 to receive them.
8163*/
8164void QQuickItem::setAcceptedMouseButtons(Qt::MouseButtons buttons)
8165{
8166 Q_D(QQuickItem);
8167 d->extra.setTag(d->extra.tag().setFlag(QQuickItemPrivate::LeftMouseButtonAccepted, buttons & Qt::LeftButton));
8168
8169 buttons &= ~Qt::LeftButton;
8170 if (buttons || d->extra.isAllocated()) {
8171 d->extra.value().acceptedMouseButtonsWithoutHandlers = buttons;
8172 d->extra.value().acceptedMouseButtons = d->extra->pointerHandlers.isEmpty() ? buttons : Qt::AllButtons;
8173 }
8174}
8175
8176/*!
8177 Returns whether pointer events intended for this item's children should be
8178 filtered through this item.
8179
8180 If both this item and a child item have acceptTouchEvents() \c true, then
8181 when a touch interaction occurs, this item will filter the touch event.
8182 But if either this item or the child cannot handle touch events,
8183 childMouseEventFilter() will be called with a synthesized mouse event.
8184
8185 \sa setFiltersChildMouseEvents(), childMouseEventFilter()
8186 */
8187bool QQuickItem::filtersChildMouseEvents() const
8188{
8189 Q_D(const QQuickItem);
8190 return d->filtersChildMouseEvents;
8191}
8192
8193/*!
8194 Sets whether pointer events intended for this item's children should be
8195 filtered through this item.
8196
8197 If \a filter is true, childMouseEventFilter() will be called when
8198 a pointer event is triggered for a child item.
8199
8200 \sa filtersChildMouseEvents()
8201 */
8202void QQuickItem::setFiltersChildMouseEvents(bool filter)
8203{
8204 Q_D(QQuickItem);
8205 d->filtersChildMouseEvents = filter;
8206}
8207
8208/*!
8209 \internal
8210 */
8211bool QQuickItem::isUnderMouse() const
8212{
8213 Q_D(const QQuickItem);
8214 if (!d->window)
8215 return false;
8216
8217 // QQuickWindow handles QEvent::Leave to reset the lastMousePosition
8218 // FIXME: Using QPointF() as the reset value means an item will not be
8219 // under the mouse if the mouse is at 0,0 of the window.
8220 if (const_cast<QQuickItemPrivate *>(d)->deliveryAgentPrivate()->lastMousePosition == QPointF())
8221 return false;
8222
8223 QPointF cursorPos = QGuiApplicationPrivate::lastCursorPosition;
8224 return contains(mapFromScene(d->window->mapFromGlobal(cursorPos)));
8225}
8226
8227/*!
8228 Returns whether hover events are accepted by this item.
8229
8230 The default value is false.
8231
8232 If this is false, then the item will not receive any hover events through
8233 the hoverEnterEvent(), hoverMoveEvent() and hoverLeaveEvent() functions.
8234*/
8235bool QQuickItem::acceptHoverEvents() const
8236{
8237 Q_D(const QQuickItem);
8238 return d->hoverEnabled;
8239}
8240
8241/*!
8242 If \a enabled is true, this sets the item to accept hover events;
8243 otherwise, hover events are not accepted by this item.
8244
8245 \sa acceptHoverEvents()
8246*/
8247void QQuickItem::setAcceptHoverEvents(bool enabled)
8248{
8249 Q_D(QQuickItem);
8250 // hoverEnabled causes hoveredLeafItemFound to be set to true when a hover
8251 // event is being delivered to this item, which effectively ends hover
8252 // event delivery, as it will then start sending hover events backwards
8253 // from the child to the root, in a straight line.
8254 d->hoverEnabled = enabled;
8255 // Recursively set subtreeHoverEnabled for all of our parents. Note that
8256 // even though this and hoverEnabled are set to the same values in this
8257 // function, only subtreeHoverEnabled is set for the entire parent chain.
8258 // subtreeHoverEnabled says that a certain tree _may_ want hover events,
8259 // but unlike hoverEnabled, won't prevent delivery to siblings.
8260 d->setHasHoverInChild(enabled);
8261 // The DA needs to resolve which items and handlers should now be hovered or unhovered.
8262 // Marking this item dirty ensures that flushFrameSynchronousEvents() will be called from the render loop,
8263 // even if this change is not in response to a mouse event and no item has already marked itself dirty.
8264 d->dirty(QQuickItemPrivate::Content);
8265}
8266
8267/*!
8268 Returns whether touch events are accepted by this item.
8269
8270 The default value is \c false.
8271
8272 If this is \c false, then the item will not receive any touch events through
8273 the touchEvent() function.
8274
8275 \since 5.10
8276*/
8277bool QQuickItem::acceptTouchEvents() const
8278{
8279 Q_D(const QQuickItem);
8280 return d->touchEnabled;
8281}
8282
8283/*!
8284 If \a enabled is true, this sets the item to accept touch events;
8285 otherwise, touch events are not accepted by this item.
8286
8287 \since 5.10
8288
8289 \sa acceptTouchEvents()
8290*/
8291void QQuickItem::setAcceptTouchEvents(bool enabled)
8292{
8293 Q_D(QQuickItem);
8294 d->touchEnabled = enabled;
8295}
8296
8297void QQuickItemPrivate::setHasCursorInChild(bool hc)
8298{
8299#if QT_CONFIG(cursor)
8300 Q_Q(QQuickItem);
8301
8302 // if we're asked to turn it off (because of an unsetcursor call, or a node
8303 // removal) then we should make sure it's really ok to turn it off.
8304 if (!hc && subtreeCursorEnabled) {
8305 if (hasCursor)
8306 return; // nope! sorry, I have a cursor myself
8307 for (QQuickItem *otherChild : std::as_const(childItems)) {
8308 QQuickItemPrivate *otherChildPrivate = QQuickItemPrivate::get(otherChild);
8309 if (otherChildPrivate->subtreeCursorEnabled || otherChildPrivate->hasCursor)
8310 return; // nope! sorry, something else wants it kept on.
8311 }
8312 }
8313
8314 subtreeCursorEnabled = hc;
8315 QQuickItem *parent = q->parentItem();
8316 if (parent) {
8317 QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(parent);
8318 parentPrivate->setHasCursorInChild(hc);
8319 }
8320#else
8321 Q_UNUSED(hc);
8322#endif
8323}
8324
8325void QQuickItemPrivate::setHasHoverInChild(bool hasHover)
8326{
8327 Q_Q(QQuickItem);
8328
8329 // if we're asked to turn it off (because of a setAcceptHoverEvents call, or a node
8330 // removal) then we should make sure it's really ok to turn it off.
8331 if (!hasHover && subtreeHoverEnabled) {
8332 if (hoverEnabled)
8333 return; // nope! sorry, I need hover myself
8334 if (hasEnabledHoverHandlers())
8335 return; // nope! sorry, this item has enabled HoverHandlers
8336
8337 for (QQuickItem *otherChild : std::as_const(childItems)) {
8338 QQuickItemPrivate *otherChildPrivate = QQuickItemPrivate::get(otherChild);
8339 if (otherChildPrivate->subtreeHoverEnabled || otherChildPrivate->hoverEnabled)
8340 return; // nope! sorry, something else wants it kept on.
8341 if (otherChildPrivate->hasEnabledHoverHandlers())
8342 return; // nope! sorry, we have pointer handlers which are interested.
8343 }
8344 }
8345
8346 qCDebug(lcHoverTrace) << q << subtreeHoverEnabled << "->" << hasHover;
8347 subtreeHoverEnabled = hasHover;
8348 QQuickItem *parent = q->parentItem();
8349 if (parent) {
8350 QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(parent);
8351 parentPrivate->setHasHoverInChild(hasHover);
8352 }
8353}
8354
8355#if QT_CONFIG(cursor)
8356
8357/*!
8358 Returns the cursor shape for this item.
8359
8360 The mouse cursor will assume this shape when it is over this
8361 item, unless an override cursor is set.
8362 See the \l{Qt::CursorShape}{list of predefined cursor objects} for a
8363 range of useful shapes.
8364
8365 If no cursor shape has been set this returns a cursor with the Qt::ArrowCursor shape, however
8366 another cursor shape may be displayed if an overlapping item has a valid cursor.
8367
8368 \sa setCursor(), unsetCursor()
8369*/
8370
8371QCursor QQuickItem::cursor() const
8372{
8373 Q_D(const QQuickItem);
8374 return d->extra.isAllocated()
8375 ? d->extra->cursor
8376 : QCursor();
8377}
8378
8379/*!
8380 Sets the \a cursor shape for this item.
8381
8382 \sa cursor(), unsetCursor()
8383*/
8384
8385void QQuickItem::setCursor(const QCursor &cursor)
8386{
8387 Q_D(QQuickItem);
8388
8389 Qt::CursorShape oldShape = d->extra.isAllocated() ? d->extra->cursor.shape() : Qt::ArrowCursor;
8390 qCDebug(lcHoverTrace) << oldShape << "->" << cursor.shape();
8391
8392 if (oldShape != cursor.shape() || oldShape >= Qt::LastCursor || cursor.shape() >= Qt::LastCursor) {
8393 d->extra.value().cursor = cursor;
8394 if (d->window) {
8395 QWindow *renderWindow = QQuickRenderControl::renderWindowFor(d->window);
8396 QWindow *window = renderWindow ? renderWindow : d->window; // this may not be a QQuickWindow
8397 if (QQuickWindowPrivate::get(d->window)->cursorItem == this)
8398 window->setCursor(cursor);
8399 }
8400 }
8401
8402 QPointF updateCursorPos;
8403 if (!d->hasCursor) {
8404 d->hasCursor = true;
8405 if (d->window) {
8406 QWindow *renderWindow = QQuickRenderControl::renderWindowFor(d->window);
8407 QWindow *window = renderWindow ? renderWindow : d->window;
8408 QPointF pos = window->mapFromGlobal(QGuiApplicationPrivate::lastCursorPosition);
8409 if (contains(mapFromScene(pos)))
8410 updateCursorPos = pos;
8411 }
8412 }
8413 d->setHasCursorInChild(d->hasCursor || d->hasCursorHandler);
8414 if (!updateCursorPos.isNull())
8415 QQuickWindowPrivate::get(d->window)->updateCursor(updateCursorPos);
8416}
8417
8418/*!
8419 Clears the cursor shape for this item.
8420
8421 \sa cursor(), setCursor()
8422*/
8423
8424void QQuickItem::unsetCursor()
8425{
8426 Q_D(QQuickItem);
8427 qCDebug(lcHoverTrace) << "clearing cursor";
8428 if (!d->hasCursor)
8429 return;
8430 d->hasCursor = false;
8431 d->setHasCursorInChild(d->hasCursorHandler);
8432 if (d->extra.isAllocated())
8433 d->extra->cursor = QCursor();
8434
8435 if (d->window) {
8436 QQuickWindowPrivate *windowPrivate = QQuickWindowPrivate::get(d->window);
8437 if (windowPrivate->cursorItem == this) {
8438 QPointF pos = d->window->mapFromGlobal(QGuiApplicationPrivate::lastCursorPosition);
8439 windowPrivate->updateCursor(pos);
8440 }
8441 }
8442}
8443
8444/*!
8445 \internal
8446 Returns the cursor that should actually be shown, allowing the given
8447 \a handler to override the Item cursor if it is active or hovered.
8448
8449 \sa cursor(), setCursor(), QtQuick::PointerHandler::cursor
8450*/
8451QCursor QQuickItemPrivate::effectiveCursor(const QQuickPointerHandler *handler) const
8452{
8453 Q_Q(const QQuickItem);
8454 if (!handler)
8455 return q->cursor();
8456 bool hoverCursorSet = false;
8457 QCursor hoverCursor;
8458 bool activeCursorSet = false;
8459 QCursor activeCursor;
8460 if (const QQuickHoverHandler *hoverHandler = qobject_cast<const QQuickHoverHandler *>(handler)) {
8461 hoverCursorSet = hoverHandler->isCursorShapeExplicitlySet();
8462 hoverCursor = hoverHandler->cursorShape();
8463 } else if (handler->active()) {
8464 activeCursorSet = handler->isCursorShapeExplicitlySet();
8465 activeCursor = handler->cursorShape();
8466 }
8467 if (activeCursorSet)
8468 return activeCursor;
8469 if (hoverCursorSet)
8470 return hoverCursor;
8471 return q->cursor();
8472}
8473
8474/*!
8475 \internal
8476 Returns the Pointer Handler that is currently attempting to set the cursor shape,
8477 or null if there is no such handler.
8478
8479 If there are multiple handlers attempting to set the cursor:
8480 \list
8481 \li an active handler has the highest priority (e.g. a DragHandler being dragged)
8482 \li any HoverHandler that is reacting to a non-mouse device has priority for
8483 kCursorOverrideTimeout ms (a tablet stylus is jittery so that's enough)
8484 \li otherwise a HoverHandler that is reacting to the mouse, if any
8485 \endlist
8486
8487 Within each category, if there are multiple handlers, the last-added one wins
8488 (the one that is declared at the bottom wins, because users may intuitively
8489 think it's "on top" even though there is no Z-order; or, one that is added
8490 in a specific use case overrides an imported component).
8491
8492 \sa QtQuick::PointerHandler::cursor
8493*/
8494QQuickPointerHandler *QQuickItemPrivate::effectiveCursorHandler() const
8495{
8496 if (!hasPointerHandlers())
8497 return nullptr;
8498 QQuickPointerHandler* activeHandler = nullptr;
8499 QQuickPointerHandler* mouseHandler = nullptr;
8500 QQuickPointerHandler* nonMouseHandler = nullptr;
8501 for (QQuickPointerHandler *h : extra->pointerHandlers) {
8502 if (!h->isCursorShapeExplicitlySet())
8503 continue;
8504 QQuickHoverHandler *hoverHandler = qmlobject_cast<QQuickHoverHandler *>(h);
8505 // Prioritize any HoverHandler that is reacting to a non-mouse device.
8506 // Otherwise, choose the first hovered handler that is found.
8507 // TODO maybe: there was an idea to add QPointerDevice* as argument to this function
8508 // and check the device type, but why? HoverHandler already does that.
8509 if (!activeHandler && hoverHandler && hoverHandler->isHovered()) {
8510 qCDebug(lcHoverTrace) << hoverHandler << hoverHandler->acceptedDevices() << "wants to set cursor" << hoverHandler->cursorShape();
8511 if (hoverHandler->acceptedDevices().testFlag(QPointingDevice::DeviceType::Mouse)) {
8512 // If there's a conflict, the last-added HoverHandler wins. Maybe the user is overriding a default...
8513 if (mouseHandler && mouseHandler->cursorShape() != hoverHandler->cursorShape()) {
8514 qCDebug(lcHoverTrace) << "mouse cursor conflict:" << mouseHandler << "wants" << mouseHandler->cursorShape()
8515 << "but" << hoverHandler << "wants" << hoverHandler->cursorShape();
8516 }
8517 mouseHandler = hoverHandler;
8518 } else {
8519 // If there's a conflict, the last-added HoverHandler wins.
8520 if (nonMouseHandler && nonMouseHandler->cursorShape() != hoverHandler->cursorShape()) {
8521 qCDebug(lcHoverTrace) << "non-mouse cursor conflict:" << nonMouseHandler << "wants" << nonMouseHandler->cursorShape()
8522 << "but" << hoverHandler << "wants" << hoverHandler->cursorShape();
8523 }
8524 nonMouseHandler = hoverHandler;
8525 }
8526 }
8527 if (!hoverHandler && h->active())
8528 activeHandler = h;
8529 }
8530 if (activeHandler) {
8531 qCDebug(lcHoverTrace) << "active handler choosing cursor" << activeHandler << activeHandler->cursorShape();
8532 return activeHandler;
8533 }
8534 // Mouse events are often synthetic; so if a HoverHandler for a non-mouse device wanted to set the cursor,
8535 // let it win, unless more than kCursorOverrideTimeout ms have passed
8536 // since the last time the non-mouse handler actually reacted to an event.
8537 // We could miss the fact that a tablet stylus has left proximity, because we don't deliver proximity events to windows.
8538 if (nonMouseHandler) {
8539 if (mouseHandler) {
8540 const bool beforeTimeout =
8541 QQuickPointerHandlerPrivate::get(mouseHandler)->lastEventTime <
8542 QQuickPointerHandlerPrivate::get(nonMouseHandler)->lastEventTime + kCursorOverrideTimeout;
8543 QQuickPointerHandler *winner = (beforeTimeout ? nonMouseHandler : mouseHandler);
8544 qCDebug(lcHoverTrace) << "non-mouse handler reacted last time:" << QQuickPointerHandlerPrivate::get(nonMouseHandler)->lastEventTime
8545 << "and mouse handler reacted at time:" << QQuickPointerHandlerPrivate::get(mouseHandler)->lastEventTime
8546 << "choosing cursor according to" << winner << winner->cursorShape();
8547 return winner;
8548 }
8549 qCDebug(lcHoverTrace) << "non-mouse handler choosing cursor" << nonMouseHandler << nonMouseHandler->cursorShape();
8550 return nonMouseHandler;
8551 }
8552 if (mouseHandler)
8553 qCDebug(lcHoverTrace) << "mouse handler choosing cursor" << mouseHandler << mouseHandler->cursorShape();
8554 return mouseHandler;
8555}
8556
8557#endif
8558
8559/*!
8560 \deprecated Use QPointerEvent::setExclusiveGrabber().
8561
8562 Grabs the mouse input.
8563
8564 This item will receive all mouse events until ungrabMouse() is called.
8565 Usually this function should not be called, since accepting for example
8566 a mouse press event makes sure that the following events are delivered
8567 to the item.
8568 If an item wants to take over mouse events from the current receiver,
8569 it needs to call this function.
8570
8571 \warning This function should be used with caution.
8572 */
8573void QQuickItem::grabMouse()
8574{
8575 Q_D(QQuickItem);
8576 if (!d->window)
8577 return;
8578 auto da = d->deliveryAgentPrivate();
8579 Q_ASSERT(da);
8580 auto eventInDelivery = da->eventInDelivery();
8581 if (!eventInDelivery) {
8582 qWarning() << "cannot grab mouse: no event is currently being delivered";
8583 return;
8584 }
8585 auto epd = da->mousePointData();
8586 eventInDelivery->setExclusiveGrabber(epd->eventPoint, this);
8587}
8588
8589/*!
8590 \deprecated Use QPointerEvent::setExclusiveGrabber().
8591
8592 Releases the mouse grab following a call to grabMouse().
8593
8594 Note that this function should only be called when the item wants
8595 to stop handling further events. There is no need to call this function
8596 after a release or cancel event since no future events will be received
8597 in any case. No move or release events will be delivered after this
8598 function was called.
8599*/
8600void QQuickItem::ungrabMouse()
8601{
8602 Q_D(QQuickItem);
8603 if (!d->window)
8604 return;
8605 auto da = d->deliveryAgentPrivate();
8606 Q_ASSERT(da);
8607 auto eventInDelivery = da->eventInDelivery();
8608 if (!eventInDelivery) {
8609 // do it the expensive way
8610 da->removeGrabber(this);
8611 return;
8612 }
8613 const auto &eventPoint = da->mousePointData()->eventPoint;
8614 if (eventInDelivery->exclusiveGrabber(eventPoint) == this)
8615 eventInDelivery->setExclusiveGrabber(eventPoint, nullptr);
8616}
8617
8618/*!
8619 Returns whether mouse input should exclusively remain with this item.
8620
8621 \sa setKeepMouseGrab(), QEvent::accept(), QEvent::ignore()
8622 */
8623bool QQuickItem::keepMouseGrab() const
8624{
8625 Q_D(const QQuickItem);
8626 return d->keepMouse;
8627}
8628
8629/*!
8630 Sets whether the mouse input should remain exclusively with this item.
8631
8632 This is useful for items that wish to grab and keep mouse
8633 interaction following a predefined gesture. For example,
8634 an item that is interested in horizontal mouse movement
8635 may set keepMouseGrab to true once a threshold has been
8636 exceeded. Once keepMouseGrab has been set to true, filtering
8637 items will not react to mouse events.
8638
8639 If \a keep is false, a filtering item may steal the grab. For example,
8640 \l Flickable may attempt to steal a mouse grab if it detects that the
8641 user has begun to move the viewport.
8642
8643 \sa keepMouseGrab()
8644 */
8645void QQuickItem::setKeepMouseGrab(bool keep)
8646{
8647 Q_D(QQuickItem);
8648 d->keepMouse = keep;
8649}
8650
8651/*!
8652 \deprecated Use QPointerEvent::setExclusiveGrabber().
8653 Grabs the touch points specified by \a ids.
8654
8655 These touch points will be owned by the item until
8656 they are released. Alternatively, the grab can be stolen
8657 by a filtering item like Flickable. Use setKeepTouchGrab()
8658 to prevent the grab from being stolen.
8659*/
8660void QQuickItem::grabTouchPoints(const QList<int> &ids)
8661{
8662 Q_D(QQuickItem);
8663 auto event = d->deliveryAgentPrivate()->eventInDelivery();
8664 if (Q_UNLIKELY(!event)) {
8665 qWarning() << "cannot grab: no event is currently being delivered";
8666 return;
8667 }
8668 for (auto pt : event->points()) {
8669 if (ids.contains(pt.id()))
8670 event->setExclusiveGrabber(pt, this);
8671 }
8672}
8673
8674/*!
8675 \deprecated Use QEventPoint::setExclusiveGrabber() instead.
8676 Ungrabs the touch points owned by this item.
8677*/
8678void QQuickItem::ungrabTouchPoints()
8679{
8680 Q_D(QQuickItem);
8681 if (!d->window)
8682 return;
8683 if (QQuickDeliveryAgentPrivate *da = d->deliveryAgentPrivate())
8684 da->removeGrabber(this, false, true);
8685}
8686
8687/*!
8688 Returns whether the touch points grabbed by this item should exclusively
8689 remain with this item.
8690
8691 \sa setKeepTouchGrab(), keepMouseGrab(), QEvent::accept(), QEvent::ignore()
8692*/
8693bool QQuickItem::keepTouchGrab() const
8694{
8695 Q_D(const QQuickItem);
8696 return d->keepTouch;
8697}
8698
8699/*!
8700 Sets whether the touch points grabbed by this item should remain
8701 exclusively with this item.
8702
8703 This is useful for items that wish to grab and keep specific touch
8704 points following a predefined gesture. For example,
8705 an item that is interested in horizontal touch point movement
8706 may set setKeepTouchGrab to true once a threshold has been
8707 exceeded. Once setKeepTouchGrab has been set to true, filtering
8708 items will not react to the relevant touch points.
8709
8710 If \a keep is false, a filtering item may steal the grab. For example,
8711 \l Flickable may attempt to steal a touch point grab if it detects that the
8712 user has begun to move the viewport.
8713
8714 \sa keepTouchGrab(), setKeepMouseGrab()
8715 */
8716void QQuickItem::setKeepTouchGrab(bool keep)
8717{
8718 Q_D(QQuickItem);
8719 d->keepTouch = keep;
8720}
8721
8722/*!
8723 \qmlmethod bool QtQuick::Item::contains(point point)
8724
8725 Returns \c true if this item contains \a point, which is in local coordinates;
8726 returns \c false otherwise. This is the same check that is used for
8727 hit-testing a QEventPoint during event delivery, and is affected by
8728 \l containmentMask if it is set.
8729*/
8730/*!
8731 Returns \c true if this item contains \a point, which is in local coordinates;
8732 returns \c false otherwise.
8733
8734 This function can be overridden in order to handle point collisions in items
8735 with custom shapes. The default implementation checks whether the point is inside
8736 \l containmentMask() if it is set, or inside the bounding box otherwise.
8737
8738 \note This method is used for hit-testing each QEventPoint during event
8739 delivery, so the implementation should be kept as lightweight as possible.
8740*/
8741bool QQuickItem::contains(const QPointF &point) const
8742{
8743 Q_D(const QQuickItem);
8744 if (d->extra.isAllocated() && d->extra->mask) {
8745 if (auto quickMask = qobject_cast<QQuickItem *>(d->extra->mask))
8746 return quickMask->contains(point - quickMask->position());
8747
8748 bool res = false;
8749 QMetaMethod maskContains = d->extra->mask->metaObject()->method(d->extra->maskContainsIndex);
8750 maskContains.invoke(d->extra->mask,
8751 Qt::DirectConnection,
8752 Q_RETURN_ARG(bool, res),
8753 Q_ARG(QPointF, point));
8754 return res;
8755 }
8756
8757 qreal x = point.x();
8758 qreal y = point.y();
8759 return x >= 0 && y >= 0 && x < d->width && y < d->height;
8760}
8761
8762/*!
8763 \qmlproperty QObject* QtQuick::Item::containmentMask
8764 \since 5.11
8765 This property holds an optional mask for the Item to be used in the
8766 \l contains() method. Its main use is currently to determine
8767 whether a \l {QPointerEvent}{pointer event} has landed into the item or not.
8768
8769 By default the \c contains() method will return true for any point
8770 within the Item's bounding box. \c containmentMask allows for
8771 more fine-grained control. For example, if a custom C++
8772 QQuickItem subclass with a specialized contains() method
8773 is used as containmentMask:
8774
8775 \code
8776 Item { id: item; containmentMask: AnotherItem { id: anotherItem } }
8777 \endcode
8778
8779 \e{item}'s contains method would then return \c true only if
8780 \e{anotherItem}'s contains() implementation returns \c true.
8781
8782 A \l Shape can be used as a mask, to make an item react to
8783 \l {QPointerEvent}{pointer events} only within a non-rectangular region:
8784
8785 \table
8786 \row
8787 \li \image containmentMask-shape.gif
8788 \li \snippet qml/item/containmentMask-shape.qml 0
8789 \endtable
8790
8791 It is also possible to define the contains method in QML. For example,
8792 to create a circular item that only responds to events within its
8793 actual bounds:
8794
8795 \table
8796 \row
8797 \li \image containmentMask-circle.gif
8798 \li \snippet qml/item/containmentMask-circle-js.qml 0
8799 \endtable
8800
8801 \sa {Qt Quick Examples - Shapes}
8802*/
8803/*!
8804 \property QQuickItem::containmentMask
8805 \since 5.11
8806 This property holds an optional mask to be used in the contains() method,
8807 which is mainly used for hit-testing each \l QPointerEvent.
8808
8809 By default, \l contains() will return \c true for any point
8810 within the Item's bounding box. But any QQuickItem, or any QObject
8811 that implements a function of the form
8812 \code
8813 Q_INVOKABLE bool contains(const QPointF &point) const;
8814 \endcode
8815 can be used as a mask, to defer hit-testing to that object.
8816
8817 \note contains() is called frequently during event delivery.
8818 Deferring hit-testing to another object slows it down somewhat.
8819 containmentMask() can cause performance problems if that object's
8820 contains() method is not efficient. If you implement a custom
8821 QQuickItem subclass, you can alternatively override contains().
8822
8823 \sa contains()
8824*/
8825QObject *QQuickItem::containmentMask() const
8826{
8827 Q_D(const QQuickItem);
8828 if (!d->extra.isAllocated())
8829 return nullptr;
8830 return d->extra->mask.data();
8831}
8832
8833void QQuickItem::setContainmentMask(QObject *mask)
8834{
8835 Q_D(QQuickItem);
8836 const bool extraDataExists = d->extra.isAllocated();
8837 // an Item can't mask itself (to prevent infinite loop in contains())
8838 if (mask == static_cast<QObject *>(this))
8839 return;
8840 // mask is null, and we had no mask
8841 if (!extraDataExists && !mask)
8842 return;
8843 // mask is non-null and the same
8844 if (extraDataExists && d->extra->mask == mask)
8845 return;
8846
8847 QQuickItem *quickMask = d->extra.isAllocated() ? qobject_cast<QQuickItem *>(d->extra->mask)
8848 : nullptr;
8849 if (quickMask) {
8850 QQuickItemPrivate *maskPrivate = QQuickItemPrivate::get(quickMask);
8851 maskPrivate->registerAsContainmentMask(this, false); // removed from use as my mask
8852 }
8853
8854 if (!extraDataExists)
8855 d->extra.value(); // ensure extra exists
8856 if (mask) {
8857 int methodIndex = mask->metaObject()->indexOfMethod(QByteArrayLiteral("contains(QPointF)"));
8858 if (methodIndex < 0) {
8859 qmlWarning(this) << QStringLiteral("QQuickItem: Object set as mask does not have an invokable contains method, ignoring it.");
8860 return;
8861 }
8862 d->extra->maskContainsIndex = methodIndex;
8863 }
8864 d->extra->mask = mask;
8865 quickMask = qobject_cast<QQuickItem *>(mask);
8866 if (quickMask) {
8867 QQuickItemPrivate *maskPrivate = QQuickItemPrivate::get(quickMask);
8868 maskPrivate->registerAsContainmentMask(this, true); // telling maskPrivate that "this" is using it as mask
8869 }
8870 emit containmentMaskChanged();
8871}
8872
8873/*!
8874 Maps the given \a point in this item's coordinate system to the equivalent
8875 point within \a item's coordinate system, and returns the mapped
8876 coordinate.
8877
8878 \input item.qdocinc mapping
8879
8880 If \a item is \nullptr, this maps \a point to the coordinate system of the
8881 scene.
8882
8883 \sa {Concepts - Visual Coordinates in Qt Quick}
8884*/
8885QPointF QQuickItem::mapToItem(const QQuickItem *item, const QPointF &point) const
8886{
8887 QPointF p = mapToScene(point);
8888 if (item) {
8889 const auto *itemWindow = item->window();
8890 const auto *thisWindow = window();
8891 if (thisWindow && itemWindow && itemWindow != thisWindow)
8892 p = itemWindow->mapFromGlobal(thisWindow->mapToGlobal(p));
8893
8894 p = item->mapFromScene(p);
8895 }
8896 return p;
8897}
8898
8899/*!
8900 Maps the given \a point in this item's coordinate system to the equivalent
8901 point within the scene's coordinate system, and returns the mapped
8902 coordinate.
8903
8904 \input item.qdocinc mapping
8905
8906 \sa {Concepts - Visual Coordinates in Qt Quick}
8907*/
8908QPointF QQuickItem::mapToScene(const QPointF &point) const
8909{
8910 Q_D(const QQuickItem);
8911 return d->itemToWindowTransform().map(point);
8912}
8913
8914/*!
8915 Maps the given \a point in this item's coordinate system to the equivalent
8916 point within global screen coordinate system, and returns the mapped
8917 coordinate.
8918
8919 \input item.qdocinc mapping
8920
8921 For example, this may be helpful to add a popup to a Qt Quick component.
8922
8923 \note Window positioning is done by the window manager and this value is
8924 treated only as a hint. So, the resulting window position may differ from
8925 what is expected.
8926
8927 \since 5.7
8928
8929 \sa {Concepts - Visual Coordinates in Qt Quick}
8930*/
8931QPointF QQuickItem::mapToGlobal(const QPointF &point) const
8932{
8933 Q_D(const QQuickItem);
8934
8935 if (Q_UNLIKELY(d->window == nullptr))
8936 return mapToScene(point);
8937
8938 QPoint renderOffset;
8939 QWindow *renderWindow = QQuickRenderControl::renderWindowFor(d->window, &renderOffset);
8940 QWindow *effectiveWindow = renderWindow ? renderWindow : d->window;
8941 return effectiveWindow->mapToGlobal((mapToScene(point) + renderOffset));
8942}
8943
8944/*!
8945 Maps the given \a rect in this item's coordinate system to the equivalent
8946 rectangular area within \a item's coordinate system, and returns the mapped
8947 rectangle value.
8948
8949 \input item.qdocinc mapping
8950
8951 If \a item is \nullptr, this maps \a rect to the coordinate system of the
8952 scene.
8953
8954 \sa {Concepts - Visual Coordinates in Qt Quick}
8955*/
8956QRectF QQuickItem::mapRectToItem(const QQuickItem *item, const QRectF &rect) const
8957{
8958 Q_D(const QQuickItem);
8959 QTransform t = d->itemToWindowTransform();
8960 if (item)
8961 t *= QQuickItemPrivate::get(item)->windowToItemTransform();
8962 return t.mapRect(rect);
8963}
8964
8965/*!
8966 Maps the given \a rect in this item's coordinate system to the equivalent
8967 rectangular area within the scene's coordinate system, and returns the mapped
8968 rectangle value.
8969
8970 \input item.qdocinc mapping
8971
8972 \sa {Concepts - Visual Coordinates in Qt Quick}
8973*/
8974QRectF QQuickItem::mapRectToScene(const QRectF &rect) const
8975{
8976 Q_D(const QQuickItem);
8977 return d->itemToWindowTransform().mapRect(rect);
8978}
8979
8980/*!
8981 Maps the given \a point in \a item's coordinate system to the equivalent
8982 point within this item's coordinate system, and returns the mapped
8983 coordinate.
8984
8985 \input item.qdocinc mapping
8986
8987 If \a item is \nullptr, this maps \a point from the coordinate system of the
8988 scene.
8989
8990 \sa {Concepts - Visual Coordinates in Qt Quick}
8991*/
8992QPointF QQuickItem::mapFromItem(const QQuickItem *item, const QPointF &point) const
8993{
8994 QPointF p = point;
8995 if (item) {
8996 p = item->mapToScene(point);
8997 const auto *itemWindow = item->window();
8998 const auto *thisWindow = window();
8999 if (thisWindow && itemWindow && itemWindow != thisWindow)
9000 p = thisWindow->mapFromGlobal(itemWindow->mapToGlobal(p));
9001 }
9002 return mapFromScene(p);
9003}
9004
9005/*!
9006 Maps the given \a point in the scene's coordinate system to the equivalent
9007 point within this item's coordinate system, and returns the mapped
9008 coordinate.
9009
9010 \input item.qdocinc mapping
9011
9012 \sa {Concepts - Visual Coordinates in Qt Quick}
9013*/
9014QPointF QQuickItem::mapFromScene(const QPointF &point) const
9015{
9016 Q_D(const QQuickItem);
9017 return d->windowToItemTransform().map(point);
9018}
9019
9020/*!
9021 Maps the given \a point in the global screen coordinate system to the
9022 equivalent point within this item's coordinate system, and returns the
9023 mapped coordinate.
9024
9025 \input item.qdocinc mapping
9026
9027 For example, this may be helpful to add a popup to a Qt Quick component.
9028
9029 \note Window positioning is done by the window manager and this value is
9030 treated only as a hint. So, the resulting window position may differ from
9031 what is expected.
9032
9033 \note If this item is in a subscene, e.g. mapped onto a 3D
9034 \l [QtQuick3D QML] {Model}{Model} object, the UV mapping is incorporated
9035 into this transformation, so that it really goes from screen coordinates to
9036 this item's coordinates, as long as \a point is actually within this item's bounds.
9037 The other mapping functions do not yet work that way.
9038
9039 \since 5.7
9040
9041 \sa {Concepts - Visual Coordinates in Qt Quick}
9042*/
9043QPointF QQuickItem::mapFromGlobal(const QPointF &point) const
9044{
9045 Q_D(const QQuickItem);
9046
9047 QPointF scenePoint;
9048 if (Q_LIKELY(d->window)) {
9049 QPoint renderOffset;
9050 QWindow *renderWindow = QQuickRenderControl::renderWindowFor(d->window, &renderOffset);
9051 QWindow *effectiveWindow = renderWindow ? renderWindow : d->window;
9052 scenePoint = effectiveWindow->mapFromGlobal(point) - renderOffset;
9053 } else {
9054 scenePoint = point;
9055 }
9056
9057 if (auto da = QQuickDeliveryAgentPrivate::currentOrItemDeliveryAgent(this)) {
9058 if (auto sceneTransform = da->sceneTransform())
9059 scenePoint = sceneTransform->map(scenePoint);
9060 }
9061 return mapFromScene(scenePoint);
9062}
9063
9064/*!
9065 Maps the given \a rect in \a item's coordinate system to the equivalent
9066 rectangular area within this item's coordinate system, and returns the mapped
9067 rectangle value.
9068
9069 \input item.qdocinc mapping
9070
9071 If \a item is \nullptr, this maps \a rect from the coordinate system of the
9072 scene.
9073
9074 \sa {Concepts - Visual Coordinates in Qt Quick}
9075*/
9076QRectF QQuickItem::mapRectFromItem(const QQuickItem *item, const QRectF &rect) const
9077{
9078 Q_D(const QQuickItem);
9079 QTransform t = item?QQuickItemPrivate::get(item)->itemToWindowTransform():QTransform();
9080 t *= d->windowToItemTransform();
9081 return t.mapRect(rect);
9082}
9083
9084/*!
9085 Maps the given \a rect in the scene's coordinate system to the equivalent
9086 rectangular area within this item's coordinate system, and returns the mapped
9087 rectangle value.
9088
9089 \input item.qdocinc mapping
9090
9091 \sa {Concepts - Visual Coordinates in Qt Quick}
9092*/
9093QRectF QQuickItem::mapRectFromScene(const QRectF &rect) const
9094{
9095 Q_D(const QQuickItem);
9096 return d->windowToItemTransform().mapRect(rect);
9097}
9098
9099/*!
9100 \property QQuickItem::anchors
9101 \internal
9102*/
9103
9104/*!
9105 \property QQuickItem::left
9106 \internal
9107*/
9108
9109/*!
9110 \property QQuickItem::right
9111 \internal
9112*/
9113
9114/*!
9115 \property QQuickItem::horizontalCenter
9116 \internal
9117*/
9118
9119/*!
9120 \property QQuickItem::top
9121 \internal
9122*/
9123
9124/*!
9125 \property QQuickItem::bottom
9126 \internal
9127*/
9128
9129/*!
9130 \property QQuickItem::verticalCenter
9131 \internal
9132*/
9133
9134/*!
9135 \property QQuickItem::baseline
9136 \internal
9137*/
9138
9139/*!
9140 \property QQuickItem::data
9141 \internal
9142*/
9143
9144/*!
9145 \property QQuickItem::resources
9146 \internal
9147*/
9148
9149/*!
9150 \reimp
9151 */
9152bool QQuickItem::event(QEvent *ev)
9153{
9154 Q_D(QQuickItem);
9155
9156 switch (ev->type()) {
9157#if QT_CONFIG(im)
9158 case QEvent::InputMethodQuery: {
9159 QInputMethodQueryEvent *query = static_cast<QInputMethodQueryEvent *>(ev);
9160 Qt::InputMethodQueries queries = query->queries();
9161 for (uint i = 0; i < 32; ++i) {
9162 Qt::InputMethodQuery q = (Qt::InputMethodQuery)(int)(queries & (1<<i));
9163 if (q) {
9164 QVariant v = inputMethodQuery(q);
9165 query->setValue(q, v);
9166 }
9167 }
9168 query->accept();
9169 break;
9170 }
9171 case QEvent::InputMethod:
9172 inputMethodEvent(static_cast<QInputMethodEvent *>(ev));
9173 break;
9174#endif // im
9175 case QEvent::TouchBegin:
9176 case QEvent::TouchUpdate:
9177 case QEvent::TouchEnd:
9178 case QEvent::TouchCancel:
9179 case QEvent::MouseButtonPress:
9180 case QEvent::MouseButtonRelease:
9181 case QEvent::MouseButtonDblClick:
9182#if QT_CONFIG(wheelevent)
9183 case QEvent::Wheel:
9184#endif
9185 d->deliverPointerEvent(ev);
9186 break;
9187 case QEvent::StyleAnimationUpdate:
9188 if (isVisible()) {
9189 ev->accept();
9190 update();
9191 }
9192 break;
9193 case QEvent::HoverEnter:
9194 hoverEnterEvent(static_cast<QHoverEvent*>(ev));
9195 break;
9196 case QEvent::HoverLeave:
9197 hoverLeaveEvent(static_cast<QHoverEvent*>(ev));
9198 break;
9199 case QEvent::HoverMove:
9200 hoverMoveEvent(static_cast<QHoverEvent*>(ev));
9201 break;
9202 case QEvent::KeyPress:
9203 case QEvent::KeyRelease:
9204 d->deliverKeyEvent(static_cast<QKeyEvent*>(ev));
9205 break;
9206 case QEvent::ShortcutOverride:
9207 d->deliverShortcutOverrideEvent(static_cast<QKeyEvent*>(ev));
9208 break;
9209 case QEvent::FocusIn:
9210 focusInEvent(static_cast<QFocusEvent*>(ev));
9211 break;
9212 case QEvent::FocusOut:
9213 focusOutEvent(static_cast<QFocusEvent*>(ev));
9214 break;
9215 case QEvent::MouseMove:
9216 mouseMoveEvent(static_cast<QMouseEvent*>(ev));
9217 break;
9218#if QT_CONFIG(quick_draganddrop)
9219 case QEvent::DragEnter:
9220 dragEnterEvent(static_cast<QDragEnterEvent*>(ev));
9221 break;
9222 case QEvent::DragLeave:
9223 dragLeaveEvent(static_cast<QDragLeaveEvent*>(ev));
9224 break;
9225 case QEvent::DragMove:
9226 dragMoveEvent(static_cast<QDragMoveEvent*>(ev));
9227 break;
9228 case QEvent::Drop:
9229 dropEvent(static_cast<QDropEvent*>(ev));
9230 break;
9231#endif // quick_draganddrop
9232#if QT_CONFIG(gestures)
9233 case QEvent::NativeGesture:
9234 ev->ignore();
9235 break;
9236#endif // gestures
9237 case QEvent::LanguageChange:
9238 case QEvent::LocaleChange:
9239 for (QQuickItem *item : std::as_const(d->childItems))
9240 QCoreApplication::sendEvent(item, ev);
9241 break;
9242 case QEvent::WindowActivate:
9243 case QEvent::WindowDeactivate:
9244 if (d->providesPalette())
9245 d->setCurrentColorGroup();
9246 for (QQuickItem *item : std::as_const(d->childItems))
9247 QCoreApplication::sendEvent(item, ev);
9248 break;
9249 case QEvent::ApplicationPaletteChange:
9250 for (QQuickItem *item : std::as_const(d->childItems))
9251 QCoreApplication::sendEvent(item, ev);
9252 break;
9253 case QEvent::ContextMenu:
9254 // ### Qt 7: add virtual contextMenuEvent (and to QWindow?)
9255 d->handleContextMenuEvent(static_cast<QContextMenuEvent*>(ev));
9256 break;
9257 default:
9258 return QObject::event(ev);
9259 }
9260
9261 return true;
9262}
9263
9264#ifndef QT_NO_DEBUG_STREAM
9265QDebug operator<<(QDebug debug,
9266#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0)
9267 const
9268#endif
9269 QQuickItem *item)
9270{
9271 QDebugStateSaver saver(debug);
9272 debug.nospace();
9273 if (!item) {
9274 debug << "QQuickItem(nullptr)";
9275 return debug;
9276 }
9277
9278 const QRectF rect(item->position(), QSizeF(item->width(), item->height()));
9279
9280 debug << item->metaObject()->className() << '(' << static_cast<void *>(item);
9281
9282 // Deferred properties will cause recursion when calling nameForObject
9283 // before the component is completed, so guard against this situation.
9284 if (item->isComponentComplete() && !QQmlData::wasDeleted(item)) {
9285 if (QQmlContext *context = qmlContext(item)) {
9286 const auto objectId = context->nameForObject(item);
9287 if (!objectId.isEmpty())
9288 debug << ", id=" << objectId;
9289 }
9290 }
9291 if (!item->objectName().isEmpty())
9292 debug << ", name=" << item->objectName();
9293 debug << ", parent=" << static_cast<void *>(item->parentItem())
9294 << ", geometry=";
9295 QtDebugUtils::formatQRect(debug, rect);
9296 if (const qreal z = item->z())
9297 debug << ", z=" << z;
9298 if (item->flags().testFlag(QQuickItem::ItemIsViewport))
9299 debug << " \U0001f5bc"; // frame with picture
9300 if (item->flags().testFlag(QQuickItem::ItemObservesViewport))
9301 debug << " \u23ff"; // observer eye
9302 debug << ')';
9303 return debug;
9304}
9305#endif // QT_NO_DEBUG_STREAM
9306
9307/*!
9308 \fn bool QQuickItem::isTextureProvider() const
9309
9310 Returns true if this item is a texture provider. The default
9311 implementation returns false.
9312
9313 This function can be called from any thread.
9314 */
9315
9316bool QQuickItem::isTextureProvider() const
9317{
9318#if QT_CONFIG(quick_shadereffect)
9319 Q_D(const QQuickItem);
9320 return d->extra.isAllocated() && d->extra->layer && d->extra->layer->effectSource() ?
9321 d->extra->layer->effectSource()->isTextureProvider() : false;
9322#else
9323 return false;
9324#endif
9325}
9326
9327/*!
9328 \fn QSGTextureProvider *QQuickItem::textureProvider() const
9329
9330 Returns the texture provider for an item. The default implementation
9331 returns \nullptr.
9332
9333 This function may only be called on the rendering thread.
9334 */
9335
9336QSGTextureProvider *QQuickItem::textureProvider() const
9337{
9338#if QT_CONFIG(quick_shadereffect)
9339 Q_D(const QQuickItem);
9340 return d->extra.isAllocated() && d->extra->layer && d->extra->layer->effectSource() ?
9341 d->extra->layer->effectSource()->textureProvider() : nullptr;
9342#else
9343 return 0;
9344#endif
9345}
9346
9347/*!
9348 \since 6.0
9349 \qmlproperty Palette QtQuick::Item::palette
9350
9351 This property holds the palette currently set for the item.
9352
9353 This property describes the item's requested palette. The palette is used by the item's style
9354 when rendering all controls, and is available as a means to ensure that custom controls can
9355 maintain consistency with the native platform's native look and feel. It's common that
9356 different platforms, or different styles, define different palettes for an application.
9357
9358 The default palette depends on the system environment. ApplicationWindow maintains a
9359 system/theme palette which serves as a default for all controls. There may also be special
9360 palette defaults for certain types of controls. You can also set the default palette for
9361 controls by either:
9362
9363 \list
9364 \li passing a custom palette to QGuiApplication::setPalette(), before loading any QML; or
9365 \li specifying the colors in the \l {Qt Quick Controls 2 Configuration File}
9366 {qtquickcontrols2.conf file}.
9367 \endlist
9368
9369 Items propagate explicit palette properties from parents to children. If you change a specific
9370 property on a items's palette, that property propagates to all of the item's children,
9371 overriding any system defaults for that property.
9372
9373 \code
9374 Item {
9375 palette {
9376 buttonText: "maroon"
9377 button: "lavender"
9378 }
9379
9380 Button {
9381 text: "Click Me"
9382 }
9383 }
9384 \endcode
9385
9386 \sa Window::palette, Popup::palette, ColorGroup, Palette, SystemPalette
9387*/
9388
9389#if QT_CONFIG(quick_shadereffect)
9390/*!
9391 \property QQuickItem::layer
9392 \internal
9393 */
9394QQuickItemLayer *QQuickItemPrivate::layer() const
9395{
9396 if (!extra.isAllocated() || !extra->layer) {
9397 extra.value().layer = new QQuickItemLayer(const_cast<QQuickItem *>(q_func()));
9398 if (!componentComplete)
9399 extra->layer->classBegin();
9400 }
9401 return extra->layer;
9402}
9403#endif
9404
9405/*!
9406 \internal
9407 Create a modified copy of the given \a event intended for delivery to this
9408 item, containing pointers to only the QEventPoint instances that are
9409 relevant to this item, and transforming their positions to this item's
9410 coordinate system.
9411
9412 Returns an invalid event with type \l QEvent::None if all points are
9413 stationary; or there are no points inside the item; or none of the points
9414 were pressed inside, neither the item nor any of its handlers is grabbing
9415 any of them, and \a isFiltering is false.
9416
9417 When \a isFiltering is true, it is assumed that the item cares about all
9418 points which are inside its bounds, because most filtering items need to
9419 monitor eventpoint movements until a drag threshold is exceeded or the
9420 requirements for a gesture to be recognized are met in some other way.
9421*/
9422void QQuickItemPrivate::localizedTouchEvent(const QTouchEvent *event, bool isFiltering, QMutableTouchEvent *localized)
9423{
9424 Q_Q(QQuickItem);
9425 QList<QEventPoint> touchPoints;
9426 QEventPoint::States eventStates;
9427
9428 bool anyPressOrReleaseInside = false;
9429 bool anyGrabber = false;
9430 for (auto &p : event->points()) {
9431 if (p.isAccepted())
9432 continue;
9433
9434 // include points where item is the grabber, or if any of its handlers is the grabber while some parent is filtering
9435 auto pointGrabber = event->exclusiveGrabber(p);
9436 bool isGrabber = (pointGrabber == q);
9437 if (!isGrabber && pointGrabber && isFiltering) {
9438 auto handlerGrabber = qmlobject_cast<QQuickPointerHandler *>(pointGrabber);
9439 if (handlerGrabber && handlerGrabber->parentItem() == q)
9440 isGrabber = true;
9441 }
9442 if (isGrabber)
9443 anyGrabber = true;
9444
9445 // include points inside the bounds if no other item is the grabber or if the item is filtering
9446 const auto localPos = q->mapFromScene(p.scenePosition());
9447 bool isInside = q->contains(localPos);
9448 bool hasAnotherGrabber = pointGrabber && pointGrabber != q;
9449 // if there's no exclusive grabber, look for passive grabbers during filtering
9450 if (isFiltering && !pointGrabber) {
9451 const auto pg = event->passiveGrabbers(p);
9452 if (!pg.isEmpty()) {
9453 // It seems unlikely to have multiple passive grabbers of one eventpoint with different grandparents.
9454 // So hopefully if we start from one passive grabber and go up the parent chain from there,
9455 // we will find any filtering parent items that exist.
9456 auto handler = qmlobject_cast<QQuickPointerHandler *>(pg.constFirst());
9457 if (handler)
9458 pointGrabber = handler->parentItem();
9459 }
9460 }
9461
9462 // filtering: (childMouseEventFilter) include points that are grabbed by children of the target item
9463 bool grabberIsChild = false;
9464 auto parent = qobject_cast<QQuickItem*>(pointGrabber);
9465 while (isFiltering && parent) {
9466 if (parent == q) {
9467 grabberIsChild = true;
9468 break;
9469 }
9470 parent = parent->parentItem();
9471 }
9472
9473 bool filterRelevant = isFiltering && grabberIsChild;
9474 if (!(isGrabber || (isInside && (!hasAnotherGrabber || isFiltering)) || filterRelevant))
9475 continue;
9476 if ((p.state() == QEventPoint::State::Pressed || p.state() == QEventPoint::State::Released) && isInside)
9477 anyPressOrReleaseInside = true;
9478 QEventPoint pCopy(p);
9479 eventStates |= p.state();
9480 if (p.state() == QEventPoint::State::Released)
9481 QMutableEventPoint::detach(pCopy);
9482 QMutableEventPoint::setPosition(pCopy, localPos);
9483 touchPoints.append(std::move(pCopy));
9484 }
9485
9486 // Now touchPoints will have only points which are inside the item.
9487 // But if none of them were just pressed inside, and the item has no other reason to care, ignore them anyway.
9488 if (touchPoints.isEmpty() || (!anyPressOrReleaseInside && !anyGrabber && !isFiltering)) {
9489 *localized = QMutableTouchEvent(QEvent::None);
9490 return;
9491 }
9492
9493 // if all points have the same state, set the event type accordingly
9494 QEvent::Type eventType = event->type();
9495 switch (eventStates) {
9496 case QEventPoint::State::Pressed:
9497 eventType = QEvent::TouchBegin;
9498 break;
9499 case QEventPoint::State::Released:
9500 eventType = QEvent::TouchEnd;
9501 break;
9502 default:
9503 eventType = QEvent::TouchUpdate;
9504 break;
9505 }
9506
9507 QMutableTouchEvent ret(eventType, event->pointingDevice(), event->modifiers(), touchPoints);
9508 ret.setTarget(q);
9509 ret.setTimestamp(event->timestamp());
9510 ret.accept();
9511 *localized = ret;
9512}
9513
9514bool QQuickItemPrivate::hasPointerHandlers() const
9515{
9516 return extra.isAllocated() && !extra->pointerHandlers.isEmpty();
9517}
9518
9519bool QQuickItemPrivate::hasEnabledHoverHandlers() const
9520{
9521 if (!hasPointerHandlers())
9522 return false;
9523 for (QQuickPointerHandler *h : extra->pointerHandlers)
9524 if (auto *hh = qmlobject_cast<QQuickHoverHandler *>(h); hh && hh->enabled())
9525 return true;
9526 return false;
9527}
9528
9529void QQuickItemPrivate::addPointerHandler(QQuickPointerHandler *h)
9530{
9531 Q_ASSERT(h);
9532 Q_Q(QQuickItem);
9533 // Accept all buttons, and leave filtering to pointerEvent() and/or user JS,
9534 // because there can be multiple handlers...
9535 extra.value().acceptedMouseButtons = Qt::AllButtons;
9536 auto &handlers = extra.value().pointerHandlers;
9537 if (!handlers.contains(h))
9538 handlers.prepend(h);
9539 auto &res = extra.value().resourcesList;
9540 if (!res.contains(h)) {
9541 res.append(h);
9542 QObject::connect(h, &QObject::destroyed, q, [this](QObject *o) {
9543 _q_resourceObjectDeleted(o);
9544 });
9545 }
9546}
9547
9548void QQuickItemPrivate::removePointerHandler(QQuickPointerHandler *h)
9549{
9550 Q_ASSERT(h);
9551 Q_Q(QQuickItem);
9552 auto &handlers = extra.value().pointerHandlers;
9553 handlers.removeOne(h);
9554 auto &res = extra.value().resourcesList;
9555 res.removeOne(h);
9556 QObject::disconnect(h, &QObject::destroyed, q, nullptr);
9557 if (handlers.isEmpty())
9558 extra.value().acceptedMouseButtons = extra.value().acceptedMouseButtonsWithoutHandlers;
9559}
9560
9561/*! \internal
9562 Replaces any existing context menu with the given \a menu,
9563 and returns the one that was already set before, or \c nullptr.
9564*/
9565QObject *QQuickItemPrivate::setContextMenu(QObject *menu)
9566{
9567 QObject *ret = (extra.isAllocated() ? extra->contextMenu : nullptr);
9568 extra.value().contextMenu = menu;
9569 return ret;
9570}
9571
9572#if QT_CONFIG(quick_shadereffect)
9573QQuickItemLayer::QQuickItemLayer(QQuickItem *item)
9574 : m_item(item)
9575 , m_enabled(false)
9576 , m_mipmap(false)
9577 , m_smooth(false)
9578 , m_live(true)
9579 , m_componentComplete(true)
9580 , m_wrapMode(QQuickShaderEffectSource::ClampToEdge)
9581 , m_format(QQuickShaderEffectSource::RGBA8)
9582 , m_name("source")
9583 , m_effectComponent(nullptr)
9584 , m_effect(nullptr)
9585 , m_effectSource(nullptr)
9586 , m_textureMirroring(QQuickShaderEffectSource::MirrorVertically)
9587 , m_samples(0)
9588{
9589}
9590
9591QQuickItemLayer::~QQuickItemLayer()
9592{
9593 delete m_effectSource;
9594 delete m_effect;
9595}
9596
9597/*!
9598 \qmlproperty bool QtQuick::Item::layer.enabled
9599
9600 Holds whether the item is layered or not. Layering is disabled by default.
9601
9602 A layered item is rendered into an offscreen surface and cached until
9603 it is changed. Enabling layering for complex QML item hierarchies can
9604 sometimes be an optimization.
9605
9606 None of the other layer properties have any effect when the layer
9607 is disabled.
9608
9609 \sa {Item Layers}
9610 */
9611void QQuickItemLayer::setEnabled(bool e)
9612{
9613 if (e == m_enabled)
9614 return;
9615 m_enabled = e;
9616 if (m_componentComplete) {
9617 if (m_enabled)
9618 activate();
9619 else
9620 deactivate();
9621 }
9622
9623 emit enabledChanged(e);
9624}
9625
9626void QQuickItemLayer::classBegin()
9627{
9628 Q_ASSERT(!m_effectSource);
9629 Q_ASSERT(!m_effect);
9630 m_componentComplete = false;
9631}
9632
9633void QQuickItemLayer::componentComplete()
9634{
9635 Q_ASSERT(!m_componentComplete);
9636 m_componentComplete = true;
9637 if (m_enabled)
9638 activate();
9639}
9640
9641void QQuickItemLayer::activate()
9642{
9643 Q_ASSERT(!m_effectSource);
9644 m_effectSource = new QQuickShaderEffectSource();
9645 QQuickItemPrivate::get(m_effectSource)->setTransparentForPositioner(true);
9646
9647 QQuickItem *parentItem = m_item->parentItem();
9648 if (parentItem) {
9649 m_effectSource->setParentItem(parentItem);
9650 m_effectSource->stackAfter(m_item);
9651 }
9652
9653 m_effectSource->setSourceItem(m_item);
9654 m_effectSource->setHideSource(true);
9655 m_effectSource->setSmooth(m_smooth);
9656 m_effectSource->setLive(m_live);
9657 m_effectSource->setTextureSize(m_size);
9658 m_effectSource->setSourceRect(m_sourceRect);
9659 m_effectSource->setMipmap(m_mipmap);
9660 m_effectSource->setWrapMode(m_wrapMode);
9661 m_effectSource->setFormat(m_format);
9662 m_effectSource->setTextureMirroring(m_textureMirroring);
9663 m_effectSource->setSamples(m_samples);
9664
9665 if (m_effectComponent)
9666 activateEffect();
9667
9668 m_effectSource->setVisible(m_item->isVisible() && !m_effect);
9669
9670 updateZ();
9671 updateGeometry();
9672 updateOpacity();
9673 updateMatrix();
9674
9675 QQuickItemPrivate *id = QQuickItemPrivate::get(m_item);
9676 id->addItemChangeListener(this, QQuickItemPrivate::Geometry | QQuickItemPrivate::Opacity | QQuickItemPrivate::Parent | QQuickItemPrivate::Visibility | QQuickItemPrivate::SiblingOrder);
9677}
9678
9679void QQuickItemLayer::deactivate()
9680{
9681 Q_ASSERT(m_effectSource);
9682
9683 if (m_effectComponent)
9684 deactivateEffect();
9685
9686 delete m_effectSource;
9687 m_effectSource = nullptr;
9688
9689 QQuickItemPrivate *id = QQuickItemPrivate::get(m_item);
9690 id->removeItemChangeListener(this, QQuickItemPrivate::Geometry | QQuickItemPrivate::Opacity | QQuickItemPrivate::Parent | QQuickItemPrivate::Visibility | QQuickItemPrivate::SiblingOrder);
9691}
9692
9693void QQuickItemLayer::activateEffect()
9694{
9695 Q_ASSERT(m_effectSource);
9696 Q_ASSERT(m_effectComponent);
9697 Q_ASSERT(!m_effect);
9698
9699 QObject *created = m_effectComponent->beginCreate(m_effectComponent->creationContext());
9700 m_effect = qobject_cast<QQuickItem *>(created);
9701 if (!m_effect) {
9702 qWarning("Item: layer.effect is not a QML Item.");
9703 m_effectComponent->completeCreate();
9704 delete created;
9705 return;
9706 }
9707 QQuickItem *parentItem = m_item->parentItem();
9708 if (parentItem) {
9709 m_effect->setParentItem(parentItem);
9710 m_effect->stackAfter(m_effectSource);
9711 }
9712 m_effect->setVisible(m_item->isVisible());
9713 m_effect->setProperty(m_name, QVariant::fromValue<QObject *>(m_effectSource));
9714 QQuickItemPrivate::get(m_effect)->setTransparentForPositioner(true);
9715 m_effectComponent->completeCreate();
9716}
9717
9718void QQuickItemLayer::deactivateEffect()
9719{
9720 Q_ASSERT(m_effectSource);
9721 Q_ASSERT(m_effectComponent);
9722
9723 delete m_effect;
9724 m_effect = nullptr;
9725}
9726
9727
9728/*!
9729 \qmlproperty Component QtQuick::Item::layer.effect
9730
9731 Holds the effect that is applied to this layer.
9732
9733 The effect is typically a \l ShaderEffect component, although any \l Item component can be
9734 assigned. The effect should have a source texture property with a name matching \l layer.samplerName.
9735
9736 \sa layer.samplerName, {Item Layers}
9737 */
9738
9739void QQuickItemLayer::setEffect(QQmlComponent *component)
9740{
9741 if (component == m_effectComponent)
9742 return;
9743
9744 bool updateNeeded = false;
9745 if (m_effectSource && m_effectComponent) {
9746 deactivateEffect();
9747 updateNeeded = true;
9748 }
9749
9750 m_effectComponent = component;
9751
9752 if (m_effectSource && m_effectComponent) {
9753 activateEffect();
9754 updateNeeded = true;
9755 }
9756
9757 if (updateNeeded) {
9758 updateZ();
9759 updateGeometry();
9760 updateOpacity();
9761 updateMatrix();
9762 m_effectSource->setVisible(m_item->isVisible() && !m_effect);
9763 }
9764
9765 emit effectChanged(component);
9766}
9767
9768
9769/*!
9770 \qmlproperty bool QtQuick::Item::layer.mipmap
9771
9772 If this property is true, mipmaps are generated for the texture.
9773
9774 \note Some OpenGL ES 2 implementations do not support mipmapping of
9775 non-power-of-two textures.
9776
9777 \sa {Item Layers}
9778 */
9779
9780void QQuickItemLayer::setMipmap(bool mipmap)
9781{
9782 if (mipmap == m_mipmap)
9783 return;
9784 m_mipmap = mipmap;
9785
9786 if (m_effectSource)
9787 m_effectSource->setMipmap(m_mipmap);
9788
9789 emit mipmapChanged(mipmap);
9790}
9791
9792
9793/*!
9794 \qmlproperty enumeration QtQuick::Item::layer.format
9795
9796 This property defines the format of the backing texture.
9797 Modifying this property makes most sense when the \a layer.effect is also
9798 specified.
9799
9800 \value ShaderEffectSource.RGBA8
9801 \value ShaderEffectSource.RGBA16F
9802 \value ShaderEffectSource.RGBA32F
9803 \value ShaderEffectSource.Alpha Starting with Qt 6.0, this value is not in use and has the same effect as \c RGBA8 in practice.
9804 \value ShaderEffectSource.RGB Starting with Qt 6.0, this value is not in use and has the same effect as \c RGBA8 in practice.
9805 \value ShaderEffectSource.RGBA Starting with Qt 6.0, this value is not in use and has the same effect as \c RGBA8 in practice.
9806
9807 \sa {Item Layers}
9808 */
9809
9810void QQuickItemLayer::setFormat(QQuickShaderEffectSource::Format f)
9811{
9812 if (f == m_format)
9813 return;
9814 m_format = f;
9815
9816 if (m_effectSource)
9817 m_effectSource->setFormat(m_format);
9818
9819 emit formatChanged(m_format);
9820}
9821
9822
9823/*!
9824 \qmlproperty rect QtQuick::Item::layer.sourceRect
9825
9826 This property defines the rectangular area of the item that should be
9827 rendered into the texture. The source rectangle can be larger than
9828 the item itself. If the rectangle is null, which is the default,
9829 then the whole item is rendered to the texture.
9830
9831 \sa {Item Layers}
9832 */
9833
9834void QQuickItemLayer::setSourceRect(const QRectF &sourceRect)
9835{
9836 if (sourceRect == m_sourceRect)
9837 return;
9838 m_sourceRect = sourceRect;
9839
9840 if (m_effectSource)
9841 m_effectSource->setSourceRect(m_sourceRect);
9842
9843 emit sourceRectChanged(sourceRect);
9844}
9845
9846/*!
9847 \qmlproperty bool QtQuick::Item::layer.smooth
9848
9849 Holds whether the layer is smoothly transformed. When enabled, sampling the
9850 layer's texture is performed using \c linear interpolation, while
9851 non-smooth results in using the \c nearest filtering mode.
9852
9853 By default, this property is set to \c false.
9854
9855 \sa {Item Layers}
9856 */
9857
9858void QQuickItemLayer::setSmooth(bool s)
9859{
9860 if (m_smooth == s)
9861 return;
9862 m_smooth = s;
9863
9864 if (m_effectSource)
9865 m_effectSource->setSmooth(m_smooth);
9866
9867 emit smoothChanged(s);
9868}
9869
9870/*!
9871 \qmlproperty bool QtQuick::Item::layer.live
9872 \since 6.5
9873
9874 When this property is true the layer texture is updated whenever the
9875 item updates. Otherwise it will always be a frozen image.
9876
9877 By default, this property is set to \c true.
9878
9879 \sa {Item Layers}
9880 */
9881
9882void QQuickItemLayer::setLive(bool live)
9883{
9884 if (m_live == live)
9885 return;
9886 m_live = live;
9887
9888 if (m_effectSource)
9889 m_effectSource->setLive(m_live);
9890
9891 emit liveChanged(live);
9892}
9893
9894/*!
9895 \qmlproperty size QtQuick::Item::layer.textureSize
9896
9897 This property holds the requested pixel size of the layers texture. If it is empty,
9898 which is the default, the size of the item is used.
9899
9900 \note Some platforms have a limit on how small framebuffer objects can be,
9901 which means the actual texture size might be larger than the requested
9902 size.
9903
9904 \sa {Item Layers}
9905 */
9906
9907void QQuickItemLayer::setSize(const QSize &size)
9908{
9909 if (size == m_size)
9910 return;
9911 m_size = size;
9912
9913 if (m_effectSource)
9914 m_effectSource->setTextureSize(size);
9915
9916 emit sizeChanged(size);
9917}
9918
9919/*!
9920 \qmlproperty enumeration QtQuick::Item::layer.wrapMode
9921
9922 This property defines the wrap modes associated with the texture.
9923 Modifying this property makes most sense when the \a layer.effect is
9924 specified.
9925
9926 \value ShaderEffectSource.ClampToEdge GL_CLAMP_TO_EDGE both horizontally and vertically
9927 \value ShaderEffectSource.RepeatHorizontally GL_REPEAT horizontally, GL_CLAMP_TO_EDGE vertically
9928 \value ShaderEffectSource.RepeatVertically GL_CLAMP_TO_EDGE horizontally, GL_REPEAT vertically
9929 \value ShaderEffectSource.Repeat GL_REPEAT both horizontally and vertically
9930
9931 \note Some OpenGL ES 2 implementations do not support the GL_REPEAT
9932 wrap mode with non-power-of-two textures.
9933
9934 \sa {Item Layers}
9935 */
9936
9937void QQuickItemLayer::setWrapMode(QQuickShaderEffectSource::WrapMode mode)
9938{
9939 if (mode == m_wrapMode)
9940 return;
9941 m_wrapMode = mode;
9942
9943 if (m_effectSource)
9944 m_effectSource->setWrapMode(m_wrapMode);
9945
9946 emit wrapModeChanged(mode);
9947}
9948
9949/*!
9950 \qmlproperty enumeration QtQuick::Item::layer.textureMirroring
9951 \since 5.6
9952
9953 This property defines how the generated texture should be mirrored.
9954 The default value is \c{ShaderEffectSource.MirrorVertically}.
9955 Custom mirroring can be useful if the generated texture is directly accessed by custom shaders,
9956 such as those specified by ShaderEffect. If no effect is specified for the layered
9957 item, mirroring has no effect on the UI representation of the item.
9958
9959 \value ShaderEffectSource.NoMirroring No mirroring
9960 \value ShaderEffectSource.MirrorHorizontally The generated texture is flipped along X-axis.
9961 \value ShaderEffectSource.MirrorVertically The generated texture is flipped along Y-axis.
9962 */
9963
9964void QQuickItemLayer::setTextureMirroring(QQuickShaderEffectSource::TextureMirroring mirroring)
9965{
9966 if (mirroring == m_textureMirroring)
9967 return;
9968 m_textureMirroring = mirroring;
9969
9970 if (m_effectSource)
9971 m_effectSource->setTextureMirroring(m_textureMirroring);
9972
9973 emit textureMirroringChanged(mirroring);
9974}
9975
9976/*!
9977 \qmlproperty enumeration QtQuick::Item::layer.samples
9978 \since 5.10
9979
9980 This property allows requesting multisampled rendering in the layer.
9981
9982 By default multisampling is enabled whenever multisampling is
9983 enabled for the entire window, assuming the scenegraph renderer in
9984 use and the underlying graphics API supports this.
9985
9986 By setting the value to 2, 4, etc. multisampled rendering can be requested
9987 for a part of the scene without enabling multisampling for the entire
9988 scene. This way multisampling is applied only to a given subtree, which can
9989 lead to significant performance gains since multisampling is not applied to
9990 other parts of the scene.
9991
9992 \note Enabling multisampling can be potentially expensive regardless of the
9993 layer's size, as it incurs a hardware and driver dependent performance and
9994 memory cost.
9995
9996 \note This property is only functional when support for multisample
9997 renderbuffers and framebuffer blits is available. Otherwise the value is
9998 silently ignored.
9999 */
10000
10001void QQuickItemLayer::setSamples(int count)
10002{
10003 if (m_samples == count)
10004 return;
10005
10006 m_samples = count;
10007
10008 if (m_effectSource)
10009 m_effectSource->setSamples(m_samples);
10010
10011 emit samplesChanged(count);
10012}
10013
10014/*!
10015 \qmlproperty string QtQuick::Item::layer.samplerName
10016
10017 Holds the name of the effect's source texture property.
10018
10019 This value must match the name of the effect's source texture property
10020 so that the Item can pass the layer's offscreen surface to the effect correctly.
10021
10022 \sa layer.effect, ShaderEffect, {Item Layers}
10023 */
10024
10025void QQuickItemLayer::setName(const QByteArray &name) {
10026 if (m_name == name)
10027 return;
10028 if (m_effect) {
10029 m_effect->setProperty(m_name, QVariant());
10030 m_effect->setProperty(name, QVariant::fromValue<QObject *>(m_effectSource));
10031 }
10032 m_name = name;
10033 emit nameChanged(name);
10034}
10035
10036void QQuickItemLayer::itemOpacityChanged(QQuickItem *item)
10037{
10038 Q_UNUSED(item);
10039 updateOpacity();
10040}
10041
10042void QQuickItemLayer::itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &)
10043{
10044 updateGeometry();
10045}
10046
10047void QQuickItemLayer::itemParentChanged(QQuickItem *item, QQuickItem *parent)
10048{
10049 Q_UNUSED(item);
10050 Q_ASSERT(item == m_item);
10051 Q_ASSERT(parent != m_effectSource);
10052 Q_ASSERT(parent == nullptr || parent != m_effect);
10053
10054 m_effectSource->setParentItem(parent);
10055 if (parent)
10056 m_effectSource->stackAfter(m_item);
10057
10058 if (m_effect) {
10059 m_effect->setParentItem(parent);
10060 if (parent)
10061 m_effect->stackAfter(m_effectSource);
10062 }
10063}
10064
10065void QQuickItemLayer::itemSiblingOrderChanged(QQuickItem *)
10066{
10067 m_effectSource->stackAfter(m_item);
10068 if (m_effect)
10069 m_effect->stackAfter(m_effectSource);
10070}
10071
10072void QQuickItemLayer::itemVisibilityChanged(QQuickItem *)
10073{
10074 QQuickItem *l = m_effect ? (QQuickItem *) m_effect : (QQuickItem *) m_effectSource;
10075 if (!l)
10076 return;
10077 l->setVisible(m_item->isVisible());
10078}
10079
10080void QQuickItemLayer::updateZ()
10081{
10082 if (!m_componentComplete || !m_enabled)
10083 return;
10084 QQuickItem *l = m_effect ? (QQuickItem *) m_effect : (QQuickItem *) m_effectSource;
10085 if (!l)
10086 return;
10087 l->setZ(m_item->z());
10088}
10089
10090void QQuickItemLayer::updateOpacity()
10091{
10092 QQuickItem *l = m_effect ? (QQuickItem *) m_effect : (QQuickItem *) m_effectSource;
10093 if (!l)
10094 return;
10095 l->setOpacity(m_item->opacity());
10096}
10097
10098void QQuickItemLayer::updateGeometry()
10099{
10100 QQuickItem *l = m_effect ? (QQuickItem *) m_effect : (QQuickItem *) m_effectSource;
10101 if (!l)
10102 return;
10103 // Avoid calling QQuickImage::boundingRect() or other overrides
10104 // which may not be up-to-date at this time (QTBUG-104442, 104536)
10105 QRectF bounds = m_item->QQuickItem::boundingRect();
10106 l->setSize(bounds.size());
10107 l->setPosition(bounds.topLeft() + m_item->position());
10108}
10109
10110void QQuickItemLayer::updateMatrix()
10111{
10112 // Called directly from transformChanged(), so needs some extra
10113 // checks.
10114 if (!m_componentComplete || !m_enabled)
10115 return;
10116 QQuickItem *l = m_effect ? (QQuickItem *) m_effect : (QQuickItem *) m_effectSource;
10117 if (!l)
10118 return;
10119 QQuickItemPrivate *ld = QQuickItemPrivate::get(l);
10120 l->setScale(m_item->scale());
10121 l->setRotation(m_item->rotation());
10122 ld->transforms = QQuickItemPrivate::get(m_item)->transforms;
10123 if (ld->origin() != QQuickItemPrivate::get(m_item)->origin())
10124 ld->extra.value().origin = QQuickItemPrivate::get(m_item)->origin();
10125 ld->dirty(QQuickItemPrivate::Transform);
10126}
10127#endif // quick_shadereffect
10128
10129QQuickItemPrivate::ExtraData::ExtraData()
10130: z(0), scale(1), rotation(0), opacity(1),
10131 contents(nullptr), screenAttached(nullptr), layoutDirectionAttached(nullptr),
10132 enterKeyAttached(nullptr),
10133 keyHandler(nullptr), contextMenu(nullptr),
10134#if QT_CONFIG(quick_shadereffect)
10135 layer(nullptr),
10136#endif
10137 effectRefCount(0), hideRefCount(0),
10138 recursiveEffectRefCount(0),
10139 opacityNode(nullptr), clipNode(nullptr), rootNode(nullptr),
10140 origin(QQuickItem::Center),
10141 transparentForPositioner(false)
10142{
10143}
10144
10145
10146#if QT_CONFIG(accessibility)
10147QAccessible::Role QQuickItemPrivate::effectiveAccessibleRole() const
10148{
10149 Q_Q(const QQuickItem);
10150 auto *attached = qmlAttachedPropertiesObject<QQuickAccessibleAttached>(q, false);
10151 auto role = QAccessible::NoRole;
10152 if (auto *accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(attached))
10153 role = accessibleAttached->role();
10154 if (role == QAccessible::NoRole)
10155 role = accessibleRole();
10156 return role;
10157}
10158
10159QAccessible::Role QQuickItemPrivate::accessibleRole() const
10160{
10161 return QAccessible::NoRole;
10162}
10163#endif
10164
10165// helper code to let a visual parent mark its visual children for the garbage collector
10166
10167namespace QV4 {
10168namespace Heap {
10170 static void markObjects(QV4::Heap::Base *that, QV4::MarkStack *markStack);
10171};
10172}
10173}
10174
10176 V4_OBJECT2(QQuickItemWrapper, QV4::QObjectWrapper)
10177};
10178
10180
10181void QV4::Heap::QQuickItemWrapper::markObjects(QV4::Heap::Base *that, QV4::MarkStack *markStack)
10182{
10183 QObjectWrapper *This = static_cast<QObjectWrapper *>(that);
10184 if (QQuickItem *item = static_cast<QQuickItem*>(This->object())) {
10185 for (QQuickItem *child : std::as_const(QQuickItemPrivate::get(item)->childItems))
10186 QV4::QObjectWrapper::markWrapper(child, markStack);
10187 }
10188 QObjectWrapper::markObjects(that, markStack);
10189}
10190
10191quint64 QQuickItemPrivate::_q_createJSWrapper(QQmlV4ExecutionEnginePtr engine)
10192{
10193 return (engine->memoryManager->allocate<QQuickItemWrapper>(q_func()))->asReturnedValue();
10194}
10195
10196QDebug operator<<(QDebug debug, const QQuickItemPrivate::ChangeListener &listener)
10197{
10198 QDebugStateSaver stateSaver(debug);
10199 debug.nospace() << "ChangeListener listener=" << listener.listener << " types=" << listener.types;
10200 return debug;
10201}
10202
10203//! \internal
10204QPointF QQuickItem::mapFromItem(const QQuickItem *item, qreal x, qreal y)
10205{ return mapFromItem(item, QPointF(x, y) ); }
10206
10207//! \internal
10208QRectF QQuickItem::mapFromItem(const QQuickItem *item, const QRectF &rect) const
10209{ return mapRectFromItem(item, rect); }
10210
10211//! \internal
10212QRectF QQuickItem::mapFromItem(const QQuickItem *item, qreal x, qreal y, qreal width, qreal height) const
10213{ return mapFromItem(item, QRectF(x, y, width, height)); }
10214
10215//! \internal
10216QPointF QQuickItem::mapToItem(const QQuickItem *item, qreal x, qreal y)
10217{ return mapToItem(item, QPointF(x, y)); }
10218
10219//! \internal
10220QRectF QQuickItem::mapToItem(const QQuickItem *item, const QRectF &rect) const
10221{ return mapRectToItem(item, rect); }
10222
10223//! \internal
10224QRectF QQuickItem::mapToItem(const QQuickItem *item, qreal x, qreal y, qreal width, qreal height) const
10225{ return mapToItem(item, QRectF(x, y, width, height)); }
10226
10227//! \internal
10228QPointF QQuickItem::mapToGlobal(qreal x, qreal y) const
10229{ return mapToGlobal(QPointF(x, y)); }
10230
10231//! \internal
10232QPointF QQuickItem::mapFromGlobal(qreal x, qreal y) const
10233{ return mapFromGlobal(QPointF(x, y)); }
10234
10235//! \internal
10236QQuickItemChangeListener::~QQuickItemChangeListener() = default;
10237
10238QT_END_NAMESPACE
10239
10240#include <moc_qquickitem.cpp>
10241
10242#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