diff options
Diffstat (limited to 'src/declarative/qml')
-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 |
5 files changed, 367 insertions, 5 deletions
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 |