diff options
author | Aaron Kennedy <aaron.kennedy@nokia.com> | 2009-07-13 05:21:42 (GMT) |
---|---|---|
committer | Aaron Kennedy <aaron.kennedy@nokia.com> | 2009-07-13 05:21:42 (GMT) |
commit | 29dd542d079d1b2bac37357d8ea18e5622cc12dc (patch) | |
tree | d4525cd54f5faf900374904d37d6e5fc1cbacd08 /src/declarative/qml | |
parent | d5e372425698c6a87e86743114e4b8d28d5d86eb (diff) | |
download | Qt-29dd542d079d1b2bac37357d8ea18e5622cc12dc.zip Qt-29dd542d079d1b2bac37357d8ea18e5622cc12dc.tar.gz Qt-29dd542d079d1b2bac37357d8ea18e5622cc12dc.tar.bz2 |
Start moving debugger out of process
Diffstat (limited to 'src/declarative/qml')
-rw-r--r-- | src/declarative/qml/qml.pri | 2 | ||||
-rw-r--r-- | src/declarative/qml/qmlcomponent.cpp | 7 | ||||
-rw-r--r-- | src/declarative/qml/qmlcontext.cpp | 33 | ||||
-rw-r--r-- | src/declarative/qml/qmlcontext.h | 5 | ||||
-rw-r--r-- | src/declarative/qml/qmlcontext_p.h | 4 | ||||
-rw-r--r-- | src/declarative/qml/qmlengine.cpp | 20 | ||||
-rw-r--r-- | src/declarative/qml/qmlengine_p.h | 1 | ||||
-rw-r--r-- | src/declarative/qml/qmlenginedebug.cpp | 268 | ||||
-rw-r--r-- | src/declarative/qml/qmlenginedebug_p.h | 108 | ||||
-rw-r--r-- | src/declarative/qml/qmlvme.cpp | 2 |
10 files changed, 440 insertions, 10 deletions
diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index fa09935..f549a5e 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -25,6 +25,7 @@ SOURCES += qml/qmlparser.cpp \ qml/qmlinfo.cpp \ qml/qmlerror.cpp \ qml/qmlscriptparser.cpp \ + qml/qmlenginedebug.cpp \ qml/qmlbasicscript.cpp HEADERS += qml/qmlparser_p.h \ @@ -66,6 +67,7 @@ HEADERS += qml/qmlparser_p.h \ qml/qmlerror.h \ qml/qmlscriptparser_p.h \ qml/qmlbasicscript_p.h \ + qml/qmlenginedebug_p.h \ qml/qpodvector_p.h # for qtscript debugger diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp index a9f5442..06e15ec 100644 --- a/src/declarative/qml/qmlcomponent.cpp +++ b/src/declarative/qml/qmlcomponent.cpp @@ -523,8 +523,9 @@ QObject *QmlComponent::beginCreate(QmlContext *context) if (!d->engine->d_func()->rootComponent) d->engine->d_func()->rootComponent = this; - QmlContext *ctxt = - new QmlContext(context, 0); + QmlContextPrivate *contextPriv = + static_cast<QmlContextPrivate *>(QObjectPrivate::get(context)); + QmlContext *ctxt = new QmlContext(context, 0, true); static_cast<QmlContextPrivate*>(ctxt->d_ptr)->url = d->cc->url; if(d->start != -1) { // ### FIXME @@ -558,6 +559,8 @@ QObject *QmlComponent::beginCreate(QmlContext *context) delete ctxt; } + if (rv && !contextPriv->isInternal && ep->isDebugging) + contextPriv->instances.append(rv); return rv; } diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp index b590596..0b2742d 100644 --- a/src/declarative/qml/qmlcontext.cpp +++ b/src/declarative/qml/qmlcontext.cpp @@ -54,8 +54,8 @@ QT_BEGIN_NAMESPACE QmlContextPrivate::QmlContextPrivate() -: parent(0), engine(0), notifyIndex(-1), highPriorityCount(0), - startLine(-1), endLine(-1) +: parent(0), engine(0), isInternal(false), notifyIndex(-1), + highPriorityCount(0), startLine(-1), endLine(-1) { } @@ -212,7 +212,7 @@ void QmlContextPrivate::addDefaultObject(QObject *object, Priority priority) */ /*! \internal */ -QmlContext::QmlContext(QmlEngine *e) +QmlContext::QmlContext(QmlEngine *e, bool) : QObject(*(new QmlContextPrivate)) { Q_D(QmlContext); @@ -221,6 +221,20 @@ QmlContext::QmlContext(QmlEngine *e) } /*! + Create a new QmlContext as a child of \a engine's root context, and the + QObject \a parent. +*/ +QmlContext::QmlContext(QmlEngine *engine, QObject *parent) +: QObject(*(new QmlContextPrivate), parent) +{ + Q_D(QmlContext); + QmlContext *parentContext = engine?engine->rootContext():0; + d->parent = parentContext; + d->engine = parentContext->engine(); + d->init(); +} + +/*! Create a new QmlContext with the given \a parentContext, and the QObject \a parent. */ @@ -234,6 +248,19 @@ QmlContext::QmlContext(QmlContext *parentContext, QObject *parent) } /*! + \internal +*/ +QmlContext::QmlContext(QmlContext *parentContext, QObject *parent, bool) +: QObject(*(new QmlContextPrivate), parent) +{ + Q_D(QmlContext); + d->parent = parentContext; + d->engine = parentContext->engine(); + d->isInternal = true; + d->init(); +} + +/*! Destroys the QmlContext. Any expressions, or sub-contexts dependent on this context will be diff --git a/src/declarative/qml/qmlcontext.h b/src/declarative/qml/qmlcontext.h index f5858cb..a0bb8e5 100644 --- a/src/declarative/qml/qmlcontext.h +++ b/src/declarative/qml/qmlcontext.h @@ -62,6 +62,7 @@ class Q_DECLARATIVE_EXPORT QmlContext : public QObject Q_DECLARE_PRIVATE(QmlContext) public: + QmlContext(QmlEngine *parent, QObject *objParent=0); QmlContext(QmlContext *parent, QObject *objParent=0); virtual ~QmlContext(); @@ -86,6 +87,7 @@ private Q_SLOTS: void objectDestroyed(QObject *); private: + friend class QmlVME; friend class QmlEngine; friend class QmlEnginePrivate; friend class QmlExpression; @@ -97,7 +99,8 @@ private: friend class QmlScriptPrivate; friend class QmlBoundSignalProxy; friend class QmlSimpleDeclarativeData; - QmlContext(QmlEngine *); + QmlContext(QmlContext *parent, QObject *objParent, bool); + QmlContext(QmlEngine *, bool); }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h index 569b320..f896873 100644 --- a/src/declarative/qml/qmlcontext_p.h +++ b/src/declarative/qml/qmlcontext_p.h @@ -76,6 +76,7 @@ public: QmlContext *parent; QmlEngine *engine; + bool isInternal; QHash<QString, int> propertyNames; QList<QVariant> propertyValues; @@ -110,6 +111,9 @@ public: QmlSimpleDeclarativeData contextData; QObjectList contextObjects; + + // Only used for debugging + QList<QPointer<QObject> > instances; }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index d88d11f..6eb0005 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -72,6 +72,7 @@ #include "private/qmlmetaproperty_p.h" #include <private/qmlbindablevalue_p.h> #include <private/qmlvme_p.h> +#include <private/qmlenginedebug_p.h> Q_DECLARE_METATYPE(QmlMetaProperty) Q_DECLARE_METATYPE(QList<QObject *>); @@ -132,8 +133,9 @@ QStack<QmlEngine *> *QmlEngineStack::engines() QmlEnginePrivate::QmlEnginePrivate(QmlEngine *e) -: rootContext(0), currentBindContext(0), currentExpression(0), q(e), - rootComponent(0), networkAccessManager(0), typeManager(e), uniqueId(1) +: rootContext(0), currentBindContext(0), currentExpression(0), q(e), + isDebugging(false), rootComponent(0), networkAccessManager(0), typeManager(e), + uniqueId(1) { QScriptValue qtObject = scriptEngine.newQMetaObject(StaticQtMetaObject::get()); scriptEngine.globalObject().setProperty(QLatin1String("Qt"), qtObject); @@ -179,12 +181,14 @@ void QmlEnginePrivate::clear(SimpleList<QmlParserStatus> &pss) pss.clear(); } +Q_GLOBAL_STATIC(QmlEngineDebugServer, qmlEngineDebugServer); + void QmlEnginePrivate::init() { scriptEngine.installTranslatorFunctions(); contextClass = new QmlContextScriptClass(q); objectClass = new QmlObjectScriptClass(q); - rootContext = new QmlContext(q); + rootContext = new QmlContext(q,true); #ifdef QT_SCRIPTTOOLS_LIB if (qmlDebugger()){ debugger = new QScriptEngineDebugger(q); @@ -198,6 +202,13 @@ void QmlEnginePrivate::init() scriptEngine.newFunction(QmlEngine::createQmlObject, 1)); scriptEngine.globalObject().setProperty(QLatin1String("createComponent"), scriptEngine.newFunction(QmlEngine::createComponent, 1)); + + if (QCoreApplication::instance()->thread() == q->thread() && + QmlEngineDebugServer::isDebuggingEnabled()) { + qmlEngineDebugServer(); + isDebugging = true; + QmlEngineDebugServer::addEngine(q); + } } QmlContext *QmlEnginePrivate::setCurrentBindContext(QmlContext *c) @@ -423,6 +434,9 @@ QmlEngine::QmlEngine(QObject *parent) */ QmlEngine::~QmlEngine() { + Q_D(QmlEngine); + if (d->isDebugging) + QmlEngineDebugServer::remEngine(this); } /*! diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h index 9171fbb..1ec1b24 100644 --- a/src/declarative/qml/qmlengine_p.h +++ b/src/declarative/qml/qmlengine_p.h @@ -117,6 +117,7 @@ public: QmlContext *currentBindContext; QmlExpression *currentExpression; QmlEngine *q; + bool isDebugging; #ifdef QT_SCRIPTTOOLS_LIB QScriptEngineDebugger *debugger; #endif diff --git a/src/declarative/qml/qmlenginedebug.cpp b/src/declarative/qml/qmlenginedebug.cpp new file mode 100644 index 0000000..b5e44e7 --- /dev/null +++ b/src/declarative/qml/qmlenginedebug.cpp @@ -0,0 +1,268 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmlenginedebug_p.h" +#include <QtCore/qdebug.h> +#include <QtCore/qmetaobject.h> +#include <QtDeclarative/qmlengine.h> +#include <QtDeclarative/qmlmetatype.h> +#include "qmlcontext_p.h" + +QT_BEGIN_NAMESPACE + +QList<QmlEngine *> QmlEngineDebugServer::m_engines; +QmlEngineDebugServer::QmlEngineDebugServer(QObject *parent) +: QmlDebugServerPlugin(QLatin1String("QmlEngine"), parent) +{ +} + +QDataStream &operator<<(QDataStream &ds, + const QmlEngineDebugServer::QmlObjectData &data) +{ + ds << data.url << data.lineNumber << data.columnNumber << data.objectName + << data.objectType << data.objectId; + return ds; +} + +QDataStream &operator>>(QDataStream &ds, + QmlEngineDebugServer::QmlObjectData &data) +{ + ds >> data.url >> data.lineNumber >> data.columnNumber >> data.objectName + >> data.objectType >> data.objectId; + return ds; +} + +QDataStream &operator<<(QDataStream &ds, + const QmlEngineDebugServer::QmlObjectProperty &data) +{ + ds << (int)data.type << data.name << data.value; + return ds; +} + +QDataStream &operator>>(QDataStream &ds, + QmlEngineDebugServer::QmlObjectProperty &data) +{ + int type; + ds >> type >> data.name >> data.value; + data.type = (QmlEngineDebugServer::QmlObjectProperty::Type)type; + return ds; +} + +QmlEngineDebugServer::QmlObjectProperty +QmlEngineDebugServer::propertyData(QObject *obj, int propIdx) +{ + QmlObjectProperty rv; + + QMetaProperty prop = obj->metaObject()->property(propIdx); + + rv.type = QmlObjectProperty::Unknown; + rv.name = prop.name(); + + if (prop.type() < QVariant::UserType) { + rv.type = QmlObjectProperty::Basic; + rv.value = prop.read(obj); + } else if (QmlMetaType::isObject(prop.userType())) { + rv.type = QmlObjectProperty::Object; + } else if (QmlMetaType::isList(prop.userType()) || + QmlMetaType::isQmlList(prop.userType())) { + rv.type = QmlObjectProperty::List; + } + return rv; +} + +void QmlEngineDebugServer::buildObjectDump(QDataStream &message, + QObject *object, bool recur) +{ + message << objectData(object); + message << object->metaObject()->propertyCount(); + + for (int ii = 0; ii < object->metaObject()->propertyCount(); ++ii) + message << propertyData(object, ii); + + QObjectList children = object->children(); + message << children.count() << recur; + + for (int ii = 0; ii < children.count(); ++ii) { + QObject *child = children.at(ii); + if (recur) + buildObjectDump(message, child, recur); + else + message << objectData(child); + } +} + +void QmlEngineDebugServer::buildObjectList(QDataStream &message, + QmlContext *ctxt) +{ + QmlContextPrivate *p = (QmlContextPrivate *)QObjectPrivate::get(ctxt); + + QString ctxtName = ctxt->objectName(); + int ctxtId = QmlDebugServerPlugin::idForObject(ctxt); + + message << ctxtName << ctxtId; + + int count = 0; + + for (QSet<QmlContext *>::ConstIterator iter = p->childContexts.begin(); + iter != p->childContexts.end(); ++iter) { + QmlContextPrivate *p = (QmlContextPrivate *)QObjectPrivate::get(*iter); + if (p->isInternal) + continue; + ++count; + } + + message << count; + + for (QSet<QmlContext *>::ConstIterator iter = p->childContexts.begin(); + iter != p->childContexts.end(); ++iter) { + QmlContextPrivate *p = (QmlContextPrivate *)QObjectPrivate::get(*iter); + if (p->isInternal) + continue; + buildObjectList(message, *iter); + } + + // Clean deleted objects + for (int ii = 0; ii < p->instances.count(); ++ii) { + if (!p->instances.at(ii)) { + p->instances.removeAt(ii); + --ii; + } + } + + message << p->instances.count(); + for (int ii = 0; ii < p->instances.count(); ++ii) { + message << objectData(p->instances.at(ii)); + } +} + +QmlEngineDebugServer::QmlObjectData +QmlEngineDebugServer::objectData(QObject *object) +{ + QmlObjectData rv; + rv.lineNumber = -1; + rv.columnNumber = -1; + + rv.objectName = object->objectName(); + rv.objectType = object->metaObject()->className(); + rv.objectId = QmlDebugServerPlugin::idForObject(object); + + return rv; +} + +void QmlEngineDebugServer::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) { + QmlEngine *engine = m_engines.at(ii); + + QString engineName = engine->objectName(); + int engineId = QmlDebugServerPlugin::idForObject(engine); + + rs << engineName << engineId; + } + + sendMessage(reply); + } else if (type == "LIST_OBJECTS") { + int queryId; + int engineId = -1; + ds >> queryId >> engineId; + + QmlEngine *engine = + qobject_cast<QmlEngine *>(QmlDebugServerPlugin::objectForId(engineId)); + + QByteArray reply; + QDataStream rs(&reply, QIODevice::WriteOnly); + rs << QByteArray("LIST_OBJECTS_R") << queryId; + + if (engine) + buildObjectList(rs, engine->rootContext()); + + sendMessage(reply); + } else if (type == "FETCH_OBJECT") { + int queryId; + int objectId; + bool recurse; + + ds >> queryId >> objectId >> recurse; + + QObject *object = QmlDebugServerPlugin::objectForId(objectId); + + QByteArray reply; + QDataStream rs(&reply, QIODevice::WriteOnly); + rs << QByteArray("FETCH_OBJECT_R") << queryId; + + if (object) + buildObjectDump(rs, object, recurse); + + sendMessage(reply); + } +} + +void QmlEngineDebugServer::addEngine(QmlEngine *engine) +{ + Q_ASSERT(engine); + Q_ASSERT(!m_engines.contains(engine)); + + m_engines.append(engine); +} + +void QmlEngineDebugServer::remEngine(QmlEngine *engine) +{ + Q_ASSERT(engine); + Q_ASSERT(m_engines.contains(engine)); + + m_engines.removeAll(engine); +} + +QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlenginedebug_p.h b/src/declarative/qml/qmlenginedebug_p.h new file mode 100644 index 0000000..634f55f --- /dev/null +++ b/src/declarative/qml/qmlenginedebug_p.h @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLENGINEDEBUG_P_H +#define QMLENGINEDEBUG_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 <QtDeclarative/qmldebugserver.h> +#include <QtCore/qurl.h> +#include <QtCore/qvariant.h> + +QT_BEGIN_NAMESPACE + +class QmlEngine; +class QmlContext; +class QDataStream; +class QmlEngineDebugServer : public QmlDebugServerPlugin +{ +public: + QmlEngineDebugServer(QObject * = 0); + + struct QmlObjectData { + QUrl url; + int lineNumber; + int columnNumber; + QString objectName; + QString objectType; + int objectId; + }; + + struct QmlObjectProperty { + enum Type { Unknown, Basic, Object, List }; + Type type; + QString name; + QVariant value; + }; + + static void addEngine(QmlEngine *); + static void remEngine(QmlEngine *); + +protected: + virtual void messageReceived(const QByteArray &); + +private: + void buildObjectList(QDataStream &, QmlContext *); + void buildObjectDump(QDataStream &, QObject *, bool); + QmlObjectData objectData(QObject *); + QmlObjectProperty propertyData(QObject *, int); + + static QList<QmlEngine *> m_engines; +}; +Q_DECLARATIVE_EXPORT QDataStream &operator<<(QDataStream &, const QmlEngineDebugServer::QmlObjectData &); +Q_DECLARATIVE_EXPORT QDataStream &operator>>(QDataStream &, QmlEngineDebugServer::QmlObjectData &); +Q_DECLARATIVE_EXPORT QDataStream &operator<<(QDataStream &, const QmlEngineDebugServer::QmlObjectProperty &); +Q_DECLARATIVE_EXPORT QDataStream &operator>>(QDataStream &, QmlEngineDebugServer::QmlObjectProperty &); + +QT_END_NAMESPACE + +#endif // QMLENGINEDEBUG_P_H + diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index a11caeb..2acf1e2 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -521,7 +521,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, QmlCompiledComp if (signal.parameterTypes().isEmpty()) { (void *)new QmlBoundSignal(QmlContext::activeContext(), primitives.at(instr.storeSignal.value), target, instr.storeSignal.signalIndex, target); } else { - (void *)new QmlBoundSignalProxy(new QmlContext(QmlContext::activeContext(), target), primitives.at(instr.storeSignal.value), target, instr.storeSignal.signalIndex, target); + (void *)new QmlBoundSignalProxy(new QmlContext(QmlContext::activeContext(), target, true), primitives.at(instr.storeSignal.value), target, instr.storeSignal.signalIndex, target); } } break; |