From 2c0255521f00a1fd95988161a03c39631350eaba Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Thu, 10 Sep 2009 13:21:36 +1000 Subject: Follow renamed to SpringFollow. --- demos/declarative/samegame/content/BoomBlock.qml | 4 +- demos/declarative/webbrowser/webbrowser.qml | 1 + .../declarative/aspectratio/face_fit_animated.qml | 2 +- examples/declarative/clock/Clock.qml | 6 +- examples/declarative/dial/DialLibrary/Dial.qml | 4 +- examples/declarative/follow/follow.qml | 10 +- examples/declarative/follow/pong.qml | 6 +- examples/declarative/listview/highlight.qml | 2 +- examples/declarative/snow/snow.qml | 6 +- examples/declarative/velocity/Day.qml | 2 +- src/declarative/QmlChanges.txt | 1 + src/declarative/fx/qfxgridview.cpp | 16 +- src/declarative/fx/qfxlistview.cpp | 52 ++- src/declarative/fx/qfxlistview.h | 1 + src/declarative/util/qmleasefollow.cpp | 28 +- src/declarative/util/qmleasefollow.h | 4 + src/declarative/util/qmlfollow.cpp | 456 --------------------- src/declarative/util/qmlfollow.h | 113 ----- src/declarative/util/qmlspringfollow.cpp | 456 +++++++++++++++++++++ src/declarative/util/qmlspringfollow.h | 113 +++++ src/declarative/util/util.pri | 4 +- 21 files changed, 676 insertions(+), 611 deletions(-) delete mode 100644 src/declarative/util/qmlfollow.cpp delete mode 100644 src/declarative/util/qmlfollow.h create mode 100644 src/declarative/util/qmlspringfollow.cpp create mode 100644 src/declarative/util/qmlspringfollow.h diff --git a/demos/declarative/samegame/content/BoomBlock.qml b/demos/declarative/samegame/content/BoomBlock.qml index 7860cf4..a495cd0 100644 --- a/demos/declarative/samegame/content/BoomBlock.qml +++ b/demos/declarative/samegame/content/BoomBlock.qml @@ -7,8 +7,8 @@ Item { id:block property int targetX: 0 property int targetY: 0 - x: Follow { enabled: spawned; source: targetX; spring: 2; damping: 0.2 } - y: Follow { source: targetY; spring: 2; damping: 0.2 } + x: SpringFollow { enabled: spawned; source: targetX; spring: 2; damping: 0.2 } + y: SpringFollow { source: targetY; spring: 2; damping: 0.2 } Image { id: img source: { diff --git a/demos/declarative/webbrowser/webbrowser.qml b/demos/declarative/webbrowser/webbrowser.qml index 9a8af29..ae3d048 100644 --- a/demos/declarative/webbrowser/webbrowser.qml +++ b/demos/declarative/webbrowser/webbrowser.qml @@ -167,6 +167,7 @@ Item { anchors.bottom: Footer.top anchors.left: parent.left anchors.right: parent.right + pressDelay: 200 WebView { id: MyWebView diff --git a/examples/declarative/aspectratio/face_fit_animated.qml b/examples/declarative/aspectratio/face_fit_animated.qml index 2768150..7db1c80 100644 --- a/examples/declarative/aspectratio/face_fit_animated.qml +++ b/examples/declarative/aspectratio/face_fit_animated.qml @@ -16,7 +16,7 @@ Rectangle { source: "pics/face.png" x: (parent.width-width*scale)/2 y: (parent.height-height*scale)/2 - scale: Follow { + scale: SpringFollow { source: Math.max(Math.min(Image.parent.width/Image.width*1.333,Image.parent.height/Image.height), Math.min(Image.parent.width/Image.width,Image.parent.height/Image.height*1.333)) spring: 1 diff --git a/examples/declarative/clock/Clock.qml b/examples/declarative/clock/Clock.qml index e152be3..6064dd4 100644 --- a/examples/declarative/clock/Clock.qml +++ b/examples/declarative/clock/Clock.qml @@ -28,7 +28,7 @@ Item { id: HourRotation origin.x: 4; origin.y: 45 angle: 0 - angle: Follow { + angle: SpringFollow { spring: 2 damping: .2 source: Clock.hours * 50 * 3 + Clock.minutes / 2 @@ -44,7 +44,7 @@ Item { id: MinuteRotation origin.x: 4; origin.y: 70 angle: 0 - angle: Follow { + angle: SpringFollow { spring: 2 damping: .2 source: Clock.minutes * 6 @@ -60,7 +60,7 @@ Item { id: SecondRotation origin.x: 2; origin.y: 60 angle: 0 - angle: Follow { + angle: SpringFollow { spring: 5 damping: .25 modulus: 360 diff --git a/examples/declarative/dial/DialLibrary/Dial.qml b/examples/declarative/dial/DialLibrary/Dial.qml index f53b25e..1a163a8 100644 --- a/examples/declarative/dial/DialLibrary/Dial.qml +++ b/examples/declarative/dial/DialLibrary/Dial.qml @@ -26,8 +26,8 @@ Item { id: NeedleRotation origin.x: 7; origin.y: 65 angle: -130 - angle: Follow { -id: MyFollow + angle: SpringFollow { + id: MyFollow spring: 1.4 damping: .15 source: Math.min(Math.max(-130, Root.value*2.2 - 130), 133) diff --git a/examples/declarative/follow/follow.qml b/examples/declarative/follow/follow.qml index 37dc2e8..1f585e2 100644 --- a/examples/declarative/follow/follow.qml +++ b/examples/declarative/follow/follow.qml @@ -26,7 +26,7 @@ Rectangle { color: "#ff0000" x: Rect.width; width: Rect.width; height: 20 y: 200 - y: Follow { source: Rect.y; velocity: 200 } + y: SpringFollow { source: Rect.y; velocity: 200 } } Text { x: Rect.width; y: 220; text: "Velocity" } @@ -35,13 +35,13 @@ Rectangle { color: "#ff0000" x: Rect.width * 2; width: Rect.width/2; height: 20 y: 200 - y: Follow { source: Rect.y; spring: 1.0; damping: 0.2 } + y: SpringFollow { source: Rect.y; spring: 1.0; damping: 0.2 } } Rectangle { color: "#880000" x: Rect.width * 2.5; width: Rect.width/2; height: 20 y: 200 - y: Follow { source: Rect.y; spring: 1.0; damping: 0.2; mass: 3.0 } // "heavier" object + y: SpringFollow { source: Rect.y; spring: 1.0; damping: 0.2; mass: 3.0 } // "heavier" object } Text { x: Rect.width * 2; y: 220; text: "Spring" } @@ -54,8 +54,8 @@ Rectangle { width: 20; height: 20 radius: 10 color: "#0000ff" - x: Follow { id: "F1"; source: Mouse.mouseX-10; spring: 1.0; damping: 0.05; epsilon: 0.25 } - y: Follow { id: "F2"; source: Mouse.mouseY-10; spring: 1.0; damping: 0.05; epsilon: 0.25 } + x: SpringFollow { id: "F1"; source: Mouse.mouseX-10; spring: 1.0; damping: 0.05; epsilon: 0.25 } + y: SpringFollow { id: "F2"; source: Mouse.mouseY-10; spring: 1.0; damping: 0.05; epsilon: 0.25 } states: [ State { name: "following" diff --git a/examples/declarative/follow/pong.qml b/examples/declarative/follow/pong.qml index 0314bb8..b51c0d0 100644 --- a/examples/declarative/follow/pong.qml +++ b/examples/declarative/follow/pong.qml @@ -25,7 +25,7 @@ Rectangle { } // Make y follow the target y coordinate, with a velocity of 200 - y: Follow { source: Ball.targetY; velocity: 200 } + y: SpringFollow { source: Ball.targetY; velocity: 200 } // Detect the ball hitting the top or bottom of the view and bounce it onYChanged: { @@ -42,7 +42,7 @@ Rectangle { id: LeftBat color: "#00ee00" x: 2; width: 20; height: 90 - y: Follow { + y: SpringFollow { source: Ball.y-45; velocity: 300 enabled: Ball.direction == 'left' } @@ -51,7 +51,7 @@ Rectangle { id: RightBat color: "#00ee00" x: Page.width-22; width: 20; height: 90 - y: Follow { + y: SpringFollow { source: Ball.y-45; velocity: 300 enabled: Ball.direction == 'right' } diff --git a/examples/declarative/listview/highlight.qml b/examples/declarative/listview/highlight.qml index 2bf3a9f..e707ac0 100644 --- a/examples/declarative/listview/highlight.qml +++ b/examples/declarative/listview/highlight.qml @@ -44,7 +44,7 @@ Rectangle { id: PetHighlight Rectangle { width: 200; height: 50; color: "#FFFF88" - y: Follow { source: List1.current.y; spring: 3; damping: 0.1 } + y: SpringFollow { source: List1.current.y; spring: 3; damping: 0.1 } } } ListView { diff --git a/examples/declarative/snow/snow.qml b/examples/declarative/snow/snow.qml index b6781c3..2241c3f 100644 --- a/examples/declarative/snow/snow.qml +++ b/examples/declarative/snow/snow.qml @@ -30,15 +30,15 @@ Rectangle { property bool slowDeform: true property real deform: 0 - deform: Follow { + deform: SpringFollow { id: "DeformFollow"; source: MyLayout.targetDeform; velocity: MyLayout.slowDeform?0.1:2 onSyncChanged: if(inSync) { MyLayout.slowDeform = true; MyLayout.targetDeform = 0; } } ImageBatch { offset: 0; ref: ImagePanel } - x: Follow { source: MyLayout.targetX; velocity: 1000 } - y: Follow { source: -(selectedY + imageHeight / 2); velocity: 500 } + x: SpringFollow { source: MyLayout.targetX; velocity: 1000 } + y: SpringFollow { source: -(selectedY + imageHeight / 2); velocity: 500 } } transform: Rotation { diff --git a/examples/declarative/velocity/Day.qml b/examples/declarative/velocity/Day.qml index 06d0bd4..4001a3e 100644 --- a/examples/declarative/velocity/Day.qml +++ b/examples/declarative/velocity/Day.qml @@ -31,7 +31,7 @@ Rectangle { x: Math.random() * 200 + 100 y: Math.random() * 300 + 50 id: StickyPage - rotation: Follow { + rotation: SpringFollow { source: -Flick.horizontalVelocity / 100 spring: 2.0 damping: 0.1 diff --git a/src/declarative/QmlChanges.txt b/src/declarative/QmlChanges.txt index 87873f2..9043421 100644 --- a/src/declarative/QmlChanges.txt +++ b/src/declarative/QmlChanges.txt @@ -29,6 +29,7 @@ SetPropertyAction -> PropertyAction RunScriptAction -> ScriptAction ParentChangeAction -> ParentAction VisualModel -> VisualDataModel +Follow -> SpringFollow Renamed properties: Item: contents -> childrenRect diff --git a/src/declarative/fx/qfxgridview.cpp b/src/declarative/fx/qfxgridview.cpp index cccd7a6..dfb04ad 100644 --- a/src/declarative/fx/qfxgridview.cpp +++ b/src/declarative/fx/qfxgridview.cpp @@ -41,7 +41,7 @@ #include "qfxvisualitemmodel.h" #include "qlistmodelinterface.h" -#include "qmlfollow.h" +#include "qmleasefollow.h" #include "private/qfxflickable_p.h" #include "qfxgridview.h" @@ -313,8 +313,8 @@ public: enum MovementReason { Other, Key, Mouse }; MovementReason moveReason; int buffer; - QmlFollow *highlightXAnimator; - QmlFollow *highlightYAnimator; + QmlEaseFollow *highlightXAnimator; + QmlEaseFollow *highlightYAnimator; int ownModel : 1; int wrap : 1; @@ -591,15 +591,13 @@ void QFxGridViewPrivate::createHighlight() if (item) { item->setParent(q->viewport()); highlight = new FxGridItem(item, q); - highlightXAnimator = new QmlFollow(q); + highlightXAnimator = new QmlEaseFollow(q); highlightXAnimator->setTarget(QmlMetaProperty(highlight->item, QLatin1String("x"))); - highlightXAnimator->setSpring(3); - highlightXAnimator->setDamping(0.3); + highlightXAnimator->setVelocity(400); highlightXAnimator->setEnabled(autoHighlight); - highlightYAnimator = new QmlFollow(q); + highlightYAnimator = new QmlEaseFollow(q); highlightYAnimator->setTarget(QmlMetaProperty(highlight->item, QLatin1String("y"))); - highlightYAnimator->setSpring(3); - highlightYAnimator->setDamping(0.3); + highlightYAnimator->setVelocity(400); highlightYAnimator->setEnabled(autoHighlight); } else { delete highlightContext; diff --git a/src/declarative/fx/qfxlistview.cpp b/src/declarative/fx/qfxlistview.cpp index 6c0a83e..49de016 100644 --- a/src/declarative/fx/qfxlistview.cpp +++ b/src/declarative/fx/qfxlistview.cpp @@ -40,7 +40,7 @@ ****************************************************************************/ #include "private/qfxflickable_p.h" -#include "qmlfollow.h" +#include "qmleasefollow.h" #include "qlistmodelinterface.h" #include "qfxvisualitemmodel.h" #include "qfxlistview.h" @@ -381,8 +381,8 @@ public: enum MovementReason { Other, Key, Mouse }; MovementReason moveReason; int buffer; - QmlFollow *highlightPosAnimator; - QmlFollow *highlightSizeAnimator; + QmlEaseFollow *highlightPosAnimator; + QmlEaseFollow *highlightSizeAnimator; QString sectionExpression; QString currentSection; int spacing; @@ -660,15 +660,18 @@ void QFxListViewPrivate::createHighlight() } if (item) { highlight = new FxListItem(item, q); + if (orient == Qt::Vertical) + highlight->item->setHeight(currentItem->item->height()); + else + highlight->item->setWidth(currentItem->item->width()); const QLatin1String posProp(orient == Qt::Vertical ? "y" : "x"); - highlightPosAnimator = new QmlFollow(q); + highlightPosAnimator = new QmlEaseFollow(q); highlightPosAnimator->setTarget(QmlMetaProperty(highlight->item, posProp)); - highlightPosAnimator->setEpsilon(0.25); - highlightPosAnimator->setSpring(2.5); - highlightPosAnimator->setDamping(0.35); + highlightPosAnimator->setVelocity(400); highlightPosAnimator->setEnabled(autoHighlight); const QLatin1String sizeProp(orient == Qt::Vertical ? "height" : "width"); - highlightSizeAnimator = new QmlFollow(q); + highlightSizeAnimator = new QmlEaseFollow(q); + highlightSizeAnimator->setVelocity(400); highlightSizeAnimator->setTarget(QmlMetaProperty(highlight->item, sizeProp)); highlightSizeAnimator->setEnabled(autoHighlight); } @@ -909,6 +912,7 @@ void QFxListView::setModel(const QVariant &model) if (d->model) { disconnect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int))); disconnect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int))); + disconnect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int))); disconnect(d->model, SIGNAL(createdItem(int, QFxItem*)), this, SLOT(createdItem(int,QFxItem*))); disconnect(d->model, SIGNAL(destroyingItem(QFxItem*)), this, SLOT(destroyingItem(QFxItem*))); } @@ -937,6 +941,7 @@ void QFxListView::setModel(const QVariant &model) d->updateCurrent(d->currentIndex); connect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int))); connect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int))); + connect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int))); connect(d->model, SIGNAL(createdItem(int, QFxItem*)), this, SLOT(createdItem(int,QFxItem*))); connect(d->model, SIGNAL(destroyingItem(QFxItem*)), this, SLOT(destroyingItem(QFxItem*))); refill(); @@ -1635,6 +1640,37 @@ void QFxListView::destroyRemoved() d->layout(); } +void QFxListView::itemsMoved(int from, int to, int count) +{ + qWarning() << "ListView does not support moving in models"; + + Q_D(QFxListView); + int fromCount = count; + int toCount = count; + bool fromVisible = d->mapRangeFromModel(from, fromCount); + bool toVisible = d->mapRangeFromModel(to, toCount); + + if (!fromVisible && !toVisible) { + // The items are outside the visible range. + if (d->visibleItems.count()) + d->visibleIndex = -1; + for (int i = 0; i < d->visibleItems.count(); ++i) { + FxListItem *listItem = d->visibleItems.at(i); + if (listItem->index != -1) { + listItem->index = d->model->indexOf(listItem->item, this); + if (d->visibleIndex < 0) + d->visibleIndex = listItem->index; + } + } + if (d->currentItem) { + d->currentItem->index = d->model->indexOf(d->currentItem->item, this); + d->currentIndex = d->currentItem->index; + } + return; + } + +} + void QFxListView::createdItem(int index, QFxItem *item) { Q_D(QFxListView); diff --git a/src/declarative/fx/qfxlistview.h b/src/declarative/fx/qfxlistview.h index dc0b039..829e202 100644 --- a/src/declarative/fx/qfxlistview.h +++ b/src/declarative/fx/qfxlistview.h @@ -155,6 +155,7 @@ private Q_SLOTS: void itemResized(); void itemsInserted(int index, int count); void itemsRemoved(int index, int count); + void itemsMoved(int from, int to, int count); void destroyRemoved(); void createdItem(int index, QFxItem *item); void destroyingItem(QFxItem *item); diff --git a/src/declarative/util/qmleasefollow.cpp b/src/declarative/util/qmleasefollow.cpp index 83dbde7..b58ad14 100644 --- a/src/declarative/util/qmleasefollow.cpp +++ b/src/declarative/util/qmleasefollow.cpp @@ -56,7 +56,7 @@ public: QmlEaseFollowPrivate() : source(0), velocity(200), duration(-1), reversingMode(QmlEaseFollow::Eased), initialVelocity(0), - initialValue(0), invert(false), trackVelocity(0), clockOffset(0), + initialValue(0), invert(false), enabled(true), trackVelocity(0), clockOffset(0), lastTick(0), clock(this) {} @@ -68,6 +68,7 @@ public: qreal initialVelocity; qreal initialValue; bool invert; + bool enabled; qreal trackVelocity; @@ -267,7 +268,7 @@ qreal QmlEaseFollow::sourceValue() const /*! \qmlproperty enumeration EaseFollow::reversingMode - Sets how the EaseFollow behaves if an animation diration is reversed. + Sets how the EaseFollow behaves if an animation direction is reversed. If reversing mode is \c Eased, the animation will smoothly decelerate, and then reverse direction. If the reversing mode is \c Immediate, the @@ -289,6 +290,9 @@ void QmlEaseFollow::setReversingMode(ReversingMode m) void QmlEaseFollowPrivate::restart() { + if (!enabled) + return; + initialValue = target.read().toReal(); if (source == initialValue) { @@ -382,6 +386,26 @@ void QmlEaseFollow::setVelocity(qreal v) d->restart(); } +/*! + \qmlproperty bool EaseFollow::enabled + This property holds whether the target will track the source. +*/ +bool QmlEaseFollow::enabled() const +{ + Q_D(const QmlEaseFollow); + return d->enabled; +} + +void QmlEaseFollow::setEnabled(bool enabled) +{ + Q_D(QmlEaseFollow); + d->enabled = enabled; + if (enabled) + d->restart(); + else + d->clockStop(); +} + void QmlEaseFollow::setTarget(const QmlMetaProperty &t) { Q_D(QmlEaseFollow); diff --git a/src/declarative/util/qmleasefollow.h b/src/declarative/util/qmleasefollow.h index adcb647..8e8c59d 100644 --- a/src/declarative/util/qmleasefollow.h +++ b/src/declarative/util/qmleasefollow.h @@ -66,6 +66,7 @@ class Q_DECLARATIVE_EXPORT QmlEaseFollow : public QObject, Q_PROPERTY(qreal velocity READ velocity WRITE setVelocity) Q_PROPERTY(qreal duration READ duration WRITE setDuration) Q_PROPERTY(ReversingMode reversingMode READ reversingMode WRITE setReversingMode) + Q_PROPERTY(bool enabled READ enabled WRITE setEnabled) public: enum ReversingMode { Eased, Immediate, Sync }; @@ -85,6 +86,9 @@ public: qreal duration() const; void setDuration(qreal); + bool enabled() const; + void setEnabled(bool enabled); + virtual void setTarget(const QmlMetaProperty &); }; diff --git a/src/declarative/util/qmlfollow.cpp b/src/declarative/util/qmlfollow.cpp deleted file mode 100644 index fe5303f..0000000 --- a/src/declarative/util/qmlfollow.cpp +++ /dev/null @@ -1,456 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (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 either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** 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.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include -#include -#include "private/qobject_p.h" -#include "qmlfollow.h" -#include "private/qmlanimation_p.h" - -QT_BEGIN_NAMESPACE - -QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Follow,QmlFollow) - -class QmlFollowPrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QmlFollow) -public: - QmlFollowPrivate() - : sourceValue(0), maxVelocity(0), lastTime(0) - , mass(1.0), useMass(false), spring(0.), damping(0.), velocity(0), epsilon(0.01) - , modulus(0.0), haveModulus(false), enabled(true), mode(Track), clock(this) {} - - QmlMetaProperty property; - qreal currentValue; - qreal sourceValue; - qreal maxVelocity; - qreal velocityms; - int lastTime; - qreal mass; - bool useMass; - qreal spring; - qreal damping; - qreal velocity; - qreal epsilon; - qreal modulus; - bool haveModulus; - bool enabled; - - enum Mode { - Track, - Velocity, - Spring - }; - Mode mode; - - void tick(int); - void updateMode(); - void start(); - void stop(); - - QTickAnimationProxy clock; -}; - -void QmlFollowPrivate::tick(int time) -{ - Q_Q(QmlFollow); - - int elapsed = time - lastTime; - if (!elapsed) - return; - qreal srcVal = sourceValue; - if (haveModulus) { - currentValue = fmod(currentValue, modulus); - srcVal = fmod(srcVal, modulus); - } - if (mode == Spring) { - if (elapsed < 16) // capped at 62fps. - return; - // Real men solve the spring DEs using RK4. - // We'll do something much simpler which gives a result that looks fine. - int count = elapsed / 16; - for (int i = 0; i < count; ++i) { - qreal diff = srcVal - currentValue; - if (haveModulus && qAbs(diff) > modulus / 2) { - if (diff < 0) - diff += modulus; - else - diff -= modulus; - } - if (useMass) - velocity = velocity + (spring * diff - damping * velocity) / mass; - else - velocity = velocity + spring * diff - damping * velocity; - if (maxVelocity > 0.) { - // limit velocity - if (velocity > maxVelocity) - velocity = maxVelocity; - else if (velocity < -maxVelocity) - velocity = -maxVelocity; - } - currentValue += velocity * 16.0 / 1000.0; - if (haveModulus) { - currentValue = fmod(currentValue, modulus); - if (currentValue < 0.0) - currentValue += modulus; - } - } - if (qAbs(velocity) < epsilon && qAbs(srcVal - currentValue) < epsilon) { - velocity = 0.0; - currentValue = srcVal; - clock.stop(); - } - lastTime = time - (elapsed - count * 16); - } else { - qreal moveBy = elapsed * velocityms; - qreal diff = srcVal - currentValue; - if (haveModulus && qAbs(diff) > modulus / 2) { - if (diff < 0) - diff += modulus; - else - diff -= modulus; - } - if (diff > 0) { - currentValue += moveBy; - if (haveModulus) - currentValue = fmod(currentValue, modulus); - if (currentValue > sourceValue) { - currentValue = sourceValue; - clock.stop(); - } - } else { - currentValue -= moveBy; - if (haveModulus && currentValue < 0.0) - currentValue = fmod(currentValue, modulus) + modulus; - if (currentValue < sourceValue) { - currentValue = sourceValue; - clock.stop(); - } - } - lastTime = time; - } - property.write(currentValue); - emit q->valueChanged(currentValue); - if (clock.state() != QAbstractAnimation::Running) - emit q->syncChanged(); -} - -void QmlFollowPrivate::updateMode() -{ - if (spring == 0. && maxVelocity == 0.) - mode = Track; - else if (spring > 0.) - mode = Spring; - else - mode = Velocity; -} - -void QmlFollowPrivate::start() -{ - if (!enabled) - return; - - Q_Q(QmlFollow); - if (mode == QmlFollowPrivate::Track) { - currentValue = sourceValue; - property.write(currentValue); - } else if (sourceValue != currentValue && clock.state() != QAbstractAnimation::Running) { - lastTime = 0; - currentValue = property.read().toDouble(); - clock.start(); // infinity?? - emit q->syncChanged(); - } -} - -void QmlFollowPrivate::stop() -{ - clock.stop(); -} - -/*! - \qmlclass Follow QmlFollow - \brief The Follow element allows a property to track a value. - - In example below, Rect2 will follow Rect1 moving with a velocity of up to 200: - \code - Rectangle { - id: Rect1 - width: 20; height: 20 - color: "#00ff00" - y: 200 //initial value - y: SequentialAnimation { - running: true - repeat: true - NumberAnimation { - to: 200 - easing: "easeOutBounce(amplitude:100)" - duration: 2000 - } - PauseAnimation { duration: 1000 } - } - } - Rectangle { - id: Rect2 - x: Rect1.width - width: 20; height: 20 - color: "#ff0000" - y: Follow { source: Rect1.y; velocity: 200 } - } - \endcode -*/ - -QmlFollow::QmlFollow(QObject *parent) -: QObject(*(new QmlFollowPrivate),parent) -{ -} - -QmlFollow::~QmlFollow() -{ -} - -void QmlFollow::setTarget(const QmlMetaProperty &property) -{ - Q_D(QmlFollow); - d->property = property; - d->currentValue = property.read().toDouble(); -} - -qreal QmlFollow::sourceValue() const -{ - Q_D(const QmlFollow); - return d->sourceValue; -} - -/*! - \qmlproperty qreal Follow::source - This property holds the source value which will be tracked. - - Bind to a property in order to track its changes. -*/ - -void QmlFollow::setSourceValue(qreal value) -{ - Q_D(QmlFollow); - if (d->sourceValue != value) { - d->sourceValue = value; - d->start(); - } -} - -/*! - \qmlproperty qreal Follow::velocity - This property holds the maximum velocity allowed when tracking the source. -*/ - -qreal QmlFollow::velocity() const -{ - Q_D(const QmlFollow); - return d->maxVelocity; -} - -void QmlFollow::setVelocity(qreal velocity) -{ - Q_D(QmlFollow); - d->maxVelocity = velocity; - d->velocityms = velocity / 1000.0; - d->updateMode(); -} - -/*! - \qmlproperty qreal Follow::spring - This property holds the spring constant - - The spring constant describes how strongly the target is pulled towards the - source. Setting spring to 0 turns off spring tracking. Useful values 0 - 5.0 - - When a spring constant is set and the velocity property is greater than 0, - velocity limits the maximum speed. -*/ -qreal QmlFollow::spring() const -{ - Q_D(const QmlFollow); - return d->spring; -} - -void QmlFollow::setSpring(qreal spring) -{ - Q_D(QmlFollow); - d->spring = spring; - d->updateMode(); -} - -/*! - \qmlproperty qreal Follow::damping - This property holds the spring damping constant - - The damping constant describes how quickly a sprung follower comes to rest. - Useful range is 0 - 1.0 -*/ -qreal QmlFollow::damping() const -{ - Q_D(const QmlFollow); - return d->damping; -} - -void QmlFollow::setDamping(qreal damping) -{ - Q_D(QmlFollow); - if (damping > 1.) - damping = 1.; - - d->damping = damping; -} - - -/*! - \qmlproperty qreal Follow::epsilon - This property holds the spring epsilon - - The epsilon is the rate and amount of change in the value which is close enough - to 0 to be considered equal to zero. This will depend on the usage of the value. - For pixel positions, 0.25 would suffice. For scale, 0.005 will suffice. - - The default is 0.01. Tuning this value can provide small performance improvements. -*/ -qreal QmlFollow::epsilon() const -{ - Q_D(const QmlFollow); - return d->epsilon; -} - -void QmlFollow::setEpsilon(qreal epsilon) -{ - Q_D(QmlFollow); - d->epsilon = epsilon; -} - -/*! - \qmlproperty qreal Follow::modulus - This property holds the modulus value. - - Setting a \a modulus forces the target value to "wrap around" at the modulus. - For example, setting the modulus to 360 will cause a value of 370 to wrap around to 10. -*/ -qreal QmlFollow::modulus() const -{ - Q_D(const QmlFollow); - return d->modulus; -} - -void QmlFollow::setModulus(qreal modulus) -{ - Q_D(QmlFollow); - if (d->modulus != modulus) { - d->haveModulus = modulus != 0.0; - d->modulus = modulus; - emit modulusChanged(); - } -} - -/*! - \qmlproperty qreal Follow::mass - This property holds the "mass" of the property being moved. - - mass is 1.0 by default. Setting a different mass changes the dynamics of - a \l spring follow. -*/ -qreal QmlFollow::mass() const -{ - Q_D(const QmlFollow); - return d->mass; -} - -void QmlFollow::setMass(qreal mass) -{ - Q_D(QmlFollow); - if (d->mass != mass && mass > 0.0) { - d->useMass = mass != 1.0; - d->mass = mass; - emit massChanged(); - } -} - -/*! - \qmlproperty qreal Follow::value - The current value. -*/ - -/*! - \qmlproperty bool Follow::enabled - This property holds whether the target will track the source. -*/ -bool QmlFollow::enabled() const -{ - Q_D(const QmlFollow); - return d->enabled; -} - -void QmlFollow::setEnabled(bool enabled) -{ - Q_D(QmlFollow); - d->enabled = enabled; - if (enabled) - d->start(); - else - d->stop(); -} - -/*! - \qmlproperty bool Follow::inSync - This property is true when target is equal to the source; otherwise - false. If inSync is true the target is not being animated. - - If \l enabled is false then inSync will also be false. -*/ -bool QmlFollow::inSync() const -{ - Q_D(const QmlFollow); - return d->enabled && d->clock.state() != QAbstractAnimation::Running; -} - -qreal QmlFollow::value() const -{ - Q_D(const QmlFollow); - return d->currentValue; -} - -QT_END_NAMESPACE diff --git a/src/declarative/util/qmlfollow.h b/src/declarative/util/qmlfollow.h deleted file mode 100644 index ff34d08..0000000 --- a/src/declarative/util/qmlfollow.h +++ /dev/null @@ -1,113 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (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 either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** 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.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QMLFOLLOW_H -#define QMLFOLLOW_H - -#include -#include - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Declarative) - -class QmlFollowPrivate; -class Q_DECLARATIVE_EXPORT QmlFollow : public QObject, - public QmlPropertyValueSource -{ - Q_OBJECT - Q_DECLARE_PRIVATE(QmlFollow) - Q_INTERFACES(QmlPropertyValueSource) - - Q_PROPERTY(qreal source READ sourceValue WRITE setSourceValue) - Q_PROPERTY(qreal velocity READ velocity WRITE setVelocity) - Q_PROPERTY(qreal spring READ spring WRITE setSpring) - Q_PROPERTY(qreal damping READ damping WRITE setDamping) - Q_PROPERTY(qreal epsilon READ epsilon WRITE setEpsilon) - Q_PROPERTY(qreal modulus READ modulus WRITE setModulus) - Q_PROPERTY(bool enabled READ enabled WRITE setEnabled) - Q_PROPERTY(qreal value READ value NOTIFY valueChanged) - Q_PROPERTY(qreal modulus READ modulus WRITE setModulus NOTIFY modulusChanged) - Q_PROPERTY(qreal mass READ mass WRITE setMass NOTIFY massChanged) - Q_PROPERTY(bool inSync READ inSync NOTIFY syncChanged) - -public: - QmlFollow(QObject *parent=0); - ~QmlFollow(); - - virtual void setTarget(const QmlMetaProperty &); - - qreal sourceValue() const; - void setSourceValue(qreal value); - qreal velocity() const; - void setVelocity(qreal velocity); - qreal spring() const; - void setSpring(qreal spring); - qreal damping() const; - void setDamping(qreal damping); - qreal epsilon() const; - void setEpsilon(qreal epsilon); - qreal mass() const; - void setMass(qreal modulus); - qreal modulus() const; - void setModulus(qreal modulus); - bool enabled() const; - void setEnabled(bool enabled); - bool inSync() const; - - qreal value() const; - -Q_SIGNALS: - void valueChanged(qreal); - void modulusChanged(); - void massChanged(); - void syncChanged(); -}; - -QT_END_NAMESPACE - -QML_DECLARE_TYPE(QmlFollow) - -QT_END_HEADER - -#endif // QFXFOLLOW_H diff --git a/src/declarative/util/qmlspringfollow.cpp b/src/declarative/util/qmlspringfollow.cpp new file mode 100644 index 0000000..8c902aa --- /dev/null +++ b/src/declarative/util/qmlspringfollow.cpp @@ -0,0 +1,456 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include "private/qobject_p.h" +#include "qmlspringfollow.h" +#include "private/qmlanimation_p.h" + +QT_BEGIN_NAMESPACE + +QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,SpringFollow,QmlSpringFollow) + +class QmlSpringFollowPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QmlSpringFollow) +public: + QmlSpringFollowPrivate() + : sourceValue(0), maxVelocity(0), lastTime(0) + , mass(1.0), useMass(false), spring(0.), damping(0.), velocity(0), epsilon(0.01) + , modulus(0.0), haveModulus(false), enabled(true), mode(Track), clock(this) {} + + QmlMetaProperty property; + qreal currentValue; + qreal sourceValue; + qreal maxVelocity; + qreal velocityms; + int lastTime; + qreal mass; + bool useMass; + qreal spring; + qreal damping; + qreal velocity; + qreal epsilon; + qreal modulus; + bool haveModulus; + bool enabled; + + enum Mode { + Track, + Velocity, + Spring + }; + Mode mode; + + void tick(int); + void updateMode(); + void start(); + void stop(); + + QTickAnimationProxy clock; +}; + +void QmlSpringFollowPrivate::tick(int time) +{ + Q_Q(QmlSpringFollow); + + int elapsed = time - lastTime; + if (!elapsed) + return; + qreal srcVal = sourceValue; + if (haveModulus) { + currentValue = fmod(currentValue, modulus); + srcVal = fmod(srcVal, modulus); + } + if (mode == Spring) { + if (elapsed < 16) // capped at 62fps. + return; + // Real men solve the spring DEs using RK4. + // We'll do something much simpler which gives a result that looks fine. + int count = elapsed / 16; + for (int i = 0; i < count; ++i) { + qreal diff = srcVal - currentValue; + if (haveModulus && qAbs(diff) > modulus / 2) { + if (diff < 0) + diff += modulus; + else + diff -= modulus; + } + if (useMass) + velocity = velocity + (spring * diff - damping * velocity) / mass; + else + velocity = velocity + spring * diff - damping * velocity; + if (maxVelocity > 0.) { + // limit velocity + if (velocity > maxVelocity) + velocity = maxVelocity; + else if (velocity < -maxVelocity) + velocity = -maxVelocity; + } + currentValue += velocity * 16.0 / 1000.0; + if (haveModulus) { + currentValue = fmod(currentValue, modulus); + if (currentValue < 0.0) + currentValue += modulus; + } + } + if (qAbs(velocity) < epsilon && qAbs(srcVal - currentValue) < epsilon) { + velocity = 0.0; + currentValue = srcVal; + clock.stop(); + } + lastTime = time - (elapsed - count * 16); + } else { + qreal moveBy = elapsed * velocityms; + qreal diff = srcVal - currentValue; + if (haveModulus && qAbs(diff) > modulus / 2) { + if (diff < 0) + diff += modulus; + else + diff -= modulus; + } + if (diff > 0) { + currentValue += moveBy; + if (haveModulus) + currentValue = fmod(currentValue, modulus); + if (currentValue > sourceValue) { + currentValue = sourceValue; + clock.stop(); + } + } else { + currentValue -= moveBy; + if (haveModulus && currentValue < 0.0) + currentValue = fmod(currentValue, modulus) + modulus; + if (currentValue < sourceValue) { + currentValue = sourceValue; + clock.stop(); + } + } + lastTime = time; + } + property.write(currentValue); + emit q->valueChanged(currentValue); + if (clock.state() != QAbstractAnimation::Running) + emit q->syncChanged(); +} + +void QmlSpringFollowPrivate::updateMode() +{ + if (spring == 0. && maxVelocity == 0.) + mode = Track; + else if (spring > 0.) + mode = Spring; + else + mode = Velocity; +} + +void QmlSpringFollowPrivate::start() +{ + if (!enabled) + return; + + Q_Q(QmlSpringFollow); + if (mode == QmlSpringFollowPrivate::Track) { + currentValue = sourceValue; + property.write(currentValue); + } else if (sourceValue != currentValue && clock.state() != QAbstractAnimation::Running) { + lastTime = 0; + currentValue = property.read().toDouble(); + clock.start(); // infinity?? + emit q->syncChanged(); + } +} + +void QmlSpringFollowPrivate::stop() +{ + clock.stop(); +} + +/*! + \qmlclass SpringFollow QmlSpringFollow + \brief The SpringFollow element allows a property to track a value. + + In example below, Rect2 will follow Rect1 moving with a velocity of up to 200: + \code + Rectangle { + id: Rect1 + width: 20; height: 20 + color: "#00ff00" + y: 200 //initial value + y: SequentialAnimation { + running: true + repeat: true + NumberAnimation { + to: 200 + easing: "easeOutBounce(amplitude:100)" + duration: 2000 + } + PauseAnimation { duration: 1000 } + } + } + Rectangle { + id: Rect2 + x: Rect1.width + width: 20; height: 20 + color: "#ff0000" + y: SpringFollow { source: Rect1.y; velocity: 200 } + } + \endcode +*/ + +QmlSpringFollow::QmlSpringFollow(QObject *parent) +: QObject(*(new QmlSpringFollowPrivate),parent) +{ +} + +QmlSpringFollow::~QmlSpringFollow() +{ +} + +void QmlSpringFollow::setTarget(const QmlMetaProperty &property) +{ + Q_D(QmlSpringFollow); + d->property = property; + d->currentValue = property.read().toDouble(); +} + +qreal QmlSpringFollow::sourceValue() const +{ + Q_D(const QmlSpringFollow); + return d->sourceValue; +} + +/*! + \qmlproperty qreal SpringFollow::source + This property holds the source value which will be tracked. + + Bind to a property in order to track its changes. +*/ + +void QmlSpringFollow::setSourceValue(qreal value) +{ + Q_D(QmlSpringFollow); + if (d->sourceValue != value) { + d->sourceValue = value; + d->start(); + } +} + +/*! + \qmlproperty qreal SpringFollow::velocity + This property holds the maximum velocity allowed when tracking the source. +*/ + +qreal QmlSpringFollow::velocity() const +{ + Q_D(const QmlSpringFollow); + return d->maxVelocity; +} + +void QmlSpringFollow::setVelocity(qreal velocity) +{ + Q_D(QmlSpringFollow); + d->maxVelocity = velocity; + d->velocityms = velocity / 1000.0; + d->updateMode(); +} + +/*! + \qmlproperty qreal SpringFollow::spring + This property holds the spring constant + + The spring constant describes how strongly the target is pulled towards the + source. Setting spring to 0 turns off spring tracking. Useful values 0 - 5.0 + + When a spring constant is set and the velocity property is greater than 0, + velocity limits the maximum speed. +*/ +qreal QmlSpringFollow::spring() const +{ + Q_D(const QmlSpringFollow); + return d->spring; +} + +void QmlSpringFollow::setSpring(qreal spring) +{ + Q_D(QmlSpringFollow); + d->spring = spring; + d->updateMode(); +} + +/*! + \qmlproperty qreal SpringFollow::damping + This property holds the spring damping constant + + The damping constant describes how quickly a sprung follower comes to rest. + Useful range is 0 - 1.0 +*/ +qreal QmlSpringFollow::damping() const +{ + Q_D(const QmlSpringFollow); + return d->damping; +} + +void QmlSpringFollow::setDamping(qreal damping) +{ + Q_D(QmlSpringFollow); + if (damping > 1.) + damping = 1.; + + d->damping = damping; +} + + +/*! + \qmlproperty qreal SpringFollow::epsilon + This property holds the spring epsilon + + The epsilon is the rate and amount of change in the value which is close enough + to 0 to be considered equal to zero. This will depend on the usage of the value. + For pixel positions, 0.25 would suffice. For scale, 0.005 will suffice. + + The default is 0.01. Tuning this value can provide small performance improvements. +*/ +qreal QmlSpringFollow::epsilon() const +{ + Q_D(const QmlSpringFollow); + return d->epsilon; +} + +void QmlSpringFollow::setEpsilon(qreal epsilon) +{ + Q_D(QmlSpringFollow); + d->epsilon = epsilon; +} + +/*! + \qmlproperty qreal SpringFollow::modulus + This property holds the modulus value. + + Setting a \a modulus forces the target value to "wrap around" at the modulus. + For example, setting the modulus to 360 will cause a value of 370 to wrap around to 10. +*/ +qreal QmlSpringFollow::modulus() const +{ + Q_D(const QmlSpringFollow); + return d->modulus; +} + +void QmlSpringFollow::setModulus(qreal modulus) +{ + Q_D(QmlSpringFollow); + if (d->modulus != modulus) { + d->haveModulus = modulus != 0.0; + d->modulus = modulus; + emit modulusChanged(); + } +} + +/*! + \qmlproperty qreal SpringFollow::mass + This property holds the "mass" of the property being moved. + + mass is 1.0 by default. Setting a different mass changes the dynamics of + a \l spring follow. +*/ +qreal QmlSpringFollow::mass() const +{ + Q_D(const QmlSpringFollow); + return d->mass; +} + +void QmlSpringFollow::setMass(qreal mass) +{ + Q_D(QmlSpringFollow); + if (d->mass != mass && mass > 0.0) { + d->useMass = mass != 1.0; + d->mass = mass; + emit massChanged(); + } +} + +/*! + \qmlproperty qreal SpringFollow::value + The current value. +*/ + +/*! + \qmlproperty bool SpringFollow::enabled + This property holds whether the target will track the source. +*/ +bool QmlSpringFollow::enabled() const +{ + Q_D(const QmlSpringFollow); + return d->enabled; +} + +void QmlSpringFollow::setEnabled(bool enabled) +{ + Q_D(QmlSpringFollow); + d->enabled = enabled; + if (enabled) + d->start(); + else + d->stop(); +} + +/*! + \qmlproperty bool SpringFollow::inSync + This property is true when target is equal to the source; otherwise + false. If inSync is true the target is not being animated. + + If \l enabled is false then inSync will also be false. +*/ +bool QmlSpringFollow::inSync() const +{ + Q_D(const QmlSpringFollow); + return d->enabled && d->clock.state() != QAbstractAnimation::Running; +} + +qreal QmlSpringFollow::value() const +{ + Q_D(const QmlSpringFollow); + return d->currentValue; +} + +QT_END_NAMESPACE diff --git a/src/declarative/util/qmlspringfollow.h b/src/declarative/util/qmlspringfollow.h new file mode 100644 index 0000000..1b77861 --- /dev/null +++ b/src/declarative/util/qmlspringfollow.h @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLFOLLOW_H +#define QMLFOLLOW_H + +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QmlSpringFollowPrivate; +class Q_DECLARATIVE_EXPORT QmlSpringFollow : public QObject, + public QmlPropertyValueSource +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QmlSpringFollow) + Q_INTERFACES(QmlPropertyValueSource) + + Q_PROPERTY(qreal source READ sourceValue WRITE setSourceValue) + Q_PROPERTY(qreal velocity READ velocity WRITE setVelocity) + Q_PROPERTY(qreal spring READ spring WRITE setSpring) + Q_PROPERTY(qreal damping READ damping WRITE setDamping) + Q_PROPERTY(qreal epsilon READ epsilon WRITE setEpsilon) + Q_PROPERTY(qreal modulus READ modulus WRITE setModulus) + Q_PROPERTY(bool enabled READ enabled WRITE setEnabled) + Q_PROPERTY(qreal value READ value NOTIFY valueChanged) + Q_PROPERTY(qreal modulus READ modulus WRITE setModulus NOTIFY modulusChanged) + Q_PROPERTY(qreal mass READ mass WRITE setMass NOTIFY massChanged) + Q_PROPERTY(bool inSync READ inSync NOTIFY syncChanged) + +public: + QmlSpringFollow(QObject *parent=0); + ~QmlSpringFollow(); + + virtual void setTarget(const QmlMetaProperty &); + + qreal sourceValue() const; + void setSourceValue(qreal value); + qreal velocity() const; + void setVelocity(qreal velocity); + qreal spring() const; + void setSpring(qreal spring); + qreal damping() const; + void setDamping(qreal damping); + qreal epsilon() const; + void setEpsilon(qreal epsilon); + qreal mass() const; + void setMass(qreal modulus); + qreal modulus() const; + void setModulus(qreal modulus); + bool enabled() const; + void setEnabled(bool enabled); + bool inSync() const; + + qreal value() const; + +Q_SIGNALS: + void valueChanged(qreal); + void modulusChanged(); + void massChanged(); + void syncChanged(); +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QmlSpringFollow) + +QT_END_HEADER + +#endif // QFXFOLLOW_H diff --git a/src/declarative/util/util.pri b/src/declarative/util/util.pri index a57f69f..442380a 100644 --- a/src/declarative/util/util.pri +++ b/src/declarative/util/util.pri @@ -7,7 +7,7 @@ SOURCES += \ util/qmlscript.cpp \ util/qmlanimation.cpp \ util/qmlsystempalette.cpp \ - util/qmlfollow.cpp \ + util/qmlspringfollow.cpp \ util/qmleasefollow.cpp \ util/qmlstate.cpp\ util/qmltransitionmanager.cpp \ @@ -33,7 +33,7 @@ HEADERS += \ util/qmlanimation.h \ util/qmlanimation_p.h \ util/qmlsystempalette.h \ - util/qmlfollow.h \ + util/qmlspringfollow.h \ util/qmleasefollow.h \ util/qmlstate.h\ util/qmlstateoperations.h \ -- cgit v0.12 From 033f7de03ed83cfa68436660e6354cb94452ee25 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Thu, 10 Sep 2009 14:29:24 +1000 Subject: Best to delete pointer before zeroing it. --- src/declarative/fx/qfxloader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/declarative/fx/qfxloader.cpp b/src/declarative/fx/qfxloader.cpp index e75ce6d..668faa4 100644 --- a/src/declarative/fx/qfxloader.cpp +++ b/src/declarative/fx/qfxloader.cpp @@ -120,8 +120,8 @@ void QFxLoader::setSource(const QUrl &url) delete d->component; d->component = 0; } - d->item = 0; delete d->item; + d->item = 0; d->source = url; if (d->source.isEmpty()) { -- cgit v0.12 From 087f3d86fccb0195e017c6ce8dfca710a94b723b Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Thu, 10 Sep 2009 11:53:57 +0200 Subject: Fix extending examples by inserting the appropriate import. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: owolff Reviewed-by: Thorbjørn Lindeijer --- examples/declarative/extending/adding/example.qml | 1 + examples/declarative/extending/attached/example.qml | 1 + examples/declarative/extending/binding/example.qml | 1 + examples/declarative/extending/coercion/example.qml | 1 + examples/declarative/extending/default/example.qml | 1 + examples/declarative/extending/extended/example.qml | 1 + examples/declarative/extending/grouped/example.qml | 1 + examples/declarative/extending/properties/example.qml | 1 + examples/declarative/extending/signal/example.qml | 1 + examples/declarative/extending/valuesource/example.qml | 1 + 10 files changed, 10 insertions(+) diff --git a/examples/declarative/extending/adding/example.qml b/examples/declarative/extending/adding/example.qml index ba7af7a..b8fee26 100644 --- a/examples/declarative/extending/adding/example.qml +++ b/examples/declarative/extending/adding/example.qml @@ -1,4 +1,5 @@ import Qt 4.6 +import People 1.0 // ![0] Person { diff --git a/examples/declarative/extending/attached/example.qml b/examples/declarative/extending/attached/example.qml index 20233f6..6cf3e39 100644 --- a/examples/declarative/extending/attached/example.qml +++ b/examples/declarative/extending/attached/example.qml @@ -1,4 +1,5 @@ import Qt 4.6 +import People 1.0 BirthdayParty { celebrant: Boy { diff --git a/examples/declarative/extending/binding/example.qml b/examples/declarative/extending/binding/example.qml index cedb8bd..7ab0d62 100644 --- a/examples/declarative/extending/binding/example.qml +++ b/examples/declarative/extending/binding/example.qml @@ -1,4 +1,5 @@ import Qt 4.6 +import People 1.0 // ![0] BirthdayParty { diff --git a/examples/declarative/extending/coercion/example.qml b/examples/declarative/extending/coercion/example.qml index 5090782..ce2c32d 100644 --- a/examples/declarative/extending/coercion/example.qml +++ b/examples/declarative/extending/coercion/example.qml @@ -1,4 +1,5 @@ import Qt 4.6 +import People 1.0 // ![0] BirthdayParty { diff --git a/examples/declarative/extending/default/example.qml b/examples/declarative/extending/default/example.qml index 5fe693a..051a9d2 100644 --- a/examples/declarative/extending/default/example.qml +++ b/examples/declarative/extending/default/example.qml @@ -1,4 +1,5 @@ import Qt 4.6 +import People 1.0 // ![0] BirthdayParty { diff --git a/examples/declarative/extending/extended/example.qml b/examples/declarative/extending/extended/example.qml index a276211..8311c8e 100644 --- a/examples/declarative/extending/extended/example.qml +++ b/examples/declarative/extending/extended/example.qml @@ -1,4 +1,5 @@ import Qt 4.6 +import People 1.0 // ![0] QLineEdit { diff --git a/examples/declarative/extending/grouped/example.qml b/examples/declarative/extending/grouped/example.qml index 1be7abe..622e204 100644 --- a/examples/declarative/extending/grouped/example.qml +++ b/examples/declarative/extending/grouped/example.qml @@ -1,4 +1,5 @@ import Qt 4.6 +import People 1.0 // ![0] BirthdayParty { diff --git a/examples/declarative/extending/properties/example.qml b/examples/declarative/extending/properties/example.qml index 326105a..976baf2 100644 --- a/examples/declarative/extending/properties/example.qml +++ b/examples/declarative/extending/properties/example.qml @@ -1,4 +1,5 @@ import Qt 4.6 +import People 1.0 // ![0] BirthdayParty { diff --git a/examples/declarative/extending/signal/example.qml b/examples/declarative/extending/signal/example.qml index 1cbaab4..dc3a61a 100644 --- a/examples/declarative/extending/signal/example.qml +++ b/examples/declarative/extending/signal/example.qml @@ -1,4 +1,5 @@ import Qt 4.6 +import People 1.0 // ![0] BirthdayParty { diff --git a/examples/declarative/extending/valuesource/example.qml b/examples/declarative/extending/valuesource/example.qml index aba2796..c536061 100644 --- a/examples/declarative/extending/valuesource/example.qml +++ b/examples/declarative/extending/valuesource/example.qml @@ -1,4 +1,5 @@ import Qt 4.6 +import People 1.0 // ![0] BirthdayParty { -- cgit v0.12 From 754c3ac2598a7c2b0f212f8aa3e281d63be6578e Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Thu, 10 Sep 2009 13:10:42 +0200 Subject: Fix QML_DEFINE_EXTENDED_TYPE use in extending/extended example. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Thorbjørn Lindeijer --- examples/declarative/extending/extended/lineedit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/declarative/extending/extended/lineedit.cpp b/examples/declarative/extending/extended/lineedit.cpp index fe4fdc3..f11d22e 100644 --- a/examples/declarative/extending/extended/lineedit.cpp +++ b/examples/declarative/extending/extended/lineedit.cpp @@ -63,4 +63,4 @@ int LineEditExtension::setBottomMargin(int m) } QML_DECLARE_TYPE(QLineEdit); -QML_DEFINE_EXTENDED_TYPE(QLineEdit, QLineEdit, LineEditExtension); +QML_DEFINE_EXTENDED_TYPE(People, 1, 0, 0, QLineEdit, QLineEdit, LineEditExtension); -- cgit v0.12 From 93340b47b14605fb54a6d74f07af8d3c4d6a1777 Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Thu, 10 Sep 2009 13:12:19 +0200 Subject: Remove unused imports from examples for extending. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Thorbjørn Lindeijer --- examples/declarative/extending/adding/example.qml | 1 - examples/declarative/extending/attached/example.qml | 1 - examples/declarative/extending/binding/example.qml | 1 - examples/declarative/extending/coercion/example.qml | 1 - examples/declarative/extending/default/example.qml | 1 - examples/declarative/extending/extended/example.qml | 1 - examples/declarative/extending/grouped/example.qml | 1 - examples/declarative/extending/properties/example.qml | 1 - examples/declarative/extending/signal/example.qml | 1 - examples/declarative/extending/valuesource/example.qml | 1 - 10 files changed, 10 deletions(-) diff --git a/examples/declarative/extending/adding/example.qml b/examples/declarative/extending/adding/example.qml index b8fee26..c608f94 100644 --- a/examples/declarative/extending/adding/example.qml +++ b/examples/declarative/extending/adding/example.qml @@ -1,4 +1,3 @@ -import Qt 4.6 import People 1.0 // ![0] diff --git a/examples/declarative/extending/attached/example.qml b/examples/declarative/extending/attached/example.qml index 6cf3e39..952eb93 100644 --- a/examples/declarative/extending/attached/example.qml +++ b/examples/declarative/extending/attached/example.qml @@ -1,4 +1,3 @@ -import Qt 4.6 import People 1.0 BirthdayParty { diff --git a/examples/declarative/extending/binding/example.qml b/examples/declarative/extending/binding/example.qml index 7ab0d62..1651b7a 100644 --- a/examples/declarative/extending/binding/example.qml +++ b/examples/declarative/extending/binding/example.qml @@ -1,4 +1,3 @@ -import Qt 4.6 import People 1.0 // ![0] diff --git a/examples/declarative/extending/coercion/example.qml b/examples/declarative/extending/coercion/example.qml index ce2c32d..64d26b0 100644 --- a/examples/declarative/extending/coercion/example.qml +++ b/examples/declarative/extending/coercion/example.qml @@ -1,4 +1,3 @@ -import Qt 4.6 import People 1.0 // ![0] diff --git a/examples/declarative/extending/default/example.qml b/examples/declarative/extending/default/example.qml index 051a9d2..58035f9 100644 --- a/examples/declarative/extending/default/example.qml +++ b/examples/declarative/extending/default/example.qml @@ -1,4 +1,3 @@ -import Qt 4.6 import People 1.0 // ![0] diff --git a/examples/declarative/extending/extended/example.qml b/examples/declarative/extending/extended/example.qml index 8311c8e..985ce20 100644 --- a/examples/declarative/extending/extended/example.qml +++ b/examples/declarative/extending/extended/example.qml @@ -1,4 +1,3 @@ -import Qt 4.6 import People 1.0 // ![0] diff --git a/examples/declarative/extending/grouped/example.qml b/examples/declarative/extending/grouped/example.qml index 622e204..55912ed 100644 --- a/examples/declarative/extending/grouped/example.qml +++ b/examples/declarative/extending/grouped/example.qml @@ -1,4 +1,3 @@ -import Qt 4.6 import People 1.0 // ![0] diff --git a/examples/declarative/extending/properties/example.qml b/examples/declarative/extending/properties/example.qml index 976baf2..9594a84 100644 --- a/examples/declarative/extending/properties/example.qml +++ b/examples/declarative/extending/properties/example.qml @@ -1,4 +1,3 @@ -import Qt 4.6 import People 1.0 // ![0] diff --git a/examples/declarative/extending/signal/example.qml b/examples/declarative/extending/signal/example.qml index dc3a61a..e46bf32 100644 --- a/examples/declarative/extending/signal/example.qml +++ b/examples/declarative/extending/signal/example.qml @@ -1,4 +1,3 @@ -import Qt 4.6 import People 1.0 // ![0] diff --git a/examples/declarative/extending/valuesource/example.qml b/examples/declarative/extending/valuesource/example.qml index c536061..6d47350 100644 --- a/examples/declarative/extending/valuesource/example.qml +++ b/examples/declarative/extending/valuesource/example.qml @@ -1,4 +1,3 @@ -import Qt 4.6 import People 1.0 // ![0] -- cgit v0.12 From abfa26ff5be47edcf38a48bacb4bd310badca09e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Thu, 10 Sep 2009 13:37:49 +0200 Subject: Fixed references to QFxPainted, which got replaced by QFxPaintedItem See commit 415708f85341448c6f30bbca6e31e48dbfde72a5, and later renaming of QFxImageItem to QFxPaintedItem in commit d1bb572b9fb5b0286df992c8ae560d91c9dc3388. Also added a table of contents to the QML for C++ Programmers page. --- doc/src/declarative/cppitem.qdoc | 6 +++--- doc/src/declarative/qmlforcpp.qdoc | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/src/declarative/cppitem.qdoc b/doc/src/declarative/cppitem.qdoc index 4543156..38da0fb 100644 --- a/doc/src/declarative/cppitem.qdoc +++ b/doc/src/declarative/cppitem.qdoc @@ -94,7 +94,7 @@ You can create a new type of QML item by: To add a new type, you first must add a new C++ class derived from QFxItem. You may of course extend existing QFxItem subclasses. -One existing subclass is QFxPainted, which provides +One existing subclass is QFxPaintedItem, which provides a simple cached-image painting model. \section2 Reimplementing paint functions @@ -105,11 +105,11 @@ Two alternative painters are available, offering different levels of performance and functionality: QPainter, GLPainter. -You can choose to subclass QFxPainted rather than QFxItem, +You can choose to subclass QFxPaintedItem rather than QFxItem, and then implement the virtual method: \code - void paint(QPainter *painter); + void drawContents(QPainter *painter, const QRect &rect); \endcode This paints into an offscreen pixmap which is then painted to the display (transformed, diff --git a/doc/src/declarative/qmlforcpp.qdoc b/doc/src/declarative/qmlforcpp.qdoc index 5838df7..ab456e5 100644 --- a/doc/src/declarative/qmlforcpp.qdoc +++ b/doc/src/declarative/qmlforcpp.qdoc @@ -15,6 +15,8 @@ either for the first time at startup or subsequently thereafter - the property is automatically updated with the new value. + \tableofcontents + \section1 Loading and using QML Files QmlComponent is used to load a QML file and to create object instances. -- cgit v0.12 From ad96554aa5eae45d256120dbaf840da0bcee2fba Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Fri, 11 Sep 2009 08:32:18 +1000 Subject: Implement itemsMoved() in ListView. No animation possible currently. --- src/declarative/fx/qfxlistview.cpp | 78 +++++++++++++++++++++---------- src/declarative/fx/qfxvisualitemmodel.cpp | 19 +++++++- src/declarative/util/qmllistmodel.cpp | 2 +- 3 files changed, 73 insertions(+), 26 deletions(-) diff --git a/src/declarative/fx/qfxlistview.cpp b/src/declarative/fx/qfxlistview.cpp index 49de016..a07b3c0 100644 --- a/src/declarative/fx/qfxlistview.cpp +++ b/src/declarative/fx/qfxlistview.cpp @@ -377,7 +377,6 @@ public: QmlComponent *highlightComponent; FxListItem *highlight; FxListItem *trackedItem; - QFxItem *activeItem; //XXX fix enum MovementReason { Other, Key, Mouse }; MovementReason moveReason; int buffer; @@ -1431,9 +1430,7 @@ void QFxListView::itemResized() Q_D(QFxListView); QFxItem *item = qobject_cast(sender()); if (item) { - d->activeItem = item; // Ick - don't delete the sender d->layout(); - d->activeItem = 0; d->fixupPosition(); } } @@ -1642,33 +1639,66 @@ void QFxListView::destroyRemoved() void QFxListView::itemsMoved(int from, int to, int count) { - qWarning() << "ListView does not support moving in models"; - Q_D(QFxListView); - int fromCount = count; - int toCount = count; - bool fromVisible = d->mapRangeFromModel(from, fromCount); - bool toVisible = d->mapRangeFromModel(to, toCount); - - if (!fromVisible && !toVisible) { - // The items are outside the visible range. - if (d->visibleItems.count()) - d->visibleIndex = -1; - for (int i = 0; i < d->visibleItems.count(); ++i) { - FxListItem *listItem = d->visibleItems.at(i); - if (listItem->index != -1) { - listItem->index = d->model->indexOf(listItem->item, this); - if (d->visibleIndex < 0) - d->visibleIndex = listItem->index; + QHash moved; + int moveBy = 0; + + QList::Iterator it = d->visibleItems.begin(); + while (it != d->visibleItems.end()) { + FxListItem *item = *it; + if (item->index >= from && item->index < from + count) { + // take the items that are moving + item->index += (to-from); + moved.insert(item->index, item); + moveBy += item->size(); + it = d->visibleItems.erase(it); + } else { + if (item->index > from && item->index != -1) { + // move everything after the moved items. + item->index -= count; + item->setPosition(item->position()-moveBy); } + ++it; } - if (d->currentItem) { - d->currentItem->index = d->model->indexOf(d->currentItem->item, this); - d->currentIndex = d->currentItem->index; + } + + int remaining = count; + int endIndex = d->visibleIndex; + it = d->visibleItems.begin(); + while (it != d->visibleItems.end()) { + FxListItem *item = *it; + if (remaining && item->index >= to && item->index < to + count) { + // place items in the target position, reusing any existing items + FxListItem *movedItem = moved.take(item->index); + if (!movedItem) + movedItem = d->createItem(item->index); + it = d->visibleItems.insert(it, movedItem); + ++it; + --remaining; + } else { + if (item->index != -1) { + if (item->index >= to) { + // update everything after the moved items. + item->index += count; + } + endIndex = item->index; + } + ++it; } - return; } + // If we have moved items to the end of the visible items + // then add any existing moved items that we have + while (FxListItem *item = moved.take(endIndex+1)) { + d->visibleItems.append(item); + ++endIndex; + } + + // Whatever moved items remain are no longer visible items. + while (moved.count()) + d->releaseItem(moved.take(moved.begin().key())); + + d->layout(); } void QFxListView::createdItem(int index, QFxItem *item) diff --git a/src/declarative/fx/qfxvisualitemmodel.cpp b/src/declarative/fx/qfxvisualitemmodel.cpp index cac8b8d..30879a2 100644 --- a/src/declarative/fx/qfxvisualitemmodel.cpp +++ b/src/declarative/fx/qfxvisualitemmodel.cpp @@ -695,7 +695,8 @@ QFxVisualDataModel::ReleaseFlags QFxVisualDataModel::release(QFxItem *item) if (inPackage) emit destroyingPackage(qobject_cast(obj)); stat |= Destroyed; - delete obj; + obj->setParent(0); + obj->deleteLater(); } else if (!inPackage) { stat |= Referenced; } @@ -916,6 +917,22 @@ void QFxVisualDataModel::_q_itemsMoved(int from, int to, int count) ++iter; } } + for (QHash::Iterator iter = d->m_cache.begin(); + iter != d->m_cache.end(); ) { + + if (iter.key() >= qMin(from,to) && iter.key() < qMax(from+count,to+count)) { + QFxVisualDataModelPrivate::ObjectRef objRef = *iter; + int index = iter.key() + from - to; + iter = d->m_cache.erase(iter); + + items.insert(index, objRef); + + QFxVisualDataModelData *data = d->data(objRef.obj); + data->setIndex(index); + } else { + ++iter; + } + } d->m_cache.unite(items); emit itemsMoved(from, to, count); diff --git a/src/declarative/util/qmllistmodel.cpp b/src/declarative/util/qmllistmodel.cpp index 19499a1..345bc3b 100644 --- a/src/declarative/util/qmllistmodel.cpp +++ b/src/declarative/util/qmllistmodel.cpp @@ -497,7 +497,7 @@ void QmlListModel::insert(int index, const QScriptValue& valuemap) */ void QmlListModel::move(int from, int to, int n) { - if (from+n > count() || to+n > count() || n==0 || from==to) + if (from+n > count() || to+n > count() || n==0 || from==to || from < 0 || to < 0) return; if (from > to) { // Only move forwards - flip if backwards moving -- cgit v0.12 From 804c9ef64085fafe6f12b92e5dd40e595ed3460f Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Fri, 11 Sep 2009 10:08:06 +1000 Subject: Handle itemsMoved() in GridView. --- src/declarative/fx/qfxgridview.cpp | 63 ++++++++++++++++++++++++++++++++++++++ src/declarative/fx/qfxgridview.h | 1 + 2 files changed, 64 insertions(+) diff --git a/src/declarative/fx/qfxgridview.cpp b/src/declarative/fx/qfxgridview.cpp index dfb04ad..f49375a 100644 --- a/src/declarative/fx/qfxgridview.cpp +++ b/src/declarative/fx/qfxgridview.cpp @@ -723,6 +723,7 @@ void QFxGridView::setModel(const QVariant &model) if (d->model) { disconnect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int))); disconnect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int))); + disconnect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int))); disconnect(d->model, SIGNAL(createdItem(int, QFxItem*)), this, SLOT(createdItem(int,QFxItem*))); disconnect(d->model, SIGNAL(destroyingItem(QFxItem*)), this, SLOT(destroyingItem(QFxItem*))); } @@ -751,6 +752,7 @@ void QFxGridView::setModel(const QVariant &model) d->updateCurrent(d->currentIndex); connect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int))); connect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int))); + connect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int))); connect(d->model, SIGNAL(createdItem(int, QFxItem*)), this, SLOT(createdItem(int,QFxItem*))); connect(d->model, SIGNAL(destroyingItem(QFxItem*)), this, SLOT(destroyingItem(QFxItem*))); refill(); @@ -1356,6 +1358,67 @@ void QFxGridView::destroyRemoved() d->layout(); } +void QFxGridView::itemsMoved(int from, int to, int count) +{ + Q_D(QFxGridView); + QHash moved; + + QList::Iterator it = d->visibleItems.begin(); + while (it != d->visibleItems.end()) { + FxGridItem *item = *it; + if (item->index >= from && item->index < from + count) { + // take the items that are moving + item->index += (to-from); + moved.insert(item->index, item); + it = d->visibleItems.erase(it); + } else { + if (item->index > from && item->index != -1) { + // move everything after the moved items. + item->index -= count; + } + ++it; + } + } + + int remaining = count; + int endIndex = d->visibleIndex; + it = d->visibleItems.begin(); + while (it != d->visibleItems.end()) { + FxGridItem *item = *it; + if (remaining && item->index >= to && item->index < to + count) { + // place items in the target position, reusing any existing items + FxGridItem *movedItem = moved.take(item->index); + if (!movedItem) + movedItem = d->createItem(item->index); + it = d->visibleItems.insert(it, movedItem); + ++it; + --remaining; + } else { + if (item->index != -1) { + if (item->index >= to) { + // update everything after the moved items. + item->index += count; + } + endIndex = item->index; + } + ++it; + } + } + + // If we have moved items to the end of the visible items + // then add any existing moved items that we have + while (FxGridItem *item = moved.take(endIndex+1)) { + d->visibleItems.append(item); + ++endIndex; + } + + // Whatever moved items remain are no longer visible items. + while (moved.count()) + d->releaseItem(moved.take(moved.begin().key())); + + d->layout(); +} + void QFxGridView::createdItem(int index, QFxItem *item) { Q_D(QFxGridView); diff --git a/src/declarative/fx/qfxgridview.h b/src/declarative/fx/qfxgridview.h index 954f9fe..734039c 100644 --- a/src/declarative/fx/qfxgridview.h +++ b/src/declarative/fx/qfxgridview.h @@ -130,6 +130,7 @@ private Q_SLOTS: void trackedPositionChanged(); void itemsInserted(int index, int count); void itemsRemoved(int index, int count); + void itemsMoved(int from, int to, int count); void destroyRemoved(); void createdItem(int index, QFxItem *item); void destroyingItem(QFxItem *item); -- cgit v0.12 From 7051254771882e88f64f9b5578d975f29efab0b6 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Fri, 11 Sep 2009 10:54:11 +1000 Subject: current -> currentItem property in ListView and GridView --- examples/declarative/listview/highlight.qml | 2 +- examples/declarative/loader/Browser.qml | 2 +- src/declarative/QmlChanges.txt | 2 ++ src/declarative/fx/qfxgridview.cpp | 4 ++-- src/declarative/fx/qfxgridview.h | 2 +- src/declarative/fx/qfxlistview.cpp | 4 ++-- src/declarative/fx/qfxlistview.h | 2 +- 7 files changed, 10 insertions(+), 8 deletions(-) diff --git a/examples/declarative/listview/highlight.qml b/examples/declarative/listview/highlight.qml index e707ac0..cb92ad9 100644 --- a/examples/declarative/listview/highlight.qml +++ b/examples/declarative/listview/highlight.qml @@ -44,7 +44,7 @@ Rectangle { id: PetHighlight Rectangle { width: 200; height: 50; color: "#FFFF88" - y: SpringFollow { source: List1.current.y; spring: 3; damping: 0.1 } + y: SpringFollow { source: List1.currentItem.y; spring: 3; damping: 0.1 } } } ListView { diff --git a/examples/declarative/loader/Browser.qml b/examples/declarative/loader/Browser.qml index 196cdc5..6711de4 100644 --- a/examples/declarative/loader/Browser.qml +++ b/examples/declarative/loader/Browser.qml @@ -82,7 +82,7 @@ Rectangle { focus: true Keys.onPressed: { if (event.key == Qt.Key_Return || event.key == Qt.Key_Select) { - View.current.launch(); + View.currentItem.launch(); event.accepted = true; } } diff --git a/src/declarative/QmlChanges.txt b/src/declarative/QmlChanges.txt index eace089..fe923a7 100644 --- a/src/declarative/QmlChanges.txt +++ b/src/declarative/QmlChanges.txt @@ -64,6 +64,8 @@ WebView: mouseY -> clickY (parameter to onDoubleClick) WebView: cacheSize -> pixelCacheSize Repeater: component -> delegate Repeater: dataSource -> model +ListView: current -> currentItem +GridView: current -> currentItem Additions: MouseRegion: add "acceptedButtons" property diff --git a/src/declarative/fx/qfxgridview.cpp b/src/declarative/fx/qfxgridview.cpp index f49375a..d4cf691 100644 --- a/src/declarative/fx/qfxgridview.cpp +++ b/src/declarative/fx/qfxgridview.cpp @@ -795,10 +795,10 @@ void QFxGridView::setDelegate(QmlComponent *delegate) /*! \qmlproperty int GridView::currentIndex - \qmlproperty Item GridView::current + \qmlproperty Item GridView::currentItem \c currentIndex holds the index of the current item. - \c current is the current item. Note that the position of the current item + \c currentItem is the current item. Note that the position of the current item may only be approximate until it becomes visible in the view. */ int QFxGridView::currentIndex() const diff --git a/src/declarative/fx/qfxgridview.h b/src/declarative/fx/qfxgridview.h index 734039c..e08ba9e 100644 --- a/src/declarative/fx/qfxgridview.h +++ b/src/declarative/fx/qfxgridview.h @@ -60,7 +60,7 @@ class Q_DECLARATIVE_EXPORT QFxGridView : public QFxFlickable Q_PROPERTY(QVariant model READ model WRITE setModel) Q_PROPERTY(QmlComponent *delegate READ delegate WRITE setDelegate) Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged) - Q_PROPERTY(QFxItem *current READ currentItem NOTIFY currentIndexChanged) //### currentItem + Q_PROPERTY(QFxItem *currentItem READ currentItem NOTIFY currentIndexChanged) Q_PROPERTY(int count READ count NOTIFY countChanged) Q_PROPERTY(QmlComponent *highlight READ highlight WRITE setHighlight) Q_PROPERTY(bool autoHighlight READ autoHighlight WRITE setAutoHighlight) diff --git a/src/declarative/fx/qfxlistview.cpp b/src/declarative/fx/qfxlistview.cpp index a07b3c0..6596735 100644 --- a/src/declarative/fx/qfxlistview.cpp +++ b/src/declarative/fx/qfxlistview.cpp @@ -983,10 +983,10 @@ void QFxListView::setDelegate(QmlComponent *delegate) /*! \qmlproperty int ListView::currentIndex - \qmlproperty Item ListView::current + \qmlproperty Item ListView::currentItem \c currentIndex holds the index of the current item. - \c current is the current item. Note that the position of the current item + \c currentItem is the current item. Note that the position of the current item may only be approximate until it becomes visible in the view. */ int QFxListView::currentIndex() const diff --git a/src/declarative/fx/qfxlistview.h b/src/declarative/fx/qfxlistview.h index 829e202..4a124cb 100644 --- a/src/declarative/fx/qfxlistview.h +++ b/src/declarative/fx/qfxlistview.h @@ -67,7 +67,7 @@ class Q_DECLARATIVE_EXPORT QFxListView : public QFxFlickable Q_PROPERTY(QVariant model READ model WRITE setModel) Q_PROPERTY(QmlComponent *delegate READ delegate WRITE setDelegate) //### what happens if delegate is not a QFxItem? Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged) - Q_PROPERTY(QFxItem *current READ currentItem NOTIFY currentIndexChanged) //### currentItem + Q_PROPERTY(QFxItem *currentItem READ currentItem NOTIFY currentIndexChanged) Q_PROPERTY(int count READ count NOTIFY countChanged) Q_PROPERTY(QmlComponent *highlight READ highlight WRITE setHighlight) Q_PROPERTY(bool autoHighlight READ autoHighlight WRITE setAutoHighlight) //### highlightFollowsCurrentItem -- cgit v0.12 From c56df535f5bf40ff0afefd10c3b1bf348763c65d Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Fri, 11 Sep 2009 11:56:18 +1000 Subject: Use drawTiledPixmap for tiling. So we can take advantage of backend optimizations. --- src/declarative/fx/qfximage.cpp | 36 ++++++------------------------------ 1 file changed, 6 insertions(+), 30 deletions(-) diff --git a/src/declarative/fx/qfximage.cpp b/src/declarative/fx/qfximage.cpp index 99e1b72..79b3ae1 100644 --- a/src/declarative/fx/qfximage.cpp +++ b/src/declarative/fx/qfximage.cpp @@ -255,36 +255,12 @@ void QFxImage::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) p->save(); p->setClipRect(0, 0, width(), height(), Qt::IntersectClip); - if (d->fillMode == Tile) { - const int pw = d->pix.width(); - const int ph = d->pix.height(); - int yy = 0; - - while(yy < height()) { - int xx = 0; - while(xx < width()) { - p->drawPixmap(xx, yy, d->pix); - xx += pw; - } - yy += ph; - } - } else if (d->fillMode == TileVertically) { - const int ph = d->pix.height(); - int yy = 0; - - while(yy < height()) { - p->drawPixmap(QRect(0, yy, width(), ph), d->pix); - yy += ph; - } - } else { - const int pw = d->pix.width(); - int xx = 0; - - while(xx < width()) { - p->drawPixmap(QRect(xx, 0, pw, height()), d->pix); - xx += pw; - } - } + if (d->fillMode == Tile) + p->drawTiledPixmap(QRectF(0,0,width(),height()), d->pix); + else if (d->fillMode == TileVertically) + p->drawTiledPixmap(QRectF(0,0,d->pix.width(),height()), d->pix); + else + p->drawTiledPixmap(QRectF(0,0,width(),d->pix.height()), d->pix); p->restore(); } else { -- cgit v0.12 From 3a4eb09c502d2394b35b62ca12b28cba392dc270 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Fri, 11 Sep 2009 13:32:23 +1000 Subject: tweak --- .../listview/content/ClickAutoRepeating.qml | 29 ++++++++++++++++++++++ examples/declarative/listview/dynamic.qml | 7 ++++-- 2 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 examples/declarative/listview/content/ClickAutoRepeating.qml diff --git a/examples/declarative/listview/content/ClickAutoRepeating.qml b/examples/declarative/listview/content/ClickAutoRepeating.qml new file mode 100644 index 0000000..19dd6f6 --- /dev/null +++ b/examples/declarative/listview/content/ClickAutoRepeating.qml @@ -0,0 +1,29 @@ +import Qt 4.6 + +Item { + id: Page + property int repeatdelay: 300 + property int repeatperiod: 75 + property bool pressed: false + signal pressed + signal released + signal clicked + pressed: SequentialAnimation { + id: AutoRepeat + PropertyAction { target: Page; property: "pressed"; value: true } + ScriptAction { script: Page.onPressed } + ScriptAction { script: Page.onClicked } + PauseAnimation { duration: repeatdelay } + SequentialAnimation { + repeat: true + ScriptAction { script: Page.onClicked } + PauseAnimation { duration: repeatperiod } + } + } + MouseRegion { + id: MR + anchors.fill: parent + onPressed: AutoRepeat.start() + onReleased: { AutoRepeat.stop(); parent.pressed = false; Page.released } + } +} diff --git a/examples/declarative/listview/dynamic.qml b/examples/declarative/listview/dynamic.qml index f615c24..dde24f6 100644 --- a/examples/declarative/listview/dynamic.qml +++ b/examples/declarative/listview/dynamic.qml @@ -1,4 +1,5 @@ import Qt 4.6 +import "content" Item { width: 320 @@ -75,10 +76,12 @@ Item { anchors.right: parent.right width: childrenRect.width Image { source: "content/pics/add.png" - MouseRegion { anchors.fill: parent; onClicked: FruitModel.set(index,"cost",Number(cost)+0.25) } + ClickAutoRepeating { id: ClickUp; anchors.fill: parent; onClicked: FruitModel.set(index,"cost",Number(cost)+0.25) } + scale: ClickUp.pressed ? 0.9 : 1 } Image { source: "content/pics/del.png" - MouseRegion { anchors.fill: parent; onClicked: FruitModel.set(index,"cost",Number(cost)-0.25) } + ClickAutoRepeating { id: ClickDown; anchors.fill: parent; onClicked: FruitModel.set(index,"cost",Math.max(0,Number(cost)-0.25)) } + scale: ClickDown.pressed ? 0.9 : 1 } Image { source: "content/pics/trash.png" MouseRegion { anchors.fill: parent; onClicked: FruitModel.remove(index) } -- cgit v0.12 From 2984be68041afc154fab2a0b9eb6618caf26cf71 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Fri, 11 Sep 2009 14:28:39 +1000 Subject: Avoid spurious flicks due to quick clicking motions. --- src/declarative/fx/qfxflickable.cpp | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/declarative/fx/qfxflickable.cpp b/src/declarative/fx/qfxflickable.cpp index c227899..1e6ad5a 100644 --- a/src/declarative/fx/qfxflickable.cpp +++ b/src/declarative/fx/qfxflickable.cpp @@ -48,6 +48,16 @@ QT_BEGIN_NAMESPACE + +// These are highly device dependant. +// DragThreshold determines how far the "mouse" must move before +// we begin a drag. +// FlickThreshold determines how far the "mouse" must have moved +// before we perform a flick. +static const int DragThreshold = 8; +static const int FlickThreshold = 20; + + class QFxFlickableVisibleArea : public QObject { Q_OBJECT @@ -147,7 +157,7 @@ QFxFlickablePrivate::QFxFlickablePrivate() : viewport(new QFxItem), _moveX(viewport, &QFxItem::setX), _moveY(viewport, &QFxItem::setY) , vWidth(-1), vHeight(-1), overShoot(true), flicked(false), moving(false), stealMouse(false) , pressed(false), atXEnd(false), atXBeginning(true), atYEnd(false), atYBeginning(true) - , interactive(true), maxVelocity(-1), reportedVelocitySmoothing(100) + , interactive(true), maxVelocity(5000), reportedVelocitySmoothing(100) , delayedPressEvent(0), delayedPressTarget(0), pressDelay(0) , horizontalVelocity(this), verticalVelocity(this), vTime(0), visibleArea(0) { @@ -327,8 +337,6 @@ void QFxFlickablePrivate::updateBeginningEnd() visibleArea->updateVisible(); } -static const int FlickThreshold = 5; - QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Flickable,QFxFlickable) /*! @@ -602,7 +610,7 @@ void QFxFlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent *event) if (q->yflick()) { int dy = int(event->pos().y() - pressPos.y()); - if (qAbs(dy) > FlickThreshold || pressTime.elapsed() > 200) { + if (qAbs(dy) > DragThreshold || pressTime.elapsed() > 200) { qreal newY = dy + pressY; const qreal minY = q->minYExtent(); const qreal maxY = q->maxYExtent(); @@ -615,14 +623,14 @@ void QFxFlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent *event) moved = true; } else if (!q->overShoot()) rejectY = true; - if (qAbs(dy) > FlickThreshold) + if (qAbs(dy) > DragThreshold) stealMouse = true; } } if (q->xflick()) { int dx = int(event->pos().x() - pressPos.x()); - if (qAbs(dx) > FlickThreshold || pressTime.elapsed() > 200) { + if (qAbs(dx) > DragThreshold || pressTime.elapsed() > 200) { qreal newX = dx + pressX; const qreal minX = q->minXExtent(); const qreal maxX = q->maxXExtent(); @@ -635,7 +643,7 @@ void QFxFlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent *event) moved = true; } else if (!q->overShoot()) rejectX = true; - if (qAbs(dx) > FlickThreshold) + if (qAbs(dx) > DragThreshold) stealMouse = true; } } @@ -666,7 +674,7 @@ void QFxFlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent *event) lastPos = event->pos(); } -void QFxFlickablePrivate::handleMouseReleaseEvent(QGraphicsSceneMouseEvent *) +void QFxFlickablePrivate::handleMouseReleaseEvent(QGraphicsSceneMouseEvent *event) { Q_Q(QFxFlickable); pressed = false; @@ -674,12 +682,12 @@ void QFxFlickablePrivate::handleMouseReleaseEvent(QGraphicsSceneMouseEvent *) return; vTime = timeline.time(); - if (qAbs(velocityY) > 10) + if (qAbs(velocityY) > 10 && qAbs(event->pos().y() - pressPos.y()) > FlickThreshold) flickY(velocityY); else fixupY(); - if (qAbs(velocityX) > 10) + if (qAbs(velocityX) > 10 && qAbs(event->pos().x() - pressPos.x()) > FlickThreshold) flickX(velocityX); else fixupX(); @@ -1093,6 +1101,8 @@ bool QFxFlickable::sceneEventFilter(QGraphicsItem *i, QEvent *e) /*! \qmlproperty int Flickable::maximumFlickVelocity This property holds the maximum velocity that the user can flick the view in pixels/second. + + The default is 5000 pixels/s */ qreal QFxFlickable::maximumFlickVelocity() const { -- cgit v0.12 From df478cf9577c766a0a8d0bcb7b4da6c9c0be0171 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Fri, 11 Sep 2009 15:17:22 +1000 Subject: Ensure item moves are passed on literally so views can animate literally. --- src/declarative/util/qmllistmodel.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/declarative/util/qmllistmodel.cpp b/src/declarative/util/qmllistmodel.cpp index 345bc3b..69bed25 100644 --- a/src/declarative/util/qmllistmodel.cpp +++ b/src/declarative/util/qmllistmodel.cpp @@ -499,6 +499,9 @@ void QmlListModel::move(int from, int to, int n) { if (from+n > count() || to+n > count() || n==0 || from==to || from < 0 || to < 0) return; + int origfrom=from; // preserve actual move, so any animations are correct + int origto=to; + int orign=n; if (from > to) { // Only move forwards - flip if backwards moving int tfrom = from; @@ -524,7 +527,7 @@ void QmlListModel::move(int from, int to, int n) for (; f != replaced.end(); ++f, ++t) *t = *f; } - emit itemsMoved(from,to,n); + emit itemsMoved(origfrom,origto,orign); } /*! -- cgit v0.12 From e4648700e7e3c84c61d6b012f7d480394b889c31 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Fri, 11 Sep 2009 15:48:20 +1000 Subject: Fix moving an item to the first visible position. Also fix the type of some properties/variables. --- src/declarative/fx/qfxlistview.cpp | 32 ++++++++++++++++---------------- src/declarative/fx/qfxlistview.h | 6 +++--- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/declarative/fx/qfxlistview.cpp b/src/declarative/fx/qfxlistview.cpp index 6596735..ac9b6ca 100644 --- a/src/declarative/fx/qfxlistview.cpp +++ b/src/declarative/fx/qfxlistview.cpp @@ -172,11 +172,11 @@ public: QFxListViewPrivate() : model(0), currentItem(0), tmpCurrent(0), orient(Qt::Vertical) , visiblePos(0), visibleIndex(0) - , averageSize(100), currentIndex(-1), requestedIndex(-1) + , averageSize(100.0), currentIndex(-1), requestedIndex(-1) , currItemMode(QFxListView::Free), snapPos(0), highlightComponent(0), highlight(0), trackedItem(0) - , moveReason(Other), buffer(0), highlightPosAnimator(0), highlightSizeAnimator(0), spacing(0) + , moveReason(Other), buffer(0), highlightPosAnimator(0), highlightSizeAnimator(0), spacing(0.0) , ownModel(false), wrap(false), autoHighlight(true) - , fixCurrentVisibility(false) {} + {} void init(); void clear(); @@ -205,7 +205,7 @@ public: else q->setViewportX(pos); } - int size() const { + qreal size() const { Q_Q(const QFxListView); return orient == Qt::Vertical ? q->height() : q->width(); } @@ -384,12 +384,11 @@ public: QmlEaseFollow *highlightSizeAnimator; QString sectionExpression; QString currentSection; - int spacing; + qreal spacing; - int ownModel : 1; - int wrap : 1; - int autoHighlight : 1; - int fixCurrentVisibility : 1; + bool ownModel : 1; + bool wrap : 1; + bool autoHighlight : 1; }; void QFxListViewPrivate::init() @@ -755,7 +754,6 @@ void QFxListViewPrivate::updateCurrent(int modelIndex) FxListItem *oldCurrentItem = currentItem; currentIndex = modelIndex; currentItem = createItem(modelIndex); - fixCurrentVisibility = true; if (oldCurrentItem && (!currentItem || oldCurrentItem->item != currentItem->item)) oldCurrentItem->attached->setIsCurrentItem(false); if (currentItem) { @@ -1149,13 +1147,13 @@ void QFxListView::setSnapPosition(int pos) This property holds the spacing to leave between items. */ -int QFxListView::spacing() const +qreal QFxListView::spacing() const { Q_D(const QFxListView); return d->spacing; } -void QFxListView::setSpacing(int spacing) +void QFxListView::setSpacing(qreal spacing) { Q_D(QFxListView); if (spacing != d->spacing) { @@ -1640,6 +1638,7 @@ void QFxListView::destroyRemoved() void QFxListView::itemsMoved(int from, int to, int count) { Q_D(QFxListView); + qreal firstItemPos = d->visibleItems.first()->position(); QHash moved; int moveBy = 0; @@ -1653,11 +1652,9 @@ void QFxListView::itemsMoved(int from, int to, int count) moveBy += item->size(); it = d->visibleItems.erase(it); } else { - if (item->index > from && item->index != -1) { - // move everything after the moved items. + // move everything after the moved items. + if (item->index > from && item->index != -1) item->index -= count; - item->setPosition(item->position()-moveBy); - } ++it; } } @@ -1698,6 +1695,9 @@ void QFxListView::itemsMoved(int from, int to, int count) while (moved.count()) d->releaseItem(moved.take(moved.begin().key())); + // Ensure we don't cause an ugly list scroll. + d->visibleItems.first()->setPosition(firstItemPos); + d->layout(); } diff --git a/src/declarative/fx/qfxlistview.h b/src/declarative/fx/qfxlistview.h index 4a124cb..095c27b 100644 --- a/src/declarative/fx/qfxlistview.h +++ b/src/declarative/fx/qfxlistview.h @@ -73,7 +73,7 @@ class Q_DECLARATIVE_EXPORT QFxListView : public QFxFlickable Q_PROPERTY(bool autoHighlight READ autoHighlight WRITE setAutoHighlight) //### highlightFollowsCurrentItem Q_PROPERTY(CurrentItemPositioning currentItemPositioning READ currentItemPositioning WRITE setCurrentItemPositioning) //### mode Q_PROPERTY(int snapPosition READ snapPosition WRITE setSnapPosition) - Q_PROPERTY(int spacing READ spacing WRITE setSpacing NOTIFY spacingChanged) //### qreal + Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing NOTIFY spacingChanged) Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation) Q_PROPERTY(bool wrap READ isWrapEnabled WRITE setWrapEnabled) //### keyNavigationWraps, stops at end when held Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer) @@ -115,8 +115,8 @@ public: int snapPosition() const; void setSnapPosition(int pos); - int spacing() const; - void setSpacing(int spacing); + qreal spacing() const; + void setSpacing(qreal spacing); Qt::Orientation orientation() const; void setOrientation(Qt::Orientation); -- cgit v0.12 From 283ad006223cd4c178465397d25edc70362612ae Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Fri, 11 Sep 2009 15:48:45 +1000 Subject: Ensure text size changes when text is made empty, or elides to empty. Previously, old size would persist if text changed from non-"" to "". Elide text in example (tests and demonstrates) --- examples/declarative/listview/dynamic.qml | 4 ++-- src/declarative/fx/qfxtext.cpp | 21 ++++++++++----------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/examples/declarative/listview/dynamic.qml b/examples/declarative/listview/dynamic.qml index dde24f6..52c3c0b 100644 --- a/examples/declarative/listview/dynamic.qml +++ b/examples/declarative/listview/dynamic.qml @@ -59,8 +59,8 @@ Item { id: FruitDelegate Item { width: parent.width; height: 55 - Text { id: Label; font.pixelSize: 24; text: name } - Text { font.pixelSize: 24; text: '$'+Number(cost).toFixed(2); anchors.right: ItemButtons.left } + Text { id: Label; font.pixelSize: 24; text: name; elide: "ElideRight"; anchors.right: Cost.left; anchors.left:parent.left } + Text { id: Cost; font.pixelSize: 24; text: '$'+Number(cost).toFixed(2); anchors.right: ItemButtons.left } Row { anchors.top: Label.bottom spacing: 5 diff --git a/src/declarative/fx/qfxtext.cpp b/src/declarative/fx/qfxtext.cpp index c60aaf2..5b10289 100644 --- a/src/declarative/fx/qfxtext.cpp +++ b/src/declarative/fx/qfxtext.cpp @@ -466,9 +466,6 @@ void QFxTextPrivate::updateSize() { Q_Q(QFxText); if (q->isComponentComplete()) { - if (text.isEmpty()) { - return; - } QFontMetrics fm(font); int dy = q->height(); @@ -633,15 +630,17 @@ QPixmap QFxTextPrivate::wrappedTextImage(bool drawStyle) //paint text QPixmap img(size); - img.fill(Qt::transparent); - QPainter p(&img); - if (drawStyle) { - p.setPen(styleColor); + if (!size.isEmpty()) { + img.fill(Qt::transparent); + QPainter p(&img); + if (drawStyle) { + p.setPen(styleColor); + } + else + p.setPen(color); + p.setFont(font); + layout.draw(&p, QPointF(0, 0)); } - else - p.setPen(color); - p.setFont(font); - layout.draw(&p, QPointF(0, 0)); return img; } -- cgit v0.12 From efc7963a15c204db48cb3b6560366410b640e5c3 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Fri, 11 Sep 2009 15:54:19 +1000 Subject: Don't need to save and restore painter for tiling. --- src/declarative/fx/qfximage.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/declarative/fx/qfximage.cpp b/src/declarative/fx/qfximage.cpp index 79b3ae1..3ac3f3c 100644 --- a/src/declarative/fx/qfximage.cpp +++ b/src/declarative/fx/qfximage.cpp @@ -252,17 +252,12 @@ void QFxImage::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) if (width() != d->pix.width() || height() != d->pix.height()) { if (d->fillMode >= Tile) { - p->save(); - p->setClipRect(0, 0, width(), height(), Qt::IntersectClip); - if (d->fillMode == Tile) p->drawTiledPixmap(QRectF(0,0,width(),height()), d->pix); else if (d->fillMode == TileVertically) p->drawTiledPixmap(QRectF(0,0,d->pix.width(),height()), d->pix); else p->drawTiledPixmap(QRectF(0,0,width(),d->pix.height()), d->pix); - - p->restore(); } else { qreal widthScale = width() / qreal(d->pix.width()); qreal heightScale = height() / qreal(d->pix.height()); -- cgit v0.12 From bc7e8e12e96ff523278032d7c32c9bd504456de3 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Fri, 11 Sep 2009 16:06:29 +1000 Subject: Fix that empty string "resolves" to empty URL. Fix typo. --- src/declarative/qml/qmlmetaproperty.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index affb93b..b305619 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -880,15 +880,14 @@ void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value) if (vt == QVariant::ByteArray) { u = QUrl(QLatin1String(value.toByteArray())); found = true; - } else if (QVariant::String) { + } else if (vt == QVariant::String) { u = QUrl(value.toString()); found = true; } - if (context && u.isRelative()) - u = context->baseUrl().resolved(u); - if (found) { + if (context && u.isRelative() && !u.isEmpty()) + u = context->baseUrl().resolved(u); void *a[1]; a[0] = &u; QMetaObject::metacall(object, -- cgit v0.12 From 788da2e8b85f3773a525a6f2bcc535fa38ed02b2 Mon Sep 17 00:00:00 2001 From: Nigel Hietala Date: Sat, 12 Sep 2009 22:29:30 +0300 Subject: Fixed UrlBar to not clip off top 3 pixels of the page --- demos/declarative/webbrowser/webbrowser.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demos/declarative/webbrowser/webbrowser.qml b/demos/declarative/webbrowser/webbrowser.qml index ae3d048..3f23d83 100644 --- a/demos/declarative/webbrowser/webbrowser.qml +++ b/demos/declarative/webbrowser/webbrowser.qml @@ -55,7 +55,7 @@ Item { id: Header source: "content/pics/header.png" width: parent.width - height: 64 + height: 60 state: "Normal" x: Flick.viewportX < 0 ? -Flick.viewportX : Flick.viewportX > Flick.viewportWidth-Flick.width ? -Flick.viewportX+Flick.viewportWidth-Flick.width : 0 -- cgit v0.12 From b42b3db9bc459ef26bfaefa924dab2e853373b0d Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Mon, 14 Sep 2009 11:36:47 +1000 Subject: Track QML API changes. --- tools/qmldebugger/engines.qml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/qmldebugger/engines.qml b/tools/qmldebugger/engines.qml index 1652ebd..1e9335b 100644 --- a/tools/qmldebugger/engines.qml +++ b/tools/qmldebugger/engines.qml @@ -9,16 +9,16 @@ Item { Row { anchors.fill: parent Repeater { - dataSource: engines + model: engines Item { width: 100; height: 100; Image { - id: Image; + id: EngineIcon; source: "qrc:/engine.png" anchors.horizontalCenter: parent.horizontalCenter } Text { - anchors.top: Image.bottom; + anchors.top: EngineIcon.bottom; text: modelData.name + "(" + modelData.engineId + ")" anchors.horizontalCenter: parent.horizontalCenter } -- cgit v0.12 From 3b9aed8d7ea23a435211264c1bec731a98678ea5 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Mon, 14 Sep 2009 13:53:28 +1000 Subject: Move XmlListModelRole to be properly private. --- src/declarative/extra/qmlxmllistmodel.cpp | 126 +++++++++++++++++++----------- src/declarative/extra/qmlxmllistmodel.h | 40 ++-------- 2 files changed, 86 insertions(+), 80 deletions(-) diff --git a/src/declarative/extra/qmlxmllistmodel.cpp b/src/declarative/extra/qmlxmllistmodel.cpp index 4b67074..01efa0e 100644 --- a/src/declarative/extra/qmlxmllistmodel.cpp +++ b/src/declarative/extra/qmlxmllistmodel.cpp @@ -58,20 +58,85 @@ QT_BEGIN_NAMESPACE -QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,XmlRole,XmlListModelRole) +QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,XmlRole,QmlXmlListModelRole) QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,XmlListModel,QmlXmlListModel) +/*! + \qmlclass XmlRole + \brief The XmlRole element allows you to specify a role for an XmlListModel. +*/ + +/*! + \qmlproperty string XmlRole::name + The name for the role. This name is used to access the model data for this role from Qml. + + \qml + XmlRole { name: "title"; query: "title/string()" } + + ... + + Component { + id: Delegate + Text { text: title } + } + \endqml +*/ + +/*! + \qmlproperty string XmlRole::query + The relative XPath query for this role. The query should not start with a '/' (i.e. it must be + relative). + + \qml + XmlRole { name: "title"; query: "title/string()" } + \endqml +*/ + +class Q_DECLARATIVE_EXPORT QmlXmlListModelRole : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString name READ name WRITE setName) + Q_PROPERTY(QString query READ query WRITE setQuery) + +public: + QmlXmlListModelRole() {} + ~QmlXmlListModelRole() {} + + QString name() const { return m_name; } + void setName(const QString &name) { m_name = name; } + + QString query() const { return m_query; } + void setQuery(const QString &query) + { + if (query.startsWith(QLatin1Char('/'))) { + qmlInfo(this) << "An XmlRole query must not start with '/'"; + return; + } + m_query = query; + } + + bool isValid() { + return !m_name.isEmpty() && !m_query.isEmpty(); + } + +private: + QString m_name; + QString m_query; +}; + +QML_DECLARE_TYPE(QmlXmlListModelRole) + class QmlXmlListModelPrivate; -struct QmlXmlRoleList : public QmlConcreteList +struct QmlXmlRoleList : public QmlConcreteList { QmlXmlRoleList(QmlXmlListModelPrivate *p) : model(p) {} - virtual void append(XmlListModelRole *role); + virtual void append(QmlXmlListModelRole *role); //XXX clear, removeAt, and insert need to invalidate any cached data (in data table) as well // (and the model should emit the appropriate signals) virtual void clear(); virtual void removeAt(int i); - virtual void insert(int i, XmlListModelRole *role); + virtual void insert(int i, QmlXmlListModelRole *role); QmlXmlListModelPrivate *model; }; @@ -220,7 +285,7 @@ void QmlXmlQuery::doSubQueryJob() //### we might be able to condense even further (query for everything in one go) for (int i = 0; i < m_roleObjects->size(); ++i) { - XmlListModelRole *role = m_roleObjects->at(i); + QmlXmlListModelRole *role = m_roleObjects->at(i); if (!role->isValid()) { QList resultList; for (int j = 0; j < m_size; ++j) @@ -248,7 +313,7 @@ void QmlXmlQuery::doSubQueryJob() /*for (int j = 0; j < m_size; ++j) { QList resultList; for (int i = 0; i < m_roleObjects->size(); ++i) { - XmlListModelRole *role = m_roleObjects->at(i); + QmlXmlListModelRole *role = m_roleObjects->at(i); subquery.setQuery(m_prefix.arg(j+1) + role->query()); if (role->isStringList()) { QStringList data; @@ -274,10 +339,8 @@ void QmlXmlQuery::doSubQueryJob() } -//TODO: do something smart while waiting for data to load -// error handling (currently quite fragile) +//TODO: error handling (currently quite fragile) // profile doQuery and doSubquery -// some sort of loading indication while we wait for initial data load (status property similar to QWebImage?) // support complex/nested objects? // how do we handle data updates (like rss feed -- usually items inserted at beginning) @@ -310,64 +373,33 @@ public: }; -void QmlXmlRoleList::append(XmlListModelRole *role) { - QmlConcreteList::append(role); +void QmlXmlRoleList::append(QmlXmlListModelRole *role) { + QmlConcreteList::append(role); model->roles << model->highestRole; model->roleNames << role->name(); ++model->highestRole; } -/*! - \qmlclass XmlRole - \brief The XmlRole element allows you to specify a role for an XmlListModel. -*/ - -/*! - \qmlproperty string XmlRole::name - The name for the role. This name is used to access the model data for this role from Qml. - - \qml - XmlRole { name: "title"; query: "title/string()" } - - ... - - Component { - id: Delegate - Text { text: title } - } - \endqml -*/ - -/*! - \qmlproperty string XmlRole::query - The relative XPath query for this role. The query should not start with a '/' (i.e. it must be - relative). - - \qml - XmlRole { name: "title"; query: "title/string()" } - \endqml -*/ - //XXX clear, removeAt, and insert need to invalidate any cached data (in data table) as well // (and the model should emit the appropriate signals) void QmlXmlRoleList::clear() { model->roles.clear(); model->roleNames.clear(); - QmlConcreteList::clear(); + QmlConcreteList::clear(); } void QmlXmlRoleList::removeAt(int i) { model->roles.removeAt(i); model->roleNames.removeAt(i); - QmlConcreteList::removeAt(i); + QmlConcreteList::removeAt(i); } //### we should enforce unique role names -void QmlXmlRoleList::insert(int i, XmlListModelRole *role) +void QmlXmlRoleList::insert(int i, QmlXmlListModelRole *role) { - QmlConcreteList::insert(i, role); + QmlConcreteList::insert(i, role); model->roles.insert(i, model->highestRole); model->roleNames.insert(i, role->name()); ++model->highestRole; @@ -413,7 +445,7 @@ QmlXmlListModel::~QmlXmlListModel() The roles to make available for this model. */ -QmlList *QmlXmlListModel::roleObjects() +QmlList *QmlXmlListModel::roleObjects() { Q_D(QmlXmlListModel); return &d->roleObjects; diff --git a/src/declarative/extra/qmlxmllistmodel.h b/src/declarative/extra/qmlxmllistmodel.h index 5f7c831..1bcc008 100644 --- a/src/declarative/extra/qmlxmllistmodel.h +++ b/src/declarative/extra/qmlxmllistmodel.h @@ -53,37 +53,8 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) class QmlContext; -class Q_DECLARATIVE_EXPORT XmlListModelRole : public QObject -{ - Q_OBJECT - Q_PROPERTY(QString name READ name WRITE setName) - Q_PROPERTY(QString query READ query WRITE setQuery) -public: - XmlListModelRole() {} - ~XmlListModelRole() {} - - QString name() const { return m_name; } - void setName(const QString &name) { m_name = name; } - - QString query() const { return m_query; } - void setQuery(const QString &query) - { - if (query.startsWith(QLatin1Char('/'))) { - qmlInfo(this) << "An XmlRole query must not start with '/'"; - return; - } - m_query = query; - } - - bool isValid() { - return !m_name.isEmpty() && !m_query.isEmpty(); - } - -private: - QString m_name; - QString m_query; -}; +class QmlXmlListModelRole; class QmlXmlListModelPrivate; class Q_DECLARATIVE_EXPORT QmlXmlListModel : public QListModelInterface, public QmlParserStatus @@ -98,7 +69,7 @@ class Q_DECLARATIVE_EXPORT QmlXmlListModel : public QListModelInterface, public Q_PROPERTY(QString xml READ xml WRITE setXml) Q_PROPERTY(QString query READ query WRITE setQuery) Q_PROPERTY(QString namespaceDeclarations READ namespaceDeclarations WRITE setNamespaceDeclarations) - Q_PROPERTY(QmlList *roles READ roleObjects) + Q_PROPERTY(QmlList *roles READ roleObjects) Q_PROPERTY(int count READ count NOTIFY countChanged) Q_CLASSINFO("DefaultProperty", "roles") @@ -111,7 +82,7 @@ public: virtual QList roles() const; virtual QString toString(int role) const; - QmlList *roleObjects(); + QmlList *roleObjects(); QUrl source() const; void setSource(const QUrl&); @@ -138,6 +109,10 @@ signals: void countChanged(); public Q_SLOTS: + // ### need to use/expose Expiry to guess when to call this? + // ### property to auto-call this on reasonable Expiry? + // ### LastModified/Age also useful to guess. + // ### Probably also applies to other network-requesting types. void reload(); private Q_SLOTS: @@ -152,7 +127,6 @@ private: QT_END_NAMESPACE -QML_DECLARE_TYPE(XmlListModelRole) QML_DECLARE_TYPE(QmlXmlListModel) QT_END_HEADER -- cgit v0.12 From 9fa3695eb3b03a4d37bc3c75bdb3bf5c5205e48c Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Mon, 14 Sep 2009 14:09:39 +1000 Subject: Don't crash. The engine tree shouldn't have all these objects in it, but for now, just prevent crash when there are signals with parameters. --- src/declarative/qml/qmlenginedebug.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/declarative/qml/qmlenginedebug.cpp b/src/declarative/qml/qmlenginedebug.cpp index 321fe74..7f9e530 100644 --- a/src/declarative/qml/qmlenginedebug.cpp +++ b/src/declarative/qml/qmlenginedebug.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "qmlenginedebug_p.h" +#include "qmlboundsignal_p.h" #include #include #include @@ -103,7 +104,11 @@ QmlEngineDebugServer::propertyData(QObject *obj, int propIdx) if (prop.type() < QVariant::UserType) { rv.type = QmlObjectProperty::Basic; - rv.value = prop.read(obj); + if (qobject_cast(obj) && prop.name() != QByteArray("objectName")) + // these "properties" only have meaning during signal emission + rv.value = tr("(signal parameter)"); + else + rv.value = prop.read(obj); } else if (QmlMetaType::isObject(prop.userType())) { rv.type = QmlObjectProperty::Object; } else if (QmlMetaType::isList(prop.userType()) || -- cgit v0.12