Setup core infrastructure for tiled scene 2d renderers

This commit is contained in:
Nyall Dawson 2023-08-06 17:30:02 +10:00
parent fb3c25e1a5
commit c8658efde4
16 changed files with 1381 additions and 2 deletions

View File

@ -745,6 +745,13 @@ Returns the application's renderer registry, used for managing vector layer rend
Returns the application's point cloud renderer registry, used for managing point cloud layer 2D renderers.
.. versionadded:: 3.18
%End
static QgsTiledSceneRendererRegistry *tiledSceneRendererRegistry() /KeepReference/;
%Docstring
Returns the application's tiled scene renderer registry, used for managing tiled scene layer 2D renderers.
.. versionadded:: 3.34
%End
static QgsDataItemProviderRegistry *dataItemProviderRegistry() /KeepReference/;

View File

@ -9,6 +9,7 @@
class QgsTiledSceneLayer : QgsMapLayer
{
%Docstring(signature="appended")
@ -89,6 +90,23 @@ QgsTiledSceneLayer cannot be copied.
virtual QgsMapLayerRenderer *createMapRenderer( QgsRenderContext &rendererContext ) /Factory/;
QgsTiledSceneRenderer *renderer();
%Docstring
Returns the 2D renderer for the tiled scene.
.. seealso:: :py:func:`setRenderer`
%End
void setRenderer( QgsTiledSceneRenderer *renderer /Transfer/ );
%Docstring
Sets the 2D ``renderer`` for the tiled scene.
Ownership of ``renderer`` is transferred to the layer.
.. seealso:: :py:func:`renderer`
%End
private:
QgsTiledSceneLayer( const QgsTiledSceneLayer &rhs );
};

View File

@ -0,0 +1,222 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/tiledscene/qgstiledscenerenderer.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
class QgsTiledSceneRenderContext
{
%Docstring(signature="appended")
Encapsulates the render context for a 2D tiled scene rendering operation.
.. versionadded:: 3.34
%End
%TypeHeaderCode
#include "qgstiledscenerenderer.h"
%End
public:
QgsTiledSceneRenderContext( QgsRenderContext &context, QgsFeedback *feedback = 0 );
%Docstring
Constructor for QgsTiledSceneRenderContext.
%End
QgsRenderContext &renderContext();
%Docstring
Returns a reference to the context's render context.
%End
QgsFeedback *feedback() const;
%Docstring
Returns the feedback object used to cancel rendering
.. versionadded:: 3.20
%End
private:
QgsTiledSceneRenderContext( const QgsTiledSceneRenderContext &rh );
};
class QgsTiledSceneRenderer
{
%Docstring(signature="appended")
Abstract base class for 2d tiled scene renderers.
.. versionadded:: 3.34
%End
%TypeHeaderCode
#include "qgstiledscenerenderer.h"
%End
%ConvertToSubClassCode
const QString type = sipCpp->type();
sipType = 0;
%End
public:
QgsTiledSceneRenderer();
%Docstring
Constructor for QgsTiledSceneRenderer.
%End
virtual ~QgsTiledSceneRenderer();
virtual QString type() const = 0;
%Docstring
Returns the identifier of the renderer type.
%End
virtual QgsTiledSceneRenderer *clone() const = 0 /Factory/;
%Docstring
Create a deep copy of this renderer. Should be implemented by all subclasses
and generate a proper subclass.
%End
static QgsTiledSceneRenderer *load( QDomElement &element, const QgsReadWriteContext &context ) /Factory/;
%Docstring
Creates a renderer from an XML ``element``.
Caller takes ownership of the returned renderer.
.. seealso:: :py:func:`save`
%End
virtual QDomElement save( QDomDocument &doc, const QgsReadWriteContext &context ) const = 0;
%Docstring
Saves the renderer configuration to an XML element.
.. seealso:: :py:func:`load`
%End
double maximumScreenError() const;
%Docstring
Returns the maximum screen error allowed when rendering the tiled scene.
Larger values result in a faster render with less detailed features rendered.
Units are retrieved via :py:func:`~QgsTiledSceneRenderer.maximumScreenErrorUnit`.
.. seealso:: :py:func:`setMaximumScreenError`
.. seealso:: :py:func:`maximumScreenErrorUnit`
%End
void setMaximumScreenError( double error );
%Docstring
Sets the maximum screen ``error`` allowed when rendering the tiled scene.
Larger values result in a faster render with less detailed features rendered.
Units are set via :py:func:`~QgsTiledSceneRenderer.setMaximumScreenErrorUnit`.
.. seealso:: :py:func:`maximumScreenError`
.. seealso:: :py:func:`setMaximumScreenErrorUnit`
%End
Qgis::RenderUnit maximumScreenErrorUnit() const;
%Docstring
Returns the unit for the maximum screen error allowed when rendering the tiled scene.
.. seealso:: :py:func:`maximumScreenError`
.. seealso:: :py:func:`setMaximumScreenErrorUnit`
%End
void setMaximumScreenErrorUnit( Qgis::RenderUnit unit );
%Docstring
Sets the ``unit`` for the maximum screen error allowed when rendering the tiled scene.
.. seealso:: :py:func:`setMaximumScreenError`
.. seealso:: :py:func:`maximumScreenErrorUnit`
%End
virtual void startRender( QgsTiledSceneRenderContext &context );
%Docstring
Must be called when a new render cycle is started. A call to :py:func:`~QgsTiledSceneRenderer.startRender` must always
be followed by a corresponding call to :py:func:`~QgsTiledSceneRenderer.stopRender` after all features have been rendered.
.. seealso:: :py:func:`stopRender`
.. warning::
This method is not thread safe. Before calling :py:func:`~QgsTiledSceneRenderer.startRender` in a non-main thread,
the renderer should instead be cloned and :py:func:`~QgsTiledSceneRenderer.startRender`/:py:func:`~QgsTiledSceneRenderer.stopRender` called on the clone.
%End
virtual void stopRender( QgsTiledSceneRenderContext &context );
%Docstring
Must be called when a render cycle has finished, to allow the renderer to clean up.
Calls to :py:func:`~QgsTiledSceneRenderer.stopRender` must always be preceded by a call to :py:func:`~QgsTiledSceneRenderer.startRender`.
.. warning::
This method is not thread safe. Before calling :py:func:`~QgsTiledSceneRenderer.startRender` in a non-main thread,
the renderer should instead be cloned and :py:func:`~QgsTiledSceneRenderer.startRender`/:py:func:`~QgsTiledSceneRenderer.stopRender` called on the clone.
.. seealso:: :py:func:`startRender`
%End
virtual QList<QgsLayerTreeModelLegendNode *> createLegendNodes( QgsLayerTreeLayer *nodeLayer ) /Factory/;
%Docstring
Creates a set of legend nodes representing the renderer.
%End
virtual QStringList legendRuleKeys() const;
%Docstring
Returns a list of all rule keys for legend nodes created by the renderer.
%End
protected:
void copyCommonProperties( QgsTiledSceneRenderer *destination ) const;
%Docstring
Copies common tiled scene renderer properties (such as screen error) to the ``destination`` renderer.
%End
void restoreCommonProperties( const QDomElement &element, const QgsReadWriteContext &context );
%Docstring
Restores common renderer properties (such as screen error) from the
specified DOM ``element``.
.. seealso:: :py:func:`saveCommonProperties`
%End
void saveCommonProperties( QDomElement &element, const QgsReadWriteContext &context ) const;
%Docstring
Saves common renderer properties (such as point size and screen error) to the
specified DOM ``element``.
.. seealso:: :py:func:`restoreCommonProperties`
%End
private:
QgsTiledSceneRenderer( const QgsTiledSceneRenderer &other );
};
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/tiledscene/qgstiledscenerenderer.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/

View File

@ -0,0 +1,173 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/tiledscene/qgstiledscenerendererregistry.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
class QgsTiledSceneRendererAbstractMetadata
{
%Docstring(signature="appended")
Stores metadata about one tiled scene renderer class.
.. note::
It's necessary to implement :py:func:`~createRenderer` function.
In C++ you can use :py:class:`QgsTiledSceneRendererMetadata` convenience class.
.. versionadded:: 3.34
%End
%TypeHeaderCode
#include "qgstiledscenerendererregistry.h"
%End
public:
QgsTiledSceneRendererAbstractMetadata( const QString &name, const QString &visibleName, const QIcon &icon = QIcon() );
%Docstring
Constructor for QgsTiledSceneRendererAbstractMetadata, with the specified ``name``.
The ``visibleName`` argument gives a translated, user friendly string identifying the renderer type.
The ``icon`` argument can be used to specify an icon representing the renderer.
%End
virtual ~QgsTiledSceneRendererAbstractMetadata();
QString name() const;
%Docstring
Returns the unique name of the renderer. This value is not translated.
.. seealso:: :py:func:`visibleName`
%End
QString visibleName() const;
%Docstring
Returns a friendly display name of the renderer. This value is translated.
.. seealso:: :py:func:`name`
%End
QIcon icon() const;
%Docstring
Returns an icon representing the renderer.
.. seealso:: :py:func:`setIcon`
%End
void setIcon( const QIcon &icon );
%Docstring
Sets an ``icon`` representing the renderer.
.. seealso:: :py:func:`icon`
%End
virtual QgsTiledSceneRenderer *createRenderer( QDomElement &elem, const QgsReadWriteContext &context ) = 0 /Factory/;
%Docstring
Returns new instance of the renderer given the DOM element. Returns ``None`` on error.
Pure virtual function: must be implemented in derived classes.
%End
protected:
};
class QgsTiledSceneRendererMetadata : QgsTiledSceneRendererAbstractMetadata
{
%Docstring(signature="appended")
Convenience metadata class that uses static functions to create tiled scene renderer and its widget.
.. versionadded:: 3.34
%End
%TypeHeaderCode
#include "qgstiledscenerendererregistry.h"
%End
public:
virtual QgsTiledSceneRenderer *createRenderer( QDomElement &elem, const QgsReadWriteContext &context ) /Factory/;
protected:
private:
QgsTiledSceneRendererMetadata();
};
class QgsTiledSceneRendererRegistry
{
%Docstring(signature="appended")
Registry of 2D renderers for tiled scenes.
:py:class:`QgsTiledSceneRendererRegistry` is not usually directly created, but rather accessed through
:py:func:`QgsApplication.tiledSceneRendererRegistry()`.
.. versionadded:: 3.34
%End
%TypeHeaderCode
#include "qgstiledscenerendererregistry.h"
%End
public:
QgsTiledSceneRendererRegistry();
~QgsTiledSceneRendererRegistry();
bool addRenderer( QgsTiledSceneRendererAbstractMetadata *metadata /Transfer/ );
%Docstring
Adds a renderer to the registry. Takes ownership of the metadata object.
:param metadata: renderer metadata
:return: ``True`` if renderer was added successfully, or ``False`` if renderer could not
be added (e.g., a renderer with a duplicate name already exists)
%End
bool removeRenderer( const QString &rendererName );
%Docstring
Removes a renderer from registry.
:param rendererName: name of renderer to remove from registry
:return: ``True`` if renderer was successfully removed, or ``False`` if matching
renderer could not be found
%End
QgsTiledSceneRendererAbstractMetadata *rendererMetadata( const QString &rendererName );
%Docstring
Returns the metadata for a specified renderer. Returns ``None`` if a matching
renderer was not found in the registry.
%End
QStringList renderersList() const;
%Docstring
Returns a list of available renderers.
%End
static QgsTiledSceneRenderer *defaultRenderer( const QgsTiledSceneLayer *layer ) /Factory/;
%Docstring
Returns a new default tiled scene renderer for a specified ``layer``.
Caller takes ownership of the returned renderer.
%End
private:
QgsTiledSceneRendererRegistry( const QgsTiledSceneRendererRegistry &rh );
};
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/tiledscene/qgstiledscenerendererregistry.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/

View File

@ -717,6 +717,8 @@
%Include auto_generated/tiledscene/qgstiledscenedataprovider.sip
%Include auto_generated/tiledscene/qgstiledsceneindex.sip
%Include auto_generated/tiledscene/qgstiledscenelayer.sip
%Include auto_generated/tiledscene/qgstiledscenerenderer.sip
%Include auto_generated/tiledscene/qgstiledscenerendererregistry.sip
%Include auto_generated/tiledscene/qgstiledscenerequest.sip
%Include auto_generated/tiledscene/qgstiledscenetile.sip
%Include auto_generated/sensor/qgssensormodel.sip

View File

@ -347,6 +347,8 @@ set(QGIS_CORE_SRCS
tiledscene/qgstiledscenelayerrenderer.cpp
tiledscene/qgstiledscenenode.cpp
tiledscene/qgstiledsceneprovidermetadata.cpp
tiledscene/qgstiledscenerenderer.cpp
tiledscene/qgstiledscenerendererregistry.cpp
tiledscene/qgstiledscenerequest.cpp
tiledscene/qgstiledscenetile.cpp
@ -1921,6 +1923,8 @@ set(QGIS_CORE_HDRS
tiledscene/qgstiledscenelayerrenderer.h
tiledscene/qgstiledscenenode.h
tiledscene/qgstiledsceneprovidermetadata.h
tiledscene/qgstiledscenerenderer.h
tiledscene/qgstiledscenerendererregistry.h
tiledscene/qgstiledscenerequest.h
tiledscene/qgstiledscenetile.h

View File

@ -57,6 +57,7 @@
#include "qgssettings.h"
#include "qgssettingsregistrycore.h"
#include "qgstiledownloadmanager.h"
#include "qgstiledscenerendererregistry.h"
#include "qgsunittypes.h"
#include "qgsuserprofile.h"
#include "qgsuserprofilemanager.h"
@ -2428,6 +2429,11 @@ QgsPointCloudRendererRegistry *QgsApplication::pointCloudRendererRegistry()
return members()->mPointCloudRendererRegistry;
}
QgsTiledSceneRendererRegistry *QgsApplication::tiledSceneRendererRegistry()
{
return members()->mTiledSceneRendererRegistry;
}
QgsDataItemProviderRegistry *QgsApplication::dataItemProviderRegistry()
{
if ( auto *lInstance = instance() )
@ -2737,6 +2743,11 @@ QgsApplication::ApplicationMembers::ApplicationMembers()
mPointCloudRendererRegistry = new QgsPointCloudRendererRegistry();
profiler->end();
}
{
profiler->start( tr( "Setup tiled scene renderer registry" ) );
mTiledSceneRendererRegistry = new QgsTiledSceneRendererRegistry();
profiler->end();
}
{
profiler->start( tr( "Setup GPS registry" ) );
mGpsConnectionRegistry = new QgsGpsConnectionRegistry();
@ -2851,6 +2862,7 @@ QgsApplication::ApplicationMembers::~ApplicationMembers()
delete mSensorRegistry;
delete mLayoutItemRegistry;
delete mPointCloudRendererRegistry;
delete mTiledSceneRendererRegistry;
delete mRasterRendererRegistry;
delete mRendererRegistry;
delete mSvgCache;

View File

@ -70,6 +70,7 @@ class QgsConnectionRegistry;
class QgsScaleBarRendererRegistry;
class Qgs3DSymbolRegistry;
class QgsPointCloudRendererRegistry;
class QgsTiledSceneRendererRegistry;
class QgsTileDownloadManager;
class QgsCoordinateReferenceSystemRegistry;
class QgsRecentStyleHandler;
@ -721,6 +722,12 @@ class CORE_EXPORT QgsApplication : public QApplication
*/
static QgsPointCloudRendererRegistry *pointCloudRendererRegistry() SIP_KEEPREFERENCE;
/**
* Returns the application's tiled scene renderer registry, used for managing tiled scene layer 2D renderers.
* \since QGIS 3.34
*/
static QgsTiledSceneRendererRegistry *tiledSceneRendererRegistry() SIP_KEEPREFERENCE;
/**
* Returns the application's data item provider registry, which keeps a list of data item
* providers that may add items to the browser tree.
@ -1170,6 +1177,7 @@ class CORE_EXPORT QgsApplication : public QApplication
QgsRasterRendererRegistry *mRasterRendererRegistry = nullptr;
QgsRendererRegistry *mRendererRegistry = nullptr;
QgsPointCloudRendererRegistry *mPointCloudRendererRegistry = nullptr;
QgsTiledSceneRendererRegistry *mTiledSceneRendererRegistry = nullptr;
QgsSvgCache *mSvgCache = nullptr;
QgsImageCache *mImageCache = nullptr;
QgsSourceCache *mSourceCache = nullptr;

View File

@ -21,10 +21,12 @@
#include "qgspainting.h"
#include "qgsproviderregistry.h"
#include "qgslayermetadataformatter.h"
#include "qgstiledscenerenderer.h"
#include "qgsxmlutils.h"
#include "qgsruntimeprofiler.h"
#include "qgsapplication.h"
#include "qgstiledscenelayerrenderer.h"
#include "qgstiledscenerendererregistry.h"
QgsTiledSceneLayer::QgsTiledSceneLayer( const QString &uri,
const QString &baseName,
@ -62,6 +64,9 @@ QgsTiledSceneLayer *QgsTiledSceneLayer::clone() const
QgsTiledSceneLayer *layer = new QgsTiledSceneLayer( source(), name(), mProviderKey, mLayerOptions );
QgsMapLayer::clone( layer );
if ( mRenderer )
layer->setRenderer( mRenderer->clone() );
layer->mLayerOptions = mLayerOptions;
return layer;
@ -84,6 +89,32 @@ QgsMapLayerRenderer *QgsTiledSceneLayer::createMapRenderer( QgsRenderContext &co
return new QgsTiledSceneLayerRenderer( this, context );
}
QgsTiledSceneRenderer *QgsTiledSceneLayer::renderer()
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
return mRenderer.get();
}
const QgsTiledSceneRenderer *QgsTiledSceneLayer::renderer() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
return mRenderer.get();
}
void QgsTiledSceneLayer::setRenderer( QgsTiledSceneRenderer *renderer )
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
if ( renderer == mRenderer.get() )
return;
mRenderer.reset( renderer );
emit rendererChanged();
emitStyleChanged();
}
QgsTiledSceneDataProvider *QgsTiledSceneLayer::dataProvider()
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
@ -172,7 +203,7 @@ bool QgsTiledSceneLayer::readSymbology( const QDomNode &node, QString &errorMess
return true;
}
bool QgsTiledSceneLayer::readStyle( const QDomNode &node, QString &, QgsReadWriteContext &, QgsMapLayer::StyleCategories categories )
bool QgsTiledSceneLayer::readStyle( const QDomNode &node, QString &, QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
@ -187,6 +218,25 @@ bool QgsTiledSceneLayer::readStyle( const QDomNode &node, QString &, QgsReadWrit
const QDomElement e = blendModeNode.toElement();
setBlendMode( QgsPainting::getCompositionMode( static_cast< Qgis::BlendMode >( e.text().toInt() ) ) );
}
QDomElement rendererElement = node.firstChildElement( QStringLiteral( "renderer" ) );
if ( !rendererElement.isNull() )
{
std::unique_ptr< QgsTiledSceneRenderer > r( QgsTiledSceneRenderer::load( rendererElement, context ) );
if ( r )
{
setRenderer( r.release() );
}
else
{
result = false;
}
}
// make sure layer has a renderer - if none exists, fallback to a default renderer
if ( !mRenderer )
{
setRenderer( QgsTiledSceneRendererRegistry::defaultRenderer( this ) );
}
}
// get and set the layer transparency and scale visibility if they exists
@ -231,7 +281,7 @@ bool QgsTiledSceneLayer::writeSymbology( QDomNode &node, QDomDocument &doc, QStr
return true;
}
bool QgsTiledSceneLayer::writeStyle( QDomNode &node, QDomDocument &doc, QString &, const QgsReadWriteContext &, QgsMapLayer::StyleCategories categories ) const
bool QgsTiledSceneLayer::writeStyle( QDomNode &node, QDomDocument &doc, QString &, const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
@ -250,6 +300,12 @@ bool QgsTiledSceneLayer::writeStyle( QDomNode &node, QDomDocument &doc, QString
const QDomText blendModeText = doc.createTextNode( QString::number( static_cast< int >( QgsPainting::getBlendModeEnum( blendMode() ) ) ) );
blendModeElem.appendChild( blendModeText );
node.appendChild( blendModeElem );
if ( mRenderer )
{
const QDomElement rendererElement = mRenderer->save( doc, context );
node.appendChild( rendererElement );
}
}
// add the layer opacity and scale visibility
@ -321,6 +377,32 @@ void QgsTiledSceneLayer::setDataSourcePrivate( const QString &dataSource, const
{
setExtent( mDataProvider->extent() );
}
bool loadDefaultStyleFlag = false;
if ( flags & QgsDataProvider::FlagLoadDefaultStyle )
{
loadDefaultStyleFlag = true;
}
if ( !mRenderer || loadDefaultStyleFlag )
{
std::unique_ptr< QgsScopedRuntimeProfile > profile;
if ( QgsApplication::profiler()->groupIsActive( QStringLiteral( "projectload" ) ) )
profile = std::make_unique< QgsScopedRuntimeProfile >( tr( "Load layer style" ), QStringLiteral( "projectload" ) );
bool defaultLoadedFlag = false;
if ( !defaultLoadedFlag && loadDefaultStyleFlag )
{
loadDefaultStyle( defaultLoadedFlag );
}
if ( !defaultLoadedFlag )
{
// all else failed, create default renderer
setRenderer( QgsTiledSceneRendererRegistry::defaultRenderer( this ) );
}
}
}
QString QgsTiledSceneLayer::encodedSource( const QString &source, const QgsReadWriteContext &context ) const

View File

@ -22,6 +22,8 @@
#include "qgsmaplayer.h"
#include "qgstiledscenedataprovider.h"
class QgsTiledSceneRenderer;
/**
* \ingroup core
*
@ -112,6 +114,30 @@ class CORE_EXPORT QgsTiledSceneLayer : public QgsMapLayer
QString htmlMetadata() const override;
QgsMapLayerRenderer *createMapRenderer( QgsRenderContext &rendererContext ) override SIP_FACTORY;
/**
* Returns the 2D renderer for the tiled scene.
*
* \see setRenderer()
*/
QgsTiledSceneRenderer *renderer();
/**
* Returns the 2D renderer for the tiled scene.
* \note not available in Python bindings
*
* \see setRenderer()
*/
const QgsTiledSceneRenderer *renderer() const SIP_SKIP;
/**
* Sets the 2D \a renderer for the tiled scene.
*
* Ownership of \a renderer is transferred to the layer.
*
* \see renderer()
*/
void setRenderer( QgsTiledSceneRenderer *renderer SIP_TRANSFER );
private slots:
void setDataSourcePrivate( const QString &dataSource, const QString &baseName, const QString &provider, const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags ) override;
@ -124,6 +150,7 @@ class CORE_EXPORT QgsTiledSceneLayer : public QgsMapLayer
#endif
std::unique_ptr<QgsTiledSceneDataProvider> mDataProvider;
std::unique_ptr<QgsTiledSceneRenderer> mRenderer;
LayerOptions mLayerOptions;
};

View File

@ -0,0 +1,124 @@
/***************************************************************************
qgstiledscenerenderer.cpp
--------------------
begin : August 2023
copyright : (C) 2023 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 "qgstiledscenerenderer.h"
#include "qgsunittypes.h"
#include "qgsapplication.h"
#include "qgstiledscenerendererregistry.h"
#include <QThread>
//
// QgsTiledSceneRenderContext
//
QgsTiledSceneRenderContext::QgsTiledSceneRenderContext( QgsRenderContext &context, QgsFeedback *feedback )
: mRenderContext( context )
, mFeedback( feedback )
{
}
//
// QgsTiledSceneRenderer
//
QgsTiledSceneRenderer *QgsTiledSceneRenderer::load( QDomElement &element, const QgsReadWriteContext &context )
{
if ( element.isNull() )
return nullptr;
// load renderer
const QString rendererType = element.attribute( QStringLiteral( "type" ) );
QgsTiledSceneRendererAbstractMetadata *m = QgsApplication::tiledSceneRendererRegistry()->rendererMetadata( rendererType );
if ( !m )
return nullptr;
std::unique_ptr< QgsTiledSceneRenderer > r( m->createRenderer( element, context ) );
return r.release();
}
void QgsTiledSceneRenderer::startRender( QgsTiledSceneRenderContext & )
{
#ifdef QGISDEBUG
if ( !mThread )
{
mThread = QThread::currentThread();
}
else
{
Q_ASSERT_X( mThread == QThread::currentThread(), "QgsTiledSceneRenderer::startRender", "startRender called in a different thread - use a cloned renderer instead" );
}
#endif
}
void QgsTiledSceneRenderer::stopRender( QgsTiledSceneRenderContext & )
{
#ifdef QGISDEBUG
Q_ASSERT_X( mThread == QThread::currentThread(), "QgsTiledSceneRenderer::stopRender", "stopRender called in a different thread - use a cloned renderer instead" );
#endif
}
double QgsTiledSceneRenderer::maximumScreenError() const
{
return mMaximumScreenError;
}
void QgsTiledSceneRenderer::setMaximumScreenError( double error )
{
mMaximumScreenError = error;
}
Qgis::RenderUnit QgsTiledSceneRenderer::maximumScreenErrorUnit() const
{
return mMaximumScreenErrorUnit;
}
void QgsTiledSceneRenderer::setMaximumScreenErrorUnit( Qgis::RenderUnit unit )
{
mMaximumScreenErrorUnit = unit;
}
QList<QgsLayerTreeModelLegendNode *> QgsTiledSceneRenderer::createLegendNodes( QgsLayerTreeLayer * )
{
return QList<QgsLayerTreeModelLegendNode *>();
}
QStringList QgsTiledSceneRenderer::legendRuleKeys() const
{
return QStringList();
}
void QgsTiledSceneRenderer::copyCommonProperties( QgsTiledSceneRenderer *destination ) const
{
destination->setMaximumScreenError( mMaximumScreenError );
destination->setMaximumScreenErrorUnit( mMaximumScreenErrorUnit );
}
void QgsTiledSceneRenderer::restoreCommonProperties( const QDomElement &element, const QgsReadWriteContext & )
{
mMaximumScreenError = element.attribute( QStringLiteral( "maximumScreenError" ), QStringLiteral( "0.3" ) ).toDouble();
mMaximumScreenErrorUnit = QgsUnitTypes::decodeRenderUnit( element.attribute( QStringLiteral( "maximumScreenErrorUnit" ), QStringLiteral( "MM" ) ) );
}
void QgsTiledSceneRenderer::saveCommonProperties( QDomElement &element, const QgsReadWriteContext & ) const
{
element.setAttribute( QStringLiteral( "maximumScreenError" ), qgsDoubleToString( mMaximumScreenError ) );
element.setAttribute( QStringLiteral( "maximumScreenErrorUnit" ), QgsUnitTypes::encodeUnit( mMaximumScreenErrorUnit ) );
}

View File

@ -0,0 +1,251 @@
/***************************************************************************
qgstiledscenerenderer.h
--------------------
begin : August 2023
copyright : (C) 2023 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 QGSTILEDSCENERENDERER_H
#define QGSTILEDSCENERENDERER_H
#include "qgsrendercontext.h"
#include "qgis_core.h"
#include "qgis_sip.h"
class QgsLayerTreeLayer;
class QgsLayerTreeModelLegendNode;
/**
* \ingroup core
* \class QgsTiledSceneRenderContext
*
* \brief Encapsulates the render context for a 2D tiled scene rendering operation.
*
* \since QGIS 3.34
*/
class CORE_EXPORT QgsTiledSceneRenderContext
{
public:
/**
* Constructor for QgsTiledSceneRenderContext.
*/
QgsTiledSceneRenderContext( QgsRenderContext &context, QgsFeedback *feedback = nullptr );
//! QgsTiledSceneRenderContext cannot be copied.
QgsTiledSceneRenderContext( const QgsTiledSceneRenderContext &rh ) = delete;
//! QgsTiledSceneRenderContext cannot be copied.
QgsTiledSceneRenderContext &operator=( const QgsTiledSceneRenderContext & ) = delete;
/**
* Returns a reference to the context's render context.
*/
QgsRenderContext &renderContext() { return mRenderContext; }
/**
* Returns a reference to the context's render context.
* \note Not available in Python bindings.
*/
const QgsRenderContext &renderContext() const { return mRenderContext; } SIP_SKIP
/**
* Returns the feedback object used to cancel rendering
*
* \since QGIS 3.20
*/
QgsFeedback *feedback() const { return mFeedback; }
private:
#ifdef SIP_RUN
QgsTiledSceneRenderContext( const QgsTiledSceneRenderContext &rh );
#endif
QgsRenderContext &mRenderContext;
QgsFeedback *mFeedback = nullptr;
};
/**
* \ingroup core
* \class QgsTiledSceneRenderer
*
* \brief Abstract base class for 2d tiled scene renderers.
*
* \since QGIS 3.34
*/
class CORE_EXPORT QgsTiledSceneRenderer
{
#ifdef SIP_RUN
SIP_CONVERT_TO_SUBCLASS_CODE
const QString type = sipCpp->type();
sipType = 0;
SIP_END
#endif
public:
/**
* Constructor for QgsTiledSceneRenderer.
*/
QgsTiledSceneRenderer() = default;
virtual ~QgsTiledSceneRenderer() = default;
/**
* Returns the identifier of the renderer type.
*/
virtual QString type() const = 0;
/**
* Create a deep copy of this renderer. Should be implemented by all subclasses
* and generate a proper subclass.
*/
virtual QgsTiledSceneRenderer *clone() const = 0 SIP_FACTORY;
//! QgsTiledSceneRenderer cannot be copied -- use clone() instead
QgsTiledSceneRenderer( const QgsTiledSceneRenderer &other ) = delete;
//! QgsTiledSceneRenderer cannot be copied -- use clone() instead
QgsTiledSceneRenderer &operator=( const QgsTiledSceneRenderer &other ) = delete;
/**
* Creates a renderer from an XML \a element.
*
* Caller takes ownership of the returned renderer.
*
* \see save()
*/
static QgsTiledSceneRenderer *load( QDomElement &element, const QgsReadWriteContext &context ) SIP_FACTORY;
/**
* Saves the renderer configuration to an XML element.
* \see load()
*/
virtual QDomElement save( QDomDocument &doc, const QgsReadWriteContext &context ) const = 0;
/**
* Returns the maximum screen error allowed when rendering the tiled scene.
*
* Larger values result in a faster render with less detailed features rendered.
*
* Units are retrieved via maximumScreenErrorUnit().
*
* \see setMaximumScreenError()
* \see maximumScreenErrorUnit()
*/
double maximumScreenError() const;
/**
* Sets the maximum screen \a error allowed when rendering the tiled scene.
*
* Larger values result in a faster render with less detailed features rendered.
*
* Units are set via setMaximumScreenErrorUnit().
*
* \see maximumScreenError()
* \see setMaximumScreenErrorUnit()
*/
void setMaximumScreenError( double error );
/**
* Returns the unit for the maximum screen error allowed when rendering the tiled scene.
*
* \see maximumScreenError()
* \see setMaximumScreenErrorUnit()
*/
Qgis::RenderUnit maximumScreenErrorUnit() const;
/**
* Sets the \a unit for the maximum screen error allowed when rendering the tiled scene.
*
* \see setMaximumScreenError()
* \see maximumScreenErrorUnit()
*/
void setMaximumScreenErrorUnit( Qgis::RenderUnit unit );
/**
* Must be called when a new render cycle is started. A call to startRender() must always
* be followed by a corresponding call to stopRender() after all features have been rendered.
*
* \see stopRender()
*
* \warning This method is not thread safe. Before calling startRender() in a non-main thread,
* the renderer should instead be cloned and startRender()/stopRender() called on the clone.
*/
virtual void startRender( QgsTiledSceneRenderContext &context );
/**
* Must be called when a render cycle has finished, to allow the renderer to clean up.
*
* Calls to stopRender() must always be preceded by a call to startRender().
*
* \warning This method is not thread safe. Before calling startRender() in a non-main thread,
* the renderer should instead be cloned and startRender()/stopRender() called on the clone.
*
* \see startRender()
*/
virtual void stopRender( QgsTiledSceneRenderContext &context );
/**
* Creates a set of legend nodes representing the renderer.
*/
virtual QList<QgsLayerTreeModelLegendNode *> createLegendNodes( QgsLayerTreeLayer *nodeLayer ) SIP_FACTORY;
/**
* Returns a list of all rule keys for legend nodes created by the renderer.
*/
virtual QStringList legendRuleKeys() const;
protected:
/**
* Copies common tiled scene renderer properties (such as screen error) to the \a destination renderer.
*/
void copyCommonProperties( QgsTiledSceneRenderer *destination ) const;
/**
* Restores common renderer properties (such as screen error) from the
* specified DOM \a element.
*
* \see saveCommonProperties()
*/
void restoreCommonProperties( const QDomElement &element, const QgsReadWriteContext &context );
/**
* Saves common renderer properties (such as point size and screen error) to the
* specified DOM \a element.
*
* \see restoreCommonProperties()
*/
void saveCommonProperties( QDomElement &element, const QgsReadWriteContext &context ) const;
private:
#ifdef SIP_RUN
QgsTiledSceneRenderer( const QgsTiledSceneRenderer &other );
#endif
#ifdef QGISDEBUG
//! Pointer to thread in which startRender was first called
QThread *mThread = nullptr;
#endif
double mMaximumScreenError = 0.3;
Qgis::RenderUnit mMaximumScreenErrorUnit = Qgis::RenderUnit::Millimeters;
};
#endif // QGSTILEDSCENERENDERER_H

View File

@ -0,0 +1,70 @@
/***************************************************************************
qgstiledscenerendererregistry.cpp
---------------------
begin : August 2023
copyright : (C) 2023 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 "qgstiledscenerendererregistry.h"
#include "qgstiledscenerenderer.h"
QgsTiledSceneRendererRegistry::QgsTiledSceneRendererRegistry()
{
// add default renderers
}
QgsTiledSceneRendererRegistry::~QgsTiledSceneRendererRegistry()
{
qDeleteAll( mRenderers );
}
bool QgsTiledSceneRendererRegistry::addRenderer( QgsTiledSceneRendererAbstractMetadata *metadata )
{
if ( !metadata || mRenderers.contains( metadata->name() ) )
return false;
mRenderers[metadata->name()] = metadata;
mRenderersOrder << metadata->name();
return true;
}
bool QgsTiledSceneRendererRegistry::removeRenderer( const QString &rendererName )
{
if ( !mRenderers.contains( rendererName ) )
return false;
delete mRenderers[rendererName];
mRenderers.remove( rendererName );
mRenderersOrder.removeAll( rendererName );
return true;
}
QgsTiledSceneRendererAbstractMetadata *QgsTiledSceneRendererRegistry::rendererMetadata( const QString &rendererName )
{
return mRenderers.value( rendererName );
}
QStringList QgsTiledSceneRendererRegistry::renderersList() const
{
QStringList renderers;
for ( const QString &renderer : mRenderersOrder )
{
QgsTiledSceneRendererAbstractMetadata *r = mRenderers.value( renderer );
if ( r )
renderers << renderer;
}
return renderers;
}
QgsTiledSceneRenderer *QgsTiledSceneRendererRegistry::defaultRenderer( const QgsTiledSceneLayer * )
{
return nullptr;
}

View File

@ -0,0 +1,239 @@
/***************************************************************************
qgstiledscenerendererregistry.h
---------------------
begin : August 2023
copyright : (C) 2023 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 QGSTILEDSCENERENDERERREGISTRY_H
#define QGSTILEDSCENERENDERERREGISTRY_H
#include "qgis_core.h"
#include "qgis_sip.h"
#include <QIcon>
#include <QMap>
#include <QStringList>
#include <QDomElement>
class QgsTiledSceneRenderer;
class QgsReadWriteContext;
class QgsTiledSceneLayer;
class QgsStyle;
#ifndef SIP_RUN
class QgsTiledSceneRendererWidget SIP_EXTERNAL;
#endif
/**
* \ingroup core
* \brief Stores metadata about one tiled scene renderer class.
*
* \note It's necessary to implement createRenderer() function.
* In C++ you can use QgsTiledSceneRendererMetadata convenience class.
*
* \since QGIS 3.34
*/
class CORE_EXPORT QgsTiledSceneRendererAbstractMetadata
{
public:
/**
* Constructor for QgsTiledSceneRendererAbstractMetadata, with the specified \a name.
*
* The \a visibleName argument gives a translated, user friendly string identifying the renderer type.
*
* The \a icon argument can be used to specify an icon representing the renderer.
*/
QgsTiledSceneRendererAbstractMetadata( const QString &name, const QString &visibleName, const QIcon &icon = QIcon() )
: mName( name )
, mVisibleName( visibleName )
, mIcon( icon )
{}
virtual ~QgsTiledSceneRendererAbstractMetadata() = default;
/**
* Returns the unique name of the renderer. This value is not translated.
* \see visibleName()
*/
QString name() const { return mName; }
/**
* Returns a friendly display name of the renderer. This value is translated.
* \see name()
*/
QString visibleName() const { return mVisibleName; }
/**
* Returns an icon representing the renderer.
* \see setIcon()
*/
QIcon icon() const { return mIcon; }
/**
* Sets an \a icon representing the renderer.
* \see icon()
*/
void setIcon( const QIcon &icon ) { mIcon = icon; }
/**
* Returns new instance of the renderer given the DOM element. Returns NULLPTR on error.
* Pure virtual function: must be implemented in derived classes.
*/
virtual QgsTiledSceneRenderer *createRenderer( QDomElement &elem, const QgsReadWriteContext &context ) = 0 SIP_FACTORY;
#ifndef SIP_RUN
/**
* Returns new instance of settings widget for the renderer. Returns NULLPTR on error.
*
* The \a oldRenderer argument may refer to previously used renderer (or it is NULLPTR).
* If not NULLPTR, it may be used to initialize GUI of the widget from the previous settings.
* The old renderer does not have to be of the same type as returned by createRenderer().
*
* \note Not available in Python bindings
*/
virtual QgsTiledSceneRendererWidget *createRendererWidget( QgsTiledSceneLayer *layer, QgsStyle *style, QgsTiledSceneRenderer *oldRenderer ) SIP_FACTORY
{ Q_UNUSED( layer ) Q_UNUSED( style ); Q_UNUSED( oldRenderer ); return nullptr; }
#endif
protected:
//! name used within QGIS for identification (the same what renderer's type() returns)
QString mName;
//! name visible for users (translatable)
QString mVisibleName;
//! icon to be shown in the renderer properties dialog
QIcon mIcon;
};
typedef QgsTiledSceneRenderer *( *QgsTiledSceneRendererCreateFunc )( QDomElement &, const QgsReadWriteContext & ) SIP_SKIP;
typedef QgsTiledSceneRendererWidget *( *QgsTiledSceneRendererWidgetFunc )( QgsTiledSceneLayer *, QgsStyle *, QgsTiledSceneRenderer * ) SIP_SKIP;
/**
* \ingroup core
* \brief Convenience metadata class that uses static functions to create tiled scene renderer and its widget.
* \since QGIS 3.34
*/
class CORE_EXPORT QgsTiledSceneRendererMetadata : public QgsTiledSceneRendererAbstractMetadata
{
public:
/**
* Construct metadata
* \note not available in Python bindings
*/
QgsTiledSceneRendererMetadata( const QString &name,
const QString &visibleName,
QgsTiledSceneRendererCreateFunc pfCreate,
const QIcon &icon = QIcon(),
QgsTiledSceneRendererWidgetFunc pfWidget = nullptr ) SIP_SKIP
: QgsTiledSceneRendererAbstractMetadata( name, visibleName, icon )
, mCreateFunc( pfCreate )
, mWidgetFunc( pfWidget )
{}
QgsTiledSceneRenderer *createRenderer( QDomElement &elem, const QgsReadWriteContext &context ) override SIP_FACTORY
{ return mCreateFunc ? mCreateFunc( elem, context ) : nullptr; }
#ifndef SIP_RUN
QgsTiledSceneRendererWidget *createRendererWidget( QgsTiledSceneLayer *layer, QgsStyle *style, QgsTiledSceneRenderer *renderer ) override SIP_FACTORY
{ return mWidgetFunc ? mWidgetFunc( layer, style, renderer ) : nullptr; }
#endif
//! \note not available in Python bindings
QgsTiledSceneRendererCreateFunc createFunction() const { return mCreateFunc; } SIP_SKIP
//! \note not available in Python bindings
QgsTiledSceneRendererWidgetFunc widgetFunction() const { return mWidgetFunc; } SIP_SKIP
//! \note not available in Python bindings
void setWidgetFunction( QgsTiledSceneRendererWidgetFunc f ) { mWidgetFunc = f; } SIP_SKIP
protected:
//! pointer to function that creates an instance of the renderer when loading project / style
QgsTiledSceneRendererCreateFunc mCreateFunc;
//! pointer to function that creates a widget for configuration of renderer's params
QgsTiledSceneRendererWidgetFunc mWidgetFunc;
private:
#ifdef SIP_RUN
QgsTiledSceneRendererMetadata();
#endif
};
/**
* \ingroup core
* \class QgsTiledSceneRendererRegistry
* \brief Registry of 2D renderers for tiled scenes.
*
* QgsTiledSceneRendererRegistry is not usually directly created, but rather accessed through
* QgsApplication::tiledSceneRendererRegistry().
*
* \since QGIS 3.34
*/
class CORE_EXPORT QgsTiledSceneRendererRegistry
{
public:
QgsTiledSceneRendererRegistry();
~QgsTiledSceneRendererRegistry();
//! QgsTiledSceneRendererRegistry cannot be copied.
QgsTiledSceneRendererRegistry( const QgsTiledSceneRendererRegistry &rh ) = delete;
//! QgsTiledSceneRendererRegistry cannot be copied.
QgsTiledSceneRendererRegistry &operator=( const QgsTiledSceneRendererRegistry &rh ) = delete;
/**
* Adds a renderer to the registry. Takes ownership of the metadata object.
* \param metadata renderer metadata
* \returns TRUE if renderer was added successfully, or FALSE if renderer could not
* be added (e.g., a renderer with a duplicate name already exists)
*/
bool addRenderer( QgsTiledSceneRendererAbstractMetadata *metadata SIP_TRANSFER );
/**
* Removes a renderer from registry.
* \param rendererName name of renderer to remove from registry
* \returns TRUE if renderer was successfully removed, or FALSE if matching
* renderer could not be found
*/
bool removeRenderer( const QString &rendererName );
/**
* Returns the metadata for a specified renderer. Returns NULLPTR if a matching
* renderer was not found in the registry.
*/
QgsTiledSceneRendererAbstractMetadata *rendererMetadata( const QString &rendererName );
/**
* Returns a list of available renderers.
*/
QStringList renderersList() const;
/**
* Returns a new default tiled scene renderer for a specified \a layer.
*
* Caller takes ownership of the returned renderer.
*/
static QgsTiledSceneRenderer *defaultRenderer( const QgsTiledSceneLayer *layer ) SIP_FACTORY;
private:
#ifdef SIP_RUN
QgsTiledSceneRendererRegistry( const QgsTiledSceneRendererRegistry &rh );
#endif
//! Map of name to renderer
QMap<QString, QgsTiledSceneRendererAbstractMetadata *> mRenderers;
//! List of renderers, maintained in the order that they have been added
QStringList mRenderersOrder;
};
#endif // QGSTILEDSCENERENDERERREGISTRY_H

View File

@ -194,6 +194,7 @@ set(TESTS
testqgstemporalproperty.cpp
testqgstemporalrangeobject.cpp
testqgstiledsceneconnection.cpp
testqgstiledscenerendererregistry.cpp
testqgstiledownloadmanager.cpp
testqgstracer.cpp
testqgstranslateproject.cpp

View File

@ -0,0 +1,139 @@
/***************************************************************************
testqgstiledscenerendererregistry.cpp
-----------------------
begin : August 2023
copyright : (C) 2023 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 "qgstiledscenerendererregistry.h"
#include "qgstiledscenerenderer.h"
#include "qgsreadwritecontext.h"
#include <QObject>
#include "qgstest.h"
//dummy renderer for testing
class DummyRenderer : public QgsTiledSceneRenderer
{
public:
DummyRenderer() = default;
QString type() const override { return QStringLiteral( "dummy" ); }
QgsTiledSceneRenderer *clone() const override { return new DummyRenderer(); }
static QgsTiledSceneRenderer *create( QDomElement &, const QgsReadWriteContext & ) { return new DummyRenderer(); }
QDomElement save( QDomDocument &doc, const QgsReadWriteContext & ) const override { return doc.createElement( QStringLiteral( "test" ) ); }
};
class TestQgsTiledSceneRendererRegistry : public QObject
{
Q_OBJECT
private slots:
void initTestCase();
void cleanupTestCase();
void init();
void cleanup();
void metadata();
void createInstance();
void instanceHasDefaultRenderers();
void addRenderer();
void fetchTypes();
private:
};
void TestQgsTiledSceneRendererRegistry::initTestCase()
{
QgsApplication::init(); // init paths for CRS lookup
QgsApplication::initQgis();
}
void TestQgsTiledSceneRendererRegistry::cleanupTestCase()
{
QgsApplication::exitQgis();
}
void TestQgsTiledSceneRendererRegistry::init()
{
}
void TestQgsTiledSceneRendererRegistry::cleanup()
{
}
void TestQgsTiledSceneRendererRegistry::metadata()
{
QgsTiledSceneRendererMetadata metadata = QgsTiledSceneRendererMetadata( QStringLiteral( "name" ), QStringLiteral( "display name" ), DummyRenderer::create, QIcon() );
QCOMPARE( metadata.name(), QString( "name" ) );
QCOMPARE( metadata.visibleName(), QString( "display name" ) );
//test creating renderer from metadata
QDomElement elem;
const std::unique_ptr< QgsTiledSceneRenderer > renderer( metadata.createRenderer( elem, QgsReadWriteContext() ) );
QVERIFY( renderer );
DummyRenderer *dummyRenderer = dynamic_cast<DummyRenderer *>( renderer.get() );
QVERIFY( dummyRenderer );
}
void TestQgsTiledSceneRendererRegistry::createInstance()
{
QgsTiledSceneRendererRegistry *registry = QgsApplication::tiledSceneRendererRegistry();
QVERIFY( registry );
}
void TestQgsTiledSceneRendererRegistry::instanceHasDefaultRenderers()
{
//check that callout registry is initially populated with some renderers
//(assumes that there is some default renderers)
QgsTiledSceneRendererRegistry *registry = QgsApplication::tiledSceneRendererRegistry();
QVERIFY( registry->renderersList().length() > 0 );
}
void TestQgsTiledSceneRendererRegistry::addRenderer()
{
QgsTiledSceneRendererRegistry *registry = QgsApplication::tiledSceneRendererRegistry();
const int previousCount = registry->renderersList().length();
registry->addRenderer( new QgsTiledSceneRendererMetadata( QStringLiteral( "Dummy" ), QStringLiteral( "Dummy renderer" ), DummyRenderer::create, QIcon() ) );
QCOMPARE( registry->renderersList().length(), previousCount + 1 );
//try adding again, should have no effect
QgsTiledSceneRendererMetadata *dupe = new QgsTiledSceneRendererMetadata( QStringLiteral( "Dummy" ), QStringLiteral( "Dummy callout" ), DummyRenderer::create, QIcon() );
QVERIFY( ! registry->addRenderer( dupe ) );
QCOMPARE( registry->renderersList().length(), previousCount + 1 );
delete dupe;
//try adding empty metadata
registry->addRenderer( nullptr );
QCOMPARE( registry->renderersList().length(), previousCount + 1 );
}
void TestQgsTiledSceneRendererRegistry::fetchTypes()
{
QgsTiledSceneRendererRegistry *registry = QgsApplication::tiledSceneRendererRegistry();
const QStringList types = registry->renderersList();
QVERIFY( types.contains( "Dummy" ) );
QgsTiledSceneRendererAbstractMetadata *metadata = registry->rendererMetadata( QStringLiteral( "Dummy" ) );
QCOMPARE( metadata->name(), QString( "Dummy" ) );
//metadata for bad renderer
metadata = registry->rendererMetadata( QStringLiteral( "bad renderer" ) );
QVERIFY( !metadata );
}
QGSTEST_MAIN( TestQgsTiledSceneRendererRegistry )
#include "testqgstiledscenerendererregistry.moc"