File indexing completed on 2024-12-08 04:34:13

0001 /*
0002    SPDX-FileCopyrightText: 2021 David Faure <faure@kde.org>
0003    SPDX-FileCopyrightText: 2024 Laurent Montel <montel@kde.org>
0004 
0005    SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #pragma once
0009 
0010 #include "libruqolawidgets_private_export.h"
0011 #include "messages/block.h"
0012 #include "messages/messageattachment.h"
0013 #include "messages/messageurl.h"
0014 
0015 #include <QObject>
0016 #include <QPersistentModelIndex>
0017 
0018 class QTextCursor;
0019 class QTextDocument;
0020 class Message;
0021 
0022 class LIBRUQOLAWIDGETS_TESTS_EXPORT DocumentFactoryInterface
0023 {
0024 public:
0025     virtual ~DocumentFactoryInterface();
0026     /**
0027      * Creates (or retrieves from a cache) the QTextDocument for a given @p index.
0028      * @param width The width for layouting that QTextDocument. -1 if no layouting is desired (e.g. for converting to text or HTML)
0029      * @return the QTextDocument. Ownership remains with the cache, don't delete it.
0030      */
0031     [[nodiscard]] virtual QTextDocument *documentForIndex(const QModelIndex &index) const
0032     {
0033         Q_UNUSED(index);
0034         Q_ASSERT(false);
0035         return nullptr;
0036     }
0037     [[nodiscard]] virtual QTextDocument *documentForAttachement(const MessageAttachment &msgAttach) const
0038     {
0039         Q_UNUSED(msgAttach);
0040         Q_ASSERT(false);
0041         return nullptr;
0042     }
0043     [[nodiscard]] virtual QTextDocument *documentForBlock(const Block &block) const
0044     {
0045         Q_UNUSED(block);
0046         Q_ASSERT(false);
0047         return nullptr;
0048     }
0049     [[nodiscard]] virtual QTextDocument *documentForUrlPreview(const MessageUrl &messageUrl) const
0050     {
0051         Q_UNUSED(messageUrl);
0052         Q_ASSERT(false);
0053         return nullptr;
0054     }
0055 };
0056 
0057 class LIBRUQOLAWIDGETS_TESTS_EXPORT TextSelection : public QObject
0058 {
0059     Q_OBJECT
0060 public:
0061     TextSelection();
0062     [[nodiscard]] bool hasSelection() const;
0063     enum Format {
0064         Text,
0065         Html,
0066     };
0067     [[nodiscard]] QString selectedText(Format format) const;
0068     [[nodiscard]] bool contains(const QModelIndex &index, int charPos, const MessageAttachment &att = {}) const;
0069     [[nodiscard]] QTextCursor
0070     selectionForIndex(const QModelIndex &index, QTextDocument *doc, const MessageAttachment &att = {}, const MessageUrl &msgUrl = {}) const;
0071 
0072     void clear();
0073     void setStart(const QModelIndex &index, int charPos, const MessageAttachment &msgAttach = {});
0074     void setEnd(const QModelIndex &index, int charPos, const MessageAttachment &msgAttach = {});
0075     void selectWordUnderCursor(const QModelIndex &index, int charPos, DocumentFactoryInterface *factory);
0076     void selectWordUnderCursor(const QModelIndex &index, int charPos, DocumentFactoryInterface *factory, const MessageAttachment &msgAttach);
0077     void selectWordUnderCursor(const QModelIndex &index, int charPos, DocumentFactoryInterface *factory, const MessageUrl &msgUrl);
0078     void selectMessage(const QModelIndex &index);
0079 
0080     void setTextHelperFactory(DocumentFactoryInterface *newTextHelperFactory);
0081     [[nodiscard]] DocumentFactoryInterface *textHelperFactory() const;
0082 
0083     void setAttachmentFactories(const QVector<DocumentFactoryInterface *> &newAttachmentFactories);
0084 
0085     [[nodiscard]] const QVector<DocumentFactoryInterface *> &attachmentFactories() const;
0086 
0087     [[nodiscard]] DocumentFactoryInterface *messageUrlHelperFactory() const;
0088     void setMessageUrlHelperFactory(DocumentFactoryInterface *newMessageUrlHelperFactory);
0089 
0090 Q_SIGNALS:
0091     void repaintNeeded(const QModelIndex &index);
0092 
0093 private:
0094     void selectWord(const QModelIndex &index, int charPos, QTextDocument *doc);
0095     struct OrderedPositions {
0096         int fromRow;
0097         int fromCharPos;
0098         int toRow;
0099         int toCharPos;
0100     };
0101 
0102     struct AttachmentSelection {
0103         MessageAttachment attachment;
0104         int fromCharPos = 0;
0105         int toCharPos = 0;
0106     };
0107 
0108     struct MessageUrlSelection {
0109         MessageUrl messageUrl;
0110         int fromCharPos = 0;
0111         int toCharPos = 0;
0112     };
0113 
0114     [[nodiscard]] OrderedPositions orderedPositions() const;
0115     void selectionText(const OrderedPositions ordered,
0116                        Format format,
0117                        int row,
0118                        const QModelIndex &index,
0119                        QTextDocument *doc,
0120                        QString &str,
0121                        const MessageAttachment &att = {},
0122                        const MessageUrl &messageUrl = {}) const;
0123 
0124     QPersistentModelIndex mStartIndex;
0125     QPersistentModelIndex mEndIndex;
0126     QVector<AttachmentSelection> mAttachmentSelection;
0127     QVector<MessageUrlSelection> mMessageUrlSelection;
0128     int mStartPos = -1; // first selected character in start row
0129     int mEndPos = -1; // last selected character in end row
0130 
0131     DocumentFactoryInterface *mTextHelperFactory = nullptr;
0132     DocumentFactoryInterface *mMessageUrlHelperFactory = nullptr;
0133     QVector<DocumentFactoryInterface *> mAttachmentFactories;
0134 };