Skip to content

Commit

Permalink
When switching symbol layer types from geometry generator or back, ke…
Browse files Browse the repository at this point in the history
…ep as much of the old symbol layer as we can
  • Loading branch information
nyalldawson committed Oct 28, 2021
1 parent 0667363 commit 5195032
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 4 deletions.
59 changes: 55 additions & 4 deletions src/gui/symbology/qgslayerpropertieswidget.cpp
Expand Up @@ -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 )
{
Expand Down Expand Up @@ -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 );
Expand Down
38 changes: 38 additions & 0 deletions src/gui/symbology/qgssymbollayerwidget.cpp
Expand Up @@ -46,6 +46,7 @@
#include "qgsimagecache.h"
#include "qgslinesymbol.h"
#include "qgsmarkersymbol.h"
#include "qgsfillsymbol.h"
#include "qgsiconutils.h"

#include <QAbstractButton>
Expand Down Expand Up @@ -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();
}

Expand Down

0 comments on commit 5195032

Please sign in to comment.