Skip to content
Permalink
Browse files
When switching symbol layer types from geometry generator or back, ke…
…ep as much of the old symbol layer as we can
  • Loading branch information
nyalldawson committed Oct 28, 2021
1 parent 0667363 commit 5195032482b5d31984b2b17be1d4208ff2b77360
Showing with 93 additions and 4 deletions.
  1. +55 −4 src/gui/symbology/qgslayerpropertieswidget.cpp
  2. +38 −0 src/gui/symbology/qgssymbollayerwidget.cpp
@@ -43,6 +43,10 @@
#include "qgsmasksymbollayerwidget.h"
#include "qgstemporalcontroller.h"
#include "qgssymbollayerutils.h"
#include "qgsgeometrygeneratorsymbollayer.h"
#include "qgsmarkersymbol.h"
#include "qgslinesymbol.h"
#include "qgsfillsymbol.h"

static bool _initWidgetFunction( const QString &name, QgsSymbolLayerWidgetFunc f )
{
@@ -327,14 +331,61 @@ void QgsLayerPropertiesWidget::layerTypeChanged()

// change layer to a new (with different type)
// base new layer on existing layer's properties
QgsSymbolLayer *newLayer = am->createSymbolLayer( layer->properties() );
QVariantMap properties = layer->properties();

// if the old symbol layer was a "geometry generator" layer then
// we instead get the properties from the generator
if ( QgsGeometryGeneratorSymbolLayer *generator = dynamic_cast< QgsGeometryGeneratorSymbolLayer * >( layer ) )
{
if ( generator->subSymbol() && generator->subSymbol()->symbolLayerCount() > 0 )
properties = generator->subSymbol()->symbolLayer( 0 )->properties();
}

QgsSymbolLayer *newLayer = am->createSymbolLayer( properties );
if ( !newLayer )
return;

// also try to copy the subsymbol, if its the same type as the new symbol layer's subsymbol
if ( newLayer->subSymbol() && layer->subSymbol() && newLayer->subSymbol()->type() == layer->subSymbol()->type() )
// if a symbol layer is changed to a "geometry generator" layer, then we move the old symbol layer into the
// geometry generator's subsymbol.
if ( QgsGeometryGeneratorSymbolLayer *generator = dynamic_cast< QgsGeometryGeneratorSymbolLayer * >( newLayer ) )
{
newLayer->setSubSymbol( layer->subSymbol()->clone() );
if ( mSymbol )
{
switch ( mSymbol->type() )
{
case Qgis::SymbolType::Marker:
{
std::unique_ptr< QgsMarkerSymbol > markerSymbol = std::make_unique< QgsMarkerSymbol >( QgsSymbolLayerList( {layer->clone() } ) );
generator->setSymbolType( Qgis::SymbolType::Marker );
generator->setSubSymbol( markerSymbol.release() );
break;
}
case Qgis::SymbolType::Line:
{
std::unique_ptr< QgsLineSymbol > lineSymbol = std::make_unique< QgsLineSymbol >( QgsSymbolLayerList( {layer->clone() } ) );
generator->setSymbolType( Qgis::SymbolType::Line );
generator->setSubSymbol( lineSymbol.release() );
break;
}
case Qgis::SymbolType::Fill:
{
std::unique_ptr< QgsFillSymbol > fillSymbol = std::make_unique< QgsFillSymbol >( QgsSymbolLayerList( {layer->clone() } ) );
generator->setSymbolType( Qgis::SymbolType::Fill );
generator->setSubSymbol( fillSymbol.release() );
break;
}
case Qgis::SymbolType::Hybrid:
break;
}
}
}
else
{
// try to copy the subsymbol, if its the same type as the new symbol layer's subsymbol
if ( newLayer->subSymbol() && layer->subSymbol() && newLayer->subSymbol()->type() == layer->subSymbol()->type() )
{
newLayer->setSubSymbol( layer->subSymbol()->clone() );
}
}

updateSymbolLayerWidget( newLayer );
@@ -46,6 +46,7 @@
#include "qgsimagecache.h"
#include "qgslinesymbol.h"
#include "qgsmarkersymbol.h"
#include "qgsfillsymbol.h"
#include "qgsiconutils.h"

#include <QAbstractButton>
@@ -4643,8 +4644,45 @@ void QgsGeometryGeneratorSymbolLayerWidget::updateExpression( const QString &str

void QgsGeometryGeneratorSymbolLayerWidget::updateSymbolType()
{
// we try to keep the subsymbol, if we can!
std::unique_ptr< QgsSymbol > subSymbol( mLayer->subSymbol()->clone() );

mLayer->setSymbolType( static_cast<Qgis::SymbolType>( cbxGeometryType->currentData().toInt() ) );

switch ( mLayer->symbolType() )
{
case Qgis::SymbolType::Marker:
case Qgis::SymbolType::Hybrid:
break;
case Qgis::SymbolType::Line:
{
if ( subSymbol->type() == Qgis::SymbolType::Fill )
{
// going from fill -> line type, so we can copy any LINE symbol layers across
QgsSymbolLayerList layers;
for ( int i = 0; i < subSymbol->symbolLayerCount(); ++i )
{
if ( const QgsLineSymbolLayer *lineLayer = dynamic_cast< const QgsLineSymbolLayer * >( subSymbol->symbolLayer( i ) ) )
layers << subSymbol->symbolLayer( i )->clone();
}

if ( !layers.empty() )
mLayer->setSubSymbol( new QgsLineSymbol( layers ) );
}
break;
}
case Qgis::SymbolType::Fill:
if ( subSymbol->type() == Qgis::SymbolType::Line )
{
// going from line -> fill type, so copy ALL line symbol layers across
QgsSymbolLayerList layers;
for ( int i = 0; i < subSymbol->symbolLayerCount(); ++i )
layers << subSymbol->symbolLayer( i )->clone();
mLayer->setSubSymbol( new QgsFillSymbol( layers ) );
}
break;
}

emit symbolChanged();
}

0 comments on commit 5195032

Please sign in to comment.