PluginManager Class

(ExtensionSystem::PluginManager)

The PluginManager class implements the core plugin system that manages the plugins, their life cycle, and their registered objects. More...

Header: #include <PluginManager>

Public Functions

Static Public Members

void addObject(QObject *obj)
QList<QObject *> allObjects()
T *getObject()
T *getObject(Predicate predicate)
QObject *getObjectByClassName(const QString &className)
QObject *getObjectByName(const QString &name)
QList<T *> getObjects()
QList<T *> getObjects(Predicate predicate)
PluginManager *instance()
QReadWriteLock *listLock()
void loadPlugins()
QList<PluginSpec *> loadQueue()
QString pluginIID()
QStringList pluginPaths()
const QList<PluginSpec *> plugins()
void removeObject(QObject *obj)
void setPluginIID(const QString &iid)
void setPluginPaths(const QStringList &paths)

Detailed Description

The PluginManager class implements the core plugin system that manages the plugins, their life cycle, and their registered objects.

The plugin manager is used for the following tasks:

  • Manage plugins and their state
  • Manipulate a 'common object pool'

Plugins

Plugins consist of an XML descriptor file, and of a library that contains a Qt plugin that must derive from the IPlugin class and has an IID of "org.qt-project.Qt.QtCreatorPlugin". The plugin manager is used to set a list of file system directories to search for plugins, retrieve information about the state of these plugins, and to load them.

Usually, the application creates a PluginManager instance and initiates the loading.


  // 'plugins' and subdirs will be searched for plugins
  PluginManager::setPluginPaths(QStringList("plugins"));
  PluginManager::loadPlugins(); // try to load all the plugins

Additionally, it is possible to directly access the plugin specifications (the information in the descriptor file), the plugin instances (via PluginSpec), and their state.

Object Pool

Plugins (and everybody else) can add objects to a common 'pool' that is located in the plugin manager. Objects in the pool must derive from QObject, there are no other prerequisites. All objects of a specified type can be retrieved from the object pool via the getObjects() and getObject() functions.

Whenever the state of the object pool changes a corresponding signal is emitted by the plugin manager.

A common usecase for the object pool is that a plugin (or the application) provides an "extension point" for other plugins, which is a class / interface that can be implemented and added to the object pool. The plugin that provides the extension point looks for implementations of the class / interface in the object pool.


  // Plugin A provides a "MimeTypeHandler" extension point
  // in plugin B:
  MyMimeTypeHandler *handler = new MyMimeTypeHandler();
  PluginManager::instance()->addObject(handler);
  // In plugin A:
  QList<MimeTypeHandler *> mimeHandlers =
      PluginManager::getObjects<MimeTypeHandler>();

The ExtensionSystem::Invoker class template provides "syntactic sugar" for using "soft" extension points that may or may not be provided by an object in the pool. This approach does neither require the "user" plugin being linked against the "provider" plugin nor a common shared header file. The exposed interface is implicitly given by the invokable functions of the "provider" object in the object pool.

