Skip to content
Permalink
Browse files

Read/write also legend symbol in DDS legend, update DDS legend dialog

  • Loading branch information
wonder-sk committed Jun 19, 2017
1 parent 517fefe commit e3270edb7a9060bbadc77272fe987cb41807f724
@@ -987,8 +987,7 @@ QgsDiagramRenderer {#qgis_api_break_3_0_QgsDiagramRenderer}
- renderDiagram() now takes an optional data defined overrides collection argument.
- readXml(), _readXml(), writeXml(), _writeXml() do not take QgsVectorLayer as an argument anymore.
- readXml(), _readXml(), writeXml(), _writeXml() require a new argument: a reference to QgsReadWriteContext
- sizeLegend() and setSizeLegend() have been replaced by dataDefinedSizeLegend() and setDataDefinedSizeLegend() methods.
- sizeLegendSymbol() and setSizeLegendSymbol() have been moved to QgsLinearlyInterpolatedDiagramRenderer subclass.
- sizeLegend(), setSizeLegend(), sizeLegendSymbol() and setSizeLegendSymbol() have been replaced by dataDefinedSizeLegend() and setDataDefinedSizeLegend() methods in QgsLinearlyInterpolatedDiagramRenderer.


QgsDiagramLayerSettings {#qgis_api_break_3_0_QgsDiagramLayerSettings}
@@ -152,19 +152,15 @@ Returns output image that would be shown in the legend. Returns invalid image if
:rtype: QImage
%End

static QgsDataDefinedSizeLegend *readTypeAndAlignmentFromXml( const QDomElement &elem ) /Factory/;
static QgsDataDefinedSizeLegend *readXml( const QDomElement &elem, const QgsReadWriteContext &context ) /Factory/;
%Docstring
.. note::

This is a temporary method and may be removed in the future
Creates instance from given element and returns it (caller takes ownership). Returns null on error.
:rtype: QgsDataDefinedSizeLegend
%End

static void writeTypeAndAlignmentToXml( const QgsDataDefinedSizeLegend &ddsLegend, QDomElement &elem );
void writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const;
%Docstring
.. note::

This is a temporary method and may be removed in the future
Writes configuration to the given XML element.
%End

};
@@ -720,24 +720,6 @@ Returns list with all diagram settings in the renderer
virtual QList< QgsLayerTreeModelLegendNode * > legendItems( QgsLayerTreeLayer *nodeLayer ) const /Factory/;


QgsMarkerSymbol *sizeLegendSymbol() const;
%Docstring
Returns the marker symbol used for rendering the diagram size legend.
.. versionadded:: 2.16
.. seealso:: setSizeLegendSymbol()
.. seealso:: sizeLegend()
:rtype: QgsMarkerSymbol
%End

void setSizeLegendSymbol( QgsMarkerSymbol *symbol /Transfer/ );
%Docstring
Sets the marker symbol used for rendering the diagram size legend.
\param symbol marker symbol, ownership is transferred to the renderer.
.. versionadded:: 2.16
.. seealso:: sizeLegendSymbol()
.. seealso:: setSizeLegend()
%End

void setDataDefinedSizeLegend( QgsDataDefinedSizeLegend *settings /Transfer/ );
%Docstring
Configures appearance of legend. Takes ownership of the passed settings objects.
@@ -10,6 +10,7 @@




class QgsDataDefinedSizeLegendDialog : QDialog
{
%Docstring
@@ -22,22 +23,12 @@ class QgsDataDefinedSizeLegendDialog : QDialog
#include "qgsdatadefinedsizelegenddialog.h"
%End
public:
explicit QgsDataDefinedSizeLegendDialog( const QgsDataDefinedSizeLegend *ddsLegend, QWidget *parent /TransferThis/ = 0 );
explicit QgsDataDefinedSizeLegendDialog( const QgsDataDefinedSizeLegend *ddsLegend, const QgsProperty &ddSize, QgsMarkerSymbol *overrideSymbol /Transfer/, QgsMapCanvas *canvas = 0, QWidget *parent /TransferThis/ = 0 );
%Docstring
Creates the dialog and initializes the content to what is passed in the legend configuration (may be null)
when the symbol is given from outside rather than being set inside QgsDataDefinedSizeLegend.
%End
~QgsDataDefinedSizeLegendDialog();

void setSourceSymbol( QgsMarkerSymbol *symbol /Transfer/ );
%Docstring
Use given symbol for preview. Takes ownership of the symbol. It should have data-defined size enabled + size scale transformer attached.
%End

void setLegendMapViewData( double mapUnitsPerPixel, int dpi, double scale );
%Docstring
Setup map view details to make preview match the expected output
%End

QgsDataDefinedSizeLegend *dataDefinedSizeLegend() const /Factory/;
%Docstring
Returns configuration as set up in the dialog (may be null). Ownership is passed to the caller.
@@ -190,8 +190,6 @@ QgsDiagramProperties::QgsDiagramProperties( QgsVectorLayer *layer, QWidget *pare
newItem->setFlags( newItem->flags() & ~Qt::ItemIsDropEnabled );
}

mSizeLegendSymbol.reset( QgsMarkerSymbol::createSimple( QgsStringMap() ) );

const QgsDiagramRenderer *dr = layer->diagramRenderer();
if ( !dr ) //no diagram renderer yet, insert reasonable default
{
@@ -360,7 +358,6 @@ QgsDiagramProperties::QgsDiagramProperties( QgsVectorLayer *layer, QWidget *pare
mSizeFieldExpressionWidget->setField( lidr->classificationField() );
}

mSizeLegendSymbol.reset( lidr->sizeLegendSymbol() ? lidr->sizeLegendSymbol()->clone() : QgsMarkerSymbol::createSimple( QgsStringMap() ) );
mSizeLegend.reset( lidr->dataDefinedSizeLegend() ? new QgsDataDefinedSizeLegend( *lidr->dataDefinedSizeLegend() ) : nullptr );
}
}
@@ -402,9 +399,6 @@ QgsDiagramProperties::QgsDiagramProperties( QgsVectorLayer *layer, QWidget *pare
}
}

QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( mSizeLegendSymbol.get(), mButtonSizeLegendSymbol->iconSize() );
mButtonSizeLegendSymbol->setIcon( icon );

connect( mAddAttributeExpression, &QPushButton::clicked, this, &QgsDiagramProperties::showAddAttributeExpressionDialog );
registerDataDefinedButton( mBackgroundColorDDBtn, QgsDiagramLayerSettings::BackgroundColor );
registerDataDefinedButton( mLineColorDDBtn, QgsDiagramLayerSettings::StrokeColor );
@@ -818,7 +812,6 @@ void QgsDiagramProperties::apply()
}
dr->setDiagramSettings( ds );

dr->setSizeLegendSymbol( mSizeLegendSymbol->clone() );
dr->setDataDefinedSizeLegend( mSizeLegend ? new QgsDataDefinedSizeLegend( *mSizeLegend ) : nullptr );

renderer = dr;
@@ -941,52 +934,20 @@ void QgsDiagramProperties::on_mPlacementComboBox_currentIndexChanged( int index
chkLineOrientationDependent->setEnabled( linePlacementEnabled );
}

void QgsDiagramProperties::on_mButtonSizeLegendSymbol_clicked()
{
QgsMarkerSymbol *newSymbol = mSizeLegendSymbol->clone();
QgsSymbolWidgetContext context;
context.setMapCanvas( mMapCanvas );
QgsExpressionContext ec = createExpressionContext();
context.setExpressionContext( &ec );

QgsSymbolSelectorDialog d( newSymbol, QgsStyle::defaultStyle(), mLayer, this );
d.setContext( context );

if ( d.exec() == QDialog::Accepted )
{
mSizeLegendSymbol.reset( newSymbol );
QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( mSizeLegendSymbol.get(), mButtonSizeLegendSymbol->iconSize() );
mButtonSizeLegendSymbol->setIcon( icon );
}
else
{
delete newSymbol;
}
}

void QgsDiagramProperties::scalingTypeChanged()
{
mSizeLegendGroupBox->setEnabled( mAttributeBasedScalingRadio->isChecked() );
mButtonSizeLegendSettings->setEnabled( mAttributeBasedScalingRadio->isChecked() );
}

void QgsDiagramProperties::showSizeLegendDialog()
{
QgsDataDefinedSizeLegendDialog dlg( mSizeLegend.get() );
QgsMarkerSymbol *symbol = mSizeLegendSymbol->clone();

// prepare size transformer
bool isExpression;
QString sizeFieldNameOrExp = mSizeFieldExpressionWidget->currentField( &isExpression );
QgsProperty ddSize = isExpression ? QgsProperty::fromExpression( sizeFieldNameOrExp ) : QgsProperty::fromField( sizeFieldNameOrExp );
ddSize.setTransformer( new QgsSizeScaleTransformer( QgsSizeScaleTransformer::Linear, 0.0, mMaxValueSpinBox->value(), 0.0, mSizeSpinBox->value() ) );
symbol->setDataDefinedSize( ddSize );
dlg.setSourceSymbol( symbol );

if ( mMapCanvas )
{
dlg.setLegendMapViewData( mMapCanvas->mapUnitsPerPixel(), mMapCanvas->mapSettings().outputDpi(), mMapCanvas->scale() );
}

QgsDataDefinedSizeLegendDialog dlg( mSizeLegend.get(), ddSize, nullptr, mMapCanvas );
if ( !dlg.exec() )
return;

@@ -52,7 +52,6 @@ class APP_EXPORT QgsDiagramProperties : public QWidget, private Ui::QgsDiagramPr
void showAddAttributeExpressionDialog();
void on_mDiagramStackedWidget_currentChanged( int index );
void on_mPlacementComboBox_currentIndexChanged( int index );
void on_mButtonSizeLegendSymbol_clicked();
void scalingTypeChanged();
void showSizeLegendDialog();

@@ -81,7 +80,6 @@ class APP_EXPORT QgsDiagramProperties : public QWidget, private Ui::QgsDiagramPr

// Keeps track of the diagram type to properly save / restore settings when the diagram type combo box is set to no diagram.
QString mDiagramType;
std::unique_ptr< QgsMarkerSymbol > mSizeLegendSymbol;
std::unique_ptr< QgsDataDefinedSizeLegend > mSizeLegend;

QString guessLegendText( const QString &expression );
@@ -290,18 +290,85 @@ QImage QgsDataDefinedSizeLegend::collapsedLegendImage( QgsRenderContext &context
return img;
}

QgsDataDefinedSizeLegend *QgsDataDefinedSizeLegend::readTypeAndAlignmentFromXml( const QDomElement &elem )
QgsDataDefinedSizeLegend *QgsDataDefinedSizeLegend::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
{
if ( elem.isNull() )
return nullptr;
QgsDataDefinedSizeLegend *ddsLegend = new QgsDataDefinedSizeLegend;
ddsLegend->setLegendType( elem.attribute( "type" ) == "collapsed" ? LegendCollapsed : LegendSeparated );
ddsLegend->setVerticalAlignment( elem.attribute( "valign" ) == "center" ? AlignCenter : AlignBottom );
ddsLegend->setTitle( elem.attribute( "title" ) );

QDomElement elemSymbol = elem.firstChildElement( "symbol" );
if ( !elemSymbol.isNull() )
{
ddsLegend->setSymbol( QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( elemSymbol, context ) );
}

QDomElement elemTextStyle = elem.firstChildElement( "text-style" );
if ( !elemTextStyle.isNull() )
{
QDomElement elemFont = elemTextStyle.firstChildElement( "font" );
if ( !elemFont.isNull() )
{
ddsLegend->setFont( QFont( elemFont.attribute( "family" ), elemFont.attribute( "size" ).toInt(),
elemFont.attribute( "weight" ).toInt(), elemFont.attribute( "italic" ).toInt() ) );
}
ddsLegend->setTextColor( QgsSymbolLayerUtils::decodeColor( elemTextStyle.attribute( "color" ) ) );
ddsLegend->setTextAlignment( static_cast<Qt::AlignmentFlag>( elemTextStyle.attribute( "align" ).toInt() ) );
}

QDomElement elemClasses = elem.firstChildElement( "classes" );
if ( !elemClasses.isNull() )
{
QList<SizeClass> classes;
QDomElement elemClass = elemClasses.firstChildElement( "class" );
while ( !elemClass.isNull() )
{
classes << SizeClass( elemClass.attribute( "size" ).toDouble(), elemClass.attribute( "label" ) );
elemClass = elemClass.nextSiblingElement();
}
ddsLegend->setClasses( classes );
}

return ddsLegend;
}

void QgsDataDefinedSizeLegend::writeTypeAndAlignmentToXml( const QgsDataDefinedSizeLegend &ddsLegend, QDomElement &elem )
void QgsDataDefinedSizeLegend::writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const
{
elem.setAttribute( "type", ddsLegend.legendType() == LegendCollapsed ? "collapsed" : "separated" );
elem.setAttribute( "valign", ddsLegend.verticalAlignment() == AlignCenter ? "center" : "bottom" );
QDomDocument doc = elem.ownerDocument();

elem.setAttribute( "type", mType == LegendCollapsed ? "collapsed" : "separated" );
elem.setAttribute( "valign", mVAlign == AlignCenter ? "center" : "bottom" );
elem.setAttribute( "title", mTitleLabel );

if ( mSymbol )
{
QgsSymbolLayerUtils::saveSymbol( "source", mSymbol.get(), doc, context );
}

QDomElement elemFont = doc.createElement( "font" );
elemFont.setAttribute( "family", mFont.family() );
elemFont.setAttribute( "size", mFont.pointSize() );
elemFont.setAttribute( "weight", mFont.weight() );
elemFont.setAttribute( "italic", mFont.italic() );

QDomElement elemTextStyle = doc.createElement( "text-style" );
elemTextStyle.setAttribute( "color", QgsSymbolLayerUtils::encodeColor( mTextColor ) );
elemTextStyle.setAttribute( "align", static_cast<int>( mTextAlignment ) );
elemTextStyle.appendChild( elemFont );
elem.appendChild( elemTextStyle );

if ( !mSizeClasses.isEmpty() )
{
QDomElement elemClasses = doc.createElement( "classes" );
Q_FOREACH ( const SizeClass &sc, mSizeClasses )
{
QDomElement elemClass = doc.createElement( "class" );
elemClass.setAttribute( "size", sc.size );
elemClass.setAttribute( "label", sc.label );
elemClasses.appendChild( elemClass );
}
elem.appendChild( elemClasses );
}
}
@@ -24,6 +24,7 @@
class QDomElement;
class QgsMarkerSymbol;
class QgsProperty;
class QgsReadWriteContext;
class QgsRenderContext;


@@ -122,14 +123,10 @@ class CORE_EXPORT QgsDataDefinedSizeLegend
QImage collapsedLegendImage( QgsRenderContext &context, double paddingMM = 1 ) const;

//! Creates instance from given element and returns it (caller takes ownership). Returns null on error.
//! \note only reads legend type and vertical alignment of symbols
//! \note This is a temporary method and may be removed in the future
static QgsDataDefinedSizeLegend *readTypeAndAlignmentFromXml( const QDomElement &elem ) SIP_FACTORY;
static QgsDataDefinedSizeLegend *readXml( const QDomElement &elem, const QgsReadWriteContext &context ) SIP_FACTORY;

//! Writes configuration to the given XML element.
//! \note only writes legend type and vertical alignment of symbols
//! \note This is a temporary method and may be removed in the future
static void writeTypeAndAlignmentToXml( const QgsDataDefinedSizeLegend &ddsLegend, QDomElement &elem );
void writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const;

private:
LegendType mType = LegendSeparated;
@@ -601,7 +601,6 @@ void QgsSingleCategoryDiagramRenderer::writeXml( QDomElement &layerElem, QDomDoc

QgsLinearlyInterpolatedDiagramRenderer::QgsLinearlyInterpolatedDiagramRenderer()
: QgsDiagramRenderer()
, mSizeLegendSymbol( QgsMarkerSymbol::createSimple( QgsStringMap() ) )
{
mInterpolationSettings.classificationAttributeIsExpression = false;
}
@@ -610,7 +609,6 @@ QgsLinearlyInterpolatedDiagramRenderer::QgsLinearlyInterpolatedDiagramRenderer(
: QgsDiagramRenderer( other )
, mSettings( other.mSettings )
, mInterpolationSettings( other.mInterpolationSettings )
, mSizeLegendSymbol( other.mSizeLegendSymbol ? other.mSizeLegendSymbol->clone() : nullptr )
, mDataDefinedSizeLegend( other.mDataDefinedSizeLegend ? new QgsDataDefinedSizeLegend( *other.mDataDefinedSizeLegend ) : nullptr )
{
}
@@ -685,22 +683,27 @@ void QgsLinearlyInterpolatedDiagramRenderer::readXml( const QDomElement &elem, c
mSettings.readXml( settingsElem );
}

QDomElement sizeLegendSymbolElem = elem.firstChildElement( QStringLiteral( "symbol" ) );
if ( !sizeLegendSymbolElem.isNull() && sizeLegendSymbolElem.attribute( QStringLiteral( "name" ) ) == QLatin1String( "sizeSymbol" ) )
{
mSizeLegendSymbol.reset( QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( sizeLegendSymbolElem, context ) );
}

QDomElement ddsLegendSizeElem = elem.firstChildElement( "data-defined-size-legend" );
if ( !ddsLegendSizeElem.isNull() )
{
mDataDefinedSizeLegend.reset( QgsDataDefinedSizeLegend::readTypeAndAlignmentFromXml( ddsLegendSizeElem ) );
mDataDefinedSizeLegend.reset( QgsDataDefinedSizeLegend::readXml( ddsLegendSizeElem, context ) );
}
else
{
// pre-3.0 projects
bool enabled = elem.attribute( QStringLiteral( "sizeLegend" ), QStringLiteral( "0" ) ) != QLatin1String( "0" );
mDataDefinedSizeLegend.reset( enabled ? new QgsDataDefinedSizeLegend() : nullptr );
if ( elem.attribute( QStringLiteral( "sizeLegend" ), QStringLiteral( "0" ) ) != QLatin1String( "0" ) )
{
mDataDefinedSizeLegend.reset( new QgsDataDefinedSizeLegend() );
QDomElement sizeLegendSymbolElem = elem.firstChildElement( QStringLiteral( "symbol" ) );
if ( !sizeLegendSymbolElem.isNull() && sizeLegendSymbolElem.attribute( QStringLiteral( "name" ) ) == QLatin1String( "sizeSymbol" ) )
{
mDataDefinedSizeLegend->setSymbol( QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( sizeLegendSymbolElem, context ) );
}
}
else
{
mDataDefinedSizeLegend.reset( nullptr );
}
}

_readXml( elem, context );
@@ -725,13 +728,10 @@ void QgsLinearlyInterpolatedDiagramRenderer::writeXml( QDomElement &layerElem, Q
}
mSettings.writeXml( rendererElem, doc );

QDomElement sizeLegendSymbolElem = QgsSymbolLayerUtils::saveSymbol( QStringLiteral( "sizeSymbol" ), mSizeLegendSymbol.get(), doc, context );
rendererElem.appendChild( sizeLegendSymbolElem );

if ( mDataDefinedSizeLegend )
{
QDomElement ddsLegendElem = doc.createElement( QStringLiteral( "data-defined-size-legend" ) );
QgsDataDefinedSizeLegend::writeTypeAndAlignmentToXml( *mDataDefinedSizeLegend, ddsLegendElem );
mDataDefinedSizeLegend->writeXml( ddsLegendElem, context );
rendererElem.appendChild( ddsLegendElem );
}

@@ -772,11 +772,10 @@ QList< QgsLayerTreeModelLegendNode * > QgsLinearlyInterpolatedDiagramRenderer::l
if ( mShowAttributeLegend )
nodes = mSettings.legendItems( nodeLayer );

if ( mDataDefinedSizeLegend && mDiagram && mSizeLegendSymbol )
if ( mDataDefinedSizeLegend && mDiagram )
{
// add size legend

QgsMarkerSymbol *legendSymbol = mSizeLegendSymbol.get()->clone();
QgsMarkerSymbol *legendSymbol = mDataDefinedSizeLegend->symbol() ? mDataDefinedSizeLegend->symbol()->clone() : QgsMarkerSymbol::createSimple( QgsStringMap() );
legendSymbol->setSizeUnit( mSettings.sizeType );
legendSymbol->setSizeMapUnitScale( mSettings.sizeScale );

0 comments on commit e3270ed

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