Skip to content

Commit 1b309c6

Browse files
committedJan 2, 2019
[layouts] Add setters/getters for map item stacking positions
1 parent 6eb49fe commit 1b309c6

File tree

5 files changed

+219
-2
lines changed

5 files changed

+219
-2
lines changed
 

‎python/core/auto_generated/layout/qgslayoutitemmapitem.sip.in

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,15 @@ An item which is drawn inside a QgsLayoutItemMap, e.g., a grid or map overview.
2222
%End
2323
public:
2424

25+
enum StackingPosition
26+
{
27+
StackBelowMap,
28+
StackBelowMapLayer,
29+
StackAboveMapLayer,
30+
StackBelowMapLabels,
31+
StackAboveMapLabels,
32+
};
33+
2534
QgsLayoutItemMapItem( const QString &name, QgsLayoutItemMap *map );
2635
%Docstring
2736
Constructor for QgsLayoutItemMapItem, attached to the specified ``map``.
@@ -111,6 +120,60 @@ Returns whether the item will be drawn.
111120
virtual bool usesAdvancedEffects() const;
112121
%Docstring
113122
Returns true if the item is drawn using advanced effects, such as blend modes.
123+
%End
124+
125+
StackingPosition stackingPosition() const;
126+
%Docstring
127+
Returns the item's stacking position, which specifies where the in the map's
128+
stack the item should be rendered.
129+
130+
.. seealso:: :py:func:`setStackingPosition`
131+
132+
.. seealso:: :py:func:`stackingLayer`
133+
134+
.. versionadded:: 3.6
135+
%End
136+
137+
void setStackingPosition( StackingPosition position );
138+
%Docstring
139+
Sets the item's stacking ``position``, which specifies where the in the map's
140+
stack the item should be rendered.
141+
142+
.. seealso:: :py:func:`stackingPosition`
143+
144+
.. seealso:: :py:func:`setStackingLayer`
145+
146+
.. versionadded:: 3.6
147+
%End
148+
149+
QgsMapLayer *stackingLayer() const;
150+
%Docstring
151+
Returns the item's stacking layer, which specifies where the in the map's
152+
stack the item should be rendered.
153+
154+
This setting is only used when stackingPosition() is StackBelowMapLayer or
155+
StackAboveMapLayer.
156+
157+
.. seealso:: :py:func:`setStackingLayer`
158+
159+
.. seealso:: :py:func:`stackingPosition`
160+
161+
.. versionadded:: 3.6
162+
%End
163+
164+
void setStackingLayer( QgsMapLayer *layer );
165+
%Docstring
166+
Sets the item's stacking ``layer``, which specifies where the in the map's
167+
stack the item should be rendered.
168+
169+
This setting is only used when stackingPosition() is StackBelowMapLayer or
170+
StackAboveMapLayer.
171+
172+
.. seealso:: :py:func:`stackingLayer`
173+
174+
.. seealso:: :py:func:`setStackingPosition`
175+
176+
.. versionadded:: 3.6
114177
%End
115178

116179
protected:
@@ -119,9 +182,9 @@ Returns true if the item is drawn using advanced effects, such as blend modes.
119182

120183

121184

122-
};
123185

124186

187+
};
125188

126189
class QgsLayoutItemMapItemStack
127190
{

‎src/core/layout/qgslayoutitemmapitem.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include "qgslayoutitemmapitem.h"
1919
#include "qgslayoutitemmap.h"
20+
#include "qgslayout.h"
2021
#include <QUuid>
2122

2223
QgsLayoutItemMapItem::QgsLayoutItemMapItem( const QString &name, QgsLayoutItemMap *map )
@@ -35,6 +36,16 @@ bool QgsLayoutItemMapItem::writeXml( QDomElement &element, QDomDocument &documen
3536
element.setAttribute( QStringLiteral( "uuid" ), mUuid );
3637
element.setAttribute( QStringLiteral( "name" ), mName );
3738
element.setAttribute( QStringLiteral( "show" ), mEnabled );
39+
element.setAttribute( QStringLiteral( "position" ), static_cast< int >( mStackingPosition ) );
40+
41+
if ( mStackingLayer )
42+
{
43+
element.setAttribute( QStringLiteral( "stackingLayer" ), mStackingLayer.layerId );
44+
element.setAttribute( QStringLiteral( "stackingLayerName" ), mStackingLayer.name );
45+
element.setAttribute( QStringLiteral( "stackingLayerSource" ), mStackingLayer.source );
46+
element.setAttribute( QStringLiteral( "stackingLayerProvider" ), mStackingLayer.provider );
47+
}
48+
3849
return true;
3950
}
4051

@@ -44,6 +55,16 @@ bool QgsLayoutItemMapItem::readXml( const QDomElement &itemElem, const QDomDocum
4455
mUuid = itemElem.attribute( QStringLiteral( "uuid" ) );
4556
mName = itemElem.attribute( QStringLiteral( "name" ) );
4657
mEnabled = ( itemElem.attribute( QStringLiteral( "show" ), QStringLiteral( "0" ) ) != QLatin1String( "0" ) );
58+
mStackingPosition = static_cast< StackingPosition >( itemElem.attribute( QStringLiteral( "position" ), QString::number( QgsLayoutItemMapItem::StackBelowMapLabels ) ).toInt() );
59+
60+
const QString layerId = itemElem.attribute( QStringLiteral( "stackingLayer" ) );
61+
const QString layerName = itemElem.attribute( QStringLiteral( "stackingLayerName" ) );
62+
const QString layerSource = itemElem.attribute( QStringLiteral( "stackingLayerSource" ) );
63+
const QString layerProvider = itemElem.attribute( QStringLiteral( "stackingLayerProvider" ) );
64+
mStackingLayer = QgsMapLayerRef( layerId, layerName, layerSource, layerProvider );
65+
if ( mMap && mMap->layout() )
66+
mStackingLayer.resolveWeakly( mMap->layout()->project() );
67+
4768
return true;
4869
}
4970

@@ -86,6 +107,16 @@ bool QgsLayoutItemMapItem::usesAdvancedEffects() const
86107
return false;
87108
}
88109

