22 #include "pluginmanager.h"
26 #include <tqapplication.h>
30 #include <tqvaluestack.h>
32 #include <tdeapplication.h>
34 #include <tdeparts/componentfactory.h>
35 #include <kplugininfo.h>
36 #include <ksettings/dispatcher.h>
37 #include <ksimpleconfig.h>
38 #include <kstandarddirs.h>
39 #include <kstaticdeleter.h>
46 class PluginManager::Private
50 TQValueList<KPluginInfo*> plugins;
54 TQMap<KPluginInfo*, Plugin*> loadedPlugins;
60 enum ShutdownMode { StartingUp, Running, ShuttingDown, DoneShutdown };
61 ShutdownMode shutdownMode;
63 TDESharedConfig::Ptr config;
65 TQValueStack<TQString> pluginsToLoad;
68 PluginManager::PluginManager( TQObject *parent )
78 d->shutdownMode = Private::StartingUp;
80 KSettings::Dispatcher::self()->registerInstance( TDEGlobal::instance(),
81 this, TQ_SLOT( loadAllPlugins() ) );
83 d->plugins = KPluginInfo::fromServices(
84 TDETrader::self()->query( TQString::fromLatin1(
"Komposer/Plugin" ),
85 TQString::fromLatin1(
"[X-Komposer-Version] == 1" ) ) );
88 PluginManager::~PluginManager()
90 if ( d->shutdownMode != Private::DoneShutdown ) {
91 slotShutdownTimeout();
93 kdWarning() << k_funcinfo
94 <<
"Destructing plugin manager without going through "
95 <<
"the shutdown process!"
97 << kdBacktrace(10) << endl;
102 TQMap<KPluginInfo*, Plugin*>::ConstIterator it;
103 for ( it = d->loadedPlugins.begin(); it != d->loadedPlugins.end(); )
106 TQMap<KPluginInfo*, Plugin*>::ConstIterator nextIt( it );
108 kdWarning() << k_funcinfo <<
"Deleting stale plugin '"
109 << it.data()->name() <<
"'" << endl;
117 TQValueList<KPluginInfo*>
118 PluginManager::availablePlugins(
const TQString &category )
const
120 if ( category.isEmpty() )
123 TQValueList<KPluginInfo*> result;
124 TQValueList<KPluginInfo*>::ConstIterator it;
125 for ( it = d->plugins.begin(); it != d->plugins.end(); ++it )
127 if ( ( *it )->category() == category )
128 result.append( *it );
134 TQMap<KPluginInfo*, Plugin*>
135 PluginManager::loadedPlugins(
const TQString &category )
const
137 TQMap<KPluginInfo*, Plugin*> result;
138 TQMap<KPluginInfo*, Plugin*>::ConstIterator it;
139 for ( it = d->loadedPlugins.begin(); it != d->loadedPlugins.end(); ++it )
141 if ( category.isEmpty() || it.key()->category() == category )
142 result.insert( it.key(), it.data() );
149 PluginManager::shutdown()
151 d->shutdownMode = Private::ShuttingDown;
154 d->pluginsToLoad.clear();
157 if ( d->loadedPlugins.empty() ) {
158 d->shutdownMode = Private::DoneShutdown;
160 TQMap<KPluginInfo*, Plugin*>::ConstIterator it;
161 for ( it = d->loadedPlugins.begin(); it != d->loadedPlugins.end(); )
164 TQMap<KPluginInfo*, Plugin*>::ConstIterator nextIt( it );
166 it.data()->aboutToUnload();
171 TQTimer::singleShot( 3000,
this, TQ_SLOT(slotShutdownTimeout()) );
175 PluginManager::slotPluginReadyForUnload()
180 Plugin* plugin =
dynamic_cast<Plugin*
>(
const_cast<TQObject*
>( sender() ) );
183 kdWarning() << k_funcinfo <<
"Calling object is not a plugin!" << endl;
187 kdDebug()<<
"manager unloading"<<endl;
188 plugin->deleteLater();
192 PluginManager::slotShutdownTimeout()
196 if ( d->shutdownMode == Private::DoneShutdown )
200 TQStringList remaining;
201 for ( TQMap<KPluginInfo*, Plugin*>::ConstIterator it = d->loadedPlugins.begin();
202 it != d->loadedPlugins.end(); ++it )
203 remaining.append( it.key()->pluginName() );
205 kdWarning() << k_funcinfo <<
"Some plugins didn't shutdown in time!" << endl
206 <<
"Remaining plugins: "
207 << remaining.join( TQString::fromLatin1(
", " ) ) << endl
208 <<
"Forcing Komposer shutdown now." << endl;
215 PluginManager::slotShutdownDone()
217 d->shutdownMode = Private::DoneShutdown;
223 PluginManager::loadAllPlugins()
228 d->config = TDESharedConfig::openConfig(
"komposerrc" );
230 TQMap<TQString, TQString> entries = d->config->entryMap(
231 TQString::fromLatin1(
"Plugins" ) );
233 TQMap<TQString, TQString>::Iterator it;
234 for ( it = entries.begin(); it != entries.end(); ++it )
236 TQString key = it.key();
237 if ( key.endsWith( TQString::fromLatin1(
"Enabled" ) ) )
239 key.setLength( key.length() - 7 );
242 if ( it.data() == TQString::fromLatin1(
"true" ) )
244 if ( !plugin( key ) )
245 d->pluginsToLoad.push( key );
259 TQTimer::singleShot( 0,
this, TQ_SLOT( slotLoadNextPlugin() ) );
262 void PluginManager::slotLoadNextPlugin()
264 if ( d->pluginsToLoad.isEmpty() )
266 if ( d->shutdownMode == Private::StartingUp )
268 d->shutdownMode = Private::Running;
269 emit allPluginsLoaded();
274 TQString key = d->pluginsToLoad.pop();
275 loadPluginInternal( key );
281 TQTimer::singleShot( 0,
this, TQ_SLOT( slotLoadNextPlugin() ) );
285 PluginManager::loadPlugin(
const TQString &pluginId,
286 PluginLoadMode mode )
288 if ( mode == LoadSync ) {
289 return loadPluginInternal( pluginId );
291 d->pluginsToLoad.push( pluginId );
292 TQTimer::singleShot( 0,
this, TQ_SLOT( slotLoadNextPlugin() ) );
298 PluginManager::loadPluginInternal(
const TQString &pluginId )
300 KPluginInfo* info = infoForPluginId( pluginId );
302 kdWarning() << k_funcinfo <<
"Unable to find a plugin named '"
303 << pluginId <<
"'!" << endl;
307 if ( d->loadedPlugins.contains( info ) )
308 return d->loadedPlugins[ info ];
311 Plugin *plugin = KParts::ComponentFactory::createInstanceFromQuery<Komposer::Plugin>(
312 TQString::fromLatin1(
"Komposer/Plugin" ),
313 TQString::fromLatin1(
"[X-TDE-PluginInfo-Name]=='%1'" ).arg( pluginId ),
314 this, 0, TQStringList(), &error );
317 d->loadedPlugins.insert( info, plugin );
318 info->setPluginEnabled(
true );
320 connect( plugin, TQ_SIGNAL(destroyed(TQObject*)),
321 this, TQ_SLOT(slotPluginDestroyed(TQObject*)) );
322 connect( plugin, TQ_SIGNAL(readyForUnload()),
323 this, TQ_SLOT(slotPluginReadyForUnload()) );
325 kdDebug() << k_funcinfo <<
"Successfully loaded plugin '"
326 << pluginId <<
"'" << endl;
328 emit pluginLoaded( plugin );
331 case KParts::ComponentFactory::ErrNoServiceFound:
332 kdDebug() << k_funcinfo <<
"No service implementing the given mimetype "
333 <<
"and fullfilling the given constraint expression can be found."
337 case KParts::ComponentFactory::ErrServiceProvidesNoLibrary:
338 kdDebug() <<
"the specified service provides no shared library." << endl;
341 case KParts::ComponentFactory::ErrNoLibrary:
342 kdDebug() <<
"the specified library could not be loaded." << endl;
345 case KParts::ComponentFactory::ErrNoFactory:
346 kdDebug() <<
"the library does not export a factory for creating components."
350 case KParts::ComponentFactory::ErrNoComponent:
351 kdDebug() <<
"the factory does not support creating components "
352 <<
"of the specified type."
357 kdDebug() << k_funcinfo <<
"Loading plugin '" << pluginId
358 <<
"' failed, KLibLoader reported error: '"
359 << KLibLoader::self()->lastErrorMessage()
367 PluginManager::unloadPlugin(
const TQString &spec )
369 TQMap<KPluginInfo*, Plugin*>::ConstIterator it;
370 for ( it = d->loadedPlugins.begin(); it != d->loadedPlugins.end(); ++it )
372 if ( it.key()->pluginName() == spec )
374 it.data()->aboutToUnload();
383 PluginManager::slotPluginDestroyed( TQObject *plugin )
385 TQMap<KPluginInfo*, Plugin*>::Iterator it;
386 for ( it = d->loadedPlugins.begin(); it != d->loadedPlugins.end(); ++it )
388 if ( it.data() == plugin )
390 d->loadedPlugins.erase( it );
395 if ( d->shutdownMode == Private::ShuttingDown && d->loadedPlugins.isEmpty() )
399 TQTimer::singleShot( 0,
this, TQ_SLOT(slotShutdownDone()) );
404 PluginManager::plugin(
const TQString &pluginId )
const
406 KPluginInfo *info = infoForPluginId( pluginId );
410 if ( d->loadedPlugins.contains( info ) )
411 return d->loadedPlugins[ info ];
417 PluginManager::pluginName(
const Plugin *plugin )
const
419 TQMap<KPluginInfo*, Plugin*>::ConstIterator it;
420 for ( it = d->loadedPlugins.begin(); it != d->loadedPlugins.end(); ++it )
422 if ( it.data() == plugin )
423 return it.key()->name();
426 return TQString::fromLatin1(
"Unknown" );
430 PluginManager::pluginId(
const Plugin *plugin )
const
432 TQMap<KPluginInfo*, Plugin*>::ConstIterator it;
433 for ( it = d->loadedPlugins.begin(); it != d->loadedPlugins.end(); ++it )
435 if ( it.data() == plugin )
436 return it.key()->pluginName();
439 return TQString::fromLatin1(
"unknown" );
443 PluginManager::pluginIcon(
const Plugin *plugin )
const
445 TQMap<KPluginInfo*, Plugin*>::ConstIterator it;
446 for ( it = d->loadedPlugins.begin(); it != d->loadedPlugins.end(); ++it )
448 if ( it.data() == plugin )
449 return it.key()->icon();
452 return TQString::fromLatin1(
"Unknown" );
456 PluginManager::infoForPluginId(
const TQString &pluginId )
const
458 TQValueList<KPluginInfo*>::ConstIterator it;
459 for ( it = d->plugins.begin(); it != d->plugins.end(); ++it )
461 if ( ( *it )->pluginName() == pluginId )
469 PluginManager::setPluginEnabled(
const TQString &pluginId,
bool enabled )
472 d->config = TDESharedConfig::openConfig(
"komposerrc" );
474 d->config->setGroup(
"Plugins" );
477 if ( !infoForPluginId( pluginId ) )
480 d->config->writeEntry( pluginId + TQString::fromLatin1(
"Enabled" ), enabled );
488 #include "pluginmanager.moc"