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