31 #include <QDomElement>
36 void QgsDiagramLayerSettings::initPropertyDefinitions()
38 if ( !sPropertyDefinitions.isEmpty() )
41 const QString origin = QStringLiteral(
"diagram" );
62 initPropertyDefinitions();
63 return sPropertyDefinitions;
68 initPropertyDefinitions();
73 , mPlacement( rh.mPlacement )
74 , mPlacementFlags( rh.mPlacementFlags )
75 , mPriority( rh.mPriority )
76 , mZIndex( rh.mZIndex )
77 , mObstacle( rh.mObstacle )
78 , mDistance( rh.mDistance )
79 , mRenderer( rh.mRenderer ? rh.mRenderer->clone() : nullptr )
80 , mShowAll( rh.mShowAll )
81 , mDataDefinedProperties( rh.mDataDefinedProperties )
83 initPropertyDefinitions();
88 mPlacement = rh.mPlacement;
89 mPlacementFlags = rh.mPlacementFlags;
90 mPriority = rh.mPriority;
92 mObstacle = rh.mObstacle;
93 mDistance = rh.mDistance;
94 mRenderer = rh.mRenderer ? rh.mRenderer->
clone() :
nullptr;
96 mShowAll = rh.mShowAll;
97 mDataDefinedProperties = rh.mDataDefinedProperties;
108 if ( diagramRenderer == mRenderer )
112 mRenderer = diagramRenderer;
122 QDomNodeList propertyElems = elem.elementsByTagName( QStringLiteral(
"properties" ) );
123 if ( !propertyElems.isEmpty() )
125 ( void )mDataDefinedProperties.
readXml( propertyElems.at( 0 ).toElement(), sPropertyDefinitions );
129 mDataDefinedProperties.
clear();
132 mPlacement =
static_cast< Placement >( elem.attribute( QStringLiteral(
"placement" ) ).toInt() );
133 mPlacementFlags =
static_cast< LinePlacementFlag >( elem.attribute( QStringLiteral(
"linePlacementFlags" ) ).toInt() );
134 mPriority = elem.attribute( QStringLiteral(
"priority" ) ).toInt();
135 mZIndex = elem.attribute( QStringLiteral(
"zIndex" ) ).toDouble();
136 mObstacle = elem.attribute( QStringLiteral(
"obstacle" ) ).toInt();
137 mDistance = elem.attribute( QStringLiteral(
"dist" ) ).toDouble();
138 mShowAll = ( elem.attribute( QStringLiteral(
"showAll" ), QStringLiteral(
"0" ) ) != QLatin1String(
"0" ) );
143 QDomElement diagramLayerElem = doc.createElement( QStringLiteral(
"DiagramLayerSettings" ) );
144 QDomElement propertiesElem = doc.createElement( QStringLiteral(
"properties" ) );
145 ( void )mDataDefinedProperties.
writeXml( propertiesElem, sPropertyDefinitions );
146 diagramLayerElem.appendChild( propertiesElem );
147 diagramLayerElem.setAttribute( QStringLiteral(
"placement" ), mPlacement );
148 diagramLayerElem.setAttribute( QStringLiteral(
"linePlacementFlags" ), mPlacementFlags );
149 diagramLayerElem.setAttribute( QStringLiteral(
"priority" ), mPriority );
150 diagramLayerElem.setAttribute( QStringLiteral(
"zIndex" ), mZIndex );
151 diagramLayerElem.setAttribute( QStringLiteral(
"obstacle" ), mObstacle );
152 diagramLayerElem.setAttribute( QStringLiteral(
"dist" ), QString::number( mDistance ) );
153 diagramLayerElem.setAttribute( QStringLiteral(
"showAll" ), mShowAll );
154 layerElem.appendChild( diagramLayerElem );
159 return mDataDefinedProperties.
prepare( context );
164 QSet< QString > referenced;
176 enabled = ( elem.attribute( QStringLiteral(
"enabled" ), QStringLiteral(
"1" ) ) != QLatin1String(
"0" ) );
179 font.fromString( elem.attribute( QStringLiteral(
"font" ) ) );
181 backgroundColor.setNamedColor( elem.attribute( QStringLiteral(
"backgroundColor" ) ) );
182 backgroundColor.setAlpha( elem.attribute( QStringLiteral(
"backgroundAlpha" ) ).toInt() );
183 size.setWidth( elem.attribute( QStringLiteral(
"width" ) ).toDouble() );
184 size.setHeight( elem.attribute( QStringLiteral(
"height" ) ).toDouble() );
185 if ( elem.hasAttribute( QStringLiteral(
"transparency" ) ) )
187 opacity = 1 - elem.attribute( QStringLiteral(
"transparency" ), QStringLiteral(
"0" ) ).toInt() / 255.0;
191 opacity = elem.attribute( QStringLiteral(
"opacity" ), QStringLiteral(
"1.00" ) ).toDouble();
194 penColor.setNamedColor( elem.attribute( QStringLiteral(
"penColor" ) ) );
195 int penAlpha = elem.attribute( QStringLiteral(
"penAlpha" ), QStringLiteral(
"255" ) ).toInt();
197 penWidth = elem.attribute( QStringLiteral(
"penWidth" ) ).toDouble();
199 mDirection =
static_cast< Direction >( elem.attribute( QStringLiteral(
"direction" ), QStringLiteral(
"1" ) ).toInt() );
201 maximumScale = elem.attribute( QStringLiteral(
"minScaleDenominator" ), QStringLiteral(
"-1" ) ).toDouble();
202 minimumScale = elem.attribute( QStringLiteral(
"maxScaleDenominator" ), QStringLiteral(
"-1" ) ).toDouble();
203 if ( elem.hasAttribute( QStringLiteral(
"scaleBasedVisibility" ) ) )
205 scaleBasedVisibility = ( elem.attribute( QStringLiteral(
"scaleBasedVisibility" ), QStringLiteral(
"1" ) ) != QLatin1String(
"0" ) );
213 if ( elem.attribute( QStringLiteral(
"sizeType" ) ) == QLatin1String(
"MapUnits" ) )
228 mSpacing = elem.attribute( QStringLiteral(
"spacing" ) ).toDouble();
233 if ( elem.attribute( QStringLiteral(
"labelPlacementMethod" ) ) == QLatin1String(
"Height" ) )
243 if ( elem.attribute( QStringLiteral(
"diagramOrientation" ) ) == QLatin1String(
"Left" ) )
247 else if ( elem.attribute( QStringLiteral(
"diagramOrientation" ) ) == QLatin1String(
"Right" ) )
251 else if ( elem.attribute( QStringLiteral(
"diagramOrientation" ) ) == QLatin1String(
"Down" ) )
261 if ( elem.attribute( QStringLiteral(
"scaleDependency" ) ) == QLatin1String(
"Diameter" ) )
270 barWidth = elem.attribute( QStringLiteral(
"barWidth" ) ).toDouble();
272 if ( elem.hasAttribute( QStringLiteral(
"angleOffset" ) ) )
273 rotationOffset = std::fmod( 360.0 - elem.attribute( QStringLiteral(
"angleOffset" ) ).toInt() / 16.0, 360.0 );
275 rotationOffset = elem.attribute( QStringLiteral(
"rotationOffset" ) ).toDouble();
277 minimumSize = elem.attribute( QStringLiteral(
"minimumSize" ) ).toDouble();
279 QDomNodeList axisSymbolNodes = elem.elementsByTagName( QStringLiteral(
"axisSymbol" ) );
280 if ( axisSymbolNodes.count() > 0 )
282 QDomElement axisSymbolElem = axisSymbolNodes.at( 0 ).toElement().firstChildElement();
283 mAxisLineSymbol.reset( QgsSymbolLayerUtils::loadSymbol<QgsLineSymbol>( axisSymbolElem, context ) );
287 mAxisLineSymbol = qgis::make_unique< QgsLineSymbol >();
290 mShowAxis = elem.attribute( QStringLiteral(
"showAxis" ), QStringLiteral(
"0" ) ).toInt();
294 QDomNodeList attributes = elem.elementsByTagName( QStringLiteral(
"attribute" ) );
297 if ( attributes.length() > 0 )
299 for (
int i = 0; i < attributes.size(); i++ )
301 QDomElement attrElem = attributes.at( i ).toElement();
302 QColor newColor( attrElem.attribute( QStringLiteral(
"color" ) ) );
306 categoryLabels.append( attrElem.attribute( QStringLiteral(
"label" ) ) );
317 QStringList colorList = elem.attribute( QStringLiteral(
"colors" ) ).split(
'/' );
318 QStringList::const_iterator colorIt = colorList.constBegin();
319 for ( ; colorIt != colorList.constEnd(); ++colorIt )
321 QColor newColor( *colorIt );
328 QStringList catList = elem.attribute( QStringLiteral(
"categories" ) ).split(
'/' );
329 QStringList::const_iterator catIt = catList.constBegin();
330 for ( ; catIt != catList.constEnd(); ++catIt )
337 QDomElement effectElem = elem.firstChildElement( QStringLiteral(
"effect" ) );
338 if ( !effectElem.isNull() )
346 QDomElement categoryElem = doc.createElement( QStringLiteral(
"DiagramCategory" ) );
347 categoryElem.setAttribute( QStringLiteral(
"enabled" ),
enabled );
349 categoryElem.setAttribute( QStringLiteral(
"backgroundColor" ),
backgroundColor.name() );
350 categoryElem.setAttribute( QStringLiteral(
"backgroundAlpha" ),
backgroundColor.alpha() );
351 categoryElem.setAttribute( QStringLiteral(
"width" ), QString::number(
size.width() ) );
352 categoryElem.setAttribute( QStringLiteral(
"height" ), QString::number(
size.height() ) );
353 categoryElem.setAttribute( QStringLiteral(
"penColor" ),
penColor.name() );
354 categoryElem.setAttribute( QStringLiteral(
"penAlpha" ),
penColor.alpha() );
355 categoryElem.setAttribute( QStringLiteral(
"penWidth" ), QString::number(
penWidth ) );
357 categoryElem.setAttribute( QStringLiteral(
"minScaleDenominator" ), QString::number(
maximumScale ) );
358 categoryElem.setAttribute( QStringLiteral(
"maxScaleDenominator" ), QString::number(
minimumScale ) );
359 categoryElem.setAttribute( QStringLiteral(
"opacity" ), QString::number(
opacity ) );
360 categoryElem.setAttribute( QStringLiteral(
"spacing" ), QString::number( mSpacing ) );
363 categoryElem.setAttribute( QStringLiteral(
"direction" ), QString::number( mDirection ) );
376 categoryElem.setAttribute( QStringLiteral(
"labelPlacementMethod" ), QStringLiteral(
"Height" ) );
380 categoryElem.setAttribute( QStringLiteral(
"labelPlacementMethod" ), QStringLiteral(
"XHeight" ) );
385 categoryElem.setAttribute( QStringLiteral(
"scaleDependency" ), QStringLiteral(
"Area" ) );
389 categoryElem.setAttribute( QStringLiteral(
"scaleDependency" ), QStringLiteral(
"Diameter" ) );
396 categoryElem.setAttribute( QStringLiteral(
"diagramOrientation" ), QStringLiteral(
"Left" ) );
400 categoryElem.setAttribute( QStringLiteral(
"diagramOrientation" ), QStringLiteral(
"Right" ) );
404 categoryElem.setAttribute( QStringLiteral(
"diagramOrientation" ), QStringLiteral(
"Down" ) );
408 categoryElem.setAttribute( QStringLiteral(
"diagramOrientation" ), QStringLiteral(
"Up" ) );
412 categoryElem.setAttribute( QStringLiteral(
"barWidth" ), QString::number(
barWidth ) );
413 categoryElem.setAttribute( QStringLiteral(
"minimumSize" ), QString::number(
minimumSize ) );
414 categoryElem.setAttribute( QStringLiteral(
"rotationOffset" ), QString::number(
rotationOffset ) );
417 for (
int i = 0; i < nCats; ++i )
419 QDomElement attributeElem = doc.createElement( QStringLiteral(
"attribute" ) );
422 attributeElem.setAttribute( QStringLiteral(
"color" ),
categoryColors.at( i ).name() );
423 attributeElem.setAttribute( QStringLiteral(
"label" ),
categoryLabels.at( i ) );
424 categoryElem.appendChild( attributeElem );
427 categoryElem.setAttribute( QStringLiteral(
"showAxis" ), mShowAxis ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
428 QDomElement axisSymbolElem = doc.createElement( QStringLiteral(
"axisSymbol" ) );
430 axisSymbolElem.appendChild( symbolElem );
431 categoryElem.appendChild( axisSymbolElem );
434 mPaintEffect->saveProperties( doc, categoryElem );
436 rendererElem.appendChild( categoryElem );
448 : mDiagram( other.mDiagram ? other.mDiagram->clone() : nullptr )
449 , mShowAttributeLegend( other.mShowAttributeLegend )
479 c.expressionContext().setOriginalValueVariable( s.
penWidth );
486 std::unique_ptr< QgsEffectPainter > effectPainter;
487 if ( effect && effect->
enabled() )
489 effectPainter = qgis::make_unique< QgsEffectPainter >(
c, effect );
492 mDiagram->renderDiagram( feature,
c, s, pos );
504 if ( size.isValid() )
507 size.rheight() *= width / size.width();
508 size.setWidth( width );
515 QSet< QString > referenced;
521 for (
const QString &att : constDiagramAttributes )
525 for (
const QString &field : constReferencedColumns )
535 if ( !size.isValid() )
541 size.rwidth() *= pixelToMap;
542 size.rheight() *= pixelToMap;
549 QPaintDevice *device = painter->device();
552 return device->logicalDpiX();
562 QString diagramType = elem.attribute( QStringLiteral(
"diagramType" ) );
563 if ( diagramType == QLatin1String(
"Pie" ) )
567 else if ( diagramType == QLatin1String(
"Text" ) )
571 else if ( diagramType == QLatin1String(
"Histogram" ) )
575 else if ( diagramType == QLatin1String(
"Stacked" ) )
584 mShowAttributeLegend = ( elem.attribute( QStringLiteral(
"attributeLegend" ), QStringLiteral(
"1" ) ) != QLatin1String(
"0" ) );
594 rendererElem.setAttribute( QStringLiteral(
"diagramType" ),
mDiagram->diagramName() );
618 QList<QgsDiagramSettings> settingsList;
619 settingsList.push_back( mSettings );
625 QDomElement categoryElem = elem.firstChildElement( QStringLiteral(
"DiagramCategory" ) );
626 if ( categoryElem.isNull() )
631 mSettings.
readXml( categoryElem, context );
637 QDomElement rendererElem = doc.createElement( QStringLiteral(
"SingleCategoryDiagramRenderer" ) );
638 mSettings.
writeXml( rendererElem, doc, context );
640 layerElem.appendChild( rendererElem );
651 , mSettings( other.mSettings )
652 , mInterpolationSettings( other.mInterpolationSettings )
653 , mDataDefinedSizeLegend( other.mDataDefinedSizeLegend ? new
QgsDataDefinedSizeLegend( *other.mDataDefinedSizeLegend ) : nullptr )
659 delete mDataDefinedSizeLegend;
669 QList<QgsDiagramSettings> settingsList;
670 settingsList.push_back( mSettings );
693 for (
const QString &field : constReferencedColumns )
707 return mDiagram->diagramSize( feature,
c, mSettings, mInterpolationSettings );
712 mInterpolationSettings.
lowerValue = elem.attribute( QStringLiteral(
"lowerValue" ) ).toDouble();
713 mInterpolationSettings.
upperValue = elem.attribute( QStringLiteral(
"upperValue" ) ).toDouble();
714 mInterpolationSettings.
lowerSize.setWidth( elem.attribute( QStringLiteral(
"lowerWidth" ) ).toDouble() );
715 mInterpolationSettings.
lowerSize.setHeight( elem.attribute( QStringLiteral(
"lowerHeight" ) ).toDouble() );
716 mInterpolationSettings.
upperSize.setWidth( elem.attribute( QStringLiteral(
"upperWidth" ) ).toDouble() );
717 mInterpolationSettings.
upperSize.setHeight( elem.attribute( QStringLiteral(
"upperHeight" ) ).toDouble() );
725 mInterpolationSettings.
classificationField = elem.attribute( QStringLiteral(
"classificationField" ) );
727 QDomElement settingsElem = elem.firstChildElement( QStringLiteral(
"DiagramCategory" ) );
728 if ( !settingsElem.isNull() )
730 mSettings.
readXml( settingsElem );
733 delete mDataDefinedSizeLegend;
735 QDomElement ddsLegendSizeElem = elem.firstChildElement( QStringLiteral(
"data-defined-size-legend" ) );
736 if ( !ddsLegendSizeElem.isNull() )
743 if ( elem.attribute( QStringLiteral(
"sizeLegend" ), QStringLiteral(
"0" ) ) != QLatin1String(
"0" ) )
746 QDomElement sizeLegendSymbolElem = elem.firstChildElement( QStringLiteral(
"symbol" ) );
747 if ( !sizeLegendSymbolElem.isNull() && sizeLegendSymbolElem.attribute( QStringLiteral(
"name" ) ) == QLatin1String(
"sizeSymbol" ) )
749 mDataDefinedSizeLegend->
setSymbol( QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( sizeLegendSymbolElem, context ) );
754 mDataDefinedSizeLegend =
nullptr;
763 QDomElement rendererElem = doc.createElement( QStringLiteral(
"LinearlyInterpolatedDiagramRenderer" ) );
764 rendererElem.setAttribute( QStringLiteral(
"lowerValue" ), QString::number( mInterpolationSettings.
lowerValue ) );
765 rendererElem.setAttribute( QStringLiteral(
"upperValue" ), QString::number( mInterpolationSettings.
upperValue ) );
766 rendererElem.setAttribute( QStringLiteral(
"lowerWidth" ), QString::number( mInterpolationSettings.
lowerSize.width() ) );
767 rendererElem.setAttribute( QStringLiteral(
"lowerHeight" ), QString::number( mInterpolationSettings.
lowerSize.height() ) );
768 rendererElem.setAttribute( QStringLiteral(
"upperWidth" ), QString::number( mInterpolationSettings.
upperSize.width() ) );
769 rendererElem.setAttribute( QStringLiteral(
"upperHeight" ), QString::number( mInterpolationSettings.
upperSize.height() ) );
776 rendererElem.setAttribute( QStringLiteral(
"classificationField" ), mInterpolationSettings.
classificationField );
778 mSettings.
writeXml( rendererElem, doc );
780 if ( mDataDefinedSizeLegend )
782 QDomElement ddsLegendElem = doc.createElement( QStringLiteral(
"data-defined-size-legend" ) );
783 mDataDefinedSizeLegend->
writeXml( ddsLegendElem, context );
784 rendererElem.appendChild( ddsLegendElem );
788 layerElem.appendChild( rendererElem );
793 QList< QgsLayerTreeModelLegendNode * > list;
797 QPixmap pix( 16, 16 );
806 return mAxisLineSymbol.get();
827 return mPaintEffect.get();
832 if ( effect != mPaintEffect.get() )
833 mPaintEffect.reset( effect );
844 : enabled( other.enabled )
846 , categoryColors( other.categoryColors )
847 , categoryAttributes( other.categoryAttributes )
848 , categoryLabels( other.categoryLabels )
850 , sizeType( other.sizeType )
851 , sizeScale( other.sizeScale )
852 , lineSizeUnit( other.lineSizeUnit )
853 , lineSizeScale( other.lineSizeScale )
854 , backgroundColor( other.backgroundColor )
855 , penColor( other.penColor )
856 , penWidth( other.penWidth )
857 , labelPlacementMethod( other.labelPlacementMethod )
858 , diagramOrientation( other.diagramOrientation )
859 , barWidth( other.barWidth )
860 , opacity( other.opacity )
861 , scaleByArea( other.scaleByArea )
862 , rotationOffset( other.rotationOffset )
863 , scaleBasedVisibility( other.scaleBasedVisibility )
864 , maximumScale( other.maximumScale )
865 , minimumScale( other.minimumScale )
866 , minimumSize( other.minimumSize )
867 , mSpacing( other.mSpacing )
868 , mSpacingUnit( other.mSpacingUnit )
869 , mSpacingMapUnitScale( other.mSpacingMapUnitScale )
870 , mDirection( other.mDirection )
871 , mShowAxis( other.mShowAxis )
872 , mAxisLineSymbol( other.mAxisLineSymbol ? other.mAxisLineSymbol->clone() : nullptr )
873 , mPaintEffect( other.mPaintEffect ? other.mPaintEffect->clone() : nullptr )
903 mSpacing = other.mSpacing;
904 mSpacingUnit = other.mSpacingUnit;
905 mSpacingMapUnitScale = other.mSpacingMapUnitScale;
906 mDirection = other.mDirection;
907 mAxisLineSymbol.reset( other.mAxisLineSymbol ? other.mAxisLineSymbol->clone() :
nullptr );
908 mShowAxis = other.mShowAxis;
909 mPaintEffect.reset( other.mPaintEffect ? other.mPaintEffect->clone() :
nullptr );
925 return QList< QgsLayerTreeModelLegendNode * >();
930 QList< QgsLayerTreeModelLegendNode * > nodes;
939 QList< QgsLayerTreeModelLegendNode * > nodes;
943 if ( mDataDefinedSizeLegend &&
mDiagram )
953 QList<QgsDataDefinedSizeLegend::SizeClass> sizeClasses;
954 if ( ddSizeLegend.
classes().isEmpty() )
958 for (
double v : prettyBreaks )
960 double size =
mDiagram->legendSize( v, mSettings, mInterpolationSettings );
967 const auto constClasses = ddSizeLegend.
classes();
970 double size =
mDiagram->legendSize( sc.size, mSettings, mInterpolationSettings );
979 if ( si.dataDefinedSizeLegendSettings() )
991 delete mDataDefinedSizeLegend;
992 mDataDefinedSizeLegend = settings;
997 return mDataDefinedSizeLegend;