34#include <QQuickWindow>
35#include <QSGSimpleTextureNode>
38#include "moc_qgsquickmapcanvasmap.cpp"
41 : QQuickItem( parent )
45 connect(
this, &QQuickItem::windowChanged,
this, &QgsQuickMapCanvasMap::onWindowChanged );
46 connect( &mRefreshTimer, &QTimer::timeout,
this, [
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 ), mousePos.
y() + ( ( oldCenter.
y() - mousePos.
y() ) * scale ) );
80 extent.
scale( scale, &newCenter );
81 mMapSettings->setExtent( extent );
86 QgsPoint start = mMapSettings->screenToCoordinate( oldPos.toPoint() );
87 QgsPoint end = mMapSettings->screenToCoordinate( newPos.toPoint() );
89 double dx = end.
x() - start.
x();
90 double dy = end.
y() - start.
y();
100 mMapSettings->setExtent( extent );
103void QgsQuickMapCanvasMap::refreshMap()
107 if ( mCacheInvalidations.testFlag( CacheInvalidationType::Temporal ) )
109 clearTemporalCache();
110 mCacheInvalidations &= ~(
static_cast<int>( CacheInvalidationType::Temporal ) );
112 if ( mCacheInvalidations.testFlag( CacheInvalidationType::Elevation ) )
114 clearElevationCache();
115 mCacheInvalidations &= ~(
static_cast<int>( CacheInvalidationType::Elevation ) );
118 QgsMapSettings
mapSettings = mMapSettings->mapSettings();
123 QgsExpressionContext expressionContext;
127 QgsProject *project = mMapSettings->project();
135 QList<QgsMapLayer *> allLayers =
mapSettings.layers();
140 mapSettings.setExpressionContext( expressionContext );
149 mJob =
new QgsMapRendererParallelJob(
mapSettings );
151 if ( mIncrementalRendering )
152 mMapUpdateTimer.start();
156 mJob->setCache( mCache.get() );
160 if ( !mSilentRefresh )
166void QgsQuickMapCanvasMap::renderJobUpdated()
171 mImage = mJob->renderedImage();
172 mImageMapSettings = mJob->mapSettings();
183void QgsQuickMapCanvasMap::renderJobFinished()
189 for (
const QgsMapRendererJob::Error &error : errors )
196 delete mLabelingResults;
197 mLabelingResults = mJob->takeLabelingResults();
199 mImage = mJob->renderedImage();
200 mImageMapSettings = mJob->mapSettings();
207 mMapUpdateTimer.stop();
216 if ( !mSilentRefresh )
222 mSilentRefresh =
false;
225 if ( mDeferredRefreshPending )
227 mDeferredRefreshPending =
false;
228 mSilentRefresh =
true;
233void QgsQuickMapCanvasMap::layerRepaintRequested(
bool deferred )
235 if ( mMapSettings->outputSize().isNull() )
244 mSilentRefresh =
true;
249 mDeferredRefreshPending =
true;
259void QgsQuickMapCanvasMap::onWindowChanged( QQuickWindow *window )
261 if ( mWindow == window )
265 disconnect( mWindow, &QQuickWindow::screenChanged,
this, &QgsQuickMapCanvasMap::onScreenChanged );
269 connect( window, &QQuickWindow::screenChanged,
this, &QgsQuickMapCanvasMap::onScreenChanged );
270 onScreenChanged( window->screen() );
276void QgsQuickMapCanvasMap::onScreenChanged( QScreen *screen )
280 if ( screen->devicePixelRatio() > 0 )
282 mMapSettings->setDevicePixelRatio( screen->devicePixelRatio() );
284 mMapSettings->setOutputDpi( screen->physicalDotsPerInch() );
288void QgsQuickMapCanvasMap::onExtentChanged()
296void QgsQuickMapCanvasMap::onTemporalStateChanged()
298 mCacheInvalidations |= CacheInvalidationType::Temporal;
304void QgsQuickMapCanvasMap::onzRangeChanged()
306 mCacheInvalidations |= CacheInvalidationType::Elevation;
312void QgsQuickMapCanvasMap::updateTransform()
314 QgsRectangle imageExtent = mImageMapSettings.visibleExtent();
315 QgsRectangle newExtent = mMapSettings->mapSettings().visibleExtent();
316 setScale( imageExtent.
width() / newExtent.
width() );
318 QgsPointXY pixelPt = mMapSettings->coordinateToScreen( QgsPoint( imageExtent.
xMinimum(), imageExtent.
yMaximum() ) );
325 return mMapUpdateTimer.interval();
340 return mIncrementalRendering;
386 if ( mImage.isNull() )
391 QSGSimpleTextureNode *node =
static_cast<QSGSimpleTextureNode *
>( oldNode );
394 node =
new QSGSimpleTextureNode();
395 QSGTexture *texture = window()->createTextureFromImage( mImage );
396 node->setTexture( texture );
397 node->setOwnsTexture(
true );
400 QRectF rect( boundingRect() );
401 QSizeF size = mImage.size();
402 if ( !size.isEmpty() )
403 size /= mMapSettings->devicePixelRatio();
406 if ( !rect.isEmpty() && !size.isEmpty() && !
qgsDoubleNear( rect.width() / rect.height(), ( size.width() ) /
static_cast<double>( size.height() ), 3 ) )
410 rect.setHeight( rect.width() / size.width() * size.height() );
414 rect.setWidth( rect.height() / size.height() * size.width() );
418 node->setRect( rect );
423#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
424void QgsQuickMapCanvasMap::geometryChanged(
const QRectF &newGeometry,
const QRectF &oldGeometry )
426 QQuickItem::geometryChanged( newGeometry, oldGeometry );
430 QQuickItem::geometryChange( newGeometry, oldGeometry );
432 if ( newGeometry.size() != oldGeometry.size() )
434 mMapSettings->setOutputSize( newGeometry.size().toSize() );
439void QgsQuickMapCanvasMap::onLayersChanged()
441 if ( mMapSettings->extent().isEmpty() )
444 for (
const QMetaObject::Connection &conn : std::as_const( mLayerConnections ) )
448 mLayerConnections.clear();
450 const QList<QgsMapLayer *> layers = mMapSettings->layers();
451 for ( QgsMapLayer *layer : layers )
459void QgsQuickMapCanvasMap::destroyJob( QgsMapRendererJob *job )
472 mJob->cancelWithoutBlocking();
477void QgsQuickMapCanvasMap::zoomToFullExtent()
480 const QList<QgsMapLayer *> layers = mMapSettings->layers();
483 if ( mMapSettings->destinationCrs() != layer->crs() )
485 QgsCoordinateTransform transform( layer->crs(), mMapSettings->destinationCrs(), mMapSettings->transformContext() );
490 catch (
const QgsCsException &exp )
500 mMapSettings->setExtent( extent );
507 if ( mMapSettings->outputSize().isNull() )
511 mRefreshTimer.start( 1 );
520void QgsQuickMapCanvasMap::clearTemporalCache()
524 bool invalidateLabels =
false;
525 const QList<QgsMapLayer *> layerList = mMapSettings->mapSettings().layers();
528 bool alreadyInvalidatedThisLayer =
false;
529 if (
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer ) )
535 mCache->invalidateCacheForLayer( layer );
536 alreadyInvalidatedThisLayer =
true;
542 if ( layer->temporalProperties() && layer->temporalProperties()->isActive() )
544 if ( QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer ) )
546 if ( vl->labelsEnabled() || vl->diagramsEnabled() )
547 invalidateLabels =
true;
553 if ( !alreadyInvalidatedThisLayer )
554 mCache->invalidateCacheForLayer( layer );
556 else if ( QgsGroupLayer *gl = qobject_cast<QgsGroupLayer *>( layer ) )
558 const QList<QgsMapLayer *> childLayerList = gl->childLayers();
559 for ( QgsMapLayer *childLayer : childLayerList )
561 if ( childLayer->temporalProperties() && childLayer->temporalProperties()->isActive() )
566 mCache->invalidateCacheForLayer( layer );
573 if ( invalidateLabels )
575 mCache->clearCacheImage( QStringLiteral(
"_labels_" ) );
576 mCache->clearCacheImage( QStringLiteral(
"_preview_labels_" ) );
581void QgsQuickMapCanvasMap::clearElevationCache()
585 bool invalidateLabels =
false;
586 const QList<QgsMapLayer *> layerList = mMapSettings->mapSettings().layers();
587 for ( QgsMapLayer *layer : layerList )
589 if ( layer->elevationProperties() && layer->elevationProperties()->hasElevation() )
591 if ( QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer ) )
593 if ( vl->labelsEnabled() || vl->diagramsEnabled() )
594 invalidateLabels =
true;
600 mCache->invalidateCacheForLayer( layer );
602 else if ( QgsGroupLayer *gl = qobject_cast<QgsGroupLayer *>( layer ) )
604 const QList<QgsMapLayer *> childLayerList = gl->childLayers();
605 for ( QgsMapLayer *childLayer : childLayerList )
607 if ( childLayer->elevationProperties() && childLayer->elevationProperties()->hasElevation() )
612 mCache->invalidateCacheForLayer( layer );
619 if ( invalidateLabels )
621 mCache->clearCacheImage( QStringLiteral(
"_labels_" ) );
622 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...
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.
@ 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...
Responsible for keeping a cache of rendered images resulting from a map rendering job.
void renderingLayersFinished()
Emitted when the layers are rendered.
void finished()
emitted when asynchronous rendering is finished (or canceled).
QList< QgsMapRendererJob::Error > Errors
virtual void cancel()=0
Stop the rendering job - does not return until the job has terminated.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
Adds a message to the log instance (and creates it if necessary).
Point geometry type, with support for z-dimension and m-values.
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.
Encapsulates QgsMapSettings class to offer settings of configuration of map rendering via QML propert...
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 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 dataset.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).