Skip to content

Commit 7f1e4d0

Browse files
committed
refactor: throttle markdown conversion and add force‑update flag
* Added a `QElapsedTimer` in `MarkdownLabel` to limit markdown conversions to ~30 fps. * Introduced a guard that restarts the timer after each conversion and an `invalidate()` method to reset it for forced updates. * Updated `ChatMessage::renderMarkdown` to take a `forceUpdate` boolean (default `false`). * Updated all callers (`ChatEditor::onMessageAppended`, `ChatMessage::buildUI`, `ChatMessage::messageCompleted`) to pass `true` when a new message is appended or finished, ensuring the UI is refreshed immediately. * Adjusted header declarations and added comments for clarity. This change prevents UI freezes caused by rapid markdown re‑rendering while still allowing explicit updates when a message changes.
1 parent 067146e commit 7f1e4d0

File tree

5 files changed

+23
-5
lines changed

5 files changed

+23
-5
lines changed

llamachateditor.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ void ChatEditor::onMessageAppended(const Message &msg, qint64 pendingId)
434434
w->setSiblingIdx(siblingIdx);
435435
w->setSiblingLeafIds(siblings);
436436

437-
w->renderMarkdown(msg.content);
437+
w->renderMarkdown(msg.content, true);
438438
w->messageCompleted(true);
439439
}
440440

llamachatmessage.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ void ChatMessage::buildUI()
7373
connect(m_thoughtToggle, &QPushButton::toggled, this, &ChatMessage::onThoughtToggle);
7474
onThoughtToggle(false);
7575
} else {
76-
renderMarkdown(m_msg.content);
76+
renderMarkdown(m_msg.content, true);
7777
}
7878

7979
m_markdownLabel->setObjectName(m_isUser ? "BubbleUser" : "BubbleAssistant");
@@ -247,8 +247,11 @@ bool ChatMessage::eventFilter(QObject *obj, QEvent *event)
247247
return QWidget::eventFilter(obj, event);
248248
}
249249

250-
void ChatMessage::renderMarkdown(const QString &text)
250+
void ChatMessage::renderMarkdown(const QString &text, bool forceUpdate)
251251
{
252+
if (forceUpdate)
253+
m_markdownLabel->invalidate();
254+
252255
if (m_thoughtToggle) {
253256
auto [thinking, message] = ThinkingSectionParser::parseThinkingSection(text);
254257
if (m_thoughtToggle->isChecked()) {
@@ -278,7 +281,7 @@ void ChatMessage::messageCompleted(bool completed)
278281
m_regenButton->setVisible(completed);
279282
m_copyButton->setVisible(completed);
280283

281-
renderMarkdown(m_msg.content);
284+
renderMarkdown(m_msg.content, completed);
282285
}
283286
}
284287

llamachatmessage.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class ChatMessage : public QWidget
2323
QWidget *parent = nullptr);
2424

2525
Message &message() { return m_msg; }
26-
void renderMarkdown(const QString &text);
26+
void renderMarkdown(const QString &text, bool forceUpdate = false);
2727

2828
void messageCompleted(bool completed);
2929
bool isUser() const;

llamamarkdownwidget.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,13 @@ MarkdownLabel::MarkdownLabel(QWidget *parent)
133133

134134
void MarkdownLabel::setMarkdown(const QString &markdown)
135135
{
136+
// We don't want something faster than 30fps, which would cause UI freezes
137+
if (m_markdownConversionTimer.isValid() && m_markdownConversionTimer.elapsed() < 33)
138+
return;
139+
140+
m_markdownConversionTimer.start();
141+
auto guard = qScopeGuard([this] { m_markdownConversionTimer.restart(); });
142+
136143
// Make sure the widget’s minimum width is large enough for the
137144
// longest line in the markdown.
138145
adjustMinimumWidth(markdown);
@@ -266,6 +273,11 @@ int MarkdownLabel::heightForWidth(int w) const
266273
return qRound(doc->size().height());
267274
}
268275

276+
void MarkdownLabel::invalidate()
277+
{
278+
m_markdownConversionTimer.invalidate();
279+
}
280+
269281
void MarkdownLabel::adjustMinimumWidth(const QString &markdown)
270282
{
271283
const QStringList lines = markdown.split('\n');

llamamarkdownwidget.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <utils/expected.h>
44

5+
#include <QElapsedTimer>
56
#include <QString>
67
#include <QTextBrowser>
78

@@ -19,6 +20,7 @@ class MarkdownLabel : public QTextBrowser
1920
void setStyleSheet();
2021
void resizeEvent(QResizeEvent *event) override;
2122
int heightForWidth(int w) const override;
23+
void invalidate();
2224

2325
signals:
2426
void copyToClipboard(const QString &verbatimText, const QString &highlightedText);
@@ -64,5 +66,6 @@ class MarkdownLabel : public QTextBrowser
6466

6567
Data m_data;
6668
QMap<int, QPair<int, int>> m_insertedHtmlSection;
69+
QElapsedTimer m_markdownConversionTimer;
6770
};
6871
} // namespace LlamaCpp

0 commit comments

Comments
 (0)