File indexing completed on 2025-02-09 04:28:38
0001 /* 0002 This file is part of the KTextTemplate library 0003 0004 SPDX-FileCopyrightText: 2009, 2010 Stephen Kelly <steveire@gmail.com> 0005 0006 SPDX-License-Identifier: LGPL-2.1-or-later 0007 0008 */ 0009 0010 #ifndef KTEXTTEMPLATE_NODE_H 0011 #define KTEXTTEMPLATE_NODE_H 0012 0013 // krazy:excludeall=dpointer 0014 0015 #include "context.h" 0016 #include "filterexpression.h" 0017 #include "ktexttemplate_export.h" 0018 #include "outputstream.h" 0019 #include "safestring.h" 0020 0021 #include <QStringList> 0022 0023 // Need these for inheriting from QList<T> to work 0024 // http://lists.trolltech.com/qt-interest/2008-01/thread00578-0.html 0025 #include <QList> 0026 #include <QSet> 0027 0028 namespace KTextTemplate 0029 { 0030 0031 class Engine; 0032 class NodeList; 0033 class TemplateImpl; 0034 0035 class NodePrivate; 0036 0037 /// @headerfile node.h <KTextTemplate/Node> 0038 0039 /** 0040 @brief Base class for all nodes. 0041 0042 The **%Node** class can be implemented to make additional functionality 0043 available to Templates. 0044 0045 A node is represented in template markup as content surrounded by percent 0046 signed tokens. 0047 0048 @code 0049 text content 0050 {% some_tag arg1 arg2 %} 0051 text content 0052 {% some_other_tag arg1 arg2 %} 0053 text content 0054 {% end_some_other_tag %} 0055 text content 0056 @endcode 0057 0058 This is parsed into a tree of **%Node** objects by an implementation of 0059 AbstractNodeFactory. The **%Node** objects can then later be rendered by their 0060 @ref render method. 0061 0062 Rendering a **%Node** will usually mean writing some output to the stream. The 0063 content written to the stream could be determined by the arguments to the tag, 0064 or by the content of child nodes between a start and end tag, or both. 0065 0066 @see FilterExpression 0067 @see @ref tags 0068 0069 @author Stephen Kelly <steveire@gmail.com> 0070 */ 0071 class KTEXTTEMPLATE_EXPORT Node : public QObject 0072 { 0073 Q_OBJECT 0074 public: 0075 /** 0076 Constructor. 0077 0078 @param parent The parent QObject 0079 */ 0080 explicit Node(QObject *parent = {}); 0081 0082 /** 0083 Destructor. 0084 */ 0085 ~Node() override; 0086 0087 /** 0088 Reimplement this to render the template in the Context @p c. 0089 0090 This will also involve calling render on and child nodes. 0091 */ 0092 virtual void render(OutputStream *stream, Context *c) const = 0; 0093 0094 #ifndef K_DOXYGEN 0095 /** 0096 @internal 0097 */ 0098 virtual bool mustBeFirst() 0099 { // krazy:exclude:inline 0100 return false; 0101 } 0102 #endif 0103 0104 protected: 0105 /** 0106 Renders the value @p input in the Context @p c. This will involve escaping 0107 @p input if necessary. 0108 0109 This is only relevant to developing template tags. 0110 */ 0111 void streamValueInContext(OutputStream *stream, const QVariant &input, KTextTemplate::Context *c) const; 0112 0113 /** 0114 Returns a raw pointer to the Template this **%Node** is in. 0115 */ 0116 TemplateImpl *containerTemplate() const; 0117 0118 private: 0119 Q_DECLARE_PRIVATE(Node) 0120 NodePrivate *const d_ptr; 0121 }; 0122 0123 /// @headerfile node.h KTextTemplate/node.h 0124 0125 /** 0126 @brief A list of Nodes with some convenience API for rendering them. 0127 0128 Typically, tags which have an end tag will create and later render a list of 0129 child nodes. 0130 0131 This class contains API such as @ref append and @ref render to make creating 0132 such list easily. 0133 0134 The @ref findChildren method behaves similarly to the QObject::findChildren 0135 method, returning a list of nodes of a particular type from the Node objects 0136 contained in the list (and their children). 0137 0138 @see @ref tags_with_end_tags 0139 */ 0140 class KTEXTTEMPLATE_EXPORT NodeList : public QList<KTextTemplate::Node *> 0141 { 0142 public: 0143 /** 0144 Creates an empty **%NodeList**. 0145 */ 0146 NodeList(); 0147 0148 /** 0149 Copy constructor. 0150 */ 0151 NodeList(const NodeList &list); 0152 0153 NodeList &operator=(const NodeList &list); 0154 0155 /** 0156 Convenience constructor 0157 */ 0158 /* implicit */ NodeList(const QList<KTextTemplate::Node *> &list); 0159 0160 /** 0161 Destructor. 0162 */ 0163 ~NodeList(); 0164 0165 /** 0166 Appends @p node to the end of this **%NodeList**. 0167 */ 0168 void append(KTextTemplate::Node *node); 0169 0170 /** 0171 Appends @p nodeList to the end of this **%NodeList**. 0172 */ 0173 void append(const QList<KTextTemplate::Node *> &nodeList); 0174 0175 /** 0176 Returns true if this **%NodeList** contains non-text nodes. 0177 */ 0178 bool containsNonText() const; 0179 0180 /** 0181 A recursive listing of nodes in this tree of type @p T. 0182 */ 0183 template<typename T> 0184 QList<T> findChildren() 0185 { 0186 QList<T> children; 0187 QList<KTextTemplate::Node *>::const_iterator it; 0188 const QList<KTextTemplate::Node *>::const_iterator first = constBegin(); 0189 const QList<KTextTemplate::Node *>::const_iterator last = constEnd(); 0190 for (it = first; it != last; ++it) { 0191 T object = qobject_cast<T>(*it); 0192 if (object) { 0193 children << object; 0194 } 0195 children << (*it)->findChildren<T>(); 0196 } 0197 return children; 0198 } 0199 0200 /** 0201 Renders the list of Nodes in the Context @p c. 0202 */ 0203 void render(OutputStream *stream, Context *c) const; 0204 0205 private: 0206 bool m_containsNonText; 0207 }; 0208 0209 class AbstractNodeFactoryPrivate; 0210 0211 /// @headerfile node.h KTextTemplate/node.h 0212 0213 /** 0214 @brief Base class for all NodeFactories 0215 0216 This class can be used to make custom tags available to templates. 0217 The getNode method should be implemented to return a Node to be rendered. 0218 0219 A node is represented in template markup as content surrounded by percent 0220 signed tokens. 0221 0222 @code 0223 text content 0224 {% some_tag arg1 arg2 %} 0225 text content 0226 {% some_other_tag arg1 arg2 %} 0227 text content 0228 {% end_some_other_tag %} 0229 text content 0230 @endcode 0231 0232 It is the responsibility of an **%AbstractNodeFactory** implementation to 0233 process the contents of a tag and return a Node implementation from its 0234 getNode method. 0235 0236 The @ref getNode method would for example be called with the tagContent 0237 \"<tt>some_tag arg1 arg2</tt>\". That content could then be split up, the 0238 arguments processed and a Node created 0239 0240 @code 0241 Node* SomeTagFactory::getNode(const QString &tagContent, Parser *p) { 0242 QStringList parts = smartSplit( tagContent ); 0243 0244 parts.removeFirst(); // Remove the "some_tag" part. 0245 0246 FilterExpression arg1( parts.first(), p ); 0247 FilterExpression arg2( parts.at( 1 ), p ); 0248 0249 return new SomeTagNode( arg1, arg2, p ); 0250 } 0251 @endcode 0252 0253 The @ref getNode implementation might also advance the parser. For example if 0254 we had a @gr_tag{times} tag which rendered content the amount of times it was 0255 given in its argument, it could be used like this: 0256 0257 @code 0258 Some text content. 0259 {% times 5 %} 0260 the bit to be repeated 0261 {% end_times %} 0262 End text content 0263 @endcode 0264 0265 The argument to @gr_tag{times} might not be a simple number, but could be a 0266 FilterExpression such as \"<tt>someobject.some_property|getDigit:1</tt>\". 0267 0268 The implementation could look like 0269 0270 @code 0271 Node* SomeOtherTagFactory::getNode(const QString &tagContent, Parser *p) { 0272 QStringList parts = smartSplit( tagContent ); 0273 0274 parts.removeFirst(); // Remove the "times" part. 0275 0276 FilterExpression arg( parts.first(), p ); 0277 0278 auto node = new SomeTagNode( arg, p ); 0279 auto childNodes = p->parse( node, "end_times" ); 0280 node->setChildNodes( childNodes ); 0281 p->removeNextToken(); 0282 0283 return node; 0284 } 0285 @endcode 0286 0287 Note that it is necessary to invoke the parser to create the child nodes only 0288 after creating the Node to return. That node must be passed to the Parser to 0289 perform as the parent QObject to the child nodes. 0290 0291 @see Parser::parse 0292 */ 0293 class KTEXTTEMPLATE_EXPORT AbstractNodeFactory : public QObject 0294 { 0295 Q_OBJECT 0296 public: 0297 /** 0298 Constructor. 0299 0300 @param parent The parent QObject 0301 */ 0302 explicit AbstractNodeFactory(QObject *parent = {}); 0303 0304 /** 0305 Destructor. 0306 */ 0307 ~AbstractNodeFactory() override; 0308 0309 /** 0310 This method should be reimplemented to return a Node which can be 0311 rendered. 0312 0313 The @p tagContent is the content of the tag including the tag name and 0314 arguments. For example, if the template content is @gr_tag{my_tag arg1 0315 arg2}, the tagContent will be "my_tag arg1 arg2". 0316 0317 The Parser @p p is available and can be advanced if appropriate. For 0318 example, if the tag has an end tag, the parser can be advanced to the end 0319 tag. 0320 0321 @see tags 0322 */ 0323 virtual Node *getNode(const QString &tagContent, Parser *p) const = 0; 0324 0325 #ifndef K_DOXYGEN 0326 /** 0327 @internal 0328 0329 Sets the Engine which created this NodeFactory. Used by the 0330 ScriptableNodeFactory. 0331 */ 0332 virtual void setEngine(Engine *) 0333 { 0334 } 0335 #endif 0336 0337 protected: 0338 /** 0339 Splits @p str into a list, taking quote marks into account. 0340 0341 This is typically used in the implementation of getNode with the 0342 tagContent. 0343 0344 If @p str is 'one "two three" four 'five " six' seven', the 0345 returned list will contain the following strings: 0346 0347 - one 0348 - "two three" 0349 - four 0350 - five " six 0351 - seven 0352 */ 0353 Q_INVOKABLE QStringList smartSplit(const QString &str) const; 0354 0355 protected: 0356 /** 0357 Returns a list of FilterExpression objects created with Parser @p p as 0358 described by the content of @p list. 0359 0360 This is used for convenience when handling the arguments to a tag. 0361 */ 0362 QList<FilterExpression> getFilterExpressionList(const QStringList &list, Parser *p) const; 0363 0364 private: 0365 Q_DECLARE_PRIVATE(AbstractNodeFactory) 0366 AbstractNodeFactoryPrivate *const d_ptr; 0367 }; 0368 } 0369 0370 #endif