summaryrefslogtreecommitdiff
path: root/src/plugins/diffeditor
diff options
context:
space:
mode:
authorjkobus <jaroslaw.kobus@digia.com>2014-02-28 10:40:20 +0100
committerJarek Kobus <jaroslaw.kobus@digia.com>2014-02-28 10:42:50 +0100
commita746f6fb27720926ab37273b824c6a4c77ef0fd2 (patch)
tree793aee6bf8dab6ec83441a921d1452b41a1b61aa /src/plugins/diffeditor
parentc09e80b8538cf072185a076b4aaf46ed51186bda (diff)
downloadqt-creator-a746f6fb27720926ab37273b824c6a4c77ef0fd2.tar.gz
Move internal structures and some functions into diffutils.h
Change-Id: Ia55e556fdb8de3a2aeebf768ad9db66d840766f2 Reviewed-by: Jarek Kobus <jaroslaw.kobus@digia.com>
Diffstat (limited to 'src/plugins/diffeditor')
-rw-r--r--src/plugins/diffeditor/diffeditor.pro2
-rw-r--r--src/plugins/diffeditor/diffeditor.qbs2
-rw-r--r--src/plugins/diffeditor/diffutils.cpp351
-rw-r--r--src/plugins/diffeditor/diffutils.h96
-rw-r--r--src/plugins/diffeditor/sidebysidediffeditorwidget.cpp368
-rw-r--r--src/plugins/diffeditor/sidebysidediffeditorwidget.h11
6 files changed, 463 insertions, 367 deletions
diff --git a/src/plugins/diffeditor/diffeditor.pro b/src/plugins/diffeditor/diffeditor.pro
index 6967772f8d..d015f3d1b4 100644
--- a/src/plugins/diffeditor/diffeditor.pro
+++ b/src/plugins/diffeditor/diffeditor.pro
@@ -11,6 +11,7 @@ HEADERS += diffeditor_global.h \
diffeditormanager.h \
diffeditorplugin.h \
differ.h \
+ diffutils.h \
sidebysidediffeditorwidget.h
SOURCES += diffeditor.cpp \
@@ -21,6 +22,7 @@ SOURCES += diffeditor.cpp \
diffeditormanager.cpp \
diffeditorplugin.cpp \
differ.cpp \
+ diffutils.cpp \
sidebysidediffeditorwidget.cpp
RESOURCES +=
diff --git a/src/plugins/diffeditor/diffeditor.qbs b/src/plugins/diffeditor/diffeditor.qbs
index e77f80318e..3ea42e4b79 100644
--- a/src/plugins/diffeditor/diffeditor.qbs
+++ b/src/plugins/diffeditor/diffeditor.qbs
@@ -31,6 +31,8 @@ QtcPlugin {
"diffeditorplugin.h",
"differ.cpp",
"differ.h",
+ "diffutils.cpp",
+ "diffutils.h",
"sidebysidediffeditorwidget.cpp",
"sidebysidediffeditorwidget.h",
]
diff --git a/src/plugins/diffeditor/diffutils.cpp b/src/plugins/diffeditor/diffutils.cpp
new file mode 100644
index 0000000000..550f2a48ae
--- /dev/null
+++ b/src/plugins/diffeditor/diffutils.cpp
@@ -0,0 +1,351 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "diffutils.h"
+#include "differ.h"
+#include <QStringList>
+
+namespace DiffEditor {
+namespace Internal {
+
+static QList<TextLineData> assemblyRows(const QStringList &lines,
+ const QMap<int, int> &lineSpans)
+{
+ QList<TextLineData> data;
+
+ const int lineCount = lines.count();
+ for (int i = 0; i <= lineCount; i++) {
+ for (int j = 0; j < lineSpans.value(i); j++)
+ data.append(TextLineData(TextLineData::Separator));
+ if (i < lineCount)
+ data.append(lines.at(i));
+ }
+ return data;
+}
+
+static bool lastLinesEqual(const QStringList &leftLines,
+ const QStringList &rightLines)
+{
+ const bool leftLineEqual = leftLines.count()
+ ? leftLines.last().isEmpty()
+ : true;
+ const bool rightLineEqual = rightLines.count()
+ ? rightLines.last().isEmpty()
+ : true;
+ return leftLineEqual && rightLineEqual;
+}
+
+static void handleLine(const QStringList &newLines,
+ int line,
+ QStringList *lines,
+ int *lineNumber,
+ int *charNumber)
+{
+ if (line < newLines.count()) {
+ const QString text = newLines.at(line);
+ if (lines->isEmpty() || line > 0) {
+ if (line > 0)
+ ++*lineNumber;
+ lines->append(text);
+ } else {
+ lines->last() += text;
+ }
+ *charNumber += text.count();
+ }
+}
+
+static void handleDifference(const QString &text,
+ QStringList *lines,
+ QMap<int, int> *changedPositions,
+ int *lineNumber,
+ int *charNumber)
+{
+ const int oldPosition = *lineNumber + *charNumber;
+ const QStringList newLeftLines = text.split(QLatin1Char('\n'));
+ for (int line = 0; line < newLeftLines.count(); ++line)
+ handleLine(newLeftLines, line, lines, lineNumber, charNumber);
+ const int newPosition = *lineNumber + *charNumber;
+ changedPositions->insert(oldPosition, newPosition);
+}
+
+/*
+ * leftDiffList can contain only deletions and equalities,
+ * while rightDiffList can contain only insertions and equalities.
+ * The number of equalities on both lists must be the same.
+*/
+ChunkData calculateOriginalData(const QList<Diff> &leftDiffList,
+ const QList<Diff> &rightDiffList)
+{
+ ChunkData chunkData;
+
+ int i = 0;
+ int j = 0;
+
+ QStringList leftLines;
+ QStringList rightLines;
+
+ // <line number, span count>
+ QMap<int, int> leftSpans;
+ QMap<int, int> rightSpans;
+ // <left line number, right line number>
+ QMap<int, int> equalLines;
+
+ int leftLineNumber = 0;
+ int rightLineNumber = 0;
+ int leftCharNumber = 0;
+ int rightCharNumber = 0;
+ int leftLineAligned = -1;
+ int rightLineAligned = -1;
+ bool lastLineEqual = true;
+
+ while (i <= leftDiffList.count() && j <= rightDiffList.count()) {
+ const Diff leftDiff = i < leftDiffList.count()
+ ? leftDiffList.at(i)
+ : Diff(Diff::Equal);
+ const Diff rightDiff = j < rightDiffList.count()
+ ? rightDiffList.at(j)
+ : Diff(Diff::Equal);
+
+ if (leftDiff.command == Diff::Delete) {
+ // process delete
+ handleDifference(leftDiff.text, &leftLines, &chunkData.changedLeftPositions, &leftLineNumber, &leftCharNumber);
+ lastLineEqual = lastLinesEqual(leftLines, rightLines);
+ i++;
+ }
+ if (rightDiff.command == Diff::Insert) {
+ // process insert
+ handleDifference(rightDiff.text, &rightLines, &chunkData.changedRightPositions, &rightLineNumber, &rightCharNumber);
+ lastLineEqual = lastLinesEqual(leftLines, rightLines);
+ j++;
+ }
+ if (leftDiff.command == Diff::Equal && rightDiff.command == Diff::Equal) {
+ // process equal
+ const QStringList newLeftLines = leftDiff.text.split(QLatin1Char('\n'));
+ const QStringList newRightLines = rightDiff.text.split(QLatin1Char('\n'));
+
+ int line = 0;
+
+ while (line < qMax(newLeftLines.count(), newRightLines.count())) {
+ handleLine(newLeftLines, line, &leftLines, &leftLineNumber, &leftCharNumber);
+ handleLine(newRightLines, line, &rightLines, &rightLineNumber, &rightCharNumber);
+
+ const int commonLineCount = qMin(newLeftLines.count(), newRightLines.count());
+ if (line < commonLineCount) {
+ // try to align
+ const int leftDifference = leftLineNumber - leftLineAligned;
+ const int rightDifference = rightLineNumber - rightLineAligned;
+
+ if (leftDifference && rightDifference) {
+ bool doAlign = true;
+ if (line == 0 // omit alignment when first lines of equalities are empty
+ && (newLeftLines.at(0).isEmpty() || newRightLines.at(0).isEmpty())) {
+ doAlign = false;
+ }
+
+ if (line == commonLineCount - 1) {
+ // omit alignment when last lines of equalities are empty
+ if (leftLines.last().isEmpty() || rightLines.last().isEmpty())
+ doAlign = false;
+
+ // unless it's the last dummy line (don't omit in that case)
+ if (i == leftDiffList.count() && j == rightDiffList.count())
+ doAlign = true;
+ }
+
+ if (doAlign) {
+ // align here
+ leftLineAligned = leftLineNumber;
+ rightLineAligned = rightLineNumber;
+
+ // insert separators if needed
+ if (rightDifference > leftDifference)
+ leftSpans.insert(leftLineNumber, rightDifference - leftDifference);
+ else if (leftDifference > rightDifference)
+ rightSpans.insert(rightLineNumber, leftDifference - rightDifference);
+ }
+ }
+ }
+
+ // check if lines are equal
+ if ((line < commonLineCount - 1) // before the last common line in equality
+ || (line == commonLineCount - 1 // or the last common line in equality
+ && i == leftDiffList.count() // and it's the last iteration
+ && j == rightDiffList.count())) {
+ if (line > 0 || lastLineEqual)
+ equalLines.insert(leftLineNumber, rightLineNumber);
+ }
+
+ if (line > 0)
+ lastLineEqual = true;
+
+ line++;
+ }
+ i++;
+ j++;
+ }
+ }
+
+ QList<TextLineData> leftData = assemblyRows(leftLines,
+ leftSpans);
+ QList<TextLineData> rightData = assemblyRows(rightLines,
+ rightSpans);
+
+ // fill ending separators
+ for (int i = leftData.count(); i < rightData.count(); i++)
+ leftData.append(TextLineData(TextLineData::Separator));
+ for (int i = rightData.count(); i < leftData.count(); i++)
+ rightData.append(TextLineData(TextLineData::Separator));
+
+ const int visualLineCount = leftData.count();
+ int leftLine = -1;
+ int rightLine = -1;
+ for (int i = 0; i < visualLineCount; i++) {
+ const TextLineData &leftTextLine = leftData.at(i);
+ const TextLineData &rightTextLine = rightData.at(i);
+ RowData row(leftTextLine, rightTextLine);
+
+ if (leftTextLine.textLineType == TextLineData::TextLine)
+ ++leftLine;
+ if (rightTextLine.textLineType == TextLineData::TextLine)
+ ++rightLine;
+ if (equalLines.value(leftLine, -1) == rightLine)
+ row.equal = true;
+
+ chunkData.rows.append(row);
+ }
+ return chunkData;
+}
+
+FileData calculateContextData(const ChunkData &originalData, int contextLinesNumber)
+{
+ if (contextLinesNumber < 0)
+ return FileData(originalData);
+
+ const int joinChunkThreshold = 1;
+
+ FileData fileData;
+ QMap<int, bool> hiddenRows;
+ int i = 0;
+ while (i < originalData.rows.count()) {
+ const RowData &row = originalData.rows[i];
+ if (row.equal) {
+ // count how many equal
+ int equalRowStart = i;
+ i++;
+ while (i < originalData.rows.count()) {
+ const RowData originalRow = originalData.rows.at(i);
+ if (!originalRow.equal)
+ break;
+ i++;
+ }
+ const bool first = equalRowStart == 0; // includes first line?
+ const bool last = i == originalData.rows.count(); // includes last line?
+
+ const int firstLine = first ? 0 : equalRowStart + contextLinesNumber;
+ const int lastLine = last ? originalData.rows.count() : i - contextLinesNumber;
+
+ if (firstLine < lastLine - joinChunkThreshold) {
+ for (int j = firstLine; j < lastLine; j++) {
+ hiddenRows.insert(j, true);
+ }
+ }
+ } else {
+ // iterate to the next row
+ i++;
+ }
+ }
+ i = 0;
+ int leftCharCounter = 0;
+ int rightCharCounter = 0;
+ QMap<int, int>::ConstIterator leftChangedIt = originalData.changedLeftPositions.constBegin();
+ QMap<int, int>::ConstIterator rightChangedIt = originalData.changedRightPositions.constBegin();
+ const QMap<int, int>::ConstIterator leftChangedItEnd = originalData.changedLeftPositions.constEnd();
+ const QMap<int, int>::ConstIterator rightChangedItEnd = originalData.changedRightPositions.constEnd();
+ while (i < originalData.rows.count()) {
+ if (!hiddenRows.contains(i)) {
+ ChunkData chunkData;
+ int leftOffset = leftCharCounter;
+ int rightOffset = rightCharCounter;
+ chunkData.contextChunk = false;
+ while (i < originalData.rows.count()) {
+ if (hiddenRows.contains(i))
+ break;
+ RowData rowData = originalData.rows.at(i);
+ chunkData.rows.append(rowData);
+
+ if (rowData.leftLine.textLineType == TextLineData::TextLine)
+ leftCharCounter += rowData.leftLine.text.count() + 1; // +1 for '\n'
+ if (rowData.rightLine.textLineType == TextLineData::TextLine)
+ rightCharCounter += rowData.rightLine.text.count() + 1; // +1 for '\n'
+ i++;
+ }
+ while (leftChangedIt != leftChangedItEnd) {
+ if (leftChangedIt.key() < leftOffset
+ || leftChangedIt.key() > leftCharCounter)
+ break;
+
+ const int startPos = leftChangedIt.key();
+ const int endPos = leftChangedIt.value();
+ chunkData.changedLeftPositions.insert(startPos - leftOffset, endPos - leftOffset);
+ leftChangedIt++;
+ }
+ while (rightChangedIt != rightChangedItEnd) {
+ if (rightChangedIt.key() < rightOffset
+ || rightChangedIt.key() > rightCharCounter)
+ break;
+
+ const int startPos = rightChangedIt.key();
+ const int endPos = rightChangedIt.value();
+ chunkData.changedRightPositions.insert(startPos - rightOffset, endPos - rightOffset);
+ rightChangedIt++;
+ }
+ fileData.chunks.append(chunkData);
+ } else {
+ ChunkData chunkData;
+ chunkData.contextChunk = true;
+ while (i < originalData.rows.count()) {
+ if (!hiddenRows.contains(i))
+ break;
+ RowData rowData = originalData.rows.at(i);
+ chunkData.rows.append(rowData);
+
+ if (rowData.leftLine.textLineType == TextLineData::TextLine)
+ leftCharCounter += rowData.leftLine.text.count() + 1; // +1 for '\n'
+ if (rowData.rightLine.textLineType == TextLineData::TextLine)
+ rightCharCounter += rowData.rightLine.text.count() + 1; // +1 for '\n'
+ i++;
+ }
+ fileData.chunks.append(chunkData);
+ }
+ }
+ return fileData;
+}
+
+} // namespace Internal
+} // namespace DiffEditor
diff --git a/src/plugins/diffeditor/diffutils.h b/src/plugins/diffeditor/diffutils.h
new file mode 100644
index 0000000000..5d252d7eb8
--- /dev/null
+++ b/src/plugins/diffeditor/diffutils.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef DIFFUTILS_H
+#define DIFFUTILS_H
+
+#include <QString>
+#include <QMap>
+#include "diffeditorcontroller.h"
+
+namespace DiffEditor {
+
+class Diff;
+
+namespace Internal {
+
+class TextLineData {
+public:
+ enum TextLineType {
+ TextLine,
+ Separator,
+ Invalid
+ };
+ TextLineData() : textLineType(Invalid) {}
+ TextLineData(const QString &txt) : textLineType(TextLine), text(txt) {}
+ TextLineData(TextLineType t) : textLineType(t) {}
+ TextLineType textLineType;
+ QString text;
+};
+
+class RowData {
+public:
+ RowData() : equal(false) {}
+ RowData(const TextLineData &l)
+ : leftLine(l), rightLine(l), equal(true) {}
+ RowData(const TextLineData &l, const TextLineData &r)
+ : leftLine(l), rightLine(r), equal(false) {}
+ TextLineData leftLine;
+ TextLineData rightLine;
+ bool equal;
+};
+
+class ChunkData {
+public:
+ ChunkData() : contextChunk(false) {}
+ QList<RowData> rows;
+ bool contextChunk;
+ // start position, end position, TextLineData::Separator lines not taken into account
+ QMap<int, int> changedLeftPositions; // counting from the beginning of the chunk
+ QMap<int, int> changedRightPositions; // counting from the beginning of the chunk
+};
+
+class FileData {
+public:
+ FileData() {}
+ FileData(const ChunkData &chunkData) { chunks.append(chunkData); }
+ QList<ChunkData> chunks;
+ DiffEditorController::DiffFileInfo leftFileInfo;
+ DiffEditorController::DiffFileInfo rightFileInfo;
+};
+
+ChunkData calculateOriginalData(const QList<Diff> &leftDiffList,
+ const QList<Diff> &rightDiffList);
+FileData calculateContextData(const ChunkData &originalData,
+ int contextLinesNumber);
+
+} // namespace Internal
+} // namespace DiffEditor
+
+#endif // DIFFUTILS_H
diff --git a/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp b/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp
index e64fb83c59..b6d62df7e1 100644
--- a/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp
+++ b/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp
@@ -29,6 +29,7 @@
#include "sidebysidediffeditorwidget.h"
#include "diffeditorguicontroller.h"
+#include "diffutils.h"
#include <QPlainTextEdit>
#include <QVBoxLayout>
@@ -66,260 +67,7 @@ using namespace TextEditor;
namespace DiffEditor {
-class TextLineData {
-public:
- enum TextLineType {
- TextLine,
- Separator,
- Invalid
- };
- TextLineData() : textLineType(Invalid) {}
- TextLineData(const QString &txt) : textLineType(TextLine), text(txt) {}
- TextLineData(TextLineType t) : textLineType(t) {}
- TextLineType textLineType;
- QString text;
-};
-
-class RowData {
-public:
- RowData() : equal(false) {}
- RowData(const TextLineData &l)
- : leftLine(l), rightLine(l), equal(true) {}
- RowData(const TextLineData &l, const TextLineData &r)
- : leftLine(l), rightLine(r), equal(false) {}
- TextLineData leftLine;
- TextLineData rightLine;
- bool equal;
-};
-
-class ChunkData {
-public:
- ChunkData() : contextChunk(false) {}
- QList<RowData> rows;
- bool contextChunk;
- // start position, end position, TextLineData::Separator lines not taken into account
- QMap<int, int> changedLeftPositions; // counting from the beginning of the chunk
- QMap<int, int> changedRightPositions; // counting from the beginning of the chunk
-};
-
-class FileData {
-public:
- FileData() {}
- FileData(const ChunkData &chunkData) { chunks.append(chunkData); }
- QList<ChunkData> chunks;
- DiffEditorController::DiffFileInfo leftFileInfo;
- DiffEditorController::DiffFileInfo rightFileInfo;
-};
-
-//////////////////////
-
-static QList<TextLineData> assemblyRows(const QStringList &lines,
- const QMap<int, int> &lineSpans)
-{
- QList<TextLineData> data;
-
- const int lineCount = lines.count();
- for (int i = 0; i <= lineCount; i++) {
- for (int j = 0; j < lineSpans.value(i); j++)
- data.append(TextLineData(TextLineData::Separator));
- if (i < lineCount)
- data.append(lines.at(i));
- }
- return data;
-}
-
-static void handleLine(const QStringList &newLines,
- int line,
- QStringList *lines,
- int *lineNumber,
- int *charNumber)
-{
- if (line < newLines.count()) {
- const QString text = newLines.at(line);
- if (lines->isEmpty() || line > 0) {
- if (line > 0)
- ++*lineNumber;
- lines->append(text);
- } else {
- lines->last() += text;
- }
- *charNumber += text.count();
- }
-}
-
-static void handleDifference(const QString &text,
- QStringList *lines,
- QMap<int, int> *changedPositions,
- int *lineNumber,
- int *charNumber)
-{
- const int oldPosition = *lineNumber + *charNumber;
- const QStringList newLeftLines = text.split(QLatin1Char('\n'));
- for (int line = 0; line < newLeftLines.count(); ++line)
- handleLine(newLeftLines, line, lines, lineNumber, charNumber);
- const int newPosition = *lineNumber + *charNumber;
- changedPositions->insert(oldPosition, newPosition);
-}
-
-static bool lastLinesEqual(const QStringList &leftLines,
- const QStringList &rightLines)
-{
- const bool leftLineEqual = leftLines.count()
- ? leftLines.last().isEmpty()
- : true;
- const bool rightLineEqual = rightLines.count()
- ? rightLines.last().isEmpty()
- : true;
- return leftLineEqual && rightLineEqual;
-}
-
-/*
- * leftDiffList can contain only deletions and equalities,
- * while rightDiffList can contain only insertions and equalities.
- * The number of equalities on both lists must be the same.
-*/
-static ChunkData calculateOriginalData(const QList<Diff> &leftDiffList,
- const QList<Diff> &rightDiffList)
-{
- ChunkData chunkData;
-
- int i = 0;
- int j = 0;
-
- QStringList leftLines;
- QStringList rightLines;
-
- // <line number, span count>
- QMap<int, int> leftSpans;
- QMap<int, int> rightSpans;
- // <left line number, right line number>
- QMap<int, int> equalLines;
-
- int leftLineNumber = 0;
- int rightLineNumber = 0;
- int leftCharNumber = 0;
- int rightCharNumber = 0;
- int leftLineAligned = -1;
- int rightLineAligned = -1;
- bool lastLineEqual = true;
-
- while (i <= leftDiffList.count() && j <= rightDiffList.count()) {
- const Diff leftDiff = i < leftDiffList.count()
- ? leftDiffList.at(i)
- : Diff(Diff::Equal);
- const Diff rightDiff = j < rightDiffList.count()
- ? rightDiffList.at(j)
- : Diff(Diff::Equal);
-
- if (leftDiff.command == Diff::Delete) {
- // process delete
- handleDifference(leftDiff.text, &leftLines, &chunkData.changedLeftPositions, &leftLineNumber, &leftCharNumber);
- lastLineEqual = lastLinesEqual(leftLines, rightLines);
- i++;
- }
- if (rightDiff.command == Diff::Insert) {
- // process insert
- handleDifference(rightDiff.text, &rightLines, &chunkData.changedRightPositions, &rightLineNumber, &rightCharNumber);
- lastLineEqual = lastLinesEqual(leftLines, rightLines);
- j++;
- }
- if (leftDiff.command == Diff::Equal && rightDiff.command == Diff::Equal) {
- // process equal
- const QStringList newLeftLines = leftDiff.text.split(QLatin1Char('\n'));
- const QStringList newRightLines = rightDiff.text.split(QLatin1Char('\n'));
-
- int line = 0;
-
- while (line < qMax(newLeftLines.count(), newRightLines.count())) {
- handleLine(newLeftLines, line, &leftLines, &leftLineNumber, &leftCharNumber);
- handleLine(newRightLines, line, &rightLines, &rightLineNumber, &rightCharNumber);
-
- const int commonLineCount = qMin(newLeftLines.count(), newRightLines.count());
- if (line < commonLineCount) {
- // try to align
- const int leftDifference = leftLineNumber - leftLineAligned;
- const int rightDifference = rightLineNumber - rightLineAligned;
-
- if (leftDifference && rightDifference) {
- bool doAlign = true;
- if (line == 0 // omit alignment when first lines of equalities are empty
- && (newLeftLines.at(0).isEmpty() || newRightLines.at(0).isEmpty())) {
- doAlign = false;
- }
-
- if (line == commonLineCount - 1) {
- // omit alignment when last lines of equalities are empty
- if (leftLines.last().isEmpty() || rightLines.last().isEmpty())
- doAlign = false;
-
- // unless it's the last dummy line (don't omit in that case)
- if (i == leftDiffList.count() && j == rightDiffList.count())
- doAlign = true;
- }
-
- if (doAlign) {
- // align here
- leftLineAligned = leftLineNumber;
- rightLineAligned = rightLineNumber;
-
- // insert separators if needed
- if (rightDifference > leftDifference)
- leftSpans.insert(leftLineNumber, rightDifference - leftDifference);
- else if (leftDifference > rightDifference)
- rightSpans.insert(rightLineNumber, leftDifference - rightDifference);
- }
- }
- }
-
- // check if lines are equal
- if ((line < commonLineCount - 1) // before the last common line in equality
- || (line == commonLineCount - 1 // or the last common line in equality
- && i == leftDiffList.count() // and it's the last iteration
- && j == rightDiffList.count())) {
- if (line > 0 || lastLineEqual)
- equalLines.insert(leftLineNumber, rightLineNumber);
- }
-
- if (line > 0)
- lastLineEqual = true;
-
- line++;
- }
- i++;
- j++;
- }
- }
-
- QList<TextLineData> leftData = assemblyRows(leftLines,
- leftSpans);
- QList<TextLineData> rightData = assemblyRows(rightLines,
- rightSpans);
-
- // fill ending separators
- for (int i = leftData.count(); i < rightData.count(); i++)
- leftData.append(TextLineData(TextLineData::Separator));
- for (int i = rightData.count(); i < leftData.count(); i++)
- rightData.append(TextLineData(TextLineData::Separator));
-
- const int visualLineCount = leftData.count();
- int leftLine = -1;
- int rightLine = -1;
- for (int i = 0; i < visualLineCount; i++) {
- const TextLineData &leftTextLine = leftData.at(i);
- const TextLineData &rightTextLine = rightData.at(i);
- RowData row(leftTextLine, rightTextLine);
-
- if (leftTextLine.textLineType == TextLineData::TextLine)
- ++leftLine;
- if (rightTextLine.textLineType == TextLineData::TextLine)
- ++rightLine;
- if (equalLines.value(leftLine, -1) == rightLine)
- row.equal = true;
-
- chunkData.rows.append(row);
- }
- return chunkData;
-}
+using namespace Internal;
//////////////////////
@@ -1076,6 +824,7 @@ void SideBySideDiffEditorWidget::setDiff(const QList<DiffList> &diffList)
m_diffList = diffList;
m_originalChunkData.clear();
m_contextFileData.clear();
+ const int contextLinesNumber = m_guiController ? m_guiController->contextLinesNumber() : 3;
for (int i = 0; i < m_diffList.count(); i++) {
const DiffList &dl = m_diffList.at(i);
@@ -1084,7 +833,7 @@ void SideBySideDiffEditorWidget::setDiff(const QList<DiffList> &diffList)
handleWhitespaces(dl.diffList, &leftDiffs, &rightDiffs);
ChunkData chunkData = calculateOriginalData(leftDiffs, rightDiffs);
m_originalChunkData.append(chunkData);
- FileData fileData = calculateContextData(chunkData);
+ FileData fileData = calculateContextData(chunkData, contextLinesNumber);
fileData.leftFileInfo = dl.leftFileInfo;
fileData.rightFileInfo = dl.rightFileInfo;
m_contextFileData.append(fileData);
@@ -1110,10 +859,11 @@ void SideBySideDiffEditorWidget::handleWhitespaces(const QList<Diff> &input,
void SideBySideDiffEditorWidget::setContextLinesNumber(int lines)
{
Q_UNUSED(lines)
+ const int contextLinesNumber = m_guiController ? m_guiController->contextLinesNumber() : 3;
for (int i = 0; i < m_contextFileData.count(); i++) {
const FileData oldFileData = m_contextFileData.at(i);
- FileData newFileData = calculateContextData(m_originalChunkData.at(i));
+ FileData newFileData = calculateContextData(m_originalChunkData.at(i), contextLinesNumber);
newFileData.leftFileInfo = oldFileData.leftFileInfo;
newFileData.rightFileInfo = oldFileData.rightFileInfo;
m_contextFileData[i] = newFileData;
@@ -1147,112 +897,6 @@ void SideBySideDiffEditorWidget::setCurrentDiffFileIndex(int diffFileIndex)
m_rightEditor->centerCursor();
}
-FileData SideBySideDiffEditorWidget::calculateContextData(const ChunkData &originalData) const
-{
- const int contextLinesNumber = m_guiController ? m_guiController->contextLinesNumber() : 3;
- if (contextLinesNumber < 0)
- return FileData(originalData);
-
- const int joinChunkThreshold = 1;
-
- FileData fileData;
- QMap<int, bool> hiddenRows;
- int i = 0;
- while (i < originalData.rows.count()) {
- const RowData &row = originalData.rows[i];
- if (row.equal) {
- // count how many equal
- int equalRowStart = i;
- i++;
- while (i < originalData.rows.count()) {
- const RowData originalRow = originalData.rows.at(i);
- if (!originalRow.equal)
- break;
- i++;
- }
- const bool first = equalRowStart == 0; // includes first line?
- const bool last = i == originalData.rows.count(); // includes last line?
-
- const int firstLine = first ? 0 : equalRowStart + contextLinesNumber;
- const int lastLine = last ? originalData.rows.count() : i - contextLinesNumber;
-
- if (firstLine < lastLine - joinChunkThreshold) {
- for (int j = firstLine; j < lastLine; j++) {
- hiddenRows.insert(j, true);
- }
- }
- } else {
- // iterate to the next row
- i++;
- }
- }
- i = 0;
- int leftCharCounter = 0;
- int rightCharCounter = 0;
- QMap<int, int>::ConstIterator leftChangedIt = originalData.changedLeftPositions.constBegin();
- QMap<int, int>::ConstIterator rightChangedIt = originalData.changedRightPositions.constBegin();
- const QMap<int, int>::ConstIterator leftChangedItEnd = originalData.changedLeftPositions.constEnd();
- const QMap<int, int>::ConstIterator rightChangedItEnd = originalData.changedRightPositions.constEnd();
- while (i < originalData.rows.count()) {
- if (!hiddenRows.contains(i)) {
- ChunkData chunkData;
- int leftOffset = leftCharCounter;
- int rightOffset = rightCharCounter;
- chunkData.contextChunk = false;
- while (i < originalData.rows.count()) {
- if (hiddenRows.contains(i))
- break;
- RowData rowData = originalData.rows.at(i);
- chunkData.rows.append(rowData);
-
- if (rowData.leftLine.textLineType == TextLineData::TextLine)
- leftCharCounter += rowData.leftLine.text.count() + 1; // +1 for '\n'
- if (rowData.rightLine.textLineType == TextLineData::TextLine)
- rightCharCounter += rowData.rightLine.text.count() + 1; // +1 for '\n'
- i++;
- }
- while (leftChangedIt != leftChangedItEnd) {
- if (leftChangedIt.key() < leftOffset
- || leftChangedIt.key() > leftCharCounter)
- break;
-
- const int startPos = leftChangedIt.key();
- const int endPos = leftChangedIt.value();
- chunkData.changedLeftPositions.insert(startPos - leftOffset, endPos - leftOffset);
- leftChangedIt++;
- }
- while (rightChangedIt != rightChangedItEnd) {
- if (rightChangedIt.key() < rightOffset
- || rightChangedIt.key() > rightCharCounter)
- break;
-
- const int startPos = rightChangedIt.key();
- const int endPos = rightChangedIt.value();
- chunkData.changedRightPositions.insert(startPos - rightOffset, endPos - rightOffset);
- rightChangedIt++;
- }
- fileData.chunks.append(chunkData);
- } else {
- ChunkData chunkData;
- chunkData.contextChunk = true;
- while (i < originalData.rows.count()) {
- if (!hiddenRows.contains(i))
- break;
- RowData rowData = originalData.rows.at(i);
- chunkData.rows.append(rowData);
-
- if (rowData.leftLine.textLineType == TextLineData::TextLine)
- leftCharCounter += rowData.leftLine.text.count() + 1; // +1 for '\n'
- if (rowData.rightLine.textLineType == TextLineData::TextLine)
- rightCharCounter += rowData.rightLine.text.count() + 1; // +1 for '\n'
- i++;
- }
- fileData.chunks.append(chunkData);
- }
- }
- return fileData;
-}
-
void SideBySideDiffEditorWidget::showDiff()
{
// TODO: remember the line number of the line in the middle
diff --git a/src/plugins/diffeditor/sidebysidediffeditorwidget.h b/src/plugins/diffeditor/sidebysidediffeditorwidget.h
index cf7cbbd884..ae05759957 100644
--- a/src/plugins/diffeditor/sidebysidediffeditorwidget.h
+++ b/src/plugins/diffeditor/sidebysidediffeditorwidget.h
@@ -46,11 +46,13 @@ QT_END_NAMESPACE
namespace DiffEditor {
-
class DiffEditorGuiController;
class SideDiffEditorWidget;
+
+namespace Internal {
class ChunkData;
class FileData;
+}
class DIFFEDITOR_EXPORT SideBySideDiffEditorWidget : public QWidget
{
@@ -101,8 +103,7 @@ private:
QList<QTextEdit::ExtraSelection> colorPositions(const QTextCharFormat &format,
QTextCursor &cursor,
const QMap<int, int> &positions) const;
- void colorDiff(const QList<FileData> &fileDataList);
- FileData calculateContextData(const ChunkData &originalData) const;
+ void colorDiff(const QList<Internal::FileData> &fileDataList);
void showDiff();
void synchronizeFoldings(SideDiffEditorWidget *source, SideDiffEditorWidget *destination);
void jumpToOriginalFile(const QString &fileName, int lineNumber, int columnNumber);
@@ -114,8 +115,8 @@ private:
QSplitter *m_splitter;
QList<DiffList> m_diffList; // list of original outputs from differ
- QList<ChunkData> m_originalChunkData; // one big chunk for every file, ignoreWhitespace taken into account
- QList<FileData> m_contextFileData; // ultimate data to be shown, contextLinesNumber taken into account
+ QList<Internal::ChunkData> m_originalChunkData; // one big chunk for every file, ignoreWhitespace taken into account
+ QList<Internal::FileData> m_contextFileData; // ultimate data to be shown, contextLinesNumber taken into account
bool m_foldingBlocker;
QString m_source;