summaryrefslogtreecommitdiffstats
path: root/src/declarative/qml/qmlmetaproperty.cpp
diff options
context:
space:
mode:
authorMichael Brasser <michael.brasser@nokia.com>2009-04-22 04:47:24 (GMT)
committerMichael Brasser <michael.brasser@nokia.com>2009-04-22 04:47:24 (GMT)
commit2366667fc97eb6a56203b2dd7dac776ff4164abd (patch)
treeb2acb6cc6bfe475d7e619e4788973b61fff775e0 /src/declarative/qml/qmlmetaproperty.cpp
parent2c762f3b8b284a7c6dc0c499b7052013bad5b707 (diff)
downloadQt-2366667fc97eb6a56203b2dd7dac776ff4164abd.zip
Qt-2366667fc97eb6a56203b2dd7dac776ff4164abd.tar.gz
Qt-2366667fc97eb6a56203b2dd7dac776ff4164abd.tar.bz2
Initial import of kinetic-dui branch from the old kinetic
Diffstat (limited to 'src/declarative/qml/qmlmetaproperty.cpp')
-rw-r--r--src/declarative/qml/qmlmetaproperty.cpp847
1 files changed, 847 insertions, 0 deletions
diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp
new file mode 100644
index 0000000..79db6ce
--- /dev/null
+++ b/src/declarative/qml/qmlmetaproperty.cpp
@@ -0,0 +1,847 @@
+/****************************************************************************
+**
+** 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 "qmlmetaproperty.h"
+#include "qmlmetaproperty_p.h"
+#include <qml.h>
+#include <qfxperf.h>
+#include <QStringList>
+#include <qmlbindablevalue.h>
+#include <qmlcontext.h>
+#include "qmlboundsignal_p.h"
+#include <math.h>
+#include <QtCore/qdebug.h>
+
+
+QT_BEGIN_NAMESPACE
+
+class QMetaPropertyEx : public QMetaProperty
+{
+public:
+ QMetaPropertyEx()
+ : propertyType(-1) {}
+
+ QMetaPropertyEx(const QMetaProperty &p)
+ : QMetaProperty(p), propertyType(p.userType()) {}
+
+ QMetaPropertyEx(const QMetaPropertyEx &o)
+ : QMetaProperty(o),
+ propertyType(o.propertyType) {}
+
+ QMetaPropertyEx &operator=(const QMetaPropertyEx &o)
+ {
+ static_cast<QMetaProperty *>(this)->operator=(o);
+ propertyType = o.propertyType;
+ return *this;
+ }
+
+ private:
+ friend class QmlMetaProperty;
+ int propertyType;
+};
+
+
+/*!
+ \class QmlMetaProperty
+ \brief The QmlMetaProperty class abstracts accessing QML properties.
+ */
+
+/*!
+ Create an invalid QmlMetaProperty.
+*/
+QmlMetaProperty::QmlMetaProperty()
+: d(new QmlMetaPropertyPrivate)
+{
+}
+
+QmlMetaProperty::~QmlMetaProperty()
+{
+ delete d; d = 0;
+}
+
+// ### not thread safe
+static QHash<const QMetaObject *, QMetaPropertyEx> qmlCacheDefProp;
+
+/*!
+ Creates a QmlMetaProperty for the default property of \a obj. If there is no
+ default property, an invalid QmlMetaProperty will be created.
+ */
+QmlMetaProperty::QmlMetaProperty(QObject *obj, QmlContext *ctxt)
+: d(new QmlMetaPropertyPrivate)
+{
+ d->context = ctxt;
+ if(!obj)
+ return;
+
+ d->object = obj;
+ QHash<const QMetaObject *, QMetaPropertyEx>::ConstIterator iter =
+ qmlCacheDefProp.find(obj->metaObject());
+ if(iter != qmlCacheDefProp.end()) {
+ d->prop = *iter;
+ d->propType = iter->propertyType;
+ d->coreIdx = iter->propertyType;
+ } else {
+ QMetaPropertyEx p(QmlMetaType::defaultProperty(obj));
+ d->prop = p;
+ d->propType = p.propertyType;
+ d->coreIdx = d->prop.propertyIndex();
+ if(!QObjectPrivate::get(obj)->metaObject)
+ qmlCacheDefProp.insert(obj->metaObject(), d->prop);
+ }
+ if(d->prop.name() != 0) {
+ d->type = Property | Default;
+ d->name = QLatin1String(d->prop.name());
+ }
+}
+
+/*!
+ \internal
+
+ Creates a QmlMetaProperty for the property at index \a idx of \a obj.
+
+ The QmlMetaProperty is assigned category \a cat.
+ */
+QmlMetaProperty::QmlMetaProperty(QObject *obj, int idx, PropertyCategory cat, QmlContext *ctxt)
+: d(new QmlMetaPropertyPrivate)
+{
+ d->context = ctxt;
+ d->object = obj;
+ d->type = Property;
+ d->category = cat;
+ QMetaPropertyEx p(obj->metaObject()->property(idx));
+ d->prop = p;
+ d->propType = p.propertyType;
+ d->coreIdx = idx;
+ if(d->prop.name() != 0)
+ d->name = QLatin1String(d->prop.name());
+}
+
+// ### Not thread safe!!!!
+static QHash<const QMetaObject *, QHash<QString, QMetaPropertyEx> > qmlCacheProps;
+/*!
+ Creates a QmlMetaProperty for the property \a name of \a obj.
+ */
+QmlMetaProperty::QmlMetaProperty(QObject *obj, const QString &name, QmlContext *ctxt)
+: d(new QmlMetaPropertyPrivate)
+{
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::MetaProperty> perf;
+#endif
+
+ d->context = ctxt;
+ d->name = name;
+ d->object = obj;
+ if(name.isEmpty() || !obj)
+ return;
+
+ if(name.at(0).isUpper()) {
+ // Attached property
+ d->attachedFunc = QmlMetaType::attachedPropertiesFuncId(name.toLatin1());
+ if(d->attachedFunc != -1)
+ d->type = Property | Attached;
+ return;
+ } else if(name.count() >= 3 && name.startsWith(QLatin1String("on")) && name.at(2).isUpper()) {
+ // Signal
+ QString signalName = name.mid(2);
+ signalName[0] = signalName.at(0).toLower();
+
+ d->findSignalInt(obj, signalName);
+ if(d->signal.signature() != 0) {
+ d->type = SignalProperty;
+ return;
+ }
+ }
+
+ // Property
+ QHash<QString, QMetaPropertyEx> &props = qmlCacheProps[obj->metaObject()];
+ QHash<QString, QMetaPropertyEx>::ConstIterator iter = props.find(name);
+ if(iter != props.end()) {
+ d->prop = *iter;
+ d->propType = iter->propertyType;
+ d->coreIdx = iter->propertyIndex();
+ } else {
+ QMetaPropertyEx p = QmlMetaType::property(obj, name.toLatin1().constData());
+ d->prop = p;
+ d->propType = p.propertyType;
+ d->coreIdx = p.propertyIndex();
+ if (!QObjectPrivate::get(obj)->metaObject)
+ props.insert(name, p);
+ }
+ if(d->prop.name() != 0)
+ d->type = Property;
+
+ if(d->type == Invalid) {
+ int sig = findSignal(obj, name.toLatin1());
+ if(sig != -1) {
+ d->signal = obj->metaObject()->method(sig);
+ d->type = Signal;
+ d->coreIdx = sig;
+ }
+ }
+}
+
+/*!
+ Create a copy of \a other.
+*/
+QmlMetaProperty::QmlMetaProperty(const QmlMetaProperty &other)
+: d(new QmlMetaPropertyPrivate(*other.d))
+{
+}
+
+/*!
+ Returns the property category.
+*/
+QmlMetaProperty::PropertyCategory QmlMetaProperty::propertyCategory() const
+{
+ if(d->category == Unknown) {
+ int type = propertyType();
+ if(!isValid())
+ d->category = InvalidProperty;
+ else if(type == qMetaTypeId<QmlBindableValue *>())
+ d->category = Bindable;
+ else if(QmlMetaType::isList(type))
+ d->category = List;
+ else if(QmlMetaType::isQmlList(type))
+ d->category = QmlList;
+ else if(QmlMetaType::isObject(type))
+ d->category = Object;
+ else
+ d->category = Normal;
+ }
+ return d->category;
+}
+
+/*!
+ Returns the property category of \a prop.
+*/
+QmlMetaProperty::PropertyCategory
+QmlMetaProperty::propertyCategory(const QMetaProperty &prop)
+{
+ if(prop.name()) {
+ int type = 0;
+ if(prop.type() == QVariant::LastType)
+ type = qMetaTypeId<QVariant>();
+ else if(prop.type() == QVariant::UserType)
+ type = prop.userType();
+ else
+ type = prop.type();
+
+ if(type == qMetaTypeId<QmlBindableValue *>())
+ return Bindable;
+ else if(QmlMetaType::isList(type))
+ return List;
+ else if(QmlMetaType::isQmlList(type))
+ return QmlList;
+ else if(QmlMetaType::isObject(type))
+ return Object;
+ else
+ return Normal;
+ } else {
+ return InvalidProperty;
+ }
+}
+
+/*!
+ Returns the type name of the property, or 0 if the property has no type
+ name.
+*/
+const char *QmlMetaProperty::propertyTypeName() const
+{
+ if(d->prop.name()) {
+ return d->prop.typeName();
+ } else {
+ return 0;
+ }
+}
+
+/*!
+ Returns true if \a other and this QmlMetaProperty represent the same
+ property.
+*/
+bool QmlMetaProperty::operator==(const QmlMetaProperty &other) const
+{
+ return d->prop.name() == other.d->prop.name() &&
+ d->signal.signature() == other.d->signal.signature() &&
+ d->type == other.d->type &&
+ d->object == other.d->object;
+}
+
+/*!
+ Returns the QVariant type of the property, or QVariant::Invalid if the
+ property has no QVariant type.
+*/
+int QmlMetaProperty::propertyType() const
+{
+ int rv = QVariant::Invalid;
+
+ if(d->prop.name()) {
+ if(d->propType == (int)QVariant::LastType)
+ rv = qMetaTypeId<QVariant>();
+ else
+ rv = d->propType;
+ } else if(d->attachedFunc) {
+ rv = qMetaTypeId<QObject *>();
+ }
+
+ return rv;
+}
+
+/*!
+ Returns the type of the property.
+*/
+QmlMetaProperty::Type QmlMetaProperty::type() const
+{
+ return (Type)d->type;
+}
+
+/*!
+ Returns true if this QmlMetaProperty represents a regular Qt property.
+*/
+bool QmlMetaProperty::isProperty() const
+{
+ return type() & Property;
+}
+
+/*!
+ Returns true if this QmlMetaProperty represents a default property.
+*/
+bool QmlMetaProperty::isDefault() const
+{
+ return type() & Default;
+}
+
+/*!
+ Returns the QmlMetaProperty's QObject.
+*/
+QObject *QmlMetaProperty::object() const
+{
+ return d->object;
+}
+
+/*!
+ Assign \a other to this QmlMetaProperty.
+*/
+QmlMetaProperty &QmlMetaProperty::operator=(const QmlMetaProperty &other)
+{
+ d->name = other.d->name;
+ d->prop = other.d->prop;
+ d->propType = other.d->propType;
+ d->type = other.d->type;
+ d->signal = other.d->signal;
+ d->coreIdx = other.d->coreIdx;
+ d->attachedFunc = other.d->attachedFunc;
+ d->object = other.d->object;
+ d->category = other.d->category;
+ return *this;
+}
+
+/*!
+ Returns true if the property is writable, otherwise false.
+*/
+bool QmlMetaProperty::isWritable() const
+{
+ if(propertyCategory() == List || propertyCategory() == QmlList)
+ return true;
+ else if(d->prop.name() != 0)
+ return d->prop.isWritable();
+ else if(type() & SignalProperty)
+ return true;
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property is designable, otherwise false.
+*/
+bool QmlMetaProperty::isDesignable() const
+{
+ if(d->prop.name() != 0)
+ return d->prop.isDesignable();
+ else
+ return false;
+}
+
+/*!
+ Returns true if the QmlMetaProperty refers to a valid property, otherwise
+ false.
+*/
+bool QmlMetaProperty::isValid() const
+{
+ return type() != Invalid;
+}
+
+/*!
+ Returns all of \a obj's Qt properties.
+*/
+QStringList QmlMetaProperty::properties(QObject *obj)
+{
+ if(!obj)
+ return QStringList();
+
+ QStringList rv;
+ const QMetaObject *mo = obj->metaObject();
+ for(int ii = 0; ii < mo->propertyCount(); ++ii) {
+ QMetaProperty prop = mo->property(ii);
+ rv << QLatin1String(prop.name());
+ }
+
+ return rv;
+}
+
+/*!
+ Return the name of this property.
+*/
+QString QmlMetaProperty::name() const
+{
+ return d->name;
+}
+
+const QMetaProperty &QmlMetaProperty::property() const
+{
+ return d->prop;
+}
+
+/*!
+ Returns the binding associated with this property, or 0 if no binding
+ exists.
+*/
+QmlBindableValue *QmlMetaProperty::binding()
+{
+ if(!isProperty() || type() & Attached)
+ return 0;
+
+ const QObjectList &children = object()->children();
+ for(QObjectList::ConstIterator iter = children.begin();
+ iter != children.end(); ++iter) {
+ QObject *child = *iter;
+ if(child->metaObject() == &QmlBindableValue::staticMetaObject) {
+ QmlBindableValue *v = static_cast<QmlBindableValue *>(child);
+ if(v->property() == *this)
+ return v;
+ }
+ }
+ return 0;
+}
+
+/*! \internal */
+int QmlMetaProperty::findSignal(const QObject *obj, const char *name)
+{
+ const QMetaObject *mo = obj->metaObject();
+ int methods = mo->methodCount();
+ for(int ii = 0; ii < methods; ++ii) {
+ QMetaMethod method = mo->method(ii);
+ if(method.methodType() != QMetaMethod::Signal)
+ continue;
+
+ QByteArray methodName = method.signature();
+ int idx = methodName.indexOf('(');
+ methodName = methodName.left(idx);
+
+ if(methodName == name)
+ return ii;
+ }
+ return -1;
+}
+
+void QmlMetaPropertyPrivate::findSignalInt(QObject *obj, const QString &name)
+{
+ const QMetaObject *mo = obj->metaObject();
+
+ int methods = mo->methodCount();
+ for(int ii = 0; ii < methods; ++ii) {
+ QMetaMethod method = mo->method(ii);
+ QString methodName = QLatin1String(method.signature());
+ int idx = methodName.indexOf(QLatin1Char('('));
+ methodName = methodName.left(idx);
+
+ if(methodName == name) {
+ signal = method;
+ coreIdx = ii;
+ return;
+ }
+ }
+}
+
+QObject *QmlMetaPropertyPrivate::attachedObject() const
+{
+ if(attachedFunc == -1)
+ return 0;
+ else
+ return QmlMetaType::attachedPropertiesFuncById(attachedFunc)(object);
+}
+
+/*!
+ Returns the property value.
+*/
+QVariant QmlMetaProperty::read() const
+{
+ if(type() & SignalProperty) {
+
+ const QObjectList &children = object()->children();
+
+ for(int ii = 0; ii < children.count(); ++ii) {
+ QmlBoundSignal *sig = qobject_cast<QmlBoundSignal *>(children.at(ii));
+ if(sig && sig->index() == d->coreIdx)
+ return sig->expression();
+ }
+ } else if(type() & Property) {
+ if(type() & Attached)
+ return QVariant::fromValue(d->attachedObject());
+ else
+ return d->prop.read(object());
+ }
+ return QVariant();
+}
+
+Q_DECLARE_METATYPE(QList<QObject *>);
+/*!
+ Set the property value to \a value.
+*/
+void QmlMetaProperty::write(const QVariant &value) const
+{
+ if(type() & SignalProperty) {
+
+ QString expr = value.toString();
+ const QObjectList &children = object()->children();
+
+ for(int ii = 0; ii < children.count(); ++ii) {
+ QmlBoundSignal *sig = qobject_cast<QmlBoundSignal *>(children.at(ii));
+ if(sig && sig->index() == d->coreIdx) {
+ if(expr.isEmpty()) {
+ sig->disconnect();
+ sig->deleteLater();
+ } else {
+ sig->setExpression(expr);
+ }
+ return;
+ }
+ }
+
+ if(!expr.isEmpty()) {
+ // XXX scope
+ (void *)new QmlBoundSignal(QmlContext::activeContext(), expr, object(), d->coreIdx, object());
+ }
+
+ } else if(d->prop.name()) {
+
+ if(d->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);
+ }
+ d->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, d->coreIdx, a);
+
+ } else if(qMetaTypeId<QVariant>() == t) {
+
+ d->prop.write(object(), value);
+
+ } else if(propertyCategory() == Object) {
+
+ QObject *o = QmlMetaType::toQObject(value);
+ if(o)
+ d->prop.write(object(), QmlMetaType::fromObject(o, propertyType()));
+
+ } else if (propertyCategory() == List) {
+
+ int listType = QmlMetaType::listType(t);
+ if(value.userType() == qMetaTypeId<QList<QObject *> >()) {
+ const QList<QObject *> &list =
+ qvariant_cast<QList<QObject *> >(value);
+ QVariant listVar = d->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 = d->prop.read(object());
+ if (!QmlMetaType::append(listVar, value)) {
+ qWarning() << "QmlMetaProperty: Unable to assign object to list";
+ }
+ }
+ } else if (propertyCategory() == QmlList) {
+ // XXX - optimize!
+ QVariant list = d->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() == 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(found) {
+ void *a[1];
+ a[0] = &r;
+ QMetaObject::metacall(object(),
+ QMetaObject::WriteProperty,
+ d->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,
+ d->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,
+ d->coreIdx, a);
+ return;
+ }
+ }
+ break;
+
+
+ default:
+ break;
+ }
+ d->prop.write(object(), value);
+ }
+
+ }
+ }
+}
+
+/*!
+ Returns true if the property has a change notifier signal, otherwise false.
+*/
+bool QmlMetaProperty::hasChangedNotifier() const
+{
+ if(type() & Property && !(type() & Attached)) {
+ return d->prop.hasNotifySignal();
+ }
+ return false;
+}
+
+/*!
+ Connect the property's change notifier signal to the \a dest \a method.
+*/
+bool QmlMetaProperty::connectNotifier(QObject *dest, int method) const
+{
+ if(!(type() & Property) || type() & Attached)
+ return false;
+
+ if(d->prop.hasNotifySignal()) {
+ return QMetaObject::connect(d->object, d->prop.notifySignalIndex(), dest, method, Qt::DirectConnection);
+ } else {
+ return false;
+ }
+}
+
+/*!
+ Connect the property's change notifier signal to the \a dest \a slot.
+*/
+bool QmlMetaProperty::connectNotifier(QObject *dest, const char *slot) const
+{
+ if(!(type() & Property) || type() & Attached)
+ return false;
+
+ if(d->prop.hasNotifySignal()) {
+ QByteArray signal(QByteArray("2") + d->prop.notifySignal().signature());
+ return QObject::connect(d->object, signal.constData(), dest, slot);
+ } else {
+ return false;
+ }
+}
+
+/*! \internal */
+void QmlMetaProperty::emitSignal()
+{
+ if(type() & Signal) {
+ if(d->signal.parameterTypes().isEmpty())
+ d->object->metaObject()->activate(d->object, d->coreIdx, 0);
+ else
+ qWarning() << "QmlMetaProperty: Cannot emit signal with parameters";
+ }
+}
+
+/*!
+ Return the Qt metaobject index of the property.
+*/
+int QmlMetaProperty::coreIndex() const
+{
+ return d->coreIdx;
+}
+
+/*!
+ Returns the property information serialized into a single integer.
+ QmlMetaProperty uses the bottom 24 bits only.
+*/
+quint32 QmlMetaProperty::save() const
+{
+ quint32 rv = 0;
+ if(type() & Attached) {
+ rv = d->attachedFunc;
+ } else if(type() != Invalid) {
+ rv = d->coreIdx;
+ }
+
+ Q_ASSERT(rv <= 0xFFFF);
+ Q_ASSERT(type() <= 0xFF);
+ rv |= (type() << 16);
+
+ return rv;
+}
+
+/*!
+ Restore a QmlMetaProperty from a previously saved id. \a obj must be the
+ same object as used in the previous call to QmlMetaProperty::save(). Only
+ the bottom 24-bits are used, the high bits can be set to any value.
+*/
+void QmlMetaProperty::restore(quint32 id, QObject *obj)
+{
+ *this = QmlMetaProperty();
+ d->object = obj;
+
+ id &= 0xFFFFFF;
+ d->type = id >> 16;
+ id &= 0xFFFF;
+
+ if(d->type & Attached) {
+ d->attachedFunc = id;
+ } else if(d->type & Property) {
+ QMetaPropertyEx p(obj->metaObject()->property(id));
+ d->prop = p;
+ d->propType = p.propertyType;
+ d->coreIdx = id;
+ } else if(d->type & SignalProperty || d->type & Signal) {
+ d->signal = obj->metaObject()->method(id);
+ d->coreIdx = id;
+ }
+}
+
+/*!
+ Return the QMetaMethod for this property if it is a SignalProperty,
+ otherwise returns an invalid QMetaMethod.
+*/
+QMetaMethod QmlMetaProperty::method() const
+{
+ return d->signal;
+}
+
+QT_END_NAMESPACE