QML Debugger: request objects from all contexts

This commit is contained in:
Olivier Goffart
2010-08-20 15:12:29 +02:00
parent 5b4f826552
commit a18c8f9e96
6 changed files with 91 additions and 95 deletions

View File

@@ -51,7 +51,6 @@ ClientProxy::ClientProxy(Debugger::Internal::QmlAdapter *adapter, QObject *paren
, m_designClient(0) , m_designClient(0)
, m_engineQuery(0) , m_engineQuery(0)
, m_contextQuery(0) , m_contextQuery(0)
, m_objectTreeQuery(0)
{ {
connect(m_adapter, SIGNAL(aboutToDisconnect()), SLOT(disconnectFromServer())); connect(m_adapter, SIGNAL(aboutToDisconnect()), SLOT(disconnectFromServer()));
@@ -125,24 +124,16 @@ void ClientProxy::disconnectFromServer()
delete m_contextQuery; delete m_contextQuery;
m_contextQuery = 0; m_contextQuery = 0;
if (m_objectTreeQuery) { qDeleteAll(m_objectTreeQuery);
delete m_objectTreeQuery; m_objectTreeQuery.clear();
m_objectTreeQuery = 0;
}
} }
void ClientProxy::refreshObjectTree() void ClientProxy::refreshObjectTree()
{ {
if (!m_objectTreeQuery) { if (!m_contextQuery) {
m_objectTreeQuery = m_client->queryObjectRecursive(m_rootObject, this); qDeleteAll(m_objectTreeQuery);
m_objectTreeQuery.clear();
if (!m_objectTreeQuery->isWaiting()) { queryEngineContext(m_engines.value(0).debugId());
objectTreeFetched(m_objectTreeQuery->state());
} else {
connect(m_objectTreeQuery,
SIGNAL(stateChanged(QDeclarativeDebugQuery::State)),
SLOT(objectTreeFetched(QDeclarativeDebugQuery::State)));
}
} }
} }
@@ -154,31 +145,19 @@ void ClientProxy::onCurrentObjectsChanged(const QList< int >& debugIds, bool req
QDeclarativeDebugObjectReference ref = objectReferenceForId(debugId); QDeclarativeDebugObjectReference ref = objectReferenceForId(debugId);
if (ref.debugId() != -1) { if (ref.debugId() != -1) {
selectedItems << ref; selectedItems << ref;
} else { } else if (requestIfNeeded) {
// ### FIXME right now, there's no way in the protocol to // ### FIXME right now, there's no way in the protocol to
// a) get some item and know its parent (although that's possible // a) get some item and know its parent (although that's possible
// by adding it to a separate plugin) // by adding it to a separate plugin)
// b) add children to part of an existing tree. // b) add children to part of an existing tree.
// So the only choice that remains is to update the complete // So the only choice that remains is to update the complete
// tree when we have an unknown debug id. // tree when we have an unknown debug id.
if (!m_objectTreeQuery && requestIfNeeded) // break;
m_objectTreeQuery = m_client->queryObjectRecursive(m_rootObject, this);
break;
} }
} }
if (m_objectTreeQuery) {
if (!m_objectTreeQuery->isWaiting()) {
objectTreeFetched(m_objectTreeQuery->state());
} else {
connect(m_objectTreeQuery,
SIGNAL(stateChanged(QDeclarativeDebugQuery::State)),
SLOT(objectTreeFetched(QDeclarativeDebugQuery::State)));
}
} else {
emit selectedItemsChanged(selectedItems); emit selectedItemsChanged(selectedItems);
} }
}
void ClientProxy::setSelectedItemsByObjectId(const QList<QDeclarativeDebugObjectReference> &objectRefs) void ClientProxy::setSelectedItemsByObjectId(const QList<QDeclarativeDebugObjectReference> &objectRefs)
{ {
@@ -188,12 +167,17 @@ void ClientProxy::setSelectedItemsByObjectId(const QList<QDeclarativeDebugObject
QDeclarativeDebugObjectReference ClientProxy::objectReferenceForId(int debugId) const QDeclarativeDebugObjectReference ClientProxy::objectReferenceForId(int debugId) const
{ {
return objectReferenceForId(debugId, m_rootObject); foreach (const QDeclarativeDebugObjectReference& it, m_rootObjects) {
QDeclarativeDebugObjectReference result = objectReferenceForId(debugId, it);
if (result.debugId() == debugId)
return result;
}
return QDeclarativeDebugObjectReference();
} }
QDeclarativeDebugObjectReference QmlJSInspector::Internal::ClientProxy::rootObjectReference() const QList<QDeclarativeDebugObjectReference> QmlJSInspector::Internal::ClientProxy::rootObjectReference() const
{ {
return m_rootObject; return m_rootObjects;
} }
QDeclarativeDebugObjectReference ClientProxy::objectReferenceForId(int debugId, QDeclarativeDebugObjectReference ClientProxy::objectReferenceForId(int debugId,
@@ -213,7 +197,11 @@ QDeclarativeDebugObjectReference ClientProxy::objectReferenceForId(int debugId,
QList<QDeclarativeDebugObjectReference> ClientProxy::objectReferences(const QUrl &url) const QList<QDeclarativeDebugObjectReference> ClientProxy::objectReferences(const QUrl &url) const
{ {
return objectReferences(url, m_rootObject); QList<QDeclarativeDebugObjectReference> result;
foreach(const QDeclarativeDebugObjectReference &it, m_rootObjects) {
result.append(objectReferences(url, it));
}
return result;
} }
QList<QDeclarativeDebugObjectReference> ClientProxy::objectReferences(const QUrl &url, QList<QDeclarativeDebugObjectReference> ClientProxy::objectReferences(const QUrl &url,
@@ -291,55 +279,58 @@ void ClientProxy::queryEngineContext(int id)
void ClientProxy::contextChanged() void ClientProxy::contextChanged()
{ {
if (m_contextQuery) { if (m_contextQuery) {
m_rootObjects = m_contextQuery->rootContext().objects();
if (m_contextQuery->rootContext().objects().isEmpty()) {
m_rootObject = QDeclarativeDebugObjectReference();
emit objectTreeUpdated(m_rootObject);
} else {
m_rootObject = m_contextQuery->rootContext().objects().last();
}
delete m_contextQuery; delete m_contextQuery;
m_contextQuery = 0; m_contextQuery = 0;
m_objectTreeQuery = m_client->queryObjectRecursive(m_rootObject, this); if (m_rootObjects.isEmpty()) {
if (!m_objectTreeQuery->isWaiting()) { emit objectTreeUpdated();
objectTreeFetched(); return;
}
qDeleteAll(m_objectTreeQuery);
m_objectTreeQuery.clear();
foreach(const QDeclarativeDebugObjectReference & obj, m_rootObjects) {
QDeclarativeDebugObjectQuery* query = m_client->queryObjectRecursive(obj, this);
if (!query->isWaiting()) {
query->deleteLater(); //ignore errors;
} else { } else {
connect(m_objectTreeQuery, m_objectTreeQuery << query;
connect(query,
SIGNAL(stateChanged(QDeclarativeDebugQuery::State)), SIGNAL(stateChanged(QDeclarativeDebugQuery::State)),
SLOT(objectTreeFetched(QDeclarativeDebugQuery::State))); SLOT(objectTreeFetched(QDeclarativeDebugQuery::State)));
} }
} }
}
} }
void ClientProxy::objectTreeFetched(QDeclarativeDebugQuery::State state) void ClientProxy::objectTreeFetched(QDeclarativeDebugQuery::State state)
{ {
if (state == QDeclarativeDebugQuery::Error) { QDeclarativeDebugObjectQuery *query = qobject_cast<QDeclarativeDebugObjectQuery *>(sender());
delete m_objectTreeQuery; if (!query || state == QDeclarativeDebugQuery::Error) {
m_objectTreeQuery = 0; delete query;
}
if (state != QDeclarativeDebugQuery::Completed) {
m_rootObject = QDeclarativeDebugObjectReference();
return; return;
} }
m_rootObject = m_objectTreeQuery->object(); m_rootObjects.append(query->object());
delete m_objectTreeQuery; int removed = m_objectTreeQuery.removeAll(query);
m_objectTreeQuery = 0; Q_ASSERT(removed == 1);
Q_UNUSED(removed);
delete query;
emit objectTreeUpdated(m_rootObject); if (m_objectTreeQuery.isEmpty()) {
emit objectTreeUpdated();
if (isDesignClientConnected()) { if (isDesignClientConnected()) {
if (!m_designClient->selectedItemIds().isEmpty()) if (!m_designClient->selectedItemIds().isEmpty())
onCurrentObjectsChanged(m_designClient->selectedItemIds(), false); onCurrentObjectsChanged(m_designClient->selectedItemIds(), false);
m_designClient->setObjectIdList(QList<QDeclarativeDebugObjectReference>() << m_rootObject); m_designClient->setObjectIdList(m_rootObjects);
}
} }
} }
void ClientProxy::reloadQmlViewer() void ClientProxy::reloadQmlViewer()

View File

@@ -66,7 +66,7 @@ public:
// returns the object references for the given url. // returns the object references for the given url.
QList<QDeclarativeDebugObjectReference> objectReferences(const QUrl &url = QUrl()) const; QList<QDeclarativeDebugObjectReference> objectReferences(const QUrl &url = QUrl()) const;
QDeclarativeDebugObjectReference objectReferenceForId(int debugId) const; QDeclarativeDebugObjectReference objectReferenceForId(int debugId) const;
QDeclarativeDebugObjectReference rootObjectReference() const; QList<QDeclarativeDebugObjectReference> rootObjectReference() const;
bool isConnected() const; bool isConnected() const;
@@ -77,7 +77,7 @@ public:
Debugger::Internal::QmlAdapter *qmlAdapter() const; Debugger::Internal::QmlAdapter *qmlAdapter() const;
signals: signals:
void objectTreeUpdated(const QDeclarativeDebugObjectReference &rootObject); void objectTreeUpdated();
void connectionStatusMessage(const QString &text); void connectionStatusMessage(const QString &text);
void aboutToReloadEngines(); void aboutToReloadEngines();
@@ -141,9 +141,9 @@ private:
QDeclarativeDebugEnginesQuery *m_engineQuery; QDeclarativeDebugEnginesQuery *m_engineQuery;
QDeclarativeDebugRootContextQuery *m_contextQuery; QDeclarativeDebugRootContextQuery *m_contextQuery;
QDeclarativeDebugObjectQuery *m_objectTreeQuery; QList<QDeclarativeDebugObjectQuery *> m_objectTreeQuery;
QDeclarativeDebugObjectReference m_rootObject; QList<QDeclarativeDebugObjectReference> m_rootObjects;
QList<QDeclarativeDebugEngineReference> m_engines; QList<QDeclarativeDebugEngineReference> m_engines;
}; };

View File

@@ -206,14 +206,14 @@ void InspectorUi::disconnected()
void InspectorUi::updateEngineList() void InspectorUi::updateEngineList()
{ {
m_engines = m_clientProxy->engines(); QList<QDeclarativeDebugEngineReference> engines = m_clientProxy->engines();
//#warning update the QML engines combo //#warning update the QML engines combo
if (m_engines.isEmpty()) if (engines.isEmpty())
qWarning("qmldebugger: no engines found!"); qWarning("qmldebugger: no engines found!");
else { else {
const QDeclarativeDebugEngineReference engine = m_engines.first(); const QDeclarativeDebugEngineReference engine = engines.first();
m_clientProxy->queryEngineContext(engine.debugId()); m_clientProxy->queryEngineContext(engine.debugId());
} }
} }
@@ -254,7 +254,7 @@ void InspectorUi::serverReloaded()
Document::Ptr doc = snapshot.document(it.key()); Document::Ptr doc = snapshot.document(it.key());
it.value()->resetInitialDoc(doc); it.value()->resetInitialDoc(doc);
} }
m_clientProxy->queryEngineContext(m_engines.value(0).debugId()); m_clientProxy->refreshObjectTree();
} }
@@ -293,7 +293,7 @@ void InspectorUi::createPreviewForEditor(Core::IEditor *newEditor)
m_textPreviews.insert(newEditor->file()->fileName(), preview); m_textPreviews.insert(newEditor->file()->fileName(), preview);
preview->associateEditor(newEditor); preview->associateEditor(newEditor);
preview->updateDebugIds(m_clientProxy->rootObjectReference()); preview->updateDebugIds();
} }
} }
} }

View File

@@ -148,7 +148,6 @@ private:
ProjectExplorer::Project *m_debugProject; ProjectExplorer::Project *m_debugProject;
static InspectorUi *m_instance; static InspectorUi *m_instance;
QList<QDeclarativeDebugEngineReference> m_engines;
}; };
} // Internal } // Internal

View File

@@ -71,7 +71,7 @@ class MapObjectWithDebugReference : public Visitor
virtual bool visit(UiObjectDefinition *ast) ; virtual bool visit(UiObjectDefinition *ast) ;
virtual bool visit(UiObjectBinding *ast) ; virtual bool visit(UiObjectBinding *ast) ;
QDeclarativeDebugObjectReference root; QList<QDeclarativeDebugObjectReference> root;
QString filename; QString filename;
QHash<UiObjectMember *, DebugIdList> result; QHash<UiObjectMember *, DebugIdList> result;
QSet<QmlJS::AST::UiObjectMember *> lookupObjects; QSet<QmlJS::AST::UiObjectMember *> lookupObjects;
@@ -97,16 +97,21 @@ bool MapObjectWithDebugReference::visit(UiObjectBinding* ast)
void MapObjectWithDebugReference::endVisit(UiObjectDefinition* ast) void MapObjectWithDebugReference::endVisit(UiObjectDefinition* ast)
{ {
if (lookupObjects.isEmpty() || activated) if (lookupObjects.isEmpty() || activated) {
processRecursive(root, ast); foreach(const QDeclarativeDebugObjectReference& it, root)
processRecursive(it, ast);
}
if (lookupObjects.contains(ast)) if (lookupObjects.contains(ast))
activated--; activated--;
} }
void MapObjectWithDebugReference::endVisit(UiObjectBinding* ast) void MapObjectWithDebugReference::endVisit(UiObjectBinding* ast)
{ {
if (lookupObjects.isEmpty() || activated) if (lookupObjects.isEmpty() || activated) {
processRecursive(root, ast); foreach(const QDeclarativeDebugObjectReference& it, root)
processRecursive(it, ast);
}
if (lookupObjects.contains(ast)) if (lookupObjects.contains(ast))
activated--; activated--;
@@ -184,9 +189,7 @@ QmlJSLiveTextPreview::QmlJSLiveTextPreview(const QmlJS::Document::Ptr &doc,
SLOT(documentChanged(QmlJS::Document::Ptr))); SLOT(documentChanged(QmlJS::Document::Ptr)));
if (m_clientProxy.data()) { if (m_clientProxy.data()) {
connect(m_clientProxy.data(), connect(m_clientProxy.data(), SIGNAL(objectTreeUpdated()), SLOT(updateDebugIds()));
SIGNAL(objectTreeUpdated(QDeclarativeDebugObjectReference)),
SLOT(updateDebugIds(QDeclarativeDebugObjectReference)));
} }
} }
@@ -279,15 +282,19 @@ static QList<int> findRootObjectRecursive(const QDeclarativeDebugObjectReference
return result; return result;
} }
void QmlJSLiveTextPreview::updateDebugIds(const QDeclarativeDebugObjectReference &rootReference) void QmlJSLiveTextPreview::updateDebugIds()
{ {
if (!m_initialDoc->qmlProgram()) if (!m_initialDoc->qmlProgram())
return; return;
ClientProxy* clientProxy = m_clientProxy.data();
if (!clientProxy)
return;
{ // Map all the object that comes from the document as it has been loaded by the server. { // Map all the object that comes from the document as it has been loaded by the server.
const QmlJS::Document::Ptr &doc = m_initialDoc; const QmlJS::Document::Ptr &doc = m_initialDoc;
MapObjectWithDebugReference visitor; MapObjectWithDebugReference visitor;
visitor.root = rootReference; visitor.root = clientProxy->rootObjectReference();
visitor.filename = doc->fileName(); visitor.filename = doc->fileName();
doc->qmlProgram()->accept(&visitor); doc->qmlProgram()->accept(&visitor);
@@ -305,7 +312,9 @@ void QmlJSLiveTextPreview::updateDebugIds(const QDeclarativeDebugObjectReference
// Map the root nodes of the document. // Map the root nodes of the document.
if(doc->qmlProgram()->members && doc->qmlProgram()->members->member) { if(doc->qmlProgram()->members && doc->qmlProgram()->members->member) {
UiObjectMember* root = doc->qmlProgram()->members->member; UiObjectMember* root = doc->qmlProgram()->members->member;
QList<int> r = findRootObjectRecursive(rootReference, doc); QList<int> r;
foreach(const QDeclarativeDebugObjectReference& it, clientProxy->rootObjectReference())
r += findRootObjectRecursive(it, doc);
if (!r.isEmpty()) if (!r.isEmpty())
m_debugIds[root] += r; m_debugIds[root] += r;
} }
@@ -316,7 +325,7 @@ void QmlJSLiveTextPreview::updateDebugIds(const QDeclarativeDebugObjectReference
const QmlJS::Document::Ptr &doc = it.key(); const QmlJS::Document::Ptr &doc = it.key();
MapObjectWithDebugReference visitor; MapObjectWithDebugReference visitor;
visitor.root = rootReference; visitor.root = clientProxy->rootObjectReference();
visitor.filename = doc->fileName(); visitor.filename = doc->fileName();
visitor.lookupObjects = it.value(); visitor.lookupObjects = it.value();
visitor.doc = doc; visitor.doc = doc;
@@ -651,18 +660,15 @@ void QmlJSLiveTextPreview::setApplyChangesToQmlObserver(bool applyChanges)
void QmlJSLiveTextPreview::setClientProxy(ClientProxy *clientProxy) void QmlJSLiveTextPreview::setClientProxy(ClientProxy *clientProxy)
{ {
if (m_clientProxy.data()) { if (m_clientProxy.data()) {
disconnect(m_clientProxy.data(), disconnect(m_clientProxy.data(), SIGNAL(objectTreeUpdated()),
SIGNAL(objectTreeUpdated(QDeclarativeDebugObjectReference)), this, SLOT(updateDebugIds()));
this,
SLOT(updateDebugIds(QDeclarativeDebugObjectReference)));
} }
m_clientProxy = clientProxy; m_clientProxy = clientProxy;
if (m_clientProxy.data()) { if (m_clientProxy.data()) {
connect(m_clientProxy.data(), connect(m_clientProxy.data(), SIGNAL(objectTreeUpdated()),
SIGNAL(objectTreeUpdated(QDeclarativeDebugObjectReference)), SLOT(updateDebugIds()));
SLOT(updateDebugIds(QDeclarativeDebugObjectReference)));
} }
} }

View File

@@ -90,7 +90,7 @@ signals:
public slots: public slots:
void setApplyChangesToQmlObserver(bool applyChanges); void setApplyChangesToQmlObserver(bool applyChanges);
void updateDebugIds(const QDeclarativeDebugObjectReference &rootReference); void updateDebugIds();
private slots: private slots:
void changeSelectedElements(QList<int> offsets, const QString &wordAtCursor); void changeSelectedElements(QList<int> offsets, const QString &wordAtCursor);