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