LogicStuff
LogicStuff

Reputation: 19617

QSyntaxHighlighter - text selection overrides style

I'm making a custom code editor with QPlainTextEdit and QSyntaxHighlighter and I've encountered a glitch. I'd like to preserve syntax highlighting even within a selection. However, colors of the selection (environment colors) override the colors of the text highlighted by QSyntaxHighlighter and html tags. Other attributes like font family are preserved.


Example:

No selection:             Selection:
Unselected      Selected
                                   (I'd like Hello to be green and World! to be black)


I've also tried to set the style sheet to:

QPlainTextEdit {
    selection-color: rgba(0, 0, 0, 0);
    selection-background-color: lightblue;
}

Result:

enter image description here
Background color overlays the text and well, text color with alpha = 0 is not visible. I've done that just to rule out the idea that syntax color persists under selection-color. It is in fact overlaid by selection-background-color.
Edit: No, if I also set selection-background-color to rgba(0, 0, 0, 0), there's no selection and there's no text in that selection. All I see is the background.


Approach of the following snippet which makes whole cursor's line highlighted seems like the way to go, but I would basically end up reimplementing all the selection mechanics...

QList<QTextEdit::ExtraSelection> extraSelections;
QTextCursor cursor = textCursor();

QTextEdit::ExtraSelection selection;
selection.format.setBackground(lineHighlightColor_);
selection.format.setProperty(QTextFormat::FullWidthSelection, true);
selection.cursor = cursor;
selection.cursor.clearSelection();
extraSelections.append(selection);
setExtraSelections(extraSelections);

Is there any simpler solution to this?

Upvotes: 23

Views: 1778

Answers (1)

Bastien Thonnat
Bastien Thonnat

Reputation: 561

the problem reside here :

https://github.com/qt/qtbase/blob/e03b64c5b1eeebfbbb94d67eb9a9c1d35eaba0bb/src/widgets/widgets/qplaintextedit.cpp#L1939-L1945

QPlainTextEdit use context palette instead of current selection format.

You could create one class inheritings from QPlainTextEdit and override paintEvent

signature :

void paintEvent(QPaintEvent *);

Copy the body of the function from github inside the new class paintEvent function :

https://github.com/qt/qtbase/blob/e03b64c5b1eeebfbbb94d67eb9a9c1d35eaba0bb/src/widgets/widgets/qplaintextedit.cpp#L1883-L2013

add this function in your cpp file before paintEvent (PlainTextEdit paintEvent need it) :

https://github.com/qt/qtbase/blob/e03b64c5b1eeebfbbb94d67eb9a9c1d35eaba0bb/src/widgets/widgets/qplaintextedit.cpp#L1861-L1876

add

#include <QPainter>
#include <QTextBlock>
#include <QScrollBar>

and replace each occurrence of

o.format = range.format;

whith

o.format = range.cursor.blockCharFormat();
o.format.setBackground(QColor(your selection color with alpha));

with that your custom PlainTextEdit check the format linked to the current char instead of your PlainTextEdit palette

(beware (L)GPL licence, I just give an opensource workaround)

Upvotes: 5

Related Questions