1/****************************************************************************
2**
3** Copyright (C) 2016 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.
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
78#if QT_CONFIG(cursor)
79# include <QtGui/qcursor.h>
80#endif
81
82#include <algorithm>
83#include <limits>
84
85// XXX todo Check that elements that create items handle memory correctly after visual ownership change
86
87QT_BEGIN_NAMESPACE
88
89Q_DECLARE_LOGGING_CATEGORY(DBG_MOUSE_TARGET)
90Q_DECLARE_LOGGING_CATEGORY(DBG_HOVER_TRACE)
91Q_DECLARE_LOGGING_CATEGORY(lcTransient)
92Q_LOGGING_CATEGORY(lcHandlerParent, "qt.quick.handler.parent")
93
94void debugFocusTree(QQuickItem *item, QQuickItem *scope = nullptr, int depth = 1)
95{
96 if (DBG_FOCUS().isEnabled(QtDebugMsg)) {
97 qCDebug(DBG_FOCUS)
98 << QByteArray(depth, '\t').constData()
99 << (scope && QQuickItemPrivate::get(scope)->subFocusItem == item ? '*' : ' ')
100 << item->hasFocus()
101 << item->hasActiveFocus()
102 << item->isFocusScope()
103 << item;
104 const auto childItems = item->childItems();
105 for (QQuickItem *child : childItems) {
106 debugFocusTree(
107 child,
108 item->isFocusScope() || !scope ? item : scope,
109 item->isFocusScope() || !scope ? depth + 1 : depth);
110 }
111 }
112}
113
114/*!
115 \qmltype Transform
116 \instantiates QQuickTransform
117 \inqmlmodule QtQuick
118 \ingroup qtquick-visual-transforms
119 \brief For specifying advanced transformations on Items.
120
121 The Transform type is a base type which cannot be instantiated directly.
122 The following concrete Transform types are available:
123
124 \list
125 \li \l Rotation
126 \li \l Scale
127 \li \l Translate
128 \li \l Matrix4x4
129 \endlist
130
131 The Transform types let you create and control advanced transformations that can be configured
132 independently using specialized properties.
133
134 You can assign any number of Transforms to an \l Item. Each Transform is applied in order,
135 one at a time.
136*/
137QQuickTransformPrivate::QQuickTransformPrivate()
138{
139}
140
141QQuickTransform::QQuickTransform(QObject *parent)
142: QObject(*(new QQuickTransformPrivate), parent)
143{
144}
145
146QQuickTransform::QQuickTransform(QQuickTransformPrivate &dd, QObject *parent)
147: QObject(dd, parent)
148{
149}
150
151QQuickTransform::~QQuickTransform()
152{
153 Q_D(QQuickTransform);
154 for (int ii = 0; ii < d->items.count(); ++ii) {
155 QQuickItemPrivate *p = QQuickItemPrivate::get(d->items.at(ii));
156 p->transforms.removeOne(this);
157 p->dirty(QQuickItemPrivate::Transform);
158 }
159}
160
161void QQuickTransform::update()
162{
163 Q_D(QQuickTransform);
164 for (int ii = 0; ii < d->items.count(); ++ii) {
165 QQuickItemPrivate *p = QQuickItemPrivate::get(d->items.at(ii));
166 p->dirty(QQuickItemPrivate::Transform);
167 }
168}
169
170QQuickContents::QQuickContents(QQuickItem *item)
171: m_item(item)
172{
173}
174
175QQuickContents::~QQuickContents()
176{
177 QList<QQuickItem *> children = m_item->childItems();
178 for (int i = 0; i < children.count(); ++i) {
179 QQuickItem *child = children.at(i);
180 QQuickItemPrivate::get(child)->removeItemChangeListener(this, QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed);
181 }
182}
183
184bool QQuickContents::calcHeight(QQuickItem *changed)
185{
186 qreal oldy = m_contents.y();
187 qreal oldheight = m_contents.height();
188
189 if (changed) {
190 qreal top = oldy;
191 qreal bottom = oldy + oldheight;
192 qreal y = changed->y();
193 if (y + changed->height() > bottom)
194 bottom = y + changed->height();
195 if (y < top)
196 top = y;
197 m_contents.setY(top);
198 m_contents.setHeight(bottom - top);
199 } else {
200 qreal top = std::numeric_limits<qreal>::max();
201 qreal bottom = -std::numeric_limits<qreal>::max();
202 QList<QQuickItem *> children = m_item->childItems();
203 for (int i = 0; i < children.count(); ++i) {
204 QQuickItem *child = children.at(i);
205 qreal y = child->y();
206 if (y + child->height() > bottom)
207 bottom = y + child->height();
208 if (y < top)
209 top = y;
210 }
211 if (!children.isEmpty())
212 m_contents.setY(top);
213 m_contents.setHeight(qMax(bottom - top, qreal(0.0)));
214 }
215
216 return (m_contents.height() != oldheight || m_contents.y() != oldy);
217}
218
219bool QQuickContents::calcWidth(QQuickItem *changed)
220{
221 qreal oldx = m_contents.x();
222 qreal oldwidth = m_contents.width();
223
224 if (changed) {
225 qreal left = oldx;
226 qreal right = oldx + oldwidth;
227 qreal x = changed->x();
228 if (x + changed->width() > right)
229 right = x + changed->width();
230 if (x < left)
231 left = x;
232 m_contents.setX(left);
233 m_contents.setWidth(right - left);
234 } else {
235 qreal left = std::numeric_limits<qreal>::max();
236 qreal right = -std::numeric_limits<qreal>::max();
237 QList<QQuickItem *> children = m_item->childItems();
238 for (int i = 0; i < children.count(); ++i) {
239 QQuickItem *child = children.at(i);
240 qreal x = child->x();
241 if (x + child->width() > right)
242 right = x + child->width();
243 if (x < left)
244 left = x;
245 }
246 if (!children.isEmpty())
247 m_contents.setX(left);
248 m_contents.setWidth(qMax(right - left, qreal(0.0)));
249 }
250
251 return (m_contents.width() != oldwidth || m_contents.x() != oldx);
252}
253
254void QQuickContents::complete()
255{
256 QQuickItemPrivate::get(m_item)->addItemChangeListener(this, QQuickItemPrivate::Children);
257
258 QList<QQuickItem *> children = m_item->childItems();
259 for (int i = 0; i < children.count(); ++i) {
260 QQuickItem *child = children.at(i);
261 QQuickItemPrivate::get(child)->addItemChangeListener(this, QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed);
262 //###what about changes to visibility?
263 }
264 calcGeometry();
265}
266
267void QQuickContents::updateRect()
268{
269 QQuickItemPrivate::get(m_item)->emitChildrenRectChanged(rectF());
270}
271
272void QQuickContents::itemGeometryChanged(QQuickItem *changed, QQuickGeometryChange change, const QRectF &)
273{
274 Q_UNUSED(changed)
275 bool wChanged = false;
276 bool hChanged = false;
277 //### we can only pass changed if the left edge has moved left, or the right edge has moved right
278 if (change.horizontalChange())
279 wChanged = calcWidth(/*changed*/);
280 if (change.verticalChange())
281 hChanged = calcHeight(/*changed*/);
282 if (wChanged || hChanged)
283 updateRect();
284}
285
286void QQuickContents::itemDestroyed(QQuickItem *item)
287{
288 if (item)
289 QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed);
290 calcGeometry();
291}
292
293void QQuickContents::itemChildRemoved(QQuickItem *, QQuickItem *item)
294{
295 if (item)
296 QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed);
297 calcGeometry();
298}
299
300void QQuickContents::itemChildAdded(QQuickItem *, QQuickItem *item)
301{
302 if (item)
303 QQuickItemPrivate::get(item)->addItemChangeListener(this, QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed);
304 calcGeometry(item);
305}
306
307QQuickItemKeyFilter::QQuickItemKeyFilter(QQuickItem *item)
308: m_processPost(false), m_next(nullptr)
309{
310 QQuickItemPrivate *p = item?QQuickItemPrivate::get(item):nullptr;
311 if (p) {
312 m_next = p->extra.value().keyHandler;
313 p->extra->keyHandler = this;
314 }
315}
316
317QQuickItemKeyFilter::~QQuickItemKeyFilter()
318{
319}
320
321void QQuickItemKeyFilter::keyPressed(QKeyEvent *event, bool post)
322{
323 if (m_next) m_next->keyPressed(event, post);
324}
325
326void QQuickItemKeyFilter::keyReleased(QKeyEvent *event, bool post)
327{
328 if (m_next) m_next->keyReleased(event, post);
329}
330
331#if QT_CONFIG(im)
332void QQuickItemKeyFilter::inputMethodEvent(QInputMethodEvent *event, bool post)
333{
334 if (m_next)
335 m_next->inputMethodEvent(event, post);
336 else
337 event->ignore();
338}
339
340QVariant QQuickItemKeyFilter::inputMethodQuery(Qt::InputMethodQuery query) const
341{
342 if (m_next) return m_next->inputMethodQuery(query);
343 return QVariant();
344}
345#endif // im
346
347void QQuickItemKeyFilter::shortcutOverride(QKeyEvent *event)
348{
349 if (m_next)
350 m_next->shortcutOverride(event);
351}
352
353void QQuickItemKeyFilter::componentComplete()
354{
355 if (m_next) m_next->componentComplete();
356}
357/*!
358 \qmltype KeyNavigation
359 \instantiates QQuickKeyNavigationAttached
360 \inqmlmodule QtQuick
361 \ingroup qtquick-input-handlers
362 \brief Supports key navigation by arrow keys.
363
364 Key-based user interfaces commonly allow the use of arrow keys to navigate between
365 focusable items. The KeyNavigation attached property enables this behavior by providing a
366 convenient way to specify the item that should gain focus when an arrow or tab key is pressed.
367
368 The following example provides key navigation for a 2x2 grid of items:
369
370 \snippet qml/keynavigation.qml 0
371
372 The top-left item initially receives focus by setting \l {Item::}{focus} to
373 \c true. When an arrow key is pressed, the focus will move to the
374 appropriate item, as defined by the value that has been set for
375 the KeyNavigation \l left, \l right, \l up or \l down properties.
376
377 Note that if a KeyNavigation attached property receives the key press and release
378 events for a requested arrow or tab key, the event is accepted and does not
379 propagate any further.
380
381 By default, KeyNavigation receives key events after the item to which it is attached.
382 If the item accepts the key event, the KeyNavigation attached property will not
383 receive an event for that key. Setting the \l priority property to
384 \c KeyNavigation.BeforeItem allows the event to be used for key navigation
385 before the item, rather than after.
386
387 If the item to which the focus is switching is not enabled or visible, an attempt will
388 be made to skip this item and focus on the next. This is possible if there are
389 a chain of items with the same KeyNavigation handler. If multiple items in a row are not enabled
390 or visible, they will also be skipped.
391
392 KeyNavigation will implicitly set the other direction to return focus to this item. So if you set
393 \l left to another item, \l right will be set on that item's KeyNavigation to set focus back to this
394 item. However, if that item's KeyNavigation has had right explicitly set then no change will occur.
395 This means that the example above could achieve the same behavior without specifying
396 KeyNavigation.right or KeyNavigation.down for any of the items.
397
398 \sa {Keys}{Keys attached property}
399*/
400
401/*!
402 \qmlproperty Item QtQuick::KeyNavigation::left
403
404 This property holds the item to assign focus to
405 when the left cursor key is pressed.
406*/
407
408/*!
409 \qmlproperty Item QtQuick::KeyNavigation::right
410
411 This property holds the item to assign focus to
412 when the right cursor key is pressed.
413*/
414
415/*!
416 \qmlproperty Item QtQuick::KeyNavigation::up
417
418 This property holds the item to assign focus to
419 when the up cursor key is pressed.
420*/
421
422/*!
423 \qmlproperty Item QtQuick::KeyNavigation::down
424
425 This property holds the item to assign focus to
426 when the down cursor key is pressed.
427*/
428
429/*!
430 \qmlproperty Item QtQuick::KeyNavigation::tab
431
432 This property holds the item to assign focus to
433 when the Tab key is pressed.
434*/
435
436/*!
437 \qmlproperty Item QtQuick::KeyNavigation::backtab
438
439 This property holds the item to assign focus to
440 when the Shift+Tab key combination (Backtab) is pressed.
441*/
442
443QQuickKeyNavigationAttached::QQuickKeyNavigationAttached(QObject *parent)
444: QObject(*(new QQuickKeyNavigationAttachedPrivate), parent),
445 QQuickItemKeyFilter(qmlobject_cast<QQuickItem*>(parent))
446{
447 m_processPost = true;
448}
449
450QQuickKeyNavigationAttached *
451QQuickKeyNavigationAttached::qmlAttachedProperties(QObject *obj)
452{
453 return new QQuickKeyNavigationAttached(obj);
454}
455
456QQuickItem *QQuickKeyNavigationAttached::left() const
457{
458 Q_D(const QQuickKeyNavigationAttached);
459 return d->left;
460}
461
462void QQuickKeyNavigationAttached::setLeft(QQuickItem *i)
463{
464 Q_D(QQuickKeyNavigationAttached);
465 if (d->leftSet && d->left == i)
466 return;
467 d->left = i;
468 d->leftSet = true;
469 QQuickKeyNavigationAttached* other =
470 qobject_cast<QQuickKeyNavigationAttached*>(qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(i));
471 if (other && !other->d_func()->rightSet){
472 other->d_func()->right = qobject_cast<QQuickItem*>(parent());
473 emit other->rightChanged();
474 }
475 emit leftChanged();
476}
477
478QQuickItem *QQuickKeyNavigationAttached::right() const
479{
480 Q_D(const QQuickKeyNavigationAttached);
481 return d->right;
482}
483
484void QQuickKeyNavigationAttached::setRight(QQuickItem *i)
485{
486 Q_D(QQuickKeyNavigationAttached);
487 if (d->rightSet && d->right == i)
488 return;
489 d->right = i;
490 d->rightSet = true;
491 QQuickKeyNavigationAttached* other =
492 qobject_cast<QQuickKeyNavigationAttached*>(qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(i));
493 if (other && !other->d_func()->leftSet){
494 other->d_func()->left = qobject_cast<QQuickItem*>(parent());
495 emit other->leftChanged();
496 }
497 emit rightChanged();
498}
499
500QQuickItem *QQuickKeyNavigationAttached::up() const
501{
502 Q_D(const QQuickKeyNavigationAttached);
503 return d->up;
504}
505
506void QQuickKeyNavigationAttached::setUp(QQuickItem *i)
507{
508 Q_D(QQuickKeyNavigationAttached);
509 if (d->upSet && d->up == i)
510 return;
511 d->up = i;
512 d->upSet = true;
513 QQuickKeyNavigationAttached* other =
514 qobject_cast<QQuickKeyNavigationAttached*>(qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(i));
515 if (other && !other->d_func()->downSet){
516 other->d_func()->down = qobject_cast<QQuickItem*>(parent());
517 emit other->downChanged();
518 }
519 emit upChanged();
520}
521
522QQuickItem *QQuickKeyNavigationAttached::down() const
523{
524 Q_D(const QQuickKeyNavigationAttached);
525 return d->down;
526}
527
528void QQuickKeyNavigationAttached::setDown(QQuickItem *i)
529{
530 Q_D(QQuickKeyNavigationAttached);
531 if (d->downSet && d->down == i)
532 return;
533 d->down = i;
534 d->downSet = true;
535 QQuickKeyNavigationAttached* other =
536 qobject_cast<QQuickKeyNavigationAttached*>(qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(i));
537 if (other && !other->d_func()->upSet) {
538 other->d_func()->up = qobject_cast<QQuickItem*>(parent());
539 emit other->upChanged();
540 }
541 emit downChanged();
542}
543
544QQuickItem *QQuickKeyNavigationAttached::tab() const
545{
546 Q_D(const QQuickKeyNavigationAttached);
547 return d->tab;
548}
549
550void QQuickKeyNavigationAttached::setTab(QQuickItem *i)
551{
552 Q_D(QQuickKeyNavigationAttached);
553 if (d->tabSet && d->tab == i)
554 return;
555 d->tab = i;
556 d->tabSet = true;
557 QQuickKeyNavigationAttached* other =
558 qobject_cast<QQuickKeyNavigationAttached*>(qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(i));
559 if (other && !other->d_func()->backtabSet) {
560 other->d_func()->backtab = qobject_cast<QQuickItem*>(parent());
561 emit other->backtabChanged();
562 }
563 emit tabChanged();
564}
565
566QQuickItem *QQuickKeyNavigationAttached::backtab() const
567{
568 Q_D(const QQuickKeyNavigationAttached);
569 return d->backtab;
570}
571
572void QQuickKeyNavigationAttached::setBacktab(QQuickItem *i)
573{
574 Q_D(QQuickKeyNavigationAttached);
575 if (d->backtabSet && d->backtab == i)
576 return;
577 d->backtab = i;
578 d->backtabSet = true;
579 QQuickKeyNavigationAttached* other =
580 qobject_cast<QQuickKeyNavigationAttached*>(qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(i));
581 if (other && !other->d_func()->tabSet) {
582 other->d_func()->tab = qobject_cast<QQuickItem*>(parent());
583 emit other->tabChanged();
584 }
585 emit backtabChanged();
586}
587
588/*!
589 \qmlproperty enumeration QtQuick::KeyNavigation::priority
590
591 This property determines whether the keys are processed before
592 or after the attached item's own key handling.
593
594 \list
595 \li KeyNavigation.BeforeItem - process the key events before normal
596 item key processing. If the event is used for key navigation, it will be accepted and will not
597 be passed on to the item.
598 \li KeyNavigation.AfterItem (default) - process the key events after normal item key
599 handling. If the item accepts the key event it will not be
600 handled by the KeyNavigation attached property handler.
601 \endlist
602*/
603QQuickKeyNavigationAttached::Priority QQuickKeyNavigationAttached::priority() const
604{
605 return m_processPost ? AfterItem : BeforeItem;
606}
607
608void QQuickKeyNavigationAttached::setPriority(Priority order)
609{
610 bool processPost = order == AfterItem;
611 if (processPost != m_processPost) {
612 m_processPost = processPost;
613 emit priorityChanged();
614 }
615}
616
617void QQuickKeyNavigationAttached::keyPressed(QKeyEvent *event, bool post)
618{
619 Q_D(QQuickKeyNavigationAttached);
620 event->ignore();
621
622 if (post != m_processPost) {
623 QQuickItemKeyFilter::keyPressed(event, post);
624 return;
625 }
626
627 bool mirror = false;
628 switch (event->key()) {
629 case Qt::Key_Left: {
630 if (QQuickItem *parentItem = qobject_cast<QQuickItem*>(parent()))
631 mirror = QQuickItemPrivate::get(parentItem)->effectiveLayoutMirror;
632 QQuickItem* leftItem = mirror ? d->right : d->left;
633 if (leftItem) {
634 setFocusNavigation(leftItem, mirror ? "right" : "left", mirror ? Qt::TabFocusReason : Qt::BacktabFocusReason);
635 event->accept();
636 }
637 break;
638 }
639 case Qt::Key_Right: {
640 if (QQuickItem *parentItem = qobject_cast<QQuickItem*>(parent()))
641 mirror = QQuickItemPrivate::get(parentItem)->effectiveLayoutMirror;
642 QQuickItem* rightItem = mirror ? d->left : d->right;
643 if (rightItem) {
644 setFocusNavigation(rightItem, mirror ? "left" : "right", mirror ? Qt::BacktabFocusReason : Qt::TabFocusReason);
645 event->accept();
646 }
647 break;
648 }
649 case Qt::Key_Up:
650 if (d->up) {
651 setFocusNavigation(d->up, "up", Qt::BacktabFocusReason);
652 event->accept();
653 }
654 break;
655 case Qt::Key_Down:
656 if (d->down) {
657 setFocusNavigation(d->down, "down", Qt::TabFocusReason);
658 event->accept();
659 }
660 break;
661 case Qt::Key_Tab:
662 if (d->tab) {
663 setFocusNavigation(d->tab, "tab", Qt::TabFocusReason);
664 event->accept();
665 }
666 break;
667 case Qt::Key_Backtab:
668 if (d->backtab) {
669 setFocusNavigation(d->backtab, "backtab", Qt::BacktabFocusReason);
670 event->accept();
671 }
672 break;
673 default:
674 break;
675 }
676
677 if (!event->isAccepted()) QQuickItemKeyFilter::keyPressed(event, post);
678}
679
680void QQuickKeyNavigationAttached::keyReleased(QKeyEvent *event, bool post)
681{
682 Q_D(QQuickKeyNavigationAttached);
683 event->ignore();
684
685 if (post != m_processPost) {
686 QQuickItemKeyFilter::keyReleased(event, post);
687 return;
688 }
689
690 bool mirror = false;
691 switch (event->key()) {
692 case Qt::Key_Left:
693 if (QQuickItem *parentItem = qobject_cast<QQuickItem*>(parent()))
694 mirror = QQuickItemPrivate::get(parentItem)->effectiveLayoutMirror;
695 if (mirror ? d->right : d->left)
696 event->accept();
697 break;
698 case Qt::Key_Right:
699 if (QQuickItem *parentItem = qobject_cast<QQuickItem*>(parent()))
700 mirror = QQuickItemPrivate::get(parentItem)->effectiveLayoutMirror;
701 if (mirror ? d->left : d->right)
702 event->accept();
703 break;
704 case Qt::Key_Up:
705 if (d->up) {
706 event->accept();
707 }
708 break;
709 case Qt::Key_Down:
710 if (d->down) {
711 event->accept();
712 }
713 break;
714 case Qt::Key_Tab:
715 if (d->tab) {
716 event->accept();
717 }
718 break;
719 case Qt::Key_Backtab:
720 if (d->backtab) {
721 event->accept();
722 }
723 break;
724 default:
725 break;
726 }
727
728 if (!event->isAccepted()) QQuickItemKeyFilter::keyReleased(event, post);
729}
730
731void QQuickKeyNavigationAttached::setFocusNavigation(QQuickItem *currentItem, const char *dir,
732 Qt::FocusReason reason)
733{
734 QQuickItem *initialItem = currentItem;
735 bool isNextItem = false;
736 QVector<QQuickItem *> visitedItems;
737 do {
738 isNextItem = false;
739 if (currentItem->isVisible() && currentItem->isEnabled()) {
740 currentItem->forceActiveFocus(reason);
741 } else {
742 QObject *attached =
743 qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(currentItem, false);
744 if (attached) {
745 QQuickItem *tempItem = qvariant_cast<QQuickItem*>(attached->property(dir));
746 if (tempItem) {
747 visitedItems.append(currentItem);
748 currentItem = tempItem;
749 isNextItem = true;
750 }
751 }
752 }
753 }
754 while (currentItem != initialItem && isNextItem && !visitedItems.contains(currentItem));
755}
756
757struct SigMap {
758 int key;
759 const char *sig;
760};
761
762const SigMap sigMap[] = {
763 { Qt::Key_Left, "leftPressed" },
764 { Qt::Key_Right, "rightPressed" },
765 { Qt::Key_Up, "upPressed" },
766 { Qt::Key_Down, "downPressed" },
767 { Qt::Key_Tab, "tabPressed" },
768 { Qt::Key_Backtab, "backtabPressed" },
769 { Qt::Key_Asterisk, "asteriskPressed" },
770 { Qt::Key_NumberSign, "numberSignPressed" },
771 { Qt::Key_Escape, "escapePressed" },
772 { Qt::Key_Return, "returnPressed" },
773 { Qt::Key_Enter, "enterPressed" },
774 { Qt::Key_Delete, "deletePressed" },
775 { Qt::Key_Space, "spacePressed" },
776 { Qt::Key_Back, "backPressed" },
777 { Qt::Key_Cancel, "cancelPressed" },
778 { Qt::Key_Select, "selectPressed" },
779 { Qt::Key_Yes, "yesPressed" },
780 { Qt::Key_No, "noPressed" },
781 { Qt::Key_Context1, "context1Pressed" },
782 { Qt::Key_Context2, "context2Pressed" },
783 { Qt::Key_Context3, "context3Pressed" },
784 { Qt::Key_Context4, "context4Pressed" },
785 { Qt::Key_Call, "callPressed" },
786 { Qt::Key_Hangup, "hangupPressed" },
787 { Qt::Key_Flip, "flipPressed" },
788 { Qt::Key_Menu, "menuPressed" },
789 { Qt::Key_VolumeUp, "volumeUpPressed" },
790 { Qt::Key_VolumeDown, "volumeDownPressed" },
791 { 0, nullptr }
792};
793
794QByteArray QQuickKeysAttached::keyToSignal(int key)
795{
796 QByteArray keySignal;
797 if (key >= Qt::Key_0 && key <= Qt::Key_9) {
798 keySignal = "digit0Pressed";
799 keySignal[5] = '0' + (key - Qt::Key_0);
800 } else {
801 int i = 0;
802 while (sigMap[i].key && sigMap[i].key != key)
803 ++i;
804 keySignal = sigMap[i].sig;
805 }
806 return keySignal;
807}
808
809bool QQuickKeysAttached::isConnected(const char *signalName) const
810{
811 Q_D(const QQuickKeysAttached);
812 int signal_index = d->signalIndex(signalName);
813 return d->isSignalConnected(signal_index);
814}
815
816/*!
817 \qmltype Keys
818 \instantiates QQuickKeysAttached
819 \inqmlmodule QtQuick
820 \ingroup qtquick-input-handlers
821 \brief Provides key handling to Items.
822
823 All visual primitives support key handling via the Keys
824 attached property. Keys can be handled via the onPressed
825 and onReleased signal properties.
826
827 The signal properties have a \l KeyEvent parameter, named
828 \e event which contains details of the event. If a key is
829 handled \e event.accepted should be set to true to prevent the
830 event from propagating up the item hierarchy.
831
832 \section1 Example Usage
833
834 The following example shows how the general onPressed handler can
835 be used to test for a certain key; in this case, the left cursor
836 key:
837
838 \snippet qml/keys/keys-pressed.qml key item
839
840 Some keys may alternatively be handled via specific signal properties,
841 for example \e onSelectPressed. These handlers automatically set
842 \e event.accepted to true.
843
844 \snippet qml/keys/keys-handler.qml key item
845
846 See \l{Qt::Key}{Qt.Key} for the list of keyboard codes.
847
848 \section1 Key Handling Priorities
849
850 The Keys attached property can be configured to handle key events
851 before or after the item it is attached to. This makes it possible
852 to intercept events in order to override an item's default behavior,
853 or act as a fallback for keys not handled by the item.
854
855 If \l priority is Keys.BeforeItem (default) the order of key event processing is:
856
857 \list 1
858 \li Items specified in \c forwardTo
859 \li specific key handlers, e.g. onReturnPressed
860 \li onPressed, onReleased handlers
861 \li Item specific key handling, e.g. TextInput key handling
862 \li parent item
863 \endlist
864
865 If priority is Keys.AfterItem the order of key event processing is:
866
867 \list 1
868 \li Item specific key handling, e.g. TextInput key handling
869 \li Items specified in \c forwardTo
870 \li specific key handlers, e.g. onReturnPressed
871 \li onPressed, onReleased handlers
872 \li parent item
873 \endlist
874
875 If the event is accepted during any of the above steps, key
876 propagation stops.
877
878 \sa KeyEvent, {KeyNavigation}{KeyNavigation attached property}
879*/
880
881/*!
882 \qmlproperty bool QtQuick::Keys::enabled
883
884 This flags enables key handling if true (default); otherwise
885 no key handlers will be called.
886*/
887
888/*!
889 \qmlproperty enumeration QtQuick::Keys::priority
890
891 This property determines whether the keys are processed before
892 or after the attached item's own key handling.
893
894 \list
895 \li Keys.BeforeItem (default) - process the key events before normal
896 item key processing. If the event is accepted it will not
897 be passed on to the item.
898 \li Keys.AfterItem - process the key events after normal item key
899 handling. If the item accepts the key event it will not be
900 handled by the Keys attached property handler.
901 \endlist
902
903 \sa {Key Handling Priorities}
904*/
905
906/*!
907 \qmlproperty list<Object> QtQuick::Keys::forwardTo
908
909 This property provides a way to forward key presses, key releases, and keyboard input
910 coming from input methods to other items. This can be useful when you want
911 one item to handle some keys (e.g. the up and down arrow keys), and another item to
912 handle other keys (e.g. the left and right arrow keys). Once an item that has been
913 forwarded keys accepts the event it is no longer forwarded to items later in the
914 list.
915
916 This example forwards key events to two lists:
917 \qml
918 Item {
919 ListView {
920 id: list1
921 // ...
922 }
923 ListView {
924 id: list2
925 // ...
926 }
927 Keys.forwardTo: [list1, list2]
928 focus: true
929 }
930 \endqml
931
932 To see the order in which events are received when using forwardTo, see
933 \l {Key Handling Priorities}.
934*/
935
936/*!
937 \qmlsignal QtQuick::Keys::pressed(KeyEvent event)
938
939 This signal is emitted when a key has been pressed. The \a event
940 parameter provides information about the event.
941
942 The corresponding handler is \c onPressed.
943*/
944
945/*!
946 \qmlsignal QtQuick::Keys::released(KeyEvent event)
947
948 This signal is emitted when a key has been released. The \a event
949 parameter provides information about the event.
950
951 The corresponding handler is \c onReleased.
952*/
953
954/*!
955 \qmlsignal QtQuick::Keys::shortcutOverride(KeyEvent event)
956 \since 5.9
957
958 This signal is emitted when a key has been pressed that could potentially
959 be used as a shortcut. The \a event parameter provides information about
960 the event.
961
962 Set \c event.accepted to \c true if you wish to prevent the pressed key
963 from being used as a shortcut by other types, such as \l Shortcut. For
964 example:
965
966 \code
967 Item {
968 id: escapeItem
969 focus: true
970
971 // Ensure that we get escape key press events first.
972 Keys.onShortcutOverride: event.accepted = (event.key === Qt.Key_Escape)
973
974 Keys.onEscapePressed: {
975 console.log("escapeItem is handling escape");
976 // event.accepted is set to true by default for the specific key handlers
977 }
978 }
979
980 Shortcut {
981 sequence: "Escape"
982 onActivated: console.log("Shortcut is handling escape")
983 }
984 \endcode
985
986 As with the other signals, \c shortcutOverride will only be emitted for an
987 item if that item has \l {Item::}{activeFocus}.
988
989 The corresponding handler is \c onShortcutOverride.
990
991 \sa Shortcut
992*/
993
994/*!
995 \qmlsignal QtQuick::Keys::digit0Pressed(KeyEvent event)
996
997 This signal is emitted when the digit '0' has been pressed. The \a event
998 parameter provides information about the event.
999
1000 The corresponding handler is \c onDigit0Pressed.
1001*/
1002
1003/*!
1004 \qmlsignal QtQuick::Keys::digit1Pressed(KeyEvent event)
1005
1006 This signal is emitted when the digit '1' has been pressed. The \a event
1007 parameter provides information about the event.
1008
1009 The corresponding handler is \c onDigit1Pressed.
1010*/
1011
1012/*!
1013 \qmlsignal QtQuick::Keys::digit2Pressed(KeyEvent event)
1014
1015 This signal is emitted when the digit '2' has been pressed. The \a event
1016 parameter provides information about the event.
1017
1018 The corresponding handler is \c onDigit2Pressed.
1019*/
1020
1021/*!
1022 \qmlsignal QtQuick::Keys::digit3Pressed(KeyEvent event)
1023
1024 This signal is emitted when the digit '3' has been pressed. The \a event
1025 parameter provides information about the event.
1026
1027 The corresponding handler is \c onDigit3Pressed.
1028*/
1029
1030/*!
1031 \qmlsignal QtQuick::Keys::digit4Pressed(KeyEvent event)
1032
1033 This signal is emitted when the digit '4' has been pressed. The \a event
1034 parameter provides information about the event.
1035
1036 The corresponding handler is \c onDigit4Pressed.
1037*/
1038
1039/*!
1040 \qmlsignal QtQuick::Keys::digit5Pressed(KeyEvent event)
1041
1042 This signal is emitted when the digit '5' has been pressed. The \a event
1043 parameter provides information about the event.
1044
1045 The corresponding handler is \c onDigit5Pressed.
1046*/
1047
1048/*!
1049 \qmlsignal QtQuick::Keys::digit6Pressed(KeyEvent event)
1050
1051 This signal is emitted when the digit '6' has been pressed. The \a event
1052 parameter provides information about the event.
1053
1054 The corresponding handler is \c onDigit6Pressed.
1055*/
1056
1057/*!
1058 \qmlsignal QtQuick::Keys::digit7Pressed(KeyEvent event)
1059
1060 This signal is emitted when the digit '7' has been pressed. The \a event
1061 parameter provides information about the event.
1062
1063 The corresponding handler is \c onDigit7Pressed.
1064*/
1065
1066/*!
1067 \qmlsignal QtQuick::Keys::digit8Pressed(KeyEvent event)
1068
1069 This signal is emitted when the digit '8' has been pressed. The \a event
1070 parameter provides information about the event.
1071
1072 The corresponding handler is \c onDigit8Pressed.
1073*/
1074
1075/*!
1076 \qmlsignal QtQuick::Keys::digit9Pressed(KeyEvent event)
1077
1078 This signal is emitted when the digit '9' has been pressed. The \a event
1079 parameter provides information about the event.
1080
1081 The corresponding handler is \c onDigit9Pressed.
1082*/
1083
1084/*!
1085 \qmlsignal QtQuick::Keys::leftPressed(KeyEvent event)
1086
1087 This signal is emitted when the Left arrow has been pressed. The \a event
1088 parameter provides information about the event.
1089
1090 The corresponding handler is \c onLeftPressed.
1091*/
1092
1093/*!
1094 \qmlsignal QtQuick::Keys::rightPressed(KeyEvent event)
1095
1096 This signal is emitted when the Right arrow has been pressed. The \a event
1097 parameter provides information about the event.
1098
1099 The corresponding handler is \c onRightPressed.
1100*/
1101
1102/*!
1103 \qmlsignal QtQuick::Keys::upPressed(KeyEvent event)
1104
1105 This signal is emitted when the Up arrow has been pressed. The \a event
1106 parameter provides information about the event.
1107
1108 The corresponding handler is \c onUpPressed.
1109*/
1110
1111/*!
1112 \qmlsignal QtQuick::Keys::downPressed(KeyEvent event)
1113
1114 This signal is emitted when the Down arrow has been pressed. The \a event
1115 parameter provides information about the event.
1116
1117 The corresponding handler is \c onDownPressed.
1118*/
1119
1120/*!
1121 \qmlsignal QtQuick::Keys::tabPressed(KeyEvent event)
1122
1123 This signal is emitted when the Tab key has been pressed. The \a event
1124 parameter provides information about the event.
1125
1126 The corresponding handler is \c onTabPressed.
1127*/
1128
1129/*!
1130 \qmlsignal QtQuick::Keys::backtabPressed(KeyEvent event)
1131
1132 This signal is emitted when the Shift+Tab key combination (Backtab) has
1133 been pressed. The \a event parameter provides information about the event.
1134
1135 The corresponding handler is \c onBacktabPressed.
1136*/
1137
1138/*!
1139 \qmlsignal QtQuick::Keys::asteriskPressed(KeyEvent event)
1140
1141 This signal is emitted when the Asterisk '*' has been pressed. The \a event
1142 parameter provides information about the event.
1143
1144 The corresponding handler is \c onAsteriskPressed.
1145*/
1146
1147/*!
1148 \qmlsignal QtQuick::Keys::escapePressed(KeyEvent event)
1149
1150 This signal is emitted when the Escape key has been pressed. The \a event
1151 parameter provides information about the event.
1152
1153 The corresponding handler is \c onEscapePressed.
1154*/
1155
1156/*!
1157 \qmlsignal QtQuick::Keys::returnPressed(KeyEvent event)
1158
1159 This signal is emitted when the Return key has been pressed. The \a event
1160 parameter provides information about the event.
1161
1162 The corresponding handler is \c onReturnPressed.
1163*/
1164
1165/*!
1166 \qmlsignal QtQuick::Keys::enterPressed(KeyEvent event)
1167
1168 This signal is emitted when the Enter key has been pressed. The \a event
1169 parameter provides information about the event.
1170
1171 The corresponding handler is \c onEnterPressed.
1172*/
1173
1174/*!
1175 \qmlsignal QtQuick::Keys::deletePressed(KeyEvent event)
1176
1177 This signal is emitted when the Delete key has been pressed. The \a event
1178 parameter provides information about the event.
1179
1180 The corresponding handler is \c onDeletePressed.
1181*/
1182
1183/*!
1184 \qmlsignal QtQuick::Keys::spacePressed(KeyEvent event)
1185
1186 This signal is emitted when the Space key has been pressed. The \a event
1187 parameter provides information about the event.
1188
1189 The corresponding handler is \c onSpacePressed.
1190*/
1191
1192/*!
1193 \qmlsignal QtQuick::Keys::backPressed(KeyEvent event)
1194
1195 This signal is emitted when the Back key has been pressed. The \a event
1196 parameter provides information about the event.
1197
1198 The corresponding handler is \c onBackPressed.
1199*/
1200
1201/*!
1202 \qmlsignal QtQuick::Keys::cancelPressed(KeyEvent event)
1203
1204 This signal is emitted when the Cancel key has been pressed. The \a event
1205 parameter provides information about the event.
1206
1207 The corresponding handler is \c onCancelPressed.
1208*/
1209
1210/*!
1211 \qmlsignal QtQuick::Keys::selectPressed(KeyEvent event)
1212
1213 This signal is emitted when the Select key has been pressed. The \a event
1214 parameter provides information about the event.
1215
1216 The corresponding handler is \c onSelectPressed.
1217*/
1218
1219/*!
1220 \qmlsignal QtQuick::Keys::yesPressed(KeyEvent event)
1221
1222 This signal is emitted when the Yes key has been pressed. The \a event
1223 parameter provides information about the event.
1224
1225 The corresponding handler is \c onYesPressed.
1226*/
1227
1228/*!
1229 \qmlsignal QtQuick::Keys::noPressed(KeyEvent event)
1230
1231 This signal is emitted when the No key has been pressed. The \a event
1232 parameter provides information about the event.
1233
1234 The corresponding handler is \c onNoPressed.
1235*/
1236
1237/*!
1238 \qmlsignal QtQuick::Keys::context1Pressed(KeyEvent event)
1239
1240 This signal is emitted when the Context1 key has been pressed. The \a event
1241 parameter provides information about the event.
1242
1243 The corresponding handler is \c onContext1Pressed.
1244*/
1245
1246/*!
1247 \qmlsignal QtQuick::Keys::context2Pressed(KeyEvent event)
1248
1249 This signal is emitted when the Context2 key has been pressed. The \a event
1250 parameter provides information about the event.
1251
1252 The corresponding handler is \c onContext2Pressed.
1253*/
1254
1255/*!
1256 \qmlsignal QtQuick::Keys::context3Pressed(KeyEvent event)
1257
1258 This signal is emitted when the Context3 key has been pressed. The \a event
1259 parameter provides information about the event.
1260
1261 The corresponding handler is \c onContext3Pressed.
1262*/
1263
1264/*!
1265 \qmlsignal QtQuick::Keys::context4Pressed(KeyEvent event)
1266
1267 This signal is emitted when the Context4 key has been pressed. The \a event
1268 parameter provides information about the event.
1269
1270 The corresponding handler is \c onContext4Pressed.
1271*/
1272
1273/*!
1274 \qmlsignal QtQuick::Keys::callPressed(KeyEvent event)
1275
1276 This signal is emitted when the Call key has been pressed. The \a event
1277 parameter provides information about the event.
1278
1279 The corresponding handler is \c onCallPressed.
1280*/
1281
1282/*!
1283 \qmlsignal QtQuick::Keys::hangupPressed(KeyEvent event)
1284
1285 This signal is emitted when the Hangup key has been pressed. The \a event
1286 parameter provides information about the event.
1287
1288 The corresponding handler is \c onHangupPressed.
1289*/
1290
1291/*!
1292 \qmlsignal QtQuick::Keys::flipPressed(KeyEvent event)
1293
1294 This signal is emitted when the Flip key has been pressed. The \a event
1295 parameter provides information about the event.
1296
1297 The corresponding handler is \c onFlipPressed.
1298*/
1299
1300/*!
1301 \qmlsignal QtQuick::Keys::menuPressed(KeyEvent event)
1302
1303 This signal is emitted when the Menu key has been pressed. The \a event
1304 parameter provides information about the event.
1305
1306 The corresponding handler is \c onMenuPressed.
1307*/
1308
1309/*!
1310 \qmlsignal QtQuick::Keys::volumeUpPressed(KeyEvent event)
1311
1312 This signal is emitted when the VolumeUp key has been pressed. The \a event
1313 parameter provides information about the event.
1314
1315 The corresponding handler is \c onVolumeUpPressed.
1316*/
1317
1318/*!
1319 \qmlsignal QtQuick::Keys::volumeDownPressed(KeyEvent event)
1320
1321 This signal is emitted when the VolumeDown key has been pressed. The \a event
1322 parameter provides information about the event.
1323
1324 The corresponding handler is \c onVolumeDownPressed.
1325*/
1326
1327QQuickKeysAttached::QQuickKeysAttached(QObject *parent)
1328: QObject(*(new QQuickKeysAttachedPrivate), parent),
1329 QQuickItemKeyFilter(qmlobject_cast<QQuickItem*>(parent))
1330{
1331 Q_D(QQuickKeysAttached);
1332 m_processPost = false;
1333 d->item = qmlobject_cast<QQuickItem*>(parent);
1334 if (d->item != parent)
1335 qWarning() << "Could not attach Keys property to: " << parent << " is not an Item";
1336}
1337
1338QQuickKeysAttached::~QQuickKeysAttached()
1339{
1340}
1341
1342QQuickKeysAttached::Priority QQuickKeysAttached::priority() const
1343{
1344 return m_processPost ? AfterItem : BeforeItem;
1345}
1346
1347void QQuickKeysAttached::setPriority(Priority order)
1348{
1349 bool processPost = order == AfterItem;
1350 if (processPost != m_processPost) {
1351 m_processPost = processPost;
1352 emit priorityChanged();
1353 }
1354}
1355
1356void QQuickKeysAttached::componentComplete()
1357{
1358#if QT_CONFIG(im)
1359 Q_D(QQuickKeysAttached);
1360 if (d->item) {
1361 for (int ii = 0; ii < d->targets.count(); ++ii) {
1362 QQuickItem *targetItem = d->targets.at(ii);
1363 if (targetItem && (targetItem->flags() & QQuickItem::ItemAcceptsInputMethod)) {
1364 d->item->setFlag(QQuickItem::ItemAcceptsInputMethod);
1365 break;
1366 }
1367 }
1368 }
1369#endif
1370}
1371
1372void QQuickKeysAttached::keyPressed(QKeyEvent *event, bool post)
1373{
1374 Q_D(QQuickKeysAttached);
1375 if (post != m_processPost || !d->enabled || d->inPress) {
1376 event->ignore();
1377 QQuickItemKeyFilter::keyPressed(event, post);
1378 return;
1379 }
1380
1381 // first process forwards
1382 if (d->item && d->item->window()) {
1383 d->inPress = true;
1384 for (int ii = 0; ii < d->targets.count(); ++ii) {
1385 QQuickItem *i = d->targets.at(ii);
1386 if (i && i->isVisible()) {
1387 event->accept();
1388 QCoreApplication::sendEvent(i, event);
1389 if (event->isAccepted()) {
1390 d->inPress = false;
1391 return;
1392 }
1393 }
1394 }
1395 d->inPress = false;
1396 }
1397
1398 QQuickKeyEvent &ke = d->theKeyEvent;
1399 ke.reset(*event);
1400 QByteArray keySignal = keyToSignal(event->key());
1401 if (!keySignal.isEmpty()) {
1402 keySignal += "(QQuickKeyEvent*)";
1403 if (isConnected(keySignal)) {
1404 // If we specifically handle a key then default to accepted
1405 ke.setAccepted(true);
1406 int idx = QQuickKeysAttached::staticMetaObject.indexOfSignal(keySignal);
1407 metaObject()->method(idx).invoke(this, Qt::DirectConnection, Q_ARG(QQuickKeyEvent*, &ke));
1408 }
1409 }
1410 if (!ke.isAccepted())
1411 emit pressed(&ke);
1412 event->setAccepted(ke.isAccepted());
1413
1414 if (!event->isAccepted()) QQuickItemKeyFilter::keyPressed(event, post);
1415}
1416
1417void QQuickKeysAttached::keyReleased(QKeyEvent *event, bool post)
1418{
1419 Q_D(QQuickKeysAttached);
1420 if (post != m_processPost || !d->enabled || d->inRelease) {
1421 event->ignore();
1422 QQuickItemKeyFilter::keyReleased(event, post);
1423 return;
1424 }
1425
1426 if (d->item && d->item->window()) {
1427 d->inRelease = true;
1428 for (int ii = 0; ii < d->targets.count(); ++ii) {
1429 QQuickItem *i = d->targets.at(ii);
1430 if (i && i->isVisible()) {
1431 event->accept();
1432 QCoreApplication::sendEvent(i, event);
1433 if (event->isAccepted()) {
1434 d->inRelease = false;
1435 return;
1436 }
1437 }
1438 }
1439 d->inRelease = false;
1440 }
1441
1442 QQuickKeyEvent &ke = d->theKeyEvent;
1443 ke.reset(*event);
1444 emit released(&ke);
1445 event->setAccepted(ke.isAccepted());
1446
1447 if (!event->isAccepted()) QQuickItemKeyFilter::keyReleased(event, post);
1448}
1449
1450#if QT_CONFIG(im)
1451void QQuickKeysAttached::inputMethodEvent(QInputMethodEvent *event, bool post)
1452{
1453 Q_D(QQuickKeysAttached);
1454 if (post == m_processPost && d->item && !d->inIM && d->item->window()) {
1455 d->inIM = true;
1456 for (int ii = 0; ii < d->targets.count(); ++ii) {
1457 QQuickItem *targetItem = d->targets.at(ii);
1458 if (targetItem && targetItem->isVisible() && (targetItem->flags() & QQuickItem::ItemAcceptsInputMethod)) {
1459 QCoreApplication::sendEvent(targetItem, event);
1460 if (event->isAccepted()) {
1461 d->imeItem = targetItem;
1462 d->inIM = false;
1463 return;
1464 }
1465 }
1466 }
1467 d->inIM = false;
1468 }
1469 QQuickItemKeyFilter::inputMethodEvent(event, post);
1470}
1471
1472QVariant QQuickKeysAttached::inputMethodQuery(Qt::InputMethodQuery query) const
1473{
1474 Q_D(const QQuickKeysAttached);
1475 if (d->item) {
1476 for (int ii = 0; ii < d->targets.count(); ++ii) {
1477 QQuickItem *i = d->targets.at(ii);
1478 if (i && i->isVisible() && (i->flags() & QQuickItem::ItemAcceptsInputMethod) && i == d->imeItem) {
1479 //### how robust is i == d->imeItem check?
1480 QVariant v = i->inputMethodQuery(query);
1481 if (v.userType() == QVariant::RectF)
1482 v = d->item->mapRectFromItem(i, v.toRectF()); //### cost?
1483 return v;
1484 }
1485 }
1486 }
1487 return QQuickItemKeyFilter::inputMethodQuery(query);
1488}
1489#endif // im
1490
1491void QQuickKeysAttached::shortcutOverride(QKeyEvent *event)
1492{
1493 Q_D(QQuickKeysAttached);
1494 QQuickKeyEvent &keyEvent = d->theKeyEvent;
1495 keyEvent.reset(*event);
1496 emit shortcutOverride(&keyEvent);
1497
1498 event->setAccepted(keyEvent.isAccepted());
1499}
1500
1501QQuickKeysAttached *QQuickKeysAttached::qmlAttachedProperties(QObject *obj)
1502{
1503 return new QQuickKeysAttached(obj);
1504}
1505
1506/*!
1507 \qmltype LayoutMirroring
1508 \instantiates QQuickLayoutMirroringAttached
1509 \inqmlmodule QtQuick
1510 \ingroup qtquick-positioners
1511 \ingroup qml-utility-elements
1512 \brief Property used to mirror layout behavior.
1513
1514 The LayoutMirroring attached property is used to horizontally mirror \l {anchor-layout}{Item anchors},
1515 \l{Item Positioners}{positioner} types (such as \l Row and \l Grid)
1516 and views (such as \l GridView and horizontal \l ListView). Mirroring is a visual change: left
1517 anchors become right anchors, and positioner types like \l Grid and \l Row reverse the
1518 horizontal layout of child items.
1519
1520 Mirroring is enabled for an item by setting the \l enabled property to true. By default, this
1521 only affects the item itself; setting the \l childrenInherit property to true propagates the mirroring
1522 behavior to all child items as well. If the \c LayoutMirroring attached property has not been defined
1523 for an item, mirroring is not enabled.
1524
1525 \note Since Qt 5.8, \c LayoutMirroring can be attached to a \l Window. In practice, it is the same as
1526 attaching \c LayoutMirroring to the window's \c contentItem.
1527
1528 The following example shows mirroring in action. The \l Row below is specified as being anchored
1529 to the left of its parent. However, since mirroring has been enabled, the anchor is horizontally
1530 reversed and it is now anchored to the right. Also, since items in a \l Row are positioned
1531 from left to right by default, they are now positioned from right to left instead, as demonstrated
1532 by the numbering and opacity of the items:
1533
1534 \snippet qml/layoutmirroring.qml 0
1535
1536 \image layoutmirroring.png
1537
1538 Layout mirroring is useful when it is necessary to support both left-to-right and right-to-left
1539 layout versions of an application to target different language areas. The \l childrenInherit
1540 property allows layout mirroring to be applied without manually setting layout configurations
1541 for every item in an application. Keep in mind, however, that mirroring does not affect any
1542 positioning that is defined by the \l Item \l {Item::}{x} coordinate value, so even with
1543 mirroring enabled, it will often be necessary to apply some layout fixes to support the
1544 desired layout direction. Also, it may be necessary to disable the mirroring of individual
1545 child items (by setting \l {enabled}{LayoutMirroring.enabled} to false for such items) if
1546 mirroring is not the desired behavior, or if the child item already implements mirroring in
1547 some custom way.
1548
1549 To set the layout direction based on the \l {Default Layout Direction}{default layout direction}
1550 of the application, use the following code:
1551
1552 \code
1553 LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft
1554 \endcode
1555
1556 See \l {Right-to-left User Interfaces} for further details on using \c LayoutMirroring and
1557 other related features to implement right-to-left support for an application.
1558*/
1559
1560/*!
1561 \qmlproperty bool QtQuick::LayoutMirroring::enabled
1562
1563 This property holds whether the item's layout is mirrored horizontally. Setting this to true
1564 horizontally reverses \l {anchor-layout}{anchor} settings such that left anchors become right,
1565 and right anchors become left. For \l{Item Positioners}{positioner} types
1566 (such as \l Row and \l Grid) and view types (such as \l {GridView}{GridView} and \l {ListView}{ListView})
1567 this also mirrors the horizontal layout direction of the item.
1568
1569 The default value is false.
1570*/
1571
1572/*!
1573 \qmlproperty bool QtQuick::LayoutMirroring::childrenInherit
1574
1575 This property holds whether the \l {enabled}{LayoutMirroring.enabled} value for this item
1576 is inherited by its children.
1577
1578 The default value is false.
1579*/
1580
1581
1582QQuickLayoutMirroringAttached::QQuickLayoutMirroringAttached(QObject *parent) : QObject(parent), itemPrivate(nullptr)
1583{
1584 if (QQuickItem *item = qobject_cast<QQuickItem *>(parent))
1585 itemPrivate = QQuickItemPrivate::get(item);
1586 else if (QQuickWindow *window = qobject_cast<QQuickWindow *>(parent))
1587 itemPrivate = QQuickItemPrivate::get(window->contentItem());
1588
1589 if (itemPrivate)
1590 itemPrivate->extra.value().layoutDirectionAttached = this;
1591 else
1592 qmlWarning(parent) << tr("LayoutDirection attached property only works with Items and Windows");
1593}
1594
1595QQuickLayoutMirroringAttached * QQuickLayoutMirroringAttached::qmlAttachedProperties(QObject *object)
1596{
1597 return new QQuickLayoutMirroringAttached(object);
1598}
1599
1600bool QQuickLayoutMirroringAttached::enabled() const
1601{
1602 return itemPrivate ? itemPrivate->effectiveLayoutMirror : false;
1603}
1604
1605void QQuickLayoutMirroringAttached::setEnabled(bool enabled)
1606{
1607 if (!itemPrivate)
1608 return;
1609
1610 itemPrivate->isMirrorImplicit = false;
1611 if (enabled != itemPrivate->effectiveLayoutMirror) {
1612 itemPrivate->setLayoutMirror(enabled);
1613 if (itemPrivate->inheritMirrorFromItem)
1614 itemPrivate->resolveLayoutMirror();
1615 }
1616}
1617
1618void QQuickLayoutMirroringAttached::resetEnabled()
1619{
1620 if (itemPrivate && !itemPrivate->isMirrorImplicit) {
1621 itemPrivate->isMirrorImplicit = true;
1622 itemPrivate->resolveLayoutMirror();
1623 }
1624}
1625
1626bool QQuickLayoutMirroringAttached::childrenInherit() const
1627{
1628 return itemPrivate ? itemPrivate->inheritMirrorFromItem : false;
1629}
1630
1631void QQuickLayoutMirroringAttached::setChildrenInherit(bool childrenInherit) {
1632 if (itemPrivate && childrenInherit != itemPrivate->inheritMirrorFromItem) {
1633 itemPrivate->inheritMirrorFromItem = childrenInherit;
1634 itemPrivate->resolveLayoutMirror();
1635 childrenInheritChanged();
1636 }
1637}
1638
1639void QQuickItemPrivate::resolveLayoutMirror()
1640{
1641 Q_Q(QQuickItem);
1642 if (QQuickItem *parentItem = q->parentItem()) {
1643 QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(parentItem);
1644 setImplicitLayoutMirror(parentPrivate->inheritedLayoutMirror, parentPrivate->inheritMirrorFromParent);
1645 } else {
1646 setImplicitLayoutMirror(isMirrorImplicit ? false : effectiveLayoutMirror, inheritMirrorFromItem);
1647 }
1648}
1649
1650void QQuickItemPrivate::setImplicitLayoutMirror(bool mirror, bool inherit)
1651{
1652 inherit = inherit || inheritMirrorFromItem;
1653 if (!isMirrorImplicit && inheritMirrorFromItem)
1654 mirror = effectiveLayoutMirror;
1655 if (mirror == inheritedLayoutMirror && inherit == inheritMirrorFromParent)
1656 return;
1657
1658 inheritMirrorFromParent = inherit;
1659 inheritedLayoutMirror = inheritMirrorFromParent ? mirror : false;
1660
1661 if (isMirrorImplicit)
1662 setLayoutMirror(inherit ? inheritedLayoutMirror : false);
1663 for (int i = 0; i < childItems.count(); ++i) {
1664 if (QQuickItem *child = qmlobject_cast<QQuickItem *>(childItems.at(i))) {
1665 QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(child);
1666 childPrivate->setImplicitLayoutMirror(inheritedLayoutMirror, inheritMirrorFromParent);
1667 }
1668 }
1669}
1670
1671void QQuickItemPrivate::setLayoutMirror(bool mirror)
1672{
1673 if (mirror != effectiveLayoutMirror) {
1674 effectiveLayoutMirror = mirror;
1675 if (_anchors) {
1676 QQuickAnchorsPrivate *anchor_d = QQuickAnchorsPrivate::get(_anchors);
1677 anchor_d->fillChanged();
1678 anchor_d->centerInChanged();
1679 anchor_d->updateHorizontalAnchors();
1680 }
1681 mirrorChange();
1682 if (extra.isAllocated() && extra->layoutDirectionAttached) {
1683 emit extra->layoutDirectionAttached->enabledChanged();
1684 }
1685 }
1686}
1687
1688/*!
1689 \qmltype EnterKey
1690 \instantiates QQuickEnterKeyAttached
1691 \inqmlmodule QtQuick
1692 \ingroup qtquick-input
1693 \since 5.6
1694 \brief Provides a property to manipulate the appearance of Enter key on
1695 an on-screen keyboard.
1696
1697 The EnterKey attached property is used to manipulate the appearance and
1698 behavior of the Enter key on an on-screen keyboard.
1699*/
1700
1701/*!
1702 \qmlattachedproperty enumeration QtQuick::EnterKey::type
1703
1704 Holds the type of the Enter key.
1705
1706 \note Not all of these values are supported on all platforms. For
1707 unsupported values the default key is used instead.
1708
1709 \value Qt.EnterKeyDefault The default Enter key. This can be either a
1710 button to accept the input and close the
1711 keyboard, or a \e Return button to enter a
1712 newline in case of a multi-line input field.
1713
1714 \value Qt.EnterKeyReturn Show a \e Return button that inserts a
1715 newline.
1716
1717 \value Qt.EnterKeyDone Show a \e {"Done"} button. Typically, the
1718 keyboard is expected to close when the button
1719 is pressed.
1720
1721 \value Qt.EnterKeyGo Show a \e {"Go"} button. Typically used in an
1722 address bar when entering a URL.
1723
1724 \value Qt.EnterKeySend Show a \e {"Send"} button.
1725
1726 \value Qt.EnterKeySearch Show a \e {"Search"} button.
1727
1728 \value Qt.EnterKeyNext Show a \e {"Next"} button. Typically used in a
1729 form to allow navigating to the next input
1730 field without the keyboard closing.
1731
1732 \value Qt.EnterKeyPrevious Show a \e {"Previous"} button.
1733*/
1734
1735QQuickEnterKeyAttached::QQuickEnterKeyAttached(QObject *parent)
1736 : QObject(parent), itemPrivate(nullptr), keyType(Qt::EnterKeyDefault)
1737{
1738 if (QQuickItem *item = qobject_cast<QQuickItem*>(parent)) {
1739 itemPrivate = QQuickItemPrivate::get(item);
1740 itemPrivate->extra.value().enterKeyAttached = this;
1741 } else
1742 qmlWarning(parent) << tr("EnterKey attached property only works with Items");
1743}
1744
1745QQuickEnterKeyAttached *QQuickEnterKeyAttached::qmlAttachedProperties(QObject *object)
1746{
1747 return new QQuickEnterKeyAttached(object);
1748}
1749
1750Qt::EnterKeyType QQuickEnterKeyAttached::type() const
1751{
1752 return keyType;
1753}
1754
1755void QQuickEnterKeyAttached::setType(Qt::EnterKeyType type)
1756{
1757 if (keyType != type) {
1758 keyType = type;
1759#if QT_CONFIG(im)
1760 if (itemPrivate && itemPrivate->activeFocus)
1761 QGuiApplication::inputMethod()->update(Qt::ImEnterKeyType);
1762#endif
1763 typeChanged();
1764 }
1765}
1766
1767void QQuickItemPrivate::setAccessible()
1768{
1769 isAccessible = true;
1770}
1771
1772/*!
1773Clears all sub focus items from \a scope.
1774If \a focus is true, sets the scope's subFocusItem
1775to be this item.
1776*/
1777void QQuickItemPrivate::updateSubFocusItem(QQuickItem *scope, bool focus)
1778{
1779 Q_Q(QQuickItem);
1780 Q_ASSERT(scope);
1781
1782 QQuickItemPrivate *scopePrivate = QQuickItemPrivate::get(scope);
1783
1784 QQuickItem *oldSubFocusItem = scopePrivate->subFocusItem;
1785 // Correct focus chain in scope
1786 if (oldSubFocusItem) {
1787 QQuickItem *sfi = scopePrivate->subFocusItem->parentItem();
1788 while (sfi && sfi != scope) {
1789 QQuickItemPrivate::get(sfi)->subFocusItem = nullptr;
1790 sfi = sfi->parentItem();
1791 }
1792 }
1793
1794 if (focus) {
1795 scopePrivate->subFocusItem = q;
1796 QQuickItem *sfi = scopePrivate->subFocusItem->parentItem();
1797 while (sfi && sfi != scope) {
1798 QQuickItemPrivate::get(sfi)->subFocusItem = q;
1799 sfi = sfi->parentItem();
1800 }
1801 } else {
1802 scopePrivate->subFocusItem = nullptr;
1803 }
1804}
1805
1806/*!
1807 \class QQuickItem
1808 \brief The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
1809 \inmodule QtQuick
1810
1811 All visual items in Qt Quick inherit from QQuickItem. Although a QQuickItem
1812 instance has no visual appearance, it defines all the attributes that are
1813 common across visual items, such as x and y position, width and height,
1814 \l {Positioning with Anchors}{anchoring} and key handling support.
1815
1816 You can subclass QQuickItem to provide your own custom visual item
1817 that inherits these features.
1818
1819 \section1 Custom Scene Graph Items
1820
1821 All visual QML items are rendered using the scene graph, the default
1822 implementation of which is a low-level, high-performance rendering stack,
1823 closely tied to OpenGL. It is possible for subclasses of QQuickItem to add
1824 their own custom content into the scene graph by setting the
1825 QQuickItem::ItemHasContents flag and reimplementing the
1826 QQuickItem::updatePaintNode() function.
1827
1828 \warning It is crucial that OpenGL operations and interaction with
1829 the scene graph happens exclusively on the rendering thread,
1830 primarily during the updatePaintNode() call. The best rule of
1831 thumb is to only use classes with the "QSG" prefix inside the
1832 QQuickItem::updatePaintNode() function.
1833
1834 \note All classes with QSG prefix should be used solely on the scene graph's
1835 rendering thread. See \l {Scene Graph and Rendering} for more information.
1836
1837 \section2 Graphics Resource Handling
1838
1839 The preferred way to handle cleanup of graphics resources used in
1840 the scene graph, is to rely on the automatic cleanup of nodes. A
1841 QSGNode returned from QQuickItem::updatePaintNode() is
1842 automatically deleted on the right thread at the right time. Trees
1843 of QSGNode instances are managed through the use of
1844 QSGNode::OwnedByParent, which is set by default. So, for the
1845 majority of custom scene graph items, no extra work will be
1846 required.
1847
1848 Implementations that store graphics resources outside the node
1849 tree, such as an item implementing QQuickItem::textureProvider(),
1850 will need to take care in cleaning it up correctly depending on
1851 how the item is used in QML. The situations to handle are:
1852
1853 \list
1854
1855 \li The scene graph is invalidated; This can happen, for instance,
1856 if the window is hidden using QQuickWindow::hide(). If the item
1857 class implements a \c slot named \c invalidateSceneGraph(), this
1858 slot will be called on the rendering thread while the GUI thread
1859 is blocked. This is equivalent to connecting to
1860 QQuickWindow::sceneGraphInvalidated(). The OpenGL context of this
1861 item's window will be bound when this slot is called. The only
1862 exception is if the native OpenGL has been destroyed outside Qt's
1863 control, for instance through \c EGL_CONTEXT_LOST.
1864
1865 \li The item is removed from the scene; If an item is taken out of
1866 the scene, for instance because it's parent was set to \c null or
1867 an item in another window, the QQuickItem::releaseResources() will
1868 be called on the GUI thread. QQuickWindow::scheduleRenderJob()
1869 should be used to schedule cleanup of rendering resources.
1870
1871 \li The item is deleted; When the destructor if an item runs, it
1872 should delete any graphics resources it has. If neither of the two
1873 conditions above were already met, the item will be part of a
1874 window and it is possible to use QQuickWindow::scheduleRenderJob()
1875 to have them cleaned up. If an implementation ignores the call to
1876 QQuickItem::releaseResources(), the item will in many cases no
1877 longer have access to a QQuickWindow and thus no means of
1878 scheduling cleanup.
1879
1880 \endlist
1881
1882 When scheduling cleanup of graphics resources using
1883 QQuickWindow::scheduleRenderJob(), one should use either
1884 QQuickWindow::BeforeSynchronizingStage or
1885 QQuickWindow::AfterSynchronizingStage. The \l {Scene Graph and
1886 Rendering}{synchronization stage} is where the scene graph is
1887 changed as a result of changes to the QML tree. If cleanup is
1888 scheduled at any other time, it may result in other parts of the
1889 scene graph referencing the newly deleted objects as these parts
1890 have not been updated.
1891
1892 \note Use of QObject::deleteLater() to clean up graphics resources
1893 is not recommended as this will run at an arbitrary time and it is
1894 unknown if there will be an OpenGL context bound when the deletion
1895 takes place.
1896
1897 \section1 Custom QPainter Items
1898
1899 The QQuickItem provides a subclass, QQuickPaintedItem, which
1900 allows the users to render content using QPainter.
1901
1902 \warning Using QQuickPaintedItem uses an indirect 2D surface to
1903 render its content, either using software rasterization or using
1904 an OpenGL framebuffer object (FBO), so the rendering is a two-step
1905 operation. First rasterize the surface, then draw the
1906 surface. Using scene graph API directly is always significantly
1907 faster.
1908
1909 \section1 Behavior Animations
1910
1911 If your Item uses the \l Behavior type to define animations for property
1912 changes, you should always use either QObject::setProperty(),
1913 QQmlProperty(), or QMetaProperty::write() when you need to modify those
1914 properties from C++. This ensures that the QML engine knows about the
1915 property change. Otherwise, the engine won't be able to carry out your
1916 requested animation.
1917 Note that these functions incur a slight performance penalty. For more
1918 details, see \l {Accessing Members of a QML Object Type from C++}.
1919
1920 \sa QQuickWindow, QQuickPaintedItem
1921*/
1922
1923/*!
1924 \qmltype Item
1925 \instantiates QQuickItem
1926 \inherits QtObject
1927 \inqmlmodule QtQuick
1928 \ingroup qtquick-visual
1929 \brief A basic visual QML type.
1930
1931 The Item type is the base type for all visual items in Qt Quick.
1932
1933 All visual items in Qt Quick inherit from Item. Although an Item
1934 object has no visual appearance, it defines all the attributes that are
1935 common across visual items, such as x and y position, width and height,
1936 \l {Positioning with Anchors}{anchoring} and key handling support.
1937
1938 The Item type can be useful for grouping several items under a single
1939 root visual item. For example:
1940
1941 \qml
1942 import QtQuick 2.0
1943
1944 Item {
1945 Image {
1946 source: "tile.png"
1947 }
1948 Image {
1949 x: 80
1950 width: 100
1951 height: 100
1952 source: "tile.png"
1953 }
1954 Image {
1955 x: 190
1956 width: 100
1957 height: 100
1958 fillMode: Image.Tile
1959 source: "tile.png"
1960 }
1961 }
1962 \endqml
1963
1964
1965 \section2 Key Handling
1966
1967 Key handling is available to all Item-based visual types via the \l Keys
1968 attached property. The \e Keys attached property provides basic signals
1969 such as \l {Keys::}{pressed} and \l {Keys::}{released}, as well as
1970 signals for specific keys, such as \l {Keys::}{spacePressed}. The
1971 example below assigns \l {Keyboard Focus in Qt Quick}{keyboard focus} to
1972 the item and handles the left key via the general \c onPressed handler
1973 and the return key via the \c onReturnPressed handler:
1974
1975 \qml
1976 import QtQuick 2.0
1977
1978 Item {
1979 focus: true
1980 Keys.onPressed: {
1981 if (event.key == Qt.Key_Left) {
1982 console.log("move left");
1983 event.accepted = true;
1984 }
1985 }
1986 Keys.onReturnPressed: console.log("Pressed return");
1987 }
1988 \endqml
1989
1990 See the \l Keys attached property for detailed documentation.
1991
1992 \section2 Layout Mirroring
1993
1994 Item layouts can be mirrored using the \l LayoutMirroring attached
1995 property. This causes \l{anchors.top}{anchors} to be horizontally
1996 reversed, and also causes items that lay out or position their children
1997 (such as ListView or \l Row) to horizontally reverse the direction of
1998 their layouts.
1999
2000 See LayoutMirroring for more details.
2001
2002 \section1 Item Layers
2003
2004 An Item will normally be rendered directly into the window it
2005 belongs to. However, by setting \l layer.enabled, it is possible
2006 to delegate the item and its entire subtree into an offscreen
2007 surface. Only the offscreen surface, a texture, will be then drawn
2008 into the window.
2009
2010 If it is desired to have a texture size different from that of the
2011 item, this is possible using \l layer.textureSize. To render only
2012 a section of the item into the texture, use \l
2013 layer.sourceRect. It is also possible to specify \l
2014 layer.sourceRect so it extends beyond the bounds of the item. In
2015 this case, the exterior will be padded with transparent pixels.
2016
2017 The item will use linear interpolation for scaling if
2018 \l layer.smooth is set to \c true and will use mipmap for
2019 downsampling if \l layer.mipmap is set to \c true. Mipmapping may
2020 improve visual quality of downscaled items. For mipmapping of
2021 single Image items, prefer Image::mipmap.
2022
2023 \section2 Layer Opacity vs Item Opacity
2024
2025 When applying \l opacity to an item hierarchy the opacity is
2026 applied to each item individually. This can lead to undesired
2027 visual results when the opacity is applied to a subtree. Consider
2028 the following example:
2029
2030 \table
2031 \row
2032 \li \inlineimage qml-blending-nonlayered.png
2033 \li \b {Non-layered Opacity} \snippet qml/layerblending.qml non-layered
2034 \endtable
2035
2036 A layer is rendered with the root item's opacity being 1, and then
2037 the root item's opacity is applied to the texture when it is
2038 drawn. This means that fading in a large item hierarchy from
2039 transparent to opaque, or vice versa, can be done without the
2040 overlap artifacts that the normal item by item alpha blending
2041 has. Here is the same example with layer enabled:
2042
2043 \table
2044 \row
2045 \li \image qml-blending-layered.png
2046 \li \b {Layered Opacity} \snippet qml/layerblending.qml layered
2047 \endtable
2048
2049 \section2 Combined with ShaderEffects
2050
2051 Setting \l layer.enabled to true will turn the item into a \l
2052 {QQuickItem::isTextureProvider}{texture provider}, making it
2053 possible to use the item directly as a texture, for instance
2054 in combination with the ShaderEffect type.
2055
2056 It is possible to apply an effect on a layer at runtime using
2057 layer.effect:
2058
2059 \snippet qml/layerwitheffect.qml 1
2060
2061 In this example, we implement the shader effect manually. The \l
2062 {Qt Graphical Effects} module contains a suite of ready-made
2063 effects for use with Qt Quick.
2064
2065 See ShaderEffect for more information about using effects.
2066
2067 \note \l layer.enabled is actually just a more convenient way of using
2068 ShaderEffectSource.
2069
2070
2071 \section2 Memory and Performance
2072
2073 When an item's layer is enabled, the scene graph will allocate memory
2074 in the GPU equal to \c {width x height x 4}. In memory constrained
2075 configurations, large layers should be used with care.
2076
2077 In the QPainter / QWidget world, it is some times favorable to
2078 cache complex content in a pixmap, image or texture. In Qt Quick,
2079 because of the techniques already applied by the \l {Qt Quick
2080 Scene Graph OpenGL Renderer} {scene graph renderer}, this will in most
2081 cases not be the case. Excessive draw calls are already reduced
2082 because of batching and a cache will in most cases end up blending
2083 more pixels than the original content. The overhead of rendering
2084 to an offscreen and the blending involved with drawing the
2085 resulting texture is therefore often more costly than simply
2086 letting the item and its children be drawn normally.
2087
2088 Also, an item using a layer can not be \l {Batching} {batched} during
2089 rendering. This means that a scene with many layered items may
2090 have performance problems.
2091
2092 Layering can be convenient and useful for visual effects, but
2093 should in most cases be enabled for the duration of the effect and
2094 disabled afterwards.
2095
2096*/
2097
2098/*!
2099 \enum QQuickItem::Flag
2100
2101 This enum type is used to specify various item properties.
2102
2103 \value ItemClipsChildrenToShape Indicates this item should visually clip
2104 its children so that they are rendered only within the boundaries of this
2105 item.
2106 \value ItemAcceptsInputMethod Indicates the item supports text input
2107 methods.
2108 \value ItemIsFocusScope Indicates the item is a focus scope. See
2109 \l {Keyboard Focus in Qt Quick} for more information.
2110 \value ItemHasContents Indicates the item has visual content and should be
2111 rendered by the scene graph.
2112 \value ItemAcceptsDrops Indicates the item accepts drag and drop events.
2113
2114 \sa setFlag(), setFlags(), flags()
2115*/
2116
2117/*!
2118 \enum QQuickItem::ItemChange
2119 \brief Used in conjunction with QQuickItem::itemChange() to notify
2120 the item about certain types of changes.
2121
2122 \value ItemChildAddedChange A child was added. ItemChangeData::item contains
2123 the added child.
2124
2125 \value ItemChildRemovedChange A child was removed. ItemChangeData::item
2126 contains the removed child.
2127
2128 \value ItemSceneChange The item was added to or removed from a scene. The
2129 QQuickWindow rendering the scene is specified in using ItemChangeData::window.
2130 The window parameter is null when the item is removed from a scene.
2131
2132 \value ItemVisibleHasChanged The item's visibility has changed.
2133 ItemChangeData::boolValue contains the new visibility.
2134
2135 \value ItemParentHasChanged The item's parent has changed.
2136 ItemChangeData::item contains the new parent.
2137
2138 \value ItemOpacityHasChanged The item's opacity has changed.
2139 ItemChangeData::realValue contains the new opacity.
2140
2141 \value ItemActiveFocusHasChanged The item's focus has changed.
2142 ItemChangeData::boolValue contains whether the item has focus or not.
2143
2144 \value ItemRotationHasChanged The item's rotation has changed.
2145 ItemChangeData::realValue contains the new rotation.
2146
2147 \value ItemDevicePixelRatioHasChanged The device pixel ratio of the screen
2148 the item is on has changed. ItemChangedData::realValue contains the new
2149 device pixel ratio.
2150
2151 \value ItemAntialiasingHasChanged The antialiasing has changed. The current
2152 (boolean) value can be found in QQuickItem::antialiasing.
2153
2154 \value ItemEnabledHasChanged The item's enabled state has changed.
2155 ItemChangeData::boolValue contains the new enabled state. (since Qt 5.10)
2156*/
2157
2158/*!
2159 \class QQuickItem::ItemChangeData
2160 \inmodule QtQuick
2161 \brief Adds supplimentary information to the QQuickItem::itemChange()
2162 function.
2163
2164 The meaning of each member of this class is defined by the change type.
2165
2166 \sa QQuickItem::ItemChange
2167*/
2168
2169/*!
2170 \fn QQuickItem::ItemChangeData::ItemChangeData(QQuickItem *)
2171 \internal
2172 */
2173
2174/*!
2175 \fn QQuickItem::ItemChangeData::ItemChangeData(QQuickWindow *)
2176 \internal
2177 */
2178
2179/*!
2180 \fn QQuickItem::ItemChangeData::ItemChangeData(qreal)
2181 \internal
2182 */
2183
2184/*!
2185 \fn QQuickItem::ItemChangeData::ItemChangeData(bool)
2186 \internal
2187 */
2188
2189/*!
2190 \variable QQuickItem::ItemChangeData::realValue
2191 Contains supplimentary information to the QQuickItem::itemChange() function.
2192 \sa QQuickItem::ItemChange
2193 */
2194
2195/*!
2196 \variable QQuickItem::ItemChangeData::boolValue
2197 Contains supplimentary information to the QQuickItem::itemChange() function.
2198 \sa QQuickItem::ItemChange
2199 */
2200
2201/*!
2202 \variable QQuickItem::ItemChangeData::item
2203 Contains supplimentary information to the QQuickItem::itemChange() function.
2204 \sa QQuickItem::ItemChange
2205 */
2206
2207/*!
2208 \variable QQuickItem::ItemChangeData::window
2209 Contains supplimentary information to the QQuickItem::itemChange() function.
2210 \sa QQuickItem::ItemChange
2211 */
2212
2213/*!
2214 \enum QQuickItem::TransformOrigin
2215
2216 Controls the point about which simple transforms like scale apply.
2217
2218 \value TopLeft The top-left corner of the item.
2219 \value Top The center point of the top of the item.
2220 \value TopRight The top-right corner of the item.
2221 \value Left The left most point of the vertical middle.
2222 \value Center The center of the item.
2223 \value Right The right most point of the vertical middle.
2224 \value BottomLeft The bottom-left corner of the item.
2225 \value Bottom The center point of the bottom of the item.
2226 \value BottomRight The bottom-right corner of the item.
2227
2228 \sa transformOrigin(), setTransformOrigin()
2229*/
2230
2231/*!
2232 \fn void QQuickItem::childrenRectChanged(const QRectF &)
2233 \internal
2234*/
2235
2236/*!
2237 \fn void QQuickItem::baselineOffsetChanged(qreal)
2238 \internal
2239*/
2240
2241/*!
2242 \fn void QQuickItem::stateChanged(const QString &state)
2243 \internal
2244*/
2245
2246/*!
2247 \fn void QQuickItem::parentChanged(QQuickItem *)
2248 \internal
2249*/
2250
2251/*!
2252 \fn void QQuickItem::smoothChanged(bool)
2253 \internal
2254*/
2255
2256/*!
2257 \fn void QQuickItem::antialiasingChanged(bool)
2258 \internal
2259*/
2260
2261/*!
2262 \fn void QQuickItem::clipChanged(bool)
2263 \internal
2264*/
2265
2266/*!
2267 \fn void QQuickItem::transformOriginChanged(TransformOrigin)
2268 \internal
2269*/
2270
2271/*!
2272 \fn void QQuickItem::focusChanged(bool)
2273 \internal
2274*/
2275
2276/*!
2277 \fn void QQuickItem::activeFocusChanged(bool)
2278 \internal
2279*/
2280
2281/*!
2282 \fn void QQuickItem::activeFocusOnTabChanged(bool)
2283 \internal
2284*/
2285
2286/*!
2287 \fn void QQuickItem::childrenChanged()
2288 \internal
2289*/
2290
2291/*!
2292 \fn void QQuickItem::opacityChanged()
2293 \internal
2294*/
2295
2296/*!
2297 \fn void QQuickItem::enabledChanged()
2298 \internal
2299*/
2300
2301/*!
2302 \fn void QQuickItem::visibleChanged()
2303 \internal
2304*/
2305
2306/*!
2307 \fn void QQuickItem::visibleChildrenChanged()
2308 \internal
2309*/
2310
2311/*!
2312 \fn void QQuickItem::rotationChanged()
2313 \internal
2314*/
2315
2316/*!
2317 \fn void QQuickItem::scaleChanged()
2318 \internal
2319*/
2320
2321/*!
2322 \fn void QQuickItem::xChanged()
2323 \internal
2324*/
2325
2326/*!
2327 \fn void QQuickItem::yChanged()
2328 \internal
2329*/
2330
2331/*!
2332 \fn void QQuickItem::widthChanged()
2333 \internal
2334*/
2335
2336/*!
2337 \fn void QQuickItem::heightChanged()
2338 \internal
2339*/
2340
2341/*!
2342 \fn void QQuickItem::zChanged()
2343 \internal
2344*/
2345
2346/*!
2347 \fn void QQuickItem::implicitWidthChanged()
2348 \internal
2349*/
2350
2351/*!
2352 \fn void QQuickItem::implicitHeightChanged()
2353 \internal
2354*/
2355
2356/*!
2357 \fn QQuickItem::QQuickItem(QQuickItem *parent)
2358
2359 Constructs a QQuickItem with the given \a parent.
2360
2361 The \c parent will be used as both the \l {setParentItem()}{visual parent}
2362 and the \l QObject parent.
2363*/
2364QQuickItem::QQuickItem(QQuickItem* parent)
2365: QObject(*(new QQuickItemPrivate), parent)
2366{
2367 Q_D(QQuickItem);
2368 d->init(parent);
2369}
2370
2371/*! \internal
2372*/
2373QQuickItem::QQuickItem(QQuickItemPrivate &dd, QQuickItem *parent)
2374: QObject(dd, parent)
2375{
2376 Q_D(QQuickItem);
2377 d->init(parent);
2378}
2379
2380/*!
2381 Destroys the QQuickItem.
2382*/
2383QQuickItem::~QQuickItem()
2384{
2385 Q_D(QQuickItem);
2386
2387 if (d->windowRefCount > 1)
2388 d->windowRefCount = 1; // Make sure window is set to null in next call to derefWindow().
2389 if (d->parentItem)
2390 setParentItem(nullptr);
2391 else if (d->window)
2392 d->derefWindow();
2393
2394 // XXX todo - optimize
2395 while (!d->childItems.isEmpty())
2396 d->childItems.constFirst()->setParentItem(nullptr);
2397
2398 if (!d->changeListeners.isEmpty()) {
2399 const auto listeners = d->changeListeners; // NOTE: intentional copy (QTBUG-54732)
2400 for (const QQuickItemPrivate::ChangeListener &change : listeners) {
2401 QQuickAnchorsPrivate *anchor = change.listener->anchorPrivate();
2402 if (anchor)
2403 anchor->clearItem(this);
2404 }
2405
2406 /*
2407 update item anchors that depended on us unless they are our child (and will also be destroyed),
2408 or our sibling, and our parent is also being destroyed.
2409 */
2410 for (const QQuickItemPrivate::ChangeListener &change : listeners) {
2411 QQuickAnchorsPrivate *anchor = change.listener->anchorPrivate();
2412 if (anchor && anchor->item && anchor->item->parentItem() && anchor->item->parentItem() != this)
2413 anchor->update();
2414 }
2415
2416 for (const QQuickItemPrivate::ChangeListener &change : listeners) {
2417 if (change.types & QQuickItemPrivate::Destroyed)
2418 change.listener->itemDestroyed(this);
2419 }
2420
2421 d->changeListeners.clear();
2422 }
2423
2424 /*
2425 Remove any references our transforms have to us, in case they try to
2426 remove themselves from our list of transforms when that list has already
2427 been destroyed after ~QQuickItem() has run.
2428 */
2429 for (int ii = 0; ii < d->transforms.count(); ++ii) {
2430 QQuickTransform *t = d->transforms.at(ii);
2431 QQuickTransformPrivate *tp = QQuickTransformPrivate::get(t);
2432 tp->items.removeOne(this);
2433 }
2434
2435 if (d->extra.isAllocated()) {
2436 delete d->extra->contents; d->extra->contents = nullptr;
2437#if QT_CONFIG(quick_shadereffect)
2438 delete d->extra->layer; d->extra->layer = nullptr;
2439#endif
2440 }
2441
2442 delete d->_anchors; d->_anchors = nullptr;
2443 delete d->_stateGroup; d->_stateGroup = nullptr;
2444}
2445
2446/*!
2447 \internal
2448*/
2449bool QQuickItemPrivate::canAcceptTabFocus(QQuickItem *item)
2450{
2451 if (!item->window())
2452 return false;
2453
2454 if (item == item->window()->contentItem())
2455 return true;
2456
2457#if QT_CONFIG(accessibility)
2458 QAccessible::Role role = QQuickItemPrivate::get(item)->accessibleRole();
2459 if (role == QAccessible::EditableText || role == QAccessible::Table || role == QAccessible::List) {
2460 return true;
2461 } else if (role == QAccessible::ComboBox || role == QAccessible::SpinBox) {
2462 if (QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(item))
2463 return iface->state().editable;
2464 }
2465#endif
2466
2467 QVariant editable = item->property("editable");
2468 if (editable.isValid())
2469 return editable.toBool();
2470
2471 QVariant readonly = item->property("readOnly");
2472 if (readonly.isValid() && !readonly.toBool() && item->property("text").isValid())
2473 return true;
2474
2475 return false;
2476}
2477
2478/*!
2479 \internal
2480 \brief QQuickItemPrivate::focusNextPrev focuses the next/prev item in the tab-focus-chain
2481 \param item The item that currently has the focus
2482 \param forward The direction
2483 \return Whether the next item in the focus chain is found or not
2484
2485 If \a next is true, the next item visited will be in depth-first order relative to \a item.
2486 If \a next is false, the next item visited will be in reverse depth-first order relative to \a item.
2487*/
2488bool QQuickItemPrivate::focusNextPrev(QQuickItem *item, bool forward)
2489{
2490 QQuickItem *next = QQuickItemPrivate::nextPrevItemInTabFocusChain(item, forward);
2491
2492 if (next == item)
2493 return false;
2494
2495 next->forceActiveFocus(forward ? Qt::TabFocusReason : Qt::BacktabFocusReason);
2496
2497 return true;
2498}
2499
2500QQuickItem *QQuickItemPrivate::nextTabChildItem(const QQuickItem *item, int start)
2501{
2502 if (!item) {
2503 qWarning() << "QQuickItemPrivate::nextTabChildItem called with null item.";
2504 return nullptr;
2505 }
2506 const QList<QQuickItem *> &children = item->childItems();
2507 const int count = children.count();
2508 if (start < 0 || start >= count) {
2509 qWarning() << "QQuickItemPrivate::nextTabChildItem: Start index value out of range for item" << item;
2510 return nullptr;
2511 }
2512 while (start < count) {
2513 QQuickItem *child = children.at(start);
2514 if (!child->d_func()->isTabFence)
2515 return child;
2516 ++start;
2517 }
2518 return nullptr;
2519}
2520
2521QQuickItem *QQuickItemPrivate::prevTabChildItem(const QQuickItem *item, int start)
2522{
2523 if (!item) {
2524 qWarning() << "QQuickItemPrivate::prevTabChildItem called with null item.";
2525 return nullptr;
2526 }
2527 const QList<QQuickItem *> &children = item->childItems();
2528 const int count = children.count();
2529 if (start == -1)
2530 start = count - 1;
2531 if (start < 0 || start >= count) {
2532 qWarning() << "QQuickItemPrivate::prevTabChildItem: Start index value out of range for item" << item;
2533 return nullptr;
2534 }
2535 while (start >= 0) {
2536 QQuickItem *child = children.at(start);
2537 if (!child->d_func()->isTabFence)
2538 return child;
2539 --start;
2540 }
2541 return nullptr;
2542}
2543
2544QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, bool forward)
2545{
2546 Q_ASSERT(item);
2547 qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: item:" << item << ", forward:" << forward;
2548
2549 if (!item->window())
2550 return item;
2551 const QQuickItem * const contentItem = item->window()->contentItem();
2552 if (!contentItem)
2553 return item;
2554
2555 bool all = QGuiApplication::styleHints()->tabFocusBehavior() == Qt::TabFocusAllControls;
2556
2557 QQuickItem *from = nullptr;
2558 bool isTabFence = item->d_func()->isTabFence;
2559 if (forward) {
2560 if (!isTabFence)
2561 from = item->parentItem();
2562 } else {
2563 if (!item->childItems().isEmpty())
2564 from = item->d_func()->childItems.constFirst();
2565 else if (!isTabFence)
2566 from = item->parentItem();
2567 }
2568 bool skip = false;
2569
2570 QQuickItem *startItem = item;
2571 // Protect from endless loop:
2572 // If we start on an invisible item we will not find it again.
2573 // If there is no other item which can become the focus item, we have a forever loop,
2574 // since the protection only works if we encounter the first item again.
2575 while (startItem && !startItem->isVisible()) {
2576 startItem = startItem->parentItem();
2577 }
2578 if (!startItem)
2579 return item;
2580
2581 QQuickItem *firstFromItem = from;
2582 QQuickItem *current = item;
2583 qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: startItem:" << startItem;
2584 qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: firstFromItem:" << firstFromItem;
2585 do {
2586 qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: current:" << current;
2587 qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: from:" << from;
2588 skip = false;
2589 QQuickItem *last = current;
2590
2591 bool hasChildren = !current->childItems().isEmpty() && current->isEnabled() && current->isVisible();
2592 QQuickItem *firstChild = nullptr;
2593 QQuickItem *lastChild = nullptr;
2594 if (hasChildren) {
2595 firstChild = nextTabChildItem(current, 0);
2596 if (!firstChild)
2597 hasChildren = false;
2598 else
2599 lastChild = prevTabChildItem(current, -1);
2600 }
2601 isTabFence = current->d_func()->isTabFence;
2602 if (isTabFence && !hasChildren)
2603 return current;
2604
2605 // coming from parent: check children
2606 if (hasChildren && from == current->parentItem()) {
2607 if (forward) {
2608 current = firstChild;
2609 } else {
2610 current = lastChild;
2611 if (!current->childItems().isEmpty())
2612 skip = true;
2613 }
2614 } else if (hasChildren && forward && from != lastChild) {
2615 // not last child going forwards
2616 int nextChild = current->childItems().indexOf(from) + 1;
2617 current = nextTabChildItem(current, nextChild);
2618 } else if (hasChildren && !forward && from != firstChild) {
2619 // not first child going backwards
2620 int prevChild = current->childItems().indexOf(from) - 1;
2621 current = prevTabChildItem(current, prevChild);
2622 if (!current->childItems().isEmpty())
2623 skip = true;
2624 // back to the parent
2625 } else if (QQuickItem *parent = !isTabFence ? current->parentItem() : nullptr) {
2626 // we would evaluate the parent twice, thus we skip
2627 if (forward) {
2628 skip = true;
2629 } else if (QQuickItem *firstSibling = !forward ? nextTabChildItem(parent, 0) : nullptr) {
2630 if (last != firstSibling
2631 || (parent->isFocusScope() && parent->activeFocusOnTab() && parent->hasActiveFocus()))
2632 skip = true;
2633 }
2634 current = parent;
2635 } else if (hasChildren) {
2636 // Wrap around after checking all items forward
2637 if (forward) {
2638 current = firstChild;
2639 } else {
2640 current = lastChild;
2641 if (!current->childItems().isEmpty())
2642 skip = true;
2643 }
2644 }
2645 from = last;
2646 if (current == startItem && from == firstFromItem) {
2647 // wrapped around, avoid endless loops
2648 if (item == contentItem) {
2649 qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: looped, return contentItem";
2650 return item;
2651 } else {
2652 qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: looped, return " << startItem;
2653 return startItem;
2654 }
2655 }
2656 if (!firstFromItem) {
2657 if (startItem->d_func()->isTabFence) {
2658 if (current == startItem)
2659 firstFromItem = from;
2660 } else { //start from root
2661 startItem = current;
2662 firstFromItem = from;
2663 }
2664 }
2665 } while (skip || !current->activeFocusOnTab() || !current->isEnabled() || !current->isVisible()
2666 || !(all || QQuickItemPrivate::canAcceptTabFocus(current)));
2667
2668 return current;
2669}
2670
2671/*!
2672 \qmlproperty Item QtQuick::Item::parent
2673 This property holds the visual parent of the item.
2674
2675 \note The concept of the \e {visual parent} differs from that of the
2676 \e {QObject parent}. An item's visual parent may not necessarily be the
2677 same as its object parent. See \l {Concepts - Visual Parent in Qt Quick}
2678 for more details.
2679*/
2680/*!
2681 \property QQuickItem::parent
2682 This property holds the visual parent of the item.
2683
2684 \note The concept of the \e {visual parent} differs from that of the
2685 \e {QObject parent}. An item's visual parent may not necessarily be the
2686 same as its object parent. See \l {Concepts - Visual Parent in Qt Quick}
2687 for more details.
2688*/
2689QQuickItem *QQuickItem::parentItem() const
2690{
2691 Q_D(const QQuickItem);
2692 return d->parentItem;
2693}
2694
2695void QQuickItem::setParentItem(QQuickItem *parentItem)
2696{
2697 Q_D(QQuickItem);
2698 if (parentItem == d->parentItem)
2699 return;
2700
2701 if (parentItem) {
2702 QQuickItem *itemAncestor = parentItem;
2703 while (itemAncestor != nullptr) {
2704 if (Q_UNLIKELY(itemAncestor == this)) {
2705 qWarning() << "QQuickItem::setParentItem: Parent" << parentItem << "is already part of the subtree of" << this;
2706 return;
2707 }
2708 itemAncestor = itemAncestor->parentItem();
2709 }
2710 }
2711
2712 d->removeFromDirtyList();
2713
2714 QQuickItem *oldParentItem = d->parentItem;
2715 QQuickItem *scopeFocusedItem = nullptr;
2716
2717 if (oldParentItem) {
2718 QQuickItemPrivate *op = QQuickItemPrivate::get(oldParentItem);
2719
2720 QQuickItem *scopeItem = nullptr;
2721
2722 if (hasFocus() || op->subFocusItem == this)
2723 scopeFocusedItem = this;
2724 else if (!isFocusScope() && d->subFocusItem)
2725 scopeFocusedItem = d->subFocusItem;
2726
2727 if (scopeFocusedItem) {
2728 scopeItem = oldParentItem;
2729 while (!scopeItem->isFocusScope() && scopeItem->parentItem())
2730 scopeItem = scopeItem->parentItem();
2731 if (d->window) {
2732 QQuickWindowPrivate::get(d->window)->clearFocusInScope(scopeItem, scopeFocusedItem, Qt::OtherFocusReason,
2733 QQuickWindowPrivate::DontChangeFocusProperty);
2734 if (scopeFocusedItem != this)
2735 QQuickItemPrivate::get(scopeFocusedItem)->updateSubFocusItem(this, true);
2736 } else {
2737 QQuickItemPrivate::get(scopeFocusedItem)->updateSubFocusItem(scopeItem, false);
2738 }
2739 }
2740
2741 const bool wasVisible = isVisible();
2742 op->removeChild(this);
2743 if (wasVisible) {
2744 emit oldParentItem->visibleChildrenChanged();
2745 }
2746 } else if (d->window) {
2747 QQuickWindowPrivate::get(d->window)->parentlessItems.remove(this);
2748 }
2749
2750 QQuickWindow *parentWindow = parentItem ? QQuickItemPrivate::get(parentItem)->window : nullptr;
2751 if (d->window == parentWindow) {
2752 // Avoid freeing and reallocating resources if the window stays the same.
2753 d->parentItem = parentItem;
2754 } else {
2755 if (d->window)
2756 d->derefWindow();
2757 d->parentItem = parentItem;
2758 if (parentWindow)
2759 d->refWindow(parentWindow);
2760 }
2761
2762 d->dirty(QQuickItemPrivate::ParentChanged);
2763
2764 if (d->parentItem)
2765 QQuickItemPrivate::get(d->parentItem)->addChild(this);
2766 else if (d->window)
2767 QQuickWindowPrivate::get(d->window)->parentlessItems.insert(this);
2768
2769 d->setEffectiveVisibleRecur(d->calcEffectiveVisible());
2770 d->setEffectiveEnableRecur(nullptr, d->calcEffectiveEnable());
2771
2772 if (d->parentItem) {
2773 if (!scopeFocusedItem) {
2774 if (hasFocus())
2775 scopeFocusedItem = this;
2776 else if (!isFocusScope() && d->subFocusItem)
2777 scopeFocusedItem = d->subFocusItem;
2778 }
2779
2780 if (scopeFocusedItem) {
2781 // We need to test whether this item becomes scope focused
2782 QQuickItem *scopeItem = d->parentItem;
2783 while (!scopeItem->isFocusScope() && scopeItem->parentItem())
2784 scopeItem = scopeItem->parentItem();
2785
2786 if (QQuickItemPrivate::get(scopeItem)->subFocusItem
2787 || (!scopeItem->isFocusScope() && scopeItem->hasFocus())) {
2788 if (scopeFocusedItem != this)
2789 QQuickItemPrivate::get(scopeFocusedItem)->updateSubFocusItem(this, false);
2790 QQuickItemPrivate::get(scopeFocusedItem)->focus = false;
2791 emit scopeFocusedItem->focusChanged(false);
2792 } else {
2793 if (d->window) {
2794 QQuickWindowPrivate::get(d->window)->setFocusInScope(scopeItem, scopeFocusedItem, Qt::OtherFocusReason,
2795 QQuickWindowPrivate::DontChangeFocusProperty);
2796 } else {
2797 QQuickItemPrivate::get(scopeFocusedItem)->updateSubFocusItem(scopeItem, true);
2798 }
2799 }
2800 }
2801 }
2802
2803 if (d->parentItem)
2804 d->resolveLayoutMirror();
2805
2806 d->itemChange(ItemParentHasChanged, d->parentItem);
2807
2808 emit parentChanged(d->parentItem);
2809 if (isVisible() && d->parentItem)
2810 emit d->parentItem->visibleChildrenChanged();
2811}
2812
2813/*!
2814 Moves the specified \a sibling item to the index before this item
2815 within the list of children. The order of children affects both the
2816 visual stacking order and tab focus navigation order.
2817
2818 Assuming the z values of both items are the same, this will cause \a
2819 sibling to be rendered above this item.
2820
2821 If both items have activeFocusOnTab set to \c true, this will also cause
2822 the tab focus order to change, with \a sibling receiving focus after this
2823 item.
2824
2825 The given \a sibling must be a sibling of this item; that is, they must
2826 have the same immediate \l parent.
2827
2828 \sa {Concepts - Visual Parent in Qt Quick}
2829*/
2830void QQuickItem::stackBefore(const QQuickItem *sibling)
2831{
2832 Q_D(QQuickItem);
2833 if (!sibling || sibling == this || !d->parentItem || d->parentItem != QQuickItemPrivate::get(sibling)->parentItem) {
2834 qWarning().nospace() << "QQuickItem::stackBefore: Cannot stack "
2835 << this << " before " << sibling << ", which must be a sibling";
2836 return;
2837 }
2838
2839 QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(d->parentItem);
2840
2841 int myIndex = parentPrivate->childItems.lastIndexOf(this);
2842 int siblingIndex = parentPrivate->childItems.lastIndexOf(const_cast<QQuickItem *>(sibling));
2843
2844 Q_ASSERT(myIndex != -1 && siblingIndex != -1);
2845
2846 if (myIndex == siblingIndex - 1)
2847 return;
2848
2849 parentPrivate->childItems.move(myIndex, myIndex < siblingIndex ? siblingIndex - 1 : siblingIndex);
2850
2851 parentPrivate->dirty(QQuickItemPrivate::ChildrenStackingChanged);
2852 parentPrivate->markSortedChildrenDirty(this);
2853
2854 for (int ii = qMin(siblingIndex, myIndex); ii < parentPrivate->childItems.count(); ++ii)
2855 QQuickItemPrivate::get(parentPrivate->childItems.at(ii))->siblingOrderChanged();
2856}
2857
2858/*!
2859 Moves the specified \a sibling item to the index after this item
2860 within the list of children. The order of children affects both the
2861 visual stacking order and tab focus navigation order.
2862
2863 Assuming the z values of both items are the same, this will cause \a
2864 sibling to be rendered below this item.
2865
2866 If both items have activeFocusOnTab set to \c true, this will also cause
2867 the tab focus order to change, with \a sibling receiving focus before this
2868 item.
2869
2870 The given \a sibling must be a sibling of this item; that is, they must
2871 have the same immediate \l parent.
2872
2873 \sa {Concepts - Visual Parent in Qt Quick}
2874*/
2875void QQuickItem::stackAfter(const QQuickItem *sibling)
2876{
2877 Q_D(QQuickItem);
2878 if (!sibling || sibling == this || !d->parentItem || d->parentItem != QQuickItemPrivate::get(sibling)->parentItem) {
2879 qWarning().nospace() << "QQuickItem::stackAfter: Cannot stack "
2880 << this << " after " << sibling << ", which must be a sibling";
2881 return;
2882 }
2883
2884 QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(d->parentItem);
2885
2886 int myIndex = parentPrivate->childItems.lastIndexOf(this);
2887 int siblingIndex = parentPrivate->childItems.lastIndexOf(const_cast<QQuickItem *>(sibling));
2888
2889 Q_ASSERT(myIndex != -1 && siblingIndex != -1);
2890
2891 if (myIndex == siblingIndex + 1)
2892 return;
2893
2894 parentPrivate->childItems.move(myIndex, myIndex > siblingIndex ? siblingIndex + 1 : siblingIndex);
2895
2896 parentPrivate->dirty(QQuickItemPrivate::ChildrenStackingChanged);
2897 parentPrivate->markSortedChildrenDirty(this);
2898
2899 for (int ii = qMin(myIndex, siblingIndex + 1); ii < parentPrivate->childItems.count(); ++ii)
2900 QQuickItemPrivate::get(parentPrivate->childItems.at(ii))->siblingOrderChanged();
2901}
2902
2903/*! \fn void QQuickItem::windowChanged(QQuickWindow *window)
2904 This signal is emitted when the item's \a window changes.
2905*/
2906
2907/*!
2908 Returns the window in which this item is rendered.
2909
2910 The item does not have a window until it has been assigned into a scene. The
2911 \l windowChanged() signal provides a notification both when the item is entered
2912 into a scene and when it is removed from a scene.
2913 */
2914QQuickWindow *QQuickItem::window() const
2915{
2916 Q_D(const QQuickItem);
2917 return d->window;
2918}
2919
2920static bool itemZOrder_sort(QQuickItem *lhs, QQuickItem *rhs)
2921{
2922 return lhs->z() < rhs->z();
2923}
2924
2925QList<QQuickItem *> QQuickItemPrivate::paintOrderChildItems() const
2926{
2927 if (sortedChildItems)
2928 return *sortedChildItems;
2929
2930 // If none of the items have set Z then the paint order list is the same as
2931 // the childItems list. This is by far the most common case.
2932 bool haveZ = false;
2933 for (int i = 0; i < childItems.count(); ++i) {
2934 if (QQuickItemPrivate::get(childItems.at(i))->z() != 0.) {
2935 haveZ = true;
2936 break;
2937 }
2938 }
2939 if (haveZ) {
2940 sortedChildItems = new QList<QQuickItem*>(childItems);
2941 std::stable_sort(sortedChildItems->begin(), sortedChildItems->end(), itemZOrder_sort);
2942 return *sortedChildItems;
2943 }
2944
2945 sortedChildItems = const_cast<QList<QQuickItem*>*>(&childItems);
2946
2947 return childItems;
2948}
2949
2950void QQuickItemPrivate::addChild(QQuickItem *child)
2951{
2952 Q_Q(QQuickItem);
2953
2954 Q_ASSERT(!childItems.contains(child));
2955
2956 childItems.append(child);
2957
2958 QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(child);
2959
2960#if QT_CONFIG(cursor)
2961 // if the added child has a cursor and we do not currently have any children
2962 // with cursors, bubble the notification up
2963 if (childPrivate->subtreeCursorEnabled && !subtreeCursorEnabled)
2964 setHasCursorInChild(true);
2965#endif
2966
2967 if (childPrivate->subtreeHoverEnabled && !subtreeHoverEnabled)
2968 setHasHoverInChild(true);
2969
2970 childPrivate->recursiveRefFromEffectItem(extra.value().recursiveEffectRefCount);
2971 markSortedChildrenDirty(child);
2972 dirty(QQuickItemPrivate::ChildrenChanged);
2973
2974 itemChange(QQuickItem::ItemChildAddedChange, child);
2975
2976 emit q->childrenChanged();
2977}
2978
2979void QQuickItemPrivate::removeChild(QQuickItem *child)
2980{
2981 Q_Q(QQuickItem);
2982
2983 Q_ASSERT(child);
2984 Q_ASSERT(childItems.contains(child));
2985 childItems.removeOne(child);
2986 Q_ASSERT(!childItems.contains(child));
2987
2988 QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(child);
2989
2990#if QT_CONFIG(cursor)
2991 // turn it off, if nothing else is using it
2992 if (childPrivate->subtreeCursorEnabled && subtreeCursorEnabled)
2993 setHasCursorInChild(false);
2994#endif
2995
2996 if (childPrivate->subtreeHoverEnabled && subtreeHoverEnabled)
2997 setHasHoverInChild(false);
2998
2999 childPrivate->recursiveRefFromEffectItem(-extra.value().recursiveEffectRefCount);
3000 markSortedChildrenDirty(child);
3001 dirty(QQuickItemPrivate::ChildrenChanged);
3002
3003 itemChange(QQuickItem::ItemChildRemovedChange, child);
3004
3005 emit q->childrenChanged();
3006}
3007
3008void QQuickItemPrivate::refWindow(QQuickWindow *c)
3009{
3010 // An item needs a window if it is referenced by another item which has a window.
3011 // Typically the item is referenced by a parent, but can also be referenced by a
3012 // ShaderEffect or ShaderEffectSource. 'windowRefCount' counts how many items with
3013 // a window is referencing this item. When the reference count goes from zero to one,
3014 // or one to zero, the window of this item is updated and propagated to the children.
3015 // As long as the reference count stays above zero, the window is unchanged.
3016 // refWindow() increments the reference count.
3017 // derefWindow() decrements the reference count.
3018
3019 Q_Q(QQuickItem);
3020 Q_ASSERT((window != nullptr) == (windowRefCount > 0));
3021 Q_ASSERT(c);
3022 if (++windowRefCount > 1) {
3023 if (c != window)
3024 qWarning("QQuickItem: Cannot use same item on different windows at the same time.");
3025 return; // Window already set.
3026 }
3027
3028 Q_ASSERT(window == nullptr);
3029 window = c;
3030
3031 if (polishScheduled)
3032 QQuickWindowPrivate::get(window)->itemsToPolish.append(q);
3033
3034 if (!parentItem)
3035 QQuickWindowPrivate::get(window)->parentlessItems.insert(q);
3036
3037 for (int ii = 0; ii < childItems.count(); ++ii) {
3038 QQuickItem *child = childItems.at(ii);
3039 QQuickItemPrivate::get(child)->refWindow(c);
3040 }
3041
3042 dirty(Window);
3043
3044 if (extra.isAllocated() && extra->screenAttached)
3045 extra->screenAttached->windowChanged(c);
3046 itemChange(QQuickItem::ItemSceneChange, c);
3047}
3048
3049void QQuickItemPrivate::derefWindow()
3050{
3051 Q_Q(QQuickItem);
3052 Q_ASSERT((window != nullptr) == (windowRefCount > 0));
3053
3054 if (!window)
3055 return; // This can happen when destroying recursive shader effect sources.
3056
3057 if (--windowRefCount > 0)
3058 return; // There are still other references, so don't set window to null yet.
3059
3060 q->releaseResources();
3061 removeFromDirtyList();
3062 QQuickWindowPrivate *c = QQuickWindowPrivate::get(window);
3063 if (polishScheduled)
3064 c->itemsToPolish.removeOne(q);
3065 c->removeGrabber(q);
3066#if QT_CONFIG(cursor)
3067 if (c->cursorItem == q) {
3068 c->cursorItem = nullptr;
3069 window->unsetCursor();
3070 }
3071#endif
3072 c->hoverItems.removeAll(q);
3073 if (itemNodeInstance)
3074 c->cleanup(itemNodeInstance);
3075 if (!parentItem)
3076 c->parentlessItems.remove(q);
3077
3078 window = nullptr;
3079
3080 itemNodeInstance = nullptr;
3081
3082 if (extra.isAllocated()) {
3083 extra->opacityNode = nullptr;
3084 extra->clipNode = nullptr;
3085 extra->rootNode = nullptr;
3086 }
3087
3088 paintNode = nullptr;
3089
3090 for (int ii = 0; ii < childItems.count(); ++ii) {
3091 QQuickItem *child = childItems.at(ii);
3092 QQuickItemPrivate::get(child)->derefWindow();
3093 }
3094
3095 dirty(Window);
3096
3097 if (extra.isAllocated() && extra->screenAttached)
3098 extra->screenAttached->windowChanged(nullptr);
3099 itemChange(QQuickItem::ItemSceneChange, (QQuickWindow *)nullptr);
3100}
3101
3102
3103/*!
3104Returns a transform that maps points from window space into item space.
3105*/
3106QTransform QQuickItemPrivate::windowToItemTransform() const
3107{
3108 // XXX todo - optimize
3109 return itemToWindowTransform().inverted();
3110}
3111
3112/*!
3113Returns a transform that maps points from item space into window space.
3114*/
3115QTransform QQuickItemPrivate::itemToWindowTransform() const
3116{
3117 // XXX todo
3118 QTransform rv = parentItem?QQuickItemPrivate::get(parentItem)->itemToWindowTransform():QTransform();
3119 itemToParentTransform(rv);
3120 return rv;
3121}
3122
3123/*!
3124Motifies \a t with this items local transform relative to its parent.
3125*/
3126void QQuickItemPrivate::itemToParentTransform(QTransform &t) const
3127{
3128 if (x || y)
3129 t.translate(x, y);
3130
3131 if (!transforms.isEmpty()) {
3132 QMatrix4x4 m(t);
3133 for (int ii = transforms.count() - 1; ii >= 0; --ii)
3134 transforms.at(ii)->applyTo(&m);
3135 t = m.toTransform();
3136 }
3137
3138 if (scale() != 1. || rotation() != 0.) {
3139 QPointF tp = computeTransformOrigin();
3140 t.translate(tp.x(), tp.y());
3141 t.scale(scale(), scale());
3142 t.rotate(rotation());
3143 t.translate(-tp.x(), -tp.y());
3144 }
3145}
3146
3147/*!
3148 Returns a transform that maps points from window space into global space.
3149*/
3150QTransform QQuickItemPrivate::windowToGlobalTransform() const
3151{
3152 if (Q_UNLIKELY(window == nullptr))
3153 return QTransform();
3154
3155 QPoint quickWidgetOffset;
3156 QWindow *renderWindow = QQuickRenderControl::renderWindowFor(window, &quickWidgetOffset);
3157 QPointF pos = (renderWindow ? renderWindow : window)->mapToGlobal(quickWidgetOffset);
3158 return QTransform::fromTranslate(pos.x(), pos.y());
3159}
3160
3161/*!
3162 Returns a transform that maps points from global space into window space.
3163*/
3164QTransform QQuickItemPrivate::globalToWindowTransform() const
3165{
3166 if (Q_UNLIKELY(window == nullptr))
3167 return QTransform();
3168
3169 QPoint quickWidgetOffset;
3170 QWindow *renderWindow = QQuickRenderControl::renderWindowFor(window, &quickWidgetOffset);
3171 QPointF pos = (renderWindow ? renderWindow : window)->mapToGlobal(quickWidgetOffset);
3172 return QTransform::fromTranslate(-pos.x(), -pos.y());
3173}
3174
3175/*!
3176 Returns true if construction of the QML component is complete; otherwise
3177 returns false.
3178
3179 It is often desirable to delay some processing until the component is
3180 completed.
3181
3182 \sa componentComplete()
3183*/
3184bool QQuickItem::isComponentComplete() const
3185{
3186 Q_D(const QQuickItem);
3187 return d->componentComplete;
3188}
3189
3190QQuickItemPrivate::QQuickItemPrivate()
3191 : _anchors(nullptr)
3192 , _stateGroup(nullptr)
3193 , flags(0)
3194 , widthValid(false)
3195 , heightValid(false)
3196 , componentComplete(true)
3197 , keepMouse(false)
3198 , keepTouch(false)
3199 , hoverEnabled(false)
3200 , smooth(true)
3201 , antialiasing(false)
3202 , focus(false)
3203 , activeFocus(false)
3204 , notifiedFocus(false)
3205 , notifiedActiveFocus(false)
3206 , filtersChildMouseEvents(false)
3207 , explicitVisible(true)
3208 , effectiveVisible(true)
3209 , explicitEnable(true)
3210 , effectiveEnable(true)
3211 , polishScheduled(false)
3212 , inheritedLayoutMirror(false)
3213 , effectiveLayoutMirror(false)
3214 , isMirrorImplicit(true)
3215 , inheritMirrorFromParent(false)
3216 , inheritMirrorFromItem(false)
3217 , isAccessible(false)
3218 , culled(false)
3219 , hasCursor(false)
3220 , subtreeCursorEnabled(false)
3221 , subtreeHoverEnabled(false)
3222 , activeFocusOnTab(false)
3223 , implicitAntialiasing(false)
3224 , antialiasingValid(false)
3225 , isTabFence(false)
3226 , replayingPressEvent(false)
3227#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
3228 , touchEnabled(true)
3229#else
3230 , touchEnabled(false)
3231#endif
3232 , dirtyAttributes(0)
3233 , nextDirtyItem(nullptr)
3234 , prevDirtyItem(nullptr)
3235 , window(nullptr)
3236 , windowRefCount(0)
3237 , parentItem(nullptr)
3238 , sortedChildItems(&childItems)
3239 , subFocusItem(nullptr)
3240 , x(0)
3241 , y(0)
3242 , width(0)
3243 , height(0)
3244 , implicitWidth(0)
3245 , implicitHeight(0)
3246 , baselineOffset(0)
3247 , itemNodeInstance(nullptr)
3248 , paintNode(nullptr)
3249{
3250}
3251
3252QQuickItemPrivate::~QQuickItemPrivate()
3253{
3254 if (sortedChildItems != &childItems)
3255 delete sortedChildItems;
3256}
3257
3258void QQuickItemPrivate::init(QQuickItem *parent)
3259{
3260 Q_Q(QQuickItem);
3261
3262 baselineOffset = 0.0;
3263
3264 if (parent) {
3265 q->setParentItem(parent);
3266 QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(parent);
3267 setImplicitLayoutMirror(parentPrivate->inheritedLayoutMirror, parentPrivate->inheritMirrorFromParent);
3268 }
3269}
3270
3271void QQuickItemPrivate::data_append(QQmlListProperty<QObject> *prop, QObject *o)
3272{
3273 if (!o)
3274 return;
3275
3276 QQuickItem *that = static_cast<QQuickItem *>(prop->object);
3277
3278 if (QQuickItem *item = qmlobject_cast<QQuickItem *>(o)) {
3279 item->setParentItem(that);
3280 } else {
3281 if (o->inherits("QGraphicsItem"))
3282 qWarning("Cannot add a QtQuick 1.0 item (%s) into a QtQuick 2.0 scene!", o->metaObject()->className());
3283 else if (QQuickPointerHandler *pointerHandler = qmlobject_cast<QQuickPointerHandler *>(o)) {
3284 if (pointerHandler->parent() != that) {
3285 qCDebug(lcHandlerParent) << "reparenting handler" << pointerHandler << ":" << pointerHandler->parent() << "->" << that;
3286 pointerHandler->setParent(that);
3287 }
3288 QQuickItemPrivate::get(that)->addPointerHandler(pointerHandler);
3289 } else {
3290 QQuickWindow *thisWindow = qmlobject_cast<QQuickWindow *>(o);
3291 QQuickItem *item = that;
3292 QQuickWindow *itemWindow = that->window();
3293 while (!itemWindow && item && item->parentItem()) {
3294 item = item->parentItem();
3295 itemWindow = item->window();
3296 }
3297
3298 if (thisWindow) {
3299 if (itemWindow) {
3300 qCDebug(lcTransient) << thisWindow << "is transient for" << itemWindow;
3301 thisWindow->setTransientParent(itemWindow);
3302 } else {
3303 QObject::connect(item, SIGNAL(windowChanged(QQuickWindow*)),
3304 thisWindow, SLOT(setTransientParent_helper(QQuickWindow*)));
3305 }
3306 }
3307 o->setParent(that);
3308 }
3309
3310 resources_append(prop, o);
3311 }
3312}
3313
3314/*!
3315 \qmlproperty list<Object> QtQuick::Item::data
3316 \default
3317
3318 The data property allows you to freely mix visual children and resources
3319 in an item. If you assign a visual item to the data list it becomes
3320 a child and if you assign any other object type, it is added as a resource.
3321
3322 So you can write:
3323 \qml
3324 Item {
3325 Text {}
3326 Rectangle {}
3327 Timer {}
3328 }
3329 \endqml
3330
3331 instead of:
3332 \qml
3333 Item {
3334 children: [
3335 Text {},
3336 Rectangle {}
3337 ]
3338 resources: [
3339 Timer {}
3340 ]
3341 }
3342 \endqml
3343
3344 It should not generally be necessary to refer to the \c data property,
3345 as it is the default property for Item and thus all child items are
3346 automatically assigned to this property.
3347 */
3348
3349int QQuickItemPrivate::data_count(QQmlListProperty<QObject> *property)
3350{
3351 QQuickItem *item = static_cast<QQuickItem*>(property->object);
3352 QQuickItemPrivate *privateItem = QQuickItemPrivate::get(item);
3353 QQmlListProperty<QObject> resourcesProperty = privateItem->resources();
3354 QQmlListProperty<QQuickItem> childrenProperty = privateItem->children();
3355
3356 return resources_count(&resourcesProperty) + children_count(&childrenProperty);
3357}
3358
3359QObject *QQuickItemPrivate::data_at(QQmlListProperty<QObject> *property, int i)
3360{
3361 QQuickItem *item = static_cast<QQuickItem*>(property->object);
3362 QQuickItemPrivate *privateItem = QQuickItemPrivate::get(item);
3363 QQmlListProperty<QObject> resourcesProperty = privateItem->resources();
3364 QQmlListProperty<QQuickItem> childrenProperty = privateItem->children();
3365
3366 int resourcesCount = resources_count(&resourcesProperty);
3367 if (i < resourcesCount)
3368 return resources_at(&resourcesProperty, i);
3369 const int j = i - resourcesCount;
3370 if (j < children_count(&childrenProperty))
3371 return children_at(&childrenProperty, j);
3372 return nullptr;
3373}
3374
3375void QQuickItemPrivate::data_clear(QQmlListProperty<QObject> *property)
3376{
3377 QQuickItem *item = static_cast<QQuickItem*>(property->object);
3378 QQuickItemPrivate *privateItem = QQuickItemPrivate::get(item);
3379 QQmlListProperty<QObject> resourcesProperty = privateItem->resources();
3380 QQmlListProperty<QQuickItem> childrenProperty = privateItem->children();
3381
3382 resources_clear(&resourcesProperty);
3383 children_clear(&childrenProperty);
3384}
3385
3386QObject *QQuickItemPrivate::resources_at(QQmlListProperty<QObject> *prop, int index)
3387{
3388 QQuickItemPrivate *quickItemPrivate = QQuickItemPrivate::get(static_cast<QQuickItem *>(prop->object));
3389 return quickItemPrivate->extra.isAllocated() ? quickItemPrivate->extra->resourcesList.value(index) : 0;
3390}
3391
3392void QQuickItemPrivate::resources_append(QQmlListProperty<QObject> *prop, QObject *object)
3393{
3394 QQuickItem *quickItem = static_cast<QQuickItem *>(prop->object);
3395 QQuickItemPrivate *quickItemPrivate = QQuickItemPrivate::get(quickItem);
3396 if (!quickItemPrivate->extra.value().resourcesList.contains(object)) {
3397 quickItemPrivate->extra.value().resourcesList.append(object);
3398 qmlobject_connect(object, QObject, SIGNAL(destroyed(QObject*)),
3399 quickItem, QQuickItem, SLOT(_q_resourceObjectDeleted(QObject*)));
3400 }
3401}
3402
3403int QQuickItemPrivate::resources_count(QQmlListProperty<QObject> *prop)
3404{
3405 QQuickItemPrivate *quickItemPrivate = QQuickItemPrivate::get(static_cast<QQuickItem *>(prop->object));
3406 return quickItemPrivate->extra.isAllocated() ? quickItemPrivate->extra->resourcesList.count() : 0;
3407}
3408
3409void QQuickItemPrivate::resources_clear(QQmlListProperty<QObject> *prop)
3410{
3411 QQuickItem *quickItem = static_cast<QQuickItem *>(prop->object);
3412 QQuickItemPrivate *quickItemPrivate = QQuickItemPrivate::get(quickItem);
3413 if (quickItemPrivate->extra.isAllocated()) {//If extra is not allocated resources is empty.
3414 for (QObject *object : qAsConst(quickItemPrivate->extra->resourcesList)) {
3415 qmlobject_disconnect(object, QObject, SIGNAL(destroyed(QObject*)),
3416 quickItem, QQuickItem, SLOT(_q_resourceObjectDeleted(QObject*)));
3417 }
3418 quickItemPrivate->extra->resourcesList.clear();
3419 }
3420}
3421
3422QQuickItem *QQuickItemPrivate::children_at(QQmlListProperty<QQuickItem> *prop, int index)
3423{
3424 QQuickItemPrivate *p = QQuickItemPrivate::get(static_cast<QQuickItem *>(prop->object));
3425 if (index >= p->childItems.count() || index < 0)
3426 return nullptr;
3427 else
3428 return p->childItems.at(index);
3429}
3430
3431void QQuickItemPrivate::children_append(QQmlListProperty<QQuickItem> *prop, QQuickItem *o)
3432{
3433 if (!o)
3434 return;
3435
3436 QQuickItem *that = static_cast<QQuickItem *>(prop->object);
3437 if (o->parentItem() == that)
3438 o->setParentItem(nullptr);
3439
3440 o->setParentItem(that);
3441}
3442
3443int QQuickItemPrivate::children_count(QQmlListProperty<QQuickItem> *prop)
3444{
3445 QQuickItemPrivate *p = QQuickItemPrivate::get(static_cast<QQuickItem *>(prop->object));
3446 return p->childItems.count();
3447}
3448
3449void QQuickItemPrivate::children_clear(QQmlListProperty<QQuickItem> *prop)
3450{
3451 QQuickItem *that = static_cast<QQuickItem *>(prop->object);
3452 QQuickItemPrivate *p = QQuickItemPrivate::get(that);
3453 while (!p->childItems.isEmpty())
3454 p->childItems.at(0)->setParentItem(nullptr);
3455}
3456
3457int QQuickItemPrivate::visibleChildren_count(QQmlListProperty<QQuickItem> *prop)
3458{
3459 QQuickItemPrivate *p = QQuickItemPrivate::get(static_cast<QQuickItem *>(prop->object));
3460 int visibleCount = 0;
3461 int c = p->childItems.count();
3462 while (c--) {
3463 if (p->childItems.at(c)->isVisible()) visibleCount++;
3464 }
3465
3466 return visibleCount;
3467}
3468
3469QQuickItem *QQuickItemPrivate::visibleChildren_at(QQmlListProperty<QQuickItem> *prop, int index)
3470{
3471 QQuickItemPrivate *p = QQuickItemPrivate::get(static_cast<QQuickItem *>(prop->object));
3472 const int childCount = p->childItems.count();
3473 if (index >= childCount || index < 0)
3474 return nullptr;
3475
3476 int visibleCount = -1;
3477 for (int i = 0; i < childCount; i++) {
3478 if (p->childItems.at(i)->isVisible()) visibleCount++;
3479 if (visibleCount == index) return p->childItems.at(i);
3480 }
3481 return nullptr;
3482}
3483
3484int QQuickItemPrivate::transform_count(QQmlListProperty<QQuickTransform> *prop)
3485{
3486 QQuickItem *that = static_cast<QQuickItem *>(prop->object);
3487 QQuickItemPrivate *p = QQuickItemPrivate::get(that);
3488
3489 return p->transforms.count();
3490}
3491
3492void QQuickTransform::appendToItem(QQuickItem *item)
3493{
3494 Q_D(QQuickTransform);
3495 if (!item)
3496 return;
3497
3498 QQuickItemPrivate *p = QQuickItemPrivate::get(item);
3499
3500 if (!d->items.isEmpty() && !p->transforms.isEmpty() && p->transforms.contains(this)) {
3501 p->transforms.removeOne(this);
3502 p->transforms.append(this);
3503 } else {
3504 p->transforms.append(this);
3505 d->items.append(item);
3506 }
3507
3508 p->dirty(QQuickItemPrivate::Transform);
3509}
3510
3511void QQuickTransform::prependToItem(QQuickItem *item)
3512{
3513 Q_D(QQuickTransform);
3514 if (!item)
3515 return;
3516
3517 QQuickItemPrivate *p = QQuickItemPrivate::get(item);
3518
3519 if (!d->items.isEmpty() && !p->transforms.isEmpty() && p->transforms.contains(this)) {
3520 p->transforms.removeOne(this);
3521 p->transforms.prepend(this);
3522 } else {
3523 p->transforms.prepend(this);
3524 d->items.append(item);
3525 }
3526
3527 p->dirty(QQuickItemPrivate::Transform);
3528}
3529
3530void QQuickItemPrivate::transform_append(QQmlListProperty<QQuickTransform> *prop, QQuickTransform *transform)
3531{
3532 if (!transform)
3533 return;
3534
3535 QQuickItem *that = static_cast<QQuickItem *>(prop->object);
3536 transform->appendToItem(that);
3537}
3538
3539QQuickTransform *QQuickItemPrivate::transform_at(QQmlListProperty<QQuickTransform> *prop, int idx)
3540{
3541 QQuickItem *that = static_cast<QQuickItem *>(prop->object);
3542 QQuickItemPrivate *p = QQuickItemPrivate::get(that);
3543
3544 if (idx < 0 || idx >= p->transforms.count())
3545 return nullptr;
3546 else
3547 return p->transforms.at(idx);
3548}
3549
3550void QQuickItemPrivate::transform_clear(QQmlListProperty<QQuickTransform> *prop)
3551{
3552 QQuickItem *that = static_cast<QQuickItem *>(prop->object);
3553 QQuickItemPrivate *p = QQuickItemPrivate::get(that);
3554
3555 for (int ii = 0; ii < p->transforms.count(); ++ii) {
3556 QQuickTransform *t = p->transforms.at(ii);
3557 QQuickTransformPrivate *tp = QQuickTransformPrivate::get(t);
3558 tp->items.removeOne(that);
3559 }
3560
3561 p->transforms.clear();
3562
3563 p->dirty(QQuickItemPrivate::Transform);
3564}
3565
3566void QQuickItemPrivate::_q_resourceObjectDeleted(QObject *object)
3567{
3568 if (extra.isAllocated() && extra->resourcesList.contains(object))
3569 extra->resourcesList.removeAll(object);
3570}
3571
3572/*!
3573 \qmlpropertygroup QtQuick::Item::anchors
3574 \qmlproperty AnchorLine QtQuick::Item::anchors.top
3575 \qmlproperty AnchorLine QtQuick::Item::anchors.bottom
3576 \qmlproperty AnchorLine QtQuick::Item::anchors.left
3577 \qmlproperty AnchorLine QtQuick::Item::anchors.right
3578 \qmlproperty AnchorLine QtQuick::Item::anchors.horizontalCenter
3579 \qmlproperty AnchorLine QtQuick::Item::anchors.verticalCenter
3580 \qmlproperty AnchorLine QtQuick::Item::anchors.baseline
3581
3582 \qmlproperty Item QtQuick::Item::anchors.fill
3583 \qmlproperty Item QtQuick::Item::anchors.centerIn
3584
3585 \qmlproperty real QtQuick::Item::anchors.margins
3586 \qmlproperty real QtQuick::Item::anchors.topMargin
3587 \qmlproperty real QtQuick::Item::anchors.bottomMargin
3588 \qmlproperty real QtQuick::Item::anchors.leftMargin
3589 \qmlproperty real QtQuick::Item::anchors.rightMargin
3590 \qmlproperty real QtQuick::Item::anchors.horizontalCenterOffset
3591 \qmlproperty real QtQuick::Item::anchors.verticalCenterOffset
3592 \qmlproperty real QtQuick::Item::anchors.baselineOffset
3593
3594 \qmlproperty bool QtQuick::Item::anchors.alignWhenCentered
3595
3596 Anchors provide a way to position an item by specifying its
3597 relationship with other items.
3598
3599 Margins apply to top, bottom, left, right, and fill anchors.
3600 The \l anchors.margins property can be used to set all of the various margins at once, to the same value.
3601 It will not override a specific margin that has been previously set; to clear an explicit margin
3602 set its value to \c undefined.
3603 Note that margins are anchor-specific and are not applied if an item does not
3604 use anchors.
3605
3606 Offsets apply for horizontal center, vertical center, and baseline anchors.
3607
3608 \table
3609 \row
3610 \li \image declarative-anchors_example.png
3611 \li Text anchored to Image, horizontally centered and vertically below, with a margin.
3612 \qml
3613 Item {
3614 Image {
3615 id: pic
3616 // ...
3617 }
3618 Text {
3619 id: label
3620 anchors.horizontalCenter: pic.horizontalCenter
3621 anchors.top: pic.bottom
3622 anchors.topMargin: 5
3623 // ...
3624 }
3625 }
3626 \endqml
3627 \row
3628 \li \image declarative-anchors_example2.png
3629 \li
3630 Left of Text anchored to right of Image, with a margin. The y
3631 property of both defaults to 0.
3632
3633 \qml
3634 Item {
3635 Image {
3636 id: pic
3637 // ...
3638 }
3639 Text {
3640 id: label
3641 anchors.left: pic.right
3642 anchors.leftMargin: 5
3643 // ...
3644 }
3645 }
3646 \endqml
3647 \endtable
3648
3649 \l anchors.fill provides a convenient way for one item to have the
3650 same geometry as another item, and is equivalent to connecting all
3651 four directional anchors.
3652
3653 To clear an anchor value, set it to \c undefined.
3654
3655 \l anchors.alignWhenCentered (default \c true) forces centered anchors to align to a
3656 whole pixel; if the item being centered has an odd \l width or \l height, the item
3657 will be positioned on a whole pixel rather than being placed on a half-pixel.
3658 This ensures the item is painted crisply. There are cases where this is not
3659 desirable, for example when rotating the item jitters may be apparent as the
3660 center is rounded.
3661
3662 \note You can only anchor an item to siblings or a parent.
3663
3664 For more information see \l {anchor-layout}{Anchor Layouts}.
3665*/
3666QQuickAnchors *QQuickItemPrivate::anchors() const
3667{
3668 if (!_anchors) {
3669 Q_Q(const QQuickItem);
3670 _anchors = new QQuickAnchors(const_cast<QQuickItem *>(q));
3671 if (!componentComplete)
3672 _anchors->classBegin();
3673 }
3674 return _anchors;
3675}
3676
3677void QQuickItemPrivate::siblingOrderChanged()
3678{
3679 Q_Q(QQuickItem);
3680 if (!changeListeners.isEmpty()) {
3681 const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732)
3682 for (const QQuickItemPrivate::ChangeListener &change : listeners) {
3683 if (change.types & QQuickItemPrivate::SiblingOrder) {
3684 change.listener->itemSiblingOrderChanged(q);
3685 }
3686 }
3687 }
3688}
3689
3690QQmlListProperty<QObject> QQuickItemPrivate::data()
3691{
3692 return QQmlListProperty<QObject>(q_func