Skip to content

Commit b87e5f7

Browse files
committed
[FEATURE][composer] Data defined style preset for composer maps
Sponsored by City of Uster
1 parent bcaee65 commit b87e5f7

File tree

8 files changed

+118
-8
lines changed

8 files changed

+118
-8
lines changed

python/core/composer/qgscomposerobject.sip

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class QgsComposerObject : QObject
4141
MapYMax, /*!< map extent y maximum */
4242
MapAtlasMargin, /*!< map atlas margin*/
4343
MapLayers, /*!< map layer set*/
44+
MapStylePreset, /*!< layer and style visibility preset */
4445
//composer picture
4546
PictureSource, /*!< picture source url */
4647
//html item

src/app/composer/qgscomposermapwidget.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,9 @@ QgsComposerMapWidget::QgsComposerMapWidget( QgsComposerMap* composerMap )
175175
connect( mLayersDDBtn, SIGNAL( dataDefinedChanged( const QString& ) ), this, SLOT( updateDataDefinedProperty() ) );
176176
connect( mLayersDDBtn, SIGNAL( dataDefinedActivated( bool ) ), this, SLOT( updateDataDefinedProperty() ) );
177177

178+
connect( mStylePresetsDDBtn, SIGNAL( dataDefinedChanged( const QString& ) ), this, SLOT( updateDataDefinedProperty() ) );
179+
connect( mStylePresetsDDBtn, SIGNAL( dataDefinedActivated( bool ) ), this, SLOT( updateDataDefinedProperty() ) );
180+
178181
updateGuiElements();
179182
loadGridEntries();
180183
loadOverviewEntries();
@@ -197,6 +200,7 @@ void QgsComposerMapWidget::populateDataDefinedButtons()
197200
mXMaxDDBtn->blockSignals( true );
198201
mYMaxDDBtn->blockSignals( true );
199202
mAtlasMarginDDBtn->blockSignals( true );
203+
mStylePresetsDDBtn->blockSignals( true );
200204
mLayersDDBtn->blockSignals( true );
201205

202206
//initialise buttons to use atlas coverage layer
@@ -214,6 +218,8 @@ void QgsComposerMapWidget::populateDataDefinedButtons()
214218
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::doubleDesc() );
215219
mAtlasMarginDDBtn->init( vl, mComposerMap->dataDefinedProperty( QgsComposerObject::MapAtlasMargin ),
216220
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::doubleDesc() );
221+
mStylePresetsDDBtn->init( vl, mComposerMap->dataDefinedProperty( QgsComposerObject::MapStylePreset ),
222+
QgsDataDefinedButton::String, tr( "string matching a style preset name" ) );
217223
mLayersDDBtn->init( vl, mComposerMap->dataDefinedProperty( QgsComposerObject::MapLayers ),
218224
QgsDataDefinedButton::String, tr( "list of map layer names separated by | characters" ) );
219225

@@ -225,6 +231,7 @@ void QgsComposerMapWidget::populateDataDefinedButtons()
225231
mXMaxDDBtn->blockSignals( false );
226232
mYMaxDDBtn->blockSignals( false );
227233
mAtlasMarginDDBtn->blockSignals( false );
234+
mStylePresetsDDBtn->blockSignals( false );
228235
mLayersDDBtn->blockSignals( false );
229236
}
230237

@@ -258,6 +265,10 @@ QgsComposerObject::DataDefinedProperty QgsComposerMapWidget::ddPropertyForWidget
258265
{
259266
return QgsComposerObject::MapAtlasMargin;
260267
}
268+
else if ( widget == mStylePresetsDDBtn )
269+
{
270+
return QgsComposerObject::MapStylePreset;
271+
}
261272
else if ( widget == mLayersDDBtn )
262273
{
263274
return QgsComposerObject::MapLayers;

src/core/composer/qgscomposermap.cpp

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "qgsvectorlayer.h"
3434
#include "qgspallabeling.h"
3535
#include "qgsexpression.h"
36+
#include "qgsvisibilitypresetcollection.h"
3637

3738
#include "qgslabel.h"
3839
#include "qgslabelattributes.h"
@@ -132,6 +133,7 @@ void QgsComposerMap::init()
132133
mDataDefinedNames.insert( QgsComposerObject::MapYMax, QString( "dataDefinedMapYMax" ) );
133134
mDataDefinedNames.insert( QgsComposerObject::MapAtlasMargin, QString( "dataDefinedMapAtlasMargin" ) );
134135
mDataDefinedNames.insert( QgsComposerObject::MapLayers, QString( "dataDefinedMapLayers" ) );
136+
mDataDefinedNames.insert( QgsComposerObject::MapStylePreset, QString( "dataDefinedMapStylePreset" ) );
135137
}
136138

