summaryrefslogtreecommitdiffstats
path: root/src/declarative
diff options
context:
space:
mode:
authorBea Lam <bea.lam@nokia.com>2009-10-28 05:55:59 (GMT)
committerBea Lam <bea.lam@nokia.com>2009-10-28 05:55:59 (GMT)
commit55a3fcd7b2fe9cd43f3c0c20d75aaef056a05c5b (patch)
treea659b792178e6ee620f3d4c4218e518e4b158f64 /src/declarative
parentf0f2941d6dccd4bd402861c01797bb210c516962 (diff)
parent44be8cc3bb1aebd47f75dcf9cae54884322e1955 (diff)
downloadQt-55a3fcd7b2fe9cd43f3c0c20d75aaef056a05c5b.zip
Qt-55a3fcd7b2fe9cd43f3c0c20d75aaef056a05c5b.tar.gz
Qt-55a3fcd7b2fe9cd43f3c0c20d75aaef056a05c5b.tar.bz2
Merge branch 'kinetic-declarativeui' of scm.dev.nokia.troll.no:qt/kinetic into kinetic-declarativeui
Diffstat (limited to 'src/declarative')
-rw-r--r--src/declarative/fx/qfxflickable.cpp26
-rw-r--r--src/declarative/fx/qfxitem.cpp2
-rw-r--r--src/declarative/fx/qfxlistview.cpp152
-rw-r--r--src/declarative/fx/qfxlistview.h8
-rw-r--r--src/declarative/fx/qfxpositioners.cpp20
-rw-r--r--src/declarative/fx/qfxrepeater.cpp12
-rw-r--r--src/declarative/fx/qfxtext.cpp22
-rw-r--r--src/declarative/fx/qfxtext.h15
-rw-r--r--src/declarative/fx/qfxtext_p.h4
-rw-r--r--src/declarative/qml/qmlbinding.cpp64
-rw-r--r--src/declarative/qml/qmlbinding_p.h6
-rw-r--r--src/declarative/qml/qmlboundsignal.cpp5
-rw-r--r--src/declarative/qml/qmlcompiler.cpp1
-rw-r--r--src/declarative/qml/qmlcomponent.cpp17
-rw-r--r--src/declarative/qml/qmlcontext.cpp7
-rw-r--r--src/declarative/qml/qmlengine.cpp5
-rw-r--r--src/declarative/qml/qmlengine_p.h5
-rw-r--r--src/declarative/qml/qmlerror.cpp42
-rw-r--r--src/declarative/qml/qmlerror.h2
-rw-r--r--src/declarative/qml/qmlexpression.cpp56
-rw-r--r--src/declarative/qml/qmlexpression.h5
-rw-r--r--src/declarative/qml/qmlexpression_p.h6
-rw-r--r--src/declarative/qml/qmlvmemetaobject.cpp6
-rw-r--r--src/declarative/util/qmleasefollow.cpp3
-rw-r--r--src/declarative/util/qmlspringfollow.cpp9
25 files changed, 385 insertions, 115 deletions
diff --git a/src/declarative/fx/qfxflickable.cpp b/src/declarative/fx/qfxflickable.cpp
index 92e79dd..659193d 100644
--- a/src/declarative/fx/qfxflickable.cpp
+++ b/src/declarative/fx/qfxflickable.cpp
@@ -57,6 +57,8 @@ QT_BEGIN_NAMESPACE
static const int DragThreshold = 8;
static const int FlickThreshold = 20;
+// Really slow flicks can be annoying.
+static const int minimumFlickVelocity = 200;
class QFxFlickableVisibleArea : public QObject
{
@@ -183,6 +185,8 @@ void QFxFlickablePrivate::flickX(qreal velocity)
{
Q_Q(QFxFlickable);
qreal maxDistance = -1;
+ if (qAbs(velocity) < minimumFlickVelocity) // Minimum velocity to avoid annoyingly slow flicks.
+ velocity = velocity < 0 ? -minimumFlickVelocity : minimumFlickVelocity;
// -ve velocity means list is moving up
if (velocity > 0) {
if (_moveX.value() < q->minXExtent())
@@ -686,8 +690,8 @@ void QFxFlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent *event)
if (rejectX) velocityX = 0;
if (moved) {
- q->viewportMoved();
q->movementStarting();
+ q->viewportMoved();
}
lastPos = event->pos();
@@ -707,15 +711,23 @@ void QFxFlickablePrivate::handleMouseReleaseEvent(QGraphicsSceneMouseEvent *even
}
vTime = timeline.time();
- if (qAbs(velocityY) > 10 && qAbs(event->pos().y() - pressPos.y()) > FlickThreshold)
- flickY(velocityY);
- else
+ if (qAbs(velocityY) > 10 && qAbs(event->pos().y() - pressPos.y()) > FlickThreshold) {
+ qreal velocity = velocityY;
+ if (qAbs(velocity) < minimumFlickVelocity) // Minimum velocity to avoid annoyingly slow flicks.
+ velocity = velocity < 0 ? -minimumFlickVelocity : minimumFlickVelocity;
+ flickY(velocity);
+ } else {
fixupY();
+ }
- if (qAbs(velocityX) > 10 && qAbs(event->pos().x() - pressPos.x()) > FlickThreshold)
- flickX(velocityX);
- else
+ if (qAbs(velocityX) > 10 && qAbs(event->pos().x() - pressPos.x()) > FlickThreshold) {
+ qreal velocity = velocityX;
+ if (qAbs(velocity) < minimumFlickVelocity) // Minimum velocity to avoid annoyingly slow flicks.
+ velocity = velocity < 0 ? -minimumFlickVelocity : minimumFlickVelocity;
+ flickX(velocity);
+ } else {
fixupX();
+ }
stealMouse = false;
lastPosTime = QTime();
diff --git a/src/declarative/fx/qfxitem.cpp b/src/declarative/fx/qfxitem.cpp
index e714494..7d60336 100644
--- a/src/declarative/fx/qfxitem.cpp
+++ b/src/declarative/fx/qfxitem.cpp
@@ -1199,7 +1199,7 @@ QFxKeysAttached *QFxKeysAttached::qmlAttachedProperties(QObject *obj)
/*!
\class QFxItem
- \brief QFxItem is the most basic of all visual items in QML.
+ \brief The QFxItem class provides the most basic of all visual items in QML.
All visual items in Qt Declarative inherit from QFxItem. Although QFxItem
has no visual appearance, it defines all the properties that are
diff --git a/src/declarative/fx/qfxlistview.cpp b/src/declarative/fx/qfxlistview.cpp
index fbb91b1..1f1b97b 100644
--- a/src/declarative/fx/qfxlistview.cpp
+++ b/src/declarative/fx/qfxlistview.cpp
@@ -141,15 +141,15 @@ public:
}
~FxListItem() {}
- qreal position() const { return (view->orientation() == Qt::Vertical ? item->y() : item->x()); }
- int size() const { return (view->orientation() == Qt::Vertical ? item->height() : item->width()); }
+ qreal position() const { return (view->orientation() == QFxListView::Vertical ? item->y() : item->x()); }
+ int size() const { return (view->orientation() == QFxListView::Vertical ? item->height() : item->width()); }
qreal endPosition() const {
- return (view->orientation() == Qt::Vertical
+ return (view->orientation() == QFxListView::Vertical
? item->y() + (item->height() > 0 ? item->height() : 1)
: item->x() + (item->width() > 0 ? item->width() : 1)) - 1;
}
void setPosition(qreal pos) {
- if (view->orientation() == Qt::Vertical) {
+ if (view->orientation() == QFxListView::Vertical) {
item->setY(pos);
} else {
item->setX(pos);
@@ -170,7 +170,7 @@ class QFxListViewPrivate : public QFxFlickablePrivate
public:
QFxListViewPrivate()
- : model(0), currentItem(0), orient(Qt::Vertical)
+ : model(0), currentItem(0), orient(QFxListView::Vertical)
, visiblePos(0), visibleIndex(0)
, averageSize(100.0), currentIndex(-1), requestedIndex(-1)
, highlightRangeStart(0), highlightRangeEnd(0)
@@ -199,18 +199,18 @@ public:
qreal position() const {
Q_Q(const QFxListView);
- return orient == Qt::Vertical ? q->viewportY() : q->viewportX();
+ return orient == QFxListView::Vertical ? q->viewportY() : q->viewportX();
}
void setPosition(qreal pos) {
Q_Q(QFxListView);
- if (orient == Qt::Vertical)
+ if (orient == QFxListView::Vertical)
q->setViewportY(pos);
else
q->setViewportX(pos);
}
qreal size() const {
Q_Q(const QFxListView);
- return orient == Qt::Vertical ? q->height() : q->width();
+ return orient == QFxListView::Vertical ? q->height() : q->width();
}
qreal startPosition() const {
@@ -378,7 +378,7 @@ public:
QList<FxListItem*> visibleItems;
QHash<QFxItem*,int> unrequestedItems;
FxListItem *currentItem;
- Qt::Orientation orient;
+ QFxListView::Orientation orient;
int visiblePos;
int visibleIndex;
qreal averageSize;
@@ -454,7 +454,7 @@ FxListItem *QFxListViewPrivate::createItem(int modelIndex)
model->completeItem();
listItem->item->setZValue(1);
listItem->item->setParent(q->viewport());
- if (orient == Qt::Vertical)
+ if (orient == QFxListView::Vertical)
QObject::connect(listItem->item, SIGNAL(heightChanged()), q, SLOT(itemResized()));
else
QObject::connect(listItem->item, SIGNAL(widthChanged()), q, SLOT(itemResized()));
@@ -470,8 +470,8 @@ void QFxListViewPrivate::releaseItem(FxListItem *item)
if (!item)
return;
if (trackedItem == item) {
- const char *notifier1 = orient == Qt::Vertical ? SIGNAL(yChanged()) : SIGNAL(xChanged());
- const char *notifier2 = orient == Qt::Vertical ? SIGNAL(heightChanged()) : SIGNAL(widthChanged());
+ const char *notifier1 = orient == QFxListView::Vertical ? SIGNAL(yChanged()) : SIGNAL(xChanged());
+ const char *notifier2 = orient == QFxListView::Vertical ? SIGNAL(heightChanged()) : SIGNAL(widthChanged());
QObject::disconnect(trackedItem->item, notifier1, q, SLOT(trackedPositionChanged()));
QObject::disconnect(trackedItem->item, notifier2, q, SLOT(trackedPositionChanged()));
trackedItem = 0;
@@ -479,7 +479,7 @@ void QFxListViewPrivate::releaseItem(FxListItem *item)
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 (orient == Qt::Vertical)
+ if (orient == QFxListView::Vertical)
QObject::disconnect(item->item, SIGNAL(heightChanged()), q, SLOT(itemResized()));
else
QObject::disconnect(item->item, SIGNAL(widthChanged()), q, SLOT(itemResized()));
@@ -553,7 +553,7 @@ void QFxListViewPrivate::refill(qreal from, qreal to)
updateAverage();
if (!sectionExpression.isEmpty())
updateCurrentSection();
- if (orient == Qt::Vertical)
+ if (orient == QFxListView::Vertical)
q->setViewportHeight(endPosition() - startPosition());
else
q->setViewportWidth(endPosition() - startPosition());
@@ -597,7 +597,7 @@ void QFxListViewPrivate::updateUnrequestedPositions()
for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it) {
if (visibleItem(*it))
continue;
- if (orient == Qt::Vertical)
+ if (orient == QFxListView::Vertical)
it.key()->setY(positionAt(*it));
else
it.key()->setX(positionAt(*it));
@@ -613,8 +613,8 @@ void QFxListViewPrivate::updateTrackedItem()
FxListItem *oldTracked = trackedItem;
- const char *notifier1 = orient == Qt::Vertical ? SIGNAL(yChanged()) : SIGNAL(xChanged());
- const char *notifier2 = orient == Qt::Vertical ? SIGNAL(heightChanged()) : SIGNAL(widthChanged());
+ const char *notifier1 = orient == QFxListView::Vertical ? SIGNAL(yChanged()) : SIGNAL(xChanged());
+ const char *notifier2 = orient == QFxListView::Vertical ? SIGNAL(heightChanged()) : SIGNAL(widthChanged());
if (trackedItem && item != trackedItem) {
QObject::disconnect(trackedItem->item, notifier1, q, SLOT(trackedPositionChanged()));
@@ -669,16 +669,16 @@ void QFxListViewPrivate::createHighlight()
if (item) {
item->setZValue(0);
highlight = new FxListItem(item, q);
- if (orient == Qt::Vertical)
+ if (orient == QFxListView::Vertical)
highlight->item->setHeight(currentItem->item->height());
else
highlight->item->setWidth(currentItem->item->width());
- const QLatin1String posProp(orient == Qt::Vertical ? "y" : "x");
+ const QLatin1String posProp(orient == QFxListView::Vertical ? "y" : "x");
highlightPosAnimator = new QmlEaseFollow(q);
highlightPosAnimator->setTarget(QmlMetaProperty(highlight->item, posProp));
highlightPosAnimator->setVelocity(highlightMoveSpeed);
highlightPosAnimator->setEnabled(autoHighlight);
- const QLatin1String sizeProp(orient == Qt::Vertical ? "height" : "width");
+ const QLatin1String sizeProp(orient == QFxListView::Vertical ? "height" : "width");
highlightSizeAnimator = new QmlEaseFollow(q);
highlightSizeAnimator->setVelocity(highlightResizeSpeed);
highlightSizeAnimator->setTarget(QmlMetaProperty(highlight->item, sizeProp));
@@ -691,12 +691,11 @@ void QFxListViewPrivate::updateHighlight()
{
if ((!currentItem && highlight) || (currentItem && !highlight))
createHighlight();
- updateTrackedItem();
- if (currentItem && autoHighlight && highlight && !pressed && moveReason != QFxListViewPrivate::Mouse) {
+ if (currentItem && autoHighlight && highlight && !moving) {
// auto-update highlight
highlightPosAnimator->setSourceValue(currentItem->position());
highlightSizeAnimator->setSourceValue(currentItem->size());
- if (orient == Qt::Vertical) {
+ if (orient == QFxListView::Vertical) {
if (highlight->item->width() == 0)
highlight->item->setWidth(currentItem->item->width());
} else {
@@ -704,6 +703,7 @@ void QFxListViewPrivate::updateHighlight()
highlight->item->setHeight(currentItem->item->height());
}
}
+ updateTrackedItem();
}
void QFxListViewPrivate::updateSections()
@@ -792,7 +792,7 @@ void QFxListViewPrivate::updateAverage()
void QFxListViewPrivate::fixupPosition()
{
- if (orient == Qt::Vertical)
+ if (orient == QFxListView::Vertical)
fixupY();
else
fixupX();
@@ -801,7 +801,7 @@ void QFxListViewPrivate::fixupPosition()
void QFxListViewPrivate::fixupY()
{
QFxFlickablePrivate::fixupY();
- if (orient == Qt::Horizontal)
+ if (orient == QFxListView::Horizontal)
return;
if (haveHighlightRange && highlightRange == QFxListView::StrictlyEnforceRange) {
@@ -816,7 +816,7 @@ void QFxListViewPrivate::fixupY()
void QFxListViewPrivate::fixupX()
{
QFxFlickablePrivate::fixupX();
- if (orient == Qt::Vertical)
+ if (orient == QFxListView::Vertical)
return;
if (haveHighlightRange && highlightRange == QFxListView::StrictlyEnforceRange) {
@@ -832,8 +832,10 @@ void QFxListViewPrivate::flickX(qreal velocity)
{
Q_Q(QFxListView);
- if (!haveHighlightRange || highlightRange != QFxListView::StrictlyEnforceRange)
+ if (!haveHighlightRange || highlightRange != QFxListView::StrictlyEnforceRange) {
QFxFlickablePrivate::flickX(velocity);
+ return;
+ }
qreal maxDistance = -1;
// -ve velocity means list is moving up
@@ -855,19 +857,20 @@ void QFxListViewPrivate::flickX(qreal velocity)
v = maxVelocity;
}
qreal accel = deceleration;
- qreal maxAccel = (v * v) / (2.0f * maxDistance);
+ qreal v2 = v * v;
+ qreal maxAccel = v2 / (2.0f * maxDistance);
if (maxAccel < accel) {
// If we are not flicking to the end then attempt to stop exactly on an item boundary
- qreal dist = (v * v) / accel / 2.0;
+ qreal dist = v2 / accel / 2.0;
if (v > 0)
dist = -dist;
- dist = -_moveX.value() - snapPosAt(-_moveX.value() + dist + highlightRangeStart);
+ dist = -_moveX.value() - snapPosAt(-(_moveX.value() - highlightRangeStart) + dist) + highlightRangeStart;
if (v < 0 && dist >= 0 || v > 0 && dist <= 0) {
timeline.reset(_moveX);
fixupX();
return;
}
- accel = (v * v) / (2.0f * qAbs(dist));
+ accel = v2 / (2.0f * qAbs(dist));
}
timeline.reset(_moveX);
timeline.accel(_moveX, v, accel, maxDistance);
@@ -885,7 +888,60 @@ void QFxListViewPrivate::flickX(qreal velocity)
void QFxListViewPrivate::flickY(qreal velocity)
{
- QFxFlickablePrivate::flickY(velocity);
+ Q_Q(QFxListView);
+
+ if (!haveHighlightRange || highlightRange != QFxListView::StrictlyEnforceRange) {
+ QFxFlickablePrivate::flickY(velocity);
+ return;
+ }
+
+ qreal maxDistance = -1;
+ // -ve velocity means list is moving up
+ if (velocity > 0) {
+ if (_moveY.value() < q->minYExtent())
+ maxDistance = qAbs(q->minYExtent() -_moveY.value() + (overShoot?30:0));
+ flickTargetY = q->minYExtent();
+ } else {
+ if (_moveY.value() > q->maxYExtent())
+ maxDistance = qAbs(q->maxYExtent() - _moveY.value()) + (overShoot?30:0);
+ flickTargetY = q->maxYExtent();
+ }
+ if (maxDistance > 0) {
+ 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 maxAccel = v2 / (2.0f * maxDistance);
+ if (maxAccel < accel) {
+ // If we are not flicking to the end then attempt to stop exactly on an item boundary
+ qreal dist = v2 / accel / 2.0;
+ if (v > 0)
+ dist = -dist;
+ dist = -_moveY.value() - snapPosAt(-(_moveY.value() - highlightRangeStart) + dist) + highlightRangeStart;
+ if (v < 0 && dist >= 0 || v > 0 && dist <= 0) {
+ timeline.reset(_moveY);
+ fixupY();
+ return;
+ }
+ accel = v2 / (2.0f * qAbs(dist));
+ }
+ timeline.reset(_moveY);
+ timeline.accel(_moveY, v, accel, maxDistance);
+ timeline.execute(fixupYEvent);
+ if (!flicked) {
+ flicked = true;
+ emit q->flickingChanged();
+ emit q->flickStarted();
+ }
+ } else {
+ timeline.reset(_moveY);
+ fixupY();
+ }
}
//----------------------------------------------------------------------------
@@ -1185,6 +1241,10 @@ void QFxListView::setHighlight(QmlComponent *highlight)
\snippet doc/src/snippets/declarative/listview/highlight.qml 1
+ 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
*/
bool QFxListView::highlightFollowsCurrentItem() const
@@ -1298,18 +1358,18 @@ void QFxListView::setSpacing(qreal spacing)
Horizontal Example:
\image ListViewHorizontal.png
*/
-Qt::Orientation QFxListView::orientation() const
+QFxListView::Orientation QFxListView::orientation() const
{
Q_D(const QFxListView);
return d->orient;
}
-void QFxListView::setOrientation(Qt::Orientation orientation)
+void QFxListView::setOrientation(QFxListView::Orientation orientation)
{
Q_D(QFxListView);
if (d->orient != orientation) {
d->orient = orientation;
- if (d->orient == Qt::Vertical)
+ if (d->orient == QFxListView::Vertical)
setViewportWidth(-1);
else
setViewportHeight(-1);
@@ -1445,7 +1505,7 @@ void QFxListView::viewportMoved()
Q_D(QFxListView);
QFxFlickable::viewportMoved();
refill();
- if (isFlicking() || d->pressed)
+ if (isFlicking() || d->moving)
d->moveReason = QFxListViewPrivate::Mouse;
if (d->moveReason == QFxListViewPrivate::Mouse) {
if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) {
@@ -1466,7 +1526,7 @@ void QFxListView::viewportMoved()
qreal QFxListView::minYExtent() const
{
Q_D(const QFxListView);
- if (d->orient == Qt::Horizontal)
+ if (d->orient == QFxListView::Horizontal)
return QFxFlickable::minYExtent();
qreal extent = -d->startPosition();
if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange)
@@ -1478,7 +1538,7 @@ qreal QFxListView::minYExtent() const
qreal QFxListView::maxYExtent() const
{
Q_D(const QFxListView);
- if (d->orient == Qt::Horizontal)
+ if (d->orient == QFxListView::Horizontal)
return QFxFlickable::maxYExtent();
qreal extent;
if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange)
@@ -1494,7 +1554,7 @@ qreal QFxListView::maxYExtent() const
qreal QFxListView::minXExtent() const
{
Q_D(const QFxListView);
- if (d->orient == Qt::Vertical)
+ if (d->orient == QFxListView::Vertical)
return QFxFlickable::minXExtent();
qreal extent = -d->startPosition();
if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange)
@@ -1506,7 +1566,7 @@ qreal QFxListView::minXExtent() const
qreal QFxListView::maxXExtent() const
{
Q_D(const QFxListView);
- if (d->orient == Qt::Vertical)
+ if (d->orient == QFxListView::Vertical)
return QFxFlickable::maxXExtent();
qreal extent;
if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange)
@@ -1527,8 +1587,8 @@ void QFxListView::keyPressEvent(QKeyEvent *event)
return;
if (d->model && d->model->count() && d->interactive) {
- if ((d->orient == Qt::Horizontal && event->key() == Qt::Key_Left)
- || (d->orient == Qt::Vertical && event->key() == Qt::Key_Up)) {
+ if ((d->orient == QFxListView::Horizontal && event->key() == Qt::Key_Left)
+ || (d->orient == QFxListView::Vertical && event->key() == Qt::Key_Up)) {
if (currentIndex() > 0 || (d->wrap && !event->isAutoRepeat())) {
d->moveReason = QFxListViewPrivate::Key;
decrementCurrentIndex();
@@ -1538,8 +1598,8 @@ void QFxListView::keyPressEvent(QKeyEvent *event)
event->accept();
return;
}
- } else if ((d->orient == Qt::Horizontal && event->key() == Qt::Key_Right)
- || (d->orient == Qt::Vertical && event->key() == Qt::Key_Down)) {
+ } else if ((d->orient == QFxListView::Horizontal && event->key() == Qt::Key_Right)
+ || (d->orient == QFxListView::Vertical && event->key() == Qt::Key_Down)) {
if (currentIndex() < d->model->count() - 1 || (d->wrap && !event->isAutoRepeat())) {
d->moveReason = QFxListViewPrivate::Key;
incrementCurrentIndex();
@@ -1606,7 +1666,7 @@ void QFxListView::trackedPositionChanged()
Q_D(QFxListView);
if (!d->trackedItem)
return;
- if (!isFlicking() && !d->pressed && d->moveReason != QFxListViewPrivate::Mouse) {
+ if (!isFlicking() && !d->moving && d->moveReason != QFxListViewPrivate::Mouse) {
const qreal trackedPos = d->trackedItem->position();
if (d->haveHighlightRange) {
if (d->highlightRange == StrictlyEnforceRange) {
@@ -1930,7 +1990,7 @@ void QFxListView::createdItem(int index, QFxItem *item)
if (d->requestedIndex != index) {
item->setParentItem(viewport());
d->unrequestedItems.insert(item, index);
- if (d->orient == Qt::Vertical)
+ if (d->orient == QFxListView::Vertical)
item->setY(d->positionAt(index));
else
item->setX(d->positionAt(index));
diff --git a/src/declarative/fx/qfxlistview.h b/src/declarative/fx/qfxlistview.h
index 0fa0fa0..b31b951 100644
--- a/src/declarative/fx/qfxlistview.h
+++ b/src/declarative/fx/qfxlistview.h
@@ -72,7 +72,7 @@ class Q_DECLARATIVE_EXPORT QFxListView : public QFxFlickable
Q_PROPERTY(HighlightRangeMode highlightRangeMode READ highlightRangeMode WRITE setHighlightRangeMode)
Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing NOTIFY spacingChanged)
- Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged)
+ 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)
@@ -81,6 +81,7 @@ class Q_DECLARATIVE_EXPORT QFxListView : public QFxFlickable
Q_PROPERTY(qreal highlightMoveSpeed READ highlightMoveSpeed WRITE setHighlightMoveSpeed NOTIFY highlightMoveSpeedChanged)
Q_PROPERTY(qreal highlightResizeSpeed READ highlightResizeSpeed WRITE setHighlightResizeSpeed NOTIFY highlightResizeSpeedChanged)
Q_ENUMS(HighlightRangeMode)
+ Q_ENUMS(Orientation)
Q_CLASSINFO("DefaultProperty", "data")
public:
@@ -118,8 +119,9 @@ public:
qreal spacing() const;
void setSpacing(qreal spacing);
- Qt::Orientation orientation() const;
- void setOrientation(Qt::Orientation);
+ enum Orientation { Horizontal = Qt::Horizontal, Vertical = Qt::Vertical };
+ Orientation orientation() const;
+ void setOrientation(Orientation);
bool isWrapEnabled() const;
void setWrapEnabled(bool);
diff --git a/src/declarative/fx/qfxpositioners.cpp b/src/declarative/fx/qfxpositioners.cpp
index f8e7213..86a069d 100644
--- a/src/declarative/fx/qfxpositioners.cpp
+++ b/src/declarative/fx/qfxpositioners.cpp
@@ -375,6 +375,10 @@ Column {
\endqml
\endtable
+ 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, or use anchors on a child of a positioner, then the
+ positioner may exhibit strange behaviour.
*/
/*!
@@ -539,6 +543,11 @@ Row {
\endqml
\image horizontalpositioner_example.png
+ 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, or use anchors on a child of a positioner, then the
+ positioner may exhibit strange behaviour.
+
*/
/*!
\qmlproperty Transition Row::remove
@@ -659,8 +668,10 @@ void QFxRow::doPositioning()
child->setX(hoffset);
setMovingItem(0);
}
- hoffset += child->width();
- hoffset += spacing();
+ if(child->width() && child->height()){//don't advance for invisible children
+ hoffset += child->width();
+ hoffset += spacing();
+ }
}
}
@@ -705,6 +716,11 @@ Grid {
}
\endqml
\endtable
+
+ 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, or use anchors on a child of a positioner, then the
+ positioner may exhibit strange behaviour.
*/
/*!
\qmlproperty Transition Grid::remove
diff --git a/src/declarative/fx/qfxrepeater.cpp b/src/declarative/fx/qfxrepeater.cpp
index 182dcc7..94954e7 100644
--- a/src/declarative/fx/qfxrepeater.cpp
+++ b/src/declarative/fx/qfxrepeater.cpp
@@ -72,10 +72,18 @@ QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Repeater,QFxRepeater)
The model may be either an object list, a string list, a number or a Qt model.
In each case, the data element and the index is exposed to each instantiated
- component. The index is always exposed as an accessible \c index property.
+ component.
+
+ The index is always exposed as an accessible \c index property.
In the case of an object or string list, the data element (of type string
or object) is available as the \c modelData property. In the case of a Qt model,
- all roles are available as named properties just like in the view classes.
+ all roles are available as named properties just like in the view classes. The
+ following example shows how to use the index property inside the instantiated
+ items.
+
+ \snippet doc/src/snippets/declarative/repeater-index.qml 0
+
+ \image repeater-index.png
Items instantiated by the Repeater are inserted, in order, as
children of the Repeater's parent. The insertion starts immediately after
diff --git a/src/declarative/fx/qfxtext.cpp b/src/declarative/fx/qfxtext.cpp
index 4d02f0d..763256b 100644
--- a/src/declarative/fx/qfxtext.cpp
+++ b/src/declarative/fx/qfxtext.cpp
@@ -420,28 +420,28 @@ void QFxText::setTextFormat(TextFormat format)
}
/*!
- \qmlproperty Qt::TextElideMode Text::elide
+ \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 wrap enabled or with rich text.
- Eliding can be ElideNone (the default), ElideLeft, ElideMiddle, or ElideRight.
+ Eliding can be \c ElideNone (the default), \c ElideLeft, \c ElideMiddle, or \c ElideRight.
- If the text is a multi-length string, and the mode is not ElideNone,
+ If the text is a multi-length string, and the mode is not \c 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 U009C (write this in QML with "\\x9C").
+ Unicode "String Terminator" character \c U009C (write this in QML with \c{"\\x9C"}).
*/
-Qt::TextElideMode QFxText::elideMode() const
+QFxText::TextElideMode QFxText::elideMode() const
{
Q_D(const QFxText);
return d->elideMode;
}
-void QFxText::setElideMode(Qt::TextElideMode mode)
+void QFxText::setElideMode(QFxText::TextElideMode mode)
{
Q_D(QFxText);
if (mode == d->elideMode)
@@ -458,7 +458,7 @@ void QFxText::geometryChanged(const QRectF &newGeometry,
{
Q_D(QFxText);
if (newGeometry.width() != oldGeometry.width()) {
- if (d->wrap || d->elideMode != Qt::ElideNone) {
+ if (d->wrap || d->elideMode != QFxText::ElideNone) {
d->imgDirty = true;
d->updateSize();
}
@@ -486,8 +486,8 @@ void QFxTextPrivate::updateSize()
tmp = text;
tmp.replace(QLatin1Char('\n'), QChar::LineSeparator);
singleline = !tmp.contains(QChar::LineSeparator);
- if (singleline && elideMode != Qt::ElideNone && q->widthValid())
- tmp = fm.elidedText(tmp,elideMode,q->width()); // XXX still worth layout...?
+ if (singleline && elideMode != QFxText::ElideNone && q->widthValid())
+ tmp = fm.elidedText(tmp,(Qt::TextElideMode)elideMode,q->width()); // XXX still worth layout...?
layout.clearLayout();
layout.setFont(font);
layout.setText(tmp);
@@ -586,7 +586,7 @@ QSize QFxTextPrivate::setupTextLayout(QTextLayout *layout)
qreal lineWidth = 0;
//set manual width
- if ((wrap || elideMode != Qt::ElideNone) && q->widthValid())
+ if ((wrap || elideMode != QFxText::ElideNone) && q->widthValid())
lineWidth = q->width();
layout->beginLayout();
@@ -596,7 +596,7 @@ QSize QFxTextPrivate::setupTextLayout(QTextLayout *layout)
if (!line.isValid())
break;
- if ((wrap || elideMode != Qt::ElideNone) && q->widthValid())
+ if ((wrap || elideMode != QFxText::ElideNone) && q->widthValid())
line.setLineWidth(lineWidth);
}
layout->endLayout();
diff --git a/src/declarative/fx/qfxtext.h b/src/declarative/fx/qfxtext.h
index 763e2aa..cdb8025 100644
--- a/src/declarative/fx/qfxtext.h
+++ b/src/declarative/fx/qfxtext.h
@@ -57,6 +57,7 @@ class Q_DECLARATIVE_EXPORT QFxText : public QFxItem
Q_ENUMS(VAlignment)
Q_ENUMS(TextStyle)
Q_ENUMS(TextFormat)
+ Q_ENUMS(TextElideMode)
Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
Q_PROPERTY(QFont font READ font WRITE setFont)
@@ -67,7 +68,7 @@ class Q_DECLARATIVE_EXPORT QFxText : public QFxItem
Q_PROPERTY(VAlignment verticalAlignment READ vAlign WRITE setVAlign)
Q_PROPERTY(bool wrap READ wrap WRITE setWrap) //### there are several wrap modes in Qt
Q_PROPERTY(TextFormat textFormat READ textFormat WRITE setTextFormat)
- Q_PROPERTY(Qt::TextElideMode elide READ elideMode WRITE setElideMode) //### elideMode?
+ Q_PROPERTY(TextElideMode elide READ elideMode WRITE setElideMode) //### elideMode?
public:
QFxText(QFxItem *parent=0);
@@ -84,8 +85,12 @@ public:
Raised,
Sunken };
enum TextFormat { PlainText = Qt::PlainText,
- RichText = Qt::RichText,
- AutoText = Qt::AutoText };
+ RichText = Qt::RichText,
+ AutoText = Qt::AutoText };
+ enum TextElideMode { ElideLeft = Qt::ElideLeft,
+ ElideRight = Qt::ElideRight,
+ ElideMiddle = Qt::ElideMiddle,
+ ElideNone = Qt::ElideNone };
QString text() const;
void setText(const QString &);
@@ -114,8 +119,8 @@ public:
TextFormat textFormat() const;
void setTextFormat(TextFormat format);
- Qt::TextElideMode elideMode() const;
- void setElideMode(Qt::TextElideMode);
+ TextElideMode elideMode() const;
+ void setElideMode(TextElideMode);
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
diff --git a/src/declarative/fx/qfxtext_p.h b/src/declarative/fx/qfxtext_p.h
index 8b24c66..a10cdfa 100644
--- a/src/declarative/fx/qfxtext_p.h
+++ b/src/declarative/fx/qfxtext_p.h
@@ -70,7 +70,7 @@ class QFxTextPrivate : public QFxItemPrivate
public:
QFxTextPrivate()
: color((QRgb)0), style(QFxText::Normal), imgDirty(true),
- hAlign(QFxText::AlignLeft), vAlign(QFxText::AlignTop), elideMode(Qt::ElideNone),
+ hAlign(QFxText::AlignLeft), vAlign(QFxText::AlignTop), elideMode(QFxText::ElideNone),
dirty(true), wrap(false), richText(false), singleline(false), control(0), doc(0),
format(QFxText::AutoText)
{
@@ -97,7 +97,7 @@ public:
QPixmap imgStyleCache;
QFxText::HAlignment hAlign;
QFxText::VAlignment vAlign;
- Qt::TextElideMode elideMode;
+ QFxText::TextElideMode elideMode;
bool dirty;
bool wrap;
bool richText;
diff --git a/src/declarative/qml/qmlbinding.cpp b/src/declarative/qml/qmlbinding.cpp
index 65ff789..317a4b3 100644
--- a/src/declarative/qml/qmlbinding.cpp
+++ b/src/declarative/qml/qmlbinding.cpp
@@ -58,10 +58,46 @@ QT_BEGIN_NAMESPACE
QML_DEFINE_NOCREATE_TYPE(QmlBinding);
QmlBindingData::QmlBindingData()
-: updating(false), enabled(false)
+: updating(false), enabled(false), nextError(0), prevError(0)
{
}
+QmlBindingData::~QmlBindingData()
+{
+ removeError();
+}
+
+void QmlBindingData::removeError()
+{
+ if (!prevError) return;
+
+ if (nextError) nextError->prevError = prevError;
+ *prevError = nextError;
+ nextError = 0;
+ prevError = 0;
+}
+
+bool QmlBindingData::addError()
+{
+ if (prevError) return false;
+
+ QmlContext *c = context();
+ if (!c) return false;
+ QmlEngine *e = c->engine();
+ if (!e) return false;
+
+ QmlEnginePrivate *p = QmlEnginePrivate::get(e);
+
+ if (p->inProgressCreations == 0) return false; // Not in construction
+
+ prevError = &p->erroredBindings;
+ nextError = p->erroredBindings;
+ p->erroredBindings = this;
+ if (nextError) nextError->prevError = &nextError;
+
+ return true;
+}
+
QmlBindingPrivate::QmlBindingPrivate()
: QmlExpressionPrivate(new QmlBindingData)
{
@@ -128,10 +164,12 @@ void QmlBinding::update(QmlMetaProperty::WriteFlags flags)
idx, a);
} else {
- bool undefined = false;
- QVariant value = this->value(&undefined);
+ bool isUndefined = false;
+ QVariant value = this->value(&isUndefined);
+
+ if (!isUndefined && data->property.object() &&
+ !data->property.write(value, flags)) {
- if (!undefined && data->property.object() && !data->property.write(value, flags)) {
QString fileName = data->fileName;
int line = data->line;
if (fileName.isEmpty()) fileName = QLatin1String("<Unknown File>");
@@ -139,9 +177,21 @@ void QmlBinding::update(QmlMetaProperty::WriteFlags flags)
const char *valueType = 0;
if (value.userType() == QVariant::Invalid) valueType = "null";
else valueType = QMetaType::typeName(value.userType());
- qWarning().nospace() << qPrintable(fileName) << ":" << line
- << " Unable to assign " << valueType << " to "
- << QMetaType::typeName(data->property.propertyType());
+
+ data->error.setUrl(fileName);
+ data->error.setLine(line);
+ data->error.setColumn(-1);
+ data->error.setDescription(QLatin1String("Unable to assign ") +
+ QLatin1String(valueType) +
+ QLatin1String(" to ") +
+ QLatin1String(QMetaType::typeName(data->property.propertyType())));
+ }
+
+ if (data->error.isValid()) {
+ if (!data->addError())
+ qWarning().nospace() << qPrintable(this->error().toString());
+ } else {
+ data->removeError();
}
}
diff --git a/src/declarative/qml/qmlbinding_p.h b/src/declarative/qml/qmlbinding_p.h
index 2c0c6b9..c9378cb 100644
--- a/src/declarative/qml/qmlbinding_p.h
+++ b/src/declarative/qml/qmlbinding_p.h
@@ -63,11 +63,17 @@ class QmlBindingData : public QmlExpressionData
{
public:
QmlBindingData();
+ virtual ~QmlBindingData();
bool updating:1;
bool enabled:1;
QmlMetaProperty property;
+
+ void removeError();
+ bool addError();
+ QmlBindingData *nextError;
+ QmlBindingData **prevError;
};
class QmlBindingPrivate : public QmlExpressionPrivate
diff --git a/src/declarative/qml/qmlboundsignal.cpp b/src/declarative/qml/qmlboundsignal.cpp
index ce591e8..d715309 100644
--- a/src/declarative/qml/qmlboundsignal.cpp
+++ b/src/declarative/qml/qmlboundsignal.cpp
@@ -175,8 +175,11 @@ int QmlBoundSignal::qt_metacall(QMetaObject::Call c, int id, void **a)
{
if (c == QMetaObject::InvokeMetaMethod && id == evaluateIdx) {
if (m_params) m_params->setValues(a);
- if (m_expression)
+ if (m_expression) {
QmlExpressionPrivate::get(m_expression)->value(m_params);
+ if (m_expression->hasError())
+ qWarning().nospace() << qPrintable(m_expression->error().toString());
+ }
if (m_params) m_params->clearValues();
return -1;
} else {
diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp
index 60282dc..ad74446 100644
--- a/src/declarative/qml/qmlcompiler.cpp
+++ b/src/declarative/qml/qmlcompiler.cpp
@@ -2234,6 +2234,7 @@ bool QmlCompiler::buildDynamicMeta(QmlParser::Object *obj, DynamicMetaMode mode)
}
sig.append(")");
QMetaMethodBuilder b = builder.addSlot(sig);
+ b.setReturnType("QVariant");
b.setParameterNames(s.parameterNames);
((QmlVMEMetaData *)dynamicData.data())->methodCount++;
diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp
index 0894758..3767695 100644
--- a/src/declarative/qml/qmlcomponent.cpp
+++ b/src/declarative/qml/qmlcomponent.cpp
@@ -55,6 +55,7 @@
#include "qmlbinding.h"
#include <QtCore/qdebug.h>
#include <QApplication>
+#include <private/qmlbinding_p.h>
#include "qmlscriptparser_p.h"
@@ -197,6 +198,12 @@ QmlComponent::QmlComponent(QObject *parent)
QmlComponent::~QmlComponent()
{
Q_D(QmlComponent);
+
+ if (d->completePending) {
+ qWarning("QmlComponent: Component destroyed while completion pending");
+ d->completeCreate();
+ }
+
if (d->typeData) {
d->typeData->remWaiter(d);
d->typeData->release();
@@ -574,8 +581,10 @@ QmlComponentPrivate::beginCreate(QmlContext *context, const QBitField &bindings)
ep->bindValues.clear();
ep->parserStatus.clear();
completePending = true;
+ QmlEnginePrivate::get(engine)->inProgressCreations++;
}
+
if (rv) {
QFx_setParent_noEvent(ctxt, rv);
} else {
@@ -643,6 +652,14 @@ void QmlComponentPrivate::completeCreate()
bindValues.clear();
parserStatus.clear();
completePending = false;
+ QmlEnginePrivate *p = QmlEnginePrivate::get(engine);
+ p->inProgressCreations--;
+ if (0 == p->inProgressCreations) {
+ while (p->erroredBindings) {
+ qWarning().nospace() << qPrintable(p->erroredBindings->error.toString());
+ p->erroredBindings->removeError();
+ }
+ }
}
}
diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp
index 2ebdf10..5032ff4 100644
--- a/src/declarative/qml/qmlcontext.cpp
+++ b/src/declarative/qml/qmlcontext.cpp
@@ -77,8 +77,11 @@ void QmlContextPrivate::addScript(const QString &script, QObject *scopeObject,
QScriptValue val = scriptEngine->evaluate(script, fileName, lineNumber);
- if (scriptEngine->hasUncaughtException())
- QmlExpressionPrivate::printException(scriptEngine);
+ if (scriptEngine->hasUncaughtException()) {
+ QmlError error;
+ QmlExpressionPrivate::exceptionToError(scriptEngine, error);
+ qWarning().nospace() << qPrintable(error.toString());
+ }
scriptEngine->popContext();
diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp
index 0e239ce..3da8aa9 100644
--- a/src/declarative/qml/qmlengine.cpp
+++ b/src/declarative/qml/qmlengine.cpp
@@ -126,8 +126,9 @@ static QString userLocalDataPath(const QString& app)
QmlEnginePrivate::QmlEnginePrivate(QmlEngine *e)
: rootContext(0), currentExpression(0),
isDebugging(false), contextClass(0), objectClass(0), valueTypeClass(0), globalClass(0),
- nodeListClass(0), namedNodeMapClass(0), sqlQueryClass(0), cleanup(0), scriptEngine(this),
- componentAttacheds(0), rootComponent(0), networkAccessManager(0), typeManager(e), uniqueId(1)
+ nodeListClass(0), namedNodeMapClass(0), sqlQueryClass(0), cleanup(0), erroredBindings(0),
+ inProgressCreations(0), scriptEngine(this), componentAttacheds(0), rootComponent(0),
+ networkAccessManager(0), typeManager(e), uniqueId(1)
{
QScriptValue qtObject =
scriptEngine.newQMetaObject(StaticQtMetaObject::get());
diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h
index 69b121e..efd26bf 100644
--- a/src/declarative/qml/qmlengine_p.h
+++ b/src/declarative/qml/qmlengine_p.h
@@ -98,6 +98,7 @@ class QmlTypeNameCache;
class QmlComponentAttached;
class QmlListScriptClass;
class QmlCleanup;
+class QmlBindingData;
class QmlEnginePrivate : public QObjectPrivate
{
@@ -143,6 +144,10 @@ public:
// Registered cleanup handlers
QmlCleanup *cleanup;
+ // Bindings that have had errors during startup
+ QmlBindingData *erroredBindings;
+ int inProgressCreations;
+
struct QmlScriptEngine : public QScriptEngine
{
QmlScriptEngine(QmlEnginePrivate *priv)
diff --git a/src/declarative/qml/qmlerror.cpp b/src/declarative/qml/qmlerror.cpp
index 514fe44..f4c9580 100644
--- a/src/declarative/qml/qmlerror.cpp
+++ b/src/declarative/qml/qmlerror.cpp
@@ -70,7 +70,7 @@ QmlErrorPrivate::QmlErrorPrivate()
Create an empty error object.
*/
QmlError::QmlError()
-: d(new QmlErrorPrivate)
+: d(0)
{
}
@@ -78,7 +78,7 @@ QmlError::QmlError()
Create a copy of \a other.
*/
QmlError::QmlError(const QmlError &other)
-: d(new QmlErrorPrivate)
+: d(0)
{
*this = other;
}
@@ -88,10 +88,16 @@ QmlError::QmlError(const QmlError &other)
*/
QmlError &QmlError::operator=(const QmlError &other)
{
- d->url = other.d->url;
- d->description = other.d->description;
- d->line = other.d->line;
- d->column = other.d->column;
+ if (!other.d) {
+ delete d;
+ d = 0;
+ } else {
+ if (!d) d = new QmlErrorPrivate;
+ d->url = other.d->url;
+ d->description = other.d->description;
+ d->line = other.d->line;
+ d->column = other.d->column;
+ }
return *this;
}
@@ -104,11 +110,20 @@ QmlError::~QmlError()
}
/*!
+ Return true if this error is valid, otherwise false.
+*/
+bool QmlError::isValid() const
+{
+ return d != 0;
+}
+
+/*!
Return the url for the file that caused this error.
*/
QUrl QmlError::url() const
{
- return d->url;
+ if (d) return d->url;
+ else return QUrl();
}
/*!
@@ -116,6 +131,7 @@ QUrl QmlError::url() const
*/
void QmlError::setUrl(const QUrl &url)
{
+ if (!d) d = new QmlErrorPrivate;
d->url = url;
}
@@ -124,7 +140,8 @@ void QmlError::setUrl(const QUrl &url)
*/
QString QmlError::description() const
{
- return d->description;
+ if (d) return d->description;
+ else return QString();
}
/*!
@@ -132,6 +149,7 @@ QString QmlError::description() const
*/
void QmlError::setDescription(const QString &description)
{
+ if (!d) d = new QmlErrorPrivate;
d->description = description;
}
@@ -140,7 +158,8 @@ void QmlError::setDescription(const QString &description)
*/
int QmlError::line() const
{
- return d->line;
+ if (d) return d->line;
+ else return -1;
}
/*!
@@ -148,6 +167,7 @@ int QmlError::line() const
*/
void QmlError::setLine(int line)
{
+ if (!d) d = new QmlErrorPrivate;
d->line = line;
}
@@ -156,7 +176,8 @@ void QmlError::setLine(int line)
*/
int QmlError::column() const
{
- return d->column;
+ if (d) return d->column;
+ else return -1;
}
/*!
@@ -164,6 +185,7 @@ int QmlError::column() const
*/
void QmlError::setColumn(int column)
{
+ if (!d) d = new QmlErrorPrivate;
d->column = column;
}
diff --git a/src/declarative/qml/qmlerror.h b/src/declarative/qml/qmlerror.h
index c1a8720..ee3d7b4 100644
--- a/src/declarative/qml/qmlerror.h
+++ b/src/declarative/qml/qmlerror.h
@@ -61,6 +61,8 @@ public:
QmlError &operator=(const QmlError &);
~QmlError();
+ bool isValid() const;
+
QUrl url() const;
void setUrl(const QUrl &);
QString description() const;
diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp
index c62756b..e5e5cf9 100644
--- a/src/declarative/qml/qmlexpression.cpp
+++ b/src/declarative/qml/qmlexpression.cpp
@@ -260,7 +260,8 @@ QVariant QmlExpressionPrivate::evalSSE()
return rv;
}
-void QmlExpressionPrivate::printException(QScriptEngine *scriptEngine)
+void QmlExpressionPrivate::exceptionToError(QScriptEngine *scriptEngine,
+ QmlError &error)
{
if (scriptEngine->hasUncaughtException() &&
scriptEngine->uncaughtException().isError()) {
@@ -277,8 +278,12 @@ void QmlExpressionPrivate::printException(QScriptEngine *scriptEngine)
fileName = QLatin1String("<Unknown File>");
}
- qWarning().nospace() << qPrintable(fileName) << ":" << lineNumber << ": "
- << qPrintable(exception.toString());
+ error.setUrl(QUrl(fileName));
+ error.setLine(lineNumber);
+ error.setColumn(-1);
+ error.setDescription(exception.toString());
+ } else {
+ error = QmlError();
}
}
@@ -288,6 +293,7 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope, bool *isUnd
QFxPerfTimer<QFxPerf::BindValueQt> perfqt;
#endif
+ QmlExpressionData *data = this->data;
QmlContextPrivate *ctxtPriv = data->context()->d_func();
QmlEngine *engine = data->context()->engine();
QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
@@ -321,10 +327,13 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope, bool *isUnd
if (isUndefined)
*isUndefined = svalue.isUndefined() || scriptEngine->hasUncaughtException();
+ // Handle exception
if (scriptEngine->hasUncaughtException()) {
- printException(scriptEngine);
+ exceptionToError(scriptEngine, data->error);
scriptEngine->clearExceptions();
return QVariant();
+ } else {
+ data->error = QmlError();
}
if (secondaryScope) {
@@ -418,6 +427,8 @@ QVariant QmlExpressionPrivate::value(QObject *secondaryScope, bool *isUndefined)
\a isUndefined is set to true if the expression resulted in an
undefined value.
+
+ \sa hasError(), error()
*/
QVariant QmlExpression::value(bool *isUndefined)
{
@@ -509,6 +520,43 @@ QObject *QmlExpression::scopeObject() const
return d->data->me;
}
+/*!
+ Returns true if the last call to value() resulted in an error,
+ otherwise false.
+
+ \sa error(), clearError()
+*/
+bool QmlExpression::hasError() const
+{
+ Q_D(const QmlExpression);
+ return d->data->error.isValid();
+}
+
+/*!
+ Clear any expression errors. Calls to hasError() following this will
+ return false.
+
+ \sa hasError(), error()
+*/
+void QmlExpression::clearError()
+{
+ Q_D(QmlExpression);
+ d->data->error = QmlError();
+}
+
+/*!
+ Return any error from the last call to value(). If there was no error,
+ this returns an invalid QmlError instance.
+
+ \sa hasError(), clearError()
+*/
+
+QmlError QmlExpression::error() const
+{
+ Q_D(const QmlExpression);
+ return d->data->error;
+}
+
/*! \internal */
void QmlExpression::__q_notify()
{
diff --git a/src/declarative/qml/qmlexpression.h b/src/declarative/qml/qmlexpression.h
index 96694d6..127d3f3 100644
--- a/src/declarative/qml/qmlexpression.h
+++ b/src/declarative/qml/qmlexpression.h
@@ -44,6 +44,7 @@
#include <QtCore/qobject.h>
#include <QtCore/qvariant.h>
+#include <QtDeclarative/qmlerror.h>
QT_BEGIN_HEADER
@@ -82,6 +83,10 @@ public:
QObject *scopeObject() const;
+ bool hasError() const;
+ void clearError();
+ QmlError error() const;
+
public Q_SLOTS:
QVariant value(bool *isUndefined = 0);
diff --git a/src/declarative/qml/qmlexpression_p.h b/src/declarative/qml/qmlexpression_p.h
index 3ec8d1c..4e13de3 100644
--- a/src/declarative/qml/qmlexpression_p.h
+++ b/src/declarative/qml/qmlexpression_p.h
@@ -83,7 +83,7 @@ class QmlExpressionData : public QmlAbstractExpression, public QmlRefCount
{
public:
QmlExpressionData();
- ~QmlExpressionData();
+ virtual ~QmlExpressionData();
QmlExpressionPrivate *q;
@@ -92,6 +92,8 @@ public:
bool expressionRewritten:1;
QScriptValue expressionFunction;
+ QmlError error;
+
QmlBasicScript sse;
QObject *me;
bool trackChange;
@@ -151,7 +153,7 @@ public:
return static_cast<QmlExpressionPrivate *>(QObjectPrivate::get(expr));
}
- static void printException(QScriptEngine *);
+ static void exceptionToError(QScriptEngine *, QmlError &);
};
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlvmemetaobject.cpp b/src/declarative/qml/qmlvmemetaobject.cpp
index 3e1d931..83f904b 100644
--- a/src/declarative/qml/qmlvmemetaobject.cpp
+++ b/src/declarative/qml/qmlvmemetaobject.cpp
@@ -269,10 +269,11 @@ int QmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
QString code = QString::fromRawData(body, data->bodyLength);
+ QVariant rv;
if (0 == (metaData->methodData() + id)->parameterCount) {
QmlExpression expr(ctxt, code, object);
expr.setTrackChange(false);
- expr.value();
+ rv = expr.value();
} else {
QmlContext newCtxt(ctxt);
QMetaMethod m = method(_id);
@@ -281,8 +282,9 @@ int QmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
newCtxt.setContextProperty(QString::fromLatin1(names.at(ii)), *(QVariant *)a[ii + 1]);
QmlExpression expr(&newCtxt, code, object);
expr.setTrackChange(false);
- expr.value();
+ rv = expr.value();
}
+ if (a[0]) *reinterpret_cast<QVariant *>(a[0]) = rv;
}
return -1;
}
diff --git a/src/declarative/util/qmleasefollow.cpp b/src/declarative/util/qmleasefollow.cpp
index 99720f8..9d17d25 100644
--- a/src/declarative/util/qmleasefollow.cpp
+++ b/src/declarative/util/qmleasefollow.cpp
@@ -210,7 +210,6 @@ void QmlEaseFollowPrivate::tick(int t)
qreal value = 0.5 * a * time_seconds * time_seconds + vi * time_seconds;
value = (invert?-1.0:1.0) * value;
target.write(initialValue + value);
-
out = initialValue + value;
} else if (time_seconds < td) {
@@ -397,7 +396,7 @@ void QmlEaseFollow::setSourceValue(qreal s)
{
Q_D(QmlEaseFollow);
- if (d->source == s)
+ if (d->clock.state() == QAbstractAnimation::Running && d->source == s)
return;
d->source = s;
diff --git a/src/declarative/util/qmlspringfollow.cpp b/src/declarative/util/qmlspringfollow.cpp
index 34ec976..569cc48 100644
--- a/src/declarative/util/qmlspringfollow.cpp
+++ b/src/declarative/util/qmlspringfollow.cpp
@@ -272,10 +272,11 @@ qreal QmlSpringFollow::sourceValue() const
void QmlSpringFollow::setSourceValue(qreal value)
{
Q_D(QmlSpringFollow);
- if (d->sourceValue != value) {
- d->sourceValue = value;
- d->start();
- }
+ if (d->clock.state() == QAbstractAnimation::Running && d->sourceValue == value)
+ return;
+
+ d->sourceValue = value;
+ d->start();
}
/*!