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.view.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"));
65QStringList CuteleeView::includePaths()
const
68 return d->includePaths;
74 d->loader->setTemplateDirs(paths);
75 d->includePaths = paths;
79QString CuteleeView::templateExtension()
const
88 d->extension = extension;
92QString CuteleeView::wrapper()
const
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();
181 if (templateFile.startsWith(u
'/')) {
182 templateFile.remove(0, 1);
186 if (templateFile.isEmpty()) {
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) {
216 c->
appendError(QLatin1String(
"Error while rendering template: ") + tmpl->errorString());
220 QString content = tmpl->render(&gc);
221 if (tmpl->error() != Cutelee::NoError) {
223 c->
appendError(QLatin1String(
"Error while rendering template: ") + tmpl->errorString());
227 if (!d->wrapper.isEmpty()) {
228 Cutelee::Template wrapper = d->engine->loadByName(d->wrapper);
229 if (tmpl->error() != Cutelee::NoError) {
231 c->
appendError(QLatin1String(
"Error while rendering template: ") + tmpl->errorString());
235 Cutelee::SafeString safeContent(content,
true);
236 gc.insert(QStringLiteral(
"content"), safeContent);
237 content = wrapper->render(&gc);
239 if (wrapper->error() != Cutelee::NoError) {
241 c->
appendError(QLatin1String(
"Error while rendering template: ") + tmpl->errorString());
246 ret = content.toUtf8();
253 Q_ASSERT_X(translator,
"add translator to CuteleeView",
"invalid QTranslator object");
254 d->translators.insert(locale, translator);
265 Q_ASSERT_X(!path.isEmpty(),
"add translation catalog to CuteleeView",
"empty path");
266 Q_ASSERT_X(!catalog.isEmpty(),
"add translation catalog to CuteleeView",
"empty catalog name");
267 d->translationCatalogs.insert(catalog, path);
273 Q_ASSERT_X(!catalogs.empty(),
"add translation catalogs to GranteleeView",
"empty QHash");
274 d->translationCatalogs.unite(catalogs);
278 const QString &directory,
279 const QString &prefix,
280 const QString &suffix)
282 QVector<QLocale> locales;
284 if (Q_LIKELY(!filename.isEmpty() && !directory.isEmpty())) {
285 const QDir i18nDir(directory);
286 if (Q_LIKELY(i18nDir.exists())) {
287 const QString _prefix = prefix.isEmpty() ? QStringLiteral(
".") : prefix;
288 const QString _suffix = suffix.isEmpty() ? QStringLiteral(
".qm") : suffix;
289 const QStringList namesFilter =
290 QStringList({filename + _prefix + QLatin1Char(
'*') + _suffix});
291 const QFileInfoList tsFiles = i18nDir.entryInfoList(namesFilter, QDir::Files);
292 if (Q_LIKELY(!tsFiles.empty())) {
293 locales.reserve(tsFiles.size());
294 for (
const QFileInfo &ts : tsFiles) {
295 const QString fn = ts.fileName();
296 const int prefIdx = fn.indexOf(_prefix);
297 const QString locString =
298 fn.mid(prefIdx + _prefix.length(),
299 fn.length() - prefIdx - _suffix.length() - _prefix.length());
300 QLocale loc(locString);
301 if (Q_LIKELY(loc.language() != QLocale::C)) {
302 auto trans =
new QTranslator(
this);
303 if (Q_LIKELY(trans->load(loc, filename, _prefix, directory))) {
306 qCDebug(CUTELYST_CUTELEE) <<
"Loaded translations for locale" << loc
307 <<
"from" << ts.absoluteFilePath();
310 qCWarning(CUTELYST_CUTELEE)
311 <<
"Can not load translations for locale" << loc;
314 qCWarning(CUTELYST_CUTELEE)
315 <<
"Can not load translations for invalid locale string" << locString;
320 qCWarning(CUTELYST_CUTELEE) <<
"Can not find translation files for" << filename
321 <<
"in directory" << directory;
324 qCWarning(CUTELYST_CUTELEE)
325 <<
"Can not load translations from not existing directory:" << directory;
328 qCWarning(CUTELYST_CUTELEE)
329 <<
"Can not load translations for empty file name or empty path.";
335void CuteleeViewPrivate::initEngine()
338 const QByteArrayList dirs = QByteArrayList{QByteArrayLiteral(CUTELYST_PLUGINS_DIR)} +
339 qgetenv(
"CUTELYST_PLUGINS_DIR").split(
';');
340 for (
const QByteArray &dir : dirs) {
341 engine->addPluginPath(QString::fromLocal8Bit(dir));
344 engine->insertDefaultLibrary(QStringLiteral(
"cutelee_cutelyst"),
new CutelystCutelee(engine));
347#include "moc_cuteleeview.cpp"
QString reverse() const noexcept
QString name() const noexcept
void stash(const QVariantHash &unite)
QLocale locale() const noexcept
Response * res() const noexcept
void setStash(const QString &key, const QVariant &value)
QString qtTrId(const char *id, int n=-1) const
void appendError(const QString &error)
void setWrapper(const QString &name)
CuteleeView(QObject *parent=nullptr, const QString &name=QString())
void addTranslator(const QLocale &locale, QTranslator *translator)
void setTemplateExtension(const QString &extension)
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"))
Cutelee::Engine * engine() const
void addTranslationCatalog(const QString &path, const QString &catalog)
QByteArray render(Context *c) const override final
void setCache(bool enable)
void setIncludePaths(const QStringList &paths)
void setBody(QIODevice *body)
View(QObject *parent, const QString &name)
QMultiMap< QString, QString > ParamsMultiMap
The Cutelyst namespace holds all public Cutelyst API.