Commit 32a0afb9 authored by Aurindam Jana's avatar Aurindam Jana Committed by hjk
Browse files

Inspector: Fetch objects lazily



QML objects are fetched lazily when constructing the object tree.
Incase parents have not been previously fetched, we fetch the
required data to construct only the relevant branch of the tree.

Task-number: QTCREATORBUG-8246
Change-Id: Id529c3b2334d33ff4eb46b14f50cf042ad2960e2
Reviewed-by: default avatarhjk <qthjk@ovi.com>
parent 8d825b5b
...@@ -62,6 +62,7 @@ QmlInspectorAgent::QmlInspectorAgent(DebuggerEngine *engine, QObject *parent) ...@@ -62,6 +62,7 @@ QmlInspectorAgent::QmlInspectorAgent(DebuggerEngine *engine, QObject *parent)
, m_objectToSelect(-1) , m_objectToSelect(-1)
, m_newObjectsCreated(false) , m_newObjectsCreated(false)
{ {
m_debugIdToIname.insert(-1, QByteArray("inspect"));
connect(debuggerCore()->action(ShowQmlObjectTree), connect(debuggerCore()->action(ShowQmlObjectTree),
SIGNAL(valueChanged(QVariant)), SLOT(updateStatus())); SIGNAL(valueChanged(QVariant)), SLOT(updateStatus()));
m_delayQueryTimer.setSingleShot(true); m_delayQueryTimer.setSingleShot(true);
...@@ -452,17 +453,17 @@ void QmlInspectorAgent::onResult(quint32 queryId, const QVariant &value, ...@@ -452,17 +453,17 @@ void QmlInspectorAgent::onResult(quint32 queryId, const QVariant &value,
} }
if (m_objectTreeQueryIds.contains(queryId)) { if (m_objectTreeQueryIds.contains(queryId)) {
m_objectTreeQueryIds.removeOne(queryId);
if (value.type() == QVariant::List) { if (value.type() == QVariant::List) {
QVariantList objList = value.toList(); QVariantList objList = value.toList();
foreach (QVariant var, objList) { foreach (QVariant var, objList) {
// TODO: check which among the list is the actual // TODO: check which among the list is the actual
// object that needs to be selected. // object that needs to be selected.
insertObjectInTree(qvariant_cast<ObjectReference>(var)); verifyAndInsertObjectInTree(qvariant_cast<ObjectReference>(var));
} }
} else { } else {
insertObjectInTree(qvariant_cast<ObjectReference>(value)); verifyAndInsertObjectInTree(qvariant_cast<ObjectReference>(value));
} }
m_objectTreeQueryIds.removeOne(queryId);
} else if (queryId == m_engineQueryId) { } else if (queryId == m_engineQueryId) {
m_engineQueryId = 0; m_engineQueryId = 0;
QList<EngineReference> engines = qvariant_cast<QList<EngineReference> >(value); QList<EngineReference> engines = qvariant_cast<QList<EngineReference> >(value);
...@@ -608,13 +609,13 @@ void QmlInspectorAgent::updateObjectTree(const ContextReference &context) ...@@ -608,13 +609,13 @@ void QmlInspectorAgent::updateObjectTree(const ContextReference &context)
return; return;
foreach (const ObjectReference & obj, context.objects()) foreach (const ObjectReference & obj, context.objects())
insertObjectInTree(obj); verifyAndInsertObjectInTree(obj);
foreach (const ContextReference &child, context.contexts()) foreach (const ContextReference &child, context.contexts())
updateObjectTree(child); updateObjectTree(child);
} }
void QmlInspectorAgent::insertObjectInTree(const ObjectReference &object) void QmlInspectorAgent::verifyAndInsertObjectInTree(const ObjectReference &object)
{ {
if (debug) if (debug)
qDebug() << __FUNCTION__ << '(' << object << ')'; qDebug() << __FUNCTION__ << '(' << object << ')';
...@@ -622,17 +623,56 @@ void QmlInspectorAgent::insertObjectInTree(const ObjectReference &object) ...@@ -622,17 +623,56 @@ void QmlInspectorAgent::insertObjectInTree(const ObjectReference &object)
if (!object.isValid()) if (!object.isValid())
return; return;
QElapsedTimer timeElapsed; // Find out the correct position in the tree
// sync tree with watchhandler // Objects are inserted to the tree if they satisfy one of the two conditions.
QList<WatchData> watchData; // Condition 1: Object is a root object i.e. parentId == -1.
int objectDebugId = object.debugId(); // Condition 2: Object has an expanded parent i.e. siblings are known.
// If the two conditions are not met then we push the object to a stack and recursively
// fetch parents till we find a previously expanded parent.
WatchHandler *handler = m_debuggerEngine->watchHandler();
const int parentId = object.parentId();
const int objectDebugId = object.debugId();
if (m_debugIdToIname.contains(parentId)) {
QByteArray parentIname = m_debugIdToIname.value(parentId);
if (parentId != -1 && !handler->isExpandedIName(parentIname)) {
m_objectStack.push(object);
handler->model()->fetchMore(handler->watchDataIndex(parentIname));
return; // recursive
}
insertObjectInTree(object);
// When root items are inserted in the object tree, m_objectTreeQueryIds = 0 } else {
if (!m_debugIdToIname.contains(objectDebugId) && m_objectTreeQueryIds.count()) m_objectStack.push(object);
return; fetchObject(parentId);
return; // recursive
}
if (!m_objectStack.isEmpty()) {
const ObjectReference &top = m_objectStack.top();
// We want to expand only a particular branch and not the whole tree. Hence, we do not
// expand siblings.
if (object.children().contains(top)) {
QByteArray objectIname = m_debugIdToIname.value(objectDebugId);
if (!handler->isExpandedIName(objectIname)) {
handler->model()->fetchMore(handler->watchDataIndex(objectIname));
} else {
verifyAndInsertObjectInTree(m_objectStack.pop());
return; // recursive
}
}
}
}
void QmlInspectorAgent::insertObjectInTree(const ObjectReference &object)
{
if (debug)
qDebug() << __FUNCTION__ << '(' << object << ')';
int parentId = parentIdForIname(m_debugIdToIname.value(objectDebugId)); const int objectDebugId = object.debugId();
const int parentId = parentIdForIname(m_debugIdToIname.value(objectDebugId));
QElapsedTimer timeElapsed;
QList<WatchData> watchData;
if (debug) if (debug)
timeElapsed.start(); timeElapsed.start();
watchData.append(buildWatchData(object, m_debugIdToIname.value(parentId), true)); watchData.append(buildWatchData(object, m_debugIdToIname.value(parentId), true));
...@@ -829,6 +869,7 @@ void QmlInspectorAgent::clearObjectTree() ...@@ -829,6 +869,7 @@ void QmlInspectorAgent::clearObjectTree()
m_debugIdHash.clear(); m_debugIdHash.clear();
m_debugIdHash.reserve(old_count + 1); m_debugIdHash.reserve(old_count + 1);
m_debugIdToIname.clear(); m_debugIdToIname.clear();
m_debugIdToIname.insert(-1, QByteArray("inspect"));
m_objectStack.clear(); m_objectStack.clear();
// reset only for qt > 4.8.3. // reset only for qt > 4.8.3.
if (m_engineClient->objectName() != QLatin1String(QDECLARATIVE_ENGINE)) if (m_engineClient->objectName() != QLatin1String(QDECLARATIVE_ENGINE))
......
...@@ -110,7 +110,7 @@ private slots: ...@@ -110,7 +110,7 @@ private slots:
private: private:
void updateObjectTree(const QmlDebug::ContextReference &context); void updateObjectTree(const QmlDebug::ContextReference &context);
void verifyAndInsertObjectInTree(const QmlDebug::ObjectReference &object);
void insertObjectInTree(const QmlDebug::ObjectReference &result); void insertObjectInTree(const QmlDebug::ObjectReference &result);
void buildDebugIdHashRecursive(const QmlDebug::ObjectReference &ref); void buildDebugIdHashRecursive(const QmlDebug::ObjectReference &ref);
......
...@@ -1807,6 +1807,11 @@ const WatchData *WatchHandler::watchData(const QModelIndex &idx) const ...@@ -1807,6 +1807,11 @@ const WatchData *WatchHandler::watchData(const QModelIndex &idx) const
return m_model->watchItem(idx); return m_model->watchItem(idx);
} }
const QModelIndex WatchHandler::watchDataIndex(const QByteArray &iname) const
{
return m_model->watchIndex(m_model->findItem(iname));
}
const WatchData *WatchHandler::findData(const QByteArray &iname) const const WatchData *WatchHandler::findData(const QByteArray &iname) const
{ {
return m_model->findItem(iname); return m_model->findItem(iname);
......
...@@ -85,6 +85,7 @@ public: ...@@ -85,6 +85,7 @@ public:
void showEditValue(const WatchData &data); void showEditValue(const WatchData &data);
const WatchData *watchData(const QModelIndex &) const; const WatchData *watchData(const QModelIndex &) const;
const QModelIndex watchDataIndex(const QByteArray &iname) const;
const WatchData *findData(const QByteArray &iname) const; const WatchData *findData(const QByteArray &iname) const;
const WatchData *findCppLocalVariable(const QString &name) const; const WatchData *findCppLocalVariable(const QString &name) const;
QString displayForAutoTest(const QByteArray &iname) const; QString displayForAutoTest(const QByteArray &iname) const;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment