1
1
# -*- coding: utf-8 -*-
2
- """QGIS unit tests for QgsPalLabeling: label rendering output via composer
2
+ """QGIS unit tests for QgsPalLabeling: label rendering output via layout
3
3
4
- From build dir, run: ctest -R PyQgsPalLabelingComposer -V
4
+ From build dir, run: ctest -R PyQgsPalLabelingLayout -V
5
5
6
6
See <qgis-src-dir>/tests/testdata/labeling/README.rst for description.
7
7
28
28
from qgis .PyQt .QtPrintSupport import QPrinter
29
29
from qgis .PyQt .QtSvg import QSvgRenderer , QSvgGenerator
30
30
31
- from qgis .core import QgsComposition , QgsMapSettings , QgsProject , QgsComposerMap , QgsVectorLayerSimpleLabeling
31
+ from qgis .core import (QgsLayout ,
32
+ QgsLayoutItemPage ,
33
+ QgsLayoutSize ,
34
+ QgsLayoutItemMap ,
35
+ QgsLayoutExporter ,
36
+ QgsMapSettings ,
37
+ QgsProject ,
38
+ QgsVectorLayerSimpleLabeling )
32
39
33
40
34
41
from utilities import (
@@ -70,7 +77,7 @@ class OutputKind():
70
77
71
78
72
79
# noinspection PyShadowingNames
73
- class TestComposerBase (TestQgsPalLabeling ):
80
+ class TestLayoutBase (TestQgsPalLabeling ):
74
81
75
82
layer = None
76
83
""":type: QgsVectorLayer"""
@@ -94,7 +101,7 @@ def tearDownClass(cls):
94
101
95
102
def setUp (self ):
96
103
"""Run before each test."""
97
- super (TestComposerBase , self ).setUp ()
104
+ super (TestLayoutBase , self ).setUp ()
98
105
self ._TestImage = ''
99
106
# ensure per test map settings stay encapsulated
100
107
self ._TestMapSettings = self .cloneMapSettings (self ._MapSettings )
@@ -104,35 +111,37 @@ def setUp(self):
104
111
self ._ColorTols .clear ()
105
112
106
113
def _set_up_composition (self , width , height , dpi , engine_settings ):
107
- # set up composition and add map
108
- self ._c = QgsComposition (QgsProject .instance ())
109
- """:type: QgsComposition """
114
+ # set up layout and add map
115
+ self ._c = QgsLayout (QgsProject .instance ())
116
+ """:type: QgsLayout """
110
117
# self._c.setUseAdvancedEffects(False)
111
- self ._c .setPrintResolution (dpi )
118
+ self ._c .renderContext (). setDpi (dpi )
112
119
# 600 x 400 px = 211.67 x 141.11 mm @ 72 dpi
113
120
paperw = width * 25.4 / dpi
114
121
paperh = height * 25.4 / dpi
115
- self ._c .setPaperSize (paperw , paperh )
116
- # NOTE: do not use QgsComposerMap(self._c, 0, 0, paperw, paperh) since
122
+ page = QgsLayoutItemPage (self ._c )
123
+ page .attemptResize (QgsLayoutSize (paperw ,paperh ))
124
+ self ._c .pageCollection ().addPage (page )
125
+ # NOTE: do not use QgsLayoutItemMap(self._c, 0, 0, paperw, paperh) since
117
126
# it only takes integers as parameters and the composition will grow
118
127
# larger based upon union of item scene rectangles and a slight buffer
119
128
# see end of QgsComposition::compositionBounds()
120
129
# add map as small graphics item first, then set its scene QRectF later
121
- self ._cmap = QgsComposerMap (self ._c , 10 , 10 , 10 , 10 )
122
- """:type: QgsComposerMap"""
130
+ self ._cmap = QgsLayoutItemMap (self ._c )
131
+ self ._cmap .attemptSetSceneRect (QRectF (10 , 10 , 10 , 10 ))
132
+ """:type: QgsLayoutItemMap"""
123
133
self ._cmap .setFrameEnabled (False )
124
134
self ._cmap .setLayers (self ._TestMapSettings .layers ())
125
- self ._c .addComposerMap (self ._cmap )
135
+ self ._c .addLayoutItem (self ._cmap )
126
136
# now expand map to fill page and set its extent
127
- self ._cmap .setSceneRect (QRectF (0 , 0 , paperw , paperw ))
128
- self ._cmap .setNewExtent (self .aoiExtent ())
137
+ self ._cmap .attemptSetSceneRect (QRectF (0 , 0 , paperw , paperw ))
138
+ self ._cmap .setExtent (self .aoiExtent ())
129
139
# self._cmap.updateCachedImage()
130
- self ._c .setPlotStyle (QgsComposition .Print )
131
140
# composition takes labeling engine settings from project
132
141
QgsProject .instance ().setLabelingEngineSettings (engine_settings )
133
142
134
143
# noinspection PyUnusedLocal
135
- def _get_composer_image (self , width , height , dpi ):
144
+ def _get_layout_image (self , width , height , dpi ):
136
145
image = QImage (QSize (width , height ),
137
146
self ._TestMapSettings .outputImageFormat ())
138
147
image .fill (QColor (152 , 219 , 249 ).rgb ())
@@ -144,7 +153,8 @@ def _get_composer_image(self, width, height, dpi):
144
153
QPainter .Antialiasing ,
145
154
self ._TestMapSettings .testFlag (QgsMapSettings .Antialiasing )
146
155
)
147
- self ._c .renderPage (p , 0 )
156
+ exporter = QgsLayoutExporter (self ._c )
157
+ exporter .renderPage (p , 0 )
148
158
p .end ()
149
159
150
160
# image = self._c.printPageAsRaster(0)
@@ -161,9 +171,7 @@ def _get_composer_image(self, width, height, dpi):
161
171
162
172
return res , filepath
163
173
164
- def _get_composer_svg_image (self , width , height , dpi ):
165
- # from qgscomposer.cpp, QgsComposer::on_mActionExportAsSVG_triggered,
166
- # near end of function
174
+ def _get_layout_svg_image (self , width , height , dpi ):
167
175
svgpath = getTempfilePath ('svg' )
168
176
temp_size = os .path .getsize (svgpath )
169
177
@@ -176,7 +184,8 @@ def _get_composer_svg_image(self, width, height, dpi):
176
184
svg_g .setResolution (dpi )
177
185
178
186
sp = QPainter (svg_g )
179
- self ._c .renderPage (sp , 0 )
187
+ exporter = QgsLayoutExporter (self ._c )
188
+ exporter .renderPage (sp , 0 )
180
189
sp .end ()
181
190
182
191
if temp_size == os .path .getsize (svgpath ):
@@ -206,24 +215,25 @@ def _get_composer_svg_image(self, width, height, dpi):
206
215
207
216
return res , filepath
208
217
209
- def _get_composer_pdf_image (self , width , height , dpi ):
218
+ def _get_layout_pdf_image (self , width , height , dpi ):
210
219
pdfpath = getTempfilePath ('pdf' )
211
220
temp_size = os .path .getsize (pdfpath )
212
221
213
222
p = QPrinter ()
214
223
p .setOutputFormat (QPrinter .PdfFormat )
215
224
p .setOutputFileName (pdfpath )
216
- p .setPaperSize (QSizeF (self ._c .paperWidth () , self ._c .paperHeight ()),
225
+ p .setPaperSize (QSizeF (self ._c .pageCollection (). page ( 0 ). sizeWithUnits (). width () , self ._c .pageCollection (). page ( 0 ). sizeWithUnits (). height ()),
217
226
QPrinter .Millimeter )
218
227
p .setFullPage (True )
219
228
p .setColorMode (QPrinter .Color )
220
- p .setResolution (self ._c .printResolution ())
229
+ p .setResolution (self ._c .renderContext (). dpi ())
221
230
222
231
pdf_p = QPainter (p )
223
232
# page_mm = p.pageRect(QPrinter.Millimeter)
224
233
# page_px = p.pageRect(QPrinter.DevicePixel)
225
234
# self._c.render(pdf_p, page_px, page_mm)
226
- self ._c .renderPage (pdf_p , 0 )
235
+ exporter = QgsLayoutExporter (self ._c )
236
+ exporter .renderPage (pdf_p , 0 )
227
237
pdf_p .end ()
228
238
229
239
if temp_size == os .path .getsize (pdfpath ):
@@ -254,13 +264,13 @@ def _get_composer_pdf_image(self, width, height, dpi):
254
264
else :
255
265
return False , ''
256
266
257
- qDebug ("_get_composer_pdf_image call: {0}" .format (' ' .join (call )))
267
+ qDebug ("_get_layout_pdf_image call: {0}" .format (' ' .join (call )))
258
268
res = False
259
269
try :
260
270
subprocess .check_call (call )
261
271
res = True
262
272
except subprocess .CalledProcessError as e :
263
- qDebug ("_get_composer_pdf_image failed!\n "
273
+ qDebug ("_get_layout_pdf_image failed!\n "
264
274
"cmd: {0}\n "
265
275
"returncode: {1}\n "
266
276
"message: {2}" .format (e .cmd , e .returncode , e .message ))
@@ -271,17 +281,17 @@ def _get_composer_pdf_image(self, width, height, dpi):
271
281
272
282
return res , filepath
273
283
274
- def get_composer_output (self , kind ):
284
+ def get_layout_output (self , kind ):
275
285
ms = self ._TestMapSettings
276
286
osize = ms .outputSize ()
277
287
width , height , dpi = osize .width (), osize .height (), ms .outputDpi ()
278
288
self ._set_up_composition (width , height , dpi , ms .labelingEngineSettings ())
279
289
if kind == OutputKind .Svg :
280
- return self ._get_composer_svg_image (width , height , dpi )
290
+ return self ._get_layout_svg_image (width , height , dpi )
281
291
elif kind == OutputKind .Pdf :
282
- return self ._get_composer_pdf_image (width , height , dpi )
292
+ return self ._get_layout_pdf_image (width , height , dpi )
283
293
else : # OutputKind.Img
284
- return self ._get_composer_image (width , height , dpi )
294
+ return self ._get_layout_image (width , height , dpi )
285
295
286
296
# noinspection PyUnusedLocal
287
297
def checkTest (self , ** kwargs ):
@@ -296,8 +306,8 @@ def checkTest(self, **kwargs):
296
306
qDebug ('MapSettings type: {0}' .format (settings_type ))
297
307
qDebug (mapSettingsString (ms ))
298
308
299
- res_m , self ._TestImage = self .get_composer_output (self ._TestKind )
300
- self .assertTrue (res_m , 'Failed to retrieve/save output from composer ' )
309
+ res_m , self ._TestImage = self .get_layout_output (self ._TestKind )
310
+ self .assertTrue (res_m , 'Failed to retrieve/save output from layout ' )
301
311
self .saveControlImage (self ._TestImage )
302
312
mismatch = 0
303
313
if 'PAL_NO_MISMATCH' not in os .environ :
@@ -315,146 +325,146 @@ def checkTest(self, **kwargs):
315
325
imgpath = self ._TestImage ))
316
326
317
327
318
- class TestComposerPointBase ( TestComposerBase ):
328
+ class TestLayoutPointBase ( TestLayoutBase ):
319
329
320
330
@classmethod
321
331
def setUpClass (cls ):
322
- TestComposerBase .setUpClass ()
332
+ TestLayoutBase .setUpClass ()
323
333
cls .layer = TestQgsPalLabeling .loadFeatureLayer ('point' )
324
334
325
335
326
- class TestComposerImagePoint ( TestComposerPointBase , TestPointBase ):
336
+ class TestLayoutImagePoint ( TestLayoutPointBase , TestPointBase ):
327
337
328
338
def setUp (self ):
329
339
"""Run before each test."""
330
- super (TestComposerImagePoint , self ).setUp ()
340
+ super (TestLayoutImagePoint , self ).setUp ()
331
341
self ._TestKind = OutputKind .Img
332
342
self .configTest ('pal_composer' , 'sp_img' )
333
343
334
344
335
- class TestComposerImageVsCanvasPoint ( TestComposerPointBase , TestPointBase ):
345
+ class TestLayoutImageVsCanvasPoint ( TestLayoutPointBase , TestPointBase ):
336
346
337
347
def setUp (self ):
338
348
"""Run before each test."""
339
- super (TestComposerImageVsCanvasPoint , self ).setUp ()
349
+ super (TestLayoutImageVsCanvasPoint , self ).setUp ()
340
350
self ._TestKind = OutputKind .Img
341
351
self .configTest ('pal_canvas' , 'sp' )
342
352
343
353
344
- class TestComposerSvgPoint ( TestComposerPointBase , TestPointBase ):
354
+ class TestLayoutSvgPoint ( TestLayoutPointBase , TestPointBase ):
345
355
346
356
def setUp (self ):
347
357
"""Run before each test."""
348
- super (TestComposerSvgPoint , self ).setUp ()
358
+ super (TestLayoutSvgPoint , self ).setUp ()
349
359
self ._TestKind = OutputKind .Svg
350
360
self .configTest ('pal_composer' , 'sp_svg' )
351
361
352
362
353
- class TestComposerSvgVsComposerPoint ( TestComposerPointBase , TestPointBase ):
363
+ class TestLayoutSvgVsLayoutPoint ( TestLayoutPointBase , TestPointBase ):
354
364
355
365
"""
356
- Compare only to composer image, which is already compared to canvas point
366
+ Compare only to layout image, which is already compared to canvas point
357
367
"""
358
368
359
369
def setUp (self ):
360
370
"""Run before each test."""
361
- super (TestComposerSvgVsComposerPoint , self ).setUp ()
371
+ super (TestLayoutSvgVsLayoutPoint , self ).setUp ()
362
372
self ._TestKind = OutputKind .Svg
363
373
self .configTest ('pal_composer' , 'sp_img' )
364
374
self ._ColorTol = 4
365
375
366
376
367
- class TestComposerPdfPoint ( TestComposerPointBase , TestPointBase ):
377
+ class TestLayoutPdfPoint ( TestLayoutPointBase , TestPointBase ):
368
378
369
379
def setUp (self ):
370
380
"""Run before each test."""
371
- super (TestComposerPdfPoint , self ).setUp ()
381
+ super (TestLayoutPdfPoint , self ).setUp ()
372
382
self ._TestKind = OutputKind .Pdf
373
383
self .configTest ('pal_composer' , 'sp_pdf' )
374
384
375
385
376
- class TestComposerPdfVsComposerPoint ( TestComposerPointBase , TestPointBase ):
386
+ class TestLayoutPdfVsLayoutPoint ( TestLayoutPointBase , TestPointBase ):
377
387
378
388
"""
379
- Compare only to composer image, which is already compared to canvas point
389
+ Compare only to layout image, which is already compared to canvas point
380
390
"""
381
391
382
392
def setUp (self ):
383
393
"""Run before each test."""
384
- super (TestComposerPdfVsComposerPoint , self ).setUp ()
394
+ super (TestLayoutPdfVsLayoutPoint , self ).setUp ()
385
395
self ._TestKind = OutputKind .Pdf
386
396
self .configTest ('pal_composer' , 'sp_img' )
387
397
self ._Mismatch = 50
388
398
self ._ColorTol = 18
389
399
390
400
391
- class TestComposerLineBase ( TestComposerBase ):
401
+ class TestLayoutLineBase ( TestLayoutBase ):
392
402
393
403
@classmethod
394
404
def setUpClass (cls ):
395
- TestComposerBase .setUpClass ()
405
+ TestLayoutBase .setUpClass ()
396
406
cls .layer = TestQgsPalLabeling .loadFeatureLayer ('line' )
397
407
398
408
399
- class TestComposerImageLine ( TestComposerLineBase , TestLineBase ):
409
+ class TestLayoutImageLine ( TestLayoutLineBase , TestLineBase ):
400
410
401
411
def setUp (self ):
402
412
"""Run before each test."""
403
- super (TestComposerImageLine , self ).setUp ()
413
+ super (TestLayoutImageLine , self ).setUp ()
404
414
self ._TestKind = OutputKind .Img
405
415
self .configTest ('pal_composer_line' , 'sp_img' )
406
416
407
417
408
- class TestComposerImageVsCanvasLine ( TestComposerLineBase , TestLineBase ):
418
+ class TestLayoutImageVsCanvasLine ( TestLayoutLineBase , TestLineBase ):
409
419
410
420
def setUp (self ):
411
421
"""Run before each test."""
412
- super (TestComposerImageVsCanvasLine , self ).setUp ()
422
+ super (TestLayoutImageVsCanvasLine , self ).setUp ()
413
423
self ._TestKind = OutputKind .Img
414
424
self .configTest ('pal_canvas_line' , 'sp' )
415
425
416
426
417
- class TestComposerSvgLine ( TestComposerLineBase , TestLineBase ):
427
+ class TestLayoutSvgLine ( TestLayoutLineBase , TestLineBase ):
418
428
419
429
def setUp (self ):
420
430
"""Run before each test."""
421
- super (TestComposerSvgLine , self ).setUp ()
431
+ super (TestLayoutSvgLine , self ).setUp ()
422
432
self ._TestKind = OutputKind .Svg
423
433
self .configTest ('pal_composer_line' , 'sp_svg' )
424
434
425
435
426
- class TestComposerSvgVsComposerLine ( TestComposerLineBase , TestLineBase ):
436
+ class TestLayoutSvgVsLayoutLine ( TestLayoutLineBase , TestLineBase ):
427
437
428
438
"""
429
- Compare only to composer image, which is already compared to canvas line
439
+ Compare only to layout image, which is already compared to canvas line
430
440
"""
431
441
432
442
def setUp (self ):
433
443
"""Run before each test."""
434
- super (TestComposerSvgVsComposerLine , self ).setUp ()
444
+ super (TestLayoutSvgVsLayoutLine , self ).setUp ()
435
445
self ._TestKind = OutputKind .Svg
436
446
self .configTest ('pal_composer_line' , 'sp_img' )
437
447
self ._ColorTol = 4
438
448
439
449
440
- class TestComposerPdfLine ( TestComposerLineBase , TestLineBase ):
450
+ class TestLayoutPdfLine ( TestLayoutLineBase , TestLineBase ):
441
451
442
452
def setUp (self ):
443
453
"""Run before each test."""
444
- super (TestComposerPdfLine , self ).setUp ()
454
+ super (TestLayoutPdfLine , self ).setUp ()
445
455
self ._TestKind = OutputKind .Pdf
446
456
self .configTest ('pal_composer_line' , 'sp_pdf' )
447
457
448
458
449
- class TestComposerPdfVsComposerLine ( TestComposerLineBase , TestLineBase ):
459
+ class TestLayoutPdfVsLayoutLine ( TestLayoutLineBase , TestLineBase ):
450
460
451
461
"""
452
- Compare only to composer image, which is already compared to canvas line
462
+ Compare only to layout image, which is already compared to canvas line
453
463
"""
454
464
455
465
def setUp (self ):
456
466
"""Run before each test."""
457
- super (TestComposerPdfVsComposerLine , self ).setUp ()
467
+ super (TestLayoutPdfVsLayoutLine , self ).setUp ()
458
468
self ._TestKind = OutputKind .Pdf
459
469
self .configTest ('pal_composer_line' , 'sp_img' )
460
470
self ._Mismatch = 50
@@ -465,12 +475,12 @@ def setUp(self):
465
475
# NOTE: unless PAL_SUITE env var is set all test class methods will be run
466
476
# SEE: test_qgspallabeling_tests.suiteTests() to define suite
467
477
st = suiteTests ()
468
- sp_i = ['TestComposerImagePoint .' + t for t in st ['sp_suite' ]]
469
- sp_ivs = ['TestComposerImageVsCanvasPoint .' + t for t in st ['sp_vs_suite' ]]
470
- sp_s = ['TestComposerSvgPoint .' + t for t in st ['sp_suite' ]]
471
- sp_svs = ['TestComposerSvgVsComposerPoint .' + t for t in st ['sp_vs_suite' ]]
472
- sp_p = ['TestComposerPdfPoint .' + t for t in st ['sp_suite' ]]
473
- sp_pvs = ['TestComposerPdfVsComposerPoint .' + t for t in st ['sp_vs_suite' ]]
478
+ sp_i = ['TestLayoutImagePoint .' + t for t in st ['sp_suite' ]]
479
+ sp_ivs = ['TestLayoutImageVsCanvasPoint .' + t for t in st ['sp_vs_suite' ]]
480
+ sp_s = ['TestLayoutSvgPoint .' + t for t in st ['sp_suite' ]]
481
+ sp_svs = ['TestLayoutSvgVsLayoutPoint .' + t for t in st ['sp_vs_suite' ]]
482
+ sp_p = ['TestLayoutPdfPoint .' + t for t in st ['sp_suite' ]]
483
+ sp_pvs = ['TestLayoutPdfVsLayoutPoint .' + t for t in st ['sp_vs_suite' ]]
474
484
suite = []
475
485
476
486
# extended separately for finer control of PAL_SUITE (comment-out undesired)
0 commit comments