summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/declarative/debugger/qmldebug.cpp81
-rw-r--r--src/declarative/debugger/qmldebug.h24
-rw-r--r--src/declarative/qml/qmlenginedebug.cpp81
-rw-r--r--src/declarative/qml/qmlenginedebug_p.h2
-rw-r--r--src/declarative/qml/qmlexpression.cpp16
-rw-r--r--src/declarative/qml/qmlexpression.h2
-rw-r--r--src/declarative/qml/qmlexpression_p.h4
-rw-r--r--tools/qmldebugger/expressionquerywidget.cpp216
-rw-r--r--tools/qmldebugger/expressionquerywidget.h62
-rw-r--r--tools/qmldebugger/objectpropertiesview.cpp23
-rw-r--r--tools/qmldebugger/objecttree.cpp10
-rw-r--r--tools/qmldebugger/objecttree.h6
-rw-r--r--tools/qmldebugger/qmldebugger.cpp4
-rw-r--r--tools/qmldebugger/qmldebugger.pri6
-rw-r--r--tools/qmldebugger/watchtable.cpp3
-rw-r--r--tools/qmlviewer/qmlviewer.cpp8
16 files changed, 500 insertions, 48 deletions
diff --git a/src/declarative/debugger/qmldebug.cpp b/src/declarative/debugger/qmldebug.cpp
index 1ef7503..2537ec0 100644
--- a/src/declarative/debugger/qmldebug.cpp
+++ b/src/declarative/debugger/qmldebug.cpp
@@ -32,10 +32,12 @@ public:
static void remove(QmlEngineDebug *, QmlDebugEnginesQuery *);
static void remove(QmlEngineDebug *, QmlDebugRootContextQuery *);
static void remove(QmlEngineDebug *, QmlDebugObjectQuery *);
+ static void remove(QmlEngineDebug *, QmlDebugExpressionQuery *);
QHash<int, QmlDebugEnginesQuery *> enginesQuery;
QHash<int, QmlDebugRootContextQuery *> rootContextQuery;
QHash<int, QmlDebugObjectQuery *> objectQuery;
+ QHash<int, QmlDebugExpressionQuery *> expressionQuery;
QHash<int, QmlDebugWatch *> watched;
};
@@ -81,6 +83,12 @@ void QmlEngineDebugPrivate::remove(QmlEngineDebug *c, QmlDebugObjectQuery *q)
p->objectQuery.remove(q->m_queryId);
}
+void QmlEngineDebugPrivate::remove(QmlEngineDebug *c, QmlDebugExpressionQuery *q)
+{
+ QmlEngineDebugPrivate *p = (QmlEngineDebugPrivate *)QObjectPrivate::get(c);
+ p->expressionQuery.remove(q->m_queryId);
+}
+
Q_DECLARE_METATYPE(QmlDebugObjectReference);
void QmlEngineDebugPrivate::decode(QDataStream &ds, QmlDebugObjectReference &o,
bool simple)
@@ -109,6 +117,7 @@ void QmlEngineDebugPrivate::decode(QDataStream &ds, QmlDebugObjectReference &o,
prop.m_name = data.name;
prop.m_binding = data.binding;
prop.m_hasNotifySignal = data.hasNotifySignal;
+ prop.m_valueTypeName = data.valueTypeName;
if (data.type == QmlEngineDebugServer::QmlObjectProperty::Basic)
prop.m_value = data.value;
else if (data.type == QmlEngineDebugServer::QmlObjectProperty::Object) {
@@ -116,7 +125,6 @@ void QmlEngineDebugPrivate::decode(QDataStream &ds, QmlDebugObjectReference &o,
obj.m_debugId = prop.m_value.toInt();
prop.m_value = qVariantFromValue(obj);
}
-
o.m_properties << prop;
}
@@ -212,6 +220,19 @@ void QmlEngineDebugPrivate::message(const QByteArray &data)
query->m_client = 0;
query->setState(QmlDebugQuery::Completed);
+ } else if (type == "EVAL_EXPRESSION_R") {
+ int queryId;
+ QVariant result;
+ ds >> queryId >> result;
+
+ QmlDebugExpressionQuery *query = expressionQuery.value(queryId);
+ if (!query)
+ return;
+ expressionQuery.remove(queryId);
+
+ query->m_result = result;
+ query->m_client = 0;
+ query->setState(QmlDebugQuery::Completed);
} else if (type == "WATCH_PROPERTY_R") {
int queryId;
bool ok;
@@ -267,7 +288,6 @@ QmlDebugPropertyWatch *QmlEngineDebug::addWatch(const QmlDebugPropertyReference
QmlDebugPropertyWatch *watch = new QmlDebugPropertyWatch(parent);
if (d->client->isConnected()) {
- //query->m_client = this;
int queryId = d->getId();
watch->m_queryId = queryId;
watch->m_objectDebugId = property.objectDebugId();
@@ -445,6 +465,29 @@ QmlDebugObjectQuery *QmlEngineDebug::queryObjectRecursive(const QmlDebugObjectRe
return query;
}
+QmlDebugExpressionQuery *QmlEngineDebug::queryExpressionResult(int objectDebugId, const QString &expr, QObject *parent)
+{
+ Q_D(QmlEngineDebug);
+
+ QmlDebugExpressionQuery *query = new QmlDebugExpressionQuery(parent);
+ if (d->client->isConnected() && objectDebugId != -1) {
+ query->m_client = this;
+ query->m_expr = expr;
+ int queryId = d->getId();
+ query->m_queryId = queryId;
+ d->expressionQuery.insert(queryId, query);
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("EVAL_EXPRESSION") << queryId << objectDebugId << expr;
+ d->client->sendMessage(message);
+ } else {
+ query->m_state = QmlDebugQuery::Error;
+ }
+
+ return query;
+}
+
QmlDebugWatch::QmlDebugWatch(QObject *parent)
: QObject(parent), m_state(Waiting), m_queryId(-1), m_objectDebugId(-1)
{
@@ -566,6 +609,27 @@ QmlDebugObjectReference QmlDebugObjectQuery::object() const
return m_object;
}
+QmlDebugExpressionQuery::QmlDebugExpressionQuery(QObject *parent)
+: QmlDebugQuery(parent), m_client(0), m_queryId(-1)
+{
+}
+
+QmlDebugExpressionQuery::~QmlDebugExpressionQuery()
+{
+ if (m_client && m_queryId != -1)
+ QmlEngineDebugPrivate::remove(m_client, this);
+}
+
+QString QmlDebugExpressionQuery::expression() const
+{
+ return m_expr;
+}
+
+QVariant QmlDebugExpressionQuery::result() const
+{
+ return m_result;
+}
+
QmlDebugEngineReference::QmlDebugEngineReference()
: m_debugId(-1)
{
@@ -748,13 +812,17 @@ QmlDebugPropertyReference::QmlDebugPropertyReference()
}
QmlDebugPropertyReference::QmlDebugPropertyReference(const QmlDebugPropertyReference &o)
-: m_objectDebugId(o.m_objectDebugId), m_name(o.m_name), m_value(o.m_value), m_binding(o.m_binding), m_hasNotifySignal(o.m_hasNotifySignal)
+: m_objectDebugId(o.m_objectDebugId), m_name(o.m_name), m_value(o.m_value),
+ m_valueTypeName(o.m_valueTypeName), m_binding(o.m_binding),
+ m_hasNotifySignal(o.m_hasNotifySignal)
{
}
QmlDebugPropertyReference &QmlDebugPropertyReference::operator=(const QmlDebugPropertyReference &o)
{
- m_objectDebugId = o.m_objectDebugId; m_name = o.m_name; m_value = o.m_value; m_binding = o.m_binding; m_hasNotifySignal = o.m_hasNotifySignal;
+ m_objectDebugId = o.m_objectDebugId; m_name = o.m_name; m_value = o.m_value;
+ m_valueTypeName = o.m_valueTypeName; m_binding = o.m_binding;
+ m_hasNotifySignal = o.m_hasNotifySignal;
return *this;
}
@@ -768,6 +836,11 @@ QString QmlDebugPropertyReference::name() const
return m_name;
}
+QString QmlDebugPropertyReference::valueTypeName() const
+{
+ return m_valueTypeName;
+}
+
QVariant QmlDebugPropertyReference::value() const
{
return m_value;
diff --git a/src/declarative/debugger/qmldebug.h b/src/declarative/debugger/qmldebug.h
index 681ee08..bd076ff 100644
--- a/src/declarative/debugger/qmldebug.h
+++ b/src/declarative/debugger/qmldebug.h
@@ -12,6 +12,7 @@ class QmlDebugObjectExpressionWatch;
class QmlDebugEnginesQuery;
class QmlDebugRootContextQuery;
class QmlDebugObjectQuery;
+class QmlDebugExpressionQuery;
class QmlDebugPropertyReference;
class QmlDebugContextReference;
class QmlDebugObjectReference;
@@ -44,6 +45,9 @@ public:
QObject *parent = 0);
QmlDebugObjectQuery *queryObjectRecursive(const QmlDebugObjectReference &,
QObject *parent = 0);
+ QmlDebugExpressionQuery *queryExpressionResult(int objectDebugId,
+ const QString &expr,
+ QObject *parent = 0);
private:
Q_DECLARE_PRIVATE(QmlEngineDebug)
@@ -228,6 +232,7 @@ public:
int objectDebugId() const;
QString name() const;
QVariant value() const;
+ QString valueTypeName() const;
QString binding() const;
bool hasNotifySignal() const;
@@ -236,6 +241,7 @@ private:
int m_objectDebugId;
QString m_name;
QVariant m_value;
+ QString m_valueTypeName;
QString m_binding;
bool m_hasNotifySignal;
};
@@ -287,4 +293,22 @@ private:
};
+class Q_DECLARATIVE_EXPORT QmlDebugExpressionQuery : public QmlDebugQuery
+{
+Q_OBJECT
+public:
+ virtual ~QmlDebugExpressionQuery();
+ QString expression() const;
+ QVariant result() const;
+private:
+ friend class QmlEngineDebug;
+ friend class QmlEngineDebugPrivate;
+ QmlDebugExpressionQuery(QObject *);
+ QmlEngineDebug *m_client;
+ int m_queryId;
+ QString m_expr;
+ QVariant m_result;
+
+};
+
#endif // QMLDEBUG_H
diff --git a/src/declarative/qml/qmlenginedebug.cpp b/src/declarative/qml/qmlenginedebug.cpp
index e20616a..7178e6c 100644
--- a/src/declarative/qml/qmlenginedebug.cpp
+++ b/src/declarative/qml/qmlenginedebug.cpp
@@ -80,7 +80,8 @@ QDataStream &operator>>(QDataStream &ds,
QDataStream &operator<<(QDataStream &ds,
const QmlEngineDebugServer::QmlObjectProperty &data)
{
- ds << (int)data.type << data.name << data.value << data.binding << data.hasNotifySignal;
+ ds << (int)data.type << data.name << data.value << data.valueTypeName
+ << data.binding << data.hasNotifySignal;
return ds;
}
@@ -88,7 +89,8 @@ QDataStream &operator>>(QDataStream &ds,
QmlEngineDebugServer::QmlObjectProperty &data)
{
int type;
- ds >> type >> data.name >> data.value >> data.binding >> data.hasNotifySignal;
+ ds >> type >> data.name >> data.value >> data.valueTypeName
+ >> data.binding >> data.hasNotifySignal;
data.type = (QmlEngineDebugServer::QmlObjectProperty::Type)type;
return ds;
}
@@ -101,6 +103,7 @@ QmlEngineDebugServer::propertyData(QObject *obj, int propIdx)
QMetaProperty prop = obj->metaObject()->property(propIdx);
rv.type = QmlObjectProperty::Unknown;
+ rv.valueTypeName = QString::fromUtf8(prop.typeName());
rv.name = prop.name();
rv.hasNotifySignal = prop.hasNotifySignal();
QmlAbstractBinding *binding = QmlMetaProperty(obj, rv.name).binding();
@@ -116,6 +119,7 @@ QmlEngineDebugServer::propertyData(QObject *obj, int propIdx)
QmlMetaType::isQmlList(prop.userType())) {
rv.type = QmlObjectProperty::List;
}
+
return rv;
}
@@ -149,7 +153,7 @@ void QmlEngineDebugServer::buildObjectList(QDataStream &message,
int ctxtId = QmlDebugService::idForObject(ctxt);
message << ctxtName << ctxtId;
-
+
int count = 0;
for (QSet<QmlContext *>::ConstIterator iter = p->childContexts.begin();
@@ -184,6 +188,32 @@ void QmlEngineDebugServer::buildObjectList(QDataStream &message,
}
}
+QVariant QmlEngineDebugServer::serializableVariant(const QVariant &value)
+{
+ if (value.type() < QVariant::UserType)
+ return value;
+
+ if (!value.toString().isEmpty())
+ return value.toString();
+
+ QVariant v;
+ if (value.type() == QVariant::UserType || QmlMetaType::isObject(value.userType())) {
+ QObject *o = QmlMetaType::toQObject(value);
+ if (o) {
+ QString objectName = o->objectName();
+ if (objectName.isEmpty())
+ objectName = QLatin1String("<unnamed>");
+ v = QString::fromUtf8(o->metaObject()->className()) +
+ QLatin1String(": ") + objectName;
+ }
+ }
+
+ if (v.isNull())
+ v = QString::fromUtf8(value.typeName());
+
+ return v;
+}
+
QmlEngineDebugServer::QmlObjectData
QmlEngineDebugServer::objectData(QObject *object)
{
@@ -310,29 +340,42 @@ void QmlEngineDebugServer::messageReceived(const QByteArray &message)
ds >> queryId;
m_watch->removeWatch(queryId);
+ } else if (type == "EVAL_EXPRESSION") {
+ int queryId;
+ int objectId;
+ QString expr;
+
+ ds >> queryId >> objectId >> expr;
+
+ QObject *object = QmlDebugService::objectForId(objectId);
+ QmlContext *context = qmlContext(object);
+ QVariant result;
+ if (object && context) {
+ QmlExpression *exprObj = new QmlExpression(context, expr, object);
+ bool undefined = false;
+ QVariant value = exprObj->value(&undefined);
+ if (undefined)
+ result = QLatin1String("<undefined>");
+ else
+ result = serializableVariant(value);
+ delete exprObj;
+ } else {
+ result = QLatin1String("<unknown context>");
+ }
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("EVAL_EXPRESSION_R") << queryId << result;
+
+ sendMessage(reply);
}
}
void QmlEngineDebugServer::propertyChanged(int id, int objectId, const QByteArray &property, const QVariant &value)
{
QByteArray reply;
- QVariant v;
+ QVariant v = serializableVariant(value);
QDataStream rs(&reply, QIODevice::WriteOnly);
-
- if (value.type() == QVariant::UserType || QmlMetaType::isObject(value.userType())) {
- QObject *o = QmlMetaType::toQObject(value);
- if (o) {
- QString objectName = o->objectName();
- if (objectName.isEmpty())
- objectName = QLatin1String("<unnamed>");
- v = QString::fromUtf8(o->metaObject()->className()) +
- QLatin1String(": ") + objectName;
- }
- if (v.isNull())
- v = value.toString();
- } else {
- v = value;
- }
rs << QByteArray("UPDATE_WATCH") << id << objectId << property << v;
diff --git a/src/declarative/qml/qmlenginedebug_p.h b/src/declarative/qml/qmlenginedebug_p.h
index e2f903c..075a711 100644
--- a/src/declarative/qml/qmlenginedebug_p.h
+++ b/src/declarative/qml/qmlenginedebug_p.h
@@ -85,6 +85,7 @@ public:
Type type;
QString name;
QVariant value;
+ QString valueTypeName;
QString binding;
bool hasNotifySignal;
};
@@ -103,6 +104,7 @@ private:
void buildObjectDump(QDataStream &, QObject *, bool);
QmlObjectData objectData(QObject *);
QmlObjectProperty propertyData(QObject *, int);
+ QVariant serializableVariant(const QVariant &value);
static QList<QmlEngine *> m_engines;
QmlWatcher *m_watch;
diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp
index 356c3c6..b07ee4c 100644
--- a/src/declarative/qml/qmlexpression.cpp
+++ b/src/declarative/qml/qmlexpression.cpp
@@ -281,7 +281,7 @@ void QmlExpressionPrivate::printException(QScriptEngine *scriptEngine)
}
}
-QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope)
+QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope, bool *isUndefined)
{
#ifdef Q_ENABLE_PERFORMANCE_LOG
QFxPerfTimer<QFxPerf::BindValueQt> perfqt;
@@ -318,6 +318,9 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope)
QScriptValue svalue = data->expressionFunction.call();
+ if (isUndefined)
+ *isUndefined = svalue.isUndefined();
+
if (scriptEngine->hasUncaughtException())
printException(scriptEngine);
@@ -355,7 +358,7 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope)
return rv;
}
-QVariant QmlExpressionPrivate::value(QObject *secondaryScope)
+QVariant QmlExpressionPrivate::value(QObject *secondaryScope, bool *isUndefined)
{
Q_Q(QmlExpression);
@@ -382,7 +385,7 @@ QVariant QmlExpressionPrivate::value(QObject *secondaryScope)
if (data->sse.isValid()) {
rv = evalSSE();
} else {
- rv = evalQtScript(secondaryScope);
+ rv = evalQtScript(secondaryScope, isUndefined);
}
ep->currentExpression = lastCurrentExpression;
@@ -406,11 +409,14 @@ QVariant QmlExpressionPrivate::value(QObject *secondaryScope)
/*!
Returns the value of the expression, or an invalid QVariant if the
expression is invalid or has an error.
+
+ \a isUndefined is set to true if the expression resulted in an
+ undefined value.
*/
-QVariant QmlExpression::value()
+QVariant QmlExpression::value(bool *isUndefined)
{
Q_D(QmlExpression);
- return d->value();
+ return d->value(0, isUndefined);
}
/*!
diff --git a/src/declarative/qml/qmlexpression.h b/src/declarative/qml/qmlexpression.h
index 73682f1..96694d6 100644
--- a/src/declarative/qml/qmlexpression.h
+++ b/src/declarative/qml/qmlexpression.h
@@ -83,7 +83,7 @@ public:
QObject *scopeObject() const;
public Q_SLOTS:
- QVariant value();
+ QVariant value(bool *isUndefined = 0);
Q_SIGNALS:
virtual void valueChanged();
diff --git a/src/declarative/qml/qmlexpression_p.h b/src/declarative/qml/qmlexpression_p.h
index d9bb27b..3ec8d1c 100644
--- a/src/declarative/qml/qmlexpression_p.h
+++ b/src/declarative/qml/qmlexpression_p.h
@@ -140,9 +140,9 @@ public:
QmlExpressionData *data;
- QVariant value(QObject *secondaryScope = 0);
+ QVariant value(QObject *secondaryScope = 0, bool *isUndefined = 0);
QVariant evalSSE();
- QVariant evalQtScript(QObject *secondaryScope);
+ QVariant evalQtScript(QObject *secondaryScope, bool *isUndefined = 0);
void updateGuards(const QPODVector<QmlEnginePrivate::CapturedProperty> &properties);
void clearGuards();
diff --git a/tools/qmldebugger/expressionquerywidget.cpp b/tools/qmldebugger/expressionquerywidget.cpp
new file mode 100644
index 0000000..b29b465
--- /dev/null
+++ b/tools/qmldebugger/expressionquerywidget.cpp
@@ -0,0 +1,216 @@
+#include <QtGui/qlabel.h>
+#include <QtGui/qtextedit.h>
+#include <QtGui/qlineedit.h>
+#include <QtGui/qpushbutton.h>
+#include <QtGui/qevent.h>
+#include <QtGui/qgroupbox.h>
+#include <QtGui/qtextobject.h>
+#include <QtGui/qlayout.h>
+
+#include "expressionquerywidget.h"
+
+ExpressionQueryWidget::ExpressionQueryWidget(QmlEngineDebug *client, QWidget *parent)
+ : QWidget(parent),
+ m_style(Compact),
+ m_client(client),
+ m_query(0),
+ m_groupBox(0),
+ m_textEdit(new QTextEdit),
+ m_lineEdit(0),
+ m_button(0)
+{
+ m_prompt = QLatin1String(">> ");
+
+ m_groupBox = new QGroupBox;
+ QVBoxLayout *vbox = new QVBoxLayout(m_groupBox);
+ vbox->addWidget(m_textEdit);
+
+ QVBoxLayout *layout = new QVBoxLayout(this);
+ layout->addWidget(m_groupBox);
+
+ updateTitle();
+
+ if (m_style == Compact) {
+ QHBoxLayout *hbox = new QHBoxLayout;
+ m_button = new QPushButton(tr("Execute"));
+ m_button->setEnabled(false);
+ connect(m_button, SIGNAL(clicked()), SLOT(executeExpression()));
+ m_lineEdit = new QLineEdit;
+ connect(m_lineEdit, SIGNAL(returnPressed()), SLOT(executeExpression()));
+ connect(m_lineEdit, SIGNAL(textChanged(QString)), SLOT(lineEditTextChanged(QString)));
+ hbox->addWidget(new QLabel(tr("Expression:")));
+ hbox->addWidget(m_lineEdit);
+ hbox->addWidget(m_button);
+ vbox->addLayout(hbox);
+
+ m_textEdit->setReadOnly(true);
+ m_lineEdit->installEventFilter(this);
+ } else {
+ m_textEdit->installEventFilter(this);
+ }
+}
+
+void ExpressionQueryWidget::updateTitle()
+{
+ if (m_currObject.debugId() < 0) {
+ m_groupBox->setTitle(tr("Expression queries"));
+ } else {
+ QString desc = QLatin1String("<")
+ + m_currObject.className() + QLatin1String(": ")
+ + (m_currObject.name().isEmpty() ? QLatin1String("<unnamed>") : m_currObject.name())
+ + QLatin1String(">");
+ m_groupBox->setTitle(tr("Expression queries (using context for %1)"
+ , "Selected object").arg(desc));
+ }
+}
+
+void ExpressionQueryWidget::appendPrompt()
+{
+ m_textEdit->moveCursor(QTextCursor::End);
+
+ if (m_style == Compact) {
+ m_textEdit->insertPlainText("\n");
+ } else {
+ m_textEdit->setTextColor(Qt::gray);
+ m_textEdit->append(m_prompt);
+ }
+}
+
+void ExpressionQueryWidget::setCurrentObject(const QmlDebugObjectReference &obj)
+{
+ m_currObject = obj;
+ updateTitle();
+}
+
+void ExpressionQueryWidget::checkCurrentContext()
+{
+ m_textEdit->moveCursor(QTextCursor::End);
+
+ if (m_currObject.debugId() != -1 && m_currObject.debugId() != m_objectAtLastFocus.debugId())
+ showCurrentContext();
+ m_objectAtLastFocus = m_currObject;
+}
+
+void ExpressionQueryWidget::showCurrentContext()
+{
+ m_textEdit->moveCursor(QTextCursor::End);
+ m_textEdit->setTextColor(Qt::darkGreen);
+ m_textEdit->append(m_currObject.className()
+ + QLatin1String(": ")
+ + (m_currObject.name().isEmpty() ? QLatin1String("<unnamed>") : m_currObject.name()));
+ appendPrompt();
+}
+
+void ExpressionQueryWidget::executeExpression()
+{
+ if (m_style == Compact)
+ m_expr = m_lineEdit->text().trimmed();
+ else
+ m_expr = m_expr.trimmed();
+
+ if (!m_expr.isEmpty() && m_currObject.debugId() != -1) {
+ if (m_query)
+ delete m_query;
+ m_query = m_client->queryExpressionResult(m_currObject.debugId(), m_expr, this);
+ if (!m_query->isWaiting())
+ showResult();
+ else
+ QObject::connect(m_query, SIGNAL(stateChanged(State)),
+ this, SLOT(showResult()));
+
+ m_lastExpr = m_expr;
+ if (m_lineEdit)
+ m_lineEdit->clear();
+ }
+}
+
+void ExpressionQueryWidget::showResult()
+{
+ if (m_query) {
+ m_textEdit->moveCursor(QTextCursor::End);
+ QString result;
+ if (m_query->result().isNull())
+ result = QLatin1String("<no value>");
+ else
+ result = m_query->result().toString();
+
+ if (m_style == Compact) {
+ m_textEdit->setTextColor(Qt::black);
+ m_textEdit->setFontWeight(QFont::Bold);
+ m_textEdit->insertPlainText(m_expr + " : ");
+ m_textEdit->setFontWeight(QFont::Normal);
+ m_textEdit->insertPlainText(result);
+ } else {
+ m_textEdit->append(result);
+ }
+ appendPrompt();
+ m_expr.clear();
+ }
+}
+
+void ExpressionQueryWidget::lineEditTextChanged(const QString &s)
+{
+ if (m_button)
+ m_button->setEnabled(!s.isEmpty());
+}
+
+bool ExpressionQueryWidget::eventFilter(QObject *obj, QEvent *event)
+{
+ if (obj == m_textEdit) {
+ switch (event->type()) {
+ case QEvent::KeyPress:
+ {
+ QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
+ int key = keyEvent->key();
+ if (key == Qt::Key_Return || key == Qt::Key_Enter) {
+ executeExpression();
+ return true;
+ } else if (key == Qt::Key_Backspace) {
+ // ensure m_expr doesn't contain backspace characters
+ QTextCursor cursor = m_textEdit->textCursor();
+ bool atLastLine = !(cursor.block().next().isValid());
+ if (!atLastLine)
+ return true;
+ if (cursor.columnNumber() <= m_prompt.count())
+ return true;
+ cursor.deletePreviousChar();
+ m_expr = cursor.block().text().mid(m_prompt.count());
+ return true;
+ } else {
+ m_textEdit->moveCursor(QTextCursor::End);
+ m_textEdit->setTextColor(Qt::black);
+ m_expr += keyEvent->text();
+ }
+ break;
+ }
+ case QEvent::FocusIn:
+ checkCurrentContext();
+ m_textEdit->moveCursor(QTextCursor::End);
+ break;
+ default:
+ break;
+ }
+ } else if (obj == m_lineEdit) {
+ switch (event->type()) {
+ case QEvent::KeyPress:
+ {
+ QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
+ int key = keyEvent->key();
+ if (key == Qt::Key_Up && m_lineEdit->text() != m_lastExpr) {
+ m_expr = m_lineEdit->text();
+ if (!m_lastExpr.isEmpty())
+ m_lineEdit->setText(m_lastExpr);
+ } else if (key == Qt::Key_Down) {
+ m_lineEdit->setText(m_expr);
+ }
+ break;
+ }
+ case QEvent::FocusIn:
+ checkCurrentContext();
+ break;
+ default:
+ break;
+ }
+ }
+ return QWidget::eventFilter(obj, event);
+}
diff --git a/tools/qmldebugger/expressionquerywidget.h b/tools/qmldebugger/expressionquerywidget.h
new file mode 100644
index 0000000..8db8f9f
--- /dev/null
+++ b/tools/qmldebugger/expressionquerywidget.h
@@ -0,0 +1,62 @@
+#ifndef EXPRESSIONQUERYWIDGET_H
+#define EXPRESSIONQUERYWIDGET_H
+
+#include <QWidget>
+
+#include <QtDeclarative/qmldebug.h>
+
+QT_BEGIN_NAMESPACE
+
+class QGroupBox;
+class QTextEdit;
+class QLineEdit;
+class QPushButton;
+
+class ExpressionQueryWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ enum Style {
+ Compact,
+ Shell
+ };
+
+ ExpressionQueryWidget(QmlEngineDebug *client, QWidget *parent = 0);
+
+protected:
+ bool eventFilter(QObject *obj, QEvent *event);
+
+public slots:
+ void setCurrentObject(const QmlDebugObjectReference &obj);
+
+private slots:
+ void executeExpression();
+ void showResult();
+ void lineEditTextChanged(const QString &s);
+
+private:
+ void appendPrompt();
+ void checkCurrentContext();
+ void showCurrentContext();
+ void updateTitle();
+
+ Style m_style;
+
+ QmlEngineDebug *m_client;
+ QmlDebugExpressionQuery *m_query;
+ QGroupBox *m_groupBox;
+ QTextEdit *m_textEdit;
+ QLineEdit *m_lineEdit;
+ QPushButton *m_button;
+ QString m_prompt;
+ QString m_expr;
+ QString m_lastExpr;
+
+ QmlDebugObjectReference m_currObject;
+ QmlDebugObjectReference m_objectAtLastFocus;
+};
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/tools/qmldebugger/objectpropertiesview.cpp b/tools/qmldebugger/objectpropertiesview.cpp
index f725194..61afe3f 100644
--- a/tools/qmldebugger/objectpropertiesview.cpp
+++ b/tools/qmldebugger/objectpropertiesview.cpp
@@ -22,12 +22,12 @@ public:
};
PropertiesViewItem::PropertiesViewItem(QTreeWidget *widget)
-: QTreeWidgetItem(widget)
+ : QTreeWidgetItem(widget)
{
}
PropertiesViewItem::PropertiesViewItem(QTreeWidgetItem *parent)
-: QTreeWidgetItem(parent)
+ : QTreeWidgetItem(parent)
{
}
@@ -108,8 +108,10 @@ void ObjectPropertiesView::setObject(const QmlDebugObjectReference &object)
item->setText(0, p.name());
item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
- if (!p.hasNotifySignal())
- item->setForeground(0, Qt::lightGray);
+ if (!p.hasNotifySignal()) {
+ item->setForeground(0, Qt::gray);
+ item->setForeground(1, Qt::gray);
+ }
if (!p.binding().isEmpty()) {
PropertiesViewItem *binding = new PropertiesViewItem(item);
@@ -159,15 +161,22 @@ void ObjectPropertiesView::valueChanged(const QByteArray &name, const QVariant &
{
for (int i=0; i<m_tree->topLevelItemCount(); i++) {
PropertiesViewItem *item = static_cast<PropertiesViewItem *>(m_tree->topLevelItem(i));
- if (item->property.name() == name)
- item->setText(1, value.toString());
+ if (item->property.name() == name) {
+ if (value.isNull()) {
+ item->setText(1, QLatin1String("<null>")
+ + QLatin1String(" : ")
+ + item->property.valueTypeName());
+ } else {
+ item->setText(1, value.toString());
+ }
+ }
}
}
void ObjectPropertiesView::itemActivated(QTreeWidgetItem *i)
{
PropertiesViewItem *item = static_cast<PropertiesViewItem *>(i);
- if (!item->property.name().isEmpty() && item->property.hasNotifySignal())
+ if (!item->property.name().isEmpty())
emit activated(m_object, item->property);
}
diff --git a/tools/qmldebugger/objecttree.cpp b/tools/qmldebugger/objecttree.cpp
index f68e7f1..0b92ceb 100644
--- a/tools/qmldebugger/objecttree.cpp
+++ b/tools/qmldebugger/objecttree.cpp
@@ -19,8 +19,8 @@ ObjectTree::ObjectTree(QmlEngineDebug *client, QWidget *parent)
{
setHeaderHidden(true);
- connect(this, SIGNAL(itemClicked(QTreeWidgetItem *, int)),
- this, SLOT(handleItemClicked(QTreeWidgetItem *)));
+ connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
+ this, SLOT(currentItemChanged(QTreeWidgetItem *)));
}
void ObjectTree::reload(int objectDebugId)
@@ -38,7 +38,7 @@ void ObjectTree::reload(int objectDebugId)
this, SLOT(objectFetched()));
}
-void ObjectTree::selectObject(int debugId)
+void ObjectTree::setCurrentObject(int debugId)
{
QTreeWidgetItem *item = findItemByObjectId(debugId);
if (item) {
@@ -57,14 +57,14 @@ void ObjectTree::objectFetched()
m_query = 0;
}
-void ObjectTree::handleItemClicked(QTreeWidgetItem *item)
+void ObjectTree::currentItemChanged(QTreeWidgetItem *item)
{
QmlDebugObjectReference obj = item->data(0, Qt::UserRole).value<QmlDebugObjectReference>();
if (obj.debugId() < 0) {
qWarning("QML Object Tree: bad object id");
return;
}
- emit objectSelected(obj);
+ emit currentObjectChanged(obj);
}
void ObjectTree::buildTree(const QmlDebugObjectReference &obj, QTreeWidgetItem *parent)
diff --git a/tools/qmldebugger/objecttree.h b/tools/qmldebugger/objecttree.h
index bba6c08..3c0a5c6 100644
--- a/tools/qmldebugger/objecttree.h
+++ b/tools/qmldebugger/objecttree.h
@@ -20,19 +20,19 @@ public:
ObjectTree(QmlEngineDebug *client, QWidget *parent = 0);
signals:
- void objectSelected(const QmlDebugObjectReference &);
+ void currentObjectChanged(const QmlDebugObjectReference &);
void expressionWatchRequested(const QmlDebugObjectReference &, const QString &);
public slots:
void reload(int objectDebugId);
- void selectObject(int debugId);
+ void setCurrentObject(int debugId);
protected:
virtual void mousePressEvent(QMouseEvent *);
private slots:
void objectFetched();
- void handleItemClicked(QTreeWidgetItem *);
+ void currentItemChanged(QTreeWidgetItem *);
private:
QTreeWidgetItem *findItemByObjectId(int debugId) const;
diff --git a/tools/qmldebugger/qmldebugger.cpp b/tools/qmldebugger/qmldebugger.cpp
index 0f0fc03..e0a76b6 100644
--- a/tools/qmldebugger/qmldebugger.cpp
+++ b/tools/qmldebugger/qmldebugger.cpp
@@ -57,6 +57,10 @@ QmlDebugger::QmlDebugger(QWidget *parent)
QObject::connect(&client, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(connectionError(QAbstractSocket::SocketError)));
+
+
+ m_tabs->setCurrentIndex(1);
+ connectToHost();
}
void QmlDebugger::setHost(const QString &host)
diff --git a/tools/qmldebugger/qmldebugger.pri b/tools/qmldebugger/qmldebugger.pri
index ce36381..c49d334 100644
--- a/tools/qmldebugger/qmldebugger.pri
+++ b/tools/qmldebugger/qmldebugger.pri
@@ -7,7 +7,8 @@ HEADERS += $$PWD/qmldebugger.h \
$$PWD/watchtable.h \
$$PWD/engine.h \
$$PWD/objecttree.h \
- $$PWD/objectpropertiesview.h
+ $$PWD/objectpropertiesview.h \
+ $$PWD/expressionquerywidget.h
SOURCES += $$PWD/qmldebugger.cpp \
$$PWD/main.cpp \
@@ -15,7 +16,8 @@ SOURCES += $$PWD/qmldebugger.cpp \
$$PWD/watchtable.cpp \
$$PWD/engine.cpp \
$$PWD/objecttree.cpp \
- $$PWD/objectpropertiesview.cpp
+ $$PWD/objectpropertiesview.cpp \
+ $$PWD/expressionquerywidget.cpp
RESOURCES += $$PWD/qmldebugger.qrc
diff --git a/tools/qmldebugger/watchtable.cpp b/tools/qmldebugger/watchtable.cpp
index e4163dc..512bfb2 100644
--- a/tools/qmldebugger/watchtable.cpp
+++ b/tools/qmldebugger/watchtable.cpp
@@ -193,6 +193,9 @@ void WatchTableModel::addValue(int column, const QVariant &value)
void WatchTableModel::togglePropertyWatch(const QmlDebugObjectReference &object, const QmlDebugPropertyReference &property)
{
+ if (!property.hasNotifySignal())
+ return;
+
QmlDebugWatch *watch = findWatch(object.debugId(), property.name());
if (watch) {
// watch will be deleted in watchStateChanged()
diff --git a/tools/qmlviewer/qmlviewer.cpp b/tools/qmlviewer/qmlviewer.cpp
index 07b68ea..a8034cf 100644
--- a/tools/qmlviewer/qmlviewer.cpp
+++ b/tools/qmlviewer/qmlviewer.cpp
@@ -630,6 +630,11 @@ void QmlViewer::openQml(const QString& fileName)
QUrl url(fileName);
QFileInfo fi(fileName);
if (fi.exists()) {
+ if (fi.suffix().toLower() != QLatin1String("qml")) {
+ qWarning() << "qmlviewer cannot open non-QML file" << fileName;
+ return;
+ }
+
url = QUrl::fromLocalFile(fi.absoluteFilePath());
QmlContext *ctxt = canvas->rootContext();
QDir dir(fi.path()+"/dummydata", "*.qml");
@@ -658,6 +663,9 @@ void QmlViewer::openQml(const QString& fileName)
dummyData->setParent(this);
}
}
+ } else {
+ qWarning() << "qmlviewer cannot find file:" << fileName;
+ return;
}
canvas->setUrl(url);