Commit 4ecad983 authored by Lasse Holmstedt's avatar Lasse Holmstedt Committed by Olivier Goffart
Browse files

added multiselection from editor to qml viewer

parent 8f528e24
......@@ -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()
......
......@@ -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();
......
......@@ -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()) {
......
......@@ -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
......@@ -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);
......
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