summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2009-10-01 03:25:49 (GMT)
committerAaron Kennedy <aaron.kennedy@nokia.com>2009-10-05 02:39:05 (GMT)
commit69c58d7e1c5713d1d6badeffc6c45eeacb1ba2d8 (patch)
treed060f3f7a76a7952f37196a2f50ad91b667a465d
parent99cf375f554fe01cf47fd4e1a291d4bba62b4018 (diff)
downloadQt-69c58d7e1c5713d1d6badeffc6c45eeacb1ba2d8.zip
Qt-69c58d7e1c5713d1d6badeffc6c45eeacb1ba2d8.tar.gz
Qt-69c58d7e1c5713d1d6badeffc6c45eeacb1ba2d8.tar.bz2
QmlMetaProperty cleanup
-rw-r--r--src/declarative/qml/qmlmetaproperty.cpp550
-rw-r--r--src/declarative/qml/qmlmetaproperty_p.h40
-rw-r--r--src/declarative/qml/qmlpropertycache.cpp55
-rw-r--r--src/declarative/qml/qmlpropertycache_p.h35
4 files changed, 348 insertions, 332 deletions
diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp
index fbe41dd..477377e 100644
--- a/src/declarative/qml/qmlmetaproperty.cpp
+++ b/src/declarative/qml/qmlmetaproperty.cpp
@@ -72,9 +72,7 @@ QmlMetaProperty::QmlMetaProperty()
d->q = this;
}
-/*!
- The destructor deletes its heap data.
- */
+/*! \internal */
QmlMetaProperty::~QmlMetaProperty()
{
delete d; d = 0;
@@ -114,11 +112,9 @@ void QmlMetaPropertyPrivate::initDefault(QObject *obj)
object = obj;
QMetaProperty p = QmlMetaType::defaultProperty(obj);
- name = QLatin1String(p.name());
- propType = p.userType();;
- coreIdx = p.propertyIndex();
- if (!name.isEmpty())
- type = QmlMetaProperty::Property | QmlMetaProperty::Default;
+ core.load(p);
+ if (core.isValid())
+ isDefaultProperty = true;
}
/*!
@@ -129,15 +125,12 @@ void QmlMetaPropertyPrivate::initDefault(QObject *obj)
QmlMetaProperty::QmlMetaProperty(QObject *obj, int idx, QmlContext *ctxt)
: d(new QmlMetaPropertyPrivate)
{
+ Q_ASSERT(obj);
+
d->q = this;
d->context = ctxt;
d->object = obj;
- d->type = Property;
- QMetaProperty p = obj->metaObject()->property(idx);
- d->propType = p.userType();
- d->coreIdx = idx;
- if (p.name() != 0)
- d->name = QLatin1String(p.name());
+ d->core.load(obj->metaObject()->property(idx));
}
/*!
@@ -168,7 +161,6 @@ void QmlMetaPropertyPrivate::initProperty(QObject *obj, const QString &name)
if (context && context->engine())
enginePrivate = QmlEnginePrivate::get(context->engine());
- this->name = name;
object = obj;
if (name.isEmpty() || !obj)
@@ -185,8 +177,6 @@ void QmlMetaPropertyPrivate::initProperty(QObject *obj, const QString &name)
enginePrivate->resolveType(typeData->imports, name.toLatin1(), &t, 0, 0, 0, 0);
if (t && t->attachedPropertiesFunction()) {
attachedFunc = t->index();
- if (attachedFunc != -1)
- type = QmlMetaProperty::Property | QmlMetaProperty::Attached;
}
typeData->release();
}
@@ -200,9 +190,9 @@ void QmlMetaPropertyPrivate::initProperty(QObject *obj, const QString &name)
QString signalName = name.mid(2);
signalName[0] = signalName.at(0).toLower();
- findSignalInt(obj, signalName);
- if (signal.signature() != 0) {
- type = QmlMetaProperty::SignalProperty;
+ QMetaMethod method = findSignal(obj, signalName);
+ if (method.signature()) {
+ core.load(method);
return;
}
}
@@ -218,18 +208,13 @@ void QmlMetaPropertyPrivate::initProperty(QObject *obj, const QString &name)
if (cache) {
QmlPropertyCache::Data *data = cache->property(name);
- if (data && !(data->flags & QmlPropertyCache::Data::IsFunction)) {
- type = QmlMetaProperty::Property;
- propType = data->propType;
- coreIdx = data->coreIndex;
- }
+ if (data && !(data->flags & QmlPropertyCache::Data::IsFunction))
+ core = *data;
+
} else {
- // Can't cache
+ // No cache available
QMetaProperty p = QmlMetaType::property(obj, name.toUtf8().constData());
- propType = p.userType();
- coreIdx = p.propertyIndex();
- if (p.name())
- type = QmlMetaProperty::Property;
+ core.load(p);
}
}
@@ -279,33 +264,31 @@ QmlMetaProperty::PropertyCategory QmlMetaProperty::propertyCategory() const
QmlMetaProperty::PropertyCategory
QmlMetaPropertyPrivate::propertyCategory() const
{
- if (category == QmlMetaProperty::Unknown) {
+ uint type = q->type();
+
+ if (type & QmlMetaProperty::ValueTypeProperty) {
+ return QmlMetaProperty::Normal;
+ } else if (type & QmlMetaProperty::Attached) {
+ return QmlMetaProperty::Object;
+ } else if (type & QmlMetaProperty::Property) {
int type = propertyType();
- if (type == QmlMetaProperty::Invalid)
- category = QmlMetaProperty::InvalidProperty;
- else if (type < QVariant::UserType)
- category = QmlMetaProperty::Normal;
+ if (type == QVariant::Invalid)
+ return QmlMetaProperty::InvalidProperty;
+ else if ((uint)type < QVariant::UserType)
+ return QmlMetaProperty::Normal;
else if (type == qMetaTypeId<QmlBinding *>())
- category = QmlMetaProperty::Bindable;
- else {
- QmlMetaType::TypeCategory tc = QmlMetaType::typeCategory(type);
- switch(tc) {
- case QmlMetaType::Object:
- category = QmlMetaProperty::Object;
- break;
- case QmlMetaType::QmlList:
- category = QmlMetaProperty::QmlList;
- break;
- case QmlMetaType::List:
- category = QmlMetaProperty::List;
- break;
- case QmlMetaType::Unknown:
- category = QmlMetaProperty::Normal;
- break;
- }
- }
+ return QmlMetaProperty::Bindable;
+ else if (core.flags & QmlPropertyCache::Data::IsQObjectDerived)
+ return QmlMetaProperty::Object;
+ else if (core.flags & QmlPropertyCache::Data::IsQmlList)
+ return QmlMetaProperty::QmlList;
+ else if (core.flags & QmlPropertyCache::Data::IsQList)
+ return QmlMetaProperty::List;
+ else
+ return QmlMetaProperty::Normal;
+ } else {
+ return QmlMetaProperty::InvalidProperty;
}
- return category;
}
/*!
@@ -314,8 +297,21 @@ QmlMetaPropertyPrivate::propertyCategory() const
*/
const char *QmlMetaProperty::propertyTypeName() const
{
- if (!d->name.isEmpty() && d->object) {
- return d->object->metaObject()->property(d->coreIdx).typeName();
+ if (type() & ValueTypeProperty) {
+
+ QmlEnginePrivate *ep = d->context?QmlEnginePrivate::get(d->context->engine()):0;
+ QmlValueType *valueType = 0;
+ if (ep) valueType = ep->valueTypes[d->core.propType];
+ else valueType = QmlValueTypeFactory::valueType(d->core.propType);
+ Q_ASSERT(valueType);
+
+ const char *rv = valueType->metaObject()->property(d->valueTypeCoreIdx).typeName();
+
+ if (!ep) delete valueType;
+
+ return rv;
+ } else if (d->object && type() & Property && d->core.isValid()) {
+ return d->object->metaObject()->property(d->core.coreIndex).typeName();
} else {
return 0;
}
@@ -327,10 +323,13 @@ const char *QmlMetaProperty::propertyTypeName() const
*/
bool QmlMetaProperty::operator==(const QmlMetaProperty &other) const
{
- return d->name == other.d->name &&
- d->signal.signature() == other.d->signal.signature() &&
- d->type == other.d->type &&
- d->object == other.d->object;
+ // category is intentially omitted here as it is generated
+ // from the other members
+ return d->object == other.d->object &&
+ d->core == other.d->core &&
+ d->valueTypeCoreIdx == other.d->valueTypeCoreIdx &&
+ d->valueTypePropType == other.d->valueTypePropType &&
+ d->attachedFunc == other.d->attachedFunc;
}
/*!
@@ -344,18 +343,19 @@ int QmlMetaProperty::propertyType() const
int QmlMetaPropertyPrivate::propertyType() const
{
- int rv = QVariant::Invalid;
-
- if (!name.isEmpty()) {
- if (propType == (int)QVariant::LastType)
- rv = qMetaTypeId<QVariant>();
+ uint type = q->type();
+ if (type & QmlMetaProperty::ValueTypeProperty) {
+ return valueTypePropType;
+ } else if (type & QmlMetaProperty::Attached) {
+ return qMetaTypeId<QObject *>();
+ } else if (type & QmlMetaProperty::Property) {
+ if (core.propType == (int)QVariant::LastType)
+ return qMetaTypeId<QVariant>();
else
- rv = propType;
- } else if (attachedFunc) {
- rv = qMetaTypeId<QObject *>();
- }
-
- return rv;
+ return core.propType;
+ } else {
+ return QVariant::Invalid;
+ }
}
/*!
@@ -363,7 +363,16 @@ int QmlMetaPropertyPrivate::propertyType() const
*/
QmlMetaProperty::Type QmlMetaProperty::type() const
{
- return (Type)d->type;
+ if (d->core.flags & QmlPropertyCache::Data::IsFunction)
+ return SignalProperty;
+ else if (d->attachedFunc != -1)
+ return Attached;
+ else if (d->valueTypeCoreIdx != -1)
+ return (Type)(Property | ValueTypeProperty);
+ else if (d->core.isValid())
+ return (Type)(Property | ((d->isDefaultProperty)?Default:0));
+ else
+ return Invalid;
}
/*!
@@ -395,17 +404,16 @@ QObject *QmlMetaProperty::object() const
*/
QmlMetaProperty &QmlMetaProperty::operator=(const QmlMetaProperty &other)
{
- d->name = other.d->name;
- d->signal = other.d->signal;
d->context = other.d->context;
- d->coreIdx = other.d->coreIdx;
- d->valueTypeIdx = other.d->valueTypeIdx;
- d->valueTypeId = other.d->valueTypeId;
- d->type = other.d->type;
- d->attachedFunc = other.d->attachedFunc;
d->object = other.d->object;
- d->propType = other.d->propType;
- d->category = other.d->category;
+
+ d->isDefaultProperty = other.d->isDefaultProperty;
+ d->core = other.d->core;
+
+ d->valueTypeCoreIdx = other.d->valueTypeCoreIdx;
+ d->valueTypePropType = other.d->valueTypePropType;
+
+ d->attachedFunc = other.d->attachedFunc;
return *this;
}
@@ -414,12 +422,14 @@ QmlMetaProperty &QmlMetaProperty::operator=(const QmlMetaProperty &other)
*/
bool QmlMetaProperty::isWritable() const
{
- if (propertyCategory() == List || propertyCategory() == QmlList)
+ QmlMetaProperty::PropertyCategory category = propertyCategory();
+
+ if (category == List || category == QmlList)
return true;
else if (type() & SignalProperty)
return true;
- else if (!d->name.isEmpty() && d->object)
- return d->object->metaObject()->property(d->coreIdx).isWritable();
+ else if (d->core.isValid() && d->object)
+ return d->object->metaObject()->property(d->core.coreIndex).isWritable();
else
return false;
}
@@ -429,8 +439,8 @@ bool QmlMetaProperty::isWritable() const
*/
bool QmlMetaProperty::isDesignable() const
{
- if (!d->name.isEmpty() && d->object)
- return d->object->metaObject()->property(d->coreIdx).isDesignable();
+ if (type() & Property && d->core.isValid() && d->object)
+ return d->object->metaObject()->property(d->core.coreIndex).isDesignable();
else
return false;
}
@@ -449,6 +459,7 @@ bool QmlMetaProperty::isValid() const
*/
QStringList QmlMetaProperty::properties(QObject *obj)
{
+ // ### What is this used for?
if (!obj)
return QStringList();
@@ -467,7 +478,23 @@ QStringList QmlMetaProperty::properties(QObject *obj)
*/
QString QmlMetaProperty::name() const
{
- return d->name;
+ if (type() & ValueTypeProperty) {
+ QString rv = d->core.name + QLatin1String(".");
+
+ QmlEnginePrivate *ep = d->context?QmlEnginePrivate::get(d->context->engine()):0;
+ QmlValueType *valueType = 0;
+ if (ep) valueType = ep->valueTypes[d->core.propType];
+ else valueType = QmlValueTypeFactory::valueType(d->core.propType);
+ Q_ASSERT(valueType);
+
+ rv += QLatin1String(valueType->metaObject()->property(d->valueTypeCoreIdx).name());
+
+ if (!ep) delete valueType;
+
+ return rv;
+ } else {
+ return d->core.name;
+ }
}
/*!
@@ -476,13 +503,26 @@ QString QmlMetaProperty::name() const
*/
QMetaProperty QmlMetaProperty::property() const
{
- if (d->object)
- return d->object->metaObject()->property(d->coreIdx);
+ if (type() & Property && d->core.isValid() && d->object)
+ return d->object->metaObject()->property(d->core.coreIndex);
else
return QMetaProperty();
}
/*!
+ Return the QMetaMethod for this property if it is a SignalProperty,
+ otherwise returns an invalid QMetaMethod.
+*/
+QMetaMethod QmlMetaProperty::method() const
+{
+ if (type() & SignalProperty && d->object)
+ return d->object->metaObject()->method(d->core.coreIndex);
+ else
+ return QMetaMethod();
+}
+
+
+/*!
Returns the binding associated with this property, or 0 if no binding
exists.
*/
@@ -495,13 +535,13 @@ QmlAbstractBinding *QmlMetaProperty::binding() const
if (!data)
return 0;
- if (!data->hasBindingBit(d->coreIdx))
+ if (!data->hasBindingBit(d->core.coreIndex))
return 0;
QmlAbstractBinding *binding = data->bindings;
while (binding) {
// ### This wont work for value types
- if (binding->propertyIndex() == d->coreIdx)
+ if (binding->propertyIndex() == d->core.coreIndex)
return binding;
binding = binding->m_nextBinding;
}
@@ -527,11 +567,11 @@ QmlMetaProperty::setBinding(QmlAbstractBinding *newBinding) const
QmlDeclarativeData *data =
QmlDeclarativeData::get(d->object, 0 != newBinding);
- if (data && data->hasBindingBit(d->coreIdx)) {
+ if (data && data->hasBindingBit(d->core.coreIndex)) {
QmlAbstractBinding *binding = data->bindings;
while (binding) {
// ### This wont work for value types
- if (binding->propertyIndex() == d->coreIdx) {
+ if (binding->propertyIndex() == d->core.coreIndex) {
binding->setEnabled(false);
if (newBinding)
@@ -594,15 +634,14 @@ QmlExpression *QmlMetaProperty::setSignalExpression(QmlExpression *expr) const
}
if (expr) {
- QmlBoundSignal *signal = new QmlBoundSignal(d->object, d->signal,
- d->object);
+ QmlBoundSignal *signal = new QmlBoundSignal(d->object, method(), d->object);
return signal->setExpression(expr);
} else {
return 0;
}
}
-void QmlMetaPropertyPrivate::findSignalInt(QObject *obj, const QString &name)
+QMetaMethod QmlMetaPropertyPrivate::findSignal(QObject *obj, const QString &name)
{
const QMetaObject *mo = obj->metaObject();
@@ -613,12 +652,10 @@ void QmlMetaPropertyPrivate::findSignalInt(QObject *obj, const QString &name)
int idx = methodName.indexOf(QLatin1Char('('));
methodName = methodName.left(idx);
- if (methodName == name) {
- signal = method;
- coreIdx = ii;
- return;
- }
+ if (methodName == name)
+ return method;
}
+ return QMetaMethod();
}
QObject *QmlMetaPropertyPrivate::attachedObject() const
@@ -643,7 +680,7 @@ QVariant QmlMetaProperty::read() const
for (int ii = 0; ii < children.count(); ++ii) {
QmlBoundSignal *sig = QmlBoundSignal::cast(children.at(ii));
- if (sig && sig->index() == d->coreIdx)
+ if (sig && sig->index() == d->core.coreIndex)
return sig->expression()->expression();
}
@@ -662,7 +699,7 @@ void QmlMetaPropertyPrivate::writeSignalProperty(const QVariant &value)
for (int ii = 0; ii < children.count(); ++ii) {
QmlBoundSignal *sig = QmlBoundSignal::cast(children.at(ii));
- if (sig && sig->index() == coreIdx) {
+ if (sig && sig->index() == core.coreIndex) {
if (expr.isEmpty()) {
sig->disconnect();
sig->deleteLater();
@@ -675,12 +712,13 @@ void QmlMetaPropertyPrivate::writeSignalProperty(const QVariant &value)
if (!expr.isEmpty()) {
// XXX scope
- (void *)new QmlBoundSignal(qmlContext(object), expr, object, signal, object);
+ (void *)new QmlBoundSignal(qmlContext(object), expr, object, q->method(), object);
}
}
QVariant QmlMetaPropertyPrivate::readValueProperty()
{
+ uint type = q->type();
if (type & QmlMetaProperty::Attached) {
return QVariant::fromValue(attachedObject());
@@ -689,22 +727,21 @@ QVariant QmlMetaPropertyPrivate::readValueProperty()
QmlEnginePrivate *ep = context?QmlEnginePrivate::get(context->engine()):0;
QmlValueType *valueType = 0;
- if (ep)
- valueType = ep->valueTypes[valueTypeId];
- else
- valueType = QmlValueTypeFactory::valueType(valueTypeId);
+ if (ep) valueType = ep->valueTypes[core.propType];
+ else valueType = QmlValueTypeFactory::valueType(core.propType);
Q_ASSERT(valueType);
- valueType->read(object, coreIdx);
+ valueType->read(object, core.coreIndex);
+
QVariant rv =
- valueType->metaObject()->property(valueTypeIdx).read(valueType);
- if (!ep)
- delete valueType;
+ valueType->metaObject()->property(valueTypeCoreIdx).read(valueType);
+
+ if (!ep) delete valueType;
return rv;
} else {
- return object->metaObject()->property(coreIdx).read(object.data());
+ return object->metaObject()->property(core.coreIndex).read(object.data());
}
}
@@ -712,40 +749,49 @@ QVariant QmlMetaPropertyPrivate::readValueProperty()
void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value,
QmlMetaProperty::WriteSource source)
{
- QObject *object = this->object;
- int coreIdx = this->coreIdx;
-
- QmlValueType *writeBack = 0;
- QObject *writeBackObj = 0;
- int writeBackIdx = -1;
- bool deleteWriteBack = false;
-
// Remove any existing bindings on this property
if (source != QmlMetaProperty::Binding)
delete q->setBinding(0);
+ uint type = q->type();
if (type & QmlMetaProperty::ValueTypeProperty) {
- QmlEnginePrivate *ep = context?static_cast<QmlEnginePrivate *>(QObjectPrivate::get(context->engine())):0;
+ QmlEnginePrivate *ep =
+ context?static_cast<QmlEnginePrivate *>(QObjectPrivate::get(context->engine())):0;
+ QmlValueType *writeBack = 0;
if (ep) {
- writeBack = ep->valueTypes[valueTypeId];
+ writeBack = ep->valueTypes[core.propType];
} else {
- writeBack = QmlValueTypeFactory::valueType(valueTypeId);
- deleteWriteBack = true;
+ writeBack = QmlValueTypeFactory::valueType(core.propType);
}
- writeBackObj = this->object;
- writeBackIdx = this->coreIdx;
- writeBack->read(writeBackObj, writeBackIdx);
- object = writeBack;
- coreIdx = valueTypeIdx;
+ writeBack->read(object, core.coreIndex);
+
+ QmlPropertyCache::Data data = core;
+ data.coreIndex = valueTypeCoreIdx;
+ data.propType = valueTypePropType;
+ write(writeBack, data, value, context);
+
+ writeBack->write(object, core.coreIndex);
+ if (!ep) delete writeBack;
+
+ } else {
+
+ write(object, core, value, context);
+
}
+}
- QMetaProperty prop = object->metaObject()->property(coreIdx);
+void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data &property,
+ const QVariant &value, QmlContext *context)
+{
+ int coreIdx = property.coreIndex;
- if (prop.isEnumType()) {
+ if (property.flags & QmlPropertyCache::Data::IsEnumType) {
+ QMetaProperty prop = object->metaObject()->property(property.coreIndex);
QVariant v = value;
- if (value.type() == QVariant::Double) { //enum values come through the script engine as doubles
+ // Enum values come through the script engine as doubles
+ if (value.type() == QVariant::Double) {
double integral;
double fractional = modf(value.toDouble(), &integral);
if (qFuzzyCompare(fractional, (double)0.0))
@@ -753,19 +799,36 @@ void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value,
}
prop.write(object, v);
- if (writeBack) {
- writeBack->write(writeBackObj, writeBackIdx);
- if (deleteWriteBack) delete writeBack;
- }
return;
}
- int t = propertyType();
+ int t = property.propType;
int vt = value.userType();
- int category = propertyCategory();
- if (vt == t
- && t != QVariant::Url) { // always resolve relative urls
+ if (t == QVariant::Url) {
+
+ QUrl u;
+ bool found = false;
+ if (vt == QVariant::Url) {
+ u = value.toUrl();
+ found = true;
+ } else if (vt == QVariant::ByteArray) {
+ u = QUrl(QLatin1String(value.toByteArray()));
+ found = true;
+ } else if (vt == QVariant::String) {
+ u = QUrl(value.toString());
+ found = true;
+ }
+
+ if (found) {
+ if (context && u.isRelative() && !u.isEmpty())
+ u = context->baseUrl().resolved(u);
+ void *a[1];
+ a[0] = &u;
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
+ }
+
+ } else if (vt == t) {
void *a[1];
a[0] = (void *)value.constData();
@@ -773,9 +836,11 @@ void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value,
} else if (qMetaTypeId<QVariant>() == t) {
- prop.write(object, value);
+ void *a[1];
+ a[0] = (void *)&value;
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
- } else if (category == QmlMetaProperty::Object) {
+ } else if (property.flags & QmlPropertyCache::Data::IsQObjectDerived) {
QObject *o = QmlMetaType::toQObject(value);
@@ -802,9 +867,10 @@ void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value,
}
- } else if (category == QmlMetaProperty::List) {
+ } else if (property.flags & QmlPropertyCache::Data::IsQList) {
int listType = QmlMetaType::listType(t);
+ QMetaProperty prop = object->metaObject()->property(property.coreIndex);
if (value.userType() == qMetaTypeId<QList<QObject *> >()) {
const QList<QObject *> &list =
@@ -822,9 +888,11 @@ void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value,
QmlMetaType::clear(listVar);
QmlMetaType::append(listVar, value);
}
- } else if (category == QmlMetaProperty::QmlList) {
+
+ } else if (property.flags & QmlPropertyCache::Data::IsQmlList) {
// XXX - optimize!
+ QMetaProperty prop = object->metaObject()->property(property.coreIndex);
QVariant list = prop.read(object);
QmlPrivate::ListInterface *li =
*(QmlPrivate::ListInterface **)list.constData();
@@ -854,118 +922,25 @@ void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value,
void *d = (void *)&obj;
li->append(d);
}
- } else if (category == QmlMetaProperty::Normal) {
-
- bool found = false;
- switch(t) {
- case QVariant::Double:
- {
- double d;
- if (vt == QVariant::Int) {
- d = value.toInt();
- found = true;
- } else if (vt == QVariant::UInt) {
- d = value.toUInt();
- found = true;
- }
-
- if (found) {
- void *a[1];
- a[0] = &d;
- QMetaObject::metacall(object,
- QMetaObject::WriteProperty,
- coreIdx, a);
- }
- }
- break;
-
- case QVariant::Int:
- {
- int i;
- if (vt == QVariant::Double) {
- i = (int)value.toDouble();
- found = true;
- } else if (vt == QVariant::UInt) {
- i = (int)value.toUInt();
- found = true;
- }
-
- if (found) {
- void *a[1];
- a[0] = &i;
- QMetaObject::metacall(object,
- QMetaObject::WriteProperty,
- coreIdx, a);
- }
- }
- break;
-
- case QVariant::String:
- {
- QString s;
- if (vt == QVariant::ByteArray) {
- s = QLatin1String(value.toByteArray());
- found = true;
- }
-
- if (found) {
- void *a[1];
- a[0] = &s;
- QMetaObject::metacall(object,
- QMetaObject::WriteProperty,
- coreIdx, a);
- }
- }
- break;
-
- case QVariant::Url:
- {
- QUrl u;
- if (vt == QVariant::Url) {
- u = value.toUrl();
- found = true;
- } else if (vt == QVariant::ByteArray) {
- u = QUrl(QLatin1String(value.toByteArray()));
- found = true;
- } else if (vt == QVariant::String) {
- u = QUrl(value.toString());
- found = true;
- }
+ } else {
+ Q_ASSERT(vt != t);
- if (found) {
- if (context && u.isRelative() && !u.isEmpty())
- u = context->baseUrl().resolved(u);
+ QVariant v = value;
+ if (v.convert((QVariant::Type)t)) {
+ void *a[1];
+ a[0] = (void *)v.constData();
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
+ } else if ((uint)t >= QVariant::UserType && vt == QVariant::String) {
+ QmlMetaType::StringConverter con = QmlMetaType::customStringConverter(t);
+ if (con) {
+ QVariant v = con(value.toString());
+ if (v.userType() == t) {
void *a[1];
- a[0] = &u;
- QMetaObject::metacall(object,
- QMetaObject::WriteProperty,
- coreIdx, a);
+ a[0] = (void *)v.constData();
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
}
-
}
- break;
-
-
- default:
- {
- if ((uint)t >= QVariant::UserType && vt == QVariant::String) {
- QmlMetaType::StringConverter con = QmlMetaType::customStringConverter(t);
- if (con) {
- QVariant v = con(value.toString());
- prop.write(object, v);
- found = true;
- }
- }
- }
- break;
}
- if (!found)
- prop.write(object, value);
- }
-
- if (writeBack) {
- writeBack->write(writeBackObj, writeBackIdx);
- if (deleteWriteBack) delete writeBack;
}
}
@@ -986,7 +961,7 @@ void QmlMetaProperty::write(const QVariant &value, WriteSource source) const
d->writeSignalProperty(value);
- } else if (d->coreIdx != -1) {
+ } else if (d->core.isValid()) {
d->writeValueProperty(value, source);
@@ -999,7 +974,7 @@ void QmlMetaProperty::write(const QVariant &value, WriteSource source) const
bool QmlMetaProperty::hasChangedNotifier() const
{
if (type() & Property && !(type() & Attached) && d->object) {
- return d->object->metaObject()->property(d->coreIdx).hasNotifySignal();
+ return d->object->metaObject()->property(d->core.coreIndex).hasNotifySignal();
}
return false;
}
@@ -1030,7 +1005,7 @@ bool QmlMetaProperty::connectNotifier(QObject *dest, int method) const
if (!(type() & Property) || (type() & Attached) || !d->object)
return false;
- QMetaProperty prop = d->object->metaObject()->property(d->coreIdx);
+ QMetaProperty prop = d->object->metaObject()->property(d->core.coreIndex);
if (prop.hasNotifySignal()) {
return QMetaObject::connect(d->object, prop.notifySignalIndex(), dest, method, Qt::DirectConnection);
} else {
@@ -1051,7 +1026,7 @@ bool QmlMetaProperty::connectNotifier(QObject *dest, const char *slot) const
if (!(type() & Property) || (type() & Attached) || !d->object)
return false;
- QMetaProperty prop = d->object->metaObject()->property(d->coreIdx);
+ QMetaProperty prop = d->object->metaObject()->property(d->core.coreIndex);
if (prop.hasNotifySignal()) {
QByteArray signal(QByteArray("2") + prop.notifySignal().signature());
return QObject::connect(d->object, signal.constData(), dest, slot);
@@ -1065,7 +1040,7 @@ bool QmlMetaProperty::connectNotifier(QObject *dest, const char *slot) const
*/
int QmlMetaProperty::coreIndex() const
{
- return d->coreIdx;
+ return d->core.coreIndex;
}
Q_GLOBAL_STATIC(QmlValueTypeFactory, qmlValueTypes);
@@ -1080,17 +1055,17 @@ quint32 QmlMetaProperty::save() const
if (type() & Attached) {
rv = d->attachedFunc;
} else if (type() != Invalid) {
- rv = d->coreIdx;
+ rv = d->core.coreIndex;
}
Q_ASSERT(rv <= 0x7FF);
Q_ASSERT(type() <= 0x3F);
- Q_ASSERT(d->valueTypeIdx <= 0x7F);
+ Q_ASSERT(d->valueTypeCoreIdx <= 0x7F);
rv |= (type() << 18);
if (type() & ValueTypeProperty)
- rv |= (d->valueTypeIdx << 11);
+ rv |= (d->valueTypeCoreIdx << 11);
return rv;
}
@@ -1131,12 +1106,12 @@ void QmlMetaProperty::restore(quint32 id, QObject *obj, QmlContext *ctxt)
d->context = ctxt;
id &= 0xFFFFFF;
- d->type = id >> 18;
+ uint type = id >> 18;
id &= 0xFFFF;
- if (d->type & Attached) {
+ if (type & Attached) {
d->attachedFunc = id;
- } else if (d->type & ValueTypeProperty) {
+ } else if (type & ValueTypeProperty) {
int coreIdx = id & 0x7FF;
int valueTypeIdx = id >> 11;
@@ -1147,46 +1122,31 @@ void QmlMetaProperty::restore(quint32 id, QObject *obj, QmlContext *ctxt)
QMetaProperty p2(valueType->metaObject()->property(valueTypeIdx));
- d->name = QLatin1String(p2.name());
- d->propType = p2.userType();
- d->coreIdx = coreIdx;
- d->valueTypeIdx = valueTypeIdx;
- d->valueTypeId = p.type();
-
- } else if (d->type & Property) {
+ d->core.load(p);
+ d->valueTypeCoreIdx = valueTypeIdx;
+ d->valueTypePropType = p.userType();
+ } else if (type & Property) {
QmlPropertyCache *cache = enginePrivate?enginePrivate->cache(obj):0;
- d->coreIdx = id;
-
if (cache) {
QmlPropertyCache::Data *data = cache->property(id);
- d->propType = data->propType;
- d->name = data->name;
+ if (data) d->core = *data;
} else {
QMetaProperty p(obj->metaObject()->property(id));
- d->name = QLatin1String(p.name());
- d->propType = p.userType();
+ d->core.load(p);
}
- } else if (d->type & SignalProperty) {
- d->signal = obj->metaObject()->method(id);
- d->coreIdx = id;
+ } else if (type & SignalProperty) {
+
+ QMetaMethod method = obj->metaObject()->method(id);
+ d->core.load(method);
} else {
*this = QmlMetaProperty();
}
}
/*!
- Return the QMetaMethod for this property if it is a SignalProperty,
- otherwise returns an invalid QMetaMethod.
-*/
-QMetaMethod QmlMetaProperty::method() const
-{
- return d->signal;
-}
-
-/*!
\internal
Creates a QmlMetaProperty for the property \a name of \a obj. Unlike
@@ -1213,17 +1173,11 @@ QmlMetaProperty QmlMetaProperty::createProperty(QObject *obj,
int idx = typeObject->metaObject()->indexOfProperty(path.last().toUtf8().constData());
if (idx == -1)
return QmlMetaProperty();
+ QMetaProperty vtProp = typeObject->metaObject()->property(idx);
- QmlMetaProperty p;
- p.d->name = pathName + QLatin1String(".") + path.last();
- p.d->context = 0;
- p.d->coreIdx = prop.coreIndex();
- p.d->valueTypeIdx = idx;
- p.d->valueTypeId = prop.propertyType();
- p.d->type = QmlMetaProperty::ValueTypeProperty |
- QmlMetaProperty::Property;
- p.d->object = obj;
- p.d->propType = typeObject->metaObject()->property(idx).userType();
+ QmlMetaProperty p = prop;
+ p.d->valueTypeCoreIdx = idx;
+ p.d->valueTypePropType = vtProp.userType();
return p;
}
diff --git a/src/declarative/qml/qmlmetaproperty_p.h b/src/declarative/qml/qmlmetaproperty_p.h
index 3193aaf..729236b 100644
--- a/src/declarative/qml/qmlmetaproperty_p.h
+++ b/src/declarative/qml/qmlmetaproperty_p.h
@@ -54,7 +54,8 @@
//
#include "qmlmetaproperty.h"
-#include "private/qobject_p.h"
+#include <private/qobject_p.h>
+#include <private/qmlpropertycache_p.h>
QT_BEGIN_NAMESPACE
@@ -63,36 +64,34 @@ class QmlMetaPropertyPrivate
{
public:
QmlMetaPropertyPrivate()
- : q(0), context(0), coreIdx(-1), valueTypeIdx(-1), valueTypeId(0),
- type(QmlMetaProperty::Invalid), attachedFunc(-1),
- object(0), propType(-1), category(QmlMetaProperty::Unknown) {}
+ : q(0), context(0), object(0), isDefaultProperty(false), valueTypeCoreIdx(-1),
+ valueTypePropType(0), attachedFunc(-1) {}
+
QmlMetaPropertyPrivate(const QmlMetaPropertyPrivate &other)
- : q(0), name(other.name), signal(other.signal), context(other.context),
- coreIdx(other.coreIdx), valueTypeIdx(other.valueTypeIdx),
- valueTypeId(other.valueTypeId), type(other.type),
- attachedFunc(other.attachedFunc), object(other.object),
- propType(other.propType), category(other.category) {}
+ : q(0), context(other.context), object(other.object),
+ isDefaultProperty(other.isDefaultProperty), core(other.core),
+ valueTypeCoreIdx(other.valueTypeCoreIdx),
+ valueTypePropType(other.valueTypePropType), attachedFunc(other.attachedFunc) {}
QmlMetaProperty *q;
-
- QString name;
- QMetaMethod signal;
QmlContext *context;
- int coreIdx;
- int valueTypeIdx;
- int valueTypeId;
- uint type;
- int attachedFunc;
QGuard<QObject> object;
- int propType;
- mutable QmlMetaProperty::PropertyCategory category;
+ bool isDefaultProperty;
+ QmlPropertyCache::Data core;
+
+ // Describes the "virtual" value-type sub-property.
+ int valueTypeCoreIdx; // The prop index of the access property on the value type wrapper
+ int valueTypePropType; // The QVariant::Type of access property on the value type wrapper
+
+ // The attached property accessor
+ int attachedFunc;
void initProperty(QObject *obj, const QString &name);
void initDefault(QObject *obj);
QObject *attachedObject() const;
- void findSignalInt(QObject *, const QString &);
+ QMetaMethod findSignal(QObject *, const QString &);
int propertyType() const;
QmlMetaProperty::PropertyCategory propertyCategory() const;
@@ -101,6 +100,7 @@ public:
QVariant readValueProperty();
void writeValueProperty(const QVariant &, QmlMetaProperty::WriteSource);
+ static void write(QObject *, const QmlPropertyCache::Data &, const QVariant &, QmlContext *);
static quint32 saveValueType(int, int);
static quint32 saveProperty(int);
diff --git a/src/declarative/qml/qmlpropertycache.cpp b/src/declarative/qml/qmlpropertycache.cpp
index 95b819a..7d234fd 100644
--- a/src/declarative/qml/qmlpropertycache.cpp
+++ b/src/declarative/qml/qmlpropertycache.cpp
@@ -40,10 +40,48 @@
****************************************************************************/
#include "qmlpropertycache_p.h"
-#include "qmlengine_p.h"
+#include <private/qmlengine_p.h>
+#include <QtDeclarative/qmlbinding.h>
QT_BEGIN_NAMESPACE
+void QmlPropertyCache::Data::load(const QMetaProperty &p)
+{
+ propType = p.userType();
+ coreIndex = p.propertyIndex();
+ notifyIndex = p.notifySignalIndex();
+ name = QLatin1String(p.name());
+
+ if (p.isConstant())
+ flags |= Data::IsConstant;
+
+ if (propType == qMetaTypeId<QmlBinding *>()) {
+ flags |= Data::IsQmlBinding;
+ } else if (p.isEnumType()) {
+ flags |= Data::IsEnumType;
+ } else {
+ QmlMetaType::TypeCategory cat = QmlMetaType::typeCategory(propType);
+ if (cat == QmlMetaType::Object)
+ flags |= Data::IsQObjectDerived;
+ else if (cat == QmlMetaType::List)
+ flags |= Data::IsQList;
+ else if (cat == QmlMetaType::QmlList)
+ flags |= Data::IsQmlList;
+ }
+}
+
+void QmlPropertyCache::Data::load(const QMetaMethod &m)
+{
+ name = QLatin1String(m.signature());
+ int parenIdx = name.indexOf(QLatin1Char('('));
+ Q_ASSERT(parenIdx != -1);
+ name = name.left(parenIdx);
+
+ coreIndex = m.methodIndex();
+ flags |= Data::IsFunction;
+}
+
+
QmlPropertyCache::QmlPropertyCache()
{
}
@@ -83,15 +121,7 @@ QmlPropertyCache *QmlPropertyCache::create(QmlEngine *engine, const QMetaObject
QScriptDeclarativeClass::PersistentIdentifier<RData> *data =
enginePriv->objectClass->createPersistentIdentifier<RData>(propName);
- data->propType = p.userType();
- data->coreIndex = ii;
- data->notifyIndex = p.notifySignalIndex();
- data->name = propName;
-
- if (p.isConstant())
- data->flags |= Data::IsConstant;
- if (QmlMetaType::isObject(data->propType))
- data->flags |= Data::IsQObjectDerived;
+ data->load(p);
cache->indexCache[ii] = data;
@@ -118,12 +148,13 @@ QmlPropertyCache *QmlPropertyCache::create(QmlEngine *engine, const QMetaObject
QScriptDeclarativeClass::PersistentIdentifier<RData> *data =
enginePriv->objectClass->createPersistentIdentifier<RData>(methodName);
+
+ data->load(m);
+
cache->stringCache.insert(methodName, data);
cache->identifierCache.insert(data->identifier, data);
data->addref();
data->addref();
-
- data->flags |= Data::IsFunction;
}
return cache;
diff --git a/src/declarative/qml/qmlpropertycache_p.h b/src/declarative/qml/qmlpropertycache_p.h
index 21c8ef3..149d2a0 100644
--- a/src/declarative/qml/qmlpropertycache_p.h
+++ b/src/declarative/qml/qmlpropertycache_p.h
@@ -69,18 +69,40 @@ public:
struct Data {
inline Data();
+ inline bool operator==(const Data &);
- enum Flag { IsFunction = 0x00000001,
+ enum Flag {
+ // Can apply to all properties, except IsFunction
+ IsConstant = 0x00000004,
+
+ // These are mutually exclusive
+ IsFunction = 0x00000001,
IsQObjectDerived = 0x00000002,
- IsConstant = 0x00000004 };
+ IsEnumType = 0x00000008,
+ IsQmlList = 0x00000010,
+ IsQList = 0x00000020,
+ IsQmlBinding = 0x00000040
+ };
Q_DECLARE_FLAGS(Flags, Flag)
+ bool isValid() const { return coreIndex != -1; }
+
Flags flags;
int propType;
int coreIndex;
int notifyIndex;
QString name;
+
+ void load(const QMetaProperty &);
+ void load(const QMetaMethod &);
+ };
+
+#if 0
+ struct ValueTypeData {
+ int valueTypeCoreIdx; // The prop index of the access property on the value type wrapper
+ int valueTypePropType; // The QVariant::Type of access property on the value type wrapper
};
+#endif
static QmlPropertyCache *create(QmlEngine *, const QMetaObject *);
@@ -106,6 +128,15 @@ QmlPropertyCache::Data::Data()
{
}
+bool QmlPropertyCache::Data::operator==(const QmlPropertyCache::Data::Data &other)
+{
+ return flags == other.flags &&
+ propType == other.propType &&
+ coreIndex == other.coreIndex &&
+ notifyIndex == other.notifyIndex &&
+ name == other.name;
+}
+
QmlPropertyCache::Data *
QmlPropertyCache::property(const QScriptDeclarativeClass::Identifier &id) const
{