125 lines
3.1 KiB
C++
125 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
|