summaryrefslogtreecommitdiffstats
path: root/src/declarative
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2009-07-09 07:25:58 (GMT)
committerAaron Kennedy <aaron.kennedy@nokia.com>2009-07-09 07:25:58 (GMT)
commit883da42f7c75775502c818aa456c8576d8457ff8 (patch)
treeb8d8c963f76c38baa9c684fe2a9d2537df02ef16 /src/declarative
parent8a6e5d5c95a8ae586c8fc2fa63be0228c4cefb53 (diff)
parent3399066881c42d1dd6fda6b3ae8cf3fc8961929b (diff)
downloadQt-883da42f7c75775502c818aa456c8576d8457ff8.zip
Qt-883da42f7c75775502c818aa456c8576d8457ff8.tar.gz
Qt-883da42f7c75775502c818aa456c8576d8457ff8.tar.bz2
Merge branch 'kinetic-declarativeui' of git@scm.dev.nokia.troll.no:qt/kinetic into kinetic-declarativeui
Diffstat (limited to 'src/declarative')
-rw-r--r--src/declarative/fx/qfxtextedit.cpp221
-rw-r--r--src/declarative/fx/qfxtextedit.h27
-rw-r--r--src/declarative/fx/qfxtextedit_p.h11
-rw-r--r--src/declarative/util/qmlanimation.cpp29
-rw-r--r--src/declarative/util/qmlanimation_p.h2
-rw-r--r--src/declarative/util/qmlfollow.cpp57
-rw-r--r--src/declarative/util/qmlfollow.h4
7 files changed, 330 insertions, 21 deletions
diff --git a/src/declarative/fx/qfxtextedit.cpp b/src/declarative/fx/qfxtextedit.cpp
index 7162bdf..c2bda6f 100644
--- a/src/declarative/fx/qfxtextedit.cpp
+++ b/src/declarative/fx/qfxtextedit.cpp
@@ -324,6 +324,36 @@ void QFxTextEdit::setHighlightColor(const QColor &color)
}
/*!
+ \qmlproperty color TextEdit::highlightedTextColor
+
+ The highlighted text color, used in selections.
+*/
+
+/*!
+ \property QFxTextEdit::highlightedTextColor
+ \brief the text edit's default highlighted text color
+*/
+QColor QFxTextEdit::highlightedTextColor() const
+{
+ Q_D(const QFxTextEdit);
+ return d->highlightColor;
+}
+
+void QFxTextEdit::setHighlightedTextColor(const QColor &color)
+{
+ Q_D(QFxTextEdit);
+ if (d->highlightedTextColor == color)
+ return;
+
+ clearCache();
+ d->highlightedTextColor = color;
+ QPalette pal = d->control->palette();
+ pal.setColor(QPalette::HighlightedText, color);
+ d->control->setPalette(pal);
+ update();
+}
+
+/*!
\qmlproperty enumeration TextEdit::hAlign
\qmlproperty enumeration TextEdit::vAlign
@@ -451,6 +481,145 @@ void QFxTextEdit::setCursorPosition(int pos)
if (cursor.position() == pos)
return;
cursor.setPosition(pos);
+ d->control->setTextCursor(cursor);
+}
+
+/*!
+ \qmlproperty TextEdit::cursorDelegate
+ \brief The delegate for the cursor in the TextEdit.
+
+ If you set a cursorDelegate for a TextEdit, this delegate will be used for
+ drawing the cursor instead of the standard cursor. An instance of the
+ delegate will be created and managed by the text edit when a cursor is
+ needed, and the x and y properties of delegate instance will be set so as
+ to be one pixel before the top left of the current character.
+
+ Note that the root item of the delegate component must be a QFxItem or
+ QFxItem derived item.
+*/
+QmlComponent* QFxTextEdit::cursorDelegate() const
+{
+ Q_D(const QFxTextEdit);
+ return d->cursorComponent;
+}
+
+void QFxTextEdit::setCursorDelegate(QmlComponent* c)
+{
+ Q_D(QFxTextEdit);
+ if(d->cursorComponent){
+ delete d->cursorComponent;
+ if(d->cursor){
+ disconnect(d->control, SIGNAL(cursorPositionChanged()),
+ this, SLOT(moveCursorDelegate()));
+ d->control->setCursorWidth(-1);
+ dirtyCache(cursorRect());
+ delete d->cursor;
+ d->cursor = 0;
+ }
+ }
+ d->cursorComponent = c;
+ if(c && c->isReady()){
+ loadCursorDelegate();
+ }else{
+ if(c)
+ connect(c, SIGNAL(statusChanged()),
+ this, SLOT(loadCursorDelegate()));
+ }
+}
+
+void QFxTextEdit::loadCursorDelegate()
+{
+ Q_D(QFxTextEdit);
+ if(d->cursorComponent->isLoading())
+ return;
+ d->cursor = qobject_cast<QFxItem*>(d->cursorComponent->create(qmlContext(this)));
+ if(d->cursor){
+ connect(d->control, SIGNAL(cursorPositionChanged()),
+ this, SLOT(moveCursorDelegate()));
+ d->control->setCursorWidth(0);
+ dirtyCache(cursorRect());
+ d->cursor->setItemParent(this);
+ d->cursor->setHeight(QFontMetrics(d->font.font()).height());
+ moveCursorDelegate();
+ }else{
+ qWarning() << "Error loading cursor delegate for TextEdit:" + objectName();
+ }
+}
+
+/*!
+ \qmlproperty int TextEdit::selectionStart
+
+ The cursor position before the first character in the current selection.
+ Setting this and selectionEnd allows you to specify a selection in the
+ text edit.
+
+ Note that if selectionStart == selectionEnd then there is no current
+ selection. If you attempt to set selectionStart to a value outside of
+ the current text, selectionStart will not be changed.
+
+ \sa selectionEnd, cursorPosition, selectedText
+*/
+int QFxTextEdit::selectionStart() const
+{
+ Q_D(const QFxTextEdit);
+ return d->control->textCursor().selectionStart();
+}
+
+void QFxTextEdit::setSelectionStart(int s)
+{
+ Q_D(QFxTextEdit);
+ if(d->lastSelectionStart == s || s < 0 || s > text().length())
+ return;
+ d->lastSelectionStart = s;
+ d->updateSelection();// Will emit the relevant signals
+}
+
+/*!
+ \qmlproperty int TextEdit::selectionEnd
+
+ The cursor position after the last character in the current selection.
+ Setting this and selectionStart allows you to specify a selection in the
+ text edit.
+
+ Note that if selectionStart == selectionEnd then there is no current
+ selection. If you attempt to set selectionEnd to a value outside of
+ the current text, selectionEnd will not be changed.
+
+ \sa selectionStart, cursorPosition, selectedText
+*/
+int QFxTextEdit::selectionEnd() const
+{
+ Q_D(const QFxTextEdit);
+ return d->control->textCursor().selectionEnd();
+}
+
+void QFxTextEdit::setSelectionEnd(int s)
+{
+ Q_D(QFxTextEdit);
+ if(d->lastSelectionEnd == s || s < 0 || s > text().length())
+ return;
+ d->lastSelectionEnd = s;
+ d->updateSelection();// Will emit the relevant signals
+}
+
+/*!
+ \qmlproperty string TextEdit::selectedText
+
+ This read-only property provides the text currently selected in the
+ text edit.
+
+ It is equivalent to the following snippet, but is faster and easier
+ to use.
+ \code
+ //myTextEdit is the id of the TextEdit
+ myTextEdit.text.toString().substring(myTextEdit.selectionStart,
+ myTextEdit.selectionEnd);
+ \endcode
+*/
+QString QFxTextEdit::selectedText() const
+{
+ Q_D(const QFxTextEdit);
+ return d->control->textCursor().selectedText();
}
/*!
@@ -853,6 +1022,10 @@ void QFxTextEdit::fontChanged()
Q_D(QFxTextEdit);
clearCache();
d->document->setDefaultFont(d->font.font());
+ if(d->cursor){
+ d->cursor->setHeight(QFontMetrics(d->font.font()).height());
+ moveCursorDelegate();
+ }
updateSize();
emit update();
}
@@ -879,6 +1052,9 @@ void QFxTextEditPrivate::init()
QObject::connect(control, SIGNAL(updateRequest(QRectF)), q, SLOT(updateImgCache(QRectF)));
QObject::connect(control, SIGNAL(textChanged()), q, SLOT(q_textChanged()));
+ QObject::connect(control, SIGNAL(selectionChanged()), q, SIGNAL(selectionChanged()));
+ QObject::connect(control, SIGNAL(selectionChanged()), q, SLOT(updateSelectionMarkers()));
+ QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SLOT(updateSelectionMarkers()));
QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SIGNAL(cursorPositionChanged()));
document = control->document();
@@ -896,6 +1072,51 @@ void QFxTextEdit::q_textChanged()
emit textChanged(text());
}
+void QFxTextEdit::moveCursorDelegate()
+{
+ Q_D(QFxTextEdit);
+ if(!d->cursor)
+ return;
+ QRectF cursorRect = d->control->cursorRect();
+ d->cursor->setX(cursorRect.x());
+ d->cursor->setY(cursorRect.y());
+}
+
+void QFxTextEditPrivate::updateSelection()
+{
+ Q_Q(QFxTextEdit);
+ QTextCursor cursor = control->textCursor();
+ bool startChange = (lastSelectionStart != cursor.selectionStart());
+ bool endChange = (lastSelectionEnd != cursor.selectionEnd());
+ //### Is it worth calculating a more minimal set of movements?
+ cursor.beginEditBlock();
+ cursor.setPosition(lastSelectionStart, QTextCursor::MoveAnchor);
+ cursor.setPosition(lastSelectionEnd, QTextCursor::KeepAnchor);
+ cursor.endEditBlock();
+ control->setTextCursor(cursor);
+ if(startChange)
+ q->selectionStartChanged();
+ if(endChange)
+ q->selectionEndChanged();
+ startChange = (lastSelectionStart != control->textCursor().selectionStart());
+ endChange = (lastSelectionEnd != control->textCursor().selectionEnd());
+ if(startChange || endChange)
+ qWarning() << "QFxTextEditPrivate::updateSelection() has failed you.";
+}
+
+void QFxTextEdit::updateSelectionMarkers()
+{
+ Q_D(QFxTextEdit);
+ if(d->lastSelectionStart != d->control->textCursor().selectionStart()){
+ d->lastSelectionStart = d->control->textCursor().selectionStart();
+ emit selectionStartChanged();
+ }
+ if(d->lastSelectionEnd != d->control->textCursor().selectionEnd()){
+ d->lastSelectionEnd = d->control->textCursor().selectionEnd();
+ emit selectionEndChanged();
+ }
+}
+
//### we should perhaps be a bit smarter here -- depending on what has changed, we shouldn't
// need to do all the calculations each time
void QFxTextEdit::updateSize()
diff --git a/src/declarative/fx/qfxtextedit.h b/src/declarative/fx/qfxtextedit.h
index 6988822..80636e2 100644
--- a/src/declarative/fx/qfxtextedit.h
+++ b/src/declarative/fx/qfxtextedit.h
@@ -70,6 +70,7 @@ class Q_DECLARATIVE_EXPORT QFxTextEdit : public QFxPaintedItem
Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
Q_PROPERTY(QColor color READ color WRITE setColor)
Q_PROPERTY(QColor highlightColor READ highlightColor WRITE setHighlightColor)
+ Q_PROPERTY(QColor highlightedTextColor READ highlightedTextColor WRITE setHighlightedTextColor)
Q_PROPERTY(QmlFont * font READ font)
Q_PROPERTY(HAlignment hAlign READ hAlign WRITE setHAlign)
Q_PROPERTY(VAlignment vAlign READ vAlign WRITE setVAlign)
@@ -77,7 +78,11 @@ class Q_DECLARATIVE_EXPORT QFxTextEdit : public QFxPaintedItem
Q_PROPERTY(TextFormat textFormat READ textFormat WRITE setTextFormat)
Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly)
Q_PROPERTY(bool cursorVisible READ isCursorVisible WRITE setCursorVisible)
- Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition)
+ Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition NOTIFY cursorPositionChanged)
+ Q_PROPERTY(QmlComponent* cursorDelegate READ cursorDelegate WRITE setCursorDelegate)
+ Q_PROPERTY(int selectionStart READ selectionStart WRITE setSelectionStart NOTIFY selectionStartChanged)
+ Q_PROPERTY(int selectionEnd READ selectionEnd WRITE setSelectionEnd NOTIFY selectionEndChanged)
+ Q_PROPERTY(QString selectedText READ selectedText NOTIFY selectionChanged)
Q_PROPERTY(bool focusOnPress READ focusOnPress WRITE setFocusOnPress)
Q_PROPERTY(bool preserveSelection READ preserveSelection WRITE setPreserveSelection)
Q_PROPERTY(qreal textMargin READ textMargin WRITE setTextMargin)
@@ -118,6 +123,9 @@ public:
QColor highlightColor() const;
void setHighlightColor(const QColor &c);
+ QColor highlightedTextColor() const;
+ void setHighlightedTextColor(const QColor &c);
+
HAlignment hAlign() const;
void setHAlign(HAlignment align);
@@ -133,6 +141,17 @@ public:
int cursorPosition() const;
void setCursorPosition(int pos);
+ QmlComponent* cursorDelegate() const;
+ void setCursorDelegate(QmlComponent*);
+
+ int selectionStart() const;
+ void setSelectionStart(int);
+
+ int selectionEnd() const;
+ void setSelectionEnd(int);
+
+ QString selectedText() const;
+
bool focusOnPress() const;
void setFocusOnPress(bool on);
@@ -168,6 +187,9 @@ public:
Q_SIGNALS:
void textChanged(const QString &);
void cursorPositionChanged();
+ void selectionStartChanged();
+ void selectionEndChanged();
+ void selectionChanged();
public Q_SLOTS:
void selectAll();
@@ -176,6 +198,9 @@ private Q_SLOTS:
void fontChanged();
void updateImgCache(const QRectF &rect);
void q_textChanged();
+ void updateSelectionMarkers();
+ void moveCursorDelegate();
+ void loadCursorDelegate();
private:
void updateSize();
diff --git a/src/declarative/fx/qfxtextedit_p.h b/src/declarative/fx/qfxtextedit_p.h
index f733a4c..b7d667e 100644
--- a/src/declarative/fx/qfxtextedit_p.h
+++ b/src/declarative/fx/qfxtextedit_p.h
@@ -69,8 +69,9 @@ class QFxTextEditPrivate : public QFxPaintedItemPrivate
public:
QFxTextEditPrivate()
: font(0), color("black"), imgDirty(true), hAlign(QFxTextEdit::AlignLeft), vAlign(QFxTextEdit::AlignTop),
- dirty(false), wrap(false), richText(false), cursorVisible(false), focusOnPress(false), preserveSelection(true),
- textMargin(0.0), format(QFxTextEdit::AutoText), document(0)
+ dirty(false), wrap(false), richText(false), cursorVisible(false), focusOnPress(false),
+ preserveSelection(true), textMargin(0.0), lastSelectionStart(0), lastSelectionEnd(0),
+ cursor(0), cursorComponent(0), format(QFxTextEdit::AutoText), document(0)
{
}
@@ -78,11 +79,13 @@ public:
void updateDefaultTextOption();
void relayoutDocument();
+ void updateSelection();
QString text;
QmlFont font;
QColor color;
QColor highlightColor;
+ QColor highlightedTextColor;
QString style;
QColor styleColor;
bool imgDirty;
@@ -100,6 +103,10 @@ public:
bool focusOnPress;
bool preserveSelection;
qreal textMargin;
+ int lastSelectionStart;
+ int lastSelectionEnd;
+ QmlComponent* cursorComponent;
+ QFxItem* cursor;
QFxTextEdit::TextFormat format;
QTextDocument *document;
QTextControl *control;
diff --git a/src/declarative/util/qmlanimation.cpp b/src/declarative/util/qmlanimation.cpp
index c0d6481..ff070c1 100644
--- a/src/declarative/util/qmlanimation.cpp
+++ b/src/declarative/util/qmlanimation.cpp
@@ -1436,11 +1436,11 @@ void QmlParallelAnimation::transition(QmlStateActions &actions,
QML_DEFINE_TYPE(QmlParallelAnimation,ParallelAnimation)
//convert a variant from string type to another animatable type
-//### should use any registered string convertor
-void QmlPropertyAnimationPrivate::convertVariant(QVariant &variant, QVariant::Type type)
+void QmlPropertyAnimationPrivate::convertVariant(QVariant &variant, int type)
{
if (variant.type() != QVariant::String) {
- variant.convert(type);
+ if ((uint)type < QVariant::UserType)
+ variant.convert((QVariant::Type)type);
return;
}
@@ -1474,7 +1474,12 @@ void QmlPropertyAnimationPrivate::convertVariant(QVariant &variant, QVariant::Ty
break;
}
default:
- variant.convert(type);
+ if ((uint)type >= QVariant::UserType) {
+ QmlMetaType::StringConverter converter = QmlMetaType::customStringConverter(type);
+ if (converter)
+ variant = converter(variant.toString());
+ } else
+ variant.convert((QVariant::Type)type);
break;
}
}
@@ -1722,7 +1727,7 @@ void QmlPropertyAnimationPrivate::valueChanged(qreal r)
if (!fromSourced) {
if (!fromIsDefined) {
from = property.read();
- convertVariant(from, (QVariant::Type)(interpolatorType ? interpolatorType : property.propertyType()));
+ convertVariant(from, interpolatorType ? interpolatorType : property.propertyType());
//### check for invalid variant if using property type
}
fromSourced = true;
@@ -1751,9 +1756,9 @@ void QmlPropertyAnimation::prepare(QmlMetaProperty &p)
d->property = d->userProperty;
int propType = d->property.propertyType();
- d->convertVariant(d->to, (QVariant::Type)(d->interpolatorType ? d->interpolatorType : propType));
+ d->convertVariant(d->to, d->interpolatorType ? d->interpolatorType : propType);
if (d->fromIsDefined)
- d->convertVariant(d->from, (QVariant::Type)(d->interpolatorType ? d->interpolatorType : propType));
+ d->convertVariant(d->from, d->interpolatorType ? d->interpolatorType : propType);
if (!d->interpolatorType) {
//### check for invalid variants
@@ -1795,7 +1800,7 @@ void QmlPropertyAnimation::transition(QmlStateActions &actions,
if (action.fromValue.isNull()) {
action.fromValue = action.property.read();
if (interpolatorType)
- QmlPropertyAnimationPrivate::convertVariant(action.fromValue, (QVariant::Type)interpolatorType);
+ QmlPropertyAnimationPrivate::convertVariant(action.fromValue, interpolatorType);
}
if (!interpolatorType) {
int propType = action.property.propertyType();
@@ -1856,8 +1861,8 @@ void QmlPropertyAnimation::transition(QmlStateActions &actions,
if (d->toIsDefined)
myAction.toValue = d->to;
- d->convertVariant(myAction.fromValue, (QVariant::Type)(d->interpolatorType ? d->interpolatorType : myAction.property.propertyType()));
- d->convertVariant(myAction.toValue, (QVariant::Type)(d->interpolatorType ? d->interpolatorType : myAction.property.propertyType()));
+ d->convertVariant(myAction.fromValue, d->interpolatorType ? d->interpolatorType : myAction.property.propertyType());
+ d->convertVariant(myAction.toValue, d->interpolatorType ? d->interpolatorType : myAction.property.propertyType());
modified << action.property;
@@ -1875,10 +1880,10 @@ void QmlPropertyAnimation::transition(QmlStateActions &actions,
continue;
if (d->fromIsDefined) {
- d->convertVariant(d->from, (QVariant::Type)(d->interpolatorType ? d->interpolatorType : myAction.property.propertyType()));
+ d->convertVariant(d->from, d->interpolatorType ? d->interpolatorType : myAction.property.propertyType());
myAction.fromValue = d->from;
}
- d->convertVariant(d->to, (QVariant::Type)(d->interpolatorType ? d->interpolatorType : myAction.property.propertyType()));
+ d->convertVariant(d->to, d->interpolatorType ? d->interpolatorType : myAction.property.propertyType());
myAction.toValue = d->to;
data->actions << myAction;
}
diff --git a/src/declarative/util/qmlanimation_p.h b/src/declarative/util/qmlanimation_p.h
index 00759e1..87d480f 100644
--- a/src/declarative/util/qmlanimation_p.h
+++ b/src/declarative/util/qmlanimation_p.h
@@ -346,7 +346,7 @@ public:
QmlTimeLineValueProxy<QmlPropertyAnimationPrivate> value;
static QVariant interpolateVariant(const QVariant &from, const QVariant &to, qreal progress);
- static void convertVariant(QVariant &variant, QVariant::Type type);
+ static void convertVariant(QVariant &variant, int type);
};
QT_END_NAMESPACE
diff --git a/src/declarative/util/qmlfollow.cpp b/src/declarative/util/qmlfollow.cpp
index c6d806a..b8e6685 100644
--- a/src/declarative/util/qmlfollow.cpp
+++ b/src/declarative/util/qmlfollow.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include <limits.h>
+#include <math.h>
#include <QtCore/qdebug.h>
#include "private/qobject_p.h"
#include "qmlfollow.h"
@@ -55,7 +56,7 @@ class QmlFollowPrivate : public QObjectPrivate
public:
QmlFollowPrivate()
: sourceValue(0), maxVelocity(0), lastTime(0)
- , mass(1.0), spring(0.), damping(0.), velocity(0), epsilon(0.005), enabled(true), mode(Track), clock(this) {}
+ , mass(1.0), spring(0.), damping(0.), velocity(0), epsilon(0.005), modulus(0.0), enabled(true), mode(Track), clock(this) {}
QmlMetaProperty property;
qreal currentValue;
@@ -68,6 +69,7 @@ public:
qreal damping;
qreal velocity;
qreal epsilon;
+ qreal modulus;
bool enabled;
enum Mode {
@@ -92,6 +94,11 @@ void QmlFollowPrivate::tick(int time)
int elapsed = time - lastTime;
if (!elapsed)
return;
+ qreal srcVal = sourceValue;
+ if (modulus != 0.0) {
+ currentValue = fmod(currentValue, modulus);
+ srcVal = fmod(srcVal, modulus);
+ }
if (mode == Spring) {
if (elapsed < 16) // capped at 62fps.
return;
@@ -99,7 +106,13 @@ void QmlFollowPrivate::tick(int time)
// We'll do something much simpler which gives a result that looks fine.
int count = (elapsed+8) / 16;
for (int i = 0; i < count; ++i) {
- qreal diff = sourceValue - currentValue;
+ qreal diff = srcVal - currentValue;
+ if (modulus != 0.0 && qAbs(diff) > modulus / 2) {
+ if (diff < 0)
+ diff += modulus;
+ else
+ diff -= modulus;
+ }
velocity = velocity + spring * diff - damping * velocity;
// The following line supports mass. Not sure its worth the extra divisions.
// velocity = velocity + spring / mass * diff - damping / mass * velocity;
@@ -111,24 +124,39 @@ void QmlFollowPrivate::tick(int time)
velocity = -maxVelocity;
}
currentValue += velocity * 16.0 / 1000.0;
+ if (modulus != 0.0) {
+ currentValue = fmod(currentValue, modulus);
+ if (currentValue < 0.0)
+ currentValue += modulus;
+ }
}
- if (qAbs(velocity) < epsilon && qAbs(sourceValue - currentValue) < epsilon) {
+ if (qAbs(velocity) < epsilon && qAbs(srcVal - currentValue) < epsilon) {
velocity = 0.0;
- currentValue = sourceValue;
+ currentValue = srcVal;
clock.stop();
}
lastTime = time - (elapsed - count * 16);
} else {
qreal moveBy = elapsed * velocityms;
- qreal diff = sourceValue - currentValue;
+ qreal diff = srcVal - currentValue;
+ if (modulus != 0.0 && qAbs(diff) > modulus / 2) {
+ if (diff < 0)
+ diff += modulus;
+ else
+ diff -= modulus;
+ }
if (diff > 0) {
currentValue += moveBy;
+ if (modulus != 0.0)
+ currentValue = fmod(currentValue, modulus);
if (currentValue > sourceValue) {
currentValue = sourceValue;
clock.stop();
}
} else {
currentValue -= moveBy;
+ if (modulus != 0.0 && currentValue < 0.0)
+ currentValue = fmod(currentValue, modulus) + modulus;
if (currentValue < sourceValue) {
currentValue = sourceValue;
clock.stop();
@@ -326,6 +354,25 @@ void QmlFollow::setEpsilon(qreal 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);
+ d->modulus = modulus;
+}
+
+/*!
\qmlproperty qreal Follow::followValue
The current value.
*/
diff --git a/src/declarative/util/qmlfollow.h b/src/declarative/util/qmlfollow.h
index 0953f2c..07e15e9 100644
--- a/src/declarative/util/qmlfollow.h
+++ b/src/declarative/util/qmlfollow.h
@@ -64,8 +64,10 @@ class Q_DECLARATIVE_EXPORT QmlFollow : public QmlPropertyValueSource,
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 followValue READ value NOTIFY valueChanged)
+ Q_PROPERTY(qreal modulus READ modulus WRITE setModulus NOTIFY modulusChanged)
public:
QmlFollow(QObject *parent=0);
@@ -83,6 +85,8 @@ public:
void setDamping(qreal damping);
qreal epsilon() const;
void setEpsilon(qreal epsilon);
+ qreal modulus() const;
+ void setModulus(qreal modulus);
bool enabled() const;
void setEnabled(bool enabled);