Skip to content

Commit 432180e

Browse files
committed
SqlTextEdit: Show line numbers
Show line numbers in the SqlTextEdit widget. This code is based on the CodeEditor example from the Qt documentation.
1 parent 61ee8b4 commit 432180e

File tree

2 files changed

+99
-6
lines changed

2 files changed

+99
-6
lines changed

src/sqltextedit.cpp

Lines changed: 79 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
#include <QAbstractItemView>
66
#include <QCompleter>
77
#include <QScrollBar>
8-
//#include <QDebug>
8+
#include <QPainter>
9+
#include <QTextBlock>
910

1011
SqlTextEdit::SqlTextEdit(QWidget* parent) :
11-
QTextEdit(parent), m_Completer(0), m_defaultCompleterModel(0)
12+
QPlainTextEdit(parent), m_Completer(0), m_defaultCompleterModel(0)
1213
{
1314
// basic auto completer for sqliteedit
1415
m_Completer = new QCompleter(this);
@@ -17,10 +18,16 @@ SqlTextEdit::SqlTextEdit(QWidget* parent) :
1718
m_Completer->setWrapAround(false);
1819
m_Completer->setWidget(this);
1920

21+
// Create line number area
22+
lineNumberArea = new LineNumberArea(this);
23+
24+
connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth()));
25+
connect(this, SIGNAL(updateRequest(QRect,int)), this, SLOT(updateLineNumberArea(QRect,int)));
2026
connect(m_Completer, SIGNAL(activated(QString)), this, SLOT(insertCompletion(QString)));
2127
connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(highlightCurrentLine()));
2228

2329
highlightCurrentLine();
30+
updateLineNumberAreaWidth();
2431
}
2532

2633
SqlTextEdit::~SqlTextEdit()
@@ -111,6 +118,74 @@ void SqlTextEdit::highlightCurrentLine()
111118
setExtraSelections(extra_selections);
112119
}
113120

121+
int SqlTextEdit::lineNumberAreaWidth()
122+
{
123+
int digits = 1;
124+
int max = qMax(1, blockCount());
125+
while(max >= 10)
126+
{
127+
max /= 10;
128+
++digits;
129+
}
130+
131+
return 3 + fontMetrics().width(QLatin1Char('9')) * digits;
132+
}
133+
134+
void SqlTextEdit::updateLineNumberAreaWidth()
135+
{
136+
setViewportMargins(lineNumberAreaWidth(), 0, 0, 0);
137+
}
138+
139+
void SqlTextEdit::updateLineNumberArea(const QRect& rect, int dy)
140+
{
141+
if(dy)
142+
lineNumberArea->scroll(0, dy);
143+
else
144+
lineNumberArea->update(0, rect.y(), lineNumberArea->width(), rect.height());
145+
146+
if(rect.contains(viewport()->rect()))
147+
updateLineNumberAreaWidth();
148+
}
149+
150+
void SqlTextEdit::resizeEvent(QResizeEvent* e)
151+
{
152+
QPlainTextEdit::resizeEvent(e);
153+
154+
QRect cr = contentsRect();
155+
lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height()));
156+
}
157+
158+
void SqlTextEdit::LineNumberArea::paintEvent(QPaintEvent* event)
159+
{
160+
QPainter painter(this);
161+
painter.fillRect(event->rect(), Qt::lightGray);
162+
163+
QTextBlock block = parent->firstVisibleBlock();
164+
int blockNumber = block.blockNumber();
165+
int top = parent->blockBoundingGeometry(block).translated(parent->contentOffset()).top();
166+
int bottom = top + parent->blockBoundingRect(block).height();
167+
168+
while(block.isValid() && top <= event->rect().bottom())
169+
{
170+
if(block.isVisible() && bottom >= event->rect().top())
171+
{
172+
QString number = QString::number(blockNumber + 1);
173+
painter.setPen(Qt::black);
174+
painter.drawText(0, top, width(), fontMetrics().height(), Qt::AlignRight, number);
175+
}
176+
177+
block = block.next();
178+
top = bottom;
179+
bottom = top + parent->blockBoundingRect(block).height();
180+
blockNumber++;
181+
}
182+
}
183+
184+
QSize SqlTextEdit::LineNumberArea::sizeHint() const
185+
{
186+
return QSize(parent->lineNumberAreaWidth(), 0);
187+
}
188+
114189
namespace {
115190
bool isSqliteIdentifierChar(QChar c) {
116191
return c.isLetterOrNumber() || c == '.' || c == '_';
@@ -165,7 +240,7 @@ void SqlTextEdit::focusInEvent(QFocusEvent *e)
165240
{
166241
if (m_Completer)
167242
m_Completer->setWidget(this);
168-
QTextEdit::focusInEvent(e);
243+
QPlainTextEdit::focusInEvent(e);
169244
}
170245

171246
void SqlTextEdit::keyPressEvent(QKeyEvent *e)
@@ -187,7 +262,7 @@ void SqlTextEdit::keyPressEvent(QKeyEvent *e)
187262

188263
bool isShortcut = ((e->modifiers() & Qt::ControlModifier) && e->key() == Qt::Key_Space); // CTRL+SPACE
189264
if (!m_Completer || !isShortcut) // do not process the shortcut when we have a completer
190-
QTextEdit::keyPressEvent(e);
265+
QPlainTextEdit::keyPressEvent(e);
191266
const bool ctrlOrShift = e->modifiers() & (Qt::ControlModifier | Qt::ShiftModifier);
192267
const bool cursorKey = e->key() == Qt::Key_Left ||
193268
e->key() == Qt::Key_Up ||

src/sqltextedit.h

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#ifndef SQLTEXTEDIT_H
22
#define SQLTEXTEDIT_H
33

4-
#include <QTextEdit>
4+
#include <QPlainTextEdit>
55

66
class QCompleter;
77
class QAbstractItemModel;
@@ -11,7 +11,7 @@ class QAbstractItemModel;
1111
* With basic table and fieldname auto completion.
1212
* This class is based on the Qt custom completion example.
1313
*/
14-
class SqlTextEdit : public QTextEdit
14+
class SqlTextEdit : public QPlainTextEdit
1515
{
1616
Q_OBJECT
1717
public:
@@ -31,13 +31,31 @@ class SqlTextEdit : public QTextEdit
3131
protected:
3232
void keyPressEvent(QKeyEvent *e);
3333
void focusInEvent(QFocusEvent *e);
34+
void resizeEvent(QResizeEvent* event);
35+
36+
void lineNumberAreaPaintEvent(QPaintEvent* event);
37+
int lineNumberAreaWidth();
3438

3539
private:
40+
class LineNumberArea : public QWidget
41+
{
42+
public:
43+
LineNumberArea(SqlTextEdit *editor) : QWidget(editor), parent(editor) {}
44+
QSize sizeHint() const;
45+
46+
protected:
47+
void paintEvent(QPaintEvent* event);
48+
SqlTextEdit* parent;
49+
};
50+
51+
LineNumberArea* lineNumberArea;
3652
QString identifierUnderCursor() const;
3753

3854
private slots:
3955
void insertCompletion(const QString& completion);
4056
void highlightCurrentLine();
57+
void updateLineNumberAreaWidth();
58+
void updateLineNumberArea(const QRect& rect, int dy);
4159

4260
private:
4361
QCompleter* m_Completer;

0 commit comments

Comments
 (0)