Skip to content
Permalink
Browse files
Fix tests
  • Loading branch information
m-kuhn committed Mar 23, 2017
1 parent f33aabd commit baa4c86262ab4276c75dcaa4a85cf48152bad732
@@ -3,20 +3,22 @@ class QgsLayerTree : QgsLayerTreeGroup
%TypeHeaderCode
#include <qgslayertree.h>
%End
static bool isGroup( QgsLayerTreeNode *node );
static bool isLayer( const QgsLayerTreeNode *node );

//! Cast node to a group. No type checking is done - use isGroup() to find out whether this operation is legal.
// PYTHON: automatic cast
//inline QgsLayerTreeGroup* toGroup( QgsLayerTreeNode* node );
public:
static bool isGroup( QgsLayerTreeNode *node );
static bool isLayer( const QgsLayerTreeNode *node );

//! Cast node to a layer. No type checking is done - use isLayer() to find out whether this operation is legal.
// PYTHON: automatic cast
//inline QgsLayerTreeLayer* toLayer( QgsLayerTreeNode* node );
//! Cast node to a group. No type checking is done - use isGroup() to find out whether this operation is legal.
// PYTHON: automatic cast
//inline QgsLayerTreeGroup* toGroup( QgsLayerTreeNode* node );

//! Cast node to a layer. No type checking is done - use isLayer() to find out whether this operation is legal.
// PYTHON: automatic cast
//inline QgsLayerTreeLayer* toLayer( QgsLayerTreeNode* node );

QList<QgsMapLayer *> customLayerOrder() const;
void setCustomLayerOrder( const QList<QgsMapLayer *> &customLayerOrder );
void setCustomLayerOrder( const QStringList &customLayerOrder );
void setCustomLayerOrder( const QStringList &customLayerOrder ) /PyName=setCustomLayerOrderByIds/;
QList<QgsMapLayer *> layerOrder() const;
bool hasCustomLayerOrder() const;
void setHasCustomLayerOrder( bool hasCustomLayerOrder );
@@ -51,6 +51,8 @@ class QgsLayerTreeNode : QObject
QgsLayerTreeNode* node = qobject_cast<QgsLayerTreeNode*>(sipCpp);
if (QgsLayerTree::isLayer(node))
sipType = sipType_QgsLayerTreeLayer;
else if (qobject_cast<QgsLayerTree*>(sipCpp))
sipType = sipType_QgsLayerTree;
else if (QgsLayerTree::isGroup(node))
sipType = sipType_QgsLayerTreeGroup;
}
@@ -418,46 +418,6 @@ bool QgsComposerLegend::writeXml( QDomElement &elem, QDomDocument &doc ) const
return _writeXml( composerLegendElem, doc );
}

static void _readOldLegendGroup( QDomElement &elem, QgsLayerTreeGroup *parentGroup, QgsProject *project )
{
QDomElement itemElem = elem.firstChildElement();

while ( !itemElem.isNull() )
{

if ( itemElem.tagName() == QLatin1String( "LayerItem" ) )
{
QString layerId = itemElem.attribute( QStringLiteral( "layerId" ) );
if ( QgsMapLayer *layer = project->mapLayer( layerId ) )
{
QgsLayerTreeLayer *nodeLayer = parentGroup->addLayer( layer );
QString userText = itemElem.attribute( QStringLiteral( "userText" ) );
if ( !userText.isEmpty() )
nodeLayer->setCustomProperty( QStringLiteral( "legend/title-label" ), userText );
QString style = itemElem.attribute( QStringLiteral( "style" ) );
if ( !style.isEmpty() )
nodeLayer->setCustomProperty( QStringLiteral( "legend/title-style" ), style );
QString showFeatureCount = itemElem.attribute( QStringLiteral( "showFeatureCount" ) );
if ( showFeatureCount.toInt() )
nodeLayer->setCustomProperty( QStringLiteral( "showFeatureCount" ), 1 );

// support for individual legend items (user text, order) not implemented yet
}
}
else if ( itemElem.tagName() == QLatin1String( "GroupItem" ) )
{
QgsLayerTreeGroup *nodeGroup = parentGroup->addGroup( itemElem.attribute( QStringLiteral( "userText" ) ) );
QString style = itemElem.attribute( QStringLiteral( "style" ) );
if ( !style.isEmpty() )
nodeGroup->setCustomProperty( QStringLiteral( "legend/title-style" ), style );

_readOldLegendGroup( itemElem, nodeGroup, project );
}

itemElem = itemElem.nextSiblingElement();
}
}

