diff --git a/src/plugins/diffeditor/diffeditorcontroller.cpp b/src/plugins/diffeditor/diffeditorcontroller.cpp index 1ab7bfccb2d..4756afc7828 100644 --- a/src/plugins/diffeditor/diffeditorcontroller.cpp +++ b/src/plugins/diffeditor/diffeditorcontroller.cpp @@ -124,17 +124,20 @@ void DiffEditorController::reloadFinished(bool success) m_document->endReload(success); } +void DiffEditorController::addExtraActions(QMenu *menu, int fileIndex, int chunkIndex, + const ChunkSelection &selection) +{ + Q_UNUSED(menu) + Q_UNUSED(fileIndex) + Q_UNUSED(chunkIndex) + Q_UNUSED(selection) +} + void DiffEditorController::setStartupFile(const QString &startupFile) { m_document->setStartupFile(startupFile); } -void DiffEditorController::requestChunkActions(QMenu *menu, int fileIndex, int chunkIndex, - const ChunkSelection &selection) -{ - emit chunkActionsRequested(menu, fileIndex, chunkIndex, selection); -} - bool DiffEditorController::chunkExists(int fileIndex, int chunkIndex) const { if (!m_document) diff --git a/src/plugins/diffeditor/diffeditorcontroller.h b/src/plugins/diffeditor/diffeditorcontroller.h index beebfb987c2..1fddc31c4dd 100644 --- a/src/plugins/diffeditor/diffeditorcontroller.h +++ b/src/plugins/diffeditor/diffeditorcontroller.h @@ -19,7 +19,10 @@ namespace Utils { class FilePath; } namespace DiffEditor { -namespace Internal { class DiffEditorDocument; } +namespace Internal { +class DiffEditorDocument; +class DiffEditorWidgetController; +} class ChunkSelection; @@ -40,26 +43,18 @@ public: AddPrefix = 2 }; Q_DECLARE_FLAGS(PatchOptions, PatchOption) - QString makePatch(int fileIndex, int chunkIndex, const ChunkSelection &selection, - PatchOptions options) const; - static Core::IDocument *findOrCreateDocument(const QString &vcsId, - const QString &displayName); + static Core::IDocument *findOrCreateDocument(const QString &vcsId, const QString &displayName); static DiffEditorController *controller(Core::IDocument *document); - void requestChunkActions(QMenu *menu, int fileIndex, int chunkIndex, - const ChunkSelection &selection); - bool chunkExists(int fileIndex, int chunkIndex) const; - Core::IDocument *document() const; - -signals: - void chunkActionsRequested(QMenu *menu, int fileIndex, int chunkIndex, - const ChunkSelection &selection); - protected: bool isReloading() const; int contextLineCount() const; bool ignoreWhitespace() const; + bool chunkExists(int fileIndex, int chunkIndex) const; + Core::IDocument *document() const; + QString makePatch(int fileIndex, int chunkIndex, const ChunkSelection &selection, + PatchOptions options) const; // Core functions: void setReloadRecipe(const Tasking::Group &recipe) { m_reloadRecipe = recipe; } @@ -72,6 +67,9 @@ protected: private: void reloadFinished(bool success); + friend class Internal::DiffEditorWidgetController; + virtual void addExtraActions(QMenu *menu, int fileIndex, int chunkIndex, + const ChunkSelection &selection); Internal::DiffEditorDocument *const m_document; QString m_displayName; diff --git a/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp b/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp index e3f321c7c44..26d94b73677 100644 --- a/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp +++ b/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp @@ -280,7 +280,7 @@ void DiffEditorWidgetController::addExtraActions(QMenu *menu, int fileIndex, int const ChunkSelection &selection) { if (DiffEditorController *controller = m_document->controller()) - controller->requestChunkActions(menu, fileIndex, chunkIndex, selection); + controller->addExtraActions(menu, fileIndex, chunkIndex, selection); } void DiffEditorWidgetController::updateCannotDecodeInfo() diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 845531ed825..69cf636e72c 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -112,6 +112,38 @@ static QString branchesDisplay(const QString &prefix, QStringList *branches, boo /////////////////////////////// +static void stage(DiffEditorController *diffController, const QString &patch, bool revert) +{ + TemporaryFile patchFile("git-patchfile"); + if (!patchFile.open()) + return; + + const FilePath baseDir = diffController->workingDirectory(); + QTextCodec *codec = EditorManager::defaultTextCodec(); + const QByteArray patchData = codec ? codec->fromUnicode(patch) : patch.toLocal8Bit(); + patchFile.write(patchData); + patchFile.close(); + + QStringList args = {"--cached"}; + if (revert) + args << "--reverse"; + QString errorMessage; + if (GitClient::instance()->synchronousApplyPatch(baseDir, patchFile.fileName(), + &errorMessage, args)) { + if (errorMessage.isEmpty()) { + if (revert) + VcsOutputWindow::appendSilently(Tr::tr("Chunk successfully unstaged")); + else + VcsOutputWindow::appendSilently(Tr::tr("Chunk successfully staged")); + } else { + VcsOutputWindow::appendError(errorMessage); + } + diffController->requestReload(); + } else { + VcsOutputWindow::appendError(errorMessage); + } +} + class GitBaseDiffEditorController : public VcsBaseDiffEditorController { Q_OBJECT @@ -120,6 +152,50 @@ protected: explicit GitBaseDiffEditorController(IDocument *document); QStringList addConfigurationArguments(const QStringList &args) const; + +private: + void addExtraActions(QMenu *menu, int fileIndex, int chunkIndex, + const ChunkSelection &selection) final + { + menu->addSeparator(); + + auto stageChunk = [this, fileIndex, chunkIndex](DiffEditorController::PatchOptions options, + const DiffEditor::ChunkSelection &selection) { + options |= DiffEditorController::AddPrefix; + const QString patch = makePatch(fileIndex, chunkIndex, selection, options); + stage(this, patch, options & Revert); + }; + + QAction *stageChunkAction = menu->addAction(Tr::tr("Stage Chunk")); + connect(stageChunkAction, &QAction::triggered, this, [stageChunk] { + stageChunk(DiffEditorController::NoOption, {}); + }); + QAction *stageLinesAction = menu->addAction(Tr::tr("Stage Selection (%n Lines)", "", + selection.selectedRowsCount())); + connect(stageLinesAction, &QAction::triggered, this, [stageChunk, selection] { + stageChunk(DiffEditorController::NoOption, selection); + }); + QAction *unstageChunkAction = menu->addAction(Tr::tr("Unstage Chunk")); + connect(unstageChunkAction, &QAction::triggered, this, [stageChunk] { + stageChunk(DiffEditorController::Revert, {}); + }); + QAction *unstageLinesAction = menu->addAction(Tr::tr("Unstage Selection (%n Lines)", "", + selection.selectedRowsCount())); + connect(unstageLinesAction, &QAction::triggered, this, [stageChunk, selection] { + stageChunk(DiffEditorController::Revert, selection); + }); + + if (selection.isNull()) { + stageLinesAction->setVisible(false); + unstageLinesAction->setVisible(false); + } + if (!chunkExists(fileIndex, chunkIndex)) { + stageChunkAction->setEnabled(false); + stageLinesAction->setEnabled(false); + unstageChunkAction->setEnabled(false); + unstageLinesAction->setEnabled(false); + } + } }; class GitDiffEditorController : public GitBaseDiffEditorController @@ -850,95 +926,6 @@ QTextCodec *GitClient::encoding(GitClient::EncodingType encodingType, const File } } -void GitClient::chunkActionsRequested(DiffEditor::DiffEditorController *controller, - QMenu *menu, int fileIndex, int chunkIndex, - const DiffEditor::ChunkSelection &selection) const -{ - QPointer diffController(controller); - - auto stageChunk = [this](QPointer diffController, - int fileIndex, int chunkIndex, DiffEditorController::PatchOptions options, - const DiffEditor::ChunkSelection &selection) { - if (diffController.isNull()) - return; - - options |= DiffEditorController::AddPrefix; - const QString patch = diffController->makePatch(fileIndex, chunkIndex, selection, options); - stage(diffController, patch, options & Revert); - }; - - menu->addSeparator(); - QAction *stageChunkAction = menu->addAction(Tr::tr("Stage Chunk")); - connect(stageChunkAction, &QAction::triggered, this, - [stageChunk, diffController, fileIndex, chunkIndex] { - stageChunk(diffController, fileIndex, chunkIndex, - DiffEditorController::NoOption, DiffEditor::ChunkSelection()); - }); - QAction *stageLinesAction = menu->addAction(Tr::tr("Stage Selection (%n Lines)", "", selection.selectedRowsCount())); - connect(stageLinesAction, &QAction::triggered, this, - [stageChunk, diffController, fileIndex, chunkIndex, selection] { - stageChunk(diffController, fileIndex, chunkIndex, - DiffEditorController::NoOption, selection); - }); - QAction *unstageChunkAction = menu->addAction(Tr::tr("Unstage Chunk")); - connect(unstageChunkAction, &QAction::triggered, this, - [stageChunk, diffController, fileIndex, chunkIndex] { - stageChunk(diffController, fileIndex, chunkIndex, - DiffEditorController::Revert, DiffEditor::ChunkSelection()); - }); - QAction *unstageLinesAction = menu->addAction(Tr::tr("Unstage Selection (%n Lines)", "", selection.selectedRowsCount())); - connect(unstageLinesAction, &QAction::triggered, this, - [stageChunk, diffController, fileIndex, chunkIndex, selection] { - stageChunk(diffController, fileIndex, chunkIndex, - DiffEditorController::Revert, - selection); - }); - if (selection.isNull()) { - stageLinesAction->setVisible(false); - unstageLinesAction->setVisible(false); - } - if (!diffController || !diffController->chunkExists(fileIndex, chunkIndex)) { - stageChunkAction->setEnabled(false); - stageLinesAction->setEnabled(false); - unstageChunkAction->setEnabled(false); - unstageLinesAction->setEnabled(false); - } -} - -void GitClient::stage(DiffEditor::DiffEditorController *diffController, - const QString &patch, bool revert) const -{ - TemporaryFile patchFile("git-patchfile"); - if (!patchFile.open()) - return; - - const FilePath baseDir = diffController->workingDirectory(); - QTextCodec *codec = EditorManager::defaultTextCodec(); - const QByteArray patchData = codec - ? codec->fromUnicode(patch) : patch.toLocal8Bit(); - patchFile.write(patchData); - patchFile.close(); - - QStringList args = {"--cached"}; - if (revert) - args << "--reverse"; - QString errorMessage; - if (synchronousApplyPatch(baseDir, patchFile.fileName(), - &errorMessage, args)) { - if (errorMessage.isEmpty()) { - if (revert) - VcsOutputWindow::appendSilently(Tr::tr("Chunk successfully unstaged")); - else - VcsOutputWindow::appendSilently(Tr::tr("Chunk successfully staged")); - } else { - VcsOutputWindow::appendError(errorMessage); - } - diffController->requestReload(); - } else { - VcsOutputWindow::appendError(errorMessage); - } -} - void GitClient::requestReload(const QString &documentId, const FilePath &source, const QString &title, const FilePath &workingDirectory, std::function factory) const @@ -956,10 +943,6 @@ void GitClient::requestReload(const QString &documentId, const FilePath &source, using namespace std::placeholders; - connect(controller, &DiffEditorController::chunkActionsRequested, this, - std::bind(&GitClient::chunkActionsRequested, this, controller, _1, _2, _3, _4), - Qt::DirectConnection); - VcsBase::setSource(document, sourceCopy); EditorManager::activateEditorForDocument(document); controller->requestReload(); diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h index 398b1c1cc86..6e2878be024 100644 --- a/src/plugins/git/gitclient.h +++ b/src/plugins/git/gitclient.h @@ -363,12 +363,6 @@ private: static GitSettings &settings(); void finishSubmoduleUpdate(); - void chunkActionsRequested(DiffEditor::DiffEditorController *controller, - QMenu *menu, int fileIndex, int chunkIndex, - const DiffEditor::ChunkSelection &selection) const; - - void stage(DiffEditor::DiffEditorController *diffController, - const QString &patch, bool revert) const; void requestReload(const QString &documentId, const Utils::FilePath &source, const QString &title, const Utils::FilePath &workingDirectory,