From c1daeb4982ab1bcf4c070aed3f7b4f939037e47d Mon Sep 17 00:00:00 2001 From: evgeny Date: Tue, 3 Nov 2026 00:12:23 +0100 Subject: [PATCH] Show resolved code language on the left of each block header --- tools/chatgui/src/message_text.cpp | 13 ++++++++++--- tools/chatgui/src/message_text.h | 1 + tools/chatgui/src/messagedelegate.cpp | 5 +++++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/tools/chatgui/src/message_text.cpp b/tools/chatgui/src/message_text.cpp index 0555088ab..c5ba9ebc5 100644 --- a/tools/chatgui/src/message_text.cpp +++ b/tools/chatgui/src/message_text.cpp @@ -166,18 +166,25 @@ QSharedPointer formattedMessageText(const QModelIndex& index) static const QHash aliases = {{"cpp", "C++"}, {"c++", "C++"}, {"c", "C"}, {"py", "Python"}, {"js", "JavaScript"}, {"ts", "TypeScript"}, {"sh", "Bash"}, {"shell", "Bash"}, {"cs", "C#"}, {"csharp", "C#"}, {"kt", "Kotlin"}, {"rs", "Rust"}, {"php", "PHP/PHP"}, {"yml", "YAML"}}; - for (const auto& block : message->code) { - if (block.language == "text" || block.language == "plain") continue; + for (auto& block : message->code) { + block.languageName = block.language; + if (block.language == "text" || block.language == "plain") { block.languageName = "text"; continue; } const QString language = block.language.isEmpty() ? detectCodeLanguage(QStringView(message->text).mid(block.start, block.length)) : block.language; if (language.isEmpty()) continue; + block.languageName = language; auto definition = repository.definitionForName(aliases.value(language, language)); if (!definition.isValid()) { for (const auto& candidate : repository.definitions()) { if (candidate.name().compare(language, Qt::CaseInsensitive) == 0) { definition = candidate; break; } } } - if (definition.isValid()) highlighter.highlight(block, definition); + if (definition.isValid()) { + block.languageName = definition.name() == "PHP/PHP" ? QStringLiteral("PHP") : definition.name(); + highlighter.highlight(block, definition); + GUI_DEBUG("message code: language=%s explicit=%d chars=%d", qPrintable(block.languageName), + !block.language.isEmpty(), block.length); + } else GUI_DEBUG("message code: unknown language=%s; using plain code", qPrintable(language)); } } diff --git a/tools/chatgui/src/message_text.h b/tools/chatgui/src/message_text.h index f47823b79..2d792b049 100644 --- a/tools/chatgui/src/message_text.h +++ b/tools/chatgui/src/message_text.h @@ -12,6 +12,7 @@ struct MessageCodeBlock { int start; // Начало кода в видимом тексте, UTF-16. int length; // Длина без строк-ограждений; ноль означает пустой блок. QString language; // Имя из ограждения: пустое включает автоопределение, неизвестное/text/plain отключает раскраску. + QString languageName; // Имя для шапки после подготовки подсветки; пусто означает обычный text. }; struct MessageText { diff --git a/tools/chatgui/src/messagedelegate.cpp b/tools/chatgui/src/messagedelegate.cpp index b528a41a9..9e9b48929 100644 --- a/tools/chatgui/src/messagedelegate.cpp +++ b/tools/chatgui/src/messagedelegate.cpp @@ -1624,6 +1624,11 @@ void MessageDelegate::paintBody(QPainter* painter, const QStyleOptionViewItem& o painter->drawRoundedRect(button.adjusted(0.5, 0.5, -0.5, -0.5), 4, 4); painter->setPen(option.palette.buttonText().color()); painter->drawText(button, Qt::AlignCenter, QCoreApplication::translate("ChatGui", "Copy")); + const QRectF label(L.textRect.x() + 8, button.top(), qMax(0.0, button.left() - L.textRect.x() - 16), button.height()); + painter->setPen(option.palette.text().color()); + const QString language = block.languageName.isEmpty() ? QStringLiteral("text") : block.languageName; + painter->drawText(label, Qt::AlignLeft | Qt::AlignVCenter, + painter->fontMetrics().elidedText(language, Qt::ElideRight, int(label.width()))); } painter->restore(); }