This repository has been archived on 2026-08-16. You can view files and clone it, but cannot push or open issues or pull requests.
ollie-kde/gui/chatblockmodel.h

88 lines
2.9 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
FormattedContentRole, // pre-formatted HTML for call/tool expanded view
};
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 QString prettyJson(const QString &text) const;
Q_INVOKABLE void copyToClipboard(const QString &text) const;
Q_INVOKABLE QString linkifyFilePaths(const QString &markdown) const;
Q_INVOKABLE void openLink(const QString &link) const;
Q_INVOKABLE bool executeInTerminal(const QString &code, const QString &language,
const QString &workingDirectory = QString()) const;
Q_INVOKABLE bool loadEarlier(); // returns true if more blocks were loaded
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_allBlocks; // all parsed blocks
QList<ChatBlock> m_blocks; // visible window (tail of m_allBlocks)
int m_visibleStart = 0; // index into m_allBlocks where visible window starts
mutable QHash<QString, QString> m_highlightCache;
};
#endif // CHAT_BLOCK_MODEL_H