diff options
author | jkobus <jaroslaw.kobus@digia.com> | 2013-04-09 10:26:31 +0200 |
---|---|---|
committer | hjk <hjk121@nokiamail.com> | 2013-04-12 14:55:08 +0200 |
commit | 77abd027876b79eddeabed36317ff57e8bbdcb1d (patch) | |
tree | 33d1271cc3f4445be598036a4bda82fbf4ef970d /src/plugins/diffeditor/diffeditorwidget.cpp | |
parent | 7051f49a6eef5e981ea008e479ca1d67869338cb (diff) | |
download | qt-creator-77abd027876b79eddeabed36317ff57e8bbdcb1d.tar.gz |
Get rid of QChar::LineSeparator
It was causing troubles while scrolling. Replace it with
\n and hack selection. Simplify the code. Now every line
is a separate block. Prepare for expanding skipped lines.
Change-Id: I8d305681c575abdaaf9cdbf26de864dd3a906d3a
Reviewed-by: David Schulz <david.schulz@digia.com>
Reviewed-by: hjk <hjk121@nokiamail.com>
Diffstat (limited to 'src/plugins/diffeditor/diffeditorwidget.cpp')
-rw-r--r-- | src/plugins/diffeditor/diffeditorwidget.cpp | 290 |
1 files changed, 127 insertions, 163 deletions
diff --git a/src/plugins/diffeditor/diffeditorwidget.cpp b/src/plugins/diffeditor/diffeditorwidget.cpp index d9ed5255a0..b21f2cae26 100644 --- a/src/plugins/diffeditor/diffeditorwidget.cpp +++ b/src/plugins/diffeditor/diffeditorwidget.cpp @@ -64,6 +64,7 @@ public: }; + //////////////////////// class DiffViewEditorWidget : public SnippetEditorWidget @@ -79,27 +80,31 @@ public: return const_cast<QTextCodec *>(baseTextDocument()->codec()); } - QMap<int, QMap<int, int> > skippedLines() const { return m_skippedLines; } + QMap<int, int> skippedLines() const { return m_skippedLines; } void setLineNumber(int blockNumber, const QString &lineNumber); - void setSkippedLines(int blockNumber, int lineInBlock, int skippedLines) { m_skippedLines[blockNumber][lineInBlock] = skippedLines; } + void setSkippedLines(int blockNumber, int skippedLines) { m_skippedLines[blockNumber] = skippedLines; } + void setSeparator(int blockNumber, bool separator) { m_separators[blockNumber] = separator; } void clearLineNumbers(); void clearSkippedLines() { m_skippedLines.clear(); } + void clearSeparators() { m_separators.clear(); } protected: virtual int extraAreaWidth(int *markWidthPtr = 0) const { return BaseTextEditorWidget::extraAreaWidth(markWidthPtr); } BaseTextEditor *createEditor() { return new DiffViewEditorEditable(this); } virtual QString lineNumber(int blockNumber) const; - int lineNumberTopPositionOffset(int blockNumber) const; virtual int lineNumberDigits() const; + virtual bool selectionVisible(int blockNumber) const; virtual void paintEvent(QPaintEvent *e); virtual void scrollContentsBy(int dx, int dy); private: QMap<int, QString> m_lineNumbers; int m_lineNumberDigits; - // block number, line in block, skipped lines - QMap<int, QMap<int, int> > m_skippedLines; + // block number, skipped lines + QMap<int, int> m_skippedLines; + // block number, separator + QMap<int, bool> m_separators; }; DiffViewEditorWidget::DiffViewEditorWidget(QWidget *parent) @@ -114,25 +119,14 @@ QString DiffViewEditorWidget::lineNumber(int blockNumber) const return m_lineNumbers.value(blockNumber); } -int DiffViewEditorWidget::lineNumberTopPositionOffset(int blockNumber) const +int DiffViewEditorWidget::lineNumberDigits() const { - int offset = 0; - const QFontMetrics fm(extraArea()->font()); - int i = 0; - const QString text = document()->findBlockByNumber(blockNumber).text(); - while (i < text.count()) { - if (text.at(i) != QChar::LineSeparator) - break; - offset += fm.height(); - i++; - } - return offset; + return m_lineNumberDigits; } - -int DiffViewEditorWidget::lineNumberDigits() const +bool DiffViewEditorWidget::selectionVisible(int blockNumber) const { - return m_lineNumberDigits; + return !m_separators.value(blockNumber, false); } void DiffViewEditorWidget::setLineNumber(int blockNumber, const QString &lineNumber) @@ -163,7 +157,7 @@ void DiffViewEditorWidget::paintEvent(QPaintEvent *e) QTextBlock firstBlock = firstVisibleBlock(); QTextBlock currentBlock = firstBlock; - QMap<int, QMap<int, int> > skipped = skippedLines(); + QMap<int, int> skipped = skippedLines(); while (currentBlock.isValid()) { if (currentBlock.isVisible()) { @@ -176,17 +170,13 @@ void DiffViewEditorWidget::paintEvent(QPaintEvent *e) if (bottom >= e->rect().top()) { QTextLayout *layout = currentBlock.layout(); - QMap<int, int> skippedInBlock = skipped.value(currentBlock.blockNumber()); - QMapIterator<int, int> itLines(skippedInBlock); - while (itLines.hasNext()) { - itLines.next(); - + int skippedBefore = skipped.value(currentBlock.blockNumber()); + if (skippedBefore) { painter.save(); painter.setPen(palette().foreground().color()); - QTextLine textLine = layout->lineAt(itLines.key()); - // QRectF lineRect = textLine.naturalTextRect().translated(offset.x(), top); + QTextLine textLine = layout->lineAt(0); QRectF lineRect = textLine.naturalTextRect().translated(0, top); - QString skippedRowsText = tr("Skipped %n lines...", 0, itLines.value()); + QString skippedRowsText = tr("Skipped %n lines...", 0, skippedBefore); QFontMetrics fm(font()); const int textWidth = fm.width(skippedRowsText); painter.drawText(QPointF(lineRect.right() @@ -206,9 +196,7 @@ void DiffViewEditorWidget::paintEvent(QPaintEvent *e) DiffEditorWidget::DiffEditorWidget(QWidget *parent) : QWidget(parent), m_contextLinesNumber(1), - m_ignoreWhitespaces(true), - m_leftSafePosHack(-1), - m_rightSafePosHack(-1) + m_ignoreWhitespaces(true) { TextEditor::TextEditorSettings *settings = TextEditorSettings::instance(); @@ -631,22 +619,16 @@ FileData DiffEditorWidget::calculateContextData(const ChunkData &originalData) c } } i = 0; - int skippedLines = 0; int leftCharCounter = 0; int rightCharCounter = 0; - int leftCharSkipped = 0; - int rightCharSkipped = 0; - int chunkOffset = 0; QMap<int, int>::ConstIterator leftChangedIt = originalData.changedLeftPositions.constBegin(); QMap<int, int>::ConstIterator rightChangedIt = originalData.changedRightPositions.constBegin(); while (i < originalData.rows.count()) { if (!hiddenRows.contains(i)) { ChunkData chunkData; - if (skippedLines) - chunkOffset++; // for chunk line - chunkData.leftOffset = leftCharCounter; - chunkData.rightOffset = rightCharCounter; - chunkData.skippedLinesBefore = skippedLines; + int leftOffset = leftCharCounter; + int rightOffset = rightCharCounter; + chunkData.alwaysShown = true; while (i < originalData.rows.count()) { if (hiddenRows.contains(i)) break; @@ -658,47 +640,42 @@ FileData DiffEditorWidget::calculateContextData(const ChunkData &originalData) c i++; } while (leftChangedIt != originalData.changedLeftPositions.constEnd()) { - if (leftChangedIt.key() < chunkData.leftOffset + if (leftChangedIt.key() < leftOffset || leftChangedIt.key() > leftCharCounter) break; - const int startPos = leftChangedIt.key() - leftCharSkipped + chunkOffset; - const int endPos = leftChangedIt.value() - leftCharSkipped + chunkOffset; + const int startPos = leftChangedIt.key(); + const int endPos = leftChangedIt.value(); chunkData.changedLeftPositions.insert(startPos, endPos); leftChangedIt++; } while (rightChangedIt != originalData.changedRightPositions.constEnd()) { - if (rightChangedIt.key() < chunkData.rightOffset + if (rightChangedIt.key() < rightOffset || rightChangedIt.key() > rightCharCounter) break; - const int startPos = rightChangedIt.key() - rightCharSkipped + chunkOffset; - const int endPos = rightChangedIt.value() - rightCharSkipped + chunkOffset; + const int startPos = rightChangedIt.key(); + const int endPos = rightChangedIt.value(); chunkData.changedRightPositions.insert(startPos, endPos); rightChangedIt++; } fileData.chunks.append(chunkData); - skippedLines = 0; } else { - const int leftChars = originalData.rows.at(i).leftLine.text.count() + 1; - const int rightChars = originalData.rows.at(i).rightLine.text.count() + 1; - leftCharCounter += leftChars; - rightCharCounter += rightChars; - leftCharSkipped += leftChars; - rightCharSkipped += rightChars; - i++; - skippedLines++; - } - } + ChunkData chunkData; + chunkData.alwaysShown = false; + while (i < originalData.rows.count()) { + if (!hiddenRows.contains(i)) + break; + RowData rowData = originalData.rows.at(i); + chunkData.rows.append(rowData); - if (skippedLines) { - ChunkData chunkData; - chunkData.leftOffset = leftCharCounter; - chunkData.rightOffset = rightCharCounter; - chunkData.skippedLinesBefore = skippedLines; - fileData.chunks.append(chunkData); + leftCharCounter += rowData.leftLine.text.count() + 1; // +1 for separator or for '\n', each line has one of it + rightCharCounter += rowData.rightLine.text.count() + 1; // +1 for separator or for '\n', each line has one of it + i++; + } + fileData.chunks.append(chunkData); + } } - return fileData; } @@ -706,123 +683,64 @@ void DiffEditorWidget::showDiff() { // QTime time; // time.start(); + + // TODO: remember the line number of the line in the middle const int verticalValue = m_leftEditor->verticalScrollBar()->value(); const int leftHorizontalValue = m_leftEditor->horizontalScrollBar()->value(); const int rightHorizontalValue = m_rightEditor->horizontalScrollBar()->value(); - // Ugly hack starts here - // When the cursor stays on the line with QChar::LineSeparator - // the new inserted text will have the background taken from that line. - if (m_leftSafePosHack >= 0) { - QTextCursor cursor = m_leftEditor->textCursor(); - cursor.setPosition(m_leftSafePosHack); - m_leftEditor->setTextCursor(cursor); - m_leftSafePosHack = -1; - } - if (m_rightSafePosHack >= 0) { - QTextCursor cursor = m_rightEditor->textCursor(); - cursor.setPosition(m_rightSafePosHack); - m_rightEditor->setTextCursor(cursor); - m_rightSafePosHack = -1; - } - // Ugly hack ends here - m_leftEditor->clear(); m_rightEditor->clear(); m_leftEditor->clearLineNumbers(); m_rightEditor->clearLineNumbers(); m_leftEditor->clearSkippedLines(); m_rightEditor->clearSkippedLines(); + m_leftEditor->clearSeparators(); + m_rightEditor->clearSeparators(); // int ela1 = time.elapsed(); QString leftText, rightText; - bool leftStartWithNewLine = false; - bool rightStartWithNewLine = false; int leftLineNumber = 0; - int leftBlockNumber = 0; int rightLineNumber = 0; - int rightBlockNumber = 0; - int leftPos = 0; - int rightPos = 0; - int leftSeparatorCount = 0; - int rightSeparatorCount = 0; + int blockNumber = 0; + QChar separator = QLatin1Char('\n'); for (int i = 0; i < m_contextFileData.chunks.count(); i++) { ChunkData chunkData = m_contextFileData.chunks.at(i); - leftLineNumber += chunkData.skippedLinesBefore; - rightLineNumber += chunkData.skippedLinesBefore; - - if (chunkData.skippedLinesBefore) { - m_leftEditor->setSkippedLines(leftBlockNumber, leftSeparatorCount, chunkData.skippedLinesBefore); - leftSeparatorCount++; - m_rightEditor->setSkippedLines(rightBlockNumber, rightSeparatorCount, chunkData.skippedLinesBefore); - rightSeparatorCount++; + if (!chunkData.alwaysShown) { + const int skippedLines = chunkData.rows.count(); +// leftLineNumber += skippedLines; +// rightLineNumber += skippedLines; + 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++) { RowData rowData = chunkData.rows.at(j); TextLineData leftLineData = rowData.leftLine; TextLineData rightLineData = rowData.rightLine; - if (leftLineData.textLineType == TextLineData::TextLine) { - if (leftStartWithNewLine) { - leftText += QLatin1Char('\n'); - leftPos++; - } - if (leftSeparatorCount) { - leftText += QString(leftSeparatorCount, QChar::LineSeparator); - leftSeparatorCount = 0; - leftPos += leftSeparatorCount; - } - if (m_leftSafePosHack < 0) - m_leftSafePosHack = leftPos; - leftPos += leftLineData.text.count(); leftText += leftLineData.text; - leftStartWithNewLine = true; leftLineNumber++; - m_leftEditor->setLineNumber(leftBlockNumber, QString::number(leftLineNumber)); - leftBlockNumber++; + m_leftEditor->setLineNumber(blockNumber, QString::number(leftLineNumber)); } else if (leftLineData.textLineType == TextLineData::Separator) { - leftSeparatorCount++; + m_leftEditor->setSeparator(blockNumber, true); } if (rightLineData.textLineType == TextLineData::TextLine) { - if (rightStartWithNewLine) { - rightText += QLatin1Char('\n'); - rightPos++; - } - if (rightSeparatorCount) { - rightText += QString(rightSeparatorCount, QChar::LineSeparator); - rightSeparatorCount = 0; - rightPos += rightSeparatorCount; - } - if (m_rightSafePosHack < 0) - m_rightSafePosHack = rightPos; - rightPos += leftLineData.text.count(); rightText += rightLineData.text; - rightStartWithNewLine = true; rightLineNumber++; - m_rightEditor->setLineNumber(rightBlockNumber, QString::number(rightLineNumber)); - rightBlockNumber++; + m_rightEditor->setLineNumber(blockNumber, QString::number(rightLineNumber)); } else if (rightLineData.textLineType == TextLineData::Separator) { - rightSeparatorCount++; - } - - } - if (i == m_contextFileData.chunks.count() - 1) { - if (leftSeparatorCount) { - if (leftStartWithNewLine) { - leftText += QLatin1Char('\n'); - leftPos++; - } - leftText += QString(leftSeparatorCount, QChar::LineSeparator); - } - if (rightSeparatorCount) { - if (rightStartWithNewLine) { - rightText += QLatin1Char('\n'); - rightPos++; - } - rightText += QString(rightSeparatorCount, QChar::LineSeparator); + m_rightEditor->setSeparator(blockNumber, true); } + leftText += separator; + rightText += separator; + blockNumber++; } } // int ela2 = time.elapsed(); @@ -834,6 +752,38 @@ void DiffEditorWidget::showDiff() // int ela4 = time.elapsed(); colorDiff(m_contextFileData); + + blockNumber = 0; + for (int i = 0; i < m_contextFileData.chunks.count(); i++) { + ChunkData chunkData = m_contextFileData.chunks.at(i); + if (!chunkData.alwaysShown) { + blockNumber++; + QTextBlock leftBlock = m_leftEditor->document()->findBlockByNumber(blockNumber); + for (int j = 0; j < chunkData.rows.count(); j++) { + leftBlock.setVisible(false); + leftBlock.setLineCount(0); + leftBlock = leftBlock.next(); + } + QTextBlock rightBlock = m_rightEditor->document()->findBlockByNumber(blockNumber); + for (int j = 0; j < chunkData.rows.count(); j++) { + rightBlock.setVisible(false); + rightBlock.setLineCount(0); + rightBlock = rightBlock.next(); + } + } + blockNumber += chunkData.rows.count(); + } + BaseTextDocumentLayout *leftLayout = qobject_cast<BaseTextDocumentLayout *>(m_leftEditor->document()->documentLayout()); + if (leftLayout) { + leftLayout->requestUpdate(); + leftLayout->emitDocumentSizeChanged(); + } + BaseTextDocumentLayout *rightLayout = qobject_cast<BaseTextDocumentLayout *>(m_rightEditor->document()->documentLayout()); + if (rightLayout) { + rightLayout->requestUpdate(); + rightLayout->emitDocumentSizeChanged(); + } + // int ela5 = time.elapsed(); m_leftEditor->verticalScrollBar()->setValue(verticalValue); @@ -898,8 +848,10 @@ void DiffEditorWidget::colorDiff(const FileData &fileData) int leftPos = 0; int rightPos = 0; // startPos, endPos - QMap<int, int> leftChangedPos; - QMap<int, int> rightChangedPos; + QMap<int, int> leftLinePos; + QMap<int, int> rightLinePos; + QMap<int, int> leftCharPos; + QMap<int, int> rightCharPos; QMap<int, int> leftSkippedPos; QMap<int, int> rightSkippedPos; QMap<int, int> leftChunkPos; @@ -908,20 +860,36 @@ void DiffEditorWidget::colorDiff(const FileData &fileData) int rightLastDiffBlockStartPos = 0; int leftLastSkippedBlockStartPos = 0; int rightLastSkippedBlockStartPos = 0; + int chunkOffset = 0; for (int i = 0; i < fileData.chunks.count(); i++) { ChunkData chunkData = fileData.chunks.at(i); - if (chunkData.skippedLinesBefore) { + if (!chunkData.alwaysShown) { leftChunkPos[leftPos] = leftPos + 1; rightChunkPos[rightPos] = rightPos + 1; leftPos++; // for chunk line rightPos++; // for chunk line + chunkOffset++; } leftLastDiffBlockStartPos = leftPos; rightLastDiffBlockStartPos = rightPos; leftLastSkippedBlockStartPos = leftPos; rightLastSkippedBlockStartPos = rightPos; + QMapIterator<int, int> itLeft(chunkData.changedLeftPositions); + while (itLeft.hasNext()) { + itLeft.next(); + + leftCharPos[itLeft.key() + chunkOffset] = itLeft.value() + chunkOffset; + } + + QMapIterator<int, int> itRight(chunkData.changedRightPositions); + while (itRight.hasNext()) { + itRight.next(); + + rightCharPos[itRight.key() + chunkOffset] = itRight.value() + chunkOffset; + } + for (int j = 0; j < chunkData.rows.count(); j++) { RowData rowData = chunkData.rows.at(j); @@ -930,14 +898,14 @@ void DiffEditorWidget::colorDiff(const FileData &fileData) if (!rowData.equal) { if (rowData.leftLine.textLineType == TextLineData::TextLine) { - leftChangedPos[leftLastDiffBlockStartPos] = leftPos; + leftLinePos[leftLastDiffBlockStartPos] = leftPos; leftLastSkippedBlockStartPos = leftPos; } else { leftSkippedPos[leftLastSkippedBlockStartPos] = leftPos; leftLastDiffBlockStartPos = leftPos; } if (rowData.rightLine.textLineType == TextLineData::TextLine) { - rightChangedPos[rightLastDiffBlockStartPos] = rightPos; + rightLinePos[rightLastDiffBlockStartPos] = rightPos; rightLastSkippedBlockStartPos = rightPos; } else { rightSkippedPos[rightLastSkippedBlockStartPos] = rightPos; @@ -956,26 +924,22 @@ void DiffEditorWidget::colorDiff(const FileData &fileData) QTextCursor rightCursor = m_rightEditor->textCursor(); QList<QTextEdit::ExtraSelection> leftSelections - = colorPositions(leftLineFormat, leftCursor, leftChangedPos); + = colorPositions(leftLineFormat, leftCursor, leftLinePos); leftSelections += colorPositions(spanLineFormat, leftCursor, leftSkippedPos); leftSelections += colorPositions(chunkLineFormat, leftCursor, leftChunkPos); + leftSelections + += colorPositions(leftCharFormat, leftCursor, leftCharPos); QList<QTextEdit::ExtraSelection> rightSelections - = colorPositions(rightLineFormat, rightCursor, rightChangedPos); + = colorPositions(rightLineFormat, rightCursor, rightLinePos); rightSelections += colorPositions(spanLineFormat, rightCursor, rightSkippedPos); rightSelections += colorPositions(chunkLineFormat, rightCursor, rightChunkPos); - - for (int i = 0; i < fileData.chunks.count(); i++) { - ChunkData chunkData = fileData.chunks.at(i); - leftSelections - += colorPositions(leftCharFormat, leftCursor, chunkData.changedLeftPositions); - rightSelections - += colorPositions(rightCharFormat, rightCursor, chunkData.changedRightPositions); - } + rightSelections + += colorPositions(rightCharFormat, rightCursor, rightCharPos); m_leftEditor->setExtraSelections(BaseTextEditorWidget::OtherSelection, m_leftEditor->extraSelections(BaseTextEditorWidget::OtherSelection) |