Skip to content

Commit

Permalink
Add signal which is emitted when a layout map's linked theme is changed
Browse files Browse the repository at this point in the history
(cherry picked from commit 0930906)
  • Loading branch information
nyalldawson committed Apr 6, 2020
1 parent deac6f5 commit 8ad01a2
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 2 deletions.
16 changes: 16 additions & 0 deletions python/core/auto_generated/layout/qgslayoutitemmap.sip.in
Expand Up @@ -296,13 +296,17 @@ Preset name that decides which layers and layer styles are used for map renderin
used when followVisibilityPreset() returns ``True``.

.. seealso:: :py:func:`setFollowVisibilityPresetName`

.. seealso:: :py:func:`themeChanged`
%End

void setFollowVisibilityPresetName( const QString &name );
%Docstring
Sets preset name for map rendering. See followVisibilityPresetName() for more details.

.. seealso:: :py:func:`followVisibilityPresetName`

.. seealso:: :py:func:`themeChanged`
%End

virtual void moveContent( double dx, double dy );
Expand Down Expand Up @@ -680,6 +684,18 @@ Emitted when the map has been prepared for atlas rendering, just before actual r
%Docstring
Emitted when layer style overrides are changed... a means to let
associated legend items know they should update
%End

void themeChanged( const QString &theme );
%Docstring
Emitted when the map's associated ``theme`` is changed.

.. note::

This signal is not emitted when the definition of the theme changes, only the map
is linked to a different theme then it previously was.

.. versionadded:: 3.14
%End

public slots:
Expand Down
27 changes: 27 additions & 0 deletions src/core/layout/qgslayoutitemmap.cpp
Expand Up @@ -309,6 +309,26 @@ void QgsLayoutItemMap::storeCurrentLayerStyles()
}
}

void QgsLayoutItemMap::setFollowVisibilityPreset( bool follow )
{
if ( mFollowVisibilityPreset == follow )
return;

mFollowVisibilityPreset = follow;
if ( !mFollowVisibilityPresetName.isEmpty() )
emit themeChanged( mFollowVisibilityPreset ? mFollowVisibilityPresetName : QString() );
}

void QgsLayoutItemMap::setFollowVisibilityPresetName( const QString &name )
{
if ( name == mFollowVisibilityPresetName )
return;

mFollowVisibilityPresetName = name;
if ( mFollowVisibilityPreset )
emit themeChanged( mFollowVisibilityPresetName );
}

