add template for plugin system

This commit is contained in:
Evgenii Alekseev 2017-03-09 04:07:01 +03:00
parent 01d5d99e16
commit d177aa81af
6 changed files with 369 additions and 0 deletions

View File

@ -84,6 +84,17 @@ const char LIB_INSTALL_DIR[] = "@LIB_INSTALL_DIR@";
* @brief the same as CMAKE_INSTALL_PREFIX
*/
const char ROOT_INSTALL_DIR[] = "@CMAKE_INSTALL_PREFIX@";
// application specific
/**
* @def HOME_PATH
* path to queued home directory
*/
const char HOME_PATH[] = "queued";
/**
* @def PLUGIN_PATH
* path to plugins inside @ref HOME_PATH
*/
const char PLUGIN_PATH[] = "plugins";
// internal configuration
/**

View File

@ -36,6 +36,9 @@
#include "QueuedEnums.h"
#include "QueuedExceptions.h"
#include "QueuedLimits.h"
#include "QueuedPluginInterface.h"
#include "QueuedPluginManager.h"
#include "QueuedPluginManagerInterface.h"
#include "QueuedProcess.h"
#include "QueuedProcessManager.h"
#include "QueuedReportManager.h"

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 2016 Evgeniy Alekseev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
*
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*/
/**
* @file QueuedPluginInterface.h
* Header of Queued library
* @author Evgeniy Alekseev
* @copyright MIT
* @bug https://github.com/arcan1s/queued/issues
*/
#ifndef QUEUEDPLUGININTERFACE_H
#define QUEUEDPLUGININTERFACE_H
#include <QtPlugin>
#include "QueuedConfig.h"
class QueuedPluginManagerInterface;
/**
* @brief plugin interface for queued
*/
class QueuedPluginInterface
{
public:
/**
* @brief QueuedPluginInterface class destructor
*/
virtual ~QueuedPluginInterface(){};
/**
* @brief will be emitted to map interface signals to plugin slots
* @param _manager
* pointer to manager interface object
*/
virtual void connect(const QueuedPluginManagerInterface *_manager) = 0;
/**
* @brief plugin initialization method
* @param _settings
* plugin settings structure from database
* @remark plugin settings will be stored as "plugin.name.Key"
*/
virtual void init(const QVariantHash &_settings) = 0;
};
Q_DECLARE_INTERFACE(QueuedPluginInterface, PLUGIN_INTERFACE_NAME)
#endif /* QUEUEDPLUGININTERFACE_H */

View File

@ -0,0 +1,97 @@
/*
* Copyright (c) 2016 Evgeniy Alekseev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
*
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*/
/**
* @file QueuedPluginManager.h
* Header of Queued library
* @author Evgeniy Alekseev
* @copyright MIT
* @bug https://github.com/arcan1s/queued/issues
*/
#ifndef QUEUEDPLUGINMANAGER_H
#define QUEUEDPLUGINMANAGER_H
#include <QHash>
#include <QObject>
class QueuedPluginInterface;
class QueuedPluginManagerInterface;
/**
* @brief report manager for queued
*/
class QueuedPluginManager : public QObject
{
Q_OBJECT
public:
/**
* @typedef QueuedPluginMap
* map of names to QueuedPluginInterface pointers
*/
typedef QHash<QString, QueuedPluginInterface *> QueuedPluginMap;
/**
* @brief QueuedPluginManager class constructor
* @param parent
* pointer to parent item
*/
explicit QueuedPluginManager(QObject *parent);
/**
* @brief QueuedPluginManager class destructor
*/
virtual ~QueuedPluginManager();
/**
* @brief plugin manager interface
* @return pointer to plugin manager interface
*/
QueuedPluginManagerInterface *interface();
/**
* @brief load plugin
* @param _name
* plugin name
* @param _settings
* plugin settings
* @return true on success load otherwise return false
*/
bool loadPlugin(const QString &_name, const QVariantHash &_settings);
/**
* @brief path to plugin location
* @return full path to plugin location
*/
QStringList pluginLocations() const;
/**
* @brief unload plugin
* @param _name
* plugin name
* @return true on success unload otherwise return false
*/
bool unloadPlugin(const QString &_name);
private:
/**
* @brief loaded plugins
*/
QueuedPluginMap m_plugins;
/**
* @brief pointer to database object
*/
QueuedPluginManagerInterface *m_interface = nullptr;
};
#endif /* QUEUEDPLUGINMANAGER_H */

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2016 Evgeniy Alekseev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
*
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*/
/**
* @file QueuedPluginManagerInterface.h
* Header of Queued library
* @author Evgeniy Alekseev
* @copyright MIT
* @bug https://github.com/arcan1s/queued/issues
*/
#ifndef QUEUEDPLUGINMANAGERINTERFACE_H
#define QUEUEDPLUGINMANAGERINTERFACE_H
#include <QObject>
/**
* @brief signal interface for plugin manager
*/
class QueuedPluginManagerInterface : public QObject
{
Q_OBJECT
public:
/**
* @brief QueuedPluginManagerInterface class constructor
* @param parent
* pointer to parent object
*/
explicit QueuedPluginManagerInterface(QObject *parent)
: QObject(parent){};
/**
* @brief QueuedPluginManagerInterface class destructor
*/
virtual ~QueuedPluginManagerInterface(){};
signals:
};
#endif /* QUEUEDPLUGINMANAGERINTERFACE_H */

