1 /*
2   pluginmanager.h
3 
4   This file is part of GammaRay, the Qt application inspection and
5   manipulation tool.
6 
7   Copyright (C) 2010-2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
8   Author: Kevin Funk <kevin.funk@kdab.com>
9 
10   Licensees holding valid commercial KDAB GammaRay licenses may use this file in
11   accordance with GammaRay Commercial License Agreement provided with the Software.
12 
13   Contact info@kdab.com if any conditions of this licensing are not clear to you.
14 
15   This program is free software; you can redistribute it and/or modify
16   it under the terms of the GNU General Public License as published by
17   the Free Software Foundation, either version 2 of the License, or
18   (at your option) any later version.
19 
20   This program is distributed in the hope that it will be useful,
21   but WITHOUT ANY WARRANTY; without even the implied warranty of
22   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23   GNU General Public License for more details.
24 
25   You should have received a copy of the GNU General Public License
26   along with this program.  If not, see <http://www.gnu.org/licenses/>.
27 */
28 
29 #ifndef GAMMARAY_PLUGINMANAGER_H
30 #define GAMMARAY_PLUGINMANAGER_H
31 
32 #include "plugininfo.h"
33 
34 #include <QCoreApplication>
35 #include <QVector>
36 #include <QList>
37 #include <QFileInfo>
38 #include <QStringList>
39 
40 #include <iostream>
41 
42 namespace GammaRay {
43 class PluginLoadError;
44 
45 typedef QList<PluginLoadError> PluginLoadErrors;
46 
47 class PluginLoadError
48 {
49 public:
PluginLoadError(const QString & _pluginFile,const QString & _errorString)50     PluginLoadError(const QString &_pluginFile, const QString &_errorString)
51         : pluginFile(_pluginFile)
52         , errorString(_errorString)
53     {
54     }
55 
pluginName()56     QString pluginName() const
57     {
58         return QFileInfo(pluginFile).baseName();
59     }
60 
61 public:
62     QString pluginFile;
63     QString errorString;
64 };
65 
66 class PluginManagerBase
67 {
68 public:
69     /**
70      * @param parent This is the parent object for all objects created by the plugins
71      */
72     explicit PluginManagerBase(QObject *parent = nullptr);
73     virtual ~PluginManagerBase();
74 
errors()75     QList<PluginLoadError> errors() const
76     {
77         return m_errors;
78     }
79 
80 protected:
81     virtual bool createProxyFactory(const PluginInfo &pluginInfo, QObject *parent) = 0;
82 
83     void scan(const QString &serviceType);
84     QStringList pluginPaths() const;
85     QStringList pluginFilter() const;
86 
87     QList<PluginLoadError> m_errors;
88     QObject *m_parent;
89 private:
90     Q_DISABLE_COPY(PluginManagerBase)
91 };
92 
93 template<typename IFace, typename Proxy>
94 class PluginManager : public PluginManagerBase
95 {
96 public:
97     explicit inline PluginManager(QObject *parent = nullptr)
PluginManagerBase(parent)98         : PluginManagerBase(parent)
99     {
100         const QString iid = QString::fromLatin1(qobject_interface_iid<IFace *>());
101         Q_ASSERT(!iid.isEmpty());
102         const QString serviceType = iid.split(QLatin1Char('/')).first();
103         scan(serviceType);
104     }
105 
~PluginManager()106     inline ~PluginManager() {}
107 
plugins()108     inline QVector<IFace *> plugins()
109     {
110         return m_plugins;
111     }
112 
113 protected:
createProxyFactory(const PluginInfo & pluginInfo,QObject * parent)114     bool createProxyFactory(const PluginInfo &pluginInfo, QObject *parent) override
115     {
116         auto *proxy = new Proxy(pluginInfo, parent);
117         if (!proxy->isValid()) {
118             m_errors << PluginLoadError(pluginInfo.path(), qApp->translate("GammaRay::PluginManager",
119                                             "Failed to load plugin: %1").arg(proxy->errorString()));
120             std::cerr << "invalid plugin " << qPrintable(pluginInfo.path()) << std::endl;
121             delete proxy;
122         } else {
123             m_plugins.push_back(proxy);
124             return true;
125         }
126         return false;
127     }
128 
129 private:
130     QVector<IFace *> m_plugins;
131 };
132 }
133 
134 #endif // GAMMARAY_PLUGINMANAGER_H
135