mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-07 00:15:48 -04:00
Initial work on rendered feature handler interface
Adds an interface for classes which provider custom handlers for features rendered as part of a map render job. QgsRenderedFeatureHandlerInterface objects are registered in the QgsMapSettings objects used to construct map render jobs. During the rendering operation, the handleRenderedFeature() method will be called once for every rendered feature, allowing the handler to perform some custom task based on the provided information. They can be used for custom tasks which operate on a set of rendered features, such as creating spatial indexes of the location and rendered symbology bounding box of all features rendered on a map.
This commit is contained in:
parent
2cc6775354
commit
c71cd4b5fc
@ -656,6 +656,27 @@ The default is to use no global simplification, and fallback to individual layer
|
||||
|
||||
.. seealso:: :py:func:`setSimplifyMethod`
|
||||
|
||||
.. versionadded:: 3.10
|
||||
%End
|
||||
|
||||
void addRenderedFeatureHandler( QgsRenderedFeatureHandlerInterface *handler );
|
||||
%Docstring
|
||||
Adds a rendered feature ``handler`` to use while rendering the map settings.
|
||||
|
||||
Ownership of ``handler`` is NOT transferred, and it is the caller's responsibility to ensure
|
||||
that the handler exists for the lifetime of the map render job.
|
||||
|
||||
.. seealso:: :py:func:`renderedFeatureHandlers`
|
||||
|
||||
.. versionadded:: 3.10
|
||||
%End
|
||||
|
||||
QList< QgsRenderedFeatureHandlerInterface * > renderedFeatureHandlers() const;
|
||||
%Docstring
|
||||
Returns the list of rendered feature handlers to use while rendering the map settings.
|
||||
|
||||
.. seealso:: :py:func:`addRenderedFeatureHandler`
|
||||
|
||||
.. versionadded:: 3.10
|
||||
%End
|
||||
|
||||
|
@ -569,6 +569,24 @@ Sets the text render ``format``, which dictates how text is rendered (e.g. as pa
|
||||
.. seealso:: :py:func:`textRenderFormat`
|
||||
|
||||
.. versionadded:: 3.4.3
|
||||
%End
|
||||
|
||||
QList<QgsRenderedFeatureHandlerInterface *> renderedFeatureHandlers() const;
|
||||
%Docstring
|
||||
Returns the list of rendered feature handlers to use while rendering map layers.
|
||||
|
||||
.. seealso:: :py:func:`hasRenderedFeatureHandlers`
|
||||
|
||||
.. versionadded:: 3.10
|
||||
%End
|
||||
|
||||
bool hasRenderedFeatureHandlers() const;
|
||||
%Docstring
|
||||
Returns ``True`` if the context has any rendered feature handlers.
|
||||
|
||||
.. seealso:: :py:func:`renderedFeatureHandlers`
|
||||
|
||||
.. versionadded:: 3.10
|
||||
%End
|
||||
|
||||
};
|
||||
|
@ -0,0 +1,68 @@
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/core/qgsrenderedfeaturehandlerinterface.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
class QgsRenderedFeatureHandlerInterface
|
||||
{
|
||||
%Docstring
|
||||
|
||||
An interface for classes which provider custom handlers for features rendered
|
||||
as part of a map render job.
|
||||
|
||||
QgsRenderedFeatureHandlerInterface objects are registered in the QgsMapSettings
|
||||
objects used to construct map render jobs. During the rendering operation,
|
||||
the handleRenderedFeature() method will be called once for every rendered feature,
|
||||
allowing the handler to perform some custom task based on the provided information.
|
||||
|
||||
They can be used for custom tasks which operate on a set of rendered features,
|
||||
such as creating spatial indexes of the location and rendered symbology bounding box
|
||||
of all features rendered on a map.
|
||||
|
||||
.. versionadded:: 3.10
|
||||
%End
|
||||
|
||||
%TypeHeaderCode
|
||||
#include "qgsrenderedfeaturehandlerinterface.h"
|
||||
%End
|
||||
public:
|
||||
virtual ~QgsRenderedFeatureHandlerInterface();
|
||||
|
||||
struct RenderedFeatureContext
|
||||
{
|
||||
bool dummy;
|
||||
};
|
||||
|
||||
virtual void handleRenderedFeature( const QgsFeature &feature, const QgsGeometry &renderedBounds, const QgsRenderedFeatureHandlerInterface::RenderedFeatureContext &context ) = 0;
|
||||
%Docstring
|
||||
Called whenever a ``feature`` is rendered during a map render job.
|
||||
|
||||
The ``renderedBounds`` argument specifies the (approximate) bounds of the rendered feature's
|
||||
symbology. E.g. for point geometry features, this will be the bounding box of the marker symbol
|
||||
used to symbolize the point. ``renderedBounds`` geometries are specified in painter units (not
|
||||
map units).
|
||||
|
||||
.. warning::
|
||||
|
||||
This method may be called from many different threads (for multi-threaded map render operations),
|
||||
and accordingly care must be taken to ensure that handleRenderedFeature() implementations are
|
||||
appropriately thread safe.
|
||||
|
||||
The ``context`` argument is used to provide additional context relating to the rendering of a feature.
|
||||
%End
|
||||
|
||||
};
|
||||
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/core/qgsrenderedfeaturehandlerinterface.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
@ -112,6 +112,7 @@
|
||||
%Include auto_generated/qgsreadwritelocker.sip
|
||||
%Include auto_generated/qgsrenderchecker.sip
|
||||
%Include auto_generated/qgsrendercontext.sip
|
||||
%Include auto_generated/qgsrenderedfeaturehandlerinterface.sip
|
||||
%Include auto_generated/qgsrulebasedlabeling.sip
|
||||
%Include auto_generated/qgsruntimeprofiler.sip
|
||||
%Include auto_generated/qgsscalecalculator.sip
|
||||
|
@ -994,6 +994,7 @@ SET(QGIS_CORE_HDRS
|
||||
qgsreadwritelocker.h
|
||||
qgsrenderchecker.h
|
||||
qgsrendercontext.h
|
||||
qgsrenderedfeaturehandlerinterface.h
|
||||
qgsrulebasedlabeling.h
|
||||
qgsruntimeprofiler.h
|
||||
qgsscalecalculator.h
|
||||
|
@ -677,3 +677,13 @@ void QgsMapSettings::setLabelBoundaryGeometry( const QgsGeometry &boundary )
|
||||
{
|
||||
mLabelBoundaryGeometry = boundary;
|
||||
}
|
||||
|
||||
void QgsMapSettings::addRenderedFeatureHandler( QgsRenderedFeatureHandlerInterface *handler )
|
||||
{
|
||||
mRenderedFeatureHandlers.append( handler );
|
||||
}
|
||||
|
||||
QList<QgsRenderedFeatureHandlerInterface *> QgsMapSettings::renderedFeatureHandlers() const
|
||||
{
|
||||
return mRenderedFeatureHandlers;
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ class QPainter;
|
||||
class QgsCoordinateTransform;
|
||||
class QgsScaleCalculator;
|
||||
class QgsMapRendererJob;
|
||||
class QgsRenderedFeatureHandlerInterface;
|
||||
|
||||
/**
|
||||
* \class QgsLabelBlockingRegion
|
||||
@ -578,6 +579,24 @@ class CORE_EXPORT QgsMapSettings
|
||||
*/
|
||||
const QgsVectorSimplifyMethod &simplifyMethod() const { return mSimplifyMethod; }
|
||||
|
||||
/**
|
||||
* Adds a rendered feature \a handler to use while rendering the map settings.
|
||||
*
|
||||
* Ownership of \a handler is NOT transferred, and it is the caller's responsibility to ensure
|
||||
* that the handler exists for the lifetime of the map render job.
|
||||
*
|
||||
* \see renderedFeatureHandlers()
|
||||
* \since QGIS 3.10
|
||||
*/
|
||||
void addRenderedFeatureHandler( QgsRenderedFeatureHandlerInterface *handler );
|
||||
|
||||
/**
|
||||
* Returns the list of rendered feature handlers to use while rendering the map settings.
|
||||
* \see addRenderedFeatureHandler()
|
||||
* \since QGIS 3.10
|
||||
*/
|
||||
QList< QgsRenderedFeatureHandlerInterface * > renderedFeatureHandlers() const;
|
||||
|
||||
protected:
|
||||
|
||||
double mDpi;
|
||||
@ -642,6 +661,7 @@ class CORE_EXPORT QgsMapSettings
|
||||
private:
|
||||
|
||||
QList< QgsLabelBlockingRegion > mLabelBlockingRegions;
|
||||
QList< QgsRenderedFeatureHandlerInterface * > mRenderedFeatureHandlers;
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS( QgsMapSettings::Flags )
|
||||
|
@ -59,6 +59,8 @@ QgsRenderContext::QgsRenderContext( const QgsRenderContext &rh )
|
||||
, mTransformContext( rh.mTransformContext )
|
||||
, mPathResolver( rh.mPathResolver )
|
||||
, mTextRenderFormat( rh.mTextRenderFormat )
|
||||
, mRenderedFeatureHandlers( rh.mRenderedFeatureHandlers )
|
||||
, mHasRenderedFeatureHandlers( rh.mHasRenderedFeatureHandlers )
|
||||
#ifdef QGISDEBUG
|
||||
, mHasTransformContext( rh.mHasTransformContext )
|
||||
#endif
|
||||
@ -88,6 +90,8 @@ QgsRenderContext &QgsRenderContext::operator=( const QgsRenderContext &rh )
|
||||
mTransformContext = rh.mTransformContext;
|
||||
mPathResolver = rh.mPathResolver;
|
||||
mTextRenderFormat = rh.mTextRenderFormat;
|
||||
mRenderedFeatureHandlers = rh.mRenderedFeatureHandlers;
|
||||
mHasRenderedFeatureHandlers = rh.mHasRenderedFeatureHandlers;
|
||||
#ifdef QGISDEBUG
|
||||
mHasTransformContext = rh.mHasTransformContext;
|
||||
#endif
|
||||
@ -185,6 +189,8 @@ QgsRenderContext QgsRenderContext::fromMapSettings( const QgsMapSettings &mapSet
|
||||
ctx.setPathResolver( mapSettings.pathResolver() );
|
||||
ctx.setTextRenderFormat( mapSettings.textRenderFormat() );
|
||||
ctx.setVectorSimplifyMethod( mapSettings.simplifyMethod() );
|
||||
ctx.mRenderedFeatureHandlers = mapSettings.renderedFeatureHandlers();
|
||||
ctx.mHasRenderedFeatureHandlers = !mapSettings.renderedFeatureHandlers().isEmpty();
|
||||
//this flag is only for stopping during the current rendering progress,
|
||||
//so must be false at every new render operation
|
||||
ctx.setRenderingStopped( false );
|
||||
@ -460,4 +466,9 @@ double QgsRenderContext::convertMetersToMapUnits( double meters ) const
|
||||
return meters;
|
||||
}
|
||||
|
||||
QList<QgsRenderedFeatureHandlerInterface *> QgsRenderContext::renderedFeatureHandlers() const
|
||||
{
|
||||
return mRenderedFeatureHandlers;
|
||||
}
|
||||
|
||||
|
||||
|
@ -38,6 +38,7 @@ class QPainter;
|
||||
class QgsAbstractGeometry;
|
||||
class QgsLabelingEngine;
|
||||
class QgsMapSettings;
|
||||
class QgsRenderedFeatureHandlerInterface;
|
||||
|
||||
|
||||
/**
|
||||
@ -595,6 +596,20 @@ class CORE_EXPORT QgsRenderContext
|
||||
mTextRenderFormat = format;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of rendered feature handlers to use while rendering map layers.
|
||||
* \see hasRenderedFeatureHandlers()
|
||||
* \since QGIS 3.10
|
||||
*/
|
||||
QList<QgsRenderedFeatureHandlerInterface *> renderedFeatureHandlers() const;
|
||||
|
||||
/**
|
||||
* Returns TRUE if the context has any rendered feature handlers.
|
||||
* \see renderedFeatureHandlers()
|
||||
* \since QGIS 3.10
|
||||
*/
|
||||
bool hasRenderedFeatureHandlers() const { return mHasRenderedFeatureHandlers; }
|
||||
|
||||
private:
|
||||
|
||||
Flags mFlags;
|
||||
@ -653,6 +668,8 @@ class CORE_EXPORT QgsRenderContext
|
||||
QgsPathResolver mPathResolver;
|
||||
|
||||
TextRenderFormat mTextRenderFormat = TextFormatAlwaysOutlines;
|
||||
QList< QgsRenderedFeatureHandlerInterface * > mRenderedFeatureHandlers;
|
||||
bool mHasRenderedFeatureHandlers = false;
|
||||
|
||||
#ifdef QGISDEBUG
|
||||
bool mHasTransformContext = false;
|
||||
|
72
src/core/qgsrenderedfeaturehandlerinterface.h
Normal file
72
src/core/qgsrenderedfeaturehandlerinterface.h
Normal file
@ -0,0 +1,72 @@
|
||||
/***************************************************************************
|
||||
qgsrenderedfeaturehandlerinterface.h
|
||||
--------------------------------------
|
||||
Date : August 2019
|
||||
Copyright : (C) 2019 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 QGSRENDEREDFEATUREHANDLERINTERFACE_H
|
||||
#define QGSRENDEREDFEATUREHANDLERINTERFACE_H
|
||||
|
||||
#include "qgis_core.h"
|
||||
|
||||
class QgsFeature;
|
||||
class QgsGeometry;
|
||||
|
||||
/**
|
||||
* \ingroup core
|
||||
*
|
||||
* An interface for classes which provider custom handlers for features rendered
|
||||
* as part of a map render job.
|
||||
*
|
||||
* QgsRenderedFeatureHandlerInterface objects are registered in the QgsMapSettings
|
||||
* objects used to construct map render jobs. During the rendering operation,
|
||||
* the handleRenderedFeature() method will be called once for every rendered feature,
|
||||
* allowing the handler to perform some custom task based on the provided information.
|
||||
*
|
||||
* They can be used for custom tasks which operate on a set of rendered features,
|
||||
* such as creating spatial indexes of the location and rendered symbology bounding box
|
||||
* of all features rendered on a map.
|
||||
*
|
||||
* \since QGIS 3.10
|
||||
*/
|
||||
class CORE_EXPORT QgsRenderedFeatureHandlerInterface
|
||||
{
|
||||
public:
|
||||
virtual ~QgsRenderedFeatureHandlerInterface() = default;
|
||||
|
||||
struct CORE_EXPORT RenderedFeatureContext
|
||||
{
|
||||
///@cond PRIVATE
|
||||
// required to allow compilation only until real members are present
|
||||
bool dummy;
|
||||
///@endcond
|
||||
};
|
||||
|
||||
/**
|
||||
* Called whenever a \a feature is rendered during a map render job.
|
||||
*
|
||||
* The \a renderedBounds argument specifies the (approximate) bounds of the rendered feature's
|
||||
* symbology. E.g. for point geometry features, this will be the bounding box of the marker symbol
|
||||
* used to symbolize the point. \a renderedBounds geometries are specified in painter units (not
|
||||
* map units).
|
||||
*
|
||||
* \warning This method may be called from many different threads (for multi-threaded map render operations),
|
||||
* and accordingly care must be taken to ensure that handleRenderedFeature() implementations are
|
||||
* appropriately thread safe.
|
||||
*
|
||||
* The \a context argument is used to provide additional context relating to the rendering of a feature.
|
||||
*/
|
||||
virtual void handleRenderedFeature( const QgsFeature &feature, const QgsGeometry &renderedBounds, const QgsRenderedFeatureHandlerInterface::RenderedFeatureContext &context ) = 0;
|
||||
|
||||
};
|
||||
|
||||
#endif // QGSRENDEREDFEATUREHANDLERINTERFACE_H
|
@ -29,6 +29,15 @@
|
||||
#include "qgsvectorlayer.h"
|
||||
#include "qgscoordinatereferencesystem.h"
|
||||
#include "qgsexpressioncontextutils.h"
|
||||
#include "qgsrenderedfeaturehandlerinterface.h"
|
||||
|
||||
class TestHandler : public QgsRenderedFeatureHandlerInterface
|
||||
{
|
||||
public:
|
||||
|
||||
void handleRenderedFeature( const QgsFeature &, const QgsGeometry &, const QgsRenderedFeatureHandlerInterface::RenderedFeatureContext & ) override {}
|
||||
|
||||
};
|
||||
|
||||
class TestQgsMapSettings: public QObject
|
||||
{
|
||||
@ -50,6 +59,7 @@ class TestQgsMapSettings: public QObject
|
||||
void testSetLayers();
|
||||
void testLabelBoundary();
|
||||
void testExpressionContext();
|
||||
void testRenderedFeatureHandlers();
|
||||
|
||||
private:
|
||||
QString toString( const QPolygonF &p, int decimalPlaces = 2 ) const;
|
||||
@ -487,5 +497,21 @@ void TestQgsMapSettings::testExpressionContext()
|
||||
QCOMPARE( r.toString(), QStringLiteral( "WGS84" ) );
|
||||
}
|
||||
|
||||
void TestQgsMapSettings::testRenderedFeatureHandlers()
|
||||
{
|
||||
std::unique_ptr< TestHandler > testHandler = qgis::make_unique< TestHandler >();
|
||||
std::unique_ptr< TestHandler > testHandler2 = qgis::make_unique< TestHandler >();
|
||||
|
||||
std::unique_ptr< QgsMapSettings> mapSettings = qgis::make_unique< QgsMapSettings >();
|
||||
QVERIFY( mapSettings->renderedFeatureHandlers().isEmpty() );
|
||||
mapSettings->addRenderedFeatureHandler( testHandler.get() );
|
||||
mapSettings->addRenderedFeatureHandler( testHandler2.get() );
|
||||
QCOMPARE( mapSettings->renderedFeatureHandlers(), QList< QgsRenderedFeatureHandlerInterface * >() << testHandler.get() << testHandler2.get() );
|
||||
|
||||
//ownership should NOT be transferred, i.e. it won't delete the registered handlers upon QgsMapSettings destruction
|
||||
mapSettings.reset();
|
||||
// should be no double-delete here
|
||||
}
|
||||
|
||||
QGSTEST_MAIN( TestQgsMapSettings )
|
||||
#include "testqgsmapsettings.moc"
|
||||
|
@ -21,7 +21,8 @@ from qgis.core import (QgsRenderContext,
|
||||
QgsUnitTypes,
|
||||
QgsProject,
|
||||
QgsRectangle,
|
||||
QgsVectorSimplifyMethod)
|
||||
QgsVectorSimplifyMethod,
|
||||
QgsRenderedFeatureHandlerInterface)
|
||||
from qgis.PyQt.QtCore import QSize
|
||||
from qgis.PyQt.QtGui import QPainter, QImage
|
||||
from qgis.testing import start_app, unittest
|
||||
@ -32,6 +33,12 @@ import math
|
||||
start_app()
|
||||
|
||||
|
||||
class TestFeatureHandler(QgsRenderedFeatureHandlerInterface):
|
||||
|
||||
def handleRenderedFeature(self, feature, geometry, context):
|
||||
pass
|
||||
|
||||
|
||||
class TestQgsRenderContext(unittest.TestCase):
|
||||
|
||||
def testGettersSetters(self):
|
||||
@ -135,6 +142,29 @@ class TestQgsRenderContext(unittest.TestCase):
|
||||
rc2 = QgsRenderContext(rc)
|
||||
self.assertEqual(rc2.vectorSimplifyMethod().simplifyHints(), QgsVectorSimplifyMethod.GeometrySimplification)
|
||||
|
||||
def testRenderedFeatureHandlers(self):
|
||||
rc = QgsRenderContext()
|
||||
self.assertFalse(rc.renderedFeatureHandlers())
|
||||
self.assertFalse(rc.hasRenderedFeatureHandlers())
|
||||
|
||||
ms = QgsMapSettings()
|
||||
rc = QgsRenderContext.fromMapSettings(ms)
|
||||
self.assertFalse(rc.renderedFeatureHandlers())
|
||||
self.assertFalse(rc.hasRenderedFeatureHandlers())
|
||||
|
||||
handler = TestFeatureHandler()
|
||||
handler2 = TestFeatureHandler()
|
||||
ms.addRenderedFeatureHandler(handler)
|
||||
ms.addRenderedFeatureHandler(handler2)
|
||||
|
||||
rc = QgsRenderContext.fromMapSettings(ms)
|
||||
self.assertEqual(rc.renderedFeatureHandlers(), [handler, handler2])
|
||||
self.assertTrue(rc.hasRenderedFeatureHandlers())
|
||||
|
||||
rc2 = QgsRenderContext(rc)
|
||||
self.assertEqual(rc2.renderedFeatureHandlers(), [handler, handler2])
|
||||
self.assertTrue(rc2.hasRenderedFeatureHandlers())
|
||||
|
||||
def testRenderMetersInMapUnits(self):
|
||||
|
||||
crs_wsg84 = QgsCoordinateReferenceSystem.fromOgcWmsCrs('EPSG:4326')
|
||||
|
Loading…
x
Reference in New Issue
Block a user