File indexing completed on 2024-05-19 05:21:46
0001 /* 0002 SPDX-FileCopyrightText: 2019-2021 Montel Laurent <montel@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 0006 */ 0007 #pragma once 0008 0009 #include "abstractmarkupbuilder.h" 0010 #include "kpimtextedit_export.h" 0011 #include <QTextDocument> 0012 #include <QTextFrame> 0013 class QTextTable; 0014 class QTextTableCell; 0015 class QTextList; 0016 class QTextCharFormat; 0017 0018 namespace KPIMTextEdit 0019 { 0020 class MarkupDirectorPrivate; 0021 class AbstractMarkupBuilder; 0022 0023 /// @headerfile markupdirector.h grantlee/markupdirector.h 0024 0025 /** 0026 @brief Instructs a builder object to create markup output 0027 0028 The **%MarkupDirector** is used with an implementation of 0029 AbstractMarkupBuilder to create a marked up document output. 0030 0031 Usage can be quite simple. 0032 0033 @code 0034 auto doc = editor->document(); // editor is a QTextEdit 0035 0036 auto builder = new HTMLBuilder(); 0037 auto md = new MarkupDirector(builder); 0038 md->processDocument(doc); 0039 browser->setHtml(builder->getResult()); // browser is a QTextBrowser. 0040 @endcode 0041 0042 Or with a different builder: 0043 0044 @code 0045 auto builder = new PlainTextMarkupBuilder(); 0046 auto md = new MarkupDirector(builder); 0047 md->processDocument(doc); 0048 browser->setPlainText(builder->getResult()); 0049 @endcode 0050 0051 The **%MarkupDirector** also provides API for processing just part of a 0052 QTextDocument, such as a QTextFrame or a QTextBlock. The appropriate method 0053 may then be called with an invalid iterator as appropriate. 0054 0055 @code 0056 // ... Do some processing to get a QTextFrame. 0057 auto frame = getFrame(); 0058 0059 auto builder = new PlainTextMarkupBuilder(); 0060 auto md = new MarkupDirector(builder); 0061 0062 // Create output from only the frame. 0063 md->processFrame(QTextFrame::iterator(), frame); 0064 browser->setPlainText(builder->getResult()); 0065 @endcode 0066 0067 The behaviour of the **%MarkupDirector** can be customized by subclassing. 0068 Support for custom types can also be added by implementing the @ref 0069 processCustomFragment method. 0070 0071 @see @ref custom_qtextobject 0072 0073 @author Stephen Kelly <steveire@gmail.com> 0074 */ 0075 class KPIMTEXTEDIT_EXPORT MarkupDirector 0076 { 0077 public: 0078 /** 0079 Constructor 0080 */ 0081 explicit MarkupDirector(KPIMTextEdit::AbstractMarkupBuilder *builder); 0082 0083 /** 0084 Destructor 0085 */ 0086 virtual ~MarkupDirector(); 0087 0088 /** 0089 Constructs the output by directing the builder to create the markup. 0090 */ 0091 virtual void processDocument(QTextDocument *doc); 0092 0093 /** 0094 Directs the builder to create output for the single @p frame. If calling 0095 this method directly, an invalid QTextFrame::iterator may be used. 0096 */ 0097 [[nodiscard]] virtual QTextFrame::iterator processFrame(QTextFrame::iterator it, QTextFrame *frame); 0098 0099 /** 0100 Directs the builder to create output for the single @p block. If calling 0101 this method directly, an invalid QTextFrame::iterator may be used. 0102 0103 This method does not process the contents of the @p block, but uses the 0104 @ref processBlockContents method to do so. 0105 */ 0106 [[nodiscard]] virtual QTextFrame::iterator processBlock(QTextFrame::iterator it, const QTextBlock &block); 0107 0108 /** 0109 Directs the builder to create output for the single @p textObject. If 0110 calling this method directly, an invalid QTextFrame::iterator may be used. 0111 0112 The block @p block is the container of the @p textObject. 0113 */ 0114 [[nodiscard]] virtual QTextFrame::iterator processObject(QTextFrame::iterator it, const QTextBlock &block, QTextObject *textObject); 0115 0116 /** 0117 Directs the builder to create output for the single @p textBlockGroup. If 0118 calling this method directly, an invalid QTextFrame::iterator may be used. 0119 0120 The block @p block is the first block in the @p textBlockGroup. 0121 */ 0122 [[nodiscard]] virtual QPair<QTextFrame::iterator, QTextBlock> 0123 processBlockGroup(const QTextFrame::iterator &it, const QTextBlock &block, QTextBlockGroup *textBlockGroup); 0124 0125 /** 0126 Directs the builder to create output for the single @p textList. If 0127 calling this method directly, an invalid QTextFrame::iterator may be used. 0128 0129 The block @p block is the first block in the @p textList. 0130 */ 0131 [[nodiscard]] virtual QPair<QTextFrame::iterator, QTextBlock> processList(QTextFrame::iterator it, const QTextBlock &block, QTextList *textList); 0132 0133 /** 0134 Directs the builder to create output for the contents of the single @p 0135 block. If calling this method directly, an invalid QTextFrame::iterator 0136 may be used. 0137 */ 0138 virtual QTextFrame::iterator processBlockContents(QTextFrame::iterator it, const QTextBlock &block); 0139 0140 /** 0141 Hook for instructing the builder to create output for the @p fragemnt with 0142 a custom type. @p doc is the document the fragment is in. 0143 */ 0144 virtual void processCustomFragment(const QTextFragment &fragment, QTextDocument const *doc); 0145 0146 /** 0147 Directs the builder to create output for the contents of the single @p 0148 fragment. If calling this method directly, an invalid QTextBlock::iterator 0149 may be used. @p doc is the document the fragment is in. 0150 */ 0151 [[nodiscard]] virtual QTextBlock::iterator processFragment(QTextBlock::iterator it, const QTextFragment &fragment, QTextDocument const *doc); 0152 0153 /** 0154 Directs the builder to create output for the contents of the single @p 0155 textObject. The @p textObject is represented in the QTextDocument with the 0156 QTextFragment @p fragment. 0157 0158 If calling this method directly, an invalid QTextBlock::iterator may be 0159 used. 0160 */ 0161 [[nodiscard]] virtual QTextBlock::iterator processCharTextObject(QTextBlock::iterator it, const QTextFragment &fragment, QTextObject *textObject); 0162 0163 /** 0164 Directs the builder to create output for the image represented by the @p 0165 imageFormat. 0166 0167 If calling this method directly, an invalid QTextBlock::iterator may be 0168 used. @p doc is the document the fragment is in. 0169 */ 0170 [[nodiscard]] virtual QTextBlock::iterator processImage(QTextBlock::iterator it, const QTextImageFormat &imageFormat, QTextDocument const *doc); 0171 0172 /** 0173 Directs the builder to create output for the contents of the single @p 0174 table. 0175 0176 If calling this method directly, an invalid QTextFrame::iterator may be 0177 used. 0178 */ 0179 [[nodiscard]] virtual QTextFrame::iterator processTable(QTextFrame::iterator it, QTextTable *table); 0180 0181 /** 0182 Directs the builder to create output for the contents of the single @p 0183 tableCell. The tableCell is in the @p table. 0184 */ 0185 virtual void processTableCell(const QTextTableCell &tableCell, QTextTable *table); 0186 0187 protected: 0188 /** 0189 Processes the document between @p begin and @p end 0190 */ 0191 void processDocumentContents(QTextFrame::iterator begin, const QTextFrame::iterator &end); 0192 0193 /** 0194 Iterates the iterator @p it to the first block after @p blockGroup. @p 0195 _block is any block in the @p blockGroup. 0196 0197 The return pair is the iterator pointing after the end of @p blockGroup 0198 and the first block after @p blockGroup. 0199 */ 0200 [[nodiscard]] QPair<QTextFrame::iterator, QTextBlock> skipBlockGroup(QTextFrame::iterator it, const QTextBlock &_block, QTextBlockGroup *blockGroup); 0201 0202 /** 0203 Returns a list of tags contained in @p openingTags sorted so they can be 0204 opened in order and will be closed in the correct order. 0205 0206 @p openingTags should be a set of tags opened at the fragment pointed to 0207 by @p it. 0208 */ 0209 [[nodiscard]] QList<int> sortOpeningOrder(QSet<int> openingTags, QTextBlock::iterator it) const; 0210 0211 /** 0212 Directs the builder to close the appropriate tags at the position of @p 0213 it. 0214 */ 0215 virtual void processClosingElements(const QTextBlock::iterator &it); 0216 0217 /** 0218 Directs the builder to open the appropriate tags at the position of @p it. 0219 */ 0220 virtual void processOpeningElements(const QTextBlock::iterator &it); 0221 0222 /** 0223 Returns the tags that should be closed at the position of @p it. 0224 */ 0225 [[nodiscard]] virtual QSet<int> getElementsToClose(const QTextBlock::iterator &it) const; 0226 0227 /** 0228 Returns the tags that should be opened at the position of @p it. 0229 */ 0230 [[nodiscard]] virtual QList<int> getElementsToOpen(const QTextBlock::iterator &it); 0231 0232 /** 0233 Flags for the tags that may be open. 0234 */ 0235 enum OpenElementValues { 0236 None = 0x0, /// No tags are open 0237 SuperScript = 0x01, /// A superscript tag is open 0238 SubScript = 0x02, /// A subscript tag is open 0239 Anchor = 0x04, /// An anchor tag is open 0240 SpanForeground = 0x08, /// A foreground altering span tag is open. 0241 SpanBackground = 0x10, /// A background altering span tag is open. 0242 SpanFontFamily = 0x20, /// A font family altering span tag is open. 0243 SpanFontPointSize = 0x40, /// A font size altering span tag is open. 0244 Strong = 0x80, /// A strong tag is open. 0245 Emph = 0x100, /// A emphasis tag is open. 0246 Underline = 0x200, /// An underline tag is open. 0247 StrikeOut = 0x400 /// A strikeout tag is open. 0248 }; 0249 0250 protected: 0251 #ifndef Q_QDOC 0252 MarkupDirectorPrivate *const d_ptr; 0253 #endif 0254 0255 /** 0256 The builder this MarkupDirector is operating on. This is available when 0257 subclassing to customize behaviour. 0258 */ 0259 KPIMTextEdit::AbstractMarkupBuilder *const m_builder; 0260 0261 #ifndef Q_QDOC 0262 private: 0263 Q_DECLARE_PRIVATE(MarkupDirector) 0264 #endif 0265 }; 0266 }