QGIS API Documentation 4.0.0-Norrköping (1ddcee3d0e4)
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 lowerValue() < other.lowerValue() || ( qgsDoubleNear( lowerValue(), other.lowerValue() ) && upperValue() < other.upperValue() );
76}
77
79{
80 return mUuid;
81}
82
84{
85 return mLowerValue;
86}
87
89{
90 return mUpperValue;
91}
92
94{
95 return mSymbol.get();
96}
97
99{
100 return mLabel;
101}
102
104{
105 if ( mSymbol.get() != s )
106 mSymbol.reset( s );
107}
108
109void QgsRendererRange::setLabel( const QString &label )
110{
111 mLabel = label;
112}
113
118
123
125{
126 return mRender;
127}
128
130{
131 mRender = render;
132}
133
135{
136 return u"%1 - %2::%3::%4\n"_s.arg( mLowerValue ).arg( mUpperValue ).arg( mLabel, mSymbol ? mSymbol->dump() : u"(no symbol)"_s );
137}
138
139void QgsRendererRange::toSld( QDomDocument &doc, QDomElement &element, QVariantMap props, bool firstRange ) const
140{
141 QgsSldExportContext context;
142 context.setExtraProperties( props );
143 toSld( doc, element, props.value( u"attribute"_s, QString() ).toString(), context, firstRange );
144}
145
146bool QgsRendererRange::toSld( QDomDocument &doc, QDomElement &element, const QString &classAttribute, QgsSldExportContext &context, bool firstRange ) const
147{
148 if ( !mSymbol || classAttribute.isEmpty() )
149 return false;
150
151 QString attrName = classAttribute;
152
153 QDomElement ruleElem = doc.createElement( u"se:Rule"_s );
154
155 QDomElement nameElem = doc.createElement( u"se:Name"_s );
156 nameElem.appendChild( doc.createTextNode( mLabel ) );
157 ruleElem.appendChild( nameElem );
158
159 QDomElement descrElem = doc.createElement( u"se:Description"_s );
160 QDomElement titleElem = doc.createElement( u"se:Title"_s );
161 QString descrStr = u"range: %1 - %2"_s.arg( qgsDoubleToString( mLowerValue ), qgsDoubleToString( mUpperValue ) );
162 titleElem.appendChild( doc.createTextNode( !mLabel.isEmpty() ? mLabel : descrStr ) );
163 descrElem.appendChild( titleElem );
164 ruleElem.appendChild( descrElem );
165
166 // create the ogc:Filter for the range
167 QString filterFunc = u"\"%1\" %2 %3 AND \"%1\" <= %4"_s.arg( attrName.replace( '\"', "\"\""_L1 ), firstRange ? u">="_s : u">"_s, qgsDoubleToString( mLowerValue ), qgsDoubleToString( mUpperValue ) );
168 QgsSymbolLayerUtils::createFunctionElement( doc, ruleElem, filterFunc, context );
169
170 mSymbol->toSld( doc, ruleElem, context );
171 if ( !QgsSymbolLayerUtils::hasSldSymbolizer( ruleElem ) )
172 {
173 // symbol could not be converted to SLD, or is an "empty" symbol. In this case we do not generate a rule, as
174 // SLD spec requires a Symbolizer element to be present
175 return false;
176 }
177
178 element.appendChild( ruleElem );
179 return true;
180}
181
183
184
187
189 : mFormat( u"%1 - %2"_s )
190 , mReTrailingZeroes( "[.,]?0*$" )
191 , mReNegativeZero( "^\\-0(?:[.,]0*)?$" )
192{}
193
202
203
205{
206 return format() == other.format() && precision() == other.precision() && trimTrailingZeroes() == other.trimTrailingZeroes();
207}
208
210{
211 return !( *this == other );
212}
213
215{
216 // Limit the range of decimal places to a reasonable range
219 mNumberScale = 1.0;
220 mNumberSuffix.clear();
221 while ( precision < 0 )
222 {
223 precision++;
224 mNumberScale /= 10.0;
225 mNumberSuffix.append( '0' );
226 }
227}
228
230{
231 return labelForRange( range.lowerValue(), range.upperValue() );
232}
233
234QString QgsRendererRangeLabelFormat::formatNumber( double value ) const
235{
236 if ( mPrecision > 0 )
237 {
238 QString valueStr = QLocale().toString( value, 'f', mPrecision );
240 valueStr = valueStr.remove( mReTrailingZeroes );
241 if ( mReNegativeZero.match( valueStr ).hasMatch() )
242 valueStr = valueStr.mid( 1 );
243 return valueStr;
244 }
245 else
246 {
247 QString valueStr = QLocale().toString( value * mNumberScale, 'f', 0 );
248 if ( valueStr == "-0"_L1 )
249 valueStr = '0';
250 if ( valueStr != "0"_L1 )
251 valueStr = valueStr + mNumberSuffix;
252 return valueStr;
253 }
254}
255
256QString QgsRendererRangeLabelFormat::labelForRange( double lower, double upper ) const
257{
258 QString lowerStr = formatNumber( lower );
259 QString upperStr = formatNumber( upper );
260
261 QString legend( mFormat );
262 return legend.replace( "%1"_L1, lowerStr ).replace( "%2"_L1, upperStr );
263}
264
266{
267 mFormat = element.attribute( u"format"_s, element.attribute( u"prefix"_s, u" "_s ) + "%1" + element.attribute( u"separator"_s, u" - "_s ) + "%2" + element.attribute( u"suffix"_s, u" "_s ) );
268 setPrecision( element.attribute( u"decimalplaces"_s, u"4"_s ).toInt() );
269 mTrimTrailingZeroes = element.attribute( u"trimtrailingzeroes"_s, u"false"_s ) == "true"_L1;
270}
271
273{
274 element.setAttribute( u"format"_s, mFormat );
275 element.setAttribute( u"decimalplaces"_s, mPrecision );
276 element.setAttribute( u"trimtrailingzeroes"_s, mTrimTrailingZeroes ? u"true"_s : u"false"_s );
277}
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:227
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition qgis.h:6893
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
Definition qgis.h:6975