summaryrefslogtreecommitdiff
path: root/libopie2/opiecore/opluginloader.cpp
Unidiff
Diffstat (limited to 'libopie2/opiecore/opluginloader.cpp') (more/less context) (show whitespace changes)
-rw-r--r--libopie2/opiecore/opluginloader.cpp270
1 files changed, 207 insertions, 63 deletions
diff --git a/libopie2/opiecore/opluginloader.cpp b/libopie2/opiecore/opluginloader.cpp
index e5a0903..b473cd7 100644
--- a/libopie2/opiecore/opluginloader.cpp
+++ b/libopie2/opiecore/opluginloader.cpp
@@ -4,6 +4,13 @@
4 */ 4 */
5 5
6#include "opluginloader.h" 6#include "opluginloader.h"
7#include "oconfig.h"
8
9#include <qpe/qpeapplication.h>
10
11#include <qdir.h>
12#include <qdict.h>
13#include <qtl.h>
7 14
8#include <stdlib.h> 15#include <stdlib.h>
9 16
@@ -14,17 +21,84 @@ namespace Core {
14namespace Internal { 21namespace Internal {
15struct OPluginLibraryHolder { 22struct OPluginLibraryHolder {
16 static OPluginLibraryHolder *self(); 23 static OPluginLibraryHolder *self();
17 QLibrary *getLibrary( const QString& ); 24 QLibrary *ref( const QString& );
18 void putLibrary( QLibrary* ); 25 void deref( QLibrary* );
19private: 26private:
27
20 OPluginLibraryHolder(); 28 OPluginLibraryHolder();
21 ~OPluginLibraryHolder(); 29 ~OPluginLibraryHolder();
22 OPluginLibraryHolder* m_self; 30 QDict<QLibrary> m_libs;
23 31 static OPluginLibraryHolder* m_self;
24}; 32};
33
34 OPluginLibraryHolder* OPluginLibraryHolder::m_self = 0;
35 OPluginLibraryHolder* OPluginLibraryHolder::self() {
36 if ( !m_self )
37 m_self = new OPluginLibraryHolder;
38
39 return m_self;
40 }
41
42 OPluginLibraryHolder::OPluginLibraryHolder() {}
43 OPluginLibraryHolder::~OPluginLibraryHolder() {}
44
45 /*
46 * 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 * 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 * to hack QPEApplication
51 */
52 QLibrary* OPluginLibraryHolder::ref(const QString& str) {
53 QLibrary *lib = m_libs[str];
54
55 /* if not in the dict try to load it */
56 if ( !lib ) {
57 lib = new QLibrary( str, QLibrary::Immediately );
58 if ( !lib->isLoaded() ) {
59 delete lib;
60 return 0l;
61 }
62 }
63
64 /* now refcount one up */
65 m_libs.insert( str, lib );
66 return lib;
67 }
68
69 /*
70 * 'unshadow' the items until we're the last then unload and delete
71 */
72 void OPluginLibraryHolder::deref( QLibrary* lib ) {
73 if ( !lib )
74 return;
75
76 QString str = lib->library();
77 /* no need to check if the lib was inserted or such */
78 (void) m_libs.take( str );
79 if ( !m_libs[str] ) {
80 lib->unload();
81 delete lib;
82 }
83 }
84}
85
86/**
87 * We want values with 30,29,28 at the beginning of the list
88 */
89
90bool operator<( const OPluginItem& l, const OPluginItem& r ) {
91 return l.position() > r.position();
92}
93
94bool operator>( const OPluginItem& l, const OPluginItem& r ) {
95 return l.position() < r.position();
96}
97
98bool operator<=( const OPluginItem& l, const OPluginItem& r ) {
99 return l.position() >= r.position();
25} 100}
26 101
27}}
28/** 102/**
29 * \brief Creates an Empty OPluginItem 103 * \brief Creates an Empty OPluginItem
30 * 104 *
@@ -41,14 +115,12 @@ OPluginItem::OPluginItem()
41 * Create a Plugin Item with all information. 115 * Create a Plugin Item with all information.
42 * 116 *
43 * @param name The if available translated Name 117 * @param name The if available translated Name
44 * @param conf The name of the config group
45 * @param path The path to the plugin 118 * @param path The path to the plugin
46 * @param pos The position of the plugin if used for sorting 119 * @param pos The position of the plugin if used for sorting
47 * 120 *
48 */ 121 */
49OPluginItem::OPluginItem( const QString& name, const QCString& conf, 122OPluginItem::OPluginItem( const QString& name, const QString& path, int pos )
50 const QString& path, int pos = -1 ) 123 : m_name( name ), m_path( path ), m_pos( pos ) {
51 : m_name( name ), m_conf( conf ), m_path( path ), m_pos( pos ) {
52} 124}
53 125
54/** 126/**
@@ -63,12 +135,11 @@ OPluginItem::~OPluginItem() {
63bool OPluginItem::operator==( const OPluginItem& r )const{ 135bool OPluginItem::operator==( const OPluginItem& r )const{
64 if ( m_pos != r.m_pos ) return false; 136 if ( m_pos != r.m_pos ) return false;
65 if ( m_name != r.m_name ) return false; 137 if ( m_name != r.m_name ) return false;
66 if ( m_conf != r.m_conf ) return false;
67 if ( m_path != r.m_path ) return false; 138 if ( m_path != r.m_path ) return false;
68 return true; 139 return true;
69} 140}
70 141
71bool OPluginItem::operator!=( const OPluginItem& r ) { 142bool OPluginItem::operator!=( const OPluginItem& r )const{
72 return !( *this == r ); 143 return !( *this == r );
73} 144}
74 145
@@ -80,13 +151,6 @@ QString OPluginItem::name()const {
80} 151}
81 152
82/** 153/**
83 * return the config key
84 */
85QCString OPluginItem::configKey()const{
86 return m_conf;
87}
88
89/**
90 * return the path of the plugin 154 * return the path of the plugin
91 */ 155 */
92QString OPluginItem::path()const { 156QString OPluginItem::path()const {
@@ -106,14 +170,6 @@ void OPluginItem::setName( const QString& name ) {
106} 170}
107 171
108/** 172/**
109 * Set the config key
110 * @param key The config key/group of this plugin
111 */
112void OPluginItem::setConfigKey( const QCString& conf ) {
113 m_conf = conf;
114}
115
116/**
117 * Set the path of Plugin Item 173 * Set the path of Plugin Item
118 * @param name The path of the plugin 174 * @param name The path of the plugin
119 */ 175 */
@@ -160,9 +216,10 @@ void OPluginItem::setPosition( int pos ) {
160 */ 216 */
161OGenericPluginLoader::OGenericPluginLoader( const QString& name, bool isSorted) 217OGenericPluginLoader::OGenericPluginLoader( const QString& name, bool isSorted)
162 : m_dir( name ), m_autoDelete( false ), m_isSafeMode( false ), 218 : m_dir( name ), m_autoDelete( false ), m_isSafeMode( false ),
163 m_isSorted( isSorted ), m_readConfig( false ) 219 m_isSorted( isSorted )
164{ 220{
165 setPluginDir( QPEApplication::qpeDir() + "/plugins/"+name ); 221 setPluginDir( QPEApplication::qpeDir() + "/plugins/"+name );
222 readConfig();
166} 223}
167 224
168 225
@@ -213,7 +270,7 @@ void OGenericPluginLoader::unload( QUnknownInterface* iface ) {
213 return; 270 return;
214 271
215 iface->release(); 272 iface->release();
216 OPluginLibraryHolder::self()->deref( m_library.take( iface ) ); 273 Internal::OPluginLibraryHolder::self()->deref( m_library.take( iface ) );
217} 274}
218 275
219/** 276/**
@@ -224,19 +281,9 @@ void OGenericPluginLoader::unload( QUnknownInterface* iface ) {
224 * @return true if prior loading failed 281 * @return true if prior loading failed
225 */ 282 */
226bool OGenericPluginLoader::isInSafeMode()const { 283bool OGenericPluginLoader::isInSafeMode()const {
227 if ( !m_readConfig )
228 readConfig();
229 return m_isSafeMode; 284 return m_isSafeMode;
230} 285}
231 286
232/**
233 * return if the plugin list is sorted.
234 */
235bool OGenericPluginLoader::isSorted()const {
236 if ( !m_readConfig )
237 readConfig();
238 return m_isSorted;
239}
240 287
241/** 288/**
242 * Return the list of all available plugins. This will go through all plugin 289 * Return the list of all available plugins. This will go through all plugin
@@ -285,8 +332,8 @@ QUnknownInterface* OGenericPluginLoader::load( const OPluginItem& item, const QU
285 * See if we get a library 332 * See if we get a library
286 * return if we've none 333 * return if we've none
287 */ 334 */
288 setSafeMode( true ); 335 setSafeMode( pa, true );
289 QLibrary *lib = OPluginLibraryHolder::self()->getLibrary( pa ); 336 QLibrary *lib = Internal::OPluginLibraryHolder::self()->ref( pa );
290 if ( !lib ) { 337 if ( !lib ) {
291 setSafeMode(); 338 setSafeMode();
292 return 0l; 339 return 0l;
@@ -295,71 +342,159 @@ QUnknownInterface* OGenericPluginLoader::load( const OPluginItem& item, const QU
295 /** 342 /**
296 * try to load the plugin and just in case initialize the pointer to a pointer again 343 * try to load the plugin and just in case initialize the pointer to a pointer again
297 */ 344 */
298 QUnknownInterface** iface = 0; 345 QUnknownInterface* iface=0;
299 if ( lib->queryInterface( uuid, iface ) == QS_OK ) { 346 if ( lib->queryInterface( uuid, &iface ) == QS_OK ) {
300 installTranslators(pa.left( pa.find("."))); 347 installTranslators(pa.left( pa.find(".")));
301 m_library.insert( *iface, lib ); 348 m_library.insert( iface, lib );
302 }else 349 }else
303 *iface = 0; 350 iface = 0;
304 351
305 setSafeMode(); 352 setSafeMode();
306 353
307 return *iface; 354 return iface;
308} 355}
309 356
357/**
358 * @internal and reads in the safe mode
359 */
310void OGenericPluginLoader::readConfig() { 360void OGenericPluginLoader::readConfig() {
311 m_readConfig = true;
312
313 /* read the config for SafeMode */ 361 /* read the config for SafeMode */
314 OConfig conf( m_name + "-odpplugins" ); 362 OConfig conf( m_dir + "-odpplugins" );
315 conf.setGroup( "General" ); 363 conf.setGroup( "General" );
316 m_isSafeMode = conf.readBoolEntry( "SafeMode", false ); 364 m_isSafeMode = conf.readBoolEntry( "SafeMode", false );
317} 365}
318 366
319void OGenericPluginLoader::setSafeMode(bool b) { 367/**
320 OConfig conf( m_name + "-odpplugins" ); 368 * Enter or leave SafeMode
369 */
370void OGenericPluginLoader::setSafeMode(const QString& str, bool b) {
371 OConfig conf( m_dir + "-odpplugins" );
321 conf.setGroup( "General" ); 372 conf.setGroup( "General" );
322 conf.writeEntry( "SafeMode", b ); 373 conf.writeEntry( "SafeMode", b );
374 conf.writeEntry( "CrashedPlugin", str );
323} 375}
324 376
377/**
378 * @internal
379 *
380 * Set the List of Plugin Dirs to lst. Currently only QPEApplication::qpeDir()+"/plugins/"+mytype
381 * is used as plugin dir
382 */
325void OGenericPluginLoader::setPluginDirs( const QStringList& lst ) { 383void OGenericPluginLoader::setPluginDirs( const QStringList& lst ) {
326 m_plugDirs = lst; 384 m_plugDirs = lst;
327} 385}
328 386
387/**
388 *
389 * @internal
390 * Set the Plugin Dir to str. Str will be the only element in the list of plugin dirs
391 */
329void OGenericPluginLoader::setPluginDir( const QString& str) { 392void OGenericPluginLoader::setPluginDir( const QString& str) {
330 m_plugDirs.clear(); 393 m_plugDirs.clear();
331 m_plugDirs.append( str ); 394 m_plugDirs.append( str );
332} 395}
333 396
334bool &OGenericPluginLoader::isSafeMode()const {
335 return m_isSafeMode;
336}
337 397
338bool &OGenericPluginLoader::isSorted()const { 398/**
399 * @internal
400 */
401bool OGenericPluginLoader::isSorted()const{
339 return m_isSorted; 402 return m_isSorted;
340} 403}
341 404
342OPluginItem::List OGenericPluginLoader::plugins( const QString& dir, bool sorted, bool disabled ) { 405/*
406 * make libfoo.so.1.0.0 -> foo on UNIX
407 * make libfoo.dylib -> foo on MAC OS X Unix
408 * windows is obviously missing
409 */
410/**
411 * @internal
412 */
413QString OGenericPluginLoader::unlibify( const QString& str ) {
414 QString st = str.mid( str.find( "lib" )+3 );
415#ifdef Q_OS_MACX
416 return st.left( st.findRev( ".dylib" ) );
417#else
418 return st.left( st.findRev( ".so" ) );
419#endif
420}
421
422/**
423 * 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
425 *
426 * @param dir The dir to look in
427 * @param sorted Should positions be read?
428 * @param disabled Remove excluded from the list
429 */
430OPluginItem::List OGenericPluginLoader::plugins( const QString& _dir, bool sorted, bool disabled )const {
343#ifdef Q_OS_MACX 431#ifdef Q_OS_MACX
344 QDir dir( dir, "lib*.dylib" ); 432 QDir dir( _dir, "lib*.dylib" );
345#else 433#else
346 QDir dir( dir, "lib*.so" ); 434 QDir dir( _dir, "lib*.so" );
347#endif 435#endif
436
437 OPluginItem::List lst;
438
348 /* 439 /*
349 * get excluded list and then iterate over them 440 * get excluded list and then iterate over them
441 * Excluded list contains the name
442 * Position is a list with 'name.pos.name.pos.name.pos'
443 *
444 * For the look up we will create two QMap<QString,pos>
350 */ 445 */
351 OConfig cfg( m_name+"odpplugins" ); 446 QMap<QString, int> positionMap;
352 cfg.setGroup( dir ); 447 QMap<QString, int> excludedMap;
353 QStringList excludes = cfg.readListEntry( "Excluded" ); 448
449
450 OConfig cfg( m_dir+"odpplugins" );
451 cfg.setGroup( _dir );
452
453
454 QStringList excludes = cfg.readListEntry( "Excluded", ',' );
455 for ( QStringList::Iterator it = excludes.begin(); it != excludes.end(); ++it )
456 excludedMap.insert( *it, -2 );
457
458 if ( m_isSorted ) {
459 QStringList pos = cfg.readListEntry( "Positions", '.' );
460 QStringList::Iterator it = pos.begin();
461 while ( it != pos.end() )
462 positionMap.insert( *it++, (*it++).toInt() );
463 }
464
465
466
354 467
355 QStringList list = dir.entryList(); 468 QStringList list = dir.entryList();
356// for ( 469 QStringList::Iterator it;
470 for (QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
471 QString str = unlibify( *it );
472 OPluginItem item( str, _dir + "/" + *it );
357 473
474 bool ex = excludedMap.contains( str );
475 /*
476 * if disabled but we should show all assign a -2
477 * else continue because we don't want to add the item
478 * else if sorted we assign the right position
479 */
480 if ( ex && !disabled)
481 item.setPosition( -2 );
482 else if ( ex && disabled )
483 continue;
484 else if ( sorted )
485 item.setPosition( positionMap[str] );
486
487 lst.append( item );
358} 488}
359 489
490 return lst;
491}
360 492
493/**
494 * @internal generate a list of languages from $LANG
495 */
361QStringList OGenericPluginLoader::languageList() { 496QStringList OGenericPluginLoader::languageList() {
362 if ( languageList.isEmpty() ) { 497 if ( m_languages.isEmpty() ) {
363 /* 498 /*
364 * be_BY.CP1251 We will add, be_BY.CP1251,be_BY,be 499 * be_BY.CP1251 We will add, be_BY.CP1251,be_BY,be
365 * to our list of languages. 500 * to our list of languages.
@@ -381,9 +516,18 @@ QStringList OGenericPluginLoader::languageList() {
381 516
382void OGenericPluginLoader::installTranslators(const QString& type) { 517void OGenericPluginLoader::installTranslators(const QString& type) {
383 QStringList lst = languageList(); 518 QStringList lst = languageList();
519
520 /*
521 * for each language and maybe later for each language dir...
522 * try to load a Translator
523 */
384 for ( QStringList::Iterator it = lst.begin(); it != lst.end(); ++it ) { 524 for ( QStringList::Iterator it = lst.begin(); it != lst.end(); ++it ) {
385 QTranslator* trans = new QTranslator( qApp ); 525 QTranslator* trans = new QTranslator( qApp );
386 QString tfn = QPEApplication::qpeDir()+"/i18n/" + lang + "/" + type + ".qm" ; 526 QString tfn = QPEApplication::qpeDir()+"/i18n/" + *it + "/" + type + ".qm" ;
527
528 /*
529 * If loaded then install else clean up and don't leak
530 */
387 if ( trans->load( tfn ) ) 531 if ( trans->load( tfn ) )
388 qApp->installTranslator( trans ); 532 qApp->installTranslator( trans );
389 else 533 else