pluginmanager.cpp
00001 /*************************************************************************** 00002 begin : 2004/03/12 00003 copyright : (C) Mark Kretschmann 00004 email : markey@web.de 00005 ***************************************************************************/ 00006 00007 /*************************************************************************** 00008 * * 00009 * This program is free software; you can redistribute it and/or modify * 00010 * it under the terms of the GNU General Public License as published by * 00011 * the Free Software Foundation; either version 2 of the License, or * 00012 * (at your option) any later version. * 00013 * * 00014 ***************************************************************************/ 00015 00016 #include "plugin.h" 00017 #include "pluginmanager.h" 00018 00019 #include <vector> 00020 00021 #include <tqfile.h> 00022 #include <tqstring.h> 00023 00024 #include <klibloader.h> 00025 #include <kdebug.h> 00026 #include <tdelocale.h> 00027 #include <tdemessagebox.h> 00028 00029 using std::vector; 00030 using Akregator::Plugin; 00031 00032 namespace Akregator { 00033 00034 vector<PluginManager::StoreItem> 00035 PluginManager::m_store; 00036 00037 00039 // PUBLIC INTERFACE 00041 00042 TDETrader::OfferList 00043 PluginManager::query( const TQString& constraint ) 00044 { 00045 // Add versioning constraint 00046 TQString 00047 str = "[X-TDE-akregator-framework-version] == "; 00048 str += TQString::number( FrameworkVersion ); 00049 str += " and "; 00050 if (!constraint.stripWhiteSpace().isEmpty()) 00051 str += constraint + " and "; 00052 str += "[X-TDE-akregator-rank] > 0"; 00053 00054 kdDebug() << "Plugin trader constraint: " << str << endl; 00055 00056 return TDETrader::self()->query( "Akregator/Plugin", str ); 00057 } 00058 00059 00060 Plugin* 00061 PluginManager::createFromQuery( const TQString &constraint ) 00062 { 00063 TDETrader::OfferList offers = query( constraint ); 00064 00065 if ( offers.isEmpty() ) { 00066 kdWarning() << k_funcinfo << "No matching plugin found.\n"; 00067 return 0; 00068 } 00069 00070 // Select plugin with highest rank 00071 int rank = 0; 00072 uint current = 0; 00073 for ( uint i = 0; i < offers.count(); i++ ) { 00074 if ( offers[i]->property( "X-TDE-akregator-rank" ).toInt() > rank ) 00075 current = i; 00076 } 00077 00078 return createFromService( offers[current] ); 00079 } 00080 00081 00082 Plugin* 00083 PluginManager::createFromService( const KService::Ptr service ) 00084 { 00085 kdDebug() << "Trying to load: " << service->library() << endl; 00086 00087 //get the library loader instance 00088 KLibLoader *loader = KLibLoader::self(); 00089 //try to load the specified library 00090 KLibrary *lib = loader->globalLibrary( TQFile::encodeName( service->library() ) ); 00091 00092 if ( !lib ) { 00093 KMessageBox::error( 0, i18n( "<p>KLibLoader could not load the plugin:<br/><i>%1</i></p>" 00094 "<p>Error message:<br/><i>%2</i></p>" ) 00095 .arg( service->library() ) 00096 .arg( loader->lastErrorMessage() ) ); 00097 return 0; 00098 } 00099 //look up address of init function and cast it to pointer-to-function 00100 Plugin* (*create_plugin)() = ( Plugin* (*)() ) lib->symbol( "create_plugin" ); 00101 00102 if ( !create_plugin ) { 00103 kdWarning() << k_funcinfo << "create_plugin == NULL\n"; 00104 return 0; 00105 } 00106 //create plugin on the heap 00107 Plugin* plugin = create_plugin(); 00108 00109 //put plugin into store 00110 StoreItem item; 00111 item.plugin = plugin; 00112 item.library = lib; 00113 item.service = service; 00114 m_store.push_back( item ); 00115 00116 dump( service ); 00117 return plugin; 00118 } 00119 00120 00121 void 00122 PluginManager::unload( Plugin* plugin ) 00123 { 00124 vector<StoreItem>::iterator iter = lookupPlugin( plugin ); 00125 00126 if ( iter != m_store.end() ) { 00127 delete (*iter).plugin; 00128 kdDebug() << "Unloading library: "<< (*iter).service->library() << endl; 00129 (*iter).library->unload(); 00130 00131 m_store.erase( iter ); 00132 } 00133 else 00134 kdWarning() << k_funcinfo << "Could not unload plugin (not found in store).\n"; 00135 } 00136 00137 00138 KService::Ptr 00139 PluginManager::getService( const Plugin* plugin ) 00140 { 00141 if ( !plugin ) { 00142 kdWarning() << k_funcinfo << "pointer == NULL\n"; 00143 return 0; 00144 } 00145 00146 //search plugin in store 00147 vector<StoreItem>::const_iterator iter = lookupPlugin( plugin ); 00148 00149 if ( iter == m_store.end() ) 00150 kdWarning() << k_funcinfo << "Plugin not found in store.\n"; 00151 00152 return (*iter).service; 00153 } 00154 00155 00156 void 00157 PluginManager::showAbout( const TQString &constraint ) 00158 { 00159 TDETrader::OfferList offers = query( constraint ); 00160 00161 if ( offers.isEmpty() ) 00162 return; 00163 00164 KService::Ptr s = offers.front(); 00165 00166 const TQString body = "<tr><td>%1</td><td>%2</td></tr>"; 00167 00168 TQString str = "<html><body><table width=\"100%\" border=\"1\">"; 00169 00170 str += body.arg( i18n( "Name" ), s->name() ); 00171 str += body.arg( i18n( "Library" ), s->library() ); 00172 str += body.arg( i18n( "Authors" ), s->property( "X-TDE-akregator-authors" ).toStringList().join( "\n" ) ); 00173 str += body.arg( i18n( "Email" ), s->property( "X-TDE-akregator-email" ).toStringList().join( "\n" ) ); 00174 str += body.arg( i18n( "Version" ), s->property( "X-TDE-akregator-version" ).toString() ); 00175 str += body.arg( i18n( "Framework Version" ), s->property( "X-TDE-akregator-framework-version" ).toString() ); 00176 00177 str += "</table></body></html>"; 00178 00179 KMessageBox::information( 0, str, i18n( "Plugin Information" ) ); 00180 } 00181 00182 00183 void 00184 PluginManager::dump( const KService::Ptr service ) 00185 { 00186 kdDebug() 00187 << "PluginManager Service Info:" << endl 00188 << "---------------------------" << endl 00189 << "name : " << service->name() << endl 00190 << "library : " << service->library() << endl 00191 << "desktopEntryPath : " << service->desktopEntryPath() << endl 00192 << "X-TDE-akregator-plugintype : " << service->property( "X-TDE-akregator-plugintype" ).toString() << endl 00193 << "X-TDE-akregator-name : " << service->property( "X-TDE-akregator-name" ).toString() << endl 00194 << "X-TDE-akregator-authors : " << service->property( "X-TDE-akregator-authors" ).toStringList() << endl 00195 << "X-TDE-akregator-rank : " << service->property( "X-TDE-akregator-rank" ).toString() << endl 00196 << "X-TDE-akregator-version : " << service->property( "X-TDE-akregator-version" ).toString() << endl 00197 << "X-TDE-akregator-framework-version: " << service->property( "X-TDE-akregator-framework-version" ).toString() 00198 << endl; 00199 00200 } 00201 00202 00204 // PRIVATE INTERFACE 00206 00207 vector<PluginManager::StoreItem>::iterator 00208 PluginManager::lookupPlugin( const Plugin* plugin ) 00209 { 00210 vector<StoreItem>::iterator iter; 00211 00212 //search plugin pointer in store 00213 vector<StoreItem>::const_iterator end; 00214 for ( iter = m_store.begin(); iter != end; ++iter ) { 00215 if ( (*iter).plugin == plugin ) 00216 break; 00217 } 00218 00219 return iter; 00220 } 00221 00222 } // namespace Akregator