113 lines
3.1 KiB
C++
113 lines
3.1 KiB
C++
#ifndef LINENUMBERAREA_H
|
|
#define LINENUMBERAREA_H
|
|
|
|
#include <QDebug>
|
|
#include <QPainter>
|
|
#include <QScrollBar>
|
|
#include <QWidget>
|
|
|
|
#include "qmarkdowntextedit.h"
|
|
|
|
class LineNumArea final : public QWidget {
|
|
Q_OBJECT
|
|
|
|
public:
|
|
explicit LineNumArea(QMarkdownTextEdit *parent)
|
|
: QWidget(parent), textEdit(parent) {
|
|
Q_ASSERT(parent);
|
|
|
|
_currentLineColor = QColor(QStringLiteral("#eef067"));
|
|
_otherLinesColor = QColor(QStringLiteral("#a6a6a6"));
|
|
setHidden(true);
|
|
|
|
// We always use fixed font to avoid "width" issues
|
|
setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
|
|
}
|
|
|
|
void setCurrentLineColor(QColor color) { _currentLineColor = color; }
|
|
|
|
void setOtherLineColor(QColor color) {
|
|
_otherLinesColor = std::move(color);
|
|
}
|
|
|
|
int lineNumAreaWidth() const {
|
|
if (!enabled) {
|
|
return 0;
|
|
}
|
|
|
|
int digits = 2;
|
|
int max = std::max(1, textEdit->blockCount());
|
|
while (max >= 10) {
|
|
max /= 10;
|
|
++digits;
|
|
}
|
|
|
|
#if QT_VERSION >= 0x050B00
|
|
int space =
|
|
13 + textEdit->fontMetrics().horizontalAdvance(u'9') * digits;
|
|
#else
|
|
int space =
|
|
13 + textEdit->fontMetrics().width(QLatin1Char('9')) * digits;
|
|
#endif
|
|
|
|
return space;
|
|
}
|
|
|
|
bool isLineNumAreaEnabled() const { return enabled; }
|
|
|
|
void setLineNumAreaEnabled(bool e) {
|
|
enabled = e;
|
|
setHidden(!e);
|
|
}
|
|
|
|
QSize sizeHint() const override { return {lineNumAreaWidth(), 0}; }
|
|
|
|
protected:
|
|
void paintEvent(QPaintEvent *event) override {
|
|
QPainter painter(this);
|
|
|
|
painter.fillRect(event->rect(),
|
|
palette().color(QPalette::Active, QPalette::Window));
|
|
|
|
auto block = textEdit->firstVisibleBlock();
|
|
int blockNumber = block.blockNumber();
|
|
qreal top = textEdit->blockBoundingGeometry(block)
|
|
.translated(textEdit->contentOffset())
|
|
.top();
|
|
// Maybe the top is not 0?
|
|
top += textEdit->viewportMargins().top();
|
|
qreal bottom = top;
|
|
|
|
const QPen currentLine = _currentLineColor;
|
|
const QPen otherLines = _otherLinesColor;
|
|
painter.setFont(font());
|
|
|
|
while (block.isValid() && top <= event->rect().bottom()) {
|
|
top = bottom;
|
|
bottom = top + textEdit->blockBoundingRect(block).height();
|
|
if (block.isVisible() && bottom >= event->rect().top()) {
|
|
QString number = QString::number(blockNumber + 1);
|
|
|
|
auto isCurrentLine =
|
|
textEdit->textCursor().blockNumber() == blockNumber;
|
|
painter.setPen(isCurrentLine ? currentLine : otherLines);
|
|
|
|
painter.drawText(-5, top, sizeHint().width(),
|
|
textEdit->fontMetrics().height(),
|
|
Qt::AlignRight, number);
|
|
}
|
|
|
|
block = block.next();
|
|
++blockNumber;
|
|
}
|
|
}
|
|
|
|
private:
|
|
bool enabled = false;
|
|
QMarkdownTextEdit *textEdit;
|
|
QColor _currentLineColor;
|
|
QColor _otherLinesColor;
|
|
};
|
|
|
|
#endif // LINENUMBERAREA_H
|