Skip to content

Commit afed772

Browse files
fix(editor): optimize key shortcut retrieval and improve performance
- Implemented caching for key shortcuts to reduce redundant settings lookups. - Introduced a mechanism to clear the cache when relevant settings change, enhancing responsiveness. - Updated left area widget refresh logic to improve performance during text editing. PMS: bug-368159 Log: 优化快捷键获取逻辑,提升编辑器性能和响应速度。
1 parent 0b7a826 commit afed772

5 files changed

Lines changed: 73 additions & 130 deletions

File tree

src/common/utils.cpp

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#include <QApplication>
1818
#include <QDebug>
1919
#include <QDir>
20+
#include <QHash>
21+
#include <QSet>
2022
#include <QFontMetrics>
2123
#include <QPainter>
2224
#include <QString>
@@ -562,8 +564,27 @@ QString Utils::getKeyshortcut(QKeyEvent *keyEvent)
562564

563565
QString Utils::getKeyshortcutFromKeymap(Settings *settings, const QString &keyCategory, const QString &keyName)
564566
{
565-
qDebug() << "Enter getKeyshortcutFromKeymap, keyCategory:" << keyCategory << "keyName:" << keyName;
566-
return settings->settings->option(QString("shortcuts.%1.%2").arg(keyCategory).arg(keyName))->value().toString();
567+
static QHash<QString, QString> cache;
568+
static QSet<Settings *> watchedSettings;
569+
const QString cacheKey = QStringLiteral("shortcuts.%1.%2").arg(keyCategory).arg(keyName);
570+
571+
if (!watchedSettings.contains(settings)) {
572+
watchedSettings.insert(settings);
573+
QObject::connect(settings->settings, &Dtk::Core::DSettings::valueChanged, settings, [&cache](const QString &key) {
574+
if (key.startsWith(QStringLiteral("shortcuts."))) {
575+
cache.clear();
576+
}
577+
});
578+
}
579+
580+
const auto it = cache.constFind(cacheKey);
581+
if (it != cache.constEnd()) {
582+
return it.value();
583+
}
584+
585+
const QString result = settings->settings->option(cacheKey)->value().toString();
586+
cache.insert(cacheKey, result);
587+
return result;
567588
}
568589

569590
QPixmap Utils::dropShadow(const QPixmap &source, qreal radius, const QColor &color, const QPoint &offset)

src/editor/dtextedit.cpp

Lines changed: 34 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -109,16 +109,15 @@ TextEdit::TextEdit(QWidget *parent)
109109
// Init widgets.
110110
//左边栏控件 滑动条滚动跟新行号 折叠标记
111111
connect(this->verticalScrollBar(), &QScrollBar::valueChanged, this, &TextEdit::slotValueChanged);
112+
// 左侧栏更新节流:textChanged 每次按键都触发,50ms 合并连续按键
113+
m_leftAreaUpdateTimer.setSingleShot(true);
114+
m_leftAreaUpdateTimer.setInterval(50);
115+
connect(&m_leftAreaUpdateTimer, &QTimer::timeout, this, &TextEdit::updateLeftAreaWidget);
112116
connect(this, &QPlainTextEdit::textChanged, this, [this]() {
113117
if (m_wrapper) {
114118
m_wrapper->UpdateBottomBarWordCnt(characterCount());
115119
}
116-
// 仅行数变化时全量刷新左侧栏;同行编辑由 cursorPositionChanged 局部 update 负责
117-
const int blockCountNow = blockCount();
118-
if (blockCountNow != m_lastLeftAreaBlockCount) {
119-
m_lastLeftAreaBlockCount = blockCountNow;
120-
updateLeftAreaWidget();
121-
}
120+
m_leftAreaUpdateTimer.start();
122121
});
123122

124123
connect(this, &QPlainTextEdit::cursorPositionChanged, this, &TextEdit::cursorPositionChanged);
@@ -170,11 +169,6 @@ TextEdit::TextEdit(QWidget *parent)
170169
m_scrollAnimation->setEasingCurve(QEasingCurve::InOutExpo);
171170
m_scrollAnimation->setDuration(300);
172171

