KTextTemplate

engine.cpp
1/*
2 This file is part of the KTextTemplate library
3
4 SPDX-FileCopyrightText: 2009, 2010 Stephen Kelly <steveire@gmail.com>
5
6 SPDX-License-Identifier: LGPL-2.1-or-later
7
8*/
9
10#include "engine.h"
11#include "engine_p.h"
12
13#include "exception.h"
14#include "ktexttemplate_config_p.h"
15#ifdef QT_QML_LIB
16#include "scriptabletags.h"
17#endif
18#include "template_p.h"
19
20#include <QCoreApplication>
21#include <QDir>
22#include <QPluginLoader>
23#include <QTextStream>
24
25using namespace KTextTemplate;
26
27static const char s_scriptableLibName[] = "ktexttemplate_scriptabletags";
28
29Engine::Engine(QObject *parent)
30 : QObject(parent)
31 , d_ptr(new EnginePrivate(this))
32{
33 d_ptr->m_defaultLibraries << QStringLiteral("ktexttemplate_defaulttags") << QStringLiteral("ktexttemplate_loadertags")
34 << QStringLiteral("ktexttemplate_defaultfilters");
35
36 d_ptr->m_pluginDirs = QCoreApplication::libraryPaths();
37 d_ptr->m_pluginDirs << QString::fromLocal8Bit(KTEXTTEMPLATE_PLUGIN_PATH);
38}
39
41{
42#ifdef QT_QML_LIB
43 qDeleteAll(d_ptr->m_scriptableLibraries);
44#endif
45 d_ptr->m_libraries.clear();
46 delete d_ptr;
47}
48
54
56{
57 Q_D(Engine);
58 d->m_loaders << loader;
59}
60
61std::pair<QString, QString> Engine::mediaUri(const QString &fileName) const
62{
63 Q_D(const Engine);
64
65 std::pair<QString, QString> uri;
66 for (auto &loader : d->m_loaders) {
67 uri = loader->getMediaUri(fileName);
68 if (!uri.second.isEmpty())
69 break;
70 }
71 return uri;
72}
73
75{
76 Q_D(Engine);
77 d->m_pluginDirs = dirs;
78}
79
81{
82 Q_D(Engine);
83 QStringList temp;
84 temp << dir;
85 temp << d->m_pluginDirs;
86 d->m_pluginDirs = temp;
87}
88
90{
91 Q_D(Engine);
92 d->m_pluginDirs.removeAll(dir);
93}
94
96{
97 Q_D(const Engine);
98 return d->m_pluginDirs;
99}
100
102{
103 Q_D(const Engine);
104 return d->m_defaultLibraries;
105}
106
108{
109 Q_D(Engine);
110 d->m_defaultLibraries << libName;
111}
112
114{
115 Q_D(Engine);
116 d->m_defaultLibraries.removeAll(libName);
117}
118
119void Engine::loadDefaultLibraries()
120{
121 Q_D(Engine);
122
123#ifdef QT_QML_LIB
124 // Make sure we can load default scriptable libraries if we're supposed to.
125 if (d->m_defaultLibraries.contains(QLatin1String(s_scriptableLibName)) && !d->m_scriptableTagLibrary) {
126 d->m_scriptableTagLibrary = new ScriptableTagLibrary(this);
127
128// It would be better to load this as a plugin, but that is not currently
129// possible with webkit/javascriptcore
130// so we new the library directly.
131// https://bugs.webkit.org/show_bug.cgi?id=38193
132#if 0
133 d->loadCppLibrary( s_scriptableLibName );
134 PluginPointer<TagLibraryInterface> library = d->loadCppLibrary( s_scriptableLibName );
135 if ( !library )
136 throw KTextTemplate::Exception( TagSyntaxError, QStringLiteral("Could not load scriptable tags library") );
137#endif
138 }
139#endif
140
141 for (const QString &libName : std::as_const(d->m_defaultLibraries)) {
142 if (libName == QLatin1String(s_scriptableLibName))
143 continue;
144
145 // already loaded by the engine.
146 if (d->m_libraries.contains(libName))
147 continue;
148
149#ifdef QT_QML_LIB
150 // Although we don't use scripted libaries here, we need to
151 // recognize them being first in the search path and not load a
152 // c++ plugin of the same name in that case.
153 auto scriptableLibrary = d->loadScriptableLibrary(libName);
154 if (scriptableLibrary) {
155 scriptableLibrary->clear();
156 break;
157 }
158#endif
159
160 auto library = d->loadCppLibrary(libName);
161 if (library) {
162 break;
163 }
164 }
165}
166
167TagLibraryInterface *Engine::loadLibrary(const QString &name)
168{
169 Q_D(Engine);
170
171#ifdef QT_QML_LIB
172 if (name == QLatin1String(s_scriptableLibName))
173 return nullptr;
174#endif
175
176 // already loaded by the engine.
177 if (d->m_libraries.contains(name))
178 return d->m_libraries.value(name).data();
179
180 auto library = d->loadLibrary(name);
181 if (library) {
182 return library;
183 }
184 throw KTextTemplate::Exception(TagSyntaxError, QStringLiteral("Plugin library '%1' not found.").arg(name));
185 return nullptr;
186}
187
188TagLibraryInterface *EnginePrivate::loadLibrary(const QString &name)
189{
190#ifdef QT_QML_LIB
191 auto scriptableLibrary = loadScriptableLibrary(name);
192 if (scriptableLibrary)
193 return scriptableLibrary;
194
195// else this is not a scriptable library.
196#endif
197
198 return loadCppLibrary(name).data();
199}
200
201EnginePrivate::EnginePrivate(Engine *engine)
202 : q_ptr(engine)
203#ifdef QT_QML_LIB
204 , m_scriptableTagLibrary(nullptr)
205#endif
206 , m_smartTrimEnabled(false)
207{
208}
209
210QString EnginePrivate::getScriptLibraryName(const QString &name) const
211{
212 auto pluginIndex = 0;
213 const QString prefix = QStringLiteral("/kf6/ktexttemplate/");
214 while (m_pluginDirs.size() > pluginIndex) {
215 const auto nextDir = m_pluginDirs.at(pluginIndex++);
216 const QString libFileName = nextDir + prefix + name + QStringLiteral(".qs");
217
218 const QFile file(libFileName);
219 if (!file.exists())
220 continue;
221 return libFileName;
222 }
223 auto it = m_loaders.constBegin();
224 const auto end = m_loaders.constEnd();
225 for (; it != end; ++it) {
226 const auto pair = (*it)->getMediaUri(prefix + name + QStringLiteral(".qs"));
227
228 if (!pair.first.isEmpty() && !pair.second.isEmpty()) {
229 return pair.first + pair.second;
230 }
231 }
232 return {};
233}
234
235#ifdef QT_QML_LIB
236ScriptableLibraryContainer *EnginePrivate::loadScriptableLibrary(const QString &name)
237{
238 if (!m_scriptableTagLibrary)
239 return nullptr;
240
241#if 0
242 if ( !m_libraries.contains( s_scriptableLibName ) )
243 return 0;
244#endif
245
246 const auto libFileName = getScriptLibraryName(name);
247
248 if (libFileName.isEmpty())
249 return nullptr;
250
251 const auto it = m_scriptableLibraries.constFind(libFileName);
252 if (it != m_scriptableLibraries.constEnd()) {
253 auto library = it.value();
254 library->setNodeFactories(m_scriptableTagLibrary->nodeFactories(libFileName));
255 library->setFilters(m_scriptableTagLibrary->filters(libFileName));
256 return library;
257 }
258#if 0
259 PluginPointer<TagLibraryInterface> scriptableTagLibrary = m_libraries.value( s_scriptableLibName );
260#endif
261
262 const auto factories = m_scriptableTagLibrary->nodeFactories(libFileName);
263 const auto filters = m_scriptableTagLibrary->filters(libFileName);
264
265 auto library = new ScriptableLibraryContainer(factories, filters);
266 m_scriptableLibraries.insert(libFileName, library);
267 return library;
268}
269#endif
270
271PluginPointer<TagLibraryInterface> EnginePrivate::loadCppLibrary(const QString &name)
272{
273 auto pluginIndex = 0;
274
275 while (m_pluginDirs.size() > pluginIndex) {
276 const auto nextDir = m_pluginDirs.at(pluginIndex++);
277 const QString pluginDirString = nextDir + QStringLiteral("/kf6/ktexttemplate/");
278
279 const QDir pluginDir(pluginDirString);
280
281 if (!pluginDir.exists())
282 continue;
283
284 auto list = pluginDir.entryList(QStringList(name
285#if PLUGINS_PREFER_DEBUG_POSTFIX
286 + QLatin1Char('d')
287#endif
288 + QLatin1Char('*')));
289
290 if (list.isEmpty()) {
291#if PLUGINS_PREFER_DEBUG_POSTFIX
292 list = pluginDir.entryList(QStringList(name + QLatin1Char('*')));
293 if (list.isEmpty())
294 continue;
295#else
296 continue;
297#endif
298 }
299
300 auto pluginPath = pluginDir.absoluteFilePath(list.first());
301 auto plugin = PluginPointer<TagLibraryInterface>(pluginPath);
302
303 if (plugin) {
304 m_libraries.insert(name, plugin);
305 return plugin;
306 }
307 }
308 return nullptr;
309}
310
312{
313 Q_D(const Engine);
314
315 for (auto &loader : d->m_loaders) {
316 if (!loader->canLoadTemplate(name))
317 continue;
318
319 const auto t = loader->loadByName(name, this);
320
321 if (t) {
322 return t;
323 }
324 }
325 auto t = Template(new TemplateImpl(this));
326 t->setObjectName(name);
327 t->d_ptr->m_error = TagSyntaxError;
328 t->d_ptr->m_errorString = QStringLiteral("Template not found, %1").arg(name);
329 return t;
330}
331
332Template Engine::newTemplate(const QString &content, const QString &name) const
333{
334 Q_D(const Engine);
335 auto t = Template(new TemplateImpl(this, d->m_smartTrimEnabled));
336 t->setObjectName(name);
337 t->setContent(content);
338 return t;
339}
340
342{
343 Q_D(Engine);
344 d->m_smartTrimEnabled = enabled;
345}
346
348{
349 Q_D(const Engine);
350 return d->m_smartTrimEnabled;
351}
352
353#include "moc_engine.cpp"
KTextTemplate::Engine is the main entry point for creating KTextTemplate Templates.
Definition engine.h:110
QStringList pluginPaths() const
Returns the currently configured plugin dirs.
Definition engine.cpp:95
~Engine() override
Destructor.
Definition engine.cpp:40
std::pair< QString, QString > mediaUri(const QString &fileName) const
Returns a URI for a media item with the name name.
Definition engine.cpp:61
Template loadByName(const QString &name) const
Load the Template identified by name.
Definition engine.cpp:311
void setPluginPaths(const QStringList &dirs)
Sets the plugin dirs currently configured on the Engine to dirs.
Definition engine.cpp:74
QList< QSharedPointer< AbstractTemplateLoader > > templateLoaders()
Returns the TemplateLoaders currently configured on the Engine.
Definition engine.cpp:49
void addPluginPath(const QString &dir)
Prepend dir to the list of plugin dirs.
Definition engine.cpp:80
void setSmartTrimEnabled(bool enabled)
Sets whether the smart trim feature is enabled for newly loaded templates.
Definition engine.cpp:341
void removeDefaultLibrary(const QString &libName)
Removes the library named libName from the libraries available by default to new Templates.
Definition engine.cpp:113
QStringList defaultLibraries() const
Returns the libraries available by default to new Templates.
Definition engine.cpp:101
Template newTemplate(const QString &content, const QString &name) const
Create a new Template with the content content identified by name.
Definition engine.cpp:332
bool smartTrimEnabled() const
Returns whether the smart trim feature is enabled for newly loaded templates.
Definition engine.cpp:347
void addTemplateLoader(QSharedPointer< AbstractTemplateLoader > loader)
Adds loader to the TemplateLoaders currently configured on the Engine.
Definition engine.cpp:55
void removePluginPath(const QString &dir)
Removes all instances of dir from the list of plugin dirs.
Definition engine.cpp:89
void addDefaultLibrary(const QString &libName)
Adds the library named libName to the libraries available by default to new Templates.
Definition engine.cpp:107
An exception for use when implementing template tags.
Definition exception.h:74
The TagLibraryInterface returns available tags and filters from libraries.
The Template class is a tree of nodes which may be rendered.
Definition template.h:85
KIOCORE_EXPORT QStringList list(const QString &fileClass)
const QList< QKeySequence > & end()
QString name(StandardShortcut id)
The KTextTemplate namespace holds all public KTextTemplate API.
Definition Mainpage.dox:8
QStringList libraryPaths()
T & first()
bool isEmpty() const const
const_iterator constBegin() const const
QString fromLocal8Bit(QByteArrayView str)
bool isEmpty() const const
Q_D(Todo)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:19:42 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.