diff --git a/src/plugins/cppeditor/cppinsertdecldef.cpp b/src/plugins/cppeditor/cppinsertdecldef.cpp index ac66b05c60560248adf1c654e58a808af62f01ad..4a4f4ffa9e59043b439404ece1df1a22b9a8c874 100644 --- a/src/plugins/cppeditor/cppinsertdecldef.cpp +++ b/src/plugins/cppeditor/cppinsertdecldef.cpp @@ -458,11 +458,8 @@ public: if (!extract.endsWith(QLatin1Char('\n')) && m_funcReturn) extract.append(QLatin1Char('\n')); - // FIXME: There are a couple related issues on the refactoring interface. You cannot - // simply have distinct indentation ranges within a chunk of content to be added, regardless - // of whether this is done through more than on change. That's why we actually apply twice, - // initially indenting the definition stub and the reindenting the original extraction. - // More details on the refactorings impl. where ranges are transformed into cursors. + // Since we need an indent range and a nested reindent range (based on the original + // formatting) it's simpler to have two different change sets. Utils::ChangeSet change; int position = currentFile->startOf(m_refFuncDef); change.insert(position, funcDef); @@ -472,8 +469,8 @@ public: currentFile->apply(); QTextCursor tc = currentFile->document()->find(QLatin1String("{"), position); - QTC_ASSERT(!tc.isNull(), return); - position = tc.position() + 2; + QTC_ASSERT(tc.hasSelection(), return); + position = tc.selectionEnd() + 1; change.clear(); change.insert(position, extract); currentFile->setChangeSet(change); diff --git a/src/plugins/texteditor/refactoringchanges.cpp b/src/plugins/texteditor/refactoringchanges.cpp index f35c61d146f0e2e62325c42b1e72694ebcf9f47f..42baa54829e379b23082dd158de01adb13da96b6 100644 --- a/src/plugins/texteditor/refactoringchanges.cpp +++ b/src/plugins/texteditor/refactoringchanges.cpp @@ -73,26 +73,19 @@ BaseTextEditorWidget *RefactoringChanges::editorForFile(const QString &fileName) return 0; } -QList<QTextCursor> RefactoringChanges::rangesToSelections(QTextDocument *document, const QList<Range> &ranges) +QList<QPair<QTextCursor, QTextCursor > > RefactoringChanges::rangesToSelections(QTextDocument *document, + const QList<Range> &ranges) { - QList<QTextCursor> selections; + QList<QPair<QTextCursor, QTextCursor> > selections; foreach (const Range &range, ranges) { - QTextCursor selection(document); - // FIXME: The subtraction below for the start range might create a selection on a different - // block, which could cause unexpected effects on indentation for example when the range is - // precisely calculate. Since this cursor moves when content is inserted, it might not be - // possible to compensate for such a difference in advance because the value could be - // negative (which would eventually be right after content is inserted) and then taken as 0. - // A proper way for allowing fine granularly specified ranges would be to have two cursors - // and the first one with *keepPositionOnInsert*, for example, like it's done for the text - // editor overlay. - - // ### workaround for moving the textcursor when inserting text at the beginning of the range. - selection.setPosition(qMax(0, range.start - 1)); - selection.setPosition(qMin(range.end, document->characterCount() - 1), QTextCursor::KeepAnchor); - - selections.append(selection); + QTextCursor start(document); + start.setPosition(range.start); + start.setKeepPositionOnInsert(true); + QTextCursor end(document); + end.setPosition(qMin(range.end, document->characterCount() - 1)); + + selections.append(qMakePair(start, end)); } return selections; @@ -363,10 +356,10 @@ void RefactoringFile::apply() c.beginEditBlock(); // build indent selections now, applying the changeset will change locations - const QList<QTextCursor> &indentSelections = + const QList<QPair<QTextCursor, QTextCursor> > &indentSelections = RefactoringChanges::rangesToSelections(doc, m_indentRanges); m_indentRanges.clear(); - const QList<QTextCursor> &reindentSelections = + const QList<QPair<QTextCursor, QTextCursor> > &reindentSelections = RefactoringChanges::rangesToSelections(doc, m_reindentRanges); m_reindentRanges.clear(); @@ -374,10 +367,8 @@ void RefactoringFile::apply() m_changes.apply(&c); m_changes.clear(); - foreach (const QTextCursor &selection, indentSelections) - m_data->indentSelection(selection, m_fileName, m_editor); - foreach (const QTextCursor &selection, reindentSelections) - m_data->reindentSelection(selection, m_fileName, m_editor); + indentOrReindent(&RefactoringChangesData::indentSelection, indentSelections); + indentOrReindent(&RefactoringChangesData::reindentSelection, reindentSelections); c.endEditBlock(); @@ -396,6 +387,20 @@ void RefactoringFile::apply() m_appliedOnce = true; } +void RefactoringFile::indentOrReindent(void (RefactoringChangesData::*mf)(const QTextCursor &, + const QString &, + const BaseTextEditorWidget *) const, + const QList<QPair<QTextCursor, QTextCursor> > &ranges) +{ + QPair<QTextCursor, QTextCursor> p; + foreach (p, ranges) { + QTextCursor selection(p.first.document()); + selection.setPosition(p.first.position()); + selection.setPosition(p.second.position(), QTextCursor::KeepAnchor); + ((*m_data).*(mf))(selection, m_fileName, m_editor); + } +} + void RefactoringFile::fileChanged() { if (!m_fileName.isEmpty()) diff --git a/src/plugins/texteditor/refactoringchanges.h b/src/plugins/texteditor/refactoringchanges.h index 1e062db3e9d41c637d88b628a15c0141a0fd67ab..cda1fa466c210e7db5a46d73acc25d6fdd78dc7a 100644 --- a/src/plugins/texteditor/refactoringchanges.h +++ b/src/plugins/texteditor/refactoringchanges.h @@ -40,6 +40,7 @@ #include <QtCore/QList> #include <QtCore/QString> #include <QtCore/QSharedPointer> +#include <QtCore/QPair> QT_BEGIN_NAMESPACE class QTextDocument; @@ -96,6 +97,11 @@ protected: // derived classes may want to clear language specific extra data virtual void fileChanged(); + void indentOrReindent(void (RefactoringChangesData::*mf)(const QTextCursor &, + const QString &, + const BaseTextEditorWidget *) const, + const QList<QPair<QTextCursor, QTextCursor> > &ranges); + protected: QString m_fileName; QSharedPointer<RefactoringChangesData> m_data; @@ -138,7 +144,8 @@ protected: static BaseTextEditorWidget *openEditor(const QString &fileName, bool activate, int line, int column); - static QList<QTextCursor> rangesToSelections(QTextDocument *document, const QList<Range> &ranges); + static QList<QPair<QTextCursor, QTextCursor> > rangesToSelections(QTextDocument *document, + const QList<Range> &ranges); protected: QSharedPointer<RefactoringChangesData> m_data;