#pragma once #include #include #include #include #include #include #include #include namespace ZShell::llm { // QML wrapper around JKQTMathText (JKQtPlotter's LaTeX renderer). // // Parses a display-math string and renders it into a transparent // QImage at the given device pixel ratio, off the GUI thread (with a // process-wide cache keyed on the full render state, so re-opening a // chat does not re-render the same equations). QML displays the image // (scaling it to the bubble width when needed) and falls back to the // raw LaTeX when parsing fails. class LlmMathText : public QObject { Q_OBJECT QML_ELEMENT Q_PROPERTY(QString latex READ latex WRITE setLatex NOTIFY changed) Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY changed) Q_PROPERTY(double fontPointSize READ fontPointSize WRITE setFontPointSize NOTIFY changed) Q_PROPERTY(qreal devicePixelRatio READ devicePixelRatio WRITE setDevicePixelRatio NOTIFY changed) Q_PROPERTY(QImage image READ image NOTIFY changed) // data: URL of the rendered equation; usable directly as // Image.source (a raw QImage is not). Q_PROPERTY(QUrl imageUrl READ imageUrl NOTIFY changed) // Logical (CSS pixel) size of the rendered equation. Q_PROPERTY(qreal width READ width NOTIFY changed) Q_PROPERTY(qreal height READ height NOTIFY changed) Q_PROPERTY(bool ok READ ok NOTIFY changed) public: explicit LlmMathText(QObject* parent = nullptr); [[nodiscard]] QString latex() const { return m_latex; } void setLatex(const QString& value); [[nodiscard]] QColor color() const { return m_color; } void setColor(const QColor& value); [[nodiscard]] double fontPointSize() const { return m_fontPointSize; } void setFontPointSize(double value); [[nodiscard]] qreal devicePixelRatio() const { return m_devicePixelRatio; } void setDevicePixelRatio(qreal value); [[nodiscard]] QImage image() const { return m_image; } [[nodiscard]] QUrl imageUrl() const { return m_imageUrl; } [[nodiscard]] qreal width() const { return m_width; } [[nodiscard]] qreal height() const { return m_height; } [[nodiscard]] bool ok() const { return m_ok; } Q_SIGNALS: void changed(); private: void reRender(); // Shared so an in-flight worker render keeps the renderer alive if // this object (and its QML item) is destroyed mid-render. std::shared_ptr m_renderer; QString m_latex; QColor m_color; double m_fontPointSize = 12.0; qreal m_devicePixelRatio = 1.0; QImage m_image; QUrl m_imageUrl; qreal m_width = 0; qreal m_height = 0; bool m_ok = false; // Bumps on every reRender; a delivery carrying an older id was // superseded and is dropped. int m_requestId = 0; bool m_inFlight = false; }; } // namespace ZShell::llm