1 // Commit: c44be8c0b27756a2025ebad1945632f3f7e4bebc
2 /****************************************************************************
4 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
5 ** All rights reserved.
6 ** Contact: Nokia Corporation (qt-info@nokia.com)
8 ** This file is part of the QtDeclarative module of the Qt Toolkit.
10 ** $QT_BEGIN_LICENSE:LGPL$
11 ** No Commercial Usage
12 ** This file contains pre-release code and may not be distributed.
13 ** You may use this file in accordance with the terms and conditions
14 ** contained in the Technology Preview License Agreement accompanying
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 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights. These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
41 ****************************************************************************/
45 #include "qsgcanvas.h"
46 #include <QtScript/qscriptengine.h>
47 #include "qsgcanvas_p.h"
49 #include "qsgevents_p_p.h"
51 #include <QtDeclarative/qdeclarativeitem.h>
52 #include <QtDeclarative/qdeclarativeengine.h>
53 #include <QtDeclarative/qdeclarativeview.h>
54 #include <QtDeclarative/qdeclarativecomponent.h>
55 #include <QtDeclarative/qdeclarativeinfo.h>
56 #include <QtGui/qgraphicstransform.h>
57 #include <QtGui/qpen.h>
58 #include <QtGui/qinputcontext.h>
59 #include <QtCore/qdebug.h>
60 #include <QtCore/qcoreevent.h>
61 #include <QtCore/qnumeric.h>
63 #include <private/qdeclarativeengine_p.h>
64 #include <private/qdeclarativestategroup_p.h>
65 #include <private/qdeclarativeopenmetaobject_p.h>
66 #include <private/qdeclarativestate_p.h>
67 #include <private/qlistmodelinterface_p.h>
68 #include <private/qsgitem_p.h>
72 // XXX todo Readd parentNotifier for faster parent bindings
73 // XXX todo Check that elements that create items handle memory correctly after visual ownership change
77 QSGTransformPrivate::QSGTransformPrivate()
81 QSGTransform::QSGTransform(QObject *parent)
82 : QObject(*(new QSGTransformPrivate), parent)
86 QSGTransform::QSGTransform(QSGTransformPrivate &dd, QObject *parent)
91 QSGTransform::~QSGTransform()
94 for (int ii = 0; ii < d->items.count(); ++ii) {
95 QSGItemPrivate *p = QSGItemPrivate::get(d->items.at(ii));
96 p->transforms.removeOne(this);
97 p->dirty(QSGItemPrivate::Transform);
101 void QSGTransform::update()
104 for (int ii = 0; ii < d->items.count(); ++ii) {
105 QSGItemPrivate *p = QSGItemPrivate::get(d->items.at(ii));
106 p->dirty(QSGItemPrivate::Transform);
110 QSGContents::QSGContents(QSGItem *item)
111 : m_item(item), m_x(0), m_y(0), m_width(0), m_height(0)
114 connect(this, SIGNAL(rectChanged(QRectF)), m_item, SIGNAL(childrenRectChanged(QRectF)));
117 QSGContents::~QSGContents()
119 QList<QSGItem *> children = m_item->childItems();
120 for (int i = 0; i < children.count(); ++i) {
121 QSGItem *child = children.at(i);
122 QSGItemPrivate::get(child)->removeItemChangeListener(this, QSGItemPrivate::Geometry | QSGItemPrivate::Destroyed);
126 QRectF QSGContents::rectF() const
128 return QRectF(m_x, m_y, m_width, m_height);
131 void QSGContents::calcHeight(QSGItem *changed)
134 qreal oldheight = m_height;
138 qreal bottom = oldy + oldheight;
139 qreal y = changed->y();
140 if (y + changed->height() > bottom)
141 bottom = y + changed->height();
145 m_height = bottom - top;
149 QList<QSGItem *> children = m_item->childItems();
150 for (int i = 0; i < children.count(); ++i) {
151 QSGItem *child = children.at(i);
152 qreal y = child->y();
153 if (y + child->height() > bottom)
154 bottom = y + child->height();
158 if (!children.isEmpty())
160 m_height = qMax(bottom - top, qreal(0.0));
163 if (m_height != oldheight || m_y != oldy)
164 emit rectChanged(rectF());
167 void QSGContents::calcWidth(QSGItem *changed)
170 qreal oldwidth = m_width;
174 qreal right = oldx + oldwidth;
175 qreal x = changed->x();
176 if (x + changed->width() > right)
177 right = x + changed->width();
181 m_width = right - left;
183 qreal left = FLT_MAX;
185 QList<QSGItem *> children = m_item->childItems();
186 for (int i = 0; i < children.count(); ++i) {
187 QSGItem *child = children.at(i);
188 qreal x = child->x();
189 if (x + child->width() > right)
190 right = x + child->width();
194 if (!children.isEmpty())
196 m_width = qMax(right - left, qreal(0.0));
199 if (m_width != oldwidth || m_x != oldx)
200 emit rectChanged(rectF());
203 void QSGContents::complete()
205 QList<QSGItem *> children = m_item->childItems();
206 for (int i = 0; i < children.count(); ++i) {
207 QSGItem *child = children.at(i);
208 QSGItemPrivate::get(child)->addItemChangeListener(this, QSGItemPrivate::Geometry | QSGItemPrivate::Destroyed);
209 //###what about changes to visibility?
215 void QSGContents::itemGeometryChanged(QSGItem *changed, const QRectF &newGeometry, const QRectF &oldGeometry)
218 //### we can only pass changed if the left edge has moved left, or the right edge has moved right
219 if (newGeometry.width() != oldGeometry.width() || newGeometry.x() != oldGeometry.x())
220 calcWidth(/*changed*/);
221 if (newGeometry.height() != oldGeometry.height() || newGeometry.y() != oldGeometry.y())
222 calcHeight(/*changed*/);
225 void QSGContents::itemDestroyed(QSGItem *item)
228 QSGItemPrivate::get(item)->removeItemChangeListener(this, QSGItemPrivate::Geometry | QSGItemPrivate::Destroyed);
232 void QSGContents::childRemoved(QSGItem *item)
235 QSGItemPrivate::get(item)->removeItemChangeListener(this, QSGItemPrivate::Geometry | QSGItemPrivate::Destroyed);
239 void QSGContents::childAdded(QSGItem *item)
242 QSGItemPrivate::get(item)->addItemChangeListener(this, QSGItemPrivate::Geometry | QSGItemPrivate::Destroyed);
247 QSGItemKeyFilter::QSGItemKeyFilter(QSGItem *item)
248 : m_processPost(false), m_next(0)
250 QSGItemPrivate *p = item?QSGItemPrivate::get(item):0;
252 m_next = p->keyHandler;
253 p->keyHandler = this;
257 QSGItemKeyFilter::~QSGItemKeyFilter()
261 void QSGItemKeyFilter::keyPressed(QKeyEvent *event, bool post)
263 if (m_next) m_next->keyPressed(event, post);
266 void QSGItemKeyFilter::keyReleased(QKeyEvent *event, bool post)
268 if (m_next) m_next->keyReleased(event, post);
271 void QSGItemKeyFilter::inputMethodEvent(QInputMethodEvent *event, bool post)
274 m_next->inputMethodEvent(event, post);
279 QVariant QSGItemKeyFilter::inputMethodQuery(Qt::InputMethodQuery query) const
281 if (m_next) return m_next->inputMethodQuery(query);
285 void QSGItemKeyFilter::componentComplete()
287 if (m_next) m_next->componentComplete();
290 QSGKeyNavigationAttached::QSGKeyNavigationAttached(QObject *parent)
291 : QObject(*(new QSGKeyNavigationAttachedPrivate), parent),
292 QSGItemKeyFilter(qobject_cast<QSGItem*>(parent))
294 m_processPost = true;
297 QSGKeyNavigationAttached *
298 QSGKeyNavigationAttached::qmlAttachedProperties(QObject *obj)
300 return new QSGKeyNavigationAttached(obj);
303 QSGItem *QSGKeyNavigationAttached::left() const
305 Q_D(const QSGKeyNavigationAttached);
309 void QSGKeyNavigationAttached::setLeft(QSGItem *i)
311 Q_D(QSGKeyNavigationAttached);
316 QSGKeyNavigationAttached* other =
317 qobject_cast<QSGKeyNavigationAttached*>(qmlAttachedPropertiesObject<QSGKeyNavigationAttached>(i));
318 if (other && !other->d_func()->rightSet){
319 other->d_func()->right = qobject_cast<QSGItem*>(parent());
320 emit other->rightChanged();
325 QSGItem *QSGKeyNavigationAttached::right() const
327 Q_D(const QSGKeyNavigationAttached);
331 void QSGKeyNavigationAttached::setRight(QSGItem *i)
333 Q_D(QSGKeyNavigationAttached);
338 QSGKeyNavigationAttached* other =
339 qobject_cast<QSGKeyNavigationAttached*>(qmlAttachedPropertiesObject<QSGKeyNavigationAttached>(i));
340 if (other && !other->d_func()->leftSet){
341 other->d_func()->left = qobject_cast<QSGItem*>(parent());
342 emit other->leftChanged();
347 QSGItem *QSGKeyNavigationAttached::up() const
349 Q_D(const QSGKeyNavigationAttached);
353 void QSGKeyNavigationAttached::setUp(QSGItem *i)
355 Q_D(QSGKeyNavigationAttached);
360 QSGKeyNavigationAttached* other =
361 qobject_cast<QSGKeyNavigationAttached*>(qmlAttachedPropertiesObject<QSGKeyNavigationAttached>(i));
362 if (other && !other->d_func()->downSet){
363 other->d_func()->down = qobject_cast<QSGItem*>(parent());
364 emit other->downChanged();
369 QSGItem *QSGKeyNavigationAttached::down() const
371 Q_D(const QSGKeyNavigationAttached);
375 void QSGKeyNavigationAttached::setDown(QSGItem *i)
377 Q_D(QSGKeyNavigationAttached);
382 QSGKeyNavigationAttached* other =
383 qobject_cast<QSGKeyNavigationAttached*>(qmlAttachedPropertiesObject<QSGKeyNavigationAttached>(i));
384 if(other && !other->d_func()->upSet){
385 other->d_func()->up = qobject_cast<QSGItem*>(parent());
386 emit other->upChanged();
391 QSGItem *QSGKeyNavigationAttached::tab() const
393 Q_D(const QSGKeyNavigationAttached);
397 void QSGKeyNavigationAttached::setTab(QSGItem *i)
399 Q_D(QSGKeyNavigationAttached);
404 QSGKeyNavigationAttached* other =
405 qobject_cast<QSGKeyNavigationAttached*>(qmlAttachedPropertiesObject<QSGKeyNavigationAttached>(i));
406 if(other && !other->d_func()->backtabSet){
407 other->d_func()->backtab = qobject_cast<QSGItem*>(parent());
408 emit other->backtabChanged();
413 QSGItem *QSGKeyNavigationAttached::backtab() const
415 Q_D(const QSGKeyNavigationAttached);
419 void QSGKeyNavigationAttached::setBacktab(QSGItem *i)
421 Q_D(QSGKeyNavigationAttached);
425 d->backtabSet = true;
426 QSGKeyNavigationAttached* other =
427 qobject_cast<QSGKeyNavigationAttached*>(qmlAttachedPropertiesObject<QSGKeyNavigationAttached>(i));
428 if(other && !other->d_func()->tabSet){
429 other->d_func()->tab = qobject_cast<QSGItem*>(parent());
430 emit other->tabChanged();
432 emit backtabChanged();
435 QSGKeyNavigationAttached::Priority QSGKeyNavigationAttached::priority() const
437 return m_processPost ? AfterItem : BeforeItem;
440 void QSGKeyNavigationAttached::setPriority(Priority order)
442 bool processPost = order == AfterItem;
443 if (processPost != m_processPost) {
444 m_processPost = processPost;
445 emit priorityChanged();
449 void QSGKeyNavigationAttached::keyPressed(QKeyEvent *event, bool post)
451 Q_D(QSGKeyNavigationAttached);
454 if (post != m_processPost) {
455 QSGItemKeyFilter::keyPressed(event, post);
460 switch(event->key()) {
462 if (QSGItem *parentItem = qobject_cast<QSGItem*>(parent()))
463 mirror = QSGItemPrivate::get(parentItem)->effectiveLayoutMirror;
464 QSGItem* leftItem = mirror ? d->right : d->left;
466 setFocusNavigation(leftItem, mirror ? "right" : "left");
471 case Qt::Key_Right: {
472 if (QSGItem *parentItem = qobject_cast<QSGItem*>(parent()))
473 mirror = QSGItemPrivate::get(parentItem)->effectiveLayoutMirror;
474 QSGItem* rightItem = mirror ? d->left : d->right;
476 setFocusNavigation(rightItem, mirror ? "left" : "right");
483 setFocusNavigation(d->up, "up");
489 setFocusNavigation(d->down, "down");
495 setFocusNavigation(d->tab, "tab");
499 case Qt::Key_Backtab:
501 setFocusNavigation(d->backtab, "backtab");
509 if (!event->isAccepted()) QSGItemKeyFilter::keyPressed(event, post);
512 void QSGKeyNavigationAttached::keyReleased(QKeyEvent *event, bool post)
514 Q_D(QSGKeyNavigationAttached);
517 if (post != m_processPost) {
518 QSGItemKeyFilter::keyReleased(event, post);
523 switch(event->key()) {
525 if (QSGItem *parentItem = qobject_cast<QSGItem*>(parent()))
526 mirror = QSGItemPrivate::get(parentItem)->effectiveLayoutMirror;
527 if (mirror ? d->right : d->left)
531 if (QSGItem *parentItem = qobject_cast<QSGItem*>(parent()))
532 mirror = QSGItemPrivate::get(parentItem)->effectiveLayoutMirror;
533 if (mirror ? d->left : d->right)
551 case Qt::Key_Backtab:
560 if (!event->isAccepted()) QSGItemKeyFilter::keyReleased(event, post);
563 void QSGKeyNavigationAttached::setFocusNavigation(QSGItem *currentItem, const char *dir)
565 QSGItem *initialItem = currentItem;
566 bool isNextItem = false;
569 if (currentItem->isVisible() && currentItem->isEnabled()) {
570 currentItem->setFocus(true);
573 qmlAttachedPropertiesObject<QSGKeyNavigationAttached>(currentItem, false);
575 QSGItem *tempItem = qvariant_cast<QSGItem*>(attached->property(dir));
577 currentItem = tempItem;
583 while (currentItem != initialItem && isNextItem);
586 const QSGKeysAttached::SigMap QSGKeysAttached::sigMap[] = {
587 { Qt::Key_Left, "leftPressed" },
588 { Qt::Key_Right, "rightPressed" },
589 { Qt::Key_Up, "upPressed" },
590 { Qt::Key_Down, "downPressed" },
591 { Qt::Key_Tab, "tabPressed" },
592 { Qt::Key_Backtab, "backtabPressed" },
593 { Qt::Key_Asterisk, "asteriskPressed" },
594 { Qt::Key_NumberSign, "numberSignPressed" },
595 { Qt::Key_Escape, "escapePressed" },
596 { Qt::Key_Return, "returnPressed" },
597 { Qt::Key_Enter, "enterPressed" },
598 { Qt::Key_Delete, "deletePressed" },
599 { Qt::Key_Space, "spacePressed" },
600 { Qt::Key_Back, "backPressed" },
601 { Qt::Key_Cancel, "cancelPressed" },
602 { Qt::Key_Select, "selectPressed" },
603 { Qt::Key_Yes, "yesPressed" },
604 { Qt::Key_No, "noPressed" },
605 { Qt::Key_Context1, "context1Pressed" },
606 { Qt::Key_Context2, "context2Pressed" },
607 { Qt::Key_Context3, "context3Pressed" },
608 { Qt::Key_Context4, "context4Pressed" },
609 { Qt::Key_Call, "callPressed" },
610 { Qt::Key_Hangup, "hangupPressed" },
611 { Qt::Key_Flip, "flipPressed" },
612 { Qt::Key_Menu, "menuPressed" },
613 { Qt::Key_VolumeUp, "volumeUpPressed" },
614 { Qt::Key_VolumeDown, "volumeDownPressed" },
618 bool QSGKeysAttachedPrivate::isConnected(const char *signalName)
620 return isSignalConnected(signalIndex(signalName));
623 QSGKeysAttached::QSGKeysAttached(QObject *parent)
624 : QObject(*(new QSGKeysAttachedPrivate), parent),
625 QSGItemKeyFilter(qobject_cast<QSGItem*>(parent))
627 Q_D(QSGKeysAttached);
628 m_processPost = false;
629 d->item = qobject_cast<QSGItem*>(parent);
632 QSGKeysAttached::~QSGKeysAttached()
636 QSGKeysAttached::Priority QSGKeysAttached::priority() const
638 return m_processPost ? AfterItem : BeforeItem;
641 void QSGKeysAttached::setPriority(Priority order)
643 bool processPost = order == AfterItem;
644 if (processPost != m_processPost) {
645 m_processPost = processPost;
646 emit priorityChanged();
650 void QSGKeysAttached::componentComplete()
652 Q_D(QSGKeysAttached);
654 for (int ii = 0; ii < d->targets.count(); ++ii) {
655 QSGItem *targetItem = d->targets.at(ii);
656 if (targetItem && (targetItem->flags() & QSGItem::ItemAcceptsInputMethod)) {
657 d->item->setFlag(QSGItem::ItemAcceptsInputMethod);
664 void QSGKeysAttached::keyPressed(QKeyEvent *event, bool post)
666 Q_D(QSGKeysAttached);
667 if (post != m_processPost || !d->enabled || d->inPress) {
669 QSGItemKeyFilter::keyPressed(event, post);
673 // first process forwards
674 if (d->item && d->item->canvas()) {
676 for (int ii = 0; ii < d->targets.count(); ++ii) {
677 QSGItem *i = d->targets.at(ii);
678 if (i && i->isVisible()) {
679 d->item->canvas()->sendEvent(i, event);
680 if (event->isAccepted()) {
689 QSGKeyEvent ke(*event);
690 QByteArray keySignal = keyToSignal(event->key());
691 if (!keySignal.isEmpty()) {
692 keySignal += "(QSGKeyEvent*)";
693 if (d->isConnected(keySignal)) {
694 // If we specifically handle a key then default to accepted
695 ke.setAccepted(true);
696 int idx = QSGKeysAttached::staticMetaObject.indexOfSignal(keySignal);
697 metaObject()->method(idx).invoke(this, Qt::DirectConnection, Q_ARG(QSGKeyEvent*, &ke));
700 if (!ke.isAccepted())
702 event->setAccepted(ke.isAccepted());
704 if (!event->isAccepted()) QSGItemKeyFilter::keyPressed(event, post);
707 void QSGKeysAttached::keyReleased(QKeyEvent *event, bool post)
709 Q_D(QSGKeysAttached);
710 if (post != m_processPost || !d->enabled || d->inRelease) {
712 QSGItemKeyFilter::keyReleased(event, post);
716 if (d->item && d->item->canvas()) {
718 for (int ii = 0; ii < d->targets.count(); ++ii) {
719 QSGItem *i = d->targets.at(ii);
720 if (i && i->isVisible()) {
721 d->item->canvas()->sendEvent(i, event);
722 if (event->isAccepted()) {
723 d->inRelease = false;
728 d->inRelease = false;
731 QSGKeyEvent ke(*event);
733 event->setAccepted(ke.isAccepted());
735 if (!event->isAccepted()) QSGItemKeyFilter::keyReleased(event, post);
738 void QSGKeysAttached::inputMethodEvent(QInputMethodEvent *event, bool post)
740 Q_D(QSGKeysAttached);
741 if (post == m_processPost && d->item && !d->inIM && d->item->canvas()) {
743 for (int ii = 0; ii < d->targets.count(); ++ii) {
744 QSGItem *i = d->targets.at(ii);
745 if (i && i->isVisible() && (i->flags() & QSGItem::ItemAcceptsInputMethod)) {
746 d->item->canvas()->sendEvent(i, event);
747 if (event->isAccepted()) {
756 QSGItemKeyFilter::inputMethodEvent(event, post);
759 QVariant QSGKeysAttached::inputMethodQuery(Qt::InputMethodQuery query) const
761 Q_D(const QSGKeysAttached);
763 for (int ii = 0; ii < d->targets.count(); ++ii) {
764 QSGItem *i = d->targets.at(ii);
765 if (i && i->isVisible() && (i->flags() & QSGItem::ItemAcceptsInputMethod) && i == d->imeItem) {
766 //### how robust is i == d->imeItem check?
767 QVariant v = i->inputMethodQuery(query);
768 if (v.userType() == QVariant::RectF)
769 v = d->item->mapRectFromItem(i, v.toRectF()); //### cost?
774 return QSGItemKeyFilter::inputMethodQuery(query);
777 QSGKeysAttached *QSGKeysAttached::qmlAttachedProperties(QObject *obj)
779 return new QSGKeysAttached(obj);
783 QSGLayoutMirroringAttached::QSGLayoutMirroringAttached(QObject *parent) : QObject(parent), itemPrivate(0)
785 if (QSGItem *item = qobject_cast<QSGItem*>(parent)) {
786 itemPrivate = QSGItemPrivate::get(item);
787 itemPrivate->attachedLayoutDirection = this;
789 qmlInfo(parent) << tr("LayoutDirection attached property only works with Items");
792 QSGLayoutMirroringAttached * QSGLayoutMirroringAttached::qmlAttachedProperties(QObject *object)
794 return new QSGLayoutMirroringAttached(object);
797 bool QSGLayoutMirroringAttached::enabled() const
799 return itemPrivate ? itemPrivate->effectiveLayoutMirror : false;
802 void QSGLayoutMirroringAttached::setEnabled(bool enabled)
807 itemPrivate->isMirrorImplicit = false;
808 if (enabled != itemPrivate->effectiveLayoutMirror) {
809 itemPrivate->setLayoutMirror(enabled);
810 if (itemPrivate->inheritMirrorFromItem)
811 itemPrivate->resolveLayoutMirror();
815 void QSGLayoutMirroringAttached::resetEnabled()
817 if (itemPrivate && !itemPrivate->isMirrorImplicit) {
818 itemPrivate->isMirrorImplicit = true;
819 itemPrivate->resolveLayoutMirror();
823 bool QSGLayoutMirroringAttached::childrenInherit() const
825 return itemPrivate ? itemPrivate->inheritMirrorFromItem : false;
828 void QSGLayoutMirroringAttached::setChildrenInherit(bool childrenInherit) {
829 if (itemPrivate && childrenInherit != itemPrivate->inheritMirrorFromItem) {
830 itemPrivate->inheritMirrorFromItem = childrenInherit;
831 itemPrivate->resolveLayoutMirror();
832 childrenInheritChanged();
836 void QSGItemPrivate::resolveLayoutMirror()
839 if (QSGItem *parentItem = q->parentItem()) {
840 QSGItemPrivate *parentPrivate = QSGItemPrivate::get(parentItem);
841 setImplicitLayoutMirror(parentPrivate->inheritedLayoutMirror, parentPrivate->inheritMirrorFromParent);
843 setImplicitLayoutMirror(isMirrorImplicit ? false : effectiveLayoutMirror, inheritMirrorFromItem);
847 void QSGItemPrivate::setImplicitLayoutMirror(bool mirror, bool inherit)
849 inherit = inherit || inheritMirrorFromItem;
850 if (!isMirrorImplicit && inheritMirrorFromItem)
851 mirror = effectiveLayoutMirror;
852 if (mirror == inheritedLayoutMirror && inherit == inheritMirrorFromParent)
855 inheritMirrorFromParent = inherit;
856 inheritedLayoutMirror = inheritMirrorFromParent ? mirror : false;
858 if (isMirrorImplicit)
859 setLayoutMirror(inherit ? inheritedLayoutMirror : false);
860 for (int i = 0; i < childItems.count(); ++i) {
861 if (QSGItem *child = qobject_cast<QSGItem *>(childItems.at(i))) {
862 QSGItemPrivate *childPrivate = QSGItemPrivate::get(child);
863 childPrivate->setImplicitLayoutMirror(inheritedLayoutMirror, inheritMirrorFromParent);
868 void QSGItemPrivate::setLayoutMirror(bool mirror)
870 if (mirror != effectiveLayoutMirror) {
871 effectiveLayoutMirror = mirror;
873 QSGAnchorsPrivate *anchor_d = QSGAnchorsPrivate::get(_anchors);
874 anchor_d->fillChanged();
875 anchor_d->centerInChanged();
876 anchor_d->updateHorizontalAnchors();
877 emit _anchors->mirroredChanged();
880 if (attachedLayoutDirection) {
881 emit attachedLayoutDirection->enabledChanged();
886 QSGItem::QSGItem(QSGItem* parent)
887 : QObject(*(new QSGItemPrivate), parent)
893 QSGItem::QSGItem(QSGItemPrivate &dd, QSGItem *parent)
894 : QObject(dd, parent)
904 // XXX todo - optimize
906 while (!d->childItems.isEmpty())
907 d->childItems.first()->setParentItem(0);
909 for (int ii = 0; ii < d->changeListeners.count(); ++ii) {
910 QSGAnchorsPrivate *anchor = d->changeListeners.at(ii).listener->anchorPrivate();
912 anchor->clearItem(this);
915 // XXX todo - the original checks if the parent is being destroyed
916 for (int ii = 0; ii < d->changeListeners.count(); ++ii) {
917 QSGAnchorsPrivate *anchor = d->changeListeners.at(ii).listener->anchorPrivate();
918 if (anchor && anchor->item && anchor->item->parent() != this) //child will be deleted anyway
919 anchor->updateOnComplete();
922 for (int ii = 0; ii < d->changeListeners.count(); ++ii) {
923 const QSGItemPrivate::ChangeListener &change = d->changeListeners.at(ii);
924 if (change.types & QSGItemPrivate::Destroyed)
925 change.listener->itemDestroyed(this);
927 d->changeListeners.clear();
928 delete d->_anchorLines; d->_anchorLines = 0;
929 delete d->_anchors; d->_anchors = 0;
930 delete d->_stateGroup; d->_stateGroup = 0;
931 delete d->_contents; d->_contents = 0;
934 void QSGItem::setParentItem(QSGItem *parentItem)
937 if (parentItem == d->parentItem)
940 d->removeFromDirtyList();
942 QSGItem *oldParentItem = d->parentItem;
943 QSGItem *scopeFocusedItem = 0;
946 QSGItemPrivate *op = QSGItemPrivate::get(oldParentItem);
948 QSGItem *scopeItem = 0;
950 if (d->canvas && hasFocus()) {
951 scopeItem = oldParentItem;
952 while (!scopeItem->isFocusScope()) scopeItem = scopeItem->parentItem();
953 scopeFocusedItem = this;
954 } else if (d->canvas && !isFocusScope() && d->subFocusItem) {
955 scopeItem = oldParentItem;
956 while (!scopeItem->isFocusScope()) scopeItem = scopeItem->parentItem();
957 scopeFocusedItem = d->subFocusItem;
960 if (scopeFocusedItem)
961 QSGCanvasPrivate::get(d->canvas)->clearFocusInScope(scopeItem, scopeFocusedItem,
962 QSGCanvasPrivate::DontChangeFocusProperty);
964 op->removeChild(this);
967 d->parentItem = parentItem;
969 QSGCanvas *parentCanvas = parentItem?QSGItemPrivate::get(parentItem)->canvas:0;
970 if (d->canvas != parentCanvas) {
971 if (d->canvas && d->itemNodeInstance)
972 QSGCanvasPrivate::get(d->canvas)->cleanup(d->itemNodeInstance);
974 QSGItemPrivate::InitializationState initState;
976 d->initCanvas(&initState, parentCanvas);
979 d->dirty(QSGItemPrivate::ParentChanged);
982 QSGItemPrivate::get(d->parentItem)->addChild(this);
984 d->setEffectiveVisibleRecur(d->calcEffectiveVisible());
985 d->setEffectiveEnableRecur(d->calcEffectiveEnable());
987 if (scopeFocusedItem && d->parentItem && d->canvas) {
988 // We need to test whether this item becomes scope focused
989 QSGItem *scopeItem = 0;
990 scopeItem = d->parentItem;
991 while (!scopeItem->isFocusScope()) scopeItem = scopeItem->parentItem();
993 if (scopeItem->scopedFocusItem()) {
994 QSGItemPrivate::get(scopeFocusedItem)->focus = false;
995 emit scopeFocusedItem->focusChanged(false);
997 QSGCanvasPrivate::get(d->canvas)->setFocusInScope(scopeItem, scopeFocusedItem,
998 QSGCanvasPrivate::DontChangeFocusProperty);
1002 d->resolveLayoutMirror();
1004 d->itemChange(ItemParentHasChanged, d->parentItem);
1006 emit parentChanged(d->parentItem);
1009 void QSGItem::stackBefore(const QSGItem *sibling)
1012 if (!sibling || sibling == this || !d->parentItem || d->parentItem != QSGItemPrivate::get(sibling)->parentItem) {
1013 qWarning("QSGItem::stackBefore: Cannot stack before %p, which must be a sibling", sibling);
1017 QSGItemPrivate *parentPrivate = QSGItemPrivate::get(d->parentItem);
1019 int myIndex = parentPrivate->childItems.indexOf(this);
1020 int siblingIndex = parentPrivate->childItems.indexOf(const_cast<QSGItem *>(sibling));
1022 Q_ASSERT(myIndex != -1 && siblingIndex != -1);
1024 if (myIndex == siblingIndex - 1)
1027 parentPrivate->childItems.removeAt(myIndex);
1029 if (myIndex < siblingIndex) --siblingIndex;
1031 parentPrivate->childItems.insert(siblingIndex, this);
1033 parentPrivate->dirty(QSGItemPrivate::ChildrenStackingChanged);
1035 for (int ii = qMin(siblingIndex, myIndex); ii < parentPrivate->childItems.count(); ++ii)
1036 QSGItemPrivate::get(parentPrivate->childItems.at(ii))->siblingOrderChanged();
1039 void QSGItem::stackAfter(const QSGItem *sibling)
1042 if (!sibling || sibling == this || !d->parentItem || d->parentItem != QSGItemPrivate::get(sibling)->parentItem) {
1043 qWarning("QSGItem::stackAfter: Cannot stack after %p, which must be a sibling", sibling);
1047 QSGItemPrivate *parentPrivate = QSGItemPrivate::get(d->parentItem);
1049 int myIndex = parentPrivate->childItems.indexOf(this);
1050 int siblingIndex = parentPrivate->childItems.indexOf(const_cast<QSGItem *>(sibling));
1052 Q_ASSERT(myIndex != -1 && siblingIndex != -1);
1054 if (myIndex == siblingIndex + 1)
1057 parentPrivate->childItems.removeAt(myIndex);
1059 if (myIndex < siblingIndex) --siblingIndex;
1061 parentPrivate->childItems.insert(siblingIndex + 1, this);
1063 parentPrivate->dirty(QSGItemPrivate::ChildrenStackingChanged);
1065 for (int ii = qMin(myIndex, siblingIndex + 1); ii < parentPrivate->childItems.count(); ++ii)
1066 QSGItemPrivate::get(parentPrivate->childItems.at(ii))->siblingOrderChanged();
1070 Returns the QSGItem parent of this item.
1072 QSGItem *QSGItem::parentItem() const
1075 return d->parentItem;
1078 QSGEngine *QSGItem::sceneGraphEngine() const
1080 return canvas()->sceneGraphEngine();
1083 QSGCanvas *QSGItem::canvas() const
1089 static bool itemZOrder_sort(QSGItem *lhs, QSGItem *rhs)
1091 return lhs->z() < rhs->z();
1094 QList<QSGItem *> QSGItemPrivate::paintOrderChildItems() const
1096 // XXX todo - optimize, don't sort and return items that are
1097 // ignored anyway, like invisible or disabled items.
1098 QList<QSGItem *> items = childItems;
1099 qStableSort(items.begin(), items.end(), itemZOrder_sort);
1103 void QSGItemPrivate::addChild(QSGItem *child)
1107 Q_ASSERT(!childItems.contains(child));
1109 childItems.append(child);
1111 dirty(QSGItemPrivate::ChildrenChanged);
1113 itemChange(QSGItem::ItemChildAddedChange, child);
1115 emit q->childrenChanged();
1118 void QSGItemPrivate::removeChild(QSGItem *child)
1123 Q_ASSERT(childItems.contains(child));
1124 childItems.removeOne(child);
1125 Q_ASSERT(!childItems.contains(child));
1127 dirty(QSGItemPrivate::ChildrenChanged);
1129 itemChange(QSGItem::ItemChildRemovedChange, child);
1131 emit q->childrenChanged();
1134 void QSGItemPrivate::InitializationState::clear()
1139 void QSGItemPrivate::InitializationState::clear(QSGItem *fs)
1144 QSGItem *QSGItemPrivate::InitializationState::getFocusScope(QSGItem *item)
1147 QSGItem *fs = item->parentItem();
1148 while (!fs->isFocusScope())
1149 fs = fs->parentItem();
1155 void QSGItemPrivate::initCanvas(InitializationState *state, QSGCanvas *c)
1160 removeFromDirtyList();
1161 QSGCanvasPrivate *c = QSGCanvasPrivate::get(canvas);
1162 if (polishScheduled)
1163 c->itemsToPolish.remove(q);
1164 if (c->mouseGrabberItem == q)
1165 c->mouseGrabberItem = 0;
1170 if (canvas && polishScheduled)
1171 QSGCanvasPrivate::get(canvas)->itemsToPolish.insert(q);
1173 if (canvas && hoverEnabled && !canvas->hasMouseTracking())
1174 canvas->setMouseTracking(true);
1176 // XXX todo - why aren't these added to the destroy list?
1177 itemNodeInstance = 0;
1185 InitializationState _dummy;
1186 InitializationState *childState = state;
1188 if (c && q->isFocusScope()) {
1190 childState = &_dummy;
1193 for (int ii = 0; ii < childItems.count(); ++ii) {
1194 QSGItem *child = childItems.at(ii);
1195 QSGItemPrivate::get(child)->initCanvas(childState, c);
1200 if (state->getFocusScope(q)->scopedFocusItem()) {
1202 emit q->focusChanged(false);
1204 QSGCanvasPrivate::get(canvas)->setFocusInScope(state->getFocusScope(q), q);
1210 itemChange(QSGItem::ItemSceneChange, c);
1214 Returns a transform that maps points from canvas space into item space.
1216 QTransform QSGItemPrivate::canvasToItemTransform() const
1218 // XXX todo - optimize
1219 return itemToCanvasTransform().inverted();
1223 Returns a transform that maps points from item space into canvas space.
1225 QTransform QSGItemPrivate::itemToCanvasTransform() const
1228 QTransform rv = parentItem?QSGItemPrivate::get(parentItem)->itemToCanvasTransform():QTransform();
1229 itemToParentTransform(rv);
1234 Motifies \a t with this items local transform relative to its parent.
1236 void QSGItemPrivate::itemToParentTransform(QTransform &t) const
1241 if (!transforms.isEmpty()) {
1243 for (int ii = transforms.count() - 1; ii >= 0; --ii)
1244 transforms.at(ii)->applyTo(&m);
1245 t = m.toTransform();
1248 if (scale != 1. || rotation != 0.) {
1249 QPointF tp = computeTransformOrigin();
1250 t.translate(tp.x(), tp.y());
1251 t.scale(scale, scale);
1253 t.translate(-tp.x(), -tp.y());
1257 bool QSGItem::isComponentComplete() const
1260 return d->componentComplete;
1263 QSGItemPrivate::QSGItemPrivate()
1264 : _anchors(0), _contents(0), baselineOffset(0), _anchorLines(0), _stateGroup(0), origin(QSGItem::Center),
1266 flags(0), widthValid(false), heightValid(false), componentComplete(true),
1267 keepMouse(false), hoverEnabled(false), smooth(false), focus(false), activeFocus(false), notifiedFocus(false),
1268 notifiedActiveFocus(false), filtersChildMouseEvents(false), explicitVisible(true),
1269 effectiveVisible(true), explicitEnable(true), effectiveEnable(true), polishScheduled(false),
1270 inheritedLayoutMirror(false), effectiveLayoutMirror(false), isMirrorImplicit(true),
1271 inheritMirrorFromParent(false), inheritMirrorFromItem(false),
1273 canvas(0), parentItem(0),
1277 x(0), y(0), width(0), height(0), implicitWidth(0), implicitHeight(0),
1278 z(0), scale(1), rotation(0), opacity(1),
1280 attachedLayoutDirection(0), acceptedMouseButtons(0),
1281 imHints(Qt::ImhNone),
1285 dirtyAttributes(0), nextDirtyItem(0), prevDirtyItem(0),
1287 itemNodeInstance(0), opacityNode(0), clipNode(0), rootNode(0), groupNode(0), paintNode(0)
1288 , paintNodeIndex(0), effectRefCount(0), hideRefCount(0)
1292 void QSGItemPrivate::init(QSGItem *parent)
1295 baselineOffset.invalidate();
1298 q->setParentItem(parent);
1299 QSGItemPrivate *parentPrivate = QSGItemPrivate::get(parent);
1300 setImplicitLayoutMirror(parentPrivate->inheritedLayoutMirror, parentPrivate->inheritMirrorFromParent);
1304 void QSGItemPrivate::data_append(QDeclarativeListProperty<QObject> *prop, QObject *o)
1309 QSGItem *that = static_cast<QSGItem *>(prop->object);
1311 // This test is measurably (albeit only slightly) faster than qobject_cast<>()
1312 const QMetaObject *mo = o->metaObject();
1313 while (mo && mo != &QSGItem::staticMetaObject) {
1314 if (mo == &QDeclarativeItem::staticMetaObject)
1315 qWarning("Cannot add a QtQuick 1.0 item (%s) into a QtQuick 2.0 scene!", o->metaObject()->className());
1316 mo = mo->d.superdata;
1320 QSGItem *item = static_cast<QSGItem *>(o);
1321 item->setParentItem(that);
1323 // XXX todo - do we really want this behavior?
1328 int QSGItemPrivate::data_count(QDeclarativeListProperty<QObject> *prop)
1335 QObject *QSGItemPrivate::data_at(QDeclarativeListProperty<QObject> *prop, int i)
1343 void QSGItemPrivate::data_clear(QDeclarativeListProperty<QObject> *prop)
1349 QObject *QSGItemPrivate::resources_at(QDeclarativeListProperty<QObject> *prop, int index)
1351 const QObjectList children = prop->object->children();
1352 if (index < children.count())
1353 return children.at(index);
1358 void QSGItemPrivate::resources_append(QDeclarativeListProperty<QObject> *prop, QObject *o)
1360 // XXX todo - do we really want this behavior?
1361 o->setParent(prop->object);
1364 int QSGItemPrivate::resources_count(QDeclarativeListProperty<QObject> *prop)
1366 return prop->object->children().count();
1369 void QSGItemPrivate::resources_clear(QDeclarativeListProperty<QObject> *prop)
1371 // XXX todo - do we really want this behavior?
1372 const QObjectList children = prop->object->children();
1373 for (int index = 0; index < children.count(); index++)
1374 children.at(index)->setParent(0);
1377 QSGItem *QSGItemPrivate::children_at(QDeclarativeListProperty<QSGItem> *prop, int index)
1379 QSGItemPrivate *p = QSGItemPrivate::get(static_cast<QSGItem *>(prop->object));
1380 if (index >= p->childItems.count() || index < 0)
1383 return p->childItems.at(index);
1386 void QSGItemPrivate::children_append(QDeclarativeListProperty<QSGItem> *prop, QSGItem *o)
1391 QSGItem *that = static_cast<QSGItem *>(prop->object);
1392 if (o->parentItem() == that)
1393 o->setParentItem(0);
1395 o->setParentItem(that);
1398 int QSGItemPrivate::children_count(QDeclarativeListProperty<QSGItem> *prop)
1400 QSGItemPrivate *p = QSGItemPrivate::get(static_cast<QSGItem *>(prop->object));
1401 return p->childItems.count();
1404 void QSGItemPrivate::children_clear(QDeclarativeListProperty<QSGItem> *prop)
1406 QSGItem *that = static_cast<QSGItem *>(prop->object);
1407 QSGItemPrivate *p = QSGItemPrivate::get(that);
1408 while (!p->childItems.isEmpty())
1409 p->childItems.at(0)->setParentItem(0);
1412 int QSGItemPrivate::transform_count(QDeclarativeListProperty<QSGTransform> *prop)
1414 QSGItem *that = static_cast<QSGItem *>(prop->object);
1415 return QSGItemPrivate::get(that)->transforms.count();
1418 void QSGTransform::appendToItem(QSGItem *item)
1424 QSGItemPrivate *p = QSGItemPrivate::get(item);
1426 if (!d->items.isEmpty() && !p->transforms.isEmpty() && p->transforms.contains(this)) {
1427 p->transforms.removeOne(this);
1428 p->transforms.append(this);
1430 p->transforms.append(this);
1431 d->items.append(item);
1434 p->dirty(QSGItemPrivate::Transform);
1437 void QSGTransform::prependToItem(QSGItem *item)
1443 QSGItemPrivate *p = QSGItemPrivate::get(item);
1445 if (!d->items.isEmpty() && !p->transforms.isEmpty() && p->transforms.contains(this)) {
1446 p->transforms.removeOne(this);
1447 p->transforms.prepend(this);
1449 p->transforms.prepend(this);
1450 d->items.append(item);
1453 p->dirty(QSGItemPrivate::Transform);
1456 void QSGItemPrivate::transform_append(QDeclarativeListProperty<QSGTransform> *prop, QSGTransform *transform)
1461 QSGItem *that = static_cast<QSGItem *>(prop->object);
1462 transform->appendToItem(that);
1465 QSGTransform *QSGItemPrivate::transform_at(QDeclarativeListProperty<QSGTransform> *prop, int idx)
1467 QSGItem *that = static_cast<QSGItem *>(prop->object);
1468 QSGItemPrivate *p = QSGItemPrivate::get(that);
1470 if (idx < 0 || idx >= p->transforms.count())
1473 return p->transforms.at(idx);
1476 void QSGItemPrivate::transform_clear(QDeclarativeListProperty<QSGTransform> *prop)
1478 QSGItem *that = static_cast<QSGItem *>(prop->object);
1479 QSGItemPrivate *p = QSGItemPrivate::get(that);
1481 for (int ii = 0; ii < p->transforms.count(); ++ii) {
1482 QSGTransform *t = p->transforms.at(ii);
1483 QSGTransformPrivate *tp = QSGTransformPrivate::get(t);
1484 tp->items.removeOne(that);
1487 p->transforms.clear();
1489 p->dirty(QSGItemPrivate::Transform);
1492 QSGAnchors *QSGItemPrivate::anchors() const
1496 _anchors = new QSGAnchors(const_cast<QSGItem *>(q));
1497 if (!componentComplete)
1498 _anchors->classBegin();
1503 QSGItemPrivate::AnchorLines *QSGItemPrivate::anchorLines() const
1506 if (!_anchorLines) _anchorLines =
1507 new AnchorLines(const_cast<QSGItem *>(q));
1508 return _anchorLines;
1511 void QSGItemPrivate::siblingOrderChanged()
1514 for(int ii = 0; ii < changeListeners.count(); ++ii) {
1515 const QSGItemPrivate::ChangeListener &change = changeListeners.at(ii);
1516 if (change.types & QSGItemPrivate::SiblingOrder) {
1517 change.listener->itemSiblingOrderChanged(q);
1522 QDeclarativeListProperty<QObject> QSGItemPrivate::data()
1524 return QDeclarativeListProperty<QObject>(q_func(), 0, QSGItemPrivate::data_append,
1525 QSGItemPrivate::data_count,
1526 QSGItemPrivate::data_at,
1527 QSGItemPrivate::data_clear);
1530 QRectF QSGItem::childrenRect()
1533 if (!d->_contents) {
1534 d->_contents = new QSGContents(this);
1535 if (d->componentComplete)
1536 d->_contents->complete();
1538 return d->_contents->rectF();
1541 QList<QSGItem *> QSGItem::childItems() const
1544 return d->childItems;
1547 bool QSGItem::clip() const
1549 return flags() & ItemClipsChildrenToShape;
1552 void QSGItem::setClip(bool c)
1557 setFlag(ItemClipsChildrenToShape, c);
1559 emit clipChanged(c);
1562 void QSGItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
1567 QSGAnchorsPrivate::get(d->_anchors)->updateMe();
1569 for(int ii = 0; ii < d->changeListeners.count(); ++ii) {
1570 const QSGItemPrivate::ChangeListener &change = d->changeListeners.at(ii);
1571 if (change.types & QSGItemPrivate::Geometry)
1572 change.listener->itemGeometryChanged(this, newGeometry, oldGeometry);
1575 if (newGeometry.x() != oldGeometry.x())
1577 if (newGeometry.y() != oldGeometry.y())
1579 if (newGeometry.width() != oldGeometry.width())
1580 emit widthChanged();
1581 if (newGeometry.height() != oldGeometry.height())
1582 emit heightChanged();
1586 Called by the rendering thread when it is time to sync the state of the QML objects with the
1587 scene graph objects. The function should return the root of the scene graph subtree for
1588 this item. \a oldNode is the node that was returned the last time the function was called.
1590 The main thread is blocked while this function is executed so it is safe to read
1591 values from the QSGItem instance and other objects in the main thread.
1593 \warning This is the only function in which it is allowed to make use of scene graph
1594 objects from the main thread. Use of scene graph objects outside this function will
1595 result in race conditions and potential crashes.
1598 QSGNode *QSGItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
1604 QSGTransformNode *QSGItemPrivate::createTransformNode()
1606 return new QSGTransformNode;
1609 void QSGItem::updatePolish()
1613 void QSGItemPrivate::removeItemChangeListener(QSGItemChangeListener *listener, ChangeTypes types)
1615 ChangeListener change(listener, types);
1616 changeListeners.removeOne(change);
1619 void QSGItem::keyPressEvent(QKeyEvent *event)
1624 void QSGItem::keyReleaseEvent(QKeyEvent *event)
1629 void QSGItem::inputMethodEvent(QInputMethodEvent *event)
1634 void QSGItem::focusInEvent(QFocusEvent *)
1638 void QSGItem::focusOutEvent(QFocusEvent *)
1642 void QSGItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
1647 void QSGItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
1652 void QSGItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
1657 void QSGItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
1659 mousePressEvent(event);
1662 void QSGItem::mouseUngrabEvent()
1667 void QSGItem::wheelEvent(QGraphicsSceneWheelEvent *event)
1672 void QSGItem::touchEvent(QTouchEvent *event)
1677 void QSGItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
1682 void QSGItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
1687 void QSGItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
1692 bool QSGItem::childMouseEventFilter(QSGItem *, QEvent *)
1697 Qt::InputMethodHints QSGItem::inputMethodHints() const
1703 void QSGItem::setInputMethodHints(Qt::InputMethodHints hints)
1708 if (!d->canvas || d->canvas->activeFocusItem() != this)
1711 QSGCanvasPrivate::get(d->canvas)->updateInputMethodData();
1713 if (d->canvas->hasFocus())
1714 if (QInputContext *inputContext = d->canvas->inputContext())
1715 inputContext->update();
1719 void QSGItem::updateMicroFocus()
1723 if (d->canvas && d->canvas->hasFocus())
1724 if (QInputContext *inputContext = d->canvas->inputContext())
1725 inputContext->update();
1729 QVariant QSGItem::inputMethodQuery(Qt::InputMethodQuery query) const
1735 v = d->keyHandler->inputMethodQuery(query);
1740 QSGAnchorLine QSGItemPrivate::left() const
1742 return anchorLines()->left;
1745 QSGAnchorLine QSGItemPrivate::right() const
1747 return anchorLines()->right;
1750 QSGAnchorLine QSGItemPrivate::horizontalCenter() const
1752 return anchorLines()->hCenter;
1755 QSGAnchorLine QSGItemPrivate::top() const
1757 return anchorLines()->top;
1760 QSGAnchorLine QSGItemPrivate::bottom() const
1762 return anchorLines()->bottom;
1765 QSGAnchorLine QSGItemPrivate::verticalCenter() const
1767 return anchorLines()->vCenter;
1770 QSGAnchorLine QSGItemPrivate::baseline() const
1772 return anchorLines()->baseline;
1775 qreal QSGItem::baselineOffset() const
1778 if (!d->baselineOffset.isValid()) {
1781 return d->baselineOffset;
1784 void QSGItem::setBaselineOffset(qreal offset)
1787 if (offset == d->baselineOffset)
1790 d->baselineOffset = offset;
1792 for(int ii = 0; ii < d->changeListeners.count(); ++ii) {
1793 const QSGItemPrivate::ChangeListener &change = d->changeListeners.at(ii);
1794 if (change.types & QSGItemPrivate::Geometry) {
1795 QSGAnchorsPrivate *anchor = change.listener->anchorPrivate();
1797 anchor->updateVerticalAnchors();
1800 emit baselineOffsetChanged(offset);
1803 void QSGItem::update()
1806 Q_ASSERT(flags() & ItemHasContents);
1807 d->dirty(QSGItemPrivate::Content);
1810 void QSGItem::polish()
1813 if (!d->polishScheduled) {
1814 d->polishScheduled = true;
1816 QSGCanvasPrivate::get(d->canvas)->itemsToPolish.insert(this);
1820 QScriptValue QSGItem::mapFromItem(const QScriptValue &item, qreal x, qreal y) const
1822 QScriptValue sv = QDeclarativeEnginePrivate::getScriptEngine(qmlEngine(this))->newObject();
1823 QSGItem *itemObj = qobject_cast<QSGItem*>(item.toQObject());
1824 if (!itemObj && !item.isNull()) {
1825 qmlInfo(this) << "mapFromItem() given argument \"" << item.toString() << "\" which is neither null nor an Item";
1829 // If QSGItem::mapFromItem() is called with 0, behaves the same as mapFromScene()
1830 QPointF p = mapFromItem(itemObj, QPointF(x, y));
1831 sv.setProperty(QLatin1String("x"), p.x());
1832 sv.setProperty(QLatin1String("y"), p.y());
1836 QTransform QSGItem::itemTransform(QSGItem *other, bool *ok) const
1840 // XXX todo - we need to be able to handle common parents better and detect
1844 QTransform t = d->itemToCanvasTransform();
1845 if (other) t *= QSGItemPrivate::get(other)->canvasToItemTransform();
1850 QScriptValue QSGItem::mapToItem(const QScriptValue &item, qreal x, qreal y) const
1852 QScriptValue sv = QDeclarativeEnginePrivate::getScriptEngine(qmlEngine(this))->newObject();
1853 QSGItem *itemObj = qobject_cast<QSGItem*>(item.toQObject());
1854 if (!itemObj && !item.isNull()) {
1855 qmlInfo(this) << "mapToItem() given argument \"" << item.toString() << "\" which is neither null nor an Item";
1859 // If QSGItem::mapToItem() is called with 0, behaves the same as mapToScene()
1860 QPointF p = mapToItem(itemObj, QPointF(x, y));
1861 sv.setProperty(QLatin1String("x"), p.x());
1862 sv.setProperty(QLatin1String("y"), p.y());
1866 void QSGItem::forceActiveFocus()
1869 QSGItem *parent = parentItem();
1871 if (parent->flags() & QSGItem::ItemIsFocusScope) {
1872 parent->setFocus(true);
1874 parent = parent->parentItem();
1878 QSGItem *QSGItem::childAt(qreal x, qreal y) const
1880 // XXX todo - should this include transform etc.?
1881 const QList<QSGItem *> children = childItems();
1882 for (int i = children.count()-1; i >= 0; --i) {
1883 if (QSGItem *child = qobject_cast<QSGItem *>(children.at(i))) {
1884 if (child->isVisible() && child->x() <= x
1885 && child->x() + child->width() >= x
1887 && child->y() + child->height() >= y)
1894 QDeclarativeListProperty<QObject> QSGItemPrivate::resources()
1896 return QDeclarativeListProperty<QObject>(q_func(), 0, QSGItemPrivate::resources_append,
1897 QSGItemPrivate::resources_count,
1898 QSGItemPrivate::resources_at,
1899 QSGItemPrivate::resources_clear);
1902 QDeclarativeListProperty<QSGItem> QSGItemPrivate::children()
1904 return QDeclarativeListProperty<QSGItem>(q_func(), 0, QSGItemPrivate::children_append,
1905 QSGItemPrivate::children_count,
1906 QSGItemPrivate::children_at,
1907 QSGItemPrivate::children_clear);
1911 QDeclarativeListProperty<QDeclarativeState> QSGItemPrivate::states()
1913 return _states()->statesProperty();
1916 QDeclarativeListProperty<QDeclarativeTransition> QSGItemPrivate::transitions()
1918 return _states()->transitionsProperty();
1921 QString QSGItemPrivate::state() const
1926 return _stateGroup->state();
1929 void QSGItemPrivate::setState(const QString &state)
1931 _states()->setState(state);
1934 QDeclarativeListProperty<QSGTransform> QSGItem::transform()
1937 return QDeclarativeListProperty<QSGTransform>(this, 0, d->transform_append, d->transform_count,
1938 d->transform_at, d->transform_clear);
1941 void QSGItem::classBegin()
1944 d->componentComplete = false;
1946 d->_stateGroup->classBegin();
1948 d->_anchors->classBegin();
1951 void QSGItem::componentComplete()
1954 d->componentComplete = true;
1956 d->_stateGroup->componentComplete();
1958 d->_anchors->componentComplete();
1959 QSGAnchorsPrivate::get(d->_anchors)->updateOnComplete();
1962 d->keyHandler->componentComplete();
1964 d->_contents->complete();
1967 QDeclarativeStateGroup *QSGItemPrivate::_states()
1971 _stateGroup = new QDeclarativeStateGroup;
1972 if (!componentComplete)
1973 _stateGroup->classBegin();
1974 QObject::connect(_stateGroup, SIGNAL(stateChanged(QString)),
1975 q, SIGNAL(stateChanged(QString)));
1981 QSGItemPrivate::AnchorLines::AnchorLines(QSGItem *q)
1984 left.anchorLine = QSGAnchorLine::Left;
1986 right.anchorLine = QSGAnchorLine::Right;
1988 hCenter.anchorLine = QSGAnchorLine::HCenter;
1990 top.anchorLine = QSGAnchorLine::Top;
1992 bottom.anchorLine = QSGAnchorLine::Bottom;
1994 vCenter.anchorLine = QSGAnchorLine::VCenter;
1996 baseline.anchorLine = QSGAnchorLine::Baseline;
1999 QPointF QSGItemPrivate::computeTransformOrigin() const
2003 case QSGItem::TopLeft:
2004 return QPointF(0, 0);
2006 return QPointF(width / 2., 0);
2007 case QSGItem::TopRight:
2008 return QPointF(width, 0);
2010 return QPointF(0, height / 2.);
2011 case QSGItem::Center:
2012 return QPointF(width / 2., height / 2.);
2013 case QSGItem::Right:
2014 return QPointF(width, height / 2.);
2015 case QSGItem::BottomLeft:
2016 return QPointF(0, height);
2017 case QSGItem::Bottom:
2018 return QPointF(width / 2., height);
2019 case QSGItem::BottomRight:
2020 return QPointF(width, height);
2024 void QSGItemPrivate::transformChanged()
2028 void QSGItemPrivate::deliverKeyEvent(QKeyEvent *e)
2032 Q_ASSERT(e->isAccepted());
2034 if (e->type() == QEvent::KeyPress)
2035 keyHandler->keyPressed(e, false);
2037 keyHandler->keyReleased(e, false);
2039 if (e->isAccepted())
2045 if (e->type() == QEvent::KeyPress)
2046 q->keyPressEvent(e);
2048 q->keyReleaseEvent(e);
2050 if (e->isAccepted())
2056 if (e->type() == QEvent::KeyPress)
2057 keyHandler->keyPressed(e, true);
2059 keyHandler->keyReleased(e, true);
2063 void QSGItemPrivate::deliverInputMethodEvent(QInputMethodEvent *e)
2067 Q_ASSERT(e->isAccepted());
2069 keyHandler->inputMethodEvent(e, false);
2071 if (e->isAccepted())
2077 q->inputMethodEvent(e);
2079 if (e->isAccepted())
2085 keyHandler->inputMethodEvent(e, true);
2089 void QSGItemPrivate::deliverFocusEvent(QFocusEvent *e)
2093 if (e->type() == QEvent::FocusIn) {
2096 q->focusOutEvent(e);
2100 void QSGItemPrivate::deliverMouseEvent(QGraphicsSceneMouseEvent *e)
2104 Q_ASSERT(e->isAccepted());
2108 Q_ASSERT(!"Unknown event type");
2109 case QEvent::GraphicsSceneMouseMove:
2110 q->mouseMoveEvent(e);
2112 case QEvent::GraphicsSceneMousePress:
2113 q->mousePressEvent(e);
2115 case QEvent::GraphicsSceneMouseRelease:
2116 q->mouseReleaseEvent(e);
2118 case QEvent::GraphicsSceneMouseDoubleClick:
2119 q->mouseDoubleClickEvent(e);
2124 void QSGItemPrivate::deliverWheelEvent(QGraphicsSceneWheelEvent *e)
2130 void QSGItemPrivate::deliverTouchEvent(QTouchEvent *e)
2136 void QSGItemPrivate::deliverHoverEvent(QGraphicsSceneHoverEvent *e)
2141 Q_ASSERT(!"Unknown event type");
2142 case QEvent::GraphicsSceneHoverEnter:
2143 q->hoverEnterEvent(e);
2145 case QEvent::GraphicsSceneHoverLeave:
2146 q->hoverLeaveEvent(e);
2148 case QEvent::GraphicsSceneHoverMove:
2149 q->hoverMoveEvent(e);
2154 void QSGItem::itemChange(ItemChange change, const ItemChangeData &value)
2161 // XXX todo - do we want/need this anymore?
2162 QRectF QSGItem::boundingRect() const
2165 return QRectF(0, 0, d->width, d->height);
2168 QSGItem::TransformOrigin QSGItem::transformOrigin() const
2174 void QSGItem::setTransformOrigin(TransformOrigin origin)
2177 if (origin == d->origin)
2181 d->dirty(QSGItemPrivate::TransformOrigin);
2183 emit transformOriginChanged(d->origin);
2186 QPointF QSGItem::transformOriginPoint() const
2189 return d->computeTransformOrigin();
2192 qreal QSGItem::z() const
2198 void QSGItem::setZ(qreal v)
2206 d->dirty(QSGItemPrivate::ZValue);
2208 QSGItemPrivate::get(d->parentItem)->dirty(QSGItemPrivate::ChildrenStackingChanged);
2213 qreal QSGItem::rotation() const
2219 void QSGItem::setRotation(qreal r)
2222 if (d->rotation == r)
2227 d->dirty(QSGItemPrivate::BasicTransform);
2229 d->itemChange(ItemRotationHasChanged, r);
2231 emit rotationChanged();
2234 qreal QSGItem::scale() const
2240 void QSGItem::setScale(qreal s)
2248 d->dirty(QSGItemPrivate::BasicTransform);
2250 emit scaleChanged();
2253 qreal QSGItem::opacity() const
2259 void QSGItem::setOpacity(qreal o)
2262 if (d->opacity == o)
2267 d->dirty(QSGItemPrivate::OpacityValue);
2269 d->itemChange(ItemOpacityHasChanged, o);
2271 emit opacityChanged();
2274 bool QSGItem::isVisible() const
2277 return d->effectiveVisible;
2280 void QSGItem::setVisible(bool v)
2283 if (v == d->explicitVisible)
2286 d->explicitVisible = v;
2288 d->setEffectiveVisibleRecur(d->calcEffectiveVisible());
2291 bool QSGItem::isEnabled() const
2294 return d->effectiveEnable;
2297 void QSGItem::setEnabled(bool e)
2300 if (e == d->explicitEnable)
2303 d->explicitEnable = e;
2305 d->setEffectiveEnableRecur(d->calcEffectiveEnable());
2308 bool QSGItemPrivate::calcEffectiveVisible() const
2310 // XXX todo - Should the effective visible of an element with no parent just be the current
2311 // effective visible? This would prevent pointless re-processing in the case of an element
2312 // moving to/from a no-parent situation, but it is different from what graphics view does.
2313 return explicitVisible && (!parentItem || QSGItemPrivate::get(parentItem)->effectiveVisible);
2316 void QSGItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible)
2320 if (newEffectiveVisible && !explicitVisible) {
2321 // This item locally overrides visibility
2325 if (newEffectiveVisible == effectiveVisible) {
2326 // No change necessary
2330 effectiveVisible = newEffectiveVisible;
2332 if (parentItem) QSGItemPrivate::get(parentItem)->dirty(ChildrenStackingChanged);
2335 QSGCanvasPrivate *canvasPriv = QSGCanvasPrivate::get(canvas);
2336 if (canvasPriv->mouseGrabberItem == q)
2340 for (int ii = 0; ii < childItems.count(); ++ii)
2341 QSGItemPrivate::get(childItems.at(ii))->setEffectiveVisibleRecur(newEffectiveVisible);
2343 for(int ii = 0; ii < changeListeners.count(); ++ii) {
2344 const QSGItemPrivate::ChangeListener &change = changeListeners.at(ii);
2345 if (change.types & QSGItemPrivate::Visibility)
2346 change.listener->itemVisibilityChanged(q);
2349 emit q->visibleChanged();
2352 bool QSGItemPrivate::calcEffectiveEnable() const
2354 // XXX todo - Should the effective enable of an element with no parent just be the current
2355 // effective enable? This would prevent pointless re-processing in the case of an element
2356 // moving to/from a no-parent situation, but it is different from what graphics view does.
2357 return explicitEnable && (!parentItem || QSGItemPrivate::get(parentItem)->effectiveEnable);
2360 void QSGItemPrivate::setEffectiveEnableRecur(bool newEffectiveEnable)
2364 // XXX todo - need to fixup focus
2366 if (newEffectiveEnable && !explicitEnable) {
2367 // This item locally overrides enable
2371 if (newEffectiveEnable == effectiveEnable) {
2372 // No change necessary
2376 effectiveEnable = newEffectiveEnable;
2379 QSGCanvasPrivate *canvasPriv = QSGCanvasPrivate::get(canvas);
2380 if (canvasPriv->mouseGrabberItem == q)
2384 for (int ii = 0; ii < childItems.count(); ++ii)
2385 QSGItemPrivate::get(childItems.at(ii))->setEffectiveEnableRecur(newEffectiveEnable);
2387 emit q->enabledChanged();
2390 QString QSGItemPrivate::dirtyToString() const
2392 #define DIRTY_TO_STRING(value) if (dirtyAttributes & value) { \
2393 if (!rv.isEmpty()) \
2394 rv.append(QLatin1String("|")); \
2395 rv.append(QLatin1String(#value)); \
2398 // QString rv = QLatin1String("0x") + QString::number(dirtyAttributes, 16);
2401 DIRTY_TO_STRING(TransformOrigin);
2402 DIRTY_TO_STRING(Transform);
2403 DIRTY_TO_STRING(BasicTransform);
2404 DIRTY_TO_STRING(Position);
2405 DIRTY_TO_STRING(Size);
2406 DIRTY_TO_STRING(ZValue);
2407 DIRTY_TO_STRING(Content);
2408 DIRTY_TO_STRING(Smooth);
2409 DIRTY_TO_STRING(OpacityValue);
2410 DIRTY_TO_STRING(ChildrenChanged);
2411 DIRTY_TO_STRING(ChildrenStackingChanged);
2412 DIRTY_TO_STRING(ParentChanged);
2413 DIRTY_TO_STRING(Clip);
2414 DIRTY_TO_STRING(Canvas);
2415 DIRTY_TO_STRING(EffectReference);
2416 DIRTY_TO_STRING(Visible);
2417 DIRTY_TO_STRING(HideReference);
2422 void QSGItemPrivate::dirty(DirtyType type)
2425 if (type & (TransformOrigin | Transform | BasicTransform | Position | Size))
2428 if (!(dirtyAttributes & type) || (canvas && !prevDirtyItem)) {
2429 dirtyAttributes |= type;
2432 QSGCanvasPrivate::get(canvas)->dirtyItem(q);
2437 void QSGItemPrivate::addToDirtyList()
2442 if (!prevDirtyItem) {
2443 Q_ASSERT(!nextDirtyItem);
2445 QSGCanvasPrivate *p = QSGCanvasPrivate::get(canvas);
2446 nextDirtyItem = p->dirtyItemList;
2447 if (nextDirtyItem) QSGItemPrivate::get(nextDirtyItem)->prevDirtyItem = &nextDirtyItem;
2448 prevDirtyItem = &p->dirtyItemList;
2449 p->dirtyItemList = q;
2452 Q_ASSERT(prevDirtyItem);
2455 void QSGItemPrivate::removeFromDirtyList()
2457 if (prevDirtyItem) {
2458 if (nextDirtyItem) QSGItemPrivate::get(nextDirtyItem)->prevDirtyItem = prevDirtyItem;
2459 *prevDirtyItem = nextDirtyItem;
2463 Q_ASSERT(!prevDirtyItem);
2464 Q_ASSERT(!nextDirtyItem);
2467 void QSGItemPrivate::refFromEffectItem(bool hide)
2470 if (1 == effectRefCount) {
2471 dirty(EffectReference);
2472 if (parentItem) QSGItemPrivate::get(parentItem)->dirty(ChildrenStackingChanged);
2475 if (++hideRefCount == 1)
2476 dirty(HideReference);
2480 void QSGItemPrivate::derefFromEffectItem(bool unhide)
2482 Q_ASSERT(effectRefCount);
2484 if (0 == effectRefCount) {
2485 dirty(EffectReference);
2486 if (parentItem) QSGItemPrivate::get(parentItem)->dirty(ChildrenStackingChanged);
2489 if (--hideRefCount == 0)
2490 dirty(HideReference);
2494 void QSGItemPrivate::itemChange(QSGItem::ItemChange change, const QSGItem::ItemChangeData &data)
2498 case QSGItem::ItemChildAddedChange:
2499 q->itemChange(change, data);
2500 if (_contents && componentComplete)
2501 _contents->childAdded(data.item);
2502 for(int ii = 0; ii < changeListeners.count(); ++ii) {
2503 const QSGItemPrivate::ChangeListener &change = changeListeners.at(ii);
2504 if (change.types & QSGItemPrivate::Children) {
2505 change.listener->itemChildAdded(q, data.item);
2509 case QSGItem::ItemChildRemovedChange:
2510 q->itemChange(change, data);
2511 if (_contents && componentComplete)
2512 _contents->childRemoved(data.item);
2513 for(int ii = 0; ii < changeListeners.count(); ++ii) {
2514 const QSGItemPrivate::ChangeListener &change = changeListeners.at(ii);
2515 if (change.types & QSGItemPrivate::Children) {
2516 change.listener->itemChildRemoved(q, data.item);
2520 case QSGItem::ItemSceneChange:
2521 q->itemChange(change, data);
2523 case QSGItem::ItemVisibleHasChanged:
2524 q->itemChange(change, data);
2525 for(int ii = 0; ii < changeListeners.count(); ++ii) {
2526 const QSGItemPrivate::ChangeListener &change = changeListeners.at(ii);
2527 if (change.types & QSGItemPrivate::Visibility) {
2528 change.listener->itemVisibilityChanged(q);
2532 case QSGItem::ItemParentHasChanged:
2533 q->itemChange(change, data);
2534 for(int ii = 0; ii < changeListeners.count(); ++ii) {
2535 const QSGItemPrivate::ChangeListener &change = changeListeners.at(ii);
2536 if (change.types & QSGItemPrivate::Parent) {
2537 change.listener->itemParentChanged(q, data.item);
2541 case QSGItem::ItemOpacityHasChanged:
2542 q->itemChange(change, data);
2543 for(int ii = 0; ii < changeListeners.count(); ++ii) {
2544 const QSGItemPrivate::ChangeListener &change = changeListeners.at(ii);
2545 if (change.types & QSGItemPrivate::Opacity) {
2546 change.listener->itemOpacityChanged(q);
2550 case QSGItem::ItemActiveFocusHasChanged:
2551 q->itemChange(change, data);
2553 case QSGItem::ItemRotationHasChanged:
2554 q->itemChange(change, data);
2555 for(int ii = 0; ii < changeListeners.count(); ++ii) {
2556 const QSGItemPrivate::ChangeListener &change = changeListeners.at(ii);
2557 if (change.types & QSGItemPrivate::Rotation) {
2558 change.listener->itemRotationChanged(q);
2565 bool QSGItem::smooth() const
2571 void QSGItem::setSmooth(bool smooth)
2574 if (d->smooth == smooth)
2578 d->dirty(QSGItemPrivate::Smooth);
2580 emit smoothChanged(smooth);
2583 QSGItem::Flags QSGItem::flags() const
2586 return (QSGItem::Flags)d->flags;
2589 void QSGItem::setFlag(Flag flag, bool enabled)
2593 setFlags((Flags)(d->flags | (quint32)flag));
2595 setFlags((Flags)(d->flags & ~(quint32)flag));
2598 void QSGItem::setFlags(Flags flags)
2602 if ((flags & ItemIsFocusScope) != (d->flags & ItemIsFocusScope)) {
2603 if (flags & ItemIsFocusScope && !d->childItems.isEmpty() && d->canvas) {
2604 qWarning("QSGItem: Cannot set FocusScope once item has children and is in a canvas.");
2605 flags &= ~ItemIsFocusScope;
2606 } else if (d->flags & ItemIsFocusScope) {
2607 qWarning("QSGItem: Cannot unset FocusScope flag.");
2608 flags |= ItemIsFocusScope;
2612 if ((flags & ItemClipsChildrenToShape ) != (d->flags & ItemClipsChildrenToShape))
2613 d->dirty(QSGItemPrivate::Clip);
2618 qreal QSGItem::x() const
2624 qreal QSGItem::y() const
2630 QPointF QSGItem::pos() const
2633 return QPointF(d->x, d->y);
2636 void QSGItem::setX(qreal v)
2645 d->dirty(QSGItemPrivate::Position);
2647 geometryChanged(QRectF(x(), y(), width(), height()),
2648 QRectF(oldx, y(), width(), height()));
2651 void QSGItem::setY(qreal v)
2660 d->dirty(QSGItemPrivate::Position);
2662 geometryChanged(QRectF(x(), y(), width(), height()),
2663 QRectF(x(), oldy, width(), height()));
2666 void QSGItem::setPos(const QPointF &pos)
2669 if (QPointF(d->x, d->y) == pos)
2678 d->dirty(QSGItemPrivate::Position);
2680 geometryChanged(QRectF(x(), y(), width(), height()),
2681 QRectF(oldx, oldy, width(), height()));
2684 qreal QSGItem::width() const
2690 void QSGItem::setWidth(qreal w)
2696 d->widthValid = true;
2700 qreal oldWidth = d->width;
2703 d->dirty(QSGItemPrivate::Size);
2705 geometryChanged(QRectF(x(), y(), width(), height()),
2706 QRectF(x(), y(), oldWidth, height()));
2709 void QSGItem::resetWidth()
2712 d->widthValid = false;
2713 setImplicitWidth(implicitWidth());
2716 void QSGItemPrivate::implicitWidthChanged()
2719 emit q->implicitWidthChanged();
2722 qreal QSGItemPrivate::getImplicitWidth() const
2724 return implicitWidth;
2727 qreal QSGItem::implicitWidth() const
2730 return d->getImplicitWidth();
2733 void QSGItem::setImplicitWidth(qreal w)
2736 bool changed = w != d->implicitWidth;
2737 d->implicitWidth = w;
2738 if (d->width == w || widthValid()) {
2740 d->implicitWidthChanged();
2744 qreal oldWidth = d->width;
2747 d->dirty(QSGItemPrivate::Size);
2749 geometryChanged(QRectF(x(), y(), width(), height()),
2750 QRectF(x(), y(), oldWidth, height()));
2753 d->implicitWidthChanged();
2756 bool QSGItem::widthValid() const
2759 return d->widthValid;
2762 qreal QSGItem::height() const
2768 void QSGItem::setHeight(qreal h)
2774 d->heightValid = true;
2778 qreal oldHeight = d->height;
2781 d->dirty(QSGItemPrivate::Size);
2783 geometryChanged(QRectF(x(), y(), width(), height()),
2784 QRectF(x(), y(), width(), oldHeight));
2787 void QSGItem::resetHeight()
2790 d->heightValid = false;
2791 setImplicitHeight(implicitHeight());
2794 void QSGItemPrivate::implicitHeightChanged()
2797 emit q->implicitHeightChanged();
2800 qreal QSGItemPrivate::getImplicitHeight() const
2802 return implicitHeight;
2805 qreal QSGItem::implicitHeight() const
2808 return d->getImplicitHeight();
2811 void QSGItem::setImplicitHeight(qreal h)
2814 bool changed = h != d->implicitHeight;
2815 d->implicitHeight = h;
2816 if (d->height == h || heightValid()) {
2818 d->implicitHeightChanged();
2822 qreal oldHeight = d->height;
2825 d->dirty(QSGItemPrivate::Size);
2827 geometryChanged(QRectF(x(), y(), width(), height()),
2828 QRectF(x(), y(), width(), oldHeight));
2831 d->implicitHeightChanged();
2834 bool QSGItem::heightValid() const
2837 return d->heightValid;
2840 void QSGItem::setSize(const QSizeF &size)
2843 d->heightValid = true;
2844 d->widthValid = true;
2846 if (QSizeF(d->width, d->height) == size)
2849 qreal oldHeight = d->height;
2850 qreal oldWidth = d->width;
2851 d->height = size.height();
2852 d->width = size.width();
2854 d->dirty(QSGItemPrivate::Size);
2856 geometryChanged(QRectF(x(), y(), width(), height()),
2857 QRectF(x(), y(), oldWidth, oldHeight));
2860 bool QSGItem::hasActiveFocus() const
2863 return d->activeFocus;
2866 bool QSGItem::hasFocus() const
2872 void QSGItem::setFocus(bool focus)
2875 if (d->focus == focus)
2879 // Need to find our nearest focus scope
2880 QSGItem *scope = parentItem();
2881 while (scope && !scope->isFocusScope())
2882 scope = scope->parentItem();
2884 QSGCanvasPrivate::get(d->canvas)->setFocusInScope(scope, this);
2886 QSGCanvasPrivate::get(d->canvas)->clearFocusInScope(scope, this);
2889 emit focusChanged(focus);
2893 bool QSGItem::isFocusScope() const
2895 return flags() & ItemIsFocusScope;
2898 QSGItem *QSGItem::scopedFocusItem() const
2901 if (!isFocusScope())
2904 return d->subFocusItem;
2908 Qt::MouseButtons QSGItem::acceptedMouseButtons() const
2911 return d->acceptedMouseButtons;
2914 void QSGItem::setAcceptedMouseButtons(Qt::MouseButtons buttons)
2917 d->acceptedMouseButtons = buttons;
2920 bool QSGItem::filtersChildMouseEvents() const
2923 return d->filtersChildMouseEvents;
2926 void QSGItem::setFiltersChildMouseEvents(bool filter)
2929 d->filtersChildMouseEvents = filter;
2932 bool QSGItem::isUnderMouse() const
2938 QPoint cursorPos = QCursor::pos();
2939 if (QRectF(0, 0, width(), height()).contains(mapFromScene(d->canvas->mapFromGlobal(cursorPos))))
2944 bool QSGItem::acceptHoverEvents() const
2947 return d->hoverEnabled;
2950 void QSGItem::setAcceptHoverEvents(bool enabled)
2953 d->hoverEnabled = enabled;
2955 if (d->canvas && d->hoverEnabled && !d->canvas->hasMouseTracking())
2956 d->canvas->setMouseTracking(true);
2959 void QSGItem::grabMouse()
2964 QSGCanvasPrivate *canvasPriv = QSGCanvasPrivate::get(d->canvas);
2965 if (canvasPriv->mouseGrabberItem == this)
2968 QSGItem *oldGrabber = canvasPriv->mouseGrabberItem;
2969 canvasPriv->mouseGrabberItem = this;
2971 oldGrabber->mouseUngrabEvent();
2974 void QSGItem::ungrabMouse()
2979 QSGCanvasPrivate *canvasPriv = QSGCanvasPrivate::get(d->canvas);
2980 if (canvasPriv->mouseGrabberItem != this) {
2981 qWarning("QSGItem::ungrabMouse(): Item is not the mouse grabber.");
2985 canvasPriv->mouseGrabberItem = 0;
2989 bool QSGItem::keepMouseGrab() const
2992 return d->keepMouse;
2995 void QSGItem::setKeepMouseGrab(bool keep)
2998 d->keepMouse = keep;
3001 QPointF QSGItem::mapToItem(const QSGItem *item, const QPointF &point) const
3003 QPointF p = mapToScene(point);
3005 p = item->mapFromScene(p);
3009 QPointF QSGItem::mapToScene(const QPointF &point) const
3012 return d->itemToCanvasTransform().map(point);
3015 QRectF QSGItem::mapRectToItem(const QSGItem *item, const QRectF &rect) const
3018 QTransform t = d->itemToCanvasTransform();
3020 t *= QSGItemPrivate::get(item)->canvasToItemTransform();
3021 return t.mapRect(rect);
3024 QRectF QSGItem::mapRectToScene(const QRectF &rect) const
3027 return d->itemToCanvasTransform().mapRect(rect);
3030 QPointF QSGItem::mapFromItem(const QSGItem *item, const QPointF &point) const
3032 QPointF p = item?item->mapToScene(point):point;
3033 return mapFromScene(p);
3036 QPointF QSGItem::mapFromScene(const QPointF &point) const
3039 return d->canvasToItemTransform().map(point);
3042 QRectF QSGItem::mapRectFromItem(const QSGItem *item, const QRectF &rect) const
3045 QTransform t = item?QSGItemPrivate::get(item)->itemToCanvasTransform():QTransform();
3046 t *= d->canvasToItemTransform();
3047 return t.mapRect(rect);
3050 QRectF QSGItem::mapRectFromScene(const QRectF &rect) const
3053 return d->canvasToItemTransform().mapRect(rect);
3056 bool QSGItem::event(QEvent *ev)
3058 return QObject::event(ev);
3061 if (ev->type() == QEvent::PolishRequest) {
3063 d->polishScheduled = false;
3067 return QObject::event(ev);
3072 #ifndef QT_NO_DEBUG_STREAM
3073 QDebug operator<<(QDebug debug, QSGItem *item)
3076 debug << "QSGItem(0)";
3080 debug << item->metaObject()->className() << "(this =" << ((void*)item)
3081 << ", name=" << item->objectName()
3082 << ", parent =" << ((void*)item->parentItem())
3083 << ", geometry =" << QRectF(item->pos(), QSizeF(item->width(), item->height()))
3084 << ", z =" << item->z() << ')';
3089 qint64 QSGItemPrivate::consistentTime = -1;
3090 void QSGItemPrivate::setConsistentTime(qint64 t)
3095 class QElapsedTimerConsistentTimeHack
3099 t1 = QSGItemPrivate::consistentTime;
3103 return QSGItemPrivate::consistentTime - t1;
3106 qint64 val = QSGItemPrivate::consistentTime - t1;
3107 t1 = QSGItemPrivate::consistentTime;
3117 void QSGItemPrivate::start(QElapsedTimer &t)
3119 if (QSGItemPrivate::consistentTime == -1)
3122 ((QElapsedTimerConsistentTimeHack*)&t)->start();
3125 qint64 QSGItemPrivate::elapsed(QElapsedTimer &t)
3127 if (QSGItemPrivate::consistentTime == -1)
3130 return ((QElapsedTimerConsistentTimeHack*)&t)->elapsed();
3133 qint64 QSGItemPrivate::restart(QElapsedTimer &t)
3135 if (QSGItemPrivate::consistentTime == -1)
3138 return ((QElapsedTimerConsistentTimeHack*)&t)->restart();
3143 #include <moc_qsgitem.cpp>