Initial import from qtquick2.
[profile/ivi/qtdeclarative.git] / src / declarative / items / qsgitem.cpp
1 // Commit: c44be8c0b27756a2025ebad1945632f3f7e4bebc
2 /****************************************************************************
3 **
4 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
5 ** All rights reserved.
6 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 **
8 ** This file is part of the QtDeclarative module of the Qt Toolkit.
9 **
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
15 ** this package.
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 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.
24 **
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.
28 **
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 **
39 ** $QT_END_LICENSE$
40 **
41 ****************************************************************************/
42
43 #include "qsgitem.h"
44
45 #include "qsgcanvas.h"
46 #include <QtScript/qscriptengine.h>
47 #include "qsgcanvas_p.h"
48
49 #include "qsgevents_p_p.h"
50
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>
62
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>
69
70 #include <float.h>
71
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
74
75 QT_BEGIN_NAMESPACE
76
77 QSGTransformPrivate::QSGTransformPrivate()
78 {
79 }
80
81 QSGTransform::QSGTransform(QObject *parent)
82 : QObject(*(new QSGTransformPrivate), parent)
83 {
84 }
85
86 QSGTransform::QSGTransform(QSGTransformPrivate &dd, QObject *parent)
87 : QObject(dd, parent)
88 {
89 }
90
91 QSGTransform::~QSGTransform()
92 {
93     Q_D(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);
98     }
99 }
100
101 void QSGTransform::update()
102 {
103     Q_D(QSGTransform);
104     for (int ii = 0; ii < d->items.count(); ++ii) {
105         QSGItemPrivate *p = QSGItemPrivate::get(d->items.at(ii));
106         p->dirty(QSGItemPrivate::Transform);
107     }
108 }
109
110 QSGContents::QSGContents(QSGItem *item) 
111 : m_item(item), m_x(0), m_y(0), m_width(0), m_height(0)
112 {
113     //### optimize
114     connect(this, SIGNAL(rectChanged(QRectF)), m_item, SIGNAL(childrenRectChanged(QRectF)));
115 }
116
117 QSGContents::~QSGContents()
118 {
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);
123     }
124 }
125
126 QRectF QSGContents::rectF() const
127 {
128     return QRectF(m_x, m_y, m_width, m_height);
129 }
130
131 void QSGContents::calcHeight(QSGItem *changed)
132 {
133     qreal oldy = m_y;
134     qreal oldheight = m_height;
135
136     if (changed) {
137         qreal top = oldy;
138         qreal bottom = oldy + oldheight;
139         qreal y = changed->y();
140         if (y + changed->height() > bottom)
141             bottom = y + changed->height();
142         if (y < top)
143             top = y;
144         m_y = top;
145         m_height = bottom - top;
146     } else {
147         qreal top = FLT_MAX;
148         qreal bottom = 0;
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();
155             if (y < top)
156                 top = y;
157         }
158         if (!children.isEmpty())
159             m_y = top;
160         m_height = qMax(bottom - top, qreal(0.0));
161     }
162
163     if (m_height != oldheight || m_y != oldy)
164         emit rectChanged(rectF());
165 }
166
167 void QSGContents::calcWidth(QSGItem *changed)
168 {
169     qreal oldx = m_x;
170     qreal oldwidth = m_width;
171
172     if (changed) {
173         qreal left = oldx;
174         qreal right = oldx + oldwidth;
175         qreal x = changed->x();
176         if (x + changed->width() > right)
177             right = x + changed->width();
178         if (x < left)
179             left = x;
180         m_x = left;
181         m_width = right - left;
182     } else {
183         qreal left = FLT_MAX;
184         qreal right = 0;
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();
191             if (x < left)
192                 left = x;
193         }
194         if (!children.isEmpty())
195             m_x = left;
196         m_width = qMax(right - left, qreal(0.0));
197     }
198
199     if (m_width != oldwidth || m_x != oldx)
200         emit rectChanged(rectF());
201 }
202
203 void QSGContents::complete()
204 {
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?
210     }
211
212     calcGeometry();
213 }
214
215 void QSGContents::itemGeometryChanged(QSGItem *changed, const QRectF &newGeometry, const QRectF &oldGeometry)
216 {
217     Q_UNUSED(changed)
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*/);
223 }
224
225 void QSGContents::itemDestroyed(QSGItem *item)
226 {
227     if (item)
228         QSGItemPrivate::get(item)->removeItemChangeListener(this, QSGItemPrivate::Geometry | QSGItemPrivate::Destroyed);
229     calcGeometry();
230 }
231
232 void QSGContents::childRemoved(QSGItem *item)
233 {
234     if (item)
235         QSGItemPrivate::get(item)->removeItemChangeListener(this, QSGItemPrivate::Geometry | QSGItemPrivate::Destroyed);
236     calcGeometry();
237 }
238
239 void QSGContents::childAdded(QSGItem *item)
240 {
241     if (item)
242         QSGItemPrivate::get(item)->addItemChangeListener(this, QSGItemPrivate::Geometry | QSGItemPrivate::Destroyed);
243     calcWidth(item);
244     calcHeight(item);
245 }
246
247 QSGItemKeyFilter::QSGItemKeyFilter(QSGItem *item)
248 : m_processPost(false), m_next(0)
249 {
250     QSGItemPrivate *p = item?QSGItemPrivate::get(item):0;
251     if (p) {
252         m_next = p->keyHandler;
253         p->keyHandler = this;
254     }
255 }
256
257 QSGItemKeyFilter::~QSGItemKeyFilter()
258 {
259 }
260
261 void QSGItemKeyFilter::keyPressed(QKeyEvent *event, bool post)
262 {
263     if (m_next) m_next->keyPressed(event, post);
264 }
265
266 void QSGItemKeyFilter::keyReleased(QKeyEvent *event, bool post)
267 {
268     if (m_next) m_next->keyReleased(event, post);
269 }
270
271 void QSGItemKeyFilter::inputMethodEvent(QInputMethodEvent *event, bool post)
272 {
273     if (m_next)
274         m_next->inputMethodEvent(event, post);
275     else
276         event->ignore();
277 }
278
279 QVariant QSGItemKeyFilter::inputMethodQuery(Qt::InputMethodQuery query) const
280 {
281     if (m_next) return m_next->inputMethodQuery(query);
282     return QVariant();
283 }
284
285 void QSGItemKeyFilter::componentComplete()
286 {
287     if (m_next) m_next->componentComplete();
288 }
289
290 QSGKeyNavigationAttached::QSGKeyNavigationAttached(QObject *parent)
291 : QObject(*(new QSGKeyNavigationAttachedPrivate), parent),
292   QSGItemKeyFilter(qobject_cast<QSGItem*>(parent))
293 {
294     m_processPost = true;
295 }
296
297 QSGKeyNavigationAttached *
298 QSGKeyNavigationAttached::qmlAttachedProperties(QObject *obj)
299 {
300     return new QSGKeyNavigationAttached(obj);
301 }
302
303 QSGItem *QSGKeyNavigationAttached::left() const
304 {
305     Q_D(const QSGKeyNavigationAttached);
306     return d->left;
307 }
308
309 void QSGKeyNavigationAttached::setLeft(QSGItem *i)
310 {
311     Q_D(QSGKeyNavigationAttached);
312     if (d->left == i)
313         return;
314     d->left = i;
315     d->leftSet = true;
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();
321     }
322     emit leftChanged();
323 }
324
325 QSGItem *QSGKeyNavigationAttached::right() const
326 {
327     Q_D(const QSGKeyNavigationAttached);
328     return d->right;
329 }
330
331 void QSGKeyNavigationAttached::setRight(QSGItem *i)
332 {
333     Q_D(QSGKeyNavigationAttached);
334     if (d->right == i)
335         return;
336     d->right = i;
337     d->rightSet = true;
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();
343     }
344     emit rightChanged();
345 }
346
347 QSGItem *QSGKeyNavigationAttached::up() const
348 {
349     Q_D(const QSGKeyNavigationAttached);
350     return d->up;
351 }
352
353 void QSGKeyNavigationAttached::setUp(QSGItem *i)
354 {
355     Q_D(QSGKeyNavigationAttached);
356     if (d->up == i)
357         return;
358     d->up = i;
359     d->upSet = true;
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();
365     }
366     emit upChanged();
367 }
368
369 QSGItem *QSGKeyNavigationAttached::down() const
370 {
371     Q_D(const QSGKeyNavigationAttached);
372     return d->down;
373 }
374
375 void QSGKeyNavigationAttached::setDown(QSGItem *i)
376 {
377     Q_D(QSGKeyNavigationAttached);
378     if (d->down == i)
379         return;
380     d->down = i;
381     d->downSet = true;
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();
387     }
388     emit downChanged();
389 }
390
391 QSGItem *QSGKeyNavigationAttached::tab() const
392 {
393     Q_D(const QSGKeyNavigationAttached);
394     return d->tab;
395 }
396
397 void QSGKeyNavigationAttached::setTab(QSGItem *i)
398 {
399     Q_D(QSGKeyNavigationAttached);
400     if (d->tab == i)
401         return;
402     d->tab = i;
403     d->tabSet = true;
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();
409     }
410     emit tabChanged();
411 }
412
413 QSGItem *QSGKeyNavigationAttached::backtab() const
414 {
415     Q_D(const QSGKeyNavigationAttached);
416     return d->backtab;
417 }
418
419 void QSGKeyNavigationAttached::setBacktab(QSGItem *i)
420 {
421     Q_D(QSGKeyNavigationAttached);
422     if (d->backtab == i)
423         return;
424     d->backtab = i;
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();
431     }
432     emit backtabChanged();
433 }
434
435 QSGKeyNavigationAttached::Priority QSGKeyNavigationAttached::priority() const
436 {
437     return m_processPost ? AfterItem : BeforeItem;
438 }
439
440 void QSGKeyNavigationAttached::setPriority(Priority order)
441 {
442     bool processPost = order == AfterItem;
443     if (processPost != m_processPost) {
444         m_processPost = processPost;
445         emit priorityChanged();
446     }
447 }
448
449 void QSGKeyNavigationAttached::keyPressed(QKeyEvent *event, bool post)
450 {
451     Q_D(QSGKeyNavigationAttached);
452     event->ignore();
453
454     if (post != m_processPost) {
455         QSGItemKeyFilter::keyPressed(event, post);
456         return;
457     }
458
459     bool mirror = false;
460     switch(event->key()) {
461     case Qt::Key_Left: {
462         if (QSGItem *parentItem = qobject_cast<QSGItem*>(parent()))
463             mirror = QSGItemPrivate::get(parentItem)->effectiveLayoutMirror;
464         QSGItem* leftItem = mirror ? d->right : d->left;
465         if (leftItem) {
466             setFocusNavigation(leftItem, mirror ? "right" : "left");
467             event->accept();
468         }
469         break;
470     }
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;
475         if (rightItem) {
476             setFocusNavigation(rightItem, mirror ? "left" : "right");
477             event->accept();
478         }
479         break;
480     }
481     case Qt::Key_Up:
482         if (d->up) {
483             setFocusNavigation(d->up, "up");
484             event->accept();
485         }
486         break;
487     case Qt::Key_Down:
488         if (d->down) {
489             setFocusNavigation(d->down, "down");
490             event->accept();
491         }
492         break;
493     case Qt::Key_Tab:
494         if (d->tab) {
495             setFocusNavigation(d->tab, "tab");
496             event->accept();
497         }
498         break;
499     case Qt::Key_Backtab:
500         if (d->backtab) {
501             setFocusNavigation(d->backtab, "backtab");
502             event->accept();
503         }
504         break;
505     default:
506         break;
507     }
508
509     if (!event->isAccepted()) QSGItemKeyFilter::keyPressed(event, post);
510 }
511
512 void QSGKeyNavigationAttached::keyReleased(QKeyEvent *event, bool post)
513 {
514     Q_D(QSGKeyNavigationAttached);
515     event->ignore();
516
517     if (post != m_processPost) {
518         QSGItemKeyFilter::keyReleased(event, post);
519         return;
520     }
521
522     bool mirror = false;
523     switch(event->key()) {
524     case Qt::Key_Left:
525         if (QSGItem *parentItem = qobject_cast<QSGItem*>(parent()))
526             mirror = QSGItemPrivate::get(parentItem)->effectiveLayoutMirror;
527         if (mirror ? d->right : d->left)
528             event->accept();
529         break;
530     case Qt::Key_Right:
531         if (QSGItem *parentItem = qobject_cast<QSGItem*>(parent()))
532             mirror = QSGItemPrivate::get(parentItem)->effectiveLayoutMirror;
533         if (mirror ? d->left : d->right)
534             event->accept();
535         break;
536     case Qt::Key_Up:
537         if (d->up) {
538             event->accept();
539         }
540         break;
541     case Qt::Key_Down:
542         if (d->down) {
543             event->accept();
544         }
545         break;
546     case Qt::Key_Tab:
547         if (d->tab) {
548             event->accept();
549         }
550         break;
551     case Qt::Key_Backtab:
552         if (d->backtab) {
553             event->accept();
554         }
555         break;
556     default:
557         break;
558     }
559
560     if (!event->isAccepted()) QSGItemKeyFilter::keyReleased(event, post);
561 }
562
563 void QSGKeyNavigationAttached::setFocusNavigation(QSGItem *currentItem, const char *dir)
564 {
565     QSGItem *initialItem = currentItem;
566     bool isNextItem = false;
567     do {
568         isNextItem = false;
569         if (currentItem->isVisible() && currentItem->isEnabled()) {
570             currentItem->setFocus(true);
571         } else {
572             QObject *attached =
573                 qmlAttachedPropertiesObject<QSGKeyNavigationAttached>(currentItem, false);
574             if (attached) {
575                 QSGItem *tempItem = qvariant_cast<QSGItem*>(attached->property(dir));
576                 if (tempItem) {
577                     currentItem = tempItem;
578                     isNextItem = true;
579                 }
580             }
581         }
582     }
583     while (currentItem != initialItem && isNextItem);
584 }
585
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" },
615     { 0, 0 }
616 };
617
618 bool QSGKeysAttachedPrivate::isConnected(const char *signalName)
619 {
620     return isSignalConnected(signalIndex(signalName));
621 }
622
623 QSGKeysAttached::QSGKeysAttached(QObject *parent)
624 : QObject(*(new QSGKeysAttachedPrivate), parent),
625   QSGItemKeyFilter(qobject_cast<QSGItem*>(parent))
626 {
627     Q_D(QSGKeysAttached);
628     m_processPost = false;
629     d->item = qobject_cast<QSGItem*>(parent);
630 }
631
632 QSGKeysAttached::~QSGKeysAttached()
633 {
634 }
635
636 QSGKeysAttached::Priority QSGKeysAttached::priority() const
637 {
638     return m_processPost ? AfterItem : BeforeItem;
639 }
640
641 void QSGKeysAttached::setPriority(Priority order)
642 {
643     bool processPost = order == AfterItem;
644     if (processPost != m_processPost) {
645         m_processPost = processPost;
646         emit priorityChanged();
647     }
648 }
649
650 void QSGKeysAttached::componentComplete()
651 {
652     Q_D(QSGKeysAttached);
653     if (d->item) {
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);
658                 break;
659             }
660         }
661     }
662 }
663
664 void QSGKeysAttached::keyPressed(QKeyEvent *event, bool post)
665 {
666     Q_D(QSGKeysAttached);
667     if (post != m_processPost || !d->enabled || d->inPress) {
668         event->ignore();
669         QSGItemKeyFilter::keyPressed(event, post);
670         return;
671     }
672
673     // first process forwards
674     if (d->item && d->item->canvas()) {
675         d->inPress = true;
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()) {
681                     d->inPress = false;
682                     return;
683                 }
684             }
685         }
686         d->inPress = false;
687     }
688
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));
698         }
699     }
700     if (!ke.isAccepted())
701         emit pressed(&ke);
702     event->setAccepted(ke.isAccepted());
703
704     if (!event->isAccepted()) QSGItemKeyFilter::keyPressed(event, post);
705 }
706
707 void QSGKeysAttached::keyReleased(QKeyEvent *event, bool post)
708 {
709     Q_D(QSGKeysAttached);
710     if (post != m_processPost || !d->enabled || d->inRelease) {
711         event->ignore();
712         QSGItemKeyFilter::keyReleased(event, post);
713         return;
714     }
715
716     if (d->item && d->item->canvas()) {
717         d->inRelease = true;
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;
724                     return;
725                 }
726             }
727         }
728         d->inRelease = false;
729     }
730
731     QSGKeyEvent ke(*event);
732     emit released(&ke);
733     event->setAccepted(ke.isAccepted());
734
735     if (!event->isAccepted()) QSGItemKeyFilter::keyReleased(event, post);
736 }
737
738 void QSGKeysAttached::inputMethodEvent(QInputMethodEvent *event, bool post)
739 {
740     Q_D(QSGKeysAttached);
741     if (post == m_processPost && d->item && !d->inIM && d->item->canvas()) {
742         d->inIM = true;
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()) {
748                     d->imeItem = i;
749                     d->inIM = false;
750                     return;
751                 }
752             }
753         }
754         d->inIM = false;
755     }
756     QSGItemKeyFilter::inputMethodEvent(event, post);
757 }
758
759 QVariant QSGKeysAttached::inputMethodQuery(Qt::InputMethodQuery query) const
760 {
761     Q_D(const QSGKeysAttached);
762     if (d->item) {
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?
770                 return v;
771             }
772         }
773     }
774     return QSGItemKeyFilter::inputMethodQuery(query);
775 }
776
777 QSGKeysAttached *QSGKeysAttached::qmlAttachedProperties(QObject *obj)
778 {
779     return new QSGKeysAttached(obj);
780 }
781
782
783 QSGLayoutMirroringAttached::QSGLayoutMirroringAttached(QObject *parent) : QObject(parent), itemPrivate(0)
784 {
785     if (QSGItem *item = qobject_cast<QSGItem*>(parent)) {
786         itemPrivate = QSGItemPrivate::get(item);
787         itemPrivate->attachedLayoutDirection = this;
788     } else
789         qmlInfo(parent) << tr("LayoutDirection attached property only works with Items");
790 }
791
792 QSGLayoutMirroringAttached * QSGLayoutMirroringAttached::qmlAttachedProperties(QObject *object)
793 {
794     return new QSGLayoutMirroringAttached(object);
795 }
796
797 bool QSGLayoutMirroringAttached::enabled() const
798 {
799     return itemPrivate ? itemPrivate->effectiveLayoutMirror : false;
800 }
801
802 void QSGLayoutMirroringAttached::setEnabled(bool enabled)
803 {
804     if (!itemPrivate)
805         return;
806
807     itemPrivate->isMirrorImplicit = false;
808     if (enabled != itemPrivate->effectiveLayoutMirror) {
809         itemPrivate->setLayoutMirror(enabled);
810         if (itemPrivate->inheritMirrorFromItem)
811              itemPrivate->resolveLayoutMirror();
812     }
813 }
814
815 void QSGLayoutMirroringAttached::resetEnabled()
816 {
817     if (itemPrivate && !itemPrivate->isMirrorImplicit) {
818         itemPrivate->isMirrorImplicit = true;
819         itemPrivate->resolveLayoutMirror();
820     }
821 }
822
823 bool QSGLayoutMirroringAttached::childrenInherit() const
824 {
825     return itemPrivate ? itemPrivate->inheritMirrorFromItem : false;
826 }
827
828 void QSGLayoutMirroringAttached::setChildrenInherit(bool childrenInherit) {
829     if (itemPrivate && childrenInherit != itemPrivate->inheritMirrorFromItem) {
830         itemPrivate->inheritMirrorFromItem = childrenInherit;
831         itemPrivate->resolveLayoutMirror();
832         childrenInheritChanged();
833     }
834 }
835
836 void QSGItemPrivate::resolveLayoutMirror()
837 {
838     Q_Q(QSGItem);
839     if (QSGItem *parentItem = q->parentItem()) {
840         QSGItemPrivate *parentPrivate = QSGItemPrivate::get(parentItem);
841         setImplicitLayoutMirror(parentPrivate->inheritedLayoutMirror, parentPrivate->inheritMirrorFromParent);
842     } else {
843         setImplicitLayoutMirror(isMirrorImplicit ? false : effectiveLayoutMirror, inheritMirrorFromItem);
844     }
845 }
846
847 void QSGItemPrivate::setImplicitLayoutMirror(bool mirror, bool inherit)
848 {
849     inherit = inherit || inheritMirrorFromItem;
850     if (!isMirrorImplicit && inheritMirrorFromItem)
851         mirror = effectiveLayoutMirror;
852     if (mirror == inheritedLayoutMirror && inherit == inheritMirrorFromParent)
853         return;
854
855     inheritMirrorFromParent = inherit;
856     inheritedLayoutMirror = inheritMirrorFromParent ? mirror : false;
857
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);
864         }
865     }
866 }
867
868 void QSGItemPrivate::setLayoutMirror(bool mirror)
869 {
870     if (mirror != effectiveLayoutMirror) {
871         effectiveLayoutMirror = mirror;
872         if (_anchors) {
873             QSGAnchorsPrivate *anchor_d = QSGAnchorsPrivate::get(_anchors);
874             anchor_d->fillChanged();
875             anchor_d->centerInChanged();
876             anchor_d->updateHorizontalAnchors();
877             emit _anchors->mirroredChanged();
878         }
879         mirrorChange();
880         if (attachedLayoutDirection) {
881             emit attachedLayoutDirection->enabledChanged();
882         }
883     }
884 }
885
886 QSGItem::QSGItem(QSGItem* parent)
887 : QObject(*(new QSGItemPrivate), parent)
888 {
889     Q_D(QSGItem);
890     d->init(parent);
891 }
892
893 QSGItem::QSGItem(QSGItemPrivate &dd, QSGItem *parent)
894 : QObject(dd, parent)
895 {
896     Q_D(QSGItem);
897     d->init(parent);
898 }
899
900 QSGItem::~QSGItem()
901 {
902     Q_D(QSGItem);
903
904     // XXX todo - optimize
905     setParentItem(0);
906     while (!d->childItems.isEmpty())
907         d->childItems.first()->setParentItem(0);
908     
909     for (int ii = 0; ii < d->changeListeners.count(); ++ii) {
910         QSGAnchorsPrivate *anchor = d->changeListeners.at(ii).listener->anchorPrivate();
911         if (anchor)
912             anchor->clearItem(this);
913     }
914
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();
920     }
921     
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);
926     }
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;
932 }
933
934 void QSGItem::setParentItem(QSGItem *parentItem)
935 {
936     Q_D(QSGItem);
937     if (parentItem == d->parentItem)
938         return;
939
940     d->removeFromDirtyList();
941
942     QSGItem *oldParentItem = d->parentItem;
943     QSGItem *scopeFocusedItem = 0;
944
945     if (oldParentItem) {
946         QSGItemPrivate *op = QSGItemPrivate::get(oldParentItem);
947
948         QSGItem *scopeItem = 0;
949
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;
958         } 
959
960         if (scopeFocusedItem) 
961             QSGCanvasPrivate::get(d->canvas)->clearFocusInScope(scopeItem, scopeFocusedItem, 
962                                                                 QSGCanvasPrivate::DontChangeFocusProperty);
963
964         op->removeChild(this);
965     }
966
967     d->parentItem = parentItem;
968
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);
973
974         QSGItemPrivate::InitializationState initState;
975         initState.clear();
976         d->initCanvas(&initState, parentCanvas);
977     }
978
979     d->dirty(QSGItemPrivate::ParentChanged);
980     
981     if (d->parentItem)
982         QSGItemPrivate::get(d->parentItem)->addChild(this);
983
984     d->setEffectiveVisibleRecur(d->calcEffectiveVisible());
985     d->setEffectiveEnableRecur(d->calcEffectiveEnable());
986
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();
992
993         if (scopeItem->scopedFocusItem()) {
994             QSGItemPrivate::get(scopeFocusedItem)->focus = false;
995             emit scopeFocusedItem->focusChanged(false);
996         } else {
997             QSGCanvasPrivate::get(d->canvas)->setFocusInScope(scopeItem, scopeFocusedItem, 
998                                                               QSGCanvasPrivate::DontChangeFocusProperty);
999         }
1000     }
1001
1002     d->resolveLayoutMirror();
1003
1004     d->itemChange(ItemParentHasChanged, d->parentItem);
1005
1006     emit parentChanged(d->parentItem);
1007 }
1008
1009 void QSGItem::stackBefore(const QSGItem *sibling)
1010 {
1011     Q_D(QSGItem);
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);
1014         return;
1015     }
1016
1017     QSGItemPrivate *parentPrivate = QSGItemPrivate::get(d->parentItem);
1018
1019     int myIndex = parentPrivate->childItems.indexOf(this);
1020     int siblingIndex = parentPrivate->childItems.indexOf(const_cast<QSGItem *>(sibling));
1021     
1022     Q_ASSERT(myIndex != -1 && siblingIndex != -1);
1023
1024     if (myIndex == siblingIndex - 1)
1025         return;
1026
1027     parentPrivate->childItems.removeAt(myIndex);
1028
1029     if (myIndex < siblingIndex) --siblingIndex;
1030
1031     parentPrivate->childItems.insert(siblingIndex, this);
1032
1033     parentPrivate->dirty(QSGItemPrivate::ChildrenStackingChanged);
1034
1035     for (int ii = qMin(siblingIndex, myIndex); ii < parentPrivate->childItems.count(); ++ii) 
1036         QSGItemPrivate::get(parentPrivate->childItems.at(ii))->siblingOrderChanged();
1037 }
1038
1039 void QSGItem::stackAfter(const QSGItem *sibling)
1040 {
1041     Q_D(QSGItem);
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);
1044         return;
1045     }
1046
1047     QSGItemPrivate *parentPrivate = QSGItemPrivate::get(d->parentItem);
1048
1049     int myIndex = parentPrivate->childItems.indexOf(this);
1050     int siblingIndex = parentPrivate->childItems.indexOf(const_cast<QSGItem *>(sibling));
1051     
1052     Q_ASSERT(myIndex != -1 && siblingIndex != -1);
1053
1054     if (myIndex == siblingIndex + 1)
1055         return;
1056
1057     parentPrivate->childItems.removeAt(myIndex);
1058
1059     if (myIndex < siblingIndex) --siblingIndex;
1060
1061     parentPrivate->childItems.insert(siblingIndex + 1, this);
1062
1063     parentPrivate->dirty(QSGItemPrivate::ChildrenStackingChanged);
1064
1065     for (int ii = qMin(myIndex, siblingIndex + 1); ii < parentPrivate->childItems.count(); ++ii) 
1066         QSGItemPrivate::get(parentPrivate->childItems.at(ii))->siblingOrderChanged();
1067 }
1068
1069 /*!
1070     Returns the QSGItem parent of this item.
1071 */
1072 QSGItem *QSGItem::parentItem() const
1073 {
1074     Q_D(const QSGItem);
1075     return d->parentItem;
1076 }
1077
1078 QSGEngine *QSGItem::sceneGraphEngine() const
1079 {
1080     return canvas()->sceneGraphEngine();
1081 }
1082
1083 QSGCanvas *QSGItem::canvas() const 
1084
1085     Q_D(const QSGItem);
1086     return d->canvas;
1087 }
1088
1089 static bool itemZOrder_sort(QSGItem *lhs, QSGItem *rhs)
1090 {
1091     return lhs->z() < rhs->z();
1092 }
1093
1094 QList<QSGItem *> QSGItemPrivate::paintOrderChildItems() const
1095 {
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);
1100     return items;
1101 }
1102
1103 void QSGItemPrivate::addChild(QSGItem *child)
1104 {
1105     Q_Q(QSGItem);
1106
1107     Q_ASSERT(!childItems.contains(child));
1108
1109     childItems.append(child);
1110
1111     dirty(QSGItemPrivate::ChildrenChanged);
1112
1113     itemChange(QSGItem::ItemChildAddedChange, child);
1114
1115     emit q->childrenChanged();
1116 }
1117
1118 void QSGItemPrivate::removeChild(QSGItem *child)
1119 {
1120     Q_Q(QSGItem);
1121
1122     Q_ASSERT(child);
1123     Q_ASSERT(childItems.contains(child));
1124     childItems.removeOne(child);
1125     Q_ASSERT(!childItems.contains(child));
1126
1127     dirty(QSGItemPrivate::ChildrenChanged);
1128
1129     itemChange(QSGItem::ItemChildRemovedChange, child);
1130
1131     emit q->childrenChanged();
1132 }
1133
1134 void QSGItemPrivate::InitializationState::clear() 
1135
1136     focusScope = 0; 
1137 }
1138
1139 void QSGItemPrivate::InitializationState::clear(QSGItem *fs) 
1140
1141     focusScope = fs;
1142 }
1143
1144 QSGItem *QSGItemPrivate::InitializationState::getFocusScope(QSGItem *item)
1145 {
1146     if (!focusScope) {
1147         QSGItem *fs = item->parentItem();
1148         while (!fs->isFocusScope())
1149             fs = fs->parentItem();
1150         focusScope = fs;
1151     }
1152     return focusScope;
1153 }
1154
1155 void QSGItemPrivate::initCanvas(InitializationState *state, QSGCanvas *c)
1156 {
1157     Q_Q(QSGItem);
1158
1159     if (canvas) {
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;
1166     }
1167
1168     canvas = c;
1169
1170     if (canvas && polishScheduled) 
1171         QSGCanvasPrivate::get(canvas)->itemsToPolish.insert(q);
1172
1173     if (canvas && hoverEnabled && !canvas->hasMouseTracking())
1174         canvas->setMouseTracking(true);
1175
1176     // XXX todo - why aren't these added to the destroy list?
1177     itemNodeInstance = 0;
1178     opacityNode = 0;
1179     clipNode = 0;
1180     rootNode = 0;
1181     groupNode = 0;
1182     paintNode = 0;
1183     paintNodeIndex = 0;
1184
1185     InitializationState _dummy;
1186     InitializationState *childState = state;
1187
1188     if (c && q->isFocusScope()) {
1189         _dummy.clear(q);
1190         childState = &_dummy;
1191     }
1192
1193     for (int ii = 0; ii < childItems.count(); ++ii) {
1194         QSGItem *child = childItems.at(ii);
1195         QSGItemPrivate::get(child)->initCanvas(childState, c);
1196     }
1197
1198     if (c && focus) {
1199         // Fixup
1200         if (state->getFocusScope(q)->scopedFocusItem()) {
1201             focus = false;
1202             emit q->focusChanged(false);
1203         } else {
1204             QSGCanvasPrivate::get(canvas)->setFocusInScope(state->getFocusScope(q), q);
1205         }
1206     }
1207
1208     dirty(Canvas);
1209
1210     itemChange(QSGItem::ItemSceneChange, c);
1211 }
1212
1213 /*!
1214 Returns a transform that maps points from canvas space into item space.
1215 */
1216 QTransform QSGItemPrivate::canvasToItemTransform() const
1217 {
1218     // XXX todo - optimize
1219     return itemToCanvasTransform().inverted();
1220 }
1221
1222 /*!
1223 Returns a transform that maps points from item space into canvas space.
1224 */
1225 QTransform QSGItemPrivate::itemToCanvasTransform() const
1226 {
1227     // XXX todo
1228     QTransform rv = parentItem?QSGItemPrivate::get(parentItem)->itemToCanvasTransform():QTransform();
1229     itemToParentTransform(rv);
1230     return rv;
1231 }
1232
1233 /*!
1234 Motifies \a t with this items local transform relative to its parent.
1235 */
1236 void QSGItemPrivate::itemToParentTransform(QTransform &t) const
1237 {
1238     if (x || y)
1239         t.translate(x, y);
1240
1241     if (!transforms.isEmpty()) {
1242         QMatrix4x4 m(t);
1243         for (int ii = transforms.count() - 1; ii >= 0; --ii)
1244             transforms.at(ii)->applyTo(&m);
1245         t = m.toTransform();
1246     }
1247
1248     if (scale != 1. || rotation != 0.) {
1249         QPointF tp = computeTransformOrigin();
1250         t.translate(tp.x(), tp.y());
1251         t.scale(scale, scale);
1252         t.rotate(rotation);
1253         t.translate(-tp.x(), -tp.y());
1254     }
1255 }
1256
1257 bool QSGItem::isComponentComplete() const
1258 {
1259     Q_D(const QSGItem);
1260     return d->componentComplete;
1261 }
1262
1263 QSGItemPrivate::QSGItemPrivate()
1264 : _anchors(0), _contents(0), baselineOffset(0), _anchorLines(0), _stateGroup(0), origin(QSGItem::Center), 
1265     
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),
1272
1273   canvas(0), parentItem(0),
1274
1275   subFocusItem(0),
1276
1277   x(0), y(0), width(0), height(0), implicitWidth(0), implicitHeight(0), 
1278   z(0), scale(1), rotation(0), opacity(1),
1279
1280   attachedLayoutDirection(0), acceptedMouseButtons(0),
1281   imHints(Qt::ImhNone),
1282   
1283   keyHandler(0),
1284
1285   dirtyAttributes(0), nextDirtyItem(0), prevDirtyItem(0),
1286
1287   itemNodeInstance(0), opacityNode(0), clipNode(0), rootNode(0), groupNode(0), paintNode(0)
1288   , paintNodeIndex(0), effectRefCount(0), hideRefCount(0)
1289 {
1290 }
1291
1292 void QSGItemPrivate::init(QSGItem *parent)
1293 {
1294     Q_Q(QSGItem);
1295     baselineOffset.invalidate();
1296
1297     if (parent) {
1298         q->setParentItem(parent);
1299         QSGItemPrivate *parentPrivate = QSGItemPrivate::get(parent);
1300         setImplicitLayoutMirror(parentPrivate->inheritedLayoutMirror, parentPrivate->inheritMirrorFromParent);
1301     }
1302 }
1303
1304 void QSGItemPrivate::data_append(QDeclarativeListProperty<QObject> *prop, QObject *o)
1305 {
1306     if (!o)
1307         return;
1308
1309     QSGItem *that = static_cast<QSGItem *>(prop->object);
1310
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;
1317     }
1318
1319     if (mo) {
1320         QSGItem *item = static_cast<QSGItem *>(o);
1321         item->setParentItem(that);
1322     } else {
1323         // XXX todo - do we really want this behavior?
1324         o->setParent(that);
1325     }
1326 }
1327
1328 int QSGItemPrivate::data_count(QDeclarativeListProperty<QObject> *prop)
1329 {
1330     Q_UNUSED(prop);
1331     // XXX todo
1332     return 0;
1333 }
1334
1335 QObject *QSGItemPrivate::data_at(QDeclarativeListProperty<QObject> *prop, int i)
1336 {
1337     Q_UNUSED(prop);
1338     Q_UNUSED(i);
1339     // XXX todo
1340     return 0;
1341 }
1342
1343 void QSGItemPrivate::data_clear(QDeclarativeListProperty<QObject> *prop)
1344 {
1345     Q_UNUSED(prop);
1346     // XXX todo
1347 }
1348
1349 QObject *QSGItemPrivate::resources_at(QDeclarativeListProperty<QObject> *prop, int index)
1350 {
1351     const QObjectList children = prop->object->children();
1352     if (index < children.count())
1353         return children.at(index);
1354     else
1355         return 0;
1356 }
1357
1358 void QSGItemPrivate::resources_append(QDeclarativeListProperty<QObject> *prop, QObject *o)
1359 {
1360     // XXX todo - do we really want this behavior?
1361     o->setParent(prop->object);
1362 }
1363
1364 int QSGItemPrivate::resources_count(QDeclarativeListProperty<QObject> *prop)
1365 {
1366     return prop->object->children().count();
1367 }
1368
1369 void QSGItemPrivate::resources_clear(QDeclarativeListProperty<QObject> *prop)
1370 {
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);
1375 }
1376
1377 QSGItem *QSGItemPrivate::children_at(QDeclarativeListProperty<QSGItem> *prop, int index)
1378 {
1379     QSGItemPrivate *p = QSGItemPrivate::get(static_cast<QSGItem *>(prop->object));
1380     if (index >= p->childItems.count() || index < 0)
1381         return 0;
1382     else
1383         return p->childItems.at(index);
1384 }
1385
1386 void QSGItemPrivate::children_append(QDeclarativeListProperty<QSGItem> *prop, QSGItem *o)
1387 {
1388     if (!o)
1389         return;
1390
1391     QSGItem *that = static_cast<QSGItem *>(prop->object);
1392     if (o->parentItem() == that)
1393         o->setParentItem(0);
1394
1395     o->setParentItem(that);
1396 }
1397
1398 int QSGItemPrivate::children_count(QDeclarativeListProperty<QSGItem> *prop)
1399 {
1400     QSGItemPrivate *p = QSGItemPrivate::get(static_cast<QSGItem *>(prop->object));
1401     return p->childItems.count();
1402 }
1403
1404 void QSGItemPrivate::children_clear(QDeclarativeListProperty<QSGItem> *prop)
1405 {
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);
1410 }
1411
1412 int QSGItemPrivate::transform_count(QDeclarativeListProperty<QSGTransform> *prop)
1413 {
1414     QSGItem *that = static_cast<QSGItem *>(prop->object);
1415     return QSGItemPrivate::get(that)->transforms.count();
1416 }
1417
1418 void QSGTransform::appendToItem(QSGItem *item)
1419 {
1420     Q_D(QSGTransform);
1421     if (!item)
1422         return;
1423
1424     QSGItemPrivate *p = QSGItemPrivate::get(item);
1425
1426     if (!d->items.isEmpty() && !p->transforms.isEmpty() && p->transforms.contains(this)) {
1427         p->transforms.removeOne(this);
1428         p->transforms.append(this);
1429     } else {
1430         p->transforms.append(this);
1431         d->items.append(item);
1432     }
1433
1434     p->dirty(QSGItemPrivate::Transform);
1435 }
1436
1437 void QSGTransform::prependToItem(QSGItem *item)
1438 {
1439     Q_D(QSGTransform);
1440     if (!item)
1441         return;
1442
1443     QSGItemPrivate *p = QSGItemPrivate::get(item);
1444
1445     if (!d->items.isEmpty() && !p->transforms.isEmpty() && p->transforms.contains(this)) {
1446         p->transforms.removeOne(this);
1447         p->transforms.prepend(this);
1448     } else {
1449         p->transforms.prepend(this);
1450         d->items.append(item);
1451     }
1452
1453     p->dirty(QSGItemPrivate::Transform);
1454 }
1455
1456 void QSGItemPrivate::transform_append(QDeclarativeListProperty<QSGTransform> *prop, QSGTransform *transform)
1457 {
1458     if (!transform)
1459         return;
1460
1461     QSGItem *that = static_cast<QSGItem *>(prop->object);
1462     transform->appendToItem(that);
1463 }
1464
1465 QSGTransform *QSGItemPrivate::transform_at(QDeclarativeListProperty<QSGTransform> *prop, int idx)
1466 {
1467     QSGItem *that = static_cast<QSGItem *>(prop->object);
1468     QSGItemPrivate *p = QSGItemPrivate::get(that);
1469
1470     if (idx < 0 || idx >= p->transforms.count())
1471         return 0;
1472     else
1473         return p->transforms.at(idx);
1474 }
1475
1476 void QSGItemPrivate::transform_clear(QDeclarativeListProperty<QSGTransform> *prop)
1477 {
1478     QSGItem *that = static_cast<QSGItem *>(prop->object);
1479     QSGItemPrivate *p = QSGItemPrivate::get(that);
1480
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);
1485     }
1486
1487     p->transforms.clear();
1488
1489     p->dirty(QSGItemPrivate::Transform);
1490 }
1491
1492 QSGAnchors *QSGItemPrivate::anchors() const
1493 {
1494     if (!_anchors) {
1495         Q_Q(const QSGItem);
1496         _anchors = new QSGAnchors(const_cast<QSGItem *>(q));
1497         if (!componentComplete)
1498             _anchors->classBegin();
1499     }
1500     return _anchors;
1501 }
1502
1503 QSGItemPrivate::AnchorLines *QSGItemPrivate::anchorLines() const 
1504 {
1505     Q_Q(const QSGItem);
1506     if (!_anchorLines) _anchorLines =
1507         new AnchorLines(const_cast<QSGItem *>(q));
1508     return _anchorLines;
1509 }
1510
1511 void QSGItemPrivate::siblingOrderChanged()
1512 {
1513     Q_Q(QSGItem);
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);
1518         }
1519     }
1520 }
1521
1522 QDeclarativeListProperty<QObject> QSGItemPrivate::data()
1523 {
1524     return QDeclarativeListProperty<QObject>(q_func(), 0, QSGItemPrivate::data_append,
1525                                              QSGItemPrivate::data_count,
1526                                              QSGItemPrivate::data_at,
1527                                              QSGItemPrivate::data_clear);
1528 }
1529
1530 QRectF QSGItem::childrenRect()
1531 {
1532     Q_D(QSGItem);
1533     if (!d->_contents) {
1534         d->_contents = new QSGContents(this);
1535         if (d->componentComplete)
1536             d->_contents->complete();
1537     }
1538     return d->_contents->rectF();
1539 }
1540
1541 QList<QSGItem *> QSGItem::childItems() const
1542 {
1543     Q_D(const QSGItem);
1544     return d->childItems;
1545 }
1546
1547 bool QSGItem::clip() const
1548 {
1549     return flags() & ItemClipsChildrenToShape;
1550 }
1551
1552 void QSGItem::setClip(bool c)
1553 {
1554     if (clip() == c)
1555         return;
1556
1557     setFlag(ItemClipsChildrenToShape, c);
1558
1559     emit clipChanged(c);
1560 }
1561
1562 void QSGItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
1563 {
1564     Q_D(QSGItem);
1565
1566     if (d->_anchors)
1567         QSGAnchorsPrivate::get(d->_anchors)->updateMe();
1568
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);
1573     }
1574
1575     if (newGeometry.x() != oldGeometry.x())
1576         emit xChanged();
1577     if (newGeometry.y() != oldGeometry.y())
1578         emit yChanged();
1579     if (newGeometry.width() != oldGeometry.width())
1580         emit widthChanged();
1581     if (newGeometry.height() != oldGeometry.height())
1582         emit heightChanged();
1583 }
1584
1585 /*!
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.
1589
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.
1592
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.
1596  */
1597
1598 QSGNode *QSGItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
1599 {
1600     delete oldNode;
1601     return 0;
1602 }
1603
1604 QSGTransformNode *QSGItemPrivate::createTransformNode()
1605 {
1606     return new QSGTransformNode;
1607 }
1608
1609 void QSGItem::updatePolish()
1610 {
1611 }
1612
1613 void QSGItemPrivate::removeItemChangeListener(QSGItemChangeListener *listener, ChangeTypes types)
1614 {
1615     ChangeListener change(listener, types);
1616     changeListeners.removeOne(change);
1617 }
1618
1619 void QSGItem::keyPressEvent(QKeyEvent *event)
1620 {
1621     event->ignore();
1622 }
1623
1624 void QSGItem::keyReleaseEvent(QKeyEvent *event)
1625 {
1626     event->ignore();
1627 }
1628
1629 void QSGItem::inputMethodEvent(QInputMethodEvent *event)
1630 {
1631     event->ignore();
1632 }
1633
1634 void QSGItem::focusInEvent(QFocusEvent *)
1635 {
1636 }
1637
1638 void QSGItem::focusOutEvent(QFocusEvent *)
1639 {
1640 }
1641
1642 void QSGItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
1643 {
1644     event->ignore();
1645 }
1646
1647 void QSGItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
1648 {
1649     event->ignore();
1650 }
1651
1652 void QSGItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
1653 {
1654     event->ignore();
1655 }
1656
1657 void QSGItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
1658 {
1659     mousePressEvent(event);
1660 }
1661
1662 void QSGItem::mouseUngrabEvent()
1663 {
1664     // XXX todo
1665 }
1666
1667 void QSGItem::wheelEvent(QGraphicsSceneWheelEvent *event)
1668 {
1669     event->ignore();
1670 }
1671
1672 void QSGItem::touchEvent(QTouchEvent *event)
1673 {
1674     event->ignore();
1675 }
1676
1677 void QSGItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
1678 {
1679     Q_UNUSED(event);
1680 }
1681
1682 void QSGItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
1683 {
1684     Q_UNUSED(event);
1685 }
1686
1687 void QSGItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
1688 {
1689     Q_UNUSED(event);
1690 }
1691
1692 bool QSGItem::childMouseEventFilter(QSGItem *, QEvent *)
1693 {
1694     return false;
1695 }
1696
1697 Qt::InputMethodHints QSGItem::inputMethodHints() const
1698 {
1699     Q_D(const QSGItem);
1700     return d->imHints;
1701 }
1702
1703 void QSGItem::setInputMethodHints(Qt::InputMethodHints hints)
1704 {
1705     Q_D(QSGItem);
1706     d->imHints = hints;
1707
1708     if (!d->canvas || d->canvas->activeFocusItem() != this)
1709         return;
1710
1711     QSGCanvasPrivate::get(d->canvas)->updateInputMethodData();
1712 #ifndef QT_NO_IM
1713     if (d->canvas->hasFocus())
1714         if (QInputContext *inputContext = d->canvas->inputContext())
1715             inputContext->update();
1716 #endif
1717 }
1718
1719 void QSGItem::updateMicroFocus()
1720 {
1721 #ifndef QT_NO_IM
1722     Q_D(QSGItem);
1723     if (d->canvas && d->canvas->hasFocus())
1724         if (QInputContext *inputContext = d->canvas->inputContext())
1725             inputContext->update();
1726 #endif
1727 }
1728
1729 QVariant QSGItem::inputMethodQuery(Qt::InputMethodQuery query) const
1730 {
1731     Q_D(const QSGItem);
1732     QVariant v;
1733
1734     if (d->keyHandler)
1735         v = d->keyHandler->inputMethodQuery(query);
1736
1737     return v;
1738 }
1739
1740 QSGAnchorLine QSGItemPrivate::left() const
1741 {
1742     return anchorLines()->left;
1743 }
1744
1745 QSGAnchorLine QSGItemPrivate::right() const
1746 {
1747     return anchorLines()->right;
1748 }
1749
1750 QSGAnchorLine QSGItemPrivate::horizontalCenter() const
1751 {
1752     return anchorLines()->hCenter;
1753 }
1754
1755 QSGAnchorLine QSGItemPrivate::top() const
1756 {
1757     return anchorLines()->top;
1758 }
1759
1760 QSGAnchorLine QSGItemPrivate::bottom() const
1761 {
1762     return anchorLines()->bottom;
1763 }
1764
1765 QSGAnchorLine QSGItemPrivate::verticalCenter() const
1766 {
1767     return anchorLines()->vCenter;
1768 }
1769
1770 QSGAnchorLine QSGItemPrivate::baseline() const
1771 {
1772     return anchorLines()->baseline;
1773 }
1774
1775 qreal QSGItem::baselineOffset() const
1776 {
1777     Q_D(const QSGItem);
1778     if (!d->baselineOffset.isValid()) {
1779         return 0.0;
1780     } else
1781         return d->baselineOffset;
1782 }
1783
1784 void QSGItem::setBaselineOffset(qreal offset)
1785 {
1786     Q_D(QSGItem);
1787     if (offset == d->baselineOffset)
1788         return;
1789
1790     d->baselineOffset = offset;
1791
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();
1796             if (anchor)
1797                 anchor->updateVerticalAnchors();
1798         }
1799     }
1800     emit baselineOffsetChanged(offset);
1801 }
1802
1803 void QSGItem::update()
1804 {
1805     Q_D(QSGItem);
1806     Q_ASSERT(flags() & ItemHasContents);
1807     d->dirty(QSGItemPrivate::Content);
1808 }
1809
1810 void QSGItem::polish()
1811 {
1812     Q_D(QSGItem);
1813     if (!d->polishScheduled) {
1814         d->polishScheduled = true;
1815         if (d->canvas)
1816             QSGCanvasPrivate::get(d->canvas)->itemsToPolish.insert(this);
1817     }
1818 }
1819
1820 QScriptValue QSGItem::mapFromItem(const QScriptValue &item, qreal x, qreal y) const
1821 {
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";
1826         return 0;
1827     }
1828
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());
1833     return sv;
1834 }
1835
1836 QTransform QSGItem::itemTransform(QSGItem *other, bool *ok) const
1837 {
1838     Q_D(const QSGItem);
1839
1840     // XXX todo - we need to be able to handle common parents better and detect 
1841     // invalid cases
1842     if (ok) *ok = true;
1843
1844     QTransform t = d->itemToCanvasTransform();
1845     if (other) t *= QSGItemPrivate::get(other)->canvasToItemTransform();
1846
1847     return t;
1848 }
1849
1850 QScriptValue QSGItem::mapToItem(const QScriptValue &item, qreal x, qreal y) const
1851 {
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";
1856         return 0;
1857     }
1858
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());
1863     return sv;
1864 }
1865
1866 void QSGItem::forceActiveFocus()
1867 {
1868     setFocus(true);
1869     QSGItem *parent = parentItem();
1870     while (parent) {
1871         if (parent->flags() & QSGItem::ItemIsFocusScope) {
1872             parent->setFocus(true);
1873         } 
1874         parent = parent->parentItem();
1875     }
1876 }
1877
1878 QSGItem *QSGItem::childAt(qreal x, qreal y) const
1879 {
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
1886                 && child->y() <= y
1887                 && child->y() + child->height() >= y)
1888                 return child;
1889         }
1890     }
1891     return 0;
1892 }
1893
1894 QDeclarativeListProperty<QObject> QSGItemPrivate::resources()
1895 {
1896     return QDeclarativeListProperty<QObject>(q_func(), 0, QSGItemPrivate::resources_append,
1897                                              QSGItemPrivate::resources_count,
1898                                              QSGItemPrivate::resources_at,
1899                                              QSGItemPrivate::resources_clear);
1900 }
1901
1902 QDeclarativeListProperty<QSGItem> QSGItemPrivate::children()
1903 {
1904     return QDeclarativeListProperty<QSGItem>(q_func(), 0, QSGItemPrivate::children_append, 
1905                                              QSGItemPrivate::children_count,
1906                                              QSGItemPrivate::children_at,
1907                                              QSGItemPrivate::children_clear);
1908                                      
1909 }
1910
1911 QDeclarativeListProperty<QDeclarativeState> QSGItemPrivate::states()
1912 {
1913     return _states()->statesProperty();
1914 }
1915
1916 QDeclarativeListProperty<QDeclarativeTransition> QSGItemPrivate::transitions()
1917 {
1918     return _states()->transitionsProperty();
1919 }
1920
1921 QString QSGItemPrivate::state() const
1922 {
1923     if (!_stateGroup)
1924         return QString();
1925     else
1926         return _stateGroup->state();
1927 }
1928
1929 void QSGItemPrivate::setState(const QString &state)
1930 {
1931     _states()->setState(state);
1932 }
1933
1934 QDeclarativeListProperty<QSGTransform> QSGItem::transform()
1935 {
1936     Q_D(QSGItem);
1937     return QDeclarativeListProperty<QSGTransform>(this, 0, d->transform_append, d->transform_count,
1938                                                   d->transform_at, d->transform_clear);
1939 }
1940
1941 void QSGItem::classBegin()
1942 {
1943     Q_D(QSGItem);
1944     d->componentComplete = false;
1945     if (d->_stateGroup)
1946         d->_stateGroup->classBegin();
1947     if (d->_anchors)
1948         d->_anchors->classBegin();
1949 }
1950
1951 void QSGItem::componentComplete()
1952 {
1953     Q_D(QSGItem);
1954     d->componentComplete = true;
1955     if (d->_stateGroup)
1956         d->_stateGroup->componentComplete();
1957     if (d->_anchors) {
1958         d->_anchors->componentComplete();
1959         QSGAnchorsPrivate::get(d->_anchors)->updateOnComplete();
1960     }
1961     if (d->keyHandler)
1962         d->keyHandler->componentComplete();
1963     if (d->_contents)
1964         d->_contents->complete();
1965 }
1966
1967 QDeclarativeStateGroup *QSGItemPrivate::_states()
1968 {
1969     Q_Q(QSGItem);
1970     if (!_stateGroup) {
1971         _stateGroup = new QDeclarativeStateGroup;
1972         if (!componentComplete)
1973             _stateGroup->classBegin();
1974         QObject::connect(_stateGroup, SIGNAL(stateChanged(QString)),
1975                          q, SIGNAL(stateChanged(QString)));
1976     }
1977
1978     return _stateGroup;
1979 }
1980
1981 QSGItemPrivate::AnchorLines::AnchorLines(QSGItem *q)
1982 {
1983     left.item = q;
1984     left.anchorLine = QSGAnchorLine::Left;
1985     right.item = q;
1986     right.anchorLine = QSGAnchorLine::Right;
1987     hCenter.item = q;
1988     hCenter.anchorLine = QSGAnchorLine::HCenter;
1989     top.item = q;
1990     top.anchorLine = QSGAnchorLine::Top;
1991     bottom.item = q;
1992     bottom.anchorLine = QSGAnchorLine::Bottom;
1993     vCenter.item = q;
1994     vCenter.anchorLine = QSGAnchorLine::VCenter;
1995     baseline.item = q;
1996     baseline.anchorLine = QSGAnchorLine::Baseline;
1997 }
1998
1999 QPointF QSGItemPrivate::computeTransformOrigin() const
2000 {
2001     switch(origin) {
2002     default:
2003     case QSGItem::TopLeft:
2004         return QPointF(0, 0);
2005     case QSGItem::Top:
2006         return QPointF(width / 2., 0);
2007     case QSGItem::TopRight:
2008         return QPointF(width, 0);
2009     case QSGItem::Left:
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);
2021     }
2022 }
2023
2024 void QSGItemPrivate::transformChanged()
2025 {
2026 }
2027
2028 void QSGItemPrivate::deliverKeyEvent(QKeyEvent *e)
2029 {
2030     Q_Q(QSGItem);
2031     
2032     Q_ASSERT(e->isAccepted());
2033     if (keyHandler) {
2034         if (e->type() == QEvent::KeyPress)
2035             keyHandler->keyPressed(e, false);
2036         else
2037             keyHandler->keyReleased(e, false);
2038
2039         if (e->isAccepted())
2040             return;
2041         else
2042             e->accept();
2043     }
2044
2045     if (e->type() == QEvent::KeyPress)
2046         q->keyPressEvent(e);
2047     else
2048         q->keyReleaseEvent(e);
2049
2050     if (e->isAccepted())
2051         return;
2052
2053     if (keyHandler) {
2054         e->accept();
2055
2056         if (e->type() == QEvent::KeyPress)
2057             keyHandler->keyPressed(e, true);
2058         else
2059             keyHandler->keyReleased(e, true);
2060     }
2061 }
2062
2063 void QSGItemPrivate::deliverInputMethodEvent(QInputMethodEvent *e)
2064 {
2065     Q_Q(QSGItem);
2066
2067     Q_ASSERT(e->isAccepted());
2068     if (keyHandler) {
2069         keyHandler->inputMethodEvent(e, false);
2070
2071         if (e->isAccepted())
2072             return;
2073         else
2074             e->accept();
2075     }
2076
2077     q->inputMethodEvent(e);
2078
2079     if (e->isAccepted())
2080         return;
2081
2082     if (keyHandler) {
2083         e->accept();
2084
2085         keyHandler->inputMethodEvent(e, true);
2086     }
2087 }
2088
2089 void QSGItemPrivate::deliverFocusEvent(QFocusEvent *e)
2090 {
2091     Q_Q(QSGItem);
2092
2093     if (e->type() == QEvent::FocusIn) {
2094         q->focusInEvent(e);
2095     } else {
2096         q->focusOutEvent(e);
2097     }
2098 }
2099
2100 void QSGItemPrivate::deliverMouseEvent(QGraphicsSceneMouseEvent *e)
2101 {
2102     Q_Q(QSGItem);
2103
2104     Q_ASSERT(e->isAccepted());
2105
2106     switch(e->type()) {
2107     default:
2108         Q_ASSERT(!"Unknown event type");
2109     case QEvent::GraphicsSceneMouseMove:
2110         q->mouseMoveEvent(e);
2111         break;
2112     case QEvent::GraphicsSceneMousePress:
2113         q->mousePressEvent(e);
2114         break;
2115     case QEvent::GraphicsSceneMouseRelease:
2116         q->mouseReleaseEvent(e);
2117         break;
2118     case QEvent::GraphicsSceneMouseDoubleClick:
2119         q->mouseDoubleClickEvent(e);
2120         break;
2121     }
2122 }
2123
2124 void QSGItemPrivate::deliverWheelEvent(QGraphicsSceneWheelEvent *e)
2125 {
2126     Q_Q(QSGItem);
2127     q->wheelEvent(e);
2128 }
2129
2130 void QSGItemPrivate::deliverTouchEvent(QTouchEvent *e)
2131 {
2132     Q_Q(QSGItem);
2133     q->touchEvent(e);
2134 }
2135
2136 void QSGItemPrivate::deliverHoverEvent(QGraphicsSceneHoverEvent *e)
2137 {
2138     Q_Q(QSGItem);
2139     switch(e->type()) {
2140     default:
2141         Q_ASSERT(!"Unknown event type");
2142     case QEvent::GraphicsSceneHoverEnter:
2143         q->hoverEnterEvent(e);
2144         break;
2145     case QEvent::GraphicsSceneHoverLeave:
2146         q->hoverLeaveEvent(e);
2147         break;
2148     case QEvent::GraphicsSceneHoverMove:
2149         q->hoverMoveEvent(e);
2150         break;
2151     }
2152 }
2153
2154 void QSGItem::itemChange(ItemChange change, const ItemChangeData &value)
2155 {
2156     Q_UNUSED(change);
2157     Q_UNUSED(value);
2158 }
2159
2160 /*! \internal */
2161 // XXX todo - do we want/need this anymore?
2162 QRectF QSGItem::boundingRect() const
2163 {
2164     Q_D(const QSGItem);
2165     return QRectF(0, 0, d->width, d->height);
2166 }
2167
2168 QSGItem::TransformOrigin QSGItem::transformOrigin() const
2169 {
2170     Q_D(const QSGItem);
2171     return d->origin;
2172 }
2173
2174 void QSGItem::setTransformOrigin(TransformOrigin origin)
2175 {
2176     Q_D(QSGItem);
2177     if (origin == d->origin) 
2178         return;
2179
2180     d->origin = origin;
2181     d->dirty(QSGItemPrivate::TransformOrigin);
2182
2183     emit transformOriginChanged(d->origin);
2184 }
2185
2186 QPointF QSGItem::transformOriginPoint() const
2187 {
2188     Q_D(const QSGItem);
2189     return d->computeTransformOrigin();
2190 }
2191
2192 qreal QSGItem::z() const
2193 {
2194     Q_D(const QSGItem);
2195     return d->z;
2196 }
2197
2198 void QSGItem::setZ(qreal v)
2199 {
2200     Q_D(QSGItem);
2201     if (d->z == v)
2202         return;
2203
2204     d->z = v;
2205
2206     d->dirty(QSGItemPrivate::ZValue);
2207     if (d->parentItem) 
2208         QSGItemPrivate::get(d->parentItem)->dirty(QSGItemPrivate::ChildrenStackingChanged);
2209
2210     emit zChanged();
2211 }
2212
2213 qreal QSGItem::rotation() const 
2214
2215     Q_D(const QSGItem);
2216     return d->rotation;
2217 }
2218
2219 void QSGItem::setRotation(qreal r) 
2220 {
2221     Q_D(QSGItem);
2222     if (d->rotation == r)
2223         return;
2224
2225     d->rotation = r;
2226
2227     d->dirty(QSGItemPrivate::BasicTransform);
2228
2229     d->itemChange(ItemRotationHasChanged, r);
2230
2231     emit rotationChanged();
2232 }
2233
2234 qreal QSGItem::scale() const 
2235
2236     Q_D(const QSGItem);
2237     return d->scale;
2238 }
2239
2240 void QSGItem::setScale(qreal s) 
2241 {
2242     Q_D(QSGItem);
2243     if (d->scale == s)
2244         return;
2245
2246     d->scale = s;
2247
2248     d->dirty(QSGItemPrivate::BasicTransform);
2249
2250     emit scaleChanged();
2251 }
2252
2253 qreal QSGItem::opacity() const
2254 {
2255     Q_D(const QSGItem);
2256     return d->opacity;
2257 }
2258
2259 void QSGItem::setOpacity(qreal o)
2260 {
2261     Q_D(QSGItem);
2262     if (d->opacity == o)
2263         return;
2264
2265     d->opacity = o;
2266     
2267     d->dirty(QSGItemPrivate::OpacityValue);
2268
2269     d->itemChange(ItemOpacityHasChanged, o);
2270
2271     emit opacityChanged();
2272 }
2273
2274 bool QSGItem::isVisible() const
2275 {
2276     Q_D(const QSGItem);
2277     return d->effectiveVisible;
2278 }
2279
2280 void QSGItem::setVisible(bool v)
2281 {
2282     Q_D(QSGItem);
2283     if (v == d->explicitVisible)
2284         return;
2285
2286     d->explicitVisible = v;
2287
2288     d->setEffectiveVisibleRecur(d->calcEffectiveVisible());
2289 }
2290
2291 bool QSGItem::isEnabled() const
2292 {
2293     Q_D(const QSGItem);
2294     return d->effectiveEnable;
2295 }
2296
2297 void QSGItem::setEnabled(bool e)
2298 {
2299     Q_D(QSGItem);
2300     if (e == d->explicitEnable)
2301         return;
2302
2303     d->explicitEnable = e;
2304
2305     d->setEffectiveEnableRecur(d->calcEffectiveEnable());
2306 }
2307
2308 bool QSGItemPrivate::calcEffectiveVisible() const
2309 {
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);
2314 }
2315
2316 void QSGItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible)
2317 {
2318     Q_Q(QSGItem);
2319
2320     if (newEffectiveVisible && !explicitVisible) {
2321         // This item locally overrides visibility
2322         return;
2323     }
2324
2325     if (newEffectiveVisible == effectiveVisible) {
2326         // No change necessary
2327         return;
2328     }
2329
2330     effectiveVisible = newEffectiveVisible;
2331     dirty(Visible);
2332     if (parentItem) QSGItemPrivate::get(parentItem)->dirty(ChildrenStackingChanged);
2333
2334     if (canvas) {
2335         QSGCanvasPrivate *canvasPriv = QSGCanvasPrivate::get(canvas);
2336         if (canvasPriv->mouseGrabberItem == q)
2337             q->ungrabMouse();
2338     }
2339
2340     for (int ii = 0; ii < childItems.count(); ++ii) 
2341         QSGItemPrivate::get(childItems.at(ii))->setEffectiveVisibleRecur(newEffectiveVisible);
2342
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);
2347     }
2348
2349     emit q->visibleChanged();
2350 }
2351
2352 bool QSGItemPrivate::calcEffectiveEnable() const
2353 {
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);
2358 }
2359
2360 void QSGItemPrivate::setEffectiveEnableRecur(bool newEffectiveEnable)
2361 {
2362     Q_Q(QSGItem);
2363
2364     // XXX todo - need to fixup focus
2365
2366     if (newEffectiveEnable && !explicitEnable) {
2367         // This item locally overrides enable
2368         return;
2369     }
2370
2371     if (newEffectiveEnable == effectiveEnable) {
2372         // No change necessary
2373         return;
2374     }
2375
2376     effectiveEnable = newEffectiveEnable;
2377
2378     if (canvas) {
2379         QSGCanvasPrivate *canvasPriv = QSGCanvasPrivate::get(canvas);
2380         if (canvasPriv->mouseGrabberItem == q)
2381             q->ungrabMouse();
2382     }
2383
2384     for (int ii = 0; ii < childItems.count(); ++ii) 
2385         QSGItemPrivate::get(childItems.at(ii))->setEffectiveEnableRecur(newEffectiveEnable);
2386
2387     emit q->enabledChanged();
2388 }
2389
2390 QString QSGItemPrivate::dirtyToString() const
2391 {
2392 #define DIRTY_TO_STRING(value) if (dirtyAttributes & value) { \
2393     if (!rv.isEmpty()) \
2394         rv.append(QLatin1String("|")); \
2395     rv.append(QLatin1String(#value)); \
2396 }
2397
2398 //    QString rv = QLatin1String("0x") + QString::number(dirtyAttributes, 16);
2399     QString rv;
2400
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);
2418
2419     return rv;
2420 }
2421
2422 void QSGItemPrivate::dirty(DirtyType type)
2423 {
2424     Q_Q(QSGItem);
2425     if (type & (TransformOrigin | Transform | BasicTransform | Position | Size))
2426         transformChanged();
2427
2428     if (!(dirtyAttributes & type) || (canvas && !prevDirtyItem)) {
2429         dirtyAttributes |= type;
2430         if (canvas) {
2431             addToDirtyList();
2432             QSGCanvasPrivate::get(canvas)->dirtyItem(q);
2433         }
2434     }
2435 }
2436
2437 void QSGItemPrivate::addToDirtyList()
2438 {
2439     Q_Q(QSGItem);
2440
2441     Q_ASSERT(canvas);
2442     if (!prevDirtyItem) {
2443         Q_ASSERT(!nextDirtyItem);
2444
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;
2450         p->dirtyItem(q);
2451     }
2452     Q_ASSERT(prevDirtyItem);
2453 }
2454
2455 void QSGItemPrivate::removeFromDirtyList()
2456 {
2457     if (prevDirtyItem) {
2458         if (nextDirtyItem) QSGItemPrivate::get(nextDirtyItem)->prevDirtyItem = prevDirtyItem;
2459         *prevDirtyItem = nextDirtyItem;
2460         prevDirtyItem = 0;
2461         nextDirtyItem = 0;
2462     }
2463     Q_ASSERT(!prevDirtyItem);
2464     Q_ASSERT(!nextDirtyItem);
2465 }
2466
2467 void QSGItemPrivate::refFromEffectItem(bool hide)
2468 {
2469     ++effectRefCount;
2470     if (1 == effectRefCount) {
2471         dirty(EffectReference);
2472         if (parentItem) QSGItemPrivate::get(parentItem)->dirty(ChildrenStackingChanged);
2473     }
2474     if (hide) {
2475         if (++hideRefCount == 1)
2476             dirty(HideReference);
2477     }
2478 }
2479
2480 void QSGItemPrivate::derefFromEffectItem(bool unhide)
2481 {
2482     Q_ASSERT(effectRefCount);
2483     --effectRefCount;
2484     if (0 == effectRefCount) {
2485         dirty(EffectReference);
2486         if (parentItem) QSGItemPrivate::get(parentItem)->dirty(ChildrenStackingChanged);
2487     }
2488     if (unhide) {
2489         if (--hideRefCount == 0)
2490             dirty(HideReference);
2491     }
2492 }
2493
2494 void QSGItemPrivate::itemChange(QSGItem::ItemChange change, const QSGItem::ItemChangeData &data)
2495 {
2496     Q_Q(QSGItem);
2497     switch(change) {
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);
2506             }
2507         }
2508         break;
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);
2517             }
2518         }
2519         break;
2520     case QSGItem::ItemSceneChange:
2521         q->itemChange(change, data);
2522         break;
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);
2529             }
2530         }
2531         break;
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);
2538             }
2539         }
2540         break;
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);
2547             }
2548         }
2549         break;
2550     case QSGItem::ItemActiveFocusHasChanged:
2551         q->itemChange(change, data);
2552         break;
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);
2559             }
2560         }
2561         break;
2562     }
2563 }
2564
2565 bool QSGItem::smooth() const
2566 {
2567     Q_D(const QSGItem);
2568     return d->smooth;
2569 }
2570
2571 void QSGItem::setSmooth(bool smooth)
2572 {
2573     Q_D(QSGItem);
2574     if (d->smooth == smooth)
2575         return;
2576
2577     d->smooth = smooth;
2578     d->dirty(QSGItemPrivate::Smooth);
2579
2580     emit smoothChanged(smooth);
2581 }
2582
2583 QSGItem::Flags QSGItem::flags() const 
2584
2585     Q_D(const QSGItem);
2586     return (QSGItem::Flags)d->flags;
2587 }
2588
2589 void QSGItem::setFlag(Flag flag, bool enabled)
2590
2591     Q_D(QSGItem);
2592     if (enabled)
2593         setFlags((Flags)(d->flags | (quint32)flag));
2594     else
2595         setFlags((Flags)(d->flags & ~(quint32)flag));
2596 }
2597
2598 void QSGItem::setFlags(Flags flags) 
2599
2600     Q_D(QSGItem);
2601
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;
2609         } 
2610     }
2611
2612     if ((flags & ItemClipsChildrenToShape ) != (d->flags & ItemClipsChildrenToShape)) 
2613         d->dirty(QSGItemPrivate::Clip);
2614
2615     d->flags = flags;
2616 }
2617
2618 qreal QSGItem::x() const
2619 {
2620     Q_D(const QSGItem);
2621     return d->x;
2622 }
2623
2624 qreal QSGItem::y() const
2625 {
2626     Q_D(const QSGItem);
2627     return d->y;
2628 }
2629
2630 QPointF QSGItem::pos() const
2631 {
2632     Q_D(const QSGItem);
2633     return QPointF(d->x, d->y);
2634 }
2635
2636 void QSGItem::setX(qreal v)
2637 {
2638     Q_D(QSGItem);
2639     if (d->x == v)
2640         return;
2641
2642     qreal oldx = d->x;
2643     d->x = v;
2644
2645     d->dirty(QSGItemPrivate::Position);
2646
2647     geometryChanged(QRectF(x(), y(), width(), height()),
2648                     QRectF(oldx, y(), width(), height()));
2649 }
2650
2651 void QSGItem::setY(qreal v)
2652 {
2653     Q_D(QSGItem);
2654     if (d->y == v)
2655         return;
2656
2657     qreal oldy = d->y;
2658     d->y = v;
2659
2660     d->dirty(QSGItemPrivate::Position);
2661
2662     geometryChanged(QRectF(x(), y(), width(), height()),
2663                     QRectF(x(), oldy, width(), height()));
2664 }
2665
2666 void QSGItem::setPos(const QPointF &pos)
2667 {
2668     Q_D(QSGItem);
2669     if (QPointF(d->x, d->y) == pos)
2670         return;
2671
2672     qreal oldx = d->x;
2673     qreal oldy = d->y;
2674
2675     d->x = pos.x();
2676     d->y = pos.y();
2677
2678     d->dirty(QSGItemPrivate::Position);
2679
2680     geometryChanged(QRectF(x(), y(), width(), height()),
2681                     QRectF(oldx, oldy, width(), height()));
2682 }
2683
2684 qreal QSGItem::width() const
2685 {
2686     Q_D(const QSGItem);
2687     return d->width;
2688 }
2689
2690 void QSGItem::setWidth(qreal w)
2691 {
2692     Q_D(QSGItem);
2693     if (qIsNaN(w))
2694         return;
2695
2696     d->widthValid = true;
2697     if (d->width == w)
2698         return;
2699
2700     qreal oldWidth = d->width;
2701     d->width = w;
2702
2703     d->dirty(QSGItemPrivate::Size);
2704
2705     geometryChanged(QRectF(x(), y(), width(), height()),
2706                     QRectF(x(), y(), oldWidth, height()));
2707 }
2708
2709 void QSGItem::resetWidth()
2710 {
2711     Q_D(QSGItem);
2712     d->widthValid = false;
2713     setImplicitWidth(implicitWidth());
2714 }
2715
2716 void QSGItemPrivate::implicitWidthChanged()
2717 {
2718     Q_Q(QSGItem);
2719     emit q->implicitWidthChanged();
2720 }
2721
2722 qreal QSGItemPrivate::getImplicitWidth() const
2723 {
2724     return implicitWidth;
2725 }
2726
2727 qreal QSGItem::implicitWidth() const
2728 {
2729     Q_D(const QSGItem);
2730     return d->getImplicitWidth();
2731 }
2732
2733 void QSGItem::setImplicitWidth(qreal w)
2734 {
2735     Q_D(QSGItem);
2736     bool changed = w != d->implicitWidth;
2737     d->implicitWidth = w;
2738     if (d->width == w || widthValid()) {
2739         if (changed)
2740             d->implicitWidthChanged();
2741         return;
2742     }   
2743
2744     qreal oldWidth = d->width;
2745     d->width = w;
2746     
2747     d->dirty(QSGItemPrivate::Size);
2748
2749     geometryChanged(QRectF(x(), y(), width(), height()),
2750                     QRectF(x(), y(), oldWidth, height()));
2751
2752     if (changed)
2753         d->implicitWidthChanged();
2754 }
2755
2756 bool QSGItem::widthValid() const
2757 {
2758     Q_D(const QSGItem);
2759     return d->widthValid;
2760 }
2761
2762 qreal QSGItem::height() const
2763 {
2764     Q_D(const QSGItem);
2765     return d->height;
2766 }
2767
2768 void QSGItem::setHeight(qreal h)
2769 {
2770     Q_D(QSGItem);
2771     if (qIsNaN(h))
2772         return;
2773
2774     d->heightValid = true;
2775     if (d->height == h)
2776         return;
2777
2778     qreal oldHeight = d->height;
2779     d->height = h;
2780
2781     d->dirty(QSGItemPrivate::Size);
2782
2783     geometryChanged(QRectF(x(), y(), width(), height()),
2784                     QRectF(x(), y(), width(), oldHeight));
2785 }
2786
2787 void QSGItem::resetHeight()
2788 {
2789     Q_D(QSGItem);
2790     d->heightValid = false;
2791     setImplicitHeight(implicitHeight());
2792 }
2793
2794 void QSGItemPrivate::implicitHeightChanged()
2795 {
2796     Q_Q(QSGItem);
2797     emit q->implicitHeightChanged();
2798 }
2799
2800 qreal QSGItemPrivate::getImplicitHeight() const
2801 {
2802     return implicitHeight;
2803 }
2804
2805 qreal QSGItem::implicitHeight() const
2806 {
2807     Q_D(const QSGItem);
2808     return d->getImplicitHeight();
2809 }
2810
2811 void QSGItem::setImplicitHeight(qreal h)
2812 {
2813     Q_D(QSGItem);
2814     bool changed = h != d->implicitHeight;
2815     d->implicitHeight = h;
2816     if (d->height == h || heightValid()) {
2817         if (changed)
2818             d->implicitHeightChanged();
2819         return;
2820     }
2821
2822     qreal oldHeight = d->height;
2823     d->height = h;
2824
2825     d->dirty(QSGItemPrivate::Size);
2826
2827     geometryChanged(QRectF(x(), y(), width(), height()),
2828                     QRectF(x(), y(), width(), oldHeight));
2829
2830     if (changed)
2831         d->implicitHeightChanged();
2832 }
2833
2834 bool QSGItem::heightValid() const
2835 {
2836     Q_D(const QSGItem);
2837     return d->heightValid;
2838 }
2839
2840 void QSGItem::setSize(const QSizeF &size)
2841 {
2842     Q_D(QSGItem);
2843     d->heightValid = true;
2844     d->widthValid = true;
2845
2846     if (QSizeF(d->width, d->height) == size)
2847         return;
2848
2849     qreal oldHeight = d->height;
2850     qreal oldWidth = d->width;
2851     d->height = size.height();
2852     d->width = size.width();
2853
2854     d->dirty(QSGItemPrivate::Size);
2855
2856     geometryChanged(QRectF(x(), y(), width(), height()),
2857                     QRectF(x(), y(), oldWidth, oldHeight));
2858 }
2859
2860 bool QSGItem::hasActiveFocus() const
2861 {
2862     Q_D(const QSGItem);
2863     return d->activeFocus;
2864 }
2865
2866 bool QSGItem::hasFocus() const
2867 {
2868     Q_D(const QSGItem);
2869     return d->focus;
2870 }
2871
2872 void QSGItem::setFocus(bool focus)
2873 {
2874     Q_D(QSGItem);
2875     if (d->focus == focus)
2876         return;
2877
2878     if (d->canvas) {
2879         // Need to find our nearest focus scope
2880         QSGItem *scope = parentItem();
2881         while (scope && !scope->isFocusScope())
2882             scope = scope->parentItem();
2883         if (focus)
2884             QSGCanvasPrivate::get(d->canvas)->setFocusInScope(scope, this);
2885         else
2886             QSGCanvasPrivate::get(d->canvas)->clearFocusInScope(scope, this);
2887     } else {
2888         d->focus = focus;
2889         emit focusChanged(focus);
2890     }
2891 }
2892
2893 bool QSGItem::isFocusScope() const
2894 {
2895     return flags() & ItemIsFocusScope;
2896 }
2897
2898 QSGItem *QSGItem::scopedFocusItem() const
2899 {
2900     Q_D(const QSGItem);
2901     if (!isFocusScope())
2902         return 0;
2903     else 
2904         return d->subFocusItem;
2905 }
2906
2907
2908 Qt::MouseButtons QSGItem::acceptedMouseButtons() const 
2909
2910     Q_D(const QSGItem);
2911     return d->acceptedMouseButtons;
2912 }
2913
2914 void QSGItem::setAcceptedMouseButtons(Qt::MouseButtons buttons) 
2915
2916     Q_D(QSGItem);
2917     d->acceptedMouseButtons = buttons;
2918 }
2919
2920 bool QSGItem::filtersChildMouseEvents() const
2921 {
2922     Q_D(const QSGItem);
2923     return d->filtersChildMouseEvents;
2924 }
2925
2926 void QSGItem::setFiltersChildMouseEvents(bool filter) 
2927
2928     Q_D(QSGItem);
2929     d->filtersChildMouseEvents = filter;
2930 }
2931
2932 bool QSGItem::isUnderMouse() const 
2933 {
2934     Q_D(const QSGItem);
2935     if (!d->canvas)
2936         return false;
2937
2938     QPoint cursorPos = QCursor::pos();
2939     if (QRectF(0, 0, width(), height()).contains(mapFromScene(d->canvas->mapFromGlobal(cursorPos))))
2940         return true;
2941     return false; 
2942 }
2943
2944 bool QSGItem::acceptHoverEvents() const 
2945
2946     Q_D(const QSGItem);
2947     return d->hoverEnabled;
2948 }
2949
2950 void QSGItem::setAcceptHoverEvents(bool enabled) 
2951
2952     Q_D(QSGItem);
2953     d->hoverEnabled = enabled;
2954
2955     if (d->canvas && d->hoverEnabled && !d->canvas->hasMouseTracking())
2956         d->canvas->setMouseTracking(true);
2957 }
2958
2959 void QSGItem::grabMouse() 
2960 {
2961     Q_D(QSGItem);
2962     if (!d->canvas)
2963         return;
2964     QSGCanvasPrivate *canvasPriv = QSGCanvasPrivate::get(d->canvas);
2965     if (canvasPriv->mouseGrabberItem == this)
2966         return;
2967
2968     QSGItem *oldGrabber = canvasPriv->mouseGrabberItem;
2969     canvasPriv->mouseGrabberItem = this;
2970     if (oldGrabber)
2971         oldGrabber->mouseUngrabEvent();
2972 }
2973
2974 void QSGItem::ungrabMouse() 
2975 {
2976     Q_D(QSGItem);
2977     if (!d->canvas)
2978         return;
2979     QSGCanvasPrivate *canvasPriv = QSGCanvasPrivate::get(d->canvas);
2980     if (canvasPriv->mouseGrabberItem != this) {
2981         qWarning("QSGItem::ungrabMouse(): Item is not the mouse grabber.");
2982         return;
2983     }
2984
2985     canvasPriv->mouseGrabberItem = 0;
2986     mouseUngrabEvent();
2987 }
2988
2989 bool QSGItem::keepMouseGrab() const
2990 {
2991     Q_D(const QSGItem);
2992     return d->keepMouse;
2993 }
2994
2995 void QSGItem::setKeepMouseGrab(bool keep)
2996 {
2997     Q_D(QSGItem);
2998     d->keepMouse = keep;
2999 }
3000
3001 QPointF QSGItem::mapToItem(const QSGItem *item, const QPointF &point) const 
3002
3003     QPointF p = mapToScene(point);
3004     if (item)
3005         p = item->mapFromScene(p);
3006     return p;
3007 }
3008
3009 QPointF QSGItem::mapToScene(const QPointF &point) const 
3010
3011     Q_D(const QSGItem);
3012     return d->itemToCanvasTransform().map(point);
3013 }
3014
3015 QRectF QSGItem::mapRectToItem(const QSGItem *item, const QRectF &rect) const
3016 {
3017     Q_D(const QSGItem);
3018     QTransform t = d->itemToCanvasTransform();
3019     if (item)
3020         t *= QSGItemPrivate::get(item)->canvasToItemTransform();
3021     return t.mapRect(rect);
3022 }
3023
3024 QRectF QSGItem::mapRectToScene(const QRectF &rect) const 
3025
3026     Q_D(const QSGItem);
3027     return d->itemToCanvasTransform().mapRect(rect);
3028 }
3029
3030 QPointF QSGItem::mapFromItem(const QSGItem *item, const QPointF &point) const 
3031
3032     QPointF p = item?item->mapToScene(point):point;
3033     return mapFromScene(p);
3034 }
3035
3036 QPointF QSGItem::mapFromScene(const QPointF &point) const 
3037
3038     Q_D(const QSGItem);
3039     return d->canvasToItemTransform().map(point);
3040 }
3041
3042 QRectF QSGItem::mapRectFromItem(const QSGItem *item, const QRectF &rect) const 
3043
3044     Q_D(const QSGItem);
3045     QTransform t = item?QSGItemPrivate::get(item)->itemToCanvasTransform():QTransform();
3046     t *= d->canvasToItemTransform();
3047     return t.mapRect(rect);
3048 }
3049
3050 QRectF QSGItem::mapRectFromScene(const QRectF &rect) const
3051 {
3052     Q_D(const QSGItem);
3053     return d->canvasToItemTransform().mapRect(rect);
3054 }
3055
3056 bool QSGItem::event(QEvent *ev)
3057 {
3058     return QObject::event(ev);
3059
3060 #if 0
3061     if (ev->type() == QEvent::PolishRequest) {
3062         Q_D(QSGItem);
3063         d->polishScheduled = false;
3064         updatePolish();
3065         return true;
3066     } else {
3067         return QObject::event(ev);
3068     }
3069 #endif
3070 }
3071
3072 #ifndef QT_NO_DEBUG_STREAM
3073 QDebug operator<<(QDebug debug, QSGItem *item)
3074 {
3075     if (!item) {
3076         debug << "QSGItem(0)";
3077         return debug;
3078     }
3079
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() << ')';
3085     return debug;
3086 }
3087 #endif
3088
3089 qint64 QSGItemPrivate::consistentTime = -1;
3090 void QSGItemPrivate::setConsistentTime(qint64 t)
3091 {
3092     consistentTime = t;
3093 }
3094
3095 class QElapsedTimerConsistentTimeHack
3096 {
3097 public:
3098     void start() {
3099         t1 = QSGItemPrivate::consistentTime;
3100         t2 = 0;
3101     }
3102     qint64 elapsed() {
3103         return QSGItemPrivate::consistentTime - t1;
3104     }
3105     qint64 restart() {
3106         qint64 val = QSGItemPrivate::consistentTime - t1;
3107         t1 = QSGItemPrivate::consistentTime;
3108         t2 = 0;
3109         return val;
3110     }
3111
3112 private:
3113     qint64 t1;
3114     qint64 t2;
3115 };
3116
3117 void QSGItemPrivate::start(QElapsedTimer &t)
3118 {
3119     if (QSGItemPrivate::consistentTime == -1)
3120         t.start();
3121     else
3122         ((QElapsedTimerConsistentTimeHack*)&t)->start();
3123 }
3124
3125 qint64 QSGItemPrivate::elapsed(QElapsedTimer &t)
3126 {
3127     if (QSGItemPrivate::consistentTime == -1)
3128         return t.elapsed();
3129     else
3130         return ((QElapsedTimerConsistentTimeHack*)&t)->elapsed();
3131 }
3132
3133 qint64 QSGItemPrivate::restart(QElapsedTimer &t)
3134 {
3135     if (QSGItemPrivate::consistentTime == -1)
3136         return t.restart();
3137     else
3138         return ((QElapsedTimerConsistentTimeHack*)&t)->restart();
3139 }
3140
3141 QT_END_NAMESPACE
3142
3143 #include <moc_qsgitem.cpp>