Skip to content

Commit e3270ed

Browse files
committed
Read/write also legend symbol in DDS legend, update DDS legend dialog
1 parent 517fefe commit e3270ed

18 files changed

+218
-207
lines changed

doc/api_break.dox

+1-2
Original file line numberDiff line numberDiff line change
@@ -987,8 +987,7 @@ QgsDiagramRenderer {#qgis_api_break_3_0_QgsDiagramRenderer}
987987
- renderDiagram() now takes an optional data defined overrides collection argument.
988988
- readXml(), _readXml(), writeXml(), _writeXml() do not take QgsVectorLayer as an argument anymore.
989989
- readXml(), _readXml(), writeXml(), _writeXml() require a new argument: a reference to QgsReadWriteContext
990-
- sizeLegend() and setSizeLegend() have been replaced by dataDefinedSizeLegend() and setDataDefinedSizeLegend() methods.
991-
- sizeLegendSymbol() and setSizeLegendSymbol() have been moved to QgsLinearlyInterpolatedDiagramRenderer subclass.
990+
- sizeLegend(), setSizeLegend(), sizeLegendSymbol() and setSizeLegendSymbol() have been replaced by dataDefinedSizeLegend() and setDataDefinedSizeLegend() methods in QgsLinearlyInterpolatedDiagramRenderer.
992991

993992

994993
QgsDiagramLayerSettings {#qgis_api_break_3_0_QgsDiagramLayerSettings}

python/core/qgsdatadefinedsizelegend.sip

+4-8
Original file line numberDiff line numberDiff line change
@@ -152,19 +152,15 @@ Returns output image that would be shown in the legend. Returns invalid image if
152152
:rtype: QImage
153153
%End
154154

155-
static QgsDataDefinedSizeLegend *readTypeAndAlignmentFromXml( const QDomElement &elem ) /Factory/;
155+
static QgsDataDefinedSizeLegend *readXml( const QDomElement &elem, const QgsReadWriteContext &context ) /Factory/;
156156
%Docstring
157-
.. note::
158-
159-
This is a temporary method and may be removed in the future
157+
Creates instance from given element and returns it (caller takes ownership). Returns null on error.
160158
:rtype: QgsDataDefinedSizeLegend
161159
%End
162160

163-
static void writeTypeAndAlignmentToXml( const QgsDataDefinedSizeLegend &ddsLegend, QDomElement &elem );
161+
void writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const;
164162
%Docstring
165-
.. note::
166-
167-
This is a temporary method and may be removed in the future
163+
Writes configuration to the given XML element.
168164
%End
169165

170166
};

python/core/qgsdiagramrenderer.sip

-18
Original file line numberDiff line numberDiff line change
@@ -720,24 +720,6 @@ Returns list with all diagram settings in the renderer
720720
virtual QList< QgsLayerTreeModelLegendNode * > legendItems( QgsLayerTreeLayer *nodeLayer ) const /Factory/;
721721

722722

723-
QgsMarkerSymbol *sizeLegendSymbol() const;
724-
%Docstring
725-
Returns the marker symbol used for rendering the diagram size legend.
726-
.. versionadded:: 2.16
727-
.. seealso:: setSizeLegendSymbol()
728-
.. seealso:: sizeLegend()
729-
:rtype: QgsMarkerSymbol
730-
%End
731-
732-
void setSizeLegendSymbol( QgsMarkerSymbol *symbol /Transfer/ );
733-
%Docstring
734-
Sets the marker symbol used for rendering the diagram size legend.
735-
\param symbol marker symbol, ownership is transferred to the renderer.
736-
.. versionadded:: 2.16
737-
.. seealso:: sizeLegendSymbol()
738-
.. seealso:: setSizeLegend()
739-
%End
740-
741723
void setDataDefinedSizeLegend( QgsDataDefinedSizeLegend *settings /Transfer/ );
742724
%Docstring
743725
Configures appearance of legend. Takes ownership of the passed settings objects.

python/gui/symbology-ng/qgsdatadefinedsizelegenddialog.sip

+3-12
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111

1212

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

31-
void setSourceSymbol( QgsMarkerSymbol *symbol /Transfer/ );
32-
%Docstring
33-
Use given symbol for preview. Takes ownership of the symbol. It should have data-defined size enabled + size scale transformer attached.
34-
%End
35-
36-
void setLegendMapViewData( double mapUnitsPerPixel, int dpi, double scale );
37-
%Docstring
38-
Setup map view details to make preview match the expected output
39-
%End
40-
4132
QgsDataDefinedSizeLegend *dataDefinedSizeLegend() const /Factory/;
4233
%Docstring
4334
Returns configuration as set up in the dialog (may be null). Ownership is passed to the caller.

src/app/qgsdiagramproperties.cpp

+2-41
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,6 @@ QgsDiagramProperties::QgsDiagramProperties( QgsVectorLayer *layer, QWidget *pare
190190
newItem->setFlags( newItem->flags() & ~Qt::ItemIsDropEnabled );
191191
}
192192

193-
mSizeLegendSymbol.reset( QgsMarkerSymbol::createSimple( QgsStringMap() ) );
194-
195193
const QgsDiagramRenderer *dr = layer->diagramRenderer();
196194
if ( !dr ) //no diagram renderer yet, insert reasonable default
197195
{
@@ -360,7 +358,6 @@ QgsDiagramProperties::QgsDiagramProperties( QgsVectorLayer *layer, QWidget *pare
360358
mSizeFieldExpressionWidget->setField( lidr->classificationField() );
361359
}
362360

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

405-
QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( mSizeLegendSymbol.get(), mButtonSizeLegendSymbol->iconSize() );
406-
mButtonSizeLegendSymbol->setIcon( icon );
407-
408402
connect( mAddAttributeExpression, &QPushButton::clicked, this, &QgsDiagramProperties::showAddAttributeExpressionDialog );
409403
registerDataDefinedButton( mBackgroundColorDDBtn, QgsDiagramLayerSettings::BackgroundColor );
410404
registerDataDefinedButton( mLineColorDDBtn, QgsDiagramLayerSettings::StrokeColor );
@@ -818,7 +812,6 @@ void QgsDiagramProperties::apply()
818812
}
819813
dr->setDiagramSettings( ds );
820814

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

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

944-
void QgsDiagramProperties::on_mButtonSizeLegendSymbol_clicked()
945-
{
946-
QgsMarkerSymbol *newSymbol = mSizeLegendSymbol->clone();
947-
QgsSymbolWidgetContext context;
948-
context.setMapCanvas( mMapCanvas );
949-
QgsExpressionContext ec = createExpressionContext();
950-
context.setExpressionContext( &ec );
951-
952-
QgsSymbolSelectorDialog d( newSymbol, QgsStyle::defaultStyle(), mLayer, this );
953-
d.setContext( context );
954-
955-
if ( d.exec() == QDialog::Accepted )
956-
{
957-
mSizeLegendSymbol.reset( newSymbol );
958-
QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( mSizeLegendSymbol.get(), mButtonSizeLegendSymbol->iconSize() );
959-
mButtonSizeLegendSymbol->setIcon( icon );
960-
}
961-
else
962-
{
963-
delete newSymbol;
964-
}
965-
}
966-
967937
void QgsDiagramProperties::scalingTypeChanged()
968938
{
969-
mSizeLegendGroupBox->setEnabled( mAttributeBasedScalingRadio->isChecked() );
939+
mButtonSizeLegendSettings->setEnabled( mAttributeBasedScalingRadio->isChecked() );
970940
}
971941

972942
void QgsDiagramProperties::showSizeLegendDialog()
973943
{
974-
QgsDataDefinedSizeLegendDialog dlg( mSizeLegend.get() );
975-
QgsMarkerSymbol *symbol = mSizeLegendSymbol->clone();
976-
977944
// prepare size transformer
978945
bool isExpression;
979946
QString sizeFieldNameOrExp = mSizeFieldExpressionWidget->currentField( &isExpression );
980947
QgsProperty ddSize = isExpression ? QgsProperty::fromExpression( sizeFieldNameOrExp ) : QgsProperty::fromField( sizeFieldNameOrExp );
981948
ddSize.setTransformer( new QgsSizeScaleTransformer( QgsSizeScaleTransformer::Linear, 0.0, mMaxValueSpinBox->value(), 0.0, mSizeSpinBox->value() ) );
982-
symbol->setDataDefinedSize( ddSize );
983-
dlg.setSourceSymbol( symbol );
984-
985-
if ( mMapCanvas )
986-
{
987-
dlg.setLegendMapViewData( mMapCanvas->mapUnitsPerPixel(), mMapCanvas->mapSettings().outputDpi(), mMapCanvas->scale() );
988-
}
989949

950+
QgsDataDefinedSizeLegendDialog dlg( mSizeLegend.get(), ddSize, nullptr, mMapCanvas );
990951
if ( !dlg.exec() )
991952
return;
992953

src/app/qgsdiagramproperties.h

-2
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ class APP_EXPORT QgsDiagramProperties : public QWidget, private Ui::QgsDiagramPr
5252
void showAddAttributeExpressionDialog();
5353
void on_mDiagramStackedWidget_currentChanged( int index );
5454
void on_mPlacementComboBox_currentIndexChanged( int index );
55-
void on_mButtonSizeLegendSymbol_clicked();
5655
void scalingTypeChanged();
5756
void showSizeLegendDialog();
5857

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

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

8785
QString guessLegendText( const QString &expression );

src/core/qgsdatadefinedsizelegend.cpp

+71-4
Original file line numberDiff line numberDiff line change
@@ -290,18 +290,85 @@ QImage QgsDataDefinedSizeLegend::collapsedLegendImage( QgsRenderContext &context
290290
return img;
291291
}
292292

293-
QgsDataDefinedSizeLegend *QgsDataDefinedSizeLegend::readTypeAndAlignmentFromXml( const QDomElement &elem )
293+
QgsDataDefinedSizeLegend *QgsDataDefinedSizeLegend::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
294294
{
295295
if ( elem.isNull() )
296296
return nullptr;
297297
QgsDataDefinedSizeLegend *ddsLegend = new QgsDataDefinedSizeLegend;
298298
ddsLegend->setLegendType( elem.attribute( "type" ) == "collapsed" ? LegendCollapsed : LegendSeparated );
299299
ddsLegend->setVerticalAlignment( elem.attribute( "valign" ) == "center" ? AlignCenter : AlignBottom );
300+
ddsLegend->setTitle( elem.attribute( "title" ) );
301+
302+
QDomElement elemSymbol = elem.firstChildElement( "symbol" );
303+
if ( !elemSymbol.isNull() )
304+
{
305+
ddsLegend->setSymbol( QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( elemSymbol, context ) );
306+
}
307+
308+
QDomElement elemTextStyle = elem.firstChildElement( "text-style" );
309+
if ( !elemTextStyle.isNull() )
310+
{
311+
QDomElement elemFont = elemTextStyle.firstChildElement( "font" );
312+
if ( !elemFont.isNull() )
313+
{
314+
ddsLegend->setFont( QFont( elemFont.attribute( "family" ), elemFont.attribute( "size" ).toInt(),
315+
elemFont.attribute( "weight" ).toInt(), elemFont.attribute( "italic" ).toInt() ) );
316+
}
317+
ddsLegend->setTextColor( QgsSymbolLayerUtils::decodeColor( elemTextStyle.attribute( "color" ) ) );
318+
ddsLegend->setTextAlignment( static_cast<Qt::AlignmentFlag>( elemTextStyle.attribute( "align" ).toInt() ) );
319+
}
320+
321+
QDomElement elemClasses = elem.firstChildElement( "classes" );
322+
if ( !elemClasses.isNull() )
323+
{
324+
QList<SizeClass> classes;
325+
QDomElement elemClass = elemClasses.firstChildElement( "class" );
326+
while ( !elemClass.isNull() )
327+
{
328+
classes << SizeClass( elemClass.attribute( "size" ).toDouble(), elemClass.attribute( "label" ) );
329+
elemClass = elemClass.nextSiblingElement();
330+
}
331+
ddsLegend->setClasses( classes );
332+
}
333+
300334
return ddsLegend;
301335
}
302336

303-
void QgsDataDefinedSizeLegend::writeTypeAndAlignmentToXml( const QgsDataDefinedSizeLegend &ddsLegend, QDomElement &elem )
337+
void QgsDataDefinedSizeLegend::writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const
304338
{
305-
elem.setAttribute( "type", ddsLegend.legendType() == LegendCollapsed ? "collapsed" : "separated" );
306-
elem.setAttribute( "valign", ddsLegend.verticalAlignment() == AlignCenter ? "center" : "bottom" );
339+
QDomDocument doc = elem.ownerDocument();
340+
341+
elem.setAttribute( "type", mType == LegendCollapsed ? "collapsed" : "separated" );
342+
elem.setAttribute( "valign", mVAlign == AlignCenter ? "center" : "bottom" );
343+
elem.setAttribute( "title", mTitleLabel );
344+
345+
if ( mSymbol )
346+
{
347+
QgsSymbolLayerUtils::saveSymbol( "source", mSymbol.get(), doc, context );
348+
}
349+
350+
QDomElement elemFont = doc.createElement( "font" );
351+
elemFont.setAttribute( "family", mFont.family() );
352+
elemFont.setAttribute( "size", mFont.pointSize() );
353+
elemFont.setAttribute( "weight", mFont.weight() );
354+
elemFont.setAttribute( "italic", mFont.italic() );
355+
356+
QDomElement elemTextStyle = doc.createElement( "text-style" );
357+
elemTextStyle.setAttribute( "color", QgsSymbolLayerUtils::encodeColor( mTextColor ) );
358+
elemTextStyle.setAttribute( "align", static_cast<int>( mTextAlignment ) );
359+
elemTextStyle.appendChild( elemFont );
360+
elem.appendChild( elemTextStyle );
361+
362+
if ( !mSizeClasses.isEmpty() )
363+
{
364+
QDomElement elemClasses = doc.createElement( "classes" );
365+
Q_FOREACH ( const SizeClass &sc, mSizeClasses )
366+
{
367+
QDomElement elemClass = doc.createElement( "class" );
368+
elemClass.setAttribute( "size", sc.size );
369+
elemClass.setAttribute( "label", sc.label );
370+
elemClasses.appendChild( elemClass );
371+
}
372+
elem.appendChild( elemClasses );
373+
}
307374
}

src/core/qgsdatadefinedsizelegend.h

+3-6
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
class QDomElement;
2525
class QgsMarkerSymbol;
2626
class QgsProperty;
27+
class QgsReadWriteContext;
2728
class QgsRenderContext;
2829

2930

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

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

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

134131
private:
135132
LegendType mType = LegendSeparated;

src/core/qgsdiagramrenderer.cpp

+17-18
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,6 @@ void QgsSingleCategoryDiagramRenderer::writeXml( QDomElement &layerElem, QDomDoc
601601

602602
QgsLinearlyInterpolatedDiagramRenderer::QgsLinearlyInterpolatedDiagramRenderer()
603603
: QgsDiagramRenderer()
604-
, mSizeLegendSymbol( QgsMarkerSymbol::createSimple( QgsStringMap() ) )
605604
{
606605
mInterpolationSettings.classificationAttributeIsExpression = false;
607606
}
@@ -610,7 +609,6 @@ QgsLinearlyInterpolatedDiagramRenderer::QgsLinearlyInterpolatedDiagramRenderer(
610609
: QgsDiagramRenderer( other )
611610
, mSettings( other.mSettings )
612611
, mInterpolationSettings( other.mInterpolationSettings )
613-
, mSizeLegendSymbol( other.mSizeLegendSymbol ? other.mSizeLegendSymbol->clone() : nullptr )
614612
, mDataDefinedSizeLegend( other.mDataDefinedSizeLegend ? new QgsDataDefinedSizeLegend( *other.mDataDefinedSizeLegend ) : nullptr )
615613
{
616614
}
@@ -685,22 +683,27 @@ void QgsLinearlyInterpolatedDiagramRenderer::readXml( const QDomElement &elem, c
685683
mSettings.readXml( settingsElem );
686684
}
687685

688-
QDomElement sizeLegendSymbolElem = elem.firstChildElement( QStringLiteral( "symbol" ) );
689-
if ( !sizeLegendSymbolElem.isNull() && sizeLegendSymbolElem.attribute( QStringLiteral( "name" ) ) == QLatin1String( "sizeSymbol" ) )
690-
{
691-
mSizeLegendSymbol.reset( QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( sizeLegendSymbolElem, context ) );
692-
}
693-
694686
QDomElement ddsLegendSizeElem = elem.firstChildElement( "data-defined-size-legend" );
695687
if ( !ddsLegendSizeElem.isNull() )
696688
{
697-
mDataDefinedSizeLegend.reset( QgsDataDefinedSizeLegend::readTypeAndAlignmentFromXml( ddsLegendSizeElem ) );
689+
mDataDefinedSizeLegend.reset( QgsDataDefinedSizeLegend::readXml( ddsLegendSizeElem, context ) );
698690
}
699691
else
700692
{
701693
// pre-3.0 projects
702-
bool enabled = elem.attribute( QStringLiteral( "sizeLegend" ), QStringLiteral( "0" ) ) != QLatin1String( "0" );
703-
mDataDefinedSizeLegend.reset( enabled ? new QgsDataDefinedSizeLegend() : nullptr );
694+
if ( elem.attribute( QStringLiteral( "sizeLegend" ), QStringLiteral( "0" ) ) != QLatin1String( "0" ) )
695+
{
696+
mDataDefinedSizeLegend.reset( new QgsDataDefinedSizeLegend() );
697+
QDomElement sizeLegendSymbolElem = elem.firstChildElement( QStringLiteral( "symbol" ) );
698+
if ( !sizeLegendSymbolElem.isNull() && sizeLegendSymbolElem.attribute( QStringLiteral( "name" ) ) == QLatin1String( "sizeSymbol" ) )
699+
{
700+
mDataDefinedSizeLegend->setSymbol( QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( sizeLegendSymbolElem, context ) );
701+
}
702+
}
703+
else
704+
{
705+
mDataDefinedSizeLegend.reset( nullptr );
706+
}
704707
}
705708

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

728-
QDomElement sizeLegendSymbolElem = QgsSymbolLayerUtils::saveSymbol( QStringLiteral( "sizeSymbol" ), mSizeLegendSymbol.get(), doc, context );
729-
rendererElem.appendChild( sizeLegendSymbolElem );
730-
731731
if ( mDataDefinedSizeLegend )
732732
{
733733
QDomElement ddsLegendElem = doc.createElement( QStringLiteral( "data-defined-size-legend" ) );
734-
QgsDataDefinedSizeLegend::writeTypeAndAlignmentToXml( *mDataDefinedSizeLegend, ddsLegendElem );
734+
mDataDefinedSizeLegend->writeXml( ddsLegendElem, context );
735735
rendererElem.appendChild( ddsLegendElem );
736736
}
737737

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

775-
if ( mDataDefinedSizeLegend && mDiagram && mSizeLegendSymbol )
775+
if ( mDataDefinedSizeLegend && mDiagram )
776776
{
777777
// add size legend
778-
779-
QgsMarkerSymbol *legendSymbol = mSizeLegendSymbol.get()->clone();
778+
QgsMarkerSymbol *legendSymbol = mDataDefinedSizeLegend->symbol() ? mDataDefinedSizeLegend->symbol()->clone() : QgsMarkerSymbol::createSimple( QgsStringMap() );
780779
legendSymbol->setSizeUnit( mSettings.sizeType );
781780
legendSymbol->setSizeMapUnitScale( mSettings.sizeScale );
782781

0 commit comments

Comments
 (0)