当前位置:网站首页>Qcodeeditor - QT based code editor
Qcodeeditor - QT based code editor
2022-06-25 15:06:00 【Knowledge first】

One Basic introduction
It’s not a project from a Qt example.
This is not qt Example project of !!! This is an introduction to the open source project
QCodeEditor Is a support for automatic completion 、 Code editor for syntax highlighting and line numbering .
It's for anyone who wants to support multiple languages , From programming languages to markup languages , Even custom scripting languages . In the present state , It can perfectly handle all the functions mentioned above , But there are still many things to be achieved .QCodeEditor Is based on Qt Of QPlainTextEdit, It already includes an interface for adding syntax highlighting and autocompletion .
Source code and sample code download links :https://download.csdn.net/download/weixin_42887343/76428055
Two Code using
Using the editor itself is simple . Can pass QPlainTextEdit Add... To the form a And elevate it to kgl::QCodeEditor( Please note that , Must be “ include/KGL/Widgets ” Add to INCLUDEPATH Variable and global include Must select “ ” Check box ) Or programmatically add it to the form :
using namespace kgl;
// ## MainWindow::MainWindow
QCodeEditor *editor = new QCodeEditor;
setCentralWidget(editor); // or: ui->someLayout->addWidget(editor);
By using QCodeEditorDesign This class can change the visual appearance of the editor . In the following example , Let's assume that the code editor is surrounded by multiple widgets , So a border is added to it . We also modified the appearance to have “ Dark ” style :
using namespace kgl;
// ## MainWindow::MainWindow
QCodeEditorDesign design;
design.setLineColumnVisible(false);
design.setEditorBackColor(0xff333333);
design.setEditorTextColor(0xffdddddd);
design.setEditorBorderColor(0xff999999);
design.setEditorBorder(QMargins(1,1,1,1)); // l t r b
editor->setDesign(design);
But how to actually add some syntax highlighting rules , As shown in the figure above ? There are two ways to do this : Add them programmatically or from XML Extract them from the file .
Programmatically :
using namespace kgl;
// ## MainWindow::MainWindow
QList<QSyntaxRule> rules;
QSyntaxRule rule;
rule.setForeColor(QColor(Qt::blue));
rule.setRegex("\\bFoo\\b");
rule.setId("Foo");
rules.push_back(rule);
editor->setRules(rules);
XML file :
using namespace kgl;
// ## MainWindow::MainWindow
QCodeEditorDesign design;
// modify design ...
QList<QSyntaxRule> rules =
QSyntaxRules::loadFromFile(":/rule_cpp.xml", design);
editor->setRules(rules);
// Note: ':/rule_cpp.xml' refers to the path of a QRC resource
The next chapter provides how to create these XML A guide to the rules . But first of all , Our editor needs some autocomplete keywords :
// ## MainWindow::MainWindow
QStringList keywords = {
"printf", "scanf" };
editor->setKeywords(keywords);
If you want to add an icon to indicate that the keyword is a function / member / macro /… QStandardItemModel, You need to create a custom and pass it to “ QCodeEditor::setKeywordModel(model)”.
3、 ... and establish XML Rules file
XML The rules file contains the topmost element composed of multiple child elements . Each child element must contain a regular expression or a list of keywords , All other properties are optional :
<rules>
<rule>
<regex>\bFoo\b</regex>
<keywords>foo bar key</keywords>
</rule>
</rules>
References to all available attributes , Please go to rules_template.xml Of github page .QCodeEditor Even rules with more than one row are supported . Although they are useful for implementing multiline annotations , But they can also be used for other purposes .
Four ID Usefulness
from rules_template.xml It can be seen that , Rules can even define custom ID. In this section , I'll show you how to use ID And why they are so useful . People may have noticed , Adding keywords statically is not a good practice , Especially if your language allows you to include other files or define variables .
“onMatch” The signal
QCodeEditorHighlighteronMatch as long as a string- Find... Through regular expressions - Be highlighted , Will send out a message called ’ ’ The signal of . This enables us to retrieve information with string The problem of :
// ## MainWindow.h
using namespace kgl;
class MainWindow : public QMainWindow {
Q_OBJECT
public:
...
private slots:
void addMacro(const QSyntaxRule &rule, QString seq, QTextBlock block);
private:
QMap<QTextBlock, QSyntaxRule> m_RuleMap;
QMap<QTextBlock, QString> m_MacroMap;
QCodeEditor *m_Editor;
};
// ## MainWindow::MainWindow
QSyntaxRule defineRule;
defineRule.setRegex("(#define\\s+)\\K(\\D\\w*)(?=\s+\S+)");
defineRule.setId("define");
editor->setRules({
defineRule });
connect(m_Editor->highlighter(), SIGNAL(onMatch(QSyntaxRule,QString,QTextBlock)),
this, SLOT(addMacro(QSyntaxRule,QString,QTextBlock)));
// ## MainWindow::addMacro
if (rule.id() == "define") {
foreach (const QTextBlock &b, m_RuleMap.keys()) {
if (b.userData() != NULL && block.userData() != NULL) {
auto *d1 = static_cast<QCodeEditorBlockData *>(block.userData());
auto *d2 = static_cast<QCodeEditorBlockData *>(b.userData());
if (d1->id == d2->id) {
return;
}
}
}
// Not existing yet; add it
QString def = seq.split(' ').at(0);
m_RuleMap.insert(block, rule);
m_MacroMap.insert(block, def);
m_Editor->addKeyword(def);
}
such , Can be a custom class 、 Variables and definitions provide automatic completion , Or include other files and import symbols from them .
“onRemove” The signal
Deleting macros that have been added can be a bit tricky , because QTextBlock Its design makes it almost impossible for us to track it .QCodeEditorHighlighter Provide ’ onRemove’ The signal , Once the highlighter detects that the previously matched rule no longer matches , Will send the signal :
// ## MainWindow.h
private slots:
void addMacro(const QSyntaxRule &rule, QString seq, QTextBlock block);
void removeMacro(QCodeEditorBlockData *data); // Add this to the slots
// ## MainWindow::MainWindow
// Add another connection
connect(m_Editor->highlighter(), SIGNAL(onRemove(QCodeEditorBlockData*)),
this, SLOT(removeMacro(QCodeEditorBlockData*)));
// ## MainWindow::removeMacro
foreach (const QTextBlock &b, m_RuleMap.keys()) {
if (b.userData()) {
auto *d = static_cast<QCodeEditorBlockData *>(b.userData());
if (d->id == data->id) {
// Data is the same; block must be the one from before!
m_Editor->removeKeyword(m_MacroMap.value(b));
m_RuleMap.remove(b);
m_MacroMap.remove(b);
}
}
}
It is a difficult task to implement such a signal which is relatively simple to use . see “ Point of interest ” Chapter for more information .
5、 ... and Compilation instructions
To compile QCodeEditor, You need to define ’ KGL_BUILD’ To export symbols to the dynamic library . If you want to build a static library , Just define ’ KGL_STATIC’. Also make sure you use Qt5 Or later .
6、 ... and Points of concern
One of the biggest obstacles is to render line numbers correctly . Although it is very easy to add rows and columns as child widgets , However, this is not the case for determining all the line numbers visible when scrolling . In the reading Qt After a long period of time , I think I can skip to the next line in the iteration , And stop the iteration immediately when the current row is no longer visible .
Another big obstacle is indenting multiple selected rows when the tab key is pressed . I use really amazing ’ QTextCursor::movePosition’ Method solved the problem , This makes it possible to implement this function ( And back indent ) It's easy .
QTextBlock
Even though QTextBlock It has amazing functions and possibilities , But it still has a weakness : For us , Track... In a text widget QTextBlock It's almost impossible . To implement a signal that allows the deletion of keywords , I first try to copy the problem QTextBlock, Then use overloaded ‘==’ Operator to check for equality . It doesn't work , Because the line number may change and cause the equation to fail . track QTextBlock The only possibility is to use ’ setUserData’ Function to assign QTextBlockUserData. To achieve this , I inherited QTextBlockUserData And will auuid and the Storage regex string In which the .uuid(+ some do-while loop ) Ensure that the block is truly unique throughout the application . Through these measurements ,‘onRemove’ The signal is finally reliable and error free .
Article reference link :https://www.codeproject.com/Articles/1139741/QCodeEditor-Widget-for-Qt
边栏推荐
猜你喜欢

Arithmetic operations and expressions

How to make GIF animation online? Try this GIF online production tool

Jaspersoft studio adding MySQL database configuration

Position (5 ways)

1090.Phone List

Sequential programming 1

开餐馆

User defined data type - structure

ffmpeg protocol concat 进行ts流合并视频的时间戳计算及其音画同步方式一点浅析

System Verilog — interface
随机推荐
System Verilog - thread
2022年广东高考分数线出炉,一个几家欢喜几家愁
HMS Core机器学习服务实现同声传译,支持中英文互译和多种音色语音播报
Errno perrno and strerrno
15 -- k points closest to the origin
Clipboard tutorial
Why should the coroutine be set to non blocking IO
SPARQL learning notes of query, an rrdf query language
RDB and AOF persistence of redis
JS select all exercise
搭建极简GB28181 网守和网关服务器,建立AI推理和3d服务场景,然后开源代码(一)
System Verilog — interface
Daily question, Caesar code,
semget No space left on device
Time stamp calculation and audio-visual synchronization of TS stream combined video by ffmpeg protocol concat
Usage of pure virtual functions
NBD Network Block Device
Add the resources directory under test in idea
Using Visual Studio
QT loading third-party library basic operation