Skip to content

Commit ea8a2c2

Browse files
committed
Added GUI for data-defined size legend (single/categorized/graduated renderer)
1 parent 8c4d5bb commit ea8a2c2

24 files changed

+677
-15
lines changed

doc/api_break.dox

+1
Original file line numberDiff line numberDiff line change
@@ -2110,6 +2110,7 @@ QgsSingleSymbolRendererWidget {#qgis_api_break_3_0_QgsSingleSymbolRendere
21102110

21112111
- sizeScaleFieldChanged() and scaleMethodChanged() were removed. These settings are no longer exposed in the widget's GUI.
21122112
- The Mode enum was removed.
2113+
- changeSingleSymbol() and showSymbolLevels() slots were made private.
21132114

21142115
QgsSlider {#qgis_api_break_3_0_QgsSlider}
21152116
---------
+178
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
/************************************************************************
2+
* This file has been generated automatically from *
3+
* *
4+
* src/core/qgsdatadefinedsizelegend.h *
5+
* *
6+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
7+
************************************************************************/
8+
9+
10+
11+
12+
13+
14+
class QgsDataDefinedSizeLegend
15+
{
16+
%Docstring
17+
Object that keeps configuration of appearance of marker symbol's data-defined size in legend.
18+
For example: the list of classes (size values), whether the classes should appear in separate
19+
legend nodes or whether to collapse them into one legend node.
20+
21+
.. versionadded:: 3.0
22+
%End
23+
24+
%TypeHeaderCode
25+
#include "qgsdatadefinedsizelegend.h"
26+
%End
27+
public:
28+
QgsDataDefinedSizeLegend();
29+
30+
QgsDataDefinedSizeLegend( const QgsDataDefinedSizeLegend &other );
31+
32+
enum LegendType
33+
{
34+
LegendSeparated,
35+
LegendCollapsed,
36+
};
37+
38+
enum VerticalAlignment
39+
{
40+
AlignCenter,
41+
AlignBottom,
42+
};
43+
44+
struct SizeClass
45+
{
46+
SizeClass( double size, const QString &label );
47+
48+
double size; //!< Marker size in units used by the symbol (usually millimeters)
49+
QString label; //!< Label to be shown with the particular symbol size
50+
};
51+
52+
void setLegendType( LegendType type );
53+
%Docstring
54+
Sets how the legend should be rendered
55+
%End
56+
LegendType legendType() const;
57+
%Docstring
58+
Returns how the legend should be rendered
59+
:rtype: LegendType
60+
%End
61+
62+
void setSymbol( QgsMarkerSymbol *symbol /Transfer/ );
63+
%Docstring
64+
Sets marker symbol that will be used to draw markers in legend
65+
%End
66+
QgsMarkerSymbol *symbol() const;
67+
%Docstring
68+
Returns marker symbol that will be used to draw markers in legend
69+
:rtype: QgsMarkerSymbol
70+
%End
71+
72+
void setClasses( const QList<QgsDataDefinedSizeLegend::SizeClass> &classes );
73+
%Docstring
74+
Sets list of classes: each class is a pair of symbol size (in units used by the symbol) and label
75+
%End
76+
QList<QgsDataDefinedSizeLegend::SizeClass> classes() const;
77+
%Docstring
78+
Returns list of classes: each class is a pair of symbol size (in units used by the symbol) and label
79+
:rtype: list of QgsDataDefinedSizeLegend.SizeClass
80+
%End
81+
82+
void setTitle( const QString &title );
83+
%Docstring
84+
Sets title label for data-defined size legend
85+
%End
86+
QString title() const;
87+
%Docstring
88+
Returns title label for data-defined size legend
89+
:rtype: str
90+
%End
91+
92+
void setVerticalAlignment( VerticalAlignment vAlign );
93+
%Docstring
94+
Sets vertical alignment of symbols - only valid for collapsed legend
95+
%End
96+
VerticalAlignment verticalAlignment() const;
97+
%Docstring
98+
Returns vertical alignment of symbols - only valid for collapsed legend
99+
:rtype: VerticalAlignment
100+
%End
101+
102+
void setFont( const QFont &font );
103+
%Docstring
104+
Sets font used for rendering of labels - only valid for collapsed legend
105+
%End
106+
QFont font() const;
107+
%Docstring
108+
Returns font used for rendering of labels - only valid for collapsed legend
109+
:rtype: QFont
110+
%End
111+
112+
void setTextColor( const QColor &color );
113+
%Docstring
114+
Sets text color for rendering of labels - only valid for collapsed legend
115+
%End
116+
QColor textColor() const;
117+
%Docstring
118+
Returns text color for rendering of labels - only valid for collapsed legend
119+
:rtype: QColor
120+
%End
121+
122+
void setTextAlignment( Qt::AlignmentFlag flag );
123+
%Docstring
124+
Sets horizontal text alignment for rendering of labels - only valid for collapsed legend
125+
%End
126+
Qt::AlignmentFlag textAlignment() const;
127+
%Docstring
128+
Returns horizontal text alignment for rendering of labels - only valid for collapsed legend
129+
:rtype: Qt.AlignmentFlag
130+
%End
131+
132+
133+
void updateFromSymbolAndProperty( const QgsMarkerSymbol *symbol, const QgsProperty &ddSize );
134+
%Docstring
135+
Updates the list of classes, source symbol and title label from given symbol and property
136+
%End
137+
138+
QgsLegendSymbolList legendSymbolList() const;
139+
%Docstring
140+
Generates legend symbol items according to the configuration
141+
:rtype: QgsLegendSymbolList
142+
%End
143+
144+
void drawCollapsedLegend( QgsRenderContext &context, QSize *outputSize /Out/ = 0, int *labelXOffset /Out/ = 0 ) const;
145+
%Docstring
146+
Does nothing if legend is not configured as collapsed.
147+
%End
148+
149+
QImage collapsedLegendImage( QgsRenderContext &context, double paddingMM = 1 ) const;
150+
%Docstring
151+
Returns output image that would be shown in the legend. Returns invalid image if legend is not configured as collapsed.
152+
:rtype: QImage
153+
%End
154+
155+
static QgsDataDefinedSizeLegend *readTypeAndAlignmentFromXml( const QDomElement &elem ) /Factory/;
156+
%Docstring
157+
.. note::
158+
159+
This is a temporary method and may be removed in the future
160+
:rtype: QgsDataDefinedSizeLegend
161+
%End
162+
163+
static void writeTypeAndAlignmentToXml( const QgsDataDefinedSizeLegend &ddsLegend, QDomElement &elem );
164+
%Docstring
165+
.. note::
166+
167+
This is a temporary method and may be removed in the future
168+
%End
169+
170+
};
171+
172+
/************************************************************************
173+
* This file has been generated automatically from *
174+
* *
175+
* src/core/qgsdatadefinedsizelegend.h *
176+
* *
177+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
178+
************************************************************************/

python/gui/gui.sip

+1
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@
239239
%Include symbology-ng/qgscategorizedsymbolrendererwidget.sip
240240
%Include symbology-ng/qgscptcitycolorrampdialog.sip
241241
%Include symbology-ng/qgsdashspacedialog.sip
242+
%Include symbology-ng/qgsdatadefinedsizelegenddialog.sip
242243
%Include symbology-ng/qgsellipsesymbollayerwidget.sip
243244
%Include symbology-ng/qgsgraduatedhistogramwidget.sip
244245
%Include symbology-ng/qgsgraduatedsymbolrendererwidget.sip
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/************************************************************************
2+
* This file has been generated automatically from *
3+
* *
4+
* src/gui/symbology-ng/qgsdatadefinedsizelegenddialog.h *
5+
* *
6+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
7+
************************************************************************/
8+
9+
10+
11+
12+
13+
class QgsDataDefinedSizeLegendDialog : QDialog
14+
{
15+
%Docstring
16+
Dialog for configuration of appearance of legend for marker symbols with data-defined size.
17+
18+
.. versionadded:: 3.0
19+
%End
20+
21+
%TypeHeaderCode
22+
#include "qgsdatadefinedsizelegenddialog.h"
23+
%End
24+
public:
25+
explicit QgsDataDefinedSizeLegendDialog( const QgsDataDefinedSizeLegend *ddsLegend, QWidget *parent /TransferThis/ = 0 );
26+
%Docstring
27+
Creates the dialog and initializes the content to what is passed in the legend configuration (may be null)
28+
%End
29+
~QgsDataDefinedSizeLegendDialog();
30+
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+
41+
QgsDataDefinedSizeLegend *dataDefinedSizeLegend() const /Factory/;
42+
%Docstring
43+
Returns configuration as set up in the dialog (may be null). Ownership is passed to the caller.
44+
:rtype: QgsDataDefinedSizeLegend
45+
%End
46+
47+
signals:
48+
49+
};
50+
51+
/************************************************************************
52+
* This file has been generated automatically from *
53+
* *
54+
* src/gui/symbology-ng/qgsdatadefinedsizelegenddialog.h *
55+
* *
56+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
57+
************************************************************************/

python/gui/symbology-ng/qgsrendererwidget.sip

+6
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@ and by connecting the slot contextMenuViewCategories(const QPoint&)*
8686
%End
8787
virtual void refreshSymbolView();
8888

89+
QgsDataDefinedSizeLegend *showDataDefinedSizeLegendDialog( const QgsMarkerSymbol *symbol, const QgsDataDefinedSizeLegend *ddsLegend, bool *ok /Out/ ) /Factory/;
90+
%Docstring
91+
.. versionadded:: 3.0
92+
:rtype: QgsDataDefinedSizeLegend
93+
%End
94+
8995
protected slots:
9096
void contextMenuViewCategories( QPoint p );
9197
void changeSymbolColor();

python/gui/symbology-ng/qgssinglesymbolrendererwidget.sip

-7
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,6 @@ class QgsSingleSymbolRendererWidget : QgsRendererWidget
3535
\param dockMode True to enable dock mode.
3636
%End
3737

38-
public slots:
39-
void changeSingleSymbol();
40-
41-
void showSymbolLevels();
42-
43-
protected:
44-
4538
};
4639

4740

src/core/layertree/qgslayertreemodellegendnode.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,11 @@ void QgsDataDefinedSizeLegendNode::cacheImage() const
785785
if ( mImage.isNull() )
786786
{
787787
std::unique_ptr<QgsRenderContext> context( createTemporaryRenderContext() );
788+
if ( !context )
789+
{
790+
context.reset( new QgsRenderContext );
791+
context->setScaleFactor( 96 / 25.4 );
792+
}
788793
mImage = mSettings->collapsedLegendImage( *context.get() );
789794
}
790795
}

src/core/qgsdatadefinedsizelegend.cpp

+18
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ QgsDataDefinedSizeLegend::QgsDataDefinedSizeLegend( const QgsDataDefinedSizeLege
2828
, mTitleLabel( other.mTitleLabel )
2929
, mSizeClasses( other.mSizeClasses )
3030
, mSymbol( other.mSymbol.get() ? other.mSymbol->clone() : nullptr )
31+
, mVAlign( other.mVAlign )
32+
, mFont( other.mFont )
33+
, mTextColor( other.mTextColor )
34+
, mTextAlignment( other.mTextAlignment )
3135
{
3236
}
3337

@@ -39,10 +43,24 @@ QgsDataDefinedSizeLegend &QgsDataDefinedSizeLegend::operator=( const QgsDataDefi
3943
mTitleLabel = other.mTitleLabel;
4044
mSizeClasses = other.mSizeClasses;
4145
mSymbol.reset( other.mSymbol.get() ? other.mSymbol->clone() : nullptr );
46+
mVAlign = other.mVAlign;
47+
mFont = other.mFont;
48+
mTextColor = other.mTextColor;
49+
mTextAlignment = other.mTextAlignment;
4250
}
4351
return *this;
4452
}
4553

54+
void QgsDataDefinedSizeLegend::setSymbol( QgsMarkerSymbol *symbol )
55+
{
56+
mSymbol.reset( symbol );
57+
}
58+
59+
QgsMarkerSymbol *QgsDataDefinedSizeLegend::symbol() const
60+
{
61+
return mSymbol.get();
62+
}
63+
4664

4765
void QgsDataDefinedSizeLegend::updateFromSymbolAndProperty( const QgsMarkerSymbol *symbol, const QgsProperty &ddSize )
4866
{

src/core/qgsdatadefinedsizelegend.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/***************************************************************************
2-
qgsdatadefinedsizelegend.cpp
2+
qgsdatadefinedsizelegend.h
33
--------------------------------------
44
Date : June 2017
55
Copyright : (C) 2017 by Martin Dobias
@@ -71,9 +71,9 @@ class CORE_EXPORT QgsDataDefinedSizeLegend
7171
LegendType legendType() const { return mType; }
7272

7373
//! Sets marker symbol that will be used to draw markers in legend
74-
void setSymbol( QgsMarkerSymbol *symbol SIP_TRANSFER ) { mSymbol.reset( symbol ); }
74+
void setSymbol( QgsMarkerSymbol *symbol SIP_TRANSFER );
7575
//! Returns marker symbol that will be used to draw markers in legend
76-
QgsMarkerSymbol *symbol() const { return mSymbol.get(); }
76+
QgsMarkerSymbol *symbol() const;
7777

7878
//! Sets list of classes: each class is a pair of symbol size (in units used by the symbol) and label
7979
void setClasses( const QList<QgsDataDefinedSizeLegend::SizeClass> &classes ) { mSizeClasses = classes; }

src/core/symbology-ng/qgscategorizedsymbolrenderer.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,7 @@ QgsCategorizedSymbolRenderer *QgsCategorizedSymbolRenderer::clone() const
471471
r->setSourceColorRamp( mSourceColorRamp->clone() );
472472
}
473473
r->setUsingSymbolLevels( usingSymbolLevels() );
474+
r->setDataDefinedSizeLegend( mDataDefinedSizeLegend ? new QgsDataDefinedSizeLegend( *mDataDefinedSizeLegend ) : nullptr );
474475

475476
copyRendererData( r );
476477
return r;

src/core/symbology-ng/qgsgraduatedsymbolrenderer.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,7 @@ QgsGraduatedSymbolRenderer *QgsGraduatedSymbolRenderer::clone() const
504504
r->setSourceColorRamp( mSourceColorRamp->clone() );
505505
}
506506
r->setUsingSymbolLevels( usingSymbolLevels() );
507+
r->setDataDefinedSizeLegend( mDataDefinedSizeLegend ? new QgsDataDefinedSizeLegend( *mDataDefinedSizeLegend ) : nullptr );
507508
r->setLabelFormat( labelFormat() );
508509
r->setGraduatedMethod( graduatedMethod() );
509510
copyRendererData( r );

src/core/symbology-ng/qgssinglesymbolrenderer.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ QgsSingleSymbolRenderer *QgsSingleSymbolRenderer::clone() const
100100
{
101101
QgsSingleSymbolRenderer *r = new QgsSingleSymbolRenderer( mSymbol->clone() );
102102
r->setUsingSymbolLevels( usingSymbolLevels() );
103+
r->setDataDefinedSizeLegend( mDataDefinedSizeLegend ? new QgsDataDefinedSizeLegend( *mDataDefinedSizeLegend ) : nullptr );
103104
copyRendererData( r );
104105
return r;
105106
}
@@ -298,7 +299,6 @@ QDomElement QgsSingleSymbolRenderer::save( QDomDocument &doc, const QgsReadWrite
298299

299300
QgsLegendSymbolList QgsSingleSymbolRenderer::legendSymbolItems() const
300301
{
301-
QgsLegendSymbolList lst;
302302
if ( mDataDefinedSizeLegend && mSymbol->type() == QgsSymbol::Marker )
303303
{
304304
const QgsMarkerSymbol *symbol = static_cast<const QgsMarkerSymbol *>( mSymbol.get() );
@@ -307,10 +307,11 @@ QgsLegendSymbolList QgsSingleSymbolRenderer::legendSymbolItems() const
307307
{
308308
QgsDataDefinedSizeLegend ddSizeLegend( *mDataDefinedSizeLegend );
309309
ddSizeLegend.updateFromSymbolAndProperty( static_cast<const QgsMarkerSymbol *>( mSymbol.get() ), sizeDD );
310-
lst += ddSizeLegend.legendSymbolList();
310+
return ddSizeLegend.legendSymbolList();
311311
}
312312
}
313313

314+
QgsLegendSymbolList lst;
314315
lst << QgsLegendSymbolItem( mSymbol.get(), QString(), QString() );
315316
return lst;
316317
}

0 commit comments

Comments
 (0)