From 8ec74f9e9295bd5957efeaa8c3b66fecb7a1b38a Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Wed, 25 Mar 2009 16:22:36 -0400 Subject: Add functions to load plugins so that parenting is preserved for the plugin classes --- sigtools/CMakeLists.txt | 2 + sigtools/PluginLoader.cpp | 130 ++++++++++++++++++++++++++++++++++++++++++++++ sigtools/PluginLoader.h | 60 +++++++++++++++++++++ sigtools/PluginLoader_p.h | 34 ++++++++++++ 4 files changed, 226 insertions(+) create mode 100644 sigtools/PluginLoader.cpp create mode 100644 sigtools/PluginLoader.h create mode 100644 sigtools/PluginLoader_p.h (limited to 'sigtools') diff --git a/sigtools/CMakeLists.txt b/sigtools/CMakeLists.txt index e564740e..96a2e589 100644 --- a/sigtools/CMakeLists.txt +++ b/sigtools/CMakeLists.txt @@ -2,11 +2,13 @@ project(sigtools) set(sigtools_HEADERS Global.h + PluginLoader.h PluginTree.h ) set(sigtools_SRCS BaseModel.cpp ClassModel.cpp + PluginLoader.cpp PluginModel.cpp PluginTree.cpp PluginTreeDelegate.cpp diff --git a/sigtools/PluginLoader.cpp b/sigtools/PluginLoader.cpp new file mode 100644 index 00000000..d655d14f --- /dev/null +++ b/sigtools/PluginLoader.cpp @@ -0,0 +1,130 @@ +/* + * Copyright 2009 Ben Boeckel + * + * This program 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. + * + * This program 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 this program. If not, see . + */ + +// Header include +#include "PluginLoader.h" +#include "PluginLoader_p.h" + +// Sigencore interface includes +#include +#include + +// KDE includes +#include +#include + +using namespace Sigscript; +using namespace Sigencore; +using namespace Sigencore::Interfaces; +using namespace Sigtools; + +K_GLOBAL_STATIC(PluginLoader::Private, loader) + +QStringList PluginLoader::availablePlugins(const QString& type, const bool forceLookup) +{ + if (forceLookup || !loader->m_available.contains(type)) + loader->refresh(type); + return loader->m_available[type].keys(); +} + +KService::Ptr PluginLoader::service(const QString& type, const QString& name) +{ + return loader->service(type, name); +} + +ArenaPlugin* PluginLoader::pluginForArena(const QString& arena) +{ + return qobject_cast(loader->factory("Arena", arena)); +} + +CanvasPlugin* PluginLoader::pluginForCanvas(const QString& canvas) +{ + return qobject_cast(loader->factory("canvasa", canvas)); +} + +Arena* PluginLoader::loadArena(const QString& name, GameWrapper* game, Config* parent) +{ + ArenaPlugin* plugin = pluginForArena(name); + if (plugin) + return plugin->getArena(name, game, parent); + return NULL; +} + +Canvas* PluginLoader::loadCanvas(const QString& name, GameWrapper* game, Config* parent) +{ + CanvasPlugin* plugin = pluginForCanvas(name); + if (plugin) + return plugin->getCanvas(name, game, parent); + return NULL; +} + +void PluginLoader::Private::refresh(const QString& type) +{ + QList curServices = m_available[type].values(); + foreach (const Service& service, curServices) + delete service.second; + m_available[type].clear(); + KService::List services = KServiceTypeTrader::self()->query(QString("Sigen/%1").arg(type), "[X-Sigen-MinVersion] <= 000101"); + foreach (KService::Ptr service, services) + { + KPluginLoader loader(service->library()); + KPluginFactory *factory = loader.factory(); + if (factory) + { + QStringList plugins; + QObject* sigenPlugin; + if (type == "Arena") + { + ArenaPlugin* plugin = factory->create(this); + if (plugin) + plugins = plugin->arenas(); + sigenPlugin = plugin; + } + else if (type == "Canvas") + { + CanvasPlugin* plugin = factory->create(this); + if (plugin) + plugins = plugin->canvases(); + sigenPlugin = plugin; + } + else + KMessageBox::information(NULL, QString("The plugin type \"Sigen/%1\" is not supported.").arg(type), "Unsupported plugin type"); + foreach (const QString& plugin, plugins) + m_available[type][plugin] = Service(service, sigenPlugin); + } + else + KMessageBox::error(NULL, QString("The plugin of type \"Sigen/%1\" with name \"%2\" is not a valid Sigen plugin. The error was:\n%3").arg(type).arg(service->name()).arg(loader.errorString()), "Plugin loading error"); + } +} + +KService::Ptr PluginLoader::Private::service(const QString& type, const QString& name) +{ + if (!m_available.contains(type)) + refresh(type); + if (m_available[type].contains(name)) + return m_available[type][name].first; + return KService::Ptr(); +} + +QObject* PluginLoader::Private::factory(const QString& type, const QString& name) +{ + if (!m_available.contains(type)) + refresh(type); + if (m_available[type].contains(name)) + return m_available[type][name].second; + return NULL; +} diff --git a/sigtools/PluginLoader.h b/sigtools/PluginLoader.h new file mode 100644 index 00000000..ccd14169 --- /dev/null +++ b/sigtools/PluginLoader.h @@ -0,0 +1,60 @@ +/* + * Copyright 2009 Ben Boeckel + * + * This program 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. + * + * This program 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 this program. If not, see . + */ + +#ifndef SIGTOOLS_PLUGINLOADER +#define SIGTOOLS_PLUGINLOADER + +// Sigtools includes +#include "Global.h" + +// KDE includes +#include + +// Forward declarations +class KPluginFactory; +namespace Sigencore +{ +class Arena; +class Canvas; +namespace Interfaces +{ +class ArenaPlugin; +class CanvasPlugin; +} +} +namespace Sigscript +{ +class Config; +class GameWrapper; +} + +namespace Sigtools +{ +namespace PluginLoader +{ + SIGTOOLS_EXPORT QStringList availablePlugins(const QString& type, const bool forceLookup = false); + SIGTOOLS_EXPORT KService::Ptr service(const QString& type, const QString& name); + + SIGTOOLS_EXPORT Sigencore::Interfaces::ArenaPlugin* pluginForArena(const QString& arena); + SIGTOOLS_EXPORT Sigencore::Interfaces::CanvasPlugin* pluginForCanvas(const QString& canvas); + + SIGTOOLS_EXPORT Sigencore::Arena* loadArena(const QString& arena, Sigscript::GameWrapper* game, Sigscript::Config* parent); + SIGTOOLS_EXPORT Sigencore::Canvas* loadCanvas(const QString& canvas, Sigscript::GameWrapper* game, Sigscript::Config* parent); +} +} + +#endif diff --git a/sigtools/PluginLoader_p.h b/sigtools/PluginLoader_p.h new file mode 100644 index 00000000..c333d8cf --- /dev/null +++ b/sigtools/PluginLoader_p.h @@ -0,0 +1,34 @@ +#ifndef SIGTOOLS_PLUGINLOADER_P +#define SIGTOOLS_PLUGINLOADER_P + +// Sigtools includes +#include "Global.h" + +// KDE includes +#include + +// Qt includes +#include +#include + +namespace Sigtools +{ +namespace PluginLoader +{ +class SIGTOOLS_NO_EXPORT Private : public QObject +{ + Q_OBJECT + + public: + void refresh(const QString& type); + KService::Ptr service(const QString& type, const QString& name); + QObject* factory(const QString& type, const QString& name); + + typedef QPair Service; + typedef QMap PluginList; + QMap m_available; +}; +} +} + +#endif -- cgit