diff options
author | Warwick Allison <warwick.allison@nokia.com> | 2009-11-09 03:14:38 (GMT) |
---|---|---|
committer | Warwick Allison <warwick.allison@nokia.com> | 2009-11-09 03:14:38 (GMT) |
commit | 82e142d6b52153024bd05fa3a7853be7c64bb3bb (patch) | |
tree | 06d69a8612742dd6ab8d519baefc3f6355329fde | |
parent | 65ebb736e7d1f134b6d3dc5c620de43b9880d544 (diff) | |
parent | 5e5ee991ad4261516cf099c9b237f8c72c9d49cc (diff) | |
download | Qt-82e142d6b52153024bd05fa3a7853be7c64bb3bb.zip Qt-82e142d6b52153024bd05fa3a7853be7c64bb3bb.tar.gz Qt-82e142d6b52153024bd05fa3a7853be7c64bb3bb.tar.bz2 |
Merge branch 'kinetic-declarativeui' of git@scm.dev.nokia.troll.no:qt/kinetic into kinetic-declarativeui
-rw-r--r-- | src/declarative/debugger/qmldebug.cpp | 12 | ||||
-rw-r--r-- | src/declarative/debugger/qmldebug_p.h | 2 | ||||
-rw-r--r-- | src/declarative/qml/qmlenginedebug.cpp | 15 | ||||
-rw-r--r-- | tests/auto/declarative/declarative.pro | 1 | ||||
-rw-r--r-- | tests/auto/declarative/qmldebug/qmldebug.pro | 5 | ||||
-rw-r--r-- | tests/auto/declarative/qmldebug/tst_qmldebug.cpp | 594 | ||||
-rw-r--r-- | tools/qmldebugger/creatorplugin/creatorplugin.pro | 1 | ||||
-rw-r--r-- | tools/qmldebugger/creatorplugin/qmlinspectormode.cpp | 24 | ||||
-rw-r--r-- | tools/qmldebugger/creatorplugin/qmlinspectormode.h | 2 | ||||
-rw-r--r-- | tools/qmldebugger/standalone/canvasframerate.cpp | 329 | ||||
-rw-r--r-- | tools/qmldebugger/standalone/canvasframerate.h | 13 | ||||
-rw-r--r-- | tools/qmldebugger/standalone/main.cpp | 3 | ||||
-rw-r--r-- | tools/qmldebugger/standalone/objecttree.cpp | 20 | ||||
-rw-r--r-- | tools/qmldebugger/standalone/objecttree.h | 2 | ||||
-rw-r--r-- | tools/qmldebugger/standalone/qmldebugger.cpp | 29 | ||||
-rw-r--r-- | tools/qmldebugger/standalone/qmldebugger.h | 3 |
16 files changed, 956 insertions, 99 deletions
diff --git a/src/declarative/debugger/qmldebug.cpp b/src/declarative/debugger/qmldebug.cpp index b06a250..1403ffa 100644 --- a/src/declarative/debugger/qmldebug.cpp +++ b/src/declarative/debugger/qmldebug.cpp @@ -69,6 +69,7 @@ public: void decode(QDataStream &, QmlDebugContextReference &); void decode(QDataStream &, QmlDebugObjectReference &, bool simple); + static void remove(QmlEngineDebug *, QmlDebugEnginesQuery *); static void remove(QmlEngineDebug *, QmlDebugRootContextQuery *); static void remove(QmlEngineDebug *, QmlDebugObjectQuery *); @@ -133,6 +134,7 @@ void QmlEngineDebugPrivate::remove(QmlEngineDebug *c, QmlDebugExpressionQuery *q p->expressionQuery.remove(q->m_queryId); } + Q_DECLARE_METATYPE(QmlDebugObjectReference); void QmlEngineDebugPrivate::decode(QDataStream &ds, QmlDebugObjectReference &o, bool simple) @@ -345,6 +347,7 @@ QmlDebugPropertyWatch *QmlEngineDebug::addWatch(const QmlDebugPropertyReference if (d->client->isConnected()) { 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); @@ -373,6 +376,7 @@ QmlDebugObjectExpressionWatch *QmlEngineDebug::addWatch(const QmlDebugObjectRefe if (d->client->isConnected()) { 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); @@ -395,6 +399,7 @@ QmlDebugWatch *QmlEngineDebug::addWatch(const QmlDebugObjectReference &object, Q if (d->client->isConnected()) { int queryId = d->getId(); watch->m_queryId = queryId; + watch->m_client = this; watch->m_objectDebugId = object.debugId(); d->watched.insert(queryId, watch); @@ -544,8 +549,13 @@ QmlDebugExpressionQuery *QmlEngineDebug::queryExpressionResult(int objectDebugId } QmlDebugWatch::QmlDebugWatch(QObject *parent) -: QObject(parent), m_state(Waiting), m_queryId(-1), m_objectDebugId(-1) +: QObject(parent), m_state(Waiting), m_queryId(-1), m_client(0), m_objectDebugId(-1) +{ +} + +QmlDebugWatch::~QmlDebugWatch() { + m_client->removeWatch(this); } int QmlDebugWatch::queryId() const diff --git a/src/declarative/debugger/qmldebug_p.h b/src/declarative/debugger/qmldebug_p.h index d7e4f5a..4bc54e8 100644 --- a/src/declarative/debugger/qmldebug_p.h +++ b/src/declarative/debugger/qmldebug_p.h @@ -106,6 +106,7 @@ public: enum State { Waiting, Active, Inactive, Dead }; QmlDebugWatch(QObject *); + ~QmlDebugWatch(); int queryId() const; int objectDebugId() const; @@ -125,6 +126,7 @@ private: void setState(State); State m_state; int m_queryId; + QmlEngineDebug *m_client; int m_objectDebugId; }; diff --git a/src/declarative/qml/qmlenginedebug.cpp b/src/declarative/qml/qmlenginedebug.cpp index 2d8acf7..20d6fc1 100644 --- a/src/declarative/qml/qmlenginedebug.cpp +++ b/src/declarative/qml/qmlenginedebug.cpp @@ -99,6 +99,7 @@ QmlEngineDebugServer::QmlObjectProperty QmlEngineDebugServer::propertyData(QObject *obj, int propIdx) { QmlObjectProperty rv; +; QMetaProperty prop = obj->metaObject()->property(propIdx); @@ -165,7 +166,7 @@ void QmlEngineDebugServer::buildObjectDump(QDataStream &message, int childrenCount = children.count(); for (int ii = 0; ii < children.count(); ++ii) { - if (QmlBoundSignal::cast(children[ii])) + if (qobject_cast<QmlContext*>(children[ii]) || QmlBoundSignal::cast(children[ii])) --childrenCount; } @@ -175,6 +176,8 @@ void QmlEngineDebugServer::buildObjectDump(QDataStream &message, for (int ii = 0; ii < children.count(); ++ii) { QObject *child = children.at(ii); + if (qobject_cast<QmlContext*>(child)) + continue; QmlBoundSignal *signal = QmlBoundSignal::cast(child); if (signal) { QmlObjectProperty prop; @@ -271,10 +274,18 @@ QmlEngineDebugServer::objectData(QObject *object) } rv.objectName = object->objectName(); - rv.objectType = QString::fromUtf8(object->metaObject()->className()); rv.objectId = QmlDebugService::idForObject(object); rv.contextId = QmlDebugService::idForObject(qmlContext(object)); + QmlType *type = QmlMetaType::qmlType(object->metaObject()); + if (type) { + QString typeName = type->qmlTypeName(); + int lastSlash = typeName.lastIndexOf(QLatin1Char('/')); + rv.objectType = lastSlash < 0 ? typeName : typeName.mid(lastSlash+1); + } else { + rv.objectType = QString::fromUtf8(object->metaObject()->className()); + } + return rv; } diff --git a/tests/auto/declarative/declarative.pro b/tests/auto/declarative/declarative.pro index b6d2241..413eb1e 100644 --- a/tests/auto/declarative/declarative.pro +++ b/tests/auto/declarative/declarative.pro @@ -17,6 +17,7 @@ SUBDIRS += \ qmlbinding \ # Cover qmlconnection \ # Cover qmlcontext \ # Cover + qmldebug \ # Cover qmldom \ # Cover qmlecmascript \ # Cover qmlerror \ # Cover diff --git a/tests/auto/declarative/qmldebug/qmldebug.pro b/tests/auto/declarative/qmldebug/qmldebug.pro new file mode 100644 index 0000000..61f821e --- /dev/null +++ b/tests/auto/declarative/qmldebug/qmldebug.pro @@ -0,0 +1,5 @@ +load(qttest_p4) +contains(QT_CONFIG,declarative): QT += network declarative +macx:CONFIG -= app_bundle + +SOURCES += tst_qmldebug.cpp diff --git a/tests/auto/declarative/qmldebug/tst_qmldebug.cpp b/tests/auto/declarative/qmldebug/tst_qmldebug.cpp new file mode 100644 index 0000000..a7573da --- /dev/null +++ b/tests/auto/declarative/qmldebug/tst_qmldebug.cpp @@ -0,0 +1,594 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite 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 <qtest.h> +#include <QSignalSpy> +#include <QTimer> +#include <QHostAddress> +#include <QDebug> +#include <QThread> +#include <QProcessEnvironment> +#include <QProcess> + +#include <QtDeclarative/qmlengine.h> +#include <QtDeclarative/qmlcontext.h> +#include <QtDeclarative/qmlcomponent.h> +#include <QtDeclarative/qmlexpression.h> + +#include <private/qmldebug_p.h> +#include <private/qmldebugclient_p.h> +#include <private/qmldebugservice_p.h> +#include <private/qmlgraphicsrectangle_p.h> +#include <private/qmlgraphicstext_p.h> + + +class tst_QmlDebug : public QObject +{ + Q_OBJECT + +public: + tst_QmlDebug(QmlDebugConnection *conn, QmlEngine *engine, QmlGraphicsItem *rootItem) + : m_conn(conn), m_dbg(0), m_engine(engine), m_rootItem(rootItem) {} + +protected slots: + void saveValueChange(const QByteArray &ba, const QVariant &v) + { + m_savedValueChanges[ba] = v; + } + +private: + QmlDebugConnection *m_conn; + QmlEngineDebug *m_dbg; + QmlEngine *m_engine; + QmlGraphicsItem *m_rootItem; + + QHash<QByteArray, QVariant> m_savedValueChanges; + + void waitForQuery(QmlDebugQuery *query) + { + QCOMPARE(query->parent(), this); + QEventLoop loop; + QTimer timer; + QVERIFY(query->state() == QmlDebugQuery::Waiting); + connect(query, SIGNAL(stateChanged(State)), &loop, SLOT(quit())); + connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit())); + timer.start(5000); + loop.exec(); + if (!timer.isActive()) + QFAIL("query timed out"); + } + + void verifyRootObject(const QmlDebugObjectReference &obj) + { + // verifies object according to component definition in main() + + QCOMPARE(obj.debugId(), QmlDebugService::idForObject(m_rootItem)); + QCOMPARE(obj.className(), QLatin1String("Item")); + QCOMPARE(obj.name(), m_rootItem->objectName()); + QCOMPARE(obj.contextDebugId(), QmlDebugService::idForObject(qmlContext(m_rootItem))); + + QmlDebugFileReference source = obj.source(); + QCOMPARE(source.url(), QUrl("file://")); + QCOMPARE(source.lineNumber(), 3); + QCOMPARE(source.columnNumber(), 3); + + QList<QmlDebugPropertyReference> props = obj.properties(); + QHash<QString, QVariant> expected; + + expected["width"] = 10; + expected["height"] = 20; + verifyProperties(props, expected); + } + + void verifyProperties(const QList<QmlDebugPropertyReference> &actual, const QHash<QString, QVariant> &expected) + { + foreach(const QmlDebugPropertyReference &p, actual) { + if (expected.contains(p.name())) + QCOMPARE(p.value(), expected[p.name()]); + } + } + + QmlDebugObjectReference findRootObject() + { + QmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this); + waitForQuery(q_engines); + + if (q_engines->engines().count() == 0) + return QmlDebugObjectReference(); + QmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this); + waitForQuery(q_context); + + if (q_context->rootContext().objects().count() == 0) + return QmlDebugObjectReference(); + QmlDebugObjectQuery *q_obj = m_dbg->queryObject(q_context->rootContext().objects()[0], this); + waitForQuery(q_obj); + + QmlDebugObjectReference result = q_obj->object(); + + delete q_engines; + delete q_context; + delete q_obj; + + return result; + } + + QmlDebugPropertyReference findProperty(const QList<QmlDebugPropertyReference> &props, const QString &name) + { + foreach(const QmlDebugPropertyReference &p, props) { + if (p.name() == name) + return p; + } + return QmlDebugPropertyReference(); + } + + int countNotifiableProperties(const QObject *obj) + { + int count = 0; + for (int i=0; i<obj->metaObject()->propertyCount(); i++) { + QMetaProperty p = obj->metaObject()->property(i); + if (p.hasNotifySignal()) + count++; + } + return count; + } + +private slots: + void initTestCase(); + + void watch_property(); + void watch_object(); + void watch_expression(); + void watch_expression_data(); + + void queryAvailableEngines(); + void queryRootContexts(); + void queryObject(); + void queryObjectRecursive(); + void queryExpressionResult(); + void queryExpressionResult_data(); +}; + +void tst_QmlDebug::initTestCase() +{ + m_dbg = new QmlEngineDebug(m_conn, this); +} + +void tst_QmlDebug::watch_property() +{ + QmlDebugObjectReference obj = findRootObject(); + QmlDebugPropertyReference prop = findProperty(obj.properties(), "width"); + + QmlDebugPropertyWatch *watch = m_dbg->addWatch(prop, this); + QCOMPARE(watch->state(), QmlDebugWatch::Waiting); + QCOMPARE(watch->objectDebugId(), obj.debugId()); + QCOMPARE(watch->name(), prop.name()); + + QSignalSpy spy(watch, SIGNAL(valueChanged(QByteArray,QVariant))); + QEventLoop loop; + QTimer timer; + connect(watch, SIGNAL(valueChanged(QByteArray,QVariant)), &loop, SLOT(quit())); + connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit())); + + int origWidth = m_rootItem->property("width").toInt(); + timer.start(5000); + m_rootItem->setProperty("width", origWidth*2); + loop.exec(); + + if (!timer.isActive()) + QFAIL("Did not receive valueChanged() for property"); + + m_dbg->removeWatch(watch); + delete watch; + + // restore original value and verify spy doesn't get a signal since watch has been removed + m_rootItem->setProperty("width", origWidth); + QTest::qWait(500); + QCOMPARE(spy.count(), 1); + + QCOMPARE(spy.at(0).at(0).value<QByteArray>(), prop.name().toUtf8()); + QCOMPARE(spy.at(0).at(1).value<QVariant>(), qVariantFromValue(origWidth*2)); +} + +void tst_QmlDebug::watch_object() +{ + QmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this); + waitForQuery(q_engines); + + QmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this); + waitForQuery(q_context); + + QmlDebugObjectQuery *q_obj = m_dbg->queryObject(q_context->rootContext().objects()[0], this); + waitForQuery(q_obj); + + QmlDebugObjectReference obj = q_obj->object(); + + delete q_engines; + delete q_context; + delete q_obj; + + QmlDebugWatch *watch = m_dbg->addWatch(obj, this); + QCOMPARE(watch->state(), QmlDebugWatch::Waiting); + QCOMPARE(watch->objectDebugId(), obj.debugId()); + + m_savedValueChanges.clear(); + connect(watch, SIGNAL(valueChanged(QByteArray,QVariant)), + SLOT(saveValueChange(QByteArray,QVariant))); + + int origWidth = m_rootItem->property("width").toInt(); + int origHeight = m_rootItem->property("height").toInt(); + m_rootItem->setProperty("width", origWidth*2); + m_rootItem->setProperty("height", origHeight*2); + + QEventLoop loop; + QTimer timer; + timer.start(5000); + while (timer.isActive() && + (!m_savedValueChanges.contains("width") || !m_savedValueChanges.contains("height"))) { + loop.processEvents(QEventLoop::AllEvents, 50); + } + + QVariant newWidth = m_savedValueChanges["width"]; + QVariant newHeight = m_savedValueChanges["height"]; + + m_dbg->removeWatch(watch); + delete watch; + + // since watch has been removed, restoring the original values should not trigger a valueChanged() + m_savedValueChanges.clear(); + m_rootItem->setProperty("width", origWidth); + m_rootItem->setProperty("height", origHeight); + QTest::qWait(500); + QCOMPARE(m_savedValueChanges.count(), 0); + + if (newWidth.isNull() || newHeight.isNull()) { + QString s = QString("Did not receive both width and height changes (width=%1, height=%2)") + .arg(newWidth.toString()).arg(newHeight.toString()); + QFAIL(qPrintable(s)); + } + + QCOMPARE(newWidth, qVariantFromValue(origWidth*2)); + QCOMPARE(newHeight, qVariantFromValue(origHeight*2)); +} + +void tst_QmlDebug::watch_expression() +{ + QFETCH(QString, expr); + QFETCH(int, increment); + QFETCH(int, incrementCount); + + int origWidth = m_rootItem->property("width").toInt(); + + QmlDebugObjectReference obj = findRootObject(); + QmlDebugPropertyReference prop; + + QmlDebugObjectExpressionWatch *watch = m_dbg->addWatch(obj, expr, this); + QCOMPARE(watch->state(), QmlDebugWatch::Waiting); + QCOMPARE(watch->objectDebugId(), obj.debugId()); + QCOMPARE(watch->expression(), expr); + + QSignalSpy spy(watch, SIGNAL(valueChanged(QByteArray,QVariant))); + int expectedSpyCount = incrementCount + 1; // should also get signal with expression's initial value + + int width = origWidth; + for (int i=0; i<incrementCount+1; i++) { + QTimer timer; + timer.start(5000); + if (i > 0) { + width += increment; + m_rootItem->setProperty("width", width); + } + QEventLoop loop; + connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit())); + connect(watch, SIGNAL(valueChanged(QByteArray,QVariant)), &loop, SLOT(quit())); + loop.exec(); + if (!timer.isActive()) + QFAIL("Did not receive valueChanged() signal for expression"); + } + + m_dbg->removeWatch(watch); + delete watch; + + // restore original value and verify spy doesn't get a signal since watch has been removed + m_rootItem->setProperty("width", origWidth); // may increase spy count before QCOMPARE() + QTest::qWait(500); + QCOMPARE(spy.count(), expectedSpyCount); + + width = origWidth + increment; + for (int i=0; i<spy.count(); i++) { + QCOMPARE(spy.at(i).at(1).value<QVariant>().toInt(), width); + width += increment; + } +} + +void tst_QmlDebug::watch_expression_data() +{ + QTest::addColumn<QString>("expr"); + QTest::addColumn<int>("increment"); + QTest::addColumn<int>("incrementCount"); + + QTest::newRow("width") << "width" << 0 << 0; + QTest::newRow("width+10") << "width + 10" << 10 << 5; +} + +void tst_QmlDebug::queryAvailableEngines() +{ + QmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this); + waitForQuery(q_engines); + + // TODO have multiple engines + QList<QmlDebugEngineReference> engines = q_engines->engines(); + QCOMPARE(engines.count(), 1); + + foreach(const QmlDebugEngineReference &e, engines) { + QCOMPARE(e.debugId(), QmlDebugService::idForObject(m_engine)); + QCOMPARE(e.name(), m_engine->objectName()); + } + + delete q_engines; +} + +void tst_QmlDebug::queryRootContexts() +{ + QmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this); + waitForQuery(q_engines); + + QmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this); + waitForQuery(q_context); + + QmlContext *actualContext = m_engine->rootContext(); + QmlDebugContextReference context = q_context->rootContext(); + QCOMPARE(context.debugId(), QmlDebugService::idForObject(actualContext)); + QCOMPARE(context.name(), actualContext->objectName()); + + QCOMPARE(context.objects().count(), 1); + + // root context query sends only root object data - it doesn't fill in + // the children or property info + QCOMPARE(context.objects()[0].properties().count(), 0); + QCOMPARE(context.objects()[0].children().count(), 0); + + // TODO have multiple contexts + QCOMPARE(context.contexts().count(), 0); + + delete q_engines; + delete q_context; +} + +void tst_QmlDebug::queryObject() +{ + QmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this); + waitForQuery(q_engines); + + QmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this); + waitForQuery(q_context); + + QmlDebugObjectQuery *q_obj = m_dbg->queryObject(q_context->rootContext().objects()[0], this); + waitForQuery(q_obj); + + QmlDebugObjectReference obj = q_obj->object(); + verifyRootObject(obj); + + QVERIFY(obj.children().count() >= 2); + + // non-recursive query, children data not available + foreach(const QmlDebugObjectReference &child, obj.children()) + QCOMPARE(child.properties().count(), 0); + + delete q_engines; + delete q_context; + delete q_obj; +} + +void tst_QmlDebug::queryObjectRecursive() +{ + QmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this); + waitForQuery(q_engines); + + QmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this); + waitForQuery(q_context); + + QmlDebugObjectQuery *q_obj = m_dbg->queryObjectRecursive(q_context->rootContext().objects()[0], this); + waitForQuery(q_obj); + + QmlDebugObjectReference obj = q_obj->object(); + verifyRootObject(obj); + + delete q_engines; + delete q_context; + delete q_obj; + + QList<QmlDebugObjectReference> children = obj.children(); + QVERIFY(children.count() >= 2); // there may be additional properties e.g. StateGroup + + QList<QmlDebugPropertyReference> props; + QHash<QString, QVariant> expected; + + QmlDebugObjectReference rectRef; + QmlDebugObjectReference textRef; + foreach (const QmlDebugObjectReference &child, children) { + if (child.className() == "Rectangle") { + props = child.properties(); + QVERIFY(props.count() > 0); + expected.clear(); + expected["width"] = 500; + expected["height"] = 600; + expected["color"] = "blue"; + verifyProperties(props, expected); + rectRef = child; + } else if (child.className() == "Text") { + props = child.properties(); + QVERIFY(props.count() > 0); + expected.clear(); + expected["color"] = "red"; + verifyProperties(props, expected); + textRef = child; + } + } + + QVERIFY(!rectRef.className().isEmpty()); + QVERIFY(!textRef.className().isEmpty()); + + QObject *rectObj = 0; + QObject *textObj = 0; + foreach (QObject *o, m_rootItem->children()) { + if (o->metaObject()->className() == QmlGraphicsRectangle::staticMetaObject.className()) + rectObj = o; + else if (o->metaObject()->className() == QmlGraphicsText::staticMetaObject.className()) + textObj = o; + } + + QVERIFY(rectObj); + QVERIFY(textObj); + + for (int i=0; i<rectObj->metaObject()->propertyCount(); i++) { + QMetaProperty p = rectObj->metaObject()->property(i); + QmlDebugPropertyReference pd = findProperty(rectRef.properties(), p.name()); + if (!pd.name().isEmpty()) { + QCOMPARE(pd.name(), QString::fromUtf8(p.name())); + if (p.type() < QVariant::UserType) + QCOMPARE(pd.value(), p.read(rectObj)); + if (pd.name() != "parent") + QCOMPARE(pd.valueTypeName(), QString::fromUtf8(p.typeName())); + QCOMPARE(pd.hasNotifySignal(), p.hasNotifySignal()); + } + } +} + +void tst_QmlDebug::queryExpressionResult() +{ + QFETCH(QString, expr); + QFETCH(QVariant, result); + + QmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this); + waitForQuery(q_engines); + + QmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this); + waitForQuery(q_context); + + QmlDebugExpressionQuery *q_expr = m_dbg->queryExpressionResult(q_context->rootContext().objects()[0].debugId(), expr, this); + QCOMPARE(q_expr->expression(), expr); + waitForQuery(q_expr); + + QCOMPARE(q_expr->result(), result); + + delete q_engines; + delete q_context; + delete q_expr; +} + +void tst_QmlDebug::queryExpressionResult_data() +{ + QTest::addColumn<QString>("expr"); + QTest::addColumn<QVariant>("result"); + + QTest::newRow("width + 50") << "width + 50" << qVariantFromValue(60); + QTest::newRow("blueRect.width") << "blueRect.width" << qVariantFromValue(500); + QTest::newRow("bad expr") << "aeaef" << qVariantFromValue(QString("<undefined>")); +} + + +class TestRunnerThread : public QThread +{ + Q_OBJECT +public: + void run() { + QTest::qWait(1000); + connectToEngine(); + } + + QPointer<QmlEngine> m_engine; + QPointer<QmlGraphicsItem> m_item; + +signals: + void testsFinished(); + +public slots: + + void connectToEngine() + { + QmlDebugConnection conn; + conn.connectToHost("127.0.0.1", 3768); + bool ok = conn.waitForConnected(5000); + Q_ASSERT(ok); + while (!m_engine && !m_item) + QTest::qWait(50); + + tst_QmlDebug test(&conn, m_engine, m_item); + QTest::qExec(&test); + emit testsFinished(); + } +}; + + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + qputenv("QML_DEBUG_SERVER_PORT", "3768"); + + TestRunnerThread thread; + QObject::connect(&thread, SIGNAL(testsFinished()), qApp, SLOT(quit())); + thread.start(); + + QmlEngine engine; // blocks until client connects + + QmlComponent component(&engine, + "import Qt 4.6\n" + "\n" // don't remove, line number is tested + " Item {\n" // don't remove spaces, column number is tested + "width: 10; height: 20;\n" + "Rectangle { id: blueRect; width: 500; height: 600; color: \"blue\"; }" + "Text { color: \"red\"; }" + "}\n", + QUrl("file://")); + Q_ASSERT(component.isReady()); + QObject *o = component.create(); + QObject::connect(&thread, SIGNAL(testsFinished()), o, SLOT(deleteLater())); + + // start the test + thread.m_engine = &engine; + thread.m_item = qobject_cast<QmlGraphicsItem*>(o); + + return app.exec(); + +} + +//QTEST_MAIN(tst_QmlDebug) + +#include "tst_qmldebug.moc" diff --git a/tools/qmldebugger/creatorplugin/creatorplugin.pro b/tools/qmldebugger/creatorplugin/creatorplugin.pro index d191a37..ff7f3da 100644 --- a/tools/qmldebugger/creatorplugin/creatorplugin.pro +++ b/tools/qmldebugger/creatorplugin/creatorplugin.pro @@ -25,5 +25,6 @@ IDE_BUILD_TREE=$$(CREATOR_BUILD_DIR) include($$(CREATOR_SRC_DIR)/src/qtcreatorplugin.pri) include($$(CREATOR_SRC_DIR)/src/plugins/projectexplorer/projectexplorer.pri) include($$(CREATOR_SRC_DIR)/src/plugins/coreplugin/coreplugin.pri) +include($$(CREATOR_SRC_DIR)/src/plugins/texteditor/texteditor.pri) LIBS += -L$$(CREATOR_BUILD_DIR)/lib/qtcreator diff --git a/tools/qmldebugger/creatorplugin/qmlinspectormode.cpp b/tools/qmldebugger/creatorplugin/qmlinspectormode.cpp index a1ca2fc..ce8ef30 100644 --- a/tools/qmldebugger/creatorplugin/qmlinspectormode.cpp +++ b/tools/qmldebugger/creatorplugin/qmlinspectormode.cpp @@ -65,6 +65,8 @@ #include <coreplugin/editormanager/editormanager.h> #include <coreplugin/actionmanager/actionmanager.h> +#include <texteditor/itexteditor.h> + #include <projectexplorer/runconfiguration.h> #include <projectexplorer/projectexplorer.h> #include <projectexplorer/projectexplorerconstants.h> @@ -435,8 +437,12 @@ void QmlInspectorMode::initWidgets() WatchTableHeaderView *header = new WatchTableHeaderView(m_watchTableModel); m_watchTableView->setHorizontalHeader(header); + connect(m_objectTreeWidget, SIGNAL(activated(QmlDebugObjectReference)), + this, SLOT(treeObjectActivated(QmlDebugObjectReference))); + connect(m_objectTreeWidget, SIGNAL(currentObjectChanged(QmlDebugObjectReference)), m_propertiesWidget, SLOT(reload(QmlDebugObjectReference))); + connect(m_objectTreeWidget, SIGNAL(expressionWatchRequested(QmlDebugObjectReference,QString)), m_watchTableModel, SLOT(expressionWatchRequested(QmlDebugObjectReference,QString))); @@ -536,6 +542,24 @@ void QmlInspectorMode::contextChanged() delete m_contextQuery; m_contextQuery = 0; } +void QmlInspectorMode::treeObjectActivated(const QmlDebugObjectReference &obj) +{ + QmlDebugFileReference source = obj.source(); + QString fileName = source.url().toLocalFile(); + + if (source.lineNumber() < 0 || !QFile::exists(fileName)) + return; + + Core::EditorManager *editorManager = Core::EditorManager::instance(); + TextEditor::ITextEditor *editor = qobject_cast<TextEditor::ITextEditor*>(editorManager->openEditor(fileName)); + if (editor) { + editorManager->ensureEditorManagerVisible(); + editorManager->addCurrentPositionToNavigationHistory(); + editor->gotoLine(source.lineNumber()); + editor->widget()->setFocus(); + } +} + QT_END_NAMESPACE #include "qmlinspectormode.moc" diff --git a/tools/qmldebugger/creatorplugin/qmlinspectormode.h b/tools/qmldebugger/creatorplugin/qmlinspectormode.h index 93c2e44..b4158f1 100644 --- a/tools/qmldebugger/creatorplugin/qmlinspectormode.h +++ b/tools/qmldebugger/creatorplugin/qmlinspectormode.h @@ -57,6 +57,7 @@ class QmlEngineDebug; class QmlDebugConnection; class QmlDebugEnginesQuery; class QmlDebugRootContextQuery; +class QmlDebugObjectReference; class ObjectTree; class WatchTableModel; class WatchTableView; @@ -92,6 +93,7 @@ private slots: void enginesChanged(); void queryEngineContext(int); void contextChanged(); + void treeObjectActivated(const QmlDebugObjectReference &obj); private: struct Actions { diff --git a/tools/qmldebugger/standalone/canvasframerate.cpp b/tools/qmldebugger/standalone/canvasframerate.cpp index 408e8d0..d956029 100644 --- a/tools/qmldebugger/standalone/canvasframerate.cpp +++ b/tools/qmldebugger/standalone/canvasframerate.cpp @@ -38,23 +38,29 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -#include "canvasframerate.h" -#include <QtGui/qwidget.h> -#include <QtGui/qpainter.h> -#include <QtGui/qscrollbar.h> -#include <private/qmldebugclient_p.h> #include <QtCore/qdebug.h> #include <QtCore/qstringlist.h> #include <QtCore/qdatastream.h> +#include <QtCore/qmargins.h> + +#include <QtGui/qapplication.h> +#include <QtGui/qpainter.h> +#include <QtGui/qtooltip.h> +#include <QtGui/qslider.h> +#include <QtGui/qscrollbar.h> +#include <QtGui/qspinbox.h> +#include <QtGui/qgroupbox.h> #include <QtGui/qboxlayout.h> +#include <QtGui/qlabel.h> +#include <QtGui/qlineedit.h> +#include <QtGui/qpushbutton.h> +#include <QtGui/qtabwidget.h> + #include <QResizeEvent> #include <QShowEvent> -#include <QTabWidget> -#include <QPushButton> -#include <QLineEdit> -#include <QCheckBox> -#include <QSpinBox> -#include <QLabel> + +#include <private/qmldebugclient_p.h> +#include "canvasframerate.h" QT_BEGIN_NAMESPACE @@ -62,75 +68,103 @@ class QLineGraph : public QWidget { Q_OBJECT public: - QLineGraph(QWidget * = 0); + QLineGraph(QAbstractSlider *slider, QWidget * = 0); void setPosition(int); public slots: void addSample(int, int, int, bool); void setResolutionForHeight(int); + void clear(); protected: virtual void paintEvent(QPaintEvent *); + virtual void mouseMoveEvent(QMouseEvent *); + virtual void leaveEvent(QEvent *); + virtual void wheelEvent(QWheelEvent *event); private slots: - void scrollbarChanged(int); + void sliderChanged(int); private: - void updateScrollbar(); - void drawSample(QPainter *, int, const QRect &); + void updateSlider(); + void drawSample(QPainter *, int, const QRect &, QList<QRect> *); void drawTime(QPainter *, const QRect &); + QRect findContainingRect(const QList<QRect> &rects, const QPoint &pos) const; struct Sample { int sample[3]; bool isBreak; }; QList<Sample> _samples; - QScrollBar sb; + QAbstractSlider *slider; int position; int samplesPerWidth; int resolutionForHeight; bool ignoreScroll; + QMargins graphMargins; + + QList<QRect> rectsPaintTime; // time to do a paintEvent() + QList<QRect> rectsTimeBetween; // time between frames + QRect highlightedBar; }; -QLineGraph::QLineGraph(QWidget *parent) -: QWidget(parent), sb(Qt::Horizontal, this), position(-1), samplesPerWidth(99), resolutionForHeight(50), ignoreScroll(false) +QLineGraph::QLineGraph(QAbstractSlider *slider, QWidget *parent) +: QWidget(parent), slider(slider), position(-1), samplesPerWidth(99), resolutionForHeight(50), + ignoreScroll(false), graphMargins(65, 10, 71, 35) { - setMinimumHeight(200); - - sb.setMaximum(0); - sb.setMinimum(0); - sb.setSingleStep(1); + setMouseTracking(true); - QVBoxLayout *layout = new QVBoxLayout; - setLayout(layout); - layout->addStretch(2); - layout->addWidget(&sb); - QObject::connect(&sb, SIGNAL(valueChanged(int)), this, SLOT(scrollbarChanged(int))); + slider->setMaximum(0); + slider->setMinimum(0); + slider->setSingleStep(1); + + connect(slider, SIGNAL(valueChanged(int)), this, SLOT(sliderChanged(int))); } -void QLineGraph::scrollbarChanged(int v) +void QLineGraph::sliderChanged(int v) { if(ignoreScroll) return; - if (v == sb.maximum()) + if (v == slider->maximum()) position = -1; else position = v; + update(); + + // update highlightedRect + QPoint pos = mapFromGlobal(QCursor::pos()); + if (geometry().contains(pos)) { + QMouseEvent *me = new QMouseEvent(QEvent::MouseMove, pos, + Qt::NoButton, Qt::NoButton, Qt::NoModifier); + QApplication::postEvent(this, me); + } } -void QLineGraph::updateScrollbar() +void QLineGraph::clear() +{ + _samples.clear(); + rectsPaintTime.clear(); + rectsTimeBetween.clear(); + highlightedBar = QRect(); + position = -1; + + updateSlider(); + update(); +} + +void QLineGraph::updateSlider() { ignoreScroll = true; - sb.setMaximum(qMax(0, _samples.count() - samplesPerWidth - 1)); + slider->setMaximum(qMax(0, _samples.count() - samplesPerWidth - 1)); if(position == -1) { - sb.setValue(sb.maximum()); + slider->setValue(slider->maximum()); } else { - sb.setValue(position); - } + slider->setValue(position); + } ignoreScroll = false; } @@ -142,13 +176,13 @@ void QLineGraph::addSample(int a, int b, int d, bool isBreak) s.sample[1] = b; s.sample[2] = d; _samples << s; - updateScrollbar(); + updateSlider(); update(); } void QLineGraph::setPosition(int p) { - scrollbarChanged(p); + sliderChanged(p); } void QLineGraph::drawTime(QPainter *p, const QRect &rect) @@ -182,7 +216,7 @@ void QLineGraph::drawTime(QPainter *p, const QRect &rect) } -void QLineGraph::drawSample(QPainter *p, int s, const QRect &rect) +void QLineGraph::drawSample(QPainter *p, int s, const QRect &rect, QList<QRect> *record) { if(_samples.isEmpty()) return; @@ -205,8 +239,11 @@ void QLineGraph::drawSample(QPainter *p, int s, const QRect &rect) xEnd = rect.left() + scaleX * (ii - first); int yEnd = rect.bottom() - _samples.at(ii).sample[s] * scaleY; - if (!(s == 0 && _samples.at(ii).isBreak)) - p->drawRect(QRect(lastXEnd, yEnd, scaleX, _samples.at(ii).sample[s] * scaleY)); + if (!(s == 0 && _samples.at(ii).isBreak)) { + QRect bar(lastXEnd, yEnd, scaleX, _samples.at(ii).sample[s] * scaleY); + record->append(bar); + p->drawRect(bar); + } lastXEnd = xEnd; } @@ -218,16 +255,33 @@ void QLineGraph::paintEvent(QPaintEvent *) QPainter p(this); p.setRenderHint(QPainter::Antialiasing); - QRect r(50, 10, width() - 60, height() - 60); + QRect r(graphMargins.left(), graphMargins.top(), + width() - graphMargins.right(), height() - graphMargins.bottom()); + + p.save(); + p.rotate(-90); + p.translate(-r.height()/2 - r.width()/2 - graphMargins.right(), -r.height()/2); + p.drawText(r, Qt::AlignCenter, tr("Frame rate")); + p.restore(); + p.setBrush(QColor("lightsteelblue")); - drawSample(&p, 0, r); + rectsTimeBetween.clear(); + drawSample(&p, 0, r, &rectsTimeBetween); p.setBrush(QColor("pink")); - drawSample(&p, 1, r); + rectsPaintTime.clear(); + drawSample(&p, 1, r, &rectsPaintTime); + + if (!highlightedBar.isNull()) { + p.setBrush(Qt::darkGreen); + p.drawRect(highlightedBar); + } p.setBrush(Qt::NoBrush); p.drawRect(r); + slider->setGeometry(x() + r.x(), slider->y(), r.width(), slider->height()); + for(int ii = 0; ii <= resolutionForHeight; ++ii) { int y = 1 + r.bottom() - ii * r.height() / resolutionForHeight; @@ -243,15 +297,117 @@ void QLineGraph::paintEvent(QPaintEvent *) drawTime(&p, r); } +void QLineGraph::mouseMoveEvent(QMouseEvent *event) +{ + QPoint pos = event->pos(); + + QRect rect = findContainingRect(rectsPaintTime, pos); + if (rect.isNull()) + rect = findContainingRect(rectsTimeBetween, pos); + + if (!highlightedBar.isNull()) + update(highlightedBar.adjusted(-1, -1, 1, 1)); + highlightedBar = rect; + + if (!rect.isNull()) { + QRect graph(graphMargins.left(), graphMargins.top(), + width() - graphMargins.right(), height() - graphMargins.bottom()); + qreal scaleY = qreal(graph.height()) / resolutionForHeight; + QToolTip::showText(event->globalPos(), QString::number(qRound(rect.height() / scaleY)), this, rect); + update(rect.adjusted(-1, -1, 1, 1)); + } +} + +void QLineGraph::leaveEvent(QEvent *) +{ + if (!highlightedBar.isNull()) { + QRect bar = highlightedBar.adjusted(-1, -1, 1, 1); + highlightedBar = QRect(); + update(bar); + } +} + +void QLineGraph::wheelEvent(QWheelEvent *event) +{ + QWheelEvent we(QPoint(0,0), event->delta(), event->buttons(), event->modifiers(), event->orientation()); + QApplication::sendEvent(slider, &we); +} + void QLineGraph::setResolutionForHeight(int resolution) { resolutionForHeight = resolution; update(); } +QRect QLineGraph::findContainingRect(const QList<QRect> &rects, const QPoint &pos) const +{ + for (int i=0; i<rects.count(); i++) { + if (rects[i].contains(pos)) + return rects[i]; + } + return QRect(); +} + + +class GraphWindow : public QWidget +{ + Q_OBJECT +public: + GraphWindow(QWidget *parent = 0); + + virtual QSize sizeHint() const; + +public slots: + void addSample(int, int, int, bool); + void setResolutionForHeight(int); + void clear(); + +private: + QLineGraph *m_graph; +}; + +GraphWindow::GraphWindow(QWidget *parent) + : QWidget(parent) +{ + QSlider *scroll = new QSlider(Qt::Horizontal); + scroll->setFocusPolicy(Qt::WheelFocus); + m_graph = new QLineGraph(scroll); + + setFocusPolicy(Qt::WheelFocus); + setFocusProxy(scroll); + + QVBoxLayout *layout = new QVBoxLayout(this); + layout->setContentsMargins(0, 0, 5, 0); + layout->setSpacing(0); + layout->addWidget(m_graph, 2); + layout->addWidget(new QLabel(tr("Total time elapsed (ms)")), 0, Qt::AlignHCenter); + layout->addWidget(scroll); +} + +void GraphWindow::addSample(int a, int b, int d, bool isBreak) +{ + m_graph->addSample(a, b, d, isBreak); +} + +void GraphWindow::setResolutionForHeight(int res) +{ + m_graph->setResolutionForHeight(res); +} + +void GraphWindow::clear() +{ + m_graph->clear(); +} + +QSize GraphWindow::sizeHint() const +{ + return QSize(400, 220); +} + + class CanvasFrameRatePlugin : public QmlDebugClient { -Q_OBJECT + Q_OBJECT public: CanvasFrameRatePlugin(QmlDebugConnection *client); @@ -290,38 +446,46 @@ CanvasFrameRate::CanvasFrameRate(QWidget *parent) : QWidget(parent), m_plugin(0) { - QVBoxLayout *layout = new QVBoxLayout; - layout->setContentsMargins(0,0,0,0); - layout->setSpacing(0); - setLayout(layout); - m_tabs = new QTabWidget(this); - layout->addWidget(m_tabs); QHBoxLayout *bottom = new QHBoxLayout; - bottom->setContentsMargins(5, 0, 5, 0); + bottom->setMargin(0); bottom->setSpacing(10); - layout->addLayout(bottom); - - QLabel *label = new QLabel("Resolution", this); - bottom->addWidget(label); - m_spin = new QSpinBox(this); - m_spin->setRange(50,200); - m_spin->setValue(50); - m_spin->setSuffix("ms"); - bottom->addWidget(m_spin); + m_res = new QSpinBox; + m_res->setRange(30, 200); + m_res->setValue(m_res->minimum()); + m_res->setSingleStep(10); + m_res->setSuffix(QLatin1String("ms")); + bottom->addWidget(new QLabel(tr("Resolution:"))); + bottom->addWidget(m_res); - bottom->addStretch(2); + bottom->addStretch(); - m_enabledCheckBox = new QCheckBox("Enable", this); - bottom->addWidget(m_enabledCheckBox); - QObject::connect(m_enabledCheckBox, SIGNAL(stateChanged(int)), - this, SLOT(enabledStateChanged(int))); + m_clearButton = new QPushButton(tr("Clear")); + connect(m_clearButton, SIGNAL(clicked()), SLOT(clearGraph())); + bottom->addWidget(m_clearButton); - QPushButton *pb = new QPushButton(tr("New Tab"), this); - QObject::connect(pb, SIGNAL(clicked()), this, SLOT(newTab())); + QPushButton *pb = new QPushButton(tr("New Graph"), this); + connect(pb, SIGNAL(clicked()), this, SLOT(newTab())); bottom->addWidget(pb); + + m_group = new QGroupBox(tr("Enabled")); + m_group->setCheckable(true); + m_group->setChecked(false); + connect(m_group, SIGNAL(toggled(bool)), SLOT(enabledToggled(bool))); + + QVBoxLayout *groupLayout = new QVBoxLayout(m_group); + groupLayout->setContentsMargins(5, 0, 5, 0); + groupLayout->setSpacing(2); + groupLayout->addWidget(m_tabs); + groupLayout->addLayout(bottom); + + QVBoxLayout *layout = new QVBoxLayout; + layout->setContentsMargins(0, 10, 0, 0); + layout->setSpacing(0); + layout->addWidget(m_group); + setLayout(layout); } void CanvasFrameRate::reset(QmlDebugConnection *conn) @@ -358,7 +522,7 @@ void CanvasFrameRate::handleConnected(QmlDebugConnection *conn) { delete m_plugin; m_plugin = new CanvasFrameRatePlugin(conn); - enabledStateChanged(m_enabledCheckBox->checkState()); + enabledToggled(m_group->isChecked()); newTab(); } @@ -372,6 +536,15 @@ QSize CanvasFrameRate::sizeHint() const return m_sizeHint; } +void CanvasFrameRate::clearGraph() +{ + if (m_tabs->count()) { + GraphWindow *w = qobject_cast<GraphWindow*>(m_tabs->currentWidget()); + if (w) + w->clear(); + } +} + void CanvasFrameRate::newTab() { if (!m_plugin) @@ -383,22 +556,22 @@ void CanvasFrameRate::newTab() w, SLOT(addSample(int,int,int,bool))); } - int id = m_tabs->count(); + int count = m_tabs->count(); - QLineGraph *graph = new QLineGraph(this); - QObject::connect(m_plugin, SIGNAL(sample(int,int,int,bool)), - graph, SLOT(addSample(int,int,int,bool))); - QObject::connect(m_spin, SIGNAL(valueChanged(int)), graph, SLOT(setResolutionForHeight(int))); + GraphWindow *graph = new GraphWindow; + graph->setResolutionForHeight(m_res->value()); + connect(m_plugin, SIGNAL(sample(int,int,int,bool)), + graph, SLOT(addSample(int,int,int,bool))); + connect(m_res, SIGNAL(valueChanged(int)), + graph, SLOT(setResolutionForHeight(int))); - QString name = QLatin1String("Graph ") + QString::number(id); + QString name = QLatin1String("Graph ") + QString::number(count + 1); m_tabs->addTab(graph, name); - m_tabs->setCurrentIndex(id); + m_tabs->setCurrentIndex(count); } -void CanvasFrameRate::enabledStateChanged(int s) +void CanvasFrameRate::enabledToggled(bool checked) { - bool checked = s != 0; - if (m_plugin) static_cast<QmlDebugClient *>(m_plugin)->setEnabled(checked); } diff --git a/tools/qmldebugger/standalone/canvasframerate.h b/tools/qmldebugger/standalone/canvasframerate.h index be6bbc6..f8eec59 100644 --- a/tools/qmldebugger/standalone/canvasframerate.h +++ b/tools/qmldebugger/standalone/canvasframerate.h @@ -49,8 +49,11 @@ QT_BEGIN_NAMESPACE class QTabWidget; +class QSlider; +class QGroupBox; +class QLabel; class QSpinBox; -class QCheckBox; +class QPushButton; class CanvasFrameRatePlugin; @@ -66,18 +69,20 @@ public: virtual QSize sizeHint() const; private slots: + void clearGraph(); void newTab(); - void enabledStateChanged(int); + void enabledToggled(bool); void connectionStateChanged(QAbstractSocket::SocketState state); private: void handleConnected(QmlDebugConnection *conn); + QGroupBox *m_group; QTabWidget *m_tabs; - QSpinBox *m_spin; + QSpinBox *m_res; + QPushButton *m_clearButton; CanvasFrameRatePlugin *m_plugin; QSize m_sizeHint; - QCheckBox *m_enabledCheckBox; }; QT_END_NAMESPACE diff --git a/tools/qmldebugger/standalone/main.cpp b/tools/qmldebugger/standalone/main.cpp index 2f2a30e..715837e 100644 --- a/tools/qmldebugger/standalone/main.cpp +++ b/tools/qmldebugger/standalone/main.cpp @@ -45,6 +45,9 @@ int main(int argc, char ** argv) { QApplication app(argc, argv); + app.setApplicationName("QtQmlDebugger"); + app.setOrganizationName("Nokia"); + app.setOrganizationDomain("nokia.com"); QStringList args = app.arguments(); diff --git a/tools/qmldebugger/standalone/objecttree.cpp b/tools/qmldebugger/standalone/objecttree.cpp index b06d377..4dbc1a7 100644 --- a/tools/qmldebugger/standalone/objecttree.cpp +++ b/tools/qmldebugger/standalone/objecttree.cpp @@ -59,9 +59,12 @@ ObjectTree::ObjectTree(QmlEngineDebug *client, QWidget *parent) { setHeaderHidden(true); setMinimumWidth(250); + setExpandsOnDoubleClick(false); connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), - this, SLOT(currentItemChanged(QTreeWidgetItem *))); + SLOT(currentItemChanged(QTreeWidgetItem *))); + connect(this, SIGNAL(itemActivated(QTreeWidgetItem *, int)), + SLOT(activated(QTreeWidgetItem *))); } void ObjectTree::setEngineDebug(QmlEngineDebug *client) @@ -113,11 +116,18 @@ void ObjectTree::currentItemChanged(QTreeWidgetItem *item) return; QmlDebugObjectReference obj = item->data(0, Qt::UserRole).value<QmlDebugObjectReference>(); - if (obj.debugId() < 0) { - qWarning("QML Object Tree: bad object id"); + if (obj.debugId() >= 0) + emit currentObjectChanged(obj); +} + +void ObjectTree::activated(QTreeWidgetItem *item) +{ + if (!item) return; - } - emit currentObjectChanged(obj); + + QmlDebugObjectReference obj = item->data(0, Qt::UserRole).value<QmlDebugObjectReference>(); + if (obj.debugId() >= 0) + emit activated(obj); } void ObjectTree::buildTree(const QmlDebugObjectReference &obj, QTreeWidgetItem *parent) diff --git a/tools/qmldebugger/standalone/objecttree.h b/tools/qmldebugger/standalone/objecttree.h index f7b3a3f..c8d625c 100644 --- a/tools/qmldebugger/standalone/objecttree.h +++ b/tools/qmldebugger/standalone/objecttree.h @@ -64,6 +64,7 @@ public: signals: void currentObjectChanged(const QmlDebugObjectReference &); + void activated(const QmlDebugObjectReference &); void expressionWatchRequested(const QmlDebugObjectReference &, const QString &); public slots: @@ -76,6 +77,7 @@ protected: private slots: void objectFetched(); void currentItemChanged(QTreeWidgetItem *); + void activated(QTreeWidgetItem *); private: QTreeWidgetItem *findItemByObjectId(int debugId) const; diff --git a/tools/qmldebugger/standalone/qmldebugger.cpp b/tools/qmldebugger/standalone/qmldebugger.cpp index afcf84c..4d86377 100644 --- a/tools/qmldebugger/standalone/qmldebugger.cpp +++ b/tools/qmldebugger/standalone/qmldebugger.cpp @@ -40,12 +40,14 @@ ****************************************************************************/ #include <QtCore/qtimer.h> #include <QtCore/qdebug.h> -#include <QVBoxLayout> -#include <QPushButton> -#include <QLineEdit> -#include <QTabWidget> -#include <QSpinBox> -#include <QLabel> +#include <QtCore/qsettings.h> + +#include <QtGui/qlayout.h> +#include <QtGui/qpushbutton.h> +#include <QtGui/qlineedit.h> +#include <QtGui/qtabwidget.h> +#include <QtGui/qspinbox.h> +#include <QtGui/qlabel.h> #include "canvasframerate.h" #include "engine.h" @@ -64,12 +66,10 @@ QmlDebugger::QmlDebugger(QWidget *parent) m_connectionState = new QLabel(this); connectLayout->addWidget(m_connectionState); m_host = new QLineEdit(this); - m_host->setText("127.0.0.1"); connectLayout->addWidget(m_host); m_port = new QSpinBox(this); m_port->setMinimum(1024); m_port->setMaximum(20000); - m_port->setValue(3768); connectLayout->addWidget(m_port); m_connectButton = new QPushButton(tr("Connect"), this); QObject::connect(m_connectButton, SIGNAL(clicked()), @@ -99,7 +99,9 @@ QmlDebugger::QmlDebugger(QWidget *parent) QObject::connect(&client, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(connectionError(QAbstractSocket::SocketError))); - m_tabs->setCurrentIndex(1); + QSettings settings; + m_host->setText(settings.value("Host", "127.0.0.1").toString()); + m_port->setValue(settings.value("Port", 3768).toInt()); connectToHost(); } @@ -119,6 +121,15 @@ void QmlDebugger::showEngineTab() m_tabs->setCurrentWidget(m_enginePane); } +void QmlDebugger::closeEvent(QCloseEvent *event) +{ + QSettings settings; + settings.setValue("Host", m_host->text()); + settings.setValue("Port", m_port->value()); + + QWidget::closeEvent(event); +} + void QmlDebugger::connectionStateChanged() { switch (client.state()) { diff --git a/tools/qmldebugger/standalone/qmldebugger.h b/tools/qmldebugger/standalone/qmldebugger.h index 7bacce7..da95ef9 100644 --- a/tools/qmldebugger/standalone/qmldebugger.h +++ b/tools/qmldebugger/standalone/qmldebugger.h @@ -67,6 +67,9 @@ public slots: void connectToHost(); void disconnectFromHost(); +protected: + void closeEvent(QCloseEvent *); + private slots: void connectionStateChanged(); void connectionError(QAbstractSocket::SocketError socketError); |