-
Antoine Lorence authoredAntoine Lorence authored
PluginManager.cpp 7.63 KiB
/*
* Copyright 2011-2012 INSA Rennes
*
* This file is part of ImageINSA.
*
* ImageINSA 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.
*
* ImageINSA 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 ImageINSA. If not, see <http://www.gnu.org/licenses/>.
*/
#include "PluginManager.h"
#include <GenericInterface.h>
#include <QMessageBox>
#include <QLibrary>
#include <string>
#include <typeinfo>
#include <sstream>
using namespace genericinterface;
using namespace std;
PluginManager::PluginManager(GenericInterface* gi) {
_gi = gi;
}
void PluginManager::display(GenericInterface* gi)
{
QMenu* menu = gi->menu(tr("&Plugin"));
_loadPluginAction = menu->addAction(tr("&Load plugin"));
_unloadPluginsAction = menu->addAction(tr("&Unload all plugins"));
// TODO: perform this task in a better and most logical place. For now,
// it works because 'addPlugin()' signal will be connected when it is emmited
// in loadPlugin(), so it will really display its menu in the GenericInterface
QDir directory("plugins");
QStringList files = directory.entryList();
std::cout << files.size() << " files in plugins' directory" << std::endl;
for(QStringList::iterator it = files.begin(); it != files.end(); ++it) {
if(QLibrary::isLibrary(*it)) {
std::cout << "library found : " << it->toStdString() << std::endl;
loadPlugin(directory.path() + QDir::separator() + *it);
}
}
checkActionsValid();
}
void PluginManager::connect(GenericInterface* gi)
{
QObject::connect(_loadPluginAction, SIGNAL(triggered()), this, SLOT(choosePlugin()));
QObject::connect(_unloadPluginsAction, SIGNAL(triggered()), this, SLOT(unloadAllPlugins()));
QObject::connect(this, SIGNAL(addPlugin(OpSet*)), this, SLOT(checkActionsValid()));
QObject::connect(this, SIGNAL(removePlugin(OpSet*)), this, SLOT(checkActionsValid()));
}
/*void PluginManager::checkActionsValid(QMdiSubWindow* activeWindow) {
StandardImageWindow* window = (activeWindow) ? dynamic_cast<StandardImageWindow*>(activeWindow->widget()) : NULL;
if(window) {
_erosion->setEnabled(true);
}
else {
_erosion->setEnabled(false);
}
}*/
void PluginManager::choosePlugin() {
QString file = QFileDialog::getOpenFileName(_gi, tr("Load plugin"), QString(), tr("Plugin (*.dll *.so *.dylib)"));
if(file.size()==0) return;
std::map<std::string, Plugin*>::iterator it = _plugins.find(file.toStdString());
if(it != _plugins.end()) {
unloadPlugin(it->second);
/*QMessageBox::information (_gi, "Library already loaded", "The library you are trying to load has already been loaded.");*/
//return;
}
loadPlugin(file, false);
//QLibrary* library = new QLibrary(file);
//if(!library->load()) {
//QMessageBox::critical (_gi, "Error loading plugin", library->errorString());
//return;
//}
//else {
////QMessageBox::information (_gi, "Library loaded", "The plugin's library has been loaded successfully");
//}
//void* ptr = library->resolve("getPlugin");
//if(ptr==0) {
//QMessageBox::critical (_gi, "Error loading plugin", "Could not find the plugin's entry point \"getPlugin\"");
//return;
//}
//ostringstream oss;
//typedef Plugin* (*entryPoint)();
//entryPoint getPlugin = reinterpret_cast<entryPoint>(ptr);
//Plugin* plugin = getPlugin();
//if(plugin==NULL) {
//QMessageBox::critical (_gi, "Error loading plugin", "The getPlugin entry point does not return a valid Plugin");
//return;
//}
//vector<Operation*> operations = plugin->getOperations();
////oss << "Found " << operations.size() << " operations in the plugin !";
//_plugins.insert(pair<string,Plugin*>(file.toStdString(), plugin));
//emit addPlugin(plugin);
////QMessageBox::information (_gi, "Library loaded", oss.str().c_str());
////PluginService* pluginService = new PluginService(plugin);
////_pluginServices.insert(pair<string,PluginService*>(file.toStdString(), pluginService));
////_gi->addNewService(pluginService);
////checkActionsValid();
//std::cout << "Plugin " << plugin->getName() << " loaded : " << operations.size() << " operations "<< std::endl;
}
void PluginManager::unloadAllPlugins() {
for(std::map<string, Plugin*>::iterator it = _plugins.begin(); it != _plugins.end(); ++it) {
Plugin* plugin = it->second;
map<Plugin*,QLibrary*>::iterator lit = _libraries.find(plugin);
if(lit != _libraries.end()) {
bool res = lit->second->unload();
std::cout << "Unloading " << lit->second->fileName().toStdString() << "..." << res << std::endl;
_libraries.erase(lit);
}
emit removePlugin(plugin);
}
_plugins.clear();
checkActionsValid();
}
void PluginManager::unloadPlugin(Plugin* plugin) {
for(std::map<std::string, Plugin*>::iterator it = _plugins.begin(); it != _plugins.end(); ++it) {
if(it->second==plugin) {
//delete it->second;
//_pluginServices.erase(it);
////it = _pluginServices.begin();
map<Plugin*,QLibrary*>::iterator lit = _libraries.find(plugin);
if(lit != _libraries.end()) {
bool res = lit->second->unload();
std::cout << "Unloading " << lit->second->fileName().toStdString() << "..." << res << std::endl;
_libraries.erase(lit);
}
_plugins.erase(it);
emit removePlugin(plugin);
return;
}
}
}
void PluginManager::checkActionsValid() {
if(_unloadPluginsAction)
_unloadPluginsAction->setEnabled(_plugins.size() > 0);
}
bool PluginManager::loadPlugin(QString file, bool silent) {
QLibrary* library = new QLibrary(file);
if(!library->load()) {
if(!silent) {
QMessageBox::critical (_gi, tr("Error loading plugin"), library->errorString());
}
return false;
}
std::cout << file.toStdString() << " loaded" << std::endl;
QFunctionPointer ptr = library->resolve("loadPlugin");
if(ptr == 0) {
if(!silent) {
QMessageBox::critical (_gi, tr("Error loading plugin"), tr("Could not find the plugin's entry point \"loadPlugin\""));
}
return false;
}
std::cout << file.toStdString() << ": entry point found" << std::endl;
typedef Plugin* (*entryPoint)();
entryPoint getPlugin = reinterpret_cast<entryPoint>(ptr);
Plugin* plugin = getPlugin();
if(plugin==NULL) {
if(!silent) {
QMessageBox::critical (_gi, tr("Error loading plugin"), tr("The getPlugin entry point does not return a valid Plugin"));
}
return false;
}
std::cout << file.toStdString() << ": got Plugin" << std::endl;
vector<GenericOperation*> operations = plugin->getOperations();
std::cout << "Plugin " << plugin->getName() << " loaded : " << operations.size() << " operations "<< std::endl;
//PluginService* pluginService = new PluginService(plugin);
_plugins.insert(pair<string,Plugin*>(file.toStdString(), plugin));
_libraries.insert(pair<Plugin*,QLibrary*>(plugin, library));
//_gi->addService(pluginService);
emit addPlugin(plugin);
return true;
}