akregator/src

pluginmanager.cpp
1 /***************************************************************************
2 begin : 2004/03/12
3 copyright : (C) Mark Kretschmann
4 email : markey@web.de
5 ***************************************************************************/
6 
7 /***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "plugin.h"
17 #include "pluginmanager.h"
18 
19 #include <vector>
20 
21 #include <tqfile.h>
22 #include <tqstring.h>
23 
24 #include <klibloader.h>
25 #include <kdebug.h>
26 #include <tdelocale.h>
27 #include <tdemessagebox.h>
28 
29 using std::vector;
30 using Akregator::Plugin;
31 
32 namespace Akregator {
33 
34 vector<PluginManager::StoreItem>
35 PluginManager::m_store;
36 
37 
39 // PUBLIC INTERFACE
41 
42 TDETrader::OfferList
43 PluginManager::query( const TQString& constraint )
44 {
45  // Add versioning constraint
46  TQString
47  str = "[X-TDE-akregator-framework-version] == ";
48  str += TQString::number( FrameworkVersion );
49  str += " and ";
50  if (!constraint.stripWhiteSpace().isEmpty())
51  str += constraint + " and ";
52  str += "[X-TDE-akregator-rank] > 0";
53 
54  kdDebug() << "Plugin trader constraint: " << str << endl;
55 
56  return TDETrader::self()->query( "Akregator/Plugin", str );
57 }
58 
59 
60 Plugin*
61 PluginManager::createFromQuery( const TQString &constraint )
62 {
63  TDETrader::OfferList offers = query( constraint );
64 
65  if ( offers.isEmpty() ) {
66  kdWarning() << k_funcinfo << "No matching plugin found.\n";
67  return 0;
68  }
69 
70  // Select plugin with highest rank
71  int rank = 0;
72  uint current = 0;
73  for ( uint i = 0; i < offers.count(); i++ ) {
74  if ( offers[i]->property( "X-TDE-akregator-rank" ).toInt() > rank )
75  current = i;
76  }
77 
78  return createFromService( offers[current] );
79 }
80 
81 
82 Plugin*
83 PluginManager::createFromService( const KService::Ptr service )
84 {
85  kdDebug() << "Trying to load: " << service->library() << endl;
86 
87  //get the library loader instance
88  KLibLoader *loader = KLibLoader::self();
89  //try to load the specified library
90  KLibrary *lib = loader->globalLibrary( TQFile::encodeName( service->library() ) );
91 
92  if ( !lib ) {
93  KMessageBox::error( 0, i18n( "<p>KLibLoader could not load the plugin:<br/><i>%1</i></p>"
94  "<p>Error message:<br/><i>%2</i></p>" )
95  .arg( service->library() )
96  .arg( loader->lastErrorMessage() ) );
97  return 0;
98  }
99  //look up address of init function and cast it to pointer-to-function
100  Plugin* (*create_plugin)() = ( Plugin* (*)() ) lib->symbol( "create_plugin" );
101 
102  if ( !create_plugin ) {
103  kdWarning() << k_funcinfo << "create_plugin == NULL\n";
104  return 0;
105  }
106  //create plugin on the heap
107  Plugin* plugin = create_plugin();
108 
109  //put plugin into store
110  StoreItem item;
111  item.plugin = plugin;
112  item.library = lib;
113  item.service = service;
114  m_store.push_back( item );
115 
116  dump( service );
117  return plugin;
118 }
119 
120 
121 void
122 PluginManager::unload( Plugin* plugin )
123 {
124  vector<StoreItem>::iterator iter = lookupPlugin( plugin );
125 
126  if ( iter != m_store.end() ) {
127  delete (*iter).plugin;
128  kdDebug() << "Unloading library: "<< (*iter).service->library() << endl;
129  (*iter).library->unload();
130 
131  m_store.erase( iter );
132  }
133  else
134  kdWarning() << k_funcinfo << "Could not unload plugin (not found in store).\n";
135 }
136 
137 
138 KService::Ptr
139 PluginManager::getService( const Plugin* plugin )
140 {
141  if ( !plugin ) {
142  kdWarning() << k_funcinfo << "pointer == NULL\n";
143  return 0;
144  }
145 
146  //search plugin in store
147  vector<StoreItem>::const_iterator iter = lookupPlugin( plugin );
148 
149  if ( iter == m_store.end() )
150  kdWarning() << k_funcinfo << "Plugin not found in store.\n";
151 
152  return (*iter).service;
153 }
154 
155 
156 void
157 PluginManager::showAbout( const TQString &constraint )
158 {
159  TDETrader::OfferList offers = query( constraint );
160 
161  if ( offers.isEmpty() )
162  return;
163 
164  KService::Ptr s = offers.front();
165 
166  const TQString body = "<tr><td>%1</td><td>%2</td></tr>";
167 
168  TQString str = "<html><body><table width=\"100%\" border=\"1\">";
169 
170  str += body.arg( i18n( "Name" ), s->name() );
171  str += body.arg( i18n( "Library" ), s->library() );
172  str += body.arg( i18n( "Authors" ), s->property( "X-TDE-akregator-authors" ).toStringList().join( "\n" ) );
173  str += body.arg( i18n( "Email" ), s->property( "X-TDE-akregator-email" ).toStringList().join( "\n" ) );
174  str += body.arg( i18n( "Version" ), s->property( "X-TDE-akregator-version" ).toString() );
175  str += body.arg( i18n( "Framework Version" ), s->property( "X-TDE-akregator-framework-version" ).toString() );
176 
177  str += "</table></body></html>";
178 
179  KMessageBox::information( 0, str, i18n( "Plugin Information" ) );
180 }
181 
182 
183 void
184 PluginManager::dump( const KService::Ptr service )
185 {
186  kdDebug()
187  << "PluginManager Service Info:" << endl
188  << "---------------------------" << endl
189  << "name : " << service->name() << endl
190  << "library : " << service->library() << endl
191  << "desktopEntryPath : " << service->desktopEntryPath() << endl
192  << "X-TDE-akregator-plugintype : " << service->property( "X-TDE-akregator-plugintype" ).toString() << endl
193  << "X-TDE-akregator-name : " << service->property( "X-TDE-akregator-name" ).toString() << endl
194  << "X-TDE-akregator-authors : " << service->property( "X-TDE-akregator-authors" ).toStringList() << endl
195  << "X-TDE-akregator-rank : " << service->property( "X-TDE-akregator-rank" ).toString() << endl
196  << "X-TDE-akregator-version : " << service->property( "X-TDE-akregator-version" ).toString() << endl
197  << "X-TDE-akregator-framework-version: " << service->property( "X-TDE-akregator-framework-version" ).toString()
198  << endl;
199 
200 }
201 
202 
204 // PRIVATE INTERFACE
206 
207 vector<PluginManager::StoreItem>::iterator
208 PluginManager::lookupPlugin( const Plugin* plugin )
209 {
210  vector<StoreItem>::iterator iter;
211 
212  //search plugin pointer in store
213  vector<StoreItem>::const_iterator end;
214  for ( iter = m_store.begin(); iter != end; ++iter ) {
215  if ( (*iter).plugin == plugin )
216  break;
217  }
218 
219  return iter;
220 }
221 
222 } // namespace Akregator