summaryrefslogtreecommitdiff
authorzecke <zecke>2004-05-10 21:11:25 (UTC)
committer zecke <zecke>2004-05-10 21:11:25 (UTC)
commit23a70b8db47ea571bf9a35f4ff8f5696a6c9c1d3 (patch) (side-by-side diff)
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) (show 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 @@
+/*
+ * LGPLv2 or later
+ * zecke@handhelds.org
+ */
+
+#include "opluginloader.h"
+
+#include <stdlib.h>
+
+
+
+namespace Opie {
+namespace Core {
+namespace Internal {
+struct OPluginLibraryHolder {
+ static OPluginLibraryHolder *self();
+ QLibrary *getLibrary( const QString& );
+ void putLibrary( QLibrary* );
+private:
+ OPluginLibraryHolder();
+ ~OPluginLibraryHolder();
+ OPluginLibraryHolder* m_self;
+
+};
+}
+
+}}
+/**
+ * \brief Creates an Empty OPluginItem
+ *
+ * create an empty pluginitem. Position is set to -1 and the
+ * other things are used with the default ctors
+ */
+OPluginItem::OPluginItem()
+ : m_pos( -1 ) {
+}
+
+/**
+ * \brief Create an OPluginItem
+ *
+ * Create a Plugin Item with all information.
+ *
+ * @param name The if available translated Name
+ * @param conf The name of the config group
+ * @param path The path to the plugin
+ * @param pos The position of the plugin if used for sorting
+ *
+ */
+OPluginItem::OPluginItem( const QString& name, const QCString& conf,
+ const QString& path, int pos = -1 )
+ : m_name( name ), m_conf( conf ), m_path( path ), m_pos( pos ) {
+}
+
+/**
+ * \brief simple d'tor
+ */
+OPluginItem::~OPluginItem() {
+}
+
+/**
+ * operator to test equalness of two OPluginItem
+ */
+bool OPluginItem::operator==( const OPluginItem& r )const{
+ if ( m_pos != r.m_pos ) return false;
+ if ( m_name != r.m_name ) return false;
+ if ( m_conf != r.m_conf ) return false;
+ if ( m_path != r.m_path ) return false;
+ return true;
+}
+
+bool OPluginItem::operator!=( const OPluginItem& r ) {
+ return !( *this == r );
+}
+
+/**
+ * return the name of this Plugin
+ */
+QString OPluginItem::name()const {
+ return m_name;
+}
+
+/**
+ * return the config key
+ */
+QCString OPluginItem::configKey()const{
+ return m_conf;
+}
+
+/**
+ * return the path of the plugin
+ */
+QString OPluginItem::path()const {
+ return m_path;
+}
+
+int OPluginItem::position()const{
+ return m_pos;
+}
+
+/**
+ * Set the name of the Plugin Item
+ * @param name
+ */
+void OPluginItem::setName( const QString& name ) {
+ m_name = name;
+}
+
+/**
+ * Set the config key
+ * @param key The config key/group of this plugin
+ */
+void OPluginItem::setConfigKey( const QCString& conf ) {
+ m_conf = conf;
+}
+
+/**
+ * Set the path of Plugin Item
+ * @param name The path of the plugin
+ */
+void OPluginItem::setPath( const QString& name ) {
+ m_name = name;
+}
+
+/**
+ * Set the position
+ * @param pos The position
+ */
+void OPluginItem::setPosition( int pos ) {
+ m_pos = pos;
+}
+
+
+
+/**
+ * \brief create a PluginLoader
+ *
+ * Create a PluginLoader autoDelete is set to false
+ *
+ * \code
+ * Opie::Core::OGenericPluginLoader loader("myapp-plugin");
+ * Opie::Core::OPluginItem::List lst = loader.filtered();
+ * for(Opie::Core::OPluginItem::List::Iterator it = lst.begin(); it!=lst.end();++it){
+ * MyIface* iface = static_cast<MyIface*>(loader.load(*it,IID_MyIface));
+ * }
+ * \endcode
+ *
+ * \code
+ * Opie::Core::OGenericPluginLoader loader("myapp-plugin");
+ * Opie::Core::OPluginItem::List lst = loader.filtered();
+ * for(Opie::Core::OPluginItem::List::Iterator it = lst.begin(); it!=lst.end();++it){
+ * MyIface* iface = static_cast<MyIface*>(loader.load(*it,IID_MyIface));
+ * }
+ * ...
+ * loader.clear();
+ *
+ * \endcode
+ *
+ * @param name The name of the plugin directory.
+ * @param isSorted Tell the PluginLoader if your Plugins are sorted
+ */
+OGenericPluginLoader::OGenericPluginLoader( const QString& name, bool isSorted)
+ : m_dir( name ), m_autoDelete( false ), m_isSafeMode( false ),
+ m_isSorted( isSorted ), m_readConfig( false )
+{
+ setPluginDir( QPEApplication::qpeDir() + "/plugins/"+name );
+}
+
+
+/**
+ * calls clear if autoDelete is true. This will release all interfaces
+ * and remove the library from this process if the refcount falls to zero
+ */
+OGenericPluginLoader::~OGenericPluginLoader() {
+ if ( m_autoDelete )
+ clear();
+}
+
+/**
+ * enable autoDelete. This will call clear on the d'tor
+ *
+ * @see ~OGenericPluginLoader
+ * @see clear()
+ */
+void OGenericPluginLoader::setAutoDelete( bool t ) {
+ m_autoDelete = t;
+}
+
+/**
+ * see if autoDelet is enabled
+ */
+bool OGenericPluginLoader::autoDelete()const{
+ return m_autoDelete;
+}
+
+/**
+ * This will unload all returned QUnknownInterfaces by load. Unload
+ * will be called.
+ */
+void OGenericPluginLoader::clear() {
+ QPtrDictIterator<QLibrary> it( m_library );
+ for ( ;it.current(); )
+ unload( static_cast<QUnknownInterface*>( it.currentKey() ) );
+}
+
+/**
+ * This will take the iface from the internal QPtrDict, Release it,
+ * and deref the libray used.
+ * The visibility depends on the QPtrDict.
+ * @see QPtrDict::insert
+ */
+void OGenericPluginLoader::unload( QUnknownInterface* iface ) {
+ if ( !iface )
+ return;
+
+ iface->release();
+ OPluginLibraryHolder::self()->deref( m_library.take( iface ) );
+}
+
+/**
+ * This tells you
+ * if by previous tries to load, loading crashed your application.
+ * If isInSafeMode you can use the GUI to configure the plugins prior to loading
+ *
+ * @return true if prior loading failed
+ */
+bool OGenericPluginLoader::isInSafeMode()const {
+ if ( !m_readConfig )
+ readConfig();
+ return m_isSafeMode;
+}
+
+/**
+ * return if the plugin list is sorted.
+ */
+bool OGenericPluginLoader::isSorted()const {
+ if ( !m_readConfig )
+ readConfig();
+ return m_isSorted;
+}
+
+/**
+ * Return the list of all available plugins. This will go through all plugin
+ * directories and search for your type of plugins ( by subdir )
+ *
+ * @param sorted Tell if you want to have the positions sorted. This only makes sense if you
+ */
+OPluginItem::List OGenericPluginLoader::allAvailable( bool sorted )const {
+ OPluginItem::List lst;
+ for ( QStringList::ConstIterator it = m_plugDirs.begin(); it != m_plugDirs.end(); ++it )
+ lst += plugins( *it, sorted, false );
+
+ if ( sorted )
+ qHeapSort( lst );
+ return lst;
+}
+
+/**
+ * Return only activated plugins.
+ *
+ * @param sorted If the list should be sorted
+ */
+OPluginItem::List OGenericPluginLoader::filtered( bool sorted )const {
+ OPluginItem::List lst;
+ for ( QStringList::ConstIterator it = m_plugDirs.begin(); it != m_plugDirs.end(); ++it )
+ lst += plugins( *it, sorted, true );
+
+ if ( sorted )
+ qHeapSort( lst );
+ return lst;
+}
+
+
+/**
+ *
+ */
+QUnknownInterface* OGenericPluginLoader::load( const OPluginItem& item, const QUuid& uuid) {
+ /*
+ * Check if there could be a library
+ */
+ QString pa = item.path();
+ if ( pa.isEmpty() )
+ return 0l;
+
+ /*
+ * See if we get a library
+ * return if we've none
+ */
+ setSafeMode( true );
+ QLibrary *lib = OPluginLibraryHolder::self()->getLibrary( pa );
+ if ( !lib ) {
+ setSafeMode();
+ return 0l;
+ }
+
+ /**
+ * try to load the plugin and just in case initialize the pointer to a pointer again
+ */
+ QUnknownInterface** iface = 0;
+ if ( lib->queryInterface( uuid, iface ) == QS_OK ) {
+ installTranslators(pa.left( pa.find(".")));
+ m_library.insert( *iface, lib );
+ }else
+ *iface = 0;
+
+ setSafeMode();
+
+ return *iface;
+}
+
+void OGenericPluginLoader::readConfig() {
+ m_readConfig = true;
+
+ /* read the config for SafeMode */
+ OConfig conf( m_name + "-odpplugins" );
+ conf.setGroup( "General" );
+ m_isSafeMode = conf.readBoolEntry( "SafeMode", false );
+}
+
+void OGenericPluginLoader::setSafeMode(bool b) {
+ OConfig conf( m_name + "-odpplugins" );
+ conf.setGroup( "General" );
+ conf.writeEntry( "SafeMode", b );
+}
+
+void OGenericPluginLoader::setPluginDirs( const QStringList& lst ) {
+ m_plugDirs = lst;
+}
+
+void OGenericPluginLoader::setPluginDir( const QString& str) {
+ m_plugDirs.clear();
+ m_plugDirs.append( str );
+}
+
+bool &OGenericPluginLoader::isSafeMode()const {
+ return m_isSafeMode;
+}
+
+bool &OGenericPluginLoader::isSorted()const {
+ return m_isSorted;
+}
+
+OPluginItem::List OGenericPluginLoader::plugins( const QString& dir, bool sorted, bool disabled ) {
+#ifdef Q_OS_MACX
+ QDir dir( dir, "lib*.dylib" );
+#else
+ QDir dir( dir, "lib*.so" );
+#endif
+ /*
+ * get excluded list and then iterate over them
+ */
+ OConfig cfg( m_name+"odpplugins" );
+ cfg.setGroup( dir );
+ QStringList excludes = cfg.readListEntry( "Excluded" );
+
+ QStringList list = dir.entryList();
+// for (
+
+}
+
+
+QStringList OGenericPluginLoader::languageList() {
+ if ( languageList.isEmpty() ) {
+ /*
+ * be_BY.CP1251 We will add, be_BY.CP1251,be_BY,be
+ * to our list of languages.
+ */
+ QString str = ::getenv( "LANG" );
+ m_languages += str;
+ int pos = str.find( '.' );
+
+ if ( pos > 0 )
+ m_languages += str.left( pos );
+
+ int n_pos = str.find( '_' );
+ if ( pos > 0 && n_pos >= pos )
+ m_languages += str.left( n_pos );
+
+ }
+ return m_languages;
+}
+
+void OGenericPluginLoader::installTranslators(const QString& type) {
+ QStringList lst = languageList();
+ for ( QStringList::Iterator it = lst.begin(); it != lst.end(); ++it ) {
+ QTranslator* trans = new QTranslator( qApp );
+ QString tfn = QPEApplication::qpeDir()+"/i18n/" + lang + "/" + type + ".qm" ;
+ if ( trans->load( tfn ) )
+ qApp->installTranslator( trans );
+ else
+ delete trans;
+ }
+}
+
+
+
+}
+}
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 @@
+/*
+ * LGPLv2 or later
+ * zecke@handhelds.org
+ */
+#ifndef ODP_CORE_OPLUGIN_LOADER_H
+#define ODP_CORE_OPLUGIN_LOADER_H
+
+#include <qpe/qlibrary.h>
+
+#include <qstringlist.h>
+
+namespace Opie {
+namespace Core {
+class OConfig;
+namespace Internal {
+class OPluginLibraryHolder;
+}
+
+template class QPtrDict<QLibrary>;
+
+/**
+ * \brief A small item representing the Plugin Information
+ * This class contains the information about a Plugin. It contains
+ * a translated name if available to the system, a config key,
+ * and the path location.
+ *
+ * @since 1.2
+ *
+ */
+class OPluginItem {
+public:
+ typedef QValueList<OPluginItem> List;
+ OPluginItem();
+ OPluginItem( const QString& name, const QCString& confopt, const QString& path, int pos = -1 );
+ ~OPluginItem();
+
+ bool operator==( const OPluginItem& )const;
+ bool operator!=( const OPluginItem& )const;
+
+
+ QString name()const;
+ QCString configKey()const;
+ QString path()const;
+ int position()const;
+
+ void setName( const QString& );
+ void setConfigKey( const QCString& );
+ void setPath( const QString& );
+ void setPosition( int );
+
+private:
+ QString m_name;
+ QCString m_conf;
+ QString m_path;
+ int m_pos;
+ struct Private;
+ Private *d;
+};
+
+/**
+ * \brief A generic class to easily load and manage plugins
+ *
+ * This is the generic non sepcialised loader for plugins. Normally
+ * you would prefer using the OPluginLoader directly. This class
+ * exists to minimize the application binary size due the usage
+ * of templates in the specialized API
+ *
+ * @since 1.2
+ * @see OPluginLoader
+ */
+class OGenericPluginLoader {
+public:
+ typedef OPluginItem::List List;
+ OGenericPluginLoader( const QString &name, bool isSorted = false );
+ virtual ~OGenericPluginLoader();
+
+ void setAutoDelete( bool );
+ bool autoDelete()const;
+ void clear();
+
+
+ bool isInSafeMode()const;
+
+
+ List allAvailable(bool sorted = FALSE)const;
+ List filtered(bool sorted = FALSE)const;
+
+
+ virtual QUnknownInterface* load( const OPluginItem& item, const QUuid& );
+ virtual void unload( QUnknownInterface* );
+
+protected:
+ virtual void readConfig();
+ virtual List plugins( const QString& dir, bool sorted, bool disabled )const;
+ void setPluginDirs( const QStringList& );
+ void setPluginDir( const QString& );
+ bool &isSafeMode()const;
+ bool &isSorted()const;
+ void readConfig()const;
+ void setSafeMode(bool b = false);
+
+private:
+ QString languageList();
+ void installTranslators(const QString& type);
+ QString m_dir;
+ QStringList m_plugDirs;
+ QStringList m_languages;
+ bool m_autoDelete : 1;
+ bool m_isSafeMode : 1;
+ bool m_readConfig : 1;
+ bool m_isSorted : 1;
+ QPtrDict<QLibrary> m_library;
+
+ struct Private;
+ Private* d;
+};
+
+/**
+ * \brief The class to load your QCOM+ plugins
+ *
+ * This class takes care of activation and even the order
+ * if you need it. It is normally good to place a .directory file
+ * into your plugin directory if you need order of activation.
+ *
+ * You'll create the OPluginLoader and then use it to load the filtered
+ * plugins.
+ *
+ * There is also a GUI for the configuration and a Manager to write the
+ * mentioned .directory file
+ *
+ * On crash the safe mode is activated for the next run. You can then decide
+ * if you want to load plugins or come up with the Configuration on
+ * next start yourself then.
+ *
+ * @since 1.2
+ */
+class OPluginLoader : public OGenericPluginLoader {
+public:
+ OPluginLoader( const QString& name, bool sorted = false );
+ ~OPluginLoader();
+
+ temlate<class IFace>
+ IFace* load( const QString& name, const QUuid& );
+ temlate<class IFace>
+ IFace* load( const OPluginItem& item, const QUuid& );
+};
+
+/**
+ * \brief A class to manager order and activation of plugins
+ *
+ * Manage order and activation. This is used by the Opie::Ui::OPluginConfig
+ * This class controls the activation and order of plugins depending
+ * on the OPluginLoader you supply.
+ *
+ * @see OPluginConfig
+ *
+ */
+class OPluginManager {
+public:
+ OPluginManager( OGenericPluginLoader* , const QString& name);
+ OPluginManager( OConfig* conf, const QString&,
+ const QCString& group, const OPluginItem::List& );
+ ~OPluginManager();
+
+ QString name();
+ void setName( const QString& );
+
+ void setPosition( const OPluginItem& );
+ void enable( const OPluginItem& );
+ void disable( const OPluginItem& );
+ void setEnabled( const OPluginItem&, bool = true);
+
+ void load();
+ void save();
+};
+
+template<class IFace>
+IFace* OPluginLoader::load( const QString& name, const QUuid& uid ) {
+ return static_cast<IFace*>( OGenericPluginLoader::load( item, uid ) );
+}
+
+template<class IFace>
+IFace* OPluginLoader::load( const OPluginItem& item, const QUuid& uid ) {
+ return static_cast<IFace*>( OGenericPluginLoader::load( item, uid ) );
+}
+
+}
+}
+
+
+#endif