From a3bfee052dff31868de0aea73674eb90a7f3ed7e Mon Sep 17 00:00:00 2001 From: Mathieu Pellerin Date: Tue, 12 Mar 2024 09:43:19 +0700 Subject: [PATCH 1/2] [quick] Add Z range support to map canvas / map settings items --- src/quickgui/qgsquickmapcanvasmap.cpp | 56 +++++++++++++++++++++++++++ src/quickgui/qgsquickmapcanvasmap.h | 2 + src/quickgui/qgsquickmapsettings.cpp | 37 ++++++++++++++++++ src/quickgui/qgsquickmapsettings.h | 30 ++++++++++++++ 4 files changed, 125 insertions(+) diff --git a/src/quickgui/qgsquickmapcanvasmap.cpp b/src/quickgui/qgsquickmapcanvasmap.cpp index e258c8484c52..472c00c06eb0 100644 --- a/src/quickgui/qgsquickmapcanvasmap.cpp +++ b/src/quickgui/qgsquickmapcanvasmap.cpp @@ -19,6 +19,8 @@ #include "qgis.h" #include "qgsexpressioncontextutils.h" +#include "qgsgrouplayer.h" +#include "qgsmaplayerelevationproperties.h" #include "qgsmaplayertemporalproperties.h" #include "qgsmaprenderercache.h" #include "qgsmaprendererparalleljob.h" @@ -45,6 +47,7 @@ QgsQuickMapCanvasMap::QgsQuickMapCanvasMap( QQuickItem *parent ) connect( mMapSettings.get(), &QgsQuickMapSettings::extentChanged, this, &QgsQuickMapCanvasMap::onExtentChanged ); connect( mMapSettings.get(), &QgsQuickMapSettings::layersChanged, this, &QgsQuickMapCanvasMap::onLayersChanged ); connect( mMapSettings.get(), &QgsQuickMapSettings::temporalStateChanged, this, &QgsQuickMapCanvasMap::onTemporalStateChanged ); + connect( mMapSettings.get(), &QgsQuickMapSettings::zRangeChanged, this, &QgsQuickMapCanvasMap::onzRangeChanged ); connect( this, &QgsQuickMapCanvasMap::renderStarting, this, &QgsQuickMapCanvasMap::isRenderingChanged ); connect( this, &QgsQuickMapCanvasMap::mapCanvasRefreshed, this, &QgsQuickMapCanvasMap::isRenderingChanged ); @@ -286,6 +289,14 @@ void QgsQuickMapCanvasMap::onTemporalStateChanged() refresh(); } +void QgsQuickMapCanvasMap::onzRangeChanged() +{ + clearElevationCache(); + + // And trigger a new rendering job + refresh(); +} + void QgsQuickMapCanvasMap::updateTransform() { QgsRectangle imageExtent = mImageMapSettings.visibleExtent(); @@ -525,3 +536,48 @@ void QgsQuickMapCanvasMap::clearTemporalCache() } } +void QgsQuickMapCanvasMap::clearElevationCache() +{ + if ( mCache ) + { + bool invalidateLabels = false; + const QList layerList = mMapSettings->mapSettings().layers(); + for ( QgsMapLayer *layer : layerList ) + { + if ( layer->elevationProperties() && layer->elevationProperties()->hasElevation() ) + { + if ( QgsVectorLayer *vl = qobject_cast< QgsVectorLayer * >( layer ) ) + { + if ( vl->labelsEnabled() || vl->diagramsEnabled() ) + invalidateLabels = true; + } + + if ( layer->elevationProperties()->flags() & QgsMapLayerElevationProperties::FlagDontInvalidateCachedRendersWhenRangeChanges ) + continue; + + mCache->invalidateCacheForLayer( layer ); + } + else if ( QgsGroupLayer *gl = qobject_cast( layer ) ) + { + const QList childLayerList = gl->childLayers(); + for ( QgsMapLayer *childLayer : childLayerList ) + { + if ( childLayer->elevationProperties() && childLayer->elevationProperties()->hasElevation() ) + { + if ( childLayer->elevationProperties()->flags() & QgsMapLayerElevationProperties::FlagDontInvalidateCachedRendersWhenRangeChanges ) + continue; + + mCache->invalidateCacheForLayer( layer ); + break; + } + } + } + } + + if ( invalidateLabels ) + { + mCache->clearCacheImage( QStringLiteral( "_labels_" ) ); + mCache->clearCacheImage( QStringLiteral( "_preview_labels_" ) ); + } + } +} diff --git a/src/quickgui/qgsquickmapcanvasmap.h b/src/quickgui/qgsquickmapcanvasmap.h index f1399b704856..0789c5bded33 100644 --- a/src/quickgui/qgsquickmapcanvasmap.h +++ b/src/quickgui/qgsquickmapcanvasmap.h @@ -185,6 +185,7 @@ class QUICK_EXPORT QgsQuickMapCanvasMap : public QQuickItem void onExtentChanged(); void onLayersChanged(); void onTemporalStateChanged(); + void onzRangeChanged(); private: @@ -196,6 +197,7 @@ class QUICK_EXPORT QgsQuickMapCanvasMap : public QQuickItem void updateTransform(); void zoomToFullExtent(); void clearTemporalCache(); + void clearElevationCache(); std::unique_ptr mMapSettings; bool mPinching = false; diff --git a/src/quickgui/qgsquickmapsettings.cpp b/src/quickgui/qgsquickmapsettings.cpp index 8ac27722930a..2f79cafef01d 100644 --- a/src/quickgui/qgsquickmapsettings.cpp +++ b/src/quickgui/qgsquickmapsettings.cpp @@ -272,6 +272,7 @@ void QgsQuickMapSettings::onReadProject( const QDomDocument &doc ) emit outputDpiChanged(); emit layersChanged(); emit temporalStateChanged(); + emit zRangeChanged(); } double QgsQuickMapSettings::rotation() const @@ -344,3 +345,39 @@ void QgsQuickMapSettings::setTemporalEnd( const QDateTime &end ) mMapSettings.setTemporalRange( QgsDateTimeRange( range.begin(), end ) ); emit temporalStateChanged(); } + +double QgsQuickMapSettings::zRangeLower() const +{ + const QgsDoubleRange zRange = mMapSettings.zRange(); + return zRange.lower(); +} + +void QgsQuickMapSettings::setZRangeLower( const double &lower ) +{ + const QgsDoubleRange zRange = mMapSettings.zRange(); + if ( zRange.lower() == lower ) + { + return; + } + + mMapSettings.setZRange( QgsDoubleRange( lower, zRange.upper(), zRange.includeLower(), zRange.includeUpper() ) ); + emit zRangeChanged(); +} + +double QgsQuickMapSettings::zRangeUpper() const +{ + const QgsDoubleRange zRange = mMapSettings.zRange(); + return zRange.upper(); +} + +void QgsQuickMapSettings::setZRangeUpper( const double &upper ) +{ + const QgsDoubleRange zRange = mMapSettings.zRange(); + if ( zRange.upper() == upper ) + { + return; + } + + mMapSettings.setZRange( QgsDoubleRange( zRange.lower(), upper, zRange.includeLower(), zRange.includeUpper() ) ); + emit zRangeChanged(); +} diff --git a/src/quickgui/qgsquickmapsettings.h b/src/quickgui/qgsquickmapsettings.h index f51227ab21e2..78b795f956d7 100644 --- a/src/quickgui/qgsquickmapsettings.h +++ b/src/quickgui/qgsquickmapsettings.h @@ -135,6 +135,16 @@ class QUICK_EXPORT QgsQuickMapSettings : public QObject */ Q_PROPERTY( QDateTime temporalEnd READ temporalEnd WRITE setTemporalEnd NOTIFY temporalStateChanged ) + /** + * The Z range's lower value (since QGIS 3.38) + */ + Q_PROPERTY( double zRangeLower READ zRangeLower WRITE setZRangeLower NOTIFY zRangeChanged ) + + /** + * The Z range's upper value (since QGIS 3.38) + */ + Q_PROPERTY( double zRangeUpper READ zRangeUpper WRITE setZRangeUpper NOTIFY zRangeChanged ) + public: //! Create new map settings explicit QgsQuickMapSettings( QObject *parent = nullptr ); @@ -288,6 +298,18 @@ class QUICK_EXPORT QgsQuickMapSettings : public QObject //! \copydoc QgsQuickMapSettings::temporalEnd void setTemporalEnd( const QDateTime &end ); + //! \copydoc QgsQuickMapSettings::zRangeLower + double zRangeLower() const; + + //! \copydoc QgsQuickMapSettings::zRangeLower + void setZRangeLower( const double &lower ); + + //! \copydoc QgsQuickMapSettings::zRangeLower + double zRangeUpper() const; + + //! \copydoc QgsQuickMapSettings::zRangeLower + void setZRangeUpper( const double &upper ); + signals: //! \copydoc QgsQuickMapSettings::project void projectChanged(); @@ -329,6 +351,14 @@ class QUICK_EXPORT QgsQuickMapSettings : public QObject */ void temporalStateChanged(); + /** + * Emitted when the Z range has changed. + * \see zRangeLower() + * \see zRangeUpper() + * \since QGIS 3.38 + */ + void zRangeChanged(); + //! \copydoc QgsQuickMapSettings::devicePixelRatio void devicePixelRatioChanged(); From d8eaf061abc20425f7a48640d86802be73b798b1 Mon Sep 17 00:00:00 2001 From: Mathieu Pellerin Date: Tue, 12 Mar 2024 09:44:49 +0700 Subject: [PATCH 2/2] [quick] Insure that group layers with temporal children are invalidated when needed --- src/quickgui/qgsquickmapcanvasmap.cpp | 39 ++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/src/quickgui/qgsquickmapcanvasmap.cpp b/src/quickgui/qgsquickmapcanvasmap.cpp index 472c00c06eb0..9bf5e2cd37c0 100644 --- a/src/quickgui/qgsquickmapcanvasmap.cpp +++ b/src/quickgui/qgsquickmapcanvasmap.cpp @@ -18,8 +18,10 @@ #include #include "qgis.h" +#include "qgsannotationlayer.h" #include "qgsexpressioncontextutils.h" #include "qgsgrouplayer.h" +#include "qgslabelingresults.h" #include "qgsmaplayerelevationproperties.h" #include "qgsmaplayertemporalproperties.h" #include "qgsmaprenderercache.h" @@ -27,9 +29,8 @@ #include "qgsmessagelog.h" #include "qgspallabeling.h" #include "qgsproject.h" -#include "qgsannotationlayer.h" +#include "qgssymbollayerutils.h" #include "qgsvectorlayer.h" -#include "qgslabelingresults.h" #include "qgsquickmapcanvasmap.h" #include "qgsquickmapsettings.h" @@ -513,9 +514,23 @@ void QgsQuickMapCanvasMap::clearTemporalCache() const QList layerList = mMapSettings->mapSettings().layers(); for ( QgsMapLayer *layer : layerList ) { + bool alreadyInvalidatedThisLayer = false; + if ( QgsVectorLayer *vl = qobject_cast< QgsVectorLayer * >( layer ) ) + { + if ( vl->renderer() && QgsSymbolLayerUtils::rendererFrameRate( vl->renderer() ) > -1 ) + { + // layer has an animated symbol assigned, so we have to redraw it regardless of whether + // or not it has temporal settings + mCache->invalidateCacheForLayer( layer ); + alreadyInvalidatedThisLayer = true; + // we can't shortcut and "continue" here, as we still need to check whether the layer + // will cause label invalidation using the logic below + } + } + if ( layer->temporalProperties() && layer->temporalProperties()->isActive() ) { - if ( QgsVectorLayer *vl = qobject_cast( layer ) ) + if ( QgsVectorLayer *vl = qobject_cast< QgsVectorLayer * >( layer ) ) { if ( vl->labelsEnabled() || vl->diagramsEnabled() ) invalidateLabels = true; @@ -524,7 +539,23 @@ void QgsQuickMapCanvasMap::clearTemporalCache() if ( layer->temporalProperties()->flags() & QgsTemporalProperty::FlagDontInvalidateCachedRendersWhenRangeChanges ) continue; - mCache->invalidateCacheForLayer( layer ); + if ( !alreadyInvalidatedThisLayer ) + mCache->invalidateCacheForLayer( layer ); + } + else if ( QgsGroupLayer *gl = qobject_cast( layer ) ) + { + const QList childLayerList = gl->childLayers(); + for ( QgsMapLayer *childLayer : childLayerList ) + { + if ( childLayer->temporalProperties() && childLayer->temporalProperties()->isActive() ) + { + if ( childLayer->temporalProperties()->flags() & QgsTemporalProperty::FlagDontInvalidateCachedRendersWhenRangeChanges ) + continue; + + mCache->invalidateCacheForLayer( layer ); + break; + } + } } }