QGIS API Documentation 3.29.0-Master (19d7edcfed)
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
28{
29 d = new QgsTextBufferSettingsPrivate();
30}
31
33 : d( other.d )
34{
35}
36
38{
39 d = other.d;
40 return *this;
41}
42
44{
45
46}
47
49{
50 if ( d->enabled != other.enabled()
51 || d->size != other.size()
52 || d->sizeUnit != other.sizeUnit()
53 || d->sizeMapUnitScale != other.sizeMapUnitScale()
54 || d->color != other.color()
55 || d->opacity != other.opacity()
56 || d->fillBufferInterior != other.fillBufferInterior()
57 || d->joinStyle != other.joinStyle()
58 || d->blendMode != other.blendMode() )
59 return false;
60
61 if ( static_cast< bool >( d->paintEffect ) != static_cast< bool >( other.paintEffect() )
62 || ( d->paintEffect && d->paintEffect->properties() != other.paintEffect()->properties() ) )
63 return false;
64
65 return true;
66}
67
69{
70 return !( *this == other );
71}
72
74{
75 return d->enabled;
76}
77
79{
80 d->enabled = enabled;
81}
82
84{
85 return d->size;
86}
87
89{
90 d->size = size;
91}
92
94{
95 return d->sizeUnit;
96}
97
99{
100 d->sizeUnit = unit;
101}
102
104{
105 return d->sizeMapUnitScale;
106}
107
109{
110 d->sizeMapUnitScale = scale;
111}
112
114{
115 return d->color;
116}
117
118void QgsTextBufferSettings::setColor( const QColor &color )
119{
120 d->color = color;
121}
122
124{
125 return d->fillBufferInterior;
126}
127
129{
130 d->fillBufferInterior = fill;
131}
132
134{
135 return d->opacity;
136}
137
139{
140 d->opacity = opacity;
141}
142
143Qt::PenJoinStyle QgsTextBufferSettings::joinStyle() const
144{
145 return d->joinStyle;
146}
147
148void QgsTextBufferSettings::setJoinStyle( Qt::PenJoinStyle style )
149{
150 d->joinStyle = style;
151}
152
153QPainter::CompositionMode QgsTextBufferSettings::blendMode() const
154{
155 return d->blendMode;
156}
157
158void QgsTextBufferSettings::setBlendMode( QPainter::CompositionMode mode )
159{
160 d->blendMode = mode;
161}
162
164{
165 return d->paintEffect.get();
166}
167
169{
170 d->paintEffect.reset( effect );
171}
172
174{
175 if ( properties.isActive( QgsPalLayerSettings::BufferDraw ) )
176 {
177 context.expressionContext().setOriginalValueVariable( d->enabled );
178 d->enabled = properties.valueAsBool( QgsPalLayerSettings::BufferDraw, context.expressionContext(), d->enabled );
179 }
180
181 if ( properties.isActive( QgsPalLayerSettings::BufferSize ) )
182 {
183 context.expressionContext().setOriginalValueVariable( d->size );
184 d->size = properties.valueAsDouble( QgsPalLayerSettings::BufferSize, context.expressionContext(), d->size );
185 }
186
187 QVariant exprVal = properties.value( QgsPalLayerSettings::BufferUnit, context.expressionContext() );
188 if ( !QgsVariantUtils::isNull( exprVal ) )
189 {
190 const QString units = exprVal.toString();
191 if ( !units.isEmpty() )
192 {
193 bool ok;
195 if ( ok )
196 d->sizeUnit = res;
197 }
198 }
199
201 {
202 context.expressionContext().setOriginalValueVariable( d->opacity * 100 );
203 const QVariant val = properties.value( QgsPalLayerSettings::BufferOpacity, context.expressionContext(), d->opacity * 100 );
204 if ( !QgsVariantUtils::isNull( val ) )
205 {
206 d->opacity = val.toDouble() / 100.0;
207 }
208 }
209
210 if ( properties.isActive( QgsPalLayerSettings::BufferColor ) )
211 {
213 d->color = properties.valueAsColor( QgsPalLayerSettings::BufferColor, context.expressionContext(), d->color );
214 }
215
217 {
218 exprVal = properties.value( QgsPalLayerSettings::BufferBlendMode, context.expressionContext() );
219 const QString blendstr = exprVal.toString().trimmed();
220 if ( !blendstr.isEmpty() )
221 d->blendMode = QgsSymbolLayerUtils::decodeBlendMode( blendstr );
222 }
223
225 {
226 exprVal = properties.value( QgsPalLayerSettings::BufferJoinStyle, context.expressionContext() );
227 const QString joinstr = exprVal.toString().trimmed();
228 if ( !joinstr.isEmpty() )
229 {
230 d->joinStyle = QgsSymbolLayerUtils::decodePenJoinStyle( joinstr );
231 }
232 }
233}
234
236{
237 return QSet< QString >(); // nothing for now
238}
239
241{
242 // text buffer
243 const double bufSize = layer->customProperty( QStringLiteral( "labeling/bufferSize" ), QVariant( 0.0 ) ).toDouble();
244
245 // fix for buffer being keyed off of just its size in the past (<2.0)
246 const QVariant drawBuffer = layer->customProperty( QStringLiteral( "labeling/bufferDraw" ), QVariant() );
247 if ( drawBuffer.isValid() )
248 {
249 d->enabled = drawBuffer.toBool();
250 d->size = bufSize;
251 }
252 else if ( bufSize != 0.0 )
253 {
254 d->enabled = true;
255 d->size = bufSize;
256 }
257 else
258 {
259 // keep bufferSize at new 1.0 default
260 d->enabled = false;
261 }
262
263 if ( layer->customProperty( QStringLiteral( "labeling/bufferSizeUnits" ) ).toString().isEmpty() )
264 {
265 const bool bufferSizeInMapUnits = layer->customProperty( QStringLiteral( "labeling/bufferSizeInMapUnits" ) ).toBool();
266 d->sizeUnit = bufferSizeInMapUnits ? QgsUnitTypes::RenderMapUnits : QgsUnitTypes::RenderMillimeters;
267 }
268 else
269 {
270 d->sizeUnit = QgsUnitTypes::decodeRenderUnit( layer->customProperty( QStringLiteral( "labeling/bufferSizeUnits" ) ).toString() );
271 }
272
273 if ( layer->customProperty( QStringLiteral( "labeling/bufferSizeMapUnitScale" ) ).toString().isEmpty() )
274 {
275 //fallback to older property
276 const double oldMin = layer->customProperty( QStringLiteral( "labeling/bufferSizeMapUnitMinScale" ), 0.0 ).toDouble();
277 d->sizeMapUnitScale.minScale = oldMin != 0 ? 1.0 / oldMin : 0;
278 const double oldMax = layer->customProperty( QStringLiteral( "labeling/bufferSizeMapUnitMaxScale" ), 0.0 ).toDouble();
279 d->sizeMapUnitScale.maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
280 }
281 else
282 {
283 d->sizeMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( layer->customProperty( QStringLiteral( "labeling/bufferSizeMapUnitScale" ) ).toString() );
284 }
285 d->color = QgsTextRendererUtils::readColor( layer, QStringLiteral( "labeling/bufferColor" ), Qt::white, false );
286 if ( layer->customProperty( QStringLiteral( "labeling/bufferOpacity" ) ).toString().isEmpty() )
287 {
288 d->opacity = ( 1 - layer->customProperty( QStringLiteral( "labeling/bufferTransp" ) ).toInt() / 100.0 ); //0 -100
289 }
290 else
291 {
292 d->opacity = ( layer->customProperty( QStringLiteral( "labeling/bufferOpacity" ) ).toDouble() );
293 }
294 d->blendMode = QgsPainting::getCompositionMode(
295 static_cast< QgsPainting::BlendMode >( layer->customProperty( QStringLiteral( "labeling/bufferBlendMode" ), QVariant( QgsPainting::BlendNormal ) ).toUInt() ) );
296 d->joinStyle = static_cast< Qt::PenJoinStyle >( layer->customProperty( QStringLiteral( "labeling/bufferJoinStyle" ), QVariant( Qt::RoundJoin ) ).toUInt() );
297
298 d->fillBufferInterior = !layer->customProperty( QStringLiteral( "labeling/bufferNoFill" ), QVariant( false ) ).toBool();
299
300 if ( layer->customProperty( QStringLiteral( "labeling/bufferEffect" ) ).isValid() )
301 {
302 QDomDocument doc( QStringLiteral( "effect" ) );
303 doc.setContent( layer->customProperty( QStringLiteral( "labeling/bufferEffect" ) ).toString() );
304 const QDomElement effectElem = doc.firstChildElement( QStringLiteral( "effect" ) ).firstChildElement( QStringLiteral( "effect" ) );
305 setPaintEffect( QgsApplication::paintEffectRegistry()->createEffect( effectElem ) );
306 }
307 else
308 setPaintEffect( nullptr );
309}
310
311void QgsTextBufferSettings::readXml( const QDomElement &elem )
312{
313 const QDomElement textBufferElem = elem.firstChildElement( QStringLiteral( "text-buffer" ) );
314 const double bufSize = textBufferElem.attribute( QStringLiteral( "bufferSize" ), QStringLiteral( "0" ) ).toDouble();
315
316 // fix for buffer being keyed off of just its size in the past (<2.0)
317 const QVariant drawBuffer = textBufferElem.attribute( QStringLiteral( "bufferDraw" ) );
318 if ( drawBuffer.isValid() )
319 {
320 d->enabled = drawBuffer.toBool();
321 d->size = bufSize;
322 }
323 else if ( bufSize != 0.0 )
324 {
325 d->enabled = true;
326 d->size = bufSize;
327 }
328 else
329 {
330 // keep bufferSize at new 1.0 default
331 d->enabled = false;
332 }
333
334 if ( !textBufferElem.hasAttribute( QStringLiteral( "bufferSizeUnits" ) ) )
335 {
336 const bool bufferSizeInMapUnits = textBufferElem.attribute( QStringLiteral( "bufferSizeInMapUnits" ) ).toInt();
337 d->sizeUnit = bufferSizeInMapUnits ? QgsUnitTypes::RenderMapUnits : QgsUnitTypes::RenderMillimeters;
338 }
339 else
340 {
341 d->sizeUnit = QgsUnitTypes::decodeRenderUnit( textBufferElem.attribute( QStringLiteral( "bufferSizeUnits" ) ) );
342 }
343
344 if ( !textBufferElem.hasAttribute( QStringLiteral( "bufferSizeMapUnitScale" ) ) )
345 {
346 //fallback to older property
347 const double oldMin = textBufferElem.attribute( QStringLiteral( "bufferSizeMapUnitMinScale" ), QStringLiteral( "0" ) ).toDouble();
348 d->sizeMapUnitScale.minScale = oldMin != 0 ? 1.0 / oldMin : 0;
349 const double oldMax = textBufferElem.attribute( QStringLiteral( "bufferSizeMapUnitMaxScale" ), QStringLiteral( "0" ) ).toDouble();
350 d->sizeMapUnitScale.maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
351 }
352 else
353 {
354 d->sizeMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( textBufferElem.attribute( QStringLiteral( "bufferSizeMapUnitScale" ) ) );
355 }
356 d->color = QgsSymbolLayerUtils::decodeColor( textBufferElem.attribute( QStringLiteral( "bufferColor" ), QgsSymbolLayerUtils::encodeColor( Qt::white ) ) );
357
358 if ( !textBufferElem.hasAttribute( QStringLiteral( "bufferOpacity" ) ) )
359 {
360 d->opacity = ( 1 - textBufferElem.attribute( QStringLiteral( "bufferTransp" ) ).toInt() / 100.0 ); //0 -100
361 }
362 else
363 {
364 d->opacity = ( textBufferElem.attribute( QStringLiteral( "bufferOpacity" ) ).toDouble() );
365 }
366
367 d->blendMode = QgsPainting::getCompositionMode(
368 static_cast< QgsPainting::BlendMode >( textBufferElem.attribute( QStringLiteral( "bufferBlendMode" ), QString::number( QgsPainting::BlendNormal ) ).toUInt() ) );
369 d->joinStyle = static_cast< Qt::PenJoinStyle >( textBufferElem.attribute( QStringLiteral( "bufferJoinStyle" ), QString::number( Qt::RoundJoin ) ).toUInt() );
370 d->fillBufferInterior = !textBufferElem.attribute( QStringLiteral( "bufferNoFill" ), QStringLiteral( "0" ) ).toInt();
371 const QDomElement effectElem = textBufferElem.firstChildElement( QStringLiteral( "effect" ) );
372 if ( !effectElem.isNull() )
374 else
375 setPaintEffect( nullptr );
376}
377
378QDomElement QgsTextBufferSettings::writeXml( QDomDocument &doc ) const
379{
380 // text buffer
381 QDomElement textBufferElem = doc.createElement( QStringLiteral( "text-buffer" ) );
382 textBufferElem.setAttribute( QStringLiteral( "bufferDraw" ), d->enabled );
383 textBufferElem.setAttribute( QStringLiteral( "bufferSize" ), d->size );
384 textBufferElem.setAttribute( QStringLiteral( "bufferSizeUnits" ), QgsUnitTypes::encodeUnit( d->sizeUnit ) );
385 textBufferElem.setAttribute( QStringLiteral( "bufferSizeMapUnitScale" ), QgsSymbolLayerUtils::encodeMapUnitScale( d->sizeMapUnitScale ) );
386 textBufferElem.setAttribute( QStringLiteral( "bufferColor" ), QgsSymbolLayerUtils::encodeColor( d->color ) );
387 textBufferElem.setAttribute( QStringLiteral( "bufferNoFill" ), !d->fillBufferInterior );
388 textBufferElem.setAttribute( QStringLiteral( "bufferOpacity" ), d->opacity );
389 textBufferElem.setAttribute( QStringLiteral( "bufferJoinStyle" ), static_cast< unsigned int >( d->joinStyle ) );
390 textBufferElem.setAttribute( QStringLiteral( "bufferBlendMode" ), QgsPainting::getBlendModeEnum( d->blendMode ) );
391 if ( d->paintEffect && !QgsPaintEffectRegistry::isDefaultStack( d->paintEffect.get() ) )
392 d->paintEffect->saveProperties( doc, textBufferElem );
393 return textBufferElem;
394}
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 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
@ 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.
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.
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.
QgsUnitTypes::RenderUnit sizeUnit() const
Returns the units for the buffer size.
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 setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the units used for the buffer size.
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 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
@ RenderMillimeters
Millimeters.
Definition: qgsunittypes.h:169
@ RenderMapUnits
Map units.
Definition: qgsunittypes.h:170
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.