137139
void QgsComposerMap::updateToolTip()
@@ -217,7 +219,7 @@ QgsMapSettings QgsComposerMap::mapSettings( const QgsRectangle& extent, const QS
217219
: QStringList(); //exporting decorations such as map frame/grid/overview, so no map layers required
218220
}
219221
jobMapSettings.setLayers( theLayerSet );
220-
jobMapSettings.setLayerStyleOverrides( mLayerStyleOverrides );
222+
jobMapSettings.setLayerStyleOverrides( layerStyleOverridesToRender() );
221223
jobMapSettings.setDestinationCrs( ms.destinationCrs() );
222224
jobMapSettings.setCrsTransformEnabled( ms.hasCrsTransformEnabled() );
223225
jobMapSettings.setFlags( ms.flags() );
@@ -522,18 +524,30 @@ const QgsMapRenderer *QgsComposerMap::mapRenderer() const
522524

523525
QStringList QgsComposerMap::layersToRender() const
524526
{
525-
//use stored layer set or read current set from main canvas
526527
QStringList renderLayerSet;
527-
if ( mKeepLayerSet )
528+
529+
QVariant exprVal;
530+
if ( dataDefinedEvaluate( QgsComposerObject::MapStylePreset, exprVal ) )
528531
{
529-
renderLayerSet = mLayerSet;
532+
QString presetName = exprVal.toString();
533+
534+
if ( QgsProject::instance()->visibilityPresetCollection()->hasPreset( presetName ) )
535+
renderLayerSet = QgsProject::instance()->visibilityPresetCollection()->presetVisibleLayers( presetName );
530536
}
531-
else
537+
538+
//use stored layer set or read current set from main canvas
539+
if ( renderLayerSet.isEmpty() )
532540
{
533-
renderLayerSet = mComposition->mapSettings().layers();
541+
if ( mKeepLayerSet )
542+
{
543+
renderLayerSet = mLayerSet;
544+
}
545+
else
546+
{
547+
renderLayerSet = mComposition->mapSettings().layers();
548+
}
534549
}
535550

536-
QVariant exprVal;
537551
if ( dataDefinedEvaluate( QgsComposerObject::MapLayers, exprVal ) )
538552
{
539553
renderLayerSet.clear();
@@ -568,6 +582,20 @@ QStringList QgsComposerMap::layersToRender() const
568582
return renderLayerSet;
569583
}
570584

585+
QMap<QString, QString> QgsComposerMap::layerStyleOverridesToRender() const
586+
{
587+
QVariant exprVal;
588+
if ( dataDefinedEvaluate( QgsComposerObject::MapStylePreset, exprVal ) )
589+
{
590+
QString presetName = exprVal.toString();
591+
592+
if ( QgsProject::instance()->visibilityPresetCollection()->hasPreset( presetName ) )
593+
return QgsProject::instance()->visibilityPresetCollection()->presetStyleOverrides( presetName );
594+
595+
}
596+
return mLayerStyleOverrides;
597+
}
598+
571599
double QgsComposerMap::scale() const
572600
{
573601
QgsScaleCalculator calculator;

src/core/composer/qgscomposermap.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -921,6 +921,9 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
921921
/** Returns a list of the layers to render for this map item*/
922922
QStringList layersToRender() const;
923923

924+
/** Returns current layer style overrides for this map item*/
925+
QMap<QString, QString> layerStyleOverridesToRender() const;
926+
924927
/** Returns extent that considers mOffsetX / mOffsetY (during content move)*/
925928
QgsRectangle transformedExtent() const;
926929

src/core/composer/qgscomposerobject.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ class CORE_EXPORT QgsComposerObject: public QObject
6666
MapYMax, /*!< map extent y maximum */
6767
MapAtlasMargin, /*!< map atlas margin*/
6868
MapLayers, /*!< map layer set*/
69+
MapStylePreset, /*!< layer and style visibility preset */
6970
//composer picture
7071
PictureSource, /*!< picture source url */
7172
//html item

src/ui/qgscomposermapwidgetbase.ui

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565
<x>0</x>
6666
<y>0</y>
6767
<width>446</width>
68-
<height>2490</height>
68+
<height>2493</height>
6969
</rect>
7070
</property>
7171
<property name="sizePolicy">
@@ -230,6 +230,13 @@
230230
</property>
231231
</widget>
232232
</item>
233+
<item>
234+
<widget class="QgsDataDefinedButton" name="mStylePresetsDDBtn">
235+
<property name="text">
236+
<string>...</string>
237+
</property>
238+
</widget>
239+
</item>
233240
</layout>
234241
</item>
235242
</layout>
@@ -1438,6 +1445,7 @@
14381445
<tabstop>mLayerListFromPresetButton</tabstop>
14391446
<tabstop>mLayersDDBtn</tabstop>
14401447
<tabstop>mKeepLayerStylesCheckBox</tabstop>
1448+
<tabstop>mStylePresetsDDBtn</tabstop>
14411449
<tabstop>mExtentsCheckBox</tabstop>
14421450
<tabstop>mXMinLineEdit</tabstop>
14431451
<tabstop>mXMinDDBtn</tabstop>

tests/src/core/testqgscomposermap.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
#include "qgsmultibandcolorrenderer.h"
2525
#include "qgsrasterlayer.h"
2626
#include "qgsvectorlayer.h"
27+
#include "qgsproject.h"
28+
#include "qgsvisibilitypresetcollection.h"
2729
#include <QObject>
2830
#include <QtTest/QtTest>
2931

@@ -49,6 +51,7 @@ class TestQgsComposerMap : public QObject
4951
void worldFileGeneration(); // test world file generation
5052
void mapPolygonVertices(); // test mapPolygon function with no map rotation
5153
void dataDefinedLayers(); //test data defined layer string
54+
void dataDefinedStyles(); //test data defined styles
5255

5356
private:
5457
QgsComposition *mComposition;
@@ -279,5 +282,60 @@ void TestQgsComposerMap::dataDefinedLayers()
279282
QVERIFY( checker.testComposition( mReport, 0, 0 ) );
280283
}
281284

285+
void TestQgsComposerMap::dataDefinedStyles()
286+
{
287+
delete mComposition;
288+
QgsMapSettings ms;
289+
ms.setLayers( QStringList() << mRasterLayer->id() << mPolysLayer->id() << mPointsLayer->id() << mLinesLayer->id() );
290+
ms.setCrsTransformEnabled( true );
291+
292+
mComposition = new QgsComposition( ms );
293+
mComposition->setPaperSize( 297, 210 ); //A4 landscape
294+
mComposerMap = new QgsComposerMap( mComposition, 20, 20, 200, 100 );
295+
mComposerMap->setFrameEnabled( true );
296+
mComposition->addComposerMap( mComposerMap );
297+
298+
QgsVisibilityPresetCollection::PresetRecord rec;
299+
rec.mVisibleLayerIDs.insert( mPointsLayer->id() );
300+
rec.mVisibleLayerIDs.insert( mLinesLayer->id() );
301+
302+
QgsProject::instance()->visibilityPresetCollection()->insert( "test preset", rec );
303+
304+
//test malformed style string
305+
mComposerMap->setDataDefinedProperty( QgsComposerObject::MapStylePreset, true, true, "5", QString() );
306+
QSet<QString> result = mComposerMap->layersToRender().toSet();
307+
QCOMPARE( result, ms.layers().toSet() );
308+
309+
//test valid preset
310+
mComposerMap->setDataDefinedProperty( QgsComposerObject::MapStylePreset, true, true, QString( "'test preset'" ), QString() );
311+
result = mComposerMap->layersToRender().toSet();
312+
QCOMPARE( result.count(), 2 );
313+
QVERIFY( result.contains( mLinesLayer->id() ) );
314+
QVERIFY( result.contains( mPointsLayer->id() ) );
315+
316+
//test non-existant preset
317+
mComposerMap->setDataDefinedProperty( QgsComposerObject::MapStylePreset, true, true,
318+
QString( "'bad preset'" ), QString() );
319+
result = mComposerMap->layersToRender().toSet();
320+
QCOMPARE( result, ms.layers().toSet() );
321+
322+
//test that dd layer set overrides style layers
323+
mComposerMap->setDataDefinedProperty( QgsComposerObject::MapStylePreset, true, true, QString( "'test preset'" ), QString() );
324+
mComposerMap->setDataDefinedProperty( QgsComposerObject::MapLayers, true, true,
325+
QString( "'%1'" ).arg( mPolysLayer->name() ), QString() );
326+
result = mComposerMap->layersToRender().toSet();
327+
QCOMPARE( result.count(), 1 );
328+
QVERIFY( result.contains( mPolysLayer->id() ) );
329+
mComposerMap->setDataDefinedProperty( QgsComposerObject::MapLayers, false, true, QString(), QString() );
330+
331+
//render test
332+
mComposerMap->setDataDefinedProperty( QgsComposerObject::MapStylePreset, true, true,
333+
QString( "'test preset'" ), QString() );
334+
mComposerMap->setNewExtent( QgsRectangle( -110.0, 25.0, -90, 40.0 ) );
335+
336+
QgsCompositionChecker checker( "composermap_ddstyles", mComposition );
337+
QVERIFY( checker.testComposition( mReport, 0, 0 ) );
338+
}
339+
282340
QTEST_MAIN( TestQgsComposerMap )
283341
#include "testqgscomposermap.moc"
24.1 KB
Loading

0 commit comments

Comments
 (0)