16#include <QQuickWindow>
17#include <QSGSimpleTextureNode>
36#include "moc_qgsquickmapcanvasmap.cpp"
41 : QQuickItem( parent )
45 connect(
this, &QQuickItem::windowChanged,
this, &QgsQuickMapCanvasMap::onWindowChanged );
46 connect( &mRefreshTimer, &QTimer::timeout,
this, [ = ] { refreshMap(); } );
47 connect( &mMapUpdateTimer, &QTimer::timeout,
this, &QgsQuickMapCanvasMap::renderJobUpdated );
57 mMapUpdateTimer.setSingleShot(
false );
58 mMapUpdateTimer.setInterval( 250 );
59 mRefreshTimer.setSingleShot(
true );
60 setTransformOrigin( QQuickItem::TopLeft );
61 setFlags( QQuickItem::ItemHasContents );
68 return mMapSettings.get();
75 QgsPoint mousePos( mMapSettings->screenToCoordinate( center ) );
77 QgsPointXY newCenter( mousePos.
x() + ( ( oldCenter.
x() - mousePos.
x() ) * scale ),
78 mousePos.
y() + ( ( oldCenter.
y() - mousePos.
y() ) * scale ) );
81 extent.
scale( scale, &newCenter );
82 mMapSettings->setExtent( extent );
87 QgsPoint start = mMapSettings->screenToCoordinate( oldPos.toPoint() );
88 QgsPoint end = mMapSettings->screenToCoordinate( newPos.toPoint() );
90 double dx = end.
x() - start.
x();
91 double dy = end.
y() - start.
y();
101 mMapSettings->setExtent( extent );
104void QgsQuickMapCanvasMap::refreshMap()
108 if ( mCacheInvalidations.testFlag( CacheInvalidationType::Temporal ) )
110 clearTemporalCache();
111 mCacheInvalidations &= ~(
static_cast< int >( CacheInvalidationType::Temporal ) );
113 if ( mCacheInvalidations.testFlag( CacheInvalidationType::Elevation ) )
115 clearElevationCache();
116 mCacheInvalidations &= ~(
static_cast< int >( CacheInvalidationType::Elevation ) );
128 QgsProject *project = mMapSettings->project();
141 mapSettings.setExpressionContext( expressionContext );
152 if ( mIncrementalRendering )
153 mMapUpdateTimer.start();
161 if ( !mSilentRefresh )
167void QgsQuickMapCanvasMap::renderJobUpdated()
184void QgsQuickMapCanvasMap::renderJobFinished()
197 delete mLabelingResults;
208 mMapUpdateTimer.stop();
217 if ( !mSilentRefresh )
223 mSilentRefresh =
false;
226 if ( mDeferredRefreshPending )
228 mDeferredRefreshPending =
false;
229 mSilentRefresh =
true;
234void QgsQuickMapCanvasMap::layerRepaintRequested(
bool deferred )
236 if ( mMapSettings->outputSize().isNull() )
245 mSilentRefresh =
true;
250 mDeferredRefreshPending =
true;
260void QgsQuickMapCanvasMap::onWindowChanged( QQuickWindow *window )
262 if ( mWindow == window )
266 disconnect( mWindow, &QQuickWindow::screenChanged,
this, &QgsQuickMapCanvasMap::onScreenChanged );
270 connect( window, &QQuickWindow::screenChanged,
this, &QgsQuickMapCanvasMap::onScreenChanged );
271 onScreenChanged( window->screen() );
277void QgsQuickMapCanvasMap::onScreenChanged( QScreen *screen )
281 if ( screen->devicePixelRatio() > 0 )
283 mMapSettings->setDevicePixelRatio( screen->devicePixelRatio() );
285 mMapSettings->setOutputDpi( screen->physicalDotsPerInch() );
289void QgsQuickMapCanvasMap::onExtentChanged()
297void QgsQuickMapCanvasMap::onTemporalStateChanged()
299 mCacheInvalidations |= CacheInvalidationType::Temporal;
305void QgsQuickMapCanvasMap::onzRangeChanged()
307 mCacheInvalidations |= CacheInvalidationType::Elevation;
313void QgsQuickMapCanvasMap::updateTransform()
316 QgsRectangle newExtent = mMapSettings->mapSettings().visibleExtent();
317 setScale( imageExtent.
width() / newExtent.
width() );
326 return mMapUpdateTimer.interval();
341 return mIncrementalRendering;
387 if ( mImage.isNull() )
392 QSGSimpleTextureNode *node =
static_cast<QSGSimpleTextureNode *
>( oldNode );
395 node =
new QSGSimpleTextureNode();
396 QSGTexture *texture = window()->createTextureFromImage( mImage );
397 node->setTexture( texture );
398 node->setOwnsTexture(
true );
401 QRectF rect( boundingRect() );
402 QSizeF size = mImage.size();
403 if ( !size.isEmpty() )
404 size /= mMapSettings->devicePixelRatio();
407 if ( !rect.isEmpty() && !size.isEmpty() && !
qgsDoubleNear( rect.width() / rect.height(), ( size.width() ) /
static_cast<double>( size.height() ), 3 ) )
411 rect.setHeight( rect.width() / size.width() * size.height() );
415 rect.setWidth( rect.height() / size.height() * size.width() );
419 node->setRect( rect );
424#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
425void QgsQuickMapCanvasMap::geometryChanged(
const QRectF &newGeometry,
const QRectF &oldGeometry )
427 QQuickItem::geometryChanged( newGeometry, oldGeometry );
431 QQuickItem::geometryChange( newGeometry, oldGeometry );
433 if ( newGeometry.size() != oldGeometry.size() )
435 mMapSettings->setOutputSize( newGeometry.size().toSize() );
440void QgsQuickMapCanvasMap::onLayersChanged()
442 if ( mMapSettings->extent().isEmpty() )
445 for (
const QMetaObject::Connection &conn : std::as_const( mLayerConnections ) )
449 mLayerConnections.clear();
451 const QList<QgsMapLayer *> layers = mMapSettings->layers();
478void QgsQuickMapCanvasMap::zoomToFullExtent()
481 const QList<QgsMapLayer *> layers = mMapSettings->layers();
484 if ( mMapSettings->destinationCrs() != layer->crs() )
486 QgsCoordinateTransform transform( layer->crs(), mMapSettings->destinationCrs(), mMapSettings->transformContext() );
501 mMapSettings->setExtent( extent );
508 if ( mMapSettings->outputSize().isNull() )
512 mRefreshTimer.start( 1 );
521void QgsQuickMapCanvasMap::clearTemporalCache()
525 bool invalidateLabels =
false;
526 const QList<QgsMapLayer *> layerList = mMapSettings->mapSettings().layers();
529 bool alreadyInvalidatedThisLayer =
false;
530 if (
QgsVectorLayer *vl = qobject_cast< QgsVectorLayer * >( layer ) )
536 mCache->invalidateCacheForLayer( layer );
537 alreadyInvalidatedThisLayer =
true;
543 if ( layer->temporalProperties() && layer->temporalProperties()->isActive() )
545 if (
QgsVectorLayer *vl = qobject_cast< QgsVectorLayer * >( layer ) )
547 if ( vl->labelsEnabled() || vl->diagramsEnabled() )
548 invalidateLabels =
true;
554 if ( !alreadyInvalidatedThisLayer )
555 mCache->invalidateCacheForLayer( layer );
557 else if (
QgsGroupLayer *gl = qobject_cast<QgsGroupLayer *>( layer ) )
559 const QList<QgsMapLayer *> childLayerList = gl->childLayers();
562 if ( childLayer->temporalProperties() && childLayer->temporalProperties()->isActive() )
567 mCache->invalidateCacheForLayer( layer );
574 if ( invalidateLabels )
576 mCache->clearCacheImage( QStringLiteral(
"_labels_" ) );
577 mCache->clearCacheImage( QStringLiteral(
"_preview_labels_" ) );
582void QgsQuickMapCanvasMap::clearElevationCache()
586 bool invalidateLabels =
false;
587 const QList<QgsMapLayer *> layerList = mMapSettings->mapSettings().layers();
590 if ( layer->elevationProperties() && layer->elevationProperties()->hasElevation() )
592 if (
QgsVectorLayer *vl = qobject_cast< QgsVectorLayer * >( layer ) )
594 if ( vl->labelsEnabled() || vl->diagramsEnabled() )
595 invalidateLabels =
true;
601 mCache->invalidateCacheForLayer( layer );
603 else if (
QgsGroupLayer *gl = qobject_cast<QgsGroupLayer *>( layer ) )
605 const QList<QgsMapLayer *> childLayerList = gl->childLayers();
608 if ( childLayer->elevationProperties() && childLayer->elevationProperties()->hasElevation() )
613 mCache->invalidateCacheForLayer( layer );
620 if ( invalidateLabels )
622 mCache->clearCacheImage( QStringLiteral(
"_labels_" ) );
623 mCache->clearCacheImage( QStringLiteral(
"_preview_labels_" ) );
@ UseRenderingOptimization
Enable vector simplification and other rendering optimizations.
@ RenderPartialOutput
Whether to make extra effort to update map image with partially rendered layers (better for interacti...
Custom exception class for Coordinate Reference System related exceptions.
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
static QgsExpressionContextScope * mapSettingsScope(const QgsMapSettings &mapSettings)
Creates a new scope which contains variables and functions relating to a QgsMapSettings object.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
A map layer which consists of a set of child layers, where all component layers are rendered as a sin...
@ FlagDontInvalidateCachedRendersWhenRangeChanges
Any cached rendering will not be invalidated when z range context is modified.
Base class for all map layer types.
void repaintRequested(bool deferredUpdate=false)
By emitting this signal the layer tells that either appearance or content have been changed and any v...
This class is responsible for keeping cache of rendered images resulting from a map rendering job.
Abstract base class for map rendering implementations.
void setCache(QgsMapRendererCache *cache)
Assign a cache to be used for reading and storing rendered images of individual layers.
Errors errors() const
List of errors that happened during the rendering job - available when the rendering has been finishe...
void renderingLayersFinished()
Emitted when the layers are rendered.
const QgsMapSettings & mapSettings() const
Returns map settings with which this job was started.
void finished()
emitted when asynchronous rendering is finished (or canceled).
void start()
Start the rendering job and immediately return.
QList< QgsMapRendererJob::Error > Errors
virtual void cancel()=0
Stop the rendering job - does not return until the job has terminated.
Job implementation that renders all layers in parallel.
QgsLabelingResults * takeLabelingResults() override
Gets pointer to internal labeling engine (in order to get access to the results).
void cancelWithoutBlocking() override
Triggers cancellation of the rendering job without blocking.
QImage renderedImage() override
Gets a preview/resulting image.
The QgsMapSettings class contains configuration for rendering of the map.
QgsRectangle visibleExtent() const
Returns the actual extent derived from requested extent that takes output image size into account.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
A class to represent a 2D point.
Point geometry type, with support for z-dimension and m-values.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
QgsAnnotationLayer * mainAnnotationLayer()
Returns the main annotation layer associated with the project.
const QgsLabelingEngineSettings & labelingEngineSettings() const
Returns project's global labeling engine settings.
void freezeChanged()
When freeze property is set to true, the map canvas does not refresh.
bool isRendering
The isRendering property is set to true while a rendering job is pending for this map canvas map.
void mapCanvasRefreshed()
Signal is emitted when a canvas is refreshed.
void incrementalRenderingChanged()
When the incrementalRendering property is set to true, the automatic refresh of map canvas during ren...
int mapUpdateInterval
Interval in milliseconds after which the map canvas will be updated while a rendering job is ongoing.
void setMapUpdateInterval(int mapUpdateInterval)
Interval in milliseconds after which the map canvas will be updated while a rendering job is ongoing.
void pan(QPointF oldPos, QPointF newPos)
Set map setting's extent (pan the map) based on the difference of positions.
void renderStarting()
Signal is emitted when a rendering is starting.
void stopRendering()
Stop map rendering.
void zoom(QPointF center, qreal scale)
Set map setting's extent (zoom the map) on the center by given scale.
void setIncrementalRendering(bool incrementalRendering)
When the incrementalRendering property is set to true, the automatic refresh of map canvas during ren...
void clearCache()
Clears rendering cache.
void setFreeze(bool freeze)
When freeze property is set to true, the map canvas does not refresh.
QgsQuickMapSettings * mapSettings
The mapSettings property contains configuration for rendering of the map.
void refresh()
Refresh the map canvas.
QSGNode * updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *) override
void mapUpdateIntervalChanged()
Interval in milliseconds after which the map canvas will be updated while a rendering job is ongoing.
bool incrementalRendering
When the incrementalRendering property is set to true, the automatic refresh of map canvas during ren...
bool freeze
When freeze property is set to true, the map canvas does not refresh.
void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override
QgsQuickMapCanvasMap(QQuickItem *parent=nullptr)
Create map canvas map.
void isRenderingChanged()
The isRendering property is set to true while a rendering job is pending for this map canvas map.
The QgsQuickMapSettings class encapsulates QgsMapSettings class to offer settings of configuration of...
void extentChanged()
Geographical coordinates of the rectangle that should be rendered.
void layersChanged()
Set list of layers for map rendering.
void temporalStateChanged()
Emitted when the temporal state has changed.
void setLayers(const QList< QgsMapLayer * > &layers)
Sets the list of layers to render in the map.
QList< QgsMapLayer * > layers
Set list of layers for map rendering.
void zRangeChanged()
Emitted when the Z range has changed.
A rectangle specified with double values.
void scale(double scaleFactor, const QgsPointXY *c=nullptr)
Scale the rectangle around its center point.
void setYMinimum(double y)
Set the minimum y value.
void setXMinimum(double x)
Set the minimum x value.
void setYMaximum(double y)
Set the maximum y value.
void setXMaximum(double x)
Set the maximum x value.
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle.
static double rendererFrameRate(const QgsFeatureRenderer *renderer)
Calculates the frame rate (in frames per second) at which the given renderer must be redrawn.
@ FlagDontInvalidateCachedRendersWhenRangeChanges
Any cached rendering will not be invalidated when temporal range context is modified.
Represents a vector layer which manages a vector based data sets.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)