aboutsummaryrefslogtreecommitdiffstats
path: root/src/declarative/qml/qdeclarativeenginedebug.cpp
diff options
context:
space:
mode:
authorQt by Nokia <qt-info@nokia.com>2011-04-27 12:05:43 +0200
committeraxis <qt-info@nokia.com>2011-04-27 12:05:43 +0200
commit885735d011472bcfbb96e688d9e64553d7fe9d4b (patch)
tree734963625eba643bf11bc4870a4c407809a6400a /src/declarative/qml/qdeclarativeenginedebug.cpp
Initial import from the monolithic Qt.
This is the beginning of revision history for this module. If you want to look at revision history older than this, please refer to the Qt Git wiki for how to use Git history grafting. At the time of writing, this wiki is located here: http://qt.gitorious.org/qt/pages/GitIntroductionWithQt If you have already performed the grafting and you don't see any history beyond this commit, try running "git log" with the "--follow" argument. Branched from the monolithic repo, Qt master branch, at commit 896db169ea224deb96c59ce8af800d019de63f12
Diffstat (limited to 'src/declarative/qml/qdeclarativeenginedebug.cpp')
-rw-r--r--src/declarative/qml/qdeclarativeenginedebug.cpp735
1 files changed, 735 insertions, 0 deletions
diff --git a/src/declarative/qml/qdeclarativeenginedebug.cpp b/src/declarative/qml/qdeclarativeenginedebug.cpp
new file mode 100644
index 0000000000..b2a05c3235
--- /dev/null
+++ b/src/declarative/qml/qdeclarativeenginedebug.cpp
@@ -0,0 +1,735 @@
+/****************************************************************************
+**
+** 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/qdeclarativeenginedebug_p.h"
+
+#include "private/qdeclarativeboundsignal_p.h"
+#include "qdeclarativeengine.h"
+#include "private/qdeclarativemetatype_p.h"
+#include "qdeclarativeproperty.h"
+#include "private/qdeclarativeproperty_p.h"
+#include "private/qdeclarativebinding_p.h"
+#include "private/qdeclarativecontext_p.h"
+#include "private/qdeclarativewatcher_p.h"
+#include "private/qdeclarativevaluetype_p.h"
+#include "private/qdeclarativevmemetaobject_p.h"
+#include "private/qdeclarativeexpression_p.h"
+#include "private/qdeclarativepropertychanges_p.h"
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qmetaobject.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_GLOBAL_STATIC(QDeclarativeEngineDebugServer, qmlEngineDebugServer);
+
+QDeclarativeEngineDebugServer *QDeclarativeEngineDebugServer::instance()
+{
+ return qmlEngineDebugServer();
+}
+
+QDeclarativeEngineDebugServer::QDeclarativeEngineDebugServer(QObject *parent)
+: QDeclarativeDebugService(QLatin1String("QDeclarativeEngine"), parent),
+ m_watch(new QDeclarativeWatcher(this))
+{
+ QObject::connect(m_watch, SIGNAL(propertyChanged(int,int,QMetaProperty,QVariant)),
+ this, SLOT(propertyChanged(int,int,QMetaProperty,QVariant)));
+}
+
+QDataStream &operator<<(QDataStream &ds,
+ const QDeclarativeEngineDebugServer::QDeclarativeObjectData &data)
+{
+ ds << data.url << data.lineNumber << data.columnNumber << data.idString
+ << data.objectName << data.objectType << data.objectId << data.contextId;
+ return ds;
+}
+
+QDataStream &operator>>(QDataStream &ds,
+ QDeclarativeEngineDebugServer::QDeclarativeObjectData &data)
+{
+ ds >> data.url >> data.lineNumber >> data.columnNumber >> data.idString
+ >> data.objectName >> data.objectType >> data.objectId >> data.contextId;
+ return ds;
+}
+
+QDataStream &operator<<(QDataStream &ds,
+ const QDeclarativeEngineDebugServer::QDeclarativeObjectProperty &data)
+{
+ ds << (int)data.type << data.name << data.value << data.valueTypeName
+ << data.binding << data.hasNotifySignal;
+ return ds;
+}
+
+QDataStream &operator>>(QDataStream &ds,
+ QDeclarativeEngineDebugServer::QDeclarativeObjectProperty &data)
+{
+ int type;
+ ds >> type >> data.name >> data.value >> data.valueTypeName
+ >> data.binding >> data.hasNotifySignal;
+ data.type = (QDeclarativeEngineDebugServer::QDeclarativeObjectProperty::Type)type;
+ return ds;
+}
+
+static inline bool isSignalPropertyName(const QString &signalName)
+{
+ // see QmlCompiler::isSignalPropertyName
+ return signalName.length() >= 3 && signalName.startsWith(QLatin1String("on")) &&
+ signalName.at(2).isLetter() && signalName.at(2).isUpper();
+}
+
+static bool hasValidSignal(QObject *object, const QString &propertyName)
+{
+ if (!isSignalPropertyName(propertyName))
+ return false;
+
+ QString signalName = propertyName.mid(2);
+ signalName[0] = signalName.at(0).toLower();
+
+ int sigIdx = QDeclarativePropertyPrivate::findSignalByName(object->metaObject(), signalName.toLatin1()).methodIndex();
+
+ if (sigIdx == -1)
+ return false;
+
+ return true;
+}
+
+QDeclarativeEngineDebugServer::QDeclarativeObjectProperty
+QDeclarativeEngineDebugServer::propertyData(QObject *obj, int propIdx)
+{
+ QDeclarativeObjectProperty rv;
+
+ QMetaProperty prop = obj->metaObject()->property(propIdx);
+
+ rv.type = QDeclarativeObjectProperty::Unknown;
+ rv.valueTypeName = QString::fromUtf8(prop.typeName());
+ rv.name = QString::fromUtf8(prop.name());
+ rv.hasNotifySignal = prop.hasNotifySignal();
+ QDeclarativeAbstractBinding *binding =
+ QDeclarativePropertyPrivate::binding(QDeclarativeProperty(obj, rv.name));
+ if (binding)
+ rv.binding = binding->expression();
+
+ QVariant value;
+ if (prop.userType() != 0) {
+ value = prop.read(obj);
+ }
+ rv.value = valueContents(value);
+
+ if (QDeclarativeValueTypeFactory::isValueType(prop.userType())) {
+ rv.type = QDeclarativeObjectProperty::Basic;
+ } else if (QDeclarativeMetaType::isQObject(prop.userType())) {
+ rv.type = QDeclarativeObjectProperty::Object;
+ } else if (QDeclarativeMetaType::isList(prop.userType())) {
+ rv.type = QDeclarativeObjectProperty::List;
+ }
+
+ return rv;
+}
+
+QVariant QDeclarativeEngineDebugServer::valueContents(const QVariant &value) const
+{
+ int userType = value.userType();
+
+ if (value.type() == QVariant::List) {
+ QVariantList contents;
+ QVariantList list = value.toList();
+ int count = list.size();
+ for (int i = 0; i < count; i++)
+ contents << valueContents(list.at(i));
+ return contents;
+ }
+
+ if (QDeclarativeValueTypeFactory::isValueType(userType))
+ return value;
+
+ if (QDeclarativeMetaType::isQObject(userType)) {
+ QObject *o = QDeclarativeMetaType::toQObject(value);
+ if (o) {
+ QString name = o->objectName();
+ if (name.isEmpty())
+ name = QLatin1String("<unnamed object>");
+ return name;
+ }
+ }
+
+ return QLatin1String("<unknown value>");
+}
+
+void QDeclarativeEngineDebugServer::buildObjectDump(QDataStream &message,
+ QObject *object, bool recur, bool dumpProperties)
+{
+ message << objectData(object);
+
+ QObjectList children = object->children();
+
+ int childrenCount = children.count();
+ for (int ii = 0; ii < children.count(); ++ii) {
+ if (qobject_cast<QDeclarativeContext*>(children[ii]) || QDeclarativeBoundSignal::cast(children[ii]))
+ --childrenCount;
+ }
+
+ message << childrenCount << recur;
+
+ QList<QDeclarativeObjectProperty> fakeProperties;
+
+ for (int ii = 0; ii < children.count(); ++ii) {
+ QObject *child = children.at(ii);
+ if (qobject_cast<QDeclarativeContext*>(child))
+ continue;
+ QDeclarativeBoundSignal *signal = QDeclarativeBoundSignal::cast(child);
+ if (signal) {
+ if (!dumpProperties)
+ continue;
+ QDeclarativeObjectProperty prop;
+ prop.type = QDeclarativeObjectProperty::SignalProperty;
+ prop.hasNotifySignal = false;
+ QDeclarativeExpression *expr = signal->expression();
+ if (expr) {
+ prop.value = expr->expression();
+ QObject *scope = expr->scopeObject();
+ if (scope) {
+ QString sig = QLatin1String(scope->metaObject()->method(signal->index()).signature());
+ int lparen = sig.indexOf(QLatin1Char('('));
+ if (lparen >= 0) {
+ QString methodName = sig.mid(0, lparen);
+ prop.name = QLatin1String("on") + methodName[0].toUpper()
+ + methodName.mid(1);
+ }
+ }
+ }
+ fakeProperties << prop;
+ } else {
+ if (recur)
+ buildObjectDump(message, child, recur, dumpProperties);
+ else
+ message << objectData(child);
+ }
+ }
+
+ if (!dumpProperties) {
+ message << 0;
+ return;
+ }
+
+ QList<int> propertyIndexes;
+ for (int ii = 0; ii < object->metaObject()->propertyCount(); ++ii) {
+ if (object->metaObject()->property(ii).isScriptable())
+ propertyIndexes << ii;
+ }
+
+ message << propertyIndexes.size() + fakeProperties.count();
+
+ for (int ii = 0; ii < propertyIndexes.size(); ++ii)
+ message << propertyData(object, propertyIndexes.at(ii));
+
+ for (int ii = 0; ii < fakeProperties.count(); ++ii)
+ message << fakeProperties[ii];
+}
+
+void QDeclarativeEngineDebugServer::prepareDeferredObjects(QObject *obj)
+{
+ qmlExecuteDeferred(obj);
+
+ QObjectList children = obj->children();
+ for (int ii = 0; ii < children.count(); ++ii) {
+ QObject *child = children.at(ii);
+ prepareDeferredObjects(child);
+ }
+
+}
+
+void QDeclarativeEngineDebugServer::buildObjectList(QDataStream &message, QDeclarativeContext *ctxt)
+{
+ QDeclarativeContextData *p = QDeclarativeContextData::get(ctxt);
+
+ QString ctxtName = ctxt->objectName();
+ int ctxtId = QDeclarativeDebugService::idForObject(ctxt);
+
+ message << ctxtName << ctxtId;
+
+ int count = 0;
+
+ QDeclarativeContextData *child = p->childContexts;
+ while (child) {
+ ++count;
+ child = child->nextChild;
+ }
+
+ message << count;
+
+ child = p->childContexts;
+ while (child) {
+ buildObjectList(message, child->asQDeclarativeContext());
+ child = child->nextChild;
+ }
+
+ // Clean deleted objects
+ QDeclarativeContextPrivate *ctxtPriv = QDeclarativeContextPrivate::get(ctxt);
+ for (int ii = 0; ii < ctxtPriv->instances.count(); ++ii) {
+ if (!ctxtPriv->instances.at(ii)) {
+ ctxtPriv->instances.removeAt(ii);
+ --ii;
+ }
+ }
+
+ message << ctxtPriv->instances.count();
+ for (int ii = 0; ii < ctxtPriv->instances.count(); ++ii) {
+ message << objectData(ctxtPriv->instances.at(ii));
+ }
+}
+
+void QDeclarativeEngineDebugServer::buildStatesList(QDeclarativeContext *ctxt, bool cleanList=false)
+{
+ if (cleanList)
+ m_allStates.clear();
+
+ QDeclarativeContextPrivate *ctxtPriv = QDeclarativeContextPrivate::get(ctxt);
+ for (int ii = 0; ii < ctxtPriv->instances.count(); ++ii) {
+ buildStatesList(ctxtPriv->instances.at(ii));
+ }
+
+ QDeclarativeContextData *child = QDeclarativeContextData::get(ctxt)->childContexts;
+ while (child) {
+ buildStatesList(child->asQDeclarativeContext());
+ child = child->nextChild;
+ }
+}
+
+void QDeclarativeEngineDebugServer::buildStatesList(QObject *obj)
+{
+ if (QDeclarativeState *state = qobject_cast<QDeclarativeState *>(obj)) {
+ m_allStates.append(state);
+ }
+
+ QObjectList children = obj->children();
+ for (int ii = 0; ii < children.count(); ++ii) {
+ buildStatesList(children.at(ii));
+ }
+}
+
+QDeclarativeEngineDebugServer::QDeclarativeObjectData
+QDeclarativeEngineDebugServer::objectData(QObject *object)
+{
+ QDeclarativeData *ddata = QDeclarativeData::get(object);
+ QDeclarativeObjectData rv;
+ if (ddata && ddata->outerContext) {
+ rv.url = ddata->outerContext->url;
+ rv.lineNumber = ddata->lineNumber;
+ rv.columnNumber = ddata->columnNumber;
+ } else {
+ rv.lineNumber = -1;
+ rv.columnNumber = -1;
+ }
+
+ QDeclarativeContext *context = qmlContext(object);
+ if (context) {
+ QDeclarativeContextData *cdata = QDeclarativeContextData::get(context);
+ if (cdata)
+ rv.idString = cdata->findObjectId(object);
+ }
+
+ rv.objectName = object->objectName();
+ rv.objectId = QDeclarativeDebugService::idForObject(object);
+ rv.contextId = QDeclarativeDebugService::idForObject(qmlContext(object));
+
+ QDeclarativeType *type = QDeclarativeMetaType::qmlType(object->metaObject());
+ if (type) {
+ QString typeName = QLatin1String(type->qmlTypeName());
+ int lastSlash = typeName.lastIndexOf(QLatin1Char('/'));
+ rv.objectType = lastSlash < 0 ? typeName : typeName.mid(lastSlash+1);
+ } else {
+ rv.objectType = QString::fromUtf8(object->metaObject()->className());
+ int marker = rv.objectType.indexOf(QLatin1String("_QMLTYPE_"));
+ if (marker != -1)
+ rv.objectType = rv.objectType.left(marker);
+ }
+
+ return rv;
+}
+
+void QDeclarativeEngineDebugServer::messageReceived(const QByteArray &message)
+{
+ QDataStream ds(message);
+
+ QByteArray type;
+ ds >> type;
+
+ if (type == "LIST_ENGINES") {
+ int queryId;
+ ds >> queryId;
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("LIST_ENGINES_R");
+ rs << queryId << m_engines.count();
+
+ for (int ii = 0; ii < m_engines.count(); ++ii) {
+ QDeclarativeEngine *engine = m_engines.at(ii);
+
+ QString engineName = engine->objectName();
+ int engineId = QDeclarativeDebugService::idForObject(engine);
+
+ rs << engineName << engineId;
+ }
+
+ sendMessage(reply);
+ } else if (type == "LIST_OBJECTS") {
+ int queryId;
+ int engineId = -1;
+ ds >> queryId >> engineId;
+
+ QDeclarativeEngine *engine =
+ qobject_cast<QDeclarativeEngine *>(QDeclarativeDebugService::objectForId(engineId));
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("LIST_OBJECTS_R") << queryId;
+
+ if (engine) {
+ buildObjectList(rs, engine->rootContext());
+ buildStatesList(engine->rootContext(), true);
+ }
+
+ sendMessage(reply);
+ } else if (type == "FETCH_OBJECT") {
+ int queryId;
+ int objectId;
+ bool recurse;
+ bool dumpProperties = true;
+
+ ds >> queryId >> objectId >> recurse >> dumpProperties;
+
+ QObject *object = QDeclarativeDebugService::objectForId(objectId);
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("FETCH_OBJECT_R") << queryId;
+
+ if (object) {
+ if (recurse)
+ prepareDeferredObjects(object);
+ buildObjectDump(rs, object, recurse, dumpProperties);
+ }
+
+ sendMessage(reply);
+ } else if (type == "WATCH_OBJECT") {
+ int queryId;
+ int objectId;
+
+ ds >> queryId >> objectId;
+ bool ok = m_watch->addWatch(queryId, objectId);
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("WATCH_OBJECT_R") << queryId << ok;
+
+ sendMessage(reply);
+ } else if (type == "WATCH_PROPERTY") {
+ int queryId;
+ int objectId;
+ QByteArray property;
+
+ ds >> queryId >> objectId >> property;
+ bool ok = m_watch->addWatch(queryId, objectId, property);
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("WATCH_PROPERTY_R") << queryId << ok;
+
+ sendMessage(reply);
+ } else if (type == "WATCH_EXPR_OBJECT") {
+ int queryId;
+ int debugId;
+ QString expr;
+
+ ds >> queryId >> debugId >> expr;
+ bool ok = m_watch->addWatch(queryId, debugId, expr);
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("WATCH_EXPR_OBJECT_R") << queryId << ok;
+ sendMessage(reply);
+ } else if (type == "NO_WATCH") {
+ int queryId;
+
+ ds >> queryId;
+ m_watch->removeWatch(queryId);
+ } else if (type == "EVAL_EXPRESSION") {
+ int queryId;
+ int objectId;
+ QString expr;
+
+ ds >> queryId >> objectId >> expr;
+
+ QObject *object = QDeclarativeDebugService::objectForId(objectId);
+ QDeclarativeContext *context = qmlContext(object);
+ QVariant result;
+ if (object && context) {
+ QDeclarativeExpression exprObj(context, object, expr);
+ bool undefined = false;
+ QVariant value = exprObj.evaluate(&undefined);
+ if (undefined)
+ result = QLatin1String("<undefined>");
+ else
+ result = valueContents(value);
+ } else {
+ result = QLatin1String("<unknown context>");
+ }
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("EVAL_EXPRESSION_R") << queryId << result;
+
+ sendMessage(reply);
+ } else if (type == "SET_BINDING") {
+ int objectId;
+ QString propertyName;
+ QVariant expr;
+ bool isLiteralValue;
+ ds >> objectId >> propertyName >> expr >> isLiteralValue;
+ setBinding(objectId, propertyName, expr, isLiteralValue);
+ } else if (type == "RESET_BINDING") {
+ int objectId;
+ QString propertyName;
+ ds >> objectId >> propertyName;
+ resetBinding(objectId, propertyName);
+ } else if (type == "SET_METHOD_BODY") {
+ int objectId;
+ QString methodName;
+ QString methodBody;
+ ds >> objectId >> methodName >> methodBody;
+ setMethodBody(objectId, methodName, methodBody);
+ }
+}
+
+void QDeclarativeEngineDebugServer::setBinding(int objectId,
+ const QString &propertyName,
+ const QVariant &expression,
+ bool isLiteralValue)
+{
+ QObject *object = objectForId(objectId);
+ QDeclarativeContext *context = qmlContext(object);
+
+ if (object && context) {
+ QDeclarativeProperty property(object, propertyName, context);
+ if (property.isValid()) {
+
+ bool inBaseState = true;
+
+ foreach(QWeakPointer<QDeclarativeState> statePointer, m_allStates) {
+ if (QDeclarativeState *state = statePointer.data()) {
+ // here we assume that the revert list on itself defines the base state
+ if (state->isStateActive() && state->containsPropertyInRevertList(object, propertyName)) {
+ inBaseState = false;
+
+ QDeclarativeBinding *newBinding = 0;
+ if (!isLiteralValue) {
+ newBinding = new QDeclarativeBinding(expression.toString(), object, context);
+ newBinding->setTarget(property);
+ newBinding->setNotifyOnValueChanged(true);
+ }
+
+ state->changeBindingInRevertList(object, propertyName, newBinding);
+
+ if (isLiteralValue)
+ state->changeValueInRevertList(object, propertyName, expression);
+ }
+ }
+ }
+
+ if (inBaseState) {
+ if (isLiteralValue) {
+ property.write(expression);
+ } else if (hasValidSignal(object, propertyName)) {
+ QDeclarativeExpression *declarativeExpression = new QDeclarativeExpression(context, object, expression.toString());
+ QDeclarativeExpression *oldExpression = QDeclarativePropertyPrivate::setSignalExpression(property, declarativeExpression);
+ declarativeExpression->setSourceLocation(oldExpression->sourceFile(), oldExpression->lineNumber());
+ } else if (property.isProperty()) {
+ QDeclarativeBinding *binding = new QDeclarativeBinding(expression.toString(), object, context);
+ binding->setTarget(property);
+ binding->setNotifyOnValueChanged(true);
+ QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::setBinding(property, binding);
+ if (oldBinding)
+ oldBinding->destroy();
+ binding->update();
+ } else {
+ qWarning() << "QDeclarativeEngineDebugServer::setBinding: unable to set property" << propertyName << "on object" << object;
+ }
+ }
+
+ } else {
+ // not a valid property
+ if (QDeclarativePropertyChanges *propertyChanges = qobject_cast<QDeclarativePropertyChanges *>(object)) {
+ if (isLiteralValue) {
+ propertyChanges->changeValue(propertyName, expression);
+ } else {
+ propertyChanges->changeExpression(propertyName, expression.toString());
+ }
+ } else {
+ qWarning() << "QDeclarativeEngineDebugServer::setBinding: unable to set property" << propertyName << "on object" << object;
+ }
+ }
+ }
+}
+
+void QDeclarativeEngineDebugServer::resetBinding(int objectId, const QString &propertyName)
+{
+ QObject *object = objectForId(objectId);
+ QDeclarativeContext *context = qmlContext(object);
+
+ if (object && context) {
+ if (object->property(propertyName.toLatin1()).isValid()) {
+ QDeclarativeProperty property(object, propertyName);
+ QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(property);
+ if (oldBinding) {
+ QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::setBinding(property, 0);
+ if (oldBinding)
+ oldBinding->destroy();
+ }
+ if (property.isResettable()) {
+ // Note: this will reset the property in any case, without regard to states
+ // Right now almost no QDeclarativeItem has reset methods for its properties (with the
+ // notable exception of QDeclarativeAnchors), so this is not a big issue
+ // later on, setBinding does take states into account
+ property.reset();
+ } else {
+ // overwrite with default value
+ if (QDeclarativeType *objType = QDeclarativeMetaType::qmlType(object->metaObject())) {
+ if (QObject *emptyObject = objType->create()) {
+ if (emptyObject->property(propertyName.toLatin1()).isValid()) {
+ QVariant defaultValue = QDeclarativeProperty(emptyObject, propertyName).read();
+ if (defaultValue.isValid()) {
+ setBinding(objectId, propertyName, defaultValue, true);
+ }
+ }
+ delete emptyObject;
+ }
+ }
+ }
+ } else {
+ if (QDeclarativePropertyChanges *propertyChanges = qobject_cast<QDeclarativePropertyChanges *>(object)) {
+ propertyChanges->removeProperty(propertyName);
+ }
+ }
+ }
+}
+
+void QDeclarativeEngineDebugServer::setMethodBody(int objectId, const QString &method, const QString &body)
+{
+ QObject *object = objectForId(objectId);
+ QDeclarativeContext *context = qmlContext(object);
+ if (!object || !context || !context->engine())
+ return;
+ QDeclarativeContextData *contextData = QDeclarativeContextData::get(context);
+ if (!contextData)
+ return;
+
+ QDeclarativePropertyCache::Data dummy;
+ QDeclarativePropertyCache::Data *prop =
+ QDeclarativePropertyCache::property(context->engine(), object, method, dummy);
+
+ if (!prop || !(prop->flags & QDeclarativePropertyCache::Data::IsVMEFunction))
+ return;
+
+ QMetaMethod metaMethod = object->metaObject()->method(prop->coreIndex);
+ QList<QByteArray> paramNames = metaMethod.parameterNames();
+
+ QString paramStr;
+ for (int ii = 0; ii < paramNames.count(); ++ii) {
+ if (ii != 0) paramStr.append(QLatin1String(","));
+ paramStr.append(QString::fromUtf8(paramNames.at(ii)));
+ }
+
+ QString jsfunction = QLatin1String("(function ") + method + QLatin1String("(") + paramStr +
+ QLatin1String(") {");
+ jsfunction += body;
+ jsfunction += QLatin1String("\n})");
+
+ QDeclarativeVMEMetaObject *vmeMetaObject =
+ static_cast<QDeclarativeVMEMetaObject*>(QObjectPrivate::get(object)->metaObject);
+ Q_ASSERT(vmeMetaObject); // the fact we found the property above should guarentee this
+
+ int lineNumber = vmeMetaObject->vmeMethodLineNumber(prop->coreIndex);
+ vmeMetaObject->setVmeMethod(prop->coreIndex, QDeclarativeExpressionPrivate::evalInObjectScope(contextData, object, jsfunction, contextData->url.toString(), lineNumber, 0));
+}
+
+void QDeclarativeEngineDebugServer::propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value)
+{
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+
+ rs << QByteArray("UPDATE_WATCH") << id << objectId << QByteArray(property.name()) << valueContents(value);
+
+ sendMessage(reply);
+}
+
+void QDeclarativeEngineDebugServer::addEngine(QDeclarativeEngine *engine)
+{
+ Q_ASSERT(engine);
+ Q_ASSERT(!m_engines.contains(engine));
+
+ m_engines.append(engine);
+}
+
+void QDeclarativeEngineDebugServer::remEngine(QDeclarativeEngine *engine)
+{
+ Q_ASSERT(engine);
+ Q_ASSERT(m_engines.contains(engine));
+
+ m_engines.removeAll(engine);
+}
+
+void QDeclarativeEngineDebugServer::objectCreated(QDeclarativeEngine *engine, QObject *object)
+{
+ Q_ASSERT(engine);
+ Q_ASSERT(m_engines.contains(engine));
+
+ int engineId = QDeclarativeDebugService::idForObject(engine);
+ int objectId = QDeclarativeDebugService::idForObject(object);
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+
+ rs << QByteArray("OBJECT_CREATED") << engineId << objectId;
+ sendMessage(reply);
+}
+
+QT_END_NAMESPACE