summaryrefslogtreecommitdiff
authorzecke <zecke>2004-05-10 21:11:25 (UTC)
committer zecke <zecke>2004-05-10 21:11:25 (UTC)
commit23a70b8db47ea571bf9a35f4ff8f5696a6c9c1d3 (patch) (unidiff)
treeb084195bd871b12c3ea1b01e52a4916d17c8a2c6
parent613e0a6b246d8dcfd808089b2b6a1dc0501732da (diff)
downloadopie-23a70b8db47ea571bf9a35f4ff8f5696a6c9c1d3.zip
opie-23a70b8db47ea571bf9a35f4ff8f5696a6c9c1d3.tar.gz
opie-23a70b8db47ea571bf9a35f4ff8f5696a6c9c1d3.tar.bz2
First draft of PluginLoader
-actual loading of plugins is 80% done -Manager no code is there yet. I hope to have some time in uni tomorrow
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--libopie2/opiecore/opluginloader.cpp397
-rw-r--r--libopie2/opiecore/opluginloader.h191
2 files changed, 588 insertions, 0 deletions
diff --git a/libopie2/opiecore/opluginloader.cpp b/libopie2/opiecore/opluginloader.cpp
new file mode 100644
index 0000000..e5a0903
--- a/dev/null
+++ b/libopie2/opiecore/opluginloader.cpp
@@ -0,0 +1,397 @@
1/*
2 * LGPLv2 or later
3 * zecke@handhelds.org
4 */
5
6#include "opluginloader.h"
7
8#include <stdlib.h>
9
10
11
12namespace Opie {
13namespace Core {
14namespace Internal {
15struct OPluginLibraryHolder {
16 static OPluginLibraryHolder *self();
17 QLibrary *getLibrary( const QString& );
18 void putLibrary( QLibrary* );
19private:
20 OPluginLibraryHolder();
21 ~OPluginLibraryHolder();
22 OPluginLibraryHolder* m_self;
23
24};
25}
26
27}}
28/**
29 * \brief Creates an Empty OPluginItem
30 *
31 * create an empty pluginitem. Position is set to -1 and the
32 * other things are used with the default ctors
33 */
34OPluginItem::OPluginItem()
35 : m_pos( -1 ) {
36}
37
38/**
39 * \brief Create an OPluginItem
40 *
41 * Create a Plugin Item with all information.
42 *
43 * @param name The if available translated Name
44 * @param conf The name of the config group
45 * @param path The path to the plugin
46 * @param pos The position of the plugin if used for sorting
47 *
48 */
49OPluginItem::OPluginItem( const QString& name, const QCString& conf,
50 const QString& path, int pos = -1 )
51 : m_name( name ), m_conf( conf ), m_path( path ), m_pos( pos ) {
52}
53
54/**
55 * \brief simple d'tor
56 */
57OPluginItem::~OPluginItem() {
58}
59
60/**
61 * operator to test equalness of two OPluginItem
62 */
63bool OPluginItem::operator==( const OPluginItem& r )const{
64 if ( m_pos != r.m_pos ) return false;
65 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;
68 return true;
69}
70
71bool OPluginItem::operator!=( const OPluginItem& r ) {
72 return !( *this == r );
73}
74
75/**
76 * return the name of this Plugin
77 */
78QString OPluginItem::name()const {
79 return m_name;
80}
81
82/**
83 * return the config key
84 */
85QCString OPluginItem::configKey()const{
86 return m_conf;
87}
88
89/**
90 * return the path of the plugin
91 */
92QString OPluginItem::path()const {
93 return m_path;
94}
95
96int OPluginItem::position()const{
97 return m_pos;
98}
99
100/**
101 * Set the name of the Plugin Item
102 * @param name
103 */
104void OPluginItem::setName( const QString& name ) {
105 m_name = name;
106}
107
108/**
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
118 * @param name The path of the plugin
119 */
120void OPluginItem::setPath( const QString& name ) {
121 m_name = name;
122}
123
124/**
125 * Set the position
126 * @param pos The position
127 */
128void OPluginItem::setPosition( int pos ) {
129 m_pos = pos;
130}
131
132
133
134/**
135 * \brief create a PluginLoader
136 *
137 * Create a PluginLoader autoDelete is set to false
138 *
139 * \code
140 * Opie::Core::OGenericPluginLoader loader("myapp-plugin");
141 * Opie::Core::OPluginItem::List lst = loader.filtered();
142 * for(Opie::Core::OPluginItem::List::Iterator it = lst.begin(); it!=lst.end();++it){
143 * MyIface* iface = static_cast<MyIface*>(loader.load(*it,IID_MyIface));
144 * }
145 * \endcode
146 *
147 * \code
148 * Opie::Core::OGenericPluginLoader loader("myapp-plugin");
149 * Opie::Core::OPluginItem::List lst = loader.filtered();
150 * for(Opie::Core::OPluginItem::List::Iterator it = lst.begin(); it!=lst.end();++it){
151 * MyIface* iface = static_cast<MyIface*>(loader.load(*it,IID_MyIface));
152 * }
153 * ...
154 * loader.clear();
155 *
156 * \endcode
157 *
158 * @param name The name of the plugin directory.
159 * @param isSorted Tell the PluginLoader if your Plugins are sorted
160 */
161OGenericPluginLoader::OGenericPluginLoader( const QString& name, bool isSorted)
162 : m_dir( name ), m_autoDelete( false ), m_isSafeMode( false ),
163 m_isSorted( isSorted ), m_readConfig( false )
164{
165 setPluginDir( QPEApplication::qpeDir() + "/plugins/"+name );
166}
167
168
169/**
170 * calls clear if autoDelete is true. This will release all interfaces
171 * and remove the library from this process if the refcount falls to zero
172 */
173OGenericPluginLoader::~OGenericPluginLoader() {
174 if ( m_autoDelete )
175 clear();
176}
177
178/**
179 * enable autoDelete. This will call clear on the d'tor
180 *
181 * @see ~OGenericPluginLoader
182 * @see clear()
183 */
184void OGenericPluginLoader::setAutoDelete( bool t ) {
185 m_autoDelete = t;
186}
187
188/**
189 * see if autoDelet is enabled
190 */
191bool OGenericPluginLoader::autoDelete()const{
192 return m_autoDelete;
193}
194
195/**
196 * This will unload all returned QUnknownInterfaces by load. Unload
197 * will be called.
198 */
199void OGenericPluginLoader::clear() {
200 QPtrDictIterator<QLibrary> it( m_library );
201 for ( ;it.current(); )
202 unload( static_cast<QUnknownInterface*>( it.currentKey() ) );
203}
204
205/**
206 * This will take the iface from the internal QPtrDict, Release it,
207 * and deref the libray used.
208 * The visibility depends on the QPtrDict.
209 * @see QPtrDict::insert
210 */
211void OGenericPluginLoader::unload( QUnknownInterface* iface ) {
212 if ( !iface )
213 return;
214
215 iface->release();
216 OPluginLibraryHolder::self()->deref( m_library.take( iface ) );
217}
218
219/**
220 * This tells you
221 * if by previous tries to load, loading crashed your application.
222 * If isInSafeMode you can use the GUI to configure the plugins prior to loading
223 *
224 * @return true if prior loading failed
225 */
226bool OGenericPluginLoader::isInSafeMode()const {
227 if ( !m_readConfig )
228 readConfig();
229 return m_isSafeMode;
230}
231
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
241/**
242 * Return the list of all available plugins. This will go through all plugin
243 * directories and search for your type of plugins ( by subdir )
244 *
245 * @param sorted Tell if you want to have the positions sorted. This only makes sense if you
246 */
247OPluginItem::List OGenericPluginLoader::allAvailable( bool sorted )const {
248 OPluginItem::List lst;
249 for ( QStringList::ConstIterator it = m_plugDirs.begin(); it != m_plugDirs.end(); ++it )
250 lst += plugins( *it, sorted, false );
251
252 if ( sorted )
253 qHeapSort( lst );
254 return lst;
255}
256
257/**
258 * Return only activated plugins.
259 *
260 * @param sorted If the list should be sorted
261 */
262OPluginItem::List OGenericPluginLoader::filtered( bool sorted )const {
263 OPluginItem::List lst;
264 for ( QStringList::ConstIterator it = m_plugDirs.begin(); it != m_plugDirs.end(); ++it )
265 lst += plugins( *it, sorted, true );
266
267 if ( sorted )
268 qHeapSort( lst );
269 return lst;
270}
271
272
273/**
274 *
275 */
276QUnknownInterface* OGenericPluginLoader::load( const OPluginItem& item, const QUuid& uuid) {
277 /*
278 * Check if there could be a library
279 */
280 QString pa = item.path();
281 if ( pa.isEmpty() )
282 return 0l;
283
284 /*
285 * See if we get a library
286 * return if we've none
287 */
288 setSafeMode( true );
289 QLibrary *lib = OPluginLibraryHolder::self()->getLibrary( pa );
290 if ( !lib ) {
291 setSafeMode();
292 return 0l;
293 }
294
295 /**
296 * try to load the plugin and just in case initialize the pointer to a pointer again
297 */
298 QUnknownInterface** iface = 0;
299 if ( lib->queryInterface( uuid, iface ) == QS_OK ) {
300 installTranslators(pa.left( pa.find(".")));
301 m_library.insert( *iface, lib );
302 }else
303 *iface = 0;
304
305 setSafeMode();
306
307 return *iface;
308}
309
310void OGenericPluginLoader::readConfig() {
311 m_readConfig = true;
312
313 /* read the config for SafeMode */
314 OConfig conf( m_name + "-odpplugins" );
315 conf.setGroup( "General" );
316 m_isSafeMode = conf.readBoolEntry( "SafeMode", false );
317}
318
319void OGenericPluginLoader::setSafeMode(bool b) {
320 OConfig conf( m_name + "-odpplugins" );
321 conf.setGroup( "General" );
322 conf.writeEntry( "SafeMode", b );
323}
324
325void OGenericPluginLoader::setPluginDirs( const QStringList& lst ) {
326 m_plugDirs = lst;
327}
328
329void OGenericPluginLoader::setPluginDir( const QString& str) {
330 m_plugDirs.clear();
331 m_plugDirs.append( str );
332}
333
334bool &OGenericPluginLoader::isSafeMode()const {
335 return m_isSafeMode;
336}
337
338bool &OGenericPluginLoader::isSorted()const {
339 return m_isSorted;
340}
341
342OPluginItem::List OGenericPluginLoader::plugins( const QString& dir, bool sorted, bool disabled ) {
343#ifdef Q_OS_MACX
344 QDir dir( dir, "lib*.dylib" );
345#else
346 QDir dir( dir, "lib*.so" );
347#endif
348 /*
349 * get excluded list and then iterate over them
350 */
351 OConfig cfg( m_name+"odpplugins" );
352 cfg.setGroup( dir );
353 QStringList excludes = cfg.readListEntry( "Excluded" );
354
355 QStringList list = dir.entryList();
356// for (
357
358}
359
360
361QStringList OGenericPluginLoader::languageList() {
362 if ( languageList.isEmpty() ) {
363 /*
364 * be_BY.CP1251 We will add, be_BY.CP1251,be_BY,be
365 * to our list of languages.
366 */
367 QString str = ::getenv( "LANG" );
368 m_languages += str;
369 int pos = str.find( '.' );
370
371 if ( pos > 0 )
372 m_languages += str.left( pos );
373
374 int n_pos = str.find( '_' );
375 if ( pos > 0 && n_pos >= pos )
376 m_languages += str.left( n_pos );
377
378 }
379 return m_languages;
380}
381
382void OGenericPluginLoader::installTranslators(const QString& type) {
383 QStringList lst = languageList();
384 for ( QStringList::Iterator it = lst.begin(); it != lst.end(); ++it ) {
385 QTranslator* trans = new QTranslator( qApp );
386 QString tfn = QPEApplication::qpeDir()+"/i18n/" + lang + "/" + type + ".qm" ;
387 if ( trans->load( tfn ) )
388 qApp->installTranslator( trans );
389 else
390 delete trans;
391 }
392}
393
394
395
396}
397}
diff --git a/libopie2/opiecore/opluginloader.h b/libopie2/opiecore/opluginloader.h
new file mode 100644
index 0000000..a7df4a8
--- a/dev/null
+++ b/libopie2/opiecore/opluginloader.h
@@ -0,0 +1,191 @@
1/*
2 * LGPLv2 or later
3 * zecke@handhelds.org
4 */
5#ifndef ODP_CORE_OPLUGIN_LOADER_H
6#define ODP_CORE_OPLUGIN_LOADER_H
7
8#include <qpe/qlibrary.h>
9
10#include <qstringlist.h>
11
12namespace Opie {
13namespace Core {
14class OConfig;
15namespace Internal {
16class OPluginLibraryHolder;
17}
18
19template class QPtrDict<QLibrary>;
20
21/**
22 * \brief A small item representing the Plugin Information
23 * This class contains the information about a Plugin. It contains
24 * a translated name if available to the system, a config key,
25 * and the path location.
26 *
27 * @since 1.2
28 *
29 */
30class OPluginItem {
31public:
32 typedef QValueList<OPluginItem> List;
33 OPluginItem();
34 OPluginItem( const QString& name, const QCString& confopt, const QString& path, int pos = -1 );
35 ~OPluginItem();
36
37 bool operator==( const OPluginItem& )const;
38 bool operator!=( const OPluginItem& )const;
39
40
41 QString name()const;
42 QCString configKey()const;
43 QString path()const;
44 int position()const;
45
46 void setName( const QString& );
47 void setConfigKey( const QCString& );
48 void setPath( const QString& );
49 void setPosition( int );
50
51private:
52 QString m_name;
53 QCString m_conf;
54 QString m_path;
55 int m_pos;
56 struct Private;
57 Private *d;
58};
59
60/**
61 * \brief A generic class to easily load and manage plugins
62 *
63 * This is the generic non sepcialised loader for plugins. Normally
64 * you would prefer using the OPluginLoader directly. This class
65 * exists to minimize the application binary size due the usage
66 * of templates in the specialized API
67 *
68 * @since 1.2
69 * @see OPluginLoader
70 */
71class OGenericPluginLoader {
72public:
73 typedef OPluginItem::List List;
74 OGenericPluginLoader( const QString &name, bool isSorted = false );
75 virtual ~OGenericPluginLoader();
76
77 void setAutoDelete( bool );
78 bool autoDelete()const;
79 void clear();
80
81
82 bool isInSafeMode()const;
83
84
85 List allAvailable(bool sorted = FALSE)const;
86 List filtered(bool sorted = FALSE)const;
87
88
89 virtual QUnknownInterface* load( const OPluginItem& item, const QUuid& );
90 virtual void unload( QUnknownInterface* );
91
92protected:
93 virtual void readConfig();
94 virtual List plugins( const QString& dir, bool sorted, bool disabled )const;
95 void setPluginDirs( const QStringList& );
96 void setPluginDir( const QString& );
97 bool &isSafeMode()const;
98 bool &isSorted()const;
99 void readConfig()const;
100 void setSafeMode(bool b = false);
101
102private:
103 QString languageList();
104 void installTranslators(const QString& type);
105 QString m_dir;
106 QStringList m_plugDirs;
107 QStringList m_languages;
108 bool m_autoDelete : 1;
109 bool m_isSafeMode : 1;
110 bool m_readConfig : 1;
111 bool m_isSorted : 1;
112 QPtrDict<QLibrary> m_library;
113
114 struct Private;
115 Private* d;
116};
117
118/**
119 * \brief The class to load your QCOM+ plugins
120 *
121 * This class takes care of activation and even the order
122 * if you need it. It is normally good to place a .directory file
123 * into your plugin directory if you need order of activation.
124 *
125 * You'll create the OPluginLoader and then use it to load the filtered
126 * plugins.
127 *
128 * There is also a GUI for the configuration and a Manager to write the
129 * mentioned .directory file
130 *
131 * On crash the safe mode is activated for the next run. You can then decide
132 * if you want to load plugins or come up with the Configuration on
133 * next start yourself then.
134 *
135 * @since 1.2
136 */
137class OPluginLoader : public OGenericPluginLoader {
138public:
139 OPluginLoader( const QString& name, bool sorted = false );
140 ~OPluginLoader();
141
142 temlate<class IFace>
143 IFace* load( const QString& name, const QUuid& );
144 temlate<class IFace>
145 IFace* load( const OPluginItem& item, const QUuid& );
146};
147
148/**
149 * \brief A class to manager order and activation of plugins
150 *
151 * Manage order and activation. This is used by the Opie::Ui::OPluginConfig
152 * This class controls the activation and order of plugins depending
153 * on the OPluginLoader you supply.
154 *
155 * @see OPluginConfig
156 *
157 */
158class OPluginManager {
159public:
160 OPluginManager( OGenericPluginLoader* , const QString& name);
161 OPluginManager( OConfig* conf, const QString&,
162 const QCString& group, const OPluginItem::List& );
163 ~OPluginManager();
164
165 QString name();
166 void setName( const QString& );
167
168 void setPosition( const OPluginItem& );
169 void enable( const OPluginItem& );
170 void disable( const OPluginItem& );
171 void setEnabled( const OPluginItem&, bool = true);
172
173 void load();
174 void save();
175};
176
177template<class IFace>
178IFace* OPluginLoader::load( const QString& name, const QUuid& uid ) {
179 return static_cast<IFace*>( OGenericPluginLoader::load( item, uid ) );
180}
181
182template<class IFace>
183IFace* OPluginLoader::load( const OPluginItem& item, const QUuid& uid ) {
184 return static_cast<IFace*>( OGenericPluginLoader::load( item, uid ) );
185}
186
187}
188}
189
190
191#endif