From 242410e288280b9bcf8f3b68fa362be44e4c8813 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 8 May 2009 12:22:17 +1000 Subject: Tweak debugger watches --- src/declarative/debugger/debugger.pri | 6 +- src/declarative/debugger/qmldebugger.cpp | 84 ++------- src/declarative/debugger/qmldebugger.h | 8 +- src/declarative/debugger/qmlpropertyview.cpp | 97 +++++++++- src/declarative/debugger/qmlpropertyview_p.h | 6 +- src/declarative/debugger/qmlwatches.cpp | 267 +++++++++++++++++++++++++++ src/declarative/debugger/qmlwatches_p.h | 99 ++++++++++ src/declarative/qml/qmlengine.cpp | 11 ++ src/declarative/qml/qmlexpression.h | 1 + 9 files changed, 499 insertions(+), 80 deletions(-) create mode 100644 src/declarative/debugger/qmlwatches.cpp create mode 100644 src/declarative/debugger/qmlwatches_p.h diff --git a/src/declarative/debugger/debugger.pri b/src/declarative/debugger/debugger.pri index 31a1d5b..bf693d9 100644 --- a/src/declarative/debugger/debugger.pri +++ b/src/declarative/debugger/debugger.pri @@ -1,7 +1,9 @@ SOURCES += debugger/qmldebugger.cpp \ debugger/qmldebuggerstatus.cpp \ - debugger/qmlpropertyview.cpp + debugger/qmlpropertyview.cpp \ + debugger/qmlwatches.cpp HEADERS += debugger/qmldebugger.h \ debugger/qmldebuggerstatus.h \ - debugger/qmlpropertyview_p.h + debugger/qmlpropertyview_p.h \ + debugger/qmlwatches_p.h diff --git a/src/declarative/debugger/qmldebugger.cpp b/src/declarative/debugger/qmldebugger.cpp index 634385b..250f451 100644 --- a/src/declarative/debugger/qmldebugger.cpp +++ b/src/declarative/debugger/qmldebugger.cpp @@ -58,10 +58,11 @@ #include #include #include +#include QmlDebugger::QmlDebugger(QWidget *parent) -: QWidget(parent), m_tree(0), m_warnings(0), m_watchers(0), m_properties(0), - m_text(0) +: QWidget(parent), m_tree(0), m_warnings(0), m_watchTable(0), m_watches(0), + m_properties(0), m_text(0) { QHBoxLayout *layout = new QHBoxLayout; setLayout(layout); @@ -75,7 +76,6 @@ 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(itemClicked(QTreeWidgetItem *, int)), this, SLOT(itemClicked(QTreeWidgetItem *))); QObject::connect(m_tree, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(itemDoubleClicked(QTreeWidgetItem *))); @@ -95,11 +95,13 @@ QmlDebugger::QmlDebugger(QWidget *parent) m_warnings->setHeaderHidden(true); tabs->addTab(m_warnings, "Warnings"); - m_watchers = new QTableWidget(this); - m_watchers->setSelectionMode(QTableWidget::NoSelection); - tabs->addTab(m_watchers, "Watchers"); + m_watches = new QmlWatches(this); + m_watchTable = new QTableView(this); + m_watchTable->setSelectionMode(QTableWidget::NoSelection); + m_watchTable->setModel(m_watches); + tabs->addTab(m_watchTable, "Watches"); - m_properties = new QmlPropertyView(this); + m_properties = new QmlPropertyView(m_watches, this); tabs->addTab(m_properties, "Properties"); splitter->addWidget(tabs); @@ -131,21 +133,6 @@ public: void QmlDebugger::itemDoubleClicked(QTreeWidgetItem *i) { - QmlDebuggerItem *item = static_cast(i); - - if(item->bindableValue) { - - QmlExpressionPrivate *p = item->bindableValue->d; - - if(m_watchedIds.contains(p->id)) { - m_watchedIds.remove(p->id); - item->setForeground(0, Qt::green); - } else { - m_watchedIds.insert(p->id); - item->setForeground(0, QColor("purple")); - } - - } } void QmlDebugger::itemClicked(QTreeWidgetItem *i) @@ -227,36 +214,16 @@ bool QmlDebugger::makeItem(QObject *obj, QmlDebuggerItem *item) QmlExpressionPrivate *p = bv->d; text = bv->property().name() + ": " + bv->expression(); - bool watched = m_watchedIds.contains(p->id); - if(watched) - item->setForeground(0, QColor("purple")); - else - item->setForeground(0, Qt::green); + 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()) { @@ -280,14 +247,12 @@ bool QmlDebugger::makeItem(QObject *obj, QmlDebuggerItem *item) } + delete item; + return false; + } else if(QmlBoundSignal *bs = qobject_cast(obj)) { - QMetaMethod method = obj->parent()->metaObject()->method(bs->index()); - QByteArray sig = method.signature(); - if(!sig.isEmpty()) - text = sig + ": "; - text += bs->expression(); - item->setForeground(0, Qt::blue); - rv = false; + delete item; + return false; } else { QmlContext *context = qmlContext(obj); QmlContext *parentContext = qmlContext(obj->parent()); @@ -359,10 +324,6 @@ 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) @@ -372,20 +333,5 @@ void QmlDebugger::setDebugObject(QObject *obj) makeItem(obj, item); buildTree(obj, item); item->setExpanded(true); - - m_watchers->setRowCount(m_expressions.count()); - - qSort(m_expressions.begin(), m_expressions.end()); - - for(int ii = 0; ii < m_expressions.count(); ++ii) { - - const QPair > &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 35ff92c..776ded3 100644 --- a/src/declarative/debugger/qmldebugger.h +++ b/src/declarative/debugger/qmldebugger.h @@ -56,8 +56,9 @@ class QTreeWidget; class QTreeWidgetItem; class QPlainTextEdit; class QmlDebuggerItem; -class QTableWidget; +class QTableView; class QmlPropertyView; +class QmlWatches; class QmlDebugger : public QWidget { Q_OBJECT @@ -78,12 +79,11 @@ private: bool makeItem(QObject *obj, QmlDebuggerItem *item); QTreeWidget *m_tree; QTreeWidget *m_warnings; - QTableWidget *m_watchers; + QTableView *m_watchTable; + QmlWatches *m_watches; QmlPropertyView *m_properties; QPlainTextEdit *m_text; QPointer m_object; - QList > > m_expressions; - QSet m_watchedIds; QPointer m_selectedItem; }; diff --git a/src/declarative/debugger/qmlpropertyview.cpp b/src/declarative/debugger/qmlpropertyview.cpp index 2434c58..b46a1bf 100644 --- a/src/declarative/debugger/qmlpropertyview.cpp +++ b/src/declarative/debugger/qmlpropertyview.cpp @@ -43,9 +43,12 @@ #include #include #include +#include +#include +#include -QmlPropertyView::QmlPropertyView(QWidget *parent) -: QWidget(parent), m_tree(0) +QmlPropertyView::QmlPropertyView(QmlWatches *watches, QWidget *parent) +: QWidget(parent), m_tree(0), m_watches(watches) { QVBoxLayout *layout = new QVBoxLayout; layout->setContentsMargins(0, 0, 0, 0); @@ -54,6 +57,8 @@ QmlPropertyView::QmlPropertyView(QWidget *parent) m_tree = new QTreeWidget(this); m_tree->setHeaderLabels(QStringList() << "Property" << "Value"); + QObject::connect(m_tree, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), + this, SLOT(itemDoubleClicked(QTreeWidgetItem *))); m_tree->setColumnCount(2); @@ -65,16 +70,24 @@ class QmlPropertyViewItem : public QObject, public QTreeWidgetItem Q_OBJECT public: QmlPropertyViewItem(QTreeWidget *widget); + QmlPropertyViewItem(QTreeWidgetItem *parent); QObject *object; QMetaProperty property; + quint32 exprId; + public slots: void refresh(); }; QmlPropertyViewItem::QmlPropertyViewItem(QTreeWidget *widget) -: QTreeWidgetItem(widget) +: QTreeWidgetItem(widget), object(0), exprId(0) +{ +} + +QmlPropertyViewItem::QmlPropertyViewItem(QTreeWidgetItem *parent) +: QTreeWidgetItem(parent), object(0), exprId(0) { } @@ -83,6 +96,33 @@ void QmlPropertyViewItem::refresh() setText(1, property.read(object).toString()); } +void QmlPropertyView::itemDoubleClicked(QTreeWidgetItem *i) +{ + QmlPropertyViewItem *item = static_cast(i); + + if(item->object) { + quint32 objectId = m_watches->objectId(item->object); + + if(m_watches->hasWatch(objectId, item->property.name())) { + m_watches->remWatch(objectId, item->property.name()); + item->setForeground(0, Qt::black); + } else { + m_watches->addWatch(objectId, item->property.name()); + item->setForeground(0, Qt::red); + } + } else if(item->exprId) { + + if(m_watches->hasWatch(item->exprId)) { + m_watches->remWatch(item->exprId); + item->setForeground(1, Qt::green); + } else { + m_watches->addWatch(item->exprId); + item->setForeground(1, Qt::darkGreen); + } + + } +} + void QmlPropertyView::setObject(QObject *object) { m_object = object; @@ -91,15 +131,38 @@ void QmlPropertyView::setObject(QObject *object) if(!m_object) return; + QMultiHash > bindings; + QHash sigs; + QObjectList children = object->children(); + + foreach(QObject *child, children) { + if(QmlBindableValue *value = qobject_cast(child)) { + bindings.insert(value->property().name().toUtf8(), qMakePair(value->expression(), value->id())); + } else if(QmlBoundSignal *signal = qobject_cast(child)) { + QMetaMethod method = object->metaObject()->method(signal->index()); + QByteArray sig = method.signature(); + sigs.insert(sig, signal->expression()); + } + } + + quint32 objectId = m_watches->objectId(object); + const QMetaObject *mo = object->metaObject(); for(int ii = 0; ii < mo->propertyCount(); ++ii) { + QMetaProperty p = mo->property(ii); + + if(QmlMetaType::isList(p.userType()) || + QmlMetaType::isQmlList(p.userType())) + continue; + QmlPropertyViewItem *item = new QmlPropertyViewItem(m_tree); - QMetaProperty p = mo->property(ii); item->object = object; item->property = p; item->setText(0, QLatin1String(p.name())); + if(m_watches->hasWatch(objectId, p.name())) + item->setForeground(0, Qt::red); static int refreshIdx = -1; if(refreshIdx == -1) @@ -109,8 +172,34 @@ void QmlPropertyView::setObject(QObject *object) QMetaObject::connect(object, p.notifySignalIndex(), item, refreshIdx); + + QMultiHash >::Iterator iter = + bindings.find(p.name()); + + while(iter != bindings.end() && iter.key() == p.name()) { + QmlPropertyViewItem *binding = new QmlPropertyViewItem(item); + binding->exprId = iter.value().second; + binding->setText(1, iter.value().first); + if (m_watches->hasWatch(binding->exprId)) + binding->setForeground(1, Qt::darkGreen); + else + binding->setForeground(1, Qt::green); + ++iter; + } + + item->setExpanded(true); item->refresh(); } + + for(QHash::ConstIterator iter = sigs.begin(); + iter != sigs.end(); + ++iter) { + + QTreeWidgetItem *item = new QTreeWidgetItem(m_tree); + item->setText(0, iter.key()); + item->setForeground(0, Qt::blue); + item->setText(1, iter.value()); + } } void QmlPropertyView::refresh() diff --git a/src/declarative/debugger/qmlpropertyview_p.h b/src/declarative/debugger/qmlpropertyview_p.h index fce9941..a671ea1 100644 --- a/src/declarative/debugger/qmlpropertyview_p.h +++ b/src/declarative/debugger/qmlpropertyview_p.h @@ -44,24 +44,28 @@ #include #include +#include QT_BEGIN_NAMESPACE class QTreeWidget; +class QTreeWidgetItem; class QmlPropertyView : public QWidget { Q_OBJECT public: - QmlPropertyView(QWidget *parent = 0); + QmlPropertyView(QmlWatches *watches, QWidget *parent = 0); void setObject(QObject *); public slots: void refresh(); + void itemDoubleClicked(QTreeWidgetItem *); private: QPointer m_object; QTreeWidget *m_tree; + QmlWatches *m_watches; }; QT_END_NAMESPACE diff --git a/src/declarative/debugger/qmlwatches.cpp b/src/declarative/debugger/qmlwatches.cpp new file mode 100644 index 0000000..1b9befd --- /dev/null +++ b/src/declarative/debugger/qmlwatches.cpp @@ -0,0 +1,267 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmlwatches_p.h" +#include +#include +#include +#include + +static QString objectToString(QObject *obj) +{ + if(!obj) + return QString(); + + QString objectName = obj->objectName(); + if(objectName.isEmpty()) + objectName = QLatin1String(""); + + QString rv = QLatin1String(obj->metaObject()->className()) + + QLatin1String(": ") + objectName; + + return rv; +} + +class QmlWatchesProxy : public QObject +{ + Q_OBJECT +public: + QmlWatchesProxy(QObject *object, + const QMetaProperty &prop, + int column, + QmlWatches *parent = 0); + +public slots: + void refresh(); + +private: + QmlWatches *m_watches; + QObject *m_object; + QMetaProperty m_property; + int m_column; +}; + +QmlWatchesProxy::QmlWatchesProxy(QObject *object, + const QMetaProperty &prop, + int column, + QmlWatches *parent) +: QObject(parent), m_watches(parent), m_object(object), m_property(prop), + m_column(column) +{ + static int refreshIdx = -1; + if(refreshIdx == -1) + refreshIdx = QmlWatchesProxy::staticMetaObject.indexOfMethod("refresh()"); + + QMetaObject::connect(m_object, prop.notifySignalIndex(), + this, refreshIdx); +} + +void QmlWatchesProxy::refresh() +{ + QVariant v = m_property.read(m_object); + m_watches->addValue(m_column, v); +} + +QmlWatches::QmlWatches(QObject *parent) +: QAbstractTableModel(parent), m_uniqueId(0) +{ +} + +bool QmlWatches::hasWatch(quint32 objectId, const QByteArray &property) +{ + return m_watches.contains(qMakePair(objectId, property)); +} + +void QmlWatches::addWatch(quint32 objectId, const QByteArray &property) +{ + if(hasWatch(objectId, property)) + return; + + int oldColumn = columnCount(QModelIndex()); + + + m_watches.append(qMakePair(objectId, property)); + + beginInsertColumns(QModelIndex(), oldColumn, oldColumn); + endInsertColumns(); + + QObject *obj = object(objectId); + m_columnNames.append(QLatin1String(property) + QLatin1String(" on ") + objectToString(obj)); + QMetaProperty prop = + obj->metaObject()->property(obj->metaObject()->indexOfProperty(property.constData())); + QmlWatchesProxy *proxy = new QmlWatchesProxy(obj, prop, oldColumn, this); + proxy->refresh(); + m_values[m_values.count() - 1].first = true; +} + +void QmlWatches::remWatch(quint32 objectId, const QByteArray &property) +{ + m_watches.removeAll(qMakePair(objectId, property)); +} + +bool QmlWatches::hasWatch(quint32 exprId) +{ + return m_exprWatches.contains(exprId); +} + +void QmlWatches::remWatch(quint32 exprId) +{ + m_exprWatches.removeAll(exprId); +} + +void QmlWatches::addWatch(quint32 exprId) +{ + if (hasWatch(exprId)) + return; + + int oldColumn = columnCount(QModelIndex()); + + m_exprWatches.append(exprId); + + beginInsertColumns(QModelIndex(), oldColumn, oldColumn); + endInsertColumns(); +} + +quint32 QmlWatches::objectId(QObject *object) +{ + Q_ASSERT(object); + + QHash, quint32> *>::Iterator iter = + m_objects.find(object); + if(iter == m_objects.end()) { + iter = m_objects.insert(object, new QPair, quint32>(QPointer(object), m_uniqueId++)); + m_objectIds.insert(iter.value()->second, iter.value()); + } + + if(iter.value()->first != object) { + iter.value()->first = object; + iter.value()->second = m_uniqueId++; + + m_objectIds.insert(iter.value()->second, iter.value()); + } + return iter.value()->second; +} + +QObject *QmlWatches::object(quint32 id) +{ + QHash, quint32> *>::Iterator iter = + m_objectIds.find(id); + if(iter == m_objectIds.end()) + return 0; + + if(!iter.value()->first) { + m_objectIds.erase(iter); + return 0; + } + + return iter.value()->first; +} + +void QmlWatches::addValue(int column, const QVariant &value) +{ + int row = m_values.count(); + + beginInsertRows(QModelIndex(), row, row); + Value v; + v.column = column; + v.variant = value; + v.first = false; + m_values.append(v); + endInsertRows(); +} + +int QmlWatches::columnCount(const QModelIndex &) const +{ + return m_watches.count() + m_exprWatches.count(); +} + +int QmlWatches::rowCount(const QModelIndex &) const +{ + return m_values.count(); +} + +QVariant QmlWatches::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation == Qt::Horizontal && section < m_columnNames.count() && + role == Qt::DisplayRole) + return m_columnNames.at(section); + else + return QVariant(); +} + +QVariant QmlWatches::data(const QModelIndex &idx, int role) const +{ + if(m_values.at(idx.row()).column == idx.column()) { + if(role == Qt::DisplayRole) { + const QVariant &value = m_values.at(idx.row()).variant; + + QString str = value.toString(); + + if(str.isEmpty() && QmlMetaType::isObject(value.userType())) { + QObject *o = QmlMetaType::toQObject(value); + if(o) { + QString objectName = o->objectName(); + if(objectName.isEmpty()) + objectName = QLatin1String(""); + str = QLatin1String(o->metaObject()->className()) + + QLatin1String(": ") + objectName; + } + } + + if(str.isEmpty()) { + QDebug d(&str); + d << value; + } + return QVariant(str); + } else if(role == Qt::BackgroundRole) { + if(m_values.at(idx.row()).first) + return QColor(Qt::green); + else + return QVariant(); + } else { + return QVariant(); + } + } else { + return QVariant(); + } +} + +#include "qmlwatches.moc" diff --git a/src/declarative/debugger/qmlwatches_p.h b/src/declarative/debugger/qmlwatches_p.h new file mode 100644 index 0000000..12a6468 --- /dev/null +++ b/src/declarative/debugger/qmlwatches_p.h @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLWATCHES_P_H +#define QMLWATCHES_P_H + +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QmlWatchesProxy; +class QmlWatches : public QAbstractTableModel +{ + Q_OBJECT +public: + QmlWatches(QObject *parent = 0); + + bool hasWatch(quint32 objectId, const QByteArray &property); + void addWatch(quint32 objectId, const QByteArray &property); + void remWatch(quint32 objectId, const QByteArray &property); + + bool hasWatch(quint32 exprId); + void remWatch(quint32 exprId); + void addWatch(quint32 exprId); + + quint32 objectId(QObject *); + QObject *object(quint32); + +protected: + int columnCount(const QModelIndex &) const; + int rowCount(const QModelIndex &) const; + QVariant data(const QModelIndex &, int) const; + QVariant headerData(int, Qt::Orientation, int) const; + +private: + friend class QmlWatchesProxy; + QList > m_watches; + QList m_exprWatches; + + void addValue(int, const QVariant &); + struct Value { + int column; + QVariant variant; + bool first; + }; + QList m_values; + QStringList m_columnNames; + + quint32 m_uniqueId; + QHash, quint32> *> m_objects; + QHash, quint32> *> m_objectIds; +}; + +QT_END_NAMESPACE + +#endif // QMLWATCHES_P_H diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index 15b5879..50c0981 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -597,6 +597,9 @@ QNetworkAccessManager *QmlEngine::networkAccessManager() const */ QmlContext *QmlEngine::contextForObject(const QObject *object) { + if(!object) + return 0; + QObjectPrivate *priv = QObjectPrivate::get(const_cast(object)); QmlSimpleDeclarativeData *data = @@ -1093,6 +1096,14 @@ QObject *QmlExpression::scopeObject() const } /*! + \internal +*/ +quint32 QmlExpression::id() const +{ + return d->id; +} + +/*! \class QmlExpression \brief The QmlExpression class evaluates ECMAScript in a QML context. */ diff --git a/src/declarative/qml/qmlexpression.h b/src/declarative/qml/qmlexpression.h index 0ab5d9c..bb6980a 100644 --- a/src/declarative/qml/qmlexpression.h +++ b/src/declarative/qml/qmlexpression.h @@ -80,6 +80,7 @@ public: QObject *scopeObject() const; + quint32 id() const; protected: virtual void valueChanged(); -- cgit v0.12