File indexing completed on 2024-04-21 04:59:18

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