line number, symtax highlight, initial dark theme
This commit is contained in:
@@ -13,5 +13,8 @@
|
||||
<entry name="editorFont" type="Font" key="editor-font">
|
||||
<default code="true">QFontDatabase::systemFont(QFontDatabase::FixedFont)</default>
|
||||
</entry>
|
||||
<entry name="editorDarkTheme" type="Bool" key="editor-dark-theme">
|
||||
<default>false</default>
|
||||
</entry>
|
||||
</group>
|
||||
</kcfg>
|
||||
|
||||
@@ -44,6 +44,20 @@
|
||||
<item row="1" column="1">
|
||||
<widget class="KFontRequester" name="kcfg_editorFont"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>eDITOR dARK tHEME</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="kcfg_editorDarkTheme">
|
||||
<property name="text">
|
||||
<string>Enabled</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
|
||||
@@ -109,7 +109,9 @@ void MainWindow::setupActions()
|
||||
lexerNoneAction->setText("None (Normal Text)");
|
||||
actionCollection()->addAction(u"lexer_none"_s, lexerNoneAction);
|
||||
connect(lexerNoneAction, &QAction::triggered, this, [this](){
|
||||
// m_editor->setLexer(nullptr);
|
||||
if (SciEdit *editor = m_tabWidget->currentEditor()) {
|
||||
editor->setLexer(nullptr);
|
||||
}
|
||||
});
|
||||
|
||||
for (const QChar & group : LexerGroupActionMenu::groups()) {
|
||||
@@ -167,6 +169,17 @@ void MainWindow::setupActions()
|
||||
// m_editor->setIndentationGuides(!m_editor->indentationGuides());
|
||||
});
|
||||
|
||||
QAction *toggleEditorDarkThemeAction = new QAction(this);
|
||||
toggleEditorDarkThemeAction->setText("Editor Dark Theme");
|
||||
toggleEditorDarkThemeAction->setCheckable(true);
|
||||
toggleEditorDarkThemeAction->setChecked(AppSettings::editorDarkTheme());
|
||||
actionCollection()->addAction(u"toggle_editor_dark_theme"_s, toggleEditorDarkThemeAction);
|
||||
connect(toggleEditorDarkThemeAction, &QAction::toggled, this, [this](bool checked){
|
||||
AppSettings::setEditorDarkTheme(checked);
|
||||
AppSettings::self()->save();
|
||||
applySettingsToAllEditors();
|
||||
});
|
||||
|
||||
// Load themes
|
||||
KColorSchemeManager *manager = KColorSchemeManager::instance();
|
||||
auto *colorSelectionMenu = KColorSchemeMenu::createMenu(manager, this);
|
||||
@@ -185,8 +198,12 @@ void MainWindow::showSettings()
|
||||
dialog->setFaceType(KPageDialog::FlatList);
|
||||
dialog->addPage(new SettingsPage<Ui::GeneralSettings>(dialog), "Appearance", "preferences-desktop-theme-global");
|
||||
|
||||
connect(dialog, &KConfigDialog::settingsChanged, this, [](const QString &dialogName){
|
||||
qDebug() << dialogName << "changed";
|
||||
connect(dialog, &KConfigDialog::settingsChanged, this, [this](const QString &dialogName){
|
||||
Q_UNUSED(dialogName)
|
||||
applySettingsToAllEditors();
|
||||
if (QAction *action = actionCollection()->action(QStringLiteral("toggle_editor_dark_theme"))) {
|
||||
action->setChecked(AppSettings::editorDarkTheme());
|
||||
}
|
||||
});
|
||||
|
||||
dialog->show();
|
||||
@@ -248,12 +265,30 @@ void MainWindow::onCurrentEditorChanged(SciEdit *editor)
|
||||
|
||||
// 连接当前编辑器的光标位置变化信号
|
||||
if (editor) {
|
||||
applySettingsToEditor(editor);
|
||||
connect(editor, &SciEdit::cursorPosChanged, this, [this](int line, int column) {
|
||||
m_cursorPosStatusLabel->setText(QString("Ln: %1 Col: %2").arg(line).arg(column));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::applySettingsToEditor(SciEdit *editor)
|
||||
{
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
editor->setTabWidth(AppSettings::tabWidth());
|
||||
editor->setEditorFont(AppSettings::editorFont());
|
||||
editor->applyTheme(AppSettings::editorDarkTheme());
|
||||
}
|
||||
|
||||
void MainWindow::applySettingsToAllEditors()
|
||||
{
|
||||
for (int i = 0; i < m_tabWidget->count(); ++i) {
|
||||
applySettingsToEditor(m_tabWidget->editorAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::onDocumentModified(int docIndex, bool modified)
|
||||
{
|
||||
Q_UNUSED(docIndex)
|
||||
|
||||
@@ -31,6 +31,8 @@ private:
|
||||
void setupActions();
|
||||
void showSettings();
|
||||
void applyLexer(const QString & lexer);
|
||||
void applySettingsToEditor(SciEdit *editor);
|
||||
void applySettingsToAllEditors();
|
||||
void updateWindowTitle();
|
||||
void updateStatusBar();
|
||||
void updateActions();
|
||||
|
||||
@@ -26,6 +26,7 @@ Template: https://github.com/KDE/kxmlgui/blob/master/src/ui_standards.rc
|
||||
<Action name="view_zoom_out"/>
|
||||
</Menu>-->
|
||||
<Action name="toggle_wrap_mode" />
|
||||
<Action name="toggle_editor_dark_theme" />
|
||||
</Menu>
|
||||
<Menu name="encoding"><text>E&ncoding</text>
|
||||
</Menu>
|
||||
|
||||
182
sciedit.cpp
182
sciedit.cpp
@@ -1,22 +1,34 @@
|
||||
#include "sciedit.h"
|
||||
|
||||
#include <SciLexer.h>
|
||||
|
||||
#include <QColor>
|
||||
#include <QDebug>
|
||||
|
||||
static sptr_t toBgr(const QColor &color) {
|
||||
return (color.blue() << 16) | (color.green() << 8) | color.red();
|
||||
}
|
||||
|
||||
SciEdit::SciEdit(QWidget * parent)
|
||||
: ScintillaEdit(parent)
|
||||
{
|
||||
connect(this, &ScintillaEditBase::updateUi, this, [this](){
|
||||
int curPos = currentPos();
|
||||
emit cursorPosChanged(lineFromPosition(curPos) + 1, column(curPos));
|
||||
updateLineNumberMarginWidth();
|
||||
});
|
||||
|
||||
// 连接文本变化信号
|
||||
connect(this, QOverload<Scintilla::ModificationFlags, Scintilla::Position, Scintilla::Position, Scintilla::Position, const QByteArray &, Scintilla::Position, Scintilla::FoldLevel, Scintilla::FoldLevel>::of(&ScintillaEditBase::modified),
|
||||
this, &SciEdit::textChanged);
|
||||
|
||||
setLineNumbersEnabled(true);
|
||||
}
|
||||
|
||||
void SciEdit::setStyleFont(const QFont &font, int style)
|
||||
{
|
||||
styleSetFont(style, font.family().toUtf8().constData());
|
||||
styleSetSizeFractional(0, long(font.pointSizeF() * SC_FONT_SIZE_MULTIPLIER));
|
||||
styleSetSizeFractional(style, long(font.pointSizeF() * SC_FONT_SIZE_MULTIPLIER));
|
||||
}
|
||||
|
||||
void SciEdit::setFolding(FoldType foldType, int margin)
|
||||
@@ -48,14 +60,64 @@ void SciEdit::setFolding(FoldType foldType, int margin)
|
||||
void SciEdit::setLexer(Scintilla::ILexer5 *lexer)
|
||||
{
|
||||
setILexer((sptr_t)lexer);
|
||||
m_lexerName = lexer ? QString::fromUtf8(lexer->GetName()) : QString();
|
||||
if (lexer == nullptr) {
|
||||
clearDocumentStyle();
|
||||
}
|
||||
applyLexerStyles();
|
||||
colourise(0, -1);
|
||||
}
|
||||
|
||||
qDebug() << lexer->GetName() << "lexer-------------";
|
||||
void SciEdit::setLineNumbersEnabled(bool enabled)
|
||||
{
|
||||
m_lineNumbersEnabled = enabled;
|
||||
setMarginTypeN(0, SC_MARGIN_NUMBER);
|
||||
updateLineNumberMarginWidth();
|
||||
}
|
||||
|
||||
void SciEdit::setEditorFont(const QFont &font)
|
||||
{
|
||||
m_editorFont = font;
|
||||
applyTheme(m_isDarkTheme);
|
||||
}
|
||||
|
||||
void SciEdit::applyTheme(bool dark)
|
||||
{
|
||||
m_isDarkTheme = dark;
|
||||
|
||||
const QColor bg = dark ? QColor(0x1e, 0x1e, 0x1e) : QColor(0xff, 0xff, 0xff);
|
||||
const QColor fg = dark ? QColor(0xd4, 0xd4, 0xd4) : QColor(0x00, 0x00, 0x00);
|
||||
const QColor caret = dark ? QColor(0xff, 0xff, 0xff) : QColor(0x00, 0x00, 0x00);
|
||||
const QColor selectionBg = dark ? QColor(0x26, 0x4f, 0x78) : QColor(0xcc, 0xe8, 0xff);
|
||||
const QColor caretLineBg = dark ? QColor(0x2a, 0x2a, 0x2a) : QColor(0xf5, 0xf5, 0xf5);
|
||||
const QColor lineNumberFg = dark ? QColor(0x85, 0x85, 0x85) : QColor(0x80, 0x80, 0x80);
|
||||
const QColor lineNumberBg = dark ? QColor(0x25, 0x25, 0x26) : QColor(0xf0, 0xf0, 0xf0);
|
||||
|
||||
styleResetDefault();
|
||||
if (!m_editorFont.family().isEmpty()) {
|
||||
setStyleFont(m_editorFont, STYLE_DEFAULT);
|
||||
}
|
||||
styleSetFore(STYLE_DEFAULT, toBgr(fg));
|
||||
styleSetBack(STYLE_DEFAULT, toBgr(bg));
|
||||
styleClearAll();
|
||||
|
||||
setCaretFore(toBgr(caret));
|
||||
setSelFore(true, toBgr(fg));
|
||||
setSelBack(true, toBgr(selectionBg));
|
||||
setCaretLineVisible(true);
|
||||
setCaretLineBack(toBgr(caretLineBg));
|
||||
|
||||
styleSetFore(STYLE_LINENUMBER, toBgr(lineNumberFg));
|
||||
styleSetBack(STYLE_LINENUMBER, toBgr(lineNumberBg));
|
||||
setMarginBackN(0, toBgr(lineNumberBg));
|
||||
|
||||
updateLineNumberMarginWidth();
|
||||
applyLexerStyles();
|
||||
}
|
||||
|
||||
void SciEdit::sendColor(unsigned int iMessage, uptr_t wParam, const QColor &color) const
|
||||
{
|
||||
sptr_t lParam = (color.blue() << 16) | (color.green() << 8) | color.red();
|
||||
send(iMessage, wParam, lParam);
|
||||
send(iMessage, wParam, toBgr(color));
|
||||
}
|
||||
|
||||
void SciEdit::setMarkerDefine(int markerNumber, int markerSymbol)
|
||||
@@ -67,3 +129,115 @@ void SciEdit::setMarkerDefine(int markerNumber, int markerSymbol)
|
||||
sendColor(SCI_MARKERSETBACK, markerNumber, QColor(128, 128, 128));
|
||||
}
|
||||
}
|
||||
|
||||
void SciEdit::updateLineNumberMarginWidth()
|
||||
{
|
||||
if (!m_lineNumbersEnabled) {
|
||||
setMarginWidthN(0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
const int lines = qMax<sptr_t>(1, lineCount());
|
||||
const int digits = QString::number(lines).size();
|
||||
if (digits == m_lastLineNumberDigits && marginWidthN(0) > 0) {
|
||||
return;
|
||||
}
|
||||
m_lastLineNumberDigits = digits;
|
||||
|
||||
const QString sample = QString(digits, QLatin1Char('9'));
|
||||
const QByteArray sampleBytes = sample.toUtf8();
|
||||
const sptr_t width = textWidth(STYLE_LINENUMBER, sampleBytes.constData()) + 10;
|
||||
setMarginWidthN(0, width);
|
||||
}
|
||||
|
||||
void SciEdit::applyLexerStyles()
|
||||
{
|
||||
if (m_lexerName.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const bool dark = m_isDarkTheme;
|
||||
const QColor comment = dark ? QColor(0x6a, 0x99, 0x55) : QColor(0x00, 0x80, 0x00);
|
||||
const QColor docComment = dark ? QColor(0x60, 0x80, 0x4f) : QColor(0x00, 0x80, 0x00);
|
||||
const QColor keyword = dark ? QColor(0x56, 0x9c, 0xd6) : QColor(0x00, 0x00, 0xff);
|
||||
const QColor type = dark ? QColor(0x4e, 0xc9, 0xb0) : QColor(0x2b, 0x91, 0xaf);
|
||||
const QColor number = dark ? QColor(0xb5, 0xce, 0xa8) : QColor(0x09, 0x86, 0x58);
|
||||
const QColor string = dark ? QColor(0xce, 0x91, 0x78) : QColor(0xa3, 0x15, 0x15);
|
||||
const QColor preprocessor = dark ? QColor(0xc5, 0x86, 0xc0) : QColor(0xaf, 0x00, 0xdb);
|
||||
const QColor tag = dark ? QColor(0x56, 0x9c, 0xd6) : QColor(0x80, 0x00, 0x00);
|
||||
const QColor attr = dark ? QColor(0x9c, 0xdc, 0xfe) : QColor(0xff, 0x00, 0x00);
|
||||
|
||||
auto setFore = [&](int style, const QColor &c) {
|
||||
styleSetFore(style, toBgr(c));
|
||||
};
|
||||
auto setBold = [&](int style, bool b) {
|
||||
styleSetBold(style, b);
|
||||
};
|
||||
|
||||
if (m_lexerName == QStringLiteral("cpp")) {
|
||||
setFore(SCE_C_COMMENT, comment);
|
||||
setFore(SCE_C_COMMENTLINE, comment);
|
||||
setFore(SCE_C_COMMENTDOC, docComment);
|
||||
setFore(SCE_C_COMMENTLINEDOC, docComment);
|
||||
setFore(SCE_C_COMMENTDOCKEYWORD, docComment);
|
||||
setFore(SCE_C_COMMENTDOCKEYWORDERROR, docComment);
|
||||
setFore(SCE_C_NUMBER, number);
|
||||
setFore(SCE_C_STRING, string);
|
||||
setFore(SCE_C_CHARACTER, string);
|
||||
setFore(SCE_C_PREPROCESSOR, preprocessor);
|
||||
setFore(SCE_C_WORD, keyword);
|
||||
setBold(SCE_C_WORD, true);
|
||||
setFore(SCE_C_WORD2, type);
|
||||
setBold(SCE_C_WORD2, true);
|
||||
} else if (m_lexerName == QStringLiteral("python")) {
|
||||
setFore(SCE_P_COMMENTLINE, comment);
|
||||
setFore(SCE_P_NUMBER, number);
|
||||
setFore(SCE_P_STRING, string);
|
||||
setFore(SCE_P_CHARACTER, string);
|
||||
setFore(SCE_P_WORD, keyword);
|
||||
setBold(SCE_P_WORD, true);
|
||||
setFore(SCE_P_WORD2, type);
|
||||
setBold(SCE_P_WORD2, true);
|
||||
setFore(SCE_P_DECORATOR, preprocessor);
|
||||
setFore(SCE_P_CLASSNAME, type);
|
||||
setFore(SCE_P_DEFNAME, type);
|
||||
} else if (m_lexerName == QStringLiteral("hypertext")) {
|
||||
setFore(SCE_H_COMMENT, comment);
|
||||
setFore(SCE_H_TAG, tag);
|
||||
setFore(SCE_H_TAGUNKNOWN, tag);
|
||||
setFore(SCE_H_ATTRIBUTE, attr);
|
||||
setFore(SCE_H_ATTRIBUTEUNKNOWN, attr);
|
||||
setFore(SCE_H_NUMBER, number);
|
||||
setFore(SCE_H_DOUBLESTRING, string);
|
||||
setFore(SCE_H_SINGLESTRING, string);
|
||||
setFore(SCE_H_ENTITY, preprocessor);
|
||||
} else if (m_lexerName == QStringLiteral("xml")) {
|
||||
setFore(SCE_H_COMMENT, comment);
|
||||
setFore(SCE_H_TAG, tag);
|
||||
setFore(SCE_H_TAGUNKNOWN, tag);
|
||||
setFore(SCE_H_ATTRIBUTE, attr);
|
||||
setFore(SCE_H_ATTRIBUTEUNKNOWN, attr);
|
||||
setFore(SCE_H_NUMBER, number);
|
||||
setFore(SCE_H_DOUBLESTRING, string);
|
||||
setFore(SCE_H_SINGLESTRING, string);
|
||||
setFore(SCE_H_ENTITY, preprocessor);
|
||||
} else if (m_lexerName == QStringLiteral("json")) {
|
||||
setFore(SCE_JSON_NUMBER, number);
|
||||
setFore(SCE_JSON_STRING, string);
|
||||
setFore(SCE_JSON_PROPERTYNAME, attr);
|
||||
setFore(SCE_JSON_OPERATOR, preprocessor);
|
||||
setFore(SCE_JSON_LINECOMMENT, comment);
|
||||
setFore(SCE_JSON_BLOCKCOMMENT, comment);
|
||||
} else if (m_lexerName == QStringLiteral("css")) {
|
||||
setFore(SCE_CSS_COMMENT, comment);
|
||||
setFore(SCE_CSS_CLASS, attr);
|
||||
setFore(SCE_CSS_ID, attr);
|
||||
setFore(SCE_CSS_TAG, tag);
|
||||
setFore(SCE_CSS_ATTRIBUTE, attr);
|
||||
setFore(SCE_CSS_DOUBLESTRING, string);
|
||||
setFore(SCE_CSS_SINGLESTRING, string);
|
||||
setFore(SCE_CSS_VALUE, string);
|
||||
setFore(SCE_CSS_IDENTIFIER, keyword);
|
||||
setBold(SCE_CSS_IDENTIFIER, true);
|
||||
}
|
||||
}
|
||||
|
||||
14
sciedit.h
14
sciedit.h
@@ -3,6 +3,9 @@
|
||||
#include <ScintillaEdit.h>
|
||||
#include <ILexer.h>
|
||||
|
||||
#include <QFont>
|
||||
#include <QString>
|
||||
|
||||
class SciEdit : public ScintillaEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -18,6 +21,9 @@ public:
|
||||
void setStyleFont(const QFont & font, int style = STYLE_DEFAULT);
|
||||
void setFolding(FoldType foldType, int margin = 2);
|
||||
void setLexer(Scintilla::ILexer5 * lexer);
|
||||
void setLineNumbersEnabled(bool enabled);
|
||||
void setEditorFont(const QFont &font);
|
||||
void applyTheme(bool dark);
|
||||
void sendColor(unsigned int iMessage, uptr_t wParam, const QColor &col) const;
|
||||
|
||||
signals:
|
||||
@@ -26,4 +32,12 @@ signals:
|
||||
|
||||
private:
|
||||
void setMarkerDefine(int markerNumber, int markerSymbol);
|
||||
void updateLineNumberMarginWidth();
|
||||
void applyLexerStyles();
|
||||
|
||||
bool m_lineNumbersEnabled = false;
|
||||
int m_lastLineNumberDigits = 0;
|
||||
bool m_isDarkTheme = false;
|
||||
QFont m_editorFont;
|
||||
QString m_lexerName;
|
||||
};
|
||||
|
||||
@@ -1,11 +1,41 @@
|
||||
#include "tabwidget.h"
|
||||
#include "sciedit.h"
|
||||
#include "documentmanager.h"
|
||||
#include "appsettings.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QDebug>
|
||||
|
||||
#include <ILexer.h>
|
||||
#include <Lexilla.h>
|
||||
|
||||
static QString lexerNameForDocumentLanguage(const QString &language)
|
||||
{
|
||||
if (language == QStringLiteral("C++") ||
|
||||
language == QStringLiteral("C") ||
|
||||
language == QStringLiteral("C/C++ Header")) {
|
||||
return QStringLiteral("cpp");
|
||||
}
|
||||
if (language == QStringLiteral("Python")) {
|
||||
return QStringLiteral("python");
|
||||
}
|
||||
if (language == QStringLiteral("HTML")) {
|
||||
return QStringLiteral("hypertext");
|
||||
}
|
||||
if (language == QStringLiteral("XML")) {
|
||||
return QStringLiteral("xml");
|
||||
}
|
||||
if (language == QStringLiteral("JSON")) {
|
||||
return QStringLiteral("json");
|
||||
}
|
||||
if (language == QStringLiteral("CSS")) {
|
||||
return QStringLiteral("css");
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
TabWidget::TabWidget(DocumentManager *documentManager, QWidget *parent)
|
||||
: QTabWidget(parent)
|
||||
, m_documentManager(documentManager)
|
||||
@@ -73,6 +103,17 @@ int TabWidget::openDocument(const QString &filePath)
|
||||
// 设置编辑器内容
|
||||
QString content = m_documentManager->getDocumentContent(docId);
|
||||
editor->setText(content.toUtf8().constData());
|
||||
editor->setTabWidth(AppSettings::tabWidth());
|
||||
editor->setEditorFont(AppSettings::editorFont());
|
||||
editor->applyTheme(AppSettings::editorDarkTheme());
|
||||
|
||||
const QString lexerName = lexerNameForDocumentLanguage(m_documentManager->getDocumentLanguage(docId));
|
||||
if (lexerName.isEmpty()) {
|
||||
editor->setLexer(nullptr);
|
||||
} else {
|
||||
Scintilla::ILexer5 *lexer = CreateLexer(lexerName.toStdString().c_str());
|
||||
editor->setLexer(lexer);
|
||||
}
|
||||
|
||||
// 重新连接信号
|
||||
connectEditorSignals(editor);
|
||||
@@ -136,7 +177,17 @@ bool TabWidget::saveCurrentDocumentAs()
|
||||
QByteArray content = editor->getText(editor->textLength());
|
||||
m_documentManager->setDocumentContent(docId, QString::fromUtf8(content));
|
||||
|
||||
return m_documentManager->saveDocumentAs(docId, fileName);
|
||||
const bool saved = m_documentManager->saveDocumentAs(docId, fileName);
|
||||
if (saved) {
|
||||
const QString lexerName = lexerNameForDocumentLanguage(m_documentManager->getDocumentLanguage(docId));
|
||||
if (lexerName.isEmpty()) {
|
||||
editor->setLexer(nullptr);
|
||||
} else {
|
||||
Scintilla::ILexer5 *lexer = CreateLexer(lexerName.toStdString().c_str());
|
||||
editor->setLexer(lexer);
|
||||
}
|
||||
}
|
||||
return saved;
|
||||
}
|
||||
|
||||
void TabWidget::closeCurrentTab()
|
||||
@@ -349,6 +400,9 @@ void TabWidget::onEditorTextChanged()
|
||||
SciEdit *TabWidget::createEditor()
|
||||
{
|
||||
SciEdit *editor = new SciEdit(this);
|
||||
editor->setTabWidth(AppSettings::tabWidth());
|
||||
editor->setEditorFont(AppSettings::editorFont());
|
||||
editor->applyTheme(AppSettings::editorDarkTheme());
|
||||
return editor;
|
||||
}
|
||||
|
||||
@@ -379,4 +433,4 @@ void TabWidget::disconnectEditorSignals(SciEdit *editor)
|
||||
if (editor) {
|
||||
disconnect(editor, &SciEdit::textChanged, this, &TabWidget::onEditorTextChanged);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user