Add file descriptions, enable file folding

Change-Id: Ie90ac9fb74e9c4b8cfba16d065d1b8751125e83c
Reviewed-by: David Schulz <david.schulz@digia.com>
This commit is contained in:
jkobus
2013-04-25 17:37:20 +02:00
committed by Jarek Kobus
parent 325c0beda5
commit e844bee1da
5 changed files with 468 additions and 209 deletions

View File

@@ -328,7 +328,15 @@ void DiffEditorPlugin::diff()
const QString text1 = getFileContents(fileName1, editorWidget->codec()); const QString text1 = getFileContents(fileName1, editorWidget->codec());
const QString text2 = getFileContents(fileName2, editorWidget->codec()); const QString text2 = getFileContents(fileName2, editorWidget->codec());
editorWidget->setDiff(text1, text2); DiffEditorWidget::DiffFilesContents dfc;
dfc.leftFileName = fileName1;
dfc.leftText = text1;
dfc.rightFileName = fileName2;
dfc.rightText = text2;
QList<DiffEditorWidget::DiffFilesContents> list;
list.append(dfc);
editorWidget->setDiff(list);
} }
} }

View File

@@ -46,6 +46,10 @@
#include <texteditor/basetextdocument.h> #include <texteditor/basetextdocument.h>
#include <texteditor/texteditorsettings.h> #include <texteditor/texteditorsettings.h>
static const int BASE_LEVEL = 0;
static const int FILE_LEVEL = 1;
static const int CHUNK_LEVEL = 2;
using namespace TextEditor; using namespace TextEditor;
namespace DiffEditor { namespace DiffEditor {
@@ -83,11 +87,12 @@ public:
QMap<int, int> skippedLines() const { return m_skippedLines; } QMap<int, int> skippedLines() const { return m_skippedLines; }
void setLineNumber(int blockNumber, const QString &lineNumber); void setLineNumber(int blockNumber, const QString &lineNumber);
void setSkippedLines(int blockNumber, int skippedLines) { m_skippedLines[blockNumber] = skippedLines; } void setFileName(int blockNumber, const QString &fileName) { m_fileNames[blockNumber] = fileName; setSeparator(blockNumber, true); }
void setSkippedLines(int blockNumber, int skippedLines) { m_skippedLines[blockNumber] = skippedLines; setSeparator(blockNumber, true); }
void setSeparator(int blockNumber, bool separator) { m_separators[blockNumber] = separator; } void setSeparator(int blockNumber, bool separator) { m_separators[blockNumber] = separator; }
void clearLineNumbers(); bool isFileLine(int blockNumber) const { return m_fileNames.contains(blockNumber); }
void clearSkippedLines() { m_skippedLines.clear(); } bool isChunkLine(int blockNumber) const { return m_skippedLines.contains(blockNumber); }
void clearSeparators() { m_separators.clear(); } void clearAllData();
QTextBlock firstVisibleBlock() const { return SnippetEditorWidget::firstVisibleBlock(); } QTextBlock firstVisibleBlock() const { return SnippetEditorWidget::firstVisibleBlock(); }
protected: protected:
@@ -97,21 +102,31 @@ protected:
virtual int lineNumberDigits() const; virtual int lineNumberDigits() const;
virtual bool selectionVisible(int blockNumber) const; virtual bool selectionVisible(int blockNumber) const;
virtual bool replacementVisible(int blockNumber) const; virtual bool replacementVisible(int blockNumber) const;
QString plainTextFromSelection(const QTextCursor &cursor) const; virtual QString plainTextFromSelection(const QTextCursor &cursor) const;
virtual void drawCollapsedBlockPopup(QPainter &painter,
const QTextBlock &block,
QPointF offset,
const QRect &clip);
virtual void paintEvent(QPaintEvent *e); virtual void paintEvent(QPaintEvent *e);
virtual void scrollContentsBy(int dx, int dy); virtual void scrollContentsBy(int dx, int dy);
private: private:
void paintCollapsedBlockPopup(QPainter &painter, const QRect &clipRect);
void paintSeparator(QPainter &painter, const QString &text, const QTextBlock &block, int top);
QMap<int, QString> m_lineNumbers; QMap<int, QString> m_lineNumbers;
int m_lineNumberDigits; int m_lineNumberDigits;
// block number, fileName
QMap<int, QString> m_fileNames;
// block number, skipped lines // block number, skipped lines
QMap<int, int> m_skippedLines; QMap<int, int> m_skippedLines;
// block number, separator. Separator used as lines alignment and inside skipped lines // block number, separator. Separator used as lines alignment and inside skipped lines
QMap<int, bool> m_separators; QMap<int, bool> m_separators;
bool m_inPaintEvent;
}; };
DiffViewEditorWidget::DiffViewEditorWidget(QWidget *parent) DiffViewEditorWidget::DiffViewEditorWidget(QWidget *parent)
: SnippetEditorWidget(parent), m_lineNumberDigits(1) : SnippetEditorWidget(parent), m_lineNumberDigits(1), m_inPaintEvent(false)
{ {
setLineNumbersVisible(true); setLineNumbersVisible(true);
setCodeFoldingSupported(true); setCodeFoldingSupported(true);
@@ -135,7 +150,8 @@ bool DiffViewEditorWidget::selectionVisible(int blockNumber) const
bool DiffViewEditorWidget::replacementVisible(int blockNumber) const bool DiffViewEditorWidget::replacementVisible(int blockNumber) const
{ {
return m_skippedLines.value(blockNumber); return isChunkLine(blockNumber) || (isFileLine(blockNumber)
&& TextEditor::BaseTextDocumentLayout::isFolded(document()->findBlockByNumber(blockNumber)));
} }
QString DiffViewEditorWidget::plainTextFromSelection(const QTextCursor &cursor) const QString DiffViewEditorWidget::plainTextFromSelection(const QTextCursor &cursor) const
@@ -179,10 +195,13 @@ void DiffViewEditorWidget::setLineNumber(int blockNumber, const QString &lineNum
m_lineNumberDigits = qMax(m_lineNumberDigits, lineNumber.count()); m_lineNumberDigits = qMax(m_lineNumberDigits, lineNumber.count());
} }
void DiffViewEditorWidget::clearLineNumbers() void DiffViewEditorWidget::clearAllData()
{ {
m_lineNumbers.clear();
m_lineNumberDigits = 1; m_lineNumberDigits = 1;
m_lineNumbers.clear();
m_fileNames.clear();
m_skippedLines.clear();
m_separators.clear();
} }
void DiffViewEditorWidget::scrollContentsBy(int dx, int dy) void DiffViewEditorWidget::scrollContentsBy(int dx, int dy)
@@ -192,17 +211,43 @@ void DiffViewEditorWidget::scrollContentsBy(int dx, int dy)
viewport()->update(); viewport()->update();
} }
void DiffViewEditorWidget::paintSeparator(QPainter &painter, const QString &text, const QTextBlock &block, int top)
{
QPointF offset = contentOffset();
painter.save();
painter.setPen(palette().foreground().color());
const QString replacementText = QLatin1String(" {")
+ foldReplacementText(block)
+ QLatin1String("}; ");
const int replacementTextWidth = fontMetrics().width(replacementText) + 24;
int x = replacementTextWidth + offset.x();
if (x < document()->documentMargin() || !TextEditor::BaseTextDocumentLayout::isFolded(block))
x = document()->documentMargin();
const QString elidedText = fontMetrics().elidedText(text,
Qt::ElideRight,
viewport()->width() - x);
QTextLayout *layout = block.layout();
QTextLine textLine = layout->lineAt(0);
QRectF lineRect = textLine.naturalTextRect().translated(offset.x(), top);
QRect clipRect = contentsRect();
clipRect.setLeft(x);
painter.setClipRect(clipRect);
painter.drawText(QPointF(x, lineRect.top() + textLine.ascent()),
elidedText);
painter.restore();
}
void DiffViewEditorWidget::paintEvent(QPaintEvent *e) void DiffViewEditorWidget::paintEvent(QPaintEvent *e)
{ {
m_inPaintEvent = true;
SnippetEditorWidget::paintEvent(e); SnippetEditorWidget::paintEvent(e);
m_inPaintEvent = false;
QPainter painter(viewport()); QPainter painter(viewport());
QPointF offset = contentOffset(); QPointF offset = contentOffset();
QTextBlock firstBlock = firstVisibleBlock(); QTextBlock firstBlock = firstVisibleBlock();
QTextBlock currentBlock = firstBlock; QTextBlock currentBlock = firstBlock;
QMap<int, int> skipped = skippedLines();
while (currentBlock.isValid()) { while (currentBlock.isValid()) {
if (currentBlock.isVisible()) { if (currentBlock.isVisible()) {
qreal top = blockBoundingGeometry(currentBlock).translated(offset).top(); qreal top = blockBoundingGeometry(currentBlock).translated(offset).top();
@@ -212,29 +257,126 @@ void DiffViewEditorWidget::paintEvent(QPaintEvent *e)
break; break;
if (bottom >= e->rect().top()) { if (bottom >= e->rect().top()) {
QTextLayout *layout = currentBlock.layout(); const int blockNumber = currentBlock.blockNumber();
int skippedBefore = skipped.value(currentBlock.blockNumber()); const int skippedBefore = m_skippedLines.value(blockNumber);
if (skippedBefore) { if (skippedBefore) {
painter.save(); const QString skippedRowsText = tr("Skipped %n lines...", 0, skippedBefore);
painter.setPen(palette().foreground().color()); paintSeparator(painter, skippedRowsText, currentBlock, top);
QTextLine textLine = layout->lineAt(0); }
QRectF lineRect = textLine.naturalTextRect().translated(0, top);
QString skippedRowsText = tr("Skipped %n lines...", 0, skippedBefore); const QString fileName = m_fileNames.value(blockNumber);
QFontMetrics fm(font()); if (!fileName.isEmpty()) {
const int textWidth = fm.width(skippedRowsText); paintSeparator(painter, fileName, currentBlock, top);
painter.drawText(QPointF(lineRect.right()
+ (viewport()->width() - textWidth) / 2.0,
lineRect.top() + textLine.ascent()),
skippedRowsText);
painter.restore();
} }
} }
} }
currentBlock = currentBlock.next(); currentBlock = currentBlock.next();
} }
paintCollapsedBlockPopup(painter, e->rect());
} }
void DiffViewEditorWidget::paintCollapsedBlockPopup(QPainter &painter, const QRect &clipRect)
{
QPointF offset(contentOffset());
QRect viewportRect = viewport()->rect();
QTextBlock block = firstVisibleBlock();
QTextBlock visibleCollapsedBlock;
QPointF visibleCollapsedBlockOffset;
while (block.isValid()) {
QRectF r = blockBoundingRect(block).translated(offset);
offset.ry() += r.height();
if (offset.y() > viewportRect.height())
break;
block = block.next();
if (!block.isVisible()) {
if (block.blockNumber() == visibleFoldedBlockNumber()) {
visibleCollapsedBlock = block;
visibleCollapsedBlockOffset = offset + QPointF(0,1);
break;
}
// invisible blocks do have zero line count
block = document()->findBlockByLineNumber(block.firstLineNumber());
}
}
if (visibleCollapsedBlock.isValid()) {
drawCollapsedBlockPopup(painter,
visibleCollapsedBlock,
visibleCollapsedBlockOffset,
clipRect);
}
}
void DiffViewEditorWidget::drawCollapsedBlockPopup(QPainter &painter,
const QTextBlock &block,
QPointF offset,
const QRect &clip)
{
// We ignore the call coming from the BaseTextEditorWidget::paintEvent()
// since we will draw it later, after custom drawings of this paintEvent.
// We need to draw it after our custom drawings, otherwise custom
// drawings will appear in front of block popup.
if (m_inPaintEvent)
return;
int margin = block.document()->documentMargin();
qreal maxWidth = 0;
qreal blockHeight = 0;
QTextBlock b = block;
while (!b.isVisible()) {
if (!m_separators.contains(b.blockNumber())) {
b.setVisible(true); // make sure block bounding rect works
QRectF r = blockBoundingRect(b).translated(offset);
QTextLayout *layout = b.layout();
for (int i = layout->lineCount()-1; i >= 0; --i)
maxWidth = qMax(maxWidth, layout->lineAt(i).naturalTextWidth() + 2*margin);
blockHeight += r.height();
b.setVisible(false); // restore previous state
b.setLineCount(0); // restore 0 line count for invisible block
}
b = b.next();
}
painter.save();
painter.setRenderHint(QPainter::Antialiasing, true);
painter.translate(.5, .5);
QBrush brush = palette().base();
painter.setBrush(brush);
painter.drawRoundedRect(QRectF(offset.x(),
offset.y(),
maxWidth, blockHeight).adjusted(0, 0, 0, 0), 3, 3);
painter.restore();
QTextBlock end = b;
b = block;
while (b != end) {
if (!m_separators.contains(b.blockNumber())) {
b.setVisible(true); // make sure block bounding rect works
QRectF r = blockBoundingRect(b).translated(offset);
QTextLayout *layout = b.layout();
QVector<QTextLayout::FormatRange> selections;
layout->draw(&painter, offset, selections, clip);
b.setVisible(false); // restore previous state
b.setLineCount(0); // restore 0 line count for invisible block
offset.ry() += r.height();
}
b = b.next();
}
}
////////////////// //////////////////
DiffEditorWidget::DiffEditorWidget(QWidget *parent) DiffEditorWidget::DiffEditorWidget(QWidget *parent)
@@ -287,25 +429,36 @@ DiffEditorWidget::~DiffEditorWidget()
} }
void DiffEditorWidget::setDiff(const QString &leftText, const QString &rightText) void DiffEditorWidget::setDiff(const QList<DiffFilesContents> &diffFileList)
{ {
// QTime time;
// time.start();
Differ differ; Differ differ;
QList<Diff> list = differ.cleanupSemantics(differ.diff(leftText, rightText)); QList<DiffList> diffList;
// int ela = time.elapsed(); for (int i = 0; i < diffFileList.count(); i++) {
// qDebug() << "Time spend in diff:" << ela; DiffFilesContents dfc = diffFileList.at(i);
setDiff(list); DiffList dl;
dl.leftFileName = dfc.leftFileName;
dl.rightFileName = dfc.rightFileName;
dl.diffList = differ.cleanupSemantics(differ.diff(dfc.leftText, dfc.rightText));
diffList.append(dl);
}
setDiff(diffList);
} }
void DiffEditorWidget::setDiff(const QList<Diff> &diffList) void DiffEditorWidget::setDiff(const QList<DiffList> &diffList)
{ {
m_diffList = diffList; m_diffList = diffList;
m_originalChunkData.clear();
m_contextFileData.clear();
QList<Diff> transformedDiffList = m_diffList; for (int i = 0; i < m_diffList.count(); i++) {
const DiffList &dl = m_diffList.at(i);
m_originalChunkData = calculateOriginalData(transformedDiffList); ChunkData chunkData = calculateOriginalData(dl.diffList);
m_contextFileData = calculateContextData(m_originalChunkData); m_originalChunkData.append(chunkData);
FileData fileData = calculateContextData(chunkData);
fileData.leftFileName = dl.leftFileName;
fileData.rightFileName = dl.rightFileName;
m_contextFileData.append(fileData);
}
showDiff(); showDiff();
} }
@@ -315,7 +468,14 @@ void DiffEditorWidget::setContextLinesNumber(int lines)
return; return;
m_contextLinesNumber = lines; m_contextLinesNumber = lines;
m_contextFileData = calculateContextData(m_originalChunkData); for (int i = 0; i < m_diffList.count(); i++) {
const FileData oldFileData = m_contextFileData.at(i);
FileData newFileData = calculateContextData(m_originalChunkData.at(i));
newFileData.leftFileName = oldFileData.leftFileName;
newFileData.rightFileName = oldFileData.rightFileName;
m_contextFileData[i] = newFileData;
}
showDiff(); showDiff();
} }
@@ -526,11 +686,9 @@ ChunkData DiffEditorWidget::calculateOriginalData(const QList<Diff> &diffList) c
if (currentLeftLineOffset < currentRightLineOffset) { if (currentLeftLineOffset < currentRightLineOffset) {
const int spans = currentRightLineOffset - currentLeftLineOffset; const int spans = currentRightLineOffset - currentLeftLineOffset;
leftLineSpans[currentLeftLine] = spans; leftLineSpans[currentLeftLine] = spans;
// currentLeftPos += spans;
} else if (currentRightLineOffset < currentLeftLineOffset) { } else if (currentRightLineOffset < currentLeftLineOffset) {
const int spans = currentLeftLineOffset - currentRightLineOffset; const int spans = currentLeftLineOffset - currentRightLineOffset;
rightLineSpans[currentRightLine] = spans; rightLineSpans[currentRightLine] = spans;
// currentRightPos += spans;
} }
currentLeftLineOffset = 0; currentLeftLineOffset = 0;
currentRightLineOffset = 0; currentRightLineOffset = 0;
@@ -560,11 +718,9 @@ ChunkData DiffEditorWidget::calculateOriginalData(const QList<Diff> &diffList) c
if (currentLeftLineOffset < currentRightLineOffset) { if (currentLeftLineOffset < currentRightLineOffset) {
const int spans = currentRightLineOffset - currentLeftLineOffset; const int spans = currentRightLineOffset - currentLeftLineOffset;
leftLineSpans[currentLeftLine] = spans; leftLineSpans[currentLeftLine] = spans;
// currentLeftPos += spans;
} else if (currentRightLineOffset < currentLeftLineOffset) { } else if (currentRightLineOffset < currentLeftLineOffset) {
const int spans = currentLeftLineOffset - currentRightLineOffset; const int spans = currentLeftLineOffset - currentRightLineOffset;
rightLineSpans[currentRightLine] = spans; rightLineSpans[currentRightLine] = spans;
// currentRightPos += spans;
} }
} }
if (lastLeftLineEqual && lastRightLineEqual) { if (lastLeftLineEqual && lastRightLineEqual) {
@@ -675,7 +831,7 @@ FileData DiffEditorWidget::calculateContextData(const ChunkData &originalData) c
const int startPos = leftChangedIt.key(); const int startPos = leftChangedIt.key();
const int endPos = leftChangedIt.value(); const int endPos = leftChangedIt.value();
chunkData.changedLeftPositions.insert(startPos, endPos); chunkData.changedLeftPositions.insert(startPos - leftOffset, endPos - leftOffset);
leftChangedIt++; leftChangedIt++;
} }
while (rightChangedIt != originalData.changedRightPositions.constEnd()) { while (rightChangedIt != originalData.changedRightPositions.constEnd()) {
@@ -685,7 +841,7 @@ FileData DiffEditorWidget::calculateContextData(const ChunkData &originalData) c
const int startPos = rightChangedIt.key(); const int startPos = rightChangedIt.key();
const int endPos = rightChangedIt.value(); const int endPos = rightChangedIt.value();
chunkData.changedRightPositions.insert(startPos, endPos); chunkData.changedRightPositions.insert(startPos - rightOffset, endPos - rightOffset);
rightChangedIt++; rightChangedIt++;
} }
fileData.chunks.append(chunkData); fileData.chunks.append(chunkData);
@@ -722,54 +878,58 @@ void DiffEditorWidget::showDiff()
m_rightEditor->setBlockSelection(false); m_rightEditor->setBlockSelection(false);
m_leftEditor->clear(); m_leftEditor->clear();
m_rightEditor->clear(); m_rightEditor->clear();
m_leftEditor->clearLineNumbers(); m_leftEditor->clearAllData();
m_rightEditor->clearLineNumbers(); m_rightEditor->clearAllData();
m_leftEditor->clearSkippedLines();
m_rightEditor->clearSkippedLines();
m_leftEditor->clearSeparators();
m_rightEditor->clearSeparators();
// int ela1 = time.elapsed(); // int ela1 = time.elapsed();
QString leftText, rightText; QString leftText, rightText;
int leftLineNumber = 0;
int rightLineNumber = 0;
int blockNumber = 0; int blockNumber = 0;
QChar separator = QLatin1Char('\n'); QChar separator = QLatin1Char('\n');
for (int i = 0; i < m_contextFileData.chunks.count(); i++) { for (int i = 0; i < m_contextFileData.count(); i++) {
ChunkData chunkData = m_contextFileData.chunks.at(i); const FileData &contextFileData = m_contextFileData.at(i);
if (chunkData.contextChunk) {
const int skippedLines = chunkData.rows.count();
m_leftEditor->setSkippedLines(blockNumber, skippedLines);
m_rightEditor->setSkippedLines(blockNumber, skippedLines);
m_leftEditor->setSeparator(blockNumber, true);
m_rightEditor->setSeparator(blockNumber, true);
leftText += separator;
rightText += separator;
blockNumber++;
}
for (int j = 0; j < chunkData.rows.count(); j++) { int leftLineNumber = 0;
RowData rowData = chunkData.rows.at(j); int rightLineNumber = 0;
TextLineData leftLineData = rowData.leftLine; m_leftEditor->setFileName(blockNumber, contextFileData.leftFileName);
TextLineData rightLineData = rowData.rightLine; m_rightEditor->setFileName(blockNumber, contextFileData.rightFileName);
if (leftLineData.textLineType == TextLineData::TextLine) { leftText += separator;
leftText += leftLineData.text; rightText += separator;
leftLineNumber++; blockNumber++;
m_leftEditor->setLineNumber(blockNumber, QString::number(leftLineNumber));
} else if (leftLineData.textLineType == TextLineData::Separator) { for (int j = 0; j < contextFileData.chunks.count(); j++) {
m_leftEditor->setSeparator(blockNumber, true); ChunkData chunkData = contextFileData.chunks.at(j);
if (chunkData.contextChunk) {
const int skippedLines = chunkData.rows.count();
m_leftEditor->setSkippedLines(blockNumber, skippedLines);
m_rightEditor->setSkippedLines(blockNumber, skippedLines);
leftText += separator;
rightText += separator;
blockNumber++;
} }
if (rightLineData.textLineType == TextLineData::TextLine) { for (int k = 0; k < chunkData.rows.count(); k++) {
rightText += rightLineData.text; RowData rowData = chunkData.rows.at(k);
rightLineNumber++; TextLineData leftLineData = rowData.leftLine;
m_rightEditor->setLineNumber(blockNumber, QString::number(rightLineNumber)); TextLineData rightLineData = rowData.rightLine;
} else if (rightLineData.textLineType == TextLineData::Separator) { if (leftLineData.textLineType == TextLineData::TextLine) {
m_rightEditor->setSeparator(blockNumber, true); leftText += leftLineData.text;
leftLineNumber++;
m_leftEditor->setLineNumber(blockNumber, QString::number(leftLineNumber));
} else if (leftLineData.textLineType == TextLineData::Separator) {
m_leftEditor->setSeparator(blockNumber, true);
}
if (rightLineData.textLineType == TextLineData::TextLine) {
rightText += rightLineData.text;
rightLineNumber++;
m_rightEditor->setLineNumber(blockNumber, QString::number(rightLineNumber));
} else if (rightLineData.textLineType == TextLineData::Separator) {
m_rightEditor->setSeparator(blockNumber, true);
}
leftText += separator;
rightText += separator;
blockNumber++;
} }
leftText += separator;
rightText += separator;
blockNumber++;
} }
} }
// int ela2 = time.elapsed(); // int ela2 = time.elapsed();
@@ -782,35 +942,44 @@ void DiffEditorWidget::showDiff()
colorDiff(m_contextFileData); colorDiff(m_contextFileData);
blockNumber = 0; QTextBlock leftBlock = m_leftEditor->document()->firstBlock();
for (int i = 0; i < m_contextFileData.chunks.count(); i++) { QTextBlock rightBlock = m_rightEditor->document()->firstBlock();
ChunkData chunkData = m_contextFileData.chunks.at(i); for (int i = 0; i < m_contextFileData.count(); i++) {
if (chunkData.contextChunk) { const FileData &contextFileData = m_contextFileData.at(i);
blockNumber++; leftBlock = leftBlock.next();
QTextBlock leftBlock = m_leftEditor->document()->findBlockByNumber(blockNumber); rightBlock = rightBlock.next();
for (int j = 0; j < chunkData.rows.count(); j++) { for (int j = 0; j < contextFileData.chunks.count(); j++) {
TextEditor::BaseTextDocumentLayout::setFoldingIndent(leftBlock, 1); ChunkData chunkData = contextFileData.chunks.at(j);
if (chunkData.contextChunk) {
TextEditor::BaseTextDocumentLayout::setFoldingIndent(leftBlock, FILE_LEVEL);
TextEditor::BaseTextDocumentLayout::setFoldingIndent(rightBlock, FILE_LEVEL);
leftBlock = leftBlock.next(); leftBlock = leftBlock.next();
rightBlock = rightBlock.next();
} }
QTextBlock rightBlock = m_rightEditor->document()->findBlockByNumber(blockNumber); const int indent = chunkData.contextChunk ? CHUNK_LEVEL : FILE_LEVEL;
for (int j = 0; j < chunkData.rows.count(); j++) { for (int k = 0; k < chunkData.rows.count(); k++) {
TextEditor::BaseTextDocumentLayout::setFoldingIndent(rightBlock, 1); TextEditor::BaseTextDocumentLayout::setFoldingIndent(leftBlock, indent);
TextEditor::BaseTextDocumentLayout::setFoldingIndent(rightBlock, indent);
leftBlock = leftBlock.next();
rightBlock = rightBlock.next(); rightBlock = rightBlock.next();
} }
} }
blockNumber += chunkData.rows.count();
} }
blockNumber = 0; blockNumber = 0;
for (int i = 0; i < m_contextFileData.chunks.count(); i++) { for (int i = 0; i < m_contextFileData.count(); i++) {
ChunkData chunkData = m_contextFileData.chunks.at(i); const FileData &contextFileData = m_contextFileData.at(i);
if (chunkData.contextChunk) { blockNumber++;
QTextBlock leftBlock = m_leftEditor->document()->findBlockByNumber(blockNumber); for (int j = 0; j < contextFileData.chunks.count(); j++) {
TextEditor::BaseTextDocumentLayout::doFoldOrUnfold(leftBlock, false); ChunkData chunkData = contextFileData.chunks.at(j);
QTextBlock rightBlock = m_rightEditor->document()->findBlockByNumber(blockNumber); if (chunkData.contextChunk) {
TextEditor::BaseTextDocumentLayout::doFoldOrUnfold(rightBlock, false); QTextBlock leftBlock = m_leftEditor->document()->findBlockByNumber(blockNumber);
blockNumber++; TextEditor::BaseTextDocumentLayout::doFoldOrUnfold(leftBlock, false);
QTextBlock rightBlock = m_rightEditor->document()->findBlockByNumber(blockNumber);
TextEditor::BaseTextDocumentLayout::doFoldOrUnfold(rightBlock, false);
blockNumber++;
}
blockNumber += chunkData.rows.count();
} }
blockNumber += chunkData.rows.count();
} }
m_foldingBlocker = true; m_foldingBlocker = true;
BaseTextDocumentLayout *leftLayout = qobject_cast<BaseTextDocumentLayout *>(m_leftEditor->document()->documentLayout()); BaseTextDocumentLayout *leftLayout = qobject_cast<BaseTextDocumentLayout *>(m_leftEditor->document()->documentLayout());
@@ -833,6 +1002,8 @@ void DiffEditorWidget::showDiff()
m_rightEditor->horizontalScrollBar()->setValue(rightHorizontalValue); m_rightEditor->horizontalScrollBar()->setValue(rightHorizontalValue);
// int ela6 = time.elapsed(); // int ela6 = time.elapsed();
// qDebug() << ela1 << ela2 << ela3 << ela4 << ela5 << ela6; // qDebug() << ela1 << ela2 << ela3 << ela4 << ela5 << ela6;
m_leftEditor->updateFoldingHighlight(QPoint(-1, -1));
m_rightEditor->updateFoldingHighlight(QPoint(-1, -1));
} }
QList<QTextEdit::ExtraSelection> DiffEditorWidget::colorPositions( QList<QTextEdit::ExtraSelection> DiffEditorWidget::colorPositions(
@@ -858,7 +1029,7 @@ QList<QTextEdit::ExtraSelection> DiffEditorWidget::colorPositions(
return lineSelections; return lineSelections;
} }
void DiffEditorWidget::colorDiff(const FileData &fileData) void DiffEditorWidget::colorDiff(const QList<FileData> &fileDataList)
{ {
QTextCharFormat leftLineFormat; QTextCharFormat leftLineFormat;
leftLineFormat.setBackground(QColor(255, 223, 223)); leftLineFormat.setBackground(QColor(255, 223, 223));
@@ -886,6 +1057,11 @@ void DiffEditorWidget::colorDiff(const FileData &fileData)
chunkLineFormat.setBackground(QColor(175, 215, 231)); chunkLineFormat.setBackground(QColor(175, 215, 231));
chunkLineFormat.setProperty(QTextFormat::FullWidthSelection, true); chunkLineFormat.setProperty(QTextFormat::FullWidthSelection, true);
QTextCharFormat fileLineFormat;
fileLineFormat.setBackground(QColor(255, 255, 0));
// fileLineFormat.setBackground(QColor(130, 60, 0));
fileLineFormat.setProperty(QTextFormat::FullWidthSelection, true);
int leftPos = 0; int leftPos = 0;
int rightPos = 0; int rightPos = 0;
// startPos, endPos // startPos, endPos
@@ -897,66 +1073,76 @@ void DiffEditorWidget::colorDiff(const FileData &fileData)
QMap<int, int> rightSkippedPos; QMap<int, int> rightSkippedPos;
QMap<int, int> leftChunkPos; QMap<int, int> leftChunkPos;
QMap<int, int> rightChunkPos; QMap<int, int> rightChunkPos;
QMap<int, int> leftFilePos;
QMap<int, int> rightFilePos;
int leftLastDiffBlockStartPos = 0; int leftLastDiffBlockStartPos = 0;
int rightLastDiffBlockStartPos = 0; int rightLastDiffBlockStartPos = 0;
int leftLastSkippedBlockStartPos = 0; int leftLastSkippedBlockStartPos = 0;
int rightLastSkippedBlockStartPos = 0; int rightLastSkippedBlockStartPos = 0;
int chunkOffset = 0;
for (int i = 0; i < fileData.chunks.count(); i++) { for (int i = 0; i < fileDataList.count(); i++) {
ChunkData chunkData = fileData.chunks.at(i); leftFilePos[leftPos] = leftPos + 1;
if (chunkData.contextChunk) { rightFilePos[rightPos] = rightPos + 1;
leftChunkPos[leftPos] = leftPos + 1; leftPos++; // for file line
rightChunkPos[rightPos] = rightPos + 1; rightPos++; // for file line
leftPos++; // for chunk line const FileData &fileData = fileDataList.at(i);
rightPos++; // for chunk line
chunkOffset++;
}
leftLastDiffBlockStartPos = leftPos;
rightLastDiffBlockStartPos = rightPos;
leftLastSkippedBlockStartPos = leftPos;
rightLastSkippedBlockStartPos = rightPos;
QMapIterator<int, int> itLeft(chunkData.changedLeftPositions); for (int j = 0; j < fileData.chunks.count(); j++) {
while (itLeft.hasNext()) { ChunkData chunkData = fileData.chunks.at(j);
itLeft.next(); if (chunkData.contextChunk) {
leftChunkPos[leftPos] = leftPos + 1;
rightChunkPos[rightPos] = rightPos + 1;
leftPos++; // for chunk line
rightPos++; // for chunk line
}
const int leftFileOffset = leftPos;
const int rightFileOffset = rightPos;
leftLastDiffBlockStartPos = leftPos;
rightLastDiffBlockStartPos = rightPos;
leftLastSkippedBlockStartPos = leftPos;
rightLastSkippedBlockStartPos = rightPos;
leftCharPos[itLeft.key() + chunkOffset] = itLeft.value() + chunkOffset; QMapIterator<int, int> itLeft(chunkData.changedLeftPositions);
} while (itLeft.hasNext()) {
itLeft.next();
QMapIterator<int, int> itRight(chunkData.changedRightPositions); leftCharPos[itLeft.key() + leftFileOffset] = itLeft.value() + leftFileOffset;
while (itRight.hasNext()) { }
itRight.next();
rightCharPos[itRight.key() + chunkOffset] = itRight.value() + chunkOffset; QMapIterator<int, int> itRight(chunkData.changedRightPositions);
} while (itRight.hasNext()) {
itRight.next();
for (int j = 0; j < chunkData.rows.count(); j++) { rightCharPos[itRight.key() + rightFileOffset] = itRight.value() + rightFileOffset;
RowData rowData = chunkData.rows.at(j); }
leftPos += rowData.leftLine.text.count() + 1; // +1 for separator or for '\n', each line has one of it for (int k = 0; k < chunkData.rows.count(); k++) {
rightPos += rowData.rightLine.text.count() + 1; // +1 for separator or for '\n', each line has one of it RowData rowData = chunkData.rows.at(k);
if (!rowData.equal) { leftPos += rowData.leftLine.text.count() + 1; // +1 for separator or for '\n', each line has one of it
if (rowData.leftLine.textLineType == TextLineData::TextLine) { rightPos += rowData.rightLine.text.count() + 1; // +1 for separator or for '\n', each line has one of it
leftLinePos[leftLastDiffBlockStartPos] = leftPos;
leftLastSkippedBlockStartPos = leftPos; if (!rowData.equal) {
if (rowData.leftLine.textLineType == TextLineData::TextLine) {
leftLinePos[leftLastDiffBlockStartPos] = leftPos;
leftLastSkippedBlockStartPos = leftPos;
} else {
leftSkippedPos[leftLastSkippedBlockStartPos] = leftPos;
leftLastDiffBlockStartPos = leftPos;
}
if (rowData.rightLine.textLineType == TextLineData::TextLine) {
rightLinePos[rightLastDiffBlockStartPos] = rightPos;
rightLastSkippedBlockStartPos = rightPos;
} else {
rightSkippedPos[rightLastSkippedBlockStartPos] = rightPos;
rightLastDiffBlockStartPos = rightPos;
}
} else { } else {
leftSkippedPos[leftLastSkippedBlockStartPos] = leftPos;
leftLastDiffBlockStartPos = leftPos; leftLastDiffBlockStartPos = leftPos;
}
if (rowData.rightLine.textLineType == TextLineData::TextLine) {
rightLinePos[rightLastDiffBlockStartPos] = rightPos;
rightLastSkippedBlockStartPos = rightPos;
} else {
rightSkippedPos[rightLastSkippedBlockStartPos] = rightPos;
rightLastDiffBlockStartPos = rightPos; rightLastDiffBlockStartPos = rightPos;
leftLastSkippedBlockStartPos = leftPos;
rightLastSkippedBlockStartPos = rightPos;
} }
} else {
leftLastDiffBlockStartPos = leftPos;
rightLastDiffBlockStartPos = rightPos;
leftLastSkippedBlockStartPos = leftPos;
rightLastSkippedBlockStartPos = rightPos;
} }
} }
} }
@@ -970,6 +1156,8 @@ void DiffEditorWidget::colorDiff(const FileData &fileData)
+= colorPositions(spanLineFormat, leftCursor, leftSkippedPos); += colorPositions(spanLineFormat, leftCursor, leftSkippedPos);
leftSelections leftSelections
+= colorPositions(chunkLineFormat, leftCursor, leftChunkPos); += colorPositions(chunkLineFormat, leftCursor, leftChunkPos);
leftSelections
+= colorPositions(fileLineFormat, leftCursor, leftFilePos);
leftSelections leftSelections
+= colorPositions(leftCharFormat, leftCursor, leftCharPos); += colorPositions(leftCharFormat, leftCursor, leftCharPos);
@@ -979,6 +1167,8 @@ void DiffEditorWidget::colorDiff(const FileData &fileData)
+= colorPositions(spanLineFormat, rightCursor, rightSkippedPos); += colorPositions(spanLineFormat, rightCursor, rightSkippedPos);
rightSelections rightSelections
+= colorPositions(chunkLineFormat, rightCursor, rightChunkPos); += colorPositions(chunkLineFormat, rightCursor, rightChunkPos);
rightSelections
+= colorPositions(fileLineFormat, rightCursor, rightFilePos);
rightSelections rightSelections
+= colorPositions(rightCharFormat, rightCursor, rightCharPos); += colorPositions(rightCharFormat, rightCursor, rightCharPos);
@@ -1010,6 +1200,39 @@ void DiffEditorWidget::rightDocumentSizeChanged()
synchronizeFoldings(m_rightEditor, m_leftEditor); synchronizeFoldings(m_rightEditor, m_leftEditor);
} }
/* Special version of that method (original: TextEditor::BaseTextDocumentLayout::doFoldOrUnfold())
The hack lies in fact, that when unfolding all direct sub-blocks are made visible,
while some of them need to stay invisible (i.e. unfolded chunk lines)
*/
static void doFoldOrUnfold(DiffViewEditorWidget *editor, const QTextBlock &block, bool unfold)
{
if (!TextEditor::BaseTextDocumentLayout::canFold(block))
return;
QTextBlock b = block.next();
int indent = TextEditor::BaseTextDocumentLayout::foldingIndent(block);
while (b.isValid() && TextEditor::BaseTextDocumentLayout::foldingIndent(b) > indent && (unfold || b.next().isValid())) {
if (unfold && editor->isChunkLine(b.blockNumber()) && !TextEditor::BaseTextDocumentLayout::isFolded(b)) {
b.setVisible(false);
b.setLineCount(0);
} else {
b.setVisible(unfold);
b.setLineCount(unfold ? qMax(1, b.layout()->lineCount()) : 0);
}
if (unfold) { // do not unfold folded sub-blocks
if (TextEditor::BaseTextDocumentLayout::isFolded(b) && b.next().isValid()) {
int jndent = TextEditor::BaseTextDocumentLayout::foldingIndent(b);
b = b.next();
while (b.isValid() && TextEditor::BaseTextDocumentLayout::foldingIndent(b) > jndent)
b = b.next();
continue;
}
}
b = b.next();
}
TextEditor::BaseTextDocumentLayout::setFolded(block, !unfold);
}
void DiffEditorWidget::synchronizeFoldings(DiffViewEditorWidget *source, DiffViewEditorWidget *destination) void DiffEditorWidget::synchronizeFoldings(DiffViewEditorWidget *source, DiffViewEditorWidget *destination)
{ {
if (m_foldingBlocker) if (m_foldingBlocker)
@@ -1023,53 +1246,62 @@ void DiffEditorWidget::synchronizeFoldings(DiffViewEditorWidget *source, DiffVie
const bool isSourceFolded = TextEditor::BaseTextDocumentLayout::isFolded(sourceBlock); const bool isSourceFolded = TextEditor::BaseTextDocumentLayout::isFolded(sourceBlock);
const bool isDestinationFolded = TextEditor::BaseTextDocumentLayout::isFolded(destinationBlock); const bool isDestinationFolded = TextEditor::BaseTextDocumentLayout::isFolded(destinationBlock);
if (isSourceFolded != isDestinationFolded) { if (isSourceFolded != isDestinationFolded) {
if (isSourceFolded) { // we fold the destination if (source->isFileLine(sourceBlock.blockNumber())) {
QTextBlock previousSource = sourceBlock.previous(); // skippedLines doFoldOrUnfold(source, sourceBlock, !isSourceFolded);
QTextBlock previousDestination = destinationBlock.previous(); // skippedLines doFoldOrUnfold(destination, destinationBlock, !isSourceFolded);
QTextBlock firstVisibleDestinationBlock = destination->firstVisibleBlock(); } else {
QTextBlock firstDestinationBlock = destination->document()->firstBlock(); if (isSourceFolded) { // we fold the destination (shrinking)
TextEditor::BaseTextDocumentLayout::doFoldOrUnfold(destinationBlock, !isSourceFolded); QTextBlock previousSource = sourceBlock.previous(); // skippedLines
TextEditor::BaseTextDocumentLayout::setFoldingIndent(sourceBlock, 1); QTextBlock previousDestination = destinationBlock.previous(); // skippedLines
TextEditor::BaseTextDocumentLayout::setFoldingIndent(destinationBlock, 1); if (source->isChunkLine(previousSource.blockNumber())) {
previousSource.setVisible(true); QTextBlock firstVisibleDestinationBlock = destination->firstVisibleBlock();
previousSource.setLineCount(1); QTextBlock firstDestinationBlock = destination->document()->firstBlock();
previousDestination.setVisible(true); TextEditor::BaseTextDocumentLayout::doFoldOrUnfold(destinationBlock, !isSourceFolded);
previousDestination.setLineCount(1); TextEditor::BaseTextDocumentLayout::setFoldingIndent(sourceBlock, CHUNK_LEVEL);
sourceBlock.setVisible(false); TextEditor::BaseTextDocumentLayout::setFoldingIndent(destinationBlock, CHUNK_LEVEL);
sourceBlock.setLineCount(0); previousSource.setVisible(true);
destinationBlock.setVisible(false); previousSource.setLineCount(1);
destinationBlock.setLineCount(0); previousDestination.setVisible(true);
TextEditor::BaseTextDocumentLayout::setFolded(previousSource, true); previousDestination.setLineCount(1);
TextEditor::BaseTextDocumentLayout::setFolded(previousDestination, true); sourceBlock.setVisible(false);
sourceBlock.setLineCount(0);
destinationBlock.setVisible(false);
destinationBlock.setLineCount(0);
TextEditor::BaseTextDocumentLayout::setFolded(previousSource, true);
TextEditor::BaseTextDocumentLayout::setFolded(previousDestination, true);
if (firstVisibleDestinationBlock == destinationBlock) { if (firstVisibleDestinationBlock == destinationBlock) {
/* /*
The following hack is completely crazy. That's the only way to scroll 1 line up The following hack is completely crazy. That's the only way to scroll 1 line up
in case destinationBlock was the top visible block. in case destinationBlock was the top visible block.
There is no need to scroll the source since this is in sync anyway There is no need to scroll the source since this is in sync anyway
(leftSliderChanged(), rightSliderChanged()) (leftSliderChanged(), rightSliderChanged())
*/ */
destination->verticalScrollBar()->setValue(destination->verticalScrollBar()->value() - 1); destination->verticalScrollBar()->setValue(destination->verticalScrollBar()->value() - 1);
destination->verticalScrollBar()->setValue(destination->verticalScrollBar()->value() + 1); destination->verticalScrollBar()->setValue(destination->verticalScrollBar()->value() + 1);
if (firstVisibleDestinationBlock.previous() == firstDestinationBlock) { if (firstVisibleDestinationBlock.previous() == firstDestinationBlock) {
/* /*
Even more crazy case: the destinationBlock was the first top visible block. Even more crazy case: the destinationBlock was the first top visible block.
*/ */
destination->verticalScrollBar()->setValue(0); destination->verticalScrollBar()->setValue(0);
}
}
}
} else { // we unfold the destination (expanding)
if (source->isChunkLine(sourceBlock.blockNumber())) {
QTextBlock nextSource = sourceBlock.next();
QTextBlock nextDestination = destinationBlock.next();
TextEditor::BaseTextDocumentLayout::doFoldOrUnfold(destinationBlock, !isSourceFolded);
TextEditor::BaseTextDocumentLayout::setFoldingIndent(nextSource, FILE_LEVEL);
TextEditor::BaseTextDocumentLayout::setFoldingIndent(nextDestination, FILE_LEVEL);
sourceBlock.setVisible(false);
sourceBlock.setLineCount(0);
destinationBlock.setVisible(false);
destinationBlock.setLineCount(0);
TextEditor::BaseTextDocumentLayout::setFolded(nextSource, false);
TextEditor::BaseTextDocumentLayout::setFolded(nextDestination, false);
} }
} }
} else { // we unfold the destination
QTextBlock nextSource = sourceBlock.next();
QTextBlock nextDestination = destinationBlock.next();
TextEditor::BaseTextDocumentLayout::doFoldOrUnfold(destinationBlock, !isSourceFolded);
TextEditor::BaseTextDocumentLayout::setFoldingIndent(nextSource, 0);
TextEditor::BaseTextDocumentLayout::setFoldingIndent(nextDestination, 0);
sourceBlock.setVisible(false);
sourceBlock.setLineCount(0);
destinationBlock.setVisible(false);
destinationBlock.setLineCount(0);
TextEditor::BaseTextDocumentLayout::setFolded(nextSource, false);
TextEditor::BaseTextDocumentLayout::setFolded(nextDestination, false);
} }
break; // only one should be synchronized break; // only one should be synchronized
} }

View File

@@ -81,7 +81,6 @@ struct ChunkData {
ChunkData() : contextChunk(false) {} ChunkData() : contextChunk(false) {}
QList<RowData> rows; QList<RowData> rows;
bool contextChunk; bool contextChunk;
// <absolute position in the file, absolute position in the file>
QMap<int, int> changedLeftPositions; // counting from the beginning of the chunk QMap<int, int> changedLeftPositions; // counting from the beginning of the chunk
QMap<int, int> changedRightPositions; // counting from the beginning of the chunk QMap<int, int> changedRightPositions; // counting from the beginning of the chunk
}; };
@@ -90,6 +89,8 @@ struct FileData {
FileData() {} FileData() {}
FileData(const ChunkData &chunkData) { chunks.append(chunkData); } FileData(const ChunkData &chunkData) { chunks.append(chunkData); }
QList<ChunkData> chunks; QList<ChunkData> chunks;
QString leftFileName;
QString rightFileName;
}; };
struct DiffData { struct DiffData {
@@ -100,10 +101,18 @@ class DIFFEDITOR_EXPORT DiffEditorWidget : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
struct DiffFilesContents {
QString leftFileName;
QString leftText;
QString rightFileName;
QString rightText;
};
DiffEditorWidget(QWidget *parent = 0); DiffEditorWidget(QWidget *parent = 0);
~DiffEditorWidget(); ~DiffEditorWidget();
void setDiff(const QString &leftText, const QString &rightText); void clear();
void setDiff(const QList<DiffFilesContents> &diffFileList);
QTextCodec *codec() const; QTextCodec *codec() const;
public slots: public slots:
@@ -121,14 +130,20 @@ private slots:
void rightDocumentSizeChanged(); void rightDocumentSizeChanged();
private: private:
void setDiff(const QList<Diff> &diffList); struct DiffList {
QString leftFileName;
QString rightFileName;
QList<Diff> diffList;
};
void setDiff(const QList<DiffList> &diffList);
bool isWhitespace(const QChar &c) const; bool isWhitespace(const QChar &c) const;
bool isWhitespace(const Diff &diff) const; bool isWhitespace(const Diff &diff) const;
bool isEqual(const QList<Diff> &diffList, int diffNumber) const; bool isEqual(const QList<Diff> &diffList, int diffNumber) const;
QList<QTextEdit::ExtraSelection> colorPositions(const QTextCharFormat &format, QList<QTextEdit::ExtraSelection> colorPositions(const QTextCharFormat &format,
QTextCursor &cursor, QTextCursor &cursor,
const QMap<int, int> &positions) const; const QMap<int, int> &positions) const;
void colorDiff(const FileData &fileData); void colorDiff(const QList<FileData> &fileDataList);
QList<TextLineData> assemblyRows(const QStringList &lines, QList<TextLineData> assemblyRows(const QStringList &lines,
const QMap<int, int> &lineSpans, const QMap<int, int> &lineSpans,
const QMap<int, int> &changedPositions, const QMap<int, int> &changedPositions,
@@ -142,13 +157,12 @@ private:
DiffViewEditorWidget *m_rightEditor; DiffViewEditorWidget *m_rightEditor;
QSplitter *m_splitter; QSplitter *m_splitter;
QList<Diff> m_diffList; QList<DiffList> m_diffList; // list of original outputs from differ
QList<ChunkData> m_originalChunkData; // one big chunk for every file, ignoreWhitespaces taken into account
QList<FileData> m_contextFileData; // ultimate data to be shown, contextLinesNumber taken into account
int m_contextLinesNumber; int m_contextLinesNumber;
bool m_ignoreWhitespaces; bool m_ignoreWhitespaces;
ChunkData m_originalChunkData;
FileData m_contextFileData;
bool m_foldingBlocker; bool m_foldingBlocker;
}; };

View File

@@ -3649,6 +3649,11 @@ void BaseTextEditorWidget::paintEvent(QPaintEvent *e)
} }
} }
int BaseTextEditorWidget::visibleFoldedBlockNumber() const
{
return d->visibleFoldedBlockNumber;
}
void BaseTextEditorWidget::drawCollapsedBlockPopup(QPainter &painter, void BaseTextEditorWidget::drawCollapsedBlockPopup(QPainter &painter,
const QTextBlock &block, const QTextBlock &block,
QPointF offset, QPointF offset,
@@ -4617,8 +4622,7 @@ void BaseTextEditorWidget::toggleBlockVisible(const QTextBlock &block)
BaseTextDocumentLayout *documentLayout = qobject_cast<BaseTextDocumentLayout*>(document()->documentLayout()); BaseTextDocumentLayout *documentLayout = qobject_cast<BaseTextDocumentLayout*>(document()->documentLayout());
QTC_ASSERT(documentLayout, return); QTC_ASSERT(documentLayout, return);
bool visible = block.next().isVisible(); BaseTextDocumentLayout::doFoldOrUnfold(block, BaseTextDocumentLayout::isFolded(block));
BaseTextDocumentLayout::doFoldOrUnfold(block, !visible);
documentLayout->requestUpdate(); documentLayout->requestUpdate();
documentLayout->emitDocumentSizeChanged(); documentLayout->emitDocumentSizeChanged();
} }

View File

@@ -539,6 +539,12 @@ protected:
Reimplement this function to change the default replacement text. Reimplement this function to change the default replacement text.
*/ */
virtual QString foldReplacementText(const QTextBlock &block) const; virtual QString foldReplacementText(const QTextBlock &block) const;
virtual void drawCollapsedBlockPopup(QPainter &painter,
const QTextBlock &block,
QPointF offset,
const QRect &clip);
int visibleFoldedBlockNumber() const;
protected slots: protected slots:
virtual void slotUpdateExtraArea(); virtual void slotUpdateExtraArea();
@@ -570,11 +576,6 @@ private:
bool active, bool active,
bool hovered) const; bool hovered) const;
void drawCollapsedBlockPopup(QPainter &painter,
const QTextBlock &block,
QPointF offset,
const QRect &clip);
void toggleBlockVisible(const QTextBlock &block); void toggleBlockVisible(const QTextBlock &block);
QRect foldBox(); QRect foldBox();