diff options
author | Bea Lam <bea.lam@nokia.com> | 2009-09-23 01:37:50 (GMT) |
---|---|---|
committer | Bea Lam <bea.lam@nokia.com> | 2009-09-23 01:37:50 (GMT) |
commit | c60dfe1f2732670eb48d98c9772815d37a16ec3c (patch) | |
tree | 80a9b76b72d4bea96f0706264a5ed17311b2073e /src | |
parent | f918c8c60369154f45008a0e7e3af3bf5121abd5 (diff) | |
download | Qt-c60dfe1f2732670eb48d98c9772815d37a16ec3c.zip Qt-c60dfe1f2732670eb48d98c9772815d37a16ec3c.tar.gz Qt-c60dfe1f2732670eb48d98c9772815d37a16ec3c.tar.bz2 |
Add some of the functionality from the old debugger (e.g. dynamic updating of property values, watch table, colouring of tree widget items).
Diffstat (limited to 'src')
-rw-r--r-- | src/declarative/debugger/qmldebug.cpp | 205 | ||||
-rw-r--r-- | src/declarative/debugger/qmldebug.h | 59 | ||||
-rw-r--r-- | src/declarative/debugger/qmldebugservice.h | 2 | ||||
-rw-r--r-- | src/declarative/qml/qml.pri | 6 | ||||
-rw-r--r-- | src/declarative/qml/qmlenginedebug.cpp | 82 | ||||
-rw-r--r-- | src/declarative/qml/qmlenginedebug_p.h | 8 | ||||
-rw-r--r-- | src/declarative/qml/qmlwatcher.cpp | 183 | ||||
-rw-r--r-- | src/declarative/qml/qmlwatcher_p.h | 93 |
8 files changed, 611 insertions, 27 deletions
diff --git a/src/declarative/debugger/qmldebug.cpp b/src/declarative/debugger/qmldebug.cpp index 57e5858..7483fe2 100644 --- a/src/declarative/debugger/qmldebug.cpp +++ b/src/declarative/debugger/qmldebug.cpp @@ -36,6 +36,8 @@ public: QHash<int, QmlDebugEnginesQuery *> enginesQuery; QHash<int, QmlDebugRootContextQuery *> rootContextQuery; QHash<int, QmlDebugObjectQuery *> objectQuery; + + QHash<int, QmlDebugWatch *> watched; }; QmlEngineDebugClient::QmlEngineDebugClient(QmlDebugConnection *client, @@ -91,6 +93,7 @@ void QmlEngineDebugPrivate::decode(QDataStream &ds, QmlDebugObjectReference &o, o.m_source.m_url = data.url; o.m_source.m_lineNumber = data.lineNumber; o.m_source.m_columnNumber = data.columnNumber; + o.m_contextDebugId = data.contextId; if (simple) return; @@ -104,6 +107,7 @@ void QmlEngineDebugPrivate::decode(QDataStream &ds, QmlDebugObjectReference &o, QmlDebugPropertyReference prop; prop.m_name = data.name; prop.m_binding = data.binding; + prop.m_objectDebugId = o.m_debugId; if (data.type == QmlEngineDebugServer::QmlObjectProperty::Basic) prop.m_value = data.value; else if (data.type == QmlEngineDebugServer::QmlObjectProperty::Object) { @@ -144,6 +148,7 @@ void QmlEngineDebugPrivate::decode(QDataStream &ds, QmlDebugContextReference &c) QmlDebugObjectReference obj; decode(ds, obj, true); + obj.m_contextDebugId = c.m_debugId; c.m_objects << obj; } } @@ -155,6 +160,8 @@ void QmlEngineDebugPrivate::message(const QByteArray &data) QByteArray type; ds >> type; + //qDebug() << "QmlEngineDebugPrivate::message()" << type; + if (type == "LIST_ENGINES_R") { int queryId; ds >> queryId; @@ -204,6 +211,47 @@ void QmlEngineDebugPrivate::message(const QByteArray &data) query->m_client = 0; query->setState(QmlDebugQuery::Completed); + } else if (type == "WATCH_PROPERTY_R") { + int queryId; + bool ok; + ds >> queryId >> ok; + + QmlDebugWatch *watch = watched.value(queryId); + if (!watch) + return; + + watch->setState(ok ? QmlDebugWatch::Active : QmlDebugWatch::Inactive); + } else if (type == "WATCH_OBJECT_R") { + int queryId; + bool ok; + ds >> queryId >> ok; + + QmlDebugWatch *watch = watched.value(queryId); + if (!watch) + return; + + watch->setState(ok ? QmlDebugWatch::Active : QmlDebugWatch::Inactive); + } else if (type == "WATCH_EXPR_OBJECT_R") { + int queryId; + bool ok; + ds >> queryId >> ok; + + QmlDebugWatch *watch = watched.value(queryId); + if (!watch) + return; + + watch->setState(ok ? QmlDebugWatch::Active : QmlDebugWatch::Inactive); + } else if (type == "UPDATE_WATCH") { + int queryId; + int debugId; + QByteArray name; + QVariant value; + ds >> queryId >> debugId >> name >> value; + + QmlDebugWatch *watch = watched.value(queryId); + if (!watch) + return; + emit watch->valueChanged(name, value); } } @@ -212,10 +260,27 @@ QmlEngineDebug::QmlEngineDebug(QmlDebugConnection *client, QObject *parent) { } -QmlDebugWatch *QmlEngineDebug::addWatch(const QmlDebugPropertyReference &, QObject *) +QmlDebugPropertyWatch *QmlEngineDebug::addWatch(const QmlDebugPropertyReference &property, QObject *parent) { - qWarning("QmlEngineDebug::addWatch(): Not implemented"); - return 0; + Q_D(QmlEngineDebug); + + QmlDebugPropertyWatch *watch = new QmlDebugPropertyWatch(parent); + if (d->client->isConnected()) { + //query->m_client = this; + int queryId = d->getId(); + watch->m_queryId = queryId; + watch->m_objectDebugId = property.objectDebugId(); + d->watched.insert(queryId, watch); + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("WATCH_PROPERTY") << queryId << property.objectDebugId() << property.name().toLatin1(); + d->client->sendMessage(message); + } else { + watch->m_state = QmlDebugWatch::Dead; + } + + return watch; } QmlDebugWatch *QmlEngineDebug::addWatch(const QmlDebugContextReference &, const QString &, QObject *) @@ -224,16 +289,46 @@ QmlDebugWatch *QmlEngineDebug::addWatch(const QmlDebugContextReference &, const return 0; } -QmlDebugWatch *QmlEngineDebug::addWatch(const QmlDebugObjectReference &, const QString &, QObject *) +QmlDebugObjectExpressionWatch *QmlEngineDebug::addWatch(const QmlDebugObjectReference &object, const QString &expr, QObject *parent) { - qWarning("QmlEngineDebug::addWatch(): Not implemented"); - return 0; + Q_D(QmlEngineDebug); + QmlDebugObjectExpressionWatch *watch = new QmlDebugObjectExpressionWatch(parent); + if (d->client->isConnected()) { + int queryId = d->getId(); + watch->m_queryId = queryId; + watch->m_objectDebugId = object.debugId(); + d->watched.insert(queryId, watch); + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("WATCH_EXPR_OBJECT") << queryId << object.debugId() << expr; + d->client->sendMessage(message); + } else { + watch->m_state = QmlDebugWatch::Dead; + } + return watch; } -QmlDebugWatch *QmlEngineDebug::addWatch(const QmlDebugObjectReference &, QObject *) +QmlDebugWatch *QmlEngineDebug::addWatch(const QmlDebugObjectReference &object, QObject *parent) { - qWarning("QmlEngineDebug::addWatch(): Not implemented"); - return 0; + Q_D(QmlEngineDebug); + + QmlDebugWatch *watch = new QmlDebugWatch(parent); + if (d->client->isConnected()) { + int queryId = d->getId(); + watch->m_queryId = queryId; + watch->m_objectDebugId = object.debugId(); + d->watched.insert(queryId, watch); + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("WATCH_OBJECT") << queryId << object.debugId(); + d->client->sendMessage(message); + } else { + watch->m_state = QmlDebugWatch::Dead; + } + + return watch; } QmlDebugWatch *QmlEngineDebug::addWatch(const QmlDebugFileReference &, QObject *) @@ -242,6 +337,20 @@ QmlDebugWatch *QmlEngineDebug::addWatch(const QmlDebugFileReference &, QObject * return 0; } +void QmlEngineDebug::removeWatch(QmlDebugWatch *watch) +{ + Q_D(QmlEngineDebug); + + d->watched.remove(watch->queryId()); + + if (d->client->isConnected()) { + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("NO_WATCH") << watch->queryId(); + d->client->sendMessage(message); + } +} + QmlDebugEnginesQuery *QmlEngineDebug::queryAvailableEngines(QObject *parent) { Q_D(QmlEngineDebug); @@ -332,6 +441,56 @@ QmlDebugObjectQuery *QmlEngineDebug::queryObjectRecursive(const QmlDebugObjectRe return query; } +QmlDebugWatch::QmlDebugWatch(QObject *parent) +: QObject(parent), m_state(Waiting), m_queryId(-1), m_objectDebugId(-1) +{ +} + +int QmlDebugWatch::queryId() const +{ + return m_queryId; +} + +int QmlDebugWatch::objectDebugId() const +{ + return m_objectDebugId; +} + +QmlDebugWatch::State QmlDebugWatch::state() const +{ + return m_state; +} + +void QmlDebugWatch::setState(State s) +{ + if (m_state == s) + return; + m_state = s; + emit stateChanged(m_state); +} + +QmlDebugPropertyWatch::QmlDebugPropertyWatch(QObject *parent) + : QmlDebugWatch(parent) +{ +} + +QString QmlDebugPropertyWatch::name() const +{ + return m_name; +} + + +QmlDebugObjectExpressionWatch::QmlDebugObjectExpressionWatch(QObject *parent) + : QmlDebugWatch(parent) +{ +} + +QString QmlDebugObjectExpressionWatch::expression() const +{ + return m_expr; +} + + QmlDebugQuery::QmlDebugQuery(QObject *parent) : QObject(parent), m_state(Waiting) { @@ -436,18 +595,19 @@ QString QmlDebugEngineReference::name() const } QmlDebugObjectReference::QmlDebugObjectReference() -: m_debugId(-1) +: m_debugId(-1), m_contextDebugId(-1) { } QmlDebugObjectReference::QmlDebugObjectReference(int debugId) -: m_debugId(debugId) +: m_debugId(debugId), m_contextDebugId(-1) { } QmlDebugObjectReference::QmlDebugObjectReference(const QmlDebugObjectReference &o) -: m_debugId(o.m_debugId), m_class(o.m_class), m_name(o.m_name), - m_source(o.m_source), m_properties(o.m_properties), m_children(o.m_children) +: m_debugId(o.m_debugId), m_class(o.m_class), m_name(o.m_name), + m_source(o.m_source), m_contextDebugId(o.m_contextDebugId), + m_properties(o.m_properties), m_children(o.m_children) { } @@ -455,8 +615,8 @@ QmlDebugObjectReference & QmlDebugObjectReference::operator=(const QmlDebugObjectReference &o) { m_debugId = o.m_debugId; m_class = o.m_class; m_name = o.m_name; - m_source = o.m_source; m_properties = o.m_properties; - m_children = o.m_children; + m_source = o.m_source; m_contextDebugId = o.m_contextDebugId; + m_properties = o.m_properties; m_children = o.m_children; return *this; } @@ -480,6 +640,11 @@ QmlDebugFileReference QmlDebugObjectReference::source() const return m_source; } +int QmlDebugObjectReference::contextDebugId() const +{ + return m_contextDebugId; +} + QList<QmlDebugPropertyReference> QmlDebugObjectReference::properties() const { return m_properties; @@ -574,20 +739,26 @@ void QmlDebugFileReference::setColumnNumber(int c) } QmlDebugPropertyReference::QmlDebugPropertyReference() +: m_objectDebugId(-1) { } QmlDebugPropertyReference::QmlDebugPropertyReference(const QmlDebugPropertyReference &o) -: m_name(o.m_name), m_value(o.m_value), m_binding(o.m_binding) +: m_objectDebugId(o.m_objectDebugId), m_name(o.m_name), m_value(o.m_value), m_binding(o.m_binding) { } QmlDebugPropertyReference &QmlDebugPropertyReference::operator=(const QmlDebugPropertyReference &o) { - m_name = o.m_name; m_value = o.m_value; m_binding = o.m_binding; + m_objectDebugId = o.m_objectDebugId; m_name = o.m_name; m_value = o.m_value; m_binding = o.m_binding; return *this; } +int QmlDebugPropertyReference::objectDebugId() const +{ + return m_objectDebugId; +} + QString QmlDebugPropertyReference::name() const { return m_name; diff --git a/src/declarative/debugger/qmldebug.h b/src/declarative/debugger/qmldebug.h index 11e6b3e..be28a7e 100644 --- a/src/declarative/debugger/qmldebug.h +++ b/src/declarative/debugger/qmldebug.h @@ -7,6 +7,8 @@ class QmlDebugConnection; class QmlDebugWatch; +class QmlDebugPropertyWatch; +class QmlDebugObjectExpressionWatch; class QmlDebugEnginesQuery; class QmlDebugRootContextQuery; class QmlDebugObjectQuery; @@ -22,17 +24,19 @@ Q_OBJECT public: QmlEngineDebug(QmlDebugConnection *, QObject * = 0); - QmlDebugWatch *addWatch(const QmlDebugPropertyReference &, + QmlDebugPropertyWatch *addWatch(const QmlDebugPropertyReference &, QObject *parent = 0); QmlDebugWatch *addWatch(const QmlDebugContextReference &, const QString &, QObject *parent = 0); - QmlDebugWatch *addWatch(const QmlDebugObjectReference &, const QString &, + QmlDebugObjectExpressionWatch *addWatch(const QmlDebugObjectReference &, const QString &, QObject *parent = 0); QmlDebugWatch *addWatch(const QmlDebugObjectReference &, QObject *parent = 0); QmlDebugWatch *addWatch(const QmlDebugFileReference &, QObject *parent = 0); + void removeWatch(QmlDebugWatch *watch); + QmlDebugEnginesQuery *queryAvailableEngines(QObject *parent = 0); QmlDebugRootContextQuery *queryRootContexts(const QmlDebugEngineReference &, QObject *parent = 0); @@ -51,14 +55,57 @@ Q_OBJECT public: enum State { Waiting, Active, Inactive, Dead }; + QmlDebugWatch(QObject *); + + int queryId() const; + int objectDebugId() const; State state() const; signals: void stateChanged(State); - void objectChanged(int, const QmlDebugObjectReference &); - void valueChanged(int, const QVariant &); + //void objectChanged(int, const QmlDebugObjectReference &); + //void valueChanged(int, const QVariant &); + + // Server sends value as string if it is a user-type variant + void valueChanged(const QByteArray &name, const QVariant &value); + +private: + friend class QmlEngineDebug; + friend class QmlEngineDebugPrivate; + void setState(State); + State m_state; + int m_queryId; + int m_objectDebugId; +}; + +class Q_DECLARATIVE_EXPORT QmlDebugPropertyWatch : public QmlDebugWatch +{ + Q_OBJECT +public: + QmlDebugPropertyWatch(QObject *parent); + + QString name() const; + +private: + friend class QmlEngineDebug; + QString m_name; }; +class Q_DECLARATIVE_EXPORT QmlDebugObjectExpressionWatch : public QmlDebugWatch +{ + Q_OBJECT +public: + QmlDebugObjectExpressionWatch(QObject *parent); + + QString expression() const; + +private: + friend class QmlEngineDebug; + QString m_expr; + int m_debugId; +}; + + class Q_DECLARATIVE_EXPORT QmlDebugQuery : public QObject { Q_OBJECT @@ -134,6 +181,7 @@ public: QString name() const; QmlDebugFileReference source() const; + int contextDebugId() const; QList<QmlDebugPropertyReference> properties() const; QList<QmlDebugObjectReference> children() const; @@ -144,6 +192,7 @@ private: QString m_class; QString m_name; QmlDebugFileReference m_source; + int m_contextDebugId; QList<QmlDebugPropertyReference> m_properties; QList<QmlDebugObjectReference> m_children; }; @@ -176,12 +225,14 @@ public: QmlDebugPropertyReference(const QmlDebugPropertyReference &); QmlDebugPropertyReference &operator=(const QmlDebugPropertyReference &); + int objectDebugId() const; QString name() const; QVariant value() const; QString binding() const; private: friend class QmlEngineDebugPrivate; + int m_objectDebugId; QString m_name; QVariant m_value; QString m_binding; diff --git a/src/declarative/debugger/qmldebugservice.h b/src/declarative/debugger/qmldebugservice.h index c3c3b01..5d20ba0 100644 --- a/src/declarative/debugger/qmldebugservice.h +++ b/src/declarative/debugger/qmldebugservice.h @@ -49,7 +49,7 @@ QT_BEGIN_HEADER QT_BEGIN_NAMESPACE class QmlDebugServicePrivate; -class QmlDebugService : public QObject +class Q_DECLARATIVE_EXPORT QmlDebugService : public QObject { Q_OBJECT Q_DECLARE_PRIVATE(QmlDebugService) diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index 29d97ba..5df6532 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -32,7 +32,8 @@ SOURCES += qml/qmlparser.cpp \ qml/qmlvaluetype.cpp \ qml/qmlbindingoptimizations.cpp \ qml/qmlxmlhttprequest.cpp \ - qml/qmetaobjectbuilder.cpp + qml/qmetaobjectbuilder.cpp \ + qml/qmlwatcher.cpp HEADERS += qml/qmlparser_p.h \ qml/qmlinstruction_p.h \ @@ -81,7 +82,8 @@ HEADERS += qml/qmlparser_p.h \ qml/qmlvaluetype_p.h \ qml/qmlbindingoptimizations_p.h \ qml/qmlxmlhttprequest_p.h \ - qml/qmetaobjectbuilder_p.h + qml/qmetaobjectbuilder_p.h \ + qml/qmlwatcher_p.h # for qtscript debugger contains(QT_CONFIG, scripttools):QT += scripttools diff --git a/src/declarative/qml/qmlenginedebug.cpp b/src/declarative/qml/qmlenginedebug.cpp index 7f9e530..f5c1297 100644 --- a/src/declarative/qml/qmlenginedebug.cpp +++ b/src/declarative/qml/qmlenginedebug.cpp @@ -48,20 +48,24 @@ #include <qmlmetaproperty.h> #include <qmlbinding.h> #include "qmlcontext_p.h" +#include "qmlwatcher_p.h" QT_BEGIN_NAMESPACE QList<QmlEngine *> QmlEngineDebugServer::m_engines; QmlEngineDebugServer::QmlEngineDebugServer(QObject *parent) -: QmlDebugService(QLatin1String("QmlEngine"), parent) +: QmlDebugService(QLatin1String("QmlEngine"), parent), + m_watch(new QmlWatcher(this)) { + QObject::connect(m_watch, SIGNAL(propertyChanged(int,int,QByteArray,QVariant)), + this, SLOT(propertyChanged(int,int,QByteArray,QVariant))); } QDataStream &operator<<(QDataStream &ds, const QmlEngineDebugServer::QmlObjectData &data) { ds << data.url << data.lineNumber << data.columnNumber << data.objectName - << data.objectType << data.objectId; + << data.objectType << data.objectId << data.contextId; return ds; } @@ -69,7 +73,7 @@ QDataStream &operator>>(QDataStream &ds, QmlEngineDebugServer::QmlObjectData &data) { ds >> data.url >> data.lineNumber >> data.columnNumber >> data.objectName - >> data.objectType >> data.objectId; + >> data.objectType >> data.objectId >> data.contextId; return ds; } @@ -200,6 +204,7 @@ QmlEngineDebugServer::objectData(QObject *object) rv.objectName = object->objectName(); rv.objectType = object->metaObject()->className(); rv.objectId = QmlDebugService::idForObject(object); + rv.contextId = QmlDebugService::idForObject(qmlContext(object)); return rv; } @@ -211,6 +216,8 @@ void QmlEngineDebugServer::messageReceived(const QByteArray &message) QByteArray type; ds >> type; + //qDebug() << "QmlEngineDebugServer::messageReceived()" << type; + if (type == "LIST_ENGINES") { int queryId; ds >> queryId; @@ -263,9 +270,78 @@ void QmlEngineDebugServer::messageReceived(const QByteArray &message) buildObjectDump(rs, object, recurse); 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 << objectId << 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); } } +void QmlEngineDebugServer::propertyChanged(int id, int objectId, const QByteArray &property, const QVariant &value) +{ + QByteArray reply; + QVariant v; + QDataStream rs(&reply, QIODevice::WriteOnly); + + if (value.type() == QVariant::UserType) { + QObject *o = QmlMetaType::toQObject(value); + if (o) { + QString objectName = o->objectName(); + if (objectName.isEmpty()) + objectName = QLatin1String("<unnamed>"); + v = QLatin1String(o->metaObject()->className()) + + QLatin1String(": ") + objectName; + } + if (v.isNull()) + v = value.toString(); + } else { + v = value; + } + + rs << QByteArray("UPDATE_WATCH") << id << objectId << property << v; + + sendMessage(reply); +} + void QmlEngineDebugServer::addEngine(QmlEngine *engine) { Q_ASSERT(engine); diff --git a/src/declarative/qml/qmlenginedebug_p.h b/src/declarative/qml/qmlenginedebug_p.h index 87b2ffd..f935c04 100644 --- a/src/declarative/qml/qmlenginedebug_p.h +++ b/src/declarative/qml/qmlenginedebug_p.h @@ -61,9 +61,12 @@ QT_BEGIN_NAMESPACE class QmlEngine; class QmlContext; +class QmlWatcher; class QDataStream; + class QmlEngineDebugServer : public QmlDebugService { + Q_OBJECT public: QmlEngineDebugServer(QObject * = 0); @@ -74,6 +77,7 @@ public: QString objectName; QString objectType; int objectId; + int contextId; }; struct QmlObjectProperty { @@ -90,6 +94,9 @@ public: protected: virtual void messageReceived(const QByteArray &); +private Q_SLOTS: + void propertyChanged(int id, int objectId, const QByteArray &property, const QVariant &value); + private: void buildObjectList(QDataStream &, QmlContext *); void buildObjectDump(QDataStream &, QObject *, bool); @@ -97,6 +104,7 @@ private: QmlObjectProperty propertyData(QObject *, int); static QList<QmlEngine *> m_engines; + QmlWatcher *m_watch; }; Q_DECLARATIVE_EXPORT QDataStream &operator<<(QDataStream &, const QmlEngineDebugServer::QmlObjectData &); Q_DECLARATIVE_EXPORT QDataStream &operator>>(QDataStream &, QmlEngineDebugServer::QmlObjectData &); diff --git a/src/declarative/qml/qmlwatcher.cpp b/src/declarative/qml/qmlwatcher.cpp new file mode 100644 index 0000000..eb00dfe --- /dev/null +++ b/src/declarative/qml/qmlwatcher.cpp @@ -0,0 +1,183 @@ +/**************************************************************************** +** +** 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 <QtCore/qmetaobject.h> +#include <QtCore/qdebug.h> +#include <QtDeclarative/qmlexpression.h> +#include <QtDeclarative/qmldebugservice.h> +#include <QtDeclarative/qmlcontext.h> +#include <QtDeclarative/qml.h> + +#include "qmlwatcher_p.h" + +QT_BEGIN_NAMESPACE + + +class QmlWatchProxy : public QObject +{ + Q_OBJECT +public: + QmlWatchProxy(int id, + QObject *object, + int debugId, + const QMetaProperty &prop, + QmlWatcher *parent = 0); + + QmlWatchProxy(int id, + QmlExpression *exp, + int debugId, + QmlWatcher *parent = 0); + +public slots: + void notifyValueChanged(); + +private: + friend class QmlWatcher; + int m_id; + QmlWatcher *m_watch; + QObject *m_object; + int m_debugId; + QMetaProperty m_property; + + QmlExpression *m_expr; +}; + +QmlWatchProxy::QmlWatchProxy(int id, + QmlExpression *exp, + int debugId, + QmlWatcher *parent) +: QObject(parent), m_id(id), m_watch(parent), m_object(0), m_debugId(debugId), m_expr(exp) +{ + QObject::connect(m_expr, SIGNAL(valueChanged()), this, SLOT(notifyValueChanged())); +} + +QmlWatchProxy::QmlWatchProxy(int id, + QObject *object, + int debugId, + const QMetaProperty &prop, + QmlWatcher *parent) +: QObject(parent), m_id(id), m_watch(parent), m_object(object), m_debugId(debugId), m_property(prop), m_expr(0) +{ + static int refreshIdx = -1; + if(refreshIdx == -1) + refreshIdx = QmlWatchProxy::staticMetaObject.indexOfMethod("notifyValueChanged()"); + + if (prop.hasNotifySignal()) + QMetaObject::connect(m_object, prop.notifySignalIndex(), this, refreshIdx); +} + +void QmlWatchProxy::notifyValueChanged() +{ + QVariant v; + if (m_expr) + v = m_expr->value(); + else + v = m_property.read(m_object); + + emit m_watch->propertyChanged(m_id, m_debugId, QByteArray(m_property.name()), v); +} + + +QmlWatcher::QmlWatcher(QObject *parent) + : QObject(parent) +{ +} + +bool QmlWatcher::addWatch(int id, quint32 debugId) +{ + QObject *object = QmlDebugService::objectForId(debugId); + if (object) { + int propCount = object->metaObject()->propertyCount(); + for (int ii=0; ii<propCount; ii++) + addPropertyWatch(id, object, debugId, object->metaObject()->property(ii)); + return true; + } + return false; +} + +bool QmlWatcher::addWatch(int id, quint32 debugId, const QByteArray &property) +{ + QObject *object = QmlDebugService::objectForId(debugId); + if (object) { + int index = object->metaObject()->indexOfProperty(property.constData()); + if (index >= 0) { + addPropertyWatch(id, object, debugId, object->metaObject()->property(index)); + return true; + } + } + return false; +} + +bool QmlWatcher::addWatch(int id, quint32 objectId, const QString &expr) +{ + QObject *object = QmlDebugService::objectForId(objectId); + QmlContext *context = qmlContext(object); + if (context) { + QmlExpression *exprObj = new QmlExpression(context, expr, object); + QmlWatchProxy *proxy = new QmlWatchProxy(id, exprObj, objectId, this); + exprObj->setParent(proxy); + m_proxies[id].append(proxy); + proxy->notifyValueChanged(); + return true; + } + return false; +} + +void QmlWatcher::removeWatch(int id) +{ + if (!m_proxies.contains(id)) + return; + + QList<QPointer<QmlWatchProxy> > proxies = m_proxies.take(id); + qDeleteAll(proxies); +} + +void QmlWatcher::addPropertyWatch(int id, QObject *object, quint32 debugId, const QMetaProperty &property) +{ + QmlWatchProxy *proxy = new QmlWatchProxy(id, object, debugId, property, this); + m_proxies[id].append(proxy); + + proxy->notifyValueChanged(); +} + +QT_END_NAMESPACE + +#include "qmlwatch.moc" diff --git a/src/declarative/qml/qmlwatcher_p.h b/src/declarative/qml/qmlwatcher_p.h new file mode 100644 index 0000000..99cae88 --- /dev/null +++ b/src/declarative/qml/qmlwatcher_p.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** 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 QMLWATCHER_P_H +#define QMLWATCHER_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 <QtCore/qobject.h> +#include <QtCore/qlist.h> +#include <QtCore/qpair.h> +#include <QtCore/qhash.h> +#include <QtCore/qset.h> +#include <QtCore/qpointer.h> + +QT_BEGIN_NAMESPACE + +class QmlWatchProxy; +class QmlExpression; +class QmlContext; + +class QmlWatcher : public QObject +{ + Q_OBJECT +public: + QmlWatcher(QObject * = 0); + + bool addWatch(int id, quint32 objectId); + bool addWatch(int id, quint32 objectId, const QByteArray &property); + bool addWatch(int id, quint32 objectId, const QString &expr); + + void removeWatch(int id); + +Q_SIGNALS: + void propertyChanged(int id, int objectId, const QByteArray &property, const QVariant &value); + +private: + friend class QmlWatchProxy; + void addPropertyWatch(int id, QObject *object, quint32 objectId, const QMetaProperty &property); + + QHash<int, QList<QPointer<QmlWatchProxy> > > m_proxies; +}; + +QT_END_NAMESPACE + +#endif // QMLWATCHER_P_H |