From e151de86a9c7ce1059707635e060ade699cfeea2 Mon Sep 17 00:00:00 2001 From: wonder Date: Wed, 12 Nov 2008 21:38:12 +0000 Subject: [PATCH] Moved plugin loading from QgisApp to QgsPluginRegistry git-svn-id: http://svn.osgeo.org/qgis/trunk@9630 c8812cc2-4d05-0410-92ff-de0c093fc19c --- src/app/qgisapp.cpp | 221 +------------------------------ src/app/qgisapp.h | 6 - src/app/qgspluginregistry.cpp | 237 +++++++++++++++++++++++++++++++++- src/app/qgspluginregistry.h | 18 +++ 4 files changed, 259 insertions(+), 223 deletions(-) diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp index 6511c4aa89d..14a30fe48de 100644 --- a/src/app/qgisapp.cpp +++ b/src/app/qgisapp.cpp @@ -187,11 +187,6 @@ class QTreeWidgetItem; -/* typedefs for plugins */ -typedef QgisPlugin *create_ui( QgisInterface * qI ); -typedef QString name_t(); -typedef QString description_t(); -typedef int type_t(); // IDs for locating particular menu items const int BEFORE_RECENT_PATHS = 123; @@ -397,7 +392,8 @@ QgisApp::QgisApp( QSplashScreen *splash, QWidget * parent, Qt::WFlags fl ) // load any plugins that were running in the last session mSplash->showMessage( tr( "Restoring loaded plugins" ), Qt::AlignHCenter | Qt::AlignBottom ); qApp->processEvents(); - restoreSessionPlugins( QgsApplication::pluginPath() ); + QgsPluginRegistry::instance()->setQgisInterface( mQgisInterface ); + QgsPluginRegistry::instance()->restoreSessionPlugins( QgsApplication::pluginPath() ); mSplash->showMessage( tr( "Initializing file filters" ), Qt::AlignHCenter | Qt::AlignBottom ); qApp->processEvents(); @@ -1827,109 +1823,7 @@ void QgisApp::about() abt->activateWindow(); } -/** Load up any plugins used in the last session -*/ -void QgisApp::restoreSessionPlugins( QString thePluginDirString ) -{ - QSettings mySettings; - -#ifdef WIN32 - QString pluginExt = "*.dll"; -#else - QString pluginExt = "*.so*"; -#endif - - // check all libs in the current plugin directory and get name and descriptions - QDir myPluginDir( thePluginDirString, pluginExt, QDir::Name | QDir::IgnoreCase, QDir::Files | QDir::NoSymLinks ); - - for ( uint i = 0; i < myPluginDir.count(); i++ ) - { - QString myFullPath = thePluginDirString + "/" + myPluginDir[i]; - - QString baseName = QFileInfo( myFullPath ).baseName(); - QLibrary *myLib = new QLibrary( myFullPath ); - bool loaded = myLib->load(); - if ( loaded ) - { - - name_t * myName = ( name_t * ) cast_to_fptr( myLib->resolve( "name" ) ); - description_t * myDescription = ( description_t * ) cast_to_fptr( myLib->resolve( "description" ) ); - version_t * myVersion = ( version_t * ) cast_to_fptr( myLib->resolve( "version" ) ); - if ( myName && myDescription && myVersion ) - { - //check if the plugin was active on last session - - // Windows stores a "true" value as a 1 in the registry so we - // have to use readBoolEntry in this function - - if ( mySettings.value( "/Plugins/" + baseName ).toBool() ) - { - //QgsDebugMsg("Loading plugin: " + myEntryName); - - loadPlugin( myFullPath, myName() ); - } - else - { - //QgsDebugMsg("Plugin was not active last session, leaving disabled: " + myEntryName); - } - } - else - { - //QgsDebugMsg("Failed to get name, description, or type for " + myLib->fileName()); - } - } - else - { - //QgsDebugMsg("Failed to load " + myLib->fileName()); - //QgsDebugMsg("Reason: " + myLib->errorString()); - } - delete myLib; - } - - QString pluginName, description, version; - - if ( mPythonUtils && mPythonUtils->isEnabled() ) - { - - // check for python plugins system-wide - QStringList pluginList = mPythonUtils->pluginList(); - std::cout << "Loading python plugins" << std::endl; // OK - - - for ( int i = 0; i < pluginList.size(); i++ ) - { - QString packageName = pluginList[i]; - - // import plugin's package - if ( !mPythonUtils->loadPlugin( packageName ) ) - continue; - - // get information from the plugin - // if there are some problems, don't continue with metadata retreival - pluginName = mPythonUtils->getPluginMetadata( packageName, "name" ); - if ( pluginName != "__error__" ) - { - description = mPythonUtils->getPluginMetadata( packageName, "description" ); - if ( description != "__error__" ) - version = mPythonUtils->getPluginMetadata( packageName, "version" ); - } - - if ( pluginName == "__error__" || description == "__error__" || version == "__error__" ) - { - QMessageBox::warning( this, tr( "Python error" ), tr( "Error when reading metadata of plugin " ) + packageName ); - continue; - } - - if ( mySettings.value( "/PythonPlugins/" + packageName ).toBool() ) - { - loadPythonPlugin( packageName, pluginName ); - } - } - } - std::cout << "Plugin loading completed" << std::endl; // OK - -} /** @@ -4131,6 +4025,7 @@ void QgisApp::showPluginManager() pm->resizeColumnsToContents(); if ( pm->exec() ) { + QgsPluginRegistry* pRegistry = QgsPluginRegistry::instance(); // load selected plugins std::vector < QgsPluginItem > pi = pm->getSelectedPlugins(); std::vector < QgsPluginItem >::iterator it = pi.begin(); @@ -4139,11 +4034,11 @@ void QgisApp::showPluginManager() QgsPluginItem plugin = *it; if ( plugin.isPython() ) { - loadPythonPlugin( plugin.fullPath(), plugin.name() ); + pRegistry->loadPythonPlugin( plugin.fullPath() ); } else { - loadPlugin( plugin.fullPath(), plugin.name() ); + pRegistry->loadCppPlugin( plugin.fullPath() ); } it++; } @@ -4200,112 +4095,6 @@ void QgisApp::loadPythonSupport() } } -void QgisApp::loadPythonPlugin( QString packageName, QString pluginName ) -{ - if ( !mPythonUtils || !mPythonUtils->isEnabled() ) - { - QgsDebugMsg( "Python is not enabled in QGIS." ); - return; - } - - - QgsPluginRegistry *pRegistry = QgsPluginRegistry::instance(); - - // is loaded already? - if ( ! pRegistry->isLoaded( packageName ) ) - { - mPythonUtils->loadPlugin( packageName ); - mPythonUtils->startPlugin( packageName ); - - // TODO: test success - - // add to plugin registry - pRegistry->addPlugin( packageName, QgsPluginMetadata( packageName, pluginName, NULL, true ) ); - - // add to settings - QSettings settings; - settings.setValue( "/PythonPlugins/" + packageName, true ); - std::cout << "Loaded : " << pluginName.toLocal8Bit().constData() << " (package: " - << packageName.toLocal8Bit().constData() << ")" << std::endl; // OK - - } -} - -void QgisApp::loadPlugin( QString theFullPathName, QString name ) -{ - QSettings settings; - // first check to see if its already loaded - QgsPluginRegistry *pRegistry = QgsPluginRegistry::instance(); - - QString baseName = QFileInfo( theFullPathName ).baseName(); - - if ( pRegistry->isLoaded( baseName ) ) - { - // plugin is loaded - // QMessageBox::warning(this, "Already Loaded", description + " is already loaded"); - } - else - { - QLibrary *myLib = new QLibrary( theFullPathName ); - - QString myError; //we will only show detailed diagnostics if something went wrong - myError += "Library name is " + myLib->fileName() + " " + QString( __LINE__ ) + " in " + QString( __FUNCTION__ ) + "\n"; - - bool loaded = myLib->load(); - if ( loaded ) - { - myError += "Attempting to resolve the classFactory function " + QString( __LINE__ ) + " in " + QString( __FUNCTION__ ) + "\n"; - - type_t *pType = ( type_t * ) cast_to_fptr( myLib->resolve( "type" ) ); - - switch ( pType() ) - { - case QgisPlugin::RENDERER: - case QgisPlugin::UI: - { - // UI only -- doesn't use mapcanvas - create_ui *cf = ( create_ui * ) cast_to_fptr( myLib->resolve( "classFactory" ) ); - if ( cf ) - { - QgisPlugin *pl = cf( mQgisInterface ); - if ( pl ) - { - pl->initGui(); - // add it to the plugin registry - pRegistry->addPlugin( baseName, QgsPluginMetadata( myLib->fileName(), name, pl ) ); - //add it to the qsettings file [ts] - settings.setValue( "/Plugins/" + baseName, true ); - } - else - { - // something went wrong - QMessageBox::warning( this, tr( "Error Loading Plugin" ), tr( "There was an error loading a plugin." - "The following diagnostic information may help the QGIS developers resolve the issue:\n%1." ).arg - ( myError ) ); - //disable it to the qsettings file [ts] - settings.setValue( "/Plugins/" + baseName, false ); - } - } - else - { - QgsDebugMsg( "Unable to find the class factory for " + theFullPathName ); - } - - } - break; - default: - // type is unknown - QgsDebugMsg( "Plugin " + theFullPathName + " did not return a valid type and cannot be loaded" ); - break; - } - } - else - { - QgsDebugMsg( "Failed to load " + theFullPathName ); - } - delete myLib; - } -} void QgisApp::checkQgisVersion() diff --git a/src/app/qgisapp.h b/src/app/qgisapp.h index d92290cf06d..6919cf2ac70 100644 --- a/src/app/qgisapp.h +++ b/src/app/qgisapp.h @@ -378,16 +378,10 @@ class QgisApp : public QMainWindow void zoomToLayerExtent(); //! zoom to actual size of raster layer void zoomActualSize(); - //! load any plugins used in the last qgis session - void restoreSessionPlugins( QString thePluginDirString ); //! plugin manager void showPluginManager(); //! load python support if possible void loadPythonSupport(); - //! plugin loader - void loadPlugin( QString mFullPath, QString name ); - //! python plugin loader - void loadPythonPlugin( QString packageName, QString pluginName ); //! Find the QMenu with the given name (ie the user visible text on the menu item) QMenu* getPluginMenu( QString menuName ); //! Add the action to the submenu with the given name under the plugin menu diff --git a/src/app/qgspluginregistry.cpp b/src/app/qgspluginregistry.cpp index 4380561d70a..bd641c1d6ff 100644 --- a/src/app/qgspluginregistry.cpp +++ b/src/app/qgspluginregistry.cpp @@ -17,12 +17,28 @@ ***************************************************************************/ /* $Id$ */ +#include +#include +#include +#include +#include + +#include "qgis.h" +#include "qgisinterface.h" #include "qgspluginregistry.h" #include "qgspluginmetadata.h" #include "qgisplugin.h" #include "qgspythonutils.h" #include "qgslogger.h" + +/* typedefs for plugins */ +typedef QgisPlugin *create_ui( QgisInterface * qI ); +typedef QString name_t(); +typedef QString description_t(); +typedef int type_t(); + + QgsPluginRegistry *QgsPluginRegistry::_instance = 0; QgsPluginRegistry *QgsPluginRegistry::instance() { @@ -34,11 +50,16 @@ QgsPluginRegistry *QgsPluginRegistry::instance() } QgsPluginRegistry::QgsPluginRegistry() - : mPythonUtils( NULL ) + : mPythonUtils( NULL ), mQgisInterface( NULL ) { // constructor does nothing } +void QgsPluginRegistry::setQgisInterface( QgisInterface* iface ) +{ + mQgisInterface = iface; +} + void QgsPluginRegistry::setPythonUtils( QgsPythonUtils* pythonUtils ) { mPythonUtils = pythonUtils; @@ -129,3 +150,217 @@ void QgsPluginRegistry::unloadAll() } } } + + + +void QgsPluginRegistry::loadPythonPlugin( QString packageName ) +{ + if ( !mPythonUtils || !mPythonUtils->isEnabled() ) + { + QgsDebugMsg( "Python is not enabled in QGIS." ); + return; + } + + // is loaded already? + if ( ! isLoaded( packageName ) ) + { + mPythonUtils->loadPlugin( packageName ); + mPythonUtils->startPlugin( packageName ); + + // TODO: test success + + QString pluginName = mPythonUtils->getPluginMetadata( packageName, "name" ); + + // add to plugin registry + addPlugin( packageName, QgsPluginMetadata( packageName, pluginName, NULL, true ) ); + + // add to settings + QSettings settings; + settings.setValue( "/PythonPlugins/" + packageName, true ); + std::cout << "Loaded : " << pluginName.toLocal8Bit().constData() << " (package: " + << packageName.toLocal8Bit().constData() << ")" << std::endl; // OK + + } +} + + +void QgsPluginRegistry::loadCppPlugin( QString theFullPathName ) +{ + QSettings settings; + + QString baseName = QFileInfo( theFullPathName ).baseName(); + + // first check to see if its already loaded + if ( isLoaded( baseName ) ) + { + // plugin is loaded + // QMessageBox::warning(this, "Already Loaded", description + " is already loaded"); + return; + } + + QLibrary myLib( theFullPathName ); + + QString myError; //we will only show detailed diagnostics if something went wrong + myError += "Library name is " + myLib.fileName() + " " + QString( __LINE__ ) + " in " + QString( __FUNCTION__ ) + "\n"; + + bool loaded = myLib.load(); + if ( ! loaded ) + { + QgsDebugMsg( "Failed to load " + theFullPathName ); + return; + } + + myError += "Attempting to resolve the classFactory function " + QString( __LINE__ ) + " in " + QString( __FUNCTION__ ) + "\n"; + + type_t *pType = ( type_t * ) cast_to_fptr( myLib.resolve( "type" ) ); + name_t *pName = ( name_t * ) cast_to_fptr( myLib.resolve( "name" ) ); + + switch ( pType() ) + { + case QgisPlugin::RENDERER: + case QgisPlugin::UI: + { + // UI only -- doesn't use mapcanvas + create_ui *cf = ( create_ui * ) cast_to_fptr( myLib.resolve( "classFactory" ) ); + if ( cf ) + { + QgisPlugin *pl = cf( mQgisInterface ); + if ( pl ) + { + pl->initGui(); + // add it to the plugin registry + addPlugin( baseName, QgsPluginMetadata( myLib.fileName(), pName(), pl ) ); + //add it to the qsettings file [ts] + settings.setValue( "/Plugins/" + baseName, true ); + } + else + { + // something went wrong + QMessageBox::warning( mQgisInterface->mainWindow(), QObject::tr( "Error Loading Plugin" ), + QObject::tr( "There was an error loading a plugin." + "The following diagnostic information may help the QGIS developers resolve the issue:\n%1." ).arg + ( myError ) ); + //disable it to the qsettings file [ts] + settings.setValue( "/Plugins/" + baseName, false ); + } + } + else + { + QgsDebugMsg( "Unable to find the class factory for " + theFullPathName ); + } + + } + break; + default: + // type is unknown + QgsDebugMsg( "Plugin " + theFullPathName + " did not return a valid type and cannot be loaded" ); + break; + } + +} + + +void QgsPluginRegistry::restoreSessionPlugins( QString thePluginDirString ) +{ + QSettings mySettings; + +#ifdef WIN32 + QString pluginExt = "*.dll"; +#else + QString pluginExt = "*.so*"; +#endif + + // check all libs in the current plugin directory and get name and descriptions + QDir myPluginDir( thePluginDirString, pluginExt, QDir::Name | QDir::IgnoreCase, QDir::Files | QDir::NoSymLinks ); + + for ( uint i = 0; i < myPluginDir.count(); i++ ) + { + QString myFullPath = thePluginDirString + "/" + myPluginDir[i]; + if (checkCppPlugin( myFullPath ) ) + { + // check if the plugin was active on last session + + QString baseName = QFileInfo( myFullPath ).baseName(); + if ( mySettings.value( "/Plugins/" + baseName ).toBool() ) + { + loadCppPlugin( myFullPath ); + } + } + } + + if ( mPythonUtils && mPythonUtils->isEnabled() ) + { + // check for python plugins system-wide + QStringList pluginList = mPythonUtils->pluginList(); + QgsDebugMsg("Loading python plugins"); + + for ( int i = 0; i < pluginList.size(); i++ ) + { + QString packageName = pluginList[i]; + + if (checkPythonPlugin( packageName ) ) + { + // check if the plugin was active on last session + + if ( mySettings.value( "/PythonPlugins/" + packageName ).toBool() ) + { + loadPythonPlugin( packageName ); + } + } + } + } + + QgsDebugMsg("Plugin loading completed"); +} + + +bool QgsPluginRegistry::checkCppPlugin( QString pluginFullPath ) +{ + QLibrary myLib( pluginFullPath ); + bool loaded = myLib.load(); + if ( ! loaded ) + { + //QgsDebugMsg("Failed to load " + myLib.fileName()); + //QgsDebugMsg("Reason: " + myLib.errorString()); + return false; + } + + name_t * myName = ( name_t * ) cast_to_fptr( myLib.resolve( "name" ) ); + description_t * myDescription = ( description_t * ) cast_to_fptr( myLib.resolve( "description" ) ); + version_t * myVersion = ( version_t * ) cast_to_fptr( myLib.resolve( "version" ) ); + + if ( myName && myDescription && myVersion ) + return true; + + QgsDebugMsg("Failed to get name, description, or type for " + myLib.fileName()); + return false; +} + + +bool QgsPluginRegistry::checkPythonPlugin( QString packageName ) +{ + // import plugin's package + if ( !mPythonUtils->loadPlugin( packageName ) ) + return false; + + QString pluginName, description, version; + + // get information from the plugin + // if there are some problems, don't continue with metadata retreival + pluginName = mPythonUtils->getPluginMetadata( packageName, "name" ); + if ( pluginName != "__error__" ) + { + description = mPythonUtils->getPluginMetadata( packageName, "description" ); + if ( description != "__error__" ) + version = mPythonUtils->getPluginMetadata( packageName, "version" ); + } + + if ( pluginName == "__error__" || description == "__error__" || version == "__error__" ) + { + QMessageBox::warning( mQgisInterface->mainWindow(), QObject::tr( "Python error" ), + QObject::tr( "Error when reading metadata of plugin " ) + packageName ); + return false; + } + + return true; +} diff --git a/src/app/qgspluginregistry.h b/src/app/qgspluginregistry.h index 8d1c3efcfd4..b6d314388e3 100644 --- a/src/app/qgspluginregistry.h +++ b/src/app/qgspluginregistry.h @@ -25,6 +25,7 @@ class QgsPluginMetadata; class QgsPythonUtils; class QgisPlugin; +class QgisInterface; class QString; /** @@ -41,6 +42,9 @@ class QgsPluginRegistry public: //! Returns the instance pointer, creating the object on the first call static QgsPluginRegistry* instance(); + + //! set pointer to qgis interface passed to plugins (used by QgisApp) + void setQgisInterface( QgisInterface* iface ); //! Check whether this module is loaded bool isLoaded( QString key ); @@ -69,13 +73,27 @@ class QgsPluginRegistry //! Dump list of plugins void dump(); + //! C++ plugin loader + void loadCppPlugin( QString mFullPath ); + //! Python plugin loader + void loadPythonPlugin( QString packageName ); + + //! Load any plugins used in the last qgis session + void restoreSessionPlugins( QString thePluginDirString ); + protected: //! protected constructor QgsPluginRegistry(); + //! Try to load and get metadata from c++ plugin, return true on success + bool checkCppPlugin( QString pluginFullPath ); + //! Try to load and get metadata from Python plugin, return true on success + bool checkPythonPlugin( QString packageName ); + private: static QgsPluginRegistry* _instance; QMap mPlugins; QgsPythonUtils* mPythonUtils; + QgisInterface* mQgisInterface; }; #endif //QgsPluginRegistry_H