diff --git a/src/plugins/qmljseditor/qmljseditor.cpp b/src/plugins/qmljseditor/qmljseditor.cpp index aed08c0180afe18af22d3db37444191634c79594..f06c138663c3bef03653e7451fed91fba30a18b5 100644 --- a/src/plugins/qmljseditor/qmljseditor.cpp +++ b/src/plugins/qmljseditor/qmljseditor.cpp @@ -857,19 +857,23 @@ void QmlJSTextEditor::updateUsesNow() class SelectedElement: protected Visitor { - unsigned cursorPosition; - UiObjectMember *selectedMember; + unsigned cursorPositionStart; + unsigned cursorPositionEnd; + UiObjectMember *containedBy; + QList<UiObjectMember *> selectedMembers; public: SelectedElement() - : cursorPosition(0), selectedMember(0) {} + : cursorPositionStart(0), cursorPositionEnd(0) {} - UiObjectMember *operator()(Node *root, unsigned position) + QList<UiObjectMember *> operator()(Node *root, unsigned startPosition, unsigned endPosition) { - cursorPosition = position; - selectedMember = 0; + containedBy = false; + cursorPositionStart = startPosition; + cursorPositionEnd = endPosition; + selectedMembers.clear(); Node::accept(root, this); - return selectedMember; + return selectedMembers; } protected: @@ -901,20 +905,38 @@ protected: return false; } + bool containsCursor(unsigned begin, unsigned end) + { + return cursorPositionStart >= begin && cursorPositionEnd <= end; + } + + bool intersectsCursor(unsigned begin, unsigned end) + { + return (cursorPositionEnd >= begin && cursorPositionStart <= end); + } + virtual void postVisit(Node *ast) { - if (selectedMember) - return; // nothing to do, we already have the result. + if ((cursorPositionStart == cursorPositionEnd && !selectedMembers.isEmpty()) + /*|| (cursorPositionStart != cursorPositionEnd && containedBy != 0)*/) + return; // nothing to do, we already have the results. if (UiObjectMember *member = ast->uiObjectMemberCast()) { unsigned begin = member->firstSourceLocation().begin(); unsigned end = member->lastSourceLocation().end(); - if (cursorPosition >= begin && cursorPosition <= end) { + if ((cursorPositionStart != cursorPositionEnd && intersectsCursor(begin, end)) + || (cursorPositionStart == cursorPositionEnd && containsCursor(begin, end))) + { + if (containsCursor(begin, end)) + containedBy = member; + if (UiObjectInitializer *init = initializer(member)) { for (UiObjectMemberList *it = init->members; it; it = it->next) { if (isIdBinding(it->member)) { - selectedMember = member; + selectedMembers << member; + // move start towards end; this facilitates multiselection so that root is usually ignored. + cursorPositionStart = qMin(end, cursorPositionEnd); break; } } @@ -927,18 +949,37 @@ protected: void QmlJSTextEditor::setSelectedElement() { QTextCursor tc = textCursor(); - tc.movePosition(QTextCursor::StartOfWord); - tc.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor); - QString wordAtCursor = tc.selectedText(); + QString wordAtCursor; + QList<int> offsets; + + unsigned startPos; + unsigned endPos; + + if (tc.hasSelection()) { + startPos = tc.selectionStart(); + endPos = tc.selectionEnd(); + } else { + tc.movePosition(QTextCursor::StartOfWord); + tc.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor); + + startPos = textCursor().position(); + endPos = textCursor().position(); + } - int offset = -1; if (Document::Ptr doc = m_semanticInfo.document) { - SelectedElement selectedMember; - if (UiObjectMember *m = selectedMember(doc->qmlProgram(), textCursor().position())) { - offset = m->firstSourceLocation().begin(); + SelectedElement selectedMembers; + + QList<UiObjectMember *> members = selectedMembers(doc->qmlProgram(), startPos, endPos); + + if (!members.isEmpty()) { + foreach(UiObjectMember *m, members) { + offsets << m->firstSourceLocation().begin(); + } } } - emit selectedElementChanged(offset, wordAtCursor); + wordAtCursor = tc.selectedText(); + + emit selectedElementsChanged(offsets, wordAtCursor); } void QmlJSTextEditor::updateMethodBoxToolTip() diff --git a/src/plugins/qmljseditor/qmljseditor.h b/src/plugins/qmljseditor/qmljseditor.h index cb5ec05c0832e03d59f8b58565d30d9988dc94b4..e2916f473323a9e7ad082e8980b7777de6ae844c 100644 --- a/src/plugins/qmljseditor/qmljseditor.h +++ b/src/plugins/qmljseditor/qmljseditor.h @@ -217,7 +217,7 @@ public: bool isOutdated() const; signals: - void selectedElementChanged(int offset, const QString &wordAtCursor); + void selectedElementsChanged(QList<int> offsets, const QString &wordAtCursor); public slots: void followSymbolUnderCursor(); diff --git a/src/plugins/qmljsinspector/qmljsclientproxy.cpp b/src/plugins/qmljsinspector/qmljsclientproxy.cpp index 7cc8ba1dff106994e264563f70eeae5704115a3e..705f6a73bfac79db5898c3fdeb912fb700cedcc9 100644 --- a/src/plugins/qmljsinspector/qmljsclientproxy.cpp +++ b/src/plugins/qmljsinspector/qmljsclientproxy.cpp @@ -238,7 +238,7 @@ QList<QDeclarativeDebugObjectReference> ClientProxy::objectReferences(const QUrl const QDeclarativeDebugObjectReference &objectRef) const { QList<QDeclarativeDebugObjectReference> result; - if (objectRef.source().url() == url) + if (objectRef.source().url() == url || url.isEmpty()) result.append(objectRef); foreach(const QDeclarativeDebugObjectReference &child, objectRef.children()) { diff --git a/src/plugins/qmljsinspector/qmljslivetextpreview.cpp b/src/plugins/qmljsinspector/qmljslivetextpreview.cpp index 0dd55e22451809fdb3bbe2fe165d347434b01b8e..6733d5289a56439ac49b4ddf35c13793c970ffd8 100644 --- a/src/plugins/qmljsinspector/qmljslivetextpreview.cpp +++ b/src/plugins/qmljsinspector/qmljslivetextpreview.cpp @@ -52,7 +52,7 @@ void QmlJSLiveTextPreview::updateDocuments() SLOT(documentChanged(QmlJS::Document::Ptr))); } -void QmlJSLiveTextPreview::changeSelectedElement(int offset, const QString &wordAtCursor) +void QmlJSLiveTextPreview::changeSelectedElements(QList<int> offsets, const QString &wordAtCursor) { if (!m_currentEditor) return; @@ -60,65 +60,73 @@ void QmlJSLiveTextPreview::changeSelectedElement(int offset, const QString &word ClientProxy *clientProxy = ClientProxy::instance(); QUrl url = QUrl::fromLocalFile(m_currentEditor.data()->file()->fileName()); QmlJS::Document::Ptr doc = modelManager()->snapshot().document(m_currentEditor.data()->file()->fileName()); - //ScriptBindingParser info(doc, clientProxy->objectReferences(url)); + ScriptBindingParser info(doc, clientProxy->objectReferences(url)); - QDeclarativeDebugObjectReference objectRef; + QDeclarativeDebugObjectReference objectRefUnderCursor; QList<QDeclarativeDebugObjectReference> refs = clientProxy->objectReferences(); foreach (const QDeclarativeDebugObjectReference &ref, refs) { if (ref.idString() == wordAtCursor) { - objectRef = ref; + objectRefUnderCursor = ref; break; } } - /* FIXME - if (objectRef.debugId() == -1 && offset >= 0) { - objectRef = info.objectReferenceForOffset(offset); - }*/ + QList<QDeclarativeDebugObjectReference> selectedReferences; - if (objectRef.debugId() != -1) - emit selectedItemsChanged(QList<QDeclarativeDebugObjectReference>() << objectRef); + foreach(int offset, offsets) { + if (offset >= 0) { + QDeclarativeDebugObjectReference ref = info.objectReferenceForOffset(offset); + if (ref.debugId() != -1) + selectedReferences << ref; + } + } + + bool containsReference = false; + foreach(const QDeclarativeDebugObjectReference &ref, selectedReferences) { + if (ref.debugId() == objectRefUnderCursor.debugId()) { + containsReference = true; + break; + } + } + + if (!containsReference && objectRefUnderCursor.debugId() != -1) + selectedReferences << objectRefUnderCursor; + + if (!selectedReferences.isEmpty()) + emit selectedItemsChanged(selectedReferences); } void QmlJSLiveTextPreview::setEditor(Core::IEditor *editor) { if (!m_currentEditor.isNull()) { - disconnect(m_currentEditor.data(), SIGNAL(selectedElementChanged(int, QString)), this, SLOT(changeSelectedElement(int, QString))); + disconnect(m_currentEditor.data(), SIGNAL(selectedElementsChanged(QList<int>, QString)), this, SLOT(changeSelectedElements(QList<int>, QString))); m_currentEditor.clear(); m_previousDoc.clear(); } if (editor) { m_currentEditor = qobject_cast<QmlJSEditor::Internal::QmlJSTextEditor*>(editor->widget()); if (m_currentEditor) { - connect(m_currentEditor.data(), SIGNAL(selectedElementChanged(int, QString)), SLOT(changeSelectedElement(int, QString))); + connect(m_currentEditor.data(), SIGNAL(selectedElementsChanged(QList<int>, QString)), SLOT(changeSelectedElements(QList<int>, QString))); m_previousDoc = m_snapshot.document(editor->file()->fileName()); } } } - void QmlJSLiveTextPreview::documentChanged(QmlJS::Document::Ptr doc) -{ - /* FIXME +{ Core::ICore *core = Core::ICore::instance(); const int dbgcontext = core->uniqueIDManager()->uniqueIdentifier(Debugger::Constants::C_DEBUGMODE); if (!core->hasContext(dbgcontext)) return; - */ if (doc && m_previousDoc && doc->fileName() == m_previousDoc->fileName()) { - - if (m_debugIds.isEmpty()) - m_debugIds = m_initialTable.value(doc->fileName()); Delta delta; - m_debugIds = delta(m_previousDoc, doc, m_debugIds); + delta(doc, m_previousDoc); m_previousDoc = doc; - } } - } // namespace Internal } // namespace QmlJSInspector diff --git a/src/plugins/qmljsinspector/qmljslivetextpreview.h b/src/plugins/qmljsinspector/qmljslivetextpreview.h index a843c914b9ccffadf01ff6c70520086612c3bac6..5f4469d1b509c8f849e8c2436f4a0152b741ad6f 100644 --- a/src/plugins/qmljsinspector/qmljslivetextpreview.h +++ b/src/plugins/qmljsinspector/qmljslivetextpreview.h @@ -47,7 +47,7 @@ signals: void selectedItemsChanged(const QList<QDeclarativeDebugObjectReference> &objects); private slots: - void changeSelectedElement(int offset, const QString &wordAtCursor); + void changeSelectedElements(QList<int> offsets, const QString &wordAtCursor); void documentChanged(QmlJS::Document::Ptr doc); void setEditor(Core::IEditor *editor);