Skip to content

Commit

Permalink
Ensure correct crs is available for QgsMapCanvas for slots connected
Browse files Browse the repository at this point in the history
to extentsChanged when canvas CRS is changed

Fixes #51833
  • Loading branch information
nyalldawson committed Feb 17, 2023
1 parent 71b5d7d commit 11d34a2
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 9 deletions.
7 changes: 7 additions & 0 deletions python/gui/auto_generated/qgsmapcanvas.sip.in
Expand Up @@ -1347,6 +1347,13 @@ called when panning is in action, reset indicates end of panning
virtual void showEvent( QShowEvent *event );


void emitExtentsChanged();
%Docstring
Emits the extentsChanged signal when appropriate.

.. versionadded:: 3.30
%End




Expand Down
36 changes: 27 additions & 9 deletions src/gui/qgsmapcanvas.cpp
Expand Up @@ -513,6 +513,12 @@ void QgsMapCanvas::setDestinationCrs( const QgsCoordinateReferenceSystem &crs )
}
}

// defer extent and scale changed signals until we've correctly
// set the destination crs, otherwise slots which connect to these signals
// may retrieve an outdated CRS for the map canvas
mBlockExtentChangedSignal++;
mBlockScaleChangedSignal++;

if ( !rect.isEmpty() )
{
// we will be manually calling updateCanvasItemPositions() later, AFTER setting the updating the mSettings destination CRS, and we don't
Expand All @@ -522,8 +528,13 @@ void QgsMapCanvas::setDestinationCrs( const QgsCoordinateReferenceSystem &crs )
mBlockItemPositionUpdates--;
}

mBlockExtentChangedSignal--;
mBlockScaleChangedSignal--;

mSettings.setDestinationCrs( crs );
updateScale();
emitExtentsChanged();

updateCanvasItemPositions();

QgsDebugMsgLevel( QStringLiteral( "refreshing after destination CRS changed" ), 2 );
Expand Down Expand Up @@ -1426,6 +1437,7 @@ void QgsMapCanvas::setExtent( const QgsRectangle &r, bool magnified )

// ### QGIS 3: do not allow empty extent - require users to call setCenter() explicitly
QgsDebugMsgLevel( QStringLiteral( "Empty extent - keeping old scale with new center!" ), 2 );

setCenter( r.center() );
}
else
Expand All @@ -1448,7 +1460,7 @@ void QgsMapCanvas::setExtent( const QgsRectangle &r, bool magnified )
mSettings.setExtent( r, magnified );
}
}
emit extentsChanged();
emitExtentsChanged();
updateScale();

//clear all extent items after current index
Expand Down Expand Up @@ -1524,7 +1536,7 @@ QgsPointXY QgsMapCanvas::cursorPoint() const
double QgsMapCanvas::rotation() const
{
return mapSettings().rotation();
} // rotation
}

void QgsMapCanvas::setRotation( double degrees )
{
Expand All @@ -1535,13 +1547,13 @@ void QgsMapCanvas::setRotation( double degrees )

mSettings.setRotation( degrees );
emit rotationChanged( degrees );
emit extentsChanged(); // visible extent changes with rotation
} // setRotation

emitExtentsChanged(); // visible extent changes with rotation
}

void QgsMapCanvas::updateScale()
{
emit scaleChanged( mapSettings().scale() );
if ( !mBlockScaleChangedSignal )
emit scaleChanged( mapSettings().scale() );
}

void QgsMapCanvas::zoomToFullExtent()
Expand Down Expand Up @@ -1577,7 +1589,7 @@ void QgsMapCanvas::zoomToPreviousExtent()
{
mLastExtentIndex--;
mSettings.setExtent( mLastExtent[mLastExtentIndex] );
emit extentsChanged();
emitExtentsChanged();
updateScale();
refresh();
// update controls' enabled state
Expand All @@ -1593,7 +1605,7 @@ void QgsMapCanvas::zoomToNextExtent()
{
mLastExtentIndex++;
mSettings.setExtent( mLastExtent[mLastExtentIndex] );
emit extentsChanged();
emitExtentsChanged();
updateScale();
refresh();
// update controls' enabled state
Expand Down Expand Up @@ -2524,7 +2536,7 @@ void QgsMapCanvas::resizeEvent( QResizeEvent *e )
updateScale();
}

emit extentsChanged();
emitExtentsChanged();
}

void QgsMapCanvas::paintEvent( QPaintEvent *e )
Expand Down Expand Up @@ -3077,6 +3089,12 @@ void QgsMapCanvas::showEvent( QShowEvent *event )
updateDevicePixelFromScreen();
}

void QgsMapCanvas::emitExtentsChanged()
{
if ( !mBlockExtentChangedSignal )
emit extentsChanged();
}

QPoint QgsMapCanvas::mouseLastXY()
{
return mCanvasProperties->mouseLastXY;
Expand Down
9 changes: 9 additions & 0 deletions src/gui/qgsmapcanvas.h
Expand Up @@ -1227,6 +1227,13 @@ class GUI_EXPORT QgsMapCanvas : public QGraphicsView, public QgsExpressionContex

void showEvent( QShowEvent *event ) override;

/**
* Emits the extentsChanged signal when appropriate.
*
* \since QGIS 3.30
*/
void emitExtentsChanged();

/// implementation struct
class CanvasProperties;

Expand Down Expand Up @@ -1425,6 +1432,8 @@ class GUI_EXPORT QgsMapCanvas : public QGraphicsView, public QgsExpressionContex
QList< QgsMapCanvasInteractionBlocker * > mInteractionBlockers;

int mBlockItemPositionUpdates = 0;
int mBlockExtentChangedSignal = 0;
int mBlockScaleChangedSignal = 0;

std::unique_ptr< QgsTemporaryCursorOverride > mTemporaryCursorOverride;

Expand Down
27 changes: 27 additions & 0 deletions tests/src/python/test_qgsmapcanvas.py
Expand Up @@ -770,6 +770,33 @@ def test_temporal_animation(self):
self.assertEqual(canvas.mapSettings().frameRate(), -1)
self.assertEqual(canvas.mapSettings().currentFrame(), -1)

def test_crs_change_signals(self):
"""
Test behavior of signals when crs is changed
"""
canvas = QgsMapCanvas()
canvas.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:4326'))
canvas.setFrameStyle(0)
canvas.resize(600, 400)
self.assertEqual(canvas.width(), 600)
self.assertEqual(canvas.height(), 400)
canvas.setExtent(QgsRectangle(10, 30, 20, 35))

def on_extent_changed():
TestQgsMapCanvas.new_extent = canvas.extent()
TestQgsMapCanvas.new_crs = canvas.mapSettings().destinationCrs()

canvas.extentsChanged.connect(on_extent_changed)

TestQgsMapCanvas.new_extent = None
TestQgsMapCanvas.new_crs = None

canvas.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:3857'))

self.assertAlmostEqual(TestQgsMapCanvas.new_extent.xMinimum(), 1008988, places=-3)

self.assertEqual(TestQgsMapCanvas.new_crs, QgsCoordinateReferenceSystem('EPSG:3857'))


if __name__ == '__main__':
unittest.main()

0 comments on commit 11d34a2

Please sign in to comment.