summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Alpert <alan.alpert@nokia.com>2009-12-16 13:52:41 (GMT)
committerAlan Alpert <alan.alpert@nokia.com>2009-12-16 13:52:41 (GMT)
commit03ce9eed5af9198170f175e976fb56682049b93c (patch)
tree3f71b37403ff14cdd6d6a172eb826ce9c0016f76
parentbb7a6e90375f4f546d1d5dc899e972d9389c2936 (diff)
parent87a939fa289a0d96c1f0eb10fa74b1cb89fc05f1 (diff)
downloadQt-03ce9eed5af9198170f175e976fb56682049b93c.zip
Qt-03ce9eed5af9198170f175e976fb56682049b93c.tar.gz
Qt-03ce9eed5af9198170f175e976fb56682049b93c.tar.bz2
Merge branch 'kinetic-declarativeui' of scm.dev.nokia.troll.no:qt/kinetic into kinetic-declarativeui
-rw-r--r--examples/declarative/listview/sections.qml28
-rw-r--r--src/declarative/3rdparty/qlistmodelinterface_p.h1
-rw-r--r--src/declarative/QmlChanges.txt8
-rw-r--r--src/declarative/graphicsitems/graphicsitems.pri1
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsanchors.cpp8
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsanchors_p_p.h9
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsflickable.cpp4
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsitem.cpp40
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsitem_p.h6
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsitemgeometrylistener_p.h70
-rw-r--r--src/declarative/graphicsitems/qmlgraphicslistview.cpp206
-rw-r--r--src/declarative/graphicsitems/qmlgraphicslistview_p.h39
-rw-r--r--src/declarative/graphicsitems/qmlgraphicspositioners.cpp7
-rw-r--r--src/declarative/graphicsitems/qmlgraphicspositioners_p_p.h9
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsvisualitemmodel.cpp45
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsvisualitemmodel_p.h3
-rw-r--r--src/declarative/qml/qmlbinding.cpp5
-rw-r--r--src/declarative/qml/qmlbinding.h2
-rw-r--r--src/declarative/qml/qmlbindingoptimizations.cpp112
-rw-r--r--src/declarative/qml/qmlbindingoptimizations_p.h54
-rw-r--r--src/declarative/qml/qmlbindingvme.cpp380
-rw-r--r--src/declarative/qml/qmlbindingvme_p.h25
-rw-r--r--src/declarative/qml/qmlcompiler.cpp93
-rw-r--r--src/declarative/qml/qmlcompiler_p.h8
-rw-r--r--src/declarative/qml/qmlcontext.cpp32
-rw-r--r--src/declarative/qml/qmlcontext.h2
-rw-r--r--src/declarative/qml/qmlengine.cpp2
-rw-r--r--src/declarative/qml/qmlenginedebug.cpp3
-rw-r--r--src/declarative/qml/qmlinstruction_p.h1
-rw-r--r--src/declarative/qml/qmlscriptparser.cpp3
-rw-r--r--src/declarative/qml/qmlvme.cpp22
-rw-r--r--src/declarative/util/qmllistmodel.cpp23
-rw-r--r--src/declarative/util/qmllistmodel_p.h1
-rw-r--r--src/declarative/util/qmlstate.cpp4
-rw-r--r--src/declarative/util/qmlxmllistmodel.cpp7
-rw-r--r--src/declarative/util/qmlxmllistmodel_p.h1
-rw-r--r--tools/qmlviewer/qmlfolderlistmodel.cpp14
-rw-r--r--tools/qmlviewer/qmlfolderlistmodel.h1
38 files changed, 978 insertions, 301 deletions
diff --git a/examples/declarative/listview/sections.qml b/examples/declarative/listview/sections.qml
index 6b1a589..6e72ce7 100644
--- a/examples/declarative/listview/sections.qml
+++ b/examples/declarative/listview/sections.qml
@@ -17,25 +17,11 @@ Rectangle {
id: wrapper
width: 200
// My height is the combined height of the description and the section separator
- height: separator.height + desc.height
- Rectangle {
- id: separator
- color: "lightsteelblue"
- width: parent.width
- // Only show the section separator when we are the beginning of a new section
- // Note that for this to work nicely, the list must be ordered by section.
- height: wrapper.ListView.prevSection != wrapper.ListView.section ? 20 : 0
- opacity: wrapper.ListView.prevSection != wrapper.ListView.section ? 1 : 0
- Text {
- text: wrapper.ListView.section; font.bold: true
- x: 2; height: parent.height; verticalAlignment: 'AlignVCenter'
- }
- }
+ height: desc.height
Item {
id: desc
x: 5
height: layout.height + 4
- anchors.top: separator.bottom
Column {
id: layout
y: 2
@@ -64,7 +50,17 @@ Rectangle {
highlight: petHighlight
// The sectionExpression is simply the size of the pet.
// We use this to determine which section we are in above.
- sectionExpression: "size"
+ section.property: "size"
+ section.criteria: ViewSection.FullString
+ section.delegate: Rectangle {
+ color: "lightsteelblue"
+ width: 200
+ height: 20
+ Text {
+ text: section; font.bold: true
+ x: 2; height: parent.height; verticalAlignment: 'AlignVCenter'
+ }
+ }
focus: true
}
}
diff --git a/src/declarative/3rdparty/qlistmodelinterface_p.h b/src/declarative/3rdparty/qlistmodelinterface_p.h
index f7c956a..a958ead 100644
--- a/src/declarative/3rdparty/qlistmodelinterface_p.h
+++ b/src/declarative/3rdparty/qlistmodelinterface_p.h
@@ -60,6 +60,7 @@ class Q_DECLARATIVE_EXPORT QListModelInterface : public QObject
virtual int count() const = 0;
virtual QHash<int,QVariant> data(int index, const QList<int>& roles = QList<int>()) const = 0;
+ virtual QVariant data(int index, int role) const = 0;
virtual bool setData(int index, const QHash<int,QVariant>& values)
{ Q_UNUSED(index); Q_UNUSED(values); return false; }
diff --git a/src/declarative/QmlChanges.txt b/src/declarative/QmlChanges.txt
index 97cefd5..940dc14 100644
--- a/src/declarative/QmlChanges.txt
+++ b/src/declarative/QmlChanges.txt
@@ -1,3 +1,11 @@
+
+
+Listview: sectionExpression has been replaced by section.property, section.criteria
+
+
+=============================================================================
+The changes below are pre-4.6.0 release.
+
QML API Review
==============
diff --git a/src/declarative/graphicsitems/graphicsitems.pri b/src/declarative/graphicsitems/graphicsitems.pri
index 728c9c0..5199c5d 100644
--- a/src/declarative/graphicsitems/graphicsitems.pri
+++ b/src/declarative/graphicsitems/graphicsitems.pri
@@ -48,6 +48,7 @@ HEADERS += \
$$PWD/qmlgraphicsgraphicsobjectcontainer_p.h \
$$PWD/qmlgraphicsparticles_p.h \
$$PWD/qmlgraphicslayoutitem_p.h \
+ $$PWD/qmlgraphicsitemgeometrylistener_p.h \
$$PWD/qmlgraphicseffects.cpp
SOURCES += \
diff --git a/src/declarative/graphicsitems/qmlgraphicsanchors.cpp b/src/declarative/graphicsitems/qmlgraphicsanchors.cpp
index 96d76cf..0febf08 100644
--- a/src/declarative/graphicsitems/qmlgraphicsanchors.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicsanchors.cpp
@@ -241,22 +241,20 @@ void QmlGraphicsAnchorsPrivate::clearItem(QmlGraphicsItem *item)
void QmlGraphicsAnchorsPrivate::addDepend(QmlGraphicsItem *item)
{
- Q_Q(QmlGraphicsAnchors);
if (!item)
return;
QmlGraphicsItemPrivate *p =
static_cast<QmlGraphicsItemPrivate *>(QGraphicsItemPrivate::get(item));
- p->dependantAnchors.append(q);
+ p->addGeometryListener(this);
}
void QmlGraphicsAnchorsPrivate::remDepend(QmlGraphicsItem *item)
{
- Q_Q(QmlGraphicsAnchors);
if (!item)
return;
QmlGraphicsItemPrivate *p =
static_cast<QmlGraphicsItemPrivate *>(QGraphicsItemPrivate::get(item));
- p->dependantAnchors.removeOne(q);
+ p->removeGeometryListener(this);
}
bool QmlGraphicsAnchorsPrivate::isItemComplete() const
@@ -332,7 +330,7 @@ void QmlGraphicsAnchorsPrivate::updateOnComplete()
updateVerticalAnchors();
}
-void QmlGraphicsAnchorsPrivate::update(QmlGraphicsItem *, const QRectF &newG, const QRectF &oldG)
+void QmlGraphicsAnchorsPrivate::itemGeometryChanged(QmlGraphicsItem *, const QRectF &newG, const QRectF &oldG)
{
fillChanged();
centerInChanged();
diff --git a/src/declarative/graphicsitems/qmlgraphicsanchors_p_p.h b/src/declarative/graphicsitems/qmlgraphicsanchors_p_p.h
index 4f7fde0..91c8ff1 100644
--- a/src/declarative/graphicsitems/qmlgraphicsanchors_p_p.h
+++ b/src/declarative/graphicsitems/qmlgraphicsanchors_p_p.h
@@ -54,7 +54,7 @@
//
#include "qmlgraphicsanchors_p.h"
-
+#include "qmlgraphicsitemgeometrylistener_p.h"
#include <private/qobject_p.h>
QT_BEGIN_NAMESPACE
@@ -91,7 +91,7 @@ Q_DECLARE_METATYPE(QmlGraphicsAnchorLine)
-class QmlGraphicsAnchorsPrivate : public QObjectPrivate
+class QmlGraphicsAnchorsPrivate : public QObjectPrivate, public QmlGraphicsItemGeometryListener
{
Q_DECLARE_PUBLIC(QmlGraphicsAnchors)
public:
@@ -128,7 +128,10 @@ public:
void updateOnComplete();
void updateMe();
- void update(QmlGraphicsItem *, const QRectF &, const QRectF &);
+
+ // QmlGraphicsItemGeometryListener interface
+ void itemGeometryChanged(QmlGraphicsItem *, const QRectF &, const QRectF &);
+ QmlGraphicsAnchorsPrivate *anchorPrivate() { return this; }
bool checkHValid() const;
bool checkVValid() const;
diff --git a/src/declarative/graphicsitems/qmlgraphicsflickable.cpp b/src/declarative/graphicsitems/qmlgraphicsflickable.cpp
index f3f138b..79c7659 100644
--- a/src/declarative/graphicsitems/qmlgraphicsflickable.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicsflickable.cpp
@@ -155,7 +155,7 @@ QmlGraphicsFlickablePrivate::QmlGraphicsFlickablePrivate()
: viewport(new QmlGraphicsItem), _moveX(viewport, &QmlGraphicsItem::setX), _moveY(viewport, &QmlGraphicsItem::setY)
, vWidth(-1), vHeight(-1), overShoot(true), flicked(false), moving(false), stealMouse(false)
, pressed(false), atXEnd(false), atXBeginning(true), atYEnd(false), atYBeginning(true)
- , interactive(true), deceleration(500), maxVelocity(5000), reportedVelocitySmoothing(100)
+ , interactive(true), deceleration(500), maxVelocity(2000), reportedVelocitySmoothing(100)
, delayedPressEvent(0), delayedPressTarget(0), pressDelay(0)
, horizontalVelocity(this), verticalVelocity(this), vTime(0), visibleArea(0)
, flickDirection(QmlGraphicsFlickable::AutoFlickDirection)
@@ -1166,7 +1166,7 @@ bool QmlGraphicsFlickable::sceneEventFilter(QGraphicsItem *i, QEvent *e)
\qmlproperty real Flickable::maximumFlickVelocity
This property holds the maximum velocity that the user can flick the view in pixels/second.
- The default is 5000 pixels/s
+ The default is 2000 pixels/s
*/
qreal QmlGraphicsFlickable::maximumFlickVelocity() const
{
diff --git a/src/declarative/graphicsitems/qmlgraphicsitem.cpp b/src/declarative/graphicsitems/qmlgraphicsitem.cpp
index ef4dfc2..4d587e4d 100644
--- a/src/declarative/graphicsitems/qmlgraphicsitem.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicsitem.cpp
@@ -1478,17 +1478,18 @@ QmlGraphicsItem::QmlGraphicsItem(QmlGraphicsItemPrivate &dd, QmlGraphicsItem *pa
QmlGraphicsItem::~QmlGraphicsItem()
{
Q_D(QmlGraphicsItem);
- for (int ii = 0; ii < d->dependantAnchors.count(); ++ii) {
- QmlGraphicsAnchors *anchor = d->dependantAnchors.at(ii);
- anchor->d_func()->clearItem(this);
+ for (int ii = 0; ii < d->geometryListeners.count(); ++ii) {
+ QmlGraphicsAnchorsPrivate *anchor = d->geometryListeners.at(ii)->anchorPrivate();
+ if (anchor)
+ anchor->clearItem(this);
}
if (!d->parent || (parentItem() && !parentItem()->QGraphicsItem::d_ptr->inDestructor))
- for (int ii = 0; ii < d->dependantAnchors.count(); ++ii) {
- QmlGraphicsAnchors *anchor = d->dependantAnchors.at(ii);
- if (anchor->d_func()->item && anchor->d_func()->item->parentItem() != this) //child will be deleted anyway
- anchor->d_func()->updateOnComplete();
+ for (int ii = 0; ii < d->geometryListeners.count(); ++ii) {
+ QmlGraphicsAnchorsPrivate *anchor = d->geometryListeners.at(ii)->anchorPrivate();
+ if (anchor && anchor->item && anchor->item->parentItem() != this) //child will be deleted anyway
+ anchor->updateOnComplete();
}
- d->dependantAnchors.clear();
+ d->geometryListeners.clear();
delete d->_anchorLines; d->_anchorLines = 0;
delete d->_anchors; d->_anchors = 0;
delete d->_stateGroup; d->_stateGroup = 0;
@@ -1974,12 +1975,22 @@ void QmlGraphicsItem::geometryChanged(const QRectF &newGeometry,
if (newGeometry.height() != oldGeometry.height())
emit heightChanged();
- for(int ii = 0; ii < d->dependantAnchors.count(); ++ii) {
- QmlGraphicsAnchors *anchor = d->dependantAnchors.at(ii);
- anchor->d_func()->update(this, newGeometry, oldGeometry);
+ for(int ii = 0; ii < d->geometryListeners.count(); ++ii) {
+ QmlGraphicsItemGeometryListener *listener = d->geometryListeners.at(ii);
+ listener->itemGeometryChanged(this, newGeometry, oldGeometry);
}
}
+void QmlGraphicsItemPrivate::addGeometryListener(QmlGraphicsItemGeometryListener *listener)
+{
+ geometryListeners.append(listener);
+}
+
+void QmlGraphicsItemPrivate::removeGeometryListener(QmlGraphicsItemGeometryListener *listener)
+{
+ geometryListeners.removeOne(listener);
+}
+
/*! \internal */
void QmlGraphicsItem::keyPressEvent(QKeyEvent *event)
{
@@ -2227,9 +2238,10 @@ void QmlGraphicsItem::setBaselineOffset(qreal offset)
d->_baselineOffset = offset;
emit baselineOffsetChanged();
- for(int ii = 0; ii < d->dependantAnchors.count(); ++ii) {
- QmlGraphicsAnchors *anchor = d->dependantAnchors.at(ii);
- anchor->d_func()->updateVerticalAnchors();
+ for(int ii = 0; ii < d->geometryListeners.count(); ++ii) {
+ QmlGraphicsAnchorsPrivate *anchor = d->geometryListeners.at(ii)->anchorPrivate();
+ if (anchor)
+ anchor->updateVerticalAnchors();
}
}
diff --git a/src/declarative/graphicsitems/qmlgraphicsitem_p.h b/src/declarative/graphicsitems/qmlgraphicsitem_p.h
index 304e36c..9496590 100644
--- a/src/declarative/graphicsitems/qmlgraphicsitem_p.h
+++ b/src/declarative/graphicsitems/qmlgraphicsitem_p.h
@@ -57,6 +57,7 @@
#include "qmlgraphicsanchors_p.h"
#include "qmlgraphicsanchors_p_p.h"
+#include "qmlgraphicsitemgeometrylistener_p.h"
#include "../util/qmlstate_p.h"
#include "../util/qmlnullablevalue_p_p.h"
@@ -182,7 +183,6 @@ public:
}
return _anchors;
}
- QList<QmlGraphicsAnchors *> dependantAnchors;
QmlGraphicsAnchors *_anchors;
QmlGraphicsContents *_contents;
@@ -206,6 +206,10 @@ public:
return _anchorLines;
}
+ void addGeometryListener(QmlGraphicsItemGeometryListener *);
+ void removeGeometryListener(QmlGraphicsItemGeometryListener *);
+ QList<QmlGraphicsItemGeometryListener *> geometryListeners;
+
QmlStateGroup *states();
QmlStateGroup *_stateGroup;
diff --git a/src/declarative/graphicsitems/qmlgraphicsitemgeometrylistener_p.h b/src/declarative/graphicsitems/qmlgraphicsitemgeometrylistener_p.h
new file mode 100644
index 0000000..6230e93
--- /dev/null
+++ b/src/declarative/graphicsitems/qmlgraphicsitemgeometrylistener_p.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLGRAPHICSITEMGEOMETRYLISTENER
+#define QMLGRAPHICSITEMGEOMETRYLISTENER
+
+//
+// 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.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QRectF;
+class QmlGraphicsItem;
+class QmlGraphicsAnchorsPrivate;
+class QmlGraphicsItemGeometryListener
+{
+public:
+ virtual void itemGeometryChanged(QmlGraphicsItem *, const QRectF &newGeometry, const QRectF &oldGeometry) = 0;
+ virtual QmlGraphicsAnchorsPrivate *anchorPrivate() { return 0; }
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLGRAPHICSITEMGEOMETRYLISTENER
diff --git a/src/declarative/graphicsitems/qmlgraphicslistview.cpp b/src/declarative/graphicsitems/qmlgraphicslistview.cpp
index 16e9d6e..28ce781 100644
--- a/src/declarative/graphicsitems/qmlgraphicslistview.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicslistview.cpp
@@ -51,6 +51,39 @@
#include <QKeyEvent>
QT_BEGIN_NAMESPACE
+
+void QmlGraphicsViewSection::setProperty(const QString &property)
+{
+ if (property != m_property) {
+ m_property = property;
+ emit changed();
+ }
+}
+
+void QmlGraphicsViewSection::setCriteria(QmlGraphicsViewSection::SectionCriteria criteria)
+{
+ if (criteria != m_criteria) {
+ m_criteria = criteria;
+ emit changed();
+ }
+}
+
+void QmlGraphicsViewSection::setDelegate(QmlComponent *delegate)
+{
+ if (delegate != m_delegate) {
+ m_delegate = delegate;
+ emit delegateChanged();
+ }
+}
+
+QString QmlGraphicsViewSection::sectionString(const QString &value)
+{
+ if (m_criteria == FirstCharacter)
+ return value.at(0);
+ else
+ return value;
+}
+
class QmlGraphicsListViewAttached : public QObject
{
Q_OBJECT
@@ -137,14 +170,23 @@ QHash<QObject*, QmlGraphicsListViewAttached*> QmlGraphicsListViewAttached::attac
class FxListItem
{
public:
- FxListItem(QmlGraphicsItem *i, QmlGraphicsListView *v) : item(i), view(v) {
+ FxListItem(QmlGraphicsItem *i, QmlGraphicsListView *v) : item(i), section(0), view(v) {
attached = QmlGraphicsListViewAttached::properties(item);
attached->m_view = view;
}
~FxListItem() {}
-
- qreal position() const { return (view->orientation() == QmlGraphicsListView::Vertical ? item->y() : item->x()); }
- int size() const { return (view->orientation() == QmlGraphicsListView::Vertical ? item->height() : item->width()); }
+ qreal position() const {
+ if (section)
+ return (view->orientation() == QmlGraphicsListView::Vertical ? section->y() : section->x());
+ else
+ return (view->orientation() == QmlGraphicsListView::Vertical ? item->y() : item->x());
+ }
+ int size() const {
+ if (section)
+ return (view->orientation() == QmlGraphicsListView::Vertical ? item->height()+section->height() : item->width()+section->height());
+ else
+ return (view->orientation() == QmlGraphicsListView::Vertical ? item->height() : item->width());
+ }
qreal endPosition() const {
return (view->orientation() == QmlGraphicsListView::Vertical
? item->y() + (item->height() > 0 ? item->height() : 1)
@@ -152,13 +194,22 @@ public:
}
void setPosition(qreal pos) {
if (view->orientation() == QmlGraphicsListView::Vertical) {
+ if (section) {
+ section->setY(pos);
+ pos += section->height();
+ }
item->setY(pos);
} else {
+ if (section) {
+ section->setX(pos);
+ pos += section->width();
+ }
item->setX(pos);
}
}
QmlGraphicsItem *item;
+ QmlGraphicsItem *section;
QmlGraphicsListView *view;
QmlGraphicsListViewAttached *attached;
int index;
@@ -166,7 +217,7 @@ public:
//----------------------------------------------------------------------------
-class QmlGraphicsListViewPrivate : public QmlGraphicsFlickablePrivate
+class QmlGraphicsListViewPrivate : public QmlGraphicsFlickablePrivate, private QmlGraphicsItemGeometryListener
{
Q_DECLARE_PUBLIC(QmlGraphicsListView)
@@ -177,7 +228,8 @@ public:
, averageSize(100.0), currentIndex(-1), requestedIndex(-1)
, highlightRangeStart(0), highlightRangeEnd(0)
, highlightComponent(0), highlight(0), trackedItem(0)
- , moveReason(Other), buffer(0), highlightPosAnimator(0), highlightSizeAnimator(0), spacing(0.0)
+ , moveReason(Other), buffer(0), highlightPosAnimator(0), highlightSizeAnimator(0)
+ , sectionCriteria(0), spacing(0.0)
, highlightMoveSpeed(400), highlightResizeSpeed(400), highlightRange(QmlGraphicsListView::NoHighlightRange)
, snapMode(QmlGraphicsListView::NoSnap), overshootDist(0.0)
, footerComponent(0), footer(0), headerComponent(0), header(0)
@@ -291,12 +343,15 @@ public:
}
QString sectionAt(int modelIndex) {
- Q_Q(QmlGraphicsListView);
if (FxListItem *item = visibleItem(modelIndex))
return item->attached->section();
+
QString section;
- if (!sectionExpression.isEmpty())
- section = model->evaluate(modelIndex, sectionExpression, q).toString();
+ if (sectionCriteria) {
+ QString propValue = model->value(modelIndex, sectionCriteria->property()).toString();
+ section = sectionCriteria->sectionString(propValue);
+ }
+
return section;
}
@@ -410,6 +465,13 @@ public:
q->setViewportWidth(q->minXExtent() - q->maxXExtent());
}
+ void itemGeometryChanged(QmlGraphicsItem *, const QRectF &newGeometry, const QRectF &oldGeometry) {
+ if ((orient == QmlGraphicsListView::Vertical && newGeometry.height() != oldGeometry.height())
+ || newGeometry.width() != oldGeometry.width()) {
+ layout();
+ fixupPosition();
+ }
+ }
// for debugging only
void checkVisible() const {
@@ -431,6 +493,7 @@ public:
void updateTrackedItem();
void createHighlight();
void updateHighlight();
+ void createSection(FxListItem *);
void updateSections();
void updateCurrentSection();
void updateCurrent(int);
@@ -464,7 +527,7 @@ public:
int buffer;
QmlEaseFollow *highlightPosAnimator;
QmlEaseFollow *highlightSizeAnimator;
- QString sectionExpression;
+ QmlGraphicsViewSection *sectionCriteria;
QString currentSection;
qreal spacing;
qreal highlightMoveSpeed;
@@ -486,12 +549,8 @@ public:
bool correctFlick : 1;
bool inFlickCorrection : 1;
bool lazyRelease : 1;
-
- static int itemResizedIdx;
};
-int QmlGraphicsListViewPrivate::itemResizedIdx = -1;
-
void QmlGraphicsListViewPrivate::init()
{
Q_Q(QmlGraphicsListView);
@@ -500,8 +559,6 @@ void QmlGraphicsListViewPrivate::init()
QObject::connect(q, SIGNAL(widthChanged()), q, SLOT(refill()));
QObject::connect(q, SIGNAL(movementEnded()), q, SLOT(animStopped()));
q->setFlickDirection(QmlGraphicsFlickable::VerticalFlick);
- if (itemResizedIdx == -1)
- itemResizedIdx = QmlGraphicsListView::staticMetaObject.indexOfSlot("itemResized()");
}
void QmlGraphicsListViewPrivate::clear()
@@ -527,10 +584,9 @@ FxListItem *QmlGraphicsListViewPrivate::createItem(int modelIndex)
listItem = new FxListItem(item, q);
listItem->index = modelIndex;
// initialise attached properties
- if (!sectionExpression.isEmpty()) {
- QmlExpression e(qmlContext(listItem->item), sectionExpression, q);
- e.setTrackChange(false);
- listItem->attached->m_section = e.value().toString();
+ if (sectionCriteria) {
+ QString propValue = model->value(modelIndex, sectionCriteria->property()).toString();
+ listItem->attached->m_section = sectionCriteria->sectionString(propValue);
if (modelIndex > 0) {
if (FxListItem *item = visibleItem(modelIndex-1))
listItem->attached->m_prevSection = item->attached->section();
@@ -543,10 +599,11 @@ FxListItem *QmlGraphicsListViewPrivate::createItem(int modelIndex)
listItem->item->setZValue(1);
listItem->item->setParent(q->viewport());
QmlGraphicsItemPrivate *itemPrivate = static_cast<QmlGraphicsItemPrivate*>(QGraphicsItemPrivate::get(item));
- if (orient == QmlGraphicsListView::Vertical)
- itemPrivate->connectToHeightChanged(q, itemResizedIdx);
- else
- itemPrivate->connectToWidthChanged(q, itemResizedIdx);
+ itemPrivate->addGeometryListener(this);
+ if (sectionCriteria && sectionCriteria->delegate()) {
+ if (listItem->attached->m_prevSection != listItem->attached->m_section)
+ createSection(listItem);
+ }
}
requestedIndex = -1;
@@ -565,15 +622,14 @@ void QmlGraphicsListViewPrivate::releaseItem(FxListItem *item)
QObject::disconnect(trackedItem->item, notifier2, q, SLOT(trackedPositionChanged()));
trackedItem = 0;
}
+ QmlGraphicsItemPrivate *itemPrivate = static_cast<QmlGraphicsItemPrivate*>(QGraphicsItemPrivate::get(item->item));
+ itemPrivate->removeGeometryListener(this);
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));
- QmlGraphicsItemPrivate *itemPrivate = static_cast<QmlGraphicsItemPrivate*>(QGraphicsItemPrivate::get(item->item));
- if (orient == QmlGraphicsListView::Vertical)
- itemPrivate->disconnectFromHeightChanged(q, itemResizedIdx);
- else
- itemPrivate->disconnectFromWidthChanged(q, itemResizedIdx);
}
+ if (item->section)
+ delete item->section;
delete item;
}
@@ -654,7 +710,7 @@ void QmlGraphicsListViewPrivate::refill(qreal from, qreal to, bool doBuffer)
if (visibleItems.count())
visiblePos = visibleItems.first()->position();
updateAverage();
- if (!sectionExpression.isEmpty())
+ if (sectionCriteria)
updateCurrentSection();
if (header)
updateHeader();
@@ -670,6 +726,7 @@ void QmlGraphicsListViewPrivate::refill(qreal from, qreal to, bool doBuffer)
void QmlGraphicsListViewPrivate::layout()
{
Q_Q(QmlGraphicsListView);
+ updateSections();
if (!visibleItems.isEmpty()) {
int oldEnd = visibleItems.last()->endPosition();
int pos = visibleItems.first()->endPosition() + spacing + 1;
@@ -819,9 +876,38 @@ void QmlGraphicsListViewPrivate::updateHighlight()
updateTrackedItem();
}
+void QmlGraphicsListViewPrivate::createSection(FxListItem *listItem)
+{
+ Q_Q(QmlGraphicsListView);
+ if (!sectionCriteria || !sectionCriteria->delegate())
+ return;
+ if (listItem->attached->m_prevSection != listItem->attached->m_section) {
+ if (!listItem->section) {
+ QmlContext *context = new QmlContext(qmlContext(q));
+ context->setContextProperty(QLatin1String("section"), listItem->attached->m_section);
+ QObject *nobj = sectionCriteria->delegate()->create(context);
+ if (nobj) {
+ context->setParent(nobj);
+ listItem->section = qobject_cast<QmlGraphicsItem *>(nobj);
+ if (!listItem->section) {
+ delete nobj;
+ } else {
+ listItem->section->setZValue(1);
+ listItem->section->setParent(q->viewport());
+ }
+ } else {
+ delete context;
+ }
+ }
+ } else {
+ delete listItem->section;
+ listItem->section = 0;
+ }
+}
+
void QmlGraphicsListViewPrivate::updateSections()
{
- if (!sectionExpression.isEmpty()) {
+ if (sectionCriteria) {
QString prevSection;
if (visibleIndex > 0)
prevSection = sectionAt(visibleIndex-1);
@@ -829,6 +915,7 @@ void QmlGraphicsListViewPrivate::updateSections()
if (visibleItems.at(i)->index != -1) {
QmlGraphicsListViewAttached *attached = visibleItems.at(i)->attached;
attached->setPrevSection(prevSection);
+ createSection(visibleItems.at(i));
prevSection = attached->section();
}
}
@@ -837,7 +924,7 @@ void QmlGraphicsListViewPrivate::updateSections()
void QmlGraphicsListViewPrivate::updateCurrentSection()
{
- if (sectionExpression.isEmpty() || visibleItems.isEmpty()) {
+ if (sectionCriteria || visibleItems.isEmpty()) {
currentSection = QString();
return;
}
@@ -1294,7 +1381,7 @@ QmlGraphicsListView::~QmlGraphicsListView()
It is attached to each instance of the delegate.
- The section is evaluated using the \l {ListView::sectionExpression}{sectionExpression} property.
+ The section is evaluated using the \l {ListView::section.property}{section} properties.
*/
/*!
@@ -1303,7 +1390,7 @@ QmlGraphicsListView::~QmlGraphicsListView()
It is attached to each instance of the delegate.
- The section is evaluated using the \l {ListView::sectionExpression}{sectionExpression} property.
+ The section is evaluated using the \l {ListView::section.property}{section} properties.
*/
/*!
@@ -1752,8 +1839,19 @@ void QmlGraphicsListView::setCacheBuffer(int b)
}
/*!
- \qmlproperty string ListView::sectionExpression
- This property holds the expression to be evaluated for the section attached property.
+ \qmlproperty string ListView::section.property
+ \qmlproperty enumeration ListView::section.criteria
+ These properties hold the expression to be evaluated for the section attached property.
+
+ section.property hold the name of the property to use to determine
+ the section the item is in.
+
+ section.criteria holds the criteria to use to get the section. It
+ can be either:
+ \list
+ \o ViewSection.FullString (default) - section is the value of the property.
+ \o ViewSection.FirstCharacter - section is the first character of the property value.
+ \endlist
Each item in the list has attached properties named \c ListView.section and
\c ListView.prevSection. These may be used to place a section header for
@@ -1765,19 +1863,12 @@ void QmlGraphicsListView::setCacheBuffer(int b)
\image ListViewSections.png
*/
-QString QmlGraphicsListView::sectionExpression() const
-{
- Q_D(const QmlGraphicsListView);
- return d->sectionExpression;
-}
-
-void QmlGraphicsListView::setSectionExpression(const QString &expression)
+QmlGraphicsViewSection *QmlGraphicsListView::sectionCriteria()
{
Q_D(QmlGraphicsListView);
- if (d->sectionExpression != expression) {
- d->sectionExpression = expression;
- emit sectionExpressionChanged();
- }
+ if (!d->sectionCriteria)
+ d->sectionCriteria = new QmlGraphicsViewSection(this);
+ return d->sectionCriteria;
}
/*!
@@ -2207,23 +2298,12 @@ void QmlGraphicsListView::trackedPositionChanged()
}
}
-void QmlGraphicsListView::itemResized()
-{
- Q_D(QmlGraphicsListView);
- QmlGraphicsItem *item = qobject_cast<QmlGraphicsItem*>(sender());
- if (item) {
- d->layout();
- d->fixupPosition();
- }
-}
-
void QmlGraphicsListView::itemsInserted(int modelIndex, int count)
{
Q_D(QmlGraphicsListView);
d->updateUnrequestedIndexes();
if (!d->visibleItems.count() || d->model->count() <= 1) {
d->layout();
- d->updateSections();
d->updateCurrent(qMax(0, qMin(d->currentIndex, d->model->count()-1)));
emit countChanged();
return;
@@ -2334,11 +2414,7 @@ void QmlGraphicsListView::itemsInserted(int modelIndex, int count)
// everything is in order now - emit add() signal
for (int j = 0; j < added.count(); ++j)
added.at(j)->attached->emitAdd();
- d->updateUnrequestedPositions();
- d->updateViewport();
- d->updateSections();
- d->updateHeader();
- d->updateFooter();
+ d->layout();
emit countChanged();
}
@@ -2369,7 +2445,6 @@ void QmlGraphicsListView::itemsRemoved(int modelIndex, int count)
d->updateCurrent(qMin(modelIndex, d->model->count()-1));
}
d->layout();
- d->updateSections();
emit countChanged();
return;
}
@@ -2442,7 +2517,6 @@ void QmlGraphicsListView::itemsRemoved(int modelIndex, int count)
} else {
// Correct the positioning of the items
d->layout();
- d->updateSections();
}
emit countChanged();
@@ -2540,7 +2614,6 @@ void QmlGraphicsListView::itemsMoved(int from, int to, int count)
d->visibleItems.first()->setPosition(d->visibleItems.first()->position() + moveBy);
d->layout();
- d->updateSections();
}
void QmlGraphicsListView::createdItem(int index, QmlGraphicsItem *item)
@@ -2575,6 +2648,7 @@ QmlGraphicsListViewAttached *QmlGraphicsListView::qmlAttachedProperties(QObject
}
QML_DEFINE_TYPE(Qt,4,6,ListView,QmlGraphicsListView)
+QML_DEFINE_TYPE(Qt,4,6,ViewSection,QmlGraphicsViewSection)
QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qmlgraphicslistview_p.h b/src/declarative/graphicsitems/qmlgraphicslistview_p.h
index 6dc131c..2a2ef8a 100644
--- a/src/declarative/graphicsitems/qmlgraphicslistview_p.h
+++ b/src/declarative/graphicsitems/qmlgraphicslistview_p.h
@@ -50,6 +50,38 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
+class Q_DECLARATIVE_EXPORT QmlGraphicsViewSection : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString property READ property WRITE setProperty NOTIFY changed)
+ Q_PROPERTY(SectionCriteria criteria READ criteria WRITE setCriteria NOTIFY changed)
+ Q_PROPERTY(QmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
+ Q_ENUMS(SectionCriteria)
+public:
+ QmlGraphicsViewSection(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);
+
+ QmlComponent *delegate() const { return m_delegate; }
+ void setDelegate(QmlComponent *delegate);
+
+ QString sectionString(const QString &value);
+
+Q_SIGNALS:
+ void changed();
+ void delegateChanged();
+
+private:
+ QString m_property;
+ SectionCriteria m_criteria;
+ QmlComponent *m_delegate;
+};
+
class QmlGraphicsVisualModel;
class QmlGraphicsListViewAttached;
@@ -79,7 +111,7 @@ class Q_DECLARATIVE_EXPORT QmlGraphicsListView : public QmlGraphicsFlickable
Q_PROPERTY(Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged)
Q_PROPERTY(bool keyNavigationWraps READ isWrapEnabled WRITE setWrapEnabled)
Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer)
- Q_PROPERTY(QString sectionExpression READ sectionExpression WRITE setSectionExpression NOTIFY sectionExpressionChanged)
+ Q_PROPERTY(QmlGraphicsViewSection *section READ sectionCriteria CONSTANT)
Q_PROPERTY(QString currentSection READ currentSection NOTIFY currentSectionChanged)
Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode)
@@ -138,8 +170,7 @@ public:
int cacheBuffer() const;
void setCacheBuffer(int);
- QString sectionExpression() const;
- void setSectionExpression(const QString &);
+ QmlGraphicsViewSection *sectionCriteria();
QString currentSection() const;
qreal highlightMoveSpeed() const;
@@ -188,7 +219,6 @@ protected:
private Q_SLOTS:
void refill();
void trackedPositionChanged();
- void itemResized();
void itemsInserted(int index, int count);
void itemsRemoved(int index, int count);
void itemsMoved(int from, int to, int count);
@@ -202,6 +232,7 @@ QT_END_NAMESPACE
QML_DECLARE_TYPEINFO(QmlGraphicsListView, QML_HAS_ATTACHED_PROPERTIES)
QML_DECLARE_TYPE(QmlGraphicsListView)
+QML_DECLARE_TYPE(QmlGraphicsViewSection)
QT_END_HEADER
diff --git a/src/declarative/graphicsitems/qmlgraphicspositioners.cpp b/src/declarative/graphicsitems/qmlgraphicspositioners.cpp
index 9f6baae..17fe59f 100644
--- a/src/declarative/graphicsitems/qmlgraphicspositioners.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicspositioners.cpp
@@ -67,8 +67,7 @@ void QmlGraphicsBasePositionerPrivate::watchChanges(QmlGraphicsItem *other)
QmlGraphicsItemPrivate *otherPrivate = static_cast<QmlGraphicsItemPrivate*>(QGraphicsItemPrivate::get(other));
- otherPrivate->connectToHeightChanged(q, prePosIdx);
- otherPrivate->connectToWidthChanged(q, prePosIdx);
+ otherPrivate->addGeometryListener(this);
otherPrivate->registerSiblingOrderNotification(this);
watched << other;
@@ -81,8 +80,8 @@ void QmlGraphicsBasePositionerPrivate::unwatchChanges(QmlGraphicsItem* other)
bool stillAlive = false; //Use the returns from disconnect to see if it was deleted or just reparented
stillAlive |= QMetaObject::disconnect(other, visibleIdx, q, prePosIdx);
stillAlive |= QMetaObject::disconnect(other, opacityIdx, q, prePosIdx);
- stillAlive |= otherPrivate->disconnectFromHeightChanged(q, prePosIdx);
- stillAlive |= otherPrivate->disconnectFromWidthChanged(q, prePosIdx);
+
+ otherPrivate->removeGeometryListener(this);
if(stillAlive)
otherPrivate->unregisterSiblingOrderNotification(this);
diff --git a/src/declarative/graphicsitems/qmlgraphicspositioners_p_p.h b/src/declarative/graphicsitems/qmlgraphicspositioners_p_p.h
index db795ec..63c1c83 100644
--- a/src/declarative/graphicsitems/qmlgraphicspositioners_p_p.h
+++ b/src/declarative/graphicsitems/qmlgraphicspositioners_p_p.h
@@ -66,7 +66,7 @@
#include <QtCore/QTimer>
QT_BEGIN_NAMESPACE
-class QmlGraphicsBasePositionerPrivate : public QmlGraphicsItemPrivate
+class QmlGraphicsBasePositionerPrivate : public QmlGraphicsItemPrivate, public QmlGraphicsItemGeometryListener
{
Q_DECLARE_PUBLIC(QmlGraphicsBasePositioner)
@@ -125,6 +125,13 @@ public:
queuedPositioning = true;
}
}
+
+ void itemGeometryChanged(QmlGraphicsItem *, const QRectF &newGeometry, const QRectF &oldGeometry)
+ {
+ Q_Q(QmlGraphicsBasePositioner);
+ if (newGeometry.size() != oldGeometry.size())
+ q->prePositioning();
+ }
};
QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qmlgraphicsvisualitemmodel.cpp b/src/declarative/graphicsitems/qmlgraphicsvisualitemmodel.cpp
index 7c2159f..6b4a773 100644
--- a/src/declarative/graphicsitems/qmlgraphicsvisualitemmodel.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicsvisualitemmodel.cpp
@@ -44,6 +44,7 @@
#include "qmlgraphicsitem.h"
#include <qmlcontext.h>
+#include <qmlengine.h>
#include <qmlexpression.h>
#include <qmlpackage_p.h>
#include <qmlopenmetaobject_p.h>
@@ -208,9 +209,19 @@ void QmlGraphicsVisualItemModel::completeItem()
// Nothing to do
}
+QVariant QmlGraphicsVisualItemModel::value(int index, const QString &name)
+{
+ Q_D(QmlGraphicsVisualItemModel);
+ if (index < 0 || index >= d->children.count())
+ return QVariant();
+ return QmlEngine::contextForObject(d->children.at(index))->contextProperty(name);
+}
+
QVariant QmlGraphicsVisualItemModel::evaluate(int index, const QString &expression, QObject *objectContext)
{
Q_D(QmlGraphicsVisualItemModel);
+ if (index < 0 || index >= d->children.count())
+ return QVariant();
QmlContext *ccontext = qmlContext(this);
QmlContext *ctxt = new QmlContext(ccontext);
ctxt->addDefaultObject(d->children.at(index));
@@ -878,6 +889,33 @@ void QmlGraphicsVisualDataModel::completeItem()
d->m_delegate->completeCreate();
}
+QVariant QmlGraphicsVisualDataModel::value(int index, const QString &name)
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ if (d->m_visualItemModel)
+ return d->m_visualItemModel->value(index, name);
+
+ if ((!d->m_listModelInterface && !d->m_abstractItemModel) || !d->m_delegate)
+ return QVariant();
+
+ QVariant val;
+ QObject *nobj = d->m_cache.item(index);
+ if (nobj) {
+ val = QmlEngine::contextForObject(nobj)->contextProperty(name);
+ } else {
+ QmlContext *ccontext = d->m_context;
+ if (!ccontext) ccontext = qmlContext(this);
+ QmlContext *ctxt = new QmlContext(ccontext);
+ QmlGraphicsVisualDataModelData *data = new QmlGraphicsVisualDataModelData(index, this);
+ ctxt->addDefaultObject(data);
+ val = ctxt->contextProperty(name);
+ delete data;
+ delete ctxt;
+ }
+
+ return val;
+}
+
QVariant QmlGraphicsVisualDataModel::evaluate(int index, const QString &expression, QObject *objectContext)
{
Q_D(QmlGraphicsVisualDataModel);
@@ -914,11 +952,8 @@ QVariant QmlGraphicsVisualDataModel::evaluate(int index, const QString &expressi
int QmlGraphicsVisualDataModel::indexOf(QmlGraphicsItem *item, QObject *objectContext) const
{
- QmlExpression e(qmlContext(item), QLatin1String("index"), objectContext);
- e.setTrackChange(false);
- QVariant value = e.value();
- if (value.isValid())
- return value.toInt();
+ QVariant val = QmlEngine::contextForObject(item)->contextProperty("index");
+ return val.toInt();
return -1;
}
diff --git a/src/declarative/graphicsitems/qmlgraphicsvisualitemmodel_p.h b/src/declarative/graphicsitems/qmlgraphicsvisualitemmodel_p.h
index 4e76aee..4e8a19b 100644
--- a/src/declarative/graphicsitems/qmlgraphicsvisualitemmodel_p.h
+++ b/src/declarative/graphicsitems/qmlgraphicsvisualitemmodel_p.h
@@ -82,6 +82,7 @@ public:
virtual ReleaseFlags release(QmlGraphicsItem *item) = 0;
virtual void completeItem() = 0;
virtual QVariant evaluate(int index, const QString &expression, QObject *objectContext) = 0;
+ virtual QVariant value(int index, const QString &role) { return QVariant(); }
virtual int indexOf(QmlGraphicsItem *item, QObject *objectContext) const = 0;
@@ -120,6 +121,7 @@ public:
virtual QmlGraphicsItem *item(int index, bool complete=true);
virtual ReleaseFlags release(QmlGraphicsItem *item);
virtual void completeItem();
+ virtual QVariant value(int index, const QString &role);
virtual QVariant evaluate(int index, const QString &expression, QObject *objectContext);
virtual int indexOf(QmlGraphicsItem *item, QObject *objectContext) const;
@@ -166,6 +168,7 @@ public:
QmlGraphicsItem *item(int index, const QByteArray &, bool complete=true);
ReleaseFlags release(QmlGraphicsItem *item);
void completeItem();
+ virtual QVariant value(int index, const QString &role);
QVariant evaluate(int index, const QString &expression, QObject *objectContext);
int indexOf(QmlGraphicsItem *item, QObject *objectContext) const;
diff --git a/src/declarative/qml/qmlbinding.cpp b/src/declarative/qml/qmlbinding.cpp
index 56d5807..d1a8fe8 100644
--- a/src/declarative/qml/qmlbinding.cpp
+++ b/src/declarative/qml/qmlbinding.cpp
@@ -276,6 +276,11 @@ QmlAbstractBinding::~QmlAbstractBinding()
*m_mePtr = 0;
}
+void QmlAbstractBinding::destroy()
+{
+ delete this;
+}
+
void QmlAbstractBinding::addToObject(QObject *object)
{
Q_ASSERT(object);
diff --git a/src/declarative/qml/qmlbinding.h b/src/declarative/qml/qmlbinding.h
index 6f2d4f1..177a0fd 100644
--- a/src/declarative/qml/qmlbinding.h
+++ b/src/declarative/qml/qmlbinding.h
@@ -61,6 +61,8 @@ public:
QmlAbstractBinding();
virtual ~QmlAbstractBinding();
+ virtual void destroy();
+
virtual QString expression() const;
void setEnabled(bool e) { setEnabled(e, QmlMetaProperty::DontRemoveBinding); }
diff --git a/src/declarative/qml/qmlbindingoptimizations.cpp b/src/declarative/qml/qmlbindingoptimizations.cpp
index 120e07b..d8a2de0 100644
--- a/src/declarative/qml/qmlbindingoptimizations.cpp
+++ b/src/declarative/qml/qmlbindingoptimizations.cpp
@@ -47,32 +47,50 @@
QT_BEGIN_NAMESPACE
-int QmlBinding_Basic::reevalIndex = -1;
+int QmlOptimizedBindings::methodCount = -1;
-QmlBinding_Basic::QmlBinding_Basic(QObject *target, int property,
- const char *data, QmlRefCount *ref,
- QObject *scope, QmlContext *context)
-: m_enabled(false), m_updating(false), m_scope(scope), m_target(target),
- m_property(property), m_data(data)
+QmlOptimizedBindings::QmlOptimizedBindings(const char *program, QmlContext *context)
+: m_program(program)
{
- if (reevalIndex == -1)
- reevalIndex = QmlBinding_Basic::staticMetaObject.indexOfSlot("reeval()");
+ if (methodCount == -1)
+ methodCount = QmlOptimizedBindings::staticMetaObject.methodCount();
m_config.target = this;
- m_config.targetSlot = reevalIndex;
- m_scope2 = m_scope;
+ m_config.targetSlot = metaObject()->methodCount();
+
+ quint32 bindings = 0;
+ QmlBindingVME::init(m_program, &m_config, &m_signalTable, &bindings);
+
+ m_bindings = new Binding[bindings];
QmlAbstractExpression::setContext(context);
}
-QmlBinding_Basic::~QmlBinding_Basic()
+QmlOptimizedBindings::~QmlOptimizedBindings()
{
+ delete [] m_bindings;
}
-void QmlBinding_Basic::setEnabled(bool e, QmlMetaProperty::WriteFlags flags)
+QmlAbstractBinding *QmlOptimizedBindings::configBinding(int index, QObject *target,
+ QObject *scope, int property)
+{
+ Binding *rv = m_bindings + index;
+
+ rv->index = index;
+ rv->property = property;
+ rv->target = target;
+ rv->scope = scope;
+ rv->parent = this;
+
+ addref(); // This is decremented in Binding::destroy()
+
+ return rv;
+}
+
+void QmlOptimizedBindings::Binding::setEnabled(bool e, QmlMetaProperty::WriteFlags flags)
{
if (e) {
- addToObject(m_target);
+ addToObject(target);
update(flags);
} else {
removeFromObject();
@@ -80,56 +98,74 @@ void QmlBinding_Basic::setEnabled(bool e, QmlMetaProperty::WriteFlags flags)
QmlAbstractBinding::setEnabled(e, flags);
- if (m_enabled != e) {
- m_enabled = e;
+ if (enabled != e) {
+ enabled = e;
if (e) update(flags);
}
}
-int QmlBinding_Basic::propertyIndex()
+int QmlOptimizedBindings::Binding::propertyIndex()
{
- return m_property & 0xFFFF;
+ return property & 0xFFFF;
}
-void QmlBinding_Basic::update(QmlMetaProperty::WriteFlags flags)
+void QmlOptimizedBindings::Binding::update(QmlMetaProperty::WriteFlags)
{
- if (!m_enabled)
- return;
+ parent->run(this);
+}
- if (m_updating) {
- qmlInfo(m_target) << tr("Binding loop detected");
- return;
+void QmlOptimizedBindings::Binding::destroy()
+{
+ enabled = false;
+ removeFromObject();
+ parent->release();
+}
+
+int QmlOptimizedBindings::qt_metacall(QMetaObject::Call c, int id, void **)
+{
+ if (c == QMetaObject::InvokeMetaMethod && id >= methodCount) {
+ id -= methodCount;
+
+ quint32 *reeval = m_signalTable + m_signalTable[id];
+ quint32 count = *reeval;
+ ++reeval;
+ for (quint32 ii = 0; ii < count; ++ii) {
+ run(m_bindings + reeval[ii]);
+ }
}
+ return -1;
+}
+
+void QmlOptimizedBindings::run(Binding *binding)
+{
+ if (!binding->enabled)
+ return;
+ if (binding->updating)
+ qWarning("ERROR: Circular binding");
QmlContext *context = QmlAbstractExpression::context();
if (!context)
return;
QmlContextPrivate *cp = QmlContextPrivate::get(context);
- m_updating = true;
-
- if (m_property & 0xFFFF0000) {
+ if (binding->property & 0xFFFF0000) {
QmlEnginePrivate *ep = QmlEnginePrivate::get(cp->engine);
- QmlValueType *vt = ep->valueTypes[(m_property >> 16) & 0xFF];
+ QmlValueType *vt = ep->valueTypes[(binding->property >> 16) & 0xFF];
Q_ASSERT(vt);
- vt->read(m_target, m_property & 0xFFFF);
+ vt->read(binding->target, binding->property & 0xFFFF);
QObject *target = vt;
- QmlBindingVME::run(m_data, &m_config, cp, &m_scope, &target);
+ QmlBindingVME::run(m_program, binding->index, &m_config, cp,
+ &binding->scope, &target);
- vt->write(m_target, m_property & 0xFFFF, flags);
+ vt->write(binding->target, binding->property & 0xFFFF,
+ QmlMetaProperty::DontRemoveBinding);
} else {
- QmlBindingVME::run(m_data, &m_config, cp, &m_scope, &m_target);
+ QmlBindingVME::run(m_program, binding->index, &m_config, cp,
+ &binding->scope, &binding->target);
}
-
- m_updating = false;
-}
-
-void QmlBinding_Basic::reeval()
-{
- update(QmlMetaProperty::DontRemoveBinding);
}
/*
diff --git a/src/declarative/qml/qmlbindingoptimizations_p.h b/src/declarative/qml/qmlbindingoptimizations_p.h
index ee2eb83..6289cc0 100644
--- a/src/declarative/qml/qmlbindingoptimizations_p.h
+++ b/src/declarative/qml/qmlbindingoptimizations_p.h
@@ -62,36 +62,44 @@ QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
-class QmlBinding_Basic : public QObject,
- public QmlAbstractExpression,
- public QmlAbstractBinding
+class QmlOptimizedBindings : public QObject, public QmlAbstractExpression, public QmlRefCount
{
- Q_OBJECT
public:
- QmlBinding_Basic(QObject *target, int property,
- const char *data, QmlRefCount *ref,
- QObject *scope, QmlContext *context);
- virtual ~QmlBinding_Basic();
+ QmlOptimizedBindings(const char *program, QmlContext *context);
+ virtual ~QmlOptimizedBindings();
+ QmlAbstractBinding *configBinding(int index, QObject *target, QObject *scope, int property);
- // Inherited from QmlAbstractBinding
- virtual void setEnabled(bool, QmlMetaProperty::WriteFlags flags);
- virtual int propertyIndex();
- virtual void update(QmlMetaProperty::WriteFlags flags);
-
-private slots:
- void reeval();
+protected:
+ int qt_metacall(QMetaObject::Call, int, void **);
private:
- bool m_enabled:1;
- bool m_updating:1;
- QObject *m_scope;
- QObject *m_target;
- int m_property;
- const char *m_data;
+ struct Binding : public QmlAbstractBinding {
+ Binding() : enabled(false), updating(0), property(0),
+ scope(0), target(0), parent(0) {}
+
+ // Inherited from QmlAbstractBinding
+ virtual void setEnabled(bool, QmlMetaProperty::WriteFlags flags);
+ virtual int propertyIndex();
+ virtual void update(QmlMetaProperty::WriteFlags flags);
+ virtual void destroy();
+
+ int index:30;
+ bool enabled:1;
+ bool updating:1;
+ int property;
+ QObject *scope;
+ QObject *target;
+
+ QmlOptimizedBindings *parent;
+ };
+ void run(Binding *);
+
QmlBindingVME::Config m_config;
- QGuard<QObject> m_scope2;
+ const char *m_program;
+ Binding *m_bindings;
+ quint32 *m_signalTable;
- static int reevalIndex;
+ static int methodCount;
};
class QmlBinding_Id : public QmlAbstractExpression,
diff --git a/src/declarative/qml/qmlbindingvme.cpp b/src/declarative/qml/qmlbindingvme.cpp
index 692be68..5abcdb8 100644
--- a/src/declarative/qml/qmlbindingvme.cpp
+++ b/src/declarative/qml/qmlbindingvme.cpp
@@ -67,6 +67,7 @@ struct Register {
QVariant *getvariantptr() { return (QVariant *)typeDataPtr(); }
QString *getstringptr() { return (QString *)typeDataPtr(); }
+ QUrl *geturlptr() { return (QUrl *)typeDataPtr(); }
void *typeDataPtr() { return (void *)&data; }
void *typeMemory() { return (void *)data; }
@@ -78,8 +79,6 @@ struct Instr {
enum {
Noop,
- Init, // init
-
Subscribe, // subscribe
SubscribeId, // subscribe
@@ -110,6 +109,9 @@ struct Instr {
GreaterThanReal, // binaryop
NewString, // construct
+ NewUrl, // construct
+
+ CleanupUrl, // cleanup
CleanupString, // cleanup
Copy, // copy
@@ -130,6 +132,7 @@ struct Instr {
ConvertGenericToReal, // genericunaryop
ConvertGenericToBool, // genericunaryop
ConvertGenericToString, // genericunaryop
+ ConvertGenericToUrl, // genericunaryop
} type;
@@ -219,13 +222,18 @@ struct Instr {
};
struct Program {
- int dataLength;
+ quint32 bindings;
+ quint32 dataLength;
+ quint32 signalTableOffset;
+ quint16 subscriptions;
+ quint16 identifiers;
+
const char *data() const { return ((const char *)this) + sizeof(Program); }
const Instr *instructions() const { return (const Instr *)(data() + dataLength); }
};
}
-struct QmlBindingCompiler
+struct QmlBindingCompilerPrivate
{
struct Result {
Result() : unknownType(false), metaObject(0), type(-1), reg(-1) {}
@@ -246,8 +254,12 @@ struct QmlBindingCompiler
QSet<QString> subscriptionSet;
};
- QmlBindingCompiler() : registers(0), strings(0) {}
- void reset();
+ QmlBindingCompilerPrivate() : registers(0), strings(0) {
+ committed.strings = 0;
+ }
+
+ void resetInstanceState();
+ int commitCompile();
QmlParser::Object *context;
QmlParser::Object *component;
@@ -256,6 +268,8 @@ struct QmlBindingCompiler
QmlEnginePrivate::Imports imports;
QmlEnginePrivate *engine;
+ QString contextName() const { return QLatin1String("$$$SCOPE_") + QString::number((intptr_t)context, 16); }
+
bool compile(QmlJS::AST::Node *);
bool parseExpression(QmlJS::AST::Node *, Result &);
@@ -288,60 +302,44 @@ struct QmlBindingCompiler
int strings;
QByteArray data;
- QSet<QString> subscriptionSet;
- QHash<QString, int> subscriptionIds;
bool subscription(const QStringList &, Result *);
int subscriptionIndex(const QStringList &);
bool subscriptionNeutral(const QSet<QString> &base, const QSet<QString> &lhs, const QSet<QString> &rhs);
- QVector<Instr> bytecode;
-};
-QByteArray QmlBindingVME::compile(const QmlBasicScript::Expression &expression, QmlEnginePrivate *engine)
-{
- if (!expression.expression.asAST()) return false;
+ QSet<int> usedSubscriptionIds;
+ QSet<QString> subscriptionSet;
+ QHash<QString, int> subscriptionIds;
+ QVector<Instr> bytecode;
- QmlBindingCompiler bsc;
- bsc.context = expression.context;
- bsc.component = expression.component;
- bsc.destination = expression.property;
- bsc.ids = expression.ids;
- bsc.imports = expression.imports;
- bsc.engine = engine;
+ // Committed binding data
+ struct {
+ QList<int> offsets;
+ QList<QSet<int> > dependencies;
- bool ok = bsc.compile(expression.expression.asAST());
+ QVector<Instr> bytecode;
+ QByteArray data;
+ int strings;
+ QHash<QString, int> subscriptionIds;
- if (ok) {
- Program prog;
- prog.dataLength = 4 * ((bsc.data.size() + 3) / 4);
- int size = sizeof(Program) + bsc.bytecode.count() * sizeof(Instr);
- size += prog.dataLength;
+ int count() const { return offsets.count(); }
+ } committed;
- QByteArray data;
- data.resize(size);
- memcpy(data.data(), &prog, sizeof(Program));
- if (prog.dataLength)
- memcpy((char *)((Program *)data.data())->data(), bsc.data.constData(),
- bsc.data.size());
- memcpy((char *)((Program *)data.data())->instructions(), bsc.bytecode.constData(),
- bsc.bytecode.count() * sizeof(Instr));
- return data;
- } else {
- return QByteArray();
- }
-}
+ QByteArray buildSignalTable() const;
+};
-inline void subscribe(QObject *o, int notifyIndex, QmlBindingVME::Config::Subscription *s,
- QmlBindingVME::Config *config)
+inline void subscribe(QObject *o, int notifyIndex,
+ int subIndex, QmlBindingVME::Config *config)
{
+ QmlBindingVME::Config::Subscription *s = config->subscriptions + subIndex;
if (o != s->source || notifyIndex != s->notifyIndex) {
if (s->source)
QMetaObject::disconnect(s->source, s->notifyIndex,
- config->target, config->targetSlot);
+ config->target, config->targetSlot + subIndex);
s->source = o;
s->notifyIndex = notifyIndex;
- if (s->source && s->notifyIndex != -1)
+ if (s->source && s->notifyIndex != -1)
QMetaObject::connect(s->source, s->notifyIndex, config->target,
- config->targetSlot, Qt::DirectConnection);
+ config->targetSlot + subIndex, Qt::DirectConnection);
}
}
@@ -431,7 +429,7 @@ static bool findproperty(QObject *obj,
}
if (subIdx != -1)
- subscribe(obj, property->notifyIndex, config->subscriptions + subIdx, config);
+ subscribe(obj, property->notifyIndex, subIdx, config);
return true;
} else {
@@ -572,16 +570,35 @@ inline static QUrl toUrl(Register *reg, int type, QmlContextPrivate *context, bo
if (ok) *ok = false;
return QUrl();
}
- } else {
+ } else {
if (ok) *ok = false;
return QUrl();
}
- return QUrl();
+ if (base.isRelative())
+ return context->url.resolved(base);
+ else
+ return base;
+}
+
+/*!
+Returns the signal/binding table.
+*/
+void QmlBindingVME::init(const char *programData, Config *config,
+ quint32 **sigTable, quint32 *bindingCount)
+{
+ Program *program = (Program *)programData;
+ if (program->subscriptions)
+ config->subscriptions = new Config::Subscription[program->subscriptions];
+ if (program->identifiers)
+ config->identifiers = new QScriptDeclarativeClass::PersistentIdentifier[program->identifiers];
+
+ *sigTable = (quint32 *)(program->data() + program->signalTableOffset);
+ *bindingCount = program->bindings;
}
-void QmlBindingVME::run(const char *programData, Config *config,
- QmlContextPrivate *context,
+void QmlBindingVME::run(const char *programData, int instrIndex,
+ Config *config, QmlContextPrivate *context,
QObject **scopes, QObject **outputs)
{
Register registers[32];
@@ -590,6 +607,7 @@ void QmlBindingVME::run(const char *programData, Config *config,
QmlEnginePrivate *engine = QmlEnginePrivate::get(context->engine);
Program *program = (Program *)programData;
const Instr *instr = program->instructions();
+ instr += instrIndex;
const char *data = program->data();
while (instr) {
@@ -597,18 +615,11 @@ void QmlBindingVME::run(const char *programData, Config *config,
switch (instr->type) {
case Instr::Noop:
break;
- case Instr::Init:
- if (!config->subscriptions && instr->init.subscriptions)
- config->subscriptions = new Config::Subscription[instr->init.subscriptions];
- if (!config->identifiers && instr->init.identifiers)
- config->identifiers = new QScriptDeclarativeClass::PersistentIdentifier[instr->init.identifiers];
- break;
case Instr::SubscribeId:
case Instr::Subscribe:
{
QObject *o = registers[instr->subscribe.reg].getQObject();
- Config::Subscription *s = config->subscriptions + instr->subscribe.offset;
int notifyIndex = instr->subscribe.index;
if (instr->type == Instr::SubscribeId) {
@@ -616,7 +627,7 @@ void QmlBindingVME::run(const char *programData, Config *config,
notifyIndex += context->notifyIndex;
}
- subscribe(o, instr->subscribe.index, s, config);
+ subscribe(o, instr->subscribe.index, instr->subscribe.offset, config);
}
break;
@@ -710,8 +721,16 @@ void QmlBindingVME::run(const char *programData, Config *config,
new (registers[instr->construct.reg].typeMemory()) QString;
break;
+ case Instr::NewUrl:
+ new (registers[instr->construct.reg].typeMemory()) QUrl;
+ break;
+
case Instr::CleanupString:
- ((QString *)(registers[instr->cleanup.reg].typeDataPtr()))->~QString();
+ registers[instr->cleanup.reg].getstringptr()->~QString();
+ break;
+
+ case Instr::CleanupUrl:
+ registers[instr->cleanup.reg].geturlptr()->~QUrl();
break;
case Instr::Fetch:
@@ -815,6 +834,14 @@ void QmlBindingVME::run(const char *programData, Config *config,
}
break;
+ case Instr::ConvertGenericToUrl:
+ {
+ int type = registers[instr->genericunaryop.srcType].getint();
+ void *regPtr = registers[instr->genericunaryop.output].typeDataPtr();
+ new (regPtr) QUrl(toUrl(registers + instr->genericunaryop.src, type, context));
+ }
+ break;
+
default:
qFatal("EEK");
break;
@@ -828,6 +855,11 @@ void QmlBindingVME::dump(const QByteArray &programData)
{
const Program *program = (const Program *)programData.constData();
+ qWarning() << "Program.bindings:" << program->bindings;
+ qWarning() << "Program.dataLength:" << program->dataLength;
+ qWarning() << "Program.subscriptions:" << program->subscriptions;
+ qWarning() << "Program.indentifiers:" << program->identifiers;
+
int count = (programData.size() - sizeof(Program) - program->dataLength) / sizeof(Instr);
const Instr *instr = program->instructions();
@@ -837,9 +869,6 @@ void QmlBindingVME::dump(const QByteArray &programData)
case Instr::Noop:
qWarning().nospace() << "Noop";
break;
- case Instr::Init:
- qWarning().nospace() << "Init" << "\t\t\t" << instr->init.subscriptions << "\t" << instr->init.identifiers;
- break;
case Instr::Subscribe:
qWarning().nospace() << "Subscribe" << "\t\t" << instr->subscribe.offset << "\t" << instr->subscribe.reg << "\t" << instr->subscribe.index;
break;
@@ -903,9 +932,15 @@ void QmlBindingVME::dump(const QByteArray &programData)
case Instr::NewString:
qWarning().nospace() << "NewString" << "\t\t" << instr->construct.reg;
break;
+ case Instr::NewUrl:
+ qWarning().nospace() << "NewUrl" << "\t\t\t" << instr->construct.reg;
+ break;
case Instr::CleanupString:
qWarning().nospace() << "CleanupString" << "\t\t" << instr->cleanup.reg << "\t" << instr->cleanup.typeReg;
break;
+ case Instr::CleanupUrl:
+ qWarning().nospace() << "CleanupUrl" << "\t\t" << instr->cleanup.reg << "\t" << instr->cleanup.typeReg;
+ break;
case Instr::Fetch:
qWarning().nospace() << "Fetch" << "\t\t\t" << instr->fetch.output << "\t" << instr->fetch.index << "\t" << instr->fetch.objectReg;
break;
@@ -948,6 +983,9 @@ void QmlBindingVME::dump(const QByteArray &programData)
case Instr::ConvertGenericToString:
qWarning().nospace() << "ConvertGenericToString" << "\t" << instr->genericunaryop.output << "\t" << instr->genericunaryop.src << "\t" << instr->genericunaryop.srcType;
break;
+ case Instr::ConvertGenericToUrl:
+ qWarning().nospace() << "ConvertGenericToUrl" << "\t" << instr->genericunaryop.output << "\t" << instr->genericunaryop.src << "\t" << instr->genericunaryop.srcType;
+ break;
default:
qWarning().nospace() << "Unknown";
break;
@@ -957,18 +995,43 @@ void QmlBindingVME::dump(const QByteArray &programData)
}
}
-void QmlBindingCompiler::reset()
+/*!
+Clear the state associated with attempting to compile a specific binding.
+This does not clear the global "commited binding" states.
+*/
+void QmlBindingCompilerPrivate::resetInstanceState()
{
registers = 0;
- strings = 0;
- data.clear();
+ registerCleanups.clear();
+ strings = committed.strings;
+ data = committed.data;
+ usedSubscriptionIds.clear();
subscriptionSet.clear();
+ subscriptionIds = committed.subscriptionIds;
bytecode.clear();
}
-bool QmlBindingCompiler::compile(QmlJS::AST::Node *node)
+/*!
+Mark the last compile as successful, and add it to the "committed data"
+section.
+
+Returns the index for the committed binding.
+*/
+int QmlBindingCompilerPrivate::commitCompile()
+{
+ int rv = committed.count();
+ committed.offsets << committed.bytecode.count();
+ committed.dependencies << usedSubscriptionIds;
+ committed.bytecode << bytecode;
+ committed.data = data;
+ committed.strings = strings;
+ committed.subscriptionIds = subscriptionIds;
+ return rv;
+}
+
+bool QmlBindingCompilerPrivate::compile(QmlJS::AST::Node *node)
{
- reset();
+ resetInstanceState();
Result type;
@@ -979,18 +1042,13 @@ bool QmlBindingCompiler::compile(QmlJS::AST::Node *node)
if (subscriptionSet.count() > 0xFFFF ||
strings > 0xFFFF)
return false;
-
- Instr init;
- init.type = Instr::Init;
- init.init.subscriptions = subscriptionIds.count();
- init.init.identifiers = strings;
- bytecode.prepend(init);
}
if (type.unknownType) {
if (destination->type != QMetaType::QReal &&
destination->type != QVariant::String &&
- destination->type != QMetaType::Bool)
+ destination->type != QMetaType::Bool &&
+ destination->type != QVariant::Url)
return false;
int convertReg = acquireReg();
@@ -1016,6 +1074,13 @@ bool QmlBindingCompiler::compile(QmlJS::AST::Node *node)
convert.genericunaryop.src = type.reg;
convert.genericunaryop.srcType = 2; // XXX
bytecode << convert;
+ } else if (destination->type == QVariant::Url) {
+ Instr convert;
+ convert.type = Instr::ConvertGenericToUrl;
+ convert.genericunaryop.output = convertReg;
+ convert.genericunaryop.src = type.reg;
+ convert.genericunaryop.srcType = 2; // XXX
+ bytecode << convert;
}
Instr cleanup;
@@ -1037,6 +1102,12 @@ bool QmlBindingCompiler::compile(QmlJS::AST::Node *node)
cleanup.cleanup.reg = convertReg;
cleanup.cleanup.typeReg = -1;
bytecode << cleanup;
+ } else if (destination->type == QVariant::Url) {
+ Instr cleanup;
+ cleanup.type = Instr::CleanupUrl;
+ cleanup.cleanup.reg = convertReg;
+ cleanup.cleanup.typeReg = -1;
+ bytecode << cleanup;
}
releaseReg(convertReg);
@@ -1094,7 +1165,7 @@ bool QmlBindingCompiler::compile(QmlJS::AST::Node *node)
}
}
-bool QmlBindingCompiler::parseExpression(QmlJS::AST::Node *node, Result &type)
+bool QmlBindingCompilerPrivate::parseExpression(QmlJS::AST::Node *node, Result &type)
{
while (node->kind == AST::Node::Kind_NestedExpression)
node = static_cast<AST::NestedExpression *>(node)->expression;
@@ -1115,13 +1186,13 @@ bool QmlBindingCompiler::parseExpression(QmlJS::AST::Node *node, Result &type)
return true;
}
-bool QmlBindingCompiler::tryName(QmlJS::AST::Node *node)
+bool QmlBindingCompilerPrivate::tryName(QmlJS::AST::Node *node)
{
return node->kind == AST::Node::Kind_IdentifierExpression ||
node->kind == AST::Node::Kind_FieldMemberExpression;
}
-bool QmlBindingCompiler::parseName(AST::Node *node, Result &type)
+bool QmlBindingCompilerPrivate::parseName(AST::Node *node, Result &type)
{
QStringList nameParts;
if (!buildName(nameParts, node))
@@ -1179,11 +1250,12 @@ bool QmlBindingCompiler::parseName(AST::Node *node, Result &type)
attach.attached.index = attachType->index();
bytecode << attach;
+ subscribeName << contextName();
+ subscribeName << QLatin1String("$$$ATTACH_") + name;
+
absType = 0;
type.metaObject = attachType->attachedPropertiesType();
- subscribeName << QLatin1String("$$$ATTACH_") + name;
-
continue;
} else if (ids.contains(name)) {
QmlParser::Object *idObject = ids.value(name);
@@ -1240,7 +1312,7 @@ bool QmlBindingCompiler::parseName(AST::Node *node, Result &type)
instr.load.reg = reg;
bytecode << instr;
- subscribeName << QLatin1String("$$$Scope");
+ subscribeName << contextName();
subscribeName << name;
fetch(type, context->metaObject(), reg, d0Idx, subscribeName);
@@ -1251,7 +1323,7 @@ bool QmlBindingCompiler::parseName(AST::Node *node, Result &type)
instr.load.reg = reg;
bytecode << instr;
- subscribeName << QLatin1String("$$$Root");
+ subscribeName << QLatin1String("$$$ROOT");
subscribeName << name;
fetch(type, component->metaObject(), reg, d1Idx, subscribeName);
@@ -1348,7 +1420,7 @@ bool QmlBindingCompiler::parseName(AST::Node *node, Result &type)
return true;
}
-bool QmlBindingCompiler::tryArith(QmlJS::AST::Node *node)
+bool QmlBindingCompilerPrivate::tryArith(QmlJS::AST::Node *node)
{
if (node->kind != AST::Node::Kind_BinaryExpression)
return false;
@@ -1361,7 +1433,7 @@ bool QmlBindingCompiler::tryArith(QmlJS::AST::Node *node)
return false;
}
-bool QmlBindingCompiler::parseArith(QmlJS::AST::Node *node, Result &type)
+bool QmlBindingCompilerPrivate::parseArith(QmlJS::AST::Node *node, Result &type)
{
AST::BinaryExpression *expression = static_cast<AST::BinaryExpression *>(node);
@@ -1426,7 +1498,7 @@ bool QmlBindingCompiler::parseArith(QmlJS::AST::Node *node, Result &type)
return true;
}
-bool QmlBindingCompiler::tryLogic(QmlJS::AST::Node *node)
+bool QmlBindingCompilerPrivate::tryLogic(QmlJS::AST::Node *node)
{
if (node->kind != AST::Node::Kind_BinaryExpression)
return false;
@@ -1440,7 +1512,7 @@ bool QmlBindingCompiler::tryLogic(QmlJS::AST::Node *node)
return false;
}
-bool QmlBindingCompiler::parseLogic(QmlJS::AST::Node *node, Result &type)
+bool QmlBindingCompilerPrivate::parseLogic(QmlJS::AST::Node *node, Result &type)
{
AST::BinaryExpression *expression = static_cast<AST::BinaryExpression *>(node);
@@ -1495,12 +1567,12 @@ bool QmlBindingCompiler::parseLogic(QmlJS::AST::Node *node, Result &type)
return true;
}
-bool QmlBindingCompiler::tryConditional(QmlJS::AST::Node *node)
+bool QmlBindingCompilerPrivate::tryConditional(QmlJS::AST::Node *node)
{
return (node->kind == AST::Node::Kind_ConditionalExpression);
}
-bool QmlBindingCompiler::parseConditional(QmlJS::AST::Node *node, Result &type)
+bool QmlBindingCompilerPrivate::parseConditional(QmlJS::AST::Node *node, Result &type)
{
AST::ConditionalExpression *expression = static_cast<AST::ConditionalExpression *>(node);
@@ -1563,14 +1635,14 @@ bool QmlBindingCompiler::parseConditional(QmlJS::AST::Node *node, Result &type)
return true;
}
-bool QmlBindingCompiler::tryConstant(QmlJS::AST::Node *node)
+bool QmlBindingCompilerPrivate::tryConstant(QmlJS::AST::Node *node)
{
return node->kind == AST::Node::Kind_TrueLiteral ||
node->kind == AST::Node::Kind_FalseLiteral ||
node->kind == AST::Node::Kind_NumericLiteral;
}
-bool QmlBindingCompiler::parseConstant(QmlJS::AST::Node *node, Result &type)
+bool QmlBindingCompilerPrivate::parseConstant(QmlJS::AST::Node *node, Result &type)
{
type.metaObject = 0;
type.type = -1;
@@ -1605,7 +1677,7 @@ bool QmlBindingCompiler::parseConstant(QmlJS::AST::Node *node, Result &type)
}
}
-bool QmlBindingCompiler::buildName(QStringList &name,
+bool QmlBindingCompilerPrivate::buildName(QStringList &name,
QmlJS::AST::Node *node)
{
if (node->kind == AST::Node::Kind_IdentifierExpression) {
@@ -1626,7 +1698,7 @@ bool QmlBindingCompiler::buildName(QStringList &name,
}
-bool QmlBindingCompiler::fetch(Result &rv, const QMetaObject *mo, int reg, int idx, const QStringList &subName)
+bool QmlBindingCompilerPrivate::fetch(Result &rv, const QMetaObject *mo, int reg, int idx, const QStringList &subName)
{
QMetaProperty prop = mo->property(idx);
rv.metaObject = 0;
@@ -1684,12 +1756,12 @@ bool QmlBindingCompiler::fetch(Result &rv, const QMetaObject *mo, int reg, int i
return true;
}
-void QmlBindingCompiler::registerCleanup(int reg, int cleanup, int cleanupType)
+void QmlBindingCompilerPrivate::registerCleanup(int reg, int cleanup, int cleanupType)
{
registerCleanups.insert(reg, qMakePair(cleanup, cleanupType));
}
-int QmlBindingCompiler::acquireReg(int cleanup, int cleanupType)
+int QmlBindingCompilerPrivate::acquireReg(int cleanup, int cleanupType)
{
for (int ii = 0; ii < 32; ++ii) {
if (!(registers & (1 << ii))) {
@@ -1704,7 +1776,7 @@ int QmlBindingCompiler::acquireReg(int cleanup, int cleanupType)
return -1;
}
-void QmlBindingCompiler::releaseReg(int reg)
+void QmlBindingCompilerPrivate::releaseReg(int reg)
{
Q_ASSERT(reg >= 0 && reg <= 31);
@@ -1722,7 +1794,7 @@ void QmlBindingCompiler::releaseReg(int reg)
registers &= ~mask;
}
-int QmlBindingCompiler::registerString(const QString &string)
+int QmlBindingCompilerPrivate::registerString(const QString &string)
{
Q_ASSERT(!string.isEmpty());
@@ -1741,7 +1813,7 @@ int QmlBindingCompiler::registerString(const QString &string)
return strings - 1;
}
-bool QmlBindingCompiler::subscription(const QStringList &sub, Result *result)
+bool QmlBindingCompilerPrivate::subscription(const QStringList &sub, Result *result)
{
QString str = sub.join(QLatin1String("."));
result->subscriptionSet.insert(str);
@@ -1754,12 +1826,13 @@ bool QmlBindingCompiler::subscription(const QStringList &sub, Result *result)
}
}
-int QmlBindingCompiler::subscriptionIndex(const QStringList &sub)
+int QmlBindingCompilerPrivate::subscriptionIndex(const QStringList &sub)
{
QString str = sub.join(QLatin1String("."));
QHash<QString, int>::ConstIterator iter = subscriptionIds.find(str);
if (iter == subscriptionIds.end())
iter = subscriptionIds.insert(str, subscriptionIds.count());
+ usedSubscriptionIds.insert(*iter);
return *iter;
}
@@ -1767,7 +1840,7 @@ int QmlBindingCompiler::subscriptionIndex(const QStringList &sub)
Returns true if lhs contains no subscriptions that aren't also in base or rhs AND
rhs contains no subscriptions that aren't also in base or lhs.
*/
-bool QmlBindingCompiler::subscriptionNeutral(const QSet<QString> &base,
+bool QmlBindingCompilerPrivate::subscriptionNeutral(const QSet<QString> &base,
const QSet<QString> &lhs,
const QSet<QString> &rhs)
{
@@ -1781,5 +1854,118 @@ bool QmlBindingCompiler::subscriptionNeutral(const QSet<QString> &base,
return difflhs.isEmpty();
}
+
+
+QmlBindingCompiler::QmlBindingCompiler()
+: d(new QmlBindingCompilerPrivate)
+{
+}
+
+QmlBindingCompiler::~QmlBindingCompiler()
+{
+ delete d; d = 0;
+}
+
+/*
+Returns true if any bindings were compiled.
+*/
+bool QmlBindingCompiler::isValid() const
+{
+ return !d->committed.bytecode.isEmpty();
+}
+
+/*
+-1 on failure, otherwise the binding index to use.
+*/
+int QmlBindingCompiler::compile(const QmlBasicScript::Expression &expression,
+ QmlEnginePrivate *engine)
+{
+ if (!expression.expression.asAST()) return false;
+
+ d->context = expression.context;
+ d->component = expression.component;
+ d->destination = expression.property;
+ d->ids = expression.ids;
+ d->imports = expression.imports;
+ d->engine = engine;
+
+ if (d->compile(expression.expression.asAST())) {
+ return d->commitCompile();
+ } else {
+ return -1;
+ }
+}
+
+
+QByteArray QmlBindingCompilerPrivate::buildSignalTable() const
+{
+ QHash<int, QList<int> > table;
+
+ for (int ii = 0; ii < committed.count(); ++ii) {
+ const QSet<int> &deps = committed.dependencies.at(ii);
+ for (QSet<int>::ConstIterator iter = deps.begin(); iter != deps.end(); ++iter)
+ table[*iter].append(ii);
+ }
+
+ QVector<quint32> header;
+ QVector<quint32> data;
+ for (int ii = 0; ii < committed.subscriptionIds.count(); ++ii) {
+ header.append(committed.subscriptionIds.count() + data.count());
+ const QList<int> &bindings = table[ii];
+ data.append(bindings.count());
+ for (int jj = 0; jj < bindings.count(); ++jj)
+ data.append(bindings.at(jj));
+ }
+ header << data;
+
+ return QByteArray((const char *)header.constData(), header.count() * sizeof(quint32));
+}
+
+/*
+Returns the compiled program.
+*/
+QByteArray QmlBindingCompiler::program() const
+{
+ QByteArray programData;
+
+ if (isValid()) {
+ Program prog;
+ prog.bindings = d->committed.count();
+
+ QVector<Instr> bytecode;
+ Instr skip;
+ skip.type = Instr::Skip;
+ skip.skip.reg = -1;
+ for (int ii = 0; ii < d->committed.count(); ++ii) {
+ skip.skip.count = d->committed.count() - ii - 1;
+ skip.skip.count+= d->committed.offsets.at(ii);
+ bytecode << skip;
+ }
+ bytecode << d->committed.bytecode;
+
+ QByteArray data = d->committed.data;
+ while (data.count() % 4) data.append('\0');
+ prog.signalTableOffset = data.count();
+ data += d->buildSignalTable();
+
+ prog.dataLength = 4 * ((data.size() + 3) / 4);
+ prog.subscriptions = d->committed.subscriptionIds.count();
+ prog.identifiers = d->committed.strings;
+ int size = sizeof(Program) + bytecode.count() * sizeof(Instr);
+ size += prog.dataLength;
+
+ programData.resize(size);
+ memcpy(programData.data(), &prog, sizeof(Program));
+ if (prog.dataLength)
+ memcpy((char *)((Program *)programData.data())->data(), data.constData(),
+ data.size());
+ memcpy((char *)((Program *)programData.data())->instructions(), bytecode.constData(),
+ bytecode.count() * sizeof(Instr));
+ }
+
+ return programData;
+}
+
+
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlbindingvme_p.h b/src/declarative/qml/qmlbindingvme_p.h
index a01c308..de73037 100644
--- a/src/declarative/qml/qmlbindingvme_p.h
+++ b/src/declarative/qml/qmlbindingvme_p.h
@@ -80,13 +80,34 @@ public:
QScriptDeclarativeClass::PersistentIdentifier *identifiers;
};
- static QByteArray compile(const QmlBasicScript::Expression &, QmlEnginePrivate *);
- static void run(const char *program,
+ static void init(const char *program, Config *config,
+ quint32 **sigTable, quint32 *bindingCount);
+ static void run(const char *program, int instr,
Config *config, QmlContextPrivate *context,
QObject **scopes, QObject **outputs);
static void dump(const QByteArray &);
};
+class QmlBindingCompilerPrivate;
+class QmlBindingCompiler
+{
+public:
+ QmlBindingCompiler();
+ ~QmlBindingCompiler();
+
+ // Returns true if bindings were compiled
+ bool isValid() const;
+
+ // -1 on failure, otherwise the binding index to use
+ int compile(const QmlBasicScript::Expression &, QmlEnginePrivate *);
+
+ // Returns the compiled program
+ QByteArray program() const;
+
+private:
+ QmlBindingCompilerPrivate *d;
+};
+
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp
index 53ea18e..aeda573 100644
--- a/src/declarative/qml/qmlcompiler.cpp
+++ b/src/declarative/qml/qmlcompiler.cpp
@@ -643,6 +643,10 @@ void QmlCompiler::compileTree(Object *tree)
init.init.bindingsSize = compileState.bindings.count();
init.init.parserStatusSize = compileState.parserStatusCount;
init.init.contextCache = genContextCache();
+ if (compileState.compiledBindingData.isEmpty())
+ init.init.compiledBinding = -1;
+ else
+ init.init.compiledBinding = output->indexForByteArray(compileState.compiledBindingData);
output->bytecode << init;
genObject(tree);
@@ -1010,6 +1014,10 @@ void QmlCompiler::genComponent(QmlParser::Object *obj)
init.init.bindingsSize = compileState.bindings.count();
init.init.parserStatusSize = compileState.parserStatusCount;
init.init.contextCache = genContextCache();
+ if (compileState.compiledBindingData.isEmpty())
+ init.init.compiledBinding = -1;
+ else
+ init.init.compiledBinding = output->indexForByteArray(compileState.compiledBindingData);
init.line = obj->location.start.line;
output->bytecode << init;
@@ -2029,6 +2037,14 @@ bool QmlCompiler::buildPropertyLiteralAssignment(QmlParser::Property *prop,
if (v->value.isScript()) {
+ //optimization for <Type>.<EnumValue> enum assignments
+ bool isEnumAssignment = false;
+ COMPILE_CHECK(testQualifiedEnumAssignment(obj->metaObject()->property(prop->index), obj, v, &isEnumAssignment));
+ if (isEnumAssignment) {
+ v->type = Value::Literal;
+ return true;
+ }
+
COMPILE_CHECK(buildBinding(v, prop, ctxt));
v->type = Value::PropertyBinding;
@@ -2043,6 +2059,50 @@ bool QmlCompiler::buildPropertyLiteralAssignment(QmlParser::Property *prop,
return true;
}
+bool QmlCompiler::testQualifiedEnumAssignment(const QMetaProperty &prop,
+ QmlParser::Object *obj,
+ QmlParser::Value *v,
+ bool *isAssignment)
+{
+ *isAssignment = false;
+ if (!prop.isEnumType())
+ return true;
+
+ if (!prop.isWritable())
+ COMPILE_EXCEPTION(v, QCoreApplication::translate("QmlCompiler","Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop.name())));
+
+ QString string = v->value.asString();
+ if (!string.at(0).isUpper())
+ return true;
+
+ QStringList parts = string.split(QLatin1Char('.'));
+ if (parts.count() != 2)
+ return true;
+
+ QString typeName = parts.at(0);
+ QmlType *type = 0;
+ QmlEnginePrivate::get(engine)->resolveType(unit->imports, typeName.toUtf8(),
+ &type, 0, 0, 0, 0);
+
+ if (!type || obj->typeName != type->qmlTypeName())
+ return true;
+
+ QString enumValue = parts.at(1);
+ int value;
+ if (prop.isFlagType()) {
+ value = prop.enumerator().keysToValue(enumValue.toUtf8().constData());
+ } else
+ value = prop.enumerator().keyToValue(enumValue.toUtf8().constData());
+ if (value == -1)
+ return true;
+
+ v->type = Value::Literal;
+ v->value = QmlParser::Variant(enumValue);
+ *isAssignment = true;
+
+ return true;
+}
+
// Ensures that the dynamic meta specification on obj is valid
bool QmlCompiler::checkDynamicMeta(QmlParser::Object *obj)
{
@@ -2130,6 +2190,14 @@ bool QmlCompiler::buildDynamicMeta(QmlParser::Object *obj, DynamicMetaMode mode)
newClassName.append("_QML_");
int idx = classIndexCounter()->fetchAndAddRelaxed(1);
newClassName.append(QByteArray::number(idx));
+ if (compileState.root == obj) {
+ QString path = output->url.path();
+ int lastSlash = path.lastIndexOf(QLatin1Char('/'));
+ if (lastSlash > -1) {
+ QString nameBase = path.mid(lastSlash + 1, path.length()-lastSlash-5);
+ newClassName = nameBase.toUtf8() + "_QMLTYPE_" + QByteArray::number(idx);
+ }
+ }
QMetaObjectBuilder builder;
builder.setClassName(newClassName);
@@ -2344,10 +2412,10 @@ bool QmlCompiler::compileAlias(QMetaObjectBuilder &builder,
QStringList alias = astNodeToStringList(node);
if (alias.count() != 1 && alias.count() != 2)
- COMPILE_EXCEPTION(prop.defaultValue, QCoreApplication::translate("QmlCompiler","Invalid alias location"));
+ COMPILE_EXCEPTION(prop.defaultValue, QCoreApplication::translate("QmlCompiler","Invalid alias reference. An alias reference must be specified as <id> or <id>.<property>"));
if (!compileState.ids.contains(alias.at(0)))
- COMPILE_EXCEPTION(prop.defaultValue, QCoreApplication::translate("QmlCompiler","Invalid alias location"));
+ COMPILE_EXCEPTION(prop.defaultValue, QCoreApplication::translate("QmlCompiler","Invalid alias reference. Unable to find id \"%1\"").arg(alias.at(0)));
Object *idObject = compileState.ids[alias.at(0)];
@@ -2423,7 +2491,7 @@ void QmlCompiler::genBindingAssignment(QmlParser::Value *binding,
if (ref.dataType == BindingReference::Experimental) {
QmlInstruction store;
store.type = QmlInstruction::StoreCompiledBinding;
- store.assignBinding.value = output->indexForByteArray(ref.compiledData);
+ store.assignBinding.value = ref.compiledIndex;
store.assignBinding.context = ref.bindingContext.stack;
store.assignBinding.owner = ref.bindingContext.owner;
if (valueTypeProperty)
@@ -2529,6 +2597,8 @@ bool QmlCompiler::completeComponentBuild()
expr.component = compileState.root;
expr.ids = compileState.ids;
+ QmlBindingCompiler bindingCompiler;
+
for (QHash<QmlParser::Value*,BindingReference>::Iterator iter = compileState.bindings.begin(); iter != compileState.bindings.end(); ++iter) {
BindingReference &binding = *iter;
@@ -2541,15 +2611,15 @@ bool QmlCompiler::completeComponentBuild()
bs.compile(expr);
if (qmlExperimental() && (!bs.isValid() || (!bs.isSingleIdFetch() && !bs.isSingleContextProperty()))) {
-
- QByteArray qmvdata = QmlBindingVME::compile(expr, QmlEnginePrivate::get(engine));
- if (!qmvdata.isEmpty()) {
- qWarning() << expr.expression.asScript();
- QmlBindingVME::dump(qmvdata);
+ int index = bindingCompiler.compile(expr, QmlEnginePrivate::get(engine));
+ if (index != -1) {
+ qWarning() << "Accepted for optimization:" << qPrintable(expr.expression.asScript());
binding.dataType = BindingReference::Experimental;
- binding.compiledData = qmvdata;
+ binding.compiledIndex = index;
componentStat.optimizedBindings++;
continue;
+ } else {
+ qWarning() << "Rejected for optimization:" << qPrintable(expr.expression.asScript());
}
}
@@ -2599,6 +2669,11 @@ bool QmlCompiler::completeComponentBuild()
sizeof(quint32)));
}
+ if (bindingCompiler.isValid()) {
+ compileState.compiledBindingData = bindingCompiler.program();
+ QmlBindingVME::dump(compileState.compiledBindingData);
+ }
+
saveComponentState();
return true;
diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h
index d734a12..740d97c 100644
--- a/src/declarative/qml/qmlcompiler_p.h
+++ b/src/declarative/qml/qmlcompiler_p.h
@@ -219,6 +219,10 @@ private:
bool doesPropertyExist(QmlParser::Property *prop, QmlParser::Object *obj);
bool testLiteralAssignment(const QMetaProperty &prop,
QmlParser::Value *value);
+ bool testQualifiedEnumAssignment(const QMetaProperty &prop,
+ QmlParser::Object *obj,
+ QmlParser::Value *value,
+ bool *isAssignment);
enum DynamicMetaMode { IgnoreAliases, ResolveAliases, ForceCreation };
bool mergeDynamicMetaProperties(QmlParser::Object *obj);
bool buildDynamicMeta(QmlParser::Object *obj, DynamicMetaMode mode);
@@ -273,6 +277,8 @@ private:
enum DataType { QtScript, BasicScript, Experimental };
DataType dataType;
+ int compiledIndex;
+
QByteArray compiledData;
BindingContext bindingContext;
};
@@ -287,6 +293,8 @@ private:
int parserStatusCount;
int pushedProperties;
+ QByteArray compiledBindingData;
+
QHash<QmlParser::Value *, BindingReference> bindings;
QList<QmlParser::Object *> aliasingObjects;
QmlParser::Object *root;
diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp
index c3971ae..49bb59c 100644
--- a/src/declarative/qml/qmlcontext.cpp
+++ b/src/declarative/qml/qmlcontext.cpp
@@ -442,6 +442,38 @@ void QmlContext::setContextProperty(const QString &name, QObject *value)
}
}
+QVariant QmlContext::contextProperty(const QString &name) const
+{
+ Q_D(const QmlContext);
+ QVariant value;
+ int idx = -1;
+ if (d->propertyNames)
+ idx = d->propertyNames->value(name);
+
+ if (idx == -1) {
+ QByteArray utf8Name = name.toUtf8();
+ for (int ii = d->defaultObjects.count() - 1; ii >= 0; --ii) {
+ QObject *obj = d->defaultObjects.at(ii);
+ QmlDeclarativeData *data = QmlDeclarativeData::get(obj);
+ if (data && data->propertyCache) {
+ QmlPropertyCache::Data *property = data->propertyCache->property(name);
+ if (property)
+ value = obj->metaObject()->property(property->coreIndex).read(obj);
+ } else {
+ value = obj->property(utf8Name);
+ }
+ if (value.isValid())
+ break;
+ }
+ if (!value.isValid() && parentContext())
+ value = parentContext()->contextProperty(name);
+ } else {
+ value = d->propertyValues[idx];
+ }
+
+ return value;
+}
+
/*!
Resolves the URL \a src relative to the URL of the
containing component.
diff --git a/src/declarative/qml/qmlcontext.h b/src/declarative/qml/qmlcontext.h
index de1d092..7547004 100644
--- a/src/declarative/qml/qmlcontext.h
+++ b/src/declarative/qml/qmlcontext.h
@@ -75,6 +75,8 @@ public:
void setContextProperty(const QString &, QObject *);
void setContextProperty(const QString &, const QVariant &);
+ QVariant contextProperty(const QString &) const;
+
QUrl resolvedUrl(const QUrl &);
void setBaseUrl(const QUrl &);
diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp
index ad68c8f..6b66095 100644
--- a/src/declarative/qml/qmlengine.cpp
+++ b/src/declarative/qml/qmlengine.cpp
@@ -564,7 +564,7 @@ void QmlDeclarativeData::destroyed(QObject * /*object*/)
QmlAbstractBinding *next = binding->m_nextBinding;
binding->m_prevBinding = 0;
binding->m_nextBinding = 0;
- delete binding;
+ binding->destroy();
binding = next;
}
diff --git a/src/declarative/qml/qmlenginedebug.cpp b/src/declarative/qml/qmlenginedebug.cpp
index 6cb57b2..46490fb 100644
--- a/src/declarative/qml/qmlenginedebug.cpp
+++ b/src/declarative/qml/qmlenginedebug.cpp
@@ -285,6 +285,9 @@ QmlEngineDebugServer::objectData(QObject *object)
rv.objectType = lastSlash < 0 ? typeName : typeName.mid(lastSlash+1);
} else {
rv.objectType = QString::fromUtf8(object->metaObject()->className());
+ int marker = rv.objectType.indexOf(QLatin1String("_QMLTYPE_"));
+ if (marker != -1)
+ rv.objectType = rv.objectType.left(marker);
}
return rv;
diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h
index d06ac86..6e2b452 100644
--- a/src/declarative/qml/qmlinstruction_p.h
+++ b/src/declarative/qml/qmlinstruction_p.h
@@ -170,6 +170,7 @@ public:
int bindingsSize;
int parserStatusSize;
int contextCache;
+ int compiledBinding;
} init;
struct {
int type;
diff --git a/src/declarative/qml/qmlscriptparser.cpp b/src/declarative/qml/qmlscriptparser.cpp
index 35234ec..a24ef51 100644
--- a/src/declarative/qml/qmlscriptparser.cpp
+++ b/src/declarative/qml/qmlscriptparser.cpp
@@ -600,6 +600,9 @@ bool ProcessAST::visit(AST::UiPublicMember *node)
if (node->expression) { // default value
property.defaultValue = new Property;
property.defaultValue->parent = _stateStack.top().object;
+ property.defaultValue->location =
+ location(node->expression->firstSourceLocation(),
+ node->expression->lastSourceLocation());
Value *value = new Value;
value->location = location(node->expression->firstSourceLocation(),
node->expression->lastSourceLocation());
diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp
index e4295a1..ae7bf51 100644
--- a/src/declarative/qml/qmlvme.cpp
+++ b/src/declarative/qml/qmlvme.cpp
@@ -161,6 +161,8 @@ QObject *QmlVME::run(QmlVMEStack<QObject *> &stack, QmlContext *ctxt,
int status = -1; //for dbus
QmlMetaProperty::WriteFlags flags = QmlMetaProperty::BypassInterceptor;
+ QmlOptimizedBindings *optimizedBindings = 0;
+
for (int ii = start; !isError() && ii < (start + count); ++ii) {
const QmlInstruction &instr = comp->bytecode.at(ii);
@@ -171,9 +173,10 @@ QObject *QmlVME::run(QmlVMEStack<QObject *> &stack, QmlContext *ctxt,
bindValues = QmlEnginePrivate::SimpleList<QmlAbstractBinding>(instr.init.bindingsSize);
if (instr.init.parserStatusSize)
parserStatus = QmlEnginePrivate::SimpleList<QmlParserStatus>(instr.init.parserStatusSize);
-
if (instr.init.contextCache != -1)
cp->setIdPropertyData(comp->contextCaches.at(instr.init.contextCache));
+ if (instr.init.compiledBinding != -1)
+ optimizedBindings = new QmlOptimizedBindings(datas.at(instr.init.compiledBinding).constData(), ctxt);
}
break;
@@ -619,13 +622,11 @@ QObject *QmlVME::run(QmlVMEStack<QObject *> &stack, QmlContext *ctxt,
if (stack.count() == 1 && bindingSkipList.testBit(property & 0xFFFF))
break;
- const char *data = datas.at(instr.assignBinding.value).constData();
-
- QmlBinding_Basic *bind =
- new QmlBinding_Basic(target, property, data, comp, scope, ctxt);
- bindValues.append(bind);
- bind->m_mePtr = &bindValues.values[bindValues.count - 1];
- bind->addToObject(target);
+ QmlAbstractBinding *binding =
+ optimizedBindings->configBinding(instr.assignBinding.value, target, scope, property);
+ bindValues.append(binding);
+ binding->m_mePtr = &bindValues.values[bindValues.count - 1];
+ binding->addToObject(target);
}
break;
@@ -894,6 +895,11 @@ QObject *QmlVME::run(QmlVMEStack<QObject *> &stack, QmlContext *ctxt,
}
}
+ if (optimizedBindings) {
+ optimizedBindings->release();
+ optimizedBindings = 0;
+ }
+
if (isError()) {
if (!stack.isEmpty()) {
delete stack.at(0);
diff --git a/src/declarative/util/qmllistmodel.cpp b/src/declarative/util/qmllistmodel.cpp
index f4317af..de6ee2e 100644
--- a/src/declarative/util/qmllistmodel.cpp
+++ b/src/declarative/util/qmllistmodel.cpp
@@ -421,6 +421,29 @@ QHash<int,QVariant> QmlListModel::data(int index, const QList<int> &roles) const
return rv;
}
+QVariant QmlListModel::data(int index, int role) const
+{
+ checkRoles();
+ QVariant rv;
+ if (index >= count())
+ 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;
+}
+
/*!
\qmlproperty int ListModel::count
The number of data entries in the model.
diff --git a/src/declarative/util/qmllistmodel_p.h b/src/declarative/util/qmllistmodel_p.h
index 2a1a57d..47236d0 100644
--- a/src/declarative/util/qmllistmodel_p.h
+++ b/src/declarative/util/qmllistmodel_p.h
@@ -72,6 +72,7 @@ public:
virtual QString toString(int role) const;
virtual int count() const;
virtual QHash<int,QVariant> data(int index, const QList<int> &roles = (QList<int>())) const;
+ virtual QVariant data(int index, int role) const;
Q_INVOKABLE void clear();
Q_INVOKABLE void remove(int index);
diff --git a/src/declarative/util/qmlstate.cpp b/src/declarative/util/qmlstate.cpp
index 98cc0b6..1749c3a 100644
--- a/src/declarative/util/qmlstate.cpp
+++ b/src/declarative/util/qmlstate.cpp
@@ -444,10 +444,10 @@ void QmlState::apply(QmlStateGroup *group, QmlTransition *trans, QmlState *rever
if (stateChangeDebug()) {
foreach(const Action &action, applyList) {
if (action.event)
- qWarning() << " Action event:" << action.event;
+ qWarning() << " Action event:" << action.event->typeName();
else
qWarning() << " Action:" << action.property.object()
- << action.property.name() << action.toValue;
+ << action.property.name() << action.fromValue << action.toValue;
}
}
diff --git a/src/declarative/util/qmlxmllistmodel.cpp b/src/declarative/util/qmlxmllistmodel.cpp
index 46ef739..d31fadf 100644
--- a/src/declarative/util/qmlxmllistmodel.cpp
+++ b/src/declarative/util/qmlxmllistmodel.cpp
@@ -462,6 +462,13 @@ QHash<int,QVariant> QmlXmlListModel::data(int index, const QList<int> &roles) co
return rv;
}
+QVariant QmlXmlListModel::data(int index, int role) const
+{
+ Q_D(const QmlXmlListModel);
+ int roleIndex = d->roles.indexOf(role);
+ return (roleIndex == -1) ? QVariant() : d->data.at(roleIndex).at(index);
+}
+
/*!
\qmlproperty int XmlListModel::count
The number of data entries in the model.
diff --git a/src/declarative/util/qmlxmllistmodel_p.h b/src/declarative/util/qmlxmllistmodel_p.h
index 67fc751..e4b8cab 100644
--- a/src/declarative/util/qmlxmllistmodel_p.h
+++ b/src/declarative/util/qmlxmllistmodel_p.h
@@ -79,6 +79,7 @@ public:
~QmlXmlListModel();
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;
diff --git a/tools/qmlviewer/qmlfolderlistmodel.cpp b/tools/qmlviewer/qmlfolderlistmodel.cpp
index 4f33f31..35c672d 100644
--- a/tools/qmlviewer/qmlfolderlistmodel.cpp
+++ b/tools/qmlviewer/qmlfolderlistmodel.cpp
@@ -142,6 +142,20 @@ QHash<int,QVariant> QmlFolderListModel::data(int index, const QList<int> &roles)
return folderData;
}
+QVariant QmlFolderListModel::data(int index, int role) const
+{
+ QVariant rv;
+ QModelIndex modelIndex = d->model.index(index, 0, d->folderIndex);
+ if (modelIndex.isValid()) {
+ if (role == QDirModel::FileNameRole)
+ rv = d->model.data(modelIndex, QDirModel::FileNameRole);
+ else if (role == QDirModel::FilePathRole)
+ rv = QUrl::fromLocalFile(d->model.data(modelIndex, QDirModel::FilePathRole).toString());
+ }
+
+ return rv;
+}
+
int QmlFolderListModel::count() const
{
return d->count;
diff --git a/tools/qmlviewer/qmlfolderlistmodel.h b/tools/qmlviewer/qmlfolderlistmodel.h
index cbee8c7..7357954 100644
--- a/tools/qmlviewer/qmlfolderlistmodel.h
+++ b/tools/qmlviewer/qmlfolderlistmodel.h
@@ -68,6 +68,7 @@ public:
~QmlFolderListModel();
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;