blokkalpluginmanager.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "blokkalpluginmanager.h"
00021 #include "blokkalpluginmanager.moc"
00022
00023 #include "blokkalprotocol.h"
00024 #include "blokkalplugin.h"
00025 #include "blokkalui/editentryviewfactory.h"
00026 #include "blokkalui/browseentryviewfactory.h"
00027
00028 #include <kparts/componentfactory.h>
00029 #include <ktrader.h>
00030 #include <kdebug.h>
00031
00032 #include <qtimer.h>
00033
00034 #include <iostream>
00035
00036
00037 class Blokkal::PluginManagerPrivate {
00038 public:
00039 PluginManagerPrivate( void ):
00040 availablePlugins( KPluginInfo::fromServices( KServiceTypeTrader::self()->query( QString::fromLatin1( "Blokkal/Plugin" ) ) ) ),
00041 shuttingDown( FALSE )
00042 {}
00043
00044 KPluginInfo::List availablePlugins;
00045 QMap<KPluginInfo, Plugin *> infoPluginMap;
00046
00047 bool shuttingDown;
00048
00049 PluginManager instance;
00050
00057 KPluginInfo::List filterPlugins( const QString & serviceType )
00058 {
00059 if( availablePlugins.isEmpty() ) {
00060 return availablePlugins;
00061 }
00062
00063 KPluginInfo::List filteredPluginList;
00064 for( KPluginInfo::List::ConstIterator it = availablePlugins.begin();
00065 it != availablePlugins.end();
00066 ++it )
00067 {
00068 if( (*it).service()->serviceTypes().contains( serviceType ) ) {
00069 filteredPluginList.append( *it );
00070 }
00071 }
00072
00073 return filteredPluginList;
00074 }
00075 };
00076
00077 K_GLOBAL_STATIC( Blokkal::PluginManagerPrivate, _bpmp );
00078
00079 Blokkal::PluginManager::PluginManager( void ):
00080 QObject( 0 )
00081 {
00082 setObjectName( "PluginManger" );
00083 KGlobal::ref();
00084 }
00085
00086 Blokkal::PluginManager::~PluginManager( void )
00087 {
00088 }
00089
00090 Blokkal::PluginManager * Blokkal::PluginManager::self( void )
00091 {
00092
00093 return &_bpmp->instance;
00094 }
00095
00096 KPluginInfo::List Blokkal::PluginManager::availablePlugins( void ) const
00097 {
00098 return _bpmp->availablePlugins;
00099 }
00100
00101 KPluginInfo::List Blokkal::PluginManager::availableProtocols( void ) const
00102 {
00103 return _bpmp->filterPlugins( "Blokkal/Protocol" );
00104 }
00105
00106
00107 KPluginInfo::List Blokkal::PluginManager::availableEditEntryViewFactorys( void ) const
00108 {
00109 return _bpmp->filterPlugins( "Blokkal/EditEntryViewFactory" );
00110 }
00111
00112 Blokkal::Protocol * Blokkal::PluginManager::protocol( const QString & pluginName )
00113 {
00114 Blokkal::Plugin * plugin = this->loadPlugin( pluginName );
00115
00116 if( !plugin ) {
00117 return 0;
00118 }
00119
00120 KPluginInfo info = pluginInfo( plugin );
00121 if( info.service()->serviceTypes().contains( "Blokkal/Protocol" ) ) {
00122 return (Blokkal::Protocol*) plugin;
00123 }
00124
00125 kError() << pluginName << " does not provide service type Blokkal/Protocol";
00126 return 0 ;
00127 }
00128
00129
00130 Blokkal::Ui::EditEntryViewFactory * Blokkal::PluginManager::editEntryViewFactory( const QString & pluginName )
00131 {
00132 Blokkal::Plugin * plugin = loadPlugin( pluginName.isEmpty() ? "blokkal_eevp" : pluginName );
00133 if( !plugin ) {
00134 return 0;
00135 }
00136
00137 KPluginInfo info = pluginInfo( plugin );
00138 if( info.service()->serviceTypes().contains( "Blokkal/EditEntryViewFactory" ) ) {
00139 return (Blokkal::Ui::EditEntryViewFactory*) plugin;
00140 }
00141
00142 kError() << pluginName << " does not provide service type Blokkal/EditEntryViewFactory";
00143 return 0 ;
00144 }
00145
00146 Blokkal::Plugin * Blokkal::PluginManager::plugin( const QString & pluginName )
00147 {
00148 return loadPlugin( pluginName );
00149 }
00150
00151 KPluginInfo Blokkal::PluginManager::pluginInfo( const QString & pluginName ) const
00152 {
00153 for( KPluginInfo::List::ConstIterator it = _bpmp->availablePlugins.begin();
00154 it != _bpmp->availablePlugins.end();
00155 ++it )
00156 {
00157 if( (*it).pluginName() == pluginName ) {
00158 return *it;
00159 }
00160 }
00161
00162 return KPluginInfo();
00163 }
00164
00165 KPluginInfo Blokkal::PluginManager::pluginInfo( const Plugin * plugin ) const
00166 {
00167 if( !plugin ) {
00168 kError() << "called with 0 pointer!" << endl;
00169 }
00170
00171 if( _bpmp->infoPluginMap.isEmpty() ) {
00172 kError() << "trying to get plugin info while no plugins are loaded" << endl;
00173 return KPluginInfo();
00174 }
00175
00176
00177 KPluginInfo::List keys = _bpmp->infoPluginMap.keys();
00178 for( KPluginInfo::List::ConstIterator it = keys.begin();
00179 it != keys.end();
00180 ++it )
00181 {
00182
00183
00184 if( _bpmp->infoPluginMap[ *it ] == plugin ) {
00185 return *it;
00186 }
00187 }
00188
00189 kError() << "unable to find info for loaded plugin!" << endl;
00190 if( plugin ) {
00191 kError() << "Problem caused by: " << plugin->metaObject()->className() << endl;
00192 }
00193 return KPluginInfo();
00194 }
00195
00196 void Blokkal::PluginManager::unloadPlugin( const QString & pluginName )
00197 {
00198
00199 KPluginInfo info = pluginInfo( pluginName );
00200 if( !info.isValid() ) {
00201 kWarning() << "Trying to unload nonexistent plugin with name " << pluginName << endl;
00202 }
00203
00204 if( _bpmp->infoPluginMap.contains( info ) ) {
00205
00206
00207
00208
00209 _bpmp->infoPluginMap[ info ]->prepareToUnload();
00210 }
00211 }
00212
00213 void Blokkal::PluginManager::unloadAllPlugins( void )
00214 {
00215 for( QMap<KPluginInfo, Plugin *>::Iterator it = _bpmp->infoPluginMap.begin();
00216 it != _bpmp->infoPluginMap.end() ;
00217 )
00218 {
00219 QString pluginName = it.key().pluginName();
00220 ++it;
00221 unloadPlugin( pluginName );
00222 }
00223 }
00224
00225 void Blokkal::PluginManager::deletePlugin( Blokkal::Plugin * plugin )
00226 {
00227 QTimer::singleShot( 0, plugin, SLOT( deleteLater( void ) ) );
00228 }
00229
00230 Blokkal::Plugin * Blokkal::PluginManager::loadPlugin( const QString & pluginName )
00231 {
00232 KPluginInfo info = pluginInfo( pluginName );
00233 if( !info.isValid() ) {
00234 kError() << "No plugin found with name " << pluginName << endl;
00235 return 0;
00236 }
00237
00238 Blokkal::Plugin * plugin = 0;
00239 if( _bpmp->infoPluginMap.contains( info ) ) {
00240 plugin = _bpmp->infoPluginMap[ info ];
00241 return plugin;
00242 }
00243
00244 QString error;
00245 plugin = KServiceTypeTrader::createInstanceFromQuery<Blokkal::Plugin>( QString::fromLatin1( "Blokkal/Plugin" ), QString::fromLatin1( "[X-KDE-PluginInfo-Name]=='%1'" ).arg( pluginName ), this, QVariantList(), & error );
00246
00247 if( plugin ) {
00248 _bpmp->infoPluginMap.insert( info, plugin );
00249 connect( plugin, SIGNAL( readyToUnload( Blokkal::Plugin * ) ),
00250 this, SLOT( deletePlugin( Blokkal::Plugin * ) ) );
00251 connect( plugin, SIGNAL( destroyed ( QObject * ) ),
00252 this, SLOT( removePlugin( QObject * ) ) );
00253 emit pluginLoaded( plugin );
00254 return plugin;
00255 }
00256 else {
00257 kError() << "error loading plugin " << pluginName << endl;
00258 }
00259
00260 return plugin;
00261 }
00262
00263 void Blokkal::PluginManager::removePlugin( QObject * plugin )
00264 {
00265 if( _bpmp->infoPluginMap.isEmpty() ) {
00266 return;
00267 }
00268
00269 for( QMap<KPluginInfo, Plugin *>::Iterator it = _bpmp->infoPluginMap.begin();
00270 it != _bpmp->infoPluginMap.end();
00271 ++it )
00272 {
00273 if( it.value() == plugin ) {
00274 _bpmp->infoPluginMap.remove( it.key() );
00275 break;
00276 }
00277 }
00278
00279 if( _bpmp->shuttingDown && _bpmp->infoPluginMap.isEmpty() ) {
00280 KGlobal::deref();
00281 }
00282 }
00283
00284 void Blokkal::PluginManager::shutdown( void )
00285 {
00286 _bpmp->shuttingDown = TRUE;
00287 unloadAllPlugins();
00288 }
00289
00290 KPluginInfo::List Blokkal::PluginManager::availableBrowseEntryViewFactorys( void ) const
00291 {
00292 return _bpmp->filterPlugins( "Blokkal/BrowseEntryViewFactory" );
00293 }
00294
00295 Blokkal::Ui::BrowseEntryViewFactory * Blokkal::PluginManager::browseEntryViewFactory( const QString & pluginName )
00296 {
00297 Blokkal::Plugin * plugin = loadPlugin( pluginName.isEmpty() ? "blokkal_bevp" : pluginName );
00298 if( !plugin ) {
00299 return 0;
00300 }
00301
00302 KPluginInfo info = pluginInfo( plugin );
00303 if( info.service()->serviceTypes().contains( "Blokkal/BrowseEntryViewFactory" ) ) {
00304 return (Blokkal::Ui::BrowseEntryViewFactory*) plugin;
00305 }
00306
00307 kError() << pluginName << " does not provide service type Blokkal/BrowseEntryViewFactory";
00308 return 0 ;
00309 }