6#include "application.h"
9#include "cuteleeview_p.h"
10#include "cutelystcutelee.h"
13#include <cutelee/metatype.h>
14#include <cutelee/qtlocalizer.h>
16#include <QDirIterator>
19#include <QtCore/QLoggingCategory>
21Q_LOGGING_CATEGORY(CUTELYST_CUTELEE,
"cutelyst.cutelee", QtWarningMsg)
26return object.value(property);
30return object->property(property.toLatin1().constData());
34 :
View(new CuteleeViewPrivate, parent,
name)
38 Cutelee::registerMetaType<ParamsMultiMap>();
39 Cutelee::registerMetaType<Cutelyst::Request *>();
41 d->loader = std::make_shared<Cutelee::FileSystemTemplateLoader>();
43 d->engine =
new Cutelee::Engine(
this);
44 d->engine->addTemplateLoader(d->loader);
48 auto app = qobject_cast<Application *>(parent);
56 app->config(QStringLiteral(
"CUTELYST_VAR"), QStringLiteral(
"c")).toString();
58 app->loadTranslations(QStringLiteral(
"plugin_view_cutelee"));
68 return d->includePaths;
74 d->loader->setTemplateDirs(paths);
75 d->includePaths = paths;
88 d->extension = extension;
109 if (enable && d->cache) {
114 d->engine =
new Cutelee::Engine(
this);
117 d->cache = std::make_shared<Cutelee::CachingLoaderDecorator>(d->loader);
118 d->engine->addTemplateLoader(d->cache);
121 d->engine->addTemplateLoader(d->loader);
141 const auto includePaths = d->includePaths;
142 for (
const QString &includePath : includePaths) {
143 QDirIterator it(includePath,
144 {QLatin1Char(
'*') + d->extension},
145 QDir::Files | QDir::NoDotAndDotDot,
146 QDirIterator::Subdirectories);
147 while (it.hasNext()) {
148 QString path = it.next();
149 path.remove(includePath);
150 if (path.startsWith(u
'/')) {
154 if (d->cache->canLoadTemplate(path)) {
155 d->cache->loadByName(path, d->engine);
172 c->
setStash(d->cutelystVar, QVariant::fromValue(c));
173 const QVariantHash stash = c->
stash();
174 auto it = stash.constFind(QStringLiteral(
"template"));
175 QString templateFile;
176 if (it != stash.constEnd()) {
177 templateFile = it.value().toString();
179 if (c->action() && !c->action()->
reverse().isEmpty()) {
180 templateFile = c->action()->
reverse() + d->extension;
181 if (templateFile.startsWith(u
'/')) {
182 templateFile.remove(0, 1);
186 if (templateFile.isEmpty()) {
187 c->
error(QStringLiteral(
188 "Cannot render template, template name or template stash key not defined"));
193 qCDebug(CUTELYST_CUTELEE) <<
"Rendering template" << templateFile;
195 Cutelee::Context gc(stash);
197 auto localizer = std::make_shared<Cutelee::QtLocalizer>(c->
locale());
199 auto transIt = d->translators.constFind(c->
locale());
200 if (transIt != d->translators.constEnd()) {
201 localizer.get()->installTranslator(transIt.value(), transIt.key().name());
204 auto catalogIt = d->translationCatalogs.constBegin();
205 while (catalogIt != d->translationCatalogs.constEnd()) {
206 localizer.get()->loadCatalog(catalogIt.value(), catalogIt.key());
210 gc.setLocalizer(localizer);
212 Cutelee::Template tmpl = d->engine->loadByName(templateFile);
213 if (tmpl->error() != Cutelee::NoError) {
215 c->
error(QLatin1String(
"Error while rendering template: ") + tmpl->errorString());
219 QString content = tmpl->render(&gc);
220 if (tmpl->error() != Cutelee::NoError) {
222 c->
error(QLatin1String(
"Error while rendering template: ") + tmpl->errorString());
226 if (!d->wrapper.isEmpty()) {
227 Cutelee::Template wrapper = d->engine->loadByName(d->wrapper);
228 if (tmpl->error() != Cutelee::NoError) {
230 c->
error(QLatin1String(
"Error while rendering template: ") + tmpl->errorString());
234 Cutelee::SafeString safeContent(content,
true);
235 gc.insert(QStringLiteral(
"content"), safeContent);
236 content = wrapper->render(&gc);
238 if (wrapper->error() != Cutelee::NoError) {
240 c->
error(QLatin1String(
"Error while rendering template: ") + tmpl->errorString());
245 ret = content.toUtf8();
252 Q_ASSERT_X(translator,
"add translator to CuteleeView",
"invalid QTranslator object");
253 d->translators.insert(locale, translator);
264 Q_ASSERT_X(!path.isEmpty(),
"add translation catalog to CuteleeView",
"empty path");
265 Q_ASSERT_X(!catalog.isEmpty(),
"add translation catalog to CuteleeView",
"empty catalog name");
266 d->translationCatalogs.insert(catalog, path);
272 Q_ASSERT_X(!catalogs.empty(),
"add translation catalogs to GranteleeView",
"empty QHash");
273 d->translationCatalogs.unite(catalogs);
277 const QString &directory,
278 const QString &prefix,
279 const QString &suffix)
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 =
289 QStringList({filename + _prefix + QLatin1Char(
'*') + _suffix});
290 const QFileInfoList tsFiles = i18nDir.entryInfoList(namesFilter, QDir::Files);
291 if (Q_LIKELY(!tsFiles.empty())) {
292 locales.reserve(tsFiles.size());
293 for (
const QFileInfo &ts : tsFiles) {
294 const QString fn = ts.fileName();
295 const int prefIdx = fn.indexOf(_prefix);
296 const QString locString =
297 fn.mid(prefIdx + _prefix.length(),
298 fn.length() - prefIdx - _suffix.length() - _prefix.length());
299 QLocale loc(locString);
300 if (Q_LIKELY(loc.language() != QLocale::C)) {
301 auto trans =
new QTranslator(
this);
302 if (Q_LIKELY(trans->load(loc, filename, _prefix, directory))) {
305 qCDebug(CUTELYST_CUTELEE) <<
"Loaded translations for locale" << loc
306 <<
"from" << ts.absoluteFilePath();
309 qCWarning(CUTELYST_CUTELEE)
310 <<
"Can not load translations for locale" << loc;
313 qCWarning(CUTELYST_CUTELEE)
314 <<
"Can not load translations for invalid locale string" << locString;
319 qCWarning(CUTELYST_CUTELEE) <<
"Can not find translation files for" << filename
320 <<
"in directory" << directory;
323 qCWarning(CUTELYST_CUTELEE)
324 <<
"Can not load translations from not existing directory:" << directory;
327 qCWarning(CUTELYST_CUTELEE)
328 <<
"Can not load translations for empty file name or empty path.";
334void CuteleeViewPrivate::initEngine()
337 const QByteArrayList dirs = QByteArrayList{QByteArrayLiteral(CUTELYST_PLUGINS_DIR)} +
338 qgetenv(
"CUTELYST_PLUGINS_DIR").split(
';');
339 for (
const QByteArray &dir : dirs) {
340 engine->addPluginPath(QString::fromLocal8Bit(dir));
343 engine->insertDefaultLibrary(QStringLiteral(
"cutelee_cutelyst"),
new CutelystCutelee(engine));
346#include "moc_cuteleeview.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.
void setWrapper(const QString &name)
Sets the template wrapper name, the template will be rendered into content variable in which the wrap...
CuteleeView(QObject *parent=nullptr, const QString &name=QString())
Constructs a CuteleeView object with the given parent and name.
void addTranslator(const QLocale &locale, QTranslator *translator)
QByteArray render(Context *c) const final
void setTemplateExtension(const QString &extension)
Sets the template extension, defaults to ".html".
void addTranslationCatalogs(const QMultiHash< QString, QString > &catalogs)
QVector< QLocale > loadTranslationsFromDir(const QString &filename, const QString &directory, const QString &prefix=QStringLiteral("."), const QString &suffix=QStringLiteral(".qm"))
QString wrapper() const
Returns the template wrapper.
bool isCaching() const
Returns true if caching is enabled.
Cutelee::Engine * engine() const
QString templateExtension() const
Returns the template extension.
void addTranslationCatalog(const QString &path, const QString &catalog)
void setCache(bool enable)
Sets if template caching should be done, this increases performance at the cost of higher memory usag...
QStringList includePaths() const
Returns the list of include paths.
void setIncludePaths(const QStringList &paths)
Sets the list of include paths which will be looked for when resolving templates files.
void setBody(QIODevice *body)
View(QObject *parent, const QString &name)
The Cutelyst namespace holds all public Cutelyst API.
QMultiMap< QString, QString > ParamsMultiMap