22 #if defined(HAVE_VALGRIND_H) && !defined(NDEBUG)
24 #define __VALGRIND_SOMESKIN_H
25 #include <valgrind/valgrind.h>
28 #include <QApplication>
34 #include <ksharedconfig.h>
36 #include <kparts/componentfactory.h>
37 #include <kplugininfo.h>
39 #include <kstandarddirs.h>
41 #include <kservicetypetrader.h>
51 class PluginManagerPrivate
54 PluginManagerPrivate() : shutdownMode( StartingUp ), isAllPluginsLoaded(false)
56 plugins = KPluginInfo::fromServices( KServiceTypeTrader::self()->query( QLatin1String(
"Kopete/Plugin" ), QLatin1String(
"[X-Kopete-Version] == 1000900" ) ) );
59 ~PluginManagerPrivate()
61 if ( shutdownMode != DoneShutdown && !loadedPlugins.empty() )
63 kWarning( 14010 ) <<
"Destructing plugin manager without going through the shutdown process! Backtrace is: " << endl << kBacktrace();
68 while ( !loadedPlugins.empty() )
70 InfoToPluginMap::ConstIterator it = loadedPlugins.constBegin();
71 kWarning( 14010 ) <<
"Deleting stale plugin '" << it.value()->objectName() <<
"'";
72 KPluginInfo info = it.key();
73 Plugin *plugin = it.value();
74 loadedPlugins.remove(info);
75 plugin->disconnect(&instance, SLOT(slotPluginDestroyed(
QObject*)));
81 QList<KPluginInfo> plugins;
85 typedef QMap<KPluginInfo, Plugin *> InfoToPluginMap;
86 InfoToPluginMap loadedPlugins;
92 enum ShutdownMode { StartingUp, Running,
ShuttingDown, DoneShutdown };
93 ShutdownMode shutdownMode;
96 QStack<QString> pluginsToLoad;
98 bool isAllPluginsLoaded;
99 PluginManager instance;
102 K_GLOBAL_STATIC(PluginManagerPrivate, _kpmp)
106 return &_kpmp->instance;
109 PluginManager::PluginManager() :
QObject( 0 )
118 PluginManager::~PluginManager()
124 if ( category.isEmpty() )
125 return _kpmp->plugins;
127 QList<KPluginInfo> result;
128 QList<KPluginInfo>::ConstIterator it;
129 for ( it = _kpmp->plugins.constBegin(); it != _kpmp->plugins.constEnd(); ++it )
131 if ( it->category() == category && !(*it).service()->noDisplay() )
132 result.append( *it );
142 for ( PluginManagerPrivate::InfoToPluginMap::ConstIterator it = _kpmp->loadedPlugins.constBegin();
143 it != _kpmp->loadedPlugins.constEnd(); ++it )
145 if ( category.isEmpty() || it.key().category() == category )
146 result.append( it.value() );
155 for ( PluginManagerPrivate::InfoToPluginMap::ConstIterator it = _kpmp->loadedPlugins.constBegin();
156 it != _kpmp->loadedPlugins.constEnd(); ++it )
158 if ( it.value() ==
plugin )
161 return KPluginInfo();
166 if(_kpmp->shutdownMode != PluginManagerPrivate::Running)
168 kDebug( 14010 ) <<
"called when not running. / state = " << _kpmp->shutdownMode;
175 _kpmp->pluginsToLoad.clear();
178 for ( PluginManagerPrivate::InfoToPluginMap::ConstIterator it = _kpmp->loadedPlugins.constBegin();
179 it != _kpmp->loadedPlugins.constEnd(); )
184 PluginManagerPrivate::InfoToPluginMap::ConstIterator current( it );
189 current.value()->aboutToUnload();
201 #if defined(HAVE_VALGRIND_H) && !defined(NDEBUG) && defined(__i386__)
202 if ( RUNNING_ON_VALGRIND )
203 kDebug(14010) <<
"Running under valgrind, disabling plugin unload timeout guard";
206 QTimer::singleShot( 3000,
this, SLOT(slotShutdownTimeout()) );
209 void PluginManager::slotPluginReadyForUnload()
219 kWarning( 14010 ) <<
"Calling object is not a plugin!";
222 kDebug( 14010 ) << plugin->
pluginId() <<
"ready for unload";
224 plugin->deleteLater();
228 void PluginManager::slotShutdownTimeout()
232 if ( _kpmp->shutdownMode == PluginManagerPrivate::DoneShutdown )
235 QStringList remaining;
236 for ( PluginManagerPrivate::InfoToPluginMap::ConstIterator it = _kpmp->loadedPlugins.constBegin(); it != _kpmp->loadedPlugins.constEnd(); ++it )
237 remaining.append( it.value()->pluginId() );
239 kWarning( 14010 ) <<
"Some plugins didn't shutdown in time!" << endl
240 <<
"Remaining plugins: " << remaining.join( QLatin1String(
", " ) ) << endl
241 <<
"Forcing Kopete shutdown now." << endl;
246 void PluginManager::slotShutdownDone()
250 if (QTextCodec::codecForCStrings())
251 kWarning(14010) <<
"WARNING: Some plugin set QTextCodec::setCodecForCStrings this may break protocols!!!";
253 _kpmp->shutdownMode = PluginManagerPrivate::DoneShutdown;
262 KSharedConfig::Ptr config = KGlobal::config();
263 if ( config->hasGroup( QLatin1String(
"Plugins" ) ) )
265 QMap<QString, bool> pluginsMap;
267 QMap<QString, QString> entries = config->entryMap( QLatin1String(
"Plugins" ) );
268 QMap<QString, QString>::Iterator it;
269 for ( it = entries.begin(); it != entries.end(); ++it )
271 QString key = it.key();
272 if ( key.endsWith( QLatin1String(
"Enabled" ) ) )
273 pluginsMap.insert( key.left(key.length() - 7), (it.value() == QLatin1String(
"true" )) );
277 QList<KPluginInfo>::ConstIterator it2 = plugins.constBegin();
278 QList<KPluginInfo>::ConstIterator end = plugins.constEnd();
279 for ( ; it2 != end; ++it2 )
282 if ( it2->category() == QLatin1String(
"Protocols" ) )
285 QString pluginName = it2->pluginName();
286 if ( pluginsMap.value( pluginName, it2->isPluginEnabledByDefault() ) )
288 if ( !
plugin( pluginName ) )
289 _kpmp->pluginsToLoad.push( pluginName );
296 if (
plugin( pluginName ) )
305 QList<KPluginInfo>::ConstIterator it = plugins.constBegin();
306 QList<KPluginInfo>::ConstIterator end = plugins.constEnd();
307 for ( ; it != end; ++it )
309 if ( it->isPluginEnabledByDefault() )
310 _kpmp->pluginsToLoad.push( it->pluginName() );
314 QTimer::singleShot( 0,
this, SLOT(slotLoadNextPlugin()) );
317 void PluginManager::slotLoadNextPlugin()
319 if ( _kpmp->pluginsToLoad.isEmpty() )
321 if ( _kpmp->shutdownMode == PluginManagerPrivate::StartingUp )
323 _kpmp->shutdownMode = PluginManagerPrivate::Running;
324 _kpmp->isAllPluginsLoaded =
true;
330 QString key = _kpmp->pluginsToLoad.pop();
331 loadPluginInternal( key );
337 QTimer::singleShot( 0,
this, SLOT(slotLoadNextPlugin()) );
342 QString pluginId = _pluginId;
346 if ( pluginId.endsWith( QLatin1String(
".desktop" ) ) )
348 kWarning( 14010 ) <<
"Trying to use old-style API!" << endl << kBacktrace();
349 pluginId = pluginId.remove( QRegExp( QLatin1String(
".desktop$" ) ) );
354 return loadPluginInternal( pluginId );
358 _kpmp->pluginsToLoad.push( pluginId );
359 QTimer::singleShot( 0,
this, SLOT(slotLoadNextPlugin()) );
364 Plugin *PluginManager::loadPluginInternal(
const QString &pluginId )
368 KPluginInfo info = infoForPluginId( pluginId );
369 if ( !info.isValid() )
371 kWarning( 14010 ) <<
"Unable to find a plugin named '" << pluginId <<
"'!";
375 if ( _kpmp->loadedPlugins.contains( info ) )
376 return _kpmp->loadedPlugins[ info ];
379 Plugin *plugin = KServiceTypeTrader::createInstanceFromQuery<Plugin>( QString::fromLatin1(
"Kopete/Plugin" ), QString::fromLatin1(
"[X-KDE-PluginInfo-Name]=='%1'" ).arg( pluginId ),
this, QVariantList(), &error );
383 _kpmp->loadedPlugins.insert( info, plugin );
384 info.setPluginEnabled(
true );
386 connect( plugin, SIGNAL(destroyed(
QObject*)),
this, SLOT(slotPluginDestroyed(
QObject*)) );
387 connect( plugin, SIGNAL(readyForUnload()),
this, SLOT(slotPluginReadyForUnload()) );
389 kDebug( 14010 ) <<
"Successfully loaded plugin '" << pluginId <<
"'";
393 Protocol* protocol =
dynamic_cast<Protocol*
>(
plugin );
399 kDebug( 14010 ) <<
"Loading plugin " << pluginId <<
" failed, KServiceTypeTrader reported error: " << error ;
410 thePlugin->aboutToUnload();
419 void PluginManager::slotPluginDestroyed(
QObject *plugin )
421 for ( PluginManagerPrivate::InfoToPluginMap::Iterator it = _kpmp->loadedPlugins.begin();
422 it != _kpmp->loadedPlugins.end(); ++it )
424 if ( it.value() ==
plugin )
426 QString pluginName = it.key().pluginName();
427 _kpmp->loadedPlugins.erase( it );
437 QTimer::singleShot( 0,
this, SLOT(slotShutdownDone()) );
453 QString pluginId = _pluginId;
454 if ( pluginId.endsWith( QLatin1String(
"Protocol" ) ) )
455 pluginId = QLatin1String(
"kopete_" ) + _pluginId.toLower().remove( QString::fromLatin1(
"protocol" ) );
458 KPluginInfo info = infoForPluginId( pluginId );
459 if ( !info.isValid() )
462 if ( _kpmp->loadedPlugins.contains( info ) )
463 return _kpmp->loadedPlugins[ info ];
468 KPluginInfo PluginManager::infoForPluginId(
const QString &pluginId )
const
470 QList<KPluginInfo>::ConstIterator it;
471 for ( it = _kpmp->plugins.constBegin(); it != _kpmp->plugins.constEnd(); ++it )
473 if ( it->pluginName() == pluginId )
477 return KPluginInfo();
483 QString pluginId = _pluginId;
485 KConfigGroup config(KGlobal::config(),
"Plugins");
488 if ( !pluginId.startsWith( QLatin1String(
"kopete_" ) ) )
489 pluginId.prepend( QLatin1String(
"kopete_" ) );
491 if ( !infoForPluginId( pluginId ).isValid() )
494 config.writeEntry( pluginId + QLatin1String(
"Enabled" ), enabled );
502 return _kpmp->isAllPluginsLoaded;
508 #include "kopetepluginmanager.moc"
void allPluginsLoaded()
All plugins have been loaded by the plugin manager.
bool setPluginEnabled(const QString &name, bool enabled=true)
Enable a plugin.
PluginList loadedPlugins(const QString &category=QString()) const
Returns a list of all plugins that are actually loaded.
Plugin * loadPlugin(const QString &pluginId, PluginLoadMode mode=LoadSync)
Load a single plugin by plugin name.
void pluginLoaded(Kopete::Plugin *plugin)
Signals a new plugin has just been loaded.
static AccountManager * self()
Retrieve the instance of AccountManager.
void pluginUnloaded(const QString &pluginName)
Signals a plugin has just been unloaded.
QList< KPluginInfo > availablePlugins(const QString &category=QString()) const
Returns a list of all available plugins for the given category.
QString pluginId() const
Get the plugin id.
bool unloadPlugin(const QString &pluginName)
Unload the plugin specified by pluginName.
QList< Plugin * > PluginList
void loadAllPlugins()
Loads all the enabled plugins.
KPluginInfo pluginInfo(const Kopete::Plugin *plugin) const
Base class for all plugins or protocols.
void shutdown()
Shuts down the plugin manager on Kopete shutdown, but first unloads all plugins asynchronously.
bool isAllPluginsLoaded() const
This method check if all the plugins are loaded.
PluginLoadMode
Plugin loading mode.
Plugin * plugin(const QString &pluginName) const
Search by plugin name.
void protocolLoaded(Kopete::Protocol *protocol)
Signals a new protocol has just been loaded.