Commit 4d81efda authored by Friedemann Kleint's avatar Friedemann Kleint

VCS: Add a 'Apply patch chunk' pairing 'Revert chunk' to VCS editor.

Fix "Open With" editor-by-mimetype search to return all (diff) editors.

Change-Id: I8d9d3cee9e5fcee5555d6e301818ed22ad4390ac
Reviewed-on: default avatarQt Sanity Bot <>
Reviewed-by: default avatarFriedemann Kleint <>
parent 7c5c6fc8
......@@ -1039,7 +1039,6 @@ static void mimeTypeFactoryRecursion(const MimeDatabase *db,
if (firstMatchOnly)
// Any parent mime type classes? -> recurse
......@@ -122,6 +122,26 @@ QByteArray DiffChunk::asPatch() const
return rc;
namespace Internal {
// Data to be passed to apply/revert diff chunk actions.
class DiffChunkAction
DiffChunkAction(const DiffChunk &dc = DiffChunk(), bool revertIn = false) :
chunk(dc), revert(revertIn) {}
DiffChunk chunk;
bool revert;
} // namespace Internal
} // VCSBase
namespace VCSBase {
\class VCSBase::VCSBaseEditor
......@@ -554,11 +574,23 @@ void VCSBaseEditorWidget::contextMenuEvent(QContextMenuEvent *e)
connect(menu->addAction(tr("Send to CodePaster...")), SIGNAL(triggered()),
this, SLOT(slotPaste()));
QAction *revertAction = menu->addAction(tr("Revert Chunk..."));
// Apply/revert diff chunk.
const DiffChunk chunk = diffChunk(cursorForPosition(e->pos()));
connect(revertAction, SIGNAL(triggered()), this, SLOT(slotRevertDiffChunk()));
const bool canApply = canApplyDiffChunk(chunk);
// Apply a chunk from a diff loaded into the editor. This typically will
// not have the 'source' property set and thus will only work if the working
// directory matches that of the patch (see findDiffFile()). In addition,
// the user has "Open With" and choose the right diff editor so that
// fileNameFromDiffSpecification() works.
QAction *applyAction = menu->addAction(tr("Apply Chunk..."));
applyAction->setData(qVariantFromValue(Internal::DiffChunkAction(chunk, false)));
connect(applyAction, SIGNAL(triggered()), this, SLOT(slotApplyDiffChunk()));
// Revert a chunk from a VCS diff, which might be linked to reloading the diff.
QAction *revertAction = menu->addAction(tr("Revert Chunk..."));
revertAction->setEnabled(isRevertDiffChunkEnabled() && canApply);
revertAction->setData(qVariantFromValue(Internal::DiffChunkAction(chunk, true)));
connect(revertAction, SIGNAL(triggered()), this, SLOT(slotApplyDiffChunk()));
......@@ -1073,34 +1105,40 @@ void VCSBaseEditorWidget::setRevertDiffChunkEnabled(bool e)
d->m_revertChunkEnabled = e;
bool VCSBaseEditorWidget::canRevertDiffChunk(const DiffChunk &dc) const
bool VCSBaseEditorWidget::canApplyDiffChunk(const DiffChunk &dc) const
if (!isRevertDiffChunkEnabled() || !dc.isValid())
if (!dc.isValid())
return false;
const QFileInfo fi(dc.fileName);
// Default implementation using patch.exe relies on absolute paths.
return fi.isFile() && fi.isAbsolute() && fi.isWritable();
// Default implementation of revert: Revert a chunk by piping it into patch
// with '-R', assuming we got absolute paths from the VCS plugins.
bool VCSBaseEditorWidget::revertDiffChunk(const DiffChunk &dc) const
// Default implementation of revert: Apply a chunk by piping it into patch,
// (passing '-R' for revert), assuming we got absolute paths from the VCS plugins.
bool VCSBaseEditorWidget::applyDiffChunk(const DiffChunk &dc, bool revert) const
return VCSBasePlugin::runPatch(dc.asPatch(), QString(), 0, true);
return VCSBasePlugin::runPatch(dc.asPatch(), QString(), 0, revert);
void VCSBaseEditorWidget::slotRevertDiffChunk()
void VCSBaseEditorWidget::slotApplyDiffChunk()
const QAction *a = qobject_cast<QAction *>(sender());
QTC_ASSERT(a, return ; )
const DiffChunk chunk = qvariant_cast<DiffChunk>(a->data());
if (QMessageBox::No == QMessageBox::question(this, tr("Revert Chunk"),
tr("Would you like to revert the chunk?"),
const Internal::DiffChunkAction chunkAction = qvariant_cast<Internal::DiffChunkAction>(a->data());
const QString title = chunkAction.revert ? tr("Revert Chunk") : tr("Apply Chunk");
const QString question = chunkAction.revert ?
tr("Would you like to revert the chunk?") : tr("Would you like to apply the chunk?");
if (QMessageBox::No == QMessageBox::question(this, title, question, QMessageBox::Yes|QMessageBox::No))
if (revertDiffChunk(chunk))
emit diffChunkReverted(chunk);
if (applyDiffChunk(chunkAction.chunk, chunkAction.revert)) {
if (chunkAction.revert) {
emit diffChunkReverted(chunkAction.chunk);
} else {
emit diffChunkApplied(chunkAction.chunk);
// Tagging of editors for re-use.
......@@ -199,6 +199,7 @@ signals:
// for LogOutput/AnnotateOutput content types.
void describeRequested(const QString &source, const QString &change);
void annotateRevisionRequested(const QString &source, const QString &change, int lineNumber);
void diffChunkApplied(const VCSBase::DiffChunk &dc);
void diffChunkReverted(const VCSBase::DiffChunk &dc);
public slots:
......@@ -226,7 +227,7 @@ private slots:
void slotDiffCursorPositionChanged();
void slotAnnotateRevision();
void slotCopyRevision();
void slotRevertDiffChunk();
void slotApplyDiffChunk();
void slotPaste();
......@@ -235,9 +236,9 @@ protected:
* source and version control. */
QString findDiffFile(const QString &f, Core::IVersionControl *control = 0) const;
virtual bool canRevertDiffChunk(const DiffChunk &dc) const;
virtual bool canApplyDiffChunk(const DiffChunk &dc) const;
// Revert a patch chunk. Default implementation uses patch.exe
virtual bool revertDiffChunk(const DiffChunk &dc) const;
virtual bool applyDiffChunk(const DiffChunk &dc, bool revert = false) const;
// Implement to return a set of change identifiers in
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