diff options
Diffstat (limited to 'src/declarative')
75 files changed, 1551 insertions, 452 deletions
diff --git a/src/declarative/QmlChanges.txt b/src/declarative/QmlChanges.txt index dfc4244..ec8f508 100644 --- a/src/declarative/QmlChanges.txt +++ b/src/declarative/QmlChanges.txt @@ -1,21 +1,30 @@ ============================================================================= The changes below are pre Qt 4.7.0 RC -Flickable: overShoot is replaced by boundsBehavior enumeration. +Flickable: + - overShoot is replaced by boundsBehavior enumeration + - flickingHorizontally and flickingVertically properties added + - movingHorizontally and movingVertically properties added + - flickDirection is renamed flickableDirection Component: isReady, isLoading, isError and isNull properties removed, use status property instead QList<QObject*> models no longer provide properties in model object. The properties are now updated when the object changes. An object's property "foo" may now be accessed as "foo", modelData.foo" or model.modelData.foo" - +component.createObject has gained a mandatory "parent" argument C++ API ------- QDeclarativeExpression::value() has been renamed to QDeclarativeExpression::evaluate() +QML Launcher +------------ +The standalone executable has been renamed to qml launcher. Runtime warnings +can be now accessed via the menu (Debugging->Show Warnings). + ============================================================================= -The changes below are pre Qt 4.7.0 beta +The changes below are pre Qt 4.7.0 beta 1 TextEdit: wrap property is replaced by wrapMode enumeration. Text: wrap property is replaced by wrapMode enumeration. diff --git a/src/declarative/declarative.pro b/src/declarative/declarative.pro index 4287e25..8037a16 100644 --- a/src/declarative/declarative.pro +++ b/src/declarative/declarative.pro @@ -1,13 +1,13 @@ TARGET = QtDeclarative QPRO_PWD = $$PWD -QT = core gui xml script network +QT = core gui script network contains(QT_CONFIG, svg): QT += svg contains(QT_CONFIG, opengl): QT += opengl DEFINES += QT_BUILD_DECLARATIVE_LIB QT_NO_URL_CAST_FROM_STRING win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x66000000 solaris-cc*:QMAKE_CXXFLAGS_RELEASE -= -O2 -unix:QMAKE_PKGCONFIG_REQUIRES = QtCore QtGui QtXml +unix:QMAKE_PKGCONFIG_REQUIRES = QtCore QtGui exists("qdeclarative_enable_gcov") { QMAKE_CXXFLAGS = -fprofile-arcs -ftest-coverage -fno-elide-constructors diff --git a/src/declarative/graphicsitems/qdeclarativeborderimage.cpp b/src/declarative/graphicsitems/qdeclarativeborderimage.cpp index 018bd55..229e15b 100644 --- a/src/declarative/graphicsitems/qdeclarativeborderimage.cpp +++ b/src/declarative/graphicsitems/qdeclarativeborderimage.cpp @@ -70,11 +70,11 @@ QT_BEGIN_NAMESPACE \endlist Examples: - \snippet snippets/declarative/border-image.qml 0 + \snippet snippets/declarative/borderimage.qml 0 \image BorderImage.png - The \l{declarative/border-image}{BorderImage example} shows how a BorderImage can be used to simulate a shadow effect on a + The \l{declarative/imageelements/borderimage}{BorderImage example} shows how a BorderImage can be used to simulate a shadow effect on a rectangular item. */ diff --git a/src/declarative/graphicsitems/qdeclarativeflickable.cpp b/src/declarative/graphicsitems/qdeclarativeflickable.cpp index 34b0606..3c0f5a2 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable.cpp +++ b/src/declarative/graphicsitems/qdeclarativeflickable.cpp @@ -125,12 +125,14 @@ QDeclarativeFlickablePrivate::QDeclarativeFlickablePrivate() : viewport(new QDeclarativeItem) , hData(this, &QDeclarativeFlickablePrivate::setRoundedViewportX) , vData(this, &QDeclarativeFlickablePrivate::setRoundedViewportY) - , flicked(false), moving(false), stealMouse(false) - , pressed(false) + , flickingHorizontally(false), flickingVertically(false) + , hMoved(false), vMoved(false) + , movingHorizontally(false), movingVertically(false) + , stealMouse(false), pressed(false) , interactive(true), deceleration(500), maxVelocity(2000), reportedVelocitySmoothing(100) , delayedPressEvent(0), delayedPressTarget(0), pressDelay(0), fixupDuration(600) , vTime(0), visibleArea(0) - , flickDirection(QDeclarativeFlickable::AutoFlickDirection) + , flickableDirection(QDeclarativeFlickable::AutoFlickDirection) , boundsBehavior(QDeclarativeFlickable::DragAndOvershootBounds) { } @@ -226,10 +228,19 @@ void QDeclarativeFlickablePrivate::flick(AxisData &data, qreal minExtent, qreal timeline.reset(data.move); timeline.accel(data.move, v, deceleration, maxDistance); timeline.callback(QDeclarativeTimeLineCallback(&data.move, fixupCallback, this)); - if (!flicked) { - flicked = true; + if (!flickingHorizontally && q->xflick()) { + flickingHorizontally = true; emit q->flickingChanged(); - emit q->flickStarted(); + emit q->flickingHorizontallyChanged(); + if (!flickingVertically) + emit q->flickStarted(); + } + if (!flickingVertically && q->yflick()) { + flickingVertically = true; + emit q->flickingChanged(); + emit q->flickingVerticallyChanged(); + if (!flickingHorizontally) + emit q->flickStarted(); } } else { timeline.reset(data.move); @@ -274,7 +285,6 @@ void QDeclarativeFlickablePrivate::fixup(AxisData &data, qreal minExtent, qreal q->viewportMoved(); } } - //emit flickingChanged(); } else if (data.move.value() < maxExtent) { timeline.reset(data.move); if (fixupDuration) { @@ -285,11 +295,7 @@ void QDeclarativeFlickablePrivate::fixup(AxisData &data, qreal minExtent, qreal data.move.setValue(maxExtent); q->viewportMoved(); } - //emit flickingChanged(); - } else { - flicked = false; } - vTime = timeline.time(); } @@ -412,7 +418,7 @@ void QDeclarativeFlickablePrivate::updateBeginningEnd() \dots 4 \snippet doc/src/snippets/declarative/flickableScrollbar.qml 1 - \sa {declarative/scrollbar}{scrollbar example} + \sa {declarative/ui-components/scrollbar}{scrollbar example} */ QDeclarativeFlickable::QDeclarativeFlickable(QDeclarativeItem *parent) @@ -498,11 +504,14 @@ void QDeclarativeFlickable::setInteractive(bool interactive) Q_D(QDeclarativeFlickable); if (interactive != d->interactive) { d->interactive = interactive; - if (!interactive && d->flicked) { + if (!interactive && (d->flickingHorizontally || d->flickingVertically)) { d->timeline.clear(); d->vTime = d->timeline.time(); - d->flicked = false; + d->flickingHorizontally = false; + d->flickingVertically = false; emit flickingChanged(); + emit flickingHorizontallyChanged(); + emit flickingVerticallyChanged(); emit flickEnded(); } emit interactiveChanged(); @@ -582,7 +591,7 @@ QDeclarativeFlickableVisibleArea *QDeclarativeFlickable::visibleArea() } /*! - \qmlproperty enumeration Flickable::flickDirection + \qmlproperty enumeration Flickable::flickableDirection This property determines which directions the view can be flicked. @@ -596,21 +605,33 @@ QDeclarativeFlickableVisibleArea *QDeclarativeFlickable::visibleArea() \o Flickable.HorizontalAndVerticalFlick - allows flicking in both directions. \endlist */ -QDeclarativeFlickable::FlickDirection QDeclarativeFlickable::flickDirection() const +QDeclarativeFlickable::FlickableDirection QDeclarativeFlickable::flickableDirection() const { Q_D(const QDeclarativeFlickable); - return d->flickDirection; + return d->flickableDirection; } -void QDeclarativeFlickable::setFlickDirection(FlickDirection direction) +void QDeclarativeFlickable::setFlickableDirection(FlickableDirection direction) { Q_D(QDeclarativeFlickable); - if (direction != d->flickDirection) { - d->flickDirection = direction; - emit flickDirectionChanged(); + if (direction != d->flickableDirection) { + d->flickableDirection = direction; + emit flickableDirectionChanged(); } } +QDeclarativeFlickable::FlickableDirection QDeclarativeFlickable::flickDirection() const +{ + qmlInfo(this) << "'flickDirection' is deprecated. Please use 'flickableDirection' instead."; + return flickableDirection(); +} + +void QDeclarativeFlickable::setFlickDirection(FlickableDirection direction) +{ + qmlInfo(this) << "'flickDirection' is deprecated. Please use 'flickableDirection' instead."; + setFlickableDirection(direction); +} + void QDeclarativeFlickablePrivate::handleMousePressEvent(QGraphicsSceneMouseEvent *event) { if (interactive && timeline.isActive() && (qAbs(hData.velocity) > 10 || qAbs(vData.velocity) > 10)) @@ -626,7 +647,8 @@ void QDeclarativeFlickablePrivate::handleMousePressEvent(QGraphicsSceneMouseEven pressPos = event->pos(); hData.pressPos = hData.move.value(); vData.pressPos = vData.move.value(); - flicked = false; + flickingHorizontally = false; + flickingVertically = false; QDeclarativeItemPrivate::start(pressTime); QDeclarativeItemPrivate::start(velocityTime); } @@ -638,7 +660,6 @@ void QDeclarativeFlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent return; bool rejectY = false; bool rejectX = false; - bool moved = false; if (q->yflick()) { int dy = int(event->pos().y() - pressPos.y()); @@ -660,7 +681,7 @@ void QDeclarativeFlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent } if (!rejectY && stealMouse) { vData.move.setValue(qRound(newY)); - moved = true; + vMoved = true; } if (qAbs(dy) > QApplication::startDragDistance()) stealMouse = true; @@ -687,7 +708,7 @@ void QDeclarativeFlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent } if (!rejectX && stealMouse) { hData.move.setValue(qRound(newX)); - moved = true; + hMoved = true; } if (qAbs(dx) > QApplication::startDragDistance()) @@ -717,7 +738,7 @@ void QDeclarativeFlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent if (rejectY) vData.velocity = 0; if (rejectX) hData.velocity = 0; - if (moved) { + if (hMoved || vMoved) { q->movementStarting(); q->viewportMoved(); } @@ -812,20 +833,24 @@ void QDeclarativeFlickable::wheelEvent(QGraphicsSceneWheelEvent *event) d->vData.velocity = qMax(event->delta() - d->vData.smoothVelocity.value(), qreal(250.0)); else d->vData.velocity = qMin(event->delta() - d->vData.smoothVelocity.value(), qreal(-250.0)); - d->flicked = false; + d->flickingVertically = false; d->flickY(d->vData.velocity); - if (d->flicked) + if (d->flickingVertically) { + d->vMoved = true; movementStarting(); + } event->accept(); } else if (xflick()) { if (event->delta() > 0) d->hData.velocity = qMax(event->delta() - d->hData.smoothVelocity.value(), qreal(250.0)); else d->hData.velocity = qMin(event->delta() - d->hData.smoothVelocity.value(), qreal(-250.0)); - d->flicked = false; + d->flickingHorizontally = false; d->flickX(d->hData.velocity); - if (d->flicked) + if (d->flickingHorizontally) { + d->hMoved = true; movementStarting(); + } event->accept(); } else { QDeclarativeItem::wheelEvent(event); @@ -1091,7 +1116,7 @@ void QDeclarativeFlickable::setContentWidth(qreal w) else d->viewport->setWidth(w); // Make sure that we're entirely in view. - if (!d->pressed && !d->moving) { + if (!d->pressed && !d->movingHorizontally && !d->movingVertically) { int oldDuration = d->fixupDuration; d->fixupDuration = 0; d->fixupX(); @@ -1118,7 +1143,7 @@ void QDeclarativeFlickable::setContentHeight(qreal h) else d->viewport->setHeight(h); // Make sure that we're entirely in view. - if (!d->pressed && !d->moving) { + if (!d->pressed && !d->movingHorizontally && !d->movingVertically) { int oldDuration = d->fixupDuration; d->fixupDuration = 0; d->fixupY(); @@ -1149,17 +1174,17 @@ qreal QDeclarativeFlickable::vHeight() const bool QDeclarativeFlickable::xflick() const { Q_D(const QDeclarativeFlickable); - if (d->flickDirection == QDeclarativeFlickable::AutoFlickDirection) + if (d->flickableDirection == QDeclarativeFlickable::AutoFlickDirection) return vWidth() != width(); - return d->flickDirection & QDeclarativeFlickable::HorizontalFlick; + return d->flickableDirection & QDeclarativeFlickable::HorizontalFlick; } bool QDeclarativeFlickable::yflick() const { Q_D(const QDeclarativeFlickable); - if (d->flickDirection == QDeclarativeFlickable::AutoFlickDirection) + if (d->flickableDirection == QDeclarativeFlickable::AutoFlickDirection) return vHeight() != height(); - return d->flickDirection & QDeclarativeFlickable::VerticalFlick; + return d->flickableDirection & QDeclarativeFlickable::VerticalFlick; } bool QDeclarativeFlickable::sendMouseEvent(QGraphicsSceneMouseEvent *event) @@ -1281,16 +1306,30 @@ void QDeclarativeFlickable::setFlickDeceleration(qreal deceleration) emit flickDecelerationChanged(); } +bool QDeclarativeFlickable::isFlicking() const +{ + Q_D(const QDeclarativeFlickable); + return d->flickingHorizontally || d->flickingVertically; +} + /*! \qmlproperty bool Flickable::flicking + \qmlproperty bool Flickable::flickingHorizontally + \qmlproperty bool Flickable::flickingVertically - This property holds whether the view is currently moving due to - the user flicking the view. + These properties hold whether the view is currently moving horizontally + or vertically due to the user flicking the view. */ -bool QDeclarativeFlickable::isFlicking() const +bool QDeclarativeFlickable::isFlickingHorizontally() const { Q_D(const QDeclarativeFlickable); - return d->flicked; + return d->flickingHorizontally; +} + +bool QDeclarativeFlickable::isFlickingVertically() const +{ + Q_D(const QDeclarativeFlickable); + return d->flickingVertically; } /*! @@ -1319,40 +1358,84 @@ void QDeclarativeFlickable::setPressDelay(int delay) emit pressDelayChanged(); } + +bool QDeclarativeFlickable::isMoving() const +{ + Q_D(const QDeclarativeFlickable); + return d->movingHorizontally || d->movingVertically; +} + /*! \qmlproperty bool Flickable::moving + \qmlproperty bool Flickable::movingHorizontally + \qmlproperty bool Flickable::movingVertically - This property holds whether the view is currently moving due to - the user either dragging or flicking the view. + These properties hold whether the view is currently moving horizontally + or vertically due to the user either dragging or flicking the view. */ -bool QDeclarativeFlickable::isMoving() const +bool QDeclarativeFlickable::isMovingHorizontally() const +{ + Q_D(const QDeclarativeFlickable); + return d->movingHorizontally; +} + +bool QDeclarativeFlickable::isMovingVertically() const { Q_D(const QDeclarativeFlickable); - return d->moving; + return d->movingVertically; } void QDeclarativeFlickable::movementStarting() { Q_D(QDeclarativeFlickable); - if (!d->moving) { - d->moving = true; + if (d->hMoved && !d->movingHorizontally) { + d->movingHorizontally = true; emit movingChanged(); - emit movementStarted(); + emit movingHorizontallyChanged(); + if (!d->movingVertically) + emit movementStarted(); + } + else if (d->vMoved && !d->movingVertically) { + d->movingVertically = true; + emit movingChanged(); + emit movingVerticallyChanged(); + if (!d->movingHorizontally) + emit movementStarted(); } } void QDeclarativeFlickable::movementEnding() { Q_D(QDeclarativeFlickable); - if (d->moving) { - d->moving = false; - emit movingChanged(); - emit movementEnded(); + if (d->flickingHorizontally) { + d->flickingHorizontally = false; + emit flickingChanged(); + emit flickingHorizontallyChanged(); + if (!d->flickingVertically) + emit flickEnded(); } - if (d->flicked) { - d->flicked = false; + if (d->flickingVertically) { + d->flickingVertically = false; emit flickingChanged(); - emit flickEnded(); + emit flickingVerticallyChanged(); + if (!d->flickingHorizontally) + emit flickEnded(); + } + if (d->movingHorizontally) { + d->movingHorizontally = false; + d->hMoved = false; + emit movingChanged(); + emit movingHorizontallyChanged(); + if (!d->movingVertically) + emit movementEnded(); + } + if (d->movingVertically) { + d->movingVertically = false; + d->vMoved = false; + emit movingChanged(); + emit movingVerticallyChanged(); + if (!d->movingHorizontally) + emit movementEnded(); } d->hData.smoothVelocity.setValue(0); d->vData.smoothVelocity.setValue(0); diff --git a/src/declarative/graphicsitems/qdeclarativeflickable_p.h b/src/declarative/graphicsitems/qdeclarativeflickable_p.h index f031a24..05887b8 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable_p.h +++ b/src/declarative/graphicsitems/qdeclarativeflickable_p.h @@ -69,8 +69,13 @@ class Q_DECLARATIVE_EXPORT QDeclarativeFlickable : public QDeclarativeItem Q_PROPERTY(qreal maximumFlickVelocity READ maximumFlickVelocity WRITE setMaximumFlickVelocity NOTIFY maximumFlickVelocityChanged) Q_PROPERTY(qreal flickDeceleration READ flickDeceleration WRITE setFlickDeceleration NOTIFY flickDecelerationChanged) Q_PROPERTY(bool moving READ isMoving NOTIFY movingChanged) + Q_PROPERTY(bool movingHorizontally READ isMovingHorizontally NOTIFY movingHorizontallyChanged) + Q_PROPERTY(bool movingVertically READ isMovingVertically NOTIFY movingVerticallyChanged) Q_PROPERTY(bool flicking READ isFlicking NOTIFY flickingChanged) - Q_PROPERTY(FlickDirection flickDirection READ flickDirection WRITE setFlickDirection NOTIFY flickDirectionChanged) + Q_PROPERTY(bool flickingHorizontally READ isFlickingHorizontally NOTIFY flickingHorizontallyChanged) + Q_PROPERTY(bool flickingVertically READ isFlickingVertically NOTIFY flickingVerticallyChanged) + Q_PROPERTY(FlickableDirection flickDirection READ flickDirection WRITE setFlickDirection NOTIFY flickableDirectionChanged) // deprecated + Q_PROPERTY(FlickableDirection flickableDirection READ flickableDirection WRITE setFlickableDirection NOTIFY flickableDirectionChanged) Q_PROPERTY(bool interactive READ isInteractive WRITE setInteractive NOTIFY interactiveChanged) Q_PROPERTY(int pressDelay READ pressDelay WRITE setPressDelay NOTIFY pressDelayChanged) @@ -86,7 +91,7 @@ class Q_DECLARATIVE_EXPORT QDeclarativeFlickable : public QDeclarativeItem Q_PROPERTY(QDeclarativeListProperty<QGraphicsObject> flickableChildren READ flickableChildren) Q_CLASSINFO("DefaultProperty", "flickableData") - Q_ENUMS(FlickDirection) + Q_ENUMS(FlickableDirection) Q_ENUMS(BoundsBehavior) public: @@ -116,7 +121,11 @@ public: void setContentY(qreal pos); bool isMoving() const; + bool isMovingHorizontally() const; + bool isMovingVertically() const; bool isFlicking() const; + bool isFlickingHorizontally() const; + bool isFlickingVertically() const; int pressDelay() const; void setPressDelay(int delay); @@ -140,9 +149,11 @@ public: QDeclarativeItem *viewport(); - enum FlickDirection { AutoFlickDirection=0x00, HorizontalFlick=0x01, VerticalFlick=0x02, HorizontalAndVerticalFlick=0x03 }; - FlickDirection flickDirection() const; - void setFlickDirection(FlickDirection); + enum FlickableDirection { AutoFlickDirection=0x00, HorizontalFlick=0x01, VerticalFlick=0x02, HorizontalAndVerticalFlick=0x03 }; + FlickableDirection flickDirection() const; // deprecated + void setFlickDirection(FlickableDirection); // deprecated + FlickableDirection flickableDirection() const; + void setFlickableDirection(FlickableDirection); Q_SIGNALS: void contentWidthChanged(); @@ -150,22 +161,26 @@ Q_SIGNALS: void contentXChanged(); void contentYChanged(); void movingChanged(); + void movingHorizontallyChanged(); + void movingVerticallyChanged(); void flickingChanged(); - void movementStarted(); - void movementEnded(); - void flickStarted(); - void flickEnded(); + void flickingHorizontallyChanged(); + void flickingVerticallyChanged(); void horizontalVelocityChanged(); void verticalVelocityChanged(); void isAtBoundaryChanged(); void pageChanged(); - void flickDirectionChanged(); + void flickableDirectionChanged(); void interactiveChanged(); void overShootChanged(); void boundsBehaviorChanged(); void maximumFlickVelocityChanged(); void flickDecelerationChanged(); void pressDelayChanged(); + void movementStarted(); + void movementEnded(); + void flickStarted(); + void flickEnded(); protected: virtual bool sceneEventFilter(QGraphicsItem *, QEvent *); diff --git a/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h b/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h index 01cfb18..b467ed2 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h @@ -131,8 +131,12 @@ public: AxisData vData; QDeclarativeTimeLine timeline; - bool flicked : 1; - bool moving : 1; + bool flickingHorizontally : 1; + bool flickingVertically : 1; + bool hMoved : 1; + bool vMoved : 1; + bool movingHorizontally : 1; + bool movingVertically : 1; bool stealMouse : 1; bool pressed : 1; bool interactive : 1; @@ -158,7 +162,7 @@ public: int vTime; QDeclarativeTimeLine velocityTimeline; QDeclarativeFlickableVisibleArea *visibleArea; - QDeclarativeFlickable::FlickDirection flickDirection; + QDeclarativeFlickable::FlickableDirection flickableDirection; QDeclarativeFlickable::BoundsBehavior boundsBehavior; void handleMousePressEvent(QGraphicsSceneMouseEvent *); diff --git a/src/declarative/graphicsitems/qdeclarativegridview.cpp b/src/declarative/graphicsitems/qdeclarativegridview.cpp index 7b413fb..e1874b8 100644 --- a/src/declarative/graphicsitems/qdeclarativegridview.cpp +++ b/src/declarative/graphicsitems/qdeclarativegridview.cpp @@ -349,7 +349,7 @@ void QDeclarativeGridViewPrivate::init() Q_Q(QDeclarativeGridView); QObject::connect(q, SIGNAL(movementEnded()), q, SLOT(animStopped())); q->setFlag(QGraphicsItem::ItemIsFocusScope); - q->setFlickDirection(QDeclarativeFlickable::VerticalFlick); + q->setFlickableDirection(QDeclarativeFlickable::VerticalFlick); addItemChangeListener(this, Geometry); } @@ -692,7 +692,7 @@ void QDeclarativeGridViewPrivate::updateHighlight() { if ((!currentItem && highlight) || (currentItem && !highlight)) createHighlight(); - if (currentItem && autoHighlight && highlight && !moving) { + if (currentItem && autoHighlight && highlight && !movingHorizontally && !movingVertically) { // auto-update highlight highlightXAnimator->to = currentItem->item->x(); highlightYAnimator->to = currentItem->item->y(); @@ -806,7 +806,8 @@ void QDeclarativeGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal m Q_Q(QDeclarativeGridView); moveReason = Mouse; - if ((!haveHighlightRange || highlightRange != QDeclarativeGridView::StrictlyEnforceRange) && snapMode == QDeclarativeGridView::NoSnap) { + if ((!haveHighlightRange || highlightRange != QDeclarativeGridView::StrictlyEnforceRange) + && snapMode == QDeclarativeGridView::NoSnap) { QDeclarativeFlickablePrivate::flick(data, minExtent, maxExtent, vSize, fixupCallback, velocity); return; } @@ -874,9 +875,18 @@ void QDeclarativeGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal m timeline.reset(data.move); timeline.accel(data.move, v, accel, maxDistance + overshootDist); timeline.callback(QDeclarativeTimeLineCallback(&data.move, fixupCallback, this)); - flicked = true; - emit q->flickingChanged(); - emit q->flickStarted(); + if (!flickingHorizontally && q->xflick()) { + flickingHorizontally = true; + emit q->flickingChanged(); + emit q->flickingHorizontallyChanged(); + emit q->flickStarted(); + } + if (!flickingVertically && q->yflick()) { + flickingVertically = true; + emit q->flickingChanged(); + emit q->flickingVerticallyChanged(); + emit q->flickStarted(); + } } else { timeline.reset(data.move); fixup(data, minExtent, maxExtent); @@ -1027,7 +1037,7 @@ void QDeclarativeGridView::setModel(const QVariant &model) d->model = vim; } else { if (!d->ownModel) { - d->model = new QDeclarativeVisualDataModel(qmlContext(this)); + d->model = new QDeclarativeVisualDataModel(qmlContext(this), this); d->ownModel = true; } if (QDeclarativeVisualDataModel *dataModel = qobject_cast<QDeclarativeVisualDataModel*>(d->model)) @@ -1371,10 +1381,10 @@ void QDeclarativeGridView::setFlow(Flow flow) d->flow = flow; if (d->flow == LeftToRight) { setContentWidth(-1); - setFlickDirection(QDeclarativeFlickable::VerticalFlick); + setFlickableDirection(QDeclarativeFlickable::VerticalFlick); } else { setContentHeight(-1); - setFlickDirection(QDeclarativeFlickable::HorizontalFlick); + setFlickableDirection(QDeclarativeFlickable::HorizontalFlick); } d->clear(); d->updateGrid(); @@ -1530,7 +1540,7 @@ void QDeclarativeGridView::viewportMoved() Q_D(QDeclarativeGridView); QDeclarativeFlickable::viewportMoved(); d->lazyRelease = true; - if (d->flicked) { + if (d->flickingHorizontally || d->flickingVertically) { if (yflick()) { if (d->vData.velocity > 0) d->bufferMode = QDeclarativeGridViewPrivate::BufferBefore; @@ -1546,7 +1556,7 @@ void QDeclarativeGridView::viewportMoved() } } refill(); - if (isFlicking() || d->moving) + if (d->flickingHorizontally || d->flickingVertically || d->movingHorizontally || d->movingVertically) d->moveReason = QDeclarativeGridViewPrivate::Mouse; if (d->moveReason != QDeclarativeGridViewPrivate::SetIndex) { if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) { @@ -1641,6 +1651,9 @@ qreal QDeclarativeGridView::maxXExtent() const void QDeclarativeGridView::keyPressEvent(QKeyEvent *event) { Q_D(QDeclarativeGridView); + keyPressPreHandler(event); + if (event->isAccepted()) + return; if (d->model && d->model->count() && d->interactive) { d->moveReason = QDeclarativeGridViewPrivate::SetIndex; int oldCurrent = currentIndex(); @@ -1666,10 +1679,8 @@ void QDeclarativeGridView::keyPressEvent(QKeyEvent *event) } } d->moveReason = QDeclarativeGridViewPrivate::Other; - QDeclarativeFlickable::keyPressEvent(event); - if (event->isAccepted()) - return; event->ignore(); + QDeclarativeFlickable::keyPressEvent(event); } /*! @@ -1885,7 +1896,8 @@ void QDeclarativeGridView::trackedPositionChanged() Q_D(QDeclarativeGridView); if (!d->trackedItem || !d->currentItem) return; - if (!isFlicking() && !d->moving && d->moveReason == QDeclarativeGridViewPrivate::SetIndex) { + if (!d->flickingHorizontally && !d->flickingVertically && !d->movingHorizontally && !d->movingVertically + && d->moveReason == QDeclarativeGridViewPrivate::SetIndex) { const qreal trackedPos = d->trackedItem->rowPos(); const qreal viewPos = d->position(); if (d->haveHighlightRange) { diff --git a/src/declarative/graphicsitems/qdeclarativegridview_p.h b/src/declarative/graphicsitems/qdeclarativegridview_p.h index c06879e..2bf154c 100644 --- a/src/declarative/graphicsitems/qdeclarativegridview_p.h +++ b/src/declarative/graphicsitems/qdeclarativegridview_p.h @@ -82,6 +82,8 @@ class Q_DECLARATIVE_EXPORT QDeclarativeGridView : public QDeclarativeFlickable Q_ENUMS(HighlightRangeMode) Q_ENUMS(SnapMode) + Q_ENUMS(Flow) + Q_ENUMS(PositionMode) Q_CLASSINFO("DefaultProperty", "data") public: @@ -120,7 +122,6 @@ public: qreal preferredHighlightEnd() const; void setPreferredHighlightEnd(qreal); - Q_ENUMS(Flow) enum Flow { LeftToRight, TopToBottom }; Flow flow() const; void setFlow(Flow); @@ -142,7 +143,6 @@ public: void setSnapMode(SnapMode mode); enum PositionMode { Beginning, Center, End, Visible, Contain }; - Q_ENUMS(PositionMode); Q_INVOKABLE void positionViewAtIndex(int index, int mode); Q_INVOKABLE int indexAt(int x, int y) const; diff --git a/src/declarative/graphicsitems/qdeclarativeimage.cpp b/src/declarative/graphicsitems/qdeclarativeimage.cpp index aeddb15..fe642e0 100644 --- a/src/declarative/graphicsitems/qdeclarativeimage.cpp +++ b/src/declarative/graphicsitems/qdeclarativeimage.cpp @@ -54,79 +54,37 @@ QT_BEGIN_NAMESPACE \brief The Image element allows you to add bitmaps to a scene. \inherits Item - Displays the image from the specified \l source. If a size is not specified explicitly, - the Image element will be sized to the loaded image. + An Image element displays a specified \l source image: - If the source resolves to a network resource, the image will be loaded asynchronously, - updating the \l progress and \l status properties appropriately. + \table + \row + \o + \image declarative-qtlogo.png + \o + \qml + import Qt 4.7 + + Image { source: "qtlogo.png" } + \endqml + \endtable + + If a size is not specified explicitly, the Image element is sized to the loaded image. + Image elements can be stretched and tiled using the \l fillMode property. - Images which are available locally - will be loaded immediately, blocking the user interface. This is typically the - correct behavior for user interface elements. For large local images, which do not need - to be visible immediately, it may be preferable to enable \l asynchronous loading. - This will load the image in the background using a low priority thread. + If the image \l source is a network resource, the image is loaded asynchronous and the + \l progress and \l status properties are updated appropriately. Otherwise, if the image is + available locally, it is loaded immediately and the user interface is blocked until loading is + complete. (This is typically the correct behavior for user interface elements.) + For large local images, which do not need to be visible immediately, it may be preferable to + enable \l asynchronous loading. This loads the image in the background using a low priority thread. Images are cached and shared internally, so if several Image elements have the same source only one copy of the image will be loaded. - \bold Note: Images are often the greatest user of memory in QML UIs. It is recommended + \bold Note: Images are often the greatest user of memory in QML user interfaces. It is recommended that images which do not form part of the user interface have their size bounded via the \l sourceSize property. This is especially important for content that is loaded from external sources or provided by the user. - - The Image element supports untransformed, stretched and tiled images. - - For an explanation of stretching and tiling, see the fillMode property description. - - Examples: - \table - \row - \o \image declarative-qtlogo1.png - \o Untransformed - \qml - Image { source: "pics/qtlogo.png" } - \endqml - \row - \o \image declarative-qtlogo2.png - \o fillMode: Stretch (default) - \qml - Image { - width: 160 - height: 160 - source: "pics/qtlogo.png" - } - \endqml - \row - \o \image declarative-qtlogo3.png - \o fillMode: Tile - \qml - Image { - fillMode: Image.Tile - width: 160; height: 160 - source: "pics/qtlogo.png" - } - \endqml - \row - \o \image declarative-qtlogo6.png - \o fillMode: TileVertically - \qml - Image { - fillMode: Image.TileVertically - width: 160; height: 160 - source: "pics/qtlogo.png" - } - \endqml - \row - \o \image declarative-qtlogo5.png - \o fillMode: TileHorizontally - \qml - Image { - fillMode: Image.TileHorizontally - width: 160; height: 160 - source: "pics/qtlogo.png" - } - \endqml - \endtable */ /*! @@ -207,7 +165,77 @@ void QDeclarativeImagePrivate::setPixmap(const QPixmap &pixmap) \o Image.TileHorizontally - the image is stretched vertically and tiled horizontally \endlist - \image declarative-image_fillMode.gif + \table + + \row + \o \image declarative-qtlogo-stretch.png + \o Stretch (default) + \qml + Image { + width: 130; height: 100 + smooth: true + source: "qtlogo.png" + } + \endqml + + \row + \o \image declarative-qtlogo-preserveaspectfit.png + \o PreserveAspectFit + \qml + Image { + width: 130; height: 100 + fillMode: Image.PreserveAspectFit + smooth: true + source: "qtlogo.png" + } + \endqml + + \row + \o \image declarative-qtlogo-preserveaspectcrop.png + \o PreserveAspectCrop + \qml + Image { + width: 130; height: 100 + fillMode: Image.PreserveAspectCrop + smooth: true + source: "qtlogo.png" + } + \endqml + + \row + \o \image declarative-qtlogo-tile.png + \o Tile + \qml + Image { + width: 120; height: 120 + fillMode: Image.Tile + source: "qtlogo.png" + } + \endqml + + \row + \o \image declarative-qtlogo-tilevertically.png + \o TileVertically + \qml + Image { + width: 120; height: 120 + fillMode: Image.TileVertically + source: "qtlogo.png" + } + \endqml + + \row + \o \image declarative-qtlogo-tilehorizontally.png + \o TileHorizontally + \qml + Image { + width: 120; height: 120 + fillMode: Image.TileHorizontally + source: "qtlogo.png" + } + \endqml + + \endtable */ QDeclarativeImage::FillMode QDeclarativeImage::fillMode() const { @@ -290,32 +318,30 @@ qreal QDeclarativeImage::paintedHeight() const /*! \qmlproperty QSize Image::sourceSize - This properties is the size of the loaded image, in pixels. + This property holds the size of the loaded image, in pixels. - If you set this property explicitly, you can to control the storage - used by a loaded image. The image will be scaled down if its intrinsic size - is greater than this value. - - If only one dimension of the size is set (and the other left at 0), the - unset dimension will be set in proportion to the set dimension to preserve - the source image aspect ratio. The fillMode is independent of this. - - Unlike setting the width and height properties, which merely scale the painting - of the image, this property affects the number of pixels stored. - - \e{Changing this property dynamically will lead to the image source being reloaded, - potentially even from the network if it is not in the disk cache.} + This is used to control the storage used by a loaded image. Unlike + the width and height properties, which scale the painting of the image, this property + affects the number of pixels stored. + If the image's actual size is larger than the sourceSize, the image is scaled down. + If only one dimension of the size is set to greater than 0, the + other dimension is set in proportion to preserve the source image's aspect ratio. + (The \l fillMode is independent of this.) + If the source is an instrinsically scalable image (eg. SVG), this property - determines the size of the loaded image regardless of intrinsic size. You should - avoid changing this property dynamically - rendering an SVG is \e slow compared + determines the size of the loaded image regardless of intrinsic size. + Avoid changing this property dynamically; rendering an SVG is \e slow compared to an image. If the source is a non-scalable image (eg. JPEG), the loaded image will be no greater than this property specifies. For some formats (currently only JPEG), the whole image will never actually be loaded into memory. + + \note \e{Changing this property dynamically will lead to the image source being reloaded, + potentially even from the network if it is not in the disk cache.} - The example below will ensure that the size of the image in memory is + Here is an example that ensures the size of the image in memory is no larger than 1024x1024 pixels, regardless of the size of the Image element. \code @@ -327,8 +353,8 @@ qreal QDeclarativeImage::paintedHeight() const } \endcode - The example below will ensure that the memory used by the image is - no more than necessary to display the image at the size of the Image element. + The example below ensures the memory used by the image is no more than necessary + to display the image at the size of the Image element. Of course if the Image element is resized a costly reload will be required, so use this technique \e only when the Image size is fixed. diff --git a/src/declarative/graphicsitems/qdeclarativeitem.cpp b/src/declarative/graphicsitems/qdeclarativeitem.cpp index 9433ba0..9547884 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitem.cpp @@ -375,7 +375,7 @@ void QDeclarativeContents::childAdded(QDeclarativeItem *item) } QDeclarativeItemKeyFilter::QDeclarativeItemKeyFilter(QDeclarativeItem *item) -: m_next(0) +: m_processPost(false), m_next(0) { QDeclarativeItemPrivate *p = item?static_cast<QDeclarativeItemPrivate *>(QGraphicsItemPrivate::get(item)):0; @@ -389,19 +389,19 @@ QDeclarativeItemKeyFilter::~QDeclarativeItemKeyFilter() { } -void QDeclarativeItemKeyFilter::keyPressed(QKeyEvent *event) +void QDeclarativeItemKeyFilter::keyPressed(QKeyEvent *event, bool post) { - if (m_next) m_next->keyPressed(event); + if (m_next) m_next->keyPressed(event, post); } -void QDeclarativeItemKeyFilter::keyReleased(QKeyEvent *event) +void QDeclarativeItemKeyFilter::keyReleased(QKeyEvent *event, bool post) { - if (m_next) m_next->keyReleased(event); + if (m_next) m_next->keyReleased(event, post); } -void QDeclarativeItemKeyFilter::inputMethodEvent(QInputMethodEvent *event) +void QDeclarativeItemKeyFilter::inputMethodEvent(QInputMethodEvent *event, bool post) { - if (m_next) m_next->inputMethodEvent(event); + if (m_next) m_next->inputMethodEvent(event, post); } QVariant QDeclarativeItemKeyFilter::inputMethodQuery(Qt::InputMethodQuery query) const @@ -463,9 +463,11 @@ void QDeclarativeItemKeyFilter::componentComplete() } \endcode - KeyNavigation receives key events after the item it is attached to. + By default KeyNavigation receives key events after the item it is attached to. If the item accepts an arrow key event, the KeyNavigation - attached property will not receive an event for that key. + attached property will not receive an event for that key. Setting the + \l priority property to KeyNavigation.BeforeItem allows handling + of the key events before normal item processing. If an item has been set for a direction and the KeyNavigation attached property receives the corresponding @@ -490,6 +492,7 @@ QDeclarativeKeyNavigationAttached::QDeclarativeKeyNavigationAttached(QObject *pa : QObject(*(new QDeclarativeKeyNavigationAttachedPrivate), parent), QDeclarativeItemKeyFilter(qobject_cast<QDeclarativeItem*>(parent)) { + m_processPost = true; } QDeclarativeKeyNavigationAttached * @@ -576,12 +579,45 @@ void QDeclarativeKeyNavigationAttached::setBacktab(QDeclarativeItem *i) emit changed(); } -void QDeclarativeKeyNavigationAttached::keyPressed(QKeyEvent *event) +/*! + \qmlproperty enumeration KeyNavigation::priority + + This property determines whether the keys are processed before + or after the attached item's own key handling. + + \list + \o KeyNavigation.BeforeItem - process the key events before normal + item key processing. If the event is accepted it will not + be passed on to the item. + \o KeyNavigation.AfterItem (default) - process the key events after normal item key + handling. If the item accepts the key event it will not be + handled by the KeyNavigation attached property handler. + \endlist +*/ +QDeclarativeKeyNavigationAttached::Priority QDeclarativeKeyNavigationAttached::priority() const { - Q_D(QDeclarativeKeyNavigationAttached); + return m_processPost ? AfterItem : BeforeItem; +} + +void QDeclarativeKeyNavigationAttached::setPriority(Priority order) +{ + bool processPost = order == AfterItem; + if (processPost != m_processPost) { + m_processPost = processPost; + emit priorityChanged(); + } +} +void QDeclarativeKeyNavigationAttached::keyPressed(QKeyEvent *event, bool post) +{ + Q_D(QDeclarativeKeyNavigationAttached); event->ignore(); + if (post != m_processPost) { + QDeclarativeItemKeyFilter::keyPressed(event, post); + return; + } + switch(event->key()) { case Qt::Key_Left: if (d->left) { @@ -623,15 +659,19 @@ void QDeclarativeKeyNavigationAttached::keyPressed(QKeyEvent *event) break; } - if (!event->isAccepted()) QDeclarativeItemKeyFilter::keyPressed(event); + if (!event->isAccepted()) QDeclarativeItemKeyFilter::keyPressed(event, post); } -void QDeclarativeKeyNavigationAttached::keyReleased(QKeyEvent *event) +void QDeclarativeKeyNavigationAttached::keyReleased(QKeyEvent *event, bool post) { Q_D(QDeclarativeKeyNavigationAttached); - event->ignore(); + if (post != m_processPost) { + QDeclarativeItemKeyFilter::keyReleased(event, post); + return; + } + switch(event->key()) { case Qt::Key_Left: if (d->left) { @@ -667,7 +707,7 @@ void QDeclarativeKeyNavigationAttached::keyReleased(QKeyEvent *event) break; } - if (!event->isAccepted()) QDeclarativeItemKeyFilter::keyReleased(event); + if (!event->isAccepted()) QDeclarativeItemKeyFilter::keyReleased(event, post); } /*! @@ -709,6 +749,28 @@ void QDeclarativeKeyNavigationAttached::keyReleased(QKeyEvent *event) See \l {Qt::Key}{Qt.Key} for the list of keyboard codes. + If priority is Keys.BeforeItem (default) the order of key event processing is: + + \list 1 + \o Items specified in \c forwardTo + \o specific key handlers, e.g. onReturnPressed + \o onKeyPress, onKeyRelease handlers + \o Item specific key handling, e.g. TextInput key handling + \o parent item + \endlist + + If priority is Keys.AfterItem the order of key event processing is: + \list 1 + \o Item specific key handling, e.g. TextInput key handling + \o Items specified in \c forwardTo + \o specific key handlers, e.g. onReturnPressed + \o onKeyPress, onKeyRelease handlers + \o parent item + \endlist + + If the event is accepted during any of the above steps, key + propagation stops. + \sa KeyEvent, {KeyNavigation}{KeyNavigation attached property} */ @@ -720,6 +782,22 @@ void QDeclarativeKeyNavigationAttached::keyReleased(QKeyEvent *event) */ /*! + \qmlproperty enumeration Keys::priority + + This property determines whether the keys are processed before + or after the attached item's own key handling. + + \list + \o Keys.BeforeItem (default) - process the key events before normal + item key processing. If the event is accepted it will not + be passed on to the item. + \o Keys.AfterItem - process the key events after normal item key + handling. If the item accepts the key event it will not be + handled by the Keys attached property handler. + \endlist +*/ + +/*! \qmlproperty list<Object> Keys::forwardTo This property provides a way to forward key presses, key releases, and keyboard input @@ -1039,6 +1117,7 @@ QDeclarativeKeysAttached::QDeclarativeKeysAttached(QObject *parent) QDeclarativeItemKeyFilter(qobject_cast<QDeclarativeItem*>(parent)) { Q_D(QDeclarativeKeysAttached); + m_processPost = false; d->item = qobject_cast<QDeclarativeItem*>(parent); } @@ -1046,6 +1125,20 @@ QDeclarativeKeysAttached::~QDeclarativeKeysAttached() { } +QDeclarativeKeysAttached::Priority QDeclarativeKeysAttached::priority() const +{ + return m_processPost ? AfterItem : BeforeItem; +} + +void QDeclarativeKeysAttached::setPriority(Priority order) +{ + bool processPost = order == AfterItem; + if (processPost != m_processPost) { + m_processPost = processPost; + emit priorityChanged(); + } +} + void QDeclarativeKeysAttached::componentComplete() { Q_D(QDeclarativeKeysAttached); @@ -1060,11 +1153,12 @@ void QDeclarativeKeysAttached::componentComplete() } } -void QDeclarativeKeysAttached::keyPressed(QKeyEvent *event) +void QDeclarativeKeysAttached::keyPressed(QKeyEvent *event, bool post) { Q_D(QDeclarativeKeysAttached); - if (!d->enabled || d->inPress) { + if (post != m_processPost || !d->enabled || d->inPress) { event->ignore(); + QDeclarativeItemKeyFilter::keyPressed(event, post); return; } @@ -1099,14 +1193,15 @@ void QDeclarativeKeysAttached::keyPressed(QKeyEvent *event) emit pressed(&ke); event->setAccepted(ke.isAccepted()); - if (!event->isAccepted()) QDeclarativeItemKeyFilter::keyPressed(event); + if (!event->isAccepted()) QDeclarativeItemKeyFilter::keyPressed(event, post); } -void QDeclarativeKeysAttached::keyReleased(QKeyEvent *event) +void QDeclarativeKeysAttached::keyReleased(QKeyEvent *event, bool post) { Q_D(QDeclarativeKeysAttached); - if (!d->enabled || d->inRelease) { + if (post != m_processPost || !d->enabled || d->inRelease) { event->ignore(); + QDeclarativeItemKeyFilter::keyReleased(event, post); return; } @@ -1129,13 +1224,13 @@ void QDeclarativeKeysAttached::keyReleased(QKeyEvent *event) emit released(&ke); event->setAccepted(ke.isAccepted()); - if (!event->isAccepted()) QDeclarativeItemKeyFilter::keyReleased(event); + if (!event->isAccepted()) QDeclarativeItemKeyFilter::keyReleased(event, post); } -void QDeclarativeKeysAttached::inputMethodEvent(QInputMethodEvent *event) +void QDeclarativeKeysAttached::inputMethodEvent(QInputMethodEvent *event, bool post) { Q_D(QDeclarativeKeysAttached); - if (d->item && !d->inIM && d->item->scene()) { + if (post == m_processPost && d->item && !d->inIM && d->item->scene()) { d->inIM = true; for (int ii = 0; ii < d->targets.count(); ++ii) { QGraphicsItem *i = d->finalFocusProxy(d->targets.at(ii)); @@ -1150,7 +1245,7 @@ void QDeclarativeKeysAttached::inputMethodEvent(QInputMethodEvent *event) } d->inIM = false; } - if (!event->isAccepted()) QDeclarativeItemKeyFilter::inputMethodEvent(event); + if (!event->isAccepted()) QDeclarativeItemKeyFilter::inputMethodEvent(event, post); } class QDeclarativeItemAccessor : public QGraphicsItem @@ -1194,7 +1289,10 @@ QDeclarativeKeysAttached *QDeclarativeKeysAttached::qmlAttachedProperties(QObjec width and height, \l {anchor-layout}{anchoring} and key handling. You can subclass QDeclarativeItem to provide your own custom visual item that inherits - these features. + these features. Note that, because it does not draw anything, QDeclarativeItem sets the + QGraphicsItem::ItemHasNoContents flag. If you subclass QDeclarativeItem to create a visual + item, you will need to unset this flag. + */ /*! @@ -1819,8 +1917,11 @@ void QDeclarativeItemPrivate::removeItemChangeListener(QDeclarativeItemChangeLis void QDeclarativeItem::keyPressEvent(QKeyEvent *event) { Q_D(QDeclarativeItem); + keyPressPreHandler(event); + if (event->isAccepted()) + return; if (d->keyHandler) - d->keyHandler->keyPressed(event); + d->keyHandler->keyPressed(event, true); else event->ignore(); } @@ -1829,8 +1930,11 @@ void QDeclarativeItem::keyPressEvent(QKeyEvent *event) void QDeclarativeItem::keyReleaseEvent(QKeyEvent *event) { Q_D(QDeclarativeItem); + keyReleasePreHandler(event); + if (event->isAccepted()) + return; if (d->keyHandler) - d->keyHandler->keyReleased(event); + d->keyHandler->keyReleased(event, true); else event->ignore(); } @@ -1839,8 +1943,11 @@ void QDeclarativeItem::keyReleaseEvent(QKeyEvent *event) void QDeclarativeItem::inputMethodEvent(QInputMethodEvent *event) { Q_D(QDeclarativeItem); + inputMethodPreHandler(event); + if (event->isAccepted()) + return; if (d->keyHandler) - d->keyHandler->inputMethodEvent(event); + d->keyHandler->inputMethodEvent(event, true); else event->ignore(); } @@ -1859,6 +1966,37 @@ QVariant QDeclarativeItem::inputMethodQuery(Qt::InputMethodQuery query) const return v; } +void QDeclarativeItem::keyPressPreHandler(QKeyEvent *event) +{ + Q_D(QDeclarativeItem); + if (d->keyHandler && !d->doneEventPreHandler) + d->keyHandler->keyPressed(event, false); + else + event->ignore(); + d->doneEventPreHandler = true; +} + +void QDeclarativeItem::keyReleasePreHandler(QKeyEvent *event) +{ + Q_D(QDeclarativeItem); + if (d->keyHandler && !d->doneEventPreHandler) + d->keyHandler->keyReleased(event, false); + else + event->ignore(); + d->doneEventPreHandler = true; +} + +void QDeclarativeItem::inputMethodPreHandler(QInputMethodEvent *event) +{ + Q_D(QDeclarativeItem); + if (d->keyHandler && !d->doneEventPreHandler) + d->keyHandler->inputMethodEvent(event, false); + else + event->ignore(); + d->doneEventPreHandler = true; +} + + /*! \internal */ @@ -2973,6 +3111,17 @@ void QDeclarativeItem::paint(QPainter *, const QStyleOptionGraphicsItem *, QWidg */ bool QDeclarativeItem::event(QEvent *ev) { + Q_D(QDeclarativeItem); + switch (ev->type()) { + case QEvent::KeyPress: + case QEvent::KeyRelease: + case QEvent::InputMethod: + d->doneEventPreHandler = false; + break; + default: + break; + } + return QGraphicsObject::event(ev); } diff --git a/src/declarative/graphicsitems/qdeclarativeitem.h b/src/declarative/graphicsitems/qdeclarativeitem.h index 3b05b09..29fd241 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem.h +++ b/src/declarative/graphicsitems/qdeclarativeitem.h @@ -178,6 +178,10 @@ protected: virtual void keyReleaseEvent(QKeyEvent *event); virtual void inputMethodEvent(QInputMethodEvent *); virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const; + void keyPressPreHandler(QKeyEvent *); + void keyReleasePreHandler(QKeyEvent *); + void inputMethodPreHandler(QInputMethodEvent *); + virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry); diff --git a/src/declarative/graphicsitems/qdeclarativeitem_p.h b/src/declarative/graphicsitems/qdeclarativeitem_p.h index 516d6d0..15b34f0 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem_p.h +++ b/src/declarative/graphicsitems/qdeclarativeitem_p.h @@ -124,7 +124,7 @@ public: _stateGroup(0), origin(QDeclarativeItem::Center), widthValid(false), heightValid(false), _componentComplete(true), _keepMouse(false), - smooth(false), transformOriginDirty(true), keyHandler(0), + smooth(false), transformOriginDirty(true), doneEventPreHandler(false), keyHandler(0), mWidth(0), mHeight(0), implicitWidth(0), implicitHeight(0) { QGraphicsItemPrivate::acceptedMouseButtons = 0; @@ -263,6 +263,7 @@ public: bool _keepMouse:1; bool smooth:1; bool transformOriginDirty : 1; + bool doneEventPreHandler : 1; QDeclarativeItemKeyFilter *keyHandler; @@ -324,12 +325,14 @@ public: QDeclarativeItemKeyFilter(QDeclarativeItem * = 0); virtual ~QDeclarativeItemKeyFilter(); - virtual void keyPressed(QKeyEvent *event); - virtual void keyReleased(QKeyEvent *event); - virtual void inputMethodEvent(QInputMethodEvent *event); + virtual void keyPressed(QKeyEvent *event, bool post); + virtual void keyReleased(QKeyEvent *event, bool post); + virtual void inputMethodEvent(QInputMethodEvent *event, bool post); virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const; virtual void componentComplete(); + bool m_processPost; + private: QDeclarativeItemKeyFilter *m_next; }; @@ -359,6 +362,9 @@ class QDeclarativeKeyNavigationAttached : public QObject, public QDeclarativeIte Q_PROPERTY(QDeclarativeItem *down READ down WRITE setDown NOTIFY changed) Q_PROPERTY(QDeclarativeItem *tab READ tab WRITE setTab NOTIFY changed) Q_PROPERTY(QDeclarativeItem *backtab READ backtab WRITE setBacktab NOTIFY changed) + Q_PROPERTY(Priority priority READ priority WRITE setPriority NOTIFY priorityChanged) + + Q_ENUMS(Priority) public: QDeclarativeKeyNavigationAttached(QObject * = 0); @@ -376,14 +382,19 @@ public: QDeclarativeItem *backtab() const; void setBacktab(QDeclarativeItem *); + enum Priority { BeforeItem, AfterItem }; + Priority priority() const; + void setPriority(Priority); + static QDeclarativeKeyNavigationAttached *qmlAttachedProperties(QObject *); Q_SIGNALS: void changed(); + void priorityChanged(); private: - virtual void keyPressed(QKeyEvent *event); - virtual void keyReleased(QKeyEvent *event); + virtual void keyPressed(QKeyEvent *event, bool post); + virtual void keyReleased(QKeyEvent *event, bool post); }; class QDeclarativeKeysAttachedPrivate : public QObjectPrivate @@ -423,6 +434,9 @@ class QDeclarativeKeysAttached : public QObject, public QDeclarativeItemKeyFilte Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged) Q_PROPERTY(QDeclarativeListProperty<QDeclarativeItem> forwardTo READ forwardTo) + Q_PROPERTY(Priority priority READ priority WRITE setPriority NOTIFY priorityChanged) + + Q_ENUMS(Priority) public: QDeclarativeKeysAttached(QObject *parent=0); @@ -437,6 +451,10 @@ public: } } + enum Priority { BeforeItem, AfterItem}; + Priority priority() const; + void setPriority(Priority); + QDeclarativeListProperty<QDeclarativeItem> forwardTo() { Q_D(QDeclarativeKeysAttached); return QDeclarativeListProperty<QDeclarativeItem>(this, d->targets); @@ -448,6 +466,7 @@ public: Q_SIGNALS: void enabledChanged(); + void priorityChanged(); void pressed(QDeclarativeKeyEvent *event); void released(QDeclarativeKeyEvent *event); void digit0Pressed(QDeclarativeKeyEvent *event); @@ -492,9 +511,9 @@ Q_SIGNALS: void volumeDownPressed(QDeclarativeKeyEvent *event); private: - virtual void keyPressed(QKeyEvent *event); - virtual void keyReleased(QKeyEvent *event); - virtual void inputMethodEvent(QInputMethodEvent *); + virtual void keyPressed(QKeyEvent *event, bool post); + virtual void keyReleased(QKeyEvent *event, bool post); + virtual void inputMethodEvent(QInputMethodEvent *, bool post); virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const; const QByteArray keyToSignal(int key) { diff --git a/src/declarative/graphicsitems/qdeclarativelistview.cpp b/src/declarative/graphicsitems/qdeclarativelistview.cpp index 416e0a8..936f9b0 100644 --- a/src/declarative/graphicsitems/qdeclarativelistview.cpp +++ b/src/declarative/graphicsitems/qdeclarativelistview.cpp @@ -48,6 +48,7 @@ #include <qdeclarativeexpression.h> #include <qdeclarativeengine.h> #include <qdeclarativeguard_p.h> +#include <qdeclarativeinfo.h> #include <qlistmodelinterface_p.h> #include <qmath.h> @@ -525,7 +526,7 @@ void QDeclarativeListViewPrivate::init() q->setFlag(QGraphicsItem::ItemIsFocusScope); addItemChangeListener(this, Geometry); QObject::connect(q, SIGNAL(movementEnded()), q, SLOT(animStopped())); - q->setFlickDirection(QDeclarativeFlickable::VerticalFlick); + q->setFlickableDirection(QDeclarativeFlickable::VerticalFlick); ::memset(sectionCache, 0, sizeof(QDeclarativeItem*) * sectionCacheSize); } @@ -868,7 +869,7 @@ void QDeclarativeListViewPrivate::updateHighlight() { if ((!currentItem && highlight) || (currentItem && !highlight)) createHighlight(); - if (currentItem && autoHighlight && highlight && !moving) { + if (currentItem && autoHighlight && highlight && !movingHorizontally && !movingVertically) { // auto-update highlight highlightPosAnimator->to = currentItem->position(); highlightSizeAnimator->to = currentItem->size(); @@ -1208,7 +1209,7 @@ void QDeclarativeListViewPrivate::flick(AxisData &data, qreal minExtent, qreal m else v = maxVelocity; } - if (!flicked) { + if (!flickingHorizontally && !flickingVertically) { // the initial flick - estimate boundary qreal accel = deceleration; qreal v2 = v * v; @@ -1256,9 +1257,18 @@ void QDeclarativeListViewPrivate::flick(AxisData &data, qreal minExtent, qreal m timeline.reset(data.move); timeline.accel(data.move, v, accel, maxDistance + overshootDist); timeline.callback(QDeclarativeTimeLineCallback(&data.move, fixupCallback, this)); - flicked = true; - emit q->flickingChanged(); - emit q->flickStarted(); + if (!flickingHorizontally && q->xflick()) { + flickingHorizontally = true; + emit q->flickingChanged(); + emit q->flickingHorizontallyChanged(); + emit q->flickStarted(); + } + if (!flickingVertically && q->yflick()) { + flickingVertically = true; + emit q->flickingChanged(); + emit q->flickingVerticallyChanged(); + emit q->flickStarted(); + } correctFlick = true; } else { // reevaluate the target boundary. @@ -1461,7 +1471,7 @@ void QDeclarativeListView::setModel(const QVariant &model) d->model = vim; } else { if (!d->ownModel) { - d->model = new QDeclarativeVisualDataModel(qmlContext(this)); + d->model = new QDeclarativeVisualDataModel(qmlContext(this), this); d->ownModel = true; } if (QDeclarativeVisualDataModel *dataModel = qobject_cast<QDeclarativeVisualDataModel*>(d->model)) @@ -1804,10 +1814,10 @@ void QDeclarativeListView::setOrientation(QDeclarativeListView::Orientation orie d->orient = orientation; if (d->orient == QDeclarativeListView::Vertical) { setContentWidth(-1); - setFlickDirection(VerticalFlick); + setFlickableDirection(VerticalFlick); } else { setContentHeight(-1); - setFlickDirection(HorizontalFlick); + setFlickableDirection(HorizontalFlick); } d->clear(); d->setPosition(0); @@ -1898,7 +1908,7 @@ void QDeclarativeListView::setCacheBuffer(int b) pet. The section expression is the size property. If \c ListView.section and \c ListView.prevSection differ, the item will display a section header. - \snippet examples/declarative/listview/sections.qml 0 + \snippet examples/declarative/modelviews/listview/sections.qml 0 \image ListViewSections.png */ @@ -2106,7 +2116,7 @@ void QDeclarativeListView::viewportMoved() QDeclarativeFlickable::viewportMoved(); d->lazyRelease = true; refill(); - if (isFlicking() || d->moving) + if (d->flickingHorizontally || d->flickingVertically || d->movingHorizontally || d->movingVertically) d->moveReason = QDeclarativeListViewPrivate::Mouse; if (d->moveReason != QDeclarativeListViewPrivate::SetIndex) { if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) { @@ -2126,7 +2136,7 @@ void QDeclarativeListView::viewportMoved() } } - if (d->flicked && d->correctFlick && !d->inFlickCorrection) { + if ((d->flickingHorizontally || d->flickingVertically) && d->correctFlick && !d->inFlickCorrection) { d->inFlickCorrection = true; // Near an end and it seems that the extent has changed? // Recalculate the flick so that we don't end up in an odd position. @@ -2253,6 +2263,9 @@ qreal QDeclarativeListView::maxXExtent() const void QDeclarativeListView::keyPressEvent(QKeyEvent *event) { Q_D(QDeclarativeListView); + keyPressPreHandler(event); + if (event->isAccepted()) + return; if (d->model && d->model->count() && d->interactive) { if ((d->orient == QDeclarativeListView::Horizontal && event->key() == Qt::Key_Left) @@ -2277,10 +2290,8 @@ void QDeclarativeListView::keyPressEvent(QKeyEvent *event) } } } - QDeclarativeFlickable::keyPressEvent(event); - if (event->isAccepted()) - return; event->ignore(); + QDeclarativeFlickable::keyPressEvent(event); } /*! @@ -2446,7 +2457,8 @@ void QDeclarativeListView::trackedPositionChanged() Q_D(QDeclarativeListView); if (!d->trackedItem || !d->currentItem) return; - if (!isFlicking() && !d->moving && d->moveReason == QDeclarativeListViewPrivate::SetIndex) { + if (!d->flickingHorizontally && !d->flickingVertically && !d->movingHorizontally && !d->movingVertically + && d->moveReason == QDeclarativeListViewPrivate::SetIndex) { const qreal trackedPos = qCeil(d->trackedItem->position()); const qreal viewPos = d->position(); if (d->haveHighlightRange) { diff --git a/src/declarative/graphicsitems/qdeclarativelistview_p.h b/src/declarative/graphicsitems/qdeclarativelistview_p.h index 9c0b7dd..d6e8023 100644 --- a/src/declarative/graphicsitems/qdeclarativelistview_p.h +++ b/src/declarative/graphicsitems/qdeclarativelistview_p.h @@ -124,6 +124,7 @@ class Q_DECLARATIVE_EXPORT QDeclarativeListView : public QDeclarativeFlickable Q_ENUMS(HighlightRangeMode) Q_ENUMS(Orientation) Q_ENUMS(SnapMode) + Q_ENUMS(PositionMode) Q_CLASSINFO("DefaultProperty", "data") public: @@ -200,7 +201,6 @@ public: static QDeclarativeListViewAttached *qmlAttachedProperties(QObject *); enum PositionMode { Beginning, Center, End, Visible, Contain }; - Q_ENUMS(PositionMode); Q_INVOKABLE void positionViewAtIndex(int index, int mode); Q_INVOKABLE int indexAt(int x, int y) const; diff --git a/src/declarative/graphicsitems/qdeclarativeloader.cpp b/src/declarative/graphicsitems/qdeclarativeloader.cpp index 7edd53c..cbdfd87 100644 --- a/src/declarative/graphicsitems/qdeclarativeloader.cpp +++ b/src/declarative/graphicsitems/qdeclarativeloader.cpp @@ -321,6 +321,7 @@ void QDeclarativeLoaderPrivate::_q_sourceLoaded() emit q->statusChanged(); emit q->progressChanged(); emit q->itemChanged(); + emit q->loaded(); } } @@ -341,10 +342,13 @@ void QDeclarativeLoaderPrivate::_q_sourceLoaded() of the following ways: \list \o Create a state, so that a state change occurs, e.g. State{name: 'loaded'; when: loader.status = Loader.Ready;} - \o Do something inside the onStatusChanged signal handler, e.g. Loader{id: loader; onStatusChanged: if(loader.status == Loader.Ready) console.log('Loaded');} + \o Do something inside the onLoaded signal handler, e.g. Loader{id: loader; onLoaded: console.log('Loaded');} \o Bind to the status variable somewhere, e.g. Text{text: if(loader.status!=Loader.Ready){'Not Loaded';}else{'Loaded';}} \endlist \sa progress + + Note that if the source is a local file, the status will initially be Ready (or Error). While + there will be no onStatusChanged signal in that case, the onLoaded will still be invoked. */ QDeclarativeLoader::Status QDeclarativeLoader::status() const @@ -360,6 +364,21 @@ QDeclarativeLoader::Status QDeclarativeLoader::status() const return d->source.isEmpty() ? Null : Error; } +void QDeclarativeLoader::componentComplete() +{ + if (status() == Ready) + emit loaded(); +} + + +/*! + \qmlsignal Loader::onLoaded() + + This handler is called when the \l status becomes Loader.Ready, or on successful + initial load. +*/ + + /*! \qmlproperty real Loader::progress @@ -382,7 +401,6 @@ qreal QDeclarativeLoader::progress() const return 0.0; } - void QDeclarativeLoaderPrivate::_q_updateSize(bool loaderGeometryChanged) { Q_Q(QDeclarativeLoader); diff --git a/src/declarative/graphicsitems/qdeclarativeloader_p.h b/src/declarative/graphicsitems/qdeclarativeloader_p.h index 49dfa11..ec7ffe9 100644 --- a/src/declarative/graphicsitems/qdeclarativeloader_p.h +++ b/src/declarative/graphicsitems/qdeclarativeloader_p.h @@ -84,11 +84,14 @@ Q_SIGNALS: void sourceChanged(); void statusChanged(); void progressChanged(); + void loaded(); protected: void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry); QVariant itemChange(GraphicsItemChange change, const QVariant &value); bool eventFilter(QObject *watched, QEvent *e); + void componentComplete(); + private: Q_DISABLE_COPY(QDeclarativeLoader) Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarativeLoader) diff --git a/src/declarative/graphicsitems/qdeclarativepath.cpp b/src/declarative/graphicsitems/qdeclarativepath.cpp index 4d8b619..2d08c7c 100644 --- a/src/declarative/graphicsitems/qdeclarativepath.cpp +++ b/src/declarative/graphicsitems/qdeclarativepath.cpp @@ -322,6 +322,17 @@ QPainterPath QDeclarativePath::path() const QStringList QDeclarativePath::attributes() const { Q_D(const QDeclarativePath); + if (!d->componentComplete) { + QSet<QString> attrs; + + // First gather up all the attributes + foreach (QDeclarativePathElement *pathElement, d->_pathElements) { + if (QDeclarativePathAttribute *attribute = + qobject_cast<QDeclarativePathAttribute *>(pathElement)) + attrs.insert(attribute->name()); + } + return attrs.toList(); + } return d->_attributes; } @@ -366,7 +377,9 @@ void QDeclarativePath::createPointCache() const { Q_D(const QDeclarativePath); qreal pathLength = d->_path.length(); - const int points = int(pathLength*2); + // more points means less jitter between items as they move along the + // path, but takes longer to generate + const int points = int(pathLength*5); const int lastElement = d->_path.elementCount() - 1; d->_pointCache.resize(points+1); diff --git a/src/declarative/graphicsitems/qdeclarativepathview.cpp b/src/declarative/graphicsitems/qdeclarativepathview.cpp index 040fc98..207cc25 100644 --- a/src/declarative/graphicsitems/qdeclarativepathview.cpp +++ b/src/declarative/graphicsitems/qdeclarativepathview.cpp @@ -49,6 +49,7 @@ #include <qlistmodelinterface_p.h> #include <QGraphicsSceneEvent> +#include <qmath.h> #include <math.h> QT_BEGIN_NAMESPACE @@ -98,9 +99,8 @@ QDeclarativeItem *QDeclarativePathViewPrivate::getItem(int modelIndex) if (!attType) { // pre-create one metatype to share with all attached objects attType = new QDeclarativeOpenMetaObjectType(&QDeclarativePathViewAttached::staticMetaObject, qmlEngine(q)); - foreach(const QString &attr, path->attributes()) { + foreach(const QString &attr, path->attributes()) attType->createProperty(attr.toUtf8()); - } } qPathViewAttachedType = attType; QDeclarativePathViewAttached *att = static_cast<QDeclarativePathViewAttached *>(qmlAttachedPropertiesObject<QDeclarativePathView>(item)); @@ -280,8 +280,8 @@ void QDeclarativePathViewPrivate::updateItem(QDeclarativeItem *item, qreal perce att->setValue(attr.toUtf8(), path->attributeAt(attr, percent)); } QPointF pf = path->pointAt(percent); - item->setX(pf.x() - item->width()*item->scale()/2); - item->setY(pf.y() - item->height()*item->scale()/2); + item->setX(qRound(pf.x() - item->width()*item->scale()/2)); + item->setY(qRound(pf.y() - item->height()*item->scale()/2)); } void QDeclarativePathViewPrivate::regenerate() @@ -418,7 +418,7 @@ void QDeclarativePathView::setModel(const QVariant &model) d->model = vim; } else { if (!d->ownModel) { - d->model = new QDeclarativeVisualDataModel(qmlContext(this)); + d->model = new QDeclarativeVisualDataModel(qmlContext(this), this); d->ownModel = true; } if (QDeclarativeVisualDataModel *dataModel = qobject_cast<QDeclarativeVisualDataModel*>(d->model)) @@ -471,12 +471,14 @@ void QDeclarativePathView::setPath(QDeclarativePath *path) disconnect(d->path, SIGNAL(changed()), this, SLOT(refill())); d->path = path; connect(d->path, SIGNAL(changed()), this, SLOT(refill())); - d->clear(); - if (d->attType) { - d->attType->release(); - d->attType = 0; + if (d->isValid() && isComponentComplete()) { + d->clear(); + if (d->attType) { + d->attType->release(); + d->attType = 0; + } + d->regenerate(); } - d->regenerate(); emit pathChanged(); } @@ -526,6 +528,33 @@ void QDeclarativePathView::setCurrentIndex(int idx) } /*! + \qmlmethod PathView::incrementCurrentIndex() + + Increments the current index. +*/ +void QDeclarativePathView::incrementCurrentIndex() +{ + setCurrentIndex(currentIndex()+1); +} + + +/*! + \qmlmethod PathView::decrementCurrentIndex() + + Decrements the current index. +*/ +void QDeclarativePathView::decrementCurrentIndex() +{ + Q_D(QDeclarativePathView); + if (d->model && d->model->count()) { + int idx = currentIndex()-1; + if (idx < 0) + idx = d->model->count() - 1; + setCurrentIndex(idx); + } +} + +/*! \qmlproperty real PathView::offset The offset specifies how far along the path the items are from their initial positions. @@ -1119,7 +1148,8 @@ void QDeclarativePathView::refill() while ((pos > startPos || !d->items.count()) && d->items.count() < count) { // qDebug() << "append" << idx; QDeclarativeItem *item = d->getItem(idx); - item->setZValue(idx+1); + if (d->model->completePending()) + item->setZValue(idx+1); if (d->currentIndex == idx) { item->setFocus(true); if (QDeclarativePathViewAttached *att = d->attached(item)) @@ -1132,7 +1162,8 @@ void QDeclarativePathView::refill() d->firstIndex = idx; d->items.append(item); d->updateItem(item, pos); - d->model->completeItem(); + if (d->model->completePending()) + d->model->completeItem(); ++idx; if (idx >= d->model->count()) idx = 0; @@ -1146,7 +1177,8 @@ void QDeclarativePathView::refill() while (pos >= 0.0 && pos < startPos) { // qDebug() << "prepend" << idx; QDeclarativeItem *item = d->getItem(idx); - item->setZValue(idx+1); + if (d->model->completePending()) + item->setZValue(idx+1); if (d->currentIndex == idx) { item->setFocus(true); if (QDeclarativePathViewAttached *att = d->attached(item)) @@ -1157,7 +1189,8 @@ void QDeclarativePathView::refill() } d->items.prepend(item); d->updateItem(item, pos); - d->model->completeItem(); + if (d->model->completePending()) + d->model->completeItem(); d->firstIndex = idx; idx = d->firstIndex - 1; if (idx < 0) @@ -1269,6 +1302,19 @@ void QDeclarativePathView::createdItem(int index, QDeclarativeItem *item) { Q_D(QDeclarativePathView); if (d->requestedIndex != index) { + if (!d->attType) { + // pre-create one metatype to share with all attached objects + d->attType = new QDeclarativeOpenMetaObjectType(&QDeclarativePathViewAttached::staticMetaObject, qmlEngine(this)); + foreach(const QString &attr, d->path->attributes()) + d->attType->createProperty(attr.toUtf8()); + } + qPathViewAttachedType = d->attType; + QDeclarativePathViewAttached *att = static_cast<QDeclarativePathViewAttached *>(qmlAttachedPropertiesObject<QDeclarativePathView>(item)); + qPathViewAttachedType = 0; + if (att) { + att->m_view = this; + att->setOnPath(false); + } item->setParentItem(this); d->updateItem(item, index < d->firstIndex ? 0.0 : 1.0); } @@ -1294,6 +1340,7 @@ int QDeclarativePathViewPrivate::calcCurrentIndex() if (offset < 0) offset += model->count(); current = qRound(qAbs(qmlMod(model->count() - offset, model->count()))); + current = current % model->count(); } return current; diff --git a/src/declarative/graphicsitems/qdeclarativepathview_p.h b/src/declarative/graphicsitems/qdeclarativepathview_p.h index 7240578..349a01c 100644 --- a/src/declarative/graphicsitems/qdeclarativepathview_p.h +++ b/src/declarative/graphicsitems/qdeclarativepathview_p.h @@ -132,6 +132,10 @@ public: static QDeclarativePathViewAttached *qmlAttachedProperties(QObject *); +public Q_SLOTS: + void incrementCurrentIndex(); + void decrementCurrentIndex(); + Q_SIGNALS: void currentIndexChanged(); void offsetChanged(); @@ -215,6 +219,7 @@ Q_SIGNALS: private: friend class QDeclarativePathViewPrivate; + friend class QDeclarativePathView; QDeclarativePathView *m_view; QDeclarativeOpenMetaObject *m_metaobject; bool m_onPath : 1; diff --git a/src/declarative/graphicsitems/qdeclarativepositioners.cpp b/src/declarative/graphicsitems/qdeclarativepositioners.cpp index 93bff3e..8796e63 100644 --- a/src/declarative/graphicsitems/qdeclarativepositioners.cpp +++ b/src/declarative/graphicsitems/qdeclarativepositioners.cpp @@ -204,7 +204,11 @@ void QDeclarativeBasePositioner::prePositioning() if (!isComponentComplete()) return; + if (d->doingPositioning) + return; + d->queuedPositioning = false; + d->doingPositioning = true; //Need to order children by creation order modified by stacking order QList<QGraphicsItem *> children = d->QGraphicsItemPrivate::children; qSort(children.begin(), children.end(), d->insertionOrder); @@ -242,6 +246,7 @@ void QDeclarativeBasePositioner::prePositioning() doPositioning(&contentSize); if(d->addTransition || d->moveTransition) finishApplyTransitions(); + d->doingPositioning = false; //Set implicit size to the size of its children setImplicitHeight(contentSize.height()); setImplicitWidth(contentSize.width()); @@ -339,7 +344,8 @@ Column { 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 + the x or y properties, use anchors on a child of a positioner, or have the + height of a child depend on the position of a child, then the positioner may exhibit strange behaviour. */ @@ -437,7 +443,7 @@ void QDeclarativeColumn::doPositioning(QSizeF *contentSize) void QDeclarativeColumn::reportConflictingAnchors() { - bool childsWithConflictingAnchors(false); + QDeclarativeBasePositionerPrivate *d = static_cast<QDeclarativeBasePositionerPrivate*>(QDeclarativeBasePositionerPrivate::get(this)); for (int ii = 0; ii < positionedItems.count(); ++ii) { const PositionedItem &child = positionedItems.at(ii); if (child.item) { @@ -446,15 +452,16 @@ void QDeclarativeColumn::reportConflictingAnchors() QDeclarativeAnchors::Anchors usedAnchors = anchors->usedAnchors(); if (usedAnchors & QDeclarativeAnchors::TopAnchor || usedAnchors & QDeclarativeAnchors::BottomAnchor || - usedAnchors & QDeclarativeAnchors::VCenterAnchor) { - childsWithConflictingAnchors = true; + usedAnchors & QDeclarativeAnchors::VCenterAnchor || + anchors->fill() || anchors->centerIn()) { + d->anchorConflict = true; break; } } } } - if (childsWithConflictingAnchors) { - qmlInfo(this) << "Cannot specify top, bottom or verticalCenter anchors for items inside Column"; + if (d->anchorConflict) { + qmlInfo(this) << "Cannot specify top, bottom, verticalCenter, fill or centerIn anchors for items inside Column"; } } @@ -486,7 +493,8 @@ Row { 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 + the x or y properties, use anchors on a child of a positioner, or have the + width of a child depend on the position of a child, then the positioner may exhibit strange behaviour. */ @@ -574,7 +582,7 @@ void QDeclarativeRow::doPositioning(QSizeF *contentSize) void QDeclarativeRow::reportConflictingAnchors() { - bool childsWithConflictingAnchors(false); + QDeclarativeBasePositionerPrivate *d = static_cast<QDeclarativeBasePositionerPrivate*>(QDeclarativeBasePositionerPrivate::get(this)); for (int ii = 0; ii < positionedItems.count(); ++ii) { const PositionedItem &child = positionedItems.at(ii); if (child.item) { @@ -583,16 +591,16 @@ void QDeclarativeRow::reportConflictingAnchors() QDeclarativeAnchors::Anchors usedAnchors = anchors->usedAnchors(); if (usedAnchors & QDeclarativeAnchors::LeftAnchor || usedAnchors & QDeclarativeAnchors::RightAnchor || - usedAnchors & QDeclarativeAnchors::HCenterAnchor) { - childsWithConflictingAnchors = true; + usedAnchors & QDeclarativeAnchors::HCenterAnchor || + anchors->fill() || anchors->centerIn()) { + d->anchorConflict = true; break; } } } } - if (childsWithConflictingAnchors) { - qmlInfo(this) << "Cannot specify left, right or horizontalCenter anchors for items inside Row"; - } + if (d->anchorConflict) + qmlInfo(this) << "Cannot specify left, right, horizontalCenter, fill or centerIn anchors for items inside Row"; } /*! @@ -638,7 +646,8 @@ Grid { 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 + the x or y properties, use anchors on a child of a positioner, or have the + width or height of a child depend on the position of a child, then the positioner may exhibit strange behaviour. */ /*! @@ -866,20 +875,19 @@ void QDeclarativeGrid::doPositioning(QSizeF *contentSize) void QDeclarativeGrid::reportConflictingAnchors() { - bool childsWithConflictingAnchors(false); + QDeclarativeBasePositionerPrivate *d = static_cast<QDeclarativeBasePositionerPrivate*>(QDeclarativeBasePositionerPrivate::get(this)); for (int ii = 0; ii < positionedItems.count(); ++ii) { const PositionedItem &child = positionedItems.at(ii); if (child.item) { QDeclarativeAnchors *anchors = QDeclarativeItemPrivate::get(child.item)->_anchors; - if (anchors && anchors->usedAnchors()) { - childsWithConflictingAnchors = true; + if (anchors && (anchors->usedAnchors() || anchors->fill() || anchors->centerIn())) { + d->anchorConflict = true; break; } } } - if (childsWithConflictingAnchors) { + if (d->anchorConflict) qmlInfo(this) << "Cannot specify anchors for items inside Grid"; - } } /*! @@ -888,6 +896,11 @@ void QDeclarativeGrid::reportConflictingAnchors() \brief The Flow item lines up its children side by side, wrapping as necessary. \inherits Item + Note that the positioner assumes that the x and y positions of its children + will not change. If you manually change the x or y properties in script, bind + the x or y properties, use anchors on a child of a positioner, or have the + width or height of a child depend on the position of a child, then the + positioner may exhibit strange behaviour. */ /*! @@ -1026,20 +1039,19 @@ void QDeclarativeFlow::doPositioning(QSizeF *contentSize) void QDeclarativeFlow::reportConflictingAnchors() { - bool childsWithConflictingAnchors(false); + Q_D(QDeclarativeFlow); for (int ii = 0; ii < positionedItems.count(); ++ii) { const PositionedItem &child = positionedItems.at(ii); if (child.item) { QDeclarativeAnchors *anchors = QDeclarativeItemPrivate::get(child.item)->_anchors; - if (anchors && anchors->usedAnchors()) { - childsWithConflictingAnchors = true; + if (anchors && (anchors->usedAnchors() || anchors->fill() || anchors->centerIn())) { + d->anchorConflict = true; break; } } } - if (childsWithConflictingAnchors) { + if (d->anchorConflict) qmlInfo(this) << "Cannot specify anchors for items inside Flow"; - } } QT_END_NAMESPACE diff --git a/src/declarative/graphicsitems/qdeclarativepositioners_p_p.h b/src/declarative/graphicsitems/qdeclarativepositioners_p_p.h index 576f35b..04f0181 100644 --- a/src/declarative/graphicsitems/qdeclarativepositioners_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativepositioners_p_p.h @@ -75,6 +75,7 @@ public: QDeclarativeBasePositionerPrivate() : spacing(0), type(QDeclarativeBasePositioner::None) , moveTransition(0), addTransition(0), queuedPositioning(false) + , doingPositioning(false), anchorConflict(false) { } @@ -95,7 +96,9 @@ public: void watchChanges(QDeclarativeItem *other); void unwatchChanges(QDeclarativeItem* other); - bool queuedPositioning; + bool queuedPositioning : 1; + bool doingPositioning : 1; + bool anchorConflict : 1; virtual void itemSiblingOrderChanged(QDeclarativeItem* other) { diff --git a/src/declarative/graphicsitems/qdeclarativerepeater.cpp b/src/declarative/graphicsitems/qdeclarativerepeater.cpp index ca0b8c6..04076f8 100644 --- a/src/declarative/graphicsitems/qdeclarativerepeater.cpp +++ b/src/declarative/graphicsitems/qdeclarativerepeater.cpp @@ -193,7 +193,7 @@ void QDeclarativeRepeater::setModel(const QVariant &model) d->model = vim; } else { if (!d->ownModel) { - d->model = new QDeclarativeVisualDataModel(qmlContext(this)); + d->model = new QDeclarativeVisualDataModel(qmlContext(this), this); d->ownModel = true; } if (QDeclarativeVisualDataModel *dataModel = qobject_cast<QDeclarativeVisualDataModel*>(d->model)) diff --git a/src/declarative/graphicsitems/qdeclarativetextedit.cpp b/src/declarative/graphicsitems/qdeclarativetextedit.cpp index 6d86e58..45b79a7 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextedit.cpp @@ -858,8 +858,9 @@ Handles the given key \a event. void QDeclarativeTextEdit::keyPressEvent(QKeyEvent *event) { Q_D(QDeclarativeTextEdit); - d->control->processEvent(event, QPointF(0, 0)); - + keyPressPreHandler(event); + if (!event->isAccepted()) + d->control->processEvent(event, QPointF(0, 0)); if (!event->isAccepted()) QDeclarativePaintedItem::keyPressEvent(event); } @@ -871,7 +872,9 @@ Handles the given key \a event. void QDeclarativeTextEdit::keyReleaseEvent(QKeyEvent *event) { Q_D(QDeclarativeTextEdit); - d->control->processEvent(event, QPointF(0, 0)); + keyReleasePreHandler(event); + if (!event->isAccepted()) + d->control->processEvent(event, QPointF(0, 0)); if (!event->isAccepted()) QDeclarativePaintedItem::keyReleaseEvent(event); } @@ -899,17 +902,18 @@ Handles the given mouse \a event. void QDeclarativeTextEdit::mousePressEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativeTextEdit); + bool hadFocus = hasFocus(); if (d->focusOnPress){ QGraphicsItem *p = parentItem();//###Is there a better way to find my focus scope? while(p) { - if(p->flags() & QGraphicsItem::ItemIsFocusScope){ + if (p->flags() & QGraphicsItem::ItemIsFocusScope) p->setFocus(); - break; - } p = p->parentItem(); } setFocus(true); } + if (!hadFocus && hasFocus()) + d->clickCausedFocus = true; d->control->processEvent(event, QPointF(0, 0)); if (!event->isAccepted()) QDeclarativePaintedItem::mousePressEvent(event); @@ -924,11 +928,12 @@ void QDeclarativeTextEdit::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) Q_D(QDeclarativeTextEdit); QWidget *widget = event->widget(); if (widget && (d->control->textInteractionFlags() & Qt::TextEditable) && boundingRect().contains(event->pos())) - qt_widget_private(widget)->handleSoftwareInputPanel(event->button(), d->focusOnPress); + qt_widget_private(widget)->handleSoftwareInputPanel(event->button(), d->clickCausedFocus); + d->clickCausedFocus = false; d->control->processEvent(event, QPointF(0, 0)); if (!event->isAccepted()) - QDeclarativePaintedItem::mousePressEvent(event); + QDeclarativePaintedItem::mouseReleaseEvent(event); } /*! @@ -952,7 +957,8 @@ void QDeclarativeTextEdit::mouseMoveEvent(QGraphicsSceneMouseEvent *event) Q_D(QDeclarativeTextEdit); d->control->processEvent(event, QPointF(0, 0)); if (!event->isAccepted()) - QDeclarativePaintedItem::mousePressEvent(event); + QDeclarativePaintedItem::mouseMoveEvent(event); + event->setAccepted(true); } /*! diff --git a/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h b/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h index 8d4b611..5e19c3d 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h @@ -70,7 +70,7 @@ public: QDeclarativeTextEditPrivate() : color("black"), hAlign(QDeclarativeTextEdit::AlignLeft), vAlign(QDeclarativeTextEdit::AlignTop), imgDirty(true), dirty(false), richText(false), cursorVisible(false), focusOnPress(true), - persistentSelection(true), textMargin(0.0), lastSelectionStart(0), lastSelectionEnd(0), + persistentSelection(true), clickCausedFocus(false), textMargin(0.0), lastSelectionStart(0), lastSelectionEnd(0), cursorComponent(0), cursor(0), format(QDeclarativeTextEdit::AutoText), document(0), wrapMode(QDeclarativeTextEdit::NoWrap) { @@ -100,6 +100,7 @@ public: bool cursorVisible : 1; bool focusOnPress : 1; bool persistentSelection : 1; + bool clickCausedFocus : 1; qreal textMargin; int lastSelectionStart; int lastSelectionEnd; diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp index 604f508..8aa7e99 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp @@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE /*! \qmlclass TextInput QDeclarativeTextInput \since 4.7 - The TextInput item allows you to add an editable line of text to a scene. + \brief The TextInput item allows you to add an editable line of text to a scene. TextInput can only display a single line of text, and can only display plain text. However it can provide addition input constraints on the text. @@ -863,6 +863,9 @@ void QDeclarativeTextInputPrivate::focusChanged(bool hasFocus) void QDeclarativeTextInput::keyPressEvent(QKeyEvent* ev) { Q_D(QDeclarativeTextInput); + keyPressPreHandler(ev); + if (ev->isAccepted()) + return; if (((ev->key() == Qt::Key_Up || ev->key() == Qt::Key_Down) && ev->modifiers() == Qt::NoModifier) // Don't allow MacOSX up/down support, and we don't allow a completer. || (((d->control->cursor() == 0 && ev->key() == Qt::Key_Left) || (d->control->cursor() == d->control->text().length() @@ -882,26 +885,30 @@ void QDeclarativeTextInput::keyPressEvent(QKeyEvent* ev) void QDeclarativeTextInput::mousePressEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativeTextInput); + bool hadFocus = hasFocus(); if(d->focusOnPress){ QGraphicsItem *p = parentItem();//###Is there a better way to find my focus scope? while(p) { - if(p->flags() & QGraphicsItem::ItemIsFocusScope){ + if (p->flags() & QGraphicsItem::ItemIsFocusScope) p->setFocus(); - break; - } p = p->parentItem(); } setFocus(true); } + if (!hadFocus && hasFocus()) + d->clickCausedFocus = true; + bool mark = event->modifiers() & Qt::ShiftModifier; int cursor = d->xToPos(event->pos().x()); d->control->moveCursor(cursor, mark); + event->setAccepted(true); } void QDeclarativeTextInput::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativeTextInput); d->control->moveCursor(d->xToPos(event->pos().x()), true); + event->setAccepted(true); } /*! @@ -913,8 +920,10 @@ void QDeclarativeTextInput::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) Q_D(QDeclarativeTextInput); QWidget *widget = event->widget(); if (widget && !d->control->isReadOnly() && boundingRect().contains(event->pos())) - qt_widget_private(widget)->handleSoftwareInputPanel(event->button(), d->focusOnPress); - d->control->processEvent(event); + qt_widget_private(widget)->handleSoftwareInputPanel(event->button(), d->clickCausedFocus); + d->clickCausedFocus = false; + if (!event->isAccepted()) + QDeclarativePaintedItem::mouseReleaseEvent(event); } bool QDeclarativeTextInput::event(QEvent* ev) @@ -935,8 +944,8 @@ bool QDeclarativeTextInput::event(QEvent* ev) updateSize(); } if(!handled) - return QDeclarativePaintedItem::event(ev); - return true; + handled = QDeclarativePaintedItem::event(ev); + return handled; } void QDeclarativeTextInput::geometryChanged(const QRectF &newGeometry, @@ -1018,6 +1027,8 @@ QVariant QDeclarativeTextInput::inputMethodQuery(Qt::InputMethodQuery property) { Q_D(const QDeclarativeTextInput); switch(property) { + case Qt::ImMicroFocus: + return d->control->cursorRect(); case Qt::ImFont: return font(); case Qt::ImCursorPosition: @@ -1233,9 +1244,7 @@ void QDeclarativeTextInput::updateSize(bool needsRedraw) int cursorWidth = d->control->cursorWidth(); if(d->cursorItem) cursorWidth = d->cursorItem->width(); - //### Is QFontMetrics too slow? - QFontMetricsF fm(d->font); - setImplicitWidth(fm.width(d->control->displayText())+cursorWidth); + setImplicitWidth(d->control->naturalTextWidth() + cursorWidth); setContentsSize(QSize(width(), height()));//Repaints if changed if(w==width() && h==height() && needsRedraw){ clearCache(); diff --git a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h index 26cf78c..99866b8 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h @@ -72,7 +72,7 @@ public: color((QRgb)0), style(QDeclarativeText::Normal), styleColor((QRgb)0), hAlign(QDeclarativeTextInput::AlignLeft), hscroll(0), oldScroll(0), focused(false), focusOnPress(true), - cursorVisible(false), autoScroll(true) + cursorVisible(false), autoScroll(true), clickCausedFocus(false) { } @@ -116,6 +116,7 @@ public: bool focusOnPress; bool cursorVisible; bool autoScroll; + bool clickCausedFocus; }; QT_END_NAMESPACE diff --git a/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp b/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp index 1038c83..0e4217e 100644 --- a/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp +++ b/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp @@ -138,8 +138,8 @@ public: } \endcode */ -QDeclarativeVisualItemModel::QDeclarativeVisualItemModel() - : QDeclarativeVisualModel(*(new QDeclarativeVisualItemModelPrivate)) +QDeclarativeVisualItemModel::QDeclarativeVisualItemModel(QObject *parent) + : QDeclarativeVisualModel(*(new QDeclarativeVisualItemModelPrivate), parent) { } @@ -269,7 +269,8 @@ public: } if (m_roles.count() == 1) m_roleNames.insert("modelData", m_roles.at(0)); - m_roleNames.insert("hasModelChildren", 0); + if (m_roles.count()) + m_roleNames.insert("hasModelChildren", 0); } else if (m_listAccessor) { m_roleNames.insert("modelData", 0); if (m_listAccessor->type() == QDeclarativeListAccessor::Instance) { @@ -285,15 +286,19 @@ public: } } + QHash<int,int> roleToPropId; void createMetaData() { if (!m_metaDataCreated) { ensureRoles(); - QHash<QByteArray, int>::const_iterator it = m_roleNames.begin(); - while (it != m_roleNames.end()) { - m_delegateDataType->createProperty(it.key()); - ++it; + if (m_roleNames.count()) { + QHash<QByteArray, int>::const_iterator it = m_roleNames.begin(); + while (it != m_roleNames.end()) { + int propId = m_delegateDataType->createProperty(it.key()) - m_delegateDataType->propertyOffset(); + roleToPropId.insert(*it, propId); + ++it; + } + m_metaDataCreated = true; } - m_metaDataCreated = true; } } @@ -383,7 +388,6 @@ public: private: friend class QDeclarativeVisualDataModelData; - QHash<int,int> roleToProp; }; class QDeclarativeVisualDataModelData : public QObject @@ -400,6 +404,8 @@ public: int propForRole(int) const; void setValue(int, const QVariant &); + void ensureProperties(); + Q_SIGNALS: void indexChanged(); @@ -412,9 +418,11 @@ private: int QDeclarativeVisualDataModelData::propForRole(int id) const { - QHash<int,int>::const_iterator it = m_meta->roleToProp.find(id); - if (it != m_meta->roleToProp.end()) - return m_meta->roleToProp[id]; + QDeclarativeVisualDataModelPrivate *model = QDeclarativeVisualDataModelPrivate::get(m_model); + QHash<int,int>::const_iterator it = model->roleToPropId.find(id); + if (it != model->roleToPropId.end()) + return *it; + return -1; } @@ -470,12 +478,10 @@ QVariant QDeclarativeVisualDataModelDataMetaObject::initialValue(int propId) model->ensureRoles(); QHash<QByteArray,int>::const_iterator it = model->m_roleNames.find(propName); if (it != model->m_roleNames.end()) { - roleToProp.insert(*it, propId); QVariant value = model->m_listModelInterface->data(data->m_index, *it); return value; } else if (model->m_roles.count() == 1 && propName == "modelData") { //for compatability with other lists, assign modelData if there is only a single role - roleToProp.insert(model->m_roles.first(), propId); QVariant value = model->m_listModelInterface->data(data->m_index, model->m_roles.first()); return value; } @@ -487,7 +493,6 @@ QVariant QDeclarativeVisualDataModelDataMetaObject::initialValue(int propId) } else { QHash<QByteArray,int>::const_iterator it = model->m_roleNames.find(propName); if (it != model->m_roleNames.end()) { - roleToProp.insert(*it, propId); QModelIndex index = model->m_abstractItemModel->index(data->m_index, 0, model->m_root); return model->m_abstractItemModel->data(index, *it); } @@ -502,18 +507,23 @@ QDeclarativeVisualDataModelData::QDeclarativeVisualDataModelData(int index, : m_index(index), m_model(model), m_meta(new QDeclarativeVisualDataModelDataMetaObject(this, QDeclarativeVisualDataModelPrivate::get(model)->m_delegateDataType)) { - QDeclarativeVisualDataModelPrivate *modelPriv = QDeclarativeVisualDataModelPrivate::get(model); - if (modelPriv->m_metaDataCacheable) { - if (!modelPriv->m_metaDataCreated) - modelPriv->createMetaData(); - m_meta->setCached(true); - } + ensureProperties(); } QDeclarativeVisualDataModelData::~QDeclarativeVisualDataModelData() { } +void QDeclarativeVisualDataModelData::ensureProperties() +{ + QDeclarativeVisualDataModelPrivate *modelPriv = QDeclarativeVisualDataModelPrivate::get(m_model); + if (modelPriv->m_metaDataCacheable && !modelPriv->m_metaDataCreated) { + modelPriv->createMetaData(); + if (modelPriv->m_metaDataCreated) + m_meta->setCached(true); + } +} + int QDeclarativeVisualDataModelData::index() const { return m_index; @@ -626,8 +636,8 @@ QDeclarativeVisualDataModel::QDeclarativeVisualDataModel() { } -QDeclarativeVisualDataModel::QDeclarativeVisualDataModel(QDeclarativeContext *ctxt) -: QDeclarativeVisualModel(*(new QDeclarativeVisualDataModelPrivate(ctxt))) +QDeclarativeVisualDataModel::QDeclarativeVisualDataModel(QDeclarativeContext *ctxt, QObject *parent) +: QDeclarativeVisualModel(*(new QDeclarativeVisualDataModelPrivate(ctxt)), parent) { } @@ -1212,6 +1222,13 @@ void QDeclarativeVisualDataModel::_q_itemsChanged(int index, int count, QModelIndex index = d->m_abstractItemModel->index(idx, 0, d->m_root); data->setValue(propId, d->m_abstractItemModel->data(index, role)); } + } else { + QString roleName; + if (d->m_listModelInterface) + roleName = d->m_listModelInterface->toString(role); + else if (d->m_abstractItemModel) + roleName = d->m_abstractItemModel->roleNames().value(role); + qmlInfo(this) << "Changing role not present in item: " << roleName; } } } diff --git a/src/declarative/graphicsitems/qdeclarativevisualitemmodel_p.h b/src/declarative/graphicsitems/qdeclarativevisualitemmodel_p.h index edfd387..0bdbbcf 100644 --- a/src/declarative/graphicsitems/qdeclarativevisualitemmodel_p.h +++ b/src/declarative/graphicsitems/qdeclarativevisualitemmodel_p.h @@ -72,7 +72,7 @@ class Q_DECLARATIVE_EXPORT QDeclarativeVisualModel : public QObject Q_PROPERTY(int count READ count NOTIFY countChanged) public: - QDeclarativeVisualModel() {} + QDeclarativeVisualModel(QObject *parent=0) : QObject(parent) {} virtual ~QDeclarativeVisualModel() {} enum ReleaseFlag { Referenced = 0x01, Destroyed = 0x02 }; @@ -117,7 +117,7 @@ class Q_DECLARATIVE_EXPORT QDeclarativeVisualItemModel : public QDeclarativeVisu Q_CLASSINFO("DefaultProperty", "children") public: - QDeclarativeVisualItemModel(); + QDeclarativeVisualItemModel(QObject *parent=0); virtual ~QDeclarativeVisualItemModel() {} virtual int count() const; @@ -156,7 +156,7 @@ class Q_DECLARATIVE_EXPORT QDeclarativeVisualDataModel : public QDeclarativeVisu Q_CLASSINFO("DefaultProperty", "delegate") public: QDeclarativeVisualDataModel(); - QDeclarativeVisualDataModel(QDeclarativeContext *); + QDeclarativeVisualDataModel(QDeclarativeContext *, QObject *parent=0); virtual ~QDeclarativeVisualDataModel(); QVariant model() const; diff --git a/src/declarative/qml/qdeclarativebinding.cpp b/src/declarative/qml/qdeclarativebinding.cpp index 8043ea9..2e905b9 100644 --- a/src/declarative/qml/qdeclarativebinding.cpp +++ b/src/declarative/qml/qdeclarativebinding.cpp @@ -286,13 +286,15 @@ QDeclarativeAbstractBinding::QDeclarativeAbstractBinding() QDeclarativeAbstractBinding::~QDeclarativeAbstractBinding() { - removeFromObject(); - if (m_mePtr) - *m_mePtr = 0; + Q_ASSERT(m_prevBinding == 0); + Q_ASSERT(m_mePtr == 0); } void QDeclarativeAbstractBinding::destroy() { + removeFromObject(); + clear(); + delete this; } diff --git a/src/declarative/qml/qdeclarativebinding_p.h b/src/declarative/qml/qdeclarativebinding_p.h index 2d3acf5..598f09f 100644 --- a/src/declarative/qml/qdeclarativebinding_p.h +++ b/src/declarative/qml/qdeclarativebinding_p.h @@ -164,6 +164,6 @@ private: QT_END_NAMESPACE -Q_DECLARE_METATYPE(QDeclarativeBinding*); +Q_DECLARE_METATYPE(QDeclarativeBinding*) #endif // QDECLARATIVEBINDING_P_H diff --git a/src/declarative/qml/qdeclarativecompiledbindings.cpp b/src/declarative/qml/qdeclarativecompiledbindings.cpp index 05b7dc6..f55d330 100644 --- a/src/declarative/qml/qdeclarativecompiledbindings.cpp +++ b/src/declarative/qml/qdeclarativecompiledbindings.cpp @@ -1624,6 +1624,8 @@ bool QDeclarativeBindingCompilerPrivate::compile(QDeclarativeJS::AST::Node *node return false; int convertReg = acquireReg(); + if (convertReg == -1) + return false; if (destination->type == QMetaType::QReal) { Instr convert; @@ -2011,6 +2013,8 @@ bool QDeclarativeBindingCompilerPrivate::parseArith(QDeclarativeJS::AST::Node *n AST::BinaryExpression *expression = static_cast<AST::BinaryExpression *>(node); type.reg = acquireReg(); + if (type.reg == -1) + return false; Result lhs; Result rhs; @@ -2062,6 +2066,8 @@ bool QDeclarativeBindingCompilerPrivate::numberArith(Result &type, const Result return false; lhsTmp = acquireReg(); + if (lhsTmp == -1) + return false; Instr conv; conv.common.type = Instr::ConvertGenericToReal; @@ -2075,6 +2081,8 @@ bool QDeclarativeBindingCompilerPrivate::numberArith(Result &type, const Result return false; rhsTmp = acquireReg(); + if (rhsTmp == -1) + return false; Instr conv; conv.common.type = Instr::ConvertGenericToReal; @@ -2123,6 +2131,8 @@ bool QDeclarativeBindingCompilerPrivate::stringArith(Result &type, const Result return false; lhsTmp = acquireReg(Instr::CleanupString); + if (lhsTmp == -1) + return false; Instr convert; convert.common.type = Instr::ConvertGenericToString; @@ -2136,6 +2146,8 @@ bool QDeclarativeBindingCompilerPrivate::stringArith(Result &type, const Result return false; rhsTmp = acquireReg(Instr::CleanupString); + if (rhsTmp == -1) + return false; Instr convert; convert.common.type = Instr::ConvertGenericToString; @@ -2145,6 +2157,9 @@ bool QDeclarativeBindingCompilerPrivate::stringArith(Result &type, const Result } type.reg = acquireReg(Instr::CleanupString); + if (type.reg == -1) + return false; + type.type = QMetaType::QString; Instr add; @@ -2185,6 +2200,9 @@ bool QDeclarativeBindingCompilerPrivate::parseLogic(QDeclarativeJS::AST::Node *n if (!parseExpression(expression->right, rhs)) return false; type.reg = acquireReg(); + if (type.reg == -1) + return false; + type.metaObject = 0; type.type = QVariant::Bool; @@ -2310,6 +2328,8 @@ bool QDeclarativeBindingCompilerPrivate::parseConstant(QDeclarativeJS::AST::Node type.metaObject = 0; type.type = -1; type.reg = acquireReg(); + if (type.reg == -1) + return false; if (node->kind == AST::Node::Kind_TrueLiteral) { type.type = QVariant::Bool; @@ -2398,6 +2418,9 @@ bool QDeclarativeBindingCompilerPrivate::parseMethod(QDeclarativeJS::AST::Node * releaseReg(r1.reg); op.binaryop.output = acquireReg(); + if (op.binaryop.output == -1) + return false; + op.binaryop.src1 = r0.reg; op.binaryop.src2 = r1.reg; bytecode << op; @@ -2473,6 +2496,8 @@ bool QDeclarativeBindingCompilerPrivate::fetch(Result &rv, const QMetaObject *mo if (rv.type == QMetaType::QString) { int tmp = acquireReg(); + if (tmp == -1) + return false; Instr copy; copy.common.type = Instr::Copy; copy.copy.reg = tmp; @@ -2549,6 +2574,8 @@ int QDeclarativeBindingCompilerPrivate::registerLiteralString(const QString &str data += strdata; int reg = acquireReg(Instr::CleanupString); + if (reg == -1) + return false; Instr string; string.common.type = Instr::String; diff --git a/src/declarative/qml/qdeclarativecompiledbindings_p.h b/src/declarative/qml/qdeclarativecompiledbindings_p.h index 29a1092..a9772cc 100644 --- a/src/declarative/qml/qdeclarativecompiledbindings_p.h +++ b/src/declarative/qml/qdeclarativecompiledbindings_p.h @@ -104,8 +104,8 @@ protected: int qt_metacall(QMetaObject::Call, int, void **); private: - Q_DISABLE_COPY(QDeclarativeCompiledBindings); - Q_DECLARE_PRIVATE(QDeclarativeCompiledBindings); + Q_DISABLE_COPY(QDeclarativeCompiledBindings) + Q_DECLARE_PRIVATE(QDeclarativeCompiledBindings) }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index 6d420a7..a43b9ac 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -352,6 +352,10 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, instr.storeDouble.propertyIndex = prop.propertyIndex(); instr.storeDouble.value = n; } + } else if(v->value.isBoolean()) { + instr.type = QDeclarativeInstruction::StoreVariantBool; + instr.storeBool.propertyIndex = prop.propertyIndex(); + instr.storeBool.value = v->value.asBoolean(); } else { instr.type = QDeclarativeInstruction::StoreVariant; instr.storeString.propertyIndex = prop.propertyIndex(); diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp index afdaee8..e757675 100644 --- a/src/declarative/qml/qdeclarativecomponent.cpp +++ b/src/declarative/qml/qdeclarativecomponent.cpp @@ -545,7 +545,7 @@ QDeclarativeComponent::QDeclarativeComponent(QDeclarativeComponentPrivate &dd, Q } /*! - \qmlmethod object Component::createObject() + \qmlmethod object Component::createObject(parent) Returns an object instance from this component, or null if object creation fails. The object will be created in the same context as the one in which the component diff --git a/src/declarative/qml/qdeclarativecomponent_p.h b/src/declarative/qml/qdeclarativecomponent_p.h index 19aac84..2a7d633 100644 --- a/src/declarative/qml/qdeclarativecomponent_p.h +++ b/src/declarative/qml/qdeclarativecomponent_p.h @@ -150,7 +150,7 @@ Q_SIGNALS: void destruction(); private: - friend class QDeclarativeContextData;; + friend class QDeclarativeContextData; friend class QDeclarativeComponentPrivate; }; diff --git a/src/declarative/qml/qdeclarativecompositetypemanager.cpp b/src/declarative/qml/qdeclarativecompositetypemanager.cpp index 0ea198d..e4405f7 100644 --- a/src/declarative/qml/qdeclarativecompositetypemanager.cpp +++ b/src/declarative/qml/qdeclarativecompositetypemanager.cpp @@ -338,7 +338,7 @@ void QDeclarativeCompositeTypeManager::resourceReplyFinished() // WARNING, there is a copy of this function in qdeclarativeengine.cpp static QString toLocalFileOrQrc(const QUrl& url) { - if (url.scheme() == QLatin1String("qrc")) { + if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) { if (url.authority().isEmpty()) return QLatin1Char(':') + url.path(); return QString(); @@ -360,7 +360,10 @@ void QDeclarativeCompositeTypeManager::loadResource(QDeclarativeCompositeTypeRes } else { resource->status = QDeclarativeCompositeTypeResource::Error; } + } else if (url.scheme().isEmpty()) { + // We can't open this, so just declare as an error + resource->status = QDeclarativeCompositeTypeResource::Error; } else { QNetworkReply *reply = @@ -382,27 +385,29 @@ void QDeclarativeCompositeTypeManager::loadSource(QDeclarativeCompositeTypeData if (file.open(QFile::ReadOnly)) { QByteArray data = file.readAll(); setData(unit, data, url); - } else { - QString errorDescription; - // ### - Fill in error - errorDescription = QLatin1String("File error for URL ") + url.toString(); - unit->status = QDeclarativeCompositeTypeData::Error; - // ### FIXME - QDeclarativeError error; - error.setDescription(errorDescription); - unit->errorType = QDeclarativeCompositeTypeData::AccessError; - unit->errors << error; - doComplete(unit); + return; // success } - - } else { + } else if (!url.scheme().isEmpty()) { QNetworkReply *reply = engine->networkAccessManager()->get(QNetworkRequest(url)); QObject::connect(reply, SIGNAL(finished()), this, SLOT(replyFinished())); QObject::connect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(requestProgress(qint64,qint64))); + return; // waiting } + + // error happened + QString errorDescription; + // ### - Fill in error + errorDescription = QLatin1String("File error for URL ") + url.toString(); + unit->status = QDeclarativeCompositeTypeData::Error; + // ### FIXME + QDeclarativeError error; + error.setDescription(errorDescription); + unit->errorType = QDeclarativeCompositeTypeData::AccessError; + unit->errors << error; + doComplete(unit); } void QDeclarativeCompositeTypeManager::requestProgress(qint64 received, qint64 total) @@ -509,7 +514,9 @@ void QDeclarativeCompositeTypeManager::checkComplete(QDeclarativeCompositeTypeDa unit->errors = u->errors; doComplete(unit); return; - } else if (u->status == QDeclarativeCompositeTypeData::Waiting) { + } else if (u->status == QDeclarativeCompositeTypeData::Waiting + || u->status == QDeclarativeCompositeTypeData::WaitingResources) + { waiting++; } } @@ -716,8 +723,10 @@ void QDeclarativeCompositeTypeManager::compile(QDeclarativeCompositeTypeData *un } } - QUrl importUrl = unit->imports.baseUrl().resolved(QUrl(QLatin1String("qmldir"))); - if (toLocalFileOrQrc(importUrl).isEmpty()) + QUrl importUrl; + if (!unit->imports.baseUrl().scheme().isEmpty()) + importUrl = unit->imports.baseUrl().resolved(QUrl(QLatin1String("qmldir"))); + if (!importUrl.scheme().isEmpty() && toLocalFileOrQrc(importUrl).isEmpty()) resourceList.prepend(importUrl); for (int ii = 0; ii < resourceList.count(); ++ii) { diff --git a/src/declarative/qml/qdeclarativecontext.cpp b/src/declarative/qml/qdeclarativecontext.cpp index b61b8cb..6a13f15 100644 --- a/src/declarative/qml/qdeclarativecontext.cpp +++ b/src/declarative/qml/qdeclarativecontext.cpp @@ -659,7 +659,7 @@ void QDeclarativeContextData::addImportedScript(const QDeclarativeParser::Object if (iter == enginePriv->m_sharedScriptImports.end()) { QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine); - scriptContext->pushScope(enginePriv->contextClass->newContext(0, 0)); + scriptContext->pushScope(enginePriv->contextClass->newUrlContext(url)); scriptContext->pushScope(enginePriv->globalClass->globalObject()); QScriptValue scope = scriptEngine->newObject(); @@ -685,7 +685,7 @@ void QDeclarativeContextData::addImportedScript(const QDeclarativeParser::Object QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine); - scriptContext->pushScope(enginePriv->contextClass->newContext(this, 0)); + scriptContext->pushScope(enginePriv->contextClass->newUrlContext(this, 0, url)); scriptContext->pushScope(enginePriv->globalClass->globalObject()); QScriptValue scope = scriptEngine->newObject(); diff --git a/src/declarative/qml/qdeclarativecontext.h b/src/declarative/qml/qdeclarativecontext.h index 548869c..d87123a 100644 --- a/src/declarative/qml/qdeclarativecontext.h +++ b/src/declarative/qml/qdeclarativecontext.h @@ -107,7 +107,7 @@ private: }; QT_END_NAMESPACE -Q_DECLARE_METATYPE(QList<QObject*>); +Q_DECLARE_METATYPE(QList<QObject*>) QT_END_HEADER diff --git a/src/declarative/qml/qdeclarativecontextscriptclass.cpp b/src/declarative/qml/qdeclarativecontextscriptclass.cpp index 1336a1a..1ebedbb 100644 --- a/src/declarative/qml/qdeclarativecontextscriptclass.cpp +++ b/src/declarative/qml/qdeclarativecontextscriptclass.cpp @@ -51,11 +51,13 @@ QT_BEGIN_NAMESPACE struct ContextData : public QScriptDeclarativeClass::Object { ContextData() : overrideObject(0), isSharedContext(true) {} - ContextData(QDeclarativeContextData *c, QObject *o) : context(c), scopeObject(o), overrideObject(0), isSharedContext(false) {} + ContextData(QDeclarativeContextData *c, QObject *o) + : context(c), scopeObject(o), overrideObject(0), isSharedContext(false), isUrlContext(false) {} QDeclarativeGuardedContextData context; QDeclarativeGuard<QObject> scopeObject; QObject *overrideObject; - bool isSharedContext; + bool isSharedContext:1; + bool isUrlContext:1; QDeclarativeContextData *getContext(QDeclarativeEngine *engine) { if (isSharedContext) { @@ -74,6 +76,18 @@ struct ContextData : public QScriptDeclarativeClass::Object { } }; +struct UrlContextData : public ContextData { + UrlContextData(QDeclarativeContextData *c, QObject *o, const QString &u) + : ContextData(c, o), url(u) { + isUrlContext = true; + } + UrlContextData(const QString &u) + : ContextData(0, 0), url(u) { + isUrlContext = true; + } + QString url; +}; + /* The QDeclarativeContextScriptClass handles property access for a QDeclarativeContext via QtScript. @@ -95,6 +109,21 @@ QScriptValue QDeclarativeContextScriptClass::newContext(QDeclarativeContextData return newObject(scriptEngine, this, new ContextData(context, scopeObject)); } +QScriptValue QDeclarativeContextScriptClass::newUrlContext(QDeclarativeContextData *context, QObject *scopeObject, + const QString &url) +{ + QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine); + + return newObject(scriptEngine, this, new UrlContextData(context, scopeObject, url)); +} + +QScriptValue QDeclarativeContextScriptClass::newUrlContext(const QString &url) +{ + QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine); + + return newObject(scriptEngine, this, new UrlContextData(url)); +} + QScriptValue QDeclarativeContextScriptClass::newSharedContext() { QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine); @@ -111,6 +140,19 @@ QDeclarativeContextData *QDeclarativeContextScriptClass::contextFromValue(const return data->getContext(engine); } +QUrl QDeclarativeContextScriptClass::urlFromValue(const QScriptValue &v) +{ + if (scriptClass(v) != this) + return QUrl(); + + ContextData *data = (ContextData *)object(v); + if (data->isUrlContext) { + return QUrl(static_cast<UrlContextData *>(data)->url); + } else { + return QUrl(); + } +} + QObject *QDeclarativeContextScriptClass::setOverrideObject(QScriptValue &v, QObject *override) { if (scriptClass(v) != this) diff --git a/src/declarative/qml/qdeclarativecontextscriptclass_p.h b/src/declarative/qml/qdeclarativecontextscriptclass_p.h index 1936d38..1215b00 100644 --- a/src/declarative/qml/qdeclarativecontextscriptclass_p.h +++ b/src/declarative/qml/qdeclarativecontextscriptclass_p.h @@ -68,9 +68,13 @@ public: ~QDeclarativeContextScriptClass(); QScriptValue newContext(QDeclarativeContextData *, QObject * = 0); + QScriptValue newUrlContext(QDeclarativeContextData *, QObject *, const QString &); + QScriptValue newUrlContext(const QString &); QScriptValue newSharedContext(); QDeclarativeContextData *contextFromValue(const QScriptValue &); + QUrl urlFromValue(const QScriptValue &); + QObject *setOverrideObject(QScriptValue &, QObject *); protected: diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index 9f5cafe..79f8a17 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -67,6 +67,7 @@ #include "qdeclarativeextensioninterface.h" #include "private/qdeclarativelist_p.h" #include "private/qdeclarativetypenamecache_p.h" +#include "private/qdeclarativeinclude_p.h" #include <QtCore/qmetaobject.h> #include <QScriptClass> @@ -204,6 +205,11 @@ QDeclarativeScriptEngine::QDeclarativeScriptEngine(QDeclarativeEnginePrivate *pr // XXX used to add Qt.Sound class. //types + if (mainthread) + qtObject.setProperty(QLatin1String("include"), newFunction(QDeclarativeInclude::include, 2)); + else + qtObject.setProperty(QLatin1String("include"), newFunction(QDeclarativeInclude::worker_include, 2)); + qtObject.setProperty(QLatin1String("isQtObject"), newFunction(QDeclarativeEnginePrivate::isQtObject, 1)); qtObject.setProperty(QLatin1String("rgba"), newFunction(QDeclarativeEnginePrivate::rgba, 4)); qtObject.setProperty(QLatin1String("hsla"), newFunction(QDeclarativeEnginePrivate::hsla, 4)); @@ -327,11 +333,12 @@ Q_GLOBAL_STATIC(QDeclarativeEngineDebugServer, qmlEngineDebugServer); void QDeclarativePrivate::qdeclarativeelement_destructor(QObject *o) { QObjectPrivate *p = QObjectPrivate::get(o); - Q_ASSERT(p->declarativeData); - QDeclarativeData *d = static_cast<QDeclarativeData*>(p->declarativeData); - if (d->ownContext && d->context) { - d->context->destroy(); - d->context = 0; + if (p->declarativeData) { + QDeclarativeData *d = static_cast<QDeclarativeData*>(p->declarativeData); + if (d->ownContext && d->context) { + d->context->destroy(); + d->context = 0; + } } } @@ -555,9 +562,9 @@ QNetworkAccessManager *QDeclarativeEngine::networkAccessManager() const This example creates a provider with id \e colors: - \snippet examples/declarative/imageprovider/imageprovider.cpp 0 + \snippet examples/declarative/cppextensions/imageprovider/imageprovider.cpp 0 - \snippet examples/declarative/imageprovider/imageprovider-example.qml 0 + \snippet examples/declarative/cppextensions/imageprovider/imageprovider-example.qml 0 \sa removeImageProvider() */ diff --git a/src/declarative/qml/qdeclarativeengine_p.h b/src/declarative/qml/qdeclarativeengine_p.h index 531ac97..0b1c17d 100644 --- a/src/declarative/qml/qdeclarativeengine_p.h +++ b/src/declarative/qml/qdeclarativeengine_p.h @@ -91,6 +91,7 @@ class QDeclarativeEngine; class QDeclarativeContextPrivate; class QDeclarativeExpression; class QDeclarativeContextScriptClass; +class QDeclarativeImportDatabase; class QDeclarativeObjectScriptClass; class QDeclarativeTypeNameScriptClass; class QDeclarativeValueTypeScriptClass; diff --git a/src/declarative/qml/qdeclarativeextensionplugin.cpp b/src/declarative/qml/qdeclarativeextensionplugin.cpp index 2c15385..c2e8300 100644 --- a/src/declarative/qml/qdeclarativeextensionplugin.cpp +++ b/src/declarative/qml/qdeclarativeextensionplugin.cpp @@ -66,7 +66,7 @@ QT_BEGIN_NAMESPACE See \l {Tutorial: Writing QML extensions with C++} for details on creating QML extensions, including how to build a plugin with with QDeclarativeExtensionPlugin. - For a simple overview, see the \l{declarative/plugins}{plugins} example. + For a simple overview, see the \l{declarative/cppextensions/plugins}{plugins} example. Also see \l {How to Create Qt Plugins} for general Qt plugin documentation. diff --git a/src/declarative/qml/qdeclarativeglobalscriptclass_p.h b/src/declarative/qml/qdeclarativeglobalscriptclass_p.h index 1b34aee..7690edd 100644 --- a/src/declarative/qml/qdeclarativeglobalscriptclass_p.h +++ b/src/declarative/qml/qdeclarativeglobalscriptclass_p.h @@ -76,6 +76,7 @@ public: void explicitSetProperty(const QString &, const QScriptValue &); const QScriptValue &globalObject() const { return m_globalObject; } + const QSet<QString> &illegalNames() const { return m_illegalNames; } private: diff --git a/src/declarative/qml/qdeclarativeguard_p.h b/src/declarative/qml/qdeclarativeguard_p.h index be60ce4..02fed0b 100644 --- a/src/declarative/qml/qdeclarativeguard_p.h +++ b/src/declarative/qml/qdeclarativeguard_p.h @@ -97,7 +97,7 @@ private: QT_END_NAMESPACE -Q_DECLARE_METATYPE(QDeclarativeGuard<QObject>); +Q_DECLARE_METATYPE(QDeclarativeGuard<QObject>) #include "private/qdeclarativedata_p.h" diff --git a/src/declarative/qml/qdeclarativeimport.cpp b/src/declarative/qml/qdeclarativeimport.cpp index 65d42a1..576e048 100644 --- a/src/declarative/qml/qdeclarativeimport.cpp +++ b/src/declarative/qml/qdeclarativeimport.cpp @@ -57,7 +57,7 @@ DEFINE_BOOL_CONFIG_OPTION(qmlCheckTypes, QML_CHECK_TYPES) static QString toLocalFileOrQrc(const QUrl& url) { - if (url.scheme() == QLatin1String("qrc")) { + if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) { if (url.authority().isEmpty()) return QLatin1Char(':') + url.path(); return QString(); diff --git a/src/declarative/qml/qdeclarativeinclude.cpp b/src/declarative/qml/qdeclarativeinclude.cpp new file mode 100644 index 0000000..619264a --- /dev/null +++ b/src/declarative/qml/qdeclarativeinclude.cpp @@ -0,0 +1,316 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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$ +** +****************************************************************************/ + +#include "qdeclarativeinclude_p.h" + +#include <QtScript/qscriptengine.h> +#include <QtNetwork/qnetworkrequest.h> +#include <QtNetwork/qnetworkreply.h> +#include <QtCore/qfile.h> + +#include <private/qdeclarativeengine_p.h> +#include <private/qdeclarativeglobalscriptclass_p.h> + +QT_BEGIN_NAMESPACE + +QDeclarativeInclude::QDeclarativeInclude(const QUrl &url, + QDeclarativeEngine *engine, + QScriptContext *ctxt) +: QObject(engine), m_engine(engine), m_network(0), m_reply(0), m_url(url), m_redirectCount(0) +{ + QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); + m_context = ep->contextClass->contextFromValue(QScriptDeclarativeClass::scopeChainValue(ctxt, -3)); + + m_scope[0] = QScriptDeclarativeClass::scopeChainValue(ctxt, -4); + m_scope[1] = QScriptDeclarativeClass::scopeChainValue(ctxt, -5); + + m_scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine); + m_network = QDeclarativeScriptEngine::get(m_scriptEngine)->networkAccessManager(); + + m_result = resultValue(m_scriptEngine); + + QNetworkRequest request; + request.setUrl(url); + + m_reply = m_network->get(request); + QObject::connect(m_reply, SIGNAL(finished()), this, SLOT(finished())); +} + +QDeclarativeInclude::~QDeclarativeInclude() +{ + delete m_reply; +} + +QScriptValue QDeclarativeInclude::resultValue(QScriptEngine *engine, Status status) +{ + QScriptValue result = engine->newObject(); + result.setProperty(QLatin1String("OK"), QScriptValue(engine, Ok)); + result.setProperty(QLatin1String("LOADING"), QScriptValue(engine, Loading)); + result.setProperty(QLatin1String("NETWORK_ERROR"), QScriptValue(engine, NetworkError)); + result.setProperty(QLatin1String("EXCEPTION"), QScriptValue(engine, Exception)); + + result.setProperty(QLatin1String("status"), QScriptValue(engine, status)); + return result; +} + +QScriptValue QDeclarativeInclude::result() const +{ + return m_result; +} + +void QDeclarativeInclude::setCallback(const QScriptValue &c) +{ + m_callback = c; +} + +QScriptValue QDeclarativeInclude::callback() const +{ + return m_callback; +} + +#define INCLUDE_MAXIMUM_REDIRECT_RECURSION 15 +void QDeclarativeInclude::finished() +{ + m_redirectCount++; + + if (m_redirectCount < INCLUDE_MAXIMUM_REDIRECT_RECURSION) { + QVariant redirect = m_reply->attribute(QNetworkRequest::RedirectionTargetAttribute); + if (redirect.isValid()) { + m_url = m_url.resolved(redirect.toUrl()); + delete m_reply; + + QNetworkRequest request; + request.setUrl(m_url); + + m_reply = m_network->get(request); + QObject::connect(m_reply, SIGNAL(finished()), this, SLOT(finished())); + return; + } + } + + if (m_reply->error() == QNetworkReply::NoError) { + QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(m_engine); + + QByteArray data = m_reply->readAll(); + + QString code = QString::fromUtf8(data); + + QString urlString = m_url.toString(); + QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(m_scriptEngine); + scriptContext->pushScope(ep->contextClass->newUrlContext(m_context, 0, urlString)); + scriptContext->pushScope(m_scope[0]); + + scriptContext->pushScope(m_scope[1]); + scriptContext->setActivationObject(m_scope[1]); + + m_scriptEngine->evaluate(code, urlString, 1); + + m_scriptEngine->popContext(); + + if (m_scriptEngine->hasUncaughtException()) { + m_result.setProperty(QLatin1String("status"), QScriptValue(m_scriptEngine, Exception)); + m_result.setProperty(QLatin1String("exception"), m_scriptEngine->uncaughtException()); + m_scriptEngine->clearExceptions(); + } else { + m_result.setProperty(QLatin1String("status"), QScriptValue(m_scriptEngine, Ok)); + } + } else { + m_result.setProperty(QLatin1String("status"), QScriptValue(m_scriptEngine, NetworkError)); + } + + callback(m_scriptEngine, m_callback, m_result); + + disconnect(); + deleteLater(); +} + +void QDeclarativeInclude::callback(QScriptEngine *engine, QScriptValue &callback, QScriptValue &status) +{ + if (callback.isValid()) { + QScriptValue args = engine->newArray(1); + args.setProperty(0, status); + callback.call(QScriptValue(), args); + } +} + +static QString toLocalFileOrQrc(const QUrl& url) +{ + if (url.scheme() == QLatin1String("qrc")) { + if (url.authority().isEmpty()) + return QLatin1Char(':') + url.path(); + return QString(); + } + return url.toLocalFile(); +} + +QScriptValue QDeclarativeInclude::include(QScriptContext *ctxt, QScriptEngine *engine) +{ + if (ctxt->argumentCount() == 0) + return engine->undefinedValue(); + + QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); + + QUrl contextUrl = ep->contextClass->urlFromValue(QScriptDeclarativeClass::scopeChainValue(ctxt, -3)); + if (contextUrl.isEmpty()) + return ctxt->throwError(QLatin1String("Qt.include(): Can only be called from JavaScript files")); + + QString urlString = ctxt->argument(0).toString(); + QUrl url(ctxt->argument(0).toString()); + if (url.isRelative()) { + url = QUrl(contextUrl).resolved(url); + urlString = url.toString(); + } + + QString localFile = toLocalFileOrQrc(url); + + QScriptValue func = ctxt->argument(1); + if (!func.isFunction()) + func = QScriptValue(); + + QScriptValue result; + if (localFile.isEmpty()) { + QDeclarativeInclude *i = + new QDeclarativeInclude(url, QDeclarativeEnginePrivate::getEngine(engine), ctxt); + + if (func.isValid()) + i->setCallback(func); + + result = i->result(); + } else { + + QFile f(localFile); + if (f.open(QIODevice::ReadOnly)) { + QByteArray data = f.readAll(); + QString code = QString::fromUtf8(data); + + QDeclarativeContextData *context = + ep->contextClass->contextFromValue(QScriptDeclarativeClass::scopeChainValue(ctxt, -3)); + + QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(engine); + scriptContext->pushScope(ep->contextClass->newUrlContext(context, 0, urlString)); + scriptContext->pushScope(ep->globalClass->globalObject()); + QScriptValue scope = QScriptDeclarativeClass::scopeChainValue(ctxt, -5); + scriptContext->pushScope(scope); + scriptContext->setActivationObject(scope); + + engine->evaluate(code, urlString, 1); + + engine->popContext(); + + if (engine->hasUncaughtException()) { + result = resultValue(engine, Exception); + result.setProperty(QLatin1String("exception"), engine->uncaughtException()); + engine->clearExceptions(); + } else { + result = resultValue(engine, Ok); + } + callback(engine, func, result); + } else { + result = resultValue(engine, NetworkError); + callback(engine, func, result); + } + } + + return result; +} + +QScriptValue QDeclarativeInclude::worker_include(QScriptContext *ctxt, QScriptEngine *engine) +{ + if (ctxt->argumentCount() == 0) + return engine->undefinedValue(); + + QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); + + QString urlString = ctxt->argument(0).toString(); + QUrl url(ctxt->argument(0).toString()); + if (url.isRelative()) { + QString contextUrl = QScriptDeclarativeClass::scopeChainValue(ctxt, -3).data().toString(); + Q_ASSERT(!contextUrl.isEmpty()); + + url = QUrl(contextUrl).resolved(url); + urlString = url.toString(); + } + + QString localFile = toLocalFileOrQrc(url); + + QScriptValue func = ctxt->argument(1); + if (!func.isFunction()) + func = QScriptValue(); + + QScriptValue result; + if (!localFile.isEmpty()) { + + QFile f(localFile); + if (f.open(QIODevice::ReadOnly)) { + QByteArray data = f.readAll(); + QString code = QString::fromUtf8(data); + + QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(engine); + QScriptValue urlContext = engine->newObject(); + urlContext.setData(QScriptValue(engine, urlString)); + scriptContext->pushScope(urlContext); + + QScriptValue scope = QScriptDeclarativeClass::scopeChainValue(ctxt, -4); + scriptContext->pushScope(scope); + scriptContext->setActivationObject(scope); + + engine->evaluate(code, urlString, 1); + + engine->popContext(); + + if (engine->hasUncaughtException()) { + result = resultValue(engine, Exception); + result.setProperty(QLatin1String("exception"), engine->uncaughtException()); + engine->clearExceptions(); + } else { + result = resultValue(engine, Ok); + } + callback(engine, func, result); + } else { + result = resultValue(engine, NetworkError); + callback(engine, func, result); + } + } + + return result; +} + +QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativeinclude_p.h b/src/declarative/qml/qdeclarativeinclude_p.h new file mode 100644 index 0000000..3124374 --- /dev/null +++ b/src/declarative/qml/qdeclarativeinclude_p.h @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 QDECLARATIVEINCLUDE_P_H +#define QDECLARATIVEINCLUDE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qobject.h> +#include <QtCore/qurl.h> +#include <QtScript/qscriptvalue.h> + +#include <private/qdeclarativecontext_p.h> +#include <private/qdeclarativeguard_p.h> + +QT_BEGIN_NAMESPACE + +class QDeclarativeEngine; +class QScriptContext; +class QScriptEngine; +class QNetworkAccessManager; +class QNetworkReply; +class QDeclarativeInclude : public QObject +{ + Q_OBJECT +public: + enum Status { + Ok = 0, + Loading = 1, + NetworkError = 2, + Exception = 3 + }; + + QDeclarativeInclude(const QUrl &, QDeclarativeEngine *, QScriptContext *ctxt); + ~QDeclarativeInclude(); + + void setCallback(const QScriptValue &); + QScriptValue callback() const; + + QScriptValue result() const; + + static QScriptValue resultValue(QScriptEngine *, Status status = Loading); + static void callback(QScriptEngine *, QScriptValue &callback, QScriptValue &status); + + static QScriptValue include(QScriptContext *ctxt, QScriptEngine *engine); + static QScriptValue worker_include(QScriptContext *ctxt, QScriptEngine *engine); + +public slots: + void finished(); + +private: + QDeclarativeEngine *m_engine; + QScriptEngine *m_scriptEngine; + QNetworkAccessManager *m_network; + QDeclarativeGuard<QNetworkReply> m_reply; + + QUrl m_url; + int m_redirectCount; + QScriptValue m_callback; + QScriptValue m_result; + QDeclarativeGuardedContextData m_context; + QScriptValue m_scope[2]; +}; + +QT_END_NAMESPACE + +#endif // QDECLARATIVEINCLUDE_P_H + diff --git a/src/declarative/qml/qdeclarativeinstruction.cpp b/src/declarative/qml/qdeclarativeinstruction.cpp index 99f1cc8..0236950 100644 --- a/src/declarative/qml/qdeclarativeinstruction.cpp +++ b/src/declarative/qml/qdeclarativeinstruction.cpp @@ -136,6 +136,9 @@ void QDeclarativeCompiledData::dump(QDeclarativeInstruction *instr, int idx) case QDeclarativeInstruction::StoreVariantDouble: qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_VARIANT_DOUBLE\t\t" << instr->storeDouble.propertyIndex << "\t" << instr->storeDouble.value; break; + case QDeclarativeInstruction::StoreVariantBool: + qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_VARIANT_BOOL\t\t" << instr->storeBool.propertyIndex << "\t" << instr->storeBool.value; + break; case QDeclarativeInstruction::StoreObject: qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_OBJECT\t\t" << instr->storeObject.propertyIndex; break; diff --git a/src/declarative/qml/qdeclarativeinstruction_p.h b/src/declarative/qml/qdeclarativeinstruction_p.h index c09b157..dc5f2f8 100644 --- a/src/declarative/qml/qdeclarativeinstruction_p.h +++ b/src/declarative/qml/qdeclarativeinstruction_p.h @@ -116,6 +116,7 @@ public: StoreVariant, /* storeString */ StoreVariantInteger, /* storeInteger */ StoreVariantDouble, /* storeDouble */ + StoreVariantBool, /* storeBool */ StoreObject, /* storeObject */ StoreVariantObject, /* storeObject */ StoreInterface, /* storeObject */ diff --git a/src/declarative/qml/qdeclarativepropertycache.cpp b/src/declarative/qml/qdeclarativepropertycache.cpp index f04a706..839d79f 100644 --- a/src/declarative/qml/qdeclarativepropertycache.cpp +++ b/src/declarative/qml/qdeclarativepropertycache.cpp @@ -45,7 +45,7 @@ #include "private/qdeclarativebinding_p.h" #include <QtCore/qdebug.h> -Q_DECLARE_METATYPE(QScriptValue); +Q_DECLARE_METATYPE(QScriptValue) QT_BEGIN_NAMESPACE diff --git a/src/declarative/qml/qdeclarativescriptstring.h b/src/declarative/qml/qdeclarativescriptstring.h index 43bef44..fc92a9b 100644 --- a/src/declarative/qml/qdeclarativescriptstring.h +++ b/src/declarative/qml/qdeclarativescriptstring.h @@ -79,7 +79,7 @@ private: QT_END_NAMESPACE -Q_DECLARE_METATYPE(QDeclarativeScriptString); +Q_DECLARE_METATYPE(QDeclarativeScriptString) QT_END_HEADER diff --git a/src/declarative/qml/qdeclarativestringconverters_p.h b/src/declarative/qml/qdeclarativestringconverters_p.h index 7afdfd3..97f72fc 100644 --- a/src/declarative/qml/qdeclarativestringconverters_p.h +++ b/src/declarative/qml/qdeclarativestringconverters_p.h @@ -80,7 +80,7 @@ namespace QDeclarativeStringConverters QSizeF Q_DECLARATIVE_EXPORT sizeFFromString(const QString &, bool *ok = 0); QRectF Q_DECLARATIVE_EXPORT rectFFromString(const QString &, bool *ok = 0); QVector3D Q_DECLARATIVE_EXPORT vector3DFromString(const QString &, bool *ok = 0); -}; +} QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp index 3e63e24..8ba79a6 100644 --- a/src/declarative/qml/qdeclarativevme.cpp +++ b/src/declarative/qml/qdeclarativevme.cpp @@ -360,6 +360,16 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack, } break; + case QDeclarativeInstruction::StoreVariantBool: + { + QObject *target = stack.top(); + QVariant v(instr.storeBool.value); + void *a[] = { &v, 0, &status, &flags }; + QMetaObject::metacall(target, QMetaObject::WriteProperty, + instr.storeString.propertyIndex, a); + } + break; + case QDeclarativeInstruction::StoreString: { QObject *target = stack.top(); diff --git a/src/declarative/qml/qdeclarativeworkerscript.cpp b/src/declarative/qml/qdeclarativeworkerscript.cpp index c55998f..4b687a9 100644 --- a/src/declarative/qml/qdeclarativeworkerscript.cpp +++ b/src/declarative/qml/qdeclarativeworkerscript.cpp @@ -289,7 +289,11 @@ void QDeclarativeWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url) QScriptValue activation = getWorker(id); - QScriptContext *ctxt = workerEngine->pushContext(); + QScriptContext *ctxt = QScriptDeclarativeClass::pushCleanContext(workerEngine); + QScriptValue urlContext = workerEngine->newObject(); + urlContext.setData(QScriptValue(workerEngine, fileName)); + ctxt->pushScope(urlContext); + ctxt->pushScope(activation); ctxt->setActivationObject(activation); workerEngine->baseUrl = url; diff --git a/src/declarative/qml/qdeclarativeworkerscript_p.h b/src/declarative/qml/qdeclarativeworkerscript_p.h index 80ef5f3..dc73811 100644 --- a/src/declarative/qml/qdeclarativeworkerscript_p.h +++ b/src/declarative/qml/qdeclarativeworkerscript_p.h @@ -122,7 +122,7 @@ private: QT_END_NAMESPACE -QML_DECLARE_TYPE(QDeclarativeWorkerScript); +QML_DECLARE_TYPE(QDeclarativeWorkerScript) QT_END_HEADER diff --git a/src/declarative/qml/qdeclarativexmlhttprequest.cpp b/src/declarative/qml/qdeclarativexmlhttprequest.cpp index 94205fe..80510f8 100644 --- a/src/declarative/qml/qdeclarativexmlhttprequest.cpp +++ b/src/declarative/qml/qdeclarativexmlhttprequest.cpp @@ -321,9 +321,9 @@ public: QT_END_NAMESPACE -Q_DECLARE_METATYPE(Node); -Q_DECLARE_METATYPE(NodeList); -Q_DECLARE_METATYPE(NamedNodeMap); +Q_DECLARE_METATYPE(Node) +Q_DECLARE_METATYPE(NodeList) +Q_DECLARE_METATYPE(NamedNodeMap) QT_BEGIN_NAMESPACE diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index dab9767..12f9794 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -9,6 +9,7 @@ SOURCES += \ $$PWD/qdeclarativeproperty.cpp \ $$PWD/qdeclarativecomponent.cpp \ $$PWD/qdeclarativecontext.cpp \ + $$PWD/qdeclarativeinclude.cpp \ $$PWD/qdeclarativecustomparser.cpp \ $$PWD/qdeclarativepropertyvaluesource.cpp \ $$PWD/qdeclarativepropertyvalueinterceptor.cpp \ @@ -92,6 +93,7 @@ HEADERS += \ $$PWD/qdeclarativeinfo.h \ $$PWD/qdeclarativeproperty_p.h \ $$PWD/qdeclarativecontext_p.h \ + $$PWD/qdeclarativeinclude_p.h \ $$PWD/qdeclarativecompositetypedata_p.h \ $$PWD/qdeclarativecompositetypemanager_p.h \ $$PWD/qdeclarativelist.h \ diff --git a/src/declarative/util/qdeclarativeanimation.cpp b/src/declarative/util/qdeclarativeanimation.cpp index 0f7c946..67440b6 100644 --- a/src/declarative/util/qdeclarativeanimation.cpp +++ b/src/declarative/util/qdeclarativeanimation.cpp @@ -2536,13 +2536,13 @@ void QDeclarativeParentAnimation::transition(QDeclarativeStateActions &actions, viaData->pc << vpc; viaData->actions << myAction; QDeclarativeAction dummyAction; - QDeclarativeAction &xAction = pc->xIsSet() ? actions[++i] : dummyAction; - QDeclarativeAction &yAction = pc->yIsSet() ? actions[++i] : dummyAction; - QDeclarativeAction &sAction = pc->scaleIsSet() ? actions[++i] : dummyAction; - QDeclarativeAction &rAction = pc->rotationIsSet() ? actions[++i] : dummyAction; + QDeclarativeAction &xAction = pc->xIsSet() && i < actions.size()-1 ? actions[++i] : dummyAction; + QDeclarativeAction &yAction = pc->yIsSet() && i < actions.size()-1 ? actions[++i] : dummyAction; + QDeclarativeAction &sAction = pc->scaleIsSet() && i < actions.size()-1 ? actions[++i] : dummyAction; + QDeclarativeAction &rAction = pc->rotationIsSet() && i < actions.size()-1 ? actions[++i] : dummyAction; bool forward = (direction == QDeclarativeAbstractAnimation::Forward); QDeclarativeItem *target = pc->object(); - QDeclarativeItem *targetParent = forward ? pc->parent() : pc->originalParent(); + QDeclarativeItem *targetParent = action.reverseEvent ? pc->originalParent() : pc->parent(); //### this mirrors the logic in QDeclarativeParentChange. bool ok; @@ -2583,9 +2583,9 @@ void QDeclarativeParentAnimation::transition(QDeclarativeStateActions &actions, if (ok && target->transformOrigin() != QDeclarativeItem::TopLeft) { qreal w = target->width(); qreal h = target->height(); - if (pc->widthIsSet()) + if (pc->widthIsSet() && i < actions.size() - 1) w = actions[++i].toValue.toReal(); - if (pc->heightIsSet()) + if (pc->heightIsSet() && i < actions.size() - 1) h = actions[++i].toValue.toReal(); const QPointF &transformOrigin = d->computeTransformOrigin(target->transformOrigin(), w,h); diff --git a/src/declarative/util/qdeclarativebehavior.cpp b/src/declarative/util/qdeclarativebehavior.cpp index ba90007..90e0ca3 100644 --- a/src/declarative/util/qdeclarativebehavior.cpp +++ b/src/declarative/util/qdeclarativebehavior.cpp @@ -62,6 +62,7 @@ public: QDeclarativeProperty property; QVariant currentValue; + QVariant targetValue; QDeclarativeGuard<QDeclarativeAbstractAnimation> animation; bool enabled; bool finalized; @@ -162,10 +163,15 @@ void QDeclarativeBehavior::write(const QVariant &value) qmlExecuteDeferred(this); if (!d->animation || !d->enabled || !d->finalized) { QDeclarativePropertyPrivate::write(d->property, value, QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::DontRemoveBinding); + d->targetValue = value; return; } + if (value == d->targetValue) + return; + d->currentValue = d->property.read(); + d->targetValue = value; if (d->animation->qtAnimation()->duration() != -1) d->animation->qtAnimation()->stop(); diff --git a/src/declarative/util/qdeclarativelistmodel.cpp b/src/declarative/util/qdeclarativelistmodel.cpp index 0985a6b..9a5c9de 100644 --- a/src/declarative/util/qdeclarativelistmodel.cpp +++ b/src/declarative/util/qdeclarativelistmodel.cpp @@ -207,11 +207,11 @@ QDeclarativeListModelParser::ListInstruction *QDeclarativeListModelParser::ListM Here is an example that uses WorkerScript to periodically append the current time to a list model: - \snippet examples/declarative/listmodel-threaded/timedisplay.qml 0 + \snippet examples/declarative/threading/threadedlistmodel/timedisplay.qml 0 The included file, \tt dataloader.js, looks like this: - \snippet examples/declarative/listmodel-threaded/dataloader.js 0 + \snippet examples/declarative/threading/threadedlistmodel/dataloader.js 0 The application's \tt Timer object periodically sends a message to the worker script by calling \tt WorkerScript::sendMessage(). When this message @@ -537,11 +537,7 @@ void QDeclarativeListModel::append(const QScriptValue& valuemap) */ QScriptValue QDeclarativeListModel::get(int index) const { - if (index >= count() || index < 0) { - qmlInfo(this) << tr("get: index %1 out of range").arg(index); - return 0; - } - + // the internal flat/nested class checks for bad index return m_flat ? m_flat->get(index) : m_nested->get(index); } @@ -930,13 +926,14 @@ bool FlatListModel::insert(int index, const QScriptValue &value) QScriptValue FlatListModel::get(int index) const { - Q_ASSERT(index >= 0 && index < m_values.count()); - QScriptEngine *scriptEngine = m_scriptEngine ? m_scriptEngine : QDeclarativeEnginePrivate::getScriptEngine(qmlEngine(m_listModel)); - if (!scriptEngine) + if (!scriptEngine) return 0; + if (index < 0 || index >= m_values.count()) + return scriptEngine->undefinedValue(); + QScriptValue rv = scriptEngine->newObject(); QHash<int, QVariant> row = m_values.at(index); @@ -999,7 +996,8 @@ bool FlatListModel::addValue(const QScriptValue &value, QHash<int, QVariant> *ro QScriptValueIterator it(value); while (it.hasNext()) { it.next(); - if (it.value().isObject()) { + QScriptValue value = it.value(); + if (!value.isVariant() && !value.isRegExp() && !value.isDate() && value.isObject()) { qmlInfo(m_listModel) << "Cannot add nested list values when modifying or after modification from a worker script"; return false; } @@ -1182,13 +1180,21 @@ bool NestedListModel::append(const QScriptValue& valuemap) } QScriptValue NestedListModel::get(int index) const -{ - ModelNode *node = qvariant_cast<ModelNode *>(_root->values.at(index)); - if (!node) - return 0; +{ QDeclarativeEngine *eng = qmlEngine(m_listModel); if (!eng) return 0; + + if (index < 0 || index >= count()) { + QScriptEngine *seng = QDeclarativeEnginePrivate::getScriptEngine(eng); + if (seng) + return seng->undefinedValue(); + return 0; + } + + ModelNode *node = qvariant_cast<ModelNode *>(_root->values.at(index)); + if (!node) + return 0; return QDeclarativeEnginePrivate::qmlScriptObject(node->object(this), eng); } diff --git a/src/declarative/util/qdeclarativelistmodelworkeragent_p.h b/src/declarative/util/qdeclarativelistmodelworkeragent_p.h index 53d30c2..1622144 100644 --- a/src/declarative/util/qdeclarativelistmodelworkeragent_p.h +++ b/src/declarative/util/qdeclarativelistmodelworkeragent_p.h @@ -146,7 +146,7 @@ private: QT_END_NAMESPACE -Q_DECLARE_METATYPE(QDeclarativeListModelWorkerAgent::VariantRef); +Q_DECLARE_METATYPE(QDeclarativeListModelWorkerAgent::VariantRef) QT_END_HEADER diff --git a/src/declarative/util/qdeclarativepackage.cpp b/src/declarative/util/qdeclarativepackage.cpp index 20e9907..9617b86 100644 --- a/src/declarative/util/qdeclarativepackage.cpp +++ b/src/declarative/util/qdeclarativepackage.cpp @@ -62,13 +62,13 @@ QT_BEGIN_NAMESPACE delegate it should appear in. This allows an item to move between views. - \snippet examples/declarative/package/Delegate.qml 0 + \snippet examples/declarative/modelviews/package/Delegate.qml 0 These named items are used as the delegates by the two views who reference the special VisualDataModel.parts property to select a model which provides the chosen delegate. - \snippet examples/declarative/package/view.qml 0 + \snippet examples/declarative/modelviews/package/view.qml 0 \sa QtDeclarative */ diff --git a/src/declarative/util/qdeclarativepixmapcache.cpp b/src/declarative/util/qdeclarativepixmapcache.cpp index dbca326..d9ce42c 100644 --- a/src/declarative/util/qdeclarativepixmapcache.cpp +++ b/src/declarative/util/qdeclarativepixmapcache.cpp @@ -55,6 +55,7 @@ #include <QFile> #include <QThread> #include <QMutex> +#include <QBuffer> #include <QWaitCondition> #include <QtCore/qdebug.h> #include <private/qobject_p.h> @@ -342,7 +343,10 @@ void QDeclarativeImageRequestHandler::networkRequestDone() errorString = reply->errorString(); } else { QSize read_impsize; - if (readImage(reply->url(), reply, &image, &errorString, &read_impsize, job->forcedWidth(), job->forcedHeight())) { + QByteArray all = reply->readAll(); + QBuffer buff(&all); + buff.open(QIODevice::ReadOnly); + if (readImage(reply->url(), &buff, &image, &errorString, &read_impsize, job->forcedWidth(), job->forcedHeight())) { qmlOriginalSizes()->insert(reply->url(), read_impsize); error = QDeclarativeImageReaderEvent::NoError; } else { diff --git a/src/declarative/util/qdeclarativepropertychanges.cpp b/src/declarative/util/qdeclarativepropertychanges.cpp index 94780c4..12fef36 100644 --- a/src/declarative/util/qdeclarativepropertychanges.cpp +++ b/src/declarative/util/qdeclarativepropertychanges.cpp @@ -161,20 +161,15 @@ public: QDeclarativeExpression *rewindExpression; QDeclarativeGuard<QDeclarativeExpression> ownedExpression; - virtual bool changesBindings() { return true; } - virtual void clearBindings() { - ownedExpression = QDeclarativePropertyPrivate::setSignalExpression(property, 0); - } - virtual void execute(Reason) { - QDeclarativePropertyPrivate::setSignalExpression(property, expression); + ownedExpression = QDeclarativePropertyPrivate::setSignalExpression(property, expression); if (ownedExpression == expression) ownedExpression = 0; } virtual bool isReversable() { return true; } virtual void reverse(Reason) { - QDeclarativePropertyPrivate::setSignalExpression(property, reverseExpression); + ownedExpression = QDeclarativePropertyPrivate::setSignalExpression(property, reverseExpression); if (ownedExpression == reverseExpression) ownedExpression = 0; } @@ -184,7 +179,7 @@ public: reverseExpression = rewindExpression; } - virtual void copyOriginals(QDeclarativeActionEvent *other) + /*virtual void copyOriginals(QDeclarativeActionEvent *other) { QDeclarativeReplaceSignalHandler *rsh = static_cast<QDeclarativeReplaceSignalHandler*>(other); saveCurrentValues(); @@ -195,10 +190,10 @@ public: ownedExpression = rsh->ownedExpression; rsh->ownedExpression = 0; } - } + }*/ virtual void rewind() { - QDeclarativePropertyPrivate::setSignalExpression(property, rewindExpression); + ownedExpression = QDeclarativePropertyPrivate::setSignalExpression(property, rewindExpression); if (ownedExpression == rewindExpression) ownedExpression = 0; } diff --git a/src/declarative/util/qdeclarativesmoothedanimation_p.h b/src/declarative/util/qdeclarativesmoothedanimation_p.h index 17aafa4..f45d19f 100644 --- a/src/declarative/util/qdeclarativesmoothedanimation_p.h +++ b/src/declarative/util/qdeclarativesmoothedanimation_p.h @@ -96,7 +96,7 @@ Q_SIGNALS: QT_END_NAMESPACE -QML_DECLARE_TYPE(QDeclarativeSmoothedAnimation); +QML_DECLARE_TYPE(QDeclarativeSmoothedAnimation) QT_END_HEADER diff --git a/src/declarative/util/qdeclarativesmoothedfollow_p.h b/src/declarative/util/qdeclarativesmoothedfollow_p.h index d860052..6319192 100644 --- a/src/declarative/util/qdeclarativesmoothedfollow_p.h +++ b/src/declarative/util/qdeclarativesmoothedfollow_p.h @@ -106,7 +106,7 @@ Q_SIGNALS: QT_END_NAMESPACE -QML_DECLARE_TYPE(QDeclarativeSmoothedFollow); +QML_DECLARE_TYPE(QDeclarativeSmoothedFollow) QT_END_HEADER diff --git a/src/declarative/util/qdeclarativestate.cpp b/src/declarative/util/qdeclarativestate.cpp index ea209aa..b5f7900 100644 --- a/src/declarative/util/qdeclarativestate.cpp +++ b/src/declarative/util/qdeclarativestate.cpp @@ -390,12 +390,13 @@ void QDeclarativeState::apply(QDeclarativeStateGroup *group, QDeclarativeTransit if (action.event->override(event)) { found = true; - if (action.event != d->revertList.at(jj).event) { + if (action.event != d->revertList.at(jj).event && action.event->needsCopy()) { action.event->copyOriginals(d->revertList.at(jj).event); QDeclarativeSimpleAction r(action); additionalReverts << r; d->revertList.removeAt(jj); + --jj; } else if (action.event->isRewindable()) //###why needed? action.event->saveCurrentValues(); diff --git a/src/declarative/util/qdeclarativestate_p.h b/src/declarative/util/qdeclarativestate_p.h index 0ba67b0..25715c6 100644 --- a/src/declarative/util/qdeclarativestate_p.h +++ b/src/declarative/util/qdeclarativestate_p.h @@ -96,6 +96,7 @@ public: virtual bool isReversable(); virtual void reverse(Reason reason = ActualChange); virtual void saveOriginals() {} + virtual bool needsCopy() { return false; } virtual void copyOriginals(QDeclarativeActionEvent *) {} virtual bool isRewindable() { return isReversable(); } diff --git a/src/declarative/util/qdeclarativestateoperations.cpp b/src/declarative/util/qdeclarativestateoperations.cpp index a93a25d..0326f6d 100644 --- a/src/declarative/util/qdeclarativestateoperations.cpp +++ b/src/declarative/util/qdeclarativestateoperations.cpp @@ -408,7 +408,7 @@ void QDeclarativeParentChange::saveOriginals() d->origStackBefore = d->rewindStackBefore; } -void QDeclarativeParentChange::copyOriginals(QDeclarativeActionEvent *other) +/*void QDeclarativeParentChange::copyOriginals(QDeclarativeActionEvent *other) { Q_D(QDeclarativeParentChange); QDeclarativeParentChange *pc = static_cast<QDeclarativeParentChange*>(other); @@ -417,7 +417,7 @@ void QDeclarativeParentChange::copyOriginals(QDeclarativeActionEvent *other) d->origStackBefore = pc->d_func()->rewindStackBefore; saveCurrentValues(); -} +}*/ void QDeclarativeParentChange::execute(Reason) { @@ -1241,24 +1241,28 @@ QList<QDeclarativeAction> QDeclarativeAnchorChanges::additionalActions() Q_D(QDeclarativeAnchorChanges); QList<QDeclarativeAction> extra; + QDeclarativeAnchors::Anchors combined = d->anchorSet->d_func()->usedAnchors | d->anchorSet->d_func()->resetAnchors; + bool hChange = combined & QDeclarativeAnchors::Horizontal_Mask; + bool vChange = combined & QDeclarativeAnchors::Vertical_Mask; + if (d->target) { QDeclarativeAction a; - if (d->fromX != d->toX) { + if (hChange && d->fromX != d->toX) { a.property = QDeclarativeProperty(d->target, QLatin1String("x")); a.toValue = d->toX; extra << a; } - if (d->fromY != d->toY) { + if (vChange && d->fromY != d->toY) { a.property = QDeclarativeProperty(d->target, QLatin1String("y")); a.toValue = d->toY; extra << a; } - if (d->fromWidth != d->toWidth) { + if (hChange && d->fromWidth != d->toWidth) { a.property = QDeclarativeProperty(d->target, QLatin1String("width")); a.toValue = d->toWidth; extra << a; } - if (d->fromHeight != d->toHeight) { + if (vChange && d->fromHeight != d->toHeight) { a.property = QDeclarativeProperty(d->target, QLatin1String("height")); a.toValue = d->toHeight; extra << a; diff --git a/src/declarative/util/qdeclarativestateoperations_p.h b/src/declarative/util/qdeclarativestateoperations_p.h index e22c1e2..21a86f5 100644 --- a/src/declarative/util/qdeclarativestateoperations_p.h +++ b/src/declarative/util/qdeclarativestateoperations_p.h @@ -107,7 +107,7 @@ public: virtual ActionList actions(); virtual void saveOriginals(); - virtual void copyOriginals(QDeclarativeActionEvent*); + //virtual void copyOriginals(QDeclarativeActionEvent*); virtual void execute(Reason reason = ActualChange); virtual bool isReversable(); virtual void reverse(Reason reason = ActualChange); @@ -277,6 +277,7 @@ public: virtual bool override(QDeclarativeActionEvent*other); virtual bool changesBindings(); virtual void saveOriginals(); + virtual bool needsCopy() { return true; } virtual void copyOriginals(QDeclarativeActionEvent*); virtual void clearBindings(); virtual void rewind(); diff --git a/src/declarative/util/qdeclarativetransitionmanager_p_p.h b/src/declarative/util/qdeclarativetransitionmanager_p_p.h index 4131391..2e23898 100644 --- a/src/declarative/util/qdeclarativetransitionmanager_p_p.h +++ b/src/declarative/util/qdeclarativetransitionmanager_p_p.h @@ -70,7 +70,7 @@ public: void cancel(); private: - Q_DISABLE_COPY(QDeclarativeTransitionManager); + Q_DISABLE_COPY(QDeclarativeTransitionManager) QDeclarativeTransitionManagerPrivate *d; void complete(); diff --git a/src/declarative/util/qdeclarativeview.cpp b/src/declarative/util/qdeclarativeview.cpp index 833e284..e68ef94 100644 --- a/src/declarative/util/qdeclarativeview.cpp +++ b/src/declarative/util/qdeclarativeview.cpp @@ -128,19 +128,18 @@ void FrameBreakAnimation::updateCurrentTime(int msecs) server->frameBreak(); } -class QDeclarativeViewPrivate : public QDeclarativeItemChangeListener +class QDeclarativeViewPrivate : public QGraphicsViewPrivate, public QDeclarativeItemChangeListener { + Q_DECLARE_PUBLIC(QDeclarativeView) public: - QDeclarativeViewPrivate(QDeclarativeView *view) - : q(view), root(0), declarativeItemRoot(0), graphicsWidgetRoot(0), component(0), resizeMode(QDeclarativeView::SizeViewToRootObject) {} + QDeclarativeViewPrivate() + : root(0), declarativeItemRoot(0), graphicsWidgetRoot(0), component(0), resizeMode(QDeclarativeView::SizeViewToRootObject) {} ~QDeclarativeViewPrivate() { delete root; } void execute(); void itemGeometryChanged(QDeclarativeItem *item, const QRectF &newGeometry, const QRectF &oldGeometry); void initResize(); void updateSize(); - inline QSize rootObjectSize(); - - QDeclarativeView *q; + inline QSize rootObjectSize() const; QDeclarativeGuard<QGraphicsObject> root; QDeclarativeGuard<QDeclarativeItem> declarativeItemRoot; @@ -162,6 +161,7 @@ public: void QDeclarativeViewPrivate::execute() { + Q_Q(QDeclarativeView); if (root) { delete root; root = 0; @@ -182,6 +182,7 @@ void QDeclarativeViewPrivate::execute() void QDeclarativeViewPrivate::itemGeometryChanged(QDeclarativeItem *resizeItem, const QRectF &newGeometry, const QRectF &oldGeometry) { + Q_Q(QDeclarativeView); if (resizeItem == root && resizeMode == QDeclarativeView::SizeViewToRootObject) { // wait for both width and height to be changed resizetimer.start(0,q); @@ -250,8 +251,9 @@ void QDeclarativeViewPrivate::itemGeometryChanged(QDeclarativeItem *resizeItem, Constructs a QDeclarativeView with the given \a parent. */ QDeclarativeView::QDeclarativeView(QWidget *parent) -: QGraphicsView(parent), d(new QDeclarativeViewPrivate(this)) + : QGraphicsView(*(new QDeclarativeViewPrivate), parent) { + Q_D(QDeclarativeView); setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Preferred); d->init(); } @@ -262,8 +264,9 @@ QDeclarativeView::QDeclarativeView(QWidget *parent) Constructs a QDeclarativeView with the given QML \a source and \a parent. */ QDeclarativeView::QDeclarativeView(const QUrl &source, QWidget *parent) -: QGraphicsView(parent), d(new QDeclarativeViewPrivate(this)) + : QGraphicsView(*(new QDeclarativeViewPrivate), parent) { + Q_D(QDeclarativeView); setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Preferred); d->init(); setSource(source); @@ -271,6 +274,7 @@ QDeclarativeView::QDeclarativeView(const QUrl &source, QWidget *parent) void QDeclarativeViewPrivate::init() { + Q_Q(QDeclarativeView); q->setScene(&scene); q->setOptimizationFlags(QGraphicsView::DontSavePainterState); @@ -288,12 +292,10 @@ void QDeclarativeViewPrivate::init() } /*! - The destructor clears the view's \l {QGraphicsObject} {items} and - deletes the internal representation. + Destroys the view. */ QDeclarativeView::~QDeclarativeView() { - delete d; } /*! \property QDeclarativeView::source @@ -316,6 +318,7 @@ QDeclarativeView::~QDeclarativeView() */ void QDeclarativeView::setSource(const QUrl& url) { + Q_D(QDeclarativeView); d->source = url; d->execute(); } @@ -327,6 +330,7 @@ void QDeclarativeView::setSource(const QUrl& url) */ QUrl QDeclarativeView::source() const { + Q_D(const QDeclarativeView); return d->source; } @@ -336,6 +340,7 @@ QUrl QDeclarativeView::source() const */ QDeclarativeEngine* QDeclarativeView::engine() { + Q_D(QDeclarativeView); return &d->engine; } @@ -348,6 +353,7 @@ QDeclarativeEngine* QDeclarativeView::engine() */ QDeclarativeContext* QDeclarativeView::rootContext() { + Q_D(QDeclarativeView); return d->engine.rootContext(); } @@ -376,6 +382,7 @@ QDeclarativeContext* QDeclarativeView::rootContext() QDeclarativeView::Status QDeclarativeView::status() const { + Q_D(const QDeclarativeView); if (!d->component) return QDeclarativeView::Null; @@ -388,6 +395,7 @@ QDeclarativeView::Status QDeclarativeView::status() const */ QList<QDeclarativeError> QDeclarativeView::errors() const { + Q_D(const QDeclarativeView); if (d->component) return d->component->errors(); return QList<QDeclarativeError>(); @@ -410,6 +418,7 @@ QList<QDeclarativeError> QDeclarativeView::errors() const void QDeclarativeView::setResizeMode(ResizeMode mode) { + Q_D(QDeclarativeView); if (d->resizeMode == mode) return; @@ -433,6 +442,7 @@ void QDeclarativeView::setResizeMode(ResizeMode mode) void QDeclarativeViewPrivate::initResize() { + Q_Q(QDeclarativeView); if (declarativeItemRoot) { if (resizeMode == QDeclarativeView::SizeViewToRootObject) { QDeclarativeItemPrivate *p = @@ -449,6 +459,7 @@ void QDeclarativeViewPrivate::initResize() void QDeclarativeViewPrivate::updateSize() { + Q_Q(QDeclarativeView); if (!root) return; if (declarativeItemRoot) { @@ -479,7 +490,7 @@ void QDeclarativeViewPrivate::updateSize() q->updateGeometry(); } -QSize QDeclarativeViewPrivate::rootObjectSize() +QSize QDeclarativeViewPrivate::rootObjectSize() const { QSize rootObjectSize(0,0); int widthCandidate = -1; @@ -500,6 +511,7 @@ QSize QDeclarativeViewPrivate::rootObjectSize() QDeclarativeView::ResizeMode QDeclarativeView::resizeMode() const { + Q_D(const QDeclarativeView); return d->resizeMode; } @@ -508,7 +520,7 @@ QDeclarativeView::ResizeMode QDeclarativeView::resizeMode() const */ void QDeclarativeView::continueExecute() { - + Q_D(QDeclarativeView); disconnect(d->component, SIGNAL(statusChanged(QDeclarativeComponent::Status)), this, SLOT(continueExecute())); if (d->component->isError()) { @@ -541,6 +553,7 @@ void QDeclarativeView::continueExecute() */ void QDeclarativeView::setRootObject(QObject *obj) { + Q_D(QDeclarativeView); if (d->root == obj) return; if (QDeclarativeItem *declarativeItem = qobject_cast<QDeclarativeItem *>(obj)) { @@ -590,6 +603,7 @@ void QDeclarativeView::setRootObject(QObject *obj) */ void QDeclarativeView::timerEvent(QTimerEvent* e) { + Q_D(QDeclarativeView); if (!e || e->timerId() == d->resizetimer.timerId()) { d->updateSize(); d->resizetimer.stop(); @@ -599,6 +613,7 @@ void QDeclarativeView::timerEvent(QTimerEvent* e) /*! \reimp */ bool QDeclarativeView::eventFilter(QObject *watched, QEvent *e) { + Q_D(QDeclarativeView); if (watched == d->root && d->resizeMode == SizeViewToRootObject) { if (d->graphicsWidgetRoot) { if (e->type() == QEvent::GraphicsSceneResize) { @@ -615,6 +630,7 @@ bool QDeclarativeView::eventFilter(QObject *watched, QEvent *e) */ QSize QDeclarativeView::sizeHint() const { + Q_D(const QDeclarativeView); QSize rootObjectSize = d->rootObjectSize(); if (rootObjectSize.isEmpty()) { return size(); @@ -628,6 +644,7 @@ QSize QDeclarativeView::sizeHint() const */ QGraphicsObject *QDeclarativeView::rootObject() const { + Q_D(const QDeclarativeView); return d->root; } @@ -638,6 +655,7 @@ QGraphicsObject *QDeclarativeView::rootObject() const */ void QDeclarativeView::resizeEvent(QResizeEvent *e) { + Q_D(QDeclarativeView); if (d->resizeMode == SizeRootObjectToView) { d->updateSize(); } @@ -657,6 +675,7 @@ void QDeclarativeView::resizeEvent(QResizeEvent *e) */ void QDeclarativeView::paintEvent(QPaintEvent *event) { + Q_D(QDeclarativeView); int time = 0; if (frameRateDebug() || QDeclarativeViewDebugServer::isDebuggingEnabled()) time = d->frameTimer.restart(); diff --git a/src/declarative/util/qdeclarativeview.h b/src/declarative/util/qdeclarativeview.h index 3513c04..e9cff32 100644 --- a/src/declarative/util/qdeclarativeview.h +++ b/src/declarative/util/qdeclarativeview.h @@ -106,9 +106,8 @@ protected: virtual bool eventFilter(QObject *watched, QEvent *e); private: - friend class QDeclarativeViewPrivate; - QDeclarativeViewPrivate *d; Q_DISABLE_COPY(QDeclarativeView) + Q_DECLARE_PRIVATE(QDeclarativeView) }; QT_END_NAMESPACE diff --git a/src/declarative/util/qdeclarativexmllistmodel.cpp b/src/declarative/util/qdeclarativexmllistmodel.cpp index ae3b5d7..4a374a5 100644 --- a/src/declarative/util/qdeclarativexmllistmodel.cpp +++ b/src/declarative/util/qdeclarativexmllistmodel.cpp @@ -472,40 +472,71 @@ void QDeclarativeXmlListModelPrivate::clear_role(QDeclarativeListProperty<QDecla \since 4.7 \brief The XmlListModel element is used to specify a model using XPath expressions. - XmlListModel is used to create a model from XML data that can be used as a data source + XmlListModel is used to create a model from XML data. XmlListModel can be used as a data source for the view classes (such as ListView, PathView, GridView) and other classes that interact with model - data (such as Repeater). + data (such as \l Repeater). + + For example, if there is a XML document at http://www.mysite.com/feed.xml like this: + + \code + <?xml version="1.0" encoding="utf-8"?> + <rss version="2.0"> + ... + <channel> + <item> + <title>Item A</title> + <pubDate>Sat, 07 Sep 2010 10:00:01 GMT</pubDate> + </item> + <item> + <title>Item B</title> + <pubDate>Sat, 07 Sep 2010 15:35:01 GMT</pubDate> + </item> + </channel> + </rss> + \endcode + + Then it could be used to create the following model: - Here is an example of a model containing news from a Yahoo RSS feed: \qml XmlListModel { - id: feedModel - source: "http://rss.news.yahoo.com/rss/oceania" + source: "http://www.mysite.com/feed.xml" query: "/rss/channel/item" XmlRole { name: "title"; query: "title/string()" } XmlRole { name: "pubDate"; query: "pubDate/string()" } - XmlRole { name: "description"; query: "description/string()" } } \endqml - You can also define certain roles as "keys" so that the model only adds data - that contains new values for these keys when reload() is called. + The \l {XmlListModel::query}{query} value of "/rss/channel/item" specifies that the XmlListModel should generate + a model item for each \c <item> in the XML document. The XmlRole objects define the + model item attributes; here, each model item will have \c title and \c pubDate + attributes that match the \c title and \c pubDate values of its corresponding \c <item>. - For example, if the roles above were defined like this: + + \section2 Using key XML roles + + You can define certain roles as "keys" so that when reload() is called, + the model will only add and refresh data that contains new values for + these keys. + + For example, if above role for "pubDate" was defined like this instead: \qml - XmlRole { name: "title"; query: "title/string()"; isKey: true } XmlRole { name: "pubDate"; query: "pubDate/string()"; isKey: true } \endqml - Then when reload() is called, the model will only add new items with a - "title" and "pubDate" value combination that is not already present in - the model. + Then when reload() is called, the model will only add and reload + items with a "pubDate" value that is not already + present in the model. - This is useful to provide incremental updates and avoid repainting an - entire model in a view. + This is useful when displaying the contents of XML documents that + are incrementally updated (such as RSS feeds) to avoid repainting the + entire contents of a model in a view. - \sa {QtDeclarative} + If multiple key roles are specified, the model only adds and reload items + with a combined value of all key roles that is not already present in + the model. + + \sa {declarative/xml/xmldata}{XML data example} */ QDeclarativeXmlListModel::QDeclarativeXmlListModel(QObject *parent) @@ -626,8 +657,8 @@ void QDeclarativeXmlListModel::setXml(const QString &xml) /*! \qmlproperty string XmlListModel::query - An absolute XPath query representing the base query for the model items. The query should start with - '/' or '//'. + An absolute XPath query representing the base query for creating model items + from this model's XmlRole objects. The query should start with '/' or '//'. */ QString QDeclarativeXmlListModel::query() const { @@ -652,7 +683,20 @@ void QDeclarativeXmlListModel::setQuery(const QString &query) /*! \qmlproperty string XmlListModel::namespaceDeclarations - A set of declarations for the namespaces used in the query. + The namespace declarations to be used in the XPath queries. + + The namespaces should be declared as in XQuery. For example, if a requested document + at http://mysite.com/feed.xml uses the namespace "http://www.w3.org/2005/Atom", + this can be declared as the default namespace: + + \qml + XmlListModel { + source: "http://mysite.com/feed.xml" + query: "/feed/entry" + namespaceDeclarations: "declare default element namespace 'http://www.w3.org/2005/Atom';" + XmlRole { name: "title"; query: "title/string()" } + } + \endqml */ QString QDeclarativeXmlListModel::namespaceDeclarations() const { @@ -735,7 +779,7 @@ void QDeclarativeXmlListModel::componentComplete() Otherwise, items are only added if the model does not already contain items with matching key role values. - \sa XmlRole::isKey + \sa {Using key XML roles}, XmlRole::isKey */ void QDeclarativeXmlListModel::reload() { @@ -752,8 +796,11 @@ void QDeclarativeXmlListModel::reload() if (d->reply) { d->reply->abort(); - d->reply->deleteLater(); - d->reply = 0; + if (d->reply) { + // abort will generally have already done this (and more) + d->reply->deleteLater(); + d->reply = 0; + } } if (!d->xml.isEmpty()) { |