110+
QgsMapLayer *QgsLayoutItemMapItem::stackingLayer() const
111+
{
112+
return mStackingLayer.get();
113+
}
114+
115+
void QgsLayoutItemMapItem::setStackingLayer( QgsMapLayer *layer )
116+
{
117+
mStackingLayer.setLayer( layer );
118+
}
119+
89120
//
90121
// QgsLayoutItemMapItemStack
91122
//

‎src/core/layout/qgslayoutitemmapitem.h

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "qgis_core.h"
2121
#include "qgis_sip.h"
2222
#include "qgslayoutobject.h"
23+
#include "qgsmaplayerref.h"
2324

2425
class QgsLayoutItemMap;
2526

@@ -35,6 +36,16 @@ class CORE_EXPORT QgsLayoutItemMapItem : public QgsLayoutObject
3536

3637
public:
3738

39+
//! Item stacking position, specifies where the in the map's stack the item should be rendered
40+
enum StackingPosition
41+
{
42+
StackBelowMap, //!< Render below all map layers
43+
StackBelowMapLayer, //!< Render below a specific map layer (see stackingLayer())
44+
StackAboveMapLayer, //!< Render above a specific map layer (see stackingLayer())
45+
StackBelowMapLabels, //!< Render above all map layers, but below map labels
46+
StackAboveMapLabels, //!< Render above all map layers and labels
47+
};
48+
3849
/**
3950
* Constructor for QgsLayoutItemMapItem, attached to the specified \a map.
4051
*
@@ -117,6 +128,56 @@ class CORE_EXPORT QgsLayoutItemMapItem : public QgsLayoutObject
117128
*/
118129
virtual bool usesAdvancedEffects() const;
119130

131+
/**
132+
* Returns the item's stacking position, which specifies where the in the map's
133+
* stack the item should be rendered.
134+
*
135+
* \see setStackingPosition()
136+
* \see stackingLayer()
137+
*
138+
* \since QGIS 3.6
139+
*/
140+
StackingPosition stackingPosition() const { return mStackingPosition; }
141+
142+
/**
143+
* Sets the item's stacking \a position, which specifies where the in the map's
144+
* stack the item should be rendered.
145+
*
146+
* \see stackingPosition()
147+
* \see setStackingLayer()
148+
*
149+
* \since QGIS 3.6
150+
*/
151+
void setStackingPosition( StackingPosition position ) { mStackingPosition = position; }
152+
153+
/**
154+
* Returns the item's stacking layer, which specifies where the in the map's
155+
* stack the item should be rendered.
156+
*
157+
* This setting is only used when stackingPosition() is StackBelowMapLayer or
158+
* StackAboveMapLayer.
159+
*
160+
* \see setStackingLayer()
161+
* \see stackingPosition()
162+
*
163+
* \since QGIS 3.6
164+
*/
165+
QgsMapLayer *stackingLayer() const;
166+
167+
/**
168+
* Sets the item's stacking \a layer, which specifies where the in the map's
169+
* stack the item should be rendered.
170+
*
171+
* This setting is only used when stackingPosition() is StackBelowMapLayer or
172+
* StackAboveMapLayer.
173+
*
174+
* \see stackingLayer()
175+
* \see setStackingPosition
176+
*
177+
* \since QGIS 3.6
178+
*/
179+
void setStackingLayer( QgsMapLayer *layer );
180+
120181
protected:
121182

122183
//! Friendly display name
@@ -131,9 +192,11 @@ class CORE_EXPORT QgsLayoutItemMapItem : public QgsLayoutObject
131192
//! True if item is to be displayed on map
132193
bool mEnabled;
133194

134-
};
195+
StackingPosition mStackingPosition = StackBelowMapLabels;
135196

