diff options
Diffstat (limited to 'src/declarative/debugger')
19 files changed, 3998 insertions, 0 deletions
diff --git a/src/declarative/debugger/debugger.pri b/src/declarative/debugger/debugger.pri new file mode 100644 index 0000000000..75287b4563 --- /dev/null +++ b/src/declarative/debugger/debugger.pri @@ -0,0 +1,23 @@ +INCLUDEPATH += $$PWD + +SOURCES += \ + $$PWD/qdeclarativedebuggerstatus.cpp \ + $$PWD/qpacketprotocol.cpp \ + $$PWD/qdeclarativedebugservice.cpp \ + $$PWD/qdeclarativedebugclient.cpp \ + $$PWD/qdeclarativedebug.cpp \ + $$PWD/qdeclarativedebugtrace.cpp \ + $$PWD/qdeclarativedebughelper.cpp \ + $$PWD/qdeclarativedebugserver.cpp + +HEADERS += \ + $$PWD/qdeclarativedebuggerstatus_p.h \ + $$PWD/qpacketprotocol_p.h \ + $$PWD/qdeclarativedebugservice_p.h \ + $$PWD/qdeclarativedebugservice_p_p.h \ + $$PWD/qdeclarativedebugclient_p.h \ + $$PWD/qdeclarativedebug_p.h \ + $$PWD/qdeclarativedebugtrace_p.h \ + $$PWD/qdeclarativedebughelper_p.h \ + $$PWD/qdeclarativedebugserver_p.h \ + debugger/qdeclarativedebugserverconnection_p.h diff --git a/src/declarative/debugger/qdeclarativedebug.cpp b/src/declarative/debugger/qdeclarativedebug.cpp new file mode 100644 index 0000000000..62eb8fea3e --- /dev/null +++ b/src/declarative/debugger/qdeclarativedebug.cpp @@ -0,0 +1,1021 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "private/qdeclarativedebug_p.h" + +#include "private/qdeclarativedebugclient_p.h" + +#include <qdeclarativeenginedebug_p.h> + +#include <private/qobject_p.h> + +QT_BEGIN_NAMESPACE + +class QDeclarativeEngineDebugClient : public QDeclarativeDebugClient +{ +public: + QDeclarativeEngineDebugClient(QDeclarativeDebugConnection *client, QDeclarativeEngineDebugPrivate *p); + +protected: + virtual void statusChanged(Status status); + virtual void messageReceived(const QByteArray &); + +private: + QDeclarativeEngineDebugPrivate *priv; + friend class QDeclarativeEngineDebugPrivate; +}; + +class QDeclarativeEngineDebugPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QDeclarativeEngineDebug) +public: + QDeclarativeEngineDebugPrivate(QDeclarativeDebugConnection *); + ~QDeclarativeEngineDebugPrivate(); + + void statusChanged(QDeclarativeEngineDebug::Status status); + void message(const QByteArray &); + + QDeclarativeEngineDebugClient *client; + int nextId; + int getId(); + + void decode(QDataStream &, QDeclarativeDebugContextReference &); + void decode(QDataStream &, QDeclarativeDebugObjectReference &, bool simple); + + static void remove(QDeclarativeEngineDebug *, QDeclarativeDebugEnginesQuery *); + static void remove(QDeclarativeEngineDebug *, QDeclarativeDebugRootContextQuery *); + static void remove(QDeclarativeEngineDebug *, QDeclarativeDebugObjectQuery *); + static void remove(QDeclarativeEngineDebug *, QDeclarativeDebugExpressionQuery *); + + QHash<int, QDeclarativeDebugEnginesQuery *> enginesQuery; + QHash<int, QDeclarativeDebugRootContextQuery *> rootContextQuery; + QHash<int, QDeclarativeDebugObjectQuery *> objectQuery; + QHash<int, QDeclarativeDebugExpressionQuery *> expressionQuery; + + QHash<int, QDeclarativeDebugWatch *> watched; +}; + +QDeclarativeEngineDebugClient::QDeclarativeEngineDebugClient(QDeclarativeDebugConnection *client, + QDeclarativeEngineDebugPrivate *p) +: QDeclarativeDebugClient(QLatin1String("QDeclarativeEngine"), client), priv(p) +{ +} + +void QDeclarativeEngineDebugClient::statusChanged(Status status) +{ + if (priv) + priv->statusChanged(static_cast<QDeclarativeEngineDebug::Status>(status)); +} + +void QDeclarativeEngineDebugClient::messageReceived(const QByteArray &data) +{ + if (priv) + priv->message(data); +} + +QDeclarativeEngineDebugPrivate::QDeclarativeEngineDebugPrivate(QDeclarativeDebugConnection *c) +: client(new QDeclarativeEngineDebugClient(c, this)), nextId(0) +{ +} + +QDeclarativeEngineDebugPrivate::~QDeclarativeEngineDebugPrivate() +{ + if (client) + client->priv = 0; +} + +int QDeclarativeEngineDebugPrivate::getId() +{ + return nextId++; +} + +void QDeclarativeEngineDebugPrivate::remove(QDeclarativeEngineDebug *c, QDeclarativeDebugEnginesQuery *q) +{ + if (c && q) { + QDeclarativeEngineDebugPrivate *p = (QDeclarativeEngineDebugPrivate *)QObjectPrivate::get(c); + p->enginesQuery.remove(q->m_queryId); + } +} + +void QDeclarativeEngineDebugPrivate::remove(QDeclarativeEngineDebug *c, + QDeclarativeDebugRootContextQuery *q) +{ + if (c && q) { + QDeclarativeEngineDebugPrivate *p = (QDeclarativeEngineDebugPrivate *)QObjectPrivate::get(c); + p->rootContextQuery.remove(q->m_queryId); + } +} + +void QDeclarativeEngineDebugPrivate::remove(QDeclarativeEngineDebug *c, QDeclarativeDebugObjectQuery *q) +{ + if (c && q) { + QDeclarativeEngineDebugPrivate *p = (QDeclarativeEngineDebugPrivate *)QObjectPrivate::get(c); + p->objectQuery.remove(q->m_queryId); + } +} + +void QDeclarativeEngineDebugPrivate::remove(QDeclarativeEngineDebug *c, QDeclarativeDebugExpressionQuery *q) +{ + if (c && q) { + QDeclarativeEngineDebugPrivate *p = (QDeclarativeEngineDebugPrivate *)QObjectPrivate::get(c); + p->expressionQuery.remove(q->m_queryId); + } +} + +void QDeclarativeEngineDebugPrivate::decode(QDataStream &ds, QDeclarativeDebugObjectReference &o, + bool simple) +{ + QDeclarativeEngineDebugServer::QDeclarativeObjectData data; + ds >> data; + o.m_debugId = data.objectId; + o.m_class = data.objectType; + o.m_idString = data.idString; + o.m_name = data.objectName; + 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; + + int childCount; + bool recur; + ds >> childCount >> recur; + + for (int ii = 0; ii < childCount; ++ii) { + o.m_children.append(QDeclarativeDebugObjectReference()); + decode(ds, o.m_children.last(), !recur); + } + + int propCount; + ds >> propCount; + + for (int ii = 0; ii < propCount; ++ii) { + QDeclarativeEngineDebugServer::QDeclarativeObjectProperty data; + ds >> data; + QDeclarativeDebugPropertyReference prop; + prop.m_objectDebugId = o.m_debugId; + prop.m_name = data.name; + prop.m_binding = data.binding; + 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: + { + prop.m_value = data.value; + break; + } + case QDeclarativeEngineDebugServer::QDeclarativeObjectProperty::Object: + { + QDeclarativeDebugObjectReference obj; + obj.m_debugId = prop.m_value.toInt(); + prop.m_value = QVariant::fromValue(obj); + break; + } + case QDeclarativeEngineDebugServer::QDeclarativeObjectProperty::Unknown: + break; + } + o.m_properties << prop; + } +} + +void QDeclarativeEngineDebugPrivate::decode(QDataStream &ds, QDeclarativeDebugContextReference &c) +{ + ds >> c.m_name >> c.m_debugId; + + int contextCount; + ds >> contextCount; + + for (int ii = 0; ii < contextCount; ++ii) { + c.m_contexts.append(QDeclarativeDebugContextReference()); + decode(ds, c.m_contexts.last()); + } + + int objectCount; + ds >> objectCount; + + for (int ii = 0; ii < objectCount; ++ii) { + QDeclarativeDebugObjectReference obj; + decode(ds, obj, true); + + obj.m_contextDebugId = c.m_debugId; + c.m_objects << obj; + } +} + +void QDeclarativeEngineDebugPrivate::statusChanged(QDeclarativeEngineDebug::Status status) +{ + emit q_func()->statusChanged(status); +} + +void QDeclarativeEngineDebugPrivate::message(const QByteArray &data) +{ + QDataStream ds(data); + + QByteArray type; + ds >> type; + + //qDebug() << "QDeclarativeEngineDebugPrivate::message()" << type; + + if (type == "LIST_ENGINES_R") { + int queryId; + ds >> queryId; + + QDeclarativeDebugEnginesQuery *query = enginesQuery.value(queryId); + if (!query) + return; + enginesQuery.remove(queryId); + + int count; + ds >> count; + + for (int ii = 0; ii < count; ++ii) { + QDeclarativeDebugEngineReference ref; + ds >> ref.m_name; + ds >> ref.m_debugId; + query->m_engines << ref; + } + + query->m_client = 0; + query->setState(QDeclarativeDebugQuery::Completed); + } else if (type == "LIST_OBJECTS_R") { + int queryId; + ds >> queryId; + + QDeclarativeDebugRootContextQuery *query = rootContextQuery.value(queryId); + if (!query) + return; + rootContextQuery.remove(queryId); + + if (!ds.atEnd()) + decode(ds, query->m_context); + + query->m_client = 0; + query->setState(QDeclarativeDebugQuery::Completed); + } else if (type == "FETCH_OBJECT_R") { + int queryId; + ds >> queryId; + + QDeclarativeDebugObjectQuery *query = objectQuery.value(queryId); + if (!query) + return; + objectQuery.remove(queryId); + + if (!ds.atEnd()) + decode(ds, query->m_object, false); + + query->m_client = 0; + query->setState(QDeclarativeDebugQuery::Completed); + } else if (type == "EVAL_EXPRESSION_R") { + int queryId; + QVariant result; + ds >> queryId >> result; + + QDeclarativeDebugExpressionQuery *query = expressionQuery.value(queryId); + if (!query) + return; + expressionQuery.remove(queryId); + + query->m_result = result; + query->m_client = 0; + query->setState(QDeclarativeDebugQuery::Completed); + } else if (type == "WATCH_PROPERTY_R") { + int queryId; + bool ok; + ds >> queryId >> ok; + + QDeclarativeDebugWatch *watch = watched.value(queryId); + if (!watch) + return; + + watch->setState(ok ? QDeclarativeDebugWatch::Active : QDeclarativeDebugWatch::Inactive); + } else if (type == "WATCH_OBJECT_R") { + int queryId; + bool ok; + ds >> queryId >> ok; + + QDeclarativeDebugWatch *watch = watched.value(queryId); + if (!watch) + return; + + watch->setState(ok ? QDeclarativeDebugWatch::Active : QDeclarativeDebugWatch::Inactive); + } else if (type == "WATCH_EXPR_OBJECT_R") { + int queryId; + bool ok; + ds >> queryId >> ok; + + QDeclarativeDebugWatch *watch = watched.value(queryId); + if (!watch) + return; + + watch->setState(ok ? QDeclarativeDebugWatch::Active : QDeclarativeDebugWatch::Inactive); + } else if (type == "UPDATE_WATCH") { + int queryId; + int debugId; + QByteArray name; + QVariant value; + ds >> queryId >> debugId >> name >> value; + + QDeclarativeDebugWatch *watch = watched.value(queryId, 0); + if (!watch) + return; + emit watch->valueChanged(name, value); + } else if (type == "OBJECT_CREATED") { + emit q_func()->newObjects(); + } +} + +QDeclarativeEngineDebug::QDeclarativeEngineDebug(QDeclarativeDebugConnection *client, QObject *parent) +: QObject(*(new QDeclarativeEngineDebugPrivate(client)), parent) +{ +} + +QDeclarativeEngineDebug::Status QDeclarativeEngineDebug::status() const +{ + Q_D(const QDeclarativeEngineDebug); + + return static_cast<QDeclarativeEngineDebug::Status>(d->client->status()); +} + +QDeclarativeDebugPropertyWatch *QDeclarativeEngineDebug::addWatch(const QDeclarativeDebugPropertyReference &property, QObject *parent) +{ + Q_D(QDeclarativeEngineDebug); + + QDeclarativeDebugPropertyWatch *watch = new QDeclarativeDebugPropertyWatch(parent); + if (d->client->status() == QDeclarativeDebugClient::Enabled) { + int queryId = d->getId(); + watch->m_queryId = queryId; + watch->m_client = this; + watch->m_objectDebugId = property.objectDebugId(); + watch->m_name = property.name(); + d->watched.insert(queryId, watch); + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("WATCH_PROPERTY") << queryId << property.objectDebugId() << property.name().toUtf8(); + d->client->sendMessage(message); + } else { + watch->m_state = QDeclarativeDebugWatch::Dead; + } + + return watch; +} + +QDeclarativeDebugWatch *QDeclarativeEngineDebug::addWatch(const QDeclarativeDebugContextReference &, const QString &, QObject *) +{ + qWarning("QDeclarativeEngineDebug::addWatch(): Not implemented"); + return 0; +} + +QDeclarativeDebugObjectExpressionWatch *QDeclarativeEngineDebug::addWatch(const QDeclarativeDebugObjectReference &object, const QString &expr, QObject *parent) +{ + Q_D(QDeclarativeEngineDebug); + QDeclarativeDebugObjectExpressionWatch *watch = new QDeclarativeDebugObjectExpressionWatch(parent); + if (d->client->status() == QDeclarativeDebugClient::Enabled) { + int queryId = d->getId(); + watch->m_queryId = queryId; + watch->m_client = this; + watch->m_objectDebugId = object.debugId(); + watch->m_expr = expr; + 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 = QDeclarativeDebugWatch::Dead; + } + return watch; +} + +QDeclarativeDebugWatch *QDeclarativeEngineDebug::addWatch(const QDeclarativeDebugObjectReference &object, QObject *parent) +{ + Q_D(QDeclarativeEngineDebug); + + QDeclarativeDebugWatch *watch = new QDeclarativeDebugWatch(parent); + if (d->client->status() == QDeclarativeDebugClient::Enabled) { + int queryId = d->getId(); + watch->m_queryId = queryId; + watch->m_client = this; + 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 = QDeclarativeDebugWatch::Dead; + } + + return watch; +} + +QDeclarativeDebugWatch *QDeclarativeEngineDebug::addWatch(const QDeclarativeDebugFileReference &, QObject *) +{ + qWarning("QDeclarativeEngineDebug::addWatch(): Not implemented"); + return 0; +} + +void QDeclarativeEngineDebug::removeWatch(QDeclarativeDebugWatch *watch) +{ + Q_D(QDeclarativeEngineDebug); + + if (!watch || !watch->m_client) + return; + + watch->m_client = 0; + watch->setState(QDeclarativeDebugWatch::Inactive); + + d->watched.remove(watch->queryId()); + + if (d->client && d->client->status() == QDeclarativeDebugClient::Enabled) { + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("NO_WATCH") << watch->queryId(); + d->client->sendMessage(message); + } +} + +QDeclarativeDebugEnginesQuery *QDeclarativeEngineDebug::queryAvailableEngines(QObject *parent) +{ + Q_D(QDeclarativeEngineDebug); + + QDeclarativeDebugEnginesQuery *query = new QDeclarativeDebugEnginesQuery(parent); + if (d->client->status() == QDeclarativeDebugClient::Enabled) { + query->m_client = this; + int queryId = d->getId(); + query->m_queryId = queryId; + d->enginesQuery.insert(queryId, query); + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("LIST_ENGINES") << queryId; + d->client->sendMessage(message); + } else { + query->m_state = QDeclarativeDebugQuery::Error; + } + + return query; +} + +QDeclarativeDebugRootContextQuery *QDeclarativeEngineDebug::queryRootContexts(const QDeclarativeDebugEngineReference &engine, QObject *parent) +{ + Q_D(QDeclarativeEngineDebug); + + QDeclarativeDebugRootContextQuery *query = new QDeclarativeDebugRootContextQuery(parent); + if (d->client->status() == QDeclarativeDebugClient::Enabled && engine.debugId() != -1) { + query->m_client = this; + int queryId = d->getId(); + query->m_queryId = queryId; + d->rootContextQuery.insert(queryId, query); + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("LIST_OBJECTS") << queryId << engine.debugId(); + d->client->sendMessage(message); + } else { + query->m_state = QDeclarativeDebugQuery::Error; + } + + return query; +} + +QDeclarativeDebugObjectQuery *QDeclarativeEngineDebug::queryObject(const QDeclarativeDebugObjectReference &object, QObject *parent) +{ + Q_D(QDeclarativeEngineDebug); + + QDeclarativeDebugObjectQuery *query = new QDeclarativeDebugObjectQuery(parent); + if (d->client->status() == QDeclarativeDebugClient::Enabled && object.debugId() != -1) { + query->m_client = this; + int queryId = d->getId(); + query->m_queryId = queryId; + d->objectQuery.insert(queryId, query); + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("FETCH_OBJECT") << queryId << object.debugId() + << false << true; + d->client->sendMessage(message); + } else { + query->m_state = QDeclarativeDebugQuery::Error; + } + + return query; +} + +QDeclarativeDebugObjectQuery *QDeclarativeEngineDebug::queryObjectRecursive(const QDeclarativeDebugObjectReference &object, QObject *parent) +{ + Q_D(QDeclarativeEngineDebug); + + QDeclarativeDebugObjectQuery *query = new QDeclarativeDebugObjectQuery(parent); + if (d->client->status() == QDeclarativeDebugClient::Enabled && object.debugId() != -1) { + query->m_client = this; + int queryId = d->getId(); + query->m_queryId = queryId; + d->objectQuery.insert(queryId, query); + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("FETCH_OBJECT") << queryId << object.debugId() + << true << true; + d->client->sendMessage(message); + } else { + query->m_state = QDeclarativeDebugQuery::Error; + } + + return query; +} + +QDeclarativeDebugExpressionQuery *QDeclarativeEngineDebug::queryExpressionResult(int objectDebugId, const QString &expr, QObject *parent) +{ + Q_D(QDeclarativeEngineDebug); + + QDeclarativeDebugExpressionQuery *query = new QDeclarativeDebugExpressionQuery(parent); + if (d->client->status() == QDeclarativeDebugClient::Enabled && objectDebugId != -1) { + query->m_client = this; + query->m_expr = expr; + int queryId = d->getId(); + query->m_queryId = queryId; + d->expressionQuery.insert(queryId, query); + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("EVAL_EXPRESSION") << queryId << objectDebugId << expr; + d->client->sendMessage(message); + } else { + query->m_state = QDeclarativeDebugQuery::Error; + } + + return query; +} + +bool QDeclarativeEngineDebug::setBindingForObject(int objectDebugId, const QString &propertyName, + const QVariant &bindingExpression, + bool isLiteralValue) +{ + Q_D(QDeclarativeEngineDebug); + + if (d->client->status() == QDeclarativeDebugClient::Enabled && objectDebugId != -1) { + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("SET_BINDING") << objectDebugId << propertyName << bindingExpression << isLiteralValue; + d->client->sendMessage(message); + return true; + } else { + return false; + } +} + +bool QDeclarativeEngineDebug::resetBindingForObject(int objectDebugId, const QString &propertyName) +{ + Q_D(QDeclarativeEngineDebug); + + if (d->client->status() == QDeclarativeDebugClient::Enabled && objectDebugId != -1) { + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("RESET_BINDING") << objectDebugId << propertyName; + d->client->sendMessage(message); + return true; + } else { + return false; + } +} + +bool QDeclarativeEngineDebug::setMethodBody(int objectDebugId, const QString &methodName, + const QString &methodBody) +{ + Q_D(QDeclarativeEngineDebug); + + if (d->client->status() == QDeclarativeDebugClient::Enabled && objectDebugId != -1) { + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("SET_METHOD_BODY") << objectDebugId << methodName << methodBody; + d->client->sendMessage(message); + return true; + } else { + return false; + } +} + +QDeclarativeDebugWatch::QDeclarativeDebugWatch(QObject *parent) +: QObject(parent), m_state(Waiting), m_queryId(-1), m_client(0), m_objectDebugId(-1) +{ +} + +QDeclarativeDebugWatch::~QDeclarativeDebugWatch() +{ +} + +int QDeclarativeDebugWatch::queryId() const +{ + return m_queryId; +} + +int QDeclarativeDebugWatch::objectDebugId() const +{ + return m_objectDebugId; +} + +QDeclarativeDebugWatch::State QDeclarativeDebugWatch::state() const +{ + return m_state; +} + +void QDeclarativeDebugWatch::setState(State s) +{ + if (m_state == s) + return; + m_state = s; + emit stateChanged(m_state); +} + +QDeclarativeDebugPropertyWatch::QDeclarativeDebugPropertyWatch(QObject *parent) + : QDeclarativeDebugWatch(parent) +{ +} + +QString QDeclarativeDebugPropertyWatch::name() const +{ + return m_name; +} + + +QDeclarativeDebugObjectExpressionWatch::QDeclarativeDebugObjectExpressionWatch(QObject *parent) + : QDeclarativeDebugWatch(parent) +{ +} + +QString QDeclarativeDebugObjectExpressionWatch::expression() const +{ + return m_expr; +} + + +QDeclarativeDebugQuery::QDeclarativeDebugQuery(QObject *parent) +: QObject(parent), m_state(Waiting) +{ +} + +QDeclarativeDebugQuery::State QDeclarativeDebugQuery::state() const +{ + return m_state; +} + +bool QDeclarativeDebugQuery::isWaiting() const +{ + return m_state == Waiting; +} + +void QDeclarativeDebugQuery::setState(State s) +{ + if (m_state == s) + return; + m_state = s; + emit stateChanged(m_state); +} + +QDeclarativeDebugEnginesQuery::QDeclarativeDebugEnginesQuery(QObject *parent) +: QDeclarativeDebugQuery(parent), m_client(0), m_queryId(-1) +{ +} + +QDeclarativeDebugEnginesQuery::~QDeclarativeDebugEnginesQuery() +{ + if (m_client && m_queryId != -1) + QDeclarativeEngineDebugPrivate::remove(m_client, this); +} + +QList<QDeclarativeDebugEngineReference> QDeclarativeDebugEnginesQuery::engines() const +{ + return m_engines; +} + +QDeclarativeDebugRootContextQuery::QDeclarativeDebugRootContextQuery(QObject *parent) +: QDeclarativeDebugQuery(parent), m_client(0), m_queryId(-1) +{ +} + +QDeclarativeDebugRootContextQuery::~QDeclarativeDebugRootContextQuery() +{ + if (m_client && m_queryId != -1) + QDeclarativeEngineDebugPrivate::remove(m_client, this); +} + +QDeclarativeDebugContextReference QDeclarativeDebugRootContextQuery::rootContext() const +{ + return m_context; +} + +QDeclarativeDebugObjectQuery::QDeclarativeDebugObjectQuery(QObject *parent) +: QDeclarativeDebugQuery(parent), m_client(0), m_queryId(-1) +{ +} + +QDeclarativeDebugObjectQuery::~QDeclarativeDebugObjectQuery() +{ + if (m_client && m_queryId != -1) + QDeclarativeEngineDebugPrivate::remove(m_client, this); +} + +QDeclarativeDebugObjectReference QDeclarativeDebugObjectQuery::object() const +{ + return m_object; +} + +QDeclarativeDebugExpressionQuery::QDeclarativeDebugExpressionQuery(QObject *parent) +: QDeclarativeDebugQuery(parent), m_client(0), m_queryId(-1) +{ +} + +QDeclarativeDebugExpressionQuery::~QDeclarativeDebugExpressionQuery() +{ + if (m_client && m_queryId != -1) + QDeclarativeEngineDebugPrivate::remove(m_client, this); +} + +QVariant QDeclarativeDebugExpressionQuery::expression() const +{ + return m_expr; +} + +QVariant QDeclarativeDebugExpressionQuery::result() const +{ + return m_result; +} + +QDeclarativeDebugEngineReference::QDeclarativeDebugEngineReference() +: m_debugId(-1) +{ +} + +QDeclarativeDebugEngineReference::QDeclarativeDebugEngineReference(int debugId) +: m_debugId(debugId) +{ +} + +QDeclarativeDebugEngineReference::QDeclarativeDebugEngineReference(const QDeclarativeDebugEngineReference &o) +: m_debugId(o.m_debugId), m_name(o.m_name) +{ +} + +QDeclarativeDebugEngineReference & +QDeclarativeDebugEngineReference::operator=(const QDeclarativeDebugEngineReference &o) +{ + m_debugId = o.m_debugId; m_name = o.m_name; + return *this; +} + +int QDeclarativeDebugEngineReference::debugId() const +{ + return m_debugId; +} + +QString QDeclarativeDebugEngineReference::name() const +{ + return m_name; +} + +QDeclarativeDebugObjectReference::QDeclarativeDebugObjectReference() +: m_debugId(-1), m_contextDebugId(-1) +{ +} + +QDeclarativeDebugObjectReference::QDeclarativeDebugObjectReference(int debugId) +: m_debugId(debugId), m_contextDebugId(-1) +{ +} + +QDeclarativeDebugObjectReference::QDeclarativeDebugObjectReference(const QDeclarativeDebugObjectReference &o) +: m_debugId(o.m_debugId), m_class(o.m_class), m_idString(o.m_idString), + 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) +{ +} + +QDeclarativeDebugObjectReference & +QDeclarativeDebugObjectReference::operator=(const QDeclarativeDebugObjectReference &o) +{ + m_debugId = o.m_debugId; m_class = o.m_class; m_idString = o.m_idString; + 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; + return *this; +} + +int QDeclarativeDebugObjectReference::debugId() const +{ + return m_debugId; +} + +QString QDeclarativeDebugObjectReference::className() const +{ + return m_class; +} + +QString QDeclarativeDebugObjectReference::idString() const +{ + return m_idString; +} + +QString QDeclarativeDebugObjectReference::name() const +{ + return m_name; +} + +QDeclarativeDebugFileReference QDeclarativeDebugObjectReference::source() const +{ + return m_source; +} + +int QDeclarativeDebugObjectReference::contextDebugId() const +{ + return m_contextDebugId; +} + +QList<QDeclarativeDebugPropertyReference> QDeclarativeDebugObjectReference::properties() const +{ + return m_properties; +} + +QList<QDeclarativeDebugObjectReference> QDeclarativeDebugObjectReference::children() const +{ + return m_children; +} + +QDeclarativeDebugContextReference::QDeclarativeDebugContextReference() +: m_debugId(-1) +{ +} + +QDeclarativeDebugContextReference::QDeclarativeDebugContextReference(const QDeclarativeDebugContextReference &o) +: m_debugId(o.m_debugId), m_name(o.m_name), m_objects(o.m_objects), m_contexts(o.m_contexts) +{ +} + +QDeclarativeDebugContextReference &QDeclarativeDebugContextReference::operator=(const QDeclarativeDebugContextReference &o) +{ + m_debugId = o.m_debugId; m_name = o.m_name; m_objects = o.m_objects; + m_contexts = o.m_contexts; + return *this; +} + +int QDeclarativeDebugContextReference::debugId() const +{ + return m_debugId; +} + +QString QDeclarativeDebugContextReference::name() const +{ + return m_name; +} + +QList<QDeclarativeDebugObjectReference> QDeclarativeDebugContextReference::objects() const +{ + return m_objects; +} + +QList<QDeclarativeDebugContextReference> QDeclarativeDebugContextReference::contexts() const +{ + return m_contexts; +} + +QDeclarativeDebugFileReference::QDeclarativeDebugFileReference() +: m_lineNumber(-1), m_columnNumber(-1) +{ +} + +QDeclarativeDebugFileReference::QDeclarativeDebugFileReference(const QDeclarativeDebugFileReference &o) +: m_url(o.m_url), m_lineNumber(o.m_lineNumber), m_columnNumber(o.m_columnNumber) +{ +} + +QDeclarativeDebugFileReference &QDeclarativeDebugFileReference::operator=(const QDeclarativeDebugFileReference &o) +{ + m_url = o.m_url; m_lineNumber = o.m_lineNumber; m_columnNumber = o.m_columnNumber; + return *this; +} + +QUrl QDeclarativeDebugFileReference::url() const +{ + return m_url; +} + +void QDeclarativeDebugFileReference::setUrl(const QUrl &u) +{ + m_url = u; +} + +int QDeclarativeDebugFileReference::lineNumber() const +{ + return m_lineNumber; +} + +void QDeclarativeDebugFileReference::setLineNumber(int l) +{ + m_lineNumber = l; +} + +int QDeclarativeDebugFileReference::columnNumber() const +{ + return m_columnNumber; +} + +void QDeclarativeDebugFileReference::setColumnNumber(int c) +{ + m_columnNumber = c; +} + +QDeclarativeDebugPropertyReference::QDeclarativeDebugPropertyReference() +: m_objectDebugId(-1), m_hasNotifySignal(false) +{ +} + +QDeclarativeDebugPropertyReference::QDeclarativeDebugPropertyReference(const QDeclarativeDebugPropertyReference &o) +: m_objectDebugId(o.m_objectDebugId), m_name(o.m_name), m_value(o.m_value), + m_valueTypeName(o.m_valueTypeName), m_binding(o.m_binding), + m_hasNotifySignal(o.m_hasNotifySignal) +{ +} + +QDeclarativeDebugPropertyReference &QDeclarativeDebugPropertyReference::operator=(const QDeclarativeDebugPropertyReference &o) +{ + m_objectDebugId = o.m_objectDebugId; m_name = o.m_name; m_value = o.m_value; + m_valueTypeName = o.m_valueTypeName; m_binding = o.m_binding; + m_hasNotifySignal = o.m_hasNotifySignal; + return *this; +} + +int QDeclarativeDebugPropertyReference::objectDebugId() const +{ + return m_objectDebugId; +} + +QString QDeclarativeDebugPropertyReference::name() const +{ + return m_name; +} + +QString QDeclarativeDebugPropertyReference::valueTypeName() const +{ + return m_valueTypeName; +} + +QVariant QDeclarativeDebugPropertyReference::value() const +{ + return m_value; +} + +QString QDeclarativeDebugPropertyReference::binding() const +{ + return m_binding; +} + +bool QDeclarativeDebugPropertyReference::hasNotifySignal() const +{ + return m_hasNotifySignal; +} + +QT_END_NAMESPACE + diff --git a/src/declarative/debugger/qdeclarativedebug_p.h b/src/declarative/debugger/qdeclarativedebug_p.h new file mode 100644 index 0000000000..58c8234555 --- /dev/null +++ b/src/declarative/debugger/qdeclarativedebug_p.h @@ -0,0 +1,386 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QDECLARATIVEDEBUG_H +#define QDECLARATIVEDEBUG_H + +#include <QtCore/qobject.h> +#include <QtCore/qurl.h> +#include <QtCore/qvariant.h> + +#include <private/qdeclarativeglobal_p.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QDeclarativeDebugConnection; +class QDeclarativeDebugWatch; +class QDeclarativeDebugPropertyWatch; +class QDeclarativeDebugObjectExpressionWatch; +class QDeclarativeDebugEnginesQuery; +class QDeclarativeDebugRootContextQuery; +class QDeclarativeDebugObjectQuery; +class QDeclarativeDebugExpressionQuery; +class QDeclarativeDebugPropertyReference; +class QDeclarativeDebugContextReference; +class QDeclarativeDebugObjectReference; +class QDeclarativeDebugFileReference; +class QDeclarativeDebugEngineReference; +class QDeclarativeEngineDebugPrivate; +class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeEngineDebug : public QObject +{ +Q_OBJECT +public: + enum Status { NotConnected, Unavailable, Enabled }; + + explicit QDeclarativeEngineDebug(QDeclarativeDebugConnection *, QObject * = 0); + + Status status() const; + + QDeclarativeDebugPropertyWatch *addWatch(const QDeclarativeDebugPropertyReference &, + QObject *parent = 0); + QDeclarativeDebugWatch *addWatch(const QDeclarativeDebugContextReference &, const QString &, + QObject *parent = 0); + QDeclarativeDebugObjectExpressionWatch *addWatch(const QDeclarativeDebugObjectReference &, const QString &, + QObject *parent = 0); + QDeclarativeDebugWatch *addWatch(const QDeclarativeDebugObjectReference &, + QObject *parent = 0); + QDeclarativeDebugWatch *addWatch(const QDeclarativeDebugFileReference &, + QObject *parent = 0); + + void removeWatch(QDeclarativeDebugWatch *watch); + + QDeclarativeDebugEnginesQuery *queryAvailableEngines(QObject *parent = 0); + QDeclarativeDebugRootContextQuery *queryRootContexts(const QDeclarativeDebugEngineReference &, + QObject *parent = 0); + QDeclarativeDebugObjectQuery *queryObject(const QDeclarativeDebugObjectReference &, + QObject *parent = 0); + QDeclarativeDebugObjectQuery *queryObjectRecursive(const QDeclarativeDebugObjectReference &, + QObject *parent = 0); + QDeclarativeDebugExpressionQuery *queryExpressionResult(int objectDebugId, + const QString &expr, + QObject *parent = 0); + bool setBindingForObject(int objectDebugId, const QString &propertyName, + const QVariant &bindingExpression, bool isLiteralValue); + bool resetBindingForObject(int objectDebugId, const QString &propertyName); + bool setMethodBody(int objectDebugId, const QString &methodName, const QString &methodBody); + +Q_SIGNALS: + void newObjects(); + void statusChanged(Status status); + +private: + Q_DECLARE_PRIVATE(QDeclarativeEngineDebug) +}; + +class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugWatch : public QObject +{ +Q_OBJECT +public: + enum State { Waiting, Active, Inactive, Dead }; + + QDeclarativeDebugWatch(QObject *); + ~QDeclarativeDebugWatch(); + + int queryId() const; + int objectDebugId() const; + State state() const; + +Q_SIGNALS: + void stateChanged(QDeclarativeDebugWatch::State); + //void objectChanged(int, const QDeclarativeDebugObjectReference &); + //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 QDeclarativeEngineDebug; + friend class QDeclarativeEngineDebugPrivate; + void setState(State); + State m_state; + int m_queryId; + QDeclarativeEngineDebug *m_client; + int m_objectDebugId; +}; + +class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugPropertyWatch : public QDeclarativeDebugWatch +{ + Q_OBJECT +public: + QDeclarativeDebugPropertyWatch(QObject *parent); + + QString name() const; + +private: + friend class QDeclarativeEngineDebug; + QString m_name; +}; + +class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugObjectExpressionWatch : public QDeclarativeDebugWatch +{ + Q_OBJECT +public: + QDeclarativeDebugObjectExpressionWatch(QObject *parent); + + QString expression() const; + +private: + friend class QDeclarativeEngineDebug; + QString m_expr; + int m_debugId; +}; + + +class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugQuery : public QObject +{ +Q_OBJECT +public: + enum State { Waiting, Error, Completed }; + + State state() const; + bool isWaiting() const; + +// bool waitUntilCompleted(); + +Q_SIGNALS: + void stateChanged(QDeclarativeDebugQuery::State); + +protected: + QDeclarativeDebugQuery(QObject *); + +private: + friend class QDeclarativeEngineDebug; + friend class QDeclarativeEngineDebugPrivate; + void setState(State); + State m_state; +}; + +class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugFileReference +{ +public: + QDeclarativeDebugFileReference(); + QDeclarativeDebugFileReference(const QDeclarativeDebugFileReference &); + QDeclarativeDebugFileReference &operator=(const QDeclarativeDebugFileReference &); + + QUrl url() const; + void setUrl(const QUrl &); + int lineNumber() const; + void setLineNumber(int); + int columnNumber() const; + void setColumnNumber(int); + +private: + friend class QDeclarativeEngineDebugPrivate; + QUrl m_url; + int m_lineNumber; + int m_columnNumber; +}; + +class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugEngineReference +{ +public: + QDeclarativeDebugEngineReference(); + QDeclarativeDebugEngineReference(int); + QDeclarativeDebugEngineReference(const QDeclarativeDebugEngineReference &); + QDeclarativeDebugEngineReference &operator=(const QDeclarativeDebugEngineReference &); + + int debugId() const; + QString name() const; + +private: + friend class QDeclarativeEngineDebugPrivate; + int m_debugId; + QString m_name; +}; + +class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugObjectReference +{ +public: + QDeclarativeDebugObjectReference(); + QDeclarativeDebugObjectReference(int); + QDeclarativeDebugObjectReference(const QDeclarativeDebugObjectReference &); + QDeclarativeDebugObjectReference &operator=(const QDeclarativeDebugObjectReference &); + + int debugId() const; + QString className() const; + QString idString() const; + QString name() const; + + QDeclarativeDebugFileReference source() const; + int contextDebugId() const; + + QList<QDeclarativeDebugPropertyReference> properties() const; + QList<QDeclarativeDebugObjectReference> children() const; + +private: + friend class QDeclarativeEngineDebugPrivate; + int m_debugId; + QString m_class; + QString m_idString; + QString m_name; + QDeclarativeDebugFileReference m_source; + int m_contextDebugId; + QList<QDeclarativeDebugPropertyReference> m_properties; + QList<QDeclarativeDebugObjectReference> m_children; +}; + +class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugContextReference +{ +public: + QDeclarativeDebugContextReference(); + QDeclarativeDebugContextReference(const QDeclarativeDebugContextReference &); + QDeclarativeDebugContextReference &operator=(const QDeclarativeDebugContextReference &); + + int debugId() const; + QString name() const; + + QList<QDeclarativeDebugObjectReference> objects() const; + QList<QDeclarativeDebugContextReference> contexts() const; + +private: + friend class QDeclarativeEngineDebugPrivate; + int m_debugId; + QString m_name; + QList<QDeclarativeDebugObjectReference> m_objects; + QList<QDeclarativeDebugContextReference> m_contexts; +}; + +class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugPropertyReference +{ +public: + QDeclarativeDebugPropertyReference(); + QDeclarativeDebugPropertyReference(const QDeclarativeDebugPropertyReference &); + QDeclarativeDebugPropertyReference &operator=(const QDeclarativeDebugPropertyReference &); + + int objectDebugId() const; + QString name() const; + QVariant value() const; + QString valueTypeName() const; + QString binding() const; + bool hasNotifySignal() const; + +private: + friend class QDeclarativeEngineDebugPrivate; + int m_objectDebugId; + QString m_name; + QVariant m_value; + QString m_valueTypeName; + QString m_binding; + bool m_hasNotifySignal; +}; + + +class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugEnginesQuery : public QDeclarativeDebugQuery +{ +Q_OBJECT +public: + virtual ~QDeclarativeDebugEnginesQuery(); + QList<QDeclarativeDebugEngineReference> engines() const; +private: + friend class QDeclarativeEngineDebug; + friend class QDeclarativeEngineDebugPrivate; + QDeclarativeDebugEnginesQuery(QObject *); + QDeclarativeEngineDebug *m_client; + int m_queryId; + QList<QDeclarativeDebugEngineReference> m_engines; +}; + +class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugRootContextQuery : public QDeclarativeDebugQuery +{ +Q_OBJECT +public: + virtual ~QDeclarativeDebugRootContextQuery(); + QDeclarativeDebugContextReference rootContext() const; +private: + friend class QDeclarativeEngineDebug; + friend class QDeclarativeEngineDebugPrivate; + QDeclarativeDebugRootContextQuery(QObject *); + QDeclarativeEngineDebug *m_client; + int m_queryId; + QDeclarativeDebugContextReference m_context; +}; + +class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugObjectQuery : public QDeclarativeDebugQuery +{ +Q_OBJECT +public: + virtual ~QDeclarativeDebugObjectQuery(); + QDeclarativeDebugObjectReference object() const; +private: + friend class QDeclarativeEngineDebug; + friend class QDeclarativeEngineDebugPrivate; + QDeclarativeDebugObjectQuery(QObject *); + QDeclarativeEngineDebug *m_client; + int m_queryId; + QDeclarativeDebugObjectReference m_object; + +}; + +class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugExpressionQuery : public QDeclarativeDebugQuery +{ +Q_OBJECT +public: + virtual ~QDeclarativeDebugExpressionQuery(); + QVariant expression() const; + QVariant result() const; +private: + friend class QDeclarativeEngineDebug; + friend class QDeclarativeEngineDebugPrivate; + QDeclarativeDebugExpressionQuery(QObject *); + QDeclarativeEngineDebug *m_client; + int m_queryId; + QVariant m_expr; + QVariant m_result; +}; + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QDeclarativeDebugEngineReference) +Q_DECLARE_METATYPE(QDeclarativeDebugObjectReference) +Q_DECLARE_METATYPE(QDeclarativeDebugContextReference) +Q_DECLARE_METATYPE(QDeclarativeDebugPropertyReference) + +QT_END_HEADER + +#endif // QDECLARATIVEDEBUG_H diff --git a/src/declarative/debugger/qdeclarativedebugclient.cpp b/src/declarative/debugger/qdeclarativedebugclient.cpp new file mode 100644 index 0000000000..036dee1f2c --- /dev/null +++ b/src/declarative/debugger/qdeclarativedebugclient.cpp @@ -0,0 +1,292 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "private/qdeclarativedebugclient_p.h" + +#include "private/qpacketprotocol_p.h" + +#include <QtCore/qdebug.h> +#include <QtCore/qstringlist.h> + +#include <private/qobject_p.h> + +QT_BEGIN_NAMESPACE + +const int protocolVersion = 1; +const QString serverId = QLatin1String("QDeclarativeDebugServer"); +const QString clientId = QLatin1String("QDeclarativeDebugClient"); + +class QDeclarativeDebugClientPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QDeclarativeDebugClient) +public: + QDeclarativeDebugClientPrivate(); + + QString name; + QDeclarativeDebugConnection *connection; +}; + +class QDeclarativeDebugConnectionPrivate : public QObject +{ + Q_OBJECT +public: + QDeclarativeDebugConnectionPrivate(QDeclarativeDebugConnection *c); + QDeclarativeDebugConnection *q; + QPacketProtocol *protocol; + + bool gotHello; + QStringList serverPlugins; + QHash<QString, QDeclarativeDebugClient *> plugins; + + void advertisePlugins(); + +public Q_SLOTS: + void connected(); + void readyRead(); +}; + +QDeclarativeDebugConnectionPrivate::QDeclarativeDebugConnectionPrivate(QDeclarativeDebugConnection *c) +: QObject(c), q(c), protocol(0), gotHello(false) +{ + protocol = new QPacketProtocol(q, this); + QObject::connect(c, SIGNAL(connected()), this, SLOT(connected())); + QObject::connect(protocol, SIGNAL(readyRead()), this, SLOT(readyRead())); +} + +void QDeclarativeDebugConnectionPrivate::advertisePlugins() +{ + if (!q->isConnected()) + return; + + QPacket pack; + pack << serverId << 1 << plugins.keys(); + protocol->send(pack); + q->flush(); +} + +void QDeclarativeDebugConnectionPrivate::connected() +{ + QPacket pack; + pack << serverId << 0 << protocolVersion << plugins.keys(); + protocol->send(pack); + q->flush(); +} + +void QDeclarativeDebugConnectionPrivate::readyRead() +{ + if (!gotHello) { + QPacket pack = protocol->read(); + QString name; + + pack >> name; + + bool validHello = false; + if (name == clientId) { + int op = -1; + pack >> op; + if (op == 0) { + int version = -1; + pack >> version; + if (version == protocolVersion) { + pack >> serverPlugins; + validHello = true; + } + } + } + + if (!validHello) { + qWarning("QDeclarativeDebugConnection: Invalid hello message"); + QObject::disconnect(protocol, SIGNAL(readyRead()), this, SLOT(readyRead())); + return; + } + + gotHello = true; + + QHash<QString, QDeclarativeDebugClient *>::Iterator iter = plugins.begin(); + for (; iter != plugins.end(); ++iter) { + QDeclarativeDebugClient::Status newStatus = QDeclarativeDebugClient::Unavailable; + if (serverPlugins.contains(iter.key())) + newStatus = QDeclarativeDebugClient::Enabled; + iter.value()->statusChanged(newStatus); + } + } + + while (protocol->packetsAvailable()) { + QPacket pack = protocol->read(); + QString name; + pack >> name; + + if (name == clientId) { + int op = -1; + pack >> op; + + if (op == 1) { + // Service Discovery + QStringList oldServerPlugins = serverPlugins; + pack >> serverPlugins; + + QHash<QString, QDeclarativeDebugClient *>::Iterator iter = plugins.begin(); + for (; iter != plugins.end(); ++iter) { + const QString pluginName = iter.key(); + QDeclarativeDebugClient::Status newStatus = QDeclarativeDebugClient::Unavailable; + if (serverPlugins.contains(pluginName)) + newStatus = QDeclarativeDebugClient::Enabled; + + if (oldServerPlugins.contains(pluginName) + != serverPlugins.contains(pluginName)) { + iter.value()->statusChanged(newStatus); + } + } + } else { + qWarning() << "QDeclarativeDebugConnection: Unknown control message id" << op; + } + } else { + QByteArray message; + pack >> message; + + QHash<QString, QDeclarativeDebugClient *>::Iterator iter = + plugins.find(name); + if (iter == plugins.end()) { + qWarning() << "QDeclarativeDebugConnection: Message received for missing plugin" << name; + } else { + (*iter)->messageReceived(message); + } + } + } +} + +QDeclarativeDebugConnection::QDeclarativeDebugConnection(QObject *parent) +: QTcpSocket(parent), d(new QDeclarativeDebugConnectionPrivate(this)) +{ +} + +QDeclarativeDebugConnection::~QDeclarativeDebugConnection() +{ + QHash<QString, QDeclarativeDebugClient*>::iterator iter = d->plugins.begin(); + for (; iter != d->plugins.end(); ++iter) { + iter.value()->d_func()->connection = 0; + iter.value()->statusChanged(QDeclarativeDebugClient::NotConnected); + } +} + +bool QDeclarativeDebugConnection::isConnected() const +{ + return state() == ConnectedState; +} + +QDeclarativeDebugClientPrivate::QDeclarativeDebugClientPrivate() +: connection(0) +{ +} + +QDeclarativeDebugClient::QDeclarativeDebugClient(const QString &name, + QDeclarativeDebugConnection *parent) +: QObject(*(new QDeclarativeDebugClientPrivate), parent) +{ + Q_D(QDeclarativeDebugClient); + d->name = name; + d->connection = parent; + + if (!d->connection) + return; + + if (d->connection->d->plugins.contains(name)) { + qWarning() << "QDeclarativeDebugClient: Conflicting plugin name" << name; + d->connection = 0; + } else { + d->connection->d->plugins.insert(name, this); + d->connection->d->advertisePlugins(); + } +} + +QDeclarativeDebugClient::~QDeclarativeDebugClient() +{ + Q_D(const QDeclarativeDebugClient); + if (d->connection && d->connection->d) { + d->connection->d->plugins.remove(d->name); + d->connection->d->advertisePlugins(); + } +} + +QString QDeclarativeDebugClient::name() const +{ + Q_D(const QDeclarativeDebugClient); + return d->name; +} + +QDeclarativeDebugClient::Status QDeclarativeDebugClient::status() const +{ + Q_D(const QDeclarativeDebugClient); + if (!d->connection + || !d->connection->isConnected() + || !d->connection->d->gotHello) + return NotConnected; + + if (d->connection->d->serverPlugins.contains(d->name)) + return Enabled; + + return Unavailable; +} + +void QDeclarativeDebugClient::sendMessage(const QByteArray &message) +{ + Q_D(QDeclarativeDebugClient); + + if (status() != Enabled) + return; + + QPacket pack; + pack << d->name << message; + d->connection->d->protocol->send(pack); + d->connection->d->q->flush(); +} + +void QDeclarativeDebugClient::statusChanged(Status) +{ +} + +void QDeclarativeDebugClient::messageReceived(const QByteArray &) +{ +} + +QT_END_NAMESPACE + +#include <qdeclarativedebugclient.moc> diff --git a/src/declarative/debugger/qdeclarativedebugclient_p.h b/src/declarative/debugger/qdeclarativedebugclient_p.h new file mode 100644 index 0000000000..2f2665e605 --- /dev/null +++ b/src/declarative/debugger/qdeclarativedebugclient_p.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEDEBUGCLIENT_H +#define QDECLARATIVEDEBUGCLIENT_H + +#include <QtNetwork/qtcpsocket.h> + +#include <private/qdeclarativeglobal_p.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QDeclarativeDebugConnectionPrivate; +class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugConnection : public QTcpSocket +{ + Q_OBJECT + Q_DISABLE_COPY(QDeclarativeDebugConnection) +public: + QDeclarativeDebugConnection(QObject * = 0); + ~QDeclarativeDebugConnection(); + + bool isConnected() const; +private: + QDeclarativeDebugConnectionPrivate *d; + friend class QDeclarativeDebugClient; + friend class QDeclarativeDebugClientPrivate; +}; + +class QDeclarativeDebugClientPrivate; +class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugClient : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QDeclarativeDebugClient) + Q_DISABLE_COPY(QDeclarativeDebugClient) + +public: + enum Status { NotConnected, Unavailable, Enabled }; + + QDeclarativeDebugClient(const QString &, QDeclarativeDebugConnection *parent); + ~QDeclarativeDebugClient(); + + QString name() const; + + Status status() const; + + void sendMessage(const QByteArray &); + +protected: + virtual void statusChanged(Status); + virtual void messageReceived(const QByteArray &); + +private: + friend class QDeclarativeDebugConnection; + friend class QDeclarativeDebugConnectionPrivate; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QDECLARATIVEDEBUGCLIENT_H diff --git a/src/declarative/debugger/qdeclarativedebuggerstatus.cpp b/src/declarative/debugger/qdeclarativedebuggerstatus.cpp new file mode 100644 index 0000000000..dc1e6e7e13 --- /dev/null +++ b/src/declarative/debugger/qdeclarativedebuggerstatus.cpp @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "private/qdeclarativedebuggerstatus_p.h" + +QT_BEGIN_NAMESPACE + +QDeclarativeDebuggerStatus::~QDeclarativeDebuggerStatus() +{ +} + +void QDeclarativeDebuggerStatus::setSelectedState(bool) +{ +} + +QT_END_NAMESPACE diff --git a/src/declarative/debugger/qdeclarativedebuggerstatus_p.h b/src/declarative/debugger/qdeclarativedebuggerstatus_p.h new file mode 100644 index 0000000000..cb79896f26 --- /dev/null +++ b/src/declarative/debugger/qdeclarativedebuggerstatus_p.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEDEBUGGERSTATUS_P_H +#define QDECLARATIVEDEBUGGERSTATUS_P_H + +#include <QtCore/qobject.h> + +#include <private/qdeclarativeglobal_p.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebuggerStatus +{ +public: + virtual ~QDeclarativeDebuggerStatus(); + + virtual void setSelectedState(bool); +}; +Q_DECLARE_INTERFACE(QDeclarativeDebuggerStatus, "com.trolltech.qml.QDeclarativeDebuggerStatus") + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QLMDEBUGGERSTATUS_P_H diff --git a/src/declarative/debugger/qdeclarativedebughelper.cpp b/src/declarative/debugger/qdeclarativedebughelper.cpp new file mode 100644 index 0000000000..93f7423e4b --- /dev/null +++ b/src/declarative/debugger/qdeclarativedebughelper.cpp @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtScript/QScriptEngine> + +#include "private/qdeclarativedebughelper_p.h" + +#include <QtCore/QAbstractAnimation> +#include <QtScript/QScriptEngine> + +#include <private/qdeclarativeengine_p.h> +#include <private/qabstractanimation_p.h> +#include <private/qdeclarativeengine_p.h> + +QT_BEGIN_NAMESPACE + +QScriptEngine *QDeclarativeDebugHelper::getScriptEngine(QDeclarativeEngine *engine) +{ + return QDeclarativeEnginePrivate::getScriptEngine(engine); +} + +void QDeclarativeDebugHelper::setAnimationSlowDownFactor(qreal factor) +{ + QUnifiedTimer *timer = QUnifiedTimer::instance(); + timer->setSlowModeEnabled(factor != 1.0); + timer->setSlowdownFactor(factor); +} + +void QDeclarativeDebugHelper::enableDebugging() { +#ifndef QDECLARATIVE_NO_DEBUG_PROTOCOL + if (!QDeclarativeEnginePrivate::qml_debugging_enabled) { + qWarning("Qml debugging is enabled. Only use this in a safe environment!"); + } + QDeclarativeEnginePrivate::qml_debugging_enabled = true; +#endif +} + +QT_END_NAMESPACE diff --git a/src/declarative/debugger/qdeclarativedebughelper_p.h b/src/declarative/debugger/qdeclarativedebughelper_p.h new file mode 100644 index 0000000000..34b4b59c8a --- /dev/null +++ b/src/declarative/debugger/qdeclarativedebughelper_p.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEDEBUGHELPER_P_H +#define QDECLARATIVEDEBUGHELPER_P_H + +#include <QtCore/qglobal.h> + +#include <private/qdeclarativeglobal_p.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QScriptEngine; +class QDeclarativeEngine; + +// Helper methods to access private API through a stable interface +// This is used in the qmljsdebugger library of QtCreator. +class Q_DECLARATIVE_EXPORT QDeclarativeDebugHelper +{ +public: + static QScriptEngine *getScriptEngine(QDeclarativeEngine *engine); + static void setAnimationSlowDownFactor(qreal factor); + + // Enables remote debugging functionality + // Only use this for debugging in a safe environment! + static void enableDebugging(); +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QDECLARATIVEDEBUGHELPER_P_H diff --git a/src/declarative/debugger/qdeclarativedebugserver.cpp b/src/declarative/debugger/qdeclarativedebugserver.cpp new file mode 100644 index 0000000000..6f46354a49 --- /dev/null +++ b/src/declarative/debugger/qdeclarativedebugserver.cpp @@ -0,0 +1,375 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "private/qdeclarativedebugserver_p.h" +#include "private/qdeclarativedebugservice_p.h" +#include "private/qdeclarativedebugservice_p_p.h" +#include "private/qdeclarativeengine_p.h" + +#include <QtCore/QDir> +#include <QtCore/QPluginLoader> +#include <QtCore/QStringList> + +#include <private/qobject_p.h> +#include <private/qapplication_p.h> + +QT_BEGIN_NAMESPACE + +/* + QDeclarativeDebug Protocol (Version 1): + + handshake: + 1. Client sends + "QDeclarativeDebugServer" 0 version pluginNames + version: an int representing the highest protocol version the client knows + pluginNames: plugins available on client side + 2. Server sends + "QDeclarativeDebugClient" 0 version pluginNames + version: an int representing the highest protocol version the client & server know + pluginNames: plugins available on server side. plugins both in the client and server message are enabled. + client plugin advertisement + 1. Client sends + "QDeclarativeDebugServer" 1 pluginNames + server plugin advertisement + 1. Server sends + "QDeclarativeDebugClient" 1 pluginNames + plugin communication: + Everything send with a header different to "QDeclarativeDebugServer" is sent to the appropriate plugin. + */ + +const int protocolVersion = 1; + + +class QDeclarativeDebugServerPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QDeclarativeDebugServer) +public: + QDeclarativeDebugServerPrivate(); + + void advertisePlugins(); + + QDeclarativeDebugServerConnection *connection; + QHash<QString, QDeclarativeDebugService *> plugins; + QStringList clientPlugins; + bool gotHello; + + static QDeclarativeDebugServerConnection *loadConnectionPlugin(const QString &pluginName); +}; + +QDeclarativeDebugServerPrivate::QDeclarativeDebugServerPrivate() : + connection(0), + gotHello(false) +{ +} + +void QDeclarativeDebugServerPrivate::advertisePlugins() +{ + if (!gotHello) + return; + + QByteArray message; + { + QDataStream out(&message, QIODevice::WriteOnly); + out << QString(QLatin1String("QDeclarativeDebugClient")) << 1 << plugins.keys(); + } + connection->send(message); +} + +QDeclarativeDebugServerConnection *QDeclarativeDebugServerPrivate::loadConnectionPlugin( + const QString &pluginName) +{ + QStringList pluginCandidates; + const QStringList paths = QCoreApplication::libraryPaths(); + foreach (const QString &libPath, paths) { + const QDir dir(libPath + QLatin1String("/qmltooling")); + if (dir.exists()) { + QStringList plugins(dir.entryList(QDir::Files)); + foreach (const QString &pluginPath, plugins) { + if (QFileInfo(pluginPath).fileName().contains(pluginName)) + pluginCandidates << dir.absoluteFilePath(pluginPath); + } + } + } + + foreach (const QString &pluginPath, pluginCandidates) { + QPluginLoader loader(pluginPath); + if (!loader.load()) { + continue; + } + QDeclarativeDebugServerConnection *connection = 0; + if (QObject *instance = loader.instance()) + connection = qobject_cast<QDeclarativeDebugServerConnection*>(instance); + + if (connection) + return connection; + loader.unload(); + } + return 0; +} + +bool QDeclarativeDebugServer::hasDebuggingClient() const +{ + Q_D(const QDeclarativeDebugServer); + return d->connection + && d->connection->isConnected() + && d->gotHello; +} + +QDeclarativeDebugServer *QDeclarativeDebugServer::instance() +{ + static bool commandLineTested = false; + static QDeclarativeDebugServer *server = 0; + + if (!commandLineTested) { + commandLineTested = true; + + QApplicationPrivate *appD = static_cast<QApplicationPrivate*>(QObjectPrivate::get(qApp)); +#ifndef QDECLARATIVE_NO_DEBUG_PROTOCOL + // ### remove port definition when protocol is changed + int port = 0; + bool block = false; + bool ok = false; + + // format: qmljsdebugger=port:3768[,block] OR qmljsdebugger=ost[,block] + if (!appD->qmljsDebugArgumentsString().isEmpty()) { + if (!QDeclarativeEnginePrivate::qml_debugging_enabled) { + const QString message = + QString::fromAscii("QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". " + "Debugging has not been enabled.").arg( + appD->qmljsDebugArgumentsString()); + qWarning("%s", qPrintable(message)); + return 0; + } + + QString pluginName; + if (appD->qmljsDebugArgumentsString().indexOf(QLatin1String("port:")) == 0) { + int separatorIndex = appD->qmljsDebugArgumentsString().indexOf(QLatin1Char(',')); + port = appD->qmljsDebugArgumentsString().mid(5, separatorIndex - 5).toInt(&ok); + pluginName = QLatin1String("qmldbg_tcp"); + } else if (appD->qmljsDebugArgumentsString().contains("ost")) { + pluginName = QLatin1String("qmldbg_ost"); + ok = true; + } + + block = appD->qmljsDebugArgumentsString().contains(QLatin1String("block")); + + if (ok) { + server = new QDeclarativeDebugServer(); + + QDeclarativeDebugServerConnection *connection + = QDeclarativeDebugServerPrivate::loadConnectionPlugin(pluginName); + if (connection) { + server->d_func()->connection = connection; + + connection->setServer(server); + connection->setPort(port, block); + } else { + qWarning() << QString::fromAscii("QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". " + "Remote debugger plugin has not been found.").arg(appD->qmljsDebugArgumentsString()); + } + + } else { + qWarning(QString::fromAscii("QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". " + "Format is -qmljsdebugger=port:<port>[,block]").arg( + appD->qmljsDebugArgumentsString()).toAscii().constData()); + } + } +#else + if (!appD->qmljsDebugArgumentsString().isEmpty()) { + qWarning(QString::fromAscii("QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". " + "QtDeclarative is not configured for debugging.").arg( + appD->qmljsDebugArgumentsString()).toAscii().constData()); + } +#endif + } + + return server; +} + +QDeclarativeDebugServer::QDeclarativeDebugServer() +: QObject(*(new QDeclarativeDebugServerPrivate)) +{ +} + +void QDeclarativeDebugServer::receiveMessage(const QByteArray &message) +{ + Q_D(QDeclarativeDebugServer); + + QDataStream in(message); + if (!d->gotHello) { + + QString name; + int op; + in >> name >> op; + + if (name != QLatin1String("QDeclarativeDebugServer") + || op != 0) { + qWarning("QDeclarativeDebugServer: Invalid hello message"); + d->connection->disconnect(); + return; + } + + int version; + in >> version >> d->clientPlugins; + + QHash<QString, QDeclarativeDebugService*>::Iterator iter = d->plugins.begin(); + for (; iter != d->plugins.end(); ++iter) { + QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable; + if (d->clientPlugins.contains(iter.key())) + newStatus = QDeclarativeDebugService::Enabled; + iter.value()->d_func()->status = newStatus; + iter.value()->statusChanged(newStatus); + } + + QByteArray helloAnswer; + { + QDataStream out(&helloAnswer, QIODevice::WriteOnly); + out << QString(QLatin1String("QDeclarativeDebugClient")) << 0 << protocolVersion << d->plugins.keys(); + } + d->connection->send(helloAnswer); + + d->gotHello = true; + qWarning("QDeclarativeDebugServer: Connection established"); + } else { + + QString debugServer(QLatin1String("QDeclarativeDebugServer")); + + QString name; + in >> name; + + if (name == debugServer) { + int op = -1; + in >> op; + + if (op == 1) { + // Service Discovery + QStringList oldClientPlugins = d->clientPlugins; + in >> d->clientPlugins; + + QHash<QString, QDeclarativeDebugService*>::Iterator iter = d->plugins.begin(); + for (; iter != d->plugins.end(); ++iter) { + const QString pluginName = iter.key(); + QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable; + if (d->clientPlugins.contains(pluginName)) + newStatus = QDeclarativeDebugService::Enabled; + + if (oldClientPlugins.contains(pluginName) + != d->clientPlugins.contains(pluginName)) { + iter.value()->d_func()->status = newStatus; + iter.value()->statusChanged(newStatus); + } + } + } else { + qWarning("QDeclarativeDebugServer: Invalid control message %d", op); + } + } else { + QByteArray message; + in >> message; + + QHash<QString, QDeclarativeDebugService *>::Iterator iter = + d->plugins.find(name); + if (iter == d->plugins.end()) { + qWarning() << "QDeclarativeDebugServer: Message received for missing plugin" << name; + } else { + (*iter)->messageReceived(message); + } + } + } +} + +QList<QDeclarativeDebugService*> QDeclarativeDebugServer::services() const +{ + const Q_D(QDeclarativeDebugServer); + return d->plugins.values(); +} + +QStringList QDeclarativeDebugServer::serviceNames() const +{ + const Q_D(QDeclarativeDebugServer); + return d->plugins.keys(); +} + +bool QDeclarativeDebugServer::addService(QDeclarativeDebugService *service) +{ + Q_D(QDeclarativeDebugServer); + if (!service || d->plugins.contains(service->name())) + return false; + + d->plugins.insert(service->name(), service); + d->advertisePlugins(); + + QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable; + if (d->clientPlugins.contains(service->name())) + newStatus = QDeclarativeDebugService::Enabled; + service->d_func()->status = newStatus; + service->statusChanged(newStatus); + return true; +} + +bool QDeclarativeDebugServer::removeService(QDeclarativeDebugService *service) +{ + Q_D(QDeclarativeDebugServer); + if (!service || !d->plugins.contains(service->name())) + return false; + + d->plugins.remove(service->name()); + d->advertisePlugins(); + + QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::NotConnected; + service->d_func()->server = 0; + service->d_func()->status = newStatus; + service->statusChanged(newStatus); + return true; +} + +void QDeclarativeDebugServer::sendMessage(QDeclarativeDebugService *service, + const QByteArray &message) +{ + Q_D(QDeclarativeDebugServer); + QByteArray msg; + { + QDataStream out(&msg, QIODevice::WriteOnly); + out << service->name() << message; + } + d->connection->send(msg); +} + +QT_END_NAMESPACE diff --git a/src/declarative/debugger/qdeclarativedebugserver_p.h b/src/declarative/debugger/qdeclarativedebugserver_p.h new file mode 100644 index 0000000000..68ea4d8531 --- /dev/null +++ b/src/declarative/debugger/qdeclarativedebugserver_p.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEDEBUGSERVER_H +#define QDECLARATIVEDEBUGSERVER_H + +#include <private/qdeclarativeglobal_p.h> +#include <private/qdeclarativedebugserverconnection_p.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QDeclarativeDebugService; + +class QDeclarativeDebugServerPrivate; +class Q_DECLARATIVE_EXPORT QDeclarativeDebugServer : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QDeclarativeDebugServer) + Q_DISABLE_COPY(QDeclarativeDebugServer) +public: + static QDeclarativeDebugServer *instance(); + + void setConnection(QDeclarativeDebugServerConnection *connection); + + bool hasDebuggingClient() const; + + QList<QDeclarativeDebugService*> services() const; + QStringList serviceNames() const; + + bool addService(QDeclarativeDebugService *service); + bool removeService(QDeclarativeDebugService *service); + + void sendMessage(QDeclarativeDebugService *service, const QByteArray &message); + void receiveMessage(const QByteArray &message); + +private: + friend class QDeclarativeDebugService; + friend class QDeclarativeDebugServicePrivate; + QDeclarativeDebugServer(); +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QDECLARATIVEDEBUGSERVICE_H diff --git a/src/declarative/debugger/qdeclarativedebugserverconnection_p.h b/src/declarative/debugger/qdeclarativedebugserverconnection_p.h new file mode 100644 index 0000000000..0c2bdb4ef2 --- /dev/null +++ b/src/declarative/debugger/qdeclarativedebugserverconnection_p.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEDEBUGSERVERCONNECTION_H +#define QDECLARATIVEDEBUGSERVERCONNECTION_H + +#include <QtDeclarative/private/qdeclarativeglobal_p.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QDeclarativeDebugServer; +class Q_DECLARATIVE_EXPORT QDeclarativeDebugServerConnection +{ +public: + QDeclarativeDebugServerConnection() {} + virtual ~QDeclarativeDebugServerConnection() {} + + virtual void setServer(QDeclarativeDebugServer *server) = 0; + virtual void setPort(int port, bool bock) = 0; + virtual bool isConnected() const = 0; + virtual void send(const QByteArray &message) = 0; + virtual void disconnect() = 0; +}; + +Q_DECLARE_INTERFACE(QDeclarativeDebugServerConnection, "com.trolltech.Qt.QDeclarativeDebugServerConnection/1.0") + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QDECLARATIVEDEBUGSERVERCONNECTION_H diff --git a/src/declarative/debugger/qdeclarativedebugservice.cpp b/src/declarative/debugger/qdeclarativedebugservice.cpp new file mode 100644 index 0000000000..1b39f1c269 --- /dev/null +++ b/src/declarative/debugger/qdeclarativedebugservice.cpp @@ -0,0 +1,220 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "private/qdeclarativedebugservice_p.h" +#include "private/qdeclarativedebugservice_p_p.h" +#include "private/qdeclarativedebugserver_p.h" + +#include <QtCore/QDebug> +#include <QtCore/QStringList> + +QT_BEGIN_NAMESPACE + +QDeclarativeDebugServicePrivate::QDeclarativeDebugServicePrivate() +: server(0) +{ +} + +QDeclarativeDebugService::QDeclarativeDebugService(const QString &name, QObject *parent) +: QObject(*(new QDeclarativeDebugServicePrivate), parent) +{ + Q_D(QDeclarativeDebugService); + d->name = name; + d->server = QDeclarativeDebugServer::instance(); + d->status = QDeclarativeDebugService::NotConnected; + + if (!d->server) + return; + + if (d->server->serviceNames().contains(name)) { + qWarning() << "QDeclarativeDebugService: Conflicting plugin name" << name; + d->server = 0; + } else { + d->server->addService(this); + } +} + +QDeclarativeDebugService::~QDeclarativeDebugService() +{ + Q_D(const QDeclarativeDebugService); + if (d->server) { + d->server->removeService(this); + } +} + +QString QDeclarativeDebugService::name() const +{ + Q_D(const QDeclarativeDebugService); + return d->name; +} + +QDeclarativeDebugService::Status QDeclarativeDebugService::status() const +{ + Q_D(const QDeclarativeDebugService); + return d->status; +} + +namespace { + + struct ObjectReference + { + QPointer<QObject> object; + int id; + }; + + struct ObjectReferenceHash + { + ObjectReferenceHash() : nextId(0) {} + + QHash<QObject *, ObjectReference> objects; + QHash<int, QObject *> ids; + + int nextId; + }; + +} +Q_GLOBAL_STATIC(ObjectReferenceHash, objectReferenceHash); + + +/*! + Returns a unique id for \a object. Calling this method multiple times + for the same object will return the same id. +*/ +int QDeclarativeDebugService::idForObject(QObject *object) +{ + if (!object) + return -1; + + ObjectReferenceHash *hash = objectReferenceHash(); + QHash<QObject *, ObjectReference>::Iterator iter = + hash->objects.find(object); + + if (iter == hash->objects.end()) { + int id = hash->nextId++; + + hash->ids.insert(id, object); + iter = hash->objects.insert(object, ObjectReference()); + iter->object = object; + iter->id = id; + } else if (iter->object != object) { + int id = hash->nextId++; + + hash->ids.remove(iter->id); + + hash->ids.insert(id, object); + iter->object = object; + iter->id = id; + } + return iter->id; +} + +/*! + Returns the object for unique \a id. If the object has not previously been + assigned an id, through idForObject(), then 0 is returned. If the object + has been destroyed, 0 is returned. +*/ +QObject *QDeclarativeDebugService::objectForId(int id) +{ + ObjectReferenceHash *hash = objectReferenceHash(); + + QHash<int, QObject *>::Iterator iter = hash->ids.find(id); + if (iter == hash->ids.end()) + return 0; + + + QHash<QObject *, ObjectReference>::Iterator objIter = + hash->objects.find(*iter); + Q_ASSERT(objIter != hash->objects.end()); + + if (objIter->object == 0) { + hash->ids.erase(iter); + hash->objects.erase(objIter); + return 0; + } else { + return *iter; + } +} + +bool QDeclarativeDebugService::isDebuggingEnabled() +{ + return QDeclarativeDebugServer::instance() != 0; +} + +bool QDeclarativeDebugService::hasDebuggingClient() +{ + return QDeclarativeDebugServer::instance() != 0 + && QDeclarativeDebugServer::instance()->hasDebuggingClient(); +} + +QString QDeclarativeDebugService::objectToString(QObject *obj) +{ + if(!obj) + return QLatin1String("NULL"); + + QString objectName = obj->objectName(); + if(objectName.isEmpty()) + objectName = QLatin1String("<unnamed>"); + + QString rv = QString::fromUtf8(obj->metaObject()->className()) + + QLatin1String(": ") + objectName; + + return rv; +} + +void QDeclarativeDebugService::sendMessage(const QByteArray &message) +{ + Q_D(QDeclarativeDebugService); + + if (status() != Enabled) + return; + + d->server->sendMessage(this, message); +} + +void QDeclarativeDebugService::statusChanged(Status) +{ +} + +void QDeclarativeDebugService::messageReceived(const QByteArray &) +{ +} + +QT_END_NAMESPACE diff --git a/src/declarative/debugger/qdeclarativedebugservice_p.h b/src/declarative/debugger/qdeclarativedebugservice_p.h new file mode 100644 index 0000000000..5e30350abf --- /dev/null +++ b/src/declarative/debugger/qdeclarativedebugservice_p.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEDEBUGSERVICE_H +#define QDECLARATIVEDEBUGSERVICE_H + +#include <QtCore/qobject.h> + +#include <private/qdeclarativeglobal_p.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QDeclarativeDebugServicePrivate; +class Q_DECLARATIVE_EXPORT QDeclarativeDebugService : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QDeclarativeDebugService) + Q_DISABLE_COPY(QDeclarativeDebugService) + +public: + explicit QDeclarativeDebugService(const QString &, QObject *parent = 0); + ~QDeclarativeDebugService(); + + QString name() const; + + enum Status { NotConnected, Unavailable, Enabled }; + Status status() const; + + void sendMessage(const QByteArray &); + + static int idForObject(QObject *); + static QObject *objectForId(int); + + static QString objectToString(QObject *obj); + + static bool isDebuggingEnabled(); + static bool hasDebuggingClient(); + +protected: + virtual void statusChanged(Status); + virtual void messageReceived(const QByteArray &); + +private: + friend class QDeclarativeDebugServer; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QDECLARATIVEDEBUGSERVICE_H + diff --git a/src/declarative/debugger/qdeclarativedebugservice_p_p.h b/src/declarative/debugger/qdeclarativedebugservice_p_p.h new file mode 100644 index 0000000000..d0423f79f8 --- /dev/null +++ b/src/declarative/debugger/qdeclarativedebugservice_p_p.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEDEBUGSERVICE_P_H +#define QDECLARATIVEDEBUGSERVICE_P_H + +#include <QtCore/qglobal.h> +#include <private/qobject_p.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QDeclarativeDebugServer; + +class QDeclarativeDebugServicePrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QDeclarativeDebugService) +public: + QDeclarativeDebugServicePrivate(); + + QString name; + QDeclarativeDebugServer *server; + QDeclarativeDebugService::Status status; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QDECLARATIVEDEBUGSERVICE_P_H diff --git a/src/declarative/debugger/qdeclarativedebugtrace.cpp b/src/declarative/debugger/qdeclarativedebugtrace.cpp new file mode 100644 index 0000000000..6f28736f52 --- /dev/null +++ b/src/declarative/debugger/qdeclarativedebugtrace.cpp @@ -0,0 +1,218 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativedebugtrace_p.h" + +#include <QtCore/qdatastream.h> +#include <QtCore/qurl.h> +#include <QtCore/qtimer.h> + +Q_GLOBAL_STATIC(QDeclarativeDebugTrace, traceInstance); + +// convert to a QByteArray that can be sent to the debug client +// use of QDataStream can skew results if m_deferredSend == false +// (see tst_qperformancetimer::trace() benchmark) +QByteArray QDeclarativeDebugData::toByteArray() const +{ + QByteArray data; + //### using QDataStream is relatively expensive + QDataStream ds(&data, QIODevice::WriteOnly); + ds << time << messageType << detailType; + if (messageType == (int)QDeclarativeDebugTrace::RangeData) + ds << detailData; + if (messageType == (int)QDeclarativeDebugTrace::RangeLocation) + ds << detailData << line; + return data; +} + +QDeclarativeDebugTrace::QDeclarativeDebugTrace() +: QDeclarativeDebugService(QLatin1String("CanvasFrameRate")), + m_enabled(false), m_deferredSend(true) +{ + m_timer.start(); +} + +void QDeclarativeDebugTrace::addEvent(EventType t) +{ + if (QDeclarativeDebugService::isDebuggingEnabled()) + traceInstance()->addEventImpl(t); +} + +void QDeclarativeDebugTrace::startRange(RangeType t) +{ + if (QDeclarativeDebugService::isDebuggingEnabled()) + traceInstance()->startRangeImpl(t); +} + +void QDeclarativeDebugTrace::rangeData(RangeType t, const QString &data) +{ + if (QDeclarativeDebugService::isDebuggingEnabled()) + traceInstance()->rangeDataImpl(t, data); +} + +void QDeclarativeDebugTrace::rangeData(RangeType t, const QUrl &data) +{ + if (QDeclarativeDebugService::isDebuggingEnabled()) + traceInstance()->rangeDataImpl(t, data); +} + +void QDeclarativeDebugTrace::rangeLocation(RangeType t, const QString &fileName, int line) +{ + if (QDeclarativeDebugService::isDebuggingEnabled()) + traceInstance()->rangeLocationImpl(t, fileName, line); +} + +void QDeclarativeDebugTrace::rangeLocation(RangeType t, const QUrl &fileName, int line) +{ + if (QDeclarativeDebugService::isDebuggingEnabled()) + traceInstance()->rangeLocationImpl(t, fileName, line); +} + +void QDeclarativeDebugTrace::endRange(RangeType t) +{ + if (QDeclarativeDebugService::isDebuggingEnabled()) + traceInstance()->endRangeImpl(t); +} + +void QDeclarativeDebugTrace::addEventImpl(EventType event) +{ + if (status() != Enabled || !m_enabled) + return; + + QDeclarativeDebugData ed = {m_timer.elapsed(), (int)Event, (int)event, QString(), -1}; + processMessage(ed); +} + +void QDeclarativeDebugTrace::startRangeImpl(RangeType range) +{ + if (status() != Enabled || !m_enabled) + return; + + QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeStart, (int)range, QString(), -1}; + processMessage(rd); +} + +void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QString &rData) +{ + if (status() != Enabled || !m_enabled) + return; + + QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeData, (int)range, rData, -1}; + processMessage(rd); +} + +void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QUrl &rData) +{ + if (status() != Enabled || !m_enabled) + return; + + QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeData, (int)range, rData.toString(QUrl::FormattingOption(0x100)), -1}; + processMessage(rd); +} + +void QDeclarativeDebugTrace::rangeLocationImpl(RangeType range, const QString &fileName, int line) +{ + if (status() != Enabled || !m_enabled) + return; + + QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeLocation, (int)range, fileName, line}; + processMessage(rd); +} + +void QDeclarativeDebugTrace::rangeLocationImpl(RangeType range, const QUrl &fileName, int line) +{ + if (status() != Enabled || !m_enabled) + return; + + QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeLocation, (int)range, fileName.toString(QUrl::FormattingOption(0x100)), line}; + processMessage(rd); +} + +void QDeclarativeDebugTrace::endRangeImpl(RangeType range) +{ + if (status() != Enabled || !m_enabled) + return; + + QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeEnd, (int)range, QString(), -1}; + processMessage(rd); +} + +/* + Either send the message directly, or queue up + a list of messages to send later (via sendMessages) +*/ +void QDeclarativeDebugTrace::processMessage(const QDeclarativeDebugData &message) +{ + if (m_deferredSend) + m_data.append(message); + else + sendMessage(message.toByteArray()); +} + +/* + Send the messages queued up by processMessage +*/ +void QDeclarativeDebugTrace::sendMessages() +{ + if (m_deferredSend) { + //### this is a suboptimal way to send batched messages + for (int i = 0; i < m_data.count(); ++i) + sendMessage(m_data.at(i).toByteArray()); + m_data.clear(); + + //indicate completion + QByteArray data; + QDataStream ds(&data, QIODevice::WriteOnly); + ds << (qint64)-1 << (int)Complete; + sendMessage(data); + } +} + +void QDeclarativeDebugTrace::messageReceived(const QByteArray &message) +{ + QByteArray rwData = message; + QDataStream stream(&rwData, QIODevice::ReadOnly); + + stream >> m_enabled; + + if (!m_enabled) + sendMessages(); +} diff --git a/src/declarative/debugger/qdeclarativedebugtrace_p.h b/src/declarative/debugger/qdeclarativedebugtrace_p.h new file mode 100644 index 0000000000..ae0653ee71 --- /dev/null +++ b/src/declarative/debugger/qdeclarativedebugtrace_p.h @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEDEBUGTRACE_P_H +#define QDECLARATIVEDEBUGTRACE_P_H + +#include <private/qdeclarativedebugservice_p.h> +#include <private/qperformancetimer_p.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +struct QDeclarativeDebugData +{ + qint64 time; + int messageType; + int detailType; + + //### + QString detailData; //used by RangeData and RangeLocation + int line; //used by RangeLocation + + QByteArray toByteArray() const; +}; + +class QUrl; +class Q_AUTOTEST_EXPORT QDeclarativeDebugTrace : public QDeclarativeDebugService +{ +public: + enum Message { + Event, + RangeStart, + RangeData, + RangeLocation, + RangeEnd, + Complete, + + MaximumMessage + }; + + enum EventType { + FramePaint, + Mouse, + Key, + + MaximumEventType + }; + + enum RangeType { + Painting, + Compiling, + Creating, + Binding, //running a binding + HandlingSignal, //running a signal handler + + MaximumRangeType + }; + + static void addEvent(EventType); + + static void startRange(RangeType); + static void rangeData(RangeType, const QString &); + static void rangeData(RangeType, const QUrl &); + static void rangeLocation(RangeType, const QString &, int); + static void rangeLocation(RangeType, const QUrl &, int); + static void endRange(RangeType); + + QDeclarativeDebugTrace(); +protected: + virtual void messageReceived(const QByteArray &); +private: + void addEventImpl(EventType); + void startRangeImpl(RangeType); + void rangeDataImpl(RangeType, const QString &); + void rangeDataImpl(RangeType, const QUrl &); + void rangeLocationImpl(RangeType, const QString &, int); + void rangeLocationImpl(RangeType, const QUrl &, int); + void endRangeImpl(RangeType); + void processMessage(const QDeclarativeDebugData &); + void sendMessages(); + QPerformanceTimer m_timer; + bool m_enabled; + bool m_deferredSend; + QList<QDeclarativeDebugData> m_data; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QDECLARATIVEDEBUGTRACE_P_H + diff --git a/src/declarative/debugger/qpacketprotocol.cpp b/src/declarative/debugger/qpacketprotocol.cpp new file mode 100644 index 0000000000..15a14cf9f4 --- /dev/null +++ b/src/declarative/debugger/qpacketprotocol.cpp @@ -0,0 +1,507 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "private/qpacketprotocol_p.h" + +#include <QBuffer> + +QT_BEGIN_NAMESPACE + +#define MAX_PACKET_SIZE 0x7FFFFFFF + +/*! + \class QPacketProtocol + \internal + + \brief The QPacketProtocol class encapsulates communicating discrete packets + across fragmented IO channels, such as TCP sockets. + + QPacketProtocol makes it simple to send arbitrary sized data "packets" across + fragmented transports such as TCP and UDP. + + As transmission boundaries are not respected, sending packets over protocols + like TCP frequently involves "stitching" them back together at the receiver. + QPacketProtocol makes this easier by performing this task for you. Packet + data sent using QPacketProtocol is prepended with a 4-byte size header + allowing the receiving QPacketProtocol to buffer the packet internally until + it has all been received. QPacketProtocol does not perform any sanity + checking on the size or on the data, so this class should only be used in + prototyping or trusted situations where DOS attacks are unlikely. + + QPacketProtocol does not perform any communications itself. Instead it can + operate on any QIODevice that supports the QIODevice::readyRead() signal. A + logical "packet" is encapsulated by the companion QPacket class. The + following example shows two ways to send data using QPacketProtocol. The + transmitted data is equivalent in both. + + \code + QTcpSocket socket; + // ... connect socket ... + + QPacketProtocol protocol(&socket); + + // Send packet the quick way + protocol.send() << "Hello world" << 123; + + // Send packet the longer way + QPacket packet; + packet << "Hello world" << 123; + protocol.send(packet); + \endcode + + Likewise, the following shows how to read data from QPacketProtocol, assuming + that the QPacketProtocol::readyRead() signal has been emitted. + + \code + // ... QPacketProtocol::readyRead() is emitted ... + + int a; + QByteArray b; + + // Receive packet the quick way + protocol.read() >> a >> b; + + // Receive packet the longer way + QPacket packet = protocol.read(); + p >> a >> b; + \endcode + + \ingroup io + \sa QPacket +*/ + +class QPacketProtocolPrivate : public QObject +{ +Q_OBJECT +public: + QPacketProtocolPrivate(QPacketProtocol * parent, QIODevice * _dev) + : QObject(parent), inProgressSize(-1), maxPacketSize(MAX_PACKET_SIZE), + dev(_dev) + { + Q_ASSERT(4 == sizeof(qint32)); + + QObject::connect(this, SIGNAL(readyRead()), + parent, SIGNAL(readyRead())); + QObject::connect(this, SIGNAL(packetWritten()), + parent, SIGNAL(packetWritten())); + QObject::connect(this, SIGNAL(invalidPacket()), + parent, SIGNAL(invalidPacket())); + QObject::connect(dev, SIGNAL(readyRead()), + this, SLOT(readyToRead()), Qt::QueuedConnection); + QObject::connect(dev, SIGNAL(aboutToClose()), + this, SLOT(aboutToClose())); + QObject::connect(dev, SIGNAL(bytesWritten(qint64)), + this, SLOT(bytesWritten(qint64))); + } + +Q_SIGNALS: + void readyRead(); + void packetWritten(); + void invalidPacket(); + +public Q_SLOTS: + void aboutToClose() + { + inProgress.clear(); + sendingPackets.clear(); + inProgressSize = -1; + } + + void bytesWritten(qint64 bytes) + { + Q_ASSERT(!sendingPackets.isEmpty()); + + while(bytes) { + if(sendingPackets.at(0) > bytes) { + sendingPackets[0] -= bytes; + bytes = 0; + } else { + bytes -= sendingPackets.at(0); + sendingPackets.removeFirst(); + emit packetWritten(); + } + } + } + + void readyToRead() + { + if(-1 == inProgressSize) { + // We need a size header of sizeof(qint32) + if(sizeof(qint32) > (uint)dev->bytesAvailable()) + return; + + // Read size header + int read = dev->read((char *)&inProgressSize, sizeof(qint32)); + Q_ASSERT(read == sizeof(qint32)); + Q_UNUSED(read); + + // Check sizing constraints + if(inProgressSize > maxPacketSize) { + QObject::disconnect(dev, SIGNAL(readyRead()), + this, SLOT(readyToRead())); + QObject::disconnect(dev, SIGNAL(aboutToClose()), + this, SLOT(aboutToClose())); + QObject::disconnect(dev, SIGNAL(bytesWritten(qint64)), + this, SLOT(bytesWritten(qint64))); + dev = 0; + emit invalidPacket(); + return; + } + + inProgressSize -= sizeof(qint32); + + // Need to get trailing data + readyToRead(); + } else { + inProgress.append(dev->read(inProgressSize - inProgress.size())); + + if(inProgressSize == inProgress.size()) { + // Packet has arrived! + packets.append(inProgress); + inProgressSize = -1; + inProgress.clear(); + + emit readyRead(); + + // Need to get trailing data + readyToRead(); + } + } + } + +public: + QList<qint64> sendingPackets; + QList<QByteArray> packets; + QByteArray inProgress; + qint32 inProgressSize; + qint32 maxPacketSize; + QIODevice * dev; +}; + +/*! + Construct a QPacketProtocol instance that works on \a dev with the + specified \a parent. + */ +QPacketProtocol::QPacketProtocol(QIODevice * dev, QObject * parent) +: QObject(parent), d(new QPacketProtocolPrivate(this, dev)) +{ + Q_ASSERT(dev); +} + +/*! + Destroys the QPacketProtocol instance. + */ +QPacketProtocol::~QPacketProtocol() +{ +} + +/*! + Returns the maximum packet size allowed. By default this is + 2,147,483,647 bytes. + + If a packet claiming to be larger than the maximum packet size is received, + the QPacketProtocol::invalidPacket() signal is emitted. + + \sa QPacketProtocol::setMaximumPacketSize() + */ +qint32 QPacketProtocol::maximumPacketSize() const +{ + return d->maxPacketSize; +} + +/*! + Sets the maximum allowable packet size to \a max. + + \sa QPacketProtocol::maximumPacketSize() + */ +qint32 QPacketProtocol::setMaximumPacketSize(qint32 max) +{ + if(max > (signed)sizeof(qint32)) + d->maxPacketSize = max; + return d->maxPacketSize; +} + +/*! + Returns a streamable object that is transmitted on destruction. For example + + \code + protocol.send() << "Hello world" << 123; + \endcode + + will send a packet containing "Hello world" and 123. To construct more + complex packets, explicitly construct a QPacket instance. + */ +QPacketAutoSend QPacketProtocol::send() +{ + return QPacketAutoSend(this); +} + +/*! + \fn void QPacketProtocol::send(const QPacket & packet) + + Transmit the \a packet. + */ +void QPacketProtocol::send(const QPacket & p) +{ + if(p.b.isEmpty()) + return; // We don't send empty packets + + qint64 sendSize = p.b.size() + sizeof(qint32); + + d->sendingPackets.append(sendSize); + qint32 sendSize32 = sendSize; + qint64 writeBytes = d->dev->write((char *)&sendSize32, sizeof(qint32)); + Q_ASSERT(writeBytes == sizeof(qint32)); + writeBytes = d->dev->write(p.b); + Q_ASSERT(writeBytes == p.b.size()); +} + +/*! + Returns the number of received packets yet to be read. + */ +qint64 QPacketProtocol::packetsAvailable() const +{ + return d->packets.count(); +} + +/*! + Discard any unread packets. + */ +void QPacketProtocol::clear() +{ + d->packets.clear(); +} + +/*! + Return the next unread packet, or an invalid QPacket instance if no packets + are available. This method does NOT block. + */ +QPacket QPacketProtocol::read() +{ + if(0 == d->packets.count()) + return QPacket(); + + QPacket rv(d->packets.at(0)); + d->packets.removeFirst(); + return rv; +} + +/*! + Return the QIODevice passed to the QPacketProtocol constructor. +*/ +QIODevice * QPacketProtocol::device() +{ + return d->dev; +} + +/*! + \fn void QPacketProtocol::readyRead() + + Emitted whenever a new packet is received. Applications may use + QPacketProtocol::read() to retrieve this packet. + */ + +/*! + \fn void QPacketProtocol::invalidPacket() + + A packet larger than the maximum allowable packet size was received. The + packet will be discarded and, as it indicates corruption in the protocol, no + further packets will be received. + */ + +/*! + \fn void QPacketProtocol::packetWritten() + + Emitted each time a packet is completing written to the device. This signal + may be used for communications flow control. + */ + +/*! + \class QPacket + \internal + + \brief The QPacket class encapsulates an unfragmentable packet of data to be + transmitted by QPacketProtocol. + + The QPacket class works together with QPacketProtocol to make it simple to + send arbitrary sized data "packets" across fragmented transports such as TCP + and UDP. + + QPacket provides a QDataStream interface to an unfragmentable packet. + Applications should construct a QPacket, propagate it with data and then + transmit it over a QPacketProtocol instance. For example: + \code + QPacketProtocol protocol(...); + + QPacket myPacket; + myPacket << "Hello world!" << 123; + protocol.send(myPacket); + \endcode + + As long as both ends of the connection are using the QPacketProtocol class, + the data within this packet will be delivered unfragmented at the other end, + ready for extraction. + + \code + QByteArray greeting; + int count; + + QPacket myPacket = protocol.read(); + + myPacket >> greeting >> count; + \endcode + + Only packets returned from QPacketProtocol::read() may be read from. QPacket + instances constructed by directly by applications are for transmission only + and are considered "write only". Attempting to read data from them will + result in undefined behavior. + + \ingroup io + \sa QPacketProtocol + */ + +/*! + Constructs an empty write-only packet. + */ +QPacket::QPacket() +: QDataStream(), buf(0) +{ + buf = new QBuffer(&b); + buf->open(QIODevice::WriteOnly); + setDevice(buf); + setVersion(QDataStream::Qt_4_7); +} + +/*! + Destroys the QPacket instance. + */ +QPacket::~QPacket() +{ + if(buf) { + delete buf; + buf = 0; + } +} + +/*! + Creates a copy of \a other. The initial stream positions are shared, but the + two packets are otherwise independent. + */ +QPacket::QPacket(const QPacket & other) +: QDataStream(), b(other.b), buf(0) +{ + buf = new QBuffer(&b); + buf->open(other.buf->openMode()); + setDevice(buf); +} + +/*! + \internal + */ +QPacket::QPacket(const QByteArray & ba) +: QDataStream(), b(ba), buf(0) +{ + buf = new QBuffer(&b); + buf->open(QIODevice::ReadOnly); + setDevice(buf); +} + +/*! + Returns true if this packet is empty - that is, contains no data. + */ +bool QPacket::isEmpty() const +{ + return b.isEmpty(); +} + +/*! + Returns raw packet data. + */ +QByteArray QPacket::data() const +{ + return b; +} + +/*! + Clears data in the packet. This is useful for reusing one writable packet. + For example + \code + QPacketProtocol protocol(...); + + QPacket packet; + + packet << "Hello world!" << 123; + protocol.send(packet); + + packet.clear(); + packet << "Goodbyte world!" << 789; + protocol.send(packet); + \endcode + */ +void QPacket::clear() +{ + QBuffer::OpenMode oldMode = buf->openMode(); + buf->close(); + b.clear(); + buf->setBuffer(&b); // reset QBuffer internals with new size of b. + buf->open(oldMode); +} + +/*! + \class QPacketAutoSend + \internal + + \internal + */ +QPacketAutoSend::QPacketAutoSend(QPacketProtocol * _p) +: QPacket(), p(_p) +{ +} + +QPacketAutoSend::~QPacketAutoSend() +{ + if(!b.isEmpty()) + p->send(*this); +} + +QT_END_NAMESPACE + +#include <qpacketprotocol.moc> diff --git a/src/declarative/debugger/qpacketprotocol_p.h b/src/declarative/debugger/qpacketprotocol_p.h new file mode 100644 index 0000000000..accb8efa67 --- /dev/null +++ b/src/declarative/debugger/qpacketprotocol_p.h @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPACKETPROTOCOL_H +#define QPACKETPROTOCOL_H + +#include <QtCore/qobject.h> +#include <QtCore/qdatastream.h> + +#include <private/qdeclarativeglobal_p.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QIODevice; +class QBuffer; +class QPacket; +class QPacketAutoSend; +class QPacketProtocolPrivate; + +class Q_DECLARATIVE_EXPORT QPacketProtocol : public QObject +{ +Q_OBJECT +public: + explicit QPacketProtocol(QIODevice * dev, QObject * parent = 0); + virtual ~QPacketProtocol(); + + qint32 maximumPacketSize() const; + qint32 setMaximumPacketSize(qint32); + + QPacketAutoSend send(); + void send(const QPacket &); + + qint64 packetsAvailable() const; + QPacket read(); + + void clear(); + + QIODevice * device(); + +Q_SIGNALS: + void readyRead(); + void invalidPacket(); + void packetWritten(); + +private: + QPacketProtocolPrivate * d; +}; + + +class Q_DECLARATIVE_EXPORT QPacket : public QDataStream +{ +public: + QPacket(); + QPacket(const QPacket &); + virtual ~QPacket(); + + void clear(); + bool isEmpty() const; + QByteArray data() const; + +protected: + friend class QPacketProtocol; + QPacket(const QByteArray & ba); + QByteArray b; + QBuffer * buf; +}; + +class Q_DECLARATIVE_PRIVATE_EXPORT QPacketAutoSend : public QPacket +{ +public: + virtual ~QPacketAutoSend(); + +private: + friend class QPacketProtocol; + QPacketAutoSend(QPacketProtocol *); + QPacketProtocol * p; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif |