aboutsummaryrefslogtreecommitdiffstats
path: root/src/qtquick1
diff options
context:
space:
mode:
authorMartin Jones <martin.jones@nokia.com>2011-07-11 13:47:51 +1000
committerQt by Nokia <qt-info@nokia.com>2011-07-12 06:38:09 +0200
commit4442dea01b9d4d45964228ac442166d89f091f9e (patch)
tree28ae20cb26967765a988b1ee522fc2d64d777671 /src/qtquick1
parentb119220da60453ecf31898f7a57eda9d3c4e9225 (diff)
Extract all QtQuick 1 elements into a separate library/plugin.
Change-Id: I41a280de2739ee08202f4be2519e5012870090f2 Reviewed-on: http://codereview.qt.nokia.com/1391 Reviewed-by: Martin Jones <martin.jones@nokia.com>
Diffstat (limited to 'src/qtquick1')
-rw-r--r--src/qtquick1/graphicsitems/graphicsitems.pri94
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeanchors.cpp1169
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeanchors_p.h206
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeanchors_p_p.h171
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeanimatedimage.cpp408
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeanimatedimage_p.h117
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeanimatedimage_p_p.h87
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeborderimage.cpp621
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeborderimage_p.h111
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeborderimage_p_p.h107
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeevents.cpp241
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeevents_p_p.h141
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeflickable.cpp1803
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeflickable_p.h229
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeflickable_p_p.h241
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeflipable.cpp258
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeflipable_p.h100
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativefocuspanel.cpp93
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativefocuspanel_p.h78
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativefocusscope.cpp77
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativefocusscope_p.h69
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativegraphicswidget.cpp129
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativegraphicswidget_p.h90
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativegridview.cpp3133
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativegridview_p.h288
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeimage.cpp588
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeimage_p.h100
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeimage_p_p.h79
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeimagebase.cpp288
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeimagebase_p.h116
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeimagebase_p_p.h94
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeimplicitsizeitem.cpp96
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeimplicitsizeitem_p.h100
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeimplicitsizeitem_p_p.h90
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeitem.cpp3815
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeitem.h235
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeitem_p.h635
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeitemchangelistener_p.h76
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeitemsmodule.cpp267
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeitemsmodule_p.h64
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativelayoutitem.cpp116
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativelayoutitem_p.h94
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativelistview.cpp3617
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativelistview_p.h371
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeloader.cpp601
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeloader_p.h108
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativeloader_p_p.h91
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativemousearea.cpp990
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativemousearea_p.h218
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativemousearea_p_p.h128
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativepainteditem.cpp501
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativepainteditem_p.h118
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativepainteditem_p_p.h90
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativepath.cpp926
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativepath_p.h286
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativepath_p_p.h83
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativepathview.cpp1732
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativepathview_p.h252
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativepathview_p_p.h192
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativepincharea.cpp611
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativepincharea_p.h313
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativepincharea_p_p.h115
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativepositioners.cpp1396
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativepositioners_p.h239
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativepositioners_p_p.h174
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativerectangle.cpp591
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativerectangle_p.h188
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativerectangle_p_p.h112
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativerepeater.cpp449
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativerepeater_p.h110
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativerepeater_p_p.h82
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativescalegrid.cpp217
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativescalegrid_p_p.h134
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativetext.cpp1645
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativetext_p.h213
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativetext_p_p.h143
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativetextedit.cpp1892
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativetextedit_p.h307
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativetextedit_p_p.h139
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativetextinput.cpp2016
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativetextinput_p.h306
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativetextinput_p_p.h156
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativetextlayout.cpp395
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativetextlayout_p.h75
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativetranslate.cpp129
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativetranslate_p.h89
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativevisualitemmodel.cpp1429
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativevisualitemmodel_p.h257
-rw-r--r--src/qtquick1/qtquick1.cpp66
-rw-r--r--src/qtquick1/qtquick1.pro42
-rw-r--r--src/qtquick1/qtquick1_p.h64
-rw-r--r--src/qtquick1/util/qdeclarativeanimation.cpp2956
-rw-r--r--src/qtquick1/util/qdeclarativeanimation_p.h528
-rw-r--r--src/qtquick1/util/qdeclarativeanimation_p_p.h397
-rw-r--r--src/qtquick1/util/qdeclarativeapplication.cpp116
-rw-r--r--src/qtquick1/util/qdeclarativeapplication_p.h86
-rw-r--r--src/qtquick1/util/qdeclarativebehavior.cpp234
-rw-r--r--src/qtquick1/util/qdeclarativebehavior_p.h98
-rw-r--r--src/qtquick1/util/qdeclarativebind.cpp217
-rw-r--r--src/qtquick1/util/qdeclarativebind_p.h96
-rw-r--r--src/qtquick1/util/qdeclarativeconnections.cpp293
-rw-r--r--src/qtquick1/util/qdeclarativeconnections_p.h102
-rw-r--r--src/qtquick1/util/qdeclarativefontloader.cpp342
-rw-r--r--src/qtquick1/util/qdeclarativefontloader_p.h97
-rw-r--r--src/qtquick1/util/qdeclarativelistaccessor.cpp142
-rw-r--r--src/qtquick1/util/qdeclarativelistaccessor_p.h81
-rw-r--r--src/qtquick1/util/qdeclarativelistmodel.cpp1631
-rw-r--r--src/qtquick1/util/qdeclarativelistmodel_p.h157
-rw-r--r--src/qtquick1/util/qdeclarativelistmodel_p_p.h281
-rw-r--r--src/qtquick1/util/qdeclarativelistmodelworkeragent.cpp282
-rw-r--r--src/qtquick1/util/qdeclarativelistmodelworkeragent_p.h163
-rw-r--r--src/qtquick1/util/qdeclarativeopenmetaobject.cpp384
-rw-r--r--src/qtquick1/util/qdeclarativeopenmetaobject_p.h130
-rw-r--r--src/qtquick1/util/qdeclarativepackage.cpp205
-rw-r--r--src/qtquick1/util/qdeclarativepackage_p.h98
-rw-r--r--src/qtquick1/util/qdeclarativepixmapcache.cpp1084
-rw-r--r--src/qtquick1/util/qdeclarativepixmapcache_p.h123
-rw-r--r--src/qtquick1/util/qdeclarativepropertychanges.cpp801
-rw-r--r--src/qtquick1/util/qdeclarativepropertychanges_p.h111
-rw-r--r--src/qtquick1/util/qdeclarativesmoothedanimation.cpp497
-rw-r--r--src/qtquick1/util/qdeclarativesmoothedanimation_p.h104
-rw-r--r--src/qtquick1/util/qdeclarativesmoothedanimation_p_p.h135
-rw-r--r--src/qtquick1/util/qdeclarativespringanimation.cpp466
-rw-r--r--src/qtquick1/util/qdeclarativespringanimation_p.h111
-rw-r--r--src/qtquick1/util/qdeclarativestate.cpp734
-rw-r--r--src/qtquick1/util/qdeclarativestate_p.h211
-rw-r--r--src/qtquick1/util/qdeclarativestate_p_p.h253
-rw-r--r--src/qtquick1/util/qdeclarativestategroup.cpp473
-rw-r--r--src/qtquick1/util/qdeclarativestategroup_p.h96
-rw-r--r--src/qtquick1/util/qdeclarativestateoperations.cpp1591
-rw-r--r--src/qtquick1/util/qdeclarativestateoperations_p.h299
-rw-r--r--src/qtquick1/util/qdeclarativestyledtext.cpp351
-rw-r--r--src/qtquick1/util/qdeclarativestyledtext_p.h70
-rw-r--r--src/qtquick1/util/qdeclarativesystempalette.cpp316
-rw-r--r--src/qtquick1/util/qdeclarativesystempalette_p.h122
-rw-r--r--src/qtquick1/util/qdeclarativetimeline.cpp951
-rw-r--r--src/qtquick1/util/qdeclarativetimeline_p_p.h200
-rw-r--r--src/qtquick1/util/qdeclarativetimer.cpp328
-rw-r--r--src/qtquick1/util/qdeclarativetimer_p.h115
-rw-r--r--src/qtquick1/util/qdeclarativetransition.cpp349
-rw-r--r--src/qtquick1/util/qdeclarativetransition_p.h106
-rw-r--r--src/qtquick1/util/qdeclarativetransitionmanager.cpp280
-rw-r--r--src/qtquick1/util/qdeclarativetransitionmanager_p_p.h85
-rw-r--r--src/qtquick1/util/qdeclarativeutilmodule.cpp177
-rw-r--r--src/qtquick1/util/qdeclarativeutilmodule_p.h64
-rw-r--r--src/qtquick1/util/qdeclarativeview.cpp737
-rw-r--r--src/qtquick1/util/qdeclarativeview.h120
-rw-r--r--src/qtquick1/util/qdeclarativexmllistmodel.cpp1058
-rw-r--r--src/qtquick1/util/qdeclarativexmllistmodel_p.h213
-rw-r--r--src/qtquick1/util/util.pri69
150 files changed, 63228 insertions, 0 deletions
diff --git a/src/qtquick1/graphicsitems/graphicsitems.pri b/src/qtquick1/graphicsitems/graphicsitems.pri
new file mode 100644
index 0000000000..9904274023
--- /dev/null
+++ b/src/qtquick1/graphicsitems/graphicsitems.pri
@@ -0,0 +1,94 @@
+INCLUDEPATH += $$PWD
+
+HEADERS += \
+ $$PWD/qdeclarativeitemsmodule_p.h \
+ $$PWD/qdeclarativeanchors_p.h \
+ $$PWD/qdeclarativeanchors_p_p.h \
+ $$PWD/qdeclarativeevents_p_p.h \
+ $$PWD/qdeclarativeflickable_p.h \
+ $$PWD/qdeclarativeflickable_p_p.h \
+ $$PWD/qdeclarativeflipable_p.h \
+ $$PWD/qdeclarativegridview_p.h \
+ $$PWD/qdeclarativeimage_p.h \
+ $$PWD/qdeclarativeimagebase_p.h \
+ $$PWD/qdeclarativeborderimage_p.h \
+ $$PWD/qdeclarativepainteditem_p.h \
+ $$PWD/qdeclarativepainteditem_p_p.h \
+ $$PWD/qdeclarativeimage_p_p.h \
+ $$PWD/qdeclarativeborderimage_p_p.h \
+ $$PWD/qdeclarativeimagebase_p_p.h \
+ $$PWD/qdeclarativeanimatedimage_p.h \
+ $$PWD/qdeclarativeanimatedimage_p_p.h \
+ $$PWD/qdeclarativeitem.h \
+ $$PWD/qdeclarativeitem_p.h \
+ $$PWD/qdeclarativefocuspanel_p.h \
+ $$PWD/qdeclarativefocusscope_p.h \
+ $$PWD/qdeclarativepositioners_p.h \
+ $$PWD/qdeclarativepositioners_p_p.h \
+ $$PWD/qdeclarativeloader_p.h \
+ $$PWD/qdeclarativeloader_p_p.h \
+ $$PWD/qdeclarativemousearea_p.h \
+ $$PWD/qdeclarativemousearea_p_p.h \
+ $$PWD/qdeclarativepath_p.h \
+ $$PWD/qdeclarativepath_p_p.h \
+ $$PWD/qdeclarativepathview_p.h \
+ $$PWD/qdeclarativepathview_p_p.h \
+ $$PWD/qdeclarativerectangle_p.h \
+ $$PWD/qdeclarativerectangle_p_p.h \
+ $$PWD/qdeclarativerepeater_p.h \
+ $$PWD/qdeclarativerepeater_p_p.h \
+ $$PWD/qdeclarativescalegrid_p_p.h \
+ $$PWD/qdeclarativetranslate_p.h \
+ $$PWD/qdeclarativetextinput_p.h \
+ $$PWD/qdeclarativetextinput_p_p.h \
+ $$PWD/qdeclarativetextedit_p.h \
+ $$PWD/qdeclarativetextedit_p_p.h \
+ $$PWD/qdeclarativetext_p.h \
+ $$PWD/qdeclarativetext_p_p.h \
+ $$PWD/qdeclarativevisualitemmodel_p.h \
+ $$PWD/qdeclarativelistview_p.h \
+ $$PWD/qdeclarativelayoutitem_p.h \
+ $$PWD/qdeclarativeitemchangelistener_p.h \
+ $$PWD/qdeclarativegraphicswidget_p.h \
+ $$PWD/qdeclarativetextlayout_p.h \
+ $$PWD/qdeclarativepincharea_p.h \
+ $$PWD/qdeclarativepincharea_p_p.h \
+ $$PWD/qdeclarativeimplicitsizeitem_p.h \
+ $$PWD/qdeclarativeimplicitsizeitem_p_p.h
+
+
+SOURCES += \
+ $$PWD/qdeclarativeitemsmodule.cpp \
+ $$PWD/qdeclarativeanchors.cpp \
+ $$PWD/qdeclarativeevents.cpp \
+ $$PWD/qdeclarativeflickable.cpp \
+ $$PWD/qdeclarativeflipable.cpp \
+ $$PWD/qdeclarativegridview.cpp \
+ $$PWD/qdeclarativeimage.cpp \
+ $$PWD/qdeclarativeborderimage.cpp \
+ $$PWD/qdeclarativeimagebase.cpp \
+ $$PWD/qdeclarativeanimatedimage.cpp \
+ $$PWD/qdeclarativepainteditem.cpp \
+ $$PWD/qdeclarativeitem.cpp \
+ $$PWD/qdeclarativefocuspanel.cpp \
+ $$PWD/qdeclarativefocusscope.cpp \
+ $$PWD/qdeclarativepositioners.cpp \
+ $$PWD/qdeclarativeloader.cpp \
+ $$PWD/qdeclarativemousearea.cpp \
+ $$PWD/qdeclarativepath.cpp \
+ $$PWD/qdeclarativepathview.cpp \
+ $$PWD/qdeclarativerectangle.cpp \
+ $$PWD/qdeclarativerepeater.cpp \
+ $$PWD/qdeclarativescalegrid.cpp \
+ $$PWD/qdeclarativetranslate.cpp \
+ $$PWD/qdeclarativetextinput.cpp \
+ $$PWD/qdeclarativetext.cpp \
+ $$PWD/qdeclarativetextedit.cpp \
+ $$PWD/qdeclarativevisualitemmodel.cpp \
+ $$PWD/qdeclarativelistview.cpp \
+ $$PWD/qdeclarativelayoutitem.cpp \
+ $$PWD/qdeclarativegraphicswidget.cpp \
+ $$PWD/qdeclarativetextlayout.cpp \
+ $$PWD/qdeclarativepincharea.cpp \
+ $$PWD/qdeclarativeimplicitsizeitem.cpp
+
diff --git a/src/qtquick1/graphicsitems/qdeclarativeanchors.cpp b/src/qtquick1/graphicsitems/qdeclarativeanchors.cpp
new file mode 100644
index 0000000000..2f074a4f04
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativeanchors.cpp
@@ -0,0 +1,1169 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativeanchors_p_p.h"
+
+#include "QtQuick1/qdeclarativeitem.h"
+#include "QtQuick1/private/qdeclarativeitem_p.h"
+
+#include <QtDeclarative/qdeclarativeinfo.h>
+
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+
+
+
+//TODO: should we cache relationships, so we don't have to check each time (parent-child or sibling)?
+//TODO: support non-parent, non-sibling (need to find lowest common ancestor)
+
+static qreal hcenter(QGraphicsItem *i)
+{
+ QGraphicsItemPrivate *item = QGraphicsItemPrivate::get(i);
+
+ qreal width = item->width();
+ int iw = width;
+ if (iw % 2)
+ return (width + 1) / 2;
+ else
+ return width / 2;
+}
+
+static qreal vcenter(QGraphicsItem *i)
+{
+ QGraphicsItemPrivate *item = QGraphicsItemPrivate::get(i);
+
+ qreal height = item->height();
+ int ih = height;
+ if (ih % 2)
+ return (height + 1) / 2;
+ else
+ return height / 2;
+}
+
+//### const item?
+//local position
+static qreal position(QGraphicsObject *item, QDeclarative1AnchorLine::AnchorLine anchorLine)
+{
+ qreal ret = 0.0;
+ QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(item);
+ switch(anchorLine) {
+ case QDeclarative1AnchorLine::Left:
+ ret = item->x();
+ break;
+ case QDeclarative1AnchorLine::Right:
+ ret = item->x() + d->width();
+ break;
+ case QDeclarative1AnchorLine::Top:
+ ret = item->y();
+ break;
+ case QDeclarative1AnchorLine::Bottom:
+ ret = item->y() + d->height();
+ break;
+ case QDeclarative1AnchorLine::HCenter:
+ ret = item->x() + hcenter(item);
+ break;
+ case QDeclarative1AnchorLine::VCenter:
+ ret = item->y() + vcenter(item);
+ break;
+ case QDeclarative1AnchorLine::Baseline:
+ if (d->isDeclarativeItem)
+ ret = item->y() + static_cast<QDeclarativeItem*>(item)->baselineOffset();
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+//position when origin is 0,0
+static qreal adjustedPosition(QGraphicsObject *item, QDeclarative1AnchorLine::AnchorLine anchorLine)
+{
+ qreal ret = 0.0;
+ QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(item);
+ switch(anchorLine) {
+ case QDeclarative1AnchorLine::Left:
+ ret = 0.0;
+ break;
+ case QDeclarative1AnchorLine::Right:
+ ret = d->width();
+ break;
+ case QDeclarative1AnchorLine::Top:
+ ret = 0.0;
+ break;
+ case QDeclarative1AnchorLine::Bottom:
+ ret = d->height();
+ break;
+ case QDeclarative1AnchorLine::HCenter:
+ ret = hcenter(item);
+ break;
+ case QDeclarative1AnchorLine::VCenter:
+ ret = vcenter(item);
+ break;
+ case QDeclarative1AnchorLine::Baseline:
+ if (d->isDeclarativeItem)
+ ret = static_cast<QDeclarativeItem*>(item)->baselineOffset();
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+QDeclarative1Anchors::QDeclarative1Anchors(QObject *parent)
+ : QObject(*new QDeclarative1AnchorsPrivate(0), parent)
+{
+ qFatal("QDeclarative1Anchors::QDeclarative1Anchors(QObject*) called");
+}
+
+QDeclarative1Anchors::QDeclarative1Anchors(QGraphicsObject *item, QObject *parent)
+ : QObject(*new QDeclarative1AnchorsPrivate(item), parent)
+{
+}
+
+QDeclarative1Anchors::~QDeclarative1Anchors()
+{
+ Q_D(QDeclarative1Anchors);
+ d->remDepend(d->fill);
+ d->remDepend(d->centerIn);
+ d->remDepend(d->left.item);
+ d->remDepend(d->right.item);
+ d->remDepend(d->top.item);
+ d->remDepend(d->bottom.item);
+ d->remDepend(d->vCenter.item);
+ d->remDepend(d->hCenter.item);
+ d->remDepend(d->baseline.item);
+}
+
+void QDeclarative1AnchorsPrivate::fillChanged()
+{
+ Q_Q(QDeclarative1Anchors);
+ if (!fill || !isItemComplete())
+ return;
+
+ if (updatingFill < 2) {
+ ++updatingFill;
+
+ qreal horizontalMargin = q->mirrored() ? rightMargin : leftMargin;
+
+ if (fill == item->parentItem()) { //child-parent
+ setItemPos(QPointF(horizontalMargin, topMargin));
+ } else if (fill->parentItem() == item->parentItem()) { //siblings
+ setItemPos(QPointF(fill->x()+horizontalMargin, fill->y()+topMargin));
+ }
+ QGraphicsItemPrivate *fillPrivate = QGraphicsItemPrivate::get(fill);
+ setItemSize(QSizeF(fillPrivate->width()-leftMargin-rightMargin, fillPrivate->height()-topMargin-bottomMargin));
+
+ --updatingFill;
+ } else {
+ // ### Make this certain :)
+ qmlInfo(item) << QDeclarative1Anchors::tr("Possible anchor loop detected on fill.");
+ }
+
+}
+
+void QDeclarative1AnchorsPrivate::centerInChanged()
+{
+ Q_Q(QDeclarative1Anchors);
+ if (!centerIn || fill || !isItemComplete())
+ return;
+
+ if (updatingCenterIn < 2) {
+ ++updatingCenterIn;
+
+ qreal effectiveHCenterOffset = q->mirrored() ? -hCenterOffset : hCenterOffset;
+ if (centerIn == item->parentItem()) {
+ QPointF p(hcenter(item->parentItem()) - hcenter(item) + effectiveHCenterOffset,
+ vcenter(item->parentItem()) - vcenter(item) + vCenterOffset);
+ setItemPos(p);
+
+ } else if (centerIn->parentItem() == item->parentItem()) {
+ QPointF p(centerIn->x() + hcenter(centerIn) - hcenter(item) + effectiveHCenterOffset,
+ centerIn->y() + vcenter(centerIn) - vcenter(item) + vCenterOffset);
+ setItemPos(p);
+ }
+
+ --updatingCenterIn;
+ } else {
+ // ### Make this certain :)
+ qmlInfo(item) << QDeclarative1Anchors::tr("Possible anchor loop detected on centerIn.");
+ }
+}
+
+void QDeclarative1AnchorsPrivate::clearItem(QGraphicsObject *item)
+{
+ if (!item)
+ return;
+ if (fill == item)
+ fill = 0;
+ if (centerIn == item)
+ centerIn = 0;
+ if (left.item == item) {
+ left.item = 0;
+ usedAnchors &= ~QDeclarative1Anchors::LeftAnchor;
+ }
+ if (right.item == item) {
+ right.item = 0;
+ usedAnchors &= ~QDeclarative1Anchors::RightAnchor;
+ }
+ if (top.item == item) {
+ top.item = 0;
+ usedAnchors &= ~QDeclarative1Anchors::TopAnchor;
+ }
+ if (bottom.item == item) {
+ bottom.item = 0;
+ usedAnchors &= ~QDeclarative1Anchors::BottomAnchor;
+ }
+ if (vCenter.item == item) {
+ vCenter.item = 0;
+ usedAnchors &= ~QDeclarative1Anchors::VCenterAnchor;
+ }
+ if (hCenter.item == item) {
+ hCenter.item = 0;
+ usedAnchors &= ~QDeclarative1Anchors::HCenterAnchor;
+ }
+ if (baseline.item == item) {
+ baseline.item = 0;
+ usedAnchors &= ~QDeclarative1Anchors::BaselineAnchor;
+ }
+}
+
+void QDeclarative1AnchorsPrivate::addDepend(QGraphicsObject *item)
+{
+ if (!item)
+ return;
+ QGraphicsItemPrivate * itemPrivate = QGraphicsItemPrivate::get(item);
+ if (itemPrivate->isDeclarativeItem) {
+ QDeclarativeItemPrivate *p =
+ static_cast<QDeclarativeItemPrivate *>(QGraphicsItemPrivate::get(item));
+ p->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
+ } else if(itemPrivate->isWidget) {
+ Q_Q(QDeclarative1Anchors);
+ QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
+ QObject::connect(widget, SIGNAL(destroyed(QObject*)), q, SLOT(_q_widgetDestroyed(QObject*)));
+ QObject::connect(widget, SIGNAL(geometryChanged()), q, SLOT(_q_widgetGeometryChanged()));
+ }
+}
+
+void QDeclarative1AnchorsPrivate::remDepend(QGraphicsObject *item)
+{
+ if (!item)
+ return;
+ QGraphicsItemPrivate * itemPrivate = QGraphicsItemPrivate::get(item);
+ if (itemPrivate->isDeclarativeItem) {
+ QDeclarativeItemPrivate *p =
+ static_cast<QDeclarativeItemPrivate *>(itemPrivate);
+ p->removeItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
+ } else if(itemPrivate->isWidget) {
+ Q_Q(QDeclarative1Anchors);
+ QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
+ QObject::disconnect(widget, SIGNAL(destroyed(QObject*)), q, SLOT(_q_widgetDestroyed(QObject*)));
+ QObject::disconnect(widget, SIGNAL(geometryChanged()), q, SLOT(_q_widgetGeometryChanged()));
+ }
+}
+
+bool QDeclarative1AnchorsPrivate::isItemComplete() const
+{
+ return componentComplete;
+}
+
+void QDeclarative1Anchors::classBegin()
+{
+ Q_D(QDeclarative1Anchors);
+ d->componentComplete = false;
+}
+
+void QDeclarative1Anchors::componentComplete()
+{
+ Q_D(QDeclarative1Anchors);
+ d->componentComplete = true;
+}
+
+bool QDeclarative1Anchors::mirrored()
+{
+ Q_D(QDeclarative1Anchors);
+ QGraphicsItemPrivate * itemPrivate = QGraphicsItemPrivate::get(d->item);
+ return itemPrivate->isDeclarativeItem ? static_cast<QDeclarativeItemPrivate *>(itemPrivate)->effectiveLayoutMirror : false;
+}
+
+void QDeclarative1AnchorsPrivate::setItemHeight(qreal v)
+{
+ updatingMe = true;
+ QGraphicsItemPrivate::get(item)->setHeight(v);
+ updatingMe = false;
+}
+
+void QDeclarative1AnchorsPrivate::setItemWidth(qreal v)
+{
+ updatingMe = true;
+ QGraphicsItemPrivate::get(item)->setWidth(v);
+ updatingMe = false;
+}
+
+void QDeclarative1AnchorsPrivate::setItemX(qreal v)
+{
+ updatingMe = true;
+ item->setX(v);
+ updatingMe = false;
+}
+
+void QDeclarative1AnchorsPrivate::setItemY(qreal v)
+{
+ updatingMe = true;
+ item->setY(v);
+ updatingMe = false;
+}
+
+void QDeclarative1AnchorsPrivate::setItemPos(const QPointF &v)
+{
+ updatingMe = true;
+ item->setPos(v);
+ updatingMe = false;
+}
+
+void QDeclarative1AnchorsPrivate::setItemSize(const QSizeF &v)
+{
+ updatingMe = true;
+ if(QGraphicsItemPrivate::get(item)->isWidget)
+ static_cast<QGraphicsWidget *>(item)->resize(v);
+ else if (QGraphicsItemPrivate::get(item)->isDeclarativeItem)
+ static_cast<QDeclarativeItem *>(item)->setSize(v);
+ updatingMe = false;
+}
+
+void QDeclarative1AnchorsPrivate::updateMe()
+{
+ if (updatingMe) {
+ updatingMe = false;
+ return;
+ }
+
+ fillChanged();
+ centerInChanged();
+ updateHorizontalAnchors();
+ updateVerticalAnchors();
+}
+
+void QDeclarative1AnchorsPrivate::updateOnComplete()
+{
+ fillChanged();
+ centerInChanged();
+ updateHorizontalAnchors();
+ updateVerticalAnchors();
+}
+
+void QDeclarative1AnchorsPrivate::_q_widgetDestroyed(QObject *obj)
+{
+ clearItem(qobject_cast<QGraphicsObject*>(obj));
+}
+
+void QDeclarative1AnchorsPrivate::_q_widgetGeometryChanged()
+{
+ fillChanged();
+ centerInChanged();
+ updateHorizontalAnchors();
+ updateVerticalAnchors();
+}
+
+void QDeclarative1AnchorsPrivate::itemGeometryChanged(QDeclarativeItem *, const QRectF &newG, const QRectF &oldG)
+{
+ fillChanged();
+ centerInChanged();
+ if (newG.x() != oldG.x() || newG.width() != oldG.width())
+ updateHorizontalAnchors();
+ if (newG.y() != oldG.y() || newG.height() != oldG.height())
+ updateVerticalAnchors();
+}
+
+QGraphicsObject *QDeclarative1Anchors::fill() const
+{
+ Q_D(const QDeclarative1Anchors);
+ return d->fill;
+}
+
+void QDeclarative1Anchors::setFill(QGraphicsObject *f)
+{
+ Q_D(QDeclarative1Anchors);
+ if (d->fill == f)
+ return;
+
+ if (!f) {
+ d->remDepend(d->fill);
+ d->fill = f;
+ emit fillChanged();
+ return;
+ }
+ if (f != d->item->parentItem() && f->parentItem() != d->item->parentItem()){
+ qmlInfo(d->item) << tr("Cannot anchor to an item that isn't a parent or sibling.");
+ return;
+ }
+ d->remDepend(d->fill);
+ d->fill = f;
+ d->addDepend(d->fill);
+ emit fillChanged();
+ d->fillChanged();
+}
+
+void QDeclarative1Anchors::resetFill()
+{
+ setFill(0);
+}
+
+QGraphicsObject *QDeclarative1Anchors::centerIn() const
+{
+ Q_D(const QDeclarative1Anchors);
+ return d->centerIn;
+}
+
+void QDeclarative1Anchors::setCenterIn(QGraphicsObject* c)
+{
+ Q_D(QDeclarative1Anchors);
+ if (d->centerIn == c)
+ return;
+
+ if (!c) {
+ d->remDepend(d->centerIn);
+ d->centerIn = c;
+ emit centerInChanged();
+ return;
+ }
+ if (c != d->item->parentItem() && c->parentItem() != d->item->parentItem()){
+ qmlInfo(d->item) << tr("Cannot anchor to an item that isn't a parent or sibling.");
+ return;
+ }
+
+ d->remDepend(d->centerIn);
+ d->centerIn = c;
+ d->addDepend(d->centerIn);
+ emit centerInChanged();
+ d->centerInChanged();
+}
+
+void QDeclarative1Anchors::resetCenterIn()
+{
+ setCenterIn(0);
+}
+
+bool QDeclarative1AnchorsPrivate::calcStretch(const QDeclarative1AnchorLine &edge1,
+ const QDeclarative1AnchorLine &edge2,
+ qreal offset1,
+ qreal offset2,
+ QDeclarative1AnchorLine::AnchorLine line,
+ qreal &stretch)
+{
+ bool edge1IsParent = (edge1.item == item->parentItem());
+ bool edge2IsParent = (edge2.item == item->parentItem());
+ bool edge1IsSibling = (edge1.item->parentItem() == item->parentItem());
+ bool edge2IsSibling = (edge2.item->parentItem() == item->parentItem());
+
+ bool invalid = false;
+ if ((edge2IsParent && edge1IsParent) || (edge2IsSibling && edge1IsSibling)) {
+ stretch = (position(edge2.item, edge2.anchorLine) + offset2)
+ - (position(edge1.item, edge1.anchorLine) + offset1);
+ } else if (edge2IsParent && edge1IsSibling) {
+ stretch = (position(edge2.item, edge2.anchorLine) + offset2)
+ - (position(item->parentObject(), line)
+ + position(edge1.item, edge1.anchorLine) + offset1);
+ } else if (edge2IsSibling && edge1IsParent) {
+ stretch = (position(item->parentObject(), line) + position(edge2.item, edge2.anchorLine) + offset2)
+ - (position(edge1.item, edge1.anchorLine) + offset1);
+ } else
+ invalid = true;
+
+ return invalid;
+}
+
+void QDeclarative1AnchorsPrivate::updateVerticalAnchors()
+{
+ if (fill || centerIn || !isItemComplete())
+ return;
+
+ if (updatingVerticalAnchor < 2) {
+ ++updatingVerticalAnchor;
+ QGraphicsItemPrivate *itemPrivate = QGraphicsItemPrivate::get(item);
+ if (usedAnchors & QDeclarative1Anchors::TopAnchor) {
+ //Handle stretching
+ bool invalid = true;
+ qreal height = 0.0;
+ if (usedAnchors & QDeclarative1Anchors::BottomAnchor) {
+ invalid = calcStretch(top, bottom, topMargin, -bottomMargin, QDeclarative1AnchorLine::Top, height);
+ } else if (usedAnchors & QDeclarative1Anchors::VCenterAnchor) {
+ invalid = calcStretch(top, vCenter, topMargin, vCenterOffset, QDeclarative1AnchorLine::Top, height);
+ height *= 2;
+ }
+ if (!invalid)
+ setItemHeight(height);
+
+ //Handle top
+ if (top.item == item->parentItem()) {
+ setItemY(adjustedPosition(top.item, top.anchorLine) + topMargin);
+ } else if (top.item->parentItem() == item->parentItem()) {
+ setItemY(position(top.item, top.anchorLine) + topMargin);
+ }
+ } else if (usedAnchors & QDeclarative1Anchors::BottomAnchor) {
+ //Handle stretching (top + bottom case is handled above)
+ if (usedAnchors & QDeclarative1Anchors::VCenterAnchor) {
+ qreal height = 0.0;
+ bool invalid = calcStretch(vCenter, bottom, vCenterOffset, -bottomMargin,
+ QDeclarative1AnchorLine::Top, height);
+ if (!invalid)
+ setItemHeight(height*2);
+ }
+
+ //Handle bottom
+ if (bottom.item == item->parentItem()) {
+ setItemY(adjustedPosition(bottom.item, bottom.anchorLine) - itemPrivate->height() - bottomMargin);
+ } else if (bottom.item->parentItem() == item->parentItem()) {
+ setItemY(position(bottom.item, bottom.anchorLine) - itemPrivate->height() - bottomMargin);
+ }
+ } else if (usedAnchors & QDeclarative1Anchors::VCenterAnchor) {
+ //(stetching handled above)
+
+ //Handle vCenter
+ if (vCenter.item == item->parentItem()) {
+ setItemY(adjustedPosition(vCenter.item, vCenter.anchorLine)
+ - vcenter(item) + vCenterOffset);
+ } else if (vCenter.item->parentItem() == item->parentItem()) {
+ setItemY(position(vCenter.item, vCenter.anchorLine) - vcenter(item) + vCenterOffset);
+ }
+ } else if (usedAnchors & QDeclarative1Anchors::BaselineAnchor) {
+ //Handle baseline
+ if (baseline.item == item->parentItem()) {
+ if (itemPrivate->isDeclarativeItem)
+ setItemY(adjustedPosition(baseline.item, baseline.anchorLine)
+ - static_cast<QDeclarativeItem *>(item)->baselineOffset() + baselineOffset);
+ } else if (baseline.item->parentItem() == item->parentItem()) {
+ if (itemPrivate->isDeclarativeItem)
+ setItemY(position(baseline.item, baseline.anchorLine)
+ - static_cast<QDeclarativeItem *>(item)->baselineOffset() + baselineOffset);
+ }
+ }
+ --updatingVerticalAnchor;
+ } else {
+ // ### Make this certain :)
+ qmlInfo(item) << QDeclarative1Anchors::tr("Possible anchor loop detected on vertical anchor.");
+ }
+}
+
+inline QDeclarative1AnchorLine::AnchorLine reverseAnchorLine(QDeclarative1AnchorLine::AnchorLine anchorLine) {
+ if (anchorLine == QDeclarative1AnchorLine::Left) {
+ return QDeclarative1AnchorLine::Right;
+ } else if (anchorLine == QDeclarative1AnchorLine::Right) {
+ return QDeclarative1AnchorLine::Left;
+ } else {
+ return anchorLine;
+ }
+}
+
+void QDeclarative1AnchorsPrivate::updateHorizontalAnchors()
+{
+ Q_Q(QDeclarative1Anchors);
+ if (fill || centerIn || !isItemComplete())
+ return;
+
+ if (updatingHorizontalAnchor < 3) {
+ ++updatingHorizontalAnchor;
+ qreal effectiveRightMargin, effectiveLeftMargin, effectiveHorizontalCenterOffset;
+ QDeclarative1AnchorLine effectiveLeft, effectiveRight, effectiveHorizontalCenter;
+ QDeclarative1Anchors::Anchor effectiveLeftAnchor, effectiveRightAnchor;
+ if (q->mirrored()) {
+ effectiveLeftAnchor = QDeclarative1Anchors::RightAnchor;
+ effectiveRightAnchor = QDeclarative1Anchors::LeftAnchor;
+ effectiveLeft.item = right.item;
+ effectiveLeft.anchorLine = reverseAnchorLine(right.anchorLine);
+ effectiveRight.item = left.item;
+ effectiveRight.anchorLine = reverseAnchorLine(left.anchorLine);
+ effectiveHorizontalCenter.item = hCenter.item;
+ effectiveHorizontalCenter.anchorLine = reverseAnchorLine(hCenter.anchorLine);
+ effectiveLeftMargin = rightMargin;
+ effectiveRightMargin = leftMargin;
+ effectiveHorizontalCenterOffset = -hCenterOffset;
+ } else {
+ effectiveLeftAnchor = QDeclarative1Anchors::LeftAnchor;
+ effectiveRightAnchor = QDeclarative1Anchors::RightAnchor;
+ effectiveLeft = left;
+ effectiveRight = right;
+ effectiveHorizontalCenter = hCenter;
+ effectiveLeftMargin = leftMargin;
+ effectiveRightMargin = rightMargin;
+ effectiveHorizontalCenterOffset = hCenterOffset;
+ }
+
+ QGraphicsItemPrivate *itemPrivate = QGraphicsItemPrivate::get(item);
+ if (usedAnchors & effectiveLeftAnchor) {
+ //Handle stretching
+ bool invalid = true;
+ qreal width = 0.0;
+ if (usedAnchors & effectiveRightAnchor) {
+ invalid = calcStretch(effectiveLeft, effectiveRight, effectiveLeftMargin, -effectiveRightMargin, QDeclarative1AnchorLine::Left, width);
+ } else if (usedAnchors & QDeclarative1Anchors::HCenterAnchor) {
+ invalid = calcStretch(effectiveLeft, effectiveHorizontalCenter, effectiveLeftMargin, effectiveHorizontalCenterOffset, QDeclarative1AnchorLine::Left, width);
+ width *= 2;
+ }
+ if (!invalid)
+ setItemWidth(width);
+
+ //Handle left
+ if (effectiveLeft.item == item->parentItem()) {
+ setItemX(adjustedPosition(effectiveLeft.item, effectiveLeft.anchorLine) + effectiveLeftMargin);
+ } else if (effectiveLeft.item->parentItem() == item->parentItem()) {
+ setItemX(position(effectiveLeft.item, effectiveLeft.anchorLine) + effectiveLeftMargin);
+ }
+ } else if (usedAnchors & effectiveRightAnchor) {
+ //Handle stretching (left + right case is handled in updateLeftAnchor)
+ if (usedAnchors & QDeclarative1Anchors::HCenterAnchor) {
+ qreal width = 0.0;
+ bool invalid = calcStretch(effectiveHorizontalCenter, effectiveRight, effectiveHorizontalCenterOffset, -effectiveRightMargin,
+ QDeclarative1AnchorLine::Left, width);
+ if (!invalid)
+ setItemWidth(width*2);
+ }
+
+ //Handle right
+ if (effectiveRight.item == item->parentItem()) {
+ setItemX(adjustedPosition(effectiveRight.item, effectiveRight.anchorLine) - itemPrivate->width() - effectiveRightMargin);
+ } else if (effectiveRight.item->parentItem() == item->parentItem()) {
+ setItemX(position(effectiveRight.item, effectiveRight.anchorLine) - itemPrivate->width() - effectiveRightMargin);
+ }
+ } else if (usedAnchors & QDeclarative1Anchors::HCenterAnchor) {
+ //Handle hCenter
+ if (effectiveHorizontalCenter.item == item->parentItem()) {
+ setItemX(adjustedPosition(effectiveHorizontalCenter.item, effectiveHorizontalCenter.anchorLine) - hcenter(item) + effectiveHorizontalCenterOffset);
+ } else if (effectiveHorizontalCenter.item->parentItem() == item->parentItem()) {
+ setItemX(position(effectiveHorizontalCenter.item, effectiveHorizontalCenter.anchorLine) - hcenter(item) + effectiveHorizontalCenterOffset);
+ }
+ }
+ --updatingHorizontalAnchor;
+ } else {
+ // ### Make this certain :)
+ qmlInfo(item) << QDeclarative1Anchors::tr("Possible anchor loop detected on horizontal anchor.");
+ }
+}
+
+QDeclarative1AnchorLine QDeclarative1Anchors::top() const
+{
+ Q_D(const QDeclarative1Anchors);
+ return d->top;
+}
+
+void QDeclarative1Anchors::setTop(const QDeclarative1AnchorLine &edge)
+{
+ Q_D(QDeclarative1Anchors);
+ if (!d->checkVAnchorValid(edge) || d->top == edge)
+ return;
+
+ d->usedAnchors |= TopAnchor;
+
+ if (!d->checkVValid()) {
+ d->usedAnchors &= ~TopAnchor;
+ return;
+ }
+
+ d->remDepend(d->top.item);
+ d->top = edge;
+ d->addDepend(d->top.item);
+ emit topChanged();
+ d->updateVerticalAnchors();
+}
+
+void QDeclarative1Anchors::resetTop()
+{
+ Q_D(QDeclarative1Anchors);
+ d->usedAnchors &= ~TopAnchor;
+ d->remDepend(d->top.item);
+ d->top = QDeclarative1AnchorLine();
+ emit topChanged();
+ d->updateVerticalAnchors();
+}
+
+QDeclarative1AnchorLine QDeclarative1Anchors::bottom() const
+{
+ Q_D(const QDeclarative1Anchors);
+ return d->bottom;
+}
+
+void QDeclarative1Anchors::setBottom(const QDeclarative1AnchorLine &edge)
+{
+ Q_D(QDeclarative1Anchors);
+ if (!d->checkVAnchorValid(edge) || d->bottom == edge)
+ return;
+
+ d->usedAnchors |= BottomAnchor;
+
+ if (!d->checkVValid()) {
+ d->usedAnchors &= ~BottomAnchor;
+ return;
+ }
+
+ d->remDepend(d->bottom.item);
+ d->bottom = edge;
+ d->addDepend(d->bottom.item);
+ emit bottomChanged();
+ d->updateVerticalAnchors();
+}
+
+void QDeclarative1Anchors::resetBottom()
+{
+ Q_D(QDeclarative1Anchors);
+ d->usedAnchors &= ~BottomAnchor;
+ d->remDepend(d->bottom.item);
+ d->bottom = QDeclarative1AnchorLine();
+ emit bottomChanged();
+ d->updateVerticalAnchors();
+}
+
+QDeclarative1AnchorLine QDeclarative1Anchors::verticalCenter() const
+{
+ Q_D(const QDeclarative1Anchors);
+ return d->vCenter;
+}
+
+void QDeclarative1Anchors::setVerticalCenter(const QDeclarative1AnchorLine &edge)
+{
+ Q_D(QDeclarative1Anchors);
+ if (!d->checkVAnchorValid(edge) || d->vCenter == edge)
+ return;
+
+ d->usedAnchors |= VCenterAnchor;
+
+ if (!d->checkVValid()) {
+ d->usedAnchors &= ~VCenterAnchor;
+ return;
+ }
+
+ d->remDepend(d->vCenter.item);
+ d->vCenter = edge;
+ d->addDepend(d->vCenter.item);
+ emit verticalCenterChanged();
+ d->updateVerticalAnchors();
+}
+
+void QDeclarative1Anchors::resetVerticalCenter()
+{
+ Q_D(QDeclarative1Anchors);
+ d->usedAnchors &= ~VCenterAnchor;
+ d->remDepend(d->vCenter.item);
+ d->vCenter = QDeclarative1AnchorLine();
+ emit verticalCenterChanged();
+ d->updateVerticalAnchors();
+}
+
+QDeclarative1AnchorLine QDeclarative1Anchors::baseline() const
+{
+ Q_D(const QDeclarative1Anchors);
+ return d->baseline;
+}
+
+void QDeclarative1Anchors::setBaseline(const QDeclarative1AnchorLine &edge)
+{
+ Q_D(QDeclarative1Anchors);
+ if (!d->checkVAnchorValid(edge) || d->baseline == edge)
+ return;
+
+ d->usedAnchors |= BaselineAnchor;
+
+ if (!d->checkVValid()) {
+ d->usedAnchors &= ~BaselineAnchor;
+ return;
+ }
+
+ d->remDepend(d->baseline.item);
+ d->baseline = edge;
+ d->addDepend(d->baseline.item);
+ emit baselineChanged();
+ d->updateVerticalAnchors();
+}
+
+void QDeclarative1Anchors::resetBaseline()
+{
+ Q_D(QDeclarative1Anchors);
+ d->usedAnchors &= ~BaselineAnchor;
+ d->remDepend(d->baseline.item);
+ d->baseline = QDeclarative1AnchorLine();
+ emit baselineChanged();
+ d->updateVerticalAnchors();
+}
+
+QDeclarative1AnchorLine QDeclarative1Anchors::left() const
+{
+ Q_D(const QDeclarative1Anchors);
+ return d->left;
+}
+
+void QDeclarative1Anchors::setLeft(const QDeclarative1AnchorLine &edge)
+{
+ Q_D(QDeclarative1Anchors);
+ if (!d->checkHAnchorValid(edge) || d->left == edge)
+ return;
+
+ d->usedAnchors |= LeftAnchor;
+
+ if (!d->checkHValid()) {
+ d->usedAnchors &= ~LeftAnchor;
+ return;
+ }
+
+ d->remDepend(d->left.item);
+ d->left = edge;
+ d->addDepend(d->left.item);
+ emit leftChanged();
+ d->updateHorizontalAnchors();
+}
+
+void QDeclarative1Anchors::resetLeft()
+{
+ Q_D(QDeclarative1Anchors);
+ d->usedAnchors &= ~LeftAnchor;
+ d->remDepend(d->left.item);
+ d->left = QDeclarative1AnchorLine();
+ emit leftChanged();
+ d->updateHorizontalAnchors();
+}
+
+QDeclarative1AnchorLine QDeclarative1Anchors::right() const
+{
+ Q_D(const QDeclarative1Anchors);
+ return d->right;
+}
+
+void QDeclarative1Anchors::setRight(const QDeclarative1AnchorLine &edge)
+{
+ Q_D(QDeclarative1Anchors);
+ if (!d->checkHAnchorValid(edge) || d->right == edge)
+ return;
+
+ d->usedAnchors |= RightAnchor;
+
+ if (!d->checkHValid()) {
+ d->usedAnchors &= ~RightAnchor;
+ return;
+ }
+
+ d->remDepend(d->right.item);
+ d->right = edge;
+ d->addDepend(d->right.item);
+ emit rightChanged();
+ d->updateHorizontalAnchors();
+}
+
+void QDeclarative1Anchors::resetRight()
+{
+ Q_D(QDeclarative1Anchors);
+ d->usedAnchors &= ~RightAnchor;
+ d->remDepend(d->right.item);
+ d->right = QDeclarative1AnchorLine();
+ emit rightChanged();
+ d->updateHorizontalAnchors();
+}
+
+QDeclarative1AnchorLine QDeclarative1Anchors::horizontalCenter() const
+{
+ Q_D(const QDeclarative1Anchors);
+ return d->hCenter;
+}
+
+void QDeclarative1Anchors::setHorizontalCenter(const QDeclarative1AnchorLine &edge)
+{
+ Q_D(QDeclarative1Anchors);
+ if (!d->checkHAnchorValid(edge) || d->hCenter == edge)
+ return;
+
+ d->usedAnchors |= HCenterAnchor;
+
+ if (!d->checkHValid()) {
+ d->usedAnchors &= ~HCenterAnchor;
+ return;
+ }
+
+ d->remDepend(d->hCenter.item);
+ d->hCenter = edge;
+ d->addDepend(d->hCenter.item);
+ emit horizontalCenterChanged();
+ d->updateHorizontalAnchors();
+}
+
+void QDeclarative1Anchors::resetHorizontalCenter()
+{
+ Q_D(QDeclarative1Anchors);
+ d->usedAnchors &= ~HCenterAnchor;
+ d->remDepend(d->hCenter.item);
+ d->hCenter = QDeclarative1AnchorLine();
+ emit horizontalCenterChanged();
+ d->updateHorizontalAnchors();
+}
+
+qreal QDeclarative1Anchors::leftMargin() const
+{
+ Q_D(const QDeclarative1Anchors);
+ return d->leftMargin;
+}
+
+void QDeclarative1Anchors::setLeftMargin(qreal offset)
+{
+ Q_D(QDeclarative1Anchors);
+ if (d->leftMargin == offset)
+ return;
+ d->leftMargin = offset;
+ if(d->fill)
+ d->fillChanged();
+ else
+ d->updateHorizontalAnchors();
+ emit leftMarginChanged();
+}
+
+qreal QDeclarative1Anchors::rightMargin() const
+{
+ Q_D(const QDeclarative1Anchors);
+ return d->rightMargin;
+}
+
+void QDeclarative1Anchors::setRightMargin(qreal offset)
+{
+ Q_D(QDeclarative1Anchors);
+ if (d->rightMargin == offset)
+ return;
+ d->rightMargin = offset;
+ if(d->fill)
+ d->fillChanged();
+ else
+ d->updateHorizontalAnchors();
+ emit rightMarginChanged();
+}
+
+qreal QDeclarative1Anchors::margins() const
+{
+ Q_D(const QDeclarative1Anchors);
+ return d->margins;
+}
+
+void QDeclarative1Anchors::setMargins(qreal offset)
+{
+ Q_D(QDeclarative1Anchors);
+ if (d->margins == offset)
+ return;
+ //###Is it significantly faster to set them directly so we can call fillChanged only once?
+ if(!d->rightMargin || d->rightMargin == d->margins)
+ setRightMargin(offset);
+ if(!d->leftMargin || d->leftMargin == d->margins)
+ setLeftMargin(offset);
+ if(!d->topMargin || d->topMargin == d->margins)
+ setTopMargin(offset);
+ if(!d->bottomMargin || d->bottomMargin == d->margins)
+ setBottomMargin(offset);
+ d->margins = offset;
+ emit marginsChanged();
+
+}
+
+qreal QDeclarative1Anchors::horizontalCenterOffset() const
+{
+ Q_D(const QDeclarative1Anchors);
+ return d->hCenterOffset;
+}
+
+void QDeclarative1Anchors::setHorizontalCenterOffset(qreal offset)
+{
+ Q_D(QDeclarative1Anchors);
+ if (d->hCenterOffset == offset)
+ return;
+ d->hCenterOffset = offset;
+ if(d->centerIn)
+ d->centerInChanged();
+ else
+ d->updateHorizontalAnchors();
+ emit horizontalCenterOffsetChanged();
+}
+
+qreal QDeclarative1Anchors::topMargin() const
+{
+ Q_D(const QDeclarative1Anchors);
+ return d->topMargin;
+}
+
+void QDeclarative1Anchors::setTopMargin(qreal offset)
+{
+ Q_D(QDeclarative1Anchors);
+ if (d->topMargin == offset)
+ return;
+ d->topMargin = offset;
+ if(d->fill)
+ d->fillChanged();
+ else
+ d->updateVerticalAnchors();
+ emit topMarginChanged();
+}
+
+qreal QDeclarative1Anchors::bottomMargin() const
+{
+ Q_D(const QDeclarative1Anchors);
+ return d->bottomMargin;
+}
+
+void QDeclarative1Anchors::setBottomMargin(qreal offset)
+{
+ Q_D(QDeclarative1Anchors);
+ if (d->bottomMargin == offset)
+ return;
+ d->bottomMargin = offset;
+ if(d->fill)
+ d->fillChanged();
+ else
+ d->updateVerticalAnchors();
+ emit bottomMarginChanged();
+}
+
+qreal QDeclarative1Anchors::verticalCenterOffset() const
+{
+ Q_D(const QDeclarative1Anchors);
+ return d->vCenterOffset;
+}
+
+void QDeclarative1Anchors::setVerticalCenterOffset(qreal offset)
+{
+ Q_D(QDeclarative1Anchors);
+ if (d->vCenterOffset == offset)
+ return;
+ d->vCenterOffset = offset;
+ if(d->centerIn)
+ d->centerInChanged();
+ else
+ d->updateVerticalAnchors();
+ emit verticalCenterOffsetChanged();
+}
+
+qreal QDeclarative1Anchors::baselineOffset() const
+{
+ Q_D(const QDeclarative1Anchors);
+ return d->baselineOffset;
+}
+
+void QDeclarative1Anchors::setBaselineOffset(qreal offset)
+{
+ Q_D(QDeclarative1Anchors);
+ if (d->baselineOffset == offset)
+ return;
+ d->baselineOffset = offset;
+ d->updateVerticalAnchors();
+ emit baselineOffsetChanged();
+}
+
+QDeclarative1Anchors::Anchors QDeclarative1Anchors::usedAnchors() const
+{
+ Q_D(const QDeclarative1Anchors);
+ return d->usedAnchors;
+}
+
+bool QDeclarative1AnchorsPrivate::checkHValid() const
+{
+ if (usedAnchors & QDeclarative1Anchors::LeftAnchor &&
+ usedAnchors & QDeclarative1Anchors::RightAnchor &&
+ usedAnchors & QDeclarative1Anchors::HCenterAnchor) {
+ qmlInfo(item) << QDeclarative1Anchors::tr("Cannot specify left, right, and hcenter anchors.");
+ return false;
+ }
+
+ return true;
+}
+
+bool QDeclarative1AnchorsPrivate::checkHAnchorValid(QDeclarative1AnchorLine anchor) const
+{
+ if (!anchor.item) {
+ qmlInfo(item) << QDeclarative1Anchors::tr("Cannot anchor to a null item.");
+ return false;
+ } else if (anchor.anchorLine & QDeclarative1AnchorLine::Vertical_Mask) {
+ qmlInfo(item) << QDeclarative1Anchors::tr("Cannot anchor a horizontal edge to a vertical edge.");
+ return false;
+ } else if (anchor.item != item->parentItem() && anchor.item->parentItem() != item->parentItem()){
+ qmlInfo(item) << QDeclarative1Anchors::tr("Cannot anchor to an item that isn't a parent or sibling.");
+ return false;
+ } else if (anchor.item == item) {
+ qmlInfo(item) << QDeclarative1Anchors::tr("Cannot anchor item to self.");
+ return false;
+ }
+
+ return true;
+}
+
+bool QDeclarative1AnchorsPrivate::checkVValid() const
+{
+ if (usedAnchors & QDeclarative1Anchors::TopAnchor &&
+ usedAnchors & QDeclarative1Anchors::BottomAnchor &&
+ usedAnchors & QDeclarative1Anchors::VCenterAnchor) {
+ qmlInfo(item) << QDeclarative1Anchors::tr("Cannot specify top, bottom, and vcenter anchors.");
+ return false;
+ } else if (usedAnchors & QDeclarative1Anchors::BaselineAnchor &&
+ (usedAnchors & QDeclarative1Anchors::TopAnchor ||
+ usedAnchors & QDeclarative1Anchors::BottomAnchor ||
+ usedAnchors & QDeclarative1Anchors::VCenterAnchor)) {
+ qmlInfo(item) << QDeclarative1Anchors::tr("Baseline anchor cannot be used in conjunction with top, bottom, or vcenter anchors.");
+ return false;
+ }
+
+ return true;
+}
+
+bool QDeclarative1AnchorsPrivate::checkVAnchorValid(QDeclarative1AnchorLine anchor) const
+{
+ if (!anchor.item) {
+ qmlInfo(item) << QDeclarative1Anchors::tr("Cannot anchor to a null item.");
+ return false;
+ } else if (anchor.anchorLine & QDeclarative1AnchorLine::Horizontal_Mask) {
+ qmlInfo(item) << QDeclarative1Anchors::tr("Cannot anchor a vertical edge to a horizontal edge.");
+ return false;
+ } else if (anchor.item != item->parentItem() && anchor.item->parentItem() != item->parentItem()){
+ qmlInfo(item) << QDeclarative1Anchors::tr("Cannot anchor to an item that isn't a parent or sibling.");
+ return false;
+ } else if (anchor.item == item){
+ qmlInfo(item) << QDeclarative1Anchors::tr("Cannot anchor item to self.");
+ return false;
+ }
+
+ return true;
+}
+
+
+
+QT_END_NAMESPACE
+
+#include <moc_qdeclarativeanchors_p.cpp>
+
diff --git a/src/qtquick1/graphicsitems/qdeclarativeanchors_p.h b/src/qtquick1/graphicsitems/qdeclarativeanchors_p.h
new file mode 100644
index 0000000000..96a5f27f1e
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativeanchors_p.h
@@ -0,0 +1,206 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEANCHORS_H
+#define QDECLARATIVEANCHORS_H
+
+#include "qdeclarativeitem.h"
+
+#include <QtDeclarative/qdeclarative.h>
+
+#include <QtCore/QObject>
+
+#include <QtDeclarative/private/qdeclarativeglobal_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarative1AnchorsPrivate;
+class QDeclarative1AnchorLine;
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarative1Anchors : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QDeclarative1AnchorLine left READ left WRITE setLeft RESET resetLeft NOTIFY leftChanged)
+ Q_PROPERTY(QDeclarative1AnchorLine right READ right WRITE setRight RESET resetRight NOTIFY rightChanged)
+ Q_PROPERTY(QDeclarative1AnchorLine horizontalCenter READ horizontalCenter WRITE setHorizontalCenter RESET resetHorizontalCenter NOTIFY horizontalCenterChanged)
+ Q_PROPERTY(QDeclarative1AnchorLine top READ top WRITE setTop RESET resetTop NOTIFY topChanged)
+ Q_PROPERTY(QDeclarative1AnchorLine bottom READ bottom WRITE setBottom RESET resetBottom NOTIFY bottomChanged)
+ Q_PROPERTY(QDeclarative1AnchorLine verticalCenter READ verticalCenter WRITE setVerticalCenter RESET resetVerticalCenter NOTIFY verticalCenterChanged)
+ Q_PROPERTY(QDeclarative1AnchorLine baseline READ baseline WRITE setBaseline RESET resetBaseline NOTIFY baselineChanged)
+ Q_PROPERTY(qreal margins READ margins WRITE setMargins NOTIFY marginsChanged)
+ Q_PROPERTY(qreal leftMargin READ leftMargin WRITE setLeftMargin NOTIFY leftMarginChanged)
+ Q_PROPERTY(qreal rightMargin READ rightMargin WRITE setRightMargin NOTIFY rightMarginChanged)
+ Q_PROPERTY(qreal horizontalCenterOffset READ horizontalCenterOffset WRITE setHorizontalCenterOffset NOTIFY horizontalCenterOffsetChanged)
+ Q_PROPERTY(qreal topMargin READ topMargin WRITE setTopMargin NOTIFY topMarginChanged)
+ Q_PROPERTY(qreal bottomMargin READ bottomMargin WRITE setBottomMargin NOTIFY bottomMarginChanged)
+ Q_PROPERTY(qreal verticalCenterOffset READ verticalCenterOffset WRITE setVerticalCenterOffset NOTIFY verticalCenterOffsetChanged)
+ Q_PROPERTY(qreal baselineOffset READ baselineOffset WRITE setBaselineOffset NOTIFY baselineOffsetChanged)
+ Q_PROPERTY(QGraphicsObject *fill READ fill WRITE setFill RESET resetFill NOTIFY fillChanged)
+ Q_PROPERTY(QGraphicsObject *centerIn READ centerIn WRITE setCenterIn RESET resetCenterIn NOTIFY centerInChanged)
+ Q_PROPERTY(bool mirrored READ mirrored NOTIFY mirroredChanged REVISION 1)
+
+public:
+ QDeclarative1Anchors(QObject *parent=0);
+ QDeclarative1Anchors(QGraphicsObject *item, QObject *parent=0);
+ virtual ~QDeclarative1Anchors();
+
+ enum Anchor {
+ LeftAnchor = 0x01,
+ RightAnchor = 0x02,
+ TopAnchor = 0x04,
+ BottomAnchor = 0x08,
+ HCenterAnchor = 0x10,
+ VCenterAnchor = 0x20,
+ BaselineAnchor = 0x40,
+ Horizontal_Mask = LeftAnchor | RightAnchor | HCenterAnchor,
+ Vertical_Mask = TopAnchor | BottomAnchor | VCenterAnchor | BaselineAnchor
+ };
+ Q_DECLARE_FLAGS(Anchors, Anchor)
+
+ QDeclarative1AnchorLine left() const;
+ void setLeft(const QDeclarative1AnchorLine &edge);
+ void resetLeft();
+
+ QDeclarative1AnchorLine right() const;
+ void setRight(const QDeclarative1AnchorLine &edge);
+ void resetRight();
+
+ QDeclarative1AnchorLine horizontalCenter() const;
+ void setHorizontalCenter(const QDeclarative1AnchorLine &edge);
+ void resetHorizontalCenter();
+
+ QDeclarative1AnchorLine top() const;
+ void setTop(const QDeclarative1AnchorLine &edge);
+ void resetTop();
+
+ QDeclarative1AnchorLine bottom() const;
+ void setBottom(const QDeclarative1AnchorLine &edge);
+ void resetBottom();
+
+ QDeclarative1AnchorLine verticalCenter() const;
+ void setVerticalCenter(const QDeclarative1AnchorLine &edge);
+ void resetVerticalCenter();
+
+ QDeclarative1AnchorLine baseline() const;
+ void setBaseline(const QDeclarative1AnchorLine &edge);
+ void resetBaseline();
+
+ qreal leftMargin() const;
+ void setLeftMargin(qreal);
+
+ qreal rightMargin() const;
+ void setRightMargin(qreal);
+
+ qreal horizontalCenterOffset() const;
+ void setHorizontalCenterOffset(qreal);
+
+ qreal topMargin() const;
+ void setTopMargin(qreal);
+
+ qreal bottomMargin() const;
+ void setBottomMargin(qreal);
+
+ qreal margins() const;
+ void setMargins(qreal);
+
+ qreal verticalCenterOffset() const;
+ void setVerticalCenterOffset(qreal);
+
+ qreal baselineOffset() const;
+ void setBaselineOffset(qreal);
+
+ QGraphicsObject *fill() const;
+ void setFill(QGraphicsObject *);
+ void resetFill();
+
+ QGraphicsObject *centerIn() const;
+ void setCenterIn(QGraphicsObject *);
+ void resetCenterIn();
+
+ Anchors usedAnchors() const;
+
+ void classBegin();
+ void componentComplete();
+
+ bool mirrored();
+
+Q_SIGNALS:
+ void leftChanged();
+ void rightChanged();
+ void topChanged();
+ void bottomChanged();
+ void verticalCenterChanged();
+ void horizontalCenterChanged();
+ void baselineChanged();
+ void fillChanged();
+ void centerInChanged();
+ void leftMarginChanged();
+ void rightMarginChanged();
+ void topMarginChanged();
+ void bottomMarginChanged();
+ void marginsChanged();
+ void verticalCenterOffsetChanged();
+ void horizontalCenterOffsetChanged();
+ void baselineOffsetChanged();
+ Q_REVISION(1) void mirroredChanged();
+
+private:
+ friend class QDeclarativeItem;
+ friend class QDeclarativeItemPrivate;
+ friend class QDeclarative1GraphicsWidget;
+ Q_DISABLE_COPY(QDeclarative1Anchors)
+ Q_DECLARE_PRIVATE(QDeclarative1Anchors)
+ Q_PRIVATE_SLOT(d_func(), void _q_widgetGeometryChanged())
+ Q_PRIVATE_SLOT(d_func(), void _q_widgetDestroyed(QObject *obj))
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarative1Anchors::Anchors)
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1Anchors)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/qtquick1/graphicsitems/qdeclarativeanchors_p_p.h b/src/qtquick1/graphicsitems/qdeclarativeanchors_p_p.h
new file mode 100644
index 0000000000..225f112636
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativeanchors_p_p.h
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEANCHORS_P_H
+#define QDECLARATIVEANCHORS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtQuick1/private/qdeclarativeanchors_p.h"
+#include "QtQuick1/private/qdeclarativeitemchangelistener_p.h"
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+// NOTE: if you change this then also update the copy in qdeclarativev4compiler_p_p.h
+class QDeclarative1AnchorLine
+{
+public:
+ QDeclarative1AnchorLine() : item(0), anchorLine(Invalid) {}
+
+ enum AnchorLine {
+ Invalid = 0x0,
+ Left = 0x01,
+ Right = 0x02,
+ Top = 0x04,
+ Bottom = 0x08,
+ HCenter = 0x10,
+ VCenter = 0x20,
+ Baseline = 0x40,
+ Horizontal_Mask = Left | Right | HCenter,
+ Vertical_Mask = Top | Bottom | VCenter | Baseline
+ };
+
+ QGraphicsObject *item;
+ AnchorLine anchorLine;
+};
+
+inline bool operator==(const QDeclarative1AnchorLine& a, const QDeclarative1AnchorLine& b)
+{
+ return a.item == b.item && a.anchorLine == b.anchorLine;
+}
+
+class QDeclarative1AnchorsPrivate : public QObjectPrivate, public QDeclarativeItemChangeListener
+{
+ Q_DECLARE_PUBLIC(QDeclarative1Anchors)
+public:
+ QDeclarative1AnchorsPrivate(QGraphicsObject *i)
+ : componentComplete(true), updatingMe(false), updatingHorizontalAnchor(0),
+ updatingVerticalAnchor(0), updatingFill(0), updatingCenterIn(0), item(i), usedAnchors(0), fill(0),
+ centerIn(0), leftMargin(0), rightMargin(0), topMargin(0), bottomMargin(0),
+ margins(0), vCenterOffset(0), hCenterOffset(0), baselineOffset(0)
+ {
+ }
+
+ void clearItem(QGraphicsObject *);
+
+ void addDepend(QGraphicsObject *);
+ void remDepend(QGraphicsObject *);
+ bool isItemComplete() const;
+
+ bool componentComplete:1;
+ bool updatingMe:1;
+ uint updatingHorizontalAnchor:2;
+ uint updatingVerticalAnchor:2;
+ uint updatingFill:2;
+ uint updatingCenterIn:2;
+
+ void setItemHeight(qreal);
+ void setItemWidth(qreal);
+ void setItemX(qreal);
+ void setItemY(qreal);
+ void setItemPos(const QPointF &);
+ void setItemSize(const QSizeF &);
+
+ void updateOnComplete();
+ void updateMe();
+
+ // QDeclarativeItemGeometryListener interface
+ void itemGeometryChanged(QDeclarativeItem *, const QRectF &, const QRectF &);
+ void _q_widgetDestroyed(QObject *);
+ void _q_widgetGeometryChanged();
+ QDeclarative1AnchorsPrivate *anchorPrivate() { return this; }
+
+ bool checkHValid() const;
+ bool checkVValid() const;
+ bool checkHAnchorValid(QDeclarative1AnchorLine anchor) const;
+ bool checkVAnchorValid(QDeclarative1AnchorLine anchor) const;
+ bool calcStretch(const QDeclarative1AnchorLine &edge1, const QDeclarative1AnchorLine &edge2, qreal offset1, qreal offset2, QDeclarative1AnchorLine::AnchorLine line, qreal &stretch);
+
+ bool isMirrored() const;
+ void updateHorizontalAnchors();
+ void updateVerticalAnchors();
+ void fillChanged();
+ void centerInChanged();
+
+ QGraphicsObject *item;
+ QDeclarative1Anchors::Anchors usedAnchors;
+
+ QGraphicsObject *fill;
+ QGraphicsObject *centerIn;
+
+ QDeclarative1AnchorLine left;
+ QDeclarative1AnchorLine right;
+ QDeclarative1AnchorLine top;
+ QDeclarative1AnchorLine bottom;
+ QDeclarative1AnchorLine vCenter;
+ QDeclarative1AnchorLine hCenter;
+ QDeclarative1AnchorLine baseline;
+
+ qreal leftMargin;
+ qreal rightMargin;
+ qreal topMargin;
+ qreal bottomMargin;
+ qreal margins;
+ qreal vCenterOffset;
+ qreal hCenterOffset;
+ qreal baselineOffset;
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QDeclarative1AnchorLine)
+
+#endif
diff --git a/src/qtquick1/graphicsitems/qdeclarativeanimatedimage.cpp b/src/qtquick1/graphicsitems/qdeclarativeanimatedimage.cpp
new file mode 100644
index 0000000000..5d7ad80bbb
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativeanimatedimage.cpp
@@ -0,0 +1,408 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativeanimatedimage_p.h"
+#include "QtQuick1/private/qdeclarativeanimatedimage_p_p.h"
+
+#ifndef QT_NO_MOVIE
+
+#include <QtDeclarative/qdeclarativeinfo.h>
+#include <QtDeclarative/private/qdeclarativeengine_p.h>
+
+#include <QMovie>
+#include <QNetworkRequest>
+#include <QNetworkReply>
+
+QT_BEGIN_NAMESPACE
+
+
+
+/*!
+ \qmlclass AnimatedImage QDeclarative1AnimatedImage
+ \inherits Image
+ \since 4.7
+ \ingroup basic-visual-elements
+
+ The AnimatedImage element extends the features of the \l Image element, providing
+ a way to play animations stored as images containing a series of frames,
+ such as those stored in GIF files.
+
+ Information about the current frame and totla length of the animation can be
+ obtained using the \l currentFrame and \l frameCount properties. You can
+ start, pause and stop the animation by changing the values of the \l playing
+ and \l paused properties.
+
+ The full list of supported formats can be determined with QMovie::supportedFormats().
+
+ \section1 Example Usage
+
+ \beginfloatleft
+ \image animatedimageitem.gif
+ \endfloat
+
+ The following QML shows how to display an animated image and obtain information
+ about its state, such as the current frame and total number of frames.
+ The result is an animated image with a simple progress indicator underneath it.
+
+ \clearfloat
+ \snippet doc/src/snippets/declarative/animatedimage.qml document
+
+ \sa BorderImage, Image
+*/
+
+/*!
+ \qmlproperty url AnimatedImage::source
+
+ This property holds the URL that refers to the source image.
+
+ AnimatedImage can handle any image format supported by Qt, loaded from any
+ URL scheme supported by Qt.
+
+ \sa QDeclarativeImageProvider
+*/
+
+/*!
+ \qmlproperty bool AnimatedImage::asynchronous
+
+ Specifies that images on the local filesystem should be loaded
+ asynchronously in a separate thread. The default value is
+ false, causing the user interface thread to block while the
+ image is loaded. Setting \a asynchronous to true is useful where
+ maintaining a responsive user interface is more desirable
+ than having images immediately visible.
+
+ Note that this property is only valid for images read from the
+ local filesystem. Images loaded via a network resource (e.g. HTTP)
+ are always loaded asynchonously.
+*/
+
+/*!
+ \qmlproperty bool AnimatedImage::cache
+ \since Quick 1.1
+
+ Specifies whether the image should be cached. The default value is
+ true. Setting \a cache to false is useful when dealing with large images,
+ to make sure that they aren't cached at the expense of small 'ui element' images.
+*/
+
+/*!
+ \qmlproperty bool AnimatedImage::mirror
+ \since Quick 1.1
+
+ This property holds whether the image should be horizontally inverted
+ (effectively displaying a mirrored image).
+
+ The default value is false.
+*/
+
+QDeclarative1AnimatedImage::QDeclarative1AnimatedImage(QDeclarativeItem *parent)
+ : QDeclarative1Image(*(new QDeclarative1AnimatedImagePrivate), parent)
+{
+}
+
+QDeclarative1AnimatedImage::~QDeclarative1AnimatedImage()
+{
+ Q_D(QDeclarative1AnimatedImage);
+ delete d->_movie;
+}
+
+/*!
+ \qmlproperty bool AnimatedImage::paused
+ This property holds whether the animated image is paused.
+
+ By default, this property is false. Set it to true when you want to pause
+ the animation.
+*/
+bool QDeclarative1AnimatedImage::isPaused() const
+{
+ Q_D(const QDeclarative1AnimatedImage);
+ if(!d->_movie)
+ return false;
+ return d->_movie->state()==QMovie::Paused;
+}
+
+void QDeclarative1AnimatedImage::setPaused(bool pause)
+{
+ Q_D(QDeclarative1AnimatedImage);
+ if(pause == d->paused)
+ return;
+ d->paused = pause;
+ if(!d->_movie)
+ return;
+ d->_movie->setPaused(pause);
+}
+/*!
+ \qmlproperty bool AnimatedImage::playing
+ This property holds whether the animated image is playing.
+
+ By default, this property is true, meaning that the animation
+ will start playing immediately.
+*/
+bool QDeclarative1AnimatedImage::isPlaying() const
+{
+ Q_D(const QDeclarative1AnimatedImage);
+ if (!d->_movie)
+ return false;
+ return d->_movie->state()!=QMovie::NotRunning;
+}
+
+void QDeclarative1AnimatedImage::setPlaying(bool play)
+{
+ Q_D(QDeclarative1AnimatedImage);
+ if(play == d->playing)
+ return;
+ d->playing = play;
+ if (!d->_movie)
+ return;
+ if (play)
+ d->_movie->start();
+ else
+ d->_movie->stop();
+}
+
+/*!
+ \qmlproperty int AnimatedImage::currentFrame
+ \qmlproperty int AnimatedImage::frameCount
+
+ currentFrame is the frame that is currently visible. By monitoring this property
+ for changes, you can animate other items at the same time as the image.
+
+ frameCount is the number of frames in the animation. For some animation formats,
+ frameCount is unknown and has a value of zero.
+*/
+int QDeclarative1AnimatedImage::currentFrame() const
+{
+ Q_D(const QDeclarative1AnimatedImage);
+ if (!d->_movie)
+ return d->preset_currentframe;
+ return d->_movie->currentFrameNumber();
+}
+
+void QDeclarative1AnimatedImage::setCurrentFrame(int frame)
+{
+ Q_D(QDeclarative1AnimatedImage);
+ if (!d->_movie) {
+ d->preset_currentframe = frame;
+ return;
+ }
+ d->_movie->jumpToFrame(frame);
+}
+
+int QDeclarative1AnimatedImage::frameCount() const
+{
+ Q_D(const QDeclarative1AnimatedImage);
+ if (!d->_movie)
+ return 0;
+ return d->_movie->frameCount();
+}
+
+void QDeclarative1AnimatedImage::setSource(const QUrl &url)
+{
+ Q_D(QDeclarative1AnimatedImage);
+ if (url == d->url)
+ return;
+
+ delete d->_movie;
+ d->_movie = 0;
+
+ if (d->reply) {
+ d->reply->deleteLater();
+ d->reply = 0;
+ }
+
+ d->url = url;
+ emit sourceChanged(d->url);
+
+ if (isComponentComplete())
+ load();
+}
+
+void QDeclarative1AnimatedImage::load()
+{
+ Q_D(QDeclarative1AnimatedImage);
+
+ QDeclarative1ImageBase::Status oldStatus = d->status;
+ qreal oldProgress = d->progress;
+
+ if (d->url.isEmpty()) {
+ delete d->_movie;
+ d->setPixmap(QPixmap());
+ d->progress = 0;
+ d->status = Null;
+ if (d->status != oldStatus)
+ emit statusChanged(d->status);
+ if (d->progress != oldProgress)
+ emit progressChanged(d->progress);
+ } else {
+#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
+ QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(d->url);
+ if (!lf.isEmpty()) {
+ //### should be unified with movieRequestFinished
+ d->_movie = new QMovie(lf);
+ if (!d->_movie->isValid()){
+ qmlInfo(this) << "Error Reading Animated Image File " << d->url.toString();
+ delete d->_movie;
+ d->_movie = 0;
+ d->status = Error;
+ if (d->status != oldStatus)
+ emit statusChanged(d->status);
+ return;
+ }
+ connect(d->_movie, SIGNAL(stateChanged(QMovie::MovieState)),
+ this, SLOT(playingStatusChanged()));
+ connect(d->_movie, SIGNAL(frameChanged(int)),
+ this, SLOT(movieUpdate()));
+ d->_movie->setCacheMode(QMovie::CacheAll);
+ if(d->playing)
+ d->_movie->start();
+ else
+ d->_movie->jumpToFrame(0);
+ if(d->paused)
+ d->_movie->setPaused(true);
+ d->setPixmap(d->_movie->currentPixmap());
+ d->status = Ready;
+ d->progress = 1.0;
+ if (d->status != oldStatus)
+ emit statusChanged(d->status);
+ if (d->progress != oldProgress)
+ emit progressChanged(d->progress);
+ return;
+ }
+#endif
+ d->status = Loading;
+ d->progress = 0;
+ emit statusChanged(d->status);
+ emit progressChanged(d->progress);
+ QNetworkRequest req(d->url);
+ req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);
+ d->reply = qmlEngine(this)->networkAccessManager()->get(req);
+ QObject::connect(d->reply, SIGNAL(finished()),
+ this, SLOT(movieRequestFinished()));
+ QObject::connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)),
+ this, SLOT(requestProgress(qint64,qint64)));
+ }
+}
+
+#define ANIMATEDIMAGE_MAXIMUM_REDIRECT_RECURSION 16
+
+void QDeclarative1AnimatedImage::movieRequestFinished()
+{
+ Q_D(QDeclarative1AnimatedImage);
+
+ d->redirectCount++;
+ if (d->redirectCount < ANIMATEDIMAGE_MAXIMUM_REDIRECT_RECURSION) {
+ QVariant redirect = d->reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
+ if (redirect.isValid()) {
+ QUrl url = d->reply->url().resolved(redirect.toUrl());
+ d->reply->deleteLater();
+ d->reply = 0;
+ setSource(url);
+ return;
+ }
+ }
+ d->redirectCount=0;
+
+ d->_movie = new QMovie(d->reply);
+ if (!d->_movie->isValid()){
+#ifndef QT_NO_DEBUG_STREAM
+ qmlInfo(this) << "Error Reading Animated Image File " << d->url;
+#endif
+ delete d->_movie;
+ d->_movie = 0;
+ d->status = Error;
+ emit statusChanged(d->status);
+ return;
+ }
+ connect(d->_movie, SIGNAL(stateChanged(QMovie::MovieState)),
+ this, SLOT(playingStatusChanged()));
+ connect(d->_movie, SIGNAL(frameChanged(int)),
+ this, SLOT(movieUpdate()));
+ d->_movie->setCacheMode(QMovie::CacheAll);
+ if(d->playing)
+ d->_movie->start();
+ if (d->paused || !d->playing) {
+ d->_movie->jumpToFrame(d->preset_currentframe);
+ d->preset_currentframe = 0;
+ }
+ if(d->paused)
+ d->_movie->setPaused(true);
+ d->setPixmap(d->_movie->currentPixmap());
+ d->status = Ready;
+ emit statusChanged(d->status);
+}
+
+void QDeclarative1AnimatedImage::movieUpdate()
+{
+ Q_D(QDeclarative1AnimatedImage);
+ d->setPixmap(d->_movie->currentPixmap());
+ emit frameChanged();
+}
+
+void QDeclarative1AnimatedImage::playingStatusChanged()
+{
+ Q_D(QDeclarative1AnimatedImage);
+ if((d->_movie->state() != QMovie::NotRunning) != d->playing){
+ d->playing = (d->_movie->state() != QMovie::NotRunning);
+ emit playingChanged();
+ }
+ if((d->_movie->state() == QMovie::Paused) != d->paused){
+ d->playing = (d->_movie->state() == QMovie::Paused);
+ emit pausedChanged();
+ }
+}
+
+void QDeclarative1AnimatedImage::componentComplete()
+{
+ Q_D(QDeclarative1AnimatedImage);
+ QDeclarativeItem::componentComplete(); // NOT QDeclarative1Image
+ if (d->url.isValid())
+ load();
+ if (!d->reply) {
+ setCurrentFrame(d->preset_currentframe);
+ d->preset_currentframe = 0;
+ }
+}
+
+
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_MOVIE
diff --git a/src/qtquick1/graphicsitems/qdeclarativeanimatedimage_p.h b/src/qtquick1/graphicsitems/qdeclarativeanimatedimage_p.h
new file mode 100644
index 0000000000..e4f3939c01
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativeanimatedimage_p.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEANIMATEDIMAGE_H
+#define QDECLARATIVEANIMATEDIMAGE_H
+
+#include "private/qdeclarativeimage_p.h"
+
+#ifndef QT_NO_MOVIE
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QMovie;
+
+QT_MODULE(Declarative)
+
+class QDeclarative1AnimatedImagePrivate;
+
+class Q_AUTOTEST_EXPORT QDeclarative1AnimatedImage : public QDeclarative1Image
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool playing READ isPlaying WRITE setPlaying NOTIFY playingChanged)
+ Q_PROPERTY(bool paused READ isPaused WRITE setPaused NOTIFY pausedChanged)
+ Q_PROPERTY(int currentFrame READ currentFrame WRITE setCurrentFrame NOTIFY frameChanged)
+ Q_PROPERTY(int frameCount READ frameCount)
+
+ // read-only for AnimatedImage
+ Q_PROPERTY(QSize sourceSize READ sourceSize NOTIFY sourceSizeChanged)
+
+public:
+ QDeclarative1AnimatedImage(QDeclarativeItem *parent=0);
+ ~QDeclarative1AnimatedImage();
+
+ bool isPlaying() const;
+ void setPlaying(bool play);
+
+ bool isPaused() const;
+ void setPaused(bool pause);
+
+ int currentFrame() const;
+ void setCurrentFrame(int frame);
+
+ int frameCount() const;
+
+ // Extends QDeclarative1Image's src property*/
+ virtual void setSource(const QUrl&);
+
+Q_SIGNALS:
+ void playingChanged();
+ void pausedChanged();
+ void frameChanged();
+ void sourceSizeChanged();
+
+private Q_SLOTS:
+ void movieUpdate();
+ void movieRequestFinished();
+ void playingStatusChanged();
+
+protected:
+ virtual void load();
+ void componentComplete();
+
+private:
+ Q_DISABLE_COPY(QDeclarative1AnimatedImage)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarative1AnimatedImage)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1AnimatedImage)
+
+QT_END_HEADER
+
+#endif // QT_NO_MOVIE
+
+#endif
diff --git a/src/qtquick1/graphicsitems/qdeclarativeanimatedimage_p_p.h b/src/qtquick1/graphicsitems/qdeclarativeanimatedimage_p_p.h
new file mode 100644
index 0000000000..bf6c2f9460
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativeanimatedimage_p_p.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEANIMATEDIMAGE_P_H
+#define QDECLARATIVEANIMATEDIMAGE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qdeclarativeimage_p_p.h"
+
+#ifndef QT_NO_MOVIE
+
+QT_BEGIN_NAMESPACE
+
+class QMovie;
+class QNetworkReply;
+
+class QDeclarative1AnimatedImagePrivate : public QDeclarative1ImagePrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1AnimatedImage)
+
+public:
+ QDeclarative1AnimatedImagePrivate()
+ : playing(true), paused(false), preset_currentframe(0), _movie(0), reply(0), redirectCount(0)
+ {
+ }
+
+ bool playing;
+ bool paused;
+ int preset_currentframe;
+ QMovie *_movie;
+ QNetworkReply *reply;
+ int redirectCount;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_MOVIE
+
+#endif // QDECLARATIVEANIMATEDIMAGE_P_H
diff --git a/src/qtquick1/graphicsitems/qdeclarativeborderimage.cpp b/src/qtquick1/graphicsitems/qdeclarativeborderimage.cpp
new file mode 100644
index 0000000000..4588d14753
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativeborderimage.cpp
@@ -0,0 +1,621 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativeborderimage_p.h"
+#include "QtQuick1/private/qdeclarativeborderimage_p_p.h"
+
+#include <QtDeclarative/qdeclarativeinfo.h>
+#include <QtDeclarative/private/qdeclarativeengine_p.h>
+
+#include <QNetworkRequest>
+#include <QNetworkReply>
+#include <QFile>
+
+QT_BEGIN_NAMESPACE
+
+
+
+/*!
+ \qmlclass BorderImage QDeclarative1BorderImage
+ \brief The BorderImage element provides an image that can be used as a border.
+ \inherits Item
+ \since 4.7
+ \ingroup qml-basic-visual-elements
+
+ The BorderImage element is used to create borders out of images by scaling or tiling
+ parts of each image.
+
+ A BorderImage element breaks a source image, specified using the \l url property,
+ into 9 regions, as shown below:
+
+ \image declarative-scalegrid.png
+
+ When the image is scaled, regions of the source image are scaled or tiled to
+ create the displayed border image in the following way:
+
+ \list
+ \i The corners (regions 1, 3, 7, and 9) are not scaled at all.
+ \i Regions 2 and 8 are scaled according to
+ \l{BorderImage::horizontalTileMode}{horizontalTileMode}.
+ \i Regions 4 and 6 are scaled according to
+ \l{BorderImage::verticalTileMode}{verticalTileMode}.
+ \i The middle (region 5) is scaled according to both
+ \l{BorderImage::horizontalTileMode}{horizontalTileMode} and
+ \l{BorderImage::verticalTileMode}{verticalTileMode}.
+ \endlist
+
+ The regions of the image are defined using the \l border property group, which
+ describes the distance from each edge of the source image to use as a border.
+
+ \section1 Example Usage
+
+ The following examples show the effects of the different modes on an image.
+ Guide lines are overlaid onto the image to show the different regions of the
+ image as described above.
+
+ \beginfloatleft
+ \image qml-borderimage-normal-image.png
+ \endfloat
+
+ An unscaled image is displayed using an Image element. The \l border property is
+ used to determine the parts of the image that will lie inside the unscaled corner
+ areas and the parts that will be stretched horizontally and vertically.
+
+ \snippet doc/src/snippets/declarative/borderimage/normal-image.qml normal image
+
+ \clearfloat
+ \beginfloatleft
+ \image qml-borderimage-scaled.png
+ \endfloat
+
+ A BorderImage element is used to display the image, and it is given a size that is
+ larger than the original image. Since the \l horizontalTileMode property is set to
+ \l{BorderImage::horizontalTileMode}{BorderImage.Stretch}, the parts of image in
+ regions 2 and 8 are stretched horizontally. Since the \l verticalTileMode property
+ is set to \l{BorderImage::verticalTileMode}{BorderImage.Stretch}, the parts of image
+ in regions 4 and 6 are stretched vertically.
+
+ \snippet doc/src/snippets/declarative/borderimage/borderimage-scaled.qml scaled border image
+
+ \clearfloat
+ \beginfloatleft
+ \image qml-borderimage-tiled.png
+ \endfloat
+
+ Again, a large BorderImage element is used to display the image. With the
+ \l horizontalTileMode property set to \l{BorderImage::horizontalTileMode}{BorderImage.Repeat},
+ the parts of image in regions 2 and 8 are tiled so that they fill the space at the
+ top and bottom of the element. Similarly, the \l verticalTileMode property is set to
+ \l{BorderImage::verticalTileMode}{BorderImage.Repeat}, the parts of image in regions
+ 4 and 6 are tiled so that they fill the space at the left and right of the element.
+
+ \snippet doc/src/snippets/declarative/borderimage/borderimage-tiled.qml tiled border image
+
+ \clearfloat
+ In some situations, the width of regions 2 and 8 may not be an exact multiple of the width
+ of the corresponding regions in the source image. Similarly, the height of regions 4 and 6
+ may not be an exact multiple of the height of the corresponding regions. It can be useful
+ to use \l{BorderImage::horizontalTileMode}{BorderImage.Round} instead of
+ \l{BorderImage::horizontalTileMode}{BorderImage.Repeat} in cases like these.
+
+ The \l{declarative/imageelements/borderimage}{BorderImage example} shows how a BorderImage
+ can be used to simulate a shadow effect on a rectangular item.
+
+ \section1 Quality and Performance
+
+ By default, any scaled regions of the image are rendered without smoothing to improve
+ rendering speed. Setting the \l smooth property improves rendering quality of scaled
+ regions, but may slow down rendering.
+
+ The source image may not be loaded instantaneously, depending on its original location.
+ Loading progress can be monitored with the \l progress property.
+
+ \sa Image, AnimatedImage
+ */
+
+/*!
+ \qmlproperty bool BorderImage::asynchronous
+
+ Specifies that images on the local filesystem should be loaded
+ asynchronously in a separate thread. The default value is
+ false, causing the user interface thread to block while the
+ image is loaded. Setting \a asynchronous to true is useful where
+ maintaining a responsive user interface is more desirable
+ than having images immediately visible.
+
+ Note that this property is only valid for images read from the
+ local filesystem. Images loaded via a network resource (e.g. HTTP)
+ are always loaded asynchonously.
+*/
+QDeclarative1BorderImage::QDeclarative1BorderImage(QDeclarativeItem *parent)
+ : QDeclarative1ImageBase(*(new QDeclarative1BorderImagePrivate), parent)
+{
+}
+
+QDeclarative1BorderImage::~QDeclarative1BorderImage()
+{
+ Q_D(QDeclarative1BorderImage);
+ if (d->sciReply)
+ d->sciReply->deleteLater();
+}
+/*!
+ \qmlproperty enumeration BorderImage::status
+
+ This property describes the status of image loading. It can be one of:
+
+ \list
+ \o BorderImage.Null - no image has been set
+ \o BorderImage.Ready - the image has been loaded
+ \o BorderImage.Loading - the image is currently being loaded
+ \o BorderImage.Error - an error occurred while loading the image
+ \endlist
+
+ \sa progress
+*/
+
+/*!
+ \qmlproperty real BorderImage::progress
+
+ This property holds the progress of image loading, from 0.0 (nothing loaded)
+ to 1.0 (finished).
+
+ \sa status
+*/
+
+/*!
+ \qmlproperty bool BorderImage::smooth
+
+ Set this property if you want the image to be smoothly filtered when scaled or
+ transformed. Smooth filtering gives better visual quality, but is slower. If
+ the image is displayed at its natural size, this property has no visual or
+ performance effect.
+
+ By default, this property is set to false.
+
+ \note Generally scaling artifacts are only visible if the image is stationary on
+ the screen. A common pattern when animating an image is to disable smooth
+ filtering at the beginning of the animation and enable it at the conclusion.
+*/
+
+/*!
+ \qmlproperty bool BorderImage::cache
+ \since Quick 1.1
+
+ Specifies whether the image should be cached. The default value is
+ true. Setting \a cache to false is useful when dealing with large images,
+ to make sure that they aren't cached at the expense of small 'ui element' images.
+*/
+
+/*!
+ \qmlproperty bool BorderImage::mirror
+ \since Quick 1.1
+
+ This property holds whether the image should be horizontally inverted
+ (effectively displaying a mirrored image).
+
+ The default value is false.
+*/
+
+/*!
+ \qmlproperty url BorderImage::source
+
+ This property holds the URL that refers to the source image.
+
+ BorderImage can handle any image format supported by Qt, loaded from any
+ URL scheme supported by Qt.
+
+ This property can also be used to refer to .sci files, which are
+ written in a QML-specific, text-based format that specifies the
+ borders, the image file and the tile rules for a given border image.
+
+ The following .sci file sets the borders to 10 on each side for the
+ image \c picture.png:
+
+ \code
+ border.left: 10
+ border.top: 10
+ border.bottom: 10
+ border.right: 10
+ source: "picture.png"
+ \endcode
+
+ The URL may be absolute, or relative to the URL of the component.
+
+ \sa QDeclarativeImageProvider
+*/
+
+/*!
+ \qmlproperty QSize BorderImage::sourceSize
+
+ This property holds the actual width and height of the loaded image.
+
+ In BorderImage, this property is read-only.
+
+ \sa Image::sourceSize
+*/
+void QDeclarative1BorderImage::setSource(const QUrl &url)
+{
+ Q_D(QDeclarative1BorderImage);
+ //equality is fairly expensive, so we bypass for simple, common case
+ if ((d->url.isEmpty() == url.isEmpty()) && url == d->url)
+ return;
+
+ if (d->sciReply) {
+ d->sciReply->deleteLater();
+ d->sciReply = 0;
+ }
+
+ d->url = url;
+ d->sciurl = QUrl();
+ emit sourceChanged(d->url);
+
+ if (isComponentComplete())
+ load();
+}
+
+void QDeclarative1BorderImage::load()
+{
+ Q_D(QDeclarative1BorderImage);
+ if (d->progress != 0.0) {
+ d->progress = 0.0;
+ emit progressChanged(d->progress);
+ }
+
+ if (d->url.isEmpty()) {
+ d->pix.clear(this);
+ d->status = Null;
+ setImplicitWidth(0);
+ setImplicitHeight(0);
+ emit statusChanged(d->status);
+ update();
+ } else {
+ d->status = Loading;
+ if (d->url.path().endsWith(QLatin1String("sci"))) {
+#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
+ QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(d->url);
+ if (!lf.isEmpty()) {
+ QFile file(lf);
+ file.open(QIODevice::ReadOnly);
+ setGridScaledImage(QDeclarative1GridScaledImage(&file));
+ } else
+#endif
+ {
+ QNetworkRequest req(d->url);
+ d->sciReply = qmlEngine(this)->networkAccessManager()->get(req);
+
+ static int sciReplyFinished = -1;
+ static int thisSciRequestFinished = -1;
+ if (sciReplyFinished == -1) {
+ sciReplyFinished =
+ QNetworkReply::staticMetaObject.indexOfSignal("finished()");
+ thisSciRequestFinished =
+ QDeclarative1BorderImage::staticMetaObject.indexOfSlot("sciRequestFinished()");
+ }
+
+ QMetaObject::connect(d->sciReply, sciReplyFinished, this,
+ thisSciRequestFinished, Qt::DirectConnection);
+ }
+ } else {
+
+ QDeclarative1Pixmap::Options options;
+ if (d->async)
+ options |= QDeclarative1Pixmap::Asynchronous;
+ if (d->cache)
+ options |= QDeclarative1Pixmap::Cache;
+ d->pix.clear(this);
+ d->pix.load(qmlEngine(this), d->url, options);
+
+ if (d->pix.isLoading()) {
+ d->pix.connectFinished(this, SLOT(requestFinished()));
+ d->pix.connectDownloadProgress(this, SLOT(requestProgress(qint64,qint64)));
+ } else {
+ QSize impsize = d->pix.implicitSize();
+ setImplicitWidth(impsize.width());
+ setImplicitHeight(impsize.height());
+
+ if (d->pix.isReady()) {
+ d->status = Ready;
+ } else {
+ d->status = Error;
+ qmlInfo(this) << d->pix.error();
+ }
+
+ d->progress = 1.0;
+ emit statusChanged(d->status);
+ emit progressChanged(d->progress);
+ requestFinished();
+ update();
+ }
+ }
+ }
+
+ emit statusChanged(d->status);
+}
+
+/*!
+ \qmlproperty int BorderImage::border.left
+ \qmlproperty int BorderImage::border.right
+ \qmlproperty int BorderImage::border.top
+ \qmlproperty int BorderImage::border.bottom
+
+ The 4 border lines (2 horizontal and 2 vertical) break the image into 9 sections,
+ as shown below:
+
+ \image declarative-scalegrid.png
+
+ Each border line (left, right, top, and bottom) specifies an offset in pixels
+ from the respective edge of the source image. By default, each border line has
+ a value of 0.
+
+ For example, the following definition sets the bottom line 10 pixels up from
+ the bottom of the image:
+
+ \qml
+ BorderImage {
+ border.bottom: 10
+ // ...
+ }
+ \endqml
+
+ The border lines can also be specified using a
+ \l {BorderImage::source}{.sci file}.
+*/
+
+QDeclarative1ScaleGrid *QDeclarative1BorderImage::border()
+{
+ Q_D(QDeclarative1BorderImage);
+ return d->getScaleGrid();
+}
+
+/*!
+ \qmlproperty enumeration BorderImage::horizontalTileMode
+ \qmlproperty enumeration BorderImage::verticalTileMode
+
+ This property describes how to repeat or stretch the middle parts of the border image.
+
+ \list
+ \o BorderImage.Stretch - Scales the image to fit to the available area.
+ \o BorderImage.Repeat - Tile the image until there is no more space. May crop the last image.
+ \o BorderImage.Round - Like Repeat, but scales the images down to ensure that the last image is not cropped.
+ \endlist
+
+ The default tile mode for each property is BorderImage.Stretch.
+*/
+QDeclarative1BorderImage::TileMode QDeclarative1BorderImage::horizontalTileMode() const
+{
+ Q_D(const QDeclarative1BorderImage);
+ return d->horizontalTileMode;
+}
+
+void QDeclarative1BorderImage::setHorizontalTileMode(TileMode t)
+{
+ Q_D(QDeclarative1BorderImage);
+ if (t != d->horizontalTileMode) {
+ d->horizontalTileMode = t;
+ emit horizontalTileModeChanged();
+ update();
+ }
+}
+
+QDeclarative1BorderImage::TileMode QDeclarative1BorderImage::verticalTileMode() const
+{
+ Q_D(const QDeclarative1BorderImage);
+ return d->verticalTileMode;
+}
+
+void QDeclarative1BorderImage::setVerticalTileMode(TileMode t)
+{
+ Q_D(QDeclarative1BorderImage);
+ if (t != d->verticalTileMode) {
+ d->verticalTileMode = t;
+ emit verticalTileModeChanged();
+ update();
+ }
+}
+
+void QDeclarative1BorderImage::setGridScaledImage(const QDeclarative1GridScaledImage& sci)
+{
+ Q_D(QDeclarative1BorderImage);
+ if (!sci.isValid()) {
+ d->status = Error;
+ emit statusChanged(d->status);
+ } else {
+ QDeclarative1ScaleGrid *sg = border();
+ sg->setTop(sci.gridTop());
+ sg->setBottom(sci.gridBottom());
+ sg->setLeft(sci.gridLeft());
+ sg->setRight(sci.gridRight());
+ d->horizontalTileMode = sci.horizontalTileRule();
+ d->verticalTileMode = sci.verticalTileRule();
+
+ d->sciurl = d->url.resolved(QUrl(sci.pixmapUrl()));
+
+ QDeclarative1Pixmap::Options options;
+ if (d->async)
+ options |= QDeclarative1Pixmap::Asynchronous;
+ if (d->cache)
+ options |= QDeclarative1Pixmap::Cache;
+ d->pix.clear(this);
+ d->pix.load(qmlEngine(this), d->sciurl, options);
+
+ if (d->pix.isLoading()) {
+ static int thisRequestProgress = -1;
+ static int thisRequestFinished = -1;
+ if (thisRequestProgress == -1) {
+ thisRequestProgress =
+ QDeclarative1BorderImage::staticMetaObject.indexOfSlot("requestProgress(qint64,qint64)");
+ thisRequestFinished =
+ QDeclarative1BorderImage::staticMetaObject.indexOfSlot("requestFinished()");
+ }
+
+ d->pix.connectFinished(this, thisRequestFinished);
+ d->pix.connectDownloadProgress(this, thisRequestProgress);
+
+ } else {
+
+ QSize impsize = d->pix.implicitSize();
+ setImplicitWidth(impsize.width());
+ setImplicitHeight(impsize.height());
+
+ if (d->pix.isReady()) {
+ d->status = Ready;
+ } else {
+ d->status = Error;
+ qmlInfo(this) << d->pix.error();
+ }
+
+ d->progress = 1.0;
+ emit statusChanged(d->status);
+ emit progressChanged(1.0);
+ update();
+
+ }
+ }
+}
+
+void QDeclarative1BorderImage::requestFinished()
+{
+ Q_D(QDeclarative1BorderImage);
+
+ QSize impsize = d->pix.implicitSize();
+ if (d->pix.isError()) {
+ d->status = Error;
+ qmlInfo(this) << d->pix.error();
+ } else {
+ d->status = Ready;
+ }
+
+ setImplicitWidth(impsize.width());
+ setImplicitHeight(impsize.height());
+
+ if (d->sourcesize.width() != d->pix.width() || d->sourcesize.height() != d->pix.height())
+ emit sourceSizeChanged();
+
+ d->progress = 1.0;
+ emit statusChanged(d->status);
+ emit progressChanged(1.0);
+ update();
+}
+
+#define BORDERIMAGE_MAX_REDIRECT 16
+
+void QDeclarative1BorderImage::sciRequestFinished()
+{
+ Q_D(QDeclarative1BorderImage);
+
+ d->redirectCount++;
+ if (d->redirectCount < BORDERIMAGE_MAX_REDIRECT) {
+ QVariant redirect = d->sciReply->attribute(QNetworkRequest::RedirectionTargetAttribute);
+ if (redirect.isValid()) {
+ QUrl url = d->sciReply->url().resolved(redirect.toUrl());
+ setSource(url);
+ return;
+ }
+ }
+ d->redirectCount=0;
+
+ if (d->sciReply->error() != QNetworkReply::NoError) {
+ d->status = Error;
+ d->sciReply->deleteLater();
+ d->sciReply = 0;
+ emit statusChanged(d->status);
+ } else {
+ QDeclarative1GridScaledImage sci(d->sciReply);
+ d->sciReply->deleteLater();
+ d->sciReply = 0;
+ setGridScaledImage(sci);
+ }
+}
+
+void QDeclarative1BorderImage::doUpdate()
+{
+ update();
+}
+
+void QDeclarative1BorderImage::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *)
+{
+ Q_D(QDeclarative1BorderImage);
+ if (d->pix.isNull() || d->width() <= 0.0 || d->height() <= 0.0)
+ return;
+
+ bool oldAA = p->testRenderHint(QPainter::Antialiasing);
+ bool oldSmooth = p->testRenderHint(QPainter::SmoothPixmapTransform);
+ QTransform oldTransform;
+ if (d->smooth)
+ p->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, d->smooth);
+ if (d->mirror) {
+ oldTransform = p->transform();
+ QTransform mirror;
+ mirror.translate(d->width(), 0).scale(-1, 1.0);
+ p->setWorldTransform(mirror * oldTransform);
+ }
+
+ const QDeclarative1ScaleGrid *border = d->getScaleGrid();
+ int left = border->left();
+ int right = border->right();
+ qreal borderWidth = left + right;
+ if (borderWidth > 0.0 && d->width() < borderWidth) {
+ qreal diff = borderWidth - d->width() - 1;
+ left -= qRound(diff * qreal(left) / borderWidth);
+ right -= qRound(diff * qreal(right) / borderWidth);
+ }
+ int top = border->top();
+ int bottom = border->bottom();
+ qreal borderHeight = top + bottom;
+ if (borderHeight > 0.0 && d->height() < borderHeight) {
+ qreal diff = borderHeight - d->height() - 1;
+ top -= qRound(diff * qreal(top) / borderHeight);
+ bottom -= qRound(diff * qreal(bottom) / borderHeight);
+ }
+ QMargins margins(left, top, right, bottom);
+ QTileRules rules((Qt::TileRule)d->horizontalTileMode, (Qt::TileRule)d->verticalTileMode);
+ qDrawBorderPixmap(p, QRect(0, 0, (int)d->width(), (int)d->height()), margins, d->pix, d->pix.rect(), margins, rules);
+ if (d->smooth) {
+ p->setRenderHint(QPainter::Antialiasing, oldAA);
+ p->setRenderHint(QPainter::SmoothPixmapTransform, oldSmooth);
+ }
+ if (d->mirror)
+ p->setWorldTransform(oldTransform);
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/graphicsitems/qdeclarativeborderimage_p.h b/src/qtquick1/graphicsitems/qdeclarativeborderimage_p.h
new file mode 100644
index 0000000000..f2349b26c6
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativeborderimage_p.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEBORDERIMAGE_H
+#define QDECLARATIVEBORDERIMAGE_H
+
+#include "private/qdeclarativeimagebase_p.h"
+
+#include <QtNetwork/qnetworkreply.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarative1ScaleGrid;
+class QDeclarative1GridScaledImage;
+class QDeclarative1BorderImagePrivate;
+class Q_AUTOTEST_EXPORT QDeclarative1BorderImage : public QDeclarative1ImageBase
+{
+ Q_OBJECT
+ Q_ENUMS(TileMode)
+
+ Q_PROPERTY(QDeclarative1ScaleGrid *border READ border CONSTANT)
+ Q_PROPERTY(TileMode horizontalTileMode READ horizontalTileMode WRITE setHorizontalTileMode NOTIFY horizontalTileModeChanged)
+ Q_PROPERTY(TileMode verticalTileMode READ verticalTileMode WRITE setVerticalTileMode NOTIFY verticalTileModeChanged)
+
+ // read-only for BorderImage
+ Q_PROPERTY(QSize sourceSize READ sourceSize NOTIFY sourceSizeChanged)
+
+public:
+ QDeclarative1BorderImage(QDeclarativeItem *parent=0);
+ ~QDeclarative1BorderImage();
+
+ QDeclarative1ScaleGrid *border();
+
+ enum TileMode { Stretch = Qt::StretchTile, Repeat = Qt::RepeatTile, Round = Qt::RoundTile };
+
+ TileMode horizontalTileMode() const;
+ void setHorizontalTileMode(TileMode);
+
+ TileMode verticalTileMode() const;
+ void setVerticalTileMode(TileMode);
+
+ void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
+ void setSource(const QUrl &url);
+
+Q_SIGNALS:
+ void horizontalTileModeChanged();
+ void verticalTileModeChanged();
+ void sourceSizeChanged();
+
+protected:
+ virtual void load();
+
+private:
+ void setGridScaledImage(const QDeclarative1GridScaledImage& sci);
+
+private Q_SLOTS:
+ void doUpdate();
+ void requestFinished();
+ void sciRequestFinished();
+
+private:
+ Q_DISABLE_COPY(QDeclarative1BorderImage)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarative1BorderImage)
+};
+
+QT_END_NAMESPACE
+QML_DECLARE_TYPE(QDeclarative1BorderImage)
+QT_END_HEADER
+
+#endif // QDECLARATIVEBORDERIMAGE_H
diff --git a/src/qtquick1/graphicsitems/qdeclarativeborderimage_p_p.h b/src/qtquick1/graphicsitems/qdeclarativeborderimage_p_p.h
new file mode 100644
index 0000000000..0d1c30ee2a
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativeborderimage_p_p.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEBORDERIMAGE_P_H
+#define QDECLARATIVEBORDERIMAGE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qdeclarativeimagebase_p_p.h"
+#include "private/qdeclarativescalegrid_p_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkReply;
+
+class QDeclarative1BorderImagePrivate : public QDeclarative1ImageBasePrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1BorderImage)
+
+public:
+ QDeclarative1BorderImagePrivate()
+ : border(0), sciReply(0),
+ horizontalTileMode(QDeclarative1BorderImage::Stretch),
+ verticalTileMode(QDeclarative1BorderImage::Stretch),
+ redirectCount(0)
+ {
+ }
+
+ ~QDeclarative1BorderImagePrivate()
+ {
+ }
+
+
+ QDeclarative1ScaleGrid *getScaleGrid()
+ {
+ Q_Q(QDeclarative1BorderImage);
+ if (!border) {
+ border = new QDeclarative1ScaleGrid(q);
+ static int borderChangedSignalIdx = -1;
+ static int doUpdateSlotIdx = -1;
+ if (borderChangedSignalIdx < 0)
+ borderChangedSignalIdx = QDeclarative1ScaleGrid::staticMetaObject.indexOfSignal("borderChanged()");
+ if (doUpdateSlotIdx < 0)
+ doUpdateSlotIdx = QDeclarative1BorderImage::staticMetaObject.indexOfSlot("doUpdate()");
+ QMetaObject::connect(border, borderChangedSignalIdx, q, doUpdateSlotIdx);
+ }
+ return border;
+ }
+
+ QDeclarative1ScaleGrid *border;
+ QUrl sciurl;
+ QNetworkReply *sciReply;
+ QDeclarative1BorderImage::TileMode horizontalTileMode;
+ QDeclarative1BorderImage::TileMode verticalTileMode;
+ int redirectCount;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDECLARATIVEBORDERIMAGE_P_H
diff --git a/src/qtquick1/graphicsitems/qdeclarativeevents.cpp b/src/qtquick1/graphicsitems/qdeclarativeevents.cpp
new file mode 100644
index 0000000000..227ad6d662
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativeevents.cpp
@@ -0,0 +1,241 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativeevents_p_p.h"
+
+QT_BEGIN_NAMESPACE
+
+
+/*!
+ \qmlclass KeyEvent QDeclarative1KeyEvent
+ \since 4.7
+ \ingroup qml-event-elements
+
+ \brief The KeyEvent object provides information about a key event.
+
+ For example, the following changes the Item's state property when the Enter
+ key is pressed:
+ \qml
+Item {
+ focus: true
+ Keys.onPressed: { if (event.key == Qt.Key_Enter) state = 'ShowDetails'; }
+}
+ \endqml
+*/
+
+/*!
+ \qmlproperty int KeyEvent::key
+
+ This property holds the code of the key that was pressed or released.
+
+ See \l {Qt::Key}{Qt.Key} for the list of keyboard codes. These codes are
+ independent of the underlying window system. Note that this
+ function does not distinguish between capital and non-capital
+ letters, use the text() function (returning the Unicode text the
+ key generated) for this purpose.
+
+ A value of either 0 or \l {Qt::Key_unknown}{Qt.Key_Unknown} means that the event is not
+ the result of a known key; for example, it may be the result of
+ a compose sequence, a keyboard macro, or due to key event
+ compression.
+*/
+
+/*!
+ \qmlproperty string KeyEvent::text
+
+ This property holds the Unicode text that the key generated.
+ The text returned can be an empty string in cases where modifier keys,
+ such as Shift, Control, Alt, and Meta, are being pressed or released.
+ In such cases \c key will contain a valid value
+*/
+
+/*!
+ \qmlproperty bool KeyEvent::isAutoRepeat
+
+ This property holds whether this event comes from an auto-repeating key.
+*/
+
+/*!
+ \qmlproperty int KeyEvent::count
+
+ This property holds the number of keys involved in this event. If \l KeyEvent::text
+ is not empty, this is simply the length of the string.
+*/
+
+/*!
+ \qmlproperty bool KeyEvent::accepted
+
+ Setting \a accepted to true prevents the key event from being
+ propagated to the item's parent.
+
+ Generally, if the item acts on the key event then it should be accepted
+ so that ancestor items do not also respond to the same event.
+*/
+
+/*!
+ \qmlproperty int KeyEvent::modifiers
+
+ This property holds the keyboard modifier flags that existed immediately
+ before the event occurred.
+
+ It contains a bitwise combination of:
+ \list
+ \o Qt.NoModifier - No modifier key is pressed.
+ \o Qt.ShiftModifier - A Shift key on the keyboard is pressed.
+ \o Qt.ControlModifier - A Ctrl key on the keyboard is pressed.
+ \o Qt.AltModifier - An Alt key on the keyboard is pressed.
+ \o Qt.MetaModifier - A Meta key on the keyboard is pressed.
+ \o Qt.KeypadModifier - A keypad button is pressed.
+ \endlist
+
+ For example, to react to a Shift key + Enter key combination:
+ \qml
+ Item {
+ focus: true
+ Keys.onPressed: {
+ if ((event.key == Qt.Key_Enter) && (event.modifiers & Qt.ShiftModifier))
+ doSomething();
+ }
+ }
+ \endqml
+*/
+
+
+/*!
+ \qmlclass MouseEvent QDeclarative1MouseEvent
+ \since 4.7
+ \ingroup qml-event-elements
+
+ \brief The MouseEvent object provides information about a mouse event.
+
+ The position of the mouse can be found via the \l x and \l y properties.
+ The button that caused the event is available via the \l button property.
+
+ \sa MouseArea
+*/
+
+/*!
+ \internal
+ \class QDeclarative1MouseEvent
+*/
+
+/*!
+ \qmlproperty int MouseEvent::x
+ \qmlproperty int MouseEvent::y
+
+ These properties hold the coordinates of the position supplied by the mouse event.
+*/
+
+
+/*!
+ \qmlproperty bool MouseEvent::accepted
+
+ Setting \a accepted to true prevents the mouse event from being
+ propagated to items below this item.
+
+ Generally, if the item acts on the mouse event then it should be accepted
+ so that items lower in the stacking order do not also respond to the same event.
+*/
+
+/*!
+ \qmlproperty enumeration MouseEvent::button
+
+ This property holds the button that caused the event. It can be one of:
+ \list
+ \o Qt.LeftButton
+ \o Qt.RightButton
+ \o Qt.MiddleButton
+ \endlist
+*/
+
+/*!
+ \qmlproperty bool MouseEvent::wasHeld
+
+ This property is true if the mouse button has been held pressed longer the
+ threshold (800ms).
+*/
+
+/*!
+ \qmlproperty int MouseEvent::buttons
+
+ This property holds the mouse buttons pressed when the event was generated.
+ For mouse move events, this is all buttons that are pressed down. For mouse
+ press and double click events this includes the button that caused the event.
+ For mouse release events this excludes the button that caused the event.
+
+ It contains a bitwise combination of:
+ \list
+ \o Qt.LeftButton
+ \o Qt.RightButton
+ \o Qt.MiddleButton
+ \endlist
+*/
+
+/*!
+ \qmlproperty int MouseEvent::modifiers
+
+ This property holds the keyboard modifier flags that existed immediately
+ before the event occurred.
+
+ It contains a bitwise combination of:
+ \list
+ \o Qt.NoModifier - No modifier key is pressed.
+ \o Qt.ShiftModifier - A Shift key on the keyboard is pressed.
+ \o Qt.ControlModifier - A Ctrl key on the keyboard is pressed.
+ \o Qt.AltModifier - An Alt key on the keyboard is pressed.
+ \o Qt.MetaModifier - A Meta key on the keyboard is pressed.
+ \o Qt.KeypadModifier - A keypad button is pressed.
+ \endlist
+
+ For example, to react to a Shift key + Left mouse button click:
+ \qml
+ MouseArea {
+ onClicked: {
+ if ((mouse.button == Qt.LeftButton) && (mouse.modifiers & Qt.ShiftModifier))
+ doSomething();
+ }
+ }
+ \endqml
+*/
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/graphicsitems/qdeclarativeevents_p_p.h b/src/qtquick1/graphicsitems/qdeclarativeevents_p_p.h
new file mode 100644
index 0000000000..bda4814a52
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativeevents_p_p.h
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEEVENTS_P_H
+#define QDECLARATIVEEVENTS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtDeclarative/qdeclarative.h>
+
+#include <QtCore/qobject.h>
+#include <QtGui/qevent.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarative1KeyEvent : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int key READ key)
+ Q_PROPERTY(QString text READ text)
+ Q_PROPERTY(int modifiers READ modifiers)
+ Q_PROPERTY(bool isAutoRepeat READ isAutoRepeat)
+ Q_PROPERTY(int count READ count)
+ Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
+
+public:
+ QDeclarative1KeyEvent(QEvent::Type type, int key, Qt::KeyboardModifiers modifiers, const QString &text=QString(), bool autorep=false, ushort count=1)
+ : event(type, key, modifiers, text, autorep, count) { event.setAccepted(false); }
+ QDeclarative1KeyEvent(const QKeyEvent &ke)
+ : event(ke) { event.setAccepted(false); }
+
+ int key() const { return event.key(); }
+ QString text() const { return event.text(); }
+ int modifiers() const { return event.modifiers(); }
+ bool isAutoRepeat() const { return event.isAutoRepeat(); }
+ int count() const { return event.count(); }
+
+ bool isAccepted() { return event.isAccepted(); }
+ void setAccepted(bool accepted) { event.setAccepted(accepted); }
+
+private:
+ QKeyEvent event;
+};
+
+class QDeclarative1MouseEvent : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int x READ x)
+ Q_PROPERTY(int y READ y)
+ Q_PROPERTY(int button READ button)
+ Q_PROPERTY(int buttons READ buttons)
+ Q_PROPERTY(int modifiers READ modifiers)
+ Q_PROPERTY(bool wasHeld READ wasHeld)
+ Q_PROPERTY(bool isClick READ isClick)
+ Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
+
+public:
+ QDeclarative1MouseEvent(int x, int y, Qt::MouseButton button, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers
+ , bool isClick=false, bool wasHeld=false)
+ : _x(x), _y(y), _button(button), _buttons(buttons), _modifiers(modifiers)
+ , _wasHeld(wasHeld), _isClick(isClick), _accepted(true) {}
+
+ int x() const { return _x; }
+ int y() const { return _y; }
+ int button() const { return _button; }
+ int buttons() const { return _buttons; }
+ int modifiers() const { return _modifiers; }
+ bool wasHeld() const { return _wasHeld; }
+ bool isClick() const { return _isClick; }
+
+ // only for internal usage
+ void setX(int x) { _x = x; }
+ void setY(int y) { _y = y; }
+
+ bool isAccepted() { return _accepted; }
+ void setAccepted(bool accepted) { _accepted = accepted; }
+
+private:
+ int _x;
+ int _y;
+ Qt::MouseButton _button;
+ Qt::MouseButtons _buttons;
+ Qt::KeyboardModifiers _modifiers;
+ bool _wasHeld;
+ bool _isClick;
+ bool _accepted;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1KeyEvent)
+QML_DECLARE_TYPE(QDeclarative1MouseEvent)
+
+#endif // QDECLARATIVEEVENTS_P_H
diff --git a/src/qtquick1/graphicsitems/qdeclarativeflickable.cpp b/src/qtquick1/graphicsitems/qdeclarativeflickable.cpp
new file mode 100644
index 0000000000..37a784f480
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativeflickable.cpp
@@ -0,0 +1,1803 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativeflickable_p.h"
+#include "QtQuick1/private/qdeclarativeflickable_p_p.h"
+#include <QtDeclarative/qdeclarativeinfo.h>
+#include <QGraphicsSceneMouseEvent>
+#include <QPointer>
+#include <QTimer>
+#include "qplatformdefs.h"
+
+QT_BEGIN_NAMESPACE
+
+
+
+// The maximum number of pixels a flick can overshoot
+#ifndef QML_FLICK_OVERSHOOT
+#define QML_FLICK_OVERSHOOT 200
+#endif
+
+// The number of samples to use in calculating the velocity of a flick
+#ifndef QML_FLICK_SAMPLEBUFFER
+#define QML_FLICK_SAMPLEBUFFER 3
+#endif
+
+// The number of samples to discard when calculating the flick velocity.
+// Touch panels often produce inaccurate results as the finger is lifted.
+#ifndef QML_FLICK_DISCARDSAMPLES
+#define QML_FLICK_DISCARDSAMPLES 1
+#endif
+
+// The default maximum velocity of a flick.
+#ifndef QML_FLICK_DEFAULTMAXVELOCITY
+#define QML_FLICK_DEFAULTMAXVELOCITY 2500
+#endif
+
+// The default deceleration of a flick.
+#ifndef QML_FLICK_DEFAULTDECELERATION
+#define QML_FLICK_DEFAULTDECELERATION 1750
+#endif
+
+// How much faster to decelerate when overshooting
+#ifndef QML_FLICK_OVERSHOOTFRICTION
+#define QML_FLICK_OVERSHOOTFRICTION 8
+#endif
+
+// FlickThreshold determines how far the "mouse" must have moved
+// before we perform a flick.
+static const int FlickThreshold = 20;
+
+// RetainGrabVelocity is the maxmimum instantaneous velocity that
+// will ensure the Flickable retains the grab on consecutive flicks.
+static const int RetainGrabVelocity = 15;
+
+QDeclarative1FlickableVisibleArea::QDeclarative1FlickableVisibleArea(QDeclarative1Flickable *parent)
+ : QObject(parent), flickable(parent), m_xPosition(0.), m_widthRatio(0.)
+ , m_yPosition(0.), m_heightRatio(0.)
+{
+}
+
+qreal QDeclarative1FlickableVisibleArea::widthRatio() const
+{
+ return m_widthRatio;
+}
+
+qreal QDeclarative1FlickableVisibleArea::xPosition() const
+{
+ return m_xPosition;
+}
+
+qreal QDeclarative1FlickableVisibleArea::heightRatio() const
+{
+ return m_heightRatio;
+}
+
+qreal QDeclarative1FlickableVisibleArea::yPosition() const
+{
+ return m_yPosition;
+}
+
+void QDeclarative1FlickableVisibleArea::updateVisible()
+{
+ QDeclarative1FlickablePrivate *p = static_cast<QDeclarative1FlickablePrivate *>(QGraphicsItemPrivate::get(flickable));
+
+ bool changeX = false;
+ bool changeY = false;
+ bool changeWidth = false;
+ bool changeHeight = false;
+
+ // Vertical
+ const qreal viewheight = flickable->height();
+ const qreal maxyextent = -flickable->maxYExtent() + flickable->minYExtent();
+ qreal pagePos = (-p->vData.move.value() + flickable->minYExtent()) / (maxyextent + viewheight);
+ qreal pageSize = viewheight / (maxyextent + viewheight);
+
+ if (pageSize != m_heightRatio) {
+ m_heightRatio = pageSize;
+ changeHeight = true;
+ }
+ if (pagePos != m_yPosition) {
+ m_yPosition = pagePos;
+ changeY = true;
+ }
+
+ // Horizontal
+ const qreal viewwidth = flickable->width();
+ const qreal maxxextent = -flickable->maxXExtent() + flickable->minXExtent();
+ pagePos = (-p->hData.move.value() + flickable->minXExtent()) / (maxxextent + viewwidth);
+ pageSize = viewwidth / (maxxextent + viewwidth);
+
+ if (pageSize != m_widthRatio) {
+ m_widthRatio = pageSize;
+ changeWidth = true;
+ }
+ if (pagePos != m_xPosition) {
+ m_xPosition = pagePos;
+ changeX = true;
+ }
+
+ if (changeX)
+ emit xPositionChanged(m_xPosition);
+ if (changeY)
+ emit yPositionChanged(m_yPosition);
+ if (changeWidth)
+ emit widthRatioChanged(m_widthRatio);
+ if (changeHeight)
+ emit heightRatioChanged(m_heightRatio);
+}
+
+
+QDeclarative1FlickablePrivate::QDeclarative1FlickablePrivate()
+ : contentItem(new QDeclarativeItem)
+ , hData(this, &QDeclarative1FlickablePrivate::setRoundedViewportX)
+ , vData(this, &QDeclarative1FlickablePrivate::setRoundedViewportY)
+ , flickingHorizontally(false), flickingVertically(false)
+ , hMoved(false), vMoved(false)
+ , movingHorizontally(false), movingVertically(false)
+ , stealMouse(false), pressed(false), interactive(true), calcVelocity(false)
+ , deceleration(QML_FLICK_DEFAULTDECELERATION)
+ , maxVelocity(QML_FLICK_DEFAULTMAXVELOCITY), reportedVelocitySmoothing(100)
+ , delayedPressEvent(0), delayedPressTarget(0), pressDelay(0), fixupDuration(400)
+ , fixupMode(Normal), vTime(0), visibleArea(0)
+ , flickableDirection(QDeclarative1Flickable::AutoFlickDirection)
+ , boundsBehavior(QDeclarative1Flickable::DragAndOvershootBounds)
+{
+}
+
+void QDeclarative1FlickablePrivate::init()
+{
+ Q_Q(QDeclarative1Flickable);
+ QDeclarative_setParent_noEvent(contentItem, q);
+ contentItem->setParentItem(q);
+ static int timelineUpdatedIdx = -1;
+ static int timelineCompletedIdx = -1;
+ static int flickableTickedIdx = -1;
+ static int flickableMovementEndingIdx = -1;
+ if (timelineUpdatedIdx == -1) {
+ timelineUpdatedIdx = QDeclarative1TimeLine::staticMetaObject.indexOfSignal("updated()");
+ timelineCompletedIdx = QDeclarative1TimeLine::staticMetaObject.indexOfSignal("completed()");
+ flickableTickedIdx = QDeclarative1Flickable::staticMetaObject.indexOfSlot("ticked()");
+ flickableMovementEndingIdx = QDeclarative1Flickable::staticMetaObject.indexOfSlot("movementEnding()");
+ }
+ QMetaObject::connect(&timeline, timelineUpdatedIdx,
+ q, flickableTickedIdx, Qt::DirectConnection);
+ QMetaObject::connect(&timeline, timelineCompletedIdx,
+ q, flickableMovementEndingIdx, Qt::DirectConnection);
+ q->setAcceptedMouseButtons(Qt::LeftButton);
+ q->setFiltersChildEvents(true);
+ QDeclarativeItemPrivate *viewportPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(contentItem));
+ viewportPrivate->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
+ lastPosTime.invalidate();
+}
+
+/*
+ Returns the amount to overshoot by given a view size.
+ Will be up to the lesser of 1/3 of the view size or QML_FLICK_OVERSHOOT
+*/
+qreal QDeclarative1FlickablePrivate::overShootDistance(qreal size)
+{
+ if (maxVelocity <= 0)
+ return 0.0;
+
+ return qMin(qreal(QML_FLICK_OVERSHOOT), size/3);
+}
+
+void QDeclarative1FlickablePrivate::AxisData::addVelocitySample(qreal v, qreal maxVelocity)
+{
+ if (v > maxVelocity)
+ v = maxVelocity;
+ else if (v < -maxVelocity)
+ v = -maxVelocity;
+ velocityBuffer.append(v);
+ if (velocityBuffer.count() > QML_FLICK_SAMPLEBUFFER)
+ velocityBuffer.remove(0);
+}
+
+void QDeclarative1FlickablePrivate::AxisData::updateVelocity()
+{
+ if (velocityBuffer.count() > QML_FLICK_DISCARDSAMPLES) {
+ velocity = 0;
+ int count = velocityBuffer.count()-QML_FLICK_DISCARDSAMPLES;
+ for (int i = 0; i < count; ++i) {
+ qreal v = velocityBuffer.at(i);
+ velocity += v;
+ }
+ velocity /= count;
+ }
+}
+
+void QDeclarative1FlickablePrivate::itemGeometryChanged(QDeclarativeItem *item, const QRectF &newGeom, const QRectF &oldGeom)
+{
+ Q_Q(QDeclarative1Flickable);
+ if (item == contentItem) {
+ if (newGeom.x() != oldGeom.x())
+ emit q->contentXChanged();
+ if (newGeom.y() != oldGeom.y())
+ emit q->contentYChanged();
+ }
+}
+
+void QDeclarative1FlickablePrivate::flickX(qreal velocity)
+{
+ Q_Q(QDeclarative1Flickable);
+ flick(hData, q->minXExtent(), q->maxXExtent(), q->width(), fixupX_callback, velocity);
+}
+
+void QDeclarative1FlickablePrivate::flickY(qreal velocity)
+{
+ Q_Q(QDeclarative1Flickable);
+ flick(vData, q->minYExtent(), q->maxYExtent(), q->height(), fixupY_callback, velocity);
+}
+
+void QDeclarative1FlickablePrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal,
+ QDeclarative1TimeLineCallback::Callback fixupCallback, qreal velocity)
+{
+ Q_Q(QDeclarative1Flickable);
+ qreal maxDistance = -1;
+ data.fixingUp = false;
+ // -ve velocity means list is moving up
+ if (velocity > 0) {
+ maxDistance = qAbs(minExtent - data.move.value());
+ data.flickTarget = minExtent;
+ } else {
+ maxDistance = qAbs(maxExtent - data.move.value());
+ data.flickTarget = maxExtent;
+ }
+ if (maxDistance > 0) {
+ qreal v = velocity;
+ if (maxVelocity != -1 && maxVelocity < qAbs(v)) {
+ if (v < 0)
+ v = -maxVelocity;
+ else
+ v = maxVelocity;
+ }
+ timeline.reset(data.move);
+ if (boundsBehavior == QDeclarative1Flickable::DragAndOvershootBounds)
+ timeline.accel(data.move, v, deceleration);
+ else
+ timeline.accel(data.move, v, deceleration, maxDistance);
+ timeline.callback(QDeclarative1TimeLineCallback(&data.move, fixupCallback, this));
+ if (!flickingHorizontally && q->xflick()) {
+ flickingHorizontally = true;
+ emit q->flickingChanged();
+ emit q->flickingHorizontallyChanged();
+ if (!flickingVertically)
+ emit q->flickStarted();
+ }
+ if (!flickingVertically && q->yflick()) {
+ flickingVertically = true;
+ emit q->flickingChanged();
+ emit q->flickingVerticallyChanged();
+ if (!flickingHorizontally)
+ emit q->flickStarted();
+ }
+ } else {
+ timeline.reset(data.move);
+ fixup(data, minExtent, maxExtent);
+ }
+}
+
+void QDeclarative1FlickablePrivate::fixupY_callback(void *data)
+{
+ ((QDeclarative1FlickablePrivate *)data)->fixupY();
+}
+
+void QDeclarative1FlickablePrivate::fixupX_callback(void *data)
+{
+ ((QDeclarative1FlickablePrivate *)data)->fixupX();
+}
+
+void QDeclarative1FlickablePrivate::fixupX()
+{
+ Q_Q(QDeclarative1Flickable);
+ fixup(hData, q->minXExtent(), q->maxXExtent());
+}
+
+void QDeclarative1FlickablePrivate::fixupY()
+{
+ Q_Q(QDeclarative1Flickable);
+ fixup(vData, q->minYExtent(), q->maxYExtent());
+}
+
+void QDeclarative1FlickablePrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
+{
+ if (data.move.value() > minExtent || maxExtent > minExtent) {
+ timeline.reset(data.move);
+ if (data.move.value() != minExtent) {
+ switch (fixupMode) {
+ case Immediate:
+ timeline.set(data.move, minExtent);
+ break;
+ case ExtentChanged:
+ // The target has changed. Don't start from the beginning; just complete the
+ // second half of the animation using the new extent.
+ timeline.move(data.move, minExtent, QEasingCurve(QEasingCurve::OutExpo), 3*fixupDuration/4);
+ data.fixingUp = true;
+ break;
+ default: {
+ qreal dist = minExtent - data.move;
+ timeline.move(data.move, minExtent - dist/2, QEasingCurve(QEasingCurve::InQuad), fixupDuration/4);
+ timeline.move(data.move, minExtent, QEasingCurve(QEasingCurve::OutExpo), 3*fixupDuration/4);
+ data.fixingUp = true;
+ }
+ }
+ }
+ } else if (data.move.value() < maxExtent) {
+ timeline.reset(data.move);
+ switch (fixupMode) {
+ case Immediate:
+ timeline.set(data.move, maxExtent);
+ break;
+ case ExtentChanged:
+ // The target has changed. Don't start from the beginning; just complete the
+ // second half of the animation using the new extent.
+ timeline.move(data.move, maxExtent, QEasingCurve(QEasingCurve::OutExpo), 3*fixupDuration/4);
+ data.fixingUp = true;
+ break;
+ default: {
+ qreal dist = maxExtent - data.move;
+ timeline.move(data.move, maxExtent - dist/2, QEasingCurve(QEasingCurve::InQuad), fixupDuration/4);
+ timeline.move(data.move, maxExtent, QEasingCurve(QEasingCurve::OutExpo), 3*fixupDuration/4);
+ data.fixingUp = true;
+ }
+ }
+ }
+ data.inOvershoot = false;
+ fixupMode = Normal;
+ vTime = timeline.time();
+}
+
+void QDeclarative1FlickablePrivate::updateBeginningEnd()
+{
+ Q_Q(QDeclarative1Flickable);
+ bool atBoundaryChange = false;
+
+ // Vertical
+ const int maxyextent = int(-q->maxYExtent());
+ const qreal ypos = -vData.move.value();
+ bool atBeginning = (ypos <= -q->minYExtent());
+ bool atEnd = (maxyextent <= ypos);
+
+ if (atBeginning != vData.atBeginning) {
+ vData.atBeginning = atBeginning;
+ atBoundaryChange = true;
+ }
+ if (atEnd != vData.atEnd) {
+ vData.atEnd = atEnd;
+ atBoundaryChange = true;
+ }
+
+ // Horizontal
+ const int maxxextent = int(-q->maxXExtent());
+ const qreal xpos = -hData.move.value();
+ atBeginning = (xpos <= -q->minXExtent());
+ atEnd = (maxxextent <= xpos);
+
+ if (atBeginning != hData.atBeginning) {
+ hData.atBeginning = atBeginning;
+ atBoundaryChange = true;
+ }
+ if (atEnd != hData.atEnd) {
+ hData.atEnd = atEnd;
+ atBoundaryChange = true;
+ }
+
+ if (atBoundaryChange)
+ emit q->isAtBoundaryChanged();
+
+ if (visibleArea)
+ visibleArea->updateVisible();
+}
+
+/*!
+ \qmlclass Flickable QDeclarative1Flickable
+ \since 4.7
+ \ingroup qml-basic-interaction-elements
+
+ \brief The Flickable item provides a surface that can be "flicked".
+ \inherits Item
+
+ The Flickable item places its children on a surface that can be dragged
+ and flicked, causing the view onto the child items to scroll. This
+ behavior forms the basis of Items that are designed to show large numbers
+ of child items, such as \l ListView and \l GridView.
+
+ In traditional user interfaces, views can be scrolled using standard
+ controls, such as scroll bars and arrow buttons. In some situations, it
+ is also possible to drag the view directly by pressing and holding a
+ mouse button while moving the cursor. In touch-based user interfaces,
+ this dragging action is often complemented with a flicking action, where
+ scrolling continues after the user has stopped touching the view.
+
+ Flickable does not automatically clip its contents. If it is not used as
+ a full-screen item, you should consider setting the \l{Item::}{clip} property
+ to true.
+
+ \section1 Example Usage
+
+ \div {class="float-right"}
+ \inlineimage flickable.gif
+ \enddiv
+
+ The following example shows a small view onto a large image in which the
+ user can drag or flick the image in order to view different parts of it.
+
+ \snippet doc/src/snippets/declarative/flickable.qml document
+
+ \clearfloat
+
+ Items declared as children of a Flickable are automatically parented to the
+ Flickable's \l contentItem. This should be taken into account when
+ operating on the children of the Flickable; it is usually the children of
+ \c contentItem that are relevant. For example, the bound of Items added
+ to the Flickable will be available by \c contentItem.childrenRect
+
+ \section1 Limitations
+
+ \note Due to an implementation detail, items placed inside a Flickable cannot anchor to it by
+ \c id. Use \c parent instead.
+*/
+
+/*!
+ \qmlsignal Flickable::onMovementStarted()
+
+ This handler is called when the view begins moving due to user
+ interaction.
+*/
+
+/*!
+ \qmlsignal Flickable::onMovementEnded()
+
+ This handler is called when the view stops moving due to user
+ interaction. If a flick was generated, this handler will
+ be triggered once the flick stops. If a flick was not
+ generated, the handler will be triggered when the
+ user stops dragging - i.e. a mouse or touch release.
+*/
+
+/*!
+ \qmlsignal Flickable::onFlickStarted()
+
+ This handler is called when the view is flicked. A flick
+ starts from the point that the mouse or touch is released,
+ while still in motion.
+*/
+
+/*!
+ \qmlsignal Flickable::onFlickEnded()
+
+ This handler is called when the view stops moving due to a flick.
+*/
+
+/*!
+ \qmlproperty real Flickable::visibleArea.xPosition
+ \qmlproperty real Flickable::visibleArea.widthRatio
+ \qmlproperty real Flickable::visibleArea.yPosition
+ \qmlproperty real Flickable::visibleArea.heightRatio
+
+ These properties describe the position and size of the currently viewed area.
+ The size is defined as the percentage of the full view currently visible,
+ scaled to 0.0 - 1.0. The page position is usually in the range 0.0 (beginning) to
+ 1.0 minus size ratio (end), i.e. \c yPosition is in the range 0.0 to 1.0-\c heightRatio.
+ However, it is possible for the contents to be dragged outside of the normal
+ range, resulting in the page positions also being outside the normal range.
+
+ These properties are typically used to draw a scrollbar. For example:
+
+ \snippet doc/src/snippets/declarative/flickableScrollbar.qml 0
+ \dots 8
+ \snippet doc/src/snippets/declarative/flickableScrollbar.qml 1
+
+ \sa {declarative/ui-components/scrollbar}{scrollbar example}
+*/
+
+QDeclarative1Flickable::QDeclarative1Flickable(QDeclarativeItem *parent)
+ : QDeclarativeItem(*(new QDeclarative1FlickablePrivate), parent)
+{
+ Q_D(QDeclarative1Flickable);
+ d->init();
+}
+
+QDeclarative1Flickable::QDeclarative1Flickable(QDeclarative1FlickablePrivate &dd, QDeclarativeItem *parent)
+ : QDeclarativeItem(dd, parent)
+{
+ Q_D(QDeclarative1Flickable);
+ d->init();
+}
+
+QDeclarative1Flickable::~QDeclarative1Flickable()
+{
+}
+
+/*!
+ \qmlproperty real Flickable::contentX
+ \qmlproperty real Flickable::contentY
+
+ These properties hold the surface coordinate currently at the top-left
+ corner of the Flickable. For example, if you flick an image up 100 pixels,
+ \c contentY will be 100.
+*/
+qreal QDeclarative1Flickable::contentX() const
+{
+ Q_D(const QDeclarative1Flickable);
+ return -d->contentItem->x();
+}
+
+void QDeclarative1Flickable::setContentX(qreal pos)
+{
+ Q_D(QDeclarative1Flickable);
+ d->timeline.reset(d->hData.move);
+ d->vTime = d->timeline.time();
+ movementXEnding();
+ if (-pos != d->hData.move.value()) {
+ d->hData.move.setValue(-pos);
+ viewportMoved();
+ }
+}
+
+qreal QDeclarative1Flickable::contentY() const
+{
+ Q_D(const QDeclarative1Flickable);
+ return -d->contentItem->y();
+}
+
+void QDeclarative1Flickable::setContentY(qreal pos)
+{
+ Q_D(QDeclarative1Flickable);
+ d->timeline.reset(d->vData.move);
+ d->vTime = d->timeline.time();
+ movementYEnding();
+ if (-pos != d->vData.move.value()) {
+ d->vData.move.setValue(-pos);
+ viewportMoved();
+ }
+}
+
+/*!
+ \qmlproperty bool Flickable::interactive
+
+ This property describes whether the user can interact with the Flickable.
+ A user cannot drag or flick a Flickable that is not interactive.
+
+ By default, this property is true.
+
+ This property is useful for temporarily disabling flicking. This allows
+ special interaction with Flickable's children; for example, you might want
+ to freeze a flickable map while scrolling through a pop-up dialog that
+ is a child of the Flickable.
+*/
+bool QDeclarative1Flickable::isInteractive() const
+{
+ Q_D(const QDeclarative1Flickable);
+ return d->interactive;
+}
+
+void QDeclarative1Flickable::setInteractive(bool interactive)
+{
+ Q_D(QDeclarative1Flickable);
+ if (interactive != d->interactive) {
+ d->interactive = interactive;
+ if (!interactive && (d->flickingHorizontally || d->flickingVertically)) {
+ d->timeline.clear();
+ d->vTime = d->timeline.time();
+ d->flickingHorizontally = false;
+ d->flickingVertically = false;
+ emit flickingChanged();
+ emit flickingHorizontallyChanged();
+ emit flickingVerticallyChanged();
+ emit flickEnded();
+ }
+ emit interactiveChanged();
+ }
+}
+
+/*!
+ \qmlproperty real Flickable::horizontalVelocity
+ \qmlproperty real Flickable::verticalVelocity
+
+ The instantaneous velocity of movement along the x and y axes, in pixels/sec.
+
+ The reported velocity is smoothed to avoid erratic output.
+*/
+qreal QDeclarative1Flickable::horizontalVelocity() const
+{
+ Q_D(const QDeclarative1Flickable);
+ return d->hData.smoothVelocity.value();
+}
+
+qreal QDeclarative1Flickable::verticalVelocity() const
+{
+ Q_D(const QDeclarative1Flickable);
+ return d->vData.smoothVelocity.value();
+}
+
+/*!
+ \qmlproperty bool Flickable::atXBeginning
+ \qmlproperty bool Flickable::atXEnd
+ \qmlproperty bool Flickable::atYBeginning
+ \qmlproperty bool Flickable::atYEnd
+
+ These properties are true if the flickable view is positioned at the beginning,
+ or end respecively.
+*/
+bool QDeclarative1Flickable::isAtXEnd() const
+{
+ Q_D(const QDeclarative1Flickable);
+ return d->hData.atEnd;
+}
+
+bool QDeclarative1Flickable::isAtXBeginning() const
+{
+ Q_D(const QDeclarative1Flickable);
+ return d->hData.atBeginning;
+}
+
+bool QDeclarative1Flickable::isAtYEnd() const
+{
+ Q_D(const QDeclarative1Flickable);
+ return d->vData.atEnd;
+}
+
+bool QDeclarative1Flickable::isAtYBeginning() const
+{
+ Q_D(const QDeclarative1Flickable);
+ return d->vData.atBeginning;
+}
+
+void QDeclarative1Flickable::ticked()
+{
+ viewportMoved();
+}
+
+/*!
+ \qmlproperty Item Flickable::contentItem
+
+ The internal item that contains the Items to be moved in the Flickable.
+
+ Items declared as children of a Flickable are automatically parented to the Flickable's contentItem.
+
+ Items created dynamically need to be explicitly parented to the \e contentItem:
+ \code
+ Flickable {
+ id: myFlickable
+ function addItem(file) {
+ var component = Qt.createComponent(file)
+ component.createObject(myFlickable.contentItem);
+ }
+ }
+ \endcode
+*/
+QDeclarativeItem *QDeclarative1Flickable::contentItem()
+{
+ Q_D(QDeclarative1Flickable);
+ return d->contentItem;
+}
+
+QDeclarative1FlickableVisibleArea *QDeclarative1Flickable::visibleArea()
+{
+ Q_D(QDeclarative1Flickable);
+ if (!d->visibleArea)
+ d->visibleArea = new QDeclarative1FlickableVisibleArea(this);
+ return d->visibleArea;
+}
+
+/*!
+ \qmlproperty enumeration Flickable::flickableDirection
+
+ This property determines which directions the view can be flicked.
+
+ \list
+ \o Flickable.AutoFlickDirection (default) - allows flicking vertically if the
+ \e contentHeight is not equal to the \e height of the Flickable.
+ Allows flicking horizontally if the \e contentWidth is not equal
+ to the \e width of the Flickable.
+ \o Flickable.HorizontalFlick - allows flicking horizontally.
+ \o Flickable.VerticalFlick - allows flicking vertically.
+ \o Flickable.HorizontalAndVerticalFlick - allows flicking in both directions.
+ \endlist
+*/
+QDeclarative1Flickable::FlickableDirection QDeclarative1Flickable::flickableDirection() const
+{
+ Q_D(const QDeclarative1Flickable);
+ return d->flickableDirection;
+}
+
+void QDeclarative1Flickable::setFlickableDirection(FlickableDirection direction)
+{
+ Q_D(QDeclarative1Flickable);
+ if (direction != d->flickableDirection) {
+ d->flickableDirection = direction;
+ emit flickableDirectionChanged();
+ }
+}
+
+void QDeclarative1FlickablePrivate::handleMousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_Q(QDeclarative1Flickable);
+ if (interactive && timeline.isActive()
+ && (qAbs(hData.smoothVelocity.value()) > RetainGrabVelocity || qAbs(vData.smoothVelocity.value()) > RetainGrabVelocity))
+ stealMouse = true; // If we've been flicked then steal the click.
+ else
+ stealMouse = false;
+ q->setKeepMouseGrab(stealMouse);
+ pressed = true;
+ timeline.clear();
+ hData.reset();
+ vData.reset();
+ hData.dragMinBound = q->minXExtent();
+ vData.dragMinBound = q->minYExtent();
+ hData.dragMaxBound = q->maxXExtent();
+ vData.dragMaxBound = q->maxYExtent();
+ fixupMode = Normal;
+ lastPos = QPoint();
+ QDeclarativeItemPrivate::start(lastPosTime);
+ pressPos = event->pos();
+ hData.pressPos = hData.move.value();
+ vData.pressPos = vData.move.value();
+ flickingHorizontally = false;
+ flickingVertically = false;
+ QDeclarativeItemPrivate::start(pressTime);
+ QDeclarativeItemPrivate::start(velocityTime);
+}
+
+void QDeclarative1FlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_Q(QDeclarative1Flickable);
+ if (!interactive || !lastPosTime.isValid())
+ return;
+ bool rejectY = false;
+ bool rejectX = false;
+
+ bool stealY = stealMouse;
+ bool stealX = stealMouse;
+
+ if (q->yflick()) {
+ int dy = int(event->pos().y() - pressPos.y());
+ if (qAbs(dy) > QApplication::startDragDistance() || QDeclarativeItemPrivate::elapsed(pressTime) > 200) {
+ if (!vMoved)
+ vData.dragStartOffset = dy;
+ qreal newY = dy + vData.pressPos - vData.dragStartOffset;
+ const qreal minY = vData.dragMinBound;
+ const qreal maxY = vData.dragMaxBound;
+ if (newY > minY)
+ newY = minY + (newY - minY) / 2;
+ if (newY < maxY && maxY - minY <= 0)
+ newY = maxY + (newY - maxY) / 2;
+ if (boundsBehavior == QDeclarative1Flickable::StopAtBounds && (newY > minY || newY < maxY)) {
+ rejectY = true;
+ if (newY < maxY) {
+ newY = maxY;
+ rejectY = false;
+ }
+ if (newY > minY) {
+ newY = minY;
+ rejectY = false;
+ }
+ }
+ if (!rejectY && stealMouse) {
+ vData.move.setValue(qRound(newY));
+ vMoved = true;
+ }
+ if (qAbs(dy) > QApplication::startDragDistance())
+ stealY = true;
+ }
+ }
+
+ if (q->xflick()) {
+ int dx = int(event->pos().x() - pressPos.x());
+ if (qAbs(dx) > QApplication::startDragDistance() || QDeclarativeItemPrivate::elapsed(pressTime) > 200) {
+ if (!hMoved)
+ hData.dragStartOffset = dx;
+ qreal newX = dx + hData.pressPos - hData.dragStartOffset;
+ const qreal minX = hData.dragMinBound;
+ const qreal maxX = hData.dragMaxBound;
+ if (newX > minX)
+ newX = minX + (newX - minX) / 2;
+ if (newX < maxX && maxX - minX <= 0)
+ newX = maxX + (newX - maxX) / 2;
+ if (boundsBehavior == QDeclarative1Flickable::StopAtBounds && (newX > minX || newX < maxX)) {
+ rejectX = true;
+ if (newX < maxX) {
+ newX = maxX;
+ rejectX = false;
+ }
+ if (newX > minX) {
+ newX = minX;
+ rejectX = false;
+ }
+ }
+ if (!rejectX && stealMouse) {
+ hData.move.setValue(qRound(newX));
+ hMoved = true;
+ }
+
+ if (qAbs(dx) > QApplication::startDragDistance())
+ stealX = true;
+ }
+ }
+
+ stealMouse = stealX || stealY;
+ if (stealMouse)
+ q->setKeepMouseGrab(true);
+
+ if (rejectY) {
+ vData.velocityBuffer.clear();
+ vData.velocity = 0;
+ }
+ if (rejectX) {
+ hData.velocityBuffer.clear();
+ hData.velocity = 0;
+ }
+
+ if (hMoved || vMoved) {
+ q->movementStarting();
+ q->viewportMoved();
+ }
+
+ if (!lastPos.isNull()) {
+ qreal elapsed = qreal(QDeclarativeItemPrivate::elapsed(lastPosTime)) / 1000.;
+ if (elapsed <= 0)
+ return;
+ QDeclarativeItemPrivate::restart(lastPosTime);
+ qreal dy = event->pos().y()-lastPos.y();
+ if (q->yflick() && !rejectY)
+ vData.addVelocitySample(dy/elapsed, maxVelocity);
+ qreal dx = event->pos().x()-lastPos.x();
+ if (q->xflick() && !rejectX)
+ hData.addVelocitySample(dx/elapsed, maxVelocity);
+ }
+
+ lastPos = event->pos();
+}
+
+void QDeclarative1FlickablePrivate::handleMouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_Q(QDeclarative1Flickable);
+ stealMouse = false;
+ q->setKeepMouseGrab(false);
+ pressed = false;
+ if (!lastPosTime.isValid())
+ return;
+
+ // if we drag then pause before release we should not cause a flick.
+ if (QDeclarativeItemPrivate::elapsed(lastPosTime) < 100) {
+ vData.updateVelocity();
+ hData.updateVelocity();
+ } else {
+ hData.velocity = 0.0;
+ vData.velocity = 0.0;
+ }
+
+ vTime = timeline.time();
+
+ qreal velocity = vData.velocity;
+ if (vData.atBeginning || vData.atEnd)
+ velocity /= 2;
+ if (qAbs(velocity) > MinimumFlickVelocity && qAbs(event->pos().y() - pressPos.y()) > FlickThreshold)
+ flickY(velocity);
+ else
+ fixupY();
+
+ velocity = hData.velocity;
+ if (hData.atBeginning || hData.atEnd)
+ velocity /= 2;
+ if (qAbs(velocity) > MinimumFlickVelocity && qAbs(event->pos().x() - pressPos.x()) > FlickThreshold)
+ flickX(velocity);
+ else
+ fixupX();
+
+ if (!timeline.isActive())
+ q->movementEnding();
+}
+
+void QDeclarative1Flickable::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QDeclarative1Flickable);
+ if (d->interactive) {
+ if (!d->pressed)
+ d->handleMousePressEvent(event);
+ event->accept();
+ } else {
+ QDeclarativeItem::mousePressEvent(event);
+ }
+}
+
+void QDeclarative1Flickable::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QDeclarative1Flickable);
+ if (d->interactive) {
+ d->handleMouseMoveEvent(event);
+ event->accept();
+ } else {
+ QDeclarativeItem::mouseMoveEvent(event);
+ }
+}
+
+void QDeclarative1Flickable::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QDeclarative1Flickable);
+ if (d->interactive) {
+ d->clearDelayedPress();
+ d->handleMouseReleaseEvent(event);
+ event->accept();
+ ungrabMouse();
+ } else {
+ QDeclarativeItem::mouseReleaseEvent(event);
+ }
+}
+
+void QDeclarative1Flickable::wheelEvent(QGraphicsSceneWheelEvent *event)
+{
+ Q_D(QDeclarative1Flickable);
+ if (!d->interactive) {
+ QDeclarativeItem::wheelEvent(event);
+ } else if (yflick() && event->orientation() == Qt::Vertical) {
+ bool valid = false;
+ if (event->delta() > 0 && contentY() > -minYExtent()) {
+ d->vData.velocity = qMax(event->delta()*2 - d->vData.smoothVelocity.value(), qreal(d->maxVelocity/4));
+ valid = true;
+ } else if (event->delta() < 0 && contentY() < -maxYExtent()) {
+ d->vData.velocity = qMin(event->delta()*2 - d->vData.smoothVelocity.value(), qreal(-d->maxVelocity/4));
+ valid = true;
+ }
+ if (valid) {
+ d->flickingVertically = false;
+ d->flickY(d->vData.velocity);
+ if (d->flickingVertically) {
+ d->vMoved = true;
+ movementStarting();
+ }
+ event->accept();
+ }
+ } else if (xflick() && event->orientation() == Qt::Horizontal) {
+ bool valid = false;
+ if (event->delta() > 0 && contentX() > -minXExtent()) {
+ d->hData.velocity = qMax(event->delta()*2 - d->hData.smoothVelocity.value(), qreal(d->maxVelocity/4));
+ valid = true;
+ } else if (event->delta() < 0 && contentX() < -maxXExtent()) {
+ d->hData.velocity = qMin(event->delta()*2 - d->hData.smoothVelocity.value(), qreal(-d->maxVelocity/4));
+ valid = true;
+ }
+ if (valid) {
+ d->flickingHorizontally = false;
+ d->flickX(d->hData.velocity);
+ if (d->flickingHorizontally) {
+ d->hMoved = true;
+ movementStarting();
+ }
+ event->accept();
+ }
+ } else {
+ QDeclarativeItem::wheelEvent(event);
+ }
+}
+
+bool QDeclarative1FlickablePrivate::isOutermostPressDelay() const
+{
+ Q_Q(const QDeclarative1Flickable);
+ QDeclarativeItem *item = q->parentItem();
+ while (item) {
+ QDeclarative1Flickable *flick = qobject_cast<QDeclarative1Flickable*>(item);
+ if (flick && flick->pressDelay() > 0 && flick->isInteractive())
+ return false;
+ item = item->parentItem();
+ }
+
+ return true;
+}
+
+void QDeclarative1FlickablePrivate::captureDelayedPress(QGraphicsSceneMouseEvent *event)
+{
+ Q_Q(QDeclarative1Flickable);
+ if (!q->scene() || pressDelay <= 0)
+ return;
+ if (!isOutermostPressDelay())
+ return;
+ delayedPressTarget = q->scene()->mouseGrabberItem();
+ delayedPressEvent = new QGraphicsSceneMouseEvent(event->type());
+ delayedPressEvent->setAccepted(false);
+ for (int i = 0x1; i <= 0x10; i <<= 1) {
+ if (event->buttons() & i) {
+ Qt::MouseButton button = Qt::MouseButton(i);
+ delayedPressEvent->setButtonDownPos(button, event->buttonDownPos(button));
+ delayedPressEvent->setButtonDownScenePos(button, event->buttonDownScenePos(button));
+ delayedPressEvent->setButtonDownScreenPos(button, event->buttonDownScreenPos(button));
+ }
+ }
+ delayedPressEvent->setButtons(event->buttons());
+ delayedPressEvent->setButton(event->button());
+ delayedPressEvent->setPos(event->pos());
+ delayedPressEvent->setScenePos(event->scenePos());
+ delayedPressEvent->setScreenPos(event->screenPos());
+ delayedPressEvent->setLastPos(event->lastPos());
+ delayedPressEvent->setLastScenePos(event->lastScenePos());
+ delayedPressEvent->setLastScreenPos(event->lastScreenPos());
+ delayedPressEvent->setModifiers(event->modifiers());
+ delayedPressTimer.start(pressDelay, q);
+}
+
+void QDeclarative1FlickablePrivate::clearDelayedPress()
+{
+ if (delayedPressEvent) {
+ delayedPressTimer.stop();
+ delete delayedPressEvent;
+ delayedPressEvent = 0;
+ }
+}
+
+void QDeclarative1FlickablePrivate::setRoundedViewportX(qreal x)
+{
+ contentItem->setX(qRound(x));
+}
+
+void QDeclarative1FlickablePrivate::setRoundedViewportY(qreal y)
+{
+ contentItem->setY(qRound(y));
+}
+
+void QDeclarative1Flickable::timerEvent(QTimerEvent *event)
+{
+ Q_D(QDeclarative1Flickable);
+ if (event->timerId() == d->delayedPressTimer.timerId()) {
+ d->delayedPressTimer.stop();
+ if (d->delayedPressEvent) {
+ QDeclarativeItem *grabber = scene() ? qobject_cast<QDeclarativeItem*>(scene()->mouseGrabberItem()) : 0;
+ if (!grabber || grabber != this) {
+ // We replay the mouse press but the grabber we had might not be interessted by the event (e.g. overlay)
+ // so we reset the grabber
+ if (scene()->mouseGrabberItem() == d->delayedPressTarget)
+ d->delayedPressTarget->ungrabMouse();
+ //Use the event handler that will take care of finding the proper item to propagate the event
+ QApplication::postEvent(scene(), d->delayedPressEvent);
+ } else {
+ delete d->delayedPressEvent;
+ }
+ d->delayedPressEvent = 0;
+ }
+ }
+}
+
+qreal QDeclarative1Flickable::minYExtent() const
+{
+ return 0.0;
+}
+
+qreal QDeclarative1Flickable::minXExtent() const
+{
+ return 0.0;
+}
+
+/* returns -ve */
+qreal QDeclarative1Flickable::maxXExtent() const
+{
+ return width() - vWidth();
+}
+/* returns -ve */
+qreal QDeclarative1Flickable::maxYExtent() const
+{
+ return height() - vHeight();
+}
+
+void QDeclarative1Flickable::viewportMoved()
+{
+ Q_D(QDeclarative1Flickable);
+
+ qreal prevX = d->lastFlickablePosition.x();
+ qreal prevY = d->lastFlickablePosition.y();
+ d->velocityTimeline.clear();
+ if (d->pressed || d->calcVelocity) {
+ int elapsed = QDeclarativeItemPrivate::restart(d->velocityTime);
+ if (elapsed > 0) {
+ qreal horizontalVelocity = (prevX - d->hData.move.value()) * 1000 / elapsed;
+ qreal verticalVelocity = (prevY - d->vData.move.value()) * 1000 / elapsed;
+ d->velocityTimeline.move(d->hData.smoothVelocity, horizontalVelocity, d->reportedVelocitySmoothing);
+ d->velocityTimeline.move(d->hData.smoothVelocity, 0, d->reportedVelocitySmoothing);
+ d->velocityTimeline.move(d->vData.smoothVelocity, verticalVelocity, d->reportedVelocitySmoothing);
+ d->velocityTimeline.move(d->vData.smoothVelocity, 0, d->reportedVelocitySmoothing);
+ }
+ } else {
+ if (d->timeline.time() > d->vTime) {
+ qreal horizontalVelocity = (prevX - d->hData.move.value()) * 1000 / (d->timeline.time() - d->vTime);
+ qreal verticalVelocity = (prevY - d->vData.move.value()) * 1000 / (d->timeline.time() - d->vTime);
+ d->hData.smoothVelocity.setValue(horizontalVelocity);
+ d->vData.smoothVelocity.setValue(verticalVelocity);
+ }
+ }
+
+ if (!d->vData.inOvershoot && !d->vData.fixingUp && d->flickingVertically
+ && (d->vData.move.value() > minYExtent() || d->vData.move.value() < maxYExtent())
+ && qAbs(d->vData.smoothVelocity.value()) > 100) {
+ // Increase deceleration if we've passed a bound
+ d->vData.inOvershoot = true;
+ qreal maxDistance = d->overShootDistance(height());
+ d->timeline.reset(d->vData.move);
+ d->timeline.accel(d->vData.move, -d->vData.smoothVelocity.value(), d->deceleration*QML_FLICK_OVERSHOOTFRICTION, maxDistance);
+ d->timeline.callback(QDeclarative1TimeLineCallback(&d->vData.move, d->fixupY_callback, d));
+ }
+ if (!d->hData.inOvershoot && !d->hData.fixingUp && d->flickingHorizontally
+ && (d->hData.move.value() > minXExtent() || d->hData.move.value() < maxXExtent())
+ && qAbs(d->hData.smoothVelocity.value()) > 100) {
+ // Increase deceleration if we've passed a bound
+ d->hData.inOvershoot = true;
+ qreal maxDistance = d->overShootDistance(width());
+ d->timeline.reset(d->hData.move);
+ d->timeline.accel(d->hData.move, -d->hData.smoothVelocity.value(), d->deceleration*QML_FLICK_OVERSHOOTFRICTION, maxDistance);
+ d->timeline.callback(QDeclarative1TimeLineCallback(&d->hData.move, d->fixupX_callback, d));
+ }
+
+ d->lastFlickablePosition = QPointF(d->hData.move.value(), d->vData.move.value());
+
+ d->vTime = d->timeline.time();
+ d->updateBeginningEnd();
+}
+
+void QDeclarative1Flickable::geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry)
+{
+ Q_D(QDeclarative1Flickable);
+ QDeclarativeItem::geometryChanged(newGeometry, oldGeometry);
+
+ bool changed = false;
+ if (newGeometry.width() != oldGeometry.width()) {
+ if (xflick())
+ changed = true;
+ if (d->hData.viewSize < 0) {
+ d->contentItem->setWidth(width());
+ emit contentWidthChanged();
+ }
+ // Make sure that we're entirely in view.
+ if (!d->pressed && !d->movingHorizontally && !d->movingVertically) {
+ d->fixupMode = QDeclarative1FlickablePrivate::Immediate;
+ d->fixupX();
+ }
+ }
+ if (newGeometry.height() != oldGeometry.height()) {
+ if (yflick())
+ changed = true;
+ if (d->vData.viewSize < 0) {
+ d->contentItem->setHeight(height());
+ emit contentHeightChanged();
+ }
+ // Make sure that we're entirely in view.
+ if (!d->pressed && !d->movingHorizontally && !d->movingVertically) {
+ d->fixupMode = QDeclarative1FlickablePrivate::Immediate;
+ d->fixupY();
+ }
+ }
+
+ if (changed)
+ d->updateBeginningEnd();
+}
+
+void QDeclarative1Flickable::cancelFlick()
+{
+ Q_D(QDeclarative1Flickable);
+ d->timeline.reset(d->hData.move);
+ d->timeline.reset(d->vData.move);
+ movementEnding();
+}
+
+void QDeclarative1FlickablePrivate::data_append(QDeclarativeListProperty<QObject> *prop, QObject *o)
+{
+ QGraphicsObject *i = qobject_cast<QGraphicsObject *>(o);
+ if (i) {
+ QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(i);
+ if (static_cast<QDeclarativeItemPrivate*>(d)->componentComplete) {
+ i->setParentItem(static_cast<QDeclarative1FlickablePrivate*>(prop->data)->contentItem);
+ } else {
+ d->setParentItemHelper(static_cast<QDeclarative1FlickablePrivate*>(prop->data)->contentItem, 0, 0);
+ }
+ } else {
+ o->setParent(prop->object);
+ }
+}
+
+int QDeclarative1FlickablePrivate::data_count(QDeclarativeListProperty<QObject> *property)
+{
+ QDeclarativeItem *contentItem= static_cast<QDeclarative1FlickablePrivate*>(property->data)->contentItem;
+ return contentItem->childItems().count() + contentItem->children().count();
+}
+
+QObject *QDeclarative1FlickablePrivate::data_at(QDeclarativeListProperty<QObject> *property, int index)
+{
+ QDeclarativeItem *contentItem = static_cast<QDeclarative1FlickablePrivate*>(property->data)->contentItem;
+
+ int childItemCount = contentItem->childItems().count();
+
+ if (index < 0)
+ return 0;
+
+ if (index < childItemCount) {
+ return contentItem->childItems().at(index)->toGraphicsObject();
+ } else {
+ return contentItem->children().at(index - childItemCount);
+ }
+
+ return 0;
+}
+
+void QDeclarative1FlickablePrivate::data_clear(QDeclarativeListProperty<QObject> *property)
+{
+ QDeclarativeItem *contentItem = static_cast<QDeclarative1FlickablePrivate*>(property->data)->contentItem;
+
+ const QList<QGraphicsItem*> graphicsItems = contentItem->childItems();
+ for (int i = 0; i < graphicsItems.count(); i++)
+ contentItem->scene()->removeItem(graphicsItems[i]);
+
+ const QList<QObject*> objects = contentItem->children();
+ for (int i = 0; i < objects.count(); i++)
+ objects[i]->setParent(0);
+}
+
+QDeclarativeListProperty<QObject> QDeclarative1Flickable::flickableData()
+{
+ Q_D(QDeclarative1Flickable);
+ return QDeclarativeListProperty<QObject>(this, (void *)d, QDeclarative1FlickablePrivate::data_append,
+ QDeclarative1FlickablePrivate::data_count,
+ QDeclarative1FlickablePrivate::data_at,
+ QDeclarative1FlickablePrivate::data_clear);
+}
+
+QDeclarativeListProperty<QGraphicsObject> QDeclarative1Flickable::flickableChildren()
+{
+ Q_D(QDeclarative1Flickable);
+ return QGraphicsItemPrivate::get(d->contentItem)->childrenList();
+}
+
+/*!
+ \qmlproperty enumeration Flickable::boundsBehavior
+ This property holds whether the surface may be dragged
+ beyond the Fickable's boundaries, or overshoot the
+ Flickable's boundaries when flicked.
+
+ This enables the feeling that the edges of the view are soft,
+ rather than a hard physical boundary.
+
+ The \c boundsBehavior can be one of:
+
+ \list
+ \o Flickable.StopAtBounds - the contents can not be dragged beyond the boundary
+ of the flickable, and flicks will not overshoot.
+ \o Flickable.DragOverBounds - the contents can be dragged beyond the boundary
+ of the Flickable, but flicks will not overshoot.
+ \o Flickable.DragAndOvershootBounds (default) - the contents can be dragged
+ beyond the boundary of the Flickable, and can overshoot the
+ boundary when flicked.
+ \endlist
+*/
+QDeclarative1Flickable::BoundsBehavior QDeclarative1Flickable::boundsBehavior() const
+{
+ Q_D(const QDeclarative1Flickable);
+ return d->boundsBehavior;
+}
+
+void QDeclarative1Flickable::setBoundsBehavior(BoundsBehavior b)
+{
+ Q_D(QDeclarative1Flickable);
+ if (b == d->boundsBehavior)
+ return;
+ d->boundsBehavior = b;
+ emit boundsBehaviorChanged();
+}
+
+/*!
+ \qmlproperty real Flickable::contentWidth
+ \qmlproperty real Flickable::contentHeight
+
+ The dimensions of the content (the surface controlled by Flickable).
+ This should typically be set to the combined size of the items placed in the
+ Flickable.
+
+ The following snippet shows how these properties are used to display
+ an image that is larger than the Flickable item itself:
+
+ \snippet doc/src/snippets/declarative/flickable.qml document
+
+ In some cases, the the content dimensions can be automatically set
+ using the \l {Item::childrenRect.width}{childrenRect.width}
+ and \l {Item::childrenRect.height}{childrenRect.height} properties.
+*/
+qreal QDeclarative1Flickable::contentWidth() const
+{
+ Q_D(const QDeclarative1Flickable);
+ return d->hData.viewSize;
+}
+
+void QDeclarative1Flickable::setContentWidth(qreal w)
+{
+ Q_D(QDeclarative1Flickable);
+ if (d->hData.viewSize == w)
+ return;
+ d->hData.viewSize = w;
+ if (w < 0)
+ d->contentItem->setWidth(width());
+ else
+ d->contentItem->setWidth(w);
+ // Make sure that we're entirely in view.
+ if (!d->pressed && !d->movingHorizontally && !d->movingVertically) {
+ d->fixupMode = QDeclarative1FlickablePrivate::Immediate;
+ d->fixupX();
+ } else if (!d->pressed && d->hData.fixingUp) {
+ d->fixupMode = QDeclarative1FlickablePrivate::ExtentChanged;
+ d->fixupX();
+ }
+ emit contentWidthChanged();
+ d->updateBeginningEnd();
+}
+
+qreal QDeclarative1Flickable::contentHeight() const
+{
+ Q_D(const QDeclarative1Flickable);
+ return d->vData.viewSize;
+}
+
+void QDeclarative1Flickable::setContentHeight(qreal h)
+{
+ Q_D(QDeclarative1Flickable);
+ if (d->vData.viewSize == h)
+ return;
+ d->vData.viewSize = h;
+ if (h < 0)
+ d->contentItem->setHeight(height());
+ else
+ d->contentItem->setHeight(h);
+ // Make sure that we're entirely in view.
+ if (!d->pressed && !d->movingHorizontally && !d->movingVertically) {
+ d->fixupMode = QDeclarative1FlickablePrivate::Immediate;
+ d->fixupY();
+ } else if (!d->pressed && d->vData.fixingUp) {
+ d->fixupMode = QDeclarative1FlickablePrivate::ExtentChanged;
+ d->fixupY();
+ }
+ emit contentHeightChanged();
+ d->updateBeginningEnd();
+}
+
+/*!
+ \qmlmethod Flickable::resizeContent(real width, real height, QPointF center)
+ \preliminary
+ \since Quick 1.1
+
+ Resizes the content to \a width x \a height about \a center.
+
+ This does not scale the contents of the Flickable - it only resizes the \l contentWidth
+ and \l contentHeight.
+
+ Resizing the content may result in the content being positioned outside
+ the bounds of the Flickable. Calling \l returnToBounds() will
+ move the content back within legal bounds.
+*/
+void QDeclarative1Flickable::resizeContent(qreal w, qreal h, QPointF center)
+{
+ Q_D(QDeclarative1Flickable);
+ if (w != d->hData.viewSize) {
+ qreal oldSize = d->hData.viewSize;
+ d->hData.viewSize = w;
+ d->contentItem->setWidth(w);
+ emit contentWidthChanged();
+ if (center.x() != 0) {
+ qreal pos = center.x() * w / oldSize;
+ setContentX(contentX() + pos - center.x());
+ }
+ }
+ if (h != d->vData.viewSize) {
+ qreal oldSize = d->vData.viewSize;
+ d->vData.viewSize = h;
+ d->contentItem->setHeight(h);
+ emit contentHeightChanged();
+ if (center.y() != 0) {
+ qreal pos = center.y() * h / oldSize;
+ setContentY(contentY() + pos - center.y());
+ }
+ }
+ d->updateBeginningEnd();
+}
+
+/*!
+ \qmlmethod Flickable::returnToBounds()
+ \preliminary
+ \since Quick 1.1
+
+ Ensures the content is within legal bounds.
+
+ This may be called to ensure that the content is within legal bounds
+ after manually positioning the content.
+*/
+void QDeclarative1Flickable::returnToBounds()
+{
+ Q_D(QDeclarative1Flickable);
+ d->fixupX();
+ d->fixupY();
+}
+
+qreal QDeclarative1Flickable::vWidth() const
+{
+ Q_D(const QDeclarative1Flickable);
+ if (d->hData.viewSize < 0)
+ return width();
+ else
+ return d->hData.viewSize;
+}
+
+qreal QDeclarative1Flickable::vHeight() const
+{
+ Q_D(const QDeclarative1Flickable);
+ if (d->vData.viewSize < 0)
+ return height();
+ else
+ return d->vData.viewSize;
+}
+
+bool QDeclarative1Flickable::xflick() const
+{
+ Q_D(const QDeclarative1Flickable);
+ if (d->flickableDirection == QDeclarative1Flickable::AutoFlickDirection)
+ return vWidth() != width();
+ return d->flickableDirection & QDeclarative1Flickable::HorizontalFlick;
+}
+
+bool QDeclarative1Flickable::yflick() const
+{
+ Q_D(const QDeclarative1Flickable);
+ if (d->flickableDirection == QDeclarative1Flickable::AutoFlickDirection)
+ return vHeight() != height();
+ return d->flickableDirection & QDeclarative1Flickable::VerticalFlick;
+}
+
+bool QDeclarative1Flickable::sceneEvent(QEvent *event)
+{
+ bool rv = QDeclarativeItem::sceneEvent(event);
+ if (event->type() == QEvent::UngrabMouse) {
+ Q_D(QDeclarative1Flickable);
+ if (d->pressed) {
+ // if our mouse grab has been removed (probably by another Flickable),
+ // fix our state
+ d->pressed = false;
+ d->stealMouse = false;
+ setKeepMouseGrab(false);
+ }
+ }
+ return rv;
+}
+
+bool QDeclarative1Flickable::sendMouseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QDeclarative1Flickable);
+ QGraphicsSceneMouseEvent mouseEvent(event->type());
+ QRectF myRect = mapToScene(QRectF(0, 0, width(), height())).boundingRect();
+
+ QGraphicsScene *s = scene();
+ QDeclarativeItem *grabber = s ? qobject_cast<QDeclarativeItem*>(s->mouseGrabberItem()) : 0;
+ QGraphicsItem *grabberItem = s ? s->mouseGrabberItem() : 0;
+ bool disabledItem = grabberItem && !grabberItem->isEnabled();
+ bool stealThisEvent = d->stealMouse;
+ if ((stealThisEvent || myRect.contains(event->scenePos().toPoint())) && (!grabber || !grabber->keepMouseGrab() || disabledItem)) {
+ mouseEvent.setAccepted(false);
+ for (int i = 0x1; i <= 0x10; i <<= 1) {
+ if (event->buttons() & i) {
+ Qt::MouseButton button = Qt::MouseButton(i);
+ mouseEvent.setButtonDownPos(button, mapFromScene(event->buttonDownPos(button)));
+ }
+ }
+ mouseEvent.setScenePos(event->scenePos());
+ mouseEvent.setLastScenePos(event->lastScenePos());
+ mouseEvent.setPos(mapFromScene(event->scenePos()));
+ mouseEvent.setLastPos(mapFromScene(event->lastScenePos()));
+
+ switch(mouseEvent.type()) {
+ case QEvent::GraphicsSceneMouseMove:
+ d->handleMouseMoveEvent(&mouseEvent);
+ break;
+ case QEvent::GraphicsSceneMousePress:
+ if (d->pressed) // we are already pressed - this is a delayed replay
+ return false;
+
+ d->handleMousePressEvent(&mouseEvent);
+ d->captureDelayedPress(event);
+ stealThisEvent = d->stealMouse; // Update stealThisEvent in case changed by function call above
+ break;
+ case QEvent::GraphicsSceneMouseRelease:
+ if (d->delayedPressEvent) {
+ // We replay the mouse press but the grabber we had might not be interessted by the event (e.g. overlay)
+ // so we reset the grabber
+ if (s->mouseGrabberItem() == d->delayedPressTarget)
+ d->delayedPressTarget->ungrabMouse();
+ //Use the event handler that will take care of finding the proper item to propagate the event
+ QApplication::sendEvent(scene(), d->delayedPressEvent);
+ d->clearDelayedPress();
+ // We send the release
+ scene()->sendEvent(s->mouseGrabberItem(), event);
+ // And the event has been consumed
+ d->stealMouse = false;
+ d->pressed = false;
+ return true;
+ }
+ d->handleMouseReleaseEvent(&mouseEvent);
+ break;
+ default:
+ break;
+ }
+ grabber = qobject_cast<QDeclarativeItem*>(s->mouseGrabberItem());
+ if ((grabber && stealThisEvent && !grabber->keepMouseGrab() && grabber != this) || disabledItem) {
+ d->clearDelayedPress();
+ grabMouse();
+ }
+
+ return stealThisEvent || d->delayedPressEvent || disabledItem;
+ } else if (d->lastPosTime.isValid()) {
+ d->lastPosTime.invalidate();
+ }
+ if (mouseEvent.type() == QEvent::GraphicsSceneMouseRelease) {
+ d->clearDelayedPress();
+ d->stealMouse = false;
+ d->pressed = false;
+ }
+
+ return false;
+}
+
+bool QDeclarative1Flickable::sceneEventFilter(QGraphicsItem *i, QEvent *e)
+{
+ Q_D(QDeclarative1Flickable);
+ if (!isVisible() || !d->interactive)
+ return QDeclarativeItem::sceneEventFilter(i, e);
+ switch (e->type()) {
+ case QEvent::GraphicsSceneMousePress:
+ case QEvent::GraphicsSceneMouseMove:
+ case QEvent::GraphicsSceneMouseRelease:
+ return sendMouseEvent(static_cast<QGraphicsSceneMouseEvent *>(e));
+ default:
+ break;
+ }
+
+ return QDeclarativeItem::sceneEventFilter(i, e);
+}
+
+/*!
+ \qmlproperty real Flickable::maximumFlickVelocity
+ This property holds the maximum velocity that the user can flick the view in pixels/second.
+
+ The default value is platform dependent.
+*/
+qreal QDeclarative1Flickable::maximumFlickVelocity() const
+{
+ Q_D(const QDeclarative1Flickable);
+ return d->maxVelocity;
+}
+
+void QDeclarative1Flickable::setMaximumFlickVelocity(qreal v)
+{
+ Q_D(QDeclarative1Flickable);
+ if (v == d->maxVelocity)
+ return;
+ d->maxVelocity = v;
+ emit maximumFlickVelocityChanged();
+}
+
+/*!
+ \qmlproperty real Flickable::flickDeceleration
+ This property holds the rate at which a flick will decelerate.
+
+ The default value is platform dependent.
+*/
+qreal QDeclarative1Flickable::flickDeceleration() const
+{
+ Q_D(const QDeclarative1Flickable);
+ return d->deceleration;
+}
+
+void QDeclarative1Flickable::setFlickDeceleration(qreal deceleration)
+{
+ Q_D(QDeclarative1Flickable);
+ if (deceleration == d->deceleration)
+ return;
+ d->deceleration = deceleration;
+ emit flickDecelerationChanged();
+}
+
+bool QDeclarative1Flickable::isFlicking() const
+{
+ Q_D(const QDeclarative1Flickable);
+ return d->flickingHorizontally || d->flickingVertically;
+}
+
+/*!
+ \qmlproperty bool Flickable::flicking
+ \qmlproperty bool Flickable::flickingHorizontally
+ \qmlproperty bool Flickable::flickingVertically
+
+ These properties describe whether the view is currently moving horizontally,
+ vertically or in either direction, due to the user flicking the view.
+*/
+bool QDeclarative1Flickable::isFlickingHorizontally() const
+{
+ Q_D(const QDeclarative1Flickable);
+ return d->flickingHorizontally;
+}
+
+bool QDeclarative1Flickable::isFlickingVertically() const
+{
+ Q_D(const QDeclarative1Flickable);
+ return d->flickingVertically;
+}
+
+/*!
+ \qmlproperty int Flickable::pressDelay
+
+ This property holds the time to delay (ms) delivering a press to
+ children of the Flickable. This can be useful where reacting
+ to a press before a flicking action has undesirable effects.
+
+ If the flickable is dragged/flicked before the delay times out
+ the press event will not be delivered. If the button is released
+ within the timeout, both the press and release will be delivered.
+
+ Note that for nested Flickables with pressDelay set, the pressDelay of
+ inner Flickables is overridden by the outermost Flickable.
+*/
+int QDeclarative1Flickable::pressDelay() const
+{
+ Q_D(const QDeclarative1Flickable);
+ return d->pressDelay;
+}
+
+void QDeclarative1Flickable::setPressDelay(int delay)
+{
+ Q_D(QDeclarative1Flickable);
+ if (d->pressDelay == delay)
+ return;
+ d->pressDelay = delay;
+ emit pressDelayChanged();
+}
+
+
+bool QDeclarative1Flickable::isMoving() const
+{
+ Q_D(const QDeclarative1Flickable);
+ return d->movingHorizontally || d->movingVertically;
+}
+
+/*!
+ \qmlproperty bool Flickable::moving
+ \qmlproperty bool Flickable::movingHorizontally
+ \qmlproperty bool Flickable::movingVertically
+
+ These properties describe whether the view is currently moving horizontally,
+ vertically or in either direction, due to the user either dragging or
+ flicking the view.
+*/
+bool QDeclarative1Flickable::isMovingHorizontally() const
+{
+ Q_D(const QDeclarative1Flickable);
+ return d->movingHorizontally;
+}
+
+bool QDeclarative1Flickable::isMovingVertically() const
+{
+ Q_D(const QDeclarative1Flickable);
+ return d->movingVertically;
+}
+
+void QDeclarative1Flickable::movementStarting()
+{
+ Q_D(QDeclarative1Flickable);
+ if (d->hMoved && !d->movingHorizontally) {
+ d->movingHorizontally = true;
+ emit movingChanged();
+ emit movingHorizontallyChanged();
+ if (!d->movingVertically)
+ emit movementStarted();
+ }
+ else if (d->vMoved && !d->movingVertically) {
+ d->movingVertically = true;
+ emit movingChanged();
+ emit movingVerticallyChanged();
+ if (!d->movingHorizontally)
+ emit movementStarted();
+ }
+}
+
+void QDeclarative1Flickable::movementEnding()
+{
+ Q_D(QDeclarative1Flickable);
+ movementXEnding();
+ movementYEnding();
+ d->hData.smoothVelocity.setValue(0);
+ d->vData.smoothVelocity.setValue(0);
+}
+
+void QDeclarative1Flickable::movementXEnding()
+{
+ Q_D(QDeclarative1Flickable);
+ if (d->flickingHorizontally) {
+ d->flickingHorizontally = false;
+ emit flickingChanged();
+ emit flickingHorizontallyChanged();
+ if (!d->flickingVertically)
+ emit flickEnded();
+ }
+ if (!d->pressed && !d->stealMouse) {
+ if (d->movingHorizontally) {
+ d->movingHorizontally = false;
+ d->hMoved = false;
+ emit movingChanged();
+ emit movingHorizontallyChanged();
+ if (!d->movingVertically)
+ emit movementEnded();
+ }
+ }
+ d->hData.fixingUp = false;
+}
+
+void QDeclarative1Flickable::movementYEnding()
+{
+ Q_D(QDeclarative1Flickable);
+ if (d->flickingVertically) {
+ d->flickingVertically = false;
+ emit flickingChanged();
+ emit flickingVerticallyChanged();
+ if (!d->flickingHorizontally)
+ emit flickEnded();
+ }
+ if (!d->pressed && !d->stealMouse) {
+ if (d->movingVertically) {
+ d->movingVertically = false;
+ d->vMoved = false;
+ emit movingChanged();
+ emit movingVerticallyChanged();
+ if (!d->movingHorizontally)
+ emit movementEnded();
+ }
+ }
+ d->vData.fixingUp = false;
+}
+
+void QDeclarative1FlickablePrivate::updateVelocity()
+{
+ Q_Q(QDeclarative1Flickable);
+ emit q->horizontalVelocityChanged();
+ emit q->verticalVelocityChanged();
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/graphicsitems/qdeclarativeflickable_p.h b/src/qtquick1/graphicsitems/qdeclarativeflickable_p.h
new file mode 100644
index 0000000000..63428840a0
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativeflickable_p.h
@@ -0,0 +1,229 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEFLICKABLE_H
+#define QDECLARATIVEFLICKABLE_H
+
+#include "qdeclarativeitem.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarative1FlickablePrivate;
+class QDeclarative1FlickableVisibleArea;
+class Q_AUTOTEST_EXPORT QDeclarative1Flickable : public QDeclarativeItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal contentWidth READ contentWidth WRITE setContentWidth NOTIFY contentWidthChanged)
+ Q_PROPERTY(qreal contentHeight READ contentHeight WRITE setContentHeight NOTIFY contentHeightChanged)
+ Q_PROPERTY(qreal contentX READ contentX WRITE setContentX NOTIFY contentXChanged)
+ Q_PROPERTY(qreal contentY READ contentY WRITE setContentY NOTIFY contentYChanged)
+ Q_PROPERTY(QDeclarativeItem *contentItem READ contentItem CONSTANT)
+
+ Q_PROPERTY(qreal horizontalVelocity READ horizontalVelocity NOTIFY horizontalVelocityChanged)
+ Q_PROPERTY(qreal verticalVelocity READ verticalVelocity NOTIFY verticalVelocityChanged)
+
+ Q_PROPERTY(BoundsBehavior boundsBehavior READ boundsBehavior WRITE setBoundsBehavior NOTIFY boundsBehaviorChanged)
+ Q_PROPERTY(qreal maximumFlickVelocity READ maximumFlickVelocity WRITE setMaximumFlickVelocity NOTIFY maximumFlickVelocityChanged)
+ Q_PROPERTY(qreal flickDeceleration READ flickDeceleration WRITE setFlickDeceleration NOTIFY flickDecelerationChanged)
+ Q_PROPERTY(bool moving READ isMoving NOTIFY movingChanged)
+ Q_PROPERTY(bool movingHorizontally READ isMovingHorizontally NOTIFY movingHorizontallyChanged)
+ Q_PROPERTY(bool movingVertically READ isMovingVertically NOTIFY movingVerticallyChanged)
+ Q_PROPERTY(bool flicking READ isFlicking NOTIFY flickingChanged)
+ Q_PROPERTY(bool flickingHorizontally READ isFlickingHorizontally NOTIFY flickingHorizontallyChanged)
+ Q_PROPERTY(bool flickingVertically READ isFlickingVertically NOTIFY flickingVerticallyChanged)
+ Q_PROPERTY(FlickableDirection flickableDirection READ flickableDirection WRITE setFlickableDirection NOTIFY flickableDirectionChanged)
+
+ Q_PROPERTY(bool interactive READ isInteractive WRITE setInteractive NOTIFY interactiveChanged)
+ Q_PROPERTY(int pressDelay READ pressDelay WRITE setPressDelay NOTIFY pressDelayChanged)
+
+ Q_PROPERTY(bool atXEnd READ isAtXEnd NOTIFY isAtBoundaryChanged)
+ Q_PROPERTY(bool atYEnd READ isAtYEnd NOTIFY isAtBoundaryChanged)
+ Q_PROPERTY(bool atXBeginning READ isAtXBeginning NOTIFY isAtBoundaryChanged)
+ Q_PROPERTY(bool atYBeginning READ isAtYBeginning NOTIFY isAtBoundaryChanged)
+
+ Q_PROPERTY(QDeclarative1FlickableVisibleArea *visibleArea READ visibleArea CONSTANT)
+
+ Q_PROPERTY(QDeclarativeListProperty<QObject> flickableData READ flickableData)
+ Q_PROPERTY(QDeclarativeListProperty<QGraphicsObject> flickableChildren READ flickableChildren)
+ Q_CLASSINFO("DefaultProperty", "flickableData")
+
+ Q_ENUMS(FlickableDirection)
+ Q_ENUMS(BoundsBehavior)
+
+public:
+ QDeclarative1Flickable(QDeclarativeItem *parent=0);
+ ~QDeclarative1Flickable();
+
+ QDeclarativeListProperty<QObject> flickableData();
+ QDeclarativeListProperty<QGraphicsObject> flickableChildren();
+
+ enum BoundsBehavior { StopAtBounds, DragOverBounds, DragAndOvershootBounds };
+ BoundsBehavior boundsBehavior() const;
+ void setBoundsBehavior(BoundsBehavior);
+
+ qreal contentWidth() const;
+ void setContentWidth(qreal);
+
+ qreal contentHeight() const;
+ void setContentHeight(qreal);
+
+ qreal contentX() const;
+ virtual void setContentX(qreal pos);
+
+ qreal contentY() const;
+ virtual void setContentY(qreal pos);
+
+ bool isMoving() const;
+ bool isMovingHorizontally() const;
+ bool isMovingVertically() const;
+ bool isFlicking() const;
+ bool isFlickingHorizontally() const;
+ bool isFlickingVertically() const;
+
+ int pressDelay() const;
+ void setPressDelay(int delay);
+
+ qreal maximumFlickVelocity() const;
+ void setMaximumFlickVelocity(qreal);
+
+ qreal flickDeceleration() const;
+ void setFlickDeceleration(qreal);
+
+ bool isInteractive() const;
+ void setInteractive(bool);
+
+ qreal horizontalVelocity() const;
+ qreal verticalVelocity() const;
+
+ bool isAtXEnd() const;
+ bool isAtXBeginning() const;
+ bool isAtYEnd() const;
+ bool isAtYBeginning() const;
+
+ QDeclarativeItem *contentItem();
+
+ enum FlickableDirection { AutoFlickDirection=0x00, HorizontalFlick=0x01, VerticalFlick=0x02, HorizontalAndVerticalFlick=0x03 };
+ FlickableDirection flickableDirection() const;
+ void setFlickableDirection(FlickableDirection);
+
+ Q_INVOKABLE Q_REVISION(1) void resizeContent(qreal w, qreal h, QPointF center);
+ Q_INVOKABLE Q_REVISION(1) void returnToBounds();
+
+Q_SIGNALS:
+ void contentWidthChanged();
+ void contentHeightChanged();
+ void contentXChanged();
+ void contentYChanged();
+ void movingChanged();
+ void movingHorizontallyChanged();
+ void movingVerticallyChanged();
+ void flickingChanged();
+ void flickingHorizontallyChanged();
+ void flickingVerticallyChanged();
+ void horizontalVelocityChanged();
+ void verticalVelocityChanged();
+ void isAtBoundaryChanged();
+ void flickableDirectionChanged();
+ void interactiveChanged();
+ void boundsBehaviorChanged();
+ void maximumFlickVelocityChanged();
+ void flickDecelerationChanged();
+ void pressDelayChanged();
+ void movementStarted();
+ void movementEnded();
+ void flickStarted();
+ void flickEnded();
+
+protected:
+ virtual bool sceneEventFilter(QGraphicsItem *, QEvent *);
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+ void wheelEvent(QGraphicsSceneWheelEvent *event);
+ void timerEvent(QTimerEvent *event);
+
+ QDeclarative1FlickableVisibleArea *visibleArea();
+
+protected Q_SLOTS:
+ virtual void ticked();
+ void movementStarting();
+ void movementEnding();
+
+protected:
+ void movementXEnding();
+ void movementYEnding();
+ virtual qreal minXExtent() const;
+ virtual qreal minYExtent() const;
+ virtual qreal maxXExtent() const;
+ virtual qreal maxYExtent() const;
+ qreal vWidth() const;
+ qreal vHeight() const;
+ virtual void viewportMoved();
+ virtual void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry);
+ bool sceneEvent(QEvent *event);
+ bool sendMouseEvent(QGraphicsSceneMouseEvent *event);
+
+ bool xflick() const;
+ bool yflick() const;
+ void cancelFlick();
+
+protected:
+ QDeclarative1Flickable(QDeclarative1FlickablePrivate &dd, QDeclarativeItem *parent);
+
+private:
+ Q_DISABLE_COPY(QDeclarative1Flickable)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarative1Flickable)
+ friend class QDeclarative1FlickableVisibleArea;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1Flickable)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/qtquick1/graphicsitems/qdeclarativeflickable_p_p.h b/src/qtquick1/graphicsitems/qdeclarativeflickable_p_p.h
new file mode 100644
index 0000000000..5bbeb27c9e
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativeflickable_p_p.h
@@ -0,0 +1,241 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEFLICKABLE_P_H
+#define QDECLARATIVEFLICKABLE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qdeclarativeflickable_p.h"
+
+#include "private/qdeclarativeitem_p.h"
+#include "private/qdeclarativeitemchangelistener_p.h"
+
+#include <QtDeclarative/qdeclarative.h>
+#include <QtQuick1/private/qdeclarativetimeline_p_p.h>
+#include <QtQuick1/private/qdeclarativeanimation_p_p.h>
+
+#include <qdatetime.h>
+
+QT_BEGIN_NAMESPACE
+
+// Really slow flicks can be annoying.
+const qreal MinimumFlickVelocity = 75.0;
+
+class QDeclarative1FlickableVisibleArea;
+class QDeclarative1FlickablePrivate : public QDeclarativeItemPrivate, public QDeclarativeItemChangeListener
+{
+ Q_DECLARE_PUBLIC(QDeclarative1Flickable)
+
+public:
+ QDeclarative1FlickablePrivate();
+ void init();
+
+ struct Velocity : public QDeclarative1TimeLineValue
+ {
+ Velocity(QDeclarative1FlickablePrivate *p)
+ : parent(p) {}
+ virtual void setValue(qreal v) {
+ if (v != value()) {
+ QDeclarative1TimeLineValue::setValue(v);
+ parent->updateVelocity();
+ }
+ }
+ QDeclarative1FlickablePrivate *parent;
+ };
+
+ struct AxisData {
+ AxisData(QDeclarative1FlickablePrivate *fp, void (QDeclarative1FlickablePrivate::*func)(qreal))
+ : move(fp, func), viewSize(-1), smoothVelocity(fp), atEnd(false), atBeginning(true)
+ , fixingUp(false), inOvershoot(false)
+ {}
+
+ void reset() {
+ velocityBuffer.clear();
+ dragStartOffset = 0;
+ fixingUp = false;
+ inOvershoot = false;
+ }
+
+ void addVelocitySample(qreal v, qreal maxVelocity);
+ void updateVelocity();
+
+ QDeclarative1TimeLineValueProxy<QDeclarative1FlickablePrivate> move;
+ qreal viewSize;
+ qreal pressPos;
+ qreal dragStartOffset;
+ qreal dragMinBound;
+ qreal dragMaxBound;
+ qreal velocity;
+ qreal flickTarget;
+ QDeclarative1FlickablePrivate::Velocity smoothVelocity;
+ QPODVector<qreal,10> velocityBuffer;
+ bool atEnd : 1;
+ bool atBeginning : 1;
+ bool fixingUp : 1;
+ bool inOvershoot : 1;
+ };
+
+ void flickX(qreal velocity);
+ void flickY(qreal velocity);
+ virtual void flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
+ QDeclarative1TimeLineCallback::Callback fixupCallback, qreal velocity);
+
+ void fixupX();
+ void fixupY();
+ virtual void fixup(AxisData &data, qreal minExtent, qreal maxExtent);
+
+ void updateBeginningEnd();
+
+ bool isOutermostPressDelay() const;
+ void captureDelayedPress(QGraphicsSceneMouseEvent *event);
+ void clearDelayedPress();
+
+ void setRoundedViewportX(qreal x);
+ void setRoundedViewportY(qreal y);
+
+ qreal overShootDistance(qreal size);
+
+ void itemGeometryChanged(QDeclarativeItem *, const QRectF &, const QRectF &);
+
+public:
+ QDeclarativeItem *contentItem;
+
+ AxisData hData;
+ AxisData vData;
+
+ QDeclarative1TimeLine timeline;
+ bool flickingHorizontally : 1;
+ bool flickingVertically : 1;
+ bool hMoved : 1;
+ bool vMoved : 1;
+ bool movingHorizontally : 1;
+ bool movingVertically : 1;
+ bool stealMouse : 1;
+ bool pressed : 1;
+ bool interactive : 1;
+ bool calcVelocity : 1;
+ QElapsedTimer lastPosTime;
+ QPointF lastPos;
+ QPointF pressPos;
+ QElapsedTimer pressTime;
+ qreal deceleration;
+ qreal maxVelocity;
+ QElapsedTimer velocityTime;
+ QPointF lastFlickablePosition;
+ qreal reportedVelocitySmoothing;
+ QGraphicsSceneMouseEvent *delayedPressEvent;
+ QGraphicsItem *delayedPressTarget;
+ QBasicTimer delayedPressTimer;
+ int pressDelay;
+ int fixupDuration;
+
+ enum FixupMode { Normal, Immediate, ExtentChanged };
+ FixupMode fixupMode;
+
+ static void fixupY_callback(void *);
+ static void fixupX_callback(void *);
+
+ void updateVelocity();
+ int vTime;
+ QDeclarative1TimeLine velocityTimeline;
+ QDeclarative1FlickableVisibleArea *visibleArea;
+ QDeclarative1Flickable::FlickableDirection flickableDirection;
+ QDeclarative1Flickable::BoundsBehavior boundsBehavior;
+
+ void handleMousePressEvent(QGraphicsSceneMouseEvent *);
+ void handleMouseMoveEvent(QGraphicsSceneMouseEvent *);
+ void handleMouseReleaseEvent(QGraphicsSceneMouseEvent *);
+
+ // flickableData property
+ static void data_append(QDeclarativeListProperty<QObject> *, QObject *);
+ static int data_count(QDeclarativeListProperty<QObject> *);
+ static QObject *data_at(QDeclarativeListProperty<QObject> *, int);
+ static void data_clear(QDeclarativeListProperty<QObject> *);
+};
+
+class QDeclarative1FlickableVisibleArea : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal xPosition READ xPosition NOTIFY xPositionChanged)
+ Q_PROPERTY(qreal yPosition READ yPosition NOTIFY yPositionChanged)
+ Q_PROPERTY(qreal widthRatio READ widthRatio NOTIFY widthRatioChanged)
+ Q_PROPERTY(qreal heightRatio READ heightRatio NOTIFY heightRatioChanged)
+
+public:
+ QDeclarative1FlickableVisibleArea(QDeclarative1Flickable *parent=0);
+
+ qreal xPosition() const;
+ qreal widthRatio() const;
+ qreal yPosition() const;
+ qreal heightRatio() const;
+
+ void updateVisible();
+
+signals:
+ void xPositionChanged(qreal xPosition);
+ void yPositionChanged(qreal yPosition);
+ void widthRatioChanged(qreal widthRatio);
+ void heightRatioChanged(qreal heightRatio);
+
+private:
+ QDeclarative1Flickable *flickable;
+ qreal m_xPosition;
+ qreal m_widthRatio;
+ qreal m_yPosition;
+ qreal m_heightRatio;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1FlickableVisibleArea)
+
+#endif
diff --git a/src/qtquick1/graphicsitems/qdeclarativeflipable.cpp b/src/qtquick1/graphicsitems/qdeclarativeflipable.cpp
new file mode 100644
index 0000000000..d25f33a129
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativeflipable.cpp
@@ -0,0 +1,258 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativeflipable_p.h"
+
+#include "QtQuick1/private/qdeclarativeitem_p.h"
+#include "QtDeclarative/private/qdeclarativeguard_p.h"
+
+#include <QtDeclarative/qdeclarativeinfo.h>
+
+#include <QtGui/qgraphicstransform.h>
+
+QT_BEGIN_NAMESPACE
+
+
+
+class QDeclarative1FlipablePrivate : public QDeclarativeItemPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1Flipable)
+public:
+ QDeclarative1FlipablePrivate() : current(QDeclarative1Flipable::Front), front(0), back(0) {}
+
+ void updateSceneTransformFromParent();
+ void setBackTransform();
+
+ QDeclarative1Flipable::Side current;
+ QDeclarativeGuard<QGraphicsObject> front;
+ QDeclarativeGuard<QGraphicsObject> back;
+
+ bool wantBackXFlipped;
+ bool wantBackYFlipped;
+};
+
+/*!
+ \qmlclass Flipable QDeclarative1Flipable
+ \since 4.7
+ \ingroup qml-basic-interaction-elements
+ \brief The Flipable item provides a surface that can be flipped.
+ \inherits Item
+
+ Flipable is an item that can be visibly "flipped" between its front and
+ back sides, like a card. It is used together with \l Rotation, \l State
+ and \l Transition elements to produce a flipping effect.
+
+ The \l front and \l back properties are used to hold the items that are
+ shown respectively on the front and back sides of the flipable item.
+
+ \section1 Example Usage
+
+ The following example shows a Flipable item that flips whenever it is
+ clicked, rotating about the y-axis.
+
+ This flipable item has a \c flipped boolean property that is toggled
+ whenever the MouseArea within the flipable is clicked. When
+ \c flipped is true, the item changes to the "back" state; in this
+ state, the \c angle of the \l Rotation item is changed to 180
+ degrees to produce the flipping effect. When \c flipped is false, the
+ item reverts to the default state, in which the \c angle value is 0.
+
+ \snippet doc/src/snippets/declarative/flipable/flipable.qml 0
+
+ \image flipable.gif
+
+ The \l Transition creates the animation that changes the angle over
+ four seconds. When the item changes between its "back" and
+ default states, the NumberAnimation animates the angle between
+ its old and new values.
+
+ See \l {QML States} for details on state changes and the default
+ state, and \l {QML Animation and Transitions} for more information on how
+ animations work within transitions.
+
+ \sa {declarative/ui-components/flipable}{Flipable example}
+*/
+
+QDeclarative1Flipable::QDeclarative1Flipable(QDeclarativeItem *parent)
+: QDeclarativeItem(*(new QDeclarative1FlipablePrivate), parent)
+{
+}
+
+QDeclarative1Flipable::~QDeclarative1Flipable()
+{
+}
+
+/*!
+ \qmlproperty Item Flipable::front
+ \qmlproperty Item Flipable::back
+
+ The front and back sides of the flipable.
+*/
+
+QGraphicsObject *QDeclarative1Flipable::front()
+{
+ Q_D(const QDeclarative1Flipable);
+ return d->front;
+}
+
+void QDeclarative1Flipable::setFront(QGraphicsObject *front)
+{
+ Q_D(QDeclarative1Flipable);
+ if (d->front) {
+ qmlInfo(this) << tr("front is a write-once property");
+ return;
+ }
+ d->front = front;
+ d->front->setParentItem(this);
+ if (Back == d->current)
+ d->front->setOpacity(0.);
+ emit frontChanged();
+}
+
+QGraphicsObject *QDeclarative1Flipable::back()
+{
+ Q_D(const QDeclarative1Flipable);
+ return d->back;
+}
+
+void QDeclarative1Flipable::setBack(QGraphicsObject *back)
+{
+ Q_D(QDeclarative1Flipable);
+ if (d->back) {
+ qmlInfo(this) << tr("back is a write-once property");
+ return;
+ }
+ d->back = back;
+ d->back->setParentItem(this);
+ if (Front == d->current)
+ d->back->setOpacity(0.);
+ connect(back, SIGNAL(widthChanged()),
+ this, SLOT(retransformBack()));
+ connect(back, SIGNAL(heightChanged()),
+ this, SLOT(retransformBack()));
+ emit backChanged();
+}
+
+void QDeclarative1Flipable::retransformBack()
+{
+ Q_D(QDeclarative1Flipable);
+ if (d->current == QDeclarative1Flipable::Back && d->back)
+ d->setBackTransform();
+}
+
+/*!
+ \qmlproperty enumeration Flipable::side
+
+ The side of the Flipable currently visible. Possible values are \c
+ Flipable.Front and \c Flipable.Back.
+*/
+QDeclarative1Flipable::Side QDeclarative1Flipable::side() const
+{
+ Q_D(const QDeclarative1Flipable);
+ if (d->dirtySceneTransform)
+ const_cast<QDeclarative1FlipablePrivate *>(d)->ensureSceneTransform();
+
+ return d->current;
+}
+
+// determination on the currently visible side of the flipable
+// has to be done on the complete scene transform to give
+// correct results.
+void QDeclarative1FlipablePrivate::updateSceneTransformFromParent()
+{
+ Q_Q(QDeclarative1Flipable);
+
+ QDeclarativeItemPrivate::updateSceneTransformFromParent();
+ QPointF p1(0, 0);
+ QPointF p2(1, 0);
+ QPointF p3(1, 1);
+
+ QPointF scenep1 = sceneTransform.map(p1);
+ QPointF scenep2 = sceneTransform.map(p2);
+ QPointF scenep3 = sceneTransform.map(p3);
+ p1 = q->mapToParent(p1);
+ p2 = q->mapToParent(p2);
+ p3 = q->mapToParent(p3);
+
+ qreal cross = (scenep1.x() - scenep2.x()) * (scenep3.y() - scenep2.y()) -
+ (scenep1.y() - scenep2.y()) * (scenep3.x() - scenep2.x());
+
+ wantBackYFlipped = p1.x() >= p2.x();
+ wantBackXFlipped = p2.y() >= p3.y();
+
+ QDeclarative1Flipable::Side newSide;
+ if (cross > 0) {
+ newSide = QDeclarative1Flipable::Back;
+ } else {
+ newSide = QDeclarative1Flipable::Front;
+ }
+
+ if (newSide != current) {
+ current = newSide;
+ if (current == QDeclarative1Flipable::Back && back)
+ setBackTransform();
+ if (front)
+ front->setOpacity((current==QDeclarative1Flipable::Front)?1.:0.);
+ if (back)
+ back->setOpacity((current==QDeclarative1Flipable::Back)?1.:0.);
+ emit q->sideChanged();
+ }
+}
+
+/* Depends on the width/height of the back item, and so needs reevaulating
+ if those change.
+*/
+void QDeclarative1FlipablePrivate::setBackTransform()
+{
+ QTransform mat;
+ QGraphicsItemPrivate *dBack = QGraphicsItemPrivate::get(back);
+ mat.translate(dBack->width()/2,dBack->height()/2);
+ if (dBack->width() && wantBackYFlipped)
+ mat.rotate(180, Qt::YAxis);
+ if (dBack->height() && wantBackXFlipped)
+ mat.rotate(180, Qt::XAxis);
+ mat.translate(-dBack->width()/2,-dBack->height()/2);
+ back->setTransform(mat);
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/graphicsitems/qdeclarativeflipable_p.h b/src/qtquick1/graphicsitems/qdeclarativeflipable_p.h
new file mode 100644
index 0000000000..f4cdb86126
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativeflipable_p.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEFLIPABLE_H
+#define QDECLARATIVEFLIPABLE_H
+
+#include "qdeclarativeitem.h"
+
+#include <QtCore/QObject>
+#include <QtGui/QTransform>
+#include <QtGui/qvector3d.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarative1FlipablePrivate;
+class Q_AUTOTEST_EXPORT QDeclarative1Flipable : public QDeclarativeItem
+{
+ Q_OBJECT
+
+ Q_ENUMS(Side)
+ Q_PROPERTY(QGraphicsObject *front READ front WRITE setFront NOTIFY frontChanged)
+ Q_PROPERTY(QGraphicsObject *back READ back WRITE setBack NOTIFY backChanged)
+ Q_PROPERTY(Side side READ side NOTIFY sideChanged)
+ //### flipAxis
+ //### flipRotation
+public:
+ QDeclarative1Flipable(QDeclarativeItem *parent=0);
+ ~QDeclarative1Flipable();
+
+ QGraphicsObject *front();
+ void setFront(QGraphicsObject *);
+
+ QGraphicsObject *back();
+ void setBack(QGraphicsObject *);
+
+ enum Side { Front, Back };
+ Side side() const;
+
+Q_SIGNALS:
+ void frontChanged();
+ void backChanged();
+ void sideChanged();
+
+private Q_SLOTS:
+ void retransformBack();
+
+private:
+ Q_DISABLE_COPY(QDeclarative1Flipable)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarative1Flipable)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1Flipable)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEFLIPABLE_H
diff --git a/src/qtquick1/graphicsitems/qdeclarativefocuspanel.cpp b/src/qtquick1/graphicsitems/qdeclarativefocuspanel.cpp
new file mode 100644
index 0000000000..e50df2ace5
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativefocuspanel.cpp
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativefocuspanel_p.h"
+
+#include "QtQuick1/private/qdeclarativeitem_p.h"
+
+#include <QtGui/qgraphicsscene.h>
+#include <QEvent>
+
+QT_BEGIN_NAMESPACE
+
+
+
+/*!
+ \qmlclass FocusPanel QDeclarative1FocusPanel
+ \since 4.7
+ \ingroup qml-basic-interaction-elements
+
+ \brief The FocusPanel item explicitly creates a focus panel.
+ \inherits Item
+
+ Focus panels assist in keyboard focus handling when building QML
+ applications. All the details are covered in the
+ \l {qmlfocus}{keyboard focus documentation}.
+*/
+
+QDeclarative1FocusPanel::QDeclarative1FocusPanel(QDeclarativeItem *parent) :
+ QDeclarativeItem(parent)
+{
+ Q_D(QDeclarativeItem);
+ d->flags |= QGraphicsItem::ItemIsPanel;
+}
+
+QDeclarative1FocusPanel::~QDeclarative1FocusPanel()
+{
+}
+
+/*!
+ \qmlproperty bool FocusPanel::active
+
+ Sets whether the item is the active focus panel.
+*/
+
+bool QDeclarative1FocusPanel::sceneEvent(QEvent *event)
+{
+ if (event->type() == QEvent::WindowActivate ||
+ event->type() == QEvent::WindowDeactivate)
+ emit activeChanged();
+ return QDeclarativeItem::sceneEvent(event);
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/graphicsitems/qdeclarativefocuspanel_p.h b/src/qtquick1/graphicsitems/qdeclarativefocuspanel_p.h
new file mode 100644
index 0000000000..38eadfdba3
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativefocuspanel_p.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEFOCUSPANEL_H
+#define QDECLARATIVEFOCUSPANEL_H
+
+#include "qdeclarativeitem.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_AUTOTEST_EXPORT QDeclarative1FocusPanel : public QDeclarativeItem
+{
+ Q_OBJECT
+ Q_PROPERTY(bool active READ isActive WRITE setActive NOTIFY activeChanged)
+public:
+ QDeclarative1FocusPanel(QDeclarativeItem *parent=0);
+ virtual ~QDeclarative1FocusPanel();
+
+Q_SIGNALS:
+ void activeChanged();
+
+protected:
+ bool sceneEvent(QEvent *event);
+
+private:
+ Q_DISABLE_COPY(QDeclarative1FocusPanel)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarativeItem)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1FocusPanel)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEFOCUSPANEL_H
diff --git a/src/qtquick1/graphicsitems/qdeclarativefocusscope.cpp b/src/qtquick1/graphicsitems/qdeclarativefocusscope.cpp
new file mode 100644
index 0000000000..5d942de9bc
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativefocusscope.cpp
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativefocusscope_p.h"
+
+#include "QtQuick1/private/qdeclarativeitem_p.h"
+
+QT_BEGIN_NAMESPACE
+
+
+
+/*!
+ \qmlclass FocusScope QDeclarative1FocusScope
+ \since 4.7
+ \ingroup qml-basic-interaction-elements
+
+ \brief The FocusScope object explicitly creates a focus scope.
+ \inherits Item
+
+ Focus scopes assist in keyboard focus handling when building reusable QML
+ components. All the details are covered in the
+ \l {qmlfocus}{keyboard focus documentation}.
+
+ \sa {declarative/keyinteraction/focus}{Keyboard focus example}
+*/
+
+QDeclarative1FocusScope::QDeclarative1FocusScope(QDeclarativeItem *parent) :
+ QDeclarativeItem(parent)
+{
+ Q_D(QDeclarativeItem);
+ d->flags |= QGraphicsItem::ItemIsFocusScope;
+}
+
+QDeclarative1FocusScope::~QDeclarative1FocusScope()
+{
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/graphicsitems/qdeclarativefocusscope_p.h b/src/qtquick1/graphicsitems/qdeclarativefocusscope_p.h
new file mode 100644
index 0000000000..ee31d94347
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativefocusscope_p.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEFOCUSSCOPE_H
+#define QDECLARATIVEFOCUSSCOPE_H
+
+#include "qdeclarativeitem.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+//### set component root as focusscope
+class Q_AUTOTEST_EXPORT QDeclarative1FocusScope : public QDeclarativeItem
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarativeItem)
+public:
+ QDeclarative1FocusScope(QDeclarativeItem *parent=0);
+ virtual ~QDeclarative1FocusScope();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1FocusScope)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEFOCUSSCOPE_H
diff --git a/src/qtquick1/graphicsitems/qdeclarativegraphicswidget.cpp b/src/qtquick1/graphicsitems/qdeclarativegraphicswidget.cpp
new file mode 100644
index 0000000000..8ccf23221a
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativegraphicswidget.cpp
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativegraphicswidget_p.h"
+#include "QtQuick1/private/qdeclarativeanchors_p.h"
+#include "QtQuick1/private/qdeclarativeitem_p.h"
+#include "QtQuick1/private/qdeclarativeanchors_p_p.h"
+
+QT_BEGIN_NAMESPACE
+
+
+
+class QDeclarative1GraphicsWidgetPrivate : public QObjectPrivate {
+ Q_DECLARE_PUBLIC(QDeclarative1GraphicsWidget)
+public :
+ QDeclarative1GraphicsWidgetPrivate() :
+ _anchors(0), _anchorLines(0)
+ {}
+ QDeclarativeItemPrivate::AnchorLines *anchorLines() const;
+ QDeclarative1Anchors *_anchors;
+ mutable QDeclarativeItemPrivate::AnchorLines *_anchorLines;
+};
+
+QDeclarative1GraphicsWidget::QDeclarative1GraphicsWidget(QObject *parent) :
+ QObject(*new QDeclarative1GraphicsWidgetPrivate, parent)
+{
+}
+QDeclarative1GraphicsWidget::~QDeclarative1GraphicsWidget()
+{
+ Q_D(QDeclarative1GraphicsWidget);
+ delete d->_anchorLines; d->_anchorLines = 0;
+ delete d->_anchors; d->_anchors = 0;
+}
+
+QDeclarative1Anchors *QDeclarative1GraphicsWidget::anchors()
+{
+ Q_D(QDeclarative1GraphicsWidget);
+ if (!d->_anchors)
+ d->_anchors = new QDeclarative1Anchors(static_cast<QGraphicsObject *>(parent()));
+ return d->_anchors;
+}
+
+QDeclarativeItemPrivate::AnchorLines *QDeclarative1GraphicsWidgetPrivate::anchorLines() const
+{
+ Q_Q(const QDeclarative1GraphicsWidget);
+ if (!_anchorLines)
+ _anchorLines = new QDeclarativeItemPrivate::AnchorLines(static_cast<QGraphicsObject *>(q->parent()));
+ return _anchorLines;
+}
+
+QDeclarative1AnchorLine QDeclarative1GraphicsWidget::left() const
+{
+ Q_D(const QDeclarative1GraphicsWidget);
+ return d->anchorLines()->left;
+}
+
+QDeclarative1AnchorLine QDeclarative1GraphicsWidget::right() const
+{
+ Q_D(const QDeclarative1GraphicsWidget);
+ return d->anchorLines()->right;
+}
+
+QDeclarative1AnchorLine QDeclarative1GraphicsWidget::horizontalCenter() const
+{
+ Q_D(const QDeclarative1GraphicsWidget);
+ return d->anchorLines()->hCenter;
+}
+
+QDeclarative1AnchorLine QDeclarative1GraphicsWidget::top() const
+{
+ Q_D(const QDeclarative1GraphicsWidget);
+ return d->anchorLines()->top;
+}
+
+QDeclarative1AnchorLine QDeclarative1GraphicsWidget::bottom() const
+{
+ Q_D(const QDeclarative1GraphicsWidget);
+ return d->anchorLines()->bottom;
+}
+
+QDeclarative1AnchorLine QDeclarative1GraphicsWidget::verticalCenter() const
+{
+ Q_D(const QDeclarative1GraphicsWidget);
+ return d->anchorLines()->vCenter;
+}
+
+
+
+QT_END_NAMESPACE
+
+#include <moc_qdeclarativegraphicswidget_p.cpp>
diff --git a/src/qtquick1/graphicsitems/qdeclarativegraphicswidget_p.h b/src/qtquick1/graphicsitems/qdeclarativegraphicswidget_p.h
new file mode 100644
index 0000000000..2e433d78aa
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativegraphicswidget_p.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEGRAPHICSWIDGET_P_H
+#define QDECLARATIVEGRAPHICSWIDGET_P_H
+
+#include <QObject>
+#include <QtDeclarative/qdeclarativecomponent.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QGraphicsObject;
+class QDeclarative1AnchorLine;
+class QDeclarative1Anchors;
+class QDeclarative1GraphicsWidgetPrivate;
+
+// ### TODO can the extension object be the anchor directly? We save one allocation -> awesome.
+class QDeclarative1GraphicsWidget : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QDeclarative1Anchors * anchors READ anchors DESIGNABLE false CONSTANT FINAL)
+ Q_PROPERTY(QDeclarative1AnchorLine left READ left CONSTANT FINAL)
+ Q_PROPERTY(QDeclarative1AnchorLine right READ right CONSTANT FINAL)
+ Q_PROPERTY(QDeclarative1AnchorLine horizontalCenter READ horizontalCenter CONSTANT FINAL)
+ Q_PROPERTY(QDeclarative1AnchorLine top READ top CONSTANT FINAL)
+ Q_PROPERTY(QDeclarative1AnchorLine bottom READ bottom CONSTANT FINAL)
+ Q_PROPERTY(QDeclarative1AnchorLine verticalCenter READ verticalCenter CONSTANT FINAL)
+ // ### TODO : QGraphicsWidget don't have a baseline concept yet.
+ //Q_PROPERTY(QDeclarative1AnchorLine baseline READ baseline CONSTANT FINAL)
+public:
+ QDeclarative1GraphicsWidget(QObject *parent = 0);
+ ~QDeclarative1GraphicsWidget();
+ QDeclarative1Anchors *anchors();
+ QDeclarative1AnchorLine left() const;
+ QDeclarative1AnchorLine right() const;
+ QDeclarative1AnchorLine horizontalCenter() const;
+ QDeclarative1AnchorLine top() const;
+ QDeclarative1AnchorLine bottom() const;
+ QDeclarative1AnchorLine verticalCenter() const;
+ Q_DISABLE_COPY(QDeclarative1GraphicsWidget)
+ Q_DECLARE_PRIVATE(QDeclarative1GraphicsWidget)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEGRAPHICSWIDGET_P_H
diff --git a/src/qtquick1/graphicsitems/qdeclarativegridview.cpp b/src/qtquick1/graphicsitems/qdeclarativegridview.cpp
new file mode 100644
index 0000000000..228cd2aba1
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativegridview.cpp
@@ -0,0 +1,3133 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativegridview_p.h"
+
+#include "QtQuick1/private/qdeclarativevisualitemmodel_p.h"
+#include "QtQuick1/private/qdeclarativeflickable_p_p.h"
+
+#include "QtQuick1/private/qdeclarativesmoothedanimation_p_p.h"
+#include <QtDeclarative/private/qdeclarativeguard_p.h>
+
+#include <QKeyEvent>
+
+#include <qmath.h>
+#include <math.h>
+
+QT_BEGIN_NAMESPACE
+
+
+
+
+//----------------------------------------------------------------------------
+
+class FxGridItem1
+{
+public:
+ FxGridItem1(QDeclarativeItem *i, QDeclarative1GridView *v) : item(i), view(v) {
+ attached = static_cast<QDeclarative1GridViewAttached*>(qmlAttachedPropertiesObject<QDeclarative1GridView>(item));
+ if (attached)
+ attached->setView(view);
+ }
+ ~FxGridItem1() {}
+
+ qreal rowPos() const {
+ qreal rowPos = 0;
+ if (view->flow() == QDeclarative1GridView::LeftToRight) {
+ rowPos = item->y();
+ } else {
+ if (view->effectiveLayoutDirection() == Qt::RightToLeft)
+ rowPos = -view->cellWidth()-item->x();
+ else
+ rowPos = item->x();
+ }
+ return rowPos;
+ }
+ qreal colPos() const {
+ qreal colPos = 0;
+ if (view->flow() == QDeclarative1GridView::LeftToRight) {
+ if (view->effectiveLayoutDirection() == Qt::RightToLeft) {
+ int colSize = view->cellWidth();
+ int columns = view->width()/colSize;
+ colPos = colSize * (columns-1) - item->x();
+ } else {
+ colPos = item->x();
+ }
+ } else {
+ colPos = item->y();
+ }
+
+ return colPos;
+ }
+
+ qreal endRowPos() const {
+ if (view->flow() == QDeclarative1GridView::LeftToRight) {
+ return item->y() + view->cellHeight() - 1;
+ } else {
+ if (view->effectiveLayoutDirection() == Qt::RightToLeft)
+ return -item->x() - 1;
+ else
+ return item->x() + view->cellWidth() - 1;
+ }
+ }
+ void setPosition(qreal col, qreal row) {
+ if (view->effectiveLayoutDirection() == Qt::RightToLeft) {
+ if (view->flow() == QDeclarative1GridView::LeftToRight) {
+ int columns = view->width()/view->cellWidth();
+ item->setPos(QPointF((view->cellWidth() * (columns-1) - col), row));
+ } else {
+ item->setPos(QPointF(-view->cellWidth()-row, col));
+ }
+ } else {
+ if (view->flow() == QDeclarative1GridView::LeftToRight)
+ item->setPos(QPointF(col, row));
+ else
+ item->setPos(QPointF(row, col));
+ }
+
+ }
+ bool contains(qreal x, qreal y) const {
+ return (x >= item->x() && x < item->x() + view->cellWidth() &&
+ y >= item->y() && y < item->y() + view->cellHeight());
+ }
+
+ QDeclarativeItem *item;
+ QDeclarative1GridView *view;
+ QDeclarative1GridViewAttached *attached;
+ int index;
+};
+
+//----------------------------------------------------------------------------
+
+class QDeclarative1GridViewPrivate : public QDeclarative1FlickablePrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1GridView)
+
+public:
+ QDeclarative1GridViewPrivate()
+ : currentItem(0), layoutDirection(Qt::LeftToRight), flow(QDeclarative1GridView::LeftToRight)
+ , visibleIndex(0) , currentIndex(-1)
+ , cellWidth(100), cellHeight(100), columns(1), requestedIndex(-1), itemCount(0)
+ , highlightRangeStart(0), highlightRangeEnd(0)
+ , highlightRangeStartValid(false), highlightRangeEndValid(false)
+ , highlightRange(QDeclarative1GridView::NoHighlightRange)
+ , highlightComponent(0), highlight(0), trackedItem(0)
+ , moveReason(Other), buffer(0), highlightXAnimator(0), highlightYAnimator(0)
+ , highlightMoveDuration(150)
+ , footerComponent(0), footer(0), headerComponent(0), header(0)
+ , bufferMode(BufferBefore | BufferAfter), snapMode(QDeclarative1GridView::NoSnap)
+ , ownModel(false), wrap(false), autoHighlight(true)
+ , fixCurrentVisibility(false), lazyRelease(false), layoutScheduled(false)
+ , deferredRelease(false), haveHighlightRange(false), currentIndexCleared(false) {}
+
+ void init();
+ void clear();
+ FxGridItem1 *createItem(int modelIndex);
+ void releaseItem(FxGridItem1 *item);
+ void refill(qreal from, qreal to, bool doBuffer=false);
+
+ void updateGrid();
+ void scheduleLayout();
+ void layout();
+ void updateUnrequestedIndexes();
+ void updateUnrequestedPositions();
+ void updateTrackedItem();
+ void createHighlight();
+ void updateHighlight();
+ void updateCurrent(int modelIndex);
+ void updateHeader();
+ void updateFooter();
+ void fixupPosition();
+
+ FxGridItem1 *visibleItem(int modelIndex) const {
+ if (modelIndex >= visibleIndex && modelIndex < visibleIndex + visibleItems.count()) {
+ for (int i = modelIndex - visibleIndex; i < visibleItems.count(); ++i) {
+ FxGridItem1 *item = visibleItems.at(i);
+ if (item->index == modelIndex)
+ return item;
+ }
+ }
+ return 0;
+ }
+
+ bool isRightToLeftTopToBottom() const {
+ Q_Q(const QDeclarative1GridView);
+ return flow == QDeclarative1GridView::TopToBottom && q->effectiveLayoutDirection() == Qt::RightToLeft;
+ }
+
+ void regenerate() {
+ Q_Q(QDeclarative1GridView);
+ if (q->isComponentComplete()) {
+ clear();
+ updateGrid();
+ setPosition(0);
+ q->refill();
+ updateCurrent(currentIndex);
+ }
+ }
+
+ void mirrorChange() {
+ Q_Q(QDeclarative1GridView);
+ regenerate();
+ emit q->effectiveLayoutDirectionChanged();
+ }
+
+ qreal position() const {
+ Q_Q(const QDeclarative1GridView);
+ return flow == QDeclarative1GridView::LeftToRight ? q->contentY() : q->contentX();
+ }
+ void setPosition(qreal pos) {
+ Q_Q(QDeclarative1GridView);
+ if (flow == QDeclarative1GridView::LeftToRight) {
+ q->QDeclarative1Flickable::setContentY(pos);
+ q->QDeclarative1Flickable::setContentX(0);
+ } else {
+ if (q->effectiveLayoutDirection() == Qt::LeftToRight)
+ q->QDeclarative1Flickable::setContentX(pos);
+ else
+ q->QDeclarative1Flickable::setContentX(-pos-size());
+ q->QDeclarative1Flickable::setContentY(0);
+ }
+ }
+ int size() const {
+ Q_Q(const QDeclarative1GridView);
+ return flow == QDeclarative1GridView::LeftToRight ? q->height() : q->width();
+ }
+ qreal originPosition() const {
+ qreal pos = 0;
+ if (!visibleItems.isEmpty())
+ pos = visibleItems.first()->rowPos() - visibleIndex / columns * rowSize();
+ return pos;
+ }
+
+ qreal lastPosition() const {
+ qreal pos = 0;
+ if (model && model->count())
+ pos = rowPosAt(model->count() - 1) + rowSize();
+ return pos;
+ }
+
+ qreal startPosition() const {
+ return isRightToLeftTopToBottom() ? -lastPosition()+1 : originPosition();
+ }
+
+ qreal endPosition() const {
+ return isRightToLeftTopToBottom() ? -originPosition()+1 : lastPosition();
+
+ }
+
+ bool isValid() const {
+ return model && model->count() && model->isValid();
+ }
+
+ int rowSize() const {
+ return flow == QDeclarative1GridView::LeftToRight ? cellHeight : cellWidth;
+ }
+ int colSize() const {
+ return flow == QDeclarative1GridView::LeftToRight ? cellWidth : cellHeight;
+ }
+
+ qreal colPosAt(int modelIndex) const {
+ if (FxGridItem1 *item = visibleItem(modelIndex))
+ return item->colPos();
+ if (!visibleItems.isEmpty()) {
+ if (modelIndex < visibleIndex) {
+ int count = (visibleIndex - modelIndex) % columns;
+ int col = visibleItems.first()->colPos() / colSize();
+ col = (columns - count + col) % columns;
+ return col * colSize();
+ } else {
+ int count = columns - 1 - (modelIndex - visibleItems.last()->index - 1) % columns;
+ return visibleItems.last()->colPos() - count * colSize();
+ }
+ } else {
+ return (modelIndex % columns) * colSize();
+ }
+ return 0;
+ }
+ qreal rowPosAt(int modelIndex) const {
+ if (FxGridItem1 *item = visibleItem(modelIndex))
+ return item->rowPos();
+ if (!visibleItems.isEmpty()) {
+ if (modelIndex < visibleIndex) {
+ int firstCol = visibleItems.first()->colPos() / colSize();
+ int col = visibleIndex - modelIndex + (columns - firstCol - 1);
+ int rows = col / columns;
+ return visibleItems.first()->rowPos() - rows * rowSize();
+ } else {
+ int count = modelIndex - visibleItems.last()->index;
+ int col = visibleItems.last()->colPos() + count * colSize();
+ int rows = col / (columns * colSize());
+ return visibleItems.last()->rowPos() + rows * rowSize();
+ }
+ } else {
+ qreal pos = (modelIndex / columns) * rowSize();
+ if (header)
+ pos += headerSize();
+ return pos;
+ }
+ return 0;
+ }
+
+ FxGridItem1 *firstVisibleItem() const {
+ const qreal pos = isRightToLeftTopToBottom() ? -position()-size() : position();
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxGridItem1 *item = visibleItems.at(i);
+ if (item->index != -1 && item->endRowPos() > pos)
+ return item;
+ }
+ return visibleItems.count() ? visibleItems.first() : 0;
+ }
+
+ int lastVisibleIndex() const {
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxGridItem1 *item = visibleItems.at(i);
+ if (item->index != -1)
+ return item->index;
+ }
+ return -1;
+ }
+
+ // Map a model index to visibleItems list index.
+ // These may differ if removed items are still present in the visible list,
+ // e.g. doing a removal animation
+ int mapFromModel(int modelIndex) const {
+ if (modelIndex < visibleIndex || modelIndex >= visibleIndex + visibleItems.count())
+ return -1;
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxGridItem1 *listItem = visibleItems.at(i);
+ if (listItem->index == modelIndex)
+ return i + visibleIndex;
+ if (listItem->index > modelIndex)
+ return -1;
+ }
+ return -1; // Not in visibleList
+ }
+
+ qreal snapPosAt(qreal pos) const {
+ Q_Q(const QDeclarative1GridView);
+ qreal snapPos = 0;
+ if (!visibleItems.isEmpty()) {
+ pos += rowSize()/2;
+ snapPos = visibleItems.first()->rowPos() - visibleIndex / columns * rowSize();
+ snapPos = pos - fmodf(pos - snapPos, qreal(rowSize()));
+ qreal maxExtent;
+ qreal minExtent;
+ if (isRightToLeftTopToBottom()) {
+ maxExtent = q->minXExtent();
+ minExtent = q->maxXExtent();
+ } else {
+ maxExtent = flow == QDeclarative1GridView::LeftToRight ? -q->maxYExtent() : -q->maxXExtent();
+ minExtent = flow == QDeclarative1GridView::LeftToRight ? -q->minYExtent() : -q->minXExtent();
+ }
+ if (snapPos > maxExtent)
+ snapPos = maxExtent;
+ if (snapPos < minExtent)
+ snapPos = minExtent;
+ }
+ return snapPos;
+ }
+
+ FxGridItem1 *snapItemAt(qreal pos) {
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxGridItem1 *item = visibleItems[i];
+ if (item->index == -1)
+ continue;
+ qreal itemTop = item->rowPos();
+ if (itemTop+rowSize()/2 >= pos && itemTop - rowSize()/2 <= pos)
+ return item;
+ }
+ return 0;
+ }
+
+ int snapIndex() {
+ int index = currentIndex;
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxGridItem1 *item = visibleItems[i];
+ if (item->index == -1)
+ continue;
+ qreal itemTop = item->rowPos();
+ if (itemTop >= highlight->rowPos()-rowSize()/2 && itemTop < highlight->rowPos()+rowSize()/2) {
+ index = item->index;
+ if (item->colPos() >= highlight->colPos()-colSize()/2 && item->colPos() < highlight->colPos()+colSize()/2)
+ return item->index;
+ }
+ }
+ return index;
+ }
+
+ qreal headerSize() const {
+ if (!header)
+ return 0.0;
+
+ return flow == QDeclarative1GridView::LeftToRight
+ ? header->item->height()
+ : header->item->width();
+ }
+
+
+ virtual void itemGeometryChanged(QDeclarativeItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) {
+ Q_Q(const QDeclarative1GridView);
+ QDeclarative1FlickablePrivate::itemGeometryChanged(item, newGeometry, oldGeometry);
+ if (item == q) {
+ if (newGeometry.height() != oldGeometry.height()
+ || newGeometry.width() != oldGeometry.width()) {
+ if (q->isComponentComplete()) {
+ updateGrid();
+ scheduleLayout();
+ }
+ }
+ } else if ((header && header->item == item) || (footer && footer->item == item)) {
+ if (header)
+ updateHeader();
+ if (footer)
+ updateFooter();
+ }
+ }
+
+ void positionViewAtIndex(int index, int mode);
+ virtual void fixup(AxisData &data, qreal minExtent, qreal maxExtent);
+ virtual void flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
+ QDeclarative1TimeLineCallback::Callback fixupCallback, qreal velocity);
+
+ // for debugging only
+ void checkVisible() const {
+ int skip = 0;
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxGridItem1 *listItem = visibleItems.at(i);
+ if (listItem->index == -1) {
+ ++skip;
+ } else if (listItem->index != visibleIndex + i - skip) {
+ for (int j = 0; j < visibleItems.count(); j++)
+ qDebug() << " index" << j << "item index" << visibleItems.at(j)->index;
+ qFatal("index %d %d %d", visibleIndex, i, listItem->index);
+ }
+ }
+ }
+
+ QDeclarativeGuard<QDeclarative1VisualModel> model;
+ QVariant modelVariant;
+ QList<FxGridItem1*> visibleItems;
+ QHash<QDeclarativeItem*,int> unrequestedItems;
+ FxGridItem1 *currentItem;
+ Qt::LayoutDirection layoutDirection;
+ QDeclarative1GridView::Flow flow;
+ int visibleIndex;
+ int currentIndex;
+ int cellWidth;
+ int cellHeight;
+ int columns;
+ int requestedIndex;
+ int itemCount;
+ qreal highlightRangeStart;
+ qreal highlightRangeEnd;
+ bool highlightRangeStartValid;
+ bool highlightRangeEndValid;
+ QDeclarative1GridView::HighlightRangeMode highlightRange;
+ QDeclarativeComponent *highlightComponent;
+ FxGridItem1 *highlight;
+ FxGridItem1 *trackedItem;
+ enum MovementReason { Other, SetIndex, Mouse };
+ MovementReason moveReason;
+ int buffer;
+ QSmoothedAnimation_1 *highlightXAnimator;
+ QSmoothedAnimation_1 *highlightYAnimator;
+ int highlightMoveDuration;
+ QDeclarativeComponent *footerComponent;
+ FxGridItem1 *footer;
+ QDeclarativeComponent *headerComponent;
+ FxGridItem1 *header;
+ enum BufferMode { NoBuffer = 0x00, BufferBefore = 0x01, BufferAfter = 0x02 };
+ int bufferMode;
+ QDeclarative1GridView::SnapMode snapMode;
+
+ bool ownModel : 1;
+ bool wrap : 1;
+ bool autoHighlight : 1;
+ bool fixCurrentVisibility : 1;
+ bool lazyRelease : 1;
+ bool layoutScheduled : 1;
+ bool deferredRelease : 1;
+ bool haveHighlightRange : 1;
+ bool currentIndexCleared : 1;
+};
+
+void QDeclarative1GridViewPrivate::init()
+{
+ Q_Q(QDeclarative1GridView);
+ QObject::connect(q, SIGNAL(movementEnded()), q, SLOT(animStopped()));
+ q->setFlag(QGraphicsItem::ItemIsFocusScope);
+ q->setFlickableDirection(QDeclarative1Flickable::VerticalFlick);
+ addItemChangeListener(this, Geometry);
+}
+
+void QDeclarative1GridViewPrivate::clear()
+{
+ for (int i = 0; i < visibleItems.count(); ++i)
+ releaseItem(visibleItems.at(i));
+ visibleItems.clear();
+ visibleIndex = 0;
+ releaseItem(currentItem);
+ currentItem = 0;
+ createHighlight();
+ trackedItem = 0;
+ itemCount = 0;
+}
+
+FxGridItem1 *QDeclarative1GridViewPrivate::createItem(int modelIndex)
+{
+ Q_Q(QDeclarative1GridView);
+ // create object
+ requestedIndex = modelIndex;
+ FxGridItem1 *listItem = 0;
+ if (QDeclarativeItem *item = model->item(modelIndex, false)) {
+ listItem = new FxGridItem1(item, q);
+ listItem->index = modelIndex;
+ if (model->completePending()) {
+ // complete
+ listItem->item->setZValue(1);
+ listItem->item->setParentItem(q->contentItem());
+ model->completeItem();
+ } else {
+ listItem->item->setParentItem(q->contentItem());
+ }
+ unrequestedItems.remove(listItem->item);
+ }
+ requestedIndex = -1;
+ return listItem;
+}
+
+
+void QDeclarative1GridViewPrivate::releaseItem(FxGridItem1 *item)
+{
+ Q_Q(QDeclarative1GridView);
+ if (!item || !model)
+ return;
+ if (trackedItem == item) {
+ QObject::disconnect(trackedItem->item, SIGNAL(yChanged()), q, SLOT(trackedPositionChanged()));
+ QObject::disconnect(trackedItem->item, SIGNAL(xChanged()), q, SLOT(trackedPositionChanged()));
+ trackedItem = 0;
+ }
+ if (model->release(item->item) == 0) {
+ // item was not destroyed, and we no longer reference it.
+ unrequestedItems.insert(item->item, model->indexOf(item->item, q));
+ }
+ delete item;
+}
+
+void QDeclarative1GridViewPrivate::refill(qreal from, qreal to, bool doBuffer)
+{
+ Q_Q(QDeclarative1GridView);
+ if (!isValid() || !q->isComponentComplete())
+ return;
+ itemCount = model->count();
+ qreal bufferFrom = from - buffer;
+ qreal bufferTo = to + buffer;
+ qreal fillFrom = from;
+ qreal fillTo = to;
+ if (doBuffer && (bufferMode & BufferAfter))
+ fillTo = bufferTo;
+ if (doBuffer && (bufferMode & BufferBefore))
+ fillFrom = bufferFrom;
+
+ bool changed = false;
+
+ int colPos = colPosAt(visibleIndex);
+ int rowPos = rowPosAt(visibleIndex);
+ int modelIndex = visibleIndex;
+ if (visibleItems.count()) {
+ rowPos = visibleItems.last()->rowPos();
+ colPos = visibleItems.last()->colPos() + colSize();
+ if (colPos > colSize() * (columns-1)) {
+ colPos = 0;
+ rowPos += rowSize();
+ }
+ int i = visibleItems.count() - 1;
+ while (i > 0 && visibleItems.at(i)->index == -1)
+ --i;
+ modelIndex = visibleItems.at(i)->index + 1;
+ }
+
+ if (visibleItems.count() && (fillFrom > rowPos + rowSize()*2
+ || fillTo < rowPosAt(visibleIndex) - rowSize())) {
+ // We've jumped more than a page. Estimate which items are now
+ // visible and fill from there.
+ int count = (fillFrom - (rowPos + rowSize())) / (rowSize()) * columns;
+ for (int i = 0; i < visibleItems.count(); ++i)
+ releaseItem(visibleItems.at(i));
+ visibleItems.clear();
+ modelIndex += count;
+ if (modelIndex >= model->count())
+ modelIndex = model->count() - 1;
+ else if (modelIndex < 0)
+ modelIndex = 0;
+ modelIndex = modelIndex / columns * columns;
+ visibleIndex = modelIndex;
+ colPos = colPosAt(visibleIndex);
+ rowPos = rowPosAt(visibleIndex);
+ }
+
+ int colNum = colPos / colSize();
+
+ FxGridItem1 *item = 0;
+
+ // Item creation and release is staggered in order to avoid
+ // creating/releasing multiple items in one frame
+ // while flicking (as much as possible).
+ while (modelIndex < model->count() && rowPos <= fillTo + rowSize()*(columns - colNum)/(columns+1)) {
+// qDebug() << "refill: append item" << modelIndex;
+ if (!(item = createItem(modelIndex)))
+ break;
+ item->setPosition(colPos, rowPos);
+ visibleItems.append(item);
+ colPos += colSize();
+ colNum++;
+ if (colPos > colSize() * (columns-1)) {
+ colPos = 0;
+ colNum = 0;
+ rowPos += rowSize();
+ }
+ ++modelIndex;
+ changed = true;
+ if (doBuffer) // never buffer more than one item per frame
+ break;
+ }
+
+ if (visibleItems.count()) {
+ rowPos = visibleItems.first()->rowPos();
+ colPos = visibleItems.first()->colPos() - colSize();
+ if (colPos < 0) {
+ colPos = colSize() * (columns - 1);
+ rowPos -= rowSize();
+ }
+ }
+ colNum = colPos / colSize();
+ while (visibleIndex > 0 && rowPos + rowSize() - 1 >= fillFrom - rowSize()*(colNum+1)/(columns+1)){
+// qDebug() << "refill: prepend item" << visibleIndex-1 << "top pos" << rowPos << colPos;
+ if (!(item = createItem(visibleIndex-1)))
+ break;
+ --visibleIndex;
+ item->setPosition(colPos, rowPos);
+ visibleItems.prepend(item);
+ colPos -= colSize();
+ colNum--;
+ if (colPos < 0) {
+ colPos = colSize() * (columns - 1);
+ colNum = columns-1;
+ rowPos -= rowSize();
+ }
+ changed = true;
+ if (doBuffer) // never buffer more than one item per frame
+ break;
+ }
+
+ if (!lazyRelease || !changed || deferredRelease) { // avoid destroying items in the same frame that we create
+ while (visibleItems.count() > 1
+ && (item = visibleItems.first())
+ && item->rowPos()+rowSize()-1 < bufferFrom - rowSize()*(item->colPos()/colSize()+1)/(columns+1)) {
+ if (item->attached->delayRemove())
+ break;
+// qDebug() << "refill: remove first" << visibleIndex << "top end pos" << item->endRowPos();
+ if (item->index != -1)
+ visibleIndex++;
+ visibleItems.removeFirst();
+ releaseItem(item);
+ changed = true;
+ }
+ while (visibleItems.count() > 1
+ && (item = visibleItems.last())
+ && item->rowPos() > bufferTo + rowSize()*(columns - item->colPos()/colSize())/(columns+1)) {
+ if (item->attached->delayRemove())
+ break;
+// qDebug() << "refill: remove last" << visibleIndex+visibleItems.count()-1;
+ visibleItems.removeLast();
+ releaseItem(item);
+ changed = true;
+ }
+ deferredRelease = false;
+ } else {
+ deferredRelease = true;
+ }
+ if (changed) {
+ if (header)
+ updateHeader();
+ if (footer)
+ updateFooter();
+ if (flow == QDeclarative1GridView::LeftToRight)
+ q->setContentHeight(endPosition() - startPosition());
+ else
+ q->setContentWidth(endPosition() - startPosition());
+ } else if (!doBuffer && buffer && bufferMode != NoBuffer) {
+ refill(from, to, true);
+ }
+ lazyRelease = false;
+}
+
+void QDeclarative1GridViewPrivate::updateGrid()
+{
+ Q_Q(QDeclarative1GridView);
+
+ columns = (int)qMax((flow == QDeclarative1GridView::LeftToRight ? q->width() : q->height()) / colSize(), qreal(1.));
+ if (isValid()) {
+ if (flow == QDeclarative1GridView::LeftToRight)
+ q->setContentHeight(endPosition() - startPosition());
+ else
+ q->setContentWidth(lastPosition() - originPosition());
+ }
+}
+
+void QDeclarative1GridViewPrivate::scheduleLayout()
+{
+ Q_Q(QDeclarative1GridView);
+ if (!layoutScheduled) {
+ layoutScheduled = true;
+ QCoreApplication::postEvent(q, new QEvent(QEvent::User), Qt::HighEventPriority);
+ }
+}
+
+void QDeclarative1GridViewPrivate::layout()
+{
+ Q_Q(QDeclarative1GridView);
+ layoutScheduled = false;
+ if (!isValid() && !visibleItems.count()) {
+ clear();
+ return;
+ }
+ if (visibleItems.count()) {
+ qreal rowPos = visibleItems.first()->rowPos();
+ qreal colPos = visibleItems.first()->colPos();
+ int col = visibleIndex % columns;
+ if (colPos != col * colSize()) {
+ colPos = col * colSize();
+ visibleItems.first()->setPosition(colPos, rowPos);
+ }
+ for (int i = 1; i < visibleItems.count(); ++i) {
+ FxGridItem1 *item = visibleItems.at(i);
+ colPos += colSize();
+ if (colPos > colSize() * (columns-1)) {
+ colPos = 0;
+ rowPos += rowSize();
+ }
+ item->setPosition(colPos, rowPos);
+ }
+ }
+ if (header)
+ updateHeader();
+ if (footer)
+ updateFooter();
+ q->refill();
+ updateHighlight();
+ moveReason = Other;
+ if (flow == QDeclarative1GridView::LeftToRight) {
+ q->setContentHeight(endPosition() - startPosition());
+ fixupY();
+ } else {
+ q->setContentWidth(endPosition() - startPosition());
+ fixupX();
+ }
+ updateUnrequestedPositions();
+}
+
+void QDeclarative1GridViewPrivate::updateUnrequestedIndexes()
+{
+ Q_Q(QDeclarative1GridView);
+ QHash<QDeclarativeItem*,int>::iterator it;
+ for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it)
+ *it = model->indexOf(it.key(), q);
+}
+
+void QDeclarative1GridViewPrivate::updateUnrequestedPositions()
+{
+ QHash<QDeclarativeItem*,int>::const_iterator it;
+ for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it) {
+ QDeclarativeItem *item = it.key();
+ if (flow == QDeclarative1GridView::LeftToRight) {
+ item->setPos(QPointF(colPosAt(*it), rowPosAt(*it)));
+ } else {
+ if (isRightToLeftTopToBottom())
+ item->setPos(QPointF(-rowPosAt(*it)-item->width(), colPosAt(*it)));
+ else
+ item->setPos(QPointF(rowPosAt(*it), colPosAt(*it)));
+ }
+ }
+}
+
+void QDeclarative1GridViewPrivate::updateTrackedItem()
+{
+ Q_Q(QDeclarative1GridView);
+ FxGridItem1 *item = currentItem;
+ if (highlight)
+ item = highlight;
+
+ if (trackedItem && item != trackedItem) {
+ QObject::disconnect(trackedItem->item, SIGNAL(yChanged()), q, SLOT(trackedPositionChanged()));
+ QObject::disconnect(trackedItem->item, SIGNAL(xChanged()), q, SLOT(trackedPositionChanged()));
+ trackedItem = 0;
+ }
+
+ if (!trackedItem && item) {
+ trackedItem = item;
+ QObject::connect(trackedItem->item, SIGNAL(yChanged()), q, SLOT(trackedPositionChanged()));
+ QObject::connect(trackedItem->item, SIGNAL(xChanged()), q, SLOT(trackedPositionChanged()));
+ }
+ if (trackedItem)
+ q->trackedPositionChanged();
+}
+
+void QDeclarative1GridViewPrivate::createHighlight()
+{
+ Q_Q(QDeclarative1GridView);
+ bool changed = false;
+ if (highlight) {
+ if (trackedItem == highlight)
+ trackedItem = 0;
+ if (highlight->item->scene())
+ highlight->item->scene()->removeItem(highlight->item);
+ highlight->item->deleteLater();
+ delete highlight;
+ highlight = 0;
+ delete highlightXAnimator;
+ delete highlightYAnimator;
+ highlightXAnimator = 0;
+ highlightYAnimator = 0;
+ changed = true;
+ }
+
+ if (currentItem) {
+ QDeclarativeItem *item = 0;
+ if (highlightComponent) {
+ QDeclarativeContext *highlightContext = new QDeclarativeContext(qmlContext(q));
+ QObject *nobj = highlightComponent->create(highlightContext);
+ if (nobj) {
+ QDeclarative_setParent_noEvent(highlightContext, nobj);
+ item = qobject_cast<QDeclarativeItem *>(nobj);
+ if (!item)
+ delete nobj;
+ } else {
+ delete highlightContext;
+ }
+ } else {
+ item = new QDeclarativeItem;
+ QDeclarative_setParent_noEvent(item, q->contentItem());
+ item->setParentItem(q->contentItem());
+ }
+ if (item) {
+ QDeclarative_setParent_noEvent(item, q->contentItem());
+ item->setParentItem(q->contentItem());
+ highlight = new FxGridItem1(item, q);
+ if (currentItem && autoHighlight)
+ highlight->setPosition(currentItem->colPos(), currentItem->rowPos());
+ highlightXAnimator = new QSmoothedAnimation_1(q);
+ highlightXAnimator->target = QDeclarativeProperty(highlight->item, QLatin1String("x"));
+ highlightXAnimator->userDuration = highlightMoveDuration;
+ highlightYAnimator = new QSmoothedAnimation_1(q);
+ highlightYAnimator->target = QDeclarativeProperty(highlight->item, QLatin1String("y"));
+ highlightYAnimator->userDuration = highlightMoveDuration;
+ if (autoHighlight) {
+ highlightXAnimator->restart();
+ highlightYAnimator->restart();
+ }
+ changed = true;
+ }
+ }
+ if (changed)
+ emit q->highlightItemChanged();
+}
+
+void QDeclarative1GridViewPrivate::updateHighlight()
+{
+ if ((!currentItem && highlight) || (currentItem && !highlight))
+ createHighlight();
+ if (currentItem && autoHighlight && highlight && !movingHorizontally && !movingVertically) {
+ // auto-update highlight
+ highlightXAnimator->to = currentItem->item->x();
+ highlightYAnimator->to = currentItem->item->y();
+ highlight->item->setWidth(currentItem->item->width());
+ highlight->item->setHeight(currentItem->item->height());
+ highlightXAnimator->restart();
+ highlightYAnimator->restart();
+ }
+ updateTrackedItem();
+}
+
+void QDeclarative1GridViewPrivate::updateCurrent(int modelIndex)
+{
+ Q_Q(QDeclarative1GridView);
+ if (!q->isComponentComplete() || !isValid() || modelIndex < 0 || modelIndex >= model->count()) {
+ if (currentItem) {
+ currentItem->attached->setIsCurrentItem(false);
+ releaseItem(currentItem);
+ currentItem = 0;
+ currentIndex = modelIndex;
+ emit q->currentIndexChanged();
+ updateHighlight();
+ } else if (currentIndex != modelIndex) {
+ currentIndex = modelIndex;
+ emit q->currentIndexChanged();
+ }
+ return;
+ }
+
+ if (currentItem && currentIndex == modelIndex) {
+ updateHighlight();
+ return;
+ }
+
+ FxGridItem1 *oldCurrentItem = currentItem;
+ currentIndex = modelIndex;
+ currentItem = createItem(modelIndex);
+ fixCurrentVisibility = true;
+ if (oldCurrentItem && (!currentItem || oldCurrentItem->item != currentItem->item))
+ oldCurrentItem->attached->setIsCurrentItem(false);
+ if (currentItem) {
+ currentItem->setPosition(colPosAt(modelIndex), rowPosAt(modelIndex));
+ currentItem->item->setFocus(true);
+ currentItem->attached->setIsCurrentItem(true);
+ }
+ updateHighlight();
+ emit q->currentIndexChanged();
+ releaseItem(oldCurrentItem);
+}
+
+void QDeclarative1GridViewPrivate::updateFooter()
+{
+ Q_Q(QDeclarative1GridView);
+ if (!footer && footerComponent) {
+ QDeclarativeItem *item = 0;
+ QDeclarativeContext *context = new QDeclarativeContext(qmlContext(q));
+ QObject *nobj = footerComponent->create(context);
+ if (nobj) {
+ QDeclarative_setParent_noEvent(context, nobj);
+ item = qobject_cast<QDeclarativeItem *>(nobj);
+ if (!item)
+ delete nobj;
+ } else {
+ delete context;
+ }
+ if (item) {
+ QDeclarative_setParent_noEvent(item, q->contentItem());
+ item->setParentItem(q->contentItem());
+ item->setZValue(1);
+ QDeclarativeItemPrivate *itemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(item));
+ itemPrivate->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
+ footer = new FxGridItem1(item, q);
+ }
+ }
+ if (footer) {
+ qreal colOffset = 0;
+ qreal rowOffset;
+ if (isRightToLeftTopToBottom()) {
+ rowOffset = footer->item->width()-cellWidth;
+ } else {
+ rowOffset = 0;
+ if (q->effectiveLayoutDirection() == Qt::RightToLeft)
+ colOffset = footer->item->width()-cellWidth;
+ }
+ if (visibleItems.count()) {
+ qreal endPos = lastPosition();
+ if (lastVisibleIndex() == model->count()-1) {
+ footer->setPosition(colOffset, endPos + rowOffset);
+ } else {
+ qreal visiblePos = isRightToLeftTopToBottom() ? -position() : position() + size();
+ if (endPos <= visiblePos || footer->endRowPos() < endPos + rowOffset)
+ footer->setPosition(colOffset, endPos + rowOffset);
+ }
+ } else {
+ qreal endPos = 0;
+ if (header) {
+ endPos += flow == QDeclarative1GridView::LeftToRight ? header->item->height() : header->item->width();
+ }
+ footer->setPosition(colOffset, endPos);
+ }
+ }
+}
+
+void QDeclarative1GridViewPrivate::updateHeader()
+{
+ Q_Q(QDeclarative1GridView);
+ if (!header && headerComponent) {
+ QDeclarativeItem *item = 0;
+ QDeclarativeContext *context = new QDeclarativeContext(qmlContext(q));
+ QObject *nobj = headerComponent->create(context);
+ if (nobj) {
+ QDeclarative_setParent_noEvent(context, nobj);
+ item = qobject_cast<QDeclarativeItem *>(nobj);
+ if (!item)
+ delete nobj;
+ } else {
+ delete context;
+ }
+ if (item) {
+ QDeclarative_setParent_noEvent(item, q->contentItem());
+ item->setParentItem(q->contentItem());
+ item->setZValue(1);
+ QDeclarativeItemPrivate *itemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(item));
+ itemPrivate->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
+ header = new FxGridItem1(item, q);
+ }
+ }
+ if (header) {
+ qreal colOffset = 0;
+ qreal rowOffset;
+ if (isRightToLeftTopToBottom()) {
+ rowOffset = -cellWidth;
+ } else {
+ rowOffset = -headerSize();
+ if (q->effectiveLayoutDirection() == Qt::RightToLeft)
+ colOffset = header->item->width()-cellWidth;
+ }
+ if (visibleItems.count()) {
+ qreal startPos = originPosition();
+ if (visibleIndex == 0) {
+ header->setPosition(colOffset, startPos + rowOffset);
+ } else {
+ qreal tempPos = isRightToLeftTopToBottom() ? -position()-size() : position();
+ qreal headerPos = isRightToLeftTopToBottom() ? header->rowPos() + cellWidth - headerSize() : header->rowPos();
+ if (tempPos <= startPos || headerPos > startPos + rowOffset)
+ header->setPosition(colOffset, startPos + rowOffset);
+ }
+ } else {
+ header->setPosition(colOffset, 0);
+ }
+ }
+}
+
+void QDeclarative1GridViewPrivate::fixupPosition()
+{
+ moveReason = Other;
+ if (flow == QDeclarative1GridView::LeftToRight)
+ fixupY();
+ else
+ fixupX();
+}
+
+void QDeclarative1GridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
+{
+ if ((flow == QDeclarative1GridView::TopToBottom && &data == &vData)
+ || (flow == QDeclarative1GridView::LeftToRight && &data == &hData))
+ return;
+
+ fixupMode = moveReason == Mouse ? fixupMode : Immediate;
+
+ qreal highlightStart;
+ qreal highlightEnd;
+ qreal viewPos;
+ if (isRightToLeftTopToBottom()) {
+ // Handle Right-To-Left exceptions
+ viewPos = -position()-size();
+ highlightStart = highlightRangeStartValid ? size()-highlightRangeEnd : highlightRangeStart;
+ highlightEnd = highlightRangeEndValid ? size()-highlightRangeStart : highlightRangeEnd;
+ } else {
+ viewPos = position();
+ highlightStart = highlightRangeStart;
+ highlightEnd = highlightRangeEnd;
+ }
+
+ if (snapMode != QDeclarative1GridView::NoSnap) {
+ qreal tempPosition = isRightToLeftTopToBottom() ? -position()-size() : position();
+ FxGridItem1 *topItem = snapItemAt(tempPosition+highlightStart);
+ FxGridItem1 *bottomItem = snapItemAt(tempPosition+highlightEnd);
+ qreal pos;
+ if (topItem && bottomItem && haveHighlightRange && highlightRange == QDeclarative1GridView::StrictlyEnforceRange) {
+ qreal topPos = qMin(topItem->rowPos() - highlightStart, -maxExtent);
+ qreal bottomPos = qMax(bottomItem->rowPos() - highlightEnd, -minExtent);
+ pos = qAbs(data.move + topPos) < qAbs(data.move + bottomPos) ? topPos : bottomPos;
+ } else if (topItem) {
+ qreal headerPos = 0;
+ if (header)
+ headerPos = isRightToLeftTopToBottom() ? header->rowPos() + cellWidth - headerSize() : header->rowPos();
+ if (topItem->index == 0 && header && tempPosition+highlightStart < headerPos+headerSize()/2) {
+ pos = isRightToLeftTopToBottom() ? - headerPos + highlightStart - size() : headerPos - highlightStart;
+ } else {
+ if (isRightToLeftTopToBottom())
+ pos = qMax(qMin(-topItem->rowPos() + highlightStart - size(), -maxExtent), -minExtent);
+ else
+ pos = qMax(qMin(topItem->rowPos() - highlightStart, -maxExtent), -minExtent);
+ }
+ } else if (bottomItem) {
+ if (isRightToLeftTopToBottom())
+ pos = qMax(qMin(-bottomItem->rowPos() + highlightStart - size(), -maxExtent), -minExtent);
+ else
+ pos = qMax(qMin(bottomItem->rowPos() - highlightStart, -maxExtent), -minExtent);
+ } else {
+ QDeclarative1FlickablePrivate::fixup(data, minExtent, maxExtent);
+ return;
+ }
+ if (currentItem && haveHighlightRange && highlightRange == QDeclarative1GridView::StrictlyEnforceRange) {
+ updateHighlight();
+ qreal currPos = currentItem->rowPos();
+ if (isRightToLeftTopToBottom())
+ pos = -pos-size(); // Transform Pos if required
+ if (pos < currPos + rowSize() - highlightEnd)
+ pos = currPos + rowSize() - highlightEnd;
+ if (pos > currPos - highlightStart)
+ pos = currPos - highlightStart;
+ if (isRightToLeftTopToBottom())
+ pos = -pos-size(); // Untransform
+ }
+ qreal dist = qAbs(data.move + pos);
+ if (dist > 0) {
+ timeline.reset(data.move);
+ if (fixupMode != Immediate) {
+ timeline.move(data.move, -pos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2);
+ data.fixingUp = true;
+ } else {
+ timeline.set(data.move, -pos);
+ }
+ vTime = timeline.time();
+ }
+ } else if (haveHighlightRange && highlightRange == QDeclarative1GridView::StrictlyEnforceRange) {
+ if (currentItem) {
+ updateHighlight();
+ qreal pos = currentItem->rowPos();
+ if (viewPos < pos + rowSize() - highlightEnd)
+ viewPos = pos + rowSize() - highlightEnd;
+ if (viewPos > pos - highlightStart)
+ viewPos = pos - highlightStart;
+ if (isRightToLeftTopToBottom())
+ viewPos = -viewPos-size();
+ timeline.reset(data.move);
+ if (viewPos != position()) {
+ if (fixupMode != Immediate) {
+ timeline.move(data.move, -viewPos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2);
+ data.fixingUp = true;
+ } else {
+ timeline.set(data.move, -viewPos);
+ }
+ }
+ vTime = timeline.time();
+ }
+ } else {
+ QDeclarative1FlickablePrivate::fixup(data, minExtent, maxExtent);
+ }
+ data.inOvershoot = false;
+ fixupMode = Normal;
+}
+
+void QDeclarative1GridViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
+ QDeclarative1TimeLineCallback::Callback fixupCallback, qreal velocity)
+{
+ Q_Q(QDeclarative1GridView);
+ data.fixingUp = false;
+ moveReason = Mouse;
+ if ((!haveHighlightRange || highlightRange != QDeclarative1GridView::StrictlyEnforceRange)
+ && snapMode == QDeclarative1GridView::NoSnap) {
+ QDeclarative1FlickablePrivate::flick(data, minExtent, maxExtent, vSize, fixupCallback, velocity);
+ return;
+ }
+ qreal maxDistance = 0;
+ qreal dataValue = isRightToLeftTopToBottom() ? -data.move.value()+size() : data.move.value();
+ // -ve velocity means list is moving up/left
+ if (velocity > 0) {
+ if (data.move.value() < minExtent) {
+ if (snapMode == QDeclarative1GridView::SnapOneRow) {
+ if (FxGridItem1 *item = firstVisibleItem()) {
+ maxDistance = qAbs(item->rowPos() + dataValue);
+ }
+ } else {
+ maxDistance = qAbs(minExtent - data.move.value());
+ }
+ }
+ if (snapMode == QDeclarative1GridView::NoSnap && highlightRange != QDeclarative1GridView::StrictlyEnforceRange)
+ data.flickTarget = minExtent;
+ } else {
+ if (data.move.value() > maxExtent) {
+ if (snapMode == QDeclarative1GridView::SnapOneRow) {
+ qreal pos = snapPosAt(-dataValue) + (isRightToLeftTopToBottom() ? 0 : rowSize());
+ maxDistance = qAbs(pos + dataValue);
+ } else {
+ maxDistance = qAbs(maxExtent - data.move.value());
+ }
+ }
+ if (snapMode == QDeclarative1GridView::NoSnap && highlightRange != QDeclarative1GridView::StrictlyEnforceRange)
+ data.flickTarget = maxExtent;
+ }
+
+ bool overShoot = boundsBehavior == QDeclarative1Flickable::DragAndOvershootBounds;
+ qreal highlightStart = isRightToLeftTopToBottom() && highlightRangeStartValid ? size()-highlightRangeEnd : highlightRangeStart;
+
+ if (maxDistance > 0 || overShoot) {
+ // This mode requires the grid to stop exactly on a row boundary.
+ qreal v = velocity;
+ if (maxVelocity != -1 && maxVelocity < qAbs(v)) {
+ if (v < 0)
+ v = -maxVelocity;
+ else
+ v = maxVelocity;
+ }
+ qreal accel = deceleration;
+ qreal v2 = v * v;
+ qreal overshootDist = 0.0;
+ if ((maxDistance > 0.0 && v2 / (2.0f * maxDistance) < accel) || snapMode == QDeclarative1GridView::SnapOneRow) {
+ // + rowSize()/4 to encourage moving at least one item in the flick direction
+ qreal dist = v2 / (accel * 2.0) + rowSize()/4;
+ dist = qMin(dist, maxDistance);
+ if (v > 0)
+ dist = -dist;
+ qreal distTemp = isRightToLeftTopToBottom() ? -dist : dist;
+ data.flickTarget = -snapPosAt(-(dataValue - highlightStart) + distTemp) + highlightStart;
+ data.flickTarget = isRightToLeftTopToBottom() ? -data.flickTarget+size() : data.flickTarget;
+ qreal adjDist = -data.flickTarget + data.move.value();
+ if (qAbs(adjDist) > qAbs(dist)) {
+ // Prevent painfully slow flicking - adjust velocity to suit flickDeceleration
+ qreal adjv2 = accel * 2.0f * qAbs(adjDist);
+ if (adjv2 > v2) {
+ v2 = adjv2;
+ v = qSqrt(v2);
+ if (dist > 0)
+ v = -v;
+ }
+ }
+ dist = adjDist;
+ accel = v2 / (2.0f * qAbs(dist));
+ } else {
+ data.flickTarget = velocity > 0 ? minExtent : maxExtent;
+ overshootDist = overShoot ? overShootDistance(vSize) : 0;
+ }
+ timeline.reset(data.move);
+ timeline.accel(data.move, v, accel, maxDistance + overshootDist);
+ timeline.callback(QDeclarative1TimeLineCallback(&data.move, fixupCallback, this));
+ if (!flickingHorizontally && q->xflick()) {
+ flickingHorizontally = true;
+ emit q->flickingChanged();
+ emit q->flickingHorizontallyChanged();
+ emit q->flickStarted();
+ }
+ if (!flickingVertically && q->yflick()) {
+ flickingVertically = true;
+ emit q->flickingChanged();
+ emit q->flickingVerticallyChanged();
+ emit q->flickStarted();
+ }
+ } else {
+ timeline.reset(data.move);
+ fixup(data, minExtent, maxExtent);
+ }
+}
+
+
+//----------------------------------------------------------------------------
+
+/*!
+ \qmlclass GridView QDeclarative1GridView
+ \since 4.7
+ \ingroup qml-view-elements
+
+ \inherits Flickable
+ \brief The GridView item provides a grid view of items provided by a model.
+
+ A GridView displays data from models created from built-in QML elements like ListModel
+ and XmlListModel, or custom model classes defined in C++ that inherit from
+ QAbstractListModel.
+
+ A GridView has a \l model, which defines the data to be displayed, and
+ a \l delegate, which defines how the data should be displayed. Items in a
+ GridView are laid out horizontally or vertically. Grid views are inherently flickable
+ as GridView inherits from \l Flickable.
+
+ \section1 Example Usage
+
+ The following example shows the definition of a simple list model defined
+ in a file called \c ContactModel.qml:
+
+ \snippet doc/src/snippets/declarative/gridview/ContactModel.qml 0
+
+ \div {class="float-right"}
+ \inlineimage gridview-simple.png
+ \enddiv
+
+ This model can be referenced as \c ContactModel in other QML files. See \l{QML Modules}
+ for more information about creating reusable components like this.
+
+ Another component can display this model data in a GridView, as in the following
+ example, which creates a \c ContactModel component for its model, and a \l Column element
+ (containing \l Image and \l Text elements) for its delegate.
+
+ \clearfloat
+ \snippet doc/src/snippets/declarative/gridview/gridview.qml import
+ \codeline
+ \snippet doc/src/snippets/declarative/gridview/gridview.qml classdocs simple
+
+ \div {class="float-right"}
+ \inlineimage gridview-highlight.png
+ \enddiv
+
+ The view will create a new delegate for each item in the model. Note that the delegate
+ is able to access the model's \c name and \c portrait data directly.
+
+ An improved grid view is shown below. The delegate is visually improved and is moved
+ into a separate \c contactDelegate component.
+
+ \clearfloat
+ \snippet doc/src/snippets/declarative/gridview/gridview.qml classdocs advanced
+
+ The currently selected item is highlighted with a blue \l Rectangle using the \l highlight property,
+ and \c focus is set to \c true to enable keyboard navigation for the grid view.
+ The grid view itself is a focus scope (see \l{qmlfocus#Acquiring Focus and Focus Scopes}{the focus documentation page} for more details).
+
+ Delegates are instantiated as needed and may be destroyed at any time.
+ State should \e never be stored in a delegate.
+
+ GridView attaches a number of properties to the root item of the delegate, for example
+ \c {GridView.isCurrentItem}. In the following example, the root delegate item can access
+ this attached property directly as \c GridView.isCurrentItem, while the child
+ \c contactInfo object must refer to this property as \c wrapper.GridView.isCurrentItem.
+
+ \snippet doc/src/snippets/declarative/gridview/gridview.qml isCurrentItem
+
+ \note Views do not set the \l{Item::}{clip} property automatically.
+ If the view is not clipped by another item or the screen, it will be necessary
+ to set this property to true in order to clip the items that are partially or
+ fully outside the view.
+
+ \sa {declarative/modelviews/gridview}{GridView example}
+*/
+QDeclarative1GridView::QDeclarative1GridView(QDeclarativeItem *parent)
+ : QDeclarative1Flickable(*(new QDeclarative1GridViewPrivate), parent)
+{
+ Q_D(QDeclarative1GridView);
+ d->init();
+}
+
+QDeclarative1GridView::~QDeclarative1GridView()
+{
+ Q_D(QDeclarative1GridView);
+ d->clear();
+ if (d->ownModel)
+ delete d->model;
+ delete d->header;
+ delete d->footer;
+}
+
+/*!
+ \qmlattachedproperty bool GridView::isCurrentItem
+ This attached property is true if this delegate is the current item; otherwise false.
+
+ It is attached to each instance of the delegate.
+*/
+
+/*!
+ \qmlattachedproperty GridView GridView::view
+ This attached property holds the view that manages this delegate instance.
+
+ It is attached to each instance of the delegate.
+
+ \snippet doc/src/snippets/declarative/gridview/gridview.qml isCurrentItem
+*/
+
+/*!
+ \qmlattachedproperty bool GridView::delayRemove
+ This attached property holds whether the delegate may be destroyed.
+
+ It is attached to each instance of the delegate.
+
+ It is sometimes necessary to delay the destruction of an item
+ until an animation completes.
+
+ The example below ensures that the animation completes before
+ the item is removed from the grid.
+
+ \snippet doc/src/snippets/declarative/gridview/gridview.qml delayRemove
+*/
+
+/*!
+ \qmlattachedsignal GridView::onAdd()
+ This attached handler is called immediately after an item is added to the view.
+*/
+
+/*!
+ \qmlattachedsignal GridView::onRemove()
+ This attached handler is called immediately before an item is removed from the view.
+*/
+
+
+/*!
+ \qmlproperty model GridView::model
+ This property holds the model providing data for the grid.
+
+ The model provides the set of data that is used to create the items
+ in the view. Models can be created directly in QML using \l ListModel, \l XmlListModel
+ or \l VisualItemModel, or provided by C++ model classes. If a C++ model class is
+ used, it must be a subclass of \l QAbstractItemModel or a simple list.
+
+ \sa {qmlmodels}{Data Models}
+*/
+QVariant QDeclarative1GridView::model() const
+{
+ Q_D(const QDeclarative1GridView);
+ return d->modelVariant;
+}
+
+// For internal use
+int QDeclarative1GridView::modelCount() const
+{
+ Q_D(const QDeclarative1GridView);
+ return d->model->count();
+}
+
+void QDeclarative1GridView::setModel(const QVariant &model)
+{
+ Q_D(QDeclarative1GridView);
+ if (d->modelVariant == model)
+ return;
+ if (d->model) {
+ disconnect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
+ disconnect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
+ disconnect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int)));
+ disconnect(d->model, SIGNAL(modelReset()), this, SLOT(modelReset()));
+ disconnect(d->model, SIGNAL(createdItem(int,QDeclarativeItem*)), this, SLOT(createdItem(int,QDeclarativeItem*)));
+ disconnect(d->model, SIGNAL(destroyingItem(QDeclarativeItem*)), this, SLOT(destroyingItem(QDeclarativeItem*)));
+ }
+ d->clear();
+ d->modelVariant = model;
+ QObject *object = qvariant_cast<QObject*>(model);
+ QDeclarative1VisualModel *vim = 0;
+ if (object && (vim = qobject_cast<QDeclarative1VisualModel *>(object))) {
+ if (d->ownModel) {
+ delete d->model;
+ d->ownModel = false;
+ }
+ d->model = vim;
+ } else {
+ if (!d->ownModel) {
+ d->model = new QDeclarative1VisualDataModel(qmlContext(this), this);
+ d->ownModel = true;
+ }
+ if (QDeclarative1VisualDataModel *dataModel = qobject_cast<QDeclarative1VisualDataModel*>(d->model))
+ dataModel->setModel(model);
+ }
+ if (d->model) {
+ d->bufferMode = QDeclarative1GridViewPrivate::BufferBefore | QDeclarative1GridViewPrivate::BufferAfter;
+ if (isComponentComplete()) {
+ refill();
+ if ((d->currentIndex >= d->model->count() || d->currentIndex < 0) && !d->currentIndexCleared) {
+ setCurrentIndex(0);
+ } else {
+ d->moveReason = QDeclarative1GridViewPrivate::SetIndex;
+ d->updateCurrent(d->currentIndex);
+ if (d->highlight && d->currentItem) {
+ if (d->autoHighlight)
+ d->highlight->setPosition(d->currentItem->colPos(), d->currentItem->rowPos());
+ d->updateTrackedItem();
+ }
+ d->moveReason = QDeclarative1GridViewPrivate::Other;
+ }
+ }
+ connect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
+ connect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
+ connect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int)));
+ connect(d->model, SIGNAL(modelReset()), this, SLOT(modelReset()));
+ connect(d->model, SIGNAL(createdItem(int,QDeclarativeItem*)), this, SLOT(createdItem(int,QDeclarativeItem*)));
+ connect(d->model, SIGNAL(destroyingItem(QDeclarativeItem*)), this, SLOT(destroyingItem(QDeclarativeItem*)));
+ emit countChanged();
+ }
+ emit modelChanged();
+}
+
+/*!
+ \qmlproperty Component GridView::delegate
+
+ The delegate provides a template defining each item instantiated by the view.
+ The index is exposed as an accessible \c index property. Properties of the
+ model are also available depending upon the type of \l {qmlmodels}{Data Model}.
+
+ The number of elements in the delegate has a direct effect on the
+ flicking performance of the view. If at all possible, place functionality
+ that is not needed for the normal display of the delegate in a \l Loader which
+ can load additional elements when needed.
+
+ The GridView will layout the items based on the size of the root item
+ in the delegate.
+
+ \note Delegates are instantiated as needed and may be destroyed at any time.
+ State should \e never be stored in a delegate.
+*/
+QDeclarativeComponent *QDeclarative1GridView::delegate() const
+{
+ Q_D(const QDeclarative1GridView);
+ if (d->model) {
+ if (QDeclarative1VisualDataModel *dataModel = qobject_cast<QDeclarative1VisualDataModel*>(d->model))
+ return dataModel->delegate();
+ }
+
+ return 0;
+}
+
+void QDeclarative1GridView::setDelegate(QDeclarativeComponent *delegate)
+{
+ Q_D(QDeclarative1GridView);
+ if (delegate == this->delegate())
+ return;
+
+ if (!d->ownModel) {
+ d->model = new QDeclarative1VisualDataModel(qmlContext(this));
+ d->ownModel = true;
+ }
+ if (QDeclarative1VisualDataModel *dataModel = qobject_cast<QDeclarative1VisualDataModel*>(d->model)) {
+ int oldCount = dataModel->count();
+ dataModel->setDelegate(delegate);
+ if (isComponentComplete()) {
+ for (int i = 0; i < d->visibleItems.count(); ++i)
+ d->releaseItem(d->visibleItems.at(i));
+ d->visibleItems.clear();
+ d->releaseItem(d->currentItem);
+ d->currentItem = 0;
+ refill();
+ d->moveReason = QDeclarative1GridViewPrivate::SetIndex;
+ d->updateCurrent(d->currentIndex);
+ if (d->highlight && d->currentItem) {
+ if (d->autoHighlight)
+ d->highlight->setPosition(d->currentItem->colPos(), d->currentItem->rowPos());
+ d->updateTrackedItem();
+ }
+ d->moveReason = QDeclarative1GridViewPrivate::Other;
+ }
+ if (oldCount != dataModel->count())
+ emit countChanged();
+ emit delegateChanged();
+ }
+}
+
+/*!
+ \qmlproperty int GridView::currentIndex
+ \qmlproperty Item GridView::currentItem
+
+ The \c currentIndex property holds the index of the current item, and
+ \c currentItem holds the current item. Setting the currentIndex to -1
+ will clear the highlight and set currentItem to null.
+
+ If highlightFollowsCurrentItem is \c true, setting either of these
+ properties will smoothly scroll the GridView so that the current
+ item becomes visible.
+
+ Note that the position of the current item
+ may only be approximate until it becomes visible in the view.
+*/
+int QDeclarative1GridView::currentIndex() const
+{
+ Q_D(const QDeclarative1GridView);
+ return d->currentIndex;
+}
+
+void QDeclarative1GridView::setCurrentIndex(int index)
+{
+ Q_D(QDeclarative1GridView);
+ if (d->requestedIndex >= 0) // currently creating item
+ return;
+ d->currentIndexCleared = (index == -1);
+ if (index == d->currentIndex)
+ return;
+ if (isComponentComplete() && d->isValid()) {
+ d->moveReason = QDeclarative1GridViewPrivate::SetIndex;
+ d->updateCurrent(index);
+ } else {
+ d->currentIndex = index;
+ emit currentIndexChanged();
+ }
+}
+
+QDeclarativeItem *QDeclarative1GridView::currentItem()
+{
+ Q_D(QDeclarative1GridView);
+ if (!d->currentItem)
+ return 0;
+ return d->currentItem->item;
+}
+
+/*!
+ \qmlproperty Item GridView::highlightItem
+
+ This holds the highlight item created from the \l highlight component.
+
+ The highlightItem is managed by the view unless
+ \l highlightFollowsCurrentItem is set to false.
+
+ \sa highlight, highlightFollowsCurrentItem
+*/
+QDeclarativeItem *QDeclarative1GridView::highlightItem()
+{
+ Q_D(QDeclarative1GridView);
+ if (!d->highlight)
+ return 0;
+ return d->highlight->item;
+}
+
+/*!
+ \qmlproperty int GridView::count
+ This property holds the number of items in the view.
+*/
+int QDeclarative1GridView::count() const
+{
+ Q_D(const QDeclarative1GridView);
+ if (d->model)
+ return d->model->count();
+ return 0;
+}
+
+/*!
+ \qmlproperty Component GridView::highlight
+ This property holds the component to use as the highlight.
+
+ An instance of the highlight component is created for each view.
+ The geometry of the resulting component instance will be managed by the view
+ so as to stay with the current item, unless the highlightFollowsCurrentItem property is false.
+
+ \sa highlightItem, highlightFollowsCurrentItem
+*/
+QDeclarativeComponent *QDeclarative1GridView::highlight() const
+{
+ Q_D(const QDeclarative1GridView);
+ return d->highlightComponent;
+}
+
+void QDeclarative1GridView::setHighlight(QDeclarativeComponent *highlight)
+{
+ Q_D(QDeclarative1GridView);
+ if (highlight != d->highlightComponent) {
+ d->highlightComponent = highlight;
+ d->updateCurrent(d->currentIndex);
+ emit highlightChanged();
+ }
+}
+
+/*!
+ \qmlproperty bool GridView::highlightFollowsCurrentItem
+ This property sets whether the highlight is managed by the view.
+
+ If this property is true (the default value), the highlight is moved smoothly
+ to follow the current item. Otherwise, the
+ highlight is not moved by the view, and any movement must be implemented
+ by the highlight.
+
+ Here is a highlight with its motion defined by a \l {SpringAnimation} item:
+
+ \snippet doc/src/snippets/declarative/gridview/gridview.qml highlightFollowsCurrentItem
+*/
+bool QDeclarative1GridView::highlightFollowsCurrentItem() const
+{
+ Q_D(const QDeclarative1GridView);
+ return d->autoHighlight;
+}
+
+void QDeclarative1GridView::setHighlightFollowsCurrentItem(bool autoHighlight)
+{
+ Q_D(QDeclarative1GridView);
+ if (d->autoHighlight != autoHighlight) {
+ d->autoHighlight = autoHighlight;
+ if (autoHighlight) {
+ d->updateHighlight();
+ } else if (d->highlightXAnimator) {
+ d->highlightXAnimator->stop();
+ d->highlightYAnimator->stop();
+ }
+ }
+}
+
+/*!
+ \qmlproperty int GridView::highlightMoveDuration
+ This property holds the move animation duration of the highlight delegate.
+
+ highlightFollowsCurrentItem must be true for this property
+ to have effect.
+
+ The default value for the duration is 150ms.
+
+ \sa highlightFollowsCurrentItem
+*/
+int QDeclarative1GridView::highlightMoveDuration() const
+{
+ Q_D(const QDeclarative1GridView);
+ return d->highlightMoveDuration;
+}
+
+void QDeclarative1GridView::setHighlightMoveDuration(int duration)
+{
+ Q_D(QDeclarative1GridView);
+ if (d->highlightMoveDuration != duration) {
+ d->highlightMoveDuration = duration;
+ if (d->highlightYAnimator) {
+ d->highlightXAnimator->userDuration = d->highlightMoveDuration;
+ d->highlightYAnimator->userDuration = d->highlightMoveDuration;
+ }
+ emit highlightMoveDurationChanged();
+ }
+}
+
+
+/*!
+ \qmlproperty real GridView::preferredHighlightBegin
+ \qmlproperty real GridView::preferredHighlightEnd
+ \qmlproperty enumeration GridView::highlightRangeMode
+
+ These properties define the preferred range of the highlight (for the current item)
+ within the view. The \c preferredHighlightBegin value must be less than the
+ \c preferredHighlightEnd value.
+
+ These properties affect the position of the current item when the view is scrolled.
+ For example, if the currently selected item should stay in the middle of the
+ view when it is scrolled, set the \c preferredHighlightBegin and
+ \c preferredHighlightEnd values to the top and bottom coordinates of where the middle
+ item would be. If the \c currentItem is changed programmatically, the view will
+ automatically scroll so that the current item is in the middle of the view.
+ Furthermore, the behavior of the current item index will occur whether or not a
+ highlight exists.
+
+ Valid values for \c highlightRangeMode are:
+
+ \list
+ \o GridView.ApplyRange - the view attempts to maintain the highlight within the range.
+ However, the highlight can move outside of the range at the ends of the view or due
+ to mouse interaction.
+ \o GridView.StrictlyEnforceRange - the highlight never moves outside of the range.
+ The current item changes if a keyboard or mouse action would cause the highlight to move
+ outside of the range.
+ \o GridView.NoHighlightRange - this is the default value.
+ \endlist
+*/
+qreal QDeclarative1GridView::preferredHighlightBegin() const
+{
+ Q_D(const QDeclarative1GridView);
+ return d->highlightRangeStart;
+}
+
+void QDeclarative1GridView::setPreferredHighlightBegin(qreal start)
+{
+ Q_D(QDeclarative1GridView);
+ d->highlightRangeStartValid = true;
+ if (d->highlightRangeStart == start)
+ return;
+ d->highlightRangeStart = start;
+ d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
+ emit preferredHighlightBeginChanged();
+}
+
+void QDeclarative1GridView::resetPreferredHighlightBegin()
+{
+ Q_D(QDeclarative1GridView);
+ d->highlightRangeStartValid = false;
+ if (d->highlightRangeStart == 0)
+ return;
+ d->highlightRangeStart = 0;
+ emit preferredHighlightBeginChanged();
+}
+
+qreal QDeclarative1GridView::preferredHighlightEnd() const
+{
+ Q_D(const QDeclarative1GridView);
+ return d->highlightRangeEnd;
+}
+
+void QDeclarative1GridView::setPreferredHighlightEnd(qreal end)
+{
+ Q_D(QDeclarative1GridView);
+ d->highlightRangeEndValid = true;
+ if (d->highlightRangeEnd == end)
+ return;
+ d->highlightRangeEnd = end;
+ d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
+ emit preferredHighlightEndChanged();
+}
+
+void QDeclarative1GridView::resetPreferredHighlightEnd()
+{
+ Q_D(QDeclarative1GridView);
+ d->highlightRangeEndValid = false;
+ if (d->highlightRangeEnd == 0)
+ return;
+ d->highlightRangeEnd = 0;
+ emit preferredHighlightEndChanged();
+}
+
+QDeclarative1GridView::HighlightRangeMode QDeclarative1GridView::highlightRangeMode() const
+{
+ Q_D(const QDeclarative1GridView);
+ return d->highlightRange;
+}
+
+void QDeclarative1GridView::setHighlightRangeMode(HighlightRangeMode mode)
+{
+ Q_D(QDeclarative1GridView);
+ if (d->highlightRange == mode)
+ return;
+ d->highlightRange = mode;
+ d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
+ emit highlightRangeModeChanged();
+}
+
+/*!
+ \qmlproperty enumeration GridView::layoutDirection
+ This property holds the layout direction of the grid.
+
+ Possible values:
+
+ \list
+ \o Qt.LeftToRight (default) - Items will be laid out starting in the top, left corner. The flow is
+ dependent on the \l GridView::flow property.
+ \o Qt.RightToLeft - Items will be laid out starting in the top, right corner. The flow is dependent
+ on the \l GridView::flow property.
+ \endlist
+
+ \bold Note: If GridView::flow is set to GridView.LeftToRight, this is not to be confused if
+ GridView::layoutDirection is set to Qt.RightToLeft. The GridView.LeftToRight flow value simply
+ indicates that the flow is horizontal.
+*/
+
+Qt::LayoutDirection QDeclarative1GridView::layoutDirection() const
+{
+ Q_D(const QDeclarative1GridView);
+ return d->layoutDirection;
+}
+
+void QDeclarative1GridView::setLayoutDirection(Qt::LayoutDirection layoutDirection)
+{
+ Q_D(QDeclarative1GridView);
+ if (d->layoutDirection != layoutDirection) {
+ d->layoutDirection = layoutDirection;
+ d->regenerate();
+ emit layoutDirectionChanged();
+ emit effectiveLayoutDirectionChanged();
+ }
+}
+
+/*!
+ \qmlproperty enumeration GridView::effectiveLayoutDirection
+ This property holds the effective layout direction of the grid.
+
+ When using the attached property \l {LayoutMirroring::enabled}{LayoutMirroring::enabled} for locale layouts,
+ the visual layout direction of the grid will be mirrored. However, the
+ property \l {GridView::layoutDirection}{layoutDirection} will remain unchanged.
+
+ \sa GridView::layoutDirection, {LayoutMirroring}{LayoutMirroring}
+*/
+
+Qt::LayoutDirection QDeclarative1GridView::effectiveLayoutDirection() const
+{
+ Q_D(const QDeclarative1GridView);
+ if (d->effectiveLayoutMirror)
+ return d->layoutDirection == Qt::RightToLeft ? Qt::LeftToRight : Qt::RightToLeft;
+ else
+ return d->layoutDirection;
+}
+
+/*!
+ \qmlproperty enumeration GridView::flow
+ This property holds the flow of the grid.
+
+ Possible values:
+
+ \list
+ \o GridView.LeftToRight (default) - Items are laid out from left to right, and the view scrolls vertically
+ \o GridView.TopToBottom - Items are laid out from top to bottom, and the view scrolls horizontally
+ \endlist
+*/
+QDeclarative1GridView::Flow QDeclarative1GridView::flow() const
+{
+ Q_D(const QDeclarative1GridView);
+ return d->flow;
+}
+
+void QDeclarative1GridView::setFlow(Flow flow)
+{
+ Q_D(QDeclarative1GridView);
+ if (d->flow != flow) {
+ d->flow = flow;
+ if (d->flow == LeftToRight) {
+ setContentWidth(-1);
+ setFlickableDirection(QDeclarative1Flickable::VerticalFlick);
+ } else {
+ setContentHeight(-1);
+ setFlickableDirection(QDeclarative1Flickable::HorizontalFlick);
+ }
+ setContentX(0);
+ setContentY(0);
+ d->regenerate();
+ emit flowChanged();
+ }
+}
+
+/*!
+ \qmlproperty bool GridView::keyNavigationWraps
+ This property holds whether the grid wraps key navigation
+
+ If this is true, key navigation that would move the current item selection
+ past one end of the view instead wraps around and moves the selection to
+ the other end of the view.
+
+ By default, key navigation is not wrapped.
+*/
+bool QDeclarative1GridView::isWrapEnabled() const
+{
+ Q_D(const QDeclarative1GridView);
+ return d->wrap;
+}
+
+void QDeclarative1GridView::setWrapEnabled(bool wrap)
+{
+ Q_D(QDeclarative1GridView);
+ if (d->wrap == wrap)
+ return;
+ d->wrap = wrap;
+ emit keyNavigationWrapsChanged();
+}
+
+/*!
+ \qmlproperty int GridView::cacheBuffer
+ This property determines whether delegates are retained outside the
+ visible area of the view.
+
+ If non-zero the view will keep as many delegates
+ instantiated as will fit within the buffer specified. For example,
+ if in a vertical view the delegate is 20 pixels high and \c cacheBuffer is
+ set to 40, then up to 2 delegates above and 2 delegates below the visible
+ area may be retained.
+
+ Note that cacheBuffer is not a pixel buffer - it only maintains additional
+ instantiated delegates.
+
+ Setting this value can make scrolling the list smoother at the expense
+ of additional memory usage. It is not a substitute for creating efficient
+ delegates; the fewer elements in a delegate, the faster a view may be
+ scrolled.
+*/
+int QDeclarative1GridView::cacheBuffer() const
+{
+ Q_D(const QDeclarative1GridView);
+ return d->buffer;
+}
+
+void QDeclarative1GridView::setCacheBuffer(int buffer)
+{
+ Q_D(QDeclarative1GridView);
+ if (d->buffer != buffer) {
+ d->buffer = buffer;
+ if (isComponentComplete())
+ refill();
+ emit cacheBufferChanged();
+ }
+}
+
+/*!
+ \qmlproperty int GridView::cellWidth
+ \qmlproperty int GridView::cellHeight
+
+ These properties holds the width and height of each cell in the grid.
+
+ The default cell size is 100x100.
+*/
+int QDeclarative1GridView::cellWidth() const
+{
+ Q_D(const QDeclarative1GridView);
+ return d->cellWidth;
+}
+
+void QDeclarative1GridView::setCellWidth(int cellWidth)
+{
+ Q_D(QDeclarative1GridView);
+ if (cellWidth != d->cellWidth && cellWidth > 0) {
+ d->cellWidth = qMax(1, cellWidth);
+ d->updateGrid();
+ emit cellWidthChanged();
+ d->layout();
+ }
+}
+
+int QDeclarative1GridView::cellHeight() const
+{
+ Q_D(const QDeclarative1GridView);
+ return d->cellHeight;
+}
+
+void QDeclarative1GridView::setCellHeight(int cellHeight)
+{
+ Q_D(QDeclarative1GridView);
+ if (cellHeight != d->cellHeight && cellHeight > 0) {
+ d->cellHeight = qMax(1, cellHeight);
+ d->updateGrid();
+ emit cellHeightChanged();
+ d->layout();
+ }
+}
+/*!
+ \qmlproperty enumeration GridView::snapMode
+
+ This property determines how the view scrolling will settle following a drag or flick.
+ The possible values are:
+
+ \list
+ \o GridView.NoSnap (default) - the view stops anywhere within the visible area.
+ \o GridView.SnapToRow - the view settles with a row (or column for \c GridView.TopToBottom flow)
+ aligned with the start of the view.
+ \o GridView.SnapOneRow - the view will settle no more than one row (or column for \c GridView.TopToBottom flow)
+ away from the first visible row at the time the mouse button is released.
+ This mode is particularly useful for moving one page at a time.
+ \endlist
+
+*/
+QDeclarative1GridView::SnapMode QDeclarative1GridView::snapMode() const
+{
+ Q_D(const QDeclarative1GridView);
+ return d->snapMode;
+}
+
+void QDeclarative1GridView::setSnapMode(SnapMode mode)
+{
+ Q_D(QDeclarative1GridView);
+ if (d->snapMode != mode) {
+ d->snapMode = mode;
+ emit snapModeChanged();
+ }
+}
+
+/*!
+ \qmlproperty Component GridView::footer
+ This property holds the component to use as the footer.
+
+ An instance of the footer component is created for each view. The
+ footer is positioned at the end of the view, after any items.
+
+ \sa header
+*/
+QDeclarativeComponent *QDeclarative1GridView::footer() const
+{
+ Q_D(const QDeclarative1GridView);
+ return d->footerComponent;
+}
+
+void QDeclarative1GridView::setFooter(QDeclarativeComponent *footer)
+{
+ Q_D(QDeclarative1GridView);
+ if (d->footerComponent != footer) {
+ if (d->footer) {
+ if (scene())
+ scene()->removeItem(d->footer->item);
+ d->footer->item->deleteLater();
+ delete d->footer;
+ d->footer = 0;
+ }
+ d->footerComponent = footer;
+ if (isComponentComplete()) {
+ d->updateFooter();
+ d->updateGrid();
+ d->fixupPosition();
+ }
+ emit footerChanged();
+ }
+}
+
+/*!
+ \qmlproperty Component GridView::header
+ This property holds the component to use as the header.
+
+ An instance of the header component is created for each view. The
+ header is positioned at the beginning of the view, before any items.
+
+ \sa footer
+*/
+QDeclarativeComponent *QDeclarative1GridView::header() const
+{
+ Q_D(const QDeclarative1GridView);
+ return d->headerComponent;
+}
+
+void QDeclarative1GridView::setHeader(QDeclarativeComponent *header)
+{
+ Q_D(QDeclarative1GridView);
+ if (d->headerComponent != header) {
+ if (d->header) {
+ if (scene())
+ scene()->removeItem(d->header->item);
+ d->header->item->deleteLater();
+ delete d->header;
+ d->header = 0;
+ }
+ d->headerComponent = header;
+ if (isComponentComplete()) {
+ d->updateHeader();
+ d->updateFooter();
+ d->updateGrid();
+ d->fixupPosition();
+ }
+ emit headerChanged();
+ }
+}
+
+void QDeclarative1GridView::setContentX(qreal pos)
+{
+ Q_D(QDeclarative1GridView);
+ // Positioning the view manually should override any current movement state
+ d->moveReason = QDeclarative1GridViewPrivate::Other;
+ QDeclarative1Flickable::setContentX(pos);
+}
+
+void QDeclarative1GridView::setContentY(qreal pos)
+{
+ Q_D(QDeclarative1GridView);
+ // Positioning the view manually should override any current movement state
+ d->moveReason = QDeclarative1GridViewPrivate::Other;
+ QDeclarative1Flickable::setContentY(pos);
+}
+
+bool QDeclarative1GridView::event(QEvent *event)
+{
+ Q_D(QDeclarative1GridView);
+ if (event->type() == QEvent::User) {
+ d->layout();
+ return true;
+ }
+
+ return QDeclarative1Flickable::event(event);
+}
+
+void QDeclarative1GridView::viewportMoved()
+{
+ Q_D(QDeclarative1GridView);
+ QDeclarative1Flickable::viewportMoved();
+ if (!d->itemCount)
+ return;
+ d->lazyRelease = true;
+ if (d->flickingHorizontally || d->flickingVertically) {
+ if (yflick()) {
+ if (d->vData.velocity > 0)
+ d->bufferMode = QDeclarative1GridViewPrivate::BufferBefore;
+ else if (d->vData.velocity < 0)
+ d->bufferMode = QDeclarative1GridViewPrivate::BufferAfter;
+ }
+
+ if (xflick()) {
+ if (d->hData.velocity > 0)
+ d->bufferMode = QDeclarative1GridViewPrivate::BufferBefore;
+ else if (d->hData.velocity < 0)
+ d->bufferMode = QDeclarative1GridViewPrivate::BufferAfter;
+ }
+ }
+ refill();
+ if (d->flickingHorizontally || d->flickingVertically || d->movingHorizontally || d->movingVertically)
+ d->moveReason = QDeclarative1GridViewPrivate::Mouse;
+ if (d->moveReason != QDeclarative1GridViewPrivate::SetIndex) {
+ if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) {
+ // reposition highlight
+ qreal pos = d->highlight->rowPos();
+ qreal viewPos;
+ qreal highlightStart;
+ qreal highlightEnd;
+ if (d->isRightToLeftTopToBottom()) {
+ highlightStart = d->highlightRangeStartValid ? d->size()-d->highlightRangeEnd : d->highlightRangeStart;
+ highlightEnd = d->highlightRangeEndValid ? d->size()-d->highlightRangeStart : d->highlightRangeEnd;
+ viewPos = -d->position()-d->size();
+ } else {
+ highlightStart = d->highlightRangeStart;
+ highlightEnd = d->highlightRangeEnd;
+ viewPos = d->position();
+ }
+ if (pos > viewPos + highlightEnd - d->rowSize())
+ pos = viewPos + highlightEnd - d->rowSize();
+ if (pos < viewPos + highlightStart)
+ pos = viewPos + highlightStart;
+
+ d->highlight->setPosition(d->highlight->colPos(), qRound(pos));
+
+ // update current index
+ int idx = d->snapIndex();
+ if (idx >= 0 && idx != d->currentIndex) {
+ d->updateCurrent(idx);
+ if (d->currentItem && d->currentItem->colPos() != d->highlight->colPos() && d->autoHighlight) {
+ if (d->flow == LeftToRight)
+ d->highlightXAnimator->to = d->currentItem->item->x();
+ else
+ d->highlightYAnimator->to = d->currentItem->item->y();
+ }
+ }
+ }
+ }
+}
+
+qreal QDeclarative1GridView::minYExtent() const
+{
+ Q_D(const QDeclarative1GridView);
+ if (d->flow == QDeclarative1GridView::TopToBottom)
+ return QDeclarative1Flickable::minYExtent();
+ qreal extent = -d->startPosition();
+ if (d->header && d->visibleItems.count())
+ extent += d->header->item->height();
+ if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
+ extent += d->highlightRangeStart;
+ extent = qMax(extent, -(d->rowPosAt(0) + d->rowSize() - d->highlightRangeEnd));
+ }
+ return extent;
+}
+
+qreal QDeclarative1GridView::maxYExtent() const
+{
+ Q_D(const QDeclarative1GridView);
+ if (d->flow == QDeclarative1GridView::TopToBottom)
+ return QDeclarative1Flickable::maxYExtent();
+ qreal extent;
+ if (!d->model || !d->model->count()) {
+ extent = 0;
+ } else if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
+ extent = -(d->rowPosAt(d->model->count()-1) - d->highlightRangeStart);
+ if (d->highlightRangeEnd != d->highlightRangeStart)
+ extent = qMin(extent, -(d->endPosition() - d->highlightRangeEnd + 1));
+ } else {
+ extent = -(d->endPosition() - height());
+ }
+ if (d->footer)
+ extent -= d->footer->item->height();
+ const qreal minY = minYExtent();
+ if (extent > minY)
+ extent = minY;
+ return extent;
+}
+
+qreal QDeclarative1GridView::minXExtent() const
+{
+ Q_D(const QDeclarative1GridView);
+ if (d->flow == QDeclarative1GridView::LeftToRight)
+ return QDeclarative1Flickable::minXExtent();
+ qreal extent = -d->startPosition();
+ qreal highlightStart;
+ qreal highlightEnd;
+ qreal endPositionFirstItem;
+ if (d->isRightToLeftTopToBottom()) {
+ endPositionFirstItem = d->rowPosAt(d->model->count()-1);
+ highlightStart = d->highlightRangeStartValid
+ ? d->highlightRangeStart - (d->lastPosition()-endPositionFirstItem)
+ : d->size() - (d->lastPosition()-endPositionFirstItem);
+ highlightEnd = d->highlightRangeEndValid ? d->highlightRangeEnd : d->size();
+ if (d->footer && d->visibleItems.count())
+ extent += d->footer->item->width();
+ } else {
+ endPositionFirstItem = d->rowPosAt(0)+d->rowSize();
+ highlightStart = d->highlightRangeStart;
+ highlightEnd = d->highlightRangeEnd;
+ if (d->header && d->visibleItems.count())
+ extent += d->header->item->width();
+ }
+ if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
+ extent += highlightStart;
+ extent = qMax(extent, -(endPositionFirstItem - highlightEnd));
+ }
+ return extent;
+}
+
+qreal QDeclarative1GridView::maxXExtent() const
+{
+ Q_D(const QDeclarative1GridView);
+ if (d->flow == QDeclarative1GridView::LeftToRight)
+ return QDeclarative1Flickable::maxXExtent();
+ qreal extent;
+ qreal highlightStart;
+ qreal highlightEnd;
+ qreal lastItemPosition = 0;
+ if (d->isRightToLeftTopToBottom()){
+ highlightStart = d->highlightRangeStartValid ? d->highlightRangeEnd : d->size();
+ highlightEnd = d->highlightRangeEndValid ? d->highlightRangeStart : d->size();
+ lastItemPosition = d->endPosition();
+ } else {
+ highlightStart = d->highlightRangeStart;
+ highlightEnd = d->highlightRangeEnd;
+ lastItemPosition = 0;
+ if (d->model && d->model->count())
+ lastItemPosition = d->rowPosAt(d->model->count()-1);
+ }
+ if (!d->model || !d->model->count()) {
+ extent = 0;
+ } else if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
+ extent = -(lastItemPosition - highlightStart);
+ if (highlightEnd != highlightStart)
+ extent = d->isRightToLeftTopToBottom()
+ ? qMax(extent, -(d->endPosition() - highlightEnd + 1))
+ : qMin(extent, -(d->endPosition() - highlightEnd + 1));
+ } else {
+ extent = -(d->endPosition() - width());
+ }
+ if (d->isRightToLeftTopToBottom()) {
+ if (d->header)
+ extent -= d->header->item->width();
+ } else {
+ if (d->footer)
+ extent -= d->footer->item->width();
+ }
+
+ const qreal minX = minXExtent();
+ if (extent > minX)
+ extent = minX;
+ return extent;
+}
+
+void QDeclarative1GridView::keyPressEvent(QKeyEvent *event)
+{
+ Q_D(QDeclarative1GridView);
+ keyPressPreHandler(event);
+ if (event->isAccepted())
+ return;
+ if (d->model && d->model->count() && d->interactive) {
+ d->moveReason = QDeclarative1GridViewPrivate::SetIndex;
+ int oldCurrent = currentIndex();
+ switch (event->key()) {
+ case Qt::Key_Up:
+ moveCurrentIndexUp();
+ break;
+ case Qt::Key_Down:
+ moveCurrentIndexDown();
+ break;
+ case Qt::Key_Left:
+ moveCurrentIndexLeft();
+ break;
+ case Qt::Key_Right:
+ moveCurrentIndexRight();
+ break;
+ default:
+ break;
+ }
+ if (oldCurrent != currentIndex()) {
+ event->accept();
+ return;
+ }
+ }
+ d->moveReason = QDeclarative1GridViewPrivate::Other;
+ event->ignore();
+ QDeclarative1Flickable::keyPressEvent(event);
+}
+
+/*!
+ \qmlmethod GridView::moveCurrentIndexUp()
+
+ Move the currentIndex up one item in the view.
+ The current index will wrap if keyNavigationWraps is true and it
+ is currently at the end. This method has no effect if the \l count is zero.
+
+ \bold Note: methods should only be called after the Component has completed.
+*/
+void QDeclarative1GridView::moveCurrentIndexUp()
+{
+ Q_D(QDeclarative1GridView);
+ const int count = d->model ? d->model->count() : 0;
+ if (!count)
+ return;
+ if (d->flow == QDeclarative1GridView::LeftToRight) {
+ if (currentIndex() >= d->columns || d->wrap) {
+ int index = currentIndex() - d->columns;
+ setCurrentIndex((index >= 0 && index < count) ? index : count-1);
+ }
+ } else {
+ if (currentIndex() > 0 || d->wrap) {
+ int index = currentIndex() - 1;
+ setCurrentIndex((index >= 0 && index < count) ? index : count-1);
+ }
+ }
+}
+
+/*!
+ \qmlmethod GridView::moveCurrentIndexDown()
+
+ Move the currentIndex down one item in the view.
+ The current index will wrap if keyNavigationWraps is true and it
+ is currently at the end. This method has no effect if the \l count is zero.
+
+ \bold Note: methods should only be called after the Component has completed.
+*/
+void QDeclarative1GridView::moveCurrentIndexDown()
+{
+ Q_D(QDeclarative1GridView);
+ const int count = d->model ? d->model->count() : 0;
+ if (!count)
+ return;
+ if (d->flow == QDeclarative1GridView::LeftToRight) {
+ if (currentIndex() < count - d->columns || d->wrap) {
+ int index = currentIndex()+d->columns;
+ setCurrentIndex((index >= 0 && index < count) ? index : 0);
+ }
+ } else {
+ if (currentIndex() < count - 1 || d->wrap) {
+ int index = currentIndex() + 1;
+ setCurrentIndex((index >= 0 && index < count) ? index : 0);
+ }
+ }
+}
+
+/*!
+ \qmlmethod GridView::moveCurrentIndexLeft()
+
+ Move the currentIndex left one item in the view.
+ The current index will wrap if keyNavigationWraps is true and it
+ is currently at the end. This method has no effect if the \l count is zero.
+
+ \bold Note: methods should only be called after the Component has completed.
+*/
+void QDeclarative1GridView::moveCurrentIndexLeft()
+{
+ Q_D(QDeclarative1GridView);
+ const int count = d->model ? d->model->count() : 0;
+ if (!count)
+ return;
+
+ if (effectiveLayoutDirection() == Qt::LeftToRight) {
+ if (d->flow == QDeclarative1GridView::LeftToRight) {
+ if (currentIndex() > 0 || d->wrap) {
+ int index = currentIndex() - 1;
+ setCurrentIndex((index >= 0 && index < count) ? index : count-1);
+ }
+ } else {
+ if (currentIndex() >= d->columns || d->wrap) {
+ int index = currentIndex() - d->columns;
+ setCurrentIndex((index >= 0 && index < count) ? index : count-1);
+ }
+ }
+ } else {
+ if (d->flow == QDeclarative1GridView::LeftToRight) {
+ if (currentIndex() < count - 1 || d->wrap) {
+ int index = currentIndex() + 1;
+ setCurrentIndex((index >= 0 && index < count) ? index : 0);
+ }
+ } else {
+ if (currentIndex() < count - d->columns || d->wrap) {
+ int index = currentIndex() + d->columns;
+ setCurrentIndex((index >= 0 && index < count) ? index : 0);
+ }
+ }
+ }
+}
+
+/*!
+ \qmlmethod GridView::moveCurrentIndexRight()
+
+ Move the currentIndex right one item in the view.
+ The current index will wrap if keyNavigationWraps is true and it
+ is currently at the end. This method has no effect if the \l count is zero.
+
+ \bold Note: methods should only be called after the Component has completed.
+*/
+void QDeclarative1GridView::moveCurrentIndexRight()
+{
+ Q_D(QDeclarative1GridView);
+ const int count = d->model ? d->model->count() : 0;
+ if (!count)
+ return;
+
+ if (effectiveLayoutDirection() == Qt::LeftToRight) {
+ if (d->flow == QDeclarative1GridView::LeftToRight) {
+ if (currentIndex() < count - 1 || d->wrap) {
+ int index = currentIndex() + 1;
+ setCurrentIndex((index >= 0 && index < count) ? index : 0);
+ }
+ } else {
+ if (currentIndex() < count - d->columns || d->wrap) {
+ int index = currentIndex()+d->columns;
+ setCurrentIndex((index >= 0 && index < count) ? index : 0);
+ }
+ }
+ } else {
+ if (d->flow == QDeclarative1GridView::LeftToRight) {
+ if (currentIndex() > 0 || d->wrap) {
+ int index = currentIndex() - 1;
+ setCurrentIndex((index >= 0 && index < count) ? index : count-1);
+ }
+ } else {
+ if (currentIndex() >= d->columns || d->wrap) {
+ int index = currentIndex() - d->columns;
+ setCurrentIndex((index >= 0 && index < count) ? index : count-1);
+ }
+ }
+ }
+}
+
+void QDeclarative1GridViewPrivate::positionViewAtIndex(int index, int mode)
+{
+ Q_Q(QDeclarative1GridView);
+ if (!isValid())
+ return;
+ if (mode < QDeclarative1GridView::Beginning || mode > QDeclarative1GridView::Contain)
+ return;
+
+ int idx = qMax(qMin(index, model->count()-1), 0);
+
+ if (layoutScheduled)
+ layout();
+ qreal pos = isRightToLeftTopToBottom() ? -position() - size() : position();
+ FxGridItem1 *item = visibleItem(idx);
+ qreal maxExtent;
+ if (flow == QDeclarative1GridView::LeftToRight)
+ maxExtent = -q->maxYExtent();
+ else
+ maxExtent = isRightToLeftTopToBottom() ? q->minXExtent()-size() : -q->maxXExtent();
+
+ if (!item) {
+ int itemPos = rowPosAt(idx);
+ // save the currently visible items in case any of them end up visible again
+ QList<FxGridItem1*> oldVisible = visibleItems;
+ visibleItems.clear();
+ visibleIndex = idx - idx % columns;
+ if (flow == QDeclarative1GridView::LeftToRight)
+ maxExtent = -q->maxYExtent();
+ else
+ maxExtent = isRightToLeftTopToBottom() ? q->minXExtent()-size() : -q->maxXExtent();
+ setPosition(qMin(qreal(itemPos), maxExtent));
+ // now release the reference to all the old visible items.
+ for (int i = 0; i < oldVisible.count(); ++i)
+ releaseItem(oldVisible.at(i));
+ item = visibleItem(idx);
+ }
+ if (item) {
+ qreal itemPos = item->rowPos();
+ switch (mode) {
+ case QDeclarative1GridView::Beginning:
+ pos = itemPos;
+ if (index < 0 && header) {
+ pos -= flow == QDeclarative1GridView::LeftToRight
+ ? header->item->height()
+ : header->item->width();
+ }
+ break;
+ case QDeclarative1GridView::Center:
+ pos = itemPos - (size() - rowSize())/2;
+ break;
+ case QDeclarative1GridView::End:
+ pos = itemPos - size() + rowSize();
+ if (index >= model->count() && footer) {
+ pos += flow == QDeclarative1GridView::LeftToRight
+ ? footer->item->height()
+ : footer->item->width();
+ }
+ break;
+ case QDeclarative1GridView::Visible:
+ if (itemPos > pos + size())
+ pos = itemPos - size() + rowSize();
+ else if (item->endRowPos() < pos)
+ pos = itemPos;
+ break;
+ case QDeclarative1GridView::Contain:
+ if (item->endRowPos() > pos + size())
+ pos = itemPos - size() + rowSize();
+ if (itemPos < pos)
+ pos = itemPos;
+ }
+
+ pos = qMin(pos, maxExtent);
+ qreal minExtent;
+ if (flow == QDeclarative1GridView::LeftToRight)
+ minExtent = -q->minYExtent();
+ else
+ minExtent = isRightToLeftTopToBottom() ? q->maxXExtent()-size() : -q->minXExtent();
+ pos = qMax(pos, minExtent);
+ moveReason = QDeclarative1GridViewPrivate::Other;
+ q->cancelFlick();
+ setPosition(pos);
+ }
+ fixupPosition();
+}
+
+/*!
+ \qmlmethod GridView::positionViewAtIndex(int index, PositionMode mode)
+
+ Positions the view such that the \a index is at the position specified by
+ \a mode:
+
+ \list
+ \o GridView.Beginning - position item at the top (or left for \c GridView.TopToBottom flow) of the view.
+ \o GridView.Center - position item in the center of the view.
+ \o GridView.End - position item at bottom (or right for horizontal orientation) of the view.
+ \o GridView.Visible - if any part of the item is visible then take no action, otherwise
+ bring the item into view.
+ \o GridView.Contain - ensure the entire item is visible. If the item is larger than
+ the view the item is positioned at the top (or left for \c GridView.TopToBottom flow) of the view.
+ \endlist
+
+ If positioning the view at the index would cause empty space to be displayed at
+ the beginning or end of the view, the view will be positioned at the boundary.
+
+ It is not recommended to use \l {Flickable::}{contentX} or \l {Flickable::}{contentY} to position the view
+ at a particular index. This is unreliable since removing items from the start
+ of the view does not cause all other items to be repositioned.
+ The correct way to bring an item into view is with \c positionViewAtIndex.
+
+ \bold Note: methods should only be called after the Component has completed. To position
+ the view at startup, this method should be called by Component.onCompleted. For
+ example, to position the view at the end:
+
+ \code
+ Component.onCompleted: positionViewAtIndex(count - 1, GridView.Beginning)
+ \endcode
+*/
+void QDeclarative1GridView::positionViewAtIndex(int index, int mode)
+{
+ Q_D(QDeclarative1GridView);
+ if (!d->isValid() || index < 0 || index >= d->model->count())
+ return;
+ d->positionViewAtIndex(index, mode);
+}
+
+/*!
+ \qmlmethod GridView::positionViewAtBeginning()
+ \qmlmethod GridView::positionViewAtEnd()
+ \since Quick 1.1
+
+ Positions the view at the beginning or end, taking into account any header or footer.
+
+ It is not recommended to use \l {Flickable::}{contentX} or \l {Flickable::}{contentY} to position the view
+ at a particular index. This is unreliable since removing items from the start
+ of the list does not cause all other items to be repositioned, and because
+ the actual start of the view can vary based on the size of the delegates.
+
+ \bold Note: methods should only be called after the Component has completed. To position
+ the view at startup, this method should be called by Component.onCompleted. For
+ example, to position the view at the end on startup:
+
+ \code
+ Component.onCompleted: positionViewAtEnd()
+ \endcode
+*/
+void QDeclarative1GridView::positionViewAtBeginning()
+{
+ Q_D(QDeclarative1GridView);
+ if (!d->isValid())
+ return;
+ d->positionViewAtIndex(-1, Beginning);
+}
+
+void QDeclarative1GridView::positionViewAtEnd()
+{
+ Q_D(QDeclarative1GridView);
+ if (!d->isValid())
+ return;
+ d->positionViewAtIndex(d->model->count(), End);
+}
+
+/*!
+ \qmlmethod int GridView::indexAt(int x, int y)
+
+ Returns the index of the visible item containing the point \a x, \a y in content
+ coordinates. If there is no item at the point specified, or the item is
+ not visible -1 is returned.
+
+ If the item is outside the visible area, -1 is returned, regardless of
+ whether an item will exist at that point when scrolled into view.
+
+ \bold Note: methods should only be called after the Component has completed.
+*/
+int QDeclarative1GridView::indexAt(qreal x, qreal y) const
+{
+ Q_D(const QDeclarative1GridView);
+ for (int i = 0; i < d->visibleItems.count(); ++i) {
+ const FxGridItem1 *listItem = d->visibleItems.at(i);
+ if(listItem->contains(x, y))
+ return listItem->index;
+ }
+
+ return -1;
+}
+
+void QDeclarative1GridView::componentComplete()
+{
+ Q_D(QDeclarative1GridView);
+ QDeclarative1Flickable::componentComplete();
+ d->updateHeader();
+ d->updateFooter();
+ d->updateGrid();
+ if (d->isValid()) {
+ refill();
+ d->moveReason = QDeclarative1GridViewPrivate::SetIndex;
+ if (d->currentIndex < 0 && !d->currentIndexCleared)
+ d->updateCurrent(0);
+ else
+ d->updateCurrent(d->currentIndex);
+ if (d->highlight && d->currentItem) {
+ if (d->autoHighlight)
+ d->highlight->setPosition(d->currentItem->colPos(), d->currentItem->rowPos());
+ d->updateTrackedItem();
+ }
+ d->moveReason = QDeclarative1GridViewPrivate::Other;
+ d->fixupPosition();
+ }
+}
+
+void QDeclarative1GridView::trackedPositionChanged()
+{
+ Q_D(QDeclarative1GridView);
+ if (!d->trackedItem || !d->currentItem)
+ return;
+ if (d->moveReason == QDeclarative1GridViewPrivate::SetIndex) {
+ const qreal trackedPos = d->trackedItem->rowPos();
+ qreal viewPos;
+ qreal highlightStart;
+ qreal highlightEnd;
+ if (d->isRightToLeftTopToBottom()) {
+ viewPos = -d->position()-d->size();
+ highlightStart = d->highlightRangeStartValid ? d->size()-d->highlightRangeEnd : d->highlightRangeStart;
+ highlightEnd = d->highlightRangeEndValid ? d->size()-d->highlightRangeStart : d->highlightRangeEnd;
+ } else {
+ viewPos = d->position();
+ highlightStart = d->highlightRangeStart;
+ highlightEnd = d->highlightRangeEnd;
+ }
+ qreal pos = viewPos;
+ if (d->haveHighlightRange) {
+ if (d->highlightRange == StrictlyEnforceRange) {
+ if (trackedPos > pos + highlightEnd - d->rowSize())
+ pos = trackedPos - highlightEnd + d->rowSize();
+ if (trackedPos < pos + highlightStart)
+ pos = trackedPos - highlightStart;
+ } else {
+ if (trackedPos < d->startPosition() + highlightStart) {
+ pos = d->startPosition();
+ } else if (d->trackedItem->endRowPos() > d->endPosition() - d->size() + highlightEnd) {
+ pos = d->endPosition() - d->size() + 1;
+ if (pos < d->startPosition())
+ pos = d->startPosition();
+ } else {
+ if (trackedPos < viewPos + highlightStart) {
+ pos = trackedPos - highlightStart;
+ } else if (trackedPos > viewPos + highlightEnd - d->rowSize()) {
+ pos = trackedPos - highlightEnd + d->rowSize();
+ }
+ }
+ }
+ } else {
+ if (trackedPos < viewPos && d->currentItem->rowPos() < viewPos) {
+ pos = qMax(trackedPos, d->currentItem->rowPos());
+ } else if (d->trackedItem->endRowPos() >= viewPos + d->size()
+ && d->currentItem->endRowPos() >= viewPos + d->size()) {
+ if (d->trackedItem->endRowPos() <= d->currentItem->endRowPos()) {
+ pos = d->trackedItem->endRowPos() - d->size() + 1;
+ if (d->rowSize() > d->size())
+ pos = trackedPos;
+ } else {
+ pos = d->currentItem->endRowPos() - d->size() + 1;
+ if (d->rowSize() > d->size())
+ pos = d->currentItem->rowPos();
+ }
+ }
+ }
+ if (viewPos != pos) {
+ cancelFlick();
+ d->calcVelocity = true;
+ d->setPosition(pos);
+ d->calcVelocity = false;
+ }
+ }
+}
+
+void QDeclarative1GridView::itemsInserted(int modelIndex, int count)
+{
+ Q_D(QDeclarative1GridView);
+ if (!isComponentComplete())
+ return;
+
+ int index = d->visibleItems.count() ? d->mapFromModel(modelIndex) : 0;
+ if (index < 0) {
+ int i = d->visibleItems.count() - 1;
+ while (i > 0 && d->visibleItems.at(i)->index == -1)
+ --i;
+ if (d->visibleItems.at(i)->index + 1 == modelIndex) {
+ // Special case of appending an item to the model.
+ index = d->visibleIndex + d->visibleItems.count();
+ } else {
+ if (modelIndex <= d->visibleIndex) {
+ // Insert before visible items
+ d->visibleIndex += count;
+ for (int i = 0; i < d->visibleItems.count(); ++i) {
+ FxGridItem1 *listItem = d->visibleItems.at(i);
+ if (listItem->index != -1 && listItem->index >= modelIndex)
+ listItem->index += count;
+ }
+ }
+ if (d->currentIndex >= modelIndex) {
+ // adjust current item index
+ d->currentIndex += count;
+ if (d->currentItem)
+ d->currentItem->index = d->currentIndex;
+ emit currentIndexChanged();
+ }
+ d->scheduleLayout();
+ d->itemCount += count;
+ emit countChanged();
+ return;
+ }
+ }
+
+ int insertCount = count;
+ if (index < d->visibleIndex && d->visibleItems.count()) {
+ insertCount -= d->visibleIndex - index;
+ index = d->visibleIndex;
+ modelIndex = d->visibleIndex;
+ }
+
+ qreal tempPos = d->isRightToLeftTopToBottom() ? -d->position()-d->size()+d->width()+1 : d->position();
+ int to = d->buffer+tempPos+d->size()-1;
+ int colPos = 0;
+ int rowPos = 0;
+ if (d->visibleItems.count()) {
+ index -= d->visibleIndex;
+ if (index < d->visibleItems.count()) {
+ colPos = d->visibleItems.at(index)->colPos();
+ rowPos = d->visibleItems.at(index)->rowPos();
+ } else {
+ // appending items to visible list
+ colPos = d->visibleItems.at(index-1)->colPos() + d->colSize();
+ rowPos = d->visibleItems.at(index-1)->rowPos();
+ if (colPos > d->colSize() * (d->columns-1)) {
+ colPos = 0;
+ rowPos += d->rowSize();
+ }
+ }
+ } else if (d->itemCount == 0 && d->header) {
+ rowPos = d->headerSize();
+ }
+
+ // Update the indexes of the following visible items.
+ for (int i = 0; i < d->visibleItems.count(); ++i) {
+ FxGridItem1 *listItem = d->visibleItems.at(i);
+ if (listItem->index != -1 && listItem->index >= modelIndex)
+ listItem->index += count;
+ }
+
+ bool addedVisible = false;
+ QList<FxGridItem1*> added;
+ int i = 0;
+ while (i < insertCount && rowPos <= to + d->rowSize()*(d->columns - (colPos/d->colSize()))/qreal(d->columns)) {
+ if (!addedVisible) {
+ d->scheduleLayout();
+ addedVisible = true;
+ }
+ FxGridItem1 *item = d->createItem(modelIndex + i);
+ d->visibleItems.insert(index, item);
+ item->setPosition(colPos, rowPos);
+ added.append(item);
+ colPos += d->colSize();
+ if (colPos > d->colSize() * (d->columns-1)) {
+ colPos = 0;
+ rowPos += d->rowSize();
+ }
+ ++index;
+ ++i;
+ }
+ if (i < insertCount) {
+ // We didn't insert all our new items, which means anything
+ // beyond the current index is not visible - remove it.
+ while (d->visibleItems.count() > index) {
+ d->releaseItem(d->visibleItems.takeLast());
+ }
+ }
+
+ // update visibleIndex
+ d->visibleIndex = 0;
+ for (QList<FxGridItem1*>::Iterator it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
+ if ((*it)->index != -1) {
+ d->visibleIndex = (*it)->index;
+ break;
+ }
+ }
+
+ if (d->itemCount && d->currentIndex >= modelIndex) {
+ // adjust current item index
+ d->currentIndex += count;
+ if (d->currentItem) {
+ d->currentItem->index = d->currentIndex;
+ d->currentItem->setPosition(d->colPosAt(d->currentIndex), d->rowPosAt(d->currentIndex));
+ }
+ emit currentIndexChanged();
+ } else if (d->itemCount == 0 && (!d->currentIndex || (d->currentIndex < 0 && !d->currentIndexCleared))) {
+ setCurrentIndex(0);
+ }
+
+ // everything is in order now - emit add() signal
+ for (int j = 0; j < added.count(); ++j)
+ added.at(j)->attached->emitAdd();
+
+ d->itemCount += count;
+ emit countChanged();
+}
+
+void QDeclarative1GridView::itemsRemoved(int modelIndex, int count)
+{
+ Q_D(QDeclarative1GridView);
+ if (!isComponentComplete())
+ return;
+
+ d->itemCount -= count;
+ bool currentRemoved = d->currentIndex >= modelIndex && d->currentIndex < modelIndex + count;
+ bool removedVisible = false;
+
+ // Remove the items from the visible list, skipping anything already marked for removal
+ QList<FxGridItem1*>::Iterator it = d->visibleItems.begin();
+ while (it != d->visibleItems.end()) {
+ FxGridItem1 *item = *it;
+ if (item->index == -1 || item->index < modelIndex) {
+ // already removed, or before removed items
+ if (item->index < modelIndex && !removedVisible) {
+ d->scheduleLayout();
+ removedVisible = true;
+ }
+ ++it;
+ } else if (item->index >= modelIndex + count) {
+ // after removed items
+ item->index -= count;
+ ++it;
+ } else {
+ // removed item
+ if (!removedVisible) {
+ d->scheduleLayout();
+ removedVisible = true;
+ }
+ item->attached->emitRemove();
+ if (item->attached->delayRemove()) {
+ item->index = -1;
+ connect(item->attached, SIGNAL(delayRemoveChanged()), this, SLOT(destroyRemoved()), Qt::QueuedConnection);
+ ++it;
+ } else {
+ it = d->visibleItems.erase(it);
+ d->releaseItem(item);
+ }
+ }
+ }
+
+ // fix current
+ if (d->currentIndex >= modelIndex + count) {
+ d->currentIndex -= count;
+ if (d->currentItem)
+ d->currentItem->index -= count;
+ emit currentIndexChanged();
+ } else if (currentRemoved) {
+ // current item has been removed.
+ d->releaseItem(d->currentItem);
+ d->currentItem = 0;
+ d->currentIndex = -1;
+ if (d->itemCount)
+ d->updateCurrent(qMin(modelIndex, d->itemCount-1));
+ else
+ emit currentIndexChanged();
+ }
+
+ // update visibleIndex
+ d->visibleIndex = 0;
+ for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
+ if ((*it)->index != -1) {
+ d->visibleIndex = (*it)->index;
+ break;
+ }
+ }
+
+ if (removedVisible && d->visibleItems.isEmpty()) {
+ d->timeline.clear();
+ if (d->itemCount == 0) {
+ d->setPosition(0);
+ d->updateHeader();
+ d->updateFooter();
+ update();
+ }
+ }
+
+ emit countChanged();
+}
+
+void QDeclarative1GridView::destroyRemoved()
+{
+ Q_D(QDeclarative1GridView);
+ for (QList<FxGridItem1*>::Iterator it = d->visibleItems.begin();
+ it != d->visibleItems.end();) {
+ FxGridItem1 *listItem = *it;
+ if (listItem->index == -1 && listItem->attached->delayRemove() == false) {
+ d->releaseItem(listItem);
+ it = d->visibleItems.erase(it);
+ } else {
+ ++it;
+ }
+ }
+
+ // Correct the positioning of the items
+ d->layout();
+}
+
+void QDeclarative1GridView::itemsMoved(int from, int to, int count)
+{
+ Q_D(QDeclarative1GridView);
+ if (!isComponentComplete())
+ return;
+ QHash<int,FxGridItem1*> moved;
+
+ FxGridItem1 *firstItem = d->firstVisibleItem();
+
+ QList<FxGridItem1*>::Iterator it = d->visibleItems.begin();
+ while (it != d->visibleItems.end()) {
+ FxGridItem1 *item = *it;
+ if (item->index >= from && item->index < from + count) {
+ // take the items that are moving
+ item->index += (to-from);
+ moved.insert(item->index, item);
+ it = d->visibleItems.erase(it);
+ } else {
+ if (item->index > from && item->index != -1) {
+ // move everything after the moved items.
+ item->index -= count;
+ if (item->index < d->visibleIndex)
+ d->visibleIndex = item->index;
+ }
+ ++it;
+ }
+ }
+
+ int remaining = count;
+ int endIndex = d->visibleIndex;
+ it = d->visibleItems.begin();
+ while (it != d->visibleItems.end()) {
+ FxGridItem1 *item = *it;
+ if (remaining && item->index >= to && item->index < to + count) {
+ // place items in the target position, reusing any existing items
+ FxGridItem1 *movedItem = moved.take(item->index);
+ if (!movedItem)
+ movedItem = d->createItem(item->index);
+ it = d->visibleItems.insert(it, movedItem);
+ if (it == d->visibleItems.begin() && firstItem)
+ movedItem->setPosition(firstItem->colPos(), firstItem->rowPos());
+ ++it;
+ --remaining;
+ } else {
+ if (item->index != -1) {
+ if (item->index >= to) {
+ // update everything after the moved items.
+ item->index += count;
+ }
+ endIndex = item->index;
+ }
+ ++it;
+ }
+ }
+
+ // If we have moved items to the end of the visible items
+ // then add any existing moved items that we have
+ while (FxGridItem1 *item = moved.take(endIndex+1)) {
+ d->visibleItems.append(item);
+ ++endIndex;
+ }
+
+ // update visibleIndex
+ for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
+ if ((*it)->index != -1) {
+ d->visibleIndex = (*it)->index;
+ break;
+ }
+ }
+
+ // Fix current index
+ if (d->currentIndex >= 0 && d->currentItem) {
+ int oldCurrent = d->currentIndex;
+ d->currentIndex = d->model->indexOf(d->currentItem->item, this);
+ if (oldCurrent != d->currentIndex) {
+ d->currentItem->index = d->currentIndex;
+ emit currentIndexChanged();
+ }
+ }
+
+ // Whatever moved items remain are no longer visible items.
+ while (moved.count()) {
+ int idx = moved.begin().key();
+ FxGridItem1 *item = moved.take(idx);
+ if (d->currentItem && item->item == d->currentItem->item)
+ item->setPosition(d->colPosAt(idx), d->rowPosAt(idx));
+ d->releaseItem(item);
+ }
+
+ d->layout();
+}
+
+void QDeclarative1GridView::modelReset()
+{
+ Q_D(QDeclarative1GridView);
+ d->clear();
+ refill();
+ d->moveReason = QDeclarative1GridViewPrivate::SetIndex;
+ d->updateCurrent(d->currentIndex);
+ if (d->highlight && d->currentItem) {
+ if (d->autoHighlight)
+ d->highlight->setPosition(d->currentItem->colPos(), d->currentItem->rowPos());
+ d->updateTrackedItem();
+ }
+ d->moveReason = QDeclarative1GridViewPrivate::Other;
+
+ emit countChanged();
+}
+
+void QDeclarative1GridView::createdItem(int index, QDeclarativeItem *item)
+{
+ Q_D(QDeclarative1GridView);
+ if (d->requestedIndex != index) {
+ item->setParentItem(this);
+ d->unrequestedItems.insert(item, index);
+ if (d->flow == QDeclarative1GridView::LeftToRight) {
+ item->setPos(QPointF(d->colPosAt(index), d->rowPosAt(index)));
+ } else {
+ item->setPos(QPointF(d->rowPosAt(index), d->colPosAt(index)));
+ }
+ }
+}
+
+void QDeclarative1GridView::destroyingItem(QDeclarativeItem *item)
+{
+ Q_D(QDeclarative1GridView);
+ d->unrequestedItems.remove(item);
+}
+
+void QDeclarative1GridView::animStopped()
+{
+ Q_D(QDeclarative1GridView);
+ d->bufferMode = QDeclarative1GridViewPrivate::NoBuffer;
+ if (d->haveHighlightRange && d->highlightRange == QDeclarative1GridView::StrictlyEnforceRange)
+ d->updateHighlight();
+}
+
+void QDeclarative1GridView::refill()
+{
+ Q_D(QDeclarative1GridView);
+ if (d->isRightToLeftTopToBottom())
+ d->refill(-d->position()-d->size()+1, -d->position());
+ else
+ d->refill(d->position(), d->position()+d->size()-1);
+}
+
+
+QDeclarative1GridViewAttached *QDeclarative1GridView::qmlAttachedProperties(QObject *obj)
+{
+ return new QDeclarative1GridViewAttached(obj);
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/graphicsitems/qdeclarativegridview_p.h b/src/qtquick1/graphicsitems/qdeclarativegridview_p.h
new file mode 100644
index 0000000000..c53a34507d
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativegridview_p.h
@@ -0,0 +1,288 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEGRIDVIEW_H
+#define QDECLARATIVEGRIDVIEW_H
+
+#include "private/qdeclarativeflickable_p.h"
+#include "QtDeclarative/private/qdeclarativeguard_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QDeclarative1VisualModel;
+class QDeclarative1GridViewAttached;
+class QDeclarative1GridViewPrivate;
+class Q_AUTOTEST_EXPORT QDeclarative1GridView : public QDeclarative1Flickable
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarative1GridView)
+
+ Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged)
+ Q_PROPERTY(QDeclarativeComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
+ Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
+ Q_PROPERTY(QDeclarativeItem *currentItem READ currentItem NOTIFY currentIndexChanged)
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+
+ Q_PROPERTY(QDeclarativeComponent *highlight READ highlight WRITE setHighlight NOTIFY highlightChanged)
+ Q_PROPERTY(QDeclarativeItem *highlightItem READ highlightItem NOTIFY highlightItemChanged)
+ Q_PROPERTY(bool highlightFollowsCurrentItem READ highlightFollowsCurrentItem WRITE setHighlightFollowsCurrentItem)
+ Q_PROPERTY(int highlightMoveDuration READ highlightMoveDuration WRITE setHighlightMoveDuration NOTIFY highlightMoveDurationChanged)
+
+ Q_PROPERTY(qreal preferredHighlightBegin READ preferredHighlightBegin WRITE setPreferredHighlightBegin NOTIFY preferredHighlightBeginChanged RESET resetPreferredHighlightBegin)
+ Q_PROPERTY(qreal preferredHighlightEnd READ preferredHighlightEnd WRITE setPreferredHighlightEnd NOTIFY preferredHighlightEndChanged RESET resetPreferredHighlightEnd)
+ Q_PROPERTY(HighlightRangeMode highlightRangeMode READ highlightRangeMode WRITE setHighlightRangeMode NOTIFY highlightRangeModeChanged)
+
+ Q_PROPERTY(Flow flow READ flow WRITE setFlow NOTIFY flowChanged)
+ Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged REVISION 1)
+ Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged REVISION 1)
+ Q_PROPERTY(bool keyNavigationWraps READ isWrapEnabled WRITE setWrapEnabled NOTIFY keyNavigationWrapsChanged)
+ Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer NOTIFY cacheBufferChanged)
+ Q_PROPERTY(int cellWidth READ cellWidth WRITE setCellWidth NOTIFY cellWidthChanged)
+ Q_PROPERTY(int cellHeight READ cellHeight WRITE setCellHeight NOTIFY cellHeightChanged)
+
+ Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged)
+
+ Q_PROPERTY(QDeclarativeComponent *header READ header WRITE setHeader NOTIFY headerChanged)
+ Q_PROPERTY(QDeclarativeComponent *footer READ footer WRITE setFooter NOTIFY footerChanged)
+
+ Q_ENUMS(HighlightRangeMode)
+ Q_ENUMS(SnapMode)
+ Q_ENUMS(Flow)
+ Q_ENUMS(PositionMode)
+ Q_CLASSINFO("DefaultProperty", "data")
+
+public:
+ QDeclarative1GridView(QDeclarativeItem *parent=0);
+ ~QDeclarative1GridView();
+
+ QVariant model() const;
+ int modelCount() const;
+ void setModel(const QVariant &);
+
+ QDeclarativeComponent *delegate() const;
+ void setDelegate(QDeclarativeComponent *);
+
+ int currentIndex() const;
+ void setCurrentIndex(int idx);
+
+ QDeclarativeItem *currentItem();
+ QDeclarativeItem *highlightItem();
+ int count() const;
+
+ QDeclarativeComponent *highlight() const;
+ void setHighlight(QDeclarativeComponent *highlight);
+
+ bool highlightFollowsCurrentItem() const;
+ void setHighlightFollowsCurrentItem(bool);
+
+ int highlightMoveDuration() const;
+ void setHighlightMoveDuration(int);
+
+ enum HighlightRangeMode { NoHighlightRange, ApplyRange, StrictlyEnforceRange };
+ HighlightRangeMode highlightRangeMode() const;
+ void setHighlightRangeMode(HighlightRangeMode mode);
+
+ qreal preferredHighlightBegin() const;
+ void setPreferredHighlightBegin(qreal);
+ void resetPreferredHighlightBegin();
+
+ qreal preferredHighlightEnd() const;
+ void setPreferredHighlightEnd(qreal);
+ void resetPreferredHighlightEnd();
+
+ Qt::LayoutDirection layoutDirection() const;
+ void setLayoutDirection(Qt::LayoutDirection);
+ Qt::LayoutDirection effectiveLayoutDirection() const;
+
+ enum Flow { LeftToRight, TopToBottom };
+ Flow flow() const;
+ void setFlow(Flow);
+
+ bool isWrapEnabled() const;
+ void setWrapEnabled(bool);
+
+ int cacheBuffer() const;
+ void setCacheBuffer(int);
+
+ int cellWidth() const;
+ void setCellWidth(int);
+
+ int cellHeight() const;
+ void setCellHeight(int);
+
+ enum SnapMode { NoSnap, SnapToRow, SnapOneRow };
+ SnapMode snapMode() const;
+ void setSnapMode(SnapMode mode);
+
+ QDeclarativeComponent *footer() const;
+ void setFooter(QDeclarativeComponent *);
+
+ QDeclarativeComponent *header() const;
+ void setHeader(QDeclarativeComponent *);
+
+ virtual void setContentX(qreal pos);
+ virtual void setContentY(qreal pos);
+
+ enum PositionMode { Beginning, Center, End, Visible, Contain };
+
+ Q_INVOKABLE void positionViewAtIndex(int index, int mode);
+ Q_INVOKABLE int indexAt(qreal x, qreal y) const;
+ Q_INVOKABLE Q_REVISION(1) void positionViewAtBeginning();
+ Q_INVOKABLE Q_REVISION(1) void positionViewAtEnd();
+
+ static QDeclarative1GridViewAttached *qmlAttachedProperties(QObject *);
+
+public Q_SLOTS:
+ void moveCurrentIndexUp();
+ void moveCurrentIndexDown();
+ void moveCurrentIndexLeft();
+ void moveCurrentIndexRight();
+
+Q_SIGNALS:
+ void countChanged();
+ void currentIndexChanged();
+ void cellWidthChanged();
+ void cellHeightChanged();
+ void highlightChanged();
+ void highlightItemChanged();
+ void preferredHighlightBeginChanged();
+ void preferredHighlightEndChanged();
+ void highlightRangeModeChanged();
+ void highlightMoveDurationChanged();
+ void modelChanged();
+ void delegateChanged();
+ void flowChanged();
+ Q_REVISION(1) void layoutDirectionChanged();
+ Q_REVISION(1) void effectiveLayoutDirectionChanged();
+ void keyNavigationWrapsChanged();
+ void cacheBufferChanged();
+ void snapModeChanged();
+ void headerChanged();
+ void footerChanged();
+
+protected:
+ virtual bool event(QEvent *event);
+ virtual void viewportMoved();
+ virtual qreal minYExtent() const;
+ virtual qreal maxYExtent() const;
+ virtual qreal minXExtent() const;
+ virtual qreal maxXExtent() const;
+ virtual void keyPressEvent(QKeyEvent *);
+ virtual void componentComplete();
+
+private Q_SLOTS:
+ void trackedPositionChanged();
+ void itemsInserted(int index, int count);
+ void itemsRemoved(int index, int count);
+ void itemsMoved(int from, int to, int count);
+ void modelReset();
+ void destroyRemoved();
+ void createdItem(int index, QDeclarativeItem *item);
+ void destroyingItem(QDeclarativeItem *item);
+ void animStopped();
+
+private:
+ void refill();
+};
+
+class QDeclarative1GridViewAttached : public QObject
+{
+ Q_OBJECT
+public:
+ QDeclarative1GridViewAttached(QObject *parent)
+ : QObject(parent), m_view(0), m_isCurrent(false), m_delayRemove(false) {}
+ ~QDeclarative1GridViewAttached() {}
+
+ Q_PROPERTY(QDeclarative1GridView *view READ view NOTIFY viewChanged)
+ QDeclarative1GridView *view() { return m_view; }
+ void setView(QDeclarative1GridView *view) {
+ if (view != m_view) {
+ m_view = view;
+ emit viewChanged();
+ }
+ }
+
+ Q_PROPERTY(bool isCurrentItem READ isCurrentItem NOTIFY currentItemChanged)
+ bool isCurrentItem() const { return m_isCurrent; }
+ void setIsCurrentItem(bool c) {
+ if (m_isCurrent != c) {
+ m_isCurrent = c;
+ emit currentItemChanged();
+ }
+ }
+
+ Q_PROPERTY(bool delayRemove READ delayRemove WRITE setDelayRemove NOTIFY delayRemoveChanged)
+ bool delayRemove() const { return m_delayRemove; }
+ void setDelayRemove(bool delay) {
+ if (m_delayRemove != delay) {
+ m_delayRemove = delay;
+ emit delayRemoveChanged();
+ }
+ }
+
+ void emitAdd() { emit add(); }
+ void emitRemove() { emit remove(); }
+
+Q_SIGNALS:
+ void currentItemChanged();
+ void delayRemoveChanged();
+ void add();
+ void remove();
+ void viewChanged();
+
+public:
+ QDeclarativeGuard<QDeclarative1GridView> m_view;
+ bool m_isCurrent : 1;
+ bool m_delayRemove : 1;
+};
+
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1GridView)
+QML_DECLARE_TYPEINFO(QDeclarative1GridView, QML_HAS_ATTACHED_PROPERTIES)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/qtquick1/graphicsitems/qdeclarativeimage.cpp b/src/qtquick1/graphicsitems/qdeclarativeimage.cpp
new file mode 100644
index 0000000000..c3d0802e8c
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativeimage.cpp
@@ -0,0 +1,588 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativeimage_p.h"
+#include "QtQuick1/private/qdeclarativeimage_p_p.h"
+
+#include <QKeyEvent>
+#include <QPainter>
+
+QT_BEGIN_NAMESPACE
+
+
+
+
+/*!
+ \qmlclass Image QDeclarative1Image
+ \since 4.7
+ \ingroup qml-basic-visual-elements
+ \brief The Image element displays an image in a declarative user interface
+ \inherits Item
+
+ The Image element is used to display images in a declarative user interface.
+
+ The source of the image is specified as a URL using the \l source property.
+ Images can be supplied in any of the standard image formats supported by Qt,
+ including bitmap formats such as PNG and JPEG, and vector graphics formats
+ such as SVG. If you need to display animated images, use the \l AnimatedImage
+ element.
+
+ If the \l{Item::width}{width} and \l{Item::height}{height} properties are not
+ specified, the Image element automatically uses the size of the loaded image.
+ By default, specifying the width and height of the element causes the image
+ to be scaled to that size. This behavior can be changed by setting the
+ \l fillMode property, allowing the image to be stretched and tiled instead.
+
+ \section1 Example Usage
+
+ The following example shows the simplest usage of the Image element.
+
+ \snippet doc/src/snippets/declarative/image.qml document
+
+ \beginfloatleft
+ \image declarative-qtlogo.png
+ \endfloat
+
+ \clearfloat
+
+ \section1 Performance
+
+ By default, locally available images are loaded immediately, and the user interface
+ is blocked until loading is complete. If a large image is to be loaded, it may be
+ preferable to load the image in a low priority thread, by enabling the \l asynchronous
+ property.
+
+ If the image is obtained from a network rather than a local resource, it is
+ automatically loaded asynchronously, and the \l progress and \l status properties
+ are updated as appropriate.
+
+ Images are cached and shared internally, so if several Image elements have the same \l source,
+ only one copy of the image will be loaded.
+
+ \bold Note: Images are often the greatest user of memory in QML user interfaces. It is recommended
+ that images which do not form part of the user interface have their
+ size bounded via the \l sourceSize property. This is especially important for content
+ that is loaded from external sources or provided by the user.
+
+ \sa {declarative/imageelements/image}{Image example}, QDeclarativeImageProvider
+*/
+
+QDeclarative1Image::QDeclarative1Image(QDeclarativeItem *parent)
+ : QDeclarative1ImageBase(*(new QDeclarative1ImagePrivate), parent)
+{
+}
+
+QDeclarative1Image::QDeclarative1Image(QDeclarative1ImagePrivate &dd, QDeclarativeItem *parent)
+ : QDeclarative1ImageBase(dd, parent)
+{
+}
+
+QDeclarative1Image::~QDeclarative1Image()
+{
+}
+
+QPixmap QDeclarative1Image::pixmap() const
+{
+ Q_D(const QDeclarative1Image);
+ return d->pix.pixmap();
+}
+
+void QDeclarative1Image::setPixmap(const QPixmap &pix)
+{
+ Q_D(QDeclarative1Image);
+ if (!d->url.isEmpty())
+ return;
+ d->setPixmap(pix);
+}
+
+void QDeclarative1ImagePrivate::setPixmap(const QPixmap &pixmap)
+{
+ Q_Q(QDeclarative1Image);
+ pix.setPixmap(pixmap);
+
+ q->pixmapChange();
+ status = pix.isNull() ? QDeclarative1ImageBase::Null : QDeclarative1ImageBase::Ready;
+
+ q->update();
+}
+
+/*!
+ \qmlproperty enumeration Image::fillMode
+
+ Set this property to define what happens when the source image has a different size
+ than the item.
+
+ \list
+ \o Image.Stretch - the image is scaled to fit
+ \o Image.PreserveAspectFit - the image is scaled uniformly to fit without cropping
+ \o Image.PreserveAspectCrop - the image is scaled uniformly to fill, cropping if necessary
+ \o Image.Tile - the image is duplicated horizontally and vertically
+ \o Image.TileVertically - the image is stretched horizontally and tiled vertically
+ \o Image.TileHorizontally - the image is stretched vertically and tiled horizontally
+ \endlist
+
+ \table
+
+ \row
+ \o \image declarative-qtlogo-stretch.png
+ \o Stretch (default)
+ \qml
+ Image {
+ width: 130; height: 100
+ smooth: true
+ source: "qtlogo.png"
+ }
+ \endqml
+
+ \row
+ \o \image declarative-qtlogo-preserveaspectfit.png
+ \o PreserveAspectFit
+ \qml
+ Image {
+ width: 130; height: 100
+ fillMode: Image.PreserveAspectFit
+ smooth: true
+ source: "qtlogo.png"
+ }
+ \endqml
+
+ \row
+ \o \image declarative-qtlogo-preserveaspectcrop.png
+ \o PreserveAspectCrop
+ \qml
+ Image {
+ width: 130; height: 100
+ fillMode: Image.PreserveAspectCrop
+ smooth: true
+ source: "qtlogo.png"
+ clip: true
+ }
+ \endqml
+
+ \row
+ \o \image declarative-qtlogo-tile.png
+ \o Tile
+ \qml
+ Image {
+ width: 120; height: 120
+ fillMode: Image.Tile
+ source: "qtlogo.png"
+ }
+ \endqml
+
+ \row
+ \o \image declarative-qtlogo-tilevertically.png
+ \o TileVertically
+ \qml
+ Image {
+ width: 120; height: 120
+ fillMode: Image.TileVertically
+ smooth: true
+ source: "qtlogo.png"
+ }
+ \endqml
+
+ \row
+ \o \image declarative-qtlogo-tilehorizontally.png
+ \o TileHorizontally
+ \qml
+ Image {
+ width: 120; height: 120
+ fillMode: Image.TileHorizontally
+ smooth: true
+ source: "qtlogo.png"
+ }
+ \endqml
+
+ \endtable
+
+ Note that \c clip is \c false by default which means that the element might
+ paint outside its bounding rectangle even if the fillMode is set to \c PreserveAspectCrop.
+
+ \sa {declarative/imageelements/image}{Image example}
+*/
+QDeclarative1Image::FillMode QDeclarative1Image::fillMode() const
+{
+ Q_D(const QDeclarative1Image);
+ return d->fillMode;
+}
+
+void QDeclarative1Image::setFillMode(FillMode mode)
+{
+ Q_D(QDeclarative1Image);
+ if (d->fillMode == mode)
+ return;
+ d->fillMode = mode;
+ update();
+ updatePaintedGeometry();
+ emit fillModeChanged();
+}
+
+/*!
+
+ \qmlproperty real Image::paintedWidth
+ \qmlproperty real Image::paintedHeight
+
+ These properties hold the size of the image that is actually painted.
+ In most cases it is the same as \c width and \c height, but when using a
+ \c fillMode \c PreserveAspectFit or \c fillMode \c PreserveAspectCrop
+ \c paintedWidth or \c paintedHeight can be smaller or larger than
+ \c width and \c height of the Image element.
+*/
+qreal QDeclarative1Image::paintedWidth() const
+{
+ Q_D(const QDeclarative1Image);
+ return d->paintedWidth;
+}
+
+qreal QDeclarative1Image::paintedHeight() const
+{
+ Q_D(const QDeclarative1Image);
+ return d->paintedHeight;
+}
+
+/*!
+ \qmlproperty enumeration Image::status
+
+ This property holds the status of image loading. It can be one of:
+ \list
+ \o Image.Null - no image has been set
+ \o Image.Ready - the image has been loaded
+ \o Image.Loading - the image is currently being loaded
+ \o Image.Error - an error occurred while loading the image
+ \endlist
+
+ Use this status to provide an update or respond to the status change in some way.
+ For example, you could:
+
+ \list
+ \o Trigger a state change:
+ \qml
+ State { name: 'loaded'; when: image.status == Image.Ready }
+ \endqml
+
+ \o Implement an \c onStatusChanged signal handler:
+ \qml
+ Image {
+ id: image
+ onStatusChanged: if (image.status == Image.Ready) console.log('Loaded')
+ }
+ \endqml
+
+ \o Bind to the status value:
+ \qml
+ Text { text: image.status == Image.Ready ? 'Loaded' : 'Not loaded' }
+ \endqml
+ \endlist
+
+ \sa progress
+*/
+
+/*!
+ \qmlproperty real Image::progress
+
+ This property holds the progress of image loading, from 0.0 (nothing loaded)
+ to 1.0 (finished).
+
+ \sa status
+*/
+
+/*!
+ \qmlproperty bool Image::smooth
+
+ Set this property if you want the image to be smoothly filtered when scaled or
+ transformed. Smooth filtering gives better visual quality, but is slower. If
+ the image is displayed at its natural size, this property has no visual or
+ performance effect.
+
+ \note Generally scaling artifacts are only visible if the image is stationary on
+ the screen. A common pattern when animating an image is to disable smooth
+ filtering at the beginning of the animation and reenable it at the conclusion.
+*/
+
+/*!
+ \qmlproperty QSize Image::sourceSize
+
+ This property holds the actual width and height of the loaded image.
+
+ Unlike the \l {Item::}{width} and \l {Item::}{height} properties, which scale
+ the painting of the image, this property sets the actual number of pixels
+ stored for the loaded image so that large images do not use more
+ memory than necessary. For example, this ensures the image in memory is no
+ larger than 1024x1024 pixels, regardless of the Image's \l {Item::}{width} and
+ \l {Item::}{height} values:
+
+ \code
+ Rectangle {
+ width: ...
+ height: ...
+
+ Image {
+ anchors.fill: parent
+ source: "reallyBigImage.jpg"
+ sourceSize.width: 1024
+ sourceSize.height: 1024
+ }
+ }
+ \endcode
+
+ If the image's actual size is larger than the sourceSize, the image is scaled down.
+ If only one dimension of the size is set to greater than 0, the
+ other dimension is set in proportion to preserve the source image's aspect ratio.
+ (The \l fillMode is independent of this.)
+
+ If the source is an instrinsically scalable image (eg. SVG), this property
+ determines the size of the loaded image regardless of intrinsic size.
+ Avoid changing this property dynamically; rendering an SVG is \e slow compared
+ to an image.
+
+ If the source is a non-scalable image (eg. JPEG), the loaded image will
+ be no greater than this property specifies. For some formats (currently only JPEG),
+ the whole image will never actually be loaded into memory.
+
+ Since QtQuick 1.1 the sourceSize can be cleared to the natural size of the image
+ by setting sourceSize to \c undefined.
+
+ \note \e {Changing this property dynamically causes the image source to be reloaded,
+ potentially even from the network, if it is not in the disk cache.}
+*/
+
+void QDeclarative1Image::updatePaintedGeometry()
+{
+ Q_D(QDeclarative1Image);
+
+ if (d->fillMode == PreserveAspectFit) {
+ if (!d->pix.width() || !d->pix.height()) {
+ setImplicitWidth(0);
+ setImplicitHeight(0);
+ return;
+ }
+ qreal w = widthValid() ? width() : d->pix.width();
+ qreal widthScale = w / qreal(d->pix.width());
+ qreal h = heightValid() ? height() : d->pix.height();
+ qreal heightScale = h / qreal(d->pix.height());
+ if (widthScale <= heightScale) {
+ d->paintedWidth = w;
+ d->paintedHeight = widthScale * qreal(d->pix.height());
+ } else if(heightScale < widthScale) {
+ d->paintedWidth = heightScale * qreal(d->pix.width());
+ d->paintedHeight = h;
+ }
+ if (widthValid() && !heightValid()) {
+ setImplicitHeight(d->paintedHeight);
+ } else {
+ setImplicitHeight(d->pix.height());
+ }
+ if (heightValid() && !widthValid()) {
+ setImplicitWidth(d->paintedWidth);
+ } else {
+ setImplicitWidth(d->pix.width());
+ }
+ } else if (d->fillMode == PreserveAspectCrop) {
+ if (!d->pix.width() || !d->pix.height())
+ return;
+ qreal widthScale = width() / qreal(d->pix.width());
+ qreal heightScale = height() / qreal(d->pix.height());
+ if (widthScale < heightScale) {
+ widthScale = heightScale;
+ } else if(heightScale < widthScale) {
+ heightScale = widthScale;
+ }
+
+ d->paintedHeight = heightScale * qreal(d->pix.height());
+ d->paintedWidth = widthScale * qreal(d->pix.width());
+ } else {
+ d->paintedWidth = width();
+ d->paintedHeight = height();
+ }
+ emit paintedGeometryChanged();
+}
+
+void QDeclarative1Image::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ QDeclarative1ImageBase::geometryChanged(newGeometry, oldGeometry);
+ updatePaintedGeometry();
+}
+
+QRectF QDeclarative1Image::boundingRect() const
+{
+ Q_D(const QDeclarative1Image);
+ return QRectF(0, 0, qMax(d->mWidth, d->paintedWidth), qMax(d->mHeight, d->paintedHeight));
+}
+
+/*!
+ \qmlproperty url Image::source
+
+ Image can handle any image format supported by Qt, loaded from any URL scheme supported by Qt.
+
+ The URL may be absolute, or relative to the URL of the component.
+
+ \sa QDeclarativeImageProvider
+*/
+
+/*!
+ \qmlproperty bool Image::asynchronous
+
+ Specifies that images on the local filesystem should be loaded
+ asynchronously in a separate thread. The default value is
+ false, causing the user interface thread to block while the
+ image is loaded. Setting \a asynchronous to true is useful where
+ maintaining a responsive user interface is more desirable
+ than having images immediately visible.
+
+ Note that this property is only valid for images read from the
+ local filesystem. Images loaded via a network resource (e.g. HTTP)
+ are always loaded asynchonously.
+*/
+
+/*!
+ \qmlproperty bool Image::cache
+ \since Quick 1.1
+
+ Specifies whether the image should be cached. The default value is
+ true. Setting \a cache to false is useful when dealing with large images,
+ to make sure that they aren't cached at the expense of small 'ui element' images.
+*/
+
+/*!
+ \qmlproperty bool Image::mirror
+ \since Quick 1.1
+
+ This property holds whether the image should be horizontally inverted
+ (effectively displaying a mirrored image).
+
+ The default value is false.
+*/
+
+
+void QDeclarative1Image::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *)
+{
+ Q_D(QDeclarative1Image);
+ if (d->pix.pixmap().isNull() )
+ return;
+
+ int drawWidth = width();
+ int drawHeight = height();
+ bool doClip = false;
+ QTransform transform;
+ qreal widthScale = width() / qreal(d->pix.width());
+ qreal heightScale = height() / qreal(d->pix.height());
+
+ if (width() != d->pix.width() || height() != d->pix.height()) {
+ if (d->fillMode >= Tile) {
+ if (d->fillMode == TileVertically) {
+ transform.scale(widthScale, 1.0);
+ drawWidth = d->pix.width();
+ } else if (d->fillMode == TileHorizontally) {
+ transform.scale(1.0, heightScale);
+ drawHeight = d->pix.height();
+ }
+ } else {
+ if (d->fillMode == PreserveAspectFit) {
+ if (widthScale <= heightScale) {
+ heightScale = widthScale;
+ transform.translate(0, (height() - heightScale * d->pix.height()) / 2);
+ } else if(heightScale < widthScale) {
+ widthScale = heightScale;
+ transform.translate((width() - widthScale * d->pix.width()) / 2, 0);
+ }
+ } else if (d->fillMode == PreserveAspectCrop) {
+ if (widthScale < heightScale) {
+ widthScale = heightScale;
+ transform.translate((width() - widthScale * d->pix.width()) / 2, 0);
+ } else if(heightScale < widthScale) {
+ heightScale = widthScale;
+ transform.translate(0, (height() - heightScale * d->pix.height()) / 2);
+ }
+ }
+ transform.scale(widthScale, heightScale);
+ drawWidth = d->pix.width();
+ drawHeight = d->pix.height();
+ doClip = clip();
+ }
+ }
+
+ QTransform oldTransform;
+ bool oldAA = p->testRenderHint(QPainter::Antialiasing);
+ bool oldSmooth = p->testRenderHint(QPainter::SmoothPixmapTransform);
+ if (d->smooth)
+ p->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, d->smooth);
+ if (doClip) {
+ p->save();
+ p->setClipRect(QRectF(0, 0, d->mWidth, d->mHeight), Qt::IntersectClip);
+ }
+ if (d->mirror)
+ transform.translate(drawWidth, 0).scale(-1.0, 1.0);
+ if (!transform.isIdentity()) {
+ oldTransform = p->transform();
+ p->setWorldTransform(transform * oldTransform);
+ }
+
+ if (d->fillMode >= Tile)
+ p->drawTiledPixmap(QRectF(0, 0, drawWidth, drawHeight), d->pix);
+ else
+ p->drawPixmap(QRectF(0, 0, drawWidth, drawHeight), d->pix, QRectF(0, 0, drawWidth, drawHeight));
+
+ if (d->smooth) {
+ p->setRenderHint(QPainter::Antialiasing, oldAA);
+ p->setRenderHint(QPainter::SmoothPixmapTransform, oldSmooth);
+ }
+ if (doClip)
+ p->restore();
+ if (!transform.isIdentity())
+ p->setWorldTransform(oldTransform);
+}
+
+void QDeclarative1Image::pixmapChange()
+{
+ Q_D(QDeclarative1Image);
+ // PreserveAspectFit calculates the implicit size differently so we
+ // don't call our superclass pixmapChange(), since that would
+ // result in the implicit size being set incorrectly, then updated
+ // in updatePaintedGeometry()
+ if (d->fillMode != PreserveAspectFit)
+ QDeclarative1ImageBase::pixmapChange();
+ updatePaintedGeometry();
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/graphicsitems/qdeclarativeimage_p.h b/src/qtquick1/graphicsitems/qdeclarativeimage_p.h
new file mode 100644
index 0000000000..615587c384
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativeimage_p.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEIMAGE_H
+#define QDECLARATIVEIMAGE_H
+
+#include "private/qdeclarativeimagebase_p.h"
+
+#include <QtNetwork/qnetworkreply.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarative1ImagePrivate;
+class Q_AUTOTEST_EXPORT QDeclarative1Image : public QDeclarative1ImageBase
+{
+ Q_OBJECT
+ Q_ENUMS(FillMode)
+
+ Q_PROPERTY(FillMode fillMode READ fillMode WRITE setFillMode NOTIFY fillModeChanged)
+ Q_PROPERTY(qreal paintedWidth READ paintedWidth NOTIFY paintedGeometryChanged)
+ Q_PROPERTY(qreal paintedHeight READ paintedHeight NOTIFY paintedGeometryChanged)
+
+public:
+ QDeclarative1Image(QDeclarativeItem *parent=0);
+ ~QDeclarative1Image();
+
+ enum FillMode { Stretch, PreserveAspectFit, PreserveAspectCrop, Tile, TileVertically, TileHorizontally };
+ FillMode fillMode() const;
+ void setFillMode(FillMode);
+
+ QPixmap pixmap() const;
+ void setPixmap(const QPixmap &);
+
+ qreal paintedWidth() const;
+ qreal paintedHeight() const;
+
+ void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
+ QRectF boundingRect() const;
+
+Q_SIGNALS:
+ void fillModeChanged();
+ void paintedGeometryChanged();
+
+protected:
+ QDeclarative1Image(QDeclarative1ImagePrivate &dd, QDeclarativeItem *parent);
+ void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
+ void pixmapChange();
+ void updatePaintedGeometry();
+
+private:
+ Q_DISABLE_COPY(QDeclarative1Image)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarative1Image)
+};
+
+QT_END_NAMESPACE
+QML_DECLARE_TYPE(QDeclarative1Image)
+QT_END_HEADER
+
+#endif // QDECLARATIVEIMAGE_H
diff --git a/src/qtquick1/graphicsitems/qdeclarativeimage_p_p.h b/src/qtquick1/graphicsitems/qdeclarativeimage_p_p.h
new file mode 100644
index 0000000000..19b8642892
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativeimage_p_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEIMAGE_P_H
+#define QDECLARATIVEIMAGE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qdeclarativeitem_p.h"
+#include "private/qdeclarativeimagebase_p_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarative1ImagePrivate : public QDeclarative1ImageBasePrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1Image)
+
+public:
+ QDeclarative1ImagePrivate()
+ : fillMode(QDeclarative1Image::Stretch), paintedWidth(0), paintedHeight(0)
+ {
+ }
+
+ QDeclarative1Image::FillMode fillMode;
+ qreal paintedWidth;
+ qreal paintedHeight;
+ void setPixmap(const QPixmap &pix);
+};
+
+QT_END_NAMESPACE
+
+#endif // QDECLARATIVEIMAGE_P_H
diff --git a/src/qtquick1/graphicsitems/qdeclarativeimagebase.cpp b/src/qtquick1/graphicsitems/qdeclarativeimagebase.cpp
new file mode 100644
index 0000000000..a4f2f72d9f
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativeimagebase.cpp
@@ -0,0 +1,288 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativeimagebase_p.h"
+#include "QtQuick1/private/qdeclarativeimagebase_p_p.h"
+
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativeinfo.h>
+#include <QtQuick1/private/qdeclarativepixmapcache_p.h>
+
+QT_BEGIN_NAMESPACE
+
+
+
+QDeclarative1ImageBase::QDeclarative1ImageBase(QDeclarativeItem *parent)
+ : QDeclarative1ImplicitSizeItem(*(new QDeclarative1ImageBasePrivate), parent)
+{
+}
+
+QDeclarative1ImageBase::QDeclarative1ImageBase(QDeclarative1ImageBasePrivate &dd, QDeclarativeItem *parent)
+ : QDeclarative1ImplicitSizeItem(dd, parent)
+{
+}
+
+QDeclarative1ImageBase::~QDeclarative1ImageBase()
+{
+}
+
+QDeclarative1ImageBase::Status QDeclarative1ImageBase::status() const
+{
+ Q_D(const QDeclarative1ImageBase);
+ return d->status;
+}
+
+
+qreal QDeclarative1ImageBase::progress() const
+{
+ Q_D(const QDeclarative1ImageBase);
+ return d->progress;
+}
+
+
+bool QDeclarative1ImageBase::asynchronous() const
+{
+ Q_D(const QDeclarative1ImageBase);
+ return d->async;
+}
+
+void QDeclarative1ImageBase::setAsynchronous(bool async)
+{
+ Q_D(QDeclarative1ImageBase);
+ if (d->async != async) {
+ d->async = async;
+ emit asynchronousChanged();
+ }
+}
+
+QUrl QDeclarative1ImageBase::source() const
+{
+ Q_D(const QDeclarative1ImageBase);
+ return d->url;
+}
+
+void QDeclarative1ImageBase::setSource(const QUrl &url)
+{
+ Q_D(QDeclarative1ImageBase);
+ //equality is fairly expensive, so we bypass for simple, common case
+ if ((d->url.isEmpty() == url.isEmpty()) && url == d->url)
+ return;
+
+ d->url = url;
+ emit sourceChanged(d->url);
+
+ if (isComponentComplete())
+ load();
+}
+
+void QDeclarative1ImageBase::setSourceSize(const QSize& size)
+{
+ Q_D(QDeclarative1ImageBase);
+ if (d->sourcesize == size)
+ return;
+
+ d->sourcesize = size;
+ d->explicitSourceSize = true;
+ emit sourceSizeChanged();
+ if (isComponentComplete())
+ load();
+}
+
+QSize QDeclarative1ImageBase::sourceSize() const
+{
+ Q_D(const QDeclarative1ImageBase);
+
+ int width = d->sourcesize.width();
+ int height = d->sourcesize.height();
+ return QSize(width != -1 ? width : d->pix.width(), height != -1 ? height : d->pix.height());
+}
+
+void QDeclarative1ImageBase::resetSourceSize()
+{
+ Q_D(QDeclarative1ImageBase);
+ if (!d->explicitSourceSize)
+ return;
+ d->explicitSourceSize = false;
+ d->sourcesize = QSize();
+ emit sourceSizeChanged();
+ if (isComponentComplete())
+ load();
+}
+
+bool QDeclarative1ImageBase::cache() const
+{
+ Q_D(const QDeclarative1ImageBase);
+ return d->cache;
+}
+
+void QDeclarative1ImageBase::setCache(bool cache)
+{
+ Q_D(QDeclarative1ImageBase);
+ if (d->cache == cache)
+ return;
+
+ d->cache = cache;
+ emit cacheChanged();
+ if (isComponentComplete())
+ load();
+}
+
+void QDeclarative1ImageBase::setMirror(bool mirror)
+{
+ Q_D(QDeclarative1ImageBase);
+ if (mirror == d->mirror)
+ return;
+
+ d->mirror = mirror;
+
+ if (isComponentComplete())
+ update();
+
+ emit mirrorChanged();
+}
+
+bool QDeclarative1ImageBase::mirror() const
+{
+ Q_D(const QDeclarative1ImageBase);
+ return d->mirror;
+}
+
+void QDeclarative1ImageBase::load()
+{
+ Q_D(QDeclarative1ImageBase);
+
+ if (d->url.isEmpty()) {
+ d->pix.clear(this);
+ d->status = Null;
+ d->progress = 0.0;
+ pixmapChange();
+ emit progressChanged(d->progress);
+ emit statusChanged(d->status);
+ update();
+ } else {
+ QDeclarative1Pixmap::Options options;
+ if (d->async)
+ options |= QDeclarative1Pixmap::Asynchronous;
+ if (d->cache)
+ options |= QDeclarative1Pixmap::Cache;
+ d->pix.clear(this);
+ d->pix.load(qmlEngine(this), d->url, d->explicitSourceSize ? sourceSize() : QSize(), options);
+
+ if (d->pix.isLoading()) {
+ d->progress = 0.0;
+ d->status = Loading;
+ emit progressChanged(d->progress);
+ emit statusChanged(d->status);
+
+ static int thisRequestProgress = -1;
+ static int thisRequestFinished = -1;
+ if (thisRequestProgress == -1) {
+ thisRequestProgress =
+ QDeclarative1ImageBase::staticMetaObject.indexOfSlot("requestProgress(qint64,qint64)");
+ thisRequestFinished =
+ QDeclarative1ImageBase::staticMetaObject.indexOfSlot("requestFinished()");
+ }
+
+ d->pix.connectFinished(this, thisRequestFinished);
+ d->pix.connectDownloadProgress(this, thisRequestProgress);
+
+ } else {
+ requestFinished();
+ }
+ }
+}
+
+void QDeclarative1ImageBase::requestFinished()
+{
+ Q_D(QDeclarative1ImageBase);
+
+ QDeclarative1ImageBase::Status oldStatus = d->status;
+ qreal oldProgress = d->progress;
+
+ if (d->pix.isError()) {
+ d->status = Error;
+ qmlInfo(this) << d->pix.error();
+ } else {
+ d->status = Ready;
+ }
+
+ d->progress = 1.0;
+
+ pixmapChange();
+
+ if (d->sourcesize.width() != d->pix.width() || d->sourcesize.height() != d->pix.height())
+ emit sourceSizeChanged();
+
+ if (d->status != oldStatus)
+ emit statusChanged(d->status);
+ if (d->progress != oldProgress)
+ emit progressChanged(d->progress);
+
+ update();
+}
+
+void QDeclarative1ImageBase::requestProgress(qint64 received, qint64 total)
+{
+ Q_D(QDeclarative1ImageBase);
+ if (d->status == Loading && total > 0) {
+ d->progress = qreal(received)/total;
+ emit progressChanged(d->progress);
+ }
+}
+
+void QDeclarative1ImageBase::componentComplete()
+{
+ Q_D(QDeclarative1ImageBase);
+ QDeclarativeItem::componentComplete();
+ if (d->url.isValid())
+ load();
+}
+
+void QDeclarative1ImageBase::pixmapChange()
+{
+ Q_D(QDeclarative1ImageBase);
+ setImplicitWidth(d->pix.width());
+ setImplicitHeight(d->pix.height());
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/graphicsitems/qdeclarativeimagebase_p.h b/src/qtquick1/graphicsitems/qdeclarativeimagebase_p.h
new file mode 100644
index 0000000000..85af4a5d7f
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativeimagebase_p.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEIMAGEBASE_H
+#define QDECLARATIVEIMAGEBASE_H
+
+#include "qdeclarativeimplicitsizeitem_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarative1ImageBasePrivate;
+class Q_AUTOTEST_EXPORT QDeclarative1ImageBase : public QDeclarative1ImplicitSizeItem
+{
+ Q_OBJECT
+ Q_ENUMS(Status)
+
+ Q_PROPERTY(Status status READ status NOTIFY statusChanged)
+ Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
+ Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged)
+ Q_PROPERTY(bool asynchronous READ asynchronous WRITE setAsynchronous NOTIFY asynchronousChanged)
+ Q_PROPERTY(bool cache READ cache WRITE setCache NOTIFY cacheChanged REVISION 1)
+ Q_PROPERTY(QSize sourceSize READ sourceSize WRITE setSourceSize RESET resetSourceSize NOTIFY sourceSizeChanged)
+ Q_PROPERTY(bool mirror READ mirror WRITE setMirror NOTIFY mirrorChanged REVISION 1)
+
+public:
+ QDeclarative1ImageBase(QDeclarativeItem *parent=0);
+ ~QDeclarative1ImageBase();
+ enum Status { Null, Ready, Loading, Error };
+ Status status() const;
+ qreal progress() const;
+
+ QUrl source() const;
+ virtual void setSource(const QUrl &url);
+
+ bool asynchronous() const;
+ void setAsynchronous(bool);
+
+ bool cache() const;
+ void setCache(bool);
+
+ virtual void setSourceSize(const QSize&);
+ QSize sourceSize() const;
+ void resetSourceSize();
+
+ virtual void setMirror(bool mirror);
+ bool mirror() const;
+
+Q_SIGNALS:
+ void sourceChanged(const QUrl &);
+ void sourceSizeChanged();
+ void statusChanged(QDeclarative1ImageBase::Status);
+ void progressChanged(qreal progress);
+ void asynchronousChanged();
+ Q_REVISION(1) void cacheChanged();
+ Q_REVISION(1) void mirrorChanged();
+
+protected:
+ virtual void load();
+ virtual void componentComplete();
+ virtual void pixmapChange();
+ QDeclarative1ImageBase(QDeclarative1ImageBasePrivate &dd, QDeclarativeItem *parent);
+
+private Q_SLOTS:
+ virtual void requestFinished();
+ void requestProgress(qint64,qint64);
+
+private:
+ Q_DISABLE_COPY(QDeclarative1ImageBase)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarative1ImageBase)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEIMAGEBASE_H
diff --git a/src/qtquick1/graphicsitems/qdeclarativeimagebase_p_p.h b/src/qtquick1/graphicsitems/qdeclarativeimagebase_p_p.h
new file mode 100644
index 0000000000..bccf953d1c
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativeimagebase_p_p.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEIMAGEBASE_P_H
+#define QDECLARATIVEIMAGEBASE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qdeclarativeimplicitsizeitem_p_p.h"
+#include "QtQuick1/private/qdeclarativepixmapcache_p.h"
+
+#include <QtCore/QPointer>
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkReply;
+
+class QDeclarative1ImageBasePrivate : public QDeclarative1ImplicitSizeItemPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1ImageBase)
+
+public:
+ QDeclarative1ImageBasePrivate()
+ : status(QDeclarative1ImageBase::Null),
+ progress(0.0),
+ explicitSourceSize(false),
+ async(false),
+ cache(true),
+ mirror(false)
+ {
+ QGraphicsItemPrivate::flags = QGraphicsItemPrivate::flags & ~QGraphicsItem::ItemHasNoContents;
+ }
+
+ QDeclarative1Pixmap pix;
+ QDeclarative1ImageBase::Status status;
+ QUrl url;
+ qreal progress;
+ QSize sourcesize;
+ bool explicitSourceSize : 1;
+ bool async : 1;
+ bool cache : 1;
+ bool mirror: 1;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/qtquick1/graphicsitems/qdeclarativeimplicitsizeitem.cpp b/src/qtquick1/graphicsitems/qdeclarativeimplicitsizeitem.cpp
new file mode 100644
index 0000000000..08fdc83170
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativeimplicitsizeitem.cpp
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativeimplicitsizeitem_p.h"
+#include "QtQuick1/private/qdeclarativeimplicitsizeitem_p_p.h"
+
+QT_BEGIN_NAMESPACE
+
+
+
+void QDeclarative1ImplicitSizeItemPrivate::implicitWidthChanged()
+{
+ Q_Q(QDeclarative1ImplicitSizeItem);
+ emit q->implicitWidthChanged();
+}
+
+void QDeclarative1ImplicitSizeItemPrivate::implicitHeightChanged()
+{
+ Q_Q(QDeclarative1ImplicitSizeItem);
+ emit q->implicitHeightChanged();
+}
+
+QDeclarative1ImplicitSizeItem::QDeclarative1ImplicitSizeItem(QDeclarativeItem *parent)
+ : QDeclarativeItem(*(new QDeclarative1ImplicitSizeItemPrivate), parent)
+{
+}
+
+QDeclarative1ImplicitSizeItem::QDeclarative1ImplicitSizeItem(QDeclarative1ImplicitSizeItemPrivate &dd, QDeclarativeItem *parent)
+ : QDeclarativeItem(dd, parent)
+{
+}
+
+
+void QDeclarative1ImplicitSizePaintedItemPrivate::implicitWidthChanged()
+{
+ Q_Q(QDeclarative1ImplicitSizePaintedItem);
+ emit q->implicitWidthChanged();
+}
+
+void QDeclarative1ImplicitSizePaintedItemPrivate::implicitHeightChanged()
+{
+ Q_Q(QDeclarative1ImplicitSizePaintedItem);
+ emit q->implicitHeightChanged();
+}
+
+QDeclarative1ImplicitSizePaintedItem::QDeclarative1ImplicitSizePaintedItem(QDeclarativeItem *parent)
+ : QDeclarative1PaintedItem(*(new QDeclarative1ImplicitSizePaintedItemPrivate), parent)
+{
+}
+
+QDeclarative1ImplicitSizePaintedItem::QDeclarative1ImplicitSizePaintedItem(QDeclarative1ImplicitSizePaintedItemPrivate &dd, QDeclarativeItem *parent)
+ : QDeclarative1PaintedItem(dd, parent)
+{
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/graphicsitems/qdeclarativeimplicitsizeitem_p.h b/src/qtquick1/graphicsitems/qdeclarativeimplicitsizeitem_p.h
new file mode 100644
index 0000000000..15275acba0
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativeimplicitsizeitem_p.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEIMPLICITSIZEITEM_H
+#define QDECLARATIVEIMPLICITSIZEITEM_H
+
+#include "qdeclarativepainteditem_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarative1ImplicitSizeItemPrivate;
+class Q_AUTOTEST_EXPORT QDeclarative1ImplicitSizeItem : public QDeclarativeItem
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal implicitWidth READ implicitWidth NOTIFY implicitWidthChanged REVISION 1)
+ Q_PROPERTY(qreal implicitHeight READ implicitHeight NOTIFY implicitHeightChanged REVISION 1)
+
+public:
+ QDeclarative1ImplicitSizeItem(QDeclarativeItem *parent = 0);
+
+protected:
+ QDeclarative1ImplicitSizeItem(QDeclarative1ImplicitSizeItemPrivate &dd, QDeclarativeItem *parent);
+
+Q_SIGNALS:
+ Q_REVISION(1) void implicitWidthChanged();
+ Q_REVISION(1) void implicitHeightChanged();
+
+private:
+ Q_DISABLE_COPY(QDeclarative1ImplicitSizeItem)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarative1ImplicitSizeItem)
+};
+
+class QDeclarative1ImplicitSizePaintedItemPrivate;
+class Q_AUTOTEST_EXPORT QDeclarative1ImplicitSizePaintedItem : public QDeclarative1PaintedItem
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal implicitWidth READ implicitWidth NOTIFY implicitWidthChanged REVISION 1)
+ Q_PROPERTY(qreal implicitHeight READ implicitHeight NOTIFY implicitHeightChanged REVISION 1)
+
+public:
+ QDeclarative1ImplicitSizePaintedItem(QDeclarativeItem *parent = 0);
+
+protected:
+ QDeclarative1ImplicitSizePaintedItem(QDeclarative1ImplicitSizePaintedItemPrivate &dd, QDeclarativeItem *parent);
+ virtual void drawContents(QPainter *, const QRect &) {};
+
+Q_SIGNALS:
+ Q_REVISION(1) void implicitWidthChanged();
+ Q_REVISION(1) void implicitHeightChanged();
+
+private:
+ Q_DISABLE_COPY(QDeclarative1ImplicitSizePaintedItem)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarative1ImplicitSizePaintedItem)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEIMPLICITSIZEITEM_H
diff --git a/src/qtquick1/graphicsitems/qdeclarativeimplicitsizeitem_p_p.h b/src/qtquick1/graphicsitems/qdeclarativeimplicitsizeitem_p_p.h
new file mode 100644
index 0000000000..4802b2754d
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativeimplicitsizeitem_p_p.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEIMPLICITSIZEITEM_P_H
+#define QDECLARATIVEIMPLICITSIZEITEM_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qdeclarativeitem_p.h"
+#include "private/qdeclarativepainteditem_p_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarative1ImplicitSizeItemPrivate : public QDeclarativeItemPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1ImplicitSizeItem)
+
+public:
+ QDeclarative1ImplicitSizeItemPrivate()
+ {
+ }
+
+ virtual void implicitWidthChanged();
+ virtual void implicitHeightChanged();
+};
+
+
+class QDeclarative1ImplicitSizePaintedItemPrivate : public QDeclarative1PaintedItemPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1ImplicitSizePaintedItem)
+
+public:
+ QDeclarative1ImplicitSizePaintedItemPrivate()
+ {
+ }
+
+ virtual void implicitWidthChanged();
+ virtual void implicitHeightChanged();
+};
+
+QT_END_NAMESPACE
+
+#endif // QDECLARATIVEIMPLICITSIZEITEM_P_H
diff --git a/src/qtquick1/graphicsitems/qdeclarativeitem.cpp b/src/qtquick1/graphicsitems/qdeclarativeitem.cpp
new file mode 100644
index 0000000000..46cfe526e4
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativeitem.cpp
@@ -0,0 +1,3815 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/qdeclarativeitem.h"
+
+#include "QtQuick1/private/qdeclarativeevents_p_p.h"
+#include <QtDeclarative/private/qdeclarativeengine_p.h>
+#include <private/qgraphicsitem_p.h>
+#include <QtQuick1/private/qdeclarativeitem_p.h>
+
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtQuick1/private/qdeclarativeopenmetaobject_p.h>
+#include <QtQuick1/private/qdeclarativestate_p.h>
+#include <QtQuick1/qdeclarativeview.h>
+#include <QtQuick1/private/qdeclarativestategroup_p.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+#include <QtDeclarative/qdeclarativeinfo.h>
+
+#include <QDebug>
+#include <QPen>
+#include <QEvent>
+#include <QGraphicsSceneMouseEvent>
+#include <QtCore/qnumeric.h>
+#include <QtScript/qscriptengine.h>
+#include <QtGui/qgraphicstransform.h>
+
+#include <private/qv8engine_p.h>
+
+#include <float.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmlclass Transform QGraphicsTransform
+ \ingroup qml-transform-elements
+ \since 4.7
+ \brief The Transform elements provide a way of building advanced transformations on Items.
+
+ The Transform element is a base type which cannot be instantiated directly.
+ The following concrete Transform types are available:
+
+ \list
+ \o \l Rotation
+ \o \l Scale
+ \o \l Translate
+ \endlist
+
+ The Transform elements let you create and control advanced transformations that can be configured
+ independently using specialized properties.
+
+ You can assign any number of Transform elements to an \l Item. Each Transform is applied in order,
+ one at a time.
+*/
+
+/*!
+ \qmlclass Translate QDeclarative1Translate
+ \ingroup qml-transform-elements
+ \since 4.7
+ \brief The Translate object provides a way to move an Item without changing its x or y properties.
+
+ The Translate object provides independent control over position in addition to the Item's x and y properties.
+
+ The following example moves the Y axis of the \l Rectangle elements while still allowing the \l Row element
+ to lay the items out as if they had not been transformed:
+ \qml
+ import QtQuick 1.0
+
+ Row {
+ Rectangle {
+ width: 100; height: 100
+ color: "blue"
+ transform: Translate { y: 20 }
+ }
+ Rectangle {
+ width: 100; height: 100
+ color: "red"
+ transform: Translate { y: -20 }
+ }
+ }
+ \endqml
+
+ \image translate.png
+*/
+
+/*!
+ \qmlproperty real Translate::x
+
+ The translation along the X axis.
+*/
+
+/*!
+ \qmlproperty real Translate::y
+
+ The translation along the Y axis.
+*/
+
+/*!
+ \qmlclass Scale QGraphicsScale
+ \ingroup qml-transform-elements
+ \since 4.7
+ \brief The Scale element provides a way to scale an Item.
+
+ The Scale element gives more control over scaling than using \l Item's \l{Item::scale}{scale} property. Specifically,
+ it allows a different scale for the x and y axes, and allows the scale to be relative to an
+ arbitrary point.
+
+ The following example scales the X axis of the Rectangle, relative to its interior point 25, 25:
+ \qml
+ Rectangle {
+ width: 100; height: 100
+ color: "blue"
+ transform: Scale { origin.x: 25; origin.y: 25; xScale: 3}
+ }
+ \endqml
+
+ \sa Rotation, Translate
+*/
+
+/*!
+ \qmlproperty real Scale::origin.x
+ \qmlproperty real Scale::origin.y
+
+ The point that the item is scaled from (i.e., the point that stays fixed relative to the parent as
+ the rest of the item grows). By default the origin is 0, 0.
+*/
+
+/*!
+ \qmlproperty real Scale::xScale
+
+ The scaling factor for the X axis.
+*/
+
+/*!
+ \qmlproperty real Scale::yScale
+
+ The scaling factor for the Y axis.
+*/
+
+/*!
+ \qmlclass Rotation QGraphicsRotation
+ \ingroup qml-transform-elements
+ \since 4.7
+ \brief The Rotation object provides a way to rotate an Item.
+
+ The Rotation object gives more control over rotation than using \l Item's \l{Item::rotation}{rotation} property.
+ Specifically, it allows (z axis) rotation to be relative to an arbitrary point.
+
+ The following example rotates a Rectangle around its interior point 25, 25:
+ \qml
+ Rectangle {
+ width: 100; height: 100
+ color: "blue"
+ transform: Rotation { origin.x: 25; origin.y: 25; angle: 45}
+ }
+ \endqml
+
+ Rotation also provides a way to specify 3D-like rotations for Items. For these types of
+ rotations you must specify the axis to rotate around in addition to the origin point.
+
+ The following example shows various 3D-like rotations applied to an \l Image.
+ \snippet doc/src/snippets/declarative/rotation.qml 0
+
+ \image axisrotation.png
+
+ \sa {declarative/ui-components/dialcontrol}{Dial Control example}, {declarative/toys/clocks}{Clocks example}
+*/
+
+/*!
+ \qmlproperty real Rotation::origin.x
+ \qmlproperty real Rotation::origin.y
+
+ The origin point of the rotation (i.e., the point that stays fixed relative to the parent as
+ the rest of the item rotates). By default the origin is 0, 0.
+*/
+
+/*!
+ \qmlproperty real Rotation::axis.x
+ \qmlproperty real Rotation::axis.y
+ \qmlproperty real Rotation::axis.z
+
+ The axis to rotate around. For simple (2D) rotation around a point, you do not need to specify an axis,
+ as the default axis is the z axis (\c{ axis { x: 0; y: 0; z: 1 } }).
+
+ For a typical 3D-like rotation you will usually specify both the origin and the axis.
+
+ \image 3d-rotation-axis.png
+*/
+
+/*!
+ \qmlproperty real Rotation::angle
+
+ The angle to rotate, in degrees clockwise.
+*/
+
+QDeclarative1Contents::QDeclarative1Contents(QDeclarativeItem *item) : m_item(item), m_x(0), m_y(0), m_width(0), m_height(0)
+{
+ //### optimize
+ connect(this, SIGNAL(rectChanged(QRectF)), m_item, SIGNAL(childrenRectChanged(QRectF)));
+}
+
+QDeclarative1Contents::~QDeclarative1Contents()
+{
+ QList<QGraphicsItem *> children = m_item->childItems();
+ for (int i = 0; i < children.count(); ++i) {
+ QDeclarativeItem *child = qobject_cast<QDeclarativeItem *>(children.at(i));
+ if(!child)//### Should this be ignoring non-QDeclarativeItem graphicsobjects?
+ continue;
+ QDeclarativeItemPrivate::get(child)->removeItemChangeListener(this, QDeclarativeItemPrivate::Geometry | QDeclarativeItemPrivate::Destroyed);
+ }
+}
+
+QRectF QDeclarative1Contents::rectF() const
+{
+ return QRectF(m_x, m_y, m_width, m_height);
+}
+
+void QDeclarative1Contents::calcHeight(QDeclarativeItem *changed)
+{
+ qreal oldy = m_y;
+ qreal oldheight = m_height;
+
+ if (changed) {
+ qreal top = oldy;
+ qreal bottom = oldy + oldheight;
+ qreal y = changed->y();
+ if (y + changed->height() > bottom)
+ bottom = y + changed->height();
+ if (y < top)
+ top = y;
+ m_y = top;
+ m_height = bottom - top;
+ } else {
+ qreal top = FLT_MAX;
+ qreal bottom = 0;
+ QList<QGraphicsItem *> children = m_item->childItems();
+ for (int i = 0; i < children.count(); ++i) {
+ QDeclarativeItem *child = qobject_cast<QDeclarativeItem *>(children.at(i));
+ if(!child)//### Should this be ignoring non-QDeclarativeItem graphicsobjects?
+ continue;
+ qreal y = child->y();
+ if (y + child->height() > bottom)
+ bottom = y + child->height();
+ if (y < top)
+ top = y;
+ }
+ if (!children.isEmpty())
+ m_y = top;
+ m_height = qMax(bottom - top, qreal(0.0));
+ }
+
+ if (m_height != oldheight || m_y != oldy)
+ emit rectChanged(rectF());
+}
+
+void QDeclarative1Contents::calcWidth(QDeclarativeItem *changed)
+{
+ qreal oldx = m_x;
+ qreal oldwidth = m_width;
+
+ if (changed) {
+ qreal left = oldx;
+ qreal right = oldx + oldwidth;
+ qreal x = changed->x();
+ if (x + changed->width() > right)
+ right = x + changed->width();
+ if (x < left)
+ left = x;
+ m_x = left;
+ m_width = right - left;
+ } else {
+ qreal left = FLT_MAX;
+ qreal right = 0;
+ QList<QGraphicsItem *> children = m_item->childItems();
+ for (int i = 0; i < children.count(); ++i) {
+ QDeclarativeItem *child = qobject_cast<QDeclarativeItem *>(children.at(i));
+ if(!child)//### Should this be ignoring non-QDeclarativeItem graphicsobjects?
+ continue;
+ qreal x = child->x();
+ if (x + child->width() > right)
+ right = x + child->width();
+ if (x < left)
+ left = x;
+ }
+ if (!children.isEmpty())
+ m_x = left;
+ m_width = qMax(right - left, qreal(0.0));
+ }
+
+ if (m_width != oldwidth || m_x != oldx)
+ emit rectChanged(rectF());
+}
+
+void QDeclarative1Contents::complete()
+{
+ QList<QGraphicsItem *> children = m_item->childItems();
+ for (int i = 0; i < children.count(); ++i) {
+ QDeclarativeItem *child = qobject_cast<QDeclarativeItem *>(children.at(i));
+ if(!child)//### Should this be ignoring non-QDeclarativeItem graphicsobjects?
+ continue;
+ QDeclarativeItemPrivate::get(child)->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry | QDeclarativeItemPrivate::Destroyed);
+ //###what about changes to visibility?
+ }
+
+ calcGeometry();
+}
+
+void QDeclarative1Contents::itemGeometryChanged(QDeclarativeItem *changed, const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ Q_UNUSED(changed)
+ //### we can only pass changed if the left edge has moved left, or the right edge has moved right
+ if (newGeometry.width() != oldGeometry.width() || newGeometry.x() != oldGeometry.x())
+ calcWidth(/*changed*/);
+ if (newGeometry.height() != oldGeometry.height() || newGeometry.y() != oldGeometry.y())
+ calcHeight(/*changed*/);
+}
+
+void QDeclarative1Contents::itemDestroyed(QDeclarativeItem *item)
+{
+ if (item)
+ QDeclarativeItemPrivate::get(item)->removeItemChangeListener(this, QDeclarativeItemPrivate::Geometry | QDeclarativeItemPrivate::Destroyed);
+ calcGeometry();
+}
+
+void QDeclarative1Contents::childRemoved(QDeclarativeItem *item)
+{
+ if (item)
+ QDeclarativeItemPrivate::get(item)->removeItemChangeListener(this, QDeclarativeItemPrivate::Geometry | QDeclarativeItemPrivate::Destroyed);
+ calcGeometry();
+}
+
+void QDeclarative1Contents::childAdded(QDeclarativeItem *item)
+{
+ if (item)
+ QDeclarativeItemPrivate::get(item)->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry | QDeclarativeItemPrivate::Destroyed);
+ calcWidth(item);
+ calcHeight(item);
+}
+
+QDeclarativeItemKeyFilter::QDeclarativeItemKeyFilter(QDeclarativeItem *item)
+: m_processPost(false), m_next(0)
+{
+ QDeclarativeItemPrivate *p =
+ item?static_cast<QDeclarativeItemPrivate *>(QGraphicsItemPrivate::get(item)):0;
+ if (p) {
+ m_next = p->keyHandler;
+ p->keyHandler = this;
+ }
+}
+
+QDeclarativeItemKeyFilter::~QDeclarativeItemKeyFilter()
+{
+}
+
+void QDeclarativeItemKeyFilter::keyPressed(QKeyEvent *event, bool post)
+{
+ if (m_next) m_next->keyPressed(event, post);
+}
+
+void QDeclarativeItemKeyFilter::keyReleased(QKeyEvent *event, bool post)
+{
+ if (m_next) m_next->keyReleased(event, post);
+}
+
+void QDeclarativeItemKeyFilter::inputMethodEvent(QInputMethodEvent *event, bool post)
+{
+ if (m_next) m_next->inputMethodEvent(event, post);
+}
+
+QVariant QDeclarativeItemKeyFilter::inputMethodQuery(Qt::InputMethodQuery query) const
+{
+ if (m_next) return m_next->inputMethodQuery(query);
+ return QVariant();
+}
+
+void QDeclarativeItemKeyFilter::componentComplete()
+{
+ if (m_next) m_next->componentComplete();
+}
+
+
+/*!
+ \qmlclass KeyNavigation QDeclarative1KeyNavigationAttached
+ \ingroup qml-basic-interaction-elements
+ \since 4.7
+ \brief The KeyNavigation attached property supports key navigation by arrow keys.
+
+ Key-based user interfaces commonly allow the use of arrow keys to navigate between
+ focusable items. The KeyNavigation attached property enables this behavior by providing a
+ convenient way to specify the item that should gain focus when an arrow or tab key is pressed.
+
+ The following example provides key navigation for a 2x2 grid of items:
+
+ \snippet doc/src/snippets/declarative/keynavigation.qml 0
+
+ The top-left item initially receives focus by setting \l {Item::}{focus} to
+ \c true. When an arrow key is pressed, the focus will move to the
+ appropriate item, as defined by the value that has been set for
+ the KeyNavigation \l left, \l right, \l up or \l down properties.
+
+ Note that if a KeyNavigation attached property receives the key press and release
+ events for a requested arrow or tab key, the event is accepted and does not
+ propagate any further.
+
+ By default, KeyNavigation receives key events after the item to which it is attached.
+ If the item accepts the key event, the KeyNavigation attached property will not
+ receive an event for that key. Setting the \l priority property to
+ \c KeyNavigation.BeforeItem allows the event to be used for key navigation
+ before the item, rather than after.
+
+ If item to which the focus is switching is not enabled or visible, an attempt will
+ be made to skip this item and focus on the next. This is possible if there are
+ a chain of items with the same KeyNavigation handler. If multiple items in a row are not enabled
+ or visible, they will also be skipped.
+
+ KeyNavigation will implicitly set the other direction to return focus to this item. So if you set
+ \l left to another item, \l right will be set on that item's KeyNavigation to set focus back to this
+ item. However, if that item's KeyNavigation has had right explicitly set then no change will occur.
+ This means that the above example could have been written, with the same behaviour, without specifing
+ KeyNavigation.right or KeyNavigation.down for any of the items.
+
+ \sa {Keys}{Keys attached property}
+*/
+
+/*!
+ \qmlproperty Item KeyNavigation::left
+ \qmlproperty Item KeyNavigation::right
+ \qmlproperty Item KeyNavigation::up
+ \qmlproperty Item KeyNavigation::down
+ \qmlproperty Item KeyNavigation::tab
+ \qmlproperty Item KeyNavigation::backtab
+
+ These properties hold the item to assign focus to
+ when the left, right, up or down cursor keys, or the
+ tab key are pressed.
+*/
+
+/*!
+ \qmlproperty Item KeyNavigation::tab
+ \qmlproperty Item KeyNavigation::backtab
+
+ These properties hold the item to assign focus to
+ when the Tab key or Shift+Tab key combination (Backtab) are pressed.
+*/
+
+QDeclarative1KeyNavigationAttached::QDeclarative1KeyNavigationAttached(QObject *parent)
+: QObject(*(new QDeclarative1KeyNavigationAttachedPrivate), parent),
+ QDeclarativeItemKeyFilter(qobject_cast<QDeclarativeItem*>(parent))
+{
+ m_processPost = true;
+}
+
+QDeclarative1KeyNavigationAttached *
+QDeclarative1KeyNavigationAttached::qmlAttachedProperties(QObject *obj)
+{
+ return new QDeclarative1KeyNavigationAttached(obj);
+}
+
+QDeclarativeItem *QDeclarative1KeyNavigationAttached::left() const
+{
+ Q_D(const QDeclarative1KeyNavigationAttached);
+ return d->left;
+}
+
+void QDeclarative1KeyNavigationAttached::setLeft(QDeclarativeItem *i)
+{
+ Q_D(QDeclarative1KeyNavigationAttached);
+ if (d->left == i)
+ return;
+ d->left = i;
+ d->leftSet = true;
+ QDeclarative1KeyNavigationAttached* other =
+ qobject_cast<QDeclarative1KeyNavigationAttached*>(qmlAttachedPropertiesObject<QDeclarative1KeyNavigationAttached>(i));
+ if(other && !other->d_func()->rightSet){
+ other->d_func()->right = qobject_cast<QDeclarativeItem*>(parent());
+ emit other->rightChanged();
+ }
+ emit leftChanged();
+}
+
+QDeclarativeItem *QDeclarative1KeyNavigationAttached::right() const
+{
+ Q_D(const QDeclarative1KeyNavigationAttached);
+ return d->right;
+}
+
+void QDeclarative1KeyNavigationAttached::setRight(QDeclarativeItem *i)
+{
+ Q_D(QDeclarative1KeyNavigationAttached);
+ if (d->right == i)
+ return;
+ d->right = i;
+ d->rightSet = true;
+ QDeclarative1KeyNavigationAttached* other =
+ qobject_cast<QDeclarative1KeyNavigationAttached*>(qmlAttachedPropertiesObject<QDeclarative1KeyNavigationAttached>(i));
+ if(other && !other->d_func()->leftSet){
+ other->d_func()->left = qobject_cast<QDeclarativeItem*>(parent());
+ emit other->leftChanged();
+ }
+ emit rightChanged();
+}
+
+QDeclarativeItem *QDeclarative1KeyNavigationAttached::up() const
+{
+ Q_D(const QDeclarative1KeyNavigationAttached);
+ return d->up;
+}
+
+void QDeclarative1KeyNavigationAttached::setUp(QDeclarativeItem *i)
+{
+ Q_D(QDeclarative1KeyNavigationAttached);
+ if (d->up == i)
+ return;
+ d->up = i;
+ d->upSet = true;
+ QDeclarative1KeyNavigationAttached* other =
+ qobject_cast<QDeclarative1KeyNavigationAttached*>(qmlAttachedPropertiesObject<QDeclarative1KeyNavigationAttached>(i));
+ if(other && !other->d_func()->downSet){
+ other->d_func()->down = qobject_cast<QDeclarativeItem*>(parent());
+ emit other->downChanged();
+ }
+ emit upChanged();
+}
+
+QDeclarativeItem *QDeclarative1KeyNavigationAttached::down() const
+{
+ Q_D(const QDeclarative1KeyNavigationAttached);
+ return d->down;
+}
+
+void QDeclarative1KeyNavigationAttached::setDown(QDeclarativeItem *i)
+{
+ Q_D(QDeclarative1KeyNavigationAttached);
+ if (d->down == i)
+ return;
+ d->down = i;
+ d->downSet = true;
+ QDeclarative1KeyNavigationAttached* other =
+ qobject_cast<QDeclarative1KeyNavigationAttached*>(qmlAttachedPropertiesObject<QDeclarative1KeyNavigationAttached>(i));
+ if(other && !other->d_func()->upSet){
+ other->d_func()->up = qobject_cast<QDeclarativeItem*>(parent());
+ emit other->upChanged();
+ }
+ emit downChanged();
+}
+
+QDeclarativeItem *QDeclarative1KeyNavigationAttached::tab() const
+{
+ Q_D(const QDeclarative1KeyNavigationAttached);
+ return d->tab;
+}
+
+void QDeclarative1KeyNavigationAttached::setTab(QDeclarativeItem *i)
+{
+ Q_D(QDeclarative1KeyNavigationAttached);
+ if (d->tab == i)
+ return;
+ d->tab = i;
+ d->tabSet = true;
+ QDeclarative1KeyNavigationAttached* other =
+ qobject_cast<QDeclarative1KeyNavigationAttached*>(qmlAttachedPropertiesObject<QDeclarative1KeyNavigationAttached>(i));
+ if(other && !other->d_func()->backtabSet){
+ other->d_func()->backtab = qobject_cast<QDeclarativeItem*>(parent());
+ emit other->backtabChanged();
+ }
+ emit tabChanged();
+}
+
+QDeclarativeItem *QDeclarative1KeyNavigationAttached::backtab() const
+{
+ Q_D(const QDeclarative1KeyNavigationAttached);
+ return d->backtab;
+}
+
+void QDeclarative1KeyNavigationAttached::setBacktab(QDeclarativeItem *i)
+{
+ Q_D(QDeclarative1KeyNavigationAttached);
+ if (d->backtab == i)
+ return;
+ d->backtab = i;
+ d->backtabSet = true;
+ QDeclarative1KeyNavigationAttached* other =
+ qobject_cast<QDeclarative1KeyNavigationAttached*>(qmlAttachedPropertiesObject<QDeclarative1KeyNavigationAttached>(i));
+ if(other && !other->d_func()->tabSet){
+ other->d_func()->tab = qobject_cast<QDeclarativeItem*>(parent());
+ emit other->tabChanged();
+ }
+ emit backtabChanged();
+}
+
+/*!
+ \qmlproperty enumeration KeyNavigation::priority
+
+ This property determines whether the keys are processed before
+ or after the attached item's own key handling.
+
+ \list
+ \o KeyNavigation.BeforeItem - process the key events before normal
+ item key processing. If the event is used for key navigation, it will be accepted and will not
+ be passed on to the item.
+ \o KeyNavigation.AfterItem (default) - process the key events after normal item key
+ handling. If the item accepts the key event it will not be
+ handled by the KeyNavigation attached property handler.
+ \endlist
+*/
+QDeclarative1KeyNavigationAttached::Priority QDeclarative1KeyNavigationAttached::priority() const
+{
+ return m_processPost ? AfterItem : BeforeItem;
+}
+
+void QDeclarative1KeyNavigationAttached::setPriority(Priority order)
+{
+ bool processPost = order == AfterItem;
+ if (processPost != m_processPost) {
+ m_processPost = processPost;
+ emit priorityChanged();
+ }
+}
+
+void QDeclarative1KeyNavigationAttached::keyPressed(QKeyEvent *event, bool post)
+{
+ Q_D(QDeclarative1KeyNavigationAttached);
+ event->ignore();
+
+ if (post != m_processPost) {
+ QDeclarativeItemKeyFilter::keyPressed(event, post);
+ return;
+ }
+
+ bool mirror = false;
+ switch(event->key()) {
+ case Qt::Key_Left: {
+ if (QDeclarativeItem *parentItem = qobject_cast<QDeclarativeItem*>(parent()))
+ mirror = QDeclarativeItemPrivate::get(parentItem)->effectiveLayoutMirror;
+ QDeclarativeItem* leftItem = mirror ? d->right : d->left;
+ if (leftItem) {
+ setFocusNavigation(leftItem, mirror ? "right" : "left");
+ event->accept();
+ }
+ break;
+ }
+ case Qt::Key_Right: {
+ if (QDeclarativeItem *parentItem = qobject_cast<QDeclarativeItem*>(parent()))
+ mirror = QDeclarativeItemPrivate::get(parentItem)->effectiveLayoutMirror;
+ QDeclarativeItem* rightItem = mirror ? d->left : d->right;
+ if (rightItem) {
+ setFocusNavigation(rightItem, mirror ? "left" : "right");
+ event->accept();
+ }
+ break;
+ }
+ case Qt::Key_Up:
+ if (d->up) {
+ setFocusNavigation(d->up, "up");
+ event->accept();
+ }
+ break;
+ case Qt::Key_Down:
+ if (d->down) {
+ setFocusNavigation(d->down, "down");
+ event->accept();
+ }
+ break;
+ case Qt::Key_Tab:
+ if (d->tab) {
+ setFocusNavigation(d->tab, "tab");
+ event->accept();
+ }
+ break;
+ case Qt::Key_Backtab:
+ if (d->backtab) {
+ setFocusNavigation(d->backtab, "backtab");
+ event->accept();
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (!event->isAccepted()) QDeclarativeItemKeyFilter::keyPressed(event, post);
+}
+
+void QDeclarative1KeyNavigationAttached::keyReleased(QKeyEvent *event, bool post)
+{
+ Q_D(QDeclarative1KeyNavigationAttached);
+ event->ignore();
+
+ if (post != m_processPost) {
+ QDeclarativeItemKeyFilter::keyReleased(event, post);
+ return;
+ }
+
+ bool mirror = false;
+ switch(event->key()) {
+ case Qt::Key_Left:
+ if (QDeclarativeItem *parentItem = qobject_cast<QDeclarativeItem*>(parent()))
+ mirror = QDeclarativeItemPrivate::get(parentItem)->effectiveLayoutMirror;
+ if (mirror ? d->right : d->left)
+ event->accept();
+ break;
+ case Qt::Key_Right:
+ if (QDeclarativeItem *parentItem = qobject_cast<QDeclarativeItem*>(parent()))
+ mirror = QDeclarativeItemPrivate::get(parentItem)->effectiveLayoutMirror;
+ if (mirror ? d->left : d->right)
+ event->accept();
+ break;
+ case Qt::Key_Up:
+ if (d->up) {
+ event->accept();
+ }
+ break;
+ case Qt::Key_Down:
+ if (d->down) {
+ event->accept();
+ }
+ break;
+ case Qt::Key_Tab:
+ if (d->tab) {
+ event->accept();
+ }
+ break;
+ case Qt::Key_Backtab:
+ if (d->backtab) {
+ event->accept();
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (!event->isAccepted()) QDeclarativeItemKeyFilter::keyReleased(event, post);
+}
+
+void QDeclarative1KeyNavigationAttached::setFocusNavigation(QDeclarativeItem *currentItem, const char *dir)
+{
+ QDeclarativeItem *initialItem = currentItem;
+ bool isNextItem = false;
+ do {
+ isNextItem = false;
+ if (currentItem->isVisible() && currentItem->isEnabled()) {
+ currentItem->setFocus(true);
+ } else {
+ QObject *attached =
+ qmlAttachedPropertiesObject<QDeclarative1KeyNavigationAttached>(currentItem, false);
+ if (attached) {
+ QDeclarativeItem *tempItem = qvariant_cast<QDeclarativeItem*>(attached->property(dir));
+ if (tempItem) {
+ currentItem = tempItem;
+ isNextItem = true;
+ }
+ }
+ }
+ }
+ while (currentItem != initialItem && isNextItem);
+}
+
+/*!
+ \qmlclass LayoutMirroring QDeclarative1LayoutMirroringAttached
+ \since QtQuick 1.1
+ \ingroup qml-utility-elements
+ \brief The LayoutMirroring attached property is used to mirror layout behavior.
+
+ The LayoutMirroring attached property is used to horizontally mirror \l {anchor-layout}{Item anchors},
+ \l{Using QML Positioner and Repeater Items}{positioner} elements (such as \l Row and \l Grid)
+ and views (such as \l GridView and horizontal \l ListView). Mirroring is a visual change: left
+ anchors become right anchors, and positioner elements like \l Grid and \l Row reverse the
+ horizontal layout of child items.
+
+ Mirroring is enabled for an item by setting the \l enabled property to true. By default, this
+ only affects the item itself; setting the \l childrenInherit property to true propagates the mirroring
+ behavior to all child elements as well. If the \c LayoutMirroring attached property has not been defined
+ for an item, mirroring is not enabled.
+
+ The following example shows mirroring in action. The \l Row below is specified as being anchored
+ to the left of its parent. However, since mirroring has been enabled, the anchor is horizontally
+ reversed and it is now anchored to the right. Also, since items in a \l Row are positioned
+ from left to right by default, they are now positioned from right to left instead, as demonstrated
+ by the numbering and opacity of the items:
+
+ \snippet doc/src/snippets/declarative/layoutmirroring.qml 0
+
+ \image layoutmirroring.png
+
+ Layout mirroring is useful when it is necessary to support both left-to-right and right-to-left
+ layout versions of an application to target different language areas. The \l childrenInherit
+ property allows layout mirroring to be applied without manually setting layout configurations
+ for every item in an application. Keep in mind, however, that mirroring does not affect any
+ positioning that is defined by the \l Item \l {Item::}{x} coordinate value, so even with
+ mirroring enabled, it will often be necessary to apply some layout fixes to support the
+ desired layout direction. Also, it may be necessary to disable the mirroring of individual
+ child items (by setting \l {enabled}{LayoutMirroring.enabled} to false for such items) if
+ mirroring is not the desired behavior, or if the child item already implements mirroring in
+ some custom way.
+
+ See \l {QML Right-to-left User Interfaces} for further details on using \c LayoutMirroring and
+ other related features to implement right-to-left support for an application.
+*/
+
+/*!
+ \qmlproperty bool LayoutMirroring::enabled
+
+ This property holds whether the item's layout is mirrored horizontally. Setting this to true
+ horizontally reverses \l {anchor-layout}{anchor} settings such that left anchors become right,
+ and right anchors become left. For \l{Using QML Positioner and Repeater Items}{positioner} elements
+ (such as \l Row and \l Grid) and view elements (such as \l {GridView}{GridView} and \l {ListView}{ListView})
+ this also mirrors the horizontal layout direction of the item.
+
+ The default value is false.
+*/
+
+/*!
+ \qmlproperty bool LayoutMirroring::childrenInherit
+
+ This property holds whether the \l {enabled}{LayoutMirroring.enabled} value for this item
+ is inherited by its children.
+
+ The default value is false.
+*/
+
+QDeclarative1LayoutMirroringAttached::QDeclarative1LayoutMirroringAttached(QObject *parent) : QObject(parent), itemPrivate(0)
+{
+ if (QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(parent)) {
+ itemPrivate = QDeclarativeItemPrivate::get(item);
+ itemPrivate->attachedLayoutDirection = this;
+ } else
+ qmlInfo(parent) << tr("LayoutDirection attached property only works with Items");
+}
+
+QDeclarative1LayoutMirroringAttached * QDeclarative1LayoutMirroringAttached::qmlAttachedProperties(QObject *object)
+{
+ return new QDeclarative1LayoutMirroringAttached(object);
+}
+
+bool QDeclarative1LayoutMirroringAttached::enabled() const
+{
+ return itemPrivate ? itemPrivate->effectiveLayoutMirror : false;
+}
+
+void QDeclarative1LayoutMirroringAttached::setEnabled(bool enabled)
+{
+ if (!itemPrivate)
+ return;
+
+ itemPrivate->isMirrorImplicit = false;
+ if (enabled != itemPrivate->effectiveLayoutMirror) {
+ itemPrivate->setLayoutMirror(enabled);
+ if (itemPrivate->inheritMirrorFromItem)
+ itemPrivate->resolveLayoutMirror();
+ }
+}
+
+void QDeclarative1LayoutMirroringAttached::resetEnabled()
+{
+ if (itemPrivate && !itemPrivate->isMirrorImplicit) {
+ itemPrivate->isMirrorImplicit = true;
+ itemPrivate->resolveLayoutMirror();
+ }
+}
+
+bool QDeclarative1LayoutMirroringAttached::childrenInherit() const
+{
+ return itemPrivate ? itemPrivate->inheritMirrorFromItem : false;
+}
+
+void QDeclarative1LayoutMirroringAttached::setChildrenInherit(bool childrenInherit) {
+ if (itemPrivate && childrenInherit != itemPrivate->inheritMirrorFromItem) {
+ itemPrivate->inheritMirrorFromItem = childrenInherit;
+ itemPrivate->resolveLayoutMirror();
+ childrenInheritChanged();
+ }
+}
+
+void QDeclarativeItemPrivate::resolveLayoutMirror()
+{
+ Q_Q(QDeclarativeItem);
+ if (QDeclarativeItem *parentItem = q->parentItem()) {
+ QDeclarativeItemPrivate *parentPrivate = QDeclarativeItemPrivate::get(parentItem);
+ setImplicitLayoutMirror(parentPrivate->inheritedLayoutMirror, parentPrivate->inheritMirrorFromParent);
+ } else {
+ setImplicitLayoutMirror(isMirrorImplicit ? false : effectiveLayoutMirror, inheritMirrorFromItem);
+ }
+}
+
+void QDeclarativeItemPrivate::setImplicitLayoutMirror(bool mirror, bool inherit)
+{
+ inherit = inherit || inheritMirrorFromItem;
+ if (!isMirrorImplicit && inheritMirrorFromItem)
+ mirror = effectiveLayoutMirror;
+ if (mirror == inheritedLayoutMirror && inherit == inheritMirrorFromParent)
+ return;
+
+ inheritMirrorFromParent = inherit;
+ inheritedLayoutMirror = inheritMirrorFromParent ? mirror : false;
+
+ if (isMirrorImplicit)
+ setLayoutMirror(inherit ? inheritedLayoutMirror : false);
+ for (int i = 0; i < children.count(); ++i) {
+ if (QDeclarativeItem *child = qobject_cast<QDeclarativeItem *>(children.at(i))) {
+ QDeclarativeItemPrivate *childPrivate = QDeclarativeItemPrivate::get(child);
+ childPrivate->setImplicitLayoutMirror(inheritedLayoutMirror, inheritMirrorFromParent);
+ }
+ }
+}
+
+void QDeclarativeItemPrivate::setLayoutMirror(bool mirror)
+{
+ if (mirror != effectiveLayoutMirror) {
+ effectiveLayoutMirror = mirror;
+ if (_anchors) {
+ _anchors->d_func()->fillChanged();
+ _anchors->d_func()->centerInChanged();
+ _anchors->d_func()->updateHorizontalAnchors();
+ emit _anchors->mirroredChanged();
+ }
+ mirrorChange();
+ if (attachedLayoutDirection) {
+ emit attachedLayoutDirection->enabledChanged();
+ }
+ }
+}
+
+/*!
+ \qmlclass Keys QDeclarative1KeysAttached
+ \ingroup qml-basic-interaction-elements
+ \since 4.7
+ \brief The Keys attached property provides key handling to Items.
+
+ All visual primitives support key handling via the Keys
+ attached property. Keys can be handled via the onPressed
+ and onReleased signal properties.
+
+ The signal properties have a \l KeyEvent parameter, named
+ \e event which contains details of the event. If a key is
+ handled \e event.accepted should be set to true to prevent the
+ event from propagating up the item hierarchy.
+
+ \section1 Example Usage
+
+ The following example shows how the general onPressed handler can
+ be used to test for a certain key; in this case, the left cursor
+ key:
+
+ \snippet doc/src/snippets/declarative/keys/keys-pressed.qml key item
+
+ Some keys may alternatively be handled via specific signal properties,
+ for example \e onSelectPressed. These handlers automatically set
+ \e event.accepted to true.
+
+ \snippet doc/src/snippets/declarative/keys/keys-handler.qml key item
+
+ See \l{Qt::Key}{Qt.Key} for the list of keyboard codes.
+
+ \section1 Key Handling Priorities
+
+ The Keys attached property can be configured to handle key events
+ before or after the item it is attached to. This makes it possible
+ to intercept events in order to override an item's default behavior,
+ or act as a fallback for keys not handled by the item.
+
+ If \l priority is Keys.BeforeItem (default) the order of key event processing is:
+
+ \list 1
+ \o Items specified in \c forwardTo
+ \o specific key handlers, e.g. onReturnPressed
+ \o onKeyPress, onKeyRelease handlers
+ \o Item specific key handling, e.g. TextInput key handling
+ \o parent item
+ \endlist
+
+ If priority is Keys.AfterItem the order of key event processing is:
+
+ \list 1
+ \o Item specific key handling, e.g. TextInput key handling
+ \o Items specified in \c forwardTo
+ \o specific key handlers, e.g. onReturnPressed
+ \o onKeyPress, onKeyRelease handlers
+ \o parent item
+ \endlist
+
+ If the event is accepted during any of the above steps, key
+ propagation stops.
+
+ \sa KeyEvent, {KeyNavigation}{KeyNavigation attached property}
+*/
+
+/*!
+ \qmlproperty bool Keys::enabled
+
+ This flags enables key handling if true (default); otherwise
+ no key handlers will be called.
+*/
+
+/*!
+ \qmlproperty enumeration Keys::priority
+
+ This property determines whether the keys are processed before
+ or after the attached item's own key handling.
+
+ \list
+ \o Keys.BeforeItem (default) - process the key events before normal
+ item key processing. If the event is accepted it will not
+ be passed on to the item.
+ \o Keys.AfterItem - process the key events after normal item key
+ handling. If the item accepts the key event it will not be
+ handled by the Keys attached property handler.
+ \endlist
+*/
+
+/*!
+ \qmlproperty list<Object> Keys::forwardTo
+
+ This property provides a way to forward key presses, key releases, and keyboard input
+ coming from input methods to other items. This can be useful when you want
+ one item to handle some keys (e.g. the up and down arrow keys), and another item to
+ handle other keys (e.g. the left and right arrow keys). Once an item that has been
+ forwarded keys accepts the event it is no longer forwarded to items later in the
+ list.
+
+ This example forwards key events to two lists:
+ \qml
+ Item {
+ ListView {
+ id: list1
+ // ...
+ }
+ ListView {
+ id: list2
+ // ...
+ }
+ Keys.forwardTo: [list1, list2]
+ focus: true
+ }
+ \endqml
+*/
+
+/*!
+ \qmlsignal Keys::onPressed(KeyEvent event)
+
+ This handler is called when a key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onReleased(KeyEvent event)
+
+ This handler is called when a key has been released. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onDigit0Pressed(KeyEvent event)
+
+ This handler is called when the digit '0' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onDigit1Pressed(KeyEvent event)
+
+ This handler is called when the digit '1' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onDigit2Pressed(KeyEvent event)
+
+ This handler is called when the digit '2' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onDigit3Pressed(KeyEvent event)
+
+ This handler is called when the digit '3' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onDigit4Pressed(KeyEvent event)
+
+ This handler is called when the digit '4' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onDigit5Pressed(KeyEvent event)
+
+ This handler is called when the digit '5' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onDigit6Pressed(KeyEvent event)
+
+ This handler is called when the digit '6' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onDigit7Pressed(KeyEvent event)
+
+ This handler is called when the digit '7' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onDigit8Pressed(KeyEvent event)
+
+ This handler is called when the digit '8' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onDigit9Pressed(KeyEvent event)
+
+ This handler is called when the digit '9' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onLeftPressed(KeyEvent event)
+
+ This handler is called when the Left arrow has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onRightPressed(KeyEvent event)
+
+ This handler is called when the Right arrow has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onUpPressed(KeyEvent event)
+
+ This handler is called when the Up arrow has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onDownPressed(KeyEvent event)
+
+ This handler is called when the Down arrow has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onTabPressed(KeyEvent event)
+
+ This handler is called when the Tab key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onBacktabPressed(KeyEvent event)
+
+ This handler is called when the Shift+Tab key combination (Backtab) has
+ been pressed. The \a event parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onAsteriskPressed(KeyEvent event)
+
+ This handler is called when the Asterisk '*' has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onEscapePressed(KeyEvent event)
+
+ This handler is called when the Escape key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onReturnPressed(KeyEvent event)
+
+ This handler is called when the Return key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onEnterPressed(KeyEvent event)
+
+ This handler is called when the Enter key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onDeletePressed(KeyEvent event)
+
+ This handler is called when the Delete key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onSpacePressed(KeyEvent event)
+
+ This handler is called when the Space key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onBackPressed(KeyEvent event)
+
+ This handler is called when the Back key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onCancelPressed(KeyEvent event)
+
+ This handler is called when the Cancel key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onSelectPressed(KeyEvent event)
+
+ This handler is called when the Select key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onYesPressed(KeyEvent event)
+
+ This handler is called when the Yes key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onNoPressed(KeyEvent event)
+
+ This handler is called when the No key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onContext1Pressed(KeyEvent event)
+
+ This handler is called when the Context1 key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onContext2Pressed(KeyEvent event)
+
+ This handler is called when the Context2 key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onContext3Pressed(KeyEvent event)
+
+ This handler is called when the Context3 key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onContext4Pressed(KeyEvent event)
+
+ This handler is called when the Context4 key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onCallPressed(KeyEvent event)
+
+ This handler is called when the Call key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onHangupPressed(KeyEvent event)
+
+ This handler is called when the Hangup key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onFlipPressed(KeyEvent event)
+
+ This handler is called when the Flip key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onMenuPressed(KeyEvent event)
+
+ This handler is called when the Menu key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onVolumeUpPressed(KeyEvent event)
+
+ This handler is called when the VolumeUp key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+/*!
+ \qmlsignal Keys::onVolumeDownPressed(KeyEvent event)
+
+ This handler is called when the VolumeDown key has been pressed. The \a event
+ parameter provides information about the event.
+*/
+
+const QDeclarative1KeysAttached::SigMap QDeclarative1KeysAttached::sigMap[] = {
+ { Qt::Key_Left, "leftPressed" },
+ { Qt::Key_Right, "rightPressed" },
+ { Qt::Key_Up, "upPressed" },
+ { Qt::Key_Down, "downPressed" },
+ { Qt::Key_Tab, "tabPressed" },
+ { Qt::Key_Backtab, "backtabPressed" },
+ { Qt::Key_Asterisk, "asteriskPressed" },
+ { Qt::Key_NumberSign, "numberSignPressed" },
+ { Qt::Key_Escape, "escapePressed" },
+ { Qt::Key_Return, "returnPressed" },
+ { Qt::Key_Enter, "enterPressed" },
+ { Qt::Key_Delete, "deletePressed" },
+ { Qt::Key_Space, "spacePressed" },
+ { Qt::Key_Back, "backPressed" },
+ { Qt::Key_Cancel, "cancelPressed" },
+ { Qt::Key_Select, "selectPressed" },
+ { Qt::Key_Yes, "yesPressed" },
+ { Qt::Key_No, "noPressed" },
+ { Qt::Key_Context1, "context1Pressed" },
+ { Qt::Key_Context2, "context2Pressed" },
+ { Qt::Key_Context3, "context3Pressed" },
+ { Qt::Key_Context4, "context4Pressed" },
+ { Qt::Key_Call, "callPressed" },
+ { Qt::Key_Hangup, "hangupPressed" },
+ { Qt::Key_Flip, "flipPressed" },
+ { Qt::Key_Menu, "menuPressed" },
+ { Qt::Key_VolumeUp, "volumeUpPressed" },
+ { Qt::Key_VolumeDown, "volumeDownPressed" },
+ { 0, 0 }
+};
+
+bool QDeclarative1KeysAttachedPrivate::isConnected(const char *signalName)
+{
+ return isSignalConnected(signalIndex(signalName));
+}
+
+QDeclarative1KeysAttached::QDeclarative1KeysAttached(QObject *parent)
+: QObject(*(new QDeclarative1KeysAttachedPrivate), parent),
+ QDeclarativeItemKeyFilter(qobject_cast<QDeclarativeItem*>(parent))
+{
+ Q_D(QDeclarative1KeysAttached);
+ m_processPost = false;
+ d->item = qobject_cast<QDeclarativeItem*>(parent);
+}
+
+QDeclarative1KeysAttached::~QDeclarative1KeysAttached()
+{
+}
+
+QDeclarative1KeysAttached::Priority QDeclarative1KeysAttached::priority() const
+{
+ return m_processPost ? AfterItem : BeforeItem;
+}
+
+void QDeclarative1KeysAttached::setPriority(Priority order)
+{
+ bool processPost = order == AfterItem;
+ if (processPost != m_processPost) {
+ m_processPost = processPost;
+ emit priorityChanged();
+ }
+}
+
+void QDeclarative1KeysAttached::componentComplete()
+{
+ Q_D(QDeclarative1KeysAttached);
+ if (d->item) {
+ for (int ii = 0; ii < d->targets.count(); ++ii) {
+ QGraphicsItem *targetItem = d->finalFocusProxy(d->targets.at(ii));
+ if (targetItem && (targetItem->flags() & QGraphicsItem::ItemAcceptsInputMethod)) {
+ d->item->setFlag(QGraphicsItem::ItemAcceptsInputMethod);
+ break;
+ }
+ }
+ }
+}
+
+void QDeclarative1KeysAttached::keyPressed(QKeyEvent *event, bool post)
+{
+ Q_D(QDeclarative1KeysAttached);
+ if (post != m_processPost || !d->enabled || d->inPress) {
+ event->ignore();
+ QDeclarativeItemKeyFilter::keyPressed(event, post);
+ return;
+ }
+
+ // first process forwards
+ if (d->item && d->item->scene()) {
+ d->inPress = true;
+ for (int ii = 0; ii < d->targets.count(); ++ii) {
+ QGraphicsItem *i = d->finalFocusProxy(d->targets.at(ii));
+ if (i && i->isVisible()) {
+ d->item->scene()->sendEvent(i, event);
+ if (event->isAccepted()) {
+ d->inPress = false;
+ return;
+ }
+ }
+ }
+ d->inPress = false;
+ }
+
+ QDeclarative1KeyEvent ke(*event);
+ QByteArray keySignal = keyToSignal(event->key());
+ if (!keySignal.isEmpty()) {
+ keySignal += "(QDeclarative1KeyEvent*)";
+ if (d->isConnected(keySignal)) {
+ // If we specifically handle a key then default to accepted
+ ke.setAccepted(true);
+ int idx = QDeclarative1KeysAttached::staticMetaObject.indexOfSignal(keySignal);
+ metaObject()->method(idx).invoke(this, Qt::DirectConnection, Q_ARG(QDeclarative1KeyEvent*, &ke));
+ }
+ }
+ if (!ke.isAccepted())
+ emit pressed(&ke);
+ event->setAccepted(ke.isAccepted());
+
+ if (!event->isAccepted()) QDeclarativeItemKeyFilter::keyPressed(event, post);
+}
+
+void QDeclarative1KeysAttached::keyReleased(QKeyEvent *event, bool post)
+{
+ Q_D(QDeclarative1KeysAttached);
+ if (post != m_processPost || !d->enabled || d->inRelease) {
+ event->ignore();
+ QDeclarativeItemKeyFilter::keyReleased(event, post);
+ return;
+ }
+
+ if (d->item && d->item->scene()) {
+ d->inRelease = true;
+ for (int ii = 0; ii < d->targets.count(); ++ii) {
+ QGraphicsItem *i = d->finalFocusProxy(d->targets.at(ii));
+ if (i && i->isVisible()) {
+ d->item->scene()->sendEvent(i, event);
+ if (event->isAccepted()) {
+ d->inRelease = false;
+ return;
+ }
+ }
+ }
+ d->inRelease = false;
+ }
+
+ QDeclarative1KeyEvent ke(*event);
+ emit released(&ke);
+ event->setAccepted(ke.isAccepted());
+
+ if (!event->isAccepted()) QDeclarativeItemKeyFilter::keyReleased(event, post);
+}
+
+void QDeclarative1KeysAttached::inputMethodEvent(QInputMethodEvent *event, bool post)
+{
+ Q_D(QDeclarative1KeysAttached);
+ if (post == m_processPost && d->item && !d->inIM && d->item->scene()) {
+ d->inIM = true;
+ for (int ii = 0; ii < d->targets.count(); ++ii) {
+ QGraphicsItem *i = d->finalFocusProxy(d->targets.at(ii));
+ if (i && i->isVisible() && (i->flags() & QGraphicsItem::ItemAcceptsInputMethod)) {
+ d->item->scene()->sendEvent(i, event);
+ if (event->isAccepted()) {
+ d->imeItem = i;
+ d->inIM = false;
+ return;
+ }
+ }
+ }
+ d->inIM = false;
+ }
+ if (!event->isAccepted()) QDeclarativeItemKeyFilter::inputMethodEvent(event, post);
+}
+
+class QDeclarativeItemAccessor : public QGraphicsItem
+{
+public:
+ QVariant doInputMethodQuery(Qt::InputMethodQuery query) const {
+ return QGraphicsItem::inputMethodQuery(query);
+ }
+};
+
+QVariant QDeclarative1KeysAttached::inputMethodQuery(Qt::InputMethodQuery query) const
+{
+ Q_D(const QDeclarative1KeysAttached);
+ if (d->item) {
+ for (int ii = 0; ii < d->targets.count(); ++ii) {
+ QGraphicsItem *i = d->finalFocusProxy(d->targets.at(ii));
+ if (i && i->isVisible() && (i->flags() & QGraphicsItem::ItemAcceptsInputMethod) && i == d->imeItem) { //### how robust is i == d->imeItem check?
+ QVariant v = static_cast<QDeclarativeItemAccessor *>(i)->doInputMethodQuery(query);
+ if (v.userType() == QVariant::RectF)
+ v = d->item->mapRectFromItem(i, v.toRectF()); //### cost?
+ return v;
+ }
+ }
+ }
+ return QDeclarativeItemKeyFilter::inputMethodQuery(query);
+}
+
+QDeclarative1KeysAttached *QDeclarative1KeysAttached::qmlAttachedProperties(QObject *obj)
+{
+ return new QDeclarative1KeysAttached(obj);
+}
+
+/*!
+ \class QDeclarativeItem
+ \since 4.7
+ \brief The QDeclarativeItem class provides the most basic of all visual items in QML.
+
+ All visual items in Qt Declarative inherit from QDeclarativeItem. Although QDeclarativeItem
+ has no visual appearance, it defines all the properties that are
+ common across visual items - such as the x and y position, the
+ width and height, \l {anchor-layout}{anchoring} and key handling.
+
+ You can subclass QDeclarativeItem to provide your own custom visual item that inherits
+ these features. Note that, because it does not draw anything, QDeclarativeItem sets the
+ QGraphicsItem::ItemHasNoContents flag. If you subclass QDeclarativeItem to create a visual
+ item, you will need to unset this flag.
+
+*/
+
+/*!
+ \qmlclass Item QDeclarativeItem
+ \ingroup qml-basic-visual-elements
+ \since 4.7
+ \brief The Item is the most basic of all visual items in QML.
+
+ All visual items in Qt Declarative inherit from Item. Although Item
+ has no visual appearance, it defines all the properties that are
+ common across visual items - such as the x and y position, the
+ width and height, \l {anchor-layout}{anchoring} and key handling.
+
+ Item is also useful for grouping items together.
+
+ \qml
+ Item {
+ Image {
+ source: "tile.png"
+ }
+ Image {
+ x: 80
+ width: 100
+ height: 100
+ source: "tile.png"
+ }
+ Image {
+ x: 190
+ width: 100
+ height: 100
+ fillMode: Image.Tile
+ source: "tile.png"
+ }
+ }
+ \endqml
+
+
+ \section1 Key Handling
+
+ Key handling is available to all Item-based visual elements via the \l {Keys}{Keys}
+ attached property. The \e Keys attached property provides basic handlers such
+ as \l {Keys::onPressed}{onPressed} and \l {Keys::onReleased}{onReleased},
+ as well as handlers for specific keys, such as
+ \l {Keys::onCancelPressed}{onCancelPressed}. The example below
+ assigns \l {qmlfocus}{focus} to the item and handles
+ the Left key via the general \e onPressed handler and the Select key via the
+ onSelectPressed handler:
+
+ \qml
+ Item {
+ focus: true
+ Keys.onPressed: {
+ if (event.key == Qt.Key_Left) {
+ console.log("move left");
+ event.accepted = true;
+ }
+ }
+ Keys.onSelectPressed: console.log("Selected");
+ }
+ \endqml
+
+ See the \l {Keys}{Keys} attached property for detailed documentation.
+
+ \section1 Layout Mirroring
+
+ Item layouts can be mirrored using the \l {LayoutMirroring}{LayoutMirroring} attached property.
+
+*/
+
+/*!
+ \fn void QDeclarativeItem::childrenRectChanged(const QRectF &)
+ \internal
+*/
+
+/*!
+ \fn void QDeclarativeItem::baselineOffsetChanged(qreal)
+ \internal
+*/
+
+/*!
+ \fn void QDeclarativeItem::stateChanged(const QString &state)
+ \internal
+*/
+
+/*!
+ \fn void QDeclarativeItem::parentChanged(QDeclarativeItem *)
+ \internal
+*/
+
+/*!
+ \fn void QDeclarativeItem::smoothChanged(bool)
+ \internal
+*/
+
+/*!
+ \fn void QDeclarativeItem::clipChanged(bool)
+ \internal
+*/
+
+/*! \fn void QDeclarativeItem::transformOriginChanged(TransformOrigin)
+ \internal
+*/
+
+/*!
+ \fn void QDeclarativeItem::focusChanged(bool)
+ \internal
+*/
+
+/*!
+ \fn void QDeclarativeItem::activeFocusChanged(bool)
+ \internal
+*/
+
+// ### Must fix
+namespace {
+struct RegisterAnchorLineAtStartup {
+ RegisterAnchorLineAtStartup() {
+ qRegisterMetaType<QDeclarative1AnchorLine>("QDeclarative1AnchorLine");
+ }
+};
+static RegisterAnchorLineAtStartup registerAnchorLineAtStartup;
+}
+
+
+/*!
+ \fn QDeclarativeItem::QDeclarativeItem(QDeclarativeItem *parent)
+
+ Constructs a QDeclarativeItem with the given \a parent.
+*/
+QDeclarativeItem::QDeclarativeItem(QDeclarativeItem* parent)
+ : QGraphicsObject(*(new QDeclarativeItemPrivate), parent, 0)
+{
+ Q_D(QDeclarativeItem);
+ d->init(parent);
+}
+
+/*! \internal
+*/
+QDeclarativeItem::QDeclarativeItem(QDeclarativeItemPrivate &dd, QDeclarativeItem *parent)
+ : QGraphicsObject(dd, parent, 0)
+{
+ Q_D(QDeclarativeItem);
+ d->init(parent);
+}
+
+/*!
+ Destroys the QDeclarativeItem.
+*/
+QDeclarativeItem::~QDeclarativeItem()
+{
+ Q_D(QDeclarativeItem);
+ for (int ii = 0; ii < d->changeListeners.count(); ++ii) {
+ QDeclarative1AnchorsPrivate *anchor = d->changeListeners.at(ii).listener->anchorPrivate();
+ if (anchor)
+ anchor->clearItem(this);
+ }
+ if (!d->parent || (parentItem() && !parentItem()->QGraphicsItem::d_ptr->inDestructor)) {
+ for (int ii = 0; ii < d->changeListeners.count(); ++ii) {
+ QDeclarative1AnchorsPrivate *anchor = d->changeListeners.at(ii).listener->anchorPrivate();
+ if (anchor && anchor->item && anchor->item->parentItem() != this) //child will be deleted anyway
+ anchor->updateOnComplete();
+ }
+ }
+ for(int ii = 0; ii < d->changeListeners.count(); ++ii) {
+ const QDeclarativeItemPrivate::ChangeListener &change = d->changeListeners.at(ii);
+ if (change.types & QDeclarativeItemPrivate::Destroyed)
+ change.listener->itemDestroyed(this);
+ }
+ d->changeListeners.clear();
+ delete d->_anchorLines; d->_anchorLines = 0;
+ delete d->_anchors; d->_anchors = 0;
+ delete d->_stateGroup; d->_stateGroup = 0;
+ delete d->_contents; d->_contents = 0;
+}
+
+/*!
+ \qmlproperty enumeration Item::transformOrigin
+ This property holds the origin point around which scale and rotation transform.
+
+ Nine transform origins are available, as shown in the image below.
+
+ \image declarative-transformorigin.png
+
+ This example rotates an image around its bottom-right corner.
+ \qml
+ Image {
+ source: "myimage.png"
+ transformOrigin: Item.BottomRight
+ rotation: 45
+ }
+ \endqml
+
+ The default transform origin is \c Item.Center.
+
+ To set an arbitrary transform origin point use the \l Scale or \l Rotation
+ transform elements.
+*/
+
+/*!
+ \qmlproperty Item Item::parent
+ This property holds the parent of the item.
+*/
+
+/*!
+ \property QDeclarativeItem::parent
+ This property holds the parent of the item.
+*/
+void QDeclarativeItem::setParentItem(QDeclarativeItem *parent)
+{
+ QGraphicsObject::setParentItem(parent);
+}
+
+/*!
+ Returns the QDeclarativeItem parent of this item.
+*/
+QDeclarativeItem *QDeclarativeItem::parentItem() const
+{
+ return qobject_cast<QDeclarativeItem *>(QGraphicsObject::parentItem());
+}
+
+/*!
+ \qmlproperty real Item::childrenRect.x
+ \qmlproperty real Item::childrenRect.y
+ \qmlproperty real Item::childrenRect.width
+ \qmlproperty real Item::childrenRect.height
+
+ The childrenRect properties allow an item access to the geometry of its
+ children. This property is useful if you have an item that needs to be
+ sized to fit its children.
+*/
+
+
+/*!
+ \qmlproperty list<Item> Item::children
+ \qmlproperty list<Object> Item::resources
+
+ The children property contains the list of visual children of this item.
+ The resources property contains non-visual resources that you want to
+ reference by name.
+
+ Generally you can rely on Item's default property to handle all this for
+ you, but it can come in handy in some cases.
+
+ \qml
+ Item {
+ children: [
+ Text {},
+ Rectangle {}
+ ]
+ resources: [
+ Component {
+ id: myComponent
+ Text {}
+ }
+ ]
+ }
+ \endqml
+*/
+
+/*!
+ Returns true if construction of the QML component is complete; otherwise
+ returns false.
+
+ It is often desirable to delay some processing until the component is
+ completed.
+
+ \sa componentComplete()
+*/
+bool QDeclarativeItem::isComponentComplete() const
+{
+ Q_D(const QDeclarativeItem);
+ return d->componentComplete;
+}
+
+void QDeclarativeItemPrivate::data_append(QDeclarativeListProperty<QObject> *prop, QObject *o)
+{
+ if (!o)
+ return;
+
+ QDeclarativeItem *that = static_cast<QDeclarativeItem *>(prop->object);
+
+ // This test is measurably (albeit only slightly) faster than qobject_cast<>()
+ const QMetaObject *mo = o->metaObject();
+ while (mo && mo != &QGraphicsObject::staticMetaObject) mo = mo->d.superdata;
+
+ if (mo) {
+ QGraphicsObject *graphicsObject = static_cast<QGraphicsObject *>(o);
+ QDeclarativeItemPrivate *contentItemPrivate = static_cast<QDeclarativeItemPrivate *>(QGraphicsItemPrivate::get(graphicsObject));
+ if (contentItemPrivate->componentComplete) {
+ graphicsObject->setParentItem(that);
+ } else {
+ contentItemPrivate->setParentItemHelper(that, /*newParentVariant=*/0, /*thisPointerVariant=*/0);
+ }
+ } else {
+ o->setParent(that);
+ }
+}
+
+static inline int children_count_helper(QDeclarativeListProperty<QObject> *prop)
+{
+ QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(static_cast<QGraphicsObject *>(prop->object));
+ return d->children.count();
+}
+
+static inline QObject *children_at_helper(QDeclarativeListProperty<QObject> *prop, int index)
+{
+ QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(static_cast<QGraphicsObject *>(prop->object));
+ if (index >= 0 && index < d->children.count())
+ return d->children.at(index)->toGraphicsObject();
+ else
+ return 0;
+}
+
+static inline void children_clear_helper(QDeclarativeListProperty<QObject> *prop)
+{
+ QDeclarativeItemPrivate *d = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(static_cast<QGraphicsObject *>(prop->object)));
+ int childCount = d->children.count();
+ if (d->componentComplete) {
+ for (int index = 0 ;index < childCount; index++)
+ d->children.at(0)->setParentItem(0);
+ } else {
+ for (int index = 0 ;index < childCount; index++)
+ QGraphicsItemPrivate::get(d->children.at(0))->setParentItemHelper(0, /*newParentVariant=*/0, /*thisPointerVariant=*/0);
+ }
+}
+
+int QDeclarativeItemPrivate::data_count(QDeclarativeListProperty<QObject> *prop)
+{
+ return resources_count(prop) + children_count_helper(prop);
+}
+
+QObject *QDeclarativeItemPrivate::data_at(QDeclarativeListProperty<QObject> *prop, int i)
+{
+ int resourcesCount = resources_count(prop);
+ if (i < resourcesCount)
+ return resources_at(prop, i);
+ const int j = i - resourcesCount;
+ if (j < children_count_helper(prop))
+ return children_at_helper(prop, j);
+ return 0;
+}
+
+void QDeclarativeItemPrivate::data_clear(QDeclarativeListProperty<QObject> *prop)
+{
+ resources_clear(prop);
+ children_clear_helper(prop);
+}
+
+QObject *QDeclarativeItemPrivate::resources_at(QDeclarativeListProperty<QObject> *prop, int index)
+{
+ const QObjectList children = prop->object->children();
+ if (index < children.count())
+ return children.at(index);
+ else
+ return 0;
+}
+
+void QDeclarativeItemPrivate::resources_append(QDeclarativeListProperty<QObject> *prop, QObject *o)
+{
+ o->setParent(prop->object);
+}
+
+int QDeclarativeItemPrivate::resources_count(QDeclarativeListProperty<QObject> *prop)
+{
+ return prop->object->children().count();
+}
+
+void QDeclarativeItemPrivate::resources_clear(QDeclarativeListProperty<QObject> *prop)
+{
+ const QObjectList children = prop->object->children();
+ for (int index = 0; index < children.count(); index++)
+ children.at(index)->setParent(0);
+}
+
+int QDeclarativeItemPrivate::transform_count(QDeclarativeListProperty<QGraphicsTransform> *list)
+{
+ QGraphicsObject *object = qobject_cast<QGraphicsObject *>(list->object);
+ if (object) {
+ QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(object);
+ return d->transformData ? d->transformData->graphicsTransforms.size() : 0;
+ } else {
+ return 0;
+ }
+}
+
+void QDeclarativeItemPrivate::transform_append(QDeclarativeListProperty<QGraphicsTransform> *list, QGraphicsTransform *item)
+{
+ QGraphicsObject *object = qobject_cast<QGraphicsObject *>(list->object);
+ if (object && item) // QGraphicsItem applies the list in the wrong order, so we prepend.
+ QGraphicsItemPrivate::get(object)->prependGraphicsTransform(item);
+}
+
+QGraphicsTransform *QDeclarativeItemPrivate::transform_at(QDeclarativeListProperty<QGraphicsTransform> *list, int idx)
+{
+ QGraphicsObject *object = qobject_cast<QGraphicsObject *>(list->object);
+ if (object) {
+ QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(object);
+ if (!d->transformData)
+ return 0;
+ return d->transformData->graphicsTransforms.at(idx);
+ } else {
+ return 0;
+ }
+}
+
+void QDeclarativeItemPrivate::transform_clear(QDeclarativeListProperty<QGraphicsTransform> *list)
+{
+ QGraphicsObject *object = qobject_cast<QGraphicsObject *>(list->object);
+ if (object) {
+ QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(object);
+ if (!d->transformData)
+ return;
+ object->setTransformations(QList<QGraphicsTransform *>());
+ }
+}
+
+void QDeclarativeItemPrivate::parentProperty(QObject *o, void *rv, QDeclarativeNotifierEndpoint *e)
+{
+ QDeclarativeItem *item = static_cast<QDeclarativeItem*>(o);
+ if (e)
+ e->connect(&item->d_func()->parentNotifier);
+ *((QDeclarativeItem **)rv) = item->parentItem();
+}
+
+/*!
+ \qmlproperty list<Object> Item::data
+ \default
+
+ The data property allows you to freely mix visual children and resources
+ in an item. If you assign a visual item to the data list it becomes
+ a child and if you assign any other object type, it is added as a resource.
+
+ So you can write:
+ \qml
+ Item {
+ Text {}
+ Rectangle {}
+ Timer {}
+ }
+ \endqml
+
+ instead of:
+ \qml
+ Item {
+ children: [
+ Text {},
+ Rectangle {}
+ ]
+ resources: [
+ Timer {}
+ ]
+ }
+ \endqml
+
+ data is a behind-the-scenes property: you should never need to explicitly
+ specify it.
+ */
+
+QDeclarativeListProperty<QObject> QDeclarativeItemPrivate::data()
+{
+ return QDeclarativeListProperty<QObject>(q_func(), 0, QDeclarativeItemPrivate::data_append,
+ QDeclarativeItemPrivate::data_count,
+ QDeclarativeItemPrivate::data_at,
+ QDeclarativeItemPrivate::data_clear
+ );
+}
+
+/*!
+ \property QDeclarativeItem::childrenRect
+ \brief The geometry of an item's children.
+
+ This property holds the (collective) position and size of the item's children.
+*/
+QRectF QDeclarativeItem::childrenRect()
+{
+ Q_D(QDeclarativeItem);
+ if (!d->_contents) {
+ d->_contents = new QDeclarative1Contents(this);
+ if (d->componentComplete)
+ d->_contents->complete();
+ }
+ return d->_contents->rectF();
+}
+
+bool QDeclarativeItem::clip() const
+{
+ return flags() & ItemClipsChildrenToShape;
+}
+
+void QDeclarativeItem::setClip(bool c)
+{
+ if (clip() == c)
+ return;
+ setFlag(ItemClipsChildrenToShape, c);
+ emit clipChanged(c);
+}
+
+/*!
+ \qmlproperty real Item::x
+ \qmlproperty real Item::y
+ \qmlproperty real Item::width
+ \qmlproperty real Item::height
+
+ Defines the item's position and size relative to its parent.
+
+ \qml
+ Item { x: 100; y: 100; width: 100; height: 100 }
+ \endqml
+ */
+
+/*!
+ \qmlproperty real Item::z
+
+ Sets the stacking order of sibling items. By default the stacking order is 0.
+
+ Items with a higher stacking value are drawn on top of siblings with a
+ lower stacking order. Items with the same stacking value are drawn
+ bottom up in the order they appear. Items with a negative stacking
+ value are drawn under their parent's content.
+
+ The following example shows the various effects of stacking order.
+
+ \table
+ \row
+ \o \image declarative-item_stacking1.png
+ \o Same \c z - later children above earlier children:
+ \qml
+ Item {
+ Rectangle {
+ color: "red"
+ width: 100; height: 100
+ }
+ Rectangle {
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ \endqml
+ \row
+ \o \image declarative-item_stacking2.png
+ \o Higher \c z on top:
+ \qml
+ Item {
+ Rectangle {
+ z: 1
+ color: "red"
+ width: 100; height: 100
+ }
+ Rectangle {
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ \endqml
+ \row
+ \o \image declarative-item_stacking3.png
+ \o Same \c z - children above parents:
+ \qml
+ Item {
+ Rectangle {
+ color: "red"
+ width: 100; height: 100
+ Rectangle {
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ }
+ \endqml
+ \row
+ \o \image declarative-item_stacking4.png
+ \o Lower \c z below:
+ \qml
+ Item {
+ Rectangle {
+ color: "red"
+ width: 100; height: 100
+ Rectangle {
+ z: -1
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ }
+ \endqml
+ \endtable
+ */
+
+/*!
+ \qmlproperty bool Item::visible
+
+ This property holds whether the item is visible. By default this is true.
+
+ Setting this property directly affects the \c visible value of child
+ items. When set to \c false, the \c visible values of all child items also
+ become \c false. When set to \c true, the \c visible values of child items
+ are returned to \c true, unless they have explicitly been set to \c false.
+
+ (Because of this flow-on behavior, using the \c visible property may not
+ have the intended effect if a property binding should only respond to
+ explicit property changes. In such cases it may be better to use the
+ \l opacity property instead.)
+
+ Setting this property to \c false automatically causes \l focus to be set
+ to \c false, and this item will longer receive mouse and keyboard events.
+ (In contrast, setting the \l opacity to 0 does not affect the \l focus
+ property and the receiving of key events.)
+
+ \note This property's value is only affected by changes to this property or
+ the parent's \c visible property. It does not change, for example, if this
+ item moves off-screen, or if the \l opacity changes to 0.
+*/
+
+
+/*!
+ This function is called to handle this item's changes in
+ geometry from \a oldGeometry to \a newGeometry. If the two
+ geometries are the same, it doesn't do anything.
+ */
+void QDeclarativeItem::geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry)
+{
+ Q_D(QDeclarativeItem);
+
+ if (d->_anchors)
+ d->_anchors->d_func()->updateMe();
+
+ if (transformOrigin() != QDeclarativeItem::TopLeft
+ && (newGeometry.width() != oldGeometry.width() || newGeometry.height() != oldGeometry.height())) {
+ if (d->transformData) {
+ QPointF origin = d->computeTransformOrigin();
+ if (transformOriginPoint() != origin)
+ setTransformOriginPoint(origin);
+ } else {
+ d->transformOriginDirty = true;
+ }
+ }
+
+ for(int ii = 0; ii < d->changeListeners.count(); ++ii) {
+ const QDeclarativeItemPrivate::ChangeListener &change = d->changeListeners.at(ii);
+ if (change.types & QDeclarativeItemPrivate::Geometry)
+ change.listener->itemGeometryChanged(this, newGeometry, oldGeometry);
+ }
+
+ if (newGeometry.width() != oldGeometry.width())
+ emit widthChanged();
+ if (newGeometry.height() != oldGeometry.height())
+ emit heightChanged();
+}
+
+void QDeclarativeItemPrivate::removeItemChangeListener(QDeclarativeItemChangeListener *listener, ChangeTypes types)
+{
+ ChangeListener change(listener, types);
+ changeListeners.removeOne(change);
+}
+
+/*! \internal */
+void QDeclarativeItem::keyPressEvent(QKeyEvent *event)
+{
+ Q_D(QDeclarativeItem);
+ keyPressPreHandler(event);
+ if (event->isAccepted())
+ return;
+ if (d->keyHandler)
+ d->keyHandler->keyPressed(event, true);
+ else
+ event->ignore();
+}
+
+/*! \internal */
+void QDeclarativeItem::keyReleaseEvent(QKeyEvent *event)
+{
+ Q_D(QDeclarativeItem);
+ keyReleasePreHandler(event);
+ if (event->isAccepted())
+ return;
+ if (d->keyHandler)
+ d->keyHandler->keyReleased(event, true);
+ else
+ event->ignore();
+}
+
+/*! \internal */
+void QDeclarativeItem::inputMethodEvent(QInputMethodEvent *event)
+{
+ Q_D(QDeclarativeItem);
+ inputMethodPreHandler(event);
+ if (event->isAccepted())
+ return;
+ if (d->keyHandler)
+ d->keyHandler->inputMethodEvent(event, true);
+ else
+ event->ignore();
+}
+
+/*! \internal */
+QVariant QDeclarativeItem::inputMethodQuery(Qt::InputMethodQuery query) const
+{
+ Q_D(const QDeclarativeItem);
+ QVariant v;
+ if (d->keyHandler)
+ v = d->keyHandler->inputMethodQuery(query);
+
+ if (!v.isValid())
+ v = QGraphicsObject::inputMethodQuery(query);
+
+ return v;
+}
+
+/*!
+ \internal
+ */
+void QDeclarativeItem::keyPressPreHandler(QKeyEvent *event)
+{
+ Q_D(QDeclarativeItem);
+ if (d->keyHandler && !d->doneEventPreHandler)
+ d->keyHandler->keyPressed(event, false);
+ else
+ event->ignore();
+ d->doneEventPreHandler = true;
+}
+
+/*!
+ \internal
+ */
+void QDeclarativeItem::keyReleasePreHandler(QKeyEvent *event)
+{
+ Q_D(QDeclarativeItem);
+ if (d->keyHandler && !d->doneEventPreHandler)
+ d->keyHandler->keyReleased(event, false);
+ else
+ event->ignore();
+ d->doneEventPreHandler = true;
+}
+
+/*!
+ \internal
+ */
+void QDeclarativeItem::inputMethodPreHandler(QInputMethodEvent *event)
+{
+ Q_D(QDeclarativeItem);
+ if (d->keyHandler && !d->doneEventPreHandler)
+ d->keyHandler->inputMethodEvent(event, false);
+ else
+ event->ignore();
+ d->doneEventPreHandler = true;
+}
+
+/*!
+ \internal
+*/
+QDeclarative1AnchorLine QDeclarativeItemPrivate::left() const
+{
+ return anchorLines()->left;
+}
+
+/*!
+ \internal
+*/
+QDeclarative1AnchorLine QDeclarativeItemPrivate::right() const
+{
+ return anchorLines()->right;
+}
+
+/*!
+ \internal
+*/
+QDeclarative1AnchorLine QDeclarativeItemPrivate::horizontalCenter() const
+{
+ return anchorLines()->hCenter;
+}
+
+/*!
+ \internal
+*/
+QDeclarative1AnchorLine QDeclarativeItemPrivate::top() const
+{
+ return anchorLines()->top;
+}
+
+/*!
+ \internal
+*/
+QDeclarative1AnchorLine QDeclarativeItemPrivate::bottom() const
+{
+ return anchorLines()->bottom;
+}
+
+/*!
+ \internal
+*/
+QDeclarative1AnchorLine QDeclarativeItemPrivate::verticalCenter() const
+{
+ return anchorLines()->vCenter;
+}
+
+
+/*!
+ \internal
+*/
+QDeclarative1AnchorLine QDeclarativeItemPrivate::baseline() const
+{
+ return anchorLines()->baseline;
+}
+
+/*!
+ \qmlproperty AnchorLine Item::anchors.top
+ \qmlproperty AnchorLine Item::anchors.bottom
+ \qmlproperty AnchorLine Item::anchors.left
+ \qmlproperty AnchorLine Item::anchors.right
+ \qmlproperty AnchorLine Item::anchors.horizontalCenter
+ \qmlproperty AnchorLine Item::anchors.verticalCenter
+ \qmlproperty AnchorLine Item::anchors.baseline
+
+ \qmlproperty Item Item::anchors.fill
+ \qmlproperty Item Item::anchors.centerIn
+
+ \qmlproperty real Item::anchors.margins
+ \qmlproperty real Item::anchors.topMargin
+ \qmlproperty real Item::anchors.bottomMargin
+ \qmlproperty real Item::anchors.leftMargin
+ \qmlproperty real Item::anchors.rightMargin
+ \qmlproperty real Item::anchors.horizontalCenterOffset
+ \qmlproperty real Item::anchors.verticalCenterOffset
+ \qmlproperty real Item::anchors.baselineOffset
+
+ \qmlproperty bool Item::anchors.mirrored
+
+ Anchors provide a way to position an item by specifying its
+ relationship with other items.
+
+ Margins apply to top, bottom, left, right, and fill anchors.
+ The \c anchors.margins property can be used to set all of the various margins at once, to the same value.
+ Note that margins are anchor-specific and are not applied if an item does not
+ use anchors.
+
+ Offsets apply for horizontal center, vertical center, and baseline anchors.
+
+ \table
+ \row
+ \o \image declarative-anchors_example.png
+ \o Text anchored to Image, horizontally centered and vertically below, with a margin.
+ \qml
+ Item {
+ Image {
+ id: pic
+ // ...
+ }
+ Text {
+ id: label
+ anchors.horizontalCenter: pic.horizontalCenter
+ anchors.top: pic.bottom
+ anchors.topMargin: 5
+ // ...
+ }
+ }
+ \endqml
+ \row
+ \o \image declarative-anchors_example2.png
+ \o
+ Left of Text anchored to right of Image, with a margin. The y
+ property of both defaults to 0.
+
+ \qml
+ Item {
+ Image {
+ id: pic
+ // ...
+ }
+ Text {
+ id: label
+ anchors.left: pic.right
+ anchors.leftMargin: 5
+ // ...
+ }
+ }
+ \endqml
+ \endtable
+
+ \c anchors.fill provides a convenient way for one item to have the
+ same geometry as another item, and is equivalent to connecting all
+ four directional anchors.
+
+ To clear an anchor value, set it to \c undefined.
+
+ \c anchors.mirrored returns true it the layout has been \l {LayoutMirroring}{mirrored}.
+
+ \note You can only anchor an item to siblings or a parent.
+
+ For more information see \l {anchor-layout}{Anchor Layouts}.
+*/
+
+/*!
+ \property QDeclarativeItem::baselineOffset
+ \brief The position of the item's baseline in local coordinates.
+
+ The baseline of a \l Text item is the imaginary line on which the text
+ sits. Controls containing text usually set their baseline to the
+ baseline of their text.
+
+ For non-text items, a default baseline offset of 0 is used.
+*/
+qreal QDeclarativeItem::baselineOffset() const
+{
+ Q_D(const QDeclarativeItem);
+ if (!d->baselineOffset.isValid()) {
+ return 0.0;
+ } else
+ return d->baselineOffset;
+}
+
+void QDeclarativeItem::setBaselineOffset(qreal offset)
+{
+ Q_D(QDeclarativeItem);
+ if (offset == d->baselineOffset)
+ return;
+
+ d->baselineOffset = offset;
+
+ for(int ii = 0; ii < d->changeListeners.count(); ++ii) {
+ const QDeclarativeItemPrivate::ChangeListener &change = d->changeListeners.at(ii);
+ if (change.types & QDeclarativeItemPrivate::Geometry) {
+ QDeclarative1AnchorsPrivate *anchor = change.listener->anchorPrivate();
+ if (anchor)
+ anchor->updateVerticalAnchors();
+ }
+ }
+ emit baselineOffsetChanged(offset);
+}
+
+/*!
+ \qmlproperty real Item::rotation
+ This property holds the rotation of the item in degrees clockwise.
+
+ This specifies how many degrees to rotate the item around its transformOrigin.
+ The default rotation is 0 degrees (i.e. not rotated at all).
+
+ \table
+ \row
+ \o \image declarative-rotation.png
+ \o
+ \qml
+ Rectangle {
+ color: "blue"
+ width: 100; height: 100
+ Rectangle {
+ color: "red"
+ x: 25; y: 25; width: 50; height: 50
+ rotation: 30
+ }
+ }
+ \endqml
+ \endtable
+
+ \sa transform, Rotation
+*/
+
+/*!
+ \qmlproperty real Item::scale
+ This property holds the scale of the item.
+
+ A scale of less than 1 means the item will be displayed smaller than
+ normal, and a scale of greater than 1 means the item will be
+ displayed larger than normal. A negative scale means the item will
+ be mirrored.
+
+ By default, items are displayed at a scale of 1 (i.e. at their
+ normal size).
+
+ Scaling is from the item's transformOrigin.
+
+ \table
+ \row
+ \o \image declarative-scale.png
+ \o
+ \qml
+ Rectangle {
+ color: "blue"
+ width: 100; height: 100
+ Rectangle {
+ color: "green"
+ width: 25; height: 25
+ }
+ Rectangle {
+ color: "red"
+ x: 25; y: 25; width: 50; height: 50
+ scale: 1.4
+ }
+ }
+ \endqml
+ \endtable
+
+ \sa transform, Scale
+*/
+
+/*!
+ \qmlproperty real Item::opacity
+
+ This property holds the opacity of the item. Opacity is specified as a
+ number between 0 (fully transparent) and 1 (fully opaque). The default is 1.
+
+ When this property is set, the specified opacity is also applied
+ individually to child items. In almost all cases this is what you want,
+ but in some cases it may produce undesired results. For example in the
+ second set of rectangles below, the red rectangle has specified an opacity
+ of 0.5, which affects the opacity of its blue child rectangle even though
+ the child has not specified an opacity.
+
+ \table
+ \row
+ \o \image declarative-item_opacity1.png
+ \o
+ \qml
+ Item {
+ Rectangle {
+ color: "red"
+ width: 100; height: 100
+ Rectangle {
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ }
+ \endqml
+ \row
+ \o \image declarative-item_opacity2.png
+ \o
+ \qml
+ Item {
+ Rectangle {
+ opacity: 0.5
+ color: "red"
+ width: 100; height: 100
+ Rectangle {
+ color: "blue"
+ x: 50; y: 50; width: 100; height: 100
+ }
+ }
+ }
+ \endqml
+ \endtable
+
+ If an item's opacity is set to 0, the item will no longer receive mouse
+ events, but will continue to receive key events and will retain the keyboard
+ \l focus if it has been set. (In contrast, setting the \l visible property
+ to \c false stops both mouse and keyboard events, and also removes focus
+ from the item.)
+*/
+
+/*!
+ Returns a value indicating whether mouse input should
+ remain with this item exclusively.
+
+ \sa setKeepMouseGrab()
+ */
+bool QDeclarativeItem::keepMouseGrab() const
+{
+ Q_D(const QDeclarativeItem);
+ return d->keepMouse;
+}
+
+/*!
+ The flag indicating whether the mouse should remain
+ with this item is set to \a keep.
+
+ This is useful for items that wish to grab and keep mouse
+ interaction following a predefined gesture. For example,
+ an item that is interested in horizontal mouse movement
+ may set keepMouseGrab to true once a threshold has been
+ exceeded. Once keepMouseGrab has been set to true, filtering
+ items will not react to mouse events.
+
+ If the item does not indicate that it wishes to retain mouse grab,
+ a filtering item may steal the grab. For example, Flickable may attempt
+ to steal a mouse grab if it detects that the user has begun to
+ move the viewport.
+
+ \sa keepMouseGrab()
+ */
+void QDeclarativeItem::setKeepMouseGrab(bool keep)
+{
+ Q_D(QDeclarativeItem);
+ d->keepMouse = keep;
+}
+
+/*!
+ \qmlmethod object Item::mapFromItem(Item item, real x, real y)
+
+ Maps the point (\a x, \a y), which is in \a item's coordinate system, to
+ this item's coordinate system, and returns an object with \c x and \c y
+ properties matching the mapped cooordinate.
+
+ If \a item is a \c null value, this maps the point from the coordinate
+ system of the root QML view.
+*/
+void QDeclarativeItem::mapFromItem(QDeclarativeV8Function *args) const
+{
+ if (args->Length() != 0) {
+ v8::Local<v8::Value> item = (*args)[0];
+ QV8Engine *engine = args->engine();
+
+ QDeclarativeItem *itemObj = 0;
+ if (!item->IsNull())
+ itemObj = qobject_cast<QDeclarativeItem*>(engine->toQObject(item));
+
+ if (!itemObj && !item->IsNull()) {
+ qmlInfo(this) << "mapFromItem() given argument \"" << engine->toString(item->ToString())
+ << "\" which is neither null nor an Item";
+ return;
+ }
+
+ v8::Local<v8::Object> rv = v8::Object::New();
+ args->returnValue(rv);
+
+ qreal x = (args->Length() > 1)?(*args)[1]->NumberValue():0;
+ qreal y = (args->Length() > 2)?(*args)[2]->NumberValue():0;
+
+ QPointF p = QGraphicsItem::mapFromItem(itemObj, x, y);
+
+ rv->Set(v8::String::New("x"), v8::Number::New(p.x()));
+ rv->Set(v8::String::New("y"), v8::Number::New(p.y()));
+ }
+}
+
+/*!
+ \qmlmethod object Item::mapToItem(Item item, real x, real y)
+
+ Maps the point (\a x, \a y), which is in this item's coordinate system, to
+ \a item's coordinate system, and returns an object with \c x and \c y
+ properties matching the mapped cooordinate.
+
+ If \a item is a \c null value, this maps \a x and \a y to the coordinate
+ system of the root QML view.
+*/
+void QDeclarativeItem::mapToItem(QDeclarativeV8Function *args) const
+{
+ if (args->Length() != 0) {
+ v8::Local<v8::Value> item = (*args)[0];
+ QV8Engine *engine = args->engine();
+
+ QDeclarativeItem *itemObj = 0;
+ if (!item->IsNull())
+ itemObj = qobject_cast<QDeclarativeItem*>(engine->toQObject(item));
+
+ if (!itemObj && !item->IsNull()) {
+ qmlInfo(this) << "mapToItem() given argument \"" << engine->toString(item->ToString())
+ << "\" which is neither null nor an Item";
+ return;
+ }
+
+ v8::Local<v8::Object> rv = v8::Object::New();
+ args->returnValue(rv);
+
+ qreal x = (args->Length() > 1)?(*args)[1]->NumberValue():0;
+ qreal y = (args->Length() > 2)?(*args)[2]->NumberValue():0;
+
+ QPointF p = QGraphicsItem::mapToItem(itemObj, x, y);
+
+ rv->Set(v8::String::New("x"), v8::Number::New(p.x()));
+ rv->Set(v8::String::New("y"), v8::Number::New(p.y()));
+ }
+}
+
+/*!
+ \qmlmethod Item::forceActiveFocus()
+
+ Forces active focus on the item.
+
+ This method sets focus on the item and makes sure that all the focus scopes
+ higher in the object hierarchy are also given the focus.
+*/
+
+/*!
+ Forces active focus on the item.
+
+ This method sets focus on the item and makes sure that all the focus scopes
+ higher in the object hierarchy are also given the focus.
+*/
+void QDeclarativeItem::forceActiveFocus()
+{
+ setFocus(true);
+ QGraphicsItem *parent = parentItem();
+ while (parent) {
+ if (parent->flags() & QGraphicsItem::ItemIsFocusScope)
+ parent->setFocus(Qt::OtherFocusReason);
+ parent = parent->parentItem();
+ }
+}
+
+
+/*!
+ \qmlmethod Item::childAt(real x, real y)
+
+ Returns the visible child item at point (\a x, \a y), which is in this
+ item's coordinate system, or \c null if there is no such item.
+*/
+
+/*!
+ Returns the visible child item at point (\a x, \a y), which is in this
+ item's coordinate system, or 0 if there is no such item.
+*/
+QDeclarativeItem *QDeclarativeItem::childAt(qreal x, qreal y) const
+{
+ const QList<QGraphicsItem *> children = childItems();
+ for (int i = children.count()-1; i >= 0; --i) {
+ if (QDeclarativeItem *child = qobject_cast<QDeclarativeItem *>(children.at(i))) {
+ if (child->isVisible() && child->x() <= x
+ && child->x() + child->width() >= x
+ && child->y() <= y
+ && child->y() + child->height() >= y)
+ return child;
+ }
+ }
+ return 0;
+}
+
+void QDeclarativeItemPrivate::focusChanged(bool flag)
+{
+ Q_Q(QDeclarativeItem);
+ if (!(flags & QGraphicsItem::ItemIsFocusScope) && parent)
+ emit q->activeFocusChanged(flag); //see also QDeclarativeItemPrivate::subFocusItemChange()
+ emit q->focusChanged(flag);
+}
+
+QDeclarativeListProperty<QObject> QDeclarativeItemPrivate::resources()
+{
+ return QDeclarativeListProperty<QObject>(q_func(), 0, QDeclarativeItemPrivate::resources_append,
+ QDeclarativeItemPrivate::resources_count,
+ QDeclarativeItemPrivate::resources_at,
+ QDeclarativeItemPrivate::resources_clear
+ );
+}
+
+/*!
+ \qmlproperty list<State> Item::states
+ This property holds a list of states defined by the item.
+
+ \qml
+ Item {
+ states: [
+ State {
+ // ...
+ },
+ State {
+ // ...
+ }
+ // ...
+ ]
+ }
+ \endqml
+
+ \sa {qmlstate}{States}
+*/
+
+QDeclarativeListProperty<QDeclarative1State> QDeclarativeItemPrivate::states()
+{
+ return _states()->statesProperty();
+}
+
+/*!
+ \qmlproperty list<Transition> Item::transitions
+ This property holds a list of transitions defined by the item.
+
+ \qml
+ Item {
+ transitions: [
+ Transition {
+ // ...
+ },
+ Transition {
+ // ...
+ }
+ // ...
+ ]
+ }
+ \endqml
+
+ \sa {QML Animation and Transitions}{Transitions}
+*/
+
+
+QDeclarativeListProperty<QDeclarative1Transition> QDeclarativeItemPrivate::transitions()
+{
+ return _states()->transitionsProperty();
+}
+
+/*
+ \qmlproperty list<Filter> Item::filter
+ This property holds a list of graphical filters to be applied to the item.
+
+ \l {Filter}{Filters} include things like \l {Blur}{blurring}
+ the item, or giving it a \l Reflection. Some
+ filters may not be available on all canvases; if a filter is not
+ available on a certain canvas, it will simply not be applied for
+ that canvas (but the QML will still be considered valid).
+
+ \qml
+ Item {
+ filter: [
+ Blur {
+ // ...
+ },
+ Reflection {
+ // ...
+ }
+ // ...
+ ]
+ }
+ \endqml
+*/
+
+/*!
+ \qmlproperty bool Item::clip
+ This property holds whether clipping is enabled. The default clip value is \c false.
+
+ If clipping is enabled, an item will clip its own painting, as well
+ as the painting of its children, to its bounding rectangle.
+
+ Non-rectangular clipping regions are not supported for performance reasons.
+*/
+
+/*!
+ \property QDeclarativeItem::clip
+ This property holds whether clipping is enabled. The default clip value is \c false.
+
+ If clipping is enabled, an item will clip its own painting, as well
+ as the painting of its children, to its bounding rectangle. If you set
+ clipping during an item's paint operation, remember to re-set it to
+ prevent clipping the rest of your scene.
+
+ Non-rectangular clipping regions are not supported for performance reasons.
+*/
+
+/*!
+ \qmlproperty string Item::state
+
+ This property holds the name of the current state of the item.
+
+ This property is often used in scripts to change between states. For
+ example:
+
+ \js
+ function toggle() {
+ if (button.state == 'On')
+ button.state = 'Off';
+ else
+ button.state = 'On';
+ }
+ \endjs
+
+ If the item is in its base state (i.e. no explicit state has been
+ set), \c state will be a blank string. Likewise, you can return an
+ item to its base state by setting its current state to \c ''.
+
+ \sa {qmlstates}{States}
+*/
+
+QString QDeclarativeItemPrivate::state() const
+{
+ if (!_stateGroup)
+ return QString();
+ else
+ return _stateGroup->state();
+}
+
+void QDeclarativeItemPrivate::setState(const QString &state)
+{
+ _states()->setState(state);
+}
+
+/*!
+ \qmlproperty list<Transform> Item::transform
+ This property holds the list of transformations to apply.
+
+ For more information see \l Transform.
+*/
+
+/*! \internal */
+QDeclarativeListProperty<QGraphicsTransform> QDeclarativeItem::transform()
+{
+ Q_D(QDeclarativeItem);
+ return QDeclarativeListProperty<QGraphicsTransform>(this, 0, d->transform_append, d->transform_count,
+ d->transform_at, d->transform_clear);
+}
+
+/*!
+ \internal
+
+ classBegin() is called when the item is constructed, but its
+ properties have not yet been set.
+
+ \sa componentComplete(), isComponentComplete()
+*/
+void QDeclarativeItem::classBegin()
+{
+ Q_D(QDeclarativeItem);
+ d->componentComplete = false;
+ if (d->_stateGroup)
+ d->_stateGroup->classBegin();
+ if (d->_anchors)
+ d->_anchors->classBegin();
+}
+
+/*!
+ \internal
+
+ componentComplete() is called when all items in the component
+ have been constructed. It is often desirable to delay some
+ processing until the component is complete an all bindings in the
+ component have been resolved.
+*/
+void QDeclarativeItem::componentComplete()
+{
+ Q_D(QDeclarativeItem);
+ d->componentComplete = true;
+ if (d->_stateGroup)
+ d->_stateGroup->componentComplete();
+ if (d->_anchors) {
+ d->_anchors->componentComplete();
+ d->_anchors->d_func()->updateOnComplete();
+ }
+ if (d->keyHandler)
+ d->keyHandler->componentComplete();
+ if (d->_contents)
+ d->_contents->complete();
+}
+
+QDeclarative1StateGroup *QDeclarativeItemPrivate::_states()
+{
+ Q_Q(QDeclarativeItem);
+ if (!_stateGroup) {
+ _stateGroup = new QDeclarative1StateGroup;
+ if (!componentComplete)
+ _stateGroup->classBegin();
+ QObject::connect(_stateGroup, SIGNAL(stateChanged(QString)),
+ q, SIGNAL(stateChanged(QString)));
+ }
+
+ return _stateGroup;
+}
+
+QDeclarativeItemPrivate::AnchorLines::AnchorLines(QGraphicsObject *q)
+{
+ left.item = q;
+ left.anchorLine = QDeclarative1AnchorLine::Left;
+ right.item = q;
+ right.anchorLine = QDeclarative1AnchorLine::Right;
+ hCenter.item = q;
+ hCenter.anchorLine = QDeclarative1AnchorLine::HCenter;
+ top.item = q;
+ top.anchorLine = QDeclarative1AnchorLine::Top;
+ bottom.item = q;
+ bottom.anchorLine = QDeclarative1AnchorLine::Bottom;
+ vCenter.item = q;
+ vCenter.anchorLine = QDeclarative1AnchorLine::VCenter;
+ baseline.item = q;
+ baseline.anchorLine = QDeclarative1AnchorLine::Baseline;
+}
+
+QPointF QDeclarativeItemPrivate::computeTransformOrigin() const
+{
+ Q_Q(const QDeclarativeItem);
+
+ QRectF br = q->boundingRect();
+
+ switch(origin) {
+ default:
+ case QDeclarativeItem::TopLeft:
+ return QPointF(0, 0);
+ case QDeclarativeItem::Top:
+ return QPointF(br.width() / 2., 0);
+ case QDeclarativeItem::TopRight:
+ return QPointF(br.width(), 0);
+ case QDeclarativeItem::Left:
+ return QPointF(0, br.height() / 2.);
+ case QDeclarativeItem::Center:
+ return QPointF(br.width() / 2., br.height() / 2.);
+ case QDeclarativeItem::Right:
+ return QPointF(br.width(), br.height() / 2.);
+ case QDeclarativeItem::BottomLeft:
+ return QPointF(0, br.height());
+ case QDeclarativeItem::Bottom:
+ return QPointF(br.width() / 2., br.height());
+ case QDeclarativeItem::BottomRight:
+ return QPointF(br.width(), br.height());
+ }
+}
+
+/*! \internal */
+bool QDeclarativeItem::sceneEvent(QEvent *event)
+{
+ Q_D(QDeclarativeItem);
+ if (event->type() == QEvent::KeyPress) {
+ QKeyEvent *k = static_cast<QKeyEvent *>(event);
+ if ((k->key() == Qt::Key_Tab || k->key() == Qt::Key_Backtab) &&
+ !(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) {
+ keyPressEvent(static_cast<QKeyEvent *>(event));
+ if (!event->isAccepted())
+ return QGraphicsItem::sceneEvent(event);
+ else
+ return true;
+ } else {
+ return QGraphicsItem::sceneEvent(event);
+ }
+ } else {
+ bool rv = QGraphicsItem::sceneEvent(event);
+
+ if (event->type() == QEvent::FocusIn ||
+ event->type() == QEvent::FocusOut) {
+ d->focusChanged(hasActiveFocus());
+ }
+ return rv;
+ }
+}
+
+/*!
+ \internal
+
+ Note that unlike QGraphicsItems, QDeclarativeItem::itemChange() is \e not called
+ during initial widget polishing. Items wishing to optimize start-up construction
+ should instead consider using componentComplete().
+*/
+QVariant QDeclarativeItem::itemChange(GraphicsItemChange change,
+ const QVariant &value)
+{
+ Q_D(QDeclarativeItem);
+ switch (change) {
+ case ItemParentHasChanged:
+ d->resolveLayoutMirror();
+ emit parentChanged(parentItem());
+ d->parentNotifier.notify();
+ break;
+ case ItemVisibleHasChanged: {
+ for(int ii = 0; ii < d->changeListeners.count(); ++ii) {
+ const QDeclarativeItemPrivate::ChangeListener &change = d->changeListeners.at(ii);
+ if (change.types & QDeclarativeItemPrivate::Visibility) {
+ change.listener->itemVisibilityChanged(this);
+ }
+ }
+ }
+ break;
+ case ItemOpacityHasChanged: {
+ for(int ii = 0; ii < d->changeListeners.count(); ++ii) {
+ const QDeclarativeItemPrivate::ChangeListener &change = d->changeListeners.at(ii);
+ if (change.types & QDeclarativeItemPrivate::Opacity) {
+ change.listener->itemOpacityChanged(this);
+ }
+ }
+ }
+ break;
+ case ItemChildAddedChange:
+ if (d->_contents && d->componentComplete)
+ d->_contents->childAdded(qobject_cast<QDeclarativeItem*>(
+ value.value<QGraphicsItem*>()));
+ break;
+ case ItemChildRemovedChange:
+ if (d->_contents && d->componentComplete)
+ d->_contents->childRemoved(qobject_cast<QDeclarativeItem*>(
+ value.value<QGraphicsItem*>()));
+ break;
+ default:
+ break;
+ }
+
+ return QGraphicsItem::itemChange(change, value);
+}
+
+/*! \internal */
+QRectF QDeclarativeItem::boundingRect() const
+{
+ Q_D(const QDeclarativeItem);
+ return QRectF(0, 0, d->mWidth, d->mHeight);
+}
+
+/*!
+ \enum QDeclarativeItem::TransformOrigin
+
+ Controls the point about which simple transforms like scale apply.
+
+ \value TopLeft The top-left corner of the item.
+ \value Top The center point of the top of the item.
+ \value TopRight The top-right corner of the item.
+ \value Left The left most point of the vertical middle.
+ \value Center The center of the item.
+ \value Right The right most point of the vertical middle.
+ \value BottomLeft The bottom-left corner of the item.
+ \value Bottom The center point of the bottom of the item.
+ \value BottomRight The bottom-right corner of the item.
+*/
+
+/*!
+ Returns the current transform origin.
+*/
+QDeclarativeItem::TransformOrigin QDeclarativeItem::transformOrigin() const
+{
+ Q_D(const QDeclarativeItem);
+ return d->origin;
+}
+
+/*!
+ Set the transform \a origin.
+*/
+void QDeclarativeItem::setTransformOrigin(TransformOrigin origin)
+{
+ Q_D(QDeclarativeItem);
+ if (origin != d->origin) {
+ d->origin = origin;
+ if (d->transformData)
+ QGraphicsItem::setTransformOriginPoint(d->computeTransformOrigin());
+ else
+ d->transformOriginDirty = true;
+ emit transformOriginChanged(d->origin);
+ }
+}
+
+void QDeclarativeItemPrivate::transformChanged()
+{
+ Q_Q(QDeclarativeItem);
+ if (transformOriginDirty) {
+ q->QGraphicsItem::setTransformOriginPoint(computeTransformOrigin());
+ transformOriginDirty = false;
+ }
+}
+
+/*!
+ \property QDeclarativeItem::smooth
+ \brief whether the item is smoothly transformed.
+
+ This property is provided purely for the purpose of optimization. Turning
+ smooth transforms off is faster, but looks worse; turning smooth
+ transformations on is slower, but looks better.
+
+ By default smooth transformations are off.
+*/
+
+/*!
+ Returns true if the item should be drawn with antialiasing and
+ smooth pixmap filtering, false otherwise.
+
+ The default is false.
+
+ \sa setSmooth()
+*/
+bool QDeclarativeItem::smooth() const
+{
+ Q_D(const QDeclarativeItem);
+ return d->smooth;
+}
+
+/*!
+ Sets whether the item should be drawn with antialiasing and
+ smooth pixmap filtering to \a smooth.
+
+ \sa smooth()
+*/
+void QDeclarativeItem::setSmooth(bool smooth)
+{
+ Q_D(QDeclarativeItem);
+ if (d->smooth == smooth)
+ return;
+ d->smooth = smooth;
+ emit smoothChanged(smooth);
+ update();
+}
+
+/*!
+ \property QDeclarativeItem::anchors
+ \internal
+*/
+
+/*!
+ \property QDeclarativeItem::left
+ \internal
+*/
+
+/*!
+ \property QDeclarativeItem::right
+ \internal
+*/
+
+/*!
+ \property QDeclarativeItem::horizontalCenter
+ \internal
+*/
+
+/*!
+ \property QDeclarativeItem::top
+ \internal
+*/
+
+/*!
+ \property QDeclarativeItem::bottom
+ \internal
+*/
+
+/*!
+ \property QDeclarativeItem::verticalCenter
+ \internal
+*/
+
+/*!
+ \property QDeclarativeItem::focus
+ \internal
+*/
+
+/*!
+ \property QDeclarativeItem::transform
+ \internal
+*/
+
+/*!
+ \property QDeclarativeItem::transformOrigin
+ \internal
+*/
+
+/*!
+ \property QDeclarativeItem::activeFocus
+ \internal
+*/
+
+/*!
+ \property QDeclarativeItem::baseline
+ \internal
+*/
+
+/*!
+ \property QDeclarativeItem::data
+ \internal
+*/
+
+/*!
+ \property QDeclarativeItem::resources
+ \internal
+*/
+
+/*!
+ \property QDeclarativeItem::state
+ \internal
+*/
+
+/*!
+ \property QDeclarativeItem::states
+ \internal
+*/
+
+/*!
+ \property QDeclarativeItem::transformOriginPoint
+ \internal
+*/
+
+/*!
+ \property QDeclarativeItem::transitions
+ \internal
+*/
+
+/*!
+ \internal
+ Return the width of the item
+*/
+qreal QDeclarativeItem::width() const
+{
+ Q_D(const QDeclarativeItem);
+ return d->width();
+}
+
+/*!
+ \internal
+ Set the width of the item
+*/
+void QDeclarativeItem::setWidth(qreal w)
+{
+ Q_D(QDeclarativeItem);
+ d->setWidth(w);
+}
+
+/*!
+ \internal
+ Reset the width of the item
+*/
+void QDeclarativeItem::resetWidth()
+{
+ Q_D(QDeclarativeItem);
+ d->resetWidth();
+}
+
+/*!
+ \internal
+ Return the width of the item
+*/
+qreal QDeclarativeItemPrivate::width() const
+{
+ return mWidth;
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeItemPrivate::setWidth(qreal w)
+{
+ Q_Q(QDeclarativeItem);
+ if (qIsNaN(w))
+ return;
+
+ widthValid = true;
+ if (mWidth == w)
+ return;
+
+ qreal oldWidth = mWidth;
+
+ q->prepareGeometryChange();
+ mWidth = w;
+
+ q->geometryChanged(QRectF(q->x(), q->y(), width(), height()),
+ QRectF(q->x(), q->y(), oldWidth, height()));
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeItemPrivate::resetWidth()
+{
+ Q_Q(QDeclarativeItem);
+ widthValid = false;
+ q->setImplicitWidth(q->implicitWidth());
+}
+
+void QDeclarativeItemPrivate::implicitWidthChanged()
+{
+ Q_Q(QDeclarativeItem);
+ emit q->implicitWidthChanged();
+}
+
+qreal QDeclarativeItemPrivate::implicitWidth() const
+{
+ return mImplicitWidth;
+}
+
+/*!
+ Returns the width of the item that is implied by other properties that determine the content.
+*/
+qreal QDeclarativeItem::implicitWidth() const
+{
+ Q_D(const QDeclarativeItem);
+ return d->implicitWidth();
+}
+
+/*!
+ Sets the implied width of the item to \a w.
+ This is the width implied by other properties that determine the content.
+*/
+void QDeclarativeItem::setImplicitWidth(qreal w)
+{
+ Q_D(QDeclarativeItem);
+ bool changed = w != d->mImplicitWidth;
+ d->mImplicitWidth = w;
+ if (d->mWidth == w || widthValid()) {
+ if (changed)
+ d->implicitWidthChanged();
+ return;
+ }
+
+ qreal oldWidth = d->mWidth;
+
+ prepareGeometryChange();
+ d->mWidth = w;
+
+ geometryChanged(QRectF(x(), y(), width(), height()),
+ QRectF(x(), y(), oldWidth, height()));
+
+ if (changed)
+ d->implicitWidthChanged();
+}
+
+/*!
+ Returns whether the width property has been set explicitly.
+*/
+bool QDeclarativeItem::widthValid() const
+{
+ Q_D(const QDeclarativeItem);
+ return d->widthValid;
+}
+
+/*!
+ \internal
+ Return the height of the item
+*/
+qreal QDeclarativeItem::height() const
+{
+ Q_D(const QDeclarativeItem);
+ return d->height();
+}
+
+/*!
+ \internal
+ Set the height of the item
+*/
+void QDeclarativeItem::setHeight(qreal h)
+{
+ Q_D(QDeclarativeItem);
+ d->setHeight(h);
+}
+
+/*!
+ \internal
+ Reset the height of the item
+*/
+void QDeclarativeItem::resetHeight()
+{
+ Q_D(QDeclarativeItem);
+ d->resetHeight();
+}
+
+/*!
+ \internal
+*/
+qreal QDeclarativeItemPrivate::height() const
+{
+ return mHeight;
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeItemPrivate::setHeight(qreal h)
+{
+ Q_Q(QDeclarativeItem);
+ if (qIsNaN(h))
+ return;
+
+ heightValid = true;
+ if (mHeight == h)
+ return;
+
+ qreal oldHeight = mHeight;
+
+ q->prepareGeometryChange();
+ mHeight = h;
+
+ q->geometryChanged(QRectF(q->x(), q->y(), width(), height()),
+ QRectF(q->x(), q->y(), width(), oldHeight));
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeItemPrivate::resetHeight()
+{
+ Q_Q(QDeclarativeItem);
+ heightValid = false;
+ q->setImplicitHeight(q->implicitHeight());
+}
+
+void QDeclarativeItemPrivate::implicitHeightChanged()
+{
+ Q_Q(QDeclarativeItem);
+ emit q->implicitHeightChanged();
+}
+
+qreal QDeclarativeItemPrivate::implicitHeight() const
+{
+ return mImplicitHeight;
+}
+
+/*!
+ Returns the height of the item that is implied by other properties that determine the content.
+*/
+qreal QDeclarativeItem::implicitHeight() const
+{
+ Q_D(const QDeclarativeItem);
+ return d->implicitHeight();
+}
+
+/*!
+ \qmlproperty real Item::implicitWidth
+ \qmlproperty real Item::implicitHeight
+ \since Quick 1.1
+
+ Defines the natural width or height of the Item if no \l width or \l height is specified.
+
+ The default implicit size for most items is 0x0, however some elements have an inherent
+ implicit size which cannot be overridden, e.g. Image, Text.
+
+ Setting the implicit size is useful for defining components that have a preferred size
+ based on their content, for example:
+
+ \qml
+ // Label.qml
+ import QtQuick 1.1
+
+ Item {
+ property alias icon: image.source
+ property alias label: text.text
+ implicitWidth: text.implicitWidth + image.implicitWidth
+ implicitHeight: Math.max(text.implicitHeight, image.implicitHeight)
+ Image { id: image }
+ Text {
+ id: text
+ wrapMode: Text.Wrap
+ anchors.left: image.right; anchors.right: parent.right
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ }
+ \endqml
+
+ \bold Note: using implicitWidth of Text or TextEdit and setting the width explicitly
+ incurs a performance penalty as the text must be laid out twice.
+*/
+
+
+/*!
+ Sets the implied height of the item to \a h.
+ This is the height implied by other properties that determine the content.
+*/
+void QDeclarativeItem::setImplicitHeight(qreal h)
+{
+ Q_D(QDeclarativeItem);
+ bool changed = h != d->mImplicitHeight;
+ d->mImplicitHeight = h;
+ if (d->mHeight == h || heightValid()) {
+ if (changed)
+ d->implicitHeightChanged();
+ return;
+ }
+
+ qreal oldHeight = d->mHeight;
+
+ prepareGeometryChange();
+ d->mHeight = h;
+
+ geometryChanged(QRectF(x(), y(), width(), height()),
+ QRectF(x(), y(), width(), oldHeight));
+
+ if (changed)
+ d->implicitHeightChanged();
+}
+
+/*!
+ Returns whether the height property has been set explicitly.
+*/
+bool QDeclarativeItem::heightValid() const
+{
+ Q_D(const QDeclarativeItem);
+ return d->heightValid;
+}
+
+/*! \internal */
+void QDeclarativeItem::setSize(const QSizeF &size)
+{
+ Q_D(QDeclarativeItem);
+ d->heightValid = true;
+ d->widthValid = true;
+
+ if (d->height() == size.height() && d->width() == size.width())
+ return;
+
+ qreal oldHeight = d->height();
+ qreal oldWidth = d->width();
+
+ prepareGeometryChange();
+ d->setHeight(size.height());
+ d->setWidth(size.width());
+
+ geometryChanged(QRectF(x(), y(), width(), height()),
+ QRectF(x(), y(), oldWidth, oldHeight));
+}
+
+/*!
+ \qmlproperty bool Item::activeFocus
+
+ This property indicates whether the item has active focus.
+
+ An item with active focus will receive keyboard input,
+ or is a FocusScope ancestor of the item that will receive keyboard input.
+
+ Usually, activeFocus is gained by setting focus on an item and its enclosing
+ FocusScopes. In the following example \c input will have activeFocus.
+ \qml
+ Rectangle {
+ FocusScope {
+ focus: true
+ TextInput {
+ id: input
+ focus: true
+ }
+ }
+ }
+ \endqml
+
+ \sa focus, {qmlfocus}{Keyboard Focus}
+*/
+
+/*! \internal */
+bool QDeclarativeItem::hasActiveFocus() const
+{
+ Q_D(const QDeclarativeItem);
+ return focusItem() == this ||
+ (d->flags & QGraphicsItem::ItemIsFocusScope && focusItem() != 0);
+}
+
+/*!
+ \qmlproperty bool Item::focus
+ This property indicates whether the item has focus within the enclosing focus scope. If true, this item
+ will gain active focus when the enclosing focus scope gains active focus.
+ In the following example, \c input will be given active focus when \c scope gains active focus.
+ \qml
+ Rectangle {
+ FocusScope {
+ id: scope
+ TextInput {
+ id: input
+ focus: true
+ }
+ }
+ }
+ \endqml
+
+ For the purposes of this property, the scene as a whole is assumed to act like a focus scope.
+ On a practical level, that means the following QML will give active focus to \c input on startup.
+
+ \qml
+ Rectangle {
+ TextInput {
+ id: input
+ focus: true
+ }
+ }
+ \endqml
+
+ \sa activeFocus, {qmlfocus}{Keyboard Focus}
+*/
+
+/*! \internal */
+bool QDeclarativeItem::hasFocus() const
+{
+ Q_D(const QDeclarativeItem);
+ QGraphicsItem *p = d->parent;
+ while (p) {
+ if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
+ return p->focusScopeItem() == this;
+ }
+ p = p->parentItem();
+ }
+
+ return hasActiveFocus();
+}
+
+/*! \internal */
+void QDeclarativeItem::setFocus(bool focus)
+{
+ if (focus)
+ QGraphicsItem::setFocus(Qt::OtherFocusReason);
+ else
+ QGraphicsItem::clearFocus();
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeItem::paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *)
+{
+}
+
+/*!
+ \internal
+*/
+bool QDeclarativeItem::event(QEvent *ev)
+{
+ Q_D(QDeclarativeItem);
+ switch (ev->type()) {
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease:
+ case QEvent::InputMethod:
+ d->doneEventPreHandler = false;
+ break;
+ default:
+ break;
+ }
+
+ return QGraphicsObject::event(ev);
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug debug, QDeclarativeItem *item)
+{
+ if (!item) {
+ debug << "QDeclarativeItem(0)";
+ return debug;
+ }
+
+ debug << item->metaObject()->className() << "(this =" << ((void*)item)
+ << ", parent =" << ((void*)item->parentItem())
+ << ", geometry =" << QRectF(item->pos(), QSizeF(item->width(), item->height()))
+ << ", z =" << item->zValue() << ')';
+ return debug;
+}
+#endif
+
+qint64 QDeclarativeItemPrivate::consistentTime = -1;
+void QDeclarativeItemPrivate::setConsistentTime(qint64 t)
+{
+ consistentTime = t;
+}
+
+class QElapsedTimerConsistentTimeHack_1
+{
+public:
+ void start() {
+ t1 = QDeclarativeItemPrivate::consistentTime;
+ t2 = 0;
+ }
+ qint64 elapsed() {
+ return QDeclarativeItemPrivate::consistentTime - t1;
+ }
+ qint64 restart() {
+ qint64 val = QDeclarativeItemPrivate::consistentTime - t1;
+ t1 = QDeclarativeItemPrivate::consistentTime;
+ t2 = 0;
+ return val;
+ }
+
+private:
+ qint64 t1;
+ qint64 t2;
+};
+
+void QDeclarativeItemPrivate::start(QElapsedTimer &t)
+{
+ if (QDeclarativeItemPrivate::consistentTime == -1)
+ t.start();
+ else
+ ((QElapsedTimerConsistentTimeHack_1*)&t)->start();
+}
+
+qint64 QDeclarativeItemPrivate::elapsed(QElapsedTimer &t)
+{
+ if (QDeclarativeItemPrivate::consistentTime == -1)
+ return t.elapsed();
+ else
+ return ((QElapsedTimerConsistentTimeHack_1*)&t)->elapsed();
+}
+
+qint64 QDeclarativeItemPrivate::restart(QElapsedTimer &t)
+{
+ if (QDeclarativeItemPrivate::consistentTime == -1)
+ return t.restart();
+ else
+ return ((QElapsedTimerConsistentTimeHack_1*)&t)->restart();
+}
+
+QT_END_NAMESPACE
+
+#include <moc_qdeclarativeitem.cpp>
diff --git a/src/qtquick1/graphicsitems/qdeclarativeitem.h b/src/qtquick1/graphicsitems/qdeclarativeitem.h
new file mode 100644
index 0000000000..a3f4931316
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativeitem.h
@@ -0,0 +1,235 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEITEM_H
+#define QDECLARATIVEITEM_H
+
+#include <QtDeclarative/qdeclarative.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+
+#include <QtCore/QObject>
+#include <QtCore/QList>
+#include <QtGui/qgraphicsitem.h>
+#include <QtGui/qgraphicstransform.h>
+#include <QtGui/qfont.h>
+#include <QtGui/qaction.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarative1State;
+class QDeclarative1AnchorLine;
+class QDeclarative1Transition;
+class QDeclarative1KeyEvent;
+class QDeclarative1Anchors;
+class QDeclarativeItemPrivate;
+class QDeclarativeV8Function;
+class Q_DECLARATIVE_EXPORT QDeclarativeItem : public QGraphicsObject, public QDeclarativeParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QDeclarativeParserStatus)
+
+ Q_PROPERTY(QDeclarativeItem * parent READ parentItem WRITE setParentItem NOTIFY parentChanged DESIGNABLE false FINAL)
+ Q_PRIVATE_PROPERTY(QDeclarativeItem::d_func(), QDeclarativeListProperty<QObject> data READ data DESIGNABLE false)
+ Q_PRIVATE_PROPERTY(QDeclarativeItem::d_func(), QDeclarativeListProperty<QObject> resources READ resources DESIGNABLE false)
+ Q_PRIVATE_PROPERTY(QDeclarativeItem::d_func(), QDeclarativeListProperty<QDeclarative1State> states READ states DESIGNABLE false)
+ Q_PRIVATE_PROPERTY(QDeclarativeItem::d_func(), QDeclarativeListProperty<QDeclarative1Transition> transitions READ transitions DESIGNABLE false)
+ Q_PRIVATE_PROPERTY(QDeclarativeItem::d_func(), QString state READ state WRITE setState NOTIFY stateChanged)
+ Q_PROPERTY(QRectF childrenRect READ childrenRect NOTIFY childrenRectChanged DESIGNABLE false FINAL)
+ Q_PRIVATE_PROPERTY(QDeclarativeItem::d_func(), QDeclarative1Anchors * anchors READ anchors DESIGNABLE false CONSTANT FINAL)
+ Q_PRIVATE_PROPERTY(QDeclarativeItem::d_func(), QDeclarative1AnchorLine left READ left CONSTANT FINAL)
+ Q_PRIVATE_PROPERTY(QDeclarativeItem::d_func(), QDeclarative1AnchorLine right READ right CONSTANT FINAL)
+ Q_PRIVATE_PROPERTY(QDeclarativeItem::d_func(), QDeclarative1AnchorLine horizontalCenter READ horizontalCenter CONSTANT FINAL)
+ Q_PRIVATE_PROPERTY(QDeclarativeItem::d_func(), QDeclarative1AnchorLine top READ top CONSTANT FINAL)
+ Q_PRIVATE_PROPERTY(QDeclarativeItem::d_func(), QDeclarative1AnchorLine bottom READ bottom CONSTANT FINAL)
+ Q_PRIVATE_PROPERTY(QDeclarativeItem::d_func(), QDeclarative1AnchorLine verticalCenter READ verticalCenter CONSTANT FINAL)
+ Q_PRIVATE_PROPERTY(QDeclarativeItem::d_func(), QDeclarative1AnchorLine baseline READ baseline CONSTANT FINAL)
+ Q_PROPERTY(qreal baselineOffset READ baselineOffset WRITE setBaselineOffset NOTIFY baselineOffsetChanged)
+ Q_PROPERTY(bool clip READ clip WRITE setClip NOTIFY clipChanged) // ### move to QGI/QGO, NOTIFY
+ Q_PROPERTY(bool focus READ hasFocus WRITE setFocus NOTIFY focusChanged FINAL)
+ Q_PROPERTY(bool activeFocus READ hasActiveFocus NOTIFY activeFocusChanged)
+ Q_PROPERTY(QDeclarativeListProperty<QGraphicsTransform> transform READ transform DESIGNABLE false FINAL)
+ Q_PROPERTY(TransformOrigin transformOrigin READ transformOrigin WRITE setTransformOrigin NOTIFY transformOriginChanged)
+ Q_PROPERTY(QPointF transformOriginPoint READ transformOriginPoint) // transformOriginPoint is read-only for Item
+ Q_PROPERTY(bool smooth READ smooth WRITE setSmooth NOTIFY smoothChanged)
+ Q_PROPERTY(qreal implicitWidth READ implicitWidth WRITE setImplicitWidth NOTIFY implicitWidthChanged REVISION 1)
+ Q_PROPERTY(qreal implicitHeight READ implicitHeight WRITE setImplicitHeight NOTIFY implicitHeightChanged REVISION 1)
+
+ Q_ENUMS(TransformOrigin)
+ Q_CLASSINFO("DefaultProperty", "data")
+
+public:
+ enum TransformOrigin {
+ TopLeft, Top, TopRight,
+ Left, Center, Right,
+ BottomLeft, Bottom, BottomRight
+ };
+
+ QDeclarativeItem(QDeclarativeItem *parent = 0);
+ virtual ~QDeclarativeItem();
+
+ QDeclarativeItem *parentItem() const;
+ void setParentItem(QDeclarativeItem *parent);
+
+ QRectF childrenRect();
+
+ bool clip() const;
+ void setClip(bool);
+
+ qreal baselineOffset() const;
+ void setBaselineOffset(qreal);
+
+ QDeclarativeListProperty<QGraphicsTransform> transform();
+
+ qreal width() const;
+ void setWidth(qreal);
+ void resetWidth();
+ qreal implicitWidth() const;
+
+ qreal height() const;
+ void setHeight(qreal);
+ void resetHeight();
+ qreal implicitHeight() const;
+
+ void setSize(const QSizeF &size);
+
+ TransformOrigin transformOrigin() const;
+ void setTransformOrigin(TransformOrigin);
+
+ bool smooth() const;
+ void setSmooth(bool);
+
+ QRectF boundingRect() const;
+ virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
+
+ bool hasActiveFocus() const;
+ bool hasFocus() const;
+ void setFocus(bool);
+
+ bool keepMouseGrab() const;
+ void setKeepMouseGrab(bool);
+
+ Q_INVOKABLE void mapFromItem(QDeclarativeV8Function*) const;
+ Q_INVOKABLE void mapToItem(QDeclarativeV8Function*) const;
+ Q_INVOKABLE void forceActiveFocus();
+ Q_INVOKABLE QDeclarativeItem *childAt(qreal x, qreal y) const;
+
+Q_SIGNALS:
+ void childrenRectChanged(const QRectF &);
+ void baselineOffsetChanged(qreal);
+ void stateChanged(const QString &);
+ void focusChanged(bool);
+ void activeFocusChanged(bool);
+ void parentChanged(QDeclarativeItem *);
+ void transformOriginChanged(TransformOrigin);
+ void smoothChanged(bool);
+ void clipChanged(bool);
+ Q_REVISION(1) void implicitWidthChanged();
+ Q_REVISION(1) void implicitHeightChanged();
+
+protected:
+ bool isComponentComplete() const;
+ virtual bool sceneEvent(QEvent *);
+ virtual bool event(QEvent *);
+ virtual QVariant itemChange(GraphicsItemChange, const QVariant &);
+
+ void setImplicitWidth(qreal);
+ bool widthValid() const; // ### better name?
+ void setImplicitHeight(qreal);
+ bool heightValid() const; // ### better name?
+
+ virtual void classBegin();
+ virtual void componentComplete();
+ virtual void keyPressEvent(QKeyEvent *event);
+ virtual void keyReleaseEvent(QKeyEvent *event);
+ virtual void inputMethodEvent(QInputMethodEvent *);
+ virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const;
+ void keyPressPreHandler(QKeyEvent *);
+ void keyReleasePreHandler(QKeyEvent *);
+ void inputMethodPreHandler(QInputMethodEvent *);
+
+ virtual void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry);
+
+protected:
+ QDeclarativeItem(QDeclarativeItemPrivate &dd, QDeclarativeItem *parent = 0);
+
+private:
+ Q_DISABLE_COPY(QDeclarativeItem)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarativeItem)
+};
+
+template<typename T>
+ T qobject_cast(QGraphicsObject *o)
+{
+ QObject *obj = o;
+ return qobject_cast<T>(obj);
+}
+
+// ### move to QGO
+template<typename T>
+T qobject_cast(QGraphicsItem *item)
+{
+ if (!item) return 0;
+ QObject *o = item->toGraphicsObject();
+ return qobject_cast<T>(o);
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug Q_DECLARATIVE_EXPORT operator<<(QDebug debug, QDeclarativeItem *item);
+#endif
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativeItem)
+QML_DECLARE_TYPE(QGraphicsObject)
+QML_DECLARE_TYPE(QGraphicsTransform)
+QML_DECLARE_TYPE(QGraphicsScale)
+QML_DECLARE_TYPE(QGraphicsRotation)
+QML_DECLARE_TYPE(QGraphicsWidget)
+QML_DECLARE_TYPE(QAction)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEITEM_H
diff --git a/src/qtquick1/graphicsitems/qdeclarativeitem_p.h b/src/qtquick1/graphicsitems/qdeclarativeitem_p.h
new file mode 100644
index 0000000000..58d57abbf3
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativeitem_p.h
@@ -0,0 +1,635 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEITEM_P_H
+#define QDECLARATIVEITEM_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtQuick1/qdeclarativeitem.h"
+
+#include "QtQuick1/private/qdeclarativeanchors_p.h"
+#include "QtQuick1/private/qdeclarativeanchors_p_p.h"
+#include "QtQuick1/private/qdeclarativeitemchangelistener_p.h"
+#include <QtDeclarative/private/qpodvector_p.h>
+
+#include <QtQuick1/private/qdeclarativestate_p.h>
+#include <QtDeclarative/private/qdeclarativenullablevalue_p_p.h>
+#include <QtDeclarative/private/qdeclarativenotifier_p.h>
+#include <QtDeclarative/private/qdeclarativeglobal_p.h>
+
+#include <QtDeclarative/qdeclarative.h>
+#include <QtDeclarative/qdeclarativecontext.h>
+
+#include <QtCore/qlist.h>
+#include <QtCore/qrect.h>
+#include <QtCore/qdebug.h>
+
+#include <private/qgraphicsitem_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkReply;
+
+class QDeclarativeItemKeyFilter;
+class QDeclarative1LayoutMirroringAttached;
+
+//### merge into private?
+class QDeclarative1Contents : public QObject, public QDeclarativeItemChangeListener
+{
+ Q_OBJECT
+public:
+ QDeclarative1Contents(QDeclarativeItem *item);
+ ~QDeclarative1Contents();
+
+ QRectF rectF() const;
+
+ void childRemoved(QDeclarativeItem *item);
+ void childAdded(QDeclarativeItem *item);
+
+ void calcGeometry() { calcWidth(); calcHeight(); }
+ void complete();
+
+Q_SIGNALS:
+ void rectChanged(QRectF);
+
+protected:
+ void itemGeometryChanged(QDeclarativeItem *item, const QRectF &newGeometry, const QRectF &oldGeometry);
+ void itemDestroyed(QDeclarativeItem *item);
+ //void itemVisibilityChanged(QDeclarativeItem *item)
+
+private:
+ void calcHeight(QDeclarativeItem *changed = 0);
+ void calcWidth(QDeclarativeItem *changed = 0);
+
+ QDeclarativeItem *m_item;
+ qreal m_x;
+ qreal m_y;
+ qreal m_width;
+ qreal m_height;
+};
+
+class Q_DECLARATIVE_EXPORT QDeclarativeItemPrivate : public QGraphicsItemPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarativeItem)
+
+public:
+ QDeclarativeItemPrivate()
+ : _anchors(0), _contents(0),
+ baselineOffset(0),
+ _anchorLines(0),
+ _stateGroup(0), origin(QDeclarativeItem::Center),
+ widthValid(false), heightValid(false),
+ componentComplete(true), keepMouse(false),
+ smooth(false), transformOriginDirty(true), doneEventPreHandler(false),
+ inheritedLayoutMirror(false), effectiveLayoutMirror(false), isMirrorImplicit(true),
+ inheritMirrorFromParent(false), inheritMirrorFromItem(false), keyHandler(0),
+ mWidth(0), mHeight(0), mImplicitWidth(0), mImplicitHeight(0), attachedLayoutDirection(0), hadSubFocusItem(false)
+ {
+ QGraphicsItemPrivate::acceptedMouseButtons = 0;
+ isDeclarativeItem = 1;
+ QGraphicsItemPrivate::flags = QGraphicsItem::GraphicsItemFlags(
+ QGraphicsItem::ItemHasNoContents
+ | QGraphicsItem::ItemIsFocusable
+ | QGraphicsItem::ItemNegativeZStacksBehindParent);
+ }
+
+ void init(QDeclarativeItem *parent)
+ {
+ Q_Q(QDeclarativeItem);
+ if (parent) {
+ QDeclarative_setParent_noEvent(q, parent);
+ q->setParentItem(parent);
+ QDeclarativeItemPrivate *parentPrivate = QDeclarativeItemPrivate::get(parent);
+ setImplicitLayoutMirror(parentPrivate->inheritedLayoutMirror, parentPrivate->inheritMirrorFromParent);
+ }
+ baselineOffset.invalidate();
+ mouseSetsFocus = false;
+ }
+
+ bool isMirrored() const {
+ return effectiveLayoutMirror;
+ }
+
+ // Private Properties
+ qreal width() const;
+ void setWidth(qreal);
+ void resetWidth();
+
+ qreal height() const;
+ void setHeight(qreal);
+ void resetHeight();
+
+ virtual qreal implicitWidth() const;
+ virtual qreal implicitHeight() const;
+ virtual void implicitWidthChanged();
+ virtual void implicitHeightChanged();
+
+ void resolveLayoutMirror();
+ void setImplicitLayoutMirror(bool mirror, bool inherit);
+ void setLayoutMirror(bool mirror);
+
+ QDeclarativeListProperty<QObject> data();
+ QDeclarativeListProperty<QObject> resources();
+
+ QDeclarativeListProperty<QDeclarative1State> states();
+ QDeclarativeListProperty<QDeclarative1Transition> transitions();
+
+ QString state() const;
+ void setState(const QString &);
+
+ QDeclarative1AnchorLine left() const;
+ QDeclarative1AnchorLine right() const;
+ QDeclarative1AnchorLine horizontalCenter() const;
+ QDeclarative1AnchorLine top() const;
+ QDeclarative1AnchorLine bottom() const;
+ QDeclarative1AnchorLine verticalCenter() const;
+ QDeclarative1AnchorLine baseline() const;
+
+ // data property
+ static void data_append(QDeclarativeListProperty<QObject> *, QObject *);
+ static int data_count(QDeclarativeListProperty<QObject> *);
+ static QObject *data_at(QDeclarativeListProperty<QObject> *, int);
+ static void data_clear(QDeclarativeListProperty<QObject> *);
+
+ // resources property
+ static QObject *resources_at(QDeclarativeListProperty<QObject> *, int);
+ static void resources_append(QDeclarativeListProperty<QObject> *, QObject *);
+ static int resources_count(QDeclarativeListProperty<QObject> *);
+ static void resources_clear(QDeclarativeListProperty<QObject> *);
+
+ // transform property
+ static int transform_count(QDeclarativeListProperty<QGraphicsTransform> *list);
+ static void transform_append(QDeclarativeListProperty<QGraphicsTransform> *list, QGraphicsTransform *);
+ static QGraphicsTransform *transform_at(QDeclarativeListProperty<QGraphicsTransform> *list, int);
+ static void transform_clear(QDeclarativeListProperty<QGraphicsTransform> *list);
+
+ static QDeclarativeItemPrivate* get(QDeclarativeItem *item)
+ {
+ return item->d_func();
+ }
+
+ // Accelerated property accessors
+ QDeclarativeNotifier parentNotifier;
+ static void parentProperty(QObject *o, void *rv, QDeclarativeNotifierEndpoint *e);
+
+ QDeclarative1Anchors *anchors() {
+ if (!_anchors) {
+ Q_Q(QDeclarativeItem);
+ _anchors = new QDeclarative1Anchors(q);
+ if (!componentComplete)
+ _anchors->classBegin();
+ }
+ return _anchors;
+ }
+ QDeclarative1Anchors *_anchors;
+ QDeclarative1Contents *_contents;
+
+ QDeclarativeNullableValue<qreal> baselineOffset;
+
+ struct AnchorLines {
+ AnchorLines(QGraphicsObject *);
+ QDeclarative1AnchorLine left;
+ QDeclarative1AnchorLine right;
+ QDeclarative1AnchorLine hCenter;
+ QDeclarative1AnchorLine top;
+ QDeclarative1AnchorLine bottom;
+ QDeclarative1AnchorLine vCenter;
+ QDeclarative1AnchorLine baseline;
+ };
+ mutable AnchorLines *_anchorLines;
+ AnchorLines *anchorLines() const {
+ Q_Q(const QDeclarativeItem);
+ if (!_anchorLines) _anchorLines =
+ new AnchorLines(const_cast<QDeclarativeItem *>(q));
+ return _anchorLines;
+ }
+
+ enum ChangeType {
+ Geometry = 0x01,
+ SiblingOrder = 0x02,
+ Visibility = 0x04,
+ Opacity = 0x08,
+ Destroyed = 0x10
+ };
+
+ Q_DECLARE_FLAGS(ChangeTypes, ChangeType)
+
+ struct ChangeListener {
+ ChangeListener(QDeclarativeItemChangeListener *l, QDeclarativeItemPrivate::ChangeTypes t) : listener(l), types(t) {}
+ QDeclarativeItemChangeListener *listener;
+ QDeclarativeItemPrivate::ChangeTypes types;
+ bool operator==(const ChangeListener &other) const { return listener == other.listener && types == other.types; }
+ };
+
+ void addItemChangeListener(QDeclarativeItemChangeListener *listener, ChangeTypes types) {
+ changeListeners.append(ChangeListener(listener, types));
+ }
+ void removeItemChangeListener(QDeclarativeItemChangeListener *, ChangeTypes types);
+ QPODVector<ChangeListener,4> changeListeners;
+
+ QDeclarative1StateGroup *_states();
+ QDeclarative1StateGroup *_stateGroup;
+
+ QDeclarativeItem::TransformOrigin origin:5;
+ bool widthValid:1;
+ bool heightValid:1;
+ bool componentComplete:1;
+ bool keepMouse:1;
+ bool smooth:1;
+ bool transformOriginDirty : 1;
+ bool doneEventPreHandler : 1;
+ bool inheritedLayoutMirror:1;
+ bool effectiveLayoutMirror:1;
+ bool isMirrorImplicit:1;
+ bool inheritMirrorFromParent:1;
+ bool inheritMirrorFromItem:1;
+
+ QDeclarativeItemKeyFilter *keyHandler;
+
+ qreal mWidth;
+ qreal mHeight;
+ qreal mImplicitWidth;
+ qreal mImplicitHeight;
+
+ QDeclarative1LayoutMirroringAttached* attachedLayoutDirection;
+
+ bool hadSubFocusItem;
+
+ QPointF computeTransformOrigin() const;
+
+ virtual void setPosHelper(const QPointF &pos)
+ {
+ Q_Q(QDeclarativeItem);
+ QRectF oldGeometry(this->pos.x(), this->pos.y(), mWidth, mHeight);
+ QGraphicsItemPrivate::setPosHelper(pos);
+ q->geometryChanged(QRectF(this->pos.x(), this->pos.y(), mWidth, mHeight), oldGeometry);
+ }
+
+ // Reimplemented from QGraphicsItemPrivate
+ virtual void subFocusItemChange()
+ {
+ bool hasSubFocusItem = subFocusItem != 0;
+ if (((flags & QGraphicsItem::ItemIsFocusScope) || !parent) && hasSubFocusItem != hadSubFocusItem)
+ emit q_func()->activeFocusChanged(hasSubFocusItem);
+ //see also QDeclarativeItemPrivate::focusChanged
+ hadSubFocusItem = hasSubFocusItem;
+ }
+
+ // Reimplemented from QGraphicsItemPrivate
+ virtual void focusScopeItemChange(bool isSubFocusItem)
+ {
+ emit q_func()->focusChanged(isSubFocusItem);
+ }
+
+
+ // Reimplemented from QGraphicsItemPrivate
+ virtual void siblingOrderChange()
+ {
+ Q_Q(QDeclarativeItem);
+ for(int ii = 0; ii < changeListeners.count(); ++ii) {
+ const QDeclarativeItemPrivate::ChangeListener &change = changeListeners.at(ii);
+ if (change.types & QDeclarativeItemPrivate::SiblingOrder) {
+ change.listener->itemSiblingOrderChanged(q);
+ }
+ }
+ }
+
+ // Reimplemented from QGraphicsItemPrivate
+ virtual void transformChanged();
+
+ virtual void focusChanged(bool);
+
+ virtual void mirrorChange() {};
+
+ static qint64 consistentTime;
+ static void setConsistentTime(qint64 t);
+ static void start(QElapsedTimer &);
+ static qint64 elapsed(QElapsedTimer &);
+ static qint64 restart(QElapsedTimer &);
+};
+
+/*
+ Key filters can be installed on a QDeclarativeItem, but not removed. Currently they
+ are only used by attached objects (which are only destroyed on Item
+ destruction), so this isn't a problem. If in future this becomes any form
+ of public API, they will have to support removal too.
+*/
+class QDeclarativeItemKeyFilter
+{
+public:
+ QDeclarativeItemKeyFilter(QDeclarativeItem * = 0);
+ virtual ~QDeclarativeItemKeyFilter();
+
+ virtual void keyPressed(QKeyEvent *event, bool post);
+ virtual void keyReleased(QKeyEvent *event, bool post);
+ virtual void inputMethodEvent(QInputMethodEvent *event, bool post);
+ virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const;
+ virtual void componentComplete();
+
+ bool m_processPost;
+
+private:
+ QDeclarativeItemKeyFilter *m_next;
+};
+
+class QDeclarative1KeyNavigationAttachedPrivate : public QObjectPrivate
+{
+public:
+ QDeclarative1KeyNavigationAttachedPrivate()
+ : QObjectPrivate(),
+ left(0), right(0), up(0), down(0), tab(0), backtab(0),
+ leftSet(false), rightSet(false), upSet(false), downSet(false),
+ tabSet(false), backtabSet(false) {}
+
+ QDeclarativeItem *left;
+ QDeclarativeItem *right;
+ QDeclarativeItem *up;
+ QDeclarativeItem *down;
+ QDeclarativeItem *tab;
+ QDeclarativeItem *backtab;
+ bool leftSet : 1;
+ bool rightSet : 1;
+ bool upSet : 1;
+ bool downSet : 1;
+ bool tabSet : 1;
+ bool backtabSet : 1;
+};
+
+class QDeclarative1KeyNavigationAttached : public QObject, public QDeclarativeItemKeyFilter
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarative1KeyNavigationAttached)
+
+ Q_PROPERTY(QDeclarativeItem *left READ left WRITE setLeft NOTIFY leftChanged)
+ Q_PROPERTY(QDeclarativeItem *right READ right WRITE setRight NOTIFY rightChanged)
+ Q_PROPERTY(QDeclarativeItem *up READ up WRITE setUp NOTIFY upChanged)
+ Q_PROPERTY(QDeclarativeItem *down READ down WRITE setDown NOTIFY downChanged)
+ Q_PROPERTY(QDeclarativeItem *tab READ tab WRITE setTab NOTIFY tabChanged)
+ Q_PROPERTY(QDeclarativeItem *backtab READ backtab WRITE setBacktab NOTIFY backtabChanged)
+ Q_PROPERTY(Priority priority READ priority WRITE setPriority NOTIFY priorityChanged)
+
+ Q_ENUMS(Priority)
+
+public:
+ QDeclarative1KeyNavigationAttached(QObject * = 0);
+
+ QDeclarativeItem *left() const;
+ void setLeft(QDeclarativeItem *);
+ QDeclarativeItem *right() const;
+ void setRight(QDeclarativeItem *);
+ QDeclarativeItem *up() const;
+ void setUp(QDeclarativeItem *);
+ QDeclarativeItem *down() const;
+ void setDown(QDeclarativeItem *);
+ QDeclarativeItem *tab() const;
+ void setTab(QDeclarativeItem *);
+ QDeclarativeItem *backtab() const;
+ void setBacktab(QDeclarativeItem *);
+
+ enum Priority { BeforeItem, AfterItem };
+ Priority priority() const;
+ void setPriority(Priority);
+
+ static QDeclarative1KeyNavigationAttached *qmlAttachedProperties(QObject *);
+
+Q_SIGNALS:
+ void leftChanged();
+ void rightChanged();
+ void upChanged();
+ void downChanged();
+ void tabChanged();
+ void backtabChanged();
+ void priorityChanged();
+
+private:
+ virtual void keyPressed(QKeyEvent *event, bool post);
+ virtual void keyReleased(QKeyEvent *event, bool post);
+ void setFocusNavigation(QDeclarativeItem *currentItem, const char *dir);
+};
+
+class QDeclarative1LayoutMirroringAttached : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled RESET resetEnabled NOTIFY enabledChanged)
+ Q_PROPERTY(bool childrenInherit READ childrenInherit WRITE setChildrenInherit NOTIFY childrenInheritChanged)
+
+public:
+ explicit QDeclarative1LayoutMirroringAttached(QObject *parent = 0);
+
+ bool enabled() const;
+ void setEnabled(bool);
+ void resetEnabled();
+
+ bool childrenInherit() const;
+ void setChildrenInherit(bool);
+
+ static QDeclarative1LayoutMirroringAttached *qmlAttachedProperties(QObject *);
+Q_SIGNALS:
+ void enabledChanged();
+ void childrenInheritChanged();
+private:
+ friend class QDeclarativeItemPrivate;
+ QDeclarativeItemPrivate *itemPrivate;
+};
+
+class QDeclarative1KeysAttachedPrivate : public QObjectPrivate
+{
+public:
+ QDeclarative1KeysAttachedPrivate()
+ : QObjectPrivate(), inPress(false), inRelease(false)
+ , inIM(false), enabled(true), imeItem(0), item(0)
+ {}
+
+ bool isConnected(const char *signalName);
+
+ QGraphicsItem *finalFocusProxy(QGraphicsItem *item) const
+ {
+ QGraphicsItem *fp;
+ while ((fp = item->focusProxy()))
+ item = fp;
+ return item;
+ }
+
+ //loop detection
+ bool inPress:1;
+ bool inRelease:1;
+ bool inIM:1;
+
+ bool enabled : 1;
+
+ QGraphicsItem *imeItem;
+ QList<QDeclarativeItem *> targets;
+ QDeclarativeItem *item;
+};
+
+class QDeclarative1KeysAttached : public QObject, public QDeclarativeItemKeyFilter
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarative1KeysAttached)
+
+ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
+ Q_PROPERTY(QDeclarativeListProperty<QDeclarativeItem> forwardTo READ forwardTo)
+ Q_PROPERTY(Priority priority READ priority WRITE setPriority NOTIFY priorityChanged)
+
+ Q_ENUMS(Priority)
+
+public:
+ QDeclarative1KeysAttached(QObject *parent=0);
+ ~QDeclarative1KeysAttached();
+
+ bool enabled() const { Q_D(const QDeclarative1KeysAttached); return d->enabled; }
+ void setEnabled(bool enabled) {
+ Q_D(QDeclarative1KeysAttached);
+ if (enabled != d->enabled) {
+ d->enabled = enabled;
+ emit enabledChanged();
+ }
+ }
+
+ enum Priority { BeforeItem, AfterItem};
+ Priority priority() const;
+ void setPriority(Priority);
+
+ QDeclarativeListProperty<QDeclarativeItem> forwardTo() {
+ Q_D(QDeclarative1KeysAttached);
+ return QDeclarativeListProperty<QDeclarativeItem>(this, d->targets);
+ }
+
+ virtual void componentComplete();
+
+ static QDeclarative1KeysAttached *qmlAttachedProperties(QObject *);
+
+Q_SIGNALS:
+ void enabledChanged();
+ void priorityChanged();
+ void pressed(QDeclarative1KeyEvent *event);
+ void released(QDeclarative1KeyEvent *event);
+ void digit0Pressed(QDeclarative1KeyEvent *event);
+ void digit1Pressed(QDeclarative1KeyEvent *event);
+ void digit2Pressed(QDeclarative1KeyEvent *event);
+ void digit3Pressed(QDeclarative1KeyEvent *event);
+ void digit4Pressed(QDeclarative1KeyEvent *event);
+ void digit5Pressed(QDeclarative1KeyEvent *event);
+ void digit6Pressed(QDeclarative1KeyEvent *event);
+ void digit7Pressed(QDeclarative1KeyEvent *event);
+ void digit8Pressed(QDeclarative1KeyEvent *event);
+ void digit9Pressed(QDeclarative1KeyEvent *event);
+
+ void leftPressed(QDeclarative1KeyEvent *event);
+ void rightPressed(QDeclarative1KeyEvent *event);
+ void upPressed(QDeclarative1KeyEvent *event);
+ void downPressed(QDeclarative1KeyEvent *event);
+ void tabPressed(QDeclarative1KeyEvent *event);
+ void backtabPressed(QDeclarative1KeyEvent *event);
+
+ void asteriskPressed(QDeclarative1KeyEvent *event);
+ void numberSignPressed(QDeclarative1KeyEvent *event);
+ void escapePressed(QDeclarative1KeyEvent *event);
+ void returnPressed(QDeclarative1KeyEvent *event);
+ void enterPressed(QDeclarative1KeyEvent *event);
+ void deletePressed(QDeclarative1KeyEvent *event);
+ void spacePressed(QDeclarative1KeyEvent *event);
+ void backPressed(QDeclarative1KeyEvent *event);
+ void cancelPressed(QDeclarative1KeyEvent *event);
+ void selectPressed(QDeclarative1KeyEvent *event);
+ void yesPressed(QDeclarative1KeyEvent *event);
+ void noPressed(QDeclarative1KeyEvent *event);
+ void context1Pressed(QDeclarative1KeyEvent *event);
+ void context2Pressed(QDeclarative1KeyEvent *event);
+ void context3Pressed(QDeclarative1KeyEvent *event);
+ void context4Pressed(QDeclarative1KeyEvent *event);
+ void callPressed(QDeclarative1KeyEvent *event);
+ void hangupPressed(QDeclarative1KeyEvent *event);
+ void flipPressed(QDeclarative1KeyEvent *event);
+ void menuPressed(QDeclarative1KeyEvent *event);
+ void volumeUpPressed(QDeclarative1KeyEvent *event);
+ void volumeDownPressed(QDeclarative1KeyEvent *event);
+
+private:
+ virtual void keyPressed(QKeyEvent *event, bool post);
+ virtual void keyReleased(QKeyEvent *event, bool post);
+ virtual void inputMethodEvent(QInputMethodEvent *, bool post);
+ virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const;
+
+ const QByteArray keyToSignal(int key) {
+ QByteArray keySignal;
+ if (key >= Qt::Key_0 && key <= Qt::Key_9) {
+ keySignal = "digit0Pressed";
+ keySignal[5] = '0' + (key - Qt::Key_0);
+ } else {
+ int i = 0;
+ while (sigMap[i].key && sigMap[i].key != key)
+ ++i;
+ keySignal = sigMap[i].sig;
+ }
+ return keySignal;
+ }
+
+ struct SigMap {
+ int key;
+ const char *sig;
+ };
+
+ static const SigMap sigMap[];
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativeItemPrivate::ChangeTypes);
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1KeysAttached)
+QML_DECLARE_TYPEINFO(QDeclarative1KeysAttached, QML_HAS_ATTACHED_PROPERTIES)
+QML_DECLARE_TYPE(QDeclarative1KeyNavigationAttached)
+QML_DECLARE_TYPEINFO(QDeclarative1KeyNavigationAttached, QML_HAS_ATTACHED_PROPERTIES)
+QML_DECLARE_TYPE(QDeclarative1LayoutMirroringAttached)
+QML_DECLARE_TYPEINFO(QDeclarative1LayoutMirroringAttached, QML_HAS_ATTACHED_PROPERTIES)
+
+#endif // QDECLARATIVEITEM_P_H
diff --git a/src/qtquick1/graphicsitems/qdeclarativeitemchangelistener_p.h b/src/qtquick1/graphicsitems/qdeclarativeitemchangelistener_p.h
new file mode 100644
index 0000000000..4b10a38660
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativeitemchangelistener_p.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEITEMCHANGELISTENER
+#define QDECLARATIVEITEMCHANGELISTENER
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QRectF;
+class QDeclarativeItem;
+class QDeclarative1AnchorsPrivate;
+class QDeclarativeItemChangeListener
+{
+public:
+ virtual void itemGeometryChanged(QDeclarativeItem *, const QRectF &, const QRectF &) {}
+ virtual void itemSiblingOrderChanged(QDeclarativeItem *) {}
+ virtual void itemVisibilityChanged(QDeclarativeItem *) {}
+ virtual void itemOpacityChanged(QDeclarativeItem *) {}
+ virtual void itemDestroyed(QDeclarativeItem *) {}
+ virtual QDeclarative1AnchorsPrivate *anchorPrivate() { return 0; }
+};
+
+QT_END_NAMESPACE
+
+#endif // QDECLARATIVEITEMCHANGELISTENER
diff --git a/src/qtquick1/graphicsitems/qdeclarativeitemsmodule.cpp b/src/qtquick1/graphicsitems/qdeclarativeitemsmodule.cpp
new file mode 100644
index 0000000000..78f13cdbd8
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativeitemsmodule.cpp
@@ -0,0 +1,267 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativeitemsmodule_p.h"
+
+#include <QtGui/qaction.h>
+#include <QtGui/qvalidator.h>
+#include <QtGui/qgraphicseffect.h>
+#include <QtGui/qgraphicsitem.h>
+
+#include "QtQuick1/private/qdeclarativeevents_p_p.h"
+#include "QtQuick1/private/qdeclarativescalegrid_p_p.h"
+#include "QtQuick1/private/qdeclarativeanimatedimage_p.h"
+#include "QtQuick1/private/qdeclarativeborderimage_p.h"
+#include "QtQuick1/private/qdeclarativepositioners_p.h"
+#include "QtQuick1/private/qdeclarativemousearea_p.h"
+#include "QtQuick1/private/qdeclarativeflickable_p.h"
+#include "QtQuick1/private/qdeclarativeflickable_p_p.h"
+#include "QtQuick1/private/qdeclarativeflipable_p.h"
+#include "QtQuick1/private/qdeclarativefocuspanel_p.h"
+#include "QtQuick1/private/qdeclarativefocusscope_p.h"
+#include "QtQuick1/private/qdeclarativegridview_p.h"
+#include "QtQuick1/private/qdeclarativeimage_p.h"
+#include "QtQuick1/private/qdeclarativeitem_p.h"
+#include "QtQuick1/private/qdeclarativelayoutitem_p.h"
+#include "QtQuick1/private/qdeclarativelistview_p.h"
+#include "QtQuick1/private/qdeclarativeloader_p.h"
+#include "QtQuick1/private/qdeclarativemousearea_p.h"
+#include "QtQuick1/private/qdeclarativepath_p.h"
+#include "QtQuick1/private/qdeclarativepathview_p.h"
+#include "QtQuick1/private/qdeclarativerectangle_p.h"
+#include "QtQuick1/private/qdeclarativerepeater_p.h"
+#include "QtQuick1/private/qdeclarativetranslate_p.h"
+#include "QtQuick1/private/qdeclarativetext_p.h"
+#include "QtQuick1/private/qdeclarativetextedit_p.h"
+#include "QtQuick1/private/qdeclarativetextinput_p.h"
+#include "QtQuick1/private/qdeclarativevisualitemmodel_p.h"
+#include "QtQuick1/private/qdeclarativegraphicswidget_p.h"
+#ifdef QT_WEBKIT_LIB
+#include "QtQuick1/private/qdeclarativewebview_p.h"
+#include "QtQuick1/private/qdeclarativewebview_p_p.h"
+#endif
+#include "QtQuick1/private/qdeclarativeanchors_p.h"
+#include "QtQuick1/private/qdeclarativepincharea_p.h"
+
+static QDeclarativePrivate::AutoParentResult qgraphicsobject_autoParent(QObject *obj, QObject *parent)
+{
+ QGraphicsObject* gobj = qobject_cast<QGraphicsObject*>(obj);
+ if (!gobj)
+ return QDeclarativePrivate::IncompatibleObject;
+
+ QGraphicsObject* gparent = qobject_cast<QGraphicsObject*>(parent);
+ if (!gparent)
+ return QDeclarativePrivate::IncompatibleParent;
+
+ gobj->setParentItem(gparent);
+ return QDeclarativePrivate::Parented;
+}
+
+void QDeclarative1ItemModule::defineModule(QDeclarativeQtQuick1Module::Module module)
+{
+ QDeclarativePrivate::RegisterAutoParent autoparent = { 0, &qgraphicsobject_autoParent };
+ QDeclarativePrivate::qmlregister(QDeclarativePrivate::AutoParentRegistration, &autoparent);
+
+ qmlRegisterType<QDeclarative1Anchors>();
+ qmlRegisterType<QDeclarative1KeyEvent>();
+ qmlRegisterType<QDeclarative1MouseEvent>();
+ qmlRegisterType<QGraphicsObject>();
+ qmlRegisterType<QGraphicsTransform>();
+ qmlRegisterType<QDeclarative1PathElement>();
+ qmlRegisterType<QDeclarative1Curve>();
+ qmlRegisterType<QDeclarative1ScaleGrid>();
+#ifndef QT_NO_VALIDATOR
+ qmlRegisterType<QValidator>();
+#endif
+ qmlRegisterType<QDeclarative1VisualModel>();
+#ifndef QT_NO_ACTION
+ qmlRegisterType<QAction>();
+#endif
+ qmlRegisterType<QDeclarative1Pen>();
+ qmlRegisterType<QDeclarative1FlickableVisibleArea>();
+#ifndef QT_NO_GRAPHICSEFFECT
+ qmlRegisterType<QGraphicsEffect>();
+#endif
+
+ if (module == QDeclarativeQtQuick1Module::QtQuick1) {
+#ifdef QT_NO_MOVIE
+ qmlRegisterTypeNotAvailable("QtQuick",1,0,"AnimatedImage",
+ qApp->translate("QDeclarative1AnimatedImage","Qt was built without support for QMovie"));
+#else
+ qmlRegisterType<QDeclarative1AnimatedImage>("QtQuick",1,0,"AnimatedImage");
+#endif
+ qmlRegisterType<QDeclarative1BorderImage>("QtQuick",1,0,"BorderImage");
+ qmlRegisterType<QDeclarative1Column>("QtQuick",1,0,"Column");
+ qmlRegisterType<QDeclarative1Drag>("QtQuick",1,0,"Drag");
+ qmlRegisterType<QDeclarative1Flickable>("QtQuick",1,0,"Flickable");
+ qmlRegisterType<QDeclarative1Flipable>("QtQuick",1,0,"Flipable");
+ qmlRegisterType<QDeclarative1Flow>("QtQuick",1,0,"Flow");
+ qmlRegisterType<QDeclarative1FocusPanel>("QtQuick",1,0,"FocusPanel");
+ qmlRegisterType<QDeclarative1FocusScope>("QtQuick",1,0,"FocusScope");
+ qmlRegisterType<QDeclarative1Gradient>("QtQuick",1,0,"Gradient");
+ qmlRegisterType<QDeclarative1GradientStop>("QtQuick",1,0,"GradientStop");
+ qmlRegisterType<QDeclarative1Grid>("QtQuick",1,0,"Grid");
+ qmlRegisterType<QDeclarative1GridView>("QtQuick",1,0,"GridView");
+ qmlRegisterType<QDeclarative1Image>("QtQuick",1,0,"Image");
+ qmlRegisterType<QDeclarativeItem>("QtQuick",1,0,"Item");
+ qmlRegisterType<QDeclarative1LayoutItem>("QtQuick",1,0,"LayoutItem");
+ qmlRegisterType<QDeclarative1ListView>("QtQuick",1,0,"ListView");
+ qmlRegisterType<QDeclarative1Loader>("QtQuick",1,0,"Loader");
+ qmlRegisterType<QDeclarative1MouseArea>("QtQuick",1,0,"MouseArea");
+ qmlRegisterType<QDeclarative1Path>("QtQuick",1,0,"Path");
+ qmlRegisterType<QDeclarative1PathAttribute>("QtQuick",1,0,"PathAttribute");
+ qmlRegisterType<QDeclarative1PathCubic>("QtQuick",1,0,"PathCubic");
+ qmlRegisterType<QDeclarative1PathLine>("QtQuick",1,0,"PathLine");
+ qmlRegisterType<QDeclarative1PathPercent>("QtQuick",1,0,"PathPercent");
+ qmlRegisterType<QDeclarative1PathQuad>("QtQuick",1,0,"PathQuad");
+ qmlRegisterType<QDeclarative1PathView>("QtQuick",1,0,"PathView");
+#ifndef QT_NO_VALIDATOR
+ qmlRegisterType<QIntValidator>("QtQuick",1,0,"IntValidator");
+ qmlRegisterType<QDoubleValidator>("QtQuick",1,0,"DoubleValidator");
+ qmlRegisterType<QRegExpValidator>("QtQuick",1,0,"RegExpValidator");
+#endif
+ qmlRegisterType<QDeclarative1Rectangle>("QtQuick",1,0,"Rectangle");
+ qmlRegisterType<QDeclarative1Repeater>("QtQuick",1,0,"Repeater");
+ qmlRegisterType<QGraphicsRotation>("QtQuick",1,0,"Rotation");
+ qmlRegisterType<QDeclarative1Row>("QtQuick",1,0,"Row");
+ qmlRegisterType<QDeclarative1Translate>("QtQuick",1,0,"Translate");
+ qmlRegisterType<QGraphicsScale>("QtQuick",1,0,"Scale");
+ qmlRegisterType<QDeclarative1Text>("QtQuick",1,0,"Text");
+ qmlRegisterType<QDeclarative1TextEdit>("QtQuick",1,0,"TextEdit");
+#ifndef QT_NO_LINEEDIT
+ qmlRegisterType<QDeclarative1TextInput>("QtQuick",1,0,"TextInput");
+#endif
+ qmlRegisterType<QDeclarative1ViewSection>("QtQuick",1,0,"ViewSection");
+ qmlRegisterType<QDeclarative1VisualDataModel>("QtQuick",1,0,"VisualDataModel");
+ qmlRegisterType<QDeclarative1VisualItemModel>("QtQuick",1,0,"VisualItemModel");
+
+ qmlRegisterType<QGraphicsWidget>("QtQuick",1,0,"QGraphicsWidget");
+ qmlRegisterExtendedType<QGraphicsWidget,QDeclarative1GraphicsWidget>("QtQuick",1,0,"QGraphicsWidget");
+
+ qmlRegisterUncreatableType<QDeclarative1KeyNavigationAttached>("QtQuick",1,0,"KeyNavigation",QDeclarative1KeyNavigationAttached::tr("KeyNavigation is only available via attached properties"));
+ qmlRegisterUncreatableType<QDeclarative1KeysAttached>("QtQuick",1,0,"Keys",QDeclarative1KeysAttached::tr("Keys is only available via attached properties"));
+
+ // QtQuick 1.1 items
+ qmlRegisterType<QDeclarative1PinchArea>("QtQuick",1,1,"PinchArea");
+ qmlRegisterType<QDeclarative1Pinch>("QtQuick",1,1,"Pinch");
+ qmlRegisterType<QDeclarative1PinchEvent>();
+ qmlRegisterType<QDeclarativeItem,1>("QtQuick",1,1,"Item");
+ qmlRegisterType<QDeclarative1MouseArea,1>("QtQuick",1,1,"MouseArea");
+ qmlRegisterType<QDeclarative1Flickable,1>("QtQuick",1,1,"Flickable");
+ qmlRegisterType<QDeclarative1ListView,1>("QtQuick",1,1,"ListView");
+ qmlRegisterType<QDeclarative1GridView,1>("QtQuick",1,1,"GridView");
+ qmlRegisterType<QDeclarative1Row,1>("QtQuick",1,1,"Row");
+ qmlRegisterType<QDeclarative1Grid,1>("QtQuick",1,1,"Grid");
+ qmlRegisterType<QDeclarative1Flow,1>("QtQuick",1,1,"Flow");
+ qmlRegisterType<QDeclarative1Repeater,1>("QtQuick",1,1,"Repeater");
+ qmlRegisterType<QDeclarative1Text,1>("QtQuick",1,1,"Text");
+ qmlRegisterType<QDeclarative1TextEdit,1>("QtQuick",1,1,"TextEdit");
+#ifndef QT_NO_LINEEDIT
+ qmlRegisterType<QDeclarative1TextInput,1>("QtQuick",1,1,"TextInput");
+#endif
+ qmlRegisterRevision<QDeclarative1ImageBase,1>("QtQuick",1,1);
+ qmlRegisterRevision<QDeclarative1ImplicitSizeItem,0>("QtQuick",1,0);
+ qmlRegisterRevision<QDeclarative1ImplicitSizeItem,1>("QtQuick",1,1);
+ qmlRegisterRevision<QDeclarative1ImplicitSizePaintedItem,0>("QtQuick",1,0);
+ qmlRegisterRevision<QDeclarative1ImplicitSizePaintedItem,1>("QtQuick",1,1);
+ qmlRegisterUncreatableType<QDeclarative1LayoutMirroringAttached>("QtQuick",1,1,"LayoutMirroring", QDeclarative1LayoutMirroringAttached::tr("LayoutMirroring is only available via attached properties"));
+ } else if (module == QDeclarativeQtQuick1Module::Qt47) {
+#ifdef QT_NO_MOVIE
+ qmlRegisterTypeNotAvailable("Qt",4,7,"AnimatedImage",
+ qApp->translate("QDeclarative1AnimatedImage","Qt was built without support for QMovie"));
+#else
+ qmlRegisterType<QDeclarative1AnimatedImage>("Qt",4,7,"AnimatedImage");
+#endif
+ qmlRegisterType<QDeclarative1BorderImage>("Qt",4,7,"BorderImage");
+ qmlRegisterType<QDeclarative1Column>("Qt",4,7,"Column");
+ qmlRegisterType<QDeclarative1Drag>("Qt",4,7,"Drag");
+ qmlRegisterType<QDeclarative1Flickable>("Qt",4,7,"Flickable");
+ qmlRegisterType<QDeclarative1Flipable>("Qt",4,7,"Flipable");
+ qmlRegisterType<QDeclarative1Flow>("Qt",4,7,"Flow");
+ qmlRegisterType<QDeclarative1FocusPanel>("Qt",4,7,"FocusPanel");
+ qmlRegisterType<QDeclarative1FocusScope>("Qt",4,7,"FocusScope");
+ qmlRegisterType<QDeclarative1Gradient>("Qt",4,7,"Gradient");
+ qmlRegisterType<QDeclarative1GradientStop>("Qt",4,7,"GradientStop");
+ qmlRegisterType<QDeclarative1Grid>("Qt",4,7,"Grid");
+ qmlRegisterType<QDeclarative1GridView>("Qt",4,7,"GridView");
+ qmlRegisterType<QDeclarative1Image>("Qt",4,7,"Image");
+ qmlRegisterType<QDeclarativeItem>("Qt",4,7,"Item");
+ qmlRegisterType<QDeclarative1LayoutItem>("Qt",4,7,"LayoutItem");
+ qmlRegisterType<QDeclarative1ListView>("Qt",4,7,"ListView");
+ qmlRegisterType<QDeclarative1Loader>("Qt",4,7,"Loader");
+ qmlRegisterType<QDeclarative1MouseArea>("Qt",4,7,"MouseArea");
+ qmlRegisterType<QDeclarative1Path>("Qt",4,7,"Path");
+ qmlRegisterType<QDeclarative1PathAttribute>("Qt",4,7,"PathAttribute");
+ qmlRegisterType<QDeclarative1PathCubic>("Qt",4,7,"PathCubic");
+ qmlRegisterType<QDeclarative1PathLine>("Qt",4,7,"PathLine");
+ qmlRegisterType<QDeclarative1PathPercent>("Qt",4,7,"PathPercent");
+ qmlRegisterType<QDeclarative1PathQuad>("Qt",4,7,"PathQuad");
+ qmlRegisterType<QDeclarative1PathView>("Qt",4,7,"PathView");
+#ifndef QT_NO_VALIDATOR
+ qmlRegisterType<QIntValidator>("Qt",4,7,"IntValidator");
+ qmlRegisterType<QDoubleValidator>("Qt",4,7,"DoubleValidator");
+ qmlRegisterType<QRegExpValidator>("Qt",4,7,"RegExpValidator");
+#endif
+ qmlRegisterType<QDeclarative1Rectangle>("Qt",4,7,"Rectangle");
+ qmlRegisterType<QDeclarative1Repeater>("Qt",4,7,"Repeater");
+ qmlRegisterType<QGraphicsRotation>("Qt",4,7,"Rotation");
+ qmlRegisterType<QDeclarative1Row>("Qt",4,7,"Row");
+ qmlRegisterType<QDeclarative1Translate>("Qt",4,7,"Translate");
+ qmlRegisterType<QGraphicsScale>("Qt",4,7,"Scale");
+ qmlRegisterType<QDeclarative1Text>("Qt",4,7,"Text");
+ qmlRegisterType<QDeclarative1TextEdit>("Qt",4,7,"TextEdit");
+#ifndef QT_NO_LINEEDIT
+ qmlRegisterType<QDeclarative1TextInput>("Qt",4,7,"TextInput");
+#endif
+ qmlRegisterType<QDeclarative1ViewSection>("Qt",4,7,"ViewSection");
+ qmlRegisterType<QDeclarative1VisualDataModel>("Qt",4,7,"VisualDataModel");
+ qmlRegisterType<QDeclarative1VisualItemModel>("Qt",4,7,"VisualItemModel");
+
+ qmlRegisterType<QGraphicsWidget>("Qt",4,7,"QGraphicsWidget");
+ qmlRegisterExtendedType<QGraphicsWidget,QDeclarative1GraphicsWidget>("Qt",4,7,"QGraphicsWidget");
+
+ qmlRegisterUncreatableType<QDeclarative1KeyNavigationAttached>("Qt",4,7,"KeyNavigation",QDeclarative1KeyNavigationAttached::tr("KeyNavigation is only available via attached properties"));
+ qmlRegisterUncreatableType<QDeclarative1KeysAttached>("Qt",4,7,"Keys",QDeclarative1KeysAttached::tr("Keys is only available via attached properties"));
+ }
+}
+
+
+
diff --git a/src/qtquick1/graphicsitems/qdeclarativeitemsmodule_p.h b/src/qtquick1/graphicsitems/qdeclarativeitemsmodule_p.h
new file mode 100644
index 0000000000..39d55f3b5e
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativeitemsmodule_p.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEITEMMODULE_H
+#define QDECLARATIVEITEMMODULE_H
+
+#include <QtDeclarative/qdeclarative.h>
+#include "../qtquick1_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarative1ItemModule
+{
+public:
+ static void defineModule(QDeclarativeQtQuick1Module::Module module);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEITEMMODULE_H
diff --git a/src/qtquick1/graphicsitems/qdeclarativelayoutitem.cpp b/src/qtquick1/graphicsitems/qdeclarativelayoutitem.cpp
new file mode 100644
index 0000000000..eea3830fca
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativelayoutitem.cpp
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qdeclarativelayoutitem_p.h"
+
+#include <QDebug>
+
+#include <limits.h>
+
+QT_BEGIN_NAMESPACE
+
+
+
+/*!
+ \qmlclass LayoutItem QDeclarative1LayoutItem
+ \ingroup qml-utility-elements
+ \since 4.7
+ \brief The LayoutItem element allows declarative UI elements to be placed inside Qt's Graphics View layouts.
+
+ LayoutItem is a variant of \l Item with additional size hint properties. These properties provide the size hints
+ necessary for items to work in conjunction with Qt \l{Graphics View Framework}{Graphics View} layout classes
+ such as QGraphicsLinearLayout and QGraphicsGridLayout. The Qt layout mechanisms will resize the LayoutItem as appropriate,
+ taking its size hints into account, and you can propagate this to the other elements in your UI via anchors and bindings.
+
+ This is a QGraphicsLayoutItem subclass, and its properties merely expose the QGraphicsLayoutItem functionality to QML.
+
+ The \l{declarative/cppextensions/qgraphicslayouts/layoutitem}{LayoutItem example}
+ demonstrates how a LayoutItem can be used within a \l{Graphics View Framework}{Graphics View}
+ scene.
+*/
+
+/*!
+ \qmlproperty QSizeF LayoutItem::maximumSize
+
+ The maximumSize property can be set to specify the maximum desired size of this LayoutItem
+*/
+
+/*!
+ \qmlproperty QSizeF LayoutItem::minimumSize
+
+ The minimumSize property can be set to specify the minimum desired size of this LayoutItem
+*/
+
+/*!
+ \qmlproperty QSizeF LayoutItem::preferredSize
+
+ The preferredSize property can be set to specify the preferred size of this LayoutItem
+*/
+
+QDeclarative1LayoutItem::QDeclarative1LayoutItem(QDeclarativeItem* parent)
+ : QDeclarativeItem(parent), m_maximumSize(INT_MAX,INT_MAX), m_minimumSize(0,0), m_preferredSize(0,0)
+{
+ setGraphicsItem(this);
+}
+
+void QDeclarative1LayoutItem::setGeometry(const QRectF & rect)
+{
+ setX(rect.x());
+ setY(rect.y());
+ setWidth(rect.width());
+ setHeight(rect.height());
+}
+
+QSizeF QDeclarative1LayoutItem::sizeHint(Qt::SizeHint w, const QSizeF &constraint) const
+{
+ Q_UNUSED(constraint);
+ if(w == Qt::MinimumSize){
+ return m_minimumSize;
+ }else if(w == Qt::MaximumSize){
+ return m_maximumSize;
+ }else{
+ return m_preferredSize;
+ }
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/graphicsitems/qdeclarativelayoutitem_p.h b/src/qtquick1/graphicsitems/qdeclarativelayoutitem_p.h
new file mode 100644
index 0000000000..9db5f19d44
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativelayoutitem_p.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEGRAPHICSLAYOUTITEM_H
+#define QDECLARATIVEGRAPHICSLAYOUTITEM_H
+#include "qdeclarativeitem.h"
+
+#include <QGraphicsLayoutItem>
+#include <QSizeF>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarative1LayoutItem : public QDeclarativeItem, public QGraphicsLayoutItem
+{
+ Q_OBJECT
+ Q_INTERFACES(QGraphicsLayoutItem)
+ Q_PROPERTY(QSizeF maximumSize READ maximumSize WRITE setMaximumSize NOTIFY maximumSizeChanged)
+ Q_PROPERTY(QSizeF minimumSize READ minimumSize WRITE setMinimumSize NOTIFY minimumSizeChanged)
+ Q_PROPERTY(QSizeF preferredSize READ preferredSize WRITE setPreferredSize NOTIFY preferredSizeChanged)
+public:
+ QDeclarative1LayoutItem(QDeclarativeItem* parent=0);
+
+ QSizeF maximumSize() const { return m_maximumSize; }
+ void setMaximumSize(const QSizeF &s) { if(s==m_maximumSize) return; m_maximumSize = s; emit maximumSizeChanged(); }
+
+ QSizeF minimumSize() const { return m_minimumSize; }
+ void setMinimumSize(const QSizeF &s) { if(s==m_minimumSize) return; m_minimumSize = s; emit minimumSizeChanged(); }
+
+ QSizeF preferredSize() const { return m_preferredSize; }
+ void setPreferredSize(const QSizeF &s) { if(s==m_preferredSize) return; m_preferredSize = s; emit preferredSizeChanged(); }
+
+ virtual void setGeometry(const QRectF & rect);
+protected:
+ virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const;
+
+Q_SIGNALS:
+ void maximumSizeChanged();
+ void minimumSizeChanged();
+ void preferredSizeChanged();
+
+private:
+ QSizeF m_maximumSize;
+ QSizeF m_minimumSize;
+ QSizeF m_preferredSize;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1LayoutItem)
+
+QT_END_HEADER
+#endif
diff --git a/src/qtquick1/graphicsitems/qdeclarativelistview.cpp b/src/qtquick1/graphicsitems/qdeclarativelistview.cpp
new file mode 100644
index 0000000000..42f1e1919b
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativelistview.cpp
@@ -0,0 +1,3617 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativelistview_p.h"
+
+#include "QtQuick1/private/qdeclarativeflickable_p_p.h"
+#include "QtQuick1/private/qdeclarativevisualitemmodel_p.h"
+
+#include "QtQuick1/private/qdeclarativesmoothedanimation_p_p.h"
+#include <QtDeclarative/qdeclarativeexpression.h>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/private/qdeclarativeguard_p.h>
+#include <QtDeclarative/qdeclarativeinfo.h>
+
+#include <qmath.h>
+#include <QKeyEvent>
+
+QT_BEGIN_NAMESPACE
+
+
+
+void QDeclarative1ViewSection::setProperty(const QString &property)
+{
+ if (property != m_property) {
+ m_property = property;
+ emit propertyChanged();
+ }
+}
+
+void QDeclarative1ViewSection::setCriteria(QDeclarative1ViewSection::SectionCriteria criteria)
+{
+ if (criteria != m_criteria) {
+ m_criteria = criteria;
+ emit criteriaChanged();
+ }
+}
+
+void QDeclarative1ViewSection::setDelegate(QDeclarativeComponent *delegate)
+{
+ if (delegate != m_delegate) {
+ m_delegate = delegate;
+ emit delegateChanged();
+ }
+}
+
+QString QDeclarative1ViewSection::sectionString(const QString &value)
+{
+ if (m_criteria == FirstCharacter)
+ return value.isEmpty() ? QString() : value.at(0);
+ else
+ return value;
+}
+
+//----------------------------------------------------------------------------
+
+class FxListItem1
+{
+public:
+ FxListItem1(QDeclarativeItem *i, QDeclarative1ListView *v) : item(i), section(0), view(v) {
+ attached = static_cast<QDeclarative1ListViewAttached*>(qmlAttachedPropertiesObject<QDeclarative1ListView>(item));
+ if (attached)
+ attached->setView(view);
+ }
+ ~FxListItem1() {}
+ qreal position() const {
+ if (section) {
+ if (view->orientation() == QDeclarative1ListView::Vertical)
+ return section->y();
+ else
+ return (view->effectiveLayoutDirection() == Qt::RightToLeft ? -section->width()-section->x() : section->x());
+ } else {
+ return itemPosition();
+ }
+ }
+
+ qreal itemPosition() const {
+ if (view->orientation() == QDeclarative1ListView::Vertical)
+ return item->y();
+ else
+ return (view->effectiveLayoutDirection() == Qt::RightToLeft ? -item->width()-item->x() : item->x());
+ }
+ qreal size() const {
+ if (section)
+ return (view->orientation() == QDeclarative1ListView::Vertical ? item->height()+section->height() : item->width()+section->width());
+ else
+ return (view->orientation() == QDeclarative1ListView::Vertical ? item->height() : item->width());
+ }
+ qreal itemSize() const {
+ return (view->orientation() == QDeclarative1ListView::Vertical ? item->height() : item->width());
+ }
+ qreal sectionSize() const {
+ if (section)
+ return (view->orientation() == QDeclarative1ListView::Vertical ? section->height() : section->width());
+ return 0.0;
+ }
+ qreal endPosition() const {
+ if (view->orientation() == QDeclarative1ListView::Vertical) {
+ return item->y() + (item->height() >= 1.0 ? item->height() : 1) - 1;
+ } else {
+ return (view->effectiveLayoutDirection() == Qt::RightToLeft
+ ? -item->width()-item->x() + (item->width() >= 1.0 ? item->width() : 1)
+ : item->x() + (item->width() >= 1.0 ? item->width() : 1)) - 1;
+ }
+ }
+ void setPosition(qreal pos) {
+ if (view->orientation() == QDeclarative1ListView::Vertical) {
+ if (section) {
+ section->setY(pos);
+ pos += section->height();
+ }
+ item->setY(pos);
+ } else {
+ if (view->effectiveLayoutDirection() == Qt::RightToLeft) {
+ if (section) {
+ section->setX(-section->width()-pos);
+ pos += section->width();
+ }
+ item->setX(-item->width()-pos);
+ } else {
+ if (section) {
+ section->setX(pos);
+ pos += section->width();
+ }
+ item->setX(pos);
+ }
+ }
+ }
+ void setSize(qreal size) {
+ if (view->orientation() == QDeclarative1ListView::Vertical)
+ item->setHeight(size);
+ else
+ item->setWidth(size);
+ }
+ bool contains(qreal x, qreal y) const {
+ return (x >= item->x() && x < item->x() + item->width() &&
+ y >= item->y() && y < item->y() + item->height());
+ }
+
+ QDeclarativeItem *item;
+ QDeclarativeItem *section;
+ QDeclarative1ListView *view;
+ QDeclarative1ListViewAttached *attached;
+ int index;
+};
+
+//----------------------------------------------------------------------------
+
+class QDeclarative1ListViewPrivate : public QDeclarative1FlickablePrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1ListView)
+
+public:
+ QDeclarative1ListViewPrivate()
+ : currentItem(0), orient(QDeclarative1ListView::Vertical), layoutDirection(Qt::LeftToRight)
+ , visiblePos(0), visibleIndex(0)
+ , averageSize(100.0), currentIndex(-1), requestedIndex(-1)
+ , itemCount(0), highlightRangeStart(0), highlightRangeEnd(0)
+ , highlightRangeStartValid(false), highlightRangeEndValid(false)
+ , highlightComponent(0), highlight(0), trackedItem(0)
+ , moveReason(Other), buffer(0), highlightPosAnimator(0), highlightSizeAnimator(0)
+ , sectionCriteria(0), spacing(0.0)
+ , highlightMoveSpeed(400), highlightMoveDuration(-1)
+ , highlightResizeSpeed(400), highlightResizeDuration(-1), highlightRange(QDeclarative1ListView::NoHighlightRange)
+ , snapMode(QDeclarative1ListView::NoSnap), overshootDist(0.0)
+ , footerComponent(0), footer(0), headerComponent(0), header(0)
+ , bufferMode(BufferBefore | BufferAfter)
+ , ownModel(false), wrap(false), autoHighlight(true), haveHighlightRange(false)
+ , correctFlick(false), inFlickCorrection(false), lazyRelease(false)
+ , deferredRelease(false), layoutScheduled(false), currentIndexCleared(false)
+ , inViewportMoved(false)
+ , minExtentDirty(true), maxExtentDirty(true)
+ {}
+
+ void init();
+ void clear();
+ FxListItem1 *createItem(int modelIndex);
+ void releaseItem(FxListItem1 *item);
+
+ FxListItem1 *visibleItem(int modelIndex) const {
+ if (modelIndex >= visibleIndex && modelIndex < visibleIndex + visibleItems.count()) {
+ for (int i = modelIndex - visibleIndex; i < visibleItems.count(); ++i) {
+ FxListItem1 *item = visibleItems.at(i);
+ if (item->index == modelIndex)
+ return item;
+ }
+ }
+ return 0;
+ }
+
+ FxListItem1 *firstVisibleItem() const {
+ const qreal pos = isRightToLeft() ? -position()-size() : position();
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxListItem1 *item = visibleItems.at(i);
+ if (item->index != -1 && item->endPosition() > pos)
+ return item;
+ }
+ return visibleItems.count() ? visibleItems.first() : 0;
+ }
+
+ FxListItem1 *nextVisibleItem() const {
+ const qreal pos = isRightToLeft() ? -position()-size() : position();
+ bool foundFirst = false;
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxListItem1 *item = visibleItems.at(i);
+ if (item->index != -1) {
+ if (foundFirst)
+ return item;
+ else if (item->position() < pos && item->endPosition() > pos)
+ foundFirst = true;
+ }
+ }
+ return 0;
+ }
+
+ // Returns the item before modelIndex, if created.
+ // May return an item marked for removal.
+ FxListItem1 *itemBefore(int modelIndex) const {
+ if (modelIndex < visibleIndex)
+ return 0;
+ int idx = 1;
+ int lastIndex = -1;
+ while (idx < visibleItems.count()) {
+ FxListItem1 *item = visibleItems.at(idx);
+ if (item->index != -1)
+ lastIndex = item->index;
+ if (item->index == modelIndex)
+ return visibleItems.at(idx-1);
+ ++idx;
+ }
+ if (lastIndex == modelIndex-1)
+ return visibleItems.last();
+ return 0;
+ }
+
+ void regenerate() {
+ Q_Q(QDeclarative1ListView);
+ if (q->isComponentComplete()) {
+ if (header) {
+ if (q->scene())
+ q->scene()->removeItem(header->item);
+ header->item->deleteLater();
+ delete header;
+ header = 0;
+ }
+ if (footer) {
+ if (q->scene())
+ q->scene()->removeItem(footer->item);
+ footer->item->deleteLater();
+ delete footer;
+ footer = 0;
+ }
+ updateHeader();
+ updateFooter();
+ clear();
+ setPosition(0);
+ q->refill();
+ updateCurrent(currentIndex);
+ }
+ }
+
+ void mirrorChange() {
+ Q_Q(QDeclarative1ListView);
+ regenerate();
+ emit q->effectiveLayoutDirectionChanged();
+ }
+
+ bool isRightToLeft() const {
+ Q_Q(const QDeclarative1ListView);
+ return orient == QDeclarative1ListView::Horizontal && q->effectiveLayoutDirection() == Qt::RightToLeft;
+ }
+
+ qreal position() const {
+ Q_Q(const QDeclarative1ListView);
+ return orient == QDeclarative1ListView::Vertical ? q->contentY() : q->contentX();
+ }
+
+ void setPosition(qreal pos) {
+ Q_Q(QDeclarative1ListView);
+ if (orient == QDeclarative1ListView::Vertical) {
+ q->QDeclarative1Flickable::setContentY(pos);
+ } else {
+ if (isRightToLeft())
+ q->QDeclarative1Flickable::setContentX(-pos-size());
+ else
+ q->QDeclarative1Flickable::setContentX(pos);
+ }
+ }
+ qreal size() const {
+ Q_Q(const QDeclarative1ListView);
+ return orient == QDeclarative1ListView::Vertical ? q->height() : q->width();
+ }
+
+ qreal originPosition() const {
+ qreal pos = 0;
+ if (!visibleItems.isEmpty()) {
+ pos = (*visibleItems.constBegin())->position();
+ if (visibleIndex > 0)
+ pos -= visibleIndex * (averageSize + spacing);
+ }
+ return pos;
+ }
+
+ qreal lastPosition() const {
+ qreal pos = 0;
+ if (!visibleItems.isEmpty()) {
+ int invisibleCount = visibleItems.count() - visibleIndex;
+ for (int i = visibleItems.count()-1; i >= 0; --i) {
+ if (visibleItems.at(i)->index != -1) {
+ invisibleCount = model->count() - visibleItems.at(i)->index - 1;
+ break;
+ }
+ }
+ pos = (*(--visibleItems.constEnd()))->endPosition() + invisibleCount * (averageSize + spacing);
+ } else if (model && model->count()) {
+ pos = model->count() * averageSize + (model->count()-1) * spacing;
+ }
+ return pos;
+ }
+
+ qreal startPosition() const {
+ return isRightToLeft() ? -lastPosition()-1 : originPosition();
+ }
+
+ qreal endPosition() const {
+ return isRightToLeft() ? -originPosition()-1 : lastPosition();
+ }
+
+ qreal positionAt(int modelIndex) const {
+ if (FxListItem1 *item = visibleItem(modelIndex))
+ return item->position();
+ if (!visibleItems.isEmpty()) {
+ if (modelIndex < visibleIndex) {
+ int count = visibleIndex - modelIndex;
+ qreal cs = 0;
+ if (modelIndex == currentIndex && currentItem) {
+ cs = currentItem->size() + spacing;
+ --count;
+ }
+ return (*visibleItems.constBegin())->position() - count * (averageSize + spacing) - cs;
+ } else {
+ int idx = visibleItems.count() - 1;
+ while (idx >= 0 && visibleItems.at(idx)->index == -1)
+ --idx;
+ if (idx < 0)
+ idx = visibleIndex;
+ else
+ idx = visibleItems.at(idx)->index;
+ int count = modelIndex - idx - 1;
+
+ return (*(--visibleItems.constEnd()))->endPosition() + spacing + count * (averageSize + spacing) + 1;
+ }
+ }
+ return 0;
+ }
+
+ qreal endPositionAt(int modelIndex) const {
+ if (FxListItem1 *item = visibleItem(modelIndex))
+ return item->endPosition();
+ if (!visibleItems.isEmpty()) {
+ if (modelIndex < visibleIndex) {
+ int count = visibleIndex - modelIndex;
+ return (*visibleItems.constBegin())->position() - (count - 1) * (averageSize + spacing) - spacing - 1;
+ } else {
+ int idx = visibleItems.count() - 1;
+ while (idx >= 0 && visibleItems.at(idx)->index == -1)
+ --idx;
+ if (idx < 0)
+ idx = visibleIndex;
+ else
+ idx = visibleItems.at(idx)->index;
+ int count = modelIndex - idx - 1;
+ return (*(--visibleItems.constEnd()))->endPosition() + count * (averageSize + spacing);
+ }
+ }
+ return 0;
+ }
+
+ QString sectionAt(int modelIndex) {
+ if (FxListItem1 *item = visibleItem(modelIndex))
+ return item->attached->section();
+
+ QString section;
+ if (sectionCriteria) {
+ QString propValue = model->stringValue(modelIndex, sectionCriteria->property());
+ section = sectionCriteria->sectionString(propValue);
+ }
+
+ return section;
+ }
+
+ bool isValid() const {
+ return model && model->count() && model->isValid();
+ }
+
+ qreal snapPosAt(qreal pos) {
+ if (FxListItem1 *snapItem = snapItemAt(pos))
+ return snapItem->position();
+ if (visibleItems.count()) {
+ qreal firstPos = visibleItems.first()->position();
+ qreal endPos = visibleItems.last()->position();
+ if (pos < firstPos) {
+ return firstPos - qRound((firstPos - pos) / averageSize) * averageSize;
+ } else if (pos > endPos)
+ return endPos + qRound((pos - endPos) / averageSize) * averageSize;
+ }
+ return qRound((pos - originPosition()) / averageSize) * averageSize + originPosition();
+ }
+
+ FxListItem1 *snapItemAt(qreal pos) {
+ FxListItem1 *snapItem = 0;
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxListItem1 *item = visibleItems[i];
+ if (item->index == -1)
+ continue;
+ qreal itemTop = item->position();
+ if (highlight && itemTop >= pos && item->endPosition() <= pos + highlight->size() - 1)
+ return item;
+ if (itemTop+item->size()/2 >= pos && itemTop-item->size()/2 < pos)
+ snapItem = item;
+ }
+ return snapItem;
+ }
+
+ int lastVisibleIndex() const {
+ int lastIndex = -1;
+ for (int i = visibleItems.count()-1; i >= 0; --i) {
+ FxListItem1 *listItem = visibleItems.at(i);
+ if (listItem->index != -1) {
+ lastIndex = listItem->index;
+ break;
+ }
+ }
+ return lastIndex;
+ }
+
+ // map a model index to visibleItems index.
+ int mapFromModel(int modelIndex) const {
+ if (modelIndex < visibleIndex || modelIndex >= visibleIndex + visibleItems.count())
+ return -1;
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxListItem1 *listItem = visibleItems.at(i);
+ if (listItem->index == modelIndex)
+ return i;
+ if (listItem->index > modelIndex)
+ return -1;
+ }
+ return -1; // Not in visibleList
+ }
+
+ void updateViewport() {
+ Q_Q(QDeclarative1ListView);
+ if (orient == QDeclarative1ListView::Vertical) {
+ q->setContentHeight(endPosition() - startPosition() + 1);
+ } else {
+ q->setContentWidth(endPosition() - startPosition() + 1);
+ }
+ }
+
+ void itemGeometryChanged(QDeclarativeItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) {
+ Q_Q(QDeclarative1ListView);
+ QDeclarative1FlickablePrivate::itemGeometryChanged(item, newGeometry, oldGeometry);
+ if (!q->isComponentComplete())
+ return;
+ if (item != contentItem && (!highlight || item != highlight->item)) {
+ if ((orient == QDeclarative1ListView::Vertical && newGeometry.height() != oldGeometry.height())
+ || (orient == QDeclarative1ListView::Horizontal && newGeometry.width() != oldGeometry.width())) {
+ scheduleLayout();
+ }
+ }
+ if ((header && header->item == item) || (footer && footer->item == item)) {
+ if (header)
+ updateHeader();
+ if (footer)
+ updateFooter();
+ }
+ if (currentItem && currentItem->item == item)
+ updateHighlight();
+ if (trackedItem && trackedItem->item == item)
+ q->trackedPositionChanged();
+ }
+
+ // for debugging only
+ void checkVisible() const {
+ int skip = 0;
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxListItem1 *listItem = visibleItems.at(i);
+ if (listItem->index == -1) {
+ ++skip;
+ } else if (listItem->index != visibleIndex + i - skip) {
+ qFatal("index %d %d %d", visibleIndex, i, listItem->index);
+ }
+ }
+ }
+
+ void refill(qreal from, qreal to, bool doBuffer = false);
+ void scheduleLayout();
+ void layout();
+ void updateUnrequestedIndexes();
+ void updateUnrequestedPositions();
+ void updateTrackedItem();
+ void createHighlight();
+ void updateHighlight();
+ void createSection(FxListItem1 *);
+ void updateSections();
+ void updateCurrentSection();
+ void updateCurrent(int);
+ void updateAverage();
+ void updateHeader();
+ void updateFooter();
+ void fixupPosition();
+ void positionViewAtIndex(int index, int mode);
+ virtual void fixup(AxisData &data, qreal minExtent, qreal maxExtent);
+ virtual void flick(QDeclarative1FlickablePrivate::AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
+ QDeclarative1TimeLineCallback::Callback fixupCallback, qreal velocity);
+
+ QDeclarativeGuard<QDeclarative1VisualModel> model;
+ QVariant modelVariant;
+ QList<FxListItem1*> visibleItems;
+ QHash<QDeclarativeItem*,int> unrequestedItems;
+ FxListItem1 *currentItem;
+ QDeclarative1ListView::Orientation orient;
+ Qt::LayoutDirection layoutDirection;
+ qreal visiblePos;
+ int visibleIndex;
+ qreal averageSize;
+ int currentIndex;
+ int requestedIndex;
+ int itemCount;
+ qreal highlightRangeStart;
+ qreal highlightRangeEnd;
+ bool highlightRangeStartValid;
+ bool highlightRangeEndValid;
+ QDeclarativeComponent *highlightComponent;
+ FxListItem1 *highlight;
+ FxListItem1 *trackedItem;
+ enum MovementReason { Other, SetIndex, Mouse };
+ MovementReason moveReason;
+ int buffer;
+ QSmoothedAnimation_1 *highlightPosAnimator;
+ QSmoothedAnimation_1 *highlightSizeAnimator;
+ QDeclarative1ViewSection *sectionCriteria;
+ QString currentSection;
+ static const int sectionCacheSize = 4;
+ QDeclarativeItem *sectionCache[sectionCacheSize];
+ qreal spacing;
+ qreal highlightMoveSpeed;
+ int highlightMoveDuration;
+ qreal highlightResizeSpeed;
+ int highlightResizeDuration;
+ QDeclarative1ListView::HighlightRangeMode highlightRange;
+ QDeclarative1ListView::SnapMode snapMode;
+ qreal overshootDist;
+ QDeclarativeComponent *footerComponent;
+ FxListItem1 *footer;
+ QDeclarativeComponent *headerComponent;
+ FxListItem1 *header;
+ enum BufferMode { NoBuffer = 0x00, BufferBefore = 0x01, BufferAfter = 0x02 };
+ int bufferMode;
+ mutable qreal minExtent;
+ mutable qreal maxExtent;
+
+ bool ownModel : 1;
+ bool wrap : 1;
+ bool autoHighlight : 1;
+ bool haveHighlightRange : 1;
+ bool correctFlick : 1;
+ bool inFlickCorrection : 1;
+ bool lazyRelease : 1;
+ bool deferredRelease : 1;
+ bool layoutScheduled : 1;
+ bool currentIndexCleared : 1;
+ bool inViewportMoved : 1;
+ mutable bool minExtentDirty : 1;
+ mutable bool maxExtentDirty : 1;
+};
+
+void QDeclarative1ListViewPrivate::init()
+{
+ Q_Q(QDeclarative1ListView);
+ q->setFlag(QGraphicsItem::ItemIsFocusScope);
+ addItemChangeListener(this, Geometry);
+ QObject::connect(q, SIGNAL(movementEnded()), q, SLOT(animStopped()));
+ q->setFlickableDirection(QDeclarative1Flickable::VerticalFlick);
+ ::memset(sectionCache, 0, sizeof(QDeclarativeItem*) * sectionCacheSize);
+}
+
+void QDeclarative1ListViewPrivate::clear()
+{
+ timeline.clear();
+ for (int i = 0; i < visibleItems.count(); ++i)
+ releaseItem(visibleItems.at(i));
+ visibleItems.clear();
+ for (int i = 0; i < sectionCacheSize; ++i) {
+ delete sectionCache[i];
+ sectionCache[i] = 0;
+ }
+ visiblePos = header ? header->size() : 0;
+ visibleIndex = 0;
+ releaseItem(currentItem);
+ currentItem = 0;
+ createHighlight();
+ trackedItem = 0;
+ minExtentDirty = true;
+ maxExtentDirty = true;
+ itemCount = 0;
+}
+
+FxListItem1 *QDeclarative1ListViewPrivate::createItem(int modelIndex)
+{
+ Q_Q(QDeclarative1ListView);
+ // create object
+ requestedIndex = modelIndex;
+ FxListItem1 *listItem = 0;
+ if (QDeclarativeItem *item = model->item(modelIndex, false)) {
+ listItem = new FxListItem1(item, q);
+ listItem->index = modelIndex;
+ // initialise attached properties
+ if (sectionCriteria) {
+ QString propValue = model->stringValue(modelIndex, sectionCriteria->property());
+ listItem->attached->m_section = sectionCriteria->sectionString(propValue);
+ if (modelIndex > 0) {
+ if (FxListItem1 *item = itemBefore(modelIndex))
+ listItem->attached->m_prevSection = item->attached->section();
+ else
+ listItem->attached->m_prevSection = sectionAt(modelIndex-1);
+ }
+ if (modelIndex < model->count()-1) {
+ if (FxListItem1 *item = visibleItem(modelIndex+1))
+ listItem->attached->m_nextSection = item->attached->section();
+ else
+ listItem->attached->m_nextSection = sectionAt(modelIndex+1);
+ }
+ }
+ if (model->completePending()) {
+ // complete
+ listItem->item->setZValue(1);
+ listItem->item->setParentItem(q->contentItem());
+ model->completeItem();
+ } else {
+ listItem->item->setParentItem(q->contentItem());
+ }
+ QDeclarativeItemPrivate *itemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(item));
+ itemPrivate->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
+ if (sectionCriteria && sectionCriteria->delegate()) {
+ if (listItem->attached->m_prevSection != listItem->attached->m_section)
+ createSection(listItem);
+ }
+ unrequestedItems.remove(listItem->item);
+ }
+ requestedIndex = -1;
+
+ return listItem;
+}
+
+void QDeclarative1ListViewPrivate::releaseItem(FxListItem1 *item)
+{
+ Q_Q(QDeclarative1ListView);
+ if (!item || !model)
+ return;
+ if (trackedItem == item)
+ trackedItem = 0;
+ QDeclarativeItemPrivate *itemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(item->item));
+ itemPrivate->removeItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
+ if (model->release(item->item) == 0) {
+ // item was not destroyed, and we no longer reference it.
+ unrequestedItems.insert(item->item, model->indexOf(item->item, q));
+ }
+ if (item->section) {
+ int i = 0;
+ do {
+ if (!sectionCache[i]) {
+ sectionCache[i] = item->section;
+ sectionCache[i]->setVisible(false);
+ item->section = 0;
+ break;
+ }
+ ++i;
+ } while (i < sectionCacheSize);
+ delete item->section;
+ }
+ delete item;
+}
+
+void QDeclarative1ListViewPrivate::refill(qreal from, qreal to, bool doBuffer)
+{
+ Q_Q(QDeclarative1ListView);
+ if (!isValid() || !q->isComponentComplete())
+ return;
+ itemCount = model->count();
+ qreal bufferFrom = from - buffer;
+ qreal bufferTo = to + buffer;
+ qreal fillFrom = from;
+ qreal fillTo = to;
+ if (doBuffer && (bufferMode & BufferAfter))
+ fillTo = bufferTo;
+ if (doBuffer && (bufferMode & BufferBefore))
+ fillFrom = bufferFrom;
+
+ bool haveValidItems = false;
+ int modelIndex = visibleIndex;
+ qreal itemEnd = visiblePos-1;
+ if (!visibleItems.isEmpty()) {
+ visiblePos = (*visibleItems.constBegin())->position();
+ itemEnd = (*(--visibleItems.constEnd()))->endPosition() + spacing;
+ int i = visibleItems.count() - 1;
+ while (i > 0 && visibleItems.at(i)->index == -1)
+ --i;
+ if (visibleItems.at(i)->index != -1) {
+ haveValidItems = true;
+ modelIndex = visibleItems.at(i)->index + 1;
+ }
+ }
+
+ if (haveValidItems && (fillFrom > itemEnd+averageSize+spacing
+ || fillTo < visiblePos - averageSize - spacing)) {
+ // We've jumped more than a page. Estimate which items are now
+ // visible and fill from there.
+ int count = (fillFrom - itemEnd) / (averageSize + spacing);
+ for (int i = 0; i < visibleItems.count(); ++i)
+ releaseItem(visibleItems.at(i));
+ visibleItems.clear();
+ modelIndex += count;
+ if (modelIndex >= model->count()) {
+ count -= modelIndex - model->count() + 1;
+ modelIndex = model->count() - 1;
+ } else if (modelIndex < 0) {
+ count -= modelIndex;
+ modelIndex = 0;
+ }
+ visibleIndex = modelIndex;
+ visiblePos = itemEnd + count * (averageSize + spacing) + 1;
+ itemEnd = visiblePos-1;
+ }
+
+ bool changed = false;
+ FxListItem1 *item = 0;
+ qreal pos = itemEnd + 1;
+ while (modelIndex < model->count() && pos <= fillTo) {
+// qDebug() << "refill: append item" << modelIndex << "pos" << pos;
+ if (!(item = createItem(modelIndex)))
+ break;
+ item->setPosition(pos);
+ pos += item->size() + spacing;
+ visibleItems.append(item);
+ ++modelIndex;
+ changed = true;
+ if (doBuffer) // never buffer more than one item per frame
+ break;
+ }
+ while (visibleIndex > 0 && visibleIndex <= model->count() && visiblePos-1 >= fillFrom) {
+// qDebug() << "refill: prepend item" << visibleIndex-1 << "current top pos" << visiblePos;
+ if (!(item = createItem(visibleIndex-1)))
+ break;
+ --visibleIndex;
+ visiblePos -= item->size() + spacing;
+ item->setPosition(visiblePos);
+ visibleItems.prepend(item);
+ changed = true;
+ if (doBuffer) // never buffer more than one item per frame
+ break;
+ }
+
+ if (!lazyRelease || !changed || deferredRelease) { // avoid destroying items in the same frame that we create
+ while (visibleItems.count() > 1 && (item = visibleItems.first()) && item->endPosition() < bufferFrom) {
+ if (item->attached->delayRemove())
+ break;
+// qDebug() << "refill: remove first" << visibleIndex << "top end pos" << item->endPosition();
+ if (item->index != -1)
+ visibleIndex++;
+ visibleItems.removeFirst();
+ releaseItem(item);
+ changed = true;
+ }
+ while (visibleItems.count() > 1 && (item = visibleItems.last()) && item->position() > bufferTo) {
+ if (item->attached->delayRemove())
+ break;
+// qDebug() << "refill: remove last" << visibleIndex+visibleItems.count()-1 << item->position();
+ visibleItems.removeLast();
+ releaseItem(item);
+ changed = true;
+ }
+ deferredRelease = false;
+ } else {
+ deferredRelease = true;
+ }
+ if (changed) {
+ minExtentDirty = true;
+ maxExtentDirty = true;
+ if (visibleItems.count())
+ visiblePos = (*visibleItems.constBegin())->position();
+ updateAverage();
+ if (currentIndex >= 0 && currentItem && !visibleItem(currentIndex)) {
+ currentItem->setPosition(positionAt(currentIndex));
+ updateHighlight();
+ }
+
+ if (sectionCriteria)
+ updateCurrentSection();
+ if (header)
+ updateHeader();
+ if (footer)
+ updateFooter();
+ updateViewport();
+ updateUnrequestedPositions();
+ } else if (!doBuffer && buffer && bufferMode != NoBuffer) {
+ refill(from, to, true);
+ }
+ lazyRelease = false;
+}
+
+void QDeclarative1ListViewPrivate::scheduleLayout()
+{
+ Q_Q(QDeclarative1ListView);
+ if (!layoutScheduled) {
+ layoutScheduled = true;
+ QCoreApplication::postEvent(q, new QEvent(QEvent::User), Qt::HighEventPriority);
+ }
+}
+
+void QDeclarative1ListViewPrivate::layout()
+{
+ Q_Q(QDeclarative1ListView);
+ layoutScheduled = false;
+ if (!isValid() && !visibleItems.count()) {
+ clear();
+ setPosition(0);
+ return;
+ }
+ if (!visibleItems.isEmpty()) {
+ bool fixedCurrent = currentItem && visibleItems.first()->item == currentItem->item;
+ qreal sum = visibleItems.first()->size();
+ qreal pos = visibleItems.first()->position() + visibleItems.first()->size() + spacing;
+ for (int i=1; i < visibleItems.count(); ++i) {
+ FxListItem1 *item = visibleItems.at(i);
+ item->setPosition(pos);
+ pos += item->size() + spacing;
+ sum += item->size();
+ fixedCurrent = fixedCurrent || (currentItem && item->item == currentItem->item);
+ }
+ averageSize = qRound(sum / visibleItems.count());
+ // move current item if it is not a visible item.
+ if (currentIndex >= 0 && currentItem && !fixedCurrent)
+ currentItem->setPosition(positionAt(currentIndex));
+ }
+ q->refill();
+ minExtentDirty = true;
+ maxExtentDirty = true;
+ updateHighlight();
+ if (!q->isMoving() && !q->isFlicking()) {
+ fixupPosition();
+ q->refill();
+ }
+ if (header)
+ updateHeader();
+ if (footer)
+ updateFooter();
+ updateViewport();
+}
+
+void QDeclarative1ListViewPrivate::updateUnrequestedIndexes()
+{
+ Q_Q(QDeclarative1ListView);
+ QHash<QDeclarativeItem*,int>::iterator it;
+ for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it)
+ *it = model->indexOf(it.key(), q);
+}
+
+void QDeclarative1ListViewPrivate::updateUnrequestedPositions()
+{
+ Q_Q(QDeclarative1ListView);
+ if (unrequestedItems.count()) {
+ qreal pos = position();
+ QHash<QDeclarativeItem*,int>::const_iterator it;
+ for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it) {
+ QDeclarativeItem *item = it.key();
+ if (orient == QDeclarative1ListView::Vertical) {
+ if (item->y() + item->height() > pos && item->y() < pos + q->height())
+ item->setY(positionAt(*it));
+ } else {
+ if (item->x() + item->width() > pos && item->x() < pos + q->width()) {
+ if (isRightToLeft())
+ item->setX(-positionAt(*it)-item->width());
+ else
+ item->setX(positionAt(*it));
+ }
+ }
+ }
+ }
+}
+
+void QDeclarative1ListViewPrivate::updateTrackedItem()
+{
+ Q_Q(QDeclarative1ListView);
+ FxListItem1 *item = currentItem;
+ if (highlight)
+ item = highlight;
+ trackedItem = item;
+ if (trackedItem)
+ q->trackedPositionChanged();
+}
+
+void QDeclarative1ListViewPrivate::createHighlight()
+{
+ Q_Q(QDeclarative1ListView);
+ bool changed = false;
+ if (highlight) {
+ if (trackedItem == highlight)
+ trackedItem = 0;
+ if (highlight->item->scene())
+ highlight->item->scene()->removeItem(highlight->item);
+ highlight->item->deleteLater();
+ delete highlight;
+ highlight = 0;
+ delete highlightPosAnimator;
+ delete highlightSizeAnimator;
+ highlightPosAnimator = 0;
+ highlightSizeAnimator = 0;
+ changed = true;
+ }
+
+ if (currentItem) {
+ QDeclarativeItem *item = 0;
+ if (highlightComponent) {
+ QDeclarativeContext *highlightContext = new QDeclarativeContext(qmlContext(q));
+ QObject *nobj = highlightComponent->create(highlightContext);
+ if (nobj) {
+ QDeclarative_setParent_noEvent(highlightContext, nobj);
+ item = qobject_cast<QDeclarativeItem *>(nobj);
+ if (!item)
+ delete nobj;
+ } else {
+ delete highlightContext;
+ }
+ } else {
+ item = new QDeclarativeItem;
+ }
+ if (item) {
+ QDeclarative_setParent_noEvent(item, q->contentItem());
+ item->setParentItem(q->contentItem());
+ highlight = new FxListItem1(item, q);
+ if (currentItem && autoHighlight) {
+ if (orient == QDeclarative1ListView::Vertical) {
+ highlight->item->setHeight(currentItem->item->height());
+ } else {
+ highlight->item->setWidth(currentItem->item->width());
+ }
+ highlight->setPosition(currentItem->itemPosition());
+ }
+ QDeclarativeItemPrivate *itemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(item));
+ itemPrivate->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
+ const QLatin1String posProp(orient == QDeclarative1ListView::Vertical ? "y" : "x");
+ highlightPosAnimator = new QSmoothedAnimation_1(q);
+ highlightPosAnimator->target = QDeclarativeProperty(highlight->item, posProp);
+ highlightPosAnimator->velocity = highlightMoveSpeed;
+ highlightPosAnimator->userDuration = highlightMoveDuration;
+ const QLatin1String sizeProp(orient == QDeclarative1ListView::Vertical ? "height" : "width");
+ highlightSizeAnimator = new QSmoothedAnimation_1(q);
+ highlightSizeAnimator->velocity = highlightResizeSpeed;
+ highlightSizeAnimator->userDuration = highlightResizeDuration;
+ highlightSizeAnimator->target = QDeclarativeProperty(highlight->item, sizeProp);
+ if (autoHighlight) {
+ highlightPosAnimator->restart();
+ highlightSizeAnimator->restart();
+ }
+ changed = true;
+ }
+ }
+ if (changed)
+ emit q->highlightItemChanged();
+}
+
+void QDeclarative1ListViewPrivate::updateHighlight()
+{
+ if ((!currentItem && highlight) || (currentItem && !highlight))
+ createHighlight();
+ if (currentItem && autoHighlight && highlight && !movingHorizontally && !movingVertically) {
+ // auto-update highlight
+ highlightPosAnimator->to = isRightToLeft()
+ ? -currentItem->itemPosition()-currentItem->itemSize()
+ : currentItem->itemPosition();
+ highlightSizeAnimator->to = currentItem->itemSize();
+ if (orient == QDeclarative1ListView::Vertical) {
+ if (highlight->item->width() == 0)
+ highlight->item->setWidth(currentItem->item->width());
+ } else {
+ if (highlight->item->height() == 0)
+ highlight->item->setHeight(currentItem->item->height());
+ }
+ highlightPosAnimator->restart();
+ highlightSizeAnimator->restart();
+ }
+ updateTrackedItem();
+}
+
+void QDeclarative1ListViewPrivate::createSection(FxListItem1 *listItem)
+{
+ Q_Q(QDeclarative1ListView);
+ if (!sectionCriteria || !sectionCriteria->delegate())
+ return;
+ if (listItem->attached->m_prevSection != listItem->attached->m_section) {
+ if (!listItem->section) {
+ qreal pos = listItem->position();
+ int i = sectionCacheSize-1;
+ while (i >= 0 && !sectionCache[i])
+ --i;
+ if (i >= 0) {
+ listItem->section = sectionCache[i];
+ sectionCache[i] = 0;
+ listItem->section->setVisible(true);
+ QDeclarativeContext *context = QDeclarativeEngine::contextForObject(listItem->section)->parentContext();
+ context->setContextProperty(QLatin1String("section"), listItem->attached->m_section);
+ } else {
+ QDeclarativeContext *context = new QDeclarativeContext(qmlContext(q));
+ context->setContextProperty(QLatin1String("section"), listItem->attached->m_section);
+ QObject *nobj = sectionCriteria->delegate()->beginCreate(context);
+ if (nobj) {
+ QDeclarative_setParent_noEvent(context, nobj);
+ listItem->section = qobject_cast<QDeclarativeItem *>(nobj);
+ if (!listItem->section) {
+ delete nobj;
+ } else {
+ listItem->section->setZValue(1);
+ QDeclarative_setParent_noEvent(listItem->section, q->contentItem());
+ listItem->section->setParentItem(q->contentItem());
+ }
+ } else {
+ delete context;
+ }
+ sectionCriteria->delegate()->completeCreate();
+ }
+ listItem->setPosition(pos);
+ } else {
+ QDeclarativeContext *context = QDeclarativeEngine::contextForObject(listItem->section)->parentContext();
+ context->setContextProperty(QLatin1String("section"), listItem->attached->m_section);
+ }
+ } else if (listItem->section) {
+ qreal pos = listItem->position();
+ int i = 0;
+ do {
+ if (!sectionCache[i]) {
+ sectionCache[i] = listItem->section;
+ sectionCache[i]->setVisible(false);
+ listItem->section = 0;
+ return;
+ }
+ ++i;
+ } while (i < sectionCacheSize);
+ delete listItem->section;
+ listItem->section = 0;
+ listItem->setPosition(pos);
+ }
+}
+
+void QDeclarative1ListViewPrivate::updateSections()
+{
+ if (sectionCriteria && !visibleItems.isEmpty()) {
+ QString prevSection;
+ if (visibleIndex > 0)
+ prevSection = sectionAt(visibleIndex-1);
+ QDeclarative1ListViewAttached *prevAtt = 0;
+ int idx = -1;
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ QDeclarative1ListViewAttached *attached = visibleItems.at(i)->attached;
+ attached->setPrevSection(prevSection);
+ if (visibleItems.at(i)->index != -1) {
+ QString propValue = model->stringValue(visibleItems.at(i)->index, sectionCriteria->property());
+ attached->setSection(sectionCriteria->sectionString(propValue));
+ idx = visibleItems.at(i)->index;
+ }
+ createSection(visibleItems.at(i));
+ if (prevAtt)
+ prevAtt->setNextSection(attached->section());
+ prevSection = attached->section();
+ prevAtt = attached;
+ }
+ if (prevAtt) {
+ if (idx > 0 && idx < model->count()-1)
+ prevAtt->setNextSection(sectionAt(idx+1));
+ else
+ prevAtt->setNextSection(QString());
+ }
+ }
+}
+
+void QDeclarative1ListViewPrivate::updateCurrentSection()
+{
+ Q_Q(QDeclarative1ListView);
+ if (!sectionCriteria || visibleItems.isEmpty()) {
+ if (!currentSection.isEmpty()) {
+ currentSection.clear();
+ emit q->currentSectionChanged();
+ }
+ return;
+ }
+ int index = 0;
+ while (index < visibleItems.count() && visibleItems.at(index)->endPosition() < position())
+ ++index;
+
+ QString newSection = currentSection;
+ if (index < visibleItems.count())
+ newSection = visibleItems.at(index)->attached->section();
+ else
+ newSection = visibleItems.first()->attached->section();
+ if (newSection != currentSection) {
+ currentSection = newSection;
+ emit q->currentSectionChanged();
+ }
+}
+
+void QDeclarative1ListViewPrivate::updateCurrent(int modelIndex)
+{
+ Q_Q(QDeclarative1ListView);
+ if (!q->isComponentComplete() || !isValid() || modelIndex < 0 || modelIndex >= model->count()) {
+ if (currentItem) {
+ currentItem->attached->setIsCurrentItem(false);
+ releaseItem(currentItem);
+ currentItem = 0;
+ currentIndex = modelIndex;
+ emit q->currentIndexChanged();
+ updateHighlight();
+ } else if (currentIndex != modelIndex) {
+ currentIndex = modelIndex;
+ emit q->currentIndexChanged();
+ }
+ return;
+ }
+
+ if (currentItem && currentIndex == modelIndex) {
+ updateHighlight();
+ return;
+ }
+ FxListItem1 *oldCurrentItem = currentItem;
+ currentIndex = modelIndex;
+ currentItem = createItem(modelIndex);
+ if (oldCurrentItem && (!currentItem || oldCurrentItem->item != currentItem->item))
+ oldCurrentItem->attached->setIsCurrentItem(false);
+ if (currentItem) {
+ if (modelIndex == visibleIndex - 1 && visibleItems.count()) {
+ // We can calculate exact postion in this case
+ currentItem->setPosition(visibleItems.first()->position() - currentItem->size() - spacing);
+ } else {
+ // Create current item now and position as best we can.
+ // Its position will be corrected when it becomes visible.
+ currentItem->setPosition(positionAt(modelIndex));
+ }
+ currentItem->item->setFocus(true);
+ currentItem->attached->setIsCurrentItem(true);
+ // Avoid showing section delegate twice. We still need the section heading so that
+ // currentItem positioning works correctly.
+ // This is slightly sub-optimal, but section heading caching minimizes the impact.
+ if (currentItem->section)
+ currentItem->section->setVisible(false);
+ if (visibleItems.isEmpty())
+ averageSize = currentItem->size();
+ }
+ updateHighlight();
+ emit q->currentIndexChanged();
+ // Release the old current item
+ releaseItem(oldCurrentItem);
+}
+
+void QDeclarative1ListViewPrivate::updateAverage()
+{
+ if (!visibleItems.count())
+ return;
+ qreal sum = 0.0;
+ for (int i = 0; i < visibleItems.count(); ++i)
+ sum += visibleItems.at(i)->size();
+ averageSize = qRound(sum / visibleItems.count());
+}
+
+void QDeclarative1ListViewPrivate::updateFooter()
+{
+ Q_Q(QDeclarative1ListView);
+ if (!footer && footerComponent) {
+ QDeclarativeItem *item = 0;
+ QDeclarativeContext *context = new QDeclarativeContext(qmlContext(q));
+ QObject *nobj = footerComponent->create(context);
+ if (nobj) {
+ QDeclarative_setParent_noEvent(context, nobj);
+ item = qobject_cast<QDeclarativeItem *>(nobj);
+ if (!item)
+ delete nobj;
+ } else {
+ delete context;
+ }
+ if (item) {
+ QDeclarative_setParent_noEvent(item, q->contentItem());
+ item->setParentItem(q->contentItem());
+ item->setZValue(1);
+ QDeclarativeItemPrivate *itemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(item));
+ itemPrivate->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
+ footer = new FxListItem1(item, q);
+ }
+ }
+ if (footer) {
+ if (visibleItems.count()) {
+ qreal endPos = lastPosition() + 1;
+ if (lastVisibleIndex() == model->count()-1) {
+ footer->setPosition(endPos);
+ } else {
+ qreal visiblePos = position() + q->height();
+ if (endPos <= visiblePos || footer->position() < endPos)
+ footer->setPosition(endPos);
+ }
+ } else {
+ footer->setPosition(visiblePos);
+ }
+ }
+}
+
+void QDeclarative1ListViewPrivate::updateHeader()
+{
+ Q_Q(QDeclarative1ListView);
+ if (!header && headerComponent) {
+ QDeclarativeItem *item = 0;
+ QDeclarativeContext *context = new QDeclarativeContext(qmlContext(q));
+ QObject *nobj = headerComponent->create(context);
+ if (nobj) {
+ QDeclarative_setParent_noEvent(context, nobj);
+ item = qobject_cast<QDeclarativeItem *>(nobj);
+ if (!item)
+ delete nobj;
+ } else {
+ delete context;
+ }
+ if (item) {
+ QDeclarative_setParent_noEvent(item, q->contentItem());
+ item->setParentItem(q->contentItem());
+ item->setZValue(1);
+ QDeclarativeItemPrivate *itemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(item));
+ itemPrivate->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
+ header = new FxListItem1(item, q);
+ }
+ }
+ if (header) {
+ if (visibleItems.count()) {
+ qreal startPos = originPosition();
+ if (visibleIndex == 0) {
+ header->setPosition(startPos - header->size());
+ } else {
+ if (position() <= startPos || header->position() > startPos - header->size())
+ header->setPosition(startPos - header->size());
+ }
+ } else {
+ if (itemCount == 0)
+ visiblePos = header->size();
+ header->setPosition(0);
+ }
+ }
+}
+
+void QDeclarative1ListViewPrivate::fixupPosition()
+{
+ if ((haveHighlightRange && highlightRange == QDeclarative1ListView::StrictlyEnforceRange)
+ || snapMode != QDeclarative1ListView::NoSnap)
+ moveReason = Other;
+ if (orient == QDeclarative1ListView::Vertical)
+ fixupY();
+ else
+ fixupX();
+}
+
+void QDeclarative1ListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
+{
+ if ((orient == QDeclarative1ListView::Horizontal && &data == &vData)
+ || (orient == QDeclarative1ListView::Vertical && &data == &hData))
+ return;
+
+ correctFlick = false;
+ fixupMode = moveReason == Mouse ? fixupMode : Immediate;
+
+ qreal highlightStart;
+ qreal highlightEnd;
+ qreal viewPos;
+ if (isRightToLeft()) {
+ // Handle Right-To-Left exceptions
+ viewPos = -position()-size();
+ highlightStart = highlightRangeStartValid ? size() - highlightRangeEnd : highlightRangeStart;
+ highlightEnd = highlightRangeEndValid ? size() - highlightRangeStart : highlightRangeEnd;
+ } else {
+ viewPos = position();
+ highlightStart = highlightRangeStart;
+ highlightEnd = highlightRangeEnd;
+ }
+
+ if (currentItem && haveHighlightRange && highlightRange == QDeclarative1ListView::StrictlyEnforceRange
+ && moveReason != QDeclarative1ListViewPrivate::SetIndex) {
+ updateHighlight();
+ qreal pos = currentItem->itemPosition();
+ if (viewPos < pos + currentItem->itemSize() - highlightEnd)
+ viewPos = pos + currentItem->itemSize() - highlightEnd;
+ if (viewPos > pos - highlightStart)
+ viewPos = pos - highlightStart;
+ if (isRightToLeft())
+ viewPos = -viewPos-size();
+
+ timeline.reset(data.move);
+ if (viewPos != position()) {
+ if (fixupMode != Immediate) {
+ timeline.move(data.move, -viewPos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2);
+ data.fixingUp = true;
+ } else {
+ timeline.set(data.move, -viewPos);
+ }
+ }
+ vTime = timeline.time();
+ } else if (snapMode != QDeclarative1ListView::NoSnap && moveReason != QDeclarative1ListViewPrivate::SetIndex) {
+ qreal tempPosition = isRightToLeft() ? -position()-size() : position();
+ FxListItem1 *topItem = snapItemAt(tempPosition+highlightStart);
+ FxListItem1 *bottomItem = snapItemAt(tempPosition+highlightEnd);
+ qreal pos;
+ bool isInBounds = -position() > maxExtent && -position() < minExtent;
+ if (topItem && isInBounds) {
+ if (topItem->index == 0 && header && tempPosition+highlightStart < header->position()+header->size()/2) {
+ pos = isRightToLeft() ? - header->position() + highlightStart - size() : header->position() - highlightStart;
+ } else {
+ if (isRightToLeft())
+ pos = qMax(qMin(-topItem->position() + highlightStart - size(), -maxExtent), -minExtent);
+ else
+ pos = qMax(qMin(topItem->position() - highlightStart, -maxExtent), -minExtent);
+ }
+ } else if (bottomItem && isInBounds) {
+ if (isRightToLeft())
+ pos = qMax(qMin(-bottomItem->position() + highlightStart - size(), -maxExtent), -minExtent);
+ else
+ pos = qMax(qMin(bottomItem->position() - highlightStart, -maxExtent), -minExtent);
+ } else {
+ QDeclarative1FlickablePrivate::fixup(data, minExtent, maxExtent);
+ return;
+ }
+
+ qreal dist = qAbs(data.move + pos);
+ if (dist > 0) {
+ timeline.reset(data.move);
+ if (fixupMode != Immediate) {
+ timeline.move(data.move, -pos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2);
+ data.fixingUp = true;
+ } else {
+ timeline.set(data.move, -pos);
+ }
+ vTime = timeline.time();
+ }
+ } else {
+ QDeclarative1FlickablePrivate::fixup(data, minExtent, maxExtent);
+ }
+ data.inOvershoot = false;
+ fixupMode = Normal;
+}
+
+void QDeclarative1ListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
+ QDeclarative1TimeLineCallback::Callback fixupCallback, qreal velocity)
+{
+ Q_Q(QDeclarative1ListView);
+
+ data.fixingUp = false;
+ moveReason = Mouse;
+ if ((!haveHighlightRange || highlightRange != QDeclarative1ListView::StrictlyEnforceRange) && snapMode == QDeclarative1ListView::NoSnap) {
+ correctFlick = true;
+ QDeclarative1FlickablePrivate::flick(data, minExtent, maxExtent, vSize, fixupCallback, velocity);
+ return;
+ }
+ qreal maxDistance = 0;
+ qreal dataValue = isRightToLeft() ? -data.move.value()+size() : data.move.value();
+ // -ve velocity means list is moving up/left
+ if (velocity > 0) {
+ if (data.move.value() < minExtent) {
+ if (snapMode == QDeclarative1ListView::SnapOneItem) {
+ if (FxListItem1 *item = isRightToLeft() ? nextVisibleItem() : firstVisibleItem())
+ maxDistance = qAbs(item->position() + dataValue);
+ } else {
+ maxDistance = qAbs(minExtent - data.move.value());
+ }
+ }
+ if (snapMode == QDeclarative1ListView::NoSnap && highlightRange != QDeclarative1ListView::StrictlyEnforceRange)
+ data.flickTarget = minExtent;
+ } else {
+ if (data.move.value() > maxExtent) {
+ if (snapMode == QDeclarative1ListView::SnapOneItem) {
+ if (FxListItem1 *item = isRightToLeft() ? firstVisibleItem() : nextVisibleItem())
+ maxDistance = qAbs(item->position() + dataValue);
+ } else {
+ maxDistance = qAbs(maxExtent - data.move.value());
+ }
+ }
+ if (snapMode == QDeclarative1ListView::NoSnap && highlightRange != QDeclarative1ListView::StrictlyEnforceRange)
+ data.flickTarget = maxExtent;
+ }
+
+ bool overShoot = boundsBehavior == QDeclarative1Flickable::DragAndOvershootBounds;
+ qreal highlightStart = isRightToLeft() && highlightRangeStartValid ? size()-highlightRangeEnd : highlightRangeStart;
+
+ if (maxDistance > 0 || overShoot) {
+ // These modes require the list to stop exactly on an item boundary.
+ // The initial flick will estimate the boundary to stop on.
+ // Since list items can have variable sizes, the boundary will be
+ // reevaluated and adjusted as we approach the boundary.
+ qreal v = velocity;
+ if (maxVelocity != -1 && maxVelocity < qAbs(v)) {
+ if (v < 0)
+ v = -maxVelocity;
+ else
+ v = maxVelocity;
+ }
+ if (!flickingHorizontally && !flickingVertically) {
+ // the initial flick - estimate boundary
+ qreal accel = deceleration;
+ qreal v2 = v * v;
+ overshootDist = 0.0;
+ // + averageSize/4 to encourage moving at least one item in the flick direction
+ qreal dist = v2 / (accel * 2.0) + averageSize/4;
+ if (maxDistance > 0)
+ dist = qMin(dist, maxDistance);
+ if (v > 0)
+ dist = -dist;
+ if ((maxDistance > 0.0 && v2 / (2.0f * maxDistance) < accel) || snapMode == QDeclarative1ListView::SnapOneItem) {
+ qreal distTemp = isRightToLeft() ? -dist : dist;
+ data.flickTarget = -snapPosAt(-(dataValue - highlightStart) + distTemp) + highlightStart;
+ data.flickTarget = isRightToLeft() ? -data.flickTarget+size() : data.flickTarget;
+ if (overShoot) {
+ if (data.flickTarget >= minExtent) {
+ overshootDist = overShootDistance(vSize);
+ data.flickTarget += overshootDist;
+ } else if (data.flickTarget <= maxExtent) {
+ overshootDist = overShootDistance(vSize);
+ data.flickTarget -= overshootDist;
+ }
+ }
+ qreal adjDist = -data.flickTarget + data.move.value();
+ if (qAbs(adjDist) > qAbs(dist)) {
+ // Prevent painfully slow flicking - adjust velocity to suit flickDeceleration
+ qreal adjv2 = accel * 2.0f * qAbs(adjDist);
+ if (adjv2 > v2) {
+ v2 = adjv2;
+ v = qSqrt(v2);
+ if (dist > 0)
+ v = -v;
+ }
+ }
+ dist = adjDist;
+ accel = v2 / (2.0f * qAbs(dist));
+ } else if (overShoot) {
+ data.flickTarget = data.move.value() - dist;
+ if (data.flickTarget >= minExtent) {
+ overshootDist = overShootDistance(vSize);
+ data.flickTarget += overshootDist;
+ } else if (data.flickTarget <= maxExtent) {
+ overshootDist = overShootDistance(vSize);
+ data.flickTarget -= overshootDist;
+ }
+ }
+
+ timeline.reset(data.move);
+ timeline.accel(data.move, v, accel, maxDistance + overshootDist);
+ timeline.callback(QDeclarative1TimeLineCallback(&data.move, fixupCallback, this));
+ if (!flickingHorizontally && q->xflick()) {
+ flickingHorizontally = true;
+ emit q->flickingChanged();
+ emit q->flickingHorizontallyChanged();
+ emit q->flickStarted();
+ }
+ if (!flickingVertically && q->yflick()) {
+ flickingVertically = true;
+ emit q->flickingChanged();
+ emit q->flickingVerticallyChanged();
+ emit q->flickStarted();
+ }
+ correctFlick = true;
+ } else {
+ // reevaluate the target boundary.
+ qreal newtarget = data.flickTarget;
+ if (snapMode != QDeclarative1ListView::NoSnap || highlightRange == QDeclarative1ListView::StrictlyEnforceRange) {
+ qreal tempFlickTarget = isRightToLeft() ? -data.flickTarget+size() : data.flickTarget;
+ newtarget = -snapPosAt(-(tempFlickTarget - highlightStart)) + highlightStart;
+ newtarget = isRightToLeft() ? -newtarget+size() : newtarget;
+ }
+ if (velocity < 0 && newtarget <= maxExtent)
+ newtarget = maxExtent - overshootDist;
+ else if (velocity > 0 && newtarget >= minExtent)
+ newtarget = minExtent + overshootDist;
+ if (newtarget == data.flickTarget) { // boundary unchanged - nothing to do
+ if (qAbs(velocity) < MinimumFlickVelocity)
+ correctFlick = false;
+ return;
+ }
+ data.flickTarget = newtarget;
+ qreal dist = -newtarget + data.move.value();
+ if ((v < 0 && dist < 0) || (v > 0 && dist > 0)) {
+ correctFlick = false;
+ timeline.reset(data.move);
+ fixup(data, minExtent, maxExtent);
+ return;
+ }
+
+ timeline.reset(data.move);
+ timeline.accelDistance(data.move, v, -dist);
+ timeline.callback(QDeclarative1TimeLineCallback(&data.move, fixupCallback, this));
+ }
+ } else {
+ correctFlick = false;
+ timeline.reset(data.move);
+ fixup(data, minExtent, maxExtent);
+ }
+}
+
+//----------------------------------------------------------------------------
+
+/*!
+ \qmlclass ListView QDeclarative1ListView
+ \ingroup qml-view-elements
+ \since 4.7
+ \inherits Flickable
+ \brief The ListView item provides a list view of items provided by a model.
+
+ A ListView displays data from models created from built-in QML elements like ListModel
+ and XmlListModel, or custom model classes defined in C++ that inherit from
+ QAbstractListModel.
+
+ A ListView has a \l model, which defines the data to be displayed, and
+ a \l delegate, which defines how the data should be displayed. Items in a
+ ListView are laid out horizontally or vertically. List views are inherently
+ flickable because ListView inherits from \l Flickable.
+
+ \section1 Example Usage
+
+ The following example shows the definition of a simple list model defined
+ in a file called \c ContactModel.qml:
+
+ \snippet doc/src/snippets/declarative/listview/ContactModel.qml 0
+
+ Another component can display this model data in a ListView, like this:
+
+ \snippet doc/src/snippets/declarative/listview/listview.qml import
+ \codeline
+ \snippet doc/src/snippets/declarative/listview/listview.qml classdocs simple
+
+ \image listview-simple.png
+
+ Here, the ListView creates a \c ContactModel component for its model, and a \l Text element
+ for its delegate. The view will create a new \l Text component for each item in the model. Notice
+ the delegate is able to access the model's \c name and \c number data directly.
+
+ An improved list view is shown below. The delegate is visually improved and is moved
+ into a separate \c contactDelegate component.
+
+ \snippet doc/src/snippets/declarative/listview/listview.qml classdocs advanced
+ \image listview-highlight.png
+
+ The currently selected item is highlighted with a blue \l Rectangle using the \l highlight property,
+ and \c focus is set to \c true to enable keyboard navigation for the list view.
+ The list view itself is a focus scope (see \l{qmlfocus#Acquiring Focus and Focus Scopes}{the focus documentation page} for more details).
+
+ Delegates are instantiated as needed and may be destroyed at any time.
+ State should \e never be stored in a delegate.
+
+ ListView attaches a number of properties to the root item of the delegate, for example
+ \c {ListView.isCurrentItem}. In the following example, the root delegate item can access
+ this attached property directly as \c ListView.isCurrentItem, while the child
+ \c contactInfo object must refer to this property as \c wrapper.ListView.isCurrentItem.
+
+ \snippet doc/src/snippets/declarative/listview/listview.qml isCurrentItem
+
+ \note Views do not enable \e clip automatically. If the view
+ is not clipped by another item or the screen, it will be necessary
+ to set \e {clip: true} in order to have the out of view items clipped
+ nicely.
+
+ \sa {QML Data Models}, GridView, {declarative/modelviews/listview}{ListView examples}
+*/
+
+QDeclarative1ListView::QDeclarative1ListView(QDeclarativeItem *parent)
+ : QDeclarative1Flickable(*(new QDeclarative1ListViewPrivate), parent)
+{
+ Q_D(QDeclarative1ListView);
+ d->init();
+}
+
+QDeclarative1ListView::~QDeclarative1ListView()
+{
+ Q_D(QDeclarative1ListView);
+ d->clear();
+ if (d->ownModel)
+ delete d->model;
+ delete d->header;
+ delete d->footer;
+}
+
+/*!
+ \qmlattachedproperty bool ListView::isCurrentItem
+ This attached property is true if this delegate is the current item; otherwise false.
+
+ It is attached to each instance of the delegate.
+
+ This property may be used to adjust the appearance of the current item, for example:
+
+ \snippet doc/src/snippets/declarative/listview/listview.qml isCurrentItem
+*/
+
+/*!
+ \qmlattachedproperty ListView ListView::view
+ This attached property holds the view that manages this delegate instance.
+
+ It is attached to each instance of the delegate.
+*/
+
+/*!
+ \qmlattachedproperty string ListView::previousSection
+ This attached property holds the section of the previous element.
+
+ It is attached to each instance of the delegate.
+
+ The section is evaluated using the \l {ListView::section.property}{section} properties.
+*/
+
+/*!
+ \qmlattachedproperty string ListView::nextSection
+ This attached property holds the section of the next element.
+
+ It is attached to each instance of the delegate.
+
+ The section is evaluated using the \l {ListView::section.property}{section} properties.
+*/
+
+/*!
+ \qmlattachedproperty string ListView::section
+ This attached property holds the section of this element.
+
+ It is attached to each instance of the delegate.
+
+ The section is evaluated using the \l {ListView::section.property}{section} properties.
+*/
+
+/*!
+ \qmlattachedproperty bool ListView::delayRemove
+ This attached property holds whether the delegate may be destroyed.
+
+ It is attached to each instance of the delegate.
+
+ It is sometimes necessary to delay the destruction of an item
+ until an animation completes.
+
+ The example delegate below ensures that the animation completes before
+ the item is removed from the list.
+
+ \snippet doc/src/snippets/declarative/listview/listview.qml delayRemove
+*/
+
+/*!
+ \qmlattachedsignal ListView::onAdd()
+ This attached handler is called immediately after an item is added to the view.
+*/
+
+/*!
+ \qmlattachedsignal ListView::onRemove()
+ This attached handler is called immediately before an item is removed from the view.
+*/
+
+/*!
+ \qmlproperty model ListView::model
+ This property holds the model providing data for the list.
+
+ The model provides the set of data that is used to create the items
+ in the view. Models can be created directly in QML using \l ListModel, \l XmlListModel
+ or \l VisualItemModel, or provided by C++ model classes. If a C++ model class is
+ used, it must be a subclass of \l QAbstractItemModel or a simple list.
+
+ \sa {qmlmodels}{Data Models}
+*/
+QVariant QDeclarative1ListView::model() const
+{
+ Q_D(const QDeclarative1ListView);
+ return d->modelVariant;
+}
+
+void QDeclarative1ListView::setModel(const QVariant &model)
+{
+ Q_D(QDeclarative1ListView);
+ if (d->modelVariant == model)
+ return;
+ if (d->model) {
+ disconnect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
+ disconnect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
+ disconnect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int)));
+ disconnect(d->model, SIGNAL(itemsChanged(int,int)), this, SLOT(itemsChanged(int,int)));
+ disconnect(d->model, SIGNAL(modelReset()), this, SLOT(modelReset()));
+ disconnect(d->model, SIGNAL(createdItem(int,QDeclarativeItem*)), this, SLOT(createdItem(int,QDeclarativeItem*)));
+ disconnect(d->model, SIGNAL(destroyingItem(QDeclarativeItem*)), this, SLOT(destroyingItem(QDeclarativeItem*)));
+ }
+ d->clear();
+ QDeclarative1VisualModel *oldModel = d->model;
+ d->model = 0;
+ d->setPosition(0);
+ d->modelVariant = model;
+ QObject *object = qvariant_cast<QObject*>(model);
+ QDeclarative1VisualModel *vim = 0;
+ if (object && (vim = qobject_cast<QDeclarative1VisualModel *>(object))) {
+ if (d->ownModel) {
+ delete oldModel;
+ d->ownModel = false;
+ }
+ d->model = vim;
+ } else {
+ if (!d->ownModel) {
+ d->model = new QDeclarative1VisualDataModel(qmlContext(this), this);
+ d->ownModel = true;
+ } else {
+ d->model = oldModel;
+ }
+ if (QDeclarative1VisualDataModel *dataModel = qobject_cast<QDeclarative1VisualDataModel*>(d->model))
+ dataModel->setModel(model);
+ }
+ if (d->model) {
+ d->bufferMode = QDeclarative1ListViewPrivate::BufferBefore | QDeclarative1ListViewPrivate::BufferAfter;
+ if (isComponentComplete()) {
+ updateSections();
+ refill();
+ if ((d->currentIndex >= d->model->count() || d->currentIndex < 0) && !d->currentIndexCleared) {
+ setCurrentIndex(0);
+ } else {
+ d->moveReason = QDeclarative1ListViewPrivate::SetIndex;
+ d->updateCurrent(d->currentIndex);
+ if (d->highlight && d->currentItem) {
+ if (d->autoHighlight)
+ d->highlight->setPosition(d->currentItem->position());
+ d->updateTrackedItem();
+ }
+ }
+ d->updateViewport();
+ }
+ connect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
+ connect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
+ connect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int)));
+ connect(d->model, SIGNAL(itemsChanged(int,int)), this, SLOT(itemsChanged(int,int)));
+ connect(d->model, SIGNAL(modelReset()), this, SLOT(modelReset()));
+ connect(d->model, SIGNAL(createdItem(int,QDeclarativeItem*)), this, SLOT(createdItem(int,QDeclarativeItem*)));
+ connect(d->model, SIGNAL(destroyingItem(QDeclarativeItem*)), this, SLOT(destroyingItem(QDeclarativeItem*)));
+ emit countChanged();
+ }
+ emit modelChanged();
+}
+
+/*!
+ \qmlproperty Component ListView::delegate
+
+ The delegate provides a template defining each item instantiated by the view.
+ The index is exposed as an accessible \c index property. Properties of the
+ model are also available depending upon the type of \l {qmlmodels}{Data Model}.
+
+ The number of elements in the delegate has a direct effect on the
+ flicking performance of the view. If at all possible, place functionality
+ that is not needed for the normal display of the delegate in a \l Loader which
+ can load additional elements when needed.
+
+ The ListView will lay out the items based on the size of the root item
+ in the delegate.
+
+ It is recommended that the delagate's size be a whole number to avoid sub-pixel
+ alignment of items.
+
+ \note Delegates are instantiated as needed and may be destroyed at any time.
+ State should \e never be stored in a delegate.
+*/
+QDeclarativeComponent *QDeclarative1ListView::delegate() const
+{
+ Q_D(const QDeclarative1ListView);
+ if (d->model) {
+ if (QDeclarative1VisualDataModel *dataModel = qobject_cast<QDeclarative1VisualDataModel*>(d->model))
+ return dataModel->delegate();
+ }
+
+ return 0;
+}
+
+void QDeclarative1ListView::setDelegate(QDeclarativeComponent *delegate)
+{
+ Q_D(QDeclarative1ListView);
+ if (delegate == this->delegate())
+ return;
+ if (!d->ownModel) {
+ d->model = new QDeclarative1VisualDataModel(qmlContext(this));
+ d->ownModel = true;
+ }
+ if (QDeclarative1VisualDataModel *dataModel = qobject_cast<QDeclarative1VisualDataModel*>(d->model)) {
+ int oldCount = dataModel->count();
+ dataModel->setDelegate(delegate);
+ if (isComponentComplete()) {
+ for (int i = 0; i < d->visibleItems.count(); ++i)
+ d->releaseItem(d->visibleItems.at(i));
+ d->visibleItems.clear();
+ d->releaseItem(d->currentItem);
+ d->currentItem = 0;
+ updateSections();
+ refill();
+ d->moveReason = QDeclarative1ListViewPrivate::SetIndex;
+ d->updateCurrent(d->currentIndex);
+ if (d->highlight && d->currentItem) {
+ if (d->autoHighlight)
+ d->highlight->setPosition(d->currentItem->position());
+ d->updateTrackedItem();
+ }
+ d->updateViewport();
+ }
+ if (oldCount != dataModel->count())
+ emit countChanged();
+ }
+ emit delegateChanged();
+}
+
+/*!
+ \qmlproperty int ListView::currentIndex
+ \qmlproperty Item ListView::currentItem
+
+ The \c currentIndex property holds the index of the current item, and
+ \c currentItem holds the current item. Setting the currentIndex to -1
+ will clear the highlight and set currentItem to null.
+
+ If highlightFollowsCurrentItem is \c true, setting either of these
+ properties will smoothly scroll the ListView so that the current
+ item becomes visible.
+
+ Note that the position of the current item
+ may only be approximate until it becomes visible in the view.
+*/
+int QDeclarative1ListView::currentIndex() const
+{
+ Q_D(const QDeclarative1ListView);
+ return d->currentIndex;
+}
+
+void QDeclarative1ListView::setCurrentIndex(int index)
+{
+ Q_D(QDeclarative1ListView);
+ if (d->requestedIndex >= 0) // currently creating item
+ return;
+ d->currentIndexCleared = (index == -1);
+ if (index == d->currentIndex)
+ return;
+ if (isComponentComplete() && d->isValid()) {
+ d->moveReason = QDeclarative1ListViewPrivate::SetIndex;
+ d->updateCurrent(index);
+ } else if (d->currentIndex != index) {
+ d->currentIndex = index;
+ emit currentIndexChanged();
+ }
+}
+
+QDeclarativeItem *QDeclarative1ListView::currentItem()
+{
+ Q_D(QDeclarative1ListView);
+ if (!d->currentItem)
+ return 0;
+ return d->currentItem->item;
+}
+
+/*!
+ \qmlproperty Item ListView::highlightItem
+
+ This holds the highlight item created from the \l highlight component.
+
+ The \c highlightItem is managed by the view unless
+ \l highlightFollowsCurrentItem is set to false.
+
+ \sa highlight, highlightFollowsCurrentItem
+*/
+QDeclarativeItem *QDeclarative1ListView::highlightItem()
+{
+ Q_D(QDeclarative1ListView);
+ if (!d->highlight)
+ return 0;
+ return d->highlight->item;
+}
+
+/*!
+ \qmlproperty int ListView::count
+ This property holds the number of items in the view.
+*/
+int QDeclarative1ListView::count() const
+{
+ Q_D(const QDeclarative1ListView);
+ if (d->model)
+ return d->model->count();
+ return 0;
+}
+
+/*!
+ \qmlproperty Component ListView::highlight
+ This property holds the component to use as the highlight.
+
+ An instance of the highlight component is created for each list.
+ The geometry of the resulting component instance is managed by the list
+ so as to stay with the current item, unless the highlightFollowsCurrentItem
+ property is false.
+
+ \sa highlightItem, highlightFollowsCurrentItem, {declarative/modelviews/listview}{ListView examples}
+*/
+QDeclarativeComponent *QDeclarative1ListView::highlight() const
+{
+ Q_D(const QDeclarative1ListView);
+ return d->highlightComponent;
+}
+
+void QDeclarative1ListView::setHighlight(QDeclarativeComponent *highlight)
+{
+ Q_D(QDeclarative1ListView);
+ if (highlight != d->highlightComponent) {
+ d->highlightComponent = highlight;
+ d->createHighlight();
+ if (d->currentItem)
+ d->updateHighlight();
+ emit highlightChanged();
+ }
+}
+
+/*!
+ \qmlproperty bool ListView::highlightFollowsCurrentItem
+ This property holds whether the highlight is managed by the view.
+
+ If this property is true (the default value), the highlight is moved smoothly
+ to follow the current item. Otherwise, the
+ highlight is not moved by the view, and any movement must be implemented
+ by the highlight.
+
+ Here is a highlight with its motion defined by a \l {SpringAnimation} item:
+
+ \snippet doc/src/snippets/declarative/listview/listview.qml highlightFollowsCurrentItem
+
+ Note that the highlight animation also affects the way that the view
+ is scrolled. This is because the view moves to maintain the
+ highlight within the preferred highlight range (or visible viewport).
+
+ \sa highlight, highlightMoveSpeed
+*/
+bool QDeclarative1ListView::highlightFollowsCurrentItem() const
+{
+ Q_D(const QDeclarative1ListView);
+ return d->autoHighlight;
+}
+
+void QDeclarative1ListView::setHighlightFollowsCurrentItem(bool autoHighlight)
+{
+ Q_D(QDeclarative1ListView);
+ if (d->autoHighlight != autoHighlight) {
+ d->autoHighlight = autoHighlight;
+ if (autoHighlight) {
+ d->updateHighlight();
+ } else {
+ if (d->highlightPosAnimator)
+ d->highlightPosAnimator->stop();
+ if (d->highlightSizeAnimator)
+ d->highlightSizeAnimator->stop();
+ }
+ emit highlightFollowsCurrentItemChanged();
+ }
+}
+
+//###Possibly rename these properties, since they are very useful even without a highlight?
+/*!
+ \qmlproperty real ListView::preferredHighlightBegin
+ \qmlproperty real ListView::preferredHighlightEnd
+ \qmlproperty enumeration ListView::highlightRangeMode
+
+ These properties define the preferred range of the highlight (for the current item)
+ within the view. The \c preferredHighlightBegin value must be less than the
+ \c preferredHighlightEnd value.
+
+ These properties affect the position of the current item when the list is scrolled.
+ For example, if the currently selected item should stay in the middle of the
+ list when the view is scrolled, set the \c preferredHighlightBegin and
+ \c preferredHighlightEnd values to the top and bottom coordinates of where the middle
+ item would be. If the \c currentItem is changed programmatically, the list will
+ automatically scroll so that the current item is in the middle of the view.
+ Furthermore, the behavior of the current item index will occur whether or not a
+ highlight exists.
+
+ Valid values for \c highlightRangeMode are:
+
+ \list
+ \o ListView.ApplyRange - the view attempts to maintain the highlight within the range.
+ However, the highlight can move outside of the range at the ends of the list or due
+ to mouse interaction.
+ \o ListView.StrictlyEnforceRange - the highlight never moves outside of the range.
+ The current item changes if a keyboard or mouse action would cause the highlight to move
+ outside of the range.
+ \o ListView.NoHighlightRange - this is the default value.
+ \endlist
+*/
+qreal QDeclarative1ListView::preferredHighlightBegin() const
+{
+ Q_D(const QDeclarative1ListView);
+ return d->highlightRangeStart;
+}
+
+void QDeclarative1ListView::setPreferredHighlightBegin(qreal start)
+{
+ Q_D(QDeclarative1ListView);
+ d->highlightRangeStartValid = true;
+ if (d->highlightRangeStart == start)
+ return;
+ d->highlightRangeStart = start;
+ d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
+ emit preferredHighlightBeginChanged();
+}
+
+void QDeclarative1ListView::resetPreferredHighlightBegin()
+{
+ Q_D(QDeclarative1ListView);
+ d->highlightRangeStartValid = false;
+ if (d->highlightRangeStart == 0)
+ return;
+ d->highlightRangeStart = 0;
+ emit preferredHighlightBeginChanged();
+}
+
+qreal QDeclarative1ListView::preferredHighlightEnd() const
+{
+ Q_D(const QDeclarative1ListView);
+ return d->highlightRangeEnd;
+}
+
+void QDeclarative1ListView::setPreferredHighlightEnd(qreal end)
+{
+ Q_D(QDeclarative1ListView);
+ d->highlightRangeEndValid = true;
+ if (d->highlightRangeEnd == end)
+ return;
+ d->highlightRangeEnd = end;
+ d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
+ emit preferredHighlightEndChanged();
+}
+
+void QDeclarative1ListView::resetPreferredHighlightEnd()
+{
+ Q_D(QDeclarative1ListView);
+ d->highlightRangeEndValid = false;
+ if (d->highlightRangeEnd == 0)
+ return;
+ d->highlightRangeEnd = 0;
+ emit preferredHighlightEndChanged();
+}
+
+QDeclarative1ListView::HighlightRangeMode QDeclarative1ListView::highlightRangeMode() const
+{
+ Q_D(const QDeclarative1ListView);
+ return d->highlightRange;
+}
+
+void QDeclarative1ListView::setHighlightRangeMode(HighlightRangeMode mode)
+{
+ Q_D(QDeclarative1ListView);
+ if (d->highlightRange == mode)
+ return;
+ d->highlightRange = mode;
+ d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
+ emit highlightRangeModeChanged();
+}
+
+/*!
+ \qmlproperty real ListView::spacing
+
+ This property holds the spacing between items.
+
+ The default value is 0.
+*/
+qreal QDeclarative1ListView::spacing() const
+{
+ Q_D(const QDeclarative1ListView);
+ return d->spacing;
+}
+
+void QDeclarative1ListView::setSpacing(qreal spacing)
+{
+ Q_D(QDeclarative1ListView);
+ if (spacing != d->spacing) {
+ d->spacing = spacing;
+ d->layout();
+ emit spacingChanged();
+ }
+}
+
+/*!
+ \qmlproperty enumeration ListView::orientation
+ This property holds the orientation of the list.
+
+ Possible values:
+
+ \list
+ \o ListView.Horizontal - Items are laid out horizontally
+ \o ListView.Vertical (default) - Items are laid out vertically
+ \endlist
+
+ \table
+ \row
+ \o Horizontal orientation:
+ \image ListViewHorizontal.png
+
+ \row
+ \o Vertical orientation:
+ \image listview-highlight.png
+ \endtable
+*/
+QDeclarative1ListView::Orientation QDeclarative1ListView::orientation() const
+{
+ Q_D(const QDeclarative1ListView);
+ return d->orient;
+}
+
+void QDeclarative1ListView::setOrientation(QDeclarative1ListView::Orientation orientation)
+{
+ Q_D(QDeclarative1ListView);
+ if (d->orient != orientation) {
+ d->orient = orientation;
+ if (d->orient == QDeclarative1ListView::Vertical) {
+ setContentWidth(-1);
+ setFlickableDirection(VerticalFlick);
+ setContentX(0);
+ } else {
+ setContentHeight(-1);
+ setFlickableDirection(HorizontalFlick);
+ setContentY(0);
+ }
+ d->regenerate();
+ emit orientationChanged();
+ }
+}
+
+/*!
+ \qmlproperty enumeration ListView::layoutDirection
+ This property holds the layout direction of the horizontal list.
+
+ Possible values:
+
+ \list
+ \o Qt.LeftToRight (default) - Items will be laid out from left to right.
+ \o Qt.RightToLeft - Items will be laid out from right to let.
+ \endlist
+
+ \sa ListView::effectiveLayoutDirection
+*/
+
+Qt::LayoutDirection QDeclarative1ListView::layoutDirection() const
+{
+ Q_D(const QDeclarative1ListView);
+ return d->layoutDirection;
+}
+
+void QDeclarative1ListView::setLayoutDirection(Qt::LayoutDirection layoutDirection)
+{
+ Q_D(QDeclarative1ListView);
+ if (d->layoutDirection != layoutDirection) {
+ d->layoutDirection = layoutDirection;
+ d->regenerate();
+ emit layoutDirectionChanged();
+ emit effectiveLayoutDirectionChanged();
+ }
+}
+
+/*!
+ \qmlproperty enumeration ListView::effectiveLayoutDirection
+ This property holds the effective layout direction of the horizontal list.
+
+ When using the attached property \l {LayoutMirroring::enabled}{LayoutMirroring::enabled} for locale layouts,
+ the visual layout direction of the horizontal list will be mirrored. However, the
+ property \l {ListView::layoutDirection}{layoutDirection} will remain unchanged.
+
+ \sa ListView::layoutDirection, {LayoutMirroring}{LayoutMirroring}
+*/
+
+Qt::LayoutDirection QDeclarative1ListView::effectiveLayoutDirection() const
+{
+ Q_D(const QDeclarative1ListView);
+ if (d->effectiveLayoutMirror)
+ return d->layoutDirection == Qt::RightToLeft ? Qt::LeftToRight : Qt::RightToLeft;
+ else
+ return d->layoutDirection;
+}
+
+/*!
+ \qmlproperty bool ListView::keyNavigationWraps
+ This property holds whether the list wraps key navigation.
+
+ If this is true, key navigation that would move the current item selection
+ past the end of the list instead wraps around and moves the selection to
+ the start of the list, and vice-versa.
+
+ By default, key navigation is not wrapped.
+*/
+bool QDeclarative1ListView::isWrapEnabled() const
+{
+ Q_D(const QDeclarative1ListView);
+ return d->wrap;
+}
+
+void QDeclarative1ListView::setWrapEnabled(bool wrap)
+{
+ Q_D(QDeclarative1ListView);
+ if (d->wrap == wrap)
+ return;
+ d->wrap = wrap;
+ emit keyNavigationWrapsChanged();
+}
+
+/*!
+ \qmlproperty int ListView::cacheBuffer
+ This property determines whether delegates are retained outside the
+ visible area of the view.
+
+ If this value is non-zero, the view keeps as many delegates
+ instantiated as it can fit within the buffer specified. For example,
+ if in a vertical view the delegate is 20 pixels high and \c cacheBuffer is
+ set to 40, then up to 2 delegates above and 2 delegates below the visible
+ area may be retained.
+
+ Note that cacheBuffer is not a pixel buffer - it only maintains additional
+ instantiated delegates.
+
+ Setting this value can improve the smoothness of scrolling behavior at the expense
+ of additional memory usage. It is not a substitute for creating efficient
+ delegates; the fewer elements in a delegate, the faster a view can be
+ scrolled.
+*/
+int QDeclarative1ListView::cacheBuffer() const
+{
+ Q_D(const QDeclarative1ListView);
+ return d->buffer;
+}
+
+void QDeclarative1ListView::setCacheBuffer(int b)
+{
+ Q_D(QDeclarative1ListView);
+ if (d->buffer != b) {
+ d->buffer = b;
+ if (isComponentComplete()) {
+ d->bufferMode = QDeclarative1ListViewPrivate::BufferBefore | QDeclarative1ListViewPrivate::BufferAfter;
+ refill();
+ }
+ emit cacheBufferChanged();
+ }
+}
+
+/*!
+ \qmlproperty string ListView::section.property
+ \qmlproperty enumeration ListView::section.criteria
+ \qmlproperty Component ListView::section.delegate
+
+ These properties hold the expression to be evaluated for the \l section attached property.
+
+ The \l section attached property enables a ListView to be visually
+ separated into different parts. These properties determine how sections
+ are created.
+
+ \c section.property holds the name of the property that is the basis
+ of each section.
+
+ \c section.criteria holds the criteria for forming each section based on
+ \c section.property. This value can be one of:
+
+ \list
+ \o ViewSection.FullString (default) - sections are created based on the
+ \c section.property value.
+ \o ViewSection.FirstCharacter - sections are created based on the first
+ character of the \c section.property value (for example, 'A', 'B', 'C'
+ sections, etc. for an address book)
+ \endlist
+
+ \c section.delegate holds the delegate component for each section.
+
+ Each item in the list has attached properties named \c ListView.section,
+ \c ListView.previousSection and \c ListView.nextSection. These may be
+ used to place a section header for related items.
+
+ For example, here is a ListView that displays a list of animals, separated
+ into sections. Each item in the ListView is placed in a different section
+ depending on the "size" property of the model item. The \c sectionHeading
+ delegate component provides the light blue bar that marks the beginning of
+ each section.
+
+
+ \snippet examples/declarative/modelviews/listview/sections.qml 0
+
+ \image qml-listview-sections-example.png
+
+ \note Adding sections to a ListView does not automatically re-order the
+ list items by the section criteria.
+ If the model is not ordered by section, then it is possible that
+ the sections created will not be unique; each boundary between
+ differing sections will result in a section header being created
+ even if that section exists elsewhere.
+
+ \sa {declarative/modelviews/listview}{ListView examples}
+*/
+QDeclarative1ViewSection *QDeclarative1ListView::sectionCriteria()
+{
+ Q_D(QDeclarative1ListView);
+ if (!d->sectionCriteria) {
+ d->sectionCriteria = new QDeclarative1ViewSection(this);
+ connect(d->sectionCriteria, SIGNAL(propertyChanged()), this, SLOT(updateSections()));
+ }
+ return d->sectionCriteria;
+}
+
+/*!
+ \qmlproperty string ListView::currentSection
+ This property holds the section that is currently at the beginning of the view.
+*/
+QString QDeclarative1ListView::currentSection() const
+{
+ Q_D(const QDeclarative1ListView);
+ return d->currentSection;
+}
+
+/*!
+ \qmlproperty real ListView::highlightMoveSpeed
+ \qmlproperty int ListView::highlightMoveDuration
+ \qmlproperty real ListView::highlightResizeSpeed
+ \qmlproperty int ListView::highlightResizeDuration
+
+ These properties hold the move and resize animation speed of the highlight delegate.
+
+ \l highlightFollowsCurrentItem must be true for these properties
+ to have effect.
+
+ The default value for the speed properties is 400 pixels/second.
+ The default value for the duration properties is -1, i.e. the
+ highlight will take as much time as necessary to move at the set speed.
+
+ These properties have the same characteristics as a SmoothedAnimation.
+
+ \sa highlightFollowsCurrentItem
+*/
+qreal QDeclarative1ListView::highlightMoveSpeed() const
+{
+ Q_D(const QDeclarative1ListView);\
+ return d->highlightMoveSpeed;
+}
+
+void QDeclarative1ListView::setHighlightMoveSpeed(qreal speed)
+{
+ Q_D(QDeclarative1ListView);\
+ if (d->highlightMoveSpeed != speed) {
+ d->highlightMoveSpeed = speed;
+ if (d->highlightPosAnimator)
+ d->highlightPosAnimator->velocity = d->highlightMoveSpeed;
+ emit highlightMoveSpeedChanged();
+ }
+}
+
+int QDeclarative1ListView::highlightMoveDuration() const
+{
+ Q_D(const QDeclarative1ListView);
+ return d->highlightMoveDuration;
+}
+
+void QDeclarative1ListView::setHighlightMoveDuration(int duration)
+{
+ Q_D(QDeclarative1ListView);\
+ if (d->highlightMoveDuration != duration) {
+ d->highlightMoveDuration = duration;
+ if (d->highlightPosAnimator)
+ d->highlightPosAnimator->userDuration = d->highlightMoveDuration;
+ emit highlightMoveDurationChanged();
+ }
+}
+
+qreal QDeclarative1ListView::highlightResizeSpeed() const
+{
+ Q_D(const QDeclarative1ListView);\
+ return d->highlightResizeSpeed;
+}
+
+void QDeclarative1ListView::setHighlightResizeSpeed(qreal speed)
+{
+ Q_D(QDeclarative1ListView);\
+ if (d->highlightResizeSpeed != speed) {
+ d->highlightResizeSpeed = speed;
+ if (d->highlightSizeAnimator)
+ d->highlightSizeAnimator->velocity = d->highlightResizeSpeed;
+ emit highlightResizeSpeedChanged();
+ }
+}
+
+int QDeclarative1ListView::highlightResizeDuration() const
+{
+ Q_D(const QDeclarative1ListView);
+ return d->highlightResizeDuration;
+}
+
+void QDeclarative1ListView::setHighlightResizeDuration(int duration)
+{
+ Q_D(QDeclarative1ListView);\
+ if (d->highlightResizeDuration != duration) {
+ d->highlightResizeDuration = duration;
+ if (d->highlightSizeAnimator)
+ d->highlightSizeAnimator->userDuration = d->highlightResizeDuration;
+ emit highlightResizeDurationChanged();
+ }
+}
+
+/*!
+ \qmlproperty enumeration ListView::snapMode
+
+ This property determines how the view scrolling will settle following a drag or flick.
+ The possible values are:
+
+ \list
+ \o ListView.NoSnap (default) - the view stops anywhere within the visible area.
+ \o ListView.SnapToItem - the view settles with an item aligned with the start of
+ the view.
+ \o ListView.SnapOneItem - the view settles no more than one item away from the first
+ visible item at the time the mouse button is released. This mode is particularly
+ useful for moving one page at a time.
+ \endlist
+
+ \c snapMode does not affect the \l currentIndex. To update the
+ \l currentIndex as the list is moved, set \l highlightRangeMode
+ to \c ListView.StrictlyEnforceRange.
+
+ \sa highlightRangeMode
+*/
+QDeclarative1ListView::SnapMode QDeclarative1ListView::snapMode() const
+{
+ Q_D(const QDeclarative1ListView);
+ return d->snapMode;
+}
+
+void QDeclarative1ListView::setSnapMode(SnapMode mode)
+{
+ Q_D(QDeclarative1ListView);
+ if (d->snapMode != mode) {
+ d->snapMode = mode;
+ emit snapModeChanged();
+ }
+}
+
+/*!
+ \qmlproperty Component ListView::footer
+ This property holds the component to use as the footer.
+
+ An instance of the footer component is created for each view. The
+ footer is positioned at the end of the view, after any items.
+
+ \sa header
+*/
+QDeclarativeComponent *QDeclarative1ListView::footer() const
+{
+ Q_D(const QDeclarative1ListView);
+ return d->footerComponent;
+}
+
+void QDeclarative1ListView::setFooter(QDeclarativeComponent *footer)
+{
+ Q_D(QDeclarative1ListView);
+ if (d->footerComponent != footer) {
+ if (d->footer) {
+ if (scene())
+ scene()->removeItem(d->footer->item);
+ d->footer->item->deleteLater();
+ delete d->footer;
+ d->footer = 0;
+ }
+ d->footerComponent = footer;
+ d->minExtentDirty = true;
+ d->maxExtentDirty = true;
+ if (isComponentComplete()) {
+ d->updateFooter();
+ d->updateViewport();
+ d->fixupPosition();
+ }
+ emit footerChanged();
+ }
+}
+
+/*!
+ \qmlproperty Component ListView::header
+ This property holds the component to use as the header.
+
+ An instance of the header component is created for each view. The
+ header is positioned at the beginning of the view, before any items.
+
+ \sa footer
+*/
+QDeclarativeComponent *QDeclarative1ListView::header() const
+{
+ Q_D(const QDeclarative1ListView);
+ return d->headerComponent;
+}
+
+void QDeclarative1ListView::setHeader(QDeclarativeComponent *header)
+{
+ Q_D(QDeclarative1ListView);
+ if (d->headerComponent != header) {
+ if (d->header) {
+ if (scene())
+ scene()->removeItem(d->header->item);
+ d->header->item->deleteLater();
+ delete d->header;
+ d->header = 0;
+ }
+ d->headerComponent = header;
+ d->minExtentDirty = true;
+ d->maxExtentDirty = true;
+ if (isComponentComplete()) {
+ d->updateHeader();
+ d->updateFooter();
+ d->updateViewport();
+ d->fixupPosition();
+ }
+ emit headerChanged();
+ }
+}
+
+void QDeclarative1ListView::setContentX(qreal pos)
+{
+ Q_D(QDeclarative1ListView);
+ // Positioning the view manually should override any current movement state
+ d->moveReason = QDeclarative1ListViewPrivate::Other;
+ QDeclarative1Flickable::setContentX(pos);
+}
+
+void QDeclarative1ListView::setContentY(qreal pos)
+{
+ Q_D(QDeclarative1ListView);
+ // Positioning the view manually should override any current movement state
+ d->moveReason = QDeclarative1ListViewPrivate::Other;
+ QDeclarative1Flickable::setContentY(pos);
+}
+
+bool QDeclarative1ListView::event(QEvent *event)
+{
+ Q_D(QDeclarative1ListView);
+ if (event->type() == QEvent::User) {
+ d->layout();
+ return true;
+ }
+
+ return QDeclarative1Flickable::event(event);
+}
+
+void QDeclarative1ListView::viewportMoved()
+{
+ Q_D(QDeclarative1ListView);
+ QDeclarative1Flickable::viewportMoved();
+ if (!d->itemCount)
+ return;
+ // Recursion can occur due to refill changing the content size.
+ if (d->inViewportMoved)
+ return;
+ d->inViewportMoved = true;
+ d->lazyRelease = true;
+ refill();
+ if (d->flickingHorizontally || d->flickingVertically || d->movingHorizontally || d->movingVertically)
+ d->moveReason = QDeclarative1ListViewPrivate::Mouse;
+ if (d->moveReason != QDeclarative1ListViewPrivate::SetIndex) {
+ if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) {
+ // reposition highlight
+ qreal pos = d->highlight->position();
+ qreal viewPos;
+ qreal highlightStart;
+ qreal highlightEnd;
+ if (d->isRightToLeft()) {
+ // Handle Right-To-Left exceptions
+ viewPos = -d->position()-d->size();
+ highlightStart = d->highlightRangeStartValid ? d->size()-d->highlightRangeEnd : d->highlightRangeStart;
+ highlightEnd = d->highlightRangeEndValid ? d->size()-d->highlightRangeStart : d->highlightRangeEnd;
+ } else {
+ viewPos = d->position();
+ highlightStart = d->highlightRangeStart;
+ highlightEnd = d->highlightRangeEnd;
+ }
+ if (pos > viewPos + highlightEnd - d->highlight->size())
+ pos = viewPos + highlightEnd - d->highlight->size();
+ if (pos < viewPos + highlightStart)
+ pos = viewPos + highlightStart;
+ d->highlightPosAnimator->stop();
+ d->highlight->setPosition(qRound(pos));
+
+ // update current index
+ if (FxListItem1 *snapItem = d->snapItemAt(d->highlight->position())) {
+ if (snapItem->index >= 0 && snapItem->index != d->currentIndex)
+ d->updateCurrent(snapItem->index);
+ }
+ }
+ }
+
+ if ((d->flickingHorizontally || d->flickingVertically) && d->correctFlick && !d->inFlickCorrection) {
+ d->inFlickCorrection = true;
+ // Near an end and it seems that the extent has changed?
+ // Recalculate the flick so that we don't end up in an odd position.
+ if (yflick() && !d->vData.inOvershoot) {
+ if (d->vData.velocity > 0) {
+ const qreal minY = minYExtent();
+ if ((minY - d->vData.move.value() < height()/2 || d->vData.flickTarget - d->vData.move.value() < height()/2)
+ && minY != d->vData.flickTarget)
+ d->flickY(-d->vData.smoothVelocity.value());
+ d->bufferMode = QDeclarative1ListViewPrivate::BufferBefore;
+ } else if (d->vData.velocity < 0) {
+ const qreal maxY = maxYExtent();
+ if ((d->vData.move.value() - maxY < height()/2 || d->vData.move.value() - d->vData.flickTarget < height()/2)
+ && maxY != d->vData.flickTarget)
+ d->flickY(-d->vData.smoothVelocity.value());
+ d->bufferMode = QDeclarative1ListViewPrivate::BufferAfter;
+ }
+ }
+
+ if (xflick() && !d->hData.inOvershoot) {
+ if (d->hData.velocity > 0) {
+ const qreal minX = minXExtent();
+ if ((minX - d->hData.move.value() < width()/2 || d->hData.flickTarget - d->hData.move.value() < width()/2)
+ && minX != d->hData.flickTarget)
+ d->flickX(-d->hData.smoothVelocity.value());
+ d->bufferMode = d->isRightToLeft()
+ ? QDeclarative1ListViewPrivate::BufferAfter : QDeclarative1ListViewPrivate::BufferBefore;
+ } else if (d->hData.velocity < 0) {
+ const qreal maxX = maxXExtent();
+ if ((d->hData.move.value() - maxX < width()/2 || d->hData.move.value() - d->hData.flickTarget < width()/2)
+ && maxX != d->hData.flickTarget)
+ d->flickX(-d->hData.smoothVelocity.value());
+ d->bufferMode = d->isRightToLeft()
+ ? QDeclarative1ListViewPrivate::BufferBefore : QDeclarative1ListViewPrivate::BufferAfter;
+ }
+ }
+ d->inFlickCorrection = false;
+ }
+ d->inViewportMoved = false;
+}
+
+qreal QDeclarative1ListView::minYExtent() const
+{
+ Q_D(const QDeclarative1ListView);
+ if (d->orient == QDeclarative1ListView::Horizontal)
+ return QDeclarative1Flickable::minYExtent();
+ if (d->minExtentDirty) {
+ d->minExtent = -d->startPosition();
+ if (d->header && d->visibleItems.count())
+ d->minExtent += d->header->size();
+ if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
+ d->minExtent += d->highlightRangeStart;
+ if (d->sectionCriteria) {
+ if (d->visibleItem(0))
+ d->minExtent -= d->visibleItem(0)->sectionSize();
+ }
+ d->minExtent = qMax(d->minExtent, -(d->endPositionAt(0) - d->highlightRangeEnd + 1));
+ }
+ d->minExtentDirty = false;
+ }
+
+ return d->minExtent;
+}
+
+qreal QDeclarative1ListView::maxYExtent() const
+{
+ Q_D(const QDeclarative1ListView);
+ if (d->orient == QDeclarative1ListView::Horizontal)
+ return height();
+ if (d->maxExtentDirty) {
+ if (!d->model || !d->model->count()) {
+ d->maxExtent = d->header ? -d->header->size() : 0;
+ d->maxExtent += height();
+ } else if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
+ d->maxExtent = -(d->positionAt(d->model->count()-1) - d->highlightRangeStart);
+ if (d->highlightRangeEnd != d->highlightRangeStart)
+ d->maxExtent = qMin(d->maxExtent, -(d->endPosition() - d->highlightRangeEnd + 1));
+ } else {
+ d->maxExtent = -(d->endPosition() - height() + 1);
+ }
+ if (d->footer)
+ d->maxExtent -= d->footer->size();
+ qreal minY = minYExtent();
+ if (d->maxExtent > minY)
+ d->maxExtent = minY;
+ d->maxExtentDirty = false;
+ }
+ return d->maxExtent;
+}
+
+qreal QDeclarative1ListView::minXExtent() const
+{
+ Q_D(const QDeclarative1ListView);
+ if (d->orient == QDeclarative1ListView::Vertical)
+ return QDeclarative1Flickable::minXExtent();
+ if (d->minExtentDirty) {
+ d->minExtent = -d->startPosition();
+
+ qreal highlightStart;
+ qreal highlightEnd;
+ qreal endPositionFirstItem = 0;
+ if (d->isRightToLeft()) {
+ if (d->model && d->model->count())
+ endPositionFirstItem = d->positionAt(d->model->count()-1);
+ else if (d->header)
+ d->minExtent += d->header->size();
+ highlightStart = d->highlightRangeStartValid
+ ? d->highlightRangeStart - (d->lastPosition()-endPositionFirstItem)
+ : d->size() - (d->lastPosition()-endPositionFirstItem);
+ highlightEnd = d->highlightRangeEndValid ? d->highlightRangeEnd : d->size();
+ if (d->footer)
+ d->minExtent += d->footer->size();
+ qreal maxX = maxXExtent();
+ if (d->minExtent < maxX)
+ d->minExtent = maxX;
+ } else {
+ endPositionFirstItem = d->endPositionAt(0);
+ highlightStart = d->highlightRangeStart;
+ highlightEnd = d->highlightRangeEnd;
+ if (d->header && d->visibleItems.count())
+ d->minExtent += d->header->size();
+ }
+ if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
+ d->minExtent += highlightStart;
+ d->minExtent = qMax(d->minExtent, -(endPositionFirstItem - highlightEnd + 1));
+ }
+ d->minExtentDirty = false;
+ }
+
+ return d->minExtent;
+}
+
+qreal QDeclarative1ListView::maxXExtent() const
+{
+ Q_D(const QDeclarative1ListView);
+ if (d->orient == QDeclarative1ListView::Vertical)
+ return width();
+ if (d->maxExtentDirty) {
+ qreal highlightStart;
+ qreal highlightEnd;
+ qreal lastItemPosition = 0;
+ d->maxExtent = 0;
+ if (d->isRightToLeft()) {
+ highlightStart = d->highlightRangeStartValid ? d->highlightRangeEnd : d->size();
+ highlightEnd = d->highlightRangeEndValid ? d->highlightRangeStart : d->size();
+ lastItemPosition = d->endPosition();
+ } else {
+ highlightStart = d->highlightRangeStart;
+ highlightEnd = d->highlightRangeEnd;
+ if (d->model && d->model->count())
+ lastItemPosition = d->positionAt(d->model->count()-1);
+ }
+ if (!d->model || !d->model->count()) {
+ if (!d->isRightToLeft())
+ d->maxExtent = d->header ? -d->header->size() : 0;
+ d->maxExtent += width();
+ } else if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
+ d->maxExtent = -(lastItemPosition - highlightStart);
+ if (highlightEnd != highlightStart) {
+ d->maxExtent = d->isRightToLeft()
+ ? qMax(d->maxExtent, -(d->endPosition() - highlightEnd + 1))
+ : qMin(d->maxExtent, -(d->endPosition() - highlightEnd + 1));
+ }
+ } else {
+ d->maxExtent = -(d->endPosition() - width() + 1);
+ }
+ if (d->isRightToLeft()) {
+ if (d->header && d->visibleItems.count())
+ d->maxExtent -= d->header->size();
+ } else {
+ if (d->footer)
+ d->maxExtent -= d->footer->size();
+ qreal minX = minXExtent();
+ if (d->maxExtent > minX)
+ d->maxExtent = minX;
+ }
+ d->maxExtentDirty = false;
+ }
+ return d->maxExtent;
+}
+
+void QDeclarative1ListView::keyPressEvent(QKeyEvent *event)
+{
+ Q_D(QDeclarative1ListView);
+ keyPressPreHandler(event);
+ if (event->isAccepted())
+ return;
+
+ if (d->model && d->model->count() && d->interactive) {
+ if ((d->orient == QDeclarative1ListView::Horizontal && !d->isRightToLeft() && event->key() == Qt::Key_Left)
+ || (d->orient == QDeclarative1ListView::Horizontal && d->isRightToLeft() && event->key() == Qt::Key_Right)
+ || (d->orient == QDeclarative1ListView::Vertical && event->key() == Qt::Key_Up)) {
+ if (currentIndex() > 0 || (d->wrap && !event->isAutoRepeat())) {
+ decrementCurrentIndex();
+ event->accept();
+ return;
+ } else if (d->wrap) {
+ event->accept();
+ return;
+ }
+ } else if ((d->orient == QDeclarative1ListView::Horizontal && !d->isRightToLeft() && event->key() == Qt::Key_Right)
+ || (d->orient == QDeclarative1ListView::Horizontal && d->isRightToLeft() && event->key() == Qt::Key_Left)
+ || (d->orient == QDeclarative1ListView::Vertical && event->key() == Qt::Key_Down)) {
+ if (currentIndex() < d->model->count() - 1 || (d->wrap && !event->isAutoRepeat())) {
+ incrementCurrentIndex();
+ event->accept();
+ return;
+ } else if (d->wrap) {
+ event->accept();
+ return;
+ }
+ }
+ }
+ event->ignore();
+ QDeclarative1Flickable::keyPressEvent(event);
+}
+
+void QDeclarative1ListView::geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry)
+{
+ Q_D(QDeclarative1ListView);
+ d->maxExtentDirty = true;
+ d->minExtentDirty = true;
+ if (d->isRightToLeft() && d->orient == QDeclarative1ListView::Horizontal) {
+ // maintain position relative to the right edge
+ int dx = newGeometry.width() - oldGeometry.width();
+ setContentX(contentX() - dx);
+ }
+ QDeclarative1Flickable::geometryChanged(newGeometry, oldGeometry);
+}
+
+
+/*!
+ \qmlmethod ListView::incrementCurrentIndex()
+
+ Increments the current index. The current index will wrap
+ if keyNavigationWraps is true and it is currently at the end.
+ This method has no effect if the \l count is zero.
+
+ \bold Note: methods should only be called after the Component has completed.
+*/
+void QDeclarative1ListView::incrementCurrentIndex()
+{
+ Q_D(QDeclarative1ListView);
+ int count = d->model ? d->model->count() : 0;
+ if (count && (currentIndex() < count - 1 || d->wrap)) {
+ d->moveReason = QDeclarative1ListViewPrivate::SetIndex;
+ int index = currentIndex()+1;
+ setCurrentIndex((index >= 0 && index < count) ? index : 0);
+ }
+}
+
+/*!
+ \qmlmethod ListView::decrementCurrentIndex()
+
+ Decrements the current index. The current index will wrap
+ if keyNavigationWraps is true and it is currently at the beginning.
+ This method has no effect if the \l count is zero.
+
+ \bold Note: methods should only be called after the Component has completed.
+*/
+void QDeclarative1ListView::decrementCurrentIndex()
+{
+ Q_D(QDeclarative1ListView);
+ int count = d->model ? d->model->count() : 0;
+ if (count && (currentIndex() > 0 || d->wrap)) {
+ d->moveReason = QDeclarative1ListViewPrivate::SetIndex;
+ int index = currentIndex()-1;
+ setCurrentIndex((index >= 0 && index < count) ? index : count-1);
+ }
+}
+
+void QDeclarative1ListViewPrivate::positionViewAtIndex(int index, int mode)
+{
+ Q_Q(QDeclarative1ListView);
+ if (!isValid())
+ return;
+ if (mode < QDeclarative1ListView::Beginning || mode > QDeclarative1ListView::Contain)
+ return;
+ int idx = qMax(qMin(index, model->count()-1), 0);
+
+ if (layoutScheduled)
+ layout();
+ qreal pos = isRightToLeft() ? -position() - size() : position();
+ FxListItem1 *item = visibleItem(idx);
+ qreal maxExtent;
+ if (orient == QDeclarative1ListView::Vertical)
+ maxExtent = -q->maxYExtent();
+ else
+ maxExtent = isRightToLeft() ? q->minXExtent()-size(): -q->maxXExtent();
+
+ if (!item) {
+ int itemPos = positionAt(idx);
+ // save the currently visible items in case any of them end up visible again
+ QList<FxListItem1*> oldVisible = visibleItems;
+ visibleItems.clear();
+ visiblePos = itemPos;
+ visibleIndex = idx;
+ setPosition(qMin(qreal(itemPos), maxExtent));
+ // now release the reference to all the old visible items.
+ for (int i = 0; i < oldVisible.count(); ++i)
+ releaseItem(oldVisible.at(i));
+ item = visibleItem(idx);
+ }
+ if (item) {
+ const qreal itemPos = item->position();
+ switch (mode) {
+ case QDeclarative1ListView::Beginning:
+ pos = itemPos;
+ if (index < 0 && header)
+ pos -= header->size();
+ break;
+ case QDeclarative1ListView::Center:
+ pos = itemPos - (size() - item->size())/2;
+ break;
+ case QDeclarative1ListView::End:
+ pos = itemPos - size() + item->size();
+ if (index >= model->count() && footer)
+ pos += footer->size();
+ break;
+ case QDeclarative1ListView::Visible:
+ if (itemPos > pos + size())
+ pos = itemPos - size() + item->size();
+ else if (item->endPosition() < pos)
+ pos = itemPos;
+ break;
+ case QDeclarative1ListView::Contain:
+ if (item->endPosition() > pos + size())
+ pos = itemPos - size() + item->size();
+ if (itemPos < pos)
+ pos = itemPos;
+ }
+ pos = qMin(pos, maxExtent);
+ qreal minExtent;
+ if (orient == QDeclarative1ListView::Vertical) {
+ minExtent = -q->minYExtent();
+ } else {
+ minExtent = isRightToLeft() ? q->maxXExtent()-size(): -q->minXExtent();
+ }
+ pos = qMax(pos, minExtent);
+ moveReason = QDeclarative1ListViewPrivate::Other;
+ q->cancelFlick();
+ setPosition(pos);
+ if (highlight) {
+ if (autoHighlight) {
+ highlight->setPosition(currentItem->itemPosition());
+ highlight->setSize(currentItem->itemSize());
+ }
+ updateHighlight();
+ }
+ }
+ fixupPosition();
+}
+
+/*!
+ \qmlmethod ListView::positionViewAtIndex(int index, PositionMode mode)
+
+ Positions the view such that the \a index is at the position specified by
+ \a mode:
+
+ \list
+ \o ListView.Beginning - position item at the top (or left for horizontal orientation) of the view.
+ \o ListView.Center - position item in the center of the view.
+ \o ListView.End - position item at bottom (or right for horizontal orientation) of the view.
+ \o ListView.Visible - if any part of the item is visible then take no action, otherwise
+ bring the item into view.
+ \o ListView.Contain - ensure the entire item is visible. If the item is larger than
+ the view the item is positioned at the top (or left for horizontal orientation) of the view.
+ \endlist
+
+ If positioning the view at \a index would cause empty space to be displayed at
+ the beginning or end of the view, the view will be positioned at the boundary.
+
+ It is not recommended to use \l {Flickable::}{contentX} or \l {Flickable::}{contentY} to position the view
+ at a particular index. This is unreliable since removing items from the start
+ of the list does not cause all other items to be repositioned, and because
+ the actual start of the view can vary based on the size of the delegates.
+ The correct way to bring an item into view is with \c positionViewAtIndex.
+
+ \bold Note: methods should only be called after the Component has completed. To position
+ the view at startup, this method should be called by Component.onCompleted. For
+ example, to position the view at the end:
+
+ \code
+ Component.onCompleted: positionViewAtIndex(count - 1, ListView.Beginning)
+ \endcode
+*/
+void QDeclarative1ListView::positionViewAtIndex(int index, int mode)
+{
+ Q_D(QDeclarative1ListView);
+ if (!d->isValid() || index < 0 || index >= d->model->count())
+ return;
+ d->positionViewAtIndex(index, mode);
+}
+
+/*!
+ \qmlmethod ListView::positionViewAtBeginning()
+ \qmlmethod ListView::positionViewAtEnd()
+ \since Quick 1.1
+
+ Positions the view at the beginning or end, taking into account any header or footer.
+
+ It is not recommended to use \l {Flickable::}{contentX} or \l {Flickable::}{contentY} to position the view
+ at a particular index. This is unreliable since removing items from the start
+ of the list does not cause all other items to be repositioned, and because
+ the actual start of the view can vary based on the size of the delegates.
+
+ \bold Note: methods should only be called after the Component has completed. To position
+ the view at startup, this method should be called by Component.onCompleted. For
+ example, to position the view at the end on startup:
+
+ \code
+ Component.onCompleted: positionViewAtEnd()
+ \endcode
+*/
+void QDeclarative1ListView::positionViewAtBeginning()
+{
+ Q_D(QDeclarative1ListView);
+ if (!d->isValid())
+ return;
+ d->positionViewAtIndex(-1, Beginning);
+}
+
+void QDeclarative1ListView::positionViewAtEnd()
+{
+ Q_D(QDeclarative1ListView);
+ if (!d->isValid())
+ return;
+ d->positionViewAtIndex(d->model->count(), End);
+}
+
+/*!
+ \qmlmethod int ListView::indexAt(int x, int y)
+
+ Returns the index of the visible item containing the point \a x, \a y in content
+ coordinates. If there is no item at the point specified, or the item is
+ not visible -1 is returned.
+
+ If the item is outside the visible area, -1 is returned, regardless of
+ whether an item will exist at that point when scrolled into view.
+
+ \bold Note: methods should only be called after the Component has completed.
+*/
+int QDeclarative1ListView::indexAt(qreal x, qreal y) const
+{
+ Q_D(const QDeclarative1ListView);
+ for (int i = 0; i < d->visibleItems.count(); ++i) {
+ const FxListItem1 *listItem = d->visibleItems.at(i);
+ if(listItem->contains(x, y))
+ return listItem->index;
+ }
+
+ return -1;
+}
+
+void QDeclarative1ListView::componentComplete()
+{
+ Q_D(QDeclarative1ListView);
+ QDeclarative1Flickable::componentComplete();
+ updateSections();
+ d->updateHeader();
+ d->updateFooter();
+ if (d->isValid()) {
+ refill();
+ d->moveReason = QDeclarative1ListViewPrivate::SetIndex;
+ if (d->currentIndex < 0 && !d->currentIndexCleared)
+ d->updateCurrent(0);
+ else
+ d->updateCurrent(d->currentIndex);
+ if (d->highlight && d->currentItem) {
+ if (d->autoHighlight)
+ d->highlight->setPosition(d->currentItem->position());
+ d->updateTrackedItem();
+ }
+ d->moveReason = QDeclarative1ListViewPrivate::Other;
+ d->fixupPosition();
+ }
+}
+
+void QDeclarative1ListView::updateSections()
+{
+ Q_D(QDeclarative1ListView);
+ if (isComponentComplete() && d->model) {
+ QList<QByteArray> roles;
+ if (d->sectionCriteria && !d->sectionCriteria->property().isEmpty())
+ roles << d->sectionCriteria->property().toUtf8();
+ d->model->setWatchedRoles(roles);
+ d->updateSections();
+ if (d->itemCount)
+ d->layout();
+ }
+}
+
+void QDeclarative1ListView::refill()
+{
+ Q_D(QDeclarative1ListView);
+ if (d->isRightToLeft())
+ d->refill(-d->position()-d->size()+1, -d->position());
+ else
+ d->refill(d->position(), d->position()+d->size()-1);
+}
+
+void QDeclarative1ListView::trackedPositionChanged()
+{
+ Q_D(QDeclarative1ListView);
+ if (!d->trackedItem || !d->currentItem)
+ return;
+ if (d->moveReason == QDeclarative1ListViewPrivate::SetIndex) {
+ qreal trackedPos = qCeil(d->trackedItem->position());
+ qreal trackedSize = d->trackedItem->size();
+ if (d->trackedItem != d->currentItem) {
+ trackedPos -= d->currentItem->sectionSize();
+ trackedSize += d->currentItem->sectionSize();
+ }
+ qreal viewPos;
+ qreal highlightStart;
+ qreal highlightEnd;
+ if (d->isRightToLeft()) {
+ viewPos = -d->position()-d->size();
+ highlightStart = d->highlightRangeStartValid ? d->size()-d->highlightRangeEnd : d->highlightRangeStart;
+ highlightEnd = d->highlightRangeEndValid ? d->size()-d->highlightRangeStart : d->highlightRangeEnd;
+ } else {
+ viewPos = d->position();
+ highlightStart = d->highlightRangeStart;
+ highlightEnd = d->highlightRangeEnd;
+ }
+ qreal pos = viewPos;
+ if (d->haveHighlightRange) {
+ if (d->highlightRange == StrictlyEnforceRange) {
+ if (trackedPos > pos + highlightEnd - d->trackedItem->size())
+ pos = trackedPos - highlightEnd + d->trackedItem->size();
+ if (trackedPos < pos + highlightStart)
+ pos = trackedPos - highlightStart;
+ } else {
+ if (trackedPos < d->startPosition() + highlightStart) {
+ pos = d->startPosition();
+ } else if (d->trackedItem->endPosition() > d->endPosition() - d->size() + highlightEnd) {
+ pos = d->endPosition() - d->size() + 1;
+ if (pos < d->startPosition())
+ pos = d->startPosition();
+ } else {
+ if (trackedPos < viewPos + highlightStart) {
+ pos = trackedPos - highlightStart;
+ } else if (trackedPos > viewPos + highlightEnd - trackedSize) {
+ pos = trackedPos - highlightEnd + trackedSize;
+ }
+ }
+ }
+ } else {
+ if (trackedPos < viewPos && d->currentItem->position() < viewPos) {
+ pos = d->currentItem->position() < trackedPos ? trackedPos : d->currentItem->position();
+ } else if (d->trackedItem->endPosition() >= viewPos + d->size()
+ && d->currentItem->endPosition() >= viewPos + d->size()) {
+ if (d->trackedItem->endPosition() <= d->currentItem->endPosition()) {
+ pos = d->trackedItem->endPosition() - d->size() + 1;
+ if (trackedSize > d->size())
+ pos = trackedPos;
+ } else {
+ pos = d->currentItem->endPosition() - d->size() + 1;
+ if (d->currentItem->size() > d->size())
+ pos = d->currentItem->position();
+ }
+ }
+ }
+ if (viewPos != pos) {
+ cancelFlick();
+ d->calcVelocity = true;
+ d->setPosition(pos);
+ d->calcVelocity = false;
+ }
+ }
+}
+
+void QDeclarative1ListView::itemsInserted(int modelIndex, int count)
+{
+ Q_D(QDeclarative1ListView);
+ if (!isComponentComplete())
+ return;
+ d->updateUnrequestedIndexes();
+ d->moveReason = QDeclarative1ListViewPrivate::Other;
+
+ qreal tempPos = d->isRightToLeft() ? -d->position()-d->size() : d->position();
+ int index = d->visibleItems.count() ? d->mapFromModel(modelIndex) : 0;
+
+ if (index < 0) {
+ int i = d->visibleItems.count() - 1;
+ while (i > 0 && d->visibleItems.at(i)->index == -1)
+ --i;
+ if (i == 0 && d->visibleItems.first()->index == -1) {
+ // there are no visible items except items marked for removal
+ index = d->visibleItems.count();
+ } else if (d->visibleItems.at(i)->index + 1 == modelIndex
+ && d->visibleItems.at(i)->endPosition() < d->buffer+tempPos+d->size()-1) {
+ // Special case of appending an item to the model.
+ index = d->visibleItems.count();
+ } else {
+ if (modelIndex < d->visibleIndex) {
+ // Insert before visible items
+ d->visibleIndex += count;
+ for (int i = 0; i < d->visibleItems.count(); ++i) {
+ FxListItem1 *listItem = d->visibleItems.at(i);
+ if (listItem->index != -1 && listItem->index >= modelIndex)
+ listItem->index += count;
+ }
+ }
+ if (d->currentIndex >= modelIndex) {
+ // adjust current item index
+ d->currentIndex += count;
+ if (d->currentItem)
+ d->currentItem->index = d->currentIndex;
+ emit currentIndexChanged();
+ }
+ d->scheduleLayout();
+ d->itemCount += count;
+ emit countChanged();
+ return;
+ }
+ }
+
+ // index can be the next item past the end of the visible items list (i.e. appended)
+ int pos = 0;
+ if (d->visibleItems.count()) {
+ pos = index < d->visibleItems.count() ? d->visibleItems.at(index)->position()
+ : d->visibleItems.last()->endPosition()+d->spacing+1;
+ } else if (d->itemCount == 0 && d->header) {
+ pos = d->header->size();
+ }
+
+ int initialPos = pos;
+ int diff = 0;
+ QList<FxListItem1*> added;
+ bool addedVisible = false;
+ FxListItem1 *firstVisible = d->firstVisibleItem();
+ if (firstVisible && pos < firstVisible->position()) {
+ // Insert items before the visible item.
+ int insertionIdx = index;
+ int i = 0;
+ int from = tempPos - d->buffer;
+ for (i = count-1; i >= 0 && pos > from; --i) {
+ if (!addedVisible) {
+ d->scheduleLayout();
+ addedVisible = true;
+ }
+ FxListItem1 *item = d->createItem(modelIndex + i);
+ d->visibleItems.insert(insertionIdx, item);
+ pos -= item->size() + d->spacing;
+ item->setPosition(pos);
+ index++;
+ }
+ if (i >= 0) {
+ // If we didn't insert all our new items - anything
+ // before the current index is not visible - remove it.
+ while (insertionIdx--) {
+ FxListItem1 *item = d->visibleItems.takeFirst();
+ if (item->index != -1)
+ d->visibleIndex++;
+ d->releaseItem(item);
+ }
+ } else {
+ // adjust pos of items before inserted items.
+ for (int i = insertionIdx-1; i >= 0; i--) {
+ FxListItem1 *listItem = d->visibleItems.at(i);
+ listItem->setPosition(listItem->position() - (initialPos - pos));
+ }
+ }
+ } else {
+ int i = 0;
+ int to = d->buffer+tempPos+d->size()-1;
+ for (i = 0; i < count && pos <= to; ++i) {
+ if (!addedVisible) {
+ d->scheduleLayout();
+ addedVisible = true;
+ }
+ FxListItem1 *item = d->createItem(modelIndex + i);
+ d->visibleItems.insert(index, item);
+ item->setPosition(pos);
+ added.append(item);
+ pos += item->size() + d->spacing;
+ ++index;
+ }
+ if (i != count) {
+ // We didn't insert all our new items, which means anything
+ // beyond the current index is not visible - remove it.
+ while (d->visibleItems.count() > index)
+ d->releaseItem(d->visibleItems.takeLast());
+ }
+ diff = pos - initialPos;
+ }
+ if (d->itemCount && d->currentIndex >= modelIndex) {
+ // adjust current item index
+ d->currentIndex += count;
+ if (d->currentItem) {
+ d->currentItem->index = d->currentIndex;
+ d->currentItem->setPosition(d->currentItem->position() + diff);
+ }
+ emit currentIndexChanged();
+ } else if (!d->itemCount && (!d->currentIndex || (d->currentIndex < 0 && !d->currentIndexCleared))) {
+ d->updateCurrent(0);
+ }
+ // Update the indexes of the following visible items.
+ for (; index < d->visibleItems.count(); ++index) {
+ FxListItem1 *listItem = d->visibleItems.at(index);
+ if (d->currentItem && listItem->item != d->currentItem->item)
+ listItem->setPosition(listItem->position() + diff);
+ if (listItem->index != -1)
+ listItem->index += count;
+ }
+ // everything is in order now - emit add() signal
+ for (int j = 0; j < added.count(); ++j)
+ added.at(j)->attached->emitAdd();
+
+ d->updateSections();
+ d->itemCount += count;
+ emit countChanged();
+}
+
+void QDeclarative1ListView::itemsRemoved(int modelIndex, int count)
+{
+ Q_D(QDeclarative1ListView);
+ if (!isComponentComplete())
+ return;
+ d->moveReason = QDeclarative1ListViewPrivate::Other;
+ d->updateUnrequestedIndexes();
+ d->itemCount -= count;
+
+ FxListItem1 *firstVisible = d->firstVisibleItem();
+ int preRemovedSize = 0;
+ bool removedVisible = false;
+ // Remove the items from the visible list, skipping anything already marked for removal
+ QList<FxListItem1*>::Iterator it = d->visibleItems.begin();
+ while (it != d->visibleItems.end()) {
+ FxListItem1 *item = *it;
+ if (item->index == -1 || item->index < modelIndex) {
+ // already removed, or before removed items
+ ++it;
+ } else if (item->index >= modelIndex + count) {
+ // after removed items
+ item->index -= count;
+ ++it;
+ } else {
+ // removed item
+ if (!removedVisible) {
+ d->scheduleLayout();
+ removedVisible = true;
+ }
+ item->attached->emitRemove();
+ if (item->attached->delayRemove()) {
+ item->index = -1;
+ connect(item->attached, SIGNAL(delayRemoveChanged()), this, SLOT(destroyRemoved()), Qt::QueuedConnection);
+ ++it;
+ } else {
+ if (item == firstVisible)
+ firstVisible = 0;
+ if (firstVisible && item->position() < firstVisible->position())
+ preRemovedSize += item->size();
+ it = d->visibleItems.erase(it);
+ d->releaseItem(item);
+ }
+ }
+ }
+
+ if (firstVisible && d->visibleItems.first() != firstVisible)
+ d->visibleItems.first()->setPosition(d->visibleItems.first()->position() + preRemovedSize);
+
+ // fix current
+ if (d->currentIndex >= modelIndex + count) {
+ d->currentIndex -= count;
+ if (d->currentItem)
+ d->currentItem->index -= count;
+ emit currentIndexChanged();
+ } else if (d->currentIndex >= modelIndex && d->currentIndex < modelIndex + count) {
+ // current item has been removed.
+ d->currentItem->attached->setIsCurrentItem(false);
+ d->releaseItem(d->currentItem);
+ d->currentItem = 0;
+ d->currentIndex = -1;
+ if (d->itemCount)
+ d->updateCurrent(qMin(modelIndex, d->itemCount-1));
+ else
+ emit currentIndexChanged();
+ }
+
+ // update visibleIndex
+ bool haveVisibleIndex = false;
+ for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
+ if ((*it)->index != -1) {
+ d->visibleIndex = (*it)->index;
+ haveVisibleIndex = true;
+ break;
+ }
+ }
+
+ if (!haveVisibleIndex) {
+ d->timeline.clear();
+ if (removedVisible && d->itemCount == 0) {
+ d->visibleIndex = 0;
+ d->visiblePos = d->header ? d->header->size() : 0;
+ d->setPosition(0);
+ d->updateHeader();
+ d->updateFooter();
+ update();
+ } else {
+ if (modelIndex < d->visibleIndex)
+ d->visibleIndex = modelIndex+1;
+ d->visibleIndex = qMax(qMin(d->visibleIndex, d->itemCount-1), 0);
+ }
+ }
+
+ d->updateSections();
+ emit countChanged();
+}
+
+void QDeclarative1ListView::destroyRemoved()
+{
+ Q_D(QDeclarative1ListView);
+ for (QList<FxListItem1*>::Iterator it = d->visibleItems.begin();
+ it != d->visibleItems.end();) {
+ FxListItem1 *listItem = *it;
+ if (listItem->index == -1 && listItem->attached->delayRemove() == false) {
+ d->releaseItem(listItem);
+ it = d->visibleItems.erase(it);
+ } else {
+ ++it;
+ }
+ }
+
+ // Correct the positioning of the items
+ d->updateSections();
+ d->layout();
+}
+
+void QDeclarative1ListView::itemsMoved(int from, int to, int count)
+{
+ Q_D(QDeclarative1ListView);
+ if (!isComponentComplete())
+ return;
+ d->updateUnrequestedIndexes();
+
+ if (d->visibleItems.isEmpty()) {
+ refill();
+ return;
+ }
+
+ d->moveReason = QDeclarative1ListViewPrivate::Other;
+ FxListItem1 *firstVisible = d->firstVisibleItem();
+ qreal firstItemPos = firstVisible->position();
+ QHash<int,FxListItem1*> moved;
+ int moveBy = 0;
+
+ QList<FxListItem1*>::Iterator it = d->visibleItems.begin();
+ while (it != d->visibleItems.end()) {
+ FxListItem1 *item = *it;
+ if (item->index >= from && item->index < from + count) {
+ // take the items that are moving
+ item->index += (to-from);
+ moved.insert(item->index, item);
+ if (item->position() < firstItemPos)
+ moveBy += item->size();
+ it = d->visibleItems.erase(it);
+ } else {
+ // move everything after the moved items.
+ if (item->index > from && item->index != -1)
+ item->index -= count;
+ ++it;
+ }
+ }
+
+ int remaining = count;
+ int endIndex = d->visibleIndex;
+ it = d->visibleItems.begin();
+ while (it != d->visibleItems.end()) {
+ FxListItem1 *item = *it;
+ if (remaining && item->index >= to && item->index < to + count) {
+ // place items in the target position, reusing any existing items
+ FxListItem1 *movedItem = moved.take(item->index);
+ if (!movedItem)
+ movedItem = d->createItem(item->index);
+ if (item->index <= firstVisible->index)
+ moveBy -= movedItem->size();
+ it = d->visibleItems.insert(it, movedItem);
+ ++it;
+ --remaining;
+ } else {
+ if (item->index != -1) {
+ if (item->index >= to) {
+ // update everything after the moved items.
+ item->index += count;
+ }
+ endIndex = item->index;
+ }
+ ++it;
+ }
+ }
+
+ // If we have moved items to the end of the visible items
+ // then add any existing moved items that we have
+ while (FxListItem1 *item = moved.take(endIndex+1)) {
+ d->visibleItems.append(item);
+ ++endIndex;
+ }
+
+ // update visibleIndex
+ for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
+ if ((*it)->index != -1) {
+ d->visibleIndex = (*it)->index;
+ break;
+ }
+ }
+
+ // Fix current index
+ if (d->currentIndex >= 0 && d->currentItem) {
+ int oldCurrent = d->currentIndex;
+ d->currentIndex = d->model->indexOf(d->currentItem->item, this);
+ if (oldCurrent != d->currentIndex) {
+ d->currentItem->index = d->currentIndex;
+ emit currentIndexChanged();
+ }
+ }
+
+ // Whatever moved items remain are no longer visible items.
+ while (moved.count()) {
+ int idx = moved.begin().key();
+ FxListItem1 *item = moved.take(idx);
+ if (d->currentItem && item->item == d->currentItem->item)
+ item->setPosition(d->positionAt(idx));
+ d->releaseItem(item);
+ }
+
+ // Ensure we don't cause an ugly list scroll.
+ d->visibleItems.first()->setPosition(d->visibleItems.first()->position() + moveBy);
+
+ d->updateSections();
+ d->layout();
+}
+
+void QDeclarative1ListView::itemsChanged(int, int)
+{
+ Q_D(QDeclarative1ListView);
+ d->updateSections();
+ d->layout();
+}
+
+void QDeclarative1ListView::modelReset()
+{
+ Q_D(QDeclarative1ListView);
+ d->moveReason = QDeclarative1ListViewPrivate::SetIndex;
+ d->regenerate();
+ if (d->highlight && d->currentItem) {
+ if (d->autoHighlight)
+ d->highlight->setPosition(d->currentItem->position());
+ d->updateTrackedItem();
+ }
+ d->moveReason = QDeclarative1ListViewPrivate::Other;
+ emit countChanged();
+}
+
+void QDeclarative1ListView::createdItem(int index, QDeclarativeItem *item)
+{
+ Q_D(QDeclarative1ListView);
+ if (d->requestedIndex != index) {
+ item->setParentItem(contentItem());
+ d->unrequestedItems.insert(item, index);
+ if (d->orient == QDeclarative1ListView::Vertical) {
+ item->setY(d->positionAt(index));
+ } else {
+ if (d->isRightToLeft())
+ item->setX(-d->positionAt(index)-item->width());
+ else
+ item->setX(d->positionAt(index));
+ }
+ }
+}
+
+void QDeclarative1ListView::destroyingItem(QDeclarativeItem *item)
+{
+ Q_D(QDeclarative1ListView);
+ d->unrequestedItems.remove(item);
+}
+
+void QDeclarative1ListView::animStopped()
+{
+ Q_D(QDeclarative1ListView);
+ d->bufferMode = QDeclarative1ListViewPrivate::NoBuffer;
+ if (d->haveHighlightRange && d->highlightRange == QDeclarative1ListView::StrictlyEnforceRange)
+ d->updateHighlight();
+}
+
+QDeclarative1ListViewAttached *QDeclarative1ListView::qmlAttachedProperties(QObject *obj)
+{
+ return new QDeclarative1ListViewAttached(obj);
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/graphicsitems/qdeclarativelistview_p.h b/src/qtquick1/graphicsitems/qdeclarativelistview_p.h
new file mode 100644
index 0000000000..dc1ff3371f
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativelistview_p.h
@@ -0,0 +1,371 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVELISTVIEW_H
+#define QDECLARATIVELISTVIEW_H
+
+#include "private/qdeclarativeflickable_p.h"
+#include "QtDeclarative/private/qdeclarativeguard_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_AUTOTEST_EXPORT QDeclarative1ViewSection : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString property READ property WRITE setProperty NOTIFY propertyChanged)
+ Q_PROPERTY(SectionCriteria criteria READ criteria WRITE setCriteria NOTIFY criteriaChanged)
+ Q_PROPERTY(QDeclarativeComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
+ Q_ENUMS(SectionCriteria)
+public:
+ QDeclarative1ViewSection(QObject *parent=0) : QObject(parent), m_criteria(FullString), m_delegate(0) {}
+
+ QString property() const { return m_property; }
+ void setProperty(const QString &);
+
+ enum SectionCriteria { FullString, FirstCharacter };
+ SectionCriteria criteria() const { return m_criteria; }
+ void setCriteria(SectionCriteria);
+
+ QDeclarativeComponent *delegate() const { return m_delegate; }
+ void setDelegate(QDeclarativeComponent *delegate);
+
+ QString sectionString(const QString &value);
+
+Q_SIGNALS:
+ void propertyChanged();
+ void criteriaChanged();
+ void delegateChanged();
+
+private:
+ QString m_property;
+ SectionCriteria m_criteria;
+ QDeclarativeComponent *m_delegate;
+};
+
+
+class QDeclarative1VisualModel;
+class QDeclarative1ListViewAttached;
+class QDeclarative1ListViewPrivate;
+class Q_AUTOTEST_EXPORT QDeclarative1ListView : public QDeclarative1Flickable
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarative1ListView)
+
+ Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged)
+ Q_PROPERTY(QDeclarativeComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
+ Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
+ Q_PROPERTY(QDeclarativeItem *currentItem READ currentItem NOTIFY currentIndexChanged)
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+
+ Q_PROPERTY(QDeclarativeComponent *highlight READ highlight WRITE setHighlight NOTIFY highlightChanged)
+ Q_PROPERTY(QDeclarativeItem *highlightItem READ highlightItem NOTIFY highlightItemChanged)
+ Q_PROPERTY(bool highlightFollowsCurrentItem READ highlightFollowsCurrentItem WRITE setHighlightFollowsCurrentItem NOTIFY highlightFollowsCurrentItemChanged)
+ Q_PROPERTY(qreal highlightMoveSpeed READ highlightMoveSpeed WRITE setHighlightMoveSpeed NOTIFY highlightMoveSpeedChanged)
+ Q_PROPERTY(int highlightMoveDuration READ highlightMoveDuration WRITE setHighlightMoveDuration NOTIFY highlightMoveDurationChanged)
+ Q_PROPERTY(qreal highlightResizeSpeed READ highlightResizeSpeed WRITE setHighlightResizeSpeed NOTIFY highlightResizeSpeedChanged)
+ Q_PROPERTY(int highlightResizeDuration READ highlightResizeDuration WRITE setHighlightResizeDuration NOTIFY highlightResizeDurationChanged)
+
+ Q_PROPERTY(qreal preferredHighlightBegin READ preferredHighlightBegin WRITE setPreferredHighlightBegin NOTIFY preferredHighlightBeginChanged RESET resetPreferredHighlightBegin)
+ Q_PROPERTY(qreal preferredHighlightEnd READ preferredHighlightEnd WRITE setPreferredHighlightEnd NOTIFY preferredHighlightEndChanged RESET resetPreferredHighlightEnd)
+ Q_PROPERTY(HighlightRangeMode highlightRangeMode READ highlightRangeMode WRITE setHighlightRangeMode NOTIFY highlightRangeModeChanged)
+
+ Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing NOTIFY spacingChanged)
+ Q_PROPERTY(Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged)
+ Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged REVISION 1)
+ Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged REVISION 1)
+ Q_PROPERTY(bool keyNavigationWraps READ isWrapEnabled WRITE setWrapEnabled NOTIFY keyNavigationWrapsChanged)
+ Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer NOTIFY cacheBufferChanged)
+ Q_PROPERTY(QDeclarative1ViewSection *section READ sectionCriteria CONSTANT)
+ Q_PROPERTY(QString currentSection READ currentSection NOTIFY currentSectionChanged)
+
+ Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged)
+
+ Q_PROPERTY(QDeclarativeComponent *header READ header WRITE setHeader NOTIFY headerChanged)
+ Q_PROPERTY(QDeclarativeComponent *footer READ footer WRITE setFooter NOTIFY footerChanged)
+
+ Q_ENUMS(HighlightRangeMode)
+ Q_ENUMS(Orientation)
+ Q_ENUMS(SnapMode)
+ Q_ENUMS(PositionMode)
+ Q_CLASSINFO("DefaultProperty", "data")
+
+public:
+ QDeclarative1ListView(QDeclarativeItem *parent=0);
+ ~QDeclarative1ListView();
+
+ QVariant model() const;
+ void setModel(const QVariant &);
+
+ QDeclarativeComponent *delegate() const;
+ void setDelegate(QDeclarativeComponent *);
+
+ int currentIndex() const;
+ void setCurrentIndex(int idx);
+
+ QDeclarativeItem *currentItem();
+ QDeclarativeItem *highlightItem();
+ int count() const;
+
+ QDeclarativeComponent *highlight() const;
+ void setHighlight(QDeclarativeComponent *highlight);
+
+ bool highlightFollowsCurrentItem() const;
+ void setHighlightFollowsCurrentItem(bool);
+
+ enum HighlightRangeMode { NoHighlightRange, ApplyRange, StrictlyEnforceRange };
+ HighlightRangeMode highlightRangeMode() const;
+ void setHighlightRangeMode(HighlightRangeMode mode);
+
+ qreal preferredHighlightBegin() const;
+ void setPreferredHighlightBegin(qreal);
+ void resetPreferredHighlightBegin();
+
+ qreal preferredHighlightEnd() const;
+ void setPreferredHighlightEnd(qreal);
+ void resetPreferredHighlightEnd();
+
+ qreal spacing() const;
+ void setSpacing(qreal spacing);
+
+ enum Orientation { Horizontal = Qt::Horizontal, Vertical = Qt::Vertical };
+ Orientation orientation() const;
+ void setOrientation(Orientation);
+
+ Qt::LayoutDirection layoutDirection() const;
+ void setLayoutDirection(Qt::LayoutDirection);
+ Qt::LayoutDirection effectiveLayoutDirection() const;
+
+ bool isWrapEnabled() const;
+ void setWrapEnabled(bool);
+
+ int cacheBuffer() const;
+ void setCacheBuffer(int);
+
+ QDeclarative1ViewSection *sectionCriteria();
+ QString currentSection() const;
+
+ qreal highlightMoveSpeed() const;
+ void setHighlightMoveSpeed(qreal);
+
+ int highlightMoveDuration() const;
+ void setHighlightMoveDuration(int);
+
+ qreal highlightResizeSpeed() const;
+ void setHighlightResizeSpeed(qreal);
+
+ int highlightResizeDuration() const;
+ void setHighlightResizeDuration(int);
+
+ enum SnapMode { NoSnap, SnapToItem, SnapOneItem };
+ SnapMode snapMode() const;
+ void setSnapMode(SnapMode mode);
+
+ QDeclarativeComponent *footer() const;
+ void setFooter(QDeclarativeComponent *);
+
+ QDeclarativeComponent *header() const;
+ void setHeader(QDeclarativeComponent *);
+
+ virtual void setContentX(qreal pos);
+ virtual void setContentY(qreal pos);
+
+ static QDeclarative1ListViewAttached *qmlAttachedProperties(QObject *);
+
+ enum PositionMode { Beginning, Center, End, Visible, Contain };
+
+ Q_INVOKABLE void positionViewAtIndex(int index, int mode);
+ Q_INVOKABLE int indexAt(qreal x, qreal y) const;
+ Q_INVOKABLE Q_REVISION(1) void positionViewAtBeginning();
+ Q_INVOKABLE Q_REVISION(1) void positionViewAtEnd();
+
+public Q_SLOTS:
+ void incrementCurrentIndex();
+ void decrementCurrentIndex();
+
+Q_SIGNALS:
+ void countChanged();
+ void spacingChanged();
+ void orientationChanged();
+ Q_REVISION(1) void layoutDirectionChanged();
+ Q_REVISION(1) void effectiveLayoutDirectionChanged();
+ void currentIndexChanged();
+ void currentSectionChanged();
+ void highlightMoveSpeedChanged();
+ void highlightMoveDurationChanged();
+ void highlightResizeSpeedChanged();
+ void highlightResizeDurationChanged();
+ void highlightChanged();
+ void highlightItemChanged();
+ void modelChanged();
+ void delegateChanged();
+ void highlightFollowsCurrentItemChanged();
+ void preferredHighlightBeginChanged();
+ void preferredHighlightEndChanged();
+ void highlightRangeModeChanged();
+ void keyNavigationWrapsChanged();
+ void cacheBufferChanged();
+ void snapModeChanged();
+ void headerChanged();
+ void footerChanged();
+
+protected:
+ virtual bool event(QEvent *event);
+ virtual void viewportMoved();
+ virtual qreal minYExtent() const;
+ virtual qreal maxYExtent() const;
+ virtual qreal minXExtent() const;
+ virtual qreal maxXExtent() const;
+ virtual void keyPressEvent(QKeyEvent *);
+ virtual void geometryChanged(const QRectF &newGeometry,const QRectF &oldGeometry);
+ virtual void componentComplete();
+
+private Q_SLOTS:
+ void updateSections();
+ void refill();
+ void trackedPositionChanged();
+ void itemsInserted(int index, int count);
+ void itemsRemoved(int index, int count);
+ void itemsMoved(int from, int to, int count);
+ void itemsChanged(int index, int count);
+ void modelReset();
+ void destroyRemoved();
+ void createdItem(int index, QDeclarativeItem *item);
+ void destroyingItem(QDeclarativeItem *item);
+ void animStopped();
+};
+
+class QDeclarative1ListViewAttached : public QObject
+{
+ Q_OBJECT
+public:
+ QDeclarative1ListViewAttached(QObject *parent)
+ : QObject(parent), m_view(0), m_isCurrent(false), m_delayRemove(false) {}
+ ~QDeclarative1ListViewAttached() {}
+
+ Q_PROPERTY(QDeclarative1ListView *view READ view NOTIFY viewChanged)
+ QDeclarative1ListView *view() { return m_view; }
+ void setView(QDeclarative1ListView *view) {
+ if (view != m_view) {
+ m_view = view;
+ emit viewChanged();
+ }
+ }
+
+ Q_PROPERTY(bool isCurrentItem READ isCurrentItem NOTIFY currentItemChanged)
+ bool isCurrentItem() const { return m_isCurrent; }
+ void setIsCurrentItem(bool c) {
+ if (m_isCurrent != c) {
+ m_isCurrent = c;
+ emit currentItemChanged();
+ }
+ }
+
+ Q_PROPERTY(QString previousSection READ prevSection NOTIFY prevSectionChanged)
+ QString prevSection() const { return m_prevSection; }
+ void setPrevSection(const QString &sect) {
+ if (m_prevSection != sect) {
+ m_prevSection = sect;
+ emit prevSectionChanged();
+ }
+ }
+
+ Q_PROPERTY(QString nextSection READ nextSection NOTIFY nextSectionChanged)
+ QString nextSection() const { return m_nextSection; }
+ void setNextSection(const QString &sect) {
+ if (m_nextSection != sect) {
+ m_nextSection = sect;
+ emit nextSectionChanged();
+ }
+ }
+
+ Q_PROPERTY(QString section READ section NOTIFY sectionChanged)
+ QString section() const { return m_section; }
+ void setSection(const QString &sect) {
+ if (m_section != sect) {
+ m_section = sect;
+ emit sectionChanged();
+ }
+ }
+
+ Q_PROPERTY(bool delayRemove READ delayRemove WRITE setDelayRemove NOTIFY delayRemoveChanged)
+ bool delayRemove() const { return m_delayRemove; }
+ void setDelayRemove(bool delay) {
+ if (m_delayRemove != delay) {
+ m_delayRemove = delay;
+ emit delayRemoveChanged();
+ }
+ }
+
+ void emitAdd() { emit add(); }
+ void emitRemove() { emit remove(); }
+
+Q_SIGNALS:
+ void currentItemChanged();
+ void sectionChanged();
+ void prevSectionChanged();
+ void nextSectionChanged();
+ void delayRemoveChanged();
+ void add();
+ void remove();
+ void viewChanged();
+
+public:
+ QDeclarativeGuard<QDeclarative1ListView> m_view;
+ mutable QString m_section;
+ QString m_prevSection;
+ QString m_nextSection;
+ bool m_isCurrent : 1;
+ bool m_delayRemove : 1;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPEINFO(QDeclarative1ListView, QML_HAS_ATTACHED_PROPERTIES)
+QML_DECLARE_TYPE(QDeclarative1ListView)
+QML_DECLARE_TYPE(QDeclarative1ViewSection)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/qtquick1/graphicsitems/qdeclarativeloader.cpp b/src/qtquick1/graphicsitems/qdeclarativeloader.cpp
new file mode 100644
index 0000000000..92b34d7001
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativeloader.cpp
@@ -0,0 +1,601 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativeloader_p_p.h"
+
+#include <QtDeclarative/qdeclarativeinfo.h>
+#include <QtDeclarative/private/qdeclarativeengine_p.h>
+#include <QtDeclarative/private/qdeclarativeglobal_p.h>
+
+QT_BEGIN_NAMESPACE
+
+
+
+QDeclarative1LoaderPrivate::QDeclarative1LoaderPrivate()
+ : item(0), component(0), ownComponent(false), updatingSize(false),
+ itemWidthValid(false), itemHeightValid(false)
+{
+}
+
+QDeclarative1LoaderPrivate::~QDeclarative1LoaderPrivate()
+{
+}
+
+void QDeclarative1LoaderPrivate::itemGeometryChanged(QDeclarativeItem *resizeItem, const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ if (resizeItem == item) {
+ if (!updatingSize && newGeometry.width() != oldGeometry.width())
+ itemWidthValid = true;
+ if (!updatingSize && newGeometry.height() != oldGeometry.height())
+ itemHeightValid = true;
+ _q_updateSize(false);
+ }
+ QDeclarativeItemChangeListener::itemGeometryChanged(resizeItem, newGeometry, oldGeometry);
+}
+
+void QDeclarative1LoaderPrivate::clear()
+{
+ if (ownComponent) {
+ component->deleteLater();
+ component = 0;
+ ownComponent = false;
+ }
+ source = QUrl();
+
+ if (item) {
+ if (QDeclarativeItem *qmlItem = qobject_cast<QDeclarativeItem*>(item)) {
+ QDeclarativeItemPrivate *p =
+ static_cast<QDeclarativeItemPrivate *>(QGraphicsItemPrivate::get(qmlItem));
+ p->removeItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
+ }
+
+ // We can't delete immediately because our item may have triggered
+ // the Loader to load a different item.
+ if (item->scene()) {
+ item->scene()->removeItem(item);
+ } else {
+ item->setParentItem(0);
+ item->setVisible(false);
+ }
+ item->deleteLater();
+ item = 0;
+ }
+}
+
+void QDeclarative1LoaderPrivate::initResize()
+{
+ Q_Q(QDeclarative1Loader);
+ if (QDeclarativeItem *qmlItem = qobject_cast<QDeclarativeItem*>(item)) {
+ QDeclarativeItemPrivate *p =
+ static_cast<QDeclarativeItemPrivate *>(QGraphicsItemPrivate::get(qmlItem));
+ p->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
+ // We may override the item's size, so we need to remember
+ // whether the item provided its own valid size.
+ itemWidthValid = p->widthValid;
+ itemHeightValid = p->heightValid;
+ } else if (item && item->isWidget()) {
+ QGraphicsWidget *widget = static_cast<QGraphicsWidget*>(item);
+ widget->installEventFilter(q);
+ }
+ _q_updateSize();
+}
+
+/*!
+ \qmlclass Loader QDeclarative1Loader
+ \ingroup qml-utility-elements
+ \since 4.7
+ \inherits Item
+
+ \brief The Loader item allows dynamically loading an Item-based
+ subtree from a URL or Component.
+
+ Loader is used to dynamically load visual QML components. It can load a
+ QML file (using the \l source property) or a \l Component object (using
+ the \l sourceComponent property). It is useful for delaying the creation
+ of a component until it is required: for example, when a component should
+ be created on demand, or when a component should not be created
+ unnecessarily for performance reasons.
+
+ Here is a Loader that loads "Page1.qml" as a component when the
+ \l MouseArea is clicked:
+
+ \snippet doc/src/snippets/declarative/loader/simple.qml 0
+
+ The loaded item can be accessed using the \l item property.
+
+ If the \l source or \l sourceComponent changes, any previously instantiated
+ items are destroyed. Setting \l source to an empty string or setting
+ \l sourceComponent to \c undefined destroys the currently loaded item,
+ freeing resources and leaving the Loader empty.
+
+ \section2 Loader sizing behavior
+
+ Loader is like any other visual item and must be positioned and sized
+ accordingly to become visible.
+
+ \list
+ \o If an explicit size is not specified for the Loader, the Loader
+ is automatically resized to the size of the loaded item once the
+ component is loaded.
+ \o If the size of the Loader is specified explicitly by setting
+ the width, height or by anchoring, the loaded item will be resized
+ to the size of the Loader.
+ \endlist
+
+ In both scenarios the size of the item and the Loader are identical.
+ This ensures that anchoring to the Loader is equivalent to anchoring
+ to the loaded item.
+
+ \table
+ \row
+ \o sizeloader.qml
+ \o sizeitem.qml
+ \row
+ \o \snippet doc/src/snippets/declarative/loader/sizeloader.qml 0
+ \o \snippet doc/src/snippets/declarative/loader/sizeitem.qml 0
+ \row
+ \o The red rectangle will be sized to the size of the root item.
+ \o The red rectangle will be 50x50, centered in the root item.
+ \endtable
+
+
+ \section2 Receiving signals from loaded items
+
+ Any signals emitted from the loaded item can be received using the
+ \l Connections element. For example, the following \c application.qml
+ loads \c MyItem.qml, and is able to receive the \c message signal from
+ the loaded item through a \l Connections object:
+
+ \table
+ \row
+ \o application.qml
+ \o MyItem.qml
+ \row
+ \o \snippet doc/src/snippets/declarative/loader/connections.qml 0
+ \o \snippet doc/src/snippets/declarative/loader/MyItem.qml 0
+ \endtable
+
+ Alternatively, since \c MyItem.qml is loaded within the scope of the
+ Loader, it could also directly call any function defined in the Loader or
+ its parent \l Item.
+
+
+ \section2 Focus and key events
+
+ Loader is a focus scope. Its \l {Item::}{focus} property must be set to
+ \c true for any of its children to get the \e {active focus}. (See
+ \l{qmlfocus#Acquiring Focus and Focus Scopes}{the focus documentation page}
+ for more details.) Any key events received in the loaded item should likely
+ also be \l {KeyEvent::}{accepted} so they are not propagated to the Loader.
+
+ For example, the following \c application.qml loads \c KeyReader.qml when
+ the \l MouseArea is clicked. Notice the \l {Item::}{focus} property is
+ set to \c true for the Loader as well as the \l Item in the dynamically
+ loaded object:
+
+ \table
+ \row
+ \o application.qml
+ \o KeyReader.qml
+ \row
+ \o \snippet doc/src/snippets/declarative/loader/focus.qml 0
+ \o \snippet doc/src/snippets/declarative/loader/KeyReader.qml 0
+ \endtable
+
+ Once \c KeyReader.qml is loaded, it accepts key events and sets
+ \c event.accepted to \c true so that the event is not propagated to the
+ parent \l Rectangle.
+
+ \sa {dynamic-object-creation}{Dynamic Object Creation}
+*/
+
+QDeclarative1Loader::QDeclarative1Loader(QDeclarativeItem *parent)
+ : QDeclarative1ImplicitSizeItem(*(new QDeclarative1LoaderPrivate), parent)
+{
+ Q_D(QDeclarative1Loader);
+ d->flags |= QGraphicsItem::ItemIsFocusScope;
+}
+
+QDeclarative1Loader::~QDeclarative1Loader()
+{
+ Q_D(QDeclarative1Loader);
+ if (d->item) {
+ if (QDeclarativeItem *qmlItem = qobject_cast<QDeclarativeItem*>(d->item)) {
+ QDeclarativeItemPrivate *p =
+ static_cast<QDeclarativeItemPrivate *>(QGraphicsItemPrivate::get(qmlItem));
+ p->removeItemChangeListener(d, QDeclarativeItemPrivate::Geometry);
+ }
+ }
+}
+
+/*!
+ \qmlproperty url Loader::source
+ This property holds the URL of the QML component to instantiate.
+
+ Note the QML component must be an \l{Item}-based component. The loader
+ cannot load non-visual components.
+
+ To unload the currently loaded item, set this property to an empty string,
+ or set \l sourceComponent to \c undefined. Setting \c source to a
+ new URL will also cause the item created by the previous URL to be unloaded.
+
+ \sa sourceComponent, status, progress
+*/
+QUrl QDeclarative1Loader::source() const
+{
+ Q_D(const QDeclarative1Loader);
+ return d->source;
+}
+
+void QDeclarative1Loader::setSource(const QUrl &url)
+{
+ Q_D(QDeclarative1Loader);
+ if (d->source == url)
+ return;
+
+ d->clear();
+
+ d->source = url;
+
+ if (d->source.isEmpty()) {
+ emit sourceChanged();
+ emit statusChanged();
+ emit progressChanged();
+ emit itemChanged();
+ return;
+ }
+
+ d->component = new QDeclarativeComponent(qmlEngine(this), d->source, this);
+ d->ownComponent = true;
+
+ if (isComponentComplete())
+ d->load();
+}
+
+/*!
+ \qmlproperty Component Loader::sourceComponent
+ This property holds the \l{Component} to instantiate.
+
+ \qml
+ Item {
+ Component {
+ id: redSquare
+ Rectangle { color: "red"; width: 10; height: 10 }
+ }
+
+ Loader { sourceComponent: redSquare }
+ Loader { sourceComponent: redSquare; x: 10 }
+ }
+ \endqml
+
+ To unload the currently loaded item, set this property to an empty string
+ or \c undefined.
+
+ \sa source, progress
+*/
+
+QDeclarativeComponent *QDeclarative1Loader::sourceComponent() const
+{
+ Q_D(const QDeclarative1Loader);
+ return d->component;
+}
+
+void QDeclarative1Loader::setSourceComponent(QDeclarativeComponent *comp)
+{
+ Q_D(QDeclarative1Loader);
+ if (comp == d->component)
+ return;
+
+ d->clear();
+
+ d->component = comp;
+ d->ownComponent = false;
+
+ if (!d->component) {
+ emit sourceChanged();
+ emit statusChanged();
+ emit progressChanged();
+ emit itemChanged();
+ return;
+ }
+
+ if (isComponentComplete())
+ d->load();
+}
+
+void QDeclarative1Loader::resetSourceComponent()
+{
+ setSourceComponent(0);
+}
+
+void QDeclarative1LoaderPrivate::load()
+{
+ Q_Q(QDeclarative1Loader);
+
+ if (!q->isComponentComplete() || !component)
+ return;
+
+ if (!component->isLoading()) {
+ _q_sourceLoaded();
+ } else {
+ QObject::connect(component, SIGNAL(statusChanged(QDeclarativeComponent::Status)),
+ q, SLOT(_q_sourceLoaded()));
+ QObject::connect(component, SIGNAL(progressChanged(qreal)),
+ q, SIGNAL(progressChanged()));
+ emit q->statusChanged();
+ emit q->progressChanged();
+ emit q->sourceChanged();
+ emit q->itemChanged();
+ }
+}
+
+void QDeclarative1LoaderPrivate::_q_sourceLoaded()
+{
+ Q_Q(QDeclarative1Loader);
+
+ if (component) {
+ if (!component->errors().isEmpty()) {
+ QDeclarativeEnginePrivate::warning(qmlEngine(q), component->errors());
+ emit q->sourceChanged();
+ emit q->statusChanged();
+ emit q->progressChanged();
+ return;
+ }
+
+ QDeclarativeContext *creationContext = component->creationContext();
+ if (!creationContext) creationContext = qmlContext(q);
+ QDeclarativeContext *ctxt = new QDeclarativeContext(creationContext);
+ ctxt->setContextObject(q);
+
+ QDeclarativeGuard<QDeclarativeComponent> c = component;
+ QObject *obj = component->beginCreate(ctxt);
+ if (component != c) {
+ // component->create could trigger a change in source that causes
+ // component to be set to something else. In that case we just
+ // need to cleanup.
+ if (c)
+ c->completeCreate();
+ delete obj;
+ delete ctxt;
+ return;
+ }
+ if (obj) {
+ item = qobject_cast<QGraphicsObject *>(obj);
+ if (item) {
+ QDeclarative_setParent_noEvent(ctxt, obj);
+ QDeclarative_setParent_noEvent(item, q);
+ item->setParentItem(q);
+// item->setFocus(true);
+ initResize();
+ } else {
+ qmlInfo(q) << QDeclarative1Loader::tr("Loader does not support loading non-visual elements.");
+ delete obj;
+ delete ctxt;
+ }
+ } else {
+ if (!component->errors().isEmpty())
+ QDeclarativeEnginePrivate::warning(qmlEngine(q), component->errors());
+ delete obj;
+ delete ctxt;
+ source = QUrl();
+ }
+ component->completeCreate();
+ emit q->sourceChanged();
+ emit q->statusChanged();
+ emit q->progressChanged();
+ emit q->itemChanged();
+ emit q->loaded();
+ }
+}
+
+/*!
+ \qmlproperty enumeration Loader::status
+
+ This property holds the status of QML loading. It can be one of:
+ \list
+ \o Loader.Null - no QML source has been set
+ \o Loader.Ready - the QML source has been loaded
+ \o Loader.Loading - the QML source is currently being loaded
+ \o Loader.Error - an error occurred while loading the QML source
+ \endlist
+
+ Use this status to provide an update or respond to the status change in some way.
+ For example, you could:
+
+ \list
+ \o Trigger a state change:
+ \qml
+ State { name: 'loaded'; when: loader.status == Loader.Ready }
+ \endqml
+
+ \o Implement an \c onStatusChanged signal handler:
+ \qml
+ Loader {
+ id: loader
+ onStatusChanged: if (loader.status == Loader.Ready) console.log('Loaded')
+ }
+ \endqml
+
+ \o Bind to the status value:
+ \qml
+ Text { text: loader.status == Loader.Ready ? 'Loaded' : 'Not loaded' }
+ \endqml
+ \endlist
+
+ Note that if the source is a local file, the status will initially be Ready (or Error). While
+ there will be no onStatusChanged signal in that case, the onLoaded will still be invoked.
+
+ \sa progress
+*/
+
+QDeclarative1Loader::Status QDeclarative1Loader::status() const
+{
+ Q_D(const QDeclarative1Loader);
+
+ if (d->component)
+ return static_cast<QDeclarative1Loader::Status>(d->component->status());
+
+ if (d->item)
+ return Ready;
+
+ return d->source.isEmpty() ? Null : Error;
+}
+
+void QDeclarative1Loader::componentComplete()
+{
+ Q_D(QDeclarative1Loader);
+
+ QDeclarativeItem::componentComplete();
+ d->load();
+}
+
+
+/*!
+ \qmlsignal Loader::onLoaded()
+
+ This handler is called when the \l status becomes \c Loader.Ready, or on successful
+ initial load.
+*/
+
+
+/*!
+\qmlproperty real Loader::progress
+
+This property holds the progress of loading QML data from the network, from
+0.0 (nothing loaded) to 1.0 (finished). Most QML files are quite small, so
+this value will rapidly change from 0 to 1.
+
+\sa status
+*/
+qreal QDeclarative1Loader::progress() const
+{
+ Q_D(const QDeclarative1Loader);
+
+ if (d->item)
+ return 1.0;
+
+ if (d->component)
+ return d->component->progress();
+
+ return 0.0;
+}
+
+void QDeclarative1LoaderPrivate::_q_updateSize(bool loaderGeometryChanged)
+{
+ Q_Q(QDeclarative1Loader);
+ if (!item || updatingSize)
+ return;
+
+ updatingSize = true;
+ if (QDeclarativeItem *qmlItem = qobject_cast<QDeclarativeItem*>(item)) {
+ if (!itemWidthValid)
+ q->setImplicitWidth(qmlItem->implicitWidth());
+ else
+ q->setImplicitWidth(qmlItem->width());
+ if (loaderGeometryChanged && q->widthValid())
+ qmlItem->setWidth(q->width());
+ if (!itemHeightValid)
+ q->setImplicitHeight(qmlItem->implicitHeight());
+ else
+ q->setImplicitHeight(qmlItem->height());
+ if (loaderGeometryChanged && q->heightValid())
+ qmlItem->setHeight(q->height());
+ } else if (item && item->isWidget()) {
+ QGraphicsWidget *widget = static_cast<QGraphicsWidget*>(item);
+ QSizeF widgetSize = widget->size();
+ q->setImplicitWidth(widgetSize.width());
+ if (loaderGeometryChanged && q->widthValid())
+ widgetSize.setWidth(q->width());
+ q->setImplicitHeight(widgetSize.height());
+ if (loaderGeometryChanged && q->heightValid())
+ widgetSize.setHeight(q->height());
+ if (widget->size() != widgetSize)
+ widget->resize(widgetSize);
+ }
+ updatingSize = false;
+}
+
+/*!
+ \qmlproperty Item Loader::item
+ This property holds the top-level item that is currently loaded.
+*/
+QGraphicsObject *QDeclarative1Loader::item() const
+{
+ Q_D(const QDeclarative1Loader);
+ return d->item;
+}
+
+void QDeclarative1Loader::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ Q_D(QDeclarative1Loader);
+ if (newGeometry != oldGeometry) {
+ d->_q_updateSize();
+ }
+ QDeclarativeItem::geometryChanged(newGeometry, oldGeometry);
+}
+
+QVariant QDeclarative1Loader::itemChange(GraphicsItemChange change, const QVariant &value)
+{
+ Q_D(QDeclarative1Loader);
+ if (change == ItemSceneHasChanged) {
+ if (d->item && d->item->isWidget()) {
+ d->item->removeEventFilter(this);
+ d->item->installEventFilter(this);
+ }
+ }
+ return QDeclarativeItem::itemChange(change, value);
+}
+
+bool QDeclarative1Loader::eventFilter(QObject *watched, QEvent *e)
+{
+ Q_D(QDeclarative1Loader);
+ if (watched == d->item && e->type() == QEvent::GraphicsSceneResize) {
+ if (d->item && d->item->isWidget())
+ d->_q_updateSize(false);
+ }
+ return QDeclarativeItem::eventFilter(watched, e);
+}
+
+#include <moc_qdeclarativeloader_p.cpp>
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/graphicsitems/qdeclarativeloader_p.h b/src/qtquick1/graphicsitems/qdeclarativeloader_p.h
new file mode 100644
index 0000000000..e2398005fd
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativeloader_p.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVELOADER_H
+#define QDECLARATIVELOADER_H
+
+#include "qdeclarativeimplicitsizeitem_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarative1LoaderPrivate;
+class Q_AUTOTEST_EXPORT QDeclarative1Loader : public QDeclarative1ImplicitSizeItem
+{
+ Q_OBJECT
+ Q_ENUMS(Status)
+
+ Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
+ Q_PROPERTY(QDeclarativeComponent *sourceComponent READ sourceComponent WRITE setSourceComponent RESET resetSourceComponent NOTIFY sourceChanged)
+ Q_PROPERTY(QGraphicsObject *item READ item NOTIFY itemChanged)
+ Q_PROPERTY(Status status READ status NOTIFY statusChanged)
+ Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged)
+
+public:
+ QDeclarative1Loader(QDeclarativeItem *parent=0);
+ virtual ~QDeclarative1Loader();
+
+ QUrl source() const;
+ void setSource(const QUrl &);
+
+ QDeclarativeComponent *sourceComponent() const;
+ void setSourceComponent(QDeclarativeComponent *);
+ void resetSourceComponent();
+
+ enum Status { Null, Ready, Loading, Error };
+ Status status() const;
+ qreal progress() const;
+
+ QGraphicsObject *item() const;
+
+Q_SIGNALS:
+ void itemChanged();
+ void sourceChanged();
+ void statusChanged();
+ void progressChanged();
+ void loaded();
+
+protected:
+ void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
+ QVariant itemChange(GraphicsItemChange change, const QVariant &value);
+ bool eventFilter(QObject *watched, QEvent *e);
+ void componentComplete();
+
+private:
+ Q_DISABLE_COPY(QDeclarative1Loader)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarative1Loader)
+ Q_PRIVATE_SLOT(d_func(), void _q_sourceLoaded())
+ Q_PRIVATE_SLOT(d_func(), void _q_updateSize())
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1Loader)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVELOADER_H
diff --git a/src/qtquick1/graphicsitems/qdeclarativeloader_p_p.h b/src/qtquick1/graphicsitems/qdeclarativeloader_p_p.h
new file mode 100644
index 0000000000..f80173536f
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativeloader_p_p.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVELOADER_P_H
+#define QDECLARATIVELOADER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qdeclarativeloader_p.h"
+
+#include "QtQuick1/private/qdeclarativeimplicitsizeitem_p_p.h"
+#include "QtQuick1/private/qdeclarativeitemchangelistener_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeContext;
+class QDeclarative1LoaderPrivate : public QDeclarative1ImplicitSizeItemPrivate, public QDeclarativeItemChangeListener
+{
+ Q_DECLARE_PUBLIC(QDeclarative1Loader)
+
+public:
+ QDeclarative1LoaderPrivate();
+ ~QDeclarative1LoaderPrivate();
+
+ void itemGeometryChanged(QDeclarativeItem *item, const QRectF &newGeometry, const QRectF &oldGeometry);
+ void clear();
+ void initResize();
+ void load();
+
+ QUrl source;
+ QGraphicsObject *item;
+ QDeclarativeComponent *component;
+ bool ownComponent : 1;
+ bool updatingSize: 1;
+ bool itemWidthValid : 1;
+ bool itemHeightValid : 1;
+
+ void _q_sourceLoaded();
+ void _q_updateSize(bool loaderGeometryChanged = true);
+};
+
+QT_END_NAMESPACE
+
+#endif // QDECLARATIVELOADER_P_H
diff --git a/src/qtquick1/graphicsitems/qdeclarativemousearea.cpp b/src/qtquick1/graphicsitems/qdeclarativemousearea.cpp
new file mode 100644
index 0000000000..6cd41ff615
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativemousearea.cpp
@@ -0,0 +1,990 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativemousearea_p.h"
+#include "QtQuick1/private/qdeclarativemousearea_p_p.h"
+
+#include "QtQuick1/private/qdeclarativeevents_p_p.h"
+
+#include <QGraphicsSceneMouseEvent>
+
+#include <float.h>
+
+QT_BEGIN_NAMESPACE
+
+
+static const int PressAndHoldDelay = 800;
+
+QDeclarative1Drag::QDeclarative1Drag(QObject *parent)
+: QObject(parent), _target(0), _axis(XandYAxis), _xmin(-FLT_MAX), _xmax(FLT_MAX), _ymin(-FLT_MAX), _ymax(FLT_MAX),
+_active(false), _filterChildren(false)
+{
+}
+
+QDeclarative1Drag::~QDeclarative1Drag()
+{
+}
+
+QGraphicsObject *QDeclarative1Drag::target() const
+{
+ return _target;
+}
+
+void QDeclarative1Drag::setTarget(QGraphicsObject *t)
+{
+ if (_target == t)
+ return;
+ _target = t;
+ emit targetChanged();
+}
+
+void QDeclarative1Drag::resetTarget()
+{
+ if (!_target)
+ return;
+ _target = 0;
+ emit targetChanged();
+}
+
+QDeclarative1Drag::Axis QDeclarative1Drag::axis() const
+{
+ return _axis;
+}
+
+void QDeclarative1Drag::setAxis(QDeclarative1Drag::Axis a)
+{
+ if (_axis == a)
+ return;
+ _axis = a;
+ emit axisChanged();
+}
+
+qreal QDeclarative1Drag::xmin() const
+{
+ return _xmin;
+}
+
+void QDeclarative1Drag::setXmin(qreal m)
+{
+ if (_xmin == m)
+ return;
+ _xmin = m;
+ emit minimumXChanged();
+}
+
+qreal QDeclarative1Drag::xmax() const
+{
+ return _xmax;
+}
+
+void QDeclarative1Drag::setXmax(qreal m)
+{
+ if (_xmax == m)
+ return;
+ _xmax = m;
+ emit maximumXChanged();
+}
+
+qreal QDeclarative1Drag::ymin() const
+{
+ return _ymin;
+}
+
+void QDeclarative1Drag::setYmin(qreal m)
+{
+ if (_ymin == m)
+ return;
+ _ymin = m;
+ emit minimumYChanged();
+}
+
+qreal QDeclarative1Drag::ymax() const
+{
+ return _ymax;
+}
+
+void QDeclarative1Drag::setYmax(qreal m)
+{
+ if (_ymax == m)
+ return;
+ _ymax = m;
+ emit maximumYChanged();
+}
+
+bool QDeclarative1Drag::active() const
+{
+ return _active;
+}
+
+void QDeclarative1Drag::setActive(bool drag)
+{
+ if (_active == drag)
+ return;
+ _active = drag;
+ emit activeChanged();
+}
+
+bool QDeclarative1Drag::filterChildren() const
+{
+ return _filterChildren;
+}
+
+void QDeclarative1Drag::setFilterChildren(bool filter)
+{
+ if (_filterChildren == filter)
+ return;
+ _filterChildren = filter;
+ emit filterChildrenChanged();
+}
+
+QDeclarative1MouseAreaPrivate::~QDeclarative1MouseAreaPrivate()
+{
+ delete drag;
+}
+
+/*!
+ \qmlclass MouseArea QDeclarative1MouseArea
+ \ingroup qml-basic-interaction-elements
+ \since 4.7
+ \brief The MouseArea item enables simple mouse handling.
+ \inherits Item
+
+ A MouseArea is an invisible item that is typically used in conjunction with
+ a visible item in order to provide mouse handling for that item.
+ By effectively acting as a proxy, the logic for mouse handling can be
+ contained within a MouseArea item.
+
+ For basic key handling, see the \l{Keys}{Keys attached property}.
+
+ The \l enabled property is used to enable and disable mouse handling for
+ the proxied item. When disabled, the mouse area becomes transparent to
+ mouse events.
+
+ The \l pressed read-only property indicates whether or not the user is
+ holding down a mouse button over the mouse area. This property is often
+ used in bindings between properties in a user interface. The containsMouse
+ read-only property indicates the presence of the mouse cursor over the
+ mouse area but, by default, only when a mouse button is held down; see below
+ for further details.
+
+ Information about the mouse position and button clicks are provided via
+ signals for which event handler properties are defined. The most commonly
+ used involved handling mouse presses and clicks: onClicked, onDoubleClicked,
+ onPressed, onReleased and onPressAndHold.
+
+ By default, MouseArea items only report mouse clicks and not changes to the
+ position of the mouse cursor. Setting the hoverEnabled property ensures that
+ handlers defined for onPositionChanged, onEntered and onExited are used and
+ that the containsMouse property is updated even when no mouse buttons are
+ pressed.
+
+ \section1 Example Usage
+
+ \div {class="float-right"}
+ \inlineimage qml-mousearea-snippet.png
+ \enddiv
+
+ The following example uses a MouseArea in a \l Rectangle that changes
+ the \l Rectangle color to red when clicked:
+
+ \snippet doc/src/snippets/declarative/mousearea/mousearea.qml import
+ \codeline
+ \snippet doc/src/snippets/declarative/mousearea/mousearea.qml intro
+
+ \clearfloat
+ Many MouseArea signals pass a \l{MouseEvent}{mouse} parameter that contains
+ additional information about the mouse event, such as the position, button,
+ and any key modifiers.
+
+ Here is an extension of the previous example that produces a different
+ color when the area is right clicked:
+
+ \snippet doc/src/snippets/declarative/mousearea/mousearea.qml intro-extended
+
+ \sa MouseEvent, {declarative/touchinteraction/mousearea}{MouseArea example}
+*/
+
+/*!
+ \qmlsignal MouseArea::onEntered()
+
+ This handler is called when the mouse enters the mouse area.
+
+ By default the onEntered handler is only called while a button is
+ pressed. Setting hoverEnabled to true enables handling of
+ onEntered when no mouse button is pressed.
+
+ \sa hoverEnabled
+*/
+
+/*!
+ \qmlsignal MouseArea::onExited()
+
+ This handler is called when the mouse exists the mouse area.
+
+ By default the onExited handler is only called while a button is
+ pressed. Setting hoverEnabled to true enables handling of
+ onExited when no mouse button is pressed.
+
+ \sa hoverEnabled
+*/
+
+/*!
+ \qmlsignal MouseArea::onPositionChanged(MouseEvent mouse)
+
+ This handler is called when the mouse position changes.
+
+ The \l {MouseEvent}{mouse} parameter provides information about the mouse, including the x and y
+ position, and any buttons currently pressed.
+
+ The \e accepted property of the MouseEvent parameter is ignored in this handler.
+
+ By default the onPositionChanged handler is only called while a button is
+ pressed. Setting hoverEnabled to true enables handling of
+ onPositionChanged when no mouse button is pressed.
+*/
+
+/*!
+ \qmlsignal MouseArea::onClicked(MouseEvent mouse)
+
+ This handler is called when there is a click. A click is defined as a press followed by a release,
+ both inside the MouseArea (pressing, moving outside the MouseArea, and then moving back inside and
+ releasing is also considered a click).
+
+ The \l {MouseEvent}{mouse} parameter provides information about the click, including the x and y
+ position of the release of the click, and whether the click was held.
+
+ The \e accepted property of the MouseEvent parameter is ignored in this handler.
+*/
+
+/*!
+ \qmlsignal MouseArea::onPressed(MouseEvent mouse)
+
+ This handler is called when there is a press.
+ The \l {MouseEvent}{mouse} parameter provides information about the press, including the x and y
+ position and which button was pressed.
+
+ The \e accepted property of the MouseEvent parameter determines whether this MouseArea
+ will handle the press and all future mouse events until release. The default is to accept
+ the event and not allow other MouseArea beneath this one to handle the event. If \e accepted
+ is set to false, no further events will be sent to this MouseArea until the button is next
+ pressed.
+*/
+
+/*!
+ \qmlsignal MouseArea::onReleased(MouseEvent mouse)
+
+ This handler is called when there is a release.
+ The \l {MouseEvent}{mouse} parameter provides information about the click, including the x and y
+ position of the release of the click, and whether the click was held.
+
+ The \e accepted property of the MouseEvent parameter is ignored in this handler.
+
+ \sa onCanceled
+*/
+
+/*!
+ \qmlsignal MouseArea::onPressAndHold(MouseEvent mouse)
+
+ This handler is called when there is a long press (currently 800ms).
+ The \l {MouseEvent}{mouse} parameter provides information about the press, including the x and y
+ position of the press, and which button is pressed.
+
+ The \e accepted property of the MouseEvent parameter is ignored in this handler.
+*/
+
+/*!
+ \qmlsignal MouseArea::onDoubleClicked(MouseEvent mouse)
+
+ This handler is called when there is a double-click (a press followed by a release followed by a press).
+ The \l {MouseEvent}{mouse} parameter provides information about the click, including the x and y
+ position of the release of the click, and whether the click was held.
+
+ If the \e accepted property of the \l {MouseEvent}{mouse} parameter is set to false
+ in the handler, the onPressed/onReleased/onClicked handlers will be called for the second
+ click; otherwise they are suppressed. The accepted property defaults to true.
+*/
+
+/*!
+ \qmlsignal MouseArea::onCanceled()
+
+ This handler is called when mouse events have been canceled, either because an event was not accepted, or
+ because another element stole the mouse event handling.
+
+ This signal is for advanced use: it is useful when there is more than one MouseArea
+ that is handling input, or when there is a MouseArea inside a \l Flickable. In the latter
+ case, if you execute some logic on the pressed signal and then start dragging, the
+ \l Flickable will steal the mouse handling from the MouseArea. In these cases, to reset
+ the logic when the MouseArea has lost the mouse handling to the \l Flickable,
+ \c onCanceled should be used in addition to onReleased.
+*/
+
+QDeclarative1MouseArea::QDeclarative1MouseArea(QDeclarativeItem *parent)
+ : QDeclarativeItem(*(new QDeclarative1MouseAreaPrivate), parent)
+{
+ Q_D(QDeclarative1MouseArea);
+ d->init();
+}
+
+QDeclarative1MouseArea::~QDeclarative1MouseArea()
+{
+}
+
+/*!
+ \qmlproperty real MouseArea::mouseX
+ \qmlproperty real MouseArea::mouseY
+ These properties hold the coordinates of the mouse cursor.
+
+ If the hoverEnabled property is false then these properties will only be valid
+ while a button is pressed, and will remain valid as long as the button is held
+ down even if the mouse is moved outside the area.
+
+ By default, this property is false.
+
+ If hoverEnabled is true then these properties will be valid when:
+ \list
+ \i no button is pressed, but the mouse is within the MouseArea (containsMouse is true).
+ \i a button is pressed and held, even if it has since moved out of the area.
+ \endlist
+
+ The coordinates are relative to the MouseArea.
+*/
+qreal QDeclarative1MouseArea::mouseX() const
+{
+ Q_D(const QDeclarative1MouseArea);
+ return d->lastPos.x();
+}
+
+qreal QDeclarative1MouseArea::mouseY() const
+{
+ Q_D(const QDeclarative1MouseArea);
+ return d->lastPos.y();
+}
+
+/*!
+ \qmlproperty bool MouseArea::enabled
+ This property holds whether the item accepts mouse events.
+
+ By default, this property is true.
+*/
+bool QDeclarative1MouseArea::isEnabled() const
+{
+ Q_D(const QDeclarative1MouseArea);
+ return d->absorb;
+}
+
+void QDeclarative1MouseArea::setEnabled(bool a)
+{
+ Q_D(QDeclarative1MouseArea);
+ if (a != d->absorb) {
+ d->absorb = a;
+ emit enabledChanged();
+ }
+}
+
+/*!
+ \qmlproperty bool MouseArea::preventStealing
+ \since Quick 1.1
+ This property holds whether the mouse events may be stolen from this
+ MouseArea.
+
+ If a MouseArea is placed within an item that filters child mouse
+ events, such as Flickable, the mouse
+ events may be stolen from the MouseArea if a gesture is recognized
+ by the parent element, e.g. a flick gesture. If preventStealing is
+ set to true, no element will steal the mouse events.
+
+ Note that setting preventStealing to true once an element has started
+ stealing events will have no effect until the next press event.
+
+ By default this property is false.
+*/
+bool QDeclarative1MouseArea::preventStealing() const
+{
+ Q_D(const QDeclarative1MouseArea);
+ return d->preventStealing;
+}
+
+void QDeclarative1MouseArea::setPreventStealing(bool prevent)
+{
+ Q_D(QDeclarative1MouseArea);
+ if (prevent != d->preventStealing) {
+ d->preventStealing = prevent;
+ setKeepMouseGrab(d->preventStealing && d->absorb);
+ emit preventStealingChanged();
+ }
+}
+
+/*!
+ \qmlproperty MouseButtons MouseArea::pressedButtons
+ This property holds the mouse buttons currently pressed.
+
+ It contains a bitwise combination of:
+ \list
+ \o Qt.LeftButton
+ \o Qt.RightButton
+ \o Qt.MiddleButton
+ \endlist
+
+ The code below displays "right" when the right mouse buttons is pressed:
+
+ \snippet doc/src/snippets/declarative/mousearea/mousearea.qml mousebuttons
+
+ \sa acceptedButtons
+*/
+Qt::MouseButtons QDeclarative1MouseArea::pressedButtons() const
+{
+ Q_D(const QDeclarative1MouseArea);
+ return d->lastButtons;
+}
+
+void QDeclarative1MouseArea::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QDeclarative1MouseArea);
+ d->moved = false;
+ d->stealMouse = d->preventStealing;
+ if (!d->absorb)
+ QDeclarativeItem::mousePressEvent(event);
+ else {
+ d->longPress = false;
+ d->saveEvent(event);
+ if (d->drag) {
+ d->dragX = drag()->axis() & QDeclarative1Drag::XAxis;
+ d->dragY = drag()->axis() & QDeclarative1Drag::YAxis;
+ }
+ if (d->drag)
+ d->drag->setActive(false);
+ setHovered(true);
+ d->startScene = event->scenePos();
+ // we should only start timer if pressAndHold is connected to.
+ if (d->isPressAndHoldConnected())
+ d->pressAndHoldTimer.start(PressAndHoldDelay, this);
+ setKeepMouseGrab(d->stealMouse);
+ event->setAccepted(setPressed(true));
+ }
+}
+
+void QDeclarative1MouseArea::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QDeclarative1MouseArea);
+ if (!d->absorb) {
+ QDeclarativeItem::mouseMoveEvent(event);
+ return;
+ }
+
+ d->saveEvent(event);
+
+ // ### we should skip this if these signals aren't used
+ // ### can GV handle this for us?
+ bool contains = boundingRect().contains(d->lastPos);
+ if (d->hovered && !contains)
+ setHovered(false);
+ else if (!d->hovered && contains)
+ setHovered(true);
+
+ if (d->drag && d->drag->target()) {
+ if (!d->moved) {
+ d->startX = drag()->target()->x();
+ d->startY = drag()->target()->y();
+ }
+
+ QPointF startLocalPos;
+ QPointF curLocalPos;
+ if (drag()->target()->parentItem()) {
+ startLocalPos = drag()->target()->parentItem()->mapFromScene(d->startScene);
+ curLocalPos = drag()->target()->parentItem()->mapFromScene(event->scenePos());
+ } else {
+ startLocalPos = d->startScene;
+ curLocalPos = event->scenePos();
+ }
+
+ const int dragThreshold = QApplication::startDragDistance();
+ qreal dx = qAbs(curLocalPos.x() - startLocalPos.x());
+ qreal dy = qAbs(curLocalPos.y() - startLocalPos.y());
+
+ if (keepMouseGrab() && d->stealMouse)
+ d->drag->setActive(true);
+
+ if (d->dragX && d->drag->active()) {
+ qreal x = (curLocalPos.x() - startLocalPos.x()) + d->startX;
+ if (x < drag()->xmin())
+ x = drag()->xmin();
+ else if (x > drag()->xmax())
+ x = drag()->xmax();
+ drag()->target()->setX(x);
+ }
+ if (d->dragY && d->drag->active()) {
+ qreal y = (curLocalPos.y() - startLocalPos.y()) + d->startY;
+ if (y < drag()->ymin())
+ y = drag()->ymin();
+ else if (y > drag()->ymax())
+ y = drag()->ymax();
+ drag()->target()->setY(y);
+ }
+
+ if (!keepMouseGrab()) {
+ if ((!d->dragY && dy < dragThreshold && d->dragX && dx > dragThreshold)
+ || (!d->dragX && dx < dragThreshold && d->dragY && dy > dragThreshold)
+ || (d->dragX && d->dragY && (dx > dragThreshold || dy > dragThreshold))) {
+ setKeepMouseGrab(true);
+ d->stealMouse = true;
+ }
+ }
+
+ d->moved = true;
+ }
+ QDeclarative1MouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, false, d->longPress);
+ emit mousePositionChanged(&me);
+ me.setX(d->lastPos.x());
+ me.setY(d->lastPos.y());
+ emit positionChanged(&me);
+}
+
+
+void QDeclarative1MouseArea::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QDeclarative1MouseArea);
+ d->stealMouse = false;
+ if (!d->absorb) {
+ QDeclarativeItem::mouseReleaseEvent(event);
+ } else {
+ d->saveEvent(event);
+ setPressed(false);
+ if (d->drag)
+ d->drag->setActive(false);
+ // If we don't accept hover, we need to reset containsMouse.
+ if (!acceptHoverEvents())
+ setHovered(false);
+ QGraphicsScene *s = scene();
+ if (s && s->mouseGrabberItem() == this)
+ ungrabMouse();
+ setKeepMouseGrab(false);
+ }
+ d->doubleClick = false;
+}
+
+void QDeclarative1MouseArea::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QDeclarative1MouseArea);
+ if (!d->absorb) {
+ QDeclarativeItem::mouseDoubleClickEvent(event);
+ } else {
+ if (d->isDoubleClickConnected())
+ d->doubleClick = true;
+ d->saveEvent(event);
+ QDeclarative1MouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, true, false);
+ me.setAccepted(d->isDoubleClickConnected());
+ emit this->doubleClicked(&me);
+ QDeclarativeItem::mouseDoubleClickEvent(event);
+ }
+}
+
+void QDeclarative1MouseArea::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
+{
+ Q_D(QDeclarative1MouseArea);
+ if (!d->absorb)
+ QDeclarativeItem::hoverEnterEvent(event);
+ else {
+ d->lastPos = event->pos();
+ setHovered(true);
+ QDeclarative1MouseEvent me(d->lastPos.x(), d->lastPos.y(), Qt::NoButton, Qt::NoButton, event->modifiers(), false, false);
+ emit mousePositionChanged(&me);
+ }
+}
+
+void QDeclarative1MouseArea::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
+{
+ Q_D(QDeclarative1MouseArea);
+ if (!d->absorb) {
+ QDeclarativeItem::hoverMoveEvent(event);
+ } else {
+ d->lastPos = event->pos();
+ QDeclarative1MouseEvent me(d->lastPos.x(), d->lastPos.y(), Qt::NoButton, Qt::NoButton, event->modifiers(), false, false);
+ emit mousePositionChanged(&me);
+ me.setX(d->lastPos.x());
+ me.setY(d->lastPos.y());
+ emit positionChanged(&me);
+ }
+}
+
+void QDeclarative1MouseArea::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
+{
+ Q_D(QDeclarative1MouseArea);
+ if (!d->absorb)
+ QDeclarativeItem::hoverLeaveEvent(event);
+ else
+ setHovered(false);
+}
+
+#ifndef QT_NO_CONTEXTMENU
+void QDeclarative1MouseArea::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
+{
+ bool acceptsContextMenuButton;
+#if defined(Q_OS_SYMBIAN)
+ // In Symbian a Long Tap on the screen will trigger. See QSymbianControl::HandleLongTapEventL().
+ acceptsContextMenuButton = acceptedButtons() & Qt::LeftButton;
+#elif defined(Q_WS_WINCE)
+ // ### WinCE can trigger context menu event with a gesture in the left button or a
+ // click with the right button. Since we have no way here to differentiate them when
+ // event happens, accepting either of the them will block the event.
+ acceptsContextMenuButton = acceptedButtons() & (Qt::LeftButton | Qt::RightButton);
+#else
+ acceptsContextMenuButton = acceptedButtons() & Qt::RightButton;
+#endif
+
+ if (isEnabled() && event->reason() == QGraphicsSceneContextMenuEvent::Mouse
+ && acceptsContextMenuButton) {
+ // Do not let the context menu event propagate to items behind.
+ return;
+ }
+
+ QDeclarativeItem::contextMenuEvent(event);
+}
+#endif // QT_NO_CONTEXTMENU
+
+bool QDeclarative1MouseArea::sceneEvent(QEvent *event)
+{
+ bool rv = QDeclarativeItem::sceneEvent(event);
+ if (event->type() == QEvent::UngrabMouse) {
+ Q_D(QDeclarative1MouseArea);
+ if (d->pressed) {
+ // if our mouse grab has been removed (probably by Flickable), fix our
+ // state
+ d->pressed = false;
+ d->stealMouse = false;
+ setKeepMouseGrab(false);
+ emit canceled();
+ emit pressedChanged();
+ if (d->hovered) {
+ d->hovered = false;
+ emit hoveredChanged();
+ }
+ }
+ }
+ return rv;
+}
+
+bool QDeclarative1MouseArea::sendMouseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QDeclarative1MouseArea);
+ QGraphicsSceneMouseEvent mouseEvent(event->type());
+ QRectF myRect = mapToScene(QRectF(0, 0, width(), height())).boundingRect();
+
+ QGraphicsScene *s = scene();
+ QDeclarativeItem *grabber = s ? qobject_cast<QDeclarativeItem*>(s->mouseGrabberItem()) : 0;
+ bool stealThisEvent = d->stealMouse;
+ if ((stealThisEvent || myRect.contains(event->scenePos().toPoint())) && (!grabber || !grabber->keepMouseGrab())) {
+ mouseEvent.setAccepted(false);
+ for (int i = 0x1; i <= 0x10; i <<= 1) {
+ if (event->buttons() & i) {
+ Qt::MouseButton button = Qt::MouseButton(i);
+ mouseEvent.setButtonDownPos(button, mapFromScene(event->buttonDownPos(button)));
+ }
+ }
+ mouseEvent.setScenePos(event->scenePos());
+ mouseEvent.setLastScenePos(event->lastScenePos());
+ mouseEvent.setPos(mapFromScene(event->scenePos()));
+ mouseEvent.setLastPos(mapFromScene(event->lastScenePos()));
+
+ switch(mouseEvent.type()) {
+ case QEvent::GraphicsSceneMouseMove:
+ mouseMoveEvent(&mouseEvent);
+ break;
+ case QEvent::GraphicsSceneMousePress:
+ mousePressEvent(&mouseEvent);
+ break;
+ case QEvent::GraphicsSceneMouseRelease:
+ mouseReleaseEvent(&mouseEvent);
+ break;
+ default:
+ break;
+ }
+ grabber = qobject_cast<QDeclarativeItem*>(s->mouseGrabberItem());
+ if (grabber && stealThisEvent && !grabber->keepMouseGrab() && grabber != this)
+ grabMouse();
+
+ return stealThisEvent;
+ }
+ if (mouseEvent.type() == QEvent::GraphicsSceneMouseRelease) {
+ if (d->pressed) {
+ d->pressed = false;
+ d->stealMouse = false;
+ if (s && s->mouseGrabberItem() == this)
+ ungrabMouse();
+ emit canceled();
+ emit pressedChanged();
+ if (d->hovered) {
+ d->hovered = false;
+ emit hoveredChanged();
+ }
+ }
+ }
+ return false;
+}
+
+bool QDeclarative1MouseArea::sceneEventFilter(QGraphicsItem *i, QEvent *e)
+{
+ Q_D(QDeclarative1MouseArea);
+ if (!d->absorb || !isVisible() || !d->drag || !d->drag->filterChildren())
+ return QDeclarativeItem::sceneEventFilter(i, e);
+ switch (e->type()) {
+ case QEvent::GraphicsSceneMousePress:
+ case QEvent::GraphicsSceneMouseMove:
+ case QEvent::GraphicsSceneMouseRelease:
+ return sendMouseEvent(static_cast<QGraphicsSceneMouseEvent *>(e));
+ default:
+ break;
+ }
+
+ return QDeclarativeItem::sceneEventFilter(i, e);
+}
+
+void QDeclarative1MouseArea::timerEvent(QTimerEvent *event)
+{
+ Q_D(QDeclarative1MouseArea);
+ if (event->timerId() == d->pressAndHoldTimer.timerId()) {
+ d->pressAndHoldTimer.stop();
+ bool dragged = d->drag && d->drag->active();
+ if (d->pressed && dragged == false && d->hovered == true) {
+ d->longPress = true;
+ QDeclarative1MouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, false, d->longPress);
+ emit pressAndHold(&me);
+ }
+ }
+}
+
+void QDeclarative1MouseArea::geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry)
+{
+ Q_D(QDeclarative1MouseArea);
+ QDeclarativeItem::geometryChanged(newGeometry, oldGeometry);
+
+ if (d->lastScenePos.isNull)
+ d->lastScenePos = mapToScene(d->lastPos);
+ else if (newGeometry.x() != oldGeometry.x() || newGeometry.y() != oldGeometry.y())
+ d->lastPos = mapFromScene(d->lastScenePos);
+}
+
+QVariant QDeclarative1MouseArea::itemChange(GraphicsItemChange change,
+ const QVariant &value)
+{
+ Q_D(QDeclarative1MouseArea);
+ switch (change) {
+ case ItemVisibleHasChanged:
+ if (acceptHoverEvents() && d->hovered != (isVisible() && isUnderMouse()))
+ setHovered(!d->hovered);
+ break;
+ default:
+ break;
+ }
+
+ return QDeclarativeItem::itemChange(change, value);
+}
+
+/*!
+ \qmlproperty bool MouseArea::hoverEnabled
+ This property holds whether hover events are handled.
+
+ By default, mouse events are only handled in response to a button event, or when a button is
+ pressed. Hover enables handling of all mouse events even when no mouse button is
+ pressed.
+
+ This property affects the containsMouse property and the onEntered, onExited and
+ onPositionChanged signals.
+*/
+bool QDeclarative1MouseArea::hoverEnabled() const
+{
+ return acceptHoverEvents();
+}
+
+void QDeclarative1MouseArea::setHoverEnabled(bool h)
+{
+ Q_D(QDeclarative1MouseArea);
+ if (h == acceptHoverEvents())
+ return;
+
+ setAcceptHoverEvents(h);
+ emit hoverEnabledChanged();
+ if (d->hovered != isUnderMouse())
+ setHovered(!d->hovered);
+}
+
+/*!
+ \qmlproperty bool MouseArea::containsMouse
+ This property holds whether the mouse is currently inside the mouse area.
+
+ \warning This property is not updated if the area moves under the mouse: \e containsMouse will not change.
+ In addition, if hoverEnabled is false, containsMouse will only be valid when the mouse is pressed.
+*/
+bool QDeclarative1MouseArea::hovered() const
+{
+ Q_D(const QDeclarative1MouseArea);
+ return d->hovered;
+}
+
+/*!
+ \qmlproperty bool MouseArea::pressed
+ This property holds whether the mouse area is currently pressed.
+*/
+bool QDeclarative1MouseArea::pressed() const
+{
+ Q_D(const QDeclarative1MouseArea);
+ return d->pressed;
+}
+
+void QDeclarative1MouseArea::setHovered(bool h)
+{
+ Q_D(QDeclarative1MouseArea);
+ if (d->hovered != h) {
+ d->hovered = h;
+ emit hoveredChanged();
+ d->hovered ? emit entered() : emit exited();
+ }
+}
+
+/*!
+ \qmlproperty Qt::MouseButtons MouseArea::acceptedButtons
+ This property holds the mouse buttons that the mouse area reacts to.
+
+ The available buttons are:
+ \list
+ \o Qt.LeftButton
+ \o Qt.RightButton
+ \o Qt.MiddleButton
+ \endlist
+
+ To accept more than one button the flags can be combined with the
+ "|" (or) operator:
+
+ \code
+ MouseArea { acceptedButtons: Qt.LeftButton | Qt.RightButton }
+ \endcode
+
+ The default value is \c Qt.LeftButton.
+*/
+Qt::MouseButtons QDeclarative1MouseArea::acceptedButtons() const
+{
+ return acceptedMouseButtons();
+}
+
+void QDeclarative1MouseArea::setAcceptedButtons(Qt::MouseButtons buttons)
+{
+ if (buttons != acceptedMouseButtons()) {
+ setAcceptedMouseButtons(buttons);
+ emit acceptedButtonsChanged();
+ }
+}
+
+bool QDeclarative1MouseArea::setPressed(bool p)
+{
+ Q_D(QDeclarative1MouseArea);
+ bool dragged = d->drag && d->drag->active();
+ bool isclick = d->pressed == true && p == false && dragged == false && d->hovered == true;
+
+ if (d->pressed != p) {
+ d->pressed = p;
+ QDeclarative1MouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, isclick, d->longPress);
+ if (d->pressed) {
+ if (!d->doubleClick)
+ emit pressed(&me);
+ me.setX(d->lastPos.x());
+ me.setY(d->lastPos.y());
+ emit mousePositionChanged(&me);
+ emit pressedChanged();
+ } else {
+ emit released(&me);
+ me.setX(d->lastPos.x());
+ me.setY(d->lastPos.y());
+ emit pressedChanged();
+ if (isclick && !d->longPress && !d->doubleClick)
+ emit clicked(&me);
+ }
+
+ return me.isAccepted();
+ }
+ return false;
+}
+
+QDeclarative1Drag *QDeclarative1MouseArea::drag()
+{
+ Q_D(QDeclarative1MouseArea);
+ if (!d->drag)
+ d->drag = new QDeclarative1Drag;
+ return d->drag;
+}
+
+/*!
+ \qmlproperty Item MouseArea::drag.target
+ \qmlproperty bool MouseArea::drag.active
+ \qmlproperty enumeration MouseArea::drag.axis
+ \qmlproperty real MouseArea::drag.minimumX
+ \qmlproperty real MouseArea::drag.maximumX
+ \qmlproperty real MouseArea::drag.minimumY
+ \qmlproperty real MouseArea::drag.maximumY
+ \qmlproperty bool MouseArea::drag.filterChildren
+
+ \c drag provides a convenient way to make an item draggable.
+
+ \list
+ \i \c drag.target specifies the id of the item to drag.
+ \i \c drag.active specifies if the target item is currently being dragged.
+ \i \c drag.axis specifies whether dragging can be done horizontally (\c Drag.XAxis), vertically (\c Drag.YAxis), or both (\c Drag.XandYAxis)
+ \i \c drag.minimum and \c drag.maximum limit how far the target can be dragged along the corresponding axes.
+ \endlist
+
+ The following example displays a \l Rectangle that can be dragged along the X-axis. The opacity
+ of the rectangle is reduced when it is dragged to the right.
+
+ \snippet doc/src/snippets/declarative/mousearea/mousearea.qml drag
+
+ \note Items cannot be dragged if they are anchored for the requested
+ \c drag.axis. For example, if \c anchors.left or \c anchors.right was set
+ for \c rect in the above example, it cannot be dragged along the X-axis.
+ This can be avoided by settng the anchor value to \c undefined in
+ an \l onPressed handler.
+
+ If \c drag.filterChildren is set to true, a drag can override descendant MouseAreas. This
+ enables a parent MouseArea to handle drags, for example, while descendants handle clicks:
+
+ \snippet doc/src/snippets/declarative/mousearea/mouseareadragfilter.qml dragfilter
+
+*/
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/graphicsitems/qdeclarativemousearea_p.h b/src/qtquick1/graphicsitems/qdeclarativemousearea_p.h
new file mode 100644
index 0000000000..082df9e7b7
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativemousearea_p.h
@@ -0,0 +1,218 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEMOUSEAREA_H
+#define QDECLARATIVEMOUSEAREA_H
+
+#include "qdeclarativeitem.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_AUTOTEST_EXPORT QDeclarative1Drag : public QObject
+{
+ Q_OBJECT
+
+ Q_ENUMS(Axis)
+ Q_PROPERTY(QGraphicsObject *target READ target WRITE setTarget NOTIFY targetChanged RESET resetTarget)
+ Q_PROPERTY(Axis axis READ axis WRITE setAxis NOTIFY axisChanged)
+ Q_PROPERTY(qreal minimumX READ xmin WRITE setXmin NOTIFY minimumXChanged)
+ Q_PROPERTY(qreal maximumX READ xmax WRITE setXmax NOTIFY maximumXChanged)
+ Q_PROPERTY(qreal minimumY READ ymin WRITE setYmin NOTIFY minimumYChanged)
+ Q_PROPERTY(qreal maximumY READ ymax WRITE setYmax NOTIFY maximumYChanged)
+ Q_PROPERTY(bool active READ active NOTIFY activeChanged)
+ Q_PROPERTY(bool filterChildren READ filterChildren WRITE setFilterChildren NOTIFY filterChildrenChanged)
+ //### consider drag and drop
+
+public:
+ QDeclarative1Drag(QObject *parent=0);
+ ~QDeclarative1Drag();
+
+ QGraphicsObject *target() const;
+ void setTarget(QGraphicsObject *);
+ void resetTarget();
+
+ enum Axis { XAxis=0x01, YAxis=0x02, XandYAxis=0x03 };
+ Axis axis() const;
+ void setAxis(Axis);
+
+ qreal xmin() const;
+ void setXmin(qreal);
+ qreal xmax() const;
+ void setXmax(qreal);
+ qreal ymin() const;
+ void setYmin(qreal);
+ qreal ymax() const;
+ void setYmax(qreal);
+
+ bool active() const;
+ void setActive(bool);
+
+ bool filterChildren() const;
+ void setFilterChildren(bool);
+
+Q_SIGNALS:
+ void targetChanged();
+ void axisChanged();
+ void minimumXChanged();
+ void maximumXChanged();
+ void minimumYChanged();
+ void maximumYChanged();
+ void activeChanged();
+ void filterChildrenChanged();
+
+private:
+ QGraphicsObject *_target;
+ Axis _axis;
+ qreal _xmin;
+ qreal _xmax;
+ qreal _ymin;
+ qreal _ymax;
+ bool _active : 1;
+ bool _filterChildren: 1;
+ Q_DISABLE_COPY(QDeclarative1Drag)
+};
+
+class QDeclarative1MouseEvent;
+class QDeclarative1MouseAreaPrivate;
+class Q_AUTOTEST_EXPORT QDeclarative1MouseArea : public QDeclarativeItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal mouseX READ mouseX NOTIFY mousePositionChanged)
+ Q_PROPERTY(qreal mouseY READ mouseY NOTIFY mousePositionChanged)
+ Q_PROPERTY(bool containsMouse READ hovered NOTIFY hoveredChanged)
+ Q_PROPERTY(bool pressed READ pressed NOTIFY pressedChanged)
+ Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged)
+ Q_PROPERTY(Qt::MouseButtons pressedButtons READ pressedButtons NOTIFY pressedChanged)
+ Q_PROPERTY(Qt::MouseButtons acceptedButtons READ acceptedButtons WRITE setAcceptedButtons NOTIFY acceptedButtonsChanged)
+ Q_PROPERTY(bool hoverEnabled READ hoverEnabled WRITE setHoverEnabled NOTIFY hoverEnabledChanged)
+ Q_PROPERTY(QDeclarative1Drag *drag READ drag CONSTANT) //### add flicking to QDeclarative1Drag or add a QDeclarative1Flick ???
+ Q_PROPERTY(bool preventStealing READ preventStealing WRITE setPreventStealing NOTIFY preventStealingChanged REVISION 1)
+
+public:
+ QDeclarative1MouseArea(QDeclarativeItem *parent=0);
+ ~QDeclarative1MouseArea();
+
+ qreal mouseX() const;
+ qreal mouseY() const;
+
+ bool isEnabled() const;
+ void setEnabled(bool);
+
+ bool hovered() const;
+ bool pressed() const;
+
+ Qt::MouseButtons pressedButtons() const;
+
+ Qt::MouseButtons acceptedButtons() const;
+ void setAcceptedButtons(Qt::MouseButtons buttons);
+
+ bool hoverEnabled() const;
+ void setHoverEnabled(bool h);
+
+ QDeclarative1Drag *drag();
+
+ bool preventStealing() const;
+ void setPreventStealing(bool prevent);
+
+Q_SIGNALS:
+ void hoveredChanged();
+ void pressedChanged();
+ void enabledChanged();
+ void acceptedButtonsChanged();
+ void hoverEnabledChanged();
+ void positionChanged(QDeclarative1MouseEvent *mouse);
+ void mousePositionChanged(QDeclarative1MouseEvent *mouse);
+ Q_REVISION(1) void preventStealingChanged();
+
+ void pressed(QDeclarative1MouseEvent *mouse);
+ void pressAndHold(QDeclarative1MouseEvent *mouse);
+ void released(QDeclarative1MouseEvent *mouse);
+ void clicked(QDeclarative1MouseEvent *mouse);
+ void doubleClicked(QDeclarative1MouseEvent *mouse);
+ void entered();
+ void exited();
+ void canceled();
+
+protected:
+ void setHovered(bool);
+ bool setPressed(bool);
+
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+ void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
+ void hoverMoveEvent(QGraphicsSceneHoverEvent *event);
+ void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
+#ifndef QT_NO_CONTEXTMENU
+ void contextMenuEvent(QGraphicsSceneContextMenuEvent *event);
+#endif // QT_NO_CONTEXTMENU
+ bool sceneEvent(QEvent *);
+ bool sendMouseEvent(QGraphicsSceneMouseEvent *event);
+ bool sceneEventFilter(QGraphicsItem *i, QEvent *e);
+ void timerEvent(QTimerEvent *event);
+
+ virtual void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry);
+ virtual QVariant itemChange(GraphicsItemChange change, const QVariant& value);
+
+private:
+ void handlePress();
+ void handleRelease();
+
+private:
+ Q_DISABLE_COPY(QDeclarative1MouseArea)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarative1MouseArea)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1Drag)
+QML_DECLARE_TYPE(QDeclarative1MouseArea)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEMOUSEAREA_H
diff --git a/src/qtquick1/graphicsitems/qdeclarativemousearea_p_p.h b/src/qtquick1/graphicsitems/qdeclarativemousearea_p_p.h
new file mode 100644
index 0000000000..2bad671ffe
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativemousearea_p_p.h
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEMOUSEREGION_P_H
+#define QDECLARATIVEMOUSEREGION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qdeclarativeitem_p.h"
+
+#include <qdatetime.h>
+#include <qbasictimer.h>
+#include <qgraphicssceneevent.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarative1MouseAreaPrivate : public QDeclarativeItemPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1MouseArea)
+
+public:
+ QDeclarative1MouseAreaPrivate()
+ : absorb(true), hovered(false), pressed(false), longPress(false),
+ moved(false), stealMouse(false), doubleClick(false), preventStealing(false), drag(0)
+ {
+ }
+
+ ~QDeclarative1MouseAreaPrivate();
+
+ void init()
+ {
+ Q_Q(QDeclarative1MouseArea);
+ q->setAcceptedMouseButtons(Qt::LeftButton);
+ q->setFiltersChildEvents(true);
+ }
+
+ void saveEvent(QGraphicsSceneMouseEvent *event) {
+ lastPos = event->pos();
+ lastScenePos = event->scenePos();
+ lastButton = event->button();
+ lastButtons = event->buttons();
+ lastModifiers = event->modifiers();
+ }
+
+ bool isPressAndHoldConnected() {
+ Q_Q(QDeclarative1MouseArea);
+ static int idx = QObjectPrivate::get(q)->signalIndex("pressAndHold(QDeclarative1MouseEvent*)");
+ return QObjectPrivate::get(q)->isSignalConnected(idx);
+ }
+
+ bool isDoubleClickConnected() {
+ Q_Q(QDeclarative1MouseArea);
+ static int idx = QObjectPrivate::get(q)->signalIndex("doubleClicked(QDeclarative1MouseEvent*)");
+ return QObjectPrivate::get(q)->isSignalConnected(idx);
+ }
+
+ bool absorb : 1;
+ bool hovered : 1;
+ bool pressed : 1;
+ bool longPress : 1;
+ bool moved : 1;
+ bool dragX : 1;
+ bool dragY : 1;
+ bool stealMouse : 1;
+ bool doubleClick : 1;
+ bool preventStealing : 1;
+ QDeclarative1Drag *drag;
+ QPointF startScene;
+ qreal startX;
+ qreal startY;
+ QPointF lastPos;
+ QDeclarativeNullableValue<QPointF> lastScenePos;
+ Qt::MouseButton lastButton;
+ Qt::MouseButtons lastButtons;
+ Qt::KeyboardModifiers lastModifiers;
+ QBasicTimer pressAndHoldTimer;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDECLARATIVEMOUSEREGION_P_H
diff --git a/src/qtquick1/graphicsitems/qdeclarativepainteditem.cpp b/src/qtquick1/graphicsitems/qdeclarativepainteditem.cpp
new file mode 100644
index 0000000000..396aed2160
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativepainteditem.cpp
@@ -0,0 +1,501 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativepainteditem_p.h"
+#include "QtQuick1/private/qdeclarativepainteditem_p_p.h"
+
+#include <QDebug>
+#include <QPen>
+#include <QEvent>
+#include <QApplication>
+#include <QGraphicsSceneMouseEvent>
+#include <QPainter>
+#include <QPaintEngine>
+#include <qmath.h>
+
+QT_BEGIN_NAMESPACE
+
+
+
+/*!
+ \class QDeclarative1PaintedItem
+ \brief The QDeclarative1PaintedItem class is an abstract base class for QDeclarative1View items that want cached painting.
+ \internal
+
+ This is a convenience class for implementing items that cache their painting.
+ The contents of the item are cached behind the scenes.
+ The dirtyCache() function should be called if the contents change to
+ ensure the cache is refreshed the next time painting occurs.
+
+ To subclass QDeclarative1PaintedItem, you must reimplement drawContents() to draw
+ the contents of the item.
+*/
+
+/*!
+ \fn void QDeclarative1PaintedItem::drawContents(QPainter *painter, const QRect &rect)
+
+ This function is called when the cache needs to be refreshed. When
+ sub-classing QDeclarative1PaintedItem this function should be implemented so as to
+ paint the contents of the item using the given \a painter for the
+ area of the contents specified by \a rect.
+*/
+
+/*!
+ \property QDeclarative1PaintedItem::contentsSize
+ \brief The size of the contents
+
+ The contents size is the size of the item in regards to how it is painted
+ using the drawContents() function. This is distinct from the size of the
+ item in regards to height() and width().
+*/
+
+// XXX bug in WebKit - can call repaintRequested and other cache-changing functions from within render!
+static int inpaint=0;
+static int inpaint_clearcache=0;
+
+extern Q_GUI_EXPORT bool qt_applefontsmoothing_enabled;
+
+/*!
+ Marks areas of the cache that intersect with the given \a rect as dirty and
+ in need of being refreshed.
+
+ \sa clearCache()
+*/
+void QDeclarative1PaintedItem::dirtyCache(const QRect& rect)
+{
+ Q_D(QDeclarative1PaintedItem);
+ QRect srect(qCeil(rect.x()*d->contentsScale),
+ qCeil(rect.y()*d->contentsScale),
+ qCeil(rect.width()*d->contentsScale),
+ qCeil(rect.height()*d->contentsScale));
+ for (int i=0; i < d->imagecache.count(); ) {
+ QDeclarative1PaintedItemPrivate::ImageCacheItem *c = d->imagecache[i];
+ QRect isect = (c->area & srect) | c->dirty;
+ if (isect == c->area && !inpaint) {
+ delete d->imagecache.takeAt(i);
+ } else {
+ c->dirty = isect;
+ ++i;
+ }
+ }
+}
+
+/*!
+ Marks the entirety of the contents cache as dirty.
+
+ \sa dirtyCache()
+*/
+void QDeclarative1PaintedItem::clearCache()
+{
+ if (inpaint) {
+ inpaint_clearcache=1;
+ return;
+ }
+ Q_D(QDeclarative1PaintedItem);
+ qDeleteAll(d->imagecache);
+ d->imagecache.clear();
+}
+
+/*!
+ Returns the size of the contents.
+
+ \sa setContentsSize()
+*/
+QSize QDeclarative1PaintedItem::contentsSize() const
+{
+ Q_D(const QDeclarative1PaintedItem);
+ return d->contentsSize;
+}
+
+/*!
+ Sets the size of the contents to the given \a size.
+
+ \sa contentsSize()
+*/
+void QDeclarative1PaintedItem::setContentsSize(const QSize &size)
+{
+ Q_D(QDeclarative1PaintedItem);
+ if (d->contentsSize == size) return;
+ prepareGeometryChange();
+ d->contentsSize = size;
+ clearCache();
+ update();
+ emit contentsSizeChanged();
+}
+
+qreal QDeclarative1PaintedItem::contentsScale() const
+{
+ Q_D(const QDeclarative1PaintedItem);
+ return d->contentsScale;
+}
+
+void QDeclarative1PaintedItem::setContentsScale(qreal scale)
+{
+ Q_D(QDeclarative1PaintedItem);
+ if (d->contentsScale == scale) return;
+ d->contentsScale = scale;
+ clearCache();
+ update();
+ emit contentsScaleChanged();
+}
+
+
+/*!
+ Constructs a new QDeclarative1PaintedItem with the given \a parent.
+*/
+QDeclarative1PaintedItem::QDeclarative1PaintedItem(QDeclarativeItem *parent)
+ : QDeclarativeItem(*(new QDeclarative1PaintedItemPrivate), parent)
+{
+}
+
+/*!
+ \internal
+ Constructs a new QDeclarative1PaintedItem with the given \a parent and
+ initialized private data member \a dd.
+*/
+QDeclarative1PaintedItem::QDeclarative1PaintedItem(QDeclarative1PaintedItemPrivate &dd, QDeclarativeItem *parent)
+ : QDeclarativeItem(dd, parent)
+{
+}
+
+/*!
+ Destroys the image item.
+*/
+QDeclarative1PaintedItem::~QDeclarative1PaintedItem()
+{
+ clearCache();
+}
+
+void QDeclarative1PaintedItem::geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry)
+{
+ if (newGeometry.width() != oldGeometry.width() ||
+ newGeometry.height() != oldGeometry.height())
+ clearCache();
+
+ QDeclarativeItem::geometryChanged(newGeometry, oldGeometry);
+}
+
+QVariant QDeclarative1PaintedItem::itemChange(GraphicsItemChange change,
+ const QVariant &value)
+{
+ if (change == ItemVisibleHasChanged)
+ clearCache();
+
+ return QDeclarativeItem::itemChange(change, value);
+}
+
+void QDeclarative1PaintedItem::setCacheFrozen(bool frozen)
+{
+ Q_D(QDeclarative1PaintedItem);
+ if (d->cachefrozen == frozen)
+ return;
+ d->cachefrozen = frozen;
+ // XXX clear cache?
+}
+
+QRectF QDeclarative1PaintedItem::boundingRect() const
+{
+ Q_D(const QDeclarative1PaintedItem);
+ qreal w = d->mWidth;
+ QSizeF sz = d->contentsSize * d->contentsScale;
+ if (w < sz.width())
+ w = sz.width();
+ qreal h = d->mHeight;
+ if (h < sz.height())
+ h = sz.height();
+ return QRectF(0.0,0.0,w,h);
+}
+
+/*!
+ \internal
+*/
+void QDeclarative1PaintedItem::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *)
+{
+ Q_D(QDeclarative1PaintedItem);
+ const QRect content = boundingRect().toRect();
+ if (content.width() <= 0 || content.height() <= 0)
+ return;
+
+ ++inpaint;
+
+ const QTransform &x = p->deviceTransform();
+ QTransform xinv = x.inverted();
+ QRegion effectiveClip;
+ QRegion sysClip = p->paintEngine()->systemClip();
+ if (xinv.type() <= QTransform::TxScale && sysClip.numRects() < 5) {
+ // simple transform, region gets no more complicated...
+ effectiveClip = xinv.map(sysClip);
+ } else {
+ // do not make complicated regions...
+ effectiveClip = xinv.mapRect(sysClip.boundingRect());
+ }
+
+ QRegion topaint = p->clipRegion();
+ if (topaint.isEmpty()) {
+ if (effectiveClip.isEmpty())
+ topaint = QRect(0,0,p->device()->width(),p->device()->height());
+ else
+ topaint = effectiveClip;
+ } else if (!effectiveClip.isEmpty()) {
+ topaint &= effectiveClip;
+ }
+
+ topaint &= content;
+ QRegion uncached(content);
+ p->setRenderHints(QPainter::SmoothPixmapTransform, d->smooth);
+
+ int cachesize=0;
+ for (int i=0; i<d->imagecache.count(); ++i) {
+ QRect area = d->imagecache[i]->area;
+ if (topaint.contains(area)) {
+ QRectF target(area.x(), area.y(), area.width(), area.height());
+ if (!d->cachefrozen) {
+ if (!d->imagecache[i]->dirty.isNull() && topaint.contains(d->imagecache[i]->dirty)) {
+#ifdef Q_WS_MAC
+ bool oldSmooth = qt_applefontsmoothing_enabled;
+ qt_applefontsmoothing_enabled = false;
+#endif
+ QPainter qp(&d->imagecache[i]->image);
+#ifdef Q_WS_MAC
+ qt_applefontsmoothing_enabled = oldSmooth;
+#endif
+ qp.setRenderHints(QPainter::HighQualityAntialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform, d->smoothCache);
+ qp.translate(-area.x(), -area.y());
+ qp.scale(d->contentsScale,d->contentsScale);
+ QRect clip = d->imagecache[i]->dirty;
+ QRect sclip(qFloor(clip.x()/d->contentsScale),
+ qFloor(clip.y()/d->contentsScale),
+ qCeil(clip.width()/d->contentsScale+clip.x()/d->contentsScale-qFloor(clip.x()/d->contentsScale)),
+ qCeil(clip.height()/d->contentsScale+clip.y()/d->contentsScale-qFloor(clip.y()/d->contentsScale)));
+ qp.setClipRect(sclip);
+ if (d->fillColor.isValid()){
+ if(d->fillColor.alpha() < 255){
+ // ### Might not work outside of raster paintengine
+ QPainter::CompositionMode prev = qp.compositionMode();
+ qp.setCompositionMode(QPainter::CompositionMode_Source);
+ qp.fillRect(sclip,d->fillColor);
+ qp.setCompositionMode(prev);
+ }else{
+ qp.fillRect(sclip,d->fillColor);
+ }
+ }
+ drawContents(&qp, sclip);
+ d->imagecache[i]->dirty = QRect();
+ }
+ }
+ p->drawPixmap(target.toRect(), d->imagecache[i]->image);
+ topaint -= area;
+ d->imagecache[i]->age=0;
+ } else {
+ d->imagecache[i]->age++;
+ }
+ cachesize += area.width()*area.height();
+ uncached -= area;
+ }
+
+ if (!topaint.isEmpty()) {
+ if (!d->cachefrozen) {
+ // Find a sensible larger area, otherwise will paint lots of tiny images.
+ QRect biggerrect = topaint.boundingRect().adjusted(-64,-64,128,128);
+ cachesize += biggerrect.width() * biggerrect.height();
+ while (d->imagecache.count() && cachesize > d->max_imagecache_size) {
+ int oldest=-1;
+ int age=-1;
+ for (int i=0; i<d->imagecache.count(); ++i) {
+ int a = d->imagecache[i]->age;
+ if (a > age) {
+ oldest = i;
+ age = a;
+ }
+ }
+ cachesize -= d->imagecache[oldest]->area.width()*d->imagecache[oldest]->area.height();
+ uncached += d->imagecache[oldest]->area;
+ delete d->imagecache.takeAt(oldest);
+ }
+ const QRegion bigger = QRegion(biggerrect) & uncached;
+ const QVector<QRect> rects = bigger.rects();
+ for (int i = 0; i < rects.count(); ++i) {
+ const QRect &r = rects.at(i);
+ QPixmap img(r.size());
+ if (d->fillColor.isValid())
+ img.fill(d->fillColor);
+ {
+#ifdef Q_WS_MAC
+ bool oldSmooth = qt_applefontsmoothing_enabled;
+ qt_applefontsmoothing_enabled = false;
+#endif
+ QPainter qp(&img);
+#ifdef Q_WS_MAC
+ qt_applefontsmoothing_enabled = oldSmooth;
+#endif
+ qp.setRenderHints(QPainter::HighQualityAntialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform, d->smoothCache);
+
+ qp.translate(-r.x(),-r.y());
+ qp.scale(d->contentsScale,d->contentsScale);
+ QRect sclip(qFloor(r.x()/d->contentsScale),
+ qFloor(r.y()/d->contentsScale),
+ qCeil(r.width()/d->contentsScale+r.x()/d->contentsScale-qFloor(r.x()/d->contentsScale)),
+ qCeil(r.height()/d->contentsScale+r.y()/d->contentsScale-qFloor(r.y()/d->contentsScale)));
+ drawContents(&qp, sclip);
+ }
+ QDeclarative1PaintedItemPrivate::ImageCacheItem *newitem = new QDeclarative1PaintedItemPrivate::ImageCacheItem;
+ newitem->area = r;
+ newitem->image = img;
+ d->imagecache.append(newitem);
+ p->drawPixmap(r, newitem->image);
+ }
+ } else {
+ const QVector<QRect> rects = uncached.rects();
+ for (int i = 0; i < rects.count(); ++i)
+ p->fillRect(rects.at(i), Qt::lightGray);
+ }
+ }
+
+ if (inpaint_clearcache) {
+ clearCache();
+ inpaint_clearcache = 0;
+ }
+
+ --inpaint;
+}
+
+/*!
+ \qmlproperty int PaintedItem::pixelCacheSize
+
+ This property holds the maximum number of pixels of image cache to
+ allow. The default is 0.1 megapixels. The cache will not be larger
+ than the (unscaled) size of the WebView.
+*/
+/*!
+ \property QDeclarative1PaintedItem::pixelCacheSize
+
+ The maximum number of pixels of image cache to allow. The default
+ is 0.1 megapixels. The cache will not be larger than the (unscaled)
+ size of the QDeclarative1PaintedItem.
+*/
+int QDeclarative1PaintedItem::pixelCacheSize() const
+{
+ Q_D(const QDeclarative1PaintedItem);
+ return d->max_imagecache_size;
+}
+
+void QDeclarative1PaintedItem::setPixelCacheSize(int pixels)
+{
+ Q_D(QDeclarative1PaintedItem);
+ if (pixels < d->max_imagecache_size) {
+ int cachesize=0;
+ for (int i=0; i<d->imagecache.count(); ++i) {
+ QRect area = d->imagecache[i]->area;
+ cachesize += area.width()*area.height();
+ }
+ while (d->imagecache.count() && cachesize > pixels) {
+ int oldest=-1;
+ int age=-1;
+ for (int i=0; i<d->imagecache.count(); ++i) {
+ int a = d->imagecache[i]->age;
+ if (a > age) {
+ oldest = i;
+ age = a;
+ }
+ }
+ cachesize -= d->imagecache[oldest]->area.width()*d->imagecache[oldest]->area.height();
+ delete d->imagecache.takeAt(oldest);
+ }
+ }
+ d->max_imagecache_size = pixels;
+}
+
+
+
+/*!
+ \property QDeclarative1PaintedItem::fillColor
+
+ The color to be used to fill the item prior to calling drawContents().
+ By default, this is Qt::transparent.
+
+ Performance improvements can be achieved if subclasses call this with either an
+ invalid color (QColor()), or an appropriate solid color.
+*/
+void QDeclarative1PaintedItem::setFillColor(const QColor& c)
+{
+ Q_D(QDeclarative1PaintedItem);
+ if (d->fillColor == c)
+ return;
+ d->fillColor = c;
+ emit fillColorChanged();
+ update();
+}
+
+QColor QDeclarative1PaintedItem::fillColor() const
+{
+ Q_D(const QDeclarative1PaintedItem);
+ return d->fillColor;
+}
+
+/*!
+ \qmlproperty bool PaintedItem::smoothCache
+
+ Controls whether the cached tiles of which the item is composed are
+ rendered smoothly when they are generated.
+
+ This is in addition toe Item::smooth, which controls the smooth painting of
+ the already-painted cached tiles under transformation.
+*/
+bool QDeclarative1PaintedItem::smoothCache() const
+{
+ Q_D(const QDeclarative1PaintedItem);
+ return d->smoothCache;
+}
+
+void QDeclarative1PaintedItem::setSmoothCache(bool on)
+{
+ Q_D(QDeclarative1PaintedItem);
+ if (d->smoothCache != on) {
+ d->smoothCache = on;
+ clearCache();
+ }
+}
+
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/graphicsitems/qdeclarativepainteditem_p.h b/src/qtquick1/graphicsitems/qdeclarativepainteditem_p.h
new file mode 100644
index 0000000000..5e123219b1
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativepainteditem_p.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEIMAGEITEM_H
+#define QDECLARATIVEIMAGEITEM_H
+
+#include "qdeclarativeitem.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarative1PaintedItemPrivate;
+class Q_AUTOTEST_EXPORT QDeclarative1PaintedItem : public QDeclarativeItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QSize contentsSize READ contentsSize WRITE setContentsSize NOTIFY contentsSizeChanged)
+ Q_PROPERTY(QColor fillColor READ fillColor WRITE setFillColor NOTIFY fillColorChanged)
+ Q_PROPERTY(int pixelCacheSize READ pixelCacheSize WRITE setPixelCacheSize)
+ Q_PROPERTY(bool smoothCache READ smoothCache WRITE setSmoothCache)
+ Q_PROPERTY(qreal contentsScale READ contentsScale WRITE setContentsScale NOTIFY contentsScaleChanged)
+
+
+public:
+ QDeclarative1PaintedItem(QDeclarativeItem *parent=0);
+ ~QDeclarative1PaintedItem();
+
+ QSize contentsSize() const;
+ void setContentsSize(const QSize &);
+
+ qreal contentsScale() const;
+ void setContentsScale(qreal);
+
+ int pixelCacheSize() const;
+ void setPixelCacheSize(int pixels);
+
+ bool smoothCache() const;
+ void setSmoothCache(bool on);
+
+ QColor fillColor() const;
+ void setFillColor(const QColor&);
+
+ void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
+
+protected:
+ QDeclarative1PaintedItem(QDeclarative1PaintedItemPrivate &dd, QDeclarativeItem *parent);
+
+ virtual void drawContents(QPainter *p, const QRect &) = 0;
+ virtual void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry);
+ virtual QVariant itemChange(GraphicsItemChange change,
+ const QVariant &value);
+
+ void setCacheFrozen(bool);
+ QRectF boundingRect() const;
+
+Q_SIGNALS:
+ void fillColorChanged();
+ void contentsSizeChanged();
+ void contentsScaleChanged();
+
+protected Q_SLOTS:
+ void dirtyCache(const QRect &);
+ void clearCache();
+
+private:
+ Q_DISABLE_COPY(QDeclarative1PaintedItem)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarative1PaintedItem)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1PaintedItem)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/qtquick1/graphicsitems/qdeclarativepainteditem_p_p.h b/src/qtquick1/graphicsitems/qdeclarativepainteditem_p_p.h
new file mode 100644
index 0000000000..44c825da9c
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativepainteditem_p_p.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEIMAGEITEM_P_H
+#define QDECLARATIVEIMAGEITEM_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qdeclarativeitem_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarative1PaintedItemPrivate : public QDeclarativeItemPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1PaintedItem)
+
+public:
+ QDeclarative1PaintedItemPrivate()
+ : max_imagecache_size(100000), contentsScale(1.0), fillColor(Qt::transparent), cachefrozen(false), smoothCache(true)
+ {
+ }
+
+ struct ImageCacheItem {
+ ImageCacheItem() : age(0) {}
+ ~ImageCacheItem() { }
+ int age;
+ QRect area;
+ QRect dirty; // one dirty area (allows optimization of common cases)
+ QPixmap image;
+ };
+
+ QList<ImageCacheItem*> imagecache;
+
+ int max_imagecache_size;
+ QSize contentsSize;
+ qreal contentsScale;
+ QColor fillColor;
+ bool cachefrozen;
+ bool smoothCache;
+};
+
+QT_END_NAMESPACE
+#endif
diff --git a/src/qtquick1/graphicsitems/qdeclarativepath.cpp b/src/qtquick1/graphicsitems/qdeclarativepath.cpp
new file mode 100644
index 0000000000..9328f2c5dd
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativepath.cpp
@@ -0,0 +1,926 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativepath_p.h"
+#include "QtQuick1/private/qdeclarativepath_p_p.h"
+
+#include <QSet>
+#include <QTime>
+
+#include <private/qbezier_p.h>
+#include <QtCore/qmath.h>
+#include <QtCore/qnumeric.h>
+
+QT_BEGIN_NAMESPACE
+
+
+
+/*!
+ \qmlclass PathElement QDeclarative1PathElement
+ \ingroup qml-view-elements
+ \since 4.7
+ \brief PathElement is the base path type.
+
+ This type is the base for all path types. It cannot
+ be instantiated.
+
+ \sa Path, PathAttribute, PathPercent, PathLine, PathQuad, PathCubic
+*/
+
+/*!
+ \qmlclass Path QDeclarative1Path
+ \ingroup qml-view-elements
+ \since 4.7
+ \brief A Path object defines a path for use by \l PathView.
+
+ A Path is composed of one or more path segments - PathLine, PathQuad,
+ PathCubic.
+
+ The spacing of the items along the Path can be adjusted via a
+ PathPercent object.
+
+ PathAttribute allows named attributes with values to be defined
+ along the path.
+
+ \sa PathView, PathAttribute, PathPercent, PathLine, PathQuad, PathCubic
+*/
+QDeclarative1Path::QDeclarative1Path(QObject *parent)
+ : QObject(*(new QDeclarative1PathPrivate), parent)
+{
+}
+
+QDeclarative1Path::~QDeclarative1Path()
+{
+}
+
+/*!
+ \qmlproperty real Path::startX
+ \qmlproperty real Path::startY
+ These properties hold the starting position of the path.
+*/
+qreal QDeclarative1Path::startX() const
+{
+ Q_D(const QDeclarative1Path);
+ return d->startX;
+}
+
+void QDeclarative1Path::setStartX(qreal x)
+{
+ Q_D(QDeclarative1Path);
+ if (qFuzzyCompare(x, d->startX))
+ return;
+ d->startX = x;
+ emit startXChanged();
+ processPath();
+}
+
+qreal QDeclarative1Path::startY() const
+{
+ Q_D(const QDeclarative1Path);
+ return d->startY;
+}
+
+void QDeclarative1Path::setStartY(qreal y)
+{
+ Q_D(QDeclarative1Path);
+ if (qFuzzyCompare(y, d->startY))
+ return;
+ d->startY = y;
+ emit startYChanged();
+ processPath();
+}
+
+/*!
+ \qmlproperty bool Path::closed
+ This property holds whether the start and end of the path are identical.
+*/
+bool QDeclarative1Path::isClosed() const
+{
+ Q_D(const QDeclarative1Path);
+ return d->closed;
+}
+
+/*!
+ \qmlproperty list<PathElement> Path::pathElements
+ This property holds the objects composing the path.
+
+ \default
+
+ A path can contain the following path objects:
+ \list
+ \i \l PathLine - a straight line to a given position.
+ \i \l PathQuad - a quadratic Bezier curve to a given position with a control point.
+ \i \l PathCubic - a cubic Bezier curve to a given position with two control points.
+ \i \l PathAttribute - an attribute at a given position in the path.
+ \i \l PathPercent - a way to spread out items along various segments of the path.
+ \endlist
+
+ \snippet doc/src/snippets/declarative/pathview/pathattributes.qml 2
+*/
+
+QDeclarativeListProperty<QDeclarative1PathElement> QDeclarative1Path::pathElements()
+{
+ Q_D(QDeclarative1Path);
+ return QDeclarativeListProperty<QDeclarative1PathElement>(this, d->_pathElements);
+}
+
+void QDeclarative1Path::interpolate(int idx, const QString &name, qreal value)
+{
+ Q_D(QDeclarative1Path);
+ if (!idx)
+ return;
+
+ qreal lastValue = 0;
+ qreal lastPercent = 0;
+ int search = idx - 1;
+ while(search >= 0) {
+ const AttributePoint &point = d->_attributePoints.at(search);
+ if (point.values.contains(name)) {
+ lastValue = point.values.value(name);
+ lastPercent = point.origpercent;
+ break;
+ }
+ --search;
+ }
+
+ ++search;
+
+ const AttributePoint &curPoint = d->_attributePoints.at(idx);
+
+ for (int ii = search; ii < idx; ++ii) {
+ AttributePoint &point = d->_attributePoints[ii];
+
+ qreal val = lastValue + (value - lastValue) * (point.origpercent - lastPercent) / (curPoint.origpercent - lastPercent);
+ point.values.insert(name, val);
+ }
+}
+
+void QDeclarative1Path::endpoint(const QString &name)
+{
+ Q_D(QDeclarative1Path);
+ const AttributePoint &first = d->_attributePoints.first();
+ qreal val = first.values.value(name);
+ for (int ii = d->_attributePoints.count() - 1; ii >= 0; ii--) {
+ const AttributePoint &point = d->_attributePoints.at(ii);
+ if (point.values.contains(name)) {
+ for (int jj = ii + 1; jj < d->_attributePoints.count(); ++jj) {
+ AttributePoint &setPoint = d->_attributePoints[jj];
+ setPoint.values.insert(name, val);
+ }
+ return;
+ }
+ }
+}
+
+void QDeclarative1Path::processPath()
+{
+ Q_D(QDeclarative1Path);
+
+ if (!d->componentComplete)
+ return;
+
+ d->_pointCache.clear();
+ d->_attributePoints.clear();
+ d->_path = QPainterPath();
+
+ AttributePoint first;
+ for (int ii = 0; ii < d->_attributes.count(); ++ii)
+ first.values[d->_attributes.at(ii)] = 0;
+ d->_attributePoints << first;
+
+ d->_path.moveTo(d->startX, d->startY);
+
+ QDeclarative1Curve *lastCurve = 0;
+ foreach (QDeclarative1PathElement *pathElement, d->_pathElements) {
+ if (QDeclarative1Curve *curve = qobject_cast<QDeclarative1Curve *>(pathElement)) {
+ curve->addToPath(d->_path);
+ AttributePoint p;
+ p.origpercent = d->_path.length();
+ d->_attributePoints << p;
+ lastCurve = curve;
+ } else if (QDeclarative1PathAttribute *attribute = qobject_cast<QDeclarative1PathAttribute *>(pathElement)) {
+ AttributePoint &point = d->_attributePoints.last();
+ point.values[attribute->name()] = attribute->value();
+ interpolate(d->_attributePoints.count() - 1, attribute->name(), attribute->value());
+ } else if (QDeclarative1PathPercent *percent = qobject_cast<QDeclarative1PathPercent *>(pathElement)) {
+ AttributePoint &point = d->_attributePoints.last();
+ point.values[QLatin1String("_qfx_percent")] = percent->value();
+ interpolate(d->_attributePoints.count() - 1, QLatin1String("_qfx_percent"), percent->value());
+ }
+ }
+
+ // Fixup end points
+ const AttributePoint &last = d->_attributePoints.last();
+ for (int ii = 0; ii < d->_attributes.count(); ++ii) {
+ if (!last.values.contains(d->_attributes.at(ii)))
+ endpoint(d->_attributes.at(ii));
+ }
+
+ // Adjust percent
+ qreal length = d->_path.length();
+ qreal prevpercent = 0;
+ qreal prevorigpercent = 0;
+ for (int ii = 0; ii < d->_attributePoints.count(); ++ii) {
+ const AttributePoint &point = d->_attributePoints.at(ii);
+ if (point.values.contains(QLatin1String("_qfx_percent"))) { //special string for QDeclarative1PathPercent
+ if ( ii > 0) {
+ qreal scale = (d->_attributePoints[ii].origpercent/length - prevorigpercent) /
+ (point.values.value(QLatin1String("_qfx_percent"))-prevpercent);
+ d->_attributePoints[ii].scale = scale;
+ }
+ d->_attributePoints[ii].origpercent /= length;
+ d->_attributePoints[ii].percent = point.values.value(QLatin1String("_qfx_percent"));
+ prevorigpercent = d->_attributePoints[ii].origpercent;
+ prevpercent = d->_attributePoints[ii].percent;
+ } else {
+ d->_attributePoints[ii].origpercent /= length;
+ d->_attributePoints[ii].percent = d->_attributePoints[ii].origpercent;
+ }
+ }
+
+ d->closed = lastCurve && d->startX == lastCurve->x() && d->startY == lastCurve->y();
+
+ emit changed();
+}
+
+void QDeclarative1Path::classBegin()
+{
+ Q_D(QDeclarative1Path);
+ d->componentComplete = false;
+}
+
+void QDeclarative1Path::componentComplete()
+{
+ Q_D(QDeclarative1Path);
+ QSet<QString> attrs;
+ d->componentComplete = true;
+
+ // First gather up all the attributes
+ foreach (QDeclarative1PathElement *pathElement, d->_pathElements) {
+ if (QDeclarative1PathAttribute *attribute =
+ qobject_cast<QDeclarative1PathAttribute *>(pathElement))
+ attrs.insert(attribute->name());
+ }
+ d->_attributes = attrs.toList();
+
+ processPath();
+
+ foreach (QDeclarative1PathElement *pathElement, d->_pathElements)
+ connect(pathElement, SIGNAL(changed()), this, SLOT(processPath()));
+}
+
+QPainterPath QDeclarative1Path::path() const
+{
+ Q_D(const QDeclarative1Path);
+ return d->_path;
+}
+
+QStringList QDeclarative1Path::attributes() const
+{
+ Q_D(const QDeclarative1Path);
+ if (!d->componentComplete) {
+ QSet<QString> attrs;
+
+ // First gather up all the attributes
+ foreach (QDeclarative1PathElement *pathElement, d->_pathElements) {
+ if (QDeclarative1PathAttribute *attribute =
+ qobject_cast<QDeclarative1PathAttribute *>(pathElement))
+ attrs.insert(attribute->name());
+ }
+ return attrs.toList();
+ }
+ return d->_attributes;
+}
+
+static inline QBezier nextBezier(const QPainterPath &path, int *from, qreal *bezLength)
+{
+ const int lastElement = path.elementCount() - 1;
+ for (int i=*from; i <= lastElement; ++i) {
+ const QPainterPath::Element &e = path.elementAt(i);
+
+ switch (e.type) {
+ case QPainterPath::MoveToElement:
+ break;
+ case QPainterPath::LineToElement:
+ {
+ QLineF line(path.elementAt(i-1), e);
+ *bezLength = line.length();
+ QPointF a = path.elementAt(i-1);
+ QPointF delta = e - a;
+ *from = i+1;
+ return QBezier::fromPoints(a, a + delta / 3, a + 2 * delta / 3, e);
+ }
+ case QPainterPath::CurveToElement:
+ {
+ QBezier b = QBezier::fromPoints(path.elementAt(i-1),
+ e,
+ path.elementAt(i+1),
+ path.elementAt(i+2));
+ *bezLength = b.length();
+ *from = i+3;
+ return b;
+ }
+ default:
+ break;
+ }
+ }
+ *from = lastElement;
+ *bezLength = 0;
+ return QBezier();
+}
+
+void QDeclarative1Path::createPointCache() const
+{
+ Q_D(const QDeclarative1Path);
+ qreal pathLength = d->_path.length();
+ if (pathLength <= 0 || qIsNaN(pathLength))
+ return;
+ // more points means less jitter between items as they move along the
+ // path, but takes longer to generate
+ const int points = qCeil(pathLength*5);
+ const int lastElement = d->_path.elementCount() - 1;
+ d->_pointCache.resize(points+1);
+
+ int currElement = 0;
+ qreal bezLength = 0;
+ QBezier currBez = nextBezier(d->_path, &currElement, &bezLength);
+ qreal currLength = bezLength;
+ qreal epc = currLength / pathLength;
+
+ for (int i = 0; i < d->_pointCache.size(); i++) {
+ //find which set we are in
+ qreal prevPercent = 0;
+ qreal prevOrigPercent = 0;
+ for (int ii = 0; ii < d->_attributePoints.count(); ++ii) {
+ qreal percent = qreal(i)/points;
+ const AttributePoint &point = d->_attributePoints.at(ii);
+ if (percent < point.percent || ii == d->_attributePoints.count() - 1) { //### || is special case for very last item
+ qreal elementPercent = (percent - prevPercent);
+
+ qreal spc = prevOrigPercent + elementPercent * point.scale;
+
+ while (spc > epc) {
+ if (currElement > lastElement)
+ break;
+ currBez = nextBezier(d->_path, &currElement, &bezLength);
+ if (bezLength == 0.0) {
+ currLength = pathLength;
+ epc = 1.0;
+ break;
+ }
+ currLength += bezLength;
+ epc = currLength / pathLength;
+ }
+ qreal realT = (pathLength * spc - (currLength - bezLength)) / bezLength;
+ d->_pointCache[i] = currBez.pointAt(qBound(qreal(0), realT, qreal(1)));
+ break;
+ }
+ prevOrigPercent = point.origpercent;
+ prevPercent = point.percent;
+ }
+ }
+}
+
+QPointF QDeclarative1Path::pointAt(qreal p) const
+{
+ Q_D(const QDeclarative1Path);
+ if (d->_pointCache.isEmpty()) {
+ createPointCache();
+ if (d->_pointCache.isEmpty())
+ return QPointF();
+ }
+ int idx = qRound(p*d->_pointCache.size());
+ if (idx >= d->_pointCache.size())
+ idx = d->_pointCache.size() - 1;
+ else if (idx < 0)
+ idx = 0;
+ return d->_pointCache.at(idx);
+}
+
+qreal QDeclarative1Path::attributeAt(const QString &name, qreal percent) const
+{
+ Q_D(const QDeclarative1Path);
+ if (percent < 0 || percent > 1)
+ return 0;
+
+ for (int ii = 0; ii < d->_attributePoints.count(); ++ii) {
+ const AttributePoint &point = d->_attributePoints.at(ii);
+
+ if (point.percent == percent) {
+ return point.values.value(name);
+ } else if (point.percent > percent) {
+ qreal lastValue =
+ ii?(d->_attributePoints.at(ii - 1).values.value(name)):0;
+ qreal lastPercent =
+ ii?(d->_attributePoints.at(ii - 1).percent):0;
+ qreal curValue = point.values.value(name);
+ qreal curPercent = point.percent;
+
+ return lastValue + (curValue - lastValue) * (percent - lastPercent) / (curPercent - lastPercent);
+ }
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+
+qreal QDeclarative1Curve::x() const
+{
+ return _x;
+}
+
+void QDeclarative1Curve::setX(qreal x)
+{
+ if (_x != x) {
+ _x = x;
+ emit xChanged();
+ emit changed();
+ }
+}
+
+qreal QDeclarative1Curve::y() const
+{
+ return _y;
+}
+
+void QDeclarative1Curve::setY(qreal y)
+{
+ if (_y != y) {
+ _y = y;
+ emit yChanged();
+ emit changed();
+ }
+}
+
+/****************************************************************************/
+
+/*!
+ \qmlclass PathAttribute QDeclarative1PathAttribute
+ \ingroup qml-view-elements
+ \since 4.7
+ \brief The PathAttribute allows setting an attribute at a given position in a Path.
+
+ The PathAttribute object allows attributes consisting of a name and
+ a value to be specified for various points along a path. The
+ attributes are exposed to the delegate as
+ \l{qdeclarativeintroduction.html#attached-properties} {Attached Properties}.
+ The value of an attribute at any particular point along the path is interpolated
+ from the PathAttributes bounding that point.
+
+ The example below shows a path with the items scaled to 30% with
+ opacity 50% at the top of the path and scaled 100% with opacity
+ 100% at the bottom. Note the use of the PathView.iconScale and
+ PathView.iconOpacity attached properties to set the scale and opacity
+ of the delegate.
+
+ \table
+ \row
+ \o \image declarative-pathattribute.png
+ \o
+ \snippet doc/src/snippets/declarative/pathview/pathattributes.qml 0
+ (see the PathView documentation for the specification of ContactModel.qml
+ used for ContactModel above.)
+ \endtable
+
+
+ \sa Path
+*/
+
+/*!
+ \qmlproperty string PathAttribute::name
+ This property holds the name of the attribute to change.
+
+ This attribute will be available to the delegate as PathView.<name>
+
+ Note that using an existing Item property name such as "opacity" as an
+ attribute is allowed. This is because path attributes add a new
+ \l{qdeclarativeintroduction.html#attached-properties} {Attached Property}
+ which in no way clashes with existing properties.
+*/
+
+/*!
+ the name of the attribute to change.
+*/
+
+QString QDeclarative1PathAttribute::name() const
+{
+ return _name;
+}
+
+void QDeclarative1PathAttribute::setName(const QString &name)
+{
+ if (_name == name)
+ return;
+ _name = name;
+ emit nameChanged();
+}
+
+/*!
+ \qmlproperty real PathAttribute::value
+ This property holds the value for the attribute.
+
+ The value specified can be used to influence the visual appearance
+ of an item along the path. For example, the following Path specifies
+ an attribute named \e itemRotation, which has the value \e 0 at the
+ beginning of the path, and the value 90 at the end of the path.
+
+ \qml
+ Path {
+ startX: 0
+ startY: 0
+ PathAttribute { name: "itemRotation"; value: 0 }
+ PathLine { x: 100; y: 100 }
+ PathAttribute { name: "itemRotation"; value: 90 }
+ }
+ \endqml
+
+ In our delegate, we can then bind the \e rotation property to the
+ \l{qdeclarativeintroduction.html#attached-properties} {Attached Property}
+ \e PathView.itemRotation created for this attribute.
+
+ \qml
+ Rectangle {
+ width: 10; height: 10
+ rotation: PathView.itemRotation
+ }
+ \endqml
+
+ As each item is positioned along the path, it will be rotated accordingly:
+ an item at the beginning of the path with be not be rotated, an item at
+ the end of the path will be rotated 90 degrees, and an item mid-way along
+ the path will be rotated 45 degrees.
+*/
+
+/*!
+ the new value of the attribute.
+*/
+qreal QDeclarative1PathAttribute::value() const
+{
+ return _value;
+}
+
+void QDeclarative1PathAttribute::setValue(qreal value)
+{
+ if (_value != value) {
+ _value = value;
+ emit valueChanged();
+ emit changed();
+ }
+}
+
+/****************************************************************************/
+
+/*!
+ \qmlclass PathLine QDeclarative1PathLine
+ \ingroup qml-view-elements
+ \since 4.7
+ \brief The PathLine defines a straight line.
+
+ The example below creates a path consisting of a straight line from
+ 0,100 to 200,100:
+
+ \qml
+ Path {
+ startX: 0; startY: 100
+ PathLine { x: 200; y: 100 }
+ }
+ \endqml
+
+ \sa Path, PathQuad, PathCubic
+*/
+
+/*!
+ \qmlproperty real PathLine::x
+ \qmlproperty real PathLine::y
+
+ Defines the end point of the line.
+*/
+
+void QDeclarative1PathLine::addToPath(QPainterPath &path)
+{
+ path.lineTo(x(), y());
+}
+
+/****************************************************************************/
+
+/*!
+ \qmlclass PathQuad QDeclarative1PathQuad
+ \ingroup qml-view-elements
+ \since 4.7
+ \brief The PathQuad defines a quadratic Bezier curve with a control point.
+
+ The following QML produces the path shown below:
+ \table
+ \row
+ \o \image declarative-pathquad.png
+ \o
+ \qml
+ Path {
+ startX: 0; startY: 0
+ PathQuad { x: 200; y: 0; controlX: 100; controlY: 150 }
+ }
+ \endqml
+ \endtable
+
+ \sa Path, PathCubic, PathLine
+*/
+
+/*!
+ \qmlproperty real PathQuad::x
+ \qmlproperty real PathQuad::y
+
+ Defines the end point of the curve.
+*/
+
+/*!
+ \qmlproperty real PathQuad::controlX
+ \qmlproperty real PathQuad::controlY
+
+ Defines the position of the control point.
+*/
+
+/*!
+ the x position of the control point.
+*/
+qreal QDeclarative1PathQuad::controlX() const
+{
+ return _controlX;
+}
+
+void QDeclarative1PathQuad::setControlX(qreal x)
+{
+ if (_controlX != x) {
+ _controlX = x;
+ emit controlXChanged();
+ emit changed();
+ }
+}
+
+
+/*!
+ the y position of the control point.
+*/
+qreal QDeclarative1PathQuad::controlY() const
+{
+ return _controlY;
+}
+
+void QDeclarative1PathQuad::setControlY(qreal y)
+{
+ if (_controlY != y) {
+ _controlY = y;
+ emit controlYChanged();
+ emit changed();
+ }
+}
+
+void QDeclarative1PathQuad::addToPath(QPainterPath &path)
+{
+ path.quadTo(controlX(), controlY(), x(), y());
+}
+
+/****************************************************************************/
+
+/*!
+ \qmlclass PathCubic QDeclarative1PathCubic
+ \ingroup qml-view-elements
+ \since 4.7
+ \brief The PathCubic defines a cubic Bezier curve with two control points.
+
+ The following QML produces the path shown below:
+ \table
+ \row
+ \o \image declarative-pathcubic.png
+ \o
+ \qml
+ Path {
+ startX: 20; startY: 0
+ PathCubic {
+ x: 180; y: 0
+ control1X: -10; control1Y: 90
+ control2X: 210; control2Y: 90
+ }
+ }
+ \endqml
+ \endtable
+
+ \sa Path, PathQuad, PathLine
+*/
+
+/*!
+ \qmlproperty real PathCubic::x
+ \qmlproperty real PathCubic::y
+
+ Defines the end point of the curve.
+*/
+
+/*!
+ \qmlproperty real PathCubic::control1X
+ \qmlproperty real PathCubic::control1Y
+
+ Defines the position of the first control point.
+*/
+qreal QDeclarative1PathCubic::control1X() const
+{
+ return _control1X;
+}
+
+void QDeclarative1PathCubic::setControl1X(qreal x)
+{
+ if (_control1X != x) {
+ _control1X = x;
+ emit control1XChanged();
+ emit changed();
+ }
+}
+
+qreal QDeclarative1PathCubic::control1Y() const
+{
+ return _control1Y;
+}
+
+void QDeclarative1PathCubic::setControl1Y(qreal y)
+{
+ if (_control1Y != y) {
+ _control1Y = y;
+ emit control1YChanged();
+ emit changed();
+ }
+}
+
+/*!
+ \qmlproperty real PathCubic::control2X
+ \qmlproperty real PathCubic::control2Y
+
+ Defines the position of the second control point.
+*/
+qreal QDeclarative1PathCubic::control2X() const
+{
+ return _control2X;
+}
+
+void QDeclarative1PathCubic::setControl2X(qreal x)
+{
+ if (_control2X != x) {
+ _control2X = x;
+ emit control2XChanged();
+ emit changed();
+ }
+}
+
+qreal QDeclarative1PathCubic::control2Y() const
+{
+ return _control2Y;
+}
+
+void QDeclarative1PathCubic::setControl2Y(qreal y)
+{
+ if (_control2Y != y) {
+ _control2Y = y;
+ emit control2YChanged();
+ emit changed();
+ }
+}
+
+void QDeclarative1PathCubic::addToPath(QPainterPath &path)
+{
+ path.cubicTo(control1X(), control1Y(), control2X(), control2Y(), x(), y());
+}
+
+/****************************************************************************/
+
+/*!
+ \qmlclass PathPercent QDeclarative1PathPercent
+ \ingroup qml-view-elements
+ \since 4.7
+ \brief The PathPercent manipulates the way a path is interpreted.
+
+ PathPercent allows you to manipulate the spacing between items on a
+ PathView's path. You can use it to bunch together items on part of
+ the path, and spread them out on other parts of the path.
+
+ The examples below show the normal distrubution of items along a path
+ compared to a distribution which places 50% of the items along the
+ PathLine section of the path.
+ \table
+ \row
+ \o \image declarative-nopercent.png
+ \o
+ \qml
+ PathView {
+ // ...
+ Path {
+ startX: 20; startY: 0
+ PathQuad { x: 50; y: 80; controlX: 0; controlY: 80 }
+ PathLine { x: 150; y: 80 }
+ PathQuad { x: 180; y: 0; controlX: 200; controlY: 80 }
+ }
+ }
+ \endqml
+ \row
+ \o \image declarative-percent.png
+ \o
+ \qml
+ PathView {
+ // ...
+ Path {
+ startX: 20; startY: 0
+ PathQuad { x: 50; y: 80; controlX: 0; controlY: 80 }
+ PathPercent { value: 0.25 }
+ PathLine { x: 150; y: 80 }
+ PathPercent { value: 0.75 }
+ PathQuad { x: 180; y: 0; controlX: 200; controlY: 80 }
+ PathPercent { value: 1 }
+ }
+ }
+ \endqml
+ \endtable
+
+ \sa Path
+*/
+
+/*!
+ \qmlproperty real PathPercent::value
+ The proporation of items that should be laid out up to this point.
+
+ This value should always be higher than the last value specified
+ by a PathPercent at a previous position in the Path.
+
+ In the following example we have a Path made up of three PathLines.
+ Normally, the items of the PathView would be laid out equally along
+ this path, with an equal number of items per line segment. PathPercent
+ allows us to specify that the first and third lines should each hold
+ 10% of the laid out items, while the second line should hold the remaining
+ 80%.
+
+ \qml
+ PathView {
+ // ...
+ Path {
+ startX: 0; startY: 0
+ PathLine { x:100; y: 0; }
+ PathPercent { value: 0.1 }
+ PathLine { x: 100; y: 100 }
+ PathPercent { value: 0.9 }
+ PathLine { x: 100; y: 0 }
+ PathPercent { value: 1 }
+ }
+ }
+ \endqml
+*/
+
+qreal QDeclarative1PathPercent::value() const
+{
+ return _value;
+}
+
+void QDeclarative1PathPercent::setValue(qreal value)
+{
+ if (_value != value) {
+ _value = value;
+ emit valueChanged();
+ emit changed();
+ }
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/graphicsitems/qdeclarativepath_p.h b/src/qtquick1/graphicsitems/qdeclarativepath_p.h
new file mode 100644
index 0000000000..e8dfad5e5f
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativepath_p.h
@@ -0,0 +1,286 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEPATH_H
+#define QDECLARATIVEPATH_H
+
+#include "qdeclarativeitem.h"
+
+#include <QtDeclarative/qdeclarative.h>
+
+#include <QtCore/QObject>
+#include <QtGui/QPainterPath>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class Q_AUTOTEST_EXPORT QDeclarative1PathElement : public QObject
+{
+ Q_OBJECT
+public:
+ QDeclarative1PathElement(QObject *parent=0) : QObject(parent) {}
+Q_SIGNALS:
+ void changed();
+};
+
+class Q_AUTOTEST_EXPORT QDeclarative1PathAttribute : public QDeclarative1PathElement
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
+ Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY valueChanged)
+public:
+ QDeclarative1PathAttribute(QObject *parent=0) : QDeclarative1PathElement(parent), _value(0) {}
+
+
+ QString name() const;
+ void setName(const QString &name);
+
+ qreal value() const;
+ void setValue(qreal value);
+
+Q_SIGNALS:
+ void nameChanged();
+ void valueChanged();
+
+private:
+ QString _name;
+ qreal _value;
+};
+
+class Q_AUTOTEST_EXPORT QDeclarative1Curve : public QDeclarative1PathElement
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)
+ Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged)
+public:
+ QDeclarative1Curve(QObject *parent=0) : QDeclarative1PathElement(parent), _x(0), _y(0) {}
+
+ qreal x() const;
+ void setX(qreal x);
+
+ qreal y() const;
+ void setY(qreal y);
+
+ virtual void addToPath(QPainterPath &) {}
+
+Q_SIGNALS:
+ void xChanged();
+ void yChanged();
+
+private:
+ qreal _x;
+ qreal _y;
+};
+
+class Q_AUTOTEST_EXPORT QDeclarative1PathLine : public QDeclarative1Curve
+{
+ Q_OBJECT
+public:
+ QDeclarative1PathLine(QObject *parent=0) : QDeclarative1Curve(parent) {}
+
+ void addToPath(QPainterPath &path);
+};
+
+class Q_AUTOTEST_EXPORT QDeclarative1PathQuad : public QDeclarative1Curve
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal controlX READ controlX WRITE setControlX NOTIFY controlXChanged)
+ Q_PROPERTY(qreal controlY READ controlY WRITE setControlY NOTIFY controlYChanged)
+public:
+ QDeclarative1PathQuad(QObject *parent=0) : QDeclarative1Curve(parent), _controlX(0), _controlY(0) {}
+
+ qreal controlX() const;
+ void setControlX(qreal x);
+
+ qreal controlY() const;
+ void setControlY(qreal y);
+
+ void addToPath(QPainterPath &path);
+
+Q_SIGNALS:
+ void controlXChanged();
+ void controlYChanged();
+
+private:
+ qreal _controlX;
+ qreal _controlY;
+};
+
+class Q_AUTOTEST_EXPORT QDeclarative1PathCubic : public QDeclarative1Curve
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal control1X READ control1X WRITE setControl1X NOTIFY control1XChanged)
+ Q_PROPERTY(qreal control1Y READ control1Y WRITE setControl1Y NOTIFY control1YChanged)
+ Q_PROPERTY(qreal control2X READ control2X WRITE setControl2X NOTIFY control2XChanged)
+ Q_PROPERTY(qreal control2Y READ control2Y WRITE setControl2Y NOTIFY control2YChanged)
+public:
+ QDeclarative1PathCubic(QObject *parent=0) : QDeclarative1Curve(parent), _control1X(0), _control1Y(0), _control2X(0), _control2Y(0) {}
+
+ qreal control1X() const;
+ void setControl1X(qreal x);
+
+ qreal control1Y() const;
+ void setControl1Y(qreal y);
+
+ qreal control2X() const;
+ void setControl2X(qreal x);
+
+ qreal control2Y() const;
+ void setControl2Y(qreal y);
+
+ void addToPath(QPainterPath &path);
+
+Q_SIGNALS:
+ void control1XChanged();
+ void control1YChanged();
+ void control2XChanged();
+ void control2YChanged();
+
+private:
+ qreal _control1X;
+ qreal _control1Y;
+ qreal _control2X;
+ qreal _control2Y;
+};
+
+class Q_AUTOTEST_EXPORT QDeclarative1PathPercent : public QDeclarative1PathElement
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY valueChanged)
+public:
+ QDeclarative1PathPercent(QObject *parent=0) : QDeclarative1PathElement(parent) {}
+
+ qreal value() const;
+ void setValue(qreal value);
+
+signals:
+ void valueChanged();
+
+private:
+ qreal _value;
+};
+
+class QDeclarative1PathPrivate;
+class Q_AUTOTEST_EXPORT QDeclarative1Path : public QObject, public QDeclarativeParserStatus
+{
+ Q_OBJECT
+
+ Q_INTERFACES(QDeclarativeParserStatus)
+ Q_PROPERTY(QDeclarativeListProperty<QDeclarative1PathElement> pathElements READ pathElements)
+ Q_PROPERTY(qreal startX READ startX WRITE setStartX NOTIFY startXChanged)
+ Q_PROPERTY(qreal startY READ startY WRITE setStartY NOTIFY startYChanged)
+ Q_PROPERTY(bool closed READ isClosed NOTIFY changed)
+ Q_CLASSINFO("DefaultProperty", "pathElements")
+ Q_INTERFACES(QDeclarativeParserStatus)
+public:
+ QDeclarative1Path(QObject *parent=0);
+ ~QDeclarative1Path();
+
+ QDeclarativeListProperty<QDeclarative1PathElement> pathElements();
+
+ qreal startX() const;
+ void setStartX(qreal x);
+
+ qreal startY() const;
+ void setStartY(qreal y);
+
+ bool isClosed() const;
+
+ QPainterPath path() const;
+ QStringList attributes() const;
+ qreal attributeAt(const QString &, qreal) const;
+ QPointF pointAt(qreal) const;
+
+Q_SIGNALS:
+ void changed();
+ void startXChanged();
+ void startYChanged();
+
+protected:
+ virtual void componentComplete();
+ virtual void classBegin();
+
+private Q_SLOTS:
+ void processPath();
+
+private:
+ struct AttributePoint {
+ AttributePoint() : percent(0), scale(1), origpercent(0) {}
+ AttributePoint(const AttributePoint &other)
+ : percent(other.percent), scale(other.scale), origpercent(other.origpercent), values(other.values) {}
+ AttributePoint &operator=(const AttributePoint &other) {
+ percent = other.percent; scale = other.scale; origpercent = other.origpercent; values = other.values; return *this;
+ }
+ qreal percent; //massaged percent along the painter path
+ qreal scale;
+ qreal origpercent; //'real' percent along the painter path
+ QHash<QString, qreal> values;
+ };
+
+ void interpolate(int idx, const QString &name, qreal value);
+ void endpoint(const QString &name);
+ void createPointCache() const;
+
+private:
+ Q_DISABLE_COPY(QDeclarative1Path)
+ Q_DECLARE_PRIVATE(QDeclarative1Path)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1PathElement)
+QML_DECLARE_TYPE(QDeclarative1PathAttribute)
+QML_DECLARE_TYPE(QDeclarative1Curve)
+QML_DECLARE_TYPE(QDeclarative1PathLine)
+QML_DECLARE_TYPE(QDeclarative1PathQuad)
+QML_DECLARE_TYPE(QDeclarative1PathCubic)
+QML_DECLARE_TYPE(QDeclarative1PathPercent)
+QML_DECLARE_TYPE(QDeclarative1Path)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEPATH_H
diff --git a/src/qtquick1/graphicsitems/qdeclarativepath_p_p.h b/src/qtquick1/graphicsitems/qdeclarativepath_p_p.h
new file mode 100644
index 0000000000..d712d777d1
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativepath_p_p.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEPATH_P_H
+#define QDECLARATIVEPATH_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qdeclarativepath_p.h"
+
+#include <QtDeclarative/qdeclarative.h>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarative1PathPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1Path)
+
+public:
+ QDeclarative1PathPrivate() : startX(0), startY(0), closed(false), componentComplete(true) { }
+
+ QPainterPath _path;
+ QList<QDeclarative1PathElement*> _pathElements;
+ mutable QVector<QPointF> _pointCache;
+ QList<QDeclarative1Path::AttributePoint> _attributePoints;
+ QStringList _attributes;
+ int startX;
+ int startY;
+ bool closed;
+ bool componentComplete;
+};
+
+QT_END_NAMESPACE
+#endif
diff --git a/src/qtquick1/graphicsitems/qdeclarativepathview.cpp b/src/qtquick1/graphicsitems/qdeclarativepathview.cpp
new file mode 100644
index 0000000000..ba914a9773
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativepathview.cpp
@@ -0,0 +1,1732 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativepathview_p.h"
+#include "QtQuick1/private/qdeclarativepathview_p_p.h"
+
+#include <QtQuick1/private/qdeclarativestate_p.h>
+#include <QtQuick1/private/qdeclarativeopenmetaobject_p.h>
+#include <QDebug>
+#include <QEvent>
+#include <QGraphicsSceneEvent>
+
+#include <qmath.h>
+#include <math.h>
+
+QT_BEGIN_NAMESPACE
+
+
+
+inline qreal qmlMod(qreal x, qreal y)
+{
+#ifdef QT_USE_MATH_H_FLOATS
+ if(sizeof(qreal) == sizeof(float))
+ return fmodf(float(x), float(y));
+ else
+#endif
+ return fmod(x, y);
+}
+
+static QDeclarative1OpenMetaObjectType *qPathViewAttachedType = 0;
+
+QDeclarative1PathViewAttached::QDeclarative1PathViewAttached(QObject *parent)
+: QObject(parent), m_percent(-1), m_view(0), m_onPath(false), m_isCurrent(false)
+{
+ if (qPathViewAttachedType) {
+ m_metaobject = new QDeclarative1OpenMetaObject(this, qPathViewAttachedType);
+ m_metaobject->setCached(true);
+ } else {
+ m_metaobject = new QDeclarative1OpenMetaObject(this);
+ }
+}
+
+QDeclarative1PathViewAttached::~QDeclarative1PathViewAttached()
+{
+}
+
+QVariant QDeclarative1PathViewAttached::value(const QByteArray &name) const
+{
+ return m_metaobject->value(name);
+}
+void QDeclarative1PathViewAttached::setValue(const QByteArray &name, const QVariant &val)
+{
+ m_metaobject->setValue(name, val);
+}
+
+
+void QDeclarative1PathViewPrivate::init()
+{
+ Q_Q(QDeclarative1PathView);
+ offset = 0;
+ q->setAcceptedMouseButtons(Qt::LeftButton);
+ q->setFlag(QGraphicsItem::ItemIsFocusScope);
+ q->setFiltersChildEvents(true);
+ q->connect(&tl, SIGNAL(updated()), q, SLOT(ticked()));
+ lastPosTime.invalidate();
+ static int timelineCompletedIdx = -1;
+ static int movementEndingIdx = -1;
+ if (timelineCompletedIdx == -1) {
+ timelineCompletedIdx = QDeclarative1TimeLine::staticMetaObject.indexOfSignal("completed()");
+ movementEndingIdx = QDeclarative1PathView::staticMetaObject.indexOfSlot("movementEnding()");
+ }
+ QMetaObject::connect(&tl, timelineCompletedIdx,
+ q, movementEndingIdx, Qt::DirectConnection);
+}
+
+QDeclarativeItem *QDeclarative1PathViewPrivate::getItem(int modelIndex)
+{
+ Q_Q(QDeclarative1PathView);
+ requestedIndex = modelIndex;
+ QDeclarativeItem *item = model->item(modelIndex, false);
+ if (item) {
+ if (!attType) {
+ // pre-create one metatype to share with all attached objects
+ attType = new QDeclarative1OpenMetaObjectType(&QDeclarative1PathViewAttached::staticMetaObject, qmlEngine(q));
+ foreach(const QString &attr, path->attributes())
+ attType->createProperty(attr.toUtf8());
+ }
+ qPathViewAttachedType = attType;
+ QDeclarative1PathViewAttached *att = static_cast<QDeclarative1PathViewAttached *>(qmlAttachedPropertiesObject<QDeclarative1PathView>(item));
+ qPathViewAttachedType = 0;
+ if (att) {
+ att->m_view = q;
+ att->setOnPath(true);
+ }
+ item->setParentItem(q);
+ QDeclarativeItemPrivate *itemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(item));
+ itemPrivate->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
+ }
+ requestedIndex = -1;
+ return item;
+}
+
+void QDeclarative1PathViewPrivate::releaseItem(QDeclarativeItem *item)
+{
+ if (!item || !model)
+ return;
+ QDeclarativeItemPrivate *itemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(item));
+ itemPrivate->removeItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
+ if (model->release(item) == 0) {
+ // item was not destroyed, and we no longer reference it.
+ if (QDeclarative1PathViewAttached *att = attached(item))
+ att->setOnPath(false);
+ }
+}
+
+QDeclarative1PathViewAttached *QDeclarative1PathViewPrivate::attached(QDeclarativeItem *item)
+{
+ return static_cast<QDeclarative1PathViewAttached *>(qmlAttachedPropertiesObject<QDeclarative1PathView>(item, false));
+}
+
+void QDeclarative1PathViewPrivate::clear()
+{
+ for (int i=0; i<items.count(); i++){
+ QDeclarativeItem *p = items[i];
+ releaseItem(p);
+ }
+ items.clear();
+}
+
+void QDeclarative1PathViewPrivate::updateMappedRange()
+{
+ if (model && pathItems != -1 && pathItems < modelCount)
+ mappedRange = qreal(pathItems)/modelCount;
+ else
+ mappedRange = 1.0;
+}
+
+qreal QDeclarative1PathViewPrivate::positionOfIndex(qreal index) const
+{
+ qreal pos = -1.0;
+
+ if (model && index >= 0 && index < modelCount) {
+ qreal start = 0.0;
+ if (haveHighlightRange && highlightRangeMode != QDeclarative1PathView::NoHighlightRange)
+ start = highlightRangeStart;
+ qreal globalPos = index + offset;
+ globalPos = qmlMod(globalPos, qreal(modelCount)) / modelCount;
+ if (pathItems != -1 && pathItems < modelCount) {
+ globalPos += start * mappedRange;
+ globalPos = qmlMod(globalPos, 1.0);
+ if (globalPos < mappedRange)
+ pos = globalPos / mappedRange;
+ } else {
+ pos = qmlMod(globalPos + start, 1.0);
+ }
+ }
+
+ return pos;
+}
+
+void QDeclarative1PathViewPrivate::createHighlight()
+{
+ Q_Q(QDeclarative1PathView);
+ if (!q->isComponentComplete())
+ return;
+
+ bool changed = false;
+ if (highlightItem) {
+ if (highlightItem->scene())
+ highlightItem->scene()->removeItem(highlightItem);
+ highlightItem->deleteLater();
+ highlightItem = 0;
+ changed = true;
+ }
+
+ QDeclarativeItem *item = 0;
+ if (highlightComponent) {
+ QDeclarativeContext *highlightContext = new QDeclarativeContext(qmlContext(q));
+ QObject *nobj = highlightComponent->create(highlightContext);
+ if (nobj) {
+ QDeclarative_setParent_noEvent(highlightContext, nobj);
+ item = qobject_cast<QDeclarativeItem *>(nobj);
+ if (!item)
+ delete nobj;
+ } else {
+ delete highlightContext;
+ }
+ } else {
+ item = new QDeclarativeItem;
+ }
+ if (item) {
+ QDeclarative_setParent_noEvent(item, q);
+ item->setParentItem(q);
+ highlightItem = item;
+ changed = true;
+ }
+ if (changed)
+ emit q->highlightItemChanged();
+}
+
+void QDeclarative1PathViewPrivate::updateHighlight()
+{
+ Q_Q(QDeclarative1PathView);
+ if (!q->isComponentComplete() || !isValid())
+ return;
+ if (highlightItem) {
+ if (haveHighlightRange && highlightRangeMode == QDeclarative1PathView::StrictlyEnforceRange) {
+ updateItem(highlightItem, highlightRangeStart);
+ } else {
+ qreal target = currentIndex;
+
+ offsetAdj = 0.0;
+ tl.reset(moveHighlight);
+ moveHighlight.setValue(highlightPosition);
+
+ const int duration = highlightMoveDuration;
+
+ if (target - highlightPosition > modelCount/2) {
+ highlightUp = false;
+ qreal distance = modelCount - target + highlightPosition;
+ tl.move(moveHighlight, 0.0, QEasingCurve(QEasingCurve::InQuad), int(duration * highlightPosition / distance));
+ tl.set(moveHighlight, modelCount-0.01);
+ tl.move(moveHighlight, target, QEasingCurve(QEasingCurve::OutQuad), int(duration * (modelCount-target) / distance));
+ } else if (target - highlightPosition <= -modelCount/2) {
+ highlightUp = true;
+ qreal distance = modelCount - highlightPosition + target;
+ tl.move(moveHighlight, modelCount-0.01, QEasingCurve(QEasingCurve::InQuad), int(duration * (modelCount-highlightPosition) / distance));
+ tl.set(moveHighlight, 0.0);
+ tl.move(moveHighlight, target, QEasingCurve(QEasingCurve::OutQuad), int(duration * target / distance));
+ } else {
+ highlightUp = highlightPosition - target < 0;
+ tl.move(moveHighlight, target, QEasingCurve(QEasingCurve::InOutQuad), duration);
+ }
+ }
+ }
+}
+
+void QDeclarative1PathViewPrivate::setHighlightPosition(qreal pos)
+{
+ if (pos != highlightPosition) {
+ qreal start = 0.0;
+ qreal end = 1.0;
+ if (haveHighlightRange && highlightRangeMode != QDeclarative1PathView::NoHighlightRange) {
+ start = highlightRangeStart;
+ end = highlightRangeEnd;
+ }
+
+ qreal range = qreal(modelCount);
+ // calc normalized position of highlight relative to offset
+ qreal relativeHighlight = qmlMod(pos + offset, range) / range;
+
+ if (!highlightUp && relativeHighlight > end * mappedRange) {
+ qreal diff = 1.0 - relativeHighlight;
+ setOffset(offset + diff * range);
+ } else if (highlightUp && relativeHighlight >= (end - start) * mappedRange) {
+ qreal diff = relativeHighlight - (end - start) * mappedRange;
+ setOffset(offset - diff * range - 0.00001);
+ }
+
+ highlightPosition = pos;
+ qreal pathPos = positionOfIndex(pos);
+ updateItem(highlightItem, pathPos);
+ if (QDeclarative1PathViewAttached *att = attached(highlightItem))
+ att->setOnPath(pathPos != -1.0);
+ }
+}
+
+void QDeclarative1PathView::pathUpdated()
+{
+ Q_D(QDeclarative1PathView);
+ QList<QDeclarativeItem*>::iterator it = d->items.begin();
+ while (it != d->items.end()) {
+ QDeclarativeItem *item = *it;
+ if (QDeclarative1PathViewAttached *att = d->attached(item))
+ att->m_percent = -1;
+ ++it;
+ }
+ refill();
+}
+
+void QDeclarative1PathViewPrivate::updateItem(QDeclarativeItem *item, qreal percent)
+{
+ if (QDeclarative1PathViewAttached *att = attached(item)) {
+ if (qFuzzyCompare(att->m_percent, percent))
+ return;
+ att->m_percent = percent;
+ foreach(const QString &attr, path->attributes())
+ att->setValue(attr.toUtf8(), path->attributeAt(attr, percent));
+ }
+ QPointF pf = path->pointAt(percent);
+ item->setX(qRound(pf.x() - item->width()/2));
+ item->setY(qRound(pf.y() - item->height()/2));
+}
+
+void QDeclarative1PathViewPrivate::regenerate()
+{
+ Q_Q(QDeclarative1PathView);
+ if (!q->isComponentComplete())
+ return;
+
+ clear();
+
+ if (!isValid())
+ return;
+
+ firstIndex = -1;
+ updateMappedRange();
+ q->refill();
+}
+
+/*!
+ \qmlclass PathView QDeclarative1PathView
+ \ingroup qml-view-elements
+ \since 4.7
+ \brief The PathView element lays out model-provided items on a path.
+ \inherits Item
+
+ A PathView displays data from models created from built-in QML elements like ListModel
+ and XmlListModel, or custom model classes defined in C++ that inherit from
+ QAbstractListModel.
+
+ The view has a \l model, which defines the data to be displayed, and
+ a \l delegate, which defines how the data should be displayed.
+ The \l delegate is instantiated for each item on the \l path.
+ The items may be flicked to move them along the path.
+
+ For example, if there is a simple list model defined in a file \c ContactModel.qml like this:
+
+ \snippet doc/src/snippets/declarative/pathview/ContactModel.qml 0
+
+ This data can be represented as a PathView, like this:
+
+ \snippet doc/src/snippets/declarative/pathview/pathview.qml 0
+
+ \image pathview.gif
+
+ (Note the above example uses PathAttribute to scale and modify the
+ opacity of the items as they rotate. This additional code can be seen in the
+ PathAttribute documentation.)
+
+ PathView does not automatically handle keyboard navigation. This is because
+ the keys to use for navigation will depend upon the shape of the path. Navigation
+ can be added quite simply by setting \c focus to \c true and calling
+ \l decrementCurrentIndex() or \l incrementCurrentIndex(), for example to navigate
+ using the left and right arrow keys:
+
+ \qml
+ PathView {
+ // ...
+ focus: true
+ Keys.onLeftPressed: decrementCurrentIndex()
+ Keys.onRightPressed: incrementCurrentIndex()
+ }
+ \endqml
+
+ The path view itself is a focus scope (see \l{qmlfocus#Acquiring Focus and Focus Scopes}{the focus documentation page} for more details).
+
+ Delegates are instantiated as needed and may be destroyed at any time.
+ State should \e never be stored in a delegate.
+
+ PathView attaches a number of properties to the root item of the delegate, for example
+ \c {PathView.isCurrentItem}. In the following example, the root delegate item can access
+ this attached property directly as \c PathView.isCurrentItem, while the child
+ \c nameText object must refer to this property as \c wrapper.PathView.isCurrentItem.
+
+ \snippet doc/src/snippets/declarative/pathview/pathview.qml 1
+
+ \bold Note that views do not enable \e clip automatically. If the view
+ is not clipped by another item or the screen, it will be necessary
+ to set \e {clip: true} in order to have the out of view items clipped
+ nicely.
+
+ \sa Path, {declarative/modelviews/pathview}{PathView example}
+*/
+
+QDeclarative1PathView::QDeclarative1PathView(QDeclarativeItem *parent)
+ : QDeclarativeItem(*(new QDeclarative1PathViewPrivate), parent)
+{
+ Q_D(QDeclarative1PathView);
+ d->init();
+}
+
+QDeclarative1PathView::~QDeclarative1PathView()
+{
+ Q_D(QDeclarative1PathView);
+ d->clear();
+ if (d->attType)
+ d->attType->release();
+ if (d->ownModel)
+ delete d->model;
+}
+
+/*!
+ \qmlattachedproperty PathView PathView::view
+ This attached property holds the view that manages this delegate instance.
+
+ It is attached to each instance of the delegate.
+*/
+
+/*!
+ \qmlattachedproperty bool PathView::onPath
+ This attached property holds whether the item is currently on the path.
+
+ If a pathItemCount has been set, it is possible that some items may
+ be instantiated, but not considered to be currently on the path.
+ Usually, these items would be set invisible, for example:
+
+ \qml
+ Component {
+ Rectangle {
+ visible: PathView.onPath
+ // ...
+ }
+ }
+ \endqml
+
+ It is attached to each instance of the delegate.
+*/
+
+/*!
+ \qmlattachedproperty bool PathView::isCurrentItem
+ This attached property is true if this delegate is the current item; otherwise false.
+
+ It is attached to each instance of the delegate.
+
+ This property may be used to adjust the appearance of the current item.
+
+ \snippet doc/src/snippets/declarative/pathview/pathview.qml 1
+*/
+
+/*!
+ \qmlproperty model PathView::model
+ This property holds the model providing data for the view.
+
+ The model provides a set of data that is used to create the items for the view.
+ For large or dynamic datasets the model is usually provided by a C++ model object.
+ Models can also be created directly in QML, using the ListModel element.
+
+ \sa {qmlmodels}{Data Models}
+*/
+QVariant QDeclarative1PathView::model() const
+{
+ Q_D(const QDeclarative1PathView);
+ return d->modelVariant;
+}
+
+void QDeclarative1PathView::setModel(const QVariant &model)
+{
+ Q_D(QDeclarative1PathView);
+ if (d->modelVariant == model)
+ return;
+
+ if (d->model) {
+ disconnect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
+ disconnect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
+ disconnect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int)));
+ disconnect(d->model, SIGNAL(modelReset()), this, SLOT(modelReset()));
+ disconnect(d->model, SIGNAL(createdItem(int,QDeclarativeItem*)), this, SLOT(createdItem(int,QDeclarativeItem*)));
+ for (int i=0; i<d->items.count(); i++){
+ QDeclarativeItem *p = d->items[i];
+ d->model->release(p);
+ }
+ d->items.clear();
+ }
+
+ d->modelVariant = model;
+ QObject *object = qvariant_cast<QObject*>(model);
+ QDeclarative1VisualModel *vim = 0;
+ if (object && (vim = qobject_cast<QDeclarative1VisualModel *>(object))) {
+ if (d->ownModel) {
+ delete d->model;
+ d->ownModel = false;
+ }
+ d->model = vim;
+ } else {
+ if (!d->ownModel) {
+ d->model = new QDeclarative1VisualDataModel(qmlContext(this), this);
+ d->ownModel = true;
+ }
+ if (QDeclarative1VisualDataModel *dataModel = qobject_cast<QDeclarative1VisualDataModel*>(d->model))
+ dataModel->setModel(model);
+ }
+ d->modelCount = 0;
+ if (d->model) {
+ connect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
+ connect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
+ connect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int)));
+ connect(d->model, SIGNAL(modelReset()), this, SLOT(modelReset()));
+ connect(d->model, SIGNAL(createdItem(int,QDeclarativeItem*)), this, SLOT(createdItem(int,QDeclarativeItem*)));
+ d->modelCount = d->model->count();
+ if (d->model->count())
+ d->offset = qmlMod(d->offset, qreal(d->model->count()));
+ if (d->offset < 0)
+ d->offset = d->model->count() + d->offset;
+}
+ d->regenerate();
+ d->fixOffset();
+ emit countChanged();
+ emit modelChanged();
+}
+
+/*!
+ \qmlproperty int PathView::count
+ This property holds the number of items in the model.
+*/
+int QDeclarative1PathView::count() const
+{
+ Q_D(const QDeclarative1PathView);
+ return d->model ? d->modelCount : 0;
+}
+
+/*!
+ \qmlproperty Path PathView::path
+ This property holds the path used to lay out the items.
+ For more information see the \l Path documentation.
+*/
+QDeclarative1Path *QDeclarative1PathView::path() const
+{
+ Q_D(const QDeclarative1PathView);
+ return d->path;
+}
+
+void QDeclarative1PathView::setPath(QDeclarative1Path *path)
+{
+ Q_D(QDeclarative1PathView);
+ if (d->path == path)
+ return;
+ if (d->path)
+ disconnect(d->path, SIGNAL(changed()), this, SLOT(pathUpdated()));
+ d->path = path;
+ connect(d->path, SIGNAL(changed()), this, SLOT(pathUpdated()));
+ if (d->isValid() && isComponentComplete()) {
+ d->clear();
+ if (d->attType) {
+ d->attType->release();
+ d->attType = 0;
+ }
+ d->regenerate();
+ }
+ emit pathChanged();
+}
+
+/*!
+ \qmlproperty int PathView::currentIndex
+ This property holds the index of the current item.
+*/
+int QDeclarative1PathView::currentIndex() const
+{
+ Q_D(const QDeclarative1PathView);
+ return d->currentIndex;
+}
+
+void QDeclarative1PathView::setCurrentIndex(int idx)
+{
+ Q_D(QDeclarative1PathView);
+ if (d->model && d->modelCount)
+ idx = qAbs(idx % d->modelCount);
+ if (d->model && idx != d->currentIndex) {
+ if (d->modelCount) {
+ int itemIndex = (d->currentIndex - d->firstIndex + d->modelCount) % d->modelCount;
+ if (itemIndex < d->items.count()) {
+ if (QDeclarativeItem *item = d->items.at(itemIndex)) {
+ if (QDeclarative1PathViewAttached *att = d->attached(item))
+ att->setIsCurrentItem(false);
+ }
+ }
+ }
+ d->currentItem = 0;
+ d->moveReason = QDeclarative1PathViewPrivate::SetIndex;
+ d->currentIndex = idx;
+ if (d->modelCount) {
+ if (d->haveHighlightRange && d->highlightRangeMode == QDeclarative1PathView::StrictlyEnforceRange)
+ d->snapToCurrent();
+ int itemIndex = (idx - d->firstIndex + d->modelCount) % d->modelCount;
+ if (itemIndex < d->items.count()) {
+ d->currentItem = d->items.at(itemIndex);
+ d->currentItem->setFocus(true);
+ if (QDeclarative1PathViewAttached *att = d->attached(d->currentItem))
+ att->setIsCurrentItem(true);
+ }
+ d->currentItemOffset = d->positionOfIndex(d->currentIndex);
+ d->updateHighlight();
+ }
+ emit currentIndexChanged();
+ }
+}
+
+/*!
+ \qmlmethod PathView::incrementCurrentIndex()
+
+ Increments the current index.
+
+ \bold Note: methods should only be called after the Component has completed.
+*/
+void QDeclarative1PathView::incrementCurrentIndex()
+{
+ Q_D(QDeclarative1PathView);
+ d->moveDirection = QDeclarative1PathViewPrivate::Positive;
+ setCurrentIndex(currentIndex()+1);
+}
+
+
+/*!
+ \qmlmethod PathView::decrementCurrentIndex()
+
+ Decrements the current index.
+
+ \bold Note: methods should only be called after the Component has completed.
+*/
+void QDeclarative1PathView::decrementCurrentIndex()
+{
+ Q_D(QDeclarative1PathView);
+ if (d->model && d->modelCount) {
+ int idx = currentIndex()-1;
+ if (idx < 0)
+ idx = d->modelCount - 1;
+ d->moveDirection = QDeclarative1PathViewPrivate::Negative;
+ setCurrentIndex(idx);
+ }
+}
+
+/*!
+ \qmlproperty real PathView::offset
+
+ The offset specifies how far along the path the items are from their initial positions.
+ This is a real number that ranges from 0.0 to the count of items in the model.
+*/
+qreal QDeclarative1PathView::offset() const
+{
+ Q_D(const QDeclarative1PathView);
+ return d->offset;
+}
+
+void QDeclarative1PathView::setOffset(qreal offset)
+{
+ Q_D(QDeclarative1PathView);
+ d->setOffset(offset);
+ d->updateCurrent();
+}
+
+void QDeclarative1PathViewPrivate::setOffset(qreal o)
+{
+ Q_Q(QDeclarative1PathView);
+ if (offset != o) {
+ if (isValid() && q->isComponentComplete()) {
+ offset = qmlMod(o, qreal(modelCount));
+ if (offset < 0)
+ offset += qreal(modelCount);
+ q->refill();
+ } else {
+ offset = o;
+ }
+ emit q->offsetChanged();
+ }
+}
+
+void QDeclarative1PathViewPrivate::setAdjustedOffset(qreal o)
+{
+ setOffset(o+offsetAdj);
+}
+
+/*!
+ \qmlproperty Component PathView::highlight
+ This property holds the component to use as the highlight.
+
+ An instance of the highlight component will be created for each view.
+ The geometry of the resultant component instance will be managed by the view
+ so as to stay with the current item.
+
+ The below example demonstrates how to make a simple highlight. Note the use
+ of the \l{PathView::onPath}{PathView.onPath} attached property to ensure that
+ the highlight is hidden when flicked away from the path.
+
+ \qml
+ Component {
+ Rectangle {
+ visible: PathView.onPath
+ // ...
+ }
+ }
+ \endqml
+
+ \sa highlightItem, highlightRangeMode
+*/
+
+QDeclarativeComponent *QDeclarative1PathView::highlight() const
+{
+ Q_D(const QDeclarative1PathView);
+ return d->highlightComponent;
+}
+
+void QDeclarative1PathView::setHighlight(QDeclarativeComponent *highlight)
+{
+ Q_D(QDeclarative1PathView);
+ if (highlight != d->highlightComponent) {
+ d->highlightComponent = highlight;
+ d->createHighlight();
+ d->updateHighlight();
+ emit highlightChanged();
+ }
+}
+
+/*!
+ \qmlproperty Item PathView::highlightItem
+
+ \c highlightItem holds the highlight item, which was created
+ from the \l highlight component.
+
+ \sa highlight
+*/
+QDeclarativeItem *QDeclarative1PathView::highlightItem()
+{
+ Q_D(const QDeclarative1PathView);
+ return d->highlightItem;
+}
+/*!
+ \qmlproperty real PathView::preferredHighlightBegin
+ \qmlproperty real PathView::preferredHighlightEnd
+ \qmlproperty enumeration PathView::highlightRangeMode
+
+ These properties set the preferred range of the highlight (current item)
+ within the view. The preferred values must be in the range 0.0-1.0.
+
+ If highlightRangeMode is set to \e PathView.NoHighlightRange
+
+ If highlightRangeMode is set to \e PathView.ApplyRange the view will
+ attempt to maintain the highlight within the range, however
+ the highlight can move outside of the range at the ends of the path
+ or due to a mouse interaction.
+
+ If highlightRangeMode is set to \e PathView.StrictlyEnforceRange the highlight will never
+ move outside of the range. This means that the current item will change
+ if a keyboard or mouse action would cause the highlight to move
+ outside of the range.
+
+ Note that this is the correct way to influence where the
+ current item ends up when the view moves. For example, if you want the
+ currently selected item to be in the middle of the path, then set the
+ highlight range to be 0.5,0.5 and highlightRangeMode to PathView.StrictlyEnforceRange.
+ Then, when the path scrolls,
+ the currently selected item will be the item at that position. This also applies to
+ when the currently selected item changes - it will scroll to within the preferred
+ highlight range. Furthermore, the behaviour of the current item index will occur
+ whether or not a highlight exists.
+
+ The default value is \e PathView.StrictlyEnforceRange.
+
+ Note that a valid range requires preferredHighlightEnd to be greater
+ than or equal to preferredHighlightBegin.
+*/
+qreal QDeclarative1PathView::preferredHighlightBegin() const
+{
+ Q_D(const QDeclarative1PathView);
+ return d->highlightRangeStart;
+}
+
+void QDeclarative1PathView::setPreferredHighlightBegin(qreal start)
+{
+ Q_D(QDeclarative1PathView);
+ if (d->highlightRangeStart == start || start < 0 || start > 1.0)
+ return;
+ d->highlightRangeStart = start;
+ d->haveHighlightRange = d->highlightRangeMode != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
+ refill();
+ emit preferredHighlightBeginChanged();
+}
+
+qreal QDeclarative1PathView::preferredHighlightEnd() const
+{
+ Q_D(const QDeclarative1PathView);
+ return d->highlightRangeEnd;
+}
+
+void QDeclarative1PathView::setPreferredHighlightEnd(qreal end)
+{
+ Q_D(QDeclarative1PathView);
+ if (d->highlightRangeEnd == end || end < 0 || end > 1.0)
+ return;
+ d->highlightRangeEnd = end;
+ d->haveHighlightRange = d->highlightRangeMode != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
+ refill();
+ emit preferredHighlightEndChanged();
+}
+
+QDeclarative1PathView::HighlightRangeMode QDeclarative1PathView::highlightRangeMode() const
+{
+ Q_D(const QDeclarative1PathView);
+ return d->highlightRangeMode;
+}
+
+void QDeclarative1PathView::setHighlightRangeMode(HighlightRangeMode mode)
+{
+ Q_D(QDeclarative1PathView);
+ if (d->highlightRangeMode == mode)
+ return;
+ d->highlightRangeMode = mode;
+ d->haveHighlightRange = d->highlightRangeMode != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
+ emit highlightRangeModeChanged();
+}
+
+
+/*!
+ \qmlproperty int PathView::highlightMoveDuration
+ This property holds the move animation duration of the highlight delegate.
+
+ If the highlightRangeMode is StrictlyEnforceRange then this property
+ determines the speed that the items move along the path.
+
+ The default value for the duration is 300ms.
+*/
+int QDeclarative1PathView::highlightMoveDuration() const
+{
+ Q_D(const QDeclarative1PathView);
+ return d->highlightMoveDuration;
+}
+
+void QDeclarative1PathView::setHighlightMoveDuration(int duration)
+{
+ Q_D(QDeclarative1PathView);
+ if (d->highlightMoveDuration == duration)
+ return;
+ d->highlightMoveDuration = duration;
+ emit highlightMoveDurationChanged();
+}
+
+/*!
+ \qmlproperty real PathView::dragMargin
+ This property holds the maximum distance from the path that initiate mouse dragging.
+
+ By default the path can only be dragged by clicking on an item. If
+ dragMargin is greater than zero, a drag can be initiated by clicking
+ within dragMargin pixels of the path.
+*/
+qreal QDeclarative1PathView::dragMargin() const
+{
+ Q_D(const QDeclarative1PathView);
+ return d->dragMargin;
+}
+
+void QDeclarative1PathView::setDragMargin(qreal dragMargin)
+{
+ Q_D(QDeclarative1PathView);
+ if (d->dragMargin == dragMargin)
+ return;
+ d->dragMargin = dragMargin;
+ emit dragMarginChanged();
+}
+
+/*!
+ \qmlproperty real PathView::flickDeceleration
+ This property holds the rate at which a flick will decelerate.
+
+ The default is 100.
+*/
+qreal QDeclarative1PathView::flickDeceleration() const
+{
+ Q_D(const QDeclarative1PathView);
+ return d->deceleration;
+}
+
+void QDeclarative1PathView::setFlickDeceleration(qreal dec)
+{
+ Q_D(QDeclarative1PathView);
+ if (d->deceleration == dec)
+ return;
+ d->deceleration = dec;
+ emit flickDecelerationChanged();
+}
+
+/*!
+ \qmlproperty bool PathView::interactive
+
+ A user cannot drag or flick a PathView that is not interactive.
+
+ This property is useful for temporarily disabling flicking. This allows
+ special interaction with PathView's children.
+*/
+bool QDeclarative1PathView::isInteractive() const
+{
+ Q_D(const QDeclarative1PathView);
+ return d->interactive;
+}
+
+void QDeclarative1PathView::setInteractive(bool interactive)
+{
+ Q_D(QDeclarative1PathView);
+ if (interactive != d->interactive) {
+ d->interactive = interactive;
+ if (!interactive)
+ d->tl.clear();
+ emit interactiveChanged();
+ }
+}
+
+/*!
+ \qmlproperty bool PathView::moving
+
+ This property holds whether the view is currently moving
+ due to the user either dragging or flicking the view.
+*/
+bool QDeclarative1PathView::isMoving() const
+{
+ Q_D(const QDeclarative1PathView);
+ return d->moving;
+}
+
+/*!
+ \qmlproperty bool PathView::flicking
+
+ This property holds whether the view is currently moving
+ due to the user flicking the view.
+*/
+bool QDeclarative1PathView::isFlicking() const
+{
+ Q_D(const QDeclarative1PathView);
+ return d->flicking;
+}
+
+/*!
+ \qmlsignal PathView::onMovementStarted()
+
+ This handler is called when the view begins moving due to user
+ interaction.
+*/
+
+/*!
+ \qmlsignal PathView::onMovementEnded()
+
+ This handler is called when the view stops moving due to user
+ interaction. If a flick was generated, this handler will
+ be triggered once the flick stops. If a flick was not
+ generated, the handler will be triggered when the
+ user stops dragging - i.e. a mouse or touch release.
+*/
+
+/*!
+ \qmlsignal PathView::onFlickStarted()
+
+ This handler is called when the view is flicked. A flick
+ starts from the point that the mouse or touch is released,
+ while still in motion.
+*/
+
+/*!
+ \qmlsignal PathView::onFlickEnded()
+
+ This handler is called when the view stops moving due to a flick.
+*/
+
+/*!
+ \qmlproperty Component PathView::delegate
+
+ The delegate provides a template defining each item instantiated by the view.
+ The index is exposed as an accessible \c index property. Properties of the
+ model are also available depending upon the type of \l {qmlmodels}{Data Model}.
+
+ The number of elements in the delegate has a direct effect on the
+ flicking performance of the view when pathItemCount is specified. If at all possible, place functionality
+ that is not needed for the normal display of the delegate in a \l Loader which
+ can load additional elements when needed.
+
+ Note that the PathView will layout the items based on the size of the root
+ item in the delegate.
+
+ Here is an example delegate:
+ \snippet doc/src/snippets/declarative/pathview/pathview.qml 1
+*/
+QDeclarativeComponent *QDeclarative1PathView::delegate() const
+{
+ Q_D(const QDeclarative1PathView);
+ if (d->model) {
+ if (QDeclarative1VisualDataModel *dataModel = qobject_cast<QDeclarative1VisualDataModel*>(d->model))
+ return dataModel->delegate();
+ }
+
+ return 0;
+}
+
+void QDeclarative1PathView::setDelegate(QDeclarativeComponent *delegate)
+{
+ Q_D(QDeclarative1PathView);
+ if (delegate == this->delegate())
+ return;
+ if (!d->ownModel) {
+ d->model = new QDeclarative1VisualDataModel(qmlContext(this));
+ d->ownModel = true;
+ }
+ if (QDeclarative1VisualDataModel *dataModel = qobject_cast<QDeclarative1VisualDataModel*>(d->model)) {
+ int oldCount = dataModel->count();
+ dataModel->setDelegate(delegate);
+ d->modelCount = dataModel->count();
+ d->regenerate();
+ if (oldCount != dataModel->count())
+ emit countChanged();
+ emit delegateChanged();
+ }
+}
+
+/*!
+ \qmlproperty int PathView::pathItemCount
+ This property holds the number of items visible on the path at any one time.
+*/
+int QDeclarative1PathView::pathItemCount() const
+{
+ Q_D(const QDeclarative1PathView);
+ return d->pathItems;
+}
+
+void QDeclarative1PathView::setPathItemCount(int i)
+{
+ Q_D(QDeclarative1PathView);
+ if (i == d->pathItems)
+ return;
+ if (i < 1)
+ i = 1;
+ d->pathItems = i;
+ d->updateMappedRange();
+ if (d->isValid() && isComponentComplete()) {
+ d->regenerate();
+ }
+ emit pathItemCountChanged();
+}
+
+QPointF QDeclarative1PathViewPrivate::pointNear(const QPointF &point, qreal *nearPercent) const
+{
+ //XXX maybe do recursively at increasing resolution.
+ qreal mindist = 1e10; // big number
+ QPointF nearPoint = path->pointAt(0);
+ qreal nearPc = 0;
+ for (qreal i=1; i < 1000; i++) {
+ QPointF pt = path->pointAt(i/1000.0);
+ QPointF diff = pt - point;
+ qreal dist = diff.x()*diff.x() + diff.y()*diff.y();
+ if (dist < mindist) {
+ nearPoint = pt;
+ nearPc = i;
+ mindist = dist;
+ }
+ }
+
+ if (nearPercent)
+ *nearPercent = nearPc / 1000.0;
+
+ return nearPoint;
+}
+
+void QDeclarative1PathView::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QDeclarative1PathView);
+ if (d->interactive) {
+ d->handleMousePressEvent(event);
+ event->accept();
+ } else {
+ QDeclarativeItem::mousePressEvent(event);
+ }
+}
+
+void QDeclarative1PathViewPrivate::handleMousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_Q(QDeclarative1PathView);
+ if (!interactive || !items.count())
+ return;
+ QPointF scenePoint = q->mapToScene(event->pos());
+ int idx = 0;
+ for (; idx < items.count(); ++idx) {
+ QRectF rect = items.at(idx)->boundingRect();
+ rect = items.at(idx)->mapToScene(rect).boundingRect();
+ if (rect.contains(scenePoint))
+ break;
+ }
+ if (idx == items.count() && dragMargin == 0.) // didn't click on an item
+ return;
+
+ startPoint = pointNear(event->pos(), &startPc);
+ if (idx == items.count()) {
+ qreal distance = qAbs(event->pos().x() - startPoint.x()) + qAbs(event->pos().y() - startPoint.y());
+ if (distance > dragMargin)
+ return;
+ }
+
+ if (tl.isActive() && flicking)
+ stealMouse = true; // If we've been flicked then steal the click.
+ else
+ stealMouse = false;
+
+ lastElapsed = 0;
+ lastDist = 0;
+ QDeclarativeItemPrivate::start(lastPosTime);
+ tl.clear();
+}
+
+void QDeclarative1PathView::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QDeclarative1PathView);
+ if (d->interactive) {
+ d->handleMouseMoveEvent(event);
+ if (d->stealMouse)
+ setKeepMouseGrab(true);
+ event->accept();
+ } else {
+ QDeclarativeItem::mouseMoveEvent(event);
+ }
+}
+
+void QDeclarative1PathViewPrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_Q(QDeclarative1PathView);
+ if (!interactive || !lastPosTime.isValid())
+ return;
+
+ qreal newPc;
+ QPointF pathPoint = pointNear(event->pos(), &newPc);
+ if (!stealMouse) {
+ QPointF delta = pathPoint - startPoint;
+ if (qAbs(delta.x()) > QApplication::startDragDistance() || qAbs(delta.y()) > QApplication::startDragDistance()) {
+ stealMouse = true;
+ startPc = newPc;
+ }
+ }
+
+ if (stealMouse) {
+ moveReason = QDeclarative1PathViewPrivate::Mouse;
+ qreal diff = (newPc - startPc)*modelCount*mappedRange;
+ if (diff) {
+ q->setOffset(offset + diff);
+
+ if (diff > modelCount/2)
+ diff -= modelCount;
+ else if (diff < -modelCount/2)
+ diff += modelCount;
+
+ lastElapsed = QDeclarativeItemPrivate::restart(lastPosTime);
+ lastDist = diff;
+ startPc = newPc;
+ }
+ if (!moving) {
+ moving = true;
+ emit q->movingChanged();
+ emit q->movementStarted();
+ }
+ }
+}
+
+void QDeclarative1PathView::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QDeclarative1PathView);
+ if (d->interactive) {
+ d->handleMouseReleaseEvent(event);
+ event->accept();
+ ungrabMouse();
+ } else {
+ QDeclarativeItem::mouseReleaseEvent(event);
+ }
+}
+
+void QDeclarative1PathViewPrivate::handleMouseReleaseEvent(QGraphicsSceneMouseEvent *)
+{
+ Q_Q(QDeclarative1PathView);
+ stealMouse = false;
+ q->setKeepMouseGrab(false);
+ if (!interactive || !lastPosTime.isValid())
+ return;
+
+ qreal elapsed = qreal(lastElapsed + QDeclarativeItemPrivate::elapsed(lastPosTime)) / 1000.;
+ qreal velocity = elapsed > 0. ? lastDist / elapsed : 0;
+ if (model && modelCount && qAbs(velocity) > 1.) {
+ qreal count = pathItems == -1 ? modelCount : pathItems;
+ if (qAbs(velocity) > count * 2) // limit velocity
+ velocity = (velocity > 0 ? count : -count) * 2;
+ // Calculate the distance to be travelled
+ qreal v2 = velocity*velocity;
+ qreal accel = deceleration/10;
+ // + 0.25 to encourage moving at least one item in the flick direction
+ qreal dist = qMin(qreal(modelCount-1), qreal(v2 / (accel * 2.0) + 0.25));
+ if (haveHighlightRange && highlightRangeMode == QDeclarative1PathView::StrictlyEnforceRange) {
+ // round to nearest item.
+ if (velocity > 0.)
+ dist = qRound(dist + offset) - offset;
+ else
+ dist = qRound(dist - offset) + offset;
+ // Calculate accel required to stop on item boundary
+ if (dist <= 0.) {
+ dist = 0.;
+ accel = 0.;
+ } else {
+ accel = v2 / (2.0f * qAbs(dist));
+ }
+ }
+ offsetAdj = 0.0;
+ moveOffset.setValue(offset);
+ tl.accel(moveOffset, velocity, accel, dist);
+ tl.callback(QDeclarative1TimeLineCallback(&moveOffset, fixOffsetCallback, this));
+ if (!flicking) {
+ flicking = true;
+ emit q->flickingChanged();
+ emit q->flickStarted();
+ }
+ } else {
+ fixOffset();
+ }
+
+ lastPosTime.invalidate();
+ if (!tl.isActive())
+ q->movementEnding();
+}
+
+bool QDeclarative1PathView::sendMouseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QDeclarative1PathView);
+ QGraphicsSceneMouseEvent mouseEvent(event->type());
+ QRectF myRect = mapToScene(QRectF(0, 0, width(), height())).boundingRect();
+ QGraphicsScene *s = scene();
+ QDeclarativeItem *grabber = s ? qobject_cast<QDeclarativeItem*>(s->mouseGrabberItem()) : 0;
+ bool stealThisEvent = d->stealMouse;
+ if ((stealThisEvent || myRect.contains(event->scenePos().toPoint())) && (!grabber || !grabber->keepMouseGrab())) {
+ mouseEvent.setAccepted(false);
+ for (int i = 0x1; i <= 0x10; i <<= 1) {
+ if (event->buttons() & i) {
+ Qt::MouseButton button = Qt::MouseButton(i);
+ mouseEvent.setButtonDownPos(button, mapFromScene(event->buttonDownPos(button)));
+ }
+ }
+ mouseEvent.setScenePos(event->scenePos());
+ mouseEvent.setLastScenePos(event->lastScenePos());
+ mouseEvent.setPos(mapFromScene(event->scenePos()));
+ mouseEvent.setLastPos(mapFromScene(event->lastScenePos()));
+
+ switch(mouseEvent.type()) {
+ case QEvent::GraphicsSceneMouseMove:
+ d->handleMouseMoveEvent(&mouseEvent);
+ break;
+ case QEvent::GraphicsSceneMousePress:
+ d->handleMousePressEvent(&mouseEvent);
+ stealThisEvent = d->stealMouse; // Update stealThisEvent in case changed by function call above
+ break;
+ case QEvent::GraphicsSceneMouseRelease:
+ d->handleMouseReleaseEvent(&mouseEvent);
+ break;
+ default:
+ break;
+ }
+ grabber = qobject_cast<QDeclarativeItem*>(s->mouseGrabberItem());
+ if (grabber && stealThisEvent && !grabber->keepMouseGrab() && grabber != this)
+ grabMouse();
+
+ return d->stealMouse;
+ } else if (d->lastPosTime.isValid()) {
+ d->lastPosTime.invalidate();
+ }
+ if (mouseEvent.type() == QEvent::GraphicsSceneMouseRelease)
+ d->stealMouse = false;
+ return false;
+}
+
+bool QDeclarative1PathView::sceneEventFilter(QGraphicsItem *i, QEvent *e)
+{
+ Q_D(QDeclarative1PathView);
+ if (!isVisible() || !d->interactive)
+ return QDeclarativeItem::sceneEventFilter(i, e);
+
+ switch (e->type()) {
+ case QEvent::GraphicsSceneMousePress:
+ case QEvent::GraphicsSceneMouseMove:
+ case QEvent::GraphicsSceneMouseRelease:
+ return sendMouseEvent(static_cast<QGraphicsSceneMouseEvent *>(e));
+ default:
+ break;
+ }
+
+ return QDeclarativeItem::sceneEventFilter(i, e);
+}
+
+bool QDeclarative1PathView::event(QEvent *event)
+{
+ if (event->type() == QEvent::User) {
+ refill();
+ return true;
+ }
+
+ return QDeclarativeItem::event(event);
+}
+
+void QDeclarative1PathView::componentComplete()
+{
+ Q_D(QDeclarative1PathView);
+ QDeclarativeItem::componentComplete();
+ d->createHighlight();
+ // It is possible that a refill has already happended to to Path
+ // bindings being handled in the componentComplete(). If so
+ // don't do it again.
+ if (d->items.count() == 0 && d->model) {
+ d->modelCount = d->model->count();
+ d->regenerate();
+ }
+ d->updateHighlight();
+}
+
+void QDeclarative1PathView::refill()
+{
+ Q_D(QDeclarative1PathView);
+ if (!d->isValid() || !isComponentComplete())
+ return;
+
+ d->layoutScheduled = false;
+ bool currentVisible = false;
+
+ // first move existing items and remove items off path
+ int idx = d->firstIndex;
+ QList<QDeclarativeItem*>::iterator it = d->items.begin();
+ while (it != d->items.end()) {
+ qreal pos = d->positionOfIndex(idx);
+ QDeclarativeItem *item = *it;
+ if (pos >= 0.0) {
+ d->updateItem(item, pos);
+ if (idx == d->currentIndex) {
+ currentVisible = true;
+ d->currentItemOffset = pos;
+ }
+ ++it;
+ } else {
+// qDebug() << "release";
+ d->updateItem(item, 1.0);
+ d->releaseItem(item);
+ if (it == d->items.begin()) {
+ if (++d->firstIndex >= d->modelCount)
+ d->firstIndex = 0;
+ }
+ it = d->items.erase(it);
+ }
+ ++idx;
+ if (idx >= d->modelCount)
+ idx = 0;
+ }
+ if (!d->items.count())
+ d->firstIndex = -1;
+
+ if (d->modelCount) {
+ // add items to beginning and end
+ int count = d->pathItems == -1 ? d->modelCount : qMin(d->pathItems, d->modelCount);
+ if (d->items.count() < count) {
+ int idx = qRound(d->modelCount - d->offset) % d->modelCount;
+ qreal startPos = 0.0;
+ if (d->haveHighlightRange && d->highlightRangeMode != QDeclarative1PathView::NoHighlightRange)
+ startPos = d->highlightRangeStart;
+ if (d->firstIndex >= 0) {
+ startPos = d->positionOfIndex(d->firstIndex);
+ idx = (d->firstIndex + d->items.count()) % d->modelCount;
+ }
+ qreal pos = d->positionOfIndex(idx);
+ while ((pos > startPos || !d->items.count()) && d->items.count() < count) {
+ // qDebug() << "append" << idx;
+ QDeclarativeItem *item = d->getItem(idx);
+ if (d->model->completePending())
+ item->setZValue(idx+1);
+ if (d->currentIndex == idx) {
+ item->setFocus(true);
+ if (QDeclarative1PathViewAttached *att = d->attached(item))
+ att->setIsCurrentItem(true);
+ currentVisible = true;
+ d->currentItemOffset = pos;
+ d->currentItem = item;
+ }
+ if (d->items.count() == 0)
+ d->firstIndex = idx;
+ d->items.append(item);
+ d->updateItem(item, pos);
+ if (d->model->completePending())
+ d->model->completeItem();
+ ++idx;
+ if (idx >= d->modelCount)
+ idx = 0;
+ pos = d->positionOfIndex(idx);
+ }
+
+ idx = d->firstIndex - 1;
+ if (idx < 0)
+ idx = d->modelCount - 1;
+ pos = d->positionOfIndex(idx);
+ while (pos >= 0.0 && pos < startPos) {
+ // qDebug() << "prepend" << idx;
+ QDeclarativeItem *item = d->getItem(idx);
+ if (d->model->completePending())
+ item->setZValue(idx+1);
+ if (d->currentIndex == idx) {
+ item->setFocus(true);
+ if (QDeclarative1PathViewAttached *att = d->attached(item))
+ att->setIsCurrentItem(true);
+ currentVisible = true;
+ d->currentItemOffset = pos;
+ d->currentItem = item;
+ }
+ d->items.prepend(item);
+ d->updateItem(item, pos);
+ if (d->model->completePending())
+ d->model->completeItem();
+ d->firstIndex = idx;
+ idx = d->firstIndex - 1;
+ if (idx < 0)
+ idx = d->modelCount - 1;
+ pos = d->positionOfIndex(idx);
+ }
+ }
+ }
+
+ if (!currentVisible)
+ d->currentItemOffset = 1.0;
+
+ if (d->highlightItem && d->haveHighlightRange && d->highlightRangeMode == QDeclarative1PathView::StrictlyEnforceRange) {
+ d->updateItem(d->highlightItem, d->highlightRangeStart);
+ if (QDeclarative1PathViewAttached *att = d->attached(d->highlightItem))
+ att->setOnPath(true);
+ } else if (d->highlightItem && d->moveReason != QDeclarative1PathViewPrivate::SetIndex) {
+ d->updateItem(d->highlightItem, d->currentItemOffset);
+ if (QDeclarative1PathViewAttached *att = d->attached(d->highlightItem))
+ att->setOnPath(currentVisible);
+ }
+ while (d->itemCache.count())
+ d->releaseItem(d->itemCache.takeLast());
+}
+
+void QDeclarative1PathView::itemsInserted(int modelIndex, int count)
+{
+ //XXX support animated insertion
+ Q_D(QDeclarative1PathView);
+ if (!d->isValid() || !isComponentComplete())
+ return;
+
+ if (d->modelCount) {
+ d->itemCache += d->items;
+ d->items.clear();
+ if (modelIndex <= d->currentIndex) {
+ d->currentIndex += count;
+ emit currentIndexChanged();
+ } else if (d->offset != 0) {
+ d->offset += count;
+ d->offsetAdj += count;
+ }
+ }
+ d->modelCount += count;
+ if (d->flicking || d->moving) {
+ d->regenerate();
+ d->updateCurrent();
+ } else {
+ d->firstIndex = -1;
+ d->updateMappedRange();
+ d->scheduleLayout();
+ }
+ emit countChanged();
+}
+
+void QDeclarative1PathView::itemsRemoved(int modelIndex, int count)
+{
+ //XXX support animated removal
+ Q_D(QDeclarative1PathView);
+ if (!d->model || !d->modelCount || !d->model->isValid() || !d->path || !isComponentComplete())
+ return;
+
+ // fix current
+ bool currentChanged = false;
+ if (d->currentIndex >= modelIndex + count) {
+ d->currentIndex -= count;
+ currentChanged = true;
+ } else if (d->currentIndex >= modelIndex && d->currentIndex < modelIndex + count) {
+ // current item has been removed.
+ d->currentIndex = qMin(modelIndex, d->modelCount-count-1);
+ if (d->currentItem) {
+ if (QDeclarative1PathViewAttached *att = d->attached(d->currentItem))
+ att->setIsCurrentItem(true);
+ }
+ currentChanged = true;
+ }
+
+ d->itemCache += d->items;
+ d->items.clear();
+
+ bool changedOffset = false;
+ if (modelIndex > d->currentIndex) {
+ if (d->offset >= count) {
+ changedOffset = true;
+ d->offset -= count;
+ d->offsetAdj -= count;
+ }
+ }
+
+ d->modelCount -= count;
+ if (!d->modelCount) {
+ while (d->itemCache.count())
+ d->releaseItem(d->itemCache.takeLast());
+ d->offset = 0;
+ changedOffset = true;
+ d->tl.reset(d->moveOffset);
+ update();
+ } else {
+ d->regenerate();
+ d->updateCurrent();
+ if (!d->flicking && !d->moving && d->haveHighlightRange && d->highlightRangeMode == QDeclarative1PathView::StrictlyEnforceRange)
+ d->snapToCurrent();
+ }
+ if (changedOffset)
+ emit offsetChanged();
+ if (currentChanged)
+ emit currentIndexChanged();
+ emit countChanged();
+}
+
+void QDeclarative1PathView::itemsMoved(int /*from*/, int /*to*/, int /*count*/)
+{
+ Q_D(QDeclarative1PathView);
+ if (!d->isValid() || !isComponentComplete())
+ return;
+
+ QList<QDeclarativeItem *> removedItems = d->items;
+ d->items.clear();
+ d->regenerate();
+ while (removedItems.count())
+ d->releaseItem(removedItems.takeLast());
+
+ // Fix current index
+ if (d->currentIndex >= 0 && d->currentItem) {
+ int oldCurrent = d->currentIndex;
+ d->currentIndex = d->model->indexOf(d->currentItem, this);
+ if (oldCurrent != d->currentIndex)
+ emit currentIndexChanged();
+ }
+ d->updateCurrent();
+}
+
+void QDeclarative1PathView::modelReset()
+{
+ Q_D(QDeclarative1PathView);
+ d->modelCount = d->model->count();
+ d->regenerate();
+ emit countChanged();
+}
+
+void QDeclarative1PathView::createdItem(int index, QDeclarativeItem *item)
+{
+ Q_D(QDeclarative1PathView);
+ if (d->requestedIndex != index) {
+ if (!d->attType) {
+ // pre-create one metatype to share with all attached objects
+ d->attType = new QDeclarative1OpenMetaObjectType(&QDeclarative1PathViewAttached::staticMetaObject, qmlEngine(this));
+ foreach(const QString &attr, d->path->attributes())
+ d->attType->createProperty(attr.toUtf8());
+ }
+ qPathViewAttachedType = d->attType;
+ QDeclarative1PathViewAttached *att = static_cast<QDeclarative1PathViewAttached *>(qmlAttachedPropertiesObject<QDeclarative1PathView>(item));
+ qPathViewAttachedType = 0;
+ if (att) {
+ att->m_view = this;
+ att->setOnPath(false);
+ }
+ item->setParentItem(this);
+ d->updateItem(item, index < d->firstIndex ? 0.0 : 1.0);
+ }
+}
+
+void QDeclarative1PathView::destroyingItem(QDeclarativeItem *item)
+{
+ Q_UNUSED(item);
+}
+
+void QDeclarative1PathView::ticked()
+{
+ Q_D(QDeclarative1PathView);
+ d->updateCurrent();
+}
+
+void QDeclarative1PathView::movementEnding()
+{
+ Q_D(QDeclarative1PathView);
+ if (d->flicking) {
+ d->flicking = false;
+ emit flickingChanged();
+ emit flickEnded();
+ }
+ if (d->moving && !d->stealMouse) {
+ d->moving = false;
+ emit movingChanged();
+ emit movementEnded();
+ }
+}
+
+// find the item closest to the snap position
+int QDeclarative1PathViewPrivate::calcCurrentIndex()
+{
+ int current = -1;
+ if (modelCount && model && items.count()) {
+ offset = qmlMod(offset, modelCount);
+ if (offset < 0)
+ offset += modelCount;
+ current = qRound(qAbs(qmlMod(modelCount - offset, modelCount)));
+ current = current % modelCount;
+ }
+
+ return current;
+}
+
+void QDeclarative1PathViewPrivate::updateCurrent()
+{
+ Q_Q(QDeclarative1PathView);
+ if (moveReason != Mouse)
+ return;
+ if (!modelCount || !haveHighlightRange || highlightRangeMode != QDeclarative1PathView::StrictlyEnforceRange)
+ return;
+
+ int idx = calcCurrentIndex();
+ if (model && idx != currentIndex) {
+ int itemIndex = (currentIndex - firstIndex + modelCount) % modelCount;
+ if (itemIndex < items.count()) {
+ if (QDeclarativeItem *item = items.at(itemIndex)) {
+ if (QDeclarative1PathViewAttached *att = attached(item))
+ att->setIsCurrentItem(false);
+ }
+ }
+ currentIndex = idx;
+ currentItem = 0;
+ itemIndex = (idx - firstIndex + modelCount) % modelCount;
+ if (itemIndex < items.count()) {
+ currentItem = items.at(itemIndex);
+ currentItem->setFocus(true);
+ if (QDeclarative1PathViewAttached *att = attached(currentItem))
+ att->setIsCurrentItem(true);
+ }
+ emit q->currentIndexChanged();
+ }
+}
+
+void QDeclarative1PathViewPrivate::fixOffsetCallback(void *d)
+{
+ ((QDeclarative1PathViewPrivate *)d)->fixOffset();
+}
+
+void QDeclarative1PathViewPrivate::fixOffset()
+{
+ Q_Q(QDeclarative1PathView);
+ if (model && items.count()) {
+ if (haveHighlightRange && highlightRangeMode == QDeclarative1PathView::StrictlyEnforceRange) {
+ int curr = calcCurrentIndex();
+ if (curr != currentIndex)
+ q->setCurrentIndex(curr);
+ else
+ snapToCurrent();
+ }
+ }
+}
+
+void QDeclarative1PathViewPrivate::snapToCurrent()
+{
+ if (!model || modelCount <= 0)
+ return;
+
+ qreal targetOffset = qmlMod(modelCount - currentIndex, modelCount);
+
+ moveReason = Other;
+ offsetAdj = 0.0;
+ tl.reset(moveOffset);
+ moveOffset.setValue(offset);
+
+ const int duration = highlightMoveDuration;
+
+ if (moveDirection == Positive || (moveDirection == Shortest && targetOffset - offset > modelCount/2)) {
+ qreal distance = modelCount - targetOffset + offset;
+ if (targetOffset > moveOffset) {
+ tl.move(moveOffset, 0.0, QEasingCurve(QEasingCurve::InQuad), int(duration * offset / distance));
+ tl.set(moveOffset, modelCount);
+ tl.move(moveOffset, targetOffset, QEasingCurve(offset == 0.0 ? QEasingCurve::InOutQuad : QEasingCurve::OutQuad), int(duration * (modelCount-targetOffset) / distance));
+ } else {
+ tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::InOutQuad), duration);
+ }
+ } else if (moveDirection == Negative || targetOffset - offset <= -modelCount/2) {
+ qreal distance = modelCount - offset + targetOffset;
+ if (targetOffset < moveOffset) {
+ tl.move(moveOffset, modelCount, QEasingCurve(targetOffset == 0 ? QEasingCurve::InOutQuad : QEasingCurve::InQuad), int(duration * (modelCount-offset) / distance));
+ tl.set(moveOffset, 0.0);
+ tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::OutQuad), int(duration * targetOffset / distance));
+ } else {
+ tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::InOutQuad), duration);
+ }
+ } else {
+ tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::InOutQuad), duration);
+ }
+ moveDirection = Shortest;
+}
+
+QDeclarative1PathViewAttached *QDeclarative1PathView::qmlAttachedProperties(QObject *obj)
+{
+ return new QDeclarative1PathViewAttached(obj);
+}
+
+
+
+QT_END_NAMESPACE
+
diff --git a/src/qtquick1/graphicsitems/qdeclarativepathview_p.h b/src/qtquick1/graphicsitems/qdeclarativepathview_p.h
new file mode 100644
index 0000000000..b4897f9e1d
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativepathview_p.h
@@ -0,0 +1,252 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEPATHVIEW_H
+#define QDECLARATIVEPATHVIEW_H
+
+#include "qdeclarativeitem.h"
+#include "QtQuick1/private/qdeclarativepath_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarative1PathViewPrivate;
+class QDeclarative1PathViewAttached;
+class Q_AUTOTEST_EXPORT QDeclarative1PathView : public QDeclarativeItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged)
+ Q_PROPERTY(QDeclarative1Path *path READ path WRITE setPath NOTIFY pathChanged)
+ Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
+ Q_PROPERTY(qreal offset READ offset WRITE setOffset NOTIFY offsetChanged)
+
+ Q_PROPERTY(QDeclarativeComponent *highlight READ highlight WRITE setHighlight NOTIFY highlightChanged)
+ Q_PROPERTY(QDeclarativeItem *highlightItem READ highlightItem NOTIFY highlightItemChanged)
+
+ Q_PROPERTY(qreal preferredHighlightBegin READ preferredHighlightBegin WRITE setPreferredHighlightBegin NOTIFY preferredHighlightBeginChanged)
+ Q_PROPERTY(qreal preferredHighlightEnd READ preferredHighlightEnd WRITE setPreferredHighlightEnd NOTIFY preferredHighlightEndChanged)
+ Q_PROPERTY(HighlightRangeMode highlightRangeMode READ highlightRangeMode WRITE setHighlightRangeMode NOTIFY highlightRangeModeChanged)
+ Q_PROPERTY(int highlightMoveDuration READ highlightMoveDuration WRITE setHighlightMoveDuration NOTIFY highlightMoveDurationChanged)
+
+ Q_PROPERTY(qreal dragMargin READ dragMargin WRITE setDragMargin NOTIFY dragMarginChanged)
+ Q_PROPERTY(qreal flickDeceleration READ flickDeceleration WRITE setFlickDeceleration NOTIFY flickDecelerationChanged)
+ Q_PROPERTY(bool interactive READ isInteractive WRITE setInteractive NOTIFY interactiveChanged)
+
+ Q_PROPERTY(bool moving READ isMoving NOTIFY movingChanged)
+ Q_PROPERTY(bool flicking READ isFlicking NOTIFY flickingChanged)
+
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+ Q_PROPERTY(QDeclarativeComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
+ Q_PROPERTY(int pathItemCount READ pathItemCount WRITE setPathItemCount NOTIFY pathItemCountChanged)
+
+ Q_ENUMS(HighlightRangeMode)
+
+public:
+ QDeclarative1PathView(QDeclarativeItem *parent=0);
+ virtual ~QDeclarative1PathView();
+
+ QVariant model() const;
+ void setModel(const QVariant &);
+
+ QDeclarative1Path *path() const;
+ void setPath(QDeclarative1Path *);
+
+ int currentIndex() const;
+ void setCurrentIndex(int idx);
+
+ qreal offset() const;
+ void setOffset(qreal offset);
+
+ QDeclarativeComponent *highlight() const;
+ void setHighlight(QDeclarativeComponent *highlight);
+ QDeclarativeItem *highlightItem();
+
+ enum HighlightRangeMode { NoHighlightRange, ApplyRange, StrictlyEnforceRange };
+ HighlightRangeMode highlightRangeMode() const;
+ void setHighlightRangeMode(HighlightRangeMode mode);
+
+ qreal preferredHighlightBegin() const;
+ void setPreferredHighlightBegin(qreal);
+
+ qreal preferredHighlightEnd() const;
+ void setPreferredHighlightEnd(qreal);
+
+ int highlightMoveDuration() const;
+ void setHighlightMoveDuration(int);
+
+ qreal dragMargin() const;
+ void setDragMargin(qreal margin);
+
+ qreal flickDeceleration() const;
+ void setFlickDeceleration(qreal dec);
+
+ bool isInteractive() const;
+ void setInteractive(bool);
+
+ bool isMoving() const;
+ bool isFlicking() const;
+
+ int count() const;
+
+ QDeclarativeComponent *delegate() const;
+ void setDelegate(QDeclarativeComponent *);
+
+ int pathItemCount() const;
+ void setPathItemCount(int);
+
+ static QDeclarative1PathViewAttached *qmlAttachedProperties(QObject *);
+
+public Q_SLOTS:
+ void incrementCurrentIndex();
+ void decrementCurrentIndex();
+
+Q_SIGNALS:
+ void currentIndexChanged();
+ void offsetChanged();
+ void modelChanged();
+ void countChanged();
+ void pathChanged();
+ void preferredHighlightBeginChanged();
+ void preferredHighlightEndChanged();
+ void highlightRangeModeChanged();
+ void dragMarginChanged();
+ void snapPositionChanged();
+ void delegateChanged();
+ void pathItemCountChanged();
+ void flickDecelerationChanged();
+ void interactiveChanged();
+ void movingChanged();
+ void flickingChanged();
+ void highlightChanged();
+ void highlightItemChanged();
+ void highlightMoveDurationChanged();
+ void movementStarted();
+ void movementEnded();
+ void flickStarted();
+ void flickEnded();
+
+protected:
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *);
+ bool sendMouseEvent(QGraphicsSceneMouseEvent *event);
+ bool sceneEventFilter(QGraphicsItem *, QEvent *);
+ bool event(QEvent *event);
+ void componentComplete();
+
+private Q_SLOTS:
+ void refill();
+ void ticked();
+ void movementEnding();
+ void itemsInserted(int index, int count);
+ void itemsRemoved(int index, int count);
+ void itemsMoved(int,int,int);
+ void modelReset();
+ void createdItem(int index, QDeclarativeItem *item);
+ void destroyingItem(QDeclarativeItem *item);
+ void pathUpdated();
+
+private:
+ friend class QDeclarative1PathViewAttached;
+ Q_DISABLE_COPY(QDeclarative1PathView)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarative1PathView)
+};
+
+class QDeclarative1OpenMetaObject;
+class QDeclarative1PathViewAttached : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QDeclarative1PathView *view READ view CONSTANT)
+ Q_PROPERTY(bool isCurrentItem READ isCurrentItem NOTIFY currentItemChanged)
+ Q_PROPERTY(bool onPath READ isOnPath NOTIFY pathChanged)
+
+public:
+ QDeclarative1PathViewAttached(QObject *parent);
+ ~QDeclarative1PathViewAttached();
+
+ QDeclarative1PathView *view() { return m_view; }
+
+ bool isCurrentItem() const { return m_isCurrent; }
+ void setIsCurrentItem(bool c) {
+ if (m_isCurrent != c) {
+ m_isCurrent = c;
+ emit currentItemChanged();
+ }
+ }
+
+ QVariant value(const QByteArray &name) const;
+ void setValue(const QByteArray &name, const QVariant &val);
+
+ bool isOnPath() const { return m_onPath; }
+ void setOnPath(bool on) {
+ if (on != m_onPath) {
+ m_onPath = on;
+ emit pathChanged();
+ }
+ }
+ qreal m_percent;
+
+Q_SIGNALS:
+ void currentItemChanged();
+ void pathChanged();
+
+private:
+ friend class QDeclarative1PathViewPrivate;
+ friend class QDeclarative1PathView;
+ QDeclarative1PathView *m_view;
+ QDeclarative1OpenMetaObject *m_metaobject;
+ bool m_onPath : 1;
+ bool m_isCurrent : 1;
+};
+
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1PathView)
+QML_DECLARE_TYPEINFO(QDeclarative1PathView, QML_HAS_ATTACHED_PROPERTIES)
+QT_END_HEADER
+
+#endif // QDECLARATIVEPATHVIEW_H
diff --git a/src/qtquick1/graphicsitems/qdeclarativepathview_p_p.h b/src/qtquick1/graphicsitems/qdeclarativepathview_p_p.h
new file mode 100644
index 0000000000..50965d6842
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativepathview_p_p.h
@@ -0,0 +1,192 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEPATHVIEW_P_H
+#define QDECLARATIVEPATHVIEW_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qdeclarativepathview_p.h"
+
+#include "QtQuick1/private/qdeclarativeitem_p.h"
+#include "QtQuick1/private/qdeclarativevisualitemmodel_p.h"
+
+#include <QtDeclarative/qdeclarative.h>
+#include <QtQuick1/private/qdeclarativeanimation_p_p.h>
+#include <QtDeclarative/private/qdeclarativeguard_p.h>
+
+#include <qdatetime.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarative1OpenMetaObjectType;
+class QDeclarative1PathViewAttached;
+class QDeclarative1PathViewPrivate : public QDeclarativeItemPrivate, public QDeclarativeItemChangeListener
+{
+ Q_DECLARE_PUBLIC(QDeclarative1PathView)
+
+public:
+ QDeclarative1PathViewPrivate()
+ : path(0), currentIndex(0), currentItemOffset(0.0), startPc(0), lastDist(0)
+ , lastElapsed(0), offset(0.0), offsetAdj(0.0), mappedRange(1.0)
+ , stealMouse(false), ownModel(false), interactive(true), haveHighlightRange(true)
+ , autoHighlight(true), highlightUp(false), layoutScheduled(false)
+ , moving(false), flicking(false)
+ , dragMargin(0), deceleration(100)
+ , moveOffset(this, &QDeclarative1PathViewPrivate::setAdjustedOffset)
+ , firstIndex(-1), pathItems(-1), requestedIndex(-1)
+ , moveReason(Other), moveDirection(Shortest), attType(0), highlightComponent(0), highlightItem(0)
+ , moveHighlight(this, &QDeclarative1PathViewPrivate::setHighlightPosition)
+ , highlightPosition(0)
+ , highlightRangeStart(0), highlightRangeEnd(0)
+ , highlightRangeMode(QDeclarative1PathView::StrictlyEnforceRange)
+ , highlightMoveDuration(300), modelCount(0)
+ {
+ }
+
+ void init();
+
+ void itemGeometryChanged(QDeclarativeItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) {
+ if ((newGeometry.size() != oldGeometry.size())
+ && (!highlightItem || item != highlightItem)) {
+ if (QDeclarative1PathViewAttached *att = attached(item))
+ att->m_percent = -1;
+ scheduleLayout();
+ }
+ }
+
+ void scheduleLayout() {
+ Q_Q(QDeclarative1PathView);
+ if (!layoutScheduled) {
+ layoutScheduled = true;
+ QCoreApplication::postEvent(q, new QEvent(QEvent::User), Qt::HighEventPriority);
+ }
+ }
+
+ QDeclarativeItem *getItem(int modelIndex);
+ void releaseItem(QDeclarativeItem *item);
+ QDeclarative1PathViewAttached *attached(QDeclarativeItem *item);
+ void clear();
+ void updateMappedRange();
+ qreal positionOfIndex(qreal index) const;
+ void createHighlight();
+ void updateHighlight();
+ void setHighlightPosition(qreal pos);
+ bool isValid() const {
+ return model && model->count() > 0 && model->isValid() && path;
+ }
+
+ void handleMousePressEvent(QGraphicsSceneMouseEvent *event);
+ void handleMouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ void handleMouseReleaseEvent(QGraphicsSceneMouseEvent *);
+
+ int calcCurrentIndex();
+ void updateCurrent();
+ static void fixOffsetCallback(void*);
+ void fixOffset();
+ void setOffset(qreal offset);
+ void setAdjustedOffset(qreal offset);
+ void regenerate();
+ void updateItem(QDeclarativeItem *, qreal);
+ void snapToCurrent();
+ QPointF pointNear(const QPointF &point, qreal *nearPercent=0) const;
+
+ QDeclarative1Path *path;
+ int currentIndex;
+ QDeclarativeGuard<QDeclarativeItem> currentItem;
+ qreal currentItemOffset;
+ qreal startPc;
+ QPointF startPoint;
+ qreal lastDist;
+ int lastElapsed;
+ qreal offset;
+ qreal offsetAdj;
+ qreal mappedRange;
+ bool stealMouse : 1;
+ bool ownModel : 1;
+ bool interactive : 1;
+ bool haveHighlightRange : 1;
+ bool autoHighlight : 1;
+ bool highlightUp : 1;
+ bool layoutScheduled : 1;
+ bool moving : 1;
+ bool flicking : 1;
+ QElapsedTimer lastPosTime;
+ QPointF lastPos;
+ qreal dragMargin;
+ qreal deceleration;
+ QDeclarative1TimeLine tl;
+ QDeclarative1TimeLineValueProxy<QDeclarative1PathViewPrivate> moveOffset;
+ int firstIndex;
+ int pathItems;
+ int requestedIndex;
+ QList<QDeclarativeItem *> items;
+ QList<QDeclarativeItem *> itemCache;
+ QDeclarativeGuard<QDeclarative1VisualModel> model;
+ QVariant modelVariant;
+ enum MovementReason { Other, SetIndex, Mouse };
+ MovementReason moveReason;
+ enum MovementDirection { Shortest, Negative, Positive };
+ MovementDirection moveDirection;
+ QDeclarative1OpenMetaObjectType *attType;
+ QDeclarativeComponent *highlightComponent;
+ QDeclarativeItem *highlightItem;
+ QDeclarative1TimeLineValueProxy<QDeclarative1PathViewPrivate> moveHighlight;
+ qreal highlightPosition;
+ qreal highlightRangeStart;
+ qreal highlightRangeEnd;
+ QDeclarative1PathView::HighlightRangeMode highlightRangeMode;
+ int highlightMoveDuration;
+ int modelCount;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/qtquick1/graphicsitems/qdeclarativepincharea.cpp b/src/qtquick1/graphicsitems/qdeclarativepincharea.cpp
new file mode 100644
index 0000000000..8efe6e5c8a
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativepincharea.cpp
@@ -0,0 +1,611 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativepincharea_p.h"
+#include "QtQuick1/private/qdeclarativepincharea_p_p.h"
+
+#include <QApplication>
+#include <QGraphicsScene>
+
+#include <float.h>
+#include <math.h>
+
+QT_BEGIN_NAMESPACE
+
+
+
+
+/*!
+ \qmlclass PinchEvent QDeclarative1PinchEvent
+ \ingroup qml-event-elements
+ \brief The PinchEvent object provides information about a pinch event.
+
+ \bold {The PinchEvent element was added in QtQuick 1.1}
+
+ The \c center, \c startCenter, \c previousCenter properties provide the center position between the two touch points.
+
+ The \c scale and \c previousScale properties provide the scale factor.
+
+ The \c angle, \c previousAngle and \c rotation properties provide the angle between the two points and the amount of rotation.
+
+ The \c point1, \c point2, \c startPoint1, \c startPoint2 properties provide the positions of the touch points.
+
+ The \c accepted property may be set to false in the \c onPinchStarted handler if the gesture should not
+ be handled.
+
+ \sa PinchArea
+*/
+
+/*!
+ \qmlproperty QPointF PinchEvent::center
+ \qmlproperty QPointF PinchEvent::startCenter
+ \qmlproperty QPointF PinchEvent::previousCenter
+
+ These properties hold the position of the center point between the two touch points.
+
+ \list
+ \o \c center is the current center point
+ \o \c previousCenter is the center point of the previous event.
+ \o \c startCenter is the center point when the gesture began
+ \endlist
+*/
+
+/*!
+ \qmlproperty real PinchEvent::scale
+ \qmlproperty real PinchEvent::previousScale
+
+ These properties hold the scale factor determined by the change in distance between the two touch points.
+
+ \list
+ \o \c scale is the current scale factor.
+ \o \c previousScale is the scale factor of the previous event.
+ \endlist
+
+ When a pinch gesture is started, the scale is 1.0.
+*/
+
+/*!
+ \qmlproperty real PinchEvent::angle
+ \qmlproperty real PinchEvent::previousAngle
+ \qmlproperty real PinchEvent::rotation
+
+ These properties hold the angle between the two touch points.
+
+ \list
+ \o \c angle is the current angle between the two points in the range -180 to 180.
+ \o \c previousAngle is the angle of the previous event.
+ \o \c rotation is the total rotation since the pinch gesture started.
+ \endlist
+
+ When a pinch gesture is started, the rotation is 0.0.
+*/
+
+/*!
+ \qmlproperty QPointF PinchEvent::point1
+ \qmlproperty QPointF PinchEvent::startPoint1
+ \qmlproperty QPointF PinchEvent::point2
+ \qmlproperty QPointF PinchEvent::startPoint2
+
+ These properties provide the actual touch points generating the pinch.
+
+ \list
+ \o \c point1 and \c point2 hold the current positions of the points.
+ \o \c startPoint1 and \c startPoint2 hold the positions of the points when the second point was touched.
+ \endlist
+*/
+
+/*!
+ \qmlproperty bool PinchEvent::accepted
+
+ Setting this property to false in the \c PinchArea::onPinchStarted handler
+ will result in no further pinch events being generated, and the gesture
+ ignored.
+*/
+
+/*!
+ \qmlproperty int PinchEvent::pointCount
+
+ Holds the number of points currently touched. The PinchArea will not react
+ until two touch points have initited a gesture, but will remain active until
+ all touch points have been released.
+*/
+
+QDeclarative1Pinch::QDeclarative1Pinch()
+ : m_target(0), m_minScale(1.0), m_maxScale(1.0)
+ , m_minRotation(0.0), m_maxRotation(0.0)
+ , m_axis(NoDrag), m_xmin(-FLT_MAX), m_xmax(FLT_MAX)
+ , m_ymin(-FLT_MAX), m_ymax(FLT_MAX), m_active(false)
+{
+}
+
+QDeclarative1PinchAreaPrivate::~QDeclarative1PinchAreaPrivate()
+{
+ delete pinch;
+}
+
+/*!
+ \qmlclass PinchArea QDeclarative1PinchArea
+ \brief The PinchArea item enables simple pinch gesture handling.
+ \inherits Item
+
+ \bold {The PinchArea element was added in QtQuick 1.1}
+
+ A PinchArea is an invisible item that is typically used in conjunction with
+ a visible item in order to provide pinch gesture handling for that item.
+
+ The \l enabled property is used to enable and disable pinch handling for
+ the proxied item. When disabled, the pinch area becomes transparent to
+ mouse/touch events.
+
+ PinchArea can be used in two ways:
+
+ \list
+ \o setting a \c pinch.target to provide automatic interaction with an element
+ \o using the onPinchStarted, onPinchUpdated and onPinchFinished handlers
+ \endlist
+
+ \sa PinchEvent
+*/
+
+/*!
+ \qmlsignal PinchArea::onPinchStarted()
+
+ This handler is called when the pinch area detects that a pinch gesture has started.
+
+ The \l {PinchEvent}{pinch} parameter provides information about the pinch gesture,
+ including the scale, center and angle of the pinch.
+
+ To ignore this gesture set the \c pinch.accepted property to false. The gesture
+ will be cancelled and no further events will be sent.
+*/
+
+/*!
+ \qmlsignal PinchArea::onPinchUpdated()
+
+ This handler is called when the pinch area detects that a pinch gesture has changed.
+
+ The \l {PinchEvent}{pinch} parameter provides information about the pinch gesture,
+ including the scale, center and angle of the pinch.
+*/
+
+/*!
+ \qmlsignal PinchArea::onPinchFinished()
+
+ This handler is called when the pinch area detects that a pinch gesture has finished.
+
+ The \l {PinchEvent}{pinch} parameter provides information about the pinch gesture,
+ including the scale, center and angle of the pinch.
+*/
+
+
+/*!
+ \qmlproperty Item PinchArea::pinch.target
+ \qmlproperty bool PinchArea::pinch.active
+ \qmlproperty real PinchArea::pinch.minimumScale
+ \qmlproperty real PinchArea::pinch.maximumScale
+ \qmlproperty real PinchArea::pinch.minimumRotation
+ \qmlproperty real PinchArea::pinch.maximumRotation
+ \qmlproperty enumeration PinchArea::pinch.dragAxis
+ \qmlproperty real PinchArea::pinch.minimumX
+ \qmlproperty real PinchArea::pinch.maximumX
+ \qmlproperty real PinchArea::pinch.minimumY
+ \qmlproperty real PinchArea::pinch.maximumY
+
+ \c pinch provides a convenient way to make an item react to pinch gestures.
+
+ \list
+ \i \c pinch.target specifies the id of the item to drag.
+ \i \c pinch.active specifies if the target item is currently being dragged.
+ \i \c pinch.minimumScale and \c pinch.maximumScale limit the range of the Item::scale property.
+ \i \c pinch.minimumRotation and \c pinch.maximumRotation limit the range of the Item::rotation property.
+ \i \c pinch.dragAxis specifies whether dragging in not allowed (\c Pinch.NoDrag), can be done horizontally (\c Pinch.XAxis), vertically (\c Pinch.YAxis), or both (\c Pinch.XandYAxis)
+ \i \c pinch.minimum and \c pinch.maximum limit how far the target can be dragged along the corresponding axes.
+ \endlist
+*/
+
+QDeclarative1PinchArea::QDeclarative1PinchArea(QDeclarativeItem *parent)
+ : QDeclarativeItem(*(new QDeclarative1PinchAreaPrivate), parent)
+{
+ Q_D(QDeclarative1PinchArea);
+ d->init();
+}
+
+QDeclarative1PinchArea::~QDeclarative1PinchArea()
+{
+}
+
+/*!
+ \qmlproperty bool PinchArea::enabled
+ This property holds whether the item accepts pinch gestures.
+
+ This property defaults to true.
+*/
+bool QDeclarative1PinchArea::isEnabled() const
+{
+ Q_D(const QDeclarative1PinchArea);
+ return d->absorb;
+}
+
+void QDeclarative1PinchArea::setEnabled(bool a)
+{
+ Q_D(QDeclarative1PinchArea);
+ if (a != d->absorb) {
+ d->absorb = a;
+ emit enabledChanged();
+ }
+}
+
+bool QDeclarative1PinchArea::event(QEvent *event)
+{
+ Q_D(QDeclarative1PinchArea);
+ if (!d->absorb || !isVisible())
+ return QDeclarativeItem::event(event);
+ switch (event->type()) {
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate: {
+ QTouchEvent *touch = static_cast<QTouchEvent*>(event);
+ d->touchPoints.clear();
+ for (int i = 0; i < touch->touchPoints().count(); ++i) {
+ if (!(touch->touchPoints().at(i).state() & Qt::TouchPointReleased)) {
+ d->touchPoints << touch->touchPoints().at(i);
+ }
+ }
+ updatePinch();
+ }
+ return true;
+ case QEvent::TouchEnd:
+ d->touchPoints.clear();
+ updatePinch();
+ break;
+ default:
+ return QDeclarativeItem::event(event);
+ }
+
+ return QDeclarativeItem::event(event);
+}
+
+void QDeclarative1PinchArea::updatePinch()
+{
+ Q_D(QDeclarative1PinchArea);
+ if (d->touchPoints.count() == 0) {
+ if (d->inPinch) {
+ d->stealMouse = false;
+ setKeepMouseGrab(false);
+ d->inPinch = false;
+ QPointF pinchCenter = mapFromScene(d->sceneLastCenter);
+ QDeclarative1PinchEvent pe(pinchCenter, d->pinchLastScale, d->pinchLastAngle, d->pinchRotation);
+ pe.setStartCenter(d->pinchStartCenter);
+ pe.setPreviousCenter(pinchCenter);
+ pe.setPreviousAngle(d->pinchLastAngle);
+ pe.setPreviousScale(d->pinchLastScale);
+ pe.setStartPoint1(mapFromScene(d->sceneStartPoint1));
+ pe.setStartPoint2(mapFromScene(d->sceneStartPoint2));
+ pe.setPoint1(mapFromScene(d->lastPoint1));
+ pe.setPoint2(mapFromScene(d->lastPoint2));
+ emit pinchFinished(&pe);
+ d->pinchStartDist = 0;
+ d->pinchActivated = false;
+ if (d->pinch && d->pinch->target())
+ d->pinch->setActive(false);
+ }
+ return;
+ }
+ QTouchEvent::TouchPoint touchPoint1 = d->touchPoints.at(0);
+ QTouchEvent::TouchPoint touchPoint2 = d->touchPoints.at(d->touchPoints. count() >= 2 ? 1 : 0);
+ if (d->touchPoints.count() == 2
+ && (touchPoint1.state() & Qt::TouchPointPressed || touchPoint2.state() & Qt::TouchPointPressed)) {
+ d->id1 = touchPoint1.id();
+ d->sceneStartPoint1 = touchPoint1.scenePos();
+ d->sceneStartPoint2 = touchPoint2.scenePos();
+ d->inPinch = false;
+ d->pinchRejected = false;
+ d->pinchActivated = true;
+ } else if (d->pinchActivated && !d->pinchRejected) {
+ const int dragThreshold = QApplication::startDragDistance();
+ QPointF p1 = touchPoint1.scenePos();
+ QPointF p2 = touchPoint2.scenePos();
+ qreal dx = p1.x() - p2.x();
+ qreal dy = p1.y() - p2.y();
+ qreal dist = sqrt(dx*dx + dy*dy);
+ QPointF sceneCenter = (p1 + p2)/2;
+ qreal angle = QLineF(p1, p2).angle();
+ if (d->touchPoints.count() == 1) {
+ // If we only have one point then just move the center
+ if (d->id1 == touchPoint1.id())
+ sceneCenter = d->sceneLastCenter + touchPoint1.scenePos() - d->lastPoint1;
+ else
+ sceneCenter = d->sceneLastCenter + touchPoint2.scenePos() - d->lastPoint2;
+ angle = d->pinchLastAngle;
+ }
+ d->id1 = touchPoint1.id();
+ if (angle > 180)
+ angle -= 360;
+ if (!d->inPinch) {
+ if (d->touchPoints.count() >= 2
+ && (qAbs(p1.x()-d->sceneStartPoint1.x()) > dragThreshold
+ || qAbs(p1.y()-d->sceneStartPoint1.y()) > dragThreshold
+ || qAbs(p2.x()-d->sceneStartPoint2.x()) > dragThreshold
+ || qAbs(p2.y()-d->sceneStartPoint2.y()) > dragThreshold)) {
+ d->sceneStartCenter = sceneCenter;
+ d->sceneLastCenter = sceneCenter;
+ d->pinchStartCenter = mapFromScene(sceneCenter);
+ d->pinchStartDist = dist;
+ d->pinchStartAngle = angle;
+ d->pinchLastScale = 1.0;
+ d->pinchLastAngle = angle;
+ d->pinchRotation = 0.0;
+ d->lastPoint1 = p1;
+ d->lastPoint2 = p2;
+ QDeclarative1PinchEvent pe(d->pinchStartCenter, 1.0, angle, 0.0);
+ pe.setStartCenter(d->pinchStartCenter);
+ pe.setPreviousCenter(d->pinchStartCenter);
+ pe.setPreviousAngle(d->pinchLastAngle);
+ pe.setPreviousScale(d->pinchLastScale);
+ pe.setStartPoint1(mapFromScene(d->sceneStartPoint1));
+ pe.setStartPoint2(mapFromScene(d->sceneStartPoint2));
+ pe.setPoint1(mapFromScene(d->lastPoint1));
+ pe.setPoint2(mapFromScene(d->lastPoint2));
+ pe.setPointCount(d->touchPoints.count());
+ emit pinchStarted(&pe);
+ if (pe.accepted()) {
+ d->inPinch = true;
+ d->stealMouse = true;
+ QGraphicsScene *s = scene();
+ if (s && s->mouseGrabberItem() != this)
+ grabMouse();
+ setKeepMouseGrab(true);
+ if (d->pinch && d->pinch->target()) {
+ d->pinchStartPos = pinch()->target()->pos();
+ d->pinchStartScale = d->pinch->target()->scale();
+ d->pinchStartRotation = d->pinch->target()->rotation();
+ d->pinch->setActive(true);
+ }
+ } else {
+ d->pinchRejected = true;
+ }
+ }
+ } else if (d->pinchStartDist > 0) {
+ qreal scale = dist ? dist / d->pinchStartDist : d->pinchLastScale;
+ qreal da = d->pinchLastAngle - angle;
+ if (da > 180)
+ da -= 360;
+ else if (da < -180)
+ da += 360;
+ d->pinchRotation += da;
+ QPointF pinchCenter = mapFromScene(sceneCenter);
+ QDeclarative1PinchEvent pe(pinchCenter, scale, angle, d->pinchRotation);
+ pe.setStartCenter(d->pinchStartCenter);
+ pe.setPreviousCenter(mapFromScene(d->sceneLastCenter));
+ pe.setPreviousAngle(d->pinchLastAngle);
+ pe.setPreviousScale(d->pinchLastScale);
+ pe.setStartPoint1(mapFromScene(d->sceneStartPoint1));
+ pe.setStartPoint2(mapFromScene(d->sceneStartPoint2));
+ pe.setPoint1(touchPoint1.pos());
+ pe.setPoint2(touchPoint2.pos());
+ pe.setPointCount(d->touchPoints.count());
+ d->pinchLastScale = scale;
+ d->sceneLastCenter = sceneCenter;
+ d->pinchLastAngle = angle;
+ d->lastPoint1 = touchPoint1.scenePos();
+ d->lastPoint2 = touchPoint2.scenePos();
+ emit pinchUpdated(&pe);
+ if (d->pinch && d->pinch->target()) {
+ qreal s = d->pinchStartScale * scale;
+ s = qMin(qMax(pinch()->minimumScale(),s), pinch()->maximumScale());
+ pinch()->target()->setScale(s);
+ QPointF pos = sceneCenter - d->sceneStartCenter + d->pinchStartPos;
+ if (pinch()->axis() & QDeclarative1Pinch::XAxis) {
+ qreal x = pos.x();
+ if (x < pinch()->xmin())
+ x = pinch()->xmin();
+ else if (x > pinch()->xmax())
+ x = pinch()->xmax();
+ pinch()->target()->setX(x);
+ }
+ if (pinch()->axis() & QDeclarative1Pinch::YAxis) {
+ qreal y = pos.y();
+ if (y < pinch()->ymin())
+ y = pinch()->ymin();
+ else if (y > pinch()->ymax())
+ y = pinch()->ymax();
+ pinch()->target()->setY(y);
+ }
+ if (d->pinchStartRotation >= pinch()->minimumRotation()
+ && d->pinchStartRotation <= pinch()->maximumRotation()) {
+ qreal r = d->pinchRotation + d->pinchStartRotation;
+ r = qMin(qMax(pinch()->minimumRotation(),r), pinch()->maximumRotation());
+ pinch()->target()->setRotation(r);
+ }
+ }
+ }
+ }
+}
+
+void QDeclarative1PinchArea::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QDeclarative1PinchArea);
+ d->stealMouse = false;
+ if (!d->absorb)
+ QDeclarativeItem::mousePressEvent(event);
+ else {
+ setKeepMouseGrab(false);
+ event->setAccepted(true);
+ }
+}
+
+void QDeclarative1PinchArea::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QDeclarative1PinchArea);
+ if (!d->absorb) {
+ QDeclarativeItem::mouseMoveEvent(event);
+ return;
+ }
+}
+
+void QDeclarative1PinchArea::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QDeclarative1PinchArea);
+ d->stealMouse = false;
+ if (!d->absorb) {
+ QDeclarativeItem::mouseReleaseEvent(event);
+ } else {
+ QGraphicsScene *s = scene();
+ if (s && s->mouseGrabberItem() == this)
+ ungrabMouse();
+ setKeepMouseGrab(false);
+ }
+}
+
+bool QDeclarative1PinchArea::sceneEvent(QEvent *event)
+{
+ bool rv = QDeclarativeItem::sceneEvent(event);
+ if (event->type() == QEvent::UngrabMouse) {
+ setKeepMouseGrab(false);
+ }
+ return rv;
+}
+
+bool QDeclarative1PinchArea::sendMouseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QDeclarative1PinchArea);
+ QGraphicsSceneMouseEvent mouseEvent(event->type());
+ QRectF myRect = mapToScene(QRectF(0, 0, width(), height())).boundingRect();
+
+ QGraphicsScene *s = scene();
+ QDeclarativeItem *grabber = s ? qobject_cast<QDeclarativeItem*>(s->mouseGrabberItem()) : 0;
+ bool stealThisEvent = d->stealMouse;
+ if ((stealThisEvent || myRect.contains(event->scenePos().toPoint())) && (!grabber || !grabber->keepMouseGrab())) {
+ mouseEvent.setAccepted(false);
+ for (int i = 0x1; i <= 0x10; i <<= 1) {
+ if (event->buttons() & i) {
+ Qt::MouseButton button = Qt::MouseButton(i);
+ mouseEvent.setButtonDownPos(button, mapFromScene(event->buttonDownPos(button)));
+ }
+ }
+ mouseEvent.setScenePos(event->scenePos());
+ mouseEvent.setLastScenePos(event->lastScenePos());
+ mouseEvent.setPos(mapFromScene(event->scenePos()));
+ mouseEvent.setLastPos(mapFromScene(event->lastScenePos()));
+
+ switch(mouseEvent.type()) {
+ case QEvent::GraphicsSceneMouseMove:
+ mouseMoveEvent(&mouseEvent);
+ break;
+ case QEvent::GraphicsSceneMousePress:
+ mousePressEvent(&mouseEvent);
+ break;
+ case QEvent::GraphicsSceneMouseRelease:
+ mouseReleaseEvent(&mouseEvent);
+ break;
+ default:
+ break;
+ }
+ grabber = qobject_cast<QDeclarativeItem*>(s->mouseGrabberItem());
+ if (grabber && stealThisEvent && !grabber->keepMouseGrab() && grabber != this)
+ grabMouse();
+
+ return stealThisEvent;
+ }
+ if (mouseEvent.type() == QEvent::GraphicsSceneMouseRelease) {
+ d->stealMouse = false;
+ if (s && s->mouseGrabberItem() == this)
+ ungrabMouse();
+ setKeepMouseGrab(false);
+ }
+ return false;
+}
+
+bool QDeclarative1PinchArea::sceneEventFilter(QGraphicsItem *i, QEvent *e)
+{
+ Q_D(QDeclarative1PinchArea);
+ if (!d->absorb || !isVisible())
+ return QDeclarativeItem::sceneEventFilter(i, e);
+ switch (e->type()) {
+ case QEvent::GraphicsSceneMousePress:
+ case QEvent::GraphicsSceneMouseMove:
+ case QEvent::GraphicsSceneMouseRelease:
+ return sendMouseEvent(static_cast<QGraphicsSceneMouseEvent *>(e));
+ break;
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate: {
+ QTouchEvent *touch = static_cast<QTouchEvent*>(e);
+ d->touchPoints.clear();
+ for (int i = 0; i < touch->touchPoints().count(); ++i)
+ if (!(touch->touchPoints().at(i).state() & Qt::TouchPointReleased))
+ d->touchPoints << touch->touchPoints().at(i);
+ updatePinch();
+ }
+ return d->inPinch;
+ case QEvent::TouchEnd:
+ d->touchPoints.clear();
+ updatePinch();
+ break;
+ default:
+ break;
+ }
+
+ return QDeclarativeItem::sceneEventFilter(i, e);
+}
+
+void QDeclarative1PinchArea::geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry)
+{
+ QDeclarativeItem::geometryChanged(newGeometry, oldGeometry);
+}
+
+QVariant QDeclarative1PinchArea::itemChange(GraphicsItemChange change,
+ const QVariant &value)
+{
+ return QDeclarativeItem::itemChange(change, value);
+}
+
+QDeclarative1Pinch *QDeclarative1PinchArea::pinch()
+{
+ Q_D(QDeclarative1PinchArea);
+ if (!d->pinch)
+ d->pinch = new QDeclarative1Pinch;
+ return d->pinch;
+}
+
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/graphicsitems/qdeclarativepincharea_p.h b/src/qtquick1/graphicsitems/qdeclarativepincharea_p.h
new file mode 100644
index 0000000000..4c1690f1fd
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativepincharea_p.h
@@ -0,0 +1,313 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEPINCHAREA_H
+#define QDECLARATIVEPINCHAREA_H
+
+#include <qdeclarativeitem.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_AUTOTEST_EXPORT QDeclarative1Pinch : public QObject
+{
+ Q_OBJECT
+
+ Q_ENUMS(Axis)
+ Q_PROPERTY(QGraphicsObject *target READ target WRITE setTarget RESET resetTarget)
+ Q_PROPERTY(qreal minimumScale READ minimumScale WRITE setMinimumScale NOTIFY minimumScaleChanged)
+ Q_PROPERTY(qreal maximumScale READ maximumScale WRITE setMaximumScale NOTIFY maximumScaleChanged)
+ Q_PROPERTY(qreal minimumRotation READ minimumRotation WRITE setMinimumRotation NOTIFY minimumRotationChanged)
+ Q_PROPERTY(qreal maximumRotation READ maximumRotation WRITE setMaximumRotation NOTIFY maximumRotationChanged)
+ Q_PROPERTY(Axis dragAxis READ axis WRITE setAxis NOTIFY dragAxisChanged)
+ Q_PROPERTY(qreal minimumX READ xmin WRITE setXmin NOTIFY minimumXChanged)
+ Q_PROPERTY(qreal maximumX READ xmax WRITE setXmax NOTIFY maximumXChanged)
+ Q_PROPERTY(qreal minimumY READ ymin WRITE setYmin NOTIFY minimumYChanged)
+ Q_PROPERTY(qreal maximumY READ ymax WRITE setYmax NOTIFY maximumYChanged)
+ Q_PROPERTY(bool active READ active NOTIFY activeChanged)
+
+public:
+ QDeclarative1Pinch();
+
+ QGraphicsObject *target() const { return m_target; }
+ void setTarget(QGraphicsObject *target) {
+ if (target == m_target)
+ return;
+ m_target = target;
+ emit targetChanged();
+ }
+ void resetTarget() {
+ if (!m_target)
+ return;
+ m_target = 0;
+ emit targetChanged();
+ }
+
+ qreal minimumScale() const { return m_minScale; }
+ void setMinimumScale(qreal s) {
+ if (s == m_minScale)
+ return;
+ m_minScale = s;
+ emit minimumScaleChanged();
+ }
+ qreal maximumScale() const { return m_maxScale; }
+ void setMaximumScale(qreal s) {
+ if (s == m_maxScale)
+ return;
+ m_maxScale = s;
+ emit maximumScaleChanged();
+ }
+
+ qreal minimumRotation() const { return m_minRotation; }
+ void setMinimumRotation(qreal r) {
+ if (r == m_minRotation)
+ return;
+ m_minRotation = r;
+ emit minimumRotationChanged();
+ }
+ qreal maximumRotation() const { return m_maxRotation; }
+ void setMaximumRotation(qreal r) {
+ if (r == m_maxRotation)
+ return;
+ m_maxRotation = r;
+ emit maximumRotationChanged();
+ }
+
+ enum Axis { NoDrag=0x00, XAxis=0x01, YAxis=0x02, XandYAxis=0x03 };
+ Axis axis() const { return m_axis; }
+ void setAxis(Axis a) {
+ if (a == m_axis)
+ return;
+ m_axis = a;
+ emit dragAxisChanged();
+ }
+
+ qreal xmin() const { return m_xmin; }
+ void setXmin(qreal x) {
+ if (x == m_xmin)
+ return;
+ m_xmin = x;
+ emit minimumXChanged();
+ }
+ qreal xmax() const { return m_xmax; }
+ void setXmax(qreal x) {
+ if (x == m_xmax)
+ return;
+ m_xmax = x;
+ emit maximumXChanged();
+ }
+ qreal ymin() const { return m_ymin; }
+ void setYmin(qreal y) {
+ if (y == m_ymin)
+ return;
+ m_ymin = y;
+ emit minimumYChanged();
+ }
+ qreal ymax() const { return m_ymax; }
+ void setYmax(qreal y) {
+ if (y == m_ymax)
+ return;
+ m_ymax = y;
+ emit maximumYChanged();
+ }
+
+ bool active() const { return m_active; }
+ void setActive(bool a) {
+ if (a == m_active)
+ return;
+ m_active = a;
+ emit activeChanged();
+ }
+
+signals:
+ void targetChanged();
+ void minimumScaleChanged();
+ void maximumScaleChanged();
+ void minimumRotationChanged();
+ void maximumRotationChanged();
+ void dragAxisChanged();
+ void minimumXChanged();
+ void maximumXChanged();
+ void minimumYChanged();
+ void maximumYChanged();
+ void activeChanged();
+
+private:
+ QGraphicsObject *m_target;
+ qreal m_minScale;
+ qreal m_maxScale;
+ qreal m_minRotation;
+ qreal m_maxRotation;
+ Axis m_axis;
+ qreal m_xmin;
+ qreal m_xmax;
+ qreal m_ymin;
+ qreal m_ymax;
+ bool m_active;
+};
+
+class Q_AUTOTEST_EXPORT QDeclarative1PinchEvent : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QPointF center READ center)
+ Q_PROPERTY(QPointF startCenter READ startCenter)
+ Q_PROPERTY(QPointF previousCenter READ previousCenter)
+ Q_PROPERTY(qreal scale READ scale)
+ Q_PROPERTY(qreal previousScale READ previousScale)
+ Q_PROPERTY(qreal angle READ angle)
+ Q_PROPERTY(qreal previousAngle READ previousAngle)
+ Q_PROPERTY(qreal rotation READ rotation)
+ Q_PROPERTY(QPointF point1 READ point1)
+ Q_PROPERTY(QPointF startPoint1 READ startPoint1)
+ Q_PROPERTY(QPointF point2 READ point2)
+ Q_PROPERTY(QPointF startPoint2 READ startPoint2)
+ Q_PROPERTY(int pointCount READ pointCount)
+ Q_PROPERTY(bool accepted READ accepted WRITE setAccepted)
+
+public:
+ QDeclarative1PinchEvent(QPointF c, qreal s, qreal a, qreal r)
+ : QObject(), m_center(c), m_scale(s), m_angle(a), m_rotation(r)
+ , m_pointCount(0), m_accepted(true) {}
+
+ QPointF center() const { return m_center; }
+ QPointF startCenter() const { return m_startCenter; }
+ void setStartCenter(QPointF c) { m_startCenter = c; }
+ QPointF previousCenter() const { return m_lastCenter; }
+ void setPreviousCenter(QPointF c) { m_lastCenter = c; }
+ qreal scale() const { return m_scale; }
+ qreal previousScale() const { return m_lastScale; }
+ void setPreviousScale(qreal s) { m_lastScale = s; }
+ qreal angle() const { return m_angle; }
+ qreal previousAngle() const { return m_lastAngle; }
+ void setPreviousAngle(qreal a) { m_lastAngle = a; }
+ qreal rotation() const { return m_rotation; }
+ QPointF point1() const { return m_point1; }
+ void setPoint1(QPointF p) { m_point1 = p; }
+ QPointF startPoint1() const { return m_startPoint1; }
+ void setStartPoint1(QPointF p) { m_startPoint1 = p; }
+ QPointF point2() const { return m_point2; }
+ void setPoint2(QPointF p) { m_point2 = p; }
+ QPointF startPoint2() const { return m_startPoint2; }
+ void setStartPoint2(QPointF p) { m_startPoint2 = p; }
+ int pointCount() const { return m_pointCount; }
+ void setPointCount(int count) { m_pointCount = count; }
+
+ bool accepted() const { return m_accepted; }
+ void setAccepted(bool a) { m_accepted = a; }
+
+private:
+ QPointF m_center;
+ QPointF m_startCenter;
+ QPointF m_lastCenter;
+ qreal m_scale;
+ qreal m_lastScale;
+ qreal m_angle;
+ qreal m_lastAngle;
+ qreal m_rotation;
+ QPointF m_point1;
+ QPointF m_point2;
+ QPointF m_startPoint1;
+ QPointF m_startPoint2;
+ int m_pointCount;
+ bool m_accepted;
+};
+
+
+class QDeclarative1MouseEvent;
+class QDeclarative1PinchAreaPrivate;
+class Q_AUTOTEST_EXPORT QDeclarative1PinchArea : public QDeclarativeItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged)
+ Q_PROPERTY(QDeclarative1Pinch *pinch READ pinch CONSTANT)
+
+public:
+ QDeclarative1PinchArea(QDeclarativeItem *parent=0);
+ ~QDeclarative1PinchArea();
+
+ bool isEnabled() const;
+ void setEnabled(bool);
+
+ QDeclarative1Pinch *pinch();
+
+Q_SIGNALS:
+ void enabledChanged();
+ void pinchStarted(QDeclarative1PinchEvent *pinch);
+ void pinchUpdated(QDeclarative1PinchEvent *pinch);
+ void pinchFinished(QDeclarative1PinchEvent *pinch);
+
+protected:
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ bool sceneEvent(QEvent *);
+ bool sendMouseEvent(QGraphicsSceneMouseEvent *event);
+ bool sceneEventFilter(QGraphicsItem *i, QEvent *e);
+ bool event(QEvent *);
+
+ virtual void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry);
+ virtual QVariant itemChange(GraphicsItemChange change, const QVariant& value);
+
+private:
+ void updatePinch();
+ void handlePress();
+ void handleRelease();
+
+private:
+ Q_DISABLE_COPY(QDeclarative1PinchArea)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarative1PinchArea)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1Pinch)
+QML_DECLARE_TYPE(QDeclarative1PinchEvent)
+QML_DECLARE_TYPE(QDeclarative1PinchArea)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEPINCHAREA_H
diff --git a/src/qtquick1/graphicsitems/qdeclarativepincharea_p_p.h b/src/qtquick1/graphicsitems/qdeclarativepincharea_p_p.h
new file mode 100644
index 0000000000..963ca6e1bc
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativepincharea_p_p.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEPINCHAREA_P_H
+#define QDECLARATIVEPINCHAREA_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qdatetime.h>
+#include <qbasictimer.h>
+#include <qevent.h>
+#include <qgraphicssceneevent.h>
+#include "qdeclarativeitem_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarative1Pinch;
+class QDeclarative1PinchAreaPrivate : public QDeclarativeItemPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1PinchArea)
+public:
+ QDeclarative1PinchAreaPrivate()
+ : absorb(true), stealMouse(false), inPinch(false)
+ , pinchRejected(false), pinchActivated(false)
+ , pinch(0), pinchStartDist(0), pinchStartScale(1.0)
+ , pinchLastScale(1.0), pinchStartRotation(0.0), pinchStartAngle(0.0)
+ , pinchLastAngle(0.0), pinchRotation(0.0)
+ {
+ }
+
+ ~QDeclarative1PinchAreaPrivate();
+
+ void init()
+ {
+ Q_Q(QDeclarative1PinchArea);
+ q->setAcceptedMouseButtons(Qt::LeftButton);
+ q->setAcceptTouchEvents(true);
+ q->setFiltersChildEvents(true);
+ }
+
+ bool absorb : 1;
+ bool stealMouse : 1;
+ bool inPinch : 1;
+ bool pinchRejected : 1;
+ bool pinchActivated : 1;
+ QDeclarative1Pinch *pinch;
+ QPointF sceneStartPoint1;
+ QPointF sceneStartPoint2;
+ QPointF lastPoint1;
+ QPointF lastPoint2;
+ qreal pinchStartDist;
+ qreal pinchStartScale;
+ qreal pinchLastScale;
+ qreal pinchStartRotation;
+ qreal pinchStartAngle;
+ qreal pinchLastAngle;
+ qreal pinchRotation;
+ QPointF sceneStartCenter;
+ QPointF pinchStartCenter;
+ QPointF sceneLastCenter;
+ QPointF pinchStartPos;
+ QList<QTouchEvent::TouchPoint> touchPoints;
+ int id1;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDECLARATIVEPINCHAREA_P_H
diff --git a/src/qtquick1/graphicsitems/qdeclarativepositioners.cpp b/src/qtquick1/graphicsitems/qdeclarativepositioners.cpp
new file mode 100644
index 0000000000..0defe40641
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativepositioners.cpp
@@ -0,0 +1,1396 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativepositioners_p.h"
+#include "QtQuick1/private/qdeclarativepositioners_p_p.h"
+
+#include <QtDeclarative/qdeclarative.h>
+#include <QtQuick1/private/qdeclarativestate_p.h>
+#include <QtQuick1/private/qdeclarativestategroup_p.h>
+#include <QtQuick1/private/qdeclarativestateoperations_p.h>
+#include <QtDeclarative/qdeclarativeinfo.h>
+#include <QtCore/qmath.h>
+
+#include <QDebug>
+#include <QCoreApplication>
+
+QT_BEGIN_NAMESPACE
+
+
+
+static const QDeclarativeItemPrivate::ChangeTypes watchedChanges
+ = QDeclarativeItemPrivate::Geometry
+ | QDeclarativeItemPrivate::SiblingOrder
+ | QDeclarativeItemPrivate::Visibility
+ | QDeclarativeItemPrivate::Opacity
+ | QDeclarativeItemPrivate::Destroyed;
+
+void QDeclarative1BasePositionerPrivate::watchChanges(QGraphicsObject *other)
+{
+ if (QGraphicsItemPrivate::get(other)->isDeclarativeItem) {
+ QDeclarativeItemPrivate *otherPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(other));
+ otherPrivate->addItemChangeListener(this, watchedChanges);
+ } else {
+ Q_Q(QDeclarative1BasePositioner);
+ QObject::connect(other, SIGNAL(widthChanged()), q, SLOT(graphicsWidgetGeometryChanged()));
+ QObject::connect(other, SIGNAL(heightChanged()), q, SLOT(graphicsWidgetGeometryChanged()));
+ QObject::connect(other, SIGNAL(opacityChanged()), q, SLOT(graphicsWidgetGeometryChanged()));
+ QObject::connect(other, SIGNAL(visibleChanged()), q, SLOT(graphicsWidgetGeometryChanged()));
+ }
+}
+
+void QDeclarative1BasePositionerPrivate::unwatchChanges(QGraphicsObject* other)
+{
+ if (QGraphicsItemPrivate::get(other)->isDeclarativeItem) {
+ QDeclarativeItemPrivate *otherPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(other));
+ otherPrivate->removeItemChangeListener(this, watchedChanges);
+ } else {
+ Q_Q(QDeclarative1BasePositioner);
+ QObject::disconnect(other, SIGNAL(widthChanged()), q, SLOT(graphicsWidgetGeometryChanged()));
+ QObject::disconnect(other, SIGNAL(heightChanged()), q, SLOT(graphicsWidgetGeometryChanged()));
+ QObject::disconnect(other, SIGNAL(opacityChanged()), q, SLOT(graphicsWidgetGeometryChanged()));
+ QObject::disconnect(other, SIGNAL(visibleChanged()), q, SLOT(graphicsWidgetGeometryChanged()));
+ }
+}
+
+void QDeclarative1BasePositioner::graphicsWidgetGeometryChanged()
+{
+ prePositioning();
+}
+
+/*!
+ \internal
+ \class QDeclarative1BasePositioner
+ \brief The QDeclarative1BasePositioner class provides a base for QDeclarative1Graphics layouts.
+
+ To create a QDeclarative1Graphics Positioner, simply subclass QDeclarative1BasePositioner and implement
+ doLayout(), which is automatically called when the layout might need
+ updating. In doLayout() use the setX and setY functions from QDeclarative1BasePositioner, and the
+ base class will apply the positions along with the appropriate transitions. The items to
+ position are provided in order as the protected member positionedItems.
+
+ You also need to set a PositionerType, to declare whether you are positioning the x, y or both
+ for the child items. Depending on the chosen type, only x or y changes will be applied.
+
+ Note that the subclass is responsible for adding the spacing in between items.
+*/
+QDeclarative1BasePositioner::QDeclarative1BasePositioner(PositionerType at, QDeclarativeItem *parent)
+ : QDeclarative1ImplicitSizeItem(*(new QDeclarative1BasePositionerPrivate), parent)
+{
+ Q_D(QDeclarative1BasePositioner);
+ d->init(at);
+}
+
+QDeclarative1BasePositioner::QDeclarative1BasePositioner(QDeclarative1BasePositionerPrivate &dd, PositionerType at, QDeclarativeItem *parent)
+ : QDeclarative1ImplicitSizeItem(dd, parent)
+{
+ Q_D(QDeclarative1BasePositioner);
+ d->init(at);
+}
+
+QDeclarative1BasePositioner::~QDeclarative1BasePositioner()
+{
+ Q_D(QDeclarative1BasePositioner);
+ for (int i = 0; i < positionedItems.count(); ++i)
+ d->unwatchChanges(positionedItems.at(i).item);
+ positionedItems.clear();
+}
+
+int QDeclarative1BasePositioner::spacing() const
+{
+ Q_D(const QDeclarative1BasePositioner);
+ return d->spacing;
+}
+
+void QDeclarative1BasePositioner::setSpacing(int s)
+{
+ Q_D(QDeclarative1BasePositioner);
+ if (s==d->spacing)
+ return;
+ d->spacing = s;
+ prePositioning();
+ emit spacingChanged();
+}
+
+QDeclarative1Transition *QDeclarative1BasePositioner::move() const
+{
+ Q_D(const QDeclarative1BasePositioner);
+ return d->moveTransition;
+}
+
+void QDeclarative1BasePositioner::setMove(QDeclarative1Transition *mt)
+{
+ Q_D(QDeclarative1BasePositioner);
+ if (mt == d->moveTransition)
+ return;
+ d->moveTransition = mt;
+ emit moveChanged();
+}
+
+QDeclarative1Transition *QDeclarative1BasePositioner::add() const
+{
+ Q_D(const QDeclarative1BasePositioner);
+ return d->addTransition;
+}
+
+void QDeclarative1BasePositioner::setAdd(QDeclarative1Transition *add)
+{
+ Q_D(QDeclarative1BasePositioner);
+ if (add == d->addTransition)
+ return;
+
+ d->addTransition = add;
+ emit addChanged();
+}
+
+void QDeclarative1BasePositioner::componentComplete()
+{
+ Q_D(QDeclarative1BasePositioner);
+ QDeclarativeItem::componentComplete();
+ positionedItems.reserve(d->QGraphicsItemPrivate::children.count());
+ prePositioning();
+ reportConflictingAnchors();
+}
+
+QVariant QDeclarative1BasePositioner::itemChange(GraphicsItemChange change,
+ const QVariant &value)
+{
+ Q_D(QDeclarative1BasePositioner);
+ if (change == ItemChildAddedChange){
+ QGraphicsItem* item = value.value<QGraphicsItem*>();
+ QGraphicsObject* child = 0;
+ if(item)
+ child = item->toGraphicsObject();
+ if (child)
+ prePositioning();
+ } else if (change == ItemChildRemovedChange) {
+ QGraphicsItem* item = value.value<QGraphicsItem*>();
+ QGraphicsObject* child = 0;
+ if(item)
+ child = item->toGraphicsObject();
+ if (child) {
+ QDeclarative1BasePositioner::PositionedItem posItem(child);
+ int idx = positionedItems.find(posItem);
+ if (idx >= 0) {
+ d->unwatchChanges(child);
+ positionedItems.remove(idx);
+ }
+ prePositioning();
+ }
+ }
+ return QDeclarativeItem::itemChange(change, value);
+}
+
+void QDeclarative1BasePositioner::prePositioning()
+{
+ Q_D(QDeclarative1BasePositioner);
+ if (!isComponentComplete())
+ return;
+
+ if (d->doingPositioning)
+ return;
+
+ d->queuedPositioning = false;
+ d->doingPositioning = true;
+ //Need to order children by creation order modified by stacking order
+ QList<QGraphicsItem *> children = d->QGraphicsItemPrivate::children;
+ qSort(children.begin(), children.end(), d->insertionOrder);
+
+ QPODVector<PositionedItem,8> oldItems;
+ positionedItems.copyAndClear(oldItems);
+ for (int ii = 0; ii < children.count(); ++ii) {
+ QGraphicsObject *child = children.at(ii)->toGraphicsObject();
+ if (!child)
+ continue;
+ QGraphicsItemPrivate *childPrivate = static_cast<QGraphicsItemPrivate*>(QGraphicsItemPrivate::get(child));
+ PositionedItem *item = 0;
+ PositionedItem posItem(child);
+ int wIdx = oldItems.find(posItem);
+ if (wIdx < 0) {
+ d->watchChanges(child);
+ positionedItems.append(posItem);
+ item = &positionedItems[positionedItems.count()-1];
+ item->isNew = true;
+ if (child->opacity() <= 0.0 || childPrivate->explicitlyHidden || !childPrivate->width() || !childPrivate->height())
+ item->isVisible = false;
+ } else {
+ item = &oldItems[wIdx];
+ // Items are only omitted from positioning if they are explicitly hidden
+ // i.e. their positioning is not affected if an ancestor is hidden.
+ if (child->opacity() <= 0.0 || childPrivate->explicitlyHidden || !childPrivate->width() || !childPrivate->height()) {
+ item->isVisible = false;
+ } else if (!item->isVisible) {
+ item->isVisible = true;
+ item->isNew = true;
+ } else {
+ item->isNew = false;
+ }
+ positionedItems.append(*item);
+ }
+ }
+ QSizeF contentSize;
+ doPositioning(&contentSize);
+ if(d->addTransition || d->moveTransition)
+ finishApplyTransitions();
+ d->doingPositioning = false;
+ //Set implicit size to the size of its children
+ setImplicitHeight(contentSize.height());
+ setImplicitWidth(contentSize.width());
+}
+
+void QDeclarative1BasePositioner::positionX(int x, const PositionedItem &target)
+{
+ Q_D(QDeclarative1BasePositioner);
+ if(d->type == Horizontal || d->type == Both){
+ if (target.isNew) {
+ if (!d->addTransition)
+ target.item->setX(x);
+ else
+ d->addActions << QDeclarative1Action(target.item, QLatin1String("x"), QVariant(x));
+ } else if (x != target.item->x()) {
+ if (!d->moveTransition)
+ target.item->setX(x);
+ else
+ d->moveActions << QDeclarative1Action(target.item, QLatin1String("x"), QVariant(x));
+ }
+ }
+}
+
+void QDeclarative1BasePositioner::positionY(int y, const PositionedItem &target)
+{
+ Q_D(QDeclarative1BasePositioner);
+ if(d->type == Vertical || d->type == Both){
+ if (target.isNew) {
+ if (!d->addTransition)
+ target.item->setY(y);
+ else
+ d->addActions << QDeclarative1Action(target.item, QLatin1String("y"), QVariant(y));
+ } else if (y != target.item->y()) {
+ if (!d->moveTransition)
+ target.item->setY(y);
+ else
+ d->moveActions << QDeclarative1Action(target.item, QLatin1String("y"), QVariant(y));
+ }
+ }
+}
+
+void QDeclarative1BasePositioner::finishApplyTransitions()
+{
+ Q_D(QDeclarative1BasePositioner);
+ // Note that if a transition is not set the transition manager will
+ // apply the changes directly, in the case add/move aren't set
+ d->addTransitionManager.transition(d->addActions, d->addTransition);
+ d->moveTransitionManager.transition(d->moveActions, d->moveTransition);
+ d->addActions.clear();
+ d->moveActions.clear();
+}
+
+/*!
+ \qmlclass Column QDeclarative1Column
+ \ingroup qml-positioning-elements
+ \since 4.7
+ \brief The Column item arranges its children vertically.
+ \inherits Item
+
+ The Column item positions its child items so that they are vertically
+ aligned and not overlapping.
+
+ Spacing between items can be added using the \l spacing property.
+ Transitions can be used for cases where items managed by a Column are
+ added or moved. These are stored in the \l add and \l move properties
+ respectively.
+
+ See \l{Using QML Positioner and Repeater Items} for more details about this item and other
+ related items.
+
+ \section1 Example Usage
+
+ The following example positions differently shaped rectangles using a Column
+ item.
+
+ \image verticalpositioner_example.png
+
+ \snippet doc/src/snippets/declarative/column/vertical-positioner.qml document
+
+ \section1 Using Transitions
+
+ Transitions can be used to animate items that are added to, moved within,
+ or removed from a Column item. The \l add and \l move properties can be set to
+ the transitions that will be applied when items are added to, removed from,
+ or re-positioned within a Column item.
+
+ The use of transitions with positioners is described in more detail in the
+ \l{Using QML Positioner and Repeater Items#Using Transitions}{Using QML
+ Positioner and Repeater Items} document.
+
+ \image verticalpositioner_transition.gif
+
+ \qml
+ Column {
+ spacing: 2
+ add: Transition {
+ // Define an animation for adding a new item...
+ }
+ move: Transition {
+ // Define an animation for moving items within the column...
+ }
+ // ...
+ }
+ \endqml
+
+ \section1 Limitations
+
+ Note that the positioner assumes that the x and y positions of its children
+ will not change. If you manually change the x or y properties in script, bind
+ the x or y properties, use anchors on a child of a positioner, or have the
+ height of a child depend on the position of a child, then the
+ positioner may exhibit strange behavior. If you need to perform any of these
+ actions, consider positioning the items without the use of a Column.
+
+ Items with a width or height of 0 will not be positioned.
+
+ \sa Row, Grid, Flow, {declarative/positioners}{Positioners example}
+*/
+/*!
+ \qmlproperty Transition Column::add
+
+ This property holds the transition to be applied when adding an
+ item to the positioner. The transition will only be applied to the
+ added item(s). Positioner transitions will only affect the
+ position (x, y) of items.
+
+ For a positioner, adding an item can mean that either the object
+ has been created or reparented, and thus is now a child or the
+ positioner, or that the object has had its opacity increased from
+ zero, and thus is now visible.
+
+ \sa move
+*/
+/*!
+ \qmlproperty Transition Column::move
+
+ This property holds the transition to apply when moving an item
+ within the positioner. Positioner transitions will only affect
+ the position (x, y) of items.
+
+ This transition can be performed when other items are added or removed
+ from the positioner, or when items resize themselves.
+
+ \image positioner-move.gif
+
+ \qml
+ Column {
+ move: Transition {
+ NumberAnimation {
+ properties: "y"
+ duration: 1000
+ }
+ }
+ }
+ \endqml
+
+ \sa add, {declarative/positioners}{Positioners example}
+*/
+/*!
+ \qmlproperty int Column::spacing
+
+ The spacing is the amount in pixels left empty between adjacent
+ items. The default spacing is 0.
+
+ \sa Grid::spacing
+*/
+QDeclarative1Column::QDeclarative1Column(QDeclarativeItem *parent)
+: QDeclarative1BasePositioner(Vertical, parent)
+{
+}
+
+void QDeclarative1Column::doPositioning(QSizeF *contentSize)
+{
+ int voffset = 0;
+
+ for (int ii = 0; ii < positionedItems.count(); ++ii) {
+ const PositionedItem &child = positionedItems.at(ii);
+ if (!child.item || !child.isVisible)
+ continue;
+
+ if(child.item->y() != voffset)
+ positionY(voffset, child);
+
+ contentSize->setWidth(qMax(contentSize->width(), QGraphicsItemPrivate::get(child.item)->width()));
+
+ voffset += QGraphicsItemPrivate::get(child.item)->height();
+ voffset += spacing();
+ }
+
+ contentSize->setHeight(voffset - spacing());
+}
+
+void QDeclarative1Column::reportConflictingAnchors()
+{
+ QDeclarative1BasePositionerPrivate *d = static_cast<QDeclarative1BasePositionerPrivate*>(QDeclarative1BasePositionerPrivate::get(this));
+ for (int ii = 0; ii < positionedItems.count(); ++ii) {
+ const PositionedItem &child = positionedItems.at(ii);
+ if (child.item && QGraphicsItemPrivate::get(child.item)->isDeclarativeItem) {
+ QDeclarative1Anchors *anchors = QDeclarativeItemPrivate::get(static_cast<QDeclarativeItem *>(child.item))->_anchors;
+ if (anchors) {
+ QDeclarative1Anchors::Anchors usedAnchors = anchors->usedAnchors();
+ if (usedAnchors & QDeclarative1Anchors::TopAnchor ||
+ usedAnchors & QDeclarative1Anchors::BottomAnchor ||
+ usedAnchors & QDeclarative1Anchors::VCenterAnchor ||
+ anchors->fill() || anchors->centerIn()) {
+ d->anchorConflict = true;
+ break;
+ }
+ }
+ }
+ }
+ if (d->anchorConflict) {
+ qmlInfo(this) << "Cannot specify top, bottom, verticalCenter, fill or centerIn anchors for items inside Column";
+ }
+}
+
+/*!
+ \qmlclass Row QDeclarative1Row
+ \ingroup qml-positioning-elements
+ \since 4.7
+ \brief The Row item arranges its children horizontally.
+ \inherits Item
+
+ The Row item positions its child items so that they are horizontally
+ aligned and not overlapping.
+
+ Use \l spacing to set the spacing between items in a Row, and use the
+ \l add and \l move properties to set the transitions that should be applied
+ when items are added to, removed from, or re-positioned within the Row.
+
+ See \l{Using QML Positioner and Repeater Items} for more details about this item and other
+ related items.
+
+ \section1 Example Usage
+
+ The following example lays out differently shaped rectangles using a Row.
+
+ \image horizontalpositioner_example.png
+
+ \snippet doc/src/snippets/declarative/row/row.qml document
+
+ \section1 Using Transitions
+
+ Transitions can be used to animate items that are added to, moved within,
+ or removed from a Grid item. The \l add and \l move properties can be set to
+ the transitions that will be applied when items are added to, removed from,
+ or re-positioned within a Row item.
+
+ \section1 Limitations
+
+ Note that the positioner assumes that the x and y positions of its children
+ will not change. If you manually change the x or y properties in script, bind
+ the x or y properties, use anchors on a child of a positioner, or have the
+ width of a child depend on the position of a child, then the
+ positioner may exhibit strange behaviour. If you need to perform any of these
+ actions, consider positioning the items without the use of a Row.
+
+ Items with a width or height of 0 will not be positioned.
+
+ \sa Column, Grid, Flow, {declarative/positioners}{Positioners example}
+*/
+/*!
+ \qmlproperty Transition Row::add
+
+ This property holds the transition to be applied when adding an
+ item to the positioner. The transition will only be applied to the
+ added item(s). Positioner transitions will only affect the
+ position (x, y) of items.
+
+ For a positioner, adding an item can mean that either the object
+ has been created or reparented, and thus is now a child or the
+ positioner, or that the object has had its opacity increased from
+ zero, and thus is now visible.
+
+ \sa move
+*/
+/*!
+ \qmlproperty Transition Row::move
+
+ This property holds the transition to be applied when moving an
+ item within the positioner. Positioner transitions will only affect
+ the position (x, y) of items.
+
+ This transition can be performed when other items are added or removed
+ from the positioner, or when items resize themselves.
+
+ \qml
+ Row {
+ id: positioner
+ move: Transition {
+ NumberAnimation {
+ properties: "x"
+ duration: 1000
+ }
+ }
+ }
+ \endqml
+
+ \sa add, {declarative/positioners}{Positioners example}
+*/
+/*!
+ \qmlproperty int Row::spacing
+
+ The spacing is the amount in pixels left empty between adjacent
+ items. The default spacing is 0.
+
+ \sa Grid::spacing
+*/
+QDeclarative1Row::QDeclarative1Row(QDeclarativeItem *parent)
+: QDeclarative1BasePositioner(Horizontal, parent)
+{
+}
+
+/*!
+ \qmlproperty enumeration Row::layoutDirection
+ \since Quick 1.1
+
+ This property holds the layoutDirection of the row.
+
+ Possible values:
+
+ \list
+ \o Qt.LeftToRight (default) - Items are laid out from left to right. If the width of the row is explicitly set,
+ the left anchor remains to the left of the row.
+ \o Qt.RightToLeft - Items are laid out from right to left. If the width of the row is explicitly set,
+ the right anchor remains to the right of the row.
+ \endlist
+
+ \sa Grid::layoutDirection, Flow::layoutDirection, {declarative/righttoleft/layoutdirection}{Layout directions example}
+*/
+Qt::LayoutDirection QDeclarative1Row::layoutDirection() const
+{
+ return QDeclarative1BasePositionerPrivate::getLayoutDirection(this);
+}
+
+void QDeclarative1Row::setLayoutDirection(Qt::LayoutDirection layoutDirection)
+{
+ QDeclarative1BasePositionerPrivate *d = static_cast<QDeclarative1BasePositionerPrivate* >(QDeclarative1BasePositionerPrivate::get(this));
+ if (d->layoutDirection != layoutDirection) {
+ d->layoutDirection = layoutDirection;
+ // For RTL layout the positioning changes when the width changes.
+ if (d->layoutDirection == Qt::RightToLeft)
+ d->addItemChangeListener(d, QDeclarativeItemPrivate::Geometry);
+ else
+ d->removeItemChangeListener(d, QDeclarativeItemPrivate::Geometry);
+ prePositioning();
+ emit layoutDirectionChanged();
+ emit effectiveLayoutDirectionChanged();
+ }
+}
+
+/*!
+ \qmlproperty enumeration Row::effectiveLayoutDirection
+ This property holds the effective layout direction of the row positioner.
+
+ When using the attached property \l {LayoutMirroring::enabled}{LayoutMirroring::enabled} for locale layouts,
+ the visual layout direction of the row positioner will be mirrored. However, the
+ property \l {Row::layoutDirection}{layoutDirection} will remain unchanged.
+
+ \sa Row::layoutDirection, {LayoutMirroring}{LayoutMirroring}
+*/
+
+Qt::LayoutDirection QDeclarative1Row::effectiveLayoutDirection() const
+{
+ return QDeclarative1BasePositionerPrivate::getEffectiveLayoutDirection(this);
+}
+
+void QDeclarative1Row::doPositioning(QSizeF *contentSize)
+{
+ QDeclarative1BasePositionerPrivate *d = static_cast<QDeclarative1BasePositionerPrivate*>(QDeclarative1BasePositionerPrivate::get(this));
+ int hoffset = 0;
+
+ QList<int> hoffsets;
+ for (int ii = 0; ii < positionedItems.count(); ++ii) {
+ const PositionedItem &child = positionedItems.at(ii);
+ if (!child.item || !child.isVisible)
+ continue;
+
+ if(d->isLeftToRight()){
+ if(child.item->x() != hoffset)
+ positionX(hoffset, child);
+ }else{
+ hoffsets << hoffset;
+ }
+
+ contentSize->setHeight(qMax(contentSize->height(), QGraphicsItemPrivate::get(child.item)->height()));
+
+ hoffset += QGraphicsItemPrivate::get(child.item)->width();
+ hoffset += spacing();
+ }
+
+ contentSize->setWidth(hoffset - spacing());
+
+ if(d->isLeftToRight())
+ return;
+
+ //Right to Left layout
+ int end = 0;
+ if(!widthValid())
+ end = contentSize->width();
+ else
+ end = width();
+
+ int acc = 0;
+ for (int ii = 0; ii < positionedItems.count(); ++ii) {
+ const PositionedItem &child = positionedItems.at(ii);
+ if (!child.item || !child.isVisible)
+ continue;
+ hoffset = end - hoffsets[acc++] - QGraphicsItemPrivate::get(child.item)->width();
+ if(child.item->x() != hoffset)
+ positionX(hoffset, child);
+ }
+}
+
+void QDeclarative1Row::reportConflictingAnchors()
+{
+ QDeclarative1BasePositionerPrivate *d = static_cast<QDeclarative1BasePositionerPrivate*>(QDeclarative1BasePositionerPrivate::get(this));
+ for (int ii = 0; ii < positionedItems.count(); ++ii) {
+ const PositionedItem &child = positionedItems.at(ii);
+ if (child.item && QGraphicsItemPrivate::get(child.item)->isDeclarativeItem) {
+ QDeclarative1Anchors *anchors = QDeclarativeItemPrivate::get(static_cast<QDeclarativeItem *>(child.item))->_anchors;
+ if (anchors) {
+ QDeclarative1Anchors::Anchors usedAnchors = anchors->usedAnchors();
+ if (usedAnchors & QDeclarative1Anchors::LeftAnchor ||
+ usedAnchors & QDeclarative1Anchors::RightAnchor ||
+ usedAnchors & QDeclarative1Anchors::HCenterAnchor ||
+ anchors->fill() || anchors->centerIn()) {
+ d->anchorConflict = true;
+ break;
+ }
+ }
+ }
+ }
+ if (d->anchorConflict)
+ qmlInfo(this) << "Cannot specify left, right, horizontalCenter, fill or centerIn anchors for items inside Row";
+}
+
+/*!
+ \qmlclass Grid QDeclarative1Grid
+ \ingroup qml-positioning-elements
+ \since 4.7
+ \brief The Grid item positions its children in a grid.
+ \inherits Item
+
+ The Grid item positions its child items so that they are
+ aligned in a grid and are not overlapping.
+
+ The grid positioner calculates a grid of rectangular cells of sufficient
+ size to hold all items, placing the items in the cells, from left to right
+ and top to bottom. Each item is positioned in the top-left corner of its
+ cell with position (0, 0).
+
+ A Grid defaults to four columns, and as many rows as are necessary to
+ fit all child items. The number of rows and columns can be constrained
+ by setting the \l rows and \l columns properties.
+
+ Spacing can be added between child items by setting the \l spacing
+ property. The amount of spacing applied will be the same in the
+ horizontal and vertical directions.
+
+ See \l{Using QML Positioner and Repeater Items} for more details about this item and other
+ related items.
+
+ \section1 Example Usage
+
+ The following example demonstrates this.
+
+ \image gridLayout_example.png
+
+ \snippet doc/src/snippets/declarative/grid/grid.qml document
+
+ \section1 Using Transitions
+
+ Transitions can be used to animate items that are added to, moved within,
+ or removed from a Grid item. The \l add and \l move properties can be set to
+ the transitions that will be applied when items are added to, removed from,
+ or re-positioned within a Grid item.
+
+ \section1 Limitations
+
+ Note that the positioner assumes that the x and y positions of its children
+ will not change. If you manually change the x or y properties in script, bind
+ the x or y properties, use anchors on a child of a positioner, or have the
+ width or height of a child depend on the position of a child, then the
+ positioner may exhibit strange behaviour. If you need to perform any of these
+ actions, consider positioning the items without the use of a Grid.
+
+ Items with a width or height of 0 will not be positioned.
+
+ \sa Flow, Row, Column, {declarative/positioners}{Positioners example}
+*/
+/*!
+ \qmlproperty Transition Grid::add
+
+ This property holds the transition to be applied when adding an
+ item to the positioner. The transition will only be applied to the
+ added item(s). Positioner transitions will only affect the
+ position (x, y) of items.
+
+ For a positioner, adding an item can mean that either the object
+ has been created or reparented, and thus is now a child or the
+ positioner, or that the object has had its opacity increased from
+ zero, and thus is now visible.
+
+ \sa move
+*/
+/*!
+ \qmlproperty Transition Grid::move
+
+ This property holds the transition to be applied when moving an
+ item within the positioner. Positioner transitions will only affect
+ the position (x, y) of items.
+
+ This transition can be performed when other items are added or removed
+ from the positioner, or when items resize themselves.
+
+ \qml
+ Grid {
+ move: Transition {
+ NumberAnimation {
+ properties: "x,y"
+ duration: 1000
+ }
+ }
+ }
+ \endqml
+
+ \sa add, {declarative/positioners}{Positioners example}
+*/
+/*!
+ \qmlproperty int Grid::spacing
+
+ The spacing is the amount in pixels left empty between adjacent
+ items. The default spacing is 0.
+
+ The below example places a Grid containing a red, a blue and a
+ green rectangle on a gray background. The area the grid positioner
+ occupies is colored white. The positioner on the left has the
+ no spacing (the default), and the positioner on the right has
+ a spacing of 6.
+
+ \inlineimage qml-grid-no-spacing.png
+ \inlineimage qml-grid-spacing.png
+
+ \sa rows, columns
+*/
+QDeclarative1Grid::QDeclarative1Grid(QDeclarativeItem *parent) :
+ QDeclarative1BasePositioner(Both, parent), m_rows(-1), m_columns(-1), m_flow(LeftToRight)
+{
+}
+
+/*!
+ \qmlproperty int Grid::columns
+
+ This property holds the number of columns in the grid. The default
+ number of columns is 4.
+
+ If the grid does not have enough items to fill the specified
+ number of columns, some columns will be of zero width.
+*/
+
+/*!
+ \qmlproperty int Grid::rows
+ This property holds the number of rows in the grid.
+
+ If the grid does not have enough items to fill the specified
+ number of rows, some rows will be of zero width.
+*/
+
+void QDeclarative1Grid::setColumns(const int columns)
+{
+ if (columns == m_columns)
+ return;
+ m_columns = columns;
+ prePositioning();
+ emit columnsChanged();
+}
+
+void QDeclarative1Grid::setRows(const int rows)
+{
+ if (rows == m_rows)
+ return;
+ m_rows = rows;
+ prePositioning();
+ emit rowsChanged();
+}
+
+/*!
+ \qmlproperty enumeration Grid::flow
+ This property holds the flow of the layout.
+
+ Possible values are:
+
+ \list
+ \o Grid.LeftToRight (default) - Items are positioned next to
+ each other in the \l layoutDirection, then wrapped to the next line.
+ \o Grid.TopToBottom - Items are positioned next to each
+ other from top to bottom, then wrapped to the next column.
+ \endlist
+*/
+QDeclarative1Grid::Flow QDeclarative1Grid::flow() const
+{
+ return m_flow;
+}
+
+void QDeclarative1Grid::setFlow(Flow flow)
+{
+ if (m_flow != flow) {
+ m_flow = flow;
+ prePositioning();
+ emit flowChanged();
+ }
+}
+
+/*!
+ \qmlproperty enumeration Grid::layoutDirection
+ \since Quick 1.1
+
+ This property holds the layout direction of the layout.
+
+ Possible values are:
+
+ \list
+ \o Qt.LeftToRight (default) - Items are positioned from the top to bottom,
+ and left to right. The flow direction is dependent on the
+ \l Grid::flow property.
+ \o Qt.RightToLeft - Items are positioned from the top to bottom,
+ and right to left. The flow direction is dependent on the
+ \l Grid::flow property.
+ \endlist
+
+ \sa Flow::layoutDirection, Row::layoutDirection, {declarative/righttoleft/layoutdirection}{Layout directions example}
+*/
+Qt::LayoutDirection QDeclarative1Grid::layoutDirection() const
+{
+ return QDeclarative1BasePositionerPrivate::getLayoutDirection(this);
+}
+
+void QDeclarative1Grid::setLayoutDirection(Qt::LayoutDirection layoutDirection)
+{
+ QDeclarative1BasePositionerPrivate *d = static_cast<QDeclarative1BasePositionerPrivate*>(QDeclarative1BasePositionerPrivate::get(this));
+ if (d->layoutDirection != layoutDirection) {
+ d->layoutDirection = layoutDirection;
+ // For RTL layout the positioning changes when the width changes.
+ if (d->layoutDirection == Qt::RightToLeft)
+ d->addItemChangeListener(d, QDeclarativeItemPrivate::Geometry);
+ else
+ d->removeItemChangeListener(d, QDeclarativeItemPrivate::Geometry);
+ prePositioning();
+ emit layoutDirectionChanged();
+ emit effectiveLayoutDirectionChanged();
+ }
+}
+
+/*!
+ \qmlproperty enumeration Grid::effectiveLayoutDirection
+ This property holds the effective layout direction of the grid positioner.
+
+ When using the attached property \l {LayoutMirroring::enabled}{LayoutMirroring::enabled} for locale layouts,
+ the visual layout direction of the grid positioner will be mirrored. However, the
+ property \l {Grid::layoutDirection}{layoutDirection} will remain unchanged.
+
+ \sa Grid::layoutDirection, {LayoutMirroring}{LayoutMirroring}
+*/
+
+Qt::LayoutDirection QDeclarative1Grid::effectiveLayoutDirection() const
+{
+ return QDeclarative1BasePositionerPrivate::getEffectiveLayoutDirection(this);
+}
+
+void QDeclarative1Grid::doPositioning(QSizeF *contentSize)
+{
+ QDeclarative1BasePositionerPrivate *d = static_cast<QDeclarative1BasePositionerPrivate*>(QDeclarative1BasePositionerPrivate::get(this));
+ int c = m_columns;
+ int r = m_rows;
+ //Is allocating the extra QPODVector too much overhead?
+ QPODVector<PositionedItem, 8> visibleItems;//we aren't concerned with invisible items
+ visibleItems.reserve(positionedItems.count());
+ for(int i=0; i<positionedItems.count(); i++)
+ if(positionedItems[i].item && positionedItems[i].isVisible)
+ visibleItems.append(positionedItems[i]);
+
+ int numVisible = visibleItems.count();
+ if (m_columns <= 0 && m_rows <= 0){
+ c = 4;
+ r = (numVisible+3)/4;
+ } else if (m_rows <= 0){
+ r = (numVisible+(m_columns-1))/m_columns;
+ } else if (m_columns <= 0){
+ c = (numVisible+(m_rows-1))/m_rows;
+ }
+
+ if(r==0 || c==0)
+ return; //Nothing to do
+
+ QList<int> maxColWidth;
+ QList<int> maxRowHeight;
+ int childIndex =0;
+ if (m_flow == LeftToRight) {
+ for (int i=0; i < r; i++){
+ for (int j=0; j < c; j++){
+ if (j==0)
+ maxRowHeight << 0;
+ if (i==0)
+ maxColWidth << 0;
+
+ if (childIndex == visibleItems.count())
+ break;
+
+ const PositionedItem &child = visibleItems.at(childIndex++);
+ QGraphicsItemPrivate *childPrivate = QGraphicsItemPrivate::get(child.item);
+ if (childPrivate->width() > maxColWidth[j])
+ maxColWidth[j] = childPrivate->width();
+ if (childPrivate->height() > maxRowHeight[i])
+ maxRowHeight[i] = childPrivate->height();
+ }
+ }
+ } else {
+ for (int j=0; j < c; j++){
+ for (int i=0; i < r; i++){
+ if (j==0)
+ maxRowHeight << 0;
+ if (i==0)
+ maxColWidth << 0;
+
+ if (childIndex == visibleItems.count())
+ break;
+
+ const PositionedItem &child = visibleItems.at(childIndex++);
+ QGraphicsItemPrivate *childPrivate = QGraphicsItemPrivate::get(child.item);
+ if (childPrivate->width() > maxColWidth[j])
+ maxColWidth[j] = childPrivate->width();
+ if (childPrivate->height() > maxRowHeight[i])
+ maxRowHeight[i] = childPrivate->height();
+ }
+ }
+ }
+
+ int widthSum = 0;
+ for(int j=0; j < maxColWidth.size(); j++){
+ if(j)
+ widthSum += spacing();
+ widthSum += maxColWidth[j];
+ }
+
+ int heightSum = 0;
+ for(int i=0; i < maxRowHeight.size(); i++){
+ if(i)
+ heightSum += spacing();
+ heightSum += maxRowHeight[i];
+ }
+
+ contentSize->setHeight(heightSum);
+ contentSize->setWidth(widthSum);
+
+ int end = 0;
+ if(widthValid())
+ end = width();
+ else
+ end = widthSum;
+
+ int xoffset=0;
+ if(!d->isLeftToRight())
+ xoffset=end;
+ int yoffset=0;
+ int curRow =0;
+ int curCol =0;
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ const PositionedItem &child = visibleItems.at(i);
+ int childXOffset = xoffset;
+ if(!d->isLeftToRight())
+ childXOffset -= QGraphicsItemPrivate::get(child.item)->width();
+ if((child.item->x()!=childXOffset)||(child.item->y()!=yoffset)){
+ positionX(childXOffset, child);
+ positionY(yoffset, child);
+ }
+
+ if (m_flow == LeftToRight) {
+ if(d->isLeftToRight())
+ xoffset+=maxColWidth[curCol]+spacing();
+ else
+ xoffset-=maxColWidth[curCol]+spacing();
+ curCol++;
+ curCol%=c;
+ if (!curCol){
+ yoffset+=maxRowHeight[curRow]+spacing();
+ if(d->isLeftToRight())
+ xoffset=0;
+ else
+ xoffset=end;
+ curRow++;
+ if (curRow>=r)
+ break;
+ }
+ } else {
+ yoffset+=maxRowHeight[curRow]+spacing();
+ curRow++;
+ curRow%=r;
+ if (!curRow){
+ if(d->isLeftToRight())
+ xoffset+=maxColWidth[curCol]+spacing();
+ else
+ xoffset-=maxColWidth[curCol]+spacing();
+ yoffset=0;
+ curCol++;
+ if (curCol>=c)
+ break;
+ }
+ }
+ }
+}
+
+void QDeclarative1Grid::reportConflictingAnchors()
+{
+ QDeclarative1BasePositionerPrivate *d = static_cast<QDeclarative1BasePositionerPrivate*>(QDeclarative1BasePositionerPrivate::get(this));
+ for (int ii = 0; ii < positionedItems.count(); ++ii) {
+ const PositionedItem &child = positionedItems.at(ii);
+ if (child.item && QGraphicsItemPrivate::get(child.item)->isDeclarativeItem) {
+ QDeclarative1Anchors *anchors = QDeclarativeItemPrivate::get(static_cast<QDeclarativeItem *>(child.item))->_anchors;
+ if (anchors && (anchors->usedAnchors() || anchors->fill() || anchors->centerIn())) {
+ d->anchorConflict = true;
+ break;
+ }
+ }
+ }
+ if (d->anchorConflict)
+ qmlInfo(this) << "Cannot specify anchors for items inside Grid";
+}
+
+/*!
+ \qmlclass Flow QDeclarative1Flow
+ \ingroup qml-positioning-elements
+ \since 4.7
+ \brief The Flow item arranges its children side by side, wrapping as necessary.
+ \inherits Item
+
+ The Flow item positions its child items like words on a page, wrapping them
+ to create rows or columns of items that do not overlap.
+
+ Spacing between items can be added using the \l spacing property.
+ Transitions can be used for cases where items managed by a Column are
+ added or moved. These are stored in the \l add and \l move properties
+ respectively.
+
+ See \l{Using QML Positioner and Repeater Items} for more details about this item and other
+ related items.
+
+ \section1 Example Usage
+
+ The following example positions \l Text items within a parent item using
+ a Flow item.
+
+ \image qml-flow-snippet.png
+
+ \snippet doc/src/snippets/declarative/flow.qml flow item
+
+ \section1 Using Transitions
+
+ Transitions can be used to animate items that are added to, moved within,
+ or removed from a Flow item. The \l add and \l move properties can be set to
+ the transitions that will be applied when items are added to, removed from,
+ or re-positioned within a Flow item.
+
+ The use of transitions with positioners is described in more detail in the
+ \l{Using QML Positioner and Repeater Items#Using Transitions}{Using QML
+ Positioner and Repeater Items} document.
+
+ \section1 Limitations
+
+ Note that the positioner assumes that the x and y positions of its children
+ will not change. If you manually change the x or y properties in script, bind
+ the x or y properties, use anchors on a child of a positioner, or have the
+ width or height of a child depend on the position of a child, then the
+ positioner may exhibit strange behaviour. If you need to perform any of these
+ actions, consider positioning the items without the use of a Flow.
+
+ Items with a width or height of 0 will not be positioned.
+
+ \sa Column, Row, Grid, {declarative/positioners}{Positioners example}
+*/
+/*!
+ \qmlproperty Transition Flow::add
+
+ This property holds the transition to be applied when adding an
+ item to the positioner. The transition will only be applied to the
+ added item(s). Positioner transitions will only affect the
+ position (x, y) of items.
+
+ For a positioner, adding an item can mean that either the object
+ has been created or reparented, and thus is now a child or the
+ positioner, or that the object has had its opacity increased from
+ zero, and thus is now visible.
+
+ \sa move
+*/
+/*!
+ \qmlproperty Transition Flow::move
+
+ This property holds the transition to be applied when moving an
+ item within the positioner. Positioner transitions will only affect
+ the position (x, y) of items.
+
+ This transition can be performed when other items are added or removed
+ from the positioner, or when items resize themselves.
+
+ \qml
+ Flow {
+ id: positioner
+ move: Transition {
+ NumberAnimation {
+ properties: "x,y"
+ ease: "easeOutBounce"
+ }
+ }
+ }
+ \endqml
+
+ \sa add, {declarative/positioners}{Positioners example}
+*/
+/*!
+ \qmlproperty int Flow::spacing
+
+ spacing is the amount in pixels left empty between each adjacent
+ item, and defaults to 0.
+
+ \sa Grid::spacing
+*/
+
+class QDeclarative1FlowPrivate : public QDeclarative1BasePositionerPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1Flow)
+
+public:
+ QDeclarative1FlowPrivate()
+ : QDeclarative1BasePositionerPrivate(), flow(QDeclarative1Flow::LeftToRight)
+ {}
+
+ QDeclarative1Flow::Flow flow;
+};
+
+QDeclarative1Flow::QDeclarative1Flow(QDeclarativeItem *parent)
+: QDeclarative1BasePositioner(*(new QDeclarative1FlowPrivate), Both, parent)
+{
+ Q_D(QDeclarative1Flow);
+ // Flow layout requires relayout if its own size changes too.
+ d->addItemChangeListener(d, QDeclarativeItemPrivate::Geometry);
+}
+
+/*!
+ \qmlproperty enumeration Flow::flow
+ This property holds the flow of the layout.
+
+ Possible values are:
+
+ \list
+ \o Flow.LeftToRight (default) - Items are positioned next to
+ to each other according to the \l layoutDirection until the width of the Flow
+ is exceeded, then wrapped to the next line.
+ \o Flow.TopToBottom - Items are positioned next to each
+ other from top to bottom until the height of the Flow is exceeded,
+ then wrapped to the next column.
+ \endlist
+*/
+QDeclarative1Flow::Flow QDeclarative1Flow::flow() const
+{
+ Q_D(const QDeclarative1Flow);
+ return d->flow;
+}
+
+void QDeclarative1Flow::setFlow(Flow flow)
+{
+ Q_D(QDeclarative1Flow);
+ if (d->flow != flow) {
+ d->flow = flow;
+ prePositioning();
+ emit flowChanged();
+ }
+}
+
+/*!
+ \qmlproperty enumeration Flow::layoutDirection
+ \since Quick 1.1
+
+ This property holds the layout direction of the layout.
+
+ Possible values are:
+
+ \list
+ \o Qt.LeftToRight (default) - Items are positioned from the top to bottom,
+ and left to right. The flow direction is dependent on the
+ \l Flow::flow property.
+ \o Qt.RightToLeft - Items are positioned from the top to bottom,
+ and right to left. The flow direction is dependent on the
+ \l Flow::flow property.
+ \endlist
+
+ \sa Grid::layoutDirection, Row::layoutDirection, {declarative/righttoleft/layoutdirection}{Layout directions example}
+*/
+
+Qt::LayoutDirection QDeclarative1Flow::layoutDirection() const
+{
+ Q_D(const QDeclarative1Flow);
+ return d->layoutDirection;
+}
+
+void QDeclarative1Flow::setLayoutDirection(Qt::LayoutDirection layoutDirection)
+{
+ Q_D(QDeclarative1Flow);
+ if (d->layoutDirection != layoutDirection) {
+ d->layoutDirection = layoutDirection;
+ prePositioning();
+ emit layoutDirectionChanged();
+ emit effectiveLayoutDirectionChanged();
+ }
+}
+
+/*!
+ \qmlproperty enumeration Flow::effectiveLayoutDirection
+ This property holds the effective layout direction of the flow positioner.
+
+ When using the attached property \l {LayoutMirroring::enabled}{LayoutMirroring::enabled} for locale layouts,
+ the visual layout direction of the grid positioner will be mirrored. However, the
+ property \l {Flow::layoutDirection}{layoutDirection} will remain unchanged.
+
+ \sa Flow::layoutDirection, {LayoutMirroring}{LayoutMirroring}
+*/
+
+Qt::LayoutDirection QDeclarative1Flow::effectiveLayoutDirection() const
+{
+ return QDeclarative1BasePositionerPrivate::getEffectiveLayoutDirection(this);
+}
+
+void QDeclarative1Flow::doPositioning(QSizeF *contentSize)
+{
+ Q_D(QDeclarative1Flow);
+
+ int hoffset = 0;
+ int voffset = 0;
+ int linemax = 0;
+ QList<int> hoffsets;
+
+ for (int i = 0; i < positionedItems.count(); ++i) {
+ const PositionedItem &child = positionedItems.at(i);
+ if (!child.item || !child.isVisible)
+ continue;
+
+ QGraphicsItemPrivate *childPrivate = QGraphicsItemPrivate::get(child.item);
+ if (d->flow == LeftToRight) {
+ if (widthValid() && hoffset && hoffset + childPrivate->width() > width()) {
+ hoffset = 0;
+ voffset += linemax + spacing();
+ linemax = 0;
+ }
+ } else {
+ if (heightValid() && voffset && voffset + childPrivate->height() > height()) {
+ voffset = 0;
+ hoffset += linemax + spacing();
+ linemax = 0;
+ }
+ }
+
+ if(d->isLeftToRight()){
+ if(child.item->x() != hoffset)
+ positionX(hoffset, child);
+ }else{
+ hoffsets << hoffset;
+ }
+ if(child.item->y() != voffset)
+ positionY(voffset, child);
+
+ contentSize->setWidth(qMax(contentSize->width(), hoffset + childPrivate->width()));
+ contentSize->setHeight(qMax(contentSize->height(), voffset + childPrivate->height()));
+
+ if (d->flow == LeftToRight) {
+ hoffset += childPrivate->width();
+ hoffset += spacing();
+ linemax = qMax(linemax, qCeil(childPrivate->height()));
+ } else {
+ voffset += childPrivate->height();
+ voffset += spacing();
+ linemax = qMax(linemax, qCeil(childPrivate->width()));
+ }
+ }
+
+ if(d->isLeftToRight())
+ return;
+
+ int end;
+ if(widthValid())
+ end = width();
+ else
+ end = contentSize->width();
+ int acc = 0;
+ for (int i = 0; i < positionedItems.count(); ++i) {
+ const PositionedItem &child = positionedItems.at(i);
+ if (!child.item || !child.isVisible)
+ continue;
+ hoffset = end - hoffsets[acc++] - QGraphicsItemPrivate::get(child.item)->width();
+ if(child.item->x() != hoffset)
+ positionX(hoffset, child);
+ }
+}
+
+void QDeclarative1Flow::reportConflictingAnchors()
+{
+ Q_D(QDeclarative1Flow);
+ for (int ii = 0; ii < positionedItems.count(); ++ii) {
+ const PositionedItem &child = positionedItems.at(ii);
+ if (child.item && QGraphicsItemPrivate::get(child.item)->isDeclarativeItem) {
+ QDeclarative1Anchors *anchors = QDeclarativeItemPrivate::get(static_cast<QDeclarativeItem *>(child.item))->_anchors;
+ if (anchors && (anchors->usedAnchors() || anchors->fill() || anchors->centerIn())) {
+ d->anchorConflict = true;
+ break;
+ }
+ }
+ }
+ if (d->anchorConflict)
+ qmlInfo(this) << "Cannot specify anchors for items inside Flow";
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/graphicsitems/qdeclarativepositioners_p.h b/src/qtquick1/graphicsitems/qdeclarativepositioners_p.h
new file mode 100644
index 0000000000..c5f25228bd
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativepositioners_p.h
@@ -0,0 +1,239 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVELAYOUTS_H
+#define QDECLARATIVELAYOUTS_H
+
+#include "qdeclarativeimplicitsizeitem_p.h"
+
+#include <QtQuick1/private/qdeclarativestate_p.h>
+#include <private/qpodvector_p.h>
+
+#include <QtCore/QObject>
+#include <QtCore/QString>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QDeclarative1BasePositionerPrivate;
+
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarative1BasePositioner : public QDeclarative1ImplicitSizeItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int spacing READ spacing WRITE setSpacing NOTIFY spacingChanged)
+ Q_PROPERTY(QDeclarative1Transition *move READ move WRITE setMove NOTIFY moveChanged)
+ Q_PROPERTY(QDeclarative1Transition *add READ add WRITE setAdd NOTIFY addChanged)
+public:
+ enum PositionerType { None = 0x0, Horizontal = 0x1, Vertical = 0x2, Both = 0x3 };
+ QDeclarative1BasePositioner(PositionerType, QDeclarativeItem *parent);
+ ~QDeclarative1BasePositioner();
+
+ int spacing() const;
+ void setSpacing(int);
+
+ QDeclarative1Transition *move() const;
+ void setMove(QDeclarative1Transition *);
+
+ QDeclarative1Transition *add() const;
+ void setAdd(QDeclarative1Transition *);
+
+protected:
+ QDeclarative1BasePositioner(QDeclarative1BasePositionerPrivate &dd, PositionerType at, QDeclarativeItem *parent);
+ virtual void componentComplete();
+ virtual QVariant itemChange(GraphicsItemChange, const QVariant &);
+ void finishApplyTransitions();
+
+Q_SIGNALS:
+ void spacingChanged();
+ void moveChanged();
+ void addChanged();
+
+protected Q_SLOTS:
+ void prePositioning();
+ void graphicsWidgetGeometryChanged();
+
+protected:
+ virtual void doPositioning(QSizeF *contentSize)=0;
+ virtual void reportConflictingAnchors()=0;
+ class PositionedItem {
+ public :
+ PositionedItem(QGraphicsObject *i) : item(i), isNew(false), isVisible(true) {}
+ bool operator==(const PositionedItem &other) const { return other.item == item; }
+ QGraphicsObject *item;
+ bool isNew;
+ bool isVisible;
+ };
+
+ QPODVector<PositionedItem,8> positionedItems;
+ void positionX(int,const PositionedItem &target);
+ void positionY(int,const PositionedItem &target);
+
+private:
+ Q_DISABLE_COPY(QDeclarative1BasePositioner)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarative1BasePositioner)
+};
+
+class Q_AUTOTEST_EXPORT QDeclarative1Column : public QDeclarative1BasePositioner
+{
+ Q_OBJECT
+public:
+ QDeclarative1Column(QDeclarativeItem *parent=0);
+protected:
+ virtual void doPositioning(QSizeF *contentSize);
+ virtual void reportConflictingAnchors();
+private:
+ Q_DISABLE_COPY(QDeclarative1Column)
+};
+
+class Q_AUTOTEST_EXPORT QDeclarative1Row: public QDeclarative1BasePositioner
+{
+ Q_OBJECT
+ Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged REVISION 1)
+ Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged REVISION 1)
+public:
+ QDeclarative1Row(QDeclarativeItem *parent=0);
+
+ Qt::LayoutDirection layoutDirection() const;
+ void setLayoutDirection (Qt::LayoutDirection);
+ Qt::LayoutDirection effectiveLayoutDirection() const;
+
+Q_SIGNALS:
+ Q_REVISION(1) void layoutDirectionChanged();
+ Q_REVISION(1) void effectiveLayoutDirectionChanged();
+
+protected:
+ virtual void doPositioning(QSizeF *contentSize);
+ virtual void reportConflictingAnchors();
+private:
+ Q_DISABLE_COPY(QDeclarative1Row)
+};
+
+class Q_AUTOTEST_EXPORT QDeclarative1Grid : public QDeclarative1BasePositioner
+{
+ Q_OBJECT
+ Q_PROPERTY(int rows READ rows WRITE setRows NOTIFY rowsChanged)
+ Q_PROPERTY(int columns READ columns WRITE setColumns NOTIFY columnsChanged)
+ Q_PROPERTY(Flow flow READ flow WRITE setFlow NOTIFY flowChanged)
+ Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged REVISION 1)
+ Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged REVISION 1)
+public:
+ QDeclarative1Grid(QDeclarativeItem *parent=0);
+
+ int rows() const {return m_rows;}
+ void setRows(const int rows);
+
+ int columns() const {return m_columns;}
+ void setColumns(const int columns);
+
+ Q_ENUMS(Flow)
+ enum Flow { LeftToRight, TopToBottom };
+ Flow flow() const;
+ void setFlow(Flow);
+
+ Qt::LayoutDirection layoutDirection() const;
+ void setLayoutDirection (Qt::LayoutDirection);
+ Qt::LayoutDirection effectiveLayoutDirection() const;
+
+Q_SIGNALS:
+ void rowsChanged();
+ void columnsChanged();
+ void flowChanged();
+ Q_REVISION(1) void layoutDirectionChanged();
+ Q_REVISION(1) void effectiveLayoutDirectionChanged();
+
+protected:
+ virtual void doPositioning(QSizeF *contentSize);
+ virtual void reportConflictingAnchors();
+
+private:
+ int m_rows;
+ int m_columns;
+ Flow m_flow;
+ Q_DISABLE_COPY(QDeclarative1Grid)
+};
+
+class QDeclarative1FlowPrivate;
+class Q_AUTOTEST_EXPORT QDeclarative1Flow: public QDeclarative1BasePositioner
+{
+ Q_OBJECT
+ Q_PROPERTY(Flow flow READ flow WRITE setFlow NOTIFY flowChanged)
+ Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged REVISION 1)
+ Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged REVISION 1)
+public:
+ QDeclarative1Flow(QDeclarativeItem *parent=0);
+
+ Q_ENUMS(Flow)
+ enum Flow { LeftToRight, TopToBottom };
+ Flow flow() const;
+ void setFlow(Flow);
+
+ Qt::LayoutDirection layoutDirection() const;
+ void setLayoutDirection (Qt::LayoutDirection);
+ Qt::LayoutDirection effectiveLayoutDirection() const;
+Q_SIGNALS:
+ void flowChanged();
+ Q_REVISION(1) void layoutDirectionChanged();
+ Q_REVISION(1) void effectiveLayoutDirectionChanged();
+
+protected:
+ virtual void doPositioning(QSizeF *contentSize);
+ virtual void reportConflictingAnchors();
+protected:
+ QDeclarative1Flow(QDeclarative1FlowPrivate &dd, QDeclarativeItem *parent);
+private:
+ Q_DISABLE_COPY(QDeclarative1Flow)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarative1Flow)
+};
+
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1Column)
+QML_DECLARE_TYPE(QDeclarative1Row)
+QML_DECLARE_TYPE(QDeclarative1Grid)
+QML_DECLARE_TYPE(QDeclarative1Flow)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/qtquick1/graphicsitems/qdeclarativepositioners_p_p.h b/src/qtquick1/graphicsitems/qdeclarativepositioners_p_p.h
new file mode 100644
index 0000000000..eb2c9fdc88
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativepositioners_p_p.h
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVELAYOUTS_P_H
+#define QDECLARATIVELAYOUTS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qdeclarativepositioners_p.h"
+
+#include "private/qdeclarativeimplicitsizeitem_p_p.h"
+
+#include <QtQuick1/private/qdeclarativestate_p.h>
+#include <QtQuick1/private/qdeclarativetransitionmanager_p_p.h>
+#include <QtQuick1/private/qdeclarativestateoperations_p.h>
+
+#include <QtCore/QObject>
+#include <QtCore/QString>
+#include <QtCore/QTimer>
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarative1BasePositionerPrivate : public QDeclarative1ImplicitSizeItemPrivate, public QDeclarativeItemChangeListener
+{
+ Q_DECLARE_PUBLIC(QDeclarative1BasePositioner)
+
+public:
+ QDeclarative1BasePositionerPrivate()
+ : spacing(0), type(QDeclarative1BasePositioner::None)
+ , moveTransition(0), addTransition(0), queuedPositioning(false)
+ , doingPositioning(false), anchorConflict(false), layoutDirection(Qt::LeftToRight)
+ {
+ }
+
+ void init(QDeclarative1BasePositioner::PositionerType at)
+ {
+ type = at;
+ }
+
+ int spacing;
+
+ QDeclarative1BasePositioner::PositionerType type;
+ QDeclarative1Transition *moveTransition;
+ QDeclarative1Transition *addTransition;
+ QDeclarative1StateOperation::ActionList addActions;
+ QDeclarative1StateOperation::ActionList moveActions;
+ QDeclarative1TransitionManager addTransitionManager;
+ QDeclarative1TransitionManager moveTransitionManager;
+
+ void watchChanges(QGraphicsObject *other);
+ void unwatchChanges(QGraphicsObject* other);
+ bool queuedPositioning : 1;
+ bool doingPositioning : 1;
+ bool anchorConflict : 1;
+
+ Qt::LayoutDirection layoutDirection;
+
+
+ void schedulePositioning()
+ {
+ Q_Q(QDeclarative1BasePositioner);
+ if(!queuedPositioning){
+ QTimer::singleShot(0,q,SLOT(prePositioning()));
+ queuedPositioning = true;
+ }
+ }
+
+ void mirrorChange() {
+ Q_Q(QDeclarative1BasePositioner);
+ if (type != QDeclarative1BasePositioner::Vertical)
+ q->prePositioning();
+ }
+ bool isLeftToRight() const {
+ if (type == QDeclarative1BasePositioner::Vertical)
+ return true;
+ else
+ return effectiveLayoutMirror ? layoutDirection == Qt::RightToLeft : layoutDirection == Qt::LeftToRight;
+ }
+
+ virtual void itemSiblingOrderChanged(QDeclarativeItem* other)
+ {
+ Q_UNUSED(other);
+ //Delay is due to many children often being reordered at once
+ //And we only want to reposition them all once
+ schedulePositioning();
+ }
+
+ void itemGeometryChanged(QDeclarativeItem *, const QRectF &newGeometry, const QRectF &oldGeometry)
+ {
+ Q_Q(QDeclarative1BasePositioner);
+ if (newGeometry.size() != oldGeometry.size())
+ q->prePositioning();
+ }
+
+ virtual void itemVisibilityChanged(QDeclarativeItem *)
+ {
+ schedulePositioning();
+ }
+ virtual void itemOpacityChanged(QDeclarativeItem *)
+ {
+ Q_Q(QDeclarative1BasePositioner);
+ q->prePositioning();
+ }
+
+ void itemDestroyed(QDeclarativeItem *item)
+ {
+ Q_Q(QDeclarative1BasePositioner);
+ q->positionedItems.removeOne(QDeclarative1BasePositioner::PositionedItem(item));
+ }
+
+ static Qt::LayoutDirection getLayoutDirection(const QDeclarative1BasePositioner *positioner)
+ {
+ return positioner->d_func()->layoutDirection;
+ }
+
+ static Qt::LayoutDirection getEffectiveLayoutDirection(const QDeclarative1BasePositioner *positioner)
+ {
+ if (positioner->d_func()->effectiveLayoutMirror)
+ return positioner->d_func()->layoutDirection == Qt::RightToLeft ? Qt::LeftToRight : Qt::RightToLeft;
+ else
+ return positioner->d_func()->layoutDirection;
+ }
+};
+
+QT_END_NAMESPACE
+#endif
diff --git a/src/qtquick1/graphicsitems/qdeclarativerectangle.cpp b/src/qtquick1/graphicsitems/qdeclarativerectangle.cpp
new file mode 100644
index 0000000000..d0bb5d143d
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativerectangle.cpp
@@ -0,0 +1,591 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativerectangle_p.h"
+#include "QtQuick1/private/qdeclarativerectangle_p_p.h"
+
+#include <QPainter>
+#include <QStringBuilder>
+#include <QtCore/qmath.h>
+
+QT_BEGIN_NAMESPACE
+
+
+
+/*!
+ \internal
+ \class QDeclarative1Pen
+ \brief The QDeclarative1Pen class provides a pen used for drawing rectangle borders on a QDeclarative1View.
+
+ By default, the pen is invalid and nothing is drawn. You must either set a color (then the default
+ width is 1) or a width (then the default color is black).
+
+ A width of 1 indicates is a single-pixel line on the border of the item being painted.
+
+ Example:
+ \qml
+ Rectangle {
+ border.width: 2
+ border.color: "red"
+ }
+ \endqml
+*/
+
+void QDeclarative1Pen::setColor(const QColor &c)
+{
+ _color = c;
+ _valid = (_color.alpha() && _width >= 1) ? true : false;
+ emit penChanged();
+}
+
+void QDeclarative1Pen::setWidth(int w)
+{
+ if (_width == w && _valid)
+ return;
+
+ _width = w;
+ _valid = (_color.alpha() && _width >= 1) ? true : false;
+ emit penChanged();
+}
+
+
+/*!
+ \qmlclass GradientStop QDeclarative1GradientStop
+ \ingroup qml-basic-visual-elements
+ \since 4.7
+ \brief The GradientStop item defines the color at a position in a Gradient.
+
+ \sa Gradient
+*/
+
+/*!
+ \qmlproperty real GradientStop::position
+ \qmlproperty color GradientStop::color
+
+ The position and color properties describe the color used at a given
+ position in a gradient, as represented by a gradient stop.
+
+ The default position is 0.0; the default color is black.
+
+ \sa Gradient
+*/
+
+void QDeclarative1GradientStop::updateGradient()
+{
+ if (QDeclarative1Gradient *grad = qobject_cast<QDeclarative1Gradient*>(parent()))
+ grad->doUpdate();
+}
+
+/*!
+ \qmlclass Gradient QDeclarative1Gradient
+ \ingroup qml-basic-visual-elements
+ \since 4.7
+ \brief The Gradient item defines a gradient fill.
+
+ A gradient is defined by two or more colors, which will be blended seamlessly.
+
+ The colors are specified as a set of GradientStop child items, each of
+ which defines a position on the gradient from 0.0 to 1.0 and a color.
+ The position of each GradientStop is defined by setting its
+ \l{GradientStop::}{position} property; its color is defined using its
+ \l{GradientStop::}{color} property.
+
+ A gradient without any gradient stops is rendered as a solid white fill.
+
+ Note that this item is not a visual representation of a gradient. To display a
+ gradient, use a visual element (like \l Rectangle) which supports the use
+ of gradients.
+
+ \section1 Example Usage
+
+ \div {class="float-right"}
+ \inlineimage qml-gradient.png
+ \enddiv
+
+ The following example declares a \l Rectangle item with a gradient starting
+ with red, blending to yellow at one third of the height of the rectangle,
+ and ending with green:
+
+ \snippet doc/src/snippets/declarative/gradient.qml code
+
+ \clearfloat
+ \section1 Performance and Limitations
+
+ Calculating gradients can be computationally expensive compared to the use
+ of solid color fills or images. Consider using gradients for static items
+ in a user interface.
+
+ In Qt 4.7, only vertical, linear gradients can be applied to items. If you
+ need to apply different orientations of gradients, a combination of rotation
+ and clipping will need to be applied to the relevant items. This can
+ introduce additional performance requirements for your application.
+
+ The use of animations involving gradient stops may not give the desired
+ result. An alternative way to animate gradients is to use pre-generated
+ images or SVG drawings containing gradients.
+
+ \sa GradientStop
+*/
+
+/*!
+ \qmlproperty list<GradientStop> Gradient::stops
+ This property holds the gradient stops describing the gradient.
+
+ By default, this property contains an empty list.
+
+ To set the gradient stops, define them as children of the Gradient element.
+*/
+
+const QGradient *QDeclarative1Gradient::gradient() const
+{
+ if (!m_gradient && !m_stops.isEmpty()) {
+ m_gradient = new QLinearGradient(0,0,0,1.0);
+ for (int i = 0; i < m_stops.count(); ++i) {
+ const QDeclarative1GradientStop *stop = m_stops.at(i);
+ m_gradient->setCoordinateMode(QGradient::ObjectBoundingMode);
+ m_gradient->setColorAt(stop->position(), stop->color());
+ }
+ }
+
+ return m_gradient;
+}
+
+void QDeclarative1Gradient::doUpdate()
+{
+ delete m_gradient;
+ m_gradient = 0;
+ emit updated();
+}
+
+
+/*!
+ \qmlclass Rectangle QDeclarative1Rectangle
+ \ingroup qml-basic-visual-elements
+ \since 4.7
+ \brief The Rectangle item provides a filled rectangle with an optional border.
+ \inherits Item
+
+ Rectangle items are used to fill areas with solid color or gradients, and are
+ often used to hold other items.
+
+ \section1 Appearance
+
+ Each Rectangle item is painted using either a solid fill color, specified using
+ the \l color property, or a gradient, defined using a Gradient element and set
+ using the \l gradient property. If both a color and a gradient are specified,
+ the gradient is used.
+
+ You can add an optional border to a rectangle with its own color and thickness
+ by settting the \l border.color and \l border.width properties.
+
+ You can also create rounded rectangles using the \l radius property. Since this
+ introduces curved edges to the corners of a rectangle, it may be appropriate to
+ set the \l smooth property to improve its appearance.
+
+ \section1 Example Usage
+
+ \div {class="float-right"}
+ \inlineimage declarative-rect.png
+ \enddiv
+
+ The following example shows the effects of some of the common properties on a
+ Rectangle item, which in this case is used to create a square:
+
+ \snippet doc/src/snippets/declarative/rectangle/rectangle.qml document
+
+ \clearfloat
+ \section1 Performance
+
+ Using the \l smooth property improves the appearance of a rounded rectangle at
+ the cost of rendering performance. You should consider unsetting this property
+ for rectangles in motion, and only set it when they are stationary.
+
+ \sa Image
+*/
+
+int QDeclarative1RectanglePrivate::doUpdateSlotIdx = -1;
+
+QDeclarative1Rectangle::QDeclarative1Rectangle(QDeclarativeItem *parent)
+ : QDeclarativeItem(*(new QDeclarative1RectanglePrivate), parent)
+{
+}
+
+void QDeclarative1Rectangle::doUpdate()
+{
+ Q_D(QDeclarative1Rectangle);
+ d->rectImage = QPixmap();
+ const int pw = d->pen && d->pen->isValid() ? d->pen->width() : 0;
+ d->setPaintMargin((pw+1)/2);
+ update();
+}
+
+/*!
+ \qmlproperty int Rectangle::border.width
+ \qmlproperty color Rectangle::border.color
+
+ The width and color used to draw the border of the rectangle.
+
+ A width of 1 creates a thin line. For no line, use a width of 0 or a transparent color.
+
+ \note The width of the rectangle's border does not affect the geometry of the
+ rectangle itself or its position relative to other items if anchors are used.
+
+ If \c border.width is an odd number, the rectangle is painted at a half-pixel offset to retain
+ border smoothness. Also, the border is rendered evenly on either side of the
+ rectangle's boundaries, and the spare pixel is rendered to the right and below the
+ rectangle (as documented for QRect rendering). This can cause unintended effects if
+ \c border.width is 1 and the rectangle is \l{Item::clip}{clipped} by a parent item:
+
+ \div {class="float-right"}
+ \inlineimage rect-border-width.png
+ \enddiv
+
+ \snippet doc/src/snippets/declarative/rectangle/rect-border-width.qml 0
+
+ \clearfloat
+ Here, the innermost rectangle's border is clipped on the bottom and right edges by its
+ parent. To avoid this, the border width can be set to two instead of one.
+*/
+QDeclarative1Pen *QDeclarative1Rectangle::border()
+{
+ Q_D(QDeclarative1Rectangle);
+ return d->getPen();
+}
+
+/*!
+ \qmlproperty Gradient Rectangle::gradient
+
+ The gradient to use to fill the rectangle.
+
+ This property allows for the construction of simple vertical gradients.
+ Other gradients may by formed by adding rotation to the rectangle.
+
+ \div {class="float-left"}
+ \inlineimage declarative-rect_gradient.png
+ \enddiv
+
+ \snippet doc/src/snippets/declarative/rectangle/rectangle-gradient.qml rectangles
+ \clearfloat
+
+ If both a gradient and a color are specified, the gradient will be used.
+
+ \sa Gradient, color
+*/
+QDeclarative1Gradient *QDeclarative1Rectangle::gradient() const
+{
+ Q_D(const QDeclarative1Rectangle);
+ return d->gradient;
+}
+
+void QDeclarative1Rectangle::setGradient(QDeclarative1Gradient *gradient)
+{
+ Q_D(QDeclarative1Rectangle);
+ if (d->gradient == gradient)
+ return;
+ static int updatedSignalIdx = -1;
+ if (updatedSignalIdx < 0)
+ updatedSignalIdx = QDeclarative1Gradient::staticMetaObject.indexOfSignal("updated()");
+ if (d->doUpdateSlotIdx < 0)
+ d->doUpdateSlotIdx = QDeclarative1Rectangle::staticMetaObject.indexOfSlot("doUpdate()");
+ if (d->gradient)
+ QMetaObject::disconnect(d->gradient, updatedSignalIdx, this, d->doUpdateSlotIdx);
+ d->gradient = gradient;
+ if (d->gradient)
+ QMetaObject::connect(d->gradient, updatedSignalIdx, this, d->doUpdateSlotIdx);
+ update();
+}
+
+
+/*!
+ \qmlproperty real Rectangle::radius
+ This property holds the corner radius used to draw a rounded rectangle.
+
+ If radius is non-zero, the rectangle will be painted as a rounded rectangle, otherwise it will be
+ painted as a normal rectangle. The same radius is used by all 4 corners; there is currently
+ no way to specify different radii for different corners.
+*/
+qreal QDeclarative1Rectangle::radius() const
+{
+ Q_D(const QDeclarative1Rectangle);
+ return d->radius;
+}
+
+void QDeclarative1Rectangle::setRadius(qreal radius)
+{
+ Q_D(QDeclarative1Rectangle);
+ if (d->radius == radius)
+ return;
+
+ d->radius = radius;
+ d->rectImage = QPixmap();
+ update();
+ emit radiusChanged();
+}
+
+/*!
+ \qmlproperty color Rectangle::color
+ This property holds the color used to fill the rectangle.
+
+ The default color is white.
+
+ \div {class="float-right"}
+ \inlineimage rect-color.png
+ \enddiv
+
+ The following example shows rectangles with colors specified
+ using hexadecimal and named color notation:
+
+ \snippet doc/src/snippets/declarative/rectangle/rectangle-colors.qml rectangles
+
+ \clearfloat
+ If both a gradient and a color are specified, the gradient will be used.
+
+ \sa gradient
+*/
+QColor QDeclarative1Rectangle::color() const
+{
+ Q_D(const QDeclarative1Rectangle);
+ return d->color;
+}
+
+void QDeclarative1Rectangle::setColor(const QColor &c)
+{
+ Q_D(QDeclarative1Rectangle);
+ if (d->color == c)
+ return;
+
+ d->color = c;
+ d->rectImage = QPixmap();
+ update();
+ emit colorChanged();
+}
+
+void QDeclarative1Rectangle::generateRoundedRect()
+{
+ Q_D(QDeclarative1Rectangle);
+ if (d->rectImage.isNull()) {
+ const int pw = d->pen && d->pen->isValid() ? d->pen->width() : 0;
+ const int radius = qCeil(d->radius); //ensure odd numbered width/height so we get 1-pixel center
+
+ QString key = QLatin1String("q_") % QString::number(pw) % d->color.name() % QString::number(d->color.alpha(), 16) % QLatin1Char('_') % QString::number(radius);
+ if (d->pen && d->pen->isValid())
+ key += d->pen->color().name() % QString::number(d->pen->color().alpha(), 16);
+
+ if (!QPixmapCache::find(key, &d->rectImage)) {
+ d->rectImage = QPixmap(radius*2 + 3 + pw*2, radius*2 + 3 + pw*2);
+ d->rectImage.fill(Qt::transparent);
+ QPainter p(&(d->rectImage));
+ p.setRenderHint(QPainter::Antialiasing);
+ if (d->pen && d->pen->isValid()) {
+ QPen pn(QColor(d->pen->color()), d->pen->width());
+ p.setPen(pn);
+ } else {
+ p.setPen(Qt::NoPen);
+ }
+ p.setBrush(d->color);
+ if (pw%2)
+ p.drawRoundedRect(QRectF(qreal(pw)/2+1, qreal(pw)/2+1, d->rectImage.width()-(pw+1), d->rectImage.height()-(pw+1)), d->radius, d->radius);
+ else
+ p.drawRoundedRect(QRectF(qreal(pw)/2, qreal(pw)/2, d->rectImage.width()-pw, d->rectImage.height()-pw), d->radius, d->radius);
+
+ // end painting before inserting pixmap
+ // to pixmap cache to avoid a deep copy
+ p.end();
+ QPixmapCache::insert(key, d->rectImage);
+ }
+ }
+}
+
+void QDeclarative1Rectangle::generateBorderedRect()
+{
+ Q_D(QDeclarative1Rectangle);
+ if (d->rectImage.isNull()) {
+ const int pw = d->pen && d->pen->isValid() ? d->pen->width() : 0;
+
+ QString key = QLatin1String("q_") % QString::number(pw) % d->color.name() % QString::number(d->color.alpha(), 16);
+ if (d->pen && d->pen->isValid())
+ key += d->pen->color().name() % QString::number(d->pen->color().alpha(), 16);
+
+ if (!QPixmapCache::find(key, &d->rectImage)) {
+ // Adding 5 here makes qDrawBorderPixmap() paint correctly with smooth: true
+ // See QTBUG-7999 and QTBUG-10765 for more details.
+ d->rectImage = QPixmap(pw*2 + 5, pw*2 + 5);
+ d->rectImage.fill(Qt::transparent);
+ QPainter p(&(d->rectImage));
+ p.setRenderHint(QPainter::Antialiasing);
+ if (d->pen && d->pen->isValid()) {
+ QPen pn(QColor(d->pen->color()), d->pen->width());
+ pn.setJoinStyle(Qt::MiterJoin);
+ p.setPen(pn);
+ } else {
+ p.setPen(Qt::NoPen);
+ }
+ p.setBrush(d->color);
+ if (pw%2)
+ p.drawRect(QRectF(qreal(pw)/2+1, qreal(pw)/2+1, d->rectImage.width()-(pw+1), d->rectImage.height()-(pw+1)));
+ else
+ p.drawRect(QRectF(qreal(pw)/2, qreal(pw)/2, d->rectImage.width()-pw, d->rectImage.height()-pw));
+
+ // end painting before inserting pixmap
+ // to pixmap cache to avoid a deep copy
+ p.end();
+ QPixmapCache::insert(key, d->rectImage);
+ }
+ }
+}
+
+void QDeclarative1Rectangle::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *)
+{
+ Q_D(QDeclarative1Rectangle);
+ if (width() <= 0 || height() <= 0)
+ return;
+ if (d->radius > 0 || (d->pen && d->pen->isValid())
+ || (d->gradient && d->gradient->gradient()) ) {
+ drawRect(*p);
+ }
+ else {
+ bool oldAA = p->testRenderHint(QPainter::Antialiasing);
+ if (d->smooth)
+ p->setRenderHints(QPainter::Antialiasing, true);
+ p->fillRect(QRectF(0, 0, width(), height()), d->color);
+ if (d->smooth)
+ p->setRenderHint(QPainter::Antialiasing, oldAA);
+ }
+}
+
+void QDeclarative1Rectangle::drawRect(QPainter &p)
+{
+ Q_D(QDeclarative1Rectangle);
+ if ((d->gradient && d->gradient->gradient())
+ || d->radius > width()/2 || d->radius > height()/2
+ || width() < 3 || height() < 3) {
+ // XXX This path is still slower than the image path
+ // Image path won't work for gradients or invalid radius though
+ bool oldAA = p.testRenderHint(QPainter::Antialiasing);
+ if (d->smooth)
+ p.setRenderHint(QPainter::Antialiasing);
+ if (d->pen && d->pen->isValid()) {
+ QPen pn(QColor(d->pen->color()), d->pen->width());
+ pn.setJoinStyle(Qt::MiterJoin);
+ p.setPen(pn);
+ } else {
+ p.setPen(Qt::NoPen);
+ }
+ if (d->gradient && d->gradient->gradient())
+ p.setBrush(*d->gradient->gradient());
+ else
+ p.setBrush(d->color);
+ const int pw = d->pen && d->pen->isValid() ? d->pen->width() : 0;
+ QRectF rect;
+ if (pw%2)
+ rect = QRectF(0.5, 0.5, width()-1, height()-1);
+ else
+ rect = QRectF(0, 0, width(), height());
+ qreal radius = d->radius;
+ if (radius > width()/2 || radius > height()/2)
+ radius = qMin(width()/2, height()/2);
+ if (radius > 0.)
+ p.drawRoundedRect(rect, radius, radius);
+ else
+ p.drawRect(rect);
+ if (d->smooth)
+ p.setRenderHint(QPainter::Antialiasing, oldAA);
+ } else {
+ bool oldAA = p.testRenderHint(QPainter::Antialiasing);
+ bool oldSmooth = p.testRenderHint(QPainter::SmoothPixmapTransform);
+ if (d->smooth)
+ p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, d->smooth);
+
+ const int pw = d->pen && d->pen->isValid() ? (d->pen->width()+1)/2*2 : 0;
+
+ if (d->radius > 0)
+ generateRoundedRect();
+ else
+ generateBorderedRect();
+
+ int xOffset = (d->rectImage.width()-1)/2;
+ int yOffset = (d->rectImage.height()-1)/2;
+ Q_ASSERT(d->rectImage.width() == 2*xOffset + 1);
+ Q_ASSERT(d->rectImage.height() == 2*yOffset + 1);
+
+ // check whether we've eliminated the center completely
+ if (2*xOffset > width()+pw)
+ xOffset = (width()+pw)/2;
+ if (2*yOffset > height()+pw)
+ yOffset = (height()+pw)/2;
+
+ QMargins margins(xOffset, yOffset, xOffset, yOffset);
+ QTileRules rules(Qt::StretchTile, Qt::StretchTile);
+ //NOTE: even though our item may have qreal-based width and height, qDrawBorderPixmap only supports QRects
+ qDrawBorderPixmap(&p, QRect(-pw/2, -pw/2, width()+pw, height()+pw), margins, d->rectImage, d->rectImage.rect(), margins, rules);
+
+ if (d->smooth) {
+ p.setRenderHint(QPainter::Antialiasing, oldAA);
+ p.setRenderHint(QPainter::SmoothPixmapTransform, oldSmooth);
+ }
+ }
+}
+
+/*!
+ \qmlproperty bool Rectangle::smooth
+
+ Set this property if you want the item to be smoothly scaled or
+ transformed. Smooth filtering gives better visual quality, but is slower. If
+ the item is displayed at its natural size, this property has no visual or
+ performance effect.
+
+ \note Generally scaling artifacts are only visible if the item is stationary on
+ the screen. A common pattern when animating an item is to disable smooth
+ filtering at the beginning of the animation and reenable it at the conclusion.
+
+ \image rect-smooth.png
+ On this image, smooth is turned off on the top half and on on the bottom half.
+*/
+
+QRectF QDeclarative1Rectangle::boundingRect() const
+{
+ Q_D(const QDeclarative1Rectangle);
+ return QRectF(-d->paintmargin, -d->paintmargin, d->width()+d->paintmargin*2, d->height()+d->paintmargin*2);
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/graphicsitems/qdeclarativerectangle_p.h b/src/qtquick1/graphicsitems/qdeclarativerectangle_p.h
new file mode 100644
index 0000000000..862799faa2
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativerectangle_p.h
@@ -0,0 +1,188 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVERECT_H
+#define QDECLARATIVERECT_H
+
+#include "qdeclarativeitem.h"
+
+#include <QtGui/qbrush.h>
+
+#include <QtDeclarative/private/qdeclarativeglobal_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarative1Pen : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int width READ width WRITE setWidth NOTIFY penChanged)
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY penChanged)
+public:
+ QDeclarative1Pen(QObject *parent=0)
+ : QObject(parent), _width(1), _color("#000000"), _valid(false)
+ {}
+
+ int width() const { return _width; }
+ void setWidth(int w);
+
+ QColor color() const { return _color; }
+ void setColor(const QColor &c);
+
+ bool isValid() { return _valid; }
+
+Q_SIGNALS:
+ void penChanged();
+
+private:
+ int _width;
+ QColor _color;
+ bool _valid;
+};
+
+class Q_AUTOTEST_EXPORT QDeclarative1GradientStop : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal position READ position WRITE setPosition)
+ Q_PROPERTY(QColor color READ color WRITE setColor)
+
+public:
+ QDeclarative1GradientStop(QObject *parent=0) : QObject(parent) {}
+
+ qreal position() const { return m_position; }
+ void setPosition(qreal position) { m_position = position; updateGradient(); }
+
+ QColor color() const { return m_color; }
+ void setColor(const QColor &color) { m_color = color; updateGradient(); }
+
+private:
+ void updateGradient();
+
+private:
+ qreal m_position;
+ QColor m_color;
+};
+
+class Q_AUTOTEST_EXPORT QDeclarative1Gradient : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QDeclarativeListProperty<QDeclarative1GradientStop> stops READ stops)
+ Q_CLASSINFO("DefaultProperty", "stops")
+
+public:
+ QDeclarative1Gradient(QObject *parent=0) : QObject(parent), m_gradient(0) {}
+ ~QDeclarative1Gradient() { delete m_gradient; }
+
+ QDeclarativeListProperty<QDeclarative1GradientStop> stops() { return QDeclarativeListProperty<QDeclarative1GradientStop>(this, m_stops); }
+
+ const QGradient *gradient() const;
+
+Q_SIGNALS:
+ void updated();
+
+private:
+ void doUpdate();
+
+private:
+ QList<QDeclarative1GradientStop *> m_stops;
+ mutable QGradient *m_gradient;
+ friend class QDeclarative1GradientStop;
+};
+
+class QDeclarative1RectanglePrivate;
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarative1Rectangle : public QDeclarativeItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
+ Q_PROPERTY(QDeclarative1Gradient *gradient READ gradient WRITE setGradient)
+ Q_PROPERTY(QDeclarative1Pen * border READ border CONSTANT)
+ Q_PROPERTY(qreal radius READ radius WRITE setRadius NOTIFY radiusChanged)
+public:
+ QDeclarative1Rectangle(QDeclarativeItem *parent=0);
+
+ QColor color() const;
+ void setColor(const QColor &);
+
+ QDeclarative1Pen *border();
+
+ QDeclarative1Gradient *gradient() const;
+ void setGradient(QDeclarative1Gradient *gradient);
+
+ qreal radius() const;
+ void setRadius(qreal radius);
+
+ QRectF boundingRect() const;
+
+ void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
+
+Q_SIGNALS:
+ void colorChanged();
+ void radiusChanged();
+
+private Q_SLOTS:
+ void doUpdate();
+
+private:
+ void generateRoundedRect();
+ void generateBorderedRect();
+ void drawRect(QPainter &painter);
+
+private:
+ Q_DISABLE_COPY(QDeclarative1Rectangle)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarative1Rectangle)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1Pen)
+QML_DECLARE_TYPE(QDeclarative1GradientStop)
+QML_DECLARE_TYPE(QDeclarative1Gradient)
+QML_DECLARE_TYPE(QDeclarative1Rectangle)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVERECT_H
diff --git a/src/qtquick1/graphicsitems/qdeclarativerectangle_p_p.h b/src/qtquick1/graphicsitems/qdeclarativerectangle_p_p.h
new file mode 100644
index 0000000000..4437f6be75
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativerectangle_p_p.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVERECT_P_H
+#define QDECLARATIVERECT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qdeclarativeitem_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarative1Gradient;
+class QDeclarative1Rectangle;
+class QDeclarative1RectanglePrivate : public QDeclarativeItemPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1Rectangle)
+
+public:
+ QDeclarative1RectanglePrivate() :
+ color(Qt::white), gradient(0), pen(0), radius(0), paintmargin(0)
+ {
+ QGraphicsItemPrivate::flags = QGraphicsItemPrivate::flags & ~QGraphicsItem::ItemHasNoContents;
+ }
+
+ ~QDeclarative1RectanglePrivate()
+ {
+ delete pen;
+ }
+
+ QColor color;
+ QDeclarative1Gradient *gradient;
+ QDeclarative1Pen *pen;
+ qreal radius;
+ qreal paintmargin;
+ QPixmap rectImage;
+ static int doUpdateSlotIdx;
+
+ QDeclarative1Pen *getPen() {
+ if (!pen) {
+ Q_Q(QDeclarative1Rectangle);
+ pen = new QDeclarative1Pen;
+ static int penChangedSignalIdx = -1;
+ if (penChangedSignalIdx < 0)
+ penChangedSignalIdx = QDeclarative1Pen::staticMetaObject.indexOfSignal("penChanged()");
+ if (doUpdateSlotIdx < 0)
+ doUpdateSlotIdx = QDeclarative1Rectangle::staticMetaObject.indexOfSlot("doUpdate()");
+ QMetaObject::connect(pen, penChangedSignalIdx, q, doUpdateSlotIdx);
+ }
+ return pen;
+ }
+
+ void setPaintMargin(qreal margin)
+ {
+ Q_Q(QDeclarative1Rectangle);
+ if (margin == paintmargin)
+ return;
+ q->prepareGeometryChange();
+ paintmargin = margin;
+ }
+};
+
+QT_END_NAMESPACE
+
+#endif // QDECLARATIVERECT_P_H
diff --git a/src/qtquick1/graphicsitems/qdeclarativerepeater.cpp b/src/qtquick1/graphicsitems/qdeclarativerepeater.cpp
new file mode 100644
index 0000000000..cebff875e8
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativerepeater.cpp
@@ -0,0 +1,449 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativerepeater_p.h"
+#include "QtQuick1/private/qdeclarativerepeater_p_p.h"
+
+#include "QtQuick1/private/qdeclarativevisualitemmodel_p.h"
+#include <QtDeclarative/private/qdeclarativeglobal_p.h>
+#include <QtQuick1/private/qdeclarativelistaccessor_p.h>
+
+QT_BEGIN_NAMESPACE
+
+
+QDeclarative1RepeaterPrivate::QDeclarative1RepeaterPrivate()
+: model(0), ownModel(false)
+{
+}
+
+QDeclarative1RepeaterPrivate::~QDeclarative1RepeaterPrivate()
+{
+ if (ownModel)
+ delete model;
+}
+
+/*!
+ \qmlclass Repeater QDeclarative1Repeater
+ \ingroup qml-utility-elements
+ \since 4.7
+ \inherits Item
+
+ \brief The Repeater element allows you to repeat an Item-based component using a model.
+
+ The Repeater element is used to create a large number of
+ similar items. Like other view elements, a Repeater has a \l model and a \l delegate:
+ for each entry in the model, the delegate is instantiated
+ in a context seeded with data from the model. A Repeater item is usually
+ enclosed in a positioner element such as \l Row or \l Column to visually
+ position the multiple delegate items created by the Repeater.
+
+ The following Repeater creates three instances of a \l Rectangle item within
+ a \l Row:
+
+ \snippet doc/src/snippets/declarative/repeaters/repeater.qml import
+ \codeline
+ \snippet doc/src/snippets/declarative/repeaters/repeater.qml simple
+
+ \image repeater-simple.png
+
+ A Repeater's \l model can be any of the supported \l {qmlmodels}{data models}.
+ Additionally, like delegates for other views, a Repeater delegate can access
+ its index within the repeater, as well as the model data relevant to the
+ delegate. See the \l delegate property documentation for details.
+
+ Items instantiated by the Repeater are inserted, in order, as
+ children of the Repeater's parent. The insertion starts immediately after
+ the repeater's position in its parent stacking list. This allows
+ a Repeater to be used inside a layout. For example, the following Repeater's
+ items are stacked between a red rectangle and a blue rectangle:
+
+ \snippet doc/src/snippets/declarative/repeaters/repeater.qml layout
+
+ \image repeater.png
+
+
+ \note A Repeater item owns all items it instantiates. Removing or dynamically destroying
+ an item created by a Repeater results in unpredictable behavior.
+
+
+ \section2 Considerations when using Repeater
+
+ The Repeater element creates all of its delegate items when the repeater is first
+ created. This can be inefficient if there are a large number of delegate items and
+ not all of the items are required to be visible at the same time. If this is the case,
+ consider using other view elements like ListView (which only creates delegate items
+ when they are scrolled into view) or use the \l {Dynamic Object Creation} methods to
+ create items as they are required.
+
+ Also, note that Repeater is \l {Item}-based, and can only repeat \l {Item}-derived objects.
+ For example, it cannot be used to repeat QtObjects:
+ \badcode
+ Item {
+ //XXX does not work! Can't repeat QtObject as it doesn't derive from Item.
+ Repeater {
+ model: 10
+ QtObject {}
+ }
+ }
+ \endcode
+ */
+
+/*!
+ \qmlsignal Repeater::onItemAdded(int index, Item item)
+ \since Quick 1.1
+
+ This handler is called when an item is added to the repeater. The \a index
+ parameter holds the index at which the item has been inserted within the
+ repeater, and the \a item parameter holds the \l Item that has been added.
+*/
+
+/*!
+ \qmlsignal Repeater::onItemRemoved(int index, Item item)
+ \since Quick 1.1
+
+ This handler is called when an item is removed from the repeater. The \a index
+ parameter holds the index at which the item was removed from the repeater,
+ and the \a item parameter holds the \l Item that was removed.
+
+ Do not keep a reference to \a item if it was created by this repeater, as
+ in these cases it will be deleted shortly after the handler is called.
+*/
+
+QDeclarative1Repeater::QDeclarative1Repeater(QDeclarativeItem *parent)
+ : QDeclarativeItem(*(new QDeclarative1RepeaterPrivate), parent)
+{
+}
+
+QDeclarative1Repeater::~QDeclarative1Repeater()
+{
+}
+
+/*!
+ \qmlproperty any Repeater::model
+
+ The model providing data for the repeater.
+
+ This property can be set to any of the supported \l {qmlmodels}{data models}:
+
+ \list
+ \o A number that indicates the number of delegates to be created by the repeater
+ \o A model (e.g. a ListModel item, or a QAbstractItemModel subclass)
+ \o A string list
+ \o An object list
+ \endlist
+
+ The type of model affects the properties that are exposed to the \l delegate.
+
+ \sa {qmlmodels}{Data Models}
+*/
+QVariant QDeclarative1Repeater::model() const
+{
+ Q_D(const QDeclarative1Repeater);
+ return d->dataSource;
+}
+
+void QDeclarative1Repeater::setModel(const QVariant &model)
+{
+ Q_D(QDeclarative1Repeater);
+ if (d->dataSource == model)
+ return;
+
+ clear();
+ if (d->model) {
+ disconnect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
+ disconnect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
+ disconnect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int)));
+ disconnect(d->model, SIGNAL(modelReset()), this, SLOT(modelReset()));
+ /*
+ disconnect(d->model, SIGNAL(createdItem(int,QDeclarativeItem*)), this, SLOT(createdItem(int,QDeclarativeItem*)));
+ disconnect(d->model, SIGNAL(destroyingItem(QDeclarativeItem*)), this, SLOT(destroyingItem(QDeclarativeItem*)));
+ */
+ }
+ d->dataSource = model;
+ QObject *object = qvariant_cast<QObject*>(model);
+ QDeclarative1VisualModel *vim = 0;
+ if (object && (vim = qobject_cast<QDeclarative1VisualModel *>(object))) {
+ if (d->ownModel) {
+ delete d->model;
+ d->ownModel = false;
+ }
+ d->model = vim;
+ } else {
+ if (!d->ownModel) {
+ d->model = new QDeclarative1VisualDataModel(qmlContext(this), this);
+ d->ownModel = true;
+ }
+ if (QDeclarative1VisualDataModel *dataModel = qobject_cast<QDeclarative1VisualDataModel*>(d->model))
+ dataModel->setModel(model);
+ }
+ if (d->model) {
+ connect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
+ connect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
+ connect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int)));
+ connect(d->model, SIGNAL(modelReset()), this, SLOT(modelReset()));
+ /*
+ connect(d->model, SIGNAL(createdItem(int,QDeclarativeItem*)), this, SLOT(createdItem(int,QDeclarativeItem*)));
+ connect(d->model, SIGNAL(destroyingItem(QDeclarativeItem*)), this, SLOT(destroyingItem(QDeclarativeItem*)));
+ */
+ regenerate();
+ }
+ emit modelChanged();
+ emit countChanged();
+}
+
+/*!
+ \qmlproperty Component Repeater::delegate
+ \default
+
+ The delegate provides a template defining each item instantiated by the repeater.
+
+ Delegates are exposed to a read-only \c index property that indicates the index
+ of the delegate within the repeater. For example, the following \l Text delegate
+ displays the index of each repeated item:
+
+ \table
+ \row
+ \o \snippet doc/src/snippets/declarative/repeaters/repeater.qml index
+ \o \image repeater-index.png
+ \endtable
+
+ If the \l model is a \l{QStringList-based model}{string list} or
+ \l{QObjectList-based model}{object list}, the delegate is also exposed to
+ a read-only \c modelData property that holds the string or object data. For
+ example:
+
+ \table
+ \row
+ \o \snippet doc/src/snippets/declarative/repeaters/repeater.qml modeldata
+ \o \image repeater-modeldata.png
+ \endtable
+
+ If the \l model is a model object (such as a \l ListModel) the delegate
+ can access all model roles as named properties, in the same way that delegates
+ do for view classes like ListView.
+
+ \sa {QML Data Models}
+ */
+QDeclarativeComponent *QDeclarative1Repeater::delegate() const
+{
+ Q_D(const QDeclarative1Repeater);
+ if (d->model) {
+ if (QDeclarative1VisualDataModel *dataModel = qobject_cast<QDeclarative1VisualDataModel*>(d->model))
+ return dataModel->delegate();
+ }
+
+ return 0;
+}
+
+void QDeclarative1Repeater::setDelegate(QDeclarativeComponent *delegate)
+{
+ Q_D(QDeclarative1Repeater);
+ if (QDeclarative1VisualDataModel *dataModel = qobject_cast<QDeclarative1VisualDataModel*>(d->model))
+ if (delegate == dataModel->delegate())
+ return;
+
+ if (!d->ownModel) {
+ d->model = new QDeclarative1VisualDataModel(qmlContext(this));
+ d->ownModel = true;
+ }
+ if (QDeclarative1VisualDataModel *dataModel = qobject_cast<QDeclarative1VisualDataModel*>(d->model)) {
+ dataModel->setDelegate(delegate);
+ regenerate();
+ emit delegateChanged();
+ }
+}
+
+/*!
+ \qmlproperty int Repeater::count
+
+ This property holds the number of items in the repeater.
+*/
+int QDeclarative1Repeater::count() const
+{
+ Q_D(const QDeclarative1Repeater);
+ if (d->model)
+ return d->model->count();
+ return 0;
+}
+
+/*!
+ \qmlmethod Item Repeater::itemAt(index)
+ \since Quick 1.1
+
+ Returns the \l Item that has been created at the given \a index, or \c null
+ if no item exists at \a index.
+*/
+QDeclarativeItem *QDeclarative1Repeater::itemAt(int index) const
+{
+ Q_D(const QDeclarative1Repeater);
+ if (index >= 0 && index < d->deletables.count())
+ return d->deletables[index];
+ return 0;
+
+}
+
+void QDeclarative1Repeater::componentComplete()
+{
+ QDeclarativeItem::componentComplete();
+ regenerate();
+}
+
+QVariant QDeclarative1Repeater::itemChange(GraphicsItemChange change,
+ const QVariant &value)
+{
+ QVariant rv = QDeclarativeItem::itemChange(change, value);
+ if (change == ItemParentHasChanged) {
+ regenerate();
+ }
+
+ return rv;
+}
+
+void QDeclarative1Repeater::clear()
+{
+ Q_D(QDeclarative1Repeater);
+ bool complete = isComponentComplete();
+
+ if (d->model) {
+ while (d->deletables.count() > 0) {
+ QDeclarativeItem *item = d->deletables.takeLast();
+ if (complete)
+ emit itemRemoved(d->deletables.count()-1, item);
+ d->model->release(item);
+ }
+ }
+ d->deletables.clear();
+}
+
+void QDeclarative1Repeater::regenerate()
+{
+ Q_D(QDeclarative1Repeater);
+ if (!isComponentComplete())
+ return;
+
+ clear();
+
+ if (!d->model || !d->model->count() || !d->model->isValid() || !parentItem() || !isComponentComplete())
+ return;
+
+ for (int ii = 0; ii < count(); ++ii) {
+ QDeclarativeItem *item = d->model->item(ii);
+ if (item) {
+ QDeclarative_setParent_noEvent(item, parentItem());
+ item->setParentItem(parentItem());
+ item->stackBefore(this);
+ d->deletables << item;
+ emit itemAdded(ii, item);
+ }
+ }
+}
+
+void QDeclarative1Repeater::itemsInserted(int index, int count)
+{
+ Q_D(QDeclarative1Repeater);
+ if (!isComponentComplete())
+ return;
+ for (int i = 0; i < count; ++i) {
+ int modelIndex = index + i;
+ QDeclarativeItem *item = d->model->item(modelIndex);
+ if (item) {
+ QDeclarative_setParent_noEvent(item, parentItem());
+ item->setParentItem(parentItem());
+ if (modelIndex < d->deletables.count())
+ item->stackBefore(d->deletables.at(modelIndex));
+ else
+ item->stackBefore(this);
+ d->deletables.insert(modelIndex, item);
+ emit itemAdded(modelIndex, item);
+ }
+ }
+ emit countChanged();
+}
+
+void QDeclarative1Repeater::itemsRemoved(int index, int count)
+{
+ Q_D(QDeclarative1Repeater);
+ if (!isComponentComplete() || count <= 0)
+ return;
+ while (count--) {
+ QDeclarativeItem *item = d->deletables.takeAt(index);
+ emit itemRemoved(index, item);
+ if (item)
+ d->model->release(item);
+ else
+ break;
+ }
+ emit countChanged();
+}
+
+void QDeclarative1Repeater::itemsMoved(int from, int to, int count)
+{
+ Q_D(QDeclarative1Repeater);
+ if (!isComponentComplete() || count <= 0)
+ return;
+ if (from + count > d->deletables.count()) {
+ regenerate();
+ return;
+ }
+ QList<QDeclarativeItem*> removed;
+ int removedCount = count;
+ while (removedCount--)
+ removed << d->deletables.takeAt(from);
+ for (int i = 0; i < count; ++i)
+ d->deletables.insert(to + i, removed.at(i));
+ d->deletables.last()->stackBefore(this);
+ for (int i = d->model->count()-1; i > 0; --i) {
+ QDeclarativeItem *item = d->deletables.at(i-1);
+ item->stackBefore(d->deletables.at(i));
+ }
+}
+
+void QDeclarative1Repeater::modelReset()
+{
+ if (!isComponentComplete())
+ return;
+ regenerate();
+ emit countChanged();
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/graphicsitems/qdeclarativerepeater_p.h b/src/qtquick1/graphicsitems/qdeclarativerepeater_p.h
new file mode 100644
index 0000000000..6176cd1d14
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativerepeater_p.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEREPEATER_H
+#define QDECLARATIVEREPEATER_H
+
+#include "qdeclarativeitem.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarative1RepeaterPrivate;
+class Q_AUTOTEST_EXPORT QDeclarative1Repeater : public QDeclarativeItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged)
+ Q_PROPERTY(QDeclarativeComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+ Q_CLASSINFO("DefaultProperty", "delegate")
+
+public:
+ QDeclarative1Repeater(QDeclarativeItem *parent=0);
+ virtual ~QDeclarative1Repeater();
+
+ QVariant model() const;
+ void setModel(const QVariant &);
+
+ QDeclarativeComponent *delegate() const;
+ void setDelegate(QDeclarativeComponent *);
+
+ int count() const;
+
+ Q_INVOKABLE Q_REVISION(1) QDeclarativeItem *itemAt(int index) const;
+
+Q_SIGNALS:
+ void modelChanged();
+ void delegateChanged();
+ void countChanged();
+
+ Q_REVISION(1) void itemAdded(int index, QDeclarativeItem *item);
+ Q_REVISION(1) void itemRemoved(int index, QDeclarativeItem *item);
+
+private:
+ void clear();
+ void regenerate();
+
+protected:
+ virtual void componentComplete();
+ QVariant itemChange(GraphicsItemChange change, const QVariant &value);
+
+private Q_SLOTS:
+ void itemsInserted(int,int);
+ void itemsRemoved(int,int);
+ void itemsMoved(int,int,int);
+ void modelReset();
+
+private:
+ Q_DISABLE_COPY(QDeclarative1Repeater)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarative1Repeater)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1Repeater)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEREPEATER_H
diff --git a/src/qtquick1/graphicsitems/qdeclarativerepeater_p_p.h b/src/qtquick1/graphicsitems/qdeclarativerepeater_p_p.h
new file mode 100644
index 0000000000..e806bd4cb5
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativerepeater_p_p.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEREPEATER_P_H
+#define QDECLARATIVEREPEATER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qdeclarativerepeater_p.h"
+
+#include "private/qdeclarativeitem_p.h"
+
+#include <QPointer>
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeContext;
+class QDeclarative1VisualModel;
+class QDeclarative1RepeaterPrivate : public QDeclarativeItemPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1Repeater)
+
+public:
+ QDeclarative1RepeaterPrivate();
+ ~QDeclarative1RepeaterPrivate();
+
+ QDeclarative1VisualModel *model;
+ QVariant dataSource;
+ bool ownModel;
+
+ QList<QPointer<QDeclarativeItem> > deletables;
+};
+
+QT_END_NAMESPACE
+#endif // QDECLARATIVEREPEATER_P_H
diff --git a/src/qtquick1/graphicsitems/qdeclarativescalegrid.cpp b/src/qtquick1/graphicsitems/qdeclarativescalegrid.cpp
new file mode 100644
index 0000000000..83a94ec9de
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativescalegrid.cpp
@@ -0,0 +1,217 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativescalegrid_p_p.h"
+
+#include <QtDeclarative/qdeclarative.h>
+
+#include <QBuffer>
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+
+
+/*!
+ \internal
+ \class QDeclarative1ScaleGrid
+ \brief The QDeclarative1ScaleGrid class allows you to specify a 3x3 grid to use in scaling an image.
+*/
+
+QDeclarative1ScaleGrid::QDeclarative1ScaleGrid(QObject *parent) : QObject(parent), _left(0), _top(0), _right(0), _bottom(0)
+{
+}
+
+QDeclarative1ScaleGrid::~QDeclarative1ScaleGrid()
+{
+}
+
+bool QDeclarative1ScaleGrid::isNull() const
+{
+ return !_left && !_top && !_right && !_bottom;
+}
+
+void QDeclarative1ScaleGrid::setLeft(int pos)
+{
+ if (_left != pos) {
+ _left = pos;
+ emit borderChanged();
+ }
+}
+
+void QDeclarative1ScaleGrid::setTop(int pos)
+{
+ if (_top != pos) {
+ _top = pos;
+ emit borderChanged();
+ }
+}
+
+void QDeclarative1ScaleGrid::setRight(int pos)
+{
+ if (_right != pos) {
+ _right = pos;
+ emit borderChanged();
+ }
+}
+
+void QDeclarative1ScaleGrid::setBottom(int pos)
+{
+ if (_bottom != pos) {
+ _bottom = pos;
+ emit borderChanged();
+ }
+}
+
+QDeclarative1GridScaledImage::QDeclarative1GridScaledImage()
+: _l(-1), _r(-1), _t(-1), _b(-1),
+ _h(QDeclarative1BorderImage::Stretch), _v(QDeclarative1BorderImage::Stretch)
+{
+}
+
+QDeclarative1GridScaledImage::QDeclarative1GridScaledImage(const QDeclarative1GridScaledImage &o)
+: _l(o._l), _r(o._r), _t(o._t), _b(o._b), _h(o._h), _v(o._v), _pix(o._pix)
+{
+}
+
+QDeclarative1GridScaledImage &QDeclarative1GridScaledImage::operator=(const QDeclarative1GridScaledImage &o)
+{
+ _l = o._l;
+ _r = o._r;
+ _t = o._t;
+ _b = o._b;
+ _h = o._h;
+ _v = o._v;
+ _pix = o._pix;
+ return *this;
+}
+
+QDeclarative1GridScaledImage::QDeclarative1GridScaledImage(QIODevice *data)
+: _l(-1), _r(-1), _t(-1), _b(-1), _h(QDeclarative1BorderImage::Stretch), _v(QDeclarative1BorderImage::Stretch)
+{
+ int l = -1;
+ int r = -1;
+ int t = -1;
+ int b = -1;
+ QString imgFile;
+
+ QByteArray raw;
+ while(raw = data->readLine(), !raw.isEmpty()) {
+ QString line = QString::fromUtf8(raw.trimmed());
+ if (line.isEmpty() || line.startsWith(QLatin1Char('#')))
+ continue;
+
+ int colonId = line.indexOf(QLatin1Char(':'));
+ if (colonId <= 0)
+ return;
+ QStringList list;
+ list.append(line.left(colonId).trimmed());
+ list.append(line.mid(colonId+1).trimmed());
+
+ if (list[0] == QLatin1String("border.left"))
+ l = list[1].toInt();
+ else if (list[0] == QLatin1String("border.right"))
+ r = list[1].toInt();
+ else if (list[0] == QLatin1String("border.top"))
+ t = list[1].toInt();
+ else if (list[0] == QLatin1String("border.bottom"))
+ b = list[1].toInt();
+ else if (list[0] == QLatin1String("source"))
+ imgFile = list[1];
+ else if (list[0] == QLatin1String("horizontalTileRule"))
+ _h = stringToRule(list[1]);
+ else if (list[0] == QLatin1String("verticalTileRule"))
+ _v = stringToRule(list[1]);
+ }
+
+ if (l < 0 || r < 0 || t < 0 || b < 0 || imgFile.isEmpty())
+ return;
+
+ _l = l; _r = r; _t = t; _b = b;
+
+ _pix = imgFile;
+}
+
+QDeclarative1BorderImage::TileMode QDeclarative1GridScaledImage::stringToRule(const QString &s)
+{
+ if (s == QLatin1String("Stretch"))
+ return QDeclarative1BorderImage::Stretch;
+ if (s == QLatin1String("Repeat"))
+ return QDeclarative1BorderImage::Repeat;
+ if (s == QLatin1String("Round"))
+ return QDeclarative1BorderImage::Round;
+
+ qWarning("QDeclarative1GridScaledImage: Invalid tile rule specified. Using Stretch.");
+ return QDeclarative1BorderImage::Stretch;
+}
+
+bool QDeclarative1GridScaledImage::isValid() const
+{
+ return _l >= 0;
+}
+
+int QDeclarative1GridScaledImage::gridLeft() const
+{
+ return _l;
+}
+
+int QDeclarative1GridScaledImage::gridRight() const
+{
+ return _r;
+}
+
+int QDeclarative1GridScaledImage::gridTop() const
+{
+ return _t;
+}
+
+int QDeclarative1GridScaledImage::gridBottom() const
+{
+ return _b;
+}
+
+QString QDeclarative1GridScaledImage::pixmapUrl() const
+{
+ return _pix;
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/graphicsitems/qdeclarativescalegrid_p_p.h b/src/qtquick1/graphicsitems/qdeclarativescalegrid_p_p.h
new file mode 100644
index 0000000000..5a1c298a74
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativescalegrid_p_p.h
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVESCALEGRID_H
+#define QDECLARATIVESCALEGRID_H
+
+#include <QtDeclarative/qdeclarative.h>
+
+#include <QtCore/QString>
+#include <QtCore/QObject>
+
+#include <QtQuick1/private/qdeclarativeborderimage_p.h>
+#include <QtQuick1/private/qdeclarativepixmapcache_p.h>
+#include <QtDeclarative/private/qdeclarativeglobal_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarative1ScaleGrid : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(TileRule)
+
+ Q_PROPERTY(int left READ left WRITE setLeft NOTIFY borderChanged)
+ Q_PROPERTY(int top READ top WRITE setTop NOTIFY borderChanged)
+ Q_PROPERTY(int right READ right WRITE setRight NOTIFY borderChanged)
+ Q_PROPERTY(int bottom READ bottom WRITE setBottom NOTIFY borderChanged)
+
+public:
+ QDeclarative1ScaleGrid(QObject *parent=0);
+ ~QDeclarative1ScaleGrid();
+
+ bool isNull() const;
+
+ int left() const { return _left; }
+ void setLeft(int);
+
+ int top() const { return _top; }
+ void setTop(int);
+
+ int right() const { return _right; }
+ void setRight(int);
+
+ int bottom() const { return _bottom; }
+ void setBottom(int);
+
+Q_SIGNALS:
+ void borderChanged();
+
+private:
+ int _left;
+ int _top;
+ int _right;
+ int _bottom;
+};
+
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarative1GridScaledImage
+{
+public:
+ QDeclarative1GridScaledImage();
+ QDeclarative1GridScaledImage(const QDeclarative1GridScaledImage &);
+ QDeclarative1GridScaledImage(QIODevice*);
+ QDeclarative1GridScaledImage &operator=(const QDeclarative1GridScaledImage &);
+ bool isValid() const;
+ int gridLeft() const;
+ int gridRight() const;
+ int gridTop() const;
+ int gridBottom() const;
+ QDeclarative1BorderImage::TileMode horizontalTileRule() const { return _h; }
+ QDeclarative1BorderImage::TileMode verticalTileRule() const { return _v; }
+
+ QString pixmapUrl() const;
+
+private:
+ static QDeclarative1BorderImage::TileMode stringToRule(const QString &);
+
+private:
+ int _l;
+ int _r;
+ int _t;
+ int _b;
+ QDeclarative1BorderImage::TileMode _h;
+ QDeclarative1BorderImage::TileMode _v;
+ QString _pix;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1ScaleGrid)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVESCALEGRID_H
diff --git a/src/qtquick1/graphicsitems/qdeclarativetext.cpp b/src/qtquick1/graphicsitems/qdeclarativetext.cpp
new file mode 100644
index 0000000000..8a497c271e
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativetext.cpp
@@ -0,0 +1,1645 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativetext_p.h"
+#include "QtQuick1/private/qdeclarativetext_p_p.h"
+#include "QtQuick1/private/qdeclarativestyledtext_p.h"
+#include <QtDeclarative/qdeclarativeinfo.h>
+#include "QtQuick1/private/qdeclarativepixmapcache_p.h"
+
+#include <QSet>
+#include <QTextLayout>
+#include <QTextLine>
+#include <QTextDocument>
+#include <QGraphicsSceneMouseEvent>
+#include <QPainter>
+#include <QAbstractTextDocumentLayout>
+#include <qmath.h>
+#include <limits.h>
+
+QT_BEGIN_NAMESPACE
+
+
+
+extern Q_GUI_EXPORT bool qt_applefontsmoothing_enabled;
+
+class QTextDocumentWithImageResources_1 : public QTextDocument {
+ Q_OBJECT
+
+public:
+ QTextDocumentWithImageResources_1(QDeclarative1Text *parent);
+ virtual ~QTextDocumentWithImageResources_1();
+
+ void setText(const QString &);
+ int resourcesLoading() const { return outstanding; }
+
+protected:
+ QVariant loadResource(int type, const QUrl &name);
+
+private slots:
+ void requestFinished();
+
+private:
+ QHash<QUrl, QDeclarative1Pixmap *> m_resources;
+
+ int outstanding;
+ static QSet<QUrl> errors;
+};
+
+
+QTextDocumentWithImageResources_1::QTextDocumentWithImageResources_1(QDeclarative1Text *parent)
+: QTextDocument(parent), outstanding(0)
+{
+}
+
+QTextDocumentWithImageResources_1::~QTextDocumentWithImageResources_1()
+{
+ if (!m_resources.isEmpty())
+ qDeleteAll(m_resources);
+}
+
+QVariant QTextDocumentWithImageResources_1::loadResource(int type, const QUrl &name)
+{
+ QDeclarativeContext *context = qmlContext(parent());
+ QUrl url = context->resolvedUrl(name);
+
+ if (type == QTextDocument::ImageResource) {
+ QHash<QUrl, QDeclarative1Pixmap *>::Iterator iter = m_resources.find(url);
+
+ if (iter == m_resources.end()) {
+ QDeclarative1Pixmap *p = new QDeclarative1Pixmap(context->engine(), url);
+ iter = m_resources.insert(name, p);
+
+ if (p->isLoading()) {
+ p->connectFinished(this, SLOT(requestFinished()));
+ outstanding++;
+ }
+ }
+
+ QDeclarative1Pixmap *p = *iter;
+ if (p->isReady()) {
+ return p->pixmap();
+ } else if (p->isError()) {
+ if (!errors.contains(url)) {
+ errors.insert(url);
+ qmlInfo(parent()) << p->error();
+ }
+ }
+ }
+
+ return QTextDocument::loadResource(type,url); // The *resolved* URL
+}
+
+void QTextDocumentWithImageResources_1::requestFinished()
+{
+ outstanding--;
+ if (outstanding == 0) {
+ QDeclarative1Text *textItem = static_cast<QDeclarative1Text*>(parent());
+ QString text = textItem->text();
+#ifndef QT_NO_TEXTHTMLPARSER
+ setHtml(text);
+#else
+ setPlainText(text);
+#endif
+ QDeclarative1TextPrivate *d = QDeclarative1TextPrivate::get(textItem);
+ d->updateLayout();
+ }
+}
+
+void QTextDocumentWithImageResources_1::setText(const QString &text)
+{
+ if (!m_resources.isEmpty()) {
+ qDeleteAll(m_resources);
+ m_resources.clear();
+ outstanding = 0;
+ }
+
+#ifndef QT_NO_TEXTHTMLPARSER
+ setHtml(text);
+#else
+ setPlainText(text);
+#endif
+}
+
+QSet<QUrl> QTextDocumentWithImageResources_1::errors;
+
+QDeclarative1TextPrivate::~QDeclarative1TextPrivate()
+{
+}
+
+DEFINE_BOOL_CONFIG_OPTION(enableImageCache, QML_ENABLE_TEXT_IMAGE_CACHE);
+
+QString QDeclarative1TextPrivate::elideChar = QString(0x2026);
+
+QDeclarative1TextPrivate::QDeclarative1TextPrivate()
+: color((QRgb)0), style(QDeclarative1Text::Normal), hAlign(QDeclarative1Text::AlignLeft),
+ vAlign(QDeclarative1Text::AlignTop), elideMode(QDeclarative1Text::ElideNone),
+ format(QDeclarative1Text::AutoText), wrapMode(QDeclarative1Text::NoWrap), lineHeight(1),
+ lineHeightMode(QDeclarative1Text::ProportionalHeight), lineCount(1), truncated(false), maximumLineCount(INT_MAX),
+ maximumLineCountValid(false), imageCacheDirty(true), updateOnComponentComplete(true), richText(false), singleline(false),
+ cacheAllTextAsImage(true), internalWidthUpdate(false), requireImplicitWidth(false), hAlignImplicit(true),
+ rightToLeftText(false), layoutTextElided(false), naturalWidth(0), doc(0)
+{
+ cacheAllTextAsImage = enableImageCache();
+ QGraphicsItemPrivate::acceptedMouseButtons = Qt::LeftButton;
+ QGraphicsItemPrivate::flags = QGraphicsItemPrivate::flags & ~QGraphicsItem::ItemHasNoContents;
+}
+
+qreal QDeclarative1TextPrivate::implicitWidth() const
+{
+ if (!requireImplicitWidth) {
+ // We don't calculate implicitWidth unless it is required.
+ // We need to force a size update now to ensure implicitWidth is calculated
+ QDeclarative1TextPrivate *me = const_cast<QDeclarative1TextPrivate*>(this);
+ me->requireImplicitWidth = true;
+ me->updateSize();
+ }
+ return mImplicitWidth;
+}
+
+void QDeclarative1TextPrivate::updateLayout()
+{
+ Q_Q(QDeclarative1Text);
+ if (!q->isComponentComplete()) {
+ updateOnComponentComplete = true;
+ return;
+ }
+
+ layoutTextElided = false;
+ // Setup instance of QTextLayout for all cases other than richtext
+ if (!richText) {
+ layout.clearLayout();
+ layout.setFont(font);
+ if (format != QDeclarative1Text::StyledText) {
+ QString tmp = text;
+ tmp.replace(QLatin1Char('\n'), QChar::LineSeparator);
+ singleline = !tmp.contains(QChar::LineSeparator);
+ if (singleline && !maximumLineCountValid && elideMode != QDeclarative1Text::ElideNone && q->widthValid()) {
+ QFontMetrics fm(font);
+ tmp = fm.elidedText(tmp,(Qt::TextElideMode)elideMode,q->width());
+ if (tmp != text) {
+ layoutTextElided = true;
+ if (!truncated) {
+ truncated = true;
+ emit q->truncatedChanged();
+ }
+ }
+ }
+ layout.setText(tmp);
+ } else {
+ singleline = false;
+ QDeclarative1StyledText::parse(text, layout);
+ }
+ }
+
+ updateSize();
+}
+
+void QDeclarative1TextPrivate::updateSize()
+{
+ Q_Q(QDeclarative1Text);
+
+ if (!q->isComponentComplete()) {
+ updateOnComponentComplete = true;
+ return;
+ }
+
+ if (!requireImplicitWidth) {
+ emit q->implicitWidthChanged();
+ // if the implicitWidth is used, then updateSize() has already been called (recursively)
+ if (requireImplicitWidth)
+ return;
+ }
+
+ invalidateImageCache();
+
+ QFontMetrics fm(font);
+ if (text.isEmpty()) {
+ q->setImplicitWidth(0);
+ q->setImplicitHeight(fm.height());
+ paintedSize = QSize(0, fm.height());
+ emit q->paintedSizeChanged();
+ q->update();
+ return;
+ }
+
+ int dy = q->height();
+ QSize size(0, 0);
+
+ //setup instance of QTextLayout for all cases other than richtext
+ if (!richText) {
+ QRect textRect = setupTextLayout();
+ if (layedOutTextRect.size() != textRect.size())
+ q->prepareGeometryChange();
+ layedOutTextRect = textRect;
+ size = textRect.size();
+ dy -= size.height();
+ } else {
+ singleline = false; // richtext can't elide or be optimized for single-line case
+ ensureDoc();
+ doc->setDefaultFont(font);
+
+ QDeclarative1Text::HAlignment horizontalAlignment = q->effectiveHAlign();
+ if (rightToLeftText) {
+ if (horizontalAlignment == QDeclarative1Text::AlignLeft)
+ horizontalAlignment = QDeclarative1Text::AlignRight;
+ else if (horizontalAlignment == QDeclarative1Text::AlignRight)
+ horizontalAlignment = QDeclarative1Text::AlignLeft;
+ }
+ QTextOption option;
+ option.setAlignment((Qt::Alignment)int(horizontalAlignment | vAlign));
+ option.setWrapMode(QTextOption::WrapMode(wrapMode));
+ doc->setDefaultTextOption(option);
+ if (requireImplicitWidth && q->widthValid()) {
+ doc->setTextWidth(-1);
+ naturalWidth = doc->idealWidth();
+ }
+ if (wrapMode != QDeclarative1Text::NoWrap && q->widthValid())
+ doc->setTextWidth(q->width());
+ else
+ doc->setTextWidth(doc->idealWidth()); // ### Text does not align if width is not set (QTextDoc bug)
+ dy -= (int)doc->size().height();
+ QSize dsize = doc->size().toSize();
+ if (dsize != layedOutTextRect.size()) {
+ q->prepareGeometryChange();
+ layedOutTextRect = QRect(QPoint(0,0), dsize);
+ }
+ size = QSize(int(doc->idealWidth()),dsize.height());
+ }
+ int yoff = 0;
+
+ if (q->heightValid()) {
+ if (vAlign == QDeclarative1Text::AlignBottom)
+ yoff = dy;
+ else if (vAlign == QDeclarative1Text::AlignVCenter)
+ yoff = dy/2;
+ }
+ q->setBaselineOffset(fm.ascent() + yoff);
+
+ //### need to comfirm cost of always setting these for richText
+ internalWidthUpdate = true;
+ if (!q->widthValid())
+ q->setImplicitWidth(size.width());
+ else if (requireImplicitWidth)
+ q->setImplicitWidth(naturalWidth);
+ internalWidthUpdate = false;
+ q->setImplicitHeight(size.height());
+ if (paintedSize != size) {
+ paintedSize = size;
+ emit q->paintedSizeChanged();
+ }
+ q->update();
+}
+
+/*!
+ Lays out the QDeclarative1TextPrivate::layout QTextLayout in the constraints of the QDeclarative1Text.
+
+ Returns the size of the final text. This can be used to position the text vertically (the text is
+ already absolutely positioned horizontally).
+*/
+QRect QDeclarative1TextPrivate::setupTextLayout()
+{
+ // ### text layout handling should be profiled and optimized as needed
+ // what about QStackTextEngine engine(tmp, d->font.font()); QTextLayout textLayout(&engine);
+ Q_Q(QDeclarative1Text);
+ layout.setCacheEnabled(true);
+
+ qreal lineWidth = 0;
+ int visibleCount = 0;
+
+ //set manual width
+ if (q->widthValid())
+ lineWidth = q->width();
+
+ QTextOption textOption = layout.textOption();
+ textOption.setAlignment(Qt::Alignment(q->effectiveHAlign()));
+ textOption.setWrapMode(QTextOption::WrapMode(wrapMode));
+ layout.setTextOption(textOption);
+
+ bool elideText = false;
+ bool truncate = false;
+
+ QFontMetrics fm(layout.font());
+ elidePos = QPointF();
+
+ if (requireImplicitWidth && q->widthValid()) {
+ // requires an extra layout
+ QString elidedText;
+ if (layoutTextElided) {
+ // We have provided elided text to the layout, but we must calculate unelided width.
+ elidedText = layout.text();
+ layout.setText(text);
+ }
+ layout.beginLayout();
+ forever {
+ QTextLine line = layout.createLine();
+ if (!line.isValid())
+ break;
+ }
+ layout.endLayout();
+ QRectF br;
+ for (int i = 0; i < layout.lineCount(); ++i) {
+ QTextLine line = layout.lineAt(i);
+ br = br.united(line.naturalTextRect());
+ }
+ naturalWidth = br.width();
+ if (layoutTextElided)
+ layout.setText(elidedText);
+ }
+
+ if (maximumLineCountValid) {
+ layout.beginLayout();
+ if (!lineWidth)
+ lineWidth = INT_MAX;
+ int linesLeft = maximumLineCount;
+ int visibleTextLength = 0;
+ while (linesLeft > 0) {
+ QTextLine line = layout.createLine();
+ if (!line.isValid())
+ break;
+
+ visibleCount++;
+ if (lineWidth)
+ line.setLineWidth(lineWidth);
+ visibleTextLength += line.textLength();
+
+ if (--linesLeft == 0) {
+ if (visibleTextLength < text.length()) {
+ truncate = true;
+ if (elideMode==QDeclarative1Text::ElideRight && q->widthValid()) {
+ qreal elideWidth = fm.width(elideChar);
+ // Need to correct for alignment
+ line.setLineWidth(lineWidth-elideWidth);
+ if (layout.text().mid(line.textStart(), line.textLength()).isRightToLeft()) {
+ line.setPosition(QPointF(line.position().x() + elideWidth, line.position().y()));
+ elidePos.setX(line.naturalTextRect().left() - elideWidth);
+ } else {
+ elidePos.setX(line.naturalTextRect().right());
+ }
+ elideText = true;
+ }
+ }
+ }
+ }
+ layout.endLayout();
+
+ //Update truncated
+ if (truncated != truncate) {
+ truncated = truncate;
+ emit q->truncatedChanged();
+ }
+ } else {
+ layout.beginLayout();
+ forever {
+ QTextLine line = layout.createLine();
+ if (!line.isValid())
+ break;
+ visibleCount++;
+ if (lineWidth)
+ line.setLineWidth(lineWidth);
+ }
+ layout.endLayout();
+ }
+
+ qreal height = 0;
+ QRectF br;
+ for (int i = 0; i < layout.lineCount(); ++i) {
+ QTextLine line = layout.lineAt(i);
+ // set line spacing
+ line.setPosition(QPointF(line.position().x(), height));
+ if (elideText && i == layout.lineCount()-1) {
+ elidePos.setY(height + fm.ascent());
+ br = br.united(QRectF(elidePos, QSizeF(fm.width(elideChar), fm.ascent())));
+ }
+ br = br.united(line.naturalTextRect());
+ height += (lineHeightMode == QDeclarative1Text::FixedHeight) ? lineHeight : line.height() * lineHeight;
+ }
+ br.setHeight(height);
+
+ if (!q->widthValid())
+ naturalWidth = br.width();
+
+ //Update the number of visible lines
+ if (lineCount != visibleCount) {
+ lineCount = visibleCount;
+ emit q->lineCountChanged();
+ }
+
+ return QRect(qRound(br.x()), qRound(br.y()), qCeil(br.width()), qCeil(br.height()));
+}
+
+/*!
+ Returns a painted version of the QDeclarative1TextPrivate::layout QTextLayout.
+ If \a drawStyle is true, the style color overrides all colors in the document.
+*/
+QPixmap QDeclarative1TextPrivate::textLayoutImage(bool drawStyle)
+{
+ //do layout
+ QSize size = layedOutTextRect.size();
+ //paint text
+ QPixmap img(size);
+ if (!size.isEmpty()) {
+ img.fill(Qt::transparent);
+#ifdef Q_WS_MAC
+ bool oldSmooth = qt_applefontsmoothing_enabled;
+ qt_applefontsmoothing_enabled = false;
+#endif
+ QPainter p(&img);
+#ifdef Q_WS_MAC
+ qt_applefontsmoothing_enabled = oldSmooth;
+#endif
+ drawTextLayout(&p, QPointF(-layedOutTextRect.x(),0), drawStyle);
+ }
+ return img;
+}
+
+/*!
+ Paints the QDeclarative1TextPrivate::layout QTextLayout into \a painter at \a pos. If
+ \a drawStyle is true, the style color overrides all colors in the document.
+*/
+void QDeclarative1TextPrivate::drawTextLayout(QPainter *painter, const QPointF &pos, bool drawStyle)
+{
+ if (drawStyle)
+ painter->setPen(styleColor);
+ else
+ painter->setPen(color);
+ painter->setFont(font);
+ layout.draw(painter, pos);
+ if (!elidePos.isNull())
+ painter->drawText(pos + elidePos, elideChar);
+}
+
+/*!
+ Returns a painted version of the QDeclarative1TextPrivate::doc QTextDocument.
+ If \a drawStyle is true, the style color overrides all colors in the document.
+*/
+QPixmap QDeclarative1TextPrivate::textDocumentImage(bool drawStyle)
+{
+ QSize size = doc->size().toSize();
+
+ //paint text
+ QPixmap img(size);
+ img.fill(Qt::transparent);
+#ifdef Q_WS_MAC
+ bool oldSmooth = qt_applefontsmoothing_enabled;
+ qt_applefontsmoothing_enabled = false;
+#endif
+ QPainter p(&img);
+#ifdef Q_WS_MAC
+ qt_applefontsmoothing_enabled = oldSmooth;
+#endif
+
+ QAbstractTextDocumentLayout::PaintContext context;
+
+ QTextOption oldOption(doc->defaultTextOption());
+ if (drawStyle) {
+ context.palette.setColor(QPalette::Text, styleColor);
+ QTextOption colorOption(doc->defaultTextOption());
+ colorOption.setFlags(QTextOption::SuppressColors);
+ doc->setDefaultTextOption(colorOption);
+ } else {
+ context.palette.setColor(QPalette::Text, color);
+ }
+ doc->documentLayout()->draw(&p, context);
+ if (drawStyle)
+ doc->setDefaultTextOption(oldOption);
+ return img;
+}
+
+/*!
+ Mark the image cache as dirty.
+*/
+void QDeclarative1TextPrivate::invalidateImageCache()
+{
+ Q_Q(QDeclarative1Text);
+
+ if(cacheAllTextAsImage || style != QDeclarative1Text::Normal){//If actually using the image cache
+ if (imageCacheDirty)
+ return;
+
+ imageCacheDirty = true;
+ imageCache = QPixmap();
+ }
+ if (q->isComponentComplete())
+ q->update();
+}
+
+/*!
+ Tests if the image cache is dirty, and repaints it if it is.
+*/
+void QDeclarative1TextPrivate::checkImageCache()
+{
+ if (!imageCacheDirty)
+ return;
+
+ if (text.isEmpty()) {
+
+ imageCache = QPixmap();
+
+ } else {
+
+ QPixmap textImage;
+ QPixmap styledImage;
+
+ if (richText) {
+ textImage = textDocumentImage(false);
+ if (style != QDeclarative1Text::Normal)
+ styledImage = textDocumentImage(true); //### should use styleColor
+ } else {
+ textImage = textLayoutImage(false);
+ if (style != QDeclarative1Text::Normal)
+ styledImage = textLayoutImage(true); //### should use styleColor
+ }
+
+ switch (style) {
+ case QDeclarative1Text::Outline:
+ imageCache = drawOutline(textImage, styledImage);
+ break;
+ case QDeclarative1Text::Sunken:
+ imageCache = drawOutline(textImage, styledImage, -1);
+ break;
+ case QDeclarative1Text::Raised:
+ imageCache = drawOutline(textImage, styledImage, 1);
+ break;
+ default:
+ imageCache = textImage;
+ break;
+ }
+
+ }
+
+ imageCacheDirty = false;
+}
+
+/*!
+ Ensures the QDeclarative1TextPrivate::doc variable is set to a valid text document
+*/
+void QDeclarative1TextPrivate::ensureDoc()
+{
+ if (!doc) {
+ Q_Q(QDeclarative1Text);
+ doc = new QTextDocumentWithImageResources_1(q);
+ doc->setDocumentMargin(0);
+ }
+}
+
+/*!
+ Draw \a styleSource as an outline around \a source and return the new image.
+*/
+QPixmap QDeclarative1TextPrivate::drawOutline(const QPixmap &source, const QPixmap &styleSource)
+{
+ QPixmap img = QPixmap(styleSource.width() + 2, styleSource.height() + 2);
+ img.fill(Qt::transparent);
+
+ QPainter ppm(&img);
+
+ QPoint pos(0, 0);
+ pos += QPoint(-1, 0);
+ ppm.drawPixmap(pos, styleSource);
+ pos += QPoint(2, 0);
+ ppm.drawPixmap(pos, styleSource);
+ pos += QPoint(-1, -1);
+ ppm.drawPixmap(pos, styleSource);
+ pos += QPoint(0, 2);
+ ppm.drawPixmap(pos, styleSource);
+
+ pos += QPoint(0, -1);
+ ppm.drawPixmap(pos, source);
+ ppm.end();
+
+ return img;
+}
+
+/*!
+ Draw \a styleSource below \a source at \a yOffset and return the new image.
+*/
+QPixmap QDeclarative1TextPrivate::drawOutline(const QPixmap &source, const QPixmap &styleSource, int yOffset)
+{
+ QPixmap img = QPixmap(styleSource.width() + 2, styleSource.height() + 2);
+ img.fill(Qt::transparent);
+
+ QPainter ppm(&img);
+
+ ppm.drawPixmap(QPoint(0, yOffset), styleSource);
+ ppm.drawPixmap(0, 0, source);
+
+ ppm.end();
+
+ return img;
+}
+
+/*!
+ \qmlclass Text QDeclarative1Text
+ \ingroup qml-basic-visual-elements
+ \since 4.7
+ \brief The Text item allows you to add formatted text to a scene.
+ \inherits Item
+
+ Text items can display both plain and rich text. For example, red text with
+ a specific font and size can be defined like this:
+
+ \qml
+ Text {
+ text: "Hello World!"
+ font.family: "Helvetica"
+ font.pointSize: 24
+ color: "red"
+ }
+ \endqml
+
+ Rich text is defined using HTML-style markup:
+
+ \qml
+ Text {
+ text: "<b>Hello</b> <i>World!</i>"
+ }
+ \endqml
+
+ \image declarative-text.png
+
+ If height and width are not explicitly set, Text will attempt to determine how
+ much room is needed and set it accordingly. Unless \l wrapMode is set, it will always
+ prefer width to height (all text will be placed on a single line).
+
+ The \l elide property can alternatively be used to fit a single line of
+ plain text to a set width.
+
+ Note that the \l{Supported HTML Subset} is limited. Also, if the text contains
+ HTML img tags that load remote images, the text is reloaded.
+
+ Text provides read-only text. For editable text, see \l TextEdit.
+
+ \sa {declarative/text/fonts}{Fonts example}
+*/
+QDeclarative1Text::QDeclarative1Text(QDeclarativeItem *parent)
+ : QDeclarative1ImplicitSizeItem(*(new QDeclarative1TextPrivate), parent)
+{
+}
+
+QDeclarative1Text::~QDeclarative1Text()
+{
+}
+
+/*!
+ \qmlproperty bool Text::clip
+ This property holds whether the text is clipped.
+
+ Note that if the text does not fit in the bounding rectangle it will be abruptly chopped.
+
+ If you want to display potentially long text in a limited space, you probably want to use \c elide instead.
+*/
+
+/*!
+ \qmlproperty bool Text::smooth
+
+ This property holds whether the text is smoothly scaled or transformed.
+
+ Smooth filtering gives better visual quality, but is slower. If
+ the item is displayed at its natural size, this property has no visual or
+ performance effect.
+
+ \note Generally scaling artifacts are only visible if the item is stationary on
+ the screen. A common pattern when animating an item is to disable smooth
+ filtering at the beginning of the animation and reenable it at the conclusion.
+*/
+
+/*!
+ \qmlsignal Text::onLinkActivated(string link)
+
+ This handler is called when the user clicks on a link embedded in the text.
+ The link must be in rich text or HTML format and the
+ \a link string provides access to the particular link.
+
+ \snippet doc/src/snippets/declarative/text/onLinkActivated.qml 0
+
+ The example code will display the text
+ "The main website is at \l{http://qt.nokia.com}{Nokia Qt DF}."
+
+ Clicking on the highlighted link will output
+ \tt{http://qt.nokia.com link activated} to the console.
+*/
+
+/*!
+ \qmlproperty string Text::font.family
+
+ Sets the family name of the font.
+
+ The family name is case insensitive and may optionally include a foundry name, e.g. "Helvetica [Cronyx]".
+ If the family is available from more than one foundry and the foundry isn't specified, an arbitrary foundry is chosen.
+ If the family isn't available a family will be set using the font matching algorithm.
+*/
+
+/*!
+ \qmlproperty bool Text::font.bold
+
+ Sets whether the font weight is bold.
+*/
+
+/*!
+ \qmlproperty enumeration Text::font.weight
+
+ Sets the font's weight.
+
+ The weight can be one of:
+ \list
+ \o Font.Light
+ \o Font.Normal - the default
+ \o Font.DemiBold
+ \o Font.Bold
+ \o Font.Black
+ \endlist
+
+ \qml
+ Text { text: "Hello"; font.weight: Font.DemiBold }
+ \endqml
+*/
+
+/*!
+ \qmlproperty bool Text::font.italic
+
+ Sets whether the font has an italic style.
+*/
+
+/*!
+ \qmlproperty bool Text::font.underline
+
+ Sets whether the text is underlined.
+*/
+
+/*!
+ \qmlproperty bool Text::font.strikeout
+
+ Sets whether the font has a strikeout style.
+*/
+
+/*!
+ \qmlproperty real Text::font.pointSize
+
+ Sets the font size in points. The point size must be greater than zero.
+*/
+
+/*!
+ \qmlproperty int Text::font.pixelSize
+
+ Sets the font size in pixels.
+
+ Using this function makes the font device dependent.
+ Use \c pointSize to set the size of the font in a device independent manner.
+*/
+
+/*!
+ \qmlproperty real Text::font.letterSpacing
+
+ Sets the letter spacing for the font.
+
+ Letter spacing changes the default spacing between individual letters in the font.
+ A positive value increases the letter spacing by the corresponding pixels; a negative value decreases the spacing.
+*/
+
+/*!
+ \qmlproperty real Text::font.wordSpacing
+
+ Sets the word spacing for the font.
+
+ Word spacing changes the default spacing between individual words.
+ A positive value increases the word spacing by a corresponding amount of pixels,
+ while a negative value decreases the inter-word spacing accordingly.
+*/
+
+/*!
+ \qmlproperty enumeration Text::font.capitalization
+
+ Sets the capitalization for the text.
+
+ \list
+ \o Font.MixedCase - This is the normal text rendering option where no capitalization change is applied.
+ \o Font.AllUppercase - This alters the text to be rendered in all uppercase type.
+ \o Font.AllLowercase - This alters the text to be rendered in all lowercase type.
+ \o Font.SmallCaps - This alters the text to be rendered in small-caps type.
+ \o Font.Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character.
+ \endlist
+
+ \qml
+ Text { text: "Hello"; font.capitalization: Font.AllLowercase }
+ \endqml
+*/
+QFont QDeclarative1Text::font() const
+{
+ Q_D(const QDeclarative1Text);
+ return d->sourceFont;
+}
+
+void QDeclarative1Text::setFont(const QFont &font)
+{
+ Q_D(QDeclarative1Text);
+ if (d->sourceFont == font)
+ return;
+
+ d->sourceFont = font;
+ QFont oldFont = d->font;
+ d->font = font;
+ if (d->font.pointSizeF() != -1) {
+ // 0.5pt resolution
+ qreal size = qRound(d->font.pointSizeF()*2.0);
+ d->font.setPointSizeF(size/2.0);
+ }
+
+ if (oldFont != d->font)
+ d->updateLayout();
+
+ emit fontChanged(d->sourceFont);
+}
+
+/*!
+ \qmlproperty string Text::text
+
+ The text to display. Text supports both plain and rich text strings.
+
+ The item will try to automatically determine whether the text should
+ be treated as rich text. This determination is made using Qt::mightBeRichText().
+*/
+QString QDeclarative1Text::text() const
+{
+ Q_D(const QDeclarative1Text);
+ return d->text;
+}
+
+void QDeclarative1Text::setText(const QString &n)
+{
+ Q_D(QDeclarative1Text);
+ if (d->text == n)
+ return;
+
+ d->richText = d->format == RichText || (d->format == AutoText && Qt::mightBeRichText(n));
+ d->text = n;
+ if (isComponentComplete()) {
+ if (d->richText) {
+ d->ensureDoc();
+ d->doc->setText(n);
+ d->rightToLeftText = d->doc->toPlainText().isRightToLeft();
+ } else {
+ d->rightToLeftText = d->text.isRightToLeft();
+ }
+ d->determineHorizontalAlignment();
+ }
+ d->updateLayout();
+ emit textChanged(d->text);
+}
+
+
+/*!
+ \qmlproperty color Text::color
+
+ The text color.
+
+ An example of green text defined using hexadecimal notation:
+ \qml
+ Text {
+ color: "#00FF00"
+ text: "green text"
+ }
+ \endqml
+
+ An example of steel blue text defined using an SVG color name:
+ \qml
+ Text {
+ color: "steelblue"
+ text: "blue text"
+ }
+ \endqml
+*/
+QColor QDeclarative1Text::color() const
+{
+ Q_D(const QDeclarative1Text);
+ return d->color;
+}
+
+void QDeclarative1Text::setColor(const QColor &color)
+{
+ Q_D(QDeclarative1Text);
+ if (d->color == color)
+ return;
+
+ d->color = color;
+ d->invalidateImageCache();
+ emit colorChanged(d->color);
+}
+
+/*!
+ \qmlproperty enumeration Text::style
+
+ Set an additional text style.
+
+ Supported text styles are:
+ \list
+ \o Text.Normal - the default
+ \o Text.Outline
+ \o Text.Raised
+ \o Text.Sunken
+ \endlist
+
+ \qml
+ Row {
+ Text { font.pointSize: 24; text: "Normal" }
+ Text { font.pointSize: 24; text: "Raised"; style: Text.Raised; styleColor: "#AAAAAA" }
+ Text { font.pointSize: 24; text: "Outline";style: Text.Outline; styleColor: "red" }
+ Text { font.pointSize: 24; text: "Sunken"; style: Text.Sunken; styleColor: "#AAAAAA" }
+ }
+ \endqml
+
+ \image declarative-textstyle.png
+*/
+QDeclarative1Text::TextStyle QDeclarative1Text::style() const
+{
+ Q_D(const QDeclarative1Text);
+ return d->style;
+}
+
+void QDeclarative1Text::setStyle(QDeclarative1Text::TextStyle style)
+{
+ Q_D(QDeclarative1Text);
+ if (d->style == style)
+ return;
+
+ // changing to/from Normal requires the boundingRect() to change
+ if (isComponentComplete() && (d->style == Normal || style == Normal))
+ prepareGeometryChange();
+ d->style = style;
+ d->invalidateImageCache();
+ emit styleChanged(d->style);
+}
+
+/*!
+ \qmlproperty color Text::styleColor
+
+ Defines the secondary color used by text styles.
+
+ \c styleColor is used as the outline color for outlined text, and as the
+ shadow color for raised or sunken text. If no style has been set, it is not
+ used at all.
+
+ \qml
+ Text { font.pointSize: 18; text: "hello"; style: Text.Raised; styleColor: "gray" }
+ \endqml
+
+ \sa style
+ */
+QColor QDeclarative1Text::styleColor() const
+{
+ Q_D(const QDeclarative1Text);
+ return d->styleColor;
+}
+
+void QDeclarative1Text::setStyleColor(const QColor &color)
+{
+ Q_D(QDeclarative1Text);
+ if (d->styleColor == color)
+ return;
+
+ d->styleColor = color;
+ d->invalidateImageCache();
+ emit styleColorChanged(d->styleColor);
+}
+
+
+/*!
+ \qmlproperty enumeration Text::horizontalAlignment
+ \qmlproperty enumeration Text::verticalAlignment
+ \qmlproperty enumeration Text::effectiveHorizontalAlignment
+
+ Sets the horizontal and vertical alignment of the text within the Text items
+ width and height. By default, the text is vertically aligned to the top. Horizontal
+ alignment follows the natural alignment of the text, for example text that is read
+ from left to right will be aligned to the left.
+
+ The valid values for \c horizontalAlignment are \c Text.AlignLeft, \c Text.AlignRight, \c Text.AlignHCenter and
+ \c Text.AlignJustify. The valid values for \c verticalAlignment are \c Text.AlignTop, \c Text.AlignBottom
+ and \c Text.AlignVCenter.
+
+ Note that for a single line of text, the size of the text is the area of the text. In this common case,
+ all alignments are equivalent. If you want the text to be, say, centered in its parent, then you will
+ need to either modify the Item::anchors, or set horizontalAlignment to Text.AlignHCenter and bind the width to
+ that of the parent.
+
+ When using the attached property LayoutMirroring::enabled to mirror application
+ layouts, the horizontal alignment of text will also be mirrored. However, the property
+ \c horizontalAlignment will remain unchanged. To query the effective horizontal alignment
+ of Text, use the read-only property \c effectiveHorizontalAlignment.
+*/
+QDeclarative1Text::HAlignment QDeclarative1Text::hAlign() const
+{
+ Q_D(const QDeclarative1Text);
+ return d->hAlign;
+}
+
+void QDeclarative1Text::setHAlign(HAlignment align)
+{
+ Q_D(QDeclarative1Text);
+ bool forceAlign = d->hAlignImplicit && d->effectiveLayoutMirror;
+ d->hAlignImplicit = false;
+ if (d->setHAlign(align, forceAlign) && isComponentComplete())
+ d->updateLayout();
+}
+
+void QDeclarative1Text::resetHAlign()
+{
+ Q_D(QDeclarative1Text);
+ d->hAlignImplicit = true;
+ if (d->determineHorizontalAlignment() && isComponentComplete())
+ d->updateLayout();
+}
+
+QDeclarative1Text::HAlignment QDeclarative1Text::effectiveHAlign() const
+{
+ Q_D(const QDeclarative1Text);
+ QDeclarative1Text::HAlignment effectiveAlignment = d->hAlign;
+ if (!d->hAlignImplicit && d->effectiveLayoutMirror) {
+ switch (d->hAlign) {
+ case QDeclarative1Text::AlignLeft:
+ effectiveAlignment = QDeclarative1Text::AlignRight;
+ break;
+ case QDeclarative1Text::AlignRight:
+ effectiveAlignment = QDeclarative1Text::AlignLeft;
+ break;
+ default:
+ break;
+ }
+ }
+ return effectiveAlignment;
+}
+
+bool QDeclarative1TextPrivate::setHAlign(QDeclarative1Text::HAlignment alignment, bool forceAlign)
+{
+ Q_Q(QDeclarative1Text);
+ if (hAlign != alignment || forceAlign) {
+ QDeclarative1Text::HAlignment oldEffectiveHAlign = q->effectiveHAlign();
+ hAlign = alignment;
+
+ emit q->horizontalAlignmentChanged(hAlign);
+ if (oldEffectiveHAlign != q->effectiveHAlign())
+ emit q->effectiveHorizontalAlignmentChanged();
+ return true;
+ }
+ return false;
+}
+
+bool QDeclarative1TextPrivate::determineHorizontalAlignment()
+{
+ Q_Q(QDeclarative1Text);
+ if (hAlignImplicit && q->isComponentComplete()) {
+ bool alignToRight = text.isEmpty() ? QApplication::keyboardInputDirection() == Qt::RightToLeft : rightToLeftText;
+ return setHAlign(alignToRight ? QDeclarative1Text::AlignRight : QDeclarative1Text::AlignLeft);
+ }
+ return false;
+}
+
+void QDeclarative1TextPrivate::mirrorChange()
+{
+ Q_Q(QDeclarative1Text);
+ if (q->isComponentComplete()) {
+ if (!hAlignImplicit && (hAlign == QDeclarative1Text::AlignRight || hAlign == QDeclarative1Text::AlignLeft)) {
+ updateLayout();
+ emit q->effectiveHorizontalAlignmentChanged();
+ }
+ }
+}
+
+QTextDocument *QDeclarative1TextPrivate::textDocument()
+{
+ return doc;
+}
+
+QDeclarative1Text::VAlignment QDeclarative1Text::vAlign() const
+{
+ Q_D(const QDeclarative1Text);
+ return d->vAlign;
+}
+
+void QDeclarative1Text::setVAlign(VAlignment align)
+{
+ Q_D(QDeclarative1Text);
+ if (d->vAlign == align)
+ return;
+
+ if (isComponentComplete())
+ prepareGeometryChange();
+ d->vAlign = align;
+ emit verticalAlignmentChanged(align);
+}
+
+/*!
+ \qmlproperty enumeration Text::wrapMode
+
+ Set this property to wrap the text to the Text item's width. The text will only
+ wrap if an explicit width has been set. wrapMode can be one of:
+
+ \list
+ \o Text.NoWrap (default) - no wrapping will be performed. If the text contains insufficient newlines, then \l paintedWidth will exceed a set width.
+ \o Text.WordWrap - wrapping is done on word boundaries only. If a word is too long, \l paintedWidth will exceed a set width.
+ \o Text.WrapAnywhere - wrapping is done at any point on a line, even if it occurs in the middle of a word.
+ \o Text.Wrap - if possible, wrapping occurs at a word boundary; otherwise it will occur at the appropriate point on the line, even in the middle of a word.
+ \endlist
+*/
+QDeclarative1Text::WrapMode QDeclarative1Text::wrapMode() const
+{
+ Q_D(const QDeclarative1Text);
+ return d->wrapMode;
+}
+
+void QDeclarative1Text::setWrapMode(WrapMode mode)
+{
+ Q_D(QDeclarative1Text);
+ if (mode == d->wrapMode)
+ return;
+
+ d->wrapMode = mode;
+ d->updateLayout();
+
+ emit wrapModeChanged();
+}
+
+/*!
+ \qmlproperty int Text::lineCount
+ \since Quick 1.1
+
+ Returns the number of lines visible in the text item.
+
+ This property is not supported for rich text.
+
+ \sa maximumLineCount
+*/
+int QDeclarative1Text::lineCount() const
+{
+ Q_D(const QDeclarative1Text);
+ return d->lineCount;
+}
+
+/*!
+ \qmlproperty bool Text::truncated
+ \since Quick 1.1
+
+ Returns true if the text has been truncated due to \l maximumLineCount
+ or \l elide.
+
+ This property is not supported for rich text.
+
+ \sa maximumLineCount, elide
+*/
+bool QDeclarative1Text::truncated() const
+{
+ Q_D(const QDeclarative1Text);
+ return d->truncated;
+}
+
+/*!
+ \qmlproperty int Text::maximumLineCount
+ \since Quick 1.1
+
+ Set this property to limit the number of lines that the text item will show.
+ If elide is set to Text.ElideRight, the text will be elided appropriately.
+ By default, this is the value of the largest possible integer.
+
+ This property is not supported for rich text.
+
+ \sa lineCount, elide
+*/
+int QDeclarative1Text::maximumLineCount() const
+{
+ Q_D(const QDeclarative1Text);
+ return d->maximumLineCount;
+}
+
+void QDeclarative1Text::setMaximumLineCount(int lines)
+{
+ Q_D(QDeclarative1Text);
+
+ d->maximumLineCountValid = lines==INT_MAX ? false : true;
+ if (d->maximumLineCount != lines) {
+ d->maximumLineCount = lines;
+ d->updateLayout();
+ emit maximumLineCountChanged();
+ }
+}
+
+void QDeclarative1Text::resetMaximumLineCount()
+{
+ Q_D(QDeclarative1Text);
+ setMaximumLineCount(INT_MAX);
+ d->elidePos = QPointF();
+ if (d->truncated != false) {
+ d->truncated = false;
+ emit truncatedChanged();
+ }
+}
+
+/*!
+ \qmlproperty enumeration Text::textFormat
+
+ The way the text property should be displayed.
+
+ Supported text formats are:
+
+ \list
+ \o Text.AutoText (default)
+ \o Text.PlainText
+ \o Text.RichText
+ \o Text.StyledText
+ \endlist
+
+ If the text format is \c Text.AutoText the text element
+ will automatically determine whether the text should be treated as
+ rich text. This determination is made using Qt::mightBeRichText().
+
+ Text.StyledText is an optimized format supporting some basic text
+ styling markup, in the style of html 3.2:
+
+ \code
+ <font size="4" color="#ff0000">font size and color</font>
+ <b>bold</b>
+ <i>italic</i>
+ <br>
+ &gt; &lt; &amp;
+ \endcode
+
+ \c Text.StyledText parser is strict, requiring tags to be correctly nested.
+
+ \table
+ \row
+ \o
+ \qml
+Column {
+ Text {
+ font.pointSize: 24
+ text: "<b>Hello</b> <i>World!</i>"
+ }
+ Text {
+ font.pointSize: 24
+ textFormat: Text.RichText
+ text: "<b>Hello</b> <i>World!</i>"
+ }
+ Text {
+ font.pointSize: 24
+ textFormat: Text.PlainText
+ text: "<b>Hello</b> <i>World!</i>"
+ }
+}
+ \endqml
+ \o \image declarative-textformat.png
+ \endtable
+*/
+QDeclarative1Text::TextFormat QDeclarative1Text::textFormat() const
+{
+ Q_D(const QDeclarative1Text);
+ return d->format;
+}
+
+void QDeclarative1Text::setTextFormat(TextFormat format)
+{
+ Q_D(QDeclarative1Text);
+ if (format == d->format)
+ return;
+ d->format = format;
+ bool wasRich = d->richText;
+ d->richText = format == RichText || (format == AutoText && Qt::mightBeRichText(d->text));
+
+ if (!wasRich && d->richText && isComponentComplete()) {
+ d->ensureDoc();
+ d->doc->setText(d->text);
+ }
+
+ d->updateLayout();
+
+ emit textFormatChanged(d->format);
+}
+
+/*!
+ \qmlproperty enumeration Text::elide
+
+ Set this property to elide parts of the text fit to the Text item's width.
+ The text will only elide if an explicit width has been set.
+
+ This property cannot be used with rich text.
+
+ Eliding can be:
+ \list
+ \o Text.ElideNone - the default
+ \o Text.ElideLeft
+ \o Text.ElideMiddle
+ \o Text.ElideRight
+ \endlist
+
+ If this property is set to Text.ElideRight, it can be used with multiline
+ text. The text will only elide if maximumLineCount has been set.
+
+ If the text is a multi-length string, and the mode is not \c Text.ElideNone,
+ the first string that fits will be used, otherwise the last will be elided.
+
+ Multi-length strings are ordered from longest to shortest, separated by the
+ Unicode "String Terminator" character \c U009C (write this in QML with \c{"\u009C"} or \c{"\x9C"}).
+*/
+QDeclarative1Text::TextElideMode QDeclarative1Text::elideMode() const
+{
+ Q_D(const QDeclarative1Text);
+ return d->elideMode;
+}
+
+void QDeclarative1Text::setElideMode(QDeclarative1Text::TextElideMode mode)
+{
+ Q_D(QDeclarative1Text);
+ if (mode == d->elideMode)
+ return;
+
+ d->elideMode = mode;
+ d->updateLayout();
+
+ emit elideModeChanged(d->elideMode);
+}
+
+/*! \internal */
+QRectF QDeclarative1Text::boundingRect() const
+{
+ Q_D(const QDeclarative1Text);
+
+ QRect rect = d->layedOutTextRect;
+ if (d->style != Normal)
+ rect.adjust(-1, 0, 1, 2);
+
+ // Could include font max left/right bearings to either side of rectangle.
+
+ int h = height();
+ switch (d->vAlign) {
+ case AlignTop:
+ break;
+ case AlignBottom:
+ rect.moveTop(h - rect.height());
+ break;
+ case AlignVCenter:
+ rect.moveTop((h - rect.height()) / 2);
+ break;
+ }
+
+ return QRectF(rect);
+}
+
+/*! \internal */
+void QDeclarative1Text::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ Q_D(QDeclarative1Text);
+ if ((!d->internalWidthUpdate && newGeometry.width() != oldGeometry.width())
+ && (d->wrapMode != QDeclarative1Text::NoWrap
+ || d->elideMode != QDeclarative1Text::ElideNone
+ || d->hAlign != QDeclarative1Text::AlignLeft)) {
+ if ((d->singleline || d->maximumLineCountValid) && d->elideMode != QDeclarative1Text::ElideNone && widthValid()) {
+ // We need to re-elide
+ d->updateLayout();
+ } else {
+ // We just need to re-layout
+ d->updateSize();
+ }
+ }
+
+ QDeclarativeItem::geometryChanged(newGeometry, oldGeometry);
+}
+
+/*!
+ \qmlproperty real Text::paintedWidth
+
+ Returns the width of the text, including width past the width
+ which is covered due to insufficient wrapping if WrapMode is set.
+*/
+qreal QDeclarative1Text::paintedWidth() const
+{
+ Q_D(const QDeclarative1Text);
+ return d->paintedSize.width();
+}
+
+/*!
+ \qmlproperty real Text::paintedHeight
+
+ Returns the height of the text, including height past the height
+ which is covered due to there being more text than fits in the set height.
+*/
+qreal QDeclarative1Text::paintedHeight() const
+{
+ Q_D(const QDeclarative1Text);
+ return d->paintedSize.height();
+}
+
+/*!
+ \qmlproperty real Text::lineHeight
+ \since Quick 1.1
+
+ Sets the line height for the text.
+ The value can be in pixels or a multiplier depending on lineHeightMode.
+
+ The default value is a multiplier of 1.0.
+ The line height must be a positive value.
+*/
+qreal QDeclarative1Text::lineHeight() const
+{
+ Q_D(const QDeclarative1Text);
+ return d->lineHeight;
+}
+
+void QDeclarative1Text::setLineHeight(qreal lineHeight)
+{
+ Q_D(QDeclarative1Text);
+
+ if ((d->lineHeight == lineHeight) || (lineHeight < 0.0))
+ return;
+
+ d->lineHeight = lineHeight;
+ d->updateLayout();
+ emit lineHeightChanged(lineHeight);
+}
+
+/*!
+ \qmlproperty enumeration Text::lineHeightMode
+
+ This property determines how the line height is specified.
+ The possible values are:
+
+ \list
+ \o Text.ProportionalHeight (default) - this sets the spacing proportional to the
+ line (as a multiplier). For example, set to 2 for double spacing.
+ \o Text.FixedHeight - this sets the line height to a fixed line height (in pixels).
+ \endlist
+*/
+QDeclarative1Text::LineHeightMode QDeclarative1Text::lineHeightMode() const
+{
+ Q_D(const QDeclarative1Text);
+ return d->lineHeightMode;
+}
+
+void QDeclarative1Text::setLineHeightMode(LineHeightMode mode)
+{
+ Q_D(QDeclarative1Text);
+ if (mode == d->lineHeightMode)
+ return;
+
+ d->lineHeightMode = mode;
+ d->updateLayout();
+
+ emit lineHeightModeChanged(mode);
+}
+
+/*!
+ Returns the number of resources (images) that are being loaded asynchronously.
+*/
+int QDeclarative1Text::resourcesLoading() const
+{
+ Q_D(const QDeclarative1Text);
+ return d->doc ? d->doc->resourcesLoading() : 0;
+}
+
+/*! \internal */
+void QDeclarative1Text::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *)
+{
+ Q_D(QDeclarative1Text);
+
+ if (d->cacheAllTextAsImage || d->style != Normal) {
+ d->checkImageCache();
+ if (d->imageCache.isNull())
+ return;
+
+ bool oldAA = p->testRenderHint(QPainter::Antialiasing);
+ bool oldSmooth = p->testRenderHint(QPainter::SmoothPixmapTransform);
+ if (d->smooth)
+ p->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, d->smooth);
+
+ QRect br = boundingRect().toRect();
+
+ bool needClip = clip() && (d->imageCache.width() > width() ||
+ d->imageCache.height() > height());
+
+ if (needClip)
+ p->drawPixmap(0, 0, width(), height(), d->imageCache, -br.x(), -br.y(), width(), height());
+ else
+ p->drawPixmap(br.x(), br.y(), d->imageCache);
+
+ if (d->smooth) {
+ p->setRenderHint(QPainter::Antialiasing, oldAA);
+ p->setRenderHint(QPainter::SmoothPixmapTransform, oldSmooth);
+ }
+ } else {
+ QRectF bounds = boundingRect();
+
+ bool needClip = clip() && (d->layedOutTextRect.width() > width() ||
+ d->layedOutTextRect.height() > height());
+
+ if (needClip) {
+ p->save();
+ p->setClipRect(0, 0, width(), height(), Qt::IntersectClip);
+ }
+ if (d->richText) {
+ QAbstractTextDocumentLayout::PaintContext context;
+ context.palette.setColor(QPalette::Text, d->color);
+ p->translate(bounds.x(), bounds.y());
+ d->doc->documentLayout()->draw(p, context);
+ p->translate(-bounds.x(), -bounds.y());
+ } else {
+ d->drawTextLayout(p, QPointF(0, bounds.y()), false);
+ }
+
+ if (needClip) {
+ p->restore();
+ }
+ }
+}
+
+/*! \internal */
+void QDeclarative1Text::componentComplete()
+{
+ Q_D(QDeclarative1Text);
+ QDeclarativeItem::componentComplete();
+ if (d->updateOnComponentComplete) {
+ d->updateOnComponentComplete = false;
+ if (d->richText) {
+ d->ensureDoc();
+ d->doc->setText(d->text);
+ d->rightToLeftText = d->doc->toPlainText().isRightToLeft();
+ } else {
+ d->rightToLeftText = d->text.isRightToLeft();
+ }
+ d->determineHorizontalAlignment();
+ d->updateLayout();
+ }
+}
+
+/*! \internal */
+void QDeclarative1Text::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QDeclarative1Text);
+
+ if (!d->richText || !d->doc || d->doc->documentLayout()->anchorAt(event->pos()).isEmpty()) {
+ event->setAccepted(false);
+ d->activeLink.clear();
+ } else {
+ d->activeLink = d->doc->documentLayout()->anchorAt(event->pos());
+ }
+
+ // ### may malfunction if two of the same links are clicked & dragged onto each other)
+
+ if (!event->isAccepted())
+ QDeclarativeItem::mousePressEvent(event);
+
+}
+
+/*! \internal */
+void QDeclarative1Text::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QDeclarative1Text);
+
+ // ### confirm the link, and send a signal out
+ if (d->richText && d->doc && d->activeLink == d->doc->documentLayout()->anchorAt(event->pos()))
+ emit linkActivated(d->activeLink);
+ else
+ event->setAccepted(false);
+
+ if (!event->isAccepted())
+ QDeclarativeItem::mouseReleaseEvent(event);
+}
+
+
+
+QT_END_NAMESPACE
+
+#include "qdeclarativetext.moc"
diff --git a/src/qtquick1/graphicsitems/qdeclarativetext_p.h b/src/qtquick1/graphicsitems/qdeclarativetext_p.h
new file mode 100644
index 0000000000..93261fbb24
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativetext_p.h
@@ -0,0 +1,213 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVETEXT_H
+#define QDECLARATIVETEXT_H
+
+#include <QtGui/qtextoption.h>
+#include "qdeclarativeimplicitsizeitem_p.h"
+
+#include <QtDeclarative/private/qdeclarativeglobal_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QDeclarative1TextPrivate;
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarative1Text : public QDeclarative1ImplicitSizeItem
+{
+ Q_OBJECT
+ Q_ENUMS(HAlignment)
+ Q_ENUMS(VAlignment)
+ Q_ENUMS(TextStyle)
+ Q_ENUMS(TextFormat)
+ Q_ENUMS(TextElideMode)
+ Q_ENUMS(WrapMode)
+ Q_ENUMS(LineHeightMode)
+
+ Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
+ Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged)
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
+ Q_PROPERTY(TextStyle style READ style WRITE setStyle NOTIFY styleChanged)
+ Q_PROPERTY(QColor styleColor READ styleColor WRITE setStyleColor NOTIFY styleColorChanged)
+ Q_PROPERTY(HAlignment horizontalAlignment READ hAlign WRITE setHAlign RESET resetHAlign NOTIFY horizontalAlignmentChanged)
+ Q_PROPERTY(HAlignment effectiveHorizontalAlignment READ effectiveHAlign NOTIFY effectiveHorizontalAlignmentChanged REVISION 1)
+ Q_PROPERTY(VAlignment verticalAlignment READ vAlign WRITE setVAlign NOTIFY verticalAlignmentChanged)
+ Q_PROPERTY(WrapMode wrapMode READ wrapMode WRITE setWrapMode NOTIFY wrapModeChanged)
+ Q_PROPERTY(int lineCount READ lineCount NOTIFY lineCountChanged REVISION 1)
+ Q_PROPERTY(bool truncated READ truncated NOTIFY truncatedChanged REVISION 1)
+ Q_PROPERTY(int maximumLineCount READ maximumLineCount WRITE setMaximumLineCount NOTIFY maximumLineCountChanged RESET resetMaximumLineCount REVISION 1)
+
+ Q_PROPERTY(TextFormat textFormat READ textFormat WRITE setTextFormat NOTIFY textFormatChanged)
+ Q_PROPERTY(TextElideMode elide READ elideMode WRITE setElideMode NOTIFY elideModeChanged) //### elideMode?
+ Q_PROPERTY(qreal paintedWidth READ paintedWidth NOTIFY paintedSizeChanged)
+ Q_PROPERTY(qreal paintedHeight READ paintedHeight NOTIFY paintedSizeChanged)
+ Q_PROPERTY(qreal lineHeight READ lineHeight WRITE setLineHeight NOTIFY lineHeightChanged REVISION 1)
+ Q_PROPERTY(LineHeightMode lineHeightMode READ lineHeightMode WRITE setLineHeightMode NOTIFY lineHeightModeChanged REVISION 1)
+
+public:
+ QDeclarative1Text(QDeclarativeItem *parent=0);
+ ~QDeclarative1Text();
+
+ enum HAlignment { AlignLeft = Qt::AlignLeft,
+ AlignRight = Qt::AlignRight,
+ AlignHCenter = Qt::AlignHCenter,
+ AlignJustify = Qt::AlignJustify }; // ### VERSIONING: Only in QtQuick 1.1
+ enum VAlignment { AlignTop = Qt::AlignTop,
+ AlignBottom = Qt::AlignBottom,
+ AlignVCenter = Qt::AlignVCenter };
+ enum TextStyle { Normal,
+ Outline,
+ Raised,
+ Sunken };
+ enum TextFormat { PlainText = Qt::PlainText,
+ RichText = Qt::RichText,
+ AutoText = Qt::AutoText,
+ StyledText = 4 };
+ enum TextElideMode { ElideLeft = Qt::ElideLeft,
+ ElideRight = Qt::ElideRight,
+ ElideMiddle = Qt::ElideMiddle,
+ ElideNone = Qt::ElideNone };
+
+ enum WrapMode { NoWrap = QTextOption::NoWrap,
+ WordWrap = QTextOption::WordWrap,
+ WrapAnywhere = QTextOption::WrapAnywhere,
+ WrapAtWordBoundaryOrAnywhere = QTextOption::WrapAtWordBoundaryOrAnywhere, // COMPAT
+ Wrap = QTextOption::WrapAtWordBoundaryOrAnywhere
+ };
+
+ enum LineHeightMode { ProportionalHeight, FixedHeight };
+
+ QString text() const;
+ void setText(const QString &);
+
+ QFont font() const;
+ void setFont(const QFont &font);
+
+ QColor color() const;
+ void setColor(const QColor &c);
+
+ TextStyle style() const;
+ void setStyle(TextStyle style);
+
+ QColor styleColor() const;
+ void setStyleColor(const QColor &c);
+
+ HAlignment hAlign() const;
+ void setHAlign(HAlignment align);
+ void resetHAlign();
+ HAlignment effectiveHAlign() const;
+
+ VAlignment vAlign() const;
+ void setVAlign(VAlignment align);
+
+ WrapMode wrapMode() const;
+ void setWrapMode(WrapMode w);
+
+ int lineCount() const;
+ bool truncated() const;
+
+ int maximumLineCount() const;
+ void setMaximumLineCount(int lines);
+ void resetMaximumLineCount();
+
+ TextFormat textFormat() const;
+ void setTextFormat(TextFormat format);
+
+ TextElideMode elideMode() const;
+ void setElideMode(TextElideMode);
+
+ qreal lineHeight() const;
+ void setLineHeight(qreal lineHeight);
+
+ LineHeightMode lineHeightMode() const;
+ void setLineHeightMode(LineHeightMode);
+
+ void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
+
+ virtual void componentComplete();
+
+ int resourcesLoading() const; // mainly for testing
+
+ qreal paintedWidth() const;
+ qreal paintedHeight() const;
+
+ QRectF boundingRect() const;
+
+Q_SIGNALS:
+ void textChanged(const QString &text);
+ void linkActivated(const QString &link);
+ void fontChanged(const QFont &font);
+ void colorChanged(const QColor &color);
+ void styleChanged(TextStyle style);
+ void styleColorChanged(const QColor &color);
+ void horizontalAlignmentChanged(HAlignment alignment);
+ void verticalAlignmentChanged(VAlignment alignment);
+ void wrapModeChanged();
+ Q_REVISION(1) void lineCountChanged();
+ Q_REVISION(1) void truncatedChanged();
+ Q_REVISION(1) void maximumLineCountChanged();
+ void textFormatChanged(TextFormat textFormat);
+ void elideModeChanged(TextElideMode mode);
+ void paintedSizeChanged();
+ Q_REVISION(1) void lineHeightChanged(qreal lineHeight);
+ Q_REVISION(1) void lineHeightModeChanged(LineHeightMode mode);
+ Q_REVISION(1) void effectiveHorizontalAlignmentChanged();
+
+protected:
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+ virtual void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry);
+
+private:
+ Q_DISABLE_COPY(QDeclarative1Text)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarative1Text)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1Text)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/qtquick1/graphicsitems/qdeclarativetext_p_p.h b/src/qtquick1/graphicsitems/qdeclarativetext_p_p.h
new file mode 100644
index 0000000000..b6862d8e85
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativetext_p_p.h
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVETEXT_P_H
+#define QDECLARATIVETEXT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qdeclarativeitem.h"
+#include "private/qdeclarativeimplicitsizeitem_p_p.h"
+#include "QtQuick1/private/qdeclarativetextlayout_p.h"
+
+#include <QtDeclarative/qdeclarative.h>
+
+#include <QtGui/qtextlayout.h>
+
+QT_BEGIN_NAMESPACE
+
+class QTextLayout;
+class QTextDocumentWithImageResources_1;
+
+class Q_AUTOTEST_EXPORT QDeclarative1TextPrivate : public QDeclarative1ImplicitSizeItemPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1Text)
+public:
+ QDeclarative1TextPrivate();
+
+ ~QDeclarative1TextPrivate();
+
+ void updateSize();
+ void updateLayout();
+ bool determineHorizontalAlignment();
+ bool setHAlign(QDeclarative1Text::HAlignment, bool forceAlign = false);
+ void mirrorChange();
+ QTextDocument *textDocument();
+
+ QString text;
+ QFont font;
+ QFont sourceFont;
+ QColor color;
+ QDeclarative1Text::TextStyle style;
+ QColor styleColor;
+ QString activeLink;
+ QDeclarative1Text::HAlignment hAlign;
+ QDeclarative1Text::VAlignment vAlign;
+ QDeclarative1Text::TextElideMode elideMode;
+ QDeclarative1Text::TextFormat format;
+ QDeclarative1Text::WrapMode wrapMode;
+ qreal lineHeight;
+ QDeclarative1Text::LineHeightMode lineHeightMode;
+ int lineCount;
+ bool truncated;
+ int maximumLineCount;
+ int maximumLineCountValid;
+ QPointF elidePos;
+
+ static QString elideChar;
+
+ void invalidateImageCache();
+ void checkImageCache();
+ QPixmap imageCache;
+
+ bool imageCacheDirty:1;
+ bool updateOnComponentComplete:1;
+ bool richText:1;
+ bool singleline:1;
+ bool cacheAllTextAsImage:1;
+ bool internalWidthUpdate:1;
+ bool requireImplicitWidth:1;
+ bool hAlignImplicit:1;
+ bool rightToLeftText:1;
+ bool layoutTextElided:1;
+
+ QRect layedOutTextRect;
+ QSize paintedSize;
+ qreal naturalWidth;
+ virtual qreal implicitWidth() const;
+ void ensureDoc();
+ QPixmap textDocumentImage(bool drawStyle);
+ QTextDocumentWithImageResources_1 *doc;
+
+ QRect setupTextLayout();
+ QPixmap textLayoutImage(bool drawStyle);
+ void drawTextLayout(QPainter *p, const QPointF &pos, bool drawStyle);
+ QDeclarative1TextLayout layout;
+
+ static QPixmap drawOutline(const QPixmap &source, const QPixmap &styleSource);
+ static QPixmap drawOutline(const QPixmap &source, const QPixmap &styleSource, int yOffset);
+
+ static inline QDeclarative1TextPrivate *get(QDeclarative1Text *t) {
+ return t->d_func();
+ }
+};
+
+QT_END_NAMESPACE
+#endif
diff --git a/src/qtquick1/graphicsitems/qdeclarativetextedit.cpp b/src/qtquick1/graphicsitems/qdeclarativetextedit.cpp
new file mode 100644
index 0000000000..1645bfd390
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativetextedit.cpp
@@ -0,0 +1,1892 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qdeclarativetextedit_p.h"
+#include "private/qdeclarativetextedit_p_p.h"
+
+#include "private/qdeclarativeevents_p_p.h"
+#include <private/qdeclarativeglobal_p.h>
+#include <qdeclarativeinfo.h>
+
+#include <QtCore/qmath.h>
+
+#include <private/qtextengine_p.h>
+#include <QTextLayout>
+#include <QTextLine>
+#include <QTextDocument>
+#include <QTextObject>
+#include <QGraphicsSceneMouseEvent>
+#include <QDebug>
+#include <QPainter>
+
+#include <private/qtextcontrol_p.h>
+
+QT_BEGIN_NAMESPACE
+
+
+
+/*!
+ \qmlclass TextEdit QDeclarative1TextEdit
+ \ingroup qml-basic-visual-elements
+ \since 4.7
+ \brief The TextEdit item displays multiple lines of editable formatted text.
+ \inherits Item
+
+ The TextEdit item displays a block of editable, formatted text.
+
+ It can display both plain and rich text. For example:
+
+ \qml
+TextEdit {
+ width: 240
+ text: "<b>Hello</b> <i>World!</i>"
+ font.family: "Helvetica"
+ font.pointSize: 20
+ color: "blue"
+ focus: true
+}
+ \endqml
+
+ \image declarative-textedit.gif
+
+ Setting \l {Item::focus}{focus} to \c true enables the TextEdit item to receive keyboard focus.
+
+ Note that the TextEdit does not implement scrolling, following the cursor, or other behaviors specific
+ to a look-and-feel. For example, to add flickable scrolling that follows the cursor:
+
+ \snippet snippets/declarative/texteditor.qml 0
+
+ A particular look-and-feel might use smooth scrolling (eg. using SmoothedFollow), might have a visible
+ scrollbar, or a scrollbar that fades in to show location, etc.
+
+ Clipboard support is provided by the cut(), copy(), and paste() functions, and the selection can
+ be handled in a traditional "mouse" mechanism by setting selectByMouse, or handled completely
+ from QML by manipulating selectionStart and selectionEnd, or using selectAll() or selectWord().
+
+ You can translate between cursor positions (characters from the start of the document) and pixel
+ points using positionAt() and positionToRectangle().
+
+ \sa Text, TextInput, {declarative/text/textselection}{Text Selection example}
+*/
+
+/*!
+ \qmlsignal TextEdit::onLinkActivated(string link)
+ \since Quick 1.1
+
+ This handler is called when the user clicks on a link embedded in the text.
+ The link must be in rich text or HTML format and the
+ \a link string provides access to the particular link.
+*/
+QDeclarative1TextEdit::QDeclarative1TextEdit(QDeclarativeItem *parent)
+: QDeclarative1ImplicitSizePaintedItem(*(new QDeclarative1TextEditPrivate), parent)
+{
+ Q_D(QDeclarative1TextEdit);
+ d->init();
+}
+
+QString QDeclarative1TextEdit::text() const
+{
+ Q_D(const QDeclarative1TextEdit);
+
+#ifndef QT_NO_TEXTHTMLPARSER
+ if (d->richText)
+ return d->document->toHtml();
+ else
+#endif
+ return d->document->toPlainText();
+}
+
+/*!
+ \qmlproperty string TextEdit::font.family
+
+ Sets the family name of the font.
+
+ The family name is case insensitive and may optionally include a foundry name, e.g. "Helvetica [Cronyx]".
+ If the family is available from more than one foundry and the foundry isn't specified, an arbitrary foundry is chosen.
+ If the family isn't available a family will be set using the font matching algorithm.
+*/
+
+/*!
+ \qmlproperty bool TextEdit::font.bold
+
+ Sets whether the font weight is bold.
+*/
+
+/*!
+ \qmlproperty enumeration TextEdit::font.weight
+
+ Sets the font's weight.
+
+ The weight can be one of:
+ \list
+ \o Font.Light
+ \o Font.Normal - the default
+ \o Font.DemiBold
+ \o Font.Bold
+ \o Font.Black
+ \endlist
+
+ \qml
+ TextEdit { text: "Hello"; font.weight: Font.DemiBold }
+ \endqml
+*/
+
+/*!
+ \qmlproperty bool TextEdit::font.italic
+
+ Sets whether the font has an italic style.
+*/
+
+/*!
+ \qmlproperty bool TextEdit::font.underline
+
+ Sets whether the text is underlined.
+*/
+
+/*!
+ \qmlproperty bool TextEdit::font.strikeout
+
+ Sets whether the font has a strikeout style.
+*/
+
+/*!
+ \qmlproperty real TextEdit::font.pointSize
+
+ Sets the font size in points. The point size must be greater than zero.
+*/
+
+/*!
+ \qmlproperty int TextEdit::font.pixelSize
+
+ Sets the font size in pixels.
+
+ Using this function makes the font device dependent. Use
+ \l{TextEdit::font.pointSize} to set the size of the font in a
+ device independent manner.
+*/
+
+/*!
+ \qmlproperty real TextEdit::font.letterSpacing
+
+ Sets the letter spacing for the font.
+
+ Letter spacing changes the default spacing between individual letters in the font.
+ A positive value increases the letter spacing by the corresponding pixels; a negative value decreases the spacing.
+*/
+
+/*!
+ \qmlproperty real TextEdit::font.wordSpacing
+
+ Sets the word spacing for the font.
+
+ Word spacing changes the default spacing between individual words.
+ A positive value increases the word spacing by a corresponding amount of pixels,
+ while a negative value decreases the inter-word spacing accordingly.
+*/
+
+/*!
+ \qmlproperty enumeration TextEdit::font.capitalization
+
+ Sets the capitalization for the text.
+
+ \list
+ \o Font.MixedCase - This is the normal text rendering option where no capitalization change is applied.
+ \o Font.AllUppercase - This alters the text to be rendered in all uppercase type.
+ \o Font.AllLowercase - This alters the text to be rendered in all lowercase type.
+ \o Font.SmallCaps - This alters the text to be rendered in small-caps type.
+ \o Font.Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character.
+ \endlist
+
+ \qml
+ TextEdit { text: "Hello"; font.capitalization: Font.AllLowercase }
+ \endqml
+*/
+
+/*!
+ \qmlproperty string TextEdit::text
+
+ The text to display. If the text format is AutoText the text edit will
+ automatically determine whether the text should be treated as
+ rich text. This determination is made using Qt::mightBeRichText().
+*/
+void QDeclarative1TextEdit::setText(const QString &text)
+{
+ Q_D(QDeclarative1TextEdit);
+ if (QDeclarative1TextEdit::text() == text)
+ return;
+
+ d->richText = d->format == RichText || (d->format == AutoText && Qt::mightBeRichText(text));
+ if (d->richText) {
+#ifndef QT_NO_TEXTHTMLPARSER
+ d->control->setHtml(text);
+#else
+ d->control->setPlainText(text);
+#endif
+ } else {
+ d->control->setPlainText(text);
+ }
+ q_textChanged();
+}
+
+/*!
+ \qmlproperty enumeration TextEdit::textFormat
+
+ The way the text property should be displayed.
+
+ \list
+ \o TextEdit.AutoText
+ \o TextEdit.PlainText
+ \o TextEdit.RichText
+ \endlist
+
+ The default is TextEdit.AutoText. If the text format is TextEdit.AutoText the text edit
+ will automatically determine whether the text should be treated as
+ rich text. This determination is made using Qt::mightBeRichText().
+
+ \table
+ \row
+ \o
+ \qml
+Column {
+ TextEdit {
+ font.pointSize: 24
+ text: "<b>Hello</b> <i>World!</i>"
+ }
+ TextEdit {
+ font.pointSize: 24
+ textFormat: TextEdit.RichText
+ text: "<b>Hello</b> <i>World!</i>"
+ }
+ TextEdit {
+ font.pointSize: 24
+ textFormat: TextEdit.PlainText
+ text: "<b>Hello</b> <i>World!</i>"
+ }
+}
+ \endqml
+ \o \image declarative-textformat.png
+ \endtable
+*/
+QDeclarative1TextEdit::TextFormat QDeclarative1TextEdit::textFormat() const
+{
+ Q_D(const QDeclarative1TextEdit);
+ return d->format;
+}
+
+void QDeclarative1TextEdit::setTextFormat(TextFormat format)
+{
+ Q_D(QDeclarative1TextEdit);
+ if (format == d->format)
+ return;
+ bool wasRich = d->richText;
+ d->richText = format == RichText || (format == AutoText && Qt::mightBeRichText(d->text));
+
+ if (wasRich && !d->richText) {
+ d->control->setPlainText(d->text);
+ updateSize();
+ } else if (!wasRich && d->richText) {
+#ifndef QT_NO_TEXTHTMLPARSER
+ d->control->setHtml(d->text);
+#else
+ d->control->setPlainText(d->text);
+#endif
+ updateSize();
+ }
+ d->format = format;
+ d->control->setAcceptRichText(d->format != PlainText);
+ emit textFormatChanged(d->format);
+}
+
+QFont QDeclarative1TextEdit::font() const
+{
+ Q_D(const QDeclarative1TextEdit);
+ return d->sourceFont;
+}
+
+void QDeclarative1TextEdit::setFont(const QFont &font)
+{
+ Q_D(QDeclarative1TextEdit);
+ if (d->sourceFont == font)
+ return;
+
+ d->sourceFont = font;
+ QFont oldFont = d->font;
+ d->font = font;
+ if (d->font.pointSizeF() != -1) {
+ // 0.5pt resolution
+ qreal size = qRound(d->font.pointSizeF()*2.0);
+ d->font.setPointSizeF(size/2.0);
+ }
+
+ if (oldFont != d->font) {
+ clearCache();
+ d->document->setDefaultFont(d->font);
+ if(d->cursor){
+ d->cursor->setHeight(QFontMetrics(d->font).height());
+ moveCursorDelegate();
+ }
+ updateSize();
+ update();
+ }
+ emit fontChanged(d->sourceFont);
+}
+
+/*!
+ \qmlproperty color TextEdit::color
+
+ The text color.
+
+ \qml
+ // green text using hexadecimal notation
+ TextEdit { color: "#00FF00" }
+ \endqml
+
+ \qml
+ // steelblue text using SVG color name
+ TextEdit { color: "steelblue" }
+ \endqml
+*/
+QColor QDeclarative1TextEdit::color() const
+{
+ Q_D(const QDeclarative1TextEdit);
+ return d->color;
+}
+
+void QDeclarative1TextEdit::setColor(const QColor &color)
+{
+ Q_D(QDeclarative1TextEdit);
+ if (d->color == color)
+ return;
+
+ clearCache();
+ d->color = color;
+ QPalette pal = d->control->palette();
+ pal.setColor(QPalette::Text, color);
+ d->control->setPalette(pal);
+ update();
+ emit colorChanged(d->color);
+}
+
+/*!
+ \qmlproperty color TextEdit::selectionColor
+
+ The text highlight color, used behind selections.
+*/
+QColor QDeclarative1TextEdit::selectionColor() const
+{
+ Q_D(const QDeclarative1TextEdit);
+ return d->selectionColor;
+}
+
+void QDeclarative1TextEdit::setSelectionColor(const QColor &color)
+{
+ Q_D(QDeclarative1TextEdit);
+ if (d->selectionColor == color)
+ return;
+
+ clearCache();
+ d->selectionColor = color;
+ QPalette pal = d->control->palette();
+ pal.setColor(QPalette::Highlight, color);
+ d->control->setPalette(pal);
+ update();
+ emit selectionColorChanged(d->selectionColor);
+}
+
+/*!
+ \qmlproperty color TextEdit::selectedTextColor
+
+ The selected text color, used in selections.
+*/
+QColor QDeclarative1TextEdit::selectedTextColor() const
+{
+ Q_D(const QDeclarative1TextEdit);
+ return d->selectedTextColor;
+}
+
+void QDeclarative1TextEdit::setSelectedTextColor(const QColor &color)
+{
+ Q_D(QDeclarative1TextEdit);
+ if (d->selectedTextColor == color)
+ return;
+
+ clearCache();
+ d->selectedTextColor = color;
+ QPalette pal = d->control->palette();
+ pal.setColor(QPalette::HighlightedText, color);
+ d->control->setPalette(pal);
+ update();
+ emit selectedTextColorChanged(d->selectedTextColor);
+}
+
+/*!
+ \qmlproperty enumeration TextEdit::horizontalAlignment
+ \qmlproperty enumeration TextEdit::verticalAlignment
+ \qmlproperty enumeration TextEdit::effectiveHorizontalAlignment
+
+ Sets the horizontal and vertical alignment of the text within the TextEdit item's
+ width and height. By default, the text alignment follows the natural alignment
+ of the text, for example text that is read from left to right will be aligned to
+ the left.
+
+ Valid values for \c horizontalAlignment are:
+ \list
+ \o TextEdit.AlignLeft (default)
+ \o TextEdit.AlignRight
+ \o TextEdit.AlignHCenter
+ \o TextEdit.AlignJustify
+ \endlist
+
+ Valid values for \c verticalAlignment are:
+ \list
+ \o TextEdit.AlignTop (default)
+ \o TextEdit.AlignBottom
+ \o TextEdit.AlignVCenter
+ \endlist
+
+ When using the attached property LayoutMirroring::enabled to mirror application
+ layouts, the horizontal alignment of text will also be mirrored. However, the property
+ \c horizontalAlignment will remain unchanged. To query the effective horizontal alignment
+ of TextEdit, use the read-only property \c effectiveHorizontalAlignment.
+*/
+QDeclarative1TextEdit::HAlignment QDeclarative1TextEdit::hAlign() const
+{
+ Q_D(const QDeclarative1TextEdit);
+ return d->hAlign;
+}
+
+void QDeclarative1TextEdit::setHAlign(HAlignment align)
+{
+ Q_D(QDeclarative1TextEdit);
+ bool forceAlign = d->hAlignImplicit && d->effectiveLayoutMirror;
+ d->hAlignImplicit = false;
+ if (d->setHAlign(align, forceAlign) && isComponentComplete()) {
+ d->updateDefaultTextOption();
+ updateSize();
+ }
+}
+
+void QDeclarative1TextEdit::resetHAlign()
+{
+ Q_D(QDeclarative1TextEdit);
+ d->hAlignImplicit = true;
+ if (d->determineHorizontalAlignment() && isComponentComplete()) {
+ d->updateDefaultTextOption();
+ updateSize();
+ }
+}
+
+QDeclarative1TextEdit::HAlignment QDeclarative1TextEdit::effectiveHAlign() const
+{
+ Q_D(const QDeclarative1TextEdit);
+ QDeclarative1TextEdit::HAlignment effectiveAlignment = d->hAlign;
+ if (!d->hAlignImplicit && d->effectiveLayoutMirror) {
+ switch (d->hAlign) {
+ case QDeclarative1TextEdit::AlignLeft:
+ effectiveAlignment = QDeclarative1TextEdit::AlignRight;
+ break;
+ case QDeclarative1TextEdit::AlignRight:
+ effectiveAlignment = QDeclarative1TextEdit::AlignLeft;
+ break;
+ default:
+ break;
+ }
+ }
+ return effectiveAlignment;
+}
+
+bool QDeclarative1TextEditPrivate::setHAlign(QDeclarative1TextEdit::HAlignment alignment, bool forceAlign)
+{
+ Q_Q(QDeclarative1TextEdit);
+ if (hAlign != alignment || forceAlign) {
+ QDeclarative1TextEdit::HAlignment oldEffectiveHAlign = q->effectiveHAlign();
+ hAlign = alignment;
+ emit q->horizontalAlignmentChanged(alignment);
+ if (oldEffectiveHAlign != q->effectiveHAlign())
+ emit q->effectiveHorizontalAlignmentChanged();
+ return true;
+ }
+ return false;
+}
+
+bool QDeclarative1TextEditPrivate::determineHorizontalAlignment()
+{
+ Q_Q(QDeclarative1TextEdit);
+ if (hAlignImplicit && q->isComponentComplete()) {
+ bool alignToRight = text.isEmpty() ? QApplication::keyboardInputDirection() == Qt::RightToLeft : rightToLeftText;
+ return setHAlign(alignToRight ? QDeclarative1TextEdit::AlignRight : QDeclarative1TextEdit::AlignLeft);
+ }
+ return false;
+}
+
+void QDeclarative1TextEditPrivate::mirrorChange()
+{
+ Q_Q(QDeclarative1TextEdit);
+ if (q->isComponentComplete()) {
+ if (!hAlignImplicit && (hAlign == QDeclarative1TextEdit::AlignRight || hAlign == QDeclarative1TextEdit::AlignLeft)) {
+ updateDefaultTextOption();
+ q->updateSize();
+ emit q->effectiveHorizontalAlignmentChanged();
+ }
+ }
+}
+
+QDeclarative1TextEdit::VAlignment QDeclarative1TextEdit::vAlign() const
+{
+ Q_D(const QDeclarative1TextEdit);
+ return d->vAlign;
+}
+
+void QDeclarative1TextEdit::setVAlign(QDeclarative1TextEdit::VAlignment alignment)
+{
+ Q_D(QDeclarative1TextEdit);
+ if (alignment == d->vAlign)
+ return;
+ d->vAlign = alignment;
+ d->updateDefaultTextOption();
+ updateSize();
+ moveCursorDelegate();
+ emit verticalAlignmentChanged(d->vAlign);
+}
+
+/*!
+ \qmlproperty enumeration TextEdit::wrapMode
+
+ Set this property to wrap the text to the TextEdit item's width.
+ The text will only wrap if an explicit width has been set.
+
+ \list
+ \o TextEdit.NoWrap - no wrapping will be performed. If the text contains insufficient newlines, then implicitWidth will exceed a set width.
+ \o TextEdit.WordWrap - wrapping is done on word boundaries only. If a word is too long, implicitWidth will exceed a set width.
+ \o TextEdit.WrapAnywhere - wrapping is done at any point on a line, even if it occurs in the middle of a word.
+ \o TextEdit.Wrap - if possible, wrapping occurs at a word boundary; otherwise it will occur at the appropriate point on the line, even in the middle of a word.
+ \endlist
+
+ The default is TextEdit.NoWrap. If you set a width, consider using TextEdit.Wrap.
+*/
+QDeclarative1TextEdit::WrapMode QDeclarative1TextEdit::wrapMode() const
+{
+ Q_D(const QDeclarative1TextEdit);
+ return d->wrapMode;
+}
+
+void QDeclarative1TextEdit::setWrapMode(WrapMode mode)
+{
+ Q_D(QDeclarative1TextEdit);
+ if (mode == d->wrapMode)
+ return;
+ d->wrapMode = mode;
+ d->updateDefaultTextOption();
+ updateSize();
+ emit wrapModeChanged();
+}
+
+/*!
+ \qmlproperty int TextEdit::lineCount
+ \since Quick 1.1
+
+ Returns the total number of lines in the textEdit item.
+*/
+int QDeclarative1TextEdit::lineCount() const
+{
+ Q_D(const QDeclarative1TextEdit);
+ return d->lineCount;
+}
+
+/*!
+ \qmlproperty real TextEdit::paintedWidth
+
+ Returns the width of the text, including the width past the width
+ which is covered due to insufficient wrapping if \l wrapMode is set.
+*/
+qreal QDeclarative1TextEdit::paintedWidth() const
+{
+ Q_D(const QDeclarative1TextEdit);
+ return d->paintedSize.width();
+}
+
+/*!
+ \qmlproperty real TextEdit::paintedHeight
+
+ Returns the height of the text, including the height past the height
+ that is covered if the text does not fit within the set height.
+*/
+qreal QDeclarative1TextEdit::paintedHeight() const
+{
+ Q_D(const QDeclarative1TextEdit);
+ return d->paintedSize.height();
+}
+
+/*!
+ \qmlmethod rectangle TextEdit::positionToRectangle(position)
+
+ Returns the rectangle at the given \a position in the text. The x, y,
+ and height properties correspond to the cursor that would describe
+ that position.
+*/
+QRectF QDeclarative1TextEdit::positionToRectangle(int pos) const
+{
+ Q_D(const QDeclarative1TextEdit);
+ QTextCursor c(d->document);
+ c.setPosition(pos);
+ return d->control->cursorRect(c);
+
+}
+
+/*!
+ \qmlmethod int TextEdit::positionAt(int x, int y)
+
+ Returns the text position closest to pixel position (\a x, \a y).
+
+ Position 0 is before the first character, position 1 is after the first character
+ but before the second, and so on until position \l {text}.length, which is after all characters.
+*/
+int QDeclarative1TextEdit::positionAt(int x, int y) const
+{
+ Q_D(const QDeclarative1TextEdit);
+ int r = d->document->documentLayout()->hitTest(QPoint(x,y-d->yoff), Qt::FuzzyHit);
+ QTextCursor cursor = d->control->textCursor();
+ if (r > cursor.position()) {
+ // The cursor position includes positions within the preedit text, but only positions in the
+ // same text block are offset so it is possible to get a position that is either part of the
+ // preedit or the next text block.
+ QTextLayout *layout = cursor.block().layout();
+ const int preeditLength = layout
+ ? layout->preeditAreaText().length()
+ : 0;
+ if (preeditLength > 0
+ && d->document->documentLayout()->blockBoundingRect(cursor.block()).contains(x,y-d->yoff)) {
+ r = r > cursor.position() + preeditLength
+ ? r - preeditLength
+ : cursor.position();
+ }
+ }
+ return r;
+}
+
+void QDeclarative1TextEdit::moveCursorSelection(int pos)
+{
+ //Note that this is the same as setCursorPosition but with the KeepAnchor flag set
+ Q_D(QDeclarative1TextEdit);
+ QTextCursor cursor = d->control->textCursor();
+ if (cursor.position() == pos)
+ return;
+ cursor.setPosition(pos, QTextCursor::KeepAnchor);
+ d->control->setTextCursor(cursor);
+}
+
+/*!
+ \qmlmethod void TextEdit::moveCursorSelection(int position, SelectionMode mode = TextEdit.SelectCharacters)
+ \since Quick 1.1
+
+ Moves the cursor to \a position and updates the selection according to the optional \a mode
+ parameter. (To only move the cursor, set the \l cursorPosition property.)
+
+ When this method is called it additionally sets either the
+ selectionStart or the selectionEnd (whichever was at the previous cursor position)
+ to the specified position. This allows you to easily extend and contract the selected
+ text range.
+
+ The selection mode specifies whether the selection is updated on a per character or a per word
+ basis. If not specified the selection mode will default to TextEdit.SelectCharacters.
+
+ \list
+ \o TextEdit.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at
+ the previous cursor position) to the specified position.
+ \o TextEdit.SelectWords - Sets the selectionStart and selectionEnd to include all
+ words between the specified postion and the previous cursor position. Words partially in the
+ range are included.
+ \endlist
+
+ For example, take this sequence of calls:
+
+ \code
+ cursorPosition = 5
+ moveCursorSelection(9, TextEdit.SelectCharacters)
+ moveCursorSelection(7, TextEdit.SelectCharacters)
+ \endcode
+
+ This moves the cursor to position 5, extend the selection end from 5 to 9
+ and then retract the selection end from 9 to 7, leaving the text from position 5 to 7
+ selected (the 6th and 7th characters).
+
+ The same sequence with TextEdit.SelectWords will extend the selection start to a word boundary
+ before or on position 5 and extend the selection end to a word boundary on or past position 9.
+*/
+void QDeclarative1TextEdit::moveCursorSelection(int pos, SelectionMode mode)
+{
+ Q_D(QDeclarative1TextEdit);
+ QTextCursor cursor = d->control->textCursor();
+ if (cursor.position() == pos)
+ return;
+ if (mode == SelectCharacters) {
+ cursor.setPosition(pos, QTextCursor::KeepAnchor);
+ } else if (cursor.anchor() < pos || (cursor.anchor() == pos && cursor.position() < pos)) {
+ if (cursor.anchor() > cursor.position()) {
+ cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor);
+ cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::KeepAnchor);
+ if (cursor.position() == cursor.anchor())
+ cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::MoveAnchor);
+ else
+ cursor.setPosition(cursor.position(), QTextCursor::MoveAnchor);
+ } else {
+ cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor);
+ cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::MoveAnchor);
+ }
+
+ cursor.setPosition(pos, QTextCursor::KeepAnchor);
+ cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::KeepAnchor);
+ if (cursor.position() != pos)
+ cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
+ } else if (cursor.anchor() > pos || (cursor.anchor() == pos && cursor.position() > pos)) {
+ if (cursor.anchor() < cursor.position()) {
+ cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor);
+ cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::MoveAnchor);
+ } else {
+ cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor);
+ cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor);
+ cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
+ if (cursor.position() != cursor.anchor()) {
+ cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor);
+ cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::MoveAnchor);
+ }
+ }
+
+ cursor.setPosition(pos, QTextCursor::KeepAnchor);
+ cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
+ if (cursor.position() != pos) {
+ cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor);
+ cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::KeepAnchor);
+ }
+ }
+ d->control->setTextCursor(cursor);
+}
+
+/*!
+ \qmlproperty bool TextEdit::cursorVisible
+ If true the text edit shows a cursor.
+
+ This property is set and unset when the text edit gets active focus, but it can also
+ be set directly (useful, for example, if a KeyProxy might forward keys to it).
+*/
+bool QDeclarative1TextEdit::isCursorVisible() const
+{
+ Q_D(const QDeclarative1TextEdit);
+ return d->cursorVisible;
+}
+
+void QDeclarative1TextEdit::setCursorVisible(bool on)
+{
+ Q_D(QDeclarative1TextEdit);
+ if (d->cursorVisible == on)
+ return;
+ d->cursorVisible = on;
+ QFocusEvent focusEvent(on ? QEvent::FocusIn : QEvent::FocusOut);
+ if (!on && !d->persistentSelection)
+ d->control->setCursorIsFocusIndicator(true);
+ d->control->processEvent(&focusEvent, QPointF(0, -d->yoff));
+ emit cursorVisibleChanged(d->cursorVisible);
+}
+
+/*!
+ \qmlproperty int TextEdit::cursorPosition
+ The position of the cursor in the TextEdit.
+*/
+int QDeclarative1TextEdit::cursorPosition() const
+{
+ Q_D(const QDeclarative1TextEdit);
+ return d->control->textCursor().position();
+}
+
+void QDeclarative1TextEdit::setCursorPosition(int pos)
+{
+ Q_D(QDeclarative1TextEdit);
+ if (pos < 0 || pos > d->text.length())
+ return;
+ QTextCursor cursor = d->control->textCursor();
+ if (cursor.position() == pos && cursor.anchor() == pos)
+ return;
+ cursor.setPosition(pos);
+ d->control->setTextCursor(cursor);
+}
+
+/*!
+ \qmlproperty Component TextEdit::cursorDelegate
+ The delegate for the cursor in the TextEdit.
+
+ If you set a cursorDelegate for a TextEdit, this delegate will be used for
+ drawing the cursor instead of the standard cursor. An instance of the
+ delegate will be created and managed by the text edit when a cursor is
+ needed, and the x and y properties of delegate instance will be set so as
+ to be one pixel before the top left of the current character.
+
+ Note that the root item of the delegate component must be a QDeclarativeItem or
+ QDeclarativeItem derived item.
+*/
+QDeclarativeComponent* QDeclarative1TextEdit::cursorDelegate() const
+{
+ Q_D(const QDeclarative1TextEdit);
+ return d->cursorComponent;
+}
+
+void QDeclarative1TextEdit::setCursorDelegate(QDeclarativeComponent* c)
+{
+ Q_D(QDeclarative1TextEdit);
+ if(d->cursorComponent){
+ if(d->cursor){
+ d->control->setCursorWidth(-1);
+ dirtyCache(cursorRectangle());
+ delete d->cursor;
+ d->cursor = 0;
+ }
+ }
+ d->cursorComponent = c;
+ if(c && c->isReady()){
+ loadCursorDelegate();
+ }else{
+ if(c)
+ connect(c, SIGNAL(statusChanged()),
+ this, SLOT(loadCursorDelegate()));
+ }
+
+ emit cursorDelegateChanged();
+}
+
+void QDeclarative1TextEdit::loadCursorDelegate()
+{
+ Q_D(QDeclarative1TextEdit);
+ if(d->cursorComponent->isLoading())
+ return;
+ d->cursor = qobject_cast<QDeclarativeItem*>(d->cursorComponent->create(qmlContext(this)));
+ if(d->cursor){
+ d->control->setCursorWidth(0);
+ dirtyCache(cursorRectangle());
+ QDeclarative_setParent_noEvent(d->cursor, this);
+ d->cursor->setParentItem(this);
+ d->cursor->setHeight(QFontMetrics(d->font).height());
+ moveCursorDelegate();
+ }else{
+ qmlInfo(this) << "Error loading cursor delegate.";
+ }
+}
+
+/*!
+ \qmlproperty int TextEdit::selectionStart
+
+ The cursor position before the first character in the current selection.
+
+ This property is read-only. To change the selection, use select(start,end),
+ selectAll(), or selectWord().
+
+ \sa selectionEnd, cursorPosition, selectedText
+*/
+int QDeclarative1TextEdit::selectionStart() const
+{
+ Q_D(const QDeclarative1TextEdit);
+ return d->control->textCursor().selectionStart();
+}
+
+/*!
+ \qmlproperty int TextEdit::selectionEnd
+
+ The cursor position after the last character in the current selection.
+
+ This property is read-only. To change the selection, use select(start,end),
+ selectAll(), or selectWord().
+
+ \sa selectionStart, cursorPosition, selectedText
+*/
+int QDeclarative1TextEdit::selectionEnd() const
+{
+ Q_D(const QDeclarative1TextEdit);
+ return d->control->textCursor().selectionEnd();
+}
+
+/*!
+ \qmlproperty string TextEdit::selectedText
+
+ This read-only property provides the text currently selected in the
+ text edit.
+
+ It is equivalent to the following snippet, but is faster and easier
+ to use.
+ \code
+ //myTextEdit is the id of the TextEdit
+ myTextEdit.text.toString().substring(myTextEdit.selectionStart,
+ myTextEdit.selectionEnd);
+ \endcode
+*/
+QString QDeclarative1TextEdit::selectedText() const
+{
+ Q_D(const QDeclarative1TextEdit);
+ return d->control->textCursor().selectedText();
+}
+
+/*!
+ \qmlproperty bool TextEdit::activeFocusOnPress
+
+ Whether the TextEdit should gain active focus on a mouse press. By default this is
+ set to true.
+*/
+bool QDeclarative1TextEdit::focusOnPress() const
+{
+ Q_D(const QDeclarative1TextEdit);
+ return d->focusOnPress;
+}
+
+void QDeclarative1TextEdit::setFocusOnPress(bool on)
+{
+ Q_D(QDeclarative1TextEdit);
+ if (d->focusOnPress == on)
+ return;
+ d->focusOnPress = on;
+ emit activeFocusOnPressChanged(d->focusOnPress);
+}
+
+/*!
+ \qmlproperty bool TextEdit::persistentSelection
+
+ Whether the TextEdit should keep the selection visible when it loses active focus to another
+ item in the scene. By default this is set to true;
+*/
+bool QDeclarative1TextEdit::persistentSelection() const
+{
+ Q_D(const QDeclarative1TextEdit);
+ return d->persistentSelection;
+}
+
+void QDeclarative1TextEdit::setPersistentSelection(bool on)
+{
+ Q_D(QDeclarative1TextEdit);
+ if (d->persistentSelection == on)
+ return;
+ d->persistentSelection = on;
+ emit persistentSelectionChanged(d->persistentSelection);
+}
+
+/*
+ \qmlproperty real TextEdit::textMargin
+
+ The margin, in pixels, around the text in the TextEdit.
+*/
+qreal QDeclarative1TextEdit::textMargin() const
+{
+ Q_D(const QDeclarative1TextEdit);
+ return d->textMargin;
+}
+
+void QDeclarative1TextEdit::setTextMargin(qreal margin)
+{
+ Q_D(QDeclarative1TextEdit);
+ if (d->textMargin == margin)
+ return;
+ d->textMargin = margin;
+ d->document->setDocumentMargin(d->textMargin);
+ emit textMarginChanged(d->textMargin);
+}
+
+void QDeclarative1TextEdit::geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry)
+{
+ if (newGeometry.width() != oldGeometry.width())
+ updateSize();
+ QDeclarative1PaintedItem::geometryChanged(newGeometry, oldGeometry);
+}
+
+/*!
+ Ensures any delayed caching or data loading the class
+ needs to performed is complete.
+*/
+void QDeclarative1TextEdit::componentComplete()
+{
+ Q_D(QDeclarative1TextEdit);
+ QDeclarative1PaintedItem::componentComplete();
+ if (d->dirty) {
+ d->determineHorizontalAlignment();
+ d->updateDefaultTextOption();
+ updateSize();
+ d->dirty = false;
+ }
+}
+
+/*!
+ \qmlproperty bool TextEdit::selectByMouse
+
+ Defaults to false.
+
+ If true, the user can use the mouse to select text in some
+ platform-specific way. Note that for some platforms this may
+ not be an appropriate interaction (eg. may conflict with how
+ the text needs to behave inside a Flickable.
+*/
+bool QDeclarative1TextEdit::selectByMouse() const
+{
+ Q_D(const QDeclarative1TextEdit);
+ return d->selectByMouse;
+}
+
+void QDeclarative1TextEdit::setSelectByMouse(bool on)
+{
+ Q_D(QDeclarative1TextEdit);
+ if (d->selectByMouse != on) {
+ d->selectByMouse = on;
+ setKeepMouseGrab(on);
+ if (on)
+ setTextInteractionFlags(d->control->textInteractionFlags() | Qt::TextSelectableByMouse);
+ else
+ setTextInteractionFlags(d->control->textInteractionFlags() & ~Qt::TextSelectableByMouse);
+ emit selectByMouseChanged(on);
+ }
+}
+
+
+/*!
+ \qmlproperty enum TextEdit::mouseSelectionMode
+ \since Quick 1.1
+
+ Specifies how text should be selected using a mouse.
+
+ \list
+ \o TextEdit.SelectCharacters - The selection is updated with individual characters. (Default)
+ \o TextEdit.SelectWords - The selection is updated with whole words.
+ \endlist
+
+ This property only applies when \l selectByMouse is true.
+*/
+
+QDeclarative1TextEdit::SelectionMode QDeclarative1TextEdit::mouseSelectionMode() const
+{
+ Q_D(const QDeclarative1TextEdit);
+ return d->mouseSelectionMode;
+}
+
+void QDeclarative1TextEdit::setMouseSelectionMode(SelectionMode mode)
+{
+ Q_D(QDeclarative1TextEdit);
+ if (d->mouseSelectionMode != mode) {
+ d->mouseSelectionMode = mode;
+ d->control->setWordSelectionEnabled(mode == SelectWords);
+ emit mouseSelectionModeChanged(mode);
+ }
+}
+
+/*!
+ \qmlproperty bool TextEdit::readOnly
+
+ Whether the user can interact with the TextEdit item. If this
+ property is set to true the text cannot be edited by user interaction.
+
+ By default this property is false.
+*/
+void QDeclarative1TextEdit::setReadOnly(bool r)
+{
+ Q_D(QDeclarative1TextEdit);
+ if (r == isReadOnly())
+ return;
+
+ setFlag(QGraphicsItem::ItemAcceptsInputMethod, !r);
+
+ Qt::TextInteractionFlags flags = Qt::LinksAccessibleByMouse;
+ if (d->selectByMouse)
+ flags = flags | Qt::TextSelectableByMouse;
+ if (!r)
+ flags = flags | Qt::TextSelectableByKeyboard | Qt::TextEditable;
+ d->control->setTextInteractionFlags(flags);
+ if (!r)
+ d->control->moveCursor(QTextCursor::End);
+
+ emit readOnlyChanged(r);
+}
+
+bool QDeclarative1TextEdit::isReadOnly() const
+{
+ Q_D(const QDeclarative1TextEdit);
+ return !(d->control->textInteractionFlags() & Qt::TextEditable);
+}
+
+/*!
+ Sets how the text edit should interact with user input to the given
+ \a flags.
+*/
+void QDeclarative1TextEdit::setTextInteractionFlags(Qt::TextInteractionFlags flags)
+{
+ Q_D(QDeclarative1TextEdit);
+ d->control->setTextInteractionFlags(flags);
+}
+
+/*!
+ Returns the flags specifying how the text edit should interact
+ with user input.
+*/
+Qt::TextInteractionFlags QDeclarative1TextEdit::textInteractionFlags() const
+{
+ Q_D(const QDeclarative1TextEdit);
+ return d->control->textInteractionFlags();
+}
+
+/*!
+ \qmlproperty rectangle TextEdit::cursorRectangle
+
+ The rectangle where the text cursor is rendered
+ within the text edit. Read-only.
+*/
+QRect QDeclarative1TextEdit::cursorRectangle() const
+{
+ Q_D(const QDeclarative1TextEdit);
+ return d->control->cursorRect().toRect().translated(0,d->yoff);
+}
+
+
+/*!
+\overload
+Handles the given \a event.
+*/
+bool QDeclarative1TextEdit::event(QEvent *event)
+{
+ Q_D(QDeclarative1TextEdit);
+ if (event->type() == QEvent::ShortcutOverride) {
+ d->control->processEvent(event, QPointF(0, -d->yoff));
+ return event->isAccepted();
+ }
+ return QDeclarative1PaintedItem::event(event);
+}
+
+/*!
+\overload
+Handles the given key \a event.
+*/
+void QDeclarative1TextEdit::keyPressEvent(QKeyEvent *event)
+{
+ Q_D(QDeclarative1TextEdit);
+ keyPressPreHandler(event);
+ if (!event->isAccepted())
+ d->control->processEvent(event, QPointF(0, -d->yoff));
+ if (!event->isAccepted())
+ QDeclarative1PaintedItem::keyPressEvent(event);
+}
+
+/*!
+\overload
+Handles the given key \a event.
+*/
+void QDeclarative1TextEdit::keyReleaseEvent(QKeyEvent *event)
+{
+ Q_D(QDeclarative1TextEdit);
+ keyReleasePreHandler(event);
+ if (!event->isAccepted())
+ d->control->processEvent(event, QPointF(0, -d->yoff));
+ if (!event->isAccepted())
+ QDeclarative1PaintedItem::keyReleaseEvent(event);
+}
+
+void QDeclarative1TextEditPrivate::focusChanged(bool hasFocus)
+{
+ Q_Q(QDeclarative1TextEdit);
+ q->setCursorVisible(hasFocus && scene && scene->hasFocus());
+ QDeclarativeItemPrivate::focusChanged(hasFocus);
+}
+
+/*!
+ \qmlmethod void TextEdit::deselect()
+ \since Quick 1.1
+
+ Removes active text selection.
+*/
+void QDeclarative1TextEdit::deselect()
+{
+ Q_D(QDeclarative1TextEdit);
+ QTextCursor c = d->control->textCursor();
+ c.clearSelection();
+ d->control->setTextCursor(c);
+}
+
+/*!
+ \qmlmethod void TextEdit::selectAll()
+
+ Causes all text to be selected.
+*/
+void QDeclarative1TextEdit::selectAll()
+{
+ Q_D(QDeclarative1TextEdit);
+ d->control->selectAll();
+}
+
+/*!
+ \qmlmethod void TextEdit::selectWord()
+
+ Causes the word closest to the current cursor position to be selected.
+*/
+void QDeclarative1TextEdit::selectWord()
+{
+ Q_D(QDeclarative1TextEdit);
+ QTextCursor c = d->control->textCursor();
+ c.select(QTextCursor::WordUnderCursor);
+ d->control->setTextCursor(c);
+}
+
+/*!
+ \qmlmethod void TextEdit::select(int start, int end)
+
+ Causes the text from \a start to \a end to be selected.
+
+ If either start or end is out of range, the selection is not changed.
+
+ After calling this, selectionStart will become the lesser
+ and selectionEnd will become the greater (regardless of the order passed
+ to this method).
+
+ \sa selectionStart, selectionEnd
+*/
+void QDeclarative1TextEdit::select(int start, int end)
+{
+ Q_D(QDeclarative1TextEdit);
+ if (start < 0 || end < 0 || start > d->text.length() || end > d->text.length())
+ return;
+ QTextCursor cursor = d->control->textCursor();
+ cursor.beginEditBlock();
+ cursor.setPosition(start, QTextCursor::MoveAnchor);
+ cursor.setPosition(end, QTextCursor::KeepAnchor);
+ cursor.endEditBlock();
+ d->control->setTextCursor(cursor);
+
+ // QTBUG-11100
+ updateSelectionMarkers();
+}
+
+/*!
+ \qmlmethod void TextEdit::isRightToLeft(int start, int end)
+
+ Returns true if the natural reading direction of the editor text
+ found between positions \a start and \a end is right to left.
+*/
+bool QDeclarative1TextEdit::isRightToLeft(int start, int end)
+{
+ Q_D(QDeclarative1TextEdit);
+ if (start > end) {
+ qmlInfo(this) << "isRightToLeft(start, end) called with the end property being smaller than the start.";
+ return false;
+ } else {
+ return d->text.mid(start, end - start).isRightToLeft();
+ }
+}
+
+#ifndef QT_NO_CLIPBOARD
+/*!
+ \qmlmethod TextEdit::cut()
+
+ Moves the currently selected text to the system clipboard.
+*/
+void QDeclarative1TextEdit::cut()
+{
+ Q_D(QDeclarative1TextEdit);
+ d->control->cut();
+}
+
+/*!
+ \qmlmethod TextEdit::copy()
+
+ Copies the currently selected text to the system clipboard.
+*/
+void QDeclarative1TextEdit::copy()
+{
+ Q_D(QDeclarative1TextEdit);
+ d->control->copy();
+}
+
+/*!
+ \qmlmethod TextEdit::paste()
+
+ Replaces the currently selected text by the contents of the system clipboard.
+*/
+void QDeclarative1TextEdit::paste()
+{
+ Q_D(QDeclarative1TextEdit);
+ d->control->paste();
+}
+#endif // QT_NO_CLIPBOARD
+
+/*!
+\overload
+Handles the given mouse \a event.
+*/
+void QDeclarative1TextEdit::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QDeclarative1TextEdit);
+ if (d->focusOnPress){
+ bool hadActiveFocus = hasActiveFocus();
+ forceActiveFocus();
+ if (d->showInputPanelOnFocus) {
+ if (hasActiveFocus() && hadActiveFocus && !isReadOnly()) {
+ // re-open input panel on press if already focused
+ openSoftwareInputPanel();
+ }
+ } else { // show input panel on click
+ if (hasActiveFocus() && !hadActiveFocus) {
+ d->clickCausedFocus = true;
+ }
+ }
+ }
+
+ d->control->processEvent(event, QPointF(0, -d->yoff));
+ if (!event->isAccepted())
+ QDeclarative1PaintedItem::mousePressEvent(event);
+}
+
+/*!
+\overload
+Handles the given mouse \a event.
+*/
+void QDeclarative1TextEdit::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QDeclarative1TextEdit);
+ d->control->processEvent(event, QPointF(0, -d->yoff));
+ if (!d->showInputPanelOnFocus) { // input panel on click
+ if (d->focusOnPress && !isReadOnly() && boundingRect().contains(event->pos())) {
+ if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
+ if (view->scene() && view->scene() == scene()) {
+ qt_widget_private(view)->handleSoftwareInputPanel(event->button(), d->clickCausedFocus);
+ }
+ }
+ }
+ }
+ d->clickCausedFocus = false;
+
+ if (!event->isAccepted())
+ QDeclarative1PaintedItem::mouseReleaseEvent(event);
+}
+
+/*!
+\overload
+Handles the given mouse \a event.
+*/
+void QDeclarative1TextEdit::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QDeclarative1TextEdit);
+
+ d->control->processEvent(event, QPointF(0, -d->yoff));
+ if (!event->isAccepted())
+ QDeclarative1PaintedItem::mouseDoubleClickEvent(event);
+
+}
+
+/*!
+\overload
+Handles the given mouse \a event.
+*/
+void QDeclarative1TextEdit::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QDeclarative1TextEdit);
+ d->control->processEvent(event, QPointF(0, -d->yoff));
+ if (!event->isAccepted())
+ QDeclarative1PaintedItem::mouseMoveEvent(event);
+}
+
+/*!
+\overload
+Handles the given input method \a event.
+*/
+void QDeclarative1TextEdit::inputMethodEvent(QInputMethodEvent *event)
+{
+ Q_D(QDeclarative1TextEdit);
+ const bool wasComposing = isInputMethodComposing();
+ d->control->processEvent(event, QPointF(0, -d->yoff));
+ if (wasComposing != isInputMethodComposing())
+ emit inputMethodComposingChanged();
+}
+
+/*!
+\overload
+Returns the value of the given \a property.
+*/
+QVariant QDeclarative1TextEdit::inputMethodQuery(Qt::InputMethodQuery property) const
+{
+ Q_D(const QDeclarative1TextEdit);
+ return d->control->inputMethodQuery(property);
+}
+
+/*!
+Draws the contents of the text edit using the given \a painter within
+the given \a bounds.
+*/
+void QDeclarative1TextEdit::drawContents(QPainter *painter, const QRect &bounds)
+{
+ Q_D(QDeclarative1TextEdit);
+
+ painter->setRenderHint(QPainter::TextAntialiasing, true);
+ painter->translate(0,d->yoff);
+
+ d->control->drawContents(painter, bounds.translated(0,-d->yoff));
+
+ painter->translate(0,-d->yoff);
+}
+
+void QDeclarative1TextEdit::updateImgCache(const QRectF &rf)
+{
+ Q_D(const QDeclarative1TextEdit);
+ QRect r;
+ if (!rf.isValid()) {
+ r = QRect(0,0,INT_MAX,INT_MAX);
+ } else {
+ r = rf.toRect();
+ if (r.height() > INT_MAX/2) {
+ // Take care of overflow when translating "everything"
+ r.setTop(r.y() + d->yoff);
+ r.setBottom(INT_MAX/2);
+ } else {
+ r = r.translated(0,d->yoff);
+ }
+ }
+ dirtyCache(r);
+ emit update();
+}
+
+/*!
+ \qmlproperty bool TextEdit::smooth
+
+ This property holds whether the text is smoothly scaled or transformed.
+
+ Smooth filtering gives better visual quality, but is slower. If
+ the item is displayed at its natural size, this property has no visual or
+ performance effect.
+
+ \note Generally scaling artifacts are only visible if the item is stationary on
+ the screen. A common pattern when animating an item is to disable smooth
+ filtering at the beginning of the animation and reenable it at the conclusion.
+*/
+
+/*!
+ \qmlproperty bool TextEdit::canPaste
+ \since QtQuick 1.1
+
+ Returns true if the TextEdit is writable and the content of the clipboard is
+ suitable for pasting into the TextEdit.
+*/
+bool QDeclarative1TextEdit::canPaste() const
+{
+ Q_D(const QDeclarative1TextEdit);
+ return d->canPaste;
+}
+
+/*!
+ \qmlproperty bool TextEdit::inputMethodComposing
+
+ \since QtQuick 1.1
+
+ This property holds whether the TextEdit has partial text input from an
+ input method.
+
+ While it is composing an input method may rely on mouse or key events from
+ the TextEdit to edit or commit the partial text. This property can be used
+ to determine when to disable events handlers that may interfere with the
+ correct operation of an input method.
+*/
+bool QDeclarative1TextEdit::isInputMethodComposing() const
+{
+ Q_D(const QDeclarative1TextEdit);
+ if (QTextLayout *layout = d->control->textCursor().block().layout())
+ return layout->preeditAreaText().length() > 0;
+ return false;
+}
+
+void QDeclarative1TextEditPrivate::init()
+{
+ Q_Q(QDeclarative1TextEdit);
+
+ q->setSmooth(smooth);
+ q->setAcceptedMouseButtons(Qt::LeftButton);
+ q->setFlag(QGraphicsItem::ItemHasNoContents, false);
+ q->setFlag(QGraphicsItem::ItemAcceptsInputMethod);
+
+ control = new QTextControl(q);
+ control->setIgnoreUnusedNavigationEvents(true);
+ control->setTextInteractionFlags(Qt::TextInteractionFlags(Qt::LinksAccessibleByMouse | Qt::TextSelectableByKeyboard | Qt::TextEditable));
+ control->setDragEnabled(false);
+
+ // QTextControl follows the default text color
+ // defined by the platform, declarative text
+ // should be black by default
+ QPalette pal = control->palette();
+ if (pal.color(QPalette::Text) != color) {
+ pal.setColor(QPalette::Text, color);
+ control->setPalette(pal);
+ }
+
+ QObject::connect(control, SIGNAL(updateRequest(QRectF)), q, SLOT(updateImgCache(QRectF)));
+
+ QObject::connect(control, SIGNAL(textChanged()), q, SLOT(q_textChanged()));
+ QObject::connect(control, SIGNAL(selectionChanged()), q, SIGNAL(selectionChanged()));
+ QObject::connect(control, SIGNAL(selectionChanged()), q, SLOT(updateSelectionMarkers()));
+ QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SLOT(updateSelectionMarkers()));
+ QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SIGNAL(cursorPositionChanged()));
+ QObject::connect(control, SIGNAL(microFocusChanged()), q, SLOT(moveCursorDelegate()));
+ QObject::connect(control, SIGNAL(linkActivated(QString)), q, SIGNAL(linkActivated(QString)));
+#ifndef QT_NO_CLIPBOARD
+ QObject::connect(q, SIGNAL(readOnlyChanged(bool)), q, SLOT(q_canPasteChanged()));
+ QObject::connect(QApplication::clipboard(), SIGNAL(dataChanged()), q, SLOT(q_canPasteChanged()));
+ canPaste = control->canPaste();
+#endif
+
+ document = control->document();
+ document->setDefaultFont(font);
+ document->setDocumentMargin(textMargin);
+ document->setUndoRedoEnabled(false); // flush undo buffer.
+ document->setUndoRedoEnabled(true);
+ updateDefaultTextOption();
+}
+
+void QDeclarative1TextEdit::q_textChanged()
+{
+ Q_D(QDeclarative1TextEdit);
+ d->text = text();
+ d->rightToLeftText = d->document->begin().layout()->engine()->isRightToLeft();
+ d->determineHorizontalAlignment();
+ d->updateDefaultTextOption();
+ updateSize();
+ updateTotalLines();
+ emit textChanged(d->text);
+}
+
+void QDeclarative1TextEdit::moveCursorDelegate()
+{
+ Q_D(QDeclarative1TextEdit);
+ updateMicroFocus();
+ emit cursorRectangleChanged();
+ if(!d->cursor)
+ return;
+ QRectF cursorRect = cursorRectangle();
+ d->cursor->setX(cursorRect.x());
+ d->cursor->setY(cursorRect.y());
+}
+
+void QDeclarative1TextEditPrivate::updateSelection()
+{
+ Q_Q(QDeclarative1TextEdit);
+ QTextCursor cursor = control->textCursor();
+ bool startChange = (lastSelectionStart != cursor.selectionStart());
+ bool endChange = (lastSelectionEnd != cursor.selectionEnd());
+ cursor.beginEditBlock();
+ cursor.setPosition(lastSelectionStart, QTextCursor::MoveAnchor);
+ cursor.setPosition(lastSelectionEnd, QTextCursor::KeepAnchor);
+ cursor.endEditBlock();
+ control->setTextCursor(cursor);
+ if(startChange)
+ q->selectionStartChanged();
+ if(endChange)
+ q->selectionEndChanged();
+}
+
+void QDeclarative1TextEdit::updateSelectionMarkers()
+{
+ Q_D(QDeclarative1TextEdit);
+ if(d->lastSelectionStart != d->control->textCursor().selectionStart()){
+ d->lastSelectionStart = d->control->textCursor().selectionStart();
+ emit selectionStartChanged();
+ }
+ if(d->lastSelectionEnd != d->control->textCursor().selectionEnd()){
+ d->lastSelectionEnd = d->control->textCursor().selectionEnd();
+ emit selectionEndChanged();
+ }
+}
+
+QRectF QDeclarative1TextEdit::boundingRect() const
+{
+ Q_D(const QDeclarative1TextEdit);
+ QRectF r = QDeclarative1PaintedItem::boundingRect();
+ int cursorWidth = 1;
+ if(d->cursor)
+ cursorWidth = d->cursor->width();
+ if(!d->document->isEmpty())
+ cursorWidth += 3;// ### Need a better way of accounting for space between char and cursor
+
+ // Could include font max left/right bearings to either side of rectangle.
+
+ r.setRight(r.right() + cursorWidth);
+ return r.translated(0,d->yoff);
+}
+
+qreal QDeclarative1TextEditPrivate::implicitWidth() const
+{
+ Q_Q(const QDeclarative1TextEdit);
+ if (!requireImplicitWidth) {
+ // We don't calculate implicitWidth unless it is required.
+ // We need to force a size update now to ensure implicitWidth is calculated
+ const_cast<QDeclarative1TextEditPrivate*>(this)->requireImplicitWidth = true;
+ const_cast<QDeclarative1TextEdit*>(q)->updateSize();
+ }
+ return mImplicitWidth;
+}
+
+//### we should perhaps be a bit smarter here -- depending on what has changed, we shouldn't
+// need to do all the calculations each time
+void QDeclarative1TextEdit::updateSize()
+{
+ Q_D(QDeclarative1TextEdit);
+ if (isComponentComplete()) {
+ qreal naturalWidth = d->mImplicitWidth;
+ // ### assumes that if the width is set, the text will fill to edges
+ // ### (unless wrap is false, then clipping will occur)
+ if (widthValid()) {
+ if (!d->requireImplicitWidth) {
+ emit implicitWidthChanged();
+ // if the implicitWidth is used, then updateSize() has already been called (recursively)
+ if (d->requireImplicitWidth)
+ return;
+ }
+ if (d->requireImplicitWidth) {
+ d->document->setTextWidth(-1);
+ naturalWidth = d->document->idealWidth();
+ }
+ if (d->document->textWidth() != width())
+ d->document->setTextWidth(width());
+ } else {
+ d->document->setTextWidth(-1);
+ }
+ QFontMetrics fm = QFontMetrics(d->font);
+ int dy = height();
+ dy -= (int)d->document->size().height();
+
+ int nyoff;
+ if (heightValid()) {
+ if (d->vAlign == AlignBottom)
+ nyoff = dy;
+ else if (d->vAlign == AlignVCenter)
+ nyoff = dy/2;
+ else
+ nyoff = 0;
+ } else {
+ nyoff = 0;
+ }
+ if (nyoff != d->yoff) {
+ prepareGeometryChange();
+ d->yoff = nyoff;
+ }
+ setBaselineOffset(fm.ascent() + d->yoff + d->textMargin);
+
+ //### need to comfirm cost of always setting these
+ int newWidth = qCeil(d->document->idealWidth());
+ if (!widthValid() && d->document->textWidth() != newWidth)
+ d->document->setTextWidth(newWidth); // ### Text does not align if width is not set (QTextDoc bug)
+ // ### Setting the implicitWidth triggers another updateSize(), and unless there are bindings nothing has changed.
+ if (!widthValid())
+ setImplicitWidth(newWidth);
+ else if (d->requireImplicitWidth)
+ setImplicitWidth(naturalWidth);
+ qreal newHeight = d->document->isEmpty() ? fm.height() : (int)d->document->size().height();
+ setImplicitHeight(newHeight);
+
+ d->paintedSize = QSize(newWidth, newHeight);
+ setContentsSize(d->paintedSize);
+ emit paintedSizeChanged();
+ } else {
+ d->dirty = true;
+ }
+ emit update();
+}
+
+void QDeclarative1TextEdit::updateTotalLines()
+{
+ Q_D(QDeclarative1TextEdit);
+
+ int subLines = 0;
+
+ for (QTextBlock it = d->document->begin(); it != d->document->end(); it = it.next()) {
+ QTextLayout *layout = it.layout();
+ if (!layout)
+ continue;
+ subLines += layout->lineCount()-1;
+ }
+
+ int newTotalLines = d->document->lineCount() + subLines;
+ if (d->lineCount != newTotalLines) {
+ d->lineCount = newTotalLines;
+ emit lineCountChanged();
+ }
+}
+
+void QDeclarative1TextEditPrivate::updateDefaultTextOption()
+{
+ Q_Q(QDeclarative1TextEdit);
+ QTextOption opt = document->defaultTextOption();
+ int oldAlignment = opt.alignment();
+
+ QDeclarative1TextEdit::HAlignment horizontalAlignment = q->effectiveHAlign();
+ if (rightToLeftText) {
+ if (horizontalAlignment == QDeclarative1TextEdit::AlignLeft)
+ horizontalAlignment = QDeclarative1TextEdit::AlignRight;
+ else if (horizontalAlignment == QDeclarative1TextEdit::AlignRight)
+ horizontalAlignment = QDeclarative1TextEdit::AlignLeft;
+ }
+ opt.setAlignment((Qt::Alignment)(int)(horizontalAlignment | vAlign));
+
+ QTextOption::WrapMode oldWrapMode = opt.wrapMode();
+ opt.setWrapMode(QTextOption::WrapMode(wrapMode));
+
+ if (oldWrapMode == opt.wrapMode() && oldAlignment == opt.alignment())
+ return;
+ document->setDefaultTextOption(opt);
+}
+
+
+/*!
+ \qmlmethod void TextEdit::openSoftwareInputPanel()
+
+ Opens software input panels like virtual keyboards for typing, useful for
+ customizing when you want the input keyboard to be shown and hidden in
+ your application.
+
+ By default the opening of input panels follows the platform style. On Symbian^1 and
+ Symbian^3 -based devices the panels are opened by clicking TextEdit. On other platforms
+ the panels are automatically opened when TextEdit element gains active focus. Input panels are
+ always closed if no editor has active focus.
+
+ You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
+ and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
+ the behavior you want.
+
+ Only relevant on platforms, which provide virtual keyboards.
+
+ \code
+ import QtQuick 1.0
+ TextEdit {
+ id: textEdit
+ text: "Hello world!"
+ activeFocusOnPress: false
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ if (!textEdit.activeFocus) {
+ textEdit.forceActiveFocus();
+ textEdit.openSoftwareInputPanel();
+ } else {
+ textEdit.focus = false;
+ }
+ }
+ onPressAndHold: textEdit.closeSoftwareInputPanel();
+ }
+ }
+ \endcode
+*/
+void QDeclarative1TextEdit::openSoftwareInputPanel()
+{
+ QEvent event(QEvent::RequestSoftwareInputPanel);
+ if (qApp) {
+ if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
+ if (view->scene() && view->scene() == scene()) {
+ QApplication::sendEvent(view, &event);
+ }
+ }
+ }
+}
+
+/*!
+ \qmlmethod void TextEdit::closeSoftwareInputPanel()
+
+ Closes a software input panel like a virtual keyboard shown on the screen, useful
+ for customizing when you want the input keyboard to be shown and hidden in
+ your application.
+
+ By default the opening of input panels follows the platform style. On Symbian^1 and
+ Symbian^3 -based devices the panels are opened by clicking TextEdit. On other platforms
+ the panels are automatically opened when TextEdit element gains active focus. Input panels are
+ always closed if no editor has active focus.
+
+ You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
+ and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
+ the behavior you want.
+
+ Only relevant on platforms, which provide virtual keyboards.
+
+ \code
+ import QtQuick 1.0
+ TextEdit {
+ id: textEdit
+ text: "Hello world!"
+ activeFocusOnPress: false
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ if (!textEdit.activeFocus) {
+ textEdit.forceActiveFocus();
+ textEdit.openSoftwareInputPanel();
+ } else {
+ textEdit.focus = false;
+ }
+ }
+ onPressAndHold: textEdit.closeSoftwareInputPanel();
+ }
+ }
+ \endcode
+*/
+void QDeclarative1TextEdit::closeSoftwareInputPanel()
+{
+ QEvent event(QEvent::CloseSoftwareInputPanel);
+ if (qApp) {
+ if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
+ if (view->scene() && view->scene() == scene()) {
+ QApplication::sendEvent(view, &event);
+ }
+ }
+ }
+}
+
+void QDeclarative1TextEdit::focusInEvent(QFocusEvent *event)
+{
+ Q_D(const QDeclarative1TextEdit);
+ if (d->showInputPanelOnFocus) {
+ if (d->focusOnPress && !isReadOnly()) {
+ openSoftwareInputPanel();
+ }
+ }
+ QDeclarative1PaintedItem::focusInEvent(event);
+}
+
+void QDeclarative1TextEdit::q_canPasteChanged()
+{
+ Q_D(QDeclarative1TextEdit);
+ bool old = d->canPaste;
+ d->canPaste = d->control->canPaste();
+ if(old!=d->canPaste)
+ emit canPasteChanged();
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/graphicsitems/qdeclarativetextedit_p.h b/src/qtquick1/graphicsitems/qdeclarativetextedit_p.h
new file mode 100644
index 0000000000..712d2f079f
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativetextedit_p.h
@@ -0,0 +1,307 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVETEXTEDIT_H
+#define QDECLARATIVETEXTEDIT_H
+
+#include "private/qdeclarativetext_p.h"
+#include "private/qdeclarativeimplicitsizeitem_p.h"
+
+#include <QtGui/qtextdocument.h>
+#include <QtGui/qtextoption.h>
+#include <QtGui/qtextcursor.h>
+#include <QtGui/qtextformat.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+
+class QDeclarative1TextEditPrivate;
+class Q_AUTOTEST_EXPORT QDeclarative1TextEdit : public QDeclarative1ImplicitSizePaintedItem
+{
+ Q_OBJECT
+ Q_ENUMS(VAlignment)
+ Q_ENUMS(HAlignment)
+ Q_ENUMS(TextFormat)
+ Q_ENUMS(WrapMode)
+ Q_ENUMS(SelectionMode)
+
+ Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
+ Q_PROPERTY(QColor selectionColor READ selectionColor WRITE setSelectionColor NOTIFY selectionColorChanged)
+ Q_PROPERTY(QColor selectedTextColor READ selectedTextColor WRITE setSelectedTextColor NOTIFY selectedTextColorChanged)
+ Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged)
+ Q_PROPERTY(HAlignment horizontalAlignment READ hAlign WRITE setHAlign RESET resetHAlign NOTIFY horizontalAlignmentChanged)
+ Q_PROPERTY(HAlignment effectiveHorizontalAlignment READ effectiveHAlign NOTIFY effectiveHorizontalAlignmentChanged REVISION 1)
+ Q_PROPERTY(VAlignment verticalAlignment READ vAlign WRITE setVAlign NOTIFY verticalAlignmentChanged)
+ Q_PROPERTY(WrapMode wrapMode READ wrapMode WRITE setWrapMode NOTIFY wrapModeChanged)
+ Q_PROPERTY(int lineCount READ lineCount NOTIFY lineCountChanged REVISION 1)
+ Q_PROPERTY(qreal paintedWidth READ paintedWidth NOTIFY paintedSizeChanged)
+ Q_PROPERTY(qreal paintedHeight READ paintedHeight NOTIFY paintedSizeChanged)
+ Q_PROPERTY(TextFormat textFormat READ textFormat WRITE setTextFormat NOTIFY textFormatChanged)
+ Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly NOTIFY readOnlyChanged)
+ Q_PROPERTY(bool cursorVisible READ isCursorVisible WRITE setCursorVisible NOTIFY cursorVisibleChanged)
+ Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition NOTIFY cursorPositionChanged)
+ Q_PROPERTY(QRect cursorRectangle READ cursorRectangle NOTIFY cursorRectangleChanged)
+ Q_PROPERTY(QDeclarativeComponent* cursorDelegate READ cursorDelegate WRITE setCursorDelegate NOTIFY cursorDelegateChanged)
+ Q_PROPERTY(int selectionStart READ selectionStart NOTIFY selectionStartChanged)
+ Q_PROPERTY(int selectionEnd READ selectionEnd NOTIFY selectionEndChanged)
+ Q_PROPERTY(QString selectedText READ selectedText NOTIFY selectionChanged)
+ Q_PROPERTY(bool activeFocusOnPress READ focusOnPress WRITE setFocusOnPress NOTIFY activeFocusOnPressChanged)
+ Q_PROPERTY(bool persistentSelection READ persistentSelection WRITE setPersistentSelection NOTIFY persistentSelectionChanged)
+ Q_PROPERTY(qreal textMargin READ textMargin WRITE setTextMargin NOTIFY textMarginChanged)
+ Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ inputMethodHints WRITE setInputMethodHints)
+ Q_PROPERTY(bool selectByMouse READ selectByMouse WRITE setSelectByMouse NOTIFY selectByMouseChanged)
+ Q_PROPERTY(SelectionMode mouseSelectionMode READ mouseSelectionMode WRITE setMouseSelectionMode NOTIFY mouseSelectionModeChanged REVISION 1)
+ Q_PROPERTY(bool canPaste READ canPaste NOTIFY canPasteChanged REVISION 1)
+ Q_PROPERTY(bool inputMethodComposing READ isInputMethodComposing NOTIFY inputMethodComposingChanged REVISION 1)
+
+public:
+ QDeclarative1TextEdit(QDeclarativeItem *parent=0);
+
+ enum HAlignment {
+ AlignLeft = Qt::AlignLeft,
+ AlignRight = Qt::AlignRight,
+ AlignHCenter = Qt::AlignHCenter,
+ AlignJustify = Qt::AlignJustify // ### VERSIONING: Only in QtQuick 1.1
+ };
+
+ enum VAlignment {
+ AlignTop = Qt::AlignTop,
+ AlignBottom = Qt::AlignBottom,
+ AlignVCenter = Qt::AlignVCenter
+ };
+
+ enum TextFormat {
+ PlainText = Qt::PlainText,
+ RichText = Qt::RichText,
+ AutoText = Qt::AutoText
+ };
+
+ enum WrapMode { NoWrap = QTextOption::NoWrap,
+ WordWrap = QTextOption::WordWrap,
+ WrapAnywhere = QTextOption::WrapAnywhere,
+ WrapAtWordBoundaryOrAnywhere = QTextOption::WrapAtWordBoundaryOrAnywhere, // COMPAT
+ Wrap = QTextOption::WrapAtWordBoundaryOrAnywhere
+ };
+
+ enum SelectionMode {
+ SelectCharacters,
+ SelectWords
+ };
+
+ Q_INVOKABLE void openSoftwareInputPanel();
+ Q_INVOKABLE void closeSoftwareInputPanel();
+
+ QString text() const;
+ void setText(const QString &);
+
+ TextFormat textFormat() const;
+ void setTextFormat(TextFormat format);
+
+ QFont font() const;
+ void setFont(const QFont &font);
+
+ QColor color() const;
+ void setColor(const QColor &c);
+
+ QColor selectionColor() const;
+ void setSelectionColor(const QColor &c);
+
+ QColor selectedTextColor() const;
+ void setSelectedTextColor(const QColor &c);
+
+ HAlignment hAlign() const;
+ void setHAlign(HAlignment align);
+ void resetHAlign();
+ HAlignment effectiveHAlign() const;
+
+ VAlignment vAlign() const;
+ void setVAlign(VAlignment align);
+
+ WrapMode wrapMode() const;
+ void setWrapMode(WrapMode w);
+
+ int lineCount() const;
+
+ bool isCursorVisible() const;
+ void setCursorVisible(bool on);
+
+ int cursorPosition() const;
+ void setCursorPosition(int pos);
+
+ QDeclarativeComponent* cursorDelegate() const;
+ void setCursorDelegate(QDeclarativeComponent*);
+
+ int selectionStart() const;
+ int selectionEnd() const;
+
+ QString selectedText() const;
+
+ bool focusOnPress() const;
+ void setFocusOnPress(bool on);
+
+ bool persistentSelection() const;
+ void setPersistentSelection(bool on);
+
+ qreal textMargin() const;
+ void setTextMargin(qreal margin);
+
+ bool selectByMouse() const;
+ void setSelectByMouse(bool);
+
+ SelectionMode mouseSelectionMode() const;
+ void setMouseSelectionMode(SelectionMode mode);
+
+ bool canPaste() const;
+
+ virtual void componentComplete();
+
+ /* FROM EDIT */
+ void setReadOnly(bool);
+ bool isReadOnly() const;
+
+ void setTextInteractionFlags(Qt::TextInteractionFlags flags);
+ Qt::TextInteractionFlags textInteractionFlags() const;
+
+ QRect cursorRectangle() const;
+
+ QVariant inputMethodQuery(Qt::InputMethodQuery property) const;
+
+ qreal paintedWidth() const;
+ qreal paintedHeight() const;
+
+ Q_INVOKABLE QRectF positionToRectangle(int) const;
+ Q_INVOKABLE int positionAt(int x, int y) const;
+ Q_INVOKABLE void moveCursorSelection(int pos);
+ Q_INVOKABLE Q_REVISION(1) void moveCursorSelection(int pos, SelectionMode mode);
+
+ QRectF boundingRect() const;
+
+ bool isInputMethodComposing() const;
+
+Q_SIGNALS:
+ void textChanged(const QString &);
+ void paintedSizeChanged();
+ void cursorPositionChanged();
+ void cursorRectangleChanged();
+ void selectionStartChanged();
+ void selectionEndChanged();
+ void selectionChanged();
+ void colorChanged(const QColor &color);
+ void selectionColorChanged(const QColor &color);
+ void selectedTextColorChanged(const QColor &color);
+ void fontChanged(const QFont &font);
+ void horizontalAlignmentChanged(HAlignment alignment);
+ void verticalAlignmentChanged(VAlignment alignment);
+ void wrapModeChanged();
+ void lineCountChanged();
+ void textFormatChanged(TextFormat textFormat);
+ void readOnlyChanged(bool isReadOnly);
+ void cursorVisibleChanged(bool isCursorVisible);
+ void cursorDelegateChanged();
+ void activeFocusOnPressChanged(bool activeFocusOnPressed);
+ void persistentSelectionChanged(bool isPersistentSelection);
+ void textMarginChanged(qreal textMargin);
+ void selectByMouseChanged(bool selectByMouse);
+ Q_REVISION(1) void mouseSelectionModeChanged(SelectionMode mode);
+ Q_REVISION(1) void linkActivated(const QString &link);
+ Q_REVISION(1) void canPasteChanged();
+ Q_REVISION(1) void inputMethodComposingChanged();
+ Q_REVISION(1) void effectiveHorizontalAlignmentChanged();
+
+public Q_SLOTS:
+ void selectAll();
+ void selectWord();
+ void select(int start, int end);
+ Q_REVISION(1) void deselect();
+ Q_REVISION(1) bool isRightToLeft(int start, int end);
+#ifndef QT_NO_CLIPBOARD
+ void cut();
+ void copy();
+ void paste();
+#endif
+
+private Q_SLOTS:
+ void updateImgCache(const QRectF &rect);
+ void q_textChanged();
+ void updateSelectionMarkers();
+ void moveCursorDelegate();
+ void loadCursorDelegate();
+ void q_canPasteChanged();
+
+private:
+ void updateSize();
+ void updateTotalLines();
+
+protected:
+ virtual void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry);
+
+ bool event(QEvent *);
+ void keyPressEvent(QKeyEvent *);
+ void keyReleaseEvent(QKeyEvent *);
+ void focusInEvent(QFocusEvent *event);
+
+ // mouse filter?
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+ void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+
+ void inputMethodEvent(QInputMethodEvent *e);
+
+ void drawContents(QPainter *, const QRect &);
+private:
+ Q_DISABLE_COPY(QDeclarative1TextEdit)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarative1TextEdit)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1TextEdit)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/qtquick1/graphicsitems/qdeclarativetextedit_p_p.h b/src/qtquick1/graphicsitems/qdeclarativetextedit_p_p.h
new file mode 100644
index 0000000000..b370d5aeaa
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativetextedit_p_p.h
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVETEXTEDIT_P_H
+#define QDECLARATIVETEXTEDIT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qdeclarativeitem.h"
+#include "private/qdeclarativeimplicitsizeitem_p_p.h"
+
+#include <QtDeclarative/qdeclarative.h>
+
+QT_BEGIN_NAMESPACE
+
+class QTextLayout;
+class QTextDocument;
+class QTextControl;
+class QDeclarative1TextEditPrivate : public QDeclarative1ImplicitSizePaintedItemPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1TextEdit)
+
+public:
+ QDeclarative1TextEditPrivate()
+ : color("black"), hAlign(QDeclarative1TextEdit::AlignLeft), vAlign(QDeclarative1TextEdit::AlignTop),
+ imgDirty(true), dirty(false), richText(false), cursorVisible(false), focusOnPress(true),
+ showInputPanelOnFocus(true), clickCausedFocus(false), persistentSelection(true), requireImplicitWidth(false),
+ hAlignImplicit(true), rightToLeftText(false), textMargin(0.0), lastSelectionStart(0), lastSelectionEnd(0),
+ cursorComponent(0), cursor(0), format(QDeclarative1TextEdit::AutoText), document(0), wrapMode(QDeclarative1TextEdit::NoWrap),
+ mouseSelectionMode(QDeclarative1TextEdit::SelectCharacters), selectByMouse(false), canPaste(false),
+ yoff(0)
+ {
+#ifdef Q_OS_SYMBIAN
+ if (QSysInfo::symbianVersion() == QSysInfo::SV_SF_1 || QSysInfo::symbianVersion() == QSysInfo::SV_SF_3) {
+ showInputPanelOnFocus = false;
+ }
+#endif
+ }
+
+ void init();
+
+ void updateDefaultTextOption();
+ void relayoutDocument();
+ void updateSelection();
+ bool determineHorizontalAlignment();
+ bool setHAlign(QDeclarative1TextEdit::HAlignment, bool forceAlign = false);
+ void mirrorChange();
+ qreal implicitWidth() const;
+ void focusChanged(bool);
+
+ QString text;
+ QFont font;
+ QFont sourceFont;
+ QColor color;
+ QColor selectionColor;
+ QColor selectedTextColor;
+ QString style;
+ QColor styleColor;
+ QPixmap imgCache;
+ QPixmap imgStyleCache;
+ QDeclarative1TextEdit::HAlignment hAlign;
+ QDeclarative1TextEdit::VAlignment vAlign;
+ bool imgDirty : 1;
+ bool dirty : 1;
+ bool richText : 1;
+ bool cursorVisible : 1;
+ bool focusOnPress : 1;
+ bool showInputPanelOnFocus : 1;
+ bool clickCausedFocus : 1;
+ bool persistentSelection : 1;
+ bool requireImplicitWidth:1;
+ bool hAlignImplicit:1;
+ bool rightToLeftText:1;
+ qreal textMargin;
+ int lastSelectionStart;
+ int lastSelectionEnd;
+ QDeclarativeComponent* cursorComponent;
+ QDeclarativeItem* cursor;
+ QDeclarative1TextEdit::TextFormat format;
+ QTextDocument *document;
+ QTextControl *control;
+ QDeclarative1TextEdit::WrapMode wrapMode;
+ QDeclarative1TextEdit::SelectionMode mouseSelectionMode;
+ int lineCount;
+ bool selectByMouse;
+ bool canPaste;
+ int yoff;
+ QSize paintedSize;
+};
+
+QT_END_NAMESPACE
+#endif
diff --git a/src/qtquick1/graphicsitems/qdeclarativetextinput.cpp b/src/qtquick1/graphicsitems/qdeclarativetextinput.cpp
new file mode 100644
index 0000000000..53be1d3dfa
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativetextinput.cpp
@@ -0,0 +1,2016 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qdeclarativetextinput_p.h"
+#include "private/qdeclarativetextinput_p_p.h"
+
+#include <private/qdeclarativeglobal_p.h>
+#include <qdeclarativeinfo.h>
+
+#include <QValidator>
+#include <QTextCursor>
+#include <QApplication>
+#include <QFontMetrics>
+#include <QPainter>
+#include <QTextBoundaryFinder>
+#include <QInputContext>
+#include <qstyle.h>
+
+#ifndef QT_NO_LINEEDIT
+
+QT_BEGIN_NAMESPACE
+
+
+
+/*!
+ \qmlclass TextInput QDeclarative1TextInput
+ \ingroup qml-basic-visual-elements
+ \since 4.7
+ \brief The TextInput item displays an editable line of text.
+ \inherits Item
+
+ The TextInput element displays a single line of editable plain text.
+
+ TextInput is used to accept a line of text input. Input constraints
+ can be placed on a TextInput item (for example, through a \l validator or \l inputMask),
+ and setting \l echoMode to an appropriate value enables TextInput to be used for
+ a password input field.
+
+ On Mac OS X, the Up/Down key bindings for Home/End are explicitly disabled.
+ If you want such bindings (on any platform), you will need to construct them in QML.
+
+ \sa TextEdit, Text, {declarative/text/textselection}{Text Selection example}
+*/
+QDeclarative1TextInput::QDeclarative1TextInput(QDeclarativeItem* parent)
+ : QDeclarative1ImplicitSizePaintedItem(*(new QDeclarative1TextInputPrivate), parent)
+{
+ Q_D(QDeclarative1TextInput);
+ d->init();
+}
+
+QDeclarative1TextInput::~QDeclarative1TextInput()
+{
+}
+
+/*!
+ \qmlproperty string TextInput::text
+
+ The text in the TextInput.
+*/
+
+QString QDeclarative1TextInput::text() const
+{
+ Q_D(const QDeclarative1TextInput);
+ return d->control->text();
+}
+
+void QDeclarative1TextInput::setText(const QString &s)
+{
+ Q_D(QDeclarative1TextInput);
+ if(s == text())
+ return;
+ d->control->setText(s);
+}
+
+/*!
+ \qmlproperty string TextInput::font.family
+
+ Sets the family name of the font.
+
+ The family name is case insensitive and may optionally include a foundry name, e.g. "Helvetica [Cronyx]".
+ If the family is available from more than one foundry and the foundry isn't specified, an arbitrary foundry is chosen.
+ If the family isn't available a family will be set using the font matching algorithm.
+*/
+
+/*!
+ \qmlproperty bool TextInput::font.bold
+
+ Sets whether the font weight is bold.
+*/
+
+/*!
+ \qmlproperty enumeration TextInput::font.weight
+
+ Sets the font's weight.
+
+ The weight can be one of:
+ \list
+ \o Font.Light
+ \o Font.Normal - the default
+ \o Font.DemiBold
+ \o Font.Bold
+ \o Font.Black
+ \endlist
+
+ \qml
+ TextInput { text: "Hello"; font.weight: Font.DemiBold }
+ \endqml
+*/
+
+/*!
+ \qmlproperty bool TextInput::font.italic
+
+ Sets whether the font has an italic style.
+*/
+
+/*!
+ \qmlproperty bool TextInput::font.underline
+
+ Sets whether the text is underlined.
+*/
+
+/*!
+ \qmlproperty bool TextInput::font.strikeout
+
+ Sets whether the font has a strikeout style.
+*/
+
+/*!
+ \qmlproperty real TextInput::font.pointSize
+
+ Sets the font size in points. The point size must be greater than zero.
+*/
+
+/*!
+ \qmlproperty int TextInput::font.pixelSize
+
+ Sets the font size in pixels.
+
+ Using this function makes the font device dependent.
+ Use \c pointSize to set the size of the font in a device independent manner.
+*/
+
+/*!
+ \qmlproperty real TextInput::font.letterSpacing
+
+ Sets the letter spacing for the font.
+
+ Letter spacing changes the default spacing between individual letters in the font.
+ A positive value increases the letter spacing by the corresponding pixels; a negative value decreases the spacing.
+*/
+
+/*!
+ \qmlproperty real TextInput::font.wordSpacing
+
+ Sets the word spacing for the font.
+
+ Word spacing changes the default spacing between individual words.
+ A positive value increases the word spacing by a corresponding amount of pixels,
+ while a negative value decreases the inter-word spacing accordingly.
+*/
+
+/*!
+ \qmlproperty enumeration TextInput::font.capitalization
+
+ Sets the capitalization for the text.
+
+ \list
+ \o Font.MixedCase - This is the normal text rendering option where no capitalization change is applied.
+ \o Font.AllUppercase - This alters the text to be rendered in all uppercase type.
+ \o Font.AllLowercase - This alters the text to be rendered in all lowercase type.
+ \o Font.SmallCaps - This alters the text to be rendered in small-caps type.
+ \o Font.Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character.
+ \endlist
+
+ \qml
+ TextInput { text: "Hello"; font.capitalization: Font.AllLowercase }
+ \endqml
+*/
+
+QFont QDeclarative1TextInput::font() const
+{
+ Q_D(const QDeclarative1TextInput);
+ return d->sourceFont;
+}
+
+void QDeclarative1TextInput::setFont(const QFont &font)
+{
+ Q_D(QDeclarative1TextInput);
+ if (d->sourceFont == font)
+ return;
+
+ d->sourceFont = font;
+ QFont oldFont = d->font;
+ d->font = font;
+ if (d->font.pointSizeF() != -1) {
+ // 0.5pt resolution
+ qreal size = qRound(d->font.pointSizeF()*2.0);
+ d->font.setPointSizeF(size/2.0);
+ }
+
+ if (oldFont != d->font) {
+ d->control->setFont(d->font);
+ updateSize();
+ updateCursorRectangle();
+ if(d->cursorItem){
+ d->cursorItem->setHeight(QFontMetrics(d->font).height());
+ }
+ }
+ emit fontChanged(d->sourceFont);
+}
+
+/*!
+ \qmlproperty color TextInput::color
+
+ The text color.
+*/
+QColor QDeclarative1TextInput::color() const
+{
+ Q_D(const QDeclarative1TextInput);
+ return d->color;
+}
+
+void QDeclarative1TextInput::setColor(const QColor &c)
+{
+ Q_D(QDeclarative1TextInput);
+ if (c != d->color) {
+ d->color = c;
+ clearCache();
+ update();
+ emit colorChanged(c);
+ }
+}
+
+
+/*!
+ \qmlproperty color TextInput::selectionColor
+
+ The text highlight color, used behind selections.
+*/
+QColor QDeclarative1TextInput::selectionColor() const
+{
+ Q_D(const QDeclarative1TextInput);
+ return d->selectionColor;
+}
+
+void QDeclarative1TextInput::setSelectionColor(const QColor &color)
+{
+ Q_D(QDeclarative1TextInput);
+ if (d->selectionColor == color)
+ return;
+
+ d->selectionColor = color;
+ QPalette p = d->control->palette();
+ p.setColor(QPalette::Highlight, d->selectionColor);
+ d->control->setPalette(p);
+ if (d->control->hasSelectedText()) {
+ clearCache();
+ update();
+ }
+ emit selectionColorChanged(color);
+}
+
+/*!
+ \qmlproperty color TextInput::selectedTextColor
+
+ The highlighted text color, used in selections.
+*/
+QColor QDeclarative1TextInput::selectedTextColor() const
+{
+ Q_D(const QDeclarative1TextInput);
+ return d->selectedTextColor;
+}
+
+void QDeclarative1TextInput::setSelectedTextColor(const QColor &color)
+{
+ Q_D(QDeclarative1TextInput);
+ if (d->selectedTextColor == color)
+ return;
+
+ d->selectedTextColor = color;
+ QPalette p = d->control->palette();
+ p.setColor(QPalette::HighlightedText, d->selectedTextColor);
+ d->control->setPalette(p);
+ if (d->control->hasSelectedText()) {
+ clearCache();
+ update();
+ }
+ emit selectedTextColorChanged(color);
+}
+
+/*!
+ \qmlproperty enumeration TextInput::horizontalAlignment
+ \qmlproperty enumeration TextInput::effectiveHorizontalAlignment
+
+ Sets the horizontal alignment of the text within the TextInput item's
+ width and height. By default, the text alignment follows the natural alignment
+ of the text, for example text that is read from left to right will be aligned to
+ the left.
+
+ TextInput does not have vertical alignment, as the natural height is
+ exactly the height of the single line of text. If you set the height
+ manually to something larger, TextInput will always be top aligned
+ vertically. You can use anchors to align it however you want within
+ another item.
+
+ The valid values for \c horizontalAlignment are \c TextInput.AlignLeft, \c TextInput.AlignRight and
+ \c TextInput.AlignHCenter.
+
+ When using the attached property LayoutMirroring::enabled to mirror application
+ layouts, the horizontal alignment of text will also be mirrored. However, the property
+ \c horizontalAlignment will remain unchanged. To query the effective horizontal alignment
+ of TextInput, use the read-only property \c effectiveHorizontalAlignment.
+*/
+QDeclarative1TextInput::HAlignment QDeclarative1TextInput::hAlign() const
+{
+ Q_D(const QDeclarative1TextInput);
+ return d->hAlign;
+}
+
+void QDeclarative1TextInput::setHAlign(HAlignment align)
+{
+ Q_D(QDeclarative1TextInput);
+ bool forceAlign = d->hAlignImplicit && d->effectiveLayoutMirror;
+ d->hAlignImplicit = false;
+ if (d->setHAlign(align, forceAlign) && isComponentComplete()) {
+ updateCursorRectangle();
+ }
+}
+
+void QDeclarative1TextInput::resetHAlign()
+{
+ Q_D(QDeclarative1TextInput);
+ d->hAlignImplicit = true;
+ if (d->determineHorizontalAlignment() && isComponentComplete()) {
+ updateCursorRectangle();
+ }
+}
+
+QDeclarative1TextInput::HAlignment QDeclarative1TextInput::effectiveHAlign() const
+{
+ Q_D(const QDeclarative1TextInput);
+ QDeclarative1TextInput::HAlignment effectiveAlignment = d->hAlign;
+ if (!d->hAlignImplicit && d->effectiveLayoutMirror) {
+ switch (d->hAlign) {
+ case QDeclarative1TextInput::AlignLeft:
+ effectiveAlignment = QDeclarative1TextInput::AlignRight;
+ break;
+ case QDeclarative1TextInput::AlignRight:
+ effectiveAlignment = QDeclarative1TextInput::AlignLeft;
+ break;
+ default:
+ break;
+ }
+ }
+ return effectiveAlignment;
+}
+
+bool QDeclarative1TextInputPrivate::setHAlign(QDeclarative1TextInput::HAlignment alignment, bool forceAlign)
+{
+ Q_Q(QDeclarative1TextInput);
+ if ((hAlign != alignment || forceAlign) && alignment <= QDeclarative1TextInput::AlignHCenter) { // justify not supported
+ QDeclarative1TextInput::HAlignment oldEffectiveHAlign = q->effectiveHAlign();
+ hAlign = alignment;
+ emit q->horizontalAlignmentChanged(alignment);
+ if (oldEffectiveHAlign != q->effectiveHAlign())
+ emit q->effectiveHorizontalAlignmentChanged();
+ return true;
+ }
+ return false;
+}
+
+bool QDeclarative1TextInputPrivate::determineHorizontalAlignment()
+{
+ if (hAlignImplicit) {
+ // if no explicit alignment has been set, follow the natural layout direction of the text
+ QString text = control->text();
+ bool isRightToLeft = text.isEmpty() ? QApplication::keyboardInputDirection() == Qt::RightToLeft : text.isRightToLeft();
+ return setHAlign(isRightToLeft ? QDeclarative1TextInput::AlignRight : QDeclarative1TextInput::AlignLeft);
+ }
+ return false;
+}
+
+void QDeclarative1TextInputPrivate::mirrorChange()
+{
+ Q_Q(QDeclarative1TextInput);
+ if (q->isComponentComplete()) {
+ if (!hAlignImplicit && (hAlign == QDeclarative1TextInput::AlignRight || hAlign == QDeclarative1TextInput::AlignLeft)) {
+ q->updateCursorRectangle();
+ emit q->effectiveHorizontalAlignmentChanged();
+ }
+ }
+}
+
+/*!
+ \qmlproperty bool TextInput::readOnly
+
+ Sets whether user input can modify the contents of the TextInput.
+
+ If readOnly is set to true, then user input will not affect the text
+ property. Any bindings or attempts to set the text property will still
+ work.
+*/
+
+bool QDeclarative1TextInput::isReadOnly() const
+{
+ Q_D(const QDeclarative1TextInput);
+ return d->control->isReadOnly();
+}
+
+void QDeclarative1TextInput::setReadOnly(bool ro)
+{
+ Q_D(QDeclarative1TextInput);
+ if (d->control->isReadOnly() == ro)
+ return;
+
+ setFlag(QGraphicsItem::ItemAcceptsInputMethod, !ro);
+ d->control->setReadOnly(ro);
+
+ emit readOnlyChanged(ro);
+}
+
+/*!
+ \qmlproperty int TextInput::maximumLength
+ The maximum permitted length of the text in the TextInput.
+
+ If the text is too long, it is truncated at the limit.
+
+ By default, this property contains a value of 32767.
+*/
+int QDeclarative1TextInput::maxLength() const
+{
+ Q_D(const QDeclarative1TextInput);
+ return d->control->maxLength();
+}
+
+void QDeclarative1TextInput::setMaxLength(int ml)
+{
+ Q_D(QDeclarative1TextInput);
+ if (d->control->maxLength() == ml)
+ return;
+
+ d->control->setMaxLength(ml);
+
+ emit maximumLengthChanged(ml);
+}
+
+/*!
+ \qmlproperty bool TextInput::cursorVisible
+ Set to true when the TextInput shows a cursor.
+
+ This property is set and unset when the TextInput gets active focus, so that other
+ properties can be bound to whether the cursor is currently showing. As it
+ gets set and unset automatically, when you set the value yourself you must
+ keep in mind that your value may be overwritten.
+
+ It can be set directly in script, for example if a KeyProxy might
+ forward keys to it and you desire it to look active when this happens
+ (but without actually giving it active focus).
+
+ It should not be set directly on the element, like in the below QML,
+ as the specified value will be overridden an lost on focus changes.
+
+ \code
+ TextInput {
+ text: "Text"
+ cursorVisible: false
+ }
+ \endcode
+
+ In the above snippet the cursor will still become visible when the
+ TextInput gains active focus.
+*/
+bool QDeclarative1TextInput::isCursorVisible() const
+{
+ Q_D(const QDeclarative1TextInput);
+ return d->cursorVisible;
+}
+
+void QDeclarative1TextInput::setCursorVisible(bool on)
+{
+ Q_D(QDeclarative1TextInput);
+ if (d->cursorVisible == on)
+ return;
+ d->cursorVisible = on;
+ d->control->setCursorBlinkPeriod(on?QApplication::cursorFlashTime():0);
+ QRect r = d->control->cursorRect();
+ if (d->control->inputMask().isEmpty())
+ updateRect(r);
+ else
+ updateRect();
+ emit cursorVisibleChanged(d->cursorVisible);
+}
+
+/*!
+ \qmlproperty int TextInput::cursorPosition
+ The position of the cursor in the TextInput.
+*/
+int QDeclarative1TextInput::cursorPosition() const
+{
+ Q_D(const QDeclarative1TextInput);
+ return d->control->cursor();
+}
+void QDeclarative1TextInput::setCursorPosition(int cp)
+{
+ Q_D(QDeclarative1TextInput);
+ if (cp < 0 || cp > d->control->text().length())
+ return;
+ d->control->moveCursor(cp);
+}
+
+/*!
+ Returns a Rect which encompasses the cursor, but which may be larger than is
+ required. Ignores custom cursor delegates.
+*/
+QRect QDeclarative1TextInput::cursorRectangle() const
+{
+ Q_D(const QDeclarative1TextInput);
+ QRect r = d->control->cursorRect();
+ // Scroll and make consistent with TextEdit
+ // QLineControl inexplicably adds 1 to the height and horizontal padding
+ // for unicode direction markers.
+ r.adjust(5 - d->hscroll, 0, -4 - d->hscroll, -1);
+ return r;
+}
+
+/*!
+ \qmlproperty int TextInput::selectionStart
+
+ The cursor position before the first character in the current selection.
+ Setting this and selectionEnd allows you to specify a selection in the
+ text edit.
+
+ Note that if selectionStart == selectionEnd then there is no current
+ selection.
+
+ \sa selectionEnd, cursorPosition, selectedText, select()
+*/
+int QDeclarative1TextInput::selectionStart() const
+{
+ Q_D(const QDeclarative1TextInput);
+ return d->lastSelectionStart;
+}
+
+/*!
+ \qmlproperty int TextInput::selectionEnd
+
+ The cursor position after the last character in the current selection.
+ Setting this and selectionStart allows you to specify a selection in the
+ text edit.
+
+ Note that if selectionStart == selectionEnd then there is no current
+ selection.
+
+ \sa selectionStart, cursorPosition, selectedText, select()
+*/
+int QDeclarative1TextInput::selectionEnd() const
+{
+ Q_D(const QDeclarative1TextInput);
+ return d->lastSelectionEnd;
+}
+
+/*!
+ \qmlmethod void TextInput::select(int start, int end)
+
+ Causes the text from \a start to \a end to be selected.
+
+ If either start or end is out of range, the selection is not changed.
+
+ After calling this, selectionStart will become the lesser
+ and selectionEnd will become the greater (regardless of the order passed
+ to this method).
+
+ \sa selectionStart, selectionEnd
+*/
+void QDeclarative1TextInput::select(int start, int end)
+{
+ Q_D(QDeclarative1TextInput);
+ if (start < 0 || end < 0 || start > d->control->text().length() || end > d->control->text().length())
+ return;
+ d->control->setSelection(start, end-start);
+}
+
+/*!
+ \qmlproperty string TextInput::selectedText
+
+ This read-only property provides the text currently selected in the
+ text input.
+
+ It is equivalent to the following snippet, but is faster and easier
+ to use.
+
+ \js
+ myTextInput.text.toString().substring(myTextInput.selectionStart,
+ myTextInput.selectionEnd);
+ \endjs
+*/
+QString QDeclarative1TextInput::selectedText() const
+{
+ Q_D(const QDeclarative1TextInput);
+ return d->control->selectedText();
+}
+
+/*!
+ \qmlproperty bool TextInput::activeFocusOnPress
+
+ Whether the TextInput should gain active focus on a mouse press. By default this is
+ set to true.
+*/
+bool QDeclarative1TextInput::focusOnPress() const
+{
+ Q_D(const QDeclarative1TextInput);
+ return d->focusOnPress;
+}
+
+void QDeclarative1TextInput::setFocusOnPress(bool b)
+{
+ Q_D(QDeclarative1TextInput);
+ if (d->focusOnPress == b)
+ return;
+
+ d->focusOnPress = b;
+
+ emit activeFocusOnPressChanged(d->focusOnPress);
+}
+
+/*!
+ \qmlproperty bool TextInput::autoScroll
+
+ Whether the TextInput should scroll when the text is longer than the width. By default this is
+ set to true.
+*/
+bool QDeclarative1TextInput::autoScroll() const
+{
+ Q_D(const QDeclarative1TextInput);
+ return d->autoScroll;
+}
+
+void QDeclarative1TextInput::setAutoScroll(bool b)
+{
+ Q_D(QDeclarative1TextInput);
+ if (d->autoScroll == b)
+ return;
+
+ d->autoScroll = b;
+ //We need to repaint so that the scrolling is taking into account.
+ updateSize(true);
+ updateCursorRectangle();
+ emit autoScrollChanged(d->autoScroll);
+}
+
+/*!
+ \qmlclass IntValidator QIntValidator
+ \ingroup qml-basic-visual-elements
+
+ This element provides a validator for integer values.
+
+ IntValidator uses the \l {QLocale::setDefault()}{default locale} to interpret the number and
+ will accept locale specific digits, group separators, and positive and negative signs. In
+ addition, IntValidator is always guaranteed to accept a number formatted according to the "C"
+ locale.
+*/
+/*!
+ \qmlproperty int IntValidator::top
+
+ This property holds the validator's highest acceptable value.
+ By default, this property's value is derived from the highest signed integer available (typically 2147483647).
+*/
+/*!
+ \qmlproperty int IntValidator::bottom
+
+ This property holds the validator's lowest acceptable value.
+ By default, this property's value is derived from the lowest signed integer available (typically -2147483647).
+*/
+
+/*!
+ \qmlclass DoubleValidator QDoubleValidator
+ \ingroup qml-basic-visual-elements
+
+ This element provides a validator for non-integer numbers.
+*/
+
+/*!
+ \qmlproperty real DoubleValidator::top
+
+ This property holds the validator's maximum acceptable value.
+ By default, this property contains a value of infinity.
+*/
+/*!
+ \qmlproperty real DoubleValidator::bottom
+
+ This property holds the validator's minimum acceptable value.
+ By default, this property contains a value of -infinity.
+*/
+/*!
+ \qmlproperty int DoubleValidator::decimals
+
+ This property holds the validator's maximum number of digits after the decimal point.
+ By default, this property contains a value of 1000.
+*/
+/*!
+ \qmlproperty enumeration DoubleValidator::notation
+ This property holds the notation of how a string can describe a number.
+
+ The possible values for this property are:
+
+ \list
+ \o DoubleValidator.StandardNotation
+ \o DoubleValidator.ScientificNotation (default)
+ \endlist
+
+ If this property is set to DoubleValidator.ScientificNotation, the written number may have an exponent part (e.g. 1.5E-2).
+*/
+
+/*!
+ \qmlclass RegExpValidator QRegExpValidator
+ \ingroup qml-basic-visual-elements
+
+ This element provides a validator, which counts as valid any string which
+ matches a specified regular expression.
+*/
+/*!
+ \qmlproperty regExp RegExpValidator::regExp
+
+ This property holds the regular expression used for validation.
+
+ Note that this property should be a regular expression in JS syntax, e.g /a/ for the regular expression
+ matching "a".
+
+ By default, this property contains a regular expression with the pattern .* that matches any string.
+*/
+
+/*!
+ \qmlproperty Validator TextInput::validator
+
+ Allows you to set a validator on the TextInput. When a validator is set
+ the TextInput will only accept input which leaves the text property in
+ an acceptable or intermediate state. The accepted signal will only be sent
+ if the text is in an acceptable state when enter is pressed.
+
+ Currently supported validators are IntValidator, DoubleValidator and
+ RegExpValidator. An example of using validators is shown below, which allows
+ input of integers between 11 and 31 into the text input:
+
+ \code
+ import QtQuick 1.0
+ TextInput{
+ validator: IntValidator{bottom: 11; top: 31;}
+ focus: true
+ }
+ \endcode
+
+ \sa acceptableInput, inputMask
+*/
+#ifndef QT_NO_VALIDATOR
+QValidator* QDeclarative1TextInput::validator() const
+{
+ Q_D(const QDeclarative1TextInput);
+ //###const cast isn't good, but needed for property system?
+ return const_cast<QValidator*>(d->control->validator());
+}
+
+void QDeclarative1TextInput::setValidator(QValidator* v)
+{
+ Q_D(QDeclarative1TextInput);
+ if (d->control->validator() == v)
+ return;
+
+ d->control->setValidator(v);
+ if(!d->control->hasAcceptableInput()){
+ d->oldValidity = false;
+ emit acceptableInputChanged();
+ }
+
+ emit validatorChanged();
+}
+#endif // QT_NO_VALIDATOR
+
+/*!
+ \qmlproperty string TextInput::inputMask
+
+ Allows you to set an input mask on the TextInput, restricting the allowable
+ text inputs. See QLineEdit::inputMask for further details, as the exact
+ same mask strings are used by TextInput.
+
+ \sa acceptableInput, validator
+*/
+QString QDeclarative1TextInput::inputMask() const
+{
+ Q_D(const QDeclarative1TextInput);
+ return d->control->inputMask();
+}
+
+void QDeclarative1TextInput::setInputMask(const QString &im)
+{
+ Q_D(QDeclarative1TextInput);
+ if (d->control->inputMask() == im)
+ return;
+
+ d->control->setInputMask(im);
+ emit inputMaskChanged(d->control->inputMask());
+}
+
+/*!
+ \qmlproperty bool TextInput::acceptableInput
+
+ This property is always true unless a validator or input mask has been set.
+ If a validator or input mask has been set, this property will only be true
+ if the current text is acceptable to the validator or input mask as a final
+ string (not as an intermediate string).
+*/
+bool QDeclarative1TextInput::hasAcceptableInput() const
+{
+ Q_D(const QDeclarative1TextInput);
+ return d->control->hasAcceptableInput();
+}
+
+/*!
+ \qmlsignal TextInput::onAccepted()
+
+ This handler is called when the Return or Enter key is pressed.
+ Note that if there is a \l validator or \l inputMask set on the text
+ input, the handler will only be emitted if the input is in an acceptable
+ state.
+*/
+
+void QDeclarative1TextInputPrivate::updateInputMethodHints()
+{
+ Q_Q(QDeclarative1TextInput);
+ Qt::InputMethodHints hints = inputMethodHints;
+ uint echo = control->echoMode();
+ if (echo == QDeclarative1TextInput::Password || echo == QDeclarative1TextInput::NoEcho)
+ hints |= Qt::ImhHiddenText;
+ else if (echo == QDeclarative1TextInput::PasswordEchoOnEdit)
+ hints &= ~Qt::ImhHiddenText;
+ if (echo != QDeclarative1TextInput::Normal) {
+ hints |= Qt::ImhNoAutoUppercase;
+ hints |= Qt::ImhNoPredictiveText;
+ }
+ q->setInputMethodHints(hints);
+}
+
+/*!
+ \qmlproperty enumeration TextInput::echoMode
+
+ Specifies how the text should be displayed in the TextInput.
+ \list
+ \o TextInput.Normal - Displays the text as it is. (Default)
+ \o TextInput.Password - Displays asterixes instead of characters.
+ \o TextInput.NoEcho - Displays nothing.
+ \o TextInput.PasswordEchoOnEdit - Displays all but the current character as asterixes.
+ \endlist
+*/
+QDeclarative1TextInput::EchoMode QDeclarative1TextInput::echoMode() const
+{
+ Q_D(const QDeclarative1TextInput);
+ return (QDeclarative1TextInput::EchoMode)d->control->echoMode();
+}
+
+void QDeclarative1TextInput::setEchoMode(QDeclarative1TextInput::EchoMode echo)
+{
+ Q_D(QDeclarative1TextInput);
+ if (echoMode() == echo)
+ return;
+ d->control->setEchoMode((uint)echo);
+ d->updateInputMethodHints();
+ q_textChanged();
+ emit echoModeChanged(echoMode());
+}
+
+Qt::InputMethodHints QDeclarative1TextInput::imHints() const
+{
+ Q_D(const QDeclarative1TextInput);
+ return d->inputMethodHints;
+}
+
+void QDeclarative1TextInput::setIMHints(Qt::InputMethodHints hints)
+{
+ Q_D(QDeclarative1TextInput);
+ if (d->inputMethodHints == hints)
+ return;
+ d->inputMethodHints = hints;
+ d->updateInputMethodHints();
+}
+
+/*!
+ \qmlproperty Component TextInput::cursorDelegate
+ The delegate for the cursor in the TextInput.
+
+ If you set a cursorDelegate for a TextInput, this delegate will be used for
+ drawing the cursor instead of the standard cursor. An instance of the
+ delegate will be created and managed by the TextInput when a cursor is
+ needed, and the x property of delegate instance will be set so as
+ to be one pixel before the top left of the current character.
+
+ Note that the root item of the delegate component must be a QDeclarativeItem or
+ QDeclarativeItem derived item.
+*/
+QDeclarativeComponent* QDeclarative1TextInput::cursorDelegate() const
+{
+ Q_D(const QDeclarative1TextInput);
+ return d->cursorComponent;
+}
+
+void QDeclarative1TextInput::setCursorDelegate(QDeclarativeComponent* c)
+{
+ Q_D(QDeclarative1TextInput);
+ if (d->cursorComponent == c)
+ return;
+
+ d->cursorComponent = c;
+ if(!c){
+ //note that the components are owned by something else
+ delete d->cursorItem;
+ }else{
+ d->startCreatingCursor();
+ }
+
+ emit cursorDelegateChanged();
+}
+
+void QDeclarative1TextInputPrivate::startCreatingCursor()
+{
+ Q_Q(QDeclarative1TextInput);
+ if(cursorComponent->isReady()){
+ q->createCursor();
+ }else if(cursorComponent->isLoading()){
+ q->connect(cursorComponent, SIGNAL(statusChanged(int)),
+ q, SLOT(createCursor()));
+ }else {//isError
+ qmlInfo(q, cursorComponent->errors()) << QDeclarative1TextInput::tr("Could not load cursor delegate");
+ }
+}
+
+void QDeclarative1TextInput::createCursor()
+{
+ Q_D(QDeclarative1TextInput);
+ if(d->cursorComponent->isError()){
+ qmlInfo(this, d->cursorComponent->errors()) << tr("Could not load cursor delegate");
+ return;
+ }
+
+ if(!d->cursorComponent->isReady())
+ return;
+
+ if(d->cursorItem)
+ delete d->cursorItem;
+ d->cursorItem = qobject_cast<QDeclarativeItem*>(d->cursorComponent->create());
+ if(!d->cursorItem){
+ qmlInfo(this, d->cursorComponent->errors()) << tr("Could not instantiate cursor delegate");
+ return;
+ }
+
+ QDeclarative_setParent_noEvent(d->cursorItem, this);
+ d->cursorItem->setParentItem(this);
+ d->cursorItem->setX(d->control->cursorToX());
+ d->cursorItem->setHeight(d->control->height()-1); // -1 to counter QLineControl's +1 which is not consistent with Text.
+}
+
+/*!
+ \qmlmethod rect TextInput::positionToRectangle(int pos)
+
+ This function takes a character position and returns the rectangle that the
+ cursor would occupy, if it was placed at that character position.
+
+ This is similar to setting the cursorPosition, and then querying the cursor
+ rectangle, but the cursorPosition is not changed.
+*/
+QRectF QDeclarative1TextInput::positionToRectangle(int pos) const
+{
+ Q_D(const QDeclarative1TextInput);
+ if (pos > d->control->cursorPosition())
+ pos += d->control->preeditAreaText().length();
+ return QRectF(d->control->cursorToX(pos)-d->hscroll,
+ 0.0,
+ d->control->cursorWidth(),
+ cursorRectangle().height());
+}
+
+int QDeclarative1TextInput::positionAt(int x) const
+{
+ return positionAt(x, CursorBetweenCharacters);
+}
+
+/*!
+ \qmlmethod int TextInput::positionAt(int x, CursorPosition position = CursorBetweenCharacters)
+ \since Quick 1.1
+
+ This function returns the character position at
+ x pixels from the left of the textInput. Position 0 is before the
+ first character, position 1 is after the first character but before the second,
+ and so on until position text.length, which is after all characters.
+
+ This means that for all x values before the first character this function returns 0,
+ and for all x values after the last character this function returns text.length.
+
+ The cursor position type specifies how the cursor position should be resolved.
+
+ \list
+ \o TextInput.CursorBetweenCharacters - Returns the position between characters that is nearest x.
+ \o TextInput.CursorOnCharacter - Returns the position before the character that is nearest x.
+ \endlist
+*/
+int QDeclarative1TextInput::positionAt(int x, CursorPosition position) const
+{
+ Q_D(const QDeclarative1TextInput);
+ int pos = d->control->xToPos(x + d->hscroll, QTextLine::CursorPosition(position));
+ const int cursor = d->control->cursor();
+ if (pos > cursor) {
+ const int preeditLength = d->control->preeditAreaText().length();
+ pos = pos > cursor + preeditLength
+ ? pos - preeditLength
+ : cursor;
+ }
+ return pos;
+}
+
+void QDeclarative1TextInputPrivate::focusChanged(bool hasFocus)
+{
+ Q_Q(QDeclarative1TextInput);
+ focused = hasFocus;
+ q->setCursorVisible(hasFocus && scene && scene->hasFocus());
+ if(q->echoMode() == QDeclarative1TextInput::PasswordEchoOnEdit && !hasFocus)
+ control->updatePasswordEchoEditing(false);//QLineControl sets it on key events, but doesn't deal with focus events
+ if (!hasFocus)
+ control->deselect();
+ QDeclarativeItemPrivate::focusChanged(hasFocus);
+}
+
+void QDeclarative1TextInput::keyPressEvent(QKeyEvent* ev)
+{
+ Q_D(QDeclarative1TextInput);
+ keyPressPreHandler(ev);
+ if (ev->isAccepted())
+ return;
+
+ // Don't allow MacOSX up/down support, and we don't allow a completer.
+ bool ignore = (ev->key() == Qt::Key_Up || ev->key() == Qt::Key_Down) && ev->modifiers() == Qt::NoModifier;
+ if (!ignore && (d->lastSelectionStart == d->lastSelectionEnd) && (ev->key() == Qt::Key_Right || ev->key() == Qt::Key_Left)) {
+ // Ignore when moving off the end unless there is a selection,
+ // because then moving will do something (deselect).
+ int cursorPosition = d->control->cursor();
+ if (cursorPosition == 0)
+ ignore = ev->key() == (d->control->layoutDirection() == Qt::LeftToRight ? Qt::Key_Left : Qt::Key_Right);
+ if (cursorPosition == d->control->text().length())
+ ignore = ev->key() == (d->control->layoutDirection() == Qt::LeftToRight ? Qt::Key_Right : Qt::Key_Left);
+ }
+ if (ignore) {
+ ev->ignore();
+ } else {
+ d->control->processKeyEvent(ev);
+ }
+ if (!ev->isAccepted())
+ QDeclarative1PaintedItem::keyPressEvent(ev);
+}
+
+void QDeclarative1TextInput::inputMethodEvent(QInputMethodEvent *ev)
+{
+ Q_D(QDeclarative1TextInput);
+ ev->ignore();
+ const bool wasComposing = d->control->preeditAreaText().length() > 0;
+ inputMethodPreHandler(ev);
+ if (!ev->isAccepted()) {
+ if (d->control->isReadOnly()) {
+ ev->ignore();
+ } else {
+ d->control->processInputMethodEvent(ev);
+ }
+ }
+ if (!ev->isAccepted())
+ QDeclarative1PaintedItem::inputMethodEvent(ev);
+
+ if (wasComposing != (d->control->preeditAreaText().length() > 0))
+ emit inputMethodComposingChanged();
+}
+
+/*!
+\overload
+Handles the given mouse \a event.
+*/
+void QDeclarative1TextInput::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QDeclarative1TextInput);
+ if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonDblClick))
+ return;
+ if (d->selectByMouse) {
+ int cursor = d->xToPos(event->pos().x());
+ d->control->selectWordAtPos(cursor);
+ event->setAccepted(true);
+ } else {
+ QDeclarative1PaintedItem::mouseDoubleClickEvent(event);
+ }
+}
+
+void QDeclarative1TextInput::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QDeclarative1TextInput);
+ if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonPress))
+ return;
+ if(d->focusOnPress){
+ bool hadActiveFocus = hasActiveFocus();
+ forceActiveFocus();
+ if (d->showInputPanelOnFocus) {
+ if (hasActiveFocus() && hadActiveFocus && !isReadOnly()) {
+ // re-open input panel on press if already focused
+ openSoftwareInputPanel();
+ }
+ } else { // show input panel on click
+ if (hasActiveFocus() && !hadActiveFocus) {
+ d->clickCausedFocus = true;
+ }
+ }
+ }
+ if (d->selectByMouse) {
+ setKeepMouseGrab(false);
+ d->selectPressed = true;
+ d->pressPos = event->pos();
+ }
+ bool mark = (event->modifiers() & Qt::ShiftModifier) && d->selectByMouse;
+ int cursor = d->xToPos(event->pos().x());
+ d->control->moveCursor(cursor, mark);
+ event->setAccepted(true);
+}
+
+void QDeclarative1TextInput::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QDeclarative1TextInput);
+ if (d->sendMouseEventToInputContext(event, QEvent::MouseMove))
+ return;
+ if (d->selectPressed) {
+ if (qAbs(int(event->pos().x() - d->pressPos.x())) > QApplication::startDragDistance())
+ setKeepMouseGrab(true);
+ moveCursorSelection(d->xToPos(event->pos().x()), d->mouseSelectionMode);
+ event->setAccepted(true);
+ } else {
+ QDeclarative1PaintedItem::mouseMoveEvent(event);
+ }
+}
+
+/*!
+\overload
+Handles the given mouse \a event.
+*/
+void QDeclarative1TextInput::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_D(QDeclarative1TextInput);
+ if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonRelease))
+ return;
+ if (d->selectPressed) {
+ d->selectPressed = false;
+ setKeepMouseGrab(false);
+ }
+ if (!d->showInputPanelOnFocus) { // input panel on click
+ if (d->focusOnPress && !isReadOnly() && boundingRect().contains(event->pos())) {
+ if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
+ if (view->scene() && view->scene() == scene()) {
+ qt_widget_private(view)->handleSoftwareInputPanel(event->button(), d->clickCausedFocus);
+ }
+ }
+ }
+ }
+ d->clickCausedFocus = false;
+ d->control->processEvent(event);
+ if (!event->isAccepted())
+ QDeclarative1PaintedItem::mouseReleaseEvent(event);
+}
+
+bool QDeclarative1TextInputPrivate::sendMouseEventToInputContext(
+ QGraphicsSceneMouseEvent *event, QEvent::Type eventType)
+{
+#if !defined QT_NO_IM
+ if (event->widget() && control->composeMode()) {
+ int tmp_cursor = xToPos(event->pos().x());
+ int mousePos = tmp_cursor - control->cursor();
+ if (mousePos < 0 || mousePos > control->preeditAreaText().length()) {
+ mousePos = -1;
+ // don't send move events outside the preedit area
+ if (eventType == QEvent::MouseMove)
+ return true;
+ }
+
+ QInputContext *qic = event->widget()->inputContext();
+ if (qic) {
+ QMouseEvent mouseEvent(
+ eventType,
+ event->widget()->mapFromGlobal(event->screenPos()),
+ event->screenPos(),
+ event->button(),
+ event->buttons(),
+ event->modifiers());
+ // may be causing reset() in some input methods
+ qic->mouseHandler(mousePos, &mouseEvent);
+ event->setAccepted(mouseEvent.isAccepted());
+ }
+ if (!control->preeditAreaText().isEmpty())
+ return true;
+ }
+#else
+ Q_UNUSED(event);
+ Q_UNUSED(eventType)
+#endif
+
+ return false;
+}
+
+bool QDeclarative1TextInput::sceneEvent(QEvent *event)
+{
+ Q_D(QDeclarative1TextInput);
+ bool rv = QDeclarativeItem::sceneEvent(event);
+ if (event->type() == QEvent::UngrabMouse) {
+ d->selectPressed = false;
+ setKeepMouseGrab(false);
+ }
+ return rv;
+}
+
+bool QDeclarative1TextInput::event(QEvent* ev)
+{
+ Q_D(QDeclarative1TextInput);
+ //Anything we don't deal with ourselves, pass to the control
+ bool handled = false;
+ switch(ev->type()){
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease://###Should the control be doing anything with release?
+ case QEvent::InputMethod:
+ case QEvent::GraphicsSceneMousePress:
+ case QEvent::GraphicsSceneMouseMove:
+ case QEvent::GraphicsSceneMouseRelease:
+ case QEvent::GraphicsSceneMouseDoubleClick:
+ break;
+ default:
+ handled = d->control->processEvent(ev);
+ }
+ if(!handled)
+ handled = QDeclarative1PaintedItem::event(ev);
+ return handled;
+}
+
+void QDeclarative1TextInput::geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry)
+{
+ Q_D(QDeclarative1TextInput);
+ if (newGeometry.width() != oldGeometry.width()) {
+ updateSize();
+ updateCursorRectangle();
+ }
+ QDeclarative1PaintedItem::geometryChanged(newGeometry, oldGeometry);
+}
+
+int QDeclarative1TextInputPrivate::calculateTextWidth()
+{
+ return qRound(control->naturalTextWidth());
+}
+
+void QDeclarative1TextInputPrivate::updateHorizontalScroll()
+{
+ Q_Q(QDeclarative1TextInput);
+ const int preeditLength = control->preeditAreaText().length();
+ int cix = qRound(control->cursorToX(control->cursor() + preeditLength));
+ QRect br(q->boundingRect().toRect());
+ int widthUsed = calculateTextWidth();
+
+ QDeclarative1TextInput::HAlignment effectiveHAlign = q->effectiveHAlign();
+ if (autoScroll) {
+ if (widthUsed <= br.width()) {
+ // text fits in br; use hscroll for alignment
+ switch (effectiveHAlign & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) {
+ case Qt::AlignRight:
+ hscroll = widthUsed - br.width() - 1;
+ break;
+ case Qt::AlignHCenter:
+ hscroll = (widthUsed - br.width()) / 2;
+ break;
+ default:
+ // Left
+ hscroll = 0;
+ break;
+ }
+ } else if (cix - hscroll >= br.width()) {
+ // text doesn't fit, cursor is to the right of br (scroll right)
+ hscroll = cix - br.width() + 1;
+ } else if (cix - hscroll < 0 && hscroll < widthUsed) {
+ // text doesn't fit, cursor is to the left of br (scroll left)
+ hscroll = cix;
+ } else if (widthUsed - hscroll < br.width()) {
+ // text doesn't fit, text document is to the left of br; align
+ // right
+ hscroll = widthUsed - br.width() + 1;
+ }
+ if (preeditLength > 0) {
+ // check to ensure long pre-edit text doesn't push the cursor
+ // off to the left
+ cix = qRound(control->cursorToX(
+ control->cursor() + qMax(0, control->preeditCursor() - 1)));
+ if (cix < hscroll)
+ hscroll = cix;
+ }
+ } else {
+ switch (effectiveHAlign) {
+ case QDeclarative1TextInput::AlignRight:
+ hscroll = q->width() - widthUsed;
+ break;
+ case QDeclarative1TextInput::AlignHCenter:
+ hscroll = (q->width() - widthUsed) / 2;
+ break;
+ default:
+ // Left
+ hscroll = 0;
+ break;
+ }
+ }
+}
+
+void QDeclarative1TextInput::drawContents(QPainter *p, const QRect &r)
+{
+ Q_D(QDeclarative1TextInput);
+ p->setRenderHint(QPainter::TextAntialiasing, true);
+ p->save();
+ p->setPen(QPen(d->color));
+ int flags = QLineControl::DrawText;
+ if(!isReadOnly() && d->cursorVisible && !d->cursorItem)
+ flags |= QLineControl::DrawCursor;
+ if (d->control->hasSelectedText())
+ flags |= QLineControl::DrawSelections;
+ QPoint offset = QPoint(0,0);
+ QFontMetrics fm = QFontMetrics(d->font);
+ QRect br(boundingRect().toRect());
+ if (d->autoScroll) {
+ // the y offset is there to keep the baseline constant in case we have script changes in the text.
+ offset = br.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent());
+ } else {
+ offset = QPoint(d->hscroll, 0);
+ }
+ d->control->draw(p, offset, r, flags);
+ p->restore();
+}
+
+/*!
+\overload
+Returns the value of the given \a property.
+*/
+QVariant QDeclarative1TextInput::inputMethodQuery(Qt::InputMethodQuery property) const
+{
+ Q_D(const QDeclarative1TextInput);
+ switch(property) {
+ case Qt::ImMicroFocus:
+ return cursorRectangle();
+ case Qt::ImFont:
+ return font();
+ case Qt::ImCursorPosition:
+ return QVariant(d->control->cursor());
+ case Qt::ImSurroundingText:
+ if (d->control->echoMode() == PasswordEchoOnEdit && !d->control->passwordEchoEditing())
+ return QVariant(displayText());
+ else
+ return QVariant(text());
+ case Qt::ImCurrentSelection:
+ return QVariant(selectedText());
+ case Qt::ImMaximumTextLength:
+ return QVariant(maxLength());
+ case Qt::ImAnchorPosition:
+ if (d->control->selectionStart() == d->control->selectionEnd())
+ return QVariant(d->control->cursor());
+ else if (d->control->selectionStart() == d->control->cursor())
+ return QVariant(d->control->selectionEnd());
+ else
+ return QVariant(d->control->selectionStart());
+ default:
+ return QVariant();
+ }
+}
+
+/*!
+ \qmlmethod void TextInput::deselect()
+ \since Quick 1.1
+
+ Removes active text selection.
+*/
+void QDeclarative1TextInput::deselect()
+{
+ Q_D(QDeclarative1TextInput);
+ d->control->deselect();
+}
+
+/*!
+ \qmlmethod void TextInput::selectAll()
+
+ Causes all text to be selected.
+*/
+void QDeclarative1TextInput::selectAll()
+{
+ Q_D(QDeclarative1TextInput);
+ d->control->setSelection(0, d->control->text().length());
+}
+
+/*!
+ \qmlmethod void TextInput::isRightToLeft(int start, int end)
+
+ Returns true if the natural reading direction of the editor text
+ found between positions \a start and \a end is right to left.
+*/
+bool QDeclarative1TextInput::isRightToLeft(int start, int end)
+{
+ Q_D(QDeclarative1TextInput);
+ if (start > end) {
+ qmlInfo(this) << "isRightToLeft(start, end) called with the end property being smaller than the start.";
+ return false;
+ } else {
+ return d->control->text().mid(start, end - start).isRightToLeft();
+ }
+}
+
+#ifndef QT_NO_CLIPBOARD
+/*!
+ \qmlmethod TextInput::cut()
+
+ Moves the currently selected text to the system clipboard.
+*/
+void QDeclarative1TextInput::cut()
+{
+ Q_D(QDeclarative1TextInput);
+ d->control->copy();
+ d->control->del();
+}
+
+/*!
+ \qmlmethod TextInput::copy()
+
+ Copies the currently selected text to the system clipboard.
+*/
+void QDeclarative1TextInput::copy()
+{
+ Q_D(QDeclarative1TextInput);
+ d->control->copy();
+}
+
+/*!
+ \qmlmethod TextInput::paste()
+
+ Replaces the currently selected text by the contents of the system clipboard.
+*/
+void QDeclarative1TextInput::paste()
+{
+ Q_D(QDeclarative1TextInput);
+ if(!d->control->isReadOnly())
+ d->control->paste();
+}
+#endif // QT_NO_CLIPBOARD
+
+/*!
+ \qmlmethod void TextInput::selectWord()
+
+ Causes the word closest to the current cursor position to be selected.
+*/
+void QDeclarative1TextInput::selectWord()
+{
+ Q_D(QDeclarative1TextInput);
+ d->control->selectWordAtPos(d->control->cursor());
+}
+
+/*!
+ \qmlproperty bool TextInput::smooth
+
+ This property holds whether the text is smoothly scaled or transformed.
+
+ Smooth filtering gives better visual quality, but is slower. If
+ the item is displayed at its natural size, this property has no visual or
+ performance effect.
+
+ \note Generally scaling artifacts are only visible if the item is stationary on
+ the screen. A common pattern when animating an item is to disable smooth
+ filtering at the beginning of the animation and reenable it at the conclusion.
+*/
+
+/*!
+ \qmlproperty string TextInput::passwordCharacter
+
+ This is the character displayed when echoMode is set to Password or
+ PasswordEchoOnEdit. By default it is an asterisk.
+
+ If this property is set to a string with more than one character,
+ the first character is used. If the string is empty, the value
+ is ignored and the property is not set.
+*/
+QString QDeclarative1TextInput::passwordCharacter() const
+{
+ Q_D(const QDeclarative1TextInput);
+ return QString(d->control->passwordCharacter());
+}
+
+void QDeclarative1TextInput::setPasswordCharacter(const QString &str)
+{
+ Q_D(QDeclarative1TextInput);
+ if(str.length() < 1)
+ return;
+ d->control->setPasswordCharacter(str.constData()[0]);
+ EchoMode echoMode_ = echoMode();
+ if (echoMode_ == Password || echoMode_ == PasswordEchoOnEdit) {
+ updateSize();
+ }
+ emit passwordCharacterChanged();
+}
+
+/*!
+ \qmlproperty string TextInput::displayText
+
+ This is the text displayed in the TextInput.
+
+ If \l echoMode is set to TextInput::Normal, this holds the
+ same value as the TextInput::text property. Otherwise,
+ this property holds the text visible to the user, while
+ the \l text property holds the actual entered text.
+*/
+QString QDeclarative1TextInput::displayText() const
+{
+ Q_D(const QDeclarative1TextInput);
+ return d->control->displayText();
+}
+
+/*!
+ \qmlproperty bool TextInput::selectByMouse
+
+ Defaults to false.
+
+ If true, the user can use the mouse to select text in some
+ platform-specific way. Note that for some platforms this may
+ not be an appropriate interaction (eg. may conflict with how
+ the text needs to behave inside a Flickable.
+*/
+bool QDeclarative1TextInput::selectByMouse() const
+{
+ Q_D(const QDeclarative1TextInput);
+ return d->selectByMouse;
+}
+
+void QDeclarative1TextInput::setSelectByMouse(bool on)
+{
+ Q_D(QDeclarative1TextInput);
+ if (d->selectByMouse != on) {
+ d->selectByMouse = on;
+ emit selectByMouseChanged(on);
+ }
+}
+
+/*!
+ \qmlproperty enum TextInput::mouseSelectionMode
+ \since Quick 1.1
+
+ Specifies how text should be selected using a mouse.
+
+ \list
+ \o TextInput.SelectCharacters - The selection is updated with individual characters. (Default)
+ \o TextInput.SelectWords - The selection is updated with whole words.
+ \endlist
+
+ This property only applies when \l selectByMouse is true.
+*/
+
+QDeclarative1TextInput::SelectionMode QDeclarative1TextInput::mouseSelectionMode() const
+{
+ Q_D(const QDeclarative1TextInput);
+ return d->mouseSelectionMode;
+}
+
+void QDeclarative1TextInput::setMouseSelectionMode(SelectionMode mode)
+{
+ Q_D(QDeclarative1TextInput);
+ if (d->mouseSelectionMode != mode) {
+ d->mouseSelectionMode = mode;
+ emit mouseSelectionModeChanged(mode);
+ }
+}
+
+/*!
+ \qmlproperty bool TextInput::canPaste
+ \since QtQuick 1.1
+
+ Returns true if the TextInput is writable and the content of the clipboard is
+ suitable for pasting into the TextEdit.
+*/
+bool QDeclarative1TextInput::canPaste() const
+{
+ Q_D(const QDeclarative1TextInput);
+ return d->canPaste;
+}
+
+void QDeclarative1TextInput::moveCursorSelection(int position)
+{
+ Q_D(QDeclarative1TextInput);
+ d->control->moveCursor(position, true);
+}
+
+/*!
+ \qmlmethod void TextInput::moveCursorSelection(int position, SelectionMode mode = TextInput.SelectCharacters)
+ \since Quick 1.1
+
+ Moves the cursor to \a position and updates the selection according to the optional \a mode
+ parameter. (To only move the cursor, set the \l cursorPosition property.)
+
+ When this method is called it additionally sets either the
+ selectionStart or the selectionEnd (whichever was at the previous cursor position)
+ to the specified position. This allows you to easily extend and contract the selected
+ text range.
+
+ The selection mode specifies whether the selection is updated on a per character or a per word
+ basis. If not specified the selection mode will default to TextInput.SelectCharacters.
+
+ \list
+ \o TextEdit.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at
+ the previous cursor position) to the specified position.
+ \o TextEdit.SelectWords - Sets the selectionStart and selectionEnd to include all
+ words between the specified postion and the previous cursor position. Words partially in the
+ range are included.
+ \endlist
+
+ For example, take this sequence of calls:
+
+ \code
+ cursorPosition = 5
+ moveCursorSelection(9, TextInput.SelectCharacters)
+ moveCursorSelection(7, TextInput.SelectCharacters)
+ \endcode
+
+ This moves the cursor to position 5, extend the selection end from 5 to 9
+ and then retract the selection end from 9 to 7, leaving the text from position 5 to 7
+ selected (the 6th and 7th characters).
+
+ The same sequence with TextInput.SelectWords will extend the selection start to a word boundary
+ before or on position 5 and extend the selection end to a word boundary on or past position 9.
+*/
+void QDeclarative1TextInput::moveCursorSelection(int pos, SelectionMode mode)
+{
+ Q_D(QDeclarative1TextInput);
+
+ if (mode == SelectCharacters) {
+ d->control->moveCursor(pos, true);
+ } else if (pos != d->control->cursor()){
+ const int cursor = d->control->cursor();
+ int anchor;
+ if (!d->control->hasSelectedText())
+ anchor = d->control->cursor();
+ else if (d->control->selectionStart() == d->control->cursor())
+ anchor = d->control->selectionEnd();
+ else
+ anchor = d->control->selectionStart();
+
+ if (anchor < pos || (anchor == pos && cursor < pos)) {
+ const QString text = d->control->text();
+ QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text);
+ finder.setPosition(anchor);
+
+ const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
+ if (anchor < text.length() && (!(reasons & QTextBoundaryFinder::StartWord)
+ || ((reasons & QTextBoundaryFinder::EndWord) && anchor > cursor))) {
+ finder.toPreviousBoundary();
+ }
+ anchor = finder.position() != -1 ? finder.position() : 0;
+
+ finder.setPosition(pos);
+ if (pos > 0 && !finder.boundaryReasons())
+ finder.toNextBoundary();
+ const int cursor = finder.position() != -1 ? finder.position() : text.length();
+
+ d->control->setSelection(anchor, cursor - anchor);
+ } else if (anchor > pos || (anchor == pos && cursor > pos)) {
+ const QString text = d->control->text();
+ QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text);
+ finder.setPosition(anchor);
+
+ const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
+ if (anchor > 0 && (!(reasons & QTextBoundaryFinder::EndWord)
+ || ((reasons & QTextBoundaryFinder::StartWord) && anchor < cursor))) {
+ finder.toNextBoundary();
+ }
+ anchor = finder.position() != -1 ? finder.position() : text.length();
+
+ finder.setPosition(pos);
+ if (pos < text.length() && !finder.boundaryReasons())
+ finder.toPreviousBoundary();
+ const int cursor = finder.position() != -1 ? finder.position() : 0;
+
+ d->control->setSelection(anchor, cursor - anchor);
+ }
+ }
+}
+
+/*!
+ \qmlmethod void TextInput::openSoftwareInputPanel()
+
+ Opens software input panels like virtual keyboards for typing, useful for
+ customizing when you want the input keyboard to be shown and hidden in
+ your application.
+
+ By default the opening of input panels follows the platform style. On Symbian^1 and
+ Symbian^3 -based devices the panels are opened by clicking TextInput. On other platforms
+ the panels are automatically opened when TextInput element gains active focus. Input panels are
+ always closed if no editor has active focus.
+
+ . You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
+ and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
+ the behavior you want.
+
+ Only relevant on platforms, which provide virtual keyboards.
+
+ \qml
+ import QtQuick 1.0
+ TextInput {
+ id: textInput
+ text: "Hello world!"
+ activeFocusOnPress: false
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ if (!textInput.activeFocus) {
+ textInput.forceActiveFocus()
+ textInput.openSoftwareInputPanel();
+ } else {
+ textInput.focus = false;
+ }
+ }
+ onPressAndHold: textInput.closeSoftwareInputPanel();
+ }
+ }
+ \endqml
+*/
+void QDeclarative1TextInput::openSoftwareInputPanel()
+{
+ QEvent event(QEvent::RequestSoftwareInputPanel);
+ if (qApp) {
+ if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
+ if (view->scene() && view->scene() == scene()) {
+ QApplication::sendEvent(view, &event);
+ }
+ }
+ }
+}
+
+/*!
+ \qmlmethod void TextInput::closeSoftwareInputPanel()
+
+ Closes a software input panel like a virtual keyboard shown on the screen, useful
+ for customizing when you want the input keyboard to be shown and hidden in
+ your application.
+
+ By default the opening of input panels follows the platform style. On Symbian^1 and
+ Symbian^3 -based devices the panels are opened by clicking TextInput. On other platforms
+ the panels are automatically opened when TextInput element gains active focus. Input panels are
+ always closed if no editor has active focus.
+
+ . You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
+ and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
+ the behavior you want.
+
+ Only relevant on platforms, which provide virtual keyboards.
+
+ \qml
+ import QtQuick 1.0
+ TextInput {
+ id: textInput
+ text: "Hello world!"
+ activeFocusOnPress: false
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ if (!textInput.activeFocus) {
+ textInput.forceActiveFocus();
+ textInput.openSoftwareInputPanel();
+ } else {
+ textInput.focus = false;
+ }
+ }
+ onPressAndHold: textInput.closeSoftwareInputPanel();
+ }
+ }
+ \endqml
+*/
+void QDeclarative1TextInput::closeSoftwareInputPanel()
+{
+ QEvent event(QEvent::CloseSoftwareInputPanel);
+ if (qApp) {
+ QEvent event(QEvent::CloseSoftwareInputPanel);
+ if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
+ if (view->scene() && view->scene() == scene()) {
+ QApplication::sendEvent(view, &event);
+ }
+ }
+ }
+}
+
+void QDeclarative1TextInput::focusInEvent(QFocusEvent *event)
+{
+ Q_D(const QDeclarative1TextInput);
+ if (d->showInputPanelOnFocus) {
+ if (d->focusOnPress && !isReadOnly()) {
+ openSoftwareInputPanel();
+ }
+ }
+ QDeclarative1PaintedItem::focusInEvent(event);
+}
+
+/*!
+ \qmlproperty bool TextInput::inputMethodComposing
+
+ \since QtQuick 1.1
+
+ This property holds whether the TextInput has partial text input from an
+ input method.
+
+ While it is composing an input method may rely on mouse or key events from
+ the TextInput to edit or commit the partial text. This property can be
+ used to determine when to disable events handlers that may interfere with
+ the correct operation of an input method.
+*/
+bool QDeclarative1TextInput::isInputMethodComposing() const
+{
+ Q_D(const QDeclarative1TextInput);
+ return d->control->preeditAreaText().length() > 0;
+}
+
+void QDeclarative1TextInputPrivate::init()
+{
+ Q_Q(QDeclarative1TextInput);
+ control->setParent(q);//Now mandatory due to accessibility changes
+ control->setCursorWidth(1);
+ control->setPasswordCharacter(QLatin1Char('*'));
+ q->setSmooth(smooth);
+ q->setAcceptedMouseButtons(Qt::LeftButton);
+ q->setFlag(QGraphicsItem::ItemHasNoContents, false);
+ q->setFlag(QGraphicsItem::ItemAcceptsInputMethod);
+ q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
+ q, SLOT(cursorPosChanged()));
+ q->connect(control, SIGNAL(selectionChanged()),
+ q, SLOT(selectionChanged()));
+ q->connect(control, SIGNAL(textChanged(QString)),
+ q, SLOT(q_textChanged()));
+ q->connect(control, SIGNAL(accepted()),
+ q, SIGNAL(accepted()));
+ q->connect(control, SIGNAL(updateNeeded(QRect)),
+ q, SLOT(updateRect(QRect)));
+#ifndef QT_NO_CLIPBOARD
+ q->connect(q, SIGNAL(readOnlyChanged(bool)),
+ q, SLOT(q_canPasteChanged()));
+ q->connect(QApplication::clipboard(), SIGNAL(dataChanged()),
+ q, SLOT(q_canPasteChanged()));
+ canPaste = !control->isReadOnly() && QApplication::clipboard()->text().length() != 0;
+#endif // QT_NO_CLIPBOARD
+ q->connect(control, SIGNAL(updateMicroFocus()),
+ q, SLOT(updateCursorRectangle()));
+ q->connect(control, SIGNAL(displayTextChanged(QString)),
+ q, SLOT(updateRect()));
+ q->updateSize();
+ oldValidity = control->hasAcceptableInput();
+ lastSelectionStart = 0;
+ lastSelectionEnd = 0;
+ QPalette p = control->palette();
+ selectedTextColor = p.color(QPalette::HighlightedText);
+ selectionColor = p.color(QPalette::Highlight);
+ determineHorizontalAlignment();
+}
+
+void QDeclarative1TextInput::cursorPosChanged()
+{
+ Q_D(QDeclarative1TextInput);
+ updateCursorRectangle();
+ emit cursorPositionChanged();
+ d->control->resetCursorBlinkTimer();
+
+ if(!d->control->hasSelectedText()){
+ if(d->lastSelectionStart != d->control->cursor()){
+ d->lastSelectionStart = d->control->cursor();
+ emit selectionStartChanged();
+ }
+ if(d->lastSelectionEnd != d->control->cursor()){
+ d->lastSelectionEnd = d->control->cursor();
+ emit selectionEndChanged();
+ }
+ }
+}
+
+void QDeclarative1TextInput::updateCursorRectangle()
+{
+ Q_D(QDeclarative1TextInput);
+ d->updateHorizontalScroll();
+ updateRect();//TODO: Only update rect between pos's
+ updateMicroFocus();
+ emit cursorRectangleChanged();
+ if (d->cursorItem)
+ d->cursorItem->setX(d->control->cursorToX() - d->hscroll);
+}
+
+void QDeclarative1TextInput::selectionChanged()
+{
+ Q_D(QDeclarative1TextInput);
+ updateRect();//TODO: Only update rect in selection
+ emit selectedTextChanged();
+
+ if(d->lastSelectionStart != d->control->selectionStart()){
+ d->lastSelectionStart = d->control->selectionStart();
+ if(d->lastSelectionStart == -1)
+ d->lastSelectionStart = d->control->cursor();
+ emit selectionStartChanged();
+ }
+ if(d->lastSelectionEnd != d->control->selectionEnd()){
+ d->lastSelectionEnd = d->control->selectionEnd();
+ if(d->lastSelectionEnd == -1)
+ d->lastSelectionEnd = d->control->cursor();
+ emit selectionEndChanged();
+ }
+}
+
+void QDeclarative1TextInput::q_textChanged()
+{
+ Q_D(QDeclarative1TextInput);
+ updateSize();
+ d->determineHorizontalAlignment();
+ d->updateHorizontalScroll();
+ updateMicroFocus();
+ emit textChanged();
+ emit displayTextChanged();
+ if(hasAcceptableInput() != d->oldValidity){
+ d->oldValidity = hasAcceptableInput();
+ emit acceptableInputChanged();
+ }
+}
+
+void QDeclarative1TextInput::updateRect(const QRect &r)
+{
+ Q_D(QDeclarative1TextInput);
+ if(r == QRect())
+ clearCache();
+ else
+ dirtyCache(QRect(r.x() - d->hscroll, r.y(), r.width(), r.height()));
+ update();
+}
+
+QRectF QDeclarative1TextInput::boundingRect() const
+{
+ Q_D(const QDeclarative1TextInput);
+ QRectF r = QDeclarative1PaintedItem::boundingRect();
+
+ int cursorWidth = d->cursorItem ? d->cursorItem->width() : d->control->cursorWidth();
+
+ // Could include font max left/right bearings to either side of rectangle.
+
+ r.setRight(r.right() + cursorWidth);
+ return r;
+}
+
+void QDeclarative1TextInput::updateSize(bool needsRedraw)
+{
+ Q_D(QDeclarative1TextInput);
+ int w = width();
+ int h = height();
+ setImplicitHeight(d->control->height()-1); // -1 to counter QLineControl's +1 which is not consistent with Text.
+ setImplicitWidth(d->calculateTextWidth());
+ setContentsSize(QSize(width(), height()));//Repaints if changed
+ if(w==width() && h==height() && needsRedraw){
+ clearCache();
+ update();
+ }
+}
+
+void QDeclarative1TextInput::q_canPasteChanged()
+{
+ Q_D(QDeclarative1TextInput);
+ bool old = d->canPaste;
+#ifndef QT_NO_CLIPBOARD
+ d->canPaste = !d->control->isReadOnly() && QApplication::clipboard()->text().length() != 0;
+#endif
+ if(d->canPaste != old)
+ emit canPasteChanged();
+}
+
+
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_LINEEDIT
+
diff --git a/src/qtquick1/graphicsitems/qdeclarativetextinput_p.h b/src/qtquick1/graphicsitems/qdeclarativetextinput_p.h
new file mode 100644
index 0000000000..562d1bf08a
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativetextinput_p.h
@@ -0,0 +1,306 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVETEXTINPUT_H
+#define QDECLARATIVETEXTINPUT_H
+
+#include "private/qdeclarativetext_p.h"
+#include "private/qdeclarativeimplicitsizeitem_p.h"
+
+#include <QGraphicsSceneMouseEvent>
+#include <QIntValidator>
+
+#ifndef QT_NO_LINEEDIT
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QValidator;
+class QDeclarative1TextInputPrivate;
+class Q_AUTOTEST_EXPORT QDeclarative1TextInput : public QDeclarative1ImplicitSizePaintedItem
+{
+ Q_OBJECT
+ Q_ENUMS(HAlignment)
+ Q_ENUMS(EchoMode)
+ Q_ENUMS(SelectionMode)
+
+ Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
+ Q_PROPERTY(QColor selectionColor READ selectionColor WRITE setSelectionColor NOTIFY selectionColorChanged)
+ Q_PROPERTY(QColor selectedTextColor READ selectedTextColor WRITE setSelectedTextColor NOTIFY selectedTextColorChanged)
+ Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged)
+ Q_PROPERTY(HAlignment horizontalAlignment READ hAlign WRITE setHAlign RESET resetHAlign NOTIFY horizontalAlignmentChanged)
+ Q_PROPERTY(HAlignment effectiveHorizontalAlignment READ effectiveHAlign NOTIFY effectiveHorizontalAlignmentChanged REVISION 1)
+ Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly NOTIFY readOnlyChanged)
+ Q_PROPERTY(bool cursorVisible READ isCursorVisible WRITE setCursorVisible NOTIFY cursorVisibleChanged)
+ Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition NOTIFY cursorPositionChanged)
+ Q_PROPERTY(QRect cursorRectangle READ cursorRectangle NOTIFY cursorRectangleChanged)
+ Q_PROPERTY(QDeclarativeComponent *cursorDelegate READ cursorDelegate WRITE setCursorDelegate NOTIFY cursorDelegateChanged)
+ Q_PROPERTY(int selectionStart READ selectionStart NOTIFY selectionStartChanged)
+ Q_PROPERTY(int selectionEnd READ selectionEnd NOTIFY selectionEndChanged)
+ Q_PROPERTY(QString selectedText READ selectedText NOTIFY selectedTextChanged)
+
+ Q_PROPERTY(int maximumLength READ maxLength WRITE setMaxLength NOTIFY maximumLengthChanged)
+#ifndef QT_NO_VALIDATOR
+ Q_PROPERTY(QValidator* validator READ validator WRITE setValidator NOTIFY validatorChanged)
+#endif
+ Q_PROPERTY(QString inputMask READ inputMask WRITE setInputMask NOTIFY inputMaskChanged)
+ Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ imHints WRITE setIMHints)
+
+ Q_PROPERTY(bool acceptableInput READ hasAcceptableInput NOTIFY acceptableInputChanged)
+ Q_PROPERTY(EchoMode echoMode READ echoMode WRITE setEchoMode NOTIFY echoModeChanged)
+ Q_PROPERTY(bool activeFocusOnPress READ focusOnPress WRITE setFocusOnPress NOTIFY activeFocusOnPressChanged)
+ Q_PROPERTY(QString passwordCharacter READ passwordCharacter WRITE setPasswordCharacter NOTIFY passwordCharacterChanged)
+ Q_PROPERTY(QString displayText READ displayText NOTIFY displayTextChanged)
+ Q_PROPERTY(bool autoScroll READ autoScroll WRITE setAutoScroll NOTIFY autoScrollChanged)
+ Q_PROPERTY(bool selectByMouse READ selectByMouse WRITE setSelectByMouse NOTIFY selectByMouseChanged)
+ Q_PROPERTY(SelectionMode mouseSelectionMode READ mouseSelectionMode WRITE setMouseSelectionMode NOTIFY mouseSelectionModeChanged REVISION 1)
+ Q_PROPERTY(bool canPaste READ canPaste NOTIFY canPasteChanged REVISION 1)
+ Q_PROPERTY(bool inputMethodComposing READ isInputMethodComposing NOTIFY inputMethodComposingChanged REVISION 1)
+
+public:
+ QDeclarative1TextInput(QDeclarativeItem* parent=0);
+ ~QDeclarative1TextInput();
+
+ enum EchoMode {//To match QLineEdit::EchoMode
+ Normal,
+ NoEcho,
+ Password,
+ PasswordEchoOnEdit
+ };
+
+ enum HAlignment {
+ AlignLeft = Qt::AlignLeft,
+ AlignRight = Qt::AlignRight,
+ AlignHCenter = Qt::AlignHCenter
+ };
+
+ enum SelectionMode {
+ SelectCharacters,
+ SelectWords
+ };
+
+ enum CursorPosition {
+ CursorBetweenCharacters,
+ CursorOnCharacter
+ };
+
+ //Auxilliary functions needed to control the TextInput from QML
+ Q_INVOKABLE int positionAt(int x) const;
+ Q_INVOKABLE Q_REVISION(1) int positionAt(int x, CursorPosition position) const;
+ Q_INVOKABLE QRectF positionToRectangle(int pos) const;
+ Q_INVOKABLE void moveCursorSelection(int pos);
+ Q_INVOKABLE Q_REVISION(1) void moveCursorSelection(int pos, SelectionMode mode);
+
+ Q_INVOKABLE void openSoftwareInputPanel();
+ Q_INVOKABLE void closeSoftwareInputPanel();
+
+ QString text() const;
+ void setText(const QString &);
+
+ QFont font() const;
+ void setFont(const QFont &font);
+
+ QColor color() const;
+ void setColor(const QColor &c);
+
+ QColor selectionColor() const;
+ void setSelectionColor(const QColor &c);
+
+ QColor selectedTextColor() const;
+ void setSelectedTextColor(const QColor &c);
+
+ HAlignment hAlign() const;
+ void setHAlign(HAlignment align);
+ void resetHAlign();
+ HAlignment effectiveHAlign() const;
+
+ bool isReadOnly() const;
+ void setReadOnly(bool);
+
+ bool isCursorVisible() const;
+ void setCursorVisible(bool on);
+
+ int cursorPosition() const;
+ void setCursorPosition(int cp);
+
+ QRect cursorRectangle() const;
+
+ int selectionStart() const;
+ int selectionEnd() const;
+
+ QString selectedText() const;
+
+ int maxLength() const;
+ void setMaxLength(int ml);
+
+#ifndef QT_NO_VALIDATOR
+ QValidator * validator() const;
+ void setValidator(QValidator* v);
+#endif
+ QString inputMask() const;
+ void setInputMask(const QString &im);
+
+ EchoMode echoMode() const;
+ void setEchoMode(EchoMode echo);
+
+ QString passwordCharacter() const;
+ void setPasswordCharacter(const QString &str);
+
+ QString displayText() const;
+
+ QDeclarativeComponent* cursorDelegate() const;
+ void setCursorDelegate(QDeclarativeComponent*);
+
+ bool focusOnPress() const;
+ void setFocusOnPress(bool);
+
+ bool autoScroll() const;
+ void setAutoScroll(bool);
+
+ bool selectByMouse() const;
+ void setSelectByMouse(bool);
+
+ SelectionMode mouseSelectionMode() const;
+ void setMouseSelectionMode(SelectionMode mode);
+
+ bool hasAcceptableInput() const;
+
+ void drawContents(QPainter *p,const QRect &r);
+ QVariant inputMethodQuery(Qt::InputMethodQuery property) const;
+
+ QRectF boundingRect() const;
+ bool canPaste() const;
+
+ bool isInputMethodComposing() const;
+
+ Qt::InputMethodHints imHints() const;
+ void setIMHints(Qt::InputMethodHints hints);
+
+Q_SIGNALS:
+ void textChanged();
+ void cursorPositionChanged();
+ void cursorRectangleChanged();
+ void selectionStartChanged();
+ void selectionEndChanged();
+ void selectedTextChanged();
+ void accepted();
+ void acceptableInputChanged();
+ void colorChanged(const QColor &color);
+ void selectionColorChanged(const QColor &color);
+ void selectedTextColorChanged(const QColor &color);
+ void fontChanged(const QFont &font);
+ void horizontalAlignmentChanged(HAlignment alignment);
+ void readOnlyChanged(bool isReadOnly);
+ void cursorVisibleChanged(bool isCursorVisible);
+ void cursorDelegateChanged();
+ void maximumLengthChanged(int maximumLength);
+ void validatorChanged();
+ void inputMaskChanged(const QString &inputMask);
+ void echoModeChanged(EchoMode echoMode);
+ void passwordCharacterChanged();
+ void displayTextChanged();
+ void activeFocusOnPressChanged(bool activeFocusOnPress);
+ void autoScrollChanged(bool autoScroll);
+ void selectByMouseChanged(bool selectByMouse);
+ Q_REVISION(1) void mouseSelectionModeChanged(SelectionMode mode);
+ Q_REVISION(1) void canPasteChanged();
+ Q_REVISION(1) void inputMethodComposingChanged();
+ Q_REVISION(1) void effectiveHorizontalAlignmentChanged();
+
+protected:
+ virtual void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry);
+
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+ void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
+ bool sceneEvent(QEvent *event);
+ void keyPressEvent(QKeyEvent* ev);
+ void inputMethodEvent(QInputMethodEvent *);
+ bool event(QEvent *e);
+ void focusInEvent(QFocusEvent *event);
+
+public Q_SLOTS:
+ void selectAll();
+ void selectWord();
+ void select(int start, int end);
+ Q_REVISION(1) void deselect();
+ Q_REVISION(1) bool isRightToLeft(int start, int end);
+#ifndef QT_NO_CLIPBOARD
+ void cut();
+ void copy();
+ void paste();
+#endif
+
+private Q_SLOTS:
+ void updateSize(bool needsRedraw = true);
+ void q_textChanged();
+ void selectionChanged();
+ void createCursor();
+ void cursorPosChanged();
+ void updateCursorRectangle();
+ void updateRect(const QRect &r = QRect());
+ void q_canPasteChanged();
+
+private:
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarative1TextInput)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1TextInput)
+#ifndef QT_NO_VALIDATOR
+QML_DECLARE_TYPE(QValidator)
+QML_DECLARE_TYPE(QIntValidator)
+QML_DECLARE_TYPE(QDoubleValidator)
+QML_DECLARE_TYPE(QRegExpValidator)
+#endif
+
+QT_END_HEADER
+
+#endif // QT_NO_LINEEDIT
+
+#endif // QDECLARATIVETEXTINPUT_H
diff --git a/src/qtquick1/graphicsitems/qdeclarativetextinput_p_p.h b/src/qtquick1/graphicsitems/qdeclarativetextinput_p_p.h
new file mode 100644
index 0000000000..4132db65f3
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativetextinput_p_p.h
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVETEXTINPUT_P_H
+#define QDECLARATIVETEXTINPUT_P_H
+
+#include "private/qdeclarativetextinput_p.h"
+
+#include "private/qdeclarativeimplicitsizeitem_p_p.h"
+
+#include <QtDeclarative/qdeclarative.h>
+
+#include <QPointer>
+
+#include <private/qlinecontrol_p.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef QT_NO_LINEEDIT
+
+QT_BEGIN_NAMESPACE
+
+class Q_AUTOTEST_EXPORT QDeclarative1TextInputPrivate : public QDeclarative1ImplicitSizePaintedItemPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1TextInput)
+public:
+ QDeclarative1TextInputPrivate() : control(new QLineControl),
+ color((QRgb)0), style(QDeclarative1Text::Normal),
+ styleColor((QRgb)0), hAlign(QDeclarative1TextInput::AlignLeft),
+ mouseSelectionMode(QDeclarative1TextInput::SelectCharacters), inputMethodHints(Qt::ImhNone),
+ hscroll(0), oldScroll(0), oldValidity(false), focused(false), focusOnPress(true),
+ showInputPanelOnFocus(true), clickCausedFocus(false), cursorVisible(false),
+ autoScroll(true), selectByMouse(false), canPaste(false), hAlignImplicit(true),
+ selectPressed(false)
+ {
+#ifdef Q_OS_SYMBIAN
+ if (QSysInfo::symbianVersion() == QSysInfo::SV_SF_1 || QSysInfo::symbianVersion() == QSysInfo::SV_SF_3) {
+ showInputPanelOnFocus = false;
+ }
+#endif
+ }
+
+ ~QDeclarative1TextInputPrivate()
+ {
+ }
+
+ int xToPos(int x, QTextLine::CursorPosition betweenOrOn = QTextLine::CursorBetweenCharacters) const
+ {
+ Q_Q(const QDeclarative1TextInput);
+ QRect cr = q->boundingRect().toRect();
+ x-= cr.x() - hscroll;
+ return control->xToPos(x, betweenOrOn);
+ }
+
+ void init();
+ void startCreatingCursor();
+ void focusChanged(bool hasFocus);
+ void updateHorizontalScroll();
+ bool determineHorizontalAlignment();
+ bool setHAlign(QDeclarative1TextInput::HAlignment, bool forceAlign = false);
+ void mirrorChange();
+ int calculateTextWidth();
+ bool sendMouseEventToInputContext(QGraphicsSceneMouseEvent *event, QEvent::Type eventType);
+ void updateInputMethodHints();
+
+ QLineControl* control;
+
+ QFont font;
+ QFont sourceFont;
+ QColor color;
+ QColor selectionColor;
+ QColor selectedTextColor;
+ QDeclarative1Text::TextStyle style;
+ QColor styleColor;
+ QDeclarative1TextInput::HAlignment hAlign;
+ QDeclarative1TextInput::SelectionMode mouseSelectionMode;
+ Qt::InputMethodHints inputMethodHints;
+ QPointer<QDeclarativeComponent> cursorComponent;
+ QPointer<QDeclarativeItem> cursorItem;
+ QPointF pressPos;
+
+ int lastSelectionStart;
+ int lastSelectionEnd;
+ int oldHeight;
+ int oldWidth;
+ int hscroll;
+ int oldScroll;
+ bool oldValidity:1;
+ bool focused:1;
+ bool focusOnPress:1;
+ bool showInputPanelOnFocus:1;
+ bool clickCausedFocus:1;
+ bool cursorVisible:1;
+ bool autoScroll:1;
+ bool selectByMouse:1;
+ bool canPaste:1;
+ bool hAlignImplicit:1;
+ bool selectPressed:1;
+
+ static inline QDeclarative1TextInputPrivate *get(QDeclarative1TextInput *t) {
+ return t->d_func();
+ }
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_LINEEDIT
+
+#endif
+
diff --git a/src/qtquick1/graphicsitems/qdeclarativetextlayout.cpp b/src/qtquick1/graphicsitems/qdeclarativetextlayout.cpp
new file mode 100644
index 0000000000..454b611783
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativetextlayout.cpp
@@ -0,0 +1,395 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdeclarativetextlayout_p.h"
+#include <private/qstatictext_p.h>
+#include <private/qfontengine_p.h>
+#include <private/qtextengine_p.h>
+#include <private/qpainter_p.h>
+#include <private/qpaintengineex_p.h>
+
+QT_BEGIN_NAMESPACE
+
+// Defined in qpainter.cpp
+extern Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray,
+ const QFixedPoint *positions, int glyphCount,
+ QFontEngine *fontEngine, const QFont &font,
+ const QTextCharFormat &charFormat);
+
+
+
+class QDeclarative1TextLayoutPrivate
+{
+public:
+ QDeclarative1TextLayoutPrivate()
+ : cached(false) {}
+
+ QPointF position;
+
+ bool cached;
+ QVector<QStaticTextItem> items;
+ QVector<QFixedPoint> positions;
+ QVector<glyph_t> glyphs;
+ QVector<QChar> chars;
+};
+
+namespace {
+class DrawTextItemRecorder: public QPaintEngine
+{
+ public:
+ DrawTextItemRecorder(bool untransformedCoordinates, bool useBackendOptimizations)
+ : m_inertText(0), m_dirtyPen(false), m_useBackendOptimizations(useBackendOptimizations),
+ m_untransformedCoordinates(untransformedCoordinates), m_currentColor(Qt::black)
+ {
+ }
+
+ virtual void updateState(const QPaintEngineState &newState)
+ {
+ if (newState.state() & QPaintEngine::DirtyPen
+ && newState.pen().color() != m_currentColor) {
+ m_dirtyPen = true;
+ m_currentColor = newState.pen().color();
+ }
+ }
+
+ virtual void drawTextItem(const QPointF &position, const QTextItem &textItem)
+ {
+ int glyphOffset = m_inertText->glyphs.size(); // Store offset into glyph pool
+ int positionOffset = m_inertText->glyphs.size(); // Offset into position pool
+ int charOffset = m_inertText->chars.size();
+
+ const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
+
+ bool needFreshCurrentItem = true;
+ if (!m_inertText->items.isEmpty()) {
+ QStaticTextItem &last = m_inertText->items[m_inertText->items.count() - 1];
+
+ if (last.fontEngine() == ti.fontEngine && last.font == ti.font() &&
+ (!m_dirtyPen || last.color == state->pen().color())) {
+ needFreshCurrentItem = false;
+
+ last.numChars += ti.num_chars;
+
+ }
+ }
+
+ if (needFreshCurrentItem) {
+ QStaticTextItem currentItem;
+
+ currentItem.setFontEngine(ti.fontEngine);
+ currentItem.font = ti.font();
+ currentItem.charOffset = charOffset;
+ currentItem.numChars = ti.num_chars;
+ currentItem.numGlyphs = 0;
+ currentItem.glyphOffset = glyphOffset;
+ currentItem.positionOffset = positionOffset;
+ currentItem.useBackendOptimizations = m_useBackendOptimizations;
+ if (m_dirtyPen)
+ currentItem.color = m_currentColor;
+
+ m_inertText->items.append(currentItem);
+ }
+
+ QStaticTextItem &currentItem = m_inertText->items.last();
+
+ QTransform matrix = m_untransformedCoordinates ? QTransform() : state->transform();
+ matrix.translate(position.x(), position.y());
+
+ QVarLengthArray<glyph_t> glyphs;
+ QVarLengthArray<QFixedPoint> positions;
+ ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
+
+ int size = glyphs.size();
+ Q_ASSERT(size == positions.size());
+ currentItem.numGlyphs += size;
+
+ m_inertText->glyphs.resize(m_inertText->glyphs.size() + size);
+ m_inertText->positions.resize(m_inertText->glyphs.size());
+ m_inertText->chars.resize(m_inertText->chars.size() + ti.num_chars);
+
+ glyph_t *glyphsDestination = m_inertText->glyphs.data() + glyphOffset;
+ qMemCopy(glyphsDestination, glyphs.constData(), sizeof(glyph_t) * size);
+
+ QFixedPoint *positionsDestination = m_inertText->positions.data() + positionOffset;
+ qMemCopy(positionsDestination, positions.constData(), sizeof(QFixedPoint) * size);
+
+ QChar *charsDestination = m_inertText->chars.data() + charOffset;
+ qMemCopy(charsDestination, ti.chars, sizeof(QChar) * ti.num_chars);
+
+ }
+
+ virtual void drawPolygon(const QPointF *, int , PolygonDrawMode )
+ {
+ /* intentionally empty */
+ }
+
+ virtual bool begin(QPaintDevice *) { return true; }
+ virtual bool end() { return true; }
+ virtual void drawPixmap(const QRectF &, const QPixmap &, const QRectF &) {}
+ virtual Type type() const
+ {
+ return User;
+ }
+
+ void begin(QDeclarative1TextLayoutPrivate *t) {
+ m_inertText = t;
+ m_dirtyPen = false;
+ }
+
+ private:
+ QDeclarative1TextLayoutPrivate *m_inertText;
+
+ bool m_dirtyPen;
+ bool m_useBackendOptimizations;
+ bool m_untransformedCoordinates;
+ QColor m_currentColor;
+};
+
+class DrawTextItemDevice: public QPaintDevice
+{
+ public:
+ DrawTextItemDevice(bool untransformedCoordinates, bool useBackendOptimizations)
+ {
+ m_paintEngine = new DrawTextItemRecorder(untransformedCoordinates,
+ useBackendOptimizations);
+ }
+
+ ~DrawTextItemDevice()
+ {
+ delete m_paintEngine;
+ }
+
+ void begin(QDeclarative1TextLayoutPrivate *t) {
+ m_paintEngine->begin(t);
+ }
+
+ int metric(PaintDeviceMetric m) const
+ {
+ int val;
+ switch (m) {
+ case PdmWidth:
+ case PdmHeight:
+ case PdmWidthMM:
+ case PdmHeightMM:
+ val = 0;
+ break;
+ case PdmDpiX:
+ case PdmPhysicalDpiX:
+ val = qt_defaultDpiX();
+ break;
+ case PdmDpiY:
+ case PdmPhysicalDpiY:
+ val = qt_defaultDpiY();
+ break;
+ case PdmNumColors:
+ val = 16777216;
+ break;
+ case PdmDepth:
+ val = 24;
+ break;
+ default:
+ val = 0;
+ qWarning("DrawTextItemDevice::metric: Invalid metric command");
+ }
+ return val;
+ }
+
+ virtual QPaintEngine *paintEngine() const
+ {
+ return m_paintEngine;
+ }
+
+ private:
+ DrawTextItemRecorder *m_paintEngine;
+};
+
+struct InertTextPainter {
+ InertTextPainter()
+ : device(true, true), painter(&device) {}
+
+ DrawTextItemDevice device;
+ QPainter painter;
+};
+}
+
+Q_GLOBAL_STATIC(InertTextPainter, inertTextPainter);
+
+/*!
+\class QDeclarative1TextLayout
+\brief The QDeclarative1TextLayout class is a version of QStaticText that works with QTextLayouts.
+\internal
+
+This class is basically a copy of the QStaticText code, but it is adapted to source its text from
+QTextLayout.
+
+It is also considerably faster to create a QDeclarative1TextLayout than a QStaticText because it uses
+a single, shared QPainter instance. QStaticText by comparison creates a new QPainter per instance.
+As a consequence this means that QDeclarative1TextLayout is not re-enterant. Adding a lock around
+the shared painter solves this, and only introduces a minor performance penalty, but is unnecessary
+for QDeclarative1TextLayout's current use (QDeclarative1Text is already tied to the GUI thread).
+*/
+
+QDeclarative1TextLayout::QDeclarative1TextLayout()
+: d(0)
+{
+}
+
+QDeclarative1TextLayout::QDeclarative1TextLayout(const QString &text)
+: QTextLayout(text), d(0)
+{
+}
+
+QDeclarative1TextLayout::~QDeclarative1TextLayout()
+{
+ if (d) delete d;
+}
+
+void QDeclarative1TextLayout::beginLayout()
+{
+ if (d && d->cached) {
+ d->cached = false;
+ d->items.clear();
+ d->positions.clear();
+ d->glyphs.clear();
+ d->chars.clear();
+ d->position = QPointF();
+ }
+ QTextLayout::beginLayout();
+}
+
+void QDeclarative1TextLayout::clearLayout()
+{
+ if (d && d->cached) {
+ d->cached = false;
+ d->items.clear();
+ d->positions.clear();
+ d->glyphs.clear();
+ d->chars.clear();
+ d->position = QPointF();
+ }
+ QTextLayout::clearLayout();
+}
+
+void QDeclarative1TextLayout::prepare()
+{
+ if (!d || !d->cached) {
+
+ if (!d)
+ d = new QDeclarative1TextLayoutPrivate;
+
+ InertTextPainter *itp = inertTextPainter();
+ itp->device.begin(d);
+ QTextLayout::draw(&itp->painter, QPointF(0, 0));
+
+ glyph_t *glyphPool = d->glyphs.data();
+ QFixedPoint *positionPool = d->positions.data();
+ QChar *charPool = d->chars.data();
+
+ int itemCount = d->items.count();
+ for (int ii = 0; ii < itemCount; ++ii) {
+ QStaticTextItem &item = d->items[ii];
+ item.glyphs = glyphPool + item.glyphOffset;
+ item.glyphPositions = positionPool + item.positionOffset;
+ item.chars = charPool + item.charOffset;
+ }
+
+ d->cached = true;
+ }
+}
+
+void QDeclarative1TextLayout::draw(QPainter *painter, const QPointF &p)
+{
+ QPainterPrivate *priv = QPainterPrivate::get(painter);
+
+ bool paintEngineSupportsTransformations = priv->extended &&
+ (priv->extended->type() == QPaintEngine::OpenGL2 ||
+ priv->extended->type() == QPaintEngine::OpenVG ||
+ priv->extended->type() == QPaintEngine::OpenGL);
+
+ if (!paintEngineSupportsTransformations || !priv->state->matrix.isAffine()) {
+ QTextLayout::draw(painter, p);
+ return;
+ }
+
+ prepare();
+
+ int itemCount = d->items.count();
+
+ if (p != d->position) {
+ QFixed fx = QFixed::fromReal(p.x());
+ QFixed fy = QFixed::fromReal(p.y());
+ QFixed oldX = QFixed::fromReal(d->position.x());
+ QFixed oldY = QFixed::fromReal(d->position.y());
+ for (int item = 0; item < itemCount; ++item) {
+ QStaticTextItem &textItem = d->items[item];
+
+ for (int ii = 0; ii < textItem.numGlyphs; ++ii) {
+ textItem.glyphPositions[ii].x += fx - oldX;
+ textItem.glyphPositions[ii].y += fy - oldY;
+ }
+ textItem.userDataNeedsUpdate = true;
+ }
+
+ d->position = p;
+ }
+
+ QPen oldPen = priv->state->pen;
+ QColor currentColor = oldPen.color();
+ for (int ii = 0; ii < itemCount; ++ii) {
+ QStaticTextItem &item = d->items[ii];
+ if (item.color.isValid() && currentColor != item.color) {
+ painter->setPen(item.color);
+ currentColor = item.color;
+ }
+ priv->extended->drawStaticTextItem(&item);
+
+ qt_draw_decoration_for_glyphs(painter, item.glyphs, item.glyphPositions,
+ item.numGlyphs, item.fontEngine(), painter->font(),
+ QTextCharFormat());
+ }
+ if (currentColor != oldPen.color())
+ painter->setPen(oldPen);
+}
+
+
+
+QT_END_NAMESPACE
+
diff --git a/src/qtquick1/graphicsitems/qdeclarativetextlayout_p.h b/src/qtquick1/graphicsitems/qdeclarativetextlayout_p.h
new file mode 100644
index 0000000000..bfedbec958
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativetextlayout_p.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVETEXTLAYOUT_P_H
+#define QDECLARATIVETEXTLAYOUT_P_H
+
+#include <QtGui/qtextlayout.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarative1TextLayoutPrivate;
+class QDeclarative1TextLayout : public QTextLayout
+{
+public:
+ QDeclarative1TextLayout();
+ QDeclarative1TextLayout(const QString &);
+ ~QDeclarative1TextLayout();
+
+ void beginLayout();
+ void clearLayout();
+
+ void prepare();
+ void draw(QPainter *, const QPointF & = QPointF());
+
+private:
+ QDeclarative1TextLayoutPrivate *d;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVETEXTLAYOUT_P_H
diff --git a/src/qtquick1/graphicsitems/qdeclarativetranslate.cpp b/src/qtquick1/graphicsitems/qdeclarativetranslate.cpp
new file mode 100644
index 0000000000..66173efc6c
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativetranslate.cpp
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qdeclarativetranslate_p.h"
+#include <private/qgraphicstransform_p.h>
+#include <QDebug>
+#include <QtCore/qmath.h>
+
+QT_BEGIN_NAMESPACE
+
+
+
+class QDeclarative1TranslatePrivate : public QGraphicsTransformPrivate
+{
+public:
+ QDeclarative1TranslatePrivate()
+ : x(0), y(0) {}
+ qreal x;
+ qreal y;
+};
+
+/*!
+ Constructs an empty QDeclarative1Translate object with the given \a parent.
+*/
+QDeclarative1Translate::QDeclarative1Translate(QObject *parent)
+ : QGraphicsTransform(*new QDeclarative1TranslatePrivate, parent)
+{
+}
+
+/*!
+ Destroys the graphics scale.
+*/
+QDeclarative1Translate::~QDeclarative1Translate()
+{
+}
+
+/*!
+ \property QDeclarative1Translate::x
+ \brief the horizontal translation.
+
+ The translation can be any real number; the default value is 0.0.
+
+ \sa y
+*/
+qreal QDeclarative1Translate::x() const
+{
+ Q_D(const QDeclarative1Translate);
+ return d->x;
+}
+void QDeclarative1Translate::setX(qreal x)
+{
+ Q_D(QDeclarative1Translate);
+ if (d->x == x)
+ return;
+ d->x = x;
+ update();
+ emit xChanged();
+}
+
+/*!
+ \property QDeclarative1Translate::y
+ \brief the vertical translation.
+
+ The translation can be any real number; the default value is 0.0.
+
+ \sa x
+*/
+qreal QDeclarative1Translate::y() const
+{
+ Q_D(const QDeclarative1Translate);
+ return d->y;
+}
+void QDeclarative1Translate::setY(qreal y)
+{
+ Q_D(QDeclarative1Translate);
+ if (d->y == y)
+ return;
+ d->y = y;
+ update();
+ emit yChanged();
+}
+
+void QDeclarative1Translate::applyTo(QMatrix4x4 *matrix) const
+{
+ Q_D(const QDeclarative1Translate);
+ matrix->translate(d->x, d->y, 0);
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/graphicsitems/qdeclarativetranslate_p.h b/src/qtquick1/graphicsitems/qdeclarativetranslate_p.h
new file mode 100644
index 0000000000..be5cd74486
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativetranslate_p.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVETRANSLATE_H
+#define QDECLARATIVETRANSLATE_H
+
+#include "qdeclarativeitem.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarative1TranslatePrivate;
+
+class Q_AUTOTEST_EXPORT QDeclarative1Translate : public QGraphicsTransform
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)
+ Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged)
+
+public:
+ QDeclarative1Translate(QObject *parent = 0);
+ ~QDeclarative1Translate();
+
+ qreal x() const;
+ void setX(qreal);
+
+ qreal y() const;
+ void setY(qreal);
+
+ void applyTo(QMatrix4x4 *matrix) const;
+
+Q_SIGNALS:
+ void xChanged();
+ void yChanged();
+
+private:
+ Q_DECLARE_PRIVATE(QDeclarative1Translate)
+ Q_DISABLE_COPY(QDeclarative1Translate)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1Translate)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/qtquick1/graphicsitems/qdeclarativevisualitemmodel.cpp b/src/qtquick1/graphicsitems/qdeclarativevisualitemmodel.cpp
new file mode 100644
index 0000000000..e712ca1888
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativevisualitemmodel.cpp
@@ -0,0 +1,1429 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativevisualitemmodel_p.h"
+
+#include "QtQuick1/qdeclarativeitem.h"
+
+#include <QtDeclarative/qdeclarativecontext.h>
+#include <QtDeclarative/private/qdeclarativecontext_p.h>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativeexpression.h>
+#include <QtQuick1/private/qdeclarativepackage_p.h>
+#include <QtQuick1/private/qdeclarativeopenmetaobject_p.h>
+#include <QtQuick1/private/qdeclarativelistaccessor_p.h>
+#include <QtDeclarative/qdeclarativeinfo.h>
+#include <QtDeclarative/private/qdeclarativedata_p.h>
+#include <QtDeclarative/private/qdeclarativepropertycache_p.h>
+#include <QtDeclarative/private/qdeclarativeguard_p.h>
+#include <QtDeclarative/private/qdeclarativeglobal_p.h>
+
+#include <qgraphicsscene.h>
+#include <QtDeclarative/private/qlistmodelinterface_p.h>
+#include <qhash.h>
+#include <qlist.h>
+#include <QtDeclarative/private/qmetaobjectbuilder_p.h>
+#include <QtCore/qdebug.h>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+
+
+QHash<QObject*, QDeclarative1VisualItemModelAttached*> QDeclarative1VisualItemModelAttached::attachedProperties;
+
+
+class QDeclarative1VisualItemModelPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1VisualItemModel)
+public:
+ QDeclarative1VisualItemModelPrivate() : QObjectPrivate() {}
+
+ static void children_append(QDeclarativeListProperty<QDeclarativeItem> *prop, QDeclarativeItem *item) {
+ QDeclarative_setParent_noEvent(item, prop->object);
+ static_cast<QDeclarative1VisualItemModelPrivate *>(prop->data)->children.append(Item(item));
+ static_cast<QDeclarative1VisualItemModelPrivate *>(prop->data)->itemAppended();
+ static_cast<QDeclarative1VisualItemModelPrivate *>(prop->data)->emitChildrenChanged();
+ }
+
+ static int children_count(QDeclarativeListProperty<QDeclarativeItem> *prop) {
+ return static_cast<QDeclarative1VisualItemModelPrivate *>(prop->data)->children.count();
+ }
+
+ static QDeclarativeItem *children_at(QDeclarativeListProperty<QDeclarativeItem> *prop, int index) {
+ return static_cast<QDeclarative1VisualItemModelPrivate *>(prop->data)->children.at(index).item;
+ }
+
+ void itemAppended() {
+ Q_Q(QDeclarative1VisualItemModel);
+ QDeclarative1VisualItemModelAttached *attached = QDeclarative1VisualItemModelAttached::properties(children.last().item);
+ attached->setIndex(children.count()-1);
+ emit q->itemsInserted(children.count()-1, 1);
+ emit q->countChanged();
+ }
+
+ void emitChildrenChanged() {
+ Q_Q(QDeclarative1VisualItemModel);
+ emit q->childrenChanged();
+ }
+
+ int indexOf(QDeclarativeItem *item) const {
+ for (int i = 0; i < children.count(); ++i)
+ if (children.at(i).item == item)
+ return i;
+ return -1;
+ }
+
+ class Item {
+ public:
+ Item(QDeclarativeItem *i) : item(i), ref(0) {}
+
+ void addRef() { ++ref; }
+ bool deref() { return --ref == 0; }
+
+ QDeclarativeItem *item;
+ int ref;
+ };
+
+ QList<Item> children;
+};
+
+
+/*!
+ \qmlclass VisualItemModel QDeclarative1VisualItemModel
+ \ingroup qml-working-with-data
+ \since 4.7
+ \brief The VisualItemModel allows items to be provided to a view.
+
+ A VisualItemModel contains the visual items to be used in a view.
+ When a VisualItemModel is used in a view, the view does not require
+ a delegate since the VisualItemModel already contains the visual
+ delegate (items).
+
+ An item can determine its index within the
+ model via the \l{VisualItemModel::index}{index} attached property.
+
+ The example below places three colored rectangles in a ListView.
+ \code
+ import QtQuick 1.0
+
+ Rectangle {
+ VisualItemModel {
+ id: itemModel
+ Rectangle { height: 30; width: 80; color: "red" }
+ Rectangle { height: 30; width: 80; color: "green" }
+ Rectangle { height: 30; width: 80; color: "blue" }
+ }
+
+ ListView {
+ anchors.fill: parent
+ model: itemModel
+ }
+ }
+ \endcode
+
+ \image visualitemmodel.png
+
+ \sa {declarative/modelviews/visualitemmodel}{VisualItemModel example}
+*/
+QDeclarative1VisualItemModel::QDeclarative1VisualItemModel(QObject *parent)
+ : QDeclarative1VisualModel(*(new QDeclarative1VisualItemModelPrivate), parent)
+{
+}
+
+/*!
+ \qmlattachedproperty int VisualItemModel::index
+ This attached property holds the index of this delegate's item within the model.
+
+ It is attached to each instance of the delegate.
+*/
+
+QDeclarativeListProperty<QDeclarativeItem> QDeclarative1VisualItemModel::children()
+{
+ Q_D(QDeclarative1VisualItemModel);
+ return QDeclarativeListProperty<QDeclarativeItem>(this, d, d->children_append,
+ d->children_count, d->children_at);
+}
+
+/*!
+ \qmlproperty int VisualItemModel::count
+
+ The number of items in the model. This property is readonly.
+*/
+int QDeclarative1VisualItemModel::count() const
+{
+ Q_D(const QDeclarative1VisualItemModel);
+ return d->children.count();
+}
+
+bool QDeclarative1VisualItemModel::isValid() const
+{
+ return true;
+}
+
+QDeclarativeItem *QDeclarative1VisualItemModel::item(int index, bool)
+{
+ Q_D(QDeclarative1VisualItemModel);
+ QDeclarative1VisualItemModelPrivate::Item &item = d->children[index];
+ item.addRef();
+ return item.item;
+}
+
+QDeclarative1VisualModel::ReleaseFlags QDeclarative1VisualItemModel::release(QDeclarativeItem *item)
+{
+ Q_D(QDeclarative1VisualItemModel);
+ int idx = d->indexOf(item);
+ if (idx >= 0) {
+ if (d->children[idx].deref()) {
+ if (item->scene())
+ item->scene()->removeItem(item);
+ QDeclarative_setParent_noEvent(item, this);
+ }
+ }
+ return 0;
+}
+
+bool QDeclarative1VisualItemModel::completePending() const
+{
+ return false;
+}
+
+void QDeclarative1VisualItemModel::completeItem()
+{
+ // Nothing to do
+}
+
+QString QDeclarative1VisualItemModel::stringValue(int index, const QString &name)
+{
+ Q_D(QDeclarative1VisualItemModel);
+ if (index < 0 || index >= d->children.count())
+ return QString();
+ return QDeclarativeEngine::contextForObject(d->children.at(index).item)->contextProperty(name).toString();
+}
+
+int QDeclarative1VisualItemModel::indexOf(QDeclarativeItem *item, QObject *) const
+{
+ Q_D(const QDeclarative1VisualItemModel);
+ return d->indexOf(item);
+}
+
+QDeclarative1VisualItemModelAttached *QDeclarative1VisualItemModel::qmlAttachedProperties(QObject *obj)
+{
+ return QDeclarative1VisualItemModelAttached::properties(obj);
+}
+
+//============================================================================
+
+class VDMDelegateDataType : public QDeclarative1OpenMetaObjectType
+{
+public:
+ VDMDelegateDataType(const QMetaObject *base, QDeclarativeEngine *engine) : QDeclarative1OpenMetaObjectType(base, engine) {}
+
+ void propertyCreated(int, QMetaPropertyBuilder &prop) {
+ prop.setWritable(false);
+ }
+};
+
+class QDeclarative1VisualDataModelParts;
+class QDeclarative1VisualDataModelData;
+class QDeclarative1VisualDataModelPrivate : public QObjectPrivate
+{
+public:
+ QDeclarative1VisualDataModelPrivate(QDeclarativeContext *);
+
+ static QDeclarative1VisualDataModelPrivate *get(QDeclarative1VisualDataModel *m) {
+ return static_cast<QDeclarative1VisualDataModelPrivate *>(QObjectPrivate::get(m));
+ }
+
+ QDeclarativeGuard<QListModelInterface> m_listModelInterface;
+ QDeclarativeGuard<QAbstractItemModel> m_abstractItemModel;
+ QDeclarativeGuard<QDeclarative1VisualDataModel> m_visualItemModel;
+ QString m_part;
+
+ QDeclarativeComponent *m_delegate;
+ QDeclarativeGuard<QDeclarativeContext> m_context;
+ QList<int> m_roles;
+ QHash<QByteArray,int> m_roleNames;
+ void ensureRoles() {
+ if (m_roleNames.isEmpty()) {
+ if (m_listModelInterface) {
+ m_roles = m_listModelInterface->roles();
+ for (int ii = 0; ii < m_roles.count(); ++ii)
+ m_roleNames.insert(m_listModelInterface->toString(m_roles.at(ii)).toUtf8(), m_roles.at(ii));
+ } else if (m_abstractItemModel) {
+ for (QHash<int,QByteArray>::const_iterator it = m_abstractItemModel->roleNames().begin();
+ it != m_abstractItemModel->roleNames().end(); ++it) {
+ m_roles.append(it.key());
+ m_roleNames.insert(*it, it.key());
+ }
+ if (m_roles.count())
+ m_roleNames.insert("hasModelChildren", -1);
+ } else if (m_listAccessor) {
+ m_roleNames.insert("modelData", 0);
+ if (m_listAccessor->type() == QDeclarative1ListAccessor::Instance) {
+ if (QObject *object = m_listAccessor->at(0).value<QObject*>()) {
+ int count = object->metaObject()->propertyCount();
+ for (int ii = 1; ii < count; ++ii) {
+ const QMetaProperty &prop = object->metaObject()->property(ii);
+ m_roleNames.insert(prop.name(), 0);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ QHash<int,int> m_roleToPropId;
+ int m_modelDataPropId;
+ void createMetaData() {
+ if (!m_metaDataCreated) {
+ ensureRoles();
+ if (m_roleNames.count()) {
+ QHash<QByteArray, int>::const_iterator it = m_roleNames.begin();
+ while (it != m_roleNames.end()) {
+ int propId = m_delegateDataType->createProperty(it.key()) - m_delegateDataType->propertyOffset();
+ m_roleToPropId.insert(*it, propId);
+ ++it;
+ }
+ // Add modelData property
+ if (m_roles.count() == 1)
+ m_modelDataPropId = m_delegateDataType->createProperty("modelData") - m_delegateDataType->propertyOffset();
+ m_metaDataCreated = true;
+ }
+ }
+ }
+
+ struct ObjectRef {
+ ObjectRef(QObject *object=0) : obj(object), ref(1) {}
+ QObject *obj;
+ int ref;
+ };
+ class Cache : public QHash<int, ObjectRef> {
+ public:
+ QObject *getItem(int index) {
+ QObject *item = 0;
+ QHash<int,ObjectRef>::iterator it = find(index);
+ if (it != end()) {
+ (*it).ref++;
+ item = (*it).obj;
+ }
+ return item;
+ }
+ QObject *item(int index) {
+ QObject *item = 0;
+ QHash<int, ObjectRef>::const_iterator it = find(index);
+ if (it != end())
+ item = (*it).obj;
+ return item;
+ }
+ void insertItem(int index, QObject *obj) {
+ insert(index, ObjectRef(obj));
+ }
+ bool releaseItem(QObject *obj) {
+ QHash<int, ObjectRef>::iterator it = begin();
+ for (; it != end(); ++it) {
+ ObjectRef &objRef = *it;
+ if (objRef.obj == obj) {
+ if (--objRef.ref == 0) {
+ erase(it);
+ return true;
+ }
+ break;
+ }
+ }
+ return false;
+ }
+ };
+
+ int modelCount() const {
+ if (m_visualItemModel)
+ return m_visualItemModel->count();
+ if (m_listModelInterface)
+ return m_listModelInterface->count();
+ if (m_abstractItemModel)
+ return m_abstractItemModel->rowCount(m_root);
+ if (m_listAccessor)
+ return m_listAccessor->count();
+ return 0;
+ }
+
+ Cache m_cache;
+ QHash<QObject *, QDeclarative1Package*> m_packaged;
+
+ QDeclarative1VisualDataModelParts *m_parts;
+ friend class QDeclarative1VisualItemParts;
+
+ VDMDelegateDataType *m_delegateDataType;
+ friend class QDeclarative1VisualDataModelData;
+ bool m_metaDataCreated : 1;
+ bool m_metaDataCacheable : 1;
+ bool m_delegateValidated : 1;
+ bool m_completePending : 1;
+
+ QDeclarative1VisualDataModelData *data(QObject *item);
+
+ QVariant m_modelVariant;
+ QDeclarative1ListAccessor *m_listAccessor;
+
+ QModelIndex m_root;
+ QList<QByteArray> watchedRoles;
+ QList<int> watchedRoleIds;
+};
+
+class QDeclarative1VisualDataModelDataMetaObject : public QDeclarative1OpenMetaObject
+{
+public:
+ QDeclarative1VisualDataModelDataMetaObject(QObject *parent, QDeclarative1OpenMetaObjectType *type)
+ : QDeclarative1OpenMetaObject(parent, type) {}
+
+ virtual QVariant initialValue(int);
+ virtual int createProperty(const char *, const char *);
+
+private:
+ friend class QDeclarative1VisualDataModelData;
+};
+
+class QDeclarative1VisualDataModelData : public QObject
+{
+Q_OBJECT
+public:
+ QDeclarative1VisualDataModelData(int index, QDeclarative1VisualDataModel *model);
+ ~QDeclarative1VisualDataModelData();
+
+ Q_PROPERTY(int index READ index NOTIFY indexChanged)
+ int index() const;
+ void setIndex(int index);
+
+ int propForRole(int) const;
+ int modelDataPropertyId() const {
+ QDeclarative1VisualDataModelPrivate *model = QDeclarative1VisualDataModelPrivate::get(m_model);
+ return model->m_modelDataPropId;
+ }
+
+ void setValue(int, const QVariant &);
+ bool hasValue(int id) const {
+ return m_meta->hasValue(id);
+ }
+
+ void ensureProperties();
+
+Q_SIGNALS:
+ void indexChanged();
+
+private:
+ friend class QDeclarative1VisualDataModelDataMetaObject;
+ int m_index;
+ QDeclarativeGuard<QDeclarative1VisualDataModel> m_model;
+ QDeclarative1VisualDataModelDataMetaObject *m_meta;
+};
+
+int QDeclarative1VisualDataModelData::propForRole(int id) const
+{
+ QDeclarative1VisualDataModelPrivate *model = QDeclarative1VisualDataModelPrivate::get(m_model);
+ QHash<int,int>::const_iterator it = model->m_roleToPropId.find(id);
+ if (it != model->m_roleToPropId.end())
+ return *it;
+
+ return -1;
+}
+
+void QDeclarative1VisualDataModelData::setValue(int id, const QVariant &val)
+{
+ m_meta->setValue(id, val);
+}
+
+int QDeclarative1VisualDataModelDataMetaObject::createProperty(const char *name, const char *type)
+{
+ QDeclarative1VisualDataModelData *data =
+ static_cast<QDeclarative1VisualDataModelData *>(object());
+
+ if (!data->m_model)
+ return -1;
+
+ QDeclarative1VisualDataModelPrivate *model = QDeclarative1VisualDataModelPrivate::get(data->m_model);
+ if (data->m_index < 0 || data->m_index >= model->modelCount())
+ return -1;
+
+ if ((!model->m_listModelInterface || !model->m_abstractItemModel) && model->m_listAccessor) {
+ if (model->m_listAccessor->type() == QDeclarative1ListAccessor::ListProperty) {
+ model->ensureRoles();
+ if (qstrcmp(name,"modelData") == 0)
+ return QDeclarative1OpenMetaObject::createProperty(name, type);
+ }
+ }
+ return -1;
+}
+
+QVariant QDeclarative1VisualDataModelDataMetaObject::initialValue(int propId)
+{
+ QDeclarative1VisualDataModelData *data =
+ static_cast<QDeclarative1VisualDataModelData *>(object());
+
+ Q_ASSERT(data->m_model);
+ QDeclarative1VisualDataModelPrivate *model = QDeclarative1VisualDataModelPrivate::get(data->m_model);
+
+ QByteArray propName = name(propId);
+ if ((!model->m_listModelInterface || !model->m_abstractItemModel) && model->m_listAccessor) {
+ if (propName == "modelData") {
+ if (model->m_listAccessor->type() == QDeclarative1ListAccessor::Instance) {
+ QObject *object = model->m_listAccessor->at(0).value<QObject*>();
+ return object->metaObject()->property(1).read(object); // the first property after objectName
+ }
+ return model->m_listAccessor->at(data->m_index);
+ } else {
+ // return any property of a single object instance.
+ QObject *object = model->m_listAccessor->at(data->m_index).value<QObject*>();
+ return object->property(propName);
+ }
+ } else if (model->m_listModelInterface) {
+ model->ensureRoles();
+ QHash<QByteArray,int>::const_iterator it = model->m_roleNames.find(propName);
+ if (it != model->m_roleNames.end()) {
+ QVariant value = model->m_listModelInterface->data(data->m_index, *it);
+ return value;
+ } else if (model->m_roles.count() == 1 && propName == "modelData") {
+ //for compatibility with other lists, assign modelData if there is only a single role
+ QVariant value = model->m_listModelInterface->data(data->m_index, model->m_roles.first());
+ return value;
+ }
+ } else if (model->m_abstractItemModel) {
+ model->ensureRoles();
+ QModelIndex index = model->m_abstractItemModel->index(data->m_index, 0, model->m_root);
+ if (propName == "hasModelChildren") {
+ return model->m_abstractItemModel->hasChildren(index);
+ } else {
+ QHash<QByteArray,int>::const_iterator it = model->m_roleNames.find(propName);
+ if (it != model->m_roleNames.end()) {
+ return model->m_abstractItemModel->data(index, *it);
+ } else if (model->m_roles.count() == 1 && propName == "modelData") {
+ //for compatibility with other lists, assign modelData if there is only a single role
+ return model->m_abstractItemModel->data(index, model->m_roles.first());
+ }
+ }
+ }
+ Q_ASSERT(!"Can never be reached");
+ return QVariant();
+}
+
+QDeclarative1VisualDataModelData::QDeclarative1VisualDataModelData(int index,
+ QDeclarative1VisualDataModel *model)
+: m_index(index), m_model(model),
+m_meta(new QDeclarative1VisualDataModelDataMetaObject(this, QDeclarative1VisualDataModelPrivate::get(model)->m_delegateDataType))
+{
+ ensureProperties();
+}
+
+QDeclarative1VisualDataModelData::~QDeclarative1VisualDataModelData()
+{
+}
+
+void QDeclarative1VisualDataModelData::ensureProperties()
+{
+ QDeclarative1VisualDataModelPrivate *modelPriv = QDeclarative1VisualDataModelPrivate::get(m_model);
+ if (modelPriv->m_metaDataCacheable) {
+ if (!modelPriv->m_metaDataCreated)
+ modelPriv->createMetaData();
+ if (modelPriv->m_metaDataCreated)
+ m_meta->setCached(true);
+ }
+}
+
+int QDeclarative1VisualDataModelData::index() const
+{
+ return m_index;
+}
+
+// This is internal only - it should not be set from qml
+void QDeclarative1VisualDataModelData::setIndex(int index)
+{
+ m_index = index;
+ emit indexChanged();
+}
+
+//---------------------------------------------------------------------------
+
+class QDeclarative1VisualDataModelPartsMetaObject : public QDeclarative1OpenMetaObject
+{
+public:
+ QDeclarative1VisualDataModelPartsMetaObject(QObject *parent)
+ : QDeclarative1OpenMetaObject(parent) {}
+
+ virtual void propertyCreated(int, QMetaPropertyBuilder &);
+ virtual QVariant initialValue(int);
+};
+
+class QDeclarative1VisualDataModelParts : public QObject
+{
+Q_OBJECT
+public:
+ QDeclarative1VisualDataModelParts(QDeclarative1VisualDataModel *parent);
+
+private:
+ friend class QDeclarative1VisualDataModelPartsMetaObject;
+ QDeclarative1VisualDataModel *model;
+};
+
+void QDeclarative1VisualDataModelPartsMetaObject::propertyCreated(int, QMetaPropertyBuilder &prop)
+{
+ prop.setWritable(false);
+}
+
+QVariant QDeclarative1VisualDataModelPartsMetaObject::initialValue(int id)
+{
+ QDeclarative1VisualDataModel *m = new QDeclarative1VisualDataModel;
+ m->setParent(object());
+ m->setPart(QString::fromUtf8(name(id)));
+ m->setModel(QVariant::fromValue(static_cast<QDeclarative1VisualDataModelParts *>(object())->model));
+
+ QVariant var = QVariant::fromValue((QObject *)m);
+ return var;
+}
+
+QDeclarative1VisualDataModelParts::QDeclarative1VisualDataModelParts(QDeclarative1VisualDataModel *parent)
+: QObject(parent), model(parent)
+{
+ new QDeclarative1VisualDataModelPartsMetaObject(this);
+}
+
+QDeclarative1VisualDataModelPrivate::QDeclarative1VisualDataModelPrivate(QDeclarativeContext *ctxt)
+: m_listModelInterface(0), m_abstractItemModel(0), m_visualItemModel(0), m_delegate(0)
+, m_context(ctxt), m_modelDataPropId(-1), m_parts(0), m_delegateDataType(0), m_metaDataCreated(false)
+, m_metaDataCacheable(false), m_delegateValidated(false), m_completePending(false), m_listAccessor(0)
+{
+}
+
+QDeclarative1VisualDataModelData *QDeclarative1VisualDataModelPrivate::data(QObject *item)
+{
+ QDeclarative1VisualDataModelData *dataItem =
+ item->findChild<QDeclarative1VisualDataModelData *>();
+ Q_ASSERT(dataItem);
+ return dataItem;
+}
+
+//---------------------------------------------------------------------------
+
+/*!
+ \qmlclass VisualDataModel QDeclarative1VisualDataModel
+ \ingroup qml-working-with-data
+ \brief The VisualDataModel encapsulates a model and delegate
+
+ A VisualDataModel encapsulates a model and the delegate that will
+ be instantiated for items in the model.
+
+ It is usually not necessary to create VisualDataModel elements.
+ However, it can be useful for manipulating and accessing the \l modelIndex
+ when a QAbstractItemModel subclass is used as the
+ model. Also, VisualDataModel is used together with \l Package to
+ provide delegates to multiple views.
+
+ The example below illustrates using a VisualDataModel with a ListView.
+
+ \snippet doc/src/snippets/declarative/visualdatamodel.qml 0
+*/
+
+QDeclarative1VisualDataModel::QDeclarative1VisualDataModel()
+: QDeclarative1VisualModel(*(new QDeclarative1VisualDataModelPrivate(0)))
+{
+}
+
+QDeclarative1VisualDataModel::QDeclarative1VisualDataModel(QDeclarativeContext *ctxt, QObject *parent)
+: QDeclarative1VisualModel(*(new QDeclarative1VisualDataModelPrivate(ctxt)), parent)
+{
+}
+
+QDeclarative1VisualDataModel::~QDeclarative1VisualDataModel()
+{
+ Q_D(QDeclarative1VisualDataModel);
+ if (d->m_listAccessor)
+ delete d->m_listAccessor;
+ if (d->m_delegateDataType)
+ d->m_delegateDataType->release();
+}
+
+/*!
+ \qmlproperty model VisualDataModel::model
+ This property holds the model providing data for the VisualDataModel.
+
+ The model provides a set of data that is used to create the items
+ for a view. For large or dynamic datasets the model is usually
+ provided by a C++ model object. The C++ model object must be a \l
+ {QAbstractItemModel} subclass or a simple list.
+
+ Models can also be created directly in QML, using a \l{ListModel} or
+ \l{XmlListModel}.
+
+ \sa {qmlmodels}{Data Models}
+*/
+QVariant QDeclarative1VisualDataModel::model() const
+{
+ Q_D(const QDeclarative1VisualDataModel);
+ return d->m_modelVariant;
+}
+
+void QDeclarative1VisualDataModel::setModel(const QVariant &model)
+{
+ Q_D(QDeclarative1VisualDataModel);
+ delete d->m_listAccessor;
+ d->m_listAccessor = 0;
+ d->m_modelVariant = model;
+ if (d->m_listModelInterface) {
+ // Assume caller has released all items.
+ QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsChanged(int,int,QList<int>)),
+ this, SLOT(_q_itemsChanged(int,int,QList<int>)));
+ QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsInserted(int,int)),
+ this, SLOT(_q_itemsInserted(int,int)));
+ QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsRemoved(int,int)),
+ this, SLOT(_q_itemsRemoved(int,int)));
+ QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsMoved(int,int,int)),
+ this, SLOT(_q_itemsMoved(int,int,int)));
+ d->m_listModelInterface = 0;
+ } else if (d->m_abstractItemModel) {
+ QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
+ this, SLOT(_q_rowsInserted(QModelIndex,int,int)));
+ QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsRemoved(QModelIndex,int,int)),
+ this, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
+ QObject::disconnect(d->m_abstractItemModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
+ this, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
+ QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
+ this, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int)));
+ QObject::disconnect(d->m_abstractItemModel, SIGNAL(modelReset()), this, SLOT(_q_modelReset()));
+ QObject::disconnect(d->m_abstractItemModel, SIGNAL(layoutChanged()), this, SLOT(_q_layoutChanged()));
+ d->m_abstractItemModel = 0;
+ } else if (d->m_visualItemModel) {
+ QObject::disconnect(d->m_visualItemModel, SIGNAL(itemsInserted(int,int)),
+ this, SIGNAL(itemsInserted(int,int)));
+ QObject::disconnect(d->m_visualItemModel, SIGNAL(itemsRemoved(int,int)),
+ this, SIGNAL(itemsRemoved(int,int)));
+ QObject::disconnect(d->m_visualItemModel, SIGNAL(itemsMoved(int,int,int)),
+ this, SIGNAL(itemsMoved(int,int,int)));
+ QObject::disconnect(d->m_visualItemModel, SIGNAL(createdPackage(int,QDeclarative1Package*)),
+ this, SLOT(_q_createdPackage(int,QDeclarative1Package*)));
+ QObject::disconnect(d->m_visualItemModel, SIGNAL(destroyingPackage(QDeclarative1Package*)),
+ this, SLOT(_q_destroyingPackage(QDeclarative1Package*)));
+ d->m_visualItemModel = 0;
+ }
+
+ d->m_roles.clear();
+ d->m_roleNames.clear();
+ if (d->m_delegateDataType)
+ d->m_delegateDataType->release();
+ d->m_metaDataCreated = 0;
+ d->m_metaDataCacheable = false;
+ d->m_delegateDataType = new VDMDelegateDataType(&QDeclarative1VisualDataModelData::staticMetaObject, d->m_context?d->m_context->engine():qmlEngine(this));
+
+ QObject *object = qvariant_cast<QObject *>(model);
+ if (object && (d->m_listModelInterface = qobject_cast<QListModelInterface *>(object))) {
+ QObject::connect(d->m_listModelInterface, SIGNAL(itemsChanged(int,int,QList<int>)),
+ this, SLOT(_q_itemsChanged(int,int,QList<int>)));
+ QObject::connect(d->m_listModelInterface, SIGNAL(itemsInserted(int,int)),
+ this, SLOT(_q_itemsInserted(int,int)));
+ QObject::connect(d->m_listModelInterface, SIGNAL(itemsRemoved(int,int)),
+ this, SLOT(_q_itemsRemoved(int,int)));
+ QObject::connect(d->m_listModelInterface, SIGNAL(itemsMoved(int,int,int)),
+ this, SLOT(_q_itemsMoved(int,int,int)));
+ d->m_metaDataCacheable = true;
+ if (d->m_delegate && d->m_listModelInterface->count())
+ emit itemsInserted(0, d->m_listModelInterface->count());
+ return;
+ } else if (object && (d->m_abstractItemModel = qobject_cast<QAbstractItemModel *>(object))) {
+ QObject::connect(d->m_abstractItemModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
+ this, SLOT(_q_rowsInserted(QModelIndex,int,int)));
+ QObject::connect(d->m_abstractItemModel, SIGNAL(rowsRemoved(QModelIndex,int,int)),
+ this, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
+ QObject::connect(d->m_abstractItemModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
+ this, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
+ QObject::connect(d->m_abstractItemModel, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
+ this, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int)));
+ QObject::connect(d->m_abstractItemModel, SIGNAL(modelReset()), this, SLOT(_q_modelReset()));
+ QObject::connect(d->m_abstractItemModel, SIGNAL(layoutChanged()), this, SLOT(_q_layoutChanged()));
+ d->m_metaDataCacheable = true;
+ if (d->m_abstractItemModel->canFetchMore(d->m_root))
+ d->m_abstractItemModel->fetchMore(d->m_root);
+ return;
+ }
+ if ((d->m_visualItemModel = qvariant_cast<QDeclarative1VisualDataModel *>(model))) {
+ QObject::connect(d->m_visualItemModel, SIGNAL(itemsInserted(int,int)),
+ this, SIGNAL(itemsInserted(int,int)));
+ QObject::connect(d->m_visualItemModel, SIGNAL(itemsRemoved(int,int)),
+ this, SIGNAL(itemsRemoved(int,int)));
+ QObject::connect(d->m_visualItemModel, SIGNAL(itemsMoved(int,int,int)),
+ this, SIGNAL(itemsMoved(int,int,int)));
+ QObject::connect(d->m_visualItemModel, SIGNAL(createdPackage(int,QDeclarative1Package*)),
+ this, SLOT(_q_createdPackage(int,QDeclarative1Package*)));
+ QObject::connect(d->m_visualItemModel, SIGNAL(destroyingPackage(QDeclarative1Package*)),
+ this, SLOT(_q_destroyingPackage(QDeclarative1Package*)));
+ return;
+ }
+ d->m_listAccessor = new QDeclarative1ListAccessor;
+ d->m_listAccessor->setList(model, d->m_context?d->m_context->engine():qmlEngine(this));
+ if (d->m_listAccessor->type() != QDeclarative1ListAccessor::ListProperty)
+ d->m_metaDataCacheable = true;
+ if (d->m_delegate && d->modelCount()) {
+ emit itemsInserted(0, d->modelCount());
+ emit countChanged();
+ }
+}
+
+/*!
+ \qmlproperty Component VisualDataModel::delegate
+
+ The delegate provides a template defining each item instantiated by a view.
+ The index is exposed as an accessible \c index property. Properties of the
+ model are also available depending upon the type of \l {qmlmodels}{Data Model}.
+*/
+QDeclarativeComponent *QDeclarative1VisualDataModel::delegate() const
+{
+ Q_D(const QDeclarative1VisualDataModel);
+ if (d->m_visualItemModel)
+ return d->m_visualItemModel->delegate();
+ return d->m_delegate;
+}
+
+void QDeclarative1VisualDataModel::setDelegate(QDeclarativeComponent *delegate)
+{
+ Q_D(QDeclarative1VisualDataModel);
+ bool wasValid = d->m_delegate != 0;
+ d->m_delegate = delegate;
+ d->m_delegateValidated = false;
+ if (!wasValid && d->modelCount() && d->m_delegate) {
+ emit itemsInserted(0, d->modelCount());
+ emit countChanged();
+ }
+ if (wasValid && !d->m_delegate && d->modelCount()) {
+ emit itemsRemoved(0, d->modelCount());
+ emit countChanged();
+ }
+}
+
+/*!
+ \qmlproperty QModelIndex VisualDataModel::rootIndex
+
+ QAbstractItemModel provides a hierarchical tree of data, whereas
+ QML only operates on list data. \c rootIndex allows the children of
+ any node in a QAbstractItemModel to be provided by this model.
+
+ This property only affects models of type QAbstractItemModel that
+ are hierarchical (e.g, a tree model).
+
+ For example, here is a simple interactive file system browser.
+ When a directory name is clicked, the view's \c rootIndex is set to the
+ QModelIndex node of the clicked directory, thus updating the view to show
+ the new directory's contents.
+
+ \c main.cpp:
+ \snippet doc/src/snippets/declarative/visualdatamodel_rootindex/main.cpp 0
+
+ \c view.qml:
+ \snippet doc/src/snippets/declarative/visualdatamodel_rootindex/view.qml 0
+
+ If the \l model is a QAbstractItemModel subclass, the delegate can also
+ reference a \c hasModelChildren property (optionally qualified by a
+ \e model. prefix) that indicates whether the delegate's model item has
+ any child nodes.
+
+
+ \sa modelIndex(), parentModelIndex()
+*/
+QVariant QDeclarative1VisualDataModel::rootIndex() const
+{
+ Q_D(const QDeclarative1VisualDataModel);
+ return QVariant::fromValue(d->m_root);
+}
+
+void QDeclarative1VisualDataModel::setRootIndex(const QVariant &root)
+{
+ Q_D(QDeclarative1VisualDataModel);
+ QModelIndex modelIndex = qvariant_cast<QModelIndex>(root);
+ if (d->m_root != modelIndex) {
+ int oldCount = d->modelCount();
+ d->m_root = modelIndex;
+ if (d->m_abstractItemModel && d->m_abstractItemModel->canFetchMore(modelIndex))
+ d->m_abstractItemModel->fetchMore(modelIndex);
+ int newCount = d->modelCount();
+ if (d->m_delegate && oldCount)
+ emit itemsRemoved(0, oldCount);
+ if (d->m_delegate && newCount)
+ emit itemsInserted(0, newCount);
+ if (newCount != oldCount)
+ emit countChanged();
+ emit rootIndexChanged();
+ }
+}
+
+
+/*!
+ \qmlmethod QModelIndex VisualDataModel::modelIndex(int index)
+
+ QAbstractItemModel provides a hierarchical tree of data, whereas
+ QML only operates on list data. This function assists in using
+ tree models in QML.
+
+ Returns a QModelIndex for the specified index.
+ This value can be assigned to rootIndex.
+
+ \sa rootIndex
+*/
+QVariant QDeclarative1VisualDataModel::modelIndex(int idx) const
+{
+ Q_D(const QDeclarative1VisualDataModel);
+ if (d->m_abstractItemModel)
+ return QVariant::fromValue(d->m_abstractItemModel->index(idx, 0, d->m_root));
+ return QVariant::fromValue(QModelIndex());
+}
+
+/*!
+ \qmlmethod QModelIndex VisualDataModel::parentModelIndex()
+
+ QAbstractItemModel provides a hierarchical tree of data, whereas
+ QML only operates on list data. This function assists in using
+ tree models in QML.
+
+ Returns a QModelIndex for the parent of the current rootIndex.
+ This value can be assigned to rootIndex.
+
+ \sa rootIndex
+*/
+QVariant QDeclarative1VisualDataModel::parentModelIndex() const
+{
+ Q_D(const QDeclarative1VisualDataModel);
+ if (d->m_abstractItemModel)
+ return QVariant::fromValue(d->m_abstractItemModel->parent(d->m_root));
+ return QVariant::fromValue(QModelIndex());
+}
+
+QString QDeclarative1VisualDataModel::part() const
+{
+ Q_D(const QDeclarative1VisualDataModel);
+ return d->m_part;
+}
+
+void QDeclarative1VisualDataModel::setPart(const QString &part)
+{
+ Q_D(QDeclarative1VisualDataModel);
+ d->m_part = part;
+}
+
+int QDeclarative1VisualDataModel::count() const
+{
+ Q_D(const QDeclarative1VisualDataModel);
+ if (d->m_visualItemModel)
+ return d->m_visualItemModel->count();
+ if (!d->m_delegate)
+ return 0;
+ return d->modelCount();
+}
+
+QDeclarativeItem *QDeclarative1VisualDataModel::item(int index, bool complete)
+{
+ Q_D(QDeclarative1VisualDataModel);
+ if (d->m_visualItemModel)
+ return d->m_visualItemModel->item(index, d->m_part.toUtf8(), complete);
+ return item(index, QByteArray(), complete);
+}
+
+/*
+ Returns ReleaseStatus flags.
+*/
+QDeclarative1VisualDataModel::ReleaseFlags QDeclarative1VisualDataModel::release(QDeclarativeItem *item)
+{
+ Q_D(QDeclarative1VisualDataModel);
+ if (d->m_visualItemModel)
+ return d->m_visualItemModel->release(item);
+
+ ReleaseFlags stat = 0;
+ QObject *obj = item;
+ bool inPackage = false;
+
+ QHash<QObject*,QDeclarative1Package*>::iterator it = d->m_packaged.find(item);
+ if (it != d->m_packaged.end()) {
+ QDeclarative1Package *package = *it;
+ d->m_packaged.erase(it);
+ if (d->m_packaged.contains(item))
+ stat |= Referenced;
+ inPackage = true;
+ obj = package; // fall through and delete
+ }
+
+ if (d->m_cache.releaseItem(obj)) {
+ // Remove any bindings to avoid warnings due to parent change.
+ QObjectPrivate *p = QObjectPrivate::get(obj);
+ Q_ASSERT(p->declarativeData);
+ QDeclarativeData *d = static_cast<QDeclarativeData*>(p->declarativeData);
+ if (d->ownContext && d->context)
+ d->context->clearContext();
+
+ if (inPackage) {
+ emit destroyingPackage(qobject_cast<QDeclarative1Package*>(obj));
+ } else {
+ if (item->scene())
+ item->scene()->removeItem(item);
+ }
+ stat |= Destroyed;
+ obj->deleteLater();
+ } else if (!inPackage) {
+ stat |= Referenced;
+ }
+
+ return stat;
+}
+
+/*!
+ \qmlproperty object VisualDataModel::parts
+
+ The \a parts property selects a VisualDataModel which creates
+ delegates from the part named. This is used in conjunction with
+ the \l Package element.
+
+ For example, the code below selects a model which creates
+ delegates named \e list from a \l Package:
+
+ \code
+ VisualDataModel {
+ id: visualModel
+ delegate: Package {
+ Item { Package.name: "list" }
+ }
+ model: myModel
+ }
+
+ ListView {
+ width: 200; height:200
+ model: visualModel.parts.list
+ }
+ \endcode
+
+ \sa Package
+*/
+QObject *QDeclarative1VisualDataModel::parts()
+{
+ Q_D(QDeclarative1VisualDataModel);
+ if (!d->m_parts)
+ d->m_parts = new QDeclarative1VisualDataModelParts(this);
+ return d->m_parts;
+}
+
+QDeclarativeItem *QDeclarative1VisualDataModel::item(int index, const QByteArray &viewId, bool complete)
+{
+ Q_D(QDeclarative1VisualDataModel);
+ if (d->m_visualItemModel)
+ return d->m_visualItemModel->item(index, viewId, complete);
+
+ if (d->modelCount() <= 0 || !d->m_delegate)
+ return 0;
+ QObject *nobj = d->m_cache.getItem(index);
+ bool needComplete = false;
+ if (!nobj) {
+ QDeclarativeContext *ccontext = d->m_context;
+ if (!ccontext) ccontext = qmlContext(this);
+ QDeclarativeContext *ctxt = new QDeclarativeContext(ccontext);
+ QDeclarative1VisualDataModelData *data = new QDeclarative1VisualDataModelData(index, this);
+ if ((!d->m_listModelInterface || !d->m_abstractItemModel) && d->m_listAccessor
+ && d->m_listAccessor->type() == QDeclarative1ListAccessor::ListProperty) {
+ ctxt->setContextObject(d->m_listAccessor->at(index).value<QObject*>());
+ ctxt = new QDeclarativeContext(ctxt, ctxt);
+ }
+ ctxt->setContextProperty(QLatin1String("model"), data);
+ ctxt->setContextObject(data);
+ d->m_completePending = false;
+ nobj = d->m_delegate->beginCreate(ctxt);
+ if (complete) {
+ d->m_delegate->completeCreate();
+ } else {
+ d->m_completePending = true;
+ needComplete = true;
+ }
+ if (nobj) {
+ QDeclarative_setParent_noEvent(ctxt, nobj);
+ QDeclarative_setParent_noEvent(data, nobj);
+ d->m_cache.insertItem(index, nobj);
+ if (QDeclarative1Package *package = qobject_cast<QDeclarative1Package *>(nobj))
+ emit createdPackage(index, package);
+ } else {
+ delete data;
+ delete ctxt;
+ qmlInfo(this, d->m_delegate->errors()) << "Error creating delegate";
+ }
+ }
+ QDeclarativeItem *item = qobject_cast<QDeclarativeItem *>(nobj);
+ if (!item) {
+ QDeclarative1Package *package = qobject_cast<QDeclarative1Package *>(nobj);
+ if (package) {
+ QObject *o = package->part(QString::fromUtf8(viewId));
+ item = qobject_cast<QDeclarativeItem *>(o);
+ if (item)
+ d->m_packaged.insertMulti(item, package);
+ }
+ }
+ if (!item) {
+ if (needComplete)
+ d->m_delegate->completeCreate();
+ d->m_cache.releaseItem(nobj);
+ if (!d->m_delegateValidated) {
+ qmlInfo(d->m_delegate) << QDeclarative1VisualDataModel::tr("Delegate component must be Item type.");
+ d->m_delegateValidated = true;
+ }
+ }
+ if (d->modelCount()-1 == index && d->m_abstractItemModel && d->m_abstractItemModel->canFetchMore(d->m_root))
+ d->m_abstractItemModel->fetchMore(d->m_root);
+
+ return item;
+}
+
+bool QDeclarative1VisualDataModel::completePending() const
+{
+ Q_D(const QDeclarative1VisualDataModel);
+ if (d->m_visualItemModel)
+ return d->m_visualItemModel->completePending();
+ return d->m_completePending;
+}
+
+void QDeclarative1VisualDataModel::completeItem()
+{
+ Q_D(QDeclarative1VisualDataModel);
+ if (d->m_visualItemModel) {
+ d->m_visualItemModel->completeItem();
+ return;
+ }
+
+ d->m_delegate->completeCreate();
+ d->m_completePending = false;
+}
+
+QString QDeclarative1VisualDataModel::stringValue(int index, const QString &name)
+{
+ Q_D(QDeclarative1VisualDataModel);
+ if (d->m_visualItemModel)
+ return d->m_visualItemModel->stringValue(index, name);
+
+ if ((!d->m_listModelInterface || !d->m_abstractItemModel) && d->m_listAccessor) {
+ if (QObject *object = d->m_listAccessor->at(index).value<QObject*>())
+ return object->property(name.toUtf8()).toString();
+ }
+
+ if ((!d->m_listModelInterface && !d->m_abstractItemModel) || !d->m_delegate)
+ return QString();
+
+ QString val;
+ QObject *data = 0;
+ bool tempData = false;
+
+ if (QObject *nobj = d->m_cache.item(index))
+ data = d->data(nobj);
+ if (!data) {
+ data = new QDeclarative1VisualDataModelData(index, this);
+ tempData = true;
+ }
+
+ QDeclarativeData *ddata = QDeclarativeData::get(data);
+ if (ddata && ddata->propertyCache) {
+ QDeclarativePropertyCache::Data *prop = ddata->propertyCache->property(name);
+ if (prop) {
+ if (prop->propType == QVariant::String) {
+ void *args[] = { &val, 0 };
+ QMetaObject::metacall(data, QMetaObject::ReadProperty, prop->coreIndex, args);
+ } else if (prop->propType == qMetaTypeId<QVariant>()) {
+ QVariant v;
+ void *args[] = { &v, 0 };
+ QMetaObject::metacall(data, QMetaObject::ReadProperty, prop->coreIndex, args);
+ val = v.toString();
+ }
+ } else {
+ val = data->property(name.toUtf8()).toString();
+ }
+ } else {
+ val = data->property(name.toUtf8()).toString();
+ }
+
+ if (tempData)
+ delete data;
+
+ return val;
+}
+
+int QDeclarative1VisualDataModel::indexOf(QDeclarativeItem *item, QObject *) const
+{
+ QVariant val = QDeclarativeEngine::contextForObject(item)->contextProperty(QLatin1String("index"));
+ return val.toInt();
+ return -1;
+}
+
+void QDeclarative1VisualDataModel::setWatchedRoles(QList<QByteArray> roles)
+{
+ Q_D(QDeclarative1VisualDataModel);
+ d->watchedRoles = roles;
+ d->watchedRoleIds.clear();
+}
+
+void QDeclarative1VisualDataModel::_q_itemsChanged(int index, int count,
+ const QList<int> &roles)
+{
+ Q_D(QDeclarative1VisualDataModel);
+ bool changed = false;
+ if (!d->watchedRoles.isEmpty() && d->watchedRoleIds.isEmpty()) {
+ foreach (QByteArray r, d->watchedRoles) {
+ if (d->m_roleNames.contains(r))
+ d->watchedRoleIds << d->m_roleNames.value(r);
+ }
+ }
+
+ for (QHash<int,QDeclarative1VisualDataModelPrivate::ObjectRef>::ConstIterator iter = d->m_cache.begin();
+ iter != d->m_cache.end(); ++iter) {
+ const int idx = iter.key();
+
+ if (idx >= index && idx < index+count) {
+ QDeclarative1VisualDataModelPrivate::ObjectRef objRef = *iter;
+ QDeclarative1VisualDataModelData *data = d->data(objRef.obj);
+ for (int roleIdx = 0; roleIdx < roles.count(); ++roleIdx) {
+ int role = roles.at(roleIdx);
+ if (!changed && !d->watchedRoleIds.isEmpty() && d->watchedRoleIds.contains(role))
+ changed = true;
+ int propId = data->propForRole(role);
+ if (propId != -1) {
+ if (data->hasValue(propId)) {
+ if (d->m_listModelInterface) {
+ data->setValue(propId, d->m_listModelInterface->data(idx, role));
+ } else if (d->m_abstractItemModel) {
+ QModelIndex index = d->m_abstractItemModel->index(idx, 0, d->m_root);
+ data->setValue(propId, d->m_abstractItemModel->data(index, role));
+ }
+ }
+ } else {
+ QString roleName;
+ if (d->m_listModelInterface)
+ roleName = d->m_listModelInterface->toString(role);
+ else if (d->m_abstractItemModel)
+ roleName = QString::fromUtf8(d->m_abstractItemModel->roleNames().value(role));
+ qmlInfo(this) << "Changing role not present in item: " << roleName;
+ }
+ }
+ if (d->m_roles.count() == 1) {
+ // Handle the modelData role we add if there is just one role.
+ int propId = data->modelDataPropertyId();
+ if (data->hasValue(propId)) {
+ int role = d->m_roles.at(0);
+ if (d->m_listModelInterface) {
+ data->setValue(propId, d->m_listModelInterface->data(idx, role));
+ } else if (d->m_abstractItemModel) {
+ QModelIndex index = d->m_abstractItemModel->index(idx, 0, d->m_root);
+ data->setValue(propId, d->m_abstractItemModel->data(index, role));
+ }
+ }
+ }
+ }
+ }
+ if (changed)
+ emit itemsChanged(index, count);
+}
+
+void QDeclarative1VisualDataModel::_q_itemsInserted(int index, int count)
+{
+ Q_D(QDeclarative1VisualDataModel);
+ if (!count)
+ return;
+ // XXX - highly inefficient
+ QHash<int,QDeclarative1VisualDataModelPrivate::ObjectRef> items;
+ for (QHash<int,QDeclarative1VisualDataModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
+ iter != d->m_cache.end(); ) {
+
+ if (iter.key() >= index) {
+ QDeclarative1VisualDataModelPrivate::ObjectRef objRef = *iter;
+ int index = iter.key() + count;
+ iter = d->m_cache.erase(iter);
+
+ items.insert(index, objRef);
+
+ QDeclarative1VisualDataModelData *data = d->data(objRef.obj);
+ data->setIndex(index);
+ } else {
+ ++iter;
+ }
+ }
+ d->m_cache.unite(items);
+
+ emit itemsInserted(index, count);
+ emit countChanged();
+}
+
+void QDeclarative1VisualDataModel::_q_itemsRemoved(int index, int count)
+{
+ Q_D(QDeclarative1VisualDataModel);
+ if (!count)
+ return;
+ // XXX - highly inefficient
+ QHash<int, QDeclarative1VisualDataModelPrivate::ObjectRef> items;
+ for (QHash<int, QDeclarative1VisualDataModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
+ iter != d->m_cache.end(); ) {
+ if (iter.key() >= index && iter.key() < index + count) {
+ QDeclarative1VisualDataModelPrivate::ObjectRef objRef = *iter;
+ iter = d->m_cache.erase(iter);
+ items.insertMulti(-1, objRef); //XXX perhaps better to maintain separately
+ QDeclarative1VisualDataModelData *data = d->data(objRef.obj);
+ data->setIndex(-1);
+ } else if (iter.key() >= index + count) {
+ QDeclarative1VisualDataModelPrivate::ObjectRef objRef = *iter;
+ int index = iter.key() - count;
+ iter = d->m_cache.erase(iter);
+ items.insert(index, objRef);
+ QDeclarative1VisualDataModelData *data = d->data(objRef.obj);
+ data->setIndex(index);
+ } else {
+ ++iter;
+ }
+ }
+
+ d->m_cache.unite(items);
+ emit itemsRemoved(index, count);
+ emit countChanged();
+}
+
+void QDeclarative1VisualDataModel::_q_itemsMoved(int from, int to, int count)
+{
+ Q_D(QDeclarative1VisualDataModel);
+ // XXX - highly inefficient
+ QHash<int,QDeclarative1VisualDataModelPrivate::ObjectRef> items;
+ for (QHash<int,QDeclarative1VisualDataModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
+ iter != d->m_cache.end(); ) {
+
+ if (iter.key() >= from && iter.key() < from + count) {
+ QDeclarative1VisualDataModelPrivate::ObjectRef objRef = *iter;
+ int index = iter.key() - from + to;
+ iter = d->m_cache.erase(iter);
+
+ items.insert(index, objRef);
+
+ QDeclarative1VisualDataModelData *data = d->data(objRef.obj);
+ data->setIndex(index);
+ } else {
+ ++iter;
+ }
+ }
+ for (QHash<int,QDeclarative1VisualDataModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
+ iter != d->m_cache.end(); ) {
+
+ int diff = from > to ? count : -count;
+ if (iter.key() >= qMin(from,to) && iter.key() < qMax(from+count,to+count)) {
+ QDeclarative1VisualDataModelPrivate::ObjectRef objRef = *iter;
+ int index = iter.key() + diff;
+ iter = d->m_cache.erase(iter);
+
+ items.insert(index, objRef);
+
+ QDeclarative1VisualDataModelData *data = d->data(objRef.obj);
+ data->setIndex(index);
+ } else {
+ ++iter;
+ }
+ }
+ d->m_cache.unite(items);
+
+ emit itemsMoved(from, to, count);
+}
+
+void QDeclarative1VisualDataModel::_q_rowsInserted(const QModelIndex &parent, int begin, int end)
+{
+ Q_D(QDeclarative1VisualDataModel);
+ if (parent == d->m_root)
+ _q_itemsInserted(begin, end - begin + 1);
+}
+
+void QDeclarative1VisualDataModel::_q_rowsRemoved(const QModelIndex &parent, int begin, int end)
+{
+ Q_D(QDeclarative1VisualDataModel);
+ if (parent == d->m_root)
+ _q_itemsRemoved(begin, end - begin + 1);
+}
+
+void QDeclarative1VisualDataModel::_q_rowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow)
+{
+ Q_D(QDeclarative1VisualDataModel);
+ const int count = sourceEnd - sourceStart + 1;
+ if (destinationParent == d->m_root && sourceParent == d->m_root) {
+ _q_itemsMoved(sourceStart, sourceStart > destinationRow ? destinationRow : destinationRow-1, count);
+ } else if (sourceParent == d->m_root) {
+ _q_itemsRemoved(sourceStart, count);
+ } else if (destinationParent == d->m_root) {
+ _q_itemsInserted(destinationRow, count);
+ }
+}
+
+void QDeclarative1VisualDataModel::_q_dataChanged(const QModelIndex &begin, const QModelIndex &end)
+{
+ Q_D(QDeclarative1VisualDataModel);
+ if (begin.parent() == d->m_root)
+ _q_itemsChanged(begin.row(), end.row() - begin.row() + 1, d->m_roles);
+}
+
+void QDeclarative1VisualDataModel::_q_layoutChanged()
+{
+ Q_D(QDeclarative1VisualDataModel);
+ _q_itemsChanged(0, count(), d->m_roles);
+}
+
+void QDeclarative1VisualDataModel::_q_modelReset()
+{
+ Q_D(QDeclarative1VisualDataModel);
+ d->m_root = QModelIndex();
+ emit modelReset();
+ emit rootIndexChanged();
+ if (d->m_abstractItemModel && d->m_abstractItemModel->canFetchMore(d->m_root))
+ d->m_abstractItemModel->fetchMore(d->m_root);
+}
+
+void QDeclarative1VisualDataModel::_q_createdPackage(int index, QDeclarative1Package *package)
+{
+ Q_D(QDeclarative1VisualDataModel);
+ emit createdItem(index, qobject_cast<QDeclarativeItem*>(package->part(d->m_part)));
+}
+
+void QDeclarative1VisualDataModel::_q_destroyingPackage(QDeclarative1Package *package)
+{
+ Q_D(QDeclarative1VisualDataModel);
+ emit destroyingItem(qobject_cast<QDeclarativeItem*>(package->part(d->m_part)));
+}
+
+
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QListModelInterface)
+
+#include <qdeclarativevisualitemmodel.moc>
diff --git a/src/qtquick1/graphicsitems/qdeclarativevisualitemmodel_p.h b/src/qtquick1/graphicsitems/qdeclarativevisualitemmodel_p.h
new file mode 100644
index 0000000000..e9729d08ce
--- /dev/null
+++ b/src/qtquick1/graphicsitems/qdeclarativevisualitemmodel_p.h
@@ -0,0 +1,257 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEVISUALDATAMODEL_H
+#define QDECLARATIVEVISUALDATAMODEL_H
+
+#include <QtDeclarative/qdeclarative.h>
+
+#include <QtCore/qobject.h>
+#include <QtCore/qabstractitemmodel.h>
+
+QT_BEGIN_HEADER
+
+Q_DECLARE_METATYPE(QModelIndex)
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeComponent;
+class QDeclarativeItem;
+class QDeclarative1Package;
+class QDeclarative1VisualDataModelPrivate;
+
+class Q_AUTOTEST_EXPORT QDeclarative1VisualModel : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+
+public:
+ virtual ~QDeclarative1VisualModel() {}
+
+ enum ReleaseFlag { Referenced = 0x01, Destroyed = 0x02 };
+ Q_DECLARE_FLAGS(ReleaseFlags, ReleaseFlag)
+
+ virtual int count() const = 0;
+ virtual bool isValid() const = 0;
+ virtual QDeclarativeItem *item(int index, bool complete=true) = 0;
+ virtual ReleaseFlags release(QDeclarativeItem *item) = 0;
+ virtual bool completePending() const = 0;
+ virtual void completeItem() = 0;
+ virtual QString stringValue(int, const QString &) = 0;
+ virtual void setWatchedRoles(QList<QByteArray> roles) = 0;
+
+ virtual int indexOf(QDeclarativeItem *item, QObject *objectContext) const = 0;
+
+Q_SIGNALS:
+ void countChanged();
+ void itemsInserted(int index, int count);
+ void itemsRemoved(int index, int count);
+ void itemsMoved(int from, int to, int count);
+ void itemsChanged(int index, int count);
+ void modelReset();
+ void createdItem(int index, QDeclarativeItem *item);
+ void destroyingItem(QDeclarativeItem *item);
+
+protected:
+ QDeclarative1VisualModel(QObjectPrivate &dd, QObject *parent = 0)
+ : QObject(dd, parent) {}
+
+private:
+ Q_DISABLE_COPY(QDeclarative1VisualModel)
+};
+
+class QDeclarative1VisualItemModelAttached;
+class QDeclarative1VisualItemModelPrivate;
+class Q_AUTOTEST_EXPORT QDeclarative1VisualItemModel : public QDeclarative1VisualModel
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarative1VisualItemModel)
+
+ Q_PROPERTY(QDeclarativeListProperty<QDeclarativeItem> children READ children NOTIFY childrenChanged DESIGNABLE false)
+ Q_CLASSINFO("DefaultProperty", "children")
+
+public:
+ QDeclarative1VisualItemModel(QObject *parent=0);
+ virtual ~QDeclarative1VisualItemModel() {}
+
+ virtual int count() const;
+ virtual bool isValid() const;
+ virtual QDeclarativeItem *item(int index, bool complete=true);
+ virtual ReleaseFlags release(QDeclarativeItem *item);
+ virtual bool completePending() const;
+ virtual void completeItem();
+ virtual QString stringValue(int index, const QString &role);
+ virtual void setWatchedRoles(QList<QByteArray>) {}
+
+ virtual int indexOf(QDeclarativeItem *item, QObject *objectContext) const;
+
+ QDeclarativeListProperty<QDeclarativeItem> children();
+
+ static QDeclarative1VisualItemModelAttached *qmlAttachedProperties(QObject *obj);
+
+Q_SIGNALS:
+ void childrenChanged();
+
+private:
+ Q_DISABLE_COPY(QDeclarative1VisualItemModel)
+};
+
+
+class Q_AUTOTEST_EXPORT QDeclarative1VisualDataModel : public QDeclarative1VisualModel
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarative1VisualDataModel)
+
+ Q_PROPERTY(QVariant model READ model WRITE setModel)
+ Q_PROPERTY(QDeclarativeComponent *delegate READ delegate WRITE setDelegate)
+ Q_PROPERTY(QString part READ part WRITE setPart)
+ Q_PROPERTY(QObject *parts READ parts CONSTANT)
+ Q_PROPERTY(QVariant rootIndex READ rootIndex WRITE setRootIndex NOTIFY rootIndexChanged)
+ Q_CLASSINFO("DefaultProperty", "delegate")
+public:
+ QDeclarative1VisualDataModel();
+ QDeclarative1VisualDataModel(QDeclarativeContext *, QObject *parent=0);
+ virtual ~QDeclarative1VisualDataModel();
+
+ QVariant model() const;
+ void setModel(const QVariant &);
+
+ QDeclarativeComponent *delegate() const;
+ void setDelegate(QDeclarativeComponent *);
+
+ QVariant rootIndex() const;
+ void setRootIndex(const QVariant &root);
+
+ Q_INVOKABLE QVariant modelIndex(int idx) const;
+ Q_INVOKABLE QVariant parentModelIndex() const;
+
+ QString part() const;
+ void setPart(const QString &);
+
+ int count() const;
+ bool isValid() const { return delegate() != 0; }
+ QDeclarativeItem *item(int index, bool complete=true);
+ QDeclarativeItem *item(int index, const QByteArray &, bool complete=true);
+ ReleaseFlags release(QDeclarativeItem *item);
+ bool completePending() const;
+ void completeItem();
+ virtual QString stringValue(int index, const QString &role);
+ virtual void setWatchedRoles(QList<QByteArray> roles);
+
+ int indexOf(QDeclarativeItem *item, QObject *objectContext) const;
+
+ QObject *parts();
+
+Q_SIGNALS:
+ void createdPackage(int index, QDeclarative1Package *package);
+ void destroyingPackage(QDeclarative1Package *package);
+ void rootIndexChanged();
+
+private Q_SLOTS:
+ void _q_itemsChanged(int, int, const QList<int> &);
+ void _q_itemsInserted(int index, int count);
+ void _q_itemsRemoved(int index, int count);
+ void _q_itemsMoved(int from, int to, int count);
+ void _q_rowsInserted(const QModelIndex &,int,int);
+ void _q_rowsRemoved(const QModelIndex &,int,int);
+ void _q_rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int);
+ void _q_dataChanged(const QModelIndex&,const QModelIndex&);
+ void _q_layoutChanged();
+ void _q_modelReset();
+ void _q_createdPackage(int index, QDeclarative1Package *package);
+ void _q_destroyingPackage(QDeclarative1Package *package);
+
+private:
+ Q_DISABLE_COPY(QDeclarative1VisualDataModel)
+};
+
+class QDeclarative1VisualItemModelAttached : public QObject
+{
+ Q_OBJECT
+
+public:
+ QDeclarative1VisualItemModelAttached(QObject *parent)
+ : QObject(parent), m_index(0) {}
+ ~QDeclarative1VisualItemModelAttached() {
+ attachedProperties.remove(parent());
+ }
+
+ Q_PROPERTY(int index READ index NOTIFY indexChanged)
+ int index() const { return m_index; }
+ void setIndex(int idx) {
+ if (m_index != idx) {
+ m_index = idx;
+ emit indexChanged();
+ }
+ }
+
+ static QDeclarative1VisualItemModelAttached *properties(QObject *obj) {
+ QDeclarative1VisualItemModelAttached *rv = attachedProperties.value(obj);
+ if (!rv) {
+ rv = new QDeclarative1VisualItemModelAttached(obj);
+ attachedProperties.insert(obj, rv);
+ }
+ return rv;
+ }
+
+Q_SIGNALS:
+ void indexChanged();
+
+public:
+ int m_index;
+
+ static QHash<QObject*, QDeclarative1VisualItemModelAttached*> attachedProperties;
+};
+
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1VisualModel)
+QML_DECLARE_TYPE(QDeclarative1VisualItemModel)
+QML_DECLARE_TYPEINFO(QDeclarative1VisualItemModel, QML_HAS_ATTACHED_PROPERTIES)
+QML_DECLARE_TYPE(QDeclarative1VisualDataModel)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEVISUALDATAMODEL_H
diff --git a/src/qtquick1/qtquick1.cpp b/src/qtquick1/qtquick1.cpp
new file mode 100644
index 0000000000..b8c0e109ba
--- /dev/null
+++ b/src/qtquick1/qtquick1.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtDeclarative/qdeclarative.h>
+#include <QtDeclarative/private/qdeclarativefastproperties_p.h>
+#include <QtQuick1/qdeclarativeitem.h>
+#include <QtQuick1/private/qdeclarativeitem_p.h>
+#include <QtQuick1/private/qdeclarativeutilmodule_p.h>
+#include <QtQuick1/private/qdeclarativeitemsmodule_p.h>
+#include "qtquick1_p.h"
+
+QT_BEGIN_NAMESPACE
+
+void QDeclarativeQtQuick1Module::defineModule(QDeclarativeQtQuick1Module::Module module)
+{
+ QDeclarativeFastProperties::instance()->add(&QDeclarativeItem::staticMetaObject,
+ QDeclarativeItem::staticMetaObject.indexOfProperty("parent"),
+ QDeclarativeItemPrivate::parentProperty);
+ if (module == QtQuick1)
+ qmlRegisterBaseTypes("QtQuick", 1, 0);
+ else if (module == Qt47)
+ qmlRegisterBaseTypes("Qt", 4, 7);
+ QDeclarative1UtilModule::defineModule(module);
+ QDeclarative1ItemModule::defineModule(module);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/qtquick1/qtquick1.pro b/src/qtquick1/qtquick1.pro
new file mode 100644
index 0000000000..e3dd0298cd
--- /dev/null
+++ b/src/qtquick1/qtquick1.pro
@@ -0,0 +1,42 @@
+load(qt_module)
+
+TARGET = QtQuick1
+QPRO_PWD = $$PWD
+
+CONFIG += module
+CONFIG += dll warn_on
+MODULE_PRI += ../../modules/qt_qtquick1.pri
+
+QT += testlib-private declarative script testlib declarative-private core-private gui-private script-private network
+DEFINES += QT_NO_URL_CAST_FROM_STRING
+
+load(qt_module_config)
+
+# Install qtquick1.prf into the Qt mkspecs so that "CONFIG += qtquick1"
+# can be used in customer applications to build against QtQuick 1.
+feature.path = $$[QT_INSTALL_DATA]/mkspecs/features
+feature.files = $$PWD/features/qtquick1.prf
+INSTALLS += feature
+
+symbian {
+ DEFINES += QT_MAKEDLL
+ CONFIG += epocallowdlldata
+ contains(QT_EDITION, OpenSource) {
+ TARGET.CAPABILITY = LocalServices NetworkServices ReadUserData UserEnvironment WriteUserData
+ } else {
+ TARGET.CAPABILITY = All -Tcb
+ }
+}
+
+#INCLUDEPATH += $$PWD/QtQuick1
+#INCLUDEPATH += $$PWD
+
+include(util/util.pri)
+include(graphicsitems/graphicsitems.pri)
+
+HEADERS += qtquick1_p.h
+SOURCES += qtquick1.cpp
+
+DEFINES += QT_NO_OPENTYPE
+INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/harfbuzz/src
+
diff --git a/src/qtquick1/qtquick1_p.h b/src/qtquick1/qtquick1_p.h
new file mode 100644
index 0000000000..36dfd1ad05
--- /dev/null
+++ b/src/qtquick1/qtquick1_p.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTQUICK1_H
+#define QTQUICK1_H
+
+#include <qglobal.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_EXPORT QDeclarativeQtQuick1Module
+{
+public:
+ enum Module { QtQuick1, Qt47 };
+ static void defineModule(Module module);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QTQUICK1_H
diff --git a/src/qtquick1/util/qdeclarativeanimation.cpp b/src/qtquick1/util/qdeclarativeanimation.cpp
new file mode 100644
index 0000000000..3b05429c84
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativeanimation.cpp
@@ -0,0 +1,2956 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativeanimation_p.h"
+#include "QtQuick1/private/qdeclarativeanimation_p_p.h"
+
+#include "QtQuick1/private/qdeclarativebehavior_p.h"
+#include "QtQuick1/private/qdeclarativestateoperations_p.h"
+#include "QtDeclarative/private/qdeclarativecontext_p.h"
+
+#include <QtDeclarative/qdeclarativepropertyvaluesource.h>
+#include <QtDeclarative/qdeclarative.h>
+#include <QtDeclarative/qdeclarativeinfo.h>
+#include <QtDeclarative/qdeclarativeexpression.h>
+#include <QtDeclarative/private/qdeclarativestringconverters_p.h>
+#include <QtDeclarative/private/qdeclarativeglobal_p.h>
+#include <QtDeclarative/private/qdeclarativemetatype_p.h>
+#include <QtDeclarative/private/qdeclarativevaluetype_p.h>
+#include <QtDeclarative/private/qdeclarativeproperty_p.h>
+#include <QtDeclarative/private/qdeclarativeengine_p.h>
+
+#include <qvariant.h>
+#include <qcolor.h>
+#include <qfile.h>
+#include <QParallelAnimationGroup>
+#include <QSequentialAnimationGroup>
+#include <QtCore/qset.h>
+#include <QtCore/qrect.h>
+#include <QtCore/qpoint.h>
+#include <QtCore/qsize.h>
+#include <QtCore/qmath.h>
+
+#include <private/qvariantanimation_p.h>
+
+QT_BEGIN_NAMESPACE
+
+
+
+/*!
+ \qmlclass Animation QDeclarative1AbstractAnimation
+ \ingroup qml-animation-transition
+ \since 4.7
+ \brief The Animation element is the base of all QML animations.
+
+ The Animation element cannot be used directly in a QML file. It exists
+ to provide a set of common properties and methods, available across all the
+ other animation types that inherit from it. Attempting to use the Animation
+ element directly will result in an error.
+*/
+
+QDeclarative1AbstractAnimation::QDeclarative1AbstractAnimation(QObject *parent)
+: QObject(*(new QDeclarative1AbstractAnimationPrivate), parent)
+{
+}
+
+QDeclarative1AbstractAnimation::~QDeclarative1AbstractAnimation()
+{
+}
+
+QDeclarative1AbstractAnimation::QDeclarative1AbstractAnimation(QDeclarative1AbstractAnimationPrivate &dd, QObject *parent)
+: QObject(dd, parent)
+{
+}
+
+/*!
+ \qmlproperty bool Animation::running
+ This property holds whether the animation is currently running.
+
+ The \c running property can be set to declaratively control whether or not
+ an animation is running. The following example will animate a rectangle
+ whenever the \l MouseArea is pressed.
+
+ \code
+ Rectangle {
+ width: 100; height: 100
+ NumberAnimation on x {
+ running: myMouse.pressed
+ from: 0; to: 100
+ }
+ MouseArea { id: myMouse }
+ }
+ \endcode
+
+ Likewise, the \c running property can be read to determine if the animation
+ is running. In the following example the text element will indicate whether
+ or not the animation is running.
+
+ \code
+ NumberAnimation { id: myAnimation }
+ Text { text: myAnimation.running ? "Animation is running" : "Animation is not running" }
+ \endcode
+
+ Animations can also be started and stopped imperatively from JavaScript
+ using the \c start() and \c stop() methods.
+
+ By default, animations are not running. Though, when the animations are assigned to properties,
+ as property value sources using the \e on syntax, they are set to running by default.
+*/
+bool QDeclarative1AbstractAnimation::isRunning() const
+{
+ Q_D(const QDeclarative1AbstractAnimation);
+ return d->running;
+}
+
+// the behavior calls this function
+void QDeclarative1AbstractAnimation::notifyRunningChanged(bool running)
+{
+ Q_D(QDeclarative1AbstractAnimation);
+ if (d->disableUserControl && d->running != running) {
+ d->running = running;
+ emit runningChanged(running);
+ }
+}
+
+//commence is called to start an animation when it is used as a
+//simple animation, and not as part of a transition
+void QDeclarative1AbstractAnimationPrivate::commence()
+{
+ Q_Q(QDeclarative1AbstractAnimation);
+
+ QDeclarative1StateActions actions;
+ QDeclarativeProperties properties;
+ q->transition(actions, properties, QDeclarative1AbstractAnimation::Forward);
+
+ q->qtAnimation()->start();
+ if (q->qtAnimation()->state() != QAbstractAnimation::Running) {
+ running = false;
+ emit q->completed();
+ }
+}
+
+QDeclarativeProperty QDeclarative1AbstractAnimationPrivate::createProperty(QObject *obj, const QString &str, QObject *infoObj)
+{
+ QDeclarativeProperty prop(obj, str, qmlContext(infoObj));
+ if (!prop.isValid()) {
+ qmlInfo(infoObj) << QDeclarative1AbstractAnimation::tr("Cannot animate non-existent property \"%1\"").arg(str);
+ return QDeclarativeProperty();
+ } else if (!prop.isWritable()) {
+ qmlInfo(infoObj) << QDeclarative1AbstractAnimation::tr("Cannot animate read-only property \"%1\"").arg(str);
+ return QDeclarativeProperty();
+ }
+ return prop;
+}
+
+void QDeclarative1AbstractAnimation::setRunning(bool r)
+{
+ Q_D(QDeclarative1AbstractAnimation);
+ if (!d->componentComplete) {
+ d->running = r;
+ if (r == false)
+ d->avoidPropertyValueSourceStart = true;
+ else if (!d->registered) {
+ d->registered = true;
+ QDeclarativeEnginePrivate *engPriv = QDeclarativeEnginePrivate::get(qmlEngine(this));
+ engPriv->registerFinalizedParserStatusObject(this, this->metaObject()->indexOfSlot("componentFinalized()"));
+ }
+ return;
+ }
+
+ if (d->running == r)
+ return;
+
+ if (d->group || d->disableUserControl) {
+ qmlInfo(this) << "setRunning() cannot be used on non-root animation nodes.";
+ return;
+ }
+
+ d->running = r;
+ if (d->running) {
+ bool supressStart = false;
+ if (d->alwaysRunToEnd && d->loopCount != 1
+ && qtAnimation()->state() == QAbstractAnimation::Running) {
+ //we've restarted before the final loop finished; restore proper loop count
+ if (d->loopCount == -1)
+ qtAnimation()->setLoopCount(d->loopCount);
+ else
+ qtAnimation()->setLoopCount(qtAnimation()->currentLoop() + d->loopCount);
+ supressStart = true; //we want the animation to continue, rather than restart
+ }
+
+ if (!d->connectedTimeLine) {
+ QObject::connect(qtAnimation(), SIGNAL(finished()),
+ this, SLOT(timelineComplete()));
+ d->connectedTimeLine = true;
+ }
+ if (!supressStart)
+ d->commence();
+ emit started();
+ } else {
+ if (d->alwaysRunToEnd) {
+ if (d->loopCount != 1)
+ qtAnimation()->setLoopCount(qtAnimation()->currentLoop()+1); //finish the current loop
+ } else
+ qtAnimation()->stop();
+
+ emit completed();
+ }
+
+ emit runningChanged(d->running);
+}
+
+/*!
+ \qmlproperty bool Animation::paused
+ This property holds whether the animation is currently paused.
+
+ The \c paused property can be set to declaratively control whether or not
+ an animation is paused.
+
+ Animations can also be paused and resumed imperatively from JavaScript
+ using the \c pause() and \c resume() methods.
+
+ By default, animations are not paused.
+*/
+bool QDeclarative1AbstractAnimation::isPaused() const
+{
+ Q_D(const QDeclarative1AbstractAnimation);
+ return d->paused;
+}
+
+void QDeclarative1AbstractAnimation::setPaused(bool p)
+{
+ Q_D(QDeclarative1AbstractAnimation);
+ if (d->paused == p)
+ return;
+
+ if (d->group || d->disableUserControl) {
+ qmlInfo(this) << "setPaused() cannot be used on non-root animation nodes.";
+ return;
+ }
+
+ d->paused = p;
+ if (d->paused)
+ qtAnimation()->pause();
+ else
+ qtAnimation()->resume();
+
+ emit pausedChanged(d->paused);
+}
+
+void QDeclarative1AbstractAnimation::classBegin()
+{
+ Q_D(QDeclarative1AbstractAnimation);
+ d->componentComplete = false;
+}
+
+void QDeclarative1AbstractAnimation::componentComplete()
+{
+ Q_D(QDeclarative1AbstractAnimation);
+ d->componentComplete = true;
+}
+
+void QDeclarative1AbstractAnimation::componentFinalized()
+{
+ Q_D(QDeclarative1AbstractAnimation);
+ if (d->running) {
+ d->running = false;
+ setRunning(true);
+ }
+}
+
+/*!
+ \qmlproperty bool Animation::alwaysRunToEnd
+ This property holds whether the animation should run to completion when it is stopped.
+
+ If this true the animation will complete its current iteration when it
+ is stopped - either by setting the \c running property to false, or by
+ calling the \c stop() method. The \c complete() method is not effected
+ by this value.
+
+ This behavior is most useful when the \c repeat property is set, as the
+ animation will finish playing normally but not restart.
+
+ By default, the alwaysRunToEnd property is not set.
+
+ \note alwaysRunToEnd has no effect on animations in a Transition.
+*/
+bool QDeclarative1AbstractAnimation::alwaysRunToEnd() const
+{
+ Q_D(const QDeclarative1AbstractAnimation);
+ return d->alwaysRunToEnd;
+}
+
+void QDeclarative1AbstractAnimation::setAlwaysRunToEnd(bool f)
+{
+ Q_D(QDeclarative1AbstractAnimation);
+ if (d->alwaysRunToEnd == f)
+ return;
+
+ d->alwaysRunToEnd = f;
+ emit alwaysRunToEndChanged(f);
+}
+
+/*!
+ \qmlproperty int Animation::loops
+ This property holds the number of times the animation should play.
+
+ By default, \c loops is 1: the animation will play through once and then stop.
+
+ If set to Animation.Infinite, the animation will continuously repeat until it is explicitly
+ stopped - either by setting the \c running property to false, or by calling
+ the \c stop() method.
+
+ In the following example, the rectangle will spin indefinitely.
+
+ \code
+ Rectangle {
+ width: 100; height: 100; color: "green"
+ RotationAnimation on rotation {
+ loops: Animation.Infinite
+ from: 0
+ to: 360
+ }
+ }
+ \endcode
+*/
+int QDeclarative1AbstractAnimation::loops() const
+{
+ Q_D(const QDeclarative1AbstractAnimation);
+ return d->loopCount;
+}
+
+void QDeclarative1AbstractAnimation::setLoops(int loops)
+{
+ Q_D(QDeclarative1AbstractAnimation);
+ if (loops < 0)
+ loops = -1;
+
+ if (loops == d->loopCount)
+ return;
+
+ d->loopCount = loops;
+ qtAnimation()->setLoopCount(loops);
+ emit loopCountChanged(loops);
+}
+
+
+int QDeclarative1AbstractAnimation::currentTime()
+{
+ return qtAnimation()->currentLoopTime();
+}
+
+void QDeclarative1AbstractAnimation::setCurrentTime(int time)
+{
+ qtAnimation()->setCurrentTime(time);
+}
+
+QDeclarative1AnimationGroup *QDeclarative1AbstractAnimation::group() const
+{
+ Q_D(const QDeclarative1AbstractAnimation);
+ return d->group;
+}
+
+void QDeclarative1AbstractAnimation::setGroup(QDeclarative1AnimationGroup *g)
+{
+ Q_D(QDeclarative1AbstractAnimation);
+ if (d->group == g)
+ return;
+ if (d->group)
+ static_cast<QDeclarative1AnimationGroupPrivate *>(d->group->d_func())->animations.removeAll(this);
+
+ d->group = g;
+
+ if (d->group && !static_cast<QDeclarative1AnimationGroupPrivate *>(d->group->d_func())->animations.contains(this))
+ static_cast<QDeclarative1AnimationGroupPrivate *>(d->group->d_func())->animations.append(this);
+
+ //if (g) //if removed from a group, then the group should no longer be the parent
+ setParent(g);
+}
+
+/*!
+ \qmlmethod Animation::start()
+ \brief Starts the animation.
+
+ If the animation is already running, calling this method has no effect. The
+ \c running property will be true following a call to \c start().
+*/
+void QDeclarative1AbstractAnimation::start()
+{
+ setRunning(true);
+}
+
+/*!
+ \qmlmethod Animation::pause()
+ \brief Pauses the animation.
+
+ If the animation is already paused, calling this method has no effect. The
+ \c paused property will be true following a call to \c pause().
+*/
+void QDeclarative1AbstractAnimation::pause()
+{
+ setPaused(true);
+}
+
+/*!
+ \qmlmethod Animation::resume()
+ \brief Resumes a paused animation.
+
+ If the animation is not paused, calling this method has no effect. The
+ \c paused property will be false following a call to \c resume().
+*/
+void QDeclarative1AbstractAnimation::resume()
+{
+ setPaused(false);
+}
+
+/*!
+ \qmlmethod Animation::stop()
+ \brief Stops the animation.
+
+ If the animation is not running, calling this method has no effect. The
+ \c running property will be false following a call to \c stop().
+
+ Normally \c stop() stops the animation immediately, and the animation has
+ no further influence on property values. In this example animation
+ \code
+ Rectangle {
+ NumberAnimation on x { from: 0; to: 100; duration: 500 }
+ }
+ \endcode
+ was stopped at time 250ms, the \c x property will have a value of 50.
+
+ However, if the \c alwaysRunToEnd property is set, the animation will
+ continue running until it completes and then stop. The \c running property
+ will still become false immediately.
+*/
+void QDeclarative1AbstractAnimation::stop()
+{
+ setRunning(false);
+}
+
+/*!
+ \qmlmethod Animation::restart()
+ \brief Restarts the animation.
+
+ This is a convenience method, and is equivalent to calling \c stop() and
+ then \c start().
+*/
+void QDeclarative1AbstractAnimation::restart()
+{
+ stop();
+ start();
+}
+
+/*!
+ \qmlmethod Animation::complete()
+ \brief Stops the animation, jumping to the final property values.
+
+ If the animation is not running, calling this method has no effect. The
+ \c running property will be false following a call to \c complete().
+
+ Unlike \c stop(), \c complete() immediately fast-forwards the animation to
+ its end. In the following example,
+ \code
+ Rectangle {
+ NumberAnimation on x { from: 0; to: 100; duration: 500 }
+ }
+ \endcode
+ calling \c stop() at time 250ms will result in the \c x property having
+ a value of 50, while calling \c complete() will set the \c x property to
+ 100, exactly as though the animation had played the whole way through.
+*/
+void QDeclarative1AbstractAnimation::complete()
+{
+ if (isRunning()) {
+ qtAnimation()->setCurrentTime(qtAnimation()->duration());
+ }
+}
+
+void QDeclarative1AbstractAnimation::setTarget(const QDeclarativeProperty &p)
+{
+ Q_D(QDeclarative1AbstractAnimation);
+ d->defaultProperty = p;
+
+ if (!d->avoidPropertyValueSourceStart)
+ setRunning(true);
+}
+
+/*
+ we rely on setTarget only being called when used as a value source
+ so this function allows us to do the same thing as setTarget without
+ that assumption
+*/
+void QDeclarative1AbstractAnimation::setDefaultTarget(const QDeclarativeProperty &p)
+{
+ Q_D(QDeclarative1AbstractAnimation);
+ d->defaultProperty = p;
+}
+
+/*
+ don't allow start/stop/pause/resume to be manually invoked,
+ because something else (like a Behavior) already has control
+ over the animation.
+*/
+void QDeclarative1AbstractAnimation::setDisableUserControl()
+{
+ Q_D(QDeclarative1AbstractAnimation);
+ d->disableUserControl = true;
+}
+
+void QDeclarative1AbstractAnimation::transition(QDeclarative1StateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction)
+{
+ Q_UNUSED(actions);
+ Q_UNUSED(modified);
+ Q_UNUSED(direction);
+}
+
+void QDeclarative1AbstractAnimation::timelineComplete()
+{
+ Q_D(QDeclarative1AbstractAnimation);
+ setRunning(false);
+ if (d->alwaysRunToEnd && d->loopCount != 1) {
+ //restore the proper loopCount for the next run
+ qtAnimation()->setLoopCount(d->loopCount);
+ }
+}
+
+/*!
+ \qmlclass PauseAnimation QDeclarative1PauseAnimation
+ \ingroup qml-animation-transition
+ \since 4.7
+ \inherits Animation
+ \brief The PauseAnimation element provides a pause for an animation.
+
+ When used in a SequentialAnimation, PauseAnimation is a step when
+ nothing happens, for a specified duration.
+
+ A 500ms animation sequence, with a 100ms pause between two animations:
+ \code
+ SequentialAnimation {
+ NumberAnimation { ... duration: 200 }
+ PauseAnimation { duration: 100 }
+ NumberAnimation { ... duration: 200 }
+ }
+ \endcode
+
+ \sa {QML Animation and Transitions}, {declarative/animation/basics}{Animation basics example}
+*/
+QDeclarative1PauseAnimation::QDeclarative1PauseAnimation(QObject *parent)
+: QDeclarative1AbstractAnimation(*(new QDeclarative1PauseAnimationPrivate), parent)
+{
+ Q_D(QDeclarative1PauseAnimation);
+ d->init();
+}
+
+QDeclarative1PauseAnimation::~QDeclarative1PauseAnimation()
+{
+}
+
+void QDeclarative1PauseAnimationPrivate::init()
+{
+ Q_Q(QDeclarative1PauseAnimation);
+ pa = new QPauseAnimation;
+ QDeclarative_setParent_noEvent(pa, q);
+}
+
+/*!
+ \qmlproperty int PauseAnimation::duration
+ This property holds the duration of the pause in milliseconds
+
+ The default value is 250.
+*/
+int QDeclarative1PauseAnimation::duration() const
+{
+ Q_D(const QDeclarative1PauseAnimation);
+ return d->pa->duration();
+}
+
+void QDeclarative1PauseAnimation::setDuration(int duration)
+{
+ if (duration < 0) {
+ qmlInfo(this) << tr("Cannot set a duration of < 0");
+ return;
+ }
+
+ Q_D(QDeclarative1PauseAnimation);
+ if (d->pa->duration() == duration)
+ return;
+ d->pa->setDuration(duration);
+ emit durationChanged(duration);
+}
+
+QAbstractAnimation *QDeclarative1PauseAnimation::qtAnimation()
+{
+ Q_D(QDeclarative1PauseAnimation);
+ return d->pa;
+}
+
+/*!
+ \qmlclass ColorAnimation QDeclarative1ColorAnimation
+ \ingroup qml-animation-transition
+ \since 4.7
+ \inherits PropertyAnimation
+ \brief The ColorAnimation element animates changes in color values.
+
+ ColorAnimation is a specialized PropertyAnimation that defines an
+ animation to be applied when a color value changes.
+
+ Here is a ColorAnimation applied to the \c color property of a \l Rectangle
+ as a property value source. It animates the \c color property's value from
+ its current value to a value of "red", over 1000 milliseconds:
+
+ \snippet doc/src/snippets/declarative/coloranimation.qml 0
+
+ Like any other animation element, a ColorAnimation can be applied in a
+ number of ways, including transitions, behaviors and property value
+ sources. The \l {QML Animation and Transitions} documentation shows a
+ variety of methods for creating animations.
+
+ For convenience, when a ColorAnimation is used in a \l Transition, it will
+ animate any \c color properties that have been modified during the state
+ change. If a \l{PropertyAnimation::}{property} or
+ \l{PropertyAnimation::}{properties} are explicitly set for the animation,
+ then those are used instead.
+
+ \sa {QML Animation and Transitions}, {declarative/animation/basics}{Animation basics example}
+*/
+QDeclarative1ColorAnimation::QDeclarative1ColorAnimation(QObject *parent)
+: QDeclarative1PropertyAnimation(parent)
+{
+ Q_D(QDeclarative1PropertyAnimation);
+ d->interpolatorType = QMetaType::QColor;
+ d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType);
+ d->defaultToInterpolatorType = true;
+}
+
+QDeclarative1ColorAnimation::~QDeclarative1ColorAnimation()
+{
+}
+
+/*!
+ \qmlproperty color ColorAnimation::from
+ This property holds the color value at which the animation should begin.
+
+ For example, the following animation is not applied until a color value
+ has reached "#c0c0c0":
+
+ \qml
+ Item {
+ states: [
+ // States are defined here...
+ ]
+
+ transition: Transition {
+ NumberAnimation { from: "#c0c0c0"; duration: 2000 }
+ }
+ }
+ \endqml
+
+ If the ColorAnimation is defined within a \l Transition or \l Behavior,
+ this value defaults to the value defined in the starting state of the
+ \l Transition, or the current value of the property at the moment the
+ \l Behavior is triggered.
+
+ \sa {QML Animation and Transitions}
+*/
+QColor QDeclarative1ColorAnimation::from() const
+{
+ Q_D(const QDeclarative1PropertyAnimation);
+ return d->from.value<QColor>();
+}
+
+void QDeclarative1ColorAnimation::setFrom(const QColor &f)
+{
+ QDeclarative1PropertyAnimation::setFrom(f);
+}
+
+/*!
+ \qmlproperty color ColorAnimation::to
+
+ This property holds the color value at which the animation should end.
+
+ If the ColorAnimation is defined within a \l Transition or \l Behavior,
+ this value defaults to the value defined in the end state of the
+ \l Transition, or the value of the property change that triggered the
+ \l Behavior.
+
+ \sa {QML Animation and Transitions}
+*/
+QColor QDeclarative1ColorAnimation::to() const
+{
+ Q_D(const QDeclarative1PropertyAnimation);
+ return d->to.value<QColor>();
+}
+
+void QDeclarative1ColorAnimation::setTo(const QColor &t)
+{
+ QDeclarative1PropertyAnimation::setTo(t);
+}
+
+
+
+/*!
+ \qmlclass ScriptAction QDeclarative1ScriptAction
+ \ingroup qml-animation-transition
+ \since 4.7
+ \inherits Animation
+ \brief The ScriptAction element allows scripts to be run during an animation.
+
+ ScriptAction can be used to run a script at a specific point in an animation.
+
+ \qml
+ SequentialAnimation {
+ NumberAnimation {
+ // ...
+ }
+ ScriptAction { script: doSomething(); }
+ NumberAnimation {
+ // ...
+ }
+ }
+ \endqml
+
+ When used as part of a Transition, you can also target a specific
+ StateChangeScript to run using the \c scriptName property.
+
+ \snippet doc/src/snippets/declarative/states/statechangescript.qml state and transition
+
+ \sa StateChangeScript
+*/
+QDeclarative1ScriptAction::QDeclarative1ScriptAction(QObject *parent)
+ :QDeclarative1AbstractAnimation(*(new QDeclarative1ScriptActionPrivate), parent)
+{
+ Q_D(QDeclarative1ScriptAction);
+ d->init();
+}
+
+QDeclarative1ScriptAction::~QDeclarative1ScriptAction()
+{
+}
+
+void QDeclarative1ScriptActionPrivate::init()
+{
+ Q_Q(QDeclarative1ScriptAction);
+ rsa = new QActionAnimation_1(&proxy);
+ QDeclarative_setParent_noEvent(rsa, q);
+}
+
+/*!
+ \qmlproperty script ScriptAction::script
+ This property holds the script to run.
+*/
+QDeclarativeScriptString QDeclarative1ScriptAction::script() const
+{
+ Q_D(const QDeclarative1ScriptAction);
+ return d->script;
+}
+
+void QDeclarative1ScriptAction::setScript(const QDeclarativeScriptString &script)
+{
+ Q_D(QDeclarative1ScriptAction);
+ d->script = script;
+}
+
+/*!
+ \qmlproperty string ScriptAction::scriptName
+ This property holds the the name of the StateChangeScript to run.
+
+ This property is only valid when ScriptAction is used as part of a transition.
+ If both script and scriptName are set, scriptName will be used.
+
+ \note When using scriptName in a reversible transition, the script will only
+ be run when the transition is being run forwards.
+*/
+QString QDeclarative1ScriptAction::stateChangeScriptName() const
+{
+ Q_D(const QDeclarative1ScriptAction);
+ return d->name;
+}
+
+void QDeclarative1ScriptAction::setStateChangeScriptName(const QString &name)
+{
+ Q_D(QDeclarative1ScriptAction);
+ d->name = name;
+}
+
+void QDeclarative1ScriptActionPrivate::execute()
+{
+ Q_Q(QDeclarative1ScriptAction);
+ if (hasRunScriptScript && reversing)
+ return;
+
+ QDeclarativeScriptString scriptStr = hasRunScriptScript ? runScriptScript : script;
+
+ const QString &str = scriptStr.script();
+ if (!str.isEmpty()) {
+ QDeclarativeExpression expr(scriptStr.context(), scriptStr.scopeObject(), str);
+ QDeclarativeData *ddata = QDeclarativeData::get(q);
+ if (ddata && ddata->outerContext && !ddata->outerContext->url.isEmpty())
+ expr.setSourceLocation(ddata->outerContext->url.toString(), ddata->lineNumber);
+ expr.evaluate();
+ if (expr.hasError())
+ qmlInfo(q) << expr.error();
+ }
+}
+
+void QDeclarative1ScriptAction::transition(QDeclarative1StateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction)
+{
+ Q_D(QDeclarative1ScriptAction);
+ Q_UNUSED(modified);
+
+ d->hasRunScriptScript = false;
+ d->reversing = (direction == Backward);
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ QDeclarative1Action &action = actions[ii];
+
+ if (action.event && action.event->typeName() == QLatin1String("StateChangeScript")
+ && static_cast<QDeclarative1StateChangeScript*>(action.event)->name() == d->name) {
+ d->runScriptScript = static_cast<QDeclarative1StateChangeScript*>(action.event)->script();
+ d->hasRunScriptScript = true;
+ action.actionDone = true;
+ break; //only match one (names should be unique)
+ }
+ }
+}
+
+QAbstractAnimation *QDeclarative1ScriptAction::qtAnimation()
+{
+ Q_D(QDeclarative1ScriptAction);
+ return d->rsa;
+}
+
+
+
+/*!
+ \qmlclass PropertyAction QDeclarative1PropertyAction
+ \ingroup qml-animation-transition
+ \since 4.7
+ \inherits Animation
+ \brief The PropertyAction element allows immediate property changes during animation.
+
+ PropertyAction is used to specify an immediate property change during an
+ animation. The property change is not animated.
+
+ It is useful for setting non-animated property values during an animation.
+
+ For example, here is a SequentialAnimation that sets the image's
+ \l {Image::}{smooth} property to \c true, animates the width of the image,
+ then sets \l {Image::}{smooth} back to \c false:
+
+ \snippet doc/src/snippets/declarative/propertyaction.qml standalone
+
+ PropertyAction is also useful for setting the exact point at which a property
+ change should occur during a \l Transition. For example, if PropertyChanges
+ was used in a \l State to rotate an item around a particular
+ \l {Item::}{transformOrigin}, it might be implemented like this:
+
+ \snippet doc/src/snippets/declarative/propertyaction.qml transition
+
+ However, with this code, the \c transformOrigin is not set until \e after
+ the animation, as a \l State is taken to define the values at the \e end of
+ a transition. The animation would rotate at the default \c transformOrigin,
+ then jump to \c Item.BottomRight. To fix this, insert a PropertyAction
+ before the RotationAnimation begins:
+
+ \snippet doc/src/snippets/declarative/propertyaction-sequential.qml sequential
+
+ This immediately sets the \c transformOrigin property to the value defined
+ in the end state of the \l Transition (i.e. the value defined in the
+ PropertyAction object) so that the rotation animation begins with the
+ correct transform origin.
+
+ \sa {QML Animation and Transitions}, QtDeclarative
+*/
+QDeclarative1PropertyAction::QDeclarative1PropertyAction(QObject *parent)
+: QDeclarative1AbstractAnimation(*(new QDeclarative1PropertyActionPrivate), parent)
+{
+ Q_D(QDeclarative1PropertyAction);
+ d->init();
+}
+
+QDeclarative1PropertyAction::~QDeclarative1PropertyAction()
+{
+}
+
+void QDeclarative1PropertyActionPrivate::init()
+{
+ Q_Q(QDeclarative1PropertyAction);
+ spa = new QActionAnimation_1;
+ QDeclarative_setParent_noEvent(spa, q);
+}
+
+QObject *QDeclarative1PropertyAction::target() const
+{
+ Q_D(const QDeclarative1PropertyAction);
+ return d->target;
+}
+
+void QDeclarative1PropertyAction::setTarget(QObject *o)
+{
+ Q_D(QDeclarative1PropertyAction);
+ if (d->target == o)
+ return;
+ d->target = o;
+ emit targetChanged();
+}
+
+QString QDeclarative1PropertyAction::property() const
+{
+ Q_D(const QDeclarative1PropertyAction);
+ return d->propertyName;
+}
+
+void QDeclarative1PropertyAction::setProperty(const QString &n)
+{
+ Q_D(QDeclarative1PropertyAction);
+ if (d->propertyName == n)
+ return;
+ d->propertyName = n;
+ emit propertyChanged();
+}
+
+/*!
+ \qmlproperty Object PropertyAction::target
+ \qmlproperty list<Object> PropertyAction::targets
+ \qmlproperty string PropertyAction::property
+ \qmlproperty string PropertyAction::properties
+
+ These properties determine the items and their properties that are
+ affected by this action.
+
+ The details of how these properties are interpreted in different situations
+ is covered in the \l{PropertyAnimation::properties}{corresponding} PropertyAnimation
+ documentation.
+
+ \sa exclude
+*/
+QString QDeclarative1PropertyAction::properties() const
+{
+ Q_D(const QDeclarative1PropertyAction);
+ return d->properties;
+}
+
+void QDeclarative1PropertyAction::setProperties(const QString &p)
+{
+ Q_D(QDeclarative1PropertyAction);
+ if (d->properties == p)
+ return;
+ d->properties = p;
+ emit propertiesChanged(p);
+}
+
+QDeclarativeListProperty<QObject> QDeclarative1PropertyAction::targets()
+{
+ Q_D(QDeclarative1PropertyAction);
+ return QDeclarativeListProperty<QObject>(this, d->targets);
+}
+
+/*!
+ \qmlproperty list<Object> PropertyAction::exclude
+ This property holds the objects that should not be affected by this action.
+
+ \sa targets
+*/
+QDeclarativeListProperty<QObject> QDeclarative1PropertyAction::exclude()
+{
+ Q_D(QDeclarative1PropertyAction);
+ return QDeclarativeListProperty<QObject>(this, d->exclude);
+}
+
+/*!
+ \qmlproperty any PropertyAction::value
+ This property holds the value to be set on the property.
+
+ If the PropertyAction is defined within a \l Transition or \l Behavior,
+ this value defaults to the value defined in the end state of the
+ \l Transition, or the value of the property change that triggered the
+ \l Behavior.
+*/
+QVariant QDeclarative1PropertyAction::value() const
+{
+ Q_D(const QDeclarative1PropertyAction);
+ return d->value;
+}
+
+void QDeclarative1PropertyAction::setValue(const QVariant &v)
+{
+ Q_D(QDeclarative1PropertyAction);
+ if (d->value.isNull || d->value != v) {
+ d->value = v;
+ emit valueChanged(v);
+ }
+}
+
+QAbstractAnimation *QDeclarative1PropertyAction::qtAnimation()
+{
+ Q_D(QDeclarative1PropertyAction);
+ return d->spa;
+}
+
+void QDeclarative1PropertyAction::transition(QDeclarative1StateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction)
+{
+ Q_D(QDeclarative1PropertyAction);
+ Q_UNUSED(direction);
+
+ struct QDeclarative1SetPropertyAnimationAction : public QAbstractAnimationAction
+ {
+ QDeclarative1StateActions actions;
+ virtual void doAction()
+ {
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ const QDeclarative1Action &action = actions.at(ii);
+ QDeclarativePropertyPrivate::write(action.property, action.toValue, QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::DontRemoveBinding);
+ }
+ }
+ };
+
+ QStringList props = d->properties.isEmpty() ? QStringList() : d->properties.split(QLatin1Char(','));
+ for (int ii = 0; ii < props.count(); ++ii)
+ props[ii] = props.at(ii).trimmed();
+ if (!d->propertyName.isEmpty())
+ props << d->propertyName;
+
+ QList<QObject*> targets = d->targets;
+ if (d->target)
+ targets.append(d->target);
+
+ bool hasSelectors = !props.isEmpty() || !targets.isEmpty() || !d->exclude.isEmpty();
+
+ if (d->defaultProperty.isValid() && !hasSelectors) {
+ props << d->defaultProperty.name();
+ targets << d->defaultProperty.object();
+ }
+
+ QDeclarative1SetPropertyAnimationAction *data = new QDeclarative1SetPropertyAnimationAction;
+
+ bool hasExplicit = false;
+ //an explicit animation has been specified
+ if (d->value.isValid()) {
+ for (int i = 0; i < props.count(); ++i) {
+ for (int j = 0; j < targets.count(); ++j) {
+ QDeclarative1Action myAction;
+ myAction.property = d->createProperty(targets.at(j), props.at(i), this);
+ if (myAction.property.isValid()) {
+ myAction.toValue = d->value;
+ QDeclarative1PropertyAnimationPrivate::convertVariant(myAction.toValue, myAction.property.propertyType());
+ data->actions << myAction;
+ hasExplicit = true;
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ QDeclarative1Action &action = actions[ii];
+ if (action.property.object() == myAction.property.object() &&
+ myAction.property.name() == action.property.name()) {
+ modified << action.property;
+ break; //### any chance there could be multiples?
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!hasExplicit)
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ QDeclarative1Action &action = actions[ii];
+
+ QObject *obj = action.property.object();
+ QString propertyName = action.property.name();
+ QObject *sObj = action.specifiedObject;
+ QString sPropertyName = action.specifiedProperty;
+ bool same = (obj == sObj);
+
+ if ((targets.isEmpty() || targets.contains(obj) || (!same && targets.contains(sObj))) &&
+ (!d->exclude.contains(obj)) && (same || (!d->exclude.contains(sObj))) &&
+ (props.contains(propertyName) || (!same && props.contains(sPropertyName)))) {
+ QDeclarative1Action myAction = action;
+
+ if (d->value.isValid())
+ myAction.toValue = d->value;
+ QDeclarative1PropertyAnimationPrivate::convertVariant(myAction.toValue, myAction.property.propertyType());
+
+ modified << action.property;
+ data->actions << myAction;
+ action.fromValue = myAction.toValue;
+ }
+ }
+
+ if (data->actions.count()) {
+ d->spa->setAnimAction(data, QAbstractAnimation::DeleteWhenStopped);
+ } else {
+ delete data;
+ }
+}
+
+/*!
+ \qmlclass NumberAnimation QDeclarative1NumberAnimation
+ \ingroup qml-animation-transition
+ \since 4.7
+ \inherits PropertyAnimation
+ \brief The NumberAnimation element animates changes in qreal-type values.
+
+ NumberAnimation is a specialized PropertyAnimation that defines an
+ animation to be applied when a numerical value changes.
+
+ Here is a NumberAnimation applied to the \c x property of a \l Rectangle
+ as a property value source. It animates the \c x value from its current
+ value to a value of 50, over 1000 milliseconds:
+
+ \snippet doc/src/snippets/declarative/numberanimation.qml 0
+
+ Like any other animation element, a NumberAnimation can be applied in a
+ number of ways, including transitions, behaviors and property value
+ sources. The \l {QML Animation and Transitions} documentation shows a
+ variety of methods for creating animations.
+
+ Note that NumberAnimation may not animate smoothly if there are irregular
+ changes in the number value that it is tracking. If this is the case, use
+ SmoothedAnimation instead.
+
+ \sa {QML Animation and Transitions}, {declarative/animation/basics}{Animation basics example}
+*/
+QDeclarative1NumberAnimation::QDeclarative1NumberAnimation(QObject *parent)
+: QDeclarative1PropertyAnimation(parent)
+{
+ init();
+}
+
+QDeclarative1NumberAnimation::QDeclarative1NumberAnimation(QDeclarative1PropertyAnimationPrivate &dd, QObject *parent)
+: QDeclarative1PropertyAnimation(dd, parent)
+{
+ init();
+}
+
+QDeclarative1NumberAnimation::~QDeclarative1NumberAnimation()
+{
+}
+
+void QDeclarative1NumberAnimation::init()
+{
+ Q_D(QDeclarative1PropertyAnimation);
+ d->interpolatorType = QMetaType::QReal;
+ d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType);
+}
+
+/*!
+ \qmlproperty real NumberAnimation::from
+ This property holds the starting value for the animation.
+
+ For example, the following animation is not applied until the \c x value
+ has reached 100:
+
+ \qml
+ Item {
+ states: [
+ // ...
+ ]
+
+ transition: Transition {
+ NumberAnimation { properties: "x"; from: 100; duration: 200 }
+ }
+ }
+ \endqml
+
+ If the NumberAnimation is defined within a \l Transition or \l Behavior,
+ this value defaults to the value defined in the starting state of the
+ \l Transition, or the current value of the property at the moment the
+ \l Behavior is triggered.
+
+ \sa {QML Animation and Transitions}
+*/
+
+qreal QDeclarative1NumberAnimation::from() const
+{
+ Q_D(const QDeclarative1PropertyAnimation);
+ return d->from.toReal();
+}
+
+void QDeclarative1NumberAnimation::setFrom(qreal f)
+{
+ QDeclarative1PropertyAnimation::setFrom(f);
+}
+
+/*!
+ \qmlproperty real NumberAnimation::to
+ This property holds the end value for the animation.
+
+ If the NumberAnimation is defined within a \l Transition or \l Behavior,
+ this value defaults to the value defined in the end state of the
+ \l Transition, or the value of the property change that triggered the
+ \l Behavior.
+
+ \sa {QML Animation and Transitions}
+*/
+qreal QDeclarative1NumberAnimation::to() const
+{
+ Q_D(const QDeclarative1PropertyAnimation);
+ return d->to.toReal();
+}
+
+void QDeclarative1NumberAnimation::setTo(qreal t)
+{
+ QDeclarative1PropertyAnimation::setTo(t);
+}
+
+
+
+/*!
+ \qmlclass Vector3dAnimation QDeclarative1Vector3dAnimation
+ \ingroup qml-animation-transition
+ \since 4.7
+ \inherits PropertyAnimation
+ \brief The Vector3dAnimation element animates changes in QVector3d values.
+
+ Vector3dAnimation is a specialized PropertyAnimation that defines an
+ animation to be applied when a Vector3d value changes.
+
+ Like any other animation element, a Vector3dAnimation can be applied in a
+ number of ways, including transitions, behaviors and property value
+ sources. The \l {QML Animation and Transitions} documentation shows a
+ variety of methods for creating animations.
+
+ \sa {QML Animation and Transitions}, {declarative/animation/basics}{Animation basics example}
+*/
+QDeclarative1Vector3dAnimation::QDeclarative1Vector3dAnimation(QObject *parent)
+: QDeclarative1PropertyAnimation(parent)
+{
+ Q_D(QDeclarative1PropertyAnimation);
+ d->interpolatorType = QMetaType::QVector3D;
+ d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType);
+ d->defaultToInterpolatorType = true;
+}
+
+QDeclarative1Vector3dAnimation::~QDeclarative1Vector3dAnimation()
+{
+}
+
+/*!
+ \qmlproperty real Vector3dAnimation::from
+ This property holds the starting value for the animation.
+
+ If the Vector3dAnimation is defined within a \l Transition or \l Behavior,
+ this value defaults to the value defined in the starting state of the
+ \l Transition, or the current value of the property at the moment the
+ \l Behavior is triggered.
+
+ \sa {QML Animation and Transitions}
+*/
+QVector3D QDeclarative1Vector3dAnimation::from() const
+{
+ Q_D(const QDeclarative1PropertyAnimation);
+ return d->from.value<QVector3D>();
+}
+
+void QDeclarative1Vector3dAnimation::setFrom(QVector3D f)
+{
+ QDeclarative1PropertyAnimation::setFrom(f);
+}
+
+/*!
+ \qmlproperty real Vector3dAnimation::to
+ This property holds the end value for the animation.
+
+ If the Vector3dAnimation is defined within a \l Transition or \l Behavior,
+ this value defaults to the value defined in the end state of the
+ \l Transition, or the value of the property change that triggered the
+ \l Behavior.
+
+ \sa {QML Animation and Transitions}
+*/
+QVector3D QDeclarative1Vector3dAnimation::to() const
+{
+ Q_D(const QDeclarative1PropertyAnimation);
+ return d->to.value<QVector3D>();
+}
+
+void QDeclarative1Vector3dAnimation::setTo(QVector3D t)
+{
+ QDeclarative1PropertyAnimation::setTo(t);
+}
+
+
+
+/*!
+ \qmlclass RotationAnimation QDeclarative1RotationAnimation
+ \ingroup qml-animation-transition
+ \since 4.7
+ \inherits PropertyAnimation
+ \brief The RotationAnimation element animates changes in rotation values.
+
+ RotationAnimation is a specialized PropertyAnimation that gives control
+ over the direction of rotation during an animation.
+
+ By default, it rotates in the direction
+ of the numerical change; a rotation from 0 to 240 will rotate 240 degrees
+ clockwise, while a rotation from 240 to 0 will rotate 240 degrees
+ counterclockwise. The \l direction property can be set to specify the
+ direction in which the rotation should occur.
+
+ In the following example we use RotationAnimation to animate the rotation
+ between states via the shortest path:
+
+ \snippet doc/src/snippets/declarative/rotationanimation.qml 0
+
+ Notice the RotationAnimation did not need to set a \l target
+ value. As a convenience, when used in a transition, RotationAnimation will rotate all
+ properties named "rotation" or "angle". You can override this by providing
+ your own properties via \l {PropertyAnimation::properties}{properties} or
+ \l {PropertyAnimation::property}{property}.
+
+ Also, note the \l Rectangle will be rotated around its default
+ \l {Item::}{transformOrigin} (which is \c Item.Center). To use a different
+ transform origin, set the origin in the PropertyChanges object and apply
+ the change at the start of the animation using PropertyAction. See the
+ PropertyAction documentation for more details.
+
+ Like any other animation element, a RotationAnimation can be applied in a
+ number of ways, including transitions, behaviors and property value
+ sources. The \l {QML Animation and Transitions} documentation shows a
+ variety of methods for creating animations.
+
+ \sa {QML Animation and Transitions}, {declarative/animation/basics}{Animation basics example}
+*/
+QVariant _q_interpolateShortestRotation(qreal &f, qreal &t, qreal progress)
+{
+ qreal newt = t;
+ qreal diff = t-f;
+ while(diff > 180.0){
+ newt -= 360.0;
+ diff -= 360.0;
+ }
+ while(diff < -180.0){
+ newt += 360.0;
+ diff += 360.0;
+ }
+ return QVariant(f + (newt - f) * progress);
+}
+
+QVariant _q_interpolateClockwiseRotation(qreal &f, qreal &t, qreal progress)
+{
+ qreal newt = t;
+ qreal diff = t-f;
+ while(diff < 0.0){
+ newt += 360.0;
+ diff += 360.0;
+ }
+ return QVariant(f + (newt - f) * progress);
+}
+
+QVariant _q_interpolateCounterclockwiseRotation(qreal &f, qreal &t, qreal progress)
+{
+ qreal newt = t;
+ qreal diff = t-f;
+ while(diff > 0.0){
+ newt -= 360.0;
+ diff -= 360.0;
+ }
+ return QVariant(f + (newt - f) * progress);
+}
+
+QDeclarative1RotationAnimation::QDeclarative1RotationAnimation(QObject *parent)
+: QDeclarative1PropertyAnimation(*(new QDeclarative1RotationAnimationPrivate), parent)
+{
+ Q_D(QDeclarative1RotationAnimation);
+ d->interpolatorType = QMetaType::QReal;
+ d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType);
+ d->defaultProperties = QLatin1String("rotation,angle");
+}
+
+QDeclarative1RotationAnimation::~QDeclarative1RotationAnimation()
+{
+}
+
+/*!
+ \qmlproperty real RotationAnimation::from
+ This property holds the starting value for the animation.
+
+ For example, the following animation is not applied until the \c angle value
+ has reached 100:
+
+ \qml
+ Item {
+ states: [
+ // ...
+ ]
+
+ transition: Transition {
+ RotationAnimation { properties: "angle"; from: 100; duration: 2000 }
+ }
+ }
+ \endqml
+
+ If the RotationAnimation is defined within a \l Transition or \l Behavior,
+ this value defaults to the value defined in the starting state of the
+ \l Transition, or the current value of the property at the moment the
+ \l Behavior is triggered.
+
+ \sa {QML Animation and Transitions}
+*/
+qreal QDeclarative1RotationAnimation::from() const
+{
+ Q_D(const QDeclarative1RotationAnimation);
+ return d->from.toReal();
+}
+
+void QDeclarative1RotationAnimation::setFrom(qreal f)
+{
+ QDeclarative1PropertyAnimation::setFrom(f);
+}
+
+/*!
+ \qmlproperty real RotationAnimation::to
+ This property holds the end value for the animation..
+
+ If the RotationAnimation is defined within a \l Transition or \l Behavior,
+ this value defaults to the value defined in the end state of the
+ \l Transition, or the value of the property change that triggered the
+ \l Behavior.
+
+ \sa {QML Animation and Transitions}
+*/
+qreal QDeclarative1RotationAnimation::to() const
+{
+ Q_D(const QDeclarative1RotationAnimation);
+ return d->to.toReal();
+}
+
+void QDeclarative1RotationAnimation::setTo(qreal t)
+{
+ QDeclarative1PropertyAnimation::setTo(t);
+}
+
+/*!
+ \qmlproperty enumeration RotationAnimation::direction
+ This property holds the direction of the rotation.
+
+ Possible values are:
+
+ \list
+ \o RotationAnimation.Numerical (default) - Rotate by linearly interpolating between the two numbers.
+ A rotation from 10 to 350 will rotate 340 degrees clockwise.
+ \o RotationAnimation.Clockwise - Rotate clockwise between the two values
+ \o RotationAnimation.Counterclockwise - Rotate counterclockwise between the two values
+ \o RotationAnimation.Shortest - Rotate in the direction that produces the shortest animation path.
+ A rotation from 10 to 350 will rotate 20 degrees counterclockwise.
+ \endlist
+*/
+QDeclarative1RotationAnimation::RotationDirection QDeclarative1RotationAnimation::direction() const
+{
+ Q_D(const QDeclarative1RotationAnimation);
+ return d->direction;
+}
+
+void QDeclarative1RotationAnimation::setDirection(QDeclarative1RotationAnimation::RotationDirection direction)
+{
+ Q_D(QDeclarative1RotationAnimation);
+ if (d->direction == direction)
+ return;
+
+ d->direction = direction;
+ switch(d->direction) {
+ case Clockwise:
+ d->interpolator = reinterpret_cast<QVariantAnimation::Interpolator>(&_q_interpolateClockwiseRotation);
+ break;
+ case Counterclockwise:
+ d->interpolator = reinterpret_cast<QVariantAnimation::Interpolator>(&_q_interpolateCounterclockwiseRotation);
+ break;
+ case Shortest:
+ d->interpolator = reinterpret_cast<QVariantAnimation::Interpolator>(&_q_interpolateShortestRotation);
+ break;
+ default:
+ d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType);
+ break;
+ }
+
+ emit directionChanged();
+}
+
+
+
+QDeclarative1AnimationGroup::QDeclarative1AnimationGroup(QObject *parent)
+: QDeclarative1AbstractAnimation(*(new QDeclarative1AnimationGroupPrivate), parent)
+{
+}
+
+QDeclarative1AnimationGroup::QDeclarative1AnimationGroup(QDeclarative1AnimationGroupPrivate &dd, QObject *parent)
+ : QDeclarative1AbstractAnimation(dd, parent)
+{
+}
+
+void QDeclarative1AnimationGroupPrivate::append_animation(QDeclarativeListProperty<QDeclarative1AbstractAnimation> *list, QDeclarative1AbstractAnimation *a)
+{
+ QDeclarative1AnimationGroup *q = qobject_cast<QDeclarative1AnimationGroup *>(list->object);
+ if (q) {
+ a->setGroup(q);
+ // This is an optimization for the parenting that already occurs via addAnimation
+ QDeclarative_setParent_noEvent(a->qtAnimation(), q->d_func()->ag);
+ q->d_func()->ag->addAnimation(a->qtAnimation());
+ }
+}
+
+void QDeclarative1AnimationGroupPrivate::clear_animation(QDeclarativeListProperty<QDeclarative1AbstractAnimation> *list)
+{
+ QDeclarative1AnimationGroup *q = qobject_cast<QDeclarative1AnimationGroup *>(list->object);
+ if (q) {
+ while (q->d_func()->animations.count()) {
+ QDeclarative1AbstractAnimation *firstAnim = q->d_func()->animations.at(0);
+ QDeclarative_setParent_noEvent(firstAnim->qtAnimation(), 0);
+ q->d_func()->ag->removeAnimation(firstAnim->qtAnimation());
+ firstAnim->setGroup(0);
+ }
+ }
+}
+
+QDeclarative1AnimationGroup::~QDeclarative1AnimationGroup()
+{
+}
+
+QDeclarativeListProperty<QDeclarative1AbstractAnimation> QDeclarative1AnimationGroup::animations()
+{
+ Q_D(QDeclarative1AnimationGroup);
+ QDeclarativeListProperty<QDeclarative1AbstractAnimation> list(this, d->animations);
+ list.append = &QDeclarative1AnimationGroupPrivate::append_animation;
+ list.clear = &QDeclarative1AnimationGroupPrivate::clear_animation;
+ return list;
+}
+
+/*!
+ \qmlclass SequentialAnimation QDeclarative1SequentialAnimation
+ \ingroup qml-animation-transition
+ \since 4.7
+ \inherits Animation
+ \brief The SequentialAnimation element allows animations to be run sequentially.
+
+ The SequentialAnimation and ParallelAnimation elements allow multiple
+ animations to be run together. Animations defined in a SequentialAnimation
+ are run one after the other, while animations defined in a ParallelAnimation
+ are run at the same time.
+
+ The following example runs two number animations in a sequence. The \l Rectangle
+ animates to a \c x position of 50, then to a \c y position of 50.
+
+ \snippet doc/src/snippets/declarative/sequentialanimation.qml 0
+
+ Animations defined within a \l Transition are automatically run in parallel,
+ so SequentialAnimation can be used to enclose the animations in a \l Transition
+ if this is the preferred behavior.
+
+ Like any other animation element, a SequentialAnimation can be applied in a
+ number of ways, including transitions, behaviors and property value
+ sources. The \l {QML Animation and Transitions} documentation shows a
+ variety of methods for creating animations.
+
+ \note Once an animation has been grouped into a SequentialAnimation or
+ ParallelAnimation, it cannot be individually started and stopped; the
+ SequentialAnimation or ParallelAnimation must be started and stopped as a group.
+
+ \sa ParallelAnimation, {QML Animation and Transitions}, {declarative/animation/basics}{Animation basics example}
+*/
+
+QDeclarative1SequentialAnimation::QDeclarative1SequentialAnimation(QObject *parent) :
+ QDeclarative1AnimationGroup(parent)
+{
+ Q_D(QDeclarative1AnimationGroup);
+ d->ag = new QSequentialAnimationGroup;
+ QDeclarative_setParent_noEvent(d->ag, this);
+}
+
+QDeclarative1SequentialAnimation::~QDeclarative1SequentialAnimation()
+{
+}
+
+QAbstractAnimation *QDeclarative1SequentialAnimation::qtAnimation()
+{
+ Q_D(QDeclarative1AnimationGroup);
+ return d->ag;
+}
+
+void QDeclarative1SequentialAnimation::transition(QDeclarative1StateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction)
+{
+ Q_D(QDeclarative1AnimationGroup);
+
+ int inc = 1;
+ int from = 0;
+ if (direction == Backward) {
+ inc = -1;
+ from = d->animations.count() - 1;
+ }
+
+ bool valid = d->defaultProperty.isValid();
+ for (int ii = from; ii < d->animations.count() && ii >= 0; ii += inc) {
+ if (valid)
+ d->animations.at(ii)->setDefaultTarget(d->defaultProperty);
+ d->animations.at(ii)->transition(actions, modified, direction);
+ }
+}
+
+
+
+/*!
+ \qmlclass ParallelAnimation QDeclarative1ParallelAnimation
+ \ingroup qml-animation-transition
+ \since 4.7
+ \inherits Animation
+ \brief The ParallelAnimation element allows animations to be run in parallel.
+
+ The SequentialAnimation and ParallelAnimation elements allow multiple
+ animations to be run together. Animations defined in a SequentialAnimation
+ are run one after the other, while animations defined in a ParallelAnimation
+ are run at the same time.
+
+ The following animation runs two number animations in parallel. The \l Rectangle
+ moves to (50,50) by animating its \c x and \c y properties at the same time.
+
+ \snippet doc/src/snippets/declarative/parallelanimation.qml 0
+
+ Like any other animation element, a ParallelAnimation can be applied in a
+ number of ways, including transitions, behaviors and property value
+ sources. The \l {QML Animation and Transitions} documentation shows a
+ variety of methods for creating animations.
+
+ \note Once an animation has been grouped into a SequentialAnimation or
+ ParallelAnimation, it cannot be individually started and stopped; the
+ SequentialAnimation or ParallelAnimation must be started and stopped as a group.
+
+ \sa SequentialAnimation, {QML Animation and Transitions}, {declarative/animation/basics}{Animation basics example}
+*/
+QDeclarative1ParallelAnimation::QDeclarative1ParallelAnimation(QObject *parent) :
+ QDeclarative1AnimationGroup(parent)
+{
+ Q_D(QDeclarative1AnimationGroup);
+ d->ag = new QParallelAnimationGroup;
+ QDeclarative_setParent_noEvent(d->ag, this);
+}
+
+QDeclarative1ParallelAnimation::~QDeclarative1ParallelAnimation()
+{
+}
+
+QAbstractAnimation *QDeclarative1ParallelAnimation::qtAnimation()
+{
+ Q_D(QDeclarative1AnimationGroup);
+ return d->ag;
+}
+
+void QDeclarative1ParallelAnimation::transition(QDeclarative1StateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction)
+{
+ Q_D(QDeclarative1AnimationGroup);
+ bool valid = d->defaultProperty.isValid();
+ for (int ii = 0; ii < d->animations.count(); ++ii) {
+ if (valid)
+ d->animations.at(ii)->setDefaultTarget(d->defaultProperty);
+ d->animations.at(ii)->transition(actions, modified, direction);
+ }
+}
+
+
+
+//convert a variant from string type to another animatable type
+void QDeclarative1PropertyAnimationPrivate::convertVariant(QVariant &variant, int type)
+{
+ if (variant.userType() != QVariant::String) {
+ variant.convert((QVariant::Type)type);
+ return;
+ }
+
+ switch (type) {
+ case QVariant::Rect: {
+ variant.setValue(QDeclarativeStringConverters::rectFFromString(variant.toString()).toRect());
+ break;
+ }
+ case QVariant::RectF: {
+ variant.setValue(QDeclarativeStringConverters::rectFFromString(variant.toString()));
+ break;
+ }
+ case QVariant::Point: {
+ variant.setValue(QDeclarativeStringConverters::pointFFromString(variant.toString()).toPoint());
+ break;
+ }
+ case QVariant::PointF: {
+ variant.setValue(QDeclarativeStringConverters::pointFFromString(variant.toString()));
+ break;
+ }
+ case QVariant::Size: {
+ variant.setValue(QDeclarativeStringConverters::sizeFFromString(variant.toString()).toSize());
+ break;
+ }
+ case QVariant::SizeF: {
+ variant.setValue(QDeclarativeStringConverters::sizeFFromString(variant.toString()));
+ break;
+ }
+ case QVariant::Color: {
+ variant.setValue(QDeclarativeStringConverters::colorFromString(variant.toString()));
+ break;
+ }
+ case QVariant::Vector3D: {
+ variant.setValue(QDeclarativeStringConverters::vector3DFromString(variant.toString()));
+ break;
+ }
+ default:
+ if (QDeclarativeValueTypeFactory::isValueType((uint)type)) {
+ variant.convert((QVariant::Type)type);
+ } else {
+ QDeclarativeMetaType::StringConverter converter = QDeclarativeMetaType::customStringConverter(type);
+ if (converter)
+ variant = converter(variant.toString());
+ }
+ break;
+ }
+}
+
+/*!
+ \qmlclass PropertyAnimation QDeclarative1PropertyAnimation
+ \ingroup qml-animation-transition
+ \since 4.7
+ \inherits Animation
+ \brief The PropertyAnimation element animates changes in property values.
+
+ PropertyAnimation provides a way to animate changes to a property's value.
+
+ It can be used to define animations in a number of ways:
+
+ \list
+ \o In a \l Transition
+
+ For example, to animate any objects that have changed their \c x or \c y properties
+ as a result of a state change, using an \c InOutQuad easing curve:
+
+ \snippet doc/src/snippets/declarative/propertyanimation.qml transition
+
+
+ \o In a \l Behavior
+
+ For example, to animate all changes to a rectangle's \c x property:
+
+ \snippet doc/src/snippets/declarative/propertyanimation.qml behavior
+
+
+ \o As a property value source
+
+ For example, to repeatedly animate the rectangle's \c x property:
+
+ \snippet doc/src/snippets/declarative/propertyanimation.qml propertyvaluesource
+
+
+ \o In a signal handler
+
+ For example, to fade out \c theObject when clicked:
+ \qml
+ MouseArea {
+ anchors.fill: theObject
+ onClicked: PropertyAnimation { target: theObject; property: "opacity"; to: 0 }
+ }
+ \endqml
+
+ \o Standalone
+
+ For example, to animate \c rect's \c width property over 500ms, from its current width to 30:
+
+ \snippet doc/src/snippets/declarative/propertyanimation.qml standalone
+
+ \endlist
+
+ Depending on how the animation is used, the set of properties normally used will be
+ different. For more information see the individual property documentation, as well
+ as the \l{QML Animation and Transitions} introduction.
+
+ Note that PropertyAnimation inherits the abstract \l Animation element.
+ This includes additional properties and methods for controlling the animation.
+
+ \sa {QML Animation and Transitions}, {declarative/animation/basics}{Animation basics example}
+*/
+
+QDeclarative1PropertyAnimation::QDeclarative1PropertyAnimation(QObject *parent)
+: QDeclarative1AbstractAnimation(*(new QDeclarative1PropertyAnimationPrivate), parent)
+{
+ Q_D(QDeclarative1PropertyAnimation);
+ d->init();
+}
+
+QDeclarative1PropertyAnimation::QDeclarative1PropertyAnimation(QDeclarative1PropertyAnimationPrivate &dd, QObject *parent)
+: QDeclarative1AbstractAnimation(dd, parent)
+{
+ Q_D(QDeclarative1PropertyAnimation);
+ d->init();
+}
+
+QDeclarative1PropertyAnimation::~QDeclarative1PropertyAnimation()
+{
+}
+
+void QDeclarative1PropertyAnimationPrivate::init()
+{
+ Q_Q(QDeclarative1PropertyAnimation);
+ va = new QDeclarative1BulkValueAnimator;
+ QDeclarative_setParent_noEvent(va, q);
+}
+
+/*!
+ \qmlproperty int PropertyAnimation::duration
+ This property holds the duration of the animation, in milliseconds.
+
+ The default value is 250.
+*/
+int QDeclarative1PropertyAnimation::duration() const
+{
+ Q_D(const QDeclarative1PropertyAnimation);
+ return d->va->duration();
+}
+
+void QDeclarative1PropertyAnimation::setDuration(int duration)
+{
+ if (duration < 0) {
+ qmlInfo(this) << tr("Cannot set a duration of < 0");
+ return;
+ }
+
+ Q_D(QDeclarative1PropertyAnimation);
+ if (d->va->duration() == duration)
+ return;
+ d->va->setDuration(duration);
+ emit durationChanged(duration);
+}
+
+/*!
+ \qmlproperty real PropertyAnimation::from
+ This property holds the starting value for the animation.
+
+ If the PropertyAnimation is defined within a \l Transition or \l Behavior,
+ this value defaults to the value defined in the starting state of the
+ \l Transition, or the current value of the property at the moment the
+ \l Behavior is triggered.
+
+ \sa {QML Animation and Transitions}
+*/
+QVariant QDeclarative1PropertyAnimation::from() const
+{
+ Q_D(const QDeclarative1PropertyAnimation);
+ return d->from;
+}
+
+void QDeclarative1PropertyAnimation::setFrom(const QVariant &f)
+{
+ Q_D(QDeclarative1PropertyAnimation);
+ if (d->fromIsDefined && f == d->from)
+ return;
+ d->from = f;
+ d->fromIsDefined = f.isValid();
+ emit fromChanged(f);
+}
+
+/*!
+ \qmlproperty real PropertyAnimation::to
+ This property holds the end value for the animation.
+
+ If the PropertyAnimation is defined within a \l Transition or \l Behavior,
+ this value defaults to the value defined in the end state of the
+ \l Transition, or the value of the property change that triggered the
+ \l Behavior.
+
+ \sa {QML Animation and Transitions}
+*/
+QVariant QDeclarative1PropertyAnimation::to() const
+{
+ Q_D(const QDeclarative1PropertyAnimation);
+ return d->to;
+}
+
+void QDeclarative1PropertyAnimation::setTo(const QVariant &t)
+{
+ Q_D(QDeclarative1PropertyAnimation);
+ if (d->toIsDefined && t == d->to)
+ return;
+ d->to = t;
+ d->toIsDefined = t.isValid();
+ emit toChanged(t);
+}
+
+/*!
+ \qmlproperty enumeration PropertyAnimation::easing.type
+ \qmlproperty real PropertyAnimation::easing.amplitude
+ \qmlproperty real PropertyAnimation::easing.overshoot
+ \qmlproperty real PropertyAnimation::easing.period
+ \brief the easing curve used for the animation.
+
+ To specify an easing curve you need to specify at least the type. For some curves you can also specify
+ amplitude, period and/or overshoot (more details provided after the table). The default easing curve is
+ \c Easing.Linear.
+
+ \qml
+ PropertyAnimation { properties: "y"; easing.type: Easing.InOutElastic; easing.amplitude: 2.0; easing.period: 1.5 }
+ \endqml
+
+ Available types are:
+
+ \table
+ \row
+ \o \c Easing.Linear
+ \o Easing curve for a linear (t) function: velocity is constant.
+ \o \inlineimage qeasingcurve-linear.png
+ \row
+ \o \c Easing.InQuad
+ \o Easing curve for a quadratic (t^2) function: accelerating from zero velocity.
+ \o \inlineimage qeasingcurve-inquad.png
+ \row
+ \o \c Easing.OutQuad
+ \o Easing curve for a quadratic (t^2) function: decelerating to zero velocity.
+ \o \inlineimage qeasingcurve-outquad.png
+ \row
+ \o \c Easing.InOutQuad
+ \o Easing curve for a quadratic (t^2) function: acceleration until halfway, then deceleration.
+ \o \inlineimage qeasingcurve-inoutquad.png
+ \row
+ \o \c Easing.OutInQuad
+ \o Easing curve for a quadratic (t^2) function: deceleration until halfway, then acceleration.
+ \o \inlineimage qeasingcurve-outinquad.png
+ \row
+ \o \c Easing.InCubic
+ \o Easing curve for a cubic (t^3) function: accelerating from zero velocity.
+ \o \inlineimage qeasingcurve-incubic.png
+ \row
+ \o \c Easing.OutCubic
+ \o Easing curve for a cubic (t^3) function: decelerating from zero velocity.
+ \o \inlineimage qeasingcurve-outcubic.png
+ \row
+ \o \c Easing.InOutCubic
+ \o Easing curve for a cubic (t^3) function: acceleration until halfway, then deceleration.
+ \o \inlineimage qeasingcurve-inoutcubic.png
+ \row
+ \o \c Easing.OutInCubic
+ \o Easing curve for a cubic (t^3) function: deceleration until halfway, then acceleration.
+ \o \inlineimage qeasingcurve-outincubic.png
+ \row
+ \o \c Easing.InQuart
+ \o Easing curve for a quartic (t^4) function: accelerating from zero velocity.
+ \o \inlineimage qeasingcurve-inquart.png
+ \row
+ \o \c Easing.OutQuart
+ \o Easing curve for a quartic (t^4) function: decelerating from zero velocity.
+ \o \inlineimage qeasingcurve-outquart.png
+ \row
+ \o \c Easing.InOutQuart
+ \o Easing curve for a quartic (t^4) function: acceleration until halfway, then deceleration.
+ \o \inlineimage qeasingcurve-inoutquart.png
+ \row
+ \o \c Easing.OutInQuart
+ \o Easing curve for a quartic (t^4) function: deceleration until halfway, then acceleration.
+ \o \inlineimage qeasingcurve-outinquart.png
+ \row
+ \o \c Easing.InQuint
+ \o Easing curve for a quintic (t^5) function: accelerating from zero velocity.
+ \o \inlineimage qeasingcurve-inquint.png
+ \row
+ \o \c Easing.OutQuint
+ \o Easing curve for a quintic (t^5) function: decelerating from zero velocity.
+ \o \inlineimage qeasingcurve-outquint.png
+ \row
+ \o \c Easing.InOutQuint
+ \o Easing curve for a quintic (t^5) function: acceleration until halfway, then deceleration.
+ \o \inlineimage qeasingcurve-inoutquint.png
+ \row
+ \o \c Easing.OutInQuint
+ \o Easing curve for a quintic (t^5) function: deceleration until halfway, then acceleration.
+ \o \inlineimage qeasingcurve-outinquint.png
+ \row
+ \o \c Easing.InSine
+ \o Easing curve for a sinusoidal (sin(t)) function: accelerating from zero velocity.
+ \o \inlineimage qeasingcurve-insine.png
+ \row
+ \o \c Easing.OutSine
+ \o Easing curve for a sinusoidal (sin(t)) function: decelerating from zero velocity.
+ \o \inlineimage qeasingcurve-outsine.png
+ \row
+ \o \c Easing.InOutSine
+ \o Easing curve for a sinusoidal (sin(t)) function: acceleration until halfway, then deceleration.
+ \o \inlineimage qeasingcurve-inoutsine.png
+ \row
+ \o \c Easing.OutInSine
+ \o Easing curve for a sinusoidal (sin(t)) function: deceleration until halfway, then acceleration.
+ \o \inlineimage qeasingcurve-outinsine.png
+ \row
+ \o \c Easing.InExpo
+ \o Easing curve for an exponential (2^t) function: accelerating from zero velocity.
+ \o \inlineimage qeasingcurve-inexpo.png
+ \row
+ \o \c Easing.OutExpo
+ \o Easing curve for an exponential (2^t) function: decelerating from zero velocity.
+ \o \inlineimage qeasingcurve-outexpo.png
+ \row
+ \o \c Easing.InOutExpo
+ \o Easing curve for an exponential (2^t) function: acceleration until halfway, then deceleration.
+ \o \inlineimage qeasingcurve-inoutexpo.png
+ \row
+ \o \c Easing.OutInExpo
+ \o Easing curve for an exponential (2^t) function: deceleration until halfway, then acceleration.
+ \o \inlineimage qeasingcurve-outinexpo.png
+ \row
+ \o \c Easing.InCirc
+ \o Easing curve for a circular (sqrt(1-t^2)) function: accelerating from zero velocity.
+ \o \inlineimage qeasingcurve-incirc.png
+ \row
+ \o \c Easing.OutCirc
+ \o Easing curve for a circular (sqrt(1-t^2)) function: decelerating from zero velocity.
+ \o \inlineimage qeasingcurve-outcirc.png
+ \row
+ \o \c Easing.InOutCirc
+ \o Easing curve for a circular (sqrt(1-t^2)) function: acceleration until halfway, then deceleration.
+ \o \inlineimage qeasingcurve-inoutcirc.png
+ \row
+ \o \c Easing.OutInCirc
+ \o Easing curve for a circular (sqrt(1-t^2)) function: deceleration until halfway, then acceleration.
+ \o \inlineimage qeasingcurve-outincirc.png
+ \row
+ \o \c Easing.InElastic
+ \o Easing curve for an elastic (exponentially decaying sine wave) function: accelerating from zero velocity.
+ \br The peak amplitude can be set with the \e amplitude parameter, and the period of decay by the \e period parameter.
+ \o \inlineimage qeasingcurve-inelastic.png
+ \row
+ \o \c Easing.OutElastic
+ \o Easing curve for an elastic (exponentially decaying sine wave) function: decelerating from zero velocity.
+ \br The peak amplitude can be set with the \e amplitude parameter, and the period of decay by the \e period parameter.
+ \o \inlineimage qeasingcurve-outelastic.png
+ \row
+ \o \c Easing.InOutElastic
+ \o Easing curve for an elastic (exponentially decaying sine wave) function: acceleration until halfway, then deceleration.
+ \o \inlineimage qeasingcurve-inoutelastic.png
+ \row
+ \o \c Easing.OutInElastic
+ \o Easing curve for an elastic (exponentially decaying sine wave) function: deceleration until halfway, then acceleration.
+ \o \inlineimage qeasingcurve-outinelastic.png
+ \row
+ \o \c Easing.InBack
+ \o Easing curve for a back (overshooting cubic function: (s+1)*t^3 - s*t^2) easing in: accelerating from zero velocity.
+ \o \inlineimage qeasingcurve-inback.png
+ \row
+ \o \c Easing.OutBack
+ \o Easing curve for a back (overshooting cubic function: (s+1)*t^3 - s*t^2) easing out: decelerating to zero velocity.
+ \o \inlineimage qeasingcurve-outback.png
+ \row
+ \o \c Easing.InOutBack
+ \o Easing curve for a back (overshooting cubic function: (s+1)*t^3 - s*t^2) easing in/out: acceleration until halfway, then deceleration.
+ \o \inlineimage qeasingcurve-inoutback.png
+ \row
+ \o \c Easing.OutInBack
+ \o Easing curve for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing out/in: deceleration until halfway, then acceleration.
+ \o \inlineimage qeasingcurve-outinback.png
+ \row
+ \o \c Easing.InBounce
+ \o Easing curve for a bounce (exponentially decaying parabolic bounce) function: accelerating from zero velocity.
+ \o \inlineimage qeasingcurve-inbounce.png
+ \row
+ \o \c Easing.OutBounce
+ \o Easing curve for a bounce (exponentially decaying parabolic bounce) function: decelerating from zero velocity.
+ \o \inlineimage qeasingcurve-outbounce.png
+ \row
+ \o \c Easing.InOutBounce
+ \o Easing curve for a bounce (exponentially decaying parabolic bounce) function easing in/out: acceleration until halfway, then deceleration.
+ \o \inlineimage qeasingcurve-inoutbounce.png
+ \row
+ \o \c Easing.OutInBounce
+ \o Easing curve for a bounce (exponentially decaying parabolic bounce) function easing out/in: deceleration until halfway, then acceleration.
+ \o \inlineimage qeasingcurve-outinbounce.png
+ \endtable
+
+ \c easing.amplitude is only applicable for bounce and elastic curves (curves of type
+ \c Easing.InBounce, \c Easing.OutBounce, \c Easing.InOutBounce, \c Easing.OutInBounce, \c Easing.InElastic,
+ \c Easing.OutElastic, \c Easing.InOutElastic or \c Easing.OutInElastic).
+
+ \c easing.overshoot is only applicable if \c easing.type is: \c Easing.InBack, \c Easing.OutBack,
+ \c Easing.InOutBack or \c Easing.OutInBack.
+
+ \c easing.period is only applicable if easing.type is: \c Easing.InElastic, \c Easing.OutElastic,
+ \c Easing.InOutElastic or \c Easing.OutInElastic.
+
+ See the \l {declarative/animation/easing}{easing} example for a demonstration of
+ the different easing settings.
+*/
+QEasingCurve QDeclarative1PropertyAnimation::easing() const
+{
+ Q_D(const QDeclarative1PropertyAnimation);
+ return d->va->easingCurve();
+}
+
+void QDeclarative1PropertyAnimation::setEasing(const QEasingCurve &e)
+{
+ Q_D(QDeclarative1PropertyAnimation);
+ if (d->va->easingCurve() == e)
+ return;
+
+ d->va->setEasingCurve(e);
+ emit easingChanged(e);
+}
+
+QObject *QDeclarative1PropertyAnimation::target() const
+{
+ Q_D(const QDeclarative1PropertyAnimation);
+ return d->target;
+}
+
+void QDeclarative1PropertyAnimation::setTarget(QObject *o)
+{
+ Q_D(QDeclarative1PropertyAnimation);
+ if (d->target == o)
+ return;
+ d->target = o;
+ emit targetChanged();
+}
+
+QString QDeclarative1PropertyAnimation::property() const
+{
+ Q_D(const QDeclarative1PropertyAnimation);
+ return d->propertyName;
+}
+
+void QDeclarative1PropertyAnimation::setProperty(const QString &n)
+{
+ Q_D(QDeclarative1PropertyAnimation);
+ if (d->propertyName == n)
+ return;
+ d->propertyName = n;
+ emit propertyChanged();
+}
+
+QString QDeclarative1PropertyAnimation::properties() const
+{
+ Q_D(const QDeclarative1PropertyAnimation);
+ return d->properties;
+}
+
+void QDeclarative1PropertyAnimation::setProperties(const QString &prop)
+{
+ Q_D(QDeclarative1PropertyAnimation);
+ if (d->properties == prop)
+ return;
+
+ d->properties = prop;
+ emit propertiesChanged(prop);
+}
+
+/*!
+ \qmlproperty string PropertyAnimation::properties
+ \qmlproperty list<Object> PropertyAnimation::targets
+ \qmlproperty string PropertyAnimation::property
+ \qmlproperty Object PropertyAnimation::target
+
+ These properties are used as a set to determine which properties should be animated.
+ The singular and plural forms are functionally identical, e.g.
+ \qml
+ NumberAnimation { target: theItem; property: "x"; to: 500 }
+ \endqml
+ has the same meaning as
+ \qml
+ NumberAnimation { targets: theItem; properties: "x"; to: 500 }
+ \endqml
+ The singular forms are slightly optimized, so if you do have only a single target/property
+ to animate you should try to use them.
+
+ The \c targets property allows multiple targets to be set. For example, this animates the
+ \c x property of both \c itemA and \c itemB:
+
+ \qml
+ NumberAnimation { targets: [itemA, itemB]; properties: "x"; to: 500 }
+ \endqml
+
+ In many cases these properties do not need to be explicitly specified, as they can be
+ inferred from the animation framework:
+
+ \table 80%
+ \row
+ \o Value Source / Behavior
+ \o When an animation is used as a value source or in a Behavior, the default target and property
+ name to be animated can both be inferred.
+ \qml
+ Rectangle {
+ id: theRect
+ width: 100; height: 100
+ color: Qt.rgba(0,0,1)
+ NumberAnimation on x { to: 500; loops: Animation.Infinite } //animate theRect's x property
+ Behavior on y { NumberAnimation {} } //animate theRect's y property
+ }
+ \endqml
+ \row
+ \o Transition
+ \o When used in a transition, a property animation is assumed to match \e all targets
+ but \e no properties. In practice, that means you need to specify at least the properties
+ in order for the animation to do anything.
+ \qml
+ Rectangle {
+ id: theRect
+ width: 100; height: 100
+ color: Qt.rgba(0,0,1)
+ Item { id: uselessItem }
+ states: State {
+ name: "state1"
+ PropertyChanges { target: theRect; x: 200; y: 200; z: 4 }
+ PropertyChanges { target: uselessItem; x: 10; y: 10; z: 2 }
+ }
+ transitions: Transition {
+ //animate both theRect's and uselessItem's x and y to their final values
+ NumberAnimation { properties: "x,y" }
+
+ //animate theRect's z to its final value
+ NumberAnimation { target: theRect; property: "z" }
+ }
+ }
+ \endqml
+ \row
+ \o Standalone
+ \o When an animation is used standalone, both the target and property need to be
+ explicitly specified.
+ \qml
+ Rectangle {
+ id: theRect
+ width: 100; height: 100
+ color: Qt.rgba(0,0,1)
+ //need to explicitly specify target and property
+ NumberAnimation { id: theAnim; target: theRect; property: "x"; to: 500 }
+ MouseArea {
+ anchors.fill: parent
+ onClicked: theAnim.start()
+ }
+ }
+ \endqml
+ \endtable
+
+ As seen in the above example, properties is specified as a comma-separated string of property names to animate.
+
+ \sa exclude, {QML Animation and Transitions}
+*/
+QDeclarativeListProperty<QObject> QDeclarative1PropertyAnimation::targets()
+{
+ Q_D(QDeclarative1PropertyAnimation);
+ return QDeclarativeListProperty<QObject>(this, d->targets);
+}
+
+/*!
+ \qmlproperty list<Object> PropertyAnimation::exclude
+ This property holds the items not to be affected by this animation.
+ \sa PropertyAnimation::targets
+*/
+QDeclarativeListProperty<QObject> QDeclarative1PropertyAnimation::exclude()
+{
+ Q_D(QDeclarative1PropertyAnimation);
+ return QDeclarativeListProperty<QObject>(this, d->exclude);
+}
+
+QAbstractAnimation *QDeclarative1PropertyAnimation::qtAnimation()
+{
+ Q_D(QDeclarative1PropertyAnimation);
+ return d->va;
+}
+
+void QDeclarative1AnimationPropertyUpdater::setValue(qreal v)
+{
+ bool deleted = false;
+ wasDeleted = &deleted;
+ if (reverse) //QVariantAnimation sends us 1->0 when reversed, but we are expecting 0->1
+ v = 1 - v;
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ QDeclarative1Action &action = actions[ii];
+
+ if (v == 1.)
+ QDeclarativePropertyPrivate::write(action.property, action.toValue, QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::DontRemoveBinding);
+ else {
+ if (!fromSourced && !fromDefined) {
+ action.fromValue = action.property.read();
+ if (interpolatorType)
+ QDeclarative1PropertyAnimationPrivate::convertVariant(action.fromValue, interpolatorType);
+ }
+ if (!interpolatorType) {
+ int propType = action.property.propertyType();
+ if (!prevInterpolatorType || prevInterpolatorType != propType) {
+ prevInterpolatorType = propType;
+ interpolator = QVariantAnimationPrivate::getInterpolator(prevInterpolatorType);
+ }
+ }
+ if (interpolator)
+ QDeclarativePropertyPrivate::write(action.property, interpolator(action.fromValue.constData(), action.toValue.constData(), v), QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::DontRemoveBinding);
+ }
+ if (deleted)
+ return;
+ }
+ wasDeleted = 0;
+ fromSourced = true;
+}
+
+void QDeclarative1PropertyAnimation::transition(QDeclarative1StateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction)
+{
+ Q_D(QDeclarative1PropertyAnimation);
+
+ QStringList props = d->properties.isEmpty() ? QStringList() : d->properties.split(QLatin1Char(','));
+ for (int ii = 0; ii < props.count(); ++ii)
+ props[ii] = props.at(ii).trimmed();
+ if (!d->propertyName.isEmpty())
+ props << d->propertyName;
+
+ QList<QObject*> targets = d->targets;
+ if (d->target)
+ targets.append(d->target);
+
+ bool hasSelectors = !props.isEmpty() || !targets.isEmpty() || !d->exclude.isEmpty();
+ bool useType = (props.isEmpty() && d->defaultToInterpolatorType) ? true : false;
+
+ if (d->defaultProperty.isValid() && !hasSelectors) {
+ props << d->defaultProperty.name();
+ targets << d->defaultProperty.object();
+ }
+
+ if (props.isEmpty() && !d->defaultProperties.isEmpty()) {
+ props << d->defaultProperties.split(QLatin1Char(','));
+ }
+
+ QDeclarative1AnimationPropertyUpdater *data = new QDeclarative1AnimationPropertyUpdater;
+ data->interpolatorType = d->interpolatorType;
+ data->interpolator = d->interpolator;
+ data->reverse = direction == Backward ? true : false;
+ data->fromSourced = false;
+ data->fromDefined = d->fromIsDefined;
+
+ bool hasExplicit = false;
+ //an explicit animation has been specified
+ if (d->toIsDefined) {
+ for (int i = 0; i < props.count(); ++i) {
+ for (int j = 0; j < targets.count(); ++j) {
+ QDeclarative1Action myAction;
+ myAction.property = d->createProperty(targets.at(j), props.at(i), this);
+ if (myAction.property.isValid()) {
+ if (d->fromIsDefined) {
+ myAction.fromValue = d->from;
+ d->convertVariant(myAction.fromValue, d->interpolatorType ? d->interpolatorType : myAction.property.propertyType());
+ }
+ myAction.toValue = d->to;
+ d->convertVariant(myAction.toValue, d->interpolatorType ? d->interpolatorType : myAction.property.propertyType());
+ data->actions << myAction;
+ hasExplicit = true;
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ QDeclarative1Action &action = actions[ii];
+ if (action.property.object() == myAction.property.object() &&
+ myAction.property.name() == action.property.name()) {
+ modified << action.property;
+ break; //### any chance there could be multiples?
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!hasExplicit)
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ QDeclarative1Action &action = actions[ii];
+
+ QObject *obj = action.property.object();
+ QString propertyName = action.property.name();
+ QObject *sObj = action.specifiedObject;
+ QString sPropertyName = action.specifiedProperty;
+ bool same = (obj == sObj);
+
+ if ((targets.isEmpty() || targets.contains(obj) || (!same && targets.contains(sObj))) &&
+ (!d->exclude.contains(obj)) && (same || (!d->exclude.contains(sObj))) &&
+ (props.contains(propertyName) || (!same && props.contains(sPropertyName))
+ || (useType && action.property.propertyType() == d->interpolatorType))) {
+ QDeclarative1Action myAction = action;
+
+ if (d->fromIsDefined)
+ myAction.fromValue = d->from;
+ else
+ myAction.fromValue = QVariant();
+ if (d->toIsDefined)
+ myAction.toValue = d->to;
+
+ d->convertVariant(myAction.fromValue, d->interpolatorType ? d->interpolatorType : myAction.property.propertyType());
+ d->convertVariant(myAction.toValue, d->interpolatorType ? d->interpolatorType : myAction.property.propertyType());
+
+ modified << action.property;
+
+ data->actions << myAction;
+ action.fromValue = myAction.toValue;
+ }
+ }
+
+ if (data->actions.count()) {
+ if (!d->rangeIsSet) {
+ d->va->setStartValue(qreal(0));
+ d->va->setEndValue(qreal(1));
+ d->rangeIsSet = true;
+ }
+ d->va->setAnimValue(data, QAbstractAnimation::DeleteWhenStopped);
+ d->va->setFromSourcedValue(&data->fromSourced);
+ d->actions = &data->actions;
+ } else {
+ delete data;
+ d->va->setFromSourcedValue(0); //clear previous data
+ d->va->setAnimValue(0, QAbstractAnimation::DeleteWhenStopped); //clear previous data
+ d->actions = 0;
+ }
+}
+
+/*!
+ \qmlclass ParentAnimation QDeclarative1ParentAnimation
+ \ingroup qml-animation-transition
+ \since 4.7
+ \inherits Animation
+ \brief The ParentAnimation element animates changes in parent values.
+
+ ParentAnimation is used to animate a parent change for an \l Item.
+
+ For example, the following ParentChange changes \c blueRect to become
+ a child of \c redRect when it is clicked. The inclusion of the
+ ParentAnimation, which defines a NumberAnimation to be applied during
+ the transition, ensures the item animates smoothly as it moves to
+ its new parent:
+
+ \snippet doc/src/snippets/declarative/parentanimation.qml 0
+
+ A ParentAnimation can contain any number of animations. These animations will
+ be run in parallel; to run them sequentially, define them within a
+ SequentialAnimation.
+
+ In some cases, such as when reparenting between items with clipping enabled, it is useful
+ to animate the parent change via another item that does not have clipping
+ enabled. Such an item can be set using the \l via property.
+
+ For convenience, when a ParentAnimation is used in a \l Transition, it will
+ animate any ParentChange that has occurred during the state change.
+ This can be overridden by setting a specific target item using the
+ \l target property.
+
+ Like any other animation element, a ParentAnimation can be applied in a
+ number of ways, including transitions, behaviors and property value
+ sources. The \l {QML Animation and Transitions} documentation shows a
+ variety of methods for creating animations.
+
+ \sa {QML Animation and Transitions}, {declarative/animation/basics}{Animation basics example}
+*/
+QDeclarative1ParentAnimation::QDeclarative1ParentAnimation(QObject *parent)
+ : QDeclarative1AnimationGroup(*(new QDeclarative1ParentAnimationPrivate), parent)
+{
+ Q_D(QDeclarative1ParentAnimation);
+ d->topLevelGroup = new QSequentialAnimationGroup;
+ QDeclarative_setParent_noEvent(d->topLevelGroup, this);
+
+ d->startAction = new QActionAnimation_1;
+ QDeclarative_setParent_noEvent(d->startAction, d->topLevelGroup);
+ d->topLevelGroup->addAnimation(d->startAction);
+
+ d->ag = new QParallelAnimationGroup;
+ QDeclarative_setParent_noEvent(d->ag, d->topLevelGroup);
+ d->topLevelGroup->addAnimation(d->ag);
+
+ d->endAction = new QActionAnimation_1;
+ QDeclarative_setParent_noEvent(d->endAction, d->topLevelGroup);
+ d->topLevelGroup->addAnimation(d->endAction);
+}
+
+QDeclarative1ParentAnimation::~QDeclarative1ParentAnimation()
+{
+}
+
+/*!
+ \qmlproperty Item ParentAnimation::target
+ The item to reparent.
+
+ When used in a transition, if no target is specified, all
+ ParentChange occurrences are animated by the ParentAnimation.
+*/
+QDeclarativeItem *QDeclarative1ParentAnimation::target() const
+{
+ Q_D(const QDeclarative1ParentAnimation);
+ return d->target;
+}
+
+void QDeclarative1ParentAnimation::setTarget(QDeclarativeItem *target)
+{
+ Q_D(QDeclarative1ParentAnimation);
+ if (target == d->target)
+ return;
+
+ d->target = target;
+ emit targetChanged();
+}
+
+/*!
+ \qmlproperty Item ParentAnimation::newParent
+ The new parent to animate to.
+
+ If the ParentAnimation is defined within a \l Transition or \l Behavior,
+ this value defaults to the value defined in the end state of the
+ \l Transition, or the value of the property change that triggered the
+ \l Behavior.
+*/
+QDeclarativeItem *QDeclarative1ParentAnimation::newParent() const
+{
+ Q_D(const QDeclarative1ParentAnimation);
+ return d->newParent;
+}
+
+void QDeclarative1ParentAnimation::setNewParent(QDeclarativeItem *newParent)
+{
+ Q_D(QDeclarative1ParentAnimation);
+ if (newParent == d->newParent)
+ return;
+
+ d->newParent = newParent;
+ emit newParentChanged();
+}
+
+/*!
+ \qmlproperty Item ParentAnimation::via
+ The item to reparent via. This provides a way to do an unclipped animation
+ when both the old parent and new parent are clipped.
+
+ \qml
+ ParentAnimation {
+ target: myItem
+ via: topLevelItem
+ // ...
+ }
+ \endqml
+*/
+QDeclarativeItem *QDeclarative1ParentAnimation::via() const
+{
+ Q_D(const QDeclarative1ParentAnimation);
+ return d->via;
+}
+
+void QDeclarative1ParentAnimation::setVia(QDeclarativeItem *via)
+{
+ Q_D(QDeclarative1ParentAnimation);
+ if (via == d->via)
+ return;
+
+ d->via = via;
+ emit viaChanged();
+}
+
+//### mirrors same-named function in QDeclarativeItem
+QPointF QDeclarative1ParentAnimationPrivate::computeTransformOrigin(QDeclarativeItem::TransformOrigin origin, qreal width, qreal height) const
+{
+ switch(origin) {
+ default:
+ case QDeclarativeItem::TopLeft:
+ return QPointF(0, 0);
+ case QDeclarativeItem::Top:
+ return QPointF(width / 2., 0);
+ case QDeclarativeItem::TopRight:
+ return QPointF(width, 0);
+ case QDeclarativeItem::Left:
+ return QPointF(0, height / 2.);
+ case QDeclarativeItem::Center:
+ return QPointF(width / 2., height / 2.);
+ case QDeclarativeItem::Right:
+ return QPointF(width, height / 2.);
+ case QDeclarativeItem::BottomLeft:
+ return QPointF(0, height);
+ case QDeclarativeItem::Bottom:
+ return QPointF(width / 2., height);
+ case QDeclarativeItem::BottomRight:
+ return QPointF(width, height);
+ }
+}
+
+void QDeclarative1ParentAnimation::transition(QDeclarative1StateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction)
+{
+ Q_D(QDeclarative1ParentAnimation);
+
+ struct QDeclarative1ParentAnimationData : public QAbstractAnimationAction
+ {
+ QDeclarative1ParentAnimationData() {}
+ ~QDeclarative1ParentAnimationData() { qDeleteAll(pc); }
+
+ QDeclarative1StateActions actions;
+ //### reverse should probably apply on a per-action basis
+ bool reverse;
+ QList<QDeclarative1ParentChange *> pc;
+ virtual void doAction()
+ {
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ const QDeclarative1Action &action = actions.at(ii);
+ if (reverse)
+ action.event->reverse();
+ else
+ action.event->execute();
+ }
+ }
+ };
+
+ QDeclarative1ParentAnimationData *data = new QDeclarative1ParentAnimationData;
+ QDeclarative1ParentAnimationData *viaData = new QDeclarative1ParentAnimationData;
+
+ bool hasExplicit = false;
+ if (d->target && d->newParent) {
+ data->reverse = false;
+ QDeclarative1Action myAction;
+ QDeclarative1ParentChange *pc = new QDeclarative1ParentChange;
+ pc->setObject(d->target);
+ pc->setParent(d->newParent);
+ myAction.event = pc;
+ data->pc << pc;
+ data->actions << myAction;
+ hasExplicit = true;
+ if (d->via) {
+ viaData->reverse = false;
+ QDeclarative1Action myVAction;
+ QDeclarative1ParentChange *vpc = new QDeclarative1ParentChange;
+ vpc->setObject(d->target);
+ vpc->setParent(d->via);
+ myVAction.event = vpc;
+ viaData->pc << vpc;
+ viaData->actions << myVAction;
+ }
+ //### once actions have concept of modified,
+ // loop to match appropriate ParentChanges and mark as modified
+ }
+
+ if (!hasExplicit)
+ for (int i = 0; i < actions.size(); ++i) {
+ QDeclarative1Action &action = actions[i];
+ if (action.event && action.event->typeName() == QLatin1String("ParentChange")
+ && (!d->target || static_cast<QDeclarative1ParentChange*>(action.event)->object() == d->target)) {
+
+ QDeclarative1ParentChange *pc = static_cast<QDeclarative1ParentChange*>(action.event);
+ QDeclarative1Action myAction = action;
+ data->reverse = action.reverseEvent;
+
+ //### this logic differs from PropertyAnimation
+ // (probably a result of modified vs. done)
+ if (d->newParent) {
+ QDeclarative1ParentChange *epc = new QDeclarative1ParentChange;
+ epc->setObject(static_cast<QDeclarative1ParentChange*>(action.event)->object());
+ epc->setParent(d->newParent);
+ myAction.event = epc;
+ data->pc << epc;
+ data->actions << myAction;
+ pc = epc;
+ } else {
+ action.actionDone = true;
+ data->actions << myAction;
+ }
+
+ if (d->via) {
+ viaData->reverse = false;
+ QDeclarative1Action myAction;
+ QDeclarative1ParentChange *vpc = new QDeclarative1ParentChange;
+ vpc->setObject(pc->object());
+ vpc->setParent(d->via);
+ myAction.event = vpc;
+ viaData->pc << vpc;
+ viaData->actions << myAction;
+ QDeclarative1Action dummyAction;
+ QDeclarative1Action &xAction = pc->xIsSet() && i < actions.size()-1 ? actions[++i] : dummyAction;
+ QDeclarative1Action &yAction = pc->yIsSet() && i < actions.size()-1 ? actions[++i] : dummyAction;
+ QDeclarative1Action &sAction = pc->scaleIsSet() && i < actions.size()-1 ? actions[++i] : dummyAction;
+ QDeclarative1Action &rAction = pc->rotationIsSet() && i < actions.size()-1 ? actions[++i] : dummyAction;
+ QDeclarativeItem *target = pc->object();
+ QDeclarativeItem *targetParent = action.reverseEvent ? pc->originalParent() : pc->parent();
+
+ //### this mirrors the logic in QDeclarative1ParentChange.
+ bool ok;
+ const QTransform &transform = targetParent->itemTransform(d->via, &ok);
+ if (transform.type() >= QTransform::TxShear || !ok) {
+ qmlInfo(this) << QDeclarative1ParentAnimation::tr("Unable to preserve appearance under complex transform");
+ ok = false;
+ }
+
+ qreal scale = 1;
+ qreal rotation = 0;
+ bool isRotate = (transform.type() == QTransform::TxRotate) || (transform.m11() < 0);
+ if (ok && !isRotate) {
+ if (transform.m11() == transform.m22())
+ scale = transform.m11();
+ else {
+ qmlInfo(this) << QDeclarative1ParentAnimation::tr("Unable to preserve appearance under non-uniform scale");
+ ok = false;
+ }
+ } else if (ok && isRotate) {
+ if (transform.m11() == transform.m22())
+ scale = qSqrt(transform.m11()*transform.m11() + transform.m12()*transform.m12());
+ else {
+ qmlInfo(this) << QDeclarative1ParentAnimation::tr("Unable to preserve appearance under non-uniform scale");
+ ok = false;
+ }
+
+ if (scale != 0)
+ rotation = atan2(transform.m12()/scale, transform.m11()/scale) * 180/M_PI;
+ else {
+ qmlInfo(this) << QDeclarative1ParentAnimation::tr("Unable to preserve appearance under scale of 0");
+ ok = false;
+ }
+ }
+
+ const QPointF &point = transform.map(QPointF(xAction.toValue.toReal(),yAction.toValue.toReal()));
+ qreal x = point.x();
+ qreal y = point.y();
+ if (ok && target->transformOrigin() != QDeclarativeItem::TopLeft) {
+ qreal w = target->width();
+ qreal h = target->height();
+ if (pc->widthIsSet() && i < actions.size() - 1)
+ w = actions[++i].toValue.toReal();
+ if (pc->heightIsSet() && i < actions.size() - 1)
+ h = actions[++i].toValue.toReal();
+ const QPointF &transformOrigin
+ = d->computeTransformOrigin(target->transformOrigin(), w,h);
+ qreal tempxt = transformOrigin.x();
+ qreal tempyt = transformOrigin.y();
+ QTransform t;
+ t.translate(-tempxt, -tempyt);
+ t.rotate(rotation);
+ t.scale(scale, scale);
+ t.translate(tempxt, tempyt);
+ const QPointF &offset = t.map(QPointF(0,0));
+ x += offset.x();
+ y += offset.y();
+ }
+
+ if (ok) {
+ //qDebug() << x << y << rotation << scale;
+ xAction.toValue = x;
+ yAction.toValue = y;
+ sAction.toValue = sAction.toValue.toReal() * scale;
+ rAction.toValue = rAction.toValue.toReal() + rotation;
+ }
+ }
+ }
+ }
+
+ if (data->actions.count()) {
+ if (direction == QDeclarative1AbstractAnimation::Forward) {
+ d->startAction->setAnimAction(d->via ? viaData : data, QActionAnimation_1::DeleteWhenStopped);
+ d->endAction->setAnimAction(d->via ? data : 0, QActionAnimation_1::DeleteWhenStopped);
+ } else {
+ d->endAction->setAnimAction(d->via ? viaData : data, QActionAnimation_1::DeleteWhenStopped);
+ d->startAction->setAnimAction(d->via ? data : 0, QActionAnimation_1::DeleteWhenStopped);
+ }
+ if (!d->via)
+ delete viaData;
+ } else {
+ delete data;
+ delete viaData;
+ }
+
+ //take care of any child animations
+ bool valid = d->defaultProperty.isValid();
+ for (int ii = 0; ii < d->animations.count(); ++ii) {
+ if (valid)
+ d->animations.at(ii)->setDefaultTarget(d->defaultProperty);
+ d->animations.at(ii)->transition(actions, modified, direction);
+ }
+
+}
+
+QAbstractAnimation *QDeclarative1ParentAnimation::qtAnimation()
+{
+ Q_D(QDeclarative1ParentAnimation);
+ return d->topLevelGroup;
+}
+
+/*!
+ \qmlclass AnchorAnimation QDeclarative1AnchorAnimation
+ \ingroup qml-animation-transition
+ \since 4.7
+ \inherits Animation
+ \brief The AnchorAnimation element animates changes in anchor values.
+
+ AnchorAnimation is used to animate an anchor change.
+
+ In the following snippet we animate the addition of a right anchor to a \l Rectangle:
+
+ \snippet doc/src/snippets/declarative/anchoranimation.qml 0
+
+ For convenience, when an AnchorAnimation is used in a \l Transition, it will
+ animate any AnchorChanges that have occurred during the state change.
+ This can be overridden by setting a specific target item using the
+ \l target property.
+
+ Like any other animation element, an AnchorAnimation can be applied in a
+ number of ways, including transitions, behaviors and property value
+ sources. The \l {QML Animation and Transitions} documentation shows a
+ variety of methods for creating animations.
+
+ \sa {QML Animation and Transitions}, AnchorChanges
+*/
+
+QDeclarative1AnchorAnimation::QDeclarative1AnchorAnimation(QObject *parent)
+: QDeclarative1AbstractAnimation(*(new QDeclarative1AnchorAnimationPrivate), parent)
+{
+ Q_D(QDeclarative1AnchorAnimation);
+ d->va = new QDeclarative1BulkValueAnimator;
+ QDeclarative_setParent_noEvent(d->va, this);
+}
+
+QDeclarative1AnchorAnimation::~QDeclarative1AnchorAnimation()
+{
+}
+
+QAbstractAnimation *QDeclarative1AnchorAnimation::qtAnimation()
+{
+ Q_D(QDeclarative1AnchorAnimation);
+ return d->va;
+}
+
+/*!
+ \qmlproperty list<Item> AnchorAnimation::targets
+ The items to reanchor.
+
+ If no targets are specified all AnchorChanges will be
+ animated by the AnchorAnimation.
+*/
+QDeclarativeListProperty<QDeclarativeItem> QDeclarative1AnchorAnimation::targets()
+{
+ Q_D(QDeclarative1AnchorAnimation);
+ return QDeclarativeListProperty<QDeclarativeItem>(this, d->targets);
+}
+
+/*!
+ \qmlproperty int AnchorAnimation::duration
+ This property holds the duration of the animation, in milliseconds.
+
+ The default value is 250.
+*/
+int QDeclarative1AnchorAnimation::duration() const
+{
+ Q_D(const QDeclarative1AnchorAnimation);
+ return d->va->duration();
+}
+
+void QDeclarative1AnchorAnimation::setDuration(int duration)
+{
+ if (duration < 0) {
+ qmlInfo(this) << tr("Cannot set a duration of < 0");
+ return;
+ }
+
+ Q_D(QDeclarative1AnchorAnimation);
+ if (d->va->duration() == duration)
+ return;
+ d->va->setDuration(duration);
+ emit durationChanged(duration);
+}
+
+/*!
+ \qmlproperty enumeration AnchorAnimation::easing.type
+ \qmlproperty real AnchorAnimation::easing.amplitude
+ \qmlproperty real AnchorAnimation::easing.overshoot
+ \qmlproperty real AnchorAnimation::easing.period
+ \brief the easing curve used for the animation.
+
+ To specify an easing curve you need to specify at least the type. For some curves you can also specify
+ amplitude, period and/or overshoot. The default easing curve is
+ Linear.
+
+ \qml
+ AnchorAnimation { easing.type: Easing.InOutQuad }
+ \endqml
+
+ See the \l{PropertyAnimation::easing.type} documentation for information
+ about the different types of easing curves.
+*/
+
+QEasingCurve QDeclarative1AnchorAnimation::easing() const
+{
+ Q_D(const QDeclarative1AnchorAnimation);
+ return d->va->easingCurve();
+}
+
+void QDeclarative1AnchorAnimation::setEasing(const QEasingCurve &e)
+{
+ Q_D(QDeclarative1AnchorAnimation);
+ if (d->va->easingCurve() == e)
+ return;
+
+ d->va->setEasingCurve(e);
+ emit easingChanged(e);
+}
+
+void QDeclarative1AnchorAnimation::transition(QDeclarative1StateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction)
+{
+ Q_UNUSED(modified);
+ Q_D(QDeclarative1AnchorAnimation);
+ QDeclarative1AnimationPropertyUpdater *data = new QDeclarative1AnimationPropertyUpdater;
+ data->interpolatorType = QMetaType::QReal;
+ data->interpolator = d->interpolator;
+
+ data->reverse = direction == Backward ? true : false;
+ data->fromSourced = false;
+ data->fromDefined = false;
+
+ for (int ii = 0; ii < actions.count(); ++ii) {
+ QDeclarative1Action &action = actions[ii];
+ if (action.event && action.event->typeName() == QLatin1String("AnchorChanges")
+ && (d->targets.isEmpty() || d->targets.contains(static_cast<QDeclarative1AnchorChanges*>(action.event)->object()))) {
+ data->actions << static_cast<QDeclarative1AnchorChanges*>(action.event)->additionalActions();
+ }
+ }
+
+ if (data->actions.count()) {
+ if (!d->rangeIsSet) {
+ d->va->setStartValue(qreal(0));
+ d->va->setEndValue(qreal(1));
+ d->rangeIsSet = true;
+ }
+ d->va->setAnimValue(data, QAbstractAnimation::DeleteWhenStopped);
+ d->va->setFromSourcedValue(&data->fromSourced);
+ } else {
+ delete data;
+ }
+}
+
+QDeclarative1ScriptActionPrivate::QDeclarative1ScriptActionPrivate()
+ : QDeclarative1AbstractAnimationPrivate(), hasRunScriptScript(false), reversing(false), proxy(this), rsa(0) {}
+
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/util/qdeclarativeanimation_p.h b/src/qtquick1/util/qdeclarativeanimation_p.h
new file mode 100644
index 0000000000..decb9a339a
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativeanimation_p.h
@@ -0,0 +1,528 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEANIMATION_H
+#define QDECLARATIVEANIMATION_H
+
+#include "QtQuick1/private/qdeclarativetransition_p.h"
+#include "QtQuick1/private/qdeclarativestate_p.h"
+#include <QtGui/qvector3d.h>
+
+#include <QtDeclarative/qdeclarativepropertyvaluesource.h>
+#include <QtDeclarative/qdeclarative.h>
+#include <QtDeclarative/qdeclarativescriptstring.h>
+
+#include <QtCore/qvariant.h>
+#include <QtCore/qeasingcurve.h>
+#include <QtCore/QAbstractAnimation>
+#include <QtGui/qcolor.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeItem;
+class QDeclarative1AbstractAnimationPrivate;
+class QDeclarative1AnimationGroup;
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarative1AbstractAnimation : public QObject, public QDeclarativePropertyValueSource, public QDeclarativeParserStatus
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarative1AbstractAnimation)
+
+ Q_INTERFACES(QDeclarativeParserStatus)
+ Q_INTERFACES(QDeclarativePropertyValueSource)
+ Q_ENUMS(Loops)
+ Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged)
+ Q_PROPERTY(bool paused READ isPaused WRITE setPaused NOTIFY pausedChanged)
+ Q_PROPERTY(bool alwaysRunToEnd READ alwaysRunToEnd WRITE setAlwaysRunToEnd NOTIFY alwaysRunToEndChanged)
+ Q_PROPERTY(int loops READ loops WRITE setLoops NOTIFY loopCountChanged)
+ Q_CLASSINFO("DefaultMethod", "start()")
+
+public:
+ QDeclarative1AbstractAnimation(QObject *parent=0);
+ virtual ~QDeclarative1AbstractAnimation();
+
+ enum Loops { Infinite = -2 };
+
+ bool isRunning() const;
+ void setRunning(bool);
+ bool isPaused() const;
+ void setPaused(bool);
+ bool alwaysRunToEnd() const;
+ void setAlwaysRunToEnd(bool);
+
+ int loops() const;
+ void setLoops(int);
+
+ int currentTime();
+ void setCurrentTime(int);
+
+ QDeclarative1AnimationGroup *group() const;
+ void setGroup(QDeclarative1AnimationGroup *);
+
+ void setDefaultTarget(const QDeclarativeProperty &);
+ void setDisableUserControl();
+
+ void classBegin();
+ void componentComplete();
+
+Q_SIGNALS:
+ void started();
+ void completed();
+ void runningChanged(bool);
+ void pausedChanged(bool);
+ void alwaysRunToEndChanged(bool);
+ void loopCountChanged(int);
+
+public Q_SLOTS:
+ void restart();
+ void start();
+ void pause();
+ void resume();
+ void stop();
+ void complete();
+
+protected:
+ QDeclarative1AbstractAnimation(QDeclarative1AbstractAnimationPrivate &dd, QObject *parent);
+
+public:
+ enum TransitionDirection { Forward, Backward };
+ virtual void transition(QDeclarative1StateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation() = 0;
+
+private Q_SLOTS:
+ void timelineComplete();
+ void componentFinalized();
+private:
+ virtual void setTarget(const QDeclarativeProperty &);
+ void notifyRunningChanged(bool running);
+ friend class QDeclarative1Behavior;
+
+
+};
+
+class QDeclarative1PauseAnimationPrivate;
+class Q_AUTOTEST_EXPORT QDeclarative1PauseAnimation : public QDeclarative1AbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarative1PauseAnimation)
+
+ Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged)
+
+public:
+ QDeclarative1PauseAnimation(QObject *parent=0);
+ virtual ~QDeclarative1PauseAnimation();
+
+ int duration() const;
+ void setDuration(int);
+
+Q_SIGNALS:
+ void durationChanged(int);
+
+protected:
+ virtual QAbstractAnimation *qtAnimation();
+};
+
+class QDeclarative1ScriptActionPrivate;
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarative1ScriptAction : public QDeclarative1AbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarative1ScriptAction)
+
+ Q_PROPERTY(QDeclarativeScriptString script READ script WRITE setScript)
+ Q_PROPERTY(QString scriptName READ stateChangeScriptName WRITE setStateChangeScriptName)
+
+public:
+ QDeclarative1ScriptAction(QObject *parent=0);
+ virtual ~QDeclarative1ScriptAction();
+
+ QDeclarativeScriptString script() const;
+ void setScript(const QDeclarativeScriptString &);
+
+ QString stateChangeScriptName() const;
+ void setStateChangeScriptName(const QString &);
+
+protected:
+ virtual void transition(QDeclarative1StateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+};
+
+class QDeclarative1PropertyActionPrivate;
+class QDeclarative1PropertyAction : public QDeclarative1AbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarative1PropertyAction)
+
+ Q_PROPERTY(QObject *target READ target WRITE setTarget NOTIFY targetChanged)
+ Q_PROPERTY(QString property READ property WRITE setProperty NOTIFY propertyChanged)
+ Q_PROPERTY(QString properties READ properties WRITE setProperties NOTIFY propertiesChanged)
+ Q_PROPERTY(QDeclarativeListProperty<QObject> targets READ targets)
+ Q_PROPERTY(QDeclarativeListProperty<QObject> exclude READ exclude)
+ Q_PROPERTY(QVariant value READ value WRITE setValue NOTIFY valueChanged)
+
+public:
+ QDeclarative1PropertyAction(QObject *parent=0);
+ virtual ~QDeclarative1PropertyAction();
+
+ QObject *target() const;
+ void setTarget(QObject *);
+
+ QString property() const;
+ void setProperty(const QString &);
+
+ QString properties() const;
+ void setProperties(const QString &);
+
+ QDeclarativeListProperty<QObject> targets();
+ QDeclarativeListProperty<QObject> exclude();
+
+ QVariant value() const;
+ void setValue(const QVariant &);
+
+Q_SIGNALS:
+ void valueChanged(const QVariant &);
+ void propertiesChanged(const QString &);
+ void targetChanged();
+ void propertyChanged();
+
+protected:
+ virtual void transition(QDeclarative1StateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+};
+
+class QDeclarative1PropertyAnimationPrivate;
+class Q_AUTOTEST_EXPORT QDeclarative1PropertyAnimation : public QDeclarative1AbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarative1PropertyAnimation)
+
+ Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged)
+ Q_PROPERTY(QVariant from READ from WRITE setFrom NOTIFY fromChanged)
+ Q_PROPERTY(QVariant to READ to WRITE setTo NOTIFY toChanged)
+ Q_PROPERTY(QEasingCurve easing READ easing WRITE setEasing NOTIFY easingChanged)
+ Q_PROPERTY(QObject *target READ target WRITE setTarget NOTIFY targetChanged)
+ Q_PROPERTY(QString property READ property WRITE setProperty NOTIFY propertyChanged)
+ Q_PROPERTY(QString properties READ properties WRITE setProperties NOTIFY propertiesChanged)
+ Q_PROPERTY(QDeclarativeListProperty<QObject> targets READ targets)
+ Q_PROPERTY(QDeclarativeListProperty<QObject> exclude READ exclude)
+
+public:
+ QDeclarative1PropertyAnimation(QObject *parent=0);
+ virtual ~QDeclarative1PropertyAnimation();
+
+ virtual int duration() const;
+ virtual void setDuration(int);
+
+ QVariant from() const;
+ void setFrom(const QVariant &);
+
+ QVariant to() const;
+ void setTo(const QVariant &);
+
+ QEasingCurve easing() const;
+ void setEasing(const QEasingCurve &);
+
+ QObject *target() const;
+ void setTarget(QObject *);
+
+ QString property() const;
+ void setProperty(const QString &);
+
+ QString properties() const;
+ void setProperties(const QString &);
+
+ QDeclarativeListProperty<QObject> targets();
+ QDeclarativeListProperty<QObject> exclude();
+
+protected:
+ QDeclarative1PropertyAnimation(QDeclarative1PropertyAnimationPrivate &dd, QObject *parent);
+ virtual void transition(QDeclarative1StateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+
+Q_SIGNALS:
+ void durationChanged(int);
+ void fromChanged(QVariant);
+ void toChanged(QVariant);
+ void easingChanged(const QEasingCurve &);
+ void propertiesChanged(const QString &);
+ void targetChanged();
+ void propertyChanged();
+};
+
+class Q_AUTOTEST_EXPORT QDeclarative1ColorAnimation : public QDeclarative1PropertyAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarative1PropertyAnimation)
+ Q_PROPERTY(QColor from READ from WRITE setFrom)
+ Q_PROPERTY(QColor to READ to WRITE setTo)
+
+public:
+ QDeclarative1ColorAnimation(QObject *parent=0);
+ virtual ~QDeclarative1ColorAnimation();
+
+ QColor from() const;
+ void setFrom(const QColor &);
+
+ QColor to() const;
+ void setTo(const QColor &);
+};
+
+class Q_AUTOTEST_EXPORT QDeclarative1NumberAnimation : public QDeclarative1PropertyAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarative1PropertyAnimation)
+
+ Q_PROPERTY(qreal from READ from WRITE setFrom)
+ Q_PROPERTY(qreal to READ to WRITE setTo)
+
+public:
+ QDeclarative1NumberAnimation(QObject *parent=0);
+ virtual ~QDeclarative1NumberAnimation();
+
+ qreal from() const;
+ void setFrom(qreal);
+
+ qreal to() const;
+ void setTo(qreal);
+
+protected:
+ QDeclarative1NumberAnimation(QDeclarative1PropertyAnimationPrivate &dd, QObject *parent);
+
+private:
+ void init();
+};
+
+class Q_AUTOTEST_EXPORT QDeclarative1Vector3dAnimation : public QDeclarative1PropertyAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarative1PropertyAnimation)
+
+ Q_PROPERTY(QVector3D from READ from WRITE setFrom)
+ Q_PROPERTY(QVector3D to READ to WRITE setTo)
+
+public:
+ QDeclarative1Vector3dAnimation(QObject *parent=0);
+ virtual ~QDeclarative1Vector3dAnimation();
+
+ QVector3D from() const;
+ void setFrom(QVector3D);
+
+ QVector3D to() const;
+ void setTo(QVector3D);
+};
+
+class QDeclarative1RotationAnimationPrivate;
+class Q_AUTOTEST_EXPORT QDeclarative1RotationAnimation : public QDeclarative1PropertyAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarative1RotationAnimation)
+ Q_ENUMS(RotationDirection)
+
+ Q_PROPERTY(qreal from READ from WRITE setFrom)
+ Q_PROPERTY(qreal to READ to WRITE setTo)
+ Q_PROPERTY(RotationDirection direction READ direction WRITE setDirection NOTIFY directionChanged)
+
+public:
+ QDeclarative1RotationAnimation(QObject *parent=0);
+ virtual ~QDeclarative1RotationAnimation();
+
+ qreal from() const;
+ void setFrom(qreal);
+
+ qreal to() const;
+ void setTo(qreal);
+
+ enum RotationDirection { Numerical, Shortest, Clockwise, Counterclockwise };
+ RotationDirection direction() const;
+ void setDirection(RotationDirection direction);
+
+Q_SIGNALS:
+ void directionChanged();
+};
+
+class QDeclarative1AnimationGroupPrivate;
+class Q_AUTOTEST_EXPORT QDeclarative1AnimationGroup : public QDeclarative1AbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarative1AnimationGroup)
+
+ Q_CLASSINFO("DefaultProperty", "animations")
+ Q_PROPERTY(QDeclarativeListProperty<QDeclarative1AbstractAnimation> animations READ animations)
+
+public:
+ QDeclarative1AnimationGroup(QObject *parent);
+ virtual ~QDeclarative1AnimationGroup();
+
+ QDeclarativeListProperty<QDeclarative1AbstractAnimation> animations();
+ friend class QDeclarative1AbstractAnimation;
+
+protected:
+ QDeclarative1AnimationGroup(QDeclarative1AnimationGroupPrivate &dd, QObject *parent);
+};
+
+class QDeclarative1SequentialAnimation : public QDeclarative1AnimationGroup
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarative1AnimationGroup)
+
+public:
+ QDeclarative1SequentialAnimation(QObject *parent=0);
+ virtual ~QDeclarative1SequentialAnimation();
+
+protected:
+ virtual void transition(QDeclarative1StateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+};
+
+class QDeclarative1ParallelAnimation : public QDeclarative1AnimationGroup
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarative1AnimationGroup)
+
+public:
+ QDeclarative1ParallelAnimation(QObject *parent=0);
+ virtual ~QDeclarative1ParallelAnimation();
+
+protected:
+ virtual void transition(QDeclarative1StateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+};
+
+class QDeclarative1ParentAnimationPrivate;
+class QDeclarative1ParentAnimation : public QDeclarative1AnimationGroup
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarative1ParentAnimation)
+
+ Q_PROPERTY(QDeclarativeItem *target READ target WRITE setTarget NOTIFY targetChanged)
+ Q_PROPERTY(QDeclarativeItem *newParent READ newParent WRITE setNewParent NOTIFY newParentChanged)
+ Q_PROPERTY(QDeclarativeItem *via READ via WRITE setVia NOTIFY viaChanged)
+
+public:
+ QDeclarative1ParentAnimation(QObject *parent=0);
+ virtual ~QDeclarative1ParentAnimation();
+
+ QDeclarativeItem *target() const;
+ void setTarget(QDeclarativeItem *);
+
+ QDeclarativeItem *newParent() const;
+ void setNewParent(QDeclarativeItem *);
+
+ QDeclarativeItem *via() const;
+ void setVia(QDeclarativeItem *);
+
+Q_SIGNALS:
+ void targetChanged();
+ void newParentChanged();
+ void viaChanged();
+
+protected:
+ virtual void transition(QDeclarative1StateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+};
+
+class QDeclarative1AnchorAnimationPrivate;
+class QDeclarative1AnchorAnimation : public QDeclarative1AbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarative1AnchorAnimation)
+ Q_PROPERTY(QDeclarativeListProperty<QDeclarativeItem> targets READ targets)
+ Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged)
+ Q_PROPERTY(QEasingCurve easing READ easing WRITE setEasing NOTIFY easingChanged)
+
+public:
+ QDeclarative1AnchorAnimation(QObject *parent=0);
+ virtual ~QDeclarative1AnchorAnimation();
+
+ QDeclarativeListProperty<QDeclarativeItem> targets();
+
+ int duration() const;
+ void setDuration(int);
+
+ QEasingCurve easing() const;
+ void setEasing(const QEasingCurve &);
+
+Q_SIGNALS:
+ void durationChanged(int);
+ void easingChanged(const QEasingCurve&);
+
+protected:
+ virtual void transition(QDeclarative1StateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1AbstractAnimation)
+QML_DECLARE_TYPE(QDeclarative1PauseAnimation)
+QML_DECLARE_TYPE(QDeclarative1ScriptAction)
+QML_DECLARE_TYPE(QDeclarative1PropertyAction)
+QML_DECLARE_TYPE(QDeclarative1PropertyAnimation)
+QML_DECLARE_TYPE(QDeclarative1ColorAnimation)
+QML_DECLARE_TYPE(QDeclarative1NumberAnimation)
+QML_DECLARE_TYPE(QDeclarative1SequentialAnimation)
+QML_DECLARE_TYPE(QDeclarative1ParallelAnimation)
+QML_DECLARE_TYPE(QDeclarative1Vector3dAnimation)
+QML_DECLARE_TYPE(QDeclarative1RotationAnimation)
+QML_DECLARE_TYPE(QDeclarative1ParentAnimation)
+QML_DECLARE_TYPE(QDeclarative1AnchorAnimation)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEANIMATION_H
diff --git a/src/qtquick1/util/qdeclarativeanimation_p_p.h b/src/qtquick1/util/qdeclarativeanimation_p_p.h
new file mode 100644
index 0000000000..e528a927ef
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativeanimation_p_p.h
@@ -0,0 +1,397 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEANIMATION_P_H
+#define QDECLARATIVEANIMATION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtQuick1/private/qdeclarativeanimation_p.h"
+
+#include "QtDeclarative/private/qdeclarativenullablevalue_p_p.h"
+#include "QtQuick1/private/qdeclarativetimeline_p_p.h"
+
+#include <QtDeclarative/qdeclarative.h>
+#include <QtQuick1/qdeclarativeitem.h>
+#include <QtDeclarative/qdeclarativecontext.h>
+
+#include <QtCore/QPauseAnimation>
+#include <QtCore/QVariantAnimation>
+#include <QtCore/QAnimationGroup>
+#include <QtGui/QColor>
+#include <QDebug>
+
+#include <private/qobject_p.h>
+#include <private/qvariantanimation_p.h>
+
+QT_BEGIN_NAMESPACE
+
+//interface for classes that provide animation actions for QActionAnimation_1
+class QAbstractAnimationAction
+{
+public:
+ virtual ~QAbstractAnimationAction() {}
+ virtual void doAction() = 0;
+};
+
+//templated animation action
+//allows us to specify an action that calls a function of a class.
+//(so that class doesn't have to inherit QDeclarative1AbstractAnimationAction)
+template<class T, void (T::*method)()>
+class QAnimationActionProxy_1 : public QAbstractAnimationAction
+{
+public:
+ QAnimationActionProxy_1(T *p) : m_p(p) {}
+ virtual void doAction() { (m_p->*method)(); }
+
+private:
+ T *m_p;
+};
+
+//performs an action of type QAbstractAnimationAction
+class Q_AUTOTEST_EXPORT QActionAnimation_1 : public QAbstractAnimation
+{
+ Q_OBJECT
+public:
+ QActionAnimation_1(QObject *parent = 0) : QAbstractAnimation(parent), animAction(0), policy(KeepWhenStopped) {}
+ QActionAnimation_1(QAbstractAnimationAction *action, QObject *parent = 0)
+ : QAbstractAnimation(parent), animAction(action), policy(KeepWhenStopped) {}
+ ~QActionAnimation_1() { if (policy == DeleteWhenStopped) { delete animAction; animAction = 0; } }
+ virtual int duration() const { return 0; }
+ void setAnimAction(QAbstractAnimationAction *action, DeletionPolicy p)
+ {
+ if (state() == Running)
+ stop();
+ if (policy == DeleteWhenStopped)
+ delete animAction;
+ animAction = action;
+ policy = p;
+ }
+protected:
+ virtual void updateCurrentTime(int) {}
+
+ virtual void updateState(State newState, State /*oldState*/)
+ {
+ if (newState == Running) {
+ if (animAction) {
+ animAction->doAction();
+ if (state() == Stopped && policy == DeleteWhenStopped) {
+ delete animAction;
+ animAction = 0;
+ }
+ }
+ }
+ }
+
+private:
+ QAbstractAnimationAction *animAction;
+ DeletionPolicy policy;
+};
+
+class QDeclarative1BulkValueUpdater
+{
+public:
+ virtual ~QDeclarative1BulkValueUpdater() {}
+ virtual void setValue(qreal value) = 0;
+};
+
+//animates QDeclarative1BulkValueUpdater (assumes start and end values will be reals or compatible)
+class Q_AUTOTEST_EXPORT QDeclarative1BulkValueAnimator : public QVariantAnimation
+{
+ Q_OBJECT
+public:
+ QDeclarative1BulkValueAnimator(QObject *parent = 0) : QVariantAnimation(parent), animValue(0), fromSourced(0), policy(KeepWhenStopped) {}
+ ~QDeclarative1BulkValueAnimator() { if (policy == DeleteWhenStopped) { delete animValue; animValue = 0; } }
+ void setAnimValue(QDeclarative1BulkValueUpdater *value, DeletionPolicy p)
+ {
+ if (state() == Running)
+ stop();
+ if (policy == DeleteWhenStopped)
+ delete animValue;
+ animValue = value;
+ policy = p;
+ }
+ void setFromSourcedValue(bool *value)
+ {
+ fromSourced = value;
+ }
+protected:
+ virtual void updateCurrentValue(const QVariant &value)
+ {
+ if (state() == QAbstractAnimation::Stopped)
+ return;
+
+ if (animValue)
+ animValue->setValue(value.toReal());
+ }
+ virtual void updateState(State newState, State oldState)
+ {
+ QVariantAnimation::updateState(newState, oldState);
+ if (newState == Running) {
+ //check for new from every loop
+ if (fromSourced)
+ *fromSourced = false;
+ }
+ }
+
+private:
+ QDeclarative1BulkValueUpdater *animValue;
+ bool *fromSourced;
+ DeletionPolicy policy;
+};
+
+//an animation that just gives a tick
+template<class T, void (T::*method)(int)>
+class QTickAnimationProxy_1 : public QAbstractAnimation
+{
+ //Q_OBJECT //doesn't work with templating
+public:
+ QTickAnimationProxy_1(T *p, QObject *parent = 0) : QAbstractAnimation(parent), m_p(p) {}
+ virtual int duration() const { return -1; }
+protected:
+ virtual void updateCurrentTime(int msec) { (m_p->*method)(msec); }
+
+private:
+ T *m_p;
+};
+
+class QDeclarative1AbstractAnimationPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1AbstractAnimation)
+public:
+ QDeclarative1AbstractAnimationPrivate()
+ : running(false), paused(false), alwaysRunToEnd(false),
+ connectedTimeLine(false), componentComplete(true),
+ avoidPropertyValueSourceStart(false), disableUserControl(false),
+ registered(false), loopCount(1), group(0) {}
+
+ bool running:1;
+ bool paused:1;
+ bool alwaysRunToEnd:1;
+ bool connectedTimeLine:1;
+ bool componentComplete:1;
+ bool avoidPropertyValueSourceStart:1;
+ bool disableUserControl:1;
+ bool registered:1;
+
+ int loopCount;
+
+ void commence();
+
+ QDeclarativeProperty defaultProperty;
+
+ QDeclarative1AnimationGroup *group;
+
+ static QDeclarativeProperty createProperty(QObject *obj, const QString &str, QObject *infoObj);
+};
+
+class QDeclarative1PauseAnimationPrivate : public QDeclarative1AbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1PauseAnimation)
+public:
+ QDeclarative1PauseAnimationPrivate()
+ : QDeclarative1AbstractAnimationPrivate(), pa(0) {}
+
+ void init();
+
+ QPauseAnimation *pa;
+};
+
+class QDeclarative1ScriptActionPrivate : public QDeclarative1AbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1ScriptAction)
+public:
+ QDeclarative1ScriptActionPrivate();
+
+ void init();
+
+ QDeclarativeScriptString script;
+ QString name;
+ QDeclarativeScriptString runScriptScript;
+ bool hasRunScriptScript;
+ bool reversing;
+
+ void execute();
+
+ QAnimationActionProxy_1<QDeclarative1ScriptActionPrivate,
+ &QDeclarative1ScriptActionPrivate::execute> proxy;
+ QActionAnimation_1 *rsa;
+};
+
+class QDeclarative1PropertyActionPrivate : public QDeclarative1AbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1PropertyAction)
+public:
+ QDeclarative1PropertyActionPrivate()
+ : QDeclarative1AbstractAnimationPrivate(), target(0), spa(0) {}
+
+ void init();
+
+ QObject *target;
+ QString propertyName;
+ QString properties;
+ QList<QObject *> targets;
+ QList<QObject *> exclude;
+
+ QDeclarativeNullableValue<QVariant> value;
+
+ QActionAnimation_1 *spa;
+};
+
+class QDeclarative1AnimationGroupPrivate : public QDeclarative1AbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1AnimationGroup)
+public:
+ QDeclarative1AnimationGroupPrivate()
+ : QDeclarative1AbstractAnimationPrivate(), ag(0) {}
+
+ static void append_animation(QDeclarativeListProperty<QDeclarative1AbstractAnimation> *list, QDeclarative1AbstractAnimation *role);
+ static void clear_animation(QDeclarativeListProperty<QDeclarative1AbstractAnimation> *list);
+ QList<QDeclarative1AbstractAnimation *> animations;
+ QAnimationGroup *ag;
+};
+
+class QDeclarative1PropertyAnimationPrivate : public QDeclarative1AbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1PropertyAnimation)
+public:
+ QDeclarative1PropertyAnimationPrivate()
+ : QDeclarative1AbstractAnimationPrivate(), target(0), fromSourced(false), fromIsDefined(false), toIsDefined(false),
+ rangeIsSet(false), defaultToInterpolatorType(0), interpolatorType(0), interpolator(0), va(0), actions(0) {}
+
+ void init();
+
+ QVariant from;
+ QVariant to;
+
+ QObject *target;
+ QString propertyName;
+ QString properties;
+ QList<QObject *> targets;
+ QList<QObject *> exclude;
+ QString defaultProperties;
+
+ bool fromSourced;
+ bool fromIsDefined:1;
+ bool toIsDefined:1;
+ bool rangeIsSet:1;
+ bool defaultToInterpolatorType:1;
+ int interpolatorType;
+ QVariantAnimation::Interpolator interpolator;
+
+ QDeclarative1BulkValueAnimator *va;
+
+ // for animations that don't use the QDeclarative1BulkValueAnimator
+ QDeclarative1StateActions *actions;
+
+ static QVariant interpolateVariant(const QVariant &from, const QVariant &to, qreal progress);
+ static void convertVariant(QVariant &variant, int type);
+};
+
+class QDeclarative1RotationAnimationPrivate : public QDeclarative1PropertyAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1RotationAnimation)
+public:
+ QDeclarative1RotationAnimationPrivate() : direction(QDeclarative1RotationAnimation::Numerical) {}
+
+ QDeclarative1RotationAnimation::RotationDirection direction;
+};
+
+class QDeclarative1ParentAnimationPrivate : public QDeclarative1AnimationGroupPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1ParentAnimation)
+public:
+ QDeclarative1ParentAnimationPrivate()
+ : QDeclarative1AnimationGroupPrivate(), target(0), newParent(0),
+ via(0), topLevelGroup(0), startAction(0), endAction(0) {}
+
+ QDeclarativeItem *target;
+ QDeclarativeItem *newParent;
+ QDeclarativeItem *via;
+
+ QSequentialAnimationGroup *topLevelGroup;
+ QActionAnimation_1 *startAction;
+ QActionAnimation_1 *endAction;
+
+ QPointF computeTransformOrigin(QDeclarativeItem::TransformOrigin origin, qreal width, qreal height) const;
+};
+
+class QDeclarative1AnchorAnimationPrivate : public QDeclarative1AbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1AnchorAnimation)
+public:
+ QDeclarative1AnchorAnimationPrivate() : rangeIsSet(false), va(0),
+ interpolator(QVariantAnimationPrivate::getInterpolator(QMetaType::QReal)) {}
+
+ bool rangeIsSet;
+ QDeclarative1BulkValueAnimator *va;
+ QVariantAnimation::Interpolator interpolator;
+ QList<QDeclarativeItem*> targets;
+};
+
+class Q_AUTOTEST_EXPORT QDeclarative1AnimationPropertyUpdater : public QDeclarative1BulkValueUpdater
+{
+public:
+ QDeclarative1StateActions actions;
+ int interpolatorType; //for Number/ColorAnimation
+ int prevInterpolatorType; //for generic
+ QVariantAnimation::Interpolator interpolator;
+ bool reverse;
+ bool fromSourced;
+ bool fromDefined;
+ bool *wasDeleted;
+ QDeclarative1AnimationPropertyUpdater() : prevInterpolatorType(0), wasDeleted(0) {}
+ ~QDeclarative1AnimationPropertyUpdater() { if (wasDeleted) *wasDeleted = true; }
+ void setValue(qreal v);
+};
+
+QT_END_NAMESPACE
+
+#endif // QDECLARATIVEANIMATION_P_H
diff --git a/src/qtquick1/util/qdeclarativeapplication.cpp b/src/qtquick1/util/qdeclarativeapplication.cpp
new file mode 100644
index 0000000000..3cc572f27b
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativeapplication.cpp
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativeapplication_p.h"
+#include <private/qobject_p.h>
+#include <QtGui/QApplication>
+
+QT_BEGIN_NAMESPACE
+
+
+
+class QDeclarative1ApplicationPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1Application)
+public:
+ QDeclarative1ApplicationPrivate() : active(QApplication::activeWindow() != 0),
+ layoutDirection(QApplication::layoutDirection()) {}
+ bool active;
+ Qt::LayoutDirection layoutDirection;
+};
+
+/*
+ This object and its properties are documented as part of the Qt object,
+ in qdeclarativengine.cpp
+*/
+
+QDeclarative1Application::QDeclarative1Application(QObject *parent) : QObject(*new QDeclarative1ApplicationPrivate(), parent)
+{
+ if (qApp)
+ qApp->installEventFilter(this);
+}
+
+QDeclarative1Application::~QDeclarative1Application()
+{
+}
+
+bool QDeclarative1Application::active() const
+{
+ Q_D(const QDeclarative1Application);
+ return d->active;
+}
+
+Qt::LayoutDirection QDeclarative1Application::layoutDirection() const
+{
+ Q_D(const QDeclarative1Application);
+ return d->layoutDirection;
+}
+
+bool QDeclarative1Application::eventFilter(QObject *obj, QEvent *event)
+{
+ Q_UNUSED(obj)
+ Q_D(QDeclarative1Application);
+ if (event->type() == QEvent::ApplicationActivate
+ || event->type() == QEvent::ApplicationDeactivate) {
+ bool active = d->active;
+ if (event->type() == QEvent::ApplicationActivate)
+ active = true;
+ else if (event->type() == QEvent::ApplicationDeactivate)
+ active = false;
+
+ if (d->active != active) {
+ d->active = active;
+ emit activeChanged();
+ }
+ }
+ if (event->type() == QEvent::LayoutDirectionChange) {
+ Qt::LayoutDirection direction = QApplication::layoutDirection();
+ if (d->layoutDirection != direction) {
+ d->layoutDirection = direction;
+ emit layoutDirectionChanged();
+ }
+ }
+ return false;
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/util/qdeclarativeapplication_p.h b/src/qtquick1/util/qdeclarativeapplication_p.h
new file mode 100644
index 0000000000..4a588c2940
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativeapplication_p.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEAPPLICATION_P_H
+#define QDECLARATIVEAPPLICATION_P_H
+
+#include <QtCore/QObject>
+#include <QtDeclarative/qdeclarative.h>
+#include <QtDeclarative/private/qdeclarativeglobal_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarative1ApplicationPrivate;
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarative1Application : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(bool active READ active NOTIFY activeChanged)
+ Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection NOTIFY layoutDirectionChanged)
+
+public:
+ explicit QDeclarative1Application(QObject *parent = 0);
+ virtual ~QDeclarative1Application();
+ bool active() const;
+ Qt::LayoutDirection layoutDirection() const;
+
+protected:
+ bool eventFilter(QObject *obj, QEvent *event);
+
+Q_SIGNALS:
+ void activeChanged();
+ void layoutDirectionChanged();
+
+private:
+ Q_DISABLE_COPY(QDeclarative1Application)
+ Q_DECLARE_PRIVATE(QDeclarative1Application)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1Application)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEAPPLICATION_P_H
diff --git a/src/qtquick1/util/qdeclarativebehavior.cpp b/src/qtquick1/util/qdeclarativebehavior.cpp
new file mode 100644
index 0000000000..203f141721
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativebehavior.cpp
@@ -0,0 +1,234 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativebehavior_p.h"
+
+#include "QtQuick1/private/qdeclarativeanimation_p.h"
+#include "QtQuick1/private/qdeclarativetransition_p.h"
+
+#include <QtDeclarative/qdeclarativecontext.h>
+#include <QtDeclarative/qdeclarativeinfo.h>
+#include <QtDeclarative/private/qdeclarativeproperty_p.h>
+#include <QtDeclarative/private/qdeclarativeguard_p.h>
+#include <QtDeclarative/private/qdeclarativeengine_p.h>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+
+
+class QDeclarative1BehaviorPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1Behavior)
+public:
+ QDeclarative1BehaviorPrivate() : animation(0), enabled(true), finalized(false)
+ , blockRunningChanged(false) {}
+
+ QDeclarativeProperty property;
+ QVariant currentValue;
+ QVariant targetValue;
+ QDeclarativeGuard<QDeclarative1AbstractAnimation> animation;
+ bool enabled;
+ bool finalized;
+ bool blockRunningChanged;
+};
+
+/*!
+ \qmlclass Behavior QDeclarative1Behavior
+ \ingroup qml-animation-transition
+ \since 4.7
+ \brief The Behavior element allows you to specify a default animation for a property change.
+
+ A Behavior defines the default animation to be applied whenever a
+ particular property value changes.
+
+ For example, the following Behavior defines a NumberAnimation to be run
+ whenever the \l Rectangle's \c width value changes. When the MouseArea
+ is clicked, the \c width is changed, triggering the behavior's animation:
+
+ \snippet doc/src/snippets/declarative/behavior.qml 0
+
+ Note that a property cannot have more than one assigned Behavior. To provide
+ multiple animations within a Behavior, use ParallelAnimation or
+ SequentialAnimation.
+
+ If a \l{QML States}{state change} has a \l Transition that matches the same property as a
+ Behavior, the \l Transition animation overrides the Behavior for that
+ state change. For general advice on using Behaviors to animate state changes, see
+ \l{Using QML Behaviors with States}.
+
+ \sa {QML Animation and Transitions}, {declarative/animation/behaviors}{Behavior example}, QtDeclarative
+*/
+
+
+QDeclarative1Behavior::QDeclarative1Behavior(QObject *parent)
+ : QObject(*(new QDeclarative1BehaviorPrivate), parent)
+{
+}
+
+QDeclarative1Behavior::~QDeclarative1Behavior()
+{
+}
+
+/*!
+ \qmlproperty Animation Behavior::animation
+ \default
+
+ This property holds the animation to run when the behavior is triggered.
+*/
+
+QDeclarative1AbstractAnimation *QDeclarative1Behavior::animation()
+{
+ Q_D(QDeclarative1Behavior);
+ return d->animation;
+}
+
+void QDeclarative1Behavior::setAnimation(QDeclarative1AbstractAnimation *animation)
+{
+ Q_D(QDeclarative1Behavior);
+ if (d->animation) {
+ qmlInfo(this) << tr("Cannot change the animation assigned to a Behavior.");
+ return;
+ }
+
+ d->animation = animation;
+ if (d->animation) {
+ d->animation->setDefaultTarget(d->property);
+ d->animation->setDisableUserControl();
+ connect(d->animation->qtAnimation(),
+ SIGNAL(stateChanged(QAbstractAnimation::State,QAbstractAnimation::State)),
+ this,
+ SLOT(qtAnimationStateChanged(QAbstractAnimation::State,QAbstractAnimation::State)));
+ }
+}
+
+
+void QDeclarative1Behavior::qtAnimationStateChanged(QAbstractAnimation::State newState,QAbstractAnimation::State)
+{
+ Q_D(QDeclarative1Behavior);
+ if (!d->blockRunningChanged)
+ d->animation->notifyRunningChanged(newState == QAbstractAnimation::Running);
+}
+
+
+/*!
+ \qmlproperty bool Behavior::enabled
+
+ This property holds whether the behavior will be triggered when the tracked
+ property changes value.
+
+ By default a Behavior is enabled.
+*/
+
+bool QDeclarative1Behavior::enabled() const
+{
+ Q_D(const QDeclarative1Behavior);
+ return d->enabled;
+}
+
+void QDeclarative1Behavior::setEnabled(bool enabled)
+{
+ Q_D(QDeclarative1Behavior);
+ if (d->enabled == enabled)
+ return;
+ d->enabled = enabled;
+ emit enabledChanged();
+}
+
+void QDeclarative1Behavior::write(const QVariant &value)
+{
+ Q_D(QDeclarative1Behavior);
+ qmlExecuteDeferred(this);
+ if (!d->animation || !d->enabled || !d->finalized) {
+ QDeclarativePropertyPrivate::write(d->property, value, QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::DontRemoveBinding);
+ d->targetValue = value;
+ return;
+ }
+
+ if (d->animation->isRunning() && value == d->targetValue)
+ return;
+
+ d->currentValue = d->property.read();
+ d->targetValue = value;
+
+ if (d->animation->qtAnimation()->duration() != -1
+ && d->animation->qtAnimation()->state() != QAbstractAnimation::Stopped) {
+ d->blockRunningChanged = true;
+ d->animation->qtAnimation()->stop();
+ }
+
+ QDeclarative1StateOperation::ActionList actions;
+ QDeclarative1Action action;
+ action.property = d->property;
+ action.fromValue = d->currentValue;
+ action.toValue = value;
+ actions << action;
+
+ QList<QDeclarativeProperty> after;
+ d->animation->transition(actions, after, QDeclarative1AbstractAnimation::Forward);
+ d->animation->qtAnimation()->start();
+ d->blockRunningChanged = false;
+ if (!after.contains(d->property))
+ QDeclarativePropertyPrivate::write(d->property, value, QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::DontRemoveBinding);
+}
+
+void QDeclarative1Behavior::setTarget(const QDeclarativeProperty &property)
+{
+ Q_D(QDeclarative1Behavior);
+ d->property = property;
+ d->currentValue = property.read();
+ if (d->animation)
+ d->animation->setDefaultTarget(property);
+
+ QDeclarativeEnginePrivate *engPriv = QDeclarativeEnginePrivate::get(qmlEngine(this));
+ engPriv->registerFinalizedParserStatusObject(this, this->metaObject()->indexOfSlot("componentFinalized()"));
+}
+
+void QDeclarative1Behavior::componentFinalized()
+{
+ Q_D(QDeclarative1Behavior);
+ d->finalized = true;
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/util/qdeclarativebehavior_p.h b/src/qtquick1/util/qdeclarativebehavior_p.h
new file mode 100644
index 0000000000..76792bc438
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativebehavior_p.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEBEHAVIOR_H
+#define QDECLARATIVEBEHAVIOR_H
+
+#include "QtQuick1/private/qdeclarativestate_p.h"
+
+#include <QtDeclarative/qdeclarativepropertyvaluesource.h>
+#include <QtDeclarative/qdeclarativepropertyvalueinterceptor.h>
+#include <QtDeclarative/qdeclarative.h>
+#include <QtCore/QAbstractAnimation>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarative1AbstractAnimation;
+class QDeclarative1BehaviorPrivate;
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarative1Behavior : public QObject, public QDeclarativePropertyValueInterceptor
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarative1Behavior)
+
+ Q_INTERFACES(QDeclarativePropertyValueInterceptor)
+ Q_CLASSINFO("DefaultProperty", "animation")
+ Q_PROPERTY(QDeclarative1AbstractAnimation *animation READ animation WRITE setAnimation)
+ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
+ Q_CLASSINFO("DeferredPropertyNames", "animation")
+
+public:
+ QDeclarative1Behavior(QObject *parent=0);
+ ~QDeclarative1Behavior();
+
+ virtual void setTarget(const QDeclarativeProperty &);
+ virtual void write(const QVariant &value);
+
+ QDeclarative1AbstractAnimation *animation();
+ void setAnimation(QDeclarative1AbstractAnimation *);
+
+ bool enabled() const;
+ void setEnabled(bool enabled);
+
+Q_SIGNALS:
+ void enabledChanged();
+
+private Q_SLOTS:
+ void componentFinalized();
+ void qtAnimationStateChanged(QAbstractAnimation::State,QAbstractAnimation::State);
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1Behavior)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEBEHAVIOR_H
diff --git a/src/qtquick1/util/qdeclarativebind.cpp b/src/qtquick1/util/qdeclarativebind.cpp
new file mode 100644
index 0000000000..bf0802b1d1
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativebind.cpp
@@ -0,0 +1,217 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativebind_p.h"
+
+#include "QtDeclarative/private/qdeclarativenullablevalue_p_p.h"
+
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativecontext.h>
+#include <QtDeclarative/qdeclarativeproperty.h>
+
+#include <QtCore/qfile.h>
+#include <QtCore/qdebug.h>
+#include <QtScript/qscriptvalue.h>
+#include <QtScript/qscriptcontext.h>
+#include <QtScript/qscriptengine.h>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+
+
+class QDeclarative1BindPrivate : public QObjectPrivate
+{
+public:
+ QDeclarative1BindPrivate() : when(true), componentComplete(true), obj(0) {}
+
+ bool when : 1;
+ bool componentComplete : 1;
+ QObject *obj;
+ QString prop;
+ QDeclarativeNullableValue<QVariant> value;
+};
+
+
+/*!
+ \qmlclass Binding QDeclarative1Bind
+ \ingroup qml-working-with-data
+ \since 4.7
+ \brief The Binding element allows arbitrary property bindings to be created.
+
+ Sometimes it is necessary to bind to a property of an object that wasn't
+ directly instantiated by QML - generally a property of a class exported
+ to QML by C++. In these cases, regular property binding doesn't work. Binding
+ allows you to bind any value to any property.
+
+ For example, imagine a C++ application that maps an "app.enteredText"
+ property into QML. You could use Binding to update the enteredText property
+ like this.
+ \code
+ TextEdit { id: myTextField; text: "Please type here..." }
+ Binding { target: app; property: "enteredText"; value: myTextField.text }
+ \endcode
+ Whenever the text in the TextEdit is updated, the C++ property will be
+ updated also.
+
+ If the binding target or binding property is changed, the bound value is
+ immediately pushed onto the new target.
+
+ \sa QtDeclarative
+*/
+QDeclarative1Bind::QDeclarative1Bind(QObject *parent)
+ : QObject(*(new QDeclarative1BindPrivate), parent)
+{
+}
+
+QDeclarative1Bind::~QDeclarative1Bind()
+{
+}
+
+/*!
+ \qmlproperty bool Binding::when
+
+ This property holds when the binding is active.
+ This should be set to an expression that evaluates to true when you want the binding to be active.
+
+ \code
+ Binding {
+ target: contactName; property: 'text'
+ value: name; when: list.ListView.isCurrentItem
+ }
+ \endcode
+*/
+bool QDeclarative1Bind::when() const
+{
+ Q_D(const QDeclarative1Bind);
+ return d->when;
+}
+
+void QDeclarative1Bind::setWhen(bool v)
+{
+ Q_D(QDeclarative1Bind);
+ d->when = v;
+ eval();
+}
+
+/*!
+ \qmlproperty Object Binding::target
+
+ The object to be updated.
+*/
+QObject *QDeclarative1Bind::object()
+{
+ Q_D(const QDeclarative1Bind);
+ return d->obj;
+}
+
+void QDeclarative1Bind::setObject(QObject *obj)
+{
+ Q_D(QDeclarative1Bind);
+ d->obj = obj;
+ eval();
+}
+
+/*!
+ \qmlproperty string Binding::property
+
+ The property to be updated.
+*/
+QString QDeclarative1Bind::property() const
+{
+ Q_D(const QDeclarative1Bind);
+ return d->prop;
+}
+
+void QDeclarative1Bind::setProperty(const QString &p)
+{
+ Q_D(QDeclarative1Bind);
+ d->prop = p;
+ eval();
+}
+
+/*!
+ \qmlproperty any Binding::value
+
+ The value to be set on the target object and property. This can be a
+ constant (which isn't very useful), or a bound expression.
+*/
+QVariant QDeclarative1Bind::value() const
+{
+ Q_D(const QDeclarative1Bind);
+ return d->value.value;
+}
+
+void QDeclarative1Bind::setValue(const QVariant &v)
+{
+ Q_D(QDeclarative1Bind);
+ d->value.value = v;
+ d->value.isNull = false;
+ eval();
+}
+
+void QDeclarative1Bind::classBegin()
+{
+ Q_D(QDeclarative1Bind);
+ d->componentComplete = false;
+}
+
+void QDeclarative1Bind::componentComplete()
+{
+ Q_D(QDeclarative1Bind);
+ d->componentComplete = true;
+ eval();
+}
+
+void QDeclarative1Bind::eval()
+{
+ Q_D(QDeclarative1Bind);
+ if (!d->obj || d->value.isNull || !d->when || !d->componentComplete)
+ return;
+
+ QDeclarativeProperty prop(d->obj, d->prop);
+ prop.write(d->value.value);
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/util/qdeclarativebind_p.h b/src/qtquick1/util/qdeclarativebind_p.h
new file mode 100644
index 0000000000..d8296455c7
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativebind_p.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEBIND_H
+#define QDECLARATIVEBIND_H
+
+#include <QtDeclarative/qdeclarative.h>
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarative1BindPrivate;
+class Q_AUTOTEST_EXPORT QDeclarative1Bind : public QObject, public QDeclarativeParserStatus
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarative1Bind)
+ Q_INTERFACES(QDeclarativeParserStatus)
+ Q_PROPERTY(QObject *target READ object WRITE setObject)
+ Q_PROPERTY(QString property READ property WRITE setProperty)
+ Q_PROPERTY(QVariant value READ value WRITE setValue)
+ Q_PROPERTY(bool when READ when WRITE setWhen)
+
+public:
+ QDeclarative1Bind(QObject *parent=0);
+ ~QDeclarative1Bind();
+
+ bool when() const;
+ void setWhen(bool);
+
+ QObject *object();
+ void setObject(QObject *);
+
+ QString property() const;
+ void setProperty(const QString &);
+
+ QVariant value() const;
+ void setValue(const QVariant &);
+
+protected:
+ virtual void classBegin();
+ virtual void componentComplete();
+
+private:
+ void eval();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1Bind)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/qtquick1/util/qdeclarativeconnections.cpp b/src/qtquick1/util/qdeclarativeconnections.cpp
new file mode 100644
index 0000000000..d1d92356ac
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativeconnections.cpp
@@ -0,0 +1,293 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativeconnections_p.h"
+
+#include <QtDeclarative/qdeclarativeexpression.h>
+#include <QtDeclarative/private/qdeclarativeproperty_p.h>
+#include <QtDeclarative/private/qdeclarativeboundsignal_p.h>
+#include <QtDeclarative/qdeclarativecontext.h>
+#include <QtDeclarative/private/qdeclarativecontext_p.h>
+#include <QtDeclarative/qdeclarativeinfo.h>
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qstringlist.h>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+
+
+class QDeclarative1ConnectionsPrivate : public QObjectPrivate
+{
+public:
+ QDeclarative1ConnectionsPrivate() : target(0), targetSet(false), ignoreUnknownSignals(false), componentcomplete(true) {}
+
+ QList<QDeclarativeBoundSignal*> boundsignals;
+ QObject *target;
+
+ bool targetSet;
+ bool ignoreUnknownSignals;
+ bool componentcomplete;
+
+ QByteArray data;
+};
+
+/*!
+ \qmlclass Connections QDeclarative1Connections
+ \ingroup qml-utility-elements
+ \since 4.7
+ \brief A Connections element describes generalized connections to signals.
+
+ A Connections object creates a connection to a QML signal.
+
+ When connecting to signals in QML, the usual way is to create an
+ "on<Signal>" handler that reacts when a signal is received, like this:
+
+ \qml
+ MouseArea {
+ onClicked: { foo(parameters) }
+ }
+ \endqml
+
+ However, it is not possible to connect to a signal in this way in some
+ cases, such as when:
+
+ \list
+ \i Multiple connections to the same signal are required
+ \i Creating connections outside the scope of the signal sender
+ \i Connecting to targets not defined in QML
+ \endlist
+
+ When any of these are needed, the Connections element can be used instead.
+
+ For example, the above code can be changed to use a Connections object,
+ like this:
+
+ \qml
+ MouseArea {
+ Connections {
+ onClicked: foo(parameters)
+ }
+ }
+ \endqml
+
+ More generally, the Connections object can be a child of some object other than
+ the sender of the signal:
+
+ \qml
+ MouseArea {
+ id: area
+ }
+ // ...
+ \endqml
+ \qml
+ Connections {
+ target: area
+ onClicked: foo(parameters)
+ }
+ \endqml
+
+ \sa QtDeclarative
+*/
+QDeclarative1Connections::QDeclarative1Connections(QObject *parent) :
+ QObject(*(new QDeclarative1ConnectionsPrivate), parent)
+{
+}
+
+QDeclarative1Connections::~QDeclarative1Connections()
+{
+}
+
+/*!
+ \qmlproperty Object Connections::target
+ This property holds the object that sends the signal.
+
+ If this property is not set, the \c target defaults to the parent of the Connection.
+
+ If set to null, no connection is made and any signal handlers are ignored
+ until the target is not null.
+*/
+QObject *QDeclarative1Connections::target() const
+{
+ Q_D(const QDeclarative1Connections);
+ return d->targetSet ? d->target : parent();
+}
+
+void QDeclarative1Connections::setTarget(QObject *obj)
+{
+ Q_D(QDeclarative1Connections);
+ d->targetSet = true; // even if setting to 0, it is *set*
+ if (d->target == obj)
+ return;
+ foreach (QDeclarativeBoundSignal *s, d->boundsignals) {
+ // It is possible that target is being changed due to one of our signal
+ // handlers -> use deleteLater().
+ if (s->isEvaluating())
+ s->deleteLater();
+ else
+ delete s;
+ }
+ d->boundsignals.clear();
+ d->target = obj;
+ connectSignals();
+ emit targetChanged();
+}
+
+/*!
+ \qmlproperty bool Connections::ignoreUnknownSignals
+
+ Normally, a connection to a non-existent signal produces runtime errors.
+
+ If this property is set to \c true, such errors are ignored.
+ This is useful if you intend to connect to different types of objects, handling
+ a different set of signals for each object.
+*/
+bool QDeclarative1Connections::ignoreUnknownSignals() const
+{
+ Q_D(const QDeclarative1Connections);
+ return d->ignoreUnknownSignals;
+}
+
+void QDeclarative1Connections::setIgnoreUnknownSignals(bool ignore)
+{
+ Q_D(QDeclarative1Connections);
+ d->ignoreUnknownSignals = ignore;
+}
+
+
+
+QByteArray
+QDeclarative1ConnectionsParser::compile(const QList<QDeclarativeCustomParserProperty> &props)
+{
+ QByteArray rv;
+ QDataStream ds(&rv, QIODevice::WriteOnly);
+
+ for(int ii = 0; ii < props.count(); ++ii)
+ {
+ QString propName = QString::fromUtf8(props.at(ii).name());
+ if (!propName.startsWith(QLatin1String("on")) || !propName.at(2).isUpper()) {
+ error(props.at(ii), QDeclarative1Connections::tr("Cannot assign to non-existent property \"%1\"").arg(propName));
+ return QByteArray();
+ }
+
+ QList<QVariant> values = props.at(ii).assignedValues();
+
+ for (int i = 0; i < values.count(); ++i) {
+ const QVariant &value = values.at(i);
+
+ if (value.userType() == qMetaTypeId<QDeclarativeCustomParserNode>()) {
+ error(props.at(ii), QDeclarative1Connections::tr("Connections: nested objects not allowed"));
+ return QByteArray();
+ } else if (value.userType() == qMetaTypeId<QDeclarativeCustomParserProperty>()) {
+ error(props.at(ii), QDeclarative1Connections::tr("Connections: syntax error"));
+ return QByteArray();
+ } else {
+ QDeclarativeParser::Variant v = qvariant_cast<QDeclarativeParser::Variant>(value);
+ if (v.isScript()) {
+ ds << propName;
+ ds << v.asScript();
+ } else {
+ error(props.at(ii), QDeclarative1Connections::tr("Connections: script expected"));
+ return QByteArray();
+ }
+ }
+ }
+ }
+
+ return rv;
+}
+
+void QDeclarative1ConnectionsParser::setCustomData(QObject *object,
+ const QByteArray &data)
+{
+ QDeclarative1ConnectionsPrivate *p =
+ static_cast<QDeclarative1ConnectionsPrivate *>(QObjectPrivate::get(object));
+ p->data = data;
+}
+
+
+void QDeclarative1Connections::connectSignals()
+{
+ Q_D(QDeclarative1Connections);
+ if (!d->componentcomplete || (d->targetSet && !target()))
+ return;
+
+ QDataStream ds(d->data);
+ while (!ds.atEnd()) {
+ QString propName;
+ ds >> propName;
+ QString script;
+ ds >> script;
+ QDeclarativeProperty prop(target(), propName);
+ if (prop.isValid() && (prop.type() & QDeclarativeProperty::SignalProperty)) {
+ QDeclarativeBoundSignal *signal =
+ new QDeclarativeBoundSignal(target(), prop.method(), this);
+ QDeclarativeExpression *expression = new QDeclarativeExpression(qmlContext(this), 0, script);
+ QDeclarativeData *ddata = QDeclarativeData::get(this);
+ if (ddata && ddata->outerContext && !ddata->outerContext->url.isEmpty())
+ expression->setSourceLocation(ddata->outerContext->url.toString(), ddata->lineNumber);
+ signal->setExpression(expression);
+ d->boundsignals += signal;
+ } else {
+ if (!d->ignoreUnknownSignals)
+ qmlInfo(this) << tr("Cannot assign to non-existent property \"%1\"").arg(propName);
+ }
+ }
+}
+
+void QDeclarative1Connections::classBegin()
+{
+ Q_D(QDeclarative1Connections);
+ d->componentcomplete=false;
+}
+
+void QDeclarative1Connections::componentComplete()
+{
+ Q_D(QDeclarative1Connections);
+ d->componentcomplete=true;
+ connectSignals();
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/util/qdeclarativeconnections_p.h b/src/qtquick1/util/qdeclarativeconnections_p.h
new file mode 100644
index 0000000000..6d6112bf98
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativeconnections_p.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVECONNECTIONS_H
+#define QDECLARATIVECONNECTIONS_H
+
+#include <QtDeclarative/qdeclarative.h>
+#include <QtDeclarative/qdeclarativescriptstring.h>
+#include <QtDeclarative/private/qdeclarativecustomparser_p.h>
+
+#include <QtCore/qobject.h>
+#include <QtCore/qstring.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeBoundSignal;
+class QDeclarativeContext;
+class QDeclarative1ConnectionsPrivate;
+class Q_AUTOTEST_EXPORT QDeclarative1Connections : public QObject, public QDeclarativeParserStatus
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarative1Connections)
+
+ Q_INTERFACES(QDeclarativeParserStatus)
+ Q_PROPERTY(QObject *target READ target WRITE setTarget NOTIFY targetChanged)
+ Q_PROPERTY(bool ignoreUnknownSignals READ ignoreUnknownSignals WRITE setIgnoreUnknownSignals)
+
+public:
+ QDeclarative1Connections(QObject *parent=0);
+ ~QDeclarative1Connections();
+
+ QObject *target() const;
+ void setTarget(QObject *);
+
+ bool ignoreUnknownSignals() const;
+ void setIgnoreUnknownSignals(bool ignore);
+
+Q_SIGNALS:
+ void targetChanged();
+
+private:
+ void connectSignals();
+ void classBegin();
+ void componentComplete();
+};
+
+class QDeclarative1ConnectionsParser : public QDeclarativeCustomParser
+{
+public:
+ virtual QByteArray compile(const QList<QDeclarativeCustomParserProperty> &);
+ virtual void setCustomData(QObject *, const QByteArray &);
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1Connections)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/qtquick1/util/qdeclarativefontloader.cpp b/src/qtquick1/util/qdeclarativefontloader.cpp
new file mode 100644
index 0000000000..38f7fc6121
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativefontloader.cpp
@@ -0,0 +1,342 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativefontloader_p.h"
+
+#include <QtDeclarative/qdeclarativecontext.h>
+#include <QtDeclarative/qdeclarativeengine.h>
+
+#include <QStringList>
+#include <QUrl>
+#include <QDebug>
+#include <QNetworkRequest>
+#include <QNetworkReply>
+#include <QFontDatabase>
+
+#include <private/qobject_p.h>
+#include <QtDeclarative/private/qdeclarativeengine_p.h>
+#include <QtDeclarative/qdeclarativeinfo.h>
+
+QT_BEGIN_NAMESPACE
+
+
+
+#define FONTLOADER_MAXIMUM_REDIRECT_RECURSION 16
+
+class QDeclarative1FontObject : public QObject
+{
+Q_OBJECT
+
+public:
+ QDeclarative1FontObject(int _id);
+
+ void download(const QUrl &url, QNetworkAccessManager *manager);
+
+Q_SIGNALS:
+ void fontDownloaded(const QString&, QDeclarative1FontLoader::Status);
+
+private Q_SLOTS:
+ void replyFinished();
+
+public:
+ int id;
+
+private:
+ QNetworkReply *reply;
+ int redirectCount;
+
+ Q_DISABLE_COPY(QDeclarative1FontObject)
+};
+
+QDeclarative1FontObject::QDeclarative1FontObject(int _id = -1)
+ : QObject(0), id(_id), reply(0), redirectCount(0) {}
+
+
+void QDeclarative1FontObject::download(const QUrl &url, QNetworkAccessManager *manager)
+{
+ QNetworkRequest req(url);
+ req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);
+ reply = manager->get(req);
+ QObject::connect(reply, SIGNAL(finished()), this, SLOT(replyFinished()));
+}
+
+void QDeclarative1FontObject::replyFinished()
+{
+ if (reply) {
+ redirectCount++;
+ if (redirectCount < FONTLOADER_MAXIMUM_REDIRECT_RECURSION) {
+ QVariant redirect = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
+ if (redirect.isValid()) {
+ QUrl url = reply->url().resolved(redirect.toUrl());
+ QNetworkAccessManager *manager = reply->manager();
+ reply->deleteLater();
+ reply = 0;
+ download(url, manager);
+ return;
+ }
+ }
+ redirectCount = 0;
+
+ if (!reply->error()) {
+ id = QFontDatabase::addApplicationFontFromData(reply->readAll());
+ if (id != -1)
+ emit fontDownloaded(QFontDatabase::applicationFontFamilies(id).at(0), QDeclarative1FontLoader::Ready);
+ else
+ emit fontDownloaded(QString(), QDeclarative1FontLoader::Error);
+ } else {
+ emit fontDownloaded(QString(), QDeclarative1FontLoader::Error);
+ }
+ reply->deleteLater();
+ reply = 0;
+ }
+}
+
+
+class QDeclarative1FontLoaderPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1FontLoader)
+
+public:
+ QDeclarative1FontLoaderPrivate() : status(QDeclarative1FontLoader::Null) {}
+
+ QUrl url;
+ QString name;
+ QDeclarative1FontLoader::Status status;
+ static QHash<QUrl, QDeclarative1FontObject*> fonts;
+};
+
+QHash<QUrl, QDeclarative1FontObject*> QDeclarative1FontLoaderPrivate::fonts;
+
+/*!
+ \qmlclass FontLoader QDeclarative1FontLoader
+ \ingroup qml-utility-elements
+ \since 4.7
+ \brief The FontLoader element allows fonts to be loaded by name or URL.
+
+ The FontLoader element is used to load fonts by name or URL.
+
+ The \l status indicates when the font has been loaded, which is useful
+ for fonts loaded from remote sources.
+
+ For example:
+ \qml
+ import QtQuick 1.0
+
+ Column {
+ FontLoader { id: fixedFont; name: "Courier" }
+ FontLoader { id: webFont; source: "http://www.mysite.com/myfont.ttf" }
+
+ Text { text: "Fixed-size font"; font.family: fixedFont.name }
+ Text { text: "Fancy font"; font.family: webFont.name }
+ }
+ \endqml
+
+ \sa {declarative/text/fonts}{Fonts example}
+*/
+QDeclarative1FontLoader::QDeclarative1FontLoader(QObject *parent)
+ : QObject(*(new QDeclarative1FontLoaderPrivate), parent)
+{
+}
+
+QDeclarative1FontLoader::~QDeclarative1FontLoader()
+{
+}
+
+/*!
+ \qmlproperty url FontLoader::source
+ The url of the font to load.
+*/
+QUrl QDeclarative1FontLoader::source() const
+{
+ Q_D(const QDeclarative1FontLoader);
+ return d->url;
+}
+
+void QDeclarative1FontLoader::setSource(const QUrl &url)
+{
+ Q_D(QDeclarative1FontLoader);
+ if (url == d->url)
+ return;
+ d->url = qmlContext(this)->resolvedUrl(url);
+ emit sourceChanged();
+
+#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
+ QString localFile = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(d->url);
+ if (!localFile.isEmpty()) {
+ if (!d->fonts.contains(d->url)) {
+ int id = QFontDatabase::addApplicationFont(localFile);
+ if (id != -1) {
+ updateFontInfo(QFontDatabase::applicationFontFamilies(id).at(0), Ready);
+ QDeclarative1FontObject *fo = new QDeclarative1FontObject(id);
+ d->fonts[d->url] = fo;
+ } else {
+ updateFontInfo(QString(), Error);
+ }
+ } else {
+ updateFontInfo(QFontDatabase::applicationFontFamilies(d->fonts[d->url]->id).at(0), Ready);
+ }
+ } else
+#endif
+ {
+ if (!d->fonts.contains(d->url)) {
+ QDeclarative1FontObject *fo = new QDeclarative1FontObject;
+ d->fonts[d->url] = fo;
+ fo->download(d->url, qmlEngine(this)->networkAccessManager());
+ d->status = Loading;
+ emit statusChanged();
+ QObject::connect(fo, SIGNAL(fontDownloaded(QString,QDeclarative1FontLoader::Status)),
+ this, SLOT(updateFontInfo(QString,QDeclarative1FontLoader::Status)));
+ } else {
+ QDeclarative1FontObject *fo = d->fonts[d->url];
+ if (fo->id == -1) {
+ d->status = Loading;
+ emit statusChanged();
+ QObject::connect(fo, SIGNAL(fontDownloaded(QString,QDeclarative1FontLoader::Status)),
+ this, SLOT(updateFontInfo(QString,QDeclarative1FontLoader::Status)));
+ }
+ else
+ updateFontInfo(QFontDatabase::applicationFontFamilies(fo->id).at(0), Ready);
+ }
+ }
+}
+
+void QDeclarative1FontLoader::updateFontInfo(const QString& name, QDeclarative1FontLoader::Status status)
+{
+ Q_D(QDeclarative1FontLoader);
+
+ if (name != d->name) {
+ d->name = name;
+ emit nameChanged();
+ }
+ if (status != d->status) {
+ if (status == Error)
+ qmlInfo(this) << "Cannot load font: \"" << d->url.toString() << "\"";
+ d->status = status;
+ emit statusChanged();
+ }
+}
+
+/*!
+ \qmlproperty string FontLoader::name
+
+ This property holds the name of the font family.
+ It is set automatically when a font is loaded using the \c url property.
+
+ Use this to set the \c font.family property of a \c Text item.
+
+ Example:
+ \qml
+ Item {
+ width: 200; height: 50
+
+ FontLoader {
+ id: webFont
+ source: "http://www.mysite.com/myfont.ttf"
+ }
+ Text {
+ text: "Fancy font"
+ font.family: webFont.name
+ }
+ }
+ \endqml
+*/
+QString QDeclarative1FontLoader::name() const
+{
+ Q_D(const QDeclarative1FontLoader);
+ return d->name;
+}
+
+void QDeclarative1FontLoader::setName(const QString &name)
+{
+ Q_D(QDeclarative1FontLoader);
+ if (d->name == name)
+ return;
+ d->name = name;
+ emit nameChanged();
+ d->status = Ready;
+ emit statusChanged();
+}
+
+/*!
+ \qmlproperty enumeration FontLoader::status
+
+ This property holds the status of font loading. It can be one of:
+ \list
+ \o FontLoader.Null - no font has been set
+ \o FontLoader.Ready - the font has been loaded
+ \o FontLoader.Loading - the font is currently being loaded
+ \o FontLoader.Error - an error occurred while loading the font
+ \endlist
+
+ Use this status to provide an update or respond to the status change in some way.
+ For example, you could:
+
+ \list
+ \o Trigger a state change:
+ \qml
+ State { name: 'loaded'; when: loader.status == FontLoader.Ready }
+ \endqml
+
+ \o Implement an \c onStatusChanged signal handler:
+ \qml
+ FontLoader {
+ id: loader
+ onStatusChanged: if (loader.status == FontLoader.Ready) console.log('Loaded')
+ }
+ \endqml
+
+ \o Bind to the status value:
+ \qml
+ Text { text: loader.status == FontLoader.Ready ? 'Loaded' : 'Not loaded' }
+ \endqml
+ \endlist
+*/
+QDeclarative1FontLoader::Status QDeclarative1FontLoader::status() const
+{
+ Q_D(const QDeclarative1FontLoader);
+ return d->status;
+}
+
+
+
+QT_END_NAMESPACE
+
+#include <qdeclarativefontloader.moc>
diff --git a/src/qtquick1/util/qdeclarativefontloader_p.h b/src/qtquick1/util/qdeclarativefontloader_p.h
new file mode 100644
index 0000000000..76fa8e350f
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativefontloader_p.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEFONTLOADER_H
+#define QDECLARATIVEFONTLOADER_H
+
+#include <QtDeclarative/qdeclarative.h>
+
+#include <QtCore/qobject.h>
+#include <QtCore/qurl.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarative1FontLoaderPrivate;
+class Q_AUTOTEST_EXPORT QDeclarative1FontLoader : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarative1FontLoader)
+ Q_ENUMS(Status)
+
+ Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
+ Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
+ Q_PROPERTY(Status status READ status NOTIFY statusChanged)
+
+public:
+ enum Status { Null = 0, Ready, Loading, Error };
+
+ QDeclarative1FontLoader(QObject *parent = 0);
+ ~QDeclarative1FontLoader();
+
+ QUrl source() const;
+ void setSource(const QUrl &url);
+
+ QString name() const;
+ void setName(const QString &name);
+
+ Status status() const;
+
+private Q_SLOTS:
+ void updateFontInfo(const QString&, QDeclarative1FontLoader::Status);
+
+Q_SIGNALS:
+ void sourceChanged();
+ void nameChanged();
+ void statusChanged();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1FontLoader)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEFONTLOADER_H
+
diff --git a/src/qtquick1/util/qdeclarativelistaccessor.cpp b/src/qtquick1/util/qdeclarativelistaccessor.cpp
new file mode 100644
index 0000000000..215fe670e5
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativelistaccessor.cpp
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativelistaccessor_p.h"
+
+#include <QtDeclarative/private/qdeclarativemetatype_p.h>
+
+#include <QtCore/qstringlist.h>
+#include <QtCore/qdebug.h>
+
+// ### Remove me
+#include <QtDeclarative/private/qdeclarativeengine_p.h>
+
+QT_BEGIN_NAMESPACE
+
+
+
+QDeclarative1ListAccessor::QDeclarative1ListAccessor()
+: m_type(Invalid)
+{
+}
+
+QDeclarative1ListAccessor::~QDeclarative1ListAccessor()
+{
+}
+
+QVariant QDeclarative1ListAccessor::list() const
+{
+ return d;
+}
+
+void QDeclarative1ListAccessor::setList(const QVariant &v, QDeclarativeEngine *engine)
+{
+ d = v;
+
+ QDeclarativeEnginePrivate *enginePrivate = engine?QDeclarativeEnginePrivate::get(engine):0;
+
+ if (!d.isValid()) {
+ m_type = Invalid;
+ } else if (d.userType() == QVariant::StringList) {
+ m_type = StringList;
+ } else if (d.userType() == QMetaType::QVariantList) {
+ m_type = VariantList;
+ } else if (d.canConvert(QVariant::Int)) {
+ m_type = Integer;
+ } else if ((!enginePrivate && QDeclarativeMetaType::isQObject(d.userType())) ||
+ (enginePrivate && enginePrivate->isQObject(d.userType()))) {
+ QObject *data = enginePrivate?enginePrivate->toQObject(v):QDeclarativeMetaType::toQObject(v);
+ d = QVariant::fromValue(data);
+ m_type = Instance;
+ } else if (d.userType() == qMetaTypeId<QDeclarativeListReference>()) {
+ m_type = ListProperty;
+ } else {
+ m_type = Instance;
+ }
+}
+
+int QDeclarative1ListAccessor::count() const
+{
+ switch(m_type) {
+ case StringList:
+ return qvariant_cast<QStringList>(d).count();
+ case VariantList:
+ return qvariant_cast<QVariantList>(d).count();
+ case ListProperty:
+ return ((QDeclarativeListReference *)d.constData())->count();
+ case Instance:
+ return 1;
+ case Integer:
+ return d.toInt();
+ default:
+ case Invalid:
+ return 0;
+ }
+}
+
+QVariant QDeclarative1ListAccessor::at(int idx) const
+{
+ Q_ASSERT(idx >= 0 && idx < count());
+ switch(m_type) {
+ case StringList:
+ return QVariant::fromValue(qvariant_cast<QStringList>(d).at(idx));
+ case VariantList:
+ return qvariant_cast<QVariantList>(d).at(idx);
+ case ListProperty:
+ return QVariant::fromValue(((QDeclarativeListReference *)d.constData())->at(idx));
+ case Instance:
+ return d;
+ case Integer:
+ return QVariant(idx);
+ default:
+ case Invalid:
+ return QVariant();
+ }
+}
+
+bool QDeclarative1ListAccessor::isValid() const
+{
+ return m_type != Invalid;
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/util/qdeclarativelistaccessor_p.h b/src/qtquick1/util/qdeclarativelistaccessor_p.h
new file mode 100644
index 0000000000..6372deec23
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativelistaccessor_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVELISTACCESSOR_H
+#define QDECLARATIVELISTACCESSOR_H
+
+#include <QtCore/QVariant>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeEngine;
+
+QT_MODULE(Declarative)
+
+class Q_AUTOTEST_EXPORT QDeclarative1ListAccessor
+{
+public:
+ QDeclarative1ListAccessor();
+ ~QDeclarative1ListAccessor();
+
+ QVariant list() const;
+ void setList(const QVariant &, QDeclarativeEngine * = 0);
+
+ bool isValid() const;
+
+ int count() const;
+ QVariant at(int) const;
+
+ enum Type { Invalid, StringList, VariantList, ListProperty, Instance, Integer };
+ Type type() const { return m_type; }
+
+private:
+ Type m_type;
+ QVariant d;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVELISTACCESSOR_H
diff --git a/src/qtquick1/util/qdeclarativelistmodel.cpp b/src/qtquick1/util/qdeclarativelistmodel.cpp
new file mode 100644
index 0000000000..f9c9ded9b0
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativelistmodel.cpp
@@ -0,0 +1,1631 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativelistmodel_p_p.h"
+#include "QtQuick1/private/qdeclarativelistmodelworkeragent_p.h"
+#include "QtQuick1/private/qdeclarativeopenmetaobject_p.h"
+
+#include <QtDeclarative/private/qdeclarativecustomparser_p.h>
+#include <QtDeclarative/private/qdeclarativeparser_p.h>
+#include <QtDeclarative/private/qdeclarativeengine_p.h>
+#include <QtDeclarative/qdeclarativecontext.h>
+#include <QtDeclarative/qdeclarativeinfo.h>
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qstack.h>
+#include <QXmlStreamReader>
+#include <QtScript/qscriptvalueiterator.h>
+
+Q_DECLARE_METATYPE(QListModelInterface *)
+
+QT_BEGIN_NAMESPACE
+
+
+
+template<typename T>
+void qdeclarativelistmodel_move(int from, int to, int n, T *items)
+{
+ if (n == 1) {
+ items->move(from, to);
+ } else {
+ T replaced;
+ int i=0;
+ typename T::ConstIterator it=items->begin(); it += from+n;
+ for (; i<to-from; ++i,++it)
+ replaced.append(*it);
+ i=0;
+ it=items->begin(); it += from;
+ for (; i<n; ++i,++it)
+ replaced.append(*it);
+ typename T::ConstIterator f=replaced.begin();
+ typename T::Iterator t=items->begin(); t += from;
+ for (; f != replaced.end(); ++f, ++t)
+ *t = *f;
+ }
+}
+
+QDeclarative1ListModelParser::ListInstruction *QDeclarative1ListModelParser::ListModelData::instructions() const
+{
+ return (QDeclarative1ListModelParser::ListInstruction *)((char *)this + sizeof(ListModelData));
+}
+
+/*!
+ \qmlclass ListModel QDeclarative1ListModel
+ \ingroup qml-working-with-data
+ \since 4.7
+ \brief The ListModel element defines a free-form list data source.
+
+ The ListModel is a simple container of ListElement definitions, each containing data roles.
+ The contents can be defined dynamically, or explicitly in QML.
+
+ The number of elements in the model can be obtained from its \l count property.
+ A number of familiar methods are also provided to manipulate the contents of the
+ model, including append(), insert(), move(), remove() and set(). These methods
+ accept dictionaries as their arguments; these are translated to ListElement objects
+ by the model.
+
+ Elements can be manipulated via the model using the setProperty() method, which
+ allows the roles of the specified element to be set and changed.
+
+ \section1 Example Usage
+
+ The following example shows a ListModel containing three elements, with the roles
+ "name" and "cost".
+
+ \div {class="float-right"}
+ \inlineimage listmodel.png
+ \enddiv
+
+ \snippet doc/src/snippets/declarative/listmodel.qml 0
+
+ \clearfloat
+ Roles (properties) in each element must begin with a lower-case letter and
+ should be common to all elements in a model. The ListElement documentation
+ provides more guidelines for how elements should be defined.
+
+ Since the example model contains an \c id property, it can be referenced
+ by views, such as the ListView in this example:
+
+ \snippet doc/src/snippets/declarative/listmodel-simple.qml 0
+ \dots 8
+ \snippet doc/src/snippets/declarative/listmodel-simple.qml 1
+
+ It is possible for roles to contain list data. In the following example we
+ create a list of fruit attributes:
+
+ \snippet doc/src/snippets/declarative/listmodel-nested.qml model
+
+ The delegate displays all the fruit attributes:
+
+ \div {class="float-right"}
+ \inlineimage listmodel-nested.png
+ \enddiv
+
+ \snippet doc/src/snippets/declarative/listmodel-nested.qml delegate
+
+ \clearfloat
+ \section1 Modifying List Models
+
+ The content of a ListModel may be created and modified using the clear(),
+ append(), set(), insert() and setProperty() methods. For example:
+
+ \snippet doc/src/snippets/declarative/listmodel-modify.qml delegate
+
+ Note that when creating content dynamically the set of available properties
+ cannot be changed once set. Whatever properties are first added to the model
+ are the only permitted properties in the model.
+
+ \section1 Using Threaded List Models with WorkerScript
+
+ ListModel can be used together with WorkerScript access a list model
+ from multiple threads. This is useful if list modifications are
+ synchronous and take some time: the list operations can be moved to a
+ different thread to avoid blocking of the main GUI thread.
+
+ Here is an example that uses WorkerScript to periodically append the
+ current time to a list model:
+
+ \snippet examples/declarative/threading/threadedlistmodel/timedisplay.qml 0
+
+ The included file, \tt dataloader.js, looks like this:
+
+ \snippet examples/declarative/threading/threadedlistmodel/dataloader.js 0
+
+ The timer in the main example sends messages to the worker script by calling
+ \l WorkerScript::sendMessage(). When this message is received,
+ \l{WorkerScript::onMessage}{WorkerScript.onMessage()} is invoked in \c dataloader.js,
+ which appends the current time to the list model.
+
+ Note the call to sync() from the \l{WorkerScript::onMessage}{WorkerScript.onMessage()}
+ handler. You must call sync() or else the changes made to the list from the external
+ thread will not be reflected in the list model in the main thread.
+
+ \section1 Restrictions
+
+ If a list model is to be accessed from a WorkerScript, it cannot
+ contain list-type data. So, the following model cannot be used from a WorkerScript
+ because of the list contained in the "attributes" property:
+
+ \code
+ ListModel {
+ id: fruitModel
+ ListElement {
+ name: "Apple"
+ cost: 2.45
+ attributes: [
+ ListElement { description: "Core" },
+ ListElement { description: "Deciduous" }
+ ]
+ }
+ }
+ \endcode
+
+ In addition, the WorkerScript cannot add list-type data to the model.
+
+ \sa {qmlmodels}{Data Models}, {declarative/threading/threadedlistmodel}{Threaded ListModel example}, QtDeclarative
+*/
+
+
+/*
+ A ListModel internally uses either a NestedListModel_1 or FlatListModel_1.
+
+ A NestedListModel_1 can contain lists of ListElements (which
+ when retrieved from get() is accessible as a list model within the list
+ model) whereas a FlatListModel_1 cannot.
+
+ ListModel uses a NestedListModel_1 to begin with, and if the model is later
+ used from a WorkerScript, it changes to use a FlatListModel_1 instead. This
+ is because ModelNode (which abstracts the nested list model data) needs
+ access to the declarative engine and script engine, which cannot be
+ safely used from outside of the main thread.
+*/
+
+QDeclarative1ListModel::QDeclarative1ListModel(QObject *parent)
+: QListModelInterface(parent), m_agent(0), m_nested(new NestedListModel_1(this)), m_flat(0)
+{
+}
+
+QDeclarative1ListModel::QDeclarative1ListModel(const QDeclarative1ListModel *orig, QDeclarative1ListModelWorkerAgent *parent)
+: QListModelInterface(parent), m_agent(0), m_nested(0), m_flat(0)
+{
+ m_flat = new FlatListModel_1(this);
+ m_flat->m_parentAgent = parent;
+
+ if (orig->m_flat) {
+ m_flat->m_roles = orig->m_flat->m_roles;
+ m_flat->m_strings = orig->m_flat->m_strings;
+ m_flat->m_values = orig->m_flat->m_values;
+
+ m_flat->m_nodeData.reserve(m_flat->m_values.count());
+ for (int i=0; i<m_flat->m_values.count(); i++)
+ m_flat->m_nodeData << 0;
+ }
+}
+
+QDeclarative1ListModel::~QDeclarative1ListModel()
+{
+ if (m_agent)
+ m_agent->release();
+
+ delete m_nested;
+ delete m_flat;
+}
+
+bool QDeclarative1ListModel::flatten()
+{
+ if (m_flat)
+ return true;
+
+ QList<int> roles = m_nested->roles();
+
+ QList<QHash<int, QVariant> > values;
+ bool hasNested = false;
+ for (int i=0; i<m_nested->count(); i++) {
+ values.append(m_nested->data(i, roles, &hasNested));
+ if (hasNested)
+ return false;
+ }
+
+ FlatListModel_1 *flat = new FlatListModel_1(this);
+ flat->m_values = values;
+
+ for (int i=0; i<roles.count(); i++) {
+ QString s = m_nested->toString(roles[i]);
+ flat->m_roles.insert(roles[i], s);
+ flat->m_strings.insert(s, roles[i]);
+ }
+
+ flat->m_nodeData.reserve(flat->m_values.count());
+ for (int i=0; i<flat->m_values.count(); i++)
+ flat->m_nodeData << 0;
+
+ m_flat = flat;
+ delete m_nested;
+ m_nested = 0;
+ return true;
+}
+
+bool QDeclarative1ListModel::inWorkerThread() const
+{
+ return m_flat && m_flat->m_parentAgent;
+}
+
+QDeclarative1ListModelWorkerAgent *QDeclarative1ListModel::agent()
+{
+ if (m_agent)
+ return m_agent;
+
+ if (!flatten()) {
+ qmlInfo(this) << "List contains list-type data and cannot be used from a worker script";
+ return 0;
+ }
+
+ m_agent = new QDeclarative1ListModelWorkerAgent(this);
+ return m_agent;
+}
+
+QList<int> QDeclarative1ListModel::roles() const
+{
+ return m_flat ? m_flat->roles() : m_nested->roles();
+}
+
+QString QDeclarative1ListModel::toString(int role) const
+{
+ return m_flat ? m_flat->toString(role) : m_nested->toString(role);
+}
+
+QVariant QDeclarative1ListModel::data(int index, int role) const
+{
+ if (index >= count() || index < 0)
+ return QVariant();
+
+ return m_flat ? m_flat->data(index, role) : m_nested->data(index, role);
+}
+
+/*!
+ \qmlproperty int ListModel::count
+ The number of data entries in the model.
+*/
+int QDeclarative1ListModel::count() const
+{
+ return m_flat ? m_flat->count() : m_nested->count();
+}
+
+/*!
+ \qmlmethod ListModel::clear()
+
+ Deletes all content from the model.
+
+ \sa append() remove()
+*/
+void QDeclarative1ListModel::clear()
+{
+ int cleared = count();
+ if (m_flat)
+ m_flat->clear();
+ else
+ m_nested->clear();
+
+ if (!inWorkerThread()) {
+ emit itemsRemoved(0, cleared);
+ emit countChanged();
+ }
+}
+
+QDeclarative1ListModel *ModelNode::model(const NestedListModel_1 *model)
+{
+ if (!modelCache) {
+ modelCache = new QDeclarative1ListModel;
+ QDeclarativeEngine::setContextForObject(modelCache,QDeclarativeEngine::contextForObject(model->m_listModel));
+ modelCache->m_nested->_root = this; // ListModel defaults to nestable model
+
+ for (int i=0; i<values.count(); ++i) {
+ ModelNode *subNode = qvariant_cast<ModelNode *>(values.at(i));
+ if (subNode)
+ subNode->m_model = modelCache->m_nested;
+ }
+ }
+ return modelCache;
+}
+
+ModelObject_1 *ModelNode::object(const NestedListModel_1 *model)
+{
+ if (!objectCache) {
+ objectCache = new ModelObject_1(this,
+ const_cast<NestedListModel_1*>(model),
+ QDeclarativeEnginePrivate::getScriptEngine(qmlEngine(model->m_listModel)));
+ QHash<QString, ModelNode *>::iterator it;
+ for (it = properties.begin(); it != properties.end(); ++it) {
+ objectCache->setValue(it.key().toUtf8(), model->valueForNode(*it));
+ }
+ objectCache->setNodeUpdatesEnabled(true);
+ }
+ return objectCache;
+}
+
+/*!
+ \qmlmethod ListModel::remove(int index)
+
+ Deletes the content at \a index from the model.
+
+ \sa clear()
+*/
+void QDeclarative1ListModel::remove(int index)
+{
+ if (index < 0 || index >= count()) {
+ qmlInfo(this) << tr("remove: index %1 out of range").arg(index);
+ return;
+ }
+
+ if (m_flat)
+ m_flat->remove(index);
+ else
+ m_nested->remove(index);
+
+ if (!inWorkerThread()) {
+ emit itemsRemoved(index, 1);
+ emit countChanged();
+ }
+}
+
+/*!
+ \qmlmethod ListModel::insert(int index, jsobject dict)
+
+ Adds a new item to the list model at position \a index, with the
+ values in \a dict.
+
+ \code
+ fruitModel.insert(2, {"cost": 5.95, "name":"Pizza"})
+ \endcode
+
+ The \a index must be to an existing item in the list, or one past
+ the end of the list (equivalent to append).
+
+ \sa set() append()
+*/
+void QDeclarative1ListModel::insert(int index, const QScriptValue& valuemap)
+{
+ if (!valuemap.isObject() || valuemap.isArray()) {
+ qmlInfo(this) << tr("insert: value is not an object");
+ return;
+ }
+
+ if (index < 0 || index > count()) {
+ qmlInfo(this) << tr("insert: index %1 out of range").arg(index);
+ return;
+ }
+
+ bool ok = m_flat ? m_flat->insert(index, valuemap) : m_nested->insert(index, valuemap);
+ if (ok && !inWorkerThread()) {
+ emit itemsInserted(index, 1);
+ emit countChanged();
+ }
+}
+
+/*!
+ \qmlmethod ListModel::move(int from, int to, int n)
+
+ Moves \a n items \a from one position \a to another.
+
+ The from and to ranges must exist; for example, to move the first 3 items
+ to the end of the list:
+
+ \code
+ fruitModel.move(0, fruitModel.count - 3, 3)
+ \endcode
+
+ \sa append()
+*/
+void QDeclarative1ListModel::move(int from, int to, int n)
+{
+ if (n==0 || from==to)
+ return;
+ if (!canMove(from, to, n)) {
+ qmlInfo(this) << tr("move: out of range");
+ return;
+ }
+
+ int origfrom = from;
+ int origto = to;
+ int orign = n;
+ if (from > to) {
+ // Only move forwards - flip if backwards moving
+ int tfrom = from;
+ int tto = to;
+ from = tto;
+ to = tto+n;
+ n = tfrom-tto;
+ }
+
+ if (m_flat)
+ m_flat->move(from, to, n);
+ else
+ m_nested->move(from, to, n);
+
+ if (!inWorkerThread())
+ emit itemsMoved(origfrom, origto, orign);
+}
+
+/*!
+ \qmlmethod ListModel::append(jsobject dict)
+
+ Adds a new item to the end of the list model, with the
+ values in \a dict.
+
+ \code
+ fruitModel.append({"cost": 5.95, "name":"Pizza"})
+ \endcode
+
+ \sa set() remove()
+*/
+void QDeclarative1ListModel::append(const QScriptValue& valuemap)
+{
+ if (!valuemap.isObject() || valuemap.isArray()) {
+ qmlInfo(this) << tr("append: value is not an object");
+ return;
+ }
+
+ insert(count(), valuemap);
+}
+
+/*!
+ \qmlmethod object ListModel::get(int index)
+
+ Returns the item at \a index in the list model. This allows the item
+ data to be accessed or modified from JavaScript:
+
+ \code
+ Component.onCompleted: {
+ fruitModel.append({"cost": 5.95, "name":"Jackfruit"});
+ console.log(fruitModel.get(0).cost);
+ fruitModel.get(0).cost = 10.95;
+ }
+ \endcode
+
+ The \a index must be an element in the list.
+
+ Note that properties of the returned object that are themselves objects
+ will also be models, and this get() method is used to access elements:
+
+ \code
+ fruitModel.append(..., "attributes":
+ [{"name":"spikes","value":"7mm"},
+ {"name":"color","value":"green"}]);
+ fruitModel.get(0).attributes.get(1).value; // == "green"
+ \endcode
+
+ \warning The returned object is not guaranteed to remain valid. It
+ should not be used in \l{Property Binding}{property bindings}.
+
+ \sa append()
+*/
+QScriptValue QDeclarative1ListModel::get(int index) const
+{
+ // the internal flat/nested class checks for bad index
+ return m_flat ? m_flat->get(index) : m_nested->get(index);
+}
+
+/*!
+ \qmlmethod ListModel::set(int index, jsobject dict)
+
+ Changes the item at \a index in the list model with the
+ values in \a dict. Properties not appearing in \a dict
+ are left unchanged.
+
+ \code
+ fruitModel.set(3, {"cost": 5.95, "name":"Pizza"})
+ \endcode
+
+ If \a index is equal to count() then a new item is appended to the
+ list. Otherwise, \a index must be an element in the list.
+
+ \sa append()
+*/
+void QDeclarative1ListModel::set(int index, const QScriptValue& valuemap)
+{
+ QList<int> roles;
+ set(index, valuemap, &roles);
+ if (!roles.isEmpty() && !inWorkerThread())
+ emit itemsChanged(index, 1, roles);
+}
+
+void QDeclarative1ListModel::set(int index, const QScriptValue& valuemap, QList<int> *roles)
+{
+ if (!valuemap.isObject() || valuemap.isArray()) {
+ qmlInfo(this) << tr("set: value is not an object");
+ return;
+ }
+ if (index > count() || index < 0) {
+ qmlInfo(this) << tr("set: index %1 out of range").arg(index);
+ return;
+ }
+
+ if (index == count()) {
+ append(valuemap);
+ } else {
+ if (m_flat)
+ m_flat->set(index, valuemap, roles);
+ else
+ m_nested->set(index, valuemap, roles);
+ }
+}
+
+/*!
+ \qmlmethod ListModel::setProperty(int index, string property, variant value)
+
+ Changes the \a property of the item at \a index in the list model to \a value.
+
+ \code
+ fruitModel.setProperty(3, "cost", 5.95)
+ \endcode
+
+ The \a index must be an element in the list.
+
+ \sa append()
+*/
+void QDeclarative1ListModel::setProperty(int index, const QString& property, const QVariant& value)
+{
+ QList<int> roles;
+ setProperty(index, property, value, &roles);
+ if (!roles.isEmpty() && !inWorkerThread())
+ emit itemsChanged(index, 1, roles);
+}
+
+void QDeclarative1ListModel::setProperty(int index, const QString& property, const QVariant& value, QList<int> *roles)
+{
+ if (count() == 0 || index >= count() || index < 0) {
+ qmlInfo(this) << tr("set: index %1 out of range").arg(index);
+ return;
+ }
+
+ if (m_flat)
+ m_flat->setProperty(index, property, value, roles);
+ else
+ m_nested->setProperty(index, property, value, roles);
+}
+
+/*!
+ \qmlmethod ListModel::sync()
+
+ Writes any unsaved changes to the list model after it has been modified
+ from a worker script.
+*/
+void QDeclarative1ListModel::sync()
+{
+ // This is just a dummy method to make it look like sync() exists in
+ // ListModel (and not just QDeclarative1ListModelWorkerAgent) and to let
+ // us document sync().
+ qmlInfo(this) << "List sync() can only be called from a WorkerScript";
+}
+
+bool QDeclarative1ListModelParser::compileProperty(const QDeclarativeCustomParserProperty &prop, QList<ListInstruction> &instr, QByteArray &data)
+{
+ QList<QVariant> values = prop.assignedValues();
+ for(int ii = 0; ii < values.count(); ++ii) {
+ const QVariant &value = values.at(ii);
+
+ if(value.userType() == qMetaTypeId<QDeclarativeCustomParserNode>()) {
+ QDeclarativeCustomParserNode node =
+ qvariant_cast<QDeclarativeCustomParserNode>(value);
+
+ if (node.name() != listElementTypeName) {
+ const QMetaObject *mo = resolveType(node.name());
+ if (mo != &QDeclarative1ListElement::staticMetaObject) {
+ error(node, QDeclarative1ListModel::tr("ListElement: cannot contain nested elements"));
+ return false;
+ }
+ listElementTypeName = node.name(); // cache right name for next time
+ }
+
+ {
+ ListInstruction li;
+ li.type = ListInstruction::Push;
+ li.dataIdx = -1;
+ instr << li;
+ }
+
+ QList<QDeclarativeCustomParserProperty> props = node.properties();
+ for(int jj = 0; jj < props.count(); ++jj) {
+ const QDeclarativeCustomParserProperty &nodeProp = props.at(jj);
+ if (nodeProp.name().isEmpty()) {
+ error(nodeProp, QDeclarative1ListModel::tr("ListElement: cannot contain nested elements"));
+ return false;
+ }
+ if (nodeProp.name() == "id") {
+ error(nodeProp, QDeclarative1ListModel::tr("ListElement: cannot use reserved \"id\" property"));
+ return false;
+ }
+
+ ListInstruction li;
+ int ref = data.count();
+ data.append(nodeProp.name());
+ data.append('\0');
+ li.type = ListInstruction::Set;
+ li.dataIdx = ref;
+ instr << li;
+
+ if(!compileProperty(nodeProp, instr, data))
+ return false;
+
+ li.type = ListInstruction::Pop;
+ li.dataIdx = -1;
+ instr << li;
+ }
+
+ {
+ ListInstruction li;
+ li.type = ListInstruction::Pop;
+ li.dataIdx = -1;
+ instr << li;
+ }
+
+ } else {
+
+ QDeclarativeParser::Variant variant =
+ qvariant_cast<QDeclarativeParser::Variant>(value);
+
+ int ref = data.count();
+
+ QByteArray d;
+ d += char(variant.type()); // type tag
+ if (variant.isString()) {
+ d += variant.asString().toUtf8();
+ } else if (variant.isNumber()) {
+ d += QByteArray::number(variant.asNumber(),'g',20);
+ } else if (variant.isBoolean()) {
+ d += char(variant.asBoolean());
+ } else if (variant.isScript()) {
+ if (definesEmptyList(variant.asScript())) {
+ d[0] = char(QDeclarativeParser::Variant::Invalid); // marks empty list
+ } else {
+ QByteArray script = variant.asScript().toUtf8();
+ int v = evaluateEnum(script);
+ if (v<0) {
+ if (script.startsWith("QT_TR_NOOP(\"") && script.endsWith("\")")) {
+ d[0] = char(QDeclarativeParser::Variant::String);
+ d += script.mid(12,script.length()-14);
+ } else {
+ error(prop, QDeclarative1ListModel::tr("ListElement: cannot use script for property value"));
+ return false;
+ }
+ } else {
+ d[0] = char(QDeclarativeParser::Variant::Number);
+ d += QByteArray::number(v);
+ }
+ }
+ }
+ d.append('\0');
+ data.append(d);
+
+ ListInstruction li;
+ li.type = ListInstruction::Value;
+ li.dataIdx = ref;
+ instr << li;
+ }
+ }
+
+ return true;
+}
+
+QByteArray QDeclarative1ListModelParser::compile(const QList<QDeclarativeCustomParserProperty> &customProps)
+{
+ QList<ListInstruction> instr;
+ QByteArray data;
+ listElementTypeName = QByteArray(); // unknown
+
+ for(int ii = 0; ii < customProps.count(); ++ii) {
+ const QDeclarativeCustomParserProperty &prop = customProps.at(ii);
+ if(!prop.name().isEmpty()) { // isn't default property
+ error(prop, QDeclarative1ListModel::tr("ListModel: undefined property '%1'").arg(QString::fromUtf8(prop.name())));
+ return QByteArray();
+ }
+
+ if(!compileProperty(prop, instr, data)) {
+ return QByteArray();
+ }
+ }
+
+ int size = sizeof(ListModelData) +
+ instr.count() * sizeof(ListInstruction) +
+ data.count();
+
+ QByteArray rv;
+ rv.resize(size);
+
+ ListModelData *lmd = (ListModelData *)rv.data();
+ lmd->dataOffset = sizeof(ListModelData) +
+ instr.count() * sizeof(ListInstruction);
+ lmd->instrCount = instr.count();
+ for (int ii = 0; ii < instr.count(); ++ii)
+ lmd->instructions()[ii] = instr.at(ii);
+ ::memcpy(rv.data() + lmd->dataOffset, data.constData(), data.count());
+
+ return rv;
+}
+
+void QDeclarative1ListModelParser::setCustomData(QObject *obj, const QByteArray &d)
+{
+ QDeclarative1ListModel *rv = static_cast<QDeclarative1ListModel *>(obj);
+
+ ModelNode *root = new ModelNode(rv->m_nested);
+ rv->m_nested->_root = root;
+ QStack<ModelNode *> nodes;
+ nodes << root;
+
+ bool processingSet = false;
+
+ const ListModelData *lmd = (const ListModelData *)d.constData();
+ const char *data = ((const char *)lmd) + lmd->dataOffset;
+
+ for (int ii = 0; ii < lmd->instrCount; ++ii) {
+ const ListInstruction &instr = lmd->instructions()[ii];
+
+ switch(instr.type) {
+ case ListInstruction::Push:
+ {
+ ModelNode *n = nodes.top();
+ ModelNode *n2 = new ModelNode(rv->m_nested);
+ n->values << QVariant::fromValue(n2);
+ nodes.push(n2);
+ if (processingSet)
+ n->isArray = true;
+ }
+ break;
+
+ case ListInstruction::Pop:
+ nodes.pop();
+ break;
+
+ case ListInstruction::Value:
+ {
+ ModelNode *n = nodes.top();
+ switch (QDeclarativeParser::Variant::Type(data[instr.dataIdx])) {
+ case QDeclarativeParser::Variant::Invalid:
+ n->isArray = true;
+ break;
+ case QDeclarativeParser::Variant::Boolean:
+ n->values.append(bool(data[1 + instr.dataIdx]));
+ break;
+ case QDeclarativeParser::Variant::Number:
+ n->values.append(QByteArray(data + 1 + instr.dataIdx).toDouble());
+ break;
+ case QDeclarativeParser::Variant::String:
+ n->values.append(QString::fromUtf8(data + 1 + instr.dataIdx));
+ break;
+ default:
+ Q_ASSERT("Format error in ListInstruction");
+ }
+
+ processingSet = false;
+ }
+ break;
+
+ case ListInstruction::Set:
+ {
+ ModelNode *n = nodes.top();
+ ModelNode *n2 = new ModelNode(rv->m_nested);
+ n->properties.insert(QString::fromUtf8(data + instr.dataIdx), n2);
+ nodes.push(n2);
+ processingSet = true;
+ }
+ break;
+ }
+ }
+
+ ModelNode *rootNode = rv->m_nested->_root;
+ for (int i=0; i<rootNode->values.count(); ++i) {
+ ModelNode *node = qvariant_cast<ModelNode *>(rootNode->values[i]);
+ node->listIndex = i;
+ node->updateListIndexes();
+ }
+}
+
+bool QDeclarative1ListModelParser::definesEmptyList(const QString &s)
+{
+ if (s.startsWith(QLatin1Char('[')) && s.endsWith(QLatin1Char(']'))) {
+ for (int i=1; i<s.length()-1; i++) {
+ if (!s[i].isSpace())
+ return false;
+ }
+ return true;
+ }
+ return false;
+}
+
+
+/*!
+ \qmlclass ListElement QDeclarative1ListElement
+ \ingroup qml-working-with-data
+ \since 4.7
+ \brief The ListElement element defines a data item in a ListModel.
+
+ List elements are defined inside ListModel definitions, and represent items in a
+ list that will be displayed using ListView or \l Repeater items.
+
+ List elements are defined like other QML elements except that they contain
+ a collection of \e role definitions instead of properties. Using the same
+ syntax as property definitions, roles both define how the data is accessed
+ and include the data itself.
+
+ The names used for roles must begin with a lower-case letter and should be
+ common to all elements in a given model. Values must be simple constants; either
+ strings (quoted and optionally within a call to QT_TR_NOOP), boolean values
+ (true, false), numbers, or enumeration values (such as AlignText.AlignHCenter).
+
+ \section1 Referencing Roles
+
+ The role names are used by delegates to obtain data from list elements.
+ Each role name is accessible in the delegate's scope, and refers to the
+ corresponding role in the current element. Where a role name would be
+ ambiguous to use, it can be accessed via the \l{ListView::}{model}
+ property (e.g., \c{model.cost} instead of \c{cost}).
+
+ \section1 Example Usage
+
+ The following model defines a series of list elements, each of which
+ contain "name" and "cost" roles and their associated values.
+
+ \snippet doc/src/snippets/declarative/qml-data-models/listelements.qml model
+
+ The delegate obtains the name and cost for each element by simply referring
+ to \c name and \c cost:
+
+ \snippet doc/src/snippets/declarative/qml-data-models/listelements.qml view
+
+ \sa ListModel
+*/
+
+FlatListModel_1::FlatListModel_1(QDeclarative1ListModel *base)
+ : m_scriptEngine(0), m_listModel(base), m_scriptClass(0), m_parentAgent(0)
+{
+}
+
+FlatListModel_1::~FlatListModel_1()
+{
+ qDeleteAll(m_nodeData);
+}
+
+QVariant FlatListModel_1::data(int index, int role) const
+{
+ Q_ASSERT(index >= 0 && index < m_values.count());
+ if (m_values[index].contains(role))
+ return m_values[index][role];
+ return QVariant();
+}
+
+QList<int> FlatListModel_1::roles() const
+{
+ return m_roles.keys();
+}
+
+QString FlatListModel_1::toString(int role) const
+{
+ if (m_roles.contains(role))
+ return m_roles[role];
+ return QString();
+}
+
+int FlatListModel_1::count() const
+{
+ return m_values.count();
+}
+
+void FlatListModel_1::clear()
+{
+ m_values.clear();
+
+ qDeleteAll(m_nodeData);
+ m_nodeData.clear();
+}
+
+void FlatListModel_1::remove(int index)
+{
+ m_values.removeAt(index);
+ removedNode(index);
+}
+
+bool FlatListModel_1::insert(int index, const QScriptValue &value)
+{
+ Q_ASSERT(index >= 0 && index <= m_values.count());
+
+ QHash<int, QVariant> row;
+ if (!addValue(value, &row, 0))
+ return false;
+
+ m_values.insert(index, row);
+ insertedNode(index);
+
+ return true;
+}
+
+QScriptValue FlatListModel_1::get(int index) const
+{
+ QScriptEngine *scriptEngine = m_scriptEngine ? m_scriptEngine : QDeclarativeEnginePrivate::getScriptEngine(qmlEngine(m_listModel));
+
+ if (!scriptEngine)
+ return 0;
+
+ if (index < 0 || index >= m_values.count())
+ return scriptEngine->undefinedValue();
+
+ FlatListModel_1 *that = const_cast<FlatListModel_1*>(this);
+ if (!m_scriptClass)
+ that->m_scriptClass = new FlatListScriptClass_1(that, scriptEngine);
+
+ FlatNodeData_1 *data = m_nodeData.value(index);
+ if (!data) {
+ data = new FlatNodeData_1(index);
+ that->m_nodeData.replace(index, data);
+ }
+
+ return QScriptDeclarativeClass::newObject(scriptEngine, m_scriptClass, new FlatNodeObjectData(data));
+}
+
+void FlatListModel_1::set(int index, const QScriptValue &value, QList<int> *roles)
+{
+ Q_ASSERT(index >= 0 && index < m_values.count());
+
+ QHash<int, QVariant> row = m_values[index];
+ if (addValue(value, &row, roles))
+ m_values[index] = row;
+}
+
+void FlatListModel_1::setProperty(int index, const QString& property, const QVariant& value, QList<int> *roles)
+{
+ Q_ASSERT(index >= 0 && index < m_values.count());
+
+ QHash<QString, int>::Iterator iter = m_strings.find(property);
+ int role;
+ if (iter == m_strings.end()) {
+ role = m_roles.count();
+ m_roles.insert(role, property);
+ m_strings.insert(property, role);
+ } else {
+ role = iter.value();
+ }
+
+ if (m_values[index][role] != value) {
+ roles->append(role);
+ m_values[index][role] = value;
+ }
+}
+
+void FlatListModel_1::move(int from, int to, int n)
+{
+ qdeclarativelistmodel_move<QList<QHash<int, QVariant> > >(from, to, n, &m_values);
+ moveNodes(from, to, n);
+}
+
+bool FlatListModel_1::addValue(const QScriptValue &value, QHash<int, QVariant> *row, QList<int> *roles)
+{
+ QScriptValueIterator it(value);
+ while (it.hasNext()) {
+ it.next();
+ QScriptValue value = it.value();
+ if (!value.isVariant() && !value.isRegExp() && !value.isDate() && value.isObject()) {
+ qmlInfo(m_listModel) << "Cannot add list-type data when modifying or after modification from a worker script";
+ return false;
+ }
+
+ QString name = it.name();
+ QVariant v = it.value().toVariant();
+
+ QHash<QString, int>::Iterator iter = m_strings.find(name);
+ if (iter == m_strings.end()) {
+ int role = m_roles.count();
+ m_roles.insert(role, name);
+ iter = m_strings.insert(name, role);
+ if (roles)
+ roles->append(role);
+ } else {
+ int role = iter.value();
+ if (roles && row->contains(role) && row->value(role) != v)
+ roles->append(role);
+ }
+ row->insert(*iter, v);
+ }
+ return true;
+}
+
+void FlatListModel_1::insertedNode(int index)
+{
+ if (index >= 0 && index <= m_values.count()) {
+ m_nodeData.insert(index, 0);
+
+ for (int i=index + 1; i<m_nodeData.count(); i++) {
+ if (m_nodeData[i])
+ m_nodeData[i]->index = i;
+ }
+ }
+}
+
+void FlatListModel_1::removedNode(int index)
+{
+ if (index >= 0 && index < m_nodeData.count()) {
+ delete m_nodeData.takeAt(index);
+
+ for (int i=index; i<m_nodeData.count(); i++) {
+ if (m_nodeData[i])
+ m_nodeData[i]->index = i;
+ }
+ }
+}
+
+void FlatListModel_1::moveNodes(int from, int to, int n)
+{
+ if (!m_listModel->canMove(from, to, n))
+ return;
+
+ qdeclarativelistmodel_move<QList<FlatNodeData_1 *> >(from, to, n, &m_nodeData);
+
+ for (int i=from; i<from + (to-from); i++) {
+ if (m_nodeData[i])
+ m_nodeData[i]->index = i;
+ }
+}
+
+
+
+FlatNodeData_1::~FlatNodeData_1()
+{
+ for (QSet<FlatNodeObjectData *>::Iterator iter = objects.begin(); iter != objects.end(); ++iter) {
+ FlatNodeObjectData *data = *iter;
+ data->nodeData = 0;
+ }
+}
+
+void FlatNodeData_1::addData(FlatNodeObjectData *data)
+{
+ objects.insert(data);
+}
+
+void FlatNodeData_1::removeData(FlatNodeObjectData *data)
+{
+ objects.remove(data);
+}
+
+
+FlatListScriptClass_1::FlatListScriptClass_1(FlatListModel_1 *model, QScriptEngine *seng)
+ : QScriptDeclarativeClass(seng),
+ m_model(model)
+{
+}
+
+QScriptDeclarativeClass::Value FlatListScriptClass_1::property(Object *obj, const Identifier &name)
+{
+ FlatNodeObjectData *objData = static_cast<FlatNodeObjectData*>(obj);
+ if (!objData->nodeData) // item at this index has been deleted
+ return QScriptDeclarativeClass::Value(engine(), engine()->undefinedValue());
+
+ int index = objData->nodeData->index;
+ QString propName = toString(name);
+ int role = m_model->m_strings.value(propName, -1);
+
+ if (role >= 0 && index >=0 ) {
+ const QHash<int, QVariant> &row = m_model->m_values[index];
+ QScriptValue sv = engine()->toScriptValue<QVariant>(row[role]);
+ return QScriptDeclarativeClass::Value(engine(), sv);
+ }
+
+ return QScriptDeclarativeClass::Value(engine(), engine()->undefinedValue());
+}
+
+void FlatListScriptClass_1::setProperty(Object *obj, const Identifier &name, const QScriptValue &value)
+{
+ if (!value.isVariant() && !value.isRegExp() && !value.isDate() && value.isObject()) {
+ qmlInfo(m_model->m_listModel) << "Cannot add list-type data when modifying or after modification from a worker script";
+ return;
+ }
+
+ FlatNodeObjectData *objData = static_cast<FlatNodeObjectData*>(obj);
+ if (!objData->nodeData) // item at this index has been deleted
+ return;
+
+ int index = objData->nodeData->index;
+ QString propName = toString(name);
+
+ int role = m_model->m_strings.value(propName, -1);
+ if (role >= 0 && index >= 0) {
+ QHash<int, QVariant> &row = m_model->m_values[index];
+ row[role] = value.toVariant();
+
+ QList<int> roles;
+ roles << role;
+ if (m_model->m_parentAgent) {
+ // This is the list in the worker thread, so tell the agent to
+ // emit itemsChanged() later
+ m_model->m_parentAgent->changedData(index, 1, roles);
+ } else {
+ // This is the list in the main thread, so emit itemsChanged()
+ emit m_model->m_listModel->itemsChanged(index, 1, roles);
+ }
+ }
+}
+
+QScriptClass::QueryFlags FlatListScriptClass_1::queryProperty(Object *, const Identifier &, QScriptClass::QueryFlags)
+{
+ return (QScriptClass::HandlesReadAccess | QScriptClass::HandlesWriteAccess);
+}
+
+bool FlatListScriptClass_1::compare(Object *obj1, Object *obj2)
+{
+ FlatNodeObjectData *data1 = static_cast<FlatNodeObjectData*>(obj1);
+ FlatNodeObjectData *data2 = static_cast<FlatNodeObjectData*>(obj2);
+
+ if (!data1->nodeData || !data2->nodeData)
+ return false;
+
+ return data1->nodeData->index == data2->nodeData->index;
+}
+
+
+
+NestedListModel_1::NestedListModel_1(QDeclarative1ListModel *base)
+ : _root(0), m_ownsRoot(false), m_listModel(base), _rolesOk(false)
+{
+}
+
+NestedListModel_1::~NestedListModel_1()
+{
+ if (m_ownsRoot)
+ delete _root;
+}
+
+QVariant NestedListModel_1::valueForNode(ModelNode *node, bool *hasNested) const
+{
+ QObject *rv = 0;
+ if (hasNested)
+ *hasNested = false;
+
+ if (node->isArray) {
+ // List
+ rv = node->model(this);
+ if (hasNested)
+ *hasNested = true;
+ } else {
+ if (!node->properties.isEmpty()) {
+ // Object
+ rv = node->object(this);
+ } else if (node->values.count() == 0) {
+ // Invalid
+ return QVariant();
+ } else if (node->values.count() == 1) {
+ // Value
+ QVariant &var = node->values[0];
+ ModelNode *valueNode = qvariant_cast<ModelNode *>(var);
+ if (valueNode) {
+ if (!valueNode->properties.isEmpty())
+ rv = valueNode->object(this);
+ else
+ rv = valueNode->model(this);
+ } else {
+ return var;
+ }
+ }
+ }
+
+ if (rv) {
+ return QVariant::fromValue(rv);
+ } else {
+ return QVariant();
+ }
+}
+
+QHash<int,QVariant> NestedListModel_1::data(int index, const QList<int> &roles, bool *hasNested) const
+{
+ Q_ASSERT(_root && index >= 0 && index < _root->values.count());
+ checkRoles();
+ QHash<int, QVariant> rv;
+
+ ModelNode *node = qvariant_cast<ModelNode *>(_root->values.at(index));
+ if (!node)
+ return rv;
+
+ for (int ii = 0; ii < roles.count(); ++ii) {
+ const QString &roleString = roleStrings.at(roles.at(ii));
+
+ QHash<QString, ModelNode *>::ConstIterator iter = node->properties.find(roleString);
+ if (iter != node->properties.end()) {
+ ModelNode *row = *iter;
+ rv.insert(roles.at(ii), valueForNode(row, hasNested));
+ }
+ }
+
+ return rv;
+}
+
+QVariant NestedListModel_1::data(int index, int role) const
+{
+ Q_ASSERT(_root && index >= 0 && index < _root->values.count());
+ checkRoles();
+ QVariant rv;
+ if (roleStrings.count() < role)
+ return rv;
+
+ ModelNode *node = qvariant_cast<ModelNode *>(_root->values.at(index));
+ if (!node)
+ return rv;
+
+ const QString &roleString = roleStrings.at(role);
+
+ QHash<QString, ModelNode *>::ConstIterator iter = node->properties.find(roleString);
+ if (iter != node->properties.end()) {
+ ModelNode *row = *iter;
+ rv = valueForNode(row);
+ }
+
+ return rv;
+}
+
+int NestedListModel_1::count() const
+{
+ if (!_root) return 0;
+ return _root->values.count();
+}
+
+void NestedListModel_1::clear()
+{
+ if (_root)
+ _root->clear();
+}
+
+void NestedListModel_1::remove(int index)
+{
+ if (!_root)
+ return;
+ ModelNode *node = qvariant_cast<ModelNode *>(_root->values.at(index));
+ _root->values.removeAt(index);
+ if (node)
+ delete node;
+}
+
+bool NestedListModel_1::insert(int index, const QScriptValue& valuemap)
+{
+ if (!_root) {
+ _root = new ModelNode(this);
+ m_ownsRoot = true;
+ }
+
+ ModelNode *mn = new ModelNode(this);
+ mn->listIndex = index;
+ mn->setObjectValue(valuemap);
+ _root->values.insert(index,QVariant::fromValue(mn));
+ return true;
+}
+
+void NestedListModel_1::move(int from, int to, int n)
+{
+ if (!_root)
+ return;
+ qdeclarativelistmodel_move<QVariantList>(from, to, n, &_root->values);
+}
+
+QScriptValue NestedListModel_1::get(int index) const
+{
+ QDeclarativeEngine *eng = qmlEngine(m_listModel);
+ if (!eng)
+ return 0;
+
+ if (index < 0 || index >= count()) {
+ QScriptEngine *seng = QDeclarativeEnginePrivate::getScriptEngine(eng);
+ if (seng)
+ return seng->undefinedValue();
+ return 0;
+ }
+
+ ModelNode *node = qvariant_cast<ModelNode *>(_root->values.at(index));
+ if (!node)
+ return 0;
+
+ return QDeclarativeEnginePrivate::qmlScriptObject(node->object(this), eng);
+}
+
+void NestedListModel_1::set(int index, const QScriptValue& valuemap, QList<int> *roles)
+{
+ Q_ASSERT(index >=0 && index < count());
+
+ ModelNode *node = qvariant_cast<ModelNode *>(_root->values.at(index));
+ bool emitItemsChanged = node->setObjectValue(valuemap);
+ if (!emitItemsChanged)
+ return;
+
+ QScriptValueIterator it(valuemap);
+ while (it.hasNext()) {
+ it.next();
+ int r = roleStrings.indexOf(it.name());
+ if (r < 0) {
+ r = roleStrings.count();
+ roleStrings << it.name();
+ }
+ roles->append(r);
+ }
+}
+
+void NestedListModel_1::setProperty(int index, const QString& property, const QVariant& value, QList<int> *roles)
+{
+ Q_ASSERT(index >=0 && index < count());
+
+ ModelNode *node = qvariant_cast<ModelNode *>(_root->values.at(index));
+ bool emitItemsChanged = node->setProperty(property, value);
+ if (!emitItemsChanged)
+ return;
+
+ int r = roleStrings.indexOf(property);
+ if (r < 0) {
+ r = roleStrings.count();
+ roleStrings << property;
+ }
+ roles->append(r);
+}
+
+void NestedListModel_1::checkRoles() const
+{
+ if (_rolesOk || !_root)
+ return;
+
+ for (int i = 0; i<_root->values.count(); ++i) {
+ ModelNode *node = qvariant_cast<ModelNode *>(_root->values.at(i));
+ if (node) {
+ foreach (const QString &role, node->properties.keys()) {
+ if (!roleStrings.contains(role))
+ roleStrings.append(role);
+ }
+ }
+ }
+
+ _rolesOk = true;
+}
+
+QList<int> NestedListModel_1::roles() const
+{
+ checkRoles();
+ QList<int> rv;
+ for (int ii = 0; ii < roleStrings.count(); ++ii)
+ rv << ii;
+ return rv;
+}
+
+QString NestedListModel_1::toString(int role) const
+{
+ checkRoles();
+ if (role < roleStrings.count())
+ return roleStrings.at(role);
+ else
+ return QString();
+}
+
+
+ModelNode::ModelNode(NestedListModel_1 *model)
+: modelCache(0), objectCache(0), isArray(false), m_model(model), listIndex(-1)
+{
+}
+
+ModelNode::~ModelNode()
+{
+ clear();
+ if (modelCache) { modelCache->m_nested->_root = 0/* ==this */; delete modelCache; modelCache = 0; }
+ if (objectCache) { delete objectCache; objectCache = 0; }
+}
+
+void ModelNode::clear()
+{
+ ModelNode *node;
+ for (int ii = 0; ii < values.count(); ++ii) {
+ node = qvariant_cast<ModelNode *>(values.at(ii));
+ if (node) { delete node; node = 0; }
+ }
+ values.clear();
+
+ qDeleteAll(properties.values());
+ properties.clear();
+}
+
+bool ModelNode::setObjectValue(const QScriptValue& valuemap, bool writeToCache)
+{
+ bool emitItemsChanged = false;
+
+ QScriptValueIterator it(valuemap);
+ while (it.hasNext()) {
+ it.next();
+ ModelNode *prev = properties.value(it.name());
+ ModelNode *value = new ModelNode(m_model);
+ QScriptValue v = it.value();
+
+ if (v.isArray()) {
+ value->isArray = true;
+ value->setListValue(v);
+ if (writeToCache && objectCache)
+ objectCache->setValue(it.name().toUtf8(), QVariant::fromValue(value->model(m_model)));
+ emitItemsChanged = true; // for now, too inefficient to check whether list and sublists have changed
+ } else {
+ value->values << v.toVariant();
+ if (writeToCache && objectCache)
+ objectCache->setValue(it.name().toUtf8(), value->values.last());
+ if (!emitItemsChanged && prev && prev->values.count() == 1
+ && prev->values[0] != value->values.last()) {
+ emitItemsChanged = true;
+ }
+ }
+ if (properties.contains(it.name()))
+ delete properties[it.name()];
+ properties.insert(it.name(), value);
+ }
+ return emitItemsChanged;
+}
+
+void ModelNode::setListValue(const QScriptValue& valuelist) {
+ values.clear();
+ int size = valuelist.property(QLatin1String("length")).toInt32();
+ for (int i=0; i<size; i++) {
+ ModelNode *value = new ModelNode(m_model);
+ QScriptValue v = valuelist.property(i);
+ if (v.isArray()) {
+ value->isArray = true;
+ value->setListValue(v);
+ } else if (v.isObject()) {
+ value->listIndex = i;
+ value->setObjectValue(v);
+ } else {
+ value->listIndex = i;
+ value->values << v.toVariant();
+ }
+ values.append(QVariant::fromValue(value));
+ }
+}
+
+bool ModelNode::setProperty(const QString& prop, const QVariant& val) {
+ QHash<QString, ModelNode *>::const_iterator it = properties.find(prop);
+ bool emitItemsChanged = false;
+ if (it != properties.end()) {
+ if (val != (*it)->values[0])
+ emitItemsChanged = true;
+ (*it)->values[0] = val;
+ } else {
+ ModelNode *n = new ModelNode(m_model);
+ n->values << val;
+ properties.insert(prop,n);
+ }
+ if (objectCache)
+ objectCache->setValue(prop.toUtf8(), val);
+ return emitItemsChanged;
+}
+
+void ModelNode::updateListIndexes()
+{
+ for (QHash<QString, ModelNode *>::ConstIterator iter = properties.begin(); iter != properties.end(); ++iter) {
+ ModelNode *node = iter.value();
+ if (node->isArray) {
+ for (int i=0; i<node->values.count(); ++i) {
+ ModelNode *subNode = qvariant_cast<ModelNode *>(node->values.at(i));
+ if (subNode)
+ subNode->listIndex = i;
+ }
+ }
+ node->updateListIndexes();
+ }
+}
+
+/*
+ Need to call this to emit itemsChanged() for modifications outside of set()
+ and setProperty(), i.e. if an item returned from get() is modified
+*/
+void ModelNode::changedProperty(const QString &name) const
+{
+ if (listIndex < 0)
+ return;
+
+ m_model->checkRoles();
+ QList<int> roles;
+ int role = m_model->roleStrings.indexOf(name);
+ if (role < 0)
+ roles = m_model->roles();
+ else
+ roles << role;
+ emit m_model->m_listModel->itemsChanged(listIndex, 1, roles);
+}
+
+void ModelNode::dump(ModelNode *node, int ind)
+{
+ QByteArray indentBa(ind * 4, ' ');
+ const char *indent = indentBa.constData();
+
+ for (int ii = 0; ii < node->values.count(); ++ii) {
+ ModelNode *subNode = qvariant_cast<ModelNode *>(node->values.at(ii));
+ if (subNode) {
+ qWarning().nospace() << indent << "Sub-node " << ii;
+ dump(subNode, ind + 1);
+ } else {
+ qWarning().nospace() << indent << "Sub-node " << ii << ": " << node->values.at(ii).toString();
+ }
+ }
+
+ for (QHash<QString, ModelNode *>::ConstIterator iter = node->properties.begin(); iter != node->properties.end(); ++iter) {
+ qWarning().nospace() << indent << "Property " << iter.key() << ':';
+ dump(iter.value(), ind + 1);
+ }
+}
+
+ModelObject_1::ModelObject_1(ModelNode *node, NestedListModel_1 *model, QScriptEngine *seng)
+ : m_model(model),
+ m_node(node),
+ m_meta(new ModelNodeMetaObject_1(seng, this))
+{
+}
+
+void ModelObject_1::setValue(const QByteArray &name, const QVariant &val)
+{
+ m_meta->setValue(name, val);
+ //setProperty(name.constData(), val);
+}
+
+void ModelObject_1::setNodeUpdatesEnabled(bool enable)
+{
+ m_meta->m_enabled = enable;
+}
+
+
+ModelNodeMetaObject_1::ModelNodeMetaObject_1(QScriptEngine *seng, ModelObject_1 *object)
+ : QDeclarative1OpenMetaObject(object),
+ m_enabled(false),
+ m_seng(seng),
+ m_obj(object)
+{
+}
+
+void ModelNodeMetaObject_1::propertyWritten(int index)
+{
+ if (!m_enabled)
+ return;
+
+ QString propName = QString::fromUtf8(name(index));
+ QVariant value = operator[](index);
+
+ QScriptValue sv = m_seng->newObject();
+ sv.setProperty(propName, m_seng->newVariant(value));
+ bool changed = m_obj->m_node->setObjectValue(sv, false);
+ if (changed)
+ m_obj->m_node->changedProperty(propName);
+}
+
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/util/qdeclarativelistmodel_p.h b/src/qtquick1/util/qdeclarativelistmodel_p.h
new file mode 100644
index 0000000000..21398f7213
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativelistmodel_p.h
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVELISTMODEL_H
+#define QDECLARATIVELISTMODEL_H
+
+#include <QtDeclarative/qdeclarative.h>
+#include <QtDeclarative/private/qdeclarativecustomparser_p.h>
+
+#include <QtCore/QObject>
+#include <QtCore/QStringList>
+#include <QtCore/QHash>
+#include <QtCore/QList>
+#include <QtCore/QVariant>
+#include <QtQuick1/private/qlistmodelinterface_p.h>
+#include <QtScript/qscriptvalue.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class FlatListModel_1;
+class NestedListModel_1;
+class QDeclarative1ListModelWorkerAgent;
+struct ModelNode;
+class FlatListScriptClass_1;
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarative1ListModel : public QListModelInterface
+{
+ Q_OBJECT
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+
+public:
+ QDeclarative1ListModel(QObject *parent=0);
+ ~QDeclarative1ListModel();
+
+ virtual QList<int> roles() const;
+ virtual QString toString(int role) const;
+ virtual int count() const;
+ virtual QVariant data(int index, int role) const;
+
+ Q_INVOKABLE void clear();
+ Q_INVOKABLE void remove(int index);
+ Q_INVOKABLE void append(const QScriptValue&);
+ Q_INVOKABLE void insert(int index, const QScriptValue&);
+ Q_INVOKABLE QScriptValue get(int index) const;
+ Q_INVOKABLE void set(int index, const QScriptValue&);
+ Q_INVOKABLE void setProperty(int index, const QString& property, const QVariant& value);
+ Q_INVOKABLE void move(int from, int to, int count);
+ Q_INVOKABLE void sync();
+
+ QDeclarative1ListModelWorkerAgent *agent();
+
+Q_SIGNALS:
+ void countChanged();
+
+private:
+ friend class QDeclarative1ListModelParser;
+ friend class QDeclarative1ListModelWorkerAgent;
+ friend class FlatListModel_1;
+ friend class FlatListScriptClass_1;
+ friend struct ModelNode;
+
+ // Constructs a flat list model for a worker agent
+ QDeclarative1ListModel(const QDeclarative1ListModel *orig, QDeclarative1ListModelWorkerAgent *parent);
+
+ void set(int index, const QScriptValue&, QList<int> *roles);
+ void setProperty(int index, const QString& property, const QVariant& value, QList<int> *roles);
+
+ bool flatten();
+ bool inWorkerThread() const;
+
+ inline bool canMove(int from, int to, int n) const { return !(from+n > count() || to+n > count() || from < 0 || to < 0 || n < 0); }
+
+ QDeclarative1ListModelWorkerAgent *m_agent;
+ NestedListModel_1 *m_nested;
+ FlatListModel_1 *m_flat;
+};
+
+// ### FIXME
+class QDeclarative1ListElement : public QObject
+{
+Q_OBJECT
+};
+
+class QDeclarative1ListModelParser : public QDeclarativeCustomParser
+{
+public:
+ QByteArray compile(const QList<QDeclarativeCustomParserProperty> &);
+ void setCustomData(QObject *, const QByteArray &);
+
+private:
+ struct ListInstruction
+ {
+ enum { Push, Pop, Value, Set } type;
+ int dataIdx;
+ };
+ struct ListModelData
+ {
+ int dataOffset;
+ int instrCount;
+ ListInstruction *instructions() const;
+ };
+ bool compileProperty(const QDeclarativeCustomParserProperty &prop, QList<ListInstruction> &instr, QByteArray &data);
+
+ bool definesEmptyList(const QString &);
+
+ QByteArray listElementTypeName;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1ListModel)
+QML_DECLARE_TYPE(QDeclarative1ListElement)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVELISTMODEL_H
diff --git a/src/qtquick1/util/qdeclarativelistmodel_p_p.h b/src/qtquick1/util/qdeclarativelistmodel_p_p.h
new file mode 100644
index 0000000000..e34f6d850d
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativelistmodel_p_p.h
@@ -0,0 +1,281 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVELISTMODEL_P_P_H
+#define QDECLARATIVELISTMODEL_P_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtDeclarative/private/qdeclarativeengine_p.h>
+#include "QtQuick1/private/qdeclarativelistmodel_p.h"
+#include "QtQuick1/private/qdeclarativeopenmetaobject_p.h"
+#include <QtDeclarative/qdeclarative.h>
+
+#include <QtScript/private/qscriptdeclarativeclass_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QScriptEngine;
+
+QT_MODULE(Declarative)
+
+class QDeclarative1OpenMetaObject;
+class QDeclarative1ListModelWorkerAgent;
+struct ModelNode;
+class FlatListScriptClass_1;
+class FlatNodeData_1;
+
+class FlatListModel_1
+{
+public:
+ FlatListModel_1(QDeclarative1ListModel *base);
+ ~FlatListModel_1();
+
+ QVariant data(int index, int role) const;
+
+ QList<int> roles() const;
+ QString toString(int role) const;
+
+ int count() const;
+ void clear();
+ void remove(int index);
+ bool insert(int index, const QScriptValue&);
+ QScriptValue get(int index) const;
+ void set(int index, const QScriptValue&, QList<int> *roles);
+ void setProperty(int index, const QString& property, const QVariant& value, QList<int> *roles);
+ void move(int from, int to, int count);
+
+private:
+ friend class QDeclarative1ListModelWorkerAgent;
+ friend class QDeclarative1ListModel;
+ friend class FlatListScriptClass_1;
+ friend class FlatNodeData_1;
+
+ bool addValue(const QScriptValue &value, QHash<int, QVariant> *row, QList<int> *roles);
+ void insertedNode(int index);
+ void removedNode(int index);
+ void moveNodes(int from, int to, int n);
+
+ QScriptEngine *m_scriptEngine;
+ QHash<int, QString> m_roles;
+ QHash<QString, int> m_strings;
+ QList<QHash<int, QVariant> > m_values;
+ QDeclarative1ListModel *m_listModel;
+
+ FlatListScriptClass_1 *m_scriptClass;
+ QList<FlatNodeData_1 *> m_nodeData;
+ QDeclarative1ListModelWorkerAgent *m_parentAgent;
+};
+
+
+/*
+ Created when get() is called on a FlatListModel_1. This allows changes to the
+ object returned by get() to be tracked, and passed onto the model.
+*/
+class FlatListScriptClass_1 : public QScriptDeclarativeClass
+{
+public:
+ FlatListScriptClass_1(FlatListModel_1 *model, QScriptEngine *seng);
+
+ Value property(Object *, const Identifier &);
+ void setProperty(Object *, const Identifier &name, const QScriptValue &);
+ QScriptClass::QueryFlags queryProperty(Object *, const Identifier &, QScriptClass::QueryFlags flags);
+ bool compare(Object *, Object *);
+
+private:
+ FlatListModel_1 *m_model;
+};
+
+/*
+ FlatNodeData_1 and FlatNodeObjectData allow objects returned by get() to still
+ point to the correct list index if move(), insert() or remove() are called.
+*/
+struct FlatNodeObjectData;
+class FlatNodeData_1
+{
+public:
+ FlatNodeData_1(int i)
+ : index(i) {}
+
+ ~FlatNodeData_1();
+
+ void addData(FlatNodeObjectData *data);
+ void removeData(FlatNodeObjectData *data);
+
+ int index;
+
+private:
+ QSet<FlatNodeObjectData*> objects;
+};
+
+struct FlatNodeObjectData : public QScriptDeclarativeClass::Object
+{
+ FlatNodeObjectData(FlatNodeData_1 *data) : nodeData(data) {
+ nodeData->addData(this);
+ }
+
+ ~FlatNodeObjectData() {
+ if (nodeData)
+ nodeData->removeData(this);
+ }
+
+ FlatNodeData_1 *nodeData;
+};
+
+
+
+class NestedListModel_1
+{
+public:
+ NestedListModel_1(QDeclarative1ListModel *base);
+ ~NestedListModel_1();
+
+ QHash<int,QVariant> data(int index, const QList<int> &roles, bool *hasNested = 0) const;
+ QVariant data(int index, int role) const;
+
+ QList<int> roles() const;
+ QString toString(int role) const;
+
+ int count() const;
+ void clear();
+ void remove(int index);
+ bool insert(int index, const QScriptValue&);
+ QScriptValue get(int index) const;
+ void set(int index, const QScriptValue&, QList<int> *roles);
+ void setProperty(int index, const QString& property, const QVariant& value, QList<int> *roles);
+ void move(int from, int to, int count);
+
+ QVariant valueForNode(ModelNode *, bool *hasNested = 0) const;
+ void checkRoles() const;
+
+ ModelNode *_root;
+ bool m_ownsRoot;
+ QDeclarative1ListModel *m_listModel;
+
+private:
+ friend struct ModelNode;
+ mutable QStringList roleStrings;
+ mutable bool _rolesOk;
+};
+
+
+class ModelNodeMetaObject_1;
+class ModelObject_1 : public QObject
+{
+ Q_OBJECT
+public:
+ ModelObject_1(ModelNode *node, NestedListModel_1 *model, QScriptEngine *seng);
+ void setValue(const QByteArray &name, const QVariant &val);
+ void setNodeUpdatesEnabled(bool enable);
+
+ NestedListModel_1 *m_model;
+ ModelNode *m_node;
+
+private:
+ ModelNodeMetaObject_1 *m_meta;
+};
+
+class ModelNodeMetaObject_1 : public QDeclarative1OpenMetaObject
+{
+public:
+ ModelNodeMetaObject_1(QScriptEngine *seng, ModelObject_1 *object);
+
+ bool m_enabled;
+
+protected:
+ void propertyWritten(int index);
+
+private:
+ QScriptEngine *m_seng;
+ ModelObject_1 *m_obj;
+};
+
+
+/*
+ A ModelNode is created for each item in a NestedListModel_1.
+*/
+struct ModelNode
+{
+ ModelNode(NestedListModel_1 *model);
+ ~ModelNode();
+
+ QList<QVariant> values;
+ QHash<QString, ModelNode *> properties;
+
+ void clear();
+
+ QDeclarative1ListModel *model(const NestedListModel_1 *model);
+ ModelObject_1 *object(const NestedListModel_1 *model);
+
+ bool setObjectValue(const QScriptValue& valuemap, bool writeToCache = true);
+ void setListValue(const QScriptValue& valuelist);
+ bool setProperty(const QString& prop, const QVariant& val);
+ void changedProperty(const QString &name) const;
+ void updateListIndexes();
+ static void dump(ModelNode *node, int ind);
+
+ QDeclarative1ListModel *modelCache;
+ ModelObject_1 *objectCache;
+ bool isArray;
+
+ NestedListModel_1 *m_model;
+ int listIndex; // only used for top-level nodes within a list
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(ModelNode *)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVELISTMODEL_P_P_H
+
diff --git a/src/qtquick1/util/qdeclarativelistmodelworkeragent.cpp b/src/qtquick1/util/qdeclarativelistmodelworkeragent.cpp
new file mode 100644
index 0000000000..903f700ee3
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativelistmodelworkeragent.cpp
@@ -0,0 +1,282 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativelistmodelworkeragent_p.h"
+#include "QtQuick1/private/qdeclarativelistmodel_p_p.h"
+#include <QtDeclarative/private/qdeclarativedata_p.h>
+#include <QtDeclarative/private/qdeclarativeengine_p.h>
+#include <QtDeclarative/qdeclarativeinfo.h>
+
+#include <QtCore/qcoreevent.h>
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qdebug.h>
+
+
+QT_BEGIN_NAMESPACE
+
+
+
+
+void QDeclarative1ListModelWorkerAgent::Data::clearChange()
+{
+ changes.clear();
+}
+
+void QDeclarative1ListModelWorkerAgent::Data::insertChange(int index, int count)
+{
+ Change c = { Change::Inserted, index, count, 0, QList<int>() };
+ changes << c;
+}
+
+void QDeclarative1ListModelWorkerAgent::Data::removeChange(int index, int count)
+{
+ Change c = { Change::Removed, index, count, 0, QList<int>() };
+ changes << c;
+}
+
+void QDeclarative1ListModelWorkerAgent::Data::moveChange(int index, int count, int to)
+{
+ Change c = { Change::Moved, index, count, to, QList<int>() };
+ changes << c;
+}
+
+void QDeclarative1ListModelWorkerAgent::Data::changedChange(int index, int count, const QList<int> &roles)
+{
+ Change c = { Change::Changed, index, count, 0, roles };
+ changes << c;
+}
+
+QDeclarative1ListModelWorkerAgent::QDeclarative1ListModelWorkerAgent(QDeclarative1ListModel *model)
+ : m_engine(0),
+ m_ref(1),
+ m_orig(model),
+ m_copy(new QDeclarative1ListModel(model, this))
+{
+}
+
+QDeclarative1ListModelWorkerAgent::~QDeclarative1ListModelWorkerAgent()
+{
+}
+
+void QDeclarative1ListModelWorkerAgent::setScriptEngine(QScriptEngine *eng)
+{
+ m_engine = eng;
+ if (m_copy->m_flat)
+ m_copy->m_flat->m_scriptEngine = eng;
+}
+
+QScriptEngine *QDeclarative1ListModelWorkerAgent::scriptEngine() const
+{
+ return m_engine;
+}
+
+void QDeclarative1ListModelWorkerAgent::addref()
+{
+ m_ref.ref();
+}
+
+void QDeclarative1ListModelWorkerAgent::release()
+{
+ bool del = !m_ref.deref();
+
+ if (del)
+ delete this;
+}
+
+int QDeclarative1ListModelWorkerAgent::count() const
+{
+ return m_copy->count();
+}
+
+void QDeclarative1ListModelWorkerAgent::clear()
+{
+ data.clearChange();
+ data.removeChange(0, m_copy->count());
+ m_copy->clear();
+}
+
+void QDeclarative1ListModelWorkerAgent::remove(int index)
+{
+ int count = m_copy->count();
+ m_copy->remove(index);
+
+ if (m_copy->count() != count)
+ data.removeChange(index, 1);
+}
+
+void QDeclarative1ListModelWorkerAgent::append(const QScriptValue &value)
+{
+ int count = m_copy->count();
+ m_copy->append(value);
+
+ if (m_copy->count() != count)
+ data.insertChange(m_copy->count() - 1, 1);
+}
+
+void QDeclarative1ListModelWorkerAgent::insert(int index, const QScriptValue &value)
+{
+ int count = m_copy->count();
+ m_copy->insert(index, value);
+
+ if (m_copy->count() != count)
+ data.insertChange(index, 1);
+}
+
+QScriptValue QDeclarative1ListModelWorkerAgent::get(int index) const
+{
+ return m_copy->get(index);
+}
+
+void QDeclarative1ListModelWorkerAgent::set(int index, const QScriptValue &value)
+{
+ QList<int> roles;
+ m_copy->set(index, value, &roles);
+ if (!roles.isEmpty())
+ data.changedChange(index, 1, roles);
+}
+
+void QDeclarative1ListModelWorkerAgent::setProperty(int index, const QString& property, const QVariant& value)
+{
+ QList<int> roles;
+ m_copy->setProperty(index, property, value, &roles);
+ if (!roles.isEmpty())
+ data.changedChange(index, 1, roles);
+}
+
+void QDeclarative1ListModelWorkerAgent::move(int from, int to, int count)
+{
+ m_copy->move(from, to, count);
+ data.moveChange(from, to, count);
+}
+
+void QDeclarative1ListModelWorkerAgent::sync()
+{
+ Sync *s = new Sync;
+ s->data = data;
+ s->list = m_copy;
+ data.changes.clear();
+
+ mutex.lock();
+ QCoreApplication::postEvent(this, s);
+ syncDone.wait(&mutex);
+ mutex.unlock();
+}
+
+void QDeclarative1ListModelWorkerAgent::changedData(int index, int count, const QList<int> &roles)
+{
+ data.changedChange(index, count, roles);
+}
+
+bool QDeclarative1ListModelWorkerAgent::event(QEvent *e)
+{
+ if (e->type() == QEvent::User) {
+ QMutexLocker locker(&mutex);
+ Sync *s = static_cast<Sync *>(e);
+
+ const QList<Change> &changes = s->data.changes;
+
+ if (m_copy) {
+ bool cc = m_orig->count() != s->list->count();
+
+ FlatListModel_1 *orig = m_orig->m_flat;
+ FlatListModel_1 *copy = s->list->m_flat;
+ if (!orig || !copy) {
+ syncDone.wakeAll();
+ return QObject::event(e);
+ }
+
+ orig->m_roles = copy->m_roles;
+ orig->m_strings = copy->m_strings;
+ orig->m_values = copy->m_values;
+
+ // update the orig->m_nodeData list
+ for (int ii = 0; ii < changes.count(); ++ii) {
+ const Change &change = changes.at(ii);
+ switch (change.type) {
+ case Change::Inserted:
+ orig->insertedNode(change.index);
+ break;
+ case Change::Removed:
+ orig->removedNode(change.index);
+ break;
+ case Change::Moved:
+ orig->moveNodes(change.index, change.to, change.count);
+ break;
+ case Change::Changed:
+ break;
+ }
+ }
+
+ syncDone.wakeAll();
+ locker.unlock();
+
+ for (int ii = 0; ii < changes.count(); ++ii) {
+ const Change &change = changes.at(ii);
+ switch (change.type) {
+ case Change::Inserted:
+ emit m_orig->itemsInserted(change.index, change.count);
+ break;
+ case Change::Removed:
+ emit m_orig->itemsRemoved(change.index, change.count);
+ break;
+ case Change::Moved:
+ emit m_orig->itemsMoved(change.index, change.to, change.count);
+ break;
+ case Change::Changed:
+ emit m_orig->itemsChanged(change.index, change.count, change.roles);
+ break;
+ }
+ }
+
+ if (cc)
+ emit m_orig->countChanged();
+ } else {
+ syncDone.wakeAll();
+ }
+ }
+
+ return QObject::event(e);
+}
+
+
+
+QT_END_NAMESPACE
+
diff --git a/src/qtquick1/util/qdeclarativelistmodelworkeragent_p.h b/src/qtquick1/util/qdeclarativelistmodelworkeragent_p.h
new file mode 100644
index 0000000000..f0979c4b31
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativelistmodelworkeragent_p.h
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVELISTMODELWORKERAGENT_P_H
+#define QDECLARATIVELISTMODELWORKERAGENT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtDeclarative/qdeclarative.h>
+
+#include <QtScript/qscriptvalue.h>
+#include <QtGui/qevent.h>
+#include <QMutex>
+#include <QWaitCondition>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarative1ListModel;
+class FlatListScriptClass_1;
+
+class QDeclarative1ListModelWorkerAgent : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int count READ count)
+
+public:
+ QDeclarative1ListModelWorkerAgent(QDeclarative1ListModel *);
+ ~QDeclarative1ListModelWorkerAgent();
+
+ void setScriptEngine(QScriptEngine *eng);
+ QScriptEngine *scriptEngine() const;
+
+ void addref();
+ void release();
+
+ int count() const;
+
+ Q_INVOKABLE void clear();
+ Q_INVOKABLE void remove(int index);
+ Q_INVOKABLE void append(const QScriptValue &);
+ Q_INVOKABLE void insert(int index, const QScriptValue&);
+ Q_INVOKABLE QScriptValue get(int index) const;
+ Q_INVOKABLE void set(int index, const QScriptValue &);
+ Q_INVOKABLE void setProperty(int index, const QString& property, const QVariant& value);
+ Q_INVOKABLE void move(int from, int to, int count);
+ Q_INVOKABLE void sync();
+
+ struct VariantRef
+ {
+ VariantRef() : a(0) {}
+ VariantRef(const VariantRef &r) : a(r.a) { if (a) a->addref(); }
+ VariantRef(QDeclarative1ListModelWorkerAgent *_a) : a(_a) { if (a) a->addref(); }
+ ~VariantRef() { if (a) a->release(); }
+
+ VariantRef &operator=(const VariantRef &o) {
+ if (o.a) o.a->addref();
+ if (a) a->release(); a = o.a;
+ return *this;
+ }
+
+ QDeclarative1ListModelWorkerAgent *a;
+ };
+protected:
+ virtual bool event(QEvent *);
+
+private:
+ friend class QDeclarative1WorkerScriptEnginePrivate;
+ friend class FlatListScriptClass_1;
+ QScriptEngine *m_engine;
+
+ struct Change {
+ enum { Inserted, Removed, Moved, Changed } type;
+ int index; // Inserted/Removed/Moved/Changed
+ int count; // Inserted/Removed/Moved/Changed
+ int to; // Moved
+ QList<int> roles;
+ };
+
+ struct Data {
+ QList<Change> changes;
+
+ void clearChange();
+ void insertChange(int index, int count);
+ void removeChange(int index, int count);
+ void moveChange(int index, int count, int to);
+ void changedChange(int index, int count, const QList<int> &roles);
+ };
+ Data data;
+
+ struct Sync : public QEvent {
+ Sync() : QEvent(QEvent::User) {}
+ Data data;
+ QDeclarative1ListModel *list;
+ };
+
+ void changedData(int index, int count, const QList<int> &roles);
+
+ QAtomicInt m_ref;
+ QDeclarative1ListModel *m_orig;
+ QDeclarative1ListModel *m_copy;
+ QMutex mutex;
+ QWaitCondition syncDone;
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QDeclarative1ListModelWorkerAgent::VariantRef)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEWORKERSCRIPT_P_H
+
diff --git a/src/qtquick1/util/qdeclarativeopenmetaobject.cpp b/src/qtquick1/util/qdeclarativeopenmetaobject.cpp
new file mode 100644
index 0000000000..b4864a9a7c
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativeopenmetaobject.cpp
@@ -0,0 +1,384 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativeopenmetaobject_p.h"
+#include "QtDeclarative/private/qdeclarativepropertycache_p.h"
+#include "QtDeclarative/private/qdeclarativedata_p.h"
+#include <QtDeclarative/private/qmetaobjectbuilder_p.h>
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+
+
+
+class QDeclarative1OpenMetaObjectTypePrivate
+{
+public:
+ QDeclarative1OpenMetaObjectTypePrivate() : mem(0), cache(0), engine(0) {}
+
+ void init(const QMetaObject *metaObj);
+
+ int propertyOffset;
+ int signalOffset;
+ QHash<QByteArray, int> names;
+ QMetaObjectBuilder mob;
+ QMetaObject *mem;
+ QDeclarativePropertyCache *cache;
+ QDeclarativeEngine *engine;
+ QSet<QDeclarative1OpenMetaObject*> referers;
+};
+
+QDeclarative1OpenMetaObjectType::QDeclarative1OpenMetaObjectType(const QMetaObject *base, QDeclarativeEngine *engine)
+ : d(new QDeclarative1OpenMetaObjectTypePrivate)
+{
+ d->engine = engine;
+ d->init(base);
+}
+
+QDeclarative1OpenMetaObjectType::~QDeclarative1OpenMetaObjectType()
+{
+ if (d->mem)
+ qFree(d->mem);
+ if (d->cache)
+ d->cache->release();
+ delete d;
+}
+
+
+int QDeclarative1OpenMetaObjectType::propertyOffset() const
+{
+ return d->propertyOffset;
+}
+
+int QDeclarative1OpenMetaObjectType::signalOffset() const
+{
+ return d->signalOffset;
+}
+
+int QDeclarative1OpenMetaObjectType::createProperty(const QByteArray &name)
+{
+ int id = d->mob.propertyCount();
+ d->mob.addSignal("__" + QByteArray::number(id) + "()");
+ QMetaPropertyBuilder build = d->mob.addProperty(name, "QVariant", id);
+ propertyCreated(id, build);
+ qFree(d->mem);
+ d->mem = d->mob.toMetaObject();
+ d->names.insert(name, id);
+ QSet<QDeclarative1OpenMetaObject*>::iterator it = d->referers.begin();
+ while (it != d->referers.end()) {
+ QDeclarative1OpenMetaObject *omo = *it;
+ *static_cast<QMetaObject *>(omo) = *d->mem;
+ if (d->cache)
+ d->cache->update(d->engine, omo);
+ ++it;
+ }
+
+ return d->propertyOffset + id;
+}
+
+void QDeclarative1OpenMetaObjectType::propertyCreated(int id, QMetaPropertyBuilder &builder)
+{
+ if (d->referers.count())
+ (*d->referers.begin())->propertyCreated(id, builder);
+}
+
+void QDeclarative1OpenMetaObjectTypePrivate::init(const QMetaObject *metaObj)
+{
+ if (!mem) {
+ mob.setSuperClass(metaObj);
+ mob.setClassName(metaObj->className());
+ mob.setFlags(QMetaObjectBuilder::DynamicMetaObject);
+
+ mem = mob.toMetaObject();
+
+ propertyOffset = mem->propertyOffset();
+ signalOffset = mem->methodOffset();
+ }
+}
+
+//----------------------------------------------------------------------------
+
+class QDeclarative1OpenMetaObjectPrivate
+{
+public:
+ QDeclarative1OpenMetaObjectPrivate(QDeclarative1OpenMetaObject *_q)
+ : q(_q), parent(0), type(0), cacheProperties(false) {}
+
+ inline QVariant &getData(int idx) {
+ while (data.count() <= idx)
+ data << QPair<QVariant, bool>(QVariant(), false);
+ QPair<QVariant, bool> &prop = data[idx];
+ if (!prop.second) {
+ prop.first = q->initialValue(idx);
+ prop.second = true;
+ }
+ return prop.first;
+ }
+
+ inline void writeData(int idx, const QVariant &value) {
+ while (data.count() <= idx)
+ data << QPair<QVariant, bool>(QVariant(), false);
+ QPair<QVariant, bool> &prop = data[idx];
+ prop.first = value;
+ prop.second = true;
+ }
+
+ inline bool hasData(int idx) const {
+ if (idx >= data.count())
+ return false;
+ return data[idx].second;
+ }
+
+ bool autoCreate;
+ QDeclarative1OpenMetaObject *q;
+ QAbstractDynamicMetaObject *parent;
+ QList<QPair<QVariant, bool> > data;
+ QObject *object;
+ QDeclarative1OpenMetaObjectType *type;
+ bool cacheProperties;
+};
+
+QDeclarative1OpenMetaObject::QDeclarative1OpenMetaObject(QObject *obj, bool automatic)
+: d(new QDeclarative1OpenMetaObjectPrivate(this))
+{
+ d->autoCreate = automatic;
+ d->object = obj;
+
+ d->type = new QDeclarative1OpenMetaObjectType(obj->metaObject(), 0);
+ d->type->d->referers.insert(this);
+
+ QObjectPrivate *op = QObjectPrivate::get(obj);
+ d->parent = static_cast<QAbstractDynamicMetaObject *>(op->metaObject);
+ *static_cast<QMetaObject *>(this) = *d->type->d->mem;
+ op->metaObject = this;
+}
+
+QDeclarative1OpenMetaObject::QDeclarative1OpenMetaObject(QObject *obj, QDeclarative1OpenMetaObjectType *type, bool automatic)
+: d(new QDeclarative1OpenMetaObjectPrivate(this))
+{
+ d->autoCreate = automatic;
+ d->object = obj;
+
+ d->type = type;
+ d->type->addref();
+ d->type->d->referers.insert(this);
+
+ QObjectPrivate *op = QObjectPrivate::get(obj);
+ d->parent = static_cast<QAbstractDynamicMetaObject *>(op->metaObject);
+ *static_cast<QMetaObject *>(this) = *d->type->d->mem;
+ op->metaObject = this;
+}
+
+QDeclarative1OpenMetaObject::~QDeclarative1OpenMetaObject()
+{
+ if (d->parent)
+ delete d->parent;
+ d->type->d->referers.remove(this);
+ d->type->release();
+ delete d;
+}
+
+QDeclarative1OpenMetaObjectType *QDeclarative1OpenMetaObject::type() const
+{
+ return d->type;
+}
+
+int QDeclarative1OpenMetaObject::metaCall(QMetaObject::Call c, int id, void **a)
+{
+ if (( c == QMetaObject::ReadProperty || c == QMetaObject::WriteProperty)
+ && id >= d->type->d->propertyOffset) {
+ int propId = id - d->type->d->propertyOffset;
+ if (c == QMetaObject::ReadProperty) {
+ propertyRead(propId);
+ *reinterpret_cast<QVariant *>(a[0]) = d->getData(propId);
+ } else if (c == QMetaObject::WriteProperty) {
+ if (propId <= d->data.count() || d->data[propId].first != *reinterpret_cast<QVariant *>(a[0])) {
+ propertyWrite(propId);
+ d->writeData(propId, *reinterpret_cast<QVariant *>(a[0]));
+ propertyWritten(propId);
+ activate(d->object, d->type->d->signalOffset + propId, 0);
+ }
+ }
+ return -1;
+ } else {
+ if (d->parent)
+ return d->parent->metaCall(c, id, a);
+ else
+ return d->object->qt_metacall(c, id, a);
+ }
+}
+
+QAbstractDynamicMetaObject *QDeclarative1OpenMetaObject::parent() const
+{
+ return d->parent;
+}
+
+QVariant QDeclarative1OpenMetaObject::value(int id) const
+{
+ return d->getData(id);
+}
+
+void QDeclarative1OpenMetaObject::setValue(int id, const QVariant &value)
+{
+ d->writeData(id, value);
+ activate(d->object, id + d->type->d->signalOffset, 0);
+}
+
+QVariant QDeclarative1OpenMetaObject::value(const QByteArray &name) const
+{
+ QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.find(name);
+ if (iter == d->type->d->names.end())
+ return QVariant();
+
+ return d->getData(*iter);
+}
+
+QVariant &QDeclarative1OpenMetaObject::operator[](const QByteArray &name)
+{
+ QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.find(name);
+ Q_ASSERT(iter != d->type->d->names.end());
+
+ return d->getData(*iter);
+}
+
+QVariant &QDeclarative1OpenMetaObject::operator[](int id)
+{
+ return d->getData(id);
+}
+
+void QDeclarative1OpenMetaObject::setValue(const QByteArray &name, const QVariant &val)
+{
+ QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.find(name);
+
+ int id = -1;
+ if (iter == d->type->d->names.end()) {
+ id = createProperty(name.constData(), "") - d->type->d->propertyOffset;
+ } else {
+ id = *iter;
+ }
+
+ if (id >= 0) {
+ QVariant &dataVal = d->getData(id);
+ if (dataVal == val)
+ return;
+
+ dataVal = val;
+ activate(d->object, id + d->type->d->signalOffset, 0);
+ }
+}
+
+// returns true if this value has been initialized by a call to either value() or setValue()
+bool QDeclarative1OpenMetaObject::hasValue(int id) const
+{
+ return d->hasData(id);
+}
+
+void QDeclarative1OpenMetaObject::setCached(bool c)
+{
+ if (c == d->cacheProperties || !d->type->d->engine)
+ return;
+
+ d->cacheProperties = c;
+
+ QDeclarativeData *qmldata = QDeclarativeData::get(d->object, true);
+ if (d->cacheProperties) {
+ if (!d->type->d->cache)
+ d->type->d->cache = new QDeclarativePropertyCache(d->type->d->engine, this);
+ qmldata->propertyCache = d->type->d->cache;
+ d->type->d->cache->addref();
+ } else {
+ if (d->type->d->cache)
+ d->type->d->cache->release();
+ qmldata->propertyCache = 0;
+ }
+}
+
+
+int QDeclarative1OpenMetaObject::createProperty(const char *name, const char *)
+{
+ if (d->autoCreate)
+ return d->type->createProperty(name);
+ else
+ return -1;
+}
+
+void QDeclarative1OpenMetaObject::propertyRead(int)
+{
+}
+
+void QDeclarative1OpenMetaObject::propertyWrite(int)
+{
+}
+
+void QDeclarative1OpenMetaObject::propertyWritten(int)
+{
+}
+
+void QDeclarative1OpenMetaObject::propertyCreated(int, QMetaPropertyBuilder &)
+{
+}
+
+QVariant QDeclarative1OpenMetaObject::initialValue(int)
+{
+ return QVariant();
+}
+
+int QDeclarative1OpenMetaObject::count() const
+{
+ return d->type->d->names.count();
+}
+
+QByteArray QDeclarative1OpenMetaObject::name(int idx) const
+{
+ Q_ASSERT(idx >= 0 && idx < d->type->d->names.count());
+
+ return d->type->d->mob.property(idx).name();
+}
+
+QObject *QDeclarative1OpenMetaObject::object() const
+{
+ return d->object;
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/util/qdeclarativeopenmetaobject_p.h b/src/qtquick1/util/qdeclarativeopenmetaobject_p.h
new file mode 100644
index 0000000000..3ee6230e71
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativeopenmetaobject_p.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEOPENMETAOBJECT_H
+#define QDECLARATIVEOPENMETAOBJECT_H
+
+#include <QtCore/QMetaObject>
+#include <QtCore/QObject>
+
+#include <QtDeclarative/private/qdeclarativerefcount_p.h>
+#include <QtDeclarative/private/qdeclarativeglobal_p.h>
+#include <QtCore/private/qobject_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeEngine;
+class QMetaPropertyBuilder;
+
+QT_MODULE(Declarative)
+
+class QDeclarative1OpenMetaObjectTypePrivate;
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarative1OpenMetaObjectType : public QDeclarativeRefCount
+{
+public:
+ QDeclarative1OpenMetaObjectType(const QMetaObject *base, QDeclarativeEngine *engine);
+ ~QDeclarative1OpenMetaObjectType();
+
+ int createProperty(const QByteArray &name);
+
+ int propertyOffset() const;
+ int signalOffset() const;
+
+protected:
+ virtual void propertyCreated(int, QMetaPropertyBuilder &);
+
+private:
+ QDeclarative1OpenMetaObjectTypePrivate *d;
+ friend class QDeclarative1OpenMetaObject;
+ friend class QDeclarative1OpenMetaObjectPrivate;
+};
+
+class QDeclarative1OpenMetaObjectPrivate;
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarative1OpenMetaObject : public QAbstractDynamicMetaObject
+{
+public:
+ QDeclarative1OpenMetaObject(QObject *, bool = true);
+ QDeclarative1OpenMetaObject(QObject *, QDeclarative1OpenMetaObjectType *, bool = true);
+ ~QDeclarative1OpenMetaObject();
+
+ QVariant value(const QByteArray &) const;
+ void setValue(const QByteArray &, const QVariant &);
+ QVariant value(int) const;
+ void setValue(int, const QVariant &);
+ QVariant &operator[](const QByteArray &);
+ QVariant &operator[](int);
+ bool hasValue(int) const;
+
+ int count() const;
+ QByteArray name(int) const;
+
+ QObject *object() const;
+ virtual QVariant initialValue(int);
+
+ // Be careful - once setCached(true) is called createProperty() is no
+ // longer automatically called for new properties.
+ void setCached(bool);
+
+ QDeclarative1OpenMetaObjectType *type() const;
+
+protected:
+ virtual int metaCall(QMetaObject::Call _c, int _id, void **_a);
+ virtual int createProperty(const char *, const char *);
+
+ virtual void propertyRead(int);
+ virtual void propertyWrite(int);
+ virtual void propertyWritten(int);
+ virtual void propertyCreated(int, QMetaPropertyBuilder &);
+
+ QAbstractDynamicMetaObject *parent() const;
+
+private:
+ QDeclarative1OpenMetaObjectPrivate *d;
+ friend class QDeclarative1OpenMetaObjectType;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEOPENMETAOBJECT_H
diff --git a/src/qtquick1/util/qdeclarativepackage.cpp b/src/qtquick1/util/qdeclarativepackage.cpp
new file mode 100644
index 0000000000..989a780f6b
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativepackage.cpp
@@ -0,0 +1,205 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativepackage_p.h"
+
+#include <private/qobject_p.h>
+#include <QtDeclarative/private/qdeclarativeguard_p.h>
+
+QT_BEGIN_NAMESPACE
+
+
+
+/*!
+ \qmlclass Package QDeclarative1Package
+ \ingroup qml-working-with-data
+ \brief Package provides a collection of named items.
+
+ The Package class is used in conjunction with
+ VisualDataModel to enable delegates with a shared context
+ to be provided to multiple views.
+
+ Any item within a Package may be assigned a name via the
+ \l{Package::name}{Package.name} attached property.
+
+ The example below creates a Package containing two named items;
+ \e list and \e grid. The third element in the package (the \l Rectangle) is parented to whichever
+ delegate it should appear in. This allows an item to move
+ between views.
+
+ \snippet examples/declarative/modelviews/package/Delegate.qml 0
+
+ These named items are used as the delegates by the two views who
+ reference the special \l{VisualDataModel::parts} property to select
+ a model which provides the chosen delegate.
+
+ \snippet examples/declarative/modelviews/package/view.qml 0
+
+ \sa {declarative/modelviews/package}{Package example}, {demos/declarative/photoviewer}{Photo Viewer demo}, QtDeclarative
+*/
+
+/*!
+ \qmlattachedproperty string Package::name
+ This attached property holds the name of an item within a Package.
+*/
+
+
+class QDeclarative1PackagePrivate : public QObjectPrivate
+{
+public:
+ QDeclarative1PackagePrivate() {}
+
+ struct DataGuard : public QDeclarativeGuard<QObject>
+ {
+ DataGuard(QObject *obj, QList<DataGuard> *l) : list(l) { (QDeclarativeGuard<QObject>&)*this = obj; }
+ QList<DataGuard> *list;
+ void objectDestroyed(QObject *) {
+ // we assume priv will always be destroyed after objectDestroyed calls
+ list->removeOne(*this);
+ }
+ };
+
+ QList<DataGuard> dataList;
+ static void data_append(QDeclarativeListProperty<QObject> *prop, QObject *o) {
+ QList<DataGuard> *list = static_cast<QList<DataGuard> *>(prop->data);
+ list->append(DataGuard(o, list));
+ }
+ static void data_clear(QDeclarativeListProperty<QObject> *prop) {
+ QList<DataGuard> *list = static_cast<QList<DataGuard> *>(prop->data);
+ list->clear();
+ }
+ static QObject *data_at(QDeclarativeListProperty<QObject> *prop, int index) {
+ QList<DataGuard> *list = static_cast<QList<DataGuard> *>(prop->data);
+ return list->at(index);
+ }
+ static int data_count(QDeclarativeListProperty<QObject> *prop) {
+ QList<DataGuard> *list = static_cast<QList<DataGuard> *>(prop->data);
+ return list->count();
+ }
+};
+
+QHash<QObject *, QDeclarative1PackageAttached *> QDeclarative1PackageAttached::attached;
+
+QDeclarative1PackageAttached::QDeclarative1PackageAttached(QObject *parent)
+: QObject(parent)
+{
+ attached.insert(parent, this);
+}
+
+QDeclarative1PackageAttached::~QDeclarative1PackageAttached()
+{
+ attached.remove(parent());
+}
+
+QString QDeclarative1PackageAttached::name() const
+{
+ return _name;
+}
+
+void QDeclarative1PackageAttached::setName(const QString &n)
+{
+ _name = n;
+}
+
+QDeclarative1Package::QDeclarative1Package(QObject *parent)
+ : QObject(*(new QDeclarative1PackagePrivate), parent)
+{
+}
+
+QDeclarative1Package::~QDeclarative1Package()
+{
+ Q_D(QDeclarative1Package);
+ for (int ii = 0; ii < d->dataList.count(); ++ii) {
+ QObject *obj = d->dataList.at(ii);
+ obj->setParent(this);
+ }
+}
+
+QDeclarativeListProperty<QObject> QDeclarative1Package::data()
+{
+ Q_D(QDeclarative1Package);
+ return QDeclarativeListProperty<QObject>(this, &d->dataList, QDeclarative1PackagePrivate::data_append,
+ QDeclarative1PackagePrivate::data_count,
+ QDeclarative1PackagePrivate::data_at,
+ QDeclarative1PackagePrivate::data_clear);
+}
+
+bool QDeclarative1Package::hasPart(const QString &name)
+{
+ Q_D(QDeclarative1Package);
+ for (int ii = 0; ii < d->dataList.count(); ++ii) {
+ QObject *obj = d->dataList.at(ii);
+ QDeclarative1PackageAttached *a = QDeclarative1PackageAttached::attached.value(obj);
+ if (a && a->name() == name)
+ return true;
+ }
+ return false;
+}
+
+QObject *QDeclarative1Package::part(const QString &name)
+{
+ Q_D(QDeclarative1Package);
+ if (name.isEmpty() && !d->dataList.isEmpty())
+ return d->dataList.at(0);
+
+ for (int ii = 0; ii < d->dataList.count(); ++ii) {
+ QObject *obj = d->dataList.at(ii);
+ QDeclarative1PackageAttached *a = QDeclarative1PackageAttached::attached.value(obj);
+ if (a && a->name() == name)
+ return obj;
+ }
+
+ if (name == QLatin1String("default") && !d->dataList.isEmpty())
+ return d->dataList.at(0);
+
+ return 0;
+}
+
+QDeclarative1PackageAttached *QDeclarative1Package::qmlAttachedProperties(QObject *o)
+{
+ return new QDeclarative1PackageAttached(o);
+}
+
+
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/util/qdeclarativepackage_p.h b/src/qtquick1/util/qdeclarativepackage_p.h
new file mode 100644
index 0000000000..33991c9809
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativepackage_p.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEPACKAGE_H
+#define QDECLARATIVEPACKAGE_H
+
+#include <QtDeclarative/qdeclarative.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarative1PackagePrivate;
+class QDeclarative1PackageAttached;
+class Q_AUTOTEST_EXPORT QDeclarative1Package : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarative1Package)
+
+ Q_CLASSINFO("DefaultProperty", "data")
+ Q_PROPERTY(QDeclarativeListProperty<QObject> data READ data SCRIPTABLE false)
+
+public:
+ QDeclarative1Package(QObject *parent=0);
+ virtual ~QDeclarative1Package();
+
+ QDeclarativeListProperty<QObject> data();
+
+ QObject *part(const QString & = QString());
+ bool hasPart(const QString &);
+
+ static QDeclarative1PackageAttached *qmlAttachedProperties(QObject *);
+};
+
+class QDeclarative1PackageAttached : public QObject
+{
+Q_OBJECT
+Q_PROPERTY(QString name READ name WRITE setName)
+public:
+ QDeclarative1PackageAttached(QObject *parent);
+ virtual ~QDeclarative1PackageAttached();
+
+ QString name() const;
+ void setName(const QString &n);
+
+ static QHash<QObject *, QDeclarative1PackageAttached *> attached;
+private:
+ QString _name;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1Package)
+QML_DECLARE_TYPEINFO(QDeclarative1Package, QML_HAS_ATTACHED_PROPERTIES)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEPACKAGE_H
diff --git a/src/qtquick1/util/qdeclarativepixmapcache.cpp b/src/qtquick1/util/qdeclarativepixmapcache.cpp
new file mode 100644
index 0000000000..0b2e16c2ff
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativepixmapcache.cpp
@@ -0,0 +1,1084 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativepixmapcache_p.h"
+#include "QtDeclarative/qdeclarativenetworkaccessmanagerfactory.h"
+#include "QtDeclarative/qdeclarativeimageprovider.h"
+
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/private/qdeclarativeglobal_p.h>
+#include <QtDeclarative/private/qdeclarativeengine_p.h>
+
+#include <QCoreApplication>
+#include <QImageReader>
+#include <QHash>
+#include <QNetworkReply>
+#include <QPixmapCache>
+#include <QFile>
+#include <QThread>
+#include <QMutex>
+#include <QMutexLocker>
+#include <QWaitCondition>
+#include <QBuffer>
+#include <QWaitCondition>
+#include <QtCore/qdebug.h>
+#include <private/qobject_p.h>
+#include <QSslError>
+
+#define IMAGEREQUEST_MAX_REQUEST_COUNT 8
+#define IMAGEREQUEST_MAX_REDIRECT_RECURSION 16
+#define CACHE_EXPIRE_TIME 30
+#define CACHE_REMOVAL_FRACTION 4
+
+QT_BEGIN_NAMESPACE
+
+
+
+// The cache limit describes the maximum "junk" in the cache.
+// These are the same defaults as QPixmapCache
+#if defined(Q_WS_QWS) || defined(Q_WS_WINCE)
+static int cache_limit = 2048 * 1024; // 2048 KB cache limit for embedded
+#else
+static int cache_limit = 10240 * 1024; // 10 MB cache limit for desktop
+#endif
+
+class QDeclarative1PixmapReader;
+class QDeclarative1PixmapData;
+class QDeclarative1PixmapReply : public QObject
+{
+ Q_OBJECT
+public:
+ enum ReadError { NoError, Loading, Decoding };
+
+ QDeclarative1PixmapReply(QDeclarative1PixmapData *);
+ ~QDeclarative1PixmapReply();
+
+ QDeclarative1PixmapData *data;
+ QDeclarative1PixmapReader *reader;
+ QSize requestSize;
+
+ bool loading;
+ int redirectCount;
+
+ class Event : public QEvent {
+ public:
+ Event(ReadError, const QString &, const QSize &, const QImage &);
+
+ ReadError error;
+ QString errorString;
+ QSize implicitSize;
+ QImage image;
+ };
+ void postReply(ReadError, const QString &, const QSize &, const QImage &);
+
+
+Q_SIGNALS:
+ void finished();
+ void downloadProgress(qint64, qint64);
+
+protected:
+ bool event(QEvent *event);
+
+private:
+ Q_DISABLE_COPY(QDeclarative1PixmapReply)
+
+public:
+ static int finishedIndex;
+ static int downloadProgressIndex;
+};
+
+class QDeclarative1PixmapReaderThreadObject : public QObject {
+ Q_OBJECT
+public:
+ QDeclarative1PixmapReaderThreadObject(QDeclarative1PixmapReader *);
+ void processJobs();
+ virtual bool event(QEvent *e);
+private slots:
+ void networkRequestDone();
+private:
+ QDeclarative1PixmapReader *reader;
+};
+
+class QDeclarative1PixmapData;
+class QDeclarative1PixmapReader : public QThread
+{
+ Q_OBJECT
+public:
+ QDeclarative1PixmapReader(QDeclarativeEngine *eng);
+ ~QDeclarative1PixmapReader();
+
+ QDeclarative1PixmapReply *getImage(QDeclarative1PixmapData *);
+ void cancel(QDeclarative1PixmapReply *rep);
+
+ static QDeclarative1PixmapReader *instance(QDeclarativeEngine *engine);
+
+protected:
+ void run();
+
+private:
+ friend class QDeclarative1PixmapReaderThreadObject;
+ void processJobs();
+ void processJob(QDeclarative1PixmapReply *, const QUrl &, const QSize &);
+ void networkRequestDone(QNetworkReply *);
+
+ QList<QDeclarative1PixmapReply*> jobs;
+ QList<QDeclarative1PixmapReply*> cancelled;
+ QDeclarativeEngine *engine;
+ QObject *eventLoopQuitHack;
+
+ QMutex mutex;
+ QDeclarative1PixmapReaderThreadObject *threadObject;
+ QWaitCondition waitCondition;
+
+ QNetworkAccessManager *networkAccessManager();
+ QNetworkAccessManager *accessManager;
+
+ QHash<QNetworkReply*,QDeclarative1PixmapReply*> replies;
+
+ static int replyDownloadProgress;
+ static int replyFinished;
+ static int downloadProgress;
+ static int threadNetworkRequestDone;
+ static QHash<QDeclarativeEngine *,QDeclarative1PixmapReader*> readers;
+ static QMutex readerMutex;
+};
+
+class QDeclarative1PixmapData
+{
+public:
+ QDeclarative1PixmapData(const QUrl &u, const QSize &s, const QString &e)
+ : refCount(1), inCache(false), pixmapStatus(QDeclarative1Pixmap::Error),
+ url(u), errorString(e), requestSize(s), reply(0), prevUnreferenced(0),
+ prevUnreferencedPtr(0), nextUnreferenced(0)
+ {
+ }
+
+ QDeclarative1PixmapData(const QUrl &u, const QSize &r)
+ : refCount(1), inCache(false), pixmapStatus(QDeclarative1Pixmap::Loading),
+ url(u), requestSize(r), reply(0), prevUnreferenced(0), prevUnreferencedPtr(0),
+ nextUnreferenced(0)
+ {
+ }
+
+ QDeclarative1PixmapData(const QUrl &u, const QPixmap &p, const QSize &s, const QSize &r)
+ : refCount(1), inCache(false), privatePixmap(false), pixmapStatus(QDeclarative1Pixmap::Ready),
+ url(u), pixmap(p), implicitSize(s), requestSize(r), reply(0), prevUnreferenced(0),
+ prevUnreferencedPtr(0), nextUnreferenced(0)
+ {
+ }
+
+ QDeclarative1PixmapData(const QPixmap &p)
+ : refCount(1), inCache(false), privatePixmap(true), pixmapStatus(QDeclarative1Pixmap::Ready),
+ pixmap(p), implicitSize(p.size()), requestSize(p.size()), reply(0), prevUnreferenced(0),
+ prevUnreferencedPtr(0), nextUnreferenced(0)
+ {
+ }
+
+ int cost() const;
+ void addref();
+ void release();
+ void addToCache();
+ void removeFromCache();
+
+ uint refCount;
+
+ bool inCache:1;
+ bool privatePixmap:1;
+
+ QDeclarative1Pixmap::Status pixmapStatus;
+ QUrl url;
+ QString errorString;
+ QPixmap pixmap;
+ QSize implicitSize;
+ QSize requestSize;
+
+ QDeclarative1PixmapReply *reply;
+
+ QDeclarative1PixmapData *prevUnreferenced;
+ QDeclarative1PixmapData**prevUnreferencedPtr;
+ QDeclarative1PixmapData *nextUnreferenced;
+};
+
+int QDeclarative1PixmapReply::finishedIndex = -1;
+int QDeclarative1PixmapReply::downloadProgressIndex = -1;
+
+// XXX
+QHash<QDeclarativeEngine *,QDeclarative1PixmapReader*> QDeclarative1PixmapReader::readers;
+QMutex QDeclarative1PixmapReader::readerMutex;
+
+int QDeclarative1PixmapReader::replyDownloadProgress = -1;
+int QDeclarative1PixmapReader::replyFinished = -1;
+int QDeclarative1PixmapReader::downloadProgress = -1;
+int QDeclarative1PixmapReader::threadNetworkRequestDone = -1;
+
+
+void QDeclarative1PixmapReply::postReply(ReadError error, const QString &errorString,
+ const QSize &implicitSize, const QImage &image)
+{
+ loading = false;
+ QCoreApplication::postEvent(this, new Event(error, errorString, implicitSize, image));
+}
+
+QDeclarative1PixmapReply::Event::Event(ReadError e, const QString &s, const QSize &iSize, const QImage &i)
+: QEvent(QEvent::User), error(e), errorString(s), implicitSize(iSize), image(i)
+{
+}
+
+QNetworkAccessManager *QDeclarative1PixmapReader::networkAccessManager()
+{
+ if (!accessManager) {
+ Q_ASSERT(threadObject);
+ accessManager = QDeclarativeEnginePrivate::get(engine)->createNetworkAccessManager(threadObject);
+ }
+ return accessManager;
+}
+
+static bool readImage(const QUrl& url, QIODevice *dev, QImage *image, QString *errorString, QSize *impsize,
+ const QSize &requestSize)
+{
+ QImageReader imgio(dev);
+
+ bool force_scale = false;
+ if (url.path().endsWith(QLatin1String(".svg"),Qt::CaseInsensitive)) {
+ imgio.setFormat("svg"); // QSvgPlugin::capabilities bug QTBUG-9053
+ force_scale = true;
+ }
+
+ bool scaled = false;
+ if (requestSize.width() > 0 || requestSize.height() > 0) {
+ QSize s = imgio.size();
+ if (requestSize.width() && (force_scale || requestSize.width() < s.width())) {
+ if (requestSize.height() <= 0)
+ s.setHeight(s.height()*requestSize.width()/s.width());
+ s.setWidth(requestSize.width()); scaled = true;
+ }
+ if (requestSize.height() && (force_scale || requestSize.height() < s.height())) {
+ if (requestSize.width() <= 0)
+ s.setWidth(s.width()*requestSize.height()/s.height());
+ s.setHeight(requestSize.height()); scaled = true;
+ }
+ if (scaled) { imgio.setScaledSize(s); }
+ }
+
+ if (impsize)
+ *impsize = imgio.size();
+
+ if (imgio.read(image)) {
+ if (impsize && impsize->width() < 0)
+ *impsize = image->size();
+ return true;
+ } else {
+ if (errorString)
+ *errorString = QDeclarative1Pixmap::tr("Error decoding: %1: %2").arg(url.toString())
+ .arg(imgio.errorString());
+ return false;
+ }
+}
+
+QDeclarative1PixmapReader::QDeclarative1PixmapReader(QDeclarativeEngine *eng)
+: QThread(eng), engine(eng), threadObject(0), accessManager(0)
+{
+ eventLoopQuitHack = new QObject;
+ eventLoopQuitHack->moveToThread(this);
+ connect(eventLoopQuitHack, SIGNAL(destroyed(QObject*)), SLOT(quit()), Qt::DirectConnection);
+ start(QThread::IdlePriority);
+}
+
+QDeclarative1PixmapReader::~QDeclarative1PixmapReader()
+{
+ readerMutex.lock();
+ readers.remove(engine);
+ readerMutex.unlock();
+
+ eventLoopQuitHack->deleteLater();
+ wait();
+}
+
+void QDeclarative1PixmapReader::networkRequestDone(QNetworkReply *reply)
+{
+ QDeclarative1PixmapReply *job = replies.take(reply);
+
+ if (job) {
+ job->redirectCount++;
+ if (job->redirectCount < IMAGEREQUEST_MAX_REDIRECT_RECURSION) {
+ QVariant redirect = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
+ if (redirect.isValid()) {
+ QUrl url = reply->url().resolved(redirect.toUrl());
+ QNetworkRequest req(url);
+ req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);
+
+ reply->deleteLater();
+ reply = networkAccessManager()->get(req);
+
+ QMetaObject::connect(reply, replyDownloadProgress, job, downloadProgress);
+ QMetaObject::connect(reply, replyFinished, threadObject, threadNetworkRequestDone);
+
+ replies.insert(reply, job);
+ return;
+ }
+ }
+
+ QImage image;
+ QDeclarative1PixmapReply::ReadError error = QDeclarative1PixmapReply::NoError;
+ QString errorString;
+ QSize readSize;
+ if (reply->error()) {
+ error = QDeclarative1PixmapReply::Loading;
+ errorString = reply->errorString();
+ } else {
+ QByteArray all = reply->readAll();
+ QBuffer buff(&all);
+ buff.open(QIODevice::ReadOnly);
+ if (!readImage(reply->url(), &buff, &image, &errorString, &readSize, job->requestSize)) {
+ error = QDeclarative1PixmapReply::Decoding;
+ }
+ }
+ // send completion event to the QDeclarative1PixmapReply
+ mutex.lock();
+ if (!cancelled.contains(job)) job->postReply(error, errorString, readSize, image);
+ mutex.unlock();
+ }
+ reply->deleteLater();
+
+ // kick off event loop again incase we have dropped below max request count
+ threadObject->processJobs();
+}
+
+QDeclarative1PixmapReaderThreadObject::QDeclarative1PixmapReaderThreadObject(QDeclarative1PixmapReader *i)
+: reader(i)
+{
+}
+
+void QDeclarative1PixmapReaderThreadObject::processJobs()
+{
+ QCoreApplication::postEvent(this, new QEvent(QEvent::User));
+}
+
+bool QDeclarative1PixmapReaderThreadObject::event(QEvent *e)
+{
+ if (e->type() == QEvent::User) {
+ reader->processJobs();
+ return true;
+ } else {
+ return QObject::event(e);
+ }
+}
+
+void QDeclarative1PixmapReaderThreadObject::networkRequestDone()
+{
+ QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
+ reader->networkRequestDone(reply);
+}
+
+void QDeclarative1PixmapReader::processJobs()
+{
+ QMutexLocker locker(&mutex);
+
+ while (true) {
+ if (cancelled.isEmpty() && (jobs.isEmpty() || replies.count() >= IMAGEREQUEST_MAX_REQUEST_COUNT))
+ return; // Nothing else to do
+
+ // Clean cancelled jobs
+ if (cancelled.count()) {
+ for (int i = 0; i < cancelled.count(); ++i) {
+ QDeclarative1PixmapReply *job = cancelled.at(i);
+ QNetworkReply *reply = replies.key(job, 0);
+ if (reply && reply->isRunning()) {
+ // cancel any jobs already started
+ replies.remove(reply);
+ reply->close();
+ }
+ // deleteLater, since not owned by this thread
+ job->deleteLater();
+ }
+ cancelled.clear();
+ }
+
+ if (!jobs.isEmpty() && replies.count() < IMAGEREQUEST_MAX_REQUEST_COUNT) {
+ QDeclarative1PixmapReply *runningJob = jobs.takeLast();
+ runningJob->loading = true;
+
+ QUrl url = runningJob->data->url;
+ QSize requestSize = runningJob->data->requestSize;
+ locker.unlock();
+ processJob(runningJob, url, requestSize);
+ locker.relock();
+ }
+ }
+}
+
+void QDeclarative1PixmapReader::processJob(QDeclarative1PixmapReply *runningJob, const QUrl &url,
+ const QSize &requestSize)
+{
+ // fetch
+ if (url.scheme() == QLatin1String("image")) {
+ // Use QmlImageProvider
+ QSize readSize;
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
+ QImage image = ep->getImageFromProvider(url, &readSize, requestSize);
+
+ QDeclarative1PixmapReply::ReadError errorCode = QDeclarative1PixmapReply::NoError;
+ QString errorStr;
+ if (image.isNull()) {
+ errorCode = QDeclarative1PixmapReply::Loading;
+ errorStr = QDeclarative1Pixmap::tr("Failed to get image from provider: %1").arg(url.toString());
+ }
+
+ mutex.lock();
+ if (!cancelled.contains(runningJob)) runningJob->postReply(errorCode, errorStr, readSize, image);
+ mutex.unlock();
+ } else {
+ QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url);
+ if (!lf.isEmpty()) {
+ // Image is local - load/decode immediately
+ QImage image;
+ QDeclarative1PixmapReply::ReadError errorCode = QDeclarative1PixmapReply::NoError;
+ QString errorStr;
+ QFile f(lf);
+ QSize readSize;
+ if (f.open(QIODevice::ReadOnly)) {
+ if (!readImage(url, &f, &image, &errorStr, &readSize, requestSize))
+ errorCode = QDeclarative1PixmapReply::Loading;
+ } else {
+ errorStr = QDeclarative1Pixmap::tr("Cannot open: %1").arg(url.toString());
+ errorCode = QDeclarative1PixmapReply::Loading;
+ }
+ mutex.lock();
+ if (!cancelled.contains(runningJob)) runningJob->postReply(errorCode, errorStr, readSize, image);
+ mutex.unlock();
+ } else {
+ // Network resource
+ QNetworkRequest req(url);
+ req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);
+ QNetworkReply *reply = networkAccessManager()->get(req);
+
+ QMetaObject::connect(reply, replyDownloadProgress, runningJob, downloadProgress);
+ QMetaObject::connect(reply, replyFinished, threadObject, threadNetworkRequestDone);
+
+ replies.insert(reply, runningJob);
+ }
+ }
+}
+
+QDeclarative1PixmapReader *QDeclarative1PixmapReader::instance(QDeclarativeEngine *engine)
+{
+ readerMutex.lock();
+ QDeclarative1PixmapReader *reader = readers.value(engine);
+ if (!reader) {
+ reader = new QDeclarative1PixmapReader(engine);
+ readers.insert(engine, reader);
+ }
+ readerMutex.unlock();
+
+ return reader;
+}
+
+QDeclarative1PixmapReply *QDeclarative1PixmapReader::getImage(QDeclarative1PixmapData *data)
+{
+ mutex.lock();
+ QDeclarative1PixmapReply *reply = new QDeclarative1PixmapReply(data);
+ reply->reader = this;
+ jobs.append(reply);
+ // XXX
+ if (threadObject) threadObject->processJobs();
+ mutex.unlock();
+ return reply;
+}
+
+void QDeclarative1PixmapReader::cancel(QDeclarative1PixmapReply *reply)
+{
+ mutex.lock();
+ if (reply->loading) {
+ cancelled.append(reply);
+ reply->data = 0;
+ // XXX
+ if (threadObject) threadObject->processJobs();
+ } else {
+ jobs.removeAll(reply);
+ delete reply;
+ }
+ mutex.unlock();
+}
+
+void QDeclarative1PixmapReader::run()
+{
+ if (replyDownloadProgress == -1) {
+ const QMetaObject *nr = &QNetworkReply::staticMetaObject;
+ const QMetaObject *pr = &QDeclarative1PixmapReply::staticMetaObject;
+ const QMetaObject *ir = &QDeclarative1PixmapReaderThreadObject::staticMetaObject;
+ replyDownloadProgress = nr->indexOfSignal("downloadProgress(qint64,qint64)");
+ replyFinished = nr->indexOfSignal("finished()");
+ downloadProgress = pr->indexOfSignal("downloadProgress(qint64,qint64)");
+ threadNetworkRequestDone = ir->indexOfSlot("networkRequestDone()");
+ }
+
+ mutex.lock();
+ threadObject = new QDeclarative1PixmapReaderThreadObject(this);
+ mutex.unlock();
+
+ processJobs();
+ exec();
+
+ delete threadObject;
+ threadObject = 0;
+}
+
+class QDeclarative1PixmapKey
+{
+public:
+ const QUrl *url;
+ const QSize *size;
+};
+
+inline bool operator==(const QDeclarative1PixmapKey &lhs, const QDeclarative1PixmapKey &rhs)
+{
+ return *lhs.size == *rhs.size && *lhs.url == *rhs.url;
+}
+
+inline uint qHash(const QDeclarative1PixmapKey &key)
+{
+ return qHash(*key.url) ^ key.size->width() ^ key.size->height();
+}
+
+class QDeclarative1PixmapStore : public QObject
+{
+ Q_OBJECT
+public:
+ QDeclarative1PixmapStore();
+
+ void unreferencePixmap(QDeclarative1PixmapData *);
+ void referencePixmap(QDeclarative1PixmapData *);
+
+protected:
+ virtual void timerEvent(QTimerEvent *);
+
+public:
+ QHash<QDeclarative1PixmapKey, QDeclarative1PixmapData *> m_cache;
+
+private:
+ void shrinkCache(int remove);
+
+ QDeclarative1PixmapData *m_unreferencedPixmaps;
+ QDeclarative1PixmapData *m_lastUnreferencedPixmap;
+
+ int m_unreferencedCost;
+ int m_timerId;
+};
+Q_GLOBAL_STATIC(QDeclarative1PixmapStore, pixmapStore);
+
+QDeclarative1PixmapStore::QDeclarative1PixmapStore()
+: m_unreferencedPixmaps(0), m_lastUnreferencedPixmap(0), m_unreferencedCost(0), m_timerId(-1)
+{
+}
+
+void QDeclarative1PixmapStore::unreferencePixmap(QDeclarative1PixmapData *data)
+{
+ Q_ASSERT(data->prevUnreferenced == 0);
+ Q_ASSERT(data->prevUnreferencedPtr == 0);
+ Q_ASSERT(data->nextUnreferenced == 0);
+
+ data->nextUnreferenced = m_unreferencedPixmaps;
+ data->prevUnreferencedPtr = &m_unreferencedPixmaps;
+
+ m_unreferencedPixmaps = data;
+ if (m_unreferencedPixmaps->nextUnreferenced) {
+ m_unreferencedPixmaps->nextUnreferenced->prevUnreferenced = m_unreferencedPixmaps;
+ m_unreferencedPixmaps->nextUnreferenced->prevUnreferencedPtr = &m_unreferencedPixmaps->nextUnreferenced;
+ }
+
+ if (!m_lastUnreferencedPixmap)
+ m_lastUnreferencedPixmap = data;
+
+ m_unreferencedCost += data->cost();
+
+ shrinkCache(-1); // Shrink the cache incase it has become larger than cache_limit
+
+ if (m_timerId == -1 && m_unreferencedPixmaps)
+ m_timerId = startTimer(CACHE_EXPIRE_TIME * 1000);
+}
+
+void QDeclarative1PixmapStore::referencePixmap(QDeclarative1PixmapData *data)
+{
+ Q_ASSERT(data->prevUnreferencedPtr);
+
+ *data->prevUnreferencedPtr = data->nextUnreferenced;
+ if (data->nextUnreferenced) {
+ data->nextUnreferenced->prevUnreferencedPtr = data->prevUnreferencedPtr;
+ data->nextUnreferenced->prevUnreferenced = data->prevUnreferenced;
+ }
+ if (m_lastUnreferencedPixmap == data)
+ m_lastUnreferencedPixmap = data->prevUnreferenced;
+
+ data->nextUnreferenced = 0;
+ data->prevUnreferencedPtr = 0;
+ data->prevUnreferenced = 0;
+
+ m_unreferencedCost -= data->cost();
+}
+
+void QDeclarative1PixmapStore::shrinkCache(int remove)
+{
+ while ((remove > 0 || m_unreferencedCost > cache_limit) && m_lastUnreferencedPixmap) {
+ QDeclarative1PixmapData *data = m_lastUnreferencedPixmap;
+ Q_ASSERT(data->nextUnreferenced == 0);
+
+ *data->prevUnreferencedPtr = 0;
+ m_lastUnreferencedPixmap = data->prevUnreferenced;
+ data->prevUnreferencedPtr = 0;
+ data->prevUnreferenced = 0;
+
+ remove -= data->cost();
+ m_unreferencedCost -= data->cost();
+ data->removeFromCache();
+ delete data;
+ }
+}
+
+void QDeclarative1PixmapStore::timerEvent(QTimerEvent *)
+{
+ int removalCost = m_unreferencedCost / CACHE_REMOVAL_FRACTION;
+
+ shrinkCache(removalCost);
+
+ if (m_unreferencedPixmaps == 0) {
+ killTimer(m_timerId);
+ m_timerId = -1;
+ }
+}
+
+QDeclarative1PixmapReply::QDeclarative1PixmapReply(QDeclarative1PixmapData *d)
+: data(d), reader(0), requestSize(d->requestSize), loading(false), redirectCount(0)
+{
+ if (finishedIndex == -1) {
+ finishedIndex = QDeclarative1PixmapReply::staticMetaObject.indexOfSignal("finished()");
+ downloadProgressIndex = QDeclarative1PixmapReply::staticMetaObject.indexOfSignal("downloadProgress(qint64,qint64)");
+ }
+}
+
+QDeclarative1PixmapReply::~QDeclarative1PixmapReply()
+{
+}
+
+bool QDeclarative1PixmapReply::event(QEvent *event)
+{
+ if (event->type() == QEvent::User) {
+
+ if (data) {
+ Event *de = static_cast<Event *>(event);
+ data->pixmapStatus = (de->error == NoError) ? QDeclarative1Pixmap::Ready : QDeclarative1Pixmap::Error;
+
+ if (data->pixmapStatus == QDeclarative1Pixmap::Ready) {
+ data->pixmap = QPixmap::fromImage(de->image);
+ data->implicitSize = de->implicitSize;
+ } else {
+ data->errorString = de->errorString;
+ data->removeFromCache(); // We don't continue to cache error'd pixmaps
+ }
+
+ data->reply = 0;
+ emit finished();
+ }
+
+ delete this;
+ return true;
+ } else {
+ return QObject::event(event);
+ }
+}
+
+int QDeclarative1PixmapData::cost() const
+{
+ return (pixmap.width() * pixmap.height() * pixmap.depth()) / 8;
+}
+
+void QDeclarative1PixmapData::addref()
+{
+ ++refCount;
+ if (prevUnreferencedPtr)
+ pixmapStore()->referencePixmap(this);
+}
+
+void QDeclarative1PixmapData::release()
+{
+ Q_ASSERT(refCount > 0);
+ --refCount;
+
+ if (refCount == 0) {
+ if (reply) {
+ reply->reader->cancel(reply);
+ reply = 0;
+ }
+
+ if (pixmapStatus == QDeclarative1Pixmap::Ready) {
+ pixmapStore()->unreferencePixmap(this);
+ } else {
+ removeFromCache();
+ delete this;
+ }
+ }
+}
+
+void QDeclarative1PixmapData::addToCache()
+{
+ if (!inCache) {
+ QDeclarative1PixmapKey key = { &url, &requestSize };
+ pixmapStore()->m_cache.insert(key, this);
+ inCache = true;
+ }
+}
+
+void QDeclarative1PixmapData::removeFromCache()
+{
+ if (inCache) {
+ QDeclarative1PixmapKey key = { &url, &requestSize };
+ pixmapStore()->m_cache.remove(key);
+ inCache = false;
+ }
+}
+
+static QDeclarative1PixmapData* createPixmapDataSync(QDeclarativeEngine *engine, const QUrl &url, const QSize &requestSize, bool *ok)
+{
+ if (url.scheme() == QLatin1String("image")) {
+ QSize readSize;
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
+ QDeclarativeImageProvider::ImageType imageType = ep->getImageProviderType(url);
+
+ switch (imageType) {
+ case QDeclarativeImageProvider::Image:
+ {
+ QImage image = ep->getImageFromProvider(url, &readSize, requestSize);
+ if (!image.isNull()) {
+ *ok = true;
+ return new QDeclarative1PixmapData(url, QPixmap::fromImage(image), readSize, requestSize);
+ }
+ }
+ case QDeclarativeImageProvider::Pixmap:
+ {
+ QPixmap pixmap = ep->getPixmapFromProvider(url, &readSize, requestSize);
+ if (!pixmap.isNull()) {
+ *ok = true;
+ return new QDeclarative1PixmapData(url, pixmap, readSize, requestSize);
+ }
+ }
+ }
+
+ // no matching provider, or provider has bad image type, or provider returned null image
+ return new QDeclarative1PixmapData(url, requestSize,
+ QDeclarative1Pixmap::tr("Failed to get image from provider: %1").arg(url.toString()));
+ }
+
+ QString localFile = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url);
+ if (localFile.isEmpty())
+ return 0;
+
+ QFile f(localFile);
+ QSize readSize;
+ QString errorString;
+
+ if (f.open(QIODevice::ReadOnly)) {
+ QImage image;
+ if (readImage(url, &f, &image, &errorString, &readSize, requestSize)) {
+ *ok = true;
+ return new QDeclarative1PixmapData(url, QPixmap::fromImage(image), readSize, requestSize);
+ }
+ } else {
+ errorString = QDeclarative1Pixmap::tr("Cannot open: %1").arg(url.toString());
+ }
+ return new QDeclarative1PixmapData(url, requestSize, errorString);
+}
+
+
+struct QDeclarative1PixmapNull {
+ QUrl url;
+ QPixmap pixmap;
+ QSize size;
+};
+Q_GLOBAL_STATIC(QDeclarative1PixmapNull, nullPixmap);
+
+QDeclarative1Pixmap::QDeclarative1Pixmap()
+: d(0)
+{
+}
+
+QDeclarative1Pixmap::QDeclarative1Pixmap(QDeclarativeEngine *engine, const QUrl &url)
+: d(0)
+{
+ load(engine, url);
+}
+
+QDeclarative1Pixmap::QDeclarative1Pixmap(QDeclarativeEngine *engine, const QUrl &url, const QSize &size)
+: d(0)
+{
+ load(engine, url, size);
+}
+
+QDeclarative1Pixmap::~QDeclarative1Pixmap()
+{
+ if (d) {
+ d->release();
+ d = 0;
+ }
+}
+
+bool QDeclarative1Pixmap::isNull() const
+{
+ return d == 0;
+}
+
+bool QDeclarative1Pixmap::isReady() const
+{
+ return status() == Ready;
+}
+
+bool QDeclarative1Pixmap::isError() const
+{
+ return status() == Error;
+}
+
+bool QDeclarative1Pixmap::isLoading() const
+{
+ return status() == Loading;
+}
+
+QString QDeclarative1Pixmap::error() const
+{
+ if (d)
+ return d->errorString;
+ else
+ return QString();
+}
+
+QDeclarative1Pixmap::Status QDeclarative1Pixmap::status() const
+{
+ if (d)
+ return d->pixmapStatus;
+ else
+ return Null;
+}
+
+const QUrl &QDeclarative1Pixmap::url() const
+{
+ if (d)
+ return d->url;
+ else
+ return nullPixmap()->url;
+}
+
+const QSize &QDeclarative1Pixmap::implicitSize() const
+{
+ if (d)
+ return d->implicitSize;
+ else
+ return nullPixmap()->size;
+}
+
+const QSize &QDeclarative1Pixmap::requestSize() const
+{
+ if (d)
+ return d->requestSize;
+ else
+ return nullPixmap()->size;
+}
+
+const QPixmap &QDeclarative1Pixmap::pixmap() const
+{
+ if (d)
+ return d->pixmap;
+ else
+ return nullPixmap()->pixmap;
+}
+
+void QDeclarative1Pixmap::setPixmap(const QPixmap &p)
+{
+ clear();
+
+ if (!p.isNull())
+ d = new QDeclarative1PixmapData(p);
+}
+
+int QDeclarative1Pixmap::width() const
+{
+ if (d)
+ return d->pixmap.width();
+ else
+ return 0;
+}
+
+int QDeclarative1Pixmap::height() const
+{
+ if (d)
+ return d->pixmap.height();
+ else
+ return 0;
+}
+
+QRect QDeclarative1Pixmap::rect() const
+{
+ if (d)
+ return d->pixmap.rect();
+ else
+ return QRect();
+}
+
+void QDeclarative1Pixmap::load(QDeclarativeEngine *engine, const QUrl &url)
+{
+ load(engine, url, QSize(), QDeclarative1Pixmap::Cache);
+}
+
+void QDeclarative1Pixmap::load(QDeclarativeEngine *engine, const QUrl &url, QDeclarative1Pixmap::Options options)
+{
+ load(engine, url, QSize(), options);
+}
+
+void QDeclarative1Pixmap::load(QDeclarativeEngine *engine, const QUrl &url, const QSize &size)
+{
+ load(engine, url, size, QDeclarative1Pixmap::Cache);
+}
+
+void QDeclarative1Pixmap::load(QDeclarativeEngine *engine, const QUrl &url, const QSize &requestSize, QDeclarative1Pixmap::Options options)
+{
+ if (d) { d->release(); d = 0; }
+
+ QDeclarative1PixmapKey key = { &url, &requestSize };
+ QDeclarative1PixmapStore *store = pixmapStore();
+
+ QHash<QDeclarative1PixmapKey, QDeclarative1PixmapData *>::Iterator iter = store->m_cache.find(key);
+
+ if (iter == store->m_cache.end()) {
+ if (options & QDeclarative1Pixmap::Asynchronous) {
+ // pixmaps can only be loaded synchronously
+ if (url.scheme() == QLatin1String("image")
+ && QDeclarativeEnginePrivate::get(engine)->getImageProviderType(url) == QDeclarativeImageProvider::Pixmap) {
+ options &= ~QDeclarative1Pixmap::Asynchronous;
+ }
+ }
+
+ if (!(options & QDeclarative1Pixmap::Asynchronous)) {
+ bool ok = false;
+ d = createPixmapDataSync(engine, url, requestSize, &ok);
+ if (ok) {
+ if (options & QDeclarative1Pixmap::Cache)
+ d->addToCache();
+ return;
+ }
+ if (d) // loadable, but encountered error while loading
+ return;
+ }
+
+ if (!engine)
+ return;
+
+ QDeclarative1PixmapReader *reader = QDeclarative1PixmapReader::instance(engine);
+
+ d = new QDeclarative1PixmapData(url, requestSize);
+ if (options & QDeclarative1Pixmap::Cache)
+ d->addToCache();
+
+ d->reply = reader->getImage(d);
+ } else {
+ d = *iter;
+ d->addref();
+ }
+}
+
+void QDeclarative1Pixmap::clear()
+{
+ if (d) {
+ d->release();
+ d = 0;
+ }
+}
+
+void QDeclarative1Pixmap::clear(QObject *obj)
+{
+ if (d) {
+ if (d->reply)
+ QObject::disconnect(d->reply, 0, obj, 0);
+ d->release();
+ d = 0;
+ }
+}
+
+bool QDeclarative1Pixmap::connectFinished(QObject *object, const char *method)
+{
+ if (!d || !d->reply) {
+ qWarning("QDeclarative1Pixmap: connectFinished() called when not loading.");
+ return false;
+ }
+
+ return QObject::connect(d->reply, SIGNAL(finished()), object, method);
+}
+
+bool QDeclarative1Pixmap::connectFinished(QObject *object, int method)
+{
+ if (!d || !d->reply) {
+ qWarning("QDeclarative1Pixmap: connectFinished() called when not loading.");
+ return false;
+ }
+
+ return QMetaObject::connect(d->reply, QDeclarative1PixmapReply::finishedIndex, object, method);
+}
+
+bool QDeclarative1Pixmap::connectDownloadProgress(QObject *object, const char *method)
+{
+ if (!d || !d->reply) {
+ qWarning("QDeclarative1Pixmap: connectDownloadProgress() called when not loading.");
+ return false;
+ }
+
+ return QObject::connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), object, method);
+}
+
+bool QDeclarative1Pixmap::connectDownloadProgress(QObject *object, int method)
+{
+ if (!d || !d->reply) {
+ qWarning("QDeclarative1Pixmap: connectDownloadProgress() called when not loading.");
+ return false;
+ }
+
+ return QMetaObject::connect(d->reply, QDeclarative1PixmapReply::downloadProgressIndex, object, method);
+}
+
+
+
+QT_END_NAMESPACE
+
+#include <qdeclarativepixmapcache.moc>
diff --git a/src/qtquick1/util/qdeclarativepixmapcache_p.h b/src/qtquick1/util/qdeclarativepixmapcache_p.h
new file mode 100644
index 0000000000..f0a7770be0
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativepixmapcache_p.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEPIXMAPCACHE_H
+#define QDECLARATIVEPIXMAPCACHE_H
+
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qstring.h>
+#include <QtGui/qpixmap.h>
+#include <QtCore/qurl.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeEngine;
+
+QT_MODULE(Declarative)
+
+class QDeclarative1PixmapData;
+class Q_DECLARATIVE_EXPORT QDeclarative1Pixmap
+{
+ Q_DECLARE_TR_FUNCTIONS(QDeclarative1Pixmap)
+public:
+ QDeclarative1Pixmap();
+ QDeclarative1Pixmap(QDeclarativeEngine *, const QUrl &);
+ QDeclarative1Pixmap(QDeclarativeEngine *, const QUrl &, const QSize &);
+ ~QDeclarative1Pixmap();
+
+ enum Status { Null, Ready, Error, Loading };
+
+ enum Option {
+ Asynchronous = 0x00000001,
+ Cache = 0x00000002
+ };
+ Q_DECLARE_FLAGS(Options, Option)
+
+ bool isNull() const;
+ bool isReady() const;
+ bool isError() const;
+ bool isLoading() const;
+
+ Status status() const;
+ QString error() const;
+ const QUrl &url() const;
+ const QSize &implicitSize() const;
+ const QSize &requestSize() const;
+ const QPixmap &pixmap() const;
+ void setPixmap(const QPixmap &);
+
+ QRect rect() const;
+ int width() const;
+ int height() const;
+ inline operator const QPixmap &() const;
+
+ void load(QDeclarativeEngine *, const QUrl &);
+ void load(QDeclarativeEngine *, const QUrl &, QDeclarative1Pixmap::Options options);
+ void load(QDeclarativeEngine *, const QUrl &, const QSize &);
+ void load(QDeclarativeEngine *, const QUrl &, const QSize &, QDeclarative1Pixmap::Options options);
+
+ void clear();
+ void clear(QObject *);
+
+ bool connectFinished(QObject *, const char *);
+ bool connectFinished(QObject *, int);
+ bool connectDownloadProgress(QObject *, const char *);
+ bool connectDownloadProgress(QObject *, int);
+
+private:
+ Q_DISABLE_COPY(QDeclarative1Pixmap)
+ QDeclarative1PixmapData *d;
+};
+
+inline QDeclarative1Pixmap::operator const QPixmap &() const
+{
+ return pixmap();
+}
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarative1Pixmap::Options)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEPIXMAPCACHE_H
diff --git a/src/qtquick1/util/qdeclarativepropertychanges.cpp b/src/qtquick1/util/qdeclarativepropertychanges.cpp
new file mode 100644
index 0000000000..c9a512503b
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativepropertychanges.cpp
@@ -0,0 +1,801 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativepropertychanges_p.h"
+
+#include "QtQuick1/private/qdeclarativeopenmetaobject_p.h"
+#include "QtDeclarative/private/qdeclarativerewrite_p.h"
+#include "QtDeclarative/private/qdeclarativeengine_p.h"
+#include "QtDeclarative/private/qdeclarativecompiler_p.h"
+
+#include <QtDeclarative/qdeclarativeinfo.h>
+#include <QtDeclarative/private/qdeclarativecustomparser_p.h>
+#include <QtDeclarative/private/qdeclarativeparser_p.h>
+#include <QtDeclarative/qdeclarativeexpression.h>
+#include <QtDeclarative/private/qdeclarativebinding_p.h>
+#include <QtDeclarative/qdeclarativecontext.h>
+#include <QtDeclarative/private/qdeclarativeguard_p.h>
+#include <QtDeclarative/private/qdeclarativeproperty_p.h>
+#include <QtDeclarative/private/qdeclarativecontext_p.h>
+#include <QtQuick1/private/qdeclarativestate_p_p.h>
+
+#include <QtCore/qdebug.h>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+
+
+/*!
+ \qmlclass PropertyChanges QDeclarative1PropertyChanges
+ \ingroup qml-state-elements
+ \since 4.7
+ \brief The PropertyChanges element describes new property bindings or values for a state.
+
+ PropertyChanges is used to define the property values or bindings in a
+ \l State. This enables an item's property values to be changed when it
+ \l {QML States}{changes between states}.
+
+ To create a PropertyChanges object, specify the \l target item whose
+ properties are to be modified, and define the new property values or
+ bindings. For example:
+
+ \snippet doc/src/snippets/declarative/propertychanges.qml import
+ \codeline
+ \snippet doc/src/snippets/declarative/propertychanges.qml 0
+
+ When the mouse is pressed, the \l Rectangle changes to the \e resized
+ state. In this state, the PropertyChanges object sets the rectangle's
+ color to blue and the \c height value to that of \c container.height.
+
+ Note this automatically binds \c rect.height to \c container.height
+ in the \e resized state. If a property binding should not be
+ established, and the height should just be set to the value of
+ \c container.height at the time of the state change, set the \l explicit
+ property to \c true.
+
+ A PropertyChanges object can also override the default signal handler
+ for an object to implement a signal handler specific to the new state:
+
+ \qml
+ PropertyChanges {
+ target: myMouseArea
+ onClicked: doSomethingDifferent()
+ }
+ \endqml
+
+ \note PropertyChanges can be used to change anchor margins, but not other anchor
+ values; use AnchorChanges for this instead. Similarly, to change an \l Item's
+ \l {Item::}{parent} value, use ParentChanges instead.
+
+
+ \section2 Resetting property values
+
+ The \c undefined value can be used to reset the property value for a state.
+ In the following example, when \c theText changes to the \e widerText
+ state, its \c width property is reset, giving the text its natural width
+ and displaying the whole string on a single line.
+
+ \snippet doc/src/snippets/declarative/propertychanges.qml reset
+
+
+ \section2 Immediate property changes in transitions
+
+ When \l{QML Animation and Transitions}{Transitions} are used to animate
+ state changes, they animate properties from their values in the current
+ state to those defined in the new state (as defined by PropertyChanges
+ objects). However, it is sometimes desirable to set a property value
+ \e immediately during a \l Transition, without animation; in these cases,
+ the PropertyAction element can be used to force an immediate property
+ change.
+
+ See the PropertyAction documentation for more details.
+
+ \sa {declarative/animation/states}{states example}, {qmlstate}{States}, QtDeclarative
+*/
+
+/*!
+ \qmlproperty Object PropertyChanges::target
+ This property holds the object which contains the properties to be changed.
+*/
+
+class QDeclarative1ReplaceSignalHandler : public QDeclarative1ActionEvent
+{
+public:
+ QDeclarative1ReplaceSignalHandler() : expression(0), reverseExpression(0),
+ rewindExpression(0), ownedExpression(0) {}
+ ~QDeclarative1ReplaceSignalHandler() {
+ delete ownedExpression;
+ }
+
+ virtual QString typeName() const { return QLatin1String("ReplaceSignalHandler"); }
+
+ QDeclarativeProperty property;
+ QDeclarativeExpression *expression;
+ QDeclarativeExpression *reverseExpression;
+ QDeclarativeExpression *rewindExpression;
+ QDeclarativeGuard<QDeclarativeExpression> ownedExpression;
+
+ virtual void execute(Reason) {
+ ownedExpression = QDeclarativePropertyPrivate::setSignalExpression(property, expression);
+ if (ownedExpression == expression)
+ ownedExpression = 0;
+ }
+
+ virtual bool isReversable() { return true; }
+ virtual void reverse(Reason) {
+ ownedExpression = QDeclarativePropertyPrivate::setSignalExpression(property, reverseExpression);
+ if (ownedExpression == reverseExpression)
+ ownedExpression = 0;
+ }
+
+ virtual void saveOriginals() {
+ saveCurrentValues();
+ reverseExpression = rewindExpression;
+ }
+
+ /*virtual void copyOriginals(QDeclarative1ActionEvent *other)
+ {
+ QDeclarative1ReplaceSignalHandler *rsh = static_cast<QDeclarative1ReplaceSignalHandler*>(other);
+ saveCurrentValues();
+ if (rsh == this)
+ return;
+ reverseExpression = rsh->reverseExpression;
+ if (rsh->ownedExpression == reverseExpression) {
+ ownedExpression = rsh->ownedExpression;
+ rsh->ownedExpression = 0;
+ }
+ }*/
+
+ virtual void rewind() {
+ ownedExpression = QDeclarativePropertyPrivate::setSignalExpression(property, rewindExpression);
+ if (ownedExpression == rewindExpression)
+ ownedExpression = 0;
+ }
+ virtual void saveCurrentValues() {
+ rewindExpression = QDeclarativePropertyPrivate::signalExpression(property);
+ }
+
+ virtual bool override(QDeclarative1ActionEvent*other) {
+ if (other == this)
+ return true;
+ if (other->typeName() != typeName())
+ return false;
+ if (static_cast<QDeclarative1ReplaceSignalHandler*>(other)->property == property)
+ return true;
+ return false;
+ }
+};
+
+
+class QDeclarative1PropertyChangesPrivate : public QDeclarative1StateOperationPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1PropertyChanges)
+public:
+ QDeclarative1PropertyChangesPrivate() : decoded(true), restore(true),
+ isExplicit(false) {}
+
+ QDeclarativeGuard<QObject> object;
+ QByteArray data;
+
+ bool decoded : 1;
+ bool restore : 1;
+ bool isExplicit : 1;
+
+ void decode();
+
+ class ExpressionChange {
+ public:
+ ExpressionChange(const QString &_name,
+ QDeclarativeBinding::Identifier _id,
+ QDeclarativeExpression *_expr)
+ : name(_name), id(_id), expression(_expr) {}
+ QString name;
+ QDeclarativeBinding::Identifier id;
+ QDeclarativeExpression *expression;
+ };
+
+ QList<QPair<QString, QVariant> > properties;
+ QList<ExpressionChange> expressions;
+ QList<QDeclarative1ReplaceSignalHandler*> signalReplacements;
+
+ QDeclarativeProperty property(const QString &);
+};
+
+void
+QDeclarative1PropertyChangesParser::compileList(QList<QPair<QByteArray, QVariant> > &list,
+ const QByteArray &pre,
+ const QDeclarativeCustomParserProperty &prop)
+{
+ QByteArray propName = pre + prop.name();
+
+ QList<QVariant> values = prop.assignedValues();
+ for (int ii = 0; ii < values.count(); ++ii) {
+ const QVariant &value = values.at(ii);
+
+ if (value.userType() == qMetaTypeId<QDeclarativeCustomParserNode>()) {
+ error(qvariant_cast<QDeclarativeCustomParserNode>(value),
+ QDeclarative1PropertyChanges::tr("PropertyChanges does not support creating state-specific objects."));
+ continue;
+ } else if(value.userType() == qMetaTypeId<QDeclarativeCustomParserProperty>()) {
+
+ QDeclarativeCustomParserProperty prop =
+ qvariant_cast<QDeclarativeCustomParserProperty>(value);
+ QByteArray pre = propName + '.';
+ compileList(list, pre, prop);
+
+ } else {
+ list << qMakePair(propName, value);
+ }
+ }
+}
+
+QByteArray
+QDeclarative1PropertyChangesParser::compile(const QList<QDeclarativeCustomParserProperty> &props)
+{
+ QList<QPair<QByteArray, QVariant> > data;
+ for(int ii = 0; ii < props.count(); ++ii)
+ compileList(data, QByteArray(), props.at(ii));
+
+ QByteArray rv;
+ QDataStream ds(&rv, QIODevice::WriteOnly);
+
+ ds << data.count();
+ for(int ii = 0; ii < data.count(); ++ii) {
+ QDeclarativeParser::Variant v = qvariant_cast<QDeclarativeParser::Variant>(data.at(ii).second);
+ QVariant var;
+ bool isScript = v.isScript();
+ QDeclarativeBinding::Identifier id = 0;
+ switch(v.type()) {
+ case QDeclarativeParser::Variant::Boolean:
+ var = QVariant(v.asBoolean());
+ break;
+ case QDeclarativeParser::Variant::Number:
+ var = QVariant(v.asNumber());
+ break;
+ case QDeclarativeParser::Variant::String:
+ var = QVariant(v.asString());
+ break;
+ case QDeclarativeParser::Variant::Invalid:
+ case QDeclarativeParser::Variant::Script:
+ var = QVariant(v.asScript());
+ {
+ // Pre-rewrite the expression
+ QString expression = v.asScript();
+ id = rewriteBinding(expression, data.at(ii).first); //### recreates the AST, which is slow
+ }
+ break;
+ }
+
+ ds << QString::fromUtf8(data.at(ii).first) << isScript << var;
+ if (isScript)
+ ds << id;
+ }
+
+ return rv;
+}
+
+void QDeclarative1PropertyChangesPrivate::decode()
+{
+ Q_Q(QDeclarative1PropertyChanges);
+ if (decoded)
+ return;
+
+ QDataStream ds(&data, QIODevice::ReadOnly);
+
+ int count;
+ ds >> count;
+ for (int ii = 0; ii < count; ++ii) {
+ QString name;
+ bool isScript;
+ QVariant data;
+ QDeclarativeBinding::Identifier id = QDeclarativeBinding::Invalid;
+ ds >> name;
+ ds >> isScript;
+ ds >> data;
+ if (isScript)
+ ds >> id;
+
+ QDeclarativeProperty prop = property(name); //### better way to check for signal property?
+ if (prop.type() & QDeclarativeProperty::SignalProperty) {
+ QDeclarativeExpression *expression = new QDeclarativeExpression(qmlContext(q), object, data.toString());
+ QDeclarativeData *ddata = QDeclarativeData::get(q);
+ if (ddata && ddata->outerContext && !ddata->outerContext->url.isEmpty())
+ expression->setSourceLocation(ddata->outerContext->url.toString(), ddata->lineNumber);
+ QDeclarative1ReplaceSignalHandler *handler = new QDeclarative1ReplaceSignalHandler;
+ handler->property = prop;
+ handler->expression = expression;
+ signalReplacements << handler;
+ } else if (isScript) {
+ QDeclarativeExpression *expression = new QDeclarativeExpression(qmlContext(q), object, data.toString());
+ QDeclarativeData *ddata = QDeclarativeData::get(q);
+ if (ddata && ddata->outerContext && !ddata->outerContext->url.isEmpty())
+ expression->setSourceLocation(ddata->outerContext->url.toString(), ddata->lineNumber);
+ expressions << ExpressionChange(name, id, expression);
+ } else {
+ properties << qMakePair(name, data);
+ }
+ }
+
+ decoded = true;
+ data.clear();
+}
+
+void QDeclarative1PropertyChangesParser::setCustomData(QObject *object,
+ const QByteArray &data)
+{
+ QDeclarative1PropertyChangesPrivate *p =
+ static_cast<QDeclarative1PropertyChangesPrivate *>(QObjectPrivate::get(object));
+ p->data = data;
+ p->decoded = false;
+}
+
+QDeclarative1PropertyChanges::QDeclarative1PropertyChanges()
+: QDeclarative1StateOperation(*(new QDeclarative1PropertyChangesPrivate))
+{
+}
+
+QDeclarative1PropertyChanges::~QDeclarative1PropertyChanges()
+{
+ Q_D(QDeclarative1PropertyChanges);
+ for(int ii = 0; ii < d->expressions.count(); ++ii)
+ delete d->expressions.at(ii).expression;
+ for(int ii = 0; ii < d->signalReplacements.count(); ++ii)
+ delete d->signalReplacements.at(ii);
+}
+
+QObject *QDeclarative1PropertyChanges::object() const
+{
+ Q_D(const QDeclarative1PropertyChanges);
+ return d->object;
+}
+
+void QDeclarative1PropertyChanges::setObject(QObject *o)
+{
+ Q_D(QDeclarative1PropertyChanges);
+ d->object = o;
+}
+
+/*!
+ \qmlproperty bool PropertyChanges::restoreEntryValues
+
+ This property holds whether the previous values should be restored when
+ leaving the state.
+
+ The default value is \c true. Setting this value to \c false creates a
+ temporary state that has permanent effects on property values.
+*/
+bool QDeclarative1PropertyChanges::restoreEntryValues() const
+{
+ Q_D(const QDeclarative1PropertyChanges);
+ return d->restore;
+}
+
+void QDeclarative1PropertyChanges::setRestoreEntryValues(bool v)
+{
+ Q_D(QDeclarative1PropertyChanges);
+ d->restore = v;
+}
+
+QDeclarativeProperty
+QDeclarative1PropertyChangesPrivate::property(const QString &property)
+{
+ Q_Q(QDeclarative1PropertyChanges);
+ QDeclarativeProperty prop(object, property, qmlContext(q));
+ if (!prop.isValid()) {
+ qmlInfo(q) << QDeclarative1PropertyChanges::tr("Cannot assign to non-existent property \"%1\"").arg(property);
+ return QDeclarativeProperty();
+ } else if (!(prop.type() & QDeclarativeProperty::SignalProperty) && !prop.isWritable()) {
+ qmlInfo(q) << QDeclarative1PropertyChanges::tr("Cannot assign to read-only property \"%1\"").arg(property);
+ return QDeclarativeProperty();
+ }
+ return prop;
+}
+
+QDeclarative1PropertyChanges::ActionList QDeclarative1PropertyChanges::actions()
+{
+ Q_D(QDeclarative1PropertyChanges);
+
+ d->decode();
+
+ ActionList list;
+
+ for (int ii = 0; ii < d->properties.count(); ++ii) {
+
+ QDeclarative1Action a(d->object, d->properties.at(ii).first,
+ qmlContext(this), d->properties.at(ii).second);
+
+ if (a.property.isValid()) {
+ a.restore = restoreEntryValues();
+ list << a;
+ }
+ }
+
+ for (int ii = 0; ii < d->signalReplacements.count(); ++ii) {
+
+ QDeclarative1ReplaceSignalHandler *handler = d->signalReplacements.at(ii);
+
+ if (handler->property.isValid()) {
+ QDeclarative1Action a;
+ a.event = handler;
+ list << a;
+ }
+ }
+
+ for (int ii = 0; ii < d->expressions.count(); ++ii) {
+
+ const QString &property = d->expressions.at(ii).name;
+ QDeclarativeProperty prop = d->property(property);
+
+ if (prop.isValid()) {
+ QDeclarative1Action a;
+ a.restore = restoreEntryValues();
+ a.property = prop;
+ a.fromValue = a.property.read();
+ a.specifiedObject = d->object;
+ a.specifiedProperty = property;
+
+ if (d->isExplicit) {
+ a.toValue = d->expressions.at(ii).expression->evaluate();
+ } else {
+ QDeclarativeExpression *e = d->expressions.at(ii).expression;
+
+ QDeclarativeBinding::Identifier id = d->expressions.at(ii).id;
+ QDeclarativeBinding *newBinding = id != QDeclarativeBinding::Invalid ? QDeclarativeBinding::createBinding(id, object(), qmlContext(this), e->sourceFile(), e->lineNumber()) : 0;
+ if (!newBinding) {
+ newBinding = new QDeclarativeBinding(e->expression(), object(), qmlContext(this));
+ newBinding->setSourceLocation(e->sourceFile(), e->lineNumber());
+ }
+ newBinding->setTarget(prop);
+ a.toBinding = newBinding;
+ a.deletableToBinding = true;
+ }
+
+ list << a;
+ }
+ }
+
+ return list;
+}
+
+/*!
+ \qmlproperty bool PropertyChanges::explicit
+
+ If explicit is set to true, any potential bindings will be interpreted as
+ once-off assignments that occur when the state is entered.
+
+ In the following example, the addition of explicit prevents \c myItem.width from
+ being bound to \c parent.width. Instead, it is assigned the value of \c parent.width
+ at the time of the state change.
+ \qml
+ PropertyChanges {
+ target: myItem
+ explicit: true
+ width: parent.width
+ }
+ \endqml
+
+ By default, explicit is false.
+*/
+bool QDeclarative1PropertyChanges::isExplicit() const
+{
+ Q_D(const QDeclarative1PropertyChanges);
+ return d->isExplicit;
+}
+
+void QDeclarative1PropertyChanges::setIsExplicit(bool e)
+{
+ Q_D(QDeclarative1PropertyChanges);
+ d->isExplicit = e;
+}
+
+bool QDeclarative1PropertyChanges::containsValue(const QString &name) const
+{
+ Q_D(const QDeclarative1PropertyChanges);
+ typedef QPair<QString, QVariant> PropertyEntry;
+
+ QListIterator<PropertyEntry> propertyIterator(d->properties);
+ while (propertyIterator.hasNext()) {
+ const PropertyEntry &entry = propertyIterator.next();
+ if (entry.first == name) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool QDeclarative1PropertyChanges::containsExpression(const QString &name) const
+{
+ Q_D(const QDeclarative1PropertyChanges);
+ typedef QDeclarative1PropertyChangesPrivate::ExpressionChange ExpressionEntry;
+
+ QListIterator<ExpressionEntry> expressionIterator(d->expressions);
+ while (expressionIterator.hasNext()) {
+ const ExpressionEntry &entry = expressionIterator.next();
+ if (entry.name == name) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool QDeclarative1PropertyChanges::containsProperty(const QString &name) const
+{
+ return containsValue(name) || containsExpression(name);
+}
+
+void QDeclarative1PropertyChanges::changeValue(const QString &name, const QVariant &value)
+{
+ Q_D(QDeclarative1PropertyChanges);
+ typedef QPair<QString, QVariant> PropertyEntry;
+ typedef QDeclarative1PropertyChangesPrivate::ExpressionChange ExpressionEntry;
+
+ QMutableListIterator<ExpressionEntry> expressionIterator(d->expressions);
+ while (expressionIterator.hasNext()) {
+ const ExpressionEntry &entry = expressionIterator.next();
+ if (entry.name == name) {
+ expressionIterator.remove();
+ if (state() && state()->isStateActive()) {
+ QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(d->property(name));
+ if (oldBinding) {
+ QDeclarativePropertyPrivate::setBinding(d->property(name), 0);
+ oldBinding->destroy();
+ }
+ d->property(name).write(value);
+ }
+
+ d->properties.append(PropertyEntry(name, value));
+ return;
+ }
+ }
+
+ QMutableListIterator<PropertyEntry> propertyIterator(d->properties);
+ while (propertyIterator.hasNext()) {
+ PropertyEntry &entry = propertyIterator.next();
+ if (entry.first == name) {
+ entry.second = value;
+ if (state() && state()->isStateActive())
+ d->property(name).write(value);
+ return;
+ }
+ }
+
+ QDeclarative1Action action;
+ action.restore = restoreEntryValues();
+ action.property = d->property(name);
+ action.fromValue = action.property.read();
+ action.specifiedObject = object();
+ action.specifiedProperty = name;
+ action.toValue = value;
+
+ propertyIterator.insert(PropertyEntry(name, value));
+ if (state() && state()->isStateActive()) {
+ state()->addEntryToRevertList(action);
+ QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(action.property);
+ if (oldBinding)
+ oldBinding->setEnabled(false, QDeclarativePropertyPrivate::DontRemoveBinding | QDeclarativePropertyPrivate::BypassInterceptor);
+ d->property(name).write(value);
+ }
+}
+
+void QDeclarative1PropertyChanges::changeExpression(const QString &name, const QString &expression)
+{
+ Q_D(QDeclarative1PropertyChanges);
+ typedef QPair<QString, QVariant> PropertyEntry;
+ typedef QDeclarative1PropertyChangesPrivate::ExpressionChange ExpressionEntry;
+
+ bool hadValue = false;
+
+ QMutableListIterator<PropertyEntry> propertyIterator(d->properties);
+ while (propertyIterator.hasNext()) {
+ PropertyEntry &entry = propertyIterator.next();
+ if (entry.first == name) {
+ propertyIterator.remove();
+ hadValue = true;
+ break;
+ }
+ }
+
+ QMutableListIterator<ExpressionEntry> expressionIterator(d->expressions);
+ while (expressionIterator.hasNext()) {
+ const ExpressionEntry &entry = expressionIterator.next();
+ if (entry.name == name) {
+ entry.expression->setExpression(expression);
+ if (state() && state()->isStateActive()) {
+ QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(d->property(name));
+ if (oldBinding) {
+ QDeclarativePropertyPrivate::setBinding(d->property(name), 0);
+ oldBinding->destroy();
+ }
+
+ QDeclarativeBinding *newBinding = new QDeclarativeBinding(expression, object(), qmlContext(this));
+ newBinding->setTarget(d->property(name));
+ QDeclarativePropertyPrivate::setBinding(d->property(name), newBinding, QDeclarativePropertyPrivate::DontRemoveBinding | QDeclarativePropertyPrivate::BypassInterceptor);
+ }
+ return;
+ }
+ }
+
+ QDeclarativeExpression *newExpression = new QDeclarativeExpression(qmlContext(this), d->object, expression);
+ expressionIterator.insert(ExpressionEntry(name, QDeclarativeBinding::Invalid, newExpression));
+
+ if (state() && state()->isStateActive()) {
+ if (hadValue) {
+ QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(d->property(name));
+ if (oldBinding) {
+ oldBinding->setEnabled(false, QDeclarativePropertyPrivate::DontRemoveBinding | QDeclarativePropertyPrivate::BypassInterceptor);
+ state()->changeBindingInRevertList(object(), name, oldBinding);
+ }
+
+ QDeclarativeBinding *newBinding = new QDeclarativeBinding(expression, object(), qmlContext(this));
+ newBinding->setTarget(d->property(name));
+ QDeclarativePropertyPrivate::setBinding(d->property(name), newBinding, QDeclarativePropertyPrivate::DontRemoveBinding | QDeclarativePropertyPrivate::BypassInterceptor);
+ } else {
+ QDeclarative1Action action;
+ action.restore = restoreEntryValues();
+ action.property = d->property(name);
+ action.fromValue = action.property.read();
+ action.specifiedObject = object();
+ action.specifiedProperty = name;
+
+
+ if (d->isExplicit) {
+ action.toValue = newExpression->evaluate();
+ } else {
+ QDeclarativeBinding *newBinding = new QDeclarativeBinding(newExpression->expression(), object(), qmlContext(this));
+ newBinding->setTarget(d->property(name));
+ action.toBinding = newBinding;
+ action.deletableToBinding = true;
+
+ state()->addEntryToRevertList(action);
+ QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(action.property);
+ if (oldBinding)
+ oldBinding->setEnabled(false, QDeclarativePropertyPrivate::DontRemoveBinding | QDeclarativePropertyPrivate::BypassInterceptor);
+
+ QDeclarativePropertyPrivate::setBinding(action.property, newBinding, QDeclarativePropertyPrivate::DontRemoveBinding | QDeclarativePropertyPrivate::BypassInterceptor);
+ }
+ }
+ }
+ // what about the signal handler?
+}
+
+QVariant QDeclarative1PropertyChanges::property(const QString &name) const
+{
+ Q_D(const QDeclarative1PropertyChanges);
+ typedef QPair<QString, QVariant> PropertyEntry;
+ typedef QDeclarative1PropertyChangesPrivate::ExpressionChange ExpressionEntry;
+
+ QListIterator<PropertyEntry> propertyIterator(d->properties);
+ while (propertyIterator.hasNext()) {
+ const PropertyEntry &entry = propertyIterator.next();
+ if (entry.first == name) {
+ return entry.second;
+ }
+ }
+
+ QListIterator<ExpressionEntry> expressionIterator(d->expressions);
+ while (expressionIterator.hasNext()) {
+ const ExpressionEntry &entry = expressionIterator.next();
+ if (entry.name == name) {
+ return QVariant(entry.expression->expression());
+ }
+ }
+
+ return QVariant();
+}
+
+void QDeclarative1PropertyChanges::removeProperty(const QString &name)
+{
+ Q_D(QDeclarative1PropertyChanges);
+ typedef QPair<QString, QVariant> PropertyEntry;
+ typedef QDeclarative1PropertyChangesPrivate::ExpressionChange ExpressionEntry;
+
+ QMutableListIterator<ExpressionEntry> expressionIterator(d->expressions);
+ while (expressionIterator.hasNext()) {
+ const ExpressionEntry &entry = expressionIterator.next();
+ if (entry.name == name) {
+ expressionIterator.remove();
+ state()->removeEntryFromRevertList(object(), name);
+ return;
+ }
+ }
+
+ QMutableListIterator<PropertyEntry> propertyIterator(d->properties);
+ while (propertyIterator.hasNext()) {
+ const PropertyEntry &entry = propertyIterator.next();
+ if (entry.first == name) {
+ propertyIterator.remove();
+ state()->removeEntryFromRevertList(object(), name);
+ return;
+ }
+ }
+}
+
+QVariant QDeclarative1PropertyChanges::value(const QString &name) const
+{
+ Q_D(const QDeclarative1PropertyChanges);
+ typedef QPair<QString, QVariant> PropertyEntry;
+
+ QListIterator<PropertyEntry> propertyIterator(d->properties);
+ while (propertyIterator.hasNext()) {
+ const PropertyEntry &entry = propertyIterator.next();
+ if (entry.first == name) {
+ return entry.second;
+ }
+ }
+
+ return QVariant();
+}
+
+QString QDeclarative1PropertyChanges::expression(const QString &name) const
+{
+ Q_D(const QDeclarative1PropertyChanges);
+ typedef QDeclarative1PropertyChangesPrivate::ExpressionChange ExpressionEntry;
+
+ QListIterator<ExpressionEntry> expressionIterator(d->expressions);
+ while (expressionIterator.hasNext()) {
+ const ExpressionEntry &entry = expressionIterator.next();
+ if (entry.name == name) {
+ return entry.expression->expression();
+ }
+ }
+
+ return QString();
+}
+
+void QDeclarative1PropertyChanges::detachFromState()
+{
+ if (state())
+ state()->removeAllEntriesFromRevertList(object());
+}
+
+void QDeclarative1PropertyChanges::attachToState()
+{
+ if (state())
+ state()->addEntriesToRevertList(actions());
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/util/qdeclarativepropertychanges_p.h b/src/qtquick1/util/qdeclarativepropertychanges_p.h
new file mode 100644
index 0000000000..30609d3c2d
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativepropertychanges_p.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEPROPERTYCHANGES_H
+#define QDECLARATIVEPROPERTYCHANGES_H
+
+#include "QtQuick1/private/qdeclarativestateoperations_p.h"
+#include <QtDeclarative/private/qdeclarativecustomparser_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarative1PropertyChangesPrivate;
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarative1PropertyChanges : public QDeclarative1StateOperation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarative1PropertyChanges)
+
+ Q_PROPERTY(QObject *target READ object WRITE setObject)
+ Q_PROPERTY(bool restoreEntryValues READ restoreEntryValues WRITE setRestoreEntryValues)
+ Q_PROPERTY(bool explicit READ isExplicit WRITE setIsExplicit)
+public:
+ QDeclarative1PropertyChanges();
+ ~QDeclarative1PropertyChanges();
+
+ QObject *object() const;
+ void setObject(QObject *);
+
+ bool restoreEntryValues() const;
+ void setRestoreEntryValues(bool);
+
+ bool isExplicit() const;
+ void setIsExplicit(bool);
+
+ virtual ActionList actions();
+
+ bool containsProperty(const QString &name) const;
+ bool containsValue(const QString &name) const;
+ bool containsExpression(const QString &name) const;
+ void changeValue(const QString &name, const QVariant &value);
+ void changeExpression(const QString &name, const QString &expression);
+ void removeProperty(const QString &name);
+ QVariant value(const QString &name) const;
+ QString expression(const QString &name) const;
+
+ void detachFromState();
+ void attachToState();
+
+ QVariant property(const QString &name) const;
+};
+
+class QDeclarative1PropertyChangesParser : public QDeclarativeCustomParser
+{
+public:
+ QDeclarative1PropertyChangesParser()
+ : QDeclarativeCustomParser(AcceptsAttachedProperties) {}
+
+ void compileList(QList<QPair<QByteArray, QVariant> > &list, const QByteArray &pre, const QDeclarativeCustomParserProperty &prop);
+
+ virtual QByteArray compile(const QList<QDeclarativeCustomParserProperty> &);
+ virtual void setCustomData(QObject *, const QByteArray &);
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1PropertyChanges)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEPROPERTYCHANGES_H
diff --git a/src/qtquick1/util/qdeclarativesmoothedanimation.cpp b/src/qtquick1/util/qdeclarativesmoothedanimation.cpp
new file mode 100644
index 0000000000..d94c132a56
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativesmoothedanimation.cpp
@@ -0,0 +1,497 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativesmoothedanimation_p.h"
+#include "QtQuick1/private/qdeclarativesmoothedanimation_p_p.h"
+
+#include "QtQuick1/private/qdeclarativeanimation_p_p.h"
+
+#include <QtDeclarative/qdeclarativeproperty.h>
+#include "QtDeclarative/private/qdeclarativeproperty_p.h"
+
+#include "QtDeclarative/private/qdeclarativeglobal_p.h"
+
+#include <QtCore/qdebug.h>
+
+#include <math.h>
+
+#define DELAY_STOP_TIMER_INTERVAL 32
+
+QT_BEGIN_NAMESPACE
+
+
+
+QSmoothedAnimation_1::QSmoothedAnimation_1(QObject *parent)
+ : QAbstractAnimation(parent), to(0), velocity(200), userDuration(-1), maximumEasingTime(-1),
+ reversingMode(QDeclarative1SmoothedAnimation::Eased), initialVelocity(0),
+ trackVelocity(0), initialValue(0), invert(false), finalDuration(-1), lastTime(0)
+{
+ delayedStopTimer.setInterval(DELAY_STOP_TIMER_INTERVAL);
+ delayedStopTimer.setSingleShot(true);
+ connect(&delayedStopTimer, SIGNAL(timeout()), this, SLOT(stop()));
+}
+
+void QSmoothedAnimation_1::restart()
+{
+ initialVelocity = trackVelocity;
+ if (state() != QAbstractAnimation::Running)
+ start();
+ else
+ init();
+}
+
+void QSmoothedAnimation_1::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State /*oldState*/)
+{
+ if (newState == QAbstractAnimation::Running)
+ init();
+}
+
+void QSmoothedAnimation_1::delayedStop()
+{
+ if (!delayedStopTimer.isActive())
+ delayedStopTimer.start();
+}
+
+int QSmoothedAnimation_1::duration() const
+{
+ return -1;
+}
+
+bool QSmoothedAnimation_1::recalc()
+{
+ s = to - initialValue;
+ vi = initialVelocity;
+
+ s = (invert? -1.0: 1.0) * s;
+
+ if (userDuration > 0 && velocity > 0) {
+ tf = s / velocity;
+ if (tf > (userDuration / 1000.)) tf = (userDuration / 1000.);
+ } else if (userDuration > 0) {
+ tf = userDuration / 1000.;
+ } else if (velocity > 0) {
+ tf = s / velocity;
+ } else {
+ return false;
+ }
+
+ finalDuration = ceil(tf * 1000.0);
+
+ if (maximumEasingTime == 0) {
+ a = 0;
+ d = 0;
+ tp = 0;
+ td = tf;
+ vp = velocity;
+ sp = 0;
+ sd = s;
+ } else if (maximumEasingTime != -1 && tf > (maximumEasingTime / 1000.)) {
+ qreal met = maximumEasingTime / 1000.;
+ td = tf - met;
+
+ qreal c1 = td;
+ qreal c2 = (tf - td) * vi - tf * velocity;
+ qreal c3 = -0.5 * (tf - td) * vi * vi;
+
+ qreal vp1 = (-c2 + sqrt(c2 * c2 - 4 * c1 * c3)) / (2. * c1);
+
+ vp = vp1;
+ a = vp / met;
+ d = a;
+ tp = (vp - vi) / a;
+ sp = vi * tp + 0.5 * a * tp * tp;
+ sd = sp + (td - tp) * vp;
+ } else {
+ qreal c1 = 0.25 * tf * tf;
+ qreal c2 = 0.5 * vi * tf - s;
+ qreal c3 = -0.25 * vi * vi;
+
+ qreal a1 = (-c2 + sqrt(c2 * c2 - 4 * c1 * c3)) / (2. * c1);
+
+ qreal tp1 = 0.5 * tf - 0.5 * vi / a1;
+ qreal vp1 = a1 * tp1 + vi;
+
+ qreal sp1 = 0.5 * a1 * tp1 * tp1 + vi * tp1;
+
+ a = a1;
+ d = a1;
+ tp = tp1;
+ td = tp1;
+ vp = vp1;
+ sp = sp1;
+ sd = sp1;
+ }
+ return true;
+}
+
+qreal QSmoothedAnimation_1::easeFollow(qreal time_seconds)
+{
+ qreal value;
+ if (time_seconds < tp) {
+ trackVelocity = vi + time_seconds * a;
+ value = 0.5 * a * time_seconds * time_seconds + vi * time_seconds;
+ } else if (time_seconds < td) {
+ time_seconds -= tp;
+ trackVelocity = vp;
+ value = sp + time_seconds * vp;
+ } else if (time_seconds < tf) {
+ time_seconds -= td;
+ trackVelocity = vp - time_seconds * a;
+ value = sd - 0.5 * d * time_seconds * time_seconds + vp * time_seconds;
+ } else {
+ trackVelocity = 0;
+ value = s;
+ delayedStop();
+ }
+
+ // to normalize 's' between [0..1], divide 'value' by 's'
+ return value;
+}
+
+void QSmoothedAnimation_1::updateCurrentTime(int t)
+{
+ qreal time_seconds = qreal(t - lastTime) / 1000.;
+
+ qreal value = easeFollow(time_seconds);
+ value *= (invert? -1.0: 1.0);
+ QDeclarativePropertyPrivate::write(target, initialValue + value,
+ QDeclarativePropertyPrivate::BypassInterceptor
+ | QDeclarativePropertyPrivate::DontRemoveBinding);
+}
+
+void QSmoothedAnimation_1::init()
+{
+ if (velocity == 0) {
+ stop();
+ return;
+ }
+
+ if (delayedStopTimer.isActive())
+ delayedStopTimer.stop();
+
+ initialValue = target.read().toReal();
+ lastTime = this->currentTime();
+
+ if (to == initialValue) {
+ stop();
+ return;
+ }
+
+ bool hasReversed = trackVelocity != 0. &&
+ ((!invert) == ((initialValue - to) > 0));
+
+ if (hasReversed) {
+ switch (reversingMode) {
+ default:
+ case QDeclarative1SmoothedAnimation::Eased:
+ initialVelocity = -trackVelocity;
+ break;
+ case QDeclarative1SmoothedAnimation::Sync:
+ QDeclarativePropertyPrivate::write(target, to,
+ QDeclarativePropertyPrivate::BypassInterceptor
+ | QDeclarativePropertyPrivate::DontRemoveBinding);
+ trackVelocity = 0;
+ stop();
+ return;
+ case QDeclarative1SmoothedAnimation::Immediate:
+ initialVelocity = 0;
+ break;
+ }
+ }
+
+ trackVelocity = initialVelocity;
+
+ invert = (to < initialValue);
+
+ if (!recalc()) {
+ QDeclarativePropertyPrivate::write(target, to,
+ QDeclarativePropertyPrivate::BypassInterceptor
+ | QDeclarativePropertyPrivate::DontRemoveBinding);
+ stop();
+ return;
+ }
+}
+
+/*!
+ \qmlclass SmoothedAnimation QDeclarative1SmoothedAnimation
+ \ingroup qml-animation-transition
+ \since 4.7
+ \inherits NumberAnimation
+ \brief The SmoothedAnimation element allows a property to smoothly track a value.
+
+ A SmoothedAnimation animates a property's value to a set target value
+ using an ease in/out quad easing curve. When the target value changes,
+ the easing curves used to animate between the old and new target values
+ are smoothly spliced together to create a smooth movement to the new
+ target value that maintains the current velocity.
+
+ The follow example shows one \l Rectangle tracking the position of another
+ using SmoothedAnimation. The green rectangle's \c x and \c y values are
+ bound to those of the red rectangle. Whenever these values change, the
+ green rectangle smoothly animates to its new position:
+
+ \snippet doc/src/snippets/declarative/smoothedanimation.qml 0
+
+ A SmoothedAnimation can be configured by setting the \l velocity at which the
+ animation should occur, or the \l duration that the animation should take.
+ If both the \l velocity and \l duration are specified, the one that results in
+ the quickest animation is chosen for each change in the target value.
+
+ For example, animating from 0 to 800 will take 4 seconds if a velocity
+ of 200 is set, will take 8 seconds with a duration of 8000 set, and will
+ take 4 seconds with both a velocity of 200 and a duration of 8000 set.
+ Animating from 0 to 20000 will take 10 seconds if a velocity of 200 is set,
+ will take 8 seconds with a duration of 8000 set, and will take 8 seconds
+ with both a velocity of 200 and a duration of 8000 set.
+
+ The default velocity of SmoothedAnimation is 200 units/second. Note that if the range of the
+ value being animated is small, then the velocity will need to be adjusted
+ appropriately. For example, the opacity of an item ranges from 0 - 1.0.
+ To enable a smooth animation in this range the velocity will need to be
+ set to a value such as 0.5 units/second. Animating from 0 to 1.0 with a velocity
+ of 0.5 will take 2000 ms to complete.
+
+ Like any other animation element, a SmoothedAnimation can be applied in a
+ number of ways, including transitions, behaviors and property value
+ sources. The \l {QML Animation and Transitions} documentation shows a
+ variety of methods for creating animations.
+
+ \sa SpringAnimation, NumberAnimation, {QML Animation and Transitions}, {declarative/animation/basics}{Animation basics example}
+*/
+
+QDeclarative1SmoothedAnimation::QDeclarative1SmoothedAnimation(QObject *parent)
+: QDeclarative1NumberAnimation(*(new QDeclarative1SmoothedAnimationPrivate), parent)
+{
+}
+
+QDeclarative1SmoothedAnimation::~QDeclarative1SmoothedAnimation()
+{
+}
+
+QDeclarative1SmoothedAnimationPrivate::QDeclarative1SmoothedAnimationPrivate()
+ : wrapperGroup(new QParallelAnimationGroup), anim(new QSmoothedAnimation_1)
+{
+ Q_Q(QDeclarative1SmoothedAnimation);
+ QDeclarative_setParent_noEvent(wrapperGroup, q);
+ QDeclarative_setParent_noEvent(anim, q);
+}
+
+void QDeclarative1SmoothedAnimationPrivate::updateRunningAnimations()
+{
+ foreach(QSmoothedAnimation_1* ease, activeAnimations.values()){
+ ease->maximumEasingTime = anim->maximumEasingTime;
+ ease->reversingMode = anim->reversingMode;
+ ease->velocity = anim->velocity;
+ ease->userDuration = anim->userDuration;
+ ease->init();
+ }
+}
+
+QAbstractAnimation* QDeclarative1SmoothedAnimation::qtAnimation()
+{
+ Q_D(QDeclarative1SmoothedAnimation);
+ return d->wrapperGroup;
+}
+
+void QDeclarative1SmoothedAnimation::transition(QDeclarative1StateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction)
+{
+ Q_D(QDeclarative1SmoothedAnimation);
+ QDeclarative1NumberAnimation::transition(actions, modified, direction);
+
+ if (!d->actions)
+ return;
+
+ QSet<QAbstractAnimation*> anims;
+ for (int i = 0; i < d->actions->size(); i++) {
+ QSmoothedAnimation_1 *ease;
+ bool needsRestart;
+ if (!d->activeAnimations.contains((*d->actions)[i].property)) {
+ ease = new QSmoothedAnimation_1();
+ d->wrapperGroup->addAnimation(ease);
+ d->activeAnimations.insert((*d->actions)[i].property, ease);
+ needsRestart = false;
+ } else {
+ ease = d->activeAnimations.value((*d->actions)[i].property);
+ needsRestart = true;
+ }
+ ease->target = (*d->actions)[i].property;
+ ease->to = (*d->actions)[i].toValue.toReal();
+
+ // copying public members from main value holder animation
+ ease->maximumEasingTime = d->anim->maximumEasingTime;
+ ease->reversingMode = d->anim->reversingMode;
+ ease->velocity = d->anim->velocity;
+ ease->userDuration = d->anim->userDuration;
+
+ ease->initialVelocity = ease->trackVelocity;
+
+ if (needsRestart)
+ ease->init();
+ anims.insert(ease);
+ }
+
+ for (int i = d->wrapperGroup->animationCount() - 1; i >= 0 ; --i) {
+ if (!anims.contains(d->wrapperGroup->animationAt(i))) {
+ QSmoothedAnimation_1 *ease = static_cast<QSmoothedAnimation_1*>(d->wrapperGroup->animationAt(i));
+ d->activeAnimations.remove(ease->target);
+ d->wrapperGroup->takeAnimation(i);
+ delete ease;
+ }
+ }
+}
+
+/*!
+ \qmlproperty enumeration SmoothedAnimation::reversingMode
+
+ Sets how the SmoothedAnimation behaves if an animation direction is reversed.
+
+ Possible values are:
+
+ \list
+ \o SmoothedAnimation.Eased (default) - the animation will smoothly decelerate, and then reverse direction
+ \o SmoothedAnimation.Immediate - the animation will immediately begin accelerating in the reverse direction, beginning with a velocity of 0
+ \o SmoothedAnimation.Sync - the property is immediately set to the target value
+ \endlist
+*/
+QDeclarative1SmoothedAnimation::ReversingMode QDeclarative1SmoothedAnimation::reversingMode() const
+{
+ Q_D(const QDeclarative1SmoothedAnimation);
+ return (QDeclarative1SmoothedAnimation::ReversingMode) d->anim->reversingMode;
+}
+
+void QDeclarative1SmoothedAnimation::setReversingMode(ReversingMode m)
+{
+ Q_D(QDeclarative1SmoothedAnimation);
+ if (d->anim->reversingMode == m)
+ return;
+
+ d->anim->reversingMode = m;
+ emit reversingModeChanged();
+ d->updateRunningAnimations();
+}
+
+/*!
+ \qmlproperty int SmoothedAnimation::duration
+
+ This property holds the animation duration, in msecs, used when tracking the source.
+
+ Setting this to -1 (the default) disables the duration value.
+
+ If the velocity value and the duration value are both enabled, then the animation will
+ use whichever gives the shorter duration.
+*/
+int QDeclarative1SmoothedAnimation::duration() const
+{
+ Q_D(const QDeclarative1SmoothedAnimation);
+ return d->anim->userDuration;
+}
+
+void QDeclarative1SmoothedAnimation::setDuration(int duration)
+{
+ Q_D(QDeclarative1SmoothedAnimation);
+ if (duration != -1)
+ QDeclarative1NumberAnimation::setDuration(duration);
+ if(duration == d->anim->userDuration)
+ return;
+ d->anim->userDuration = duration;
+ d->updateRunningAnimations();
+}
+
+qreal QDeclarative1SmoothedAnimation::velocity() const
+{
+ Q_D(const QDeclarative1SmoothedAnimation);
+ return d->anim->velocity;
+}
+
+/*!
+ \qmlproperty real SmoothedAnimation::velocity
+
+ This property holds the average velocity allowed when tracking the 'to' value.
+
+ The default velocity of SmoothedAnimation is 200 units/second.
+
+ Setting this to -1 disables the velocity value.
+
+ If the velocity value and the duration value are both enabled, then the animation will
+ use whichever gives the shorter duration.
+*/
+void QDeclarative1SmoothedAnimation::setVelocity(qreal v)
+{
+ Q_D(QDeclarative1SmoothedAnimation);
+ if (d->anim->velocity == v)
+ return;
+
+ d->anim->velocity = v;
+ emit velocityChanged();
+ d->updateRunningAnimations();
+}
+
+/*!
+ \qmlproperty int SmoothedAnimation::maximumEasingTime
+
+ This property specifies the maximum time, in msecs, any "eases" during the follow should take.
+ Setting this property causes the velocity to "level out" after at a time. Setting
+ a negative value reverts to the normal mode of easing over the entire animation
+ duration.
+
+ The default value is -1.
+*/
+int QDeclarative1SmoothedAnimation::maximumEasingTime() const
+{
+ Q_D(const QDeclarative1SmoothedAnimation);
+ return d->anim->maximumEasingTime;
+}
+
+void QDeclarative1SmoothedAnimation::setMaximumEasingTime(int v)
+{
+ Q_D(QDeclarative1SmoothedAnimation);
+ if(v == d->anim->maximumEasingTime)
+ return;
+ d->anim->maximumEasingTime = v;
+ emit maximumEasingTimeChanged();
+ d->updateRunningAnimations();
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/util/qdeclarativesmoothedanimation_p.h b/src/qtquick1/util/qdeclarativesmoothedanimation_p.h
new file mode 100644
index 0000000000..89946179da
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativesmoothedanimation_p.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVESMOOTHEDANIMATION_H
+#define QDECLARATIVESMOOTHEDANIMATION_H
+
+#include <QtDeclarative/qdeclarative.h>
+#include "QtQuick1/private/qdeclarativeanimation_p.h"
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeProperty;
+
+QT_MODULE(Declarative)
+
+class QDeclarative1SmoothedAnimationPrivate;
+class Q_AUTOTEST_EXPORT QDeclarative1SmoothedAnimation : public QDeclarative1NumberAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarative1SmoothedAnimation)
+ Q_ENUMS(ReversingMode)
+
+ Q_PROPERTY(qreal velocity READ velocity WRITE setVelocity NOTIFY velocityChanged)
+ Q_PROPERTY(ReversingMode reversingMode READ reversingMode WRITE setReversingMode NOTIFY reversingModeChanged)
+ Q_PROPERTY(qreal maximumEasingTime READ maximumEasingTime WRITE setMaximumEasingTime NOTIFY maximumEasingTimeChanged)
+
+public:
+ enum ReversingMode { Eased, Immediate, Sync };
+
+ QDeclarative1SmoothedAnimation(QObject *parent = 0);
+ ~QDeclarative1SmoothedAnimation();
+
+ ReversingMode reversingMode() const;
+ void setReversingMode(ReversingMode);
+
+ virtual int duration() const;
+ virtual void setDuration(int);
+
+ qreal velocity() const;
+ void setVelocity(qreal);
+
+ int maximumEasingTime() const;
+ void setMaximumEasingTime(int);
+
+ virtual void transition(QDeclarative1StateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction);
+ QAbstractAnimation* qtAnimation();
+
+Q_SIGNALS:
+ void velocityChanged();
+ void reversingModeChanged();
+ void maximumEasingTimeChanged();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1SmoothedAnimation)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVESMOOTHEDANIMATION_H
diff --git a/src/qtquick1/util/qdeclarativesmoothedanimation_p_p.h b/src/qtquick1/util/qdeclarativesmoothedanimation_p_p.h
new file mode 100644
index 0000000000..b31a931873
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativesmoothedanimation_p_p.h
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVESMOOTHEDANIMATION_P_H
+#define QDECLARATIVESMOOTHEDANIMATION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtQuick1/private/qdeclarativesmoothedanimation_p.h"
+#include "QtQuick1/private/qdeclarativeanimation_p.h"
+
+#include "QtQuick1/private/qdeclarativeanimation_p_p.h"
+
+#include <qparallelanimationgroup.h>
+
+#include <QtCore/private/qobject_p.h>
+#include <QTimer>
+
+QT_BEGIN_NAMESPACE
+
+class Q_AUTOTEST_EXPORT QSmoothedAnimation_1 : public QAbstractAnimation
+{
+public:
+ QSmoothedAnimation_1(QObject *parent=0);
+
+ qreal to;
+ qreal velocity;
+ int userDuration;
+
+ int maximumEasingTime;
+ QDeclarative1SmoothedAnimation::ReversingMode reversingMode;
+
+ qreal initialVelocity;
+ qreal trackVelocity;
+
+ QDeclarativeProperty target;
+
+ int duration() const;
+ void restart();
+ void init();
+
+protected:
+ virtual void updateCurrentTime(int);
+ virtual void updateState(QAbstractAnimation::State, QAbstractAnimation::State);
+
+private:
+ qreal easeFollow(qreal);
+ qreal initialValue;
+
+ bool invert;
+
+ int finalDuration;
+
+ // Parameters for use in updateCurrentTime()
+ qreal a; // Acceleration
+ qreal d; // Deceleration
+ qreal tf; // Total time
+ qreal tp; // Time at which peak velocity occurs
+ qreal td; // Time at which decelleration begins
+ qreal vp; // Velocity at tp
+ qreal sp; // Displacement at tp
+ qreal sd; // Displacement at td
+ qreal vi; // "Normalized" initialvelocity
+ qreal s; // Total s
+
+ int lastTime;
+
+ bool recalc();
+ void delayedStop();
+
+ QTimer delayedStopTimer;
+};
+
+class QDeclarative1SmoothedAnimationPrivate : public QDeclarative1PropertyAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1SmoothedAnimation)
+public:
+ QDeclarative1SmoothedAnimationPrivate();
+ void updateRunningAnimations();
+
+ QParallelAnimationGroup *wrapperGroup;
+ QSmoothedAnimation_1 *anim;
+ QHash<QDeclarativeProperty, QSmoothedAnimation_1*> activeAnimations;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDECLARATIVESMOOTHEDANIMATION_P_H
diff --git a/src/qtquick1/util/qdeclarativespringanimation.cpp b/src/qtquick1/util/qdeclarativespringanimation.cpp
new file mode 100644
index 0000000000..8afa5e7840
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativespringanimation.cpp
@@ -0,0 +1,466 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativespringanimation_p.h"
+
+#include "QtQuick1/private/qdeclarativeanimation_p_p.h"
+#include <QtDeclarative/private/qdeclarativeproperty_p.h>
+
+#include <QtCore/qdebug.h>
+
+#include <private/qobject_p.h>
+
+#include <limits.h>
+#include <math.h>
+
+QT_BEGIN_NAMESPACE
+
+
+
+
+class QDeclarative1SpringAnimationPrivate : public QDeclarative1PropertyAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1SpringAnimation)
+public:
+
+
+ struct SpringAnimation {
+ SpringAnimation()
+ : currentValue(0), to(0), velocity(0), start(0), duration(0) {}
+ qreal currentValue;
+ qreal to;
+ qreal velocity;
+ int start;
+ int duration;
+ };
+ QHash<QDeclarativeProperty, SpringAnimation> activeAnimations;
+
+ qreal maxVelocity;
+ qreal velocityms;
+ int lastTime;
+ qreal mass;
+ qreal spring;
+ qreal damping;
+ qreal epsilon;
+ qreal modulus;
+
+ bool useMass : 1;
+ bool haveModulus : 1;
+
+ enum Mode {
+ Track,
+ Velocity,
+ Spring
+ };
+ Mode mode;
+
+ QDeclarative1SpringAnimationPrivate()
+ : maxVelocity(0), velocityms(0), lastTime(0)
+ , mass(1.0), spring(0.), damping(0.), epsilon(0.01)
+ , modulus(0.0), useMass(false), haveModulus(false)
+ , mode(Track), clock(0)
+ { }
+
+ void tick(int time);
+ bool animate(const QDeclarativeProperty &property, SpringAnimation &animation, int elapsed);
+ void updateMode();
+
+ typedef QTickAnimationProxy_1<QDeclarative1SpringAnimationPrivate, &QDeclarative1SpringAnimationPrivate::tick> Clock;
+ Clock *clock;
+};
+
+void QDeclarative1SpringAnimationPrivate::tick(int time)
+{
+ if (mode == Track) {
+ clock->stop();
+ return;
+ }
+ int elapsed = time - lastTime;
+ if (!elapsed)
+ return;
+
+ if (mode == Spring) {
+ if (elapsed < 16) // capped at 62fps.
+ return;
+ int count = elapsed / 16;
+ lastTime = time - (elapsed - count * 16);
+ } else {
+ lastTime = time;
+ }
+
+ QMutableHashIterator<QDeclarativeProperty, SpringAnimation> it(activeAnimations);
+ while (it.hasNext()) {
+ it.next();
+ if (animate(it.key(), it.value(), elapsed))
+ it.remove();
+ }
+
+ if (activeAnimations.isEmpty())
+ clock->stop();
+}
+
+bool QDeclarative1SpringAnimationPrivate::animate(const QDeclarativeProperty &property, SpringAnimation &animation, int elapsed)
+{
+ qreal srcVal = animation.to;
+
+ bool stop = false;
+
+ if (haveModulus) {
+ animation.currentValue = fmod(animation.currentValue, modulus);
+ srcVal = fmod(srcVal, modulus);
+ }
+ if (mode == Spring) {
+ // Real men solve the spring DEs using RK4.
+ // We'll do something much simpler which gives a result that looks fine.
+ int count = elapsed / 16;
+ for (int i = 0; i < count; ++i) {
+ qreal diff = srcVal - animation.currentValue;
+ if (haveModulus && qAbs(diff) > modulus / 2) {
+ if (diff < 0)
+ diff += modulus;
+ else
+ diff -= modulus;
+ }
+ if (useMass)
+ animation.velocity = animation.velocity + (spring * diff - damping * animation.velocity) / mass;
+ else
+ animation.velocity = animation.velocity + spring * diff - damping * animation.velocity;
+ if (maxVelocity > 0.) {
+ // limit velocity
+ if (animation.velocity > maxVelocity)
+ animation.velocity = maxVelocity;
+ else if (animation.velocity < -maxVelocity)
+ animation.velocity = -maxVelocity;
+ }
+ animation.currentValue += animation.velocity * 16.0 / 1000.0;
+ if (haveModulus) {
+ animation.currentValue = fmod(animation.currentValue, modulus);
+ if (animation.currentValue < 0.0)
+ animation.currentValue += modulus;
+ }
+ }
+ if (qAbs(animation.velocity) < epsilon && qAbs(srcVal - animation.currentValue) < epsilon) {
+ animation.velocity = 0.0;
+ animation.currentValue = srcVal;
+ stop = true;
+ }
+ } else {
+ qreal moveBy = elapsed * velocityms;
+ qreal diff = srcVal - animation.currentValue;
+ if (haveModulus && qAbs(diff) > modulus / 2) {
+ if (diff < 0)
+ diff += modulus;
+ else
+ diff -= modulus;
+ }
+ if (diff > 0) {
+ animation.currentValue += moveBy;
+ if (haveModulus)
+ animation.currentValue = fmod(animation.currentValue, modulus);
+ } else {
+ animation.currentValue -= moveBy;
+ if (haveModulus && animation.currentValue < 0.0)
+ animation.currentValue = fmod(animation.currentValue, modulus) + modulus;
+ }
+ if (lastTime - animation.start >= animation.duration) {
+ animation.currentValue = animation.to;
+ stop = true;
+ }
+ }
+
+ qreal old_to = animation.to;
+
+ QDeclarativePropertyPrivate::write(property, animation.currentValue,
+ QDeclarativePropertyPrivate::BypassInterceptor |
+ QDeclarativePropertyPrivate::DontRemoveBinding);
+
+ return (stop && old_to == animation.to); // do not stop if we got restarted
+}
+
+void QDeclarative1SpringAnimationPrivate::updateMode()
+{
+ if (spring == 0. && maxVelocity == 0.)
+ mode = Track;
+ else if (spring > 0.)
+ mode = Spring;
+ else {
+ mode = Velocity;
+ QHash<QDeclarativeProperty, SpringAnimation>::iterator it;
+ for (it = activeAnimations.begin(); it != activeAnimations.end(); ++it) {
+ SpringAnimation &animation = *it;
+ animation.start = lastTime;
+ qreal dist = qAbs(animation.currentValue - animation.to);
+ if (haveModulus && dist > modulus / 2)
+ dist = modulus - fmod(dist, modulus);
+ animation.duration = dist / velocityms;
+ }
+ }
+}
+
+/*!
+ \qmlclass SpringAnimation QDeclarative1SpringAnimation
+ \ingroup qml-animation-transition
+ \inherits NumberAnimation
+ \since 4.7
+
+ \brief The SpringAnimation element allows a property to track a value in a spring-like motion.
+
+ SpringAnimation mimics the oscillatory behavior of a spring, with the appropriate \l spring constant to
+ control the acceleration and the \l damping to control how quickly the effect dies away.
+
+ You can also limit the maximum \l velocity of the animation.
+
+ The following \l Rectangle moves to the position of the mouse using a
+ SpringAnimation when the mouse is clicked. The use of the \l Behavior
+ on the \c x and \c y values indicates that whenever these values are
+ changed, a SpringAnimation should be applied.
+
+ \snippet doc/src/snippets/declarative/springanimation.qml 0
+
+ Like any other animation element, a SpringAnimation can be applied in a
+ number of ways, including transitions, behaviors and property value
+ sources. The \l {QML Animation and Transitions} documentation shows a
+ variety of methods for creating animations.
+
+ \sa SmoothedAnimation, {QML Animation and Transitions}, {declarative/animation/basics}{Animation basics example}, {declarative/toys/clocks}{Clocks example}
+*/
+
+QDeclarative1SpringAnimation::QDeclarative1SpringAnimation(QObject *parent)
+: QDeclarative1NumberAnimation(*(new QDeclarative1SpringAnimationPrivate),parent)
+{
+ Q_D(QDeclarative1SpringAnimation);
+ d->clock = new QDeclarative1SpringAnimationPrivate::Clock(d, this);
+}
+
+QDeclarative1SpringAnimation::~QDeclarative1SpringAnimation()
+{
+}
+
+/*!
+ \qmlproperty real SpringAnimation::velocity
+
+ This property holds the maximum velocity allowed when tracking the source.
+
+ The default value is 0 (no maximum velocity).
+*/
+
+qreal QDeclarative1SpringAnimation::velocity() const
+{
+ Q_D(const QDeclarative1SpringAnimation);
+ return d->maxVelocity;
+}
+
+void QDeclarative1SpringAnimation::setVelocity(qreal velocity)
+{
+ Q_D(QDeclarative1SpringAnimation);
+ d->maxVelocity = velocity;
+ d->velocityms = velocity / 1000.0;
+ d->updateMode();
+}
+
+/*!
+ \qmlproperty real SpringAnimation::spring
+
+ This property describes how strongly the target is pulled towards the
+ source. The default value is 0 (that is, the spring-like motion is disabled).
+
+ The useful value range is 0 - 5.0.
+
+ When this property is set and the \l velocity value is greater than 0,
+ the \l velocity limits the maximum speed.
+*/
+qreal QDeclarative1SpringAnimation::spring() const
+{
+ Q_D(const QDeclarative1SpringAnimation);
+ return d->spring;
+}
+
+void QDeclarative1SpringAnimation::setSpring(qreal spring)
+{
+ Q_D(QDeclarative1SpringAnimation);
+ d->spring = spring;
+ d->updateMode();
+}
+
+/*!
+ \qmlproperty real SpringAnimation::damping
+ This property holds the spring damping value.
+
+ This value describes how quickly the spring-like motion comes to rest.
+ The default value is 0.
+
+ The useful value range is 0 - 1.0. The lower the value, the faster it
+ comes to rest.
+*/
+qreal QDeclarative1SpringAnimation::damping() const
+{
+ Q_D(const QDeclarative1SpringAnimation);
+ return d->damping;
+}
+
+void QDeclarative1SpringAnimation::setDamping(qreal damping)
+{
+ Q_D(QDeclarative1SpringAnimation);
+ if (damping > 1.)
+ damping = 1.;
+
+ d->damping = damping;
+}
+
+
+/*!
+ \qmlproperty real SpringAnimation::epsilon
+ This property holds the spring epsilon.
+
+ The epsilon is the rate and amount of change in the value which is close enough
+ to 0 to be considered equal to zero. This will depend on the usage of the value.
+ For pixel positions, 0.25 would suffice. For scale, 0.005 will suffice.
+
+ The default is 0.01. Tuning this value can provide small performance improvements.
+*/
+qreal QDeclarative1SpringAnimation::epsilon() const
+{
+ Q_D(const QDeclarative1SpringAnimation);
+ return d->epsilon;
+}
+
+void QDeclarative1SpringAnimation::setEpsilon(qreal epsilon)
+{
+ Q_D(QDeclarative1SpringAnimation);
+ d->epsilon = epsilon;
+}
+
+/*!
+ \qmlproperty real SpringAnimation::modulus
+ This property holds the modulus value. The default value is 0.
+
+ Setting a \a modulus forces the target value to "wrap around" at the modulus.
+ For example, setting the modulus to 360 will cause a value of 370 to wrap around to 10.
+*/
+qreal QDeclarative1SpringAnimation::modulus() const
+{
+ Q_D(const QDeclarative1SpringAnimation);
+ return d->modulus;
+}
+
+void QDeclarative1SpringAnimation::setModulus(qreal modulus)
+{
+ Q_D(QDeclarative1SpringAnimation);
+ if (d->modulus != modulus) {
+ d->haveModulus = modulus != 0.0;
+ d->modulus = modulus;
+ d->updateMode();
+ emit modulusChanged();
+ }
+}
+
+/*!
+ \qmlproperty real SpringAnimation::mass
+ This property holds the "mass" of the property being moved.
+
+ The value is 1.0 by default.
+
+ A greater mass causes slower movement and a greater spring-like
+ motion when an item comes to rest.
+*/
+qreal QDeclarative1SpringAnimation::mass() const
+{
+ Q_D(const QDeclarative1SpringAnimation);
+ return d->mass;
+}
+
+void QDeclarative1SpringAnimation::setMass(qreal mass)
+{
+ Q_D(QDeclarative1SpringAnimation);
+ if (d->mass != mass && mass > 0.0) {
+ d->useMass = mass != 1.0;
+ d->mass = mass;
+ emit massChanged();
+ }
+}
+
+void QDeclarative1SpringAnimation::transition(QDeclarative1StateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction)
+{
+ Q_D(QDeclarative1SpringAnimation);
+ Q_UNUSED(direction);
+
+ if (d->clock->state() != QAbstractAnimation::Running) {
+ d->lastTime = 0;
+ }
+
+ QDeclarative1NumberAnimation::transition(actions, modified, direction);
+
+ if (!d->actions)
+ return;
+
+ if (!d->actions->isEmpty()) {
+ for (int i = 0; i < d->actions->size(); ++i) {
+ const QDeclarativeProperty &property = d->actions->at(i).property;
+ QDeclarative1SpringAnimationPrivate::SpringAnimation &animation
+ = d->activeAnimations[property];
+ animation.to = d->actions->at(i).toValue.toReal();
+ animation.start = d->lastTime;
+ if (d->fromIsDefined)
+ animation.currentValue = d->actions->at(i).fromValue.toReal();
+ else
+ animation.currentValue = property.read().toReal();
+ if (d->mode == QDeclarative1SpringAnimationPrivate::Velocity) {
+ qreal dist = qAbs(animation.currentValue - animation.to);
+ if (d->haveModulus && dist > d->modulus / 2)
+ dist = d->modulus - fmod(dist, d->modulus);
+ animation.duration = dist / d->velocityms;
+ }
+ }
+ }
+}
+
+
+QAbstractAnimation *QDeclarative1SpringAnimation::qtAnimation()
+{
+ Q_D(QDeclarative1SpringAnimation);
+ return d->clock;
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/util/qdeclarativespringanimation_p.h b/src/qtquick1/util/qdeclarativespringanimation_p.h
new file mode 100644
index 0000000000..2eb3f3772c
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativespringanimation_p.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVESPRINGANIMATION_H
+#define QDECLARATIVESPRINGANIMATION_H
+
+#include <QtDeclarative/qdeclarative.h>
+#include "QtQuick1/private/qdeclarativeanimation_p.h"
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarative1SpringAnimationPrivate;
+class Q_AUTOTEST_EXPORT QDeclarative1SpringAnimation : public QDeclarative1NumberAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarative1SpringAnimation)
+ Q_INTERFACES(QDeclarativePropertyValueSource)
+
+ Q_PROPERTY(qreal velocity READ velocity WRITE setVelocity)
+ Q_PROPERTY(qreal spring READ spring WRITE setSpring)
+ Q_PROPERTY(qreal damping READ damping WRITE setDamping)
+ Q_PROPERTY(qreal epsilon READ epsilon WRITE setEpsilon)
+ Q_PROPERTY(qreal modulus READ modulus WRITE setModulus NOTIFY modulusChanged)
+ Q_PROPERTY(qreal mass READ mass WRITE setMass NOTIFY massChanged)
+
+public:
+ QDeclarative1SpringAnimation(QObject *parent=0);
+ ~QDeclarative1SpringAnimation();
+
+ qreal velocity() const;
+ void setVelocity(qreal velocity);
+
+ qreal spring() const;
+ void setSpring(qreal spring);
+
+ qreal damping() const;
+ void setDamping(qreal damping);
+
+ qreal epsilon() const;
+ void setEpsilon(qreal epsilon);
+
+ qreal mass() const;
+ void setMass(qreal modulus);
+
+ qreal modulus() const;
+ void setModulus(qreal modulus);
+
+ virtual void transition(QDeclarative1StateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction);
+
+protected:
+ virtual QAbstractAnimation *qtAnimation();
+
+Q_SIGNALS:
+ void modulusChanged();
+ void massChanged();
+ void syncChanged();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1SpringAnimation)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVESPRINGANIMATION_H
diff --git a/src/qtquick1/util/qdeclarativestate.cpp b/src/qtquick1/util/qdeclarativestate.cpp
new file mode 100644
index 0000000000..de6fcd0d86
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativestate.cpp
@@ -0,0 +1,734 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativestate_p_p.h"
+#include "QtQuick1/private/qdeclarativestate_p.h"
+
+#include "QtQuick1/private/qdeclarativetransition_p.h"
+#include "QtQuick1/private/qdeclarativestategroup_p.h"
+#include "QtQuick1/private/qdeclarativestateoperations_p.h"
+#include "QtQuick1/private/qdeclarativeanimation_p.h"
+#include "QtQuick1/private/qdeclarativeanimation_p_p.h"
+
+#include <QtDeclarative/private/qdeclarativebinding_p.h>
+#include <QtDeclarative/private/qdeclarativeglobal_p.h>
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+
+
+DEFINE_BOOL_CONFIG_OPTION(stateChangeDebug, STATECHANGE_DEBUG);
+
+QDeclarative1Action::QDeclarative1Action()
+: restore(true), actionDone(false), reverseEvent(false), deletableToBinding(false), fromBinding(0), event(0),
+ specifiedObject(0)
+{
+}
+
+QDeclarative1Action::QDeclarative1Action(QObject *target, const QString &propertyName,
+ const QVariant &value)
+: restore(true), actionDone(false), reverseEvent(false), deletableToBinding(false),
+ property(target, propertyName, qmlEngine(target)), toValue(value),
+ fromBinding(0), event(0),
+ specifiedObject(target), specifiedProperty(propertyName)
+{
+ if (property.isValid())
+ fromValue = property.read();
+}
+
+QDeclarative1Action::QDeclarative1Action(QObject *target, const QString &propertyName,
+ QDeclarativeContext *context, const QVariant &value)
+: restore(true), actionDone(false), reverseEvent(false), deletableToBinding(false),
+ property(target, propertyName, context), toValue(value),
+ fromBinding(0), event(0),
+ specifiedObject(target), specifiedProperty(propertyName)
+{
+ if (property.isValid())
+ fromValue = property.read();
+}
+
+
+QDeclarative1ActionEvent::~QDeclarative1ActionEvent()
+{
+}
+
+QString QDeclarative1ActionEvent::typeName() const
+{
+ return QString();
+}
+
+void QDeclarative1ActionEvent::execute(Reason)
+{
+}
+
+bool QDeclarative1ActionEvent::isReversable()
+{
+ return false;
+}
+
+void QDeclarative1ActionEvent::reverse(Reason)
+{
+}
+
+bool QDeclarative1ActionEvent::changesBindings()
+{
+ return false;
+}
+
+void QDeclarative1ActionEvent::clearBindings()
+{
+}
+
+bool QDeclarative1ActionEvent::override(QDeclarative1ActionEvent *other)
+{
+ Q_UNUSED(other);
+ return false;
+}
+
+QDeclarative1StateOperation::QDeclarative1StateOperation(QObjectPrivate &dd, QObject *parent)
+ : QObject(dd, parent)
+{
+}
+
+/*!
+ \qmlclass State QDeclarative1State
+ \ingroup qml-state-elements
+ \since 4.7
+ \brief The State element defines configurations of objects and properties.
+
+ A \e state is a set of batched changes from the default configuration.
+
+ All items have a default state that defines the default configuration of objects
+ and property values. New states can be defined by adding State items to the \l {Item::states}{states} property to
+ allow items to switch between different configurations. These configurations
+ can, for example, be used to apply different sets of property values or execute
+ different scripts.
+
+ The following example displays a single \l Rectangle. In the default state, the rectangle
+ is colored black. In the "clicked" state, a PropertyChanges element changes the
+ rectangle's color to red. Clicking within the MouseArea toggles the rectangle's state
+ between the default state and the "clicked" state, thus toggling the color of the
+ rectangle between black and red.
+
+ \snippet doc/src/snippets/declarative/state.qml 0
+
+ Notice the default state is referred to using an empty string ("").
+
+ States are commonly used together with \l{QML Animation and Transitions}{Transitions} to provide
+ animations when state changes occur.
+
+ \note Setting the state of an object from within another state of the same object is
+ not allowed.
+
+ \sa {declarative/animation/states}{states example}, {qmlstates}{States},
+ {QML Animation and Transitions}{Transitions}, QtDeclarative
+*/
+QDeclarative1State::QDeclarative1State(QObject *parent)
+: QObject(*(new QDeclarative1StatePrivate), parent)
+{
+ Q_D(QDeclarative1State);
+ d->transitionManager.setState(this);
+}
+
+QDeclarative1State::~QDeclarative1State()
+{
+ Q_D(QDeclarative1State);
+ if (d->group)
+ d->group->removeState(this);
+}
+
+/*!
+ \qmlproperty string State::name
+ This property holds the name of the state.
+
+ Each state should have a unique name within its item.
+*/
+QString QDeclarative1State::name() const
+{
+ Q_D(const QDeclarative1State);
+ return d->name;
+}
+
+void QDeclarative1State::setName(const QString &n)
+{
+ Q_D(QDeclarative1State);
+ d->name = n;
+ d->named = true;
+}
+
+bool QDeclarative1State::isNamed() const
+{
+ Q_D(const QDeclarative1State);
+ return d->named;
+}
+
+bool QDeclarative1State::isWhenKnown() const
+{
+ Q_D(const QDeclarative1State);
+ return d->when != 0;
+}
+
+/*!
+ \qmlproperty bool State::when
+ This property holds when the state should be applied.
+
+ This should be set to an expression that evaluates to \c true when you want the state to
+ be applied. For example, the following \l Rectangle changes in and out of the "hidden"
+ state when the \l MouseArea is pressed:
+
+ \snippet doc/src/snippets/declarative/state-when.qml 0
+
+ If multiple states in a group have \c when clauses that evaluate to \c true
+ at the same time, the first matching state will be applied. For example, in
+ the following snippet \c state1 will always be selected rather than
+ \c state2 when sharedCondition becomes \c true.
+ \qml
+ Item {
+ states: [
+ State { name: "state1"; when: sharedCondition },
+ State { name: "state2"; when: sharedCondition }
+ ]
+ // ...
+ }
+ \endqml
+*/
+QDeclarativeBinding *QDeclarative1State::when() const
+{
+ Q_D(const QDeclarative1State);
+ return d->when;
+}
+
+void QDeclarative1State::setWhen(QDeclarativeBinding *when)
+{
+ Q_D(QDeclarative1State);
+ d->when = when;
+ if (d->group)
+ d->group->updateAutoState();
+}
+
+/*!
+ \qmlproperty string State::extend
+ This property holds the state that this state extends.
+
+ When a state extends another state, it inherits all the changes of that state.
+
+ The state being extended is treated as the base state in regards to
+ the changes specified by the extending state.
+*/
+QString QDeclarative1State::extends() const
+{
+ Q_D(const QDeclarative1State);
+ return d->extends;
+}
+
+void QDeclarative1State::setExtends(const QString &extends)
+{
+ Q_D(QDeclarative1State);
+ d->extends = extends;
+}
+
+/*!
+ \qmlproperty list<Change> State::changes
+ This property holds the changes to apply for this state
+ \default
+
+ By default these changes are applied against the default state. If the state
+ extends another state, then the changes are applied against the state being
+ extended.
+*/
+QDeclarativeListProperty<QDeclarative1StateOperation> QDeclarative1State::changes()
+{
+ Q_D(QDeclarative1State);
+ return QDeclarativeListProperty<QDeclarative1StateOperation>(this, &d->operations, QDeclarative1StatePrivate::operations_append,
+ QDeclarative1StatePrivate::operations_count, QDeclarative1StatePrivate::operations_at,
+ QDeclarative1StatePrivate::operations_clear);
+}
+
+int QDeclarative1State::operationCount() const
+{
+ Q_D(const QDeclarative1State);
+ return d->operations.count();
+}
+
+QDeclarative1StateOperation *QDeclarative1State::operationAt(int index) const
+{
+ Q_D(const QDeclarative1State);
+ return d->operations.at(index);
+}
+
+QDeclarative1State &QDeclarative1State::operator<<(QDeclarative1StateOperation *op)
+{
+ Q_D(QDeclarative1State);
+ d->operations.append(QDeclarative1StatePrivate::OperationGuard(op, &d->operations));
+ return *this;
+}
+
+void QDeclarative1StatePrivate::complete()
+{
+ Q_Q(QDeclarative1State);
+
+ for (int ii = 0; ii < reverting.count(); ++ii) {
+ for (int jj = 0; jj < revertList.count(); ++jj) {
+ if (revertList.at(jj).property() == reverting.at(ii)) {
+ revertList.removeAt(jj);
+ break;
+ }
+ }
+ }
+ reverting.clear();
+
+ emit q->completed();
+}
+
+// Generate a list of actions for this state. This includes coelescing state
+// actions that this state "extends"
+QDeclarative1StateOperation::ActionList
+QDeclarative1StatePrivate::generateActionList(QDeclarative1StateGroup *group) const
+{
+ QDeclarative1StateOperation::ActionList applyList;
+ if (inState)
+ return applyList;
+
+ // Prevent "extends" recursion
+ inState = true;
+
+ if (!extends.isEmpty()) {
+ QList<QDeclarative1State *> states = group->states();
+ for (int ii = 0; ii < states.count(); ++ii)
+ if (states.at(ii)->name() == extends) {
+ qmlExecuteDeferred(states.at(ii));
+ applyList = static_cast<QDeclarative1StatePrivate*>(states.at(ii)->d_func())->generateActionList(group);
+ }
+ }
+
+ foreach(QDeclarative1StateOperation *op, operations)
+ applyList << op->actions();
+
+ inState = false;
+ return applyList;
+}
+
+QDeclarative1StateGroup *QDeclarative1State::stateGroup() const
+{
+ Q_D(const QDeclarative1State);
+ return d->group;
+}
+
+void QDeclarative1State::setStateGroup(QDeclarative1StateGroup *group)
+{
+ Q_D(QDeclarative1State);
+ d->group = group;
+}
+
+void QDeclarative1State::cancel()
+{
+ Q_D(QDeclarative1State);
+ d->transitionManager.cancel();
+}
+
+void QDeclarative1Action::deleteFromBinding()
+{
+ if (fromBinding) {
+ QDeclarativePropertyPrivate::setBinding(property, 0);
+ fromBinding->destroy();
+ fromBinding = 0;
+ }
+}
+
+bool QDeclarative1State::containsPropertyInRevertList(QObject *target, const QString &name) const
+{
+ Q_D(const QDeclarative1State);
+
+ if (isStateActive()) {
+ QListIterator<QDeclarative1SimpleAction> revertListIterator(d->revertList);
+
+ while (revertListIterator.hasNext()) {
+ const QDeclarative1SimpleAction &simpleAction = revertListIterator.next();
+ if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name)
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool QDeclarative1State::changeValueInRevertList(QObject *target, const QString &name, const QVariant &revertValue)
+{
+ Q_D(QDeclarative1State);
+
+ if (isStateActive()) {
+ QMutableListIterator<QDeclarative1SimpleAction> revertListIterator(d->revertList);
+
+ while (revertListIterator.hasNext()) {
+ QDeclarative1SimpleAction &simpleAction = revertListIterator.next();
+ if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name) {
+ simpleAction.setValue(revertValue);
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool QDeclarative1State::changeBindingInRevertList(QObject *target, const QString &name, QDeclarativeAbstractBinding *binding)
+{
+ Q_D(QDeclarative1State);
+
+ if (isStateActive()) {
+ QMutableListIterator<QDeclarative1SimpleAction> revertListIterator(d->revertList);
+
+ while (revertListIterator.hasNext()) {
+ QDeclarative1SimpleAction &simpleAction = revertListIterator.next();
+ if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name) {
+ if (simpleAction.binding())
+ simpleAction.binding()->destroy();
+
+ simpleAction.setBinding(binding);
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool QDeclarative1State::removeEntryFromRevertList(QObject *target, const QString &name)
+{
+ Q_D(QDeclarative1State);
+
+ if (isStateActive()) {
+ QMutableListIterator<QDeclarative1SimpleAction> revertListIterator(d->revertList);
+
+ while (revertListIterator.hasNext()) {
+ QDeclarative1SimpleAction &simpleAction = revertListIterator.next();
+ if (simpleAction.property().object() == target && simpleAction.property().name() == name) {
+ QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(simpleAction.property());
+ if (oldBinding) {
+ QDeclarativePropertyPrivate::setBinding(simpleAction.property(), 0);
+ oldBinding->destroy();
+ }
+
+ simpleAction.property().write(simpleAction.value());
+ if (simpleAction.binding())
+ QDeclarativePropertyPrivate::setBinding(simpleAction.property(), simpleAction.binding());
+
+ revertListIterator.remove();
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+void QDeclarative1State::addEntryToRevertList(const QDeclarative1Action &action)
+{
+ Q_D(QDeclarative1State);
+
+ QDeclarative1SimpleAction simpleAction(action);
+
+ d->revertList.append(simpleAction);
+}
+
+void QDeclarative1State::removeAllEntriesFromRevertList(QObject *target)
+{
+ Q_D(QDeclarative1State);
+
+ if (isStateActive()) {
+ QMutableListIterator<QDeclarative1SimpleAction> revertListIterator(d->revertList);
+
+ while (revertListIterator.hasNext()) {
+ QDeclarative1SimpleAction &simpleAction = revertListIterator.next();
+ if (simpleAction.property().object() == target) {
+ QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(simpleAction.property());
+ if (oldBinding) {
+ QDeclarativePropertyPrivate::setBinding(simpleAction.property(), 0);
+ oldBinding->destroy();
+ }
+
+ simpleAction.property().write(simpleAction.value());
+ if (simpleAction.binding())
+ QDeclarativePropertyPrivate::setBinding(simpleAction.property(), simpleAction.binding());
+
+ revertListIterator.remove();
+ }
+ }
+ }
+}
+
+void QDeclarative1State::addEntriesToRevertList(const QList<QDeclarative1Action> &actionList)
+{
+ Q_D(QDeclarative1State);
+ if (isStateActive()) {
+ QList<QDeclarative1SimpleAction> simpleActionList;
+
+ QListIterator<QDeclarative1Action> actionListIterator(actionList);
+ while(actionListIterator.hasNext()) {
+ const QDeclarative1Action &action = actionListIterator.next();
+ QDeclarative1SimpleAction simpleAction(action);
+ action.property.write(action.toValue);
+ if (!action.toBinding.isNull()) {
+ QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(simpleAction.property());
+ if (oldBinding)
+ QDeclarativePropertyPrivate::setBinding(simpleAction.property(), 0);
+ QDeclarativePropertyPrivate::setBinding(simpleAction.property(), action.toBinding.data(), QDeclarativePropertyPrivate::DontRemoveBinding);
+ }
+
+ simpleActionList.append(simpleAction);
+ }
+
+ d->revertList.append(simpleActionList);
+ }
+}
+
+QVariant QDeclarative1State::valueInRevertList(QObject *target, const QString &name) const
+{
+ Q_D(const QDeclarative1State);
+
+ if (isStateActive()) {
+ QListIterator<QDeclarative1SimpleAction> revertListIterator(d->revertList);
+
+ while (revertListIterator.hasNext()) {
+ const QDeclarative1SimpleAction &simpleAction = revertListIterator.next();
+ if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name)
+ return simpleAction.value();
+ }
+ }
+
+ return QVariant();
+}
+
+QDeclarativeAbstractBinding *QDeclarative1State::bindingInRevertList(QObject *target, const QString &name) const
+{
+ Q_D(const QDeclarative1State);
+
+ if (isStateActive()) {
+ QListIterator<QDeclarative1SimpleAction> revertListIterator(d->revertList);
+
+ while (revertListIterator.hasNext()) {
+ const QDeclarative1SimpleAction &simpleAction = revertListIterator.next();
+ if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name)
+ return simpleAction.binding();
+ }
+ }
+
+ return 0;
+}
+
+bool QDeclarative1State::isStateActive() const
+{
+ return stateGroup() && stateGroup()->state() == name();
+}
+
+void QDeclarative1State::apply(QDeclarative1StateGroup *group, QDeclarative1Transition *trans, QDeclarative1State *revert)
+{
+ Q_D(QDeclarative1State);
+
+ qmlExecuteDeferred(this);
+
+ cancel();
+ if (revert)
+ revert->cancel();
+ d->revertList.clear();
+ d->reverting.clear();
+
+ if (revert) {
+ QDeclarative1StatePrivate *revertPrivate =
+ static_cast<QDeclarative1StatePrivate*>(revert->d_func());
+ d->revertList = revertPrivate->revertList;
+ revertPrivate->revertList.clear();
+ }
+
+ // List of actions caused by this state
+ QDeclarative1StateOperation::ActionList applyList = d->generateActionList(group);
+
+ // List of actions that need to be reverted to roll back (just) this state
+ QDeclarative1StatePrivate::SimpleActionList additionalReverts;
+ // First add the reverse of all the applyList actions
+ for (int ii = 0; ii < applyList.count(); ++ii) {
+ QDeclarative1Action &action = applyList[ii];
+
+ if (action.event) {
+ if (!action.event->isReversable())
+ continue;
+ bool found = false;
+ for (int jj = 0; jj < d->revertList.count(); ++jj) {
+ QDeclarative1ActionEvent *event = d->revertList.at(jj).event();
+ if (event && event->typeName() == action.event->typeName()) {
+ if (action.event->override(event)) {
+ found = true;
+
+ if (action.event != d->revertList.at(jj).event() && action.event->needsCopy()) {
+ action.event->copyOriginals(d->revertList.at(jj).event());
+
+ QDeclarative1SimpleAction r(action);
+ additionalReverts << r;
+ d->revertList.removeAt(jj);
+ --jj;
+ } else if (action.event->isRewindable()) //###why needed?
+ action.event->saveCurrentValues();
+
+ break;
+ }
+ }
+ }
+ if (!found) {
+ action.event->saveOriginals();
+ // Only need to revert the applyList action if the previous
+ // state doesn't have a higher priority revert already
+ QDeclarative1SimpleAction r(action);
+ additionalReverts << r;
+ }
+ } else {
+ bool found = false;
+ action.fromBinding = QDeclarativePropertyPrivate::binding(action.property);
+
+ for (int jj = 0; jj < d->revertList.count(); ++jj) {
+ if (d->revertList.at(jj).property() == action.property) {
+ found = true;
+ if (d->revertList.at(jj).binding() != action.fromBinding) {
+ action.deleteFromBinding();
+ }
+ break;
+ }
+ }
+
+ if (!found) {
+ if (!action.restore) {
+ action.deleteFromBinding();;
+ } else {
+ // Only need to revert the applyList action if the previous
+ // state doesn't have a higher priority revert already
+ QDeclarative1SimpleAction r(action);
+ additionalReverts << r;
+ }
+ }
+ }
+ }
+
+ // Any reverts from a previous state that aren't carried forth
+ // into this state need to be translated into apply actions
+ for (int ii = 0; ii < d->revertList.count(); ++ii) {
+ bool found = false;
+ if (d->revertList.at(ii).event()) {
+ QDeclarative1ActionEvent *event = d->revertList.at(ii).event();
+ if (!event->isReversable())
+ continue;
+ for (int jj = 0; !found && jj < applyList.count(); ++jj) {
+ const QDeclarative1Action &action = applyList.at(jj);
+ if (action.event && action.event->typeName() == event->typeName()) {
+ if (action.event->override(event))
+ found = true;
+ }
+ }
+ } else {
+ for (int jj = 0; !found && jj < applyList.count(); ++jj) {
+ const QDeclarative1Action &action = applyList.at(jj);
+ if (action.property == d->revertList.at(ii).property())
+ found = true;
+ }
+ }
+ if (!found) {
+ QVariant cur = d->revertList.at(ii).property().read();
+ QDeclarativeAbstractBinding *delBinding =
+ QDeclarativePropertyPrivate::setBinding(d->revertList.at(ii).property(), 0);
+ if (delBinding)
+ delBinding->destroy();
+
+ QDeclarative1Action a;
+ a.property = d->revertList.at(ii).property();
+ a.fromValue = cur;
+ a.toValue = d->revertList.at(ii).value();
+ a.toBinding = QDeclarativeAbstractBinding::getPointer(d->revertList.at(ii).binding());
+ a.specifiedObject = d->revertList.at(ii).specifiedObject();
+ a.specifiedProperty = d->revertList.at(ii).specifiedProperty();
+ a.event = d->revertList.at(ii).event();
+ a.reverseEvent = d->revertList.at(ii).reverseEvent();
+ if (a.event && a.event->isRewindable())
+ a.event->saveCurrentValues();
+ applyList << a;
+ // Store these special reverts in the reverting list
+ d->reverting << d->revertList.at(ii).property();
+ }
+ }
+ // All the local reverts now become part of the ongoing revertList
+ d->revertList << additionalReverts;
+
+#ifndef QT_NO_DEBUG_STREAM
+ // Output for debugging
+ if (stateChangeDebug()) {
+ foreach(const QDeclarative1Action &action, applyList) {
+ if (action.event)
+ qWarning() << " QDeclarative1Action event:" << action.event->typeName();
+ else
+ qWarning() << " QDeclarative1Action:" << action.property.object()
+ << action.property.name() << "From:" << action.fromValue
+ << "To:" << action.toValue;
+ }
+ }
+#endif
+
+ d->transitionManager.transition(applyList, trans);
+}
+
+QDeclarative1StateOperation::ActionList QDeclarative1StateOperation::actions()
+{
+ return ActionList();
+}
+
+QDeclarative1State *QDeclarative1StateOperation::state() const
+{
+ Q_D(const QDeclarative1StateOperation);
+ return d->m_state;
+}
+
+void QDeclarative1StateOperation::setState(QDeclarative1State *state)
+{
+ Q_D(QDeclarative1StateOperation);
+ d->m_state = state;
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/util/qdeclarativestate_p.h b/src/qtquick1/util/qdeclarativestate_p.h
new file mode 100644
index 0000000000..fcfa2efead
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativestate_p.h
@@ -0,0 +1,211 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVESTATE_H
+#define QDECLARATIVESTATE_H
+
+#include <QtDeclarative/qdeclarative.h>
+#include <QtDeclarative/qdeclarativeproperty.h>
+#include <QtCore/qobject.h>
+#include <QtCore/qsharedpointer.h>
+#include <QtDeclarative/private/qdeclarativeglobal_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeAbstractBinding;
+class QDeclarativeBinding;
+class QDeclarativeExpression;
+
+QT_MODULE(Declarative)
+
+class QDeclarative1ActionEvent;
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarative1Action
+{
+public:
+ QDeclarative1Action();
+ QDeclarative1Action(QObject *, const QString &, const QVariant &);
+ QDeclarative1Action(QObject *, const QString &,
+ QDeclarativeContext *, const QVariant &);
+
+ bool restore:1;
+ bool actionDone:1;
+ bool reverseEvent:1;
+ bool deletableToBinding:1;
+
+ QDeclarativeProperty property;
+ QVariant fromValue;
+ QVariant toValue;
+
+ QDeclarativeAbstractBinding *fromBinding;
+ QWeakPointer<QDeclarativeAbstractBinding> toBinding;
+ QDeclarative1ActionEvent *event;
+
+ //strictly for matching
+ QObject *specifiedObject;
+ QString specifiedProperty;
+
+ void deleteFromBinding();
+};
+
+class Q_AUTOTEST_EXPORT QDeclarative1ActionEvent
+{
+public:
+ virtual ~QDeclarative1ActionEvent();
+ virtual QString typeName() const;
+
+ enum Reason { ActualChange, FastForward };
+
+ virtual void execute(Reason reason = ActualChange);
+ virtual bool isReversable();
+ virtual void reverse(Reason reason = ActualChange);
+ virtual void saveOriginals() {}
+ virtual bool needsCopy() { return false; }
+ virtual void copyOriginals(QDeclarative1ActionEvent *) {}
+
+ virtual bool isRewindable() { return isReversable(); }
+ virtual void rewind() {}
+ virtual void saveCurrentValues() {}
+ virtual void saveTargetValues() {}
+
+ virtual bool changesBindings();
+ virtual void clearBindings();
+ virtual bool override(QDeclarative1ActionEvent*other);
+};
+
+//### rename to QDeclarative1StateChange?
+class QDeclarative1StateGroup;
+class QDeclarative1State;
+class QDeclarative1StateOperationPrivate;
+class Q_DECLARATIVE_EXPORT QDeclarative1StateOperation : public QObject
+{
+ Q_OBJECT
+public:
+ QDeclarative1StateOperation(QObject *parent = 0)
+ : QObject(parent) {}
+ typedef QList<QDeclarative1Action> ActionList;
+
+ virtual ActionList actions();
+
+ QDeclarative1State *state() const;
+ void setState(QDeclarative1State *state);
+
+protected:
+ QDeclarative1StateOperation(QObjectPrivate &dd, QObject *parent = 0);
+
+private:
+ Q_DECLARE_PRIVATE(QDeclarative1StateOperation)
+ Q_DISABLE_COPY(QDeclarative1StateOperation)
+};
+
+typedef QDeclarative1StateOperation::ActionList QDeclarative1StateActions;
+
+class QDeclarative1Transition;
+class QDeclarative1StatePrivate;
+class Q_DECLARATIVE_EXPORT QDeclarative1State : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString name READ name WRITE setName)
+ Q_PROPERTY(QDeclarativeBinding *when READ when WRITE setWhen)
+ Q_PROPERTY(QString extend READ extends WRITE setExtends)
+ Q_PROPERTY(QDeclarativeListProperty<QDeclarative1StateOperation> changes READ changes)
+ Q_CLASSINFO("DefaultProperty", "changes")
+ Q_CLASSINFO("DeferredPropertyNames", "changes")
+
+public:
+ QDeclarative1State(QObject *parent=0);
+ virtual ~QDeclarative1State();
+
+ QString name() const;
+ void setName(const QString &);
+ bool isNamed() const;
+
+ /*'when' is a QDeclarativeBinding to limit state changes oscillation
+ due to the unpredictable order of evaluation of bound expressions*/
+ bool isWhenKnown() const;
+ QDeclarativeBinding *when() const;
+ void setWhen(QDeclarativeBinding *);
+
+ QString extends() const;
+ void setExtends(const QString &);
+
+ QDeclarativeListProperty<QDeclarative1StateOperation> changes();
+ int operationCount() const;
+ QDeclarative1StateOperation *operationAt(int) const;
+
+ QDeclarative1State &operator<<(QDeclarative1StateOperation *);
+
+ void apply(QDeclarative1StateGroup *, QDeclarative1Transition *, QDeclarative1State *revert);
+ void cancel();
+
+ QDeclarative1StateGroup *stateGroup() const;
+ void setStateGroup(QDeclarative1StateGroup *);
+
+ bool containsPropertyInRevertList(QObject *target, const QString &name) const;
+ bool changeValueInRevertList(QObject *target, const QString &name, const QVariant &revertValue);
+ bool changeBindingInRevertList(QObject *target, const QString &name, QDeclarativeAbstractBinding *binding);
+ bool removeEntryFromRevertList(QObject *target, const QString &name);
+ void addEntryToRevertList(const QDeclarative1Action &action);
+ void removeAllEntriesFromRevertList(QObject *target);
+ void addEntriesToRevertList(const QList<QDeclarative1Action> &actions);
+ QVariant valueInRevertList(QObject *target, const QString &name) const;
+ QDeclarativeAbstractBinding *bindingInRevertList(QObject *target, const QString &name) const;
+
+ bool isStateActive() const;
+
+Q_SIGNALS:
+ void completed();
+
+private:
+ Q_DECLARE_PRIVATE(QDeclarative1State)
+ Q_DISABLE_COPY(QDeclarative1State)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1StateOperation)
+QML_DECLARE_TYPE(QDeclarative1State)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVESTATE_H
diff --git a/src/qtquick1/util/qdeclarativestate_p_p.h b/src/qtquick1/util/qdeclarativestate_p_p.h
new file mode 100644
index 0000000000..cf3fbd2299
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativestate_p_p.h
@@ -0,0 +1,253 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVESTATE_P_H
+#define QDECLARATIVESTATE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtQuick1/private/qdeclarativestate_p.h"
+
+#include "QtQuick1/private/qdeclarativeanimation_p_p.h"
+#include "QtQuick1/private/qdeclarativetransitionmanager_p_p.h"
+
+#include <QtDeclarative/private/qdeclarativeproperty_p.h>
+#include <QtDeclarative/private/qdeclarativeguard_p.h>
+
+#include <QtDeclarative/private/qdeclarativebinding_p.h>
+
+#include <QtCore/private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarative1SimpleAction
+{
+public:
+ enum State { StartState, EndState };
+ QDeclarative1SimpleAction(const QDeclarative1Action &a, State state = StartState)
+ {
+ m_property = a.property;
+ m_specifiedObject = a.specifiedObject;
+ m_specifiedProperty = a.specifiedProperty;
+ m_event = a.event;
+ if (state == StartState) {
+ m_value = a.fromValue;
+ if (QDeclarativePropertyPrivate::binding(m_property)) {
+ m_binding = QDeclarativeAbstractBinding::getPointer(QDeclarativePropertyPrivate::binding(m_property));
+ }
+ m_reverseEvent = true;
+ } else {
+ m_value = a.toValue;
+ m_binding = a.toBinding;
+ m_reverseEvent = false;
+ }
+ }
+
+ ~QDeclarative1SimpleAction()
+ {
+ }
+
+ QDeclarative1SimpleAction(const QDeclarative1SimpleAction &other)
+ : m_property(other.m_property),
+ m_value(other.m_value),
+ m_binding(QDeclarativeAbstractBinding::getPointer(other.binding())),
+ m_specifiedObject(other.m_specifiedObject),
+ m_specifiedProperty(other.m_specifiedProperty),
+ m_event(other.m_event),
+ m_reverseEvent(other.m_reverseEvent)
+ {
+ }
+
+ QDeclarative1SimpleAction &operator =(const QDeclarative1SimpleAction &other)
+ {
+ m_property = other.m_property;
+ m_value = other.m_value;
+ m_binding = QDeclarativeAbstractBinding::getPointer(other.binding());
+ m_specifiedObject = other.m_specifiedObject;
+ m_specifiedProperty = other.m_specifiedProperty;
+ m_event = other.m_event;
+ m_reverseEvent = other.m_reverseEvent;
+
+ return *this;
+ }
+
+ void setProperty(const QDeclarativeProperty &property)
+ {
+ m_property = property;
+ }
+
+ const QDeclarativeProperty &property() const
+ {
+ return m_property;
+ }
+
+ void setValue(const QVariant &value)
+ {
+ m_value = value;
+ }
+
+ const QVariant &value() const
+ {
+ return m_value;
+ }
+
+ void setBinding(QDeclarativeAbstractBinding *binding)
+ {
+ m_binding = QDeclarativeAbstractBinding::getPointer(binding);
+ }
+
+ QDeclarativeAbstractBinding *binding() const
+ {
+ return m_binding.data();
+ }
+
+ QObject *specifiedObject() const
+ {
+ return m_specifiedObject;
+ }
+
+ const QString &specifiedProperty() const
+ {
+ return m_specifiedProperty;
+ }
+
+ QDeclarative1ActionEvent *event() const
+ {
+ return m_event;
+ }
+
+ bool reverseEvent() const
+ {
+ return m_reverseEvent;
+ }
+
+private:
+ QDeclarativeProperty m_property;
+ QVariant m_value;
+ QDeclarativeAbstractBinding::Pointer m_binding;
+ QObject *m_specifiedObject;
+ QString m_specifiedProperty;
+ QDeclarative1ActionEvent *m_event;
+ bool m_reverseEvent;
+};
+
+class QDeclarative1StateOperationPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1StateOperation)
+
+public:
+
+ QDeclarative1StateOperationPrivate()
+ : m_state(0) {}
+
+ QDeclarative1State *m_state;
+};
+
+class QDeclarative1StatePrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1State)
+
+public:
+ QDeclarative1StatePrivate()
+ : when(0), named(false), inState(false), group(0) {}
+
+ typedef QList<QDeclarative1SimpleAction> SimpleActionList;
+
+ QString name;
+ QDeclarativeBinding *when;
+ bool named;
+
+ struct OperationGuard : public QDeclarativeGuard<QDeclarative1StateOperation>
+ {
+ OperationGuard(QObject *obj, QList<OperationGuard> *l) : list(l) { (QDeclarativeGuard<QObject>&)*this = obj; }
+ QList<OperationGuard> *list;
+ void objectDestroyed(QDeclarative1StateOperation *) {
+ // we assume priv will always be destroyed after objectDestroyed calls
+ list->removeOne(*this);
+ }
+ };
+ QList<OperationGuard> operations;
+
+ static void operations_append(QDeclarativeListProperty<QDeclarative1StateOperation> *prop, QDeclarative1StateOperation *op) {
+ QList<OperationGuard> *list = static_cast<QList<OperationGuard> *>(prop->data);
+ op->setState(qobject_cast<QDeclarative1State*>(prop->object));
+ list->append(OperationGuard(op, list));
+ }
+ static void operations_clear(QDeclarativeListProperty<QDeclarative1StateOperation> *prop) {
+ QList<OperationGuard> *list = static_cast<QList<OperationGuard> *>(prop->data);
+ QMutableListIterator<OperationGuard> listIterator(*list);
+ while(listIterator.hasNext())
+ listIterator.next()->setState(0);
+ list->clear();
+ }
+ static int operations_count(QDeclarativeListProperty<QDeclarative1StateOperation> *prop) {
+ QList<OperationGuard> *list = static_cast<QList<OperationGuard> *>(prop->data);
+ return list->count();
+ }
+ static QDeclarative1StateOperation *operations_at(QDeclarativeListProperty<QDeclarative1StateOperation> *prop, int index) {
+ QList<OperationGuard> *list = static_cast<QList<OperationGuard> *>(prop->data);
+ return list->at(index);
+ }
+
+ QDeclarative1TransitionManager transitionManager;
+
+ SimpleActionList revertList;
+ QList<QDeclarativeProperty> reverting;
+ QString extends;
+ mutable bool inState;
+ QDeclarative1StateGroup *group;
+
+ QDeclarative1StateOperation::ActionList generateActionList(QDeclarative1StateGroup *) const;
+ void complete();
+};
+
+QT_END_NAMESPACE
+
+#endif // QDECLARATIVESTATE_P_H
diff --git a/src/qtquick1/util/qdeclarativestategroup.cpp b/src/qtquick1/util/qdeclarativestategroup.cpp
new file mode 100644
index 0000000000..f04a8d4f03
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativestategroup.cpp
@@ -0,0 +1,473 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativestategroup_p.h"
+
+#include "QtQuick1/private/qdeclarativetransition_p.h"
+#include "QtQuick1/private/qdeclarativestate_p_p.h"
+
+#include <QtDeclarative/private/qdeclarativebinding_p.h>
+#include <QtDeclarative/private/qdeclarativeglobal_p.h>
+
+#include <QtCore/qstringbuilder.h>
+#include <QtCore/qdebug.h>
+
+#include <private/qobject_p.h>
+#include <QtDeclarative/qdeclarativeinfo.h>
+
+QT_BEGIN_NAMESPACE
+
+
+
+DEFINE_BOOL_CONFIG_OPTION(stateChangeDebug, STATECHANGE_DEBUG);
+
+class QDeclarative1StateGroupPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1StateGroup)
+public:
+ QDeclarative1StateGroupPrivate()
+ : nullState(0), componentComplete(true),
+ ignoreTrans(false), applyingState(false), unnamedCount(0) {}
+
+ QString currentState;
+ QDeclarative1State *nullState;
+
+ static void append_state(QDeclarativeListProperty<QDeclarative1State> *list, QDeclarative1State *state);
+ static int count_state(QDeclarativeListProperty<QDeclarative1State> *list);
+ static QDeclarative1State *at_state(QDeclarativeListProperty<QDeclarative1State> *list, int index);
+ static void clear_states(QDeclarativeListProperty<QDeclarative1State> *list);
+
+ QList<QDeclarative1State *> states;
+ QList<QDeclarative1Transition *> transitions;
+
+ bool componentComplete;
+ bool ignoreTrans;
+ bool applyingState;
+ int unnamedCount;
+
+ QDeclarative1Transition *findTransition(const QString &from, const QString &to);
+ void setCurrentStateInternal(const QString &state, bool = false);
+ bool updateAutoState();
+};
+
+/*!
+ \qmlclass StateGroup QDeclarative1StateGroup
+ \ingroup qml-state-elements
+ \since 4.7
+ \brief The StateGroup element provides state support for non-Item elements.
+
+ Item (and all derived elements) provides built in support for states and transitions
+ via its \l{Item::state}{state}, \l{Item::states}{states} and \l{Item::transitions}{transitions} properties. StateGroup provides an easy way to
+ use this support in other (non-Item-derived) elements.
+
+ \qml
+ MyCustomObject {
+ StateGroup {
+ id: myStateGroup
+ states: State {
+ name: "state1"
+ // ...
+ }
+ transitions: Transition {
+ // ...
+ }
+ }
+
+ onSomethingHappened: myStateGroup.state = "state1";
+ }
+ \endqml
+
+ \sa {qmlstate}{States} {QML Animation and Transitions}{Transitions}, {QtDeclarative}
+*/
+
+QDeclarative1StateGroup::QDeclarative1StateGroup(QObject *parent)
+ : QObject(*(new QDeclarative1StateGroupPrivate), parent)
+{
+}
+
+QDeclarative1StateGroup::~QDeclarative1StateGroup()
+{
+ Q_D(const QDeclarative1StateGroup);
+ for (int i = 0; i < d->states.count(); ++i)
+ d->states.at(i)->setStateGroup(0);
+}
+
+QList<QDeclarative1State *> QDeclarative1StateGroup::states() const
+{
+ Q_D(const QDeclarative1StateGroup);
+ return d->states;
+}
+
+/*!
+ \qmlproperty list<State> StateGroup::states
+ This property holds a list of states defined by the state group.
+
+ \qml
+ StateGroup {
+ states: [
+ State {
+ // State definition...
+ },
+ State {
+ // ...
+ }
+ // Other states...
+ ]
+ }
+ \endqml
+
+ \sa {qmlstate}{States}
+*/
+QDeclarativeListProperty<QDeclarative1State> QDeclarative1StateGroup::statesProperty()
+{
+ Q_D(QDeclarative1StateGroup);
+ return QDeclarativeListProperty<QDeclarative1State>(this, &d->states, &QDeclarative1StateGroupPrivate::append_state,
+ &QDeclarative1StateGroupPrivate::count_state,
+ &QDeclarative1StateGroupPrivate::at_state,
+ &QDeclarative1StateGroupPrivate::clear_states);
+}
+
+void QDeclarative1StateGroupPrivate::append_state(QDeclarativeListProperty<QDeclarative1State> *list, QDeclarative1State *state)
+{
+ QDeclarative1StateGroup *_this = static_cast<QDeclarative1StateGroup *>(list->object);
+ if (state) {
+ _this->d_func()->states.append(state);
+ state->setStateGroup(_this);
+ }
+
+}
+
+int QDeclarative1StateGroupPrivate::count_state(QDeclarativeListProperty<QDeclarative1State> *list)
+{
+ QDeclarative1StateGroup *_this = static_cast<QDeclarative1StateGroup *>(list->object);
+ return _this->d_func()->states.count();
+}
+
+QDeclarative1State *QDeclarative1StateGroupPrivate::at_state(QDeclarativeListProperty<QDeclarative1State> *list, int index)
+{
+ QDeclarative1StateGroup *_this = static_cast<QDeclarative1StateGroup *>(list->object);
+ return _this->d_func()->states.at(index);
+}
+
+void QDeclarative1StateGroupPrivate::clear_states(QDeclarativeListProperty<QDeclarative1State> *list)
+{
+ QDeclarative1StateGroup *_this = static_cast<QDeclarative1StateGroup *>(list->object);
+ _this->d_func()->setCurrentStateInternal(QString(), true);
+ for (int i = 0; i < _this->d_func()->states.count(); ++i) {
+ _this->d_func()->states.at(i)->setStateGroup(0);
+ }
+ _this->d_func()->states.clear();
+}
+
+/*!
+ \qmlproperty list<Transition> StateGroup::transitions
+ This property holds a list of transitions defined by the state group.
+
+ \qml
+ StateGroup {
+ transitions: [
+ Transition {
+ // ...
+ },
+ Transition {
+ // ...
+ }
+ // ...
+ ]
+ }
+ \endqml
+
+ \sa {QML Animation and Transitions}{Transitions}
+*/
+QDeclarativeListProperty<QDeclarative1Transition> QDeclarative1StateGroup::transitionsProperty()
+{
+ Q_D(QDeclarative1StateGroup);
+ return QDeclarativeListProperty<QDeclarative1Transition>(this, d->transitions);
+}
+
+/*!
+ \qmlproperty string StateGroup::state
+
+ This property holds the name of the current state of the state group.
+
+ This property is often used in scripts to change between states. For
+ example:
+
+ \js
+ function toggle() {
+ if (button.state == 'On')
+ button.state = 'Off';
+ else
+ button.state = 'On';
+ }
+ \endjs
+
+ If the state group is in its base state (i.e. no explicit state has been
+ set), \c state will be a blank string. Likewise, you can return a
+ state group to its base state by setting its current state to \c ''.
+
+ \sa {qmlstates}{States}
+*/
+QString QDeclarative1StateGroup::state() const
+{
+ Q_D(const QDeclarative1StateGroup);
+ return d->currentState;
+}
+
+void QDeclarative1StateGroup::setState(const QString &state)
+{
+ Q_D(QDeclarative1StateGroup);
+ if (d->currentState == state)
+ return;
+
+ d->setCurrentStateInternal(state);
+}
+
+void QDeclarative1StateGroup::classBegin()
+{
+ Q_D(QDeclarative1StateGroup);
+ d->componentComplete = false;
+}
+
+void QDeclarative1StateGroup::componentComplete()
+{
+ Q_D(QDeclarative1StateGroup);
+ d->componentComplete = true;
+
+ for (int ii = 0; ii < d->states.count(); ++ii) {
+ QDeclarative1State *state = d->states.at(ii);
+ if (!state->isNamed())
+ state->setName(QLatin1String("anonymousState") % QString::number(++d->unnamedCount));
+ }
+
+ if (d->updateAutoState()) {
+ return;
+ } else if (!d->currentState.isEmpty()) {
+ QString cs = d->currentState;
+ d->currentState.clear();
+ d->setCurrentStateInternal(cs, true);
+ }
+}
+
+/*!
+ Returns true if the state was changed, otherwise false.
+*/
+bool QDeclarative1StateGroup::updateAutoState()
+{
+ Q_D(QDeclarative1StateGroup);
+ return d->updateAutoState();
+}
+
+bool QDeclarative1StateGroupPrivate::updateAutoState()
+{
+ Q_Q(QDeclarative1StateGroup);
+ if (!componentComplete)
+ return false;
+
+ bool revert = false;
+ for (int ii = 0; ii < states.count(); ++ii) {
+ QDeclarative1State *state = states.at(ii);
+ if (state->isWhenKnown()) {
+ if (state->isNamed()) {
+ if (state->when() && state->when()->evaluate().toBool()) {
+ if (stateChangeDebug())
+ qWarning() << "Setting auto state due to:"
+ << state->when()->expression();
+ if (currentState != state->name()) {
+ q->setState(state->name());
+ return true;
+ } else {
+ return false;
+ }
+ } else if (state->name() == currentState) {
+ revert = true;
+ }
+ }
+ }
+ }
+ if (revert) {
+ bool rv = !currentState.isEmpty();
+ q->setState(QString());
+ return rv;
+ } else {
+ return false;
+ }
+}
+
+QDeclarative1Transition *QDeclarative1StateGroupPrivate::findTransition(const QString &from, const QString &to)
+{
+ QDeclarative1Transition *highest = 0;
+ int score = 0;
+ bool reversed = false;
+ bool done = false;
+
+ for (int ii = 0; !done && ii < transitions.count(); ++ii) {
+ QDeclarative1Transition *t = transitions.at(ii);
+ for (int ii = 0; ii < 2; ++ii)
+ {
+ if (ii && (!t->reversible() ||
+ (t->fromState() == QLatin1String("*") &&
+ t->toState() == QLatin1String("*"))))
+ break;
+ QStringList fromState;
+ QStringList toState;
+
+ fromState = t->fromState().split(QLatin1Char(','));
+ toState = t->toState().split(QLatin1Char(','));
+ if (ii == 1)
+ qSwap(fromState, toState);
+ int tScore = 0;
+ if (fromState.contains(from))
+ tScore += 2;
+ else if (fromState.contains(QLatin1String("*")))
+ tScore += 1;
+ else
+ continue;
+
+ if (toState.contains(to))
+ tScore += 2;
+ else if (toState.contains(QLatin1String("*")))
+ tScore += 1;
+ else
+ continue;
+
+ if (ii == 1)
+ reversed = true;
+ else
+ reversed = false;
+
+ if (tScore == 4) {
+ highest = t;
+ done = true;
+ break;
+ } else if (tScore > score) {
+ score = tScore;
+ highest = t;
+ }
+ }
+ }
+
+ if (highest)
+ highest->setReversed(reversed);
+
+ return highest;
+}
+
+void QDeclarative1StateGroupPrivate::setCurrentStateInternal(const QString &state,
+ bool ignoreTrans)
+{
+ Q_Q(QDeclarative1StateGroup);
+ if (!componentComplete) {
+ currentState = state;
+ return;
+ }
+
+ if (applyingState) {
+ qmlInfo(q) << "Can't apply a state change as part of a state definition.";
+ return;
+ }
+
+ applyingState = true;
+
+ QDeclarative1Transition *transition = (ignoreTrans || ignoreTrans) ? 0 : findTransition(currentState, state);
+ if (stateChangeDebug()) {
+ qWarning() << this << "Changing state. From" << currentState << ". To" << state;
+ if (transition)
+ qWarning() << " using transition" << transition->fromState()
+ << transition->toState();
+ }
+
+ QDeclarative1State *oldState = 0;
+ if (!currentState.isEmpty()) {
+ for (int ii = 0; ii < states.count(); ++ii) {
+ if (states.at(ii)->name() == currentState) {
+ oldState = states.at(ii);
+ break;
+ }
+ }
+ }
+
+ currentState = state;
+ emit q->stateChanged(currentState);
+
+ QDeclarative1State *newState = 0;
+ for (int ii = 0; ii < states.count(); ++ii) {
+ if (states.at(ii)->name() == currentState) {
+ newState = states.at(ii);
+ break;
+ }
+ }
+
+ if (oldState == 0 || newState == 0) {
+ if (!nullState) { nullState = new QDeclarative1State; QDeclarative_setParent_noEvent(nullState, q); }
+ if (!oldState) oldState = nullState;
+ if (!newState) newState = nullState;
+ }
+
+ newState->apply(q, transition, oldState);
+ applyingState = false;
+ if (!transition)
+ static_cast<QDeclarative1StatePrivate*>(QObjectPrivate::get(newState))->complete();
+}
+
+QDeclarative1State *QDeclarative1StateGroup::findState(const QString &name) const
+{
+ Q_D(const QDeclarative1StateGroup);
+ for (int i = 0; i < d->states.count(); ++i) {
+ QDeclarative1State *state = d->states.at(i);
+ if (state->name() == name)
+ return state;
+ }
+
+ return 0;
+}
+
+void QDeclarative1StateGroup::removeState(QDeclarative1State *state)
+{
+ Q_D(QDeclarative1StateGroup);
+ d->states.removeOne(state);
+}
+
+
+
+QT_END_NAMESPACE
+
+
diff --git a/src/qtquick1/util/qdeclarativestategroup_p.h b/src/qtquick1/util/qdeclarativestategroup_p.h
new file mode 100644
index 0000000000..e7831d4cca
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativestategroup_p.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVESTATEGROUP_H
+#define QDECLARATIVESTATEGROUP_H
+
+#include "QtQuick1/private/qdeclarativestate_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+
+QT_MODULE(Declarative)
+
+class QDeclarative1StateGroupPrivate;
+class Q_DECLARATIVE_EXPORT QDeclarative1StateGroup : public QObject, public QDeclarativeParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QDeclarativeParserStatus)
+ Q_DECLARE_PRIVATE(QDeclarative1StateGroup)
+
+ Q_PROPERTY(QString state READ state WRITE setState NOTIFY stateChanged)
+ Q_PROPERTY(QDeclarativeListProperty<QDeclarative1State> states READ statesProperty DESIGNABLE false)
+ Q_PROPERTY(QDeclarativeListProperty<QDeclarative1Transition> transitions READ transitionsProperty DESIGNABLE false)
+
+public:
+ QDeclarative1StateGroup(QObject * = 0);
+ virtual ~QDeclarative1StateGroup();
+
+ QString state() const;
+ void setState(const QString &);
+
+ QDeclarativeListProperty<QDeclarative1State> statesProperty();
+ QList<QDeclarative1State *> states() const;
+
+ QDeclarativeListProperty<QDeclarative1Transition> transitionsProperty();
+
+ QDeclarative1State *findState(const QString &name) const;
+
+ virtual void classBegin();
+ virtual void componentComplete();
+Q_SIGNALS:
+ void stateChanged(const QString &);
+
+private:
+ friend class QDeclarative1State;
+ bool updateAutoState();
+ void removeState(QDeclarative1State *state);
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1StateGroup)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVESTATEGROUP_H
diff --git a/src/qtquick1/util/qdeclarativestateoperations.cpp b/src/qtquick1/util/qdeclarativestateoperations.cpp
new file mode 100644
index 0000000000..26a8e33f6b
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativestateoperations.cpp
@@ -0,0 +1,1591 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativestateoperations_p.h"
+#include "QtQuick1/private/qdeclarativeanchors_p_p.h"
+#include "QtQuick1/private/qdeclarativeitem_p.h"
+#include "QtDeclarative/private/qdeclarativenullablevalue_p_p.h"
+
+#include <QtDeclarative/qdeclarative.h>
+#include <QtDeclarative/qdeclarativecontext.h>
+#include <QtDeclarative/qdeclarativeexpression.h>
+#include <QtDeclarative/qdeclarativeinfo.h>
+#include <QtDeclarative/private/qdeclarativeguard_p.h>
+#include <QtDeclarative/private/qdeclarativecontext_p.h>
+#include <QtDeclarative/private/qdeclarativeproperty_p.h>
+#include <QtDeclarative/private/qdeclarativebinding_p.h>
+#include <QtQuick1/private/qdeclarativestate_p_p.h>
+
+#include <QtCore/qdebug.h>
+#include <QtGui/qgraphicsitem.h>
+#include <QtCore/qmath.h>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+
+
+class QDeclarative1ParentChangePrivate : public QDeclarative1StateOperationPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1ParentChange)
+public:
+ QDeclarative1ParentChangePrivate() : target(0), parent(0), origParent(0), origStackBefore(0),
+ rewindParent(0), rewindStackBefore(0) {}
+
+ QDeclarativeItem *target;
+ QDeclarativeGuard<QDeclarativeItem> parent;
+ QDeclarativeGuard<QDeclarativeItem> origParent;
+ QDeclarativeGuard<QDeclarativeItem> origStackBefore;
+ QDeclarativeItem *rewindParent;
+ QDeclarativeItem *rewindStackBefore;
+
+ QDeclarativeNullableValue<QDeclarativeScriptString> xString;
+ QDeclarativeNullableValue<QDeclarativeScriptString> yString;
+ QDeclarativeNullableValue<QDeclarativeScriptString> widthString;
+ QDeclarativeNullableValue<QDeclarativeScriptString> heightString;
+ QDeclarativeNullableValue<QDeclarativeScriptString> scaleString;
+ QDeclarativeNullableValue<QDeclarativeScriptString> rotationString;
+
+ QDeclarativeNullableValue<qreal> x;
+ QDeclarativeNullableValue<qreal> y;
+ QDeclarativeNullableValue<qreal> width;
+ QDeclarativeNullableValue<qreal> height;
+ QDeclarativeNullableValue<qreal> scale;
+ QDeclarativeNullableValue<qreal> rotation;
+
+ void doChange(QDeclarativeItem *targetParent, QDeclarativeItem *stackBefore = 0);
+};
+
+void QDeclarative1ParentChangePrivate::doChange(QDeclarativeItem *targetParent, QDeclarativeItem *stackBefore)
+{
+ if (targetParent && target && target->parentItem()) {
+ Q_Q(QDeclarative1ParentChange);
+ bool ok;
+ const QTransform &transform = target->parentItem()->itemTransform(targetParent, &ok);
+ if (transform.type() >= QTransform::TxShear || !ok) {
+ qmlInfo(q) << QDeclarative1ParentChange::tr("Unable to preserve appearance under complex transform");
+ ok = false;
+ }
+
+ qreal scale = 1;
+ qreal rotation = 0;
+ bool isRotate = (transform.type() == QTransform::TxRotate) || (transform.m11() < 0);
+ if (ok && !isRotate) {
+ if (transform.m11() == transform.m22())
+ scale = transform.m11();
+ else {
+ qmlInfo(q) << QDeclarative1ParentChange::tr("Unable to preserve appearance under non-uniform scale");
+ ok = false;
+ }
+ } else if (ok && isRotate) {
+ if (transform.m11() == transform.m22())
+ scale = qSqrt(transform.m11()*transform.m11() + transform.m12()*transform.m12());
+ else {
+ qmlInfo(q) << QDeclarative1ParentChange::tr("Unable to preserve appearance under non-uniform scale");
+ ok = false;
+ }
+
+ if (scale != 0)
+ rotation = atan2(transform.m12()/scale, transform.m11()/scale) * 180/M_PI;
+ else {
+ qmlInfo(q) << QDeclarative1ParentChange::tr("Unable to preserve appearance under scale of 0");
+ ok = false;
+ }
+ }
+
+ const QPointF &point = transform.map(QPointF(target->x(),target->y()));
+ qreal x = point.x();
+ qreal y = point.y();
+
+ // setParentItem will update the transformOriginPoint if needed
+ target->setParentItem(targetParent);
+
+ if (ok && target->transformOrigin() != QDeclarativeItem::TopLeft) {
+ qreal tempxt = target->transformOriginPoint().x();
+ qreal tempyt = target->transformOriginPoint().y();
+ QTransform t;
+ t.translate(-tempxt, -tempyt);
+ t.rotate(rotation);
+ t.scale(scale, scale);
+ t.translate(tempxt, tempyt);
+ const QPointF &offset = t.map(QPointF(0,0));
+ x += offset.x();
+ y += offset.y();
+ }
+
+ if (ok) {
+ //qDebug() << x << y << rotation << scale;
+ target->setX(x);
+ target->setY(y);
+ target->setRotation(target->rotation() + rotation);
+ target->setScale(target->scale() * scale);
+ }
+ } else if (target) {
+ target->setParentItem(targetParent);
+ }
+
+ //restore the original stack position.
+ //### if stackBefore has also been reparented this won't work
+ if (stackBefore)
+ target->stackBefore(stackBefore);
+}
+
+/*!
+ \preliminary
+ \qmlclass ParentChange QDeclarative1ParentChange
+ \ingroup qml-state-elements
+ \brief The ParentChange element allows you to reparent an Item in a state change.
+
+ ParentChange reparents an item while preserving its visual appearance (position, size,
+ rotation, and scale) on screen. You can then specify a transition to move/resize/rotate/scale
+ the item to its final intended appearance.
+
+ ParentChange can only preserve visual appearance if no complex transforms are involved.
+ More specifically, it will not work if the transform property has been set for any
+ items involved in the reparenting (i.e. items in the common ancestor tree
+ for the original and new parent).
+
+ The example below displays a large red rectangle and a small blue rectangle, side by side.
+ When the \c blueRect is clicked, it changes to the "reparented" state: its parent is changed to \c redRect and it is
+ positioned at (10, 10) within the red rectangle, as specified in the ParentChange.
+
+ \snippet doc/src/snippets/declarative/parentchange.qml 0
+
+ \image parentchange.png
+
+ You can specify at which point in a transition you want a ParentChange to occur by
+ using a ParentAnimation.
+*/
+
+
+QDeclarative1ParentChange::QDeclarative1ParentChange(QObject *parent)
+ : QDeclarative1StateOperation(*(new QDeclarative1ParentChangePrivate), parent)
+{
+}
+
+QDeclarative1ParentChange::~QDeclarative1ParentChange()
+{
+}
+
+/*!
+ \qmlproperty real ParentChange::x
+ \qmlproperty real ParentChange::y
+ \qmlproperty real ParentChange::width
+ \qmlproperty real ParentChange::height
+ \qmlproperty real ParentChange::scale
+ \qmlproperty real ParentChange::rotation
+ These properties hold the new position, size, scale, and rotation
+ for the item in this state.
+*/
+QDeclarativeScriptString QDeclarative1ParentChange::x() const
+{
+ Q_D(const QDeclarative1ParentChange);
+ return d->xString.value;
+}
+
+void tryReal(QDeclarativeNullableValue<qreal> &value, const QString &string)
+{
+ bool ok = false;
+ qreal realValue = string.toFloat(&ok);
+ if (ok)
+ value = realValue;
+ else
+ value.invalidate();
+}
+
+void QDeclarative1ParentChange::setX(QDeclarativeScriptString x)
+{
+ Q_D(QDeclarative1ParentChange);
+ d->xString = x;
+ tryReal(d->x, x.script());
+}
+
+bool QDeclarative1ParentChange::xIsSet() const
+{
+ Q_D(const QDeclarative1ParentChange);
+ return d->xString.isValid();
+}
+
+QDeclarativeScriptString QDeclarative1ParentChange::y() const
+{
+ Q_D(const QDeclarative1ParentChange);
+ return d->yString.value;
+}
+
+void QDeclarative1ParentChange::setY(QDeclarativeScriptString y)
+{
+ Q_D(QDeclarative1ParentChange);
+ d->yString = y;
+ tryReal(d->y, y.script());
+}
+
+bool QDeclarative1ParentChange::yIsSet() const
+{
+ Q_D(const QDeclarative1ParentChange);
+ return d->yString.isValid();
+}
+
+QDeclarativeScriptString QDeclarative1ParentChange::width() const
+{
+ Q_D(const QDeclarative1ParentChange);
+ return d->widthString.value;
+}
+
+void QDeclarative1ParentChange::setWidth(QDeclarativeScriptString width)
+{
+ Q_D(QDeclarative1ParentChange);
+ d->widthString = width;
+ tryReal(d->width, width.script());
+}
+
+bool QDeclarative1ParentChange::widthIsSet() const
+{
+ Q_D(const QDeclarative1ParentChange);
+ return d->widthString.isValid();
+}
+
+QDeclarativeScriptString QDeclarative1ParentChange::height() const
+{
+ Q_D(const QDeclarative1ParentChange);
+ return d->heightString.value;
+}
+
+void QDeclarative1ParentChange::setHeight(QDeclarativeScriptString height)
+{
+ Q_D(QDeclarative1ParentChange);
+ d->heightString = height;
+ tryReal(d->height, height.script());
+}
+
+bool QDeclarative1ParentChange::heightIsSet() const
+{
+ Q_D(const QDeclarative1ParentChange);
+ return d->heightString.isValid();
+}
+
+QDeclarativeScriptString QDeclarative1ParentChange::scale() const
+{
+ Q_D(const QDeclarative1ParentChange);
+ return d->scaleString.value;
+}
+
+void QDeclarative1ParentChange::setScale(QDeclarativeScriptString scale)
+{
+ Q_D(QDeclarative1ParentChange);
+ d->scaleString = scale;
+ tryReal(d->scale, scale.script());
+}
+
+bool QDeclarative1ParentChange::scaleIsSet() const
+{
+ Q_D(const QDeclarative1ParentChange);
+ return d->scaleString.isValid();
+}
+
+QDeclarativeScriptString QDeclarative1ParentChange::rotation() const
+{
+ Q_D(const QDeclarative1ParentChange);
+ return d->rotationString.value;
+}
+
+void QDeclarative1ParentChange::setRotation(QDeclarativeScriptString rotation)
+{
+ Q_D(QDeclarative1ParentChange);
+ d->rotationString = rotation;
+ tryReal(d->rotation, rotation.script());
+}
+
+bool QDeclarative1ParentChange::rotationIsSet() const
+{
+ Q_D(const QDeclarative1ParentChange);
+ return d->rotationString.isValid();
+}
+
+QDeclarativeItem *QDeclarative1ParentChange::originalParent() const
+{
+ Q_D(const QDeclarative1ParentChange);
+ return d->origParent;
+}
+
+/*!
+ \qmlproperty Item ParentChange::target
+ This property holds the item to be reparented
+*/
+
+QDeclarativeItem *QDeclarative1ParentChange::object() const
+{
+ Q_D(const QDeclarative1ParentChange);
+ return d->target;
+}
+
+void QDeclarative1ParentChange::setObject(QDeclarativeItem *target)
+{
+ Q_D(QDeclarative1ParentChange);
+ d->target = target;
+}
+
+/*!
+ \qmlproperty Item ParentChange::parent
+ This property holds the new parent for the item in this state.
+*/
+
+QDeclarativeItem *QDeclarative1ParentChange::parent() const
+{
+ Q_D(const QDeclarative1ParentChange);
+ return d->parent;
+}
+
+void QDeclarative1ParentChange::setParent(QDeclarativeItem *parent)
+{
+ Q_D(QDeclarative1ParentChange);
+ d->parent = parent;
+}
+
+QDeclarative1StateOperation::ActionList QDeclarative1ParentChange::actions()
+{
+ Q_D(QDeclarative1ParentChange);
+ if (!d->target || !d->parent)
+ return ActionList();
+
+ ActionList actions;
+
+ QDeclarative1Action a;
+ a.event = this;
+ actions << a;
+
+ QDeclarativeContext *ctxt = qmlContext(this);
+
+ if (d->xString.isValid()) {
+ if (d->x.isValid()) {
+ QDeclarative1Action xa(d->target, QLatin1String("x"), ctxt, d->x.value);
+ actions << xa;
+ } else {
+ QDeclarativeBinding *newBinding = new QDeclarativeBinding(d->xString.value.script(), d->target, ctxt);
+ newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("x"), ctxt));
+ QDeclarative1Action xa;
+ xa.property = newBinding->property();
+ xa.toBinding = newBinding;
+ xa.fromValue = xa.property.read();
+ xa.deletableToBinding = true;
+ actions << xa;
+ }
+ }
+
+ if (d->yString.isValid()) {
+ if (d->y.isValid()) {
+ QDeclarative1Action ya(d->target, QLatin1String("y"), ctxt, d->y.value);
+ actions << ya;
+ } else {
+ QDeclarativeBinding *newBinding = new QDeclarativeBinding(d->yString.value.script(), d->target, ctxt);
+ newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("y"), ctxt));
+ QDeclarative1Action ya;
+ ya.property = newBinding->property();
+ ya.toBinding = newBinding;
+ ya.fromValue = ya.property.read();
+ ya.deletableToBinding = true;
+ actions << ya;
+ }
+ }
+
+ if (d->scaleString.isValid()) {
+ if (d->scale.isValid()) {
+ QDeclarative1Action sa(d->target, QLatin1String("scale"), ctxt, d->scale.value);
+ actions << sa;
+ } else {
+ QDeclarativeBinding *newBinding = new QDeclarativeBinding(d->scaleString.value.script(), d->target, ctxt);
+ newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("scale"), ctxt));
+ QDeclarative1Action sa;
+ sa.property = newBinding->property();
+ sa.toBinding = newBinding;
+ sa.fromValue = sa.property.read();
+ sa.deletableToBinding = true;
+ actions << sa;
+ }
+ }
+
+ if (d->rotationString.isValid()) {
+ if (d->rotation.isValid()) {
+ QDeclarative1Action ra(d->target, QLatin1String("rotation"), ctxt, d->rotation.value);
+ actions << ra;
+ } else {
+ QDeclarativeBinding *newBinding = new QDeclarativeBinding(d->rotationString.value.script(), d->target, ctxt);
+ newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("rotation"), ctxt));
+ QDeclarative1Action ra;
+ ra.property = newBinding->property();
+ ra.toBinding = newBinding;
+ ra.fromValue = ra.property.read();
+ ra.deletableToBinding = true;
+ actions << ra;
+ }
+ }
+
+ if (d->widthString.isValid()) {
+ if (d->width.isValid()) {
+ QDeclarative1Action wa(d->target, QLatin1String("width"), ctxt, d->width.value);
+ actions << wa;
+ } else {
+ QDeclarativeBinding *newBinding = new QDeclarativeBinding(d->widthString.value.script(), d->target, ctxt);
+ newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("width"), ctxt));
+ QDeclarative1Action wa;
+ wa.property = newBinding->property();
+ wa.toBinding = newBinding;
+ wa.fromValue = wa.property.read();
+ wa.deletableToBinding = true;
+ actions << wa;
+ }
+ }
+
+ if (d->heightString.isValid()) {
+ if (d->height.isValid()) {
+ QDeclarative1Action ha(d->target, QLatin1String("height"), ctxt, d->height.value);
+ actions << ha;
+ } else {
+ QDeclarativeBinding *newBinding = new QDeclarativeBinding(d->heightString.value.script(), d->target, ctxt);
+ newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("height"), ctxt));
+ QDeclarative1Action ha;
+ ha.property = newBinding->property();
+ ha.toBinding = newBinding;
+ ha.fromValue = ha.property.read();
+ ha.deletableToBinding = true;
+ actions << ha;
+ }
+ }
+
+ return actions;
+}
+
+class AccessibleFxItem : public QDeclarativeItem
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarativeItem)
+public:
+ int siblingIndex() {
+ Q_D(QDeclarativeItem);
+ return d->siblingIndex;
+ }
+};
+
+void QDeclarative1ParentChange::saveOriginals()
+{
+ Q_D(QDeclarative1ParentChange);
+ saveCurrentValues();
+ d->origParent = d->rewindParent;
+ d->origStackBefore = d->rewindStackBefore;
+}
+
+/*void QDeclarative1ParentChange::copyOriginals(QDeclarative1ActionEvent *other)
+{
+ Q_D(QDeclarative1ParentChange);
+ QDeclarative1ParentChange *pc = static_cast<QDeclarative1ParentChange*>(other);
+
+ d->origParent = pc->d_func()->rewindParent;
+ d->origStackBefore = pc->d_func()->rewindStackBefore;
+
+ saveCurrentValues();
+}*/
+
+void QDeclarative1ParentChange::execute(Reason)
+{
+ Q_D(QDeclarative1ParentChange);
+ d->doChange(d->parent);
+}
+
+bool QDeclarative1ParentChange::isReversable()
+{
+ return true;
+}
+
+void QDeclarative1ParentChange::reverse(Reason)
+{
+ Q_D(QDeclarative1ParentChange);
+ d->doChange(d->origParent, d->origStackBefore);
+}
+
+QString QDeclarative1ParentChange::typeName() const
+{
+ return QLatin1String("ParentChange");
+}
+
+bool QDeclarative1ParentChange::override(QDeclarative1ActionEvent*other)
+{
+ Q_D(QDeclarative1ParentChange);
+ if (other->typeName() != QLatin1String("ParentChange"))
+ return false;
+ if (QDeclarative1ParentChange *otherPC = static_cast<QDeclarative1ParentChange*>(other))
+ return (d->target == otherPC->object());
+ return false;
+}
+
+void QDeclarative1ParentChange::saveCurrentValues()
+{
+ Q_D(QDeclarative1ParentChange);
+ if (!d->target) {
+ d->rewindParent = 0;
+ d->rewindStackBefore = 0;
+ return;
+ }
+
+ d->rewindParent = d->target->parentItem();
+ d->rewindStackBefore = 0;
+
+ if (!d->rewindParent)
+ return;
+
+ //try to determine the item's original stack position so we can restore it
+ int siblingIndex = ((AccessibleFxItem*)d->target)->siblingIndex() + 1;
+ QList<QGraphicsItem*> children = d->rewindParent->childItems();
+ for (int i = 0; i < children.count(); ++i) {
+ QDeclarativeItem *child = qobject_cast<QDeclarativeItem*>(children.at(i));
+ if (!child)
+ continue;
+ if (((AccessibleFxItem*)child)->siblingIndex() == siblingIndex) {
+ d->rewindStackBefore = child;
+ break;
+ }
+ }
+}
+
+void QDeclarative1ParentChange::rewind()
+{
+ Q_D(QDeclarative1ParentChange);
+ d->doChange(d->rewindParent, d->rewindStackBefore);
+}
+
+class QDeclarative1StateChangeScriptPrivate : public QDeclarative1StateOperationPrivate
+{
+public:
+ QDeclarative1StateChangeScriptPrivate() {}
+
+ QDeclarativeScriptString script;
+ QString name;
+};
+
+/*!
+ \qmlclass StateChangeScript QDeclarative1StateChangeScript
+ \ingroup qml-state-elements
+ \brief The StateChangeScript element allows you to run a script in a state.
+
+ A StateChangeScript is run upon entering a state. You can optionally use
+ ScriptAction to specify the point in the transition at which
+ the StateChangeScript should to be run.
+
+ \snippet snippets/declarative/states/statechangescript.qml state and transition
+
+ \sa ScriptAction
+*/
+
+QDeclarative1StateChangeScript::QDeclarative1StateChangeScript(QObject *parent)
+: QDeclarative1StateOperation(*(new QDeclarative1StateChangeScriptPrivate), parent)
+{
+}
+
+QDeclarative1StateChangeScript::~QDeclarative1StateChangeScript()
+{
+}
+
+/*!
+ \qmlproperty script StateChangeScript::script
+ This property holds the script to run when the state is current.
+*/
+QDeclarativeScriptString QDeclarative1StateChangeScript::script() const
+{
+ Q_D(const QDeclarative1StateChangeScript);
+ return d->script;
+}
+
+void QDeclarative1StateChangeScript::setScript(const QDeclarativeScriptString &s)
+{
+ Q_D(QDeclarative1StateChangeScript);
+ d->script = s;
+}
+
+/*!
+ \qmlproperty string StateChangeScript::name
+ This property holds the name of the script. This name can be used by a
+ ScriptAction to target a specific script.
+
+ \sa ScriptAction::scriptName
+*/
+QString QDeclarative1StateChangeScript::name() const
+{
+ Q_D(const QDeclarative1StateChangeScript);
+ return d->name;
+}
+
+void QDeclarative1StateChangeScript::setName(const QString &n)
+{
+ Q_D(QDeclarative1StateChangeScript);
+ d->name = n;
+}
+
+void QDeclarative1StateChangeScript::execute(Reason)
+{
+ Q_D(QDeclarative1StateChangeScript);
+ const QString &script = d->script.script();
+ if (!script.isEmpty()) {
+ QDeclarativeExpression expr(d->script.context(), d->script.scopeObject(), script);
+ QDeclarativeData *ddata = QDeclarativeData::get(this);
+ if (ddata && ddata->outerContext && !ddata->outerContext->url.isEmpty())
+ expr.setSourceLocation(ddata->outerContext->url.toString(), ddata->lineNumber);
+ expr.evaluate();
+ if (expr.hasError())
+ qmlInfo(this, expr.error());
+ }
+}
+
+QDeclarative1StateChangeScript::ActionList QDeclarative1StateChangeScript::actions()
+{
+ ActionList rv;
+ QDeclarative1Action a;
+ a.event = this;
+ rv << a;
+ return rv;
+}
+
+QString QDeclarative1StateChangeScript::typeName() const
+{
+ return QLatin1String("StateChangeScript");
+}
+
+/*!
+ \qmlclass AnchorChanges QDeclarative1AnchorChanges
+ \ingroup qml-state-elements
+ \brief The AnchorChanges element allows you to change the anchors of an item in a state.
+
+ The AnchorChanges element is used to modify the anchors of an item in a \l State.
+
+ AnchorChanges cannot be used to modify the margins on an item. For this, use
+ PropertyChanges intead.
+
+ In the following example we change the top and bottom anchors of an item
+ using AnchorChanges, and the top and bottom anchor margins using
+ PropertyChanges:
+
+ \snippet doc/src/snippets/declarative/anchorchanges.qml 0
+
+ \image anchorchanges.png
+
+ AnchorChanges can be animated using AnchorAnimation.
+ \qml
+ //animate our anchor changes
+ Transition {
+ AnchorAnimation {}
+ }
+ \endqml
+
+ Margin animations can be animated using NumberAnimation.
+
+ For more information on anchors see \l {anchor-layout}{Anchor Layouts}.
+*/
+
+class QDeclarative1AnchorSetPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1AnchorSet)
+public:
+ QDeclarative1AnchorSetPrivate()
+ : usedAnchors(0), resetAnchors(0), fill(0),
+ centerIn(0)/*, leftMargin(0), rightMargin(0), topMargin(0), bottomMargin(0),
+ margins(0), vCenterOffset(0), hCenterOffset(0), baselineOffset(0)*/
+ {
+ }
+
+ QDeclarative1Anchors::Anchors usedAnchors;
+ QDeclarative1Anchors::Anchors resetAnchors;
+
+ QDeclarativeItem *fill;
+ QDeclarativeItem *centerIn;
+
+ QDeclarativeScriptString leftScript;
+ QDeclarativeScriptString rightScript;
+ QDeclarativeScriptString topScript;
+ QDeclarativeScriptString bottomScript;
+ QDeclarativeScriptString hCenterScript;
+ QDeclarativeScriptString vCenterScript;
+ QDeclarativeScriptString baselineScript;
+
+ /*qreal leftMargin;
+ qreal rightMargin;
+ qreal topMargin;
+ qreal bottomMargin;
+ qreal margins;
+ qreal vCenterOffset;
+ qreal hCenterOffset;
+ qreal baselineOffset;*/
+};
+
+QDeclarative1AnchorSet::QDeclarative1AnchorSet(QObject *parent)
+ : QObject(*new QDeclarative1AnchorSetPrivate, parent)
+{
+}
+
+QDeclarative1AnchorSet::~QDeclarative1AnchorSet()
+{
+}
+
+QDeclarativeScriptString QDeclarative1AnchorSet::top() const
+{
+ Q_D(const QDeclarative1AnchorSet);
+ return d->topScript;
+}
+
+void QDeclarative1AnchorSet::setTop(const QDeclarativeScriptString &edge)
+{
+ Q_D(QDeclarative1AnchorSet);
+ d->usedAnchors |= QDeclarative1Anchors::TopAnchor;
+ d->topScript = edge;
+ if (edge.script() == QLatin1String("undefined"))
+ resetTop();
+}
+
+void QDeclarative1AnchorSet::resetTop()
+{
+ Q_D(QDeclarative1AnchorSet);
+ d->usedAnchors &= ~QDeclarative1Anchors::TopAnchor;
+ d->topScript = QDeclarativeScriptString();
+ d->resetAnchors |= QDeclarative1Anchors::TopAnchor;
+}
+
+QDeclarativeScriptString QDeclarative1AnchorSet::bottom() const
+{
+ Q_D(const QDeclarative1AnchorSet);
+ return d->bottomScript;
+}
+
+void QDeclarative1AnchorSet::setBottom(const QDeclarativeScriptString &edge)
+{
+ Q_D(QDeclarative1AnchorSet);
+ d->usedAnchors |= QDeclarative1Anchors::BottomAnchor;
+ d->bottomScript = edge;
+ if (edge.script() == QLatin1String("undefined"))
+ resetBottom();
+}
+
+void QDeclarative1AnchorSet::resetBottom()
+{
+ Q_D(QDeclarative1AnchorSet);
+ d->usedAnchors &= ~QDeclarative1Anchors::BottomAnchor;
+ d->bottomScript = QDeclarativeScriptString();
+ d->resetAnchors |= QDeclarative1Anchors::BottomAnchor;
+}
+
+QDeclarativeScriptString QDeclarative1AnchorSet::verticalCenter() const
+{
+ Q_D(const QDeclarative1AnchorSet);
+ return d->vCenterScript;
+}
+
+void QDeclarative1AnchorSet::setVerticalCenter(const QDeclarativeScriptString &edge)
+{
+ Q_D(QDeclarative1AnchorSet);
+ d->usedAnchors |= QDeclarative1Anchors::VCenterAnchor;
+ d->vCenterScript = edge;
+ if (edge.script() == QLatin1String("undefined"))
+ resetVerticalCenter();
+}
+
+void QDeclarative1AnchorSet::resetVerticalCenter()
+{
+ Q_D(QDeclarative1AnchorSet);
+ d->usedAnchors &= ~QDeclarative1Anchors::VCenterAnchor;
+ d->vCenterScript = QDeclarativeScriptString();
+ d->resetAnchors |= QDeclarative1Anchors::VCenterAnchor;
+}
+
+QDeclarativeScriptString QDeclarative1AnchorSet::baseline() const
+{
+ Q_D(const QDeclarative1AnchorSet);
+ return d->baselineScript;
+}
+
+void QDeclarative1AnchorSet::setBaseline(const QDeclarativeScriptString &edge)
+{
+ Q_D(QDeclarative1AnchorSet);
+ d->usedAnchors |= QDeclarative1Anchors::BaselineAnchor;
+ d->baselineScript = edge;
+ if (edge.script() == QLatin1String("undefined"))
+ resetBaseline();
+}
+
+void QDeclarative1AnchorSet::resetBaseline()
+{
+ Q_D(QDeclarative1AnchorSet);
+ d->usedAnchors &= ~QDeclarative1Anchors::BaselineAnchor;
+ d->baselineScript = QDeclarativeScriptString();
+ d->resetAnchors |= QDeclarative1Anchors::BaselineAnchor;
+}
+
+QDeclarativeScriptString QDeclarative1AnchorSet::left() const
+{
+ Q_D(const QDeclarative1AnchorSet);
+ return d->leftScript;
+}
+
+void QDeclarative1AnchorSet::setLeft(const QDeclarativeScriptString &edge)
+{
+ Q_D(QDeclarative1AnchorSet);
+ d->usedAnchors |= QDeclarative1Anchors::LeftAnchor;
+ d->leftScript = edge;
+ if (edge.script() == QLatin1String("undefined"))
+ resetLeft();
+}
+
+void QDeclarative1AnchorSet::resetLeft()
+{
+ Q_D(QDeclarative1AnchorSet);
+ d->usedAnchors &= ~QDeclarative1Anchors::LeftAnchor;
+ d->leftScript = QDeclarativeScriptString();
+ d->resetAnchors |= QDeclarative1Anchors::LeftAnchor;
+}
+
+QDeclarativeScriptString QDeclarative1AnchorSet::right() const
+{
+ Q_D(const QDeclarative1AnchorSet);
+ return d->rightScript;
+}
+
+void QDeclarative1AnchorSet::setRight(const QDeclarativeScriptString &edge)
+{
+ Q_D(QDeclarative1AnchorSet);
+ d->usedAnchors |= QDeclarative1Anchors::RightAnchor;
+ d->rightScript = edge;
+ if (edge.script() == QLatin1String("undefined"))
+ resetRight();
+}
+
+void QDeclarative1AnchorSet::resetRight()
+{
+ Q_D(QDeclarative1AnchorSet);
+ d->usedAnchors &= ~QDeclarative1Anchors::RightAnchor;
+ d->rightScript = QDeclarativeScriptString();
+ d->resetAnchors |= QDeclarative1Anchors::RightAnchor;
+}
+
+QDeclarativeScriptString QDeclarative1AnchorSet::horizontalCenter() const
+{
+ Q_D(const QDeclarative1AnchorSet);
+ return d->hCenterScript;
+}
+
+void QDeclarative1AnchorSet::setHorizontalCenter(const QDeclarativeScriptString &edge)
+{
+ Q_D(QDeclarative1AnchorSet);
+ d->usedAnchors |= QDeclarative1Anchors::HCenterAnchor;
+ d->hCenterScript = edge;
+ if (edge.script() == QLatin1String("undefined"))
+ resetHorizontalCenter();
+}
+
+void QDeclarative1AnchorSet::resetHorizontalCenter()
+{
+ Q_D(QDeclarative1AnchorSet);
+ d->usedAnchors &= ~QDeclarative1Anchors::HCenterAnchor;
+ d->hCenterScript = QDeclarativeScriptString();
+ d->resetAnchors |= QDeclarative1Anchors::HCenterAnchor;
+}
+
+QDeclarativeItem *QDeclarative1AnchorSet::fill() const
+{
+ Q_D(const QDeclarative1AnchorSet);
+ return d->fill;
+}
+
+void QDeclarative1AnchorSet::setFill(QDeclarativeItem *f)
+{
+ Q_D(QDeclarative1AnchorSet);
+ d->fill = f;
+}
+
+void QDeclarative1AnchorSet::resetFill()
+{
+ setFill(0);
+}
+
+QDeclarativeItem *QDeclarative1AnchorSet::centerIn() const
+{
+ Q_D(const QDeclarative1AnchorSet);
+ return d->centerIn;
+}
+
+void QDeclarative1AnchorSet::setCenterIn(QDeclarativeItem* c)
+{
+ Q_D(QDeclarative1AnchorSet);
+ d->centerIn = c;
+}
+
+void QDeclarative1AnchorSet::resetCenterIn()
+{
+ setCenterIn(0);
+}
+
+
+class QDeclarative1AnchorChangesPrivate : public QDeclarative1StateOperationPrivate
+{
+public:
+ QDeclarative1AnchorChangesPrivate()
+ : target(0), anchorSet(new QDeclarative1AnchorSet),
+ leftBinding(0), rightBinding(0), hCenterBinding(0),
+ topBinding(0), bottomBinding(0), vCenterBinding(0), baselineBinding(0),
+ origLeftBinding(0), origRightBinding(0), origHCenterBinding(0),
+ origTopBinding(0), origBottomBinding(0), origVCenterBinding(0),
+ origBaselineBinding(0)
+ {
+
+ }
+ ~QDeclarative1AnchorChangesPrivate() { delete anchorSet; }
+
+ QDeclarativeItem *target;
+ QDeclarative1AnchorSet *anchorSet;
+
+ QDeclarativeBinding *leftBinding;
+ QDeclarativeBinding *rightBinding;
+ QDeclarativeBinding *hCenterBinding;
+ QDeclarativeBinding *topBinding;
+ QDeclarativeBinding *bottomBinding;
+ QDeclarativeBinding *vCenterBinding;
+ QDeclarativeBinding *baselineBinding;
+
+ QDeclarativeAbstractBinding *origLeftBinding;
+ QDeclarativeAbstractBinding *origRightBinding;
+ QDeclarativeAbstractBinding *origHCenterBinding;
+ QDeclarativeAbstractBinding *origTopBinding;
+ QDeclarativeAbstractBinding *origBottomBinding;
+ QDeclarativeAbstractBinding *origVCenterBinding;
+ QDeclarativeAbstractBinding *origBaselineBinding;
+
+ QDeclarative1AnchorLine rewindLeft;
+ QDeclarative1AnchorLine rewindRight;
+ QDeclarative1AnchorLine rewindHCenter;
+ QDeclarative1AnchorLine rewindTop;
+ QDeclarative1AnchorLine rewindBottom;
+ QDeclarative1AnchorLine rewindVCenter;
+ QDeclarative1AnchorLine rewindBaseline;
+
+ qreal fromX;
+ qreal fromY;
+ qreal fromWidth;
+ qreal fromHeight;
+
+ qreal toX;
+ qreal toY;
+ qreal toWidth;
+ qreal toHeight;
+
+ qreal rewindX;
+ qreal rewindY;
+ qreal rewindWidth;
+ qreal rewindHeight;
+
+ bool applyOrigLeft;
+ bool applyOrigRight;
+ bool applyOrigHCenter;
+ bool applyOrigTop;
+ bool applyOrigBottom;
+ bool applyOrigVCenter;
+ bool applyOrigBaseline;
+
+ QDeclarativeNullableValue<qreal> origWidth;
+ QDeclarativeNullableValue<qreal> origHeight;
+ qreal origX;
+ qreal origY;
+
+ QList<QDeclarativeAbstractBinding*> oldBindings;
+
+ QDeclarativeProperty leftProp;
+ QDeclarativeProperty rightProp;
+ QDeclarativeProperty hCenterProp;
+ QDeclarativeProperty topProp;
+ QDeclarativeProperty bottomProp;
+ QDeclarativeProperty vCenterProp;
+ QDeclarativeProperty baselineProp;
+};
+
+/*!
+ \qmlproperty Item AnchorChanges::target
+ This property holds the \l Item for which the anchor changes will be applied.
+*/
+
+QDeclarative1AnchorChanges::QDeclarative1AnchorChanges(QObject *parent)
+ : QDeclarative1StateOperation(*(new QDeclarative1AnchorChangesPrivate), parent)
+{
+}
+
+QDeclarative1AnchorChanges::~QDeclarative1AnchorChanges()
+{
+}
+
+QDeclarative1AnchorChanges::ActionList QDeclarative1AnchorChanges::actions()
+{
+ Q_D(QDeclarative1AnchorChanges);
+ d->leftBinding = d->rightBinding = d->hCenterBinding = d->topBinding
+ = d->bottomBinding = d->vCenterBinding = d->baselineBinding = 0;
+
+ d->leftProp = QDeclarativeProperty(d->target, QLatin1String("anchors.left"));
+ d->rightProp = QDeclarativeProperty(d->target, QLatin1String("anchors.right"));
+ d->hCenterProp = QDeclarativeProperty(d->target, QLatin1String("anchors.horizontalCenter"));
+ d->topProp = QDeclarativeProperty(d->target, QLatin1String("anchors.top"));
+ d->bottomProp = QDeclarativeProperty(d->target, QLatin1String("anchors.bottom"));
+ d->vCenterProp = QDeclarativeProperty(d->target, QLatin1String("anchors.verticalCenter"));
+ d->baselineProp = QDeclarativeProperty(d->target, QLatin1String("anchors.baseline"));
+
+ QDeclarativeContext *ctxt = qmlContext(this);
+
+ if (d->anchorSet->d_func()->usedAnchors & QDeclarative1Anchors::LeftAnchor) {
+ d->leftBinding = new QDeclarativeBinding(d->anchorSet->d_func()->leftScript.script(), d->target, ctxt);
+ d->leftBinding->setTarget(d->leftProp);
+ }
+ if (d->anchorSet->d_func()->usedAnchors & QDeclarative1Anchors::RightAnchor) {
+ d->rightBinding = new QDeclarativeBinding(d->anchorSet->d_func()->rightScript.script(), d->target, ctxt);
+ d->rightBinding->setTarget(d->rightProp);
+ }
+ if (d->anchorSet->d_func()->usedAnchors & QDeclarative1Anchors::HCenterAnchor) {
+ d->hCenterBinding = new QDeclarativeBinding(d->anchorSet->d_func()->hCenterScript.script(), d->target, ctxt);
+ d->hCenterBinding->setTarget(d->hCenterProp);
+ }
+ if (d->anchorSet->d_func()->usedAnchors & QDeclarative1Anchors::TopAnchor) {
+ d->topBinding = new QDeclarativeBinding(d->anchorSet->d_func()->topScript.script(), d->target, ctxt);
+ d->topBinding->setTarget(d->topProp);
+ }
+ if (d->anchorSet->d_func()->usedAnchors & QDeclarative1Anchors::BottomAnchor) {
+ d->bottomBinding = new QDeclarativeBinding(d->anchorSet->d_func()->bottomScript.script(), d->target, ctxt);
+ d->bottomBinding->setTarget(d->bottomProp);
+ }
+ if (d->anchorSet->d_func()->usedAnchors & QDeclarative1Anchors::VCenterAnchor) {
+ d->vCenterBinding = new QDeclarativeBinding(d->anchorSet->d_func()->vCenterScript.script(), d->target, ctxt);
+ d->vCenterBinding->setTarget(d->vCenterProp);
+ }
+ if (d->anchorSet->d_func()->usedAnchors & QDeclarative1Anchors::BaselineAnchor) {
+ d->baselineBinding = new QDeclarativeBinding(d->anchorSet->d_func()->baselineScript.script(), d->target, ctxt);
+ d->baselineBinding->setTarget(d->baselineProp);
+ }
+
+ QDeclarative1Action a;
+ a.event = this;
+ return ActionList() << a;
+}
+
+QDeclarative1AnchorSet *QDeclarative1AnchorChanges::anchors()
+{
+ Q_D(QDeclarative1AnchorChanges);
+ return d->anchorSet;
+}
+
+QDeclarativeItem *QDeclarative1AnchorChanges::object() const
+{
+ Q_D(const QDeclarative1AnchorChanges);
+ return d->target;
+}
+
+void QDeclarative1AnchorChanges::setObject(QDeclarativeItem *target)
+{
+ Q_D(QDeclarative1AnchorChanges);
+ d->target = target;
+}
+
+/*!
+ \qmlproperty AnchorLine AnchorChanges::anchors.left
+ \qmlproperty AnchorLine AnchorChanges::anchors.right
+ \qmlproperty AnchorLine AnchorChanges::anchors.horizontalCenter
+ \qmlproperty AnchorLine AnchorChanges::anchors.top
+ \qmlproperty AnchorLine AnchorChanges::anchors.bottom
+ \qmlproperty AnchorLine AnchorChanges::anchors.verticalCenter
+ \qmlproperty AnchorLine AnchorChanges::anchors.baseline
+
+ These properties change the respective anchors of the item.
+
+ To reset an anchor you can assign \c undefined:
+ \qml
+ AnchorChanges {
+ target: myItem
+ anchors.left: undefined //remove myItem's left anchor
+ anchors.right: otherItem.right
+ }
+ \endqml
+*/
+
+void QDeclarative1AnchorChanges::execute(Reason reason)
+{
+ Q_D(QDeclarative1AnchorChanges);
+ if (!d->target)
+ return;
+
+ QDeclarativeItemPrivate *targetPrivate = QDeclarativeItemPrivate::get(d->target);
+ //incorporate any needed "reverts"
+ if (d->applyOrigLeft) {
+ if (!d->origLeftBinding)
+ targetPrivate->anchors()->resetLeft();
+ QDeclarativePropertyPrivate::setBinding(d->leftProp, d->origLeftBinding);
+ }
+ if (d->applyOrigRight) {
+ if (!d->origRightBinding)
+ targetPrivate->anchors()->resetRight();
+ QDeclarativePropertyPrivate::setBinding(d->rightProp, d->origRightBinding);
+ }
+ if (d->applyOrigHCenter) {
+ if (!d->origHCenterBinding)
+ targetPrivate->anchors()->resetHorizontalCenter();
+ QDeclarativePropertyPrivate::setBinding(d->hCenterProp, d->origHCenterBinding);
+ }
+ if (d->applyOrigTop) {
+ if (!d->origTopBinding)
+ targetPrivate->anchors()->resetTop();
+ QDeclarativePropertyPrivate::setBinding(d->topProp, d->origTopBinding);
+ }
+ if (d->applyOrigBottom) {
+ if (!d->origBottomBinding)
+ targetPrivate->anchors()->resetBottom();
+ QDeclarativePropertyPrivate::setBinding(d->bottomProp, d->origBottomBinding);
+ }
+ if (d->applyOrigVCenter) {
+ if (!d->origVCenterBinding)
+ targetPrivate->anchors()->resetVerticalCenter();
+ QDeclarativePropertyPrivate::setBinding(d->vCenterProp, d->origVCenterBinding);
+ }
+ if (d->applyOrigBaseline) {
+ if (!d->origBaselineBinding)
+ targetPrivate->anchors()->resetBaseline();
+ QDeclarativePropertyPrivate::setBinding(d->baselineProp, d->origBaselineBinding);
+ }
+
+ //destroy old bindings
+ if (reason == ActualChange) {
+ for (int i = 0; i < d->oldBindings.size(); ++i) {
+ QDeclarativeAbstractBinding *binding = d->oldBindings.at(i);
+ if (binding)
+ binding->destroy();
+ }
+ d->oldBindings.clear();
+ }
+
+ //reset any anchors that have been specified as "undefined"
+ if (d->anchorSet->d_func()->resetAnchors & QDeclarative1Anchors::LeftAnchor) {
+ targetPrivate->anchors()->resetLeft();
+ QDeclarativePropertyPrivate::setBinding(d->leftProp, 0);
+ }
+ if (d->anchorSet->d_func()->resetAnchors & QDeclarative1Anchors::RightAnchor) {
+ targetPrivate->anchors()->resetRight();
+ QDeclarativePropertyPrivate::setBinding(d->rightProp, 0);
+ }
+ if (d->anchorSet->d_func()->resetAnchors & QDeclarative1Anchors::HCenterAnchor) {
+ targetPrivate->anchors()->resetHorizontalCenter();
+ QDeclarativePropertyPrivate::setBinding(d->hCenterProp, 0);
+ }
+ if (d->anchorSet->d_func()->resetAnchors & QDeclarative1Anchors::TopAnchor) {
+ targetPrivate->anchors()->resetTop();
+ QDeclarativePropertyPrivate::setBinding(d->topProp, 0);
+ }
+ if (d->anchorSet->d_func()->resetAnchors & QDeclarative1Anchors::BottomAnchor) {
+ targetPrivate->anchors()->resetBottom();
+ QDeclarativePropertyPrivate::setBinding(d->bottomProp, 0);
+ }
+ if (d->anchorSet->d_func()->resetAnchors & QDeclarative1Anchors::VCenterAnchor) {
+ targetPrivate->anchors()->resetVerticalCenter();
+ QDeclarativePropertyPrivate::setBinding(d->vCenterProp, 0);
+ }
+ if (d->anchorSet->d_func()->resetAnchors & QDeclarative1Anchors::BaselineAnchor) {
+ targetPrivate->anchors()->resetBaseline();
+ QDeclarativePropertyPrivate::setBinding(d->baselineProp, 0);
+ }
+
+ //set any anchors that have been specified
+ if (d->leftBinding)
+ QDeclarativePropertyPrivate::setBinding(d->leftBinding->property(), d->leftBinding);
+ if (d->rightBinding)
+ QDeclarativePropertyPrivate::setBinding(d->rightBinding->property(), d->rightBinding);
+ if (d->hCenterBinding)
+ QDeclarativePropertyPrivate::setBinding(d->hCenterBinding->property(), d->hCenterBinding);
+ if (d->topBinding)
+ QDeclarativePropertyPrivate::setBinding(d->topBinding->property(), d->topBinding);
+ if (d->bottomBinding)
+ QDeclarativePropertyPrivate::setBinding(d->bottomBinding->property(), d->bottomBinding);
+ if (d->vCenterBinding)
+ QDeclarativePropertyPrivate::setBinding(d->vCenterBinding->property(), d->vCenterBinding);
+ if (d->baselineBinding)
+ QDeclarativePropertyPrivate::setBinding(d->baselineBinding->property(), d->baselineBinding);
+}
+
+bool QDeclarative1AnchorChanges::isReversable()
+{
+ return true;
+}
+
+void QDeclarative1AnchorChanges::reverse(Reason reason)
+{
+ Q_D(QDeclarative1AnchorChanges);
+ if (!d->target)
+ return;
+
+ QDeclarativeItemPrivate *targetPrivate = QDeclarativeItemPrivate::get(d->target);
+ //reset any anchors set by the state
+ if (d->leftBinding) {
+ targetPrivate->anchors()->resetLeft();
+ QDeclarativePropertyPrivate::setBinding(d->leftBinding->property(), 0);
+ if (reason == ActualChange) {
+ d->leftBinding->destroy(); d->leftBinding = 0;
+ }
+ }
+ if (d->rightBinding) {
+ targetPrivate->anchors()->resetRight();
+ QDeclarativePropertyPrivate::setBinding(d->rightBinding->property(), 0);
+ if (reason == ActualChange) {
+ d->rightBinding->destroy(); d->rightBinding = 0;
+ }
+ }
+ if (d->hCenterBinding) {
+ targetPrivate->anchors()->resetHorizontalCenter();
+ QDeclarativePropertyPrivate::setBinding(d->hCenterBinding->property(), 0);
+ if (reason == ActualChange) {
+ d->hCenterBinding->destroy(); d->hCenterBinding = 0;
+ }
+ }
+ if (d->topBinding) {
+ targetPrivate->anchors()->resetTop();
+ QDeclarativePropertyPrivate::setBinding(d->topBinding->property(), 0);
+ if (reason == ActualChange) {
+ d->topBinding->destroy(); d->topBinding = 0;
+ }
+ }
+ if (d->bottomBinding) {
+ targetPrivate->anchors()->resetBottom();
+ QDeclarativePropertyPrivate::setBinding(d->bottomBinding->property(), 0);
+ if (reason == ActualChange) {
+ d->bottomBinding->destroy(); d->bottomBinding = 0;
+ }
+ }
+ if (d->vCenterBinding) {
+ targetPrivate->anchors()->resetVerticalCenter();
+ QDeclarativePropertyPrivate::setBinding(d->vCenterBinding->property(), 0);
+ if (reason == ActualChange) {
+ d->vCenterBinding->destroy(); d->vCenterBinding = 0;
+ }
+ }
+ if (d->baselineBinding) {
+ targetPrivate->anchors()->resetBaseline();
+ QDeclarativePropertyPrivate::setBinding(d->baselineBinding->property(), 0);
+ if (reason == ActualChange) {
+ d->baselineBinding->destroy(); d->baselineBinding = 0;
+ }
+ }
+
+ //restore previous anchors
+ if (d->origLeftBinding)
+ QDeclarativePropertyPrivate::setBinding(d->leftProp, d->origLeftBinding);
+ if (d->origRightBinding)
+ QDeclarativePropertyPrivate::setBinding(d->rightProp, d->origRightBinding);
+ if (d->origHCenterBinding)
+ QDeclarativePropertyPrivate::setBinding(d->hCenterProp, d->origHCenterBinding);
+ if (d->origTopBinding)
+ QDeclarativePropertyPrivate::setBinding(d->topProp, d->origTopBinding);
+ if (d->origBottomBinding)
+ QDeclarativePropertyPrivate::setBinding(d->bottomProp, d->origBottomBinding);
+ if (d->origVCenterBinding)
+ QDeclarativePropertyPrivate::setBinding(d->vCenterProp, d->origVCenterBinding);
+ if (d->origBaselineBinding)
+ QDeclarativePropertyPrivate::setBinding(d->baselineProp, d->origBaselineBinding);
+
+ //restore any absolute geometry changed by the state's anchors
+ QDeclarative1Anchors::Anchors stateVAnchors = d->anchorSet->d_func()->usedAnchors & QDeclarative1Anchors::Vertical_Mask;
+ QDeclarative1Anchors::Anchors origVAnchors = targetPrivate->anchors()->usedAnchors() & QDeclarative1Anchors::Vertical_Mask;
+ QDeclarative1Anchors::Anchors stateHAnchors = d->anchorSet->d_func()->usedAnchors & QDeclarative1Anchors::Horizontal_Mask;
+ QDeclarative1Anchors::Anchors origHAnchors = targetPrivate->anchors()->usedAnchors() & QDeclarative1Anchors::Horizontal_Mask;
+
+ bool stateSetWidth = (stateHAnchors &&
+ stateHAnchors != QDeclarative1Anchors::LeftAnchor &&
+ stateHAnchors != QDeclarative1Anchors::RightAnchor &&
+ stateHAnchors != QDeclarative1Anchors::HCenterAnchor);
+ bool origSetWidth = (origHAnchors &&
+ origHAnchors != QDeclarative1Anchors::LeftAnchor &&
+ origHAnchors != QDeclarative1Anchors::RightAnchor &&
+ origHAnchors != QDeclarative1Anchors::HCenterAnchor);
+ if (d->origWidth.isValid() && stateSetWidth && !origSetWidth)
+ d->target->setWidth(d->origWidth.value);
+
+ bool stateSetHeight = (stateVAnchors &&
+ stateVAnchors != QDeclarative1Anchors::TopAnchor &&
+ stateVAnchors != QDeclarative1Anchors::BottomAnchor &&
+ stateVAnchors != QDeclarative1Anchors::VCenterAnchor &&
+ stateVAnchors != QDeclarative1Anchors::BaselineAnchor);
+ bool origSetHeight = (origVAnchors &&
+ origVAnchors != QDeclarative1Anchors::TopAnchor &&
+ origVAnchors != QDeclarative1Anchors::BottomAnchor &&
+ origVAnchors != QDeclarative1Anchors::VCenterAnchor &&
+ origVAnchors != QDeclarative1Anchors::BaselineAnchor);
+ if (d->origHeight.isValid() && stateSetHeight && !origSetHeight)
+ d->target->setHeight(d->origHeight.value);
+
+ if (stateHAnchors && !origHAnchors)
+ d->target->setX(d->origX);
+
+ if (stateVAnchors && !origVAnchors)
+ d->target->setY(d->origY);
+}
+
+QString QDeclarative1AnchorChanges::typeName() const
+{
+ return QLatin1String("AnchorChanges");
+}
+
+QList<QDeclarative1Action> QDeclarative1AnchorChanges::additionalActions()
+{
+ Q_D(QDeclarative1AnchorChanges);
+ QList<QDeclarative1Action> extra;
+
+ QDeclarative1Anchors::Anchors combined = d->anchorSet->d_func()->usedAnchors | d->anchorSet->d_func()->resetAnchors;
+ bool hChange = combined & QDeclarative1Anchors::Horizontal_Mask;
+ bool vChange = combined & QDeclarative1Anchors::Vertical_Mask;
+
+ if (d->target) {
+ QDeclarativeContext *ctxt = qmlContext(this);
+ QDeclarative1Action a;
+ if (hChange && d->fromX != d->toX) {
+ a.property = QDeclarativeProperty(d->target, QLatin1String("x"), ctxt);
+ a.toValue = d->toX;
+ extra << a;
+ }
+ if (vChange && d->fromY != d->toY) {
+ a.property = QDeclarativeProperty(d->target, QLatin1String("y"), ctxt);
+ a.toValue = d->toY;
+ extra << a;
+ }
+ if (hChange && d->fromWidth != d->toWidth) {
+ a.property = QDeclarativeProperty(d->target, QLatin1String("width"), ctxt);
+ a.toValue = d->toWidth;
+ extra << a;
+ }
+ if (vChange && d->fromHeight != d->toHeight) {
+ a.property = QDeclarativeProperty(d->target, QLatin1String("height"), ctxt);
+ a.toValue = d->toHeight;
+ extra << a;
+ }
+ }
+
+ return extra;
+}
+
+bool QDeclarative1AnchorChanges::changesBindings()
+{
+ return true;
+}
+
+void QDeclarative1AnchorChanges::saveOriginals()
+{
+ Q_D(QDeclarative1AnchorChanges);
+ if (!d->target)
+ return;
+
+ d->origLeftBinding = QDeclarativePropertyPrivate::binding(d->leftProp);
+ d->origRightBinding = QDeclarativePropertyPrivate::binding(d->rightProp);
+ d->origHCenterBinding = QDeclarativePropertyPrivate::binding(d->hCenterProp);
+ d->origTopBinding = QDeclarativePropertyPrivate::binding(d->topProp);
+ d->origBottomBinding = QDeclarativePropertyPrivate::binding(d->bottomProp);
+ d->origVCenterBinding = QDeclarativePropertyPrivate::binding(d->vCenterProp);
+ d->origBaselineBinding = QDeclarativePropertyPrivate::binding(d->baselineProp);
+
+ QDeclarativeItemPrivate *targetPrivate = QDeclarativeItemPrivate::get(d->target);
+ if (targetPrivate->widthValid)
+ d->origWidth = d->target->width();
+ if (targetPrivate->heightValid)
+ d->origHeight = d->target->height();
+ d->origX = d->target->x();
+ d->origY = d->target->y();
+
+ d->applyOrigLeft = d->applyOrigRight = d->applyOrigHCenter = d->applyOrigTop
+ = d->applyOrigBottom = d->applyOrigVCenter = d->applyOrigBaseline = false;
+
+ saveCurrentValues();
+}
+
+void QDeclarative1AnchorChanges::copyOriginals(QDeclarative1ActionEvent *other)
+{
+ Q_D(QDeclarative1AnchorChanges);
+ QDeclarative1AnchorChanges *ac = static_cast<QDeclarative1AnchorChanges*>(other);
+ QDeclarative1AnchorChangesPrivate *acp = ac->d_func();
+
+ QDeclarative1Anchors::Anchors combined = acp->anchorSet->d_func()->usedAnchors |
+ acp->anchorSet->d_func()->resetAnchors;
+
+ //probably also need to revert some things
+ d->applyOrigLeft = (combined & QDeclarative1Anchors::LeftAnchor);
+ d->applyOrigRight = (combined & QDeclarative1Anchors::RightAnchor);
+ d->applyOrigHCenter = (combined & QDeclarative1Anchors::HCenterAnchor);
+ d->applyOrigTop = (combined & QDeclarative1Anchors::TopAnchor);
+ d->applyOrigBottom = (combined & QDeclarative1Anchors::BottomAnchor);
+ d->applyOrigVCenter = (combined & QDeclarative1Anchors::VCenterAnchor);
+ d->applyOrigBaseline = (combined & QDeclarative1Anchors::BaselineAnchor);
+
+ d->origLeftBinding = acp->origLeftBinding;
+ d->origRightBinding = acp->origRightBinding;
+ d->origHCenterBinding = acp->origHCenterBinding;
+ d->origTopBinding = acp->origTopBinding;
+ d->origBottomBinding = acp->origBottomBinding;
+ d->origVCenterBinding = acp->origVCenterBinding;
+ d->origBaselineBinding = acp->origBaselineBinding;
+
+ d->origWidth = acp->origWidth;
+ d->origHeight = acp->origHeight;
+ d->origX = acp->origX;
+ d->origY = acp->origY;
+
+ d->oldBindings.clear();
+ d->oldBindings << acp->leftBinding << acp->rightBinding << acp->hCenterBinding
+ << acp->topBinding << acp->bottomBinding << acp->baselineBinding;
+
+ saveCurrentValues();
+}
+
+void QDeclarative1AnchorChanges::clearBindings()
+{
+ Q_D(QDeclarative1AnchorChanges);
+ if (!d->target)
+ return;
+
+ //### should this (saving "from" values) be moved to saveCurrentValues()?
+ d->fromX = d->target->x();
+ d->fromY = d->target->y();
+ d->fromWidth = d->target->width();
+ d->fromHeight = d->target->height();
+
+ QDeclarativeItemPrivate *targetPrivate = QDeclarativeItemPrivate::get(d->target);
+ //reset any anchors with corresponding reverts
+ //reset any anchors that have been specified as "undefined"
+ //reset any anchors that we'll be setting in the state
+ QDeclarative1Anchors::Anchors combined = d->anchorSet->d_func()->resetAnchors |
+ d->anchorSet->d_func()->usedAnchors;
+ if (d->applyOrigLeft || (combined & QDeclarative1Anchors::LeftAnchor)) {
+ targetPrivate->anchors()->resetLeft();
+ QDeclarativePropertyPrivate::setBinding(d->leftProp, 0);
+ }
+ if (d->applyOrigRight || (combined & QDeclarative1Anchors::RightAnchor)) {
+ targetPrivate->anchors()->resetRight();
+ QDeclarativePropertyPrivate::setBinding(d->rightProp, 0);
+ }
+ if (d->applyOrigHCenter || (combined & QDeclarative1Anchors::HCenterAnchor)) {
+ targetPrivate->anchors()->resetHorizontalCenter();
+ QDeclarativePropertyPrivate::setBinding(d->hCenterProp, 0);
+ }
+ if (d->applyOrigTop || (combined & QDeclarative1Anchors::TopAnchor)) {
+ targetPrivate->anchors()->resetTop();
+ QDeclarativePropertyPrivate::setBinding(d->topProp, 0);
+ }
+ if (d->applyOrigBottom || (combined & QDeclarative1Anchors::BottomAnchor)) {
+ targetPrivate->anchors()->resetBottom();
+ QDeclarativePropertyPrivate::setBinding(d->bottomProp, 0);
+ }
+ if (d->applyOrigVCenter || (combined & QDeclarative1Anchors::VCenterAnchor)) {
+ targetPrivate->anchors()->resetVerticalCenter();
+ QDeclarativePropertyPrivate::setBinding(d->vCenterProp, 0);
+ }
+ if (d->applyOrigBaseline || (combined & QDeclarative1Anchors::BaselineAnchor)) {
+ targetPrivate->anchors()->resetBaseline();
+ QDeclarativePropertyPrivate::setBinding(d->baselineProp, 0);
+ }
+}
+
+bool QDeclarative1AnchorChanges::override(QDeclarative1ActionEvent*other)
+{
+ if (other->typeName() != QLatin1String("AnchorChanges"))
+ return false;
+ if (static_cast<QDeclarative1ActionEvent*>(this) == other)
+ return true;
+ if (static_cast<QDeclarative1AnchorChanges*>(other)->object() == object())
+ return true;
+ return false;
+}
+
+void QDeclarative1AnchorChanges::rewind()
+{
+ Q_D(QDeclarative1AnchorChanges);
+ if (!d->target)
+ return;
+
+ QDeclarativeItemPrivate *targetPrivate = QDeclarativeItemPrivate::get(d->target);
+
+ //restore previous values (but not previous bindings, i.e. anchors)
+ d->target->setX(d->rewindX);
+ d->target->setY(d->rewindY);
+ if (targetPrivate->widthValid) {
+ d->target->setWidth(d->rewindWidth);
+ }
+ if (targetPrivate->heightValid) {
+ d->target->setHeight(d->rewindHeight);
+ }
+}
+
+void QDeclarative1AnchorChanges::saveCurrentValues()
+{
+ Q_D(QDeclarative1AnchorChanges);
+ if (!d->target)
+ return;
+
+ QDeclarativeItemPrivate *targetPrivate = QDeclarativeItemPrivate::get(d->target);
+ d->rewindLeft = targetPrivate->anchors()->left();
+ d->rewindRight = targetPrivate->anchors()->right();
+ d->rewindHCenter = targetPrivate->anchors()->horizontalCenter();
+ d->rewindTop = targetPrivate->anchors()->top();
+ d->rewindBottom = targetPrivate->anchors()->bottom();
+ d->rewindVCenter = targetPrivate->anchors()->verticalCenter();
+ d->rewindBaseline = targetPrivate->anchors()->baseline();
+
+ d->rewindX = d->target->x();
+ d->rewindY = d->target->y();
+ d->rewindWidth = d->target->width();
+ d->rewindHeight = d->target->height();
+}
+
+void QDeclarative1AnchorChanges::saveTargetValues()
+{
+ Q_D(QDeclarative1AnchorChanges);
+ if (!d->target)
+ return;
+
+ d->toX = d->target->x();
+ d->toY = d->target->y();
+ d->toWidth = d->target->width();
+ d->toHeight = d->target->height();
+}
+
+#include <qdeclarativestateoperations.moc>
+#include <moc_qdeclarativestateoperations_p.cpp>
+
+
+
+QT_END_NAMESPACE
+
diff --git a/src/qtquick1/util/qdeclarativestateoperations_p.h b/src/qtquick1/util/qdeclarativestateoperations_p.h
new file mode 100644
index 0000000000..7d0b618c3b
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativestateoperations_p.h
@@ -0,0 +1,299 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVESTATEOPERATIONS_H
+#define QDECLARATIVESTATEOPERATIONS_H
+
+#include "QtQuick1/private/qdeclarativestate_p.h"
+
+#include <QtQuick1/qdeclarativeitem.h>
+#include <QtQuick1/private/qdeclarativeanchors_p.h>
+#include <QtDeclarative/qdeclarativescriptstring.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarative1ParentChangePrivate;
+class Q_AUTOTEST_EXPORT QDeclarative1ParentChange : public QDeclarative1StateOperation, public QDeclarative1ActionEvent
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarative1ParentChange)
+
+ Q_PROPERTY(QDeclarativeItem *target READ object WRITE setObject)
+ Q_PROPERTY(QDeclarativeItem *parent READ parent WRITE setParent)
+ Q_PROPERTY(QDeclarativeScriptString x READ x WRITE setX)
+ Q_PROPERTY(QDeclarativeScriptString y READ y WRITE setY)
+ Q_PROPERTY(QDeclarativeScriptString width READ width WRITE setWidth)
+ Q_PROPERTY(QDeclarativeScriptString height READ height WRITE setHeight)
+ Q_PROPERTY(QDeclarativeScriptString scale READ scale WRITE setScale)
+ Q_PROPERTY(QDeclarativeScriptString rotation READ rotation WRITE setRotation)
+public:
+ QDeclarative1ParentChange(QObject *parent=0);
+ ~QDeclarative1ParentChange();
+
+ QDeclarativeItem *object() const;
+ void setObject(QDeclarativeItem *);
+
+ QDeclarativeItem *parent() const;
+ void setParent(QDeclarativeItem *);
+
+ QDeclarativeItem *originalParent() const;
+
+ QDeclarativeScriptString x() const;
+ void setX(QDeclarativeScriptString x);
+ bool xIsSet() const;
+
+ QDeclarativeScriptString y() const;
+ void setY(QDeclarativeScriptString y);
+ bool yIsSet() const;
+
+ QDeclarativeScriptString width() const;
+ void setWidth(QDeclarativeScriptString width);
+ bool widthIsSet() const;
+
+ QDeclarativeScriptString height() const;
+ void setHeight(QDeclarativeScriptString height);
+ bool heightIsSet() const;
+
+ QDeclarativeScriptString scale() const;
+ void setScale(QDeclarativeScriptString scale);
+ bool scaleIsSet() const;
+
+ QDeclarativeScriptString rotation() const;
+ void setRotation(QDeclarativeScriptString rotation);
+ bool rotationIsSet() const;
+
+ virtual ActionList actions();
+
+ virtual void saveOriginals();
+ //virtual void copyOriginals(QDeclarative1ActionEvent*);
+ virtual void execute(Reason reason = ActualChange);
+ virtual bool isReversable();
+ virtual void reverse(Reason reason = ActualChange);
+ virtual QString typeName() const;
+ virtual bool override(QDeclarative1ActionEvent*other);
+ virtual void rewind();
+ virtual void saveCurrentValues();
+};
+
+class QDeclarative1StateChangeScriptPrivate;
+class Q_AUTOTEST_EXPORT QDeclarative1StateChangeScript : public QDeclarative1StateOperation, public QDeclarative1ActionEvent
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarative1StateChangeScript)
+
+ Q_PROPERTY(QDeclarativeScriptString script READ script WRITE setScript)
+ Q_PROPERTY(QString name READ name WRITE setName)
+
+public:
+ QDeclarative1StateChangeScript(QObject *parent=0);
+ ~QDeclarative1StateChangeScript();
+
+ virtual ActionList actions();
+
+ virtual QString typeName() const;
+
+ QDeclarativeScriptString script() const;
+ void setScript(const QDeclarativeScriptString &);
+
+ QString name() const;
+ void setName(const QString &);
+
+ virtual void execute(Reason reason = ActualChange);
+};
+
+class QDeclarative1AnchorChanges;
+class QDeclarative1AnchorSetPrivate;
+class Q_AUTOTEST_EXPORT QDeclarative1AnchorSet : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QDeclarativeScriptString left READ left WRITE setLeft RESET resetLeft)
+ Q_PROPERTY(QDeclarativeScriptString right READ right WRITE setRight RESET resetRight)
+ Q_PROPERTY(QDeclarativeScriptString horizontalCenter READ horizontalCenter WRITE setHorizontalCenter RESET resetHorizontalCenter)
+ Q_PROPERTY(QDeclarativeScriptString top READ top WRITE setTop RESET resetTop)
+ Q_PROPERTY(QDeclarativeScriptString bottom READ bottom WRITE setBottom RESET resetBottom)
+ Q_PROPERTY(QDeclarativeScriptString verticalCenter READ verticalCenter WRITE setVerticalCenter RESET resetVerticalCenter)
+ Q_PROPERTY(QDeclarativeScriptString baseline READ baseline WRITE setBaseline RESET resetBaseline)
+ //Q_PROPERTY(QDeclarativeItem *fill READ fill WRITE setFill RESET resetFill)
+ //Q_PROPERTY(QDeclarativeItem *centerIn READ centerIn WRITE setCenterIn RESET resetCenterIn)
+
+ /*Q_PROPERTY(qreal margins READ margins WRITE setMargins NOTIFY marginsChanged)
+ Q_PROPERTY(qreal leftMargin READ leftMargin WRITE setLeftMargin NOTIFY leftMarginChanged)
+ Q_PROPERTY(qreal rightMargin READ rightMargin WRITE setRightMargin NOTIFY rightMarginChanged)
+ Q_PROPERTY(qreal horizontalCenterOffset READ horizontalCenterOffset WRITE setHorizontalCenterOffset NOTIFY horizontalCenterOffsetChanged())
+ Q_PROPERTY(qreal topMargin READ topMargin WRITE setTopMargin NOTIFY topMarginChanged)
+ Q_PROPERTY(qreal bottomMargin READ bottomMargin WRITE setBottomMargin NOTIFY bottomMarginChanged)
+ Q_PROPERTY(qreal verticalCenterOffset READ verticalCenterOffset WRITE setVerticalCenterOffset NOTIFY verticalCenterOffsetChanged())
+ Q_PROPERTY(qreal baselineOffset READ baselineOffset WRITE setBaselineOffset NOTIFY baselineOffsetChanged())*/
+
+public:
+ QDeclarative1AnchorSet(QObject *parent=0);
+ virtual ~QDeclarative1AnchorSet();
+
+ QDeclarativeScriptString left() const;
+ void setLeft(const QDeclarativeScriptString &edge);
+ void resetLeft();
+
+ QDeclarativeScriptString right() const;
+ void setRight(const QDeclarativeScriptString &edge);
+ void resetRight();
+
+ QDeclarativeScriptString horizontalCenter() const;
+ void setHorizontalCenter(const QDeclarativeScriptString &edge);
+ void resetHorizontalCenter();
+
+ QDeclarativeScriptString top() const;
+ void setTop(const QDeclarativeScriptString &edge);
+ void resetTop();
+
+ QDeclarativeScriptString bottom() const;
+ void setBottom(const QDeclarativeScriptString &edge);
+ void resetBottom();
+
+ QDeclarativeScriptString verticalCenter() const;
+ void setVerticalCenter(const QDeclarativeScriptString &edge);
+ void resetVerticalCenter();
+
+ QDeclarativeScriptString baseline() const;
+ void setBaseline(const QDeclarativeScriptString &edge);
+ void resetBaseline();
+
+ QDeclarativeItem *fill() const;
+ void setFill(QDeclarativeItem *);
+ void resetFill();
+
+ QDeclarativeItem *centerIn() const;
+ void setCenterIn(QDeclarativeItem *);
+ void resetCenterIn();
+
+ /*qreal leftMargin() const;
+ void setLeftMargin(qreal);
+
+ qreal rightMargin() const;
+ void setRightMargin(qreal);
+
+ qreal horizontalCenterOffset() const;
+ void setHorizontalCenterOffset(qreal);
+
+ qreal topMargin() const;
+ void setTopMargin(qreal);
+
+ qreal bottomMargin() const;
+ void setBottomMargin(qreal);
+
+ qreal margins() const;
+ void setMargins(qreal);
+
+ qreal verticalCenterOffset() const;
+ void setVerticalCenterOffset(qreal);
+
+ qreal baselineOffset() const;
+ void setBaselineOffset(qreal);*/
+
+ QDeclarative1Anchors::Anchors usedAnchors() const;
+
+/*Q_SIGNALS:
+ void leftMarginChanged();
+ void rightMarginChanged();
+ void topMarginChanged();
+ void bottomMarginChanged();
+ void marginsChanged();
+ void verticalCenterOffsetChanged();
+ void horizontalCenterOffsetChanged();
+ void baselineOffsetChanged();*/
+
+private:
+ friend class QDeclarative1AnchorChanges;
+ Q_DISABLE_COPY(QDeclarative1AnchorSet)
+ Q_DECLARE_PRIVATE(QDeclarative1AnchorSet)
+};
+
+class QDeclarative1AnchorChangesPrivate;
+class Q_AUTOTEST_EXPORT QDeclarative1AnchorChanges : public QDeclarative1StateOperation, public QDeclarative1ActionEvent
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarative1AnchorChanges)
+
+ Q_PROPERTY(QDeclarativeItem *target READ object WRITE setObject)
+ Q_PROPERTY(QDeclarative1AnchorSet *anchors READ anchors CONSTANT)
+
+public:
+ QDeclarative1AnchorChanges(QObject *parent=0);
+ ~QDeclarative1AnchorChanges();
+
+ virtual ActionList actions();
+
+ QDeclarative1AnchorSet *anchors();
+
+ QDeclarativeItem *object() const;
+ void setObject(QDeclarativeItem *);
+
+ virtual void execute(Reason reason = ActualChange);
+ virtual bool isReversable();
+ virtual void reverse(Reason reason = ActualChange);
+ virtual QString typeName() const;
+ virtual bool override(QDeclarative1ActionEvent*other);
+ virtual bool changesBindings();
+ virtual void saveOriginals();
+ virtual bool needsCopy() { return true; }
+ virtual void copyOriginals(QDeclarative1ActionEvent*);
+ virtual void clearBindings();
+ virtual void rewind();
+ virtual void saveCurrentValues();
+
+ QList<QDeclarative1Action> additionalActions();
+ virtual void saveTargetValues();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1ParentChange)
+QML_DECLARE_TYPE(QDeclarative1StateChangeScript)
+QML_DECLARE_TYPE(QDeclarative1AnchorSet)
+QML_DECLARE_TYPE(QDeclarative1AnchorChanges)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVESTATEOPERATIONS_H
diff --git a/src/qtquick1/util/qdeclarativestyledtext.cpp b/src/qtquick1/util/qdeclarativestyledtext.cpp
new file mode 100644
index 0000000000..46d2224f5e
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativestyledtext.cpp
@@ -0,0 +1,351 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QStack>
+#include <QVector>
+#include <QPainter>
+#include <QTextLayout>
+#include <QDebug>
+#include <qmath.h>
+#include "QtQuick1/private/qdeclarativestyledtext_p.h"
+
+/*
+ QDeclarative1StyledText supports few tags:
+
+ <b></b> - bold
+ <i></i> - italic
+ <br> - new line
+ <font color="color_name" size="1-7"></font>
+
+ The opening and closing tags must be correctly nested.
+*/
+
+QT_BEGIN_NAMESPACE
+
+
+
+class QDeclarative1StyledTextPrivate
+{
+public:
+ QDeclarative1StyledTextPrivate(const QString &t, QTextLayout &l) : text(t), layout(l), baseFont(layout.font()) {}
+
+ void parse();
+ bool parseTag(const QChar *&ch, const QString &textIn, QString &textOut, QTextCharFormat &format);
+ bool parseCloseTag(const QChar *&ch, const QString &textIn);
+ void parseEntity(const QChar *&ch, const QString &textIn, QString &textOut);
+ bool parseFontAttributes(const QChar *&ch, const QString &textIn, QTextCharFormat &format);
+ QPair<QStringRef,QStringRef> parseAttribute(const QChar *&ch, const QString &textIn);
+ QStringRef parseValue(const QChar *&ch, const QString &textIn);
+
+ inline void skipSpace(const QChar *&ch) {
+ while (ch->isSpace() && !ch->isNull())
+ ++ch;
+ }
+
+ QString text;
+ QTextLayout &layout;
+ QFont baseFont;
+
+ static const QChar lessThan;
+ static const QChar greaterThan;
+ static const QChar equals;
+ static const QChar singleQuote;
+ static const QChar doubleQuote;
+ static const QChar slash;
+ static const QChar ampersand;
+};
+
+const QChar QDeclarative1StyledTextPrivate::lessThan(QLatin1Char('<'));
+const QChar QDeclarative1StyledTextPrivate::greaterThan(QLatin1Char('>'));
+const QChar QDeclarative1StyledTextPrivate::equals(QLatin1Char('='));
+const QChar QDeclarative1StyledTextPrivate::singleQuote(QLatin1Char('\''));
+const QChar QDeclarative1StyledTextPrivate::doubleQuote(QLatin1Char('\"'));
+const QChar QDeclarative1StyledTextPrivate::slash(QLatin1Char('/'));
+const QChar QDeclarative1StyledTextPrivate::ampersand(QLatin1Char('&'));
+
+QDeclarative1StyledText::QDeclarative1StyledText(const QString &string, QTextLayout &layout)
+: d(new QDeclarative1StyledTextPrivate(string, layout))
+{
+}
+
+QDeclarative1StyledText::~QDeclarative1StyledText()
+{
+ delete d;
+}
+
+void QDeclarative1StyledText::parse(const QString &string, QTextLayout &layout)
+{
+ if (string.isEmpty())
+ return;
+ QDeclarative1StyledText styledText(string, layout);
+ styledText.d->parse();
+}
+
+void QDeclarative1StyledTextPrivate::parse()
+{
+ QList<QTextLayout::FormatRange> ranges;
+ QStack<QTextCharFormat> formatStack;
+
+ QString drawText;
+ drawText.reserve(text.count());
+
+ int textStart = 0;
+ int textLength = 0;
+ int rangeStart = 0;
+ const QChar *ch = text.constData();
+ while (!ch->isNull()) {
+ if (*ch == lessThan) {
+ if (textLength)
+ drawText.append(QStringRef(&text, textStart, textLength));
+ if (rangeStart != drawText.length() && formatStack.count()) {
+ QTextLayout::FormatRange formatRange;
+ formatRange.format = formatStack.top();
+ formatRange.start = rangeStart;
+ formatRange.length = drawText.length() - rangeStart;
+ ranges.append(formatRange);
+ }
+ rangeStart = drawText.length();
+ ++ch;
+ if (*ch == slash) {
+ ++ch;
+ if (parseCloseTag(ch, text)) {
+ if (formatStack.count())
+ formatStack.pop();
+ }
+ } else {
+ QTextCharFormat format;
+ if (formatStack.count())
+ format = formatStack.top();
+ if (parseTag(ch, text, drawText, format))
+ formatStack.push(format);
+ }
+ textStart = ch - text.constData() + 1;
+ textLength = 0;
+ } else if (*ch == ampersand) {
+ ++ch;
+ drawText.append(QStringRef(&text, textStart, textLength));
+ parseEntity(ch, text, drawText);
+ textStart = ch - text.constData() + 1;
+ textLength = 0;
+ } else {
+ ++textLength;
+ }
+ if (!ch->isNull())
+ ++ch;
+ }
+ if (textLength)
+ drawText.append(QStringRef(&text, textStart, textLength));
+ if (rangeStart != drawText.length() && formatStack.count()) {
+ QTextLayout::FormatRange formatRange;
+ formatRange.format = formatStack.top();
+ formatRange.start = rangeStart;
+ formatRange.length = drawText.length() - rangeStart;
+ ranges.append(formatRange);
+ }
+
+ layout.setText(drawText);
+ layout.setAdditionalFormats(ranges);
+}
+
+bool QDeclarative1StyledTextPrivate::parseTag(const QChar *&ch, const QString &textIn, QString &textOut, QTextCharFormat &format)
+{
+ skipSpace(ch);
+
+ int tagStart = ch - textIn.constData();
+ int tagLength = 0;
+ while (!ch->isNull()) {
+ if (*ch == greaterThan) {
+ QStringRef tag(&textIn, tagStart, tagLength);
+ const QChar char0 = tag.at(0);
+ if (char0 == QLatin1Char('b')) {
+ if (tagLength == 1)
+ format.setFontWeight(QFont::Bold);
+ else if (tagLength == 2 && tag.at(1) == QLatin1Char('r')) {
+ textOut.append(QChar(QChar::LineSeparator));
+ return false;
+ }
+ } else if (char0 == QLatin1Char('i')) {
+ if (tagLength == 1)
+ format.setFontItalic(true);
+ }
+ return true;
+ } else if (ch->isSpace()) {
+ // may have params.
+ QStringRef tag(&textIn, tagStart, tagLength);
+ if (tag == QLatin1String("font"))
+ return parseFontAttributes(ch, textIn, format);
+ if (*ch == greaterThan || ch->isNull())
+ continue;
+ } else if (*ch != slash){
+ tagLength++;
+ }
+ ++ch;
+ }
+
+ return false;
+}
+
+bool QDeclarative1StyledTextPrivate::parseCloseTag(const QChar *&ch, const QString &textIn)
+{
+ skipSpace(ch);
+
+ int tagStart = ch - textIn.constData();
+ int tagLength = 0;
+ while (!ch->isNull()) {
+ if (*ch == greaterThan) {
+ QStringRef tag(&textIn, tagStart, tagLength);
+ const QChar char0 = tag.at(0);
+ if (char0 == QLatin1Char('b')) {
+ if (tagLength == 1)
+ return true;
+ else if (tag.at(1) == QLatin1Char('r') && tagLength == 2)
+ return true;
+ } else if (char0 == QLatin1Char('i')) {
+ if (tagLength == 1)
+ return true;
+ } else if (tag == QLatin1String("font")) {
+ return true;
+ }
+ return false;
+ } else if (!ch->isSpace()){
+ tagLength++;
+ }
+ ++ch;
+ }
+
+ return false;
+}
+
+void QDeclarative1StyledTextPrivate::parseEntity(const QChar *&ch, const QString &textIn, QString &textOut)
+{
+ int entityStart = ch - textIn.constData();
+ int entityLength = 0;
+ while (!ch->isNull()) {
+ if (*ch == QLatin1Char(';')) {
+ QStringRef entity(&textIn, entityStart, entityLength);
+ if (entity == QLatin1String("gt"))
+ textOut += QChar(62);
+ else if (entity == QLatin1String("lt"))
+ textOut += QChar(60);
+ else if (entity == QLatin1String("amp"))
+ textOut += QChar(38);
+ return;
+ }
+ ++entityLength;
+ ++ch;
+ }
+}
+
+bool QDeclarative1StyledTextPrivate::parseFontAttributes(const QChar *&ch, const QString &textIn, QTextCharFormat &format)
+{
+ bool valid = false;
+ QPair<QStringRef,QStringRef> attr;
+ do {
+ attr = parseAttribute(ch, textIn);
+ if (attr.first == QLatin1String("color")) {
+ valid = true;
+ format.setForeground(QColor(attr.second.toString()));
+ } else if (attr.first == QLatin1String("size")) {
+ valid = true;
+ int size = attr.second.toString().toInt();
+ if (attr.second.at(0) == QLatin1Char('-') || attr.second.at(0) == QLatin1Char('+'))
+ size += 3;
+ if (size >= 1 && size <= 7) {
+ static const qreal scaling[] = { 0.7, 0.8, 1.0, 1.2, 1.5, 2.0, 2.4 };
+ format.setFontPointSize(baseFont.pointSize() * scaling[size-1]);
+ }
+ }
+ } while (!ch->isNull() && !attr.first.isEmpty());
+
+ return valid;
+}
+
+QPair<QStringRef,QStringRef> QDeclarative1StyledTextPrivate::parseAttribute(const QChar *&ch, const QString &textIn)
+{
+ skipSpace(ch);
+
+ int attrStart = ch - textIn.constData();
+ int attrLength = 0;
+ while (!ch->isNull()) {
+ if (*ch == greaterThan) {
+ break;
+ } else if (*ch == equals) {
+ ++ch;
+ if (*ch != singleQuote && *ch != doubleQuote) {
+ while (*ch != greaterThan && !ch->isNull())
+ ++ch;
+ break;
+ }
+ ++ch;
+ if (!attrLength)
+ break;
+ QStringRef attr(&textIn, attrStart, attrLength);
+ QStringRef val = parseValue(ch, textIn);
+ if (!val.isEmpty())
+ return QPair<QStringRef,QStringRef>(attr,val);
+ break;
+ } else {
+ ++attrLength;
+ }
+ ++ch;
+ }
+
+ return QPair<QStringRef,QStringRef>();
+}
+
+QStringRef QDeclarative1StyledTextPrivate::parseValue(const QChar *&ch, const QString &textIn)
+{
+ int valStart = ch - textIn.constData();
+ int valLength = 0;
+ while (*ch != singleQuote && *ch != doubleQuote && !ch->isNull()) {
+ ++valLength;
+ ++ch;
+ }
+ if (ch->isNull())
+ return QStringRef();
+ ++ch; // skip quote
+
+ return QStringRef(&textIn, valStart, valLength);
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/util/qdeclarativestyledtext_p.h b/src/qtquick1/util/qdeclarativestyledtext_p.h
new file mode 100644
index 0000000000..43a391a9d5
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativestyledtext_p.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVESTYLEDTEXT_H
+#define QDECLARATIVESTYLEDTEXT_H
+
+#include <QSizeF>
+
+QT_BEGIN_NAMESPACE
+
+class QPainter;
+class QPointF;
+class QString;
+class QTextLayout;
+
+class QDeclarative1StyledTextPrivate;
+
+class Q_AUTOTEST_EXPORT QDeclarative1StyledText
+{
+public:
+ static void parse(const QString &string, QTextLayout &layout);
+
+private:
+ QDeclarative1StyledText(const QString &string, QTextLayout &layout);
+ ~QDeclarative1StyledText();
+
+ QDeclarative1StyledTextPrivate *d;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/qtquick1/util/qdeclarativesystempalette.cpp b/src/qtquick1/util/qdeclarativesystempalette.cpp
new file mode 100644
index 0000000000..311a2bf16e
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativesystempalette.cpp
@@ -0,0 +1,316 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativesystempalette_p.h"
+
+#include <QApplication>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+
+
+class QDeclarative1SystemPalettePrivate : public QObjectPrivate
+{
+public:
+ QPalette palette;
+ QPalette::ColorGroup group;
+};
+
+
+
+/*!
+ \qmlclass SystemPalette QDeclarative1SystemPalette
+ \ingroup qml-utility-elements
+ \since 4.7
+ \brief The SystemPalette element provides access to the Qt palettes.
+
+ The SystemPalette element provides access to the Qt application
+ palettes. This provides information about the standard colors used
+ for application windows, buttons and other features. These colors
+ are grouped into three \e {color groups}: \c Active, \c Inactive,
+ and \c Disabled. See the QPalette documentation for details about
+ color groups and the properties provided by SystemPalette.
+
+ This can be used to color items in a way that provides a more
+ native look and feel.
+
+ The following example creates a palette from the \c Active color
+ group and uses this to color the window and text items
+ appropriately:
+
+ \snippet doc/src/snippets/declarative/systempalette.qml 0
+
+ \sa QPalette
+*/
+QDeclarative1SystemPalette::QDeclarative1SystemPalette(QObject *parent)
+ : QObject(*(new QDeclarative1SystemPalettePrivate), parent)
+{
+ Q_D(QDeclarative1SystemPalette);
+ d->palette = QApplication::palette();
+ d->group = QPalette::Active;
+ qApp->installEventFilter(this);
+}
+
+QDeclarative1SystemPalette::~QDeclarative1SystemPalette()
+{
+}
+
+/*!
+ \qmlproperty color SystemPalette::window
+ The window (general background) color of the current color group.
+
+ \sa QPalette::ColorRole
+*/
+QColor QDeclarative1SystemPalette::window() const
+{
+ Q_D(const QDeclarative1SystemPalette);
+ return d->palette.color(d->group, QPalette::Window);
+}
+
+/*!
+ \qmlproperty color SystemPalette::windowText
+ The window text (general foreground) color of the current color group.
+
+ \sa QPalette::ColorRole
+*/
+QColor QDeclarative1SystemPalette::windowText() const
+{
+ Q_D(const QDeclarative1SystemPalette);
+ return d->palette.color(d->group, QPalette::WindowText);
+}
+
+/*!
+ \qmlproperty color SystemPalette::base
+ The base color of the current color group.
+
+ \sa QPalette::ColorRole
+*/
+QColor QDeclarative1SystemPalette::base() const
+{
+ Q_D(const QDeclarative1SystemPalette);
+ return d->palette.color(d->group, QPalette::Base);
+}
+
+/*!
+ \qmlproperty color SystemPalette::text
+ The text color of the current color group.
+
+ \sa QPalette::ColorRole
+*/
+QColor QDeclarative1SystemPalette::text() const
+{
+ Q_D(const QDeclarative1SystemPalette);
+ return d->palette.color(d->group, QPalette::Text);
+}
+
+/*!
+ \qmlproperty color SystemPalette::alternateBase
+ The alternate base color of the current color group.
+
+ \sa QPalette::ColorRole
+*/
+QColor QDeclarative1SystemPalette::alternateBase() const
+{
+ Q_D(const QDeclarative1SystemPalette);
+ return d->palette.color(d->group, QPalette::AlternateBase);
+}
+
+/*!
+ \qmlproperty color SystemPalette::button
+ The button color of the current color group.
+
+ \sa QPalette::ColorRole
+*/
+QColor QDeclarative1SystemPalette::button() const
+{
+ Q_D(const QDeclarative1SystemPalette);
+ return d->palette.color(d->group, QPalette::Button);
+}
+
+/*!
+ \qmlproperty color SystemPalette::buttonText
+ The button text foreground color of the current color group.
+
+ \sa QPalette::ColorRole
+*/
+QColor QDeclarative1SystemPalette::buttonText() const
+{
+ Q_D(const QDeclarative1SystemPalette);
+ return d->palette.color(d->group, QPalette::ButtonText);
+}
+
+/*!
+ \qmlproperty color SystemPalette::light
+ The light color of the current color group.
+
+ \sa QPalette::ColorRole
+*/
+QColor QDeclarative1SystemPalette::light() const
+{
+ Q_D(const QDeclarative1SystemPalette);
+ return d->palette.color(d->group, QPalette::Light);
+}
+
+/*!
+ \qmlproperty color SystemPalette::midlight
+ The midlight color of the current color group.
+
+ \sa QPalette::ColorRole
+*/
+QColor QDeclarative1SystemPalette::midlight() const
+{
+ Q_D(const QDeclarative1SystemPalette);
+ return d->palette.color(d->group, QPalette::Midlight);
+}
+
+/*!
+ \qmlproperty color SystemPalette::dark
+ The dark color of the current color group.
+
+ \sa QPalette::ColorRole
+*/
+QColor QDeclarative1SystemPalette::dark() const
+{
+ Q_D(const QDeclarative1SystemPalette);
+ return d->palette.color(d->group, QPalette::Dark);
+}
+
+/*!
+ \qmlproperty color SystemPalette::mid
+ The mid color of the current color group.
+
+ \sa QPalette::ColorRole
+*/
+QColor QDeclarative1SystemPalette::mid() const
+{
+ Q_D(const QDeclarative1SystemPalette);
+ return d->palette.color(d->group, QPalette::Mid);
+}
+
+/*!
+ \qmlproperty color SystemPalette::shadow
+ The shadow color of the current color group.
+
+ \sa QPalette::ColorRole
+*/
+QColor QDeclarative1SystemPalette::shadow() const
+{
+ Q_D(const QDeclarative1SystemPalette);
+ return d->palette.color(d->group, QPalette::Shadow);
+}
+
+/*!
+ \qmlproperty color SystemPalette::highlight
+ The highlight color of the current color group.
+
+ \sa QPalette::ColorRole
+*/
+QColor QDeclarative1SystemPalette::highlight() const
+{
+ Q_D(const QDeclarative1SystemPalette);
+ return d->palette.color(d->group, QPalette::Highlight);
+}
+
+/*!
+ \qmlproperty color SystemPalette::highlightedText
+ The highlighted text color of the current color group.
+
+ \sa QPalette::ColorRole
+*/
+QColor QDeclarative1SystemPalette::highlightedText() const
+{
+ Q_D(const QDeclarative1SystemPalette);
+ return d->palette.color(d->group, QPalette::HighlightedText);
+}
+
+/*!
+ \qmlproperty enumeration SystemPalette::colorGroup
+
+ The color group of the palette. This can be one of:
+
+ \list
+ \o SystemPalette.Active (default)
+ \o SystemPalette.Inactive
+ \o SystemPalette.Disabled
+ \endlist
+
+ \sa QPalette::ColorGroup
+*/
+QDeclarative1SystemPalette::ColorGroup QDeclarative1SystemPalette::colorGroup() const
+{
+ Q_D(const QDeclarative1SystemPalette);
+ return (QDeclarative1SystemPalette::ColorGroup)d->group;
+}
+
+void QDeclarative1SystemPalette::setColorGroup(QDeclarative1SystemPalette::ColorGroup colorGroup)
+{
+ Q_D(QDeclarative1SystemPalette);
+ d->group = (QPalette::ColorGroup)colorGroup;
+ emit paletteChanged();
+}
+
+bool QDeclarative1SystemPalette::eventFilter(QObject *watched, QEvent *event)
+{
+ if (watched == qApp) {
+ if (event->type() == QEvent::ApplicationPaletteChange) {
+ QApplication::postEvent(this, new QEvent(QEvent::ApplicationPaletteChange));
+ return false;
+ }
+ }
+ return QObject::eventFilter(watched, event);
+}
+
+bool QDeclarative1SystemPalette::event(QEvent *event)
+{
+ Q_D(QDeclarative1SystemPalette);
+ if (event->type() == QEvent::ApplicationPaletteChange) {
+ d->palette = QApplication::palette();
+ emit paletteChanged();
+ return true;
+ }
+ return QObject::event(event);
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/util/qdeclarativesystempalette_p.h b/src/qtquick1/util/qdeclarativesystempalette_p.h
new file mode 100644
index 0000000000..3dd1933748
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativesystempalette_p.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVESYSTEMPALETTE_H
+#define QDECLARATIVESYSTEMPALETTE_H
+
+#include <QtDeclarative/qdeclarative.h>
+
+#include <QtCore/qobject.h>
+#include <QPalette>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarative1SystemPalettePrivate;
+class Q_AUTOTEST_EXPORT QDeclarative1SystemPalette : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(ColorGroup)
+ Q_DECLARE_PRIVATE(QDeclarative1SystemPalette)
+
+ Q_PROPERTY(QDeclarative1SystemPalette::ColorGroup colorGroup READ colorGroup WRITE setColorGroup NOTIFY paletteChanged)
+ Q_PROPERTY(QColor window READ window NOTIFY paletteChanged)
+ Q_PROPERTY(QColor windowText READ windowText NOTIFY paletteChanged)
+ Q_PROPERTY(QColor base READ base NOTIFY paletteChanged)
+ Q_PROPERTY(QColor text READ text NOTIFY paletteChanged)
+ Q_PROPERTY(QColor alternateBase READ alternateBase NOTIFY paletteChanged)
+ Q_PROPERTY(QColor button READ button NOTIFY paletteChanged)
+ Q_PROPERTY(QColor buttonText READ buttonText NOTIFY paletteChanged)
+ Q_PROPERTY(QColor light READ light NOTIFY paletteChanged)
+ Q_PROPERTY(QColor midlight READ midlight NOTIFY paletteChanged)
+ Q_PROPERTY(QColor dark READ dark NOTIFY paletteChanged)
+ Q_PROPERTY(QColor mid READ mid NOTIFY paletteChanged)
+ Q_PROPERTY(QColor shadow READ shadow NOTIFY paletteChanged)
+ Q_PROPERTY(QColor highlight READ highlight NOTIFY paletteChanged)
+ Q_PROPERTY(QColor highlightedText READ highlightedText NOTIFY paletteChanged)
+
+public:
+ QDeclarative1SystemPalette(QObject *parent=0);
+ ~QDeclarative1SystemPalette();
+
+ enum ColorGroup { Active = QPalette::Active, Inactive = QPalette::Inactive, Disabled = QPalette::Disabled };
+
+ QColor window() const;
+ QColor windowText() const;
+
+ QColor base() const;
+ QColor text() const;
+ QColor alternateBase() const;
+
+ QColor button() const;
+ QColor buttonText() const;
+
+ QColor light() const;
+ QColor midlight() const;
+ QColor dark() const;
+ QColor mid() const;
+ QColor shadow() const;
+
+ QColor highlight() const;
+ QColor highlightedText() const;
+
+ QDeclarative1SystemPalette::ColorGroup colorGroup() const;
+ void setColorGroup(QDeclarative1SystemPalette::ColorGroup);
+
+Q_SIGNALS:
+ void paletteChanged();
+
+private:
+ bool eventFilter(QObject *watched, QEvent *event);
+ bool event(QEvent *event);
+
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1SystemPalette)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVESYSTEMPALETTE_H
diff --git a/src/qtquick1/util/qdeclarativetimeline.cpp b/src/qtquick1/util/qdeclarativetimeline.cpp
new file mode 100644
index 0000000000..0b5cbc85b3
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativetimeline.cpp
@@ -0,0 +1,951 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativetimeline_p_p.h"
+
+#include <QDebug>
+#include <QMutex>
+#include <QThread>
+#include <QWaitCondition>
+#include <QEvent>
+#include <QCoreApplication>
+#include <QEasingCurve>
+#include <QTime>
+
+QT_BEGIN_NAMESPACE
+
+
+
+struct Update {
+ Update(QDeclarative1TimeLineValue *_g, qreal _v)
+ : g(_g), v(_v) {}
+ Update(const QDeclarative1TimeLineCallback &_e)
+ : g(0), v(0), e(_e) {}
+
+ QDeclarative1TimeLineValue *g;
+ qreal v;
+ QDeclarative1TimeLineCallback e;
+};
+
+struct QDeclarative1TimeLinePrivate
+{
+ QDeclarative1TimeLinePrivate(QDeclarative1TimeLine *);
+
+ struct Op {
+ enum Type {
+ Pause,
+ Set,
+ Move,
+ MoveBy,
+ Accel,
+ AccelDistance,
+ Execute
+ };
+ Op() {}
+ Op(Type t, int l, qreal v, qreal v2, int o,
+ const QDeclarative1TimeLineCallback &ev = QDeclarative1TimeLineCallback(), const QEasingCurve &es = QEasingCurve())
+ : type(t), length(l), value(v), value2(v2), order(o), event(ev),
+ easing(es) {}
+ Op(const Op &o)
+ : type(o.type), length(o.length), value(o.value), value2(o.value2),
+ order(o.order), event(o.event), easing(o.easing) {}
+ Op &operator=(const Op &o) {
+ type = o.type; length = o.length; value = o.value;
+ value2 = o.value2; order = o.order; event = o.event;
+ easing = o.easing;
+ return *this;
+ }
+
+ Type type;
+ int length;
+ qreal value;
+ qreal value2;
+
+ int order;
+ QDeclarative1TimeLineCallback event;
+ QEasingCurve easing;
+ };
+ struct TimeLine
+ {
+ TimeLine() : length(0), consumedOpLength(0), base(0.) {}
+ QList<Op> ops;
+ int length;
+ int consumedOpLength;
+ qreal base;
+ };
+
+ int length;
+ int syncPoint;
+ typedef QHash<QDeclarative1TimeLineObject *, TimeLine> Ops;
+ Ops ops;
+ QDeclarative1TimeLine *q;
+
+ void add(QDeclarative1TimeLineObject &, const Op &);
+ qreal value(const Op &op, int time, qreal base, bool *) const;
+
+ int advance(int);
+
+ bool clockRunning;
+ int prevTime;
+
+ int order;
+
+ QDeclarative1TimeLine::SyncMode syncMode;
+ int syncAdj;
+ QList<QPair<int, Update> > *updateQueue;
+};
+
+QDeclarative1TimeLinePrivate::QDeclarative1TimeLinePrivate(QDeclarative1TimeLine *parent)
+: length(0), syncPoint(0), q(parent), clockRunning(false), prevTime(0), order(0), syncMode(QDeclarative1TimeLine::LocalSync), syncAdj(0), updateQueue(0)
+{
+}
+
+void QDeclarative1TimeLinePrivate::add(QDeclarative1TimeLineObject &g, const Op &o)
+{
+ if (g._t && g._t != q) {
+ qWarning() << "QDeclarative1TimeLine: Cannot modify a QDeclarative1TimeLineValue owned by"
+ << "another timeline.";
+ return;
+ }
+ g._t = q;
+
+ Ops::Iterator iter = ops.find(&g);
+ if (iter == ops.end()) {
+ iter = ops.insert(&g, TimeLine());
+ if (syncPoint > 0)
+ q->pause(g, syncPoint);
+ }
+ if (!iter->ops.isEmpty() &&
+ o.type == Op::Pause &&
+ iter->ops.last().type == Op::Pause) {
+ iter->ops.last().length += o.length;
+ iter->length += o.length;
+ } else {
+ iter->ops.append(o);
+ iter->length += o.length;
+ }
+
+ if (iter->length > length)
+ length = iter->length;
+
+ if (!clockRunning) {
+ q->stop();
+ prevTime = 0;
+ clockRunning = true;
+
+ if (syncMode == QDeclarative1TimeLine::LocalSync) {
+ syncAdj = -1;
+ } else {
+ syncAdj = 0;
+ }
+ q->start();
+/* q->tick(0);
+ if (syncMode == QDeclarative1TimeLine::LocalSync) {
+ syncAdj = -1;
+ } else {
+ syncAdj = 0;
+ }
+ */
+ }
+}
+
+qreal QDeclarative1TimeLinePrivate::value(const Op &op, int time, qreal base, bool *changed) const
+{
+ Q_ASSERT(time >= 0);
+ Q_ASSERT(time <= op.length);
+ *changed = true;
+
+ switch(op.type) {
+ case Op::Pause:
+ *changed = false;
+ return base;
+ case Op::Set:
+ return op.value;
+ case Op::Move:
+ if (time == 0) {
+ return base;
+ } else if (time == (op.length)) {
+ return op.value;
+ } else {
+ qreal delta = op.value - base;
+ qreal pTime = (qreal)(time) / (qreal)op.length;
+ if (op.easing.type() == QEasingCurve::Linear)
+ return base + delta * pTime;
+ else
+ return base + delta * op.easing.valueForProgress(pTime);
+ }
+ case Op::MoveBy:
+ if (time == 0) {
+ return base;
+ } else if (time == (op.length)) {
+ return base + op.value;
+ } else {
+ qreal delta = op.value;
+ qreal pTime = (qreal)(time) / (qreal)op.length;
+ if (op.easing.type() == QEasingCurve::Linear)
+ return base + delta * pTime;
+ else
+ return base + delta * op.easing.valueForProgress(pTime);
+ }
+ case Op::Accel:
+ if (time == 0) {
+ return base;
+ } else {
+ qreal t = (qreal)(time) / 1000.0f;
+ qreal delta = op.value * t + 0.5f * op.value2 * t * t;
+ return base + delta;
+ }
+ case Op::AccelDistance:
+ if (time == 0) {
+ return base;
+ } else if (time == (op.length)) {
+ return base + op.value2;
+ } else {
+ qreal t = (qreal)(time) / 1000.0f;
+ qreal accel = -1.0f * 1000.0f * op.value / (qreal)op.length;
+ qreal delta = op.value * t + 0.5f * accel * t * t;
+ return base + delta;
+
+ }
+ case Op::Execute:
+ op.event.d0(op.event.d1);
+ *changed = false;
+ return -1;
+ }
+
+ return base;
+}
+
+/*!
+ \internal
+ \class QDeclarative1TimeLine
+ \brief The QDeclarative1TimeLine class provides a timeline for controlling animations.
+
+ QDeclarative1TimeLine is similar to QTimeLine except:
+ \list
+ \i It updates QDeclarative1TimeLineValue instances directly, rather than maintaining a single
+ current value.
+
+ For example, the following animates a simple value over 200 milliseconds:
+ \code
+ QDeclarative1TimeLineValue v(<starting value>);
+ QDeclarative1TimeLine tl;
+ tl.move(v, 100., 200);
+ tl.start()
+ \endcode
+
+ If your program needs to know when values are changed, it can either
+ connect to the QDeclarative1TimeLine's updated() signal, or inherit from QDeclarative1TimeLineValue
+ and reimplement the QDeclarative1TimeLineValue::setValue() method.
+
+ \i Supports multiple QDeclarative1TimeLineValue, arbitrary start and end values and allows
+ animations to be strung together for more complex effects.
+
+ For example, the following animation moves the x and y coordinates of
+ an object from wherever they are to the position (100, 100) in 50
+ milliseconds and then further animates them to (100, 200) in 50
+ milliseconds:
+
+ \code
+ QDeclarative1TimeLineValue x(<starting value>);
+ QDeclarative1TimeLineValue y(<starting value>);
+
+ QDeclarative1TimeLine tl;
+ tl.start();
+
+ tl.move(x, 100., 50);
+ tl.move(y, 100., 50);
+ tl.move(y, 200., 50);
+ \endcode
+
+ \i All QDeclarative1TimeLine instances share a single, synchronized clock.
+
+ Actions scheduled within the same event loop tick are scheduled
+ synchronously against each other, regardless of the wall time between the
+ scheduling. Synchronized scheduling applies both to within the same
+ QDeclarative1TimeLine and across separate QDeclarative1TimeLine's within the same process.
+
+ \endlist
+
+ Currently easing functions are not supported.
+*/
+
+
+/*!
+ Construct a new QDeclarative1TimeLine with the specified \a parent.
+*/
+QDeclarative1TimeLine::QDeclarative1TimeLine(QObject *parent)
+: QAbstractAnimation(parent)
+{
+ d = new QDeclarative1TimeLinePrivate(this);
+}
+
+/*!
+ Destroys the time line. Any inprogress animations are canceled, but not
+ completed.
+*/
+QDeclarative1TimeLine::~QDeclarative1TimeLine()
+{
+ for (QDeclarative1TimeLinePrivate::Ops::Iterator iter = d->ops.begin();
+ iter != d->ops.end();
+ ++iter)
+ iter.key()->_t = 0;
+
+ delete d; d = 0;
+}
+
+/*!
+ \enum QDeclarative1TimeLine::SyncMode
+ */
+
+/*!
+ Return the timeline's synchronization mode.
+ */
+QDeclarative1TimeLine::SyncMode QDeclarative1TimeLine::syncMode() const
+{
+ return d->syncMode;
+}
+
+/*!
+ Set the timeline's synchronization mode to \a syncMode.
+ */
+void QDeclarative1TimeLine::setSyncMode(SyncMode syncMode)
+{
+ d->syncMode = syncMode;
+}
+
+/*!
+ Pause \a obj for \a time milliseconds.
+*/
+void QDeclarative1TimeLine::pause(QDeclarative1TimeLineObject &obj, int time)
+{
+ if (time <= 0) return;
+ QDeclarative1TimeLinePrivate::Op op(QDeclarative1TimeLinePrivate::Op::Pause, time, 0., 0., d->order++);
+ d->add(obj, op);
+}
+
+/*!
+ Execute the \a event.
+ */
+void QDeclarative1TimeLine::callback(const QDeclarative1TimeLineCallback &callback)
+{
+ QDeclarative1TimeLinePrivate::Op op(QDeclarative1TimeLinePrivate::Op::Execute, 0, 0, 0., d->order++, callback);
+ d->add(*callback.callbackObject(), op);
+}
+
+/*!
+ Set the \a value of \a timeLineValue.
+*/
+void QDeclarative1TimeLine::set(QDeclarative1TimeLineValue &timeLineValue, qreal value)
+{
+ QDeclarative1TimeLinePrivate::Op op(QDeclarative1TimeLinePrivate::Op::Set, 0, value, 0., d->order++);
+ d->add(timeLineValue, op);
+}
+
+/*!
+ Decelerate \a timeLineValue from the starting \a velocity to zero at the
+ given \a acceleration rate. Although the \a acceleration is technically
+ a deceleration, it should always be positive. The QDeclarative1TimeLine will ensure
+ that the deceleration is in the opposite direction to the initial velocity.
+*/
+int QDeclarative1TimeLine::accel(QDeclarative1TimeLineValue &timeLineValue, qreal velocity, qreal acceleration)
+{
+ if (acceleration == 0.0f)
+ return -1;
+
+ if ((velocity > 0.0f) == (acceleration > 0.0f))
+ acceleration = acceleration * -1.0f;
+
+ int time = static_cast<int>(-1000 * velocity / acceleration);
+
+ QDeclarative1TimeLinePrivate::Op op(QDeclarative1TimeLinePrivate::Op::Accel, time, velocity, acceleration, d->order++);
+ d->add(timeLineValue, op);
+
+ return time;
+}
+
+/*!
+ \overload
+
+ Decelerate \a timeLineValue from the starting \a velocity to zero at the
+ given \a acceleration rate over a maximum distance of maxDistance.
+
+ If necessary, QDeclarative1TimeLine will reduce the acceleration to ensure that the
+ entire operation does not require a move of more than \a maxDistance.
+ \a maxDistance should always be positive.
+*/
+int QDeclarative1TimeLine::accel(QDeclarative1TimeLineValue &timeLineValue, qreal velocity, qreal acceleration, qreal maxDistance)
+{
+ if (maxDistance == 0.0f || acceleration == 0.0f)
+ return -1;
+
+ Q_ASSERT(acceleration > 0.0f && maxDistance > 0.0f);
+
+ qreal maxAccel = (velocity * velocity) / (2.0f * maxDistance);
+ if (maxAccel > acceleration)
+ acceleration = maxAccel;
+
+ if ((velocity > 0.0f) == (acceleration > 0.0f))
+ acceleration = acceleration * -1.0f;
+
+ int time = static_cast<int>(-1000 * velocity / acceleration);
+
+ QDeclarative1TimeLinePrivate::Op op(QDeclarative1TimeLinePrivate::Op::Accel, time, velocity, acceleration, d->order++);
+ d->add(timeLineValue, op);
+
+ return time;
+}
+
+/*!
+ Decelerate \a timeLineValue from the starting \a velocity to zero over the given
+ \a distance. This is like accel(), but the QDeclarative1TimeLine calculates the exact
+ deceleration to use.
+
+ \a distance should be positive.
+*/
+int QDeclarative1TimeLine::accelDistance(QDeclarative1TimeLineValue &timeLineValue, qreal velocity, qreal distance)
+{
+ if (distance == 0.0f || velocity == 0.0f)
+ return -1;
+
+ Q_ASSERT((distance >= 0.0f) == (velocity >= 0.0f));
+
+ int time = static_cast<int>(1000 * (2.0f * distance) / velocity);
+
+ QDeclarative1TimeLinePrivate::Op op(QDeclarative1TimeLinePrivate::Op::AccelDistance, time, velocity, distance, d->order++);
+ d->add(timeLineValue, op);
+
+ return time;
+}
+
+/*!
+ Linearly change the \a timeLineValue from its current value to the given
+ \a destination value over \a time milliseconds.
+*/
+void QDeclarative1TimeLine::move(QDeclarative1TimeLineValue &timeLineValue, qreal destination, int time)
+{
+ if (time <= 0) return;
+ QDeclarative1TimeLinePrivate::Op op(QDeclarative1TimeLinePrivate::Op::Move, time, destination, 0.0f, d->order++);
+ d->add(timeLineValue, op);
+}
+
+/*!
+ Change the \a timeLineValue from its current value to the given \a destination
+ value over \a time milliseconds using the \a easing curve.
+ */
+void QDeclarative1TimeLine::move(QDeclarative1TimeLineValue &timeLineValue, qreal destination, const QEasingCurve &easing, int time)
+{
+ if (time <= 0) return;
+ QDeclarative1TimeLinePrivate::Op op(QDeclarative1TimeLinePrivate::Op::Move, time, destination, 0.0f, d->order++, QDeclarative1TimeLineCallback(), easing);
+ d->add(timeLineValue, op);
+}
+
+/*!
+ Linearly change the \a timeLineValue from its current value by the \a change amount
+ over \a time milliseconds.
+*/
+void QDeclarative1TimeLine::moveBy(QDeclarative1TimeLineValue &timeLineValue, qreal change, int time)
+{
+ if (time <= 0) return;
+ QDeclarative1TimeLinePrivate::Op op(QDeclarative1TimeLinePrivate::Op::MoveBy, time, change, 0.0f, d->order++);
+ d->add(timeLineValue, op);
+}
+
+/*!
+ Change the \a timeLineValue from its current value by the \a change amount over
+ \a time milliseconds using the \a easing curve.
+ */
+void QDeclarative1TimeLine::moveBy(QDeclarative1TimeLineValue &timeLineValue, qreal change, const QEasingCurve &easing, int time)
+{
+ if (time <= 0) return;
+ QDeclarative1TimeLinePrivate::Op op(QDeclarative1TimeLinePrivate::Op::MoveBy, time, change, 0.0f, d->order++, QDeclarative1TimeLineCallback(), easing);
+ d->add(timeLineValue, op);
+}
+
+/*!
+ Cancel (but don't complete) all scheduled actions for \a timeLineValue.
+*/
+void QDeclarative1TimeLine::reset(QDeclarative1TimeLineValue &timeLineValue)
+{
+ if (!timeLineValue._t)
+ return;
+ if (timeLineValue._t != this) {
+ qWarning() << "QDeclarative1TimeLine: Cannot reset a QDeclarative1TimeLineValue owned by another timeline.";
+ return;
+ }
+ remove(&timeLineValue);
+ timeLineValue._t = 0;
+}
+
+int QDeclarative1TimeLine::duration() const
+{
+ return -1;
+}
+
+/*!
+ Synchronize the end point of \a timeLineValue to the endpoint of \a syncTo
+ within this timeline.
+
+ Following operations on \a timeLineValue in this timeline will be scheduled after
+ all the currently scheduled actions on \a syncTo are complete. In
+ pseudo-code this is equivalent to:
+ \code
+ QDeclarative1TimeLine::pause(timeLineValue, min(0, length_of(syncTo) - length_of(timeLineValue)))
+ \endcode
+*/
+void QDeclarative1TimeLine::sync(QDeclarative1TimeLineValue &timeLineValue, QDeclarative1TimeLineValue &syncTo)
+{
+ QDeclarative1TimeLinePrivate::Ops::Iterator iter = d->ops.find(&syncTo);
+ if (iter == d->ops.end())
+ return;
+ int length = iter->length;
+
+ iter = d->ops.find(&timeLineValue);
+ if (iter == d->ops.end()) {
+ pause(timeLineValue, length);
+ } else {
+ int glength = iter->length;
+ pause(timeLineValue, length - glength);
+ }
+}
+
+/*!
+ Synchronize the end point of \a timeLineValue to the endpoint of the longest
+ action cursrently scheduled in the timeline.
+
+ In pseudo-code, this is equivalent to:
+ \code
+ QDeclarative1TimeLine::pause(timeLineValue, length_of(timeline) - length_of(timeLineValue))
+ \endcode
+*/
+void QDeclarative1TimeLine::sync(QDeclarative1TimeLineValue &timeLineValue)
+{
+ QDeclarative1TimeLinePrivate::Ops::Iterator iter = d->ops.find(&timeLineValue);
+ if (iter == d->ops.end()) {
+ pause(timeLineValue, d->length);
+ } else {
+ pause(timeLineValue, d->length - iter->length);
+ }
+}
+
+/*
+ Synchronize all currently and future scheduled values in this timeline to
+ the longest action currently scheduled.
+
+ For example:
+ \code
+ value1->setValue(0.);
+ value2->setValue(0.);
+ value3->setValue(0.);
+ QDeclarative1TimeLine tl;
+ ...
+ tl.move(value1, 10, 200);
+ tl.move(value2, 10, 100);
+ tl.sync();
+ tl.move(value2, 20, 100);
+ tl.move(value3, 20, 100);
+ \endcode
+
+ will result in:
+
+ \table
+ \header \o \o 0ms \o 50ms \o 100ms \o 150ms \o 200ms \o 250ms \o 300ms
+ \row \o value1 \o 0 \o 2.5 \o 5.0 \o 7.5 \o 10 \o 10 \o 10
+ \row \o value2 \o 0 \o 5.0 \o 10.0 \o 10.0 \o 10.0 \o 15.0 \o 20.0
+ \row \o value2 \o 0 \o 0 \o 0 \o 0 \o 0 \o 10.0 \o 20.0
+ \endtable
+*/
+
+/*void QDeclarative1TimeLine::sync()
+{
+ for (QDeclarative1TimeLinePrivate::Ops::Iterator iter = d->ops.begin();
+ iter != d->ops.end();
+ ++iter)
+ pause(*iter.key(), d->length - iter->length);
+ d->syncPoint = d->length;
+}*/
+
+/*!
+ \internal
+
+ Temporary hack.
+ */
+void QDeclarative1TimeLine::setSyncPoint(int sp)
+{
+ d->syncPoint = sp;
+}
+
+/*!
+ \internal
+
+ Temporary hack.
+ */
+int QDeclarative1TimeLine::syncPoint() const
+{
+ return d->syncPoint;
+}
+
+/*!
+ Returns true if the timeline is active. An active timeline is one where
+ QDeclarative1TimeLineValue actions are still pending.
+*/
+bool QDeclarative1TimeLine::isActive() const
+{
+ return !d->ops.isEmpty();
+}
+
+/*!
+ Completes the timeline. All queued actions are played to completion, and then discarded. For example,
+ \code
+ QDeclarative1TimeLineValue v(0.);
+ QDeclarative1TimeLine tl;
+ tl.move(v, 100., 1000.);
+ // 500 ms passes
+ // v.value() == 50.
+ tl.complete();
+ // v.value() == 100.
+ \endcode
+*/
+void QDeclarative1TimeLine::complete()
+{
+ d->advance(d->length);
+}
+
+/*!
+ Resets the timeline. All queued actions are discarded and QDeclarative1TimeLineValue's retain their current value. For example,
+ \code
+ QDeclarative1TimeLineValue v(0.);
+ QDeclarative1TimeLine tl;
+ tl.move(v, 100., 1000.);
+ // 500 ms passes
+ // v.value() == 50.
+ tl.clear();
+ // v.value() == 50.
+ \endcode
+*/
+void QDeclarative1TimeLine::clear()
+{
+ for (QDeclarative1TimeLinePrivate::Ops::ConstIterator iter = d->ops.begin(); iter != d->ops.end(); ++iter)
+ iter.key()->_t = 0;
+ d->ops.clear();
+ d->length = 0;
+ d->syncPoint = 0;
+ //XXX need stop here?
+}
+
+int QDeclarative1TimeLine::time() const
+{
+ return d->prevTime;
+}
+
+/*!
+ \fn void QDeclarative1TimeLine::updated()
+
+ Emitted each time the timeline modifies QDeclarative1TimeLineValues. Even if multiple
+ QDeclarative1TimeLineValues are changed, this signal is only emitted once for each clock tick.
+*/
+
+void QDeclarative1TimeLine::updateCurrentTime(int v)
+{
+ if (d->syncAdj == -1)
+ d->syncAdj = v;
+ v -= d->syncAdj;
+
+ int timeChanged = v - d->prevTime;
+#if 0
+ if (!timeChanged)
+ return;
+#endif
+ d->prevTime = v;
+ d->advance(timeChanged);
+ emit updated();
+
+ // Do we need to stop the clock?
+ if (d->ops.isEmpty()) {
+ stop();
+ d->prevTime = 0;
+ d->clockRunning = false;
+ emit completed();
+ } /*else if (pauseTime > 0) {
+ GfxClock::cancelClock();
+ d->prevTime = 0;
+ GfxClock::pauseFor(pauseTime);
+ d->syncAdj = 0;
+ d->clockRunning = false;
+ }*/ else if (/*!GfxClock::isActive()*/ state() != Running) {
+ stop();
+ d->prevTime = 0;
+ d->clockRunning = true;
+ d->syncAdj = 0;
+ start();
+ }
+}
+
+bool operator<(const QPair<int, Update> &lhs,
+ const QPair<int, Update> &rhs)
+{
+ return lhs.first < rhs.first;
+}
+
+int QDeclarative1TimeLinePrivate::advance(int t)
+{
+ int pauseTime = -1;
+
+ // XXX - surely there is a more efficient way?
+ do {
+ pauseTime = -1;
+ // Minimal advance time
+ int advanceTime = t;
+ for (Ops::Iterator iter = ops.begin(); iter != ops.end(); ++iter) {
+ TimeLine &tl = *iter;
+ Op &op = tl.ops.first();
+ int length = op.length - tl.consumedOpLength;
+
+ if (length < advanceTime) {
+ advanceTime = length;
+ if (advanceTime == 0)
+ break;
+ }
+ }
+ t -= advanceTime;
+
+ // Process until then. A zero length advance time will only process
+ // sets.
+ QList<QPair<int, Update> > updates;
+
+ for (Ops::Iterator iter = ops.begin(); iter != ops.end(); ) {
+ QDeclarative1TimeLineValue *v = static_cast<QDeclarative1TimeLineValue *>(iter.key());
+ TimeLine &tl = *iter;
+ Q_ASSERT(!tl.ops.isEmpty());
+
+ do {
+ Op &op = tl.ops.first();
+ if (advanceTime == 0 && op.length != 0)
+ continue;
+
+ if (tl.consumedOpLength == 0 &&
+ op.type != Op::Pause &&
+ op.type != Op::Execute)
+ tl.base = v->value();
+
+ if ((tl.consumedOpLength + advanceTime) == op.length) {
+ if (op.type == Op::Execute) {
+ updates << qMakePair(op.order, Update(op.event));
+ } else {
+ bool changed = false;
+ qreal val = value(op, op.length, tl.base, &changed);
+ if (changed)
+ updates << qMakePair(op.order, Update(v, val));
+ }
+ tl.length -= qMin(advanceTime, tl.length);
+ tl.consumedOpLength = 0;
+ tl.ops.removeFirst();
+ } else {
+ tl.consumedOpLength += advanceTime;
+ bool changed = false;
+ qreal val = value(op, tl.consumedOpLength, tl.base, &changed);
+ if (changed)
+ updates << qMakePair(op.order, Update(v, val));
+ tl.length -= qMin(advanceTime, tl.length);
+ break;
+ }
+
+ } while(!tl.ops.isEmpty() && advanceTime == 0 && tl.ops.first().length == 0);
+
+
+ if (tl.ops.isEmpty()) {
+ iter = ops.erase(iter);
+ v->_t = 0;
+ } else {
+ if (tl.ops.first().type == Op::Pause && pauseTime != 0) {
+ int opPauseTime = tl.ops.first().length - tl.consumedOpLength;
+ if (pauseTime == -1 || opPauseTime < pauseTime)
+ pauseTime = opPauseTime;
+ } else {
+ pauseTime = 0;
+ }
+ ++iter;
+ }
+ }
+
+ length -= qMin(length, advanceTime);
+ syncPoint -= advanceTime;
+
+ qSort(updates.begin(), updates.end());
+ updateQueue = &updates;
+ for (int ii = 0; ii < updates.count(); ++ii) {
+ const Update &v = updates.at(ii).second;
+ if (v.g) {
+ v.g->setValue(v.v);
+ } else {
+ v.e.d0(v.e.d1);
+ }
+ }
+ updateQueue = 0;
+ } while(t);
+
+ return pauseTime;
+}
+
+void QDeclarative1TimeLine::remove(QDeclarative1TimeLineObject *v)
+{
+ QDeclarative1TimeLinePrivate::Ops::Iterator iter = d->ops.find(v);
+ Q_ASSERT(iter != d->ops.end());
+
+ int len = iter->length;
+ d->ops.erase(iter);
+ if (len == d->length) {
+ // We need to recalculate the length
+ d->length = 0;
+ for (QDeclarative1TimeLinePrivate::Ops::Iterator iter = d->ops.begin();
+ iter != d->ops.end();
+ ++iter) {
+
+ if (iter->length > d->length)
+ d->length = iter->length;
+
+ }
+ }
+ if (d->ops.isEmpty()) {
+ stop();
+ d->clockRunning = false;
+ } else if (/*!GfxClock::isActive()*/ state() != Running) {
+ stop();
+ d->prevTime = 0;
+ d->clockRunning = true;
+
+ if (d->syncMode == QDeclarative1TimeLine::LocalSync) {
+ d->syncAdj = -1;
+ } else {
+ d->syncAdj = 0;
+ }
+ start();
+ }
+
+ if (d->updateQueue) {
+ for (int ii = 0; ii < d->updateQueue->count(); ++ii) {
+ if (d->updateQueue->at(ii).second.g == v ||
+ d->updateQueue->at(ii).second.e.callbackObject() == v) {
+ d->updateQueue->removeAt(ii);
+ --ii;
+ }
+ }
+ }
+
+
+}
+
+/*!
+ \internal
+ \class QDeclarative1TimeLineValue
+ \brief The QDeclarative1TimeLineValue class provides a value that can be modified by QDeclarative1TimeLine.
+*/
+
+/*!
+ \fn QDeclarative1TimeLineValue::QDeclarative1TimeLineValue(qreal value = 0)
+
+ Construct a new QDeclarative1TimeLineValue with an initial \a value.
+*/
+
+/*!
+ \fn qreal QDeclarative1TimeLineValue::value() const
+
+ Return the current value.
+*/
+
+/*!
+ \fn void QDeclarative1TimeLineValue::setValue(qreal value)
+
+ Set the current \a value.
+*/
+
+/*!
+ \fn QDeclarative1TimeLine *QDeclarative1TimeLineValue::timeLine() const
+
+ If a QDeclarative1TimeLine is operating on this value, return a pointer to it,
+ otherwise return null.
+*/
+
+
+QDeclarative1TimeLineObject::QDeclarative1TimeLineObject()
+: _t(0)
+{
+}
+
+QDeclarative1TimeLineObject::~QDeclarative1TimeLineObject()
+{
+ if (_t) {
+ _t->remove(this);
+ _t = 0;
+ }
+}
+
+QDeclarative1TimeLineCallback::QDeclarative1TimeLineCallback()
+: d0(0), d1(0), d2(0)
+{
+}
+
+QDeclarative1TimeLineCallback::QDeclarative1TimeLineCallback(QDeclarative1TimeLineObject *b, Callback f, void *d)
+: d0(f), d1(d), d2(b)
+{
+}
+
+QDeclarative1TimeLineCallback::QDeclarative1TimeLineCallback(const QDeclarative1TimeLineCallback &o)
+: d0(o.d0), d1(o.d1), d2(o.d2)
+{
+}
+
+QDeclarative1TimeLineCallback &QDeclarative1TimeLineCallback::operator=(const QDeclarative1TimeLineCallback &o)
+{
+ d0 = o.d0;
+ d1 = o.d1;
+ d2 = o.d2;
+ return *this;
+}
+
+QDeclarative1TimeLineObject *QDeclarative1TimeLineCallback::callbackObject() const
+{
+ return d2;
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/util/qdeclarativetimeline_p_p.h b/src/qtquick1/util/qdeclarativetimeline_p_p.h
new file mode 100644
index 0000000000..73f1ebfabe
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativetimeline_p_p.h
@@ -0,0 +1,200 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVETIMELINE_H
+#define QDECLARATIVETIMELINE_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QObject>
+#include <QtCore/QAbstractAnimation>
+
+QT_BEGIN_NAMESPACE
+
+class QEasingCurve;
+class QDeclarative1TimeLineValue;
+class QDeclarative1TimeLineCallback;
+struct QDeclarative1TimeLinePrivate;
+class QDeclarative1TimeLineObject;
+class Q_AUTOTEST_EXPORT QDeclarative1TimeLine : public QAbstractAnimation
+{
+Q_OBJECT
+public:
+ QDeclarative1TimeLine(QObject *parent = 0);
+ ~QDeclarative1TimeLine();
+
+ enum SyncMode { LocalSync, GlobalSync };
+ SyncMode syncMode() const;
+ void setSyncMode(SyncMode);
+
+ void pause(QDeclarative1TimeLineObject &, int);
+ void callback(const QDeclarative1TimeLineCallback &);
+ void set(QDeclarative1TimeLineValue &, qreal);
+
+ int accel(QDeclarative1TimeLineValue &, qreal velocity, qreal accel);
+ int accel(QDeclarative1TimeLineValue &, qreal velocity, qreal accel, qreal maxDistance);
+ int accelDistance(QDeclarative1TimeLineValue &, qreal velocity, qreal distance);
+
+ void move(QDeclarative1TimeLineValue &, qreal destination, int time = 500);
+ void move(QDeclarative1TimeLineValue &, qreal destination, const QEasingCurve &, int time = 500);
+ void moveBy(QDeclarative1TimeLineValue &, qreal change, int time = 500);
+ void moveBy(QDeclarative1TimeLineValue &, qreal change, const QEasingCurve &, int time = 500);
+
+ void sync();
+ void setSyncPoint(int);
+ int syncPoint() const;
+
+ void sync(QDeclarative1TimeLineValue &);
+ void sync(QDeclarative1TimeLineValue &, QDeclarative1TimeLineValue &);
+
+ void reset(QDeclarative1TimeLineValue &);
+
+ void complete();
+ void clear();
+ bool isActive() const;
+
+ int time() const;
+
+ virtual int duration() const;
+Q_SIGNALS:
+ void updated();
+ void completed();
+
+protected:
+ virtual void updateCurrentTime(int);
+
+private:
+ void remove(QDeclarative1TimeLineObject *);
+ friend class QDeclarative1TimeLineObject;
+ friend struct QDeclarative1TimeLinePrivate;
+ QDeclarative1TimeLinePrivate *d;
+};
+
+class Q_AUTOTEST_EXPORT QDeclarative1TimeLineObject
+{
+public:
+ QDeclarative1TimeLineObject();
+ virtual ~QDeclarative1TimeLineObject();
+
+protected:
+ friend class QDeclarative1TimeLine;
+ friend struct QDeclarative1TimeLinePrivate;
+ QDeclarative1TimeLine *_t;
+};
+
+class Q_AUTOTEST_EXPORT QDeclarative1TimeLineValue : public QDeclarative1TimeLineObject
+{
+public:
+ QDeclarative1TimeLineValue(qreal v = 0.) : _v(v) {}
+
+ virtual qreal value() const { return _v; }
+ virtual void setValue(qreal v) { _v = v; }
+
+ QDeclarative1TimeLine *timeLine() const { return _t; }
+
+ operator qreal() const { return _v; }
+ QDeclarative1TimeLineValue &operator=(qreal v) { setValue(v); return *this; }
+private:
+ friend class QDeclarative1TimeLine;
+ friend struct QDeclarative1TimeLinePrivate;
+ qreal _v;
+};
+
+class Q_AUTOTEST_EXPORT QDeclarative1TimeLineCallback
+{
+public:
+ typedef void (*Callback)(void *);
+
+ QDeclarative1TimeLineCallback();
+ QDeclarative1TimeLineCallback(QDeclarative1TimeLineObject *b, Callback, void * = 0);
+ QDeclarative1TimeLineCallback(const QDeclarative1TimeLineCallback &o);
+
+ QDeclarative1TimeLineCallback &operator=(const QDeclarative1TimeLineCallback &o);
+ QDeclarative1TimeLineObject *callbackObject() const;
+
+private:
+ friend struct QDeclarative1TimeLinePrivate;
+ Callback d0;
+ void *d1;
+ QDeclarative1TimeLineObject *d2;
+};
+
+template<class T>
+class QDeclarative1TimeLineValueProxy : public QDeclarative1TimeLineValue
+{
+public:
+ QDeclarative1TimeLineValueProxy(T *cls, void (T::*func)(qreal), qreal v = 0.)
+ : QDeclarative1TimeLineValue(v), _class(cls), _setFunctionReal(func), _setFunctionInt(0)
+ {
+ Q_ASSERT(_class);
+ }
+
+ QDeclarative1TimeLineValueProxy(T *cls, void (T::*func)(int), qreal v = 0.)
+ : QDeclarative1TimeLineValue(v), _class(cls), _setFunctionReal(0), _setFunctionInt(func)
+ {
+ Q_ASSERT(_class);
+ }
+
+ virtual void setValue(qreal v)
+ {
+ QDeclarative1TimeLineValue::setValue(v);
+ if (_setFunctionReal) (_class->*_setFunctionReal)(v);
+ else if (_setFunctionInt) (_class->*_setFunctionInt)((int)v);
+ }
+
+private:
+ T *_class;
+ void (T::*_setFunctionReal)(qreal);
+ void (T::*_setFunctionInt)(int);
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/qtquick1/util/qdeclarativetimer.cpp b/src/qtquick1/util/qdeclarativetimer.cpp
new file mode 100644
index 0000000000..2456dc06cf
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativetimer.cpp
@@ -0,0 +1,328 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativetimer_p.h"
+
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qpauseanimation.h>
+#include <qdebug.h>
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+
+
+
+
+class QDeclarative1TimerPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1Timer)
+public:
+ QDeclarative1TimerPrivate()
+ : interval(1000), running(false), repeating(false), triggeredOnStart(false)
+ , classBegun(false), componentComplete(false), firstTick(true) {}
+ int interval;
+ QPauseAnimation pause;
+ bool running : 1;
+ bool repeating : 1;
+ bool triggeredOnStart : 1;
+ bool classBegun : 1;
+ bool componentComplete : 1;
+ bool firstTick : 1;
+};
+
+/*!
+ \qmlclass Timer QDeclarative1Timer
+ \ingroup qml-utility-elements
+ \since 4.7
+ \brief The Timer item triggers a handler at a specified interval.
+
+ A Timer can be used to trigger an action either once, or repeatedly
+ at a given interval.
+
+ Here is a Timer that shows the current date and time, and updates
+ the text every 500 milliseconds. It uses the JavaScript \c Date
+ object to access the current time.
+
+ \qml
+ import QtQuick 1.0
+
+ Item {
+ Timer {
+ interval: 500; running: true; repeat: true
+ onTriggered: time.text = Date().toString()
+ }
+
+ Text { id: time }
+ }
+ \endqml
+
+ The Timer element is synchronized with the animation timer. Since the animation
+ timer is usually set to 60fps, the resolution of Timer will be
+ at best 16ms.
+
+ If the Timer is running and one of its properties is changed, the
+ elapsed time will be reset. For example, if a Timer with interval of
+ 1000ms has its \e repeat property changed 500ms after starting, the
+ elapsed time will be reset to 0, and the Timer will be triggered
+ 1000ms later.
+
+ \sa {declarative/toys/clocks}{Clocks example}
+*/
+
+QDeclarative1Timer::QDeclarative1Timer(QObject *parent)
+ : QObject(*(new QDeclarative1TimerPrivate), parent)
+{
+ Q_D(QDeclarative1Timer);
+ connect(&d->pause, SIGNAL(currentLoopChanged(int)), this, SLOT(ticked()));
+ connect(&d->pause, SIGNAL(finished()), this, SLOT(finished()));
+ d->pause.setLoopCount(1);
+ d->pause.setDuration(d->interval);
+}
+
+/*!
+ \qmlproperty int Timer::interval
+
+ Sets the \a interval between triggers, in milliseconds.
+
+ The default interval is 1000 milliseconds.
+*/
+void QDeclarative1Timer::setInterval(int interval)
+{
+ Q_D(QDeclarative1Timer);
+ if (interval != d->interval) {
+ d->interval = interval;
+ update();
+ emit intervalChanged();
+ }
+}
+
+int QDeclarative1Timer::interval() const
+{
+ Q_D(const QDeclarative1Timer);
+ return d->interval;
+}
+
+/*!
+ \qmlproperty bool Timer::running
+
+ If set to true, starts the timer; otherwise stops the timer.
+ For a non-repeating timer, \a running is set to false after the
+ timer has been triggered.
+
+ \a running defaults to false.
+
+ \sa repeat
+*/
+bool QDeclarative1Timer::isRunning() const
+{
+ Q_D(const QDeclarative1Timer);
+ return d->running;
+}
+
+void QDeclarative1Timer::setRunning(bool running)
+{
+ Q_D(QDeclarative1Timer);
+ if (d->running != running) {
+ d->running = running;
+ d->firstTick = true;
+ emit runningChanged();
+ update();
+ }
+}
+
+/*!
+ \qmlproperty bool Timer::repeat
+
+ If \a repeat is true the timer is triggered repeatedly at the
+ specified interval; otherwise, the timer will trigger once at the
+ specified interval and then stop (i.e. running will be set to false).
+
+ \a repeat defaults to false.
+
+ \sa running
+*/
+bool QDeclarative1Timer::isRepeating() const
+{
+ Q_D(const QDeclarative1Timer);
+ return d->repeating;
+}
+
+void QDeclarative1Timer::setRepeating(bool repeating)
+{
+ Q_D(QDeclarative1Timer);
+ if (repeating != d->repeating) {
+ d->repeating = repeating;
+ update();
+ emit repeatChanged();
+ }
+}
+
+/*!
+ \qmlproperty bool Timer::triggeredOnStart
+
+ When a timer is started, the first trigger is usually after the specified
+ interval has elapsed. It is sometimes desirable to trigger immediately
+ when the timer is started; for example, to establish an initial
+ state.
+
+ If \a triggeredOnStart is true, the timer is triggered immediately
+ when started, and subsequently at the specified interval. Note that if
+ \e repeat is set to false, the timer is triggered twice; once on start,
+ and again at the interval.
+
+ \a triggeredOnStart defaults to false.
+
+ \sa running
+*/
+bool QDeclarative1Timer::triggeredOnStart() const
+{
+ Q_D(const QDeclarative1Timer);
+ return d->triggeredOnStart;
+}
+
+void QDeclarative1Timer::setTriggeredOnStart(bool triggeredOnStart)
+{
+ Q_D(QDeclarative1Timer);
+ if (d->triggeredOnStart != triggeredOnStart) {
+ d->triggeredOnStart = triggeredOnStart;
+ update();
+ emit triggeredOnStartChanged();
+ }
+}
+
+/*!
+ \qmlmethod Timer::start()
+ \brief Starts the timer.
+
+ If the timer is already running, calling this method has no effect. The
+ \c running property will be true following a call to \c start().
+*/
+void QDeclarative1Timer::start()
+{
+ setRunning(true);
+}
+
+/*!
+ \qmlmethod Timer::stop()
+ \brief Stops the timer.
+
+ If the timer is not running, calling this method has no effect. The
+ \c running property will be false following a call to \c stop().
+*/
+void QDeclarative1Timer::stop()
+{
+ setRunning(false);
+}
+
+/*!
+ \qmlmethod Timer::restart()
+ \brief Restarts the timer.
+
+ If the Timer is not running it will be started, otherwise it will be
+ stopped, reset to initial state and started. The \c running property
+ will be true following a call to \c restart().
+*/
+void QDeclarative1Timer::restart()
+{
+ setRunning(false);
+ setRunning(true);
+}
+
+void QDeclarative1Timer::update()
+{
+ Q_D(QDeclarative1Timer);
+ if (d->classBegun && !d->componentComplete)
+ return;
+ d->pause.stop();
+ if (d->running) {
+ d->pause.setCurrentTime(0);
+ d->pause.setLoopCount(d->repeating ? -1 : 1);
+ d->pause.setDuration(d->interval);
+ d->pause.start();
+ if (d->triggeredOnStart && d->firstTick) {
+ QCoreApplication::removePostedEvents(this, QEvent::MetaCall);
+ QMetaObject::invokeMethod(this, "ticked", Qt::QueuedConnection);
+ }
+ }
+}
+
+void QDeclarative1Timer::classBegin()
+{
+ Q_D(QDeclarative1Timer);
+ d->classBegun = true;
+}
+
+void QDeclarative1Timer::componentComplete()
+{
+ Q_D(QDeclarative1Timer);
+ d->componentComplete = true;
+ update();
+}
+
+/*!
+ \qmlsignal Timer::onTriggered()
+
+ This handler is called when the Timer is triggered.
+*/
+void QDeclarative1Timer::ticked()
+{
+ Q_D(QDeclarative1Timer);
+ if (d->running && (d->pause.currentTime() > 0 || (d->triggeredOnStart && d->firstTick)))
+ emit triggered();
+ d->firstTick = false;
+}
+
+void QDeclarative1Timer::finished()
+{
+ Q_D(QDeclarative1Timer);
+ if (d->repeating || !d->running)
+ return;
+ emit triggered();
+ d->running = false;
+ d->firstTick = false;
+ emit runningChanged();
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/util/qdeclarativetimer_p.h b/src/qtquick1/util/qdeclarativetimer_p.h
new file mode 100644
index 0000000000..5465773280
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativetimer_p.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVETIMER_H
+#define QDECLARATIVETIMER_H
+
+#include <QtDeclarative/qdeclarative.h>
+
+#include <QtCore/qobject.h>
+#include <QtCore/qabstractanimation.h>
+
+#include <QtDeclarative/private/qdeclarativeglobal_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarative1TimerPrivate;
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarative1Timer : public QObject, public QDeclarativeParserStatus
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarative1Timer)
+ Q_INTERFACES(QDeclarativeParserStatus)
+ Q_PROPERTY(int interval READ interval WRITE setInterval NOTIFY intervalChanged)
+ Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged)
+ Q_PROPERTY(bool repeat READ isRepeating WRITE setRepeating NOTIFY repeatChanged)
+ Q_PROPERTY(bool triggeredOnStart READ triggeredOnStart WRITE setTriggeredOnStart NOTIFY triggeredOnStartChanged)
+ Q_PROPERTY(QObject *parent READ parent CONSTANT)
+
+public:
+ QDeclarative1Timer(QObject *parent=0);
+
+ void setInterval(int interval);
+ int interval() const;
+
+ bool isRunning() const;
+ void setRunning(bool running);
+
+ bool isRepeating() const;
+ void setRepeating(bool repeating);
+
+ bool triggeredOnStart() const;
+ void setTriggeredOnStart(bool triggeredOnStart);
+
+protected:
+ void classBegin();
+ void componentComplete();
+
+public Q_SLOTS:
+ void start();
+ void stop();
+ void restart();
+
+Q_SIGNALS:
+ void triggered();
+ void runningChanged();
+ void intervalChanged();
+ void repeatChanged();
+ void triggeredOnStartChanged();
+
+private:
+ void update();
+
+private Q_SLOTS:
+ void ticked();
+ void finished();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1Timer)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/qtquick1/util/qdeclarativetransition.cpp b/src/qtquick1/util/qdeclarativetransition.cpp
new file mode 100644
index 0000000000..7a2d4af94e
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativetransition.cpp
@@ -0,0 +1,349 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativestate_p.h"
+#include "QtQuick1/private/qdeclarativestategroup_p.h"
+#include "QtQuick1/private/qdeclarativestate_p_p.h"
+#include "QtQuick1/private/qdeclarativestateoperations_p.h"
+#include "QtQuick1/private/qdeclarativeanimation_p.h"
+#include "QtQuick1/private/qdeclarativeanimation_p_p.h"
+#include "QtQuick1/private/qdeclarativetransitionmanager_p_p.h"
+
+#include <QParallelAnimationGroup>
+
+QT_BEGIN_NAMESPACE
+
+
+
+/*!
+ \qmlclass Transition QDeclarative1Transition
+ \ingroup qml-animation-transition
+ \since 4.7
+ \brief The Transition element defines animated transitions that occur on state changes.
+
+ A Transition defines the animations to be applied when a \l State change occurs.
+
+ For example, the following \l Rectangle has two states: the default state, and
+ an added "moved" state. In the "moved state, the rectangle's position changes
+ to (50, 50). The added Transition specifies that when the rectangle
+ changes between the default and the "moved" state, any changes
+ to the \c x and \c y properties should be animated, using an \c Easing.InOutQuad.
+
+ \snippet doc/src/snippets/declarative/transition.qml 0
+
+ Notice the example does not require \l{PropertyAnimation::}{to} and
+ \l{PropertyAnimation::}{from} values for the NumberAnimation. As a convenience,
+ these properties are automatically set to the values of \c x and \c y before
+ and after the state change; the \c from values are provided by
+ the current values of \c x and \c y, and the \c to values are provided by
+ the PropertyChanges object. If you wish, you can provide \l{PropertyAnimation::}{to} and
+ \l{PropertyAnimation::}{from} values anyway to override the default values.
+
+ By default, a Transition's animations are applied for any state change in the
+ parent item. The Transition \l {Transition::}{from} and \l {Transition::}{to}
+ values can be set to restrict the animations to only be applied when changing
+ from one particular state to another.
+
+ To define multiple transitions, specify \l Item::transitions as a list:
+
+ \snippet doc/src/snippets/declarative/transitions-list.qml list of transitions
+
+ If multiple Transitions are specified, only a single (best-matching) Transition will be applied for any particular
+ state change. In the example above, when changing to \c state1, the first transition will be used, rather
+ than the more generic second transition.
+
+ If a state change has a Transition that matches the same property as a
+ \l Behavior, the Transition animation overrides the \l Behavior for that
+ state change.
+
+ \sa {QML Animation and Transitions}, {declarative/animation/states}{states example}, {qmlstates}{States}, {QtDeclarative}
+*/
+
+//ParallelAnimationWrapper_1 allows us to do a "callback" when the animation finishes, rather than connecting
+//and disconnecting signals and slots frequently
+class ParallelAnimationWrapper_1 : public QParallelAnimationGroup
+{
+ Q_OBJECT
+public:
+ ParallelAnimationWrapper_1(QObject *parent = 0) : QParallelAnimationGroup(parent) {}
+ QDeclarative1TransitionPrivate *trans;
+protected:
+ virtual void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState);
+};
+
+class QDeclarative1TransitionPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1Transition)
+public:
+ QDeclarative1TransitionPrivate()
+ : fromState(QLatin1String("*")), toState(QLatin1String("*")),
+ reversed(false), reversible(false), endState(0)
+ {
+ group.trans = this;
+ }
+
+ QString fromState;
+ QString toState;
+ bool reversed;
+ bool reversible;
+ ParallelAnimationWrapper_1 group;
+ QDeclarative1TransitionManager *endState;
+
+ void complete()
+ {
+ endState->complete();
+ }
+ static void append_animation(QDeclarativeListProperty<QDeclarative1AbstractAnimation> *list, QDeclarative1AbstractAnimation *a);
+ static int animation_count(QDeclarativeListProperty<QDeclarative1AbstractAnimation> *list);
+ static QDeclarative1AbstractAnimation* animation_at(QDeclarativeListProperty<QDeclarative1AbstractAnimation> *list, int pos);
+ static void clear_animations(QDeclarativeListProperty<QDeclarative1AbstractAnimation> *list);
+ QList<QDeclarative1AbstractAnimation *> animations;
+};
+
+void QDeclarative1TransitionPrivate::append_animation(QDeclarativeListProperty<QDeclarative1AbstractAnimation> *list, QDeclarative1AbstractAnimation *a)
+{
+ QDeclarative1Transition *q = static_cast<QDeclarative1Transition *>(list->object);
+ q->d_func()->animations.append(a);
+ q->d_func()->group.addAnimation(a->qtAnimation());
+ a->setDisableUserControl();
+}
+
+int QDeclarative1TransitionPrivate::animation_count(QDeclarativeListProperty<QDeclarative1AbstractAnimation> *list)
+{
+ QDeclarative1Transition *q = static_cast<QDeclarative1Transition *>(list->object);
+ return q->d_func()->animations.count();
+}
+
+QDeclarative1AbstractAnimation* QDeclarative1TransitionPrivate::animation_at(QDeclarativeListProperty<QDeclarative1AbstractAnimation> *list, int pos)
+{
+ QDeclarative1Transition *q = static_cast<QDeclarative1Transition *>(list->object);
+ return q->d_func()->animations.at(pos);
+}
+
+void QDeclarative1TransitionPrivate::clear_animations(QDeclarativeListProperty<QDeclarative1AbstractAnimation> *list)
+{
+ QDeclarative1Transition *q = static_cast<QDeclarative1Transition *>(list->object);
+ while (q->d_func()->animations.count()) {
+ QDeclarative1AbstractAnimation *firstAnim = q->d_func()->animations.at(0);
+ q->d_func()->group.removeAnimation(firstAnim->qtAnimation());
+ q->d_func()->animations.removeAll(firstAnim);
+ }
+}
+
+void ParallelAnimationWrapper_1::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState)
+{
+ QParallelAnimationGroup::updateState(newState, oldState);
+ if (newState == Stopped && (duration() == -1
+ || (direction() == QAbstractAnimation::Forward && currentLoopTime() == duration())
+ || (direction() == QAbstractAnimation::Backward && currentLoopTime() == 0)))
+ {
+ trans->complete();
+ }
+}
+
+
+
+QDeclarative1Transition::QDeclarative1Transition(QObject *parent)
+ : QObject(*(new QDeclarative1TransitionPrivate), parent)
+{
+}
+
+QDeclarative1Transition::~QDeclarative1Transition()
+{
+}
+
+void QDeclarative1Transition::stop()
+{
+ Q_D(QDeclarative1Transition);
+ d->group.stop();
+}
+
+void QDeclarative1Transition::setReversed(bool r)
+{
+ Q_D(QDeclarative1Transition);
+ d->reversed = r;
+}
+
+void QDeclarative1Transition::prepare(QDeclarative1StateOperation::ActionList &actions,
+ QList<QDeclarativeProperty> &after,
+ QDeclarative1TransitionManager *endState)
+{
+ Q_D(QDeclarative1Transition);
+
+ qmlExecuteDeferred(this);
+
+ if (d->reversed) {
+ for (int ii = d->animations.count() - 1; ii >= 0; --ii) {
+ d->animations.at(ii)->transition(actions, after, QDeclarative1AbstractAnimation::Backward);
+ }
+ } else {
+ for (int ii = 0; ii < d->animations.count(); ++ii) {
+ d->animations.at(ii)->transition(actions, after, QDeclarative1AbstractAnimation::Forward);
+ }
+ }
+
+ d->endState = endState;
+ d->group.setDirection(d->reversed ? QAbstractAnimation::Backward : QAbstractAnimation::Forward);
+ d->group.start();
+}
+
+/*!
+ \qmlproperty string Transition::from
+ \qmlproperty string Transition::to
+
+ These properties indicate the state changes that trigger the transition.
+
+ The default values for these properties is "*" (that is, any state).
+
+ For example, the following transition has not set the \c to and \c from
+ properties, so the animation is always applied when changing between
+ the two states (i.e. when the mouse is pressed and released).
+
+ \snippet doc/src/snippets/declarative/transition-from-to.qml 0
+
+ If the transition was changed to this:
+
+ \snippet doc/src/snippets/declarative/transition-from-to-modified.qml modified transition
+
+ The animation would only be applied when changing from the default state to
+ the "brighter" state (i.e. when the mouse is pressed, but not on release).
+
+ \sa reversible
+*/
+QString QDeclarative1Transition::fromState() const
+{
+ Q_D(const QDeclarative1Transition);
+ return d->fromState;
+}
+
+void QDeclarative1Transition::setFromState(const QString &f)
+{
+ Q_D(QDeclarative1Transition);
+ if (f == d->fromState)
+ return;
+
+ d->fromState = f;
+ emit fromChanged();
+}
+
+/*!
+ \qmlproperty bool Transition::reversible
+ This property holds whether the transition should be automatically reversed when the conditions that triggered this transition are reversed.
+
+ The default value is false.
+
+ By default, transitions run in parallel and are applied to all state
+ changes if the \l from and \l to states have not been set. In this
+ situation, the transition is automatically applied when a state change
+ is reversed, and it is not necessary to set this property to reverse
+ the transition.
+
+ However, if a SequentialAnimation is used, or if the \l from or \l to
+ properties have been set, this property will need to be set to reverse
+ a transition when a state change is reverted. For example, the following
+ transition applies a sequential animation when the mouse is pressed,
+ and reverses the sequence of the animation when the mouse is released:
+
+ \snippet doc/src/snippets/declarative/transition-reversible.qml 0
+
+ If the transition did not set the \c to and \c reversible values, then
+ on the mouse release, the transition would play the PropertyAnimation
+ before the ColorAnimation instead of reversing the sequence.
+*/
+bool QDeclarative1Transition::reversible() const
+{
+ Q_D(const QDeclarative1Transition);
+ return d->reversible;
+}
+
+void QDeclarative1Transition::setReversible(bool r)
+{
+ Q_D(QDeclarative1Transition);
+ if (r == d->reversible)
+ return;
+
+ d->reversible = r;
+ emit reversibleChanged();
+}
+
+QString QDeclarative1Transition::toState() const
+{
+ Q_D(const QDeclarative1Transition);
+ return d->toState;
+}
+
+void QDeclarative1Transition::setToState(const QString &t)
+{
+ Q_D(QDeclarative1Transition);
+ if (t == d->toState)
+ return;
+
+ d->toState = t;
+ emit toChanged();
+}
+
+/*!
+ \qmlproperty list<Animation> Transition::animations
+ \default
+
+ This property holds a list of the animations to be run for this transition.
+
+ \snippet examples/declarative/toys/dynamicscene/dynamicscene.qml top-level transitions
+
+ The top-level animations are run in parallel. To run them sequentially,
+ define them within a SequentialAnimation:
+
+ \snippet doc/src/snippets/declarative/transition-reversible.qml sequential animations
+*/
+QDeclarativeListProperty<QDeclarative1AbstractAnimation> QDeclarative1Transition::animations()
+{
+ Q_D(QDeclarative1Transition);
+ return QDeclarativeListProperty<QDeclarative1AbstractAnimation>(this, &d->animations, QDeclarative1TransitionPrivate::append_animation,
+ QDeclarative1TransitionPrivate::animation_count,
+ QDeclarative1TransitionPrivate::animation_at,
+ QDeclarative1TransitionPrivate::clear_animations);
+}
+
+
+
+QT_END_NAMESPACE
+
+#include <qdeclarativetransition.moc>
diff --git a/src/qtquick1/util/qdeclarativetransition_p.h b/src/qtquick1/util/qdeclarativetransition_p.h
new file mode 100644
index 0000000000..f3f7afae6d
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativetransition_p.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVETRANSITION_H
+#define QDECLARATIVETRANSITION_H
+
+#include "QtQuick1/private/qdeclarativestate_p.h"
+
+#include <QtDeclarative/qdeclarative.h>
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarative1AbstractAnimation;
+class QDeclarative1TransitionPrivate;
+class QDeclarative1TransitionManager;
+class Q_DECLARATIVE_EXPORT QDeclarative1Transition : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarative1Transition)
+
+ Q_PROPERTY(QString from READ fromState WRITE setFromState NOTIFY fromChanged)
+ Q_PROPERTY(QString to READ toState WRITE setToState NOTIFY toChanged)
+ Q_PROPERTY(bool reversible READ reversible WRITE setReversible NOTIFY reversibleChanged)
+ Q_PROPERTY(QDeclarativeListProperty<QDeclarative1AbstractAnimation> animations READ animations)
+ Q_CLASSINFO("DefaultProperty", "animations")
+ Q_CLASSINFO("DeferredPropertyNames", "animations")
+
+public:
+ QDeclarative1Transition(QObject *parent=0);
+ ~QDeclarative1Transition();
+
+ QString fromState() const;
+ void setFromState(const QString &);
+
+ QString toState() const;
+ void setToState(const QString &);
+
+ bool reversible() const;
+ void setReversible(bool);
+
+ QDeclarativeListProperty<QDeclarative1AbstractAnimation> animations();
+
+ void prepare(QDeclarative1StateOperation::ActionList &actions,
+ QList<QDeclarativeProperty> &after,
+ QDeclarative1TransitionManager *end);
+
+ void setReversed(bool r);
+ void stop();
+
+Q_SIGNALS:
+ void fromChanged();
+ void toChanged();
+ void reversibleChanged();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1Transition)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVETRANSITION_H
diff --git a/src/qtquick1/util/qdeclarativetransitionmanager.cpp b/src/qtquick1/util/qdeclarativetransitionmanager.cpp
new file mode 100644
index 0000000000..914168119a
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativetransitionmanager.cpp
@@ -0,0 +1,280 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativetransitionmanager_p_p.h"
+
+#include "QtQuick1/private/qdeclarativestate_p_p.h"
+#include "QtQuick1/private/qdeclarativestate_p.h"
+
+#include <QtDeclarative/private/qdeclarativebinding_p.h>
+#include <QtDeclarative/private/qdeclarativeglobal_p.h>
+#include <QtDeclarative/private/qdeclarativeproperty_p.h>
+
+QT_BEGIN_NAMESPACE
+
+
+
+DEFINE_BOOL_CONFIG_OPTION(stateChangeDebug, STATECHANGE_DEBUG);
+
+class QDeclarative1TransitionManagerPrivate
+{
+public:
+ QDeclarative1TransitionManagerPrivate()
+ : state(0) {}
+
+ void applyBindings();
+ typedef QList<QDeclarative1SimpleAction> SimpleActionList;
+ QDeclarative1State *state;
+ QDeclarativeGuard<QDeclarative1Transition> transition;
+ QDeclarative1StateOperation::ActionList bindingsList;
+ SimpleActionList completeList;
+};
+
+QDeclarative1TransitionManager::QDeclarative1TransitionManager()
+: d(new QDeclarative1TransitionManagerPrivate)
+{
+}
+
+void QDeclarative1TransitionManager::setState(QDeclarative1State *s)
+{
+ d->state = s;
+}
+
+QDeclarative1TransitionManager::~QDeclarative1TransitionManager()
+{
+ delete d; d = 0;
+}
+
+void QDeclarative1TransitionManager::complete()
+{
+ d->applyBindings();
+
+ for (int ii = 0; ii < d->completeList.count(); ++ii) {
+ const QDeclarativeProperty &prop = d->completeList.at(ii).property();
+ prop.write(d->completeList.at(ii).value());
+ }
+
+ d->completeList.clear();
+
+ if (d->state)
+ static_cast<QDeclarative1StatePrivate*>(QObjectPrivate::get(d->state))->complete();
+}
+
+void QDeclarative1TransitionManagerPrivate::applyBindings()
+{
+ foreach(const QDeclarative1Action &action, bindingsList) {
+ if (!action.toBinding.isNull()) {
+ QDeclarativePropertyPrivate::setBinding(action.property, action.toBinding.data());
+ } else if (action.event) {
+ if (action.reverseEvent)
+ action.event->reverse();
+ else
+ action.event->execute();
+ }
+
+ }
+
+ bindingsList.clear();
+}
+
+void QDeclarative1TransitionManager::transition(const QList<QDeclarative1Action> &list,
+ QDeclarative1Transition *transition)
+{
+ cancel();
+
+ QDeclarative1StateOperation::ActionList applyList = list;
+ // Determine which actions are binding changes.
+ foreach(const QDeclarative1Action &action, applyList) {
+ if (action.toBinding)
+ d->bindingsList << action;
+ if (action.fromBinding)
+ QDeclarativePropertyPrivate::setBinding(action.property, 0); // Disable current binding
+ if (action.event && action.event->changesBindings()) { //### assume isReversable()?
+ d->bindingsList << action;
+ action.event->clearBindings();
+ }
+ }
+
+ // Animated transitions need both the start and the end value for
+ // each property change. In the presence of bindings, the end values
+ // are non-trivial to calculate. As a "best effort" attempt, we first
+ // apply all the property and binding changes, then read all the actual
+ // final values, then roll back the changes and proceed as normal.
+ //
+ // This doesn't catch everything, and it might be a little fragile in
+ // some cases - but whatcha going to do?
+
+ if (!d->bindingsList.isEmpty()) {
+
+ // Apply all the property and binding changes
+ for (int ii = 0; ii < applyList.size(); ++ii) {
+ const QDeclarative1Action &action = applyList.at(ii);
+ if (!action.toBinding.isNull()) {
+ QDeclarativePropertyPrivate::setBinding(action.property, action.toBinding.data(), QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::DontRemoveBinding);
+ } else if (!action.event) {
+ QDeclarativePropertyPrivate::write(action.property, action.toValue, QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::DontRemoveBinding);
+ } else if (action.event->isReversable()) {
+ if (action.reverseEvent)
+ action.event->reverse(QDeclarative1ActionEvent::FastForward);
+ else
+ action.event->execute(QDeclarative1ActionEvent::FastForward);
+ }
+ }
+
+ // Read all the end values for binding changes
+ for (int ii = 0; ii < applyList.size(); ++ii) {
+ QDeclarative1Action *action = &applyList[ii];
+ if (action->event) {
+ action->event->saveTargetValues();
+ continue;
+ }
+ const QDeclarativeProperty &prop = action->property;
+ if (!action->toBinding.isNull() || !action->toValue.isValid()) {
+ action->toValue = prop.read();
+ }
+ }
+
+ // Revert back to the original values
+ foreach(const QDeclarative1Action &action, applyList) {
+ if (action.event) {
+ if (action.event->isReversable()) {
+ action.event->clearBindings();
+ action.event->rewind();
+ action.event->clearBindings(); //### shouldn't be needed
+ }
+ continue;
+ }
+
+ if (action.toBinding)
+ QDeclarativePropertyPrivate::setBinding(action.property, 0); // Make sure this is disabled during the transition
+
+ QDeclarativePropertyPrivate::write(action.property, action.fromValue, QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::DontRemoveBinding);
+ }
+ }
+
+ if (transition) {
+ QList<QDeclarativeProperty> touched;
+ d->transition = transition;
+ d->transition->prepare(applyList, touched, this);
+
+ // Modify the action list to remove actions handled in the transition
+ for (int ii = 0; ii < applyList.count(); ++ii) {
+ const QDeclarative1Action &action = applyList.at(ii);
+
+ if (action.event) {
+
+ if (action.actionDone) {
+ applyList.removeAt(ii);
+ --ii;
+ }
+
+ } else {
+
+ if (touched.contains(action.property)) {
+ if (action.toValue != action.fromValue)
+ d->completeList <<
+ QDeclarative1SimpleAction(action, QDeclarative1SimpleAction::EndState);
+
+ applyList.removeAt(ii);
+ --ii;
+ }
+
+ }
+ }
+ }
+
+ // Any actions remaining have not been handled by the transition and should
+ // be applied immediately. We skip applying bindings, as they are all
+ // applied at the end in applyBindings() to avoid any nastiness mid
+ // transition
+ foreach(const QDeclarative1Action &action, applyList) {
+ if (action.event && !action.event->changesBindings()) {
+ if (action.event->isReversable() && action.reverseEvent)
+ action.event->reverse();
+ else
+ action.event->execute();
+ } else if (!action.event && !action.toBinding) {
+ action.property.write(action.toValue);
+ }
+ }
+#ifndef QT_NO_DEBUG_STREAM
+ if (stateChangeDebug()) {
+ foreach(const QDeclarative1Action &action, applyList) {
+ if (action.event)
+ qWarning() << " No transition for event:" << action.event->typeName();
+ else
+ qWarning() << " No transition for:" << action.property.object()
+ << action.property.name() << "From:" << action.fromValue
+ << "To:" << action.toValue;
+ }
+ }
+#endif
+ if (!transition)
+ d->applyBindings();
+}
+
+void QDeclarative1TransitionManager::cancel()
+{
+ if (d->transition) {
+ // ### this could potentially trigger a complete in rare circumstances
+ d->transition->stop();
+ d->transition = 0;
+ }
+
+ for(int i = 0; i < d->bindingsList.count(); ++i) {
+ QDeclarative1Action action = d->bindingsList[i];
+ if (!action.toBinding.isNull() && action.deletableToBinding) {
+ QDeclarativePropertyPrivate::setBinding(action.property, 0);
+ action.toBinding.data()->destroy();
+ action.toBinding.clear();
+ action.deletableToBinding = false;
+ } else if (action.event) {
+ //### what do we do here?
+ }
+
+ }
+ d->bindingsList.clear();
+ d->completeList.clear();
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/util/qdeclarativetransitionmanager_p_p.h b/src/qtquick1/util/qdeclarativetransitionmanager_p_p.h
new file mode 100644
index 0000000000..3f4100786f
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativetransitionmanager_p_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVETRANSITIONMANAGER_P_H
+#define QDECLARATIVETRANSITIONMANAGER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtQuick1/private/qdeclarativestateoperations_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarative1StatePrivate;
+class QDeclarative1TransitionManagerPrivate;
+class Q_AUTOTEST_EXPORT QDeclarative1TransitionManager
+{
+public:
+ QDeclarative1TransitionManager();
+ ~QDeclarative1TransitionManager();
+
+ void transition(const QList<QDeclarative1Action> &, QDeclarative1Transition *transition);
+
+ void cancel();
+
+private:
+ Q_DISABLE_COPY(QDeclarative1TransitionManager)
+ QDeclarative1TransitionManagerPrivate *d;
+
+ void complete();
+ void setState(QDeclarative1State *);
+
+ friend class QDeclarative1State;
+ friend class QDeclarative1TransitionPrivate;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDECLARATIVETRANSITIONMANAGER_P_H
diff --git a/src/qtquick1/util/qdeclarativeutilmodule.cpp b/src/qtquick1/util/qdeclarativeutilmodule.cpp
new file mode 100644
index 0000000000..65afa3655f
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativeutilmodule.cpp
@@ -0,0 +1,177 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativeutilmodule_p.h"
+#include "QtQuick1/private/qdeclarativeanimation_p.h"
+#include "QtQuick1/private/qdeclarativeanimation_p_p.h"
+#include "QtQuick1/private/qdeclarativebehavior_p.h"
+#include "QtQuick1/private/qdeclarativebind_p.h"
+#include "QtQuick1/private/qdeclarativeconnections_p.h"
+#include "QtQuick1/private/qdeclarativesmoothedanimation_p.h"
+#include "QtQuick1/private/qdeclarativefontloader_p.h"
+#include "QtQuick1/private/qdeclarativelistaccessor_p.h"
+//#include "QtQuick1/private/qdeclarativelistmodel_p.h"
+#include "QtQuick1/private/qdeclarativeopenmetaobject_p.h"
+#include "QtQuick1/private/qdeclarativepackage_p.h"
+#include "QtQuick1/private/qdeclarativepixmapcache_p.h"
+#include "QtQuick1/private/qdeclarativepropertychanges_p.h"
+#include "QtQuick1/private/qdeclarativespringanimation_p.h"
+#include "QtQuick1/private/qdeclarativestategroup_p.h"
+#include "QtQuick1/private/qdeclarativestateoperations_p.h"
+#include "QtQuick1/private/qdeclarativestate_p.h"
+#include "QtQuick1/private/qdeclarativestate_p_p.h"
+#include "QtQuick1/private/qdeclarativestyledtext_p.h"
+#include "QtQuick1/private/qdeclarativesystempalette_p.h"
+#include "QtQuick1/private/qdeclarativetimeline_p_p.h"
+#include "QtQuick1/private/qdeclarativetimer_p.h"
+#include "QtQuick1/private/qdeclarativetransitionmanager_p_p.h"
+#include "QtQuick1/private/qdeclarativetransition_p.h"
+#include "QtQuick1/private/qdeclarativeapplication_p.h"
+#include "QtQuick1/qdeclarativeview.h"
+#include <QtDeclarative/qdeclarativeinfo.h>
+#include <QtDeclarative/private/qdeclarativetypenotavailable_p.h>
+#ifndef QT_NO_XMLPATTERNS
+#include "QtQuick1/private/qdeclarativexmllistmodel_p.h"
+#endif
+
+
+void QDeclarative1UtilModule::defineModule(QDeclarativeQtQuick1Module::Module module)
+{
+ qmlRegisterType<QDeclarative1Anchors>();
+ qmlRegisterType<QDeclarative1StateOperation>();
+ qmlRegisterType<QDeclarative1AnchorSet>();
+
+ if (module == QDeclarativeQtQuick1Module::QtQuick1) {
+ qmlRegisterUncreatableType<QDeclarative1Application>("QtQuick",1,1,"Application", QDeclarative1Application::tr("Application is an abstract class"));
+
+ qmlRegisterType<QDeclarative1AnchorAnimation>("QtQuick",1,0,"AnchorAnimation");
+ qmlRegisterType<QDeclarative1AnchorChanges>("QtQuick",1,0,"AnchorChanges");
+ qmlRegisterType<QDeclarative1Behavior>("QtQuick",1,0,"Behavior");
+ qmlRegisterType<QDeclarative1Bind>("QtQuick",1,0,"Binding");
+ qmlRegisterType<QDeclarative1ColorAnimation>("QtQuick",1,0,"ColorAnimation");
+ qmlRegisterType<QDeclarative1Connections>("QtQuick",1,0,"Connections");
+ qmlRegisterType<QDeclarative1SmoothedAnimation>("QtQuick",1,0,"SmoothedAnimation");
+ qmlRegisterType<QDeclarative1FontLoader>("QtQuick",1,0,"FontLoader");
+ // qmlRegisterType<QDeclarative1ListElement>("QtQuick",1,0,"ListElement");
+ qmlRegisterType<QDeclarative1NumberAnimation>("QtQuick",1,0,"NumberAnimation");
+ qmlRegisterType<QDeclarative1Package>("QtQuick",1,0,"Package");
+ qmlRegisterType<QDeclarative1ParallelAnimation>("QtQuick",1,0,"ParallelAnimation");
+ qmlRegisterType<QDeclarative1ParentAnimation>("QtQuick",1,0,"ParentAnimation");
+ qmlRegisterType<QDeclarative1ParentChange>("QtQuick",1,0,"ParentChange");
+ qmlRegisterType<QDeclarative1PauseAnimation>("QtQuick",1,0,"PauseAnimation");
+ qmlRegisterType<QDeclarative1PropertyAction>("QtQuick",1,0,"PropertyAction");
+ qmlRegisterType<QDeclarative1PropertyAnimation>("QtQuick",1,0,"PropertyAnimation");
+ qmlRegisterType<QDeclarative1RotationAnimation>("QtQuick",1,0,"RotationAnimation");
+ qmlRegisterType<QDeclarative1ScriptAction>("QtQuick",1,0,"ScriptAction");
+ qmlRegisterType<QDeclarative1SequentialAnimation>("QtQuick",1,0,"SequentialAnimation");
+ qmlRegisterType<QDeclarative1SpringAnimation>("QtQuick",1,0,"SpringAnimation");
+ qmlRegisterType<QDeclarative1StateChangeScript>("QtQuick",1,0,"StateChangeScript");
+ qmlRegisterType<QDeclarative1StateGroup>("QtQuick",1,0,"StateGroup");
+ qmlRegisterType<QDeclarative1State>("QtQuick",1,0,"State");
+ qmlRegisterType<QDeclarative1SystemPalette>("QtQuick",1,0,"SystemPalette");
+ qmlRegisterType<QDeclarative1Timer>("QtQuick",1,0,"Timer");
+ qmlRegisterType<QDeclarative1Transition>("QtQuick",1,0,"Transition");
+ qmlRegisterType<QDeclarative1Vector3dAnimation>("QtQuick",1,0,"Vector3dAnimation");
+#ifdef QT_NO_XMLPATTERNS
+ qmlRegisterTypeNotAvailable("QtQuick",1,0,"XmlListModel",
+ qApp->translate("QDeclarative1XmlListModel","Qt was built without support for xmlpatterns"));
+ qmlRegisterTypeNotAvailable("QtQuick",1,0,"XmlRole",
+ qApp->translate("QDeclarative1XmlListModel","Qt was built without support for xmlpatterns"));
+#else
+ qmlRegisterType<QDeclarative1XmlListModel>("QtQuick",1,0,"XmlListModel");
+ qmlRegisterType<QDeclarative1XmlListModelRole>("QtQuick",1,0,"XmlRole");
+#endif
+
+
+ qmlRegisterUncreatableType<QDeclarative1AbstractAnimation>("QtQuick",1,0,"Animation",QDeclarative1AbstractAnimation::tr("Animation is an abstract class"));
+
+ // qmlRegisterCustomType<QDeclarative1ListModel>("QtQuick",1,0,"ListModel", new QDeclarative1ListModelParser);
+ qmlRegisterCustomType<QDeclarative1PropertyChanges>("QtQuick",1,0,"PropertyChanges", new QDeclarative1PropertyChangesParser);
+ qmlRegisterCustomType<QDeclarative1Connections>("QtQuick",1,0,"Connections", new QDeclarative1ConnectionsParser);
+ } else if (module == QDeclarativeQtQuick1Module::Qt47) {
+ qmlRegisterType<QDeclarative1AnchorAnimation>("Qt",4,7,"AnchorAnimation");
+ qmlRegisterType<QDeclarative1AnchorChanges>("Qt",4,7,"AnchorChanges");
+ qmlRegisterType<QDeclarative1Behavior>("Qt",4,7,"Behavior");
+ qmlRegisterType<QDeclarative1Bind>("Qt",4,7,"Binding");
+ qmlRegisterType<QDeclarative1ColorAnimation>("Qt",4,7,"ColorAnimation");
+ qmlRegisterType<QDeclarative1Connections>("Qt",4,7,"Connections");
+ qmlRegisterType<QDeclarative1SmoothedAnimation>("Qt",4,7,"SmoothedAnimation");
+ qmlRegisterType<QDeclarative1FontLoader>("Qt",4,7,"FontLoader");
+ // qmlRegisterType<QDeclarative1ListElement>("Qt",4,7,"ListElement");
+ qmlRegisterType<QDeclarative1NumberAnimation>("Qt",4,7,"NumberAnimation");
+ qmlRegisterType<QDeclarative1Package>("Qt",4,7,"Package");
+ qmlRegisterType<QDeclarative1ParallelAnimation>("Qt",4,7,"ParallelAnimation");
+ qmlRegisterType<QDeclarative1ParentAnimation>("Qt",4,7,"ParentAnimation");
+ qmlRegisterType<QDeclarative1ParentChange>("Qt",4,7,"ParentChange");
+ qmlRegisterType<QDeclarative1PauseAnimation>("Qt",4,7,"PauseAnimation");
+ qmlRegisterType<QDeclarative1PropertyAction>("Qt",4,7,"PropertyAction");
+ qmlRegisterType<QDeclarative1PropertyAnimation>("Qt",4,7,"PropertyAnimation");
+ qmlRegisterType<QDeclarative1RotationAnimation>("Qt",4,7,"RotationAnimation");
+ qmlRegisterType<QDeclarative1ScriptAction>("Qt",4,7,"ScriptAction");
+ qmlRegisterType<QDeclarative1SequentialAnimation>("Qt",4,7,"SequentialAnimation");
+ qmlRegisterType<QDeclarative1SpringAnimation>("Qt",4,7,"SpringAnimation");
+ qmlRegisterType<QDeclarative1StateChangeScript>("Qt",4,7,"StateChangeScript");
+ qmlRegisterType<QDeclarative1StateGroup>("Qt",4,7,"StateGroup");
+ qmlRegisterType<QDeclarative1State>("Qt",4,7,"State");
+ qmlRegisterType<QDeclarative1SystemPalette>("Qt",4,7,"SystemPalette");
+ qmlRegisterType<QDeclarative1Timer>("Qt",4,7,"Timer");
+ qmlRegisterType<QDeclarative1Transition>("Qt",4,7,"Transition");
+ qmlRegisterType<QDeclarative1Vector3dAnimation>("Qt",4,7,"Vector3dAnimation");
+#ifdef QT_NO_XMLPATTERNS
+ qmlRegisterTypeNotAvailable("Qt",4,7,"XmlListModel",
+ qApp->translate("QDeclarative1XmlListModel","Qt was built without support for xmlpatterns"));
+ qmlRegisterTypeNotAvailable("Qt",4,7,"XmlRole",
+ qApp->translate("QDeclarative1XmlListModel","Qt was built without support for xmlpatterns"));
+#else
+ qmlRegisterType<QDeclarative1XmlListModel>("Qt",4,7,"XmlListModel");
+ qmlRegisterType<QDeclarative1XmlListModelRole>("Qt",4,7,"XmlRole");
+#endif
+
+ qmlRegisterUncreatableType<QDeclarative1AbstractAnimation>("Qt",4,7,"Animation",QDeclarative1AbstractAnimation::tr("Animation is an abstract class"));
+
+ // qmlRegisterCustomType<QDeclarative1ListModel>("Qt", 4,7, "ListModel", new QDeclarative1ListModelParser);
+ qmlRegisterCustomType<QDeclarative1PropertyChanges>("Qt", 4, 7, "PropertyChanges", new QDeclarative1PropertyChangesParser);
+ qmlRegisterCustomType<QDeclarative1Connections>("Qt", 4, 7, "Connections", new QDeclarative1ConnectionsParser);
+ }
+}
+
+
+
diff --git a/src/qtquick1/util/qdeclarativeutilmodule_p.h b/src/qtquick1/util/qdeclarativeutilmodule_p.h
new file mode 100644
index 0000000000..b6561ccd3f
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativeutilmodule_p.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEUTILMODULE_H
+#define QDECLARATIVEUTILMODULE_H
+
+#include <QtDeclarative/qdeclarative.h>
+#include "../qtquick1_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarative1UtilModule
+{
+public:
+ static void defineModule(QDeclarativeQtQuick1Module::Module module);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEUTILMODULE_H
diff --git a/src/qtquick1/util/qdeclarativeview.cpp b/src/qtquick1/util/qdeclarativeview.cpp
new file mode 100644
index 0000000000..b6ba7a4fcb
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativeview.cpp
@@ -0,0 +1,737 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/qdeclarativeview.h"
+
+#include <QtDeclarative/qdeclarative.h>
+#include <QtQuick1/qdeclarativeitem.h>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativecontext.h>
+#include <QtDeclarative/private/qdeclarativeglobal_p.h>
+#include <QtDeclarative/private/qdeclarativeguard_p.h>
+
+#include <QtDeclarative/private/qdeclarativedebugtrace_p.h>
+#include <QtDeclarative/private/qdeclarativeinspectorservice_p.h>
+
+#include <qscriptvalueiterator.h>
+#include <qdebug.h>
+#include <qtimer.h>
+#include <qevent.h>
+#include <qdir.h>
+#include <qcoreapplication.h>
+#include <qfontdatabase.h>
+#include <qicon.h>
+#include <qurl.h>
+#include <qlayout.h>
+#include <qwidget.h>
+#include <qgraphicswidget.h>
+#include <qbasictimer.h>
+#include <QtCore/qabstractanimation.h>
+#include <private/qgraphicsview_p.h>
+#include <QtQuick1/private/qdeclarativeitem_p.h>
+#include <private/qabstractanimation_p.h>
+#include <QtQuick1/private/qdeclarativeitemchangelistener_p.h>
+
+QT_BEGIN_NAMESPACE
+
+DEFINE_BOOL_CONFIG_OPTION(frameRateDebug, QML_SHOW_FRAMERATE)
+
+class QDeclarative1Scene : public QGraphicsScene
+{
+public:
+ QDeclarative1Scene(QObject *parent = 0);
+
+protected:
+ virtual void keyPressEvent(QKeyEvent *);
+ virtual void keyReleaseEvent(QKeyEvent *);
+
+ virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *);
+ virtual void mousePressEvent(QGraphicsSceneMouseEvent *);
+ virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *);
+};
+
+QDeclarative1Scene::QDeclarative1Scene(QObject *parent) : QGraphicsScene(parent)
+{
+}
+
+void QDeclarative1Scene::keyPressEvent(QKeyEvent *e)
+{
+ QDeclarativeDebugTrace::addEvent(QDeclarativeDebugTrace::Key);
+
+ QGraphicsScene::keyPressEvent(e);
+}
+
+void QDeclarative1Scene::keyReleaseEvent(QKeyEvent *e)
+{
+ QDeclarativeDebugTrace::addEvent(QDeclarativeDebugTrace::Key);
+
+ QGraphicsScene::keyReleaseEvent(e);
+}
+
+void QDeclarative1Scene::mouseMoveEvent(QGraphicsSceneMouseEvent *e)
+{
+ QDeclarativeDebugTrace::addEvent(QDeclarativeDebugTrace::Mouse);
+
+ QGraphicsScene::mouseMoveEvent(e);
+}
+
+void QDeclarative1Scene::mousePressEvent(QGraphicsSceneMouseEvent *e)
+{
+ QDeclarativeDebugTrace::addEvent(QDeclarativeDebugTrace::Mouse);
+
+ QGraphicsScene::mousePressEvent(e);
+}
+
+void QDeclarative1Scene::mouseReleaseEvent(QGraphicsSceneMouseEvent *e)
+{
+ QDeclarativeDebugTrace::addEvent(QDeclarativeDebugTrace::Mouse);
+
+ QGraphicsScene::mouseReleaseEvent(e);
+}
+
+class QDeclarativeViewPrivate : public QGraphicsViewPrivate, public QDeclarativeItemChangeListener
+{
+ Q_DECLARE_PUBLIC(QDeclarativeView)
+public:
+ QDeclarativeViewPrivate()
+ : root(0), declarativeItemRoot(0), graphicsWidgetRoot(0), component(0),
+ resizeMode(QDeclarativeView::SizeViewToRootObject), initialSize(0,0) {}
+ ~QDeclarativeViewPrivate() { delete root; delete engine; }
+ void execute();
+ void itemGeometryChanged(QDeclarativeItem *item, const QRectF &newGeometry, const QRectF &oldGeometry);
+ void initResize();
+ void updateSize();
+ inline QSize rootObjectSize() const;
+
+ QDeclarativeGuard<QGraphicsObject> root;
+ QDeclarativeGuard<QDeclarativeItem> declarativeItemRoot;
+ QDeclarativeGuard<QGraphicsWidget> graphicsWidgetRoot;
+
+ QUrl source;
+
+ QDeclarativeEngine* engine;
+ QDeclarativeComponent *component;
+ QBasicTimer resizetimer;
+
+ QDeclarativeView::ResizeMode resizeMode;
+ QSize initialSize;
+ QElapsedTimer frameTimer;
+
+ void init();
+};
+
+void QDeclarativeViewPrivate::execute()
+{
+ Q_Q(QDeclarativeView);
+ if (root) {
+ delete root;
+ root = 0;
+ }
+ if (component) {
+ delete component;
+ component = 0;
+ }
+ if (!source.isEmpty()) {
+ component = new QDeclarativeComponent(engine, source, q);
+ if (!component->isLoading()) {
+ q->continueExecute();
+ } else {
+ QObject::connect(component, SIGNAL(statusChanged(QDeclarativeComponent::Status)), q, SLOT(continueExecute()));
+ }
+ }
+}
+
+void QDeclarativeViewPrivate::itemGeometryChanged(QDeclarativeItem *resizeItem, const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ Q_Q(QDeclarativeView);
+ if (resizeItem == root && resizeMode == QDeclarativeView::SizeViewToRootObject) {
+ // wait for both width and height to be changed
+ resizetimer.start(0,q);
+ }
+ QDeclarativeItemChangeListener::itemGeometryChanged(resizeItem, newGeometry, oldGeometry);
+}
+
+/*!
+ \class QDeclarativeView
+ \since 4.7
+ \brief The QDeclarativeView class provides a widget for displaying a Qt Declarative user interface.
+
+ QDeclarativeItem objects can be placed on a standard QGraphicsScene and
+ displayed with QGraphicsView. QDeclarativeView is a QGraphicsView subclass
+ provided as a convenience for displaying QML files, and connecting between
+ QML and C++ Qt objects.
+
+ QDeclarativeView provides:
+
+ \list
+ \o Management of QDeclarativeComponent loading and object creation
+ \o Initialization of QGraphicsView for optimal performance with QML using these settings:
+ \list
+ \o QGraphicsView::setOptimizationFlags(QGraphicsView::DontSavePainterState)
+ \o QGraphicsView::setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate)
+ \o QGraphicsScene::setItemIndexMethod(QGraphicsScene::NoIndex)
+ \endlist
+ \o Initialization of QGraphicsView for QML key handling using these settings:
+ \list
+ \o QGraphicsView::viewport()->setFocusPolicy(Qt::NoFocus)
+ \o QGraphicsView::setFocusPolicy(Qt::StrongFocus)
+ \o QGraphicsScene::setStickyFocus(true)
+ \endlist
+ \endlist
+
+ Typical usage:
+
+ \code
+ QDeclarativeView *view = new QDeclarativeView;
+ view->setSource(QUrl::fromLocalFile("myqmlfile.qml"));
+ view->show();
+ \endcode
+
+ Since QDeclarativeView is a QWidget-based class, it can be used to
+ display QML interfaces within QWidget-based GUI applications that do not
+ use the Graphics View framework.
+
+ To receive errors related to loading and executing QML with QDeclarativeView,
+ you can connect to the statusChanged() signal and monitor for QDeclarativeView::Error.
+ The errors are available via QDeclarativeView::errors().
+
+ If you're using your own QGraphicsScene-based scene with QDeclarativeView, remember to
+ enable scene's sticky focus mode and to set itemIndexMethod to QGraphicsScene::NoIndex.
+
+ \sa {Integrating QML Code with Existing Qt UI Code}, {Using QML Bindings in C++ Applications}
+*/
+
+
+/*! \fn void QDeclarativeView::sceneResized(QSize size)
+ This signal is emitted when the view is resized to \a size.
+*/
+
+/*! \fn void QDeclarativeView::statusChanged(QDeclarativeView::Status status)
+ This signal is emitted when the component's current \a status changes.
+*/
+
+/*!
+ \fn QDeclarativeView::QDeclarativeView(QWidget *parent)
+
+ Constructs a QDeclarativeView with the given \a parent.
+*/
+QDeclarativeView::QDeclarativeView(QWidget *parent)
+ : QGraphicsView(*(new QDeclarativeViewPrivate), parent)
+{
+ Q_D(QDeclarativeView);
+ setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Preferred);
+ d->init();
+}
+
+/*!
+ \fn QDeclarativeView::QDeclarativeView(const QUrl &source, QWidget *parent)
+
+ Constructs a QDeclarativeView with the given QML \a source and \a parent.
+*/
+QDeclarativeView::QDeclarativeView(const QUrl &source, QWidget *parent)
+ : QGraphicsView(*(new QDeclarativeViewPrivate), parent)
+{
+ Q_D(QDeclarativeView);
+ setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Preferred);
+ d->init();
+ setSource(source);
+}
+
+void QDeclarativeViewPrivate::init()
+{
+ Q_Q(QDeclarativeView);
+ engine = new QDeclarativeEngine();
+ q->setScene(new QDeclarative1Scene(q));
+
+ q->setOptimizationFlags(QGraphicsView::DontSavePainterState);
+ q->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ q->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ q->setFrameStyle(0);
+
+ // These seem to give the best performance
+ q->setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
+ q->scene()->setItemIndexMethod(QGraphicsScene::NoIndex);
+ q->viewport()->setFocusPolicy(Qt::NoFocus);
+ q->setFocusPolicy(Qt::StrongFocus);
+
+ q->scene()->setStickyFocus(true); //### needed for correct focus handling
+
+#ifdef QDECLARATIVEVIEW_NOBACKGROUND
+ q->setAttribute(Qt::WA_OpaquePaintEvent);
+ q->setAttribute(Qt::WA_NoSystemBackground);
+ q->viewport()->setAttribute(Qt::WA_OpaquePaintEvent);
+ q->viewport()->setAttribute(Qt::WA_NoSystemBackground);
+#endif
+
+ QDeclarativeInspectorService::instance()->addView(q);
+}
+
+/*!
+ Destroys the view.
+ */
+QDeclarativeView::~QDeclarativeView()
+{
+ QDeclarativeInspectorService::instance()->removeView(this);
+}
+
+/*! \property QDeclarativeView::source
+ \brief The URL of the source of the QML component.
+
+ Changing this property causes the QML component to be reloaded.
+
+ Ensure that the URL provided is full and correct, in particular, use
+ \l QUrl::fromLocalFile() when loading a file from the local filesystem.
+ */
+
+/*!
+ Sets the source to the \a url, loads the QML component and instantiates it.
+
+ Ensure that the URL provided is full and correct, in particular, use
+ \l QUrl::fromLocalFile() when loading a file from the local filesystem.
+
+ Calling this methods multiple times with the same url will result
+ in the QML being reloaded.
+ */
+void QDeclarativeView::setSource(const QUrl& url)
+{
+ Q_D(QDeclarativeView);
+ d->source = url;
+ d->execute();
+}
+
+/*!
+ Returns the source URL, if set.
+
+ \sa setSource()
+ */
+QUrl QDeclarativeView::source() const
+{
+ Q_D(const QDeclarativeView);
+ return d->source;
+}
+
+/*!
+ Returns a pointer to the QDeclarativeEngine used for instantiating
+ QML Components.
+ */
+QDeclarativeEngine* QDeclarativeView::engine() const
+{
+ Q_D(const QDeclarativeView);
+ return d->engine;
+}
+
+/*!
+ This function returns the root of the context hierarchy. Each QML
+ component is instantiated in a QDeclarativeContext. QDeclarativeContext's are
+ essential for passing data to QML components. In QML, contexts are
+ arranged hierarchically and this hierarchy is managed by the
+ QDeclarativeEngine.
+ */
+QDeclarativeContext* QDeclarativeView::rootContext() const
+{
+ Q_D(const QDeclarativeView);
+ return d->engine->rootContext();
+}
+
+/*!
+ \enum QDeclarativeView::Status
+ Specifies the loading status of the QDeclarativeView.
+
+ \value Null This QDeclarativeView has no source set.
+ \value Ready This QDeclarativeView has loaded and created the QML component.
+ \value Loading This QDeclarativeView is loading network data.
+ \value Error One or more errors has occurred. Call errors() to retrieve a list
+ of errors.
+*/
+
+/*! \enum QDeclarativeView::ResizeMode
+
+ This enum specifies how to resize the view.
+
+ \value SizeViewToRootObject The view resizes with the root item in the QML.
+ \value SizeRootObjectToView The view will automatically resize the root item to the size of the view.
+*/
+
+/*!
+ \property QDeclarativeView::status
+ The component's current \l{QDeclarativeView::Status} {status}.
+*/
+
+QDeclarativeView::Status QDeclarativeView::status() const
+{
+ Q_D(const QDeclarativeView);
+ if (!d->component)
+ return QDeclarativeView::Null;
+
+ return QDeclarativeView::Status(d->component->status());
+}
+
+/*!
+ Return the list of errors that occurred during the last compile or create
+ operation. When the status is not Error, an empty list is returned.
+*/
+QList<QDeclarativeError> QDeclarativeView::errors() const
+{
+ Q_D(const QDeclarativeView);
+ if (d->component)
+ return d->component->errors();
+ return QList<QDeclarativeError>();
+}
+
+/*!
+ \property QDeclarativeView::resizeMode
+ \brief whether the view should resize the canvas contents
+
+ If this property is set to SizeViewToRootObject (the default), the view
+ resizes with the root item in the QML.
+
+ If this property is set to SizeRootObjectToView, the view will
+ automatically resize the root item.
+
+ Regardless of this property, the sizeHint of the view
+ is the initial size of the root item. Note though that
+ since QML may load dynamically, that size may change.
+*/
+
+void QDeclarativeView::setResizeMode(ResizeMode mode)
+{
+ Q_D(QDeclarativeView);
+ if (d->resizeMode == mode)
+ return;
+
+ if (d->declarativeItemRoot) {
+ if (d->resizeMode == SizeViewToRootObject) {
+ QDeclarativeItemPrivate *p =
+ static_cast<QDeclarativeItemPrivate *>(QGraphicsItemPrivate::get(d->declarativeItemRoot));
+ p->removeItemChangeListener(d, QDeclarativeItemPrivate::Geometry);
+ }
+ } else if (d->graphicsWidgetRoot) {
+ if (d->resizeMode == QDeclarativeView::SizeViewToRootObject) {
+ d->graphicsWidgetRoot->removeEventFilter(this);
+ }
+ }
+
+ d->resizeMode = mode;
+ if (d->root) {
+ d->initResize();
+ }
+}
+
+void QDeclarativeViewPrivate::initResize()
+{
+ Q_Q(QDeclarativeView);
+ if (declarativeItemRoot) {
+ if (resizeMode == QDeclarativeView::SizeViewToRootObject) {
+ QDeclarativeItemPrivate *p =
+ static_cast<QDeclarativeItemPrivate *>(QGraphicsItemPrivate::get(declarativeItemRoot));
+ p->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
+ }
+ } else if (graphicsWidgetRoot) {
+ if (resizeMode == QDeclarativeView::SizeViewToRootObject) {
+ graphicsWidgetRoot->installEventFilter(q);
+ }
+ }
+ updateSize();
+}
+
+void QDeclarativeViewPrivate::updateSize()
+{
+ Q_Q(QDeclarativeView);
+ if (!root)
+ return;
+ if (declarativeItemRoot) {
+ if (resizeMode == QDeclarativeView::SizeViewToRootObject) {
+ QSize newSize = QSize(declarativeItemRoot->width(), declarativeItemRoot->height());
+ if (newSize.isValid() && newSize != q->size()) {
+ q->resize(newSize);
+ }
+ } else if (resizeMode == QDeclarativeView::SizeRootObjectToView) {
+ if (!qFuzzyCompare(q->width(), declarativeItemRoot->width()))
+ declarativeItemRoot->setWidth(q->width());
+ if (!qFuzzyCompare(q->height(), declarativeItemRoot->height()))
+ declarativeItemRoot->setHeight(q->height());
+ }
+ } else if (graphicsWidgetRoot) {
+ if (resizeMode == QDeclarativeView::SizeViewToRootObject) {
+ QSize newSize = QSize(graphicsWidgetRoot->size().width(), graphicsWidgetRoot->size().height());
+ if (newSize.isValid() && newSize != q->size()) {
+ q->resize(newSize);
+ }
+ } else if (resizeMode == QDeclarativeView::SizeRootObjectToView) {
+ QSizeF newSize = QSize(q->size().width(), q->size().height());
+ if (newSize.isValid() && newSize != graphicsWidgetRoot->size()) {
+ graphicsWidgetRoot->resize(newSize);
+ }
+ }
+ }
+ q->updateGeometry();
+}
+
+QSize QDeclarativeViewPrivate::rootObjectSize() const
+{
+ QSize rootObjectSize(0,0);
+ int widthCandidate = -1;
+ int heightCandidate = -1;
+ if (root) {
+ QSizeF size = root->boundingRect().size();
+ widthCandidate = size.width();
+ heightCandidate = size.height();
+ }
+ if (widthCandidate > 0) {
+ rootObjectSize.setWidth(widthCandidate);
+ }
+ if (heightCandidate > 0) {
+ rootObjectSize.setHeight(heightCandidate);
+ }
+ return rootObjectSize;
+}
+
+QDeclarativeView::ResizeMode QDeclarativeView::resizeMode() const
+{
+ Q_D(const QDeclarativeView);
+ return d->resizeMode;
+}
+
+/*!
+ \internal
+ */
+void QDeclarativeView::continueExecute()
+{
+ Q_D(QDeclarativeView);
+ disconnect(d->component, SIGNAL(statusChanged(QDeclarativeComponent::Status)), this, SLOT(continueExecute()));
+
+ if (d->component->isError()) {
+ QList<QDeclarativeError> errorList = d->component->errors();
+ foreach (const QDeclarativeError &error, errorList) {
+ qWarning() << error;
+ }
+ emit statusChanged(status());
+ return;
+ }
+
+ QObject *obj = d->component->create();
+
+ if(d->component->isError()) {
+ QList<QDeclarativeError> errorList = d->component->errors();
+ foreach (const QDeclarativeError &error, errorList) {
+ qWarning() << error;
+ }
+ emit statusChanged(status());
+ return;
+ }
+
+ setRootObject(obj);
+ emit statusChanged(status());
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeView::setRootObject(QObject *obj)
+{
+ Q_D(QDeclarativeView);
+ if (d->root == obj || !scene())
+ return;
+ if (QDeclarativeItem *declarativeItem = qobject_cast<QDeclarativeItem *>(obj)) {
+ scene()->addItem(declarativeItem);
+ d->root = declarativeItem;
+ d->declarativeItemRoot = declarativeItem;
+ } else if (QGraphicsObject *graphicsObject = qobject_cast<QGraphicsObject *>(obj)) {
+ scene()->addItem(graphicsObject);
+ d->root = graphicsObject;
+ if (graphicsObject->isWidget()) {
+ d->graphicsWidgetRoot = static_cast<QGraphicsWidget*>(graphicsObject);
+ } else {
+ qWarning() << "QDeclarativeView::resizeMode is not honored for components of type QGraphicsObject";
+ }
+ } else if (obj) {
+ qWarning() << "QDeclarativeView only supports loading of root objects that derive from QGraphicsObject";
+ if (QWidget* widget = qobject_cast<QWidget *>(obj)) {
+ window()->setAttribute(Qt::WA_OpaquePaintEvent, false);
+ window()->setAttribute(Qt::WA_NoSystemBackground, false);
+ if (layout() && layout()->count()) {
+ // Hide the QGraphicsView in GV mode.
+ QLayoutItem *item = layout()->itemAt(0);
+ if (item->widget())
+ item->widget()->hide();
+ }
+ widget->setParent(this);
+ if (isVisible()) {
+ widget->setVisible(true);
+ }
+ resize(widget->size());
+ }
+ }
+
+ if (d->root) {
+ d->initialSize = d->rootObjectSize();
+ if (d->initialSize != size()) {
+ if (!(parentWidget() && parentWidget()->layout())) {
+ resize(d->initialSize);
+ }
+ }
+ d->initResize();
+ }
+}
+
+/*!
+ \internal
+ If the \l {QTimerEvent} {timer event} \a e is this
+ view's resize timer, sceneResized() is emitted.
+ */
+void QDeclarativeView::timerEvent(QTimerEvent* e)
+{
+ Q_D(QDeclarativeView);
+ if (!e || e->timerId() == d->resizetimer.timerId()) {
+ d->updateSize();
+ d->resizetimer.stop();
+ }
+}
+
+/*! \internal */
+bool QDeclarativeView::eventFilter(QObject *watched, QEvent *e)
+{
+ Q_D(QDeclarativeView);
+ if (watched == d->root && d->resizeMode == SizeViewToRootObject) {
+ if (d->graphicsWidgetRoot) {
+ if (e->type() == QEvent::GraphicsSceneResize) {
+ d->updateSize();
+ }
+ }
+ }
+ return QGraphicsView::eventFilter(watched, e);
+}
+
+/*!
+ \internal
+ Preferred size follows the root object geometry.
+*/
+QSize QDeclarativeView::sizeHint() const
+{
+ Q_D(const QDeclarativeView);
+ QSize rootObjectSize = d->rootObjectSize();
+ if (rootObjectSize.isEmpty()) {
+ return size();
+ } else {
+ return rootObjectSize;
+ }
+}
+
+/*!
+ Returns the initial size of the root object
+*/
+QSize QDeclarativeView::initialSize() const
+{
+ Q_D(const QDeclarativeView);
+ return d->initialSize;
+}
+
+/*!
+ Returns the view's root \l {QGraphicsObject} {item}.
+ */
+QGraphicsObject *QDeclarativeView::rootObject() const
+{
+ Q_D(const QDeclarativeView);
+ return d->root;
+}
+
+/*!
+ \internal
+ This function handles the \l {QResizeEvent} {resize event}
+ \a e.
+ */
+void QDeclarativeView::resizeEvent(QResizeEvent *e)
+{
+ Q_D(QDeclarativeView);
+ if (d->resizeMode == SizeRootObjectToView) {
+ d->updateSize();
+ }
+ if (d->declarativeItemRoot) {
+ setSceneRect(QRectF(0, 0, d->declarativeItemRoot->width(), d->declarativeItemRoot->height()));
+ } else if (d->root) {
+ setSceneRect(d->root->boundingRect());
+ } else {
+ setSceneRect(rect());
+ }
+ emit sceneResized(e->size());
+ QGraphicsView::resizeEvent(e);
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeView::paintEvent(QPaintEvent *event)
+{
+ Q_D(QDeclarativeView);
+
+ QDeclarativeDebugTrace::addEvent(QDeclarativeDebugTrace::FramePaint);
+ QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Painting);
+
+ int time = 0;
+ if (frameRateDebug())
+ time = d->frameTimer.restart();
+
+ QGraphicsView::paintEvent(event);
+
+ QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Painting);
+
+ if (frameRateDebug())
+ qDebug() << "paintEvent:" << d->frameTimer.elapsed() << "time since last frame:" << time;
+
+#if QT_SHOW_DECLARATIVEVIEW_FPS
+ static QTime timer;
+ static int frames;
+
+ if (frames == 0) {
+ timer.start();
+ } else if (timer.elapsed() > 5000) {
+ qreal avgtime = timer.elapsed() / (qreal) frames;
+ qDebug("Average time per frame: %f ms (%i fps)", avgtime, int(1000 / avgtime));
+ timer.start();
+ frames = 0;
+ }
+ ++frames;
+ scene()->update();
+#endif
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/qtquick1/util/qdeclarativeview.h b/src/qtquick1/util/qdeclarativeview.h
new file mode 100644
index 0000000000..cfe1d458dc
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativeview.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEVIEW_H
+#define QDECLARATIVEVIEW_H
+
+#include <QtCore/qdatetime.h>
+#include <QtCore/qurl.h>
+#include <QtGui/qgraphicssceneevent.h>
+#include <QtGui/qgraphicsview.h>
+#include <QtGui/qwidget.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QGraphicsObject;
+class QDeclarativeEngine;
+class QDeclarativeContext;
+class QDeclarativeError;
+
+QT_MODULE(Declarative)
+
+class QDeclarativeViewPrivate;
+class Q_DECLARATIVE_EXPORT QDeclarativeView : public QGraphicsView
+{
+ Q_OBJECT
+ Q_PROPERTY(ResizeMode resizeMode READ resizeMode WRITE setResizeMode)
+ Q_PROPERTY(Status status READ status NOTIFY statusChanged)
+ Q_PROPERTY(QUrl source READ source WRITE setSource DESIGNABLE true)
+ Q_ENUMS(ResizeMode Status)
+public:
+ explicit QDeclarativeView(QWidget *parent = 0);
+ QDeclarativeView(const QUrl &source, QWidget *parent = 0);
+ virtual ~QDeclarativeView();
+
+ QUrl source() const;
+
+ QDeclarativeEngine* engine() const;
+ QDeclarativeContext* rootContext() const;
+
+ QGraphicsObject *rootObject() const;
+
+ enum ResizeMode { SizeViewToRootObject, SizeRootObjectToView };
+ ResizeMode resizeMode() const;
+ void setResizeMode(ResizeMode);
+
+ enum Status { Null, Ready, Loading, Error };
+ Status status() const;
+
+ QList<QDeclarativeError> errors() const;
+
+ QSize sizeHint() const;
+ QSize initialSize() const;
+
+public Q_SLOTS:
+ void setSource(const QUrl&);
+
+Q_SIGNALS:
+ void sceneResized(QSize size); // ???
+ void statusChanged(QDeclarativeView::Status);
+
+private Q_SLOTS:
+ void continueExecute();
+
+protected:
+ virtual void resizeEvent(QResizeEvent *);
+ virtual void paintEvent(QPaintEvent *event);
+ virtual void timerEvent(QTimerEvent*);
+ virtual void setRootObject(QObject *obj);
+ virtual bool eventFilter(QObject *watched, QEvent *e);
+
+private:
+ Q_DISABLE_COPY(QDeclarativeView)
+ Q_DECLARE_PRIVATE(QDeclarativeView)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEVIEW_H
diff --git a/src/qtquick1/util/qdeclarativexmllistmodel.cpp b/src/qtquick1/util/qdeclarativexmllistmodel.cpp
new file mode 100644
index 0000000000..1f89f95a34
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativexmllistmodel.cpp
@@ -0,0 +1,1058 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtQuick1/private/qdeclarativexmllistmodel_p.h"
+
+#include <QtDeclarative/qdeclarativecontext.h>
+#include <QtDeclarative/private/qdeclarativeengine_p.h>
+
+#include <QDebug>
+#include <QStringList>
+#include <QMap>
+#include <QApplication>
+#include <QThread>
+#include <QXmlQuery>
+#include <QXmlResultItems>
+#include <QXmlNodeModelIndex>
+#include <QBuffer>
+#include <QNetworkRequest>
+#include <QNetworkReply>
+#include <QTimer>
+#include <QMutex>
+
+#include <private/qobject_p.h>
+
+Q_DECLARE_METATYPE(QDeclarative1XmlQueryResult)
+
+QT_BEGIN_NAMESPACE
+
+
+
+
+typedef QPair<int, int> QDeclarative1XmlListRange;
+
+#define XMLLISTMODEL_CLEAR_ID 0
+
+/*!
+ \qmlclass XmlRole QDeclarative1XmlListModelRole
+ \ingroup qml-working-with-data
+ \since 4.7
+ \brief The XmlRole element allows you to specify a role for an XmlListModel.
+
+ \sa {QtDeclarative}
+*/
+
+/*!
+ \qmlproperty string XmlRole::name
+
+ The name for the role. This name is used to access the model data for this role.
+
+ For example, the following model has a role named "title", which can be accessed
+ from the view's delegate:
+
+ \qml
+ XmlListModel {
+ id: xmlModel
+ // ...
+ XmlRole {
+ name: "title"
+ query: "title/string()"
+ }
+ }
+ \endqml
+
+ \qml
+ ListView {
+ model: xmlModel
+ delegate: Text { text: title }
+ }
+ \endqml
+*/
+
+/*!
+ \qmlproperty string XmlRole::query
+ The relative XPath expression query for this role. The query must be relative; it cannot start
+ with a '/'.
+
+ For example, if there is an XML document like this:
+
+ \quotefile doc/src/snippets/declarative/xmlrole.xml
+
+ Here are some valid XPath expressions for XmlRole queries on this document:
+
+ \snippet doc/src/snippets/declarative/xmlrole.qml 0
+ \dots 4
+ \snippet doc/src/snippets/declarative/xmlrole.qml 1
+
+ See the \l{http://www.w3.org/TR/xpath20/}{W3C XPath 2.0 specification} for more information.
+*/
+
+/*!
+ \qmlproperty bool XmlRole::isKey
+ Defines whether this is a key role.
+
+ Key roles are used to to determine whether a set of values should
+ be updated or added to the XML list model when XmlListModel::reload()
+ is called.
+
+ \sa XmlListModel
+*/
+
+struct XmlQueryJob
+{
+ int queryId;
+ QByteArray data;
+ QString query;
+ QString namespaces;
+ QStringList roleQueries;
+ QList<void*> roleQueryErrorId; // the ptr to send back if there is an error
+ QStringList keyRoleQueries;
+ QStringList keyRoleResultsCache;
+ QString prefix;
+};
+
+class QDeclarative1XmlQuery : public QObject
+{
+ Q_OBJECT
+public:
+ QDeclarative1XmlQuery(QObject *parent=0)
+ : QObject(parent), m_queryIds(XMLLISTMODEL_CLEAR_ID + 1) {
+ qRegisterMetaType<QDeclarative1XmlQueryResult>("QDeclarative1XmlQueryResult");
+ moveToThread(&m_thread);
+ m_thread.start(QThread::IdlePriority);
+ }
+
+ ~QDeclarative1XmlQuery() {
+ if(m_thread.isRunning()) {
+ m_thread.quit();
+ m_thread.wait();
+ }
+ }
+
+ void abort(int id) {
+ QMutexLocker ml(&m_mutex);
+ if (id != -1) {
+ m_jobs.remove(id);
+ }
+ }
+
+ int doQuery(QString query, QString namespaces, QByteArray data, QList<QDeclarative1XmlListModelRole *>* roleObjects, QStringList keyRoleResultsCache) {
+ {
+ QMutexLocker m1(&m_mutex);
+ m_queryIds.ref();
+ if (m_queryIds <= 0)
+ m_queryIds = 1;
+ }
+
+ XmlQueryJob job;
+ job.queryId = m_queryIds;
+ job.data = data;
+ job.query = QLatin1String("doc($src)") + query;
+ job.namespaces = namespaces;
+ job.keyRoleResultsCache = keyRoleResultsCache;
+
+ for (int i=0; i<roleObjects->count(); i++) {
+ if (!roleObjects->at(i)->isValid()) {
+ job.roleQueries << QString();
+ continue;
+ }
+ job.roleQueries << roleObjects->at(i)->query();
+ job.roleQueryErrorId << static_cast<void*>(roleObjects->at(i));
+ if (roleObjects->at(i)->isKey())
+ job.keyRoleQueries << job.roleQueries.last();
+ }
+
+ {
+ QMutexLocker ml(&m_mutex);
+ m_jobs.insert(m_queryIds, job);
+ }
+
+ QMetaObject::invokeMethod(this, "processQuery", Qt::QueuedConnection, Q_ARG(int, job.queryId));
+ return job.queryId;
+ }
+
+private slots:
+ void processQuery(int queryId) {
+ XmlQueryJob job;
+
+ {
+ QMutexLocker ml(&m_mutex);
+ if (!m_jobs.contains(queryId))
+ return;
+ job = m_jobs.value(queryId);
+ }
+
+ QDeclarative1XmlQueryResult result;
+ result.queryId = job.queryId;
+ doQueryJob(&job, &result);
+ doSubQueryJob(&job, &result);
+
+ {
+ QMutexLocker ml(&m_mutex);
+ if (m_jobs.contains(queryId)) {
+ emit queryCompleted(result);
+ m_jobs.remove(queryId);
+ }
+ }
+ }
+
+Q_SIGNALS:
+ void queryCompleted(const QDeclarative1XmlQueryResult &);
+ void error(void*, const QString&);
+
+protected:
+
+
+private:
+ void doQueryJob(XmlQueryJob *job, QDeclarative1XmlQueryResult *currentResult);
+ void doSubQueryJob(XmlQueryJob *job, QDeclarative1XmlQueryResult *currentResult);
+ void getValuesOfKeyRoles(const XmlQueryJob& currentJob, QStringList *values, QXmlQuery *query) const;
+ void addIndexToRangeList(QList<QDeclarative1XmlListRange> *ranges, int index) const;
+
+private:
+ QMutex m_mutex;
+ QThread m_thread;
+ QMap<int, XmlQueryJob> m_jobs;
+ QAtomicInt m_queryIds;
+};
+
+Q_GLOBAL_STATIC(QDeclarative1XmlQuery, globalXmlQuery)
+
+void QDeclarative1XmlQuery::doQueryJob(XmlQueryJob *currentJob, QDeclarative1XmlQueryResult *currentResult)
+{
+ Q_ASSERT(currentJob->queryId != -1);
+
+ QString r;
+ QXmlQuery query;
+ QBuffer buffer(&currentJob->data);
+ buffer.open(QIODevice::ReadOnly);
+ query.bindVariable(QLatin1String("src"), &buffer);
+ query.setQuery(currentJob->namespaces + currentJob->query);
+ query.evaluateTo(&r);
+
+ //always need a single root element
+ QByteArray xml = "<dummy:items xmlns:dummy=\"http://qtsotware.com/dummy\">\n" + r.toUtf8() + "</dummy:items>";
+ QBuffer b(&xml);
+ b.open(QIODevice::ReadOnly);
+
+ QString namespaces = QLatin1String("declare namespace dummy=\"http://qtsotware.com/dummy\";\n") + currentJob->namespaces;
+ QString prefix = QLatin1String("doc($inputDocument)/dummy:items") +
+ currentJob->query.mid(currentJob->query.lastIndexOf(QLatin1Char('/')));
+
+ //figure out how many items we are dealing with
+ int count = -1;
+ {
+ QXmlResultItems result;
+ QXmlQuery countquery;
+ countquery.bindVariable(QLatin1String("inputDocument"), &b);
+ countquery.setQuery(namespaces + QLatin1String("count(") + prefix + QLatin1Char(')'));
+ countquery.evaluateTo(&result);
+ QXmlItem item(result.next());
+ if (item.isAtomicValue())
+ count = item.toAtomicValue().toInt();
+ }
+
+ currentJob->data = xml;
+ currentJob->prefix = namespaces + prefix + QLatin1Char('/');
+ currentResult->size = (count > 0 ? count : 0);
+}
+
+void QDeclarative1XmlQuery::getValuesOfKeyRoles(const XmlQueryJob& currentJob, QStringList *values, QXmlQuery *query) const
+{
+ const QStringList &keysQueries = currentJob.keyRoleQueries;
+ QString keysQuery;
+ if (keysQueries.count() == 1)
+ keysQuery = currentJob.prefix + keysQueries[0];
+ else if (keysQueries.count() > 1)
+ keysQuery = currentJob.prefix + QLatin1String("concat(") + keysQueries.join(QLatin1String(",")) + QLatin1String(")");
+
+ if (!keysQuery.isEmpty()) {
+ query->setQuery(keysQuery);
+ QXmlResultItems resultItems;
+ query->evaluateTo(&resultItems);
+ QXmlItem item(resultItems.next());
+ while (!item.isNull()) {
+ values->append(item.toAtomicValue().toString());
+ item = resultItems.next();
+ }
+ }
+}
+
+void QDeclarative1XmlQuery::addIndexToRangeList(QList<QDeclarative1XmlListRange> *ranges, int index) const {
+ if (ranges->isEmpty())
+ ranges->append(qMakePair(index, 1));
+ else if (ranges->last().first + ranges->last().second == index)
+ ranges->last().second += 1;
+ else
+ ranges->append(qMakePair(index, 1));
+}
+
+void QDeclarative1XmlQuery::doSubQueryJob(XmlQueryJob *currentJob, QDeclarative1XmlQueryResult *currentResult)
+{
+ Q_ASSERT(currentJob->queryId != -1);
+
+ QBuffer b(&currentJob->data);
+ b.open(QIODevice::ReadOnly);
+
+ QXmlQuery subquery;
+ subquery.bindVariable(QLatin1String("inputDocument"), &b);
+
+ QStringList keyRoleResults;
+ getValuesOfKeyRoles(*currentJob, &keyRoleResults, &subquery);
+
+ // See if any values of key roles have been inserted or removed.
+
+ if (currentJob->keyRoleResultsCache.isEmpty()) {
+ currentResult->inserted << qMakePair(0, currentResult->size);
+ } else {
+ if (keyRoleResults != currentJob->keyRoleResultsCache) {
+ QStringList temp;
+ for (int i=0; i<currentJob->keyRoleResultsCache.count(); i++) {
+ if (!keyRoleResults.contains(currentJob->keyRoleResultsCache[i]))
+ addIndexToRangeList(&currentResult->removed, i);
+ else
+ temp << currentJob->keyRoleResultsCache[i];
+ }
+
+ for (int i=0; i<keyRoleResults.count(); i++) {
+ if (temp.count() == i || keyRoleResults[i] != temp[i]) {
+ temp.insert(i, keyRoleResults[i]);
+ addIndexToRangeList(&currentResult->inserted, i);
+ }
+ }
+ }
+ }
+ currentResult->keyRoleResultsCache = keyRoleResults;
+
+ // Get the new values for each role.
+ //### we might be able to condense even further (query for everything in one go)
+ const QStringList &queries = currentJob->roleQueries;
+ for (int i = 0; i < queries.size(); ++i) {
+ QList<QVariant> resultList;
+ if (!queries[i].isEmpty()) {
+ subquery.setQuery(currentJob->prefix + QLatin1String("(let $v := string(") + queries[i] + QLatin1String(") return if ($v) then ") + queries[i] + QLatin1String(" else \"\")"));
+ if (subquery.isValid()) {
+ QXmlResultItems resultItems;
+ subquery.evaluateTo(&resultItems);
+ QXmlItem item(resultItems.next());
+ while (!item.isNull()) {
+ resultList << item.toAtomicValue(); //### we used to trim strings
+ item = resultItems.next();
+ }
+ } else {
+ emit error(currentJob->roleQueryErrorId.at(i), queries[i]);
+ }
+ }
+ //### should warn here if things have gone wrong.
+ while (resultList.count() < currentResult->size)
+ resultList << QVariant();
+ currentResult->data << resultList;
+ b.seek(0);
+ }
+
+ //this method is much slower, but works better for incremental loading
+ /*for (int j = 0; j < m_size; ++j) {
+ QList<QVariant> resultList;
+ for (int i = 0; i < m_roleObjects->size(); ++i) {
+ QDeclarative1XmlListModelRole *role = m_roleObjects->at(i);
+ subquery.setQuery(m_prefix.arg(j+1) + role->query());
+ if (role->isStringList()) {
+ QStringList data;
+ subquery.evaluateTo(&data);
+ resultList << QVariant(data);
+ //qDebug() << data;
+ } else {
+ QString s;
+ subquery.evaluateTo(&s);
+ if (role->isCData()) {
+ //un-escape
+ s.replace(QLatin1String("&lt;"), QLatin1String("<"));
+ s.replace(QLatin1String("&gt;"), QLatin1String(">"));
+ s.replace(QLatin1String("&amp;"), QLatin1String("&"));
+ }
+ resultList << s.trimmed();
+ //qDebug() << s;
+ }
+ b.seek(0);
+ }
+ m_modelData << resultList;
+ }*/
+}
+
+class QDeclarative1XmlListModelPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarative1XmlListModel)
+public:
+ QDeclarative1XmlListModelPrivate()
+ : isComponentComplete(true), size(-1), highestRole(Qt::UserRole)
+ , reply(0), status(QDeclarative1XmlListModel::Null), progress(0.0)
+ , queryId(-1), roleObjects(), redirectCount(0) {}
+
+
+ void notifyQueryStarted(bool remoteSource) {
+ Q_Q(QDeclarative1XmlListModel);
+ progress = remoteSource ? 0.0 : 1.0;
+ status = QDeclarative1XmlListModel::Loading;
+ errorString.clear();
+ emit q->progressChanged(progress);
+ emit q->statusChanged(status);
+ }
+
+ bool isComponentComplete;
+ QUrl src;
+ QString xml;
+ QString query;
+ QString namespaces;
+ int size;
+ QList<int> roles;
+ QStringList roleNames;
+ int highestRole;
+ QNetworkReply *reply;
+ QDeclarative1XmlListModel::Status status;
+ QString errorString;
+ qreal progress;
+ int queryId;
+ QStringList keyRoleResultsCache;
+ QList<QDeclarative1XmlListModelRole *> roleObjects;
+ static void append_role(QDeclarativeListProperty<QDeclarative1XmlListModelRole> *list, QDeclarative1XmlListModelRole *role);
+ static void clear_role(QDeclarativeListProperty<QDeclarative1XmlListModelRole> *list);
+ QList<QList<QVariant> > data;
+ int redirectCount;
+};
+
+
+void QDeclarative1XmlListModelPrivate::append_role(QDeclarativeListProperty<QDeclarative1XmlListModelRole> *list, QDeclarative1XmlListModelRole *role)
+{
+ QDeclarative1XmlListModel *_this = qobject_cast<QDeclarative1XmlListModel *>(list->object);
+ if (_this && role) {
+ int i = _this->d_func()->roleObjects.count();
+ _this->d_func()->roleObjects.append(role);
+ if (_this->d_func()->roleNames.contains(role->name())) {
+ qmlInfo(role) << QObject::tr("\"%1\" duplicates a previous role name and will be disabled.").arg(role->name());
+ return;
+ }
+ _this->d_func()->roles.insert(i, _this->d_func()->highestRole);
+ _this->d_func()->roleNames.insert(i, role->name());
+ ++_this->d_func()->highestRole;
+ }
+}
+
+//### clear needs to invalidate any cached data (in data table) as well
+// (and the model should emit the appropriate signals)
+void QDeclarative1XmlListModelPrivate::clear_role(QDeclarativeListProperty<QDeclarative1XmlListModelRole> *list)
+{
+ QDeclarative1XmlListModel *_this = static_cast<QDeclarative1XmlListModel *>(list->object);
+ _this->d_func()->roles.clear();
+ _this->d_func()->roleNames.clear();
+ _this->d_func()->roleObjects.clear();
+}
+
+/*!
+ \qmlclass XmlListModel QDeclarative1XmlListModel
+ \ingroup qml-working-with-data
+ \since 4.7
+ \brief The XmlListModel element is used to specify a read-only model using XPath expressions.
+
+ XmlListModel is used to create a read-only model from XML data. It can be used as a data source
+ for view elements (such as ListView, PathView, GridView) and other elements that interact with model
+ data (such as \l Repeater).
+
+ For example, if there is a XML document at http://www.mysite.com/feed.xml like this:
+
+ \code
+ <?xml version="1.0" encoding="utf-8"?>
+ <rss version="2.0">
+ ...
+ <channel>
+ <item>
+ <title>A blog post</title>
+ <pubDate>Sat, 07 Sep 2010 10:00:01 GMT</pubDate>
+ </item>
+ <item>
+ <title>Another blog post</title>
+ <pubDate>Sat, 07 Sep 2010 15:35:01 GMT</pubDate>
+ </item>
+ </channel>
+ </rss>
+ \endcode
+
+ A XmlListModel could create a model from this data, like this:
+
+ \qml
+ import QtQuick 1.0
+
+ XmlListModel {
+ id: xmlModel
+ source: "http://www.mysite.com/feed.xml"
+ query: "/rss/channel/item"
+
+ XmlRole { name: "title"; query: "title/string()" }
+ XmlRole { name: "pubDate"; query: "pubDate/string()" }
+ }
+ \endqml
+
+ The \l {XmlListModel::query}{query} value of "/rss/channel/item" specifies that the XmlListModel should generate
+ a model item for each \c <item> in the XML document.
+
+ The XmlRole objects define the
+ model item attributes. Here, each model item will have \c title and \c pubDate
+ attributes that match the \c title and \c pubDate values of its corresponding \c <item>.
+ (See \l XmlRole::query for more examples of valid XPath expressions for XmlRole.)
+
+ The model could be used in a ListView, like this:
+
+ \qml
+ ListView {
+ width: 180; height: 300
+ model: xmlModel
+ delegate: Text { text: title + ": " + pubDate }
+ }
+ \endqml
+
+ \image qml-xmllistmodel-example.png
+
+ The XmlListModel data is loaded asynchronously, and \l status
+ is set to \c XmlListModel.Ready when loading is complete.
+ Note this means when XmlListModel is used for a view, the view is not
+ populated until the model is loaded.
+
+
+ \section2 Using key XML roles
+
+ You can define certain roles as "keys" so that when reload() is called,
+ the model will only add and refresh data that contains new values for
+ these keys.
+
+ For example, if above role for "pubDate" was defined like this instead:
+
+ \qml
+ XmlRole { name: "pubDate"; query: "pubDate/string()"; isKey: true }
+ \endqml
+
+ Then when reload() is called, the model will only add and reload
+ items with a "pubDate" value that is not already
+ present in the model.
+
+ This is useful when displaying the contents of XML documents that
+ are incrementally updated (such as RSS feeds) to avoid repainting the
+ entire contents of a model in a view.
+
+ If multiple key roles are specified, the model only adds and reload items
+ with a combined value of all key roles that is not already present in
+ the model.
+
+ \sa {RSS News}
+*/
+
+QDeclarative1XmlListModel::QDeclarative1XmlListModel(QObject *parent)
+ : QListModelInterface(*(new QDeclarative1XmlListModelPrivate), parent)
+{
+ connect(globalXmlQuery(), SIGNAL(queryCompleted(QDeclarative1XmlQueryResult)),
+ this, SLOT(queryCompleted(QDeclarative1XmlQueryResult)));
+ connect(globalXmlQuery(), SIGNAL(error(void*,QString)),
+ this, SLOT(queryError(void*,QString)));
+}
+
+QDeclarative1XmlListModel::~QDeclarative1XmlListModel()
+{
+}
+
+/*!
+ \qmlproperty list<XmlRole> XmlListModel::roles
+
+ The roles to make available for this model.
+*/
+QDeclarativeListProperty<QDeclarative1XmlListModelRole> QDeclarative1XmlListModel::roleObjects()
+{
+ Q_D(QDeclarative1XmlListModel);
+ QDeclarativeListProperty<QDeclarative1XmlListModelRole> list(this, d->roleObjects);
+ list.append = &QDeclarative1XmlListModelPrivate::append_role;
+ list.clear = &QDeclarative1XmlListModelPrivate::clear_role;
+ return list;
+}
+
+QHash<int,QVariant> QDeclarative1XmlListModel::data(int index, const QList<int> &roles) const
+{
+ Q_D(const QDeclarative1XmlListModel);
+ QHash<int, QVariant> rv;
+ for (int i = 0; i < roles.size(); ++i) {
+ int role = roles.at(i);
+ int roleIndex = d->roles.indexOf(role);
+ rv.insert(role, roleIndex == -1 ? QVariant() : d->data.value(roleIndex).value(index));
+ }
+ return rv;
+}
+
+QVariant QDeclarative1XmlListModel::data(int index, int role) const
+{
+ Q_D(const QDeclarative1XmlListModel);
+ int roleIndex = d->roles.indexOf(role);
+ return (roleIndex == -1) ? QVariant() : d->data.value(roleIndex).value(index);
+}
+
+/*!
+ \qmlproperty int XmlListModel::count
+ The number of data entries in the model.
+*/
+int QDeclarative1XmlListModel::count() const
+{
+ Q_D(const QDeclarative1XmlListModel);
+ return d->size;
+}
+
+QList<int> QDeclarative1XmlListModel::roles() const
+{
+ Q_D(const QDeclarative1XmlListModel);
+ return d->roles;
+}
+
+QString QDeclarative1XmlListModel::toString(int role) const
+{
+ Q_D(const QDeclarative1XmlListModel);
+ int index = d->roles.indexOf(role);
+ if (index == -1)
+ return QString();
+ return d->roleNames.at(index);
+}
+
+/*!
+ \qmlproperty url XmlListModel::source
+ The location of the XML data source.
+
+ If both \c source and \l xml are set, \l xml is used.
+*/
+QUrl QDeclarative1XmlListModel::source() const
+{
+ Q_D(const QDeclarative1XmlListModel);
+ return d->src;
+}
+
+void QDeclarative1XmlListModel::setSource(const QUrl &src)
+{
+ Q_D(QDeclarative1XmlListModel);
+ if (d->src != src) {
+ d->src = src;
+ if (d->xml.isEmpty()) // src is only used if d->xml is not set
+ reload();
+ emit sourceChanged();
+ }
+}
+
+/*!
+ \qmlproperty string XmlListModel::xml
+ This property holds the XML data for this model, if set.
+
+ The text is assumed to be UTF-8 encoded.
+
+ If both \l source and \c xml are set, \c xml is used.
+*/
+QString QDeclarative1XmlListModel::xml() const
+{
+ Q_D(const QDeclarative1XmlListModel);
+ return d->xml;
+}
+
+void QDeclarative1XmlListModel::setXml(const QString &xml)
+{
+ Q_D(QDeclarative1XmlListModel);
+ if (d->xml != xml) {
+ d->xml = xml;
+ reload();
+ emit xmlChanged();
+ }
+}
+
+/*!
+ \qmlproperty string XmlListModel::query
+ An absolute XPath query representing the base query for creating model items
+ from this model's XmlRole objects. The query should start with '/' or '//'.
+*/
+QString QDeclarative1XmlListModel::query() const
+{
+ Q_D(const QDeclarative1XmlListModel);
+ return d->query;
+}
+
+void QDeclarative1XmlListModel::setQuery(const QString &query)
+{
+ Q_D(QDeclarative1XmlListModel);
+ if (!query.startsWith(QLatin1Char('/'))) {
+ qmlInfo(this) << QCoreApplication::translate("QDeclarative1XmlRoleList", "An XmlListModel query must start with '/' or \"//\"");
+ return;
+ }
+
+ if (d->query != query) {
+ d->query = query;
+ reload();
+ emit queryChanged();
+ }
+}
+
+/*!
+ \qmlproperty string XmlListModel::namespaceDeclarations
+ The namespace declarations to be used in the XPath queries.
+
+ The namespaces should be declared as in XQuery. For example, if a requested document
+ at http://mysite.com/feed.xml uses the namespace "http://www.w3.org/2005/Atom",
+ this can be declared as the default namespace:
+
+ \qml
+ XmlListModel {
+ source: "http://mysite.com/feed.xml"
+ query: "/feed/entry"
+ namespaceDeclarations: "declare default element namespace 'http://www.w3.org/2005/Atom';"
+
+ XmlRole { name: "title"; query: "title/string()" }
+ }
+ \endqml
+*/
+QString QDeclarative1XmlListModel::namespaceDeclarations() const
+{
+ Q_D(const QDeclarative1XmlListModel);
+ return d->namespaces;
+}
+
+void QDeclarative1XmlListModel::setNamespaceDeclarations(const QString &declarations)
+{
+ Q_D(QDeclarative1XmlListModel);
+ if (d->namespaces != declarations) {
+ d->namespaces = declarations;
+ reload();
+ emit namespaceDeclarationsChanged();
+ }
+}
+
+/*!
+ \qmlmethod object XmlListModel::get(int index)
+
+ Returns the item at \a index in the model.
+
+ For example, for a model like this:
+
+ \qml
+ XmlListModel {
+ id: model
+ source: "http://mysite.com/feed.xml"
+ query: "/feed/entry"
+ XmlRole { name: "title"; query: "title/string()" }
+ }
+ \endqml
+
+ This will access the \c title value for the first item in the model:
+
+ \js
+ var title = model.get(0).title;
+ \endjs
+*/
+QDeclarativeV8Handle QDeclarative1XmlListModel::get(int index) const
+{
+ // Must be called with a context and handle scope
+ Q_D(const QDeclarative1XmlListModel);
+
+ if (index < 0 || index >= count())
+ return QDeclarativeV8Handle::fromHandle(v8::Undefined());
+
+ QDeclarativeEngine *engine = qmlContext(this)->engine();
+ QV8Engine *v8engine = QDeclarativeEnginePrivate::getV8Engine(engine);
+ v8::Local<v8::Object> rv = v8::Object::New();
+ for (int ii = 0; ii < d->roleObjects.count(); ++ii)
+ rv->Set(v8engine->toString(d->roleObjects[ii]->name()),
+ v8engine->fromVariant(d->data.value(ii).value(index)));
+
+ return QDeclarativeV8Handle::fromHandle(rv);
+}
+
+/*!
+ \qmlproperty enumeration XmlListModel::status
+ Specifies the model loading status, which can be one of the following:
+
+ \list
+ \o XmlListModel.Null - No XML data has been set for this model.
+ \o XmlListModel.Ready - The XML data has been loaded into the model.
+ \o XmlListModel.Loading - The model is in the process of reading and loading XML data.
+ \o XmlListModel.Error - An error occurred while the model was loading. See errorString() for details
+ about the error.
+ \endlist
+
+ \sa progress
+
+*/
+QDeclarative1XmlListModel::Status QDeclarative1XmlListModel::status() const
+{
+ Q_D(const QDeclarative1XmlListModel);
+ return d->status;
+}
+
+/*!
+ \qmlproperty real XmlListModel::progress
+
+ This indicates the current progress of the downloading of the XML data
+ source. This value ranges from 0.0 (no data downloaded) to
+ 1.0 (all data downloaded). If the XML data is not from a remote source,
+ the progress becomes 1.0 as soon as the data is read.
+
+ Note that when the progress is 1.0, the XML data has been downloaded, but
+ it is yet to be loaded into the model at this point. Use the status
+ property to find out when the XML data has been read and loaded into
+ the model.
+
+ \sa status, source
+*/
+qreal QDeclarative1XmlListModel::progress() const
+{
+ Q_D(const QDeclarative1XmlListModel);
+ return d->progress;
+}
+
+/*!
+ \qmlmethod void XmlListModel::errorString()
+
+ Returns a string description of the last error that occurred
+ if \l status is XmlListModel::Error.
+*/
+QString QDeclarative1XmlListModel::errorString() const
+{
+ Q_D(const QDeclarative1XmlListModel);
+ return d->errorString;
+}
+
+void QDeclarative1XmlListModel::classBegin()
+{
+ Q_D(QDeclarative1XmlListModel);
+ d->isComponentComplete = false;
+}
+
+void QDeclarative1XmlListModel::componentComplete()
+{
+ Q_D(QDeclarative1XmlListModel);
+ d->isComponentComplete = true;
+ reload();
+}
+
+/*!
+ \qmlmethod XmlListModel::reload()
+
+ Reloads the model.
+
+ If no key roles have been specified, all existing model
+ data is removed, and the model is rebuilt from scratch.
+
+ Otherwise, items are only added if the model does not already
+ contain items with matching key role values.
+
+ \sa {Using key XML roles}, XmlRole::isKey
+*/
+void QDeclarative1XmlListModel::reload()
+{
+ Q_D(QDeclarative1XmlListModel);
+
+ if (!d->isComponentComplete)
+ return;
+
+ globalXmlQuery()->abort(d->queryId);
+ d->queryId = -1;
+
+ if (d->size < 0)
+ d->size = 0;
+
+ if (d->reply) {
+ d->reply->abort();
+ if (d->reply) {
+ // abort will generally have already done this (and more)
+ d->reply->deleteLater();
+ d->reply = 0;
+ }
+ }
+
+ if (!d->xml.isEmpty()) {
+ d->queryId = globalXmlQuery()->doQuery(d->query, d->namespaces, d->xml.toUtf8(), &d->roleObjects, d->keyRoleResultsCache);
+ d->notifyQueryStarted(false);
+
+ } else if (d->src.isEmpty()) {
+ d->queryId = XMLLISTMODEL_CLEAR_ID;
+ d->notifyQueryStarted(false);
+ QTimer::singleShot(0, this, SLOT(dataCleared()));
+
+ } else {
+ d->notifyQueryStarted(true);
+ QNetworkRequest req(d->src);
+ req.setRawHeader("Accept", "application/xml,*/*");
+ d->reply = qmlContext(this)->engine()->networkAccessManager()->get(req);
+ QObject::connect(d->reply, SIGNAL(finished()), this, SLOT(requestFinished()));
+ QObject::connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)),
+ this, SLOT(requestProgress(qint64,qint64)));
+ }
+}
+
+#define XMLLISTMODEL_MAX_REDIRECT 16
+
+void QDeclarative1XmlListModel::requestFinished()
+{
+ Q_D(QDeclarative1XmlListModel);
+
+ d->redirectCount++;
+ if (d->redirectCount < XMLLISTMODEL_MAX_REDIRECT) {
+ QVariant redirect = d->reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
+ if (redirect.isValid()) {
+ QUrl url = d->reply->url().resolved(redirect.toUrl());
+ d->reply->deleteLater();
+ d->reply = 0;
+ setSource(url);
+ return;
+ }
+ }
+ d->redirectCount = 0;
+
+ if (d->reply->error() != QNetworkReply::NoError) {
+ d->errorString = d->reply->errorString();
+ disconnect(d->reply, 0, this, 0);
+ d->reply->deleteLater();
+ d->reply = 0;
+
+ int count = this->count();
+ d->data.clear();
+ d->size = 0;
+ if (count > 0) {
+ emit itemsRemoved(0, count);
+ emit countChanged();
+ }
+
+ d->status = Error;
+ d->queryId = -1;
+ emit statusChanged(d->status);
+ } else {
+ QByteArray data = d->reply->readAll();
+ if (data.isEmpty()) {
+ d->queryId = XMLLISTMODEL_CLEAR_ID;
+ QTimer::singleShot(0, this, SLOT(dataCleared()));
+ } else {
+ d->queryId = globalXmlQuery()->doQuery(d->query, d->namespaces, data, &d->roleObjects, d->keyRoleResultsCache);
+ }
+ disconnect(d->reply, 0, this, 0);
+ d->reply->deleteLater();
+ d->reply = 0;
+
+ d->progress = 1.0;
+ emit progressChanged(d->progress);
+ }
+}
+
+void QDeclarative1XmlListModel::requestProgress(qint64 received, qint64 total)
+{
+ Q_D(QDeclarative1XmlListModel);
+ if (d->status == Loading && total > 0) {
+ d->progress = qreal(received)/total;
+ emit progressChanged(d->progress);
+ }
+}
+
+void QDeclarative1XmlListModel::dataCleared()
+{
+ Q_D(QDeclarative1XmlListModel);
+ QDeclarative1XmlQueryResult r;
+ r.queryId = XMLLISTMODEL_CLEAR_ID;
+ r.size = 0;
+ r.removed << qMakePair(0, count());
+ r.keyRoleResultsCache = d->keyRoleResultsCache;
+ queryCompleted(r);
+}
+
+void QDeclarative1XmlListModel::queryError(void* object, const QString& error)
+{
+ // Be extra careful, object may no longer exist, it's just an ID.
+ Q_D(QDeclarative1XmlListModel);
+ for (int i=0; i<d->roleObjects.count(); i++) {
+ if (d->roleObjects.at(i) == static_cast<QDeclarative1XmlListModelRole*>(object)) {
+ qmlInfo(d->roleObjects.at(i)) << QObject::tr("invalid query: \"%1\"").arg(error);
+ return;
+ }
+ }
+ qmlInfo(this) << QObject::tr("invalid query: \"%1\"").arg(error);
+}
+
+void QDeclarative1XmlListModel::queryCompleted(const QDeclarative1XmlQueryResult &result)
+{
+ Q_D(QDeclarative1XmlListModel);
+ if (result.queryId != d->queryId)
+ return;
+
+ int origCount = d->size;
+ bool sizeChanged = result.size != d->size;
+
+ d->size = result.size;
+ d->data = result.data;
+ d->keyRoleResultsCache = result.keyRoleResultsCache;
+ d->status = Ready;
+ d->errorString.clear();
+ d->queryId = -1;
+
+ bool hasKeys = false;
+ for (int i=0; i<d->roleObjects.count(); i++) {
+ if (d->roleObjects[i]->isKey()) {
+ hasKeys = true;
+ break;
+ }
+ }
+ if (!hasKeys) {
+ if (!(origCount == 0 && d->size == 0)) {
+ emit itemsRemoved(0, origCount);
+ emit itemsInserted(0, d->size);
+ emit countChanged();
+ }
+
+ } else {
+ for (int i=0; i<result.removed.count(); i++)
+ emit itemsRemoved(result.removed[i].first, result.removed[i].second);
+ for (int i=0; i<result.inserted.count(); i++)
+ emit itemsInserted(result.inserted[i].first, result.inserted[i].second);
+
+ if (sizeChanged)
+ emit countChanged();
+ }
+
+ emit statusChanged(d->status);
+}
+
+
+
+QT_END_NAMESPACE
+
+#include <qdeclarativexmllistmodel.moc>
diff --git a/src/qtquick1/util/qdeclarativexmllistmodel_p.h b/src/qtquick1/util/qdeclarativexmllistmodel_p.h
new file mode 100644
index 0000000000..7b2ddbf268
--- /dev/null
+++ b/src/qtquick1/util/qdeclarativexmllistmodel_p.h
@@ -0,0 +1,213 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEXMLLISTMODEL_H
+#define QDECLARATIVEXMLLISTMODEL_H
+
+#include <QtDeclarative/qdeclarative.h>
+#include <QtDeclarative/qdeclarativeinfo.h>
+
+#include <QtCore/qurl.h>
+#include <QtCore/qstringlist.h>
+
+#include <QtDeclarative/private/qlistmodelinterface_p.h>
+#include <private/qv8engine_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeContext;
+class QDeclarative1XmlListModelRole;
+class QDeclarative1XmlListModelPrivate;
+
+struct QDeclarative1XmlQueryResult {
+ int queryId;
+ int size;
+ QList<QList<QVariant> > data;
+ QList<QPair<int, int> > inserted;
+ QList<QPair<int, int> > removed;
+ QStringList keyRoleResultsCache;
+};
+
+class Q_AUTOTEST_EXPORT QDeclarative1XmlListModel : public QListModelInterface, public QDeclarativeParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QDeclarativeParserStatus)
+ Q_ENUMS(Status)
+
+ Q_PROPERTY(Status status READ status NOTIFY statusChanged)
+ Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged)
+ Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
+ Q_PROPERTY(QString xml READ xml WRITE setXml NOTIFY xmlChanged)
+ Q_PROPERTY(QString query READ query WRITE setQuery NOTIFY queryChanged)
+ Q_PROPERTY(QString namespaceDeclarations READ namespaceDeclarations WRITE setNamespaceDeclarations NOTIFY namespaceDeclarationsChanged)
+ Q_PROPERTY(QDeclarativeListProperty<QDeclarative1XmlListModelRole> roles READ roleObjects)
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+ Q_CLASSINFO("DefaultProperty", "roles")
+
+public:
+ QDeclarative1XmlListModel(QObject *parent = 0);
+ ~QDeclarative1XmlListModel();
+
+ virtual QHash<int,QVariant> data(int index, const QList<int> &roles = (QList<int>())) const;
+ virtual QVariant data(int index, int role) const;
+ virtual int count() const;
+ virtual QList<int> roles() const;
+ virtual QString toString(int role) const;
+
+ QDeclarativeListProperty<QDeclarative1XmlListModelRole> roleObjects();
+
+ QUrl source() const;
+ void setSource(const QUrl&);
+
+ QString xml() const;
+ void setXml(const QString&);
+
+ QString query() const;
+ void setQuery(const QString&);
+
+ QString namespaceDeclarations() const;
+ void setNamespaceDeclarations(const QString&);
+
+ Q_INVOKABLE QDeclarativeV8Handle get(int index) const;
+
+ enum Status { Null, Ready, Loading, Error };
+ Status status() const;
+ qreal progress() const;
+
+ Q_INVOKABLE QString errorString() const;
+
+ virtual void classBegin();
+ virtual void componentComplete();
+
+Q_SIGNALS:
+ void statusChanged(QDeclarative1XmlListModel::Status);
+ void progressChanged(qreal progress);
+ void countChanged();
+ void sourceChanged();
+ void xmlChanged();
+ void queryChanged();
+ void namespaceDeclarationsChanged();
+
+public Q_SLOTS:
+ // ### need to use/expose Expiry to guess when to call this?
+ // ### property to auto-call this on reasonable Expiry?
+ // ### LastModified/Age also useful to guess.
+ // ### Probably also applies to other network-requesting types.
+ void reload();
+
+private Q_SLOTS:
+ void requestFinished();
+ void requestProgress(qint64,qint64);
+ void dataCleared();
+ void queryCompleted(const QDeclarative1XmlQueryResult &);
+ void queryError(void* object, const QString& error);
+
+private:
+ Q_DECLARE_PRIVATE(QDeclarative1XmlListModel)
+ Q_DISABLE_COPY(QDeclarative1XmlListModel)
+};
+
+class Q_AUTOTEST_EXPORT QDeclarative1XmlListModelRole : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
+ Q_PROPERTY(QString query READ query WRITE setQuery NOTIFY queryChanged)
+ Q_PROPERTY(bool isKey READ isKey WRITE setIsKey NOTIFY isKeyChanged)
+public:
+ QDeclarative1XmlListModelRole() : m_isKey(false) {}
+ ~QDeclarative1XmlListModelRole() {}
+
+ QString name() const { return m_name; }
+ void setName(const QString &name) {
+ if (name == m_name)
+ return;
+ m_name = name;
+ emit nameChanged();
+ }
+
+ QString query() const { return m_query; }
+ void setQuery(const QString &query)
+ {
+ if (query.startsWith(QLatin1Char('/'))) {
+ qmlInfo(this) << tr("An XmlRole query must not start with '/'");
+ return;
+ }
+ if (m_query == query)
+ return;
+ m_query = query;
+ emit queryChanged();
+ }
+
+ bool isKey() const { return m_isKey; }
+ void setIsKey(bool b) {
+ if (m_isKey == b)
+ return;
+ m_isKey = b;
+ emit isKeyChanged();
+ }
+
+ bool isValid() {
+ return !m_name.isEmpty() && !m_query.isEmpty();
+ }
+
+Q_SIGNALS:
+ void nameChanged();
+ void queryChanged();
+ void isKeyChanged();
+
+private:
+ QString m_name;
+ QString m_query;
+ bool m_isKey;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarative1XmlListModel)
+QML_DECLARE_TYPE(QDeclarative1XmlListModelRole)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEXMLLISTMODEL_H
diff --git a/src/qtquick1/util/util.pri b/src/qtquick1/util/util.pri
new file mode 100644
index 0000000000..c5e68b78e3
--- /dev/null
+++ b/src/qtquick1/util/util.pri
@@ -0,0 +1,69 @@
+INCLUDEPATH += $$PWD
+
+SOURCES += \
+ $$PWD/qdeclarativeapplication.cpp \
+ $$PWD/qdeclarativeview.cpp \
+ $$PWD/qdeclarativeconnections.cpp \
+ $$PWD/qdeclarativepackage.cpp \
+ $$PWD/qdeclarativeanimation.cpp \
+ $$PWD/qdeclarativesystempalette.cpp \
+ $$PWD/qdeclarativespringanimation.cpp \
+ $$PWD/qdeclarativesmoothedanimation.cpp \
+ $$PWD/qdeclarativestate.cpp\
+ $$PWD/qdeclarativetransitionmanager.cpp \
+ $$PWD/qdeclarativestateoperations.cpp \
+ $$PWD/qdeclarativepropertychanges.cpp \
+ $$PWD/qdeclarativestategroup.cpp \
+ $$PWD/qdeclarativetransition.cpp \
+# $$PWD/qdeclarativelistmodel.cpp\
+# $$PWD/qdeclarativelistmodelworkeragent.cpp \
+ $$PWD/qdeclarativelistaccessor.cpp \
+ $$PWD/qdeclarativeopenmetaobject.cpp \
+ $$PWD/qdeclarativetimeline.cpp \
+ $$PWD/qdeclarativetimer.cpp \
+ $$PWD/qdeclarativebind.cpp \
+ $$PWD/qdeclarativepixmapcache.cpp \
+ $$PWD/qdeclarativebehavior.cpp \
+ $$PWD/qdeclarativefontloader.cpp \
+ $$PWD/qdeclarativestyledtext.cpp \
+ $$PWD/qdeclarativeutilmodule.cpp\
+
+HEADERS += \
+ $$PWD/qdeclarativeapplication_p.h \
+ $$PWD/qdeclarativeutilmodule_p.h\
+ $$PWD/qdeclarativeview.h \
+ $$PWD/qdeclarativeconnections_p.h \
+ $$PWD/qdeclarativepackage_p.h \
+ $$PWD/qdeclarativeanimation_p.h \
+ $$PWD/qdeclarativeanimation_p_p.h \
+ $$PWD/qdeclarativesystempalette_p.h \
+ $$PWD/qdeclarativespringanimation_p.h \
+ $$PWD/qdeclarativesmoothedanimation_p.h \
+ $$PWD/qdeclarativesmoothedanimation_p_p.h \
+ $$PWD/qdeclarativestate_p.h\
+ $$PWD/qdeclarativestateoperations_p.h \
+ $$PWD/qdeclarativepropertychanges_p.h \
+ $$PWD/qdeclarativestate_p_p.h\
+ $$PWD/qdeclarativetransitionmanager_p_p.h \
+ $$PWD/qdeclarativestategroup_p.h \
+ $$PWD/qdeclarativetransition_p.h \
+# $$PWD/qdeclarativelistmodel_p.h\
+# $$PWD/qdeclarativelistmodel_p_p.h\
+# $$PWD/qdeclarativelistmodelworkeragent_p.h \
+ $$PWD/qdeclarativelistaccessor_p.h \
+ $$PWD/qdeclarativeopenmetaobject_p.h \
+ $$PWD/qdeclarativetimeline_p_p.h \
+ $$PWD/qdeclarativetimer_p.h \
+ $$PWD/qdeclarativebind_p.h \
+ $$PWD/qdeclarativepixmapcache_p.h \
+ $$PWD/qdeclarativebehavior_p.h \
+ $$PWD/qdeclarativefontloader_p.h \
+ $$PWD/qdeclarativestyledtext_p.h \
+
+contains(QT_CONFIG, xmlpatterns) {
+ QT+=xmlpatterns
+ SOURCES += $$PWD/qdeclarativexmllistmodel.cpp
+ HEADERS += $$PWD/qdeclarativexmllistmodel_p.h
+} else {
+ DEFINES += QT_NO_XMLPATTERNS
+}