Skip to content

Commit

Permalink
Move containsAdvancedEffects test to QgsLayoutItem
Browse files Browse the repository at this point in the history
And start a generic test library for all item types to ensure
correct behavior for QgsLayoutItem subclasses

Currently justs tests to ensure that overriden
containsAdvancedEffects methods also call the base class
test
  • Loading branch information
nyalldawson committed Dec 17, 2017
1 parent 0110b43 commit a59dce5
Show file tree
Hide file tree
Showing 17 changed files with 226 additions and 10 deletions.
10 changes: 10 additions & 0 deletions python/core/layout/qgslayoutitem.sip
Expand Up @@ -820,6 +820,16 @@ Sets whether the item should be excluded from composer exports and prints.
.. seealso:: :py:func:`excludeFromExports()`
%End

virtual bool containsAdvancedEffects() const;
%Docstring
Returns true if the item contains contents with blend modes or transparency
effects which can only be reproduced by rastering the item.

Subclasses should ensure that implemented overrides of this method
also check the base class result.
:rtype: bool
%End

virtual double estimatedFrameBleed() const;
%Docstring
Returns the estimated amount the item's frame bleeds outside the item's
Expand Down
5 changes: 5 additions & 0 deletions src/core/layout/qgslayoutitem.cpp
Expand Up @@ -840,6 +840,11 @@ void QgsLayoutItem::setExcludeFromExports( bool exclude )
refreshDataDefinedProperty( QgsLayoutObject::ExcludeFromExports );
}

bool QgsLayoutItem::containsAdvancedEffects() const
{
return blendMode() != QPainter::CompositionMode_SourceOver;
}

double QgsLayoutItem::estimatedFrameBleed() const
{
if ( !hasFrame() )
Expand Down
9 changes: 9 additions & 0 deletions src/core/layout/qgslayoutitem.h
Expand Up @@ -742,6 +742,15 @@ class CORE_EXPORT QgsLayoutItem : public QgsLayoutObject, public QGraphicsRectIt
*/
void setExcludeFromExports( bool exclude );

/**
* Returns true if the item contains contents with blend modes or transparency
* effects which can only be reproduced by rastering the item.
*
* Subclasses should ensure that implemented overrides of this method
* also check the base class result.
*/
virtual bool containsAdvancedEffects() const;

/**
* Returns the estimated amount the item's frame bleeds outside the item's
* actual rectangle. For instance, if the item has a 2mm frame stroke, then
Expand Down
3 changes: 3 additions & 0 deletions src/core/layout/qgslayoutitemmap.cpp
Expand Up @@ -379,6 +379,9 @@ bool QgsLayoutItemMap::containsWmsLayer() const

bool QgsLayoutItemMap::containsAdvancedEffects() const
{
if ( QgsLayoutItem::containsAdvancedEffects() )
return true;

//check easy things first

//overviews
Expand Down
4 changes: 1 addition & 3 deletions src/core/layout/qgslayoutitemmap.h
Expand Up @@ -91,7 +91,6 @@ class CORE_EXPORT QgsLayoutItemMap : public QgsLayoutItem
int numberExportLayers() const override;
void setFrameStrokeWidth( const QgsLayoutMeasurement &width ) override;


/**
* Returns the map scale.
* The scale value indicates the scale denominator, e.g. 1000.0 for a 1:1000 map.
Expand Down Expand Up @@ -276,8 +275,7 @@ class CORE_EXPORT QgsLayoutItemMap : public QgsLayoutItem
//! Returns true if the map contains a WMS layer.
bool containsWmsLayer() const;

//! Returns true if the map contains layers with blend modes or flattened layers for vectors
bool containsAdvancedEffects() const;
bool containsAdvancedEffects() const override;

/**
* Sets the \a rotation for the map - this does not affect the composer item shape, only the
Expand Down
4 changes: 4 additions & 0 deletions tests/src/python/CMakeLists.txt
Expand Up @@ -84,6 +84,7 @@ ADD_PYTHON_TEST(PyQgsLayerTree test_qgslayertree.py)
ADD_PYTHON_TEST(PyQgsLayout test_qgslayout.py)
ADD_PYTHON_TEST(PyQgsLayoutAlign test_qgslayoutaligner.py)
ADD_PYTHON_TEST(PyQgsLayoutExporter test_qgslayoutexporter.py)
ADD_PYTHON_TEST(PyQgsLayoutFrame test_qgslayoutframe.py)
ADD_PYTHON_TEST(PyQgsLayoutManager test_qgslayoutmanager.py)
ADD_PYTHON_TEST(PyQgsLayoutPageCollection test_qgslayoutpagecollection.py)
ADD_PYTHON_TEST(PyQgsLayoutView test_qgslayoutview.py)
Expand All @@ -96,9 +97,12 @@ ADD_PYTHON_TEST(PyQgsLayoutLabel test_qgslayoutlabel.py)
ADD_PYTHON_TEST(PyQgsLayoutLegend test_qgslayoutlegend.py)
ADD_PYTHON_TEST(PyQgsLayoutMap test_qgslayoutmap.py)
ADD_PYTHON_TEST(PyQgsLayoutMapGrid test_qgslayoutmapgrid.py)
ADD_PYTHON_TEST(PyQgsLayoutPage test_qgslayoutpage.py)
ADD_PYTHON_TEST(PyQgsLayoutPicture test_qgslayoutpicture.py)
ADD_PYTHON_TEST(PyQgsLayoutPolygon test_qgslayoutpolygon.py)
ADD_PYTHON_TEST(PyQgsLayoutPolyline test_qgslayoutpolyline.py)
ADD_PYTHON_TEST(PyQgsLayoutScaleBar test_qgslayoutscalebar.py)
ADD_PYTHON_TEST(PyQgsLayoutShape test_qgslayoutshape.py)
ADD_PYTHON_TEST(PyQgsLayoutSnapper test_qgslayoutsnapper.py)
ADD_PYTHON_TEST(PyQgsLayoutUnitsComboBox test_qgslayoutunitscombobox.py)
ADD_PYTHON_TEST(PyQgsLineSymbolLayers test_qgslinesymbollayers.py)
Expand Down
38 changes: 38 additions & 0 deletions tests/src/python/test_qgslayoutframe.py
@@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-
"""QGIS Unit tests for QgsLayoutFrame.
.. 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__ = '(C) 2017 by Nyall Dawson'
__date__ = '23/10/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

from qgis.testing import start_app, unittest
from qgis.core import QgsLayoutFrame, QgsLayoutItemHtml

from test_qgslayoutitem import LayoutItemTestCase

start_app()


class TestQgsLayoutFrame(unittest.TestCase, LayoutItemTestCase):

@classmethod
def setUpClass(cls):
cls.mf = None

@classmethod
def createItem(cls, layout):
cls.mf = QgsLayoutItemHtml(layout)
return QgsLayoutFrame(layout, cls.mf)


if __name__ == '__main__':
unittest.main()
23 changes: 22 additions & 1 deletion tests/src/python/test_qgslayoutitem.py
Expand Up @@ -26,13 +26,34 @@
QgsLayoutSize,
QgsApplication)
from qgis.PyQt.QtCore import QRectF
from qgis.PyQt.QtGui import QColor
from qgis.PyQt.QtGui import QColor, QPainter
from qgis.PyQt.QtTest import QSignalSpy


start_app()


class LayoutItemTestCase(object):

'''
This is a collection of generic tests for QgsLayoutItem subclasses.
To make use of it, subclass it and set self.item_class to a QgsLayoutItem subclass you want to test.
'''

def make_item(self, layout):
if hasattr(self, 'item_class'):
return self.item_class(layout)
else:
return self.createItem(layout)

def testContainsAdvancedEffects(self):
l = QgsLayout(QgsProject.instance())
item = self.make_item(l)
self.assertFalse(item.containsAdvancedEffects())
item.setBlendMode(QPainter.CompositionMode_SourceIn)
self.assertTrue(item.containsAdvancedEffects())


class TestQgsLayoutItem(unittest.TestCase):

def testDataDefinedFrameColor(self):
Expand Down
7 changes: 6 additions & 1 deletion tests/src/python/test_qgslayoutlabel.py
Expand Up @@ -19,11 +19,16 @@
from qgis.core import QgsVectorLayer, QgsLayout, QgsLayoutItemLabel, QgsProject
from utilities import unitTestDataPath

from test_qgslayoutitem import LayoutItemTestCase

start_app()


class TestQgsLayoutItemLabel(unittest.TestCase):
class TestQgsLayoutItemLabel(unittest.TestCase, LayoutItemTestCase):

@classmethod
def setUpClass(cls):
cls.item_class = QgsLayoutItemLabel

def testCase(self):
TEST_DATA_DIR = unitTestDataPath()
Expand Down
8 changes: 7 additions & 1 deletion tests/src/python/test_qgslayoutlegend.py
Expand Up @@ -34,11 +34,17 @@
from qgslayoutchecker import QgsLayoutChecker
import os

from test_qgslayoutitem import LayoutItemTestCase

start_app()
TEST_DATA_DIR = unitTestDataPath()


class TestQgsLayoutItemLegend(unittest.TestCase):
class TestQgsLayoutItemLegend(unittest.TestCase, LayoutItemTestCase):

@classmethod
def setUpClass(cls):
cls.item_class = QgsLayoutItemLegend

def testInitialSizeSymbolMapUnits(self):
"""Test initial size of legend with a symbol size in map units"""
Expand Down
7 changes: 6 additions & 1 deletion tests/src/python/test_qgslayoutmap.py
Expand Up @@ -34,12 +34,17 @@
from qgis.testing import start_app, unittest
from utilities import unitTestDataPath
from qgslayoutchecker import QgsLayoutChecker
from test_qgslayoutitem import LayoutItemTestCase

start_app()
TEST_DATA_DIR = unitTestDataPath()


class TestQgsComposerMap(unittest.TestCase):
class TestQgsComposerMap(unittest.TestCase, LayoutItemTestCase):

@classmethod
def setUpClass(cls):
cls.item_class = QgsLayoutItemMap

def __init__(self, methodName):
"""Run once on class initialization."""
Expand Down
33 changes: 33 additions & 0 deletions tests/src/python/test_qgslayoutpage.py
@@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
"""QGIS Unit tests for QgsLayoutItemPage.
.. 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__ = '(C) 2017 by Nyall Dawson'
__date__ = '23/10/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

from qgis.testing import start_app, unittest
from qgis.core import QgsLayoutItemPage

from test_qgslayoutitem import LayoutItemTestCase

start_app()


class TestQgsLayoutPage(unittest.TestCase, LayoutItemTestCase):

@classmethod
def setUpClass(cls):
cls.item_class = QgsLayoutItemPage


if __name__ == '__main__':
unittest.main()
5 changes: 4 additions & 1 deletion tests/src/python/test_qgslayoutpicture.py
Expand Up @@ -30,15 +30,18 @@
from qgis.testing import start_app, unittest
from utilities import unitTestDataPath
from qgslayoutchecker import QgsLayoutChecker
from test_qgslayoutitem import LayoutItemTestCase

start_app()
TEST_DATA_DIR = unitTestDataPath()


class TestQgsLayoutPicture(unittest.TestCase):
class TestQgsLayoutPicture(unittest.TestCase, LayoutItemTestCase):

@classmethod
def setUpClass(cls):
cls.item_class = QgsLayoutItemPicture

# Bring up a simple HTTP server, for remote picture tests
os.chdir(unitTestDataPath() + '')
handler = http.server.SimpleHTTPRequestHandler
Expand Down
7 changes: 6 additions & 1 deletion tests/src/python/test_qgslayoutpolygon.py
Expand Up @@ -29,12 +29,17 @@
)
from utilities import unitTestDataPath
from qgslayoutchecker import QgsLayoutChecker
from test_qgslayoutitem import LayoutItemTestCase

start_app()
TEST_DATA_DIR = unitTestDataPath()


class TestQgsLayoutPolygon(unittest.TestCase):
class TestQgsLayoutPolygon(unittest.TestCase, LayoutItemTestCase):

@classmethod
def setUpClass(cls):
cls.item_class = QgsLayoutItemPolygon

def __init__(self, methodName):
"""Run once on class initialization."""
Expand Down
7 changes: 6 additions & 1 deletion tests/src/python/test_qgslayoutpolyline.py
Expand Up @@ -29,12 +29,17 @@
)
from utilities import unitTestDataPath
from qgslayoutchecker import QgsLayoutChecker
from test_qgslayoutitem import LayoutItemTestCase

start_app()
TEST_DATA_DIR = unitTestDataPath()


class TestQgsLayoutPolyline(unittest.TestCase):
class TestQgsLayoutPolyline(unittest.TestCase, LayoutItemTestCase):

@classmethod
def setUpClass(cls):
cls.item_class = QgsLayoutItemPolyline

def __init__(self, methodName):
"""Run once on class initialization."""
Expand Down
33 changes: 33 additions & 0 deletions tests/src/python/test_qgslayoutscalebar.py
@@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
"""QGIS Unit tests for QgsLayoutItemScaleBar.
.. 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__ = '(C) 2017 by Nyall Dawson'
__date__ = '23/10/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

from qgis.testing import start_app, unittest
from qgis.core import QgsLayoutItemScaleBar

from test_qgslayoutitem import LayoutItemTestCase

start_app()


class TestQgsLayoutScaleBar(unittest.TestCase, LayoutItemTestCase):

@classmethod
def setUpClass(cls):
cls.item_class = QgsLayoutItemScaleBar


if __name__ == '__main__':
unittest.main()
33 changes: 33 additions & 0 deletions tests/src/python/test_qgslayoutshape.py
@@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
"""QGIS Unit tests for QgsLayoutItemShape.
.. 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__ = '(C) 2017 by Nyall Dawson'
__date__ = '23/10/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

from qgis.testing import start_app, unittest
from qgis.core import QgsLayoutItemShape

from test_qgslayoutitem import LayoutItemTestCase

start_app()


class TestQgsLayoutShape(unittest.TestCase, LayoutItemTestCase):

@classmethod
def setUpClass(cls):
cls.item_class = QgsLayoutItemShape


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

0 comments on commit a59dce5

Please sign in to comment.