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() )
119 lst.reserve( mSizeClasses.size() );
120 for (
const SizeClass &cl : mSizeClasses )
124 double size = cl.
size;
125 if ( mSizeScaleTransformer )
127 size = mSizeScaleTransformer->size( size );
145 *outputSize = QSize();
152 double hLengthLineMM = 2;
153 double hSpaceLineTextMM = 1;
155 std::unique_ptr<QgsMarkerSymbol> s( mSymbol->clone() );
157 QList<SizeClass>
classes = mSizeClasses;
160 if ( mSizeScaleTransformer )
163 cls.size = mSizeScaleTransformer->size( cls.size );
167 std::sort( classes.begin(), classes.end(), [](
const SizeClass & a,
const SizeClass & b ) {
return a.
size > b.size; } );
171 int dpm = std::round( context.
scaleFactor() * 1000 );
174 QImage tmpImg( QSize( 1, 1 ), QImage::Format_ARGB32_Premultiplied );
175 tmpImg.setDotsPerMeterX( dpm );
176 tmpImg.setDotsPerMeterY( dpm );
177 QFontMetrics fm( mFont, &tmpImg );
178 int textHeight = fm.height();
179 int leading = fm.leading();
180 int minTextDistY = textHeight + leading;
187 int maxTextWidth = 0;
188 for (
const SizeClass &
c : qgis::as_const( classes ) )
190 int w = fm.width(
c.label );
191 if ( w > maxTextWidth )
198 double largestSize = classes.at( 0 ).size;
199 int outputLargestSize = std::round( context.
convertToPainterUnits( largestSize, s->sizeUnit(), s->sizeMapUnitScale() ) );
202 QList<int> symbolTopY;
203 for (
const SizeClass &
c : qgis::as_const( classes ) )
205 int outputSymbolSize = std::round( context.
convertToPainterUnits(
c.size, s->sizeUnit(), s->sizeMapUnitScale() ) );
209 symbolTopY << std::round( outputLargestSize / 2 - outputSymbolSize / 2 );
212 symbolTopY << std::round( outputLargestSize - outputSymbolSize );
220 QList<int> textCenterY;
221 int lastY = symbolTopY[middleIndex];
222 textCenterY << lastY;
223 for (
int i = middleIndex + 1; i < classes.count(); ++i )
225 int symbolY = symbolTopY[i];
226 if ( symbolY - lastY < minTextDistY )
227 symbolY = lastY + minTextDistY;
228 textCenterY << symbolY;
232 int textTopY = textCenterY.first() - textHeight / 2;
233 int textBottomY = textCenterY.last() + textHeight / 2;
234 int totalTextHeight = textBottomY - textTopY;
236 int fullWidth = outputLargestSize + hLengthLine + hSpaceLineText + maxTextWidth;
237 int fullHeight = std::max( static_cast< int >( std::round( outputLargestSize ) ) - textTopY, totalTextHeight );
240 *outputSize = QSize( fullWidth, fullHeight );
242 *labelXOffset = outputLargestSize + hLengthLine + hSpaceLineText;
251 QPainter *p = context.
painter();
254 p->translate( 0, -textTopY );
257 for (
const SizeClass &
c : qgis::as_const( classes ) )
259 s->setSize(
c.size );
261 int outputSymbolSize = std::round( context.
convertToPainterUnits(
c.size, s->sizeUnit(), s->sizeMapUnitScale() ) );
262 double tx = ( outputLargestSize - outputSymbolSize ) / 2;
268 p->translate( tx, ( outputLargestSize - outputSymbolSize ) / 2 );
271 p->translate( tx, outputLargestSize - outputSymbolSize );
274 s->drawPreviewIcon( p, QSize( outputSymbolSize, outputSymbolSize ) );
278 p->setPen( mTextColor );
282 for (
const SizeClass &
c : qgis::as_const( classes ) )
285 p->drawLine( outputLargestSize / 2, symbolTopY[i], outputLargestSize + hLengthLine, textCenterY[i] );
288 QRect rect( outputLargestSize + hLengthLine + hSpaceLineText, textCenterY[i] - textHeight / 2,
289 maxTextWidth, textHeight );
290 p->drawText( rect, mTextAlignment,
c.label );
308 int dpm = std::round( context.
scaleFactor() * 1000 );
310 QImage img( contentSize.width() + padding * 2, contentSize.height() + padding * 2, QImage::Format_ARGB32_Premultiplied );
311 img.setDotsPerMeterX( dpm );
312 img.setDotsPerMeterY( dpm );
313 img.fill( backgroundColor );
315 QPainter painter( &img );
316 painter.setRenderHint( QPainter::Antialiasing,
true );
318 painter.translate( padding, padding );
321 QPainter *oldPainter = context.
painter();
337 ddsLegend->
setTitle( elem.attribute( QStringLiteral(
"title" ) ) );
339 QDomElement elemSymbol = elem.firstChildElement( QStringLiteral(
"symbol" ) );
340 if ( !elemSymbol.isNull() )
342 ddsLegend->
setSymbol( QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( elemSymbol, context ) );
346 QDomElement elemTransformer = elem.firstChildElement( QStringLiteral(
"transformer" ) );
347 if ( !elemTransformer.isNull() )
354 QDomElement elemTextStyle = elem.firstChildElement( QStringLiteral(
"text-style" ) );
355 if ( !elemTextStyle.isNull() )
357 QDomElement elemFont = elemTextStyle.firstChildElement( QStringLiteral(
"font" ) );
358 if ( !elemFont.isNull() )
360 ddsLegend->
setFont( QFont( elemFont.attribute( QStringLiteral(
"family" ) ), elemFont.attribute( QStringLiteral(
"size" ) ).toInt(),
361 elemFont.attribute( QStringLiteral(
"weight" ) ).toInt(), elemFont.attribute( QStringLiteral(
"italic" ) ).toInt() ) );
364 ddsLegend->
setTextAlignment( static_cast<Qt::AlignmentFlag>( elemTextStyle.attribute( QStringLiteral(
"align" ) ).toInt() ) );
367 QDomElement elemClasses = elem.firstChildElement( QStringLiteral(
"classes" ) );
368 if ( !elemClasses.isNull() )
371 QDomElement elemClass = elemClasses.firstChildElement( QStringLiteral(
"class" ) );
372 while ( !elemClass.isNull() )
374 classes <<
SizeClass( elemClass.attribute( QStringLiteral(
"size" ) ).toDouble(), elemClass.attribute( QStringLiteral(
"label" ) ) );
375 elemClass = elemClass.nextSiblingElement();
385 QDomDocument doc = elem.ownerDocument();
387 elem.setAttribute( QStringLiteral(
"type" ), mType ==
LegendCollapsed ?
"collapsed" :
"separated" );
388 elem.setAttribute( QStringLiteral(
"valign" ), mVAlign ==
AlignCenter ?
"center" :
"bottom" );
389 elem.setAttribute( QStringLiteral(
"title" ), mTitleLabel );
394 elem.appendChild( elemSymbol );
397 if ( mSizeScaleTransformer )
400 elemTransformer.setTagName( QStringLiteral(
"transformer" ) );
401 elem.appendChild( elemTransformer );
404 QDomElement elemFont = doc.createElement( QStringLiteral(
"font" ) );
405 elemFont.setAttribute( QStringLiteral(
"family" ), mFont.family() );
406 elemFont.setAttribute( QStringLiteral(
"size" ), mFont.pointSize() );
407 elemFont.setAttribute( QStringLiteral(
"weight" ), mFont.weight() );
408 elemFont.setAttribute( QStringLiteral(
"italic" ), mFont.italic() );
410 QDomElement elemTextStyle = doc.createElement( QStringLiteral(
"text-style" ) );
412 elemTextStyle.setAttribute( QStringLiteral(
"align" ), static_cast<int>( mTextAlignment ) );
413 elemTextStyle.appendChild( elemFont );
414 elem.appendChild( elemTextStyle );
416 if ( !mSizeClasses.isEmpty() )
418 QDomElement elemClasses = doc.createElement( QStringLiteral(
"classes" ) );
419 for (
const SizeClass &sc : qgis::as_const( mSizeClasses ) )
421 QDomElement elemClass = doc.createElement( QStringLiteral(
"class" ) );
422 elemClass.setAttribute( QStringLiteral(
"size" ), sc.size );
423 elemClass.setAttribute( QStringLiteral(
"label" ), sc.label );
424 elemClasses.appendChild( elemClass );
426 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)
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
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.
double size() const
Returns the estimated size for the whole symbol, which is the maximum size of all marker symbol layer...
QString title() const
Returns title label for data-defined size legend.
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...