[libcalamares] Swap out own PluginLoader for KCoreAddons
This commit is contained in:
parent
44991e700b
commit
1711071c58
@ -44,7 +44,6 @@ set( libSources
|
||||
utils/CommandList.cpp
|
||||
utils/Dirs.cpp
|
||||
utils/Logger.cpp
|
||||
utils/PluginFactory.cpp
|
||||
utils/Retranslator.cpp
|
||||
utils/String.cpp
|
||||
utils/UMask.cpp
|
||||
@ -120,6 +119,7 @@ target_link_libraries( calamares
|
||||
LINK_PUBLIC
|
||||
${YAMLCPP_LIBRARY}
|
||||
Qt5::Core
|
||||
KF5::CoreAddons
|
||||
${OPTIONAL_PUBLIC_LIBRARIES}
|
||||
)
|
||||
|
||||
|
@ -1,127 +0,0 @@
|
||||
/* === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
*
|
||||
* Copyright 2015, Teo Mrnjavac <teo@kde.org>
|
||||
* Copyright 2017-2018, Adriaan de Groot <groot@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 <QDebug>
|
||||
#include <QObjectCleanupHandler>
|
||||
|
||||
// *INDENT-OFF*
|
||||
// clang-format off
|
||||
|
||||
Q_GLOBAL_STATIC( QObjectCleanupHandler, factorycleanup )
|
||||
|
||||
namespace Calamares
|
||||
{
|
||||
|
||||
PluginFactory::PluginFactory()
|
||||
: pd_ptr( new PluginFactoryPrivate )
|
||||
{
|
||||
pd_ptr->q_ptr = this;
|
||||
|
||||
factorycleanup()->add( this );
|
||||
}
|
||||
|
||||
PluginFactory::PluginFactory( PluginFactoryPrivate& d )
|
||||
: pd_ptr( &d )
|
||||
{
|
||||
factorycleanup()->add( this );
|
||||
}
|
||||
|
||||
PluginFactory::~PluginFactory()
|
||||
{
|
||||
delete pd_ptr;
|
||||
}
|
||||
|
||||
void PluginFactory::doRegisterPlugin( const QString& keyword, const QMetaObject* metaObject, CreateInstanceFunction instanceFunction )
|
||||
{
|
||||
Q_ASSERT( metaObject );
|
||||
|
||||
// we allow different interfaces to be registered without keyword
|
||||
if ( !keyword.isEmpty() )
|
||||
{
|
||||
if ( pd_ptr->createInstanceHash.contains( keyword ) )
|
||||
qWarning() << "A plugin with the keyword" << keyword << "was already registered. A keyword must be unique!";
|
||||
pd_ptr->createInstanceHash.insert( keyword, PluginFactoryPrivate::Plugin( metaObject, instanceFunction ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
const QList<PluginFactoryPrivate::Plugin> clashes( pd_ptr->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.";
|
||||
}
|
||||
}
|
||||
}
|
||||
pd_ptr->createInstanceHash.insertMulti( keyword, PluginFactoryPrivate::Plugin( metaObject, instanceFunction ) );
|
||||
}
|
||||
}
|
||||
|
||||
QObject* PluginFactory::create( const char* iface, QWidget* parentWidget, QObject* parent, const QString& keyword )
|
||||
{
|
||||
QObject* obj = nullptr;
|
||||
|
||||
const QList<PluginFactoryPrivate::Plugin> candidates( pd_ptr->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;
|
||||
}
|
||||
|
||||
}
|
@ -24,298 +24,15 @@
|
||||
#ifndef UTILS_PLUGINFACTORY_H
|
||||
#define UTILS_PLUGINFACTORY_H
|
||||
|
||||
#include "DllMacro.h"
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QVariant>
|
||||
|
||||
// *INDENT-OFF*
|
||||
// clang-format off
|
||||
|
||||
namespace Calamares
|
||||
{
|
||||
class PluginFactoryPrivate;
|
||||
}
|
||||
#include <KF5/KCoreAddons/KPluginFactory>
|
||||
|
||||
#define CalamaresPluginFactory_iid "io.calamares.PluginFactory"
|
||||
|
||||
/**
|
||||
* \relates PluginFactory
|
||||
*
|
||||
* CALAMARES_PLUGIN_FACTORY_DECLARATION declares the PluginFactory subclass. This macro
|
||||
* can be used in a header file.
|
||||
*
|
||||
* \param name The name of the PluginFactory derived class.
|
||||
*
|
||||
* \see CALAMARES_PLUGIN_FACTORY
|
||||
* \see CALAMARES_PLUGIN_FACTORY_DEFINITION
|
||||
*/
|
||||
#define CALAMARES_PLUGIN_FACTORY_DECLARATION(name) \
|
||||
class name : public Calamares::PluginFactory \
|
||||
{ \
|
||||
Q_OBJECT \
|
||||
Q_INTERFACES(Calamares::PluginFactory) \
|
||||
Q_PLUGIN_METADATA(IID CalamaresPluginFactory_iid) \
|
||||
public: \
|
||||
explicit name(); \
|
||||
~name(); \
|
||||
private: \
|
||||
void init(); \
|
||||
};
|
||||
|
||||
/**
|
||||
* \relates PluginFactory
|
||||
* CALAMARES_PLUGIN_FACTORY_DEFINITION defines the PluginFactory subclass. This macro
|
||||
* can <b>not</b> be used in a header file.
|
||||
*
|
||||
* \param name The name of the PluginFactory derived class.
|
||||
*
|
||||
* \param pluginRegistrations Code to be inserted into the constructor of the
|
||||
* class. Usually a series of registerPlugin() calls.
|
||||
*
|
||||
* \see CALAMARES_PLUGIN_FACTORY
|
||||
* \see CALAMARES_PLUGIN_FACTORY_DECLARATION
|
||||
*/
|
||||
K_PLUGIN_FACTORY_DECLARATION_WITH_BASEFACTORY_SKEL(name,KPluginFactory,Q_PLUGIN_METADATA(IID CalamaresPluginFactory_iid))
|
||||
#define CALAMARES_PLUGIN_FACTORY_DEFINITION(name, pluginRegistrations) \
|
||||
name::name() \
|
||||
{ \
|
||||
pluginRegistrations \
|
||||
} \
|
||||
name::~name() {}
|
||||
K_PLUGIN_FACTORY_DEFINITION(name, pluginRegistrations )
|
||||
|
||||
namespace Calamares
|
||||
{
|
||||
|
||||
/**
|
||||
* \class PluginFactory PluginFactory.h <PluginFactory.h>
|
||||
*
|
||||
* PluginFactory provides a convenient way to provide factory-style plugins.
|
||||
* Qt plugins provide a singleton object, but a common pattern is for plugins
|
||||
* to generate as many objects of a particular type as the application requires.
|
||||
* By using PluginFactory, you can avoid implementing the factory pattern
|
||||
* yourself.
|
||||
*
|
||||
* PluginFactory also allows plugins to provide multiple different object
|
||||
* types, indexed by keywords.
|
||||
*
|
||||
* The objects created by PluginFactory must inherit QObject, and must have a
|
||||
* standard constructor pattern:
|
||||
* \li if the object is a KPart::Part, it must be of the form
|
||||
* \code
|
||||
* T(QWidget *parentWidget, QObject *parent, const QVariantList &args)
|
||||
* \endcode
|
||||
* \li if it is a QWidget, it must be of the form
|
||||
* \code
|
||||
* T(QWidget *parent, const QVariantList &args)
|
||||
* \endcode
|
||||
* \li otherwise it must be of the form
|
||||
* \code
|
||||
* T(QObject *parent, const QVariantList &args)
|
||||
* \endcode
|
||||
*
|
||||
* You should typically use CALAMARES_PLUGIN_FACTORY_DEFINITION() in your plugin code to
|
||||
* create the factory. The pattern is
|
||||
*
|
||||
* \code
|
||||
* #include "utils/PluginFactory.h"
|
||||
*
|
||||
* class MyPlugin : public PluginInterface
|
||||
* {
|
||||
* public:
|
||||
* MyPlugin(QObject *parent, const QVariantList &args)
|
||||
* : PluginInterface(parent)
|
||||
* {}
|
||||
* };
|
||||
*
|
||||
* CALAMARES_PLUGIN_FACTORY_DEFINITION(MyPluginFactory,
|
||||
* registerPlugin<MyPlugin>();
|
||||
* )
|
||||
* \endcode
|
||||
*
|
||||
* If you want to load a library use KPluginLoader.
|
||||
* The application that wants to instantiate plugin classes can do the following:
|
||||
* \code
|
||||
* PluginFactory *factory = KPluginLoader("libraryname").factory();
|
||||
* if (factory) {
|
||||
* PluginInterface *p1 = factory->create<PluginInterface>(parent);
|
||||
* OtherInterface *p2 = factory->create<OtherInterface>(parent);
|
||||
* NextInterface *p3 = factory->create<NextInterface>("keyword1", parent);
|
||||
* NextInterface *p3 = factory->create<NextInterface>("keyword2", parent);
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* \author Matthias Kretz <kretz\@kde.org>
|
||||
* \author Bernhard Loos <nhuh.put\@web.de>
|
||||
*/
|
||||
class DLLEXPORT PluginFactory : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
friend class PluginFactoryPrivate;
|
||||
public:
|
||||
/**
|
||||
* This constructor creates a factory for a plugin.
|
||||
*/
|
||||
explicit PluginFactory();
|
||||
|
||||
/**
|
||||
* This destroys the PluginFactory.
|
||||
*/
|
||||
virtual ~PluginFactory();
|
||||
|
||||
/**
|
||||
* Use this method to create an object. It will try to create an object which inherits
|
||||
* \p T. If it has multiple choices, you will get a fatal error (kFatal()), so be careful
|
||||
* to request a unique interface or use keywords.
|
||||
*
|
||||
* \tparam T The interface for which an object should be created. The object will inherit \p T.
|
||||
* \param parent The parent of the object. If \p parent is a widget type, it will also passed
|
||||
* to the parentWidget argument of the CreateInstanceFunction for the object.
|
||||
* \returns A pointer to the created object is returned, or 0 if an error occurred.
|
||||
*/
|
||||
template<typename T>
|
||||
T* create( QObject* parent = nullptr );
|
||||
|
||||
/**
|
||||
* Use this method to create an object. It will try to create an object which inherits
|
||||
* \p T and was registered with \p keyword.
|
||||
*
|
||||
* \tparam T The interface for which an object should be created. The object will inherit \p T.
|
||||
* \param keyword The keyword of the object.
|
||||
* \param parent The parent of the object. If \p parent is a widget type, it will also passed
|
||||
* to the parentWidget argument of the CreateInstanceFunction for the object.
|
||||
* \returns A pointer to the created object is returned, or 0 if an error occurred.
|
||||
*/
|
||||
template<typename T>
|
||||
T* create( const QString& keyword, QObject* parent = nullptr );
|
||||
|
||||
Q_SIGNALS:
|
||||
void objectCreated( QObject* object );
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Function pointer type to a function that instantiates a plugin.
|
||||
*/
|
||||
typedef QObject* ( *CreateInstanceFunction )( QWidget*, QObject* );
|
||||
|
||||
/**
|
||||
* This is used to detect the arguments need for the constructor of plugin classes.
|
||||
* You can inherit it, if you want to add new classes and still keep support for the old ones.
|
||||
*/
|
||||
template<class impl>
|
||||
struct InheritanceChecker
|
||||
{
|
||||
CreateInstanceFunction createInstanceFunction( QWidget* )
|
||||
{
|
||||
return &createInstance<impl, QWidget>;
|
||||
}
|
||||
CreateInstanceFunction createInstanceFunction( ... )
|
||||
{
|
||||
return &createInstance<impl, QObject>;
|
||||
}
|
||||
};
|
||||
|
||||
explicit PluginFactory( PluginFactoryPrivate& dd );
|
||||
|
||||
/**
|
||||
* Registers a plugin with the factory. Call this function from the constructor of the
|
||||
* PluginFactory subclass to make the create function able to instantiate the plugin when asked
|
||||
* for an interface the plugin implements.
|
||||
*
|
||||
* \tparam T the name of the plugin class
|
||||
*
|
||||
* \param keyword An optional keyword as unique identifier for the plugin. This allows you to
|
||||
* put more than one plugin with the same interface into the same library using the same
|
||||
* factory. X-KDE-PluginKeyword is a convenient way to specify the keyword in a desktop file.
|
||||
*
|
||||
* \param instanceFunction A function pointer to a function that creates an instance of the
|
||||
* plugin. The default function that will be used depends on the type of interface. If the
|
||||
* interface inherits from
|
||||
* \li \c KParts::Part the function will call
|
||||
* \code
|
||||
* new T(QWidget *parentWidget, QObject *parent)
|
||||
* \endcode
|
||||
* \li \c QWidget the function will call
|
||||
* \code
|
||||
* new T(QWidget *parent)
|
||||
* \endcode
|
||||
* \li else the function will call
|
||||
* \code
|
||||
* new T(QObject *parent)
|
||||
* \endcode
|
||||
*/
|
||||
template<class T>
|
||||
void registerPlugin( const QString& keyword = QString(),
|
||||
CreateInstanceFunction instanceFunction
|
||||
= InheritanceChecker<T>().createInstanceFunction( reinterpret_cast<T*>( 0 ) ) )
|
||||
{
|
||||
doRegisterPlugin( keyword, &T::staticMetaObject, instanceFunction );
|
||||
}
|
||||
|
||||
PluginFactoryPrivate* const pd_ptr;
|
||||
|
||||
/**
|
||||
* This function is called when the factory asked to create an Object.
|
||||
*
|
||||
* You may reimplement it to provide a very flexible factory. This is especially useful to
|
||||
* provide generic factories for plugins implemeted using a scripting language.
|
||||
*
|
||||
* \param iface The staticMetaObject::className() string identifying the plugin interface that
|
||||
* was requested. E.g. for KCModule plugins this string will be "KCModule".
|
||||
* \param parentWidget Only used if the requested plugin is a KPart.
|
||||
* \param parent The parent object for the plugin object.
|
||||
* \param keyword A string that uniquely identifies the plugin. If a KService is used this
|
||||
* keyword is read from the X-KDE-PluginKeyword entry in the .desktop file.
|
||||
*/
|
||||
virtual QObject* create( const char* iface, QWidget* parentWidget, QObject* parent, const QString& keyword );
|
||||
|
||||
template<class impl, class ParentType>
|
||||
static QObject* createInstance( QWidget* parentWidget, QObject* parent )
|
||||
{
|
||||
Q_UNUSED( parentWidget )
|
||||
ParentType* p = nullptr;
|
||||
if ( parent )
|
||||
{
|
||||
p = qobject_cast<ParentType*>( parent );
|
||||
Q_ASSERT( p );
|
||||
}
|
||||
return new impl( p );
|
||||
}
|
||||
|
||||
private:
|
||||
void doRegisterPlugin( const QString& keyword, const QMetaObject* metaObject, CreateInstanceFunction instanceFunction );
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline T* PluginFactory::create( QObject* parent )
|
||||
{
|
||||
QObject* o = create( T::staticMetaObject.className(),
|
||||
parent && parent->isWidgetType() ? reinterpret_cast<QWidget*>( parent ) : nullptr,
|
||||
parent,
|
||||
QString() );
|
||||
|
||||
T* t = qobject_cast<T*>( o );
|
||||
if ( !t )
|
||||
delete o;
|
||||
return t;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T* PluginFactory::create( const QString& keyword, QObject* parent )
|
||||
{
|
||||
QObject* o = create( T::staticMetaObject.className(),
|
||||
parent && parent->isWidgetType() ? reinterpret_cast<QWidget*>( parent ) : nullptr,
|
||||
parent,
|
||||
keyword );
|
||||
|
||||
T* t = qobject_cast<T*>( o );
|
||||
if ( !t )
|
||||
delete o;
|
||||
return t;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Q_DECLARE_INTERFACE( Calamares::PluginFactory, CalamaresPluginFactory_iid )
|
||||
// Q_DECLARE_INTERFACE( Calamares::PluginFactory, CalamaresPluginFactory_iid )
|
||||
|
||||
#endif
|
||||
|
@ -1,55 +0,0 @@
|
||||
/* === This file is part of Calamares - <https://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/>.
|
||||
*/
|
||||
|
||||
#ifndef UTILS_PLUGINFACTORY_P_H
|
||||
#define UTILS_PLUGINFACTORY_P_H
|
||||
|
||||
#include "PluginFactory.h"
|
||||
|
||||
#include <QtCore/QHash>
|
||||
|
||||
namespace Calamares
|
||||
{
|
||||
|
||||
class PluginFactoryPrivate
|
||||
{
|
||||
Q_DECLARE_PUBLIC( PluginFactory )
|
||||
protected:
|
||||
typedef QPair< const QMetaObject*, PluginFactory::CreateInstanceFunction > Plugin;
|
||||
|
||||
PluginFactoryPrivate()
|
||||
: catalogInitialized( false )
|
||||
, q_ptr( nullptr )
|
||||
{
|
||||
}
|
||||
~PluginFactoryPrivate() {}
|
||||
|
||||
QHash< QString, Plugin > createInstanceHash;
|
||||
QString catalogName;
|
||||
bool catalogInitialized;
|
||||
|
||||
PluginFactory* q_ptr;
|
||||
};
|
||||
|
||||
} // namespace Calamares
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user