diff options
author | Aaron Kennedy <aaron.kennedy@nokia.com> | 2009-07-09 07:25:58 (GMT) |
---|---|---|
committer | Aaron Kennedy <aaron.kennedy@nokia.com> | 2009-07-09 07:25:58 (GMT) |
commit | 883da42f7c75775502c818aa456c8576d8457ff8 (patch) | |
tree | b8d8c963f76c38baa9c684fe2a9d2537df02ef16 /src/declarative | |
parent | 8a6e5d5c95a8ae586c8fc2fa63be0228c4cefb53 (diff) | |
parent | 3399066881c42d1dd6fda6b3ae8cf3fc8961929b (diff) | |
download | Qt-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.cpp | 221 | ||||
-rw-r--r-- | src/declarative/fx/qfxtextedit.h | 27 | ||||
-rw-r--r-- | src/declarative/fx/qfxtextedit_p.h | 11 | ||||
-rw-r--r-- | src/declarative/util/qmlanimation.cpp | 29 | ||||
-rw-r--r-- | src/declarative/util/qmlanimation_p.h | 2 | ||||
-rw-r--r-- | src/declarative/util/qmlfollow.cpp | 57 | ||||
-rw-r--r-- | src/declarative/util/qmlfollow.h | 4 |
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); |