akregator/src

pluginmanager.cpp
1/***************************************************************************
2begin : 2004/03/12
3copyright : (C) Mark Kretschmann
4email : 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
29using std::vector;
30using Akregator::Plugin;
31
32namespace Akregator {
33
34vector<PluginManager::StoreItem>
35PluginManager::m_store;
36
37
39// PUBLIC INTERFACE
41
42TDETrader::OfferList
43PluginManager::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
60Plugin*
61PluginManager::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
82Plugin*
83PluginManager::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
121void
122PluginManager::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
138KService::Ptr
139PluginManager::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
156void
157PluginManager::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
183void
184PluginManager::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
207vector<PluginManager::StoreItem>::iterator
208PluginManager::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