summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWarwick Allison <warwick.allison@nokia.com>2009-11-09 03:14:38 (GMT)
committerWarwick Allison <warwick.allison@nokia.com>2009-11-09 03:14:38 (GMT)
commit82e142d6b52153024bd05fa3a7853be7c64bb3bb (patch)
tree06d69a8612742dd6ab8d519baefc3f6355329fde
parent65ebb736e7d1f134b6d3dc5c620de43b9880d544 (diff)
parent5e5ee991ad4261516cf099c9b237f8c72c9d49cc (diff)
downloadQt-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.cpp12
-rw-r--r--src/declarative/debugger/qmldebug_p.h2
-rw-r--r--src/declarative/qml/qmlenginedebug.cpp15
-rw-r--r--tests/auto/declarative/declarative.pro1
-rw-r--r--tests/auto/declarative/qmldebug/qmldebug.pro5
-rw-r--r--tests/auto/declarative/qmldebug/tst_qmldebug.cpp594
-rw-r--r--tools/qmldebugger/creatorplugin/creatorplugin.pro1
-rw-r--r--tools/qmldebugger/creatorplugin/qmlinspectormode.cpp24
-rw-r--r--tools/qmldebugger/creatorplugin/qmlinspectormode.h2
-rw-r--r--tools/qmldebugger/standalone/canvasframerate.cpp329
-rw-r--r--tools/qmldebugger/standalone/canvasframerate.h13
-rw-r--r--tools/qmldebugger/standalone/main.cpp3
-rw-r--r--tools/qmldebugger/standalone/objecttree.cpp20
-rw-r--r--tools/qmldebugger/standalone/objecttree.h2
-rw-r--r--tools/qmldebugger/standalone/qmldebugger.cpp29
-rw-r--r--tools/qmldebugger/standalone/qmldebugger.h3
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);