Move memory provider to core

This commit introduces basic support for non-library based
data providers, and moves the memory provider from a library
based provider to a core provider.

The memory provider is used so frequently throughout QGIS that
it has become integral to QGIS functionality and must be
available wherever the QGIS core library is used.

The changes here (while not exposed yet to Python) could potentially
be built on to allow creation of pure Python data providers.
This commit is contained in:
Nyall Dawson 2017-05-03 11:56:40 +10:00
parent 5e3c6e54be
commit 5511b07e40
15 changed files with 225 additions and 93 deletions

View File

@ -66,6 +66,8 @@ IF(WITH_APIDOC)
${CMAKE_SOURCE_DIR}/src/core/metadata
${CMAKE_SOURCE_DIR}/src/core/pal
${CMAKE_SOURCE_DIR}/src/core/processing
${CMAKE_SOURCE_DIR}/src/core/providers
${CMAKE_SOURCE_DIR}/src/core/providers/memory
${CMAKE_SOURCE_DIR}/src/core/raster
${CMAKE_SOURCE_DIR}/src/core/scalebar
${CMAKE_SOURCE_DIR}/src/core/symbology-ng

View File

@ -0,0 +1,34 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/providers/memory/qgsmemoryproviderutils.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
class QgsMemoryProviderUtils
{
%Docstring
Utility functions for use with the memory vector data provider.
.. versionadded:: 3.0
%End
%TypeHeaderCode
#include "qgsmemoryproviderutils.h"
%End
public:
};
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/providers/memory/qgsmemoryproviderutils.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/

View File

@ -92,6 +92,9 @@ SET(QGIS_CORE_SRCS
processing/qgsprocessingregistry.cpp
processing/qgsprocessingutils.cpp
providers/memory/qgsmemoryfeatureiterator.cpp
providers/memory/qgsmemoryprovider.cpp
scalebar/qgsdoubleboxscalebarrenderer.cpp
scalebar/qgsnumericscalebarrenderer.cpp
scalebar/qgsscalebarrenderer.cpp
@ -618,6 +621,8 @@ SET(QGIS_CORE_MOC_HDRS
processing/qgsprocessingprovider.h
processing/qgsprocessingregistry.h
providers/memory/qgsmemoryprovider.h
raster/qgsrasterfilewritertask.h
raster/qgsrasterlayer.h
raster/qgsrasterdataprovider.h
@ -866,6 +871,8 @@ SET(QGIS_CORE_HDRS
processing/qgsprocessingcontext.h
processing/qgsprocessingutils.h
providers/memory/qgsmemoryfeatureiterator.h
raster/qgsbilinearrasterresampler.h
raster/qgsbrightnesscontrastfilter.h
raster/qgscliptominmaxenhancement.h
@ -1001,6 +1008,8 @@ INCLUDE_DIRECTORIES(
metadata
pal
processing
providers
providers/memory
raster
renderer
scalebar

View File

@ -21,7 +21,7 @@
#include "qgsmessagelog.h"
#include "qgsproject.h"
///@cond PRIVATE
QgsMemoryFeatureIterator::QgsMemoryFeatureIterator( QgsMemoryFeatureSource *source, bool ownSource, const QgsFeatureRequest &request )
: QgsAbstractFeatureIteratorFromSource<QgsMemoryFeatureSource>( source, ownSource, request )
@ -223,3 +223,5 @@ QgsFeatureIterator QgsMemoryFeatureSource::getFeatures( const QgsFeatureRequest
{
return QgsFeatureIterator( new QgsMemoryFeatureIterator( this, false, request ) );
}
///@endcond PRIVATE

View File

@ -20,6 +20,8 @@
#include "qgsfields.h"
#include "qgsgeometry.h"
///@cond PRIVATE
class QgsMemoryProvider;
typedef QMap<QgsFeatureId, QgsFeature> QgsFeatureMap;
@ -72,4 +74,6 @@ class QgsMemoryFeatureIterator : public QgsAbstractFeatureIteratorFromSource<Qgs
};
///@endcond PRIVATE
#endif // QGSMEMORYFEATUREITERATOR_H

View File

@ -26,6 +26,7 @@
#include <QUrl>
#include <QRegExp>
///@cond PRIVATE
static const QString TEXT_PROVIDER_KEY = QStringLiteral( "memory" );
static const QString TEXT_PROVIDER_DESCRIPTION = QStringLiteral( "Memory provider" );
@ -190,6 +191,21 @@ QgsMemoryProvider::~QgsMemoryProvider()
delete mSpatialIndex;
}
QString QgsMemoryProvider::providerKey()
{
return TEXT_PROVIDER_KEY;
}
QString QgsMemoryProvider::providerDescription()
{
return TEXT_PROVIDER_DESCRIPTION;
}
QgsMemoryProvider *QgsMemoryProvider::createProvider( const QString &uri )
{
return new QgsMemoryProvider( uri );
}
QgsAbstractFeatureSource *QgsMemoryProvider::featureSource() const
{
return new QgsMemoryFeatureSource( this );
@ -523,52 +539,15 @@ void QgsMemoryProvider::updateExtent()
}
}
// --------------------------------
QString QgsMemoryProvider::name() const
QString QgsMemoryProvider::name() const
{
return TEXT_PROVIDER_KEY;
}
QString QgsMemoryProvider::description() const
QString QgsMemoryProvider::description() const
{
return TEXT_PROVIDER_DESCRIPTION;
}
// --------------------------------
/**
* Class factory to return a pointer to a newly created
* QgsMemoryProvider object
*/
QGISEXTERN QgsMemoryProvider *classFactory( const QString *uri )
{
return new QgsMemoryProvider( *uri );
}
/** Required key function (used to map the plugin to a data store type)
*/
QGISEXTERN QString providerKey()
{
return TEXT_PROVIDER_KEY;
}
/**
* Required description function
*/
QGISEXTERN QString description()
{
return TEXT_PROVIDER_DESCRIPTION;
}
/**
* Required isProvider function. Used to determine if this shared library
* is a data provider plugin
*/
QGISEXTERN bool isProvider()
{
return true;
}
///@endcond

View File

@ -17,6 +17,7 @@
#include "qgscoordinatereferencesystem.h"
#include "qgsfields.h"
///@cond PRIVATE
typedef QMap<QgsFeatureId, QgsFeature> QgsFeatureMap;
class QgsSpatialIndex;
@ -32,6 +33,13 @@ class QgsMemoryProvider : public QgsVectorDataProvider
virtual ~QgsMemoryProvider();
//! Returns the memory provider key
static QString providerKey();
//! Returns the memory provider description
static QString providerDescription();
static QgsMemoryProvider *createProvider( const QString &uri );
/* Implementation of functions from QgsVectorDataProvider */
virtual QgsAbstractFeatureSource *featureSource() const override;
@ -88,3 +96,5 @@ class QgsMemoryProvider : public QgsVectorDataProvider
friend class QgsMemoryFeatureSource;
};
///@endcond

View File

@ -0,0 +1,18 @@
/***************************************************************************
qgsmemoryproviderutils.cpp
--------------------------
begin : May 2017
copyright : (C) 2017 by Nyall Dawson
email : nyall dot dawson 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 "qgsmemoryproviderutils.h"

View File

@ -0,0 +1,38 @@
/***************************************************************************
qgsmemoryproviderutils.h
------------------------
begin : May 2017
copyright : (C) 2017 by Nyall Dawson
email : nyall dot dawson 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 QGSMEMORYPROVIDERUTILS_H
#define QGSMEMORYPROVIDERUTILS_H
#include "qgis_core.h"
/**
* \class QgsMemoryProviderUtils
* \ingroup core
* Utility functions for use with the memory vector data provider.
* \since QGIS 3.0
*/
class CORE_EXPORT QgsMemoryProviderUtils
{
public:
};
#endif // QGSMEMORYPROVIDERUTILS_H

View File

@ -28,6 +28,12 @@ QgsProviderMetadata::QgsProviderMetadata( QString const &_key,
, library_( _library )
{}
QgsProviderMetadata::QgsProviderMetadata( const QString &key, const QString &description, QgsProviderMetadata::CreateDataProviderFunction createFunc )
: key_( key )
, description_( description )
, mCreateFunc( createFunc )
{}
QString QgsProviderMetadata::key() const
{
return key_;
@ -42,3 +48,8 @@ QString QgsProviderMetadata::library() const
{
return library_;
}
QgsProviderMetadata::CreateDataProviderFunction QgsProviderMetadata::createFunction() const
{
return mCreateFunc;
}

View File

@ -21,27 +21,48 @@
#include <QString>
#include "qgis.h"
#include "qgis_core.h"
#include <functional>
class QgsDataProvider;
/** \ingroup core
* Holds data provider key, description, and associated shared library file information.
The metadata class is used in a lazy load implementation in
QgsProviderRegistry. To save memory, data providers are only actually
loaded via QLibrary calls if they're to be used. (Though they're all
iteratively loaded once to get their metadata information, and then
unloaded when the QgsProviderRegistry is created.) QgsProviderMetadata
supplies enough information to be able to later load the associated shared
library object.
* Holds data provider key, description, and associated shared library file or function pointer information.
*
* Provider metadata refers either to providers which are loaded via libraries or
* which are native providers that are included in the core QGIS installation
* and accessed through function pointers.
*
* For library based providers, the metadata class is used in a lazy load
* implementation in QgsProviderRegistry. To save memory, data providers
* are only actually loaded via QLibrary calls if they're to be used. (Though they're all
* iteratively loaded once to get their metadata information, and then
* unloaded when the QgsProviderRegistry is created.) QgsProviderMetadata
* supplies enough information to be able to later load the associated shared
* library object.
*
*/
class CORE_EXPORT QgsProviderMetadata
{
public:
/**
* Typedef for data provider creation function.
* \since QGIS 3.0
*/
SIP_SKIP typedef std::function < QgsDataProvider*( const QString & ) > CreateDataProviderFunction;
QgsProviderMetadata( const QString &_key, const QString &_description, const QString &_library );
/**
* Metadata for provider with direct provider creation function pointer, where
* no library is involved.
* \since QGIS 3.0
* \note not available in Python bindings
*/
SIP_SKIP QgsProviderMetadata( const QString &key, const QString &description, QgsProviderMetadata::CreateDataProviderFunction createFunc );
/** This returns the unique key associated with the provider
This key string is used for the associative container in QgsProviderRegistry
@ -60,6 +81,14 @@ class CORE_EXPORT QgsProviderMetadata
*/
QString library() const;
/**
* Returns a pointer to the direct provider creation function, if supported
* by the provider.
* \since QGIS 3.0
* \note not available in Python bindings
*/
SIP_SKIP CreateDataProviderFunction createFunction() const;
private:
/// unique key for data provider
@ -71,7 +100,9 @@ class CORE_EXPORT QgsProviderMetadata
/// file path
QString library_;
}; // class QgsProviderMetadata
CreateDataProviderFunction mCreateFunc = nullptr;
};
#endif //QGSPROVIDERMETADATA_H

View File

@ -30,6 +30,7 @@
#include "qgsprovidermetadata.h"
#include "qgsvectorlayer.h"
#include "qgsproject.h"
#include "providers/memory/qgsmemoryprovider.h"
// typedefs for provider plugin functions of interest
@ -75,6 +76,9 @@ QgsProviderRegistry::QgsProviderRegistry( const QString &pluginPath )
void QgsProviderRegistry::init()
{
// add standard providers
mProviders[ QgsMemoryProvider::providerKey() ] = new QgsProviderMetadata( QgsMemoryProvider::providerKey(), QgsMemoryProvider::providerDescription(), &QgsMemoryProvider::createProvider );
mLibraryDirectory.setSorting( QDir::Name | QDir::IgnoreCase );
mLibraryDirectory.setFilter( QDir::Files | QDir::NoSymLinks );
@ -233,16 +237,20 @@ void QgsProviderRegistry::clean()
{
QgsDebugMsg( QString( "cleanup:%1" ).arg( it->first ) );
QString lib = it->second->library();
QLibrary myLib( lib );
if ( myLib.isLoaded() )
if ( !lib.isEmpty() )
{
cleanupProviderFunction_t *cleanupFunc = reinterpret_cast< cleanupProviderFunction_t * >( cast_to_fptr( myLib.resolve( "cleanupProvider" ) ) );
if ( cleanupFunc )
cleanupFunc();
QLibrary myLib( lib );
if ( myLib.isLoaded() )
{
cleanupProviderFunction_t *cleanupFunc = reinterpret_cast< cleanupProviderFunction_t * >( cast_to_fptr( myLib.resolve( "cleanupProvider" ) ) );
if ( cleanupFunc )
cleanupFunc();
}
}
delete it->second;
++it;
}
mProviders.clear();
}
QgsProviderRegistry::~QgsProviderRegistry()
@ -351,6 +359,18 @@ QgsDataProvider *QgsProviderRegistry::provider( QString const &providerKey, QStr
// XXX should I check for and possibly delete any pre-existing providers?
// XXX How often will that scenario occur?
const QgsProviderMetadata *metadata = providerMetadata( providerKey );
if ( !metadata )
{
QgsMessageLog::logMessage( QObject::tr( "Invalid data provider %1" ).arg( providerKey ) );
return nullptr;
}
if ( metadata->createFunction() )
{
return metadata->createFunction()( dataSource );
}
// load the plugin
QString lib = library( providerKey );
@ -435,6 +455,10 @@ QWidget *QgsProviderRegistry::selectWidget( const QString &providerKey,
QFunctionPointer QgsProviderRegistry::function( QString const &providerKey,
QString const &functionName )
{
QString lib = library( providerKey );
if ( lib.isEmpty() )
return nullptr;
QLibrary myLib( library( providerKey ) );
QgsDebugMsg( "Library name is " + myLib.fileName() );
@ -452,7 +476,11 @@ QFunctionPointer QgsProviderRegistry::function( QString const &providerKey,
QLibrary *QgsProviderRegistry::providerLibrary( QString const &providerKey ) const
{
std::unique_ptr< QLibrary > myLib( new QLibrary( library( providerKey ) ) );
QString lib = library( providerKey );
if ( lib.isEmpty() )
return nullptr;
std::unique_ptr< QLibrary > myLib( new QLibrary( lib ) );
QgsDebugMsg( "Library name is " + myLib->fileName() );

View File

@ -52,7 +52,6 @@ class CORE_EXPORT QgsProviderRegistry
//! Means of accessing canonical single instance
static QgsProviderRegistry *instance( const QString &pluginPath = QString::null );
//! Virtual dectructor
virtual ~QgsProviderRegistry();
//! Return path for the library of the provider

View File

@ -3,7 +3,6 @@ SET (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${QGIS_OUTPUT_DIRECTORY}/${QGIS_PLUGIN_SUBDI
SET (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${QGIS_OUTPUT_DIRECTORY}/${QGIS_PLUGIN_SUBDIR})
ADD_SUBDIRECTORY(arcgisrest)
ADD_SUBDIRECTORY(memory)
ADD_SUBDIRECTORY(ogr)
ADD_SUBDIRECTORY(wms)
ADD_SUBDIRECTORY(delimitedtext)

View File

@ -1,32 +0,0 @@
SET (MEMORY_SRCS qgsmemoryprovider.cpp qgsmemoryfeatureiterator.cpp)
INCLUDE_DIRECTORIES(
.
../../core
../../core/geometry
${CMAKE_BINARY_DIR}/src/core
)
INCLUDE_DIRECTORIES(SYSTEM
${GEOS_INCLUDE_DIR}
)
QT5_WRAP_CPP(MEMORY_MOC_SRCS qgsmemoryprovider.h)
ADD_LIBRARY(memoryprovider MODULE ${MEMORY_SRCS} ${MEMORY_MOC_SRCS})
TARGET_LINK_LIBRARIES(memoryprovider
qgis_core
)
# clang-tidy
IF(CLANG_TIDY_EXE)
SET_TARGET_PROPERTIES(
memoryprovider PROPERTIES
CXX_CLANG_TIDY "${DO_CLANG_TIDY}"
)
ENDIF(CLANG_TIDY_EXE)
INSTALL (TARGETS memoryprovider
RUNTIME DESTINATION ${QGIS_PLUGIN_DIR}
LIBRARY DESTINATION ${QGIS_PLUGIN_DIR})