QGIS API Documentation 4.0.0-Norrköping (1ddcee3d0e4)
Loading...
Searching...
No Matches
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
19#include "qgsapplication.h"
20#include "qgscolorutils.h"
22#include "qgspainting.h"
23#include "qgspallabeling.h"
24#include "qgssymbollayerutils.h"
25#include "qgstextrenderer_p.h"
27#include "qgsunittypes.h"
28#include "qgsvectorlayer.h"
29
30#include <QString>
31
32using namespace Qt::StringLiterals;
33
35{
36 d = new QgsTextBufferSettingsPrivate();
37}
38
40 : d( other.d )
41{}
43 : d( std::move( other.d ) )
44{}
45
47{
48 if ( &other == this )
49 return *this;
50
51 d = other.d;
52 return *this;
53}
54
56{
57 if ( &other == this )
58 return *this;
59
60 d = std::move( other.d );
61 return *this;
62}
63
66
68{
69 if ( d->enabled != other.enabled()
70 || d->size != other.size()
71 || d->sizeUnit != other.sizeUnit()
72 || d->sizeMapUnitScale != other.sizeMapUnitScale()
73 || d->color != other.color()
74 || d->opacity != other.opacity()
75 || d->fillBufferInterior != other.fillBufferInterior()
76 || d->joinStyle != other.joinStyle()
77 || d->blendMode != other.blendMode() )
78 return false;
79
80 if ( static_cast< bool >( d->paintEffect ) != static_cast< bool >( other.paintEffect() ) || ( d->paintEffect && d->paintEffect->properties() != other.paintEffect()->properties() ) )
81 return false;
82
83 return true;
84}
85
87{
88 return !( *this == other );
89}
90
92{
93 return d->enabled;
94}
95
97{
98 d->enabled = enabled;
99}
100
102{
103 return d->size;
104}
105
107{
108 d->size = size;
109}
110
112{
113 return d->sizeUnit;
114}
115
117{
118 d->sizeUnit = unit;
119}
120
122{
123 return d->sizeMapUnitScale;
124}
125
127{
128 d->sizeMapUnitScale = scale;
129}
130
132{
133 return d->color;
134}
135
137{
138 d->color = color;
139}
140
142{
143 return d->fillBufferInterior;
144}
145
147{
148 d->fillBufferInterior = fill;
149}
150
152{
153 return d->opacity;
154}
155
157{
158 d->opacity = opacity;
159}
160
161Qt::PenJoinStyle QgsTextBufferSettings::joinStyle() const
162{
163 return d->joinStyle;
164}
165
166void QgsTextBufferSettings::setJoinStyle( Qt::PenJoinStyle style )
167{
168 d->joinStyle = style;
169}
170
171QPainter::CompositionMode QgsTextBufferSettings::blendMode() const
172{
173 return d->blendMode;
174}
175
176void QgsTextBufferSettings::setBlendMode( QPainter::CompositionMode mode )
177{
178 d->blendMode = mode;
179}
180
182{
183 return d->paintEffect.get();
184}
185
187{
188 d->paintEffect.reset( effect );
189}
190
192{
194 {
195 context.expressionContext().setOriginalValueVariable( d->enabled );
196 d->enabled = properties.valueAsBool( QgsPalLayerSettings::Property::BufferDraw, context.expressionContext(), d->enabled );
197 }
198
200 {
201 context.expressionContext().setOriginalValueVariable( d->size );
202 d->size = properties.valueAsDouble( QgsPalLayerSettings::Property::BufferSize, context.expressionContext(), d->size );
203 }
204
205 QVariant exprVal = properties.value( QgsPalLayerSettings::Property::BufferUnit, context.expressionContext() );
206 if ( !QgsVariantUtils::isNull( exprVal ) )
207 {
208 const QString units = exprVal.toString();
209 if ( !units.isEmpty() )
210 {
211 bool ok;
212 const Qgis::RenderUnit res = QgsUnitTypes::decodeRenderUnit( units, &ok );
213 if ( ok )
214 d->sizeUnit = res;
215 }
216 }
217
219 {
220 context.expressionContext().setOriginalValueVariable( d->opacity * 100 );
221 const QVariant val = properties.value( QgsPalLayerSettings::Property::BufferOpacity, context.expressionContext(), d->opacity * 100 );
222 if ( !QgsVariantUtils::isNull( val ) )
223 {
224 d->opacity = val.toDouble() / 100.0;
225 }
226 }
227
229 {
231 d->color = properties.valueAsColor( QgsPalLayerSettings::Property::BufferColor, context.expressionContext(), d->color );
232 }
233
235 {
237 const QString blendstr = exprVal.toString().trimmed();
238 if ( !blendstr.isEmpty() )
239 d->blendMode = QgsSymbolLayerUtils::decodeBlendMode( blendstr );
240 }
241
243 {
245 const QString joinstr = exprVal.toString().trimmed();
246 if ( !joinstr.isEmpty() )
247 {
248 d->joinStyle = QgsSymbolLayerUtils::decodePenJoinStyle( joinstr );
249 }
250 }
251}
252
254{
255 return QSet< QString >(); // nothing for now
256}
257
259{
260 // text buffer
261 const double bufSize = layer->customProperty( u"labeling/bufferSize"_s, QVariant( 0.0 ) ).toDouble();
262
263 // fix for buffer being keyed off of just its size in the past (<2.0)
264 const QVariant drawBuffer = layer->customProperty( u"labeling/bufferDraw"_s, QVariant() );
265 if ( drawBuffer.isValid() )
266 {
267 d->enabled = drawBuffer.toBool();
268 d->size = bufSize;
269 }
270 else if ( bufSize != 0.0 )
271 {
272 d->enabled = true;
273 d->size = bufSize;
274 }
275 else
276 {
277 // keep bufferSize at new 1.0 default
278 d->enabled = false;
279 }
280
281 if ( layer->customProperty( u"labeling/bufferSizeUnits"_s ).toString().isEmpty() )
282 {
283 const bool bufferSizeInMapUnits = layer->customProperty( u"labeling/bufferSizeInMapUnits"_s ).toBool();
284 d->sizeUnit = bufferSizeInMapUnits ? Qgis::RenderUnit::MapUnits : Qgis::RenderUnit::Millimeters;
285 }
286 else
287 {
288 d->sizeUnit = QgsUnitTypes::decodeRenderUnit( layer->customProperty( u"labeling/bufferSizeUnits"_s ).toString() );
289 }
290
291 if ( layer->customProperty( u"labeling/bufferSizeMapUnitScale"_s ).toString().isEmpty() )
292 {
293 //fallback to older property
294 const double oldMin = layer->customProperty( u"labeling/bufferSizeMapUnitMinScale"_s, 0.0 ).toDouble();
295 d->sizeMapUnitScale.minScale = oldMin != 0 ? 1.0 / oldMin : 0;
296 const double oldMax = layer->customProperty( u"labeling/bufferSizeMapUnitMaxScale"_s, 0.0 ).toDouble();
297 d->sizeMapUnitScale.maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
298 }
299 else
300 {
301 d->sizeMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( layer->customProperty( u"labeling/bufferSizeMapUnitScale"_s ).toString() );
302 }
303 d->color = QgsTextRendererUtils::readColor( layer, u"labeling/bufferColor"_s, Qt::white, false );
304 if ( layer->customProperty( u"labeling/bufferOpacity"_s ).toString().isEmpty() )
305 {
306 d->opacity = ( 1 - layer->customProperty( u"labeling/bufferTransp"_s ).toInt() / 100.0 ); //0 -100
307 }
308 else
309 {
310 d->opacity = ( layer->customProperty( u"labeling/bufferOpacity"_s ).toDouble() );
311 }
312 d->blendMode = QgsPainting::getCompositionMode(
313 static_cast< Qgis::BlendMode >( layer->customProperty( u"labeling/bufferBlendMode"_s, QVariant( static_cast< int >( Qgis::BlendMode::Normal ) ) ).toUInt() )
314 );
315 d->joinStyle = static_cast< Qt::PenJoinStyle >( layer->customProperty( u"labeling/bufferJoinStyle"_s, QVariant( Qt::RoundJoin ) ).toUInt() );
316
317 d->fillBufferInterior = !layer->customProperty( u"labeling/bufferNoFill"_s, QVariant( false ) ).toBool();
318
319 if ( layer->customProperty( u"labeling/bufferEffect"_s ).isValid() )
320 {
321 QDomDocument doc( u"effect"_s );
322 doc.setContent( layer->customProperty( u"labeling/bufferEffect"_s ).toString() );
323 const QDomElement effectElem = doc.firstChildElement( u"effect"_s ).firstChildElement( u"effect"_s );
324 setPaintEffect( QgsApplication::paintEffectRegistry()->createEffect( effectElem ) );
325 }
326 else
327 setPaintEffect( nullptr );
328}
329
330void QgsTextBufferSettings::readXml( const QDomElement &elem )
331{
332 const QDomElement textBufferElem = elem.firstChildElement( u"text-buffer"_s );
333 const double bufSize = textBufferElem.attribute( u"bufferSize"_s, u"0"_s ).toDouble();
334
335 // fix for buffer being keyed off of just its size in the past (<2.0)
336 const QVariant drawBuffer = textBufferElem.attribute( u"bufferDraw"_s );
337 if ( drawBuffer.isValid() )
338 {
339 d->enabled = drawBuffer.toBool();
340 d->size = bufSize;
341 }
342 else if ( bufSize != 0.0 )
343 {
344 d->enabled = true;
345 d->size = bufSize;
346 }
347 else
348 {
349 // keep bufferSize at new 1.0 default
350 d->enabled = false;
351 }
352
353 if ( !textBufferElem.hasAttribute( u"bufferSizeUnits"_s ) )
354 {
355 const bool bufferSizeInMapUnits = textBufferElem.attribute( u"bufferSizeInMapUnits"_s ).toInt();
356 d->sizeUnit = bufferSizeInMapUnits ? Qgis::RenderUnit::MapUnits : Qgis::RenderUnit::Millimeters;
357 }
358 else
359 {
360 d->sizeUnit = QgsUnitTypes::decodeRenderUnit( textBufferElem.attribute( u"bufferSizeUnits"_s ) );
361 }
362
363 if ( !textBufferElem.hasAttribute( u"bufferSizeMapUnitScale"_s ) )
364 {
365 //fallback to older property
366 const double oldMin = textBufferElem.attribute( u"bufferSizeMapUnitMinScale"_s, u"0"_s ).toDouble();
367 d->sizeMapUnitScale.minScale = oldMin != 0 ? 1.0 / oldMin : 0;
368 const double oldMax = textBufferElem.attribute( u"bufferSizeMapUnitMaxScale"_s, u"0"_s ).toDouble();
369 d->sizeMapUnitScale.maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
370 }
371 else
372 {
373 d->sizeMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( textBufferElem.attribute( u"bufferSizeMapUnitScale"_s ) );
374 }
375 d->color = QgsColorUtils::colorFromString( textBufferElem.attribute( u"bufferColor"_s, QgsColorUtils::colorToString( Qt::white ) ) );
376
377 if ( !textBufferElem.hasAttribute( u"bufferOpacity"_s ) )
378 {
379 d->opacity = ( 1 - textBufferElem.attribute( u"bufferTransp"_s ).toInt() / 100.0 ); //0 -100
380 }
381 else
382 {
383 d->opacity = ( textBufferElem.attribute( u"bufferOpacity"_s ).toDouble() );
384 }
385
386 d->blendMode = QgsPainting::getCompositionMode(
387 static_cast< Qgis::BlendMode >( textBufferElem.attribute( u"bufferBlendMode"_s, QString::number( static_cast< int >( Qgis::BlendMode::Normal ) ) ).toUInt() )
388 );
389 d->joinStyle = static_cast< Qt::PenJoinStyle >( textBufferElem.attribute( u"bufferJoinStyle"_s, QString::number( Qt::RoundJoin ) ).toUInt() );
390 d->fillBufferInterior = !textBufferElem.attribute( u"bufferNoFill"_s, u"0"_s ).toInt();
391 const QDomElement effectElem = textBufferElem.firstChildElement( u"effect"_s );
392 if ( !effectElem.isNull() )
393 setPaintEffect( QgsApplication::paintEffectRegistry()->createEffect( effectElem ) );
394 else
395 setPaintEffect( nullptr );
396}
397
398QDomElement QgsTextBufferSettings::writeXml( QDomDocument &doc ) const
399{
400 // text buffer
401 QDomElement textBufferElem = doc.createElement( u"text-buffer"_s );
402 textBufferElem.setAttribute( u"bufferDraw"_s, d->enabled );
403 textBufferElem.setAttribute( u"bufferSize"_s, d->size );
404 textBufferElem.setAttribute( u"bufferSizeUnits"_s, QgsUnitTypes::encodeUnit( d->sizeUnit ) );
405 textBufferElem.setAttribute( u"bufferSizeMapUnitScale"_s, QgsSymbolLayerUtils::encodeMapUnitScale( d->sizeMapUnitScale ) );
406 textBufferElem.setAttribute( u"bufferColor"_s, QgsColorUtils::colorToString( d->color ) );
407 textBufferElem.setAttribute( u"bufferNoFill"_s, !d->fillBufferInterior );
408 textBufferElem.setAttribute( u"bufferOpacity"_s, d->opacity );
409 textBufferElem.setAttribute( u"bufferJoinStyle"_s, static_cast< unsigned int >( d->joinStyle ) );
410 textBufferElem.setAttribute( u"bufferBlendMode"_s, static_cast< int >( QgsPainting::getBlendModeEnum( d->blendMode ) ) );
411 if ( d->paintEffect && !QgsPaintEffectRegistry::isDefaultStack( d->paintEffect.get() ) )
412 d->paintEffect->saveProperties( doc, textBufferElem );
413 return textBufferElem;
414}
BlendMode
Blending modes defining the available composition modes that can be used when painting.
Definition qgis.h:5087
@ Normal
Normal.
Definition qgis.h:5088
RenderUnit
Rendering size units.
Definition qgis.h:5340
@ Millimeters
Millimeters.
Definition qgis.h:5341
@ MapUnits
Map units.
Definition qgis.h:5342
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.
static QColor colorFromString(const QString &string)
Decodes a string into a color value.
static QString colorToString(const QColor &color)
Encodes a color into a string value.
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.
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 Qgis::BlendMode corresponding to a QPainter::CompositionMode.
static QPainter::CompositionMode getCompositionMode(Qgis::BlendMode blendMode)
Returns a QPainter::CompositionMode corresponding to a Qgis::BlendMode.
A grouped map of multiple QgsProperty objects, each referenced by an integer key value.
QVariant value(int key, const QgsExpressionContext &context, const QVariant &defaultValue=QVariant()) const final
Returns the calculated value of the property with the specified key from within the collection.
bool isActive(int key) const final
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 QgsMapUnitScale decodeMapUnitScale(const QString &str)
static QPainter::CompositionMode decodeBlendMode(const QString &s)
static QString encodeColor(const QColor &color)
QgsTextBufferSettings & operator=(const QgsTextBufferSettings &other)
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, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
Represents a vector layer which manages a vector based dataset.