diff --git a/python/core/core.sip b/python/core/core.sip index 4469b1805e8..85ca3fc8dca 100644 --- a/python/core/core.sip +++ b/python/core/core.sip @@ -26,6 +26,8 @@ %Include qgscrscache.sip %Include qgsdatadefined.sip %Include qgsdataitem.sip +%Include qgsdataitemprovider.sip +%Include qgsdataitemproviderregistry.sip %Include qgsdataprovider.sip %Include qgsdatasourceuri.sip %Include qgsdatumtransformstore.sip diff --git a/python/core/qgsdataitemprovider.sip b/python/core/qgsdataitemprovider.sip new file mode 100644 index 00000000000..e10ce3da494 --- /dev/null +++ b/python/core/qgsdataitemprovider.sip @@ -0,0 +1,20 @@ + +class QgsDataItemProvider +{ +%TypeHeaderCode +#include +%End + public: + virtual ~QgsDataItemProvider(); + + //! Human-readable name of the provider name + virtual QString name() = 0; + + //! Return combination of flags from QgsDataProvider::DataCapabilities + virtual int capabilities() = 0; + + //! Create a new instance of QgsDataItem (or null) for given path and parent item. + //! Caller takes responsibility of deleting created items. + virtual QgsDataItem* createDataItem( const QString& path, QgsDataItem* parentItem ) = 0 /Factory/; + +}; diff --git a/python/core/qgsdataitemproviderregistry.sip b/python/core/qgsdataitemproviderregistry.sip new file mode 100644 index 00000000000..d14a311b9c7 --- /dev/null +++ b/python/core/qgsdataitemproviderregistry.sip @@ -0,0 +1,19 @@ + +class QgsDataItemProviderRegistry +{ +%TypeHeaderCode +#include +%End + public: + //! Returns the instance pointer, creating the object on the first call + static QgsDataItemProviderRegistry * instance(); + + ~QgsDataItemProviderRegistry(); + + //! Get list of available providers + QList providers() const; + + private: + QgsDataItemProviderRegistry(); + +}; diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 55a1fce8bc0..169cc460bec 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -77,6 +77,8 @@ SET(QGIS_CORE_SRCS qgsdatadefined.cpp qgsdatasourceuri.cpp qgsdataitem.cpp + qgsdataitemprovider.cpp + qgsdataitemproviderregistry.cpp qgsdatumtransformstore.cpp qgsdbfilterproxymodel.cpp qgsdiagramrendererv2.cpp @@ -475,6 +477,9 @@ SET(QGIS_CORE_HDRS qgscsexception.h qgsdartmeasurement.h qgsdatadefined.h + qgsdataitem.h + qgsdataitemprovider.h + qgsdataitemproviderregistry.h qgsdatasourceuri.h qgsdatumtransformstore.h qgsdbfilterproxymodel.h diff --git a/src/core/qgsapplication.cpp b/src/core/qgsapplication.cpp index 254fc90df36..4dc5315fc81 100644 --- a/src/core/qgsapplication.cpp +++ b/src/core/qgsapplication.cpp @@ -15,6 +15,7 @@ #include "qgsapplication.h" #include "qgscrscache.h" +#include "qgsdataitemproviderregistry.h" #include "qgsexception.h" #include "qgsgeometry.h" #include "qgslogger.h" @@ -626,6 +627,7 @@ void QgsApplication::exitQgis() QgsMapLayerRegistry::cleanup(); QgsNetworkAccessManager::cleanup(); QgsCoordinateTransformCache::cleanup(); + QgsDataItemProviderRegistry::cleanup(); // Cleanup providers delete QgsProviderRegistry::instance(); diff --git a/src/core/qgsbrowsermodel.cpp b/src/core/qgsbrowsermodel.cpp index c2c98476b37..3fa9ed7f41c 100644 --- a/src/core/qgsbrowsermodel.cpp +++ b/src/core/qgsbrowsermodel.cpp @@ -19,6 +19,8 @@ #include "qgis.h" #include "qgsapplication.h" +#include "qgsdataitemprovider.h" +#include "qgsdataitemproviderregistry.h" #include "qgsdataprovider.h" #include "qgsmimedatautils.h" #include "qgslogger.h" @@ -123,40 +125,19 @@ void QgsBrowserModel::addRootItems() mRootItems << vols; #endif - // Add non file top level items - QStringList providersList = QgsProviderRegistry::instance()->providerList(); - // container for displaying providers as sorted groups (by QgsDataProvider::DataCapability enum) QMap providerMap; - foreach ( QString key, providersList ) + foreach ( QgsDataItemProvider* pr, QgsDataItemProviderRegistry::instance()->providers() ) { - QLibrary *library = QgsProviderRegistry::instance()->providerLibrary( key ); - if ( !library ) - continue; - - dataCapabilities_t * dataCapabilities = ( dataCapabilities_t * ) cast_to_fptr( library->resolve( "dataCapabilities" ) ); - if ( !dataCapabilities ) - { - QgsDebugMsg( library->fileName() + " does not have dataCapabilities" ); - continue; - } - - int capabilities = dataCapabilities(); + int capabilities = pr->capabilities(); if ( capabilities == QgsDataProvider::NoDataCapabilities ) { - QgsDebugMsg( library->fileName() + " does not have any dataCapabilities" ); + QgsDebugMsg( pr->name() + " does not have any dataCapabilities" ); continue; } - dataItem_t *dataItem = ( dataItem_t * ) cast_to_fptr( library->resolve( "dataItem" ) ); - if ( !dataItem ) - { - QgsDebugMsg( library->fileName() + " does not have dataItem" ); - continue; - } - - QgsDataItem *item = dataItem( "", NULL ); // empty path -> top level + QgsDataItem *item = pr->createDataItem( "", NULL ); // empty path -> top level if ( item ) { QgsDebugMsg( "Add new top level item : " + item->name() ); diff --git a/src/core/qgsdataitem.cpp b/src/core/qgsdataitem.cpp index e40ef155f8b..eb2d6261e9c 100644 --- a/src/core/qgsdataitem.cpp +++ b/src/core/qgsdataitem.cpp @@ -32,6 +32,8 @@ #include "qgis.h" #include "qgsdataitem.h" +#include "qgsdataitemprovider.h" +#include "qgsdataitemproviderregistry.h" #include "qgsdataprovider.h" #include "qgslogger.h" #include "qgsproviderregistry.h" @@ -715,39 +717,6 @@ QgsDirectoryItem::QgsDirectoryItem( QgsDataItem* parent, QString name, QString d void QgsDirectoryItem::init() { - if ( mLibraries.size() > 0 ) - return; - - QStringList keys = QgsProviderRegistry::instance()->providerList(); - QStringList::const_iterator i; - for ( i = keys.begin(); i != keys.end(); ++i ) - { - QString k( *i ); - // some providers hangs with empty uri (Postgis) etc... - // -> using libraries directly - QLibrary *library = QgsProviderRegistry::instance()->providerLibrary( k ); - if ( library ) - { - dataCapabilities_t * dataCapabilities = ( dataCapabilities_t * ) cast_to_fptr( library->resolve( "dataCapabilities" ) ); - if ( !dataCapabilities ) - { - QgsDebugMsg( library->fileName() + " does not have dataCapabilities" ); - continue; - } - if ( dataCapabilities() == QgsDataProvider::NoDataCapabilities ) - { - QgsDebugMsg( library->fileName() + " has NoDataCapabilities" ); - continue; - } - - QgsDebugMsg( QString( "%1 dataCapabilities : %2" ).arg( library->fileName() ).arg( dataCapabilities() ) ); - mLibraries.append( library ); - } - else - { - //QgsDebugMsg ( "Cannot get provider " + k ); - } - } } QgsDirectoryItem::~QgsDirectoryItem() @@ -761,6 +730,7 @@ QIcon QgsDirectoryItem::icon() return iconDir(); } + QVector QgsDirectoryItem::createChildren() { QVector children; @@ -808,18 +778,9 @@ QVector QgsDirectoryItem::createChildren() } } - foreach ( QLibrary *library, mLibraries ) + foreach ( QgsDataItemProvider* provider, QgsDataItemProviderRegistry::instance()->providers() ) { - // we could/should create separate list of providers for each purpose - - // TODO: use existing fileVectorFilters(),directoryDrivers() ? - dataCapabilities_t * dataCapabilities = ( dataCapabilities_t * ) cast_to_fptr( library->resolve( "dataCapabilities" ) ); - if ( !dataCapabilities ) - { - continue; - } - - int capabilities = dataCapabilities(); + int capabilities = provider->capabilities(); if ( !(( fileInfo.isFile() && ( capabilities & QgsDataProvider::File ) ) || ( fileInfo.isDir() && ( capabilities & QgsDataProvider::Dir ) ) ) ) @@ -827,19 +788,13 @@ QVector QgsDirectoryItem::createChildren() continue; } - dataItem_t * dataItem = ( dataItem_t * ) cast_to_fptr( library->resolve( "dataItem" ) ); - if ( ! dataItem ) - { - QgsDebugMsg( library->fileName() + " does not have dataItem" ); - continue; - } - - QgsDataItem * item = dataItem( path, this ); + QgsDataItem * item = provider->createDataItem( path, this ); if ( item ) { children.append( item ); } } + } return children; diff --git a/src/core/qgsdataitem.h b/src/core/qgsdataitem.h index 99e6db32dda..c8808ee0f01 100644 --- a/src/core/qgsdataitem.h +++ b/src/core/qgsdataitem.h @@ -362,7 +362,8 @@ class CORE_EXPORT QgsDirectoryItem : public QgsDataCollectionItem /* static QVector mProviders; */ //! @note not available via python bindings - static QVector mLibraries; + //! @note deprecated since 2.10 - use QgsDataItemProviderRegistry + Q_DECL_DEPRECATED static QVector mLibraries; public slots: virtual void childrenCreated() override; diff --git a/src/core/qgsdataitemprovider.cpp b/src/core/qgsdataitemprovider.cpp new file mode 100644 index 00000000000..b294328a206 --- /dev/null +++ b/src/core/qgsdataitemprovider.cpp @@ -0,0 +1,18 @@ +/*************************************************************************** + qgsdataitemprovider.cpp + -------------------------------------- + Date : March 2015 + Copyright : (C) 2015 by Martin Dobias + Email : wonder dot sk at gmail dot com + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "qgsdataitemprovider.h" + +// no implementation currently diff --git a/src/core/qgsdataitemprovider.h b/src/core/qgsdataitemprovider.h new file mode 100644 index 00000000000..baf436b1165 --- /dev/null +++ b/src/core/qgsdataitemprovider.h @@ -0,0 +1,52 @@ +/*************************************************************************** + qgsdataitemprovider.h + -------------------------------------- + Date : March 2015 + Copyright : (C) 2015 by Martin Dobias + Email : wonder dot sk at gmail dot com + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef QGSDATAITEMPROVIDER_H +#define QGSDATAITEMPROVIDER_H + +class QgsDataItem; + +class QString; + +/** + * This is the interface for those who want to add custom data items to the browser tree. + * + * The method createDataItem() is ever called only if capabilities() return non-zero value. + * There are two occasions when createDataItem() is called: + * 1. to create root items (passed path is empty, parent item is null). + * 2. to create items in directory structure. For this capabilities have to return at least + * of the following: QgsDataProider::Dir or QgsDataProvider::File. Passed path is the file + * or directory being inspected, parent item is a valid QgsDirectoryItem + * + * @note added in 2.10 + */ +class CORE_EXPORT QgsDataItemProvider +{ + public: + virtual ~QgsDataItemProvider() {} + + //! Human-readable name of the provider name + virtual QString name() = 0; + + //! Return combination of flags from QgsDataProvider::DataCapabilities + virtual int capabilities() = 0; + + //! Create a new instance of QgsDataItem (or null) for given path and parent item. + //! Caller takes responsibility of deleting created items. + virtual QgsDataItem* createDataItem( const QString& path, QgsDataItem* parentItem ) = 0; + +}; + +#endif // QGSDATAITEMPROVIDER_H diff --git a/src/core/qgsdataitemproviderregistry.cpp b/src/core/qgsdataitemproviderregistry.cpp new file mode 100644 index 00000000000..35c07f3c936 --- /dev/null +++ b/src/core/qgsdataitemproviderregistry.cpp @@ -0,0 +1,86 @@ +/*************************************************************************** + qgsdataitemproviderregistry.cpp + -------------------------------------- + Date : March 2015 + Copyright : (C) 2015 by Martin Dobias + Email : wonder dot sk at gmail dot com + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "qgsdataitemproviderregistry.h" + +#include "qgsdataitem.h" +#include "qgsdataitemprovider.h" +#include "qgsdataprovider.h" +#include "qgslogger.h" +#include "qgsproviderregistry.h" + + +/** Simple data item provider implementation that handles the support for provider plugins (which may contain + * dataCapabilities() and dataItem() functions). + * + * Ideally the provider plugins should directly provide implementation of QgsDataItemProvider, for the time being + * this is a wrapper for the legacy interface. + */ +class QgsDataItemProviderFromPlugin : public QgsDataItemProvider +{ + public: + QgsDataItemProviderFromPlugin( const QString& name, dataCapabilities_t* capabilitiesFunc, dataItem_t* dataItemFunc ) + : mName( name ) + , mCapabilitiesFunc( capabilitiesFunc ) + , mDataItemFunc( dataItemFunc ) + { + } + + virtual QString name() { return mName; } + + virtual int capabilities() { return mCapabilitiesFunc(); } + + virtual QgsDataItem* createDataItem( const QString& path, QgsDataItem* parentItem ) { return mDataItemFunc( path, parentItem ); } + + protected: + QString mName; + dataCapabilities_t* mCapabilitiesFunc; + dataItem_t* mDataItemFunc; +}; + + +QgsDataItemProviderRegistry::QgsDataItemProviderRegistry() +{ + QStringList providersList = QgsProviderRegistry::instance()->providerList(); + + foreach ( QString key, providersList ) + { + QLibrary *library = QgsProviderRegistry::instance()->providerLibrary( key ); + if ( !library ) + continue; + + dataCapabilities_t * dataCapabilities = ( dataCapabilities_t * ) cast_to_fptr( library->resolve( "dataCapabilities" ) ); + if ( !dataCapabilities ) + { + QgsDebugMsg( library->fileName() + " does not have dataCapabilities" ); + continue; + } + + dataItem_t *dataItem = ( dataItem_t * ) cast_to_fptr( library->resolve( "dataItem" ) ); + if ( !dataItem ) + { + QgsDebugMsg( library->fileName() + " does not have dataItem" ); + continue; + } + + mProviders.append( new QgsDataItemProviderFromPlugin( library->fileName(), dataCapabilities, dataItem ) ); + } +} + +QgsDataItemProviderRegistry::~QgsDataItemProviderRegistry() +{ + qDeleteAll( mProviders ); +} + diff --git a/src/core/qgsdataitemproviderregistry.h b/src/core/qgsdataitemproviderregistry.h new file mode 100644 index 00000000000..edcd6546c71 --- /dev/null +++ b/src/core/qgsdataitemproviderregistry.h @@ -0,0 +1,48 @@ +/*************************************************************************** + qgsdataitemproviderregistry.h + -------------------------------------- + Date : March 2015 + Copyright : (C) 2015 by Martin Dobias + Email : wonder dot sk at gmail dot com + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef QGSDATAITEMPROVIDERREGISTRY_H +#define QGSDATAITEMPROVIDERREGISTRY_H + +#include "qgssingleton.h" + +#include + +class QgsDataItemProvider; + +/** + * This singleton class keeps a list of data item providers that may add items to the browser tree. + * When created, it automatically adds providers from provider plugins (e.g. PostGIS, WMS, ...) + * + * @note added in 2.10 + */ +class CORE_EXPORT QgsDataItemProviderRegistry : public QgsSingleton +{ + public: + ~QgsDataItemProviderRegistry(); + + //! Get list of available providers + QList providers() const { return mProviders; } + + private: + QgsDataItemProviderRegistry(); + + friend class QgsSingleton; // Let QgsSingleton access private constructor + + //! available providers. this class owns the pointers + QList mProviders; +}; + +#endif // QGSDATAITEMPROVIDERREGISTRY_H