File indexing completed on 2024-10-06 12:53:59
0001 // SPDX-FileCopyrightText: 2020 Carl Schwan <carl@carlschwan.eu> 0002 // SPDX-License-Identifier: GPL-2.0-or-later 0003 0004 #pragma once 0005 0006 #include <QObject> 0007 #include <QQuickTextDocument> 0008 #include <QTextCursor> 0009 0010 #include "models/completionmodel.h" 0011 #include "neochatroom.h" 0012 0013 class QTextDocument; 0014 class NeoChatRoom; 0015 class SyntaxHighlighter; 0016 0017 /** 0018 * @class ChatDocumentHandler 0019 * 0020 * Handle the QQuickTextDocument of a qml text item. 0021 * 0022 * The class provides functionality to highlight text in the text document as well 0023 * as providing completion functionality via a CompletionModel. 0024 * 0025 * The ChatDocumentHandler is also linked to a NeoChatRoom to provide functionality 0026 * to save the chat document text when switching between rooms. 0027 * 0028 * To get the full functionality the cursor position and text selection information 0029 * need to be passed in. For example: 0030 * 0031 * @code{.qml} 0032 * import QtQuick 2.0 0033 * import QtQuick.Controls 2.15 as QQC2 0034 * 0035 * import org.kde.kirigami 2.12 as Kirigami 0036 * import org.kde.neochat 1.0 0037 * 0038 * QQC2.TextArea { 0039 * id: textField 0040 * 0041 * // Set this to a NeoChatRoom object. 0042 * property var room 0043 * 0044 * ChatDocumentHandler { 0045 * id: documentHandler 0046 * document: textField.textDocument 0047 * cursorPosition: textField.cursorPosition 0048 * selectionStart: textField.selectionStart 0049 * selectionEnd: textField.selectionEnd 0050 * mentionColor: Kirigami.Theme.linkColor 0051 * errorColor: Kirigami.Theme.negativeTextColor 0052 * room: textField.room 0053 * } 0054 * } 0055 * @endcode 0056 * 0057 * @sa QQuickTextDocument, CompletionModel, NeoChatRoom 0058 */ 0059 class ChatDocumentHandler : public QObject 0060 { 0061 Q_OBJECT 0062 0063 /** 0064 * @brief Is the instance being used to handle an edit message. 0065 * 0066 * This is needed to ensure that the text and mentions are saved and retrieved 0067 * from the correct parameters in the assigned room. 0068 */ 0069 Q_PROPERTY(bool isEdit READ isEdit WRITE setIsEdit NOTIFY isEditChanged) 0070 0071 /** 0072 * @brief The QQuickTextDocument that is being handled. 0073 */ 0074 Q_PROPERTY(QQuickTextDocument *document READ document WRITE setDocument NOTIFY documentChanged) 0075 0076 /** 0077 * @brief The current saved cursor position. 0078 */ 0079 Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition NOTIFY cursorPositionChanged) 0080 0081 /** 0082 * @brief The start position of any currently selected text. 0083 */ 0084 Q_PROPERTY(int selectionStart READ selectionStart WRITE setSelectionStart NOTIFY selectionStartChanged) 0085 0086 /** 0087 * @brief The end position of any currently selected text. 0088 */ 0089 Q_PROPERTY(int selectionEnd READ selectionEnd WRITE setSelectionEnd NOTIFY selectionEndChanged) 0090 0091 /** 0092 * @brief The current CompletionModel. 0093 * 0094 * This is typically provided to a qml component to visualise the current 0095 * completion results. 0096 */ 0097 Q_PROPERTY(CompletionModel *completionModel READ completionModel NOTIFY completionModelChanged) 0098 0099 /** 0100 * @brief The current room that the the text document is being handled for. 0101 */ 0102 Q_PROPERTY(NeoChatRoom *room READ room WRITE setRoom NOTIFY roomChanged) 0103 0104 /** 0105 * @brief The color to highlight user mentions. 0106 */ 0107 Q_PROPERTY(QColor mentionColor READ mentionColor WRITE setMentionColor NOTIFY mentionColorChanged); 0108 0109 /** 0110 * @brief The color to highlight spelling errors. 0111 */ 0112 Q_PROPERTY(QColor errorColor READ errorColor WRITE setErrorColor NOTIFY errorColorChanged); 0113 0114 public: 0115 explicit ChatDocumentHandler(QObject *parent = nullptr); 0116 0117 [[nodiscard]] bool isEdit() const; 0118 void setIsEdit(bool edit); 0119 0120 [[nodiscard]] QQuickTextDocument *document() const; 0121 void setDocument(QQuickTextDocument *document); 0122 0123 [[nodiscard]] int cursorPosition() const; 0124 void setCursorPosition(int position); 0125 0126 [[nodiscard]] int selectionStart() const; 0127 void setSelectionStart(int position); 0128 0129 [[nodiscard]] int selectionEnd() const; 0130 void setSelectionEnd(int position); 0131 0132 [[nodiscard]] NeoChatRoom *room() const; 0133 void setRoom(NeoChatRoom *room); 0134 0135 Q_INVOKABLE void complete(int index); 0136 0137 void updateCompletions(); 0138 CompletionModel *completionModel() const; 0139 0140 [[nodiscard]] QColor mentionColor() const; 0141 void setMentionColor(const QColor &color); 0142 0143 [[nodiscard]] QColor errorColor() const; 0144 void setErrorColor(const QColor &color); 0145 0146 Q_SIGNALS: 0147 void isEditChanged(); 0148 void documentChanged(); 0149 void cursorPositionChanged(); 0150 void roomChanged(); 0151 void completionModelChanged(); 0152 void selectionStartChanged(); 0153 void selectionEndChanged(); 0154 void errorColorChanged(); 0155 void mentionColorChanged(); 0156 0157 private: 0158 int completionStartIndex() const; 0159 0160 bool m_isEdit = false; 0161 0162 QPointer<QQuickTextDocument> m_document; 0163 0164 QPointer<NeoChatRoom> m_room; 0165 bool completionVisible = false; 0166 0167 QColor m_mentionColor; 0168 QColor m_errorColor; 0169 0170 int m_cursorPosition; 0171 int m_selectionStart; 0172 int m_selectionEnd; 0173 0174 QString getText() const; 0175 void pushMention(const Mention mention) const; 0176 0177 SyntaxHighlighter *m_highlighter = nullptr; 0178 0179 CompletionModel::AutoCompletionType m_completionType = CompletionModel::None; 0180 0181 CompletionModel *m_completionModel = nullptr; 0182 };