summaryrefslogtreecommitdiff
path: root/src/plugins/texteditor/refactoringchanges.cpp
diff options
context:
space:
mode:
authorChristian Kamm <christian.d.kamm@nokia.com>2011-08-17 11:35:57 +0200
committerChristian Kamm <christian.d.kamm@nokia.com>2011-08-19 11:12:09 +0200
commit8a6d767a8f2f98ea4e04847f92cff40d661b806f (patch)
tree586e5c539adfbb18623246d00dec5e894288c8e1 /src/plugins/texteditor/refactoringchanges.cpp
parenta07acad516b5fa1ac503493b4ec28d595f6e1ea0 (diff)
downloadqt-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.cpp247
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 &)
+{
}