QGIS API Documentation  3.20.0-Odense (decaadbb31)
qgstextbackgroundsettings.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgstextbackgroundsettings.cpp
3  -----------------
4  begin : May 2020
5  copyright : (C) Nyall Dawson
6  email : nyall dot dawson at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
17 #include "qgstextrenderer_p.h"
18 #include "qgsvectorlayer.h"
19 #include "qgspallabeling.h"
20 #include "qgssymbollayerutils.h"
21 #include "qgsfillsymbollayer.h"
22 #include "qgspainting.h"
23 #include "qgstextrendererutils.h"
24 #include "qgspainteffectregistry.h"
25 
27 {
28  d = new QgsTextBackgroundSettingsPrivate();
29 
30  // Create a default fill symbol to preserve API promise until QGIS 4.0
31  QgsSimpleFillSymbolLayer *fill = new QgsSimpleFillSymbolLayer( d->fillColor, Qt::SolidPattern, d->strokeColor );
32  fill->setStrokeWidth( d->strokeWidth );
33  fill->setStrokeWidthUnit( d->strokeWidthUnits );
34  fill->setStrokeWidthMapUnitScale( d->strokeWidthMapUnitScale );
35  fill->setStrokeStyle( !qgsDoubleNear( d->strokeWidth, 0.0 ) ? Qt::SolidLine : Qt::NoPen );
36  fill->setPenJoinStyle( d->joinStyle );
37 
39  fillSymbol->changeSymbolLayer( 0, fill );
41 }
42 
44  : d( other.d )
45 {
46 
47 }
48 
50 {
51  d = other.d;
52  return *this;
53 }
54 
56 {
57 
58 }
59 
61 {
62  if ( !d->enabled == other.enabled()
63  || d->type != other.type()
64  || d->svgFile != other.svgFile()
65  || d->sizeType != other.sizeType()
66  || d->size != other.size()
67  || d->sizeUnits != other.sizeUnit()
68  || d->sizeMapUnitScale != other.sizeMapUnitScale()
69  || d->rotationType != other.rotationType()
70  || d->rotation != other.rotation()
71  || d->offset != other.offset()
72  || d->offsetUnits != other.offsetUnit()
73  || d->offsetMapUnitScale != other.offsetMapUnitScale()
74  || d->radii != other.radii()
75  || d->radiiUnits != other.radiiUnit()
76  || d->radiiMapUnitScale != other.radiiMapUnitScale()
77  || d->blendMode != other.blendMode()
78  || d->fillColor != other.fillColor()
79  || d->strokeColor != other.strokeColor()
80  || d->opacity != other.opacity()
81  || d->strokeWidth != other.strokeWidth()
82  || d->strokeWidthUnits != other.strokeWidthUnit()
83  || d->strokeWidthMapUnitScale != other.strokeWidthMapUnitScale()
84  || d->joinStyle != other.joinStyle() )
85  return false;
86 
87  if ( static_cast< bool >( d->paintEffect ) != static_cast< bool >( other.paintEffect() )
88  || ( d->paintEffect && d->paintEffect->properties() != other.paintEffect()->properties() ) )
89  return false;
90 
91  if ( static_cast< bool >( d->markerSymbol ) != static_cast< bool >( other.markerSymbol() )
92  || ( d->markerSymbol && QgsSymbolLayerUtils::symbolProperties( d->markerSymbol.get() ) != QgsSymbolLayerUtils::symbolProperties( other.markerSymbol() ) ) )
93  return false;
94 
95  if ( static_cast< bool >( d->fillSymbol ) != static_cast< bool >( other.fillSymbol() )
96  || ( d->fillSymbol && QgsSymbolLayerUtils::symbolProperties( d->fillSymbol.get() ) != QgsSymbolLayerUtils::symbolProperties( other.fillSymbol() ) ) )
97  return false;
98 
99  return true;
100 }
101 
103 {
104  return !( *this == other );
105 }
106 
108 {
109  return d->enabled;
110 }
111 
113 {
114  d->enabled = enabled;
115 }
116 
118 {
119  return d->type;
120 }
121 
123 {
124  d->type = type;
125 }
126 
128 {
129  return d->svgFile;
130 }
131 
132 void QgsTextBackgroundSettings::setSvgFile( const QString &file )
133 {
134  d->svgFile = file;
135 }
136 
138 {
139  return d->markerSymbol.get();
140 }
141 
143 {
144  d->markerSymbol.reset( symbol );
145 }
146 
148 {
149  return d->fillSymbol.get();
150 }
151 
153 {
154  d->fillSymbol.reset( symbol );
155 }
156 
158 {
159  return d->sizeType;
160 }
161 
163 {
164  d->sizeType = type;
165 }
166 
168 {
169  return d->size;
170 }
171 
173 {
174  d->size = size;
175 }
176 
178 {
179  return d->sizeUnits;
180 }
181 
183 {
184  d->sizeUnits = unit;
185 }
186 
188 {
189  return d->sizeMapUnitScale;
190 }
191 
193 {
194  d->sizeMapUnitScale = scale;
195 }
196 
198 {
199  return d->rotationType;
200 }
201 
203 {
204  d->rotationType = type;
205 }
206 
208 {
209  return d->rotation;
210 }
211 
213 {
214  d->rotation = rotation;
215 }
216 
218 {
219  return d->offset;
220 }
221 
223 {
224  d->offset = offset;
225 }
226 
228 {
229  return d->offsetUnits;
230 }
231 
233 {
234  d->offsetUnits = units;
235 }
236 
238 {
239  return d->offsetMapUnitScale;
240 }
241 
243 {
244  d->offsetMapUnitScale = scale;
245 }
246 
248 {
249  return d->radii;
250 }
251 
253 {
254  d->radii = radii;
255 }
256 
258 {
259  return d->radiiUnits;
260 }
261 
263 {
264  d->radiiUnits = units;
265 }
266 
268 {
269  return d->radiiMapUnitScale;
270 }
271 
273 {
274  d->radiiMapUnitScale = scale;
275 }
276 
278 {
279  return d->opacity;
280 }
281 
283 {
284  d->opacity = opacity;
285 }
286 
287 QPainter::CompositionMode QgsTextBackgroundSettings::blendMode() const
288 {
289  return d->blendMode;
290 }
291 
292 void QgsTextBackgroundSettings::setBlendMode( QPainter::CompositionMode mode )
293 {
294  d->blendMode = mode;
295 }
296 
298 {
299  return d->fillColor;
300 }
301 
302 void QgsTextBackgroundSettings::setFillColor( const QColor &color )
303 {
304  d->fillColor = color;
305  if ( d->fillSymbol && d->fillSymbol->symbolLayers().at( 0 )->layerType() == QLatin1String( "SimpleFill" ) )
306  {
307  qgis::down_cast< QgsSimpleFillSymbolLayer * >( d->fillSymbol->symbolLayers().at( 0 ) )->setColor( color );
308  }
309 }
310 
312 {
313  return d->strokeColor;
314 }
315 
316 void QgsTextBackgroundSettings::setStrokeColor( const QColor &color )
317 {
318  d->strokeColor = color;
319  if ( d->fillSymbol && d->fillSymbol->symbolLayers().at( 0 )->layerType() == QLatin1String( "SimpleFill" ) )
320  {
321  qgis::down_cast< QgsSimpleFillSymbolLayer * >( d->fillSymbol->symbolLayers().at( 0 ) )->setStrokeColor( color );
322  }
323 }
324 
326 {
327  return d->strokeWidth;
328 }
329 
331 {
332  d->strokeWidth = width;
333  if ( d->fillSymbol && d->fillSymbol->symbolLayers().at( 0 )->layerType() == QLatin1String( "SimpleFill" ) )
334  {
335  QgsSimpleFillSymbolLayer *fill = qgis::down_cast< QgsSimpleFillSymbolLayer * >( d->fillSymbol->symbolLayers().at( 0 ) );
336  fill->setStrokeWidth( width );
337  fill->setStrokeStyle( !qgsDoubleNear( width, 0.0 ) ? Qt::SolidLine : Qt::NoPen );
338  }
339 }
340 
342 {
343  return d->strokeWidthUnits;
344 }
345 
347 {
348  d->strokeWidthUnits = units;
349  if ( d->fillSymbol && d->fillSymbol->symbolLayers().at( 0 )->layerType() == QLatin1String( "SimpleFill" ) )
350  {
351  qgis::down_cast< QgsSimpleFillSymbolLayer * >( d->fillSymbol->symbolLayers().at( 0 ) )->setStrokeWidthUnit( units );
352  }
353 }
354 
356 {
357  return d->strokeWidthMapUnitScale;
358 }
359 
361 {
362  d->strokeWidthMapUnitScale = scale;
363  if ( d->fillSymbol && d->fillSymbol->symbolLayers().at( 0 )->layerType() == QLatin1String( "SimpleFill" ) )
364  {
365  qgis::down_cast< QgsSimpleFillSymbolLayer * >( d->fillSymbol->symbolLayers().at( 0 ) )->setStrokeWidthMapUnitScale( scale );
366  }
367 }
368 
369 Qt::PenJoinStyle QgsTextBackgroundSettings::joinStyle() const
370 {
371  return d->joinStyle;
372 }
373 
374 void QgsTextBackgroundSettings::setJoinStyle( Qt::PenJoinStyle style )
375 {
376  d->joinStyle = style;
377  if ( d->fillSymbol && d->fillSymbol->symbolLayers().at( 0 )->layerType() == QLatin1String( "SimpleFill" ) )
378  {
379  qgis::down_cast< QgsSimpleFillSymbolLayer * >( d->fillSymbol->symbolLayers().at( 0 ) )->setPenJoinStyle( style );
380  }
381 }
382 
384 {
385  return d->paintEffect.get();
386 }
387 
389 {
390  d->paintEffect.reset( effect );
391 }
392 
394 {
395  d->enabled = layer->customProperty( QStringLiteral( "labeling/shapeDraw" ), QVariant( false ) ).toBool();
396  d->type = static_cast< ShapeType >( layer->customProperty( QStringLiteral( "labeling/shapeType" ), QVariant( ShapeRectangle ) ).toUInt() );
397  d->svgFile = layer->customProperty( QStringLiteral( "labeling/shapeSVGFile" ), QVariant( "" ) ).toString();
398  d->sizeType = static_cast< SizeType >( layer->customProperty( QStringLiteral( "labeling/shapeSizeType" ), QVariant( SizeBuffer ) ).toUInt() );
399  d->size = QSizeF( layer->customProperty( QStringLiteral( "labeling/shapeSizeX" ), QVariant( 0.0 ) ).toDouble(),
400  layer->customProperty( QStringLiteral( "labeling/shapeSizeY" ), QVariant( 0.0 ) ).toDouble() );
401 
402  if ( layer->customProperty( QStringLiteral( "labeling/shapeSizeUnit" ) ).toString().isEmpty() )
403  {
404  d->sizeUnits = QgsTextRendererUtils::convertFromOldLabelUnit( layer->customProperty( QStringLiteral( "labeling/shapeSizeUnits" ), 0 ).toUInt() );
405  }
406  else
407  {
408  d->sizeUnits = QgsUnitTypes::decodeRenderUnit( layer->customProperty( QStringLiteral( "labeling/shapeSizeUnit" ) ).toString() );
409  }
410 
411  if ( layer->customProperty( QStringLiteral( "labeling/shapeSizeMapUnitScale" ) ).toString().isEmpty() )
412  {
413  //fallback to older property
414  double oldMin = layer->customProperty( QStringLiteral( "labeling/shapeSizeMapUnitMinScale" ), 0.0 ).toDouble();
415  d->sizeMapUnitScale.minScale = oldMin != 0 ? 1.0 / oldMin : 0;
416  double oldMax = layer->customProperty( QStringLiteral( "labeling/shapeSizeMapUnitMaxScale" ), 0.0 ).toDouble();
417  d->sizeMapUnitScale.maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
418  }
419  else
420  {
421  d->sizeMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( layer->customProperty( QStringLiteral( "labeling/shapeSizeMapUnitScale" ) ).toString() );
422  }
423  d->rotationType = static_cast< RotationType >( layer->customProperty( QStringLiteral( "labeling/shapeRotationType" ), QVariant( RotationSync ) ).toUInt() );
424  d->rotation = layer->customProperty( QStringLiteral( "labeling/shapeRotation" ), QVariant( 0.0 ) ).toDouble();
425  d->offset = QPointF( layer->customProperty( QStringLiteral( "labeling/shapeOffsetX" ), QVariant( 0.0 ) ).toDouble(),
426  layer->customProperty( QStringLiteral( "labeling/shapeOffsetY" ), QVariant( 0.0 ) ).toDouble() );
427 
428  if ( layer->customProperty( QStringLiteral( "labeling/shapeOffsetUnit" ) ).toString().isEmpty() )
429  {
430  d->offsetUnits = QgsTextRendererUtils::convertFromOldLabelUnit( layer->customProperty( QStringLiteral( "labeling/shapeOffsetUnits" ), 0 ).toUInt() );
431  }
432  else
433  {
434  d->offsetUnits = QgsUnitTypes::decodeRenderUnit( layer->customProperty( QStringLiteral( "labeling/shapeOffsetUnit" ) ).toString() );
435  }
436 
437  if ( layer->customProperty( QStringLiteral( "labeling/shapeOffsetMapUnitScale" ) ).toString().isEmpty() )
438  {
439  //fallback to older property
440  double oldMin = layer->customProperty( QStringLiteral( "labeling/shapeOffsetMapUnitMinScale" ), 0.0 ).toDouble();
441  d->offsetMapUnitScale.minScale = oldMin != 0 ? 1.0 / oldMin : 0;
442  double oldMax = layer->customProperty( QStringLiteral( "labeling/shapeOffsetMapUnitMaxScale" ), 0.0 ).toDouble();
443  d->offsetMapUnitScale.maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
444  }
445  else
446  {
447  d->offsetMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( layer->customProperty( QStringLiteral( "labeling/shapeOffsetMapUnitScale" ) ).toString() );
448  }
449  d->radii = QSizeF( layer->customProperty( QStringLiteral( "labeling/shapeRadiiX" ), QVariant( 0.0 ) ).toDouble(),
450  layer->customProperty( QStringLiteral( "labeling/shapeRadiiY" ), QVariant( 0.0 ) ).toDouble() );
451 
452 
453  if ( layer->customProperty( QStringLiteral( "labeling/shapeRadiiUnit" ) ).toString().isEmpty() )
454  {
455  d->radiiUnits = QgsTextRendererUtils::convertFromOldLabelUnit( layer->customProperty( QStringLiteral( "labeling/shapeRadiiUnits" ), 0 ).toUInt() );
456  }
457  else
458  {
459  d->radiiUnits = QgsUnitTypes::decodeRenderUnit( layer->customProperty( QStringLiteral( "labeling/shapeRadiiUnit" ) ).toString() );
460  }
461 
462  if ( layer->customProperty( QStringLiteral( "labeling/shapeRadiiMapUnitScale" ) ).toString().isEmpty() )
463  {
464  //fallback to older property
465  double oldMin = layer->customProperty( QStringLiteral( "labeling/shapeRadiiMapUnitMinScale" ), 0.0 ).toDouble();
466  d->radiiMapUnitScale.minScale = oldMin != 0 ? 1.0 / oldMin : 0;
467  double oldMax = layer->customProperty( QStringLiteral( "labeling/shapeRadiiMapUnitMaxScale" ), 0.0 ).toDouble();
468  d->radiiMapUnitScale.maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
469  }
470  else
471  {
472  d->radiiMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( layer->customProperty( QStringLiteral( "labeling/shapeRadiiMapUnitScale" ) ).toString() );
473  }
474  d->fillColor = QgsTextRendererUtils::readColor( layer, QStringLiteral( "labeling/shapeFillColor" ), Qt::white, true );
475  d->strokeColor = QgsTextRendererUtils::readColor( layer, QStringLiteral( "labeling/shapeBorderColor" ), Qt::darkGray, true );
476  d->strokeWidth = layer->customProperty( QStringLiteral( "labeling/shapeBorderWidth" ), QVariant( .0 ) ).toDouble();
477  if ( layer->customProperty( QStringLiteral( "labeling/shapeBorderWidthUnit" ) ).toString().isEmpty() )
478  {
479  d->strokeWidthUnits = QgsTextRendererUtils::convertFromOldLabelUnit( layer->customProperty( QStringLiteral( "labeling/shapeBorderWidthUnits" ), 0 ).toUInt() );
480  }
481  else
482  {
483  d->strokeWidthUnits = QgsUnitTypes::decodeRenderUnit( layer->customProperty( QStringLiteral( "labeling/shapeBorderWidthUnit" ) ).toString() );
484  }
485  if ( layer->customProperty( QStringLiteral( "labeling/shapeBorderWidthMapUnitScale" ) ).toString().isEmpty() )
486  {
487  //fallback to older property
488  double oldMin = layer->customProperty( QStringLiteral( "labeling/shapeBorderWidthMapUnitMinScale" ), 0.0 ).toDouble();
489  d->strokeWidthMapUnitScale.minScale = oldMin != 0 ? 1.0 / oldMin : 0;
490  double oldMax = layer->customProperty( QStringLiteral( "labeling/shapeBorderWidthMapUnitMaxScale" ), 0.0 ).toDouble();
491  d->strokeWidthMapUnitScale.maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
492  }
493  else
494  {
495  d->strokeWidthMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( layer->customProperty( QStringLiteral( "labeling/shapeBorderWidthMapUnitScale" ) ).toString() );
496  }
497  d->joinStyle = static_cast< Qt::PenJoinStyle >( layer->customProperty( QStringLiteral( "labeling/shapeJoinStyle" ), QVariant( Qt::BevelJoin ) ).toUInt() );
498 
499  if ( layer->customProperty( QStringLiteral( "labeling/shapeOpacity" ) ).toString().isEmpty() )
500  {
501  d->opacity = ( 1 - layer->customProperty( QStringLiteral( "labeling/shapeTransparency" ) ).toInt() / 100.0 ); //0 -100
502  }
503  else
504  {
505  d->opacity = ( layer->customProperty( QStringLiteral( "labeling/shapeOpacity" ) ).toDouble() );
506  }
507  d->blendMode = QgsPainting::getCompositionMode(
508  static_cast< QgsPainting::BlendMode >( layer->customProperty( QStringLiteral( "labeling/shapeBlendMode" ), QVariant( QgsPainting::BlendNormal ) ).toUInt() ) );
509 
510  if ( layer->customProperty( QStringLiteral( "labeling/shapeEffect" ) ).isValid() )
511  {
512  QDomDocument doc( QStringLiteral( "effect" ) );
513  doc.setContent( layer->customProperty( QStringLiteral( "labeling/shapeEffect" ) ).toString() );
514  QDomElement effectElem = doc.firstChildElement( QStringLiteral( "effect" ) ).firstChildElement( QStringLiteral( "effect" ) );
515  setPaintEffect( QgsApplication::paintEffectRegistry()->createEffect( effectElem ) );
516  }
517  else
518  setPaintEffect( nullptr );
519 }
520 
521 void QgsTextBackgroundSettings::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
522 {
523  QDomElement backgroundElem = elem.firstChildElement( QStringLiteral( "background" ) );
524  d->enabled = backgroundElem.attribute( QStringLiteral( "shapeDraw" ), QStringLiteral( "0" ) ).toInt();
525  d->type = static_cast< ShapeType >( backgroundElem.attribute( QStringLiteral( "shapeType" ), QString::number( ShapeRectangle ) ).toUInt() );
526  d->svgFile = QgsSymbolLayerUtils::svgSymbolNameToPath( backgroundElem.attribute( QStringLiteral( "shapeSVGFile" ) ), context.pathResolver() );
527  d->sizeType = static_cast< SizeType >( backgroundElem.attribute( QStringLiteral( "shapeSizeType" ), QString::number( SizeBuffer ) ).toUInt() );
528  d->size = QSizeF( backgroundElem.attribute( QStringLiteral( "shapeSizeX" ), QStringLiteral( "0" ) ).toDouble(),
529  backgroundElem.attribute( QStringLiteral( "shapeSizeY" ), QStringLiteral( "0" ) ).toDouble() );
530 
531  if ( !backgroundElem.hasAttribute( QStringLiteral( "shapeSizeUnit" ) ) )
532  {
533  d->sizeUnits = QgsTextRendererUtils::convertFromOldLabelUnit( backgroundElem.attribute( QStringLiteral( "shapeSizeUnits" ) ).toUInt() );
534  }
535  else
536  {
537  d->sizeUnits = QgsUnitTypes::decodeRenderUnit( backgroundElem.attribute( QStringLiteral( "shapeSizeUnit" ) ) );
538  }
539 
540  if ( !backgroundElem.hasAttribute( QStringLiteral( "shapeSizeMapUnitScale" ) ) )
541  {
542  //fallback to older property
543  double oldMin = backgroundElem.attribute( QStringLiteral( "shapeSizeMapUnitMinScale" ), QStringLiteral( "0" ) ).toDouble();
544  d->sizeMapUnitScale.minScale = oldMin != 0 ? 1.0 / oldMin : 0;
545  double oldMax = backgroundElem.attribute( QStringLiteral( "shapeSizeMapUnitMaxScale" ), QStringLiteral( "0" ) ).toDouble();
546  d->sizeMapUnitScale.maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
547  }
548  else
549  {
550  d->sizeMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( backgroundElem.attribute( QStringLiteral( "shapeSizeMapUnitScale" ) ) );
551  }
552  d->rotationType = static_cast< RotationType >( backgroundElem.attribute( QStringLiteral( "shapeRotationType" ), QString::number( RotationSync ) ).toUInt() );
553  d->rotation = backgroundElem.attribute( QStringLiteral( "shapeRotation" ), QStringLiteral( "0" ) ).toDouble();
554  d->offset = QPointF( backgroundElem.attribute( QStringLiteral( "shapeOffsetX" ), QStringLiteral( "0" ) ).toDouble(),
555  backgroundElem.attribute( QStringLiteral( "shapeOffsetY" ), QStringLiteral( "0" ) ).toDouble() );
556 
557  if ( !backgroundElem.hasAttribute( QStringLiteral( "shapeOffsetUnit" ) ) )
558  {
559  d->offsetUnits = QgsTextRendererUtils::convertFromOldLabelUnit( backgroundElem.attribute( QStringLiteral( "shapeOffsetUnits" ) ).toUInt() );
560  }
561  else
562  {
563  d->offsetUnits = QgsUnitTypes::decodeRenderUnit( backgroundElem.attribute( QStringLiteral( "shapeOffsetUnit" ) ) );
564  }
565 
566  if ( !backgroundElem.hasAttribute( QStringLiteral( "shapeOffsetMapUnitScale" ) ) )
567  {
568  //fallback to older property
569  double oldMin = backgroundElem.attribute( QStringLiteral( "shapeOffsetMapUnitMinScale" ), QStringLiteral( "0" ) ).toDouble();
570  d->offsetMapUnitScale.minScale = oldMin != 0 ? 1.0 / oldMin : 0;
571  double oldMax = backgroundElem.attribute( QStringLiteral( "shapeOffsetMapUnitMaxScale" ), QStringLiteral( "0" ) ).toDouble();
572  d->offsetMapUnitScale.maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
573  }
574  else
575  {
576  d->offsetMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( backgroundElem.attribute( QStringLiteral( "shapeOffsetMapUnitScale" ) ) );
577  }
578  d->radii = QSizeF( backgroundElem.attribute( QStringLiteral( "shapeRadiiX" ), QStringLiteral( "0" ) ).toDouble(),
579  backgroundElem.attribute( QStringLiteral( "shapeRadiiY" ), QStringLiteral( "0" ) ).toDouble() );
580 
581  if ( !backgroundElem.hasAttribute( QStringLiteral( "shapeRadiiUnit" ) ) )
582  {
583  d->radiiUnits = QgsTextRendererUtils::convertFromOldLabelUnit( backgroundElem.attribute( QStringLiteral( "shapeRadiiUnits" ) ).toUInt() );
584  }
585  else
586  {
587  d->radiiUnits = QgsUnitTypes::decodeRenderUnit( backgroundElem.attribute( QStringLiteral( "shapeRadiiUnit" ) ) );
588  }
589  if ( !backgroundElem.hasAttribute( QStringLiteral( "shapeRadiiMapUnitScale" ) ) )
590  {
591  //fallback to older property
592  double oldMin = backgroundElem.attribute( QStringLiteral( "shapeRadiiMapUnitMinScale" ), QStringLiteral( "0" ) ).toDouble();
593  d->radiiMapUnitScale.minScale = oldMin != 0 ? 1.0 / oldMin : 0;
594  double oldMax = backgroundElem.attribute( QStringLiteral( "shapeRadiiMapUnitMaxScale" ), QStringLiteral( "0" ) ).toDouble();
595  d->radiiMapUnitScale.maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
596  }
597  else
598  {
599  d->radiiMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( backgroundElem.attribute( QStringLiteral( "shapeRadiiMapUnitScale" ) ) );
600  }
601  d->fillColor = QgsSymbolLayerUtils::decodeColor( backgroundElem.attribute( QStringLiteral( "shapeFillColor" ), QgsSymbolLayerUtils::encodeColor( Qt::white ) ) );
602  d->strokeColor = QgsSymbolLayerUtils::decodeColor( backgroundElem.attribute( QStringLiteral( "shapeBorderColor" ), QgsSymbolLayerUtils::encodeColor( Qt::darkGray ) ) );
603  d->strokeWidth = backgroundElem.attribute( QStringLiteral( "shapeBorderWidth" ), QStringLiteral( "0" ) ).toDouble();
604 
605  if ( !backgroundElem.hasAttribute( QStringLiteral( "shapeBorderWidthUnit" ) ) )
606  {
607  d->strokeWidthUnits = QgsTextRendererUtils::convertFromOldLabelUnit( backgroundElem.attribute( QStringLiteral( "shapeBorderWidthUnits" ) ).toUInt() );
608  }
609  else
610  {
611  d->strokeWidthUnits = QgsUnitTypes::decodeRenderUnit( backgroundElem.attribute( QStringLiteral( "shapeBorderWidthUnit" ) ) );
612  }
613  if ( !backgroundElem.hasAttribute( QStringLiteral( "shapeBorderWidthMapUnitScale" ) ) )
614  {
615  //fallback to older property
616  double oldMin = backgroundElem.attribute( QStringLiteral( "shapeBorderWidthMapUnitMinScale" ), QStringLiteral( "0" ) ).toDouble();
617  d->strokeWidthMapUnitScale.minScale = oldMin != 0 ? 1.0 / oldMin : 0;
618  double oldMax = backgroundElem.attribute( QStringLiteral( "shapeBorderWidthMapUnitMaxScale" ), QStringLiteral( "0" ) ).toDouble();
619  d->strokeWidthMapUnitScale.maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
620  }
621  else
622  {
623  d->strokeWidthMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( backgroundElem.attribute( QStringLiteral( "shapeBorderWidthMapUnitScale" ) ) );
624  }
625  d->joinStyle = static_cast< Qt::PenJoinStyle >( backgroundElem.attribute( QStringLiteral( "shapeJoinStyle" ), QString::number( Qt::BevelJoin ) ).toUInt() );
626 
627  if ( !backgroundElem.hasAttribute( QStringLiteral( "shapeOpacity" ) ) )
628  {
629  d->opacity = ( 1 - backgroundElem.attribute( QStringLiteral( "shapeTransparency" ) ).toInt() / 100.0 ); //0 -100
630  }
631  else
632  {
633  d->opacity = ( backgroundElem.attribute( QStringLiteral( "shapeOpacity" ) ).toDouble() );
634  }
635 
636  d->blendMode = QgsPainting::getCompositionMode(
637  static_cast< QgsPainting::BlendMode >( backgroundElem.attribute( QStringLiteral( "shapeBlendMode" ), QString::number( QgsPainting::BlendNormal ) ).toUInt() ) );
638 
639  QDomElement effectElem = backgroundElem.firstChildElement( QStringLiteral( "effect" ) );
640  if ( !effectElem.isNull() )
641  setPaintEffect( QgsApplication::paintEffectRegistry()->createEffect( effectElem ) );
642  else
643  setPaintEffect( nullptr );
644 
645  setMarkerSymbol( nullptr );
646  setFillSymbol( nullptr );
647  const QDomNodeList symbols = backgroundElem.elementsByTagName( QStringLiteral( "symbol" ) );
648  for ( int i = 0; i < symbols.size(); ++i )
649  {
650  if ( symbols.at( i ).isElement() )
651  {
652  const QDomElement symbolElement = symbols.at( i ).toElement();
653  const QString symbolElementName = symbolElement.attribute( QStringLiteral( "name" ) );
654  if ( symbolElementName == QLatin1String( "markerSymbol" ) )
655  {
656  setMarkerSymbol( QgsSymbolLayerUtils::loadSymbol< QgsMarkerSymbol >( symbolElement, context ) );
657  }
658  else if ( symbolElementName == QLatin1String( "fillSymbol" ) )
659  {
660  setFillSymbol( QgsSymbolLayerUtils::loadSymbol< QgsFillSymbol >( symbolElement, context ) );
661  }
662  }
663  }
664 
665  if ( !d->fillSymbol )
666  {
667  QgsSimpleFillSymbolLayer *fill = new QgsSimpleFillSymbolLayer( d->fillColor, Qt::SolidPattern, d->strokeColor );
668  fill->setStrokeWidth( d->strokeWidth );
669  fill->setStrokeWidthUnit( d->strokeWidthUnits );
670  fill->setStrokeWidthMapUnitScale( d->strokeWidthMapUnitScale );
671  fill->setStrokeStyle( !qgsDoubleNear( d->strokeWidth, 0.0 ) ? Qt::SolidLine : Qt::NoPen );
672  fill->setPenJoinStyle( d->joinStyle );
673 
675  fillSymbol->changeSymbolLayer( 0, fill );
677  }
678 }
679 
680 QDomElement QgsTextBackgroundSettings::writeXml( QDomDocument &doc, const QgsReadWriteContext &context ) const
681 {
682  QDomElement backgroundElem = doc.createElement( QStringLiteral( "background" ) );
683  backgroundElem.setAttribute( QStringLiteral( "shapeDraw" ), d->enabled );
684  backgroundElem.setAttribute( QStringLiteral( "shapeType" ), static_cast< unsigned int >( d->type ) );
685  backgroundElem.setAttribute( QStringLiteral( "shapeSVGFile" ), QgsSymbolLayerUtils::svgSymbolPathToName( d->svgFile, context.pathResolver() ) );
686  backgroundElem.setAttribute( QStringLiteral( "shapeSizeType" ), static_cast< unsigned int >( d->sizeType ) );
687  backgroundElem.setAttribute( QStringLiteral( "shapeSizeX" ), d->size.width() );
688  backgroundElem.setAttribute( QStringLiteral( "shapeSizeY" ), d->size.height() );
689  backgroundElem.setAttribute( QStringLiteral( "shapeSizeUnit" ), QgsUnitTypes::encodeUnit( d->sizeUnits ) );
690  backgroundElem.setAttribute( QStringLiteral( "shapeSizeMapUnitScale" ), QgsSymbolLayerUtils::encodeMapUnitScale( d->sizeMapUnitScale ) );
691  backgroundElem.setAttribute( QStringLiteral( "shapeRotationType" ), static_cast< unsigned int >( d->rotationType ) );
692  backgroundElem.setAttribute( QStringLiteral( "shapeRotation" ), d->rotation );
693  backgroundElem.setAttribute( QStringLiteral( "shapeOffsetX" ), d->offset.x() );
694  backgroundElem.setAttribute( QStringLiteral( "shapeOffsetY" ), d->offset.y() );
695  backgroundElem.setAttribute( QStringLiteral( "shapeOffsetUnit" ), QgsUnitTypes::encodeUnit( d->offsetUnits ) );
696  backgroundElem.setAttribute( QStringLiteral( "shapeOffsetMapUnitScale" ), QgsSymbolLayerUtils::encodeMapUnitScale( d->offsetMapUnitScale ) );
697  backgroundElem.setAttribute( QStringLiteral( "shapeRadiiX" ), d->radii.width() );
698  backgroundElem.setAttribute( QStringLiteral( "shapeRadiiY" ), d->radii.height() );
699  backgroundElem.setAttribute( QStringLiteral( "shapeRadiiUnit" ), QgsUnitTypes::encodeUnit( d->radiiUnits ) );
700  backgroundElem.setAttribute( QStringLiteral( "shapeRadiiMapUnitScale" ), QgsSymbolLayerUtils::encodeMapUnitScale( d->radiiMapUnitScale ) );
701  backgroundElem.setAttribute( QStringLiteral( "shapeFillColor" ), QgsSymbolLayerUtils::encodeColor( d->fillColor ) );
702  backgroundElem.setAttribute( QStringLiteral( "shapeBorderColor" ), QgsSymbolLayerUtils::encodeColor( d->strokeColor ) );
703  backgroundElem.setAttribute( QStringLiteral( "shapeBorderWidth" ), d->strokeWidth );
704  backgroundElem.setAttribute( QStringLiteral( "shapeBorderWidthUnit" ), QgsUnitTypes::encodeUnit( d->strokeWidthUnits ) );
705  backgroundElem.setAttribute( QStringLiteral( "shapeBorderWidthMapUnitScale" ), QgsSymbolLayerUtils::encodeMapUnitScale( d->strokeWidthMapUnitScale ) );
706  backgroundElem.setAttribute( QStringLiteral( "shapeJoinStyle" ), static_cast< unsigned int >( d->joinStyle ) );
707  backgroundElem.setAttribute( QStringLiteral( "shapeOpacity" ), d->opacity );
708  backgroundElem.setAttribute( QStringLiteral( "shapeBlendMode" ), QgsPainting::getBlendModeEnum( d->blendMode ) );
709  if ( d->paintEffect && !QgsPaintEffectRegistry::isDefaultStack( d->paintEffect.get() ) )
710  d->paintEffect->saveProperties( doc, backgroundElem );
711 
712  if ( d->markerSymbol )
713  backgroundElem.appendChild( QgsSymbolLayerUtils::saveSymbol( QStringLiteral( "markerSymbol" ), d->markerSymbol.get(), doc, context ) );
714 
715  if ( d->fillSymbol )
716  backgroundElem.appendChild( QgsSymbolLayerUtils::saveSymbol( QStringLiteral( "fillSymbol" ), d->fillSymbol.get(), doc, context ) );
717 
718  return backgroundElem;
719 }
720 
722 {
723  if ( !d->fillSymbol || d->fillSymbol->symbolLayers().at( 0 )->layerType() != QLatin1String( "SimpleFill" ) )
724  return;
725  QgsSimpleFillSymbolLayer *fill = qgis::down_cast< QgsSimpleFillSymbolLayer * >( d->fillSymbol->symbolLayers().at( 0 ) );
726 
727  if ( d->type != QgsTextBackgroundSettings::ShapeSVG )
728  {
731  {
734  }
735 
738  {
741  }
742 
745  {
748  }
749 
752  {
755  }
756  }
757 }
758 
760 {
761  if ( properties.isActive( QgsPalLayerSettings::ShapeDraw ) )
762  {
763  context.expressionContext().setOriginalValueVariable( d->enabled );
764  d->enabled = properties.valueAsBool( QgsPalLayerSettings::ShapeDraw, context.expressionContext(), d->enabled );
765  }
766 
767  if ( properties.isActive( QgsPalLayerSettings::ShapeSizeX ) )
768  {
769  context.expressionContext().setOriginalValueVariable( d->size.width() );
770  d->size.setWidth( properties.valueAsDouble( QgsPalLayerSettings::ShapeSizeX, context.expressionContext(), d->size.width() ) );
771  }
772  if ( properties.isActive( QgsPalLayerSettings::ShapeSizeY ) )
773  {
774  context.expressionContext().setOriginalValueVariable( d->size.height() );
775  d->size.setHeight( properties.valueAsDouble( QgsPalLayerSettings::ShapeSizeY, context.expressionContext(), d->size.height() ) );
776  }
777 
778  QVariant exprVal = properties.value( QgsPalLayerSettings::ShapeSizeUnits, context.expressionContext() );
779  if ( !exprVal.isNull() )
780  {
781  QString units = exprVal.toString();
782  if ( !units.isEmpty() )
783  {
784  bool ok;
786  if ( ok )
787  d->sizeUnits = res;
788  }
789  }
790 
791  exprVal = properties.value( QgsPalLayerSettings::ShapeKind, context.expressionContext() );
792  if ( !exprVal.isNull() )
793  {
794  const QString skind = exprVal.toString().trimmed();
795  if ( !skind.isEmpty() )
796  {
797  d->type = QgsTextRendererUtils::decodeShapeType( skind );
798  }
799  }
800 
801  exprVal = properties.value( QgsPalLayerSettings::ShapeSizeType, context.expressionContext() );
802  if ( !exprVal.isNull() )
803  {
804  QString stype = exprVal.toString().trimmed();
805  if ( !stype.isEmpty() )
806  {
807  d->sizeType = QgsTextRendererUtils::decodeBackgroundSizeType( stype );
808  }
809  }
810 
811  // data defined shape SVG path?
812  context.expressionContext().setOriginalValueVariable( d->svgFile );
813  exprVal = properties.value( QgsPalLayerSettings::ShapeSVGFile, context.expressionContext() );
814  if ( !exprVal.isNull() )
815  {
816  QString svgfile = exprVal.toString().trimmed();
817  d->svgFile = QgsSymbolLayerUtils::svgSymbolNameToPath( svgfile, context.pathResolver() );
818  }
819 
820  if ( properties.isActive( QgsPalLayerSettings::ShapeRotation ) )
821  {
822  context.expressionContext().setOriginalValueVariable( d->rotation );
823  d->rotation = properties.valueAsDouble( QgsPalLayerSettings::ShapeRotation, context.expressionContext(), d->rotation );
824  }
825  exprVal = properties.value( QgsPalLayerSettings::ShapeRotationType, context.expressionContext() );
826  if ( !exprVal.isNull() )
827  {
828  QString rotstr = exprVal.toString().trimmed();
829  if ( !rotstr.isEmpty() )
830  {
831  d->rotationType = QgsTextRendererUtils::decodeBackgroundRotationType( rotstr );
832  }
833  }
834 
835  exprVal = properties.value( QgsPalLayerSettings::ShapeOffset, context.expressionContext() );
836  if ( !exprVal.isNull() )
837  {
838  bool ok = false;
839  const QPointF res = QgsSymbolLayerUtils::toPoint( exprVal, &ok );
840  if ( ok )
841  {
842  d->offset = res;
843  }
844  }
845  exprVal = properties.value( QgsPalLayerSettings::ShapeOffsetUnits, context.expressionContext() );
846  if ( !exprVal.isNull() )
847  {
848  QString units = exprVal.toString();
849  if ( !units.isEmpty() )
850  {
851  bool ok;
853  if ( ok )
854  d->offsetUnits = res;
855  }
856  }
857 
858  exprVal = properties.value( QgsPalLayerSettings::ShapeRadii, context.expressionContext() );
859  if ( !exprVal.isNull() )
860  {
861  bool ok = false;
862  const QSizeF res = QgsSymbolLayerUtils::toSize( exprVal, &ok );
863  if ( ok )
864  {
865  d->radii = res;
866  }
867  }
868 
869  exprVal = properties.value( QgsPalLayerSettings::ShapeRadiiUnits, context.expressionContext() );
870  if ( !exprVal.isNull() )
871  {
872  QString units = exprVal.toString();
873  if ( !units.isEmpty() )
874  {
875  bool ok;
877  if ( ok )
878  d->radiiUnits = res;
879  }
880  }
881 
882  if ( properties.isActive( QgsPalLayerSettings::ShapeOpacity ) )
883  {
884  context.expressionContext().setOriginalValueVariable( d->opacity * 100 );
885  const QVariant val = properties.value( QgsPalLayerSettings::ShapeOpacity, context.expressionContext(), d->opacity * 100 );
886  if ( !val.isNull() )
887  {
888  d->opacity = val.toDouble() / 100.0;
889  }
890  }
891 
892  // for non-SVG background types, those data defined properties will not having an impact,
893  // instead use data defined properties within symbols
894  if ( properties.isActive( QgsPalLayerSettings::ShapeFillColor ) )
895  {
897  d->fillColor = properties.valueAsColor( QgsPalLayerSettings::ShapeFillColor, context.expressionContext(), d->fillColor );
898  }
900  {
902  d->strokeColor = properties.valueAsColor( QgsPalLayerSettings::ShapeStrokeColor, context.expressionContext(), d->strokeColor );
903  }
904 
906  {
907  context.expressionContext().setOriginalValueVariable( d->strokeWidth );
908  d->strokeWidth = properties.valueAsDouble( QgsPalLayerSettings::ShapeStrokeWidth, context.expressionContext(), d->strokeWidth );
909  }
910  exprVal = properties.value( QgsPalLayerSettings::ShapeStrokeWidthUnits, context.expressionContext() );
911  if ( !exprVal.isNull() )
912  {
913  QString units = exprVal.toString();
914  if ( !units.isEmpty() )
915  {
916  bool ok;
918  if ( ok )
919  d->strokeWidthUnits = res;
920  }
921  }
922 
923  if ( properties.isActive( QgsPalLayerSettings::ShapeBlendMode ) )
924  {
925  exprVal = properties.value( QgsPalLayerSettings::ShapeBlendMode, context.expressionContext() );
926  QString blendstr = exprVal.toString().trimmed();
927  if ( !blendstr.isEmpty() )
928  d->blendMode = QgsSymbolLayerUtils::decodeBlendMode( blendstr );
929  }
930 
931  if ( properties.isActive( QgsPalLayerSettings::ShapeJoinStyle ) )
932  {
933  exprVal = properties.value( QgsPalLayerSettings::ShapeJoinStyle, context.expressionContext() );
934  QString joinstr = exprVal.toString().trimmed();
935  if ( !joinstr.isEmpty() )
936  {
937  d->joinStyle = QgsSymbolLayerUtils::decodePenJoinStyle( joinstr );
938  }
939  }
940 }
941 
943 {
944  QSet< QString > fields;
945  if ( d->markerSymbol )
946  {
947  fields.unite( d->markerSymbol->usedAttributes( context ) );
948  }
949  if ( d->fillSymbol )
950  {
951  fields.unite( d->fillSymbol->usedAttributes( context ) );
952  }
953  return fields;
954 }
QColor valueAsColor(int key, const QgsExpressionContext &context, const QColor &defaultColor=QColor(), bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a color.
bool valueAsBool(int key, const QgsExpressionContext &context, bool defaultValue=false, bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as an boolean.
double valueAsDouble(int key, const QgsExpressionContext &context, double defaultValue=0.0, bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a double.
static QgsPaintEffectRegistry * paintEffectRegistry()
Returns the application's paint effect registry, used for managing paint effects.
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for the context.
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
Definition: qgsfillsymbol.h:30
Q_INVOKABLE QVariant customProperty(const QString &value, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer.
Struct for storing maximum and minimum scales for measurements in map units.
A marker symbol type, for rendering Point and MultiPoint geometries.
static bool isDefaultStack(QgsPaintEffect *effect)
Tests whether a paint effect matches the default effects stack.
Base class for visual effects which can be applied to QPicture drawings.
virtual QVariantMap properties() const =0
Returns the properties describing the paint effect encoded in a string format.
static QgsPainting::BlendMode getBlendModeEnum(QPainter::CompositionMode blendMode)
Returns a BlendMode corresponding to a QPainter::CompositionMode.
Definition: qgspainting.cpp:80
static QPainter::CompositionMode getCompositionMode(QgsPainting::BlendMode blendMode)
Returns a QPainter::CompositionMode corresponding to a BlendMode.
Definition: qgspainting.cpp:20
BlendMode
Blending modes enum defining the available composition modes that can be used when rendering a layer.
Definition: qgspainting.h:37
@ ShapeOpacity
Shape opacity.
A grouped map of multiple QgsProperty objects, each referenced by a integer key value.
bool hasProperty(int key) const override
Returns true if the collection contains a property with the specified key.
QgsProperty property(int key) const override
Returns a matching property from the collection, if one exists.
QVariant value(int key, const QgsExpressionContext &context, const QVariant &defaultValue=QVariant()) const override
Returns the calculated value of the property with the specified key from within the collection.
void setProperty(int key, const QgsProperty &property)
Adds a property to the collection and takes ownership of it.
bool isActive(int key) const override
Returns true if the collection contains an active property with the specified key.
A store for object properties.
Definition: qgsproperty.h:232
The class is used as a container of context for various read/write operations on other objects.
const QgsPathResolver & pathResolver() const
Returns path resolver for conversion between relative and absolute paths.
Contains information about the context of a rendering operation.
QgsExpressionContext & expressionContext()
Gets the expression context.
const QgsPathResolver & pathResolver() const
Returns the path resolver for conversion between relative and absolute paths during rendering operati...
void setStrokeWidthMapUnitScale(const QgsMapUnitScale &scale)
void setPenJoinStyle(Qt::PenJoinStyle style)
void setStrokeWidth(double strokeWidth)
void setStrokeStyle(Qt::PenStyle strokeStyle)
void setStrokeWidthUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the width of the fill's stroke.
static Qt::PenJoinStyle decodePenJoinStyle(const QString &str)
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
static QColor decodeColor(const QString &str)
static QString svgSymbolPathToName(const QString &path, const QgsPathResolver &pathResolver)
Determines an SVG symbol's name from its path.
static QPointF toPoint(const QVariant &value, bool *ok=nullptr)
Converts a value to a point.
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
static QSizeF toSize(const QVariant &value, bool *ok=nullptr)
Converts a value to a size.
static QPainter::CompositionMode decodeBlendMode(const QString &s)
static QString svgSymbolNameToPath(const QString &name, const QgsPathResolver &pathResolver)
Determines an SVG symbol's path from its name.
static QString encodeColor(const QColor &color)
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
static QString symbolProperties(QgsSymbol *symbol)
Returns a string representing the symbol.
@ PropertyJoinStyle
Line join style.
@ PropertyStrokeWidth
Stroke width.
@ PropertyFillColor
Fill color.
@ PropertyStrokeColor
Stroke color.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol layer's property collection, used for data defined overrides.
bool changeSymbolLayer(int index, QgsSymbolLayer *layer)
Deletes the current layer at the specified index and replaces it with layer.
Definition: qgssymbol.cpp:473
Container for settings relating to a text background object.
QgsMapUnitScale strokeWidthMapUnitScale() const
Returns the map unit scale object for the shape stroke width.
void setFillSymbol(QgsFillSymbol *symbol)
Sets the current fill symbol for the background shape.
RotationType rotationType() const
Returns the method used for rotating the background shape.
QString svgFile() const
Returns the absolute path to the background SVG file, if set.
QSizeF size() const
Returns the size of the background shape.
QSizeF radii() const
Returns the radii used for rounding the corners of shapes.
QSet< QString > referencedFields(const QgsRenderContext &context) const
Returns all field names referenced by the configuration (e.g.
QgsMapUnitScale radiiMapUnitScale() const
Returns the map unit scale object for the shape radii.
void upgradeDataDefinedProperties(QgsPropertyCollection &properties)
Upgrade data defined properties when reading a project file saved in QGIS prior to version 3....
void setOpacity(double opacity)
Sets the background shape's opacity.
void setStrokeColor(const QColor &color)
Sets the color used for outlining the background shape.
QgsUnitTypes::RenderUnit strokeWidthUnit() const
Returns the units used for the shape's stroke width.
void setSizeMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale object for the shape size.
QPainter::CompositionMode blendMode() const
Returns the blending mode used for drawing the background shape.
Qt::PenJoinStyle joinStyle() const
Returns the join style used for drawing the background shape.
SizeType
Methods for determining the background shape size.
@ SizeBuffer
Shape size is determined by adding a buffer margin around text.
bool enabled() const
Returns whether the background is enabled.
void readXml(const QDomElement &elem, const QgsReadWriteContext &context)
Read settings from a DOM element.
void setJoinStyle(Qt::PenJoinStyle style)
Sets the join style used for drawing the background shape.
void setRadiiUnit(QgsUnitTypes::RenderUnit units)
Sets the units used for the shape's radii.
double opacity() const
Returns the background shape's opacity.
bool operator!=(const QgsTextBackgroundSettings &other) const
void updateDataDefinedProperties(QgsRenderContext &context, const QgsPropertyCollection &properties)
Updates the format by evaluating current values of data defined properties.
void setStrokeWidthMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale object for the shape stroke width.
QgsUnitTypes::RenderUnit offsetUnit() const
Returns the units used for the shape's offset.
double rotation() const
Returns the rotation for the background shape, in degrees clockwise.
QColor fillColor() const
Returns the color used for filing the background shape.
void setMarkerSymbol(QgsMarkerSymbol *symbol)
Sets the current marker symbol for the background shape.
void setRadii(QSizeF radii)
Sets the radii used for rounding the corners of shapes.
SizeType sizeType() const
Returns the method used to determine the size of the background shape (e.g., fixed size or buffer aro...
QgsTextBackgroundSettings & operator=(const QgsTextBackgroundSettings &other)
ShapeType type() const
Returns the type of background shape (e.g., square, ellipse, SVG).
double strokeWidth() const
Returns the width of the shape's stroke (stroke).
void setSizeType(SizeType type)
Sets the method used to determine the size of the background shape (e.g., fixed size or buffer around...
ShapeType
Background shape types.
void setFillColor(const QColor &color)
Sets the color used for filing the background shape.
void setPaintEffect(QgsPaintEffect *effect)
Sets the current paint effect for the background shape.
void setStrokeWidthUnit(QgsUnitTypes::RenderUnit units)
Sets the units used for the shape's stroke width.
QColor strokeColor() const
Returns the color used for outlining the background shape.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Write settings into a DOM element.
void setRotationType(RotationType type)
Sets the method used for rotating the background shape.
void setOffsetMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale object for the shape offset.
QgsFillSymbol * fillSymbol() const
Returns the fill symbol to be rendered in the background.
void setBlendMode(QPainter::CompositionMode mode)
Sets the blending mode used for drawing the background shape.
void readFromLayer(QgsVectorLayer *layer)
Reads settings from a layer's custom properties (for QGIS 2.x projects).
QgsMapUnitScale sizeMapUnitScale() const
Returns the map unit scale object for the shape size.
void setType(ShapeType type)
Sets the type of background shape to draw (e.g., square, ellipse, SVG).
QgsUnitTypes::RenderUnit sizeUnit() const
Returns the units used for the shape's size.
RotationType
Methods for determining the rotation of the background shape.
@ RotationSync
Shape rotation is synced with text rotation.
bool operator==(const QgsTextBackgroundSettings &other) const
QgsUnitTypes::RenderUnit radiiUnit() const
Returns the units used for the shape's radii.
void setEnabled(bool enabled)
Sets whether the text background will be drawn.
QgsMarkerSymbol * markerSymbol() const
Returns the marker symbol to be rendered in the background.
void setRadiiMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale object for the shape radii.
void setRotation(double rotation)
Sets the rotation for the background shape, in degrees clockwise.
void setOffset(QPointF offset)
Sets the offset used for drawing the background shape.
void setSize(QSizeF size)
Sets the size of the background shape.
void setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the units used for the shape's size.
const QgsPaintEffect * paintEffect() const
Returns the current paint effect for the background shape.
void setSvgFile(const QString &file)
Sets the path to the background SVG file.
QgsMapUnitScale offsetMapUnitScale() const
Returns the map unit scale object for the shape offset.
void setStrokeWidth(double width)
Sets the width of the shape's stroke (stroke).
QPointF offset() const
Returns the offset used for drawing the background shape.
void setOffsetUnit(QgsUnitTypes::RenderUnit units)
Sets the units used for the shape's offset.
static QgsTextBackgroundSettings::ShapeType decodeShapeType(const QString &string)
Decodes a string representation of a background shape type to a type.
static QColor readColor(QgsVectorLayer *layer, const QString &property, const QColor &defaultColor=Qt::black, bool withAlpha=true)
Converts an encoded color value from a layer property.
static QgsTextBackgroundSettings::RotationType decodeBackgroundRotationType(const QString &string)
Decodes a string representation of a background rotation type to a type.
static QgsTextBackgroundSettings::SizeType decodeBackgroundSizeType(const QString &string)
Decodes a string representation of a background size type to a type.
static QgsUnitTypes::RenderUnit convertFromOldLabelUnit(int val)
Converts a unit from an old (pre 3.0) label unit.
static Q_INVOKABLE QString encodeUnit(QgsUnitTypes::DistanceUnit unit)
Encodes a distance unit to a string.
static Q_INVOKABLE QgsUnitTypes::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
RenderUnit
Rendering size units.
Definition: qgsunittypes.h:168
Represents a vector layer which manages a vector based data sets.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:598