25 : mType( other.mType )
26 , mTitleLabel( other.mTitleLabel )
27 , mSizeClasses( other.mSizeClasses )
28 , mSymbol( other.mSymbol.get() ? other.mSymbol->clone() : nullptr )
29 , mSizeScaleTransformer( other.mSizeScaleTransformer.get() ? new
QgsSizeScaleTransformer( *other.mSizeScaleTransformer ) : nullptr )
30 , mVAlign( other.mVAlign )
31 , mFont( other.mFont )
32 , mTextColor( other.mTextColor )
33 , mTextAlignment( other.mTextAlignment )
42 mTitleLabel = other.mTitleLabel;
43 mSizeClasses = other.mSizeClasses;
44 mSymbol.reset( other.mSymbol.get() ? other.mSymbol->clone() : nullptr );
45 mSizeScaleTransformer.reset( other.mSizeScaleTransformer.get() ?
new QgsSizeScaleTransformer( *other.mSizeScaleTransformer ) : nullptr );
46 mVAlign = other.mVAlign;
48 mTextColor = other.mTextColor;
49 mTextAlignment = other.mTextAlignment;
56 mSymbol.reset( symbol );
66 mSizeScaleTransformer.reset( transformer );
71 return mSizeScaleTransformer.get();
77 mSymbol.reset( symbol->
clone() );
81 mSizeScaleTransformer.reset( sizeTransformer ? sizeTransformer->
clone() : nullptr );
83 if ( mTitleLabel.isEmpty() )
87 if ( sizeTransformer && mSizeClasses.isEmpty() )
91 for (
double v : prettyBreaks )
93 mSizeClasses <<
SizeClass( v, QString::number( v ) );
101 if ( !mTitleLabel.isEmpty() )
116 const auto constMSizeClasses = mSizeClasses;
117 for (
const SizeClass &cl : constMSizeClasses )
134 *outputSize = QSize();
141 double hLengthLineMM = 2;
142 double hSpaceLineTextMM = 1;
144 std::unique_ptr<QgsMarkerSymbol> s( mSymbol->clone() );
146 QList<SizeClass>
classes = mSizeClasses;
149 if ( mSizeScaleTransformer )
152 cls.size = mSizeScaleTransformer->size( cls.size );
156 std::sort( classes.begin(), classes.end(), [](
const SizeClass & a,
const SizeClass & b ) {
return a.
size > b.size; } );
160 int dpm = std::round( context.
scaleFactor() * 1000 );
163 QImage tmpImg( QSize( 1, 1 ), QImage::Format_ARGB32_Premultiplied );
164 tmpImg.setDotsPerMeterX( dpm );
165 tmpImg.setDotsPerMeterY( dpm );
166 QFontMetrics fm( mFont, &tmpImg );
167 int textHeight = fm.height();
168 int leading = fm.leading();
169 int minTextDistY = textHeight + leading;
176 int maxTextWidth = 0;
177 for (
const SizeClass &
c : qgis::as_const( classes ) )
179 int w = fm.width(
c.label );
180 if ( w > maxTextWidth )
187 double largestSize = classes.at( 0 ).size;
188 int outputLargestSize = std::round( context.
convertToPainterUnits( largestSize, s->sizeUnit(), s->sizeMapUnitScale() ) );
191 QList<int> symbolTopY;
192 for (
const SizeClass &
c : qgis::as_const( classes ) )
194 int outputSymbolSize = std::round( context.
convertToPainterUnits(
c.size, s->sizeUnit(), s->sizeMapUnitScale() ) );
198 symbolTopY << std::round( outputLargestSize / 2 - outputSymbolSize / 2 );
201 symbolTopY << std::round( outputLargestSize - outputSymbolSize );
209 QList<int> textCenterY;
210 int lastY = symbolTopY[middleIndex];
211 textCenterY << lastY;
212 for (
int i = middleIndex + 1; i < classes.count(); ++i )
214 int symbolY = symbolTopY[i];
215 if ( symbolY - lastY < minTextDistY )
216 symbolY = lastY + minTextDistY;
217 textCenterY << symbolY;
221 int textTopY = textCenterY.first() - textHeight / 2;
222 int textBottomY = textCenterY.last() + textHeight / 2;
223 int totalTextHeight = textBottomY - textTopY;
225 int fullWidth = outputLargestSize + hLengthLine + hSpaceLineText + maxTextWidth;
226 int fullHeight = std::max( static_cast< int >( std::round( outputLargestSize ) ) - textTopY, totalTextHeight );
229 *outputSize = QSize( fullWidth, fullHeight );
231 *labelXOffset = outputLargestSize + hLengthLine + hSpaceLineText;
240 QPainter *p = context.
painter();
243 p->translate( 0, -textTopY );
246 for (
const SizeClass &
c : qgis::as_const( classes ) )
248 s->setSize(
c.size );
250 int outputSymbolSize = std::round( context.
convertToPainterUnits(
c.size, s->sizeUnit(), s->sizeMapUnitScale() ) );
251 double tx = ( outputLargestSize - outputSymbolSize ) / 2;
257 p->translate( tx, ( outputLargestSize - outputSymbolSize ) / 2 );
260 p->translate( tx, outputLargestSize - outputSymbolSize );
263 s->drawPreviewIcon( p, QSize( outputSymbolSize, outputSymbolSize ) );
267 p->setPen( mTextColor );
271 for (
const SizeClass &
c : qgis::as_const( classes ) )
274 p->drawLine( outputLargestSize / 2, symbolTopY[i], outputLargestSize + hLengthLine, textCenterY[i] );
277 QRect rect( outputLargestSize + hLengthLine + hSpaceLineText, textCenterY[i] - textHeight / 2,
278 maxTextWidth, textHeight );
279 p->drawText( rect, mTextAlignment,
c.label );
297 int dpm = std::round( context.
scaleFactor() * 1000 );
299 QImage img( contentSize.width() + padding * 2, contentSize.height() + padding * 2, QImage::Format_ARGB32_Premultiplied );
300 img.setDotsPerMeterX( dpm );
301 img.setDotsPerMeterY( dpm );
302 img.fill( backgroundColor );
304 QPainter painter( &img );
305 painter.setRenderHint( QPainter::Antialiasing,
true );
307 painter.translate( padding, padding );
310 QPainter *oldPainter = context.
painter();
326 ddsLegend->
setTitle( elem.attribute( QStringLiteral(
"title" ) ) );
328 QDomElement elemSymbol = elem.firstChildElement( QStringLiteral(
"symbol" ) );
329 if ( !elemSymbol.isNull() )
331 ddsLegend->
setSymbol( QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( elemSymbol, context ) );
335 QDomElement elemTransformer = elem.firstChildElement( QStringLiteral(
"transformer" ) );
336 if ( !elemTransformer.isNull() )
343 QDomElement elemTextStyle = elem.firstChildElement( QStringLiteral(
"text-style" ) );
344 if ( !elemTextStyle.isNull() )
346 QDomElement elemFont = elemTextStyle.firstChildElement( QStringLiteral(
"font" ) );
347 if ( !elemFont.isNull() )
349 ddsLegend->
setFont( QFont( elemFont.attribute( QStringLiteral(
"family" ) ), elemFont.attribute( QStringLiteral(
"size" ) ).toInt(),
350 elemFont.attribute( QStringLiteral(
"weight" ) ).toInt(), elemFont.attribute( QStringLiteral(
"italic" ) ).toInt() ) );
353 ddsLegend->
setTextAlignment( static_cast<Qt::AlignmentFlag>( elemTextStyle.attribute( QStringLiteral(
"align" ) ).toInt() ) );
356 QDomElement elemClasses = elem.firstChildElement( QStringLiteral(
"classes" ) );
357 if ( !elemClasses.isNull() )
360 QDomElement elemClass = elemClasses.firstChildElement( QStringLiteral(
"class" ) );
361 while ( !elemClass.isNull() )
363 classes <<
SizeClass( elemClass.attribute( QStringLiteral(
"size" ) ).toDouble(), elemClass.attribute( QStringLiteral(
"label" ) ) );
364 elemClass = elemClass.nextSiblingElement();
374 QDomDocument doc = elem.ownerDocument();
376 elem.setAttribute( QStringLiteral(
"type" ), mType ==
LegendCollapsed ?
"collapsed" :
"separated" );
377 elem.setAttribute( QStringLiteral(
"valign" ), mVAlign ==
AlignCenter ?
"center" :
"bottom" );
378 elem.setAttribute( QStringLiteral(
"title" ), mTitleLabel );
383 elem.appendChild( elemSymbol );
386 if ( mSizeScaleTransformer )
389 elemTransformer.setTagName( QStringLiteral(
"transformer" ) );
390 elem.appendChild( elemTransformer );
393 QDomElement elemFont = doc.createElement( QStringLiteral(
"font" ) );
394 elemFont.setAttribute( QStringLiteral(
"family" ), mFont.family() );
395 elemFont.setAttribute( QStringLiteral(
"size" ), mFont.pointSize() );
396 elemFont.setAttribute( QStringLiteral(
"weight" ), mFont.weight() );
397 elemFont.setAttribute( QStringLiteral(
"italic" ), mFont.italic() );
399 QDomElement elemTextStyle = doc.createElement( QStringLiteral(
"text-style" ) );
401 elemTextStyle.setAttribute( QStringLiteral(
"align" ), static_cast<int>( mTextAlignment ) );
402 elemTextStyle.appendChild( elemFont );
403 elem.appendChild( elemTextStyle );
405 if ( !mSizeClasses.isEmpty() )
407 QDomElement elemClasses = doc.createElement( QStringLiteral(
"classes" ) );
408 for (
const SizeClass &sc : qgis::as_const( mSizeClasses ) )
410 QDomElement elemClass = doc.createElement( QStringLiteral(
"class" ) );
411 elemClass.setAttribute( QStringLiteral(
"size" ), sc.size );
412 elemClass.setAttribute( QStringLiteral(
"label" ), sc.label );
413 elemClasses.appendChild( elemClass );
415 elem.appendChild( elemClasses );
The class is used as a container of context for various read/write operations on other objects...
Symbols are aligned to the center.
Each class (size value) has a separate legend node.
QList< QgsLegendSymbolItem > QgsLegendSymbolList
void setTextAlignment(Qt::AlignmentFlag flag)
Sets horizontal text alignment for rendering of labels - only valid for collapsed legend...
void setFont(const QFont &font)
Sets font used for rendering of labels - only valid for collapsed legend.
Definition of one class for the legend.
Expression based property (QgsExpressionBasedProperty)
QgsDataDefinedSizeLegend & operator=(const QgsDataDefinedSizeLegend &other)
void setSize(double size)
Sets the size for the whole symbol.
QgsLegendSymbolList legendSymbolList() const
Generates legend symbol items according to the configuration.
void setTitle(const QString &title)
Sets title label for data-defined size legend.
void setLegendType(LegendType type)
Sets how the legend should be rendered.
QgsMarkerSymbol * symbol() const
Returns marker symbol that will be used to draw markers in legend.
A marker symbol type, for rendering Point and MultiPoint geometries.
const QgsPropertyTransformer * transformer() const
Returns the existing transformer used for manipulating the calculated values for the property...
static QString encodeColor(const QColor &color)
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
QString expressionString() const
Returns the expression used for the property value.
QImage collapsedLegendImage(QgsRenderContext &context, const QColor &backgroundColor=Qt::transparent, double paddingMM=1) const
Returns output image that would be shown in the legend. Returns invalid image if legend is not config...
static QVariant readVariant(const QDomElement &element)
Read a QVariant from a QDomElement.
Type propertyType() const
Returns the property type.
QList< QgsDataDefinedSizeLegend::SizeClass > classes() const
Returns list of classes: each class is a pair of symbol size (in units used by the symbol) and label...
QgsSizeScaleTransformer * sizeScaleTransformer() const
Returns transformer for scaling of symbol sizes. Returns nullptr if no transformer is defined...
QgsDataDefinedSizeLegend()=default
Constructor for QgsDataDefinedSizeLegend.
double size
Marker size in units used by the symbol (usually millimeters). May be further scaled before rendering...
void setPainter(QPainter *p)
Sets the destination QPainter for the render operation.
void updateFromSymbolAndProperty(const QgsMarkerSymbol *symbol, const QgsProperty &ddSize)
Updates the list of classes, source symbol and title label from given symbol and property.
void setSizeScaleTransformer(QgsSizeScaleTransformer *transformer SIP_TRANSFER)
Sets transformer for scaling of symbol sizes. Takes ownership of the object. Accepts nullptr to set n...
A store for object properties.
void writeXml(QDomElement &elem, const QgsReadWriteContext &context) const
Writes configuration to the given XML element.
QString field() const
Returns the current field name the property references.
void setVerticalAlignment(VerticalAlignment vAlign)
Sets vertical alignment of symbols - only valid for collapsed legend.
Symbols are aligned to the bottom.
static QList< double > prettyBreaks(double minimum, double maximum, int classes)
Computes a sequence of about 'classes' equally spaced round values which cover the range of values fr...
The class stores information about one class/rule of a vector layer renderer in a unified way that ca...
Contains information about the context of a rendering operation.
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to painter units (pixels).
QPainter * painter()
Returns the destination QPainter for the render operation.
void setSymbol(QgsMarkerSymbol *symbol SIP_TRANSFER)
Sets marker symbol that will be used to draw markers in legend.
QString title() const
Returns title label for data-defined size legend.
static QDomElement saveSymbol(const QString &symbolName, QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
void setTextColor(const QColor &color)
Sets text color for rendering of labels - only valid for collapsed legend.
void drawCollapsedLegend(QgsRenderContext &context, QSize *outputSize SIP_OUT=nullptr, int *labelXOffset SIP_OUT=nullptr) const
Draw the legend if using LegendOneNodeForAll and optionally output size of the legend and x offset of...
double scaleFactor() const
Returns the scaling factor for the render to convert painter units to physical sizes.
Object that keeps configuration of appearance of marker symbol's data-defined size in legend...
All classes are rendered within one legend node.
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...
void setDataDefinedSizeLegendSettings(QgsDataDefinedSizeLegend *settings)
Sets extra information about data-defined size.
static QDomElement writeVariant(const QVariant &value, QDomDocument &doc)
Write a QVariant to a QDomElement.
QgsMarkerSymbol * clone() const override
Returns a deep copy of this symbol.
static QColor decodeColor(const QString &str)
void setClasses(const QList< QgsDataDefinedSizeLegend::SizeClass > &classes)
Sets list of classes: each class is a pair of symbol size (in units used by the symbol) and label...