Skip to content
Permalink
Browse files

[layouts] Add setters/getters for map item stacking positions

  • Loading branch information
nyalldawson committed Dec 28, 2018
1 parent 6eb49fe commit 1b309c68100eba2fbd872aa8791e8e94c95473b7
@@ -22,6 +22,15 @@ An item which is drawn inside a QgsLayoutItemMap, e.g., a grid or map overview.
%End
public:

enum StackingPosition
{
StackBelowMap,
StackBelowMapLayer,
StackAboveMapLayer,
StackBelowMapLabels,
StackAboveMapLabels,
};

QgsLayoutItemMapItem( const QString &name, QgsLayoutItemMap *map );
%Docstring
Constructor for QgsLayoutItemMapItem, attached to the specified ``map``.
@@ -111,6 +120,60 @@ Returns whether the item will be drawn.
virtual bool usesAdvancedEffects() const;
%Docstring
Returns true if the item is drawn using advanced effects, such as blend modes.
%End

StackingPosition stackingPosition() const;
%Docstring
Returns the item's stacking position, which specifies where the in the map's
stack the item should be rendered.

.. seealso:: :py:func:`setStackingPosition`

.. seealso:: :py:func:`stackingLayer`

.. versionadded:: 3.6
%End

void setStackingPosition( StackingPosition position );
%Docstring
Sets the item's stacking ``position``, which specifies where the in the map's
stack the item should be rendered.

.. seealso:: :py:func:`stackingPosition`

.. seealso:: :py:func:`setStackingLayer`

.. versionadded:: 3.6
%End

QgsMapLayer *stackingLayer() const;
%Docstring
Returns the item's stacking layer, which specifies where the in the map's
stack the item should be rendered.

This setting is only used when stackingPosition() is StackBelowMapLayer or
StackAboveMapLayer.

.. seealso:: :py:func:`setStackingLayer`

.. seealso:: :py:func:`stackingPosition`

.. versionadded:: 3.6
%End

void setStackingLayer( QgsMapLayer *layer );
%Docstring
Sets the item's stacking ``layer``, which specifies where the in the map's
stack the item should be rendered.

This setting is only used when stackingPosition() is StackBelowMapLayer or
StackAboveMapLayer.

.. seealso:: :py:func:`stackingLayer`

.. seealso:: :py:func:`setStackingPosition`

.. versionadded:: 3.6
%End

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



};


};

class QgsLayoutItemMapItemStack
{
@@ -17,6 +17,7 @@

#include "qgslayoutitemmapitem.h"
#include "qgslayoutitemmap.h"
#include "qgslayout.h"
#include <QUuid>

QgsLayoutItemMapItem::QgsLayoutItemMapItem( const QString &name, QgsLayoutItemMap *map )
@@ -35,6 +36,16 @@ bool QgsLayoutItemMapItem::writeXml( QDomElement &element, QDomDocument &documen
element.setAttribute( QStringLiteral( "uuid" ), mUuid );
element.setAttribute( QStringLiteral( "name" ), mName );
element.setAttribute( QStringLiteral( "show" ), mEnabled );
element.setAttribute( QStringLiteral( "position" ), static_cast< int >( mStackingPosition ) );

if ( mStackingLayer )
{
element.setAttribute( QStringLiteral( "stackingLayer" ), mStackingLayer.layerId );
element.setAttribute( QStringLiteral( "stackingLayerName" ), mStackingLayer.name );
element.setAttribute( QStringLiteral( "stackingLayerSource" ), mStackingLayer.source );
element.setAttribute( QStringLiteral( "stackingLayerProvider" ), mStackingLayer.provider );
}

return true;
}

@@ -44,6 +55,16 @@ bool QgsLayoutItemMapItem::readXml( const QDomElement &itemElem, const QDomDocum
mUuid = itemElem.attribute( QStringLiteral( "uuid" ) );
mName = itemElem.attribute( QStringLiteral( "name" ) );
mEnabled = ( itemElem.attribute( QStringLiteral( "show" ), QStringLiteral( "0" ) ) != QLatin1String( "0" ) );
mStackingPosition = static_cast< StackingPosition >( itemElem.attribute( QStringLiteral( "position" ), QString::number( QgsLayoutItemMapItem::StackBelowMapLabels ) ).toInt() );

const QString layerId = itemElem.attribute( QStringLiteral( "stackingLayer" ) );
const QString layerName = itemElem.attribute( QStringLiteral( "stackingLayerName" ) );
const QString layerSource = itemElem.attribute( QStringLiteral( "stackingLayerSource" ) );
const QString layerProvider = itemElem.attribute( QStringLiteral( "stackingLayerProvider" ) );
mStackingLayer = QgsMapLayerRef( layerId, layerName, layerSource, layerProvider );
if ( mMap && mMap->layout() )
mStackingLayer.resolveWeakly( mMap->layout()->project() );

return true;
}

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

QgsMapLayer *QgsLayoutItemMapItem::stackingLayer() const
{
return mStackingLayer.get();
}

void QgsLayoutItemMapItem::setStackingLayer( QgsMapLayer *layer )
{
mStackingLayer.setLayer( layer );
}

//
// QgsLayoutItemMapItemStack
//
@@ -20,6 +20,7 @@
#include "qgis_core.h"
#include "qgis_sip.h"
#include "qgslayoutobject.h"
#include "qgsmaplayerref.h"

class QgsLayoutItemMap;

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

public:

//! Item stacking position, specifies where the in the map's stack the item should be rendered
enum StackingPosition
{
StackBelowMap, //!< Render below all map layers
StackBelowMapLayer, //!< Render below a specific map layer (see stackingLayer())
StackAboveMapLayer, //!< Render above a specific map layer (see stackingLayer())
StackBelowMapLabels, //!< Render above all map layers, but below map labels
StackAboveMapLabels, //!< Render above all map layers and labels
};

/**
* Constructor for QgsLayoutItemMapItem, attached to the specified \a map.
*
@@ -117,6 +128,56 @@ class CORE_EXPORT QgsLayoutItemMapItem : public QgsLayoutObject
*/
virtual bool usesAdvancedEffects() const;

/**
* Returns the item's stacking position, which specifies where the in the map's
* stack the item should be rendered.
*
* \see setStackingPosition()
* \see stackingLayer()
*
* \since QGIS 3.6
*/
StackingPosition stackingPosition() const { return mStackingPosition; }

/**
* Sets the item's stacking \a position, which specifies where the in the map's
* stack the item should be rendered.
*
* \see stackingPosition()
* \see setStackingLayer()
*
* \since QGIS 3.6
*/
void setStackingPosition( StackingPosition position ) { mStackingPosition = position; }

/**
* Returns the item's stacking layer, which specifies where the in the map's
* stack the item should be rendered.
*
* This setting is only used when stackingPosition() is StackBelowMapLayer or
* StackAboveMapLayer.
*
* \see setStackingLayer()
* \see stackingPosition()
*
* \since QGIS 3.6
*/
QgsMapLayer *stackingLayer() const;

/**
* Sets the item's stacking \a layer, which specifies where the in the map's
* stack the item should be rendered.
*
* This setting is only used when stackingPosition() is StackBelowMapLayer or
* StackAboveMapLayer.
*
* \see stackingLayer()
* \see setStackingPosition
*
* \since QGIS 3.6
*/
void setStackingLayer( QgsMapLayer *layer );

protected:

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

};
StackingPosition mStackingPosition = StackBelowMapLabels;

