5 #include "grantleeview_p.h"
7 #include "application.h"
13 #include <grantlee/qtlocalizer.h>
14 #include <grantlee/metatype.h>
17 #include <QDirIterator>
18 #include <QtCore/QLoggingCategory>
19 #include <QTranslator>
21 Q_LOGGING_CATEGORY(CUTELYST_GRANTLEE,
"cutelyst.grantlee", QtWarningMsg)
26 return object.value(property);
30 return object->property(property.toLatin1().constData());
37 Grantlee::registerMetaType<ParamsMultiMap>();
38 Grantlee::registerMetaType<Cutelyst::Request*>();
40 d->loader = QSharedPointer<Grantlee::FileSystemTemplateLoader>(
new Grantlee::FileSystemTemplateLoader);
42 d->engine =
new Grantlee::Engine(
this);
43 d->engine->addTemplateLoader(d->loader);
46 const QByteArrayList dirs = QByteArrayList{ QByteArrayLiteral(CUTELYST_PLUGINS_DIR) } + qgetenv(
"CUTELYST_PLUGINS_DIR").split(
';');
47 for (
const QByteArray &dir : dirs) {
48 d->engine->addPluginPath(QString::fromLocal8Bit(dir));
51 d->engine->addDefaultLibrary(QStringLiteral(
"grantlee_cutelyst"));
53 auto app = qobject_cast<Application *>(parent);
60 d->cutelystVar = app->config(QStringLiteral(
"CUTELYST_VAR"), QStringLiteral(
"c")).toString();
62 app->loadTranslations(QStringLiteral(
"plugin_view_grantlee"));
69 QStringList GrantleeView::includePaths()
const
72 return d->includePaths;
78 d->loader->setTemplateDirs(paths);
79 d->includePaths = paths;
83 QString GrantleeView::templateExtension()
const
92 d->extension = extension;
96 QString GrantleeView::wrapper()
const
113 if (enable != d->cache.isNull()) {
118 d->engine =
new Grantlee::Engine(
this);
121 d->cache = QSharedPointer<Grantlee::CachingLoaderDecorator>(
new Grantlee::CachingLoaderDecorator(d->loader));
122 d->engine->addTemplateLoader(d->cache);
125 d->engine->addTemplateLoader(d->loader);
144 const auto includePaths = d->includePaths;
145 for (
const QString &includePath : includePaths) {
146 QDirIterator it(includePath, {
147 QLatin1Char(
'*') + d->extension
149 QDir::Files | QDir::NoDotAndDotDot,
150 QDirIterator::Subdirectories);
151 while (it.hasNext()) {
152 QString path = it.next();
153 path.remove(includePath);
154 if (path.startsWith(QLatin1Char(
'/'))) {
158 if (d->cache->canLoadTemplate(path)) {
159 d->cache->loadByName(path, d->engine);
168 return !d->cache.isNull();
176 c->
setStash(d->cutelystVar, QVariant::fromValue(c));
177 const QVariantHash stash = c->
stash();
178 auto it = stash.constFind(QStringLiteral(
"template"));
179 QString templateFile;
180 if (it != stash.constEnd()) {
181 templateFile = it.value().toString();
183 if (c->action() && !c->action()->
reverse().isEmpty()) {
184 templateFile = c->action()->
reverse() + d->extension;
185 if (templateFile.startsWith(QLatin1Char(
'/'))) {
186 templateFile.remove(0, 1);
190 if (templateFile.isEmpty()) {
191 c->
error(QStringLiteral(
"Cannot render template, template name or template stash key not defined"));
196 qCDebug(CUTELYST_GRANTLEE) <<
"Rendering template" << templateFile;
198 Grantlee::Context gc(stash);
200 auto localizer = QSharedPointer<Grantlee::QtLocalizer>::create(c->
locale());
202 auto transIt = d->translators.constFind(c->
locale());
203 if (transIt != d->translators.constEnd()) {
204 localizer.data()->installTranslator(transIt.value(), transIt.key().name());
207 auto catalogIt = d->translationCatalogs.constBegin();
208 while (catalogIt != d->translationCatalogs.constEnd()) {
209 localizer.data()->loadCatalog(catalogIt.value(), catalogIt.key());
213 gc.setLocalizer(localizer);
215 Grantlee::Template tmpl = d->engine->loadByName(templateFile);
216 if (tmpl->error() != Grantlee::NoError) {
218 c->
error(QLatin1String(
"Error while rendering template: ") + tmpl->errorString());
222 QString content = tmpl->render(&gc);
223 if (tmpl->error() != Grantlee::NoError) {
225 c->
error(QLatin1String(
"Error while rendering template: ") + tmpl->errorString());
229 if (!d->wrapper.isEmpty()) {
230 Grantlee::Template wrapper = d->engine->loadByName(d->wrapper);
231 if (tmpl->error() != Grantlee::NoError) {
233 c->
error(QLatin1String(
"Error while rendering template: ") + tmpl->errorString());
237 Grantlee::SafeString safeContent(content,
true);
238 gc.insert(QStringLiteral(
"content"), safeContent);
239 content = wrapper->render(&gc);
241 if (wrapper->error() != Grantlee::NoError) {
243 c->
error(QLatin1String(
"Error while rendering template: ") + tmpl->errorString());
248 ret = content.toUtf8();
255 Q_ASSERT_X(translator,
"add translator to GrantleeView",
"invalid QTranslator object");
256 d->translators.insert(locale, translator);
267 Q_ASSERT_X(!path.isEmpty(),
"add translation catalog to GrantleeView",
"empty path");
268 Q_ASSERT_X(!catalog.isEmpty(),
"add translation catalog to GrantleeView",
"empty catalog name");
269 d->translationCatalogs.insert(catalog, path);
275 Q_ASSERT_X(!catalogs.empty(),
"add translation catalogs to GranteleeView",
"empty QHash");
276 d->translationCatalogs.unite(catalogs);
281 QVector<QLocale> locales;
283 if (Q_LIKELY(!filename.isEmpty() && !directory.isEmpty())) {
284 const QDir i18nDir(directory);
285 if (Q_LIKELY(i18nDir.exists())) {
286 const QString _prefix = prefix.isEmpty() ? QStringLiteral(
".") : prefix;
287 const QString _suffix = suffix.isEmpty() ? QStringLiteral(
".qm") : suffix;
288 const QStringList namesFilter = QStringList({filename + _prefix + QLatin1Char(
'*') + _suffix});
289 const QFileInfoList tsFiles = i18nDir.entryInfoList(namesFilter, QDir::Files);
290 if (Q_LIKELY(!tsFiles.empty())) {
291 locales.reserve(tsFiles.size());
292 for (
const QFileInfo &ts : tsFiles) {
293 const QString fn = ts.fileName();
294 const int prefIdx = fn.indexOf(_prefix);
295 const QString locString = fn.mid(prefIdx + _prefix.length(), fn.length() - prefIdx - _suffix.length() - _prefix.length());
296 QLocale loc(locString);
297 if (Q_LIKELY(loc.language() != QLocale::C)) {
298 auto trans =
new QTranslator(
this);
299 if (Q_LIKELY(trans->load(loc, filename, _prefix, directory))) {
302 qCDebug(CUTELYST_GRANTLEE) <<
"Loaded translations for locale" << loc <<
"from" << ts.absoluteFilePath();
305 qCWarning(CUTELYST_GRANTLEE) <<
"Can not load translations for locale" << loc;
308 qCWarning(CUTELYST_GRANTLEE) <<
"Can not load translations for invalid locale string" << locString;
313 qCWarning(CUTELYST_GRANTLEE) <<
"Can not find translation files for" << filename <<
"in directory" << directory;
316 qCWarning(CUTELYST_GRANTLEE) <<
"Can not load translations from not existing directory:" << directory;
319 qCWarning(CUTELYST_GRANTLEE) <<
"Can not load translations for empty file name or empty path.";
325 #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.
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.
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)
void setBody(QIODevice *body)
Cutelyst View abstract view component
The Cutelyst namespace holds all public Cutelyst API.
QMultiMap< QString, QString > ParamsMultiMap