diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/plugins/git/gitclient.cpp | 9 | ||||
-rw-r--r-- | src/plugins/git/gitclient.h | 2 | ||||
-rw-r--r-- | src/plugins/git/giteditor.cpp | 63 | ||||
-rw-r--r-- | src/plugins/git/giteditor.h | 4 | ||||
-rw-r--r-- | src/plugins/vcsbase/vcsbaseeditor.cpp | 25 | ||||
-rw-r--r-- | src/plugins/vcsbase/vcsbaseeditor.h | 5 |
6 files changed, 99 insertions, 9 deletions
diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 4de3a026d2..9a91cc7491 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -1115,6 +1115,8 @@ void GitClient::diff(const QString &workingDirectory, workingDirectory, argWidget); newEditor = vcsEditor->editor(); + connect(vcsEditor, SIGNAL(diffChunkApplied(VcsBase::DiffChunk)), + argWidget, SLOT(executeCommand())); connect(vcsEditor, SIGNAL(diffChunkReverted(VcsBase::DiffChunk)), argWidget, SLOT(executeCommand())); } @@ -1222,6 +1224,8 @@ void GitClient::diff(const QString &workingDirectory, sourceFile, argWidget); newEditor = vcsEditor->editor(); + connect(vcsEditor, SIGNAL(diffChunkApplied(VcsBase::DiffChunk)), + argWidget, SLOT(executeCommand())); connect(vcsEditor, SIGNAL(diffChunkReverted(VcsBase::DiffChunk)), argWidget, SLOT(executeCommand())); } @@ -2433,10 +2437,11 @@ bool GitClient::synchronousCleanList(const QString &workingDirectory, QStringLis } bool GitClient::synchronousApplyPatch(const QString &workingDirectory, - const QString &file, QString *errorMessage) + const QString &file, QString *errorMessage, + const QStringList &arguments) { QStringList args; - args << QLatin1String("apply") << QLatin1String("--whitespace=fix") << file; + args << QLatin1String("apply") << QLatin1String("--whitespace=fix") << arguments << file; QByteArray outputText; QByteArray errorText; const bool rc = fullySynchronousGit(workingDirectory, args, &outputText, &errorText); diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h index 5b1631c3bd..6e4a990baf 100644 --- a/src/plugins/git/gitclient.h +++ b/src/plugins/git/gitclient.h @@ -182,7 +182,7 @@ public: const QStringList &files = QStringList(), QString *errorMessage = 0); bool synchronousCleanList(const QString &workingDirectory, QStringList *files, QStringList *ignoredFiles, QString *errorMessage); - bool synchronousApplyPatch(const QString &workingDirectory, const QString &file, QString *errorMessage); + bool synchronousApplyPatch(const QString &workingDirectory, const QString &file, QString *errorMessage, const QStringList &arguments = QStringList()); bool synchronousInit(const QString &workingDirectory); bool synchronousCheckoutFiles(const QString &workingDirectory, QStringList files = QStringList(), diff --git a/src/plugins/git/giteditor.cpp b/src/plugins/git/giteditor.cpp index 7018e51eb9..7aa36ec7fe 100644 --- a/src/plugins/git/giteditor.cpp +++ b/src/plugins/git/giteditor.cpp @@ -44,9 +44,12 @@ #include <QFileInfo> #include <QRegExp> #include <QSet> +#include <QTemporaryFile> +#include <QDir> #include <QTextCursor> #include <QTextBlock> +#include <QMessageBox> #define CHANGE_PATTERN "[a-f0-9]{7,40}" @@ -223,6 +226,53 @@ void GitEditor::revertChange() GitPlugin::instance()->gitClient()->synchronousRevert(workingDirectory, m_currentChange); } +void GitEditor::stageDiffChunk() +{ + const QAction *a = qobject_cast<QAction *>(sender()); + QTC_ASSERT(a, return); + const VcsBase::DiffChunk chunk = qvariant_cast<VcsBase::DiffChunk>(a->data()); + return applyDiffChunk(chunk, false); +} + +void GitEditor::unstageDiffChunk() +{ + const QAction *a = qobject_cast<QAction *>(sender()); + QTC_ASSERT(a, return); + const VcsBase::DiffChunk chunk = qvariant_cast<VcsBase::DiffChunk>(a->data()); + return applyDiffChunk(chunk, true); +} + +void GitEditor::applyDiffChunk(const VcsBase::DiffChunk& chunk, bool revert) +{ + VcsBase::VcsBaseOutputWindow *outwin = VcsBase::VcsBaseOutputWindow::instance(); + QTemporaryFile patchFile; + if (!patchFile.open()) + return; + + const QString baseDir = diffBaseDirectory(); + patchFile.write(chunk.header); + patchFile.write(chunk.chunk); + patchFile.close(); + + GitClient *client = GitPlugin::instance()->gitClient(); + QStringList args = QStringList() << QLatin1String("--cached"); + if (revert) + args << QLatin1String("--reverse"); + QString errorMessage; + if (client->synchronousApplyPatch(baseDir, patchFile.fileName(), &errorMessage, args)) { + if (errorMessage.isEmpty()) + outwin->append(tr("Chunk successfully staged")); + else + outwin->append(errorMessage); + if (revert) + emit diffChunkReverted(chunk); + else + emit diffChunkApplied(chunk); + } else { + outwin->appendError(errorMessage); + } +} + void GitEditor::init() { VcsBase::VcsBaseEditorWidget::init(); @@ -233,6 +283,19 @@ void GitEditor::init() new GitRebaseHighlighter(baseTextDocument().data()); } +void GitEditor::addDiffActions(QMenu *menu, const VcsBase::DiffChunk &chunk) +{ + menu->addSeparator(); + + QAction *stageAction = menu->addAction(tr("Stage Chunk...")); + stageAction->setData(qVariantFromValue(chunk)); + connect(stageAction, SIGNAL(triggered()), this, SLOT(stageDiffChunk())); + + QAction *unstageAction = menu->addAction(tr("Unstage Chunk...")); + unstageAction->setData(qVariantFromValue(chunk)); + connect(unstageAction, SIGNAL(triggered()), this, SLOT(unstageDiffChunk())); +} + bool GitEditor::open(QString *errorString, const QString &fileName, const QString &realFileName) { bool res = VcsBaseEditorWidget::open(errorString, fileName, realFileName); diff --git a/src/plugins/git/giteditor.h b/src/plugins/git/giteditor.h index 648a2fa4ec..1ed80c7ccf 100644 --- a/src/plugins/git/giteditor.h +++ b/src/plugins/git/giteditor.h @@ -57,9 +57,13 @@ public slots: private slots: void cherryPickChange(); void revertChange(); + void stageDiffChunk(); + void unstageDiffChunk(); + void applyDiffChunk(const VcsBase::DiffChunk& chunk, bool revert); private: void init(); + void addDiffActions(QMenu *menu, const VcsBase::DiffChunk &chunk); bool open(QString *errorString, const QString &fileName, const QString &realFileName); QSet<QString> annotationChanges() const; QString changeUnderCursor(const QTextCursor &) const; diff --git a/src/plugins/vcsbase/vcsbaseeditor.cpp b/src/plugins/vcsbase/vcsbaseeditor.cpp index 7ded80ec7f..7171851c76 100644 --- a/src/plugins/vcsbase/vcsbaseeditor.cpp +++ b/src/plugins/vcsbase/vcsbaseeditor.cpp @@ -950,6 +950,8 @@ void VcsBaseEditorWidget::contextMenuEvent(QContextMenuEvent *e) QAction *revertAction = menu->addAction(tr("Revert Chunk...")); revertAction->setData(qVariantFromValue(Internal::DiffChunkAction(chunk, true))); connect(revertAction, SIGNAL(triggered()), this, SLOT(slotApplyDiffChunk())); + // Custom diff actions + addDiffActions(menu, chunk); break; } default: @@ -1145,7 +1147,8 @@ DiffChunk VcsBaseEditorWidget::diffChunk(QTextCursor cursor) const } if (!chunkStart || !block.isValid()) return rc; - rc.fileName = findDiffFile(fileNameFromDiffSpecification(block)); + QString header; + rc.fileName = findDiffFile(fileNameFromDiffSpecification(block, &header)); if (rc.fileName.isEmpty()) return rc; // Concatenate chunk and convert @@ -1163,6 +1166,7 @@ DiffChunk VcsBaseEditorWidget::diffChunk(QTextCursor cursor) const } const QTextCodec *cd = baseTextDocument()->codec(); rc.chunk = cd ? cd->fromUnicode(unicode) : unicode.toLocal8Bit(); + rc.header = cd ? cd->fromUnicode(header) : header.toLocal8Bit(); return rc; } @@ -1388,6 +1392,10 @@ QString VcsBaseEditorWidget::findDiffFile(const QString &f) const return QString(); } +void VcsBaseEditorWidget::addDiffActions(QMenu *, const DiffChunk &) +{ +} + void VcsBaseEditorWidget::slotAnnotateRevision() { if (const QAction *a = qobject_cast<const QAction *>(sender())) @@ -1430,18 +1438,25 @@ bool VcsBaseEditorWidget::applyDiffChunk(const DiffChunk &dc, bool revert) const d->m_diffBaseDirectory, 0, revert); } -QString VcsBaseEditorWidget::fileNameFromDiffSpecification(const QTextBlock &inBlock) const +QString VcsBaseEditorWidget::fileNameFromDiffSpecification(const QTextBlock &inBlock, QString *header) const { // Go back chunks + QString fileName; for (QTextBlock block = inBlock; block.isValid(); block = block.previous()) { const QString line = block.text(); if (d->m_diffFilePattern.indexIn(line) != -1) { QString cap = d->m_diffFilePattern.cap(1); - if (!cap.isEmpty()) - return findDiffFile(cap); + if (header) + header->prepend(line + QLatin1String("\n")); + if (fileName.isEmpty() && !cap.isEmpty()) + fileName = cap; + } else if (!fileName.isEmpty()) { + return findDiffFile(fileName); + } else if (header) { + header->clear(); } } - return QString(); + return fileName.isEmpty() ? QString() : findDiffFile(fileName); } void VcsBaseEditorWidget::addChangeActions(QMenu *, const QString &) diff --git a/src/plugins/vcsbase/vcsbaseeditor.h b/src/plugins/vcsbase/vcsbaseeditor.h index 5bbd78b4d4..b2fd845d9e 100644 --- a/src/plugins/vcsbase/vcsbaseeditor.h +++ b/src/plugins/vcsbase/vcsbaseeditor.h @@ -83,6 +83,7 @@ public: QString fileName; QByteArray chunk; + QByteArray header; }; class VCSBASE_EXPORT VcsBaseEditorWidget : public TextEditor::BaseTextEditorWidget @@ -234,6 +235,8 @@ protected: * source and version control. */ virtual QString findDiffFile(const QString &f) const; + virtual void addDiffActions(QMenu *menu, const DiffChunk &chunk); + virtual void addChangeActions(QMenu *menu, const QString &change); // Implement to return a set of change identifiers in @@ -245,7 +248,7 @@ protected: virtual BaseAnnotationHighlighter *createAnnotationHighlighter(const QSet<QString> &changes) const = 0; // Returns a local file name from the diff file specification // (text cursor at position above change hunk) - QString fileNameFromDiffSpecification(const QTextBlock &inBlock) const; + QString fileNameFromDiffSpecification(const QTextBlock &inBlock, QString *header = 0) const; // Implement to return decorated annotation change for "Annotate version" virtual QString decorateVersion(const QString &revision) const; |