Skip to content

Commit

Permalink
[layouts] Add setters/getters for map item stacking positions
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Jan 2, 2019
1 parent 6eb49fe commit 1b309c6
Show file tree
Hide file tree
Showing 5 changed files with 219 additions and 2 deletions.
65 changes: 64 additions & 1 deletion python/core/auto_generated/layout/qgslayoutitemmapitem.sip.in
Expand Up @@ -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``.
Expand Down Expand Up @@ -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:
Expand All @@ -119,9 +182,9 @@ Returns true if the item is drawn using advanced effects, such as blend modes.



};


};

class QgsLayoutItemMapItemStack
{
Expand Down
31 changes: 31 additions & 0 deletions src/core/layout/qgslayoutitemmapitem.cpp
Expand Up @@ -17,6 +17,7 @@

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

QgsLayoutItemMapItem::QgsLayoutItemMapItem( const QString &name, QgsLayoutItemMap *map )
Expand All @@ -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;
}

Expand All @@ -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;
}

Expand Down Expand Up @@ -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
//
Expand Down
65 changes: 64 additions & 1 deletion src/core/layout/qgslayoutitemmapitem.h
Expand Up @@ -20,6 +20,7 @@
#include "qgis_core.h"
#include "qgis_sip.h"
#include "qgslayoutobject.h"
#include "qgsmaplayerref.h"

class QgsLayoutItemMap;

Expand All @@ -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.
*
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
40 changes: 40 additions & 0 deletions tests/src/core/testqgslayout.cpp
Expand Up @@ -69,6 +69,7 @@ class TestQgsLayout: public QObject
void mapLayersRestoredFromTemplate();
void mapLayersStyleOverrideRestoredFromTemplate();
void atlasLayerRestoredFromTemplate();
void overviewStackingLayerRestoredFromTemplate();

private:
QString mReport;
Expand Down Expand Up @@ -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 changes: 20 additions & 0 deletions tests/src/python/test_qgslayoutmapoverview.py
Expand Up @@ -20,6 +20,7 @@
from qgis.PyQt.QtGui import QPainter

from qgis.core import (QgsLayoutItemMap,
QgsLayoutItemMapItem,
QgsRectangle,
QgsRasterLayer,
QgsVectorLayer,
Expand Down Expand Up @@ -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.