From 8224c1c95df481ad34fad3f699e67db42bc8b6ea Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Wed, 19 Oct 2016 16:44:25 +0200 Subject: [PATCH] DiffEditor: fix revert chunk for diffs of modified files Apply chunk action doesn't make sense for that case, will stay disabled. Task-number: QTCREATORBUG-17136 Change-Id: Idce31b3aa9d354536a01607c10b20273158961d5 Reviewed-by: Tobias Hunger --- src/plugins/diffeditor/diffeditordocument.cpp | 11 ++-- src/plugins/diffeditor/diffeditordocument.h | 4 +- src/plugins/diffeditor/diffeditorplugin.cpp | 3 + .../diffeditor/diffeditorwidgetcontroller.cpp | 55 +++++++++++++++---- src/plugins/diffeditor/diffutils.h | 6 ++ src/plugins/texteditor/textdocument.cpp | 19 ++++++- src/plugins/texteditor/textdocument.h | 1 + 7 files changed, 81 insertions(+), 18 deletions(-) diff --git a/src/plugins/diffeditor/diffeditordocument.cpp b/src/plugins/diffeditor/diffeditordocument.cpp index 5102df44d96..5a4d575d9c2 100644 --- a/src/plugins/diffeditor/diffeditordocument.cpp +++ b/src/plugins/diffeditor/diffeditordocument.cpp @@ -87,7 +87,9 @@ DiffEditorController *DiffEditorDocument::controller() const return m_controller; } -QString DiffEditorDocument::makePatch(int fileIndex, int chunkIndex, bool revert, bool addPrefix) const +QString DiffEditorDocument::makePatch(int fileIndex, int chunkIndex, + bool revert, bool addPrefix, + const QString &overriddenFileName) const { if (fileIndex < 0 || chunkIndex < 0) return QString(); @@ -102,9 +104,10 @@ QString DiffEditorDocument::makePatch(int fileIndex, int chunkIndex, bool revert const ChunkData &chunkData = fileData.chunks.at(chunkIndex); const bool lastChunk = (chunkIndex == fileData.chunks.count() - 1); - const QString fileName = revert - ? fileData.rightFileInfo.fileName - : fileData.leftFileInfo.fileName; + const QString fileName = !overriddenFileName.isEmpty() + ? overriddenFileName : revert + ? fileData.rightFileInfo.fileName + : fileData.leftFileInfo.fileName; QString leftPrefix, rightPrefix; if (addPrefix) { diff --git a/src/plugins/diffeditor/diffeditordocument.h b/src/plugins/diffeditor/diffeditordocument.h index 5b4771b0e71..18864711fe7 100644 --- a/src/plugins/diffeditor/diffeditordocument.h +++ b/src/plugins/diffeditor/diffeditordocument.h @@ -46,7 +46,9 @@ public: DiffEditorController *controller() const; - QString makePatch(int fileIndex, int chunkIndex, bool revert, bool addPrefix = false) const; + QString makePatch(int fileIndex, int chunkIndex, + bool revert, bool addPrefix = false, + const QString &overriddenFileName = QString()) const; void setDiffFiles(const QList &data, const QString &directory, const QString &startupFile = QString()); diff --git a/src/plugins/diffeditor/diffeditorplugin.cpp b/src/plugins/diffeditor/diffeditorplugin.cpp index ac697055008..4eb0a07878a 100644 --- a/src/plugins/diffeditor/diffeditorplugin.cpp +++ b/src/plugins/diffeditor/diffeditorplugin.cpp @@ -143,6 +143,7 @@ void DiffCurrentFileController::reload() fileData.rightFileInfo.fileName = m_fileName; fileData.leftFileInfo.typeInfo = tr("Saved"); fileData.rightFileInfo.typeInfo = tr("Modified"); + fileData.rightFileInfo.patchBehaviour = DiffFileInfo::PatchEditor; if (!leftFileExists) fileData.fileOperation = FileData::NewFile; @@ -201,6 +202,7 @@ void DiffOpenFilesController::reload() fileData.rightFileInfo.fileName = fileName; fileData.leftFileInfo.typeInfo = tr("Saved"); fileData.rightFileInfo.typeInfo = tr("Modified"); + fileData.rightFileInfo.patchBehaviour = DiffFileInfo::PatchEditor; if (!leftFileExists) fileData.fileOperation = FileData::NewFile; @@ -261,6 +263,7 @@ void DiffModifiedFilesController::reload() fileData.rightFileInfo.fileName = fileName; fileData.leftFileInfo.typeInfo = tr("Saved"); fileData.rightFileInfo.typeInfo = tr("Modified"); + fileData.rightFileInfo.patchBehaviour = DiffFileInfo::PatchEditor; if (!leftFileExists) fileData.fileOperation = FileData::NewFile; diff --git a/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp b/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp index 8c4e182b229..3e30a0d8204 100644 --- a/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp +++ b/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp @@ -32,6 +32,7 @@ #include #include +#include #include @@ -42,6 +43,7 @@ #include #include #include +#include #include using namespace Core; @@ -77,27 +79,60 @@ void DiffEditorWidgetController::patch(bool revert) return; } - const int strip = m_document->baseDirectory().isEmpty() ? -1 : 0; - const FileData fileData = m_contextFileData.at(m_contextMenuFileIndex); const QString fileName = revert ? fileData.rightFileInfo.fileName : fileData.leftFileInfo.fileName; + const DiffFileInfo::PatchBehaviour patchBehaviour = revert + ? fileData.rightFileInfo.patchBehaviour + : fileData.leftFileInfo.patchBehaviour; const QString workingDirectory = m_document->baseDirectory().isEmpty() ? QFileInfo(fileName).absolutePath() : m_document->baseDirectory(); + const QString absFileName = QFileInfo(workingDirectory + '/' + QFileInfo(fileName).fileName()).absoluteFilePath(); - const QString patch = m_document->makePatch(m_contextMenuFileIndex, m_contextMenuChunkIndex, revert); + if (patchBehaviour == DiffFileInfo::PatchFile) { + const int strip = m_document->baseDirectory().isEmpty() ? -1 : 0; - if (patch.isEmpty()) - return; + const QString patch = m_document->makePatch(m_contextMenuFileIndex, m_contextMenuChunkIndex, revert); - const QString absFileName = QFileInfo(workingDirectory + '/' + fileName).absoluteFilePath(); - FileChangeBlocker fileChangeBlocker(absFileName); - if (PatchTool::runPatch(EditorManager::defaultTextCodec()->fromUnicode(patch), - workingDirectory, strip, revert)) - m_document->reload(); + if (patch.isEmpty()) + return; + + FileChangeBlocker fileChangeBlocker(absFileName); + if (PatchTool::runPatch(EditorManager::defaultTextCodec()->fromUnicode(patch), + workingDirectory, strip, revert)) + m_document->reload(); + } else { // PatchEditor + TextEditor::TextDocument *textDocument = qobject_cast( + DocumentModel::documentForFilePath(absFileName)); + if (!textDocument) + return; + + QTemporaryFile contentsCopy; + if (!contentsCopy.open()) + return; + + contentsCopy.write(textDocument->contents()); + contentsCopy.close(); + + const QString contentsCopyFileName = contentsCopy.fileName(); + const QString contentsCopyDir = QFileInfo(contentsCopyFileName).absolutePath(); + + const QString patch = m_document->makePatch(m_contextMenuFileIndex, + m_contextMenuChunkIndex, revert, false, QFileInfo(contentsCopyFileName).fileName()); + + if (patch.isEmpty()) + return; + + if (PatchTool::runPatch(EditorManager::defaultTextCodec()->fromUnicode(patch), + contentsCopyDir, 0, revert)) { + QString errorString; + if (textDocument->reload(&errorString, contentsCopyFileName)) + m_document->reload(); + } + } } void DiffEditorWidgetController::jumpToOriginalFile(const QString &fileName, diff --git a/src/plugins/diffeditor/diffutils.h b/src/plugins/diffeditor/diffutils.h index 417309294b9..d588a52ad8f 100644 --- a/src/plugins/diffeditor/diffutils.h +++ b/src/plugins/diffeditor/diffutils.h @@ -38,12 +38,18 @@ class Diff; class DIFFEDITOR_EXPORT DiffFileInfo { public: + enum PatchBehaviour { + PatchFile, + PatchEditor + }; + DiffFileInfo() {} DiffFileInfo(const QString &file) : fileName(file) {} DiffFileInfo(const QString &file, const QString &type) : fileName(file), typeInfo(type) {} QString fileName; QString typeInfo; + PatchBehaviour patchBehaviour = PatchFile; }; class DIFFEDITOR_EXPORT TextLineData { diff --git a/src/plugins/texteditor/textdocument.cpp b/src/plugins/texteditor/textdocument.cpp index dc7bd87296f..7c1e3157ab8 100644 --- a/src/plugins/texteditor/textdocument.cpp +++ b/src/plugins/texteditor/textdocument.cpp @@ -634,7 +634,11 @@ Core::IDocument::OpenResult TextDocument::openImpl(QString *errorString, const Q readResult = read(realFileName, &content, errorString); const int chunks = content.size(); - d->m_document.setUndoRedoEnabled(reload); + // Don't call setUndoRedoEnabled(true) when reload is true and filenames are different, + // since it will reset the undo's clear index + if (!reload || fileName == realFileName) + d->m_document.setUndoRedoEnabled(reload); + QTextCursor c(&d->m_document); c.beginEditBlock(); if (reload) { @@ -663,7 +667,11 @@ Core::IDocument::OpenResult TextDocument::openImpl(QString *errorString, const Q } c.endEditBlock(); - d->m_document.setUndoRedoEnabled(true); + + // Don't call setUndoRedoEnabled(true) when reload is true and filenames are different, + // since it will reset the undo's clear index + if (!reload || fileName == realFileName) + d->m_document.setUndoRedoEnabled(true); TextDocumentLayout *documentLayout = qobject_cast(d->m_document.documentLayout()); @@ -686,6 +694,11 @@ bool TextDocument::reload(QString *errorString, QTextCodec *codec) } bool TextDocument::reload(QString *errorString) +{ + return reload(errorString, filePath().toString()); +} + +bool TextDocument::reload(QString *errorString, const QString &realFileName) { emit aboutToReload(); TextDocumentLayout *documentLayout = @@ -695,7 +708,7 @@ bool TextDocument::reload(QString *errorString) marks = documentLayout->documentClosing(); // removes text marks non-permanently const QString &file = filePath().toString(); - bool success = openImpl(errorString, file, file, /*reload =*/ true) == OpenResult::Success; + bool success = openImpl(errorString, file, realFileName, /*reload =*/ true) == OpenResult::Success; if (documentLayout) documentLayout->documentReloaded(marks, this); // re-adds text marks diff --git a/src/plugins/texteditor/textdocument.h b/src/plugins/texteditor/textdocument.h index 30576043b40..4bb466382ca 100644 --- a/src/plugins/texteditor/textdocument.h +++ b/src/plugins/texteditor/textdocument.h @@ -118,6 +118,7 @@ public: OpenResult open(QString *errorString, const QString &fileName, const QString &realFileName) override; virtual bool reload(QString *errorString); + bool reload(QString *errorString, const QString &realFileName); bool setPlainText(const QString &text); QTextDocument *document() const;