33 #include <QDomElement>
38 void QgsDiagramLayerSettings::initPropertyDefinitions()
40 if ( !sPropertyDefinitions.isEmpty() )
43 const QString origin = QStringLiteral(
"diagram" );
64 initPropertyDefinitions();
65 return sPropertyDefinitions;
70 initPropertyDefinitions();
75 , mPlacement( rh.mPlacement )
76 , mPlacementFlags( rh.mPlacementFlags )
77 , mPriority( rh.mPriority )
78 , mZIndex( rh.mZIndex )
79 , mObstacle( rh.mObstacle )
80 , mDistance( rh.mDistance )
81 , mRenderer( rh.mRenderer ? rh.mRenderer->clone() : nullptr )
82 , mShowAll( rh.mShowAll )
83 , mDataDefinedProperties( rh.mDataDefinedProperties )
85 initPropertyDefinitions();
90 mPlacement = rh.mPlacement;
91 mPlacementFlags = rh.mPlacementFlags;
92 mPriority = rh.mPriority;
94 mObstacle = rh.mObstacle;
95 mDistance = rh.mDistance;
96 mRenderer = rh.mRenderer ? rh.mRenderer->
clone() :
nullptr;
98 mShowAll = rh.mShowAll;
99 mDataDefinedProperties = rh.mDataDefinedProperties;
110 if ( diagramRenderer == mRenderer )
114 mRenderer = diagramRenderer;
124 const QDomNodeList propertyElems = elem.elementsByTagName( QStringLiteral(
"properties" ) );
125 if ( !propertyElems.isEmpty() )
127 ( void )mDataDefinedProperties.
readXml( propertyElems.at( 0 ).toElement(), sPropertyDefinitions );
131 mDataDefinedProperties.
clear();
134 mPlacement =
static_cast< Placement >( elem.attribute( QStringLiteral(
"placement" ) ).toInt() );
135 mPlacementFlags =
static_cast< LinePlacementFlag >( elem.attribute( QStringLiteral(
"linePlacementFlags" ) ).toInt() );
136 mPriority = elem.attribute( QStringLiteral(
"priority" ) ).toInt();
137 mZIndex = elem.attribute( QStringLiteral(
"zIndex" ) ).toDouble();
138 mObstacle = elem.attribute( QStringLiteral(
"obstacle" ) ).toInt();
139 mDistance = elem.attribute( QStringLiteral(
"dist" ) ).toDouble();
140 mShowAll = ( elem.attribute( QStringLiteral(
"showAll" ), QStringLiteral(
"0" ) ) != QLatin1String(
"0" ) );
145 QDomElement diagramLayerElem = doc.createElement( QStringLiteral(
"DiagramLayerSettings" ) );
146 QDomElement propertiesElem = doc.createElement( QStringLiteral(
"properties" ) );
147 ( void )mDataDefinedProperties.
writeXml( propertiesElem, sPropertyDefinitions );
148 diagramLayerElem.appendChild( propertiesElem );
149 diagramLayerElem.setAttribute( QStringLiteral(
"placement" ), mPlacement );
150 diagramLayerElem.setAttribute( QStringLiteral(
"linePlacementFlags" ), mPlacementFlags );
151 diagramLayerElem.setAttribute( QStringLiteral(
"priority" ), mPriority );
152 diagramLayerElem.setAttribute( QStringLiteral(
"zIndex" ), mZIndex );
153 diagramLayerElem.setAttribute( QStringLiteral(
"obstacle" ), mObstacle );
154 diagramLayerElem.setAttribute( QStringLiteral(
"dist" ), QString::number( mDistance ) );
155 diagramLayerElem.setAttribute( QStringLiteral(
"showAll" ), mShowAll );
156 layerElem.appendChild( diagramLayerElem );
161 return mDataDefinedProperties.
prepare( context );
166 QSet< QString > referenced;
178 enabled = ( elem.attribute( QStringLiteral(
"enabled" ), QStringLiteral(
"1" ) ) != QLatin1String(
"0" ) );
181 font.fromString( elem.attribute( QStringLiteral(
"font" ) ) );
183 backgroundColor.setNamedColor( elem.attribute( QStringLiteral(
"backgroundColor" ) ) );
184 backgroundColor.setAlpha( elem.attribute( QStringLiteral(
"backgroundAlpha" ) ).toInt() );
185 size.setWidth( elem.attribute( QStringLiteral(
"width" ) ).toDouble() );
186 size.setHeight( elem.attribute( QStringLiteral(
"height" ) ).toDouble() );
187 if ( elem.hasAttribute( QStringLiteral(
"transparency" ) ) )
189 opacity = 1 - elem.attribute( QStringLiteral(
"transparency" ), QStringLiteral(
"0" ) ).toInt() / 255.0;
193 opacity = elem.attribute( QStringLiteral(
"opacity" ), QStringLiteral(
"1.00" ) ).toDouble();
196 penColor.setNamedColor( elem.attribute( QStringLiteral(
"penColor" ) ) );
197 const int penAlpha = elem.attribute( QStringLiteral(
"penAlpha" ), QStringLiteral(
"255" ) ).toInt();
199 penWidth = elem.attribute( QStringLiteral(
"penWidth" ) ).toDouble();
201 mDirection =
static_cast< Direction >( elem.attribute( QStringLiteral(
"direction" ), QStringLiteral(
"1" ) ).toInt() );
203 maximumScale = elem.attribute( QStringLiteral(
"minScaleDenominator" ), QStringLiteral(
"-1" ) ).toDouble();
204 minimumScale = elem.attribute( QStringLiteral(
"maxScaleDenominator" ), QStringLiteral(
"-1" ) ).toDouble();
205 if ( elem.hasAttribute( QStringLiteral(
"scaleBasedVisibility" ) ) )
207 scaleBasedVisibility = ( elem.attribute( QStringLiteral(
"scaleBasedVisibility" ), QStringLiteral(
"1" ) ) != QLatin1String(
"0" ) );
215 if ( elem.attribute( QStringLiteral(
"sizeType" ) ) == QLatin1String(
"MapUnits" ) )
230 mSpacing = elem.attribute( QStringLiteral(
"spacing" ) ).toDouble();
235 if ( elem.attribute( QStringLiteral(
"labelPlacementMethod" ) ) == QLatin1String(
"Height" ) )
245 if ( elem.attribute( QStringLiteral(
"diagramOrientation" ) ) == QLatin1String(
"Left" ) )
249 else if ( elem.attribute( QStringLiteral(
"diagramOrientation" ) ) == QLatin1String(
"Right" ) )
253 else if ( elem.attribute( QStringLiteral(
"diagramOrientation" ) ) == QLatin1String(
"Down" ) )
263 if ( elem.attribute( QStringLiteral(
"scaleDependency" ) ) == QLatin1String(
"Diameter" ) )
272 barWidth = elem.attribute( QStringLiteral(
"barWidth" ) ).toDouble();
274 if ( elem.hasAttribute( QStringLiteral(
"angleOffset" ) ) )
275 rotationOffset = std::fmod( 360.0 - elem.attribute( QStringLiteral(
"angleOffset" ) ).toInt() / 16.0, 360.0 );
277 rotationOffset = elem.attribute( QStringLiteral(
"rotationOffset" ) ).toDouble();
279 minimumSize = elem.attribute( QStringLiteral(
"minimumSize" ) ).toDouble();
281 const QDomNodeList axisSymbolNodes = elem.elementsByTagName( QStringLiteral(
"axisSymbol" ) );
282 if ( axisSymbolNodes.count() > 0 )
284 const QDomElement axisSymbolElem = axisSymbolNodes.at( 0 ).toElement().firstChildElement();
285 mAxisLineSymbol.reset( QgsSymbolLayerUtils::loadSymbol<QgsLineSymbol>( axisSymbolElem, context ) );
289 mAxisLineSymbol = std::make_unique< QgsLineSymbol >();
292 mShowAxis = elem.attribute( QStringLiteral(
"showAxis" ), QStringLiteral(
"0" ) ).toInt();
296 const QDomNodeList attributes = elem.elementsByTagName( QStringLiteral(
"attribute" ) );
299 if ( attributes.length() > 0 )
301 for (
int i = 0; i < attributes.size(); i++ )
303 const QDomElement attrElem = attributes.at( i ).toElement();
304 QColor newColor( attrElem.attribute( QStringLiteral(
"color" ) ) );
305 newColor.setAlphaF( attrElem.attribute( QStringLiteral(
"colorOpacity" ), QStringLiteral(
"1.0" ) ).toDouble() );
308 categoryLabels.append( attrElem.attribute( QStringLiteral(
"label" ) ) );
319 const QStringList colorList = elem.attribute( QStringLiteral(
"colors" ) ).split(
'/' );
320 QStringList::const_iterator colorIt = colorList.constBegin();
321 for ( ; colorIt != colorList.constEnd(); ++colorIt )
323 QColor newColor( *colorIt );
329 const QStringList catList = elem.attribute( QStringLiteral(
"categories" ) ).split(
'/' );
330 QStringList::const_iterator catIt = catList.constBegin();
331 for ( ; catIt != catList.constEnd(); ++catIt )
338 const QDomElement effectElem = elem.firstChildElement( QStringLiteral(
"effect" ) );
339 if ( !effectElem.isNull() )
347 QDomElement categoryElem = doc.createElement( QStringLiteral(
"DiagramCategory" ) );
348 categoryElem.setAttribute( QStringLiteral(
"enabled" ),
enabled );
350 categoryElem.setAttribute( QStringLiteral(
"backgroundColor" ),
backgroundColor.name() );
351 categoryElem.setAttribute( QStringLiteral(
"backgroundAlpha" ),
backgroundColor.alpha() );
352 categoryElem.setAttribute( QStringLiteral(
"width" ), QString::number(
size.width() ) );
353 categoryElem.setAttribute( QStringLiteral(
"height" ), QString::number(
size.height() ) );
354 categoryElem.setAttribute( QStringLiteral(
"penColor" ),
penColor.name() );
355 categoryElem.setAttribute( QStringLiteral(
"penAlpha" ),
penColor.alpha() );
356 categoryElem.setAttribute( QStringLiteral(
"penWidth" ), QString::number(
penWidth ) );
358 categoryElem.setAttribute( QStringLiteral(
"minScaleDenominator" ), QString::number(
maximumScale ) );
359 categoryElem.setAttribute( QStringLiteral(
"maxScaleDenominator" ), QString::number(
minimumScale ) );
360 categoryElem.setAttribute( QStringLiteral(
"opacity" ), QString::number(
opacity ) );
361 categoryElem.setAttribute( QStringLiteral(
"spacing" ), QString::number( mSpacing ) );
364 categoryElem.setAttribute( QStringLiteral(
"direction" ), QString::number( mDirection ) );
377 categoryElem.setAttribute( QStringLiteral(
"labelPlacementMethod" ), QStringLiteral(
"Height" ) );
381 categoryElem.setAttribute( QStringLiteral(
"labelPlacementMethod" ), QStringLiteral(
"XHeight" ) );
386 categoryElem.setAttribute( QStringLiteral(
"scaleDependency" ), QStringLiteral(
"Area" ) );
390 categoryElem.setAttribute( QStringLiteral(
"scaleDependency" ), QStringLiteral(
"Diameter" ) );
397 categoryElem.setAttribute( QStringLiteral(
"diagramOrientation" ), QStringLiteral(
"Left" ) );
401 categoryElem.setAttribute( QStringLiteral(
"diagramOrientation" ), QStringLiteral(
"Right" ) );
405 categoryElem.setAttribute( QStringLiteral(
"diagramOrientation" ), QStringLiteral(
"Down" ) );
409 categoryElem.setAttribute( QStringLiteral(
"diagramOrientation" ), QStringLiteral(
"Up" ) );
413 categoryElem.setAttribute( QStringLiteral(
"barWidth" ), QString::number(
barWidth ) );
414 categoryElem.setAttribute( QStringLiteral(
"minimumSize" ), QString::number(
minimumSize ) );
415 categoryElem.setAttribute( QStringLiteral(
"rotationOffset" ), QString::number(
rotationOffset ) );
418 for (
int i = 0; i < nCats; ++i )
420 QDomElement attributeElem = doc.createElement( QStringLiteral(
"attribute" ) );
423 attributeElem.setAttribute( QStringLiteral(
"color" ),
categoryColors.at( i ).name() );
424 attributeElem.setAttribute( QStringLiteral(
"colorOpacity" ), QString::number(
categoryColors.at( i ).alphaF() ) );
425 attributeElem.setAttribute( QStringLiteral(
"label" ),
categoryLabels.at( i ) );
426 categoryElem.appendChild( attributeElem );
429 categoryElem.setAttribute( QStringLiteral(
"showAxis" ), mShowAxis ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
430 QDomElement axisSymbolElem = doc.createElement( QStringLiteral(
"axisSymbol" ) );
432 axisSymbolElem.appendChild( symbolElem );
433 categoryElem.appendChild( axisSymbolElem );
436 mPaintEffect->saveProperties( doc, categoryElem );
438 rendererElem.appendChild( categoryElem );
450 : mDiagram( other.mDiagram ? other.mDiagram->clone() : nullptr )
451 , mShowAttributeLegend( other.mShowAttributeLegend )
481 c.expressionContext().setOriginalValueVariable( s.
penWidth );
488 std::unique_ptr< QgsEffectPainter > effectPainter;
489 if ( effect && effect->
enabled() )
491 effectPainter = std::make_unique< QgsEffectPainter >(
c, effect );
494 mDiagram->renderDiagram( feature,
c, s, pos );
506 if ( size.isValid() )
509 size.rheight() *= width / size.width();
510 size.setWidth( width );
517 QSet< QString > referenced;
523 for (
const QString &att : constDiagramAttributes )
527 for (
const QString &
field : constReferencedColumns )
537 if ( !size.isValid() )
543 size.rwidth() *= pixelToMap;
544 size.rheight() *= pixelToMap;
551 QPaintDevice *device = painter->device();
554 return device->logicalDpiX();
564 const QString diagramType = elem.attribute( QStringLiteral(
"diagramType" ) );
565 if ( diagramType == QLatin1String(
"Pie" ) )
569 else if ( diagramType == QLatin1String(
"Text" ) )
573 else if ( diagramType == QLatin1String(
"Histogram" ) )
577 else if ( diagramType == QLatin1String(
"Stacked" ) )
586 mShowAttributeLegend = ( elem.attribute( QStringLiteral(
"attributeLegend" ), QStringLiteral(
"1" ) ) != QLatin1String(
"0" ) );
596 rendererElem.setAttribute( QStringLiteral(
"diagramType" ),
mDiagram->diagramName() );
620 QList<QgsDiagramSettings> settingsList;
621 settingsList.push_back( mSettings );
627 const QDomElement categoryElem = elem.firstChildElement( QStringLiteral(
"DiagramCategory" ) );
628 if ( categoryElem.isNull() )
633 mSettings.
readXml( categoryElem, context );
639 QDomElement rendererElem = doc.createElement( QStringLiteral(
"SingleCategoryDiagramRenderer" ) );
640 mSettings.
writeXml( rendererElem, doc, context );
642 layerElem.appendChild( rendererElem );
653 , mSettings( other.mSettings )
654 , mInterpolationSettings( other.mInterpolationSettings )
655 , mDataDefinedSizeLegend( other.mDataDefinedSizeLegend ? new
QgsDataDefinedSizeLegend( *other.mDataDefinedSizeLegend ) : nullptr )
661 delete mDataDefinedSizeLegend;
666 if ( &other ==
this )
670 mSettings = other.mSettings;
671 mInterpolationSettings = other.mInterpolationSettings;
672 delete mDataDefinedSizeLegend;
684 QList<QgsDiagramSettings> settingsList;
685 settingsList.push_back( mSettings );
708 for (
const QString &
field : constReferencedColumns )
722 return mDiagram->diagramSize( feature,
c, mSettings, mInterpolationSettings );
727 mInterpolationSettings.
lowerValue = elem.attribute( QStringLiteral(
"lowerValue" ) ).toDouble();
728 mInterpolationSettings.
upperValue = elem.attribute( QStringLiteral(
"upperValue" ) ).toDouble();
729 mInterpolationSettings.
lowerSize.setWidth( elem.attribute( QStringLiteral(
"lowerWidth" ) ).toDouble() );
730 mInterpolationSettings.
lowerSize.setHeight( elem.attribute( QStringLiteral(
"lowerHeight" ) ).toDouble() );
731 mInterpolationSettings.
upperSize.setWidth( elem.attribute( QStringLiteral(
"upperWidth" ) ).toDouble() );
732 mInterpolationSettings.
upperSize.setHeight( elem.attribute( QStringLiteral(
"upperHeight" ) ).toDouble() );
740 mInterpolationSettings.
classificationField = elem.attribute( QStringLiteral(
"classificationField" ) );
742 const QDomElement settingsElem = elem.firstChildElement( QStringLiteral(
"DiagramCategory" ) );
743 if ( !settingsElem.isNull() )
745 mSettings.
readXml( settingsElem );
748 delete mDataDefinedSizeLegend;
750 const QDomElement ddsLegendSizeElem = elem.firstChildElement( QStringLiteral(
"data-defined-size-legend" ) );
751 if ( !ddsLegendSizeElem.isNull() )
758 if ( elem.attribute( QStringLiteral(
"sizeLegend" ), QStringLiteral(
"0" ) ) != QLatin1String(
"0" ) )
761 const QDomElement sizeLegendSymbolElem = elem.firstChildElement( QStringLiteral(
"symbol" ) );
762 if ( !sizeLegendSymbolElem.isNull() && sizeLegendSymbolElem.attribute( QStringLiteral(
"name" ) ) == QLatin1String(
"sizeSymbol" ) )
764 mDataDefinedSizeLegend->
setSymbol( QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( sizeLegendSymbolElem, context ) );
769 mDataDefinedSizeLegend =
nullptr;
778 QDomElement rendererElem = doc.createElement( QStringLiteral(
"LinearlyInterpolatedDiagramRenderer" ) );
779 rendererElem.setAttribute( QStringLiteral(
"lowerValue" ), QString::number( mInterpolationSettings.
lowerValue ) );
780 rendererElem.setAttribute( QStringLiteral(
"upperValue" ), QString::number( mInterpolationSettings.
upperValue ) );
781 rendererElem.setAttribute( QStringLiteral(
"lowerWidth" ), QString::number( mInterpolationSettings.
lowerSize.width() ) );
782 rendererElem.setAttribute( QStringLiteral(
"lowerHeight" ), QString::number( mInterpolationSettings.
lowerSize.height() ) );
783 rendererElem.setAttribute( QStringLiteral(
"upperWidth" ), QString::number( mInterpolationSettings.
upperSize.width() ) );
784 rendererElem.setAttribute( QStringLiteral(
"upperHeight" ), QString::number( mInterpolationSettings.
upperSize.height() ) );
791 rendererElem.setAttribute( QStringLiteral(
"classificationField" ), mInterpolationSettings.
classificationField );
793 mSettings.
writeXml( rendererElem, doc );
795 if ( mDataDefinedSizeLegend )
797 QDomElement ddsLegendElem = doc.createElement( QStringLiteral(
"data-defined-size-legend" ) );
798 mDataDefinedSizeLegend->
writeXml( ddsLegendElem, context );
799 rendererElem.appendChild( ddsLegendElem );
803 layerElem.appendChild( rendererElem );
808 QList< QgsLayerTreeModelLegendNode * > list;
812 QPixmap pix( 16, 16 );
821 return mAxisLineSymbol.get();
842 return mPaintEffect.get();
847 if ( effect != mPaintEffect.get() )
848 mPaintEffect.reset( effect );
859 : enabled( other.enabled )
861 , categoryColors( other.categoryColors )
862 , categoryAttributes( other.categoryAttributes )
863 , categoryLabels( other.categoryLabels )
865 , sizeType( other.sizeType )
866 , sizeScale( other.sizeScale )
867 , lineSizeUnit( other.lineSizeUnit )
868 , lineSizeScale( other.lineSizeScale )
869 , backgroundColor( other.backgroundColor )
870 , penColor( other.penColor )
871 , penWidth( other.penWidth )
872 , labelPlacementMethod( other.labelPlacementMethod )
873 , diagramOrientation( other.diagramOrientation )
874 , barWidth( other.barWidth )
875 , opacity( other.opacity )
876 , scaleByArea( other.scaleByArea )
877 , rotationOffset( other.rotationOffset )
878 , scaleBasedVisibility( other.scaleBasedVisibility )
879 , maximumScale( other.maximumScale )
880 , minimumScale( other.minimumScale )
881 , minimumSize( other.minimumSize )
882 , mSpacing( other.mSpacing )
883 , mSpacingUnit( other.mSpacingUnit )
884 , mSpacingMapUnitScale( other.mSpacingMapUnitScale )
885 , mDirection( other.mDirection )
886 , mShowAxis( other.mShowAxis )
887 , mAxisLineSymbol( other.mAxisLineSymbol ? other.mAxisLineSymbol->clone() : nullptr )
888 , mPaintEffect( other.mPaintEffect ? other.mPaintEffect->clone() : nullptr )
918 mSpacing = other.mSpacing;
919 mSpacingUnit = other.mSpacingUnit;
920 mSpacingMapUnitScale = other.mSpacingMapUnitScale;
921 mDirection = other.mDirection;
922 mAxisLineSymbol.reset( other.mAxisLineSymbol ? other.mAxisLineSymbol->clone() :
nullptr );
923 mShowAxis = other.mShowAxis;
924 mPaintEffect.reset( other.mPaintEffect ? other.mPaintEffect->clone() :
nullptr );
940 return QList< QgsLayerTreeModelLegendNode * >();
945 QList< QgsLayerTreeModelLegendNode * > nodes;
954 QList< QgsLayerTreeModelLegendNode * > nodes;
958 if ( mDataDefinedSizeLegend &&
mDiagram )
968 QList<QgsDataDefinedSizeLegend::SizeClass> sizeClasses;
969 if ( ddSizeLegend.
classes().isEmpty() )
973 for (
const double v : prettyBreaks )
975 const double size =
mDiagram->legendSize( v, mSettings, mInterpolationSettings );
982 const auto constClasses = ddSizeLegend.
classes();
985 const double size =
mDiagram->legendSize( sc.size, mSettings, mInterpolationSettings );
994 if (
auto *lDataDefinedSizeLegendSettings = si.dataDefinedSizeLegendSettings() )
1006 delete mDataDefinedSizeLegend;
1007 mDataDefinedSizeLegend = settings;
1012 return mDataDefinedSizeLegend;