aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/diffeditor
diff options
context:
space:
mode:
authorAndre Hartmann <aha_1980@gmx.de>2017-11-29 21:36:30 +0100
committerJarek Kobus <jaroslaw.kobus@qt.io>2019-11-19 11:19:43 +0000
commit17668329181be771669c10baa0e322e0192fecdb (patch)
treeca70331ef982dc38de26da13201b6f8c090dd3c9 /src/plugins/diffeditor
parent27586827238ca9079860e77a7b23ae20d163143e (diff)
DiffEditor: Stage and unstage selected lines for Git
Fixes: QTCREATORBUG-19071 Change-Id: I560ba208e68e477ea865e499847d819cfdfeb6f3 Reviewed-by: Orgad Shaneh <orgads@gmail.com> Reviewed-by: André Hartmann <aha_1980@gmx.de>
Diffstat (limited to 'src/plugins/diffeditor')
-rw-r--r--src/plugins/diffeditor/diffeditorcontroller.cpp8
-rw-r--r--src/plugins/diffeditor/diffeditorcontroller.h11
-rw-r--r--src/plugins/diffeditor/diffeditordocument.cpp34
-rw-r--r--src/plugins/diffeditor/diffeditordocument.h5
-rw-r--r--src/plugins/diffeditor/diffeditorplugin.cpp135
-rw-r--r--src/plugins/diffeditor/diffeditorplugin.h2
-rw-r--r--src/plugins/diffeditor/diffeditorwidgetcontroller.cpp33
-rw-r--r--src/plugins/diffeditor/diffeditorwidgetcontroller.h6
-rw-r--r--src/plugins/diffeditor/diffutils.h9
-rw-r--r--src/plugins/diffeditor/sidebysidediffeditorwidget.cpp80
-rw-r--r--src/plugins/diffeditor/sidebysidediffeditorwidget.h4
-rw-r--r--src/plugins/diffeditor/unifieddiffeditorwidget.cpp94
-rw-r--r--src/plugins/diffeditor/unifieddiffeditorwidget.h14
13 files changed, 389 insertions, 46 deletions
diff --git a/src/plugins/diffeditor/diffeditorcontroller.cpp b/src/plugins/diffeditor/diffeditorcontroller.cpp
index 0a82110bbe..7ca1a4694b 100644
--- a/src/plugins/diffeditor/diffeditorcontroller.cpp
+++ b/src/plugins/diffeditor/diffeditorcontroller.cpp
@@ -71,9 +71,10 @@ bool DiffEditorController::ignoreWhitespace() const
}
QString DiffEditorController::makePatch(int fileIndex, int chunkIndex,
+ const ChunkSelection &selection,
PatchOptions options) const
{
- return m_document->makePatch(fileIndex, chunkIndex,
+ return m_document->makePatch(fileIndex, chunkIndex, selection,
options & Revert, options & AddPrefix);
}
@@ -143,9 +144,10 @@ void DiffEditorController::reloadFinished(bool success)
m_isReloading = false;
}
-void DiffEditorController::requestChunkActions(QMenu *menu, int fileIndex, int chunkIndex)
+void DiffEditorController::requestChunkActions(QMenu *menu, int fileIndex, int chunkIndex,
+ const ChunkSelection &selection)
{
- emit chunkActionsRequested(menu, fileIndex, chunkIndex);
+ emit chunkActionsRequested(menu, fileIndex, chunkIndex, selection);
}
bool DiffEditorController::chunkExists(int fileIndex, int chunkIndex) const
diff --git a/src/plugins/diffeditor/diffeditorcontroller.h b/src/plugins/diffeditor/diffeditorcontroller.h
index b32537c0e4..ef8f209254 100644
--- a/src/plugins/diffeditor/diffeditorcontroller.h
+++ b/src/plugins/diffeditor/diffeditorcontroller.h
@@ -38,6 +38,8 @@ namespace DiffEditor {
namespace Internal { class DiffEditorDocument; }
+class ChunkSelection;
+
class DIFFEDITOR_EXPORT DiffEditorController : public QObject
{
Q_OBJECT
@@ -58,18 +60,21 @@ public:
AddPrefix = 2
};
Q_DECLARE_FLAGS(PatchOptions, PatchOption)
- QString makePatch(int fileIndex, int chunkIndex, PatchOptions options) const;
+ QString makePatch(int fileIndex, int chunkIndex, const ChunkSelection &selection,
+ PatchOptions options) const;
static Core::IDocument *findOrCreateDocument(const QString &vcsId,
const QString &displayName);
static DiffEditorController *controller(Core::IDocument *document);
- void requestChunkActions(QMenu *menu, int fileIndex, int chunkIndex);
+ 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);
+ void chunkActionsRequested(QMenu *menu, int fileIndex, int chunkIndex,
+ const ChunkSelection &selection);
protected:
// reloadFinished() should be called
diff --git a/src/plugins/diffeditor/diffeditordocument.cpp b/src/plugins/diffeditor/diffeditordocument.cpp
index b38235adbe..529dac382e 100644
--- a/src/plugins/diffeditor/diffeditordocument.cpp
+++ b/src/plugins/diffeditor/diffeditordocument.cpp
@@ -76,7 +76,39 @@ DiffEditorController *DiffEditorDocument::controller() const
return m_controller;
}
+ChunkData DiffEditorDocument::filterChunk(const ChunkData &data,
+ const ChunkSelection &selection, bool revert)
+{
+ if (selection.isNull())
+ return data;
+
+ ChunkData chunk(data);
+ for (int i = 0; i < chunk.rows.count(); ++i) {
+ RowData &row = chunk.rows[i];
+ if (i < selection.startRow || i >= selection.startRow + selection.selectedRowsCount) {
+ if (revert)
+ row.leftLine = row.rightLine;
+ else
+ row.rightLine = row.leftLine;
+ row.equal = true;
+ }
+ }
+
+ for (int i = 0; i < chunk.rows.count(); ) {
+ const RowData &row = chunk.rows[i];
+ const bool isSeparator = row.leftLine.textLineType == TextLineData::Separator
+ && row.rightLine.textLineType == TextLineData::Separator;
+ if (isSeparator)
+ chunk.rows.removeAt(i);
+ else
+ ++i;
+ }
+
+ return chunk;
+}
+
QString DiffEditorDocument::makePatch(int fileIndex, int chunkIndex,
+ const ChunkSelection &selection,
bool revert, bool addPrefix,
const QString &overriddenFileName) const
{
@@ -90,7 +122,7 @@ QString DiffEditorDocument::makePatch(int fileIndex, int chunkIndex,
if (chunkIndex >= fileData.chunks.count())
return QString();
- const ChunkData &chunkData = fileData.chunks.at(chunkIndex);
+ const ChunkData chunkData = filterChunk(fileData.chunks.at(chunkIndex), selection, revert);
const bool lastChunk = (chunkIndex == fileData.chunks.count() - 1);
const QString fileName = !overriddenFileName.isEmpty()
diff --git a/src/plugins/diffeditor/diffeditordocument.h b/src/plugins/diffeditor/diffeditordocument.h
index 42657e43f3..dce1106260 100644
--- a/src/plugins/diffeditor/diffeditordocument.h
+++ b/src/plugins/diffeditor/diffeditordocument.h
@@ -34,6 +34,7 @@ QT_FORWARD_DECLARE_CLASS(QMenu)
namespace DiffEditor {
class DiffEditorController;
+class ChunkSelection;
namespace Internal {
@@ -52,7 +53,9 @@ public:
LoadFailed
};
- QString makePatch(int fileIndex, int chunkIndex,
+ static ChunkData filterChunk(const ChunkData &data,
+ const ChunkSelection &selection, bool revert);
+ QString makePatch(int fileIndex, int chunkIndex, const ChunkSelection &selection,
bool revert, bool addPrefix = false,
const QString &overriddenFileName = QString()) const;
diff --git a/src/plugins/diffeditor/diffeditorplugin.cpp b/src/plugins/diffeditor/diffeditorplugin.cpp
index 0c52b55a9e..652c6e9d14 100644
--- a/src/plugins/diffeditor/diffeditorplugin.cpp
+++ b/src/plugins/diffeditor/diffeditorplugin.cpp
@@ -610,6 +610,7 @@ void DiffEditorPlugin::diffExternalFiles()
Q_DECLARE_METATYPE(DiffEditor::ChunkData)
Q_DECLARE_METATYPE(DiffEditor::FileData)
+Q_DECLARE_METATYPE(DiffEditor::ChunkSelection)
static inline QString _(const char *string) { return QString::fromLatin1(string); }
@@ -1430,6 +1431,140 @@ void DiffEditor::Internal::DiffEditorPlugin::testReadPatch()
}
}
+void DiffEditor::Internal::DiffEditorPlugin::testFilterPatch_data()
+{
+ QTest::addColumn<ChunkData>("chunk");
+ QTest::addColumn<QStringList>("rightLines");
+ QTest::addColumn<ChunkSelection>("selection");
+
+ auto createChunk = []() {
+ ChunkData chunk;
+ chunk.contextInfo = "void DiffEditor::ctor()";
+ chunk.contextChunk = false;
+ chunk.leftStartingLineNumber = 49;
+ chunk.rightStartingLineNumber = 49;
+ return chunk;
+ };
+ auto appendRow = [](ChunkData *chunk, const QString &left, const QString &right) {
+ RowData row;
+ row.equal = (left == right);
+ row.leftLine.text = left;
+ row.leftLine.textLineType = left.isEmpty() ? TextLineData::Separator : TextLineData::TextLine;
+ row.rightLine.text = right;
+ row.rightLine.textLineType = right.isEmpty() ? TextLineData::Separator : TextLineData::TextLine;
+ chunk->rows.append(row);
+ };
+ ChunkData chunk;
+ QStringList rightLines;
+
+ chunk = createChunk();
+ appendRow(&chunk, "A", "A"); // 50
+ appendRow(&chunk, "", "B"); // 51 +
+ appendRow(&chunk, "C", "C"); // 52
+ rightLines = QStringList {
+ "A",
+ "B",
+ "C"
+ };
+ QTest::newRow("one added") << chunk << rightLines << ChunkSelection();
+
+ chunk = createChunk();
+ appendRow(&chunk, "A", "A"); // 50
+ appendRow(&chunk, "B", ""); // 51 -
+ appendRow(&chunk, "C", "C"); // 52
+ rightLines = QStringList {
+ "A",
+ "",
+ "C"
+ };
+ QTest::newRow("one removed") << chunk << rightLines << ChunkSelection();
+
+ chunk = createChunk();
+ appendRow(&chunk, "A", "A"); // 50
+ appendRow(&chunk, "", "B"); // 51
+ appendRow(&chunk, "", "C"); // 52 +
+ appendRow(&chunk, "", "D"); // 53 +
+ appendRow(&chunk, "", "E"); // 54
+ appendRow(&chunk, "F", "F"); // 55
+ rightLines = QStringList {
+ "A",
+ "C",
+ "D",
+ "F",
+ };
+ QTest::newRow("stage selected added") << chunk << rightLines << ChunkSelection(2, 2);
+
+ chunk = createChunk();
+ appendRow(&chunk, "A", "A"); // 50
+ appendRow(&chunk, "", "B"); // 51 +
+ appendRow(&chunk, "C", "D"); // 52
+ appendRow(&chunk, "E", "E"); // 53
+ rightLines = QStringList {
+ "A",
+ "B",
+ "C",
+ "E",
+ };
+ QTest::newRow("stage selected added keep changed") << chunk << rightLines << ChunkSelection(1, 1);
+
+ chunk = createChunk();
+ appendRow(&chunk, "A", "A"); // 50
+ appendRow(&chunk, "B", ""); // 51
+ appendRow(&chunk, "C", ""); // 52 -
+ appendRow(&chunk, "D", ""); // 53 -
+ appendRow(&chunk, "E", ""); // 54
+ appendRow(&chunk, "F", "F"); // 55
+ rightLines = QStringList {
+ "A",
+ "B",
+ "",
+ "",
+ "E",
+ "F",
+ };
+ QTest::newRow("stage selected removed") << chunk << rightLines << ChunkSelection(2, 2);
+
+ chunk = createChunk();
+ appendRow(&chunk, "A", "A"); // 50
+ appendRow(&chunk, "B", ""); // 51
+ appendRow(&chunk, "C", ""); // 52 -
+ appendRow(&chunk, "", "D"); // 53 +
+ appendRow(&chunk, "", "E"); // 54
+ appendRow(&chunk, "F", "F"); // 55
+ rightLines = QStringList {
+ "A",
+ "B",
+ "",
+ "D",
+ "F",
+ };
+ QTest::newRow("stage selected added/removed") << chunk << rightLines << ChunkSelection(2, 2);
+
+ chunk = createChunk();
+ appendRow(&chunk, "A", "A"); // 50
+ appendRow(&chunk, "B", "C"); // 51 -/+
+ appendRow(&chunk, "D", "D"); // 52
+ rightLines = QStringList {
+ "A",
+ "C",
+ "D",
+ };
+ QTest::newRow("stage modified row") << chunk << rightLines << ChunkSelection(1, 1);
+}
+
+void DiffEditor::Internal::DiffEditorPlugin::testFilterPatch()
+{
+ QFETCH(ChunkData, chunk);
+ QFETCH(QStringList, rightLines);
+ QFETCH(ChunkSelection, selection);
+
+ ChunkData result = DiffEditorDocument::filterChunk(chunk, selection, false);
+ QCOMPARE(result.rows.size(), rightLines.size());
+ for (int i = 0; i < rightLines.size(); ++i) {
+ QCOMPARE(result.rows.at(i).rightLine.text, rightLines.at(i));
+ }
+}
+
#endif // WITH_TESTS
#include "diffeditorplugin.moc"
diff --git a/src/plugins/diffeditor/diffeditorplugin.h b/src/plugins/diffeditor/diffeditorplugin.h
index 84d642b9f3..7ec3e2d392 100644
--- a/src/plugins/diffeditor/diffeditorplugin.h
+++ b/src/plugins/diffeditor/diffeditorplugin.h
@@ -73,6 +73,8 @@ private slots:
void testMakePatch();
void testReadPatch_data();
void testReadPatch();
+ void testFilterPatch_data();
+ void testFilterPatch();
#endif // WITH_TESTS
};
diff --git a/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp b/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp
index e1c656d5c7..c4f0ab5cb5 100644
--- a/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp
+++ b/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp
@@ -158,7 +158,7 @@ void DiffEditorWidgetController::patch(bool revert, int fileIndex, int chunkInde
if (patchBehaviour == DiffFileInfo::PatchFile) {
const int strip = m_document->baseDirectory().isEmpty() ? -1 : 0;
- const QString patch = m_document->makePatch(fileIndex, chunkIndex, revert);
+ const QString patch = m_document->makePatch(fileIndex, chunkIndex, ChunkSelection(), revert);
if (patch.isEmpty())
return;
@@ -183,8 +183,9 @@ void DiffEditorWidgetController::patch(bool revert, int fileIndex, int chunkInde
const QString contentsCopyFileName = contentsCopy.fileName();
const QString contentsCopyDir = QFileInfo(contentsCopyFileName).absolutePath();
- const QString patch = m_document->makePatch(fileIndex,
- chunkIndex, revert, false, QFileInfo(contentsCopyFileName).fileName());
+ const QString patch = m_document->makePatch(fileIndex, chunkIndex,
+ ChunkSelection(), revert, false,
+ QFileInfo(contentsCopyFileName).fileName());
if (patch.isEmpty())
return;
@@ -244,6 +245,24 @@ bool DiffEditorWidgetController::chunkExists(int fileIndex, int chunkIndex) cons
return false;
}
+ChunkData DiffEditorWidgetController::chunkData(int fileIndex, int chunkIndex) const
+{
+ if (!m_document)
+ return ChunkData();
+
+ if (fileIndex < 0 || chunkIndex < 0)
+ return ChunkData();
+
+ if (fileIndex >= m_contextFileData.count())
+ return ChunkData();
+
+ const FileData fileData = m_contextFileData.at(fileIndex);
+ if (chunkIndex >= fileData.chunks.count())
+ return ChunkData();
+
+ return fileData.chunks.at(chunkIndex);
+}
+
bool DiffEditorWidgetController::fileNamesAreDifferent(int fileIndex) const
{
const FileData fileData = m_contextFileData.at(fileIndex);
@@ -268,10 +287,11 @@ void DiffEditorWidgetController::addRevertAction(QMenu *menu, int fileIndex, int
revertAction->setEnabled(chunkExists(fileIndex, chunkIndex));
}
-void DiffEditorWidgetController::addExtraActions(QMenu *menu, int fileIndex, int chunkIndex)
+void DiffEditorWidgetController::addExtraActions(QMenu *menu, int fileIndex, int chunkIndex,
+ const ChunkSelection &selection)
{
if (DiffEditorController *controller = m_document->controller())
- controller->requestChunkActions(menu, fileIndex, chunkIndex);
+ controller->requestChunkActions(menu, fileIndex, chunkIndex, selection);
}
void DiffEditorWidgetController::sendChunkToCodePaster(int fileIndex, int chunkIndex)
@@ -283,7 +303,8 @@ void DiffEditorWidgetController::sendChunkToCodePaster(int fileIndex, int chunkI
auto pasteService = ExtensionSystem::PluginManager::getObject<CodePaster::Service>();
QTC_ASSERT(pasteService, return);
- const QString patch = m_document->makePatch(fileIndex, chunkIndex, false);
+ const QString patch = m_document->makePatch(fileIndex, chunkIndex,
+ ChunkSelection(), false);
if (patch.isEmpty())
return;
diff --git a/src/plugins/diffeditor/diffeditorwidgetcontroller.h b/src/plugins/diffeditor/diffeditorwidgetcontroller.h
index c0c1be9548..4951ec1cb4 100644
--- a/src/plugins/diffeditor/diffeditorwidgetcontroller.h
+++ b/src/plugins/diffeditor/diffeditorwidgetcontroller.h
@@ -39,6 +39,8 @@ namespace Utils { class ProgressIndicator; }
namespace DiffEditor {
+class ChunkSelection;
+
namespace Internal {
class DiffEditorDocument;
@@ -58,7 +60,9 @@ public:
void addCodePasterAction(QMenu *menu, int fileIndex, int chunkIndex);
void addApplyAction(QMenu *menu, int fileIndex, int chunkIndex);
void addRevertAction(QMenu *menu, int fileIndex, int chunkIndex);
- void addExtraActions(QMenu *menu, int fileIndex, int chunkIndex);
+ void addExtraActions(QMenu *menu, int fileIndex, int chunkIndex, const ChunkSelection &selection);
+
+ ChunkData chunkData(int fileIndex, int chunkIndex) const;
bool m_ignoreCurrentIndexChange = false;
QList<FileData> m_contextFileData; // ultimate data to be shown
diff --git a/src/plugins/diffeditor/diffutils.h b/src/plugins/diffeditor/diffutils.h
index 605266a0ef..47ae8c126a 100644
--- a/src/plugins/diffeditor/diffutils.h
+++ b/src/plugins/diffeditor/diffutils.h
@@ -99,6 +99,15 @@ public:
bool contextChunk = false;
};
+class DIFFEDITOR_EXPORT ChunkSelection {
+public:
+ ChunkSelection() {}
+ ChunkSelection(int s, int c) : startRow(s), selectedRowsCount(c) {}
+ bool isNull() const { return selectedRowsCount <= 0; }
+ int startRow = -1;
+ int selectedRowsCount = 0;
+};
+
class DIFFEDITOR_EXPORT FileData {
public:
enum FileOperation {
diff --git a/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp b/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp
index a2799e7ca0..ffe4b2bc14 100644
--- a/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp
+++ b/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp
@@ -79,6 +79,8 @@ public:
int blockNumberForFileIndex(int fileIndex) const;
int fileIndexForBlockNumber(int blockNumber) const;
int chunkIndexForBlockNumber(int blockNumber) const;
+ int chunkRowForBlockNumber(int blockNumber) const;
+ int chunkRowsCountForBlockNumber(int blockNumber) const;
bool isChunkLine(int blockNumber) const {
return m_skippedLines.contains(blockNumber);
}
@@ -97,7 +99,8 @@ signals:
int columnNumber);
void contextMenuRequested(QMenu *menu,
int diffFileIndex,
- int chunkIndex);
+ int chunkIndex,
+ const ChunkSelection &selection);
void foldChanged(int blockNumber, bool folded);
void gotDisplaySettings();
void gotFocus();
@@ -355,6 +358,40 @@ int SideDiffEditorWidget::chunkIndexForBlockNumber(int blockNumber) const
return -1;
}
+int SideDiffEditorWidget::chunkRowForBlockNumber(int blockNumber) const
+{
+ if (m_chunkInfo.isEmpty())
+ return -1;
+
+ auto it = m_chunkInfo.upperBound(blockNumber);
+ if (it == m_chunkInfo.constBegin())
+ return -1;
+
+ --it;
+
+ if (blockNumber < it.key() + it.value().first)
+ return blockNumber - it.key();
+
+ return -1;
+}
+
+int SideDiffEditorWidget::chunkRowsCountForBlockNumber(int blockNumber) const
+{
+ if (m_chunkInfo.isEmpty())
+ return -1;
+
+ auto it = m_chunkInfo.upperBound(blockNumber);
+ if (it == m_chunkInfo.constBegin())
+ return -1;
+
+ --it;
+
+ if (blockNumber < it.key() + it.value().first)
+ return it.value().first;
+
+ return -1;
+}
+
void SideDiffEditorWidget::clearAll(const QString &message)
{
setBlockSelection(false);
@@ -446,11 +483,40 @@ void SideDiffEditorWidget::contextMenuEvent(QContextMenuEvent *e)
{
QPointer<QMenu> menu = createStandardContextMenu();
+ const QTextCursor tc = textCursor();
+ QTextCursor start = tc;
+ start.setPosition(tc.selectionStart());
+ QTextCursor end = tc;
+ end.setPosition(tc.selectionEnd());
+ const int startBlockNumber = start.blockNumber();
+ const int endBlockNumber = end.blockNumber();
+
QTextCursor cursor = cursorForPosition(e->pos());
const int blockNumber = cursor.blockNumber();
+ const int fileIndex = fileIndexForBlockNumber(blockNumber);
+ const int chunkIndex = chunkIndexForBlockNumber(blockNumber);
+
+ const int selectionStartFileIndex = fileIndexForBlockNumber(startBlockNumber);
+ const int selectionStartChunkIndex = chunkIndexForBlockNumber(startBlockNumber);
+ const int selectionEndFileIndex = fileIndexForBlockNumber(endBlockNumber);
+ const int selectionEndChunkIndex = chunkIndexForBlockNumber(endBlockNumber);
+
+ const int selectionStart = selectionStartFileIndex == fileIndex
+ && selectionStartChunkIndex == chunkIndex
+ ? chunkRowForBlockNumber(startBlockNumber)
+ : 0;
+
+ const int selectionEnd = selectionEndFileIndex == fileIndex
+ && selectionEndChunkIndex == chunkIndex
+ ? chunkRowForBlockNumber(endBlockNumber)
+ : chunkRowsCountForBlockNumber(blockNumber);
+
+ const ChunkSelection selection(selectionStart, selectionEnd - selectionStart + 1);
+
emit contextMenuRequested(menu, fileIndexForBlockNumber(blockNumber),
- chunkIndexForBlockNumber(blockNumber));
+ chunkIndexForBlockNumber(blockNumber),
+ selection);
connect(this, &SideDiffEditorWidget::destroyed, menu.data(), &QMenu::deleteLater);
menu->exec(e->globalPos());
@@ -1067,24 +1133,26 @@ void SideBySideDiffEditorWidget::slotRightJumpToOriginalFileRequested(
void SideBySideDiffEditorWidget::slotLeftContextMenuRequested(QMenu *menu,
int fileIndex,
- int chunkIndex)
+ int chunkIndex,
+ const ChunkSelection &selection)
{
menu->addSeparator();
m_controller.addCodePasterAction(menu, fileIndex, chunkIndex);
m_controller.addApplyAction(menu, fileIndex, chunkIndex);
- m_controller.addExtraActions(menu, fileIndex, chunkIndex);
+ m_controller.addExtraActions(menu, fileIndex, chunkIndex, selection);
}
void SideBySideDiffEditorWidget::slotRightContextMenuRequested(QMenu *menu,
int fileIndex,
- int chunkIndex)
+ 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);
+ m_controller.addExtraActions(menu, fileIndex, chunkIndex, selection);
}
void SideBySideDiffEditorWidget::leftVSliderChanged()
diff --git a/src/plugins/diffeditor/sidebysidediffeditorwidget.h b/src/plugins/diffeditor/sidebysidediffeditorwidget.h
index 5fbd253e7c..14795cf085 100644
--- a/src/plugins/diffeditor/sidebysidediffeditorwidget.h
+++ b/src/plugins/diffeditor/sidebysidediffeditorwidget.h
@@ -85,9 +85,9 @@ private:
void slotRightJumpToOriginalFileRequested(int diffFileIndex,
int lineNumber, int columnNumber);
void slotLeftContextMenuRequested(QMenu *menu, int fileIndex,
- int chunkIndex);
+ int chunkIndex, const ChunkSelection &selection);
void slotRightContextMenuRequested(QMenu *menu, int fileIndex,
- int chunkIndex);
+ int chunkIndex, const ChunkSelection &selection);
void leftVSliderChanged();
void rightVSliderChanged();
void leftHSliderChanged();
diff --git a/src/plugins/diffeditor/unifieddiffeditorwidget.cpp b/src/plugins/diffeditor/unifieddiffeditorwidget.cpp
index 83767e0a72..a383a55c15 100644
--- a/src/plugins/diffeditor/unifieddiffeditorwidget.cpp
+++ b/src/plugins/diffeditor/unifieddiffeditorwidget.cpp
@@ -178,11 +178,57 @@ void UnifiedDiffEditorWidget::contextMenuEvent(QContextMenuEvent *e)
{
QPointer<QMenu> menu = createStandardContextMenu();
+ const QTextCursor tc = textCursor();
+ QTextCursor start = tc;
+ start.setPosition(tc.selectionStart());
+ QTextCursor end = tc;
+ end.setPosition(tc.selectionEnd());
+ const int startBlockNumber = start.blockNumber();
+ const int endBlockNumber = end.blockNumber();
+
QTextCursor cursor = cursorForPosition(e->pos());
const int blockNumber = cursor.blockNumber();
+ const int fileIndex = fileIndexForBlockNumber(blockNumber);
+ const int chunkIndex = chunkIndexForBlockNumber(blockNumber);
+
+ const ChunkData chunkData = m_controller.chunkData(fileIndex, chunkIndex);
+
+ int selectionStart = -1;
+ int selectionEnd = -1;
+
+ for (int i = startBlockNumber; i <= endBlockNumber; ++i) {
+ const int currentFileIndex = fileIndexForBlockNumber(i);
+ if (currentFileIndex < fileIndex)
+ continue;
+
+ if (currentFileIndex > fileIndex)
+ break;
+
+ const int currentChunkIndex = chunkIndexForBlockNumber(i);
+ if (currentChunkIndex < chunkIndex)
+ continue;
+
+ if (currentChunkIndex > chunkIndex)
+ break;
+
+ const int leftRow = m_leftLineNumbers.value(i, qMakePair(-1, -1)).second;
+ const int rightRow = m_rightLineNumbers.value(i, qMakePair(-1, -1)).second;
+ const int row = leftRow >= 0 ? leftRow : rightRow;
+
+ if (row < 0)
+ continue;
+
+ if (selectionStart < 0 || selectionStart > row)
+ selectionStart = row;
+ if (selectionEnd < 0 || selectionEnd < row)
+ selectionEnd = row;
+ }
+
+ const ChunkSelection selection(selectionStart, selectionEnd - selectionStart + 1);
+
addContextMenuActions(menu, fileIndexForBlockNumber(blockNumber),
- chunkIndexForBlockNumber(blockNumber));
+ chunkIndexForBlockNumber(blockNumber), selection);
connect(this, &UnifiedDiffEditorWidget::destroyed, menu.data(), &QMenu::deleteLater);
menu->exec(e->globalPos());
@@ -191,14 +237,15 @@ void UnifiedDiffEditorWidget::contextMenuEvent(QContextMenuEvent *e)
void UnifiedDiffEditorWidget::addContextMenuActions(QMenu *menu,
int fileIndex,
- int chunkIndex)
+ int chunkIndex,
+ const ChunkSelection &selection)
{
menu->addSeparator();
m_controller.addCodePasterAction(menu, fileIndex, chunkIndex);
m_controller.addApplyAction(menu, fileIndex, chunkIndex);
m_controller.addRevertAction(menu, fileIndex, chunkIndex);
- m_controller.addExtraActions(menu, fileIndex, chunkIndex);
+ m_controller.addExtraActions(menu, fileIndex, chunkIndex, selection);
}
void UnifiedDiffEditorWidget::clear(const QString &message)
@@ -228,7 +275,7 @@ QString UnifiedDiffEditorWidget::lineNumber(int blockNumber) const
if (leftLineExists || rightLineExists) {
const QString leftLine = leftLineExists
- ? QString::number(m_leftLineNumbers.value(blockNumber))
+ ? QString::number(m_leftLineNumbers.value(blockNumber).first)
: QString();
lineNumberString += QString(m_leftLineNumberDigits - leftLine.count(),
' ') + leftLine;
@@ -236,7 +283,7 @@ QString UnifiedDiffEditorWidget::lineNumber(int blockNumber) const
lineNumberString += '|';
const QString rightLine = rightLineExists
- ? QString::number(m_rightLineNumbers.value(blockNumber))
+ ? QString::number(m_rightLineNumbers.value(blockNumber).first)
: QString();
lineNumberString += QString(m_rightLineNumberDigits - rightLine.count(),
' ') + rightLine;
@@ -249,18 +296,20 @@ int UnifiedDiffEditorWidget::lineNumberDigits() const
return m_leftLineNumberDigits + m_rightLineNumberDigits + 1;
}
-void UnifiedDiffEditorWidget::setLeftLineNumber(int blockNumber, int lineNumber)
+void UnifiedDiffEditorWidget::setLeftLineNumber(int blockNumber, int lineNumber,
+ int rowNumberInChunk)
{
const QString lineNumberString = QString::number(lineNumber);
- m_leftLineNumbers.insert(blockNumber, lineNumber);
+ m_leftLineNumbers.insert(blockNumber, qMakePair(lineNumber, rowNumberInChunk));
m_leftLineNumberDigits = qMax(m_leftLineNumberDigits,
lineNumberString.count());
}
-void UnifiedDiffEditorWidget::setRightLineNumber(int blockNumber, int lineNumber)
+void UnifiedDiffEditorWidget::setRightLineNumber(int blockNumber, int lineNumber,
+ int rowNumberInChunk)
{
const QString lineNumberString = QString::number(lineNumber);
- m_rightLineNumbers.insert(blockNumber, lineNumber);
+ m_rightLineNumbers.insert(blockNumber, qMakePair(lineNumber, rowNumberInChunk));
m_rightLineNumberDigits = qMax(m_rightLineNumberDigits,
lineNumberString.count());
}
@@ -307,6 +356,7 @@ QString UnifiedDiffEditorWidget::showChunk(const ChunkData &chunkData,
int blockCount = 0;
int charCount = 0;
QList<TextLineData> leftBuffer, rightBuffer;
+ QList<int> leftRowsBuffer, rightRowsBuffer;
(*selections)[*blockNumber].append(DiffSelection(&m_controller.m_chunkLineFormat));
@@ -356,7 +406,8 @@ QString UnifiedDiffEditorWidget::showChunk(const ChunkData &chunkData,
if (!line.isEmpty()) {
setLeftLineNumber(*blockNumber + blockCount + 1,
chunkData.leftStartingLineNumber
- + leftLineCount + 1);
+ + leftLineCount + 1,
+ leftRowsBuffer.at(j));
blockCount += blockDelta;
++leftLineCount;
}
@@ -366,6 +417,7 @@ QString UnifiedDiffEditorWidget::showChunk(const ChunkData &chunkData,
charCount += line.count();
}
leftBuffer.clear();
+ leftRowsBuffer.clear();
}
if (rightBuffer.count()) {
for (int j = 0; j < rightBuffer.count(); j++) {
@@ -396,7 +448,8 @@ QString UnifiedDiffEditorWidget::showChunk(const ChunkData &chunkData,
if (!line.isEmpty()) {
setRightLineNumber(*blockNumber + blockCount + 1,
chunkData.rightStartingLineNumber
- + rightLineCount + 1);
+ + rightLineCount + 1,
+ rightRowsBuffer.at(j));
blockCount += blockDelta;
++rightLineCount;
}
@@ -406,6 +459,7 @@ QString UnifiedDiffEditorWidget::showChunk(const ChunkData &chunkData,
charCount += line.count();
}
rightBuffer.clear();
+ rightRowsBuffer.clear();
}
if (i < chunkData.rows.count()) {
const QString line = DiffUtils::makePatchLine(' ',
@@ -416,10 +470,12 @@ QString UnifiedDiffEditorWidget::showChunk(const ChunkData &chunkData,
if (!line.isEmpty()) {
setLeftLineNumber(*blockNumber + blockCount + 1,
chunkData.leftStartingLineNumber
- + leftLineCount + 1);
+ + leftLineCount + 1,
+ i);
setRightLineNumber(*blockNumber + blockCount + 1,
chunkData.rightStartingLineNumber
- + rightLineCount + 1);
+ + rightLineCount + 1,
+ i);
blockCount += line.count('\n');
++leftLineCount;
++rightLineCount;
@@ -430,10 +486,14 @@ QString UnifiedDiffEditorWidget::showChunk(const ChunkData &chunkData,
charCount += line.count();
}
} else {
- if (rowData.leftLine.textLineType == TextLineData::TextLine)
+ if (rowData.leftLine.textLineType == TextLineData::TextLine) {
leftBuffer.append(rowData.leftLine);
- if (rowData.rightLine.textLineType == TextLineData::TextLine)
+ leftRowsBuffer.append(i);
+ }
+ if (rowData.rightLine.textLineType == TextLineData::TextLine) {
rightBuffer.append(rowData.rightLine);
+ rightRowsBuffer.append(i);
+ }
}
}
@@ -584,13 +644,13 @@ void UnifiedDiffEditorWidget::jumpToOriginalFile(const QTextCursor &cursor)
const int columnNumber = cursor.positionInBlock() - 1; // -1 for the first character in line
- const int rightLineNumber = m_rightLineNumbers.value(blockNumber, -1);
+ const int rightLineNumber = m_rightLineNumbers.value(blockNumber, qMakePair(-1, 0)).first;
if (rightLineNumber >= 0) {
m_controller.jumpToOriginalFile(rightFileName, rightLineNumber, columnNumber);
return;
}
- const int leftLineNumber = m_leftLineNumbers.value(blockNumber, -1);
+ const int leftLineNumber = m_leftLineNumbers.value(blockNumber, qMakePair(-1, 0)).first;
if (leftLineNumber >= 0) {
if (leftFileName == rightFileName) {
for (const ChunkData &chunkData : fileData.chunks) {
diff --git a/src/plugins/diffeditor/unifieddiffeditorwidget.h b/src/plugins/diffeditor/unifieddiffeditorwidget.h
index 087426e94e..993d6cba20 100644
--- a/src/plugins/diffeditor/unifieddiffeditorwidget.h
+++ b/src/plugins/diffeditor/unifieddiffeditorwidget.h
@@ -39,6 +39,7 @@ namespace DiffEditor {
class ChunkData;
class FileData;
+class ChunkSelection;
namespace Internal {
@@ -79,8 +80,8 @@ private:
void slotCursorPositionChangedInEditor();
- void setLeftLineNumber(int blockNumber, int lineNumber);
- void setRightLineNumber(int blockNumber, int lineNumber);
+ void setLeftLineNumber(int blockNumber, int lineNumber, int rowNumberInChunk);
+ void setRightLineNumber(int blockNumber, int lineNumber, int rowNumberInChunk);
void setFileInfo(int blockNumber,
const DiffFileInfo &leftFileInfo,
const DiffFileInfo &rightFileInfo);
@@ -97,11 +98,12 @@ private:
void jumpToOriginalFile(const QTextCursor &cursor);
void addContextMenuActions(QMenu *menu,
int fileIndex,
- int chunkIndex);
+ int chunkIndex,
+ const ChunkSelection &selection);
- // block number, visual line number.
- QMap<int, int> m_leftLineNumbers;
- QMap<int, int> m_rightLineNumbers;
+ // block number, visual line number, chunk row number
+ QMap<int, QPair<int, int> > m_leftLineNumbers;
+ QMap<int, QPair<int, int> > m_rightLineNumbers;
DiffEditorWidgetController m_controller;