File indexing completed on 2025-02-09 04:28:37

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_FILTEREXPRESSION_H
0011 #define KTEXTTEMPLATE_FILTEREXPRESSION_H
0012 
0013 #include "variable.h"
0014 
0015 #include "ktexttemplate_export.h"
0016 
0017 namespace KTextTemplate
0018 {
0019 class Filter;
0020 class OutputStream;
0021 class Parser;
0022 struct Token;
0023 
0024 class FilterExpressionPrivate;
0025 
0026 /// @headerfile filterexpression.h <KTextTemplate/FilterExpression>
0027 
0028 /**
0029   @brief A **%FilterExpression** object represents a filter expression in a
0030   template.
0031 
0032   This class is only relevant if implementing custom tags or filters. Most of
0033   the API here is internal.
0034   Usually when implementing tags or filters, filter expressions will just be
0035   created and resolved.
0036 
0037   In template markup, a filter expression is a variable followed by one or more
0038   filters separated by pipes:
0039 
0040   %Filter expressions may appear in variable nodes:
0041   @code
0042     {{ some_var|upper_filter|lower_filter }}
0043   @endcode
0044 
0045   Or as arguments to tags
0046   @code
0047     {% some_tag some_arg1|filter1|filter2 some_arg2|filter3 %}
0048   @endcode
0049 
0050   The **%FilterExpression** class would be used in the getNode implementation of
0051   the AbstractNodeFactory implementation for the <tt>some_tag</tt> tag.
0052 
0053   @code
0054     Node* SomeTagFactory::getNode(const QString &tagContent, Parser *p) const {
0055       auto parts = smartSplit( tagContent );
0056 
0057       parts.removeFirst(); // Remove the "some_tag" part.
0058 
0059       FilterExpression arg1( parts.first(), p );
0060       FilterExpression arg2( parts.at( 1 ), p );
0061 
0062       return new SomeTagNode( arg1, arg2, p );
0063     }
0064   @endcode
0065 
0066   @see AbstractNodeFactory::getFilterExpressionList
0067 
0068   When implementing the Node::render method, the @ref resolve method may be used
0069   to process the filter expression.
0070 
0071   For example, if our <tt>SomeTagNode</tt> was to concatenate the resolved
0072   values given as arguments:
0073 
0074   @code
0075     void SomeTagNode::render( QTextStream *stream, Context *c ) {
0076       m_arg1.resolve( stream, c );
0077       m_arg2.resolve( stream, c );
0078     }
0079   @endcode
0080 
0081   Because Filters are highly generic, they do not all write data to the stream.
0082   For example, a Filter might take as input a string, and return a list by
0083   splitting the string on commas, or a Filter might compare an input to its
0084   argument and return whether they are the same, but not write anything to the
0085   stream. For that reason, the @ref resolve method writes data to the given
0086   stream, and returns the same data in its returned QVariant.
0087 
0088   The suitability of either of the @ref resolve methods will depend on the
0089   implementation and requirements of your custom tag. For example if the
0090   <tt>SomeTagNode</tt> ran a comparison of the arguments:
0091 
0092   @code
0093     void SomeTagNode::render( QTextStream *stream, Context *c ) {
0094       QString first = m_arg1.resolve( c ).toString();
0095       QString second = m_arg2.resolve( c ).toString();
0096 
0097       if ( first == second )
0098         m_trueList.render( stream, c );
0099       else
0100         m_falseList.render( stream, c );
0101     }
0102   @endcode
0103 
0104   @see @ref tags_with_end_tags
0105 
0106   @author Stephen Kelly <steveire@gmail.com>
0107 */
0108 class KTEXTTEMPLATE_EXPORT FilterExpression
0109 {
0110 public:
0111     /**
0112       Constructs an invalid **%FilterExpression**.
0113     */
0114     FilterExpression();
0115 
0116     /**
0117       Constructs a filter expression from the string @p varString. The Parser @p
0118       parser is used to retrieve filters.
0119     */
0120     FilterExpression(const QString &varString, KTextTemplate::Parser *parser);
0121 
0122     /**
0123       Copy constructor.
0124     */
0125     FilterExpression(const FilterExpression &other);
0126 
0127     /**
0128       Destructor.
0129     */
0130     ~FilterExpression();
0131 
0132     /**
0133       Assignment operator.
0134     */
0135     FilterExpression &operator=(const FilterExpression &other);
0136 
0137     /**
0138       Returns the initial variable in the **%FilterExpression**.
0139     */
0140     Variable variable() const;
0141 
0142     /**
0143       Resolves the **%FilterExpression** in the Context @p c and writes it to the
0144       stream @p stream.
0145     */
0146     QVariant resolve(OutputStream *stream, Context *c) const;
0147 
0148     /**
0149       Resolves the **%FilterExpression** in the Context @p c.
0150     */
0151     QVariant resolve(Context *c) const;
0152 
0153     /**
0154       Returns whether the Filter resolves to true in the Context @p c.
0155       @see @ref truthiness
0156     */
0157     bool isTrue(Context *c) const;
0158 
0159     /**
0160       Returns a list for the **%FilterExpression**.
0161 
0162       If the **%FilterExpression** can not be resolved to a list, an empty list
0163       will be returned.
0164     */
0165     QVariantList toList(Context *c) const;
0166 
0167     /**
0168       Returns whether a filter expression is valid.
0169 
0170       A **%FilterExpression** is valid if all filters in the expression exist and
0171       the initial variable being filtered is valid.
0172     */
0173     bool isValid() const;
0174 
0175 #ifndef K_DOXYGEN
0176     /**
0177       @internal
0178       Returns the list of filters in the **%FilterExpression**.
0179     */
0180     QStringList filters() const;
0181 #endif
0182 
0183 private:
0184     Q_DECLARE_PRIVATE(FilterExpression)
0185     FilterExpressionPrivate *const d_ptr;
0186 };
0187 }
0188 
0189 #endif