Added a gutter and currentline highlighting to the SQL editor.

Currently gutter only shows linenumbers. Code is mostly from http://doc.qt.io/qt-5/qtwidgets-widgets-codeeditor-example.html

There is a little bit included in this commit from a first try to make toobars adept to the current tab.

Code #2
This commit is contained in:
eelke 2018-04-08 09:07:43 +02:00
parent 5e83094e6a
commit 47ee1857cd
15 changed files with 281 additions and 6 deletions

112
pglab/CodeEditor.cpp Normal file
View file

@ -0,0 +1,112 @@
#include "CodeEditor.h"
#include "EditorGutter.h"
#include <QPainter>
#include <QTextBlock>
//
// Adapted from codeeditor example
// http://doc.qt.io/qt-5/qtwidgets-widgets-codeeditor-example.html
//
// Used term gutter as I want to expand it to do other things to like error
// position marking.
//
CodeEditor::CodeEditor(QWidget *parent)
: QPlainTextEdit(parent)
, gutterArea(new EditorGutter(this))
{
connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateGutterAreaWidth(int)));
connect(this, SIGNAL(updateRequest(QRect,int)), this, SLOT(updateGutterArea(QRect,int)));
connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(highlightCurrentLine()));
updateGutterAreaWidth(0);
highlightCurrentLine();
}
int CodeEditor::gutterAreaWidth()
{
int digits = 1;
int max = qMax(1, blockCount());
while (max >= 10) {
max /= 10;
++digits;
}
int space = 3 + fontMetrics().width(QLatin1Char('9')) * digits;
return space;
}
void CodeEditor::updateGutterAreaWidth(int /* newBlockCount */)
{
setViewportMargins(gutterAreaWidth(), 0, 0, 0);
}
void CodeEditor::updateGutterArea(const QRect &rect, int dy)
{
if (dy)
gutterArea->scroll(0, dy);
else
gutterArea->update(0, rect.y(), gutterArea->width(), rect.height());
if (rect.contains(viewport()->rect()))
updateGutterAreaWidth(0);
}
void CodeEditor::resizeEvent(QResizeEvent *e)
{
QPlainTextEdit::resizeEvent(e);
QRect cr = contentsRect();
gutterArea->setGeometry(QRect(cr.left(), cr.top(), gutterAreaWidth(), cr.height()));
}
void CodeEditor::highlightCurrentLine()
{
QList<QTextEdit::ExtraSelection> extraSelections;
if (!isReadOnly()) {
QTextEdit::ExtraSelection selection;
QColor lineColor = QColor(Qt::yellow).lighter(160);
selection.format.setBackground(lineColor);
selection.format.setProperty(QTextFormat::FullWidthSelection, true);
selection.cursor = textCursor();
selection.cursor.clearSelection();
extraSelections.append(selection);
}
setExtraSelections(extraSelections);
}
void CodeEditor::gutterAreaPaintEvent(QPaintEvent *event)
{
QPainter painter(gutterArea);
painter.fillRect(event->rect(), Qt::lightGray);
QTextBlock block = firstVisibleBlock();
int blockNumber = block.blockNumber();
int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top();
int bottom = top + (int) blockBoundingRect(block).height();
// We will now loop through all visible lines and paint the line numbers in the
// extra area for each line. Notice that in a plain text edit each line will
// consist of one QTextBlock; though, if line wrapping is enabled, a line may span
// several rows in the text edit's viewport.
//
// We get the top and bottom y-coordinate of the first text block, and adjust these
// values by the height of the current text block in each iteration in the loop.
while (block.isValid() && top <= event->rect().bottom()) {
if (block.isVisible() && bottom >= event->rect().top()) {
QString number = QString::number(blockNumber + 1);
painter.setPen(Qt::black);
painter.drawText(0, top, gutterArea->width(), fontMetrics().height(),
Qt::AlignRight, number);
}
block = block.next();
top = bottom;
bottom = top + (int) blockBoundingRect(block).height();
++blockNumber;
}
}