00d9f211f5
These job plugins work similarly to view modules, with the following differences: * These jobs need to link only libcalamares, not libcalamaresui. For this reason, PluginFactory was moved from libcalamaresui to libcalamares. (It depends only on QtCore.) * Instead of deriving from ViewModule, derive from CppJob (which is a subclass of Job). * Like process and Python jobs, a job plugin is a single job, whereas a ViewModule can generate a whole list of jobs. The CppJob and CppJobModule classes are new. In Module::fromDescriptor, the combination type=job, intf=qtplugin is now supported and mapped to CppJobModule.
124 lines
4.3 KiB
C++
124 lines
4.3 KiB
C++
/* === This file is part of Calamares - <http://github.com/calamares> ===
|
|
*
|
|
* Copyright 2015, Teo Mrnjavac <teo@kde.org>
|
|
*
|
|
* Based on KPluginFactory from KCoreAddons, KDE project
|
|
* Copyright 2007, Matthias Kretz <kretz@kde.org>
|
|
* Copyright 2007, Bernhard Loos <nhuh.put@web.de>
|
|
*
|
|
* Calamares is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Calamares is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "PluginFactory.h"
|
|
#include "PluginFactory_p.h"
|
|
|
|
#include <QObjectCleanupHandler>
|
|
#include <QDebug>
|
|
|
|
Q_GLOBAL_STATIC(QObjectCleanupHandler, factorycleanup)
|
|
|
|
extern int kLibraryDebugArea();
|
|
|
|
namespace Calamares
|
|
{
|
|
|
|
PluginFactory::PluginFactory()
|
|
: d_ptr(new PluginFactoryPrivate)
|
|
{
|
|
Q_D(PluginFactory);
|
|
d->q_ptr = this;
|
|
|
|
factorycleanup()->add(this);
|
|
}
|
|
|
|
PluginFactory::PluginFactory(PluginFactoryPrivate &d)
|
|
: d_ptr(&d)
|
|
{
|
|
factorycleanup()->add(this);
|
|
}
|
|
|
|
PluginFactory::~PluginFactory()
|
|
{
|
|
delete d_ptr;
|
|
}
|
|
|
|
void PluginFactory::doRegisterPlugin(const QString &keyword, const QMetaObject *metaObject, CreateInstanceFunction instanceFunction)
|
|
{
|
|
Q_D(PluginFactory);
|
|
|
|
Q_ASSERT(metaObject);
|
|
|
|
// we allow different interfaces to be registered without keyword
|
|
if (!keyword.isEmpty()) {
|
|
if (d->createInstanceHash.contains(keyword)) {
|
|
qWarning() << "A plugin with the keyword" << keyword << "was already registered. A keyword must be unique!";
|
|
}
|
|
d->createInstanceHash.insert(keyword, PluginFactoryPrivate::Plugin(metaObject, instanceFunction));
|
|
} else {
|
|
const QList<PluginFactoryPrivate::Plugin> clashes(d->createInstanceHash.values(keyword));
|
|
const QMetaObject *superClass = metaObject->superClass();
|
|
if (superClass) {
|
|
for (const PluginFactoryPrivate::Plugin &plugin : clashes) {
|
|
for (const QMetaObject *otherSuper = plugin.first->superClass(); otherSuper;
|
|
otherSuper = otherSuper->superClass()) {
|
|
if (superClass == otherSuper) {
|
|
qWarning() << "Two plugins with the same interface(" << superClass->className() << ") were registered. Use keywords to identify the plugins.";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (const PluginFactoryPrivate::Plugin &plugin : clashes) {
|
|
superClass = plugin.first->superClass();
|
|
if (superClass) {
|
|
for (const QMetaObject *otherSuper = metaObject->superClass(); otherSuper;
|
|
otherSuper = otherSuper->superClass()) {
|
|
if (superClass == otherSuper) {
|
|
qWarning() << "Two plugins with the same interface(" << superClass->className() << ") were registered. Use keywords to identify the plugins.";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
d->createInstanceHash.insertMulti(keyword, PluginFactoryPrivate::Plugin(metaObject, instanceFunction));
|
|
}
|
|
}
|
|
|
|
QObject *PluginFactory::create(const char *iface, QWidget *parentWidget, QObject *parent, const QString &keyword)
|
|
{
|
|
Q_D(PluginFactory);
|
|
|
|
QObject *obj = 0;
|
|
|
|
const QList<PluginFactoryPrivate::Plugin> candidates(d->createInstanceHash.values(keyword));
|
|
// for !keyword.isEmpty() candidates.count() is 0 or 1
|
|
|
|
for (const PluginFactoryPrivate::Plugin &plugin : candidates) {
|
|
for (const QMetaObject *current = plugin.first; current; current = current->superClass()) {
|
|
if (0 == qstrcmp(iface, current->className())) {
|
|
if (obj) {
|
|
qWarning() << "ambiguous interface requested from a DSO containing more than one plugin";
|
|
}
|
|
obj = plugin.second(parentWidget, parent);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (obj) {
|
|
emit objectCreated(obj);
|
|
}
|
|
return obj;
|
|
}
|
|
|
|
}
|