173-
m_typingBurstFlushTimer = new QTimer(this);
174-
m_typingBurstFlushTimer->setSingleShot(true);
175-
m_typingBurstFlushTimer->setInterval(120);
176-
connect(m_typingBurstFlushTimer, &QTimer::timeout, this, &TextEdit::flushDeferredCursorUpdate);
177-
178172
m_cursorMode = Insert;
179173

180174
connect(m_scrollAnimation, &QPropertyAnimation::finished, this, &TextEdit::handleScrollFinish, Qt::QueuedConnection);
@@ -309,7 +303,6 @@ void TextEdit::deleteSelectTextEx(QTextCursor cursor, QString text, bool currLin
309303
void TextEdit::deleteTextEx(QTextCursor cursor)
310304
{
311305
qDebug() << "Deleting text at position:" << cursor.position();
312-
flushDeferredCursorUpdate();
313306
QUndoCommand *pDeleteStack = new DeleteTextUndoCommand(cursor, this);
314307
m_pUndoStack->push(pDeleteStack);
315308
qDebug() << "Text deleted successfully";
@@ -340,32 +333,15 @@ void TextEdit::deleteMultiTextEx(const QList<QTextCursor> &multiText)
340333
void TextEdit::insertSelectTextEx(QTextCursor cursor, QString text)
341334
{
342335
qDebug() << "Inserting selected text at position:" << cursor.position() << "Length:" << text.length();
343-
344-
const bool deferHeavyUpdate = shouldDeferCursorHeavyUpdate(cursor, text);
345-
if (!deferHeavyUpdate) {
346-
flushDeferredCursorUpdate();
347-
} else {
348-
const int line = cursor.blockNumber();
349-
if (m_deferCursorHeavyUpdate && line != m_deferCursorLastLine) {
350-
flushDeferredCursorUpdate();
351-
}
352-
m_deferCursorHeavyUpdate = true;
353-
m_deferCursorLastLine = line;
354-
}
355-
356336
QUndoCommand *pInsertStack = new InsertTextUndoCommand(cursor, text, this);
357337
m_pUndoStack->push(pInsertStack);
358338
ensureCursorVisible();
359-
if (deferHeavyUpdate) {
360-
scheduleDeferredCursorUpdateBurst();
361-
}
362339
qDebug() << "Selected text inserted successfully";
363340
}
364341

365342
void TextEdit::insertColumnEditTextEx(QString text)
366343
{
367344
qDebug() << "Inserting column text";
368-
flushDeferredCursorUpdate();
369345
if (m_isSelectAll) {
370346
QPlainTextEdit::selectAll();
371347
}
@@ -3016,63 +2992,7 @@ bool TextEdit::setCursorKeywordSeletoin(int position, bool findNext)
30162992
return false;
30172993
}
30182994

3019-
bool TextEdit::shouldDeferCursorHeavyUpdate(const QTextCursor &cursor, const QString &text) const
3020-
{
3021-
if (m_cursorMode != Insert
3022-
|| m_bIsAltMod
3023-
|| m_readOnlyMode
3024-
|| m_bReadOnlyPermission
3025-
|| m_bIsFileOpen
3026-
|| m_isPreeditBefore
3027-
|| m_bIsInputMethod) {
3028-
return false;
3029-
}
3030-
3031-
if (cursor.anchor() != cursor.position()) {
3032-
return false;
3033-
}
3034-
3035-
for (const QChar ch : text) {
3036-
if (ch == QLatin1Char('\n') || ch == QLatin1Char('\t') || ch == QChar::ParagraphSeparator) {
3037-
return false;
3038-
}
3039-
}
3040-
3041-
return true;
3042-
}
3043-
3044-
void TextEdit::scheduleDeferredCursorUpdateBurst()
3045-
{
3046-
m_deferCursorHeavyUpdate = true;
3047-
m_deferCursorLastLine = textCursor().blockNumber();
3048-
m_typingBurstFlushTimer->start();
3049-
}
3050-
3051-
void TextEdit::flushDeferredCursorUpdate()
3052-
{
3053-
if (m_typingBurstFlushTimer != nullptr) {
3054-
m_typingBurstFlushTimer->stop();
3055-
}
3056-
3057-
if (!m_deferCursorHeavyUpdate) {
3058-
return;
3059-
}
3060-
3061-
m_deferCursorHeavyUpdate = false;
3062-
m_deferCursorLastLine = -1;
3063-
applyCursorHeavyUpdate();
3064-
}
3065-
3066-
void TextEdit::updateCursorPositionStatusLightweight()
3067-
{
3068-
QTextCursor cursor = textCursor();
3069-
if (m_wrapper) {
3070-
m_wrapper->bottomBar()->updatePosition(cursor.blockNumber() + 1,
3071-
cursor.positionInBlock() + 1);
3072-
}
3073-
}
3074-
3075-
void TextEdit::applyCursorHeavyUpdate()
2995+
void TextEdit::cursorPositionChanged()
30762996
{
30772997
qDebug() << "Cursor position changed";
30782998
// 以赋值形式,清空 Bracket 括号的selection
@@ -3081,35 +3001,21 @@ void TextEdit::applyCursorHeavyUpdate()
30813001
m_endBracketSelection = QTextEdit::ExtraSelection();
30823002

30833003
updateHighlightLineSelection();
3084-
updateHighlightBrackets('(', ')');
3085-
updateHighlightBrackets('{', '}');
3086-
updateHighlightBrackets('[', ']');
3004+
updateHighlightBracketsAll();
30873005
renderAllSelections();
30883006

3089-
updateCursorPositionStatusLightweight();
3007+
QTextCursor cursor = textCursor();
3008+
if (m_wrapper) {
3009+
m_wrapper->bottomBar()->updatePosition(cursor.blockNumber() + 1,
3010+
cursor.positionInBlock() + 1);
3011+
}
30903012

30913013
m_pLeftAreaWidget->m_pLineNumberArea->update();
30923014
m_pLeftAreaWidget->m_pBookMarkArea->update();
30933015
m_pLeftAreaWidget->m_pFlodArea->update();
30943016
qDebug() << "Cursor position changed completed";
30953017
}
30963018

3097-
void TextEdit::cursorPositionChanged()
3098-
{
3099-
if (m_deferCursorHeavyUpdate) {
3100-
const int line = textCursor().blockNumber();
3101-
if (line != m_deferCursorLastLine) {
3102-
flushDeferredCursorUpdate();
3103-
return;
3104-
}
3105-
3106-
updateCursorPositionStatusLightweight();
3107-
return;
3108-
}
3109-
3110-
applyCursorHeavyUpdate();
3111-
}
3112-
31133019
/**
31143020
* @brief 剪切光标选中的文本
31153021
* @param ignoreCheck 是否忽略权限判断(外部已进行),默认false
@@ -3277,10 +3183,10 @@ void TextEdit::paste()
32773183

32783184
void TextEdit::highlight()
32793185
{
3280-
QTimer::singleShot(0, this, [&]() {
3281-
if (nullptr != m_wrapper) {
3186+
QTimer::singleShot(0, this, [this]() {
3187+
if (m_wrapper != nullptr) {
32823188
qDebug() << "Highlighting with wrapper";
3283-
m_wrapper->OnUpdateHighlighter();
3189+
m_wrapper->scheduleHighlight();
32843190
}
32853191
});
32863192
qDebug() << "Highlighting completed";
@@ -3635,7 +3541,6 @@ void TextEdit::slotRedoAvailable(bool redoIsAvailable)
36353541
void TextEdit::redo_()
36363542
{
36373543
qDebug() << "Starting redo operation";
3638-
flushDeferredCursorUpdate();
36393544
if (!m_pUndoStack->canRedo()) {
36403545
qDebug() << "Redo operation skipped - nothing to redo";
36413546
return;
@@ -3667,7 +3572,6 @@ void TextEdit::undo_()
36673572
{
36683573
qDebug() << "Starting undo operation";
36693574
qDebug() << "Starting undo operation";
3670-
flushDeferredCursorUpdate();
36713575
if (!m_pUndoStack->canUndo()) {
36723576
qDebug() << "Undo operation skipped - nothing to undo";
36733577
return;
@@ -4044,6 +3948,24 @@ void TextEdit::updateHighlightBrackets(const QChar &openChar, const QChar &close
40443948
qDebug() << "Updating highlight brackets completed";
40453949
}
40463950

3951+
void TextEdit::updateHighlightBracketsAll()
3952+
{
3953+
QTextDocument *doc = document();
3954+
QTextCursor cursor = textCursor();
3955+
const int position = cursor.position();
3956+
3957+
const QChar atPos = doc->characterAt(position);
3958+
const QChar atPrev = doc->characterAt(position - 1);
3959+
static const QString brackets = QStringLiteral("(){}[]");
3960+
if (!brackets.contains(atPos) && !brackets.contains(atPrev)) {
3961+
return;
3962+
}
3963+
3964+
updateHighlightBrackets('(', ')');
3965+
updateHighlightBrackets('{', '}');
3966+
updateHighlightBrackets('[', ']');
3967+
}
3968+
40473969
int TextEdit::getFirstVisibleBlockId() const
40483970
{
40493971
qDebug() << "Getting first visible block id";
@@ -5593,7 +5515,6 @@ void TextEdit::setTextFinished()
55935515
qDebug() << "Set text finished";
55945516
m_bIsFileOpen = false;
55955517
m_nLines = blockCount();
5596-
m_lastLeftAreaBlockCount = m_nLines;
55975518

55985519
if (!m_listBookmark.isEmpty()) {
55995520
qDebug() << "Set text finished, m_listBookmark is not empty";
@@ -6798,8 +6719,7 @@ void TextEdit::updateMark(int from, int charsRemoved, int charsAdded)
67986719
}
67996720
}
68006721

6801-
//渲染所有的指定字符格式
6802-
renderAllSelections();
6722+
// renderAllSelections 和 highlight 已在 cursorPositionChanged / highlight 防抖定时器中统一调度
68036723
qDebug() << "updateMark, completed";
68046724
}
68056725

@@ -7710,7 +7630,6 @@ void TextEdit::dropEvent(QDropEvent *event)
77107630

77117631
void TextEdit::inputMethodEvent(QInputMethodEvent *e)
77127632
{
7713-
flushDeferredCursorUpdate();
77147633
m_bIsInputMethod = true;
77157634

77167635
if (m_isSelectAll)
@@ -7781,7 +7700,6 @@ void TextEdit::inputMethodEvent(QInputMethodEvent *e)
77817700

77827701
void TextEdit::mousePressEvent(QMouseEvent *e)
77837702
{
7784-
flushDeferredCursorUpdate();
77857703
if (m_bIsFindClose)
77867704
{
77877705
m_bIsFindClose = false;
@@ -8301,7 +8219,6 @@ void TextEdit::keyPressEvent(QKeyEvent *e)
83018219

83028220
//列编辑 删除撤销重做
83038221
if (modifiers == Qt::NoModifier && (e->key() == Qt::Key_Backspace)) {
8304-
flushDeferredCursorUpdate();
83058222
if (m_isSelectAll)
83068223
QPlainTextEdit::selectAll();
83078224

@@ -8325,7 +8242,6 @@ void TextEdit::keyPressEvent(QKeyEvent *e)
83258242

83268243
//列编辑 向后删除撤销重做
83278244
if (modifiers == Qt::NoModifier && (e->key() == Qt::Key_Delete)) {
8328-
flushDeferredCursorUpdate();
83298245
if (m_isSelectAll)
83308246
QPlainTextEdit::selectAll();
83318247

src/editor/dtextedit.h

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -511,9 +511,6 @@ public slots:
511511
void onSelectionArea();
512512
void fingerZoom(QString name, QString direction, int fingers);
513513
void cursorPositionChanged();
514-
void flushDeferredCursorUpdate();
515-
void applyCursorHeavyUpdate();
516-
void updateCursorPositionStatusLightweight();
517514

518515
//剪切槽函数
519516
void cut(bool ignoreCheck = false);
@@ -589,6 +586,7 @@ public slots:
589586
void unCommentSelection();
590587
void setComment();
591588
void removeComment();
589+
void updateHighlightBracketsAll();
592590

593591
//去除"*{*" "*}*" "*{*}*"跳过当做普通文本处理不折叠 梁卫东2020-09-01 17:16:41
594592
bool blockContainStrBrackets(int line);
@@ -788,7 +786,6 @@ private slots:
788786
QList<int> m_listBookmark;///< 存储书签的list
789787
int m_nBookMarkHoverLine;///< 悬浮效果书签所在的行
790788
int m_nLines;///< 文本总行数
791-
int m_lastLeftAreaBlockCount = 0;///< 上次刷新左侧栏时的文档行数
792789
bool m_bIsFileOpen;///< 是否在读取文件(导致文本变化)
793790
bool m_bIsShortCut;///< 是否在使用书签快捷键
794791

@@ -877,12 +874,7 @@ private slots:
877874
bool m_isPreeditBefore = false; // 上一个输入法时间是否是 preedit
878875
int m_preeditLengthBefore = 0;
879876

880-
bool shouldDeferCursorHeavyUpdate(const QTextCursor &cursor, const QString &text) const;
881-
void scheduleDeferredCursorUpdateBurst();
882-
883-
bool m_deferCursorHeavyUpdate = false;
884-
int m_deferCursorLastLine = -1;
885-
QTimer *m_typingBurstFlushTimer = nullptr;
877+
QTimer m_leftAreaUpdateTimer;
886878

887879
Qt::CaseSensitivity defaultCaseSensitive = Qt::CaseInsensitive; // 查找匹配时默认不区分大小写
888880
};

src/editor/editwrapper.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,11 @@ EditWrapper::EditWrapper(Window *window, QWidget *parent)
119119
connect(m_pTextEdit, &TextEdit::cursorModeChanged, this, &EditWrapper::handleCursorModeChanged);
120120
connect(m_pWaringNotices, &WarningNotices::reloadBtnClicked, this, &EditWrapper::reloadModifyFile);
121121
connect(m_pWaringNotices, &WarningNotices::saveAsBtnClicked, m_pWindow, &Window::saveAsFile);
122+
123+
m_highlightDebounceTimer.setSingleShot(true);
124+
m_highlightDebounceTimer.setInterval(150);
125+
connect(&m_highlightDebounceTimer, &QTimer::timeout, this, &EditWrapper::OnUpdateHighlighter);
126+
122127
// NOTE: 文本高亮会触发重新布局,与界面布局(拖拽、放大窗口)变更时的布局操作冲突,因此调整更新顺序,在布局后刷新高亮
123128
connect(m_pTextEdit->verticalScrollBar(), &QScrollBar::valueChanged, this, [this](int) {
124129
qDebug() << "EditWrapper connect verticalScrollBar valueChanged";
@@ -1150,6 +1155,11 @@ void EditWrapper::UpdateBottomBarWordCnt(int cnt)
11501155
m_pBottomBar->updateWordCount(cnt);
11511156
}
11521157

1158+
void EditWrapper::scheduleHighlight()
1159+
{
1160+
m_highlightDebounceTimer.start();
1161+
}
1162+
11531163
/**
11541164
* @brief 界面显示内容变更时触发,将查询当前显示的内容
11551165
* @param forceUpdate 是否强制重设高亮处理,部分高亮无需重复设置

0 commit comments

Comments
 (0)