Skip to content

Commit

Permalink
Add signals for when layout item map crs or grid crs are changed
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Nov 22, 2020
1 parent 1b56825 commit 494bf24
Show file tree
Hide file tree
Showing 8 changed files with 147 additions and 7 deletions.
7 changes: 7 additions & 0 deletions python/core/auto_generated/layout/qgslayoutitemmap.sip.in
Expand Up @@ -988,6 +988,13 @@ Emitted when the map's associated ``theme`` is changed.
is linked to a different theme then it previously was.

.. versionadded:: 3.14
%End

void crsChanged();
%Docstring
Emitted when the map's coordinate reference system is changed.

.. versionadded:: 3.18
%End

public slots:
Expand Down
9 changes: 9 additions & 0 deletions python/core/auto_generated/layout/qgslayoutitemmapgrid.sip.in
Expand Up @@ -1118,6 +1118,15 @@ Retrieves the second fill color for the grid frame.
virtual void refresh();


signals:

void crsChanged();
%Docstring
Emitted whenever the grid's CRS is changed.

.. versionadded:: 3.18
%End

};

QFlags<QgsLayoutItemMapGrid::FrameSideFlag> operator|(QgsLayoutItemMapGrid::FrameSideFlag f1, QFlags<QgsLayoutItemMapGrid::FrameSideFlag> f2);
Expand Down
23 changes: 16 additions & 7 deletions src/core/layout/qgslayoutitemmap.cpp
Expand Up @@ -300,7 +300,11 @@ QgsCoordinateReferenceSystem QgsLayoutItemMap::crs() const

void QgsLayoutItemMap::setCrs( const QgsCoordinateReferenceSystem &crs )
{
if ( mCrs == crs )
return;

mCrs = crs;
emit crsChanged();
}

QList<QgsMapLayer *> QgsLayoutItemMap::layers() const
Expand Down Expand Up @@ -707,15 +711,13 @@ bool QgsLayoutItemMap::readPropertiesFromElement( const QDomElement &itemElem, c
}

QDomNodeList crsNodeList = itemElem.elementsByTagName( QStringLiteral( "crs" ) );
QgsCoordinateReferenceSystem crs;
if ( !crsNodeList.isEmpty() )
{
QDomElement crsElem = crsNodeList.at( 0 ).toElement();
mCrs.readXml( crsElem );
}
else
{
mCrs = QgsCoordinateReferenceSystem();
crs.readXml( crsElem );
}
setCrs( crs );

//map rotation
mMapRotation = itemElem.attribute( QStringLiteral( "mapRotation" ), QStringLiteral( "0" ) ).toDouble();
Expand Down Expand Up @@ -1856,9 +1858,15 @@ void QgsLayoutItemMap::refreshDataDefinedProperty( const QgsLayoutObject::DataDe
if ( property == QgsLayoutObject::MapCrs || property == QgsLayoutObject::AllProperties )
{
bool ok;
QString crsVar = mDataDefinedProperties.valueAsString( QgsLayoutObject::MapCrs, context, QString(), &ok );
const QString crsVar = mDataDefinedProperties.valueAsString( QgsLayoutObject::MapCrs, context, QString(), &ok );
if ( ok && QgsCoordinateReferenceSystem( crsVar ).isValid() )
mCrs = QgsCoordinateReferenceSystem( crsVar );
{
const QgsCoordinateReferenceSystem newCrs( crsVar );
if ( newCrs.isValid() )
{
setCrs( newCrs );
}
}
}
//updates data defined properties and redraws item to match
if ( property == QgsLayoutObject::MapRotation || property == QgsLayoutObject::MapScale ||
Expand Down Expand Up @@ -1992,6 +2000,7 @@ void QgsLayoutItemMap::connectUpdateSlot()
{
//using project CRS, which just changed....
invalidateCache();
emit crsChanged();
}
} );

Expand Down
7 changes: 7 additions & 0 deletions src/core/layout/qgslayoutitemmap.h
Expand Up @@ -910,6 +910,13 @@ class CORE_EXPORT QgsLayoutItemMap : public QgsLayoutItem, public QgsTemporalRan
*/
void themeChanged( const QString &theme );

/**
* Emitted when the map's coordinate reference system is changed.
*
* \since QGIS 3.18
*/
void crsChanged();

public slots:

void refresh() override;
Expand Down
9 changes: 9 additions & 0 deletions src/core/layout/qgslayoutitemmapgrid.cpp
Expand Up @@ -203,6 +203,11 @@ QgsLayoutItemMapGrid::QgsLayoutItemMapGrid( const QString &name, QgsLayoutItemMa

connect( mMap, &QgsLayoutItemMap::extentChanged, this, &QgsLayoutItemMapGrid::refreshDataDefinedProperties );
connect( mMap, &QgsLayoutItemMap::mapRotationChanged, this, &QgsLayoutItemMapGrid::refreshDataDefinedProperties );
connect( mMap, &QgsLayoutItemMap::crsChanged, this, [ = ]
{
if ( !mCRS.isValid() )
emit crsChanged();
} );
}

