Grantlee: Using Grantlee in your application

Grantlee 5.2.0

Using Grantlee in your application

Using Grantlee in Qt applications will often not require much code.

auto engine = getEngine();
auto t = engine->loadByName( "mytemplate.html" );
Context c;
c.insert( "some_input", some_value );
browser.setHtml( t->render( c ) );

Error handling etc is omitted for clarity. In order for the above to work as expected, it is necessary to configure the build system to find Grantlee, and to configure Grantlee to find templates and plugins.

# Finding Grantlee with CMake

Grantlee uses the CMake cross platform build system, and installs a cmake file called `Grantlee5Config.cmake`. This config file is automatically searched for by CMake and contains the information needed for other CMake based applications to find headers and link against Grantlee libraries. See https://cmake.org/cmake/help/latest/manual/cmake-packages.7.html for more.

When creating an application using CMake that depends on Grantlee, first issue the `find_package` command, and then use the CMake `target_link_libraries` command link to and use the libraries.

project(my_application)
cmake_minimum_required(VERSION 2.8.11)
set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
find_package(Grantlee5 REQUIRED)
# ... Application sources etc.
target_link_libraries(my_application
PRIVATE
Qt5::Widgets
Grantlee5::Templates
)

# Deploying Templates

Template files can be installed by your application and must later be found by Grantlee so they can be used. If the files are installed on the filesystem, the path they were installed to can be specified when creating a AbstractTemplateLoader instance.

Engine* getEngine()
{
auto engine = new Engine( this );
auto loader = QSharedPointer<FileSystemTemplateLoader>::create();
loader->setTemplateDirs( QStringList{ path_to_installed_templates } );
engine->addTemplateLoader( loader );
return engine;
}

It is also possible to compile the templates into a Qt Resource file and set the resource URL on the AbstractTemplateLoader instance.

my_app_templates.qrc:

<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>mybasetemplate.html</file>
<file>mytemplate.html</file>
<file>myothertemplate.html</file>
</qresource>
</RCC>

CMake code:

set (_rcc_file "my_app_templates.qrc")
qt5_add_resources(_template_rcc_src ${_rcc_file} OPTIONS -root "/templates/" )
add_executable(my_app, ${my_app_srcs} ${_template_rcc_src})

Application code:

auto loader = QSharedPointer<FileSystemTemplateLoader>::create();
loader->setTemplateDirs( QStringList{ ":/templates/" } );
engine->addTemplateLoader( loader );

The `-root` option passed to `rcc` in CMake causes the templates to be in the virtual filesystem location "`:/templates/mytemplate.html`" etc. This name spacing helps keep independent data in the virtual filesystem separate.

# Finding user defined templates

If users are able to define their own templates in an application that uses Grantlee for theming for example, the path to the location of such potential templates must also be set through the AbstractTemplateLoader instance. Paths to user defined templates should be defined before default/installed templates so that the user templates are found first. If there is a reason to disallow user overriding of certain templates, they can be specified in a separate AbstractTemplateLoader instance.

auto no_override_loader = QSharedPointer<FileSystemTemplateLoader>::create();
no_override_loader->setTemplateDirs(
QStringList{ path_to_non_overridable_templates }
);
engine->addTemplateLoader( no_override_loader );
auto override_loader = QSharedPointer<FileSystemTemplateLoader>::create();
override_loader->setTemplateDirs(
QStringList{ path_to_user_templates, path_to_default_templates }
);
engine->addTemplateLoader( override_loader );

Additionally, the External binary resources feature could be used to allow savvy users to share themes/templates in a package, or to deploy updated templates easily to existing deployed applications.

# Finding tags and filters

Grantlee looks for plugins in the paths from the Engine::pluginPaths property. It does so in the same order they appear there.

The property defaults to the following directories

- The default plugin directory of your Qt installation (`qmake -query QT_INSTALL_PLUGINS`).
- The directories specified in the environment variable `QT_PLUGIN_DIR`.
- The default plugin directory of your Grantlee installation.

Each path has `"grantlee/$version/"` appended to it, and the resulting directory is searched for plugins. For example, if the version of Grantlee is 5.0 and QCoreApplication::libraryPaths() contains `"/usr/lib/plugins/"`, the directory `"/usr/lib/plugins/grantlee/5.0"` would be searched for plugins. The search stops when a plugin matching a particular name is found.

The paths used to search for plugins can be overriden by using Engine::setPluginPaths. If you just want to add some additional paths use Engine::addPluginPath. The added path will be prepended to the list of search paths.

# Deploying custom tags and filters

Custom tags and filters can be defined in C++ code or in Javascript.

To create a custom C++ plugin it must be built as part of a library and installed in a location known to the application.

# CMake code
add_library(my_custom_plugin MODULE
custom_plugin_library.cpp
)
install(TARGETS my_custom_plugin
RUNTIME DESTINATION ${PLUGIN_INSTALL_DIR}
LIBRARY DESTINATION ${PLUGIN_INSTALL_DIR}
ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
COMPONENT Devel
)

In this case, `my_custom_plugin` is a name used for the plugin in the CMake environment. It is used to install the custom library in the CMake `install` command.

`custom_plugin_library.cpp` is the C++ file where you implement the Grantlee::TagLibraryInterface to return custom tags and filters.

Note that the `PLUGIN_INSTALL_DIR` given to the install command should contain the version number of Grantlee used to create the custom library. For example, `/usr/share/my_app/plugins/grantlee/5.0/`.

In C++ code, it is necessary to either instruct the Grantlee::Engine about the location of the plugins or to configure your QCoreApplication::libraryPaths by another standard method. Note that it is possible to define custom versions of built in tags and filters by putting your own plugin library in the path before the path to the default Grantlee plugins.

For example, if your custom plugin library contained a custom implementation of the `{% for %}` tag:

auto engine = new Engine( this );
engine->setPluginPaths(
QStringList{ path_to_custom_plugins, path_to_grantlee_defaults }
);

Note that neither the path to the custom libarary nor the path to the Grantlee default library should contain the version number when specified in C++ code with the Engine. The version is only specified when installing the plugin in CMake.

Custom tags and filters implemented in Javascript can also be deployed on the file system, or, like template files, can also be deployed in Qt Resource files. In that case, the version should be specified in the -root argument in CMake.

# CMake code:
set (_rcc_file "my_qtscript_library.qrc")
qt5_add_resources(_scripted_rcc_src
${_rcc_file}
OPTIONS -root "/plugins/grantlee/${Grantlee5_VERSION_MAJOR}.${Grantlee5_VERSION_MINOR}"
)
add_executable(my_app, ${my_app_srcs} ${_scripted_rcc_src})
# C++ code:
engine->setPluginPaths( QStringList{ ":/plugins/" } );

Note again that when specifying the path in the virtual filesystem, the version is omitted. User defined filter written in Javascript can also be located similiarly to templates from either the filesystem or the Qt Resource virtual filesystem.

# Building Grantlee

It is possible to build only parts of Grantlee if your application is a QCoreApplication that depends only on QtCore

The appropriate options may be specified in the cmake gui, or on the command line using the `BUILD_TEXTDOCUMENT` or `BUILD_TEMPLATES` CMake options.

mkdir build && cd build
cmake .. -DBUILD_TEXTDOCUMENT=OFF -DBUILD_TESTS=OFF

Similarly, it is possible to build only the core of the Grantlee Template library without the plugins. This may be useful for specialized applications, but as the unit tests depend on the plugins, the tests would need to be deactivated in this case too:

mkdir build && cd build
cmake .. -DBUILD_TEXTDOCUMENT=OFF -DBUILD_TESTS=OFF -DBUILD_MAIN_PLUGINS=OFF

By default, Grantlee depends on the QtQml library in order to implement Javascript support. This support is only enabled if the QtQml library is found.

Dependency Graph for Grantlee

To prevent CMake searching for that library, use the `-DCMAKE_DISABLE_FIND_PACKAGE_Qt5Qml=ON` argument to CMake.

Dependency Graph for Grantlee without QtQml