DiffEditor: Refactor DiffEditorController

Replace requestChunkActions() and chunkActionsRequested()
with a virtual method addExtraActions().
Implement it in GitBaseDiffEditorController.

Task-number: QTCREATORBUG-23242
Change-Id: I5da166b35d1146b9fd439e748803531d982ad2a8
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
This commit is contained in:
Jarek Kobus
2023-06-08 16:10:03 +02:00
parent 7f2ad8079d
commit 2caf4efbb2
5 changed files with 98 additions and 120 deletions

View File

@@ -124,17 +124,20 @@ void DiffEditorController::reloadFinished(bool success)
m_document->endReload(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) void DiffEditorController::setStartupFile(const QString &startupFile)
{ {
m_document->setStartupFile(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 bool DiffEditorController::chunkExists(int fileIndex, int chunkIndex) const
{ {
if (!m_document) if (!m_document)

View File

@@ -19,7 +19,10 @@ namespace Utils { class FilePath; }
namespace DiffEditor { namespace DiffEditor {
namespace Internal { class DiffEditorDocument; } namespace Internal {
class DiffEditorDocument;
class DiffEditorWidgetController;
}
class ChunkSelection; class ChunkSelection;
@@ -40,26 +43,18 @@ public:
AddPrefix = 2 AddPrefix = 2
}; };
Q_DECLARE_FLAGS(PatchOptions, PatchOption) Q_DECLARE_FLAGS(PatchOptions, PatchOption)
QString makePatch(int fileIndex, int chunkIndex, const ChunkSelection &selection,
PatchOptions options) const;
static Core::IDocument *findOrCreateDocument(const QString &vcsId, static Core::IDocument *findOrCreateDocument(const QString &vcsId, const QString &displayName);
const QString &displayName);
static DiffEditorController *controller(Core::IDocument *document); 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: protected:
bool isReloading() const; bool isReloading() const;
int contextLineCount() const; int contextLineCount() const;
bool ignoreWhitespace() 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: // Core functions:
void setReloadRecipe(const Tasking::Group &recipe) { m_reloadRecipe = recipe; } void setReloadRecipe(const Tasking::Group &recipe) { m_reloadRecipe = recipe; }
@@ -72,6 +67,9 @@ protected:
private: private:
void reloadFinished(bool success); 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; Internal::DiffEditorDocument *const m_document;
QString m_displayName; QString m_displayName;

View File

@@ -280,7 +280,7 @@ void DiffEditorWidgetController::addExtraActions(QMenu *menu, int fileIndex, int
const ChunkSelection &selection) const ChunkSelection &selection)
{ {
if (DiffEditorController *controller = m_document->controller()) if (DiffEditorController *controller = m_document->controller())
controller->requestChunkActions(menu, fileIndex, chunkIndex, selection); controller->addExtraActions(menu, fileIndex, chunkIndex, selection);
} }
void DiffEditorWidgetController::updateCannotDecodeInfo() void DiffEditorWidgetController::updateCannotDecodeInfo()

View File

@@ -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 class GitBaseDiffEditorController : public VcsBaseDiffEditorController
{ {
Q_OBJECT Q_OBJECT
@@ -120,6 +152,50 @@ protected:
explicit GitBaseDiffEditorController(IDocument *document); explicit GitBaseDiffEditorController(IDocument *document);
QStringList addConfigurationArguments(const QStringList &args) const; 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 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<DiffEditor::DiffEditorController> diffController(controller);
auto stageChunk = [this](QPointer<DiffEditor::DiffEditorController> 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, void GitClient::requestReload(const QString &documentId, const FilePath &source,
const QString &title, const FilePath &workingDirectory, const QString &title, const FilePath &workingDirectory,
std::function<GitBaseDiffEditorController *(IDocument *)> factory) const std::function<GitBaseDiffEditorController *(IDocument *)> factory) const
@@ -956,10 +943,6 @@ void GitClient::requestReload(const QString &documentId, const FilePath &source,
using namespace std::placeholders; 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); VcsBase::setSource(document, sourceCopy);
EditorManager::activateEditorForDocument(document); EditorManager::activateEditorForDocument(document);
controller->requestReload(); controller->requestReload();

View File

@@ -363,12 +363,6 @@ private:
static GitSettings &settings(); static GitSettings &settings();
void finishSubmoduleUpdate(); 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, void requestReload(const QString &documentId, const Utils::FilePath &source,
const QString &title, const Utils::FilePath &workingDirectory, const QString &title, const Utils::FilePath &workingDirectory,