QGIS API Documentation 3.99.0-Master (2fe06baccd8)
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 <QUuid>
24
26 : mLowerValue( range.lowerBound() )
27 , mUpperValue( range.upperBound() )
28 , mSymbol( symbol )
29 , mLabel( range.label() )
30 , mRender( render )
31{
32 mUuid = !uuid.isEmpty() ? uuid : QUuid::createUuid().toString();
33}
34
35QgsRendererRange::QgsRendererRange( double lowerValue, double upperValue, QgsSymbol *symbol, const QString &label, bool render, const QString &uuid )
38 , mSymbol( symbol )
39 , mLabel( label )
40 , mRender( render )
41{
42 mUuid = !uuid.isEmpty() ? uuid : QUuid::createUuid().toString();
43}
44
46 : mLowerValue( range.mLowerValue )
47 , mUpperValue( range.mUpperValue )
48 , mSymbol( range.mSymbol ? range.mSymbol->clone() : nullptr )
49 , mLabel( range.mLabel )
50 , mRender( range.mRender )
51 , mUuid( range.mUuid )
52{}
53
55
57{
58 if ( &range == this )
59 return *this;
60
63 mSymbol.reset( range.mSymbol ? range.mSymbol->clone() : nullptr );
64 mLabel = range.mLabel;
65 mRender = range.mRender;
66 mUuid = range.mUuid;
67 return *this;
68}
69
71{
72 return
73 lowerValue() < other.lowerValue() ||
74 ( qgsDoubleNear( lowerValue(), other.lowerValue() ) && upperValue() < other.upperValue() );
75}
76
78{
79 return mUuid;
80}
81
83{
84 return mLowerValue;
85}
86
88{
89 return mUpperValue;
90}
91
93{
94 return mSymbol.get();
95}
96
98{
99 return mLabel;
100}
101
103{
104 if ( mSymbol.get() != s ) mSymbol.reset( s );
105}
106
107void QgsRendererRange::setLabel( const QString &label )
108{
109 mLabel = label;
110}
111
116
121
123{
124 return mRender;
125}
126
128{
129 mRender = render;
130}
131
133{
134 return QStringLiteral( "%1 - %2::%3::%4\n" ).arg( mLowerValue ).arg( mUpperValue ).arg( mLabel, mSymbol ? mSymbol->dump() : QStringLiteral( "(no symbol)" ) );
135}
136
137void QgsRendererRange::toSld( QDomDocument &doc, QDomElement &element, QVariantMap props, bool firstRange ) const
138{
139 QgsSldExportContext context;
140 context.setExtraProperties( props );
141 toSld( doc, element, props.value( QStringLiteral( "attribute" ), QString() ).toString(), context, firstRange );
142}
143
144bool QgsRendererRange::toSld( QDomDocument &doc, QDomElement &element, const QString &classAttribute, QgsSldExportContext &context, bool firstRange ) const
145{
146 if ( !mSymbol || classAttribute.isEmpty() )
147 return false;
148
149 QString attrName = classAttribute;
150
151 QDomElement ruleElem = doc.createElement( QStringLiteral( "se:Rule" ) );
152
153 QDomElement nameElem = doc.createElement( QStringLiteral( "se:Name" ) );
154 nameElem.appendChild( doc.createTextNode( mLabel ) );
155 ruleElem.appendChild( nameElem );
156
157 QDomElement descrElem = doc.createElement( QStringLiteral( "se:Description" ) );
158 QDomElement titleElem = doc.createElement( QStringLiteral( "se:Title" ) );
159 QString descrStr = QStringLiteral( "range: %1 - %2" ).arg( qgsDoubleToString( mLowerValue ), qgsDoubleToString( mUpperValue ) );
160 titleElem.appendChild( doc.createTextNode( !mLabel.isEmpty() ? mLabel : descrStr ) );
161 descrElem.appendChild( titleElem );
162 ruleElem.appendChild( descrElem );
163
164 // create the ogc:Filter for the range
165 QString filterFunc = QStringLiteral( "\"%1\" %2 %3 AND \"%1\" <= %4" )
166 .arg( attrName.replace( '\"', QLatin1String( "\"\"" ) ),
167 firstRange ? QStringLiteral( ">=" ) : QStringLiteral( ">" ),
170 QgsSymbolLayerUtils::createFunctionElement( doc, ruleElem, filterFunc, context );
171
172 mSymbol->toSld( doc, ruleElem, context );
173 if ( !QgsSymbolLayerUtils::hasSldSymbolizer( ruleElem ) )
174 {
175 // symbol could not be converted to SLD, or is an "empty" symbol. In this case we do not generate a rule, as
176 // SLD spec requires a Symbolizer element to be present
177 return false;
178 }
179
180 element.appendChild( ruleElem );
181 return true;
182}
183
185
186
189
191 : mFormat( QStringLiteral( "%1 - %2" ) )
192 , mReTrailingZeroes( "[.,]?0*$" )
193 , mReNegativeZero( "^\\-0(?:[.,]0*)?$" )
194{
195}
196
205
206
208{
209 return
210 format() == other.format() &&
211 precision() == other.precision() &&
213}
214
216{
217 return !( *this == other );
218}
219
221{
222 // Limit the range of decimal places to a reasonable range
225 mNumberScale = 1.0;
226 mNumberSuffix.clear();
227 while ( precision < 0 )
228 {
229 precision++;
230 mNumberScale /= 10.0;
231 mNumberSuffix.append( '0' );
232 }
233}
234
236{
237 return labelForRange( range.lowerValue(), range.upperValue() );
238}
239
240QString QgsRendererRangeLabelFormat::formatNumber( double value ) const
241{
242 if ( mPrecision > 0 )
243 {
244 QString valueStr = QLocale().toString( value, 'f', mPrecision );
246 valueStr = valueStr.remove( mReTrailingZeroes );
247 if ( mReNegativeZero.match( valueStr ).hasMatch() )
248 valueStr = valueStr.mid( 1 );
249 return valueStr;
250 }
251 else
252 {
253 QString valueStr = QLocale().toString( value * mNumberScale, 'f', 0 );
254 if ( valueStr == QLatin1String( "-0" ) )
255 valueStr = '0';
256 if ( valueStr != QLatin1String( "0" ) )
257 valueStr = valueStr + mNumberSuffix;
258 return valueStr;
259 }
260}
261
262QString QgsRendererRangeLabelFormat::labelForRange( double lower, double upper ) const
263{
264 QString lowerStr = formatNumber( lower );
265 QString upperStr = formatNumber( upper );
266
267 QString legend( mFormat );
268 return legend.replace( QLatin1String( "%1" ), lowerStr ).replace( QLatin1String( "%2" ), upperStr );
269}
270
272{
273 mFormat = element.attribute( QStringLiteral( "format" ),
274 element.attribute( QStringLiteral( "prefix" ), QStringLiteral( " " ) ) + "%1" +
275 element.attribute( QStringLiteral( "separator" ), QStringLiteral( " - " ) ) + "%2" +
276 element.attribute( QStringLiteral( "suffix" ), QStringLiteral( " " ) )
277 );
278 setPrecision( element.attribute( QStringLiteral( "decimalplaces" ), QStringLiteral( "4" ) ).toInt() );
279 mTrimTrailingZeroes = element.attribute( QStringLiteral( "trimtrailingzeroes" ), QStringLiteral( "false" ) ) == QLatin1String( "true" );
280}
281
283{
284 element.setAttribute( QStringLiteral( "format" ), mFormat );
285 element.setAttribute( QStringLiteral( "decimalplaces" ), mPrecision );
286 element.setAttribute( QStringLiteral( "trimtrailingzeroes" ), mTrimTrailingZeroes ? QStringLiteral( "true" ) : QStringLiteral( "false" ) );
287}
288
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:6524
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
Definition qgis.h:6607