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

This commit is contained in:
Martin Dobias 2017-06-19 15:55:46 +02:00
parent 517fefe02a
commit e3270edb7a
18 changed files with 218 additions and 207 deletions

View File

@ -987,8 +987,7 @@ QgsDiagramRenderer {#qgis_api_break_3_0_QgsDiagramRenderer}
- renderDiagram() now takes an optional data defined overrides collection argument.
- readXml(), _readXml(), writeXml(), _writeXml() do not take QgsVectorLayer as an argument anymore.
- readXml(), _readXml(), writeXml(), _writeXml() require a new argument: a reference to QgsReadWriteContext
- sizeLegend() and setSizeLegend() have been replaced by dataDefinedSizeLegend() and setDataDefinedSizeLegend() methods.
- sizeLegendSymbol() and setSizeLegendSymbol() have been moved to QgsLinearlyInterpolatedDiagramRenderer subclass.
- sizeLegend(), setSizeLegend(), sizeLegendSymbol() and setSizeLegendSymbol() have been replaced by dataDefinedSizeLegend() and setDataDefinedSizeLegend() methods in QgsLinearlyInterpolatedDiagramRenderer.
QgsDiagramLayerSettings {#qgis_api_break_3_0_QgsDiagramLayerSettings}

View File

@ -152,19 +152,15 @@ Returns output image that would be shown in the legend. Returns invalid image if
:rtype: QImage
%End
static QgsDataDefinedSizeLegend *readTypeAndAlignmentFromXml( const QDomElement &elem ) /Factory/;
static QgsDataDefinedSizeLegend *readXml( const QDomElement &elem, const QgsReadWriteContext &context ) /Factory/;
%Docstring
.. note::
This is a temporary method and may be removed in the future
Creates instance from given element and returns it (caller takes ownership). Returns null on error.
:rtype: QgsDataDefinedSizeLegend
%End
static void writeTypeAndAlignmentToXml( const QgsDataDefinedSizeLegend &ddsLegend, QDomElement &elem );
void writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const;
%Docstring
.. note::
This is a temporary method and may be removed in the future
Writes configuration to the given XML element.
%End
};

View File

@ -720,24 +720,6 @@ Returns list with all diagram settings in the renderer
virtual QList< QgsLayerTreeModelLegendNode * > legendItems( QgsLayerTreeLayer *nodeLayer ) const /Factory/;
QgsMarkerSymbol *sizeLegendSymbol() const;
%Docstring
Returns the marker symbol used for rendering the diagram size legend.
.. versionadded:: 2.16
.. seealso:: setSizeLegendSymbol()
.. seealso:: sizeLegend()
:rtype: QgsMarkerSymbol
%End
void setSizeLegendSymbol( QgsMarkerSymbol *symbol /Transfer/ );
%Docstring
Sets the marker symbol used for rendering the diagram size legend.
\param symbol marker symbol, ownership is transferred to the renderer.
.. versionadded:: 2.16
.. seealso:: sizeLegendSymbol()
.. seealso:: setSizeLegend()
%End
void setDataDefinedSizeLegend( QgsDataDefinedSizeLegend *settings /Transfer/ );
%Docstring
Configures appearance of legend. Takes ownership of the passed settings objects.

View File

@ -10,6 +10,7 @@
class QgsDataDefinedSizeLegendDialog : QDialog
{
%Docstring
@ -22,22 +23,12 @@ class QgsDataDefinedSizeLegendDialog : QDialog
#include "qgsdatadefinedsizelegenddialog.h"
%End
public:
explicit QgsDataDefinedSizeLegendDialog( const QgsDataDefinedSizeLegend *ddsLegend, QWidget *parent /TransferThis/ = 0 );
explicit QgsDataDefinedSizeLegendDialog( const QgsDataDefinedSizeLegend *ddsLegend, const QgsProperty &ddSize, QgsMarkerSymbol *overrideSymbol /Transfer/, QgsMapCanvas *canvas = 0, QWidget *parent /TransferThis/ = 0 );
%Docstring
Creates the dialog and initializes the content to what is passed in the legend configuration (may be null)
when the symbol is given from outside rather than being set inside QgsDataDefinedSizeLegend.
%End
~QgsDataDefinedSizeLegendDialog();
void setSourceSymbol( QgsMarkerSymbol *symbol /Transfer/ );
%Docstring
Use given symbol for preview. Takes ownership of the symbol. It should have data-defined size enabled + size scale transformer attached.
%End
void setLegendMapViewData( double mapUnitsPerPixel, int dpi, double scale );
%Docstring
Setup map view details to make preview match the expected output
%End
QgsDataDefinedSizeLegend *dataDefinedSizeLegend() const /Factory/;
%Docstring
Returns configuration as set up in the dialog (may be null). Ownership is passed to the caller.

View File

@ -190,8 +190,6 @@ QgsDiagramProperties::QgsDiagramProperties( QgsVectorLayer *layer, QWidget *pare
newItem->setFlags( newItem->flags() & ~Qt::ItemIsDropEnabled );
}
mSizeLegendSymbol.reset( QgsMarkerSymbol::createSimple( QgsStringMap() ) );
const QgsDiagramRenderer *dr = layer->diagramRenderer();
if ( !dr ) //no diagram renderer yet, insert reasonable default
{
@ -360,7 +358,6 @@ QgsDiagramProperties::QgsDiagramProperties( QgsVectorLayer *layer, QWidget *pare
mSizeFieldExpressionWidget->setField( lidr->classificationField() );
}
mSizeLegendSymbol.reset( lidr->sizeLegendSymbol() ? lidr->sizeLegendSymbol()->clone() : QgsMarkerSymbol::createSimple( QgsStringMap() ) );
mSizeLegend.reset( lidr->dataDefinedSizeLegend() ? new QgsDataDefinedSizeLegend( *lidr->dataDefinedSizeLegend() ) : nullptr );
}
}
@ -402,9 +399,6 @@ QgsDiagramProperties::QgsDiagramProperties( QgsVectorLayer *layer, QWidget *pare
}
}
QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( mSizeLegendSymbol.get(), mButtonSizeLegendSymbol->iconSize() );
mButtonSizeLegendSymbol->setIcon( icon );
connect( mAddAttributeExpression, &QPushButton::clicked, this, &QgsDiagramProperties::showAddAttributeExpressionDialog );
registerDataDefinedButton( mBackgroundColorDDBtn, QgsDiagramLayerSettings::BackgroundColor );
registerDataDefinedButton( mLineColorDDBtn, QgsDiagramLayerSettings::StrokeColor );
@ -818,7 +812,6 @@ void QgsDiagramProperties::apply()
}
dr->setDiagramSettings( ds );
dr->setSizeLegendSymbol( mSizeLegendSymbol->clone() );
dr->setDataDefinedSizeLegend( mSizeLegend ? new QgsDataDefinedSizeLegend( *mSizeLegend ) : nullptr );
renderer = dr;
@ -941,52 +934,20 @@ void QgsDiagramProperties::on_mPlacementComboBox_currentIndexChanged( int index
chkLineOrientationDependent->setEnabled( linePlacementEnabled );
}
void QgsDiagramProperties::on_mButtonSizeLegendSymbol_clicked()
{
QgsMarkerSymbol *newSymbol = mSizeLegendSymbol->clone();
QgsSymbolWidgetContext context;
context.setMapCanvas( mMapCanvas );
QgsExpressionContext ec = createExpressionContext();
context.setExpressionContext( &ec );
QgsSymbolSelectorDialog d( newSymbol, QgsStyle::defaultStyle(), mLayer, this );
d.setContext( context );
if ( d.exec() == QDialog::Accepted )
{
mSizeLegendSymbol.reset( newSymbol );
QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( mSizeLegendSymbol.get(), mButtonSizeLegendSymbol->iconSize() );
mButtonSizeLegendSymbol->setIcon( icon );
}
else
{
delete newSymbol;
}
}
void QgsDiagramProperties::scalingTypeChanged()
{
mSizeLegendGroupBox->setEnabled( mAttributeBasedScalingRadio->isChecked() );
mButtonSizeLegendSettings->setEnabled( mAttributeBasedScalingRadio->isChecked() );
}
void QgsDiagramProperties::showSizeLegendDialog()
{
QgsDataDefinedSizeLegendDialog dlg( mSizeLegend.get() );
QgsMarkerSymbol *symbol = mSizeLegendSymbol->clone();
// prepare size transformer
bool isExpression;
QString sizeFieldNameOrExp = mSizeFieldExpressionWidget->currentField( &isExpression );
QgsProperty ddSize = isExpression ? QgsProperty::fromExpression( sizeFieldNameOrExp ) : QgsProperty::fromField( sizeFieldNameOrExp );
ddSize.setTransformer( new QgsSizeScaleTransformer( QgsSizeScaleTransformer::Linear, 0.0, mMaxValueSpinBox->value(), 0.0, mSizeSpinBox->value() ) );
symbol->setDataDefinedSize( ddSize );
dlg.setSourceSymbol( symbol );
if ( mMapCanvas )
{
dlg.setLegendMapViewData( mMapCanvas->mapUnitsPerPixel(), mMapCanvas->mapSettings().outputDpi(), mMapCanvas->scale() );
}
QgsDataDefinedSizeLegendDialog dlg( mSizeLegend.get(), ddSize, nullptr, mMapCanvas );
if ( !dlg.exec() )
return;

View File

@ -52,7 +52,6 @@ class APP_EXPORT QgsDiagramProperties : public QWidget, private Ui::QgsDiagramPr
void showAddAttributeExpressionDialog();
void on_mDiagramStackedWidget_currentChanged( int index );
void on_mPlacementComboBox_currentIndexChanged( int index );
void on_mButtonSizeLegendSymbol_clicked();
void scalingTypeChanged();
void showSizeLegendDialog();
@ -81,7 +80,6 @@ class APP_EXPORT QgsDiagramProperties : public QWidget, private Ui::QgsDiagramPr
// Keeps track of the diagram type to properly save / restore settings when the diagram type combo box is set to no diagram.
QString mDiagramType;
std::unique_ptr< QgsMarkerSymbol > mSizeLegendSymbol;
std::unique_ptr< QgsDataDefinedSizeLegend > mSizeLegend;
QString guessLegendText( const QString &expression );

View File

@ -290,18 +290,85 @@ QImage QgsDataDefinedSizeLegend::collapsedLegendImage( QgsRenderContext &context
return img;
}
QgsDataDefinedSizeLegend *QgsDataDefinedSizeLegend::readTypeAndAlignmentFromXml( const QDomElement &elem )
QgsDataDefinedSizeLegend *QgsDataDefinedSizeLegend::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
{
if ( elem.isNull() )
return nullptr;
QgsDataDefinedSizeLegend *ddsLegend = new QgsDataDefinedSizeLegend;
ddsLegend->setLegendType( elem.attribute( "type" ) == "collapsed" ? LegendCollapsed : LegendSeparated );
ddsLegend->setVerticalAlignment( elem.attribute( "valign" ) == "center" ? AlignCenter : AlignBottom );
ddsLegend->setTitle( elem.attribute( "title" ) );
QDomElement elemSymbol = elem.firstChildElement( "symbol" );
if ( !elemSymbol.isNull() )
{
ddsLegend->setSymbol( QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( elemSymbol, context ) );
}
QDomElement elemTextStyle = elem.firstChildElement( "text-style" );
if ( !elemTextStyle.isNull() )
{
QDomElement elemFont = elemTextStyle.firstChildElement( "font" );
if ( !elemFont.isNull() )
{
ddsLegend->setFont( QFont( elemFont.attribute( "family" ), elemFont.attribute( "size" ).toInt(),
elemFont.attribute( "weight" ).toInt(), elemFont.attribute( "italic" ).toInt() ) );
}
ddsLegend->setTextColor( QgsSymbolLayerUtils::decodeColor( elemTextStyle.attribute( "color" ) ) );
ddsLegend->setTextAlignment( static_cast<Qt::AlignmentFlag>( elemTextStyle.attribute( "align" ).toInt() ) );
}
QDomElement elemClasses = elem.firstChildElement( "classes" );
if ( !elemClasses.isNull() )
{
QList<SizeClass> classes;
QDomElement elemClass = elemClasses.firstChildElement( "class" );
while ( !elemClass.isNull() )
{
classes << SizeClass( elemClass.attribute( "size" ).toDouble(), elemClass.attribute( "label" ) );
elemClass = elemClass.nextSiblingElement();
}
ddsLegend->setClasses( classes );
}
return ddsLegend;
}
void QgsDataDefinedSizeLegend::writeTypeAndAlignmentToXml( const QgsDataDefinedSizeLegend &ddsLegend, QDomElement &elem )
void QgsDataDefinedSizeLegend::writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const
{
elem.setAttribute( "type", ddsLegend.legendType() == LegendCollapsed ? "collapsed" : "separated" );
elem.setAttribute( "valign", ddsLegend.verticalAlignment() == AlignCenter ? "center" : "bottom" );
QDomDocument doc = elem.ownerDocument();
elem.setAttribute( "type", mType == LegendCollapsed ? "collapsed" : "separated" );
elem.setAttribute( "valign", mVAlign == AlignCenter ? "center" : "bottom" );
elem.setAttribute( "title", mTitleLabel );
if ( mSymbol )
{
QgsSymbolLayerUtils::saveSymbol( "source", mSymbol.get(), doc, context );
}
QDomElement elemFont = doc.createElement( "font" );
elemFont.setAttribute( "family", mFont.family() );
elemFont.setAttribute( "size", mFont.pointSize() );
elemFont.setAttribute( "weight", mFont.weight() );
elemFont.setAttribute( "italic", mFont.italic() );
QDomElement elemTextStyle = doc.createElement( "text-style" );
elemTextStyle.setAttribute( "color", QgsSymbolLayerUtils::encodeColor( mTextColor ) );
elemTextStyle.setAttribute( "align", static_cast<int>( mTextAlignment ) );
elemTextStyle.appendChild( elemFont );
elem.appendChild( elemTextStyle );
if ( !mSizeClasses.isEmpty() )
{
QDomElement elemClasses = doc.createElement( "classes" );
Q_FOREACH ( const SizeClass &sc, mSizeClasses )
{
QDomElement elemClass = doc.createElement( "class" );
elemClass.setAttribute( "size", sc.size );
elemClass.setAttribute( "label", sc.label );
elemClasses.appendChild( elemClass );
}
elem.appendChild( elemClasses );
}
}

View File

@ -24,6 +24,7 @@
class QDomElement;
class QgsMarkerSymbol;
class QgsProperty;
class QgsReadWriteContext;
class QgsRenderContext;
@ -122,14 +123,10 @@ class CORE_EXPORT QgsDataDefinedSizeLegend
QImage collapsedLegendImage( QgsRenderContext &context, double paddingMM = 1 ) const;
//! Creates instance from given element and returns it (caller takes ownership). Returns null on error.
//! \note only reads legend type and vertical alignment of symbols
//! \note This is a temporary method and may be removed in the future
static QgsDataDefinedSizeLegend *readTypeAndAlignmentFromXml( const QDomElement &elem ) SIP_FACTORY;
static QgsDataDefinedSizeLegend *readXml( const QDomElement &elem, const QgsReadWriteContext &context ) SIP_FACTORY;
//! Writes configuration to the given XML element.
//! \note only writes legend type and vertical alignment of symbols
//! \note This is a temporary method and may be removed in the future
static void writeTypeAndAlignmentToXml( const QgsDataDefinedSizeLegend &ddsLegend, QDomElement &elem );
void writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const;
private:
LegendType mType = LegendSeparated;

View File

@ -601,7 +601,6 @@ void QgsSingleCategoryDiagramRenderer::writeXml( QDomElement &layerElem, QDomDoc
QgsLinearlyInterpolatedDiagramRenderer::QgsLinearlyInterpolatedDiagramRenderer()
: QgsDiagramRenderer()
, mSizeLegendSymbol( QgsMarkerSymbol::createSimple( QgsStringMap() ) )
{
mInterpolationSettings.classificationAttributeIsExpression = false;
}
@ -610,7 +609,6 @@ QgsLinearlyInterpolatedDiagramRenderer::QgsLinearlyInterpolatedDiagramRenderer(
: QgsDiagramRenderer( other )
, mSettings( other.mSettings )
, mInterpolationSettings( other.mInterpolationSettings )
, mSizeLegendSymbol( other.mSizeLegendSymbol ? other.mSizeLegendSymbol->clone() : nullptr )
, mDataDefinedSizeLegend( other.mDataDefinedSizeLegend ? new QgsDataDefinedSizeLegend( *other.mDataDefinedSizeLegend ) : nullptr )
{
}
@ -685,22 +683,27 @@ void QgsLinearlyInterpolatedDiagramRenderer::readXml( const QDomElement &elem, c
mSettings.readXml( settingsElem );
}
QDomElement sizeLegendSymbolElem = elem.firstChildElement( QStringLiteral( "symbol" ) );
if ( !sizeLegendSymbolElem.isNull() && sizeLegendSymbolElem.attribute( QStringLiteral( "name" ) ) == QLatin1String( "sizeSymbol" ) )
{
mSizeLegendSymbol.reset( QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( sizeLegendSymbolElem, context ) );
}
QDomElement ddsLegendSizeElem = elem.firstChildElement( "data-defined-size-legend" );
if ( !ddsLegendSizeElem.isNull() )
{
mDataDefinedSizeLegend.reset( QgsDataDefinedSizeLegend::readTypeAndAlignmentFromXml( ddsLegendSizeElem ) );
mDataDefinedSizeLegend.reset( QgsDataDefinedSizeLegend::readXml( ddsLegendSizeElem, context ) );
}
else
{
// pre-3.0 projects
bool enabled = elem.attribute( QStringLiteral( "sizeLegend" ), QStringLiteral( "0" ) ) != QLatin1String( "0" );
mDataDefinedSizeLegend.reset( enabled ? new QgsDataDefinedSizeLegend() : nullptr );
if ( elem.attribute( QStringLiteral( "sizeLegend" ), QStringLiteral( "0" ) ) != QLatin1String( "0" ) )
{
mDataDefinedSizeLegend.reset( new QgsDataDefinedSizeLegend() );
QDomElement sizeLegendSymbolElem = elem.firstChildElement( QStringLiteral( "symbol" ) );
if ( !sizeLegendSymbolElem.isNull() && sizeLegendSymbolElem.attribute( QStringLiteral( "name" ) ) == QLatin1String( "sizeSymbol" ) )
{
mDataDefinedSizeLegend->setSymbol( QgsSymbolLayerUtils::loadSymbol<QgsMarkerSymbol>( sizeLegendSymbolElem, context ) );
}
}
else
{
mDataDefinedSizeLegend.reset( nullptr );
}
}
_readXml( elem, context );
@ -725,13 +728,10 @@ void QgsLinearlyInterpolatedDiagramRenderer::writeXml( QDomElement &layerElem, Q
}
mSettings.writeXml( rendererElem, doc );
QDomElement sizeLegendSymbolElem = QgsSymbolLayerUtils::saveSymbol( QStringLiteral( "sizeSymbol" ), mSizeLegendSymbol.get(), doc, context );
rendererElem.appendChild( sizeLegendSymbolElem );
if ( mDataDefinedSizeLegend )
{
QDomElement ddsLegendElem = doc.createElement( QStringLiteral( "data-defined-size-legend" ) );
QgsDataDefinedSizeLegend::writeTypeAndAlignmentToXml( *mDataDefinedSizeLegend, ddsLegendElem );
mDataDefinedSizeLegend->writeXml( ddsLegendElem, context );
rendererElem.appendChild( ddsLegendElem );
}
@ -772,11 +772,10 @@ QList< QgsLayerTreeModelLegendNode * > QgsLinearlyInterpolatedDiagramRenderer::l
if ( mShowAttributeLegend )
nodes = mSettings.legendItems( nodeLayer );
if ( mDataDefinedSizeLegend && mDiagram && mSizeLegendSymbol )
if ( mDataDefinedSizeLegend && mDiagram )
{
// add size legend
QgsMarkerSymbol *legendSymbol = mSizeLegendSymbol.get()->clone();
QgsMarkerSymbol *legendSymbol = mDataDefinedSizeLegend->symbol() ? mDataDefinedSizeLegend->symbol()->clone() : QgsMarkerSymbol::createSimple( QgsStringMap() );
legendSymbol->setSizeUnit( mSettings.sizeType );
legendSymbol->setSizeMapUnitScale( mSettings.sizeScale );

View File

@ -685,21 +685,6 @@ class CORE_EXPORT QgsLinearlyInterpolatedDiagramRenderer : public QgsDiagramRend
QList< QgsLayerTreeModelLegendNode * > legendItems( QgsLayerTreeLayer *nodeLayer ) const override SIP_FACTORY;
/** Returns the marker symbol used for rendering the diagram size legend.
* \since QGIS 2.16
* \see setSizeLegendSymbol()
* \see sizeLegend()
*/
QgsMarkerSymbol *sizeLegendSymbol() const { return mSizeLegendSymbol.get(); }
/** Sets the marker symbol used for rendering the diagram size legend.
* \param symbol marker symbol, ownership is transferred to the renderer.
* \since QGIS 2.16
* \see sizeLegendSymbol()
* \see setSizeLegend()
*/
void setSizeLegendSymbol( QgsMarkerSymbol *symbol SIP_TRANSFER ) { mSizeLegendSymbol.reset( symbol ); }
/**
* Configures appearance of legend. Takes ownership of the passed settings objects.
* \since QGIS 3.0
@ -723,9 +708,6 @@ class CORE_EXPORT QgsLinearlyInterpolatedDiagramRenderer : public QgsDiagramRend
QgsDiagramSettings mSettings;
QgsDiagramInterpolationSettings mInterpolationSettings;
//! Marker symbol to use in size legends
std::unique_ptr< QgsMarkerSymbol > mSizeLegendSymbol;
//! Stores more settings about how legend for varying size of symbols should be rendered
std::unique_ptr<QgsDataDefinedSizeLegend> mDataDefinedSizeLegend;
};

View File

@ -662,7 +662,7 @@ QgsFeatureRenderer *QgsCategorizedSymbolRenderer::create( QDomElement &element,
QDomElement ddsLegendSizeElem = element.firstChildElement( "data-defined-size-legend" );
if ( !ddsLegendSizeElem.isNull() )
{
r->mDataDefinedSizeLegend.reset( QgsDataDefinedSizeLegend::readTypeAndAlignmentFromXml( ddsLegendSizeElem ) );
r->mDataDefinedSizeLegend.reset( QgsDataDefinedSizeLegend::readXml( ddsLegendSizeElem, context ) );
}
// TODO: symbol levels
@ -742,7 +742,7 @@ QDomElement QgsCategorizedSymbolRenderer::save( QDomDocument &doc, const QgsRead
if ( mDataDefinedSizeLegend )
{
QDomElement ddsLegendElem = doc.createElement( QStringLiteral( "data-defined-size-legend" ) );
QgsDataDefinedSizeLegend::writeTypeAndAlignmentToXml( *mDataDefinedSizeLegend, ddsLegendElem );
mDataDefinedSizeLegend->writeXml( ddsLegendElem, context );
rendererElem.appendChild( ddsLegendElem );
}

View File

@ -1043,7 +1043,7 @@ QgsFeatureRenderer *QgsGraduatedSymbolRenderer::create( QDomElement &element, co
QDomElement ddsLegendSizeElem = element.firstChildElement( "data-defined-size-legend" );
if ( !ddsLegendSizeElem.isNull() )
{
r->mDataDefinedSizeLegend.reset( QgsDataDefinedSizeLegend::readTypeAndAlignmentFromXml( ddsLegendSizeElem ) );
r->mDataDefinedSizeLegend.reset( QgsDataDefinedSizeLegend::readXml( ddsLegendSizeElem, context ) );
}
// TODO: symbol levels
@ -1145,7 +1145,7 @@ QDomElement QgsGraduatedSymbolRenderer::save( QDomDocument &doc, const QgsReadWr
if ( mDataDefinedSizeLegend )
{
QDomElement ddsLegendElem = doc.createElement( QStringLiteral( "data-defined-size-legend" ) );
QgsDataDefinedSizeLegend::writeTypeAndAlignmentToXml( *mDataDefinedSizeLegend, ddsLegendElem );
mDataDefinedSizeLegend->writeXml( ddsLegendElem, context );
rendererElem.appendChild( ddsLegendElem );
}

View File

@ -163,7 +163,7 @@ QgsFeatureRenderer *QgsSingleSymbolRenderer::create( QDomElement &element, const
QDomElement ddsLegendSizeElem = element.firstChildElement( "data-defined-size-legend" );
if ( !ddsLegendSizeElem.isNull() )
{
r->mDataDefinedSizeLegend.reset( QgsDataDefinedSizeLegend::readTypeAndAlignmentFromXml( ddsLegendSizeElem ) );
r->mDataDefinedSizeLegend.reset( QgsDataDefinedSizeLegend::readXml( ddsLegendSizeElem, context ) );
}
// TODO: symbol levels
@ -290,7 +290,7 @@ QDomElement QgsSingleSymbolRenderer::save( QDomDocument &doc, const QgsReadWrite
if ( mDataDefinedSizeLegend )
{
QDomElement ddsLegendElem = doc.createElement( QStringLiteral( "data-defined-size-legend" ) );
QgsDataDefinedSizeLegend::writeTypeAndAlignmentToXml( *mDataDefinedSizeLegend, ddsLegendElem );
mDataDefinedSizeLegend->writeXml( ddsLegendElem, context );
rendererElem.appendChild( ddsLegendElem );
}

View File

@ -18,16 +18,23 @@
#include "qgsdatadefinedsizelegend.h"
#include "qgslayertree.h"
#include "qgslayertreemodel.h"
#include "qgsmapcanvas.h"
#include "qgssinglesymbolrenderer.h"
#include "qgsstyle.h"
#include "qgssymbol.h"
#include "qgssymbollayer.h"
#include "qgssymbolselectordialog.h"
#include "qgsvectorlayer.h"
QgsDataDefinedSizeLegendDialog::QgsDataDefinedSizeLegendDialog( const QgsDataDefinedSizeLegend *ddsLegend, QWidget *parent )
QgsDataDefinedSizeLegendDialog::QgsDataDefinedSizeLegendDialog( const QgsDataDefinedSizeLegend *ddsLegend, const QgsProperty &ddSize, QgsMarkerSymbol *overrideSymbol, QgsMapCanvas *canvas, QWidget *parent )
: QDialog( parent )
, mSizeProperty( ddSize )
, mMapCanvas( canvas )
{
setupUi( this );
QgsMarkerSymbol *symbol = nullptr;
if ( !ddsLegend )
{
radDisabled->setChecked( true );
@ -43,25 +50,41 @@ QgsDataDefinedSizeLegendDialog::QgsDataDefinedSizeLegendDialog( const QgsDataDef
cboAlignSymbols->setCurrentIndex( 0 );
else
cboAlignSymbols->setCurrentIndex( 1 );
symbol = ddsLegend->symbol(); // may be null (undefined)
}
// 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 );
if ( overrideSymbol )
{
symbol = overrideSymbol; // takes ownership
mOverrideSymbol = true;
}
if ( !symbol )
{
symbol = QgsMarkerSymbol::createSimple( QgsStringMap() );
}
mSourceSymbol.reset( symbol );
btnChangeSymbol->setEnabled( !mOverrideSymbol );
QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( mSourceSymbol.get(), btnChangeSymbol->iconSize() );
btnChangeSymbol->setIcon( icon );
// 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 );
if ( canvas )
mPreviewModel->setLegendMapViewData( canvas->mapUnitsPerPixel(), canvas->mapSettings().outputDpi(), canvas->scale() );
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 );
connect( btnChangeSymbol, &QPushButton::clicked, this, &QgsDataDefinedSizeLegendDialog::changeSymbol );
updatePreview();
}
@ -72,18 +95,6 @@ QgsDataDefinedSizeLegendDialog::~QgsDataDefinedSizeLegendDialog()
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() )
@ -92,14 +103,50 @@ QgsDataDefinedSizeLegend *QgsDataDefinedSizeLegendDialog::dataDefinedSizeLegend(
QgsDataDefinedSizeLegend *ddsLegend = new QgsDataDefinedSizeLegend;
ddsLegend->setLegendType( radSeparated->isChecked() ? QgsDataDefinedSizeLegend::LegendSeparated : QgsDataDefinedSizeLegend::LegendCollapsed );
ddsLegend->setVerticalAlignment( cboAlignSymbols->currentIndex() == 0 ? QgsDataDefinedSizeLegend::AlignBottom : QgsDataDefinedSizeLegend::AlignCenter );
if ( !mOverrideSymbol )
{
ddsLegend->setSymbol( mSourceSymbol->clone() );
}
return ddsLegend;
}
void QgsDataDefinedSizeLegendDialog::updatePreview()
{
QgsSingleSymbolRenderer *r = new QgsSingleSymbolRenderer( mSourceSymbol->clone() );
QgsMarkerSymbol *symbol = mSourceSymbol->clone();
symbol->setDataDefinedSize( mSizeProperty );
QgsSingleSymbolRenderer *r = new QgsSingleSymbolRenderer( symbol );
r->setDataDefinedSizeLegend( dataDefinedSizeLegend() );
mPreviewLayer->setRenderer( r );
mPreviewModel->refreshLayerLegend( mPreviewLayerNode );
viewLayerTree->expandAll();
}
void QgsDataDefinedSizeLegendDialog::changeSymbol()
{
std::unique_ptr<QgsMarkerSymbol> newSymbol( mSourceSymbol->clone() );
QgsSymbolWidgetContext context;
if ( mMapCanvas )
context.setMapCanvas( mMapCanvas );
QgsExpressionContext ec;
ec << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope( QgsProject::instance() )
<< QgsExpressionContextUtils::atlasScope( nullptr );
if ( mMapCanvas )
ec << QgsExpressionContextUtils::mapSettingsScope( mMapCanvas->mapSettings() );
context.setExpressionContext( &ec );
std::unique_ptr<QgsVectorLayer> layer( new QgsVectorLayer( "Point", "tmp", "memory" ) );
QgsSymbolSelectorDialog d( newSymbol.get(), QgsStyle::defaultStyle(), layer.get(), this );
d.setContext( context );
if ( d.exec() != QDialog::Accepted )
return;
mSourceSymbol.reset( newSymbol.release() );
QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( mSourceSymbol.get(), btnChangeSymbol->iconSize() );
btnChangeSymbol->setIcon( icon );
updatePreview();
}

View File

@ -23,11 +23,15 @@
#include <QDialog>
#include <ui_qgsdatadefinedsizelegenddialog.h>
#include "qgsproperty.h"
class QgsDataDefinedSizeLegend;
class QgsLayerTree;
class QgsLayerTreeLayer;
class QgsLayerTreeModel;
class QgsMapCanvas;
class QgsMarkerSymbol;
class QgsProperty;
class QgsVectorLayer;
/** \ingroup gui
@ -39,16 +43,13 @@ class GUI_EXPORT QgsDataDefinedSizeLegendDialog : public QDialog, private Ui::Qg
{
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 );
//! Creates the dialog and initializes the content to what is passed in the legend configuration (may be null).
//! The ddSize argument determines scaling of the marker symbol - it should have a size scale transformer assigned
//! to know the range of sizes. The overrideSymbol argument may override the source symbol: this is useful in case
//! when the symbol is given from outside rather than being set inside QgsDataDefinedSizeLegend.
explicit QgsDataDefinedSizeLegendDialog( const QgsDataDefinedSizeLegend *ddsLegend, const QgsProperty &ddSize, QgsMarkerSymbol *overrideSymbol SIP_TRANSFER, QgsMapCanvas *canvas = nullptr, 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;
@ -56,13 +57,17 @@ class GUI_EXPORT QgsDataDefinedSizeLegendDialog : public QDialog, private Ui::Qg
private slots:
void updatePreview();
void changeSymbol();
private:
std::unique_ptr<QgsMarkerSymbol> mSourceSymbol;
std::unique_ptr<QgsMarkerSymbol> mSourceSymbol; //!< Source symbol (without data-defined size set)
bool mOverrideSymbol = false; //!< If true, symbol should not be editable because it will be overridden
QgsProperty mSizeProperty; //!< Definition of data-defined size of symbol (should have a size scale transformer associated)
QgsLayerTreeModel *mPreviewModel;
QgsLayerTree *mPreviewTree;
QgsLayerTreeLayer *mPreviewLayerNode;
QgsVectorLayer *mPreviewLayer;
QgsMapCanvas *mMapCanvas = nullptr;
};
#endif // QGSDATADEFINEDSIZELEGENDDIALOG_H

View File

@ -291,13 +291,7 @@ QgsDataDefinedSizeLegend *QgsRendererWidget::showDataDefinedSizeLegendDialog( co
return nullptr;
}
QgsDataDefinedSizeLegendDialog dlg( ddsLegend );
dlg.setSourceSymbol( symbol->clone() );
if ( QgsMapCanvas *canvas = mContext.mapCanvas() )
{
dlg.setLegendMapViewData( canvas->mapUnitsPerPixel(), canvas->mapSettings().outputDpi(), canvas->scale() );
}
QgsDataDefinedSizeLegendDialog dlg( ddsLegend, ddSize, symbol->clone(), mContext.mapCanvas() );
if ( !dlg.exec() )
return nullptr;

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>674</width>
<height>393</height>
<height>492</height>
</rect>
</property>
<property name="windowTitle">
@ -40,6 +40,13 @@
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnChangeSymbol">
<property name="text">
<string>Legend symbol...</string>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">

View File

@ -2066,40 +2066,28 @@
</widget>
</item>
<item>
<widget class="QgsCollapsibleGroupBox" name="mSizeLegendGroupBox">
<property name="title">
<string>Legend entries for diagram size</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_71">
<item>
<widget class="QPushButton" name="mButtonSizeLegendSettings">
<property name="text">
<string>Legend settings...</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="mButtonSizeLegendSymbol">
<property name="text">
<string>Legend symbol...</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_111">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QPushButton" name="mButtonSizeLegendSettings">
<property name="text">
<string>Legend entries for diagram size...</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_111">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_7">
@ -2236,8 +2224,6 @@
<tabstop>mOrientationLeftButton</tabstop>
<tabstop>scrollArea_2</tabstop>
<tabstop>mCheckBoxAttributeLegend</tabstop>
<tabstop>mSizeLegendGroupBox</tabstop>
<tabstop>mButtonSizeLegendSymbol</tabstop>
<tabstop>mBackgroundColorDDBtn</tabstop>
<tabstop>mLineColorDDBtn</tabstop>
<tabstop>mDiagramLineUnitComboBox</tabstop>