You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdeutils/ksim/library/pluginloader.cpp

327 lines
8.4 KiB

/* ksim - a system monitor for kde
*
* Copyright (C) 2001 Robbie Ward <linuxphreak@gmx.co.uk>
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "pluginloader.h"
#include "pluginloader.moc"
#include <kdebug.h>
#include <klibloader.h>
#include <kdesktopfile.h>
#include <tdelocale.h>
#include <tdeglobal.h>
#include <kstandarddirs.h>
#include <tdemessagebox.h>
#include <tqstringlist.h>
class KSim::PluginInfo::Private
{
public:
};
KSim::PluginInfo::~PluginInfo()
{
}
const TQString &KSim::PluginInfo::name() const
{
return m_name;
}
TQCString KSim::PluginInfo::libName(bool includePrefix) const
{
return (includePrefix ? "ksim_" + m_libName : m_libName);
}
const TQString &KSim::PluginInfo::location() const
{
return m_location;
}
KSim::PluginInfo::PluginInfo()
{
}
class KSim::PluginLoader::Private
{
public:
typedef KSim::PluginObject *(PluginPtr)(const char *);
KSim::PluginList pluginList;
TQString error;
TQString lib;
bool lastLoaded;
static const char *const ksimString;
};
const char *const KSim::PluginLoader::Private::ksimString = "ksim_";
KSim::PluginLoader *KSim::PluginLoader::m_instance = 0; // initialize pointer
KSim::PluginLoader &KSim::PluginLoader::self()
{
if (!m_instance) // is it the first call?
m_instance = new PluginLoader; // create sole instance
return *m_instance; // address of sole instance
}
KSim::PluginLoader::~PluginLoader()
{
unloadAllPlugins();
delete d;
}
bool KSim::PluginLoader::loadPlugin(const KDesktopFile &file)
{
switch (createPlugin(file)) {
case KSim::PluginLoader::EmptyLibName:
KMessageBox::error(0, i18n("KSim was unable to load the plugin %1"
" due to the X-KSIM-LIBRARY property being empty in the"
" plugins desktop file").arg(file.readName()));
return false;
break;
case KSim::PluginLoader::LibNotFound:
KMessageBox::error(0, i18n("KSim was unable to load the plugin %1"
" due to not being able to find the plugin, check that the plugin"
" is installed and is in your $TDEDIR/lib path").arg(file.readName()));
return false;
break;
case KSim::PluginLoader::UnSymbols:
KMessageBox::error(0, i18n("<qt>An error occurred while trying \n"
"to load the plugin '%1'. \nThis could be caused by the"
" following:<ul>\n<li>The plugin doesn't have the %2"
" macro</li>\n<li>The plugin has been damaged or has"
" some unresolved symbols</li>\n</ul> \nLast"
" error message that occurred: \n%3</qt>")
.arg(d->lib.prepend("ksim_")).arg("KSIM_INIT_PLUGIN")
.arg(d->error));
return false;
break;
default:
break;
}
return true;
}
bool KSim::PluginLoader::unloadPlugin(const TQCString &name)
{
if (name.isEmpty())
return false;
// see if our plugin is loaded
KSim::Plugin plugin = find(name);
if (plugin.isNull())
return false;
// try to unload the library
kdDebug(2003) << "Unloading plugin " << plugin.libName() << endl;
KLibLoader::self()->unloadLibrary(plugin.libName());
d->pluginList.remove(plugin);
return true;
}
void KSim::PluginLoader::unloadAllPlugins()
{
kdDebug(2003) << "Unloading all plugins" << endl;
// Go through the plugin list and unload each plugin;
KSim::PluginList::ConstIterator it;
for (it = d->pluginList.begin(); it != d->pluginList.end(); ++it) {
KLibLoader::self()->unloadLibrary((*it).libName());
}
// Clear the plugin list;
d->pluginList.clear();
KLibLoader::cleanUp();
}
bool KSim::PluginLoader::isLoaded(const KSim::Plugin &info) const
{
return isLoaded(info.libName());
}
bool KSim::PluginLoader::isLoaded(const TQCString &library) const
{
if (library.isEmpty())
return false;
return !find(library).isNull();
}
KSim::PluginInfo KSim::PluginLoader::findPluginInfo(const TQString &name,
SearchType type) const
{
TQString location;
switch (type) {
case Name: {
TQStringList files = TDEGlobal::dirs()->findAllResources("data", "ksim/monitors/*.desktop");
TQStringList::ConstIterator it;
for (it = files.begin(); it != files.end(); ++it) {
KDesktopFile file((*it));
if (file.readName() == name) {
location = (*it);
break;
}
}
break;
}
case LibName: {
TQStringList files = TDEGlobal::dirs()->findAllResources("data", "ksim/monitors/*.desktop");
TQStringList::ConstIterator it;
for (it = files.begin(); it != files.end(); ++it) {
KDesktopFile file((*it));
if (file.readEntry("X-KSIM-LIBRARY") == name) {
location = (*it);
break;
}
}
break;
}
case DesktopFile: {
if (!KDesktopFile::isDesktopFile(name))
return KSim::PluginInfo();
location = name;
break;
}
}
KDesktopFile file(location);
KSim::PluginInfo info;
info.m_name = file.readName();
info.m_libName = file.readEntry("X-KSIM-LIBRARY").local8Bit();
info.m_location = location;
return info;
}
KSim::Plugin &KSim::PluginLoader::find(const TQCString &libName)
{
if (libName.isEmpty())
return KSim::Plugin::null;
TQCString library(libName);
if (libName.find(Private::ksimString) == -1)
library.prepend(Private::ksimString);
KSim::PluginList::Iterator it;
for (it = d->pluginList.begin(); it != d->pluginList.end(); ++it) {
if ((*it).libName() == library)
return (*it);
}
return KSim::Plugin::null;
}
const KSim::Plugin &KSim::PluginLoader::find(const TQCString &libName) const
{
if (libName.isEmpty())
return KSim::Plugin::null;
TQCString library(libName);
if (libName.find(Private::ksimString) == -1)
library.prepend(Private::ksimString);
KSim::PluginList::ConstIterator it;
for (it = d->pluginList.begin(); it != d->pluginList.end(); ++it) {
if ((*it).libName() == library)
return (*it);
}
return KSim::Plugin::null;
}
KSim::Plugin &KSim::PluginLoader::find(const KSim::PluginInfo &info)
{
return find(info.libName());
}
const KSim::Plugin &KSim::PluginLoader::find(const KSim::PluginInfo &info) const
{
return find(info.libName());
}
const KSim::PluginList &KSim::PluginLoader::pluginList() const
{
return d->pluginList;
}
KSim::PluginList &KSim::PluginLoader::pluginList()
{
return d->pluginList;
}
const KSim::Plugin &KSim::PluginLoader::plugin() const
{
return (d->lastLoaded ? d->pluginList.last() : KSim::Plugin::null);
}
KSim::Plugin &KSim::PluginLoader::plugin()
{
return (d->lastLoaded ? d->pluginList.last() : KSim::Plugin::null);
}
KSim::PluginLoader::PluginLoader() : TQObject(0, "PluginLoader")
{
d = new KSim::PluginLoader::Private;
d->lastLoaded = false;
}
void KSim::PluginLoader::cleanup()
{
if (!m_instance)
return;
delete m_instance;
m_instance = 0;
}
KSim::PluginLoader::ErrorCode KSim::PluginLoader::createPlugin(const KDesktopFile &file)
{
d->error = TQString();
TQCString pluginName(file.readEntry("X-KSIM-LIBRARY").local8Bit());
if (pluginName.isEmpty())
return EmptyLibName;
TQCString libName(Private::ksimString + pluginName);
KLibrary *library = KLibLoader::self()->library(libName);
if (!library)
return LibNotFound;
TQCString symbol("init_plugin");
if (Private::PluginPtr *create = (Private::PluginPtr *)(library->symbol(symbol))) {
d->pluginList.append(KSim::Plugin(create(pluginName), file));
d->lib = TQString();
d->lastLoaded = true;
}
else {
d->error = KLibLoader::self()->lastErrorMessage().isEmpty() ?
i18n("Unable to get last error message") :
KLibLoader::self()->lastErrorMessage();
KLibLoader::self()->unloadLibrary(libName);
d->lib = pluginName;
d->lastLoaded = false;
return UnSymbols;
}
emit pluginLoaded(d->pluginList.last());
return LibLoaded;
}