Skip to content

Commit

Permalink
[legends] Fix corrupted data defined legend rendering in layout designer
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Jun 10, 2020
1 parent 871a1f8 commit c72f408
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 7 deletions.
20 changes: 20 additions & 0 deletions python/core/auto_generated/qgsdatadefinedsizelegend.sip.in
Expand Up @@ -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/ );
Expand Down
2 changes: 2 additions & 0 deletions src/core/layertree/qgslayertreemodellegendnode.cpp
Expand Up @@ -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() );
}

Expand Down
62 changes: 55 additions & 7 deletions src/core/qgsdatadefinedsizelegend.cpp
Expand Up @@ -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;

Expand All @@ -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 )
Expand All @@ -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;
Expand All @@ -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 );
Expand Down Expand Up @@ -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 )
Expand Down Expand Up @@ -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();
}

Expand Down Expand Up @@ -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() )
Expand Down Expand Up @@ -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 );
Expand Down
19 changes: 19 additions & 0 deletions src/core/qgsdatadefinedsizelegend.h
Expand Up @@ -27,6 +27,7 @@ class QgsProperty;
class QgsReadWriteContext;
class QgsRenderContext;
class QgsSizeScaleTransformer;
class QgsLineSymbol;


/**
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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;
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit c72f408

Please sign in to comment.