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() )
92 mSizeClasses <<
SizeClass( v, QString::number( v ) );
100 if ( !mTitleLabel.isEmpty() )
115 Q_FOREACH (
const SizeClass &cl, mSizeClasses )
132 *outputSize = QSize();
139 double hLengthLineMM = 2;
140 double hSpaceLineTextMM = 1;
142 std::unique_ptr<QgsMarkerSymbol> s( mSymbol->clone() );
144 QList<SizeClass>
classes = mSizeClasses;
147 if ( mSizeScaleTransformer )
149 for (
auto it = classes.begin(); it != classes.end(); ++it )
150 it->size = mSizeScaleTransformer->size( it->size );
154 std::sort( classes.begin(), classes.end(), [](
const SizeClass & a,
const SizeClass & b ) {
return a.
size > b.size; } );
158 int dpm = std::round( context.
scaleFactor() * 1000 );
161 QImage tmpImg( QSize( 1, 1 ), QImage::Format_ARGB32_Premultiplied );
162 tmpImg.setDotsPerMeterX( dpm );
163 tmpImg.setDotsPerMeterY( dpm );
164 QFontMetrics fm( mFont, &tmpImg );
165 int textHeight = fm.height();
166 int leading = fm.leading();
167 int minTextDistY = textHeight + leading;
174 int maxTextWidth = 0;
175 Q_FOREACH (
const SizeClass &c, classes )
177 int w = fm.width( c.
label );
178 if ( w > maxTextWidth )
183 double largestSize = classes.at( 0 ).size;
184 double outputLargestSize = context.
convertToPainterUnits( largestSize, s->sizeUnit(), s->sizeMapUnitScale() );
187 QList<int> symbolTopY;
188 Q_FOREACH (
const SizeClass &c, classes )
194 symbolTopY << std::round( outputLargestSize / 2 - outputSymbolSize / 2 );
197 symbolTopY << std::round( outputLargestSize - outputSymbolSize );
205 QList<int> textCenterY;
206 int lastY = symbolTopY[middleIndex];
207 textCenterY << lastY;
208 for (
int i = middleIndex + 1; i < classes.count(); ++i )
210 int symbolY = symbolTopY[i];
211 if ( symbolY - lastY < minTextDistY )
212 symbolY = lastY + minTextDistY;
213 textCenterY << symbolY;
217 int textTopY = textCenterY.first() - textHeight / 2;
218 int textBottomY = textCenterY.last() + textHeight / 2;
219 int totalTextHeight = textBottomY - textTopY;
221 int fullWidth = outputLargestSize + hLengthLine + hSpaceLineText + maxTextWidth;
222 int fullHeight = std::max( static_cast< int >( std::round( outputLargestSize ) ) - textTopY, totalTextHeight );
225 *outputSize = QSize( fullWidth, fullHeight );
227 *labelXOffset = outputLargestSize + hLengthLine + hSpaceLineText;
236 QPainter *p = context.
painter();
239 p->translate( 0, -textTopY );
242 Q_FOREACH (
const SizeClass &c, classes )
244 s->setSize( c.
size );
247 double tx = ( outputLargestSize - outputSymbolSize ) / 2;
253 p->translate( tx, ( outputLargestSize - outputSymbolSize ) / 2 );
256 p->translate( tx, outputLargestSize - outputSymbolSize );
259 s->drawPreviewIcon( p, QSize( outputSymbolSize, outputSymbolSize ) );
263 p->setPen( mTextColor );
267 Q_FOREACH (
const SizeClass &c, classes )
270 p->drawLine( outputLargestSize / 2, symbolTopY[i], outputLargestSize + hLengthLine, textCenterY[i] );
273 QRect rect( outputLargestSize + hLengthLine + hSpaceLineText, textCenterY[i] - textHeight / 2,
274 maxTextWidth, textHeight );
275 p->drawText( rect, mTextAlignment, c.
label );
293 int dpm = std::round( context.
scaleFactor() * 1000 );
295 QImage img( contentSize.width() + padding * 2, contentSize.height() + padding * 2, QImage::Format_ARGB32_Premultiplied );
296 img.setDotsPerMeterX( dpm );
297 img.setDotsPerMeterY( dpm );
298 img.fill( backgroundColor );
300 QPainter painter( &img );
301 painter.setRenderHint( QPainter::Antialiasing,
true );
303 painter.translate( padding, padding );
306 QPainter *oldPainter = context.
painter();
322 ddsLegend->
setTitle( elem.attribute( QStringLiteral(
"title" ) ) );
324 QDomElement elemSymbol = elem.firstChildElement( QStringLiteral(
"symbol" ) );
325 if ( !elemSymbol.isNull() )
327 ddsLegend->
setSymbol( QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( elemSymbol, context ) );
331 QDomElement elemTransformer = elem.firstChildElement( QStringLiteral(
"transformer" ) );
332 if ( !elemTransformer.isNull() )
339 QDomElement elemTextStyle = elem.firstChildElement( QStringLiteral(
"text-style" ) );
340 if ( !elemTextStyle.isNull() )
342 QDomElement elemFont = elemTextStyle.firstChildElement( QStringLiteral(
"font" ) );
343 if ( !elemFont.isNull() )
345 ddsLegend->
setFont( QFont( elemFont.attribute( QStringLiteral(
"family" ) ), elemFont.attribute( QStringLiteral(
"size" ) ).toInt(),
346 elemFont.attribute( QStringLiteral(
"weight" ) ).toInt(), elemFont.attribute( QStringLiteral(
"italic" ) ).toInt() ) );
349 ddsLegend->
setTextAlignment( static_cast<Qt::AlignmentFlag>( elemTextStyle.attribute( QStringLiteral(
"align" ) ).toInt() ) );
352 QDomElement elemClasses = elem.firstChildElement( QStringLiteral(
"classes" ) );
353 if ( !elemClasses.isNull() )
356 QDomElement elemClass = elemClasses.firstChildElement( QStringLiteral(
"class" ) );
357 while ( !elemClass.isNull() )
359 classes <<
SizeClass( elemClass.attribute( QStringLiteral(
"size" ) ).toDouble(), elemClass.attribute( QStringLiteral(
"label" ) ) );
360 elemClass = elemClass.nextSiblingElement();
370 QDomDocument doc = elem.ownerDocument();
372 elem.setAttribute( QStringLiteral(
"type" ), mType ==
LegendCollapsed ?
"collapsed" :
"separated" );
373 elem.setAttribute( QStringLiteral(
"valign" ), mVAlign ==
AlignCenter ?
"center" :
"bottom" );
374 elem.setAttribute( QStringLiteral(
"title" ), mTitleLabel );
379 elem.appendChild( elemSymbol );
382 if ( mSizeScaleTransformer )
385 elemTransformer.setTagName( QStringLiteral(
"transformer" ) );
386 elem.appendChild( elemTransformer );
389 QDomElement elemFont = doc.createElement( QStringLiteral(
"font" ) );
390 elemFont.setAttribute( QStringLiteral(
"family" ), mFont.family() );
391 elemFont.setAttribute( QStringLiteral(
"size" ), mFont.pointSize() );
392 elemFont.setAttribute( QStringLiteral(
"weight" ), mFont.weight() );
393 elemFont.setAttribute( QStringLiteral(
"italic" ), mFont.italic() );
395 QDomElement elemTextStyle = doc.createElement( QStringLiteral(
"text-style" ) );
397 elemTextStyle.setAttribute( QStringLiteral(
"align" ), static_cast<int>( mTextAlignment ) );
398 elemTextStyle.appendChild( elemFont );
399 elem.appendChild( elemTextStyle );
401 if ( !mSizeClasses.isEmpty() )
403 QDomElement elemClasses = doc.createElement( QStringLiteral(
"classes" ) );
404 Q_FOREACH (
const SizeClass &sc, mSizeClasses )
406 QDomElement elemClass = doc.createElement( QStringLiteral(
"class" ) );
407 elemClass.setAttribute( QStringLiteral(
"size" ), sc.
size );
408 elemClass.setAttribute( QStringLiteral(
"label" ), sc.
label );
409 elemClasses.appendChild( elemClass );
411 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.
QString label
Label to be shown with the particular symbol size.
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.
const QgsPropertyTransformer * transformer() const
Returns the existing transformer used for manipulating the calculated values for the property...
static QString encodeColor(const QColor &color)
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 null 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 null pointer to ...
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 null 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
Get 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...