QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
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"
18#include "qgssymbol.h"
19
20#include <QLocale>
21
22
24 : mLowerValue( range.lowerBound() )
25 , mUpperValue( range.upperBound() )
26 , mSymbol( symbol )
27 , mLabel( range.label() )
28 , mRender( render )
29{
30}
31
32QgsRendererRange::QgsRendererRange( double lowerValue, double upperValue, QgsSymbol *symbol, const QString &label, bool render )
33 : mLowerValue( lowerValue )
34 , mUpperValue( upperValue )
35 , mSymbol( symbol )
36 , mLabel( label )
37 , mRender( render )
38{}
39
41 : mLowerValue( range.mLowerValue )
42 , mUpperValue( range.mUpperValue )
43 , mSymbol( range.mSymbol ? range.mSymbol->clone() : nullptr )
44 , mLabel( range.mLabel )
45 , mRender( range.mRender )
46{}
47
49
50
51// cpy and swap idiom, note that the cpy is done with 'pass by value'
53{
54 swap( range );
55 return *this;
56}
57
59{
60 return
61 lowerValue() < other.lowerValue() ||
62 ( qgsDoubleNear( lowerValue(), other.lowerValue() ) && upperValue() < other.upperValue() );
63}
64
65
67{
68 std::swap( mLowerValue, other.mLowerValue );
69 std::swap( mUpperValue, other.mUpperValue );
70 std::swap( mSymbol, other.mSymbol );
71 std::swap( mLabel, other.mLabel );
72}
73
75{
76 return mLowerValue;
77}
78
80{
81 return mUpperValue;
82}
83
85{
86 return mSymbol.get();
87}
88
90{
91 return mLabel;
92}
93
95{
96 if ( mSymbol.get() != s ) mSymbol.reset( s );
97}
98
99void QgsRendererRange::setLabel( const QString &label )
100{
101 mLabel = label;
102}
103
104void QgsRendererRange::setUpperValue( double upperValue )
105{
107}
108
109void QgsRendererRange::setLowerValue( double lowerValue )
110{
112}
113
115{
116 return mRender;
117}
118
120{
121 mRender = render;
122}
123
125{
126 return QStringLiteral( "%1 - %2::%3::%4\n" ).arg( mLowerValue ).arg( mUpperValue ).arg( mLabel, mSymbol ? mSymbol->dump() : QStringLiteral( "(no symbol)" ) );
127}
128
129void QgsRendererRange::toSld( QDomDocument &doc, QDomElement &element, QVariantMap props, bool firstRange ) const
130{
131 if ( !mSymbol || props.value( QStringLiteral( "attribute" ), QString() ).toString().isEmpty() )
132 return;
133
134 QString attrName = props[ QStringLiteral( "attribute" )].toString();
135
136 QDomElement ruleElem = doc.createElement( QStringLiteral( "se:Rule" ) );
137 element.appendChild( ruleElem );
138
139 QDomElement nameElem = doc.createElement( QStringLiteral( "se:Name" ) );
140 nameElem.appendChild( doc.createTextNode( mLabel ) );
141 ruleElem.appendChild( nameElem );
142
143 QDomElement descrElem = doc.createElement( QStringLiteral( "se:Description" ) );
144 QDomElement titleElem = doc.createElement( QStringLiteral( "se:Title" ) );
145 QString descrStr = QStringLiteral( "range: %1 - %2" ).arg( qgsDoubleToString( mLowerValue ), qgsDoubleToString( mUpperValue ) );
146 titleElem.appendChild( doc.createTextNode( !mLabel.isEmpty() ? mLabel : descrStr ) );
147 descrElem.appendChild( titleElem );
148 ruleElem.appendChild( descrElem );
149
150 // create the ogc:Filter for the range
151 QString filterFunc = QStringLiteral( "\"%1\" %2 %3 AND \"%1\" <= %4" )
152 .arg( attrName.replace( '\"', QLatin1String( "\"\"" ) ),
153 firstRange ? QStringLiteral( ">=" ) : QStringLiteral( ">" ),
156 QgsSymbolLayerUtils::createFunctionElement( doc, ruleElem, filterFunc );
157
158 mSymbol->toSld( doc, ruleElem, props );
159}
160
162
163
166
168 : mFormat( QStringLiteral( "%1 - %2" ) )
169 , mReTrailingZeroes( "[.,]?0*$" )
170 , mReNegativeZero( "^\\-0(?:[.,]0*)?$" )
171{
172}
173
174QgsRendererRangeLabelFormat::QgsRendererRangeLabelFormat( const QString &format, int precision, bool trimTrailingZeroes )
175 : mReTrailingZeroes( "[.,]?0*$" )
176 , mReNegativeZero( "^\\-0(?:[.,]0*)?$" )
177{
178 setFormat( format );
181}
182
183
185{
186 return
187 format() == other.format() &&
188 precision() == other.precision() &&
190}
191
193{
194 return !( *this == other );
195}
196
198{
199 // Limit the range of decimal places to a reasonable range
202 mNumberScale = 1.0;
203 mNumberSuffix.clear();
204 while ( precision < 0 )
205 {
206 precision++;
207 mNumberScale /= 10.0;
208 mNumberSuffix.append( '0' );
209 }
210}
211
213{
214 return labelForRange( range.lowerValue(), range.upperValue() );
215}
216
217QString QgsRendererRangeLabelFormat::formatNumber( double value ) const
218{
219 if ( mPrecision > 0 )
220 {
221 QString valueStr = QLocale().toString( value, 'f', mPrecision );
223 valueStr = valueStr.remove( mReTrailingZeroes );
224 if ( mReNegativeZero.match( valueStr ).hasMatch() )
225 valueStr = valueStr.mid( 1 );
226 return valueStr;
227 }
228 else
229 {
230 QString valueStr = QLocale().toString( value * mNumberScale, 'f', 0 );
231 if ( valueStr == QLatin1String( "-0" ) )
232 valueStr = '0';
233 if ( valueStr != QLatin1String( "0" ) )
234 valueStr = valueStr + mNumberSuffix;
235 return valueStr;
236 }
237}
238
239QString QgsRendererRangeLabelFormat::labelForRange( double lower, double upper ) const
240{
241 QString lowerStr = formatNumber( lower );
242 QString upperStr = formatNumber( upper );
243
244 QString legend( mFormat );
245 return legend.replace( QLatin1String( "%1" ), lowerStr ).replace( QLatin1String( "%2" ), upperStr );
246}
247
249{
250 mFormat = element.attribute( QStringLiteral( "format" ),
251 element.attribute( QStringLiteral( "prefix" ), QStringLiteral( " " ) ) + "%1" +
252 element.attribute( QStringLiteral( "separator" ), QStringLiteral( " - " ) ) + "%2" +
253 element.attribute( QStringLiteral( "suffix" ), QStringLiteral( " " ) )
254 );
255 setPrecision( element.attribute( QStringLiteral( "decimalplaces" ), QStringLiteral( "4" ) ).toInt() );
256 mTrimTrailingZeroes = element.attribute( QStringLiteral( "trimtrailingzeroes" ), QStringLiteral( "false" ) ) == QLatin1String( "true" );
257}
258
260{
261 element.setAttribute( QStringLiteral( "format" ), mFormat );
262 element.setAttribute( QStringLiteral( "decimalplaces" ), mPrecision );
263 element.setAttribute( QStringLiteral( "trimtrailingzeroes" ), mTrimTrailingZeroes ? QStringLiteral( "true" ) : QStringLiteral( "false" ) );
264}
265
QgsClassificationRange 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)
void setPrecision(int precision)
QString labelForRange(double lower, double upper) const
QRegularExpression mReTrailingZeroes
QRegularExpression mReNegativeZero
void setTrimTrailingZeroes(bool trimTrailingZeroes)
QString formatNumber(double value) const
bool operator==(const QgsRendererRangeLabelFormat &other) const
void setUpperValue(double upperValue)
Sets the upper bound of the range.
QgsRendererRange()=default
Constructor for QgsRendererRange.
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
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.
double lowerValue() const
Returns the lower bound of the range.
bool operator<(const QgsRendererRange &other) const
void swap(QgsRendererRange &other)
static bool createFunctionElement(QDomDocument &doc, QDomElement &element, const QString &function)
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:93
int ANALYSIS_EXPORT lower(int n, int i)
Lower function.
Definition: MathUtils.cpp:407
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition: qgis.h:2466
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:2527
int precision