diff options
Diffstat (limited to 'src/declarative/qml/qdeclarativeproperty.cpp')
-rw-r--r-- | src/declarative/qml/qdeclarativeproperty.cpp | 1917 |
1 files changed, 0 insertions, 1917 deletions
diff --git a/src/declarative/qml/qdeclarativeproperty.cpp b/src/declarative/qml/qdeclarativeproperty.cpp deleted file mode 100644 index 7ba801d72f..0000000000 --- a/src/declarative/qml/qdeclarativeproperty.cpp +++ /dev/null @@ -1,1917 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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.1, 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qdeclarativeproperty.h" -#include "qdeclarativeproperty_p.h" - -#include "qdeclarative.h" -#include "qdeclarativebinding_p.h" -#include "qdeclarativecontext.h" -#include "qdeclarativecontext_p.h" -#include "qdeclarativeboundsignal_p.h" -#include "qdeclarativeengine.h" -#include "qdeclarativeengine_p.h" -#include "qdeclarativedata_p.h" -#include "qdeclarativestringconverters_p.h" -#include "qdeclarativelist_p.h" -#include "qdeclarativecompiler_p.h" -#include "qdeclarativevmemetaobject_p.h" -#include "qdeclarativeexpression_p.h" - -#include <QStringList> -#include <QtCore/qdebug.h> - -#include <math.h> - -Q_DECLARE_METATYPE(QList<int>) -Q_DECLARE_METATYPE(QList<qreal>) -Q_DECLARE_METATYPE(QList<bool>) -Q_DECLARE_METATYPE(QList<QString>) -Q_DECLARE_METATYPE(QList<QUrl>) - -QT_BEGIN_NAMESPACE - -/*! -\class QDeclarativeProperty -\since 4.7 -\brief The QDeclarativeProperty class abstracts accessing properties on objects created from QML. - -As QML uses Qt's meta-type system all of the existing QMetaObject classes can be used to introspect -and interact with objects created by QML. However, some of the new features provided by QML - such -as type safety and attached properties - are most easily used through the QDeclarativeProperty class -that simplifies some of their natural complexity. - -Unlike QMetaProperty which represents a property on a class type, QDeclarativeProperty encapsulates -a property on a specific object instance. To read a property's value, programmers create a -QDeclarativeProperty instance and call the read() method. Likewise to write a property value the -write() method is used. - -For example, for the following QML code: - -\qml -// MyItem.qml -import QtQuick 2.0 - -Text { text: "A bit of text" } -\endqml - -The \l Text object's properties could be accessed using QDeclarativeProperty, like this: - -\code -#include <QDeclarativeProperty> -#include <QGraphicsObject> - -... - -QDeclarativeView view(QUrl::fromLocalFile("MyItem.qml")); -QDeclarativeProperty property(view.rootObject(), "font.pixelSize"); -qWarning() << "Current pixel size:" << property.read().toInt(); -property.write(24); -qWarning() << "Pixel size should now be 24:" << property.read().toInt(); -\endcode -*/ - -/*! - Create an invalid QDeclarativeProperty. -*/ -QDeclarativeProperty::QDeclarativeProperty() -: d(0) -{ -} - -/*! \internal */ -QDeclarativeProperty::~QDeclarativeProperty() -{ - if (d) - d->release(); - d = 0; -} - -/*! - Creates a QDeclarativeProperty for the default property of \a obj. If there is no - default property, an invalid QDeclarativeProperty will be created. - */ -QDeclarativeProperty::QDeclarativeProperty(QObject *obj) -: d(new QDeclarativePropertyPrivate) -{ - d->initDefault(obj); -} - -/*! - Creates a QDeclarativeProperty for the default property of \a obj - using the \l{QDeclarativeContext} {context} \a ctxt. If there is - no default property, an invalid QDeclarativeProperty will be - created. - */ -QDeclarativeProperty::QDeclarativeProperty(QObject *obj, QDeclarativeContext *ctxt) -: d(new QDeclarativePropertyPrivate) -{ - d->context = ctxt?QDeclarativeContextData::get(ctxt):0; - d->engine = ctxt?ctxt->engine():0; - d->initDefault(obj); -} - -/*! - Creates a QDeclarativeProperty for the default property of \a obj - using the environment for instantiating QML components that is - provided by \a engine. If there is no default property, an - invalid QDeclarativeProperty will be created. - */ -QDeclarativeProperty::QDeclarativeProperty(QObject *obj, QDeclarativeEngine *engine) - : d(new QDeclarativePropertyPrivate) -{ - d->context = 0; - d->engine = engine; - d->initDefault(obj); -} - -/*! - Initialize from the default property of \a obj -*/ -void QDeclarativePropertyPrivate::initDefault(QObject *obj) -{ - if (!obj) - return; - - QMetaProperty p = QDeclarativeMetaType::defaultProperty(obj); - core.load(p); - if (core.isValid()) - object = obj; -} - -/*! - Creates a QDeclarativeProperty for the property \a name of \a obj. - */ -QDeclarativeProperty::QDeclarativeProperty(QObject *obj, const QString &name) -: d(new QDeclarativePropertyPrivate) -{ - d->initProperty(obj, name); - if (!isValid()) d->object = 0; -} - -/*! - Creates a QDeclarativeProperty for the property \a name of \a obj - using the \l{QDeclarativeContext} {context} \a ctxt. - - Creating a QDeclarativeProperty without a context will render some - properties - like attached properties - inaccessible. -*/ -QDeclarativeProperty::QDeclarativeProperty(QObject *obj, const QString &name, QDeclarativeContext *ctxt) -: d(new QDeclarativePropertyPrivate) -{ - d->context = ctxt?QDeclarativeContextData::get(ctxt):0; - d->engine = ctxt?ctxt->engine():0; - d->initProperty(obj, name); - if (!isValid()) { d->object = 0; d->context = 0; d->engine = 0; } -} - -/*! - Creates a QDeclarativeProperty for the property \a name of \a obj - using the environment for instantiating QML components that is - provided by \a engine. - */ -QDeclarativeProperty::QDeclarativeProperty(QObject *obj, const QString &name, QDeclarativeEngine *engine) -: d(new QDeclarativePropertyPrivate) -{ - d->context = 0; - d->engine = engine; - d->initProperty(obj, name); - if (!isValid()) { d->object = 0; d->context = 0; d->engine = 0; } -} - -Q_GLOBAL_STATIC(QDeclarativeValueTypeFactory, qmlValueTypes); - -QDeclarativePropertyPrivate::QDeclarativePropertyPrivate() -: context(0), engine(0), object(0), isNameCached(false) -{ -} - -QDeclarativeContextData *QDeclarativePropertyPrivate::effectiveContext() const -{ - if (context) return context; - else if (engine) return QDeclarativeContextData::get(engine->rootContext()); - else return 0; -} - -void QDeclarativePropertyPrivate::initProperty(QObject *obj, const QString &name) -{ - if (!obj) return; - - QDeclarativeTypeNameCache *typeNameCache = context?context->imports:0; - - QStringList path = name.split(QLatin1Char('.')); - if (path.isEmpty()) return; - - QObject *currentObject = obj; - - // Everything up to the last property must be an "object type" property - for (int ii = 0; ii < path.count() - 1; ++ii) { - const QString &pathName = path.at(ii); - - if (typeNameCache) { - QDeclarativeTypeNameCache::Result r = typeNameCache->query(pathName); - if (r.isValid()) { - if (r.type) { - QDeclarativeAttachedPropertiesFunc func = r.type->attachedPropertiesFunction(); - if (!func) return; // Not an attachable type - - currentObject = qmlAttachedPropertiesObjectById(r.type->attachedPropertiesId(), currentObject); - if (!currentObject) return; // Something is broken with the attachable type - } else if (r.importNamespace) { - if ((ii + 1) == path.count()) return; // No type following the namespace - - ++ii; r = typeNameCache->query(path.at(ii), r.importNamespace); - if (!r.type) return; // Invalid type in namespace - - QDeclarativeAttachedPropertiesFunc func = r.type->attachedPropertiesFunction(); - if (!func) return; // Not an attachable type - - currentObject = qmlAttachedPropertiesObjectById(r.type->attachedPropertiesId(), currentObject); - if (!currentObject) return; // Something is broken with the attachable type - - } else if (r.scriptIndex != -1) { - return; // Not a type - } else { - Q_ASSERT(!"Unreachable"); - } - continue; - } - - } - - QDeclarativePropertyData local; - QDeclarativePropertyData *property = - QDeclarativePropertyCache::property(engine, obj, pathName, local); - - if (!property) return; // Not a property - if (property->isFunction()) - return; // Not an object property - - if (ii == (path.count() - 2) && QDeclarativeValueTypeFactory::isValueType(property->propType)) { - // We're now at a value type property. We can use a global valuetypes array as we - // never actually use the objects, just look up their properties. - QObject *typeObject = (*qmlValueTypes())[property->propType]; - if (!typeObject) return; // Not a value type - - int idx = typeObject->metaObject()->indexOfProperty(path.last().toUtf8().constData()); - if (idx == -1) return; // Value type property does not exist - - QMetaProperty vtProp = typeObject->metaObject()->property(idx); - - typedef QDeclarativePropertyData PCD; - - Q_ASSERT(PCD::flagsForProperty(vtProp) <= PCD::ValueTypeFlagMask); - Q_ASSERT(vtProp.userType() <= 0xFF); - Q_ASSERT(idx <= 0xFF); - - object = currentObject; - core = *property; - core.setFlags(core.getFlags() | PCD::IsValueTypeVirtual); - core.valueTypeFlags = PCD::flagsForProperty(vtProp); - core.valueTypePropType = vtProp.userType(); - core.valueTypeCoreIndex = idx; - - return; - } else { - if (!property->isQObject()) - return; // Not an object property - - void *args[] = { ¤tObject, 0 }; - QMetaObject::metacall(currentObject, QMetaObject::ReadProperty, property->coreIndex, args); - if (!currentObject) return; // No value - - } - - } - - const QString &terminal = path.last(); - - if (terminal.count() >= 3 && - terminal.at(0) == QLatin1Char('o') && - terminal.at(1) == QLatin1Char('n') && - terminal.at(2).isUpper()) { - - QString signalName = terminal.mid(2); - signalName[0] = signalName.at(0).toLower(); - - QMetaMethod method = findSignalByName(currentObject->metaObject(), signalName.toLatin1().constData()); - if (method.signature()) { - object = currentObject; - core.load(method); - return; - } - } - - // Property - QDeclarativePropertyData local; - QDeclarativePropertyData *property = - QDeclarativePropertyCache::property(engine, currentObject, terminal, local); - if (property && !property->isFunction()) { - object = currentObject; - core = *property; - nameCache = terminal; - isNameCached = true; - } -} - -/*! - Create a copy of \a other. -*/ -QDeclarativeProperty::QDeclarativeProperty(const QDeclarativeProperty &other) -{ - d = other.d; - if (d) - d->addref(); -} - -/*! - \enum QDeclarativeProperty::PropertyTypeCategory - - This enum specifies a category of QML property. - - \value InvalidCategory The property is invalid, or is a signal property. - \value List The property is a QDeclarativeListProperty list property - \value Object The property is a QObject derived type pointer - \value Normal The property is a normal value property. - */ - -/*! - \enum QDeclarativeProperty::Type - - This enum specifies a type of QML property. - - \value Invalid The property is invalid. - \value Property The property is a regular Qt property. - \value SignalProperty The property is a signal property. -*/ - -/*! - Returns the property category. -*/ -QDeclarativeProperty::PropertyTypeCategory QDeclarativeProperty::propertyTypeCategory() const -{ - return d ? d->propertyTypeCategory() : InvalidCategory; -} - -QDeclarativeProperty::PropertyTypeCategory -QDeclarativePropertyPrivate::propertyTypeCategory() const -{ - uint type = this->type(); - - if (isValueType()) { - return QDeclarativeProperty::Normal; - } else if (type & QDeclarativeProperty::Property) { - int type = propertyType(); - if (type == QVariant::Invalid) - return QDeclarativeProperty::InvalidCategory; - else if (QDeclarativeValueTypeFactory::isValueType((uint)type)) - return QDeclarativeProperty::Normal; - else if (core.isQObject()) - return QDeclarativeProperty::Object; - else if (core.isQList()) - return QDeclarativeProperty::List; - else - return QDeclarativeProperty::Normal; - } else { - return QDeclarativeProperty::InvalidCategory; - } -} - -/*! - Returns the type name of the property, or 0 if the property has no type - name. -*/ -const char *QDeclarativeProperty::propertyTypeName() const -{ - if (!d) - return 0; - if (d->isValueType()) { - - QDeclarativeEnginePrivate *ep = d->engine?QDeclarativeEnginePrivate::get(d->engine):0; - QDeclarativeValueType *valueType = 0; - if (ep) valueType = ep->valueTypes[d->core.propType]; - else valueType = QDeclarativeValueTypeFactory::valueType(d->core.propType); - Q_ASSERT(valueType); - - const char *rv = valueType->metaObject()->property(d->core.valueTypeCoreIndex).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; - } -} - -/*! - Returns true if \a other and this QDeclarativeProperty represent the same - property. -*/ -bool QDeclarativeProperty::operator==(const QDeclarativeProperty &other) const -{ - if (!d || !other.d) - return false; - // category is intentially omitted here as it is generated - // from the other members - return d->object == other.d->object && - d->core.coreIndex == other.d->core.coreIndex && - d->core.isValueTypeVirtual() == other.d->core.isValueTypeVirtual() && - (!d->core.isValueTypeVirtual() || - (d->core.valueTypeCoreIndex == other.d->core.valueTypeCoreIndex && - d->core.valueTypePropType == other.d->core.valueTypePropType)); -} - -/*! - Returns the QVariant type of the property, or QVariant::Invalid if the - property has no QVariant type. -*/ -int QDeclarativeProperty::propertyType() const -{ - return d ? d->propertyType() : int(QVariant::Invalid); -} - -bool QDeclarativePropertyPrivate::isValueType() const -{ - return core.isValueTypeVirtual(); -} - -int QDeclarativePropertyPrivate::propertyType() const -{ - uint type = this->type(); - if (isValueType()) { - return core.valueTypePropType; - } else if (type & QDeclarativeProperty::Property) { - return core.propType; - } else { - return QVariant::Invalid; - } -} - -QDeclarativeProperty::Type QDeclarativePropertyPrivate::type() const -{ - if (core.isFunction()) - return QDeclarativeProperty::SignalProperty; - else if (core.isValid()) - return QDeclarativeProperty::Property; - else - return QDeclarativeProperty::Invalid; -} - -/*! - Returns the type of the property. -*/ -QDeclarativeProperty::Type QDeclarativeProperty::type() const -{ - return d ? d->type() : Invalid; -} - -/*! - Returns true if this QDeclarativeProperty represents a regular Qt property. -*/ -bool QDeclarativeProperty::isProperty() const -{ - return type() & Property; -} - -/*! - Returns true if this QDeclarativeProperty represents a QML signal property. -*/ -bool QDeclarativeProperty::isSignalProperty() const -{ - return type() & SignalProperty; -} - -/*! - Returns the QDeclarativeProperty's QObject. -*/ -QObject *QDeclarativeProperty::object() const -{ - return d ? d->object : 0; -} - -/*! - Assign \a other to this QDeclarativeProperty. -*/ -QDeclarativeProperty &QDeclarativeProperty::operator=(const QDeclarativeProperty &other) -{ - if (d) - d->release(); - d = other.d; - if (d) - d->addref(); - - return *this; -} - -/*! - Returns true if the property is writable, otherwise false. -*/ -bool QDeclarativeProperty::isWritable() const -{ - if (!d) - return false; - if (!d->object) - return false; - if (d->core.isQList()) //list - return true; - else if (d->core.isFunction()) //signal handler - return false; - else if (d->core.isValid()) //normal property - return d->core.isWritable(); - else - return false; -} - -/*! - Returns true if the property is designable, otherwise false. -*/ -bool QDeclarativeProperty::isDesignable() const -{ - if (!d) - return false; - if (type() & Property && d->core.isValid() && d->object) - return d->object->metaObject()->property(d->core.coreIndex).isDesignable(); - else - return false; -} - -/*! - Returns true if the property is resettable, otherwise false. -*/ -bool QDeclarativeProperty::isResettable() const -{ - if (!d) - return false; - if (type() & Property && d->core.isValid() && d->object) - return d->core.isResettable(); - else - return false; -} - -/*! - Returns true if the QDeclarativeProperty refers to a valid property, otherwise - false. -*/ -bool QDeclarativeProperty::isValid() const -{ - if (!d) - return false; - return type() != Invalid; -} - -/*! - Return the name of this QML property. -*/ -QString QDeclarativeProperty::name() const -{ - if (!d) - return QString(); - if (!d->isNameCached) { - // ### - if (!d->object) { - } else if (d->isValueType()) { - QString rv = d->core.name(d->object) + QLatin1Char('.'); - - QDeclarativeEnginePrivate *ep = d->engine?QDeclarativeEnginePrivate::get(d->engine):0; - QDeclarativeValueType *valueType = 0; - if (ep) valueType = ep->valueTypes[d->core.propType]; - else valueType = QDeclarativeValueTypeFactory::valueType(d->core.propType); - Q_ASSERT(valueType); - - const char *vtName = valueType->metaObject()->property(d->core.valueTypeCoreIndex).name(); - rv += QString::fromUtf8(vtName); - - if (!ep) delete valueType; - - d->nameCache = rv; - } else if (type() & SignalProperty) { - QString name = QLatin1String("on") + d->core.name(d->object); - name[2] = name.at(2).toUpper(); - d->nameCache = name; - } else { - d->nameCache = d->core.name(d->object); - } - d->isNameCached = true; - } - - return d->nameCache; -} - -/*! - Returns the \l{QMetaProperty} {Qt property} associated with - this QML property. - */ -QMetaProperty QDeclarativeProperty::property() const -{ - if (!d) - return QMetaProperty(); - 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 QDeclarativeProperty::method() const -{ - if (!d) - return QMetaMethod(); - 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. -*/ -QDeclarativeAbstractBinding * -QDeclarativePropertyPrivate::binding(const QDeclarativeProperty &that) -{ - if (!that.d || !that.isProperty() || !that.d->object) - return 0; - - return binding(that.d->object, that.d->core.coreIndex, - that.d->core.getValueTypeCoreIndex()); -} - -/*! - Set the binding associated with this property to \a newBinding. Returns - the existing binding (if any), otherwise 0. - - \a newBinding will be enabled, and the returned binding (if any) will be - disabled. - - Ownership of \a newBinding transfers to QML. Ownership of the return value - is assumed by the caller. - - \a flags is passed through to the binding and is used for the initial update (when - the binding sets the initial value, it will use these flags for the write). -*/ -QDeclarativeAbstractBinding * -QDeclarativePropertyPrivate::setBinding(const QDeclarativeProperty &that, - QDeclarativeAbstractBinding *newBinding, - WriteFlags flags) -{ - if (!that.d || !that.isProperty() || !that.d->object) { - if (newBinding) - newBinding->destroy(); - return 0; - } - - if (newBinding) { - // In the case that the new binding is provided, we must target the property it - // is associated with. If we don't do this, retargetBinding() can fail. - QObject *object = newBinding->object(); - int pi = newBinding->propertyIndex(); - - int core = pi & 0xFFFFFF; - int vt = (pi & 0xFF000000)?(pi >> 24):-1; - - return setBinding(object, core, vt, newBinding, flags); - } else { - return setBinding(that.d->object, that.d->core.coreIndex, - that.d->core.getValueTypeCoreIndex(), - newBinding, flags); - } -} - -QDeclarativeAbstractBinding * -QDeclarativePropertyPrivate::binding(QObject *object, int coreIndex, int valueTypeIndex) -{ - QDeclarativeData *data = QDeclarativeData::get(object); - if (!data) - return 0; - - QDeclarativePropertyData *propertyData = - data->propertyCache?data->propertyCache->property(coreIndex):0; - if (propertyData && propertyData->isAlias()) { - const QDeclarativeVMEMetaObject *vme = - static_cast<const QDeclarativeVMEMetaObject *>(metaObjectForProperty(object->metaObject(), coreIndex)); - - QObject *aObject = 0; int aCoreIndex = -1; int aValueTypeIndex = -1; - if (!vme->aliasTarget(coreIndex, &aObject, &aCoreIndex, &aValueTypeIndex) || aCoreIndex == -1) - return 0; - - // This will either be a value type sub-reference or an alias to a value-type sub-reference not both - Q_ASSERT(valueTypeIndex == -1 || aValueTypeIndex == -1); - aValueTypeIndex = (valueTypeIndex == -1)?aValueTypeIndex:valueTypeIndex; - return binding(aObject, aCoreIndex, aValueTypeIndex); - } - - if (!data->hasBindingBit(coreIndex)) - return 0; - - QDeclarativeAbstractBinding *binding = data->bindings; - while (binding && binding->propertyIndex() != coreIndex) - binding = binding->m_nextBinding; - - if (binding && valueTypeIndex != -1) { - if (binding->bindingType() == QDeclarativeAbstractBinding::ValueTypeProxy) { - int index = coreIndex | (valueTypeIndex << 24); - binding = static_cast<QDeclarativeValueTypeProxyBinding *>(binding)->binding(index); - } - } - - return binding; -} - -void QDeclarativePropertyPrivate::findAliasTarget(QObject *object, int bindingIndex, - QObject **targetObject, int *targetBindingIndex) -{ - int coreIndex = bindingIndex & 0xFFFFFF; - int valueTypeIndex = bindingIndex >> 24; - if (valueTypeIndex == 0) valueTypeIndex = -1; - - QDeclarativeData *data = QDeclarativeData::get(object, false); - if (data) { - QDeclarativePropertyData *propertyData = - data->propertyCache?data->propertyCache->property(coreIndex):0; - if (propertyData && propertyData->isAlias()) { - const QDeclarativeVMEMetaObject *vme = - static_cast<const QDeclarativeVMEMetaObject *>(metaObjectForProperty(object->metaObject(), coreIndex)); - QObject *aObject = 0; int aCoreIndex = -1; int aValueTypeIndex = -1; - if (vme->aliasTarget(coreIndex, &aObject, &aCoreIndex, &aValueTypeIndex)) { - // This will either be a value type sub-reference or an alias to a value-type sub-reference not both - Q_ASSERT(valueTypeIndex == -1 || aValueTypeIndex == -1); - - int aBindingIndex = aCoreIndex; - if (aValueTypeIndex != -1) - aBindingIndex |= aValueTypeIndex << 24; - else if (valueTypeIndex != -1) - aBindingIndex |= valueTypeIndex << 24; - - findAliasTarget(aObject, aBindingIndex, targetObject, targetBindingIndex); - return; - } - } - } - - *targetObject = object; - *targetBindingIndex = bindingIndex; -} - -QDeclarativeAbstractBinding * -QDeclarativePropertyPrivate::setBinding(QObject *object, int coreIndex, int valueTypeIndex, - QDeclarativeAbstractBinding *newBinding, WriteFlags flags) -{ - QDeclarativeData *data = QDeclarativeData::get(object, 0 != newBinding); - QDeclarativeAbstractBinding *binding = 0; - - if (data) { - QDeclarativePropertyData *propertyData = - data->propertyCache?data->propertyCache->property(coreIndex):0; - if (propertyData && propertyData->isAlias()) { - const QDeclarativeVMEMetaObject *vme = - static_cast<const QDeclarativeVMEMetaObject *>(metaObjectForProperty(object->metaObject(), coreIndex)); - - QObject *aObject = 0; int aCoreIndex = -1; int aValueTypeIndex = -1; - if (!vme->aliasTarget(coreIndex, &aObject, &aCoreIndex, &aValueTypeIndex)) { - if (newBinding) newBinding->destroy(); - return 0; - } - - // This will either be a value type sub-reference or an alias to a value-type sub-reference not both - Q_ASSERT(valueTypeIndex == -1 || aValueTypeIndex == -1); - aValueTypeIndex = (valueTypeIndex == -1)?aValueTypeIndex:valueTypeIndex; - return setBinding(aObject, aCoreIndex, aValueTypeIndex, newBinding, flags); - } - } - - if (data && data->hasBindingBit(coreIndex)) { - binding = data->bindings; - - while (binding && binding->propertyIndex() != coreIndex) - binding = binding->m_nextBinding; - } - - int index = coreIndex; - if (valueTypeIndex != -1) - index |= (valueTypeIndex << 24); - - if (binding && valueTypeIndex != -1 && binding->bindingType() == QDeclarativeAbstractBinding::ValueTypeProxy) - binding = static_cast<QDeclarativeValueTypeProxyBinding *>(binding)->binding(index); - - if (binding) { - binding->removeFromObject(); - binding->setEnabled(false, 0); - } - - if (newBinding) { - if (newBinding->propertyIndex() != index || newBinding->object() != object) - newBinding->retargetBinding(object, index); - - Q_ASSERT(newBinding->propertyIndex() == index); - Q_ASSERT(newBinding->object() == object); - - newBinding->addToObject(); - newBinding->setEnabled(true, flags); - } - - return binding; -} - -QDeclarativeAbstractBinding * -QDeclarativePropertyPrivate::setBindingNoEnable(QObject *object, int coreIndex, int valueTypeIndex, - QDeclarativeAbstractBinding *newBinding) -{ - QDeclarativeData *data = QDeclarativeData::get(object, 0 != newBinding); - QDeclarativeAbstractBinding *binding = 0; - - if (data) { - QDeclarativePropertyData *propertyData = - data->propertyCache?data->propertyCache->property(coreIndex):0; - if (propertyData && propertyData->isAlias()) { - const QDeclarativeVMEMetaObject *vme = - static_cast<const QDeclarativeVMEMetaObject *>(metaObjectForProperty(object->metaObject(), coreIndex)); - - QObject *aObject = 0; int aCoreIndex = -1; int aValueTypeIndex = -1; - if (!vme->aliasTarget(coreIndex, &aObject, &aCoreIndex, &aValueTypeIndex)) { - if (newBinding) newBinding->destroy(); - return 0; - } - - // This will either be a value type sub-reference or an alias to a value-type sub-reference not both - Q_ASSERT(valueTypeIndex == -1 || aValueTypeIndex == -1); - aValueTypeIndex = (valueTypeIndex == -1)?aValueTypeIndex:valueTypeIndex; - return setBindingNoEnable(aObject, aCoreIndex, aValueTypeIndex, newBinding); - } - } - - if (data && data->hasBindingBit(coreIndex)) { - binding = data->bindings; - - while (binding && binding->propertyIndex() != coreIndex) - binding = binding->m_nextBinding; - } - - int index = coreIndex; - if (valueTypeIndex != -1) - index |= (valueTypeIndex << 24); - - if (binding && valueTypeIndex != -1 && binding->bindingType() == QDeclarativeAbstractBinding::ValueTypeProxy) - binding = static_cast<QDeclarativeValueTypeProxyBinding *>(binding)->binding(index); - - if (binding) - binding->removeFromObject(); - - if (newBinding) { - if (newBinding->propertyIndex() != index || newBinding->object() != object) - newBinding->retargetBinding(object, index); - - Q_ASSERT(newBinding->propertyIndex() == index); - Q_ASSERT(newBinding->object() == object); - - newBinding->addToObject(); - } - - return binding; -} - -/*! - Returns the expression associated with this signal property, or 0 if no - signal expression exists. -*/ -QDeclarativeExpression * -QDeclarativePropertyPrivate::signalExpression(const QDeclarativeProperty &that) -{ - if (!(that.type() & QDeclarativeProperty::SignalProperty)) - return 0; - - const QObjectList &children = that.d->object->children(); - - for (int ii = 0; ii < children.count(); ++ii) { - QObject *child = children.at(ii); - - QDeclarativeBoundSignal *signal = QDeclarativeBoundSignal::cast(child); - if (signal && signal->index() == that.index()) - return signal->expression(); - } - - return 0; -} - -/*! - Set the signal expression associated with this signal property to \a expr. - Returns the existing signal expression (if any), otherwise 0. - - Ownership of \a expr transfers to QML. Ownership of the return value is - assumed by the caller. -*/ -QDeclarativeExpression * -QDeclarativePropertyPrivate::setSignalExpression(const QDeclarativeProperty &that, - QDeclarativeExpression *expr) -{ - if (!(that.type() & QDeclarativeProperty::SignalProperty)) { - delete expr; - return 0; - } - - const QObjectList &children = that.d->object->children(); - - for (int ii = 0; ii < children.count(); ++ii) { - QObject *child = children.at(ii); - - QDeclarativeBoundSignal *signal = QDeclarativeBoundSignal::cast(child); - if (signal && signal->index() == that.index()) - return signal->setExpression(expr); - } - - if (expr) { - QDeclarativeBoundSignal *signal = new QDeclarativeBoundSignal(that.d->object, that.method(), that.d->object); - return signal->setExpression(expr); - } else { - return 0; - } -} - -/*! - Returns the property value. -*/ -QVariant QDeclarativeProperty::read() const -{ - if (!d) - return QVariant(); - if (!d->object) - return QVariant(); - - if (type() & SignalProperty) { - - return QVariant(); - - } else if (type() & Property) { - - return d->readValueProperty(); - - } - return QVariant(); -} - -/*! -Return the \a name property value of \a object. This method is equivalent to: -\code - QDeclarativeProperty p(object, name); - p.read(); -\endcode -*/ -QVariant QDeclarativeProperty::read(QObject *object, const QString &name) -{ - QDeclarativeProperty p(object, name); - return p.read(); -} - -/*! - Return the \a name property value of \a object using the - \l{QDeclarativeContext} {context} \a ctxt. This method is - equivalent to: - - \code - QDeclarativeProperty p(object, name, context); - p.read(); - \endcode -*/ -QVariant QDeclarativeProperty::read(QObject *object, const QString &name, QDeclarativeContext *ctxt) -{ - QDeclarativeProperty p(object, name, ctxt); - return p.read(); -} - -/*! - - Return the \a name property value of \a object using the environment - for instantiating QML components that is provided by \a engine. . - This method is equivalent to: - - \code - QDeclarativeProperty p(object, name, engine); - p.read(); - \endcode -*/ -QVariant QDeclarativeProperty::read(QObject *object, const QString &name, QDeclarativeEngine *engine) -{ - QDeclarativeProperty p(object, name, engine); - return p.read(); -} - -QVariant QDeclarativePropertyPrivate::readValueProperty() -{ - if (isValueType()) { - - QDeclarativeEnginePrivate *ep = engine?QDeclarativeEnginePrivate::get(engine):0; - QDeclarativeValueType *valueType = 0; - if (ep) valueType = ep->valueTypes[core.propType]; - else valueType = QDeclarativeValueTypeFactory::valueType(core.propType); - Q_ASSERT(valueType); - - valueType->read(object, core.coreIndex); - - QVariant rv = valueType->metaObject()->property(core.valueTypeCoreIndex).read(valueType); - - if (!ep) delete valueType; - return rv; - - } else if (core.isQList()) { - - QDeclarativeListProperty<QObject> prop; - void *args[] = { &prop, 0 }; - QMetaObject::metacall(object, QMetaObject::ReadProperty, core.coreIndex, args); - return QVariant::fromValue(QDeclarativeListReferencePrivate::init(prop, core.propType, engine)); - - } else if (core.isQObject()) { - - QObject *rv = 0; - void *args[] = { &rv, 0 }; - QMetaObject::metacall(object, QMetaObject::ReadProperty, core.coreIndex, args); - return QVariant::fromValue(rv); - - } else { - - return object->metaObject()->property(core.coreIndex).read(object.data()); - - } -} - -static QUrl urlFromUserString(const QByteArray &data) -{ - QUrl u; - if (!data.isEmpty()) - { - // Preserve any valid percent-encoded octets supplied by the source - u.setEncodedUrl(data, QUrl::TolerantMode); - } - return u; -} - -static QUrl urlFromUserString(const QString &data) -{ - return urlFromUserString(data.toUtf8()); -} - -// helper function to allow assignment / binding to QList<QUrl> properties. -static QVariant resolvedUrlSequence(const QVariant &value, QDeclarativeContextData *context) -{ - QList<QUrl> urls; - if (value.userType() == qMetaTypeId<QUrl>()) { - urls.append(value.toUrl()); - } else if (value.userType() == qMetaTypeId<QString>()) { - urls.append(urlFromUserString(value.toString())); - } else if (value.userType() == qMetaTypeId<QByteArray>()) { - urls.append(urlFromUserString(value.toByteArray())); - } else if (value.userType() == qMetaTypeId<QList<QUrl> >()) { - urls = value.value<QList<QUrl> >(); - } else if (value.userType() == qMetaTypeId<QStringList>()) { - QStringList urlStrings = value.value<QStringList>(); - for (int i = 0; i < urlStrings.size(); ++i) - urls.append(urlFromUserString(urlStrings.at(i))); - } else if (value.userType() == qMetaTypeId<QList<QString> >()) { - QList<QString> urlStrings = value.value<QList<QString> >(); - for (int i = 0; i < urlStrings.size(); ++i) - urls.append(urlFromUserString(urlStrings.at(i))); - } // note: QList<QByteArray> is not currently supported. - - QList<QUrl> resolvedUrls; - for (int i = 0; i < urls.size(); ++i) { - QUrl u = urls.at(i); - if (context && u.isRelative() && !u.isEmpty()) - u = context->resolvedUrl(u); - resolvedUrls.append(u); - } - - return QVariant::fromValue<QList<QUrl> >(resolvedUrls); -} - -//writeEnumProperty MIRRORS the relelvant bit of QMetaProperty::write AND MUST BE KEPT IN SYNC! -bool QDeclarativePropertyPrivate::writeEnumProperty(const QMetaProperty &prop, int idx, QObject *object, const QVariant &value, int flags) -{ - if (!object || !prop.isWritable()) - return false; - - QVariant v = value; - if (prop.isEnumType()) { - QMetaEnum menum = prop.enumerator(); - if (v.userType() == QVariant::String -#ifdef QT3_SUPPORT - || v.userType() == QVariant::CString -#endif - ) { - bool ok; - if (prop.isFlagType()) - v = QVariant(menum.keysToValue(value.toByteArray(), &ok)); - else - v = QVariant(menum.keyToValue(value.toByteArray(), &ok)); - if (!ok) - return false; - } else if (v.userType() != QVariant::Int && v.userType() != QVariant::UInt) { - int enumMetaTypeId = QMetaType::type(QByteArray(menum.scope() + QByteArray("::") + menum.name())); - if ((enumMetaTypeId == 0) || (v.userType() != enumMetaTypeId) || !v.constData()) - return false; - v = QVariant(*reinterpret_cast<const int *>(v.constData())); - } - v.convert(QVariant::Int); - } - - // the status variable is changed by qt_metacall to indicate what it did - // this feature is currently only used by QtDBus and should not be depended - // upon. Don't change it without looking into QDBusAbstractInterface first - // -1 (unchanged): normal qt_metacall, result stored in argv[0] - // changed: result stored directly in value, return the value of status - int status = -1; - void *argv[] = { v.data(), &v, &status, &flags }; - QMetaObject::metacall(object, QMetaObject::WriteProperty, idx, argv); - return status; -} - -bool QDeclarativePropertyPrivate::writeValueProperty(const QVariant &value, WriteFlags flags) -{ - return writeValueProperty(object, engine, core, value, effectiveContext(), flags); -} - -bool -QDeclarativePropertyPrivate::writeValueProperty(QObject *object, QDeclarativeEngine *engine, - const QDeclarativePropertyData &core, - const QVariant &value, - QDeclarativeContextData *context, WriteFlags flags) -{ - // Remove any existing bindings on this property - if (!(flags & DontRemoveBinding) && object) { - QDeclarativeAbstractBinding *binding = setBinding(object, core.coreIndex, - core.getValueTypeCoreIndex(), - 0, flags); - if (binding) binding->destroy(); - } - - bool rv = false; - if (core.isValueTypeVirtual()) { - QDeclarativeEnginePrivate *ep = engine?QDeclarativeEnginePrivate::get(engine):0; - - QDeclarativeValueType *writeBack = 0; - if (ep) { - writeBack = ep->valueTypes[core.propType]; - } else { - writeBack = QDeclarativeValueTypeFactory::valueType(core.propType); - } - - writeBack->read(object, core.coreIndex); - - QDeclarativePropertyData data = core; - data.setFlags(QDeclarativePropertyData::Flag(core.valueTypeFlags)); - data.coreIndex = core.valueTypeCoreIndex; - data.propType = core.valueTypePropType; - - rv = write(writeBack, data, value, context, flags); - - writeBack->write(object, core.coreIndex, flags); - if (!ep) delete writeBack; - - } else { - - rv = write(object, core, value, context, flags); - - } - - return rv; -} - -bool QDeclarativePropertyPrivate::write(QObject *object, - const QDeclarativePropertyData &property, - const QVariant &value, QDeclarativeContextData *context, - WriteFlags flags) -{ - int coreIdx = property.coreIndex; - int status = -1; //for dbus - - if (property.isEnum()) { - QMetaProperty prop = object->metaObject()->property(property.coreIndex); - QVariant v = value; - // Enum values come through the script engine as doubles - if (value.userType() == QVariant::Double) { - double integral; - double fractional = modf(value.toDouble(), &integral); - if (qFuzzyIsNull(fractional)) - v.convert(QVariant::Int); - } - return writeEnumProperty(prop, coreIdx, object, v, flags); - } - - int propertyType = property.propType; - int variantType = value.userType(); - - QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(context); - - if (propertyType == QVariant::Url) { - - QUrl u; - bool found = false; - if (variantType == QVariant::Url) { - u = value.toUrl(); - found = true; - } else if (variantType == QVariant::ByteArray) { - u = urlFromUserString(value.toByteArray()); - found = true; - } else if (variantType == QVariant::String) { - u = urlFromUserString(value.toString()); - found = true; - } - - if (!found) - return false; - - if (context && u.isRelative() && !u.isEmpty()) - u = context->resolvedUrl(u); - int status = -1; - void *argv[] = { &u, 0, &status, &flags }; - QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, argv); - - } else if (propertyType == qMetaTypeId<QList<QUrl> >()) { - QList<QUrl> urlSeq = resolvedUrlSequence(value, context).value<QList<QUrl> >(); - int status = -1; - void *argv[] = { &urlSeq, 0, &status, &flags }; - QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, argv); - } else if (variantType == propertyType) { - - void *a[] = { (void *)value.constData(), 0, &status, &flags }; - QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a); - - } else if (qMetaTypeId<QVariant>() == propertyType) { - - void *a[] = { (void *)&value, 0, &status, &flags }; - QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a); - - } else if (property.isQObject()) { - - const QMetaObject *valMo = rawMetaObjectForType(enginePriv, value.userType()); - - if (!valMo) - return false; - - QObject *o = *(QObject **)value.constData(); - const QMetaObject *propMo = rawMetaObjectForType(enginePriv, propertyType); - - if (o) valMo = o->metaObject(); - - if (canConvert(valMo, propMo)) { - void *args[] = { &o, 0, &status, &flags }; - QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, - args); - } else if (!o && canConvert(propMo, valMo)) { - // In the case of a null QObject, we assign the null if there is - // any change that the null variant type could be up or down cast to - // the property type. - void *args[] = { &o, 0, &status, &flags }; - QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, - args); - } else { - return false; - } - - } else if (property.isQList()) { - - const QMetaObject *listType = 0; - if (enginePriv) { - listType = enginePriv->rawMetaObjectForType(enginePriv->listType(property.propType)); - } else { - QDeclarativeType *type = QDeclarativeMetaType::qmlType(QDeclarativeMetaType::listType(property.propType)); - if (!type) return false; - listType = type->baseMetaObject(); - } - if (!listType) return false; - - QDeclarativeListProperty<void> prop; - void *args[] = { &prop, 0 }; - QMetaObject::metacall(object, QMetaObject::ReadProperty, coreIdx, args); - - if (!prop.clear) return false; - - prop.clear(&prop); - - if (value.userType() == qMetaTypeId<QDeclarativeListReference>()) { - QDeclarativeListReference qdlr = value.value<QDeclarativeListReference>(); - - for (int ii = 0; ii < qdlr.count(); ++ii) { - QObject *o = qdlr.at(ii); - if (o && !canConvert(o->metaObject(), listType)) - o = 0; - prop.append(&prop, (void *)o); - } - } else if (value.userType() == qMetaTypeId<QList<QObject *> >()) { - const QList<QObject *> &list = qvariant_cast<QList<QObject *> >(value); - - for (int ii = 0; ii < list.count(); ++ii) { - QObject *o = list.at(ii); - if (o && !canConvert(o->metaObject(), listType)) - o = 0; - prop.append(&prop, (void *)o); - } - } else { - QObject *o = enginePriv?enginePriv->toQObject(value):QDeclarativeMetaType::toQObject(value); - if (o && !canConvert(o->metaObject(), listType)) - o = 0; - prop.append(&prop, (void *)o); - } - - } else { - Q_ASSERT(variantType != propertyType); - - bool ok = false; - QVariant v; - if (variantType == QVariant::String) - v = QDeclarativeStringConverters::variantFromString(value.toString(), propertyType, &ok); - if (!ok) { - v = value; - if (v.convert((QVariant::Type)propertyType)) { - ok = true; - } else if ((uint)propertyType >= QVariant::UserType && variantType == QVariant::String) { - QDeclarativeMetaType::StringConverter con = QDeclarativeMetaType::customStringConverter(propertyType); - if (con) { - v = con(value.toString()); - if (v.userType() == propertyType) - ok = true; - } - } - } - if (!ok) { - // the only other option is that they are assigning a single value - // to a sequence type property (eg, an int to a QList<int> property). - // Note that we've already handled single-value assignment to QList<QUrl> properties. - if (variantType == QVariant::Int && propertyType == qMetaTypeId<QList<int> >()) { - QList<int> list; - list << value.toInt(); - v = QVariant::fromValue<QList<int> >(list); - ok = true; - } else if (variantType == QVariant::Double && propertyType == qMetaTypeId<QList<qreal> >()) { - QList<qreal> list; - list << value.toReal(); - v = QVariant::fromValue<QList<qreal> >(list); - ok = true; - } else if (variantType == QVariant::Bool && propertyType == qMetaTypeId<QList<bool> >()) { - QList<bool> list; - list << value.toBool(); - v = QVariant::fromValue<QList<bool> >(list); - ok = true; - } else if (variantType == QVariant::String && propertyType == qMetaTypeId<QList<QString> >()) { - QList<QString> list; - list << value.toString(); - v = QVariant::fromValue<QList<QString> >(list); - ok = true; - } else if (variantType == QVariant::String && propertyType == qMetaTypeId<QStringList>()) { - QStringList list; - list << value.toString(); - v = QVariant::fromValue<QStringList>(list); - ok = true; - } - } - - if (ok) { - void *a[] = { (void *)v.constData(), 0, &status, &flags}; - QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a); - } else { - return false; - } - } - - return true; -} - -// Returns true if successful, false if an error description was set on expression -bool QDeclarativePropertyPrivate::writeBinding(QObject *object, - const QDeclarativePropertyData &core, - QDeclarativeContextData *context, - QDeclarativeJavaScriptExpression *expression, - v8::Handle<v8::Value> result, bool isUndefined, - WriteFlags flags) -{ - Q_ASSERT(object); - Q_ASSERT(core.coreIndex != -1); - - QDeclarativeEngine *engine = context->engine; - QV8Engine *v8engine = QDeclarativeEnginePrivate::getV8Engine(engine); - -#define QUICK_STORE(cpptype, conversion) \ - { \ - cpptype o = (conversion); \ - int status = -1; \ - void *argv[] = { &o, 0, &status, &flags }; \ - QMetaObject::metacall(object, QMetaObject::WriteProperty, core.coreIndex, argv); \ - return true; \ - } \ - - - if (!isUndefined && !core.isValueTypeVirtual()) { - switch (core.propType) { - case QMetaType::Int: - if (result->IsInt32()) - QUICK_STORE(int, result->Int32Value()) - else if (result->IsNumber()) - QUICK_STORE(int, qRound(result->NumberValue())) - break; - case QMetaType::Double: - if (result->IsNumber()) - QUICK_STORE(double, result->NumberValue()) - break; - case QMetaType::Float: - if (result->IsNumber()) - QUICK_STORE(float, result->NumberValue()) - break; - case QMetaType::QString: - if (result->IsString()) - QUICK_STORE(QString, v8engine->toString(result)) - break; - default: - break; - } - } -#undef QUICK_STORE - - int type = core.isValueTypeVirtual()?core.valueTypePropType:core.propType; - - QDeclarativeJavaScriptExpression::DeleteWatcher watcher(expression); - - QVariant value; - bool isVmeProperty = core.isVMEProperty(); - - if (isUndefined) { - } else if (core.isQList()) { - value = v8engine->toVariant(result, qMetaTypeId<QList<QObject *> >()); - } else if (result->IsNull() && core.isQObject()) { - value = QVariant::fromValue((QObject *)0); - } else if (core.propType == qMetaTypeId<QList<QUrl> >()) { - value = resolvedUrlSequence(v8engine->toVariant(result, qMetaTypeId<QList<QUrl> >()), context); - } else if (!isVmeProperty) { - value = v8engine->toVariant(result, type); - } - - if (expression->hasError()) { - return false; - } else if (isUndefined && core.isResettable()) { - void *args[] = { 0 }; - QMetaObject::metacall(object, QMetaObject::ResetProperty, core.coreIndex, args); - } else if (isUndefined && type == qMetaTypeId<QVariant>()) { - writeValueProperty(object, engine, core, QVariant(), context, flags); - } else if (isUndefined) { - expression->delayedError()->error.setDescription(QLatin1String("Unable to assign [undefined] to ") + QLatin1String(QMetaType::typeName(type))); - return false; - } else if (result->IsFunction()) { - expression->delayedError()->error.setDescription(QLatin1String("Unable to assign a function to a property.")); - return false; - } else if (isVmeProperty) { - typedef QDeclarativeVMEMetaObject VMEMO; - VMEMO *vmemo = static_cast<VMEMO *>(const_cast<QMetaObject *>(object->metaObject())); - vmemo->setVMEProperty(core.coreIndex, result); - } else if (!writeValueProperty(object, engine, core, value, context, flags)) { - - if (watcher.wasDeleted()) - return true; - - const char *valueType = 0; - if (value.userType() == QVariant::Invalid) valueType = "null"; - else valueType = QMetaType::typeName(value.userType()); - - expression->delayedError()->error.setDescription(QLatin1String("Unable to assign ") + - QLatin1String(valueType) + - QLatin1String(" to ") + - QLatin1String(QMetaType::typeName(type))); - return false; - } - - return true; -} - -bool QDeclarativePropertyPrivate::writeBinding(const QDeclarativeProperty &that, - QDeclarativeContextData *context, - QDeclarativeJavaScriptExpression *expression, - v8::Handle<v8::Value> result, bool isUndefined, - WriteFlags flags) -{ - QDeclarativePropertyPrivate *pp = that.d; - - if (!pp) - return true; - - QObject *object = that.object(); - if (!object) - return true; - - return writeBinding(object, pp->core, context, expression, result, isUndefined, flags); -} - -const QMetaObject *QDeclarativePropertyPrivate::rawMetaObjectForType(QDeclarativeEnginePrivate *engine, int userType) -{ - if (engine) { - return engine->rawMetaObjectForType(userType); - } else { - QDeclarativeType *type = QDeclarativeMetaType::qmlType(userType); - return type?type->baseMetaObject():0; - } -} - -/*! - Sets the property value to \a value and returns true. - Returns false if the property can't be set because the - \a value is the wrong type, for example. - */ -bool QDeclarativeProperty::write(const QVariant &value) const -{ - return QDeclarativePropertyPrivate::write(*this, value, 0); -} - -/*! - Writes \a value to the \a name property of \a object. This method - is equivalent to: - - \code - QDeclarativeProperty p(object, name); - p.write(value); - \endcode -*/ -bool QDeclarativeProperty::write(QObject *object, const QString &name, const QVariant &value) -{ - QDeclarativeProperty p(object, name); - return p.write(value); -} - -/*! - Writes \a value to the \a name property of \a object using the - \l{QDeclarativeContext} {context} \a ctxt. This method is - equivalent to: - - \code - QDeclarativeProperty p(object, name, ctxt); - p.write(value); - \endcode -*/ -bool QDeclarativeProperty::write(QObject *object, - const QString &name, - const QVariant &value, - QDeclarativeContext *ctxt) -{ - QDeclarativeProperty p(object, name, ctxt); - return p.write(value); -} - -/*! - - Writes \a value to the \a name property of \a object using the - environment for instantiating QML components that is provided by - \a engine. This method is equivalent to: - - \code - QDeclarativeProperty p(object, name, engine); - p.write(value); - \endcode -*/ -bool QDeclarativeProperty::write(QObject *object, const QString &name, const QVariant &value, - QDeclarativeEngine *engine) -{ - QDeclarativeProperty p(object, name, engine); - return p.write(value); -} - -/*! - Resets the property and returns true if the property is - resettable. If the property is not resettable, nothing happens - and false is returned. -*/ -bool QDeclarativeProperty::reset() const -{ - if (isResettable()) { - void *args[] = { 0 }; - QMetaObject::metacall(d->object, QMetaObject::ResetProperty, d->core.coreIndex, args); - return true; - } else { - return false; - } -} - -bool QDeclarativePropertyPrivate::write(const QDeclarativeProperty &that, - const QVariant &value, WriteFlags flags) -{ - if (!that.d) - return false; - if (that.d->object && that.type() & QDeclarativeProperty::Property && - that.d->core.isValid() && that.isWritable()) - return that.d->writeValueProperty(value, flags); - else - return false; -} - -/*! - Returns true if the property has a change notifier signal, otherwise false. -*/ -bool QDeclarativeProperty::hasNotifySignal() const -{ - if (type() & Property && d->object) { - return d->object->metaObject()->property(d->core.coreIndex).hasNotifySignal(); - } - return false; -} - -/*! - Returns true if the property needs a change notifier signal for bindings - to remain upto date, false otherwise. - - Some properties, such as attached properties or those whose value never - changes, do not require a change notifier. -*/ -bool QDeclarativeProperty::needsNotifySignal() const -{ - return type() & Property && !property().isConstant(); -} - -/*! - Connects the property's change notifier signal to the - specified \a method of the \a dest object and returns - true. Returns false if this metaproperty does not - represent a regular Qt property or if it has no - change notifier signal, or if the \a dest object does - not have the specified \a method. -*/ -bool QDeclarativeProperty::connectNotifySignal(QObject *dest, int method) const -{ - if (!(type() & Property) || !d->object) - return false; - - QMetaProperty prop = d->object->metaObject()->property(d->core.coreIndex); - if (prop.hasNotifySignal()) { - return QDeclarativePropertyPrivate::connect(d->object, prop.notifySignalIndex(), dest, method, Qt::DirectConnection); - } else { - return false; - } -} - -/*! - Connects the property's change notifier signal to the - specified \a slot of the \a dest object and returns - true. Returns false if this metaproperty does not - represent a regular Qt property or if it has no - change notifier signal, or if the \a dest object does - not have the specified \a slot. -*/ -bool QDeclarativeProperty::connectNotifySignal(QObject *dest, const char *slot) const -{ - if (!(type() & Property) || !d->object) - return false; - - 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); - } else { - return false; - } -} - -/*! - Return the Qt metaobject index of the property. -*/ -int QDeclarativeProperty::index() const -{ - return d ? d->core.coreIndex : -1; -} - -int QDeclarativePropertyPrivate::valueTypeCoreIndex(const QDeclarativeProperty &that) -{ - return that.d ? that.d->core.getValueTypeCoreIndex() : -1; -} - -/*! - Returns the "property index" for use in bindings. The top 8 bits are the value type - offset, and 0 otherwise. The bottom 24-bits are the regular property index. -*/ -int QDeclarativePropertyPrivate::bindingIndex(const QDeclarativeProperty &that) -{ - if (!that.d) - return -1; - return bindingIndex(that.d->core); -} - -int QDeclarativePropertyPrivate::bindingIndex(const QDeclarativePropertyData &that) -{ - int rv = that.coreIndex; - if (rv != -1 && that.isValueTypeVirtual()) - rv = rv | (that.valueTypeCoreIndex << 24); - return rv; -} - -QDeclarativePropertyData -QDeclarativePropertyPrivate::saveValueType(const QMetaObject *metaObject, int index, - const QMetaObject *subObject, int subIndex, - QDeclarativeEngine *) -{ - QMetaProperty subProp = subObject->property(subIndex); - - QDeclarativePropertyData core; - core.load(metaObject->property(index)); - core.setFlags(core.getFlags() | QDeclarativePropertyData::IsValueTypeVirtual); - core.valueTypeFlags = QDeclarativePropertyData::flagsForProperty(subProp); - core.valueTypeCoreIndex = subIndex; - core.valueTypePropType = subProp.userType(); - - return core; -} - -QDeclarativeProperty -QDeclarativePropertyPrivate::restore(QObject *object, const QDeclarativePropertyData &data, - QDeclarativeContextData *ctxt) -{ - QDeclarativeProperty prop; - - prop.d = new QDeclarativePropertyPrivate; - prop.d->object = object; - prop.d->context = ctxt; - prop.d->engine = ctxt?ctxt->engine:0; - - prop.d->core = data; - - return prop; -} - -/*! - Returns true if lhs and rhs refer to the same metaobject data -*/ -bool QDeclarativePropertyPrivate::equal(const QMetaObject *lhs, const QMetaObject *rhs) -{ - return lhs == rhs || (1 && lhs && rhs && lhs->d.stringdata == rhs->d.stringdata); -} - -/*! - Returns true if from inherits to. -*/ -bool QDeclarativePropertyPrivate::canConvert(const QMetaObject *from, const QMetaObject *to) -{ - if (from && to == &QObject::staticMetaObject) - return true; - - while (from) { - if (equal(from, to)) - return true; - from = from->superClass(); - } - - return false; -} - -/*! - Return the signal corresponding to \a name -*/ -QMetaMethod QDeclarativePropertyPrivate::findSignalByName(const QMetaObject *mo, const QByteArray &name) -{ - Q_ASSERT(mo); - int methods = mo->methodCount(); - for (int ii = methods - 1; ii >= 2; --ii) { // >= 2 to block the destroyed signal - QMetaMethod method = mo->method(ii); - QByteArray methodName = method.signature(); - int idx = methodName.indexOf('('); - methodName = methodName.left(idx); - - if (methodName == name) - return method; - } - - // If no signal is found, but the signal is of the form "onBlahChanged", - // return the notify signal for the property "Blah" - if (name.endsWith("Changed")) { - QByteArray propName = name.mid(0, name.length() - 7); - int propIdx = mo->indexOfProperty(propName.constData()); - if (propIdx >= 0) { - QMetaProperty prop = mo->property(propIdx); - if (prop.hasNotifySignal()) - return prop.notifySignal(); - } - } - - return QMetaMethod(); -} - -static inline int QMetaObject_methods(const QMetaObject *metaObject) -{ - struct Private - { - int revision; - int className; - int classInfoCount, classInfoData; - int methodCount, methodData; - int propertyCount, propertyData; - }; - - return reinterpret_cast<const Private *>(metaObject->d.data)->methodCount; -} - -static inline int QMetaObject_properties(const QMetaObject *metaObject) -{ - struct Private - { - int revision; - int className; - int classInfoCount, classInfoData; - int methodCount, methodData; - int propertyCount, propertyData; - }; - - return reinterpret_cast<const Private *>(metaObject->d.data)->propertyCount; -} - -static inline void flush_vme_signal(const QObject *object, int index) -{ - QDeclarativeData *data = static_cast<QDeclarativeData *>(QObjectPrivate::get(const_cast<QObject *>(object))->declarativeData); - if (data && data->propertyCache) { - QDeclarativePropertyData *property = data->propertyCache->method(index); - - if (property && property->isVMESignal()) { - const QMetaObject *metaObject = object->metaObject(); - int methodOffset = metaObject->methodOffset(); - - while (methodOffset > index) { - metaObject = metaObject->d.superdata; - methodOffset -= QMetaObject_methods(metaObject); - } - - QDeclarativeVMEMetaObject *vme = - static_cast<QDeclarativeVMEMetaObject *>(const_cast<QMetaObject *>(metaObject)); - - vme->connectAliasSignal(index); - } - } -} - -/*! -Connect \a sender \a signal_index to \a receiver \a method_index with the specified -\a type and \a types. This behaves identically to QMetaObject::connect() except that -it connects any lazy "proxy" signal connections set up by QML. - -It is possible that this logic should be moved to QMetaObject::connect(). -*/ -bool QDeclarativePropertyPrivate::connect(const QObject *sender, int signal_index, - const QObject *receiver, int method_index, - int type, int *types) -{ - flush_vme_signal(sender, signal_index); - flush_vme_signal(receiver, method_index); - - return QMetaObject::connect(sender, signal_index, receiver, method_index, type, types); -} - -void QDeclarativePropertyPrivate::flushSignal(const QObject *sender, int signal_index) -{ - flush_vme_signal(sender, signal_index); -} - -/*! -Return \a metaObject's [super] meta object that provides data for \a property. -*/ -const QMetaObject *QDeclarativePropertyPrivate::metaObjectForProperty(const QMetaObject *metaObject, int property) -{ - int propertyOffset = metaObject->propertyOffset(); - - while (propertyOffset > property) { - metaObject = metaObject->d.superdata; - propertyOffset -= QMetaObject_properties(metaObject); - } - - return metaObject; -} - -QT_END_NAMESPACE |