diff --git a/sources/queued/QueuedConfig.h.in b/sources/queued/QueuedConfig.h.in index 6f2ae23..7e5a686 100644 --- a/sources/queued/QueuedConfig.h.in +++ b/sources/queued/QueuedConfig.h.in @@ -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 /** diff --git a/sources/queued/include/queued/Queued.h b/sources/queued/include/queued/Queued.h index 5449cb0..72c94b7 100644 --- a/sources/queued/include/queued/Queued.h +++ b/sources/queued/include/queued/Queued.h @@ -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" diff --git a/sources/queued/include/queued/QueuedPluginInterface.h b/sources/queued/include/queued/QueuedPluginInterface.h new file mode 100644 index 0000000..5ecb5b4 --- /dev/null +++ b/sources/queued/include/queued/QueuedPluginInterface.h @@ -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 + +#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 */ diff --git a/sources/queued/include/queued/QueuedPluginManager.h b/sources/queued/include/queued/QueuedPluginManager.h new file mode 100644 index 0000000..7e077aa --- /dev/null +++ b/sources/queued/include/queued/QueuedPluginManager.h @@ -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 +#include + + +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 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 */ diff --git a/sources/queued/include/queued/QueuedPluginManagerInterface.h b/sources/queued/include/queued/QueuedPluginManagerInterface.h new file mode 100644 index 0000000..3bd10c1 --- /dev/null +++ b/sources/queued/include/queued/QueuedPluginManagerInterface.h @@ -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 + + +/** + * @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 */ diff --git a/sources/queued/src/QueuedPluginManager.cpp b/sources/queued/src/QueuedPluginManager.cpp new file mode 100644 index 0000000..c0fb48a --- /dev/null +++ b/sources/queued/src/QueuedPluginManager.cpp @@ -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 +#include +#include + + +/** + * @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(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; +}