QGIS API Documentation 3.99.0-Master (d270888f95f)
Loading...
Searching...
No Matches
qgsrendererrange.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsrendererrange.cpp
3 ---------------------
4 begin : September 2019
5 copyright : (C) 2019 by Denis Rouzaud
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
16#include "qgsrendererrange.h"
17
19#include "qgssldexportcontext.h"
20#include "qgssymbol.h"
21
22#include <QLocale>
23#include <QString>
24#include <QUuid>
25
26using namespace Qt::StringLiterals;
27
29 : mLowerValue( range.lowerBound() )
30 , mUpperValue( range.upperBound() )
31 , mSymbol( symbol )
32 , mLabel( range.label() )
33 , mRender( render )
34{
35 mUuid = !uuid.isEmpty() ? uuid : QUuid::createUuid().toString();
36}
37
38QgsRendererRange::QgsRendererRange( double lowerValue, double upperValue, QgsSymbol *symbol, const QString &label, bool render, const QString &uuid )
41 , mSymbol( symbol )
42 , mLabel( label )
43 , mRender( render )
44{
45 mUuid = !uuid.isEmpty() ? uuid : QUuid::createUuid().toString();
46}
47
49 : mLowerValue( range.mLowerValue )
50 , mUpperValue( range.mUpperValue )
51 , mSymbol( range.mSymbol ? range.mSymbol->clone() : nullptr )
52 , mLabel( range.mLabel )
53 , mRender( range.mRender )
54 , mUuid( range.mUuid )
55{}
56
58
60{
61 if ( &range == this )
62 return *this;
63
66 mSymbol.reset( range.mSymbol ? range.mSymbol->clone() : nullptr );
67 mLabel = range.mLabel;
68 mRender = range.mRender;
69 mUuid = range.mUuid;
70 return *this;
71}
72
74{
75 return
76 lowerValue() < other.lowerValue() ||
77 ( qgsDoubleNear( lowerValue(), other.lowerValue() ) && upperValue() < other.upperValue() );
78}
79
81{
82 return mUuid;
83}
84
86{
87 return mLowerValue;
88}
89
91{
92 return mUpperValue;
93}
94
96{
97 return mSymbol.get();
98}
99
101{
102 return mLabel;
103}
104
106{
107 if ( mSymbol.get() != s ) mSymbol.reset( s );
108}
109
110void QgsRendererRange::setLabel( const QString &label )
111{
112 mLabel = label;
113}
114
119
124
126{
127 return mRender;
128}
129
131{
132 mRender = render;
133}
134
136{
137 return u"%1 - %2::%3::%4\n"_s.arg( mLowerValue ).arg( mUpperValue ).arg( mLabel, mSymbol ? mSymbol->dump() : u"(no symbol)"_s );
138}
139
140void QgsRendererRange::toSld( QDomDocument &doc, QDomElement &element, QVariantMap props, bool firstRange ) const
141{
142 QgsSldExportContext context;
143 context.setExtraProperties( props );
144 toSld( doc, element, props.value( u"attribute"_s, QString() ).toString(), context, firstRange );
145}
146
147bool QgsRendererRange::toSld( QDomDocument &doc, QDomElement &element, const QString &classAttribute, QgsSldExportContext &context, bool firstRange ) const
148{
149 if ( !mSymbol || classAttribute.isEmpty() )
150 return false;
151
152 QString attrName = classAttribute;
153
154 QDomElement ruleElem = doc.createElement( u"se:Rule"_s );
155
156 QDomElement nameElem = doc.createElement( u"se:Name"_s );
157 nameElem.appendChild( doc.createTextNode( mLabel ) );
158 ruleElem.appendChild( nameElem );
159
160 QDomElement descrElem = doc.createElement( u"se:Description"_s );
161 QDomElement titleElem = doc.createElement( u"se:Title"_s );
162 QString descrStr = u"range: %1 - %2"_s.arg( qgsDoubleToString( mLowerValue ), qgsDoubleToString( mUpperValue ) );
163 titleElem.appendChild( doc.createTextNode( !mLabel.isEmpty() ? mLabel : descrStr ) );
164 descrElem.appendChild( titleElem );
165 ruleElem.appendChild( descrElem );
166
167 // create the ogc:Filter for the range
168 QString filterFunc = u"\"%1\" %2 %3 AND \"%1\" <= %4"_s
169 .arg( attrName.replace( '\"', "\"\""_L1 ),
170 firstRange ? u">="_s : u">"_s,
173 QgsSymbolLayerUtils::createFunctionElement( doc, ruleElem, filterFunc, context );
174
175 mSymbol->toSld( doc, ruleElem, context );
176 if ( !QgsSymbolLayerUtils::hasSldSymbolizer( ruleElem ) )
177 {
178 // symbol could not be converted to SLD, or is an "empty" symbol. In this case we do not generate a rule, as
179 // SLD spec requires a Symbolizer element to be present
180 return false;
181 }
182
183 element.appendChild( ruleElem );
184 return true;
185}
186
188
189
192
194 : mFormat( u"%1 - %2"_s )
195 , mReTrailingZeroes( "[.,]?0*$" )
196 , mReNegativeZero( "^\\-0(?:[.,]0*)?$" )
197{
198}
199
208
209
211{
212 return
213 format() == other.format() &&
214 precision() == other.precision() &&
216}
217
219{
220 return !( *this == other );
221}
222
224{
225 // Limit the range of decimal places to a reasonable range
228 mNumberScale = 1.0;
229 mNumberSuffix.clear();
230 while ( precision < 0 )
231 {
232 precision++;
233 mNumberScale /= 10.0;
234 mNumberSuffix.append( '0' );
235 }
236}
237
239{
240 return labelForRange( range.lowerValue(), range.upperValue() );
241}
242
243QString QgsRendererRangeLabelFormat::formatNumber( double value ) const
244{
245 if ( mPrecision > 0 )
246 {
247 QString valueStr = QLocale().toString( value, 'f', mPrecision );
249 valueStr = valueStr.remove( mReTrailingZeroes );
250 if ( mReNegativeZero.match( valueStr ).hasMatch() )
251 valueStr = valueStr.mid( 1 );
252 return valueStr;
253 }
254 else
255 {
256 QString valueStr = QLocale().toString( value * mNumberScale, 'f', 0 );
257 if ( valueStr == "-0"_L1 )
258 valueStr = '0';
259 if ( valueStr != "0"_L1 )
260 valueStr = valueStr + mNumberSuffix;
261 return valueStr;
262 }
263}
264
265QString QgsRendererRangeLabelFormat::labelForRange( double lower, double upper ) const
266{
267 QString lowerStr = formatNumber( lower );
268 QString upperStr = formatNumber( upper );
269
270 QString legend( mFormat );
271 return legend.replace( "%1"_L1, lowerStr ).replace( "%2"_L1, upperStr );
272}
273
275{
276 mFormat = element.attribute( u"format"_s,
277 element.attribute( u"prefix"_s, u" "_s ) + "%1" +
278 element.attribute( u"separator"_s, u" - "_s ) + "%2" +
279 element.attribute( u"suffix"_s, u" "_s )
280 );
281 setPrecision( element.attribute( u"decimalplaces"_s, u"4"_s ).toInt() );
282 mTrimTrailingZeroes = element.attribute( u"trimtrailingzeroes"_s, u"false"_s ) == "true"_L1;
283}
284
286{
287 element.setAttribute( u"format"_s, mFormat );
288 element.setAttribute( u"decimalplaces"_s, mPrecision );
289 element.setAttribute( u"trimtrailingzeroes"_s, mTrimTrailingZeroes ? u"true"_s : u"false"_s );
290}
291
Contains the information about a classification range.
void saveToDomElement(QDomElement &element)
void setFromDomElement(QDomElement &element)
bool operator!=(const QgsRendererRangeLabelFormat &other) const
void setFormat(const QString &format)
QString labelForRange(double lower, double upper) const
Returns the label to use for a range with the specified lower and upper bounds.
QRegularExpression mReTrailingZeroes
QRegularExpression mReNegativeZero
void setTrimTrailingZeroes(bool trimTrailingZeroes)
QString formatNumber(double value) const
bool operator==(const QgsRendererRangeLabelFormat &other) const
Represents a value range for a QgsGraduatedSymbolRenderer.
void setUpperValue(double upperValue)
Sets the upper bound of the range.
QgsRendererRange()=default
QString label() const
Returns the label used for the range.
void setSymbol(QgsSymbol *s)
Sets the symbol used for the range.
std::unique_ptr< QgsSymbol > mSymbol
Q_DECL_DEPRECATED void toSld(QDomDocument &doc, QDomElement &element, QVariantMap props, bool firstRange=false) const
Creates a DOM element representing the range in SLD format.
QgsRendererRange & operator=(QgsRendererRange range)
QgsSymbol * symbol() const
Returns the symbol used for the range.
void setLabel(const QString &label)
Sets the label used for the range.
bool renderState() const
Returns true if the range should be rendered.
void setRenderState(bool render)
Sets whether the range should be rendered.
QString dump() const
Dumps a string representation of the range.
double upperValue() const
Returns the upper bound of the range.
void setLowerValue(double lowerValue)
Sets the lower bound of the range.
QString uuid() const
Returns the unique identifier for this range.
double lowerValue() const
Returns the lower bound of the range.
bool operator<(const QgsRendererRange &other) const
Holds SLD export options and other information related to SLD export of a QGIS layer style.
void setExtraProperties(const QVariantMap &properties)
Sets the open ended set of properties that can drive/inform the SLD encoding.
static Q_DECL_DEPRECATED bool createFunctionElement(QDomDocument &doc, QDomElement &element, const QString &function)
Creates an OGC function element.
static bool hasSldSymbolizer(const QDomElement &element)
Returns true if a DOM element contains an SLD Symbolizer element.
Abstract base class for all rendered symbols.
Definition qgssymbol.h:231
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition qgis.h:6817
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
Definition qgis.h:6900