Fix Qt6 deprecated APIs: QCheckBox::checkStateChanged, ExploratoryLocationViewshed

- Replace QCheckBox::stateChanged with checkStateChanged in:
  - lts_dialog.cpp
  - simple_esri_layer.cpp (2 occurrences)
  - layer_control_widget.cpp
  - symbol_dialog.cpp
- Replace LocationViewshed with ExploratoryLocationViewshed (ArcGIS SDK v300):
  - viewshed_analysis.h/.cpp
  - ViewshedLocation.h/.cpp
  - function_dialog.cpp (include)
- Update ViewshedLocation member variable type to ExploratoryLocationViewshed

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
torstenandCopilot committed 2026-10-13 14:41:33 +02:00
1 parent e581d1e91c
commit 124fbb4de8
1079 files changed
+111705 -17

No files matched your search

@@ -0,0 +1,140 @@
/*
This file is part of the KTextTemplate library
SPDX-FileCopyrightText: 2010 Stephen Kelly <steveire@gmail.com>
SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef KTEXTTEMPLATE_ABSTRACTLOCALIZER_H
#define KTEXTTEMPLATE_ABSTRACTLOCALIZER_H
#include "ktexttemplate_export.h"
#include <QLocale>
#include <QSharedPointer>
#include <QVariantList>
class QDateTime;
namespace KTextTemplate
{
/// @headerfile abstractlocalizer.h <KTextTemplate/AbstractLocalizer>
/**
@brief Interface for implementing an internationalization system.
This class defines an interface for accessing an internationalization, such as
QLocale/QTranslator or gettext/KLocale.
@author Stephen Kelly <steveire@gmail.com>
*/
class KTEXTTEMPLATE_EXPORT AbstractLocalizer
{
public:
/**
Constructor
*/
AbstractLocalizer();
/**
Destructor
*/
virtual ~AbstractLocalizer();
/**
Processes the data in @p variant into a localized string.
The base implementation can localize numbers, dates and times, and
strings.
*/
virtual QString localize(const QVariant &variant) const;
/**
Returns the current locale as a string.
*/
virtual QString currentLocale() const = 0;
/**
Makes this localizer use the locale specified by @p localeName for output.
*/
virtual void pushLocale(const QString &localeName) = 0;
/**
Makes this localizer use the previous locale for output.
*/
virtual void popLocale() = 0;
/**
Loads the @p catalog from @p path.
*/
virtual void loadCatalog(const QString &path, const QString &catalog) = 0;
/**
Unloads the @p catalog
*/
virtual void unloadCatalog(const QString &catalog) = 0;
/**
Localizes @p number
*/
virtual QString localizeNumber(int number) const = 0;
/**
Localizes @p number
*/
virtual QString localizeNumber(qreal number) const = 0;
/**
Localizes @p value as a monetary value in the currency specified by @p
currencyCode.
*/
virtual QString localizeMonetaryValue(qreal value, const QString &currencyCode = {}) const = 0;
/**
Localizes @p date with the specified @p formatType
*/
virtual QString localizeDate(const QDate &date, QLocale::FormatType formatType = QLocale::ShortFormat) const = 0;
/**
Localizes @p time with the specified @p formatType
*/
virtual QString localizeTime(const QTime &time, QLocale::FormatType formatType = QLocale::ShortFormat) const = 0;
/**
Localizes @p dateTime with the specified @p formatType
*/
virtual QString localizeDateTime(const QDateTime &dateTime, QLocale::FormatType formatType = QLocale::ShortFormat) const = 0;
/**
Localizes @p string with the specified @p arguments for substitution
*/
virtual QString localizeString(const QString &string, const QVariantList &arguments = {}) const = 0;
/**
Localizes @p string, disambiguated by @p context with the specified @p
arguments for substitution
*/
virtual QString localizeContextString(const QString &string, const QString &context, const QVariantList &arguments = {}) const = 0;
/**
Localizes @p string or its @p pluralForm with the specified @p arguments
for substitution
*/
virtual QString localizePluralString(const QString &string, const QString &pluralForm, const QVariantList &arguments = {}) const = 0;
/**
Localizes @p string or its @p pluralForm, disambiguated by @p context with
the specified @p arguments for substitution
*/
virtual QString
localizePluralContextString(const QString &string, const QString &pluralForm, const QString &context, const QVariantList &arguments = {}) const = 0;
private:
Q_DISABLE_COPY(AbstractLocalizer)
};
}
#endif
@@ -0,0 +1,99 @@
/*
This file is part of the KTextTemplate library
SPDX-FileCopyrightText: 2010 Stephen Kelly <steveire@gmail.com>
SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef KTEXTTEMPLATE_CACHINGLOADERDECORATOR_H
#define KTEXTTEMPLATE_CACHINGLOADERDECORATOR_H
#include "templateloader.h"
#include "ktexttemplate_export.h"
namespace KTextTemplate
{
class CachingLoaderDecoratorPrivate;
/// @headerfile cachingloaderdecorator.h <KTextTemplate/CachingLoaderDecorator>
/**
@brief Implements a loader decorator which caches compiled Template objects.
The **%CachingLoaderDecorator** can be used with any implementation of
KTextTemplate::AbstractTemplateLoader.
@code
auto loader = QSharedPointer<KTextTemplate::FileSystemTemplateLoader>::create();
loader->setTemplateDirs({"/path/one", "/path/two"});
auto cache =
QSharedPointer<KTextTemplate::CachingLoaderDecorator>::create( loader );
m_engine->addTemplateLoader( cache );
@endcode
The effect is that templates do not need to be loaded from the filesystem and
compiled into Template objects on each access, but may be returned from the
cache instead.
This can be significant if loading Templates in a loop, or loading the same
Template very often in an application.
@code
<ul>
{% for item in list %}
<li>{% include "itemtemplate.html" %}</li>
{% endfor %}
</ul>
@endcode
If the loading of Templates is a bottleneck in an application, it may make
sense to use the caching decorator.
@author Stephen Kelly <steveire@gmail.com>
*/
class KTEXTTEMPLATE_EXPORT CachingLoaderDecorator : public AbstractTemplateLoader
{
public:
/**
Constructor
*/
CachingLoaderDecorator(QSharedPointer<AbstractTemplateLoader> loader);
/**
Destructor
*/
~CachingLoaderDecorator() override;
bool canLoadTemplate(const QString &name) const override;
std::pair<QString, QString> getMediaUri(const QString &fileName) const override;
Template loadByName(const QString &name, const KTextTemplate::Engine *engine) const override;
/**
Clears the Templates objects cached in the decorator.
*/
void clear();
/**
Returns the number of Template objects cached in the decorator.
*/
int size() const;
/**
Returns whether the cache is empty.
*/
bool isEmpty() const;
private:
Q_DECLARE_PRIVATE(CachingLoaderDecorator)
CachingLoaderDecoratorPrivate *const d_ptr;
};
}
#endif
@@ -0,0 +1,271 @@
/*
This file is part of the KTextTemplate library
SPDX-FileCopyrightText: 2009, 2010 Stephen Kelly <steveire@gmail.com>
SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef KTEXTTEMPLATE_CONTEXT_H
#define KTEXTTEMPLATE_CONTEXT_H
#include "abstractlocalizer.h"
#include "ktexttemplate_export.h"
#include <QVariantHash>
namespace KTextTemplate
{
class RenderContext;
class ContextPrivate;
/// @headerfile context.h <KTextTemplate/Context>
/**
@brief The **%Context** class holds the context to render a Template with.
For application developers, using the **%Context** class is a matter of
inserting keys and values as appropriate for rendering a Template using the
@ref insert method.
@code
auto t = engine->newTemplate(
"Name is {% name %} and age is {% age %}.", "some_template" );
Context c1;
c1.insert( "name", "Tom" );
c1.insert( "age", 34 );
Context c2;
c2.insert( "name", "Harry" );
c2.insert( "age", 43 );
t->render(c1); // Returns "Name is Tom and age is 43."
t->render(c2); // Returns "Name is Harry and age is 34."
@endcode
Note that one Template may be rendered multiple times with different contexts.
Note also that any QVariant may be inserted into a **%Context** object. Most
commonly, QObjects will be used here.
@see @ref custom_objects
@section context_stack Context Stack.
For template tag developers, some other **%Context** API is relevant.
It is possible to @ref push and @ref pop layers of context while a template
is being rendered. This is useful if your template tag makes additional
variables temporarily available in a part of a template. %Template tags
should only modify layers of context that they @ref push themselves, and
should @ref pop any layers created before finishing its rendering step.
See for example the @gr_tag{with} tag. In a template such as
@code
Some content
{% with person.name|toUpper as lowerName %}
Name is {% lowerName %}
{% endwith %}
@endcode
In this case, lowerName is available in the context only between the
@gr_tag{with} and @gr_tag{endwith} tags. The implementation of
the @gr_tag{with} tag render method is:
@code
void WithNode::render( OutputStream *stream, Context *c ) const
{
c->push();
// {% with m_filterExpression as m_name %}
c->insert( m_name, m_filterExpression.resolve( c ) );
m_list.render( stream, c );
c->pop(); // The section of context defining m_name is removed.
}
@endcode
Note that a **%Context** may temporarily override a variable in a parent
context. This is why it is important to @ref push a new context when adding
items to context and @ref pop it when finished.
@code
Some content
{% with "foo" as var %}
Var is {% var %} // Var is "foo"
{% with "bar" as var %}
Var is {% var %} // Var is "bar"
{% endwith %}
Var is {% var %} // Var is "foo"
{% endwith %}
@endcode
@author Stephen Kelly <steveire@gmail.com>
*/
class KTEXTTEMPLATE_EXPORT Context
{
public:
/**
Creates an empty context
*/
Context();
/**
Sets every key in the hash as a property name with the variant as the
value.
*/
explicit Context(const QVariantHash &hash);
/**
Copy Constructor
*/
Context(const Context &other);
/**
Assignmant operator
*/
Context &operator=(const Context &other);
#ifndef K_DOXYGEN
/**
@internal
Whether to automatically escape all context content. This is not usually
used directly. Use the @gr_tag{autoescape} tag instead.
*/
bool autoEscape() const;
/**
@internal
Sets whether to automatically escape all context content. This is not
usually used directly. Use the @gr_tag{autoescape} tag instead.
*/
void setAutoEscape(bool autoescape);
#endif
/**
Destructor
*/
~Context();
/**
Returns the context object identified by the key @p str
*/
QVariant lookup(const QString &str) const;
/**
Insert the context object @p object identified by @p name into
the **%Context**.
*/
void insert(const QString &name, QObject *object);
/**
Insert the context object @p variant identified by @p name into
the **%Context**.
*/
void insert(const QString &name, const QVariant &variant);
/**
Pushes a new context.
@see @ref context_stack
*/
void push();
/**
Pops the context.
@see @ref context_stack
*/
void pop();
#ifndef K_DOXYGEN
/**
@internal Returns the context hash at depth @p depth.
*/
QVariantHash stackHash(int depth) const;
/**
@internal
Returns whether template being rendered is being mutated.
*/
bool isMutating() const;
/**
@internal
Sets whether template being rendered is being mutated to @p mutating.
*/
void setMutating(bool mutating);
/**
@internal
*/
void addExternalMedia(const QString &absolutePart, const QString &relativePart);
/**
@internal
*/
void clearExternalMedia();
#endif
/**
Sets the @p localizer to be used.
The **%Context** takes ownerwhip of the localizer.
*/
void setLocalizer(QSharedPointer<AbstractLocalizer> localizer);
/**
Returns the localizer currently in use.
*/
QSharedPointer<AbstractLocalizer> localizer() const;
/**
Returns the external media encountered in the Template while rendering.
*/
QList<std::pair<QString, QString>> externalMedia() const;
/**
The type of urls to external media that should be put in the template.
*/
enum UrlType {
AbsoluteUrls, ///< Absolute URLs should be put in the template.
RelativeUrls ///< Relative URLs should be put in the template.
};
/**
Sets the type of external media URL to be used in the template to @p type.
@see @ref media_finder_tag
*/
void setUrlType(UrlType type);
/**
The type of URL used in the template.
*/
UrlType urlType() const;
/**
Sets the relative path to external media to be used in templates to @p
relativePath
@see @ref media_finder_tag
*/
void setRelativeMediaPath(const QString &relativePath);
/**
The relative path to external media to be used in templates.
*/
QString relativeMediaPath() const;
/**
Returns a modifiable RenderContext. This may be used to make
Template rendering threadsafe so that render state does not need to be
stored in the Node implementation itself.
*/
RenderContext *renderContext() const;
private:
Q_DECLARE_PRIVATE(Context)
ContextPrivate *const d_ptr;
};
}
#endif
@@ -0,0 +1,248 @@
/*
This file is part of the KTextTemplate library
SPDX-FileCopyrightText: 2009, 2010 Stephen Kelly <steveire@gmail.com>
SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef KTEXTTEMPLATE_ENGINE_H
#define KTEXTTEMPLATE_ENGINE_H
#include "template.h"
#include "templateloader.h"
namespace KTextTemplate
{
class TagLibraryInterface;
class EnginePrivate;
/// @headerfile engine.h <KTextTemplate/Engine>
/**
@brief **%KTextTemplate::Engine** is the main entry point for creating %KTextTemplate
Templates.
The **%KTextTemplate::Engine** is responsible for configuring and creating Template
objects. In typical use, one or more AbstractTemplateLoader objects will be
added to the Engine to load template objects, and plugin directories will be
set to enable finding template tags and filters.
@code
auto engine = new Engine();
auto loader = QSharedPointer<FileSystemTemplateLoader>::create();
loader->setTemplateDirs( {"/usr/share/myapp/templates"} );
engine->addTemplateLoader( loader );
engine->addPluginPath( "/usr/lib/myapp" );
auto template1 = engine->newTemplate( "Template content", "template name" );
auto template2 = engine->loadByName( "templatefile.html" );
@endcode
Once it is configured, the **%Engine** can be used to create new templates by
name by loading the templates with the @ref loadByName method, or by defining
the content in the @ref newTemplate method.
By default the builtin tags and filters distributed with %KTextTemplate are
available in all templates without using the @gr_tag{load} tag in the
template. These pre-loaded libraries may be configured if appropriate to the
application. For example, an application which defines its own tags and
filters may want them to be always available, or it may be desirable to
restrict the features available to template authors by removing built in
libraries.
Different **%Engine** objects can be used to create templates with differing
configurations.
@section smart_trim Insignificant whitespace
The output of rendering a template depends on the content of the template. In
some cases when generating content in which whitespace is significant, this
can have undesired effects. For example, given a template to generate C++ code
like:
@verbatim
class MyClass {
{# This loop creates the #}
{# methods in the class #}
{% for method in methods %}
{% if method.hasDox %}
{{ method.dox }}
{% endif %}
{{ method.signature }}
{% endfor %}
};
@endverbatim
The output would have a lot of whitespace which is not necessarily wanted.
@code
class MyClass {
void foo() const;
};
@endcode
It is possible to strip insignificant whitespace by enabling the smartTrim
feature with @ref setSmartTrimEnabled. When enabled the output will not
contain a newline for any line in the template which has only one token of
template syntax, such as a comment, tag or variable.
@code
class MyClass {
void foo() const;
};
@endcode
@author Stephen Kelly <steveire@gmail.com>
*/
class KTEXTTEMPLATE_EXPORT Engine : public QObject
{
Q_OBJECT
public:
/**
Constructor
*/
Engine(QObject *parent = {});
/**
Destructor.
*/
~Engine() override;
/**
Returns the TemplateLoaders currently configured on the **%Engine**.
*/
QList<QSharedPointer<AbstractTemplateLoader>> templateLoaders();
/**
Adds @p loader to the TemplateLoaders currently configured on
the **%Engine**.
*/
void addTemplateLoader(QSharedPointer<AbstractTemplateLoader> loader);
/**
Sets the plugin dirs currently configured on the **%Engine** to @p dirs.
@warning This overwrites the default paths. You normally want
@ref addPluginPath.
@see @ref finding_plugins
*/
void setPluginPaths(const QStringList &dirs);
/**
Prepend @p dir to the list of plugin dirs.
*/
void addPluginPath(const QString &dir);
/**
Removes all instances of @p dir from the list of plugin dirs.
*/
void removePluginPath(const QString &dir);
/**
Returns the currently configured plugin dirs
*/
QStringList pluginPaths() const;
/**
Returns a URI for a media item with the name @p name.
Typically this will be used for images. For example the media URI for the
image <tt>"header_logo.png"</tt> may be
<tt>"/home/user/common/header_logo.png"</tt> or
<tt>"/home/user/some_theme/header_logo.png"</tt>
depending on the @ref templateLoaders configured.
This method will not usually be called by application code. To load media
in a template, use the @gr_tag{media_finder} template tag.
*/
std::pair<QString, QString> mediaUri(const QString &fileName) const;
/**
Load the Template identified by @p name.
The Templates and plugins loaded will be determined by
the **%Engine** configuration.
*/
Template loadByName(const QString &name) const;
/**
Create a new Template with the content @p content identified by @p name.
The secondary Templates and plugins loaded will be determined by
the **%Engine** configuration.
*/
Template newTemplate(const QString &content, const QString &name) const;
/**
Returns the libraries available by default to new Templates.
*/
QStringList defaultLibraries() const;
/**
Adds the library named @p libName to the libraries available by default to
new Templates.
*/
void addDefaultLibrary(const QString &libName);
/**
Removes the library named @p libName from the libraries available by
default to new Templates.
*/
void removeDefaultLibrary(const QString &libName);
/**
Returns whether the smart trim feature is enabled for newly loaded
templates.
@see smart_trim
This is false by default.
*/
bool smartTrimEnabled() const;
/**
Sets whether the smart trim feature is enabled for newly loaded templates.
@see smart_trim
*/
void setSmartTrimEnabled(bool enabled);
#ifndef K_DOXYGEN
/**
@internal
Loads and returns the libraries specified in defaultLibraries or @p state.
*/
void loadDefaultLibraries();
/**
@internal
Loads and returns the library specified by @p name in the
current **%Engine** configuration or @p state.
Templates wishing to load a library should use the @gr_tag{load} tag.
*/
TagLibraryInterface *loadLibrary(const QString &name);
#endif
private:
Q_DECLARE_PRIVATE(Engine)
EnginePrivate *const d_ptr;
};
}
#endif
@@ -0,0 +1,118 @@
/*
This file is part of the KTextTemplate library
SPDX-FileCopyrightText: 2009, 2010 Stephen Kelly <steveire@gmail.com>
SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef KTEXTTEMPLATE_EXCEPTION_H
#define KTEXTTEMPLATE_EXCEPTION_H
#include "ktexttemplate_export.h"
#include <QString>
#include <exception>
namespace KTextTemplate
{
/**
Types of errors that can occur while using %KTextTemplate
*/
enum Error {
NoError,
EmptyVariableError,
EmptyBlockTagError,
InvalidBlockTagError,
UnclosedBlockTagError,
UnknownFilterError,
TagSyntaxError,
// VariableSyntaxError,
VariableNotInContext,
ObjectReturnTypeInvalid,
CompileFunctionError
};
/// @headerfile exception.h <KTextTemplate/Exception>
/**
@brief An exception for use when implementing template tags.
The **%Exception** class can be used when implementing
AbstractNodeFactory::getNode. An exception can be thrown to indicate that
the syntax of a particular tag is invalid.
For example, the following template markup should throw an error because the
include tag should have exactly one argument:
@code
<div>
{% include %}
</div>
@endcode
The corresponding implementation of IncludeNodeFactory::getNode is
@code
QStringList tagContents = smartSplit( tagContent );
if ( tagContents.size() != 2 )
throw KTextTemplate::Exception( TagSyntaxError,
"Error: Include tag takes exactly one argument" );
// The item at index 0 in the list is the tag name, "include"
QString includeName = tagContents.at( 1 );
@endcode
@author Stephen Kelly <steveire@gmail.com>
*/
class KTEXTTEMPLATE_EXPORT Exception
{
public:
/**
Creates an exception for the error @p errorCode and the verbose
message @p what
*/
Exception(Error errorCode, const QString &what)
: m_errorCode(errorCode)
, m_what(what)
{
}
virtual ~Exception() throw()
{
}
#ifndef K_DOXYGEN
/**
@internal
Returns the verbose message for the exception.
*/
const QString what() const throw()
{
return m_what;
}
/**
@internal
Returns the error code for the exception.
*/
Error errorCode() const
{
return m_errorCode;
}
#endif
private:
Error m_errorCode;
QString m_what;
};
}
#endif
@@ -0,0 +1,104 @@
/*
This file is part of the KTextTemplate library
SPDX-FileCopyrightText: 2009, 2010 Stephen Kelly <steveire@gmail.com>
SPDX-License-Identifier: LGPL-2.1-or-later
*/
// krazy:excludeall=dpointer
#ifndef KTEXTTEMPLATE_FILTER_H
#define KTEXTTEMPLATE_FILTER_H
#include "ktexttemplate_export.h"
#include "outputstream.h"
#include "safestring.h"
#include <QSharedPointer>
#include <QStringList>
#include <QVariant>
namespace KTextTemplate
{
/// @headerfile filter.h <KTextTemplate/Filter>
/**
@brief Base class for all filters.
The **%Filter** class can be implemented in plugin libraries to make
additional functionality available to templates.
Developers are required only to implement the @ref doFilter method and
integrate the filter as part of a custom plugin, but will never create or
access filters directly in application code.
The FilterExpression class is the access interface to a chain of **%Filter**
objects.
The @ref escape and @ref conditionalEscape methods are available for escaping
data where needed.
@see @ref filters
@author Stephen Kelly <steveire@gmail.com>
*/
class KTEXTTEMPLATE_EXPORT Filter
{
public:
/**
Destructor.
*/
virtual ~Filter();
#ifndef K_DOXYGEN
/**
FilterExpression makes it possible to access stream methods like escape
while resolving.
*/
void setStream(OutputStream *stream);
#endif
/**
Escapes and returns @p input. The OutputStream::escape method is used to
escape @p input.
*/
SafeString escape(const QString &input) const;
/**
Escapes and returns @p input. The OutputStream::escape method is used to
escape @p input.
*/
SafeString escape(const SafeString &input) const;
/**
Escapes @p input if not already safe from further escaping and returns it.
The OutputStream::escape method is used to escape @p input.
*/
SafeString conditionalEscape(const SafeString &input) const;
/**
Reimplement to filter @p input given @p argument.
@p autoescape determines whether the autoescape feature is currently on or
off. Most filters will not use this.
@see @ref autoescaping
*/
virtual QVariant doFilter(const QVariant &input, const QVariant &argument = {}, bool autoescape = {}) const = 0;
/**
Reimplement to return whether this filter is safe.
*/
virtual bool isSafe() const;
private:
#ifndef K_DOXYGEN
OutputStream *m_stream;
#endif
};
}
#endif
@@ -0,0 +1,189 @@
/*
This file is part of the KTextTemplate library
SPDX-FileCopyrightText: 2009, 2010 Stephen Kelly <steveire@gmail.com>
SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef KTEXTTEMPLATE_FILTEREXPRESSION_H
#define KTEXTTEMPLATE_FILTEREXPRESSION_H
#include "variable.h"
#include "ktexttemplate_export.h"
namespace KTextTemplate
{
class Filter;
class OutputStream;
class Parser;
struct Token;
class FilterExpressionPrivate;
/// @headerfile filterexpression.h <KTextTemplate/FilterExpression>
/**
@brief A **%FilterExpression** object represents a filter expression in a
template.
This class is only relevant if implementing custom tags or filters. Most of
the API here is internal.
Usually when implementing tags or filters, filter expressions will just be
created and resolved.
In template markup, a filter expression is a variable followed by one or more
filters separated by pipes:
%Filter expressions may appear in variable nodes:
@code
{{ some_var|upper_filter|lower_filter }}
@endcode
Or as arguments to tags
@code
{% some_tag some_arg1|filter1|filter2 some_arg2|filter3 %}
@endcode
The **%FilterExpression** class would be used in the getNode implementation of
the AbstractNodeFactory implementation for the <tt>some_tag</tt> tag.
@code
Node* SomeTagFactory::getNode(const QString &tagContent, Parser *p) const {
auto parts = smartSplit( tagContent );
parts.removeFirst(); // Remove the "some_tag" part.
FilterExpression arg1( parts.first(), p );
FilterExpression arg2( parts.at( 1 ), p );
return new SomeTagNode( arg1, arg2, p );
}
@endcode
@see AbstractNodeFactory::getFilterExpressionList
When implementing the Node::render method, the @ref resolve method may be used
to process the filter expression.
For example, if our <tt>SomeTagNode</tt> was to concatenate the resolved
values given as arguments:
@code
void SomeTagNode::render( QTextStream *stream, Context *c ) {
m_arg1.resolve( stream, c );
m_arg2.resolve( stream, c );
}
@endcode
Because Filters are highly generic, they do not all write data to the stream.
For example, a Filter might take as input a string, and return a list by
splitting the string on commas, or a Filter might compare an input to its
argument and return whether they are the same, but not write anything to the
stream. For that reason, the @ref resolve method writes data to the given
stream, and returns the same data in its returned QVariant.
The suitability of either of the @ref resolve methods will depend on the
implementation and requirements of your custom tag. For example if the
<tt>SomeTagNode</tt> ran a comparison of the arguments:
@code
void SomeTagNode::render( QTextStream *stream, Context *c ) {
QString first = m_arg1.resolve( c ).toString();
QString second = m_arg2.resolve( c ).toString();
if ( first == second )
m_trueList.render( stream, c );
else
m_falseList.render( stream, c );
}
@endcode
@see @ref tags_with_end_tags
@author Stephen Kelly <steveire@gmail.com>
*/
class KTEXTTEMPLATE_EXPORT FilterExpression
{
public:
/**
Constructs an invalid **%FilterExpression**.
*/
FilterExpression();
/**
Constructs a filter expression from the string @p varString. The Parser @p
parser is used to retrieve filters.
*/
FilterExpression(const QString &varString, KTextTemplate::Parser *parser);
/**
Copy constructor.
*/
FilterExpression(const FilterExpression &other);
/**
Destructor.
*/
~FilterExpression();
/**
Assignment operator.
*/
FilterExpression &operator=(const FilterExpression &other);
/**
Returns the initial variable in the **%FilterExpression**.
*/
Variable variable() const;
/**
Resolves the **%FilterExpression** in the Context @p c and writes it to the
stream @p stream.
*/
QVariant resolve(OutputStream *stream, Context *c) const;
/**
Resolves the **%FilterExpression** in the Context @p c.
*/
QVariant resolve(Context *c) const;
/**
Returns whether the Filter resolves to true in the Context @p c.
@see @ref truthiness
*/
bool isTrue(Context *c) const;
/**
Returns a list for the **%FilterExpression**.
If the **%FilterExpression** can not be resolved to a list, an empty list
will be returned.
*/
QVariantList toList(Context *c) const;
/**
Returns whether a filter expression is valid.
A **%FilterExpression** is valid if all filters in the expression exist and
the initial variable being filtered is valid.
*/
bool isValid() const;
#ifndef K_DOXYGEN
/**
@internal
Returns the list of filters in the **%FilterExpression**.
*/
QStringList filters() const;
#endif
private:
Q_DECLARE_PRIVATE(FilterExpression)
FilterExpressionPrivate *const d_ptr;
};
}
#endif
@@ -0,0 +1,112 @@
#ifndef KTEXTTEMPLATE_EXPORT_H
#define KTEXTTEMPLATE_EXPORT_H
#ifdef KTEXTTEMPLATE_STATIC_DEFINE
# define KTEXTTEMPLATE_EXPORT
# define KTEXTTEMPLATE_NO_EXPORT
#else
# ifndef KTEXTTEMPLATE_EXPORT
# ifdef KF6TextTemplate_EXPORTS
/* We are building this library */
# define KTEXTTEMPLATE_EXPORT __attribute__((visibility("default")))
# else
/* We are using this library */
# define KTEXTTEMPLATE_EXPORT __attribute__((visibility("default")))
# endif
# endif
# ifndef KTEXTTEMPLATE_NO_EXPORT
# define KTEXTTEMPLATE_NO_EXPORT __attribute__((visibility("hidden")))
# endif
#endif
#ifndef KTEXTTEMPLATE_DECL_DEPRECATED
# define KTEXTTEMPLATE_DECL_DEPRECATED __attribute__ ((__deprecated__))
#endif
#ifndef KTEXTTEMPLATE_DECL_DEPRECATED_EXPORT
# define KTEXTTEMPLATE_DECL_DEPRECATED_EXPORT KTEXTTEMPLATE_EXPORT KTEXTTEMPLATE_DECL_DEPRECATED
#endif
#ifndef KTEXTTEMPLATE_DECL_DEPRECATED_NO_EXPORT
# define KTEXTTEMPLATE_DECL_DEPRECATED_NO_EXPORT KTEXTTEMPLATE_NO_EXPORT KTEXTTEMPLATE_DECL_DEPRECATED
#endif
#if 0 /* DEFINE_NO_DEPRECATED */
# ifndef KTEXTTEMPLATE_NO_DEPRECATED
# define KTEXTTEMPLATE_NO_DEPRECATED
# endif
#endif
#include <ktexttemplate_version.h>
#define KTEXTTEMPLATE_DECL_DEPRECATED_TEXT(text) __attribute__ ((__deprecated__(text)))
/* Take any defaults from group settings */
#if !defined(KTEXTTEMPLATE_NO_DEPRECATED) && !defined(KTEXTTEMPLATE_DISABLE_DEPRECATED_BEFORE_AND_AT)
# ifdef KF_NO_DEPRECATED
# define KTEXTTEMPLATE_NO_DEPRECATED
# elif defined(KF_DISABLE_DEPRECATED_BEFORE_AND_AT)
# define KTEXTTEMPLATE_DISABLE_DEPRECATED_BEFORE_AND_AT KF_DISABLE_DEPRECATED_BEFORE_AND_AT
# endif
#endif
#if !defined(KTEXTTEMPLATE_DISABLE_DEPRECATED_BEFORE_AND_AT) && defined(KF_DISABLE_DEPRECATED_BEFORE_AND_AT)
# define KTEXTTEMPLATE_DISABLE_DEPRECATED_BEFORE_AND_AT KF_DISABLE_DEPRECATED_BEFORE_AND_AT
#endif
#if !defined(KTEXTTEMPLATE_NO_DEPRECATED_WARNINGS) && !defined(KTEXTTEMPLATE_DEPRECATED_WARNINGS_SINCE)
# ifdef KF_NO_DEPRECATED_WARNINGS
# define KTEXTTEMPLATE_NO_DEPRECATED_WARNINGS
# elif defined(KF_DEPRECATED_WARNINGS_SINCE)
# define KTEXTTEMPLATE_DEPRECATED_WARNINGS_SINCE KF_DEPRECATED_WARNINGS_SINCE
# endif
#endif
#if !defined(KTEXTTEMPLATE_DEPRECATED_WARNINGS_SINCE) && defined(KF_DEPRECATED_WARNINGS_SINCE)
# define KTEXTTEMPLATE_DEPRECATED_WARNINGS_SINCE KF_DEPRECATED_WARNINGS_SINCE
#endif
#if defined(KTEXTTEMPLATE_NO_DEPRECATED)
# undef KTEXTTEMPLATE_DEPRECATED
# define KTEXTTEMPLATE_DEPRECATED_EXPORT KTEXTTEMPLATE_EXPORT
# define KTEXTTEMPLATE_DEPRECATED_NO_EXPORT KTEXTTEMPLATE_NO_EXPORT
#elif defined(KTEXTTEMPLATE_NO_DEPRECATED_WARNINGS)
# define KTEXTTEMPLATE_DEPRECATED
# define KTEXTTEMPLATE_DEPRECATED_EXPORT KTEXTTEMPLATE_EXPORT
# define KTEXTTEMPLATE_DEPRECATED_NO_EXPORT KTEXTTEMPLATE_NO_EXPORT
#else
# define KTEXTTEMPLATE_DEPRECATED KTEXTTEMPLATE_DECL_DEPRECATED
# define KTEXTTEMPLATE_DEPRECATED_EXPORT KTEXTTEMPLATE_DECL_DEPRECATED_EXPORT
# define KTEXTTEMPLATE_DEPRECATED_NO_EXPORT KTEXTTEMPLATE_DECL_DEPRECATED_NO_EXPORT
#endif
/* No deprecated API had been removed from build */
#define KTEXTTEMPLATE_EXCLUDE_DEPRECATED_BEFORE_AND_AT 0
#define KTEXTTEMPLATE_BUILD_DEPRECATED_SINCE(major, minor) 1
#ifdef KTEXTTEMPLATE_NO_DEPRECATED
# define KTEXTTEMPLATE_DISABLE_DEPRECATED_BEFORE_AND_AT KTEXTTEMPLATE_VERSION
#endif
#ifdef KTEXTTEMPLATE_NO_DEPRECATED_WARNINGS
# define KTEXTTEMPLATE_DEPRECATED_WARNINGS_SINCE 0
#endif
#ifndef KTEXTTEMPLATE_DEPRECATED_WARNINGS_SINCE
# ifdef KTEXTTEMPLATE_DISABLE_DEPRECATED_BEFORE_AND_AT
# define KTEXTTEMPLATE_DEPRECATED_WARNINGS_SINCE KTEXTTEMPLATE_DISABLE_DEPRECATED_BEFORE_AND_AT
# else
# define KTEXTTEMPLATE_DEPRECATED_WARNINGS_SINCE KTEXTTEMPLATE_VERSION
# endif
#endif
#ifndef KTEXTTEMPLATE_DISABLE_DEPRECATED_BEFORE_AND_AT
# define KTEXTTEMPLATE_DISABLE_DEPRECATED_BEFORE_AND_AT 0
#endif
#ifdef KTEXTTEMPLATE_DEPRECATED
# define KTEXTTEMPLATE_ENABLE_DEPRECATED_SINCE(major, minor) (((major<<16)|(minor<<8)) > KTEXTTEMPLATE_DISABLE_DEPRECATED_BEFORE_AND_AT)
#else
# define KTEXTTEMPLATE_ENABLE_DEPRECATED_SINCE(major, minor) 0
#endif
#endif /* KTEXTTEMPLATE_EXPORT_H */
@@ -0,0 +1,232 @@
/*
This file is part of the KTextTemplate library
SPDX-FileCopyrightText: 2010 Michael Jansen <kde@michael-jansen.biz>
SPDX-FileCopyrightText: 2010 Stephen Kelly <steveire@gmail.com>
SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef KTEXTTEMPLATE_METATYPE_H
#define KTEXTTEMPLATE_METATYPE_H
#include "ktexttemplate_export.h"
#include "typeaccessor.h"
#include <QVariant>
/// @file
namespace KTextTemplate
{
/// @headerfile metatype.h <KTextTemplate/MetaType>
#ifndef K_DOXYGEN
/**
@brief The **%MetaType** is the interface to the KTextTemplate introspection
system.
The **%MetaType** class is used as part of the type registration system of
%KTextTemplate.
@see @ref generic_types_and_templates
@author Michael Jansen <kde@michael-jansen.biz>
@author Stephen Kelly <steveire@gmail.com>
*/
class KTEXTTEMPLATE_EXPORT MetaType
{
public:
/**
@internal The signature for a property lookup method
*/
typedef QVariant (*LookupFunction)(const QVariant &, const QString &);
/**
@internal Registers a property lookup method
*/
static void registerLookUpOperator(int id, LookupFunction f);
/**
@internal
*/
static void internalLock();
/**
@internal
*/
static void internalUnlock();
/**
@internal
*/
static QVariant lookup(const QVariant &object, const QString &property);
/**
@internal
*/
static bool lookupAlreadyRegistered(int id);
private:
MetaType();
};
#endif
namespace
{
/*
This is a helper to select an appropriate overload of indexAccess
*/
template<typename RealType, typename HandleAs>
struct LookupTrait {
static QVariant doLookUp(const QVariant &object, const QString &property)
{
typedef typename KTextTemplate::TypeAccessor<RealType> Accessor;
return Accessor::lookUp(object.value<RealType>(), property);
}
};
template<typename RealType, typename HandleAs>
struct LookupTrait<RealType &, HandleAs &> {
static QVariant doLookUp(const QVariant &object, const QString &property)
{
typedef typename KTextTemplate::TypeAccessor<HandleAs &> Accessor;
return Accessor::lookUp(object.value<HandleAs>(), property);
}
};
template<typename RealType, typename HandleAs>
static int doRegister(int id)
{
if (MetaType::lookupAlreadyRegistered(id))
return id;
QVariant (*lf)(const QVariant &, const QString &) = LookupTrait<RealType, HandleAs>::doLookUp;
MetaType::registerLookUpOperator(id, reinterpret_cast<MetaType::LookupFunction>(lf));
return id;
}
/*
Register a type so KTextTemplate knows how to handle it.
*/
template<typename RealType, typename HandleAs>
struct InternalRegisterType {
static int doReg()
{
const int id = qMetaTypeId<RealType>();
return doRegister<RealType &, HandleAs &>(id);
}
};
template<typename RealType, typename HandleAs>
struct InternalRegisterType<RealType *, HandleAs *> {
static int doReg()
{
const int id = qMetaTypeId<RealType *>();
return doRegister<RealType *, HandleAs *>(id);
}
};
}
/**
@brief Registers the type RealType with the metatype system.
This method can take a second template parameter to specify a cast
that should be invoked during registration. This is useful if a base type is
already supported.
@code
class SomeType
{
public:
QString someProp() const;
};
// define some introspectable API for SomeType
KTEXTTEMPLATE_BEGIN_LOOKUP(SomeType)
if (property == "someProp")
return object.someProp();
KTEXTTEMPLATE_END_LOOKUP
class OtherType : public SomeType
{
// ...
};
registerMetaType<SomeType>();
// Only the introspectable API from SomeType is needed, so we can reuse that
registration.
registerMetaType<OtherType, SomeType>();
@endcode
@see @ref generic_types_and_templates
*/
template<typename RealType, typename HandleAs>
int registerMetaType()
{
MetaType::internalLock();
const int id = InternalRegisterType<RealType, HandleAs>::doReg();
MetaType::internalUnlock();
return id;
}
#ifndef K_DOXYGEN
/**
@internal
Register a type so %KTextTemplate knows how to handle it.
This is a convenience method.
*/
template<typename Type>
int registerMetaType()
{
return registerMetaType<Type, Type>();
}
#endif
} // namespace KTextTemplate
/**
Top boundary of a lookup function for Type.
@see @ref generic_types
*/
#define KTEXTTEMPLATE_BEGIN_LOOKUP(Type) \
namespace KTextTemplate \
{ \
template<> \
inline QVariant TypeAccessor<Type &>::lookUp(const Type &object, const QString &property) \
{
/**
Top boundary of a lookup function for Type*.
@see @ref generic_types
*/
#define KTEXTTEMPLATE_BEGIN_LOOKUP_PTR(Type) \
namespace KTextTemplate \
{ \
template<> \
inline QVariant TypeAccessor<Type *>::lookUp(const Type *const object, const QString &property) \
{
/**
Bottom boundary of a lookup function for Type.
@see @ref generic_types
*/
#define KTEXTTEMPLATE_END_LOOKUP \
return QVariant(); \
} \
}
#endif // #define KTEXTTEMPLATE_METATYPE_H
@@ -0,0 +1,370 @@
/*
This file is part of the KTextTemplate library
SPDX-FileCopyrightText: 2009, 2010 Stephen Kelly <steveire@gmail.com>
SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef KTEXTTEMPLATE_NODE_H
#define KTEXTTEMPLATE_NODE_H
// krazy:excludeall=dpointer
#include "context.h"
#include "filterexpression.h"
#include "ktexttemplate_export.h"
#include "outputstream.h"
#include "safestring.h"
#include <QStringList>
// Need these for inheriting from QList<T> to work
// http://lists.trolltech.com/qt-interest/2008-01/thread00578-0.html
#include <QList>
#include <QSet>
namespace KTextTemplate
{
class Engine;
class NodeList;
class TemplateImpl;
class NodePrivate;
/// @headerfile node.h <KTextTemplate/Node>
/**
@brief Base class for all nodes.
The **%Node** class can be implemented to make additional functionality
available to Templates.
A node is represented in template markup as content surrounded by percent
signed tokens.
@code
text content
{% some_tag arg1 arg2 %}
text content
{% some_other_tag arg1 arg2 %}
text content
{% end_some_other_tag %}
text content
@endcode
This is parsed into a tree of **%Node** objects by an implementation of
AbstractNodeFactory. The **%Node** objects can then later be rendered by their
@ref render method.
Rendering a **%Node** will usually mean writing some output to the stream. The
content written to the stream could be determined by the arguments to the tag,
or by the content of child nodes between a start and end tag, or both.
@see FilterExpression
@see @ref tags
@author Stephen Kelly <steveire@gmail.com>
*/
class KTEXTTEMPLATE_EXPORT Node : public QObject
{
Q_OBJECT
public:
/**
Constructor.
@param parent The parent QObject
*/
explicit Node(QObject *parent = {});
/**
Destructor.
*/
~Node() override;
/**
Reimplement this to render the template in the Context @p c.
This will also involve calling render on and child nodes.
*/
virtual void render(OutputStream *stream, Context *c) const = 0;
#ifndef K_DOXYGEN
/**
@internal
*/
virtual bool mustBeFirst()
{ // krazy:exclude:inline
return false;
}
#endif
protected:
/**
Renders the value @p input in the Context @p c. This will involve escaping
@p input if necessary.
This is only relevant to developing template tags.
*/
void streamValueInContext(OutputStream *stream, const QVariant &input, KTextTemplate::Context *c) const;
/**
Returns a raw pointer to the Template this **%Node** is in.
*/
TemplateImpl *containerTemplate() const;
private:
Q_DECLARE_PRIVATE(Node)
NodePrivate *const d_ptr;
};
/// @headerfile node.h KTextTemplate/node.h
/**
@brief A list of Nodes with some convenience API for rendering them.
Typically, tags which have an end tag will create and later render a list of
child nodes.
This class contains API such as @ref append and @ref render to make creating
such list easily.
The @ref findChildren method behaves similarly to the QObject::findChildren
method, returning a list of nodes of a particular type from the Node objects
contained in the list (and their children).
@see @ref tags_with_end_tags
*/
class KTEXTTEMPLATE_EXPORT NodeList : public QList<KTextTemplate::Node *>
{
public:
/**
Creates an empty **%NodeList**.
*/
NodeList();
/**
Copy constructor.
*/
NodeList(const NodeList &list);
NodeList &operator=(const NodeList &list);
/**
Convenience constructor
*/
/* implicit */ NodeList(const QList<KTextTemplate::Node *> &list);
/**
Destructor.
*/
~NodeList();
/**
Appends @p node to the end of this **%NodeList**.
*/
void append(KTextTemplate::Node *node);
/**
Appends @p nodeList to the end of this **%NodeList**.
*/
void append(const QList<KTextTemplate::Node *> &nodeList);
/**
Returns true if this **%NodeList** contains non-text nodes.
*/
bool containsNonText() const;
/**
A recursive listing of nodes in this tree of type @p T.
*/
template<typename T>
QList<T> findChildren()
{
QList<T> children;
QList<KTextTemplate::Node *>::const_iterator it;
const QList<KTextTemplate::Node *>::const_iterator first = constBegin();
const QList<KTextTemplate::Node *>::const_iterator last = constEnd();
for (it = first; it != last; ++it) {
T object = qobject_cast<T>(*it);
if (object) {
children << object;
}
children << (*it)->findChildren<T>();
}
return children;
}
/**
Renders the list of Nodes in the Context @p c.
*/
void render(OutputStream *stream, Context *c) const;
private:
bool m_containsNonText;
};
class AbstractNodeFactoryPrivate;
/// @headerfile node.h KTextTemplate/node.h
/**
@brief Base class for all NodeFactories
This class can be used to make custom tags available to templates.
The getNode method should be implemented to return a Node to be rendered.
A node is represented in template markup as content surrounded by percent
signed tokens.
@code
text content
{% some_tag arg1 arg2 %}
text content
{% some_other_tag arg1 arg2 %}
text content
{% end_some_other_tag %}
text content
@endcode
It is the responsibility of an **%AbstractNodeFactory** implementation to
process the contents of a tag and return a Node implementation from its
getNode method.
The @ref getNode method would for example be called with the tagContent
\"<tt>some_tag arg1 arg2</tt>\". That content could then be split up, the
arguments processed and a Node created
@code
Node* SomeTagFactory::getNode(const QString &tagContent, Parser *p) {
QStringList parts = smartSplit( tagContent );
parts.removeFirst(); // Remove the "some_tag" part.
FilterExpression arg1( parts.first(), p );
FilterExpression arg2( parts.at( 1 ), p );
return new SomeTagNode( arg1, arg2, p );
}
@endcode
The @ref getNode implementation might also advance the parser. For example if
we had a @gr_tag{times} tag which rendered content the amount of times it was
given in its argument, it could be used like this:
@code
Some text content.
{% times 5 %}
the bit to be repeated
{% end_times %}
End text content
@endcode
The argument to @gr_tag{times} might not be a simple number, but could be a
FilterExpression such as \"<tt>someobject.some_property|getDigit:1</tt>\".
The implementation could look like
@code
Node* SomeOtherTagFactory::getNode(const QString &tagContent, Parser *p) {
QStringList parts = smartSplit( tagContent );
parts.removeFirst(); // Remove the "times" part.
FilterExpression arg( parts.first(), p );
auto node = new SomeTagNode( arg, p );
auto childNodes = p->parse( node, "end_times" );
node->setChildNodes( childNodes );
p->removeNextToken();
return node;
}
@endcode
Note that it is necessary to invoke the parser to create the child nodes only
after creating the Node to return. That node must be passed to the Parser to
perform as the parent QObject to the child nodes.
@see Parser::parse
*/
class KTEXTTEMPLATE_EXPORT AbstractNodeFactory : public QObject
{
Q_OBJECT
public:
/**
Constructor.
@param parent The parent QObject
*/
explicit AbstractNodeFactory(QObject *parent = {});
/**
Destructor.
*/
~AbstractNodeFactory() override;
/**
This method should be reimplemented to return a Node which can be
rendered.
The @p tagContent is the content of the tag including the tag name and
arguments. For example, if the template content is @gr_tag{my_tag arg1
arg2}, the tagContent will be &quot;my_tag arg1 arg2&quot;.
The Parser @p p is available and can be advanced if appropriate. For
example, if the tag has an end tag, the parser can be advanced to the end
tag.
@see tags
*/
virtual Node *getNode(const QString &tagContent, Parser *p) const = 0;
#ifndef K_DOXYGEN
/**
@internal
Sets the Engine which created this NodeFactory. Used by the
ScriptableNodeFactory.
*/
virtual void setEngine(Engine *)
{
}
#endif
protected:
/**
Splits @p str into a list, taking quote marks into account.
This is typically used in the implementation of getNode with the
tagContent.
If @p str is 'one &quot;two three&quot; four 'five &quot; six' seven', the
returned list will contain the following strings:
- one
- &quot;two three&quot;
- four
- five &quot; six
- seven
*/
Q_INVOKABLE QStringList smartSplit(const QString &str) const;
protected:
/**
Returns a list of FilterExpression objects created with Parser @p p as
described by the content of @p list.
This is used for convenience when handling the arguments to a tag.
*/
QList<FilterExpression> getFilterExpressionList(const QStringList &list, Parser *p) const;
private:
Q_DECLARE_PRIVATE(AbstractNodeFactory)
AbstractNodeFactoryPrivate *const d_ptr;
};
}
#endif
@@ -0,0 +1,134 @@
/*
This file is part of the KTextTemplate library
SPDX-FileCopyrightText: 2010 Stephen Kelly <steveire@gmail.com>
SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef KTEXTTEMPLATE_OUTPUTSTREAM_H
#define KTEXTTEMPLATE_OUTPUTSTREAM_H
#include "ktexttemplate_export.h"
#include <QSharedPointer>
#include <QTextStream>
namespace KTextTemplate
{
class SafeString;
/// @headerfile outputstream.h <KTextTemplate/OutputStream>
/**
@brief The **%OutputStream** class is used to render templates to a
QTextStream
A **%OutputStream** instance may be passed to the render method of a Template
to render the template to a stream.
@code
QFile outputFile("./output");
outputFile.open(QFile::WriteOnly);
QTextStream tstream( &outputFile );
OutputStream os(&tstream);
t->render( &os, &context );
@endcode
The **%OutputStream** is used to escape the content streamed to it. By
default, the escaping is html escaping, converting "&" to "&amp;" for example.
If generating non-html output, the @ref escape method may be overriden to
perform a different escaping, or non at all.
If overriding the @ref escape method, the @ref clone method must also be
overriden to return an **%OutputStream** with the same escaping behaviour.
@code
class NoEscapeStream : public KTextTemplate::OutputStream
{
public:
// ...
QString escape( const QString &input ) const
{
return input;
}
QSharedPointer<OutputStream> clone( QTextStream *stream ) const
{
return QSharedPointer<NoEscapeStream>::create( stream );
}
};
@endcode
@author Stephen Kelly <steveire@gmail.com>
*/
class KTEXTTEMPLATE_EXPORT OutputStream
{
public:
/**
Creates a null **%OutputStream**. Content streamed to
this **%OutputStream** is sent to <tt>/dev/null</tt>
*/
OutputStream();
/**
Creates an **%OutputStream** which will stream content to @p stream
with appropriate escaping.
*/
explicit OutputStream(QTextStream *stream);
/**
Destructor
*/
virtual ~OutputStream();
/**
Returns an escaped version of @p input. Does not write anything to the
stream.
*/
virtual QString escape(const QString &input) const;
/**
Returns an escaped version of @p input. Does not write anything to the
stream.
*/
QString escape(const SafeString &input) const;
/**
Returns a cloned **%OutputStream** with the same filtering behaviour.
*/
virtual QSharedPointer<OutputStream> clone(QTextStream *stream) const;
/**
Returns @p after escaping it, unless @p input is "safe", in which case,
@p input is returned unmodified.
*/
QString conditionalEscape(const KTextTemplate::SafeString &input) const;
/**
Writes @p input to the stream after escaping it.
*/
OutputStream &operator<<(const QString &input);
/**
Writes @p input to the stream after escaping it if necessary.
*/
OutputStream &operator<<(const SafeString &input);
/**
Reads the content of @p stream and writes it unmodified to the result
stream.
*/
OutputStream &operator<<(QTextStream *stream);
private:
QTextStream *m_stream;
Q_DISABLE_COPY(OutputStream)
};
}
#endif
@@ -0,0 +1,132 @@
/*
This file is part of the KTextTemplate library
SPDX-FileCopyrightText: 2009, 2010 Stephen Kelly <steveire@gmail.com>
SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef KTEXTTEMPLATE_PARSER_H
#define KTEXTTEMPLATE_PARSER_H
#include "filter.h"
#include "node.h"
#include "token.h"
#include <QStringList>
namespace KTextTemplate
{
class TemplateImpl;
class ParserPrivate;
/// @headerfile parser.h <KTextTemplate/Parser>
/**
@brief The **%Parser** class processes a string template into a tree of nodes.
For application developers, this class is internal.
For template tag authors it may be necessary to advance the parser and process
contained tags if the tag works in a tag -- endtag fashion.
@author Stephen Kelly <steveire@gmail.com>
*/
class KTEXTTEMPLATE_EXPORT Parser : public QObject
{
Q_OBJECT
public:
/**
Constructor.
Initialises the **%Parser** with the @p tokenList.
*/
Parser(const QList<Token> &tokenList, QObject *parent);
/**
Destructor.
*/
~Parser() override;
/**
Advance the parser, using @p parent as the parent of new Nodes. The parser
will stop if it encounters a tag which is contained in the list @p stopAt.
For example, the @gr_tag{if} tag would stopAt both @gr_tag{endif} and
@gr_tag{else} tags.
@see AbstractNodeFactory::getNode
*/
NodeList parse(Node *parent, const QStringList &stopAt = {});
/**
This is an overloaded method.
@see parse.
*/
NodeList parse(TemplateImpl *parent, const QStringList &stopAt = {});
/**
This is an overloaded method.
@see parse.
*/
NodeList parse(Node *parent, const QString &stopAt);
/**
Returns the filter object called @p name or an invalid object if no filter
with that name is loaded.
*/
QSharedPointer<Filter> getFilter(const QString &name) const;
/**
Advances the parser to the tag @p tag. This method is similar to @ref parse,
but it does not create nodes for tags encountered.
*/
void skipPast(const QString &tag);
/**
Returns the next token to be processed by the parser. This can be examined
in template tag implementations to determine why parsing stopped.
For example, if the @gr_tag{if} tag, parsing may stop at an @gr_tag{else}
tag, in which case parsing should be restarted, or it could stop at an
@gr_tag{endif} tag, in which case parsing is finished for that node.
*/
Token takeNextToken();
/**
Returns whether the parser has another token to process.
*/
bool hasNextToken() const;
/**
Deletes the next token available to the parser.
*/
void removeNextToken();
void invalidBlockTag(const Token &token, const QString &command, const QStringList &stopAt = {});
#ifndef K_DOXYGEN
/**
@internal
Used by the @gr_tag{load} tag to load libraries.
*/
void loadLib(const QString &name);
#endif
protected:
/**
Puts the token @p token to the front of the list to be processed by the
parser.
*/
void prependToken(const Token &token);
private:
Q_DECLARE_PRIVATE(Parser)
ParserPrivate *const d_ptr;
};
}
#endif
@@ -0,0 +1,110 @@
/*
This file is part of the KTextTemplate library
SPDX-FileCopyrightText: 2010 Stephen Kelly <steveire@gmail.com>
SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef KTEXTTEMPLATE_QTLOCALIZER_P_H
#define KTEXTTEMPLATE_QTLOCALIZER_P_H
#include "abstractlocalizer.h"
class QTranslator;
namespace KTextTemplate
{
class QtLocalizerPrivate;
/// @headerfile qtlocalizer.h <KTextTemplate/QtLocalizer>
/**
@brief Provides internationalization based on QLocale and QTranslator.
This class implements access to the %Qt Localization system. Localizable
types such as strings, numbers, dates and times can be processed.
@code
auto t = m_engine->loadTemplate(someTemplate);
auto c = getContext();
// Render with the German locale
c.setLocalizer(m_de_Localizer);
auto deText = t->render(&c);
de_display->setText(deText);
// Render with the French locale
c.setLocalizer(m_fr_Localizer);
auto frText = t->render(&c);
fr_display->setText(frText);
@endcode
*/
class KTEXTTEMPLATE_EXPORT QtLocalizer : public AbstractLocalizer
{
public:
/**
Constructs a new **%QtLocalizer** using the @p locale
*/
QtLocalizer(const QLocale &locale = QLocale::system());
/**
Destructor
*/
~QtLocalizer() override;
/**
Set the path to look for translations of the application strings.
*/
void setAppTranslatorPath(const QString &path);
/**
Set the prefix of translation files. For example, if the German translation
file is called <tt>myapp_de_DE.qm</tt>, the prefix should be set to
<tt>myapp_</tt>.
*/
void setAppTranslatorPrefix(const QString &prefix);
/**
Install a @p translator to use for a particular @p localeName.
@code
auto deTranslator = new QTranslator(this);
auto loaded = deTranslator->load("myapp_de_DE");
if (!loaded)
return;
de_localizer->installTranslator(deTranslator, "de_DE");
@endcode
*/
void installTranslator(QTranslator *translator, const QString &localeName = QLocale::system().name());
QString currentLocale() const override;
void pushLocale(const QString &localeName) override;
void popLocale() override;
void loadCatalog(const QString &path, const QString &catalog) override;
void unloadCatalog(const QString &catalog) override;
QString localizeNumber(int number) const override;
QString localizeNumber(qreal number) const override;
QString localizeMonetaryValue(qreal value, const QString &currencyCode = {}) const override;
QString localizeDate(const QDate &date, QLocale::FormatType formatType = QLocale::ShortFormat) const override;
QString localizeTime(const QTime &time, QLocale::FormatType formatType = QLocale::ShortFormat) const override;
QString localizeDateTime(const QDateTime &dateTime, QLocale::FormatType formatType = QLocale::ShortFormat) const override;
QString localizeString(const QString &string, const QVariantList &arguments = {}) const override;
QString localizeContextString(const QString &string, const QString &context, const QVariantList &arguments = {}) const override;
QString
localizePluralContextString(const QString &string, const QString &pluralForm, const QString &context, const QVariantList &arguments = {}) const override;
QString localizePluralString(const QString &string, const QString &pluralForm, const QVariantList &arguments = {}) const override;
private:
Q_DECLARE_PRIVATE(QtLocalizer)
Q_DISABLE_COPY(QtLocalizer)
QtLocalizerPrivate *const d_ptr;
};
}
#endif
@@ -0,0 +1,72 @@
/*
This file is part of the KTextTemplate library
SPDX-FileCopyrightText: 2010 Stephen Kelly <steveire@gmail.com>
SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef KTEXTTEMPLATE_RENDERCONTEXT_H
#define KTEXTTEMPLATE_RENDERCONTEXT_H
#include "ktexttemplate_export.h"
#include <QVariantHash>
/// @headerfile rendercontext.h <KTextTemplate/RenderContext>
namespace KTextTemplate
{
class ContextPrivate;
class TemplateImpl;
class Node;
class RenderContextPrivate;
/**
@brief Provides storage facility for state while rendering a template.
This class can not be instatiated by users of it. An instance
of **%RenderContext** is available through Context::renderContext() for use
with implementations of re-entrant template tags.
*/
class KTEXTTEMPLATE_EXPORT RenderContext
{
public:
/**
Returns the data for the node @p scopeNode.
*/
QVariant &data(const Node *const scopeNode);
/**
Returns whether the **%RenderContext** contains data for @p scopeNode.
*/
bool contains(Node *const scopeNode) const;
/**
Destructor
*/
~RenderContext();
#ifndef K_DOXYGEN
private:
RenderContext();
void push();
void pop();
private:
friend class ContextPrivate;
friend class TemplateImpl;
Q_DISABLE_COPY(RenderContext)
Q_DECLARE_PRIVATE(RenderContext)
RenderContextPrivate *const d_ptr;
#endif
};
}
#endif
@@ -0,0 +1,370 @@
/*
This file is part of the KTextTemplate library
SPDX-FileCopyrightText: 2009, 2010 Stephen Kelly <steveire@gmail.com>
SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef KTEXTTEMPLATE_SAFESTRING_H
#define KTEXTTEMPLATE_SAFESTRING_H
#include "ktexttemplate_export.h"
#include <QString>
#include <QVariant>
namespace KTextTemplate
{
/// @headerfile safestring.h <KTextTemplate/SafeString>
/**
@brief A QString wrapper class for containing whether a string is safe or
needs to be escaped.
This allows lazy escaping of strings. Otherwise a string may be escaped
multiple times where it should only be escaped once.
The **%SafeString** class itself provides information about whether a string
is safe from further escaping through the @ref isSafe method. The actual
string content held by the **%SafeString** instance is available through the
@ref get method. The @ref get method returns a QString subclass which should
be used like any other QString. The difference is that all methods on
NestedString return a **%SafeString** instead of a QString.
@code
SafeString s("this & that", SafeString::IsSafe);
s.get().replace( "this", "these" ).toUpper();
qDebug() << s.get() << s.isSafe(); // outputs "these & that" false
@endcode
Note that most operations on strings make the string unsafe. For example,
while <tt>"K &amp; R"</tt> is safe, using replace("m", "n") will result in
<tt>"K &anp; R"</tt>, which is unsafe. Likewise using upper() will return
<tt>"K &AMP; R"</tt>, which is unsafe. Because the **%SafeString** can not
determine whether a method call with particular arguments will change
a **%SafeString** from being safe to being unsafe, any operation which can
possibly make the string unsafe does cause the string to become unsafe. It is
then up to the caller to restore safe-ness if needed.
NestedString has overloads for SafeStrings whereever appropriate so that
strings remain marked as safe where possible.
For example:
@code
SafeString s1("this & that", SafeString::IsSafe);
s2 = s1;
s1.append( QString( " & the other" ) );
// s1 is now "this & that & the other" and is unsafe.
SafeString s3(" Wobl & Bob", SafeString::IsSafe);
s2.append(s3);
// Both s2 and s3 are safe, and append is a safe operation, so s2
// is still safe
@endcode
@see @ref autoescaping
@see OutputStream::escape
The **%SafeString** class has appropriate operator overloads to make it
convenient to use in methods returning a QVariant, such as Filter::doFilter,
or as a QString. Note that a raw QString is essentially the same
as a **%SafeString** which is marked as unsafe.
@author Stephen Kelly <steveire@gmail.com>
*/
class KTEXTTEMPLATE_EXPORT SafeString
{
public:
/**
Possible safety states of a **%SafeString**
*/
enum Safety {
IsSafe, ///< The string is safe and requires no further escaping
IsNotSafe ///< The string is not safe. It will be escaped before being
/// added to the output of rendering.
};
/**
Constructs an empty **%SafeString**.
*/
SafeString();
/**
Copy constructor
*/
SafeString(const SafeString &safeString);
/**
Constructs a **%SafeString** with the content @p str whose safety is given
by @p safe.
*/
SafeString(const QString &str, bool safe);
/**
Constructs a **%SafeString** with the content @p str whose safety is given
by @p safety.
*/
/* implicit */ SafeString(const QString &str,
Safety safety = IsNotSafe); // krazy:exclude=explicit
/**
Destructor
*/
~SafeString();
#ifndef K_DOXYGEN
/**
Set whether the string should be escaped.
*/
void setNeedsEscape(bool needsEscape);
#endif
/**
Whether the string needs to be escaped.
*/
bool needsEscape() const;
/**
Whether the string is safe.
*/
bool isSafe() const;
#ifndef K_DOXYGEN
/**
Set whether the string is safe.
*/
void setSafety(Safety safety);
#endif
/**
@brief The NestedString is a QString whose methods always return a
SafeString
This class is largely an implementation detail. See the SafeString
documentation for details.
*/
class KTEXTTEMPLATE_EXPORT NestedString : public QString
{
#ifndef K_DOXYGEN
friend class SafeString;
SafeString *m_safeString;
public:
explicit NestedString(SafeString *safeString);
NestedString(const QString &content, SafeString *safeString);
SafeString &append(const SafeString &str);
SafeString &append(const QString &str);
SafeString &append(const QLatin1String &str);
#ifndef QT_NO_CAST_FROM_ASCII
SafeString &append(const QByteArray &ba)
{
QString::append(ba);
m_safeString->m_safety = IsNotSafe;
return *m_safeString;
}
SafeString &append(const char *str)
{
QString::append(str);
m_safeString->m_safety = IsNotSafe;
return *m_safeString;
}
#endif
SafeString &append(const QChar ch);
SafeString &fill(QChar ch, int size = -1);
SafeString &insert(int position, const SafeString &str);
SafeString &insert(int position, const QString &str);
SafeString &insert(int position, const QLatin1String &str);
SafeString &insert(int position, const QChar *unicode, int size);
SafeString &insert(int position, QChar ch);
SafeString left(int n) const;
SafeString leftJustified(int width, QChar fill = QLatin1Char(' '), bool truncate = {}) const;
SafeString mid(int position, int n = -1) const;
SafeString normalized(NormalizationForm mode) const;
SafeString normalized(NormalizationForm mode, QChar::UnicodeVersion version) const;
SafeString &prepend(const SafeString &str);
SafeString &prepend(const QString &str);
SafeString &prepend(const QLatin1String &str);
#ifndef QT_NO_CAST_FROM_ASCII
SafeString &prepend(const QByteArray &ba)
{
QString::prepend(ba);
m_safeString->m_safety = IsNotSafe;
return *m_safeString;
}
SafeString &prepend(const char *str)
{
QString::prepend(str);
m_safeString->m_safety = IsNotSafe;
return *m_safeString;
}
#endif
SafeString &prepend(QChar ch);
void push_back(const SafeString &other);
void push_front(const SafeString &other);
SafeString &remove(int position, int n);
SafeString &remove(QChar ch, Qt::CaseSensitivity cs = Qt::CaseSensitive);
SafeString &remove(const SafeString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive);
SafeString &remove(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive);
SafeString &remove(const QRegularExpression &rx);
SafeString repeated(int times) const;
SafeString &replace(int position, int n, const SafeString &after);
SafeString &replace(int position, int n, const QString &after);
SafeString &replace(int position, int n, const QChar *unicode, int size);
SafeString &replace(int position, int n, QChar after);
SafeString &replace(const SafeString &before, const SafeString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
SafeString &replace(const QString &before, const SafeString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
SafeString &replace(const SafeString &before, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
SafeString &replace(const QString &before, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
SafeString &replace(const QChar *before, int blen, const QChar *after, int alen, Qt::CaseSensitivity cs = Qt::CaseSensitive);
SafeString &replace(QChar ch, const SafeString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
SafeString &replace(QChar ch, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
SafeString &replace(QChar before, QChar after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
SafeString &replace(const QLatin1String &before, const QLatin1String &after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
SafeString &replace(const QLatin1String &before, const SafeString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
SafeString &replace(const QLatin1String &before, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
SafeString &replace(const SafeString &before, const QLatin1String &after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
SafeString &replace(const QString &before, const QLatin1String &after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
SafeString &replace(QChar c, const QLatin1String &after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
SafeString &replace(const QRegularExpression &rx, const SafeString &after);
SafeString &replace(const QRegularExpression &rx, const QString &after);
SafeString right(int n) const;
SafeString rightJustified(int width, QChar fill = QLatin1Char(' '), bool truncate = {}) const;
SafeString section(QChar sep, int start, int end = -1, SectionFlags flags = SectionDefault) const;
SafeString section(const SafeString &sep, int start, int end = -1, SectionFlags flags = SectionDefault) const;
SafeString section(const QString &sep, int start, int end = -1, SectionFlags flags = SectionDefault) const;
SafeString section(const QRegularExpression &reg, int start, int end = -1, SectionFlags flags = SectionDefault) const;
SafeString &setNum(int n, int base = 10);
SafeString &setNum(uint n, int base = 10);
SafeString &setNum(long n, int base = 10);
SafeString &setNum(ulong n, int base = 10);
SafeString &setNum(qlonglong n, int base = 10);
SafeString &setNum(qulonglong n, int base = 10);
SafeString &setNum(short n, int base = 10);
SafeString &setNum(ushort n, int base = 10);
SafeString &setNum(double n, char format = 'g', int precision = 6);
SafeString &setNum(float n, char format = 'g', int precision = 6);
SafeString &setUnicode(const QChar *unicode, int size);
SafeString &setUtf16(const ushort *unicode, int size);
SafeString simplified() const;
QStringList split(const SafeString &sep, Qt::SplitBehavior behavior = Qt::KeepEmptyParts, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
QStringList split(const QString &sep, Qt::SplitBehavior behavior = Qt::KeepEmptyParts, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
QStringList split(const QChar &sep, Qt::SplitBehavior behavior = Qt::KeepEmptyParts, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
QStringList split(const QRegularExpression &rx, Qt::SplitBehavior behavior = Qt::KeepEmptyParts) const;
SafeString toLower() const;
SafeString toUpper() const;
SafeString trimmed() const;
void chop(int n);
#endif
};
/**
Returns the String held by this **%SafeString**
*/
const NestedString &get() const
{
return m_nestedString;
}
/**
Returns the String held by this **%SafeString**
*/
NestedString &get()
{
return m_nestedString;
}
/**
Convenience operator for treating a **%SafeString** like a QString.
*/
operator QString() const
{
return m_nestedString;
}
/**
Assignment operator.
*/
SafeString &operator=(const SafeString &str);
/**
Returns a concatenation of this with @p str.
The result is not safe because str is not safe.
*/
SafeString operator+(const QString &str);
/**
Returns a concatenation of this with @p str.
The result is safe if both this and str are safe.
*/
SafeString operator+(const SafeString &str);
/**
Appends the content of @p str to this.
The result is not safe because @p str is not safe.
*/
SafeString &operator+=(const QString &str);
/**
Appends the content of @p str to this.
The result is safe if both this and @p str are safe.
*/
SafeString &operator+=(const SafeString &str);
/**
Returns true if the content of @p other matches the content of this.
Safeness and needing escaping are not accounted for in the comparison.
*/
bool operator==(const SafeString &other) const;
/**
Returns true if the content of @p other matches the content of this.
Safeness and needing escaping are not accounted for in the comparison.
*/
bool operator==(const QString &other) const;
/**
Convenience operator for storing a **%SafeString** in a QVariant.
*/
operator QVariant() const
{
return QVariant::fromValue(*this);
}
private:
#ifndef K_DOXYGEN
NestedString m_nestedString;
#endif
Safety m_safety;
bool m_needsescape;
};
}
Q_DECLARE_METATYPE(KTextTemplate::SafeString)
#endif
@@ -0,0 +1,98 @@
/*
This file is part of the KTextTemplate library
SPDX-FileCopyrightText: 2009, 2010 Stephen Kelly <steveire@gmail.com>
SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef TAGLIBRARYINTERFACE_H
#define TAGLIBRARYINTERFACE_H
#include "outputstream.h"
#include <QHash>
#include <QtPlugin>
namespace KTextTemplate
{
class AbstractNodeFactory;
class Filter;
/// @headerfile taglibraryinterface.h <KTextTemplate/TagLibraryInterface>
/**
@brief The **%TagLibraryInterface** returns available tags and filters from
libraries.
This interface must be implemented in tag and filter libraries.
The implementation will usually be very simple.
@code
class MyTagLibrary : public QObject, public TagLibraryInterface
{
Q_OBJECT
Q_INTERFACES( KTextTemplate::TagLibraryInterface )
public:
MyTagLibrary( QObject *parent = {} )
: QObject( parent ) {
}
QHash<QString, AbstractNodeFactory*>
nodeFactories(const QString &name = {}) {
Q_UNUSED( name );
QHash<QString, AbstractNodeFactory*> nodeFactories;
nodeFactories.insert( "mytag1", new MyTag1() );
nodeFactories.insert( "mytag2", new MyTag2() );
return nodeFactories;
}
QHash<QString, Filter*> filters( const QString &name = {} ) {
Q_UNUSED( name );
QHash<QString, Filter*> filters;
filters.insert( "myfilter1", new MyFilter1() );
filters.insert( "myfilter2", new MyFilter2() );
return filters;
}
};
@endcode
@author Stephen Kelly <steveire@gmail.com>
*/
class TagLibraryInterface
{
public:
virtual ~TagLibraryInterface()
{
}
/**
Returns the AbstractNodeFactory implementations available in this library.
*/
virtual QHash<QString, AbstractNodeFactory *> nodeFactories(const QString &name = {})
{
Q_UNUSED(name);
static const QHash<QString, AbstractNodeFactory *> h;
return h;
};
/**
Returns the Filter implementations available in this library.
*/
virtual QHash<QString, Filter *> filters(const QString &name = {})
{
Q_UNUSED(name);
static const QHash<QString, Filter *> h;
return h;
};
};
}
Q_DECLARE_INTERFACE(KTextTemplate::TagLibraryInterface, "org.kde.KTextTemplate.TagLibraryInterface/1.0")
#endif
@@ -0,0 +1,150 @@
/*
This file is part of the KTextTemplate library
SPDX-FileCopyrightText: 2009, 2010 Stephen Kelly <steveire@gmail.com>
SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef KTEXTTEMPLATE_TEMPLATE_H
#define KTEXTTEMPLATE_TEMPLATE_H
#include "exception.h"
#include "ktexttemplate_export.h"
#include "node.h"
#include <QSharedPointer>
#include <QStringList>
namespace KTextTemplate
{
class Context;
class Engine;
class TemplateImpl;
class OutputStream;
#ifdef K_DOXYGEN
#define TemplateImpl Template
#else
typedef QSharedPointer<TemplateImpl> Template;
#endif
class TemplatePrivate;
/// @headerfile template.h <KTextTemplate/Template>
/**
@brief The **%Template** class is a tree of nodes which may be rendered.
All Templates are created through the KTextTemplate::Engine class.
A **%Template** is created by parsing some text markup passed into the Engine,
or by reading it from a file.
Note that **%Template** is actually a typedef for a
<tt>QSharedPointer&lt;TemplateImpl&gt;</tt>, so all of its members should be
accessed with <tt>operator-&gt;()</tt>.
The result of parsing is a **%Template** object which can be rendered multiple
times with multiple different Contexts.
@code
auto engine = getEngine();
auto t = engine->newTemplate(
"{{ name }} is aged {{ age }}",
"simple template" );
if ( t->error() )
{
// Tokenizing or parsing error, or couldn't find custom tags or filters.
qDebug() << t->errorString();
return;
}
QTextStream textStream( stdout );
OutputStream stream( textStream );
for ( ... )
{
Context c;
// ... c.insert
t->render( stream, c );
if (t->error())
{
// Rendering error.
qDebug() << t->errorString();
}
}
@endcode
If there is an error in parsing or rendering, the @ref error and @ref
errorString methods can be used to check the source of the error.
@author Stephen Kelly <steveire@gmail.com>
*/
class KTEXTTEMPLATE_EXPORT TemplateImpl : public QObject
{
Q_OBJECT
public:
~TemplateImpl() override;
/**
Renders the **%Template** to a string given the Context @p c.
*/
QString render(Context *c) const;
/**
Renders the **%Template** to the OutputStream @p stream given the Context c.
*/
OutputStream *render(OutputStream *stream, Context *c) const;
#ifndef K_DOXYGEN
/**
@internal
*/
NodeList nodeList() const;
/**
@internal
*/
void setNodeList(const NodeList &list);
#endif
/**
Returns an error code for the error encountered.
*/
Error error() const;
/**
Returns more information to developers in the form of a string.
*/
QString errorString() const;
/**
Returns the Engine that created this **%Template**.
*/
Engine const *engine() const;
#ifndef K_DOXYGEN
protected:
TemplateImpl(Engine const *engine, QObject *parent = {});
TemplateImpl(Engine const *engine, bool smartTrim, QObject *parent = {});
void setContent(const QString &templateString);
#endif
private:
// Don't allow setting the parent on a Template, which is memory managed as
// a QSharedPointer.
using QObject::setParent;
private:
Q_DECLARE_PRIVATE(Template)
TemplatePrivate *const d_ptr;
#ifndef K_DOXYGEN
friend class Engine;
friend class Parser;
#endif
};
}
#endif
@@ -0,0 +1,213 @@
/*
This file is part of the KTextTemplate library
SPDX-FileCopyrightText: 2009, 2010 Stephen Kelly <steveire@gmail.com>
SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef KTEXTTEMPLATE_TEMPLATELOADER_H
#define KTEXTTEMPLATE_TEMPLATELOADER_H
#include "ktexttemplate_export.h"
#include "template.h"
#include <QSharedPointer>
namespace KTextTemplate
{
class AbstractLocalizer;
/// @headerfile templateloader.h <KTextTemplate/TemplateLoader>
/**
@brief An retrieval interface to a storage location for Template objects.
This interface can be implemented to define new ways of retrieving the content
of Templates.
The interface of this class should not be called directly from applications.
TemplateLoaders will typically be created, configured and added to the
KTextTemplate::Engine which will call the appropriate API.
@author Stephen Kelly <steveire@gmail.com>
*/
class KTEXTTEMPLATE_EXPORT AbstractTemplateLoader
{
public:
/**
Destructor
*/
virtual ~AbstractTemplateLoader();
/**
Load a Template called @p name. Return an invalid Template if no content
by that name exists.
*/
virtual Template loadByName(const QString &name, Engine const *engine) const = 0;
/**
Return a complete URI for media identified by fileName.
*/
virtual std::pair<QString, QString> getMediaUri(const QString &fileName) const = 0;
/**
Return true if a Template identified by @p name exists and can be loaded.
*/
virtual bool canLoadTemplate(const QString &name) const = 0;
};
/// @headerfile templateloader.h KTextTemplate/templateloader.h
class FileSystemTemplateLoaderPrivate;
/**
@brief The **%FileSystemTemplateLoader** loads Templates from the file system.
This template loader works by traversing a list of directories to find
templates. Directories are checked in order, and the first match hit is parsed
and returned.
@code
loader->setTemplateDirs({
"/home/user/app/templates",
"/usr/local/share/app/templates"
});
engine->setTemplateLoader( loader );
// This will try /home/user/app/templates/mytemplate.html
// followed by /usr/local/share/app/templates/mytemplate.html
engine->loadByName( "mytemplate.html" );
@endcode
Additionally, a themeName may be set on the template loader, which will be
appended to search paths before the template name.
@code
loader->setTemplateDirs({
"/home/user/app/templates" <<
"/usr/local/share/app/templates"
});
loader->setTheme( "simple_theme" );
engine->setTemplateLoader( loader );
// This will try /home/user/app/templates/simple_theme/mytemplate.html
// followed by /usr/local/share/app/templates/simple_theme/mytemplate.html
engine->loadByName( "mytemplate.html" );
@endcode
Media URIs may be retrieved for media relative to the directories searched
queried for templates.
@code
loader->setTemplateDirs({
"/home/user/app/templates",
"/usr/local/share/app/templates"
});
loader->setTheme( "simple_theme" );
engine->setTemplateLoader( loader );
// This will try /home/user/app/templates/simple_theme/logo.png
// followed by /usr/local/share/app/templates/simple_theme/logo.png
// and return the first one that exists.
engine->mediaUri( "logo.png" );
@endcode
The template files loaded by a %**FileSystemTemplateLoader** must be UTF-8
encoded.
@see @ref deploying_templates
*/
class KTEXTTEMPLATE_EXPORT FileSystemTemplateLoader : public AbstractTemplateLoader
{
public:
/**
Constructor
*/
FileSystemTemplateLoader(const QSharedPointer<AbstractLocalizer> localizer = {});
/**
Destructor
*/
~FileSystemTemplateLoader() override;
Template loadByName(const QString &name, Engine const *engine) const override;
bool canLoadTemplate(const QString &name) const override;
std::pair<QString, QString> getMediaUri(const QString &fileName) const override;
/**
Sets the theme of this loader to @p themeName
*/
void setTheme(const QString &themeName);
/**
The themeName of this TemplateLoader
*/
QString themeName() const;
/**
Sets the directories to look for template files to @p dirs.
*/
void setTemplateDirs(const QStringList &dirs);
/**
The directories this TemplateLoader looks in for template files.
*/
QStringList templateDirs() const;
private:
Q_DECLARE_PRIVATE(FileSystemTemplateLoader)
FileSystemTemplateLoaderPrivate *const d_ptr;
};
/// @headerfile templateloader.h KTextTemplate/templateloader.h
/**
@brief The **%InMemoryTemplateLoader** loads Templates set dynamically in
memory
This class is mostly used for testing purposes, but can also be used for
simple uses of %KTextTemplate.
Templates can be made available using the @ref setTemplate method, and will
then be retrieved by the KTextTemplate::Engine as appropriate.
*/
class KTEXTTEMPLATE_EXPORT InMemoryTemplateLoader : public AbstractTemplateLoader
{
public:
InMemoryTemplateLoader();
~InMemoryTemplateLoader() override;
Template loadByName(const QString &name, Engine const *engine) const override;
bool canLoadTemplate(const QString &name) const override;
std::pair<QString, QString> getMediaUri(const QString &fileName) const override;
/**
Add a template content to this Loader.
Example:
@code
auto loader = QSharedPointer<InMemoryTemplateLoader::create();
loader->setTemplate( "name_template", "My name is {{ name }}" );
loader->setTemplate( "age_template", "My age is {{ age }}" );
engine->addTemplateLoader( loader );
// Both templates may now be retrieved by calling Engine::loadByName.
@endcode
*/
void setTemplate(const QString &name, const QString &content);
private:
QHash<QString, QString> m_namedTemplates;
};
}
#endif
@@ -0,0 +1,46 @@
/*
This file is part of the KTextTemplate library
SPDX-FileCopyrightText: 2009, 2010 Stephen Kelly <steveire@gmail.com>
SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef KTEXTTEMPLATE_TOKEN_H
#define KTEXTTEMPLATE_TOKEN_H
#include <QString>
namespace KTextTemplate
{
/**
@internal
The available token types.
*/
enum TokenType {
TextToken, ///< The Token is a text fragment
VariableToken, ///< The Token is a variable node
BlockToken, ///< The Token is a block, ie, part of a tag
CommentToken ///< The Token is a comment node.
};
/// @headerfile token.h <KTextTemplate/Token>
/**
A token in a parse stream for a template.
This class is only relevant for template tag implementations.
*/
struct Token {
int tokenType; ///< The Type of this Token
int linenumber; ///< The line number this Token starts at
QString content; ///< The content of this Token
};
}
Q_DECLARE_TYPEINFO(KTextTemplate::Token, Q_RELOCATABLE_TYPE);
#endif
@@ -0,0 +1,40 @@
/*
This file is part of the KTextTemplate library
SPDX-FileCopyrightText: 2010 Stephen Kelly <steveire@gmail.com>
SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef KTEXTTEMPLATE_TYPEACCESSOR_H
#define KTEXTTEMPLATE_TYPEACCESSOR_H
#include "ktexttemplate_export.h"
#include <QObject>
/// @file
namespace KTextTemplate
{
#ifndef K_DOXYGEN
template<typename T>
struct TypeAccessor {
static QVariant lookUp(const T object, const QString &property);
};
template<typename T>
struct TypeAccessor<T *> {
static QVariant lookUp(const T *const object, const QString &property);
};
template<typename T>
struct TypeAccessor<T &> {
static QVariant lookUp(const T &object, const QString &property);
};
#endif
}
#endif
@@ -0,0 +1,96 @@
/*
This file is part of the KTextTemplate library
SPDX-FileCopyrightText: 2009, 2010 Stephen Kelly <steveire@gmail.com>
SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef KTEXTTEMPLATE_UTIL_P_H
#define KTEXTTEMPLATE_UTIL_P_H
#include "context.h"
#include "ktexttemplate_export.h"
#include "safestring.h"
#include <QVariant>
/// @file util.h Utility functions used throughout %KTextTemplate.
/// @headerfile util.h <KTextTemplate/Util>
namespace KTextTemplate
{
/**
Returns whether the @p variant is evaluated to true.
@see @ref truthiness
*/
KTEXTTEMPLATE_EXPORT bool variantIsTrue(const QVariant &variant);
/**
Converts the @p input into its unescaped form.
Double slashes are converted to single slashes, \\&quot is converted to &quot
etc.
*/
KTEXTTEMPLATE_EXPORT QString unescapeStringLiteral(const QString &input);
/**
Marks the @p input as safe.
*/
KTEXTTEMPLATE_EXPORT KTextTemplate::SafeString markSafe(const KTextTemplate::SafeString &input);
/**
Marks the @p input as requiring escaping.
*/
KTEXTTEMPLATE_EXPORT KTextTemplate::SafeString markForEscaping(const KTextTemplate::SafeString &input);
/**
Retrieves and returns a SafeString from the @p input.
*/
KTEXTTEMPLATE_EXPORT KTextTemplate::SafeString getSafeString(const QVariant &input);
/**
Returns whether @p input contains a SafeString.
*/
KTEXTTEMPLATE_EXPORT bool isSafeString(const QVariant &input);
/**
Returns true if the type of @p input can be inserted into a rendered template
directly.
Note that lists, hashes and QObject*s can not be.
*/
KTEXTTEMPLATE_EXPORT bool supportedOutputType(const QVariant &input);
/**
Compares @p lhs and @p rhs for equality. SafeStrings are compared as raw
QStrings. Their safeness is not part of the comparison.
@see QVariant::operator==
*/
KTEXTTEMPLATE_EXPORT bool equals(const QVariant &lhs, const QVariant &rhs);
/**
Converts @p size into the nearest file size unit like MB or MiB, based on the
@p unitSystem value. Use @c 2 for the @p unitSystem to get binary units, use
@c 10 to get decimal units - by default, decimal units will be returned. The
@p multiplier can be used if the input @p size is not in pure bytes. If @p
size is for example given in @a KiB, use a multiplier of @a 1024. The returned
pair will have the converted size as @a first and the unit as @a second.
*/
KTEXTTEMPLATE_EXPORT std::pair<qreal, QString> calcFileSize(qreal size, int unitSystem = 10, qreal multiplier = 1.0);
#ifndef K_DOXYGEN
/**
@internal
Returns the @p list as a formatted string. This is for debugging purposes
only.
*/
KTEXTTEMPLATE_EXPORT KTextTemplate::SafeString toString(const QVariantList &list);
#endif
}
#endif
@@ -0,0 +1,118 @@
/*
This file is part of the KTextTemplate library
SPDX-FileCopyrightText: 2009, 2010 Stephen Kelly <steveire@gmail.com>
SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef KTEXTTEMPLATE_VARIABLE_H
#define KTEXTTEMPLATE_VARIABLE_H
#include "ktexttemplate_export.h"
#include <QVariant>
namespace KTextTemplate
{
class Context;
class VariablePrivate;
/// @headerfile variable.h <KTextTemplate/Variable>
/**
@brief A container for static variables defined in Templates.
This class is only relevant to Template tag authors.
When processing a template tag in a AbstractNodeFactory implementation, it
will sometimes make sense to process arguments to the tag as
KTextTemplate::Variables. Note that usually they should be processed as
FilterExpression objects instead.
Arguments to the tag can be used to construct Variables, which may then be
resolved into the objects they represent in the given Context in the render
stage.
@author Stephen Kelly <steveire@gmail.com>
*/
class KTEXTTEMPLATE_EXPORT Variable
{
public:
/**
Constructs an invalid **%Variable**
*/
Variable();
/**
Creates a **%Variable** represented by the given @p var
*/
explicit Variable(const QString &var);
/**
Copy constructor
*/
Variable(const Variable &other);
/**
Destructor
*/
~Variable();
/**
Assignment operator.
*/
Variable &operator=(const Variable &other);
/**
Returns whether this **%Variable** is valid.
*/
bool isValid() const;
/**
Returns whether this **%Variable** evaluates to true with the Context @p c.
*/
bool isTrue(Context *c) const;
/**
Resolves this **%Variable** with the Context @p c.
*/
QVariant resolve(Context *c) const;
/**
Returns whether this **%Variable** is a constant in the Template. A constant
is represented as a static string in the template
@code
Text content
{% some_tag "constant" variable %}
@endcode
*/
bool isConstant() const;
/**
Returns whether this variable is localized, that is, if it is wrapped with
_(). @see @ref i18n_l10n
*/
bool isLocalized() const;
/**
Returns whether this variable is a literal string or number. A
literal **%Variable** does not have any lookup components.
*/
QVariant literal() const;
/**
Returns the lookup components of this **%Variable**.
*/
QStringList lookups() const;
private:
Q_DECLARE_PRIVATE(Variable)
VariablePrivate *const d_ptr;
};
}
#endif