mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
Added GUI for data-defined size legend (single/categorized/graduated renderer)
This commit is contained in:
parent
8c4d5bbb95
commit
ea8a2c2bf9
@ -2110,6 +2110,7 @@ QgsSingleSymbolRendererWidget {#qgis_api_break_3_0_QgsSingleSymbolRendere
|
||||
|
||||
- sizeScaleFieldChanged() and scaleMethodChanged() were removed. These settings are no longer exposed in the widget's GUI.
|
||||
- The Mode enum was removed.
|
||||
- changeSingleSymbol() and showSymbolLevels() slots were made private.
|
||||
|
||||
QgsSlider {#qgis_api_break_3_0_QgsSlider}
|
||||
---------
|
||||
|
178
python/core/qgsdatadefinedsizelegend.sip
Normal file
178
python/core/qgsdatadefinedsizelegend.sip
Normal file
@ -0,0 +1,178 @@
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/core/qgsdatadefinedsizelegend.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class QgsDataDefinedSizeLegend
|
||||
{
|
||||
%Docstring
|
||||
Object that keeps configuration of appearance of marker symbol's data-defined size in legend.
|
||||
For example: the list of classes (size values), whether the classes should appear in separate
|
||||
legend nodes or whether to collapse them into one legend node.
|
||||
|
||||
.. versionadded:: 3.0
|
||||
%End
|
||||
|
||||
%TypeHeaderCode
|
||||
#include "qgsdatadefinedsizelegend.h"
|
||||
%End
|
||||
public:
|
||||
QgsDataDefinedSizeLegend();
|
||||
|
||||
QgsDataDefinedSizeLegend( const QgsDataDefinedSizeLegend &other );
|
||||
|
||||
enum LegendType
|
||||
{
|
||||
LegendSeparated,
|
||||
LegendCollapsed,
|
||||
};
|
||||
|
||||
enum VerticalAlignment
|
||||
{
|
||||
AlignCenter,
|
||||
AlignBottom,
|
||||
};
|
||||
|
||||
struct SizeClass
|
||||
{
|
||||
SizeClass( double size, const QString &label );
|
||||
|
||||
double size; //!< Marker size in units used by the symbol (usually millimeters)
|
||||
QString label; //!< Label to be shown with the particular symbol size
|
||||
};
|
||||
|
||||
void setLegendType( LegendType type );
|
||||
%Docstring
|
||||
Sets how the legend should be rendered
|
||||
%End
|
||||
LegendType legendType() const;
|
||||
%Docstring
|
||||
Returns how the legend should be rendered
|
||||
:rtype: LegendType
|
||||
%End
|
||||
|
||||
void setSymbol( QgsMarkerSymbol *symbol /Transfer/ );
|
||||
%Docstring
|
||||
Sets marker symbol that will be used to draw markers in legend
|
||||
%End
|
||||
QgsMarkerSymbol *symbol() const;
|
||||
%Docstring
|
||||
Returns marker symbol that will be used to draw markers in legend
|
||||
:rtype: QgsMarkerSymbol
|
||||
%End
|
||||
|
||||
void setClasses( const QList<QgsDataDefinedSizeLegend::SizeClass> &classes );
|
||||
%Docstring
|
||||
Sets list of classes: each class is a pair of symbol size (in units used by the symbol) and label
|
||||
%End
|
||||
QList<QgsDataDefinedSizeLegend::SizeClass> classes() const;
|
||||
%Docstring
|
||||
Returns list of classes: each class is a pair of symbol size (in units used by the symbol) and label
|
||||
:rtype: list of QgsDataDefinedSizeLegend.SizeClass
|
||||
%End
|
||||
|
||||
void setTitle( const QString &title );
|
||||
%Docstring
|
||||
Sets title label for data-defined size legend
|
||||
%End
|
||||
QString title() const;
|
||||
%Docstring
|
||||
Returns title label for data-defined size legend
|
||||
:rtype: str
|
||||
%End
|
||||
|
||||
void setVerticalAlignment( VerticalAlignment vAlign );
|
||||
%Docstring
|
||||
Sets vertical alignment of symbols - only valid for collapsed legend
|
||||
%End
|
||||
VerticalAlignment verticalAlignment() const;
|
||||
%Docstring
|
||||
Returns vertical alignment of symbols - only valid for collapsed legend
|
||||
:rtype: VerticalAlignment
|
||||
%End
|
||||
|
||||
void setFont( const QFont &font );
|
||||
%Docstring
|
||||
Sets font used for rendering of labels - only valid for collapsed legend
|
||||
%End
|
||||
QFont font() const;
|
||||
%Docstring
|
||||
Returns font used for rendering of labels - only valid for collapsed legend
|
||||
:rtype: QFont
|
||||
%End
|
||||
|
||||
void setTextColor( const QColor &color );
|
||||
%Docstring
|
||||
Sets text color for rendering of labels - only valid for collapsed legend
|
||||
%End
|
||||
QColor textColor() const;
|
||||
%Docstring
|
||||
Returns text color for rendering of labels - only valid for collapsed legend
|
||||
:rtype: QColor
|
||||
%End
|
||||
|
||||
void setTextAlignment( Qt::AlignmentFlag flag );
|
||||
%Docstring
|
||||
Sets horizontal text alignment for rendering of labels - only valid for collapsed legend
|
||||
%End
|
||||
Qt::AlignmentFlag textAlignment() const;
|
||||
%Docstring
|
||||
Returns horizontal text alignment for rendering of labels - only valid for collapsed legend
|
||||
:rtype: Qt.AlignmentFlag
|
||||
%End
|
||||
|
||||
|
||||
void updateFromSymbolAndProperty( const QgsMarkerSymbol *symbol, const QgsProperty &ddSize );
|
||||
%Docstring
|
||||
Updates the list of classes, source symbol and title label from given symbol and property
|
||||
%End
|
||||
|
||||
QgsLegendSymbolList legendSymbolList() const;
|
||||
%Docstring
|
||||
Generates legend symbol items according to the configuration
|
||||
:rtype: QgsLegendSymbolList
|
||||
%End
|
||||
|
||||
void drawCollapsedLegend( QgsRenderContext &context, QSize *outputSize /Out/ = 0, int *labelXOffset /Out/ = 0 ) const;
|
||||
%Docstring
|
||||
Does nothing if legend is not configured as collapsed.
|
||||
%End
|
||||
|
||||
QImage collapsedLegendImage( QgsRenderContext &context, double paddingMM = 1 ) const;
|
||||
%Docstring
|
||||
Returns output image that would be shown in the legend. Returns invalid image if legend is not configured as collapsed.
|
||||
:rtype: QImage
|
||||
%End
|
||||
|
||||
static QgsDataDefinedSizeLegend *readTypeAndAlignmentFromXml( const QDomElement &elem ) /Factory/;
|
||||
%Docstring
|
||||
.. note::
|
||||
|
||||
This is a temporary method and may be removed in the future
|
||||
:rtype: QgsDataDefinedSizeLegend
|
||||
%End
|
||||
|
||||
static void writeTypeAndAlignmentToXml( const QgsDataDefinedSizeLegend &ddsLegend, QDomElement &elem );
|
||||
%Docstring
|
||||
.. note::
|
||||
|
||||
This is a temporary method and may be removed in the future
|
||||
%End
|
||||
|
||||
};
|
||||
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/core/qgsdatadefinedsizelegend.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
@ -239,6 +239,7 @@
|
||||
%Include symbology-ng/qgscategorizedsymbolrendererwidget.sip
|
||||
%Include symbology-ng/qgscptcitycolorrampdialog.sip
|
||||
%Include symbology-ng/qgsdashspacedialog.sip
|
||||
%Include symbology-ng/qgsdatadefinedsizelegenddialog.sip
|
||||
%Include symbology-ng/qgsellipsesymbollayerwidget.sip
|
||||
%Include symbology-ng/qgsgraduatedhistogramwidget.sip
|
||||
%Include symbology-ng/qgsgraduatedsymbolrendererwidget.sip
|
||||
|
57
python/gui/symbology-ng/qgsdatadefinedsizelegenddialog.sip
Normal file
57
python/gui/symbology-ng/qgsdatadefinedsizelegenddialog.sip
Normal file
@ -0,0 +1,57 @@
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/gui/symbology-ng/qgsdatadefinedsizelegenddialog.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class QgsDataDefinedSizeLegendDialog : QDialog
|
||||
{
|
||||
%Docstring
|
||||
Dialog for configuration of appearance of legend for marker symbols with data-defined size.
|
||||
|
||||
.. versionadded:: 3.0
|
||||
%End
|
||||
|
||||
%TypeHeaderCode
|
||||
#include "qgsdatadefinedsizelegenddialog.h"
|
||||
%End
|
||||
public:
|
||||
explicit QgsDataDefinedSizeLegendDialog( const QgsDataDefinedSizeLegend *ddsLegend, QWidget *parent /TransferThis/ = 0 );
|
||||
%Docstring
|
||||
Creates the dialog and initializes the content to what is passed in the legend configuration (may be null)
|
||||
%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.
|
||||
:rtype: QgsDataDefinedSizeLegend
|
||||
%End
|
||||
|
||||
signals:
|
||||
|
||||
};
|
||||
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/gui/symbology-ng/qgsdatadefinedsizelegenddialog.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
@ -86,6 +86,12 @@ and by connecting the slot contextMenuViewCategories(const QPoint&)*
|
||||
%End
|
||||
virtual void refreshSymbolView();
|
||||
|
||||
QgsDataDefinedSizeLegend *showDataDefinedSizeLegendDialog( const QgsMarkerSymbol *symbol, const QgsDataDefinedSizeLegend *ddsLegend, bool *ok /Out/ ) /Factory/;
|
||||
%Docstring
|
||||
.. versionadded:: 3.0
|
||||
:rtype: QgsDataDefinedSizeLegend
|
||||
%End
|
||||
|
||||
protected slots:
|
||||
void contextMenuViewCategories( QPoint p );
|
||||
void changeSymbolColor();
|
||||
|
@ -35,13 +35,6 @@ class QgsSingleSymbolRendererWidget : QgsRendererWidget
|
||||
\param dockMode True to enable dock mode.
|
||||
%End
|
||||
|
||||
public slots:
|
||||
void changeSingleSymbol();
|
||||
|
||||
void showSymbolLevels();
|
||||
|
||||
protected:
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -785,6 +785,11 @@ void QgsDataDefinedSizeLegendNode::cacheImage() const
|
||||
if ( mImage.isNull() )
|
||||
{
|
||||
std::unique_ptr<QgsRenderContext> context( createTemporaryRenderContext() );
|
||||
if ( !context )
|
||||
{
|
||||
context.reset( new QgsRenderContext );
|
||||
context->setScaleFactor( 96 / 25.4 );
|
||||
}
|
||||
mImage = mSettings->collapsedLegendImage( *context.get() );
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,10 @@ QgsDataDefinedSizeLegend::QgsDataDefinedSizeLegend( const QgsDataDefinedSizeLege
|
||||
, mTitleLabel( other.mTitleLabel )
|
||||
, mSizeClasses( other.mSizeClasses )
|
||||
, mSymbol( other.mSymbol.get() ? other.mSymbol->clone() : nullptr )
|
||||
, mVAlign( other.mVAlign )
|
||||
, mFont( other.mFont )
|
||||
, mTextColor( other.mTextColor )
|
||||
, mTextAlignment( other.mTextAlignment )
|
||||
{
|
||||
}
|
||||
|
||||
@ -39,10 +43,24 @@ QgsDataDefinedSizeLegend &QgsDataDefinedSizeLegend::operator=( const QgsDataDefi
|
||||
mTitleLabel = other.mTitleLabel;
|
||||
mSizeClasses = other.mSizeClasses;
|
||||
mSymbol.reset( other.mSymbol.get() ? other.mSymbol->clone() : nullptr );
|
||||
mVAlign = other.mVAlign;
|
||||
mFont = other.mFont;
|
||||
mTextColor = other.mTextColor;
|
||||
mTextAlignment = other.mTextAlignment;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void QgsDataDefinedSizeLegend::setSymbol( QgsMarkerSymbol *symbol )
|
||||
{
|
||||
mSymbol.reset( symbol );
|
||||
}
|
||||
|
||||
QgsMarkerSymbol *QgsDataDefinedSizeLegend::symbol() const
|
||||
{
|
||||
return mSymbol.get();
|
||||
}
|
||||
|
||||
|
||||
void QgsDataDefinedSizeLegend::updateFromSymbolAndProperty( const QgsMarkerSymbol *symbol, const QgsProperty &ddSize )
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
qgsdatadefinedsizelegend.cpp
|
||||
qgsdatadefinedsizelegend.h
|
||||
--------------------------------------
|
||||
Date : June 2017
|
||||
Copyright : (C) 2017 by Martin Dobias
|
||||
@ -71,9 +71,9 @@ class CORE_EXPORT QgsDataDefinedSizeLegend
|
||||
LegendType legendType() const { return mType; }
|
||||
|
||||
//! Sets marker symbol that will be used to draw markers in legend
|
||||
void setSymbol( QgsMarkerSymbol *symbol SIP_TRANSFER ) { mSymbol.reset( symbol ); }
|
||||
void setSymbol( QgsMarkerSymbol *symbol SIP_TRANSFER );
|
||||
//! Returns marker symbol that will be used to draw markers in legend
|
||||
QgsMarkerSymbol *symbol() const { return mSymbol.get(); }
|
||||
QgsMarkerSymbol *symbol() const;
|
||||
|
||||
//! Sets list of classes: each class is a pair of symbol size (in units used by the symbol) and label
|
||||
void setClasses( const QList<QgsDataDefinedSizeLegend::SizeClass> &classes ) { mSizeClasses = classes; }
|
||||
|
@ -471,6 +471,7 @@ QgsCategorizedSymbolRenderer *QgsCategorizedSymbolRenderer::clone() const
|
||||
r->setSourceColorRamp( mSourceColorRamp->clone() );
|
||||
}
|
||||
r->setUsingSymbolLevels( usingSymbolLevels() );
|
||||
r->setDataDefinedSizeLegend( mDataDefinedSizeLegend ? new QgsDataDefinedSizeLegend( *mDataDefinedSizeLegend ) : nullptr );
|
||||
|
||||
copyRendererData( r );
|
||||
return r;
|
||||
|
@ -504,6 +504,7 @@ QgsGraduatedSymbolRenderer *QgsGraduatedSymbolRenderer::clone() const
|
||||
r->setSourceColorRamp( mSourceColorRamp->clone() );
|
||||
}
|
||||
r->setUsingSymbolLevels( usingSymbolLevels() );
|
||||
r->setDataDefinedSizeLegend( mDataDefinedSizeLegend ? new QgsDataDefinedSizeLegend( *mDataDefinedSizeLegend ) : nullptr );
|
||||
r->setLabelFormat( labelFormat() );
|
||||
r->setGraduatedMethod( graduatedMethod() );
|
||||
copyRendererData( r );
|
||||
|
@ -100,6 +100,7 @@ QgsSingleSymbolRenderer *QgsSingleSymbolRenderer::clone() const
|
||||
{
|
||||
QgsSingleSymbolRenderer *r = new QgsSingleSymbolRenderer( mSymbol->clone() );
|
||||
r->setUsingSymbolLevels( usingSymbolLevels() );
|
||||
r->setDataDefinedSizeLegend( mDataDefinedSizeLegend ? new QgsDataDefinedSizeLegend( *mDataDefinedSizeLegend ) : nullptr );
|
||||
copyRendererData( r );
|
||||
return r;
|
||||
}
|
||||
@ -298,7 +299,6 @@ QDomElement QgsSingleSymbolRenderer::save( QDomDocument &doc, const QgsReadWrite
|
||||
|
||||
QgsLegendSymbolList QgsSingleSymbolRenderer::legendSymbolItems() const
|
||||
{
|
||||
QgsLegendSymbolList lst;
|
||||
if ( mDataDefinedSizeLegend && mSymbol->type() == QgsSymbol::Marker )
|
||||
{
|
||||
const QgsMarkerSymbol *symbol = static_cast<const QgsMarkerSymbol *>( mSymbol.get() );
|
||||
@ -307,10 +307,11 @@ QgsLegendSymbolList QgsSingleSymbolRenderer::legendSymbolItems() const
|
||||
{
|
||||
QgsDataDefinedSizeLegend ddSizeLegend( *mDataDefinedSizeLegend );
|
||||
ddSizeLegend.updateFromSymbolAndProperty( static_cast<const QgsMarkerSymbol *>( mSymbol.get() ), sizeDD );
|
||||
lst += ddSizeLegend.legendSymbolList();
|
||||
return ddSizeLegend.legendSymbolList();
|
||||
}
|
||||
}
|
||||
|
||||
QgsLegendSymbolList lst;
|
||||
lst << QgsLegendSymbolItem( mSymbol.get(), QString(), QString() );
|
||||
return lst;
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ SET(QGIS_GUI_SRCS
|
||||
symbology-ng/qgscategorizedsymbolrendererwidget.cpp
|
||||
symbology-ng/qgscptcitycolorrampdialog.cpp
|
||||
symbology-ng/qgsdashspacedialog.cpp
|
||||
symbology-ng/qgsdatadefinedsizelegenddialog.cpp
|
||||
symbology-ng/qgsellipsesymbollayerwidget.cpp
|
||||
symbology-ng/qgsgraduatedhistogramwidget.cpp
|
||||
symbology-ng/qgsgraduatedsymbolrendererwidget.cpp
|
||||
@ -493,6 +494,7 @@ SET(QGIS_GUI_MOC_HDRS
|
||||
symbology-ng/qgscategorizedsymbolrendererwidget.h
|
||||
symbology-ng/qgscptcitycolorrampdialog.h
|
||||
symbology-ng/qgsdashspacedialog.h
|
||||
symbology-ng/qgsdatadefinedsizelegenddialog.h
|
||||
symbology-ng/qgsellipsesymbollayerwidget.h
|
||||
symbology-ng/qgsgraduatedhistogramwidget.h
|
||||
symbology-ng/qgsgraduatedsymbolrendererwidget.h
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "qgscategorizedsymbolrenderer.h"
|
||||
|
||||
#include "qgsdatadefinedsizelegend.h"
|
||||
#include "qgssymbol.h"
|
||||
#include "qgssymbollayerutils.h"
|
||||
#include "qgscolorramp.h"
|
||||
@ -464,6 +465,8 @@ QgsCategorizedSymbolRendererWidget::QgsCategorizedSymbolRendererWidget( QgsVecto
|
||||
advMenu->addAction( tr( "Match to saved symbols" ), this, SLOT( matchToSymbolsFromLibrary() ) );
|
||||
advMenu->addAction( tr( "Match to symbols from file..." ), this, SLOT( matchToSymbolsFromXml() ) );
|
||||
advMenu->addAction( tr( "Symbol levels..." ), this, SLOT( showSymbolLevels() ) );
|
||||
if ( mCategorizedSymbol->type() == QgsSymbol::Marker )
|
||||
advMenu->addAction( tr( "Data-defined size legend..." ), this, &QgsCategorizedSymbolRendererWidget::dataDefinedSizeLegend );
|
||||
|
||||
btnAdvanced->setMenu( advMenu );
|
||||
|
||||
@ -1034,3 +1037,15 @@ QgsExpressionContext QgsCategorizedSymbolRendererWidget::createExpressionContext
|
||||
|
||||
return expContext;
|
||||
}
|
||||
|
||||
void QgsCategorizedSymbolRendererWidget::dataDefinedSizeLegend()
|
||||
{
|
||||
bool ok;
|
||||
QgsMarkerSymbol *s = static_cast<QgsMarkerSymbol *>( mCategorizedSymbol ); // this should be only enabled for marker symbols
|
||||
std::unique_ptr<QgsDataDefinedSizeLegend> ddsLegend( showDataDefinedSizeLegendDialog( s, mRenderer->dataDefinedSizeLegend(), &ok ) );
|
||||
if ( ok )
|
||||
{
|
||||
mRenderer->setDataDefinedSizeLegend( ddsLegend.release() ); // ownership is passed from dlg to renderer
|
||||
emit widgetChanged();
|
||||
}
|
||||
}
|
||||
|
@ -145,6 +145,7 @@ class GUI_EXPORT QgsCategorizedSymbolRendererWidget : public QgsRendererWidget,
|
||||
|
||||
void cleanUpSymbolSelector( QgsPanelWidget *container );
|
||||
void updateSymbolsFromWidget();
|
||||
void dataDefinedSizeLegend();
|
||||
|
||||
protected:
|
||||
|
||||
|
105
src/gui/symbology-ng/qgsdatadefinedsizelegenddialog.cpp
Normal file
105
src/gui/symbology-ng/qgsdatadefinedsizelegenddialog.cpp
Normal file
@ -0,0 +1,105 @@
|
||||
/***************************************************************************
|
||||
qgsdatadefinedsizelegenddialog.cpp
|
||||
--------------------------------------
|
||||
Date : June 2017
|
||||
Copyright : (C) 2017 by Martin Dobias
|
||||
Email : wonder dot sk at gmail dot com
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgsdatadefinedsizelegenddialog.h"
|
||||
|
||||
#include "qgsdatadefinedsizelegend.h"
|
||||
#include "qgslayertree.h"
|
||||
#include "qgslayertreemodel.h"
|
||||
#include "qgssinglesymbolrenderer.h"
|
||||
#include "qgssymbol.h"
|
||||
#include "qgssymbollayer.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
|
||||
QgsDataDefinedSizeLegendDialog::QgsDataDefinedSizeLegendDialog( const QgsDataDefinedSizeLegend *ddsLegend, QWidget *parent )
|
||||
: QDialog( parent )
|
||||
{
|
||||
setupUi( this );
|
||||
|
||||
if ( !ddsLegend )
|
||||
{
|
||||
radDisabled->setChecked( true );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( ddsLegend->legendType() == QgsDataDefinedSizeLegend::LegendSeparated )
|
||||
radSeparated->setChecked( true );
|
||||
else
|
||||
radCollapsed->setChecked( true );
|
||||
|
||||
if ( ddsLegend->verticalAlignment() == QgsDataDefinedSizeLegend::AlignBottom )
|
||||
cboAlignSymbols->setCurrentIndex( 0 );
|
||||
else
|
||||
cboAlignSymbols->setCurrentIndex( 1 );
|
||||
}
|
||||
|
||||
// prepare default source symbol - it should be hopefully replaced in setSourceSymbol() later
|
||||
mSourceSymbol.reset( static_cast<QgsMarkerSymbol *>( QgsSymbol::defaultSymbol( QgsWkbTypes::PointGeometry ) ) );
|
||||
QgsProperty property = QgsProperty::fromValue( 1 );
|
||||
property.setTransformer( new QgsSizeScaleTransformer( QgsSizeScaleTransformer::Linear, 0, 1, 0, 20 ) );
|
||||
mSourceSymbol->setDataDefinedSize( property );
|
||||
|
||||
// prepare layer and model to preview legend
|
||||
mPreviewLayer = new QgsVectorLayer( "Point?crs=EPSG:4326", "Preview", "memory" );
|
||||
mPreviewTree = new QgsLayerTree;
|
||||
mPreviewLayerNode = mPreviewTree->addLayer( mPreviewLayer ); // node owned by the tree
|
||||
mPreviewModel = new QgsLayerTreeModel( mPreviewTree );
|
||||
viewLayerTree->setModel( mPreviewModel );
|
||||
|
||||
connect( cboAlignSymbols, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), [ = ] { updatePreview(); } );
|
||||
connect( radDisabled, &QRadioButton::clicked, this, &QgsDataDefinedSizeLegendDialog::updatePreview );
|
||||
connect( radSeparated, &QRadioButton::clicked, this, &QgsDataDefinedSizeLegendDialog::updatePreview );
|
||||
connect( radCollapsed, &QRadioButton::clicked, this, &QgsDataDefinedSizeLegendDialog::updatePreview );
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
QgsDataDefinedSizeLegendDialog::~QgsDataDefinedSizeLegendDialog()
|
||||
{
|
||||
delete mPreviewModel;
|
||||
delete mPreviewTree;
|
||||
delete mPreviewLayer;
|
||||
}
|
||||
|
||||
void QgsDataDefinedSizeLegendDialog::setSourceSymbol( QgsMarkerSymbol *symbol )
|
||||
{
|
||||
mSourceSymbol.reset( symbol );
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void QgsDataDefinedSizeLegendDialog::setLegendMapViewData( double mapUnitsPerPixel, int dpi, double scale )
|
||||
{
|
||||
mPreviewModel->setLegendMapViewData( mapUnitsPerPixel, dpi, scale );
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
QgsDataDefinedSizeLegend *QgsDataDefinedSizeLegendDialog::dataDefinedSizeLegend() const
|
||||
{
|
||||
if ( radDisabled->isChecked() )
|
||||
return nullptr;
|
||||
|
||||
QgsDataDefinedSizeLegend *ddsLegend = new QgsDataDefinedSizeLegend;
|
||||
ddsLegend->setLegendType( radSeparated->isChecked() ? QgsDataDefinedSizeLegend::LegendSeparated : QgsDataDefinedSizeLegend::LegendCollapsed );
|
||||
ddsLegend->setVerticalAlignment( cboAlignSymbols->currentIndex() == 0 ? QgsDataDefinedSizeLegend::AlignBottom : QgsDataDefinedSizeLegend::AlignCenter );
|
||||
return ddsLegend;
|
||||
}
|
||||
|
||||
void QgsDataDefinedSizeLegendDialog::updatePreview()
|
||||
{
|
||||
QgsSingleSymbolRenderer *r = new QgsSingleSymbolRenderer( mSourceSymbol->clone() );
|
||||
r->setDataDefinedSizeLegend( dataDefinedSizeLegend() );
|
||||
mPreviewLayer->setRenderer( r );
|
||||
mPreviewModel->refreshLayerLegend( mPreviewLayerNode );
|
||||
viewLayerTree->expandAll();
|
||||
}
|
68
src/gui/symbology-ng/qgsdatadefinedsizelegenddialog.h
Normal file
68
src/gui/symbology-ng/qgsdatadefinedsizelegenddialog.h
Normal file
@ -0,0 +1,68 @@
|
||||
/***************************************************************************
|
||||
qgsdatadefinedsizelegenddialog.h
|
||||
--------------------------------------
|
||||
Date : June 2017
|
||||
Copyright : (C) 2017 by Martin Dobias
|
||||
Email : wonder dot sk at gmail dot com
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef QGSDATADEFINEDSIZELEGENDDIALOG_H
|
||||
#define QGSDATADEFINEDSIZELEGENDDIALOG_H
|
||||
|
||||
#include "qgis.h"
|
||||
#include "qgis_gui.h"
|
||||
|
||||
#include <memory>
|
||||
#include <QDialog>
|
||||
#include <ui_qgsdatadefinedsizelegenddialog.h>
|
||||
|
||||
class QgsDataDefinedSizeLegend;
|
||||
class QgsLayerTree;
|
||||
class QgsLayerTreeLayer;
|
||||
class QgsLayerTreeModel;
|
||||
class QgsMarkerSymbol;
|
||||
class QgsVectorLayer;
|
||||
|
||||
/** \ingroup gui
|
||||
* Dialog for configuration of appearance of legend for marker symbols with data-defined size.
|
||||
*
|
||||
* \since QGIS 3.0
|
||||
*/
|
||||
class GUI_EXPORT QgsDataDefinedSizeLegendDialog : public QDialog, private Ui::QgsDataDefinedSizeLegendDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
//! Creates the dialog and initializes the content to what is passed in the legend configuration (may be null)
|
||||
explicit QgsDataDefinedSizeLegendDialog( const QgsDataDefinedSizeLegend *ddsLegend, QWidget *parent SIP_TRANSFERTHIS = nullptr );
|
||||
~QgsDataDefinedSizeLegendDialog();
|
||||
|
||||
//! Use given symbol for preview. Takes ownership of the symbol. It should have data-defined size enabled + size scale transformer attached.
|
||||
void setSourceSymbol( QgsMarkerSymbol *symbol SIP_TRANSFER );
|
||||
|
||||
//! Setup map view details to make preview match the expected output
|
||||
void setLegendMapViewData( double mapUnitsPerPixel, int dpi, double scale );
|
||||
|
||||
//! Returns configuration as set up in the dialog (may be null). Ownership is passed to the caller.
|
||||
QgsDataDefinedSizeLegend *dataDefinedSizeLegend() const SIP_FACTORY;
|
||||
|
||||
signals:
|
||||
|
||||
private slots:
|
||||
void updatePreview();
|
||||
|
||||
private:
|
||||
std::unique_ptr<QgsMarkerSymbol> mSourceSymbol;
|
||||
QgsLayerTreeModel *mPreviewModel;
|
||||
QgsLayerTree *mPreviewTree;
|
||||
QgsLayerTreeLayer *mPreviewLayerNode;
|
||||
QgsVectorLayer *mPreviewLayer;
|
||||
};
|
||||
|
||||
#endif // QGSDATADEFINEDSIZELEGENDDIALOG_H
|
@ -15,6 +15,7 @@
|
||||
#include "qgsgraduatedsymbolrendererwidget.h"
|
||||
#include "qgspanelwidget.h"
|
||||
|
||||
#include "qgsdatadefinedsizelegend.h"
|
||||
#include "qgssymbol.h"
|
||||
#include "qgssymbollayerutils.h"
|
||||
#include "qgscolorramp.h"
|
||||
@ -511,6 +512,8 @@ QgsGraduatedSymbolRendererWidget::QgsGraduatedSymbolRendererWidget( QgsVectorLay
|
||||
QMenu *advMenu = new QMenu( this );
|
||||
|
||||
advMenu->addAction( tr( "Symbol levels..." ), this, SLOT( showSymbolLevels() ) );
|
||||
if ( mGraduatedSymbol->type() == QgsSymbol::Marker )
|
||||
advMenu->addAction( tr( "Data-defined size legend..." ), this, &QgsGraduatedSymbolRendererWidget::dataDefinedSizeLegend );
|
||||
|
||||
btnAdvanced->setMenu( advMenu );
|
||||
|
||||
@ -1166,3 +1169,15 @@ void QgsGraduatedSymbolRendererWidget::keyPressEvent( QKeyEvent *event )
|
||||
emit widgetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void QgsGraduatedSymbolRendererWidget::dataDefinedSizeLegend()
|
||||
{
|
||||
bool ok;
|
||||
QgsMarkerSymbol *s = static_cast<QgsMarkerSymbol *>( mGraduatedSymbol ); // this should be only enabled for marker symbols
|
||||
std::unique_ptr<QgsDataDefinedSizeLegend> ddsLegend( showDataDefinedSizeLegendDialog( s, mRenderer->dataDefinedSizeLegend(), &ok ) );
|
||||
if ( ok )
|
||||
{
|
||||
mRenderer->setDataDefinedSizeLegend( ddsLegend.release() ); // ownership is passed from dlg to renderer
|
||||
emit widgetChanged();
|
||||
}
|
||||
}
|
||||
|
@ -127,6 +127,7 @@ class GUI_EXPORT QgsGraduatedSymbolRendererWidget : public QgsRendererWidget, pr
|
||||
void cleanUpSymbolSelector( QgsPanelWidget *container );
|
||||
void updateSymbolsFromWidget();
|
||||
void toggleMethodWidgets( int idx );
|
||||
void dataDefinedSizeLegend();
|
||||
|
||||
protected:
|
||||
void updateUiFromRenderer( bool updateCount = true );
|
||||
|
@ -13,6 +13,8 @@
|
||||
* *
|
||||
***************************************************************************/
|
||||
#include "qgsrendererwidget.h"
|
||||
|
||||
#include "qgsdatadefinedsizelegenddialog.h"
|
||||
#include "qgssymbol.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
#include "qgscolordialog.h"
|
||||
@ -273,6 +275,37 @@ void QgsRendererWidget::applyChanges()
|
||||
apply();
|
||||
}
|
||||
|
||||
QgsDataDefinedSizeLegend *QgsRendererWidget::showDataDefinedSizeLegendDialog( const QgsMarkerSymbol *symbol, const QgsDataDefinedSizeLegend *ddsLegend, bool *ok )
|
||||
{
|
||||
*ok = false;
|
||||
|
||||
QgsProperty ddSize = symbol->dataDefinedSize();
|
||||
if ( !ddSize || !ddSize.isActive() )
|
||||
{
|
||||
QMessageBox::warning( this, tr( "Data-defined size legend" ), tr( "Data-defined size is not enabled!" ) );
|
||||
return nullptr;
|
||||
}
|
||||
if ( !ddSize.transformer() )
|
||||
{
|
||||
QMessageBox::warning( this, tr( "Data-defined size legend" ), tr( "Data-defined size is enabled, but without size scale transformer. Use assistant to define it." ) );
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QgsDataDefinedSizeLegendDialog dlg( ddsLegend );
|
||||
dlg.setSourceSymbol( symbol->clone() );
|
||||
if ( QgsMapCanvas *canvas = mContext.mapCanvas() )
|
||||
{
|
||||
dlg.setLegendMapViewData( canvas->mapUnitsPerPixel(), canvas->mapSettings().outputDpi(), canvas->scale() );
|
||||
}
|
||||
|
||||
if ( !dlg.exec() )
|
||||
return nullptr;
|
||||
|
||||
*ok = true;
|
||||
return dlg.dataDefinedSizeLegend();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// QgsDataDefinedValueDialog
|
||||
//
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "qgssymbolwidgetcontext.h"
|
||||
#include "qgssymbollayer.h"
|
||||
|
||||
class QgsDataDefinedSizeLegend;
|
||||
class QgsVectorLayer;
|
||||
class QgsStyle;
|
||||
class QgsFeatureRenderer;
|
||||
@ -98,6 +99,11 @@ class GUI_EXPORT QgsRendererWidget : public QgsPanelWidget
|
||||
virtual QList<QgsSymbol *> selectedSymbols() { return QList<QgsSymbol *>(); }
|
||||
virtual void refreshSymbolView() {}
|
||||
|
||||
//! Shows GUI to setup data-defined size legend. If accepted, ok argument will be true and a new legend configuration is returned.
|
||||
//! Caller takes ownership of the returned object.
|
||||
//! \since QGIS 3.0
|
||||
QgsDataDefinedSizeLegend *showDataDefinedSizeLegendDialog( const QgsMarkerSymbol *symbol, const QgsDataDefinedSizeLegend *ddsLegend, bool *ok SIP_OUT ) SIP_FACTORY;
|
||||
|
||||
protected slots:
|
||||
void contextMenuViewCategories( QPoint p );
|
||||
//! Change color of selected symbols
|
||||
|
@ -14,6 +14,7 @@
|
||||
***************************************************************************/
|
||||
#include "qgssinglesymbolrendererwidget.h"
|
||||
|
||||
#include "qgsdatadefinedsizelegend.h"
|
||||
#include "qgssinglesymbolrenderer.h"
|
||||
#include "qgssymbol.h"
|
||||
|
||||
@ -24,6 +25,7 @@
|
||||
|
||||
#include <QMenu>
|
||||
|
||||
|
||||
QgsRendererWidget *QgsSingleSymbolRendererWidget::create( QgsVectorLayer *layer, QgsStyle *style, QgsFeatureRenderer *renderer )
|
||||
{
|
||||
return new QgsSingleSymbolRendererWidget( layer, style, renderer );
|
||||
@ -62,7 +64,9 @@ QgsSingleSymbolRendererWidget::QgsSingleSymbolRendererWidget( QgsVectorLayer *la
|
||||
// advanced actions - data defined rendering
|
||||
QMenu *advMenu = mSelector->advancedMenu();
|
||||
|
||||
advMenu->addAction( tr( "Symbol levels..." ), this, SLOT( showSymbolLevels() ) );
|
||||
advMenu->addAction( tr( "Symbol levels..." ), this, &QgsSingleSymbolRendererWidget::showSymbolLevels );
|
||||
if ( mSingleSymbol->type() == QgsSymbol::Marker )
|
||||
advMenu->addAction( tr( "Data-defined size legend..." ), this, &QgsSingleSymbolRendererWidget::dataDefinedSizeLegend );
|
||||
}
|
||||
|
||||
QgsSingleSymbolRendererWidget::~QgsSingleSymbolRendererWidget()
|
||||
@ -105,3 +109,15 @@ void QgsSingleSymbolRendererWidget::showSymbolLevels()
|
||||
{
|
||||
showSymbolLevelsDialog( mRenderer );
|
||||
}
|
||||
|
||||
void QgsSingleSymbolRendererWidget::dataDefinedSizeLegend()
|
||||
{
|
||||
bool ok;
|
||||
QgsMarkerSymbol *s = static_cast<QgsMarkerSymbol *>( mSingleSymbol ); // this should be only enabled for marker symbols
|
||||
std::unique_ptr<QgsDataDefinedSizeLegend> ddsLegend( showDataDefinedSizeLegendDialog( s, mRenderer->dataDefinedSizeLegend(), &ok ) );
|
||||
if ( ok )
|
||||
{
|
||||
mRenderer->setDataDefinedSizeLegend( ddsLegend.release() ); // ownership is passed from dlg to renderer
|
||||
emit widgetChanged();
|
||||
}
|
||||
}
|
||||
|
@ -48,12 +48,14 @@ class GUI_EXPORT QgsSingleSymbolRendererWidget : public QgsRendererWidget
|
||||
*/
|
||||
virtual void setDockMode( bool dockMode ) override;
|
||||
|
||||
public slots:
|
||||
private slots:
|
||||
void changeSingleSymbol();
|
||||
|
||||
void showSymbolLevels();
|
||||
|
||||
protected:
|
||||
void dataDefinedSizeLegend();
|
||||
|
||||
private:
|
||||
|
||||
QgsSingleSymbolRenderer *mRenderer = nullptr;
|
||||
QgsSymbolSelectorWidget *mSelector = nullptr;
|
||||
|
136
src/ui/qgsdatadefinedsizelegenddialog.ui
Normal file
136
src/ui/qgsdatadefinedsizelegenddialog.ui
Normal file
@ -0,0 +1,136 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>QgsDataDefinedSizeLegendDialog</class>
|
||||
<widget class="QDialog" name="QgsDataDefinedSizeLegendDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>674</width>
|
||||
<height>393</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Data-defined size legend</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radDisabled">
|
||||
<property name="text">
|
||||
<string>Legend not enabled</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radSeparated">
|
||||
<property name="text">
|
||||
<string>Separated legend items</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radCollapsed">
|
||||
<property name="text">
|
||||
<string>Collapsed legend</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Options (collapsed only)</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Align symbols</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cboAlignSymbols">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Bottom</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Center</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QTreeView" name="viewLayerTree">
|
||||
<property name="headerHidden">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>radDisabled</tabstop>
|
||||
<tabstop>radSeparated</tabstop>
|
||||
<tabstop>radCollapsed</tabstop>
|
||||
<tabstop>cboAlignSymbols</tabstop>
|
||||
<tabstop>viewLayerTree</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>QgsDataDefinedSizeLegendDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>QgsDataDefinedSizeLegendDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
Loading…
x
Reference in New Issue
Block a user