From fbc927101b8b01b30d5b776e79511165eb1bf2e1 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 23 Apr 2009 14:26:37 +1000 Subject: Split up QmlMetaProperty::write() method --- src/declarative/qml/qmlmetaproperty.cpp | 250 +++++++++++++++++++++++++++----- src/declarative/qml/qmlmetaproperty_p.h | 8 + 2 files changed, 225 insertions(+), 33 deletions(-) diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index 79db6ce..30e0bbc 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -231,22 +231,28 @@ QmlMetaProperty::QmlMetaProperty(const QmlMetaProperty &other) */ QmlMetaProperty::PropertyCategory QmlMetaProperty::propertyCategory() const { - if(d->category == Unknown) { + return d->propertyCategory(); +} + +QmlMetaProperty::PropertyCategory +QmlMetaPropertyPrivate::propertyCategory() const +{ + if(category == QmlMetaProperty::Unknown) { int type = propertyType(); - if(!isValid()) - d->category = InvalidProperty; + if(type == QmlMetaProperty::Invalid) + category = QmlMetaProperty::InvalidProperty; else if(type == qMetaTypeId()) - d->category = Bindable; + category = QmlMetaProperty::Bindable; else if(QmlMetaType::isList(type)) - d->category = List; + category = QmlMetaProperty::List; else if(QmlMetaType::isQmlList(type)) - d->category = QmlList; + category = QmlMetaProperty::QmlList; else if(QmlMetaType::isObject(type)) - d->category = Object; + category = QmlMetaProperty::Object; else - d->category = Normal; + category = QmlMetaProperty::Normal; } - return d->category; + return category; } /*! @@ -310,14 +316,19 @@ bool QmlMetaProperty::operator==(const QmlMetaProperty &other) const */ int QmlMetaProperty::propertyType() const { + return d->propertyType(); +} + +int QmlMetaPropertyPrivate::propertyType() const +{ int rv = QVariant::Invalid; - if(d->prop.name()) { - if(d->propType == (int)QVariant::LastType) + if(prop.name()) { + if(propType == (int)QVariant::LastType) rv = qMetaTypeId(); else - rv = d->propType; - } else if(d->attachedFunc) { + rv = propType; + } else if(attachedFunc) { rv = qMetaTypeId(); } @@ -532,34 +543,207 @@ QVariant QmlMetaProperty::read() const } Q_DECLARE_METATYPE(QList); -/*! - Set the property value to \a value. -*/ -void QmlMetaProperty::write(const QVariant &value) const + +void QmlMetaPropertyPrivate::writeSignalProperty(const QVariant &value) { - if(type() & SignalProperty) { + QString expr = value.toString(); + const QObjectList &children = object->children(); + + for(int ii = 0; ii < children.count(); ++ii) { + QmlBoundSignal *sig = qobject_cast(children.at(ii)); + if(sig && sig->index() == coreIdx) { + if(expr.isEmpty()) { + sig->disconnect(); + sig->deleteLater(); + } else { + sig->setExpression(expr); + } + return; + } + } - QString expr = value.toString(); - const QObjectList &children = object()->children(); + if(!expr.isEmpty()) { + // XXX scope + (void *)new QmlBoundSignal(QmlContext::activeContext(), expr, object, + coreIdx, object); + } +} - for(int ii = 0; ii < children.count(); ++ii) { - QmlBoundSignal *sig = qobject_cast(children.at(ii)); - if(sig && sig->index() == d->coreIdx) { - if(expr.isEmpty()) { - sig->disconnect(); - sig->deleteLater(); - } else { - sig->setExpression(expr); +void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value) +{ + if(prop.isEnumType()) { + QVariant v = value; + if (value.type() == QVariant::Double) { //enum values come through the script engine as doubles + double integral; + double fractional = modf(value.toDouble(), &integral); + if (qFuzzyCompare(fractional, (double)0.0)) + v.convert(QVariant::Int); + } + prop.write(object, v); + } else { + if(!value.isValid()) + return; + + int t = propertyType(); + int vt = value.type(); + + if(vt == t || + value.userType() == t) { + + void *a[1]; + a[0] = (void *)value.constData(); + QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a); + + } else if(qMetaTypeId() == t) { + + prop.write(object, value); + + } else if(propertyCategory() == QmlMetaProperty::Object) { + + QObject *o = QmlMetaType::toQObject(value); + if(o) + prop.write(object, QmlMetaType::fromObject(o, propertyType())); + + } else if (propertyCategory() == QmlMetaProperty::List) { + + int listType = QmlMetaType::listType(t); + if(value.userType() == qMetaTypeId >()) { + const QList &list = + qvariant_cast >(value); + QVariant listVar = prop.read(object); + QmlMetaType::clear(listVar); + for(int ii = 0; ii < list.count(); ++ii) { + QVariant v = QmlMetaType::fromObject(list.at(ii), listType); + QmlMetaType::append(listVar, v); + } + + } else if(vt == listType || + value.userType() == listType) { + QVariant listVar = prop.read(object); + if (!QmlMetaType::append(listVar, value)) { + qWarning() << "QmlMetaProperty: Unable to assign object to list"; } - return; } - } + } else if (propertyCategory() == QmlMetaProperty::QmlList) { + // XXX - optimize! + QVariant list = prop.read(object); + QmlPrivate::ListInterface *li = + *(QmlPrivate::ListInterface **)list.constData(); + + int type = li->type(); + + if (QObject *obj = QmlMetaType::toQObject(value)) { + const QMetaObject *mo = + QmlMetaType::rawMetaObjectForType(type); + + const QMetaObject *objMo = obj->metaObject(); + bool found = false; + while(!found && objMo) { + if(objMo == mo) + found = true; + else + objMo = objMo->superClass(); + } + + if(!found) { + qWarning() << "Unable to assign object to list"; + return; + } + + // NOTE: This assumes a cast to QObject does not alter + // the object pointer + void *d = (void *)&obj; + li->append(d); + } + } else if(propertyCategory() == QmlMetaProperty::Normal) { + + switch(t) { + case QVariant::Double: + { + qreal r; + bool found = true; + if(vt == QVariant::Int) { + r = value.toInt(); + } else if(vt == QVariant::UInt) { + r = value.toUInt(); + } else { + found = false; + } - if(!expr.isEmpty()) { - // XXX scope - (void *)new QmlBoundSignal(QmlContext::activeContext(), expr, object(), d->coreIdx, object()); + if(found) { + void *a[1]; + a[0] = &r; + QMetaObject::metacall(object, + QMetaObject::WriteProperty, + coreIdx, a); + return; + } + } + break; + + case QVariant::Int: + { + int i; + bool found = true; + if(vt == QVariant::Double) { + i = (int)value.toDouble(); + } else if(vt == QVariant::UInt) { + i = (int)value.toUInt(); + } else { + found = false; + } + + if(found) { + void *a[1]; + a[0] = &i; + QMetaObject::metacall(object, + QMetaObject::WriteProperty, + coreIdx, a); + return; + } + } + break; + + case QVariant::String: + { + QString s; + bool found = true; + if(vt == QVariant::ByteArray) { + s = QLatin1String(value.toByteArray()); + } else { + found = false; + } + + if(found) { + void *a[1]; + a[0] = &s; + QMetaObject::metacall(object, + QMetaObject::WriteProperty, + coreIdx, a); + return; + } + } + break; + + + default: + break; + } + prop.write(object, value); } + } +} + +/*! + Set the property value to \a value. +*/ +void QmlMetaProperty::write(const QVariant &value) const +{ + if(type() & SignalProperty) { + + d->writeSignalProperty(value); + } else if(d->prop.name()) { if(d->prop.isEnumType()) { diff --git a/src/declarative/qml/qmlmetaproperty_p.h b/src/declarative/qml/qmlmetaproperty_p.h index 5c13f5e..1ea38e9 100644 --- a/src/declarative/qml/qmlmetaproperty_p.h +++ b/src/declarative/qml/qmlmetaproperty_p.h @@ -42,6 +42,8 @@ #ifndef QMLMETAPROPERTY_P_H #define QMLMETAPROPERTY_P_H +#include "qmlmetaproperty.h" + class QmlContext; class QmlMetaPropertyPrivate { @@ -69,6 +71,12 @@ public: QObject *attachedObject() const; void findSignalInt(QObject *, const QString &); + + int propertyType() const; + QmlMetaProperty::PropertyCategory propertyCategory() const; + + void writeSignalProperty(const QVariant &); + void writeValueProperty(const QVariant &); }; #endif // QMLMETAPROPERTY_P_H -- cgit v0.12 From 161cf1f17eabd87e46c2056af731174e930883dd Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 23 Apr 2009 16:52:07 +1000 Subject: Add a Follow::followValue property --- src/declarative/util/qmlfollow.cpp | 16 ++++++++++++++++ src/declarative/util/qmlfollow.h | 6 ++++++ 2 files changed, 22 insertions(+) diff --git a/src/declarative/util/qmlfollow.cpp b/src/declarative/util/qmlfollow.cpp index c841b85..01d8962 100644 --- a/src/declarative/util/qmlfollow.cpp +++ b/src/declarative/util/qmlfollow.cpp @@ -52,6 +52,7 @@ QML_DEFINE_TYPE(QmlFollow,Follow); class QmlFollowPrivate : public QObjectPrivate { + Q_DECLARE_PUBLIC(QmlFollow) public: QmlFollowPrivate() : sourceValue(0), maxVelocity(0), lastTime(0) @@ -86,6 +87,8 @@ public: void QmlFollowPrivate::tick(int time) { + Q_Q(QmlFollow); + int elapsed = time - lastTime; if (!elapsed) return; @@ -133,6 +136,7 @@ void QmlFollowPrivate::tick(int time) } lastTime = time; } + emit q->valueChanged(currentValue); property.write(currentValue); } @@ -288,6 +292,11 @@ void QmlFollow::setDamping(qreal damping) } /*! + \qmlproperty qreal Follow::followValue + The current value. +*/ + +/*! \qmlproperty bool Follow::enabled This property holds whether the target will track the source. */ @@ -306,4 +315,11 @@ void QmlFollow::setEnabled(bool enabled) else d->stop(); } + +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 index a609305..aac4c01 100644 --- a/src/declarative/util/qmlfollow.h +++ b/src/declarative/util/qmlfollow.h @@ -65,6 +65,7 @@ class Q_DECLARATIVE_EXPORT QmlFollow : public QmlPropertyValueSource, Q_PROPERTY(qreal damping READ damping WRITE setDamping); Q_PROPERTY(bool enabled READ enabled WRITE setEnabled); + Q_PROPERTY(qreal followValue READ value NOTIFY valueChanged); public: QmlFollow(QObject *parent=0); ~QmlFollow(); @@ -81,6 +82,11 @@ public: void setDamping(qreal damping); bool enabled() const; void setEnabled(bool enabled); + + qreal value() const; + +Q_SIGNALS: + void valueChanged(qreal); }; QML_DECLARE_TYPE(QmlFollow); -- cgit v0.12 From c0979cc534e9204edc04759b7b6bef7d6980c466 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 24 Apr 2009 10:13:14 +1000 Subject: Don't access internal QMetaProperty members We can use the new QMetaProperty::propertyIndex() method instead. --- src/declarative/qml/qmlengine.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index 63f45b4..b42480d 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -39,11 +39,7 @@ ** ****************************************************************************/ -// XXX ;) -#define private public #include -#undef private - #include #include @@ -308,7 +304,7 @@ bool QmlEnginePrivate::fetchCache(QmlBasicScriptNodeCache &cache, const QString cache.object = obj; cache.type = QmlBasicScriptNodeCache::Core; - cache.core = prop.property().idx + prop.property().mobj->propertyOffset(); + cache.core = prop.property().propertyIndex(); cache.coreType = prop.propertyType(); return true; -- cgit v0.12 From 728e1e1c3678768aafeb07ebe8e17dd2fbf047b2 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 24 Apr 2009 11:09:39 +1000 Subject: Don't manually stack children on GraphicsView GraphicsView now has a sane default stacking order. --- src/declarative/canvas/qsimplecanvasitem.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/declarative/canvas/qsimplecanvasitem.cpp b/src/declarative/canvas/qsimplecanvasitem.cpp index 5e4b5fa..7d9f61c 100644 --- a/src/declarative/canvas/qsimplecanvasitem.cpp +++ b/src/declarative/canvas/qsimplecanvasitem.cpp @@ -626,12 +626,8 @@ void QSimpleCanvasItem::addChild(QSimpleCanvasItem *c) { Q_D(QSimpleCanvasItem); d->children.append(c); - if(d->graphicsItem) { - // XXX - GraphicsView does not preserve the stacking order of items - c->setZ(d->children.count()); - } else { + if(!d->graphicsItem) d->needsZOrder = true; - } childrenChanged(); } -- cgit v0.12 From 19a507c5cc8c178a0e00fa302f6315c4b18b50a5 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 24 Apr 2009 11:18:54 +1000 Subject: Ensure -ve z stacks behind parent when using GraphicsView --- src/declarative/canvas/qsimplecanvasitem.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/declarative/canvas/qsimplecanvasitem.cpp b/src/declarative/canvas/qsimplecanvasitem.cpp index 7d9f61c..95f7623 100644 --- a/src/declarative/canvas/qsimplecanvasitem.cpp +++ b/src/declarative/canvas/qsimplecanvasitem.cpp @@ -443,7 +443,16 @@ void QSimpleCanvasItem::setZ(qreal z) return; if(d->graphicsItem) { + + if(z < 0) + d->graphicsItem->setFlag(QGraphicsItem::ItemStacksBehindParent, + true); + else + d->graphicsItem->setFlag(QGraphicsItem::ItemStacksBehindParent, + false); + d->graphicsItem->setZValue(z); + } else { if(d->data()->z == z) return; -- cgit v0.12