QGIS API Documentation 3.41.0-Master (fda2aa46e9a)
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"
18#include "qgssymbol.h"
19
20#include <QLocale>
21#include <QUuid>
22
23
24QgsRendererRange::QgsRendererRange( const QgsClassificationRange &range, QgsSymbol *symbol, bool render, const QString &uuid )
25 : mLowerValue( range.lowerBound() )
26 , mUpperValue( range.upperBound() )
27 , mSymbol( symbol )
28 , mLabel( range.label() )
29 , mRender( render )
30{
31 mUuid = !uuid.isEmpty() ? uuid : QUuid::createUuid().toString();
32}
33
34QgsRendererRange::QgsRendererRange( double lowerValue, double upperValue, QgsSymbol *symbol, const QString &label, bool render, const QString &uuid )
35 : mLowerValue( lowerValue )
36 , mUpperValue( upperValue )
37 , mSymbol( symbol )
38 , mLabel( label )
39 , mRender( render )
40{
41 mUuid = !uuid.isEmpty() ? uuid : QUuid::createUuid().toString();
42}
43
45 : mLowerValue( range.mLowerValue )
46 , mUpperValue( range.mUpperValue )
47 , mSymbol( range.mSymbol ? range.mSymbol->clone() : nullptr )
48 , mLabel( range.mLabel )
49 , mRender( range.mRender )
50 , mUuid( range.mUuid )
51{}
52
54
56{
59 mSymbol.reset( range.mSymbol ? range.mSymbol->clone() : nullptr );
60 mLabel = range.mLabel;
61 mRender = range.mRender;
62 mUuid = range.mUuid;
63 return *this;
64}
65
67{
68 return
69 lowerValue() < other.lowerValue() ||
70 ( qgsDoubleNear( lowerValue(), other.lowerValue() ) && upperValue() < other.upperValue() );
71}
72
74{
75 return mUuid;
76}
77
79{
80 return mLowerValue;
81}
82
84{
85 return mUpperValue;
86}
87
89{
90 return mSymbol.get();
91}
92
94{
95 return mLabel;
96}
97
99{
100 if ( mSymbol.get() != s ) mSymbol.reset( s );
101}
102
103void QgsRendererRange::setLabel( const QString &label )
104{
105 mLabel = label;
106}
107
108void QgsRendererRange::setUpperValue( double upperValue )
109{
111}
112
113void QgsRendererRange::setLowerValue( double lowerValue )
114{
116}
117
119{
120 return mRender;
121}
122
124{
125 mRender = render;
126}
127
129{
130 return QStringLiteral( "%1 - %2::%3::%4\n" ).arg( mLowerValue ).arg( mUpperValue ).arg( mLabel, mSymbol ? mSymbol->dump() : QStringLiteral( "(no symbol)" ) );
131}
132
133void QgsRendererRange::toSld( QDomDocument &doc, QDomElement &element, QVariantMap props, bool firstRange ) const
134{
135 if ( !mSymbol || props.value( QStringLiteral( "attribute" ), QString() ).toString().isEmpty() )
136 return;
137
138 QString attrName = props[ QStringLiteral( "attribute" )].toString();
139
140 QDomElement ruleElem = doc.createElement( QStringLiteral( "se:Rule" ) );
141 element.appendChild( ruleElem );
142
143 QDomElement nameElem = doc.createElement( QStringLiteral( "se:Name" ) );
144 nameElem.appendChild( doc.createTextNode( mLabel ) );
145 ruleElem.appendChild( nameElem );
146
147 QDomElement descrElem = doc.createElement( QStringLiteral( "se:Description" ) );
148 QDomElement titleElem = doc.createElement( QStringLiteral( "se:Title" ) );
149 QString descrStr = QStringLiteral( "range: %1 - %2" ).arg( qgsDoubleToString( mLowerValue ), qgsDoubleToString( mUpperValue ) );
150 titleElem.appendChild( doc.createTextNode( !mLabel.isEmpty() ? mLabel : descrStr ) );
151 descrElem.appendChild( titleElem );
152 ruleElem.appendChild( descrElem );
153
154 // create the ogc:Filter for the range
155 QString filterFunc = QStringLiteral( "\"%1\" %2 %3 AND \"%1\" <= %4" )
156 .arg( attrName.replace( '\"', QLatin1String( "\"\"" ) ),
157 firstRange ? QStringLiteral( ">=" ) : QStringLiteral( ">" ),
160 QgsSymbolLayerUtils::createFunctionElement( doc, ruleElem, filterFunc );
161
162 mSymbol->toSld( doc, ruleElem, props );
163}
164
166
167
170
172 : mFormat( QStringLiteral( "%1 - %2" ) )
173 , mReTrailingZeroes( "[.,]?0*$" )
174 , mReNegativeZero( "^\\-0(?:[.,]0*)?$" )
175{
176}
177
178QgsRendererRangeLabelFormat::QgsRendererRangeLabelFormat( const QString &format, int precision, bool trimTrailingZeroes )
179 : mReTrailingZeroes( "[.,]?0*$" )
180 , mReNegativeZero( "^\\-0(?:[.,]0*)?$" )
181{
182 setFormat( format );
185}
186
187
189{
190 return
191 format() == other.format() &&
192 precision() == other.precision() &&
194}
195
197{
198 return !( *this == other );
199}
200
202{
203 // Limit the range of decimal places to a reasonable range
206 mNumberScale = 1.0;
207 mNumberSuffix.clear();
208 while ( precision < 0 )
209 {
210 precision++;
211 mNumberScale /= 10.0;
212 mNumberSuffix.append( '0' );
213 }
214}
215
217{
218 return labelForRange( range.lowerValue(), range.upperValue() );
219}
220
221QString QgsRendererRangeLabelFormat::formatNumber( double value ) const
222{
223 if ( mPrecision > 0 )
224 {
225 QString valueStr = QLocale().toString( value, 'f', mPrecision );
227 valueStr = valueStr.remove( mReTrailingZeroes );
228 if ( mReNegativeZero.match( valueStr ).hasMatch() )
229 valueStr = valueStr.mid( 1 );
230 return valueStr;
231 }
232 else
233 {
234 QString valueStr = QLocale().toString( value * mNumberScale, 'f', 0 );
235 if ( valueStr == QLatin1String( "-0" ) )
236 valueStr = '0';
237 if ( valueStr != QLatin1String( "0" ) )
238 valueStr = valueStr + mNumberSuffix;
239 return valueStr;
240 }
241}
242
243QString QgsRendererRangeLabelFormat::labelForRange( double lower, double upper ) const
244{
245 QString lowerStr = formatNumber( lower );
246 QString upperStr = formatNumber( upper );
247
248 QString legend( mFormat );
249 return legend.replace( QLatin1String( "%1" ), lowerStr ).replace( QLatin1String( "%2" ), upperStr );
250}
251
253{
254 mFormat = element.attribute( QStringLiteral( "format" ),
255 element.attribute( QStringLiteral( "prefix" ), QStringLiteral( " " ) ) + "%1" +
256 element.attribute( QStringLiteral( "separator" ), QStringLiteral( " - " ) ) + "%2" +
257 element.attribute( QStringLiteral( "suffix" ), QStringLiteral( " " ) )
258 );
259 setPrecision( element.attribute( QStringLiteral( "decimalplaces" ), QStringLiteral( "4" ) ).toInt() );
260 mTrimTrailingZeroes = element.attribute( QStringLiteral( "trimtrailingzeroes" ), QStringLiteral( "false" ) ) == QLatin1String( "true" );
261}
262
264{
265 element.setAttribute( QStringLiteral( "format" ), mFormat );
266 element.setAttribute( QStringLiteral( "decimalplaces" ), mPrecision );
267 element.setAttribute( QStringLiteral( "trimtrailingzeroes" ), mTrimTrailingZeroes ? QStringLiteral( "true" ) : QStringLiteral( "false" ) );
268}
269
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)
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
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.
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
static bool createFunctionElement(QDomDocument &doc, QDomElement &element, const QString &function)
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:5834
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition qgis.h:5917
int precision