79 lines
2.3 KiB
C++
79 lines
2.3 KiB
C++
#ifndef CHAT_BLOCK_MODEL_H
|
|
#define CHAT_BLOCK_MODEL_H
|
|
|
|
#include <QAbstractListModel>
|
|
#include <QList>
|
|
#include <QString>
|
|
|
|
// A single block in the chat output
|
|
struct ChatBlock {
|
|
enum Type {
|
|
User, // [user] markdown
|
|
Assistant, // [assistant] markdown
|
|
Reasoning, // [reasoning] content
|
|
Call, // [call:name] args
|
|
Tool, // [tool:name] output
|
|
Error, // [error] text
|
|
Info // [info] text
|
|
};
|
|
|
|
Type type;
|
|
QString name; // tool/call name, empty for others
|
|
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)
|
|
struct ContentBlock {
|
|
enum Type {
|
|
Prose, // regular markdown text
|
|
Code, // fenced code block
|
|
Diff // unified diff (detected by content pattern)
|
|
};
|
|
|
|
Type type;
|
|
QString language; // for Code blocks
|
|
QString content;
|
|
};
|
|
|
|
class ChatBlockModel : public QAbstractListModel
|
|
{
|
|
Q_OBJECT
|
|
Q_PROPERTY(QString rawText READ rawText WRITE setRawText NOTIFY rawTextChanged)
|
|
|
|
public:
|
|
enum Roles {
|
|
BlockTypeRole = Qt::UserRole + 1,
|
|
NameRole,
|
|
ContentRole,
|
|
SubBlocksRole, // QVariantList of sub-block maps
|
|
};
|
|
|
|
explicit ChatBlockModel(QObject *parent = nullptr);
|
|
|
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
|
QHash<int, QByteArray> roleNames() const override;
|
|
|
|
QString rawText() const { return m_rawText; }
|
|
void setRawText(const QString &text);
|
|
|
|
Q_INVOKABLE QString highlightedHtml(const QString &code, const QString &language) const;
|
|
Q_INVOKABLE void copyToClipboard(const QString &text) const;
|
|
|
|
signals:
|
|
void rawTextChanged();
|
|
|
|
private:
|
|
void reparse();
|
|
QList<ChatBlock> parseBlocks(const QString &text) const;
|
|
QVariantList parseSubBlocks(const QString &content) const;
|
|
|
|
QString m_rawText;
|
|
QList<ChatBlock> m_blocks;
|
|
mutable QHash<QString, QString> m_highlightCache; // key: code+lang, value: html
|
|
};
|
|
|
|
#endif // CHAT_BLOCK_MODEL_H
|