Add ChatBarMessageContentModel and hook up

This commit is contained in:
James Graham
2025-08-04 18:11:21 +01:00
parent 9cbe9f7280
commit c128450cf5
20 changed files with 1825 additions and 648 deletions

View File

@@ -7,6 +7,8 @@
#include <QObject>
#include <QQmlEngine>
#include <QTextCursor>
#include <qnamespace.h>
#include <qtextdocumentfragment.h>
#include "chatbarcache.h"
#include "enums/chatbartype.h"
@@ -71,6 +73,11 @@ class ChatDocumentHandler : public QObject
*/
Q_PROPERTY(ChatBarType::Type type READ type WRITE setType NOTIFY typeChanged)
/**
* @brief The current room that the text document is being handled for.
*/
Q_PROPERTY(NeoChatRoom *room READ room WRITE setRoom NOTIFY roomChanged)
/**
* @brief The QML text Item the ChatDocumentHandler is handling.
*/
@@ -85,23 +92,30 @@ class ChatDocumentHandler : public QObject
Q_PROPERTY(CompletionModel *completionModel READ completionModel CONSTANT)
/**
* @brief The current room that the text document is being handled for.
* @brief Whether the cursor is cuurently on the first line.
*/
Q_PROPERTY(NeoChatRoom *room READ room WRITE setRoom NOTIFY roomChanged)
Q_PROPERTY(bool atFirstLine READ atFirstLine NOTIFY atFirstLineChanged)
/**
* @brief Whether the cursor is cuurently on the last line.
*/
Q_PROPERTY(bool atLastLine READ atLastLine NOTIFY atLastLineChanged)
Q_PROPERTY(QColor textColor READ textColor WRITE setTextColor NOTIFY textColorChanged)
Q_PROPERTY(QString fontFamily READ fontFamily WRITE setFontFamily NOTIFY fontFamilyChanged)
Q_PROPERTY(Qt::Alignment alignment READ alignment WRITE setAlignment NOTIFY alignmentChanged)
Q_PROPERTY(bool bold READ bold WRITE setBold NOTIFY boldChanged)
Q_PROPERTY(bool italic READ italic WRITE setItalic NOTIFY italicChanged)
Q_PROPERTY(bool underline READ underline WRITE setUnderline NOTIFY underlineChanged)
Q_PROPERTY(bool strikethrough READ strikethrough WRITE setStrikethrough NOTIFY strikethroughChanged)
Q_PROPERTY(bool bold READ bold WRITE setBold NOTIFY formatChanged)
Q_PROPERTY(bool italic READ italic WRITE setItalic NOTIFY formatChanged)
Q_PROPERTY(bool underline READ underline WRITE setUnderline NOTIFY formatChanged)
Q_PROPERTY(bool strikethrough READ strikethrough WRITE setStrikethrough NOTIFY formatChanged)
Q_PROPERTY(bool canIndentList READ canIndentList NOTIFY cursorPositionChanged)
Q_PROPERTY(bool canDedentList READ canDedentList NOTIFY cursorPositionChanged)
Q_PROPERTY(ChatDocumentHandler::Style style READ style WRITE setStyle NOTIFY styleChanged)
// Q_PROPERTY(bool canIndentList READ canIndentList NOTIFY cursorPositionChanged)
// Q_PROPERTY(bool canDedentList READ canDedentList NOTIFY cursorPositionChanged)
Q_PROPERTY(int currentListStyle READ currentListStyle NOTIFY currentListStyleChanged)
Q_PROPERTY(int currentHeadingLevel READ currentHeadingLevel NOTIFY cursorPositionChanged)
// Q_PROPERTY(int currentHeadingLevel READ currentHeadingLevel NOTIFY cursorPositionChanged)
// Q_PROPERTY(bool list READ list WRITE setList NOTIFY listChanged)
@@ -112,18 +126,64 @@ class ChatDocumentHandler : public QObject
Q_PROPERTY(QUrl fileUrl READ fileUrl NOTIFY fileUrlChanged)
public:
enum InsertPosition {
Cursor,
Start,
End,
};
/**
* @brief Enum to define available styles.
*
* @note The Paragraph and Heading values are intentially fixed to match heading
* level values returned by QTextBlockFormat::headingLevel().
*
* @sa QTextBlockFormat::headingLevel()
*/
enum Style {
Paragraph = 0,
Heading1 = 1,
Heading2 = 2,
Heading3 = 3,
Heading4 = 4,
Heading5 = 5,
Heading6 = 6,
};
Q_ENUM(Style);
explicit ChatDocumentHandler(QObject *parent = nullptr);
ChatBarType::Type type() const;
void setType(ChatBarType::Type type);
QQuickItem *textItem() const;
void setTextItem(QQuickItem *textItem);
[[nodiscard]] NeoChatRoom *room() const;
void setRoom(NeoChatRoom *room);
ChatBarCache *chatBarCache() const;
QQuickItem *textItem() const;
void setTextItem(QQuickItem *textItem);
ChatDocumentHandler *previousDocumentHandler() const;
void setPreviousDocumentHandler(ChatDocumentHandler *previousDocumentHandler);
ChatDocumentHandler *nextDocumentHandler() const;
void setNextDocumentHandler(ChatDocumentHandler *nextDocumentHandler);
QString fixedStartChars() const;
void setFixedStartChars(const QString &chars);
QString fixedEndChars() const;
void setFixedEndChars(const QString &chars);
QString initialText() const;
void setInitialText(const QString &text);
bool isEmpty() const;
bool atFirstLine() const;
bool atLastLine() const;
void setCursorFromDocumentHandler(ChatDocumentHandler *previousDocumentHandler, bool infront, int defaultPosition = 0);
int lineCount() const;
std::optional<int> lineLength(int lineNumber) const;
int cursorPositionInLine() const;
QTextDocumentFragment takeFirstBlock();
void fillFragments(bool &hasBefore, QTextDocumentFragment &midFragment, std::optional<QTextDocumentFragment> &afterFragment);
Q_INVOKABLE void complete(int index);
@@ -145,7 +205,6 @@ public:
bool bold() const;
void setBold(bool bold);
bool italic() const;
void setItalic(bool italic);
@@ -159,7 +218,8 @@ public:
bool canDedentList() const;
int currentListStyle() const;
int currentHeadingLevel() const;
Style style() const;
void setStyle(Style style);
// bool list() const;
// void setList(bool list);
@@ -171,7 +231,10 @@ public:
QString fileType() const;
QUrl fileUrl() const;
Q_INVOKABLE void deleteChar();
Q_INVOKABLE void backspace();
Q_INVOKABLE void insertText(const QString &text);
void insertFragment(const QTextDocumentFragment fragment, InsertPosition position = Cursor, bool keepPosition = false);
Q_INVOKABLE QString currentLinkUrl() const;
Q_INVOKABLE QString currentLinkText() const;
Q_INVOKABLE void updateLink(const QString &linkUrl, const QString &linkText);
@@ -182,16 +245,18 @@ public:
Q_INVOKABLE void indentListMore();
Q_INVOKABLE void setListStyle(int styleIndex);
Q_INVOKABLE void setHeadingLevel(int level);
Q_INVOKABLE void dumpHtml();
Q_INVOKABLE QString htmlText();
Q_INVOKABLE QString htmlText() const;
Q_SIGNALS:
void typeChanged();
void textItemChanged();
void roomChanged();
void atFirstLineChanged();
void atLastLineChanged();
void fontFamilyChanged();
void textColorChanged();
void alignmentChanged();
@@ -205,11 +270,27 @@ Q_SIGNALS:
void fontSizeChanged();
void fileUrlChanged();
void formatChanged();
void styleChanged();
void contentsChanged();
void unhandledBackspaceAtBeginning(ChatDocumentHandler *self);
void removeMe(ChatDocumentHandler *self);
private:
ChatBarType::Type m_type = ChatBarType::None;
QPointer<QQuickItem> m_textItem;
QTextDocument *document() const;
QPointer<ChatDocumentHandler> m_previousDocumentHandler;
QPointer<ChatDocumentHandler> m_nextDocumentHandler;
QString m_fixedStartChars = {};
QString m_fixedEndChars = {};
QString m_initialText = {};
void initializeChars();
int completionStartIndex() const;
QPointer<NeoChatRoom> m_room;
@@ -226,6 +307,7 @@ private:
CompletionModel *m_completionModel = nullptr;
QTextCursor textCursor() const;
std::optional<Qt::TextFormat> textFormat() const;
void mergeFormatOnWordOrSelection(const QTextCharFormat &format);
void selectLinkText(QTextCursor *cursor) const;
NestedListHelper m_nestedListHelper;
@@ -233,4 +315,9 @@ private:
QColor mLinkColor;
void regenerateColorScheme();
QUrl m_fileUrl;
QString trim(QString string) const;
private Q_SLOTS:
void updateCursor();
};