197+
QgsMapLayerRef mStackingLayer;
136198

199+
};
137200

138201
/**
139202
* \ingroup core

‎tests/src/core/testqgslayout.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ class TestQgsLayout: public QObject
6969
void mapLayersRestoredFromTemplate();
7070
void mapLayersStyleOverrideRestoredFromTemplate();
7171
void atlasLayerRestoredFromTemplate();
72+
void overviewStackingLayerRestoredFromTemplate();
7273

7374
private:
7475
QString mReport;
@@ -1264,6 +1265,45 @@ void TestQgsLayout::atlasLayerRestoredFromTemplate()
12641265
QCOMPARE( c2.atlas()->coverageLayer(), layer2 );
12651266
}
12661267

1268+
void TestQgsLayout::overviewStackingLayerRestoredFromTemplate()
1269+
{
1270+
// load some layers
1271+
QFileInfo vectorFileInfo( QStringLiteral( TEST_DATA_DIR ) + "/points.shp" );
1272+
QgsVectorLayer *layer = new QgsVectorLayer( vectorFileInfo.filePath(),
1273+
vectorFileInfo.completeBaseName(),
1274+
QStringLiteral( "ogr" ) );
1275+
QgsProject p;
1276+
p.addMapLayer( layer );
1277+
1278+
QgsPrintLayout c( &p );
1279+
QgsLayoutItemMap *map = new QgsLayoutItemMap( &c );
1280+
map->attemptSetSceneRect( QRectF( 1, 1, 10, 10 ) );
1281+
c.addLayoutItem( map );
1282+
map->overview()->setStackingLayer( layer );
1283+
1284+
// save composition to template
1285+
QDomDocument doc;
1286+
doc.appendChild( c.writeXml( doc, QgsReadWriteContext() ) );
1287+
1288+
// new project
1289+
QgsProject p2;
1290+
QgsVectorLayer *layer2 = new QgsVectorLayer( vectorFileInfo.filePath(),
1291+
vectorFileInfo.completeBaseName(),
1292+
QStringLiteral( "ogr" ) );
1293+
p2.addMapLayer( layer2 );
1294+
1295+
// make a new layout from template
1296+
QgsPrintLayout c2( &p2 );
1297+
c2.loadFromTemplate( doc, QgsReadWriteContext() );
1298+
// get legend from new composition
1299+
QList< QgsLayoutItemMap * > maps2;
1300+
c2.layoutItems( maps2 );
1301+
QgsLayoutItemMap *map2 = maps2.at( 0 );
1302+
QVERIFY( map2 );
1303+
1304+
QCOMPARE( map2->overview()->stackingLayer(), layer2 );
1305+
}
1306+
12671307

12681308
QGSTEST_MAIN( TestQgsLayout )
12691309
#include "testqgslayout.moc"

‎tests/src/python/test_qgslayoutmapoverview.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from qgis.PyQt.QtGui import QPainter
2121

2222
from qgis.core import (QgsLayoutItemMap,
23+
QgsLayoutItemMapItem,
2324
QgsRectangle,
2425
QgsRasterLayer,
2526
QgsVectorLayer,
@@ -217,6 +218,25 @@ def testAsMapLayer(self):
217218
layer = overviewMap.overview().asMapLayer()
218219
self.assertEqual([f.geometry().asWkt(0) for f in layer.getFeatures()], ['Polygon ((-53 -128, 128 53, 309 -128, 128 -309, -53 -128),(93 -129, 101 -160, 163 -143, 155 -112, 93 -129))'])
219220

221+
def test_StackingPosition(self):
222+
l = QgsLayout(QgsProject.instance())
223+
l.initializeDefaults()
224+
225+
overviewMap = QgsLayoutItemMap(l)
226+
overviewMap.attemptSetSceneRect(QRectF(20, 130, 70, 70))
227+
l.addLayoutItem(overviewMap)
228+
overviewMap.overview().setStackingPosition(QgsLayoutItemMapItem.StackBelowMap)
229+
self.assertEqual(overviewMap.overview().stackingPosition(), QgsLayoutItemMapItem.StackBelowMap)
230+
overviewMap.overview().setStackingPosition(QgsLayoutItemMapItem.StackBelowMapLayer)
231+
self.assertEqual(overviewMap.overview().stackingPosition(), QgsLayoutItemMapItem.StackBelowMapLayer)
232+
233+
overviewMap.overview().setStackingLayer(self.raster_layer)
234+
self.assertEqual(overviewMap.overview().stackingLayer(), self.raster_layer)
235+
overviewMap.overview().setStackingLayer(self.vector_layer)
236+
self.assertEqual(overviewMap.overview().stackingLayer(), self.vector_layer)
237+
overviewMap.overview().setStackingLayer(None)
238+
self.assertIsNone(overviewMap.overview().stackingLayer())
239+
220240

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

0 commit comments

Comments
 (0)
Please sign in to comment.