#include "message.hpp" #include namespace ZShell { ChatMessage::ChatMessage( Role role, const QString& content, qint64 timestamp, QObject* parent) : QObject(parent), m_role(role), m_content(content), m_timestamp(timestamp) { m_timer.setParent(this); m_timer.setInterval(500); m_timer.setTimerType(Qt::CoarseTimer); connect(&m_timer, &QTimer::timeout, this, [this]() { if (!reasoningInFlight() && !contentInFlight()) { m_timer.stop(); return; } Q_EMIT elapsedMsChanged(); }); } qint64 ChatMessage::reasoningElapsedMs() const { if (m_reasoningStartedAt <= 0) return 0; const qint64 end = m_reasoningEndedAt > 0 ? m_reasoningEndedAt : QDateTime::currentMSecsSinceEpoch(); return end - m_reasoningStartedAt; } qint64 ChatMessage::contentElapsedMs() const { if (m_contentStartedAt <= 0) return 0; const qint64 end = m_contentEndedAt > 0 ? m_contentEndedAt : QDateTime::currentMSecsSinceEpoch(); return end - m_contentStartedAt; } void ChatMessage::updateReasoningActive() { const bool active = m_streaming && !m_reasoning.isEmpty() && m_content.isEmpty(); if (m_reasoningActive == active) return; m_reasoningActive = active; Q_EMIT reasoningActiveChanged(); } void ChatMessage::appendContent(const QString& piece) { if (piece.isEmpty()) return; if (m_content.isEmpty()) { const qint64 now = QDateTime::currentMSecsSinceEpoch(); if (reasoningInFlight()) m_reasoningEndedAt = now; m_contentStartedAt = now; if (!m_timer.isActive()) m_timer.start(); } m_content += piece; Q_EMIT contentChanged(); updateReasoningActive(); Q_EMIT elapsedMsChanged(); } void ChatMessage::appendReasoning(const QString& piece) { if (piece.isEmpty()) return; if (m_reasoning.isEmpty()) { m_reasoningStartedAt = QDateTime::currentMSecsSinceEpoch(); if (!m_timer.isActive()) m_timer.start(); } m_reasoning += piece; Q_EMIT reasoningChanged(); updateReasoningActive(); Q_EMIT elapsedMsChanged(); } void ChatMessage::setReasoning(const QString& value) { if (m_reasoning == value) return; m_reasoning = value; Q_EMIT reasoningChanged(); } void ChatMessage::setElapsedMs(qint64 reasoningMs, qint64 contentMs) { if (reasoningMs > 0) { m_reasoningStartedAt = m_timestamp; m_reasoningEndedAt = m_timestamp + reasoningMs; } if (contentMs > 0) { m_contentStartedAt = m_timestamp; m_contentEndedAt = m_timestamp + contentMs; } } void ChatMessage::setStreaming(bool value) { if (m_streaming == value) return; m_streaming = value; Q_EMIT streamingChanged(); if (!value) { const qint64 now = QDateTime::currentMSecsSinceEpoch(); if (reasoningInFlight()) m_reasoningEndedAt = now; if (contentInFlight()) m_contentEndedAt = now; m_timer.stop(); Q_EMIT elapsedMsChanged(); } updateReasoningActive(); } } // namespace ZShell