QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgscategorizedsymbolrenderer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgscategorizedsymbolrenderer.cpp
3  ---------------------
4  begin : November 2009
5  copyright : (C) 2009 by Martin Dobias
6  email : wonder dot sk at gmail dot com
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 #include <algorithm>
16 
18 
20 #include "qgssymbol.h"
21 #include "qgssymbollayerutils.h"
22 #include "qgscolorramp.h"
23 #include "qgscolorrampimpl.h"
27 #include "qgspainteffect.h"
28 #include "qgspainteffectregistry.h"
29 #include "qgssymbollayer.h"
30 #include "qgsfeature.h"
31 #include "qgsvectorlayer.h"
32 #include "qgslogger.h"
33 #include "qgsproperty.h"
34 #include "qgsstyle.h"
35 #include "qgsfieldformatter.h"
37 #include "qgsapplication.h"
39 #include "qgsstyleentityvisitor.h"
41 #include "qgsmarkersymbol.h"
42 
43 #include <QDomDocument>
44 #include <QDomElement>
45 #include <QSettings> // for legend
46 #include <QRegularExpression>
47 
48 QgsRendererCategory::QgsRendererCategory( const QVariant &value, QgsSymbol *symbol, const QString &label, bool render )
49  : mValue( value )
50  , mSymbol( symbol )
51  , mLabel( label )
52  , mRender( render )
53 {
54 }
55 
57  : mValue( cat.mValue )
58  , mSymbol( cat.mSymbol ? cat.mSymbol->clone() : nullptr )
59  , mLabel( cat.mLabel )
60  , mRender( cat.mRender )
61 {
62 }
63 
64 // copy+swap idion, the copy is done through the 'pass by value'
66 {
67  swap( cat );
68  return *this;
69 }
70 
72 
74 {
75  std::swap( mValue, cat.mValue );
76  std::swap( mSymbol, cat.mSymbol );
77  std::swap( mLabel, cat.mLabel );
78 }
79 
81 {
82  return mValue;
83 }
84 
86 {
87  return mSymbol.get();
88 }
89 
91 {
92  return mLabel;
93 }
94 
96 {
97  return mRender;
98 }
99 
100 void QgsRendererCategory::setValue( const QVariant &value )
101 {
102  mValue = value;
103 }
104 
106 {
107  if ( mSymbol.get() != s ) mSymbol.reset( s );
108 }
109 
110 void QgsRendererCategory::setLabel( const QString &label )
111 {
112  mLabel = label;
113 }
114 
116 {
117  mRender = render;
118 }
119 
121 {
122  return QStringLiteral( "%1::%2::%3:%4\n" ).arg( mValue.toString(), mLabel, mSymbol->dump() ).arg( mRender );
123 }
124 
125 void QgsRendererCategory::toSld( QDomDocument &doc, QDomElement &element, QVariantMap props ) const
126 {
127  if ( !mSymbol.get() || props.value( QStringLiteral( "attribute" ), QString() ).toString().isEmpty() )
128  return;
129 
130  QString attrName = props[ QStringLiteral( "attribute" )].toString();
131 
132  QDomElement ruleElem = doc.createElement( QStringLiteral( "se:Rule" ) );
133  element.appendChild( ruleElem );
134 
135  QDomElement nameElem = doc.createElement( QStringLiteral( "se:Name" ) );
136  nameElem.appendChild( doc.createTextNode( mLabel ) );
137  ruleElem.appendChild( nameElem );
138 
139  QDomElement descrElem = doc.createElement( QStringLiteral( "se:Description" ) );
140  QDomElement titleElem = doc.createElement( QStringLiteral( "se:Title" ) );
141  QString descrStr = QStringLiteral( "%1 is '%2'" ).arg( attrName, mValue.toString() );
142  titleElem.appendChild( doc.createTextNode( !mLabel.isEmpty() ? mLabel : descrStr ) );
143  descrElem.appendChild( titleElem );
144  ruleElem.appendChild( descrElem );
145 
146  // create the ogc:Filter for the range
147  QString filterFunc;
148  if ( mValue.isNull() || mValue.toString().isEmpty() )
149  {
150  filterFunc = QStringLiteral( "%1 = '%2' or %1 is null" )
151  .arg( attrName.replace( '\"', QLatin1String( "\"\"" ) ),
152  mValue.toString().replace( '\'', QLatin1String( "''" ) ) );
153  }
154  else
155  {
156  filterFunc = QStringLiteral( "%1 = '%2'" )
157  .arg( attrName.replace( '\"', QLatin1String( "\"\"" ) ),
158  mValue.toString().replace( '\'', QLatin1String( "''" ) ) );
159  }
160 
161  QgsSymbolLayerUtils::createFunctionElement( doc, ruleElem, filterFunc );
162 
163  // add the mix/max scale denoms if we got any from the callers
164  QgsSymbolLayerUtils::applyScaleDependency( doc, ruleElem, props );
165 
166  mSymbol->toSld( doc, ruleElem, props );
167 }
168 
170 
172  : QgsFeatureRenderer( QStringLiteral( "categorizedSymbol" ) )
173  , mAttrName( attrName )
174 {
175  //important - we need a deep copy of the categories list, not a shared copy. This is required because
176  //QgsRendererCategory::symbol() is marked const, and so retrieving the symbol via this method does not
177  //trigger a detachment and copy of mCategories BUT that same method CAN be used to modify a symbol in place
178  for ( const QgsRendererCategory &cat : categories )
179  {
180  if ( !cat.symbol() )
181  {
182  QgsDebugMsg( QStringLiteral( "invalid symbol in a category! ignoring..." ) );
183  }
184  mCategories << cat;
185  }
186 }
187 
189 
191 {
192  mSymbolHash.clear();
193 
194  for ( const QgsRendererCategory &cat : std::as_const( mCategories ) )
195  {
196  const QVariant val = cat.value();
197  if ( val.type() == QVariant::List )
198  {
199  const QVariantList list = val.toList();
200  for ( const QVariant &v : list )
201  {
202  mSymbolHash.insert( v.toString(), ( cat.renderState() || mCounting ) ? cat.symbol() : nullptr );
203  }
204  }
205  else
206  {
207  mSymbolHash.insert( val.toString(), ( cat.renderState() || mCounting ) ? cat.symbol() : nullptr );
208  }
209  }
210 }
211 
213 {
214  return nullptr;
215 }
216 
218 {
219  bool found = false;
220  return symbolForValue( value, found );
221 }
222 
223 QgsSymbol *QgsCategorizedSymbolRenderer::symbolForValue( const QVariant &value, bool &foundMatchingSymbol ) const
224 {
225  foundMatchingSymbol = false;
226 
227  // TODO: special case for int, double
228  QHash<QString, QgsSymbol *>::const_iterator it = mSymbolHash.constFind( value.isNull() ? QString() : value.toString() );
229  if ( it == mSymbolHash.constEnd() )
230  {
231  if ( mSymbolHash.isEmpty() )
232  {
233  QgsDebugMsg( QStringLiteral( "there are no hashed symbols!!!" ) );
234  }
235  else
236  {
237  QgsDebugMsgLevel( "attribute value not found: " + value.toString(), 3 );
238  }
239  return nullptr;
240  }
241 
242  foundMatchingSymbol = true;
243 
244  return *it;
245 }
246 
248 {
249  return originalSymbolForFeature( feature, context );
250 }
251 
252 QVariant QgsCategorizedSymbolRenderer::valueForFeature( const QgsFeature &feature, QgsRenderContext &context ) const
253 {
254  QgsAttributes attrs = feature.attributes();
255  QVariant value;
256  if ( mAttrNum == -1 )
257  {
258  Q_ASSERT( mExpression );
259 
260  value = mExpression->evaluate( &context.expressionContext() );
261  }
262  else
263  {
264  value = attrs.value( mAttrNum );
265  }
266 
267  return value;
268 }
269 
271 {
272  QVariant value = valueForFeature( feature, context );
273 
274  bool foundCategory = false;
275  // find the right symbol for the category
276  QgsSymbol *symbol = symbolForValue( value, foundCategory );
277 
278  if ( !foundCategory )
279  {
280  // if no symbol found, use default symbol
281  return symbolForValue( QVariant( "" ), foundCategory );
282  }
283 
284  return symbol;
285 }
286 
287 
289 {
290  for ( int i = 0; i < mCategories.count(); i++ )
291  {
292  if ( mCategories[i].value() == val )
293  return i;
294  }
295  return -1;
296 }
297 
299 {
300  int idx = -1;
301  for ( int i = 0; i < mCategories.count(); i++ )
302  {
303  if ( mCategories[i].label() == val )
304  {
305  if ( idx != -1 )
306  return -1;
307  else
308  idx = i;
309  }
310  }
311  return idx;
312 }
313 
314 bool QgsCategorizedSymbolRenderer::updateCategoryValue( int catIndex, const QVariant &value )
315 {
316  if ( catIndex < 0 || catIndex >= mCategories.size() )
317  return false;
318  mCategories[catIndex].setValue( value );
319  return true;
320 }
321 
323 {
324  if ( catIndex < 0 || catIndex >= mCategories.size() )
325  return false;
326  mCategories[catIndex].setSymbol( symbol );
327  return true;
328 }
329 
330 bool QgsCategorizedSymbolRenderer::updateCategoryLabel( int catIndex, const QString &label )
331 {
332  if ( catIndex < 0 || catIndex >= mCategories.size() )
333  return false;
334  mCategories[catIndex].setLabel( label );
335  return true;
336 }
337 
339 {
340  if ( catIndex < 0 || catIndex >= mCategories.size() )
341  return false;
342  mCategories[catIndex].setRenderState( render );
343  return true;
344 }
345 
347 {
348  if ( !cat.symbol() )
349  {
350  QgsDebugMsg( QStringLiteral( "invalid symbol in a category! ignoring..." ) );
351  return;
352  }
353 
354  mCategories.append( cat );
355 }
356 
358 {
359  if ( catIndex < 0 || catIndex >= mCategories.size() )
360  return false;
361 
362  mCategories.removeAt( catIndex );
363  return true;
364 }
365 
367 {
368  mCategories.clear();
369 }
370 
372 {
373  if ( from < 0 || from >= mCategories.size() || to < 0 || to >= mCategories.size() ) return;
374  mCategories.move( from, to );
375 }
376 
378 {
379  return qgsVariantLessThan( c1.value(), c2.value() );
380 }
382 {
383  return qgsVariantGreaterThan( c1.value(), c2.value() );
384 }
385 
386 void QgsCategorizedSymbolRenderer::sortByValue( Qt::SortOrder order )
387 {
388  if ( order == Qt::AscendingOrder )
389  {
390  std::sort( mCategories.begin(), mCategories.end(), valueLessThan );
391  }
392  else
393  {
394  std::sort( mCategories.begin(), mCategories.end(), valueGreaterThan );
395  }
396 }
397 
399 {
400  return QString::localeAwareCompare( c1.label(), c2.label() ) < 0;
401 }
402 
404 {
405  return !labelLessThan( c1, c2 );
406 }
407 
408 void QgsCategorizedSymbolRenderer::sortByLabel( Qt::SortOrder order )
409 {
410  if ( order == Qt::AscendingOrder )
411  {
412  std::sort( mCategories.begin(), mCategories.end(), labelLessThan );
413  }
414  else
415  {
416  std::sort( mCategories.begin(), mCategories.end(), labelGreaterThan );
417  }
418 }
419 
421 {
422  QgsFeatureRenderer::startRender( context, fields );
423 
424  mCounting = context.rendererScale() == 0.0;
425 
426  // make sure that the hash table is up to date
427  rebuildHash();
428 
429  // find out classification attribute index from name
430  mAttrNum = fields.lookupField( mAttrName );
431  if ( mAttrNum == -1 )
432  {
433  mExpression.reset( new QgsExpression( mAttrName ) );
434  mExpression->prepare( &context.expressionContext() );
435  }
436 
437  for ( const QgsRendererCategory &cat : std::as_const( mCategories ) )
438  {
439  cat.symbol()->startRender( context, fields );
440  }
441 }
442 
444 {
446 
447  for ( const QgsRendererCategory &cat : std::as_const( mCategories ) )
448  {
449  cat.symbol()->stopRender( context );
450  }
451  mExpression.reset();
452 }
453 
455 {
456  QSet<QString> attributes;
457 
458  // mAttrName can contain either attribute name or an expression.
459  // Sometimes it is not possible to distinguish between those two,
460  // e.g. "a - b" can be both a valid attribute name or expression.
461  // Since we do not have access to fields here, try both options.
462  attributes << mAttrName;
463 
464  QgsExpression testExpr( mAttrName );
465  if ( !testExpr.hasParserError() )
466  attributes.unite( testExpr.referencedColumns() );
467 
468  QgsCategoryList::const_iterator catIt = mCategories.constBegin();
469  for ( ; catIt != mCategories.constEnd(); ++catIt )
470  {
471  QgsSymbol *catSymbol = catIt->symbol();
472  if ( catSymbol )
473  {
474  attributes.unite( catSymbol->usedAttributes( context ) );
475  }
476  }
477  return attributes;
478 }
479 
481 {
482  QgsExpression testExpr( mAttrName );
483  if ( !testExpr.hasParserError() )
484  {
485  QgsExpressionContext context;
486  context.appendScopes( QgsExpressionContextUtils::globalProjectLayerScopes( nullptr ) ); // unfortunately no layer access available!
487  testExpr.prepare( &context );
488  return testExpr.needsGeometry();
489  }
490  return false;
491 }
492 
494 {
495  QString s = QStringLiteral( "CATEGORIZED: idx %1\n" ).arg( mAttrName );
496  for ( int i = 0; i < mCategories.count(); i++ )
497  s += mCategories[i].dump();
498  return s;
499 }
500 
502 {
504  if ( mSourceSymbol )
505  r->setSourceSymbol( mSourceSymbol->clone() );
506  if ( mSourceColorRamp )
507  {
508  r->setSourceColorRamp( mSourceColorRamp->clone() );
509  }
511 
512  copyRendererData( r );
513  return r;
514 }
515 
516 void QgsCategorizedSymbolRenderer::toSld( QDomDocument &doc, QDomElement &element, const QVariantMap &props ) const
517 {
518  QVariantMap newProps = props;
519  newProps[ QStringLiteral( "attribute" )] = mAttrName;
520 
521  // create a Rule for each range
522  for ( QgsCategoryList::const_iterator it = mCategories.constBegin(); it != mCategories.constEnd(); ++it )
523  {
524  it->toSld( doc, element, newProps );
525  }
526 }
527 
529 {
530  int attrNum = fields.lookupField( mAttrName );
531  bool isExpression = ( attrNum == -1 );
532 
533  bool hasDefault = false;
534  bool defaultActive = false;
535  bool allActive = true;
536  bool noneActive = true;
537 
538  //we need to build lists of both inactive and active values, as either list may be required
539  //depending on whether the default category is active or not
540  QString activeValues;
541  QString inactiveValues;
542 
543  for ( const QgsRendererCategory &cat : std::as_const( mCategories ) )
544  {
545  if ( cat.value() == "" || cat.value().isNull() )
546  {
547  hasDefault = true;
548  defaultActive = cat.renderState();
549  }
550 
551  noneActive = noneActive && !cat.renderState();
552  allActive = allActive && cat.renderState();
553 
554  QVariant::Type valType = isExpression ? cat.value().type() : fields.at( attrNum ).type();
555  const bool isList = cat.value().type() == QVariant::List;
556  QString value = QgsExpression::quotedValue( cat.value(), valType );
557 
558  if ( !cat.renderState() )
559  {
560  if ( cat.value() != "" )
561  {
562  if ( isList )
563  {
564  const QVariantList list = cat.value().toList();
565  for ( const QVariant &v : list )
566  {
567  if ( !inactiveValues.isEmpty() )
568  inactiveValues.append( ',' );
569 
570  inactiveValues.append( QgsExpression::quotedValue( v, isExpression ? v.type() : fields.at( attrNum ).type() ) );
571  }
572  }
573  else
574  {
575  if ( !inactiveValues.isEmpty() )
576  inactiveValues.append( ',' );
577 
578  inactiveValues.append( value );
579  }
580  }
581  }
582  else
583  {
584  if ( cat.value() != "" )
585  {
586  if ( isList )
587  {
588  const QVariantList list = cat.value().toList();
589  for ( const QVariant &v : list )
590  {
591  if ( !activeValues.isEmpty() )
592  activeValues.append( ',' );
593 
594  activeValues.append( QgsExpression::quotedValue( v, isExpression ? v.type() : fields.at( attrNum ).type() ) );
595  }
596  }
597  else
598  {
599  if ( !activeValues.isEmpty() )
600  activeValues.append( ',' );
601 
602  activeValues.append( value );
603  }
604  }
605  }
606  }
607 
608  QString attr = isExpression ? mAttrName : QStringLiteral( "\"%1\"" ).arg( mAttrName );
609 
610  if ( allActive && hasDefault )
611  {
612  return QString();
613  }
614  else if ( noneActive )
615  {
616  return QStringLiteral( "FALSE" );
617  }
618  else if ( defaultActive )
619  {
620  return QStringLiteral( "(%1) NOT IN (%2) OR (%1) IS NULL" ).arg( attr, inactiveValues );
621  }
622  else
623  {
624  return QStringLiteral( "(%1) IN (%2)" ).arg( attr, activeValues );
625  }
626 }
627 
629 {
630  Q_UNUSED( context )
631  QgsSymbolList lst;
632  lst.reserve( mCategories.count() );
633  for ( const QgsRendererCategory &cat : mCategories )
634  {
635  lst.append( cat.symbol() );
636  }
637  return lst;
638 }
639 
641 {
642  for ( const QgsRendererCategory &cat : mCategories )
643  {
644  QgsStyleSymbolEntity entity( cat.symbol() );
645  if ( !visitor->visit( QgsStyleEntityVisitorInterface::StyleLeaf( &entity, cat.value().toString(), cat.label() ) ) )
646  return false;
647  }
648 
649  if ( mSourceColorRamp )
650  {
652  if ( !visitor->visit( QgsStyleEntityVisitorInterface::StyleLeaf( &entity ) ) )
653  return false;
654  }
655 
656  return true;
657 }
658 
660 {
661  QDomElement symbolsElem = element.firstChildElement( QStringLiteral( "symbols" ) );
662  if ( symbolsElem.isNull() )
663  return nullptr;
664 
665  QDomElement catsElem = element.firstChildElement( QStringLiteral( "categories" ) );
666  if ( catsElem.isNull() )
667  return nullptr;
668 
669  QgsSymbolMap symbolMap = QgsSymbolLayerUtils::loadSymbols( symbolsElem, context );
670  QgsCategoryList cats;
671 
672  // Value from string (long, ulong, double and string)
673  const auto valueFromString = []( const QString & value, const QString & valueType ) -> QVariant
674  {
675  if ( valueType == QLatin1String( "double" ) )
676  {
677  bool ok;
678  const auto val { value.toDouble( &ok ) };
679  if ( ok )
680  {
681  return val;
682  }
683  }
684  else if ( valueType == QLatin1String( "ulong" ) )
685  {
686  bool ok;
687  const auto val { value.toULongLong( &ok ) };
688  if ( ok )
689  {
690  return val;
691  }
692  }
693  else if ( valueType == QLatin1String( "long" ) )
694  {
695  bool ok;
696  const auto val { value.toLongLong( &ok ) };
697  if ( ok )
698  {
699  return val;
700  }
701  }
702  return value;
703  };
704 
705  QDomElement catElem = catsElem.firstChildElement();
706  while ( !catElem.isNull() )
707  {
708  if ( catElem.tagName() == QLatin1String( "category" ) )
709  {
710  QVariant value;
711  if ( catElem.hasAttribute( QStringLiteral( "value" ) ) )
712  {
713  value = valueFromString( catElem.attribute( QStringLiteral( "value" ) ), catElem.attribute( QStringLiteral( "type" ), QString() ) ) ;
714 
715  }
716  else
717  {
718  QVariantList values;
719  QDomElement valElem = catElem.firstChildElement();
720  while ( !valElem.isNull() )
721  {
722  if ( valElem.tagName() == QLatin1String( "val" ) )
723  {
724  values << valueFromString( valElem.attribute( QStringLiteral( "value" ) ), valElem.attribute( QStringLiteral( "type" ), QString() ) );
725  }
726  valElem = valElem.nextSiblingElement();
727  }
728  if ( !values.isEmpty() )
729  value = values;
730  }
731  QString symbolName = catElem.attribute( QStringLiteral( "symbol" ) );
732  QString label = catElem.attribute( QStringLiteral( "label" ) );
733  bool render = catElem.attribute( QStringLiteral( "render" ) ) != QLatin1String( "false" );
734  if ( symbolMap.contains( symbolName ) )
735  {
736  QgsSymbol *symbol = symbolMap.take( symbolName );
737  cats.append( QgsRendererCategory( value, symbol, label, render ) );
738  }
739  }
740  catElem = catElem.nextSiblingElement();
741  }
742 
743  QString attrName = element.attribute( QStringLiteral( "attr" ) );
744 
746 
747  // delete symbols if there are any more
749 
750  // try to load source symbol (optional)
751  QDomElement sourceSymbolElem = element.firstChildElement( QStringLiteral( "source-symbol" ) );
752  if ( !sourceSymbolElem.isNull() )
753  {
754  QgsSymbolMap sourceSymbolMap = QgsSymbolLayerUtils::loadSymbols( sourceSymbolElem, context );
755  if ( sourceSymbolMap.contains( QStringLiteral( "0" ) ) )
756  {
757  r->setSourceSymbol( sourceSymbolMap.take( QStringLiteral( "0" ) ) );
758  }
759  QgsSymbolLayerUtils::clearSymbolMap( sourceSymbolMap );
760  }
761 
762  // try to load color ramp (optional)
763  QDomElement sourceColorRampElem = element.firstChildElement( QStringLiteral( "colorramp" ) );
764  if ( !sourceColorRampElem.isNull() && sourceColorRampElem.attribute( QStringLiteral( "name" ) ) == QLatin1String( "[source]" ) )
765  {
766  r->setSourceColorRamp( QgsSymbolLayerUtils::loadColorRamp( sourceColorRampElem ) );
767  }
768 
769  QDomElement rotationElem = element.firstChildElement( QStringLiteral( "rotation" ) );
770  if ( !rotationElem.isNull() && !rotationElem.attribute( QStringLiteral( "field" ) ).isEmpty() )
771  {
772  for ( const QgsRendererCategory &cat : r->mCategories )
773  {
774  convertSymbolRotation( cat.symbol(), rotationElem.attribute( QStringLiteral( "field" ) ) );
775  }
776  if ( r->mSourceSymbol )
777  {
778  convertSymbolRotation( r->mSourceSymbol.get(), rotationElem.attribute( QStringLiteral( "field" ) ) );
779  }
780  }
781 
782  QDomElement sizeScaleElem = element.firstChildElement( QStringLiteral( "sizescale" ) );
783  if ( !sizeScaleElem.isNull() && !sizeScaleElem.attribute( QStringLiteral( "field" ) ).isEmpty() )
784  {
785  for ( const QgsRendererCategory &cat : r->mCategories )
786  {
788  QgsSymbolLayerUtils::decodeScaleMethod( sizeScaleElem.attribute( QStringLiteral( "scalemethod" ) ) ),
789  sizeScaleElem.attribute( QStringLiteral( "field" ) ) );
790  }
791  if ( r->mSourceSymbol && r->mSourceSymbol->type() == Qgis::SymbolType::Marker )
792  {
794  QgsSymbolLayerUtils::decodeScaleMethod( sizeScaleElem.attribute( QStringLiteral( "scalemethod" ) ) ),
795  sizeScaleElem.attribute( QStringLiteral( "field" ) ) );
796  }
797  }
798 
799  QDomElement ddsLegendSizeElem = element.firstChildElement( QStringLiteral( "data-defined-size-legend" ) );
800  if ( !ddsLegendSizeElem.isNull() )
801  {
802  r->mDataDefinedSizeLegend.reset( QgsDataDefinedSizeLegend::readXml( ddsLegendSizeElem, context ) );
803  }
804 
805  // TODO: symbol levels
806  return r;
807 }
808 
809 QDomElement QgsCategorizedSymbolRenderer::save( QDomDocument &doc, const QgsReadWriteContext &context )
810 {
811  // clazy:skip
812  QDomElement rendererElem = doc.createElement( RENDERER_TAG_NAME );
813  rendererElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "categorizedSymbol" ) );
814  rendererElem.setAttribute( QStringLiteral( "attr" ), mAttrName );
815 
816  // String for type
817  // We just need string and three numeric types: double, ulong and long for unsigned, signed and float/double
818  const auto stringForType = []( const QVariant::Type type ) -> QString
819  {
820  if ( type == QVariant::Char || type == QVariant::Int || type == QVariant::LongLong )
821  {
822  return QStringLiteral( "long" );
823  }
824  else if ( type == QVariant::UInt || type == QVariant::ULongLong )
825  {
826  return QStringLiteral( "ulong" );
827  }
828  else if ( type == QVariant::Double )
829  {
830  return QStringLiteral( "double" ) ;
831  }
832  else // Default: string
833  {
834  return QStringLiteral( "string" );
835  }
836  };
837 
838  // categories
839  if ( !mCategories.isEmpty() )
840  {
841  int i = 0;
843  QDomElement catsElem = doc.createElement( QStringLiteral( "categories" ) );
844  QgsCategoryList::const_iterator it = mCategories.constBegin();
845  for ( ; it != mCategories.constEnd(); ++it )
846  {
847  const QgsRendererCategory &cat = *it;
848  QString symbolName = QString::number( i );
849  symbols.insert( symbolName, cat.symbol() );
850 
851  QDomElement catElem = doc.createElement( QStringLiteral( "category" ) );
852  if ( cat.value().type() == QVariant::List )
853  {
854  const QVariantList list = cat.value().toList();
855  for ( const QVariant &v : list )
856  {
857  QDomElement valueElem = doc.createElement( QStringLiteral( "val" ) );
858  valueElem.setAttribute( QStringLiteral( "value" ), v.toString() );
859  valueElem.setAttribute( QStringLiteral( "type" ), stringForType( v.type() ) );
860  catElem.appendChild( valueElem );
861  }
862  }
863  else
864  {
865  catElem.setAttribute( QStringLiteral( "value" ), cat.value().toString() );
866  catElem.setAttribute( QStringLiteral( "type" ), stringForType( cat.value().type() ) );
867  }
868  catElem.setAttribute( QStringLiteral( "symbol" ), symbolName );
869  catElem.setAttribute( QStringLiteral( "label" ), cat.label() );
870  catElem.setAttribute( QStringLiteral( "render" ), cat.renderState() ? "true" : "false" );
871  catsElem.appendChild( catElem );
872  i++;
873  }
874  rendererElem.appendChild( catsElem );
875 
876  // save symbols
877  QDomElement symbolsElem = QgsSymbolLayerUtils::saveSymbols( symbols, QStringLiteral( "symbols" ), doc, context );
878  rendererElem.appendChild( symbolsElem );
879  }
880 
881  // save source symbol
882  if ( mSourceSymbol )
883  {
884  QgsSymbolMap sourceSymbols;
885  sourceSymbols.insert( QStringLiteral( "0" ), mSourceSymbol.get() );
886  QDomElement sourceSymbolElem = QgsSymbolLayerUtils::saveSymbols( sourceSymbols, QStringLiteral( "source-symbol" ), doc, context );
887  rendererElem.appendChild( sourceSymbolElem );
888  }
889 
890  // save source color ramp
891  if ( mSourceColorRamp )
892  {
893  QDomElement colorRampElem = QgsSymbolLayerUtils::saveColorRamp( QStringLiteral( "[source]" ), mSourceColorRamp.get(), doc );
894  rendererElem.appendChild( colorRampElem );
895  }
896 
897  QDomElement rotationElem = doc.createElement( QStringLiteral( "rotation" ) );
898  rendererElem.appendChild( rotationElem );
899 
900  QDomElement sizeScaleElem = doc.createElement( QStringLiteral( "sizescale" ) );
901  rendererElem.appendChild( sizeScaleElem );
902 
904  {
905  QDomElement ddsLegendElem = doc.createElement( QStringLiteral( "data-defined-size-legend" ) );
906  mDataDefinedSizeLegend->writeXml( ddsLegendElem, context );
907  rendererElem.appendChild( ddsLegendElem );
908  }
909 
910  saveRendererData( doc, rendererElem, context );
911 
912  return rendererElem;
913 }
914 
915 
916 QgsLegendSymbolList QgsCategorizedSymbolRenderer::baseLegendSymbolItems() const
917 {
919  int i = 0;
920  for ( const QgsRendererCategory &cat : mCategories )
921  {
922  lst << QgsLegendSymbolItem( cat.symbol(), cat.label(), QString::number( i++ ), true );
923  }
924  return lst;
925 }
926 
928 {
929 
930  auto _displayString = [ ]( const QVariant & v, int precision ) -> QString
931  {
932 
933  if ( v.isNull() )
934  {
936  }
937 
938  const bool isNumeric {v.type() == QVariant::Double || v.type() == QVariant::Int || v.type() == QVariant::UInt || v.type() == QVariant::LongLong || v.type() == QVariant::ULongLong};
939 
940  // Special treatment for numeric types if group separator is set or decimalPoint is not a dot
941  if ( v.type() == QVariant::Double )
942  {
943  // if value doesn't contain a double (a default value expression for instance),
944  // apply no transformation
945  bool ok;
946  v.toDouble( &ok );
947  if ( !ok )
948  return v.toString();
949 
950  // Locales with decimal point != '.' or that require group separator: use QLocale
951  if ( QLocale().decimalPoint() != '.' ||
952  !( QLocale().numberOptions() & QLocale::NumberOption::OmitGroupSeparator ) )
953  {
954  if ( precision > 0 )
955  {
956  if ( -1 < v.toDouble() && v.toDouble() < 1 )
957  {
958  return QLocale().toString( v.toDouble(), 'g', precision );
959  }
960  else
961  {
962  return QLocale().toString( v.toDouble(), 'f', precision );
963  }
964  }
965  else
966  {
967  // Precision is not set, let's guess it from the
968  // standard conversion to string
969  const QString s( v.toString() );
970  const int dotPosition( s.indexOf( '.' ) );
971  int precision;
972  if ( dotPosition < 0 && s.indexOf( 'e' ) < 0 )
973  {
974  precision = 0;
975  return QLocale().toString( v.toDouble(), 'f', precision );
976  }
977  else
978  {
979  if ( dotPosition < 0 ) precision = 0;
980  else precision = s.length() - dotPosition - 1;
981 
982  if ( -1 < v.toDouble() && v.toDouble() < 1 )
983  {
984  return QLocale().toString( v.toDouble(), 'g', precision );
985  }
986  else
987  {
988  return QLocale().toString( v.toDouble(), 'f', precision );
989  }
990  }
991  }
992  }
993  // Default for doubles with precision
994  else if ( precision > 0 )
995  {
996  if ( -1 < v.toDouble() && v.toDouble() < 1 )
997  {
998  return QString::number( v.toDouble(), 'g', precision );
999  }
1000  else
1001  {
1002  return QString::number( v.toDouble(), 'f', precision );
1003  }
1004  }
1005  }
1006  // Other numeric types than doubles
1007  else if ( isNumeric &&
1008  !( QLocale().numberOptions() & QLocale::NumberOption::OmitGroupSeparator ) )
1009  {
1010  bool ok;
1011  const qlonglong converted( v.toLongLong( &ok ) );
1012  if ( ok )
1013  return QLocale().toString( converted );
1014  }
1015  else if ( v.type() == QVariant::ByteArray )
1016  {
1017  return QObject::tr( "BLOB" );
1018  }
1019 
1020  // Fallback if special rules do not apply
1021  return v.toString();
1022  };
1023 
1024  if ( v.type() == QVariant::StringList || v.type() == QVariant::List )
1025  {
1026  // Note that this code is never hit because the joining of lists (merged categories) happens
1027  // in data(); I'm leaving this here anyway because it is tested and it may be useful for
1028  // other purposes in the future.
1029  QString result;
1030  const QVariantList list = v.toList();
1031  for ( const QVariant &var : list )
1032  {
1033  if ( !result.isEmpty() )
1034  {
1035  result.append( ';' );
1036  }
1037  result.append( _displayString( var, precision ) );
1038  }
1039  return result;
1040  }
1041  else
1042  {
1043  return _displayString( v, precision );
1044  }
1045 }
1046 
1048 {
1050  {
1051  // check that all symbols that have the same size expression
1052  QgsProperty ddSize;
1053  for ( const QgsRendererCategory &category : mCategories )
1054  {
1055  const QgsMarkerSymbol *symbol = static_cast<const QgsMarkerSymbol *>( category.symbol() );
1056  if ( ddSize )
1057  {
1058  QgsProperty sSize( symbol->dataDefinedSize() );
1059  if ( sSize != ddSize )
1060  {
1061  // no common size expression
1062  return baseLegendSymbolItems();
1063  }
1064  }
1065  else
1066  {
1067  ddSize = symbol->dataDefinedSize();
1068  }
1069  }
1070 
1071  if ( ddSize && ddSize.isActive() )
1072  {
1073  QgsLegendSymbolList lst;
1074 
1076  ddSizeLegend.updateFromSymbolAndProperty( static_cast<const QgsMarkerSymbol *>( mSourceSymbol.get() ), ddSize );
1077  lst += ddSizeLegend.legendSymbolList();
1078 
1079  lst += baseLegendSymbolItems();
1080  return lst;
1081  }
1082  }
1083 
1084  return baseLegendSymbolItems();
1085 }
1086 
1088 {
1089  const QVariant value = valueForFeature( feature, context );
1090  int i = 0;
1091 
1092  for ( const QgsRendererCategory &cat : mCategories )
1093  {
1094  bool match = false;
1095  if ( cat.value().type() == QVariant::List )
1096  {
1097  const QVariantList list = cat.value().toList();
1098  for ( const QVariant &v : list )
1099  {
1100  if ( value == v )
1101  {
1102  match = true;
1103  break;
1104  }
1105  }
1106  }
1107  else
1108  {
1109  // Numeric NULL cat value is stored as an empty string
1110  if ( value.isNull() && ( value.type() == QVariant::Double || value.type() == QVariant::Int ||
1111  value.type() == QVariant::UInt || value.type() == QVariant::LongLong ||
1112  value.type() == QVariant::ULongLong ) )
1113  {
1114  match = cat.value().toString().isEmpty();
1115  }
1116  else
1117  {
1118  match = value == cat.value();
1119  }
1120  }
1121 
1122  if ( match )
1123  {
1124  if ( cat.renderState() || mCounting )
1125  return QSet< QString >() << QString::number( i );
1126  else
1127  return QSet< QString >();
1128  }
1129  i++;
1130  }
1131 
1132  return QSet< QString >();
1133 }
1134 
1135 QString QgsCategorizedSymbolRenderer::legendKeyToExpression( const QString &key, QgsVectorLayer *layer, bool &ok ) const
1136 {
1137  ok = false;
1138  int ruleIndex = key.toInt( &ok );
1139  if ( !ok || ruleIndex < 0 || ruleIndex >= mCategories.size() )
1140  {
1141  ok = false;
1142  return QString();
1143  }
1144 
1145  const int fieldIndex = layer ? layer->fields().lookupField( mAttrName ) : -1;
1146  const bool isNumeric = layer && fieldIndex >= 0 ? layer->fields().at( fieldIndex ).isNumeric() : false;
1147  const QVariant::Type fieldType = layer && fieldIndex >= 0 ? layer->fields().at( fieldIndex ).type() : QVariant::Invalid;
1148  const QString attributeComponent = QgsExpression::quoteFieldExpression( mAttrName, layer );
1149 
1150  ok = true;
1151  const QgsRendererCategory &cat = mCategories[ ruleIndex ];
1152  if ( cat.value().type() == QVariant::List )
1153  {
1154  const QVariantList list = cat.value().toList();
1155  QStringList parts;
1156  parts.reserve( list.size() );
1157  for ( const QVariant &v : list )
1158  {
1159  parts.append( QgsExpression::quotedValue( v ) );
1160  }
1161 
1162  return QStringLiteral( "%1 IN (%2)" ).arg( attributeComponent, parts.join( QLatin1String( ", " ) ) );
1163  }
1164  else
1165  {
1166  // Numeric NULL cat value is stored as an empty string
1167  QVariant value = cat.value();
1168  if ( isNumeric && value.toString().isEmpty() )
1169  {
1170  value = QVariant();
1171  }
1172 
1173  if ( value.isNull() )
1174  return QStringLiteral( "%1 IS NULL" ).arg( attributeComponent );
1175  else if ( fieldType == QVariant::Type::Invalid )
1176  return QStringLiteral( "%1 = %2" ).arg( attributeComponent, QgsExpression::quotedValue( value ) );
1177  else
1178  return QStringLiteral( "%1 = %2" ).arg( attributeComponent, QgsExpression::quotedValue( value, fieldType ) );
1179  }
1180 }
1181 
1183 {
1184  return mSourceSymbol.get();
1185 }
1186 
1188 {
1189  return mSourceSymbol.get();
1190 }
1191 
1193 {
1194  mSourceSymbol.reset( sym );
1195 }
1196 
1198 {
1199  return mSourceColorRamp.get();
1200 }
1201 
1203 {
1204  return mSourceColorRamp.get();
1205 }
1206 
1208 {
1209  mSourceColorRamp.reset( ramp );
1210 }
1211 
1213 {
1214  setSourceColorRamp( ramp );
1215  double num = mCategories.count() - 1;
1216  double count = 0;
1217 
1218  QgsRandomColorRamp *randomRamp = dynamic_cast<QgsRandomColorRamp *>( ramp );
1219  if ( randomRamp )
1220  {
1221  //ramp is a random colors ramp, so inform it of the total number of required colors
1222  //this allows the ramp to pregenerate a set of visually distinctive colors
1223  randomRamp->setTotalColorCount( mCategories.count() );
1224  }
1225 
1226  for ( const QgsRendererCategory &cat : mCategories )
1227  {
1228  double value = count / num;
1229  cat.symbol()->setColor( mSourceColorRamp->color( value ) );
1230  count += 1;
1231  }
1232 }
1233 
1235 {
1236  int i = 0;
1237  for ( const QgsRendererCategory &cat : mCategories )
1238  {
1239  QgsSymbol *symbol = sym->clone();
1240  symbol->setColor( cat.symbol()->color() );
1241  updateCategorySymbol( i, symbol );
1242  ++i;
1243  }
1244  setSourceSymbol( sym->clone() );
1245 }
1246 
1248 {
1249  return true;
1250 }
1251 
1253 {
1254  bool ok;
1255  int index = key.toInt( &ok );
1256  if ( ok && index >= 0 && index < mCategories.size() )
1257  return mCategories.at( index ).renderState();
1258  else
1259  return true;
1260 }
1261 
1263 {
1264  bool ok;
1265  int index = key.toInt( &ok );
1266  if ( ok )
1267  updateCategorySymbol( index, symbol );
1268  else
1269  delete symbol;
1270 }
1271 
1272 void QgsCategorizedSymbolRenderer::checkLegendSymbolItem( const QString &key, bool state )
1273 {
1274  bool ok;
1275  int index = key.toInt( &ok );
1276  if ( ok )
1277  updateCategoryRenderState( index, state );
1278 }
1279 
1281 {
1282  std::unique_ptr< QgsCategorizedSymbolRenderer > r;
1283  if ( renderer->type() == QLatin1String( "categorizedSymbol" ) )
1284  {
1285  r.reset( static_cast<QgsCategorizedSymbolRenderer *>( renderer->clone() ) );
1286  }
1287  else if ( renderer->type() == QLatin1String( "graduatedSymbol" ) )
1288  {
1289  const QgsGraduatedSymbolRenderer *graduatedSymbolRenderer = dynamic_cast<const QgsGraduatedSymbolRenderer *>( renderer );
1290  if ( graduatedSymbolRenderer )
1291  {
1292  r.reset( new QgsCategorizedSymbolRenderer( QString(), QgsCategoryList() ) );
1293  if ( graduatedSymbolRenderer->sourceSymbol() )
1294  r->setSourceSymbol( graduatedSymbolRenderer->sourceSymbol()->clone() );
1295  if ( graduatedSymbolRenderer->sourceColorRamp() )
1296  {
1297  r->setSourceColorRamp( graduatedSymbolRenderer->sourceColorRamp()->clone() );
1298  }
1299  r->setClassAttribute( graduatedSymbolRenderer->classAttribute() );
1300  }
1301  }
1302  else if ( renderer->type() == QLatin1String( "pointDisplacement" ) || renderer->type() == QLatin1String( "pointCluster" ) )
1303  {
1304  const QgsPointDistanceRenderer *pointDistanceRenderer = dynamic_cast<const QgsPointDistanceRenderer *>( renderer );
1305  if ( pointDistanceRenderer )
1306  r.reset( convertFromRenderer( pointDistanceRenderer->embeddedRenderer() ) );
1307  }
1308  else if ( renderer->type() == QLatin1String( "invertedPolygonRenderer" ) )
1309  {
1310  const QgsInvertedPolygonRenderer *invertedPolygonRenderer = dynamic_cast<const QgsInvertedPolygonRenderer *>( renderer );
1311  if ( invertedPolygonRenderer )
1312  r.reset( convertFromRenderer( invertedPolygonRenderer->embeddedRenderer() ) );
1313  }
1314  else if ( renderer->type() == QLatin1String( "embeddedSymbol" ) && layer )
1315  {
1316  const QgsEmbeddedSymbolRenderer *embeddedRenderer = dynamic_cast<const QgsEmbeddedSymbolRenderer *>( renderer );
1318  QgsFeatureRequest req;
1320  req.setNoAttributes();
1321  QgsFeatureIterator it = layer->getFeatures( req );
1322  QgsFeature feature;
1323  while ( it.nextFeature( feature ) && categories.size() < 2000 )
1324  {
1325  if ( feature.embeddedSymbol() )
1326  categories.append( QgsRendererCategory( feature.id(), feature.embeddedSymbol()->clone(), QString::number( feature.id() ) ) );
1327  }
1328  categories.append( QgsRendererCategory( QVariant(), embeddedRenderer->defaultSymbol()->clone(), QString() ) );
1329  r.reset( new QgsCategorizedSymbolRenderer( QStringLiteral( "$id" ), categories ) );
1330  }
1331 
1332  // If not one of the specifically handled renderers, then just grab the symbol from the renderer
1333  // Could have applied this to specific renderer types (singleSymbol, graduatedSymbol)
1334 
1335  if ( !r )
1336  {
1337  r = std::make_unique< QgsCategorizedSymbolRenderer >( QString(), QgsCategoryList() );
1338  QgsRenderContext context;
1339  QgsSymbolList symbols = const_cast<QgsFeatureRenderer *>( renderer )->symbols( context );
1340  if ( !symbols.isEmpty() )
1341  {
1342  r->setSourceSymbol( symbols.at( 0 )->clone() );
1343  }
1344  }
1345 
1346  renderer->copyRendererData( r.get() );
1347 
1348  return r.release();
1349 }
1350 
1352 {
1353  mDataDefinedSizeLegend.reset( settings );
1354 }
1355 
1357 {
1358  return mDataDefinedSizeLegend.get();
1359 }
1360 
1361 int QgsCategorizedSymbolRenderer::matchToSymbols( QgsStyle *style, Qgis::SymbolType type, QVariantList &unmatchedCategories, QStringList &unmatchedSymbols, const bool caseSensitive, const bool useTolerantMatch )
1362 {
1363  if ( !style )
1364  return 0;
1365 
1366  int matched = 0;
1367  unmatchedSymbols = style->symbolNames();
1368  const QSet< QString > allSymbolNames = qgis::listToSet( unmatchedSymbols );
1369 
1370  const QRegularExpression tolerantMatchRe( QStringLiteral( "[^\\w\\d ]" ), QRegularExpression::UseUnicodePropertiesOption );
1371 
1372  for ( int catIdx = 0; catIdx < mCategories.count(); ++catIdx )
1373  {
1374  const QVariant value = mCategories.at( catIdx ).value();
1375  const QString val = value.toString().trimmed();
1376  std::unique_ptr< QgsSymbol > symbol( style->symbol( val ) );
1377  // case-sensitive match
1378  if ( symbol && symbol->type() == type )
1379  {
1380  matched++;
1381  unmatchedSymbols.removeAll( val );
1382  updateCategorySymbol( catIdx, symbol.release() );
1383  continue;
1384  }
1385 
1386  if ( !caseSensitive || useTolerantMatch )
1387  {
1388  QString testVal = val;
1389  if ( useTolerantMatch )
1390  testVal.replace( tolerantMatchRe, QString() );
1391 
1392  bool foundMatch = false;
1393  for ( const QString &name : allSymbolNames )
1394  {
1395  QString testName = name.trimmed();
1396  if ( useTolerantMatch )
1397  testName.replace( tolerantMatchRe, QString() );
1398 
1399  if ( testName == testVal || ( !caseSensitive && testName.trimmed().compare( testVal, Qt::CaseInsensitive ) == 0 ) )
1400  {
1401  // found a case-insensitive match
1402  std::unique_ptr< QgsSymbol > symbol( style->symbol( name ) );
1403  if ( symbol && symbol->type() == type )
1404  {
1405  matched++;
1406  unmatchedSymbols.removeAll( name );
1407  updateCategorySymbol( catIdx, symbol.release() );
1408  foundMatch = true;
1409  break;
1410  }
1411  }
1412  }
1413  if ( foundMatch )
1414  continue;
1415  }
1416 
1417  unmatchedCategories << value;
1418  }
1419 
1420  return matched;
1421 }
1422 
1423 QgsCategoryList QgsCategorizedSymbolRenderer::createCategories( const QList<QVariant> &values, const QgsSymbol *symbol, QgsVectorLayer *layer, const QString &attributeName )
1424 {
1425  QgsCategoryList cats;
1426  QVariantList vals = values;
1427  // sort the categories first
1428  QgsSymbolLayerUtils::sortVariantList( vals, Qt::AscendingOrder );
1429 
1430  if ( layer && !attributeName.isNull() )
1431  {
1432  const QgsFields fields = layer->fields();
1433  for ( const QVariant &value : vals )
1434  {
1435  QgsSymbol *newSymbol = symbol->clone();
1436  if ( !value.isNull() )
1437  {
1438  const int fieldIdx = fields.lookupField( attributeName );
1439  QString categoryName = displayString( value );
1440  if ( fieldIdx != -1 )
1441  {
1442  const QgsField field = fields.at( fieldIdx );
1445  categoryName = formatter->representValue( layer, fieldIdx, setup.config(), QVariant(), value );
1446  }
1447  cats.append( QgsRendererCategory( value, newSymbol, categoryName, true ) );
1448  }
1449  }
1450  }
1451 
1452  // add null (default) value
1453  QgsSymbol *newSymbol = symbol->clone();
1454  cats.append( QgsRendererCategory( QVariant(), newSymbol, QString(), true ) );
1455 
1456  return cats;
1457 }
1458 
QgsCategorizedSymbolRenderer::dump
QString dump() const override
Returns debug information about this renderer.
Definition: qgscategorizedsymbolrenderer.cpp:493
QgsGraduatedSymbolRenderer::sourceColorRamp
QgsColorRamp * sourceColorRamp()
Returns the source color ramp, from which each classes' color is derived.
Definition: qgsgraduatedsymbolrenderer.cpp:839
QgsFeatureRequest::NoGeometry
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
Definition: qgsfeaturerequest.h:115
QgsCategorizedSymbolRenderer::save
QDomElement save(QDomDocument &doc, const QgsReadWriteContext &context) override
Stores renderer properties to an XML element.
Definition: qgscategorizedsymbolrenderer.cpp:809
QgsVectorLayer::getFeatures
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
Definition: qgsvectorlayer.cpp:1052
QgsFeatureRenderer::copyRendererData
void copyRendererData(QgsFeatureRenderer *destRenderer) const
Clones generic renderer data to another renderer.
Definition: qgsrenderer.cpp:52
QgsExpressionContext
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Definition: qgsexpressioncontext.h:406
QgsProperty::isActive
bool isActive() const
Returns whether the property is currently active.
Definition: qgsproperty.cpp:291
formatter
Definition: qgsbasicnumericformat.cpp:24
QgsColorRamp
Abstract base class for color ramps.
Definition: qgscolorramp.h:29
qgsexpressioncontextutils.h
QgsExpressionContext::appendScopes
void appendScopes(const QList< QgsExpressionContextScope * > &scopes)
Appends a list of scopes to the end of the context.
Definition: qgsexpressioncontext.cpp:499
qgscolorrampimpl.h
QgsField::isNumeric
bool isNumeric
Definition: qgsfield.h:54
QgsCategorizedSymbolRenderer::symbolForFeature
QgsSymbol * symbolForFeature(const QgsFeature &feature, QgsRenderContext &context) const override
To be overridden.
Definition: qgscategorizedsymbolrenderer.cpp:247
QgsRendererCategory::setLabel
void setLabel(const QString &label)
Sets the label for this category, which is used to represent the category within legends and the laye...
Definition: qgscategorizedsymbolrenderer.cpp:110
QgsSymbolLayerUtils::loadSymbols
static QgsSymbolMap loadSymbols(QDomElement &element, const QgsReadWriteContext &context)
Reads a collection of symbols from XML and returns them in a map. Caller is responsible for deleting ...
Definition: qgssymbollayerutils.cpp:3189
QgsProperty
A store for object properties.
Definition: qgsproperty.h:230
QgsGraduatedSymbolRenderer::sourceSymbol
QgsSymbol * sourceSymbol()
Returns the renderer's source symbol, which is the base symbol used for the each classes' symbol befo...
Definition: qgsgraduatedsymbolrenderer.cpp:824
QgsRenderContext::expressionContext
QgsExpressionContext & expressionContext()
Gets the expression context.
Definition: qgsrendercontext.h:625
QgsReadWriteContext
The class is used as a container of context for various read/write operations on other objects.
Definition: qgsreadwritecontext.h:34
qgscategorizedsymbolrenderer.h
QgsGraduatedSymbolRenderer::classAttribute
QString classAttribute() const
Returns the attribute name (or expression) used for the classification.
Definition: qgsgraduatedsymbolrenderer.h:61
QgsEditorWidgetSetup
Holder for the widget type and its configuration for a field.
Definition: qgseditorwidgetsetup.h:28
QgsExpression::referencedColumns
QSet< QString > referencedColumns() const
Gets list of columns referenced by the expression.
Definition: qgsexpression.cpp:221
QgsCategorizedSymbolRenderer::dataDefinedSizeLegend
QgsDataDefinedSizeLegend * dataDefinedSizeLegend() const
Returns configuration of appearance of legend when using data-defined size for marker symbols.
Definition: qgscategorizedsymbolrenderer.cpp:1356
QgsCategorizedSymbolRenderer::clone
QgsCategorizedSymbolRenderer * clone() const override
Create a deep copy of this renderer.
Definition: qgscategorizedsymbolrenderer.cpp:501
QgsDebugMsgLevel
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
QgsStyleSymbolEntity
A symbol entity for QgsStyle databases.
Definition: qgsstyle.h:1341
QgsCategorizedSymbolRenderer::originalSymbolForFeature
QgsSymbol * originalSymbolForFeature(const QgsFeature &feature, QgsRenderContext &context) const override
Returns symbol for feature.
Definition: qgscategorizedsymbolrenderer.cpp:270
QgsCategorizedSymbolRenderer::updateSymbols
void updateSymbols(QgsSymbol *sym)
Update all the symbols but leave categories and colors.
Definition: qgscategorizedsymbolrenderer.cpp:1234
labelLessThan
bool labelLessThan(const QgsRendererCategory &c1, const QgsRendererCategory &c2)
Definition: qgscategorizedsymbolrenderer.cpp:398
QgsCategorizedSymbolRenderer::mSourceColorRamp
std::unique_ptr< QgsColorRamp > mSourceColorRamp
Definition: qgscategorizedsymbolrenderer.h:473
QgsCategorizedSymbolRenderer::sortByLabel
void sortByLabel(Qt::SortOrder order=Qt::AscendingOrder)
Sorts the existing categories by their label.
Definition: qgscategorizedsymbolrenderer.cpp:408
qgsVariantLessThan
bool qgsVariantLessThan(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether the first is less than the second.
Definition: qgis.cpp:119
QgsMarkerSymbol::dataDefinedSize
QgsProperty dataDefinedSize() const
Returns data defined size for whole symbol (including all symbol layers).
Definition: qgsmarkersymbol.cpp:343
QgsCategorizedSymbolRenderer::rebuildHash
void rebuildHash()
Definition: qgscategorizedsymbolrenderer.cpp:190
QgsFeatureRenderer::convertSymbolSizeScale
static void convertSymbolSizeScale(QgsSymbol *symbol, Qgis::ScaleMethod method, const QString &field)
Definition: qgsrenderer.cpp:494
QgsSymbolMap
QMap< QString, QgsSymbol * > QgsSymbolMap
Definition: qgsrenderer.h:45
QgsCategorizedSymbolRenderer::updateCategorySymbol
bool updateCategorySymbol(int catIndex, QgsSymbol *symbol)
Changes the symbol for the category with the specified index.
Definition: qgscategorizedsymbolrenderer.cpp:322
QgsStyleColorRampEntity
A color ramp entity for QgsStyle databases.
Definition: qgsstyle.h:1373
QgsCategorizedSymbolRenderer::categories
const QgsCategoryList & categories() const
Returns a list of all categories recognized by the renderer.
Definition: qgscategorizedsymbolrenderer.h:204
qgssymbollayerutils.h
QgsFields
Container of fields for a vector layer.
Definition: qgsfields.h:44
QgsEditorWidgetSetup::config
QVariantMap config() const
Definition: qgseditorwidgetsetup.h:64
QgsCategorizedSymbolRenderer::setLegendSymbolItem
void setLegendSymbolItem(const QString &key, QgsSymbol *symbol) override
Sets the symbol to be used for a legend symbol item.
Definition: qgscategorizedsymbolrenderer.cpp:1262
qgsfeature.h
QgsFeatureRenderer::convertSymbolRotation
static void convertSymbolRotation(QgsSymbol *symbol, const QString &field)
Definition: qgsrenderer.cpp:516
QgsFeatureRenderer::type
QString type() const
Definition: qgsrenderer.h:142
QgsRendererCategory::mLabel
QString mLabel
Definition: qgscategorizedsymbolrenderer.h:152
qgsfieldformatterregistry.h
QgsDataDefinedSizeLegend
Object that keeps configuration of appearance of marker symbol's data-defined size in legend.
Definition: qgsdatadefinedsizelegend.h:42
QgsRendererCategory
Represents an individual category (class) from a QgsCategorizedSymbolRenderer.
Definition: qgscategorizedsymbolrenderer.h:35
QgsRenderContext
Contains information about the context of a rendering operation.
Definition: qgsrendercontext.h:59
QgsStyleEntityVisitorInterface
An interface for classes which can visit style entity (e.g. symbol) nodes (using the visitor pattern)...
Definition: qgsstyleentityvisitor.h:33
QgsRendererCategory::mValue
QVariant mValue
Definition: qgscategorizedsymbolrenderer.h:150
QgsExpressionContextUtils::globalProjectLayerScopes
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Definition: qgsexpressioncontextutils.cpp:377
qgspainteffectregistry.h
QgsCategorizedSymbolRenderer::mDataDefinedSizeLegend
std::unique_ptr< QgsDataDefinedSizeLegend > mDataDefinedSizeLegend
Definition: qgscategorizedsymbolrenderer.h:476
QgsCategorizedSymbolRenderer::toSld
void toSld(QDomDocument &doc, QDomElement &element, const QVariantMap &props=QVariantMap()) const override
used from subclasses to create SLD Rule elements following SLD v1.1 specs
Definition: qgscategorizedsymbolrenderer.cpp:516
QgsPointDistanceRenderer::embeddedRenderer
const QgsFeatureRenderer * embeddedRenderer() const override
Returns the current embedded renderer (subrenderer) for this feature renderer.
Definition: qgspointdistancerenderer.cpp:173
QgsSymbol
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:92
field
const QgsField & field
Definition: qgsfield.h:463
QgsDebugMsg
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
qgspainteffect.h
QgsCategorizedSymbolRenderer::startRender
void startRender(QgsRenderContext &context, const QgsFields &fields) override
Must be called when a new render cycle is started.
Definition: qgscategorizedsymbolrenderer.cpp:420
QgsCategorizedSymbolRenderer::matchToSymbols
int matchToSymbols(QgsStyle *style, Qgis::SymbolType type, QVariantList &unmatchedCategories, QStringList &unmatchedSymbols, bool caseSensitive=true, bool useTolerantMatch=false)
Replaces category symbols with the symbols from a style that have a matching name and symbol type.
Definition: qgscategorizedsymbolrenderer.cpp:1361
QgsRendererCategory::mRender
bool mRender
Definition: qgscategorizedsymbolrenderer.h:153
QgsCategorizedSymbolRenderer::legendSymbolItemChecked
bool legendSymbolItemChecked(const QString &key) override
items of symbology items in legend is checked
Definition: qgscategorizedsymbolrenderer.cpp:1252
QgsCategorizedSymbolRenderer::mAttrNum
int mAttrNum
attribute index (derived from attribute name in startRender)
Definition: qgscategorizedsymbolrenderer.h:479
QgsCategorizedSymbolRenderer::displayString
static QString displayString(const QVariant &value, int precision=-1)
Returns a localized representation of value with the given precision, if precision is -1 then precisi...
Definition: qgscategorizedsymbolrenderer.cpp:927
QgsCategorizedSymbolRenderer::setDataDefinedSizeLegend
void setDataDefinedSizeLegend(QgsDataDefinedSizeLegend *settings)
Configures appearance of legend when renderer is configured to use data-defined size for marker symbo...
Definition: qgscategorizedsymbolrenderer.cpp:1351
QgsStyleEntityVisitorInterface::StyleLeaf
Contains information relating to the style entity currently being visited.
Definition: qgsstyleentityvisitor.h:60
QgsStyle::symbol
QgsSymbol * symbol(const QString &name)
Returns a NEW copy of symbol.
Definition: qgsstyle.cpp:291
QgsExpression::quoteFieldExpression
static QString quoteFieldExpression(const QString &expression, const QgsVectorLayer *layer)
Validate if the expression is a field in the layer and ensure it is quoted.
Definition: qgsexpression.cpp:1385
QgsFeatureRenderer::stopRender
virtual void stopRender(QgsRenderContext &context)
Must be called when a render cycle has finished, to allow the renderer to clean up.
Definition: qgsrenderer.cpp:110
QgsCategorizedSymbolRenderer::stopRender
void stopRender(QgsRenderContext &context) override
Must be called when a render cycle has finished, to allow the renderer to clean up.
Definition: qgscategorizedsymbolrenderer.cpp:443
QgsCategorizedSymbolRenderer::legendSymbolItemsCheckable
bool legendSymbolItemsCheckable() const override
items of symbology items in legend should be checkable
Definition: qgscategorizedsymbolrenderer.cpp:1247
QgsRandomColorRamp
Totally random color ramp. Returns colors generated at random, but constrained to some hardcoded satu...
Definition: qgscolorrampimpl.h:492
qgsVariantGreaterThan
bool qgsVariantGreaterThan(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether the first is greater than the second.
Definition: qgis.cpp:187
qgsapplication.h
QgsExpression::quotedValue
static QString quotedValue(const QVariant &value)
Returns a string representation of a literal value, including appropriate quotations where required.
Definition: qgsexpression.cpp:82
QgsSymbolLayerUtils::sortVariantList
static void sortVariantList(QList< QVariant > &list, Qt::SortOrder order)
Sorts the passed list in requested order.
Definition: qgssymbollayerutils.cpp:4160
QgsFeature::embeddedSymbol
const QgsSymbol * embeddedSymbol() const
Returns the feature's embedded symbology, or nullptr if the feature has no embedded symbol.
Definition: qgsfeature.cpp:313
QgsCategorizedSymbolRenderer::skipRender
Q_DECL_DEPRECATED QgsSymbol * skipRender()
Definition: qgscategorizedsymbolrenderer.cpp:212
QgsVectorLayer::fields
QgsFields fields() const FINAL
Returns the list of fields of this layer.
Definition: qgsvectorlayer.cpp:3436
QgsCategorizedSymbolRenderer::symbolForValue
Q_DECL_DEPRECATED QgsSymbol * symbolForValue(const QVariant &value) const
Returns the matching symbol corresponding to an attribute value.
Definition: qgscategorizedsymbolrenderer.cpp:217
QgsFeature::id
QgsFeatureId id
Definition: qgsfeature.h:68
QgsEditorWidgetSetup::type
QString type() const
Definition: qgseditorwidgetsetup.h:59
QgsLegendSymbolItem
The class stores information about one class/rule of a vector layer renderer in a unified way that ca...
Definition: qgslegendsymbolitem.h:36
QgsFeatureRequest
This class wraps a request for features to a vector layer (or directly its vector data provider).
Definition: qgsfeaturerequest.h:83
precision
int precision
Definition: qgswfsgetfeature.cpp:103
QgsDataDefinedSizeLegend::legendSymbolList
QgsLegendSymbolList legendSymbolList() const
Generates legend symbol items according to the configuration.
Definition: qgsdatadefinedsizelegend.cpp:122
QgsCategorizedSymbolRenderer::~QgsCategorizedSymbolRenderer
~QgsCategorizedSymbolRenderer() override
QgsCategorizedSymbolRenderer::symbols
QgsSymbolList symbols(QgsRenderContext &context) const override
Returns list of symbols used by the renderer.
Definition: qgscategorizedsymbolrenderer.cpp:628
QgsRendererCategory::operator=
QgsRendererCategory & operator=(QgsRendererCategory cat)
Definition: qgscategorizedsymbolrenderer.cpp:65
QgsCategorizedSymbolRenderer::updateCategoryValue
bool updateCategoryValue(int catIndex, const QVariant &value)
Changes the value for the category with the specified index.
Definition: qgscategorizedsymbolrenderer.cpp:314
valueGreaterThan
bool valueGreaterThan(const QgsRendererCategory &c1, const QgsRendererCategory &c2)
Definition: qgscategorizedsymbolrenderer.cpp:381
Qgis::SymbolType
SymbolType
Symbol types.
Definition: qgis.h:205
QgsCategorizedSymbolRenderer::categoryIndexForValue
int categoryIndexForValue(const QVariant &val)
Returns the index for the category with the specified value (or -1 if not found).
Definition: qgscategorizedsymbolrenderer.cpp:288
QgsCategorizedSymbolRenderer::QgsCategorizedSymbolRenderer
QgsCategorizedSymbolRenderer(const QString &attrName=QString(), const QgsCategoryList &categories=QgsCategoryList())
Constructor for QgsCategorizedSymbolRenderer.
Definition: qgscategorizedsymbolrenderer.cpp:171
QgsCategorizedSymbolRenderer::moveCategory
void moveCategory(int from, int to)
Moves an existing category at index position from to index position to.
Definition: qgscategorizedsymbolrenderer.cpp:371
QgsSymbolLayerUtils::applyScaleDependency
static void applyScaleDependency(QDomDocument &doc, QDomElement &ruleElem, QVariantMap &props)
Checks if the properties contain scaleMinDenom and scaleMaxDenom, if available, they are added into t...
Definition: qgssymbollayerutils.cpp:4837
QgsCategorizedSymbolRenderer::filterNeedsGeometry
bool filterNeedsGeometry() const override
Returns true if this renderer requires the geometry to apply the filter.
Definition: qgscategorizedsymbolrenderer.cpp:480
QgsSymbolLayerUtils::decodeScaleMethod
static Qgis::ScaleMethod decodeScaleMethod(const QString &str)
Decodes a symbol scale method from a string.
Definition: qgssymbollayerutils.cpp:838
QgsCategoryList
QList< QgsRendererCategory > QgsCategoryList
Definition: qgscategorizedsymbolrenderer.h:158
QgsApplication::nullRepresentation
static QString nullRepresentation()
This string is used to represent the value NULL throughout QGIS.
Definition: qgsapplication.cpp:2018
QgsRendererCategory::setSymbol
void setSymbol(QgsSymbol *s)
Sets the symbol which will be used to render this category.
Definition: qgscategorizedsymbolrenderer.cpp:105
qgscolorramp.h
QgsSymbolList
QList< QgsSymbol * > QgsSymbolList
Definition: qgsrenderer.h:44
QgsMarkerSymbol
A marker symbol type, for rendering Point and MultiPoint geometries.
Definition: qgsmarkersymbol.h:30
QgsCategorizedSymbolRenderer::updateCategoryRenderState
bool updateCategoryRenderState(int catIndex, bool render)
Changes the render state for the category with the specified index.
Definition: qgscategorizedsymbolrenderer.cpp:338
QgsRandomColorRamp::setTotalColorCount
virtual void setTotalColorCount(int colorCount)
Sets the desired total number of unique colors for the resultant ramp.
Definition: qgscolorrampimpl.cpp:771
QgsCategorizedSymbolRenderer::filter
QString filter(const QgsFields &fields=QgsFields()) override
If a renderer does not require all the features this method may be overridden and return an expressio...
Definition: qgscategorizedsymbolrenderer.cpp:528
QgsFeatureRenderer::saveRendererData
void saveRendererData(QDomDocument &doc, QDomElement &element, const QgsReadWriteContext &context)
Saves generic renderer data into the specified element.
Definition: qgsrenderer.cpp:204
QgsFeatureRenderer::clone
virtual QgsFeatureRenderer * clone() const =0
Create a deep copy of this renderer.
QgsRendererCategory::setRenderState
void setRenderState(bool render)
Sets whether the category is currently enabled and should be rendered.
Definition: qgscategorizedsymbolrenderer.cpp:115
QgsCategorizedSymbolRenderer::accept
bool accept(QgsStyleEntityVisitorInterface *visitor) const override
Accepts the specified symbology visitor, causing it to visit all symbols associated with the renderer...
Definition: qgscategorizedsymbolrenderer.cpp:640
QgsGraduatedSymbolRenderer
Definition: qgsgraduatedsymbolrenderer.h:35
QgsRendererCategory::symbol
QgsSymbol * symbol() const
Returns the symbol which will be used to render this category.
Definition: qgscategorizedsymbolrenderer.cpp:85
QgsSymbolLayerUtils::saveColorRamp
static QDomElement saveColorRamp(const QString &name, QgsColorRamp *ramp, QDomDocument &doc)
Encodes a color ramp's settings to an XML element.
Definition: qgssymbollayerutils.cpp:3355
QgsCategorizedSymbolRenderer::create
static QgsFeatureRenderer * create(QDomElement &element, const QgsReadWriteContext &context)
Creates a categorized renderer from an XML element.
Definition: qgscategorizedsymbolrenderer.cpp:659
RENDERER_TAG_NAME
#define RENDERER_TAG_NAME
Definition: qgsrenderer.h:50
QgsPointDistanceRenderer
An abstract base class for distance based point renderers (e.g., clusterer and displacement renderers...
Definition: qgspointdistancerenderer.h:41
QgsCategorizedSymbolRenderer::legendSymbolItems
QgsLegendSymbolList legendSymbolItems() const override
Returns a list of symbology items for the legend.
Definition: qgscategorizedsymbolrenderer.cpp:1047
QgsMergedFeatureRenderer::embeddedRenderer
const QgsFeatureRenderer * embeddedRenderer() const override
Returns the current embedded renderer (subrenderer) for this feature renderer.
Definition: qgsmergedfeaturerenderer.cpp:53
QgsCategorizedSymbolRenderer::sourceColorRamp
QgsColorRamp * sourceColorRamp()
Returns the source color ramp, from which each categories' color is derived.
Definition: qgscategorizedsymbolrenderer.cpp:1197
QgsCategorizedSymbolRenderer::mSourceSymbol
std::unique_ptr< QgsSymbol > mSourceSymbol
Definition: qgscategorizedsymbolrenderer.h:472
qgssymbollayer.h
QgsCategorizedSymbolRenderer::mExpression
std::unique_ptr< QgsExpression > mExpression
Definition: qgscategorizedsymbolrenderer.h:474
QgsCategorizedSymbolRenderer::mSymbolHash
QHash< QString, QgsSymbol * > mSymbolHash
hashtable for faster access to symbols
Definition: qgscategorizedsymbolrenderer.h:482
QgsRendererCategory::QgsRendererCategory
QgsRendererCategory()=default
Constructor for QgsRendererCategory.
QgsCategorizedSymbolRenderer::deleteCategory
bool deleteCategory(int catIndex)
Deletes the category with the specified index from the renderer.
Definition: qgscategorizedsymbolrenderer.cpp:357
QgsCategorizedSymbolRenderer::updateCategoryLabel
bool updateCategoryLabel(int catIndex, const QString &label)
Changes the label for the category with the specified index.
Definition: qgscategorizedsymbolrenderer.cpp:330
QgsRendererCategory::swap
void swap(QgsRendererCategory &other)
Definition: qgscategorizedsymbolrenderer.cpp:73
QgsCategorizedSymbolRenderer::sortByValue
void sortByValue(Qt::SortOrder order=Qt::AscendingOrder)
Sorts the existing categories by their value.
Definition: qgscategorizedsymbolrenderer.cpp:386
QgsCategorizedSymbolRenderer::usedAttributes
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns a list of attributes required by this renderer.
Definition: qgscategorizedsymbolrenderer.cpp:454
QgsGraduatedSymbolRenderer::setSourceSymbol
void setSourceSymbol(QgsSymbol *sym)
Sets the source symbol for the renderer, which is the base symbol used for the each classes' symbol b...
Definition: qgsgraduatedsymbolrenderer.cpp:834
QgsFeatureRequest::setNoAttributes
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
Definition: qgsfeaturerequest.cpp:235
QgsCategorizedSymbolRenderer::mAttrName
QString mAttrName
Definition: qgscategorizedsymbolrenderer.h:470
QgsExpression::prepare
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
Definition: qgsexpression.cpp:327
QgsFeature::attributes
QgsAttributes attributes
Definition: qgsfeature.h:69
QgsColorRamp::clone
virtual QgsColorRamp * clone() const =0
Creates a clone of the color ramp.
QgsApplication::fieldFormatterRegistry
static QgsFieldFormatterRegistry * fieldFormatterRegistry()
Gets the registry of available field formatters.
Definition: qgsapplication.cpp:2480
qgsstyle.h
QgsSymbolLayerUtils::loadColorRamp
static QgsColorRamp * loadColorRamp(QDomElement &element)
Creates a color ramp from the settings encoded in an XML element.
Definition: qgssymbollayerutils.cpp:3330
QgsCategorizedSymbolRenderer::categoryIndexForLabel
int categoryIndexForLabel(const QString &val)
Returns the index of the category with the specified label (or -1 if the label was not found,...
Definition: qgscategorizedsymbolrenderer.cpp:298
valueLessThan
bool valueLessThan(const QgsRendererCategory &c1, const QgsRendererCategory &c2)
Definition: qgscategorizedsymbolrenderer.cpp:377
QgsStyle::symbolNames
QStringList symbolNames() const
Returns a list of names of symbols.
Definition: qgsstyle.cpp:307
qgsvectorlayer.h
QgsCategorizedSymbolRenderer::legendKeyToExpression
QString legendKeyToExpression(const QString &key, QgsVectorLayer *layer, bool &ok) const override
Attempts to convert the specified legend rule key to a QGIS expression matching the features displaye...
Definition: qgscategorizedsymbolrenderer.cpp:1135
QgsDataDefinedSizeLegend::updateFromSymbolAndProperty
void updateFromSymbolAndProperty(const QgsMarkerSymbol *symbol, const QgsProperty &ddSize)
Updates the list of classes, source symbol and title label from given symbol and property.
Definition: qgsdatadefinedsizelegend.cpp:99
QgsCategorizedSymbolRenderer::mCounting
bool mCounting
Definition: qgscategorizedsymbolrenderer.h:483
QgsCategorizedSymbolRenderer::setSourceSymbol
void setSourceSymbol(QgsSymbol *sym)
Sets the source symbol for the renderer, which is the base symbol used for the each categories' symbo...
Definition: qgscategorizedsymbolrenderer.cpp:1192
QgsRendererCategory::toSld
void toSld(QDomDocument &doc, QDomElement &element, QVariantMap props) const
Converts the category to a matching SLD rule, within the specified DOM document and element.
Definition: qgscategorizedsymbolrenderer.cpp:125
QgsSymbol::clone
virtual QgsSymbol * clone() const =0
Returns a deep copy of this symbol.
QgsRendererCategory::label
QString label() const
Returns the label for this category, which is used to represent the category within legends and the l...
Definition: qgscategorizedsymbolrenderer.cpp:90
QgsFeatureRenderer
Definition: qgsrenderer.h:101
QgsRendererCategory::renderState
bool renderState() const
Returns true if the category is currently enabled and should be rendered.
Definition: qgscategorizedsymbolrenderer.cpp:95
QgsFeatureIterator::nextFeature
bool nextFeature(QgsFeature &f)
Definition: qgsfeatureiterator.h:399
QgsCategorizedSymbolRenderer::createCategories
static QgsCategoryList createCategories(const QVariantList &values, const QgsSymbol *symbol, QgsVectorLayer *layer=nullptr, const QString &fieldName=QString())
Create categories for a list of values.
Definition: qgscategorizedsymbolrenderer.cpp:1423
QgsStyle
Definition: qgsstyle.h:159
QgsEmbeddedSymbolRenderer
A vector feature renderer which uses embedded feature symbology to render per-feature symbols.
Definition: qgsembeddedsymbolrenderer.h:35
QgsCategorizedSymbolRenderer::updateColorRamp
void updateColorRamp(QgsColorRamp *ramp)
Update the color ramp used and all symbols colors.
Definition: qgscategorizedsymbolrenderer.cpp:1212
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:391
QgsSymbolLayerUtils::saveSymbols
static QDomElement saveSymbols(QgsSymbolMap &symbols, const QString &tagName, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a collection of symbols to XML with specified tagName for the top-level element.
Definition: qgssymbollayerutils.cpp:3267
QgsRendererCategory::dump
QString dump() const
Returns a string representing the categories settings, used for debugging purposes only.
Definition: qgscategorizedsymbolrenderer.cpp:120
qgsmarkersymbol.h
QgsSymbolLayerUtils::clearSymbolMap
static void clearSymbolMap(QgsSymbolMap &symbols)
Definition: qgssymbollayerutils.cpp:3281
QgsSymbol::usedAttributes
QSet< QString > usedAttributes(const QgsRenderContext &context) const
Returns a list of attributes required to render this feature.
Definition: qgssymbol.cpp:1151
QgsFieldFormatterRegistry::fieldFormatter
QgsFieldFormatter * fieldFormatter(const QString &id) const
Gets a field formatter by its id.
Definition: qgsfieldformatterregistry.cpp:76
qgspointdisplacementrenderer.h
qgsproperty.h
QgsRendererCategory::~QgsRendererCategory
~QgsRendererCategory()
labelGreaterThan
bool labelGreaterThan(const QgsRendererCategory &c1, const QgsRendererCategory &c2)
Definition: qgscategorizedsymbolrenderer.cpp:403
QgsStyleEntityVisitorInterface::visit
virtual bool visit(const QgsStyleEntityVisitorInterface::StyleLeaf &entity)
Called when the visitor will visit a style entity.
Definition: qgsstyleentityvisitor.h:153
QgsExpression::needsGeometry
bool needsGeometry() const
Returns true if the expression uses feature geometry for some computation.
Definition: qgsexpression.cpp:270
QgsCategorizedSymbolRenderer::mCategories
QgsCategoryList mCategories
Definition: qgscategorizedsymbolrenderer.h:471
qgsembeddedsymbolrenderer.h
QgsAttributes
A vector of attributes. Mostly equal to QVector<QVariant>.
Definition: qgsattributes.h:57
QgsRendererCategory::setValue
void setValue(const QVariant &value)
Sets the value corresponding to this category.
Definition: qgscategorizedsymbolrenderer.cpp:100
qgsinvertedpolygonrenderer.h
QgsCategorizedSymbolRenderer
Definition: qgscategorizedsymbolrenderer.h:164
QgsDataDefinedSizeLegend::readXml
static QgsDataDefinedSizeLegend * readXml(const QDomElement &elem, const QgsReadWriteContext &context) SIP_FACTORY
Creates instance from given element and returns it (caller takes ownership). Returns nullptr on error...
Definition: qgsdatadefinedsizelegend.cpp:364
QgsFeature
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:55
QgsCategorizedSymbolRenderer::deleteAllCategories
void deleteAllCategories()
Deletes all existing categories from the renderer.
Definition: qgscategorizedsymbolrenderer.cpp:366
qgsdatadefinedsizelegend.h
QgsFeatureRequest::EmbeddedSymbols
@ EmbeddedSymbols
Retrieve any embedded feature symbology (since QGIS 3.20)
Definition: qgsfeaturerequest.h:119
QgsExpression::hasParserError
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
Definition: qgsexpression.cpp:206
qgslogger.h
QgsFields::lookupField
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
Definition: qgsfields.cpp:349
QgsRenderContext::rendererScale
double rendererScale() const
Returns the renderer map scale.
Definition: qgsrendercontext.h:344
QgsField::editorWidgetSetup
QgsEditorWidgetSetup editorWidgetSetup() const
Gets the editor widget setup for the field.
Definition: qgsfield.cpp:602
QgsFields::at
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
Definition: qgsfields.cpp:163
QgsExpression
Class for parsing and evaluation of expressions (formerly called "search strings")....
Definition: qgsexpression.h:102
QgsCategorizedSymbolRenderer::convertFromRenderer
static QgsCategorizedSymbolRenderer * convertFromRenderer(const QgsFeatureRenderer *renderer, QgsVectorLayer *layer=nullptr)
Creates a new QgsCategorizedSymbolRenderer from an existing renderer.
Definition: qgscategorizedsymbolrenderer.cpp:1280
qgsgraduatedsymbolrenderer.h
QgsLegendSymbolList
QList< QgsLegendSymbolItem > QgsLegendSymbolList
Definition: qgslegendsymbolitem.h:144
QgsFeatureRenderer::startRender
virtual void startRender(QgsRenderContext &context, const QgsFields &fields)
Must be called when a new render cycle is started.
Definition: qgsrenderer.cpp:96
QgsFeatureIterator
Wrapper for iterator of features from vector data provider or vector layer.
Definition: qgsfeatureiterator.h:289
QgsSymbol::setColor
void setColor(const QColor &color) const
Sets the color for the symbol.
Definition: qgssymbol.cpp:867
QgsFieldFormatter
A field formatter helps to handle and display values for a field.
Definition: qgsfieldformatter.h:72
QgsFeatureRequest::setFlags
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Sets flags that affect how features will be fetched.
Definition: qgsfeaturerequest.cpp:222
QgsFeatureRenderer::embeddedRenderer
virtual const QgsFeatureRenderer * embeddedRenderer() const
Returns the current embedded renderer (subrenderer) for this feature renderer.
Definition: qgsrenderer.cpp:484
qgssymbol.h
QgsRendererCategory::value
QVariant value() const
Returns the value corresponding to this category.
Definition: qgscategorizedsymbolrenderer.cpp:80
QgsCategorizedSymbolRenderer::setSourceColorRamp
void setSourceColorRamp(QgsColorRamp *ramp)
Sets the source color ramp.
Definition: qgscategorizedsymbolrenderer.cpp:1207
Qgis::SymbolType::Marker
@ Marker
Marker symbol.
QgsField::type
QVariant::Type type
Definition: qgsfield.h:58
QgsCategorizedSymbolRenderer::addCategory
void addCategory(const QgsRendererCategory &category)
Adds a new category to the renderer.
Definition: qgscategorizedsymbolrenderer.cpp:346
QgsRendererCategory::mSymbol
std::unique_ptr< QgsSymbol > mSymbol
Definition: qgscategorizedsymbolrenderer.h:151
qgsfieldformatter.h
qgsstyleentityvisitor.h
QgsCategorizedSymbolRenderer::checkLegendSymbolItem
void checkLegendSymbolItem(const QString &key, bool state=true) override
item in symbology was checked
Definition: qgscategorizedsymbolrenderer.cpp:1272
QgsCategorizedSymbolRenderer::sourceSymbol
QgsSymbol * sourceSymbol()
Returns the renderer's source symbol, which is the base symbol used for the each categories' symbol b...
Definition: qgscategorizedsymbolrenderer.cpp:1182
QgsCategorizedSymbolRenderer::legendKeysForFeature
QSet< QString > legendKeysForFeature(const QgsFeature &feature, QgsRenderContext &context) const override
Returns legend keys matching a specified feature.
Definition: qgscategorizedsymbolrenderer.cpp:1087
QgsSymbolLayerUtils::createFunctionElement
static bool createFunctionElement(QDomDocument &doc, QDomElement &element, const QString &function)
Definition: qgssymbollayerutils.cpp:2982
QgsInvertedPolygonRenderer
QgsInvertedPolygonRenderer is a polygon-only feature renderer used to display features inverted,...
Definition: qgsinvertedpolygonrenderer.h:42
QgsField
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:50