bool QgsComposerLegend::readXml( const QDomElement &itemElem, const QDomDocument &doc )
{
if ( itemElem.isNull() )
@@ -58,6 +58,7 @@ class CORE_EXPORT QgsLayerTree : public QgsLayerTreeGroup
* Cast node to a group. No type checking is done - use isGroup() to find out whether this operation is legal.
*
* @note Added in QGIS 2.4
* @note Not available in python bindings, because cast is automatic.
*/
static inline QgsLayerTreeGroup *toGroup( QgsLayerTreeNode *node )
{
@@ -68,6 +69,7 @@ class CORE_EXPORT QgsLayerTree : public QgsLayerTreeGroup
* Cast node to a layer. No type checking is done - use isLayer() to find out whether this operation is legal.
*
* @note Added in QGIS 2.4
* @note Not available in python bindings, because cast is automatic.
*/
static inline QgsLayerTreeLayer *toLayer( QgsLayerTreeNode *node )
{
@@ -78,14 +80,21 @@ class CORE_EXPORT QgsLayerTree : public QgsLayerTreeGroup
* Cast node to a layer. No type checking is done - use isLayer() to find out whether this operation is legal.
*
* @note Added in QGIS 2.4
* @note Not available in python bindings, because cast is automatic.
*/
static inline const QgsLayerTreeLayer *toLayer( const QgsLayerTreeNode *node )
{
return static_cast< const QgsLayerTreeLayer *>( node );
}

//! Constructor
/**
* Create a new empty layer tree
*/
QgsLayerTree();

/**
* Copy constructor
*/
QgsLayerTree( const QgsLayerTree &other );

/**
@@ -64,6 +64,7 @@ ADD_PYTHON_TEST(PyQgsGraduatedSymbolRenderer test_qgsgraduatedsymbolrenderer.py)
ADD_PYTHON_TEST(PyQgsInterval test_qgsinterval.py)
ADD_PYTHON_TEST(PyQgsJSONUtils test_qgsjsonutils.py)
ADD_PYTHON_TEST(PyQgsLayerTreeMapCanvasBridge test_qgslayertreemapcanvasbridge.py)
ADD_PYTHON_TEST(PyQgsLayerTree test_qgslayertree.py)
ADD_PYTHON_TEST(PyQgsLayoutManager test_qgslayoutmanager.py)
ADD_PYTHON_TEST(PyQgsLineSymbolLayers test_qgslinesymbollayers.py)
ADD_PYTHON_TEST(PyQgsMapCanvas test_qgsmapcanvas.py)
@@ -0,0 +1,83 @@
# -*- coding: utf-8 -*-
"""QGIS Unit tests for QgsLayerTree.
.. note:: This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
"""
__author__ = 'Matthias Kuhn'
__date__ = '22.3.2017'
__copyright__ = 'Copyright 2017, The QGIS Project'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'

import qgis # NOQA

import os

from qgis.core import (
QgsLayerTree,
QgsProject,
QgsVectorLayer
)
from qgis.testing import start_app, unittest
from utilities import (unitTestDataPath)
from qgis.PyQt.QtTest import QSignalSpy
from qgis.PyQt.QtCore import QDir

app = start_app()
TEST_DATA_DIR = unitTestDataPath()


class TestQgsLayerTree(unittest.TestCase):

def __init__(self, methodName):
"""Run once on class initialization."""
unittest.TestCase.__init__(self, methodName)

def testCustomLayerOrder(self):
""" test project layer order"""
prj = QgsProject()
layer = QgsVectorLayer("Point?field=fldtxt:string",
"layer1", "memory")
layer2 = QgsVectorLayer("Point?field=fldtxt:string",
"layer2", "memory")
layer3 = QgsVectorLayer("Point?field=fldtxt:string",
"layer3", "memory")
prj.addMapLayers([layer, layer2, layer3])

layer_order_changed_spy = QSignalSpy(prj.layerTreeRoot().customLayerOrderChanged)
prj.layerTreeRoot().setCustomLayerOrder([layer2, layer])
self.assertEqual(len(layer_order_changed_spy), 1)
prj.layerTreeRoot().setCustomLayerOrder([layer2, layer])
self.assertEqual(len(layer_order_changed_spy), 1) # no signal, order not changed

self.assertEqual(prj.layerTreeRoot().customLayerOrder(), [layer2, layer])
prj.layerTreeRoot().setCustomLayerOrder([layer])
self.assertEqual(prj.layerTreeRoot().customLayerOrder(), [layer])
self.assertEqual(len(layer_order_changed_spy), 2)

# remove a layer
prj.layerTreeRoot().setCustomLayerOrder([layer2, layer, layer3])
self.assertEqual(len(layer_order_changed_spy), 3)
prj.removeMapLayer(layer)
self.assertEqual(prj.layerTreeRoot().customLayerOrder(), [layer2, layer3])
self.assertEqual(len(layer_order_changed_spy), 4)

# save and restore
file_name = os.path.join(QDir.tempPath(), 'proj.qgs')
prj.setFileName(file_name)
prj.write()
prj2 = QgsProject()
prj2.setFileName(file_name)
prj2.read()
self.assertEqual([l.id() for l in prj2.layerTreeRoot().customLayerOrder()], [layer2.id(), layer3.id()])

# clear project
prj.clear()
self.assertEqual(prj.layerTreeRoot().customLayerOrder(), [])


if __name__ == '__main__':
unittest.main()
@@ -54,32 +54,34 @@ def testLayerOrderUpdatedThroughBridge(self):
bridge = QgsLayerTreeMapCanvasBridge(prj.layerTreeRoot(), canvas)

#custom layer order
bridge.setHasCustomLayerOrder(True)
bridge.setCustomLayerOrder([layer3.id(), layer.id(), layer2.id()])
prj.layerTreeRoot().setHasCustomLayerOrder(True)
prj.layerTreeRoot().setCustomLayerOrder([layer3, layer, layer2])
app.processEvents()
self.assertEqual([l.id() for l in prj.layerOrder()], [layer3.id(), layer.id(), layer2.id()])
self.assertEqual([l for l in prj.layerTreeRoot().customLayerOrder()], [layer3, layer, layer2])
self.assertEqual([l for l in prj.layerTreeRoot().layerOrder()], [layer3, layer, layer2])

# no custom layer order
bridge.setHasCustomLayerOrder(False)
prj.layerTreeRoot().setHasCustomLayerOrder(False)
app.processEvents()
self.assertEqual([l.id() for l in prj.layerOrder()], [layer.id(), layer2.id(), layer3.id()])
self.assertEqual([l for l in prj.layerTreeRoot().customLayerOrder()], [layer3, layer, layer2])
self.assertEqual([l for l in prj.layerTreeRoot().layerOrder()], [layer, layer2, layer3])

# mess around with the layer tree order
root = prj.layerTreeRoot()
layer_node = root.findLayer(layer2.id())
layer_node = root.findLayer(layer2)
cloned_node = layer_node.clone()
parent = layer_node.parent()
parent.insertChildNode(0, cloned_node)
parent.removeChildNode(layer_node)
app.processEvents()
# make sure project respects this
self.assertEqual([l.id() for l in prj.layerOrder()], [layer2.id(), layer.id(), layer3.id()])
self.assertEqual([l for l in prj.layerTreeRoot().layerOrder()], [layer2, layer, layer3])

# make sure project order includes ALL layers, not just visible ones
layer_node = root.findLayer(layer.id())
layer_node = root.findLayer(layer)
layer_node.setItemVisibilityChecked(False)
app.processEvents()
self.assertEqual([l.id() for l in prj.layerOrder()], [layer2.id(), layer.id(), layer3.id()])
self.assertEqual([l for l in prj.layerTreeRoot().layerOrder()], [layer2, layer, layer3])

def testCustomLayerOrderUpdatedFromProject(self):
""" test that setting project layer order is reflected in custom layer order panel """
@@ -99,37 +101,35 @@ def testCustomLayerOrderUpdatedFromProject(self):
custom_order_widget = QgsCustomLayerOrderWidget(bridge)

#custom layer order
bridge.setHasCustomLayerOrder(True)
bridge.setCustomLayerOrder([layer3.id(), layer.id(), layer2.id()])
prj.layerTreeRoot().setHasCustomLayerOrder(True)
prj.layerTreeRoot().setCustomLayerOrder([layer3, layer, layer2])
app.processEvents()
self.assertEqual([l.id() for l in prj.layerOrder()], [layer3.id(), layer.id(), layer2.id()])
self.assertEqual([l for l in prj.layerTreeRoot().customLayerOrder()], [layer3, layer, layer2])

# no custom layer order
bridge.setHasCustomLayerOrder(False)
prj.layerTreeRoot().setHasCustomLayerOrder(False)
app.processEvents()
self.assertEqual([l.id() for l in prj.layerOrder()], [layer.id(), layer2.id(), layer3.id()])
self.assertEqual([l for l in prj.layerTreeRoot().layerOrder()], [layer, layer2, layer3])

# mess around with the project layer order
prj.setLayerOrder([layer3, layer, layer2])
prj.layerTreeRoot().setCustomLayerOrder([layer3, layer, layer2])
app.processEvents()
# make sure bridge respects this new order
self.assertTrue(bridge.hasCustomLayerOrder())
self.assertEqual(bridge.customLayerOrder(), [layer3.id(), layer.id(), layer2.id()])
self.assertEqual(prj.layerTreeRoot().layerOrder(), [layer, layer2, layer3])

# try reordering through bridge
bridge.setHasCustomLayerOrder(False)
prj.layerTreeRoot().setHasCustomLayerOrder(False)
app.processEvents()
self.assertEqual([l.id() for l in prj.layerOrder()], [layer.id(), layer2.id(), layer3.id()])
self.assertEqual([l for l in prj.layerTreeRoot().layerOrder()], [layer, layer2, layer3])
root = prj.layerTreeRoot()
layer_node = root.findLayer(layer2.id())
layer_node = root.findLayer(layer2)
cloned_node = layer_node.clone()
parent = layer_node.parent()
parent.insertChildNode(0, cloned_node)
parent.removeChildNode(layer_node)
app.processEvents()
# make sure project respects this
self.assertEqual([l.id() for l in prj.layerOrder()], [layer2.id(), layer.id(), layer3.id()])
self.assertFalse(bridge.hasCustomLayerOrder())
self.assertEqual([l for l in prj.layerTreeRoot().layerOrder()], [layer2, layer, layer3])
self.assertFalse(prj.layerTreeRoot().hasCustomLayerOrder())


if __name__ == '__main__':
@@ -111,10 +111,11 @@ def testMasterLayerOrder(self):
"layer3", "memory")
prj.addMapLayers([layer, layer2, layer3])

prj.setLayerOrder([layer2, layer])
prj.layerTreeRoot().setHasCustomLayerOrder(True)
prj.layerTreeRoot().setCustomLayerOrder([layer2, layer])
self.assertEqual(prj.mapThemeCollection().masterLayerOrder(), [layer2, layer])

prj.setLayerOrder([layer, layer2, layer3])
prj.layerTreeRoot().setCustomLayerOrder([layer, layer2, layer3])
# make some themes...
theme1 = QgsMapThemeCollection.MapThemeRecord()
theme1.setLayerRecords([QgsMapThemeCollection.MapThemeLayerRecord(layer3),
@@ -144,7 +145,7 @@ def testMasterLayerOrder(self):
self.assertEqual(prj.mapThemeCollection().mapThemeVisibleLayerIds('theme3'), [layer.id(), layer2.id()])

# reset master order
prj.setLayerOrder([layer2, layer3, layer])
prj.layerTreeRoot().setCustomLayerOrder([layer2, layer3, layer])
self.assertEqual(prj.mapThemeCollection().mapThemeVisibleLayers('theme1'), [layer3, layer])
self.assertEqual(prj.mapThemeCollection().mapThemeVisibleLayers('theme2'), [layer2, layer3, layer])
self.assertEqual(prj.mapThemeCollection().mapThemeVisibleLayers('theme3'), [layer2, layer])
@@ -159,6 +160,7 @@ def testMasterLayerOrder(self):
layer_node = root.findLayer(layer2.id())
layer_node.setItemVisibilityChecked(False)
app.processEvents()
prj.layerTreeRoot().setHasCustomLayerOrder(False)
self.assertEqual(prj.mapThemeCollection().masterLayerOrder(), [layer, layer2, layer3])

self.assertEqual(prj.mapThemeCollection().mapThemeVisibleLayers('theme1'), [layer, layer3])
@@ -169,12 +171,6 @@ def testMasterLayerOrder(self):
[layer.id(), layer2.id(), layer3.id()])
self.assertEqual(prj.mapThemeCollection().mapThemeVisibleLayerIds('theme3'), [layer.id(), layer2.id()])

# no layer order - should use stored order as a last resort
prj.setLayerOrder([])
self.assertEqual(prj.mapThemeCollection().mapThemeVisibleLayers('theme1'), [layer3, layer])
self.assertEqual(prj.mapThemeCollection().mapThemeVisibleLayers('theme2'), [layer3, layer2, layer])
self.assertEqual(prj.mapThemeCollection().mapThemeVisibleLayers('theme3'), [layer2, layer])

def testMasterVisibleLayers(self):
""" test master visible layers"""
prj = QgsProject.instance()
@@ -188,9 +184,10 @@ def testMasterVisibleLayers(self):
prj.addMapLayers([layer, layer2, layer3])

# general setup...
prj.setLayerOrder([layer2, layer])
prj.layerTreeRoot().setHasCustomLayerOrder(True)
prj.layerTreeRoot().setCustomLayerOrder([layer2, layer])
self.assertEqual(prj.mapThemeCollection().masterVisibleLayers(), [layer2, layer])
prj.setLayerOrder([layer3, layer, layer2])
prj.layerTreeRoot().setCustomLayerOrder([layer3, layer, layer2])
self.assertEqual(prj.mapThemeCollection().masterVisibleLayers(), [layer3, layer, layer2])

#hide some layers
@@ -201,11 +198,11 @@ def testMasterVisibleLayers(self):
layer_node.setItemVisibilityChecked(True)
self.assertEqual(prj.mapThemeCollection().masterVisibleLayers(), [layer3, layer, layer2])
layer_node.setItemVisibilityChecked(False)
prj.setLayerOrder([layer, layer2, layer3])
prj.layerTreeRoot().setCustomLayerOrder([layer, layer2, layer3])
self.assertEqual(prj.mapThemeCollection().masterVisibleLayers(), [layer, layer3])

# test with no project layer order set, should respect tree order
prj.setLayerOrder([])
prj.layerTreeRoot().setCustomLayerOrder([])
self.assertEqual(prj.mapThemeCollection().masterVisibleLayers(), [layer, layer3])
layer_node.setItemVisibilityChecked(True)
self.assertEqual(prj.mapThemeCollection().masterVisibleLayers(), [layer, layer2, layer3])

0 comments on commit baa4c86

Please sign in to comment.