-rw-r--r-- | libopie2/opiecore/opluginloader.cpp | 369 | ||||
-rw-r--r-- | libopie2/opiecore/opluginloader.h | 59 |
2 files changed, 395 insertions, 33 deletions
diff --git a/libopie2/opiecore/opluginloader.cpp b/libopie2/opiecore/opluginloader.cpp index b473cd7..2aca382 100644 --- a/libopie2/opiecore/opluginloader.cpp +++ b/libopie2/opiecore/opluginloader.cpp | |||
@@ -1,541 +1,878 @@ | |||
1 | /* | 1 | /* |
2 | * LGPLv2 or later | 2 | * LGPLv2 or later |
3 | * zecke@handhelds.org | 3 | * zecke@handhelds.org |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "opluginloader.h" | 6 | #include "opluginloader.h" |
7 | #include "oconfig.h" | 7 | #include "oconfig.h" |
8 | 8 | ||
9 | #include <qpe/qpeapplication.h> | 9 | #include <qpe/qpeapplication.h> |
10 | 10 | ||
11 | #include <qdir.h> | 11 | #include <qdir.h> |
12 | #include <qdict.h> | 12 | #include <qdict.h> |
13 | #include <qtl.h> | 13 | #include <qtl.h> |
14 | #include <qfile.h> | ||
14 | 15 | ||
15 | #include <stdlib.h> | 16 | #include <stdlib.h> |
16 | 17 | ||
17 | 18 | ||
18 | 19 | ||
19 | namespace Opie { | 20 | namespace Opie { |
20 | namespace Core { | 21 | namespace Core { |
21 | namespace Internal { | 22 | namespace Internal { |
22 | struct OPluginLibraryHolder { | 23 | struct OPluginLibraryHolder { |
23 | static OPluginLibraryHolder *self(); | 24 | static OPluginLibraryHolder *self(); |
24 | QLibrary *ref( const QString& ); | 25 | QLibrary *ref( const QString& ); |
25 | void deref( QLibrary* ); | 26 | void deref( QLibrary* ); |
26 | private: | 27 | private: |
27 | 28 | ||
28 | OPluginLibraryHolder(); | 29 | OPluginLibraryHolder(); |
29 | ~OPluginLibraryHolder(); | 30 | ~OPluginLibraryHolder(); |
30 | QDict<QLibrary> m_libs; | 31 | QDict<QLibrary> m_libs; |
31 | static OPluginLibraryHolder* m_self; | 32 | static OPluginLibraryHolder* m_self; |
32 | }; | 33 | }; |
33 | 34 | ||
34 | OPluginLibraryHolder* OPluginLibraryHolder::m_self = 0; | 35 | OPluginLibraryHolder* OPluginLibraryHolder::m_self = 0; |
35 | OPluginLibraryHolder* OPluginLibraryHolder::self() { | 36 | OPluginLibraryHolder* OPluginLibraryHolder::self() { |
36 | if ( !m_self ) | 37 | if ( !m_self ) |
37 | m_self = new OPluginLibraryHolder; | 38 | m_self = new OPluginLibraryHolder; |
38 | 39 | ||
39 | return m_self; | 40 | return m_self; |
40 | } | 41 | } |
41 | 42 | ||
42 | OPluginLibraryHolder::OPluginLibraryHolder() {} | 43 | OPluginLibraryHolder::OPluginLibraryHolder() {} |
43 | OPluginLibraryHolder::~OPluginLibraryHolder() {} | 44 | OPluginLibraryHolder::~OPluginLibraryHolder() {} |
44 | 45 | ||
45 | /* | 46 | /* |
46 | * We do simple ref counting... We will add the QLibrary again | 47 | * We do simple ref counting... We will add the QLibrary again |
47 | * and again to the dictionary and on deref we will pop and pop it | 48 | * and again to the dictionary and on deref we will pop and pop it |
48 | * until there are no more library and we will unload and delete the library | 49 | * until there are no more library and we will unload and delete the library |
49 | * luckily dlopen does some ref counting as well so we don't need | 50 | * luckily dlopen does some ref counting as well so we don't need |
50 | * to hack QPEApplication | 51 | * to hack QPEApplication |
51 | */ | 52 | */ |
52 | QLibrary* OPluginLibraryHolder::ref(const QString& str) { | 53 | QLibrary* OPluginLibraryHolder::ref(const QString& str) { |
53 | QLibrary *lib = m_libs[str]; | 54 | QLibrary *lib = m_libs[str]; |
54 | 55 | ||
55 | /* if not in the dict try to load it */ | 56 | /* if not in the dict try to load it */ |
56 | if ( !lib ) { | 57 | if ( !lib ) { |
57 | lib = new QLibrary( str, QLibrary::Immediately ); | 58 | lib = new QLibrary( str, QLibrary::Immediately ); |
58 | if ( !lib->isLoaded() ) { | 59 | if ( !lib->isLoaded() ) { |
59 | delete lib; | 60 | delete lib; |
60 | return 0l; | 61 | return 0l; |
61 | } | 62 | } |
62 | } | 63 | } |
63 | 64 | ||
64 | /* now refcount one up */ | 65 | /* now refcount one up */ |
65 | m_libs.insert( str, lib ); | 66 | m_libs.insert( str, lib ); |
66 | return lib; | 67 | return lib; |
67 | } | 68 | } |
68 | 69 | ||
69 | /* | 70 | /* |
70 | * 'unshadow' the items until we're the last then unload and delete | 71 | * 'unshadow' the items until we're the last then unload and delete |
71 | */ | 72 | */ |
72 | void OPluginLibraryHolder::deref( QLibrary* lib ) { | 73 | void OPluginLibraryHolder::deref( QLibrary* lib ) { |
73 | if ( !lib ) | 74 | if ( !lib ) |
74 | return; | 75 | return; |
75 | 76 | ||
76 | QString str = lib->library(); | 77 | QString str = lib->library(); |
77 | /* no need to check if the lib was inserted or such */ | 78 | /* no need to check if the lib was inserted or such */ |
78 | (void) m_libs.take( str ); | 79 | (void) m_libs.take( str ); |
79 | if ( !m_libs[str] ) { | 80 | if ( !m_libs[str] ) { |
80 | lib->unload(); | 81 | lib->unload(); |
81 | delete lib; | 82 | delete lib; |
82 | } | 83 | } |
83 | } | 84 | } |
84 | } | 85 | } |
85 | 86 | ||
86 | /** | 87 | /** |
87 | * We want values with 30,29,28 at the beginning of the list | 88 | * We want values with 30,29,28 at the beginning of the list |
88 | */ | 89 | */ |
89 | 90 | ||
90 | bool operator<( const OPluginItem& l, const OPluginItem& r ) { | 91 | bool operator<( const OPluginItem& l, const OPluginItem& r ) { |
91 | return l.position() > r.position(); | 92 | return l.position() > r.position(); |
92 | } | 93 | } |
93 | 94 | ||
94 | bool operator>( const OPluginItem& l, const OPluginItem& r ) { | 95 | bool operator>( const OPluginItem& l, const OPluginItem& r ) { |
95 | return l.position() < r.position(); | 96 | return l.position() < r.position(); |
96 | } | 97 | } |
97 | 98 | ||
98 | bool operator<=( const OPluginItem& l, const OPluginItem& r ) { | 99 | bool operator<=( const OPluginItem& l, const OPluginItem& r ) { |
99 | return l.position() >= r.position(); | 100 | return l.position() >= r.position(); |
100 | } | 101 | } |
101 | 102 | ||
102 | /** | 103 | /** |
103 | * \brief Creates an Empty OPluginItem | 104 | * \brief Creates an Empty OPluginItem |
104 | * | 105 | * |
105 | * create an empty pluginitem. Position is set to -1 and the | 106 | * create an empty pluginitem. Position is set to -1 and the |
106 | * other things are used with the default ctors | 107 | * other things are used with the default ctors |
107 | */ | 108 | */ |
108 | OPluginItem::OPluginItem() | 109 | OPluginItem::OPluginItem() |
109 | : m_pos( -1 ) { | 110 | : m_pos( -1 ) { |
110 | } | 111 | } |
111 | 112 | ||
112 | /** | 113 | /** |
114 | * @todo Create Internal name so we can have the plugin names translated. Or only for the gui? I'm not yet sure | ||
113 | * \brief Create an OPluginItem | 115 | * \brief Create an OPluginItem |
114 | * | 116 | * |
115 | * Create a Plugin Item with all information. | 117 | * Create a Plugin Item with all information. If you for some reasons |
118 | * need to create your own OPluginItems make sure that 'name' is always the same | ||
119 | * as it if used for positions and exclude list. | ||
116 | * | 120 | * |
117 | * @param name The if available translated Name | 121 | * @param name The if available translated Name |
118 | * @param path The path to the plugin | 122 | * @param path The path to the plugin must be absolute. |
123 | * @param b If the OPluginItem is enabled or not | ||
119 | * @param pos The position of the plugin if used for sorting | 124 | * @param pos The position of the plugin if used for sorting |
120 | * | 125 | * |
121 | */ | 126 | */ |
122 | OPluginItem::OPluginItem( const QString& name, const QString& path, int pos ) | 127 | OPluginItem::OPluginItem( const QString& name, const QString& path, bool b, int pos ) |
123 | : m_name( name ), m_path( path ), m_pos( pos ) { | 128 | : m_name( name ), m_path( path ), m_enabled( b ), m_pos( pos ) |
124 | } | 129 | {} |
125 | 130 | ||
126 | /** | 131 | /** |
127 | * \brief simple d'tor | 132 | * \brief simple d'tor |
128 | */ | 133 | */ |
129 | OPluginItem::~OPluginItem() { | 134 | OPluginItem::~OPluginItem() { |
130 | } | 135 | } |
131 | 136 | ||
132 | /** | 137 | /** |
138 | * \brief Test if this Item is Empty and does not represent a loadable plugin | ||
139 | * Test if a OPluginItem is empty. A OPluginItem is empty if name and path are empty | ||
140 | * ,pos equals -1 and the item is disabled | ||
141 | * | ||
142 | * @see QString::isEmpty() | ||
143 | * | ||
144 | */ | ||
145 | bool OPluginItem::isEmpty()const { | ||
146 | if ( m_pos != -1 ) return false; | ||
147 | if ( m_enabled ) return false; | ||
148 | if ( !m_name.isEmpty() ) return false; | ||
149 | if ( !m_path.isEmpty() ) return false; | ||
150 | |||
151 | return true; | ||
152 | } | ||
153 | |||
154 | /** | ||
155 | * \brief test equality | ||
133 | * operator to test equalness of two OPluginItem | 156 | * operator to test equalness of two OPluginItem |
134 | */ | 157 | */ |
135 | bool OPluginItem::operator==( const OPluginItem& r )const{ | 158 | bool OPluginItem::operator==( const OPluginItem& r )const{ |
136 | if ( m_pos != r.m_pos ) return false; | 159 | if ( m_pos != r.m_pos ) return false; |
137 | if ( m_name != r.m_name ) return false; | 160 | if ( m_enabled != r.m_enabled) return false; |
138 | if ( m_path != r.m_path ) return false; | 161 | if ( m_name != r.m_name ) return false; |
162 | if ( m_path != r.m_path ) return false; | ||
139 | return true; | 163 | return true; |
140 | } | 164 | } |
141 | 165 | ||
166 | /** | ||
167 | * \brief test non equality | ||
168 | * operator to test non-equalness of two OPluginItem | ||
169 | */ | ||
142 | bool OPluginItem::operator!=( const OPluginItem& r )const{ | 170 | bool OPluginItem::operator!=( const OPluginItem& r )const{ |
143 | return !( *this == r ); | 171 | return !( *this == r ); |
144 | } | 172 | } |
145 | 173 | ||
146 | /** | 174 | /** |
175 | * \brief returns the name of the plugin | ||
147 | * return the name of this Plugin | 176 | * return the name of this Plugin |
148 | */ | 177 | */ |
149 | QString OPluginItem::name()const { | 178 | QString OPluginItem::name()const { |
150 | return m_name; | 179 | return m_name; |
151 | } | 180 | } |
152 | 181 | ||
153 | /** | 182 | /** |
154 | * return the path of the plugin | 183 | * \brief return the path of the plugin |
155 | */ | 184 | */ |
156 | QString OPluginItem::path()const { | 185 | QString OPluginItem::path()const { |
157 | return m_path; | 186 | return m_path; |
158 | } | 187 | } |
159 | 188 | ||
189 | /** | ||
190 | * \brief Return if this item is enabled. | ||
191 | */ | ||
192 | bool OPluginItem::isEnabled()const { | ||
193 | return m_enabled; | ||
194 | } | ||
195 | |||
196 | /** | ||
197 | * \brief return the position of a plugin. | ||
198 | * return the position of the item | ||
199 | * -1 is the default value and means normally that the whole items are unsorted. | ||
200 | * Higher numbers belong to an upper position. With plugins with the postions 20,19,5,3 | ||
201 | * the item with pos 20 would be the first in the list returned by the OGenericPluginLoader | ||
202 | * | ||
203 | * @see OGenericPluginLoader::allAvailable | ||
204 | * @see OGenericPluginLoader::filtered | ||
205 | */ | ||
160 | int OPluginItem::position()const{ | 206 | int OPluginItem::position()const{ |
161 | return m_pos; | 207 | return m_pos; |
162 | } | 208 | } |
163 | 209 | ||
164 | /** | 210 | /** |
211 | * \brief set the name of a plugin | ||
165 | * Set the name of the Plugin Item | 212 | * Set the name of the Plugin Item |
166 | * @param name | 213 | * @param name |
167 | */ | 214 | */ |
168 | void OPluginItem::setName( const QString& name ) { | 215 | void OPluginItem::setName( const QString& name ) { |
169 | m_name = name; | 216 | m_name = name; |
170 | } | 217 | } |
171 | 218 | ||
172 | /** | 219 | /** |
173 | * Set the path of Plugin Item | 220 | * \brief set the path of a plugin |
221 | * Set the path of Plugin Item. The path must be absolute. | ||
174 | * @param name The path of the plugin | 222 | * @param name The path of the plugin |
175 | */ | 223 | */ |
176 | void OPluginItem::setPath( const QString& name ) { | 224 | void OPluginItem::setPath( const QString& name ) { |
177 | m_name = name; | 225 | m_name = name; |
178 | } | 226 | } |
179 | 227 | ||
180 | /** | 228 | /** |
229 | * \brief enable or disable the to load attribute | ||
230 | * Set the Enabled attribute. Such changes won't be saved. If you want to save it | ||
231 | * use a OPluginManager to configure your plugins manually or Opie::Ui::OPluginConfig | ||
232 | * for a graphical frontend. | ||
233 | * | ||
234 | * @param enabled Enable or Disable the Enabled Attribute | ||
235 | */ | ||
236 | void OPluginItem::setEnabled( bool enabled ) { | ||
237 | m_enabled = enabled; | ||
238 | } | ||
239 | |||
240 | /** | ||
241 | * \brief Set the position. | ||
181 | * Set the position | 242 | * Set the position |
182 | * @param pos The position | 243 | * @param pos The position |
244 | * | ||
245 | * @see position() | ||
183 | */ | 246 | */ |
184 | void OPluginItem::setPosition( int pos ) { | 247 | void OPluginItem::setPosition( int pos ) { |
185 | m_pos = pos; | 248 | m_pos = pos; |
186 | } | 249 | } |
187 | 250 | ||
188 | 251 | ||
189 | 252 | ||
190 | /** | 253 | /** |
191 | * \brief create a PluginLoader | 254 | * \brief create a PluginLoader |
192 | * | 255 | * |
193 | * Create a PluginLoader autoDelete is set to false | 256 | * Create a PluginLoader autoDelete is set to false |
194 | * | 257 | * |
195 | * \code | 258 | * \code |
196 | * Opie::Core::OGenericPluginLoader loader("myapp-plugin"); | 259 | * Opie::Core::OGenericPluginLoader loader("myapp-plugin"); |
197 | * Opie::Core::OPluginItem::List lst = loader.filtered(); | 260 | * Opie::Core::OPluginItem::List lst = loader.filtered(); |
198 | * for(Opie::Core::OPluginItem::List::Iterator it = lst.begin(); it!=lst.end();++it){ | 261 | * for(Opie::Core::OPluginItem::List::Iterator it = lst.begin(); it!=lst.end();++it){ |
199 | * MyIface* iface = static_cast<MyIface*>(loader.load(*it,IID_MyIface)); | 262 | * MyIface* iface = static_cast<MyIface*>(loader.load(*it,IID_MyIface)); |
200 | * } | 263 | * } |
201 | * \endcode | 264 | * \endcode |
202 | * | 265 | * |
203 | * \code | 266 | * \code |
204 | * Opie::Core::OGenericPluginLoader loader("myapp-plugin"); | 267 | * Opie::Core::OGenericPluginLoader loader("myapp-plugin"); |
205 | * Opie::Core::OPluginItem::List lst = loader.filtered(); | 268 | * Opie::Core::OPluginItem::List lst = loader.filtered(); |
206 | * for(Opie::Core::OPluginItem::List::Iterator it = lst.begin(); it!=lst.end();++it){ | 269 | * for(Opie::Core::OPluginItem::List::Iterator it = lst.begin(); it!=lst.end();++it){ |
207 | * MyIface* iface = static_cast<MyIface*>(loader.load(*it,IID_MyIface)); | 270 | * MyIface* iface = static_cast<MyIface*>(loader.load(*it,IID_MyIface)); |
208 | * } | 271 | * } |
209 | * ... | 272 | * ... |
210 | * loader.clear(); | 273 | * loader.clear(); |
211 | * | 274 | * |
212 | * \endcode | 275 | * \endcode |
213 | * | 276 | * |
214 | * @param name The name of the plugin directory. | 277 | * @param name The name of the plugin directory. |
215 | * @param isSorted Tell the PluginLoader if your Plugins are sorted | 278 | * @param isSorted Tell the PluginLoader if your Plugins are sorted |
216 | */ | 279 | */ |
217 | OGenericPluginLoader::OGenericPluginLoader( const QString& name, bool isSorted) | 280 | OGenericPluginLoader::OGenericPluginLoader( const QString& name, bool isSorted) |
218 | : m_dir( name ), m_autoDelete( false ), m_isSafeMode( false ), | 281 | : m_dir( name ), m_autoDelete( false ), m_isSafeMode( false ), |
219 | m_isSorted( isSorted ) | 282 | m_isSorted( isSorted ) |
220 | { | 283 | { |
221 | setPluginDir( QPEApplication::qpeDir() + "/plugins/"+name ); | 284 | setPluginDir( QPEApplication::qpeDir() + "/plugins/"+name ); |
222 | readConfig(); | 285 | readConfig(); |
223 | } | 286 | } |
224 | 287 | ||
225 | 288 | ||
226 | /** | 289 | /** |
290 | * \brief simple d'tor that cleans up depending on autoDelete | ||
291 | * | ||
227 | * calls clear if autoDelete is true. This will release all interfaces | 292 | * calls clear if autoDelete is true. This will release all interfaces |
228 | * and remove the library from this process if the refcount falls to zero | 293 | * and remove the library from this process if the refcount falls to zero |
229 | */ | 294 | */ |
230 | OGenericPluginLoader::~OGenericPluginLoader() { | 295 | OGenericPluginLoader::~OGenericPluginLoader() { |
231 | if ( m_autoDelete ) | 296 | if ( m_autoDelete ) |
232 | clear(); | 297 | clear(); |
233 | } | 298 | } |
234 | 299 | ||
235 | /** | 300 | /** |
301 | * \brief Enable or disable autoDelete on destruction | ||
302 | * | ||
236 | * enable autoDelete. This will call clear on the d'tor | 303 | * enable autoDelete. This will call clear on the d'tor |
237 | * | 304 | * |
238 | * @see ~OGenericPluginLoader | 305 | * @see ~OGenericPluginLoader |
239 | * @see clear() | 306 | * @see clear() |
240 | */ | 307 | */ |
241 | void OGenericPluginLoader::setAutoDelete( bool t ) { | 308 | void OGenericPluginLoader::setAutoDelete( bool t ) { |
242 | m_autoDelete = t; | 309 | m_autoDelete = t; |
243 | } | 310 | } |
244 | 311 | ||
245 | /** | 312 | /** |
246 | * see if autoDelet is enabled | 313 | * \brief See if autoDelete is enabled. |
247 | */ | 314 | */ |
248 | bool OGenericPluginLoader::autoDelete()const{ | 315 | bool OGenericPluginLoader::autoDelete()const{ |
249 | return m_autoDelete; | 316 | return m_autoDelete; |
250 | } | 317 | } |
251 | 318 | ||
252 | /** | 319 | /** |
320 | * \brief unload all loaded Plugins | ||
321 | * | ||
253 | * This will unload all returned QUnknownInterfaces by load. Unload | 322 | * This will unload all returned QUnknownInterfaces by load. Unload |
254 | * will be called. | 323 | * will be called. |
255 | */ | 324 | */ |
256 | void OGenericPluginLoader::clear() { | 325 | void OGenericPluginLoader::clear() { |
257 | QPtrDictIterator<QLibrary> it( m_library ); | 326 | QPtrDictIterator<QLibrary> it( m_library ); |
258 | for ( ;it.current(); ) | 327 | for ( ;it.current(); ) |
259 | unload( static_cast<QUnknownInterface*>( it.currentKey() ) ); | 328 | unload( static_cast<QUnknownInterface*>( it.currentKey() ) ); |
260 | } | 329 | } |
261 | 330 | ||
262 | /** | 331 | /** |
332 | * \brief unload the Plugin and the accompanied Resources. | ||
333 | * | ||
263 | * This will take the iface from the internal QPtrDict, Release it, | 334 | * This will take the iface from the internal QPtrDict, Release it, |
264 | * and deref the libray used. | 335 | * and deref the libray used. |
265 | * The visibility depends on the QPtrDict. | 336 | * The visibility depends on the QPtrDict. |
266 | * @see QPtrDict::insert | 337 | * @see QPtrDict::insert |
267 | */ | 338 | */ |
268 | void OGenericPluginLoader::unload( QUnknownInterface* iface ) { | 339 | void OGenericPluginLoader::unload( QUnknownInterface* iface ) { |
269 | if ( !iface ) | 340 | if ( !iface ) |
270 | return; | 341 | return; |
271 | 342 | ||
272 | iface->release(); | 343 | iface->release(); |
273 | Internal::OPluginLibraryHolder::self()->deref( m_library.take( iface ) ); | 344 | Internal::OPluginLibraryHolder::self()->deref( m_library.take( iface ) ); |
274 | } | 345 | } |
275 | 346 | ||
276 | /** | 347 | /** |
348 | * \brief The name of the plugins. | ||
349 | * | ||
350 | * Return the name/type you specified in the constructor. | ||
351 | * This is at least used by the OPluginManager to find the right config | ||
352 | */ | ||
353 | QString OGenericPluginLoader::name()const { | ||
354 | return m_dir; | ||
355 | } | ||
356 | |||
357 | |||
358 | /** | ||
359 | * \brief See if loading of a plugin segfaulted | ||
277 | * This tells you | 360 | * This tells you |
278 | * if by previous tries to load, loading crashed your application. | 361 | * if by previous tries to load, loading crashed your application. |
279 | * If isInSafeMode you can use the GUI to configure the plugins prior to loading | 362 | * If isInSafeMode you can use the GUI to configure the plugins prior to loading |
280 | * | 363 | * |
281 | * @return true if prior loading failed | 364 | * @return true if prior loading failed |
282 | */ | 365 | */ |
283 | bool OGenericPluginLoader::isInSafeMode()const { | 366 | bool OGenericPluginLoader::isInSafeMode()const { |
284 | return m_isSafeMode; | 367 | return m_isSafeMode; |
285 | } | 368 | } |
286 | 369 | ||
287 | 370 | ||
288 | /** | 371 | /** |
372 | * \brief Return all Plugins found in the plugins dirs. | ||
289 | * Return the list of all available plugins. This will go through all plugin | 373 | * Return the list of all available plugins. This will go through all plugin |
290 | * directories and search for your type of plugins ( by subdir ) | 374 | * directories and search for your type of plugins ( by subdir ) |
291 | * | 375 | * |
292 | * @param sorted Tell if you want to have the positions sorted. This only makes sense if you | 376 | * @param sorted Tell if you want to have the positions sorted. This only makes sense if you |
293 | */ | 377 | */ |
294 | OPluginItem::List OGenericPluginLoader::allAvailable( bool sorted )const { | 378 | OPluginItem::List OGenericPluginLoader::allAvailable( bool sorted )const { |
295 | OPluginItem::List lst; | 379 | OPluginItem::List lst; |
296 | for ( QStringList::ConstIterator it = m_plugDirs.begin(); it != m_plugDirs.end(); ++it ) | 380 | for ( QStringList::ConstIterator it = m_plugDirs.begin(); it != m_plugDirs.end(); ++it ) |
297 | lst += plugins( *it, sorted, false ); | 381 | lst += plugins( *it, sorted, false ); |
298 | 382 | ||
299 | if ( sorted ) | 383 | if ( sorted ) |
300 | qHeapSort( lst ); | 384 | qHeapSort( lst ); |
301 | return lst; | 385 | return lst; |
302 | } | 386 | } |
303 | 387 | ||
304 | /** | 388 | /** |
389 | * \brief Return only the enabled plugins | ||
305 | * Return only activated plugins. | 390 | * Return only activated plugins. |
306 | * | 391 | * |
307 | * @param sorted If the list should be sorted | 392 | * @param sorted If the list should be sorted |
308 | */ | 393 | */ |
309 | OPluginItem::List OGenericPluginLoader::filtered( bool sorted )const { | 394 | OPluginItem::List OGenericPluginLoader::filtered( bool sorted )const { |
310 | OPluginItem::List lst; | 395 | OPluginItem::List lst; |
311 | for ( QStringList::ConstIterator it = m_plugDirs.begin(); it != m_plugDirs.end(); ++it ) | 396 | for ( QStringList::ConstIterator it = m_plugDirs.begin(); it != m_plugDirs.end(); ++it ) |
312 | lst += plugins( *it, sorted, true ); | 397 | lst += plugins( *it, sorted, true ); |
313 | 398 | ||
314 | if ( sorted ) | 399 | if ( sorted ) |
315 | qHeapSort( lst ); | 400 | qHeapSort( lst ); |
316 | return lst; | 401 | return lst; |
317 | } | 402 | } |
318 | 403 | ||
319 | 404 | ||
320 | /** | 405 | /** |
406 | * \brief Load a OPluginItem for the specified interface | ||
407 | * This will open the resource of the OPluginItem::path() and then will query | ||
408 | * if the Interface specified in the uuid is available and then will manage the | ||
409 | * resource and Interface. | ||
410 | * | ||
411 | * @param item The OPluginItem that should be loaded | ||
412 | * @param uuid The Interface to query for | ||
321 | * | 413 | * |
414 | * @return Either 0 in case of failure or the Plugin as QUnknownInterface* | ||
322 | */ | 415 | */ |
323 | QUnknownInterface* OGenericPluginLoader::load( const OPluginItem& item, const QUuid& uuid) { | 416 | QUnknownInterface* OGenericPluginLoader::load( const OPluginItem& item, const QUuid& uuid) { |
324 | /* | 417 | /* |
325 | * Check if there could be a library | 418 | * Check if there could be a library |
326 | */ | 419 | */ |
327 | QString pa = item.path(); | 420 | QString pa = item.path(); |
328 | if ( pa.isEmpty() ) | 421 | if ( pa.isEmpty() ) |
329 | return 0l; | 422 | return 0l; |
330 | 423 | ||
331 | /* | 424 | /* |
332 | * See if we get a library | 425 | * See if we get a library |
333 | * return if we've none | 426 | * return if we've none |
334 | */ | 427 | */ |
335 | setSafeMode( pa, true ); | 428 | setSafeMode( pa, true ); |
336 | QLibrary *lib = Internal::OPluginLibraryHolder::self()->ref( pa ); | 429 | QLibrary *lib = Internal::OPluginLibraryHolder::self()->ref( pa ); |
337 | if ( !lib ) { | 430 | if ( !lib ) { |
338 | setSafeMode(); | 431 | setSafeMode(); |
339 | return 0l; | 432 | return 0l; |
340 | } | 433 | } |
341 | 434 | ||
342 | /** | 435 | /** |
343 | * try to load the plugin and just in case initialize the pointer to a pointer again | 436 | * try to load the plugin and just in case initialize the pointer to a pointer again |
344 | */ | 437 | */ |
345 | QUnknownInterface* iface=0; | 438 | QUnknownInterface* iface=0; |
346 | if ( lib->queryInterface( uuid, &iface ) == QS_OK ) { | 439 | if ( lib->queryInterface( uuid, &iface ) == QS_OK ) { |
347 | installTranslators(pa.left( pa.find("."))); | 440 | installTranslators(pa.left( pa.find("."))); |
348 | m_library.insert( iface, lib ); | 441 | m_library.insert( iface, lib ); |
349 | }else | 442 | }else |
350 | iface = 0; | 443 | iface = 0; |
351 | 444 | ||
352 | setSafeMode(); | 445 | setSafeMode(); |
353 | 446 | ||
354 | return iface; | 447 | return iface; |
355 | } | 448 | } |
356 | 449 | ||
357 | /** | 450 | /** |
358 | * @internal and reads in the safe mode | 451 | * @internal and reads in the safe mode |
359 | */ | 452 | */ |
360 | void OGenericPluginLoader::readConfig() { | 453 | void OGenericPluginLoader::readConfig() { |
361 | /* read the config for SafeMode */ | 454 | |
455 | |||
456 | /* read the config for SafeMode */ | ||
362 | OConfig conf( m_dir + "-odpplugins" ); | 457 | OConfig conf( m_dir + "-odpplugins" ); |
363 | conf.setGroup( "General" ); | 458 | conf.setGroup( "General" ); |
364 | m_isSafeMode = conf.readBoolEntry( "SafeMode", false ); | 459 | m_isSafeMode = conf.readBoolEntry( "SafeMode", false ); |
365 | } | 460 | } |
366 | 461 | ||
367 | /** | 462 | /** |
368 | * Enter or leave SafeMode | 463 | * @internal Enter or leave SafeMode |
369 | */ | 464 | */ |
370 | void OGenericPluginLoader::setSafeMode(const QString& str, bool b) { | 465 | void OGenericPluginLoader::setSafeMode(const QString& str, bool b) { |
371 | OConfig conf( m_dir + "-odpplugins" ); | 466 | OConfig conf( m_dir + "-odpplugins" ); |
372 | conf.setGroup( "General" ); | 467 | conf.setGroup( "General" ); |
373 | conf.writeEntry( "SafeMode", b ); | 468 | conf.writeEntry( "SafeMode", b ); |
374 | conf.writeEntry( "CrashedPlugin", str ); | 469 | conf.writeEntry( "CrashedPlugin", str ); |
375 | } | 470 | } |
376 | 471 | ||
377 | /** | 472 | /** |
378 | * @internal | 473 | * @internal |
379 | * | 474 | * |
380 | * Set the List of Plugin Dirs to lst. Currently only QPEApplication::qpeDir()+"/plugins/"+mytype | 475 | * Set the List of Plugin Dirs to lst. Currently only QPEApplication::qpeDir()+"/plugins/"+mytype |
381 | * is used as plugin dir | 476 | * is used as plugin dir |
382 | */ | 477 | */ |
383 | void OGenericPluginLoader::setPluginDirs( const QStringList& lst ) { | 478 | void OGenericPluginLoader::setPluginDirs( const QStringList& lst ) { |
384 | m_plugDirs = lst; | 479 | m_plugDirs = lst; |
385 | } | 480 | } |
386 | 481 | ||
387 | /** | 482 | /** |
388 | * | 483 | * |
389 | * @internal | 484 | * @internal |
390 | * Set the Plugin Dir to str. Str will be the only element in the list of plugin dirs | 485 | * Set the Plugin Dir to str. Str will be the only element in the list of plugin dirs |
391 | */ | 486 | */ |
392 | void OGenericPluginLoader::setPluginDir( const QString& str) { | 487 | void OGenericPluginLoader::setPluginDir( const QString& str) { |
393 | m_plugDirs.clear(); | 488 | m_plugDirs.clear(); |
394 | m_plugDirs.append( str ); | 489 | m_plugDirs.append( str ); |
395 | } | 490 | } |
396 | 491 | ||
397 | 492 | ||
398 | /** | 493 | /** |
399 | * @internal | 494 | * @internal |
400 | */ | 495 | */ |
401 | bool OGenericPluginLoader::isSorted()const{ | 496 | bool OGenericPluginLoader::isSorted()const{ |
402 | return m_isSorted; | 497 | return m_isSorted; |
403 | } | 498 | } |
404 | 499 | ||
405 | /* | 500 | /* |
406 | * make libfoo.so.1.0.0 -> foo on UNIX | 501 | * make libfoo.so.1.0.0 -> foo on UNIX |
407 | * make libfoo.dylib -> foo on MAC OS X Unix | 502 | * make libfoo.dylib -> foo on MAC OS X Unix |
408 | * windows is obviously missing | 503 | * windows is obviously missing |
409 | */ | 504 | */ |
410 | /** | 505 | /** |
411 | * @internal | 506 | * @internal |
412 | */ | 507 | */ |
413 | QString OGenericPluginLoader::unlibify( const QString& str ) { | 508 | QString OGenericPluginLoader::unlibify( const QString& str ) { |
414 | QString st = str.mid( str.find( "lib" )+3 ); | 509 | QString st = str.mid( str.find( "lib" )+3 ); |
415 | #ifdef Q_OS_MACX | 510 | #ifdef Q_OS_MACX |
416 | return st.left( st.findRev( ".dylib" ) ); | 511 | return st.left( st.findRev( ".dylib" ) ); |
417 | #else | 512 | #else |
418 | return st.left( st.findRev( ".so" ) ); | 513 | return st.left( st.findRev( ".so" ) ); |
419 | #endif | 514 | #endif |
420 | } | 515 | } |
421 | 516 | ||
422 | /** | 517 | /** |
423 | * Return a List of Plugins for a dir and add positions and remove disabled. | 518 | * @internal |
519 | * | ||
520 | * \brief method to return available plugins. Internal and for reeimplementations | ||
521 | * | ||
522 | *Return a List of Plugins for a dir and add positions and remove disabled. | ||
424 | * If a plugin is on the excluded list assign position -2 | 523 | * If a plugin is on the excluded list assign position -2 |
425 | * | 524 | * |
426 | * @param dir The dir to look in | 525 | * @param dir The dir to look in |
427 | * @param sorted Should positions be read? | 526 | * @param sorted Should positions be read? |
428 | * @param disabled Remove excluded from the list | 527 | * @param disabled Remove excluded from the list |
429 | */ | 528 | */ |
430 | OPluginItem::List OGenericPluginLoader::plugins( const QString& _dir, bool sorted, bool disabled )const { | 529 | OPluginItem::List OGenericPluginLoader::plugins( const QString& _dir, bool sorted, bool disabled )const { |
431 | #ifdef Q_OS_MACX | 530 | #ifdef Q_OS_MACX |
432 | QDir dir( _dir, "lib*.dylib" ); | 531 | QDir dir( _dir, "lib*.dylib" ); |
433 | #else | 532 | #else |
434 | QDir dir( _dir, "lib*.so" ); | 533 | QDir dir( _dir, "lib*.so" ); |
435 | #endif | 534 | #endif |
436 | 535 | ||
437 | OPluginItem::List lst; | 536 | OPluginItem::List lst; |
438 | 537 | ||
439 | /* | 538 | /* |
440 | * get excluded list and then iterate over them | 539 | * get excluded list and then iterate over them |
441 | * Excluded list contains the name | 540 | * Excluded list contains the name |
442 | * Position is a list with 'name.pos.name.pos.name.pos' | 541 | * Position is a list with 'name.pos.name.pos.name.pos' |
443 | * | 542 | * |
444 | * For the look up we will create two QMap<QString,pos> | 543 | * For the look up we will create two QMap<QString,pos> |
445 | */ | 544 | */ |
446 | QMap<QString, int> positionMap; | 545 | QMap<QString, int> positionMap; |
447 | QMap<QString, int> excludedMap; | 546 | QMap<QString, int> excludedMap; |
448 | 547 | ||
449 | 548 | ||
450 | OConfig cfg( m_dir+"odpplugins" ); | 549 | OConfig cfg( m_dir+"odpplugins" ); |
451 | cfg.setGroup( _dir ); | 550 | cfg.setGroup( _dir ); |
452 | 551 | ||
453 | 552 | ||
454 | QStringList excludes = cfg.readListEntry( "Excluded", ',' ); | 553 | QStringList excludes = cfg.readListEntry( "Excluded", ',' ); |
455 | for ( QStringList::Iterator it = excludes.begin(); it != excludes.end(); ++it ) | 554 | for ( QStringList::Iterator it = excludes.begin(); it != excludes.end(); ++it ) |
456 | excludedMap.insert( *it, -2 ); | 555 | excludedMap.insert( *it, -2 ); |
457 | 556 | ||
458 | if ( m_isSorted ) { | 557 | if ( m_isSorted ) { |
459 | QStringList pos = cfg.readListEntry( "Positions", '.' ); | 558 | QStringList pos = cfg.readListEntry( "Positions", '.' ); |
460 | QStringList::Iterator it = pos.begin(); | 559 | QStringList::Iterator it = pos.begin(); |
461 | while ( it != pos.end() ) | 560 | while ( it != pos.end() ) |
462 | positionMap.insert( *it++, (*it++).toInt() ); | 561 | positionMap.insert( *it++, (*it++).toInt() ); |
463 | } | 562 | } |
464 | 563 | ||
465 | 564 | ||
466 | 565 | ||
467 | 566 | ||
468 | QStringList list = dir.entryList(); | 567 | QStringList list = dir.entryList(); |
469 | QStringList::Iterator it; | 568 | QStringList::Iterator it; |
470 | for (QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { | 569 | for (QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { |
471 | QString str = unlibify( *it ); | 570 | QString str = unlibify( *it ); |
472 | OPluginItem item( str, _dir + "/" + *it ); | 571 | OPluginItem item( str, _dir + "/" + *it ); |
473 | 572 | ||
474 | bool ex = excludedMap.contains( str ); | 573 | bool ex = excludedMap.contains( str ); |
475 | /* | 574 | /* |
476 | * if disabled but we should show all assign a -2 | 575 | * if disabled but we should show all mark it as disabled |
477 | * else continue because we don't want to add the item | 576 | * else continue because we don't want to add the item |
478 | * else if sorted we assign the right position | 577 | * else if sorted we assign the right position |
479 | */ | 578 | */ |
480 | if ( ex && !disabled) | 579 | if ( ex && !disabled) |
481 | item.setPosition( -2 ); | 580 | item.setEnabled( false ); |
482 | else if ( ex && disabled ) | 581 | else if ( ex && disabled ) |
483 | continue; | 582 | continue; |
484 | else if ( sorted ) | 583 | else if ( sorted ) |
485 | item.setPosition( positionMap[str] ); | 584 | item.setPosition( positionMap[str] ); |
486 | 585 | ||
487 | lst.append( item ); | 586 | lst.append( item ); |
488 | } | 587 | } |
489 | 588 | ||
490 | return lst; | 589 | return lst; |
491 | } | 590 | } |
492 | 591 | ||
493 | /** | 592 | /** |
494 | * @internal generate a list of languages from $LANG | 593 | * @internal generate a list of languages from $LANG |
495 | */ | 594 | */ |
496 | QStringList OGenericPluginLoader::languageList() { | 595 | QStringList OGenericPluginLoader::languageList() { |
497 | if ( m_languages.isEmpty() ) { | 596 | if ( m_languages.isEmpty() ) { |
498 | /* | 597 | /* |
499 | * be_BY.CP1251 We will add, be_BY.CP1251,be_BY,be | 598 | * be_BY.CP1251 We will add, be_BY.CP1251,be_BY,be |
500 | * to our list of languages. | 599 | * to our list of languages. |
501 | */ | 600 | */ |
502 | QString str = ::getenv( "LANG" ); | 601 | QString str = ::getenv( "LANG" ); |
503 | m_languages += str; | 602 | m_languages += str; |
504 | int pos = str.find( '.' ); | 603 | int pos = str.find( '.' ); |
505 | 604 | ||
506 | if ( pos > 0 ) | 605 | if ( pos > 0 ) |
507 | m_languages += str.left( pos ); | 606 | m_languages += str.left( pos ); |
508 | 607 | ||
509 | int n_pos = str.find( '_' ); | 608 | int n_pos = str.find( '_' ); |
510 | if ( pos > 0 && n_pos >= pos ) | 609 | if ( pos > 0 && n_pos >= pos ) |
511 | m_languages += str.left( n_pos ); | 610 | m_languages += str.left( n_pos ); |
512 | 611 | ||
513 | } | 612 | } |
514 | return m_languages; | 613 | return m_languages; |
515 | } | 614 | } |
516 | 615 | ||
616 | /** | ||
617 | * @internal | ||
618 | * Tries to install languages using the languageList for the type | ||
619 | */ | ||
517 | void OGenericPluginLoader::installTranslators(const QString& type) { | 620 | void OGenericPluginLoader::installTranslators(const QString& type) { |
518 | QStringList lst = languageList(); | 621 | QStringList lst = languageList(); |
519 | 622 | ||
520 | /* | 623 | /* |
521 | * for each language and maybe later for each language dir... | 624 | * for each language and maybe later for each language dir... |
522 | * try to load a Translator | 625 | * try to load a Translator |
523 | */ | 626 | */ |
524 | for ( QStringList::Iterator it = lst.begin(); it != lst.end(); ++it ) { | 627 | for ( QStringList::Iterator it = lst.begin(); it != lst.end(); ++it ) { |
525 | QTranslator* trans = new QTranslator( qApp ); | 628 | QTranslator* trans = new QTranslator( qApp ); |
526 | QString tfn = QPEApplication::qpeDir()+"/i18n/" + *it + "/" + type + ".qm" ; | 629 | QString tfn = QPEApplication::qpeDir()+"/i18n/" + *it + "/" + type + ".qm" ; |
527 | 630 | ||
528 | /* | 631 | /* |
529 | * If loaded then install else clean up and don't leak | 632 | * If loaded then install else clean up and don't leak |
530 | */ | 633 | */ |
531 | if ( trans->load( tfn ) ) | 634 | if ( trans->load( tfn ) ) |
532 | qApp->installTranslator( trans ); | 635 | qApp->installTranslator( trans ); |
533 | else | 636 | else |
534 | delete trans; | 637 | delete trans; |
535 | } | 638 | } |
536 | } | 639 | } |
537 | 640 | ||
641 | /** | ||
642 | * \brief Simple c'tor. | ||
643 | * | ||
644 | * Simple C'tor same as the one of the base class. Additional this | ||
645 | * class can cast for you if you nee it. | ||
646 | * | ||
647 | * | ||
648 | * @param name The name of your plugin class | ||
649 | * @param sorted If plugins are sorted | ||
650 | * | ||
651 | * @see OGenericPluginLoader | ||
652 | */ | ||
653 | OPluginLoader::OPluginLoader( const QString& name, bool sorted ) | ||
654 | : OGenericPluginLoader( name, sorted ) | ||
655 | { | ||
656 | } | ||
657 | |||
658 | /** | ||
659 | * d'tor | ||
660 | * @see OGenericPluginLoader::~OGenericPluginLoader | ||
661 | */ | ||
662 | OPluginLoader::~OPluginLoader() { | ||
663 | } | ||
664 | |||
665 | /** | ||
666 | * \brief C'Tor using a OGenericPluginLoader | ||
667 | * The C'tor. Pass your OGenericPluginLoader to manage | ||
668 | * OGenericPluginLoader::allAvailable plugins. | ||
669 | * | ||
670 | * | ||
671 | * @param loader A Pointer to your OGenericPluginLoader | ||
672 | * @param name The name | ||
673 | */ | ||
674 | OPluginManager::OPluginManager( OGenericPluginLoader* loader) | ||
675 | : m_loader( loader ) | ||
676 | { | ||
677 | } | ||
678 | |||
679 | /** | ||
680 | * \brief Overloaded c'tor using a List of Plugins and a type name | ||
681 | * Overloaded Constructor to work with a 'Type' of plugins | ||
682 | * and a correspending list of those. In this case calling load | ||
683 | * is a no operation. | ||
684 | * | ||
685 | * @param name The name of your plugin ('today','inputmethods','applets') | ||
686 | * @param lst A List with plugins of your type to manage | ||
687 | * @param isSorted If the List should be treated sorted | ||
688 | */ | ||
689 | OPluginManager::OPluginManager( const QString& name, const OPluginItem::List& lst, bool isSorted) | ||
690 | : m_loader( 0l ), m_cfgName( name ), m_plugins( lst ), m_isSorted( isSorted ) | ||
691 | { | ||
692 | } | ||
693 | |||
694 | /** | ||
695 | * \brief A simple d'tor | ||
696 | */ | ||
697 | OPluginManager::~OPluginManager() { | ||
698 | } | ||
699 | |||
700 | /** | ||
701 | * \brief Return the OPluginItem where loading is likely to have crashed on. | ||
538 | 702 | ||
703 | * Return the Item that made the OGenericPluginLoader crash | ||
704 | * the returned OPluginItem could be empty if no crash occured | ||
705 | * which should apply most of the time. It could also be empty if the crashed | ||
706 | * plugin is not in the current list of available/managed plugins | ||
707 | * | ||
708 | * @see OPluginItem::isEmpty | ||
709 | * @return OPluginItem that crashed the loader | ||
710 | */ | ||
711 | OPluginItem OPluginManager::crashedPlugin()const { | ||
712 | return m_crashed; | ||
713 | } | ||
714 | |||
715 | /** | ||
716 | * \brief Return a list of plugins that are managed by this OPluginManager | ||
717 | * | ||
718 | * Return the list of managed plugins. This could either result | ||
719 | * from passing a OGenericPluginLoader and calling load or by | ||
720 | * giving name and a list of plugins. | ||
721 | */ | ||
722 | OPluginItem::List OPluginManager::managedPlugins()const { | ||
723 | return m_plugins; | ||
724 | } | ||
725 | |||
726 | /** | ||
727 | * \brief Set the position of the items | ||
728 | * | ||
729 | * Replace the OPluginItem with the name and path and this way | ||
730 | * apply the new position. The search is linear and this way O(n/2) | ||
731 | * You still need to call save() to make your changes effective. After saving | ||
732 | * a call to OGenericPluginLoader::filtered() returns the newly configured order and items | ||
733 | * | ||
734 | * @param item The OPluginItem to be replaced internall | ||
735 | * | ||
736 | */ | ||
737 | void OPluginManager::setPosition( const OPluginItem& item) { | ||
738 | replace( item ); | ||
739 | } | ||
740 | |||
741 | /** | ||
742 | * \brief Enable the item specified as argument | ||
743 | * | ||
744 | * This will make sure that OPluginItem::setEnabled is called and then will replace | ||
745 | * the item with one that matches name and path internally. | ||
746 | * @see setPosition | ||
747 | * | ||
748 | * @param the Item to enable | ||
749 | */ | ||
750 | void OPluginManager::enable( const OPluginItem& item ) { | ||
751 | setEnabled( item, true ); | ||
752 | } | ||
753 | |||
754 | /** | ||
755 | * \brief disable the Item. | ||
756 | * | ||
757 | * Disable the OPluginItem. Same applies as in | ||
758 | * @see setPosition and @see enable | ||
759 | * | ||
760 | * @param item Item to disable | ||
761 | */ | ||
762 | void OPluginManager::disable( const OPluginItem& item) { | ||
763 | setEnabled( item, false ); | ||
764 | } | ||
765 | |||
766 | /** | ||
767 | * \brief Enable or disable the OPluginItem. | ||
768 | * Depending on the value of the parameter this will either disable | ||
769 | * or enable the pluginitem. | ||
770 | * Beside that same as in @see disable, @see enable, @see setPosition | ||
771 | * applies. | ||
772 | * | ||
773 | * @param _item The OPluginItem to enable or to disable. | ||
774 | * @param b Enable or disable the plugin. | ||
775 | * | ||
776 | */ | ||
777 | void OPluginManager::setEnabled( const OPluginItem& _item, bool b ) { | ||
778 | OPluginItem item = _item; | ||
779 | item.setEnabled( b ); | ||
780 | replace( item ); | ||
781 | } | ||
782 | |||
783 | /** | ||
784 | * \brief Load necessary information after constructing the object | ||
785 | * If you speified a OGenericPluginLoader you need to call this method | ||
786 | * so that this manager knows what to manage and have a right value for \sa crashedPlugin | ||
787 | * For the name and the list of plugins this does only try to find out the crashed plugin | ||
788 | */ | ||
789 | void OPluginManager::load() { | ||
790 | OConfig cfg( configName() ); | ||
791 | cfg.setGroup( "General" ); | ||
792 | QString crashedPath = cfg.readEntry( "CrashedPlugin" ); | ||
793 | |||
794 | /* if we've a loader this applies if we were called from the first part */ | ||
795 | if ( m_loader ) | ||
796 | m_plugins = m_loader->allAvailable( m_loader->isSorted() ); | ||
797 | |||
798 | /* fast and normal route if we did not crash... */ | ||
799 | if ( crashedPath.isEmpty() ) | ||
800 | return; | ||
801 | |||
802 | /* lets try to find the plugin path and this way the associated item */ | ||
803 | for ( OPluginItem::List::Iterator it = m_plugins.begin(); it != m_plugins.end(); ++it ) | ||
804 | if ( (*it).path() == crashedPath ) { | ||
805 | m_crashed = *it; | ||
806 | break; | ||
807 | } | ||
808 | } | ||
809 | |||
810 | |||
811 | /** | ||
812 | * \brief Save the values and this way make it available. | ||
813 | * | ||
814 | * Save the current set of data. A call to @see OGenericPluginLoader::filtered | ||
815 | * now would return your saved changes. | ||
816 | */ | ||
817 | void OPluginManager::save() { | ||
818 | QMap<QString, QStringList> excluded; // map for path to excluded name | ||
819 | QMap<QString, QStringList> positions; // if positions matter contains splitted up by dirs | ||
820 | bool sorted = m_loader ? m_loader->isSorted() : m_isSorted; | ||
821 | |||
822 | /* | ||
823 | * We will create some maps for the groups to include positions a | ||
824 | */ | ||
825 | for ( OPluginItem::List::Iterator it = m_plugins.begin(); it != m_plugins.end(); ++it ) { | ||
826 | OPluginItem item = *it; | ||
827 | QString path = QFileInfo( item.path() ).filePath(); | ||
828 | if ( sorted ) { | ||
829 | positions[path].append( item.name() ); | ||
830 | positions[path].append( QString::number( item.position() ) ); | ||
831 | } | ||
832 | |||
833 | if ( !item.isEnabled() ) | ||
834 | excluded[path].append( item.name() ); | ||
835 | } | ||
836 | |||
837 | /* | ||
838 | * The code below wouldn't work because we can't delete groups/keys from the config | ||
839 | * ### for ODP make Config right! | ||
840 | */ | ||
841 | // if ( excluded.isEmpty() && positions.isEmpty() ) return; | ||
842 | /* | ||
843 | * Now safe for each path | ||
844 | */ | ||
845 | OConfig cfg( configName() ); | ||
846 | |||
847 | /* safe excluded items */ | ||
848 | for ( QMap<QString, QStringList>::Iterator it = excluded.begin(); it != excluded.end(); ++it ) { | ||
849 | OConfigGroupSaver saver( &cfg, it.key() ); | ||
850 | cfg.writeEntry("Excluded", it.data(), ',' ); | ||
851 | } | ||
852 | |||
853 | /* safe positions we could also see if positions.contains(path) and remove/write in the above loop | ||
854 | * ### Write a Test Suite that can profile these runs... | ||
855 | */ | ||
856 | for ( QMap<QString, QStringList>::Iterator it = positions.begin(); it != positions.end(); ++it ) { | ||
857 | OConfigGroupSaver saver( &cfg, it.key() ); | ||
858 | cfg.writeEntry("Positions", it.data(), '.' ); | ||
859 | } | ||
860 | } | ||
861 | |||
862 | /** | ||
863 | * @internal | ||
864 | */ | ||
865 | QString OPluginManager::configName()const { | ||
866 | QString str = m_loader ? m_loader->name() : m_cfgName; | ||
867 | return str + "odpplugins"; | ||
868 | } | ||
869 | |||
870 | /** | ||
871 | * @internal.. replace in m_plugins by path... this is linear search O(n/2) | ||
872 | */ | ||
873 | void OPluginManager::replace( const OPluginItem& item ) { | ||
874 | // ### fixme | ||
875 | } | ||
539 | 876 | ||
540 | } | 877 | } |
541 | } | 878 | } |
diff --git a/libopie2/opiecore/opluginloader.h b/libopie2/opiecore/opluginloader.h index 6166b75..2f9ec2a 100644 --- a/libopie2/opiecore/opluginloader.h +++ b/libopie2/opiecore/opluginloader.h | |||
@@ -1,181 +1,206 @@ | |||
1 | /* | 1 | /* |
2 | * LGPLv2 or later | 2 | * LGPLv2 or later |
3 | * zecke@handhelds.org | 3 | * zecke@handhelds.org |
4 | */ | 4 | */ |
5 | #ifndef ODP_CORE_OPLUGIN_LOADER_H | 5 | #ifndef ODP_CORE_OPLUGIN_LOADER_H |
6 | #define ODP_CORE_OPLUGIN_LOADER_H | 6 | #define ODP_CORE_OPLUGIN_LOADER_H |
7 | 7 | ||
8 | #include <qpe/qlibrary.h> | 8 | #include <qpe/qlibrary.h> |
9 | 9 | ||
10 | #include <qptrdict.h> | 10 | #include <qptrdict.h> |
11 | #include <qstringlist.h> | 11 | #include <qstringlist.h> |
12 | 12 | ||
13 | namespace Opie { | 13 | namespace Opie { |
14 | namespace Core { | 14 | namespace Core { |
15 | class OConfig; | 15 | class OConfig; |
16 | namespace Internal { | 16 | namespace Internal { |
17 | class OPluginLibraryHolder; | 17 | class OPluginLibraryHolder; |
18 | } | 18 | } |
19 | 19 | ||
20 | template class QPtrDict<QLibrary>; | 20 | template class QPtrDict<QLibrary>; |
21 | 21 | ||
22 | /** | 22 | /** |
23 | * \brief A small item representing the Plugin Information | 23 | * \brief A small item representing the Plugin Information |
24 | * This class contains the information about a Plugin. It contains | 24 | * This class contains the information about a Plugin. It contains |
25 | * a translated name if available to the system, a config key, | 25 | * a translated name if available to the system, a config key, |
26 | * and the path location. | 26 | * and the path location. |
27 | * | 27 | * |
28 | * @since 1.2 | 28 | * @since 1.2 |
29 | * | 29 | * |
30 | */ | 30 | */ |
31 | class OPluginItem { | 31 | class OPluginItem { |
32 | public: | 32 | public: |
33 | typedef QValueList<OPluginItem> List; | 33 | typedef QValueList<OPluginItem> List; |
34 | OPluginItem(); | 34 | OPluginItem(); |
35 | OPluginItem( const QString& name, const QString& path, int pos = -1 ); | 35 | OPluginItem( const QString& name, const QString& path, bool enabled = true, int pos = -1 ); |
36 | ~OPluginItem(); | 36 | ~OPluginItem(); |
37 | 37 | ||
38 | bool isEmpty()const; | ||
39 | |||
38 | bool operator==( const OPluginItem& )const; | 40 | bool operator==( const OPluginItem& )const; |
39 | bool operator!=( const OPluginItem& )const; | 41 | bool operator!=( const OPluginItem& )const; |
40 | 42 | ||
41 | 43 | ||
42 | QString name()const; | 44 | QString name()const; |
43 | QString path()const; | 45 | QString path()const; |
46 | bool isEnabled()const; | ||
44 | int position()const; | 47 | int position()const; |
45 | 48 | ||
46 | void setName( const QString& ); | 49 | void setName( const QString& ); |
47 | void setPath( const QString& ); | 50 | void setPath( const QString& ); |
51 | void setEnabled( bool ); | ||
48 | void setPosition( int ); | 52 | void setPosition( int ); |
49 | 53 | ||
50 | private: | 54 | private: |
51 | QString m_name; | 55 | QString m_name; |
52 | QString m_path; | 56 | QString m_path; |
57 | bool m_enabled : 1; | ||
53 | int m_pos; | 58 | int m_pos; |
54 | struct Private; | 59 | struct Private; |
55 | Private *d; | 60 | Private *d; |
56 | }; | 61 | }; |
57 | 62 | ||
58 | /** | 63 | /** |
59 | * \brief A generic class to easily load and manage plugins | 64 | * \brief A generic class to easily load and manage plugins |
60 | * | 65 | * |
61 | * This is the generic non sepcialised loader for plugins. Normally | 66 | * This is the generic non sepcialised loader for plugins. Normally |
62 | * you would prefer using the OPluginLoader directly. This class | 67 | * you would prefer using the OPluginLoader directly. This class |
63 | * exists to minimize the application binary size due the usage | 68 | * exists to minimize the application binary size due the usage |
64 | * of templates in the specialized API | 69 | * of templates in the specialized API |
65 | * | 70 | * |
66 | * @since 1.2 | 71 | * @since 1.2 |
67 | * @see OPluginLoader | 72 | * @see OPluginLoader |
68 | */ | 73 | */ |
69 | class OGenericPluginLoader { | 74 | class OGenericPluginLoader { |
70 | public: | 75 | public: |
71 | typedef OPluginItem::List List; | 76 | typedef OPluginItem::List List; |
72 | OGenericPluginLoader( const QString &name, bool isSorted = false ); | 77 | OGenericPluginLoader( const QString &name, bool isSorted = false ); |
73 | virtual ~OGenericPluginLoader(); | 78 | virtual ~OGenericPluginLoader(); |
74 | 79 | ||
75 | void setAutoDelete( bool ); | 80 | void setAutoDelete( bool ); |
76 | bool autoDelete()const; | 81 | bool autoDelete()const; |
77 | void clear(); | 82 | void clear(); |
78 | 83 | ||
79 | 84 | QString name()const; | |
85 | bool isSorted()const; | ||
80 | bool isInSafeMode()const; | 86 | bool isInSafeMode()const; |
81 | 87 | ||
82 | 88 | ||
83 | List allAvailable(bool sorted = FALSE)const; | 89 | List allAvailable(bool sorted = false )const; |
84 | List filtered(bool sorted = FALSE)const; | 90 | List filtered(bool sorted = false )const; |
85 | 91 | ||
86 | 92 | ||
87 | virtual QUnknownInterface* load( const OPluginItem& item, const QUuid& ); | 93 | virtual QUnknownInterface* load( const OPluginItem& item, const QUuid& ); |
88 | virtual void unload( QUnknownInterface* ); | 94 | virtual void unload( QUnknownInterface* ); |
89 | 95 | ||
90 | protected: | 96 | protected: |
97 | friend class OPluginManager; // we need the static unlibify | ||
91 | void readConfig(); | 98 | void readConfig(); |
92 | virtual List plugins( const QString& dir, bool sorted, bool disabled )const; | 99 | virtual List plugins( const QString& dir, bool sorted, bool disabled )const; |
93 | void setPluginDirs( const QStringList& ); | 100 | void setPluginDirs( const QStringList& ); |
94 | void setPluginDir( const QString& ); | 101 | void setPluginDir( const QString& ); |
95 | bool isSorted()const; | ||
96 | void setSafeMode(const QString& app = QString::null, bool b = false); | 102 | void setSafeMode(const QString& app = QString::null, bool b = false); |
97 | static QString unlibify( const QString& str ); | 103 | static QString unlibify( const QString& str ); |
98 | |||
99 | private: | 104 | private: |
100 | QStringList languageList(); | 105 | QStringList languageList(); |
101 | void installTranslators(const QString& type); | 106 | void installTranslators(const QString& type); |
102 | QString m_dir; | 107 | QString m_dir; |
103 | QStringList m_plugDirs; | 108 | QStringList m_plugDirs; |
104 | QStringList m_languages; | 109 | QStringList m_languages; |
105 | bool m_autoDelete : 1; | 110 | bool m_autoDelete : 1; |
106 | bool m_isSafeMode : 1; | 111 | bool m_isSafeMode : 1; |
107 | bool m_isSorted : 1; | 112 | bool m_isSorted : 1; |
108 | QPtrDict<QLibrary> m_library; | 113 | QPtrDict<QLibrary> m_library; |
109 | 114 | ||
110 | struct Private; | 115 | struct Private; |
111 | Private* d; | 116 | Private* d; |
112 | }; | 117 | }; |
113 | 118 | ||
114 | /** | 119 | /** |
115 | * \brief The class to load your QCOM+ plugins | 120 | * \brief The class to load your QCOM+ plugins |
116 | * | 121 | * |
117 | * This class takes care of activation and even the order | 122 | * This class takes care of activation and even the order |
118 | * if you need it. It is normally good to place a .directory file | 123 | * if you need it. It is normally good to place a .directory file |
119 | * into your plugin directory if you need order of activation. | 124 | * into your plugin directory if you need order of activation. |
120 | * | 125 | * |
121 | * You'll create the OPluginLoader and then use it to load the filtered | 126 | * You'll create the OPluginLoader and then use it to load the filtered |
122 | * plugins. | 127 | * plugins. |
123 | * | 128 | * |
124 | * There is also a GUI for the configuration and a Manager to write the | 129 | * There is also a GUI for the configuration and a Manager to write the |
125 | * mentioned .directory file | 130 | * mentioned .directory file |
126 | * | 131 | * |
127 | * On crash the safe mode is activated for the next run. You can then decide | 132 | * On crash the safe mode is activated for the next run. You can then decide |
128 | * if you want to load plugins or come up with the Configuration on | 133 | * if you want to load plugins or come up with the Configuration on |
129 | * next start yourself then. | 134 | * next start yourself then. |
130 | * | 135 | * |
131 | * @since 1.2 | 136 | * @since 1.2 |
132 | */ | 137 | */ |
133 | class OPluginLoader : public OGenericPluginLoader { | 138 | class OPluginLoader : public OGenericPluginLoader { |
134 | public: | 139 | public: |
135 | OPluginLoader( const QString& name, bool sorted = false ); | 140 | OPluginLoader( const QString& name, bool sorted = false ); |
136 | ~OPluginLoader(); | 141 | virtual ~OPluginLoader(); |
137 | 142 | ||
138 | template<class IFace> | 143 | template<class IFace> |
139 | IFace* load( const OPluginItem& item, const QUuid& ); | 144 | IFace* load( const OPluginItem& item, const QUuid& ); |
140 | }; | 145 | }; |
141 | 146 | ||
142 | /** | 147 | /** |
143 | * \brief A class to manager order and activation of plugins | 148 | * \brief A class to manage order and activation of plugins |
144 | * | 149 | * |
145 | * Manage order and activation. This is used by the Opie::Ui::OPluginConfig | 150 | * Manage order and activation. This is used by the Opie::Ui::OPluginConfig |
146 | * This class controls the activation and order of plugins depending | 151 | * This class controls the activation and order of plugins depending |
147 | * on the OPluginLoader you supply. | 152 | * on the OPluginLoader you supply. |
153 | * You must call load() and save after construnction an instance | ||
148 | * | 154 | * |
149 | * @see OPluginConfig | 155 | * @see Opie::Ui::OPluginConfig |
150 | * | 156 | * |
151 | */ | 157 | */ |
152 | class OPluginManager { | 158 | class OPluginManager { |
153 | public: | 159 | public: |
154 | OPluginManager( OGenericPluginLoader* , const QString& name); | 160 | OPluginManager( OGenericPluginLoader* ); |
155 | OPluginManager( OConfig* conf, const QString&, | 161 | OPluginManager( const QString& name, const OPluginItem::List&, bool isSorted = false ); |
156 | const QCString& group, const OPluginItem::List& ); | 162 | virtual ~OPluginManager(); |
157 | ~OPluginManager(); | ||
158 | 163 | ||
159 | QString name(); | 164 | OPluginItem crashedPlugin()const; |
160 | void setName( const QString& ); | 165 | |
166 | OPluginItem::List managedPlugins()const; | ||
161 | 167 | ||
162 | void setPosition( const OPluginItem& ); | 168 | void setPosition( const OPluginItem& ); |
163 | void enable( const OPluginItem& ); | 169 | void enable( const OPluginItem& ); |
164 | void disable( const OPluginItem& ); | 170 | void disable( const OPluginItem& ); |
165 | void setEnabled( const OPluginItem&, bool = true); | 171 | void setEnabled( const OPluginItem&, bool = true); |
166 | 172 | ||
167 | void load(); | 173 | virtual void load(); |
168 | void save(); | 174 | virtual void save(); |
175 | |||
176 | protected: | ||
177 | QString configName()const; | ||
178 | void replace( const OPluginItem& ); | ||
179 | private: | ||
180 | OGenericPluginLoader *m_loader; | ||
181 | QString m_cfgName; | ||
182 | OPluginItem::List m_plugins; | ||
183 | OPluginItem m_crashed; | ||
184 | bool m_isSorted : 1; | ||
169 | }; | 185 | }; |
170 | 186 | ||
171 | 187 | ||
188 | /** | ||
189 | * This is a template method allowing you to safely cast | ||
190 | * your load function | ||
191 | * | ||
192 | * \code | ||
193 | * MyTypePlugin *plug = load->load<MyTypePlugin>( item, IID_MyPlugin ); | ||
194 | * \endcode | ||
195 | * | ||
196 | */ | ||
172 | template<class IFace> | 197 | template<class IFace> |
173 | IFace* OPluginLoader::load( const OPluginItem& item, const QUuid& uid ) { | 198 | IFace* OPluginLoader::load( const OPluginItem& item, const QUuid& uid ) { |
174 | return static_cast<IFace*>( OGenericPluginLoader::load( item, uid ) ); | 199 | return static_cast<IFace*>( OGenericPluginLoader::load( item, uid ) ); |
175 | } | 200 | } |
176 | 201 | ||
177 | } | 202 | } |
178 | } | 203 | } |
179 | 204 | ||
180 | 205 | ||
181 | #endif | 206 | #endif |