forked from qt-creator/qt-creator
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:
@@ -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)
|
||||||
|
@@ -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;
|
||||||
|
@@ -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()
|
||||||
|
@@ -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();
|
||||||
|
@@ -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,
|
||||||
|
Reference in New Issue
Block a user