void QgsLayoutItemMap::moveContent( double dx, double dy )
{
mLastRenderedImageOffsetX -= dx;
Expand Down Expand Up @@ -1707,6 +1727,13 @@ void QgsLayoutItemMap::refreshDataDefinedProperty( const QgsLayoutObject::DataDe
{
refreshLabelMargin( false );
}
if ( property == QgsLayoutObject::MapStylePreset || property == QgsLayoutObject::AllProperties )
{
const QString previousTheme = mLastEvaluatedThemeName.isEmpty() ? mFollowVisibilityPresetName : mLastEvaluatedThemeName;
mLastEvaluatedThemeName = mDataDefinedProperties.valueAsString( QgsLayoutObject::MapStylePreset, context, mFollowVisibilityPresetName );
if ( mLastEvaluatedThemeName != previousTheme )
emit themeChanged( mLastEvaluatedThemeName );
}

//force redraw
mCacheInvalidated = true;
Expand Down
21 changes: 19 additions & 2 deletions src/core/layout/qgslayoutitemmap.h
Expand Up @@ -285,20 +285,24 @@ class CORE_EXPORT QgsLayoutItemMap : public QgsLayoutItem
/**
* Sets whether the map should follow a map theme. See followVisibilityPreset() for more details.
*/
void setFollowVisibilityPreset( bool follow ) { mFollowVisibilityPreset = follow; }
void setFollowVisibilityPreset( bool follow );

/**
* Preset name that decides which layers and layer styles are used for map rendering. It is only
* used when followVisibilityPreset() returns TRUE.
* \see setFollowVisibilityPresetName()
*
* \see themeChanged()
*/
QString followVisibilityPresetName() const { return mFollowVisibilityPresetName; }

/**
* Sets preset name for map rendering. See followVisibilityPresetName() for more details.
* \see followVisibilityPresetName()
*
* \see themeChanged()
*/
void setFollowVisibilityPresetName( const QString &name ) { mFollowVisibilityPresetName = name; }
void setFollowVisibilityPresetName( const QString &name );

void moveContent( double dx, double dy ) override;
void setMoveContentPreviewOffset( double dx, double dy ) override;
Expand Down Expand Up @@ -602,6 +606,16 @@ class CORE_EXPORT QgsLayoutItemMap : public QgsLayoutItem
*/
void layerStyleOverridesChanged();

/**
* Emitted when the map's associated \a theme is changed.
*
* \note This signal is not emitted when the definition of the theme changes, only the map
* is linked to a different theme then it previously was.
*
* \since QGIS 3.14
*/
void themeChanged( const QString &theme );

public slots:

void refresh() override;
Expand Down Expand Up @@ -716,6 +730,9 @@ class CORE_EXPORT QgsLayoutItemMap : public QgsLayoutItem
* is TRUE. May be overridden by data-defined expression. */
QString mFollowVisibilityPresetName;

//! Name of the last data-defined evaluated theme name
QString mLastEvaluatedThemeName;

/**
* \brief Draw to paint device
* \param painter painter
Expand Down
58 changes: 58 additions & 0 deletions tests/src/python/test_qgslayoutmap.py
Expand Up @@ -17,6 +17,7 @@
from qgis.PyQt.QtCore import QFileInfo, QRectF, QDir
from qgis.PyQt.QtXml import QDomDocument
from qgis.PyQt.QtGui import QPainter, QColor
from qgis.PyQt.QtTest import QSignalSpy

from qgis.core import (QgsLayoutItemMap,
QgsRectangle,
Expand Down Expand Up @@ -398,6 +399,63 @@ def testBlockingItems(self):
self.assertTrue(map_restore.isLabelBlockingItem(map2_restore))
self.assertTrue(map_restore.isLabelBlockingItem(map3_restore))

def testTheme(self):
layout = QgsLayout(QgsProject.instance())
map = QgsLayoutItemMap(layout)
self.assertFalse(map.followVisibilityPreset())
self.assertFalse(map.followVisibilityPresetName())

spy = QSignalSpy(map.themeChanged)

map.setFollowVisibilityPresetName('theme')
self.assertFalse(map.followVisibilityPreset())
self.assertEqual(map.followVisibilityPresetName(), 'theme')
# should not be emitted - followVisibilityPreset is False
self.assertEqual(len(spy), 0)
map.setFollowVisibilityPresetName('theme2')
self.assertEqual(map.followVisibilityPresetName(), 'theme2')
self.assertEqual(len(spy), 0)

map.setFollowVisibilityPresetName('')
map.setFollowVisibilityPreset(True)
# should not be emitted - followVisibilityPresetName is empty
self.assertEqual(len(spy), 0)
self.assertFalse(map.followVisibilityPresetName())
self.assertTrue(map.followVisibilityPreset())

map.setFollowVisibilityPresetName('theme')
self.assertEqual(len(spy), 1)
self.assertEqual(spy[-1][0], 'theme')
map.setFollowVisibilityPresetName('theme')
self.assertEqual(len(spy), 1)
map.setFollowVisibilityPresetName('theme2')
self.assertEqual(len(spy), 2)
self.assertEqual(spy[-1][0], 'theme2')
map.setFollowVisibilityPreset(False)
self.assertEqual(len(spy), 3)
self.assertFalse(spy[-1][0])
map.setFollowVisibilityPreset(False)
self.assertEqual(len(spy), 3)
map.setFollowVisibilityPresetName('theme3')
self.assertEqual(len(spy), 3)
map.setFollowVisibilityPreset(True)
self.assertEqual(len(spy), 4)
self.assertEqual(spy[-1][0], 'theme3')
map.setFollowVisibilityPreset(True)
self.assertEqual(len(spy), 4)

# data defined theme
map.dataDefinedProperties().setProperty(QgsLayoutObject.MapStylePreset, QgsProperty.fromValue('theme4'))
map.refresh()
self.assertEqual(len(spy), 5)
self.assertEqual(spy[-1][0], 'theme4')
map.refresh()
self.assertEqual(len(spy), 5)
map.dataDefinedProperties().setProperty(QgsLayoutObject.MapStylePreset, QgsProperty.fromValue('theme6'))
map.refresh()
self.assertEqual(len(spy), 6)
self.assertEqual(spy[-1][0], 'theme6')


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

0 comments on commit 8ad01a2

Please sign in to comment.