当前位置:网站首页>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
边栏推荐
- Dynamic memory allocation
- 移除区间(贪心)
- Add the resources directory under test in idea
- [C language] implementation of magic square array (the most complete)
- Source code analysis of zeromq lockless queue
- Compile Caffe's project using cmake
- Go closure usage example
- Stderr and stdout related standard outputs and other C system APIs
- For the first time in China, Chinatelecom 5g underground personnel positioning project is officially commercial: it can track the position in real time to ensure operation safety
- How to combine multiple motion graphs into a GIF? Generate GIF animation pictures in three steps
猜你喜欢
随机推荐
Flexible layout (display:flex;) Attribute details
User defined data type - structure
Remove interval (greedy)
RDB and AOF persistence of redis
dev/mapper的解释
Explanation of dev/mapper
Jaspersoft studio installation
Open a restaurant
How to combine multiple motion graphs into a GIF? Generate GIF animation pictures in three steps
3. Sequential structure multiple choice questions
Gif动图如何裁剪?收下这个图片在线裁剪工具
Real variable instance
@Font face fonts only work on their own domain - @font-face fonts only work on their own domain
QQ love talk candy love talk content acquisition and storage
Power automatic test system nsat-8000, accurate, high-speed and reliable power test equipment
Common operations in VIM
Mining procedure processing
Uniapp cloud packaging app
Modal and modeless dialogs for QT
System Verilog - data type