aboutsummaryrefslogtreecommitdiffstats
path: root/src/declarative/qml/qdeclarativeobjectscriptclass.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative/qml/qdeclarativeobjectscriptclass.cpp')
-rw-r--r--src/declarative/qml/qdeclarativeobjectscriptclass.cpp1226
1 files changed, 0 insertions, 1226 deletions
diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp
deleted file mode 100644
index edc1755a72..0000000000
--- a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp
+++ /dev/null
@@ -1,1226 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtDeclarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "private/qdeclarativeobjectscriptclass_p.h"
-
-#include "private/qdeclarativeengine_p.h"
-#include "private/qdeclarativecontext_p.h"
-#include "private/qdeclarativedata_p.h"
-#include "private/qdeclarativetypenamescriptclass_p.h"
-#include "private/qdeclarativelistscriptclass_p.h"
-#include "private/qdeclarativebinding_p.h"
-#include "private/qdeclarativeguard_p.h"
-#include "private/qdeclarativevmemetaobject_p.h"
-
-#include <QtCore/qtimer.h>
-#include <QtCore/qvarlengtharray.h>
-#include <QtScript/qscriptcontextinfo.h>
-
-Q_DECLARE_METATYPE(QScriptValue)
-
-#if defined(__GNUC__)
-# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405
-// The code in this file does not violate strict aliasing, but GCC thinks it does
-// so turn off the warnings for us to have a clean build
-# pragma GCC diagnostic ignored "-Wstrict-aliasing"
-# endif
-#endif
-
-QT_BEGIN_NAMESPACE
-
-struct ObjectData : public QScriptDeclarativeClass::Object {
- ObjectData(QObject *o, int t) : object(o), type(t) {
- if (o) {
- QDeclarativeData *ddata = QDeclarativeData::get(object, true);
- if (ddata) ddata->objectDataRefCount++;
- }
- }
-
- virtual ~ObjectData() {
- if (object && !object->parent()) {
- QDeclarativeData *ddata = QDeclarativeData::get(object, false);
- if (ddata && !ddata->indestructible && 0 == --ddata->objectDataRefCount)
- object->deleteLater();
- }
- }
-
- QDeclarativeGuard<QObject> object;
- int type;
-};
-
-/*
- The QDeclarativeObjectScriptClass handles property access for QObjects
- via QtScript. It is also used to provide a more useful API in
- QtScript for QML.
- */
-QDeclarativeObjectScriptClass::QDeclarativeObjectScriptClass(QDeclarativeEngine *bindEngine)
-: QScriptDeclarativeClass(QDeclarativeEnginePrivate::getScriptEngine(bindEngine)),
- methods(bindEngine), lastData(0), engine(bindEngine)
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- m_destroy = scriptEngine->newFunction(destroy);
- m_destroyId = createPersistentIdentifier(QLatin1String("destroy"));
- m_toString = scriptEngine->newFunction(tostring);
- m_toStringId = createPersistentIdentifier(QLatin1String("toString"));
-}
-
-QDeclarativeObjectScriptClass::~QDeclarativeObjectScriptClass()
-{
-}
-
-QScriptValue QDeclarativeObjectScriptClass::newQObject(QObject *object, int type)
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- if (!object)
- return scriptEngine->nullValue();
-// return newObject(scriptEngine, this, new ObjectData(object, type));
-
- if (QObjectPrivate::get(object)->wasDeleted)
- return scriptEngine->undefinedValue();
-
- QDeclarativeData *ddata = QDeclarativeData::get(object, true);
-
- if (!ddata) {
- return scriptEngine->undefinedValue();
- } else if (!ddata->indestructible && !object->parent()) {
- return newObject(scriptEngine, this, new ObjectData(object, type));
- } else if (!ddata->scriptValue) {
- ddata->scriptValue = new QScriptValue(newObject(scriptEngine, this, new ObjectData(object, type)));
- return *ddata->scriptValue;
- } else if (ddata->scriptValue->engine() == QDeclarativeEnginePrivate::getScriptEngine(engine)) {
- return *ddata->scriptValue;
- } else {
- return newObject(scriptEngine, this, new ObjectData(object, type));
- }
-}
-
-QObject *QDeclarativeObjectScriptClass::toQObject(const QScriptValue &value) const
-{
- return value.toQObject();
-}
-
-int QDeclarativeObjectScriptClass::objectType(const QScriptValue &value) const
-{
- if (scriptClass(value) != this)
- return QVariant::Invalid;
-
- Object *o = object(value);
- return ((ObjectData*)(o))->type;
-}
-
-QScriptClass::QueryFlags
-QDeclarativeObjectScriptClass::queryProperty(Object *object, const Identifier &name,
- QScriptClass::QueryFlags flags)
-{
- return queryProperty(toQObject(object), name, flags, 0);
-}
-
-QScriptClass::QueryFlags
-QDeclarativeObjectScriptClass::queryProperty(QObject *obj, const Identifier &name,
- QScriptClass::QueryFlags flags, QDeclarativeContextData *evalContext,
- QueryHints hints)
-{
- Q_UNUSED(flags);
- lastData = 0;
- lastTNData = 0;
-
- if (name == m_destroyId.identifier ||
- name == m_toStringId.identifier)
- return QScriptClass::HandlesReadAccess;
-
- if (!obj)
- return 0;
-
- QDeclarativeEnginePrivate *enginePrivate = QDeclarativeEnginePrivate::get(engine);
- lastData = QDeclarativePropertyCache::property(engine, obj, name, local);
- if ((hints & ImplicitObject) && lastData && lastData->revision != 0) {
-
- QDeclarativeData *ddata = QDeclarativeData::get(obj);
- if (ddata && ddata->propertyCache && !ddata->propertyCache->isAllowedInRevision(lastData))
- return 0;
- }
-
- if (lastData)
- return QScriptClass::HandlesReadAccess | QScriptClass::HandlesWriteAccess;
-
- if (!(hints & SkipAttachedProperties)) {
- if (!evalContext && context()) {
- // Global object, QScriptContext activation object, QDeclarativeContext object
- QScriptValue scopeNode = scopeChainValue(context(), -3);
- if (scopeNode.isValid()) {
- Q_ASSERT(scriptClass(scopeNode) == enginePrivate->contextClass);
-
- evalContext = enginePrivate->contextClass->contextFromValue(scopeNode);
- }
- }
-
- if (evalContext && evalContext->imports) {
- QDeclarativeTypeNameCache::Data *data = evalContext->imports->data(name);
- if (data) {
- lastTNData = data;
- return QScriptClass::HandlesReadAccess;
- }
- }
- }
-
- if (!(hints & ImplicitObject)) {
- local.coreIndex = -1;
- lastData = &local;
- return QScriptClass::HandlesWriteAccess;
- }
-
- return 0;
-}
-
-QDeclarativeObjectScriptClass::Value
-QDeclarativeObjectScriptClass::property(Object *object, const Identifier &name)
-{
- return property(toQObject(object), name);
-}
-
-QDeclarativeObjectScriptClass::Value
-QDeclarativeObjectScriptClass::property(QObject *obj, const Identifier &name)
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- if (name == m_destroyId.identifier)
- return Value(scriptEngine, m_destroy);
- else if (name == m_toStringId.identifier)
- return Value(scriptEngine, m_toString);
-
- if (lastData && !lastData->isValid())
- return Value();
-
- Q_ASSERT(obj);
-
- QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine);
-
- if (lastTNData) {
-
- if (lastTNData->type)
- return Value(scriptEngine, enginePriv->typeNameClass->newObject(obj, lastTNData->type));
- else
- return Value(scriptEngine, enginePriv->typeNameClass->newObject(obj, lastTNData->typeNamespace));
-
- } else if (lastData->flags & QDeclarativePropertyCache::Data::IsFunction) {
- if (lastData->flags & QDeclarativePropertyCache::Data::IsVMEFunction) {
- return Value(scriptEngine, ((QDeclarativeVMEMetaObject *)(obj->metaObject()))->vmeMethod(lastData->coreIndex));
- } else {
- // Uncomment to use QtScript method call logic
- // QScriptValue sobj = scriptEngine->newQObject(obj);
- // return Value(scriptEngine, sobj.property(toString(name)));
- return Value(scriptEngine, methods.newMethod(obj, lastData));
- }
- } else {
- if (enginePriv->captureProperties && !(lastData->flags & QDeclarativePropertyCache::Data::IsConstant)) {
- if (lastData->coreIndex == 0) {
- enginePriv->capturedProperties <<
- QDeclarativeEnginePrivate::CapturedProperty(QDeclarativeData::get(obj, true)->objectNameNotifier());
- } else {
- enginePriv->capturedProperties <<
- QDeclarativeEnginePrivate::CapturedProperty(obj, lastData->coreIndex, lastData->notifyIndex);
- }
- }
-
- if (QDeclarativeValueTypeFactory::isValueType((uint)lastData->propType)) {
- QDeclarativeValueType *valueType = enginePriv->valueTypes[lastData->propType];
- if (valueType)
- return Value(scriptEngine, enginePriv->valueTypeClass->newObject(obj, lastData->coreIndex, valueType));
- }
-
- if (lastData->flags & QDeclarativePropertyCache::Data::IsQList) {
- return Value(scriptEngine, enginePriv->listClass->newList(obj, lastData->coreIndex, lastData->propType));
- } else if (lastData->flags & QDeclarativePropertyCache::Data::IsQObjectDerived) {
- QObject *rv = 0;
- void *args[] = { &rv, 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
- return Value(scriptEngine, newQObject(rv, lastData->propType));
- } else if (lastData->flags & QDeclarativePropertyCache::Data::IsQScriptValue) {
- QScriptValue rv = scriptEngine->nullValue();
- void *args[] = { &rv, 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
- return Value(scriptEngine, rv);
- } else if (lastData->propType == QMetaType::QReal) {
- qreal rv = 0;
- void *args[] = { &rv, 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
- return Value(scriptEngine, rv);
- } else if (lastData->propType == QMetaType::Int || lastData->flags & QDeclarativePropertyCache::Data::IsEnumType) {
- int rv = 0;
- void *args[] = { &rv, 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
- return Value(scriptEngine, rv);
- } else if (lastData->propType == QMetaType::Bool) {
- bool rv = false;
- void *args[] = { &rv, 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
- return Value(scriptEngine, rv);
- } else if (lastData->propType == QMetaType::QString) {
- QString rv;
- void *args[] = { &rv, 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
- return Value(scriptEngine, rv);
- } else if (lastData->propType == QMetaType::UInt) {
- uint rv = 0;
- void *args[] = { &rv, 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
- return Value(scriptEngine, rv);
- } else if (lastData->propType == QMetaType::Float) {
- float rv = 0;
- void *args[] = { &rv, 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
- return Value(scriptEngine, rv);
- } else if (lastData->propType == QMetaType::Double) {
- double rv = 0;
- void *args[] = { &rv, 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
- return Value(scriptEngine, rv);
- } else {
- QVariant var = obj->metaObject()->property(lastData->coreIndex).read(obj);
- return Value(scriptEngine, enginePriv->scriptValueFromVariant(var));
- }
- }
-}
-
-void QDeclarativeObjectScriptClass::setProperty(Object *object,
- const Identifier &name,
- const QScriptValue &value)
-{
- return setProperty(toQObject(object), name, value, context());
-}
-
-void QDeclarativeObjectScriptClass::setProperty(QObject *obj,
- const Identifier &name,
- const QScriptValue &value,
- QScriptContext *context,
- QDeclarativeContextData *evalContext)
-{
- Q_UNUSED(name);
-
- Q_ASSERT(obj);
- Q_ASSERT(lastData);
- Q_ASSERT(context);
-
- if (!lastData->isValid()) {
- QString error = QLatin1String("Cannot assign to non-existent property \"") +
- toString(name) + QLatin1Char('\"');
- context->throwError(error);
- return;
- }
-
- if (!(lastData->flags & QDeclarativePropertyCache::Data::IsWritable) &&
- !(lastData->flags & QDeclarativePropertyCache::Data::IsQList)) {
- QString error = QLatin1String("Cannot assign to read-only property \"") +
- toString(name) + QLatin1Char('\"');
- context->throwError(error);
- return;
- }
-
- QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine);
-
- if (!evalContext) {
- // Global object, QScriptContext activation object, QDeclarativeContext object
- QScriptValue scopeNode = scopeChainValue(context, -3);
- if (scopeNode.isValid()) {
- Q_ASSERT(scriptClass(scopeNode) == enginePriv->contextClass);
-
- evalContext = enginePriv->contextClass->contextFromValue(scopeNode);
- }
- }
-
- QDeclarativeBinding *newBinding = 0;
- if (value.isFunction() && !value.isRegExp()) {
- QScriptContextInfo ctxtInfo(context);
- QDeclarativePropertyCache::ValueTypeData valueTypeData;
-
- newBinding = new QDeclarativeBinding(value, obj, evalContext);
- newBinding->setSourceLocation(ctxtInfo.fileName(), ctxtInfo.functionStartLineNumber());
- newBinding->setTarget(QDeclarativePropertyPrivate::restore(*lastData, valueTypeData, obj, evalContext));
- if (newBinding->expression().contains(QLatin1String("this")))
- newBinding->setEvaluateFlags(newBinding->evaluateFlags() | QDeclarativeBinding::RequiresThisObject);
- }
-
- QDeclarativeAbstractBinding *delBinding =
- QDeclarativePropertyPrivate::setBinding(obj, lastData->coreIndex, -1, newBinding);
- if (delBinding)
- delBinding->destroy();
-
- if (value.isNull() && lastData->flags & QDeclarativePropertyCache::Data::IsQObjectDerived) {
- QObject *o = 0;
- int status = -1;
- int flags = 0;
- void *argv[] = { &o, 0, &status, &flags };
- QMetaObject::metacall(obj, QMetaObject::WriteProperty, lastData->coreIndex, argv);
- } else if (value.isUndefined() && lastData->flags & QDeclarativePropertyCache::Data::IsResettable) {
- void *a[] = { 0 };
- QMetaObject::metacall(obj, QMetaObject::ResetProperty, lastData->coreIndex, a);
- } else if (value.isUndefined() && lastData->propType == qMetaTypeId<QVariant>()) {
- QDeclarativePropertyPrivate::write(obj, *lastData, QVariant(), evalContext);
- } else if (value.isUndefined()) {
- QString error = QLatin1String("Cannot assign [undefined] to ") +
- QLatin1String(QMetaType::typeName(lastData->propType));
- context->throwError(error);
- } else if (value.isFunction() && !value.isRegExp()) {
- // this is handled by the binding creation above
- } else {
- //### expand optimization for other known types
- if (lastData->propType == QMetaType::Int && value.isNumber()) {
- int rawValue = qRound(value.toNumber());
- int status = -1;
- int flags = 0;
- void *a[] = { (void *)&rawValue, 0, &status, &flags };
- QMetaObject::metacall(obj, QMetaObject::WriteProperty,
- lastData->coreIndex, a);
- return;
- } else if (lastData->propType == QMetaType::QReal && value.isNumber()) {
- qreal rawValue = qreal(value.toNumber());
- int status = -1;
- int flags = 0;
- void *a[] = { (void *)&rawValue, 0, &status, &flags };
- QMetaObject::metacall(obj, QMetaObject::WriteProperty,
- lastData->coreIndex, a);
- return;
- } else if (lastData->propType == QMetaType::QString && value.isString()) {
- const QString &rawValue = value.toString();
- int status = -1;
- int flags = 0;
- void *a[] = { (void *)&rawValue, 0, &status, &flags };
- QMetaObject::metacall(obj, QMetaObject::WriteProperty,
- lastData->coreIndex, a);
- return;
- }
-
- QVariant v;
- if (lastData->flags & QDeclarativePropertyCache::Data::IsQList)
- v = enginePriv->scriptValueToVariant(value, qMetaTypeId<QList<QObject *> >());
- else
- v = enginePriv->scriptValueToVariant(value, lastData->propType);
-
- if (!QDeclarativePropertyPrivate::write(obj, *lastData, v, evalContext)) {
- const char *valueType = 0;
- if (v.userType() == QVariant::Invalid) valueType = "null";
- else valueType = QMetaType::typeName(v.userType());
-
- QString error = QLatin1String("Cannot assign ") +
- QLatin1String(valueType) +
- QLatin1String(" to ") +
- QLatin1String(QMetaType::typeName(lastData->propType));
- context->throwError(error);
- }
- }
-}
-
-bool QDeclarativeObjectScriptClass::isQObject() const
-{
- return true;
-}
-
-QObject *QDeclarativeObjectScriptClass::toQObject(Object *object, bool *ok)
-{
- if (ok) *ok = true;
-
- ObjectData *data = (ObjectData*)object;
- return data->object.data();
-}
-
-QScriptValue QDeclarativeObjectScriptClass::tostring(QScriptContext *context, QScriptEngine *)
-{
- QObject* obj = context->thisObject().toQObject();
-
- QString ret;
- if(obj){
- QString objectName = obj->objectName();
-
- ret += QString::fromUtf8(obj->metaObject()->className());
- ret += QLatin1String("(0x");
- ret += QString::number((quintptr)obj,16);
-
- if (!objectName.isEmpty()) {
- ret += QLatin1String(", \"");
- ret += objectName;
- ret += QLatin1Char('\"');
- }
-
- ret += QLatin1Char(')');
- }else{
- ret += QLatin1String("null");
- }
- return QScriptValue(ret);
-}
-
-QScriptValue QDeclarativeObjectScriptClass::destroy(QScriptContext *context, QScriptEngine *engine)
-{
- QDeclarativeEnginePrivate *p = QDeclarativeEnginePrivate::get(engine);
- QScriptValue that = context->thisObject();
-
- if (scriptClass(that) != p->objectClass)
- return engine->undefinedValue();
-
- ObjectData *data = (ObjectData *)p->objectClass->object(that);
- if (!data->object)
- return engine->undefinedValue();
-
- QDeclarativeData *ddata = QDeclarativeData::get(data->object, false);
- if (!ddata || ddata->indestructible)
- return engine->currentContext()->throwError(QLatin1String("Invalid attempt to destroy() an indestructible object"));
-
- QObject *obj = data->object;
- int delay = 0;
- if (context->argumentCount() > 0)
- delay = context->argument(0).toInt32();
- if (delay > 0)
- QTimer::singleShot(delay, obj, SLOT(deleteLater()));
- else
- obj->deleteLater();
-
- return engine->undefinedValue();
-}
-
-QStringList QDeclarativeObjectScriptClass::propertyNames(Object *object)
-{
- QObject *obj = toQObject(object);
- if (!obj)
- return QStringList();
-
- QDeclarativeEnginePrivate *enginePrivate = QDeclarativeEnginePrivate::get(engine);
-
- QDeclarativePropertyCache *cache = 0;
- QDeclarativeData *ddata = QDeclarativeData::get(obj);
- if (ddata)
- cache = ddata->propertyCache;
- if (!cache) {
- cache = enginePrivate->cache(obj);
- if (cache) {
- if (ddata) { cache->addref(); ddata->propertyCache = cache; }
- } else {
- // Not cachable - fall back to QMetaObject (eg. dynamic meta object)
- // XXX QDeclarativeOpenMetaObject has a cache, so this is suboptimal.
- // XXX This is a workaround for QTBUG-9420.
- const QMetaObject *mo = obj->metaObject();
- QStringList r;
- int pc = mo->propertyCount();
- int po = mo->propertyOffset();
- for (int i=po; i<pc; ++i)
- r += QString::fromUtf8(mo->property(i).name());
- return r;
- }
- }
- return cache->propertyNames();
-}
-
-bool QDeclarativeObjectScriptClass::compare(Object *o1, Object *o2)
-{
- ObjectData *d1 = (ObjectData *)o1;
- ObjectData *d2 = (ObjectData *)o2;
-
- return d1 == d2 || d1->object == d2->object;
-}
-
-struct MethodData : public QScriptDeclarativeClass::Object {
- MethodData(QObject *o, const QDeclarativePropertyCache::Data &d) : object(o), data(d) {}
-
- QDeclarativeGuard<QObject> object;
- QDeclarativePropertyCache::Data data;
-};
-
-QDeclarativeObjectMethodScriptClass::QDeclarativeObjectMethodScriptClass(QDeclarativeEngine *bindEngine)
-: QScriptDeclarativeClass(QDeclarativeEnginePrivate::getScriptEngine(bindEngine)),
- engine(bindEngine)
-{
- qRegisterMetaType<QList<QObject *> >("QList<QObject *>");
-
- setSupportsCall(true);
-
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- m_connect = scriptEngine->newFunction(connect);
- m_connectId = createPersistentIdentifier(QLatin1String("connect"));
- m_disconnect = scriptEngine->newFunction(disconnect);
- m_disconnectId = createPersistentIdentifier(QLatin1String("disconnect"));
-}
-
-QDeclarativeObjectMethodScriptClass::~QDeclarativeObjectMethodScriptClass()
-{
-}
-
-QScriptValue QDeclarativeObjectMethodScriptClass::newMethod(QObject *object, const QDeclarativePropertyCache::Data *method)
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- return newObject(scriptEngine, this, new MethodData(object, *method));
-}
-
-QScriptValue QDeclarativeObjectMethodScriptClass::connect(QScriptContext *context, QScriptEngine *engine)
-{
- QDeclarativeEnginePrivate *p = QDeclarativeEnginePrivate::get(engine);
-
- QScriptValue that = context->thisObject();
- if (&p->objectClass->methods != scriptClass(that))
- return engine->undefinedValue();
-
- MethodData *data = (MethodData *)object(that);
-
- if (!data->object || context->argumentCount() == 0)
- return engine->undefinedValue();
-
- QByteArray signal("2");
- signal.append(data->object->metaObject()->method(data->data.coreIndex).signature());
-
- if (context->argumentCount() == 1) {
- qScriptConnect(data->object, signal.constData(), QScriptValue(), context->argument(0));
- } else {
- qScriptConnect(data->object, signal.constData(), context->argument(0), context->argument(1));
- }
-
- return engine->undefinedValue();
-}
-
-QScriptValue QDeclarativeObjectMethodScriptClass::disconnect(QScriptContext *context, QScriptEngine *engine)
-{
- QDeclarativeEnginePrivate *p = QDeclarativeEnginePrivate::get(engine);
-
- QScriptValue that = context->thisObject();
- if (&p->objectClass->methods != scriptClass(that))
- return engine->undefinedValue();
-
- MethodData *data = (MethodData *)object(that);
-
- if (!data->object || context->argumentCount() == 0)
- return engine->undefinedValue();
-
- QByteArray signal("2");
- signal.append(data->object->metaObject()->method(data->data.coreIndex).signature());
-
- if (context->argumentCount() == 1) {
- qScriptDisconnect(data->object, signal.constData(), QScriptValue(), context->argument(0));
- } else {
- qScriptDisconnect(data->object, signal.constData(), context->argument(0), context->argument(1));
- }
-
- return engine->undefinedValue();
-}
-
-QScriptClass::QueryFlags
-QDeclarativeObjectMethodScriptClass::queryProperty(Object *, const Identifier &name,
- QScriptClass::QueryFlags flags)
-{
- Q_UNUSED(flags);
- if (name == m_connectId.identifier || name == m_disconnectId.identifier)
- return QScriptClass::HandlesReadAccess;
- else
- return 0;
-
-}
-
-QDeclarativeObjectMethodScriptClass::Value
-QDeclarativeObjectMethodScriptClass::property(Object *, const Identifier &name)
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- if (name == m_connectId.identifier)
- return Value(scriptEngine, m_connect);
- else if (name == m_disconnectId.identifier)
- return Value(scriptEngine, m_disconnect);
- else
- return Value();
-}
-
-namespace {
-struct MetaCallArgument {
- inline MetaCallArgument();
- inline ~MetaCallArgument();
- inline void *dataPtr();
-
- inline void initAsType(int type, QDeclarativeEngine *);
- void fromScriptValue(int type, QDeclarativeEngine *, const QScriptValue &);
- inline QScriptDeclarativeClass::Value toValue(QDeclarativeEngine *);
-
-private:
- MetaCallArgument(const MetaCallArgument &);
-
- inline void cleanup();
-
- char data[4 * sizeof(void *)];
- int type;
- bool isObjectType;
-};
-}
-
-MetaCallArgument::MetaCallArgument()
-: type(QVariant::Invalid), isObjectType(false)
-{
-}
-
-MetaCallArgument::~MetaCallArgument()
-{
- cleanup();
-}
-
-void MetaCallArgument::cleanup()
-{
- if (type == QMetaType::QString) {
- ((QString *)&data)->~QString();
- } else if (type == -1 || type == qMetaTypeId<QVariant>()) {
- ((QVariant *)&data)->~QVariant();
- } else if (type == qMetaTypeId<QScriptValue>()) {
- ((QScriptValue *)&data)->~QScriptValue();
- } else if (type == qMetaTypeId<QList<QObject *> >()) {
- ((QList<QObject *> *)&data)->~QList<QObject *>();
- }
-}
-
-void *MetaCallArgument::dataPtr()
-{
- if (type == -1)
- return ((QVariant *)data)->data();
- else
- return (void *)&data;
-}
-
-void MetaCallArgument::initAsType(int callType, QDeclarativeEngine *e)
-{
- if (type != 0) { cleanup(); type = 0; }
- if (callType == 0) return;
-
- QScriptEngine *engine = QDeclarativeEnginePrivate::getScriptEngine(e);
-
- if (callType == qMetaTypeId<QScriptValue>()) {
- new (&data) QScriptValue(engine->undefinedValue());
- type = callType;
- } else if (callType == QMetaType::Int ||
- callType == QMetaType::UInt ||
- callType == QMetaType::Bool ||
- callType == QMetaType::Double ||
- callType == QMetaType::Float) {
- type = callType;
- } else if (callType == QMetaType::QObjectStar) {
- *((QObject **)&data) = 0;
- type = callType;
- } else if (callType == QMetaType::QString) {
- new (&data) QString();
- type = callType;
- } else if (callType == qMetaTypeId<QVariant>()) {
- type = callType;
- new (&data) QVariant();
- } else if (callType == qMetaTypeId<QList<QObject *> >()) {
- type = callType;
- new (&data) QList<QObject *>();
- } else {
- type = -1;
- new (&data) QVariant(callType, (void *)0);
- }
-}
-
-void MetaCallArgument::fromScriptValue(int callType, QDeclarativeEngine *engine, const QScriptValue &value)
-{
- if (type != 0) { cleanup(); type = 0; }
-
- if (callType == qMetaTypeId<QScriptValue>()) {
- new (&data) QScriptValue(value);
- type = qMetaTypeId<QScriptValue>();
- } else if (callType == QMetaType::Int) {
- *((int *)&data) = int(value.toInt32());
- type = callType;
- } else if (callType == QMetaType::UInt) {
- *((uint *)&data) = uint(value.toUInt32());
- type = callType;
- } else if (callType == QMetaType::Bool) {
- *((bool *)&data) = value.toBool();
- type = callType;
- } else if (callType == QMetaType::Double) {
- *((double *)&data) = double(value.toNumber());
- type = callType;
- } else if (callType == QMetaType::Float) {
- *((float *)&data) = float(value.toNumber());
- type = callType;
- } else if (callType == QMetaType::QString) {
- if (value.isNull() || value.isUndefined())
- new (&data) QString();
- else
- new (&data) QString(value.toString());
- type = callType;
- } else if (callType == QMetaType::QObjectStar) {
- *((QObject **)&data) = value.toQObject();
- type = callType;
- } else if (callType == qMetaTypeId<QVariant>()) {
- new (&data) QVariant(QDeclarativeEnginePrivate::get(engine)->scriptValueToVariant(value));
- type = callType;
- } else if (callType == qMetaTypeId<QList<QObject*> >()) {
- QList<QObject *> *list = new (&data) QList<QObject *>();
- if (value.isArray()) {
- int length = value.property(QLatin1String("length")).toInt32();
- for (int ii = 0; ii < length; ++ii) {
- QScriptValue arrayItem = value.property(ii);
- QObject *d = arrayItem.toQObject();
- list->append(d);
- }
- } else if (QObject *d = value.toQObject()) {
- list->append(d);
- }
- type = callType;
- } else {
- new (&data) QVariant();
- type = -1;
-
- QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(engine);
- QVariant v = priv->scriptValueToVariant(value);
- if (v.userType() == callType) {
- *((QVariant *)&data) = v;
- } else if (v.canConvert((QVariant::Type)callType)) {
- *((QVariant *)&data) = v;
- ((QVariant *)&data)->convert((QVariant::Type)callType);
- } else if (const QMetaObject *mo = priv->rawMetaObjectForType(callType)) {
- QObject *obj = priv->toQObject(v);
-
- if (obj) {
- const QMetaObject *objMo = obj->metaObject();
- while (objMo && objMo != mo) objMo = objMo->superClass();
- if (!objMo) obj = 0;
- }
-
- *((QVariant *)&data) = QVariant(callType, &obj);
- } else {
- *((QVariant *)&data) = QVariant(callType, (void *)0);
- }
- }
-}
-
-QScriptDeclarativeClass::Value MetaCallArgument::toValue(QDeclarativeEngine *e)
-{
- QScriptEngine *engine = QDeclarativeEnginePrivate::getScriptEngine(e);
-
- if (type == qMetaTypeId<QScriptValue>()) {
- return QScriptDeclarativeClass::Value(engine, *((QScriptValue *)&data));
- } else if (type == QMetaType::Int) {
- return QScriptDeclarativeClass::Value(engine, *((int *)&data));
- } else if (type == QMetaType::UInt) {
- return QScriptDeclarativeClass::Value(engine, *((uint *)&data));
- } else if (type == QMetaType::Bool) {
- return QScriptDeclarativeClass::Value(engine, *((bool *)&data));
- } else if (type == QMetaType::Double) {
- return QScriptDeclarativeClass::Value(engine, *((double *)&data));
- } else if (type == QMetaType::Float) {
- return QScriptDeclarativeClass::Value(engine, *((float *)&data));
- } else if (type == QMetaType::QString) {
- return QScriptDeclarativeClass::Value(engine, *((QString *)&data));
- } else if (type == QMetaType::QObjectStar) {
- QObject *object = *((QObject **)&data);
- if (object)
- QDeclarativeData::get(object, true)->setImplicitDestructible();
- QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(e);
- return QScriptDeclarativeClass::Value(engine, priv->objectClass->newQObject(object));
- } else if (type == qMetaTypeId<QList<QObject *> >()) {
- QList<QObject *> &list = *(QList<QObject *>*)&data;
- QScriptValue rv = engine->newArray(list.count());
- QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(e);
- for (int ii = 0; ii < list.count(); ++ii) {
- QObject *object = list.at(ii);
- QDeclarativeData::get(object, true)->setImplicitDestructible();
- rv.setProperty(ii, priv->objectClass->newQObject(object));
- }
- return QScriptDeclarativeClass::Value(engine, rv);
- } else if (type == -1 || type == qMetaTypeId<QVariant>()) {
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(e);
- QScriptValue rv = ep->scriptValueFromVariant(*((QVariant *)&data));
- if (rv.isQObject()) {
- QObject *object = rv.toQObject();
- if (object)
- QDeclarativeData::get(object, true)->setImplicitDestructible();
- }
- return QScriptDeclarativeClass::Value(engine, rv);
- } else {
- return QScriptDeclarativeClass::Value();
- }
-}
-
-int QDeclarativeObjectMethodScriptClass::enumType(const QMetaObject *meta, const QString &strname)
-{
- QByteArray str = strname.toUtf8();
- QByteArray scope;
- QByteArray name;
- int scopeIdx = str.lastIndexOf("::");
- if (scopeIdx != -1) {
- scope = str.left(scopeIdx);
- name = str.mid(scopeIdx + 2);
- } else {
- name = str;
- }
- for (int i = meta->enumeratorCount() - 1; i >= 0; --i) {
- QMetaEnum m = meta->enumerator(i);
- if ((m.name() == name) && (scope.isEmpty() || (m.scope() == scope)))
- return QVariant::Int;
- }
- return QVariant::Invalid;
-}
-
-QDeclarativeObjectMethodScriptClass::Value QDeclarativeObjectMethodScriptClass::call(Object *o, QScriptContext *ctxt)
-{
- MethodData *method = static_cast<MethodData *>(o);
-
- if (method->data.relatedIndex == -1)
- return callPrecise(method->object, method->data, ctxt);
- else
- return callOverloaded(method, ctxt);
-}
-
-QDeclarativeObjectMethodScriptClass::Value
-QDeclarativeObjectMethodScriptClass::callPrecise(QObject *object, const QDeclarativePropertyCache::Data &data,
- QScriptContext *ctxt)
-{
- if (data.flags & QDeclarativePropertyCache::Data::HasArguments) {
-
- QMetaMethod m = object->metaObject()->method(data.coreIndex);
- QList<QByteArray> argTypeNames = m.parameterTypes();
- QVarLengthArray<int, 9> argTypes(argTypeNames.count());
-
- // ### Cache
- for (int ii = 0; ii < argTypeNames.count(); ++ii) {
- argTypes[ii] = QMetaType::type(argTypeNames.at(ii));
- if (argTypes[ii] == QVariant::Invalid)
- argTypes[ii] = enumType(object->metaObject(), QString::fromLatin1(argTypeNames.at(ii)));
- if (argTypes[ii] == QVariant::Invalid)
- return Value(ctxt, ctxt->throwError(QString::fromLatin1("Unknown method parameter type: %1").arg(QLatin1String(argTypeNames.at(ii)))));
- }
-
- if (argTypes.count() > ctxt->argumentCount())
- return Value(ctxt, ctxt->throwError(QLatin1String("Insufficient arguments")));
-
- return callMethod(object, data.coreIndex, data.propType, argTypes.count(), argTypes.data(), ctxt);
-
- } else {
-
- return callMethod(object, data.coreIndex, data.propType, 0, 0, ctxt);
-
- }
-}
-
-QDeclarativeObjectMethodScriptClass::Value
-QDeclarativeObjectMethodScriptClass::callMethod(QObject *object, int index,
- int returnType, int argCount, int *argTypes,
- QScriptContext *ctxt)
-{
- if (argCount > 0) {
-
- QVarLengthArray<MetaCallArgument, 9> args(argCount + 1);
- args[0].initAsType(returnType, engine);
-
- for (int ii = 0; ii < argCount; ++ii)
- args[ii + 1].fromScriptValue(argTypes[ii], engine, ctxt->argument(ii));
-
- QVarLengthArray<void *, 9> argData(args.count());
- for (int ii = 0; ii < args.count(); ++ii)
- argData[ii] = args[ii].dataPtr();
-
- QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, index, argData.data());
-
- return args[0].toValue(engine);
-
- } else if (returnType != 0) {
-
- MetaCallArgument arg;
- arg.initAsType(returnType, engine);
-
- void *args[] = { arg.dataPtr() };
-
- QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, index, args);
-
- return arg.toValue(engine);
-
- } else {
-
- void *args[] = { 0 };
- QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, index, args);
- return Value();
-
- }
-}
-
-/*!
-Resolve the overloaded method to call. The algorithm works conceptually like this:
- 1. Resolve the set of overloads it is *possible* to call.
- Impossible overloads include those that have too many parameters or have parameters
- of unknown type.
- 2. Filter the set of overloads to only contain those with the closest number of
- parameters.
- For example, if we are called with 3 parameters and there are 2 overloads that
- take 2 parameters and one that takes 3, eliminate the 2 parameter overloads.
- 3. Find the best remaining overload based on its match score.
- If two or more overloads have the same match score, call the last one. The match
- score is constructed by adding the matchScore() result for each of the parameters.
-*/
-QDeclarativeObjectMethodScriptClass::Value
-QDeclarativeObjectMethodScriptClass::callOverloaded(MethodData *method, QScriptContext *ctxt)
-{
- int argumentCount = ctxt->argumentCount();
-
- QDeclarativePropertyCache::Data *best = 0;
- int bestParameterScore = INT_MAX;
- int bestMatchScore = INT_MAX;
-
- QDeclarativePropertyCache::Data dummy;
- QDeclarativePropertyCache::Data *attempt = &method->data;
-
- do {
- QList<QByteArray> methodArgTypeNames;
-
- if (attempt->flags & QDeclarativePropertyCache::Data::HasArguments)
- methodArgTypeNames = method->object->metaObject()->method(attempt->coreIndex).parameterTypes();
-
- int methodArgumentCount = methodArgTypeNames.count();
-
- if (methodArgumentCount > argumentCount)
- continue; // We don't have sufficient arguments to call this method
-
- int methodParameterScore = argumentCount - methodArgumentCount;
- if (methodParameterScore > bestParameterScore)
- continue; // We already have a better option
-
- int methodMatchScore = 0;
- QVarLengthArray<int, 9> methodArgTypes(methodArgumentCount);
-
- bool unknownArgument = false;
- for (int ii = 0; ii < methodArgumentCount; ++ii) {
- methodArgTypes[ii] = QMetaType::type(methodArgTypeNames.at(ii));
- if (methodArgTypes[ii] == QVariant::Invalid)
- methodArgTypes[ii] = enumType(method->object->metaObject(),
- QString::fromLatin1(methodArgTypeNames.at(ii)));
- if (methodArgTypes[ii] == QVariant::Invalid) {
- unknownArgument = true;
- break;
- }
- methodMatchScore += matchScore(ctxt->argument(ii), methodArgTypes[ii], methodArgTypeNames.at(ii));
- }
- if (unknownArgument)
- continue; // We don't understand all the parameters
-
- if (bestParameterScore > methodParameterScore || bestMatchScore > methodMatchScore) {
- best = attempt;
- bestParameterScore = methodParameterScore;
- bestMatchScore = methodMatchScore;
- }
-
- if (bestParameterScore == 0 && bestMatchScore == 0)
- break; // We can't get better than that
-
- } while((attempt = relatedMethod(method->object, attempt, dummy)) != 0);
-
- if (best) {
- return callPrecise(method->object, *best, ctxt);
- } else {
- QString error = QLatin1String("Unable to determine callable overload. Candidates are:");
- QDeclarativePropertyCache::Data *candidate = &method->data;
- while (candidate) {
- error += QLatin1String("\n ") + QString::fromUtf8(method->object->metaObject()->method(candidate->coreIndex).signature());
- candidate = relatedMethod(method->object, candidate, dummy);
- }
- return Value(ctxt, ctxt->throwError(error));
- }
-}
-
-/*!
- Returns the match score for converting \a actual to be of type \a conversionType. A
- zero score means "perfect match" whereas a higher score is worse.
-
- The conversion table is copied out of the QtScript callQtMethod() function.
-*/
-int QDeclarativeObjectMethodScriptClass::matchScore(const QScriptValue &actual, int conversionType,
- const QByteArray &conversionTypeName)
-{
- if (actual.isNumber()) {
- switch (conversionType) {
- case QMetaType::Double:
- return 0;
- case QMetaType::Float:
- return 1;
- case QMetaType::LongLong:
- case QMetaType::ULongLong:
- return 2;
- case QMetaType::Long:
- case QMetaType::ULong:
- return 3;
- case QMetaType::Int:
- case QMetaType::UInt:
- return 4;
- case QMetaType::Short:
- case QMetaType::UShort:
- return 5;
- break;
- case QMetaType::Char:
- case QMetaType::UChar:
- return 6;
- default:
- return 10;
- }
- } else if (actual.isString()) {
- switch (conversionType) {
- case QMetaType::QString:
- return 0;
- default:
- return 10;
- }
- } else if (actual.isBoolean()) {
- switch (conversionType) {
- case QMetaType::Bool:
- return 0;
- default:
- return 10;
- }
- } else if (actual.isDate()) {
- switch (conversionType) {
- case QMetaType::QDateTime:
- return 0;
- case QMetaType::QDate:
- return 1;
- case QMetaType::QTime:
- return 2;
- default:
- return 10;
- }
- } else if (actual.isRegExp()) {
- switch (conversionType) {
- case QMetaType::QRegExp:
- return 0;
- default:
- return 10;
- }
- } else if (actual.isVariant()) {
- if (conversionType == qMetaTypeId<QVariant>())
- return 0;
- else if (actual.toVariant().userType() == conversionType)
- return 0;
- else
- return 10;
- } else if (actual.isArray()) {
- switch (conversionType) {
- case QMetaType::QStringList:
- case QMetaType::QVariantList:
- return 5;
- default:
- return 10;
- }
- } else if (actual.isQObject()) {
- switch (conversionType) {
- case QMetaType::QObjectStar:
- return 0;
- default:
- return 10;
- }
- } else if (actual.isNull()) {
- switch (conversionType) {
- case QMetaType::VoidStar:
- case QMetaType::QObjectStar:
- return 0;
- default:
- if (!conversionTypeName.endsWith('*'))
- return 10;
- else
- return 0;
- }
- } else {
- return 10;
- }
-}
-
-static inline int QMetaObject_methods(const QMetaObject *metaObject)
-{
- struct Private
- {
- int revision;
- int className;
- int classInfoCount, classInfoData;
- int methodCount, methodData;
- };
-
- return reinterpret_cast<const Private *>(metaObject->d.data)->methodCount;
-}
-
-static QByteArray QMetaMethod_name(const QMetaMethod &m)
-{
- QByteArray sig = m.signature();
- int paren = sig.indexOf('(');
- if (paren == -1)
- return sig;
- else
- return sig.left(paren);
-}
-
-/*!
-Returns the next related method, if one, or 0.
-*/
-QDeclarativePropertyCache::Data *
-QDeclarativeObjectMethodScriptClass::relatedMethod(QObject *object, QDeclarativePropertyCache::Data *current,
- QDeclarativePropertyCache::Data &dummy)
-{
- QDeclarativePropertyCache *cache = QDeclarativeData::get(object)->propertyCache;
- if (current->relatedIndex == -1)
- return 0;
-
- if (cache) {
- return cache->method(current->relatedIndex);
- } else {
- const QMetaObject *mo = object->metaObject();
- int methodOffset = mo->methodCount() - QMetaObject_methods(mo);
-
- while (methodOffset > current->relatedIndex) {
- mo = mo->superClass();
- methodOffset -= QMetaObject_methods(mo);
- }
-
- QMetaMethod method = mo->method(current->relatedIndex);
- dummy.load(method);
-
- // Look for overloaded methods
- QByteArray methodName = QMetaMethod_name(method);
- for (int ii = current->relatedIndex - 1; ii >= methodOffset; --ii) {
- if (methodName == QMetaMethod_name(mo->method(ii))) {
- dummy.relatedIndex = ii;
- return &dummy;
- }
- }
-
- return &dummy;
- }
-}
-
-QT_END_NAMESPACE
-