void QgsLayoutItemMapGrid::createDefaultGridLineSymbol()
Expand Down Expand Up @@ -438,8 +443,12 @@ bool QgsLayoutItemMapGrid::readXml( const QDomElement &itemElem, const QDomDocum

void QgsLayoutItemMapGrid::setCrs( const QgsCoordinateReferenceSystem &crs )
{
if ( mCRS == crs )
return;

mCRS = crs;
mTransformDirty = true;
emit crsChanged();
}

bool QgsLayoutItemMapGrid::usesAdvancedEffects() const
Expand Down
9 changes: 9 additions & 0 deletions src/core/layout/qgslayoutitemmapgrid.h
Expand Up @@ -1006,6 +1006,15 @@ class CORE_EXPORT QgsLayoutItemMapGrid : public QgsLayoutItemMapItem
bool accept( QgsStyleEntityVisitorInterface *visitor ) const override;
void refresh() override;

signals:

/**
* Emitted whenever the grid's CRS is changed.
*
* \since QGIS 3.18
*/
void crsChanged();

private:

QgsLayoutItemMapGrid() = delete;
Expand Down
38 changes: 38 additions & 0 deletions tests/src/python/test_qgslayoutmap.py
Expand Up @@ -822,6 +822,44 @@ def testMainAnnotationLayer(self):
TestQgsLayoutMap.report += checker.report()
self.assertTrue(result, message)

def testCrsChanged(self):
"""
Test that the CRS changed signal is emitted in the right circumstances
"""
p = QgsProject()
layout = QgsLayout(p)
p.setCrs(QgsCoordinateReferenceSystem('EPSG:4326'))
map = QgsLayoutItemMap(layout)

spy = QSignalSpy(map.crsChanged)
# map has no explicit crs set, so follows project crs => signal should be emitted
# when project crs is changed
p.setCrs(QgsCoordinateReferenceSystem('EPSG:3111'))
self.assertEqual(len(spy), 1)
p.setCrs(QgsCoordinateReferenceSystem('EPSG:4326'))
self.assertEqual(len(spy), 2)
# set explicit crs on map item
map.setCrs(QgsCoordinateReferenceSystem('EPSG:28356'))
self.assertEqual(len(spy), 3)
map.setCrs(QgsCoordinateReferenceSystem('EPSG:28356'))
self.assertEqual(len(spy), 3)
map.setCrs(QgsCoordinateReferenceSystem('EPSG:28355'))
self.assertEqual(len(spy), 4)
# should not care about project crs changes anymore..
p.setCrs(QgsCoordinateReferenceSystem('EPSG:3111'))
self.assertEqual(len(spy), 4)
# set back to project crs
map.setCrs(QgsCoordinateReferenceSystem())
self.assertEqual(len(spy), 5)

map.setCrs(QgsCoordinateReferenceSystem('EPSG:28355'))
self.assertEqual(len(spy), 6)
# data defined crs
map.dataDefinedProperties().setProperty(QgsLayoutObject.MapCrs, QgsProperty.fromValue('EPSG:4283'))
self.assertEqual(len(spy), 6)
map.refresh()
self.assertEqual(len(spy), 7)


if __name__ == '__main__':
unittest.main()
52 changes: 52 additions & 0 deletions tests/src/python/test_qgslayoutmapgrid.py
Expand Up @@ -14,6 +14,7 @@

from qgis.PyQt.QtCore import QRectF, QDir
from qgis.PyQt.QtGui import QPainter, QColor
from qgis.PyQt.QtTest import QSignalSpy

from qgis.core import (QgsLayoutItemMap,
QgsLayoutItemMapGrid,
Expand Down Expand Up @@ -852,6 +853,57 @@ def testDynamicInterval(self):
self.report += checker.report()
self.assertTrue(myTestResult, myMessage)

def testCrsChanged(self):
"""
Test that the CRS changed signal is emitted in the right circumstances
"""
p = QgsProject()
layout = QgsLayout(p)
p.setCrs(QgsCoordinateReferenceSystem('EPSG:4326'))
map = QgsLayoutItemMap(layout)

grid = map.grid()

spy = QSignalSpy(grid.crsChanged)
# map grid and map have no explicit crs set, so follows project crs => signal should be emitted
# when project crs is changed
p.setCrs(QgsCoordinateReferenceSystem('EPSG:3111'))
self.assertEqual(len(spy), 1)
p.setCrs(QgsCoordinateReferenceSystem('EPSG:4326'))
self.assertEqual(len(spy), 2)
# set explicit crs on map item
map.setCrs(QgsCoordinateReferenceSystem('EPSG:28356'))
self.assertEqual(len(spy), 3)
map.setCrs(QgsCoordinateReferenceSystem('EPSG:28356'))
self.assertEqual(len(spy), 3)
map.setCrs(QgsCoordinateReferenceSystem('EPSG:28355'))
self.assertEqual(len(spy), 4)
# should not care about project crs changes anymore..
p.setCrs(QgsCoordinateReferenceSystem('EPSG:3111'))
self.assertEqual(len(spy), 4)
# set back to project crs
map.setCrs(QgsCoordinateReferenceSystem())
self.assertEqual(len(spy), 5)

map.setCrs(QgsCoordinateReferenceSystem('EPSG:28355'))
self.assertEqual(len(spy), 6)
# data defined crs
map.dataDefinedProperties().setProperty(QgsLayoutObject.MapCrs, QgsProperty.fromValue('EPSG:4283'))
self.assertEqual(len(spy), 6)
map.refresh()
self.assertEqual(len(spy), 7)

# explicit crs for map grid
grid.setCrs(QgsCoordinateReferenceSystem('EPSG:3857'))
self.assertEqual(len(spy), 8)
grid.setCrs(QgsCoordinateReferenceSystem('EPSG:3857'))
self.assertEqual(len(spy), 8)
map.dataDefinedProperties().setProperty(QgsLayoutObject.MapCrs, QgsProperty.fromValue('EPSG:3111'))
map.refresh()
self.assertEqual(len(spy), 8)
grid.setCrs(QgsCoordinateReferenceSystem('EPSG:3111'))
self.assertEqual(len(spy), 9)


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

0 comments on commit 494bf24

Please sign in to comment.