From 8804ec49bda8672c5700ab843f2958c3d2bd8e41 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Tue, 30 Aug 2011 17:21:30 +0200 Subject: [PATCH] Rename QDeclarativeEngineDebugServer to ~Service And fix the file names/location, too Change-Id: If2d5ec0896332896ad11af748ec8f75c39e1555c Reviewed-on: http://codereview.qt.nokia.com/3890 Reviewed-by: Qt Sanity Bot Reviewed-by: Kai Koehne --- src/declarative/debugger/debugger.pri | 6 +- src/declarative/debugger/qdeclarativedebug.cpp | 16 +- .../debugger/qdeclarativeenginedebugservice.cpp | 747 ++++++++++++++++++++ .../debugger/qdeclarativeenginedebugservice_p.h | 134 ++++ src/declarative/qml/qdeclarativecomponent.cpp | 4 +- src/declarative/qml/qdeclarativeengine.cpp | 8 +- src/declarative/qml/qdeclarativeenginedebug.cpp | 747 -------------------- src/declarative/qml/qdeclarativeenginedebug_p.h | 134 ---- src/declarative/qml/qml.pri | 2 - .../qdeclarativedebug/tst_qdeclarativedebug.cpp | 1 - .../tst_qdeclarativedebugclient.cpp | 1 - .../tst_qdeclarativedebugservice.cpp | 1 - 12 files changed, 899 insertions(+), 902 deletions(-) create mode 100644 src/declarative/debugger/qdeclarativeenginedebugservice.cpp create mode 100644 src/declarative/debugger/qdeclarativeenginedebugservice_p.h delete mode 100644 src/declarative/qml/qdeclarativeenginedebug.cpp delete mode 100644 src/declarative/qml/qdeclarativeenginedebug_p.h diff --git a/src/declarative/debugger/debugger.pri b/src/declarative/debugger/debugger.pri index e7462d4..8124774 100644 --- a/src/declarative/debugger/debugger.pri +++ b/src/declarative/debugger/debugger.pri @@ -10,7 +10,8 @@ SOURCES += \ $$PWD/qdeclarativedebughelper.cpp \ $$PWD/qdeclarativedebugserver.cpp \ $$PWD/qdeclarativeinspectorservice.cpp \ - $$PWD/qv8debugservice.cpp + $$PWD/qv8debugservice.cpp \ + $$PWD/qdeclarativeenginedebugservice.cpp HEADERS += \ $$PWD/qdeclarativedebuggerstatus_p.h \ @@ -25,4 +26,5 @@ HEADERS += \ $$PWD/qdeclarativedebugserverconnection_p.h \ $$PWD/qdeclarativeinspectorservice_p.h \ $$PWD/qdeclarativeinspectorinterface_p.h \ - $$PWD/qv8debugservice_p.h + $$PWD/qv8debugservice_p.h \ + $$PWD/qdeclarativeenginedebugservice_p.h diff --git a/src/declarative/debugger/qdeclarativedebug.cpp b/src/declarative/debugger/qdeclarativedebug.cpp index 620ee1d..17bd553 100644 --- a/src/declarative/debugger/qdeclarativedebug.cpp +++ b/src/declarative/debugger/qdeclarativedebug.cpp @@ -43,7 +43,7 @@ #include "private/qdeclarativedebugclient_p.h" -#include +#include #include @@ -207,7 +207,7 @@ void QDeclarativeEngineDebugPrivate::remove(QDeclarativeEngineDebug *c, QDeclara void QDeclarativeEngineDebugPrivate::decode(QDataStream &ds, QDeclarativeDebugObjectReference &o, bool simple) { - QDeclarativeEngineDebugServer::QDeclarativeObjectData data; + QDeclarativeEngineDebugService::QDeclarativeObjectData data; ds >> data; o.m_debugId = data.objectId; o.m_class = data.objectType; @@ -234,7 +234,7 @@ void QDeclarativeEngineDebugPrivate::decode(QDataStream &ds, QDeclarativeDebugOb ds >> propCount; for (int ii = 0; ii < propCount; ++ii) { - QDeclarativeEngineDebugServer::QDeclarativeObjectProperty data; + QDeclarativeEngineDebugService::QDeclarativeObjectProperty data; ds >> data; QDeclarativeDebugPropertyReference prop; prop.m_objectDebugId = o.m_debugId; @@ -243,21 +243,21 @@ void QDeclarativeEngineDebugPrivate::decode(QDataStream &ds, QDeclarativeDebugOb prop.m_hasNotifySignal = data.hasNotifySignal; prop.m_valueTypeName = data.valueTypeName; switch (data.type) { - case QDeclarativeEngineDebugServer::QDeclarativeObjectProperty::Basic: - case QDeclarativeEngineDebugServer::QDeclarativeObjectProperty::List: - case QDeclarativeEngineDebugServer::QDeclarativeObjectProperty::SignalProperty: + case QDeclarativeEngineDebugService::QDeclarativeObjectProperty::Basic: + case QDeclarativeEngineDebugService::QDeclarativeObjectProperty::List: + case QDeclarativeEngineDebugService::QDeclarativeObjectProperty::SignalProperty: { prop.m_value = data.value; break; } - case QDeclarativeEngineDebugServer::QDeclarativeObjectProperty::Object: + case QDeclarativeEngineDebugService::QDeclarativeObjectProperty::Object: { QDeclarativeDebugObjectReference obj; obj.m_debugId = prop.m_value.toInt(); prop.m_value = QVariant::fromValue(obj); break; } - case QDeclarativeEngineDebugServer::QDeclarativeObjectProperty::Unknown: + case QDeclarativeEngineDebugService::QDeclarativeObjectProperty::Unknown: break; } o.m_properties << prop; diff --git a/src/declarative/debugger/qdeclarativeenginedebugservice.cpp b/src/declarative/debugger/qdeclarativeenginedebugservice.cpp new file mode 100644 index 0000000..2e5683c --- /dev/null +++ b/src/declarative/debugger/qdeclarativeenginedebugservice.cpp @@ -0,0 +1,747 @@ +/**************************************************************************** +** +** 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$ +** 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 "private/qdeclarativeenginedebugservice_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 +#include + +QT_BEGIN_NAMESPACE + +Q_GLOBAL_STATIC(QDeclarativeEngineDebugService, qmlEngineDebugService); + +QDeclarativeEngineDebugService *QDeclarativeEngineDebugService::instance() +{ + return qmlEngineDebugService(); +} + +QDeclarativeEngineDebugService::QDeclarativeEngineDebugService(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 QDeclarativeEngineDebugService::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, + QDeclarativeEngineDebugService::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 QDeclarativeEngineDebugService::QDeclarativeObjectProperty &data) +{ + ds << (int)data.type << data.name << data.value << data.valueTypeName + << data.binding << data.hasNotifySignal; + return ds; +} + +QDataStream &operator>>(QDataStream &ds, + QDeclarativeEngineDebugService::QDeclarativeObjectProperty &data) +{ + int type; + ds >> type >> data.name >> data.value >> data.valueTypeName + >> data.binding >> data.hasNotifySignal; + data.type = (QDeclarativeEngineDebugService::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; +} + +QDeclarativeEngineDebugService::QDeclarativeObjectProperty +QDeclarativeEngineDebugService::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(); + + 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; + } + + QVariant value; + if (rv.type != QDeclarativeObjectProperty::Unknown && prop.userType() != 0) { + value = prop.read(obj); + } + rv.value = valueContents(value); + + return rv; +} + +QVariant QDeclarativeEngineDebugService::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(""); + return name; + } + } + + return QLatin1String(""); +} + +void QDeclarativeEngineDebugService::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(children[ii]) || QDeclarativeBoundSignal::cast(children[ii])) + --childrenCount; + } + + message << childrenCount << recur; + + QList fakeProperties; + + for (int ii = 0; ii < children.count(); ++ii) { + QObject *child = children.at(ii); + if (qobject_cast(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 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 QDeclarativeEngineDebugService::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 QDeclarativeEngineDebugService::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 QDeclarativeEngineDebugService::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 QDeclarativeEngineDebugService::buildStatesList(QObject *obj) +{ + if (QDeclarativeState *state = qobject_cast(obj)) { + m_allStates.append(state); + } + + QObjectList children = obj->children(); + for (int ii = 0; ii < children.count(); ++ii) { + buildStatesList(children.at(ii)); + } +} + +QDeclarativeEngineDebugService::QDeclarativeObjectData +QDeclarativeEngineDebugService::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 QDeclarativeEngineDebugService::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(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(""); + else + result = valueContents(value); + } else { + result = QLatin1String(""); + } + + 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; + QString filename; + int line; + ds >> objectId >> propertyName >> expr >> isLiteralValue; + if (!ds.atEnd()) { // backward compatibility from 2.1, 2.2 + ds >> filename >> line; + } + setBinding(objectId, propertyName, expr, isLiteralValue, filename, line); + } 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 QDeclarativeEngineDebugService::setBinding(int objectId, + const QString &propertyName, + const QVariant &expression, + bool isLiteralValue, + QString filename, + int line) +{ + QObject *object = objectForId(objectId); + QDeclarativeContext *context = qmlContext(object); + + if (object && context) { + QDeclarativeProperty property(object, propertyName, context); + if (property.isValid()) { + + bool inBaseState = true; + + foreach(QWeakPointer 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); + newBinding->setSourceLocation(filename, line); + } + + 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()); + QDeclarativePropertyPrivate::setSignalExpression(property, declarativeExpression); + declarativeExpression->setSourceLocation(filename, line); + } else if (property.isProperty()) { + QDeclarativeBinding *binding = new QDeclarativeBinding(expression.toString(), object, context); + binding->setTarget(property); + binding->setSourceLocation(filename, line); + binding->setNotifyOnValueChanged(true); + QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::setBinding(property, binding); + if (oldBinding) + oldBinding->destroy(); + binding->update(); + } else { + qWarning() << "QDeclarativeEngineDebugService::setBinding: unable to set property" << propertyName << "on object" << object; + } + } + + } else { + // not a valid property + if (QDeclarativePropertyChanges *propertyChanges = qobject_cast(object)) { + if (isLiteralValue) { + propertyChanges->changeValue(propertyName, expression); + } else { + propertyChanges->changeExpression(propertyName, expression.toString()); + } + } else { + qWarning() << "QDeclarativeEngineDebugService::setBinding: unable to set property" << propertyName << "on object" << object; + } + } + } +} + +void QDeclarativeEngineDebugService::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 (hasValidSignal(object, propertyName)) { + QDeclarativeProperty property(object, propertyName, context); + QDeclarativePropertyPrivate::setSignalExpression(property, 0); + } else { + if (QDeclarativePropertyChanges *propertyChanges = qobject_cast(object)) { + propertyChanges->removeProperty(propertyName); + } + } + } +} + +void QDeclarativeEngineDebugService::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->isVMEFunction()) + return; + + QMetaMethod metaMethod = object->metaObject()->method(prop->coreIndex); + QList 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(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::evalFunction(contextData, object, jsfunction, contextData->url.toString(), lineNumber)); +} + +void QDeclarativeEngineDebugService::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 QDeclarativeEngineDebugService::addEngine(QDeclarativeEngine *engine) +{ + Q_ASSERT(engine); + Q_ASSERT(!m_engines.contains(engine)); + + m_engines.append(engine); +} + +void QDeclarativeEngineDebugService::remEngine(QDeclarativeEngine *engine) +{ + Q_ASSERT(engine); + Q_ASSERT(m_engines.contains(engine)); + + m_engines.removeAll(engine); +} + +void QDeclarativeEngineDebugService::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 diff --git a/src/declarative/debugger/qdeclarativeenginedebugservice_p.h b/src/declarative/debugger/qdeclarativeenginedebugservice_p.h new file mode 100644 index 0000000..3674b83 --- /dev/null +++ b/src/declarative/debugger/qdeclarativeenginedebugservice_p.h @@ -0,0 +1,134 @@ +/**************************************************************************** +** +** 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$ +** 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$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEENGINEDEBUGSERVICE_P_H +#define QDECLARATIVEENGINEDEBUGSERVICE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QDeclarativeEngine; +class QDeclarativeContext; +class QDeclarativeWatcher; +class QDataStream; +class QDeclarativeState; + +class QDeclarativeEngineDebugService : public QDeclarativeDebugService +{ + Q_OBJECT +public: + QDeclarativeEngineDebugService(QObject * = 0); + + struct QDeclarativeObjectData { + QUrl url; + int lineNumber; + int columnNumber; + QString idString; + QString objectName; + QString objectType; + int objectId; + int contextId; + }; + + struct QDeclarativeObjectProperty { + enum Type { Unknown, Basic, Object, List, SignalProperty }; + Type type; + QString name; + QVariant value; + QString valueTypeName; + QString binding; + bool hasNotifySignal; + }; + + void addEngine(QDeclarativeEngine *); + void remEngine(QDeclarativeEngine *); + void objectCreated(QDeclarativeEngine *, QObject *); + + static QDeclarativeEngineDebugService *instance(); + +protected: + virtual void messageReceived(const QByteArray &); + +private Q_SLOTS: + void propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value); + +private: + void prepareDeferredObjects(QObject *); + void buildObjectList(QDataStream &, QDeclarativeContext *); + void buildObjectDump(QDataStream &, QObject *, bool, bool); + void buildStatesList(QDeclarativeContext *, bool); + void buildStatesList(QObject *obj); + QDeclarativeObjectData objectData(QObject *); + QDeclarativeObjectProperty propertyData(QObject *, int); + QVariant valueContents(const QVariant &defaultValue) const; + void setBinding(int objectId, const QString &propertyName, const QVariant &expression, bool isLiteralValue, QString filename = QString(), int line = -1); + void resetBinding(int objectId, const QString &propertyName); + void setMethodBody(int objectId, const QString &method, const QString &body); + + QList m_engines; + QDeclarativeWatcher *m_watch; + QList > m_allStates; +}; +Q_DECLARATIVE_PRIVATE_EXPORT QDataStream &operator<<(QDataStream &, const QDeclarativeEngineDebugService::QDeclarativeObjectData &); +Q_DECLARATIVE_PRIVATE_EXPORT QDataStream &operator>>(QDataStream &, QDeclarativeEngineDebugService::QDeclarativeObjectData &); +Q_DECLARATIVE_PRIVATE_EXPORT QDataStream &operator<<(QDataStream &, const QDeclarativeEngineDebugService::QDeclarativeObjectProperty &); +Q_DECLARATIVE_PRIVATE_EXPORT QDataStream &operator>>(QDataStream &, QDeclarativeEngineDebugService::QDeclarativeObjectProperty &); + +QT_END_NAMESPACE + +#endif // QDECLARATIVEENGINEDEBUGSERVICE_P_H + diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp index 49aa6d9..c7bc2cd 100644 --- a/src/declarative/qml/qdeclarativecomponent.cpp +++ b/src/declarative/qml/qdeclarativecomponent.cpp @@ -53,7 +53,7 @@ #include "private/qdeclarativeglobal_p.h" #include "private/qdeclarativescript_p.h" #include "private/qdeclarativedebugtrace_p.h" -#include "private/qdeclarativeenginedebug_p.h" +#include "private/qdeclarativeenginedebugservice_p.h" #include "private/qv8engine_p.h" #include "private/qv8include_p.h" @@ -952,7 +952,7 @@ QObject * QDeclarativeComponentPrivate::begin(QDeclarativeContextData *parentCon if (enginePriv->isDebugging && rv) { if (!parentContext->isInternal) parentContext->asQDeclarativeContextPrivate()->instances.append(rv); - QDeclarativeEngineDebugServer::instance()->objectCreated(parentContext->engine, rv); + QDeclarativeEngineDebugService::instance()->objectCreated(parentContext->engine, rv); if (isRoot) { QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Creating, buildTypeNameForDebug(rv->metaObject())); QDeclarativeData *data = QDeclarativeData::get(rv); diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index 7e8f93e..fa7854b 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -50,7 +50,7 @@ #include "qdeclarativecomponent.h" #include "private/qdeclarativebinding_p_p.h" #include "private/qdeclarativevme_p.h" -#include "private/qdeclarativeenginedebug_p.h" +#include "private/qdeclarativeenginedebugservice_p.h" #include "private/qdeclarativestringconverters_p.h" #include "private/qdeclarativexmlhttprequest_p.h" #include "private/qdeclarativesqldatabase_p.h" @@ -448,9 +448,9 @@ void QDeclarativeEnginePrivate::init() rootContext = new QDeclarativeContext(q,true); if (QCoreApplication::instance()->thread() == q->thread() && - QDeclarativeEngineDebugServer::isDebuggingEnabled()) { + QDeclarativeEngineDebugService::isDebuggingEnabled()) { isDebugging = true; - QDeclarativeEngineDebugServer::instance()->addEngine(q); + QDeclarativeEngineDebugService::instance()->addEngine(q); QV8DebugService::instance()->addEngine(q); } } @@ -515,7 +515,7 @@ QDeclarativeEngine::~QDeclarativeEngine() { Q_D(QDeclarativeEngine); if (d->isDebugging) - QDeclarativeEngineDebugServer::instance()->remEngine(this); + QDeclarativeEngineDebugService::instance()->remEngine(this); // if we are the parent of any of the qobject module api instances, // we need to remove them from our internal list, in order to prevent diff --git a/src/declarative/qml/qdeclarativeenginedebug.cpp b/src/declarative/qml/qdeclarativeenginedebug.cpp deleted file mode 100644 index 6c605cb..0000000 --- a/src/declarative/qml/qdeclarativeenginedebug.cpp +++ /dev/null @@ -1,747 +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$ -** 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 "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 -#include - -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(); - - 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; - } - - QVariant value; - if (rv.type != QDeclarativeObjectProperty::Unknown && prop.userType() != 0) { - value = prop.read(obj); - } - rv.value = valueContents(value); - - 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(""); - return name; - } - } - - return QLatin1String(""); -} - -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(children[ii]) || QDeclarativeBoundSignal::cast(children[ii])) - --childrenCount; - } - - message << childrenCount << recur; - - QList fakeProperties; - - for (int ii = 0; ii < children.count(); ++ii) { - QObject *child = children.at(ii); - if (qobject_cast(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 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(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(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(""); - else - result = valueContents(value); - } else { - result = QLatin1String(""); - } - - 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; - QString filename; - int line; - ds >> objectId >> propertyName >> expr >> isLiteralValue; - if (!ds.atEnd()) { // backward compatibility from 2.1, 2.2 - ds >> filename >> line; - } - setBinding(objectId, propertyName, expr, isLiteralValue, filename, line); - } 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, - QString filename, - int line) -{ - QObject *object = objectForId(objectId); - QDeclarativeContext *context = qmlContext(object); - - if (object && context) { - QDeclarativeProperty property(object, propertyName, context); - if (property.isValid()) { - - bool inBaseState = true; - - foreach(QWeakPointer 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); - newBinding->setSourceLocation(filename, line); - } - - 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()); - QDeclarativePropertyPrivate::setSignalExpression(property, declarativeExpression); - declarativeExpression->setSourceLocation(filename, line); - } else if (property.isProperty()) { - QDeclarativeBinding *binding = new QDeclarativeBinding(expression.toString(), object, context); - binding->setTarget(property); - binding->setSourceLocation(filename, line); - 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(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 (hasValidSignal(object, propertyName)) { - QDeclarativeProperty property(object, propertyName, context); - QDeclarativePropertyPrivate::setSignalExpression(property, 0); - } else { - if (QDeclarativePropertyChanges *propertyChanges = qobject_cast(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->isVMEFunction()) - return; - - QMetaMethod metaMethod = object->metaObject()->method(prop->coreIndex); - QList 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(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::evalFunction(contextData, object, jsfunction, contextData->url.toString(), lineNumber)); -} - -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 diff --git a/src/declarative/qml/qdeclarativeenginedebug_p.h b/src/declarative/qml/qdeclarativeenginedebug_p.h deleted file mode 100644 index 804a043..0000000 --- a/src/declarative/qml/qdeclarativeenginedebug_p.h +++ /dev/null @@ -1,134 +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$ -** 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$ -** -****************************************************************************/ - -#ifndef QDECLARATIVEENGINEDEBUG_P_H -#define QDECLARATIVEENGINEDEBUG_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include - -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class QDeclarativeEngine; -class QDeclarativeContext; -class QDeclarativeWatcher; -class QDataStream; -class QDeclarativeState; - -class QDeclarativeEngineDebugServer : public QDeclarativeDebugService -{ - Q_OBJECT -public: - QDeclarativeEngineDebugServer(QObject * = 0); - - struct QDeclarativeObjectData { - QUrl url; - int lineNumber; - int columnNumber; - QString idString; - QString objectName; - QString objectType; - int objectId; - int contextId; - }; - - struct QDeclarativeObjectProperty { - enum Type { Unknown, Basic, Object, List, SignalProperty }; - Type type; - QString name; - QVariant value; - QString valueTypeName; - QString binding; - bool hasNotifySignal; - }; - - void addEngine(QDeclarativeEngine *); - void remEngine(QDeclarativeEngine *); - void objectCreated(QDeclarativeEngine *, QObject *); - - static QDeclarativeEngineDebugServer *instance(); - -protected: - virtual void messageReceived(const QByteArray &); - -private Q_SLOTS: - void propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value); - -private: - void prepareDeferredObjects(QObject *); - void buildObjectList(QDataStream &, QDeclarativeContext *); - void buildObjectDump(QDataStream &, QObject *, bool, bool); - void buildStatesList(QDeclarativeContext *, bool); - void buildStatesList(QObject *obj); - QDeclarativeObjectData objectData(QObject *); - QDeclarativeObjectProperty propertyData(QObject *, int); - QVariant valueContents(const QVariant &defaultValue) const; - void setBinding(int objectId, const QString &propertyName, const QVariant &expression, bool isLiteralValue, QString filename = QString(), int line = -1); - void resetBinding(int objectId, const QString &propertyName); - void setMethodBody(int objectId, const QString &method, const QString &body); - - QList m_engines; - QDeclarativeWatcher *m_watch; - QList > m_allStates; -}; -Q_DECLARATIVE_PRIVATE_EXPORT QDataStream &operator<<(QDataStream &, const QDeclarativeEngineDebugServer::QDeclarativeObjectData &); -Q_DECLARATIVE_PRIVATE_EXPORT QDataStream &operator>>(QDataStream &, QDeclarativeEngineDebugServer::QDeclarativeObjectData &); -Q_DECLARATIVE_PRIVATE_EXPORT QDataStream &operator<<(QDataStream &, const QDeclarativeEngineDebugServer::QDeclarativeObjectProperty &); -Q_DECLARATIVE_PRIVATE_EXPORT QDataStream &operator>>(QDataStream &, QDeclarativeEngineDebugServer::QDeclarativeObjectProperty &); - -QT_END_NAMESPACE - -#endif // QDECLARATIVEENGINEDEBUG_P_H - diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index 7ef28c0..61e3aa3 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -23,7 +23,6 @@ SOURCES += \ $$PWD/qdeclarativeinfo.cpp \ $$PWD/qdeclarativeerror.cpp \ $$PWD/qdeclarativescript.cpp \ - $$PWD/qdeclarativeenginedebug.cpp \ $$PWD/qdeclarativerewrite.cpp \ $$PWD/qdeclarativevaluetype.cpp \ $$PWD/qdeclarativefastproperties.cpp \ @@ -81,7 +80,6 @@ HEADERS += \ $$PWD/qdeclarativedata_p.h \ $$PWD/qdeclarativeerror.h \ $$PWD/qdeclarativescript_p.h \ - $$PWD/qdeclarativeenginedebug_p.h \ $$PWD/qdeclarativerewrite_p.h \ $$PWD/qdeclarativevaluetype_p.h \ $$PWD/qdeclarativefastproperties_p.h \ diff --git a/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp b/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp index a5a5009..632c404 100644 --- a/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp +++ b/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp @@ -54,7 +54,6 @@ #include #include -#include #include #include #include diff --git a/tests/auto/declarative/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp b/tests/auto/declarative/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp index 2ad50b1..ea7104f 100644 --- a/tests/auto/declarative/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp +++ b/tests/auto/declarative/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp @@ -48,7 +48,6 @@ #include #include -#include #include #include "../../../shared/util.h" diff --git a/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp b/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp index 3a285e0..286b258 100644 --- a/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp +++ b/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp @@ -48,7 +48,6 @@ #include #include -#include #include #include -- 1.7.2.5