[frameworks/ktexttemplate] src: Turn scriptable tag support in a plugin, as originally intended

Volker Krause <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit d6ad59eda8552249ad8a9fe2969edde7ab18f186 by Volker Krause.
Committed on 20/07/2026 at 05:50.
Pushed by vkrause into branch 'master'.

Turn scriptable tag support in a plugin, as originally intended

This removes a long obsolete workaround for Webkit/JSC. Nowadays this uses
the QML script engine though, which has no problem being loaded via a
plugin.

M  +4    -0    src/CMakeLists.txt
M  +0    -24   src/lib/CMakeLists.txt
M  +24   -55   src/lib/engine.cpp
M  +0    -7    src/lib/engine_p.h
M  +4    -2    src/lib/pluginpointer_p.h
A  +27   -0    src/scriptabletags/CMakeLists.txt

https://invent.kde.org/frameworks/ktexttemplate/-/commit/d6ad59eda8552249ad8a9fe2969edde7ab18f186

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 32febec4..8eae8085 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -8,3 +8,7 @@ add_subdirectory(defaultfilters)
 
 add_subdirectory(i18n)
 
+if(Qt6Qml_FOUND)
+    add_subdirectory(scriptabletags)
+endif()
+
diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt
index 3c9130b4..12e3ee4f 100644
--- a/src/lib/CMakeLists.txt
+++ b/src/lib/CMakeLists.txt
@@ -116,30 +116,6 @@ ecm_generate_headers(KTextTemplate_CamelCase_HEADERS
     REQUIRED_HEADERS KTextTemplate_HEADERS
 )
 
-if (Qt6Qml_FOUND)
-  set(scriptabletags_FILES
-    scriptablecontext.cpp
-    scriptablefilterexpression.cpp
-    scriptablenode.cpp
-    scriptableparser.cpp
-    scriptablesafestring.cpp
-    scriptabletags.cpp
-    scriptabletemplate.cpp
-    scriptablevariable.cpp
-    scriptablefilter.cpp
-    )
-
-  foreach(file ${scriptabletags_FILES})
-    list(APPEND scriptabletags_SRCS ${CMAKE_SOURCE_DIR}/src/scriptabletags/${file})
-  endforeach()
-
-  target_sources(KF6TextTemplate PRIVATE ${scriptabletags_SRCS})
-  target_include_directories(KF6TextTemplate PRIVATE ../scriptabletags)
-  target_link_libraries(KF6TextTemplate
-    PRIVATE Qt6::Qml
-  )
-endif()
-
 if (BUILD_TESTING)
   set(KTEXTTEMPLATE_TESTS_EXPORT "KTEXTTEMPLATE_EXPORT")
 endif()
diff --git a/src/lib/engine.cpp b/src/lib/engine.cpp
index b3bbbfa3..b010e020 100644
--- a/src/lib/engine.cpp
+++ b/src/lib/engine.cpp
@@ -12,9 +12,6 @@
 
 #include "exception.h"
 #include "ktexttemplate_config_p.h"
-#ifdef QT_QML_LIB
-#include "scriptabletags.h"
-#endif
 #include "template_p.h"
 
 #include <QCoreApplication>
@@ -22,9 +19,10 @@
 #include <QPluginLoader>
 #include <QTextStream>
 
+using namespace Qt::Literals;
 using namespace KTextTemplate;
 
-static const char s_scriptableLibName[] = "ktexttemplate_scriptabletags";
+inline constexpr const auto s_scriptableLibName = "ktexttemplate_scriptabletags"_L1;
 
 Engine::Engine(QObject *parent)
     : QObject(parent)
@@ -39,9 +37,7 @@ Engine::Engine(QObject *parent)
 
 Engine::~Engine()
 {
-#ifdef QT_QML_LIB
     qDeleteAll(d_ptr->m_scriptableLibraries);
-#endif
     d_ptr->m_libraries.clear();
     delete d_ptr;
 }
@@ -120,33 +116,25 @@ void Engine::loadDefaultLibraries()
 {
     Q_D(Engine);
 
-#ifdef QT_QML_LIB
     // Make sure we can load default scriptable libraries if we're supposed to.
-    if (d->m_defaultLibraries.contains(QLatin1String(s_scriptableLibName)) && !d->m_scriptableTagLibrary) {
-        d->m_scriptableTagLibrary = new ScriptableTagLibrary(this);
-
-// It would be better to load this as a plugin, but that is not currently
-// possible with webkit/javascriptcore
-// so we new the library directly.
-// https://bugs.webkit.org/show_bug.cgi?id=38193
-#if 0
-    d->loadCppLibrary( s_scriptableLibName );
-    PluginPointer<TagLibraryInterface> library = d->loadCppLibrary( s_scriptableLibName );
-    if ( !library )
-      throw KTextTemplate::Exception( TagSyntaxError, QStringLiteral("Could not load scriptable tags library") );
-#endif
+    if (d->m_defaultLibraries.contains(s_scriptableLibName)) {
+        d->loadCppLibrary(s_scriptableLibName);
+        PluginPointer<TagLibraryInterface> library = d->loadCppLibrary(s_scriptableLibName);
+        if (!library) {
+            throw KTextTemplate::Exception(TagSyntaxError, QStringLiteral("Could not load scriptable tags library"));
+        }
     }
-#endif
 
     for (const QString &libName : std::as_const(d->m_defaultLibraries)) {
-        if (libName == QLatin1String(s_scriptableLibName))
+        if (libName == s_scriptableLibName) {
             continue;
+        }
 
         // already loaded by the engine.
-        if (d->m_libraries.contains(libName))
+        if (d->m_libraries.contains(libName)) {
             continue;
+        }
 
-#ifdef QT_QML_LIB
         // Although we don't use scripted libaries here, we need to
         // recognize them being first in the search path and not load a
         // c++ plugin of the same name in that case.
@@ -155,7 +143,6 @@ void Engine::loadDefaultLibraries()
             scriptableLibrary->clear();
             break;
         }
-#endif
 
         auto library = d->loadCppLibrary(libName);
         if (library) {
@@ -168,11 +155,6 @@ TagLibraryInterface *Engine::loadLibrary(const QString &name)
 {
     Q_D(Engine);
 
-#ifdef QT_QML_LIB
-    if (name == QLatin1String(s_scriptableLibName))
-        return nullptr;
-#endif
-
     // already loaded by the engine.
     if (d->m_libraries.contains(name))
         return d->m_libraries.value(name).data();
@@ -187,22 +169,17 @@ TagLibraryInterface *Engine::loadLibrary(const QString &name)
 
 TagLibraryInterface *EnginePrivate::loadLibrary(const QString &name)
 {
-#ifdef QT_QML_LIB
     auto scriptableLibrary = loadScriptableLibrary(name);
-    if (scriptableLibrary)
+    if (scriptableLibrary) {
         return scriptableLibrary;
+    }
 
-// else this is not a scriptable library.
-#endif
-
+    // else this is not a scriptable library.
     return loadCppLibrary(name).data();
 }
 
 EnginePrivate::EnginePrivate(Engine *engine)
     : q_ptr(engine)
-#ifdef QT_QML_LIB
-    , m_scriptableTagLibrary(nullptr)
-#endif
     , m_smartTrimEnabled(false)
 {
 }
@@ -232,41 +209,33 @@ QString EnginePrivate::getScriptLibraryName(const QString &name) const
     return {};
 }
 
-#ifdef QT_QML_LIB
 ScriptableLibraryContainer *EnginePrivate::loadScriptableLibrary(const QString &name)
 {
-    if (!m_scriptableTagLibrary)
+    auto scriptableTagLibrary = m_libraries.value(s_scriptableLibName);
+    if (!scriptableTagLibrary) {
         return nullptr;
-
-#if 0
-  if ( !m_libraries.contains( s_scriptableLibName ) )
-    return 0;
-#endif
+    }
 
     const auto libFileName = getScriptLibraryName(name);
-
-    if (libFileName.isEmpty())
+    if (libFileName.isEmpty()) {
         return nullptr;
+    }
 
     const auto it = m_scriptableLibraries.constFind(libFileName);
     if (it != m_scriptableLibraries.constEnd()) {
         auto library = it.value();
-        library->setNodeFactories(m_scriptableTagLibrary->nodeFactories(libFileName));
-        library->setFilters(m_scriptableTagLibrary->filters(libFileName));
+        library->setNodeFactories(scriptableTagLibrary->nodeFactories(libFileName));
+        library->setFilters(scriptableTagLibrary->filters(libFileName));
         return library;
     }
-#if 0
-  PluginPointer<TagLibraryInterface> scriptableTagLibrary = m_libraries.value( s_scriptableLibName );
-#endif
 
-    const auto factories = m_scriptableTagLibrary->nodeFactories(libFileName);
-    const auto filters = m_scriptableTagLibrary->filters(libFileName);
+    const auto factories = scriptableTagLibrary->nodeFactories(libFileName);
+    const auto filters = scriptableTagLibrary->filters(libFileName);
 
     auto library = new ScriptableLibraryContainer(factories, filters);
     m_scriptableLibraries.insert(libFileName, library);
     return library;
 }
-#endif
 
 PluginPointer<TagLibraryInterface> EnginePrivate::loadCppLibrary(const QString &name)
 {
diff --git a/src/lib/engine_p.h b/src/lib/engine_p.h
index 532e2889..03b7cfc2 100644
--- a/src/lib/engine_p.h
+++ b/src/lib/engine_p.h
@@ -71,25 +71,18 @@ class EnginePrivate
 
     TagLibraryInterface *loadLibrary(const QString &name);
     QString getScriptLibraryName(const QString &name) const;
-#ifdef QT_QML_LIB
     ScriptableLibraryContainer *loadScriptableLibrary(const QString &name);
-#endif
     PluginPointer<TagLibraryInterface> loadCppLibrary(const QString &name);
 
     Q_DECLARE_PUBLIC(Engine)
     Engine *const q_ptr;
 
     QHash<QString, PluginPointer<TagLibraryInterface>> m_libraries;
-#ifdef QT_QML_LIB
     QHash<QString, ScriptableLibraryContainer *> m_scriptableLibraries;
-#endif
 
     QList<QSharedPointer<AbstractTemplateLoader>> m_loaders;
     QStringList m_pluginDirs;
     QStringList m_defaultLibraries;
-#ifdef QT_QML_LIB
-    ScriptableTagLibrary *m_scriptableTagLibrary;
-#endif
     bool m_smartTrimEnabled;
 };
 }
diff --git a/src/lib/pluginpointer_p.h b/src/lib/pluginpointer_p.h
index df620de7..0989e0cc 100644
--- a/src/lib/pluginpointer_p.h
+++ b/src/lib/pluginpointer_p.h
@@ -10,6 +10,7 @@
 #ifndef KTEXTTEMPLATE_PLUGINPOINTER_H
 #define KTEXTTEMPLATE_PLUGINPOINTER_H
 
+#include <QCoreApplication>
 #include <QPluginLoader>
 #include <QSharedPointer>
 
@@ -46,6 +47,7 @@ public:
         // that
         // causes segfaults if the plugin has been unloaded.
         m_object = m_pluginLoader->instance();
+        m_object->setParent(QCoreApplication::instance());
 
         m_plugin = qobject_cast<PluginType *>(m_object);
     }
@@ -65,9 +67,9 @@ public:
         return m_plugin;
     }
 
-    operator bool()
+    operator bool() const
     {
-        return m_plugin ? true : false;
+        return m_plugin;
     }
 
     PluginType *data() const
diff --git a/src/scriptabletags/CMakeLists.txt b/src/scriptabletags/CMakeLists.txt
new file mode 100644
index 00000000..e2138d8f
--- /dev/null
+++ b/src/scriptabletags/CMakeLists.txt
@@ -0,0 +1,27 @@
+# SPDX-FileCopyrightText: Volker Krause <[email protected]>
+# SPDX-License-Identifier: BSD-2-Clause
+
+add_library(ktexttemplate_scriptabletags MODULE
+    scriptablecontext.cpp
+    scriptablefilterexpression.cpp
+    scriptablenode.cpp
+    scriptableparser.cpp
+    scriptablesafestring.cpp
+    scriptabletags.cpp
+    scriptabletemplate.cpp
+    scriptablevariable.cpp
+    scriptablefilter.cpp
+)
+set_property(TARGET ktexttemplate_scriptabletags PROPERTY
+    EXPORT_NAME scriptabletags
+)
+target_link_libraries(ktexttemplate_scriptabletags PRIVATE
+    KF6::TextTemplate
+    Qt6::Qml
+)
+ktexttemplate_adjust_plugin_name(ktexttemplate_scriptabletags)
+
+install(TARGETS ktexttemplate_scriptabletags
+  EXPORT KF6TextTemplateTargets
+  DESTINATION ${KTextTemplate_INSTALL_PLUGINDIR}
+)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.