diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp index c2d15347139..6d0ad40550b 100644 --- a/src/app/qgisapp.cpp +++ b/src/app/qgisapp.cpp @@ -119,6 +119,7 @@ #include "qgspastetransformations.h" #include "qgspluginitem.h" #include "qgspluginmanager.h" +#include "qgspluginmetadata.h" #include "qgspluginregistry.h" #include "qgspoint.h" #include "qgsproject.h" @@ -1846,7 +1847,7 @@ void QgisApp::restoreSessionPlugins( QString thePluginDirString ) { QString myFullPath = thePluginDirString + "/" + myPluginDir[i]; - + QString baseName = QFileInfo(myFullPath).baseName(); QLibrary *myLib = new QLibrary( myFullPath ); bool loaded = myLib->load(); if ( loaded ) @@ -1858,15 +1859,15 @@ void QgisApp::restoreSessionPlugins( QString thePluginDirString ) if ( myName && myDescription && myVersion ) { //check if the plugin was active on last session - QString myEntryName = myName(); + // Windows stores a "true" value as a 1 in the registry so we // have to use readBoolEntry in this function - if ( mySettings.value( "/Plugins/" + myEntryName ).toBool() ) + if ( mySettings.value( "/Plugins/" + baseName ).toBool() ) { //QgsDebugMsg("Loading plugin: " + myEntryName); - loadPlugin( myName(), myDescription(), myFullPath ); + loadPlugin( myFullPath, myName() ); } else { @@ -4142,7 +4143,7 @@ void QgisApp::showPluginManager() } else { - loadPlugin( plugin.name(), plugin.description(), plugin.fullPath() ); + loadPlugin( plugin.fullPath(), plugin.name() ); } it++; } @@ -4209,9 +4210,9 @@ void QgisApp::loadPythonPlugin( QString packageName, QString pluginName ) QgsPluginRegistry *pRegistry = QgsPluginRegistry::instance(); - + // is loaded already? - if ( pRegistry->library( pluginName ).isEmpty() ) + if ( ! pRegistry->isLoaded(packageName) ) { mPythonUtils->loadPlugin( packageName ); mPythonUtils->startPlugin( packageName ); @@ -4219,7 +4220,7 @@ void QgisApp::loadPythonPlugin( QString packageName, QString pluginName ) // TODO: test success // add to plugin registry - pRegistry->addPythonPlugin( packageName, pluginName ); + pRegistry->addPlugin( packageName, QgsPluginMetadata( packageName, pluginName, NULL, true) ); // add to settings QSettings settings; @@ -4230,13 +4231,15 @@ void QgisApp::loadPythonPlugin( QString packageName, QString pluginName ) } } -void QgisApp::loadPlugin( QString name, QString description, QString theFullPathName ) +void QgisApp::loadPlugin( QString theFullPathName, QString name ) { QSettings settings; // first check to see if its already loaded QgsPluginRegistry *pRegistry = QgsPluginRegistry::instance(); - QString lib = pRegistry->library( name ); - if ( lib.length() > 0 ) + + QString baseName = QFileInfo(theFullPathName).baseName(); + + if ( pRegistry->isLoaded(baseName) ) { // plugin is loaded // QMessageBox::warning(this, "Already Loaded", description + " is already loaded"); @@ -4269,9 +4272,9 @@ void QgisApp::loadPlugin( QString name, QString description, QString theFullPath { pl->initGui(); // add it to the plugin registry - pRegistry->addPlugin( myLib->fileName(), name, pl ); + pRegistry->addPlugin(baseName, QgsPluginMetadata(myLib->fileName(), name, pl) ); //add it to the qsettings file [ts] - settings.setValue( "/Plugins/" + name, true ); + settings.setValue( "/Plugins/" + baseName, true ); } else { @@ -4280,7 +4283,7 @@ void QgisApp::loadPlugin( QString name, QString description, QString theFullPath "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/" + name, false ); + settings.setValue( "/Plugins/" + baseName, false ); } } else @@ -4290,6 +4293,8 @@ void QgisApp::loadPlugin( QString name, QString description, QString theFullPath } break; +/* + // TODO: to be removed completely case QgisPlugin::MAPLAYER: { // Map layer - requires interaction with the canvas @@ -4320,6 +4325,7 @@ void QgisApp::loadPlugin( QString name, QString description, QString theFullPath } } break; +*/ default: // type is unknown QgsDebugMsg( "Plugin " + theFullPathName + " did not return a valid type and cannot be loaded" ); diff --git a/src/app/qgisapp.h b/src/app/qgisapp.h index df02cd1e3d8..93b5f284adb 100644 --- a/src/app/qgisapp.h +++ b/src/app/qgisapp.h @@ -385,7 +385,7 @@ class QgisApp : public QMainWindow //! load python support if possible void loadPythonSupport(); //! plugin loader - void loadPlugin( QString name, QString description, QString mFullPath ); + 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) diff --git a/src/app/qgspluginitem.cpp b/src/app/qgspluginitem.cpp index 3640984eeb3..5fcb2ed1890 100644 --- a/src/app/qgspluginitem.cpp +++ b/src/app/qgspluginitem.cpp @@ -17,8 +17,8 @@ /* $Id$ */ #include "qgspluginitem.h" -QgsPluginItem::QgsPluginItem( QString _name, QString _description, QString _fullPath, QString _type, bool _python ): - m_name( _name ), m_description( _description ), m_fullPath( _fullPath ), m_type( _type ), m_python( _python ) +QgsPluginItem::QgsPluginItem( QString _name, QString _fullPath, QString _type, bool _python ): + m_name( _name ), m_fullPath( _fullPath ), m_type( _type ), m_python( _python ) { } diff --git a/src/app/qgspluginitem.h b/src/app/qgspluginitem.h index a981f48f777..827173389d8 100644 --- a/src/app/qgspluginitem.h +++ b/src/app/qgspluginitem.h @@ -26,7 +26,7 @@ Class to contain information about a loadable plugin, including its name, descri class QgsPluginItem { public: - QgsPluginItem( QString name = 0, QString description = 0, QString fullPath = 0, QString type = 0, bool python = false ); + QgsPluginItem( QString name = 0, QString fullPath = 0, QString type = 0, bool python = false ); QString name(); QString description(); QString fullPath(); diff --git a/src/app/qgspluginmanager.cpp b/src/app/qgspluginmanager.cpp index 3d04ddc95fa..7aaa5c46055 100644 --- a/src/app/qgspluginmanager.cpp +++ b/src/app/qgspluginmanager.cpp @@ -55,7 +55,7 @@ const int PLUGIN_DATA_ROLE = Qt::UserRole; const int PLUGIN_LIBRARY_ROLE = Qt::UserRole + 1; -const int PLUGIN_LIBRARY_NAME_ROLE = Qt::UserRole + 2; +const int PLUGIN_BASE_NAME_ROLE = Qt::UserRole + 2; QgsPluginManager::QgsPluginManager( QgsPythonUtils* pythonUtils, QWidget * parent, Qt::WFlags fl ) : QDialog( parent, fl ) @@ -151,9 +151,9 @@ void QgsPluginManager::getPythonPluginDescriptions() // filtering will be done on the display role so give it name and desription // user wont see this text since we are using a custome delegate QStandardItem * mypDetailItem = new QStandardItem( pluginName + " - " + description ); - QString myLibraryName = "python:" + packageName;; + QString myLibraryName = "python:" + packageName; mypDetailItem->setData( myLibraryName, PLUGIN_LIBRARY_ROLE ); //for loading libs later - mypDetailItem->setData( pluginName, PLUGIN_LIBRARY_NAME_ROLE ); //for matching in registry later + mypDetailItem->setData( packageName, PLUGIN_BASE_NAME_ROLE ); //for matching in registry later mypDetailItem->setCheckable( false ); mypDetailItem->setEditable( false ); // setData in the delegate with a variantised QgsDetailedItemData @@ -167,19 +167,15 @@ void QgsPluginManager::getPythonPluginDescriptions() // check to see if the plugin is loaded and set the checkbox accordingly QgsPluginRegistry *pRegistry = QgsPluginRegistry::instance(); - QString libName = pRegistry->library( pluginName ); - if ( libName.length() == 0 || !pRegistry->isPythonPlugin( pluginName ) ) + if ( pRegistry->isLoaded(packageName) && pRegistry->isPythonPlugin(packageName) ) { - QgsDebugMsg( "Couldn't find library name in the registry" ); + QgsDebugMsg( "Found plugin in the registry" ); + // set the checkbox + myData.setChecked( true ); } else { - QgsDebugMsg( "Found library name in the registry" ); - if ( libName == packageName ) - { - // set the checkbox - myData.setChecked( true ); - } + QgsDebugMsg( "Couldn't find plugin in the registry: " + packageName ); } QVariant myVariant = qVariantFromValue( myData ); mypDetailItem->setData( myVariant, PLUGIN_DATA_ROLE ); @@ -297,40 +293,40 @@ void QgsPluginManager::getPluginDescriptions() delete myLib; continue; } + + QString pluginName = pName(); + QString pluginDesc = pDesc(); + QString pluginVersion = pVersion(); + QString baseName = QFileInfo(lib).baseName(); QString myLibraryName = pluginDir[i]; // filtering will be done on the display role so give it name and desription // user wont see this text since we are using a custome delegate - QStandardItem * mypDetailItem = new QStandardItem( pName() + " - " + pDesc() ); + QStandardItem * mypDetailItem = new QStandardItem( pluginName + " - " + pluginDesc ); mypDetailItem->setData( myLibraryName, PLUGIN_LIBRARY_ROLE ); - mypDetailItem->setData( pName(), PLUGIN_LIBRARY_NAME_ROLE ); //for matching in registry later + mypDetailItem->setData( baseName, PLUGIN_BASE_NAME_ROLE ); //for matching in registry later QgsDetailedItemData myData; - myData.setTitle( pName() ); - myData.setDetail( pDesc() ); + myData.setTitle( pluginName ); + myData.setDetail( pluginDesc ); myData.setRenderAsWidget( false ); myData.setCheckable( true ); myData.setChecked( false ); //start unchecked - we will check it later if needed - //round trip test - delete this...no need to uncomment - //QgsDetailedItemData myData2 = qVariantValue(myVariant); - //Q_ASSERT(myData.title() == myData2.title()); - //round trip test ends - QgsDebugMsg( "Getting an instance of the QgsPluginRegistry" ); // check to see if the plugin is loaded and set the checkbox accordingly QgsPluginRegistry *pRegistry = QgsPluginRegistry::instance(); - QString libName = pRegistry->library( pName() ); // get the library using the plugin description - if ( libName.length() == 0 ) + if ( !pRegistry->isLoaded(baseName) ) { - QgsDebugMsg( "Couldn't find library name in the registry" ); + QgsDebugMsg( "Couldn't find plugin in the registry" ); } else { - QgsDebugMsg( "Found library name in the registry" ); - if ( libName == myLib->fileName() ) + QgsDebugMsg( "Found plugin in the registry" ); + // TODO: this check shouldn't be necessary, plugin base names must be unique + if ( pRegistry->library(baseName) == myLib->fileName() ) { // set the checkbox myData.setChecked( true ); @@ -367,32 +363,36 @@ void QgsPluginManager::unload() myIndex = mModelPlugins->index( row, 0 ); // its off -- see if it is loaded and if so, unload it QgsPluginRegistry *pRegistry = QgsPluginRegistry::instance(); - QgsDebugMsg( QString( "Checking to see if %1 is loaded" ).arg( mModelPlugins->data( myIndex, PLUGIN_LIBRARY_NAME_ROLE ).toString() ) ); - QString pluginName = mModelPlugins->data( myIndex, PLUGIN_LIBRARY_NAME_ROLE ).toString(); - if ( pRegistry->isPythonPlugin( pluginName ) ) + + // is loaded? + QString baseName = mModelPlugins->data( myIndex, PLUGIN_BASE_NAME_ROLE ).toString(); + if ( ! pRegistry->isLoaded( baseName ) ) + continue; + + if ( pRegistry->isPythonPlugin( baseName ) ) { if ( mPythonUtils && mPythonUtils->isEnabled() ) { - QString packageName = pRegistry->library( pluginName ); - mPythonUtils->unloadPlugin( packageName ); + mPythonUtils->unloadPlugin( baseName ); //disable it to the qsettings file - settings.setValue( "/PythonPlugins/" + packageName, false ); + settings.setValue( "/PythonPlugins/" + baseName, false ); } } else // C++ plugin { - QgisPlugin *plugin = pRegistry->plugin( pluginName ); + QgisPlugin *plugin = pRegistry->plugin( baseName ); if ( plugin ) { plugin->unload(); } //disable it to the qsettings file [ts] - settings.setValue( "/Plugins/" + pluginName, false ); + settings.setValue( "/Plugins/" + baseName, false ); } // remove the plugin from the registry - pRegistry->removePlugin( pluginName ); + pRegistry->removePlugin( baseName ); } } + QgsPluginRegistry::instance()->dump(); } std::vector < QgsPluginItem > QgsPluginManager::getSelectedPlugins() @@ -406,7 +406,8 @@ std::vector < QgsPluginItem > QgsPluginManager::getSelectedPlugins() if ( myData.isChecked() ) { - QString pluginName = mModelPlugins->item( row, 0 )->data( PLUGIN_LIBRARY_NAME_ROLE ).toString(); + //QString baseName = mModelPlugins->item( row, 0 )->data( PLUGIN_BASE_NAME_ROLE ).toString(); + QString pluginName = mModelPlugins->item( row, 0 )->data( Qt::DisplayRole ).toString(); bool pythonic = false; QString library = mModelPlugins->item( row, 0 )->data( PLUGIN_LIBRARY_ROLE ).toString(); @@ -425,9 +426,7 @@ std::vector < QgsPluginItem > QgsPluginManager::getSelectedPlugins() // QString fullPath=0, // QString type=0, // bool python=false); - pis.push_back( QgsPluginItem( pluginName, - mModelPlugins->item( row, 0 )->data( Qt::DisplayRole ).toString(), //display role - library, 0, pythonic ) ); + pis.push_back( QgsPluginItem( pluginName, library, 0, pythonic ) ); } } @@ -472,9 +471,10 @@ void QgsPluginManager::on_vwPlugins_clicked( const QModelIndex &theIndex ) // the index row in the underlying model so we need to jump through this // little hoop to get the correct item // - QStandardItem * mypItem = - mModelPlugins->findItems( theIndex.data( Qt ::DisplayRole ).toString() ).first(); - QgsDetailedItemData myData = + + QModelIndex realIndex = mModelProxy->mapToSource(theIndex); + QStandardItem* mypItem = mModelPlugins->itemFromIndex(realIndex); + QgsDetailedItemData myData = qVariantValue( mypItem->data( PLUGIN_DATA_ROLE ) ); if ( myData.isChecked() ) { diff --git a/src/app/qgspluginregistry.cpp b/src/app/qgspluginregistry.cpp index d1d60263725..2a87bcee56d 100644 --- a/src/app/qgspluginregistry.cpp +++ b/src/app/qgspluginregistry.cpp @@ -44,77 +44,88 @@ void QgsPluginRegistry::setPythonUtils( QgsPythonUtils* pythonUtils ) mPythonUtils = pythonUtils; } -QString QgsPluginRegistry::library( QString pluginKey ) +bool QgsPluginRegistry::isLoaded( QString key ) { - QgsPluginMetadata *pmd = plugins[pluginKey]; - QString retval; - if ( pmd ) - { - retval = pmd->library(); - } - return retval; + QMap::iterator it = mPlugins.find(key); + return (it != mPlugins.end()); } -QgsPluginMetadata *QgsPluginRegistry::pluginMetadata( QString name ) +QString QgsPluginRegistry::library( QString key ) { - return plugins[name]; + QMap::iterator it = mPlugins.find(key); + if (it == mPlugins.end()) + return QString(); + + return it->library(); } -QgisPlugin *QgsPluginRegistry::plugin( QString name ) +QgisPlugin *QgsPluginRegistry::plugin( QString key ) { - QgsPluginMetadata *pmd = plugins[name]; - QgisPlugin *retval = 0; - if ( pmd ) - { - retval = pmd->plugin(); - } - return retval; + QMap::iterator it = mPlugins.find(key); + if (it == mPlugins.end()) + return NULL; + + return it->plugin(); } -bool QgsPluginRegistry::isPythonPlugin( QString name ) +bool QgsPluginRegistry::isPythonPlugin( QString key ) { - QgsPluginMetadata* pmd = plugins[name]; - if ( pmd ) - return pmd->isPython(); - else + QMap::iterator it = mPlugins.find(key); + if (it == mPlugins.end()) return false; + return it->isPython(); } -void QgsPluginRegistry::addPlugin( QString library, QString name, QgisPlugin * plugin ) +void QgsPluginRegistry::addPlugin( QString key, QgsPluginMetadata metadata ) { - plugins[name] = new QgsPluginMetadata( library, name, plugin ); + mPlugins.insert(key, metadata); +} + +void QgsPluginRegistry::dump() +{ + QgsDebugMsg("PLUGINS IN REGISTRY: key -> (name, library, isPython)"); + for ( QMap::iterator it = mPlugins.begin(); + it != mPlugins.end(); + it++ ) + { + QgsDebugMsg(QString("PLUGIN: %1 -> (%2, %3, %4)") + .arg(it.key()) + .arg(it->name()) + .arg(it->library()) + .arg(it->isPython())); + } } -void QgsPluginRegistry::addPythonPlugin( QString packageName, QString pluginName ) +void QgsPluginRegistry::removePlugin( QString key ) { - plugins[pluginName] = new QgsPluginMetadata( packageName, pluginName, NULL, true ); // true == python plugin -} - -void QgsPluginRegistry::removePlugin( QString name ) -{ - plugins.erase( name ); + QgsDebugMsg("removing plugin: "+key); + QMap::iterator it = mPlugins.find(key); + if (it != mPlugins.end()) + { + mPlugins.erase( it ); + } } void QgsPluginRegistry::unloadAll() { - for ( std::map::iterator it = plugins.begin(); - it != plugins.end(); + for ( QMap::iterator it = mPlugins.begin(); + it != mPlugins.end(); it++ ) { - if ( isPythonPlugin( it->second->name() ) ) + if (isPythonPlugin(it.key())) { - if ( mPythonUtils ) - mPythonUtils->unloadPlugin( it->second->library() ); + if (mPythonUtils) + mPythonUtils->unloadPlugin(it->library()); else QgsDebugMsg( "warning: python utils is NULL" ); } else { - if ( it->second->plugin() ) - it->second->plugin()->unload(); + if ( it->plugin() ) + it->plugin()->unload(); else - QgsDebugMsg( "warning: plugin is NULL:" + it->second->name() ); + QgsDebugMsg("warning: plugin is NULL:" + it.key()); } } } diff --git a/src/app/qgspluginregistry.h b/src/app/qgspluginregistry.h index e0b7dd3d72b..fe9eb7ec4ee 100644 --- a/src/app/qgspluginregistry.h +++ b/src/app/qgspluginregistry.h @@ -19,45 +19,63 @@ #ifndef QGSPLUGINREGISTRY_H #define QGSPLUGINREGISTRY_H -#include + +#include + class QgsPluginMetadata; class QgsPythonUtils; class QgisPlugin; class QString; + /** * \class QgsPluginRegistry * \brief This class tracks plugins that are currently loaded an provides * a means to fetch a pointer to a plugin and unload it +* +* plugin key is: +* - C++ plugins: base name of plugin library, e.g. libgrassplugin +* - Python plugins: module name (directory) of plugin, e.g. plugin_installer */ class QgsPluginRegistry { public: //! Returns the instance pointer, creating the object on the first call static QgsPluginRegistry* instance(); - //! Return the full path to the plugins library using the plugin name as a key - QString library( QString pluginKey ); - //! Retrieve the metadata for a plugin by name - QgsPluginMetadata * pluginMetadata( QString name ); - //! Retrieve a pointer to a loaded plugin by name - QgisPlugin * plugin( QString name ); + + //! Check whether this module is loaded + bool isLoaded( QString key ); + + //! Retrieve library of the plugin + QString library( QString key ); + + //! Retrieve a pointer to a loaded plugin + QgisPlugin * plugin( QString key ); + //! Return whether the plugin is pythonic - bool isPythonPlugin( QString name ); + bool isPythonPlugin( QString key ); + //! Add a plugin to the map of loaded plugins - void addPlugin( QString _library, QString _name, QgisPlugin * _plugin ); - //! Add a plugin written in python - void addPythonPlugin( QString packageName, QString pluginName ); + void addPlugin( QString key, QgsPluginMetadata metadata ); + //! Remove a plugin from the list of loaded plugins - void removePlugin( QString name ); + void removePlugin( QString key ); + //! Unload plugins void unloadAll(); + //! Save pointer for python utils (needed for unloading python plugins) void setPythonUtils( QgsPythonUtils* pythonUtils ); + + //! Dump list of plugins + void dump(); + protected: //! protected constructor QgsPluginRegistry(); + private: static QgsPluginRegistry* _instance; - std::map plugins; + QMap mPlugins; QgsPythonUtils* mPythonUtils; }; #endif //QgsPluginRegistry_H