QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
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"
26 #include "qgspainteffect.h"
27 #include "qgspainteffectregistry.h"
28 #include "qgssymbollayer.h"
29 #include "qgsfeature.h"
30 #include "qgsvectorlayer.h"
31 #include "qgslogger.h"
32 #include "qgsproperty.h"
33 #include "qgsstyle.h"
34 #include "qgsfieldformatter.h"
36 #include "qgsapplication.h"
38 #include "qgsstyleentityvisitor.h"
39 
40 #include <QDomDocument>
41 #include <QDomElement>
42 #include <QSettings> // for legend
43 
44 QgsRendererCategory::QgsRendererCategory( const QVariant &value, QgsSymbol *symbol, const QString &label, bool render )
45  : mValue( value )
46  , mSymbol( symbol )
47  , mLabel( label )
48  , mRender( render )
49 {
50 }
51 
53  : mValue( cat.mValue )
54  , mSymbol( cat.mSymbol ? cat.mSymbol->clone() : nullptr )
55  , mLabel( cat.mLabel )
56  , mRender( cat.mRender )
57 {
58 }
59 
60 // copy+swap idion, the copy is done through the 'pass by value'
62 {
63  swap( cat );
64  return *this;
65 }
66 
68 {
69  std::swap( mValue, cat.mValue );
70  std::swap( mSymbol, cat.mSymbol );
71  std::swap( mLabel, cat.mLabel );
72 }
73 
75 {
76  return mValue;
77 }
78 
80 {
81  return mSymbol.get();
82 }
83 
85 {
86  return mLabel;
87 }
88 
90 {
91  return mRender;
92 }
93 
94 void QgsRendererCategory::setValue( const QVariant &value )
95 {
96  mValue = value;
97 }
98 
100 {
101  if ( mSymbol.get() != s ) mSymbol.reset( s );
102 }
103 
104 void QgsRendererCategory::setLabel( const QString &label )
105 {
106  mLabel = label;
107 }
108 
110 {
111  mRender = render;
112 }
113 
115 {
116  return QStringLiteral( "%1::%2::%3:%4\n" ).arg( mValue.toString(), mLabel, mSymbol->dump() ).arg( mRender );
117 }
118 
119 void QgsRendererCategory::toSld( QDomDocument &doc, QDomElement &element, QgsStringMap props ) const
120 {
121  if ( !mSymbol.get() || props.value( QStringLiteral( "attribute" ), QString() ).isEmpty() )
122  return;
123 
124  QString attrName = props[ QStringLiteral( "attribute" )];
125 
126  QDomElement ruleElem = doc.createElement( QStringLiteral( "se:Rule" ) );
127  element.appendChild( ruleElem );
128 
129  QDomElement nameElem = doc.createElement( QStringLiteral( "se:Name" ) );
130  nameElem.appendChild( doc.createTextNode( mLabel ) );
131  ruleElem.appendChild( nameElem );
132 
133  QDomElement descrElem = doc.createElement( QStringLiteral( "se:Description" ) );
134  QDomElement titleElem = doc.createElement( QStringLiteral( "se:Title" ) );
135  QString descrStr = QStringLiteral( "%1 is '%2'" ).arg( attrName, mValue.toString() );
136  titleElem.appendChild( doc.createTextNode( !mLabel.isEmpty() ? mLabel : descrStr ) );
137  descrElem.appendChild( titleElem );
138  ruleElem.appendChild( descrElem );
139 
140  // create the ogc:Filter for the range
141  QString filterFunc;
142  if ( mValue.isNull() || mValue.toString().isEmpty() )
143  {
144  filterFunc = QStringLiteral( "%1 = '%2' or %1 is null" )
145  .arg( attrName.replace( '\"', QLatin1String( "\"\"" ) ),
146  mValue.toString().replace( '\'', QLatin1String( "''" ) ) );
147  }
148  else
149  {
150  filterFunc = QStringLiteral( "%1 = '%2'" )
151  .arg( attrName.replace( '\"', QLatin1String( "\"\"" ) ),
152  mValue.toString().replace( '\'', QLatin1String( "''" ) ) );
153  }
154 
155  QgsSymbolLayerUtils::createFunctionElement( doc, ruleElem, filterFunc );
156 
157  // add the mix/max scale denoms if we got any from the callers
158  QgsSymbolLayerUtils::applyScaleDependency( doc, ruleElem, props );
159 
160  mSymbol->toSld( doc, ruleElem, props );
161 }
162 
164 
166  : QgsFeatureRenderer( QStringLiteral( "categorizedSymbol" ) )
167  , mAttrName( attrName )
168 {
169  //important - we need a deep copy of the categories list, not a shared copy. This is required because
170  //QgsRendererCategory::symbol() is marked const, and so retrieving the symbol via this method does not
171  //trigger a detachment and copy of mCategories BUT that same method CAN be used to modify a symbol in place
172  for ( const QgsRendererCategory &cat : categories )
173  {
174  if ( !cat.symbol() )
175  {
176  QgsDebugMsg( QStringLiteral( "invalid symbol in a category! ignoring..." ) );
177  }
178  mCategories << cat;
179  }
180 }
181 
183 
185 {
186  mSymbolHash.clear();
187 
188  for ( const QgsRendererCategory &cat : qgis::as_const( mCategories ) )
189  {
190  const QVariant val = cat.value();
191  if ( val.type() == QVariant::List )
192  {
193  const QVariantList list = val.toList();
194  for ( const QVariant &v : list )
195  {
196  mSymbolHash.insert( v.toString(), ( cat.renderState() || mCounting ) ? cat.symbol() : nullptr );
197  }
198  }
199  else
200  {
201  mSymbolHash.insert( val.toString(), ( cat.renderState() || mCounting ) ? cat.symbol() : nullptr );
202  }
203  }
204 }
205 
207 {
208  return nullptr;
209 }
210 
212 {
213  bool found = false;
214  return symbolForValue( value, found );
215 }
216 
217 QgsSymbol *QgsCategorizedSymbolRenderer::symbolForValue( const QVariant &value, bool &foundMatchingSymbol ) const
218 {
219  foundMatchingSymbol = false;
220 
221  // TODO: special case for int, double
222  QHash<QString, QgsSymbol *>::const_iterator it = mSymbolHash.constFind( value.isNull() ? QString() : value.toString() );
223  if ( it == mSymbolHash.constEnd() )
224  {
225  if ( mSymbolHash.isEmpty() )
226  {
227  QgsDebugMsg( QStringLiteral( "there are no hashed symbols!!!" ) );
228  }
229  else
230  {
231  QgsDebugMsgLevel( "attribute value not found: " + value.toString(), 3 );
232  }
233  return nullptr;
234  }
235 
236  foundMatchingSymbol = true;
237 
238  return *it;
239 }
240 
242 {
243  return originalSymbolForFeature( feature, context );
244 }
245 
246 QVariant QgsCategorizedSymbolRenderer::valueForFeature( const QgsFeature &feature, QgsRenderContext &context ) const
247 {
248  QgsAttributes attrs = feature.attributes();
249  QVariant value;
250  if ( mAttrNum == -1 )
251  {
252  Q_ASSERT( mExpression );
253 
254  value = mExpression->evaluate( &context.expressionContext() );
255  }
256  else
257  {
258  value = attrs.value( mAttrNum );
259  }
260 
261  return value;
262 }
263 
265 {
266  QVariant value = valueForFeature( feature, context );
267 
268  bool foundCategory = false;
269  // find the right symbol for the category
270  QgsSymbol *symbol = symbolForValue( value, foundCategory );
271 
272  if ( !foundCategory )
273  {
274  // if no symbol found, use default symbol
275  return symbolForValue( QVariant( "" ), foundCategory );
276  }
277 
278  return symbol;
279 }
280 
281 
283 {
284  for ( int i = 0; i < mCategories.count(); i++ )
285  {
286  if ( mCategories[i].value() == val )
287  return i;
288  }
289  return -1;
290 }
291 
293 {
294  int idx = -1;
295  for ( int i = 0; i < mCategories.count(); i++ )
296  {
297  if ( mCategories[i].label() == val )
298  {
299  if ( idx != -1 )
300  return -1;
301  else
302  idx = i;
303  }
304  }
305  return idx;
306 }
307 
308 bool QgsCategorizedSymbolRenderer::updateCategoryValue( int catIndex, const QVariant &value )
309 {
310  if ( catIndex < 0 || catIndex >= mCategories.size() )
311  return false;
312  mCategories[catIndex].setValue( value );
313  return true;
314 }
315 
317 {
318  if ( catIndex < 0 || catIndex >= mCategories.size() )
319  return false;
320  mCategories[catIndex].setSymbol( symbol );
321  return true;
322 }
323 
324 bool QgsCategorizedSymbolRenderer::updateCategoryLabel( int catIndex, const QString &label )
325 {
326  if ( catIndex < 0 || catIndex >= mCategories.size() )
327  return false;
328  mCategories[catIndex].setLabel( label );
329  return true;
330 }
331 
333 {
334  if ( catIndex < 0 || catIndex >= mCategories.size() )
335  return false;
336  mCategories[catIndex].setRenderState( render );
337  return true;
338 }
339 
341 {
342  if ( !cat.symbol() )
343  {
344  QgsDebugMsg( QStringLiteral( "invalid symbol in a category! ignoring..." ) );
345  return;
346  }
347 
348  mCategories.append( cat );
349 }
350 
352 {
353  if ( catIndex < 0 || catIndex >= mCategories.size() )
354  return false;
355 
356  mCategories.removeAt( catIndex );
357  return true;
358 }
359 
361 {
362  mCategories.clear();
363 }
364 
366 {
367  if ( from < 0 || from >= mCategories.size() || to < 0 || to >= mCategories.size() ) return;
368  mCategories.move( from, to );
369 }
370 
372 {
373  return qgsVariantLessThan( c1.value(), c2.value() );
374 }
376 {
377  return qgsVariantGreaterThan( c1.value(), c2.value() );
378 }
379 
380 void QgsCategorizedSymbolRenderer::sortByValue( Qt::SortOrder order )
381 {
382  if ( order == Qt::AscendingOrder )
383  {
384  std::sort( mCategories.begin(), mCategories.end(), valueLessThan );
385  }
386  else
387  {
388  std::sort( mCategories.begin(), mCategories.end(), valueGreaterThan );
389  }
390 }
391 
393 {
394  return QString::localeAwareCompare( c1.label(), c2.label() ) < 0;
395 }
396 
398 {
399  return !labelLessThan( c1, c2 );
400 }
401 
402 void QgsCategorizedSymbolRenderer::sortByLabel( Qt::SortOrder order )
403 {
404  if ( order == Qt::AscendingOrder )
405  {
406  std::sort( mCategories.begin(), mCategories.end(), labelLessThan );
407  }
408  else
409  {
410  std::sort( mCategories.begin(), mCategories.end(), labelGreaterThan );
411  }
412 }
413 
415 {
416  QgsFeatureRenderer::startRender( context, fields );
417 
418  mCounting = context.rendererScale() == 0.0;
419 
420  // make sure that the hash table is up to date
421  rebuildHash();
422 
423  // find out classification attribute index from name
424  mAttrNum = fields.lookupField( mAttrName );
425  if ( mAttrNum == -1 )
426  {
427  mExpression.reset( new QgsExpression( mAttrName ) );
428  mExpression->prepare( &context.expressionContext() );
429  }
430 
431  for ( const QgsRendererCategory &cat : qgis::as_const( mCategories ) )
432  {
433  cat.symbol()->startRender( context, fields );
434  }
435 }
436 
438 {
440 
441  for ( const QgsRendererCategory &cat : qgis::as_const( mCategories ) )
442  {
443  cat.symbol()->stopRender( context );
444  }
445  mExpression.reset();
446 }
447 
449 {
450  QSet<QString> attributes;
451 
452  // mAttrName can contain either attribute name or an expression.
453  // Sometimes it is not possible to distinguish between those two,
454  // e.g. "a - b" can be both a valid attribute name or expression.
455  // Since we do not have access to fields here, try both options.
456  attributes << mAttrName;
457 
458  QgsExpression testExpr( mAttrName );
459  if ( !testExpr.hasParserError() )
460  attributes.unite( testExpr.referencedColumns() );
461 
462  QgsCategoryList::const_iterator catIt = mCategories.constBegin();
463  for ( ; catIt != mCategories.constEnd(); ++catIt )
464  {
465  QgsSymbol *catSymbol = catIt->symbol();
466  if ( catSymbol )
467  {
468  attributes.unite( catSymbol->usedAttributes( context ) );
469  }
470  }
471  return attributes;
472 }
473 
475 {
476  QgsExpression testExpr( mAttrName );
477  if ( !testExpr.hasParserError() )
478  {
479  QgsExpressionContext context;
480  context.appendScopes( QgsExpressionContextUtils::globalProjectLayerScopes( nullptr ) ); // unfortunately no layer access available!
481  testExpr.prepare( &context );
482  return testExpr.needsGeometry();
483  }
484  return false;
485 }
486 
488 {
489  QString s = QStringLiteral( "CATEGORIZED: idx %1\n" ).arg( mAttrName );
490  for ( int i = 0; i < mCategories.count(); i++ )
491  s += mCategories[i].dump();
492  return s;
493 }
494 
496 {
498  if ( mSourceSymbol )
499  r->setSourceSymbol( mSourceSymbol->clone() );
500  if ( mSourceColorRamp )
501  {
502  r->setSourceColorRamp( mSourceColorRamp->clone() );
503  }
506 
507  copyRendererData( r );
508  return r;
509 }
510 
511 void QgsCategorizedSymbolRenderer::toSld( QDomDocument &doc, QDomElement &element, const QgsStringMap &props ) const
512 {
513  QgsStringMap newProps = props;
514  newProps[ QStringLiteral( "attribute" )] = mAttrName;
515 
516  // create a Rule for each range
517  for ( QgsCategoryList::const_iterator it = mCategories.constBegin(); it != mCategories.constEnd(); ++it )
518  {
519  it->toSld( doc, element, newProps );
520  }
521 }
522 
524 {
525  int attrNum = fields.lookupField( mAttrName );
526  bool isExpression = ( attrNum == -1 );
527 
528  bool hasDefault = false;
529  bool defaultActive = false;
530  bool allActive = true;
531  bool noneActive = true;
532 
533  //we need to build lists of both inactive and active values, as either list may be required
534  //depending on whether the default category is active or not
535  QString activeValues;
536  QString inactiveValues;
537 
538  for ( const QgsRendererCategory &cat : qgis::as_const( mCategories ) )
539  {
540  if ( cat.value() == "" || cat.value().isNull() )
541  {
542  hasDefault = true;
543  defaultActive = cat.renderState();
544  }
545 
546  noneActive = noneActive && !cat.renderState();
547  allActive = allActive && cat.renderState();
548 
549  QVariant::Type valType = isExpression ? cat.value().type() : fields.at( attrNum ).type();
550  const bool isList = cat.value().type() == QVariant::List;
551  QString value = QgsExpression::quotedValue( cat.value(), valType );
552 
553  if ( !cat.renderState() )
554  {
555  if ( cat.value() != "" )
556  {
557  if ( isList )
558  {
559  const QVariantList list = cat.value().toList();
560  for ( const QVariant &v : list )
561  {
562  if ( !inactiveValues.isEmpty() )
563  inactiveValues.append( ',' );
564 
565  inactiveValues.append( QgsExpression::quotedValue( v, isExpression ? v.type() : fields.at( attrNum ).type() ) );
566  }
567  }
568  else
569  {
570  if ( !inactiveValues.isEmpty() )
571  inactiveValues.append( ',' );
572 
573  inactiveValues.append( value );
574  }
575  }
576  }
577  else
578  {
579  if ( cat.value() != "" )
580  {
581  if ( isList )
582  {
583  const QVariantList list = cat.value().toList();
584  for ( const QVariant &v : list )
585  {
586  if ( !activeValues.isEmpty() )
587  activeValues.append( ',' );
588 
589  activeValues.append( QgsExpression::quotedValue( v, isExpression ? v.type() : fields.at( attrNum ).type() ) );
590  }
591  }
592  else
593  {
594  if ( !activeValues.isEmpty() )
595  activeValues.append( ',' );
596 
597  activeValues.append( value );
598  }
599  }
600  }
601  }
602 
603  QString attr = isExpression ? mAttrName : QStringLiteral( "\"%1\"" ).arg( mAttrName );
604 
605  if ( allActive && hasDefault )
606  {
607  return QString();
608  }
609  else if ( noneActive )
610  {
611  return QStringLiteral( "FALSE" );
612  }
613  else if ( defaultActive )
614  {
615  return QStringLiteral( "(%1) NOT IN (%2) OR (%1) IS NULL" ).arg( attr, inactiveValues );
616  }
617  else
618  {
619  return QStringLiteral( "(%1) IN (%2)" ).arg( attr, activeValues );
620  }
621 }
622 
624 {
625  Q_UNUSED( context )
626  QgsSymbolList lst;
627  lst.reserve( mCategories.count() );
628  for ( const QgsRendererCategory &cat : mCategories )
629  {
630  lst.append( cat.symbol() );
631  }
632  return lst;
633 }
634 
636 {
637  for ( const QgsRendererCategory &cat : mCategories )
638  {
639  QgsStyleSymbolEntity entity( cat.symbol() );
640  if ( !visitor->visit( QgsStyleEntityVisitorInterface::StyleLeaf( &entity, cat.value().toString(), cat.label() ) ) )
641  return false;
642  }
643 
644  if ( mSourceColorRamp )
645  {
647  if ( !visitor->visit( QgsStyleEntityVisitorInterface::StyleLeaf( &entity ) ) )
648  return false;
649  }
650 
651  return true;
652 }
653 
655 {
656  QDomElement symbolsElem = element.firstChildElement( QStringLiteral( "symbols" ) );
657  if ( symbolsElem.isNull() )
658  return nullptr;
659 
660  QDomElement catsElem = element.firstChildElement( QStringLiteral( "categories" ) );
661  if ( catsElem.isNull() )
662  return nullptr;
663 
664  QgsSymbolMap symbolMap = QgsSymbolLayerUtils::loadSymbols( symbolsElem, context );
665  QgsCategoryList cats;
666 
667  QDomElement catElem = catsElem.firstChildElement();
668  while ( !catElem.isNull() )
669  {
670  if ( catElem.tagName() == QLatin1String( "category" ) )
671  {
672  QVariant value;
673  if ( catElem.hasAttribute( QStringLiteral( "value" ) ) )
674  {
675  value = QVariant( catElem.attribute( QStringLiteral( "value" ) ) );
676  }
677  else
678  {
679  QVariantList values;
680  QDomElement valElem = catElem.firstChildElement();
681  while ( !valElem.isNull() )
682  {
683  if ( valElem.tagName() == QLatin1String( "val" ) )
684  {
685  values << QVariant( valElem.attribute( QStringLiteral( "value" ) ) );
686  }
687  valElem = valElem.nextSiblingElement();
688  }
689  if ( !values.isEmpty() )
690  value = values;
691  }
692  QString symbolName = catElem.attribute( QStringLiteral( "symbol" ) );
693  QString label = catElem.attribute( QStringLiteral( "label" ) );
694  bool render = catElem.attribute( QStringLiteral( "render" ) ) != QLatin1String( "false" );
695  if ( symbolMap.contains( symbolName ) )
696  {
697  QgsSymbol *symbol = symbolMap.take( symbolName );
698  cats.append( QgsRendererCategory( value, symbol, label, render ) );
699  }
700  }
701  catElem = catElem.nextSiblingElement();
702  }
703 
704  QString attrName = element.attribute( QStringLiteral( "attr" ) );
705 
707 
708  // delete symbols if there are any more
710 
711  // try to load source symbol (optional)
712  QDomElement sourceSymbolElem = element.firstChildElement( QStringLiteral( "source-symbol" ) );
713  if ( !sourceSymbolElem.isNull() )
714  {
715  QgsSymbolMap sourceSymbolMap = QgsSymbolLayerUtils::loadSymbols( sourceSymbolElem, context );
716  if ( sourceSymbolMap.contains( QStringLiteral( "0" ) ) )
717  {
718  r->setSourceSymbol( sourceSymbolMap.take( QStringLiteral( "0" ) ) );
719  }
720  QgsSymbolLayerUtils::clearSymbolMap( sourceSymbolMap );
721  }
722 
723  // try to load color ramp (optional)
724  QDomElement sourceColorRampElem = element.firstChildElement( QStringLiteral( "colorramp" ) );
725  if ( !sourceColorRampElem.isNull() && sourceColorRampElem.attribute( QStringLiteral( "name" ) ) == QLatin1String( "[source]" ) )
726  {
727  r->setSourceColorRamp( QgsSymbolLayerUtils::loadColorRamp( sourceColorRampElem ) );
728  }
729 
730  QDomElement rotationElem = element.firstChildElement( QStringLiteral( "rotation" ) );
731  if ( !rotationElem.isNull() && !rotationElem.attribute( QStringLiteral( "field" ) ).isEmpty() )
732  {
733  for ( const QgsRendererCategory &cat : r->mCategories )
734  {
735  convertSymbolRotation( cat.symbol(), rotationElem.attribute( QStringLiteral( "field" ) ) );
736  }
737  if ( r->mSourceSymbol )
738  {
739  convertSymbolRotation( r->mSourceSymbol.get(), rotationElem.attribute( QStringLiteral( "field" ) ) );
740  }
741  }
742 
743  QDomElement sizeScaleElem = element.firstChildElement( QStringLiteral( "sizescale" ) );
744  if ( !sizeScaleElem.isNull() && !sizeScaleElem.attribute( QStringLiteral( "field" ) ).isEmpty() )
745  {
746  for ( const QgsRendererCategory &cat : r->mCategories )
747  {
749  QgsSymbolLayerUtils::decodeScaleMethod( sizeScaleElem.attribute( QStringLiteral( "scalemethod" ) ) ),
750  sizeScaleElem.attribute( QStringLiteral( "field" ) ) );
751  }
752  if ( r->mSourceSymbol && r->mSourceSymbol->type() == QgsSymbol::Marker )
753  {
755  QgsSymbolLayerUtils::decodeScaleMethod( sizeScaleElem.attribute( QStringLiteral( "scalemethod" ) ) ),
756  sizeScaleElem.attribute( QStringLiteral( "field" ) ) );
757  }
758  }
759 
760  QDomElement ddsLegendSizeElem = element.firstChildElement( QStringLiteral( "data-defined-size-legend" ) );
761  if ( !ddsLegendSizeElem.isNull() )
762  {
763  r->mDataDefinedSizeLegend.reset( QgsDataDefinedSizeLegend::readXml( ddsLegendSizeElem, context ) );
764  }
765 
766  // TODO: symbol levels
767  return r;
768 }
769 
770 QDomElement QgsCategorizedSymbolRenderer::save( QDomDocument &doc, const QgsReadWriteContext &context )
771 {
772  // clazy:skip
773  QDomElement rendererElem = doc.createElement( RENDERER_TAG_NAME );
774  rendererElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "categorizedSymbol" ) );
775  rendererElem.setAttribute( QStringLiteral( "symbollevels" ), ( mUsingSymbolLevels ? QStringLiteral( "1" ) : QStringLiteral( "0" ) ) );
776  rendererElem.setAttribute( QStringLiteral( "forceraster" ), ( mForceRaster ? QStringLiteral( "1" ) : QStringLiteral( "0" ) ) );
777  rendererElem.setAttribute( QStringLiteral( "attr" ), mAttrName );
778 
779  // categories
780  if ( !mCategories.isEmpty() )
781  {
782  int i = 0;
784  QDomElement catsElem = doc.createElement( QStringLiteral( "categories" ) );
785  QgsCategoryList::const_iterator it = mCategories.constBegin();
786  for ( ; it != mCategories.constEnd(); ++it )
787  {
788  const QgsRendererCategory &cat = *it;
789  QString symbolName = QString::number( i );
790  symbols.insert( symbolName, cat.symbol() );
791 
792  QDomElement catElem = doc.createElement( QStringLiteral( "category" ) );
793  if ( cat.value().type() == QVariant::List )
794  {
795  const QVariantList list = cat.value().toList();
796  for ( const QVariant &v : list )
797  {
798  QDomElement valueElem = doc.createElement( QStringLiteral( "val" ) );
799  valueElem.setAttribute( "value", v.toString() );
800  catElem.appendChild( valueElem );
801  }
802  }
803  else
804  {
805  catElem.setAttribute( QStringLiteral( "value" ), cat.value().toString() );
806  }
807  catElem.setAttribute( QStringLiteral( "symbol" ), symbolName );
808  catElem.setAttribute( QStringLiteral( "label" ), cat.label() );
809  catElem.setAttribute( QStringLiteral( "render" ), cat.renderState() ? "true" : "false" );
810  catsElem.appendChild( catElem );
811  i++;
812  }
813  rendererElem.appendChild( catsElem );
814 
815  // save symbols
816  QDomElement symbolsElem = QgsSymbolLayerUtils::saveSymbols( symbols, QStringLiteral( "symbols" ), doc, context );
817  rendererElem.appendChild( symbolsElem );
818 
819  }
820 
821  // save source symbol
822  if ( mSourceSymbol )
823  {
824  QgsSymbolMap sourceSymbols;
825  sourceSymbols.insert( QStringLiteral( "0" ), mSourceSymbol.get() );
826  QDomElement sourceSymbolElem = QgsSymbolLayerUtils::saveSymbols( sourceSymbols, QStringLiteral( "source-symbol" ), doc, context );
827  rendererElem.appendChild( sourceSymbolElem );
828  }
829 
830  // save source color ramp
831  if ( mSourceColorRamp )
832  {
833  QDomElement colorRampElem = QgsSymbolLayerUtils::saveColorRamp( QStringLiteral( "[source]" ), mSourceColorRamp.get(), doc );
834  rendererElem.appendChild( colorRampElem );
835  }
836 
837  QDomElement rotationElem = doc.createElement( QStringLiteral( "rotation" ) );
838  rendererElem.appendChild( rotationElem );
839 
840  QDomElement sizeScaleElem = doc.createElement( QStringLiteral( "sizescale" ) );
841  rendererElem.appendChild( sizeScaleElem );
842 
844  mPaintEffect->saveProperties( doc, rendererElem );
845 
846  if ( !mOrderBy.isEmpty() )
847  {
848  QDomElement orderBy = doc.createElement( QStringLiteral( "orderby" ) );
849  mOrderBy.save( orderBy );
850  rendererElem.appendChild( orderBy );
851  }
852  rendererElem.setAttribute( QStringLiteral( "enableorderby" ), ( mOrderByEnabled ? QStringLiteral( "1" ) : QStringLiteral( "0" ) ) );
853 
855  {
856  QDomElement ddsLegendElem = doc.createElement( QStringLiteral( "data-defined-size-legend" ) );
857  mDataDefinedSizeLegend->writeXml( ddsLegendElem, context );
858  rendererElem.appendChild( ddsLegendElem );
859  }
860 
861  return rendererElem;
862 }
863 
864 
865 QgsLegendSymbolList QgsCategorizedSymbolRenderer::baseLegendSymbolItems() const
866 {
868  int i = 0;
869  for ( const QgsRendererCategory &cat : mCategories )
870  {
871  lst << QgsLegendSymbolItem( cat.symbol(), cat.label(), QString::number( i++ ), true );
872  }
873  return lst;
874 }
875 
877 {
879  {
880  // check that all symbols that have the same size expression
881  QgsProperty ddSize;
882  for ( const QgsRendererCategory &category : mCategories )
883  {
884  const QgsMarkerSymbol *symbol = static_cast<const QgsMarkerSymbol *>( category.symbol() );
885  if ( ddSize )
886  {
887  QgsProperty sSize( symbol->dataDefinedSize() );
888  if ( sSize != ddSize )
889  {
890  // no common size expression
891  return baseLegendSymbolItems();
892  }
893  }
894  else
895  {
896  ddSize = symbol->dataDefinedSize();
897  }
898  }
899 
900  if ( ddSize && ddSize.isActive() )
901  {
903 
905  ddSizeLegend.updateFromSymbolAndProperty( static_cast<const QgsMarkerSymbol *>( mSourceSymbol.get() ), ddSize );
906  lst += ddSizeLegend.legendSymbolList();
907 
908  lst += baseLegendSymbolItems();
909  return lst;
910  }
911  }
912 
913  return baseLegendSymbolItems();
914 }
915 
917 {
918  QString value = valueForFeature( feature, context ).toString();
919  int i = 0;
920 
921  for ( const QgsRendererCategory &cat : mCategories )
922  {
923  bool match = false;
924  if ( cat.value().type() == QVariant::List )
925  {
926  const QVariantList list = cat.value().toList();
927  for ( const QVariant &v : list )
928  {
929  if ( value == v )
930  {
931  match = true;
932  break;
933  }
934  }
935  }
936  else
937  {
938  match = value == cat.value();
939  }
940 
941  if ( match )
942  {
943  if ( cat.renderState() || mCounting )
944  return QSet< QString >() << QString::number( i );
945  else
946  return QSet< QString >();
947  }
948  i++;
949  }
950 
951  return QSet< QString >();
952 }
953 
955 {
956  return mSourceSymbol.get();
957 }
958 
960 {
961  return mSourceSymbol.get();
962 }
963 
965 {
966  mSourceSymbol.reset( sym );
967 }
968 
970 {
971  return mSourceColorRamp.get();
972 }
973 
975 {
976  return mSourceColorRamp.get();
977 }
978 
980 {
981  mSourceColorRamp.reset( ramp );
982 }
983 
985 {
986  setSourceColorRamp( ramp );
987  double num = mCategories.count() - 1;
988  double count = 0;
989 
990  QgsRandomColorRamp *randomRamp = dynamic_cast<QgsRandomColorRamp *>( ramp );
991  if ( randomRamp )
992  {
993  //ramp is a random colors ramp, so inform it of the total number of required colors
994  //this allows the ramp to pregenerate a set of visually distinctive colors
995  randomRamp->setTotalColorCount( mCategories.count() );
996  }
997 
998  for ( const QgsRendererCategory &cat : mCategories )
999  {
1000  double value = count / num;
1001  cat.symbol()->setColor( mSourceColorRamp->color( value ) );
1002  count += 1;
1003  }
1004 }
1005 
1007 {
1008  int i = 0;
1009  for ( const QgsRendererCategory &cat : mCategories )
1010  {
1011  QgsSymbol *symbol = sym->clone();
1012  symbol->setColor( cat.symbol()->color() );
1013  updateCategorySymbol( i, symbol );
1014  ++i;
1015  }
1016  setSourceSymbol( sym->clone() );
1017 }
1018 
1020 {
1021  return true;
1022 }
1023 
1025 {
1026  bool ok;
1027  int index = key.toInt( &ok );
1028  if ( ok && index >= 0 && index < mCategories.size() )
1029  return mCategories.at( index ).renderState();
1030  else
1031  return true;
1032 }
1033 
1035 {
1036  bool ok;
1037  int index = key.toInt( &ok );
1038  if ( ok )
1039  updateCategorySymbol( index, symbol );
1040  else
1041  delete symbol;
1042 }
1043 
1044 void QgsCategorizedSymbolRenderer::checkLegendSymbolItem( const QString &key, bool state )
1045 {
1046  bool ok;
1047  int index = key.toInt( &ok );
1048  if ( ok )
1049  updateCategoryRenderState( index, state );
1050 }
1051 
1053 {
1054  std::unique_ptr< QgsCategorizedSymbolRenderer > r;
1055  if ( renderer->type() == QLatin1String( "categorizedSymbol" ) )
1056  {
1057  r.reset( static_cast<QgsCategorizedSymbolRenderer *>( renderer->clone() ) );
1058  }
1059  else if ( renderer->type() == QLatin1String( "graduatedSymbol" ) )
1060  {
1061  const QgsGraduatedSymbolRenderer *graduatedSymbolRenderer = dynamic_cast<const QgsGraduatedSymbolRenderer *>( renderer );
1062  if ( graduatedSymbolRenderer )
1063  {
1064  r.reset( new QgsCategorizedSymbolRenderer( QString(), QgsCategoryList() ) );
1065  if ( graduatedSymbolRenderer->sourceSymbol() )
1066  r->setSourceSymbol( graduatedSymbolRenderer->sourceSymbol()->clone() );
1067  if ( graduatedSymbolRenderer->sourceColorRamp() )
1068  {
1069  r->setSourceColorRamp( graduatedSymbolRenderer->sourceColorRamp()->clone() );
1070  }
1071  r->setClassAttribute( graduatedSymbolRenderer->classAttribute() );
1072  }
1073  }
1074  else if ( renderer->type() == QLatin1String( "pointDisplacement" ) || renderer->type() == QLatin1String( "pointCluster" ) )
1075  {
1076  const QgsPointDistanceRenderer *pointDistanceRenderer = dynamic_cast<const QgsPointDistanceRenderer *>( renderer );
1077  if ( pointDistanceRenderer )
1078  r.reset( convertFromRenderer( pointDistanceRenderer->embeddedRenderer() ) );
1079  }
1080  else if ( renderer->type() == QLatin1String( "invertedPolygonRenderer" ) )
1081  {
1082  const QgsInvertedPolygonRenderer *invertedPolygonRenderer = dynamic_cast<const QgsInvertedPolygonRenderer *>( renderer );
1083  if ( invertedPolygonRenderer )
1084  r.reset( convertFromRenderer( invertedPolygonRenderer->embeddedRenderer() ) );
1085  }
1086 
1087  // If not one of the specifically handled renderers, then just grab the symbol from the renderer
1088  // Could have applied this to specific renderer types (singleSymbol, graduatedSymbol)
1089 
1090  if ( !r )
1091  {
1092  r = qgis::make_unique< QgsCategorizedSymbolRenderer >( QString(), QgsCategoryList() );
1093  QgsRenderContext context;
1094  QgsSymbolList symbols = const_cast<QgsFeatureRenderer *>( renderer )->symbols( context );
1095  if ( !symbols.isEmpty() )
1096  {
1097  r->setSourceSymbol( symbols.at( 0 )->clone() );
1098  }
1099  }
1100 
1101  r->setOrderBy( renderer->orderBy() );
1102  r->setOrderByEnabled( renderer->orderByEnabled() );
1103 
1104  return r.release();
1105 }
1106 
1108 {
1109  mDataDefinedSizeLegend.reset( settings );
1110 }
1111 
1113 {
1114  return mDataDefinedSizeLegend.get();
1115 }
1116 
1117 int QgsCategorizedSymbolRenderer::matchToSymbols( QgsStyle *style, const QgsSymbol::SymbolType type, QVariantList &unmatchedCategories, QStringList &unmatchedSymbols, const bool caseSensitive, const bool useTolerantMatch )
1118 {
1119  if ( !style )
1120  return 0;
1121 
1122  int matched = 0;
1123  unmatchedSymbols = style->symbolNames();
1124  const QSet< QString > allSymbolNames = qgis::listToSet( unmatchedSymbols );
1125 
1126  const QRegularExpression tolerantMatchRe( QStringLiteral( "[^\\w\\d ]" ), QRegularExpression::UseUnicodePropertiesOption );
1127 
1128  for ( int catIdx = 0; catIdx < mCategories.count(); ++catIdx )
1129  {
1130  const QVariant value = mCategories.at( catIdx ).value();
1131  const QString val = value.toString().trimmed();
1132  std::unique_ptr< QgsSymbol > symbol( style->symbol( val ) );
1133  // case-sensitive match
1134  if ( symbol && symbol->type() == type )
1135  {
1136  matched++;
1137  unmatchedSymbols.removeAll( val );
1138  updateCategorySymbol( catIdx, symbol.release() );
1139  continue;
1140  }
1141 
1142  if ( !caseSensitive || useTolerantMatch )
1143  {
1144  QString testVal = val;
1145  if ( useTolerantMatch )
1146  testVal.replace( tolerantMatchRe, QString() );
1147 
1148  bool foundMatch = false;
1149  for ( const QString &name : allSymbolNames )
1150  {
1151  QString testName = name.trimmed();
1152  if ( useTolerantMatch )
1153  testName.replace( tolerantMatchRe, QString() );
1154 
1155  if ( testName == testVal || ( !caseSensitive && testName.trimmed().compare( testVal, Qt::CaseInsensitive ) == 0 ) )
1156  {
1157  // found a case-insensitive match
1158  std::unique_ptr< QgsSymbol > symbol( style->symbol( name ) );
1159  if ( symbol && symbol->type() == type )
1160  {
1161  matched++;
1162  unmatchedSymbols.removeAll( name );
1163  updateCategorySymbol( catIdx, symbol.release() );
1164  foundMatch = true;
1165  break;
1166  }
1167  }
1168  }
1169  if ( foundMatch )
1170  continue;
1171  }
1172 
1173  unmatchedCategories << value;
1174  }
1175 
1176  return matched;
1177 }
1178 
1179 QgsCategoryList QgsCategorizedSymbolRenderer::createCategories( const QList<QVariant> &values, const QgsSymbol *symbol, QgsVectorLayer *layer, const QString &attributeName )
1180 {
1181  QgsCategoryList cats;
1182  QVariantList vals = values;
1183  // sort the categories first
1184  QgsSymbolLayerUtils::sortVariantList( vals, Qt::AscendingOrder );
1185 
1186  if ( layer && !attributeName.isNull() )
1187  {
1188  const QgsFields fields = layer->fields();
1189  for ( const QVariant &value : vals )
1190  {
1191  QgsSymbol *newSymbol = symbol->clone();
1192  if ( !value.isNull() )
1193  {
1194  int fieldIdx = fields.lookupField( attributeName );
1195  QString categoryName = value.toString();
1196  if ( fieldIdx != -1 )
1197  {
1198  const QgsField field = fields.at( fieldIdx );
1201  categoryName = formatter->representValue( layer, fieldIdx, setup.config(), QVariant(), value );
1202  }
1203  cats.append( QgsRendererCategory( value, newSymbol, categoryName, true ) );
1204  }
1205  }
1206  }
1207 
1208  // add null (default) value
1209  QgsSymbol *newSymbol = symbol->clone();
1210  cats.append( QgsRendererCategory( QVariant(), newSymbol, QString(), true ) );
1211 
1212  return cats;
1213 }
1214 
QgsCategorizedSymbolRenderer::dump
QString dump() const override
Returns debug information about this renderer.
Definition: qgscategorizedsymbolrenderer.cpp:487
QgsCategorizedSymbolRenderer::save
QDomElement save(QDomDocument &doc, const QgsReadWriteContext &context) override
store renderer info to XML element
Definition: qgscategorizedsymbolrenderer.cpp:770
QgsFeatureRenderer::copyRendererData
void copyRendererData(QgsFeatureRenderer *destRenderer) const
Clones generic renderer data to another renderer.
Definition: qgsrenderer.cpp:49
QgsFeatureRenderer::mOrderByEnabled
bool mOrderByEnabled
Definition: qgsrenderer.h:547
QgsExpressionContext
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Definition: qgsexpressioncontext.h:370
QgsProperty::isActive
bool isActive() const
Returns whether the property is currently active.
Definition: qgsproperty.cpp:266
formatter
Definition: qgsbasicnumericformat.cpp:25
QgsColorRamp
Abstract base class for color ramps.
Definition: qgscolorramp.h:32
qgsexpressioncontextutils.h
QgsExpressionContext::appendScopes
void appendScopes(const QList< QgsExpressionContextScope * > &scopes)
Appends a list of scopes to the end of the context.
Definition: qgsexpressioncontext.cpp:495
QgsFeatureRenderer::mForceRaster
bool mForceRaster
Definition: qgsrenderer.h:531
QgsCategorizedSymbolRenderer::symbolForFeature
QgsSymbol * symbolForFeature(const QgsFeature &feature, QgsRenderContext &context) const override
To be overridden.
Definition: qgscategorizedsymbolrenderer.cpp:241
QgsFeatureRenderer::mPaintEffect
QgsPaintEffect * mPaintEffect
Definition: qgsrenderer.h:529
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:104
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:2946
QgsCategorizedSymbolRenderer::convertFromRenderer
static QgsCategorizedSymbolRenderer * convertFromRenderer(const QgsFeatureRenderer *renderer)
creates a QgsCategorizedSymbolRenderer from an existing renderer.
Definition: qgscategorizedsymbolrenderer.cpp:1052
QgsProperty
A store for object properties.
Definition: qgsproperty.h:232
QgsRenderContext::expressionContext
QgsExpressionContext & expressionContext()
Gets the expression context.
Definition: qgsrendercontext.h:596
QgsReadWriteContext
The class is used as a container of context for various read/write operations on other objects.
Definition: qgsreadwritecontext.h:35
qgscategorizedsymbolrenderer.h
QgsGraduatedSymbolRenderer::classAttribute
QString classAttribute() const
Definition: qgsgraduatedsymbolrenderer.h:56
QgsEditorWidgetSetup
Holder for the widget type and its configuration for a field.
Definition: qgseditorwidgetsetup.h:29
QgsExpression::referencedColumns
QSet< QString > referencedColumns() const
Gets list of columns referenced by the expression.
Definition: qgsexpression.cpp:217
QgsCategorizedSymbolRenderer::dataDefinedSizeLegend
QgsDataDefinedSizeLegend * dataDefinedSizeLegend() const
Returns configuration of appearance of legend when using data-defined size for marker symbols.
Definition: qgscategorizedsymbolrenderer.cpp:1112
QgsCategorizedSymbolRenderer::clone
QgsCategorizedSymbolRenderer * clone() const override
Create a deep copy of this renderer.
Definition: qgscategorizedsymbolrenderer.cpp:495
QgsDebugMsgLevel
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
QgsFeatureRequest::OrderBy::save
void CORE_EXPORT save(QDomElement &elem) const
Serialize to XML.
Definition: qgsfeaturerequest.cpp:448
QgsStyleSymbolEntity
A symbol entity for QgsStyle databases.
Definition: qgsstyle.h:1201
QgsCategorizedSymbolRenderer::originalSymbolForFeature
QgsSymbol * originalSymbolForFeature(const QgsFeature &feature, QgsRenderContext &context) const override
Returns symbol for feature.
Definition: qgscategorizedsymbolrenderer.cpp:264
QgsCategorizedSymbolRenderer::updateSymbols
void updateSymbols(QgsSymbol *sym)
Update all the symbols but leave categories and colors.
Definition: qgscategorizedsymbolrenderer.cpp:1006
labelLessThan
bool labelLessThan(const QgsRendererCategory &c1, const QgsRendererCategory &c2)
Definition: qgscategorizedsymbolrenderer.cpp:392
QgsCategorizedSymbolRenderer::mSourceColorRamp
std::unique_ptr< QgsColorRamp > mSourceColorRamp
Definition: qgscategorizedsymbolrenderer.h:444
QgsCategorizedSymbolRenderer::sortByLabel
void sortByLabel(Qt::SortOrder order=Qt::AscendingOrder)
Sorts the existing categories by their label.
Definition: qgscategorizedsymbolrenderer.cpp:402
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:121
QgsMarkerSymbol::dataDefinedSize
QgsProperty dataDefinedSize() const
Returns data defined size for whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:1772
QgsCategorizedSymbolRenderer::rebuildHash
void rebuildHash()
Definition: qgscategorizedsymbolrenderer.cpp:184
QgsSymbolMap
QMap< QString, QgsSymbol * > QgsSymbolMap
Definition: qgsrenderer.h:46
QgsCategorizedSymbolRenderer::updateCategorySymbol
bool updateCategorySymbol(int catIndex, QgsSymbol *symbol)
Changes the symbol for the category with the specified index.
Definition: qgscategorizedsymbolrenderer.cpp:316
QgsStyleColorRampEntity
A color ramp entity for QgsStyle databases.
Definition: qgsstyle.h:1233
QgsSymbolLayerUtils::decodeScaleMethod
static QgsSymbol::ScaleMethod decodeScaleMethod(const QString &str)
Definition: qgssymbollayerutils.cpp:729
QgsCategorizedSymbolRenderer::categories
const QgsCategoryList & categories() const
Returns a list of all categories recognized by the renderer.
Definition: qgscategorizedsymbolrenderer.h:191
qgssymbollayerutils.h
QgsFields
Container of fields for a vector layer.
Definition: qgsfields.h:45
QgsEditorWidgetSetup::config
QVariantMap config() const
Definition: qgseditorwidgetsetup.h:51
QgsCategorizedSymbolRenderer::setLegendSymbolItem
void setLegendSymbolItem(const QString &key, QgsSymbol *symbol) override
Sets the symbol to be used for a legend symbol item.
Definition: qgscategorizedsymbolrenderer.cpp:1034
qgsfeature.h
QgsFeatureRenderer::convertSymbolRotation
static void convertSymbolRotation(QgsSymbol *symbol, const QString &field)
Definition: qgsrenderer.cpp:492
QgsFeatureRenderer::type
QString type() const
Definition: qgsrenderer.h:141
QgsRendererCategory::mLabel
QString mLabel
Definition: qgscategorizedsymbolrenderer.h:139
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:36
QgsRenderContext
Contains information about the context of a rendering operation.
Definition: qgsrendercontext.h:58
QgsStyleEntityVisitorInterface
An interface for classes which can visit style entity (e.g.
Definition: qgsstyleentityvisitor.h:34
QgsRendererCategory::mValue
QVariant mValue
Definition: qgscategorizedsymbolrenderer.h:137
QgsExpressionContextUtils::globalProjectLayerScopes
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Definition: qgsexpressioncontextutils.cpp:307
qgspainteffectregistry.h
QgsCategorizedSymbolRenderer::mDataDefinedSizeLegend
std::unique_ptr< QgsDataDefinedSizeLegend > mDataDefinedSizeLegend
Definition: qgscategorizedsymbolrenderer.h:447
QgsPointDistanceRenderer::embeddedRenderer
const QgsFeatureRenderer * embeddedRenderer() const override
Returns the current embedded renderer (subrenderer) for this feature renderer.
Definition: qgspointdistancerenderer.cpp:164
QgsSymbol
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:64
field
const QgsField & field
Definition: qgsfield.h:456
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:414
QgsCategorizedSymbolRenderer::matchToSymbols
int matchToSymbols(QgsStyle *style, QgsSymbol::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:1117
QgsRendererCategory::mRender
bool mRender
Definition: qgscategorizedsymbolrenderer.h:140
QgsCategorizedSymbolRenderer::legendSymbolItemChecked
bool legendSymbolItemChecked(const QString &key) override
items of symbology items in legend is checked
Definition: qgscategorizedsymbolrenderer.cpp:1024
QgsCategorizedSymbolRenderer::mAttrNum
int mAttrNum
attribute index (derived from attribute name in startRender)
Definition: qgscategorizedsymbolrenderer.h:450
QgsPaintEffect::saveProperties
virtual bool saveProperties(QDomDocument &doc, QDomElement &element) const
Saves the current state of the effect to a DOM element.
Definition: qgspainteffect.cpp:54
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:1107
QgsStyleEntityVisitorInterface::StyleLeaf
Contains information relating to the style entity currently being visited.
Definition: qgsstyleentityvisitor.h:61
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:815
QgsStyle::symbol
QgsSymbol * symbol(const QString &name)
Returns a NEW copy of symbol.
Definition: qgsstyle.cpp:269
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:107
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:437
QgsCategorizedSymbolRenderer::legendSymbolItemsCheckable
bool legendSymbolItemsCheckable() const override
items of symbology items in legend should be checkable
Definition: qgscategorizedsymbolrenderer.cpp:1019
QgsFeatureRenderer::orderBy
QgsFeatureRequest::OrderBy orderBy() const
Gets the order in which features shall be processed by this renderer.
Definition: qgsrenderer.cpp:435
QgsRandomColorRamp
Totally random color ramp.
Definition: qgscolorramp.h:455
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:189
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:79
QgsSymbolLayerUtils::sortVariantList
static void sortVariantList(QList< QVariant > &list, Qt::SortOrder order)
Sorts the passed list in requested order.
Definition: qgssymbollayerutils.cpp:3864
QgsCategorizedSymbolRenderer::skipRender
Q_DECL_DEPRECATED QgsSymbol * skipRender()
Definition: qgscategorizedsymbolrenderer.cpp:206
QgsVectorLayer::fields
QgsFields fields() const FINAL
Returns the list of fields of this layer.
Definition: qgsvectorlayer.cpp:3283
QgsCategorizedSymbolRenderer::symbolForValue
Q_DECL_DEPRECATED QgsSymbol * symbolForValue(const QVariant &value) const
Returns the matching symbol corresponding to an attribute value.
Definition: qgscategorizedsymbolrenderer.cpp:211
QgsEditorWidgetSetup::type
QString type() const
Definition: qgseditorwidgetsetup.h:46
QgsLegendSymbolItem
The class stores information about one class/rule of a vector layer renderer in a unified way that ca...
Definition: qgslegendsymbolitem.h:37
QgsDataDefinedSizeLegend::legendSymbolList
QgsLegendSymbolList legendSymbolList() const
Generates legend symbol items according to the configuration.
Definition: qgsdatadefinedsizelegend.cpp:120
QgsCategorizedSymbolRenderer::~QgsCategorizedSymbolRenderer
~QgsCategorizedSymbolRenderer() override
QgsCategorizedSymbolRenderer::symbols
QgsSymbolList symbols(QgsRenderContext &context) const override
Returns list of symbols used by the renderer.
Definition: qgscategorizedsymbolrenderer.cpp:623
QgsPaintEffectRegistry::isDefaultStack
static bool isDefaultStack(QgsPaintEffect *effect)
Tests whether a paint effect matches the default effects stack.
Definition: qgspainteffectregistry.cpp:134
QgsInvertedPolygonRenderer::embeddedRenderer
const QgsFeatureRenderer * embeddedRenderer() const override
Returns the current embedded renderer (subrenderer) for this feature renderer.
Definition: qgsinvertedpolygonrenderer.cpp:58
QgsRendererCategory::operator=
QgsRendererCategory & operator=(QgsRendererCategory cat)
Definition: qgscategorizedsymbolrenderer.cpp:61
QgsCategorizedSymbolRenderer::updateCategoryValue
bool updateCategoryValue(int catIndex, const QVariant &value)
Changes the value for the category with the specified index.
Definition: qgscategorizedsymbolrenderer.cpp:308
valueGreaterThan
bool valueGreaterThan(const QgsRendererCategory &c1, const QgsRendererCategory &c2)
Definition: qgscategorizedsymbolrenderer.cpp:375
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:282
QgsCategorizedSymbolRenderer::QgsCategorizedSymbolRenderer
QgsCategorizedSymbolRenderer(const QString &attrName=QString(), const QgsCategoryList &categories=QgsCategoryList())
Constructor for QgsCategorizedSymbolRenderer.
Definition: qgscategorizedsymbolrenderer.cpp:165
QgsCategorizedSymbolRenderer::moveCategory
void moveCategory(int from, int to)
Moves an existing category at index position from to index position to.
Definition: qgscategorizedsymbolrenderer.cpp:365
QgsFeatureRenderer::setUsingSymbolLevels
void setUsingSymbolLevels(bool usingSymbolLevels)
Definition: qgsrenderer.h:284
QgsCategorizedSymbolRenderer::filterNeedsGeometry
bool filterNeedsGeometry() const override
Returns true if this renderer requires the geometry to apply the filter.
Definition: qgscategorizedsymbolrenderer.cpp:474
QgsCategoryList
QList< QgsRendererCategory > QgsCategoryList
Definition: qgscategorizedsymbolrenderer.h:145
QgsRendererCategory::setSymbol
void setSymbol(QgsSymbol *s)
Sets the symbol which will be used to render this category.
Definition: qgscategorizedsymbolrenderer.cpp:99
qgscolorramp.h
QgsSymbolList
QList< QgsSymbol * > QgsSymbolList
Definition: qgsrenderer.h:45
QgsMarkerSymbol
A marker symbol type, for rendering Point and MultiPoint geometries.
Definition: qgssymbol.h:931
QgsCategorizedSymbolRenderer::updateCategoryRenderState
bool updateCategoryRenderState(int catIndex, bool render)
Changes the render state for the category with the specified index.
Definition: qgscategorizedsymbolrenderer.cpp:332
QgsRandomColorRamp::setTotalColorCount
virtual void setTotalColorCount(int colorCount)
Sets the desired total number of unique colors for the resultant ramp.
Definition: qgscolorramp.cpp:457
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:523
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:109
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:635
QgsGraduatedSymbolRenderer
Definition: qgsgraduatedsymbolrenderer.h:36
QgsRendererCategory::symbol
QgsSymbol * symbol() const
Returns the symbol which will be used to render this category.
Definition: qgscategorizedsymbolrenderer.cpp:79
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:3112
QgsCategorizedSymbolRenderer::create
static QgsFeatureRenderer * create(QDomElement &element, const QgsReadWriteContext &context)
Creates a categorized renderer from an XML element.
Definition: qgscategorizedsymbolrenderer.cpp:654
RENDERER_TAG_NAME
#define RENDERER_TAG_NAME
Definition: qgsrenderer.h:51
QgsPointDistanceRenderer
An abstract base class for distance based point renderers (e.g., clusterer and displacement renderers...
Definition: qgspointdistancerenderer.h:39
QgsCategorizedSymbolRenderer::legendSymbolItems
QgsLegendSymbolList legendSymbolItems() const override
Returns a list of symbology items for the legend.
Definition: qgscategorizedsymbolrenderer.cpp:876
QgsCategorizedSymbolRenderer::mSourceSymbol
std::unique_ptr< QgsSymbol > mSourceSymbol
Definition: qgscategorizedsymbolrenderer.h:443
QgsFeatureRenderer::usingSymbolLevels
bool usingSymbolLevels() const
Definition: qgsrenderer.h:283
QgsCategorizedSymbolRenderer::toSld
void toSld(QDomDocument &doc, QDomElement &element, const QgsStringMap &props=QgsStringMap()) const override
used from subclasses to create SLD Rule elements following SLD v1.1 specs
Definition: qgscategorizedsymbolrenderer.cpp:511
qgssymbollayer.h
QgsCategorizedSymbolRenderer::mExpression
std::unique_ptr< QgsExpression > mExpression
Definition: qgscategorizedsymbolrenderer.h:445
QgsCategorizedSymbolRenderer::mSymbolHash
QHash< QString, QgsSymbol * > mSymbolHash
hashtable for faster access to symbols
Definition: qgscategorizedsymbolrenderer.h:453
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:351
QgsCategorizedSymbolRenderer::updateCategoryLabel
bool updateCategoryLabel(int catIndex, const QString &label)
Changes the label for the category with the specified index.
Definition: qgscategorizedsymbolrenderer.cpp:324
QgsRendererCategory::swap
void swap(QgsRendererCategory &other)
Definition: qgscategorizedsymbolrenderer.cpp:67
QgsCategorizedSymbolRenderer::sortByValue
void sortByValue(Qt::SortOrder order=Qt::AscendingOrder)
Sorts the existing categories by their value.
Definition: qgscategorizedsymbolrenderer.cpp:380
QgsCategorizedSymbolRenderer::usedAttributes
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns a list of attributes required by this renderer.
Definition: qgscategorizedsymbolrenderer.cpp:448
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:825
QgsCategorizedSymbolRenderer::mAttrName
QString mAttrName
Definition: qgscategorizedsymbolrenderer.h:441
QgsExpression::prepare
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
Definition: qgsexpression.cpp:323
QgsFeature::attributes
QgsAttributes attributes
Definition: qgsfeature.h:65
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:2278
qgsstyle.h
QgsSymbolLayerUtils::loadColorRamp
static QgsColorRamp * loadColorRamp(QDomElement &element)
Creates a color ramp from the settings encoded in an XML element.
Definition: qgssymbollayerutils.cpp:3087
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:292
valueLessThan
bool valueLessThan(const QgsRendererCategory &c1, const QgsRendererCategory &c2)
Definition: qgscategorizedsymbolrenderer.cpp:371
QgsStyle::symbolNames
QStringList symbolNames() const
Returns a list of names of symbols.
Definition: qgsstyle.cpp:285
QgsSymbolLayerUtils::applyScaleDependency
static void applyScaleDependency(QDomDocument &doc, QDomElement &ruleElem, QgsStringMap &props)
Checks if the properties contain scaleMinDenom and scaleMaxDenom, if available, they are added into t...
Definition: qgssymbollayerutils.cpp:4523
QgsFeatureRenderer::mOrderBy
QgsFeatureRequest::OrderBy mOrderBy
Definition: qgsrenderer.h:545
qgsvectorlayer.h
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:97
QgsCategorizedSymbolRenderer::mCounting
bool mCounting
Definition: qgscategorizedsymbolrenderer.h:454
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:964
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:84
QgsStringMap
QMap< QString, QString > QgsStringMap
Definition: qgis.h:758
QgsFeatureRenderer::mUsingSymbolLevels
bool mUsingSymbolLevels
Definition: qgsrenderer.h:522
QgsFeatureRenderer
Definition: qgsrenderer.h:103
QgsRendererCategory::renderState
bool renderState() const
Returns true if the category is currently enabled and should be rendered.
Definition: qgscategorizedsymbolrenderer.cpp:89
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:1179
QgsSymbol::setColor
void setColor(const QColor &color)
Sets the color for the symbol.
Definition: qgssymbol.cpp:504
QgsStyle
Definition: qgsstyle.h:160
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:387
QgsCategorizedSymbolRenderer::updateColorRamp
void updateColorRamp(QgsColorRamp *ramp)
Update the color ramp used and all symbols colors.
Definition: qgscategorizedsymbolrenderer.cpp:984
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:3024
QgsFeatureRenderer::orderByEnabled
bool orderByEnabled() const
Returns whether custom ordering will be applied before features are processed by this renderer.
Definition: qgsrenderer.cpp:445
QgsRendererCategory::toSld
void toSld(QDomDocument &doc, QDomElement &element, QgsStringMap props) const
Converts the category to a matching SLD rule, within the specified DOM document and element.
Definition: qgscategorizedsymbolrenderer.cpp:119
QgsFeatureRenderer::convertSymbolSizeScale
static void convertSymbolSizeScale(QgsSymbol *symbol, QgsSymbol::ScaleMethod method, const QString &field)
Definition: qgsrenderer.cpp:470
QgsRendererCategory::dump
QString dump() const
Returns a string representing the categories settings, used for debugging purposes only.
Definition: qgscategorizedsymbolrenderer.cpp:114
QgsGraduatedSymbolRenderer::sourceColorRamp
QgsColorRamp * sourceColorRamp()
Returns the source color ramp, from which each classes' color is derived.
Definition: qgsgraduatedsymbolrenderer.cpp:830
QgsSymbolLayerUtils::clearSymbolMap
static void clearSymbolMap(QgsSymbolMap &symbols)
Definition: qgssymbollayerutils.cpp:3038
QgsSymbol::usedAttributes
QSet< QString > usedAttributes(const QgsRenderContext &context) const
Returns a list of attributes required to render this feature.
Definition: qgssymbol.cpp:757
QgsFieldFormatterRegistry::fieldFormatter
QgsFieldFormatter * fieldFormatter(const QString &id) const
Gets a field formatter by its id.
Definition: qgsfieldformatterregistry.cpp:72
qgspointdisplacementrenderer.h
qgsproperty.h
labelGreaterThan
bool labelGreaterThan(const QgsRendererCategory &c1, const QgsRendererCategory &c2)
Definition: qgscategorizedsymbolrenderer.cpp:397
QgsSymbol::Marker
@ Marker
Marker symbol.
Definition: qgssymbol.h:87
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:266
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:954
QgsCategorizedSymbolRenderer::mCategories
QgsCategoryList mCategories
Definition: qgscategorizedsymbolrenderer.h:442
QgsAttributes
A vector of attributes.
Definition: qgsattributes.h:58
QgsRendererCategory::setValue
void setValue(const QVariant &value)
Sets the value corresponding to this category.
Definition: qgscategorizedsymbolrenderer.cpp:94
qgsinvertedpolygonrenderer.h
QgsCategorizedSymbolRenderer
Definition: qgscategorizedsymbolrenderer.h:152
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:363
QgsFeature
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:56
QgsCategorizedSymbolRenderer::deleteAllCategories
void deleteAllCategories()
Deletes all existing categories from the renderer.
Definition: qgscategorizedsymbolrenderer.cpp:360
qgsdatadefinedsizelegend.h
QgsExpression::hasParserError
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
Definition: qgsexpression.cpp:202
QgsSymbol::SymbolType
SymbolType
Type of the symbol.
Definition: qgssymbol.h:86
qgslogger.h
QgsFields::lookupField
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
Definition: qgsfields.cpp:344
QgsRenderContext::rendererScale
double rendererScale() const
Returns the renderer map scale.
Definition: qgsrendercontext.h:377
QgsField::editorWidgetSetup
QgsEditorWidgetSetup editorWidgetSetup() const
Gets the editor widget setup for the field.
Definition: qgsfield.cpp:559
QgsFields::at
QgsField at(int i) const
Gets 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:105
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:93
QgsFieldFormatter
A field formatter helps to handle and display values for a field.
Definition: qgsfieldformatter.h:73
qgssymbol.h
QgsRendererCategory::value
QVariant value() const
Returns the value corresponding to this category.
Definition: qgscategorizedsymbolrenderer.cpp:74
QgsCategorizedSymbolRenderer::setSourceColorRamp
void setSourceColorRamp(QgsColorRamp *ramp)
Sets the source color ramp.
Definition: qgscategorizedsymbolrenderer.cpp:979
QgsField::type
QVariant::Type type
Definition: qgsfield.h:57
QgsCategorizedSymbolRenderer::addCategory
void addCategory(const QgsRendererCategory &category)
Adds a new category to the renderer.
Definition: qgscategorizedsymbolrenderer.cpp:340
QgsRendererCategory::mSymbol
std::unique_ptr< QgsSymbol > mSymbol
Definition: qgscategorizedsymbolrenderer.h:138
qgsfieldformatter.h
qgsstyleentityvisitor.h
QgsCategorizedSymbolRenderer::checkLegendSymbolItem
void checkLegendSymbolItem(const QString &key, bool state=true) override
item in symbology was checked
Definition: qgscategorizedsymbolrenderer.cpp:1044
QgsCategorizedSymbolRenderer::legendKeysForFeature
QSet< QString > legendKeysForFeature(const QgsFeature &feature, QgsRenderContext &context) const override
Returns legend keys matching a specified feature.
Definition: qgscategorizedsymbolrenderer.cpp:916
QgsCategorizedSymbolRenderer::sourceColorRamp
QgsColorRamp * sourceColorRamp()
Returns the source color ramp, from which each categories' color is derived.
Definition: qgscategorizedsymbolrenderer.cpp:969
QgsSymbolLayerUtils::createFunctionElement
static bool createFunctionElement(QDomDocument &doc, QDomElement &element, const QString &function)
Definition: qgssymbollayerutils.cpp:2756
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