QGIS API Documentation 3.30.0-'s-Hertogenbosch (f186b8efe0)
qgstextbuffersettings.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgstextbuffersettings.cpp
3 -----------------
4 begin : May 2020
5 copyright : (C) Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7
8 ***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
16
18#include "qgstextrenderer_p.h"
19#include "qgsvectorlayer.h"
20#include "qgspallabeling.h"
21#include "qgssymbollayerutils.h"
22#include "qgspainting.h"
25#include "qgsapplication.h"
26#include "qgsunittypes.h"
27
29{
30 d = new QgsTextBufferSettingsPrivate();
31}
32
34 : d( other.d )
35{
36}
37
39{
40 d = other.d;
41 return *this;
42}
43
45{
46
47}
48
50{
51 if ( d->enabled != other.enabled()
52 || d->size != other.size()
53 || d->sizeUnit != other.sizeUnit()
54 || d->sizeMapUnitScale != other.sizeMapUnitScale()
55 || d->color != other.color()
56 || d->opacity != other.opacity()
57 || d->fillBufferInterior != other.fillBufferInterior()
58 || d->joinStyle != other.joinStyle()
59 || d->blendMode != other.blendMode() )
60 return false;
61
62 if ( static_cast< bool >( d->paintEffect ) != static_cast< bool >( other.paintEffect() )
63 || ( d->paintEffect && d->paintEffect->properties() != other.paintEffect()->properties() ) )
64 return false;
65
66 return true;
67}
68
70{
71 return !( *this == other );
72}
73
75{
76 return d->enabled;
77}
78
80{
81 d->enabled = enabled;
82}
83
85{
86 return d->size;
87}
88
90{
91 d->size = size;
92}
93
95{
96 return d->sizeUnit;
97}
98
100{
101 d->sizeUnit = unit;
102}
103
105{
106 return d->sizeMapUnitScale;
107}
108
110{
111 d->sizeMapUnitScale = scale;
112}
113
115{
116 return d->color;
117}
118
119void QgsTextBufferSettings::setColor( const QColor &color )
120{
121 d->color = color;
122}
123
125{
126 return d->fillBufferInterior;
127}
128
130{
131 d->fillBufferInterior = fill;
132}
133
135{
136 return d->opacity;
137}
138
140{
141 d->opacity = opacity;
142}
143
144Qt::PenJoinStyle QgsTextBufferSettings::joinStyle() const
145{
146 return d->joinStyle;
147}
148
149void QgsTextBufferSettings::setJoinStyle( Qt::PenJoinStyle style )
150{
151 d->joinStyle = style;
152}
153
154QPainter::CompositionMode QgsTextBufferSettings::blendMode() const
155{
156 return d->blendMode;
157}
158
159void QgsTextBufferSettings::setBlendMode( QPainter::CompositionMode mode )
160{
161 d->blendMode = mode;
162}
163
165{
166 return d->paintEffect.get();
167}
168
170{
171 d->paintEffect.reset( effect );
172}
173
175{
176 if ( properties.isActive( QgsPalLayerSettings::BufferDraw ) )
177 {
178 context.expressionContext().setOriginalValueVariable( d->enabled );
179 d->enabled = properties.valueAsBool( QgsPalLayerSettings::BufferDraw, context.expressionContext(), d->enabled );
180 }
181
182 if ( properties.isActive( QgsPalLayerSettings::BufferSize ) )
183 {
184 context.expressionContext().setOriginalValueVariable( d->size );
185 d->size = properties.valueAsDouble( QgsPalLayerSettings::BufferSize, context.expressionContext(), d->size );
186 }
187
188 QVariant exprVal = properties.value( QgsPalLayerSettings::BufferUnit, context.expressionContext() );
189 if ( !QgsVariantUtils::isNull( exprVal ) )
190 {
191 const QString units = exprVal.toString();
192 if ( !units.isEmpty() )
193 {
194 bool ok;
195 const Qgis::RenderUnit res = QgsUnitTypes::decodeRenderUnit( units, &ok );
196 if ( ok )
197 d->sizeUnit = res;
198 }
199 }
200
202 {
203 context.expressionContext().setOriginalValueVariable( d->opacity * 100 );
204 const QVariant val = properties.value( QgsPalLayerSettings::BufferOpacity, context.expressionContext(), d->opacity * 100 );
205 if ( !QgsVariantUtils::isNull( val ) )
206 {
207 d->opacity = val.toDouble() / 100.0;
208 }
209 }
210
211 if ( properties.isActive( QgsPalLayerSettings::BufferColor ) )
212 {
214 d->color = properties.valueAsColor( QgsPalLayerSettings::BufferColor, context.expressionContext(), d->color );
215 }
216
218 {
219 exprVal = properties.value( QgsPalLayerSettings::BufferBlendMode, context.expressionContext() );
220 const QString blendstr = exprVal.toString().trimmed();
221 if ( !blendstr.isEmpty() )
222 d->blendMode = QgsSymbolLayerUtils::decodeBlendMode( blendstr );
223 }
224
226 {
227 exprVal = properties.value( QgsPalLayerSettings::BufferJoinStyle, context.expressionContext() );
228 const QString joinstr = exprVal.toString().trimmed();
229 if ( !joinstr.isEmpty() )
230 {
231 d->joinStyle = QgsSymbolLayerUtils::decodePenJoinStyle( joinstr );
232 }
233 }
234}
235
237{
238 return QSet< QString >(); // nothing for now
239}
240
242{
243 // text buffer
244 const double bufSize = layer->customProperty( QStringLiteral( "labeling/bufferSize" ), QVariant( 0.0 ) ).toDouble();
245
246 // fix for buffer being keyed off of just its size in the past (<2.0)
247 const QVariant drawBuffer = layer->customProperty( QStringLiteral( "labeling/bufferDraw" ), QVariant() );
248 if ( drawBuffer.isValid() )
249 {
250 d->enabled = drawBuffer.toBool();
251 d->size = bufSize;
252 }
253 else if ( bufSize != 0.0 )
254 {
255 d->enabled = true;
256 d->size = bufSize;
257 }
258 else
259 {
260 // keep bufferSize at new 1.0 default
261 d->enabled = false;
262 }
263
264 if ( layer->customProperty( QStringLiteral( "labeling/bufferSizeUnits" ) ).toString().isEmpty() )
265 {
266 const bool bufferSizeInMapUnits = layer->customProperty( QStringLiteral( "labeling/bufferSizeInMapUnits" ) ).toBool();
267 d->sizeUnit = bufferSizeInMapUnits ? Qgis::RenderUnit::MapUnits : Qgis::RenderUnit::Millimeters;
268 }
269 else
270 {
271 d->sizeUnit = QgsUnitTypes::decodeRenderUnit( layer->customProperty( QStringLiteral( "labeling/bufferSizeUnits" ) ).toString() );
272 }
273
274 if ( layer->customProperty( QStringLiteral( "labeling/bufferSizeMapUnitScale" ) ).toString().isEmpty() )
275 {
276 //fallback to older property
277 const double oldMin = layer->customProperty( QStringLiteral( "labeling/bufferSizeMapUnitMinScale" ), 0.0 ).toDouble();
278 d->sizeMapUnitScale.minScale = oldMin != 0 ? 1.0 / oldMin : 0;
279 const double oldMax = layer->customProperty( QStringLiteral( "labeling/bufferSizeMapUnitMaxScale" ), 0.0 ).toDouble();
280 d->sizeMapUnitScale.maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
281 }
282 else
283 {
284 d->sizeMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( layer->customProperty( QStringLiteral( "labeling/bufferSizeMapUnitScale" ) ).toString() );
285 }
286 d->color = QgsTextRendererUtils::readColor( layer, QStringLiteral( "labeling/bufferColor" ), Qt::white, false );
287 if ( layer->customProperty( QStringLiteral( "labeling/bufferOpacity" ) ).toString().isEmpty() )
288 {
289 d->opacity = ( 1 - layer->customProperty( QStringLiteral( "labeling/bufferTransp" ) ).toInt() / 100.0 ); //0 -100
290 }
291 else
292 {
293 d->opacity = ( layer->customProperty( QStringLiteral( "labeling/bufferOpacity" ) ).toDouble() );
294 }
295 d->blendMode = QgsPainting::getCompositionMode(
296 static_cast< Qgis::BlendMode >( layer->customProperty( QStringLiteral( "labeling/bufferBlendMode" ), QVariant( static_cast< int >( Qgis::BlendMode::Normal ) ) ).toUInt() ) );
297 d->joinStyle = static_cast< Qt::PenJoinStyle >( layer->customProperty( QStringLiteral( "labeling/bufferJoinStyle" ), QVariant( Qt::RoundJoin ) ).toUInt() );
298
299 d->fillBufferInterior = !layer->customProperty( QStringLiteral( "labeling/bufferNoFill" ), QVariant( false ) ).toBool();
300
301 if ( layer->customProperty( QStringLiteral( "labeling/bufferEffect" ) ).isValid() )
302 {
303 QDomDocument doc( QStringLiteral( "effect" ) );
304 doc.setContent( layer->customProperty( QStringLiteral( "labeling/bufferEffect" ) ).toString() );
305 const QDomElement effectElem = doc.firstChildElement( QStringLiteral( "effect" ) ).firstChildElement( QStringLiteral( "effect" ) );
306 setPaintEffect( QgsApplication::paintEffectRegistry()->createEffect( effectElem ) );
307 }
308 else
309 setPaintEffect( nullptr );
310}
311
312void QgsTextBufferSettings::readXml( const QDomElement &elem )
313{
314 const QDomElement textBufferElem = elem.firstChildElement( QStringLiteral( "text-buffer" ) );
315 const double bufSize = textBufferElem.attribute( QStringLiteral( "bufferSize" ), QStringLiteral( "0" ) ).toDouble();
316
317 // fix for buffer being keyed off of just its size in the past (<2.0)
318 const QVariant drawBuffer = textBufferElem.attribute( QStringLiteral( "bufferDraw" ) );
319 if ( drawBuffer.isValid() )
320 {
321 d->enabled = drawBuffer.toBool();
322 d->size = bufSize;
323 }
324 else if ( bufSize != 0.0 )
325 {
326 d->enabled = true;
327 d->size = bufSize;
328 }
329 else
330 {
331 // keep bufferSize at new 1.0 default
332 d->enabled = false;
333 }
334
335 if ( !textBufferElem.hasAttribute( QStringLiteral( "bufferSizeUnits" ) ) )
336 {
337 const bool bufferSizeInMapUnits = textBufferElem.attribute( QStringLiteral( "bufferSizeInMapUnits" ) ).toInt();
338 d->sizeUnit = bufferSizeInMapUnits ? Qgis::RenderUnit::MapUnits : Qgis::RenderUnit::Millimeters;
339 }
340 else
341 {
342 d->sizeUnit = QgsUnitTypes::decodeRenderUnit( textBufferElem.attribute( QStringLiteral( "bufferSizeUnits" ) ) );
343 }
344
345 if ( !textBufferElem.hasAttribute( QStringLiteral( "bufferSizeMapUnitScale" ) ) )
346 {
347 //fallback to older property
348 const double oldMin = textBufferElem.attribute( QStringLiteral( "bufferSizeMapUnitMinScale" ), QStringLiteral( "0" ) ).toDouble();
349 d->sizeMapUnitScale.minScale = oldMin != 0 ? 1.0 / oldMin : 0;
350 const double oldMax = textBufferElem.attribute( QStringLiteral( "bufferSizeMapUnitMaxScale" ), QStringLiteral( "0" ) ).toDouble();
351 d->sizeMapUnitScale.maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
352 }
353 else
354 {
355 d->sizeMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( textBufferElem.attribute( QStringLiteral( "bufferSizeMapUnitScale" ) ) );
356 }
357 d->color = QgsSymbolLayerUtils::decodeColor( textBufferElem.attribute( QStringLiteral( "bufferColor" ), QgsSymbolLayerUtils::encodeColor( Qt::white ) ) );
358
359 if ( !textBufferElem.hasAttribute( QStringLiteral( "bufferOpacity" ) ) )
360 {
361 d->opacity = ( 1 - textBufferElem.attribute( QStringLiteral( "bufferTransp" ) ).toInt() / 100.0 ); //0 -100
362 }
363 else
364 {
365 d->opacity = ( textBufferElem.attribute( QStringLiteral( "bufferOpacity" ) ).toDouble() );
366 }
367
368 d->blendMode = QgsPainting::getCompositionMode(
369 static_cast< Qgis::BlendMode >( textBufferElem.attribute( QStringLiteral( "bufferBlendMode" ), QString::number( static_cast< int >( Qgis::BlendMode::Normal ) ) ).toUInt() ) );
370 d->joinStyle = static_cast< Qt::PenJoinStyle >( textBufferElem.attribute( QStringLiteral( "bufferJoinStyle" ), QString::number( Qt::RoundJoin ) ).toUInt() );
371 d->fillBufferInterior = !textBufferElem.attribute( QStringLiteral( "bufferNoFill" ), QStringLiteral( "0" ) ).toInt();
372 const QDomElement effectElem = textBufferElem.firstChildElement( QStringLiteral( "effect" ) );
373 if ( !effectElem.isNull() )
375 else
376 setPaintEffect( nullptr );
377}
378
379QDomElement QgsTextBufferSettings::writeXml( QDomDocument &doc ) const
380{
381 // text buffer
382 QDomElement textBufferElem = doc.createElement( QStringLiteral( "text-buffer" ) );
383 textBufferElem.setAttribute( QStringLiteral( "bufferDraw" ), d->enabled );
384 textBufferElem.setAttribute( QStringLiteral( "bufferSize" ), d->size );
385 textBufferElem.setAttribute( QStringLiteral( "bufferSizeUnits" ), QgsUnitTypes::encodeUnit( d->sizeUnit ) );
386 textBufferElem.setAttribute( QStringLiteral( "bufferSizeMapUnitScale" ), QgsSymbolLayerUtils::encodeMapUnitScale( d->sizeMapUnitScale ) );
387 textBufferElem.setAttribute( QStringLiteral( "bufferColor" ), QgsSymbolLayerUtils::encodeColor( d->color ) );
388 textBufferElem.setAttribute( QStringLiteral( "bufferNoFill" ), !d->fillBufferInterior );
389 textBufferElem.setAttribute( QStringLiteral( "bufferOpacity" ), d->opacity );
390 textBufferElem.setAttribute( QStringLiteral( "bufferJoinStyle" ), static_cast< unsigned int >( d->joinStyle ) );
391 textBufferElem.setAttribute( QStringLiteral( "bufferBlendMode" ), static_cast< int >( QgsPainting::getBlendModeEnum( d->blendMode ) ) );
392 if ( d->paintEffect && !QgsPaintEffectRegistry::isDefaultStack( d->paintEffect.get() ) )
393 d->paintEffect->saveProperties( doc, textBufferElem );
394 return textBufferElem;
395}
BlendMode
Blending modes defining the available composition modes that can be used when painting.
Definition: qgis.h:2978
RenderUnit
Rendering size units.
Definition: qgis.h:3176
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.
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.
static bool isDefaultStack(QgsPaintEffect *effect)
Tests whether a paint effect matches the default effects stack.
QgsPaintEffect * createEffect(const QString &name, const QVariantMap &properties=QVariantMap()) const
Creates a new paint effect given the effect name and properties map.
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 Qgis::BlendMode getBlendModeEnum(QPainter::CompositionMode blendMode)
Returns a BlendMode corresponding to a QPainter::CompositionMode.
Definition: qgspainting.cpp:80
static QPainter::CompositionMode getCompositionMode(Qgis::BlendMode blendMode)
Returns a QPainter::CompositionMode corresponding to a BlendMode.
Definition: qgspainting.cpp:20
@ BufferOpacity
Buffer opacity.
A grouped map of multiple QgsProperty objects, each referenced by a integer key value.
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.
bool isActive(int key) const override
Returns true if the collection contains an active property with the specified key.
Contains information about the context of a rendering operation.
QgsExpressionContext & expressionContext()
Gets the expression context.
static Qt::PenJoinStyle decodePenJoinStyle(const QString &str)
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
static QColor decodeColor(const QString &str)
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
static QPainter::CompositionMode decodeBlendMode(const QString &s)
static QString encodeColor(const QColor &color)
Container for settings relating to a text buffer.
QgsTextBufferSettings & operator=(const QgsTextBufferSettings &other)
Copy constructor.
void setFillBufferInterior(bool fill)
Sets whether the interior of the buffer will be filled in.
void setBlendMode(QPainter::CompositionMode mode)
Sets the blending mode used for drawing the buffer.
Qgis::RenderUnit sizeUnit() const
Returns the units for the buffer size.
void readFromLayer(QgsVectorLayer *layer)
Reads settings from a layer's custom properties (for QGIS 2.x projects).
QSet< QString > referencedFields(const QgsRenderContext &context) const
Returns all field names referenced by the configuration (e.g.
Qt::PenJoinStyle joinStyle() const
Returns the buffer join style.
double size() const
Returns the size of the buffer.
void setColor(const QColor &color)
Sets the color for the buffer.
void setSizeMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale object for the buffer size.
void setOpacity(double opacity)
Sets the buffer opacity.
QgsMapUnitScale sizeMapUnitScale() const
Returns the map unit scale object for the buffer size.
bool enabled() const
Returns whether the buffer is enabled.
double opacity() const
Returns the buffer opacity.
void setSizeUnit(Qgis::RenderUnit unit)
Sets the units used for the buffer size.
bool operator!=(const QgsTextBufferSettings &other) const
QDomElement writeXml(QDomDocument &doc) const
Write settings into a DOM element.
bool fillBufferInterior() const
Returns whether the interior of the buffer will be filled in.
void setEnabled(bool enabled)
Sets whether the text buffer will be drawn.
void setPaintEffect(QgsPaintEffect *effect)
Sets the current paint effect for the buffer.
const QgsPaintEffect * paintEffect() const
Returns the current paint effect for the buffer.
QColor color() const
Returns the color of the buffer.
bool operator==(const QgsTextBufferSettings &other) const
QPainter::CompositionMode blendMode() const
Returns the blending mode used for drawing the buffer.
void updateDataDefinedProperties(QgsRenderContext &context, const QgsPropertyCollection &properties)
Updates the format by evaluating current values of data defined properties.
void setJoinStyle(Qt::PenJoinStyle style)
Sets the join style used for drawing the buffer.
void setSize(double size)
Sets the size of the buffer.
void readXml(const QDomElement &elem)
Read settings from a DOM element.
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 Q_INVOKABLE Qgis::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
static Q_INVOKABLE QString encodeUnit(Qgis::DistanceUnit unit)
Encodes a distance unit to a string.
static bool isNull(const QVariant &variant)
Returns true if the specified variant should be considered a NULL value.
Represents a vector layer which manages a vector based data sets.