fix performance: cache subBlocks and syntax highlighting
- Cache parseSubBlocks per block (only reparse when content changes) - Cache highlightedHtml results (code+language key) - Prevents expensive KSyntaxHighlighting and regex on every render - Also fixes scroll loop with _scrolling guard
This commit is contained in:
parent
a6a1a227c3
commit
6f351b77e4
|
|
@ -54,7 +54,11 @@ QVariant ChatBlockModel::data(const QModelIndex &index, int role) const
|
||||||
case ContentRole:
|
case ContentRole:
|
||||||
return block.content;
|
return block.content;
|
||||||
case SubBlocksRole:
|
case SubBlocksRole:
|
||||||
return parseSubBlocks(block.content);
|
if (block.cachedContent != block.content) {
|
||||||
|
block.cachedSubBlocks = parseSubBlocks(block.content);
|
||||||
|
block.cachedContent = block.content;
|
||||||
|
}
|
||||||
|
return block.cachedSubBlocks;
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
@ -251,6 +255,12 @@ QVariantList ChatBlockModel::parseSubBlocks(const QString &content) const
|
||||||
|
|
||||||
QString ChatBlockModel::highlightedHtml(const QString &code, const QString &language) const
|
QString ChatBlockModel::highlightedHtml(const QString &code, const QString &language) const
|
||||||
{
|
{
|
||||||
|
// Check cache first
|
||||||
|
QString cacheKey = language + "\x1f" + code;
|
||||||
|
auto cached = m_highlightCache.find(cacheKey);
|
||||||
|
if (cached != m_highlightCache.end())
|
||||||
|
return *cached;
|
||||||
|
|
||||||
auto def = repo().definitionForName(language);
|
auto def = repo().definitionForName(language);
|
||||||
if (!def.isValid()) {
|
if (!def.isValid()) {
|
||||||
// Try by file extension
|
// Try by file extension
|
||||||
|
|
@ -258,7 +268,9 @@ QString ChatBlockModel::highlightedHtml(const QString &code, const QString &lang
|
||||||
}
|
}
|
||||||
if (!def.isValid()) {
|
if (!def.isValid()) {
|
||||||
// Return escaped plain text
|
// Return escaped plain text
|
||||||
return code.toHtmlEscaped().replace('\n', "<br>");
|
QString plain = code.toHtmlEscaped().replace('\n', "<br>");
|
||||||
|
m_highlightCache.insert(cacheKey, plain);
|
||||||
|
return plain;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine theme based on current palette
|
// Determine theme based on current palette
|
||||||
|
|
@ -298,6 +310,7 @@ QString ChatBlockModel::highlightedHtml(const QString &code, const QString &lang
|
||||||
html += "<br>";
|
html += "<br>";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_highlightCache.insert(cacheKey, html);
|
||||||
return html;
|
return html;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,8 @@ struct ChatBlock {
|
||||||
Type type;
|
Type type;
|
||||||
QString name; // tool/call name, empty for others
|
QString name; // tool/call name, empty for others
|
||||||
QString content; // raw text content
|
QString content; // raw text content
|
||||||
|
mutable QVariantList cachedSubBlocks; // cached parseSubBlocks result
|
||||||
|
mutable QString cachedContent; // content when subBlocks were cached
|
||||||
};
|
};
|
||||||
|
|
||||||
// A sub-block within a markdown block (prose, code fence, diff)
|
// A sub-block within a markdown block (prose, code fence, diff)
|
||||||
|
|
@ -70,6 +72,7 @@ private:
|
||||||
|
|
||||||
QString m_rawText;
|
QString m_rawText;
|
||||||
QList<ChatBlock> m_blocks;
|
QList<ChatBlock> m_blocks;
|
||||||
|
mutable QHash<QString, QString> m_highlightCache; // key: code+lang, value: html
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CHAT_BLOCK_MODEL_H
|
#endif // CHAT_BLOCK_MODEL_H
|
||||||
|
|
|
||||||
Reference in New Issue