SideBySideDiffEditor: Avoid code repetition

Change-Id: Ie49834a4896dbf32a87329345e52dc99ca2f86bd
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
This commit is contained in:
Jarek Kobus
2022-09-29 14:25:34 +02:00
parent 38b19bfae6
commit 2d360db2c3
15 changed files with 207 additions and 305 deletions

View File

@@ -13,6 +13,7 @@ add_qtc_plugin(DiffEditor
diffeditoricons.h diffeditoricons.h
diffeditorplugin.cpp diffeditorplugin.h diffeditorplugin.cpp diffeditorplugin.h
diffeditorwidgetcontroller.cpp diffeditorwidgetcontroller.h diffeditorwidgetcontroller.cpp diffeditorwidgetcontroller.h
diffenums.h
diffutils.cpp diffutils.h diffutils.cpp diffutils.h
diffview.cpp diffview.h diffview.cpp diffview.h
selectabletexteditorwidget.cpp selectabletexteditorwidget.h selectabletexteditorwidget.cpp selectabletexteditorwidget.h

View File

@@ -292,15 +292,11 @@ TextEditorWidget *DiffEditor::unifiedEditorWidget() const
return m_unifiedView->textEditorWidget(); return m_unifiedView->textEditorWidget();
} }
TextEditorWidget *DiffEditor::leftEditorWidget() const TextEditorWidget *DiffEditor::sideEditorWidget(DiffSide side) const
{ {
return m_sideBySideView->leftEditorWidget(); return m_sideBySideView->sideEditorWidget(side);
} }
TextEditorWidget *DiffEditor::rightEditorWidget() const
{
return m_sideBySideView->rightEditorWidget();
}
void DiffEditor::documentHasChanged() void DiffEditor::documentHasChanged()
{ {

View File

@@ -3,6 +3,8 @@
#pragma once #pragma once
#include "diffenums.h"
#include <coreplugin/editormanager/ieditor.h> #include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/idocument.h> #include <coreplugin/idocument.h>
#include <utils/guard.h> #include <utils/guard.h>
@@ -38,8 +40,7 @@ public:
QWidget *toolBar() override; QWidget *toolBar() override;
TextEditor::TextEditorWidget *descriptionWidget() const; TextEditor::TextEditorWidget *descriptionWidget() const;
TextEditor::TextEditorWidget *unifiedEditorWidget() const; TextEditor::TextEditorWidget *unifiedEditorWidget() const;
TextEditor::TextEditorWidget *leftEditorWidget() const; TextEditor::TextEditorWidget *sideEditorWidget(DiffSide side) const;
TextEditor::TextEditorWidget *rightEditorWidget() const;
private: private:
DiffEditor(); DiffEditor();

View File

@@ -32,6 +32,7 @@ QtcPlugin {
"diffeditorplugin.h", "diffeditorplugin.h",
"diffeditorwidgetcontroller.cpp", "diffeditorwidgetcontroller.cpp",
"diffeditorwidgetcontroller.h", "diffeditorwidgetcontroller.h",
"diffenums.h",
"diffutils.cpp", "diffutils.cpp",
"diffutils.h", "diffutils.h",
"diffview.cpp", "diffview.cpp",

View File

@@ -34,13 +34,13 @@ DiffEditorFactory::DiffEditorFactory() :
Constants::DIFF_EDITOR_ID, Constants::DIFF_EDITOR_ID,
Id(Constants::SIDE_BY_SIDE_VIEW_ID).withSuffix(1), Id(Constants::SIDE_BY_SIDE_VIEW_ID).withSuffix(1),
TextEditorActionHandler::None, TextEditorActionHandler::None,
[](IEditor *e) { return static_cast<DiffEditor *>(e)->leftEditorWidget(); } [](IEditor *e) { return static_cast<DiffEditor *>(e)->sideEditorWidget(LeftSide); }
}, },
rightHandler { rightHandler {
Constants::DIFF_EDITOR_ID, Constants::DIFF_EDITOR_ID,
Id(Constants::SIDE_BY_SIDE_VIEW_ID).withSuffix(2), Id(Constants::SIDE_BY_SIDE_VIEW_ID).withSuffix(2),
TextEditorActionHandler::None, TextEditorActionHandler::None,
[](Core::IEditor *e) { return static_cast<DiffEditor *>(e)->rightEditorWidget(); } [](Core::IEditor *e) { return static_cast<DiffEditor *>(e)->sideEditorWidget(RightSide); }
} }
{ {
setId(Constants::DIFF_EDITOR_ID); setId(Constants::DIFF_EDITOR_ID);

View File

@@ -266,22 +266,16 @@ bool DiffEditorWidgetController::fileNamesAreDifferent(int fileIndex) const
return fileData.fileInfo[LeftSide].fileName != fileData.fileInfo[RightSide].fileName; return fileData.fileInfo[LeftSide].fileName != fileData.fileInfo[RightSide].fileName;
} }
void DiffEditorWidgetController::addApplyAction(QMenu *menu, int fileIndex, int chunkIndex) void DiffEditorWidgetController::addApplyRevertAction(QMenu *menu, int fileIndex, int chunkIndex, DiffSide side)
{ {
QAction *applyAction = menu->addAction(tr("Apply Chunk...")); const QString actionName = side == LeftSide ? tr("Apply Chunk...") : tr("Revert Chunk...");
connect(applyAction, &QAction::triggered, this, [this, fileIndex, chunkIndex] { QAction *action = menu->addAction(actionName);
patch(false, fileIndex, chunkIndex); connect(action, &QAction::triggered, this, [this, fileIndex, chunkIndex, side] {
patch(side == RightSide, fileIndex, chunkIndex);
}); });
applyAction->setEnabled(chunkExists(fileIndex, chunkIndex) && fileNamesAreDifferent(fileIndex)); const bool enabled = chunkExists(fileIndex, chunkIndex)
} && (side == RightSide || fileNamesAreDifferent(fileIndex));
action->setEnabled(enabled);
void DiffEditorWidgetController::addRevertAction(QMenu *menu, int fileIndex, int chunkIndex)
{
QAction *revertAction = menu->addAction(tr("Revert Chunk..."));
connect(revertAction, &QAction::triggered, this, [this, fileIndex, chunkIndex] {
patch(true, fileIndex, chunkIndex);
});
revertAction->setEnabled(chunkExists(fileIndex, chunkIndex));
} }
void DiffEditorWidgetController::addExtraActions(QMenu *menu, int fileIndex, int chunkIndex, void DiffEditorWidgetController::addExtraActions(QMenu *menu, int fileIndex, int chunkIndex,

View File

@@ -38,8 +38,7 @@ public:
int columnNumber); int columnNumber);
void setFontSettings(const TextEditor::FontSettings &fontSettings); void setFontSettings(const TextEditor::FontSettings &fontSettings);
void addCodePasterAction(QMenu *menu, int fileIndex, int chunkIndex); void addCodePasterAction(QMenu *menu, int fileIndex, int chunkIndex);
void addApplyAction(QMenu *menu, int fileIndex, int chunkIndex); void addApplyRevertAction(QMenu *menu, int fileIndex, int chunkIndex, DiffSide side);
void addRevertAction(QMenu *menu, int fileIndex, int chunkIndex);
void addExtraActions(QMenu *menu, int fileIndex, int chunkIndex, const ChunkSelection &selection); void addExtraActions(QMenu *menu, int fileIndex, int chunkIndex, const ChunkSelection &selection);
void updateCannotDecodeInfo(); void updateCannotDecodeInfo();
void setBusyShowing(bool busy); void setBusyShowing(bool busy);

View File

@@ -0,0 +1,14 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
#pragma once
namespace DiffEditor {
enum DiffSide {
LeftSide,
RightSide,
SideCount // Use only in array declarations
};
} // namespace DiffEditor

View File

@@ -4,6 +4,7 @@
#pragma once #pragma once
#include "diffeditor_global.h" #include "diffeditor_global.h"
#include "diffenums.h"
#include <utils/algorithm.h> #include <utils/algorithm.h>
@@ -18,12 +19,6 @@ namespace Utils { class Diff; }
namespace DiffEditor { namespace DiffEditor {
enum DiffSide {
LeftSide,
RightSide,
SideCount // Use only in array declarations
};
class DIFFEDITOR_EXPORT DiffFileInfo { class DIFFEDITOR_EXPORT DiffFileInfo {
public: public:
enum PatchBehaviour { enum PatchBehaviour {

View File

@@ -166,16 +166,10 @@ QWidget *SideBySideView::widget()
return m_widget; return m_widget;
} }
TextEditor::TextEditorWidget *SideBySideView::leftEditorWidget() TextEditor::TextEditorWidget *SideBySideView::sideEditorWidget(DiffSide side)
{ {
widget(); // ensure widget creation widget(); // ensure widget creation
return m_widget->leftEditorWidget(); return m_widget->sideEditorWidget(side);
}
TextEditor::TextEditorWidget *SideBySideView::rightEditorWidget()
{
widget(); // ensure widget creation
return m_widget->rightEditorWidget();
} }
void SideBySideView::setDocument(DiffEditorDocument *document) void SideBySideView::setDocument(DiffEditorDocument *document)

View File

@@ -3,6 +3,8 @@
#pragma once #pragma once
#include "diffenums.h"
#include <utils/id.h> #include <utils/id.h>
#include <QIcon> #include <QIcon>
@@ -95,8 +97,7 @@ public:
SideBySideView(); SideBySideView();
QWidget *widget() override; QWidget *widget() override;
TextEditor::TextEditorWidget *leftEditorWidget(); TextEditor::TextEditorWidget *sideEditorWidget(DiffSide side);
TextEditor::TextEditorWidget *rightEditorWidget();
void setDocument(DiffEditorDocument *document) override; void setDocument(DiffEditorDocument *document) override;

View File

@@ -32,9 +32,16 @@ using namespace Core;
using namespace TextEditor; using namespace TextEditor;
using namespace Utils; using namespace Utils;
using namespace std::placeholders;
namespace DiffEditor { namespace DiffEditor {
namespace Internal { namespace Internal {
static DiffSide oppositeSide(DiffSide side)
{
return side == LeftSide ? RightSide : LeftSide;
}
class SideDiffEditorWidget : public SelectableTextEditorWidget class SideDiffEditorWidget : public SelectableTextEditorWidget
{ {
Q_OBJECT Q_OBJECT
@@ -760,61 +767,76 @@ SideBySideDiffEditorWidget::SideBySideDiffEditorWidget(QWidget *parent)
: QWidget(parent) : QWidget(parent)
, m_controller(this) , m_controller(this)
{ {
m_leftEditor = new SideDiffEditorWidget(this); auto setupEditor = [this](DiffSide side) {
m_leftEditor->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); m_editor[side] = new SideDiffEditorWidget(this);
m_leftEditor->setReadOnly(true); m_editor[side]->setReadOnly(true);
m_leftEditor->setCodeStyle(TextEditorSettings::codeStyle()); m_editor[side]->setCodeStyle(TextEditorSettings::codeStyle());
connect(m_leftEditor, &SideDiffEditorWidget::jumpToOriginalFileRequested,
this, &SideBySideDiffEditorWidget::slotLeftJumpToOriginalFileRequested);
connect(m_leftEditor, &SideDiffEditorWidget::contextMenuRequested,
this, &SideBySideDiffEditorWidget::slotLeftContextMenuRequested,
Qt::DirectConnection);
m_rightEditor = new SideDiffEditorWidget(this); connect(m_editor[side], &SideDiffEditorWidget::jumpToOriginalFileRequested,
m_rightEditor->setReadOnly(true); this, std::bind(&SideBySideDiffEditorWidget::jumpToOriginalFileRequested, this,
m_rightEditor->setCodeStyle(TextEditorSettings::codeStyle()); side, _1, _2, _3));
connect(m_rightEditor, &SideDiffEditorWidget::jumpToOriginalFileRequested, connect(m_editor[side], &SideDiffEditorWidget::contextMenuRequested,
this, &SideBySideDiffEditorWidget::slotRightJumpToOriginalFileRequested); this, std::bind(&SideBySideDiffEditorWidget::contextMenuRequested, this,
connect(m_rightEditor, &SideDiffEditorWidget::contextMenuRequested, side, _1, _2, _3, _4));
this, &SideBySideDiffEditorWidget::slotRightContextMenuRequested,
Qt::DirectConnection);
auto setupHighlightController = [this] { connect(m_editor[side]->verticalScrollBar(), &QAbstractSlider::valueChanged,
HighlightScrollBarController *highlightController = m_leftEditor->highlightScrollBarController(); this, std::bind(&SideBySideDiffEditorWidget::verticalSliderChanged, this, side));
if (highlightController) connect(m_editor[side]->verticalScrollBar(), &QAbstractSlider::actionTriggered,
highlightController->setScrollArea(m_rightEditor); this, std::bind(&SideBySideDiffEditorWidget::verticalSliderChanged, this, side));
connect(m_editor[side]->horizontalScrollBar(), &QAbstractSlider::valueChanged,
this, std::bind(&SideBySideDiffEditorWidget::horizontalSliderChanged, this, side));
connect(m_editor[side]->horizontalScrollBar(), &QAbstractSlider::actionTriggered,
this, std::bind(&SideBySideDiffEditorWidget::horizontalSliderChanged, this, side));
connect(m_editor[side], &QPlainTextEdit::cursorPositionChanged,
this, std::bind(&SideBySideDiffEditorWidget::cursorPositionChanged, this, side));
connect(m_editor[side]->horizontalScrollBar(), &QAbstractSlider::rangeChanged,
this, &SideBySideDiffEditorWidget::syncHorizontalScrollBarPolicy);
auto context = new IContext(this);
context->setWidget(m_editor[side]);
context->setContext(Context(Utils::Id(Constants::SIDE_BY_SIDE_VIEW_ID).withSuffix(1)));
ICore::addContextObject(context);
}; };
setupEditor(LeftSide);
setupEditor(RightSide);
m_editor[LeftSide]->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setupHighlightController(); auto setupHighlight = [this] {
connect(m_leftEditor, &SideDiffEditorWidget::gotDisplaySettings, this, setupHighlightController); HighlightScrollBarController *ctrl = m_editor[LeftSide]->highlightScrollBarController();
if (ctrl)
ctrl->setScrollArea(m_editor[RightSide]);
};
setupHighlight();
connect(m_editor[LeftSide], &SideDiffEditorWidget::gotDisplaySettings, this, setupHighlight);
m_rightEditor->verticalScrollBar()->setFocusProxy(m_leftEditor); m_editor[RightSide]->verticalScrollBar()->setFocusProxy(m_editor[LeftSide]);
connect(m_leftEditor, &SideDiffEditorWidget::gotFocus, this, [this] { connect(m_editor[LeftSide], &SideDiffEditorWidget::gotFocus, this, [this] {
if (m_rightEditor->verticalScrollBar()->focusProxy() == m_leftEditor) if (m_editor[RightSide]->verticalScrollBar()->focusProxy() == m_editor[LeftSide])
return; // We already did it before. return; // We already did it before.
// Hack #1. If the left editor got a focus last time // Hack #1. If the left editor got a focus last time we don't want to focus right editor
// we don't want to focus right editor when clicking the right // when clicking the right scrollbar.
// scrollbar. m_editor[RightSide]->verticalScrollBar()->setFocusProxy(m_editor[LeftSide]);
m_rightEditor->verticalScrollBar()->setFocusProxy(m_leftEditor);
// Hack #2. If the focus is currently not on the scrollbar's proxy // Hack #2. If the focus is currently not on the scrollbar's proxy and we click on
// and we click on the scrollbar, the focus will go to the parent // the scrollbar, the focus will go to the parent of the scrollbar. In order to give
// of the scrollbar. In order to give the focus to the proxy // the focus to the proxy we need to set a click focus policy on the scrollbar.
// we need to set a click focus policy on the scrollbar.
// See QApplicationPrivate::giveFocusAccordingToFocusPolicy(). // See QApplicationPrivate::giveFocusAccordingToFocusPolicy().
m_rightEditor->verticalScrollBar()->setFocusPolicy(Qt::ClickFocus); m_editor[RightSide]->verticalScrollBar()->setFocusPolicy(Qt::ClickFocus);
// Hack #3. Setting the focus policy is not orthogonal to setting // Hack #3. Setting the focus policy is not orthogonal to setting the focus proxy and
// the focus proxy and unfortuantely it changes the policy of the proxy // unfortuantely it changes the policy of the proxy too. We bring back the original policy
// too. We bring back the original policy to keep tab focus working. // to keep tab focus working.
m_leftEditor->setFocusPolicy(Qt::StrongFocus); m_editor[LeftSide]->setFocusPolicy(Qt::StrongFocus);
}); });
connect(m_rightEditor, &SideDiffEditorWidget::gotFocus, this, [this] { connect(m_editor[RightSide], &SideDiffEditorWidget::gotFocus, this, [this] {
// Unhack #1. // Unhack #1.
m_rightEditor->verticalScrollBar()->setFocusProxy(nullptr); m_editor[RightSide]->verticalScrollBar()->setFocusProxy(nullptr);
// Unhack #2. // Unhack #2.
m_rightEditor->verticalScrollBar()->setFocusPolicy(Qt::NoFocus); m_editor[RightSide]->verticalScrollBar()->setFocusPolicy(Qt::NoFocus);
}); });
connect(TextEditorSettings::instance(), connect(TextEditorSettings::instance(),
@@ -822,61 +844,20 @@ SideBySideDiffEditorWidget::SideBySideDiffEditorWidget(QWidget *parent)
this, &SideBySideDiffEditorWidget::setFontSettings); this, &SideBySideDiffEditorWidget::setFontSettings);
setFontSettings(TextEditorSettings::fontSettings()); setFontSettings(TextEditorSettings::fontSettings());
connect(m_leftEditor->verticalScrollBar(), &QAbstractSlider::valueChanged, connect(m_editor[LeftSide], &SideDiffEditorWidget::foldChanged,
this, &SideBySideDiffEditorWidget::leftVSliderChanged); m_editor[RightSide], &SideDiffEditorWidget::setFolded);
connect(m_leftEditor->verticalScrollBar(), &QAbstractSlider::actionTriggered, connect(m_editor[RightSide], &SideDiffEditorWidget::foldChanged,
this, &SideBySideDiffEditorWidget::leftVSliderChanged); m_editor[LeftSide], &SideDiffEditorWidget::setFolded);
connect(m_leftEditor->horizontalScrollBar(), &QAbstractSlider::valueChanged,
this, &SideBySideDiffEditorWidget::leftHSliderChanged);
connect(m_leftEditor->horizontalScrollBar(), &QAbstractSlider::actionTriggered,
this, &SideBySideDiffEditorWidget::leftHSliderChanged);
connect(m_leftEditor, &QPlainTextEdit::cursorPositionChanged,
this, &SideBySideDiffEditorWidget::leftCursorPositionChanged);
connect(m_rightEditor->verticalScrollBar(), &QAbstractSlider::valueChanged,
this, &SideBySideDiffEditorWidget::rightVSliderChanged);
connect(m_rightEditor->verticalScrollBar(), &QAbstractSlider::actionTriggered,
this, &SideBySideDiffEditorWidget::rightVSliderChanged);
connect(m_rightEditor->horizontalScrollBar(), &QAbstractSlider::valueChanged,
this, &SideBySideDiffEditorWidget::rightHSliderChanged);
connect(m_rightEditor->horizontalScrollBar(), &QAbstractSlider::actionTriggered,
this, &SideBySideDiffEditorWidget::rightHSliderChanged);
connect(m_rightEditor, &QPlainTextEdit::cursorPositionChanged,
this, &SideBySideDiffEditorWidget::rightCursorPositionChanged);
connect(m_leftEditor, &SideDiffEditorWidget::foldChanged,
m_rightEditor, &SideDiffEditorWidget::setFolded);
connect(m_rightEditor, &SideDiffEditorWidget::foldChanged,
m_leftEditor, &SideDiffEditorWidget::setFolded);
connect(m_leftEditor->horizontalScrollBar(), &QAbstractSlider::rangeChanged,
this, &SideBySideDiffEditorWidget::syncHorizontalScrollBarPolicy);
connect(m_rightEditor->horizontalScrollBar(), &QAbstractSlider::rangeChanged,
this, &SideBySideDiffEditorWidget::syncHorizontalScrollBarPolicy);
syncHorizontalScrollBarPolicy(); syncHorizontalScrollBarPolicy();
m_splitter = new MiniSplitter(this); m_splitter = new MiniSplitter(this);
m_splitter->addWidget(m_leftEditor); m_splitter->addWidget(m_editor[LeftSide]);
m_splitter->addWidget(m_rightEditor); m_splitter->addWidget(m_editor[RightSide]);
QVBoxLayout *l = new QVBoxLayout(this); QVBoxLayout *l = new QVBoxLayout(this);
l->setContentsMargins(0, 0, 0, 0); l->setContentsMargins(0, 0, 0, 0);
l->addWidget(m_splitter); l->addWidget(m_splitter);
setFocusProxy(m_leftEditor); setFocusProxy(m_editor[LeftSide]);
auto leftContext = new IContext(this);
leftContext->setWidget(m_leftEditor);
leftContext->setContext(Core::Context(Utils::Id(Constants::SIDE_BY_SIDE_VIEW_ID).withSuffix(1)));
Core::ICore::addContextObject(leftContext);
auto rightContext = new IContext(this);
rightContext->setWidget(m_rightEditor);
rightContext->setContext(Core::Context(Utils::Id(Constants::SIDE_BY_SIDE_VIEW_ID).withSuffix(2)));
Core::ICore::addContextObject(rightContext);
} }
SideBySideDiffEditorWidget::~SideBySideDiffEditorWidget() SideBySideDiffEditorWidget::~SideBySideDiffEditorWidget()
@@ -887,14 +868,9 @@ SideBySideDiffEditorWidget::~SideBySideDiffEditorWidget()
} }
} }
TextEditorWidget *SideBySideDiffEditorWidget::leftEditorWidget() const TextEditorWidget *SideBySideDiffEditorWidget::sideEditorWidget(DiffSide side) const
{ {
return m_leftEditor; return m_editor[side];
}
TextEditorWidget *SideBySideDiffEditorWidget::rightEditorWidget() const
{
return m_rightEditor;
} }
void SideBySideDiffEditorWidget::setDocument(DiffEditorDocument *document) void SideBySideDiffEditorWidget::setDocument(DiffEditorDocument *document)
@@ -916,8 +892,8 @@ void SideBySideDiffEditorWidget::clear(const QString &message)
{ {
const GuardLocker locker(m_controller.m_ignoreChanges); const GuardLocker locker(m_controller.m_ignoreChanges);
setDiff({}); setDiff({});
m_leftEditor->clearAll(message); for (SideDiffEditorWidget *editor : m_editor)
m_rightEditor->clearAll(message); editor->clearAll(message);
if (m_watcher) { if (m_watcher) {
m_watcher->cancel(); m_watcher->cancel();
DiffEditorPlugin::addFuture(m_watcher->future()); DiffEditorPlugin::addFuture(m_watcher->future());
@@ -929,14 +905,14 @@ void SideBySideDiffEditorWidget::clear(const QString &message)
void SideBySideDiffEditorWidget::setDiff(const QList<FileData> &diffFileList) void SideBySideDiffEditorWidget::setDiff(const QList<FileData> &diffFileList)
{ {
const GuardLocker locker(m_controller.m_ignoreChanges); const GuardLocker locker(m_controller.m_ignoreChanges);
m_leftEditor->clearAll(tr("Waiting for data...")); for (SideDiffEditorWidget *editor : m_editor)
m_rightEditor->clearAll(tr("Waiting for data...")); editor->clearAll(tr("Waiting for data..."));
m_controller.m_contextFileData = diffFileList; m_controller.m_contextFileData = diffFileList;
if (m_controller.m_contextFileData.isEmpty()) { if (m_controller.m_contextFileData.isEmpty()) {
const QString msg = tr("No difference."); const QString msg = tr("No difference.");
m_leftEditor->setPlainText(msg); for (SideDiffEditorWidget *editor : m_editor)
m_rightEditor->setPlainText(msg); editor->setPlainText(msg);
} else { } else {
showDiff(); showDiff();
} }
@@ -947,40 +923,36 @@ void SideBySideDiffEditorWidget::setCurrentDiffFileIndex(int diffFileIndex)
if (m_controller.m_ignoreChanges.isLocked()) if (m_controller.m_ignoreChanges.isLocked())
return; return;
const int blockNumber = m_leftEditor->diffData().blockNumberForFileIndex(diffFileIndex); const int blockNumber = m_editor[LeftSide]->diffData().blockNumberForFileIndex(diffFileIndex);
const GuardLocker locker(m_controller.m_ignoreChanges); const GuardLocker locker(m_controller.m_ignoreChanges);
m_controller.setCurrentDiffFileIndex(diffFileIndex); m_controller.setCurrentDiffFileIndex(diffFileIndex);
QTextBlock leftBlock = m_leftEditor->document()->findBlockByNumber(blockNumber); for (SideDiffEditorWidget *editor : m_editor) {
QTextCursor leftCursor = m_leftEditor->textCursor(); QTextBlock block = editor->document()->findBlockByNumber(blockNumber);
leftCursor.setPosition(leftBlock.position()); QTextCursor cursor = editor->textCursor();
m_leftEditor->setTextCursor(leftCursor); cursor.setPosition(block.position());
m_leftEditor->verticalScrollBar()->setValue(blockNumber); editor->setTextCursor(cursor);
editor->verticalScrollBar()->setValue(blockNumber);
QTextBlock rightBlock = m_rightEditor->document()->findBlockByNumber(blockNumber); }
QTextCursor rightCursor = m_rightEditor->textCursor();
rightCursor.setPosition(rightBlock.position());
m_rightEditor->setTextCursor(rightCursor);
m_rightEditor->verticalScrollBar()->setValue(blockNumber);
} }
void SideBySideDiffEditorWidget::setHorizontalSync(bool sync) void SideBySideDiffEditorWidget::setHorizontalSync(bool sync)
{ {
m_horizontalSync = sync; m_horizontalSync = sync;
rightHSliderChanged(); horizontalSliderChanged(RightSide);
} }
void SideBySideDiffEditorWidget::saveState() void SideBySideDiffEditorWidget::saveState()
{ {
m_leftEditor->saveState(); for (SideDiffEditorWidget *editor : m_editor)
m_rightEditor->saveState(); editor->saveState();
} }
void SideBySideDiffEditorWidget::restoreState() void SideBySideDiffEditorWidget::restoreState()
{ {
m_leftEditor->restoreState(); for (SideDiffEditorWidget *editor : m_editor)
m_rightEditor->restoreState(); editor->restoreState();
} }
void SideBySideDiffEditorWidget::showDiff() void SideBySideDiffEditorWidget::showDiff()
@@ -990,12 +962,12 @@ void SideBySideDiffEditorWidget::showDiff()
connect(m_watcher.get(), &QFutureWatcherBase::finished, this, [this] { connect(m_watcher.get(), &QFutureWatcherBase::finished, this, [this] {
if (m_watcher->isCanceled()) { if (m_watcher->isCanceled()) {
m_leftEditor->clearAll(tr("Retrieving data failed.")); for (SideDiffEditorWidget *editor : m_editor)
m_rightEditor->clearAll(tr("Retrieving data failed.")); editor->clearAll(tr("Retrieving data failed."));
} else { } else {
const ShowResults results = m_watcher->result(); const ShowResults results = m_watcher->result();
m_leftEditor->setDiffData(results[LeftSide].diffData); m_editor[LeftSide]->setDiffData(results[LeftSide].diffData);
m_rightEditor->setDiffData(results[RightSide].diffData); m_editor[RightSide]->setDiffData(results[RightSide].diffData);
TextDocumentPtr leftDoc(results[LeftSide].textDocument); TextDocumentPtr leftDoc(results[LeftSide].textDocument);
TextDocumentPtr rightDoc(results[RightSide].textDocument); TextDocumentPtr rightDoc(results[RightSide].textDocument);
{ {
@@ -1003,14 +975,14 @@ void SideBySideDiffEditorWidget::showDiff()
// TextDocument was living in no thread, so it's safe to pull it // TextDocument was living in no thread, so it's safe to pull it
leftDoc->moveToThread(thread()); leftDoc->moveToThread(thread());
rightDoc->moveToThread(thread()); rightDoc->moveToThread(thread());
m_leftEditor->setTextDocument(leftDoc); m_editor[LeftSide]->setTextDocument(leftDoc);
m_rightEditor->setTextDocument(rightDoc); m_editor[RightSide]->setTextDocument(rightDoc);
m_leftEditor->setReadOnly(true); m_editor[LeftSide]->setReadOnly(true);
m_rightEditor->setReadOnly(true); m_editor[RightSide]->setReadOnly(true);
} }
m_leftEditor->setSelections(results[LeftSide].selections); m_editor[LeftSide]->setSelections(results[LeftSide].selections);
m_rightEditor->setSelections(results[RightSide].selections); m_editor[RightSide]->setSelections(results[RightSide].selections);
setCurrentDiffFileIndex(m_controller.currentDiffFileIndex()); setCurrentDiffFileIndex(m_controller.currentDiffFileIndex());
} }
m_watcher.release()->deleteLater(); m_watcher.release()->deleteLater();
@@ -1091,146 +1063,92 @@ void SideBySideDiffEditorWidget::setFontSettings(const FontSettings &fontSetting
m_controller.setFontSettings(fontSettings); m_controller.setFontSettings(fontSettings);
} }
void SideBySideDiffEditorWidget::slotLeftJumpToOriginalFileRequested( void SideBySideDiffEditorWidget::jumpToOriginalFileRequested(DiffSide side, int diffFileIndex,
int diffFileIndex, int lineNumber, int columnNumber)
int lineNumber,
int columnNumber)
{ {
if (diffFileIndex < 0 || diffFileIndex >= m_controller.m_contextFileData.count()) if (diffFileIndex < 0 || diffFileIndex >= m_controller.m_contextFileData.count())
return; return;
const FileData fileData = m_controller.m_contextFileData.at(diffFileIndex); const FileData fileData = m_controller.m_contextFileData.at(diffFileIndex);
const QString leftFileName = fileData.fileInfo[LeftSide].fileName; const QString fileName = fileData.fileInfo[side].fileName;
const QString rightFileName = fileData.fileInfo[RightSide].fileName; const DiffSide otherSide = oppositeSide(side);
if (leftFileName == rightFileName) { const QString otherFileName = fileData.fileInfo[otherSide].fileName;
// The same file (e.g. in git diff), jump to the line number taken from the right editor. if (side == RightSide || fileName != otherFileName) {
// Warning: git show SHA^ vs SHA or git diff HEAD vs Index // different file (e.g. in Tools | Diff...)
// (when Working tree has changed in meantime) will not work properly. m_controller.jumpToOriginalFile(fileName, lineNumber, columnNumber);
for (const ChunkData &chunkData : fileData.chunks) { return;
}
int leftLineNumber = chunkData.startingLineNumber[LeftSide]; // The same file (e.g. in git diff), jump to the line number taken from the right editor.
int rightLineNumber = chunkData.startingLineNumber[RightSide]; // Warning: git show SHA^ vs SHA or git diff HEAD vs Index
// (when Working tree has changed in meantime) will not work properly.
for (const ChunkData &chunkData : fileData.chunks) {
for (int j = 0; j < chunkData.rows.count(); j++) { int thisLineNumber = chunkData.startingLineNumber[side];
const RowData rowData = chunkData.rows.at(j); int otherLineNumber = chunkData.startingLineNumber[otherSide];
if (rowData.line[LeftSide].textLineType == TextLineData::TextLine)
leftLineNumber++; for (int j = 0; j < chunkData.rows.count(); j++) {
if (rowData.line[RightSide].textLineType == TextLineData::TextLine) const RowData rowData = chunkData.rows.at(j);
rightLineNumber++; if (rowData.line[side].textLineType == TextLineData::TextLine)
if (leftLineNumber == lineNumber) { thisLineNumber++;
int colNr = rowData.equal ? columnNumber : 0; if (rowData.line[otherSide].textLineType == TextLineData::TextLine)
m_controller.jumpToOriginalFile(leftFileName, rightLineNumber, colNr); otherLineNumber++;
return; if (thisLineNumber == lineNumber) {
} int colNr = rowData.equal ? columnNumber : 0;
m_controller.jumpToOriginalFile(fileName, otherLineNumber, colNr);
return;
} }
} }
} else {
// different file (e.g. in Tools | Diff...)
m_controller.jumpToOriginalFile(leftFileName, lineNumber, columnNumber);
} }
} }
void SideBySideDiffEditorWidget::slotRightJumpToOriginalFileRequested( void SideBySideDiffEditorWidget::contextMenuRequested(DiffSide side, QMenu *menu, int fileIndex,
int diffFileIndex, int chunkIndex, const ChunkSelection &selection)
int lineNumber,
int columnNumber)
{
if (diffFileIndex < 0 || diffFileIndex >= m_controller.m_contextFileData.count())
return;
const FileData fileData = m_controller.m_contextFileData.at(diffFileIndex);
const QString fileName = fileData.fileInfo[RightSide].fileName;
m_controller.jumpToOriginalFile(fileName, lineNumber, columnNumber);
}
void SideBySideDiffEditorWidget::slotLeftContextMenuRequested(QMenu *menu,
int fileIndex,
int chunkIndex,
const ChunkSelection &selection)
{ {
menu->addSeparator(); menu->addSeparator();
m_controller.addCodePasterAction(menu, fileIndex, chunkIndex); m_controller.addCodePasterAction(menu, fileIndex, chunkIndex);
m_controller.addApplyAction(menu, fileIndex, chunkIndex); m_controller.addApplyRevertAction(menu, fileIndex, chunkIndex, side);
m_controller.addExtraActions(menu, fileIndex, chunkIndex, selection); m_controller.addExtraActions(menu, fileIndex, chunkIndex, selection);
} }
void SideBySideDiffEditorWidget::slotRightContextMenuRequested(QMenu *menu, void SideBySideDiffEditorWidget::verticalSliderChanged(DiffSide side)
int fileIndex,
int chunkIndex,
const ChunkSelection &selection)
{
menu->addSeparator();
m_controller.addCodePasterAction(menu, fileIndex, chunkIndex);
m_controller.addRevertAction(menu, fileIndex, chunkIndex);
m_controller.addExtraActions(menu, fileIndex, chunkIndex, selection);
}
void SideBySideDiffEditorWidget::leftVSliderChanged()
{ {
if (m_controller.m_ignoreChanges.isLocked()) if (m_controller.m_ignoreChanges.isLocked())
return; return;
m_rightEditor->verticalScrollBar()->setValue(m_leftEditor->verticalScrollBar()->value()); m_editor[oppositeSide(side)]->verticalScrollBar()->setValue(
m_editor[side]->verticalScrollBar()->value());
} }
void SideBySideDiffEditorWidget::rightVSliderChanged() void SideBySideDiffEditorWidget::horizontalSliderChanged(DiffSide side)
{
if (m_controller.m_ignoreChanges.isLocked() || !m_horizontalSync)
return;
m_editor[oppositeSide(side)]->horizontalScrollBar()->setValue(
m_editor[side]->horizontalScrollBar()->value());
}
void SideBySideDiffEditorWidget::cursorPositionChanged(DiffSide side)
{ {
if (m_controller.m_ignoreChanges.isLocked()) if (m_controller.m_ignoreChanges.isLocked())
return; return;
m_leftEditor->verticalScrollBar()->setValue(m_rightEditor->verticalScrollBar()->value()); handlePositionChange(m_editor[side], m_editor[oppositeSide(side)]);
} verticalSliderChanged(side);
horizontalSliderChanged(side);
void SideBySideDiffEditorWidget::leftHSliderChanged()
{
if (m_controller.m_ignoreChanges.isLocked())
return;
if (m_horizontalSync)
m_rightEditor->horizontalScrollBar()->setValue(m_leftEditor->horizontalScrollBar()->value());
}
void SideBySideDiffEditorWidget::rightHSliderChanged()
{
if (m_controller.m_ignoreChanges.isLocked())
return;
if (m_horizontalSync)
m_leftEditor->horizontalScrollBar()->setValue(m_rightEditor->horizontalScrollBar()->value());
}
void SideBySideDiffEditorWidget::leftCursorPositionChanged()
{
if (m_controller.m_ignoreChanges.isLocked())
return;
handlePositionChange(m_leftEditor, m_rightEditor);
leftVSliderChanged();
leftHSliderChanged();
}
void SideBySideDiffEditorWidget::rightCursorPositionChanged()
{
if (m_controller.m_ignoreChanges.isLocked())
return;
handlePositionChange(m_rightEditor, m_leftEditor);
rightVSliderChanged();
rightHSliderChanged();
} }
void SideBySideDiffEditorWidget::syncHorizontalScrollBarPolicy() void SideBySideDiffEditorWidget::syncHorizontalScrollBarPolicy()
{ {
const bool alwaysOn = m_leftEditor->horizontalScrollBar()->maximum() const bool alwaysOn = m_editor[LeftSide]->horizontalScrollBar()->maximum()
|| m_rightEditor->horizontalScrollBar()->maximum(); || m_editor[RightSide]->horizontalScrollBar()->maximum();
const Qt::ScrollBarPolicy newPolicy = alwaysOn const Qt::ScrollBarPolicy newPolicy = alwaysOn ? Qt::ScrollBarAlwaysOn : Qt::ScrollBarAsNeeded;
? Qt::ScrollBarAlwaysOn : Qt::ScrollBarAsNeeded; for (SideDiffEditorWidget *editor : m_editor) {
if (m_leftEditor->horizontalScrollBarPolicy() != newPolicy) if (editor->horizontalScrollBarPolicy() != newPolicy)
m_leftEditor->setHorizontalScrollBarPolicy(newPolicy); editor->setHorizontalScrollBarPolicy(newPolicy);
if (m_rightEditor->horizontalScrollBarPolicy() != newPolicy) }
m_rightEditor->setHorizontalScrollBarPolicy(newPolicy);
} }
void SideBySideDiffEditorWidget::handlePositionChange(SideDiffEditorWidget *source, SideDiffEditorWidget *dest) void SideBySideDiffEditorWidget::handlePositionChange(SideDiffEditorWidget *source, SideDiffEditorWidget *dest)

View File

@@ -3,6 +3,7 @@
#pragma once #pragma once
#include "diffenums.h"
#include "diffeditorwidgetcontroller.h" #include "diffeditorwidgetcontroller.h"
#include "selectabletexteditorwidget.h" // TODO: we need DiffSelections here only #include "selectabletexteditorwidget.h" // TODO: we need DiffSelections here only
@@ -94,8 +95,7 @@ public:
explicit SideBySideDiffEditorWidget(QWidget *parent = nullptr); explicit SideBySideDiffEditorWidget(QWidget *parent = nullptr);
~SideBySideDiffEditorWidget(); ~SideBySideDiffEditorWidget();
TextEditor::TextEditorWidget *leftEditorWidget() const; TextEditor::TextEditorWidget *sideEditorWidget(DiffSide side) const;
TextEditor::TextEditorWidget *rightEditorWidget() const;
void setDocument(DiffEditorDocument *document); void setDocument(DiffEditorDocument *document);
DiffEditorDocument *diffDocument() const; DiffEditorDocument *diffDocument() const;
@@ -115,28 +115,20 @@ signals:
private: private:
void setFontSettings(const TextEditor::FontSettings &fontSettings); void setFontSettings(const TextEditor::FontSettings &fontSettings);
void slotLeftJumpToOriginalFileRequested(int diffFileIndex, void jumpToOriginalFileRequested(DiffSide side, int diffFileIndex,
int lineNumber, int columnNumber); int lineNumber, int columnNumber);
void slotRightJumpToOriginalFileRequested(int diffFileIndex, void contextMenuRequested(DiffSide side, QMenu *menu, int fileIndex, int chunkIndex,
int lineNumber, int columnNumber); const ChunkSelection &selection);
void slotLeftContextMenuRequested(QMenu *menu, int fileIndex, void verticalSliderChanged(DiffSide side);
int chunkIndex, const ChunkSelection &selection); void horizontalSliderChanged(DiffSide side);
void slotRightContextMenuRequested(QMenu *menu, int fileIndex, void cursorPositionChanged(DiffSide side);
int chunkIndex, const ChunkSelection &selection);
void leftVSliderChanged();
void rightVSliderChanged();
void leftHSliderChanged();
void rightHSliderChanged();
void leftCursorPositionChanged();
void rightCursorPositionChanged();
void syncHorizontalScrollBarPolicy(); void syncHorizontalScrollBarPolicy();
void handlePositionChange(SideDiffEditorWidget *source, SideDiffEditorWidget *dest); void handlePositionChange(SideDiffEditorWidget *source, SideDiffEditorWidget *dest);
void syncCursor(SideDiffEditorWidget *source, SideDiffEditorWidget *dest); void syncCursor(SideDiffEditorWidget *source, SideDiffEditorWidget *dest);
void showDiff(); void showDiff();
SideDiffEditorWidget *m_leftEditor = nullptr; std::array<SideDiffEditorWidget *, SideCount> m_editor{};
SideDiffEditorWidget *m_rightEditor = nullptr;
QSplitter *m_splitter = nullptr; QSplitter *m_splitter = nullptr;
DiffEditorWidgetController m_controller; DiffEditorWidgetController m_controller;

View File

@@ -212,16 +212,14 @@ void UnifiedDiffEditorWidget::contextMenuEvent(QContextMenuEvent *e)
delete menu; delete menu;
} }
void UnifiedDiffEditorWidget::addContextMenuActions(QMenu *menu, void UnifiedDiffEditorWidget::addContextMenuActions(QMenu *menu, int fileIndex, int chunkIndex,
int fileIndex,
int chunkIndex,
const ChunkSelection &selection) const ChunkSelection &selection)
{ {
menu->addSeparator(); menu->addSeparator();
m_controller.addCodePasterAction(menu, fileIndex, chunkIndex); m_controller.addCodePasterAction(menu, fileIndex, chunkIndex);
m_controller.addApplyAction(menu, fileIndex, chunkIndex); m_controller.addApplyRevertAction(menu, fileIndex, chunkIndex, LeftSide);
m_controller.addRevertAction(menu, fileIndex, chunkIndex); m_controller.addApplyRevertAction(menu, fileIndex, chunkIndex, RightSide);
m_controller.addExtraActions(menu, fileIndex, chunkIndex, selection); m_controller.addExtraActions(menu, fileIndex, chunkIndex, selection);
} }

View File

@@ -103,9 +103,7 @@ private:
int fileIndexForBlockNumber(int blockNumber) const; int fileIndexForBlockNumber(int blockNumber) const;
int chunkIndexForBlockNumber(int blockNumber) const; int chunkIndexForBlockNumber(int blockNumber) const;
void jumpToOriginalFile(const QTextCursor &cursor); void jumpToOriginalFile(const QTextCursor &cursor);
void addContextMenuActions(QMenu *menu, void addContextMenuActions(QMenu *menu, int fileIndex, int chunkIndex,
int fileIndex,
int chunkIndex,
const ChunkSelection &selection); const ChunkSelection &selection);
UnifiedDiffData m_data; UnifiedDiffData m_data;