View File

@ -0,0 +1,142 @@
/*
* Copyright (c) 2016 Evgeniy Alekseev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
*
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*/
/**
* @file QueuedPluginManager.cpp
* Source code of queued library
* @author Evgeniy Alekseev
* @copyright GPLv3
* @bug https://github.com/arcan1s/queued/issues
*/
#include "queued/Queued.h"
#include <QDir>
#include <QPluginLoader>
#include <QStandardPaths>
/**
* @class QueuedPluginManager
*/
/**
* @fn QueuedPluginManager
*/
QueuedPluginManager::QueuedPluginManager(QObject *parent)
: QObject(parent)
{
qCDebug(LOG_PL) << __PRETTY_FUNCTION__;
m_interface = new QueuedPluginManagerInterface(this);
}
/**
* @fn ~QueuedPluginManager
*/
QueuedPluginManager::~QueuedPluginManager()
{
qCDebug(LOG_PL) << __PRETTY_FUNCTION__;
QStringList plugins = m_plugins.keys();
for (auto &plugin : plugins)
unloadPlugin(plugin);
delete m_interface;
}
/**
* @fn interface
*/
QueuedPluginManagerInterface *QueuedPluginManager::interface()
{
return m_interface;
}
/**
* @fn loadPlugin
*/
bool QueuedPluginManager::loadPlugin(const QString &_name,
const QVariantHash &_settings)
{
qCDebug(LOG_PL) << "Load plugin" << _name << "with settings" << _settings;
QString libraryName = QString("lib%2.so").arg(_name);
for (auto &dir : pluginLocations()) {
if (!QDir(dir).entryList(QDir::Files).contains(libraryName))
continue;
// build plugin loader
QPluginLoader loader(QString("%1/%2").arg(dir).arg(libraryName), this);
qCInfo(LOG_PL) << "Loading" << loader.fileName();
// load plugin
QObject *plugin = loader.instance();
QueuedPluginInterface *item = nullptr;
if (loader.isLoaded())
item = qobject_cast<QueuedPluginInterface *>(plugin);
else
qCCritical(LOG_PL) << "Could not load the library for" << _name
<< "error" << loader.errorString();
if (item) {
m_plugins[_name] = item;
item->init(_settings);
item->connect(interface());
} else {
qCCritical(LOG_PL) << "Could not cast plugin" << _name;
}
// do not try to load it from other paths
break;
}
return m_plugins.contains(_name);
}
/**
* @fn pluginLocations
*/
QStringList QueuedPluginManager::pluginLocations() const
{
QStringList locations = QStandardPaths::standardLocations(
QStandardPaths::GenericDataLocation);
for (auto &loc : locations)
loc = QString("%1/%2/%3")
.arg(loc)
.arg(QueuedConfig::HOME_PATH)
.arg(QueuedConfig::PLUGIN_PATH);
return locations;
}
/**
* @fn unloadPlugin
*/
bool QueuedPluginManager::unloadPlugin(const QString &_name)
{
qCDebug(LOG_PL) << "Unload plugin" << _name;
if (!m_plugins.contains(_name)) {
qCWarning(LOG_LIB) << "Could not find plugin" << _name;
return false;
}
auto plugin = m_plugins.take(_name);
delete plugin;
return true;
}