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: http://codereview.qt.nokia.com/2912
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@nokia.com>
This commit is contained in:
Friedemann Kleint
2011-08-12 13:42:21 +02:00
parent 7c5c6fc88e
commit 4d81efda31
3 changed files with 59 additions and 21 deletions

View File

@@ -122,6 +122,26 @@ QByteArray DiffChunk::asPatch() const
return rc;
}
namespace Internal {
// Data to be passed to apply/revert diff chunk actions.
class DiffChunkAction
{
public:
DiffChunkAction(const DiffChunk &dc = DiffChunk(), bool revertIn = false) :
chunk(dc), revert(revertIn) {}
DiffChunk chunk;
bool revert;
};
} // namespace Internal
} // VCSBase
Q_DECLARE_METATYPE(VCSBase::Internal::DiffChunkAction)
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()));
menu->addSeparator();
QAction *revertAction = menu->addAction(tr("Revert Chunk..."));
// Apply/revert diff chunk.
const DiffChunk chunk = diffChunk(cursorForPosition(e->pos()));
revertAction->setEnabled(canRevertDiffChunk(chunk));
revertAction->setData(qVariantFromValue(chunk));
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->setEnabled(canApply);
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()));
}
break;
default:
@@ -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?"),
QMessageBox::Yes|QMessageBox::No))
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))
return;
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.