Refactor painting of editor gutter
This commit is contained in:
parent
e082a5731d
commit
a5563949e5
7 changed files with 188 additions and 85 deletions
|
|
@ -86,8 +86,8 @@ void CodeEditor::onTextChanged()
|
|||
|
||||
void CodeEditor::addErrorMarker(int position, int length)
|
||||
{
|
||||
QTextEdit::ExtraSelection selection;
|
||||
QColor lineColor = QColor(Qt::red).lighter(160);
|
||||
QTextEdit::ExtraSelection selection;
|
||||
QColor lineColor = QColor(Qt::red).lighter(160);
|
||||
selection.format.setBackground(lineColor);
|
||||
selection.format.setFontItalic(true);
|
||||
selection.cursor = textCursor();
|
||||
|
|
@ -120,45 +120,17 @@ void CodeEditor::updateExtraSelections()
|
|||
setExtraSelections(extraSelections);
|
||||
}
|
||||
|
||||
void CodeEditor::gutterAreaPaintEvent(QPaintEvent *event)
|
||||
void CodeEditor::drawGutterErrorMarker(QPainter &painter, int top)
|
||||
{
|
||||
QPainter painter(gutterArea);
|
||||
painter.fillRect(event->rect(), Qt::lightGray);
|
||||
int s = fontMetrics().height() - 8;
|
||||
painter.setBrush(QBrush(Qt::red));
|
||||
painter.drawEllipse(4, top + 4, s, s);
|
||||
|
||||
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);
|
||||
|
||||
if (errorLines.count(blockNumber) > 0)
|
||||
{
|
||||
int s = fontMetrics().height() - 8;
|
||||
painter.setBrush(QBrush(Qt::red));
|
||||
painter.drawEllipse(4, top + 4, s, s);
|
||||
}
|
||||
}
|
||||
|
||||
block = block.next();
|
||||
top = bottom;
|
||||
bottom = top + (int) blockBoundingRect(block).height();
|
||||
++blockNumber;
|
||||
}
|
||||
bool CodeEditor::lineHasError(int blockNumber) const
|
||||
{
|
||||
return errorLines.count(blockNumber) > 0;
|
||||
}
|
||||
|
||||
void CodeEditor::keyPressEvent(QKeyEvent *e)
|
||||
|
|
@ -194,6 +166,8 @@ void CodeEditor::keyPressEvent(QKeyEvent *e)
|
|||
QPlainTextEdit::keyPressEvent(e);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool CodeEditor::indentSelection(bool indent)
|
||||
{
|
||||
auto cursor = textCursor();
|
||||
|
|
@ -222,63 +196,75 @@ bool CodeEditor::indentSelection(bool indent)
|
|||
{
|
||||
cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::MoveAnchor);
|
||||
if (indent)
|
||||
{
|
||||
if (m_useTab)
|
||||
cursor.insertText("\t");
|
||||
else
|
||||
cursor.insertText(QString(m_tabSize, ' '));
|
||||
}
|
||||
insertIndentation(cursor);
|
||||
else
|
||||
{
|
||||
// remove tab if there is a tab
|
||||
cursor.movePosition(QTextCursor::EndOfLine, QTextCursor::KeepAnchor);
|
||||
const QString text = cursor.selectedText();
|
||||
int index = 0;
|
||||
int pos = 0;
|
||||
while (pos < m_tabSize && index < text.length())
|
||||
{
|
||||
QChar c = text[index++];
|
||||
if (c == ' ')
|
||||
++pos;
|
||||
else if (c == '\t')
|
||||
pos = ((pos + m_tabSize) / m_tabSize) * m_tabSize;
|
||||
else
|
||||
{
|
||||
--index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::MoveAnchor);
|
||||
for (int i = 0; i < index; ++i)
|
||||
cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor);
|
||||
cursor.removeSelectedText();
|
||||
}
|
||||
removeIndentation(cursor);
|
||||
cursor.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor);
|
||||
}
|
||||
cursor.endEditBlock();
|
||||
|
||||
cursor.setPosition(first_pos, QTextCursor::MoveAnchor);
|
||||
cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::MoveAnchor);
|
||||
while(cursor.block().blockNumber() < end_block)
|
||||
cursor.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor);
|
||||
|
||||
cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
|
||||
makeSelection(cursor, first_pos, end_block);
|
||||
|
||||
setTextCursor(cursor);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CodeEditor::insertIndentation(QTextCursor &cursor)
|
||||
{
|
||||
if (m_useTab)
|
||||
cursor.insertText("\t");
|
||||
else
|
||||
cursor.insertText(QString(m_tabSize, ' '));
|
||||
}
|
||||
|
||||
void CodeEditor::removeIndentation(QTextCursor &cursor)
|
||||
{
|
||||
// remove tab if there is a tab
|
||||
cursor.movePosition(QTextCursor::EndOfLine, QTextCursor::KeepAnchor);
|
||||
const QString text = cursor.selectedText();
|
||||
int index = 0;
|
||||
int pos = 0;
|
||||
while (pos < m_tabSize && index < text.length())
|
||||
{
|
||||
QChar c = text[index++];
|
||||
if (c == ' ')
|
||||
++pos;
|
||||
else if (c == '\t')
|
||||
pos = ((pos + m_tabSize) / m_tabSize) * m_tabSize;
|
||||
else
|
||||
{
|
||||
--index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::MoveAnchor);
|
||||
for (int i = 0; i < index; ++i)
|
||||
cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor);
|
||||
cursor.removeSelectedText();
|
||||
|
||||
}
|
||||
|
||||
void CodeEditor::makeSelection(QTextCursor &cursor, int first_pos, int end_block)
|
||||
{
|
||||
cursor.setPosition(first_pos, QTextCursor::MoveAnchor);
|
||||
cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::MoveAnchor);
|
||||
while(cursor.block().blockNumber() < end_block)
|
||||
cursor.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor);
|
||||
|
||||
cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
|
||||
}
|
||||
|
||||
void CodeEditor::setFont(const QFont &f)
|
||||
{
|
||||
QWidget::setFont(f);
|
||||
auto orig_tab = m_tabSize;
|
||||
m_tabSize = 0;
|
||||
setTabSize(orig_tab);
|
||||
QWidget::setFont(f);
|
||||
auto orig_tab = m_tabSize;
|
||||
m_tabSize = 0;
|
||||
setTabSize(orig_tab);
|
||||
}
|
||||
|
||||
void CodeEditor::setTabSize(int chars)
|
||||
{
|
||||
m_tabSize = chars;
|
||||
int pixels = fontMetrics().horizontalAdvance(QString(chars, '0'));
|
||||
this->setTabStopDistance(pixels);
|
||||
m_tabSize = chars;
|
||||
int pixels = fontMetrics().horizontalAdvance(QString(chars, '0'));
|
||||
this->setTabStopDistance(pixels);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue