File indexing completed on 2024-12-22 04:40:14

0001 /*
0002     SPDX-FileCopyrightText: 2010-2022 Mladen Milinkovic <max@smoothware.net>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #ifndef PLUGINHELPER_H
0008 #define PLUGINHELPER_H
0009 
0010 #include "config.h"
0011 
0012 #include <QApplication>
0013 #include <QDebug>
0014 #include <QPluginLoader>
0015 #include <QDir>
0016 #include <QFile>
0017 #include <QVariant>
0018 #include <QStringList>
0019 
0020 namespace SubtitleComposer {
0021 template <class C, class T>
0022 class PluginHelper
0023 {
0024 public:
0025     PluginHelper(C *container) : m_cont(container) {}
0026 
0027     void loadAll(const QString &buildLocation);
0028 //  void unload(T *plugin);
0029     T * pluginLoad(const QString &filename);
0030     void pluginAdd(T *plugin);
0031 
0032 private:
0033     C *m_cont;
0034 };
0035 
0036 template <class C, class T> void
0037 PluginHelper<C, T>::loadAll(const QString &buildLocation)
0038 {
0039     const QDir appDir(qApp->applicationDirPath());
0040     const QDir buildPluginPath(appDir.absoluteFilePath(buildLocation));
0041     if(buildPluginPath.exists()) {
0042         // if application is launched from build directory it must load plugins from build directory
0043         const QStringList subdirs = buildPluginPath.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
0044         for(const QString &subdir: subdirs) {
0045             const QDir path(buildPluginPath.filePath(subdir));
0046             const QStringList libs = path.entryList(QDir::Files);
0047             for(const QString &lib: libs) {
0048                 if(QLibrary::isLibrary(lib))
0049                     pluginLoad(path.filePath(lib));
0050             }
0051         }
0052     } else {
0053         const QDir pluginsDir(appDir.absoluteFilePath(QDir(QStringLiteral(SC_INSTALL_BIN)).relativeFilePath(QStringLiteral(SC_INSTALL_PLUGIN))));
0054         foreach(const QString pluginFile, pluginsDir.entryList(QDir::Files, QDir::Name)) {
0055             if(QLibrary::isLibrary(pluginFile))
0056                 pluginLoad(pluginsDir.filePath(pluginFile));
0057         }
0058     }
0059 }
0060 
0061 template <class C, class T> T *
0062 PluginHelper<C, T>::pluginLoad(const QString &filename)
0063 {
0064     QPluginLoader *loader = new QPluginLoader(filename);
0065     QObject *pluginLib = loader->instance();
0066     Q_ASSERT(pluginLib->thread() == QApplication::instance()->thread());
0067     if(!pluginLib)
0068         return nullptr;
0069 
0070     // make sure library doesn't get unloaded and plugin gets destroyed from non-gui thread
0071     loader->setParent(QApplication::instance());
0072 
0073     pluginLib->setProperty("pluginPath", loader->fileName());
0074     T *plugin = qobject_cast<T *>(pluginLib);
0075     if(!plugin)
0076         return nullptr;
0077 
0078     const char *className = T::staticMetaObject.className();
0079     if(strlen(className) > 18 && className[17] == ':') className += 18;
0080     qInfo() << "Loaded" << className << plugin->name() << "from" << loader->fileName();
0081 
0082     pluginAdd(plugin);
0083 
0084     return plugin;
0085 }
0086 
0087 template <class C, class T> void
0088 PluginHelper<C, T>::pluginAdd(T *plugin)
0089 {
0090     // Plugin will be deleted with container
0091     plugin->setParent(m_cont);
0092     Q_ASSERT(plugin->thread() == QApplication::instance()->thread());
0093 
0094     if(m_cont->m_plugins.contains(plugin->name())) {
0095         qCritical() << "Attempted to insert duplicate SpeechProcessor plugin" << plugin->name();
0096         return;
0097     }
0098 
0099     m_cont->m_plugins[plugin->name()] = plugin;
0100 }
0101 
0102 //template <class C, class T> void
0103 //PluginHelper<C, T>::unload(T *plugin)
0104 //{
0105 //  const QString &filename = plugin->property("pluginPath").toString();
0106 //  qDebug() << "plugin" << plugin->staticMetaObject.className() << "unload" << plugin->name();
0107 //  if(filename.isEmpty()) {
0108 //      delete plugin;
0109 //      return;
0110 //  }
0111 //  QPluginLoader loader(filename);
0112 //  Q_ASSERT(loader.instance() == plugin);
0113 //  delete plugin;
0114 //  if(!loader.unload())
0115 //      qWarning() << "Failed unloading plugin" << filename << "-" << loader.errorString();
0116 //}
0117 
0118 } // namespace
0119 
0120 #endif // PLUGINHELPER_H