Skip to content
Permalink
Browse files

[legends] Fix corrupted data defined legend rendering in layout designer

Fixes #36765
Fixes #34658
  • Loading branch information
nyalldawson committed Jun 10, 2020
1 parent 98d618b commit 8d00ae8638a09cb9a4c9ecd5d1fec3b352050cdd
@@ -74,6 +74,26 @@ Sets marker symbol that will be used to draw markers in legend
QgsMarkerSymbol *symbol() const;
%Docstring
Returns marker symbol that will be used to draw markers in legend
%End

void setLineSymbol( QgsLineSymbol *symbol /Transfer/ );
%Docstring
Sets the line ``symbol`` that will be used to draw callout lines in legend.

Ownership of ``symbol`` is transferred.

.. seealso:: :py:func:`lineSymbol`

.. versionadded:: 3.14
%End

QgsLineSymbol *lineSymbol() const;
%Docstring
Returns the line symbol that will be used to draw callout lines in legend.

.. seealso:: :py:func:`setLineSymbol`

.. versionadded:: 3.14
%End

void setSizeScaleTransformer( QgsSizeScaleTransformer *transformer /Transfer/ );
@@ -1219,6 +1219,8 @@ QgsLayerTreeModelLegendNode::ItemMetrics QgsDataDefinedSizeLegendNode::draw( con
{
context->painter()->save();
context->painter()->translate( ctx->columnLeft, ctx->top );

// scale to pixels
context->painter()->scale( 1 / context->scaleFactor(), 1 / context->scaleFactor() );
}

@@ -19,9 +19,15 @@
#include "qgspropertytransformer.h"
#include "qgssymbollayerutils.h"
#include "qgsxmlutils.h"
#include "qgslinesymbollayer.h"
#include "qgstextformat.h"
#include "qgstextrenderer.h"


QgsDataDefinedSizeLegend::QgsDataDefinedSizeLegend() = default;
QgsDataDefinedSizeLegend::QgsDataDefinedSizeLegend()
{
std::unique_ptr< QgsSimpleLineSymbolLayer > lineSymbolLayer = qgis::make_unique< QgsSimpleLineSymbolLayer >( QColor( 0, 0, 0 ), 0.2 );
mLineSymbol = qgis::make_unique< QgsLineSymbol >( QgsSymbolLayerList() << lineSymbolLayer.release() );
}

QgsDataDefinedSizeLegend::~QgsDataDefinedSizeLegend() = default;

@@ -30,6 +36,7 @@ QgsDataDefinedSizeLegend::QgsDataDefinedSizeLegend( const QgsDataDefinedSizeLege
, mTitleLabel( other.mTitleLabel )
, mSizeClasses( other.mSizeClasses )
, mSymbol( other.mSymbol.get() ? other.mSymbol->clone() : nullptr )
, mLineSymbol( other.mLineSymbol.get() ? other.mLineSymbol->clone() : nullptr )
, mSizeScaleTransformer( other.mSizeScaleTransformer.get() ? new QgsSizeScaleTransformer( *other.mSizeScaleTransformer ) : nullptr )
, mVAlign( other.mVAlign )
, mFont( other.mFont )
@@ -46,6 +53,7 @@ QgsDataDefinedSizeLegend &QgsDataDefinedSizeLegend::operator=( const QgsDataDefi
mTitleLabel = other.mTitleLabel;
mSizeClasses = other.mSizeClasses;
mSymbol.reset( other.mSymbol.get() ? other.mSymbol->clone() : nullptr );
mLineSymbol.reset( other.mLineSymbol.get() ? other.mLineSymbol->clone() : nullptr );
mSizeScaleTransformer.reset( other.mSizeScaleTransformer.get() ? new QgsSizeScaleTransformer( *other.mSizeScaleTransformer ) : nullptr );
mVAlign = other.mVAlign;
mFont = other.mFont;
@@ -65,6 +73,16 @@ QgsMarkerSymbol *QgsDataDefinedSizeLegend::symbol() const
return mSymbol.get();
}

void QgsDataDefinedSizeLegend::setLineSymbol( QgsLineSymbol *symbol )
{
mLineSymbol.reset( symbol );
}

QgsLineSymbol *QgsDataDefinedSizeLegend::lineSymbol() const
{
return mLineSymbol.get();
}

void QgsDataDefinedSizeLegend::setSizeScaleTransformer( QgsSizeScaleTransformer *transformer )
{
mSizeScaleTransformer.reset( transformer );
@@ -143,6 +161,8 @@ QgsLegendSymbolList QgsDataDefinedSizeLegend::legendSymbolList() const

void QgsDataDefinedSizeLegend::drawCollapsedLegend( QgsRenderContext &context, QSizeF *outputSize, double *labelXOffset ) const
{
// this assumes the context's painter has been scaled to pixels in advance!

if ( mType != LegendCollapsed || mSizeClasses.isEmpty() || !mSymbol )
{
if ( outputSize )
@@ -273,26 +293,42 @@ void QgsDataDefinedSizeLegend::drawCollapsedLegend( QgsRenderContext &context, Q
p->translate( tx, outputLargestSize - outputSymbolSize );
break;
}
s->drawPreviewIcon( p, QSize( outputSymbolSize, outputSymbolSize ) );
s->drawPreviewIcon( nullptr, QSize( outputSymbolSize, outputSymbolSize ), &context );
p->restore();
}

p->setPen( mTextColor );
p->setFont( mFont );
QgsTextFormat format = QgsTextFormat::fromQFont( mFont );
format.setColor( mTextColor );

if ( mLineSymbol )
{
mLineSymbol->setColor( mTextColor );
mLineSymbol->startRender( context );
}

int i = 0;
for ( const SizeClass &c : qgis::as_const( classes ) )
{
// line from symbol to the text
p->drawLine( outputLargestSize / 2, symbolTopY[i], outputLargestSize + hLengthLine, textCenterY[i] );
if ( mLineSymbol )
{
mLineSymbol->renderPolyline( QPolygonF() << QPointF( outputLargestSize / 2, symbolTopY[i] )
<< QPointF( outputLargestSize + hLengthLine, textCenterY[i] ), nullptr, context );
}

// draw label
QRect rect( outputLargestSize + hLengthLine + hSpaceLineText, textCenterY[i] - textHeight / 2,
maxTextWidth, textHeight );
p->drawText( rect, mTextAlignment, c.label );

QgsTextRenderer::drawText( rect, 0, mTextAlignment == Qt::AlignRight ? QgsTextRenderer::AlignRight :
mTextAlignment == Qt::AlignHCenter ? QgsTextRenderer::AlignCenter : QgsTextRenderer::AlignLeft,
QStringList() << c.label, context, format );
i++;
}

if ( mLineSymbol )
mLineSymbol->stopRender( context );

p->restore();
}

@@ -344,6 +380,12 @@ QgsDataDefinedSizeLegend *QgsDataDefinedSizeLegend::readXml( const QDomElement &
ddsLegend->setSymbol( QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( elemSymbol, context ) );
}

QDomElement lineSymbol = elem.firstChildElement( QStringLiteral( "lineSymbol" ) );
if ( !lineSymbol.isNull() )
{
ddsLegend->setLineSymbol( QgsSymbolLayerUtils::loadSymbol<QgsLineSymbol>( lineSymbol, context ) );
}

QgsSizeScaleTransformer *transformer = nullptr;
QDomElement elemTransformer = elem.firstChildElement( QStringLiteral( "transformer" ) );
if ( !elemTransformer.isNull() )
@@ -396,6 +438,12 @@ void QgsDataDefinedSizeLegend::writeXml( QDomElement &elem, const QgsReadWriteCo
elem.appendChild( elemSymbol );
}

if ( mLineSymbol )
{
QDomElement elemSymbol = QgsSymbolLayerUtils::saveSymbol( QStringLiteral( "lineSymbol" ), mLineSymbol.get(), doc, context );
elem.appendChild( elemSymbol );
}

if ( mSizeScaleTransformer )
{
QDomElement elemTransformer = QgsXmlUtils::writeVariant( mSizeScaleTransformer->toVariant(), doc );
@@ -27,6 +27,7 @@ class QgsProperty;
class QgsReadWriteContext;
class QgsRenderContext;
class QgsSizeScaleTransformer;
class QgsLineSymbol;


/**
@@ -85,6 +86,23 @@ class CORE_EXPORT QgsDataDefinedSizeLegend
//! Returns marker symbol that will be used to draw markers in legend
QgsMarkerSymbol *symbol() const;

/**
* Sets the line \a symbol that will be used to draw callout lines in legend.
*
* Ownership of \a symbol is transferred.
*
* \see lineSymbol()
* \since QGIS 3.14
*/
void setLineSymbol( QgsLineSymbol *symbol SIP_TRANSFER );

/**
* Returns the line symbol that will be used to draw callout lines in legend.
* \see setLineSymbol()
* \since QGIS 3.14
*/
QgsLineSymbol *lineSymbol() const;

//! Sets transformer for scaling of symbol sizes. Takes ownership of the object. Accepts NULLPTR to set no transformer.
void setSizeScaleTransformer( QgsSizeScaleTransformer *transformer SIP_TRANSFER );
//! Returns transformer for scaling of symbol sizes. Returns NULLPTR if no transformer is defined.
@@ -149,6 +167,7 @@ class CORE_EXPORT QgsDataDefinedSizeLegend
QString mTitleLabel; //!< Title label for the following size-based item(s)
QList< SizeClass > mSizeClasses; //!< List of classes: symbol size (in whatever units symbol uses) + label
std::unique_ptr<QgsMarkerSymbol> mSymbol;
std::unique_ptr<QgsLineSymbol> mLineSymbol;
std::unique_ptr<QgsSizeScaleTransformer> mSizeScaleTransformer; //!< Optional transformer for classes
VerticalAlignment mVAlign = AlignBottom;
QFont mFont;
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 comments on commit 8d00ae8

Please sign in to comment.
You can’t perform that action at this time.