summaryrefslogtreecommitdiffstats
path: root/src/declarative
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative')
-rw-r--r--src/declarative/debugger/qmldebugger.cpp153
-rw-r--r--src/declarative/debugger/qmldebugger.h12
-rw-r--r--src/declarative/qml/qmlengine.cpp36
-rw-r--r--src/declarative/qml/qmlengine_p.h11
-rw-r--r--src/declarative/qml/qmlmetaproperty.cpp12
-rw-r--r--src/declarative/qml/qmlmetaproperty.h1
6 files changed, 185 insertions, 40 deletions
diff --git a/src/declarative/debugger/qmldebugger.cpp b/src/declarative/debugger/qmldebugger.cpp
index 033a15f..9b84b9e 100644
--- a/src/declarative/debugger/qmldebugger.cpp
+++ b/src/declarative/debugger/qmldebugger.cpp
@@ -43,6 +43,8 @@
#include <QtGui/qtreewidget.h>
#include <QtGui/qboxlayout.h>
#include <QtGui/qplaintextedit.h>
+#include <QTextBlock>
+#include <QtGui/qtabwidget.h>
#include <QtDeclarative/qmlbindablevalue.h>
#include <private/qmlboundsignal_p.h>
#include <private/qmlcontext_p.h>
@@ -52,10 +54,11 @@
#include <QtCore/qurl.h>
#include <QtGui/qsplitter.h>
#include <QtGui/qpushbutton.h>
+#include <QtGui/qtablewidget.h>
#include <QtGui/qevent.h>
QmlDebugger::QmlDebugger(QWidget *parent)
-: QWidget(parent), m_tree(0)
+: QWidget(parent), m_tree(0), m_warnings(0), m_watchers(0), m_text(0)
{
QHBoxLayout *layout = new QHBoxLayout;
setLayout(layout);
@@ -69,18 +72,33 @@ QmlDebugger::QmlDebugger(QWidget *parent)
splitter->addWidget(treeWid);
m_tree = new QTreeWidget(treeWid);
+ m_tree->setSelectionMode(QTreeWidget::NoSelection);
m_tree->setHeaderHidden(true);
- QObject::connect(m_tree, SIGNAL(itemPressed(QTreeWidgetItem *, int)), this, SLOT(itemPressed(QTreeWidgetItem *)));
+ QObject::connect(m_tree, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this, SLOT(itemClicked(QTreeWidgetItem *)));
+ QObject::connect(m_tree, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(itemDoubleClicked(QTreeWidgetItem *)));
vlayout->addWidget(m_tree);
QPushButton *pb = new QPushButton("Refresh", treeWid);
QObject::connect(pb, SIGNAL(clicked()), this, SLOT(refresh()));
vlayout->addWidget(pb);
+ QTabWidget *tabs = new QTabWidget(this);
+
m_text = new QPlainTextEdit(this);
m_text->setReadOnly(true);
- splitter->addWidget(m_text);
+ tabs->addTab(m_text, "File");
+
+ m_warnings = new QTreeWidget(this);
+ m_warnings->setHeaderHidden(true);
+ tabs->addTab(m_warnings, "Warnings");
+
+ m_watchers = new QTableWidget(this);
+ tabs->addTab(m_watchers, "Watchers");
+
+ splitter->addWidget(tabs);
splitter->setStretchFactor(1, 2);
+
+ setGeometry(0, 100, 800, 600);
}
class QmlDebuggerItem : public QTreeWidgetItem
@@ -103,31 +121,29 @@ public:
QPointer<QmlBindableValue> bindableValue;
};
-void QmlDebugger::itemPressed(QTreeWidgetItem *i)
+void QmlDebugger::itemDoubleClicked(QTreeWidgetItem *i)
{
QmlDebuggerItem *item = static_cast<QmlDebuggerItem *>(i);
if(item->bindableValue) {
- QString str;
-
QmlExpressionPrivate *p = item->bindableValue->d;
- if(p->log) {
- QString str;
- QDebug d(&str);
- for(int ii = 0; ii < p->log->count(); ++ii) {
- d << p->log->at(ii).result() << "\n";
- QStringList warnings = p->log->at(ii).warnings();
- foreach(const QString &warning, warnings)
- d << " " << warning << "\n";
- }
- m_text->setPlainText(str);
+ if(m_watchedIds.contains(p->id)) {
+ m_watchedIds.remove(p->id);
+ item->setForeground(0, Qt::green);
} else {
- m_text->setPlainText("No history");
+ m_watchedIds.insert(p->id);
+ item->setForeground(0, QColor("purple"));
}
- } else if(item->url.scheme() == QLatin1String("file")) {
+ }
+}
+
+void QmlDebugger::itemClicked(QTreeWidgetItem *i)
+{
+ QmlDebuggerItem *item = static_cast<QmlDebuggerItem *>(i);
+ if(item->url.scheme() == QLatin1String("file")) {
QString f = item->url.toLocalFile();
QFile file(f);
file.open(QIODevice::ReadOnly);
@@ -141,17 +157,11 @@ void QmlDebugger::itemPressed(QTreeWidgetItem *i)
QTextDocument *document = m_text->document();
QTextCharFormat format;
format.setForeground(Qt::lightGray);
- {
- QTextCursor cursor(document);
- cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
- cursor.movePosition(QTextCursor::Down, QTextCursor::KeepAnchor, item->startLine - 1);
- cursor.setCharFormat(format);
- }
{
QTextCursor cursor(document);
cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
- cursor.movePosition(QTextCursor::Down, QTextCursor::MoveAnchor, item->endLine);
+ cursor.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor, item->endLine);
cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
cursor.setCharFormat(format);
}
@@ -159,31 +169,87 @@ void QmlDebugger::itemPressed(QTreeWidgetItem *i)
{
QTextCursor cursor(document);
cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
- cursor.setCharFormat(QTextCharFormat());
+ cursor.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor, item->startLine - 1);
+ cursor.setCharFormat(format);
}
{
QTextCursor cursor(document);
cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
- cursor.movePosition(QTextCursor::Down, QTextCursor::MoveAnchor, item->startLine - 1);
+ cursor.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor, item->startLine - 1);
m_text->setTextCursor(cursor);
m_text->centerCursor();
}
+
+
}
}
}
-static bool makeItem(QObject *obj, QmlDebuggerItem *item)
+bool QmlDebugger::makeItem(QObject *obj, QmlDebuggerItem *item)
{
bool rv = true;
QString text;
if(QmlBindableValue *bv = qobject_cast<QmlBindableValue *>(obj)) {
+ QmlExpressionPrivate *p = bv->d;
+
text = bv->property().name() + ": " + bv->expression();
- item->setForeground(0, Qt::green);
+ bool watched = m_watchedIds.contains(p->id);
+ if(watched)
+ item->setForeground(0, QColor("purple"));
+ else
+ item->setForeground(0, Qt::green);
item->bindableValue = bv;
+
+ if(p->log) {
+ QTreeWidgetItem *warningItem = 0;
+
+ int column = m_watchers->columnCount();
+
+ if(watched) {
+ m_watchers->insertColumn(column);
+ QTableWidgetItem *tableheader = new QTableWidgetItem;
+ tableheader->setText(bv->expression());
+ tableheader->setToolTip(bv->expression());
+ m_watchers->setHorizontalHeaderItem(column, tableheader);
+ }
+
+ for(int ii = 0; ii < p->log->count(); ++ii) {
+ const QmlExpressionLog &log = p->log->at(ii);
+
+ QString variant; QDebug d(&variant); d << log.result();
+ if(watched) {
+ QString str = log.result().toString();
+ if(str.isEmpty())
+ str = variant;
+ m_expressions << qMakePair(log.time(), qMakePair(column, str));
+ }
+
+ if(!log.warnings().isEmpty()) {
+
+ if(!warningItem) {
+ warningItem = new QTreeWidgetItem(m_warnings);
+ warningItem->setText(0, bv->expression());
+ }
+
+ QTreeWidgetItem *entry = new QTreeWidgetItem(warningItem);
+ entry->setExpanded(true);
+
+ entry->setText(0, variant);
+
+ foreach(const QString &warning, log.warnings()) {
+ QTreeWidgetItem *w = new QTreeWidgetItem(entry);
+ w->setText(0, warning);
+ }
+ }
+
+ }
+
+ }
+
} else if(QmlBoundSignal *bs = qobject_cast<QmlBoundSignal *>(obj)) {
QMetaMethod method = obj->parent()->metaObject()->method(bs->index());
QByteArray sig = method.signature();
@@ -237,7 +303,7 @@ static bool makeItem(QObject *obj, QmlDebuggerItem *item)
return rv;
}
-static void buildTree(QObject *obj, QmlDebuggerItem *parent)
+void QmlDebugger::buildTree(QObject *obj, QmlDebuggerItem *parent)
{
QObjectList children = obj->children();
@@ -253,9 +319,20 @@ void QmlDebugger::refresh()
setDebugObject(m_object);
}
+bool operator<(const QPair<quint32, QPair<int, QString> > &lhs,
+ const QPair<quint32, QPair<int, QString> > &rhs)
+{
+ return lhs.first < rhs.first;
+}
+
void QmlDebugger::setDebugObject(QObject *obj)
{
m_tree->clear();
+ m_warnings->clear();
+ m_watchers->clear();
+ m_watchers->setColumnCount(0);
+ m_watchers->setRowCount(0);
+ m_expressions.clear();
m_object = obj;
if(!obj)
@@ -265,6 +342,20 @@ void QmlDebugger::setDebugObject(QObject *obj)
makeItem(obj, item);
buildTree(obj, item);
item->setExpanded(true);
- setGeometry(0, 100, 800, 600);
+
+ m_watchers->setRowCount(m_expressions.count());
+
+ qSort(m_expressions.begin(), m_expressions.end());
+
+ for(int ii = 0; ii < m_expressions.count(); ++ii) {
+
+ const QPair<quint32, QPair<int, QString> > &expr = m_expressions.at(ii);
+ QTableWidgetItem *item = new QTableWidgetItem;
+ item->setText(expr.second.second);
+ m_watchers->setItem(ii, expr.second.first, item);
+
+ }
+
+
}
diff --git a/src/declarative/debugger/qmldebugger.h b/src/declarative/debugger/qmldebugger.h
index 943abef..e04eb2e 100644
--- a/src/declarative/debugger/qmldebugger.h
+++ b/src/declarative/debugger/qmldebugger.h
@@ -43,6 +43,7 @@
#define QMLDEBUGGER_H
#include <QtCore/qpointer.h>
+#include <QtCore/qset.h>
#include <QtGui/qwidget.h>
QT_BEGIN_HEADER
@@ -54,6 +55,8 @@ QT_MODULE(Declarative)
class QTreeWidget;
class QTreeWidgetItem;
class QPlainTextEdit;
+class QmlDebuggerItem;
+class QTableWidget;
class QmlDebugger : public QWidget
{
Q_OBJECT
@@ -66,12 +69,19 @@ public slots:
void refresh();
private slots:
- void itemPressed(QTreeWidgetItem *);
+ void itemClicked(QTreeWidgetItem *);
+ void itemDoubleClicked(QTreeWidgetItem *);
private:
+ void buildTree(QObject *obj, QmlDebuggerItem *parent);
+ bool makeItem(QObject *obj, QmlDebuggerItem *item);
QTreeWidget *m_tree;
+ QTreeWidget *m_warnings;
+ QTableWidget *m_watchers;
QPlainTextEdit *m_text;
QPointer<QObject> m_object;
+ QList<QPair<quint32, QPair<int, QString> > > m_expressions;
+ QSet<quint32> m_watchedIds;
};
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp
index be5226e..15b5879 100644
--- a/src/declarative/qml/qmlengine.cpp
+++ b/src/declarative/qml/qmlengine.cpp
@@ -139,7 +139,7 @@ QStack<QmlEngine *> *QmlEngineStack::engines()
QmlEnginePrivate::QmlEnginePrivate(QmlEngine *e)
: rootContext(0), currentBindContext(0), currentExpression(0), q(e),
- rootComponent(0), networkAccessManager(0), typeManager(e)
+ rootComponent(0), networkAccessManager(0), typeManager(e), uniqueId(1)
{
QScriptValue proto = scriptEngine.newObject();
proto.setProperty(QLatin1String("emit"),
@@ -720,17 +720,17 @@ QmlEngine *QmlEngine::activeEngine()
QmlExpressionPrivate::QmlExpressionPrivate(QmlExpression *b)
-: q(b), ctxt(0), sseData(0), proxy(0), me(0), trackChange(false), log(0)
+: q(b), ctxt(0), sseData(0), proxy(0), me(0), trackChange(false), id(0), log(0)
{
}
QmlExpressionPrivate::QmlExpressionPrivate(QmlExpression *b, void *expr, QmlRefCount *rc)
-: q(b), ctxt(0), sse((const char *)expr, rc), sseData(0), proxy(0), me(0), trackChange(true), log(0)
+: q(b), ctxt(0), sse((const char *)expr, rc), sseData(0), proxy(0), me(0), trackChange(true), id(0), log(0)
{
}
QmlExpressionPrivate::QmlExpressionPrivate(QmlExpression *b, const QString &expr, bool ssecompile)
-: q(b), ctxt(0), expression(expr), sseData(0), proxy(0), me(0), trackChange(true), log(0)
+: q(b), ctxt(0), expression(expr), sseData(0), proxy(0), me(0), trackChange(true), id(0), log(0)
{
if (ssecompile) {
#ifdef Q_ENABLE_PERFORMANCE_LOG
@@ -765,6 +765,8 @@ QmlExpression::QmlExpression(QmlContext *ctxt, void *expr,
: d(new QmlExpressionPrivate(this, expr, rc))
{
d->ctxt = ctxt;
+ if(ctxt && ctxt->engine())
+ d->id = ctxt->engine()->d_func()->getUniqueId();
d->me = me;
}
@@ -774,6 +776,8 @@ QmlExpression::QmlExpression(QmlContext *ctxt, const QString &expr,
: d(new QmlExpressionPrivate(this, expr, ssecompile))
{
d->ctxt = ctxt;
+ if(ctxt && ctxt->engine())
+ d->id = ctxt->engine()->d_func()->getUniqueId();
d->me = me;
}
@@ -789,6 +793,8 @@ QmlExpression::QmlExpression(QmlContext *ctxt, const QString &expression,
: d(new QmlExpressionPrivate(this, expression, true))
{
d->ctxt = ctxt;
+ if(ctxt && ctxt->engine())
+ d->id = ctxt->engine()->d_func()->getUniqueId();
d->me = scope;
}
@@ -810,7 +816,7 @@ QmlEngine *QmlExpression::engine() const
}
/*!
- Returns teh QmlContext this expression is associated with, or 0 if there
+ Returns the QmlContext this expression is associated with, or 0 if there
is no association or the QmlContext has been destroyed.
*/
QmlContext *QmlExpression::context() const
@@ -988,6 +994,7 @@ QVariant QmlExpression::value()
if(qmlDebugger()) {
QmlExpressionLog log;
+ log.setTime(engine()->d_func()->getUniqueId());
log.setExpression(expression());
log.setResult(rv);
@@ -997,8 +1004,8 @@ QVariant QmlExpression::value()
if (prop.hasChangedNotifier()) {
prop.connectNotifier(d->proxy, changedIndex);
- } else {
- QString warn = QLatin1String("Expression depends on property without a NOTIFY signal: ") + QLatin1String(prop.object()->metaObject()->className()) + QLatin1String(".") + prop.name();
+ } else if (prop.needsChangedNotifier()) {
+ QString warn = QLatin1String("Expression depends on property without a NOTIFY signal: [") + QLatin1String(prop.object()->metaObject()->className()) + QLatin1String("].") + prop.name();
log.addWarning(warn);
}
}
@@ -1015,6 +1022,7 @@ QVariant QmlExpression::value()
}
} else {
QmlExpressionLog log;
+ log.setTime(engine()->d_func()->getUniqueId());
log.setExpression(expression());
log.setResult(rv);
d->addLog(log);
@@ -1023,6 +1031,7 @@ QVariant QmlExpression::value()
} else {
if(qmlDebugger()) {
QmlExpressionLog log;
+ log.setTime(engine()->d_func()->getUniqueId());
log.setExpression(expression());
log.setResult(rv);
d->addLog(log);
@@ -1421,7 +1430,8 @@ QmlExpressionLog::QmlExpressionLog()
}
QmlExpressionLog::QmlExpressionLog(const QmlExpressionLog &o)
-: m_expression(o.m_expression),
+: m_time(o.m_time),
+ m_expression(o.m_expression),
m_result(o.m_result),
m_warnings(o.m_warnings)
{
@@ -1433,12 +1443,22 @@ QmlExpressionLog::~QmlExpressionLog()
QmlExpressionLog &QmlExpressionLog::operator=(const QmlExpressionLog &o)
{
+ m_time = o.m_time;
m_expression = o.m_expression;
m_result = o.m_result;
m_warnings = o.m_warnings;
return *this;
}
+void QmlExpressionLog::setTime(quint32 time)
+{
+ m_time = time;
+}
+
+quint32 QmlExpressionLog::time() const
+{
+ return m_time;
+}
QString QmlExpressionLog::expression() const
{
diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h
index 7d5176e..63df0ba 100644
--- a/src/declarative/qml/qmlengine_p.h
+++ b/src/declarative/qml/qmlengine_p.h
@@ -114,6 +114,11 @@ public:
QmlCompositeTypeManager typeManager;
QMap<QString,QString> nameSpacePaths;
+
+ mutable quint32 uniqueId;
+ quint32 getUniqueId() const {
+ return uniqueId++;
+ }
};
@@ -201,6 +206,9 @@ public:
QmlExpressionLog &operator=(const QmlExpressionLog &);
+ void setTime(quint32);
+ quint32 time() const;
+
QString expression() const;
void setExpression(const QString &);
@@ -211,6 +219,7 @@ public:
void setResult(const QVariant &);
private:
+ quint32 m_time;
QString m_expression;
QVariant m_result;
QStringList m_warnings;
@@ -233,6 +242,8 @@ public:
QObject *me;
bool trackChange;
+ quint32 id;
+
void addLog(const QmlExpressionLog &);
QList<QmlExpressionLog> *log;
};
diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp
index 40c9b0e..59d6b38 100644
--- a/src/declarative/qml/qmlmetaproperty.cpp
+++ b/src/declarative/qml/qmlmetaproperty.cpp
@@ -988,6 +988,18 @@ bool QmlMetaProperty::hasChangedNotifier() const
}
/*!
+ Returns true if the property needs a change notifier signal for bindings
+ to remain upto date, false otherwise.
+
+ Some properties, such as attached properties or those whose value never
+ changes, do not require a change notifier.
+*/
+bool QmlMetaProperty::needsChangedNotifier() const
+{
+ return type() & Property && !(type() & Attached);
+}
+
+/*!
Connects the property's change notifier signal to the
specified \a method of the \a dest object and returns
true. Returns false if this metaproperty does not
diff --git a/src/declarative/qml/qmlmetaproperty.h b/src/declarative/qml/qmlmetaproperty.h
index 4836038..68b06e5 100644
--- a/src/declarative/qml/qmlmetaproperty.h
+++ b/src/declarative/qml/qmlmetaproperty.h
@@ -89,6 +89,7 @@ public:
void emitSignal();
bool hasChangedNotifier() const;
+ bool needsChangedNotifier() const;
bool connectNotifier(QObject *dest, const char *slot) const;
bool connectNotifier(QObject *dest, int method) const;