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

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