QgsMapLayerRef mStackingLayer;

};

/**
* \ingroup core
@@ -69,6 +69,7 @@ class TestQgsLayout: public QObject
void mapLayersRestoredFromTemplate();
void mapLayersStyleOverrideRestoredFromTemplate();
void atlasLayerRestoredFromTemplate();
void overviewStackingLayerRestoredFromTemplate();

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

void TestQgsLayout::overviewStackingLayerRestoredFromTemplate()
{
// load some layers
QFileInfo vectorFileInfo( QStringLiteral( TEST_DATA_DIR ) + "/points.shp" );
QgsVectorLayer *layer = new QgsVectorLayer( vectorFileInfo.filePath(),
vectorFileInfo.completeBaseName(),
QStringLiteral( "ogr" ) );
QgsProject p;
p.addMapLayer( layer );

QgsPrintLayout c( &p );
QgsLayoutItemMap *map = new QgsLayoutItemMap( &c );
map->attemptSetSceneRect( QRectF( 1, 1, 10, 10 ) );
c.addLayoutItem( map );
map->overview()->setStackingLayer( layer );

// save composition to template
QDomDocument doc;
doc.appendChild( c.writeXml( doc, QgsReadWriteContext() ) );

// new project
QgsProject p2;
QgsVectorLayer *layer2 = new QgsVectorLayer( vectorFileInfo.filePath(),
vectorFileInfo.completeBaseName(),
QStringLiteral( "ogr" ) );
p2.addMapLayer( layer2 );

// make a new layout from template
QgsPrintLayout c2( &p2 );
c2.loadFromTemplate( doc, QgsReadWriteContext() );
// get legend from new composition
QList< QgsLayoutItemMap * > maps2;
c2.layoutItems( maps2 );
QgsLayoutItemMap *map2 = maps2.at( 0 );
QVERIFY( map2 );

QCOMPARE( map2->overview()->stackingLayer(), layer2 );
}


QGSTEST_MAIN( TestQgsLayout )
#include "testqgslayout.moc"
@@ -20,6 +20,7 @@
from qgis.PyQt.QtGui import QPainter

from qgis.core import (QgsLayoutItemMap,
QgsLayoutItemMapItem,
QgsRectangle,
QgsRasterLayer,
QgsVectorLayer,
@@ -217,6 +218,25 @@ def testAsMapLayer(self):
layer = overviewMap.overview().asMapLayer()
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))'])

def test_StackingPosition(self):
l = QgsLayout(QgsProject.instance())
l.initializeDefaults()

overviewMap = QgsLayoutItemMap(l)
overviewMap.attemptSetSceneRect(QRectF(20, 130, 70, 70))
l.addLayoutItem(overviewMap)
overviewMap.overview().setStackingPosition(QgsLayoutItemMapItem.StackBelowMap)
self.assertEqual(overviewMap.overview().stackingPosition(), QgsLayoutItemMapItem.StackBelowMap)
overviewMap.overview().setStackingPosition(QgsLayoutItemMapItem.StackBelowMapLayer)
self.assertEqual(overviewMap.overview().stackingPosition(), QgsLayoutItemMapItem.StackBelowMapLayer)

overviewMap.overview().setStackingLayer(self.raster_layer)
self.assertEqual(overviewMap.overview().stackingLayer(), self.raster_layer)
overviewMap.overview().setStackingLayer(self.vector_layer)
self.assertEqual(overviewMap.overview().stackingLayer(), self.vector_layer)
overviewMap.overview().setStackingLayer(None)
self.assertIsNone(overviewMap.overview().stackingLayer())


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

0 comments on commit 1b309c6

Please sign in to comment.
You can’t perform that action at this time.