diff options
author | jkobus <jaroslaw.kobus@digia.com> | 2014-02-28 10:40:20 +0100 |
---|---|---|
committer | Jarek Kobus <jaroslaw.kobus@digia.com> | 2014-02-28 10:42:50 +0100 |
commit | a746f6fb27720926ab37273b824c6a4c77ef0fd2 (patch) | |
tree | 793aee6bf8dab6ec83441a921d1452b41a1b61aa /src/plugins/diffeditor | |
parent | c09e80b8538cf072185a076b4aaf46ed51186bda (diff) | |
download | qt-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.pro | 2 | ||||
-rw-r--r-- | src/plugins/diffeditor/diffeditor.qbs | 2 | ||||
-rw-r--r-- | src/plugins/diffeditor/diffutils.cpp | 351 | ||||
-rw-r--r-- | src/plugins/diffeditor/diffutils.h | 96 | ||||
-rw-r--r-- | src/plugins/diffeditor/sidebysidediffeditorwidget.cpp | 368 | ||||
-rw-r--r-- | src/plugins/diffeditor/sidebysidediffeditorwidget.h | 11 |
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; |