23 #include <QCoreApplication>
26 #include <QPluginLoader>
29 #include <QStandardPaths>
40 const QJsonObject metaObject = loader->metaData();
42 if (metaObject.isEmpty()) {
43 const QString fileName = QFileInfo(loader->fileName()).fileName();
47 "\t%1 does not supply meta data in the "
48 "Q_PLUGIN_METADATA (see one of the example plugins).")
54 return metaObject[
"IID"].toString();
60 const QJsonObject metaObject = loader->metaData();
62 const QString fileName = QFileInfo(loader->fileName()).fileName();
64 if (metaObject.isEmpty() || metaObject[
"MetaData"].toObject().isEmpty()) {
67 "%1 does not supply meta data in the Q_PLUGIN_METADATA "
68 "(see one of the example plugins).")
73 const QJsonObject
data = metaObject[
"MetaData"].toObject();
76 const QStringList validTypes{
"I/O",
"Standard"};
78 const QString pluginType =
data[
"type"].toString();
80 if (!validTypes.contains(pluginType)) {
83 "%1 does not supply a valid plugin type in its "
84 "info.json.\n\nFound: %2\n\nIt must be one of: %3")
85 .arg(fileName, pluginType, validTypes.join(
", ")));
99 m_pluginPaths = paths;
105 m_pluginList.clear();
107 if (m_pluginPaths.empty()) {
108 qWarning() <<
"There are no plugin paths set. Maybe missing a call to "
109 "ccPluginManager::setPaths()?";
113 const QObjectList pluginInstances = QPluginLoader::staticInstances();
115 for (QObject *plugin : pluginInstances) {
118 if (ccPlugin ==
nullptr) {
123 tr(
"[Plugin] Found: %1 (STATIC)").arg(ccPlugin->
getName()));
124 m_pluginList.push_back(ccPlugin);
128 loadFromPathsAndAddToList();
133 const QStringList disabledList = disabledPluginIIDs();
137 if (plugin ==
nullptr) {
144 if (!
ecvApp->isCommandLine() && disabledList.contains(plugin->IID())) {
145 CVLog::Print(tr(
"[Plugin][%1] Disabled").arg(plugin->getName()));
150 switch (plugin->getType()) {
162 ->addFactory(factory);
171 QStringList ioExtensions;
177 ioExtensions += filter->getDefaultExtension().toUpper();
181 if (!ioExtensions.empty()) {
187 ioExtensions.join(
' ')));
201 if (m_pluginList.empty()) {
202 qWarning() <<
"Plugin list is empty - did you call loadPlugins()?";
211 QStringList list = disabledPluginIIDs();
213 const QString &iid = plugin->
IID();
218 if (!list.contains(iid)) {
225 settings.beginGroup(
"Plugins");
227 settings.setValue(
"Disabled", list);
231 const QString &iid = plugin->
IID();
233 return !disabledPluginIIDs().contains(iid);
236 void ccPluginManager::loadFromPathsAndAddToList() {
237 const QStringList nameFilters{
238 #if defined(Q_OS_MAC)
240 #elif defined(Q_OS_WIN)
242 #elif defined(Q_OS_LINUX)
245 #error Need to specify the dynamic library extension for this OS.
251 QMap<QString, QPluginLoader *> pluginIIDToLoaderMap;
254 for (
const QString &
path : paths) {
257 QDir pluginsDir(
path);
259 pluginsDir.setNameFilters(nameFilters);
261 const QStringList fileNames = pluginsDir.entryList();
263 for (
const QString &fileName : fileNames) {
264 const QString pluginPath = pluginsDir.absoluteFilePath(fileName);
266 QPluginLoader *loader =
new QPluginLoader(pluginPath);
272 if (!metaDataValid || pluginIID.isNull()) {
274 tr(
"\t%1 has invalid meta data\t").arg(fileName));
281 QObject *plugin = loader->instance();
283 qobject_cast<ccPluginInterface *>(plugin);
285 if ((plugin ==
nullptr) || (ccPlugin ==
nullptr)) {
286 if (plugin ==
nullptr) {
288 tr(
"\t%1 does not seem to be a valid plugin\t(%2)")
289 .arg(fileName, loader->errorString()));
292 "or it is not supported by this version")
303 if (ccPlugin->
getName().isEmpty()) {
304 CVLog::Error(tr(
"\tPlugin %1 has a blank name").arg(fileName));
313 ccPlugin->
setIID(pluginIID);
315 QPluginLoader *previousLoader =
316 pluginIIDToLoaderMap.value(pluginIID);
320 if (previousLoader !=
nullptr) {
322 qobject_cast<ccPluginInterface *>(
323 previousLoader->instance());
326 const int index = m_pluginList.indexOf(pluginInterface);
327 m_pluginList.replace(index, ccPlugin);
329 previousLoader->unload();
331 delete previousLoader;
335 m_pluginList.push_back(ccPlugin);
338 pluginIIDToLoaderMap[pluginIID] = loader;
341 .arg(ccPlugin->
getName(), fileName));
345 const auto loaders = pluginIIDToLoaderMap.values();
347 for (QPluginLoader *loader : loaders) {
352 QStringList ccPluginManager::disabledPluginIIDs()
const {
355 settings.beginGroup(
"Plugins");
357 return settings.value(
"Disabled").toStringList();
static bool Warning(const char *format,...)
Prints out a formatted warning message in console.
static bool Print(const char *format,...)
Prints out a formatted message in console.
static bool Error(const char *format,...)
Display an error dialog with formatted message.
static void Register(Shared filter)
Registers a new filter.
virtual QString getName() const override
Returns (short) name (for menu entry, etc.)
static Container::Shared GetUniqueInstance()
I/O filter plugin interface.
virtual FilterList getFilters()
Returns a list of I/O filter instances.
Standard ECV plugin interface.
virtual const QString & IID() const =0
Get the IID of the plugin.
virtual ccExternalFactory * getCustomObjectsFactory() const
Returns the plugin's custom object factory (if any)
virtual QString getName() const =0
Returns (short) name (for menu entry, etc.)
virtual void setIID(const QString &iid)=0
ccPluginManager(QObject *parent=nullptr)
static ccPluginManager & get()
void setPaths(const QStringList &paths)
bool isEnabled(const ccPluginInterface *plugin) const
QStringList pluginPaths()
ccPluginInterfaceList & pluginList()
void setPluginEnabled(const ccPluginInterface *plugin, bool enabled)
Standard ECV plugin interface.
#define ecvApp
Mimic Qt's qApp for easy access to the application instance.
static QString sPluginIID(QPluginLoader *loader)
static bool sMetaDataValid(QPluginLoader *loader)
Q_GLOBAL_STATIC(PrivatePluginManager, sPluginManager)
QVector< ccPluginInterface * > ccPluginInterfaceList
Simply a list of.
static const std::string path