6#include "application.h"
9#include "grantleeview_p.h"
12#include <grantlee/metatype.h>
13#include <grantlee/qtlocalizer.h>
15#include <QDirIterator>
18#include <QtCore/QLoggingCategory>
20Q_LOGGING_CATEGORY(CUTELYST_GRANTLEE,
"cutelyst.grantlee", QtWarningMsg)
25return object.value(property);
29return object->property(property.toLatin1().constData());
33 :
View(new GrantleeViewPrivate, parent,
name)
37 Grantlee::registerMetaType<ParamsMultiMap>();
38 Grantlee::registerMetaType<Cutelyst::Request *>();
41 QSharedPointer<Grantlee::FileSystemTemplateLoader>(
new Grantlee::FileSystemTemplateLoader);
43 d->engine =
new Grantlee::Engine(
this);
44 d->engine->addTemplateLoader(d->loader);
47 const QByteArrayList dirs = QByteArrayList{QByteArrayLiteral(CUTELYST_PLUGINS_DIR)} +
48 qgetenv(
"CUTELYST_PLUGINS_DIR").split(
';');
49 for (
const QByteArray &dir : dirs) {
50 d->engine->addPluginPath(QString::fromLocal8Bit(dir));
53 d->engine->addDefaultLibrary(QStringLiteral(
"grantlee_cutelyst"));
55 auto app = qobject_cast<Application *>(parent);
63 app->config(QStringLiteral(
"CUTELYST_VAR"), QStringLiteral(
"c")).toString();
65 app->loadTranslations(QStringLiteral(
"plugin_view_grantlee"));
75 return d->includePaths;
81 d->loader->setTemplateDirs(paths);
82 d->includePaths = paths;
95 d->extension = extension;
116 if (enable != d->cache.isNull()) {
121 d->engine =
new Grantlee::Engine(
this);
124 d->cache = QSharedPointer<Grantlee::CachingLoaderDecorator>(
125 new Grantlee::CachingLoaderDecorator(d->loader));
126 d->engine->addTemplateLoader(d->cache);
129 d->engine->addTemplateLoader(d->loader);
148 const auto includePaths = d->includePaths;
149 for (
const QString &includePath : includePaths) {
150 QDirIterator it(includePath,
151 {QLatin1Char(
'*') + d->extension},
152 QDir::Files | QDir::NoDotAndDotDot,
153 QDirIterator::Subdirectories);
154 while (it.hasNext()) {
155 QString path = it.next();
156 path.remove(includePath);
157 if (path.startsWith(QLatin1Char(
'/'))) {
161 if (d->cache->canLoadTemplate(path)) {
162 d->cache->loadByName(path, d->engine);
171 return !d->cache.isNull();
179 c->
setStash(d->cutelystVar, QVariant::fromValue(c));
180 const QVariantHash stash = c->
stash();
181 auto it = stash.constFind(QStringLiteral(
"template"));
182 QString templateFile;
183 if (it != stash.constEnd()) {
184 templateFile = it.value().toString();
186 if (c->action() && !c->action()->
reverse().isEmpty()) {
187 templateFile = c->action()->
reverse() + d->extension;
188 if (templateFile.startsWith(QLatin1Char(
'/'))) {
189 templateFile.remove(0, 1);
193 if (templateFile.isEmpty()) {
194 c->
error(QStringLiteral(
195 "Cannot render template, template name or template stash key not defined"));
200 qCDebug(CUTELYST_GRANTLEE) <<
"Rendering template" << templateFile;
202 Grantlee::Context gc(stash);
204 auto localizer = QSharedPointer<Grantlee::QtLocalizer>::create(c->
locale());
206 auto transIt = d->translators.constFind(c->
locale());
207 if (transIt != d->translators.constEnd()) {
208 localizer.data()->installTranslator(transIt.value(), transIt.key().name());
211 auto catalogIt = d->translationCatalogs.constBegin();
212 while (catalogIt != d->translationCatalogs.constEnd()) {
213 localizer.data()->loadCatalog(catalogIt.value(), catalogIt.key());
217 gc.setLocalizer(localizer);
219 Grantlee::Template tmpl = d->engine->loadByName(templateFile);
220 if (tmpl->error() != Grantlee::NoError) {
222 c->
error(QLatin1String(
"Error while rendering template: ") + tmpl->errorString());
226 QString content = tmpl->render(&gc);
227 if (tmpl->error() != Grantlee::NoError) {
229 c->
error(QLatin1String(
"Error while rendering template: ") + tmpl->errorString());
233 if (!d->wrapper.isEmpty()) {
234 Grantlee::Template wrapper = d->engine->loadByName(d->wrapper);
235 if (tmpl->error() != Grantlee::NoError) {
237 c->
error(QLatin1String(
"Error while rendering template: ") + tmpl->errorString());
241 Grantlee::SafeString safeContent(content,
true);
242 gc.insert(QStringLiteral(
"content"), safeContent);
243 content = wrapper->render(&gc);
245 if (wrapper->error() != Grantlee::NoError) {
247 c->
error(QLatin1String(
"Error while rendering template: ") + tmpl->errorString());
252 ret = content.toUtf8();
259 Q_ASSERT_X(translator,
"add translator to GrantleeView",
"invalid QTranslator object");
260 d->translators.insert(locale, translator);
271 Q_ASSERT_X(!path.isEmpty(),
"add translation catalog to GrantleeView",
"empty path");
272 Q_ASSERT_X(!catalog.isEmpty(),
"add translation catalog to GrantleeView",
"empty catalog name");
273 d->translationCatalogs.insert(catalog, path);
279 Q_ASSERT_X(!catalogs.empty(),
"add translation catalogs to GranteleeView",
"empty QHash");
280 d->translationCatalogs.unite(catalogs);
284 const QString &directory,
285 const QString &prefix,
286 const QString &suffix)
288 QVector<QLocale> locales;
290 if (Q_LIKELY(!filename.isEmpty() && !directory.isEmpty())) {
291 const QDir i18nDir(directory);
292 if (Q_LIKELY(i18nDir.exists())) {
293 const QString _prefix = prefix.isEmpty() ? QStringLiteral(
".") : prefix;
294 const QString _suffix = suffix.isEmpty() ? QStringLiteral(
".qm") : suffix;
295 const QStringList namesFilter =
296 QStringList({filename + _prefix + QLatin1Char(
'*') + _suffix});
297 const QFileInfoList tsFiles = i18nDir.entryInfoList(namesFilter, QDir::Files);
298 if (Q_LIKELY(!tsFiles.empty())) {
299 locales.reserve(tsFiles.size());
300 for (
const QFileInfo &ts : tsFiles) {
301 const QString fn = ts.fileName();
302 const int prefIdx = fn.indexOf(_prefix);
303 const QString locString =
304 fn.mid(prefIdx + _prefix.length(),
305 fn.length() - prefIdx - _suffix.length() - _prefix.length());
306 QLocale loc(locString);
307 if (Q_LIKELY(loc.language() != QLocale::C)) {
308 auto trans =
new QTranslator(
this);
309 if (Q_LIKELY(trans->load(loc, filename, _prefix, directory))) {
312 qCDebug(CUTELYST_GRANTLEE) <<
"Loaded translations for locale" << loc
313 <<
"from" << ts.absoluteFilePath();
316 qCWarning(CUTELYST_GRANTLEE)
317 <<
"Can not load translations for locale" << loc;
320 qCWarning(CUTELYST_GRANTLEE)
321 <<
"Can not load translations for invalid locale string" << locString;
326 qCWarning(CUTELYST_GRANTLEE) <<
"Can not find translation files for" << filename
327 <<
"in directory" << directory;
330 qCWarning(CUTELYST_GRANTLEE)
331 <<
"Can not load translations from not existing directory:" << directory;
334 qCWarning(CUTELYST_GRANTLEE)
335 <<
"Can not load translations for empty file name or empty path.";
341#include "moc_grantleeview.cpp"
void stash(const QVariantHash &unite)
QLocale locale() const noexcept
Response * res() const noexcept
QString translate(const char *context, const char *sourceText, const char *disambiguation=nullptr, int n=-1) const
void setStash(const QString &key, const QVariant &value)
bool error() const noexcept
Returns true if an error was set.
QStringList includePaths() const
Returns the list of include paths.
QVector< QLocale > loadTranslationsFromDir(const QString &filename, const QString &directory, const QString &prefix=QStringLiteral("."), const QString &suffix=QStringLiteral(".qm"))
Grantlee::Engine * engine() const
QByteArray render(Context *c) const final
void setWrapper(const QString &name)
Sets the template wrapper name, the template will be rendered into content variable in which the wrap...
void addTranslator(const QLocale &locale, QTranslator *translator)
bool isCaching() const
Returns true if caching is enabled.
void setTemplateExtension(const QString &extension)
Sets the template extension, defaults to ".html".
GrantleeView(QObject *parent=nullptr, const QString &name=QString())
Constructs a GrantleeView object with the given parent and name.
QString wrapper() const
Returns the template wrapper.
void setIncludePaths(const QStringList &paths)
Sets the list of include paths which will be looked for when resolving templates files.
void setCache(bool enable)
Sets if template caching should be done, this increases performance at the cost of higher memory usag...
void addTranslationCatalog(const QString &path, const QString &catalog)
void addTranslationCatalogs(const QHash< QString, QString > &catalogs)
QString templateExtension() const
Returns the template extension.
void setBody(QIODevice *body)
View(QObject *parent, const QString &name)
The Cutelyst namespace holds all public Cutelyst API.
QMultiMap< QString, QString > ParamsMultiMap