Syntax highlighter to QPlainTextEdit
-
How make highlighter? Where are samples of highlighters?
I am using /usr/include/KF5/KSyntaxHighlighting/
Highlighters to Kate are in xml format: https://invent.kde.org/frameworks/syntax-highlighting/-/tree/master/data/syntax
this means, it uses general syntax highlighter which read xml?
How can I use highlighter without KF5 ? -
How make highlighter? Where are samples of highlighters?
I am using /usr/include/KF5/KSyntaxHighlighting/
Highlighters to Kate are in xml format: https://invent.kde.org/frameworks/syntax-highlighting/-/tree/master/data/syntax
this means, it uses general syntax highlighter which read xml?
How can I use highlighter without KF5 ?@AndrzejB said in Syntax highlighter to QPlainTextEdit:
Where are samples of highlighters?
How can I use highlighter without KF5.https://doc.qt.io/qt-5/qtwidgets-richtext-syntaxhighlighter-example.html
https://doc.qt.io/qt-6/qtwidgets-richtext-syntaxhighlighter-example.html -
Highlighter can also enable code folding? How it implement in highlighter? Code folding can't be implement by regular expression, must be stack?
-
Kf5 extension has folding:
SyntaxHighlighterPrivate::foldingRegion
in
https://invent.kde.org/frameworks/syntax-highlighting/-/blob/master/src/lib/syntaxhighlighter.cpp -
Kf5 extension has folding:
SyntaxHighlighterPrivate::foldingRegion
in
https://invent.kde.org/frameworks/syntax-highlighting/-/blob/master/src/lib/syntaxhighlighter.cpp -
OK, I prefer KF5 Highlighters, but have issues
- I want to better know QSyntaxHighlighter and highlighting process
- sometimes I need only a few syntax but more control with syntax
- if is possible apply QSyntaxHighlighter not only to QPlainTextEdit, but also to other, for example my viewer?
- KF5 and Windows? I prefer Linux, but is well to write portable appllcations.
-
Hi,
KF5 is also available on Windows.
Out of curiosity, why not use KDE's KTextEditor ? -
I compiled example from
Qt/Examples/Qt-6.2.4/widgets/richtext/syntaxhighlighter/
In source file Qt/6.2.4/Src/qtbase/src/gui/text/qsyntaxhighlighter.cpp isvoid QSyntaxHighlighter::setDocument(QTextDocument *doc) { Q_D(QSyntaxHighlighter); if (d->doc) { disconnect(d->doc, SIGNAL(contentsChange(int,int,int)), this, SLOT(_q_reformatBlocks(int,int,int))); QTextCursor cursor(d->doc); cursor.beginEditBlock(); for (QTextBlock blk = d->doc->begin(); blk.isValid(); blk = blk.next()) blk.layout()->clearFormats(); cursor.endEditBlock(); } d->doc = doc; if (d->doc) { connect(d->doc, SIGNAL(contentsChange(int,int,int)), this, SLOT(_q_reformatBlocks(int,int,int))); if (!d->doc->isEmpty()) { d->rehighlightPending = true; QTimer::singleShot(0, this, SLOT(_q_delayedRehighlight())); } } }
Where is defined and set "d" variable? It must be PlainTextEditor or can be my own control?
whats is class QTextDocument? -
I compiled example from
Qt/Examples/Qt-6.2.4/widgets/richtext/syntaxhighlighter/
In source file Qt/6.2.4/Src/qtbase/src/gui/text/qsyntaxhighlighter.cpp isvoid QSyntaxHighlighter::setDocument(QTextDocument *doc) { Q_D(QSyntaxHighlighter); if (d->doc) { disconnect(d->doc, SIGNAL(contentsChange(int,int,int)), this, SLOT(_q_reformatBlocks(int,int,int))); QTextCursor cursor(d->doc); cursor.beginEditBlock(); for (QTextBlock blk = d->doc->begin(); blk.isValid(); blk = blk.next()) blk.layout()->clearFormats(); cursor.endEditBlock(); } d->doc = doc; if (d->doc) { connect(d->doc, SIGNAL(contentsChange(int,int,int)), this, SLOT(_q_reformatBlocks(int,int,int))); if (!d->doc->isEmpty()) { d->rehighlightPending = true; QTimer::singleShot(0, this, SLOT(_q_delayedRehighlight())); } } }
Where is defined and set "d" variable? It must be PlainTextEditor or can be my own control?
whats is class QTextDocument?@AndrzejB said in Syntax highlighter to QPlainTextEdit:
Where is defined and set "d" variable?
From the
Q_D(QSyntaxHighlighter);
line. See e.g. https://wiki.qt.io/D-Pointer.It must be PlainTextEditor or can be my own control?
No.
whats is class QTextDocument?
See void QSyntaxHighlighter::setDocument(QTextDocument *doc). It is the document the
QSyntaxHighlighter
is working on. -
Example of mpergand in thread "How to use scrollbars in my component?" will good start point for exercise.
I wrote simple in-memory text viewer with QScrollArea::
main.cpp#include <QApplication> #include <QMainWindow> #include <QScrollArea> #include "FileViewer.h" #include "FileViewer.h" using namespace std; int main(int argc, char *argv[]) { QApplication app(argc, argv); QMainWindow textWindow; auto scrollArea=new QScrollArea; textWindow.setCentralWidget(scrollArea); auto fileViewer=new FileViewer; scrollArea->setWidget(fileViewer); string filepath = "../main.cpp"; if(!fileViewer->setFile(filepath)) // file path of your big file { qDebug()<<filepath.c_str()<<"Error openning the file!"; } textWindow.resize(600, 600); textWindow.show(); return app.exec(); }
FileViewer.h
#ifndef FILEVIEWER_H #define FILEVIEWER_H #include <QWidget> class FileViewer : public QWidget { Q_OBJECT public: explicit FileViewer(QWidget *parent = nullptr); bool setFile(const std::string& filepath); private: std::vector<std::string> lines; static std::vector<std::string> readLines(std::string filename); void paintEvent(QPaintEvent* ev); int _LineHeight; // height of a line in pixel }; #endif // FILEVIEWER_H
FileViewer.cpp
#include "FileViewer.h" #include <QFontMetrics> #include <QPainter> #include <QPaintEvent> #include <QDebug> #include <iostream> #include <fstream> using namespace std; FileViewer::FileViewer(QWidget *parent) : QWidget(parent) { //setVisible(true); } bool FileViewer::setFile(const string &filepath) { lines = readLines(filepath); // height of a line in the default font _LineHeight=fontMetrics().height(); resize(800, _LineHeight*lines.size()); return true; } void FileViewer::paintEvent(QPaintEvent *ev) { QPainter painter(this); painter.setPen(Qt::black); auto reg = ev->region(); int originY=reg.boundingRect().topLeft().y(); int endY=reg.boundingRect().bottomLeft().y(); int firstLine=originY/_LineHeight; int lastLine=endY/_LineHeight+1; //qDebug()<<firstLine<<lastLine; for(int l=firstLine; l<lastLine; l++) { const QString str=QString(lines[l].c_str()); QRect rec=fontMetrics().boundingRect(str); /*if(rec.width()+20>_WidestLine) { _WidestLine=rec.width()+20; resize(_WidestLine,_lineCount*_LineHeight); }*/ painter.drawText(QPoint(10,originY+_LineHeight), str); originY+=_LineHeight; } painter.drawRect(reg.boundingRect().adjusted(1,1,-2,-2)); } vector<string> FileViewer::readLines(string filename) { ifstream infile(filename); vector<string> v; string line; bool readedNewline; if (infile.peek() != EOF) while(true) { readedNewline = std::getline(infile, line).good(); v.push_back(line); if (!readedNewline) break; } return v; }
Is maximum simple, only view lines. How to add syntax highlighter? Fileviewer must be descendant of QTextDocument?
Area is repainted even by move window, but not with scroll, how repaint on scroll only needed area? -
Example of mpergand in thread "How to use scrollbars in my component?" will good start point for exercise.
I wrote simple in-memory text viewer with QScrollArea::
main.cpp#include <QApplication> #include <QMainWindow> #include <QScrollArea> #include "FileViewer.h" #include "FileViewer.h" using namespace std; int main(int argc, char *argv[]) { QApplication app(argc, argv); QMainWindow textWindow; auto scrollArea=new QScrollArea; textWindow.setCentralWidget(scrollArea); auto fileViewer=new FileViewer; scrollArea->setWidget(fileViewer); string filepath = "../main.cpp"; if(!fileViewer->setFile(filepath)) // file path of your big file { qDebug()<<filepath.c_str()<<"Error openning the file!"; } textWindow.resize(600, 600); textWindow.show(); return app.exec(); }
FileViewer.h
#ifndef FILEVIEWER_H #define FILEVIEWER_H #include <QWidget> class FileViewer : public QWidget { Q_OBJECT public: explicit FileViewer(QWidget *parent = nullptr); bool setFile(const std::string& filepath); private: std::vector<std::string> lines; static std::vector<std::string> readLines(std::string filename); void paintEvent(QPaintEvent* ev); int _LineHeight; // height of a line in pixel }; #endif // FILEVIEWER_H
FileViewer.cpp
#include "FileViewer.h" #include <QFontMetrics> #include <QPainter> #include <QPaintEvent> #include <QDebug> #include <iostream> #include <fstream> using namespace std; FileViewer::FileViewer(QWidget *parent) : QWidget(parent) { //setVisible(true); } bool FileViewer::setFile(const string &filepath) { lines = readLines(filepath); // height of a line in the default font _LineHeight=fontMetrics().height(); resize(800, _LineHeight*lines.size()); return true; } void FileViewer::paintEvent(QPaintEvent *ev) { QPainter painter(this); painter.setPen(Qt::black); auto reg = ev->region(); int originY=reg.boundingRect().topLeft().y(); int endY=reg.boundingRect().bottomLeft().y(); int firstLine=originY/_LineHeight; int lastLine=endY/_LineHeight+1; //qDebug()<<firstLine<<lastLine; for(int l=firstLine; l<lastLine; l++) { const QString str=QString(lines[l].c_str()); QRect rec=fontMetrics().boundingRect(str); /*if(rec.width()+20>_WidestLine) { _WidestLine=rec.width()+20; resize(_WidestLine,_lineCount*_LineHeight); }*/ painter.drawText(QPoint(10,originY+_LineHeight), str); originY+=_LineHeight; } painter.drawRect(reg.boundingRect().adjusted(1,1,-2,-2)); } vector<string> FileViewer::readLines(string filename) { ifstream infile(filename); vector<string> v; string line; bool readedNewline; if (infile.peek() != EOF) while(true) { readedNewline = std::getline(infile, line).good(); v.push_back(line); if (!readedNewline) break; } return v; }
Is maximum simple, only view lines. How to add syntax highlighter? Fileviewer must be descendant of QTextDocument?
Area is repainted even by move window, but not with scroll, how repaint on scroll only needed area?@AndrzejB said in Syntax highlighter to QPlainTextEdit:
Fileviewer must be descendant of QTextDocument?
These are two totally separate things. Your
FileViewer
is aQWidget
. A visual thing with scrolling etc.A
QSyntaxHighlighter
works on a text document to highlight according to syntax rules. You must supply it with aQTextDocument
:To provide your own syntax highlighting, you must subclass QSyntaxHighlighter and reimplement highlightBlock().
When you create an instance of your QSyntaxHighlighter subclass, pass it the QTextDocument that you want the syntax highlighting to be applied to.
It is then the
QTextDocument
which you can show in a widget, e.g. aQTextEdit
.Have you looked through https://doc.qt.io/qt-5/qtwidgets-richtext-syntaxhighlighter-example.html ?