diff options
author | Christian Kamm <christian.d.kamm@nokia.com> | 2011-08-17 11:35:57 +0200 |
---|---|---|
committer | Christian Kamm <christian.d.kamm@nokia.com> | 2011-08-19 11:12:09 +0200 |
commit | 8a6d767a8f2f98ea4e04847f92cff40d661b806f (patch) | |
tree | 586e5c539adfbb18623246d00dec5e894288c8e1 /src/plugins/texteditor/refactoringchanges.cpp | |
parent | a07acad516b5fa1ac503493b4ec28d595f6e1ea0 (diff) | |
download | qt-creator-8a6d767a8f2f98ea4e04847f92cff40d661b806f.tar.gz |
Refactoring changes: Cleanup and improvements.
Previously RefactoringFiles were usually passed around by value.
However, since a RefactoringFile may sometimes own a QTextDocument
(when it was read from a file), that's not great and caused the
file to be reread after every copy.
With this change RefactoringFile becomes noncopyable and is always
owned by a shared pointer.
This change also allowed having const RefactoringFiles which is
useful because they can be safely used from other threads. See
CppRefactoringChanges::fileNoEditor.
Change-Id: I9045921d6d0f6349f9558ff2a3d8317ea172193b
Reviewed-on: http://codereview.qt.nokia.com/3084
Reviewed-by: Leandro T. C. Melo <leandro.melo@nokia.com>
Diffstat (limited to 'src/plugins/texteditor/refactoringchanges.cpp')
-rw-r--r-- | src/plugins/texteditor/refactoringchanges.cpp | 247 |
1 files changed, 130 insertions, 117 deletions
diff --git a/src/plugins/texteditor/refactoringchanges.cpp b/src/plugins/texteditor/refactoringchanges.cpp index 60d5fb0862..b81ff89494 100644 --- a/src/plugins/texteditor/refactoringchanges.cpp +++ b/src/plugins/texteditor/refactoringchanges.cpp @@ -50,17 +50,17 @@ using namespace TextEditor; RefactoringChanges::RefactoringChanges() + : m_data(new RefactoringChangesData) +{} + +RefactoringChanges::RefactoringChanges(RefactoringChangesData *data) + : m_data(data) {} RefactoringChanges::~RefactoringChanges() -{ - if (!m_fileToOpen.isEmpty()) { - BaseTextEditorWidget::openEditorAt(m_fileToOpen, m_lineToOpen, m_columnToOpen); - } -} +{} -BaseTextEditorWidget *RefactoringChanges::editorForFile(const QString &fileName, - bool openIfClosed) +BaseTextEditorWidget *RefactoringChanges::editorForFile(const QString &fileName) { Core::EditorManager *editorManager = Core::EditorManager::instance(); @@ -70,20 +70,7 @@ BaseTextEditorWidget *RefactoringChanges::editorForFile(const QString &fileName, if (textEditor != 0) return textEditor; } - - if (!openIfClosed) - return 0; - - QFile file(fileName); - if (!file.exists()) { - if (!file.open(QIODevice::Append)) - return 0; - file.close(); - } - - Core::IEditor *editor = editorManager->openEditor(fileName, QString(), - Core::EditorManager::NoActivate | Core::EditorManager::IgnoreNavigationHistory); - return qobject_cast<BaseTextEditorWidget *>(editor->widget()); + return 0; } QList<QTextCursor> RefactoringChanges::rangesToSelections(QTextDocument *document, const QList<Range> &ranges) @@ -102,12 +89,15 @@ QList<QTextCursor> RefactoringChanges::rangesToSelections(QTextDocument *documen return selections; } -bool RefactoringChanges::createFile(const QString &fileName, const QString &contents, bool reindent, bool openEditor) +bool RefactoringChanges::createFile(const QString &fileName, const QString &contents, bool reindent, bool openEditor) const { if (QFile::exists(fileName)) return false; - BaseTextEditorWidget *editor = editorForFile(fileName, openEditor); + BaseTextEditorWidget *editor = editorForFile(fileName); + if (!editor && openEditor) { + editor = this->openEditor(fileName, false, -1, -1); + } QTextDocument *document; if (editor) @@ -123,7 +113,7 @@ bool RefactoringChanges::createFile(const QString &fileName, const QString &cont if (reindent) { cursor.select(QTextCursor::Document); - indentSelection(cursor, fileName, editor); + m_data->indentSelection(cursor, fileName, editor); } cursor.endEditBlock(); @@ -137,12 +127,12 @@ bool RefactoringChanges::createFile(const QString &fileName, const QString &cont return false; } - fileChanged(fileName); + m_data->fileChanged(fileName); return true; } -bool RefactoringChanges::removeFile(const QString &fileName) +bool RefactoringChanges::removeFile(const QString &fileName) const { if (!QFile::exists(fileName)) return false; @@ -152,119 +142,70 @@ bool RefactoringChanges::removeFile(const QString &fileName) return true; } -RefactoringFile RefactoringChanges::file(const QString &fileName) +BaseTextEditorWidget *RefactoringChanges::openEditor(const QString &fileName, bool activate, int line, int column) { - if (QFile::exists(fileName)) - return RefactoringFile(fileName, this); - else - return RefactoringFile(); + Core::EditorManager::OpenEditorFlags flags = Core::EditorManager::IgnoreNavigationHistory; + if (!activate) + flags |= Core::EditorManager::NoActivate; + if (line != -1) { + // openEditorAt uses a 1-based line and a 0-based column! + column -= 1; + } + Core::IEditor *editor = BaseTextEditorWidget::openEditorAt( + fileName, line, column, QString(), flags); + return qobject_cast<BaseTextEditorWidget *>(editor->widget()); } -BaseTextEditorWidget *RefactoringChanges::openEditor(const QString &fileName, int pos) +RefactoringFilePtr RefactoringChanges::file(BaseTextEditorWidget *editor) { - BaseTextEditorWidget *editor = editorForFile(fileName, true); - if (pos != -1) { - QTextCursor cursor = editor->textCursor(); - cursor.setPosition(pos); - editor->setTextCursor(cursor); - } - return editor; + return RefactoringFilePtr(new RefactoringFile(editor)); } -void RefactoringChanges::activateEditor(const QString &fileName, int line, int column) +RefactoringFilePtr RefactoringChanges::file(const QString &fileName) const { - m_fileToOpen = fileName; - m_lineToOpen = line; - m_columnToOpen = column; + return RefactoringFilePtr(new RefactoringFile(fileName, m_data)); } - -RefactoringFile::RefactoringFile() - : m_refactoringChanges(0) - , m_document(0) - , m_editor(0) - , m_openEditor(false) -{ } - RefactoringFile::RefactoringFile(QTextDocument *document, const QString &fileName) : m_fileName(fileName) - , m_refactoringChanges(0) , m_document(document) , m_editor(0) , m_openEditor(false) + , m_activateEditor(false) + , m_editorCursorPosition(-1) { } RefactoringFile::RefactoringFile(BaseTextEditorWidget *editor) : m_fileName(editor->file()->fileName()) - , m_refactoringChanges(0) , m_document(0) , m_editor(editor) , m_openEditor(false) + , m_activateEditor(false) + , m_editorCursorPosition(-1) { } -RefactoringFile::RefactoringFile(const QString &fileName, RefactoringChanges *refactoringChanges) +RefactoringFile::RefactoringFile(const QString &fileName, const QSharedPointer<RefactoringChangesData> &data) : m_fileName(fileName) - , m_refactoringChanges(refactoringChanges) + , m_data(data) , m_document(0) , m_editor(0) , m_openEditor(false) + , m_activateEditor(false) + , m_editorCursorPosition(-1) { - m_editor = RefactoringChanges::editorForFile(fileName, false); -} - -RefactoringFile::RefactoringFile(const RefactoringFile &other) - : m_fileName(other.m_fileName) - , m_refactoringChanges(other.m_refactoringChanges) - , m_document(0) - , m_editor(other.m_editor) -{ - Q_ASSERT_X(!other.m_document && other.m_changes.isEmpty() && other.m_indentRanges.isEmpty(), - "RefactoringFile", "A refactoring file with changes is not copyable"); + m_editor = RefactoringChanges::editorForFile(fileName); } RefactoringFile::~RefactoringFile() { - if (m_refactoringChanges && m_openEditor && !m_fileName.isEmpty()) - m_editor = m_refactoringChanges->openEditor(m_fileName, -1); - - // apply changes, if any - if (m_refactoringChanges && !(m_indentRanges.isEmpty() && m_changes.isEmpty())) { - QTextDocument *doc = mutableDocument(); - { - QTextCursor c = cursor(); - c.beginEditBlock(); - - // build indent selections now, applying the changeset will change locations - const QList<QTextCursor> &indentSelections = - RefactoringChanges::rangesToSelections( - doc, m_indentRanges); - - // apply changes and reindent - m_changes.apply(&c); - foreach (const QTextCursor &selection, indentSelections) { - m_refactoringChanges->indentSelection(selection, m_fileName, m_editor); - } - - c.endEditBlock(); - } - - // if this document doesn't have an editor, write the result to a file - if (!m_editor && !m_fileName.isEmpty()) { - Utils::FileSaver saver(m_fileName); - saver.write(doc->toPlainText().toUtf8()); - saver.finalize(Core::ICore::instance()->mainWindow()); - } - - if (!m_fileName.isEmpty()) - m_refactoringChanges->fileChanged(m_fileName); - } - delete m_document; } bool RefactoringFile::isValid() const { - return !m_fileName.isEmpty(); + if (m_fileName.isEmpty()) + return false; + return document(); } const QTextDocument *RefactoringFile::document() const @@ -278,7 +219,7 @@ QTextDocument *RefactoringFile::mutableDocument() const return m_editor->document(); else if (!m_document) { QString fileContents; - if (!m_fileName.isEmpty()) { + if (!m_fileName.isEmpty() && QFile::exists(m_fileName)) { Utils::FileReader reader; if (reader.fetch(m_fileName, Core::ICore::instance()->mainWindow())) fileContents = QString::fromUtf8(reader.data()); @@ -292,8 +233,10 @@ const QTextCursor RefactoringFile::cursor() const { if (m_editor) return m_editor->textCursor(); - else if (!m_fileName.isEmpty()) - return QTextCursor(mutableDocument()); + else if (!m_fileName.isEmpty()) { + if (QTextDocument *doc = mutableDocument()) + return QTextCursor(doc); + } return QTextCursor(); } @@ -312,6 +255,17 @@ int RefactoringFile::position(unsigned line, unsigned column) const return -1; } +void RefactoringFile::lineAndColumn(int offset, unsigned *line, unsigned *column) const +{ + Q_ASSERT(line); + Q_ASSERT(column); + Q_ASSERT(offset >= 0); + QTextCursor c(cursor()); + c.setPosition(offset); + *line = c.blockNumber() + 1; + *column = c.positionInBlock() + 1; +} + QChar RefactoringFile::charAt(int pos) const { if (const QTextDocument *doc = document()) @@ -332,28 +286,87 @@ QString RefactoringFile::textOf(const Range &range) const return textOf(range.start, range.end); } -bool RefactoringFile::change(const Utils::ChangeSet &changeSet, bool openEditor) +void RefactoringFile::setChangeSet(const Utils::ChangeSet &changeSet) { if (m_fileName.isEmpty()) - return false; - if (!m_changes.isEmpty()) - return false; + return; m_changes = changeSet; - m_openEditor = openEditor; - - return true; } -bool RefactoringFile::indent(const Range &range, bool openEditor) +void RefactoringFile::appendIndentRange(const Range &range) { if (m_fileName.isEmpty()) - return false; + return; m_indentRanges.append(range); +} - if (openEditor) - m_openEditor = true; +void RefactoringFile::setOpenEditor(bool activate, int pos) +{ + m_openEditor = true; + m_activateEditor = activate; + m_editorCursorPosition = pos; +} - return true; +void RefactoringFile::apply() +{ + // open / activate / goto position + if (m_openEditor && !m_fileName.isEmpty()) { + unsigned line = -1, column = -1; + if (m_editorCursorPosition != -1) + lineAndColumn(m_editorCursorPosition, &line, &column); + m_editor = RefactoringChanges::openEditor(m_fileName, m_activateEditor, line, column); + m_openEditor = false; + m_activateEditor = false; + m_editorCursorPosition = -1; + } + + // apply changes, if any + if (m_data && !(m_indentRanges.isEmpty() && m_changes.isEmpty())) { + QTextDocument *doc = mutableDocument(); + if (doc) { + QTextCursor c(doc); + c.beginEditBlock(); + + // build indent selections now, applying the changeset will change locations + const QList<QTextCursor> &indentSelections = + RefactoringChanges::rangesToSelections( + doc, m_indentRanges); + m_indentRanges.clear(); + + // apply changes and reindent + m_changes.apply(&c); + m_changes.clear(); + foreach (const QTextCursor &selection, indentSelections) { + m_data->indentSelection(selection, m_fileName, m_editor); + } + + c.endEditBlock(); + } + + // if this document doesn't have an editor, write the result to a file + if (!m_editor && !m_fileName.isEmpty()) { + Utils::FileSaver saver(m_fileName); + saver.write(doc->toPlainText().toUtf8()); + saver.finalize(Core::ICore::instance()->mainWindow()); + } + + fileChanged(); + } +} + +void RefactoringFile::fileChanged() +{ + if (!m_fileName.isEmpty()) + m_data->fileChanged(m_fileName); +} + +void RefactoringChangesData::indentSelection(const QTextCursor &, const QString &, const BaseTextEditorWidget *) const +{ + qWarning() << Q_FUNC_INFO << "not implemented"; +} + +void RefactoringChangesData::fileChanged(const QString &) +{ } |