Add generic method to QgsMapLayerFactory to create map layers of

any type
This commit is contained in:
Nyall Dawson 2021-06-22 12:09:08 +10:00
parent 07f5812383
commit 00db2820cd
4 changed files with 126 additions and 1 deletions

View File

@ -41,6 +41,16 @@ Returns the map layer type corresponding a ``string`` value.
Converts a map layer ``type`` to a string value.
.. seealso:: :py:func:`typeFromString`
%End
static QgsMapLayer *createLayer( const QString &uri, const QString &name, QgsMapLayerType type,
const QString &provider = QString(), const QgsCoordinateTransformContext &transformContext = QgsCoordinateTransformContext() ) /Factory/;
%Docstring
Creates a map layer, given a ``uri``, ``name``, layer ``type`` and ``provider`` name.
Caller takes ownership of the returned layer.
.. versionadded:: 3.22
%End
};

View File

@ -16,6 +16,12 @@
***************************************************************************/
#include "qgsmaplayerfactory.h"
#include "qgsvectorlayer.h"
#include "qgsrasterlayer.h"
#include "qgsmeshlayer.h"
#include "qgspointcloudlayer.h"
#include "qgsvectortilelayer.h"
#include "qgsannotationlayer.h"
QgsMapLayerType QgsMapLayerFactory::typeFromString( const QString &string, bool &ok )
{
@ -60,3 +66,47 @@ QString QgsMapLayerFactory::typeToString( QgsMapLayerType type )
}
return QString();
}
QgsMapLayer *QgsMapLayerFactory::createLayer( const QString &uri, const QString &name, QgsMapLayerType type, const QString &provider, const QgsCoordinateTransformContext &transformContext )
{
switch ( type )
{
case QgsMapLayerType::VectorLayer:
{
QgsVectorLayer::LayerOptions options;
options.transformContext = transformContext;
return new QgsVectorLayer( uri, name, provider, options );
}
case QgsMapLayerType::RasterLayer:
{
QgsRasterLayer::LayerOptions options;
options.transformContext = transformContext;
return new QgsRasterLayer( uri, name, provider, options );
}
case QgsMapLayerType::MeshLayer:
{
QgsMeshLayer::LayerOptions options;
options.transformContext = transformContext;
return new QgsMeshLayer( uri, name, provider, options );
}
case QgsMapLayerType::VectorTileLayer:
return new QgsVectorTileLayer( uri, name );
case QgsMapLayerType::AnnotationLayer:
return new QgsAnnotationLayer( name, QgsAnnotationLayer::LayerOptions( transformContext ) );
case QgsMapLayerType::PointCloudLayer:
{
QgsPointCloudLayer::LayerOptions options;
options.transformContext = transformContext;
return new QgsPointCloudLayer( uri, name, provider, options );
}
case QgsMapLayerType::PluginLayer:
break;
}
return nullptr;
}

View File

@ -20,6 +20,7 @@
#include "qgis_core.h"
#include "qgis.h"
#include "qgscoordinatetransformcontext.h"
#include <QString>
@ -52,6 +53,16 @@ class CORE_EXPORT QgsMapLayerFactory
*/
static QString typeToString( QgsMapLayerType type );
/**
* Creates a map layer, given a \a uri, \a name, layer \a type and \a provider name.
*
* Caller takes ownership of the returned layer.
*
* \since QGIS 3.22
*/
static QgsMapLayer *createLayer( const QString &uri, const QString &name, QgsMapLayerType type,
const QString &provider = QString(), const QgsCoordinateTransformContext &transformContext = QgsCoordinateTransformContext() ) SIP_FACTORY;
};
#endif // QGSMAPLAYERFACTORY_H

View File

@ -12,8 +12,21 @@ __copyright__ = 'Copyright 2021, The QGIS Project'
import qgis # NOQA
from qgis.core import QgsMapLayerFactory, QgsMapLayerType
import os
from qgis.core import (
QgsMapLayerFactory,
QgsMapLayerType,
QgsVectorLayer,
QgsRasterLayer,
QgsMeshLayer,
QgsPointCloudLayer,
QgsAnnotationLayer,
QgsVectorTileLayer,
QgsDataSourceUri
)
from qgis.testing import start_app, unittest
from utilities import unitTestDataPath
start_app()
@ -62,6 +75,47 @@ class TestQgsMapLayerFactory(unittest.TestCase):
QgsMapLayerFactory.typeFromString(QgsMapLayerFactory.typeToString(QgsMapLayerType.AnnotationLayer))[0],
QgsMapLayerType.AnnotationLayer)
def testCreateLayer(self):
# create vector
ml = QgsMapLayerFactory.createLayer(os.path.join(unitTestDataPath(), 'lines.shp'), 'lines', QgsMapLayerType.VectorLayer, 'ogr')
self.assertTrue(ml.isValid())
self.assertIsInstance(ml, QgsVectorLayer)
self.assertEqual(ml.name(), 'lines')
# create raster
ml = QgsMapLayerFactory.createLayer(os.path.join(unitTestDataPath(), 'landsat.tif'), 'rl', QgsMapLayerType.RasterLayer, 'gdal')
self.assertTrue(ml.isValid())
self.assertIsInstance(ml, QgsRasterLayer)
self.assertEqual(ml.name(), 'rl')
# create mesh
ml = QgsMapLayerFactory.createLayer(os.path.join(unitTestDataPath(), 'mesh', 'lines.2dm'), 'ml', QgsMapLayerType.MeshLayer, 'mdal')
self.assertTrue(ml.isValid())
self.assertIsInstance(ml, QgsMeshLayer)
self.assertEqual(ml.name(), 'ml')
# create point cloud
ml = QgsMapLayerFactory.createLayer(os.path.join(unitTestDataPath(), 'point_clouds', 'ept', 'rgb', 'ept.json'), 'pcl', QgsMapLayerType.PointCloudLayer, 'ept')
self.assertTrue(ml.isValid())
self.assertIsInstance(ml, QgsPointCloudLayer)
self.assertEqual(ml.name(), 'pcl')
# annotation layer
ml = QgsMapLayerFactory.createLayer('', 'al', QgsMapLayerType.AnnotationLayer)
self.assertTrue(ml.isValid())
self.assertIsInstance(ml, QgsAnnotationLayer)
self.assertEqual(ml.name(), 'al')
# vector tile layer
ds = QgsDataSourceUri()
ds.setParam("type", "xyz")
ds.setParam("url", "file://{}/{{z}}-{{x}}-{{y}}.pbf".format(os.path.join(unitTestDataPath(), 'vector_tile')))
ds.setParam("zmax", "1")
ml = QgsMapLayerFactory.createLayer(ds.encodedUri().data().decode(), 'vtl', QgsMapLayerType.VectorTileLayer)
self.assertTrue(ml.isValid())
self.assertIsInstance(ml, QgsVectorTileLayer)
self.assertEqual(ml.name(), 'vtl')
if __name__ == '__main__':
unittest.main()