diff --git a/python/PyQt6/core/auto_generated/painting/qgsgeometrypaintdevice.sip.in b/python/PyQt6/core/auto_generated/painting/qgsgeometrypaintdevice.sip.in index 682745c9c253..371851e85d7a 100644 --- a/python/PyQt6/core/auto_generated/painting/qgsgeometrypaintdevice.sip.in +++ b/python/PyQt6/core/auto_generated/painting/qgsgeometrypaintdevice.sip.in @@ -58,6 +58,13 @@ Set ``tolerance`` to 0 to disable simplification. (No simplification is the defa const QgsAbstractGeometry &geometry() const; %Docstring Returns the rendered geometry. +%End + + static QgsGeometry painterPathToGeometry( const QPainterPath &path ); +%Docstring +Converts a painter ``path`` to a :py:class:`QgsGeometry`. + +.. versionadded:: 3.38.1 %End }; diff --git a/python/PyQt6/core/auto_generated/painting/qgsmaskpaintdevice.sip.in b/python/PyQt6/core/auto_generated/painting/qgsmaskpaintdevice.sip.in index f89755db8454..a2b64f837d59 100644 --- a/python/PyQt6/core/auto_generated/painting/qgsmaskpaintdevice.sip.in +++ b/python/PyQt6/core/auto_generated/painting/qgsmaskpaintdevice.sip.in @@ -17,7 +17,8 @@ class QgsMaskPaintDevice: QPaintDevice Mask painter device that can be used to register everything painted into a QPainterPath used later as clip path -.. versionadded:: 3.26 +.. deprecated:: + QGIS 3.38, use :py:class:`QgsGeometryPaintDevice` instead %End %TypeHeaderCode @@ -25,12 +26,15 @@ used later as clip path %End public: - QgsMaskPaintDevice( bool usePathStroker = false ); + QgsMaskPaintDevice( bool usePathStroker = false ) /Deprecated/; %Docstring ! Constructor If ``usePathStroker`` is ``True``, path will be considered with a stroke regarding QPainter pen configuration + +.. deprecated:: + QGIS 3.38, use :py:class:`QgsGeometryPaintDevice` instead %End virtual QPaintEngine *paintEngine() const; @@ -39,9 +43,12 @@ pen configuration virtual int metric( PaintDeviceMetric metric ) const; - QPainterPath maskPainterPath() const; + QPainterPath maskPainterPath() const /Deprecated/; %Docstring Returns the mask painter path painted on this paint device + +.. deprecated:: + Use :py:class:`QgsGeometryPaintDevice` instead %End }; diff --git a/python/PyQt6/core/auto_generated/qgsrendercontext.sip.in b/python/PyQt6/core/auto_generated/qgsrendercontext.sip.in index 9f6577b31e49..0b4ba3913447 100644 --- a/python/PyQt6/core/auto_generated/qgsrendercontext.sip.in +++ b/python/PyQt6/core/auto_generated/qgsrendercontext.sip.in @@ -972,22 +972,24 @@ are drawn and behave during render operations. .. versionadded:: 3.38 %End - void addSymbolLayerClipPath( const QString &symbolLayerId, QPainterPath path ); + void addSymbolLayerClipPath( const QString &symbolLayerId, QPainterPath path ) /Deprecated/; %Docstring Add a clip ``path`` to be applied to the ``symbolLayer`` before rendering .. seealso:: :py:func:`addSymbolLayerClipGeometry` -.. versionadded:: 3.26 +.. deprecated:: + QGIS 3.38, use :py:func:`~QgsRenderContext.addSymbolLayerClipGeometry` instead. %End - QList symbolLayerClipPaths( const QString &symbolLayerId ) const; + QList symbolLayerClipPaths( const QString &symbolLayerId ) const /Deprecated/; %Docstring Returns clip paths to be applied to the ``symbolLayer`` before rendering .. seealso:: :py:func:`symbolLayerClipGeometries` -.. versionadded:: 3.26 +.. deprecated:: + QGIS 3.38, use :py:func:`~QgsRenderContext.symbolLayerClipGeometries` instead. %End void addSymbolLayerClipGeometry( const QString &symbolLayerId, const QgsGeometry &geometry ); diff --git a/python/core/auto_generated/painting/qgsgeometrypaintdevice.sip.in b/python/core/auto_generated/painting/qgsgeometrypaintdevice.sip.in index 682745c9c253..371851e85d7a 100644 --- a/python/core/auto_generated/painting/qgsgeometrypaintdevice.sip.in +++ b/python/core/auto_generated/painting/qgsgeometrypaintdevice.sip.in @@ -58,6 +58,13 @@ Set ``tolerance`` to 0 to disable simplification. (No simplification is the defa const QgsAbstractGeometry &geometry() const; %Docstring Returns the rendered geometry. +%End + + static QgsGeometry painterPathToGeometry( const QPainterPath &path ); +%Docstring +Converts a painter ``path`` to a :py:class:`QgsGeometry`. + +.. versionadded:: 3.38.1 %End }; diff --git a/python/core/auto_generated/painting/qgsmaskpaintdevice.sip.in b/python/core/auto_generated/painting/qgsmaskpaintdevice.sip.in index f89755db8454..a2b64f837d59 100644 --- a/python/core/auto_generated/painting/qgsmaskpaintdevice.sip.in +++ b/python/core/auto_generated/painting/qgsmaskpaintdevice.sip.in @@ -17,7 +17,8 @@ class QgsMaskPaintDevice: QPaintDevice Mask painter device that can be used to register everything painted into a QPainterPath used later as clip path -.. versionadded:: 3.26 +.. deprecated:: + QGIS 3.38, use :py:class:`QgsGeometryPaintDevice` instead %End %TypeHeaderCode @@ -25,12 +26,15 @@ used later as clip path %End public: - QgsMaskPaintDevice( bool usePathStroker = false ); + QgsMaskPaintDevice( bool usePathStroker = false ) /Deprecated/; %Docstring ! Constructor If ``usePathStroker`` is ``True``, path will be considered with a stroke regarding QPainter pen configuration + +.. deprecated:: + QGIS 3.38, use :py:class:`QgsGeometryPaintDevice` instead %End virtual QPaintEngine *paintEngine() const; @@ -39,9 +43,12 @@ pen configuration virtual int metric( PaintDeviceMetric metric ) const; - QPainterPath maskPainterPath() const; + QPainterPath maskPainterPath() const /Deprecated/; %Docstring Returns the mask painter path painted on this paint device + +.. deprecated:: + Use :py:class:`QgsGeometryPaintDevice` instead %End }; diff --git a/python/core/auto_generated/qgsrendercontext.sip.in b/python/core/auto_generated/qgsrendercontext.sip.in index 9f6577b31e49..0b4ba3913447 100644 --- a/python/core/auto_generated/qgsrendercontext.sip.in +++ b/python/core/auto_generated/qgsrendercontext.sip.in @@ -972,22 +972,24 @@ are drawn and behave during render operations. .. versionadded:: 3.38 %End - void addSymbolLayerClipPath( const QString &symbolLayerId, QPainterPath path ); + void addSymbolLayerClipPath( const QString &symbolLayerId, QPainterPath path ) /Deprecated/; %Docstring Add a clip ``path`` to be applied to the ``symbolLayer`` before rendering .. seealso:: :py:func:`addSymbolLayerClipGeometry` -.. versionadded:: 3.26 +.. deprecated:: + QGIS 3.38, use :py:func:`~QgsRenderContext.addSymbolLayerClipGeometry` instead. %End - QList symbolLayerClipPaths( const QString &symbolLayerId ) const; + QList symbolLayerClipPaths( const QString &symbolLayerId ) const /Deprecated/; %Docstring Returns clip paths to be applied to the ``symbolLayer`` before rendering .. seealso:: :py:func:`symbolLayerClipGeometries` -.. versionadded:: 3.26 +.. deprecated:: + QGIS 3.38, use :py:func:`~QgsRenderContext.symbolLayerClipGeometries` instead. %End void addSymbolLayerClipGeometry( const QString &symbolLayerId, const QgsGeometry &geometry ); diff --git a/src/core/maprenderer/qgsmaprendererjob.cpp b/src/core/maprenderer/qgsmaprendererjob.cpp index ce23a077596c..1b4e01357244 100644 --- a/src/core/maprenderer/qgsmaprendererjob.cpp +++ b/src/core/maprenderer/qgsmaprendererjob.cpp @@ -41,7 +41,6 @@ #include "qgsmaplayerstyle.h" #include "qgsvectorlayerrenderer.h" #include "qgsrendereditemresults.h" -#include "qgsmaskpaintdevice.h" #include "qgsgeometrypaintdevice.h" #include "qgsrasterrenderer.h" #include "qgselevationmap.h" @@ -686,8 +685,6 @@ std::vector QgsMapRendererJob::prepareJobs( QPainter *painter, Q std::vector< LayerRenderJob > QgsMapRendererJob::prepareSecondPassJobs( std::vector< LayerRenderJob > &firstPassJobs, LabelRenderJob &labelJob ) { - const bool useGeometryBackend = settingsMaskBackend->value().compare( QLatin1String( "geometry" ), Qt::CaseInsensitive ) == 0; - std::vector< LayerRenderJob > secondPassJobs; // We will need to quickly access the associated rendering job of a layer @@ -817,17 +814,10 @@ std::vector< LayerRenderJob > QgsMapRendererJob::prepareSecondPassJobs( std::vec if ( forceVector && !labelHasEffects[ maskId ] ) { // set a painter to get all masking instruction in order to later clip masked symbol layer - if ( useGeometryBackend ) - { - std::unique_ptr< QgsGeometryPaintDevice > geomPaintDevice = std::make_unique< QgsGeometryPaintDevice >( true ); - geomPaintDevice->setStrokedPathSegments( 4 ); - geomPaintDevice->setSimplificationTolerance( labelJob.context.maskSettings().simplifyTolerance() ); - maskPaintDevice = geomPaintDevice.release(); - } - else - { - maskPaintDevice = new QgsMaskPaintDevice( true ); - } + std::unique_ptr< QgsGeometryPaintDevice > geomPaintDevice = std::make_unique< QgsGeometryPaintDevice >( true ); + geomPaintDevice->setStrokedPathSegments( 4 ); + geomPaintDevice->setSimplificationTolerance( labelJob.context.maskSettings().simplifyTolerance() ); + maskPaintDevice = geomPaintDevice.release(); maskPainter = new QPainter( maskPaintDevice ); } else @@ -902,18 +892,10 @@ std::vector< LayerRenderJob > QgsMapRendererJob::prepareSecondPassJobs( std::vec if ( forceVector && !maskLayerHasEffects[ job.layerId ] ) { // set a painter to get all masking instruction in order to later clip masked symbol layer - if ( useGeometryBackend ) - { - std::unique_ptr< QgsGeometryPaintDevice > geomPaintDevice = std::make_unique< QgsGeometryPaintDevice >( ); - geomPaintDevice->setStrokedPathSegments( 4 ); - geomPaintDevice->setSimplificationTolerance( job.context()->maskSettings().simplifyTolerance() ); - maskPaintDevice = geomPaintDevice.release(); - } - else - { - maskPaintDevice = new QgsMaskPaintDevice(); - } - + std::unique_ptr< QgsGeometryPaintDevice > geomPaintDevice = std::make_unique< QgsGeometryPaintDevice >( ); + geomPaintDevice->setStrokedPathSegments( 4 ); + geomPaintDevice->setSimplificationTolerance( job.context()->maskSettings().simplifyTolerance() ); + maskPaintDevice = geomPaintDevice.release(); maskPainter = new QPainter( maskPaintDevice ); } else @@ -1018,15 +1000,7 @@ void QgsMapRendererJob::initSecondPassJobs( std::vector< LayerRenderJob > &secon QPainter *maskPainter = p.first ? p.first->maskPainter.get() : labelJob.maskPainters[p.second].get(); const QSet layers = job.context()->disabledSymbolLayersV2(); - if ( QgsMaskPaintDevice *maskDevice = dynamic_cast( maskPainter->device() ) ) - { - QPainterPath path = maskDevice->maskPainterPath(); - for ( const QString &symbolLayerId : layers ) - { - job.context()->addSymbolLayerClipPath( symbolLayerId, path ); - } - } - else if ( QgsGeometryPaintDevice *geometryDevice = dynamic_cast( maskPainter->device() ) ) + if ( QgsGeometryPaintDevice *geometryDevice = dynamic_cast( maskPainter->device() ) ) { QgsGeometry geometry( geometryDevice->geometry().clone() ); diff --git a/src/core/painting/qgsgeometrypaintdevice.cpp b/src/core/painting/qgsgeometrypaintdevice.cpp index 8c217429b5ad..18f73665d85c 100644 --- a/src/core/painting/qgsgeometrypaintdevice.cpp +++ b/src/core/painting/qgsgeometrypaintdevice.cpp @@ -611,6 +611,7 @@ void QgsGeometryPaintEngine::drawPath( const QPainterPath &path ) addSubpathGeometries( path, transform ); } + // // QgsGeometryPaintDevice // @@ -688,3 +689,12 @@ const QgsAbstractGeometry &QgsGeometryPaintDevice::geometry() const return mPaintEngine->geometry(); } +QgsGeometry QgsGeometryPaintDevice::painterPathToGeometry( const QPainterPath &path ) +{ + QgsGeometryPaintDevice device; + QPainter painter( &device ); + painter.drawPath( path ); + painter.end(); + return QgsGeometry( device.geometry().clone() ); +} + diff --git a/src/core/painting/qgsgeometrypaintdevice.h b/src/core/painting/qgsgeometrypaintdevice.h index c10666948500..9c781b38535c 100644 --- a/src/core/painting/qgsgeometrypaintdevice.h +++ b/src/core/painting/qgsgeometrypaintdevice.h @@ -19,6 +19,7 @@ #include "qgis_core.h" #include "qgis_sip.h" #include "qgsgeometrycollection.h" +#include "qgsgeometry.h" #include #include @@ -158,6 +159,13 @@ class CORE_EXPORT QgsGeometryPaintDevice: public QPaintDevice */ const QgsAbstractGeometry &geometry() const; + /** + * Converts a painter \a path to a QgsGeometry. + * + * \since QGIS 3.38.1 + */ + static QgsGeometry painterPathToGeometry( const QPainterPath &path ); + private: std::unique_ptr mPaintEngine; diff --git a/src/core/painting/qgsmaskpaintdevice.h b/src/core/painting/qgsmaskpaintdevice.h index 02e64056ed65..1486c7bb16c9 100644 --- a/src/core/painting/qgsmaskpaintdevice.h +++ b/src/core/painting/qgsmaskpaintdevice.h @@ -31,7 +31,7 @@ class QgsMaskPaintEngine: public QPaintEngine public: - QgsMaskPaintEngine( bool usePathStroker = false ); + Q_DECL_DEPRECATED QgsMaskPaintEngine( bool usePathStroker = false ); bool begin( QPaintDevice * ) override { return true; }; bool end() override { return true; }; @@ -58,7 +58,7 @@ class QgsMaskPaintEngine: public QPaintEngine * \ingroup core * \brief Mask painter device that can be used to register everything painted into a QPainterPath * used later as clip path - * \since QGIS 3.26 + * \deprecated QGIS 3.38, use QgsGeometryPaintDevice instead */ class CORE_EXPORT QgsMaskPaintDevice: public QPaintDevice { @@ -69,8 +69,9 @@ class CORE_EXPORT QgsMaskPaintDevice: public QPaintDevice * Constructor * If \a usePathStroker is TRUE, path will be considered with a stroke regarding QPainter * pen configuration + * \deprecated QGIS 3.38, use QgsGeometryPaintDevice instead */ - QgsMaskPaintDevice( bool usePathStroker = false ); + Q_DECL_DEPRECATED QgsMaskPaintDevice( bool usePathStroker = false ) SIP_DEPRECATED; QPaintEngine *paintEngine() const override; @@ -78,8 +79,10 @@ class CORE_EXPORT QgsMaskPaintDevice: public QPaintDevice /** * Returns the mask painter path painted on this paint device + * + * \deprecated Use QgsGeometryPaintDevice instead */ - QPainterPath maskPainterPath() const; + Q_DECL_DEPRECATED QPainterPath maskPainterPath() const SIP_DEPRECATED; private: diff --git a/src/core/qgsrendercontext.cpp b/src/core/qgsrendercontext.cpp index 7d01a3bf96c3..18c1bf75c619 100644 --- a/src/core/qgsrendercontext.cpp +++ b/src/core/qgsrendercontext.cpp @@ -24,6 +24,7 @@ #include "qgselevationmap.h" #include "qgsunittypes.h" #include "qgssymbollayer.h" +#include "qgsgeometrypaintdevice.h" #define POINTS_TO_MM 2.83464567 #define INCH_TO_MM 25.4 @@ -82,7 +83,6 @@ QgsRenderContext::QgsRenderContext( const QgsRenderContext &rh ) , mRendererUsage( rh.mRendererUsage ) , mFrameRate( rh.mFrameRate ) , mCurrentFrame( rh.mCurrentFrame ) - , mSymbolLayerClipPaths( rh.mSymbolLayerClipPaths ) , mSymbolLayerClippingGeometries( rh.mSymbolLayerClippingGeometries ) , mMaskRenderSettings( rh.mMaskRenderSettings ) #ifdef QGISDEBUG @@ -135,7 +135,6 @@ QgsRenderContext &QgsRenderContext::operator=( const QgsRenderContext &rh ) mRendererUsage = rh.mRendererUsage; mFrameRate = rh.mFrameRate; mCurrentFrame = rh.mCurrentFrame; - mSymbolLayerClipPaths = rh.mSymbolLayerClipPaths; mSymbolLayerClippingGeometries = rh.mSymbolLayerClippingGeometries; mMaskRenderSettings = rh.mMaskRenderSettings; if ( isTemporal() ) @@ -736,12 +735,21 @@ void QgsRenderContext::setElevationMap( QgsElevationMap *map ) void QgsRenderContext::addSymbolLayerClipPath( const QString &symbolLayerId, QPainterPath path ) { - mSymbolLayerClipPaths[ symbolLayerId ].append( path ); + const QgsGeometry geometry = QgsGeometryPaintDevice::painterPathToGeometry( path ); + if ( !geometry.isEmpty() ) + addSymbolLayerClipGeometry( symbolLayerId, geometry ); } QList QgsRenderContext::symbolLayerClipPaths( const QString &symbolLayerId ) const { - return mSymbolLayerClipPaths[ symbolLayerId ]; + const QVector geometries = symbolLayerClipGeometries( symbolLayerId ); + QList res; + res.reserve( geometries.size() ); + for ( const QgsGeometry &geometry : geometries ) + { + res << geometry.constGet()->asQPainterPath(); + } + return res; } void QgsRenderContext::addSymbolLayerClipGeometry( const QString &symbolLayerId, const QgsGeometry &geometry ) diff --git a/src/core/qgsrendercontext.h b/src/core/qgsrendercontext.h index c2eb8adacbaa..210c30bf87b5 100644 --- a/src/core/qgsrendercontext.h +++ b/src/core/qgsrendercontext.h @@ -961,17 +961,17 @@ class CORE_EXPORT QgsRenderContext : public QgsTemporalRangeObject * Add a clip \a path to be applied to the \a symbolLayer before rendering * \see addSymbolLayerClipGeometry() * - * \since QGIS 3.26, arguments changed and public API since 3.30 + * \deprecated QGIS 3.38, use addSymbolLayerClipGeometry() instead. */ - void addSymbolLayerClipPath( const QString &symbolLayerId, QPainterPath path ); + Q_DECL_DEPRECATED void addSymbolLayerClipPath( const QString &symbolLayerId, QPainterPath path ) SIP_DEPRECATED; /** * Returns clip paths to be applied to the \a symbolLayer before rendering * *\see symbolLayerClipGeometries() - * \since QGIS 3.26, arguments changed and public API since 3.30 + * \deprecated QGIS 3.38, use symbolLayerClipGeometries() instead. */ - QList symbolLayerClipPaths( const QString &symbolLayerId ) const; + Q_DECL_DEPRECATED QList symbolLayerClipPaths( const QString &symbolLayerId ) const SIP_DEPRECATED; /** * Add a clip \a geometry to be applied to the \a symbolLayer before rendering. @@ -1281,9 +1281,6 @@ class CORE_EXPORT QgsRenderContext : public QgsTemporalRangeObject double mFrameRate = -1; long long mCurrentFrame = -1; - //! clip paths to be applied to the symbol layer before rendering - QMap< QString, QList > mSymbolLayerClipPaths; - //! Clip geometries to be applied to the symbol layer before rendering QMap< QString, QVector > mSymbolLayerClippingGeometries; diff --git a/src/core/symbology/qgssymbol.cpp b/src/core/symbology/qgssymbol.cpp index 7efebe820228..1c7f909b060a 100644 --- a/src/core/symbology/qgssymbol.cpp +++ b/src/core/symbology/qgssymbol.cpp @@ -881,14 +881,11 @@ void QgsSymbol::startRender( QgsRenderContext &context, const QgsFields &fields // - we could add another special condition here to check whether the subsymbol actually does have unique // clipping paths in its symbol layers, or whether they are identical to the parent symbol layer's clipping paths. // 2. When the symbol layer type doesn't explicitly state that it's compatible with per-feature mask geometries - // 3. When the older clipping mask approach using QPainterPaths is being used. (This last condition can be - // safely removed when the older QPainterPath backend is removed.) - // 4. When per feature mask geometry is explicitly disabled for the render context + // 3. When per feature mask geometry is explicitly disabled for the render context // In other circumstances we do NOT prepare masks in advance, and instead calculate them in renderFeature(). if ( mRenderHints.testFlag( Qgis::SymbolRenderHint::IsSymbolLayerSubSymbol ) || context.testFlag( Qgis::RenderContextFlag::AlwaysUseGlobalMasks ) - || !layer->flags().testFlag( Qgis::SymbolLayerFlag::CanCalculateMaskGeometryPerFeature ) - || !context.symbolLayerClipPaths( layer->id() ).isEmpty() ) + || !layer->flags().testFlag( Qgis::SymbolLayerFlag::CanCalculateMaskGeometryPerFeature ) ) layer->prepareMasks( symbolContext ); layer->startRender( symbolContext ); } diff --git a/src/core/symbology/qgssymbollayer.cpp b/src/core/symbology/qgssymbollayer.cpp index 87eafd7b2952..7cb61d37fa37 100644 --- a/src/core/symbology/qgssymbollayer.cpp +++ b/src/core/symbology/qgssymbollayer.cpp @@ -998,26 +998,6 @@ void QgsSymbolLayer::prepareMasks( const QgsSymbolRenderContext &context ) bool foundGeometries = false; mClipPath = generateClipPath( renderContext, id(), nullptr, foundGeometries ); - if ( !foundGeometries ) - { - const QList clipPaths = renderContext.symbolLayerClipPaths( id() ); - if ( !clipPaths.isEmpty() ) - { - QPainterPath mergedPaths; - mergedPaths.setFillRule( Qt::WindingFill ); - for ( const QPainterPath &path : clipPaths ) - { - mergedPaths.addPath( path ); - } - - if ( !mergedPaths.isEmpty() ) - { - mClipPath.addRect( 0, 0, renderContext.outputSize().width(), - renderContext.outputSize().height() ); - mClipPath = mClipPath.subtracted( mergedPaths ); - } - } - } } bool QgsSymbolLayer::installMasks( QgsRenderContext &context, bool recursive, const QRectF &rect ) diff --git a/tests/code_layout/doxygen_parser.py b/tests/code_layout/doxygen_parser.py index f5a66965b1fd..d83ea3acc90c 100644 --- a/tests/code_layout/doxygen_parser.py +++ b/tests/code_layout/doxygen_parser.py @@ -64,7 +64,7 @@ def __init__(self, path, acceptable_missing={}, acceptable_missing_added_note=[] 'QgsSQLStatement::NodeUnaryOperator', 'QgsRuleBasedLabeling::Rule', 'QgsSQLStatement::Visitor'] - self.version_regex = re.compile(r'QGIS [\d\.]+.*') + self.version_regex = re.compile(r'.*QGIS\s+(?:)?[\d\.]+.*', re.MULTILINE) self.parseFiles(path) def parseFiles(self, path): @@ -257,7 +257,7 @@ def parseClassElem(self, e): # test for brief description d = e.find('briefdescription') has_brief_description = False - if d: + if d is not None: has_brief_description = True for para in d.iter('para'): if para.text and re.search(r'\btodo\b', para.text.lower()) is not None: @@ -271,9 +271,14 @@ def parseClassElem(self, e): for s in para.iter('simplesect'): if s.get('kind') == 'since': for p in s.iter('para'): - if self.version_regex.match(p.text): + if self.version_regex.match(ET.tostring(p).decode()): found_version_added = True break + for s in para.iter('xrefsect'): + if s.find('xreftitle') is not None and 'Deprecated' in s.find('xreftitle').text: + # can't have both deprecated and since, so if we've found deprecated then treat it as having satisfied the "since" requirement too + found_version_added = True + break if para.text and re.search(r'\btodo\b', para.text.lower()) is not None: noncompliant_members.append({ @@ -529,6 +534,8 @@ def isDeprecated(self, member_elem): decl_deprecated = True except: pass + if b'Q_DECL_DEPRECATED' in ET.tostring(type_elem): + decl_deprecated = True doxy_deprecated = False has_description = True diff --git a/tests/src/python/test_qgsrendercontext.py b/tests/src/python/test_qgsrendercontext.py index f5755c80bee7..43156d8ff262 100644 --- a/tests/src/python/test_qgsrendercontext.py +++ b/tests/src/python/test_qgsrendercontext.py @@ -10,7 +10,7 @@ __copyright__ = 'Copyright 2017, The QGIS Project' from qgis.PyQt.QtCore import QDateTime, QSize -from qgis.PyQt.QtGui import QImage, QPainter +from qgis.PyQt.QtGui import QImage, QPainter, QPainterPath from qgis.core import ( Qgis, QgsCoordinateReferenceSystem, @@ -811,6 +811,21 @@ def testFeatureClipGeometry(self): rc2 = QgsRenderContext(rc) self.assertEqual(rc2.featureClipGeometry().asWkt(), 'Polygon ((0 0, 1 0, 1 1, 0 1, 0 0))') + def test_deprecated_mask_methods(self): + rc = QgsRenderContext() + self.assertFalse(rc.symbolLayerClipPaths('x')) + path = QPainterPath() + path.moveTo(1, 1) + path.lineTo(1, 10) + path.lineTo(10, 10) + path.lineTo(10, 1) + path.lineTo(1, 1) + rc.addSymbolLayerClipPath('x', path) + self.assertEqual([g.asWkt() for g in rc.symbolLayerClipGeometries('x')], + ['Polygon ((1 1, 1 10, 10 10, 10 1, 1 1))']) + self.assertEqual([p.elementCount() for p in rc.symbolLayerClipPaths('x')], + [5]) + def testSetPainterFlags(self): rc = QgsRenderContext() p = QPainter() diff --git a/tests/src/python/test_selective_masking.py b/tests/src/python/test_selective_masking.py index e417e8fe5392..760a7d79504a 100644 --- a/tests/src/python/test_selective_masking.py +++ b/tests/src/python/test_selective_masking.py @@ -81,7 +81,21 @@ def renderMapToImageWithTime(mapsettings, parallel=False, cache=None): return (job.renderedImage(), job.renderingTime()) -class SelectiveMaskingTestBase(): +class TestSelectiveMasking(QgisTestCase): + + @classmethod + def control_path_prefix(cls): + return "selective_masking" + + @classmethod + def setUpClass(cls): + super(TestSelectiveMasking, cls).setUpClass() + QCoreApplication.setOrganizationName("QGIS_Test") + QCoreApplication.setOrganizationDomain("SelectiveMaskingTestBase.com") + QCoreApplication.setApplicationName("SelectiveMaskingTestBase") + QgsSettings().clear() + + start_app() def setUp(self): self.map_settings = QgsMapSettings() @@ -177,7 +191,7 @@ def check_renderings(self, map_settings, control_name): renderMapToImageWithTime(map_settings, parallel=do_parallel, cache=cache) img, t = renderMapToImageWithTime(map_settings, parallel=do_parallel, cache=cache) - suffix = "_" + self.suite_id() + ("_parallel" if do_parallel else "_sequential") + ("_cache" if use_cache else "_nocache") + suffix = ("_parallel" if do_parallel else "_sequential") + ("_cache" if use_cache else "_nocache") res = self.image_check( control_name + suffix, control_name, @@ -240,8 +254,7 @@ def check_layout_export(self, control_name, expected_nb_raster, layers=None, dpi "-png", "-r", "300", "-singlefile"]) rendered_image = QImage(image_result_filename) - suffix = "_" + self.suite_id() - res = self.image_check(control_name + suffix, + res = self.image_check(control_name, control_name, rendered_image, control_name, @@ -1376,53 +1389,5 @@ def test_markerline_masked(self): self.check_layout_export("layout_export_markerline_masked", 0, [self.polys_layer, self.lines_layer]) -class TestSelectiveMaskingQPainterPathBackend(QgisTestCase, SelectiveMaskingTestBase): - """ - Test selective masking with the QPainterPath backend - """ - @classmethod - def control_path_prefix(cls): - return "selective_masking" - - @classmethod - def suite_id(cls): - return "qpainterpath" - - @classmethod - def setUpClass(cls): - QgsSettings().setValue('map/mask-backend', 'qpainterpath') - QgisTestCase.setUpClass() - - def setUp(self): - SelectiveMaskingTestBase.setUp(self) - - -class TestSelectiveMaskingGeometryBackend(QgisTestCase, SelectiveMaskingTestBase): - """ - Test selective masking with the QgsGeometry backend - """ - @classmethod - def control_path_prefix(cls): - return "selective_masking" - - @classmethod - def suite_id(cls): - return "geometry" - - @classmethod - def setUpClass(cls): - QgsSettings().setValue('map/mask-backend', 'geometry') - QgisTestCase.setUpClass() - - def setUp(self): - SelectiveMaskingTestBase.setUp(self) - - if __name__ == '__main__': - QCoreApplication.setOrganizationName("QGIS_Test") - QCoreApplication.setOrganizationDomain("SelectiveMaskingTestBase.com") - QCoreApplication.setApplicationName("SelectiveMaskingTestBase") - QgsSettings().clear() - - start_app() unittest.main()