Commit f9fdf079 authored by Waqar Ahmed's avatar Waqar Ahmed
Browse files

Diff: Allow folding hunks

parent e48c0369
Pipeline #227160 canceled with stage
in 1 minute and 1 second
......@@ -240,7 +240,7 @@ void DiffEditor::paintEvent(QPaintEvent *e)
auto layout = block.layout();
auto hl = highlightingForLine(block.blockNumber());
if (hl && layout) {
if (block.isVisible() && hl && layout) {
const auto changes = hl->changes;
for (auto c : changes) {
// full line background is colored
......@@ -282,7 +282,7 @@ void DiffEditor::paintEvent(QPaintEvent *e)
}
}
if (m_diffWidget->isHunk(block.blockNumber())) {
if (isHunkLine(block.blockNumber())) {
p.save();
QPen pen;
pen.setColor(hunkSeparatorColor);
......@@ -349,3 +349,42 @@ void DiffEditor::restoreState(State s)
cursor.setPosition(qMin(cursor.document()->characterCount(), s.cursorPosition));
setTextCursor(cursor);
}
bool DiffEditor::isHunkLine(int line) const
{
return m_diffWidget->isHunk(line);
}
bool DiffEditor::isHunkFolded(int blockNumber)
{
Q_ASSERT(isHunkLine(blockNumber));
const auto block = document()->findBlockByNumber(blockNumber).next();
return block.isValid() && !block.isVisible();
}
void DiffEditor::toggleFoldHunk(int blockNumber)
{
Q_ASSERT(isHunkLine(blockNumber));
int count = m_diffWidget->hunkLineCount(blockNumber);
if (count == 0) {
return;
}
if (count == -1) {
count = blockCount() - blockNumber;
}
auto block = document()->findBlockByNumber(blockNumber).next();
int i = 0;
bool visible = !block.isVisible();
while (true) {
i++;
if (i == count || !block.isValid()) {
break;
}
block.setVisible(visible);
block = block.next();
}
viewport()->update();
m_lineNumArea->update();
}
......@@ -75,6 +75,10 @@ public:
KTextEditor::Range selectionRange() const;
bool isHunkLine(int line) const;
void toggleFoldHunk(int block);
bool isHunkFolded(int blockNumber);
protected:
void resizeEvent(QResizeEvent *event) override;
void paintEvent(QPaintEvent *e) override;
......
......@@ -9,6 +9,7 @@
#include <QTextBlock>
#include <KTextEditor/Editor>
// #include <KColorUtils>
static constexpr int Margin = 4;
......@@ -51,7 +52,38 @@ void LineNumArea::setLineNumData(QVector<int> data)
QSize LineNumArea::sizeHint() const
{
return {lineNumAreaWidth(), 0};
return {lineNumAreaWidth() + textEdit->fontMetrics().height(), 0};
}
static void paintTriangle(QPainter &painter, QColor c, int xOffset, int yOffset, int width, int height, bool open)
{
painter.setRenderHint(QPainter::Antialiasing);
qreal size = qMin(width, height);
QPen pen;
pen.setJoinStyle(Qt::RoundJoin);
pen.setColor(c);
pen.setWidthF(1.5);
painter.setPen(pen);
painter.setBrush(c);
// let some border, if possible
size *= 0.6;
qreal halfSize = size / 2;
qreal halfSizeP = halfSize * 0.6;
QPointF middle(xOffset + (qreal)width / 2, yOffset + (qreal)height / 2);
if (open) {
QPointF points[3] = {middle + QPointF(-halfSize, -halfSizeP), middle + QPointF(halfSize, -halfSizeP), middle + QPointF(0, halfSizeP)};
painter.drawConvexPolygon(points, 3);
} else {
QPointF points[3] = {middle + QPointF(-halfSizeP, -halfSize), middle + QPointF(-halfSizeP, halfSize), middle + QPointF(halfSizeP, 0)};
painter.drawConvexPolygon(points, 3);
}
painter.setRenderHint(QPainter::Antialiasing, false);
}
void LineNumArea::paintEvent(QPaintEvent *event)
......@@ -74,6 +106,8 @@ void LineNumArea::paintEvent(QPaintEvent *event)
const QPen otherLines = m_otherLinesColor;
painter.setFont(font());
const int w = lineNumAreaWidth();
while (block.isValid() && top <= event->rect().bottom()) {
top = bottom;
bottom = top + textEdit->blockBoundingRect(block).height();
......@@ -83,9 +117,15 @@ void LineNumArea::paintEvent(QPaintEvent *event)
const QString number = QString::number(n);
auto isCurrentLine = textEdit->textCursor().blockNumber() == blockNumber;
painter.setPen(isCurrentLine ? currentLine : otherLines);
QRect numRect(0, top, sizeHint().width(), textEdit->fontMetrics().height());
QRect numRect(0, top, w, textEdit->fontMetrics().height());
numRect.adjust(0, 0, -(Margin * 2), 0);
painter.drawText(numRect, Qt::AlignRight | Qt::AlignVCenter | Qt::TextDontClip, number);
} else if (textEdit->isHunkLine(blockNumber)) {
const int x = rect().width() - (textEdit->fontMetrics().height() + Margin);
const int y = top;
const int width = textEdit->fontMetrics().height();
const int height = width;
paintTriangle(painter, m_otherLinesColor, x, y, width, height, !textEdit->isHunkFolded(blockNumber));
}
}
......@@ -96,3 +136,19 @@ void LineNumArea::paintEvent(QPaintEvent *event)
painter.setPen(m_borderColor);
painter.drawLine(rect().topRight() - QPoint(1, 0), rect().bottomRight() - QPoint(1, 0));
}
void LineNumArea::mousePressEvent(QMouseEvent *e)
{
auto pos = e->pos();
auto r = rect();
r.setLeft(lineNumAreaWidth());
if (!r.contains(pos)) {
QWidget::mousePressEvent(e);
return;
}
int block = textEdit->cursorForPosition(pos).block().blockNumber();
if (textEdit->isHunkLine(block)) {
textEdit->toggleFoldHunk(block);
}
}
......@@ -24,6 +24,7 @@ public:
protected:
void paintEvent(QPaintEvent *event) override;
void mousePressEvent(QMouseEvent *e) override;
private:
class DiffEditor *const textEdit;
......
......@@ -794,3 +794,22 @@ bool DiffWidget::isHunk(const int line) const
return l.line == line;
});
}
int DiffWidget::hunkLineCount(int hunkLine)
{
for (int i = 0; i < m_lineToDiffHunkLine.size(); ++i) {
const auto h = m_lineToDiffHunkLine.at(i);
if (h.line == hunkLine) {
// last hunk?
if (i + 1 >= m_lineToDiffHunkLine.size()) {
return -1;
}
auto nextHunk = m_lineToDiffHunkLine.at(i + 1);
auto count = nextHunk.line - h.line;
count -= 1; // one separator line is ignored
return count;
}
}
return 0;
}
......@@ -34,6 +34,7 @@ public:
{
return m_linesWithFileName.contains(line);
}
int hunkLineCount(int hunkLine);
private:
void clearData();
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment