Added GUI for data-defined size legend (single/categorized/graduated renderer)

This commit is contained in:
Martin Dobias 2017-06-16 16:24:30 +02:00
parent 8c4d5bbb95
commit ea8a2c2bf9
24 changed files with 677 additions and 15 deletions

View File

@ -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}
---------

View 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 *
************************************************************************/

View File

@ -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

View 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 *
************************************************************************/

View File

@ -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();

View File

@ -35,13 +35,6 @@ class QgsSingleSymbolRendererWidget : QgsRendererWidget
\param dockMode True to enable dock mode.
%End
public slots:
void changeSingleSymbol();
void showSymbolLevels();
protected:
};

View File

@ -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() );
}
}

View File

@ -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 )
{

View File

@ -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; }

View File

@ -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;

View File

@ -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 );

View File

@ -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;
}

View File

@ -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

View File

@ -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();
}
}

View File

@ -145,6 +145,7 @@ class GUI_EXPORT QgsCategorizedSymbolRendererWidget : public QgsRendererWidget,
void cleanUpSymbolSelector( QgsPanelWidget *container );
void updateSymbolsFromWidget();
void dataDefinedSizeLegend();
protected:

View 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();
}

View 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

View File

@ -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();
}
}

View File

@ -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 );

View File

@ -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
//

View File

@ -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

View File

@ -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();
}
}

View File

@ -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;

View 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>