From 1ce574f19efd5a5661a849940bb1df3770478a1b Mon Sep 17 00:00:00 2001 From: Olivier Goffart <olivier.goffart@nokia.com> Date: Mon, 19 Jul 2010 15:10:36 +0200 Subject: [PATCH] Qml Live Preview: Match debug Id for new created objects. --- src/plugins/qmljsinspector/qmljsdelta.cpp | 8 ++- src/plugins/qmljsinspector/qmljsdelta.h | 1 + src/plugins/qmljsinspector/qmljsinspector.cpp | 2 + .../qmljsinspector/qmljslivetextpreview.cpp | 68 +++++++++++++++++-- .../qmljsinspector/qmljslivetextpreview.h | 1 + .../qml/qmlobserver/editor/qmltoolbar.cpp | 1 + 6 files changed, 75 insertions(+), 6 deletions(-) diff --git a/src/plugins/qmljsinspector/qmljsdelta.cpp b/src/plugins/qmljsinspector/qmljsdelta.cpp index 18cbc70e2c8..4c9c514b6d4 100644 --- a/src/plugins/qmljsinspector/qmljsdelta.cpp +++ b/src/plugins/qmljsinspector/qmljsdelta.cpp @@ -290,7 +290,8 @@ void Delta::insert(UiObjectMember *member, UiObjectMember *parentMember, const Q if (UiObjectDefinition* uiObjectDef = cast<UiObjectDefinition *>(member)) { unsigned begin = uiObjectDef->firstSourceLocation().begin(); unsigned end = uiObjectDef->lastSourceLocation().end(); - QString qmlText = doc->source().mid(begin, end - begin); + QString qmlText = QString(uiObjectDef->firstSourceLocation().startColumn - 1, QLatin1Char(' ')); + qmlText += doc->source().midRef(begin, end - begin); QStringList importList; for (UiImportList *it = doc->qmlProgram()->imports; it; it = it->next) { if (!it->import) @@ -301,12 +302,15 @@ void Delta::insert(UiObjectMember *member, UiObjectMember *parentMember, const Q importList << doc->source().mid(importBegin, importEnd - importBegin); } + QString filename = doc->fileName() + QLatin1Char('_') + QString::number(doc->editorRevision()) + + QLatin1Char(':') + QString::number(uiObjectDef->firstSourceLocation().startLine-importList.count()); foreach(const QDeclarativeDebugObjectReference &ref, debugReferences) { if (ref.debugId() != -1) { _referenceRefreshRequired = true; - ClientProxy::instance()->createQmlObject(qmlText, ref, importList, doc->fileName()); + ClientProxy::instance()->createQmlObject(qmlText, ref, importList, filename); } } + newObjects += member; } } diff --git a/src/plugins/qmljsinspector/qmljsdelta.h b/src/plugins/qmljsinspector/qmljsdelta.h index c03769bccd0..7033b506916 100644 --- a/src/plugins/qmljsinspector/qmljsdelta.h +++ b/src/plugins/qmljsinspector/qmljsdelta.h @@ -49,6 +49,7 @@ public: Delta() : doNotSendChanges(false) {} bool doNotSendChanges; + QSet<UiObjectMember *> newObjects; struct Change { Change(): script(0), isLiteral(false) {} diff --git a/src/plugins/qmljsinspector/qmljsinspector.cpp b/src/plugins/qmljsinspector/qmljsinspector.cpp index 5a464f58e7d..f1a76c3556f 100644 --- a/src/plugins/qmljsinspector/qmljsinspector.cpp +++ b/src/plugins/qmljsinspector/qmljsinspector.cpp @@ -251,6 +251,8 @@ void Inspector::createPreviewForEditor(Core::IEditor *newEditor) if (newEditor && newEditor->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID) { QString filename = newEditor->file()->fileName(); QmlJS::Document::Ptr doc = modelManager()->snapshot().document(filename); + if (!doc || !doc->qmlProgram()) + return; if (m_textPreviews.contains(filename)) { m_textPreviews.value(filename)->associateEditor(newEditor); diff --git a/src/plugins/qmljsinspector/qmljslivetextpreview.cpp b/src/plugins/qmljsinspector/qmljslivetextpreview.cpp index fc61e949ebe..0bdc0f12687 100644 --- a/src/plugins/qmljsinspector/qmljslivetextpreview.cpp +++ b/src/plugins/qmljsinspector/qmljslivetextpreview.cpp @@ -29,23 +29,51 @@ namespace Internal { class MapObjectWithDebugReference : public Visitor { public: + MapObjectWithDebugReference() : activated(0) {} virtual void endVisit(UiObjectDefinition *ast) ; virtual void endVisit(UiObjectBinding *ast) ; + virtual bool visit(UiObjectDefinition *ast) ; + virtual bool visit(UiObjectBinding *ast) ; QDeclarativeDebugObjectReference root; QString filename; QHash<UiObjectMember *, QList<QDeclarativeDebugObjectReference> > result; + QSet<QmlJS::AST::UiObjectMember *> lookupObjects; + Document::Ptr doc; private: + int activated; void processRecursive(const QDeclarativeDebugObjectReference &object, UiObjectMember *ast); }; +bool MapObjectWithDebugReference::visit(UiObjectDefinition* ast) +{ + if (lookupObjects.contains(ast)) + activated++; + return true; +} + +bool MapObjectWithDebugReference::visit(UiObjectBinding* ast) +{ + if (lookupObjects.contains(ast)) + activated++; + return true; +} + void MapObjectWithDebugReference::endVisit(UiObjectDefinition* ast) { - processRecursive(root, ast); + if (lookupObjects.isEmpty() || activated) + processRecursive(root, ast); + + if (lookupObjects.contains(ast)) + activated--; } void MapObjectWithDebugReference::endVisit(UiObjectBinding* ast) { - processRecursive(root, ast); + if (lookupObjects.isEmpty() || activated) + processRecursive(root, ast); + + if (lookupObjects.contains(ast)) + activated--; } void MapObjectWithDebugReference::processRecursive(const QDeclarativeDebugObjectReference& object, UiObjectMember* ast) @@ -54,8 +82,16 @@ void MapObjectWithDebugReference::processRecursive(const QDeclarativeDebugObject // the QDeclarativeDebugObjectReference by filename/loc in a fist pass SourceLocation loc = ast->firstSourceLocation(); - if (object.source().lineNumber() == int(loc.startLine) && object.source().columnNumber() == int(loc.startColumn) && object.source().url().toLocalFile() == filename) { - result[ast] += object; + if (object.source().columnNumber() == int(loc.startColumn)) { + QString objectFileName = object.source().url().toLocalFile(); + if (object.source().lineNumber() == int(loc.startLine) && objectFileName == filename) { + result[ast] += object; + } else if (doc && objectFileName.startsWith(filename + QLatin1Char('_') + QString::number(doc->editorRevision()) + QLatin1Char(':'))) { + bool ok; + int line = objectFileName.mid(objectFileName.lastIndexOf(':') + 1).toInt(&ok); + if (ok && int(loc.startLine) == line + object.source().lineNumber() - 1) + result[ast] += object; + } } foreach (const QDeclarativeDebugObjectReference &it, object.children()) { @@ -214,6 +250,28 @@ void QmlJSLiveTextPreview::updateDebugIds(const QDeclarativeDebugObjectReference if (!r.isEmpty()) m_debugIds[root] += r; } + + // Map the node of the later created objects. + for(QHash<Document::Ptr,QSet<UiObjectMember*> >::const_iterator it = m_createdObjects.constBegin(); + it != m_createdObjects.constEnd(); ++it) { + + const QmlJS::Document::Ptr &doc = it.key(); + MapObjectWithDebugReference visitor; + visitor.root = rootReference; + visitor.filename = doc->fileName(); + visitor.lookupObjects = it.value(); + visitor.doc = doc; + doc->qmlProgram()->accept(&visitor); + + Delta::DebugIdMap debugIds = visitor.result; + Delta delta; + delta.doNotSendChanges = true; + debugIds = delta(doc, m_previousDoc, debugIds); + for(Delta::DebugIdMap::const_iterator it2 = debugIds.constBegin(); + it2 != debugIds.constEnd(); ++it2) { + m_debugIds[it2.key()] += it2.value(); + } + } } void QmlJSLiveTextPreview::documentChanged(QmlJS::Document::Ptr doc) @@ -237,6 +295,8 @@ void QmlJSLiveTextPreview::documentChanged(QmlJS::Document::Ptr doc) ClientProxy::instance()->refreshObjectTree(); m_previousDoc = doc; + if (!delta.newObjects.isEmpty()) + m_createdObjects[doc] += delta.newObjects; } } diff --git a/src/plugins/qmljsinspector/qmljslivetextpreview.h b/src/plugins/qmljsinspector/qmljslivetextpreview.h index 82651aa327c..1f2410a7be6 100644 --- a/src/plugins/qmljsinspector/qmljslivetextpreview.h +++ b/src/plugins/qmljsinspector/qmljslivetextpreview.h @@ -56,6 +56,7 @@ private: private: QHash<QmlJS::AST::UiObjectMember*, QList<QDeclarativeDebugObjectReference> > m_debugIds; + QHash<QmlJS::Document::Ptr, QSet<QmlJS::AST::UiObjectMember *> > m_createdObjects; QmlJS::Document::Ptr m_previousDoc; QmlJS::Document::Ptr m_initialDoc; //the document that was loaded by the server diff --git a/src/tools/qml/qmlobserver/editor/qmltoolbar.cpp b/src/tools/qml/qmlobserver/editor/qmltoolbar.cpp index 06ba69f7c50..333616289c0 100644 --- a/src/tools/qml/qmlobserver/editor/qmltoolbar.cpp +++ b/src/tools/qml/qmlobserver/editor/qmltoolbar.cpp @@ -12,6 +12,7 @@ namespace QmlViewer { QmlToolbar::QmlToolbar(QWidget *parent) : QToolBar(parent), m_emitSignals(true), + m_isRunning(false), ui(new Ui) { ui->designmode = new QAction(QIcon(":/qml/images/designmode.png"), tr("Design Mode"), this); -- GitLab