GrantleeTheme

grantleetheme.cpp
1 /*
2  SPDX-FileCopyrightText: 2013-2022 Laurent Montel <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.1-or-later
5 */
6 
7 #include "grantleetheme.h"
8 #include "grantleetheme_debug.h"
9 #include "grantleetheme_p.h"
10 #include "grantleethemeengine.h"
11 #include "qtresourcetemplateloader.h"
12 #include <config-grantleetheme.h>
13 
14 #include <KConfig>
15 #include <KConfigGroup>
16 #include <KLocalizedString>
17 
18 #include <QDir>
19 #include <QSharedPointer>
20 
21 using namespace GrantleeTheme;
22 
23 QSharedPointer<GrantleeKi18nLocalizer> GrantleeTheme::ThemePrivate::sLocalizer;
24 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
25 Grantlee::Engine *GrantleeTheme::ThemePrivate::sEngine = nullptr;
26 #else
27 KTextTemplate::Engine *GrantleeTheme::ThemePrivate::sEngine = nullptr;
28 #endif
29 
30 ThemePrivate::ThemePrivate()
31  : QSharedData()
32 {
33 }
34 
35 ThemePrivate::ThemePrivate(const ThemePrivate &other)
36 
37  = default;
38 
39 ThemePrivate::~ThemePrivate() = default;
40 
41 void ThemePrivate::setupEngine()
42 {
43  sEngine = new GrantleeTheme::Engine();
44 }
45 
46 void ThemePrivate::setupLoader()
47 {
48  // Get the parent dir with themes, we set the theme directory separately
49 
50  QStringList templatePaths;
51  for (const QString &absolutePath : std::as_const(absolutePaths)) {
52  QDir dir(absolutePath);
53  dir.cdUp();
54  templatePaths << dir.absolutePath();
55  }
57  loader->setTemplateDirs(templatePaths);
58  loader->setTheme(dirName);
59 
60  if (!sEngine) {
61  ThemePrivate::setupEngine();
62  }
63  sEngine->addTemplateLoader(loader);
64 }
65 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
66 Grantlee::Context ThemePrivate::createContext(const QVariantHash &data, const QByteArray &applicationDomain)
67 #else
68 KTextTemplate::Context ThemePrivate::createContext(const QVariantHash &data, const QByteArray &applicationDomain)
69 #endif
70 {
71  if (!sLocalizer) {
72  sLocalizer.reset(new GrantleeKi18nLocalizer());
73  }
74  sLocalizer->setApplicationDomain(applicationDomain);
75 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
76  Grantlee::Context ctx(data);
77 #else
78  KTextTemplate::Context ctx(data);
79 #endif
80  ctx.setLocalizer(sLocalizer);
81  return ctx;
82 }
83 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
84 QString ThemePrivate::errorTemplate(const QString &reason, const QString &origTemplateName, const Grantlee::Template &failedTemplate)
85 #else
86 QString ThemePrivate::errorTemplate(const QString &reason, const QString &origTemplateName, const KTextTemplate::Template &failedTemplate)
87 #endif
88 {
89 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
90  Grantlee::Template tpl = sEngine->newTemplate(QStringLiteral("<h1>{{ error }}</h1>\n"
91  "<b>%1:</b> {{ templateName }}<br>\n"
92  "<b>%2:</b> {{ errorMessage }}")
93  .arg(i18n("Template"), i18n("Error message")),
94  QStringLiteral("TemplateError"));
95 
96  Grantlee::Context ctx = createContext();
97 #else
98  KTextTemplate::Template tpl = sEngine->newTemplate(QStringLiteral("<h1>{{ error }}</h1>\n"
99  "<b>%1:</b> {{ templateName }}<br>\n"
100  "<b>%2:</b> {{ errorMessage }}")
101  .arg(i18n("Template"), i18n("Error message")),
102  QStringLiteral("TemplateError"));
103 
104  KTextTemplate::Context ctx = createContext();
105 #endif
106  ctx.insert(QStringLiteral("error"), reason);
107  ctx.insert(QStringLiteral("templateName"), origTemplateName);
108  const QString errorString = failedTemplate ? failedTemplate->errorString() : i18n("(null template)");
109  ctx.insert(QStringLiteral("errorMessage"), errorString);
110  return tpl->render(&ctx);
111 }
112 
113 Theme::Theme()
114  : d(new ThemePrivate)
115 {
116 }
117 
118 Theme::Theme(const QString &themePath, const QString &dirName, const QString &defaultDesktopFileName)
119  : d(new ThemePrivate)
120 {
121  const QString themeInfoFile = themePath + QLatin1Char('/') + defaultDesktopFileName;
122  KConfig config(themeInfoFile);
123  KConfigGroup group(&config, QStringLiteral("Desktop Entry"));
124  if (group.isValid()) {
125  d->dirName = dirName;
126  d->absolutePaths.append(themePath);
127  d->name = group.readEntry("Name", QString());
128  d->description = group.readEntry("Description", QString());
129  d->themeFileName = group.readEntry("FileName", QString());
130  d->displayExtraVariables = group.readEntry("DisplayExtraVariables", QStringList());
131  }
132 }
133 
134 Theme::Theme(const Theme &other)
135 
136  = default;
137 
138 Theme::~Theme() = default;
139 
140 bool Theme::operator==(const Theme &other) const
141 {
142  return isValid() && other.isValid() && d->absolutePaths == other.d->absolutePaths;
143 }
144 
145 Theme &Theme::operator=(const Theme &other)
146 {
147  if (this != &other) {
148  d = other.d;
149  }
150 
151  return *this;
152 }
153 
154 bool Theme::isValid() const
155 {
156  return !d->themeFileName.isEmpty() && !d->name.isEmpty();
157 }
158 
159 QString Theme::description() const
160 {
161  return d->description;
162 }
163 
164 QString Theme::themeFilename() const
165 {
166  return d->themeFileName;
167 }
168 
169 QString Theme::name() const
170 {
171  return d->name;
172 }
173 
174 QStringList Theme::displayExtraVariables() const
175 {
176  return d->displayExtraVariables;
177 }
178 
179 QString Theme::dirName() const
180 {
181  return d->dirName;
182 }
183 
184 QString Theme::absolutePath() const
185 {
186  if (!d->absolutePaths.isEmpty()) {
187  return d->absolutePaths.at(0); // ####
188  }
189  return {};
190 }
191 
192 QString Theme::author() const
193 {
194  return d->author;
195 }
196 
197 QString Theme::authorEmail() const
198 {
199  return d->email;
200 }
201 
202 void Theme::addThemePath(const QString &path)
203 {
204  d->absolutePaths.append(path);
205 }
206 
207 QString Theme::render(const QString &templateName, const QVariantHash &data, const QByteArray &applicationDomain)
208 {
209  if (!d->loader) {
210  d->setupLoader();
211  }
212  Q_ASSERT(d->loader);
213 
214  if (!d->loader->canLoadTemplate(templateName)) {
215  qCWarning(GRANTLEETHEME_LOG) << "Cannot load template" << templateName
216  << ", please check your installation. Tried in these dirs:" << d->loader->templateDirs();
217  return {};
218  }
219 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
220  Grantlee::Template tpl = d->loader->loadByName(templateName, ThemePrivate::sEngine);
221 #else
222  KTextTemplate::Template tpl = d->loader->loadByName(templateName, ThemePrivate::sEngine);
223 #endif
224  if (!tpl || tpl->error()) {
225  return d->errorTemplate(i18n("Template parsing error"), templateName, tpl);
226  }
227 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
228  Grantlee::Context ctx = d->createContext(data, applicationDomain);
229 #else
230  KTextTemplate::Context ctx = d->createContext(data, applicationDomain);
231 #endif
232  const QString result = tpl->render(&ctx);
233  if (tpl->error()) {
234  return d->errorTemplate(i18n("Template rendering error"), templateName, tpl);
235  }
236 
237  return result;
238 }
239 
240 void Theme::addPluginPath(const QString &path)
241 {
242  if (!ThemePrivate::sEngine) {
243  ThemePrivate::setupEngine();
244  }
245 
246  QStringList paths = ThemePrivate::sEngine->pluginPaths();
247  if (!paths.contains(path)) {
248  paths.prepend(path);
249  ThemePrivate::sEngine->setPluginPaths(paths);
250  }
251 }
bool contains(const QString &str, Qt::CaseSensitivity cs) const const
QSharedPointer< T > create(Args &&... args)
void prepend(const T &value)
QString i18n(const char *text, const TYPE &arg...)
The Theme class.
Definition: grantleetheme.h:26
KSharedConfigPtr config()
KIOFILEWIDGETS_EXPORT QString dir(const QString &fileClass)
The GrantleeKi18nLocalizer class.
QString & append(QChar ch)
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Wed Sep 28 2022 04:06:59 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.