The ExtensionSystem::invoke function template encapsulates {ExtensionSystem::Invoker} construction for the common case where the success of the call is not checked.


  // In the "provide" plugin A:
  namespace PluginA {
  class SomeProvider : public QObject
  {
      Q_OBJECT

  public:
      Q_INVOKABLE QString doit(const QString &msg, int n) {
      {
          qDebug() << "I AM DOING IT " << msg;
          return QString::number(n);
      }
  };
  } // namespace PluginA


  // In the "user" plugin B:
  int someFuntionUsingPluginA()
  {
      using namespace ExtensionSystem;

      QObject *target = PluginManager::getObjectByClassName("PluginA::SomeProvider");

      if (target) {
          // Some random argument.
          QString msg = "REALLY.";

          // Plain function call, no return value.
          invoke<void>(target, "doit", msg, 2);

          // Plain function with no return value.
          qDebug() << "Result: " << invoke<QString>(target, "doit", msg, 21);

          // Record success of function call with return value.
          Invoker<QString> in1(target, "doit", msg, 21);
          qDebug() << "Success: (expected)" << in1.wasSuccessful();

          // Try to invoke a non-existing function.
          Invoker<QString> in2(target, "doitWrong", msg, 22);
          qDebug() << "Success (not expected):" << in2.wasSuccessful();

      } else {

          // We have to cope with plugin A's absence.
      }
  };

Note: The type of the parameters passed to the invoke() calls is deduced from the parameters themselves and must match the type of the arguments of the called functions exactly. No conversion or even integer promotions are applicable, so to invoke a function with a long parameter explicitly use long(43) or such.

Note: The object pool manipulating functions are thread-safe.

Member Function Documentation

PluginManager::PluginManager()

Creates a plugin manager. Should be done only once per application.

[static] void PluginManager::addObject(QObject *obj)

Adds the object obj to the object pool, so it can be retrieved again from the pool by type.

The plugin manager does not do any memory management - added objects must be removed from the pool and deleted manually by whoever is responsible for the object.

Emits the objectAdded() signal.

See also PluginManager::removeObject(), PluginManager::getObject(), and PluginManager::getObjects().

[static] QList<QObject *> PluginManager::allObjects()

Retrieves the list of all objects in the pool, unfiltered.

Usually, clients do not need to call this function.

See also PluginManager::getObject() and PluginManager::getObjects().

[static] T *PluginManager::getObject()

Retrieves the object of a given type from the object pool.

This function uses qobject_cast to determine the type of an object. If there are more than one object of the given type in the object pool, this function will arbitrarily choose one of them.

See also addObject().

[static] T *PluginManager::getObject(Predicate predicate)

Retrieves the object of a given type from the object pool that matches the predicate.

This function uses qobject_cast to determine the type of an object. The predicate must be a function taking T * and returning a bool. If there is more than one object matching the type and predicate, this function will arbitrarily choose one of them.

See also addObject().

[static] QObject *PluginManager::getObjectByClassName(const QString &className)

Retrieves one object inheriting a class with className from the object pool.

See also addObject().

[static] QObject *PluginManager::getObjectByName(const QString &name)

Retrieves one object with name from the object pool.

See also addObject().

[static] QList<T *> PluginManager::getObjects()

Retrieves all objects of a given type from the object pool.

This function uses qobject_cast to determine the type of an object.

See also addObject().

[static] QList<T *> PluginManager::getObjects(Predicate predicate)

Retrieves all objects of a given type from the object pool that match the predicate.

This function uses qobject_cast to determine the type of an object. The predicate should be a unary function taking a T* parameter and returning a bool.

See also addObject().

[static] PluginManager *PluginManager::instance()

Gets the unique plugin manager instance.

[static] QReadWriteLock *PluginManager::listLock()

[static] void PluginManager::loadPlugins()

Tries to load all the plugins that were previously found when setting the plugin search paths. The plugin specs of the plugins can be used to retrieve error and state information about individual plugins.

See also setPluginPaths() and plugins().

[static] QList<PluginSpec *> PluginManager::loadQueue()

Returns a list of plugins in load order.

[static] QString PluginManager::pluginIID()

The IID that valid plugins must have.

See also setPluginIID().

[static] QStringList PluginManager::pluginPaths()

The list of paths were the plugin manager searches for plugins.

See also setPluginPaths().

[static] const QList<PluginSpec *> PluginManager::plugins()

List of all plugin specifications that have been found in the plugin search paths. This list is valid directly after the setPluginPaths() call. The plugin specifications contain the information from the plugins' xml description files and the current state of the plugins. If a plugin's library has been already successfully loaded, the plugin specification has a reference to the created plugin instance as well.

See also setPluginPaths().

[static] void PluginManager::removeObject(QObject *obj)

Emits aboutToRemoveObject() and removes the object obj from the object pool.

See also PluginManager::addObject().

[static] void PluginManager::setPluginIID(const QString &iid)

Sets the IID that valid plugins must have. Only plugins with this IID are loaded, others are silently ignored.

At the moment this must be called before setPluginPaths() is called. // ### TODO let this + setPluginPaths read the plugin meta data lazyly whenever loadPlugins() or plugins() is called.

See also pluginIID().

[static] void PluginManager::setPluginPaths(const QStringList &paths)

Sets the plugin search paths, i.e. the file system paths where the plugin manager looks for plugin descriptions. All given paths and their sub directory trees are searched for plugin xml description files.

See also pluginPaths() and loadPlugins().