QGIS API Documentation  3.25.0-Master (10b47c2603)
qgssymbollayerwidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgssymbollayerwidget.cpp - symbol layer widgets
3 
4  ---------------------
5  begin : November 2009
6  copyright : (C) 2009 by Martin Dobias
7  email : wonder dot sk at gmail dot com
8  ***************************************************************************
9  * *
10  * This program is free software; you can redistribute it and/or modify *
11  * it under the terms of the GNU General Public License as published by *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  ***************************************************************************/
16 
17 #include "qgssymbollayerwidget.h"
18 
19 #include "qgslinesymbollayer.h"
20 #include "qgsmarkersymbollayer.h"
21 #include "qgsfillsymbollayer.h"
23 #include "qgssymbolslistwidget.h"
25 
26 #include "characterwidget.h"
27 #include "qgsdashspacedialog.h"
29 #include "qgssvgcache.h"
30 #include "qgssymbollayerutils.h"
31 #include "qgscolorramp.h"
32 #include "qgscolorrampbutton.h"
33 #include "qgsfontutils.h"
35 #include "qgsproperty.h"
36 #include "qgsstyle.h" //for symbol selector dialog
37 #include "qgsmapcanvas.h"
38 #include "qgsapplication.h"
39 #include "qgsvectorlayer.h"
40 #include "qgssvgselectorwidget.h"
41 #include "qgslogger.h"
42 #include "qgssettings.h"
45 #include "qgsauxiliarystorage.h"
46 #include "qgsimagecache.h"
47 #include "qgslinesymbol.h"
48 #include "qgsmarkersymbol.h"
49 #include "qgsfillsymbol.h"
50 #include "qgsiconutils.h"
51 
52 #include <QAbstractButton>
53 #include <QButtonGroup>
54 #include <QColorDialog>
55 #include <QCursor>
56 #include <QDir>
57 #include <QFileDialog>
58 #include <QPainter>
59 #include <QStandardItemModel>
60 #include <QSvgRenderer>
61 #include <QMessageBox>
62 #include <QMenu>
63 #include <QAction>
64 #include <QInputDialog>
65 #include <QBuffer>
66 #include <QRegularExpression>
67 #include <QMovie>
68 
70 {
71  if ( auto *lExpressionContext = mContext.expressionContext() )
72  return *lExpressionContext;
73 
75 
77  if ( const QgsSymbolLayer *symbolLayer = const_cast< QgsSymbolLayerWidget * >( this )->symbolLayer() )
78  {
79  //cheat a bit - set the symbol color variable to match the symbol layer's color (when we should really be using the *symbols*
80  //color, but that's not accessible here). 99% of the time these will be the same anyway
82  }
83  expContext << symbolScope;
89  expContext.lastScope()->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "symbol_layer_count" ), 1, true ) );
90  expContext.lastScope()->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "symbol_layer_index" ), 1, true ) );
91  expContext.lastScope()->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "symbol_marker_row" ), 1, true ) );
92  expContext.lastScope()->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "symbol_marker_column" ), 1, true ) );
93  expContext.lastScope()->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "symbol_frame" ), 1, true ) );
94 
95  // additional scopes
96  const auto constAdditionalExpressionContextScopes = mContext.additionalExpressionContextScopes();
97  for ( const QgsExpressionContextScope &scope : constAdditionalExpressionContextScopes )
98  {
99  expContext.appendScope( new QgsExpressionContextScope( scope ) );
100  }
101 
102  //TODO - show actual value
103  expContext.setOriginalValueVariable( QVariant() );
104 
105  QStringList highlights;
111  << QStringLiteral( "symbol_layer_count" ) << QStringLiteral( "symbol_layer_index" ) << QStringLiteral( "symbol_frame" );
112 
113 
114  if ( expContext.hasVariable( QStringLiteral( "zoom_level" ) ) )
115  {
116  highlights << QStringLiteral( "zoom_level" );
117  }
118  if ( expContext.hasVariable( QStringLiteral( "vector_tile_zoom" ) ) )
119  {
120  highlights << QStringLiteral( "vector_tile_zoom" );
121  }
122 
123  expContext.setHighlightedVariables( highlights );
124 
125  return expContext;
126 }
127 
129 {
130  mContext = context;
131  const auto unitSelectionWidgets = findChildren<QgsUnitSelectionWidget *>();
132  for ( QgsUnitSelectionWidget *unitWidget : unitSelectionWidgets )
133  {
134  unitWidget->setMapCanvas( mContext.mapCanvas() );
135  }
136 }
137 
139 {
140  return mContext;
141 }
142 
144 {
145  button->init( key, symbolLayer()->dataDefinedProperties(), QgsSymbolLayer::propertyDefinitions(), mVectorLayer, true );
147  connect( button, &QgsPropertyOverrideButton::createAuxiliaryField, this, &QgsSymbolLayerWidget::createAuxiliaryField );
148 
149  button->registerExpressionContextGenerator( this );
150 }
151 
152 void QgsSymbolLayerWidget::createAuxiliaryField()
153 {
154  // try to create an auxiliary layer if not yet created
155  if ( !mVectorLayer->auxiliaryLayer() )
156  {
157  QgsNewAuxiliaryLayerDialog dlg( mVectorLayer, this );
158  dlg.exec();
159  }
160 
161  // return if still not exists
162  if ( !mVectorLayer->auxiliaryLayer() )
163  return;
164 
165  QgsPropertyOverrideButton *button = qobject_cast<QgsPropertyOverrideButton *>( sender() );
166  const QgsSymbolLayer::Property key = static_cast< QgsSymbolLayer::Property >( button->propertyKey() );
168 
169  // create property in auxiliary storage if necessary
170  if ( !mVectorLayer->auxiliaryLayer()->exists( def ) )
171  {
172  QgsNewAuxiliaryFieldDialog dlg( def, mVectorLayer, true, this );
173  if ( dlg.exec() == QDialog::Accepted )
174  def = dlg.propertyDefinition();
175  }
176 
177  // return if still not exist
178  if ( !mVectorLayer->auxiliaryLayer()->exists( def ) )
179  return;
180 
181  // update property with join field name from auxiliary storage
182  QgsProperty property = button->toProperty();
183  property.setField( QgsAuxiliaryLayer::nameFromProperty( def, true ) );
184  property.setActive( true );
185  button->updateFieldLists();
186  button->setToProperty( property );
187  symbolLayer()->setDataDefinedProperty( key, button->toProperty() );
188 
189  emit changed();
190 }
191 
193 {
194  QgsPropertyOverrideButton *button = qobject_cast<QgsPropertyOverrideButton *>( sender() );
195  const QgsSymbolLayer::Property key = static_cast< QgsSymbolLayer::Property >( button->propertyKey() );
196  symbolLayer()->setDataDefinedProperty( key, button->toProperty() );
197  emit changed();
198 }
199 
201  : QgsSymbolLayerWidget( parent, vl )
202 {
203  mLayer = nullptr;
204 
205  setupUi( this );
206  connect( mCustomCheckBox, &QCheckBox::stateChanged, this, &QgsSimpleLineSymbolLayerWidget::mCustomCheckBox_stateChanged );
207  connect( mChangePatternButton, &QPushButton::clicked, this, &QgsSimpleLineSymbolLayerWidget::mChangePatternButton_clicked );
208  connect( mPenWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSimpleLineSymbolLayerWidget::mPenWidthUnitWidget_changed );
209  connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSimpleLineSymbolLayerWidget::mOffsetUnitWidget_changed );
210  connect( mDashPatternUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSimpleLineSymbolLayerWidget::mDashPatternUnitWidget_changed );
211  connect( mDrawInsideCheckBox, &QCheckBox::stateChanged, this, &QgsSimpleLineSymbolLayerWidget::mDrawInsideCheckBox_stateChanged );
212  connect( mPatternOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSimpleLineSymbolLayerWidget::patternOffsetUnitChanged );
213  connect( mCheckAlignDash, &QCheckBox::toggled, this, [ = ]
214  {
215  mCheckDashCorners->setEnabled( mCheckAlignDash->isChecked() );
216  if ( !mCheckAlignDash->isChecked() )
217  mCheckDashCorners->setChecked( false );
218 
219  if ( mLayer )
220  {
221  mLayer->setAlignDashPattern( mCheckAlignDash->isChecked() );
222  emit changed();
223  }
224  } );
225  connect( mCheckDashCorners, &QCheckBox::toggled, this, [ = ]
226  {
227  if ( mLayer )
228  {
229  mLayer->setTweakDashPatternOnCorners( mCheckDashCorners->isChecked() );
230  emit changed();
231  }
232  } );
233 
246 
247  btnChangeColor->setAllowOpacity( true );
248  btnChangeColor->setColorDialogTitle( tr( "Select Line Color" ) );
249  btnChangeColor->setContext( QStringLiteral( "symbology" ) );
250 
251  mColorDDBtn->registerLinkedWidget( btnChangeColor );
252 
253  mRingFilterComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "mIconAllRings.svg" ) ), tr( "All Rings" ), QgsLineSymbolLayer::AllRings );
254  mRingFilterComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "mIconExteriorRing.svg" ) ), tr( "Exterior Ring Only" ), QgsLineSymbolLayer::ExteriorRingOnly );
255  mRingFilterComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "mIconInteriorRings.svg" ) ), tr( "Interior Rings Only" ), QgsLineSymbolLayer::InteriorRingsOnly );
256  connect( mRingFilterComboBox, qOverload< int >( &QComboBox::currentIndexChanged ), this, [ = ]( int )
257  {
258  if ( mLayer )
259  {
260  mLayer->setRingFilter( static_cast< QgsLineSymbolLayer::RenderRingFilter >( mRingFilterComboBox->currentData().toInt() ) );
261  emit changed();
262  }
263  } );
264 
265  spinOffset->setClearValue( 0.0 );
266  spinPatternOffset->setClearValue( 0.0 );
267 
268  mTrimStartDistanceSpin->setClearValue( 0.0 );
269  mTrimDistanceEndSpin->setClearValue( 0.0 );
270 
271  //make a temporary symbol for the size assistant preview
272  mAssistantPreviewSymbol.reset( new QgsLineSymbol() );
273 
274  if ( vectorLayer() )
275  mPenWidthDDBtn->setSymbol( mAssistantPreviewSymbol );
276 
277  connect( spinWidth, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleLineSymbolLayerWidget::penWidthChanged );
278  connect( btnChangeColor, &QgsColorButton::colorChanged, this, &QgsSimpleLineSymbolLayerWidget::colorChanged );
279  connect( cboPenStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleLineSymbolLayerWidget::penStyleChanged );
280  connect( spinOffset, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleLineSymbolLayerWidget::offsetChanged );
281  connect( cboCapStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleLineSymbolLayerWidget::penStyleChanged );
282  connect( cboJoinStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleLineSymbolLayerWidget::penStyleChanged );
283  connect( spinPatternOffset, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleLineSymbolLayerWidget::patternOffsetChanged );
284 
285  connect( mTrimStartDistanceSpin, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, [ = ]( double value )
286  {
287  if ( !mLayer )
288  return;
289 
290  mLayer->setTrimDistanceStart( value );
291  emit changed();
292  } );
293  connect( mTrimDistanceStartUnitWidget, &QgsUnitSelectionWidget::changed, this, [ = ]
294  {
295  if ( !mLayer )
296  return;
297 
298  mLayer->setTrimDistanceStartUnit( mTrimDistanceStartUnitWidget->unit() );
299  mLayer->setTrimDistanceStartMapUnitScale( mTrimDistanceStartUnitWidget->getMapUnitScale() );
300  emit changed();
301  } );
302  connect( mTrimDistanceEndSpin, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, [ = ]( double value )
303  {
304  if ( !mLayer )
305  return;
306 
307  mLayer->setTrimDistanceEnd( value );
308  emit changed();
309  } );
310  connect( mTrimDistanceEndUnitWidget, &QgsUnitSelectionWidget::changed, this, [ = ]
311  {
312  if ( !mLayer )
313  return;
314 
315  mLayer->setTrimDistanceEndUnit( mTrimDistanceEndUnitWidget->unit() );
316  mLayer->setTrimDistanceEndMapUnitScale( mTrimDistanceEndUnitWidget->getMapUnitScale() );
317  emit changed();
318  } );
319 
320 
322 
323  connect( this, &QgsSymbolLayerWidget::changed, this, &QgsSimpleLineSymbolLayerWidget::updateAssistantSymbol );
324 }
325 
327 
328 void QgsSimpleLineSymbolLayerWidget::updateAssistantSymbol()
329 {
330  for ( int i = mAssistantPreviewSymbol->symbolLayerCount() - 1 ; i >= 0; --i )
331  {
332  mAssistantPreviewSymbol->deleteSymbolLayer( i );
333  }
334  mAssistantPreviewSymbol->appendSymbolLayer( mLayer->clone() );
336  if ( ddWidth )
337  mAssistantPreviewSymbol->setDataDefinedWidth( ddWidth );
338 }
339 
340 
342 {
343  if ( !layer || layer->layerType() != QLatin1String( "SimpleLine" ) )
344  return;
345 
346  // layer type is correct, we can do the cast
347  mLayer = static_cast<QgsSimpleLineSymbolLayer *>( layer );
348 
349  // set units
350  mPenWidthUnitWidget->blockSignals( true );
351  mPenWidthUnitWidget->setUnit( mLayer->widthUnit() );
352  mPenWidthUnitWidget->setMapUnitScale( mLayer->widthMapUnitScale() );
353  mPenWidthUnitWidget->blockSignals( false );
354  mOffsetUnitWidget->blockSignals( true );
355  mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
356  mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
357  mOffsetUnitWidget->blockSignals( false );
358  mDashPatternUnitWidget->blockSignals( true );
359  mDashPatternUnitWidget->setUnit( mLayer->customDashPatternUnit() );
360  mDashPatternUnitWidget->setMapUnitScale( mLayer->customDashPatternMapUnitScale() );
361  mDashPatternUnitWidget->blockSignals( false );
362 
363  whileBlocking( mPatternOffsetUnitWidget )->setUnit( mLayer->dashPatternOffsetUnit() );
364  whileBlocking( mPatternOffsetUnitWidget )->setMapUnitScale( mLayer->dashPatternOffsetMapUnitScale() );
365  whileBlocking( mTrimDistanceStartUnitWidget )->setUnit( mLayer->trimDistanceStartUnit() );
366  whileBlocking( mTrimDistanceStartUnitWidget )->setMapUnitScale( mLayer->trimDistanceStartMapUnitScale() );
367  whileBlocking( mTrimDistanceEndUnitWidget )->setUnit( mLayer->trimDistanceEndUnit() );
368  whileBlocking( mTrimDistanceEndUnitWidget )->setMapUnitScale( mLayer->trimDistanceEndMapUnitScale() );
369 
370  // set values
371  spinWidth->blockSignals( true );
372  spinWidth->setValue( mLayer->width() );
373  spinWidth->blockSignals( false );
374  btnChangeColor->blockSignals( true );
375  btnChangeColor->setColor( mLayer->color() );
376  btnChangeColor->blockSignals( false );
377  spinOffset->blockSignals( true );
378  spinOffset->setValue( mLayer->offset() );
379  spinOffset->blockSignals( false );
380  cboPenStyle->blockSignals( true );
381  cboJoinStyle->blockSignals( true );
382  cboCapStyle->blockSignals( true );
383  cboPenStyle->setPenStyle( mLayer->penStyle() );
384  cboJoinStyle->setPenJoinStyle( mLayer->penJoinStyle() );
385  cboCapStyle->setPenCapStyle( mLayer->penCapStyle() );
386  cboPenStyle->blockSignals( false );
387  cboJoinStyle->blockSignals( false );
388  cboCapStyle->blockSignals( false );
389  whileBlocking( spinPatternOffset )->setValue( mLayer->dashPatternOffset() );
390  whileBlocking( mTrimStartDistanceSpin )->setValue( mLayer->trimDistanceStart() );
391  whileBlocking( mTrimDistanceEndSpin )->setValue( mLayer->trimDistanceEnd() );
392 
393  //use a custom dash pattern?
394  const bool useCustomDashPattern = mLayer->useCustomDashPattern();
395  mChangePatternButton->setEnabled( useCustomDashPattern );
396  label_3->setEnabled( !useCustomDashPattern );
397  cboPenStyle->setEnabled( !useCustomDashPattern );
398  mCustomCheckBox->blockSignals( true );
399  mCustomCheckBox->setCheckState( useCustomDashPattern ? Qt::Checked : Qt::Unchecked );
400  mCustomCheckBox->blockSignals( false );
401 
402  //make sure height of custom dash button looks good under different platforms
403  const QSize size = mChangePatternButton->minimumSizeHint();
404  const int fontHeight = static_cast< int >( Qgis::UI_SCALE_FACTOR * fontMetrics().height() * 1.4 );
405  mChangePatternButton->setMinimumSize( QSize( size.width(), std::max( size.height(), fontHeight ) ) );
406 
407  //draw inside polygon?
408  const bool drawInsidePolygon = mLayer->drawInsidePolygon();
409  whileBlocking( mDrawInsideCheckBox )->setCheckState( drawInsidePolygon ? Qt::Checked : Qt::Unchecked );
410 
411  whileBlocking( mRingFilterComboBox )->setCurrentIndex( mRingFilterComboBox->findData( mLayer->ringFilter() ) );
412 
413  whileBlocking( mCheckAlignDash )->setChecked( mLayer->alignDashPattern() );
414  mCheckDashCorners->setEnabled( mLayer->alignDashPattern() );
415  whileBlocking( mCheckDashCorners )->setChecked( mLayer->tweakDashPatternOnCorners() && mLayer->alignDashPattern() );
416 
418 
429 
430  updateAssistantSymbol();
431 }
432 
434 {
435  return mLayer;
436 }
437 
439 {
441 
442  switch ( context.symbolType() )
443  {
446  //these settings only have an effect when the symbol layers is part of a fill symbol
447  mDrawInsideCheckBox->hide();
448  mRingFilterComboBox->hide();
449  mRingsLabel->hide();
450  break;
451 
454  break;
455  }
456 }
457 
458 void QgsSimpleLineSymbolLayerWidget::penWidthChanged()
459 {
460  mLayer->setWidth( spinWidth->value() );
462  emit changed();
463 }
464 
465 void QgsSimpleLineSymbolLayerWidget::colorChanged( const QColor &color )
466 {
467  mLayer->setColor( color );
468  emit changed();
469 }
470 
471 void QgsSimpleLineSymbolLayerWidget::penStyleChanged()
472 {
473  mLayer->setPenStyle( cboPenStyle->penStyle() );
474  mLayer->setPenJoinStyle( cboJoinStyle->penJoinStyle() );
475  mLayer->setPenCapStyle( cboCapStyle->penCapStyle() );
477  emit changed();
478 }
479 
480 void QgsSimpleLineSymbolLayerWidget::offsetChanged()
481 {
482  mLayer->setOffset( spinOffset->value() );
484  emit changed();
485 }
486 
487 void QgsSimpleLineSymbolLayerWidget::patternOffsetChanged()
488 {
489  mLayer->setDashPatternOffset( spinPatternOffset->value() );
491  emit changed();
492 }
493 
494 void QgsSimpleLineSymbolLayerWidget::mCustomCheckBox_stateChanged( int state )
495 {
496  const bool checked = ( state == Qt::Checked );
497  mChangePatternButton->setEnabled( checked );
498  label_3->setEnabled( !checked );
499  cboPenStyle->setEnabled( !checked );
500 
501  mLayer->setUseCustomDashPattern( checked );
502  emit changed();
503 }
504 
505 void QgsSimpleLineSymbolLayerWidget::mChangePatternButton_clicked()
506 {
508  if ( panel && panel->dockMode() )
509  {
511  widget->setPanelTitle( tr( "Custom Dash Pattern" ) );
512  widget->setUnit( mDashPatternUnitWidget->unit() );
513  connect( widget, &QgsPanelWidget::widgetChanged, this, [ this, widget ]()
514  {
517  } );
519  panel->openPanel( widget );
520  return;
521  }
522 
524  d.setUnit( mDashPatternUnitWidget->unit() );
525  if ( d.exec() == QDialog::Accepted )
526  {
527  mLayer->setCustomDashVector( d.dashDotVector() );
529  emit changed();
530  }
531 }
532 
533 void QgsSimpleLineSymbolLayerWidget::mPenWidthUnitWidget_changed()
534 {
535  if ( mLayer )
536  {
537  mLayer->setWidthUnit( mPenWidthUnitWidget->unit() );
538  mLayer->setWidthMapUnitScale( mPenWidthUnitWidget->getMapUnitScale() );
540  emit changed();
541  }
542 }
543 
544 void QgsSimpleLineSymbolLayerWidget::mOffsetUnitWidget_changed()
545 {
546  if ( mLayer )
547  {
548  mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
549  mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
550  emit changed();
551  }
552 }
553 
554 void QgsSimpleLineSymbolLayerWidget::mDashPatternUnitWidget_changed()
555 {
556  if ( mLayer )
557  {
558  mLayer->setCustomDashPatternUnit( mDashPatternUnitWidget->unit() );
559  mLayer->setCustomDashPatternMapUnitScale( mDashPatternUnitWidget->getMapUnitScale() );
561  emit changed();
562  }
563 }
564 
565 void QgsSimpleLineSymbolLayerWidget::mDrawInsideCheckBox_stateChanged( int state )
566 {
567  const bool checked = ( state == Qt::Checked );
568  mLayer->setDrawInsidePolygon( checked );
569  emit changed();
570 }
571 
572 void QgsSimpleLineSymbolLayerWidget::patternOffsetUnitChanged()
573 {
574  if ( mLayer )
575  {
576  mLayer->setDashPatternOffsetUnit( mPatternOffsetUnitWidget->unit() );
577  mLayer->setDashPatternOffsetMapUnitScale( mPatternOffsetUnitWidget->getMapUnitScale() );
579  emit changed();
580  }
581 }
582 
584 {
585  if ( !mLayer )
586  {
587  return;
588  }
589  std::unique_ptr< QgsSimpleLineSymbolLayer > layerCopy( mLayer->clone() );
590  if ( !layerCopy )
591  {
592  return;
593  }
594  const QColor color = qApp->palette().color( QPalette::WindowText );
595  layerCopy->setColor( color );
596  // reset offset, we don't want to show that in the preview
597  layerCopy->setOffset( 0 );
598  layerCopy->setUseCustomDashPattern( true );
599 
600  QSize currentIconSize;
601  //icon size is button size with a small margin
602 #ifdef Q_OS_WIN
603  currentIconSize = QSize( mChangePatternButton->width() - 10, mChangePatternButton->height() - 6 );
604 #else
605  currentIconSize = QSize( mChangePatternButton->width() - 10, mChangePatternButton->height() - 12 );
606 #endif
607 
608  if ( !currentIconSize.isValid() || currentIconSize.width() <= 0 || currentIconSize.height() <= 0 )
609  {
610  return;
611  }
612 
613  //create an icon pixmap
614  const std::unique_ptr< QgsLineSymbol > previewSymbol = std::make_unique< QgsLineSymbol >( QgsSymbolLayerList() << layerCopy.release() );
615  const QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( previewSymbol.get(), currentIconSize );
616  mChangePatternButton->setIconSize( currentIconSize );
617  mChangePatternButton->setIcon( icon );
618 
619  // set tooltip
620  // create very large preview image
621  const int width = static_cast< int >( Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance( 'X' ) * 23 );
622  const int height = static_cast< int >( width / 1.61803398875 ); // golden ratio
623 
624  const QPixmap pm = QgsSymbolLayerUtils::symbolPreviewPixmap( previewSymbol.get(), QSize( width, height ), height / 20 );
625  QByteArray data;
626  QBuffer buffer( &data );
627  pm.save( &buffer, "PNG", 100 );
628  mChangePatternButton->setToolTip( QStringLiteral( "<img src='data:image/png;base64, %3'>" ).arg( QString( data.toBase64() ) ) );
629 }
630 
632 {
633  QgsSymbolLayerWidget::resizeEvent( event );
634  // redraw custom dash pattern icon -- the button size has changed
636 }
637 
638 
640 
641 
643  : QgsSymbolLayerWidget( parent, vl )
644 {
645  mLayer = nullptr;
646 
647  setupUi( this );
648  connect( mSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSimpleMarkerSymbolLayerWidget::mSizeUnitWidget_changed );
649  connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSimpleMarkerSymbolLayerWidget::mOffsetUnitWidget_changed );
650  connect( mStrokeWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSimpleMarkerSymbolLayerWidget::mStrokeWidthUnitWidget_changed );
651  connect( mStrokeStyleComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::mStrokeStyleComboBox_currentIndexChanged );
652  connect( mStrokeWidthSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::mStrokeWidthSpinBox_valueChanged );
653  connect( mHorizontalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged );
654  connect( mVerticalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged );
661 
662  btnChangeColorFill->setAllowOpacity( true );
663  btnChangeColorFill->setColorDialogTitle( tr( "Select Fill Color" ) );
664  btnChangeColorFill->setContext( QStringLiteral( "symbology" ) );
665  btnChangeColorFill->setShowNoColor( true );
666  btnChangeColorFill->setNoColorString( tr( "Transparent Fill" ) );
667  btnChangeColorStroke->setAllowOpacity( true );
668  btnChangeColorStroke->setColorDialogTitle( tr( "Select Stroke Color" ) );
669  btnChangeColorStroke->setContext( QStringLiteral( "symbology" ) );
670  btnChangeColorStroke->setShowNoColor( true );
671  btnChangeColorStroke->setNoColorString( tr( "Transparent Stroke" ) );
672 
673  mFillColorDDBtn->registerLinkedWidget( btnChangeColorFill );
674  mStrokeColorDDBtn->registerLinkedWidget( btnChangeColorStroke );
675 
676  spinOffsetX->setClearValue( 0.0 );
677  spinOffsetY->setClearValue( 0.0 );
678  spinAngle->setClearValue( 0.0 );
679 
680  //make a temporary symbol for the size assistant preview
681  mAssistantPreviewSymbol.reset( new QgsMarkerSymbol() );
682 
683  if ( vectorLayer() )
684  mSizeDDBtn->setSymbol( mAssistantPreviewSymbol );
685 
686  int size = lstNames->iconSize().width();
687 
688  size = std::max( 30, static_cast< int >( std::round( Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance( 'X' ) * 3 ) ) );
689 
690  lstNames->setGridSize( QSize( size * 1.2, size * 1.2 ) );
691  lstNames->setIconSize( QSize( size, size ) );
692 
693  const double markerSize = size * 0.8;
695  for ( const Qgis::MarkerShape shape : shapes )
696  {
697  QgsSimpleMarkerSymbolLayer *lyr = new QgsSimpleMarkerSymbolLayer( shape, markerSize );
699  lyr->setColor( QColor( 200, 200, 200 ) );
700  lyr->setStrokeColor( QColor( 0, 0, 0 ) );
701  const QIcon icon = QgsSymbolLayerUtils::symbolLayerPreviewIcon( lyr, QgsUnitTypes::RenderPixels, QSize( size, size ) );
702  QListWidgetItem *item = new QListWidgetItem( icon, QString(), lstNames );
703  item->setData( Qt::UserRole, static_cast< int >( shape ) );
704  item->setToolTip( QgsSimpleMarkerSymbolLayerBase::encodeShape( shape ) );
705  delete lyr;
706  }
707  // show at least 3 rows
708  lstNames->setMinimumHeight( lstNames->gridSize().height() * 3.1 );
709 
710  connect( lstNames, &QListWidget::currentRowChanged, this, &QgsSimpleMarkerSymbolLayerWidget::setShape );
711  connect( btnChangeColorStroke, &QgsColorButton::colorChanged, this, &QgsSimpleMarkerSymbolLayerWidget::setColorStroke );
713  connect( cboJoinStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::penJoinStyleChanged );
714  connect( cboCapStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::penCapStyleChanged );
715  connect( spinSize, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::setSize );
716  connect( spinAngle, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::setAngle );
717  connect( spinOffsetX, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::setOffset );
718  connect( spinOffsetY, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::setOffset );
719  connect( this, &QgsSymbolLayerWidget::changed, this, &QgsSimpleMarkerSymbolLayerWidget::updateAssistantSymbol );
720 }
721 
723 
725 {
726  if ( layer->layerType() != QLatin1String( "SimpleMarker" ) )
727  return;
728 
729  // layer type is correct, we can do the cast
730  mLayer = static_cast<QgsSimpleMarkerSymbolLayer *>( layer );
731 
732  // set values
733  const Qgis::MarkerShape shape = mLayer->shape();
734  for ( int i = 0; i < lstNames->count(); ++i )
735  {
736  if ( static_cast< Qgis::MarkerShape >( lstNames->item( i )->data( Qt::UserRole ).toInt() ) == shape )
737  {
738  lstNames->setCurrentRow( i );
739  break;
740  }
741  }
742  btnChangeColorStroke->blockSignals( true );
743  btnChangeColorStroke->setColor( mLayer->strokeColor() );
744  btnChangeColorStroke->blockSignals( false );
745  btnChangeColorFill->blockSignals( true );
746  btnChangeColorFill->setColor( mLayer->fillColor() );
747  btnChangeColorFill->setEnabled( QgsSimpleMarkerSymbolLayerBase::shapeIsFilled( mLayer->shape() ) );
748  btnChangeColorFill->blockSignals( false );
749  spinSize->blockSignals( true );
750  spinSize->setValue( mLayer->size() );
751  spinSize->blockSignals( false );
752  spinAngle->blockSignals( true );
753  spinAngle->setValue( mLayer->angle() );
754  spinAngle->blockSignals( false );
755  mStrokeStyleComboBox->blockSignals( true );
756  mStrokeStyleComboBox->setPenStyle( mLayer->strokeStyle() );
757  mStrokeStyleComboBox->blockSignals( false );
758  mStrokeWidthSpinBox->blockSignals( true );
759  mStrokeWidthSpinBox->setValue( mLayer->strokeWidth() );
760  mStrokeWidthSpinBox->blockSignals( false );
761  cboJoinStyle->blockSignals( true );
762  cboJoinStyle->setPenJoinStyle( mLayer->penJoinStyle() );
763  cboJoinStyle->blockSignals( false );
764  cboCapStyle->blockSignals( true );
765  cboCapStyle->setPenCapStyle( mLayer->penCapStyle() );
766  cboCapStyle->blockSignals( false );
767 
768  // without blocking signals the value gets changed because of slot setOffset()
769  spinOffsetX->blockSignals( true );
770  spinOffsetX->setValue( mLayer->offset().x() );
771  spinOffsetX->blockSignals( false );
772  spinOffsetY->blockSignals( true );
773  spinOffsetY->setValue( mLayer->offset().y() );
774  spinOffsetY->blockSignals( false );
775 
776  mSizeUnitWidget->blockSignals( true );
777  mSizeUnitWidget->setUnit( mLayer->sizeUnit() );
778  mSizeUnitWidget->setMapUnitScale( mLayer->sizeMapUnitScale() );
779  mSizeUnitWidget->blockSignals( false );
780  mOffsetUnitWidget->blockSignals( true );
781  mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
782  mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
783  mOffsetUnitWidget->blockSignals( false );
784  mStrokeWidthUnitWidget->blockSignals( true );
785  mStrokeWidthUnitWidget->setUnit( mLayer->strokeWidthUnit() );
786  mStrokeWidthUnitWidget->setMapUnitScale( mLayer->strokeWidthMapUnitScale() );
787  mStrokeWidthUnitWidget->blockSignals( false );
788 
789  //anchor points
790  mHorizontalAnchorComboBox->blockSignals( true );
791  mVerticalAnchorComboBox->blockSignals( true );
792  mHorizontalAnchorComboBox->setCurrentIndex( mLayer->horizontalAnchorPoint() );
793  mVerticalAnchorComboBox->setCurrentIndex( mLayer->verticalAnchorPoint() );
794  mHorizontalAnchorComboBox->blockSignals( false );
795  mVerticalAnchorComboBox->blockSignals( false );
796 
809 
810  updateAssistantSymbol();
811 }
812 
814 {
815  return mLayer;
816 }
817 
818 void QgsSimpleMarkerSymbolLayerWidget::setShape()
819 {
820  mLayer->setShape( static_cast< Qgis::MarkerShape >( lstNames->currentItem()->data( Qt::UserRole ).toInt() ) );
821  btnChangeColorFill->setEnabled( QgsSimpleMarkerSymbolLayerBase::shapeIsFilled( mLayer->shape() ) );
822  emit changed();
823 }
824 
826 {
827  mLayer->setStrokeColor( color );
828  emit changed();
829 }
830 
832 {
833  mLayer->setColor( color );
834  emit changed();
835 }
836 
837 void QgsSimpleMarkerSymbolLayerWidget::penJoinStyleChanged()
838 {
839  mLayer->setPenJoinStyle( cboJoinStyle->penJoinStyle() );
840  emit changed();
841 }
842 
843 void QgsSimpleMarkerSymbolLayerWidget::penCapStyleChanged()
844 {
845  mLayer->setPenCapStyle( cboCapStyle->penCapStyle() );
846  emit changed();
847 }
848 
849 void QgsSimpleMarkerSymbolLayerWidget::setSize()
850 {
851  mLayer->setSize( spinSize->value() );
852  emit changed();
853 }
854 
855 void QgsSimpleMarkerSymbolLayerWidget::setAngle()
856 {
857  mLayer->setAngle( spinAngle->value() );
858  emit changed();
859 }
860 
861 void QgsSimpleMarkerSymbolLayerWidget::setOffset()
862 {
863  mLayer->setOffset( QPointF( spinOffsetX->value(), spinOffsetY->value() ) );
864  emit changed();
865 }
866 
867 void QgsSimpleMarkerSymbolLayerWidget::mStrokeStyleComboBox_currentIndexChanged( int index )
868 {
869  Q_UNUSED( index )
870 
871  if ( mLayer )
872  {
873  mLayer->setStrokeStyle( mStrokeStyleComboBox->penStyle() );
874  emit changed();
875  }
876 }
877 
878 void QgsSimpleMarkerSymbolLayerWidget::mStrokeWidthSpinBox_valueChanged( double d )
879 {
880  if ( mLayer )
881  {
882  mLayer->setStrokeWidth( d );
883  emit changed();
884  }
885 }
886 
887 void QgsSimpleMarkerSymbolLayerWidget::mSizeUnitWidget_changed()
888 {
889  if ( mLayer )
890  {
891  mLayer->setSizeUnit( mSizeUnitWidget->unit() );
892  mLayer->setSizeMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
893  emit changed();
894  }
895 }
896 
897 void QgsSimpleMarkerSymbolLayerWidget::mOffsetUnitWidget_changed()
898 {
899  if ( mLayer )
900  {
901  mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
902  mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
903  emit changed();
904  }
905 }
906 
907 void QgsSimpleMarkerSymbolLayerWidget::mStrokeWidthUnitWidget_changed()
908 {
909  if ( mLayer )
910  {
911  mLayer->setStrokeWidthUnit( mStrokeWidthUnitWidget->unit() );
912  mLayer->setStrokeWidthMapUnitScale( mStrokeWidthUnitWidget->getMapUnitScale() );
913  emit changed();
914  }
915 }
916 
917 void QgsSimpleMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged( int index )
918 {
919  if ( mLayer )
920  {
922  emit changed();
923  }
924 }
925 
926 void QgsSimpleMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged( int index )
927 {
928  if ( mLayer )
929  {
931  emit changed();
932  }
933 }
934 
935 void QgsSimpleMarkerSymbolLayerWidget::updateAssistantSymbol()
936 {
937  for ( int i = mAssistantPreviewSymbol->symbolLayerCount() - 1 ; i >= 0; --i )
938  {
939  mAssistantPreviewSymbol->deleteSymbolLayer( i );
940  }
941  mAssistantPreviewSymbol->appendSymbolLayer( mLayer->clone() );
943  if ( ddSize )
944  mAssistantPreviewSymbol->setDataDefinedSize( ddSize );
945 }
946 
947 
949 
951  : QgsSymbolLayerWidget( parent, vl )
952 {
953  mLayer = nullptr;
954 
955  setupUi( this );
956  connect( mStrokeWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSimpleFillSymbolLayerWidget::mStrokeWidthUnitWidget_changed );
957  connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSimpleFillSymbolLayerWidget::mOffsetUnitWidget_changed );
962 
963  btnChangeColor->setAllowOpacity( true );
964  btnChangeColor->setColorDialogTitle( tr( "Select Fill Color" ) );
965  btnChangeColor->setContext( QStringLiteral( "symbology" ) );
966  btnChangeColor->setShowNoColor( true );
967  btnChangeColor->setNoColorString( tr( "Transparent Fill" ) );
968  btnChangeStrokeColor->setAllowOpacity( true );
969  btnChangeStrokeColor->setColorDialogTitle( tr( "Select Stroke Color" ) );
970  btnChangeStrokeColor->setContext( QStringLiteral( "symbology" ) );
971  btnChangeStrokeColor->setShowNoColor( true );
972  btnChangeStrokeColor->setNoColorString( tr( "Transparent Stroke" ) );
973 
974  spinOffsetX->setClearValue( 0.0 );
975  spinOffsetY->setClearValue( 0.0 );
976 
978  connect( cboFillStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleFillSymbolLayerWidget::setBrushStyle );
979  connect( btnChangeStrokeColor, &QgsColorButton::colorChanged, this, &QgsSimpleFillSymbolLayerWidget::setStrokeColor );
980  connect( spinStrokeWidth, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleFillSymbolLayerWidget::strokeWidthChanged );
981  connect( cboStrokeStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleFillSymbolLayerWidget::strokeStyleChanged );
982  connect( cboJoinStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleFillSymbolLayerWidget::strokeStyleChanged );
983  connect( spinOffsetX, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleFillSymbolLayerWidget::offsetChanged );
984  connect( spinOffsetY, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleFillSymbolLayerWidget::offsetChanged );
985 
986  mFillColorDDBtn->registerLinkedWidget( btnChangeColor );
987  mStrokeColorDDBtn->registerLinkedWidget( btnChangeStrokeColor );
988 }
989 
991 {
992  if ( layer->layerType() != QLatin1String( "SimpleFill" ) )
993  return;
994 
995  // layer type is correct, we can do the cast
996  mLayer = static_cast<QgsSimpleFillSymbolLayer *>( layer );
997 
998  // set values
999  btnChangeColor->blockSignals( true );
1000  btnChangeColor->setColor( mLayer->color() );
1001  btnChangeColor->blockSignals( false );
1002  cboFillStyle->blockSignals( true );
1003  cboFillStyle->setBrushStyle( mLayer->brushStyle() );
1004  cboFillStyle->blockSignals( false );
1005  btnChangeStrokeColor->blockSignals( true );
1006  btnChangeStrokeColor->setColor( mLayer->strokeColor() );
1007  btnChangeStrokeColor->blockSignals( false );
1008  cboStrokeStyle->blockSignals( true );
1009  cboStrokeStyle->setPenStyle( mLayer->strokeStyle() );
1010  cboStrokeStyle->blockSignals( false );
1011  spinStrokeWidth->blockSignals( true );
1012  spinStrokeWidth->setValue( mLayer->strokeWidth() );
1013  spinStrokeWidth->blockSignals( false );
1014  cboJoinStyle->blockSignals( true );
1015  cboJoinStyle->setPenJoinStyle( mLayer->penJoinStyle() );
1016  cboJoinStyle->blockSignals( false );
1017  spinOffsetX->blockSignals( true );
1018  spinOffsetX->setValue( mLayer->offset().x() );
1019  spinOffsetX->blockSignals( false );
1020  spinOffsetY->blockSignals( true );
1021  spinOffsetY->setValue( mLayer->offset().y() );
1022  spinOffsetY->blockSignals( false );
1023 
1024  mStrokeWidthUnitWidget->blockSignals( true );
1025  mStrokeWidthUnitWidget->setUnit( mLayer->strokeWidthUnit() );
1026  mStrokeWidthUnitWidget->setMapUnitScale( mLayer->strokeWidthMapUnitScale() );
1027  mStrokeWidthUnitWidget->blockSignals( false );
1028  mOffsetUnitWidget->blockSignals( true );
1029  mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
1030  mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
1031  mOffsetUnitWidget->blockSignals( false );
1032 
1040 }
1041 
1043 {
1044  return mLayer;
1045 }
1046 
1047 void QgsSimpleFillSymbolLayerWidget::setColor( const QColor &color )
1048 {
1049  mLayer->setColor( color );
1050  emit changed();
1051 }
1052 
1054 {
1055  mLayer->setStrokeColor( color );
1056  emit changed();
1057 }
1058 
1059 void QgsSimpleFillSymbolLayerWidget::setBrushStyle()
1060 {
1061  mLayer->setBrushStyle( cboFillStyle->brushStyle() );
1062  emit changed();
1063 }
1064 
1065 void QgsSimpleFillSymbolLayerWidget::strokeWidthChanged()
1066 {
1067  mLayer->setStrokeWidth( spinStrokeWidth->value() );
1068  emit changed();
1069 }
1070 
1071 void QgsSimpleFillSymbolLayerWidget::strokeStyleChanged()
1072 {
1073  mLayer->setStrokeStyle( cboStrokeStyle->penStyle() );
1074  mLayer->setPenJoinStyle( cboJoinStyle->penJoinStyle() );
1075  emit changed();
1076 }
1077 
1078 void QgsSimpleFillSymbolLayerWidget::offsetChanged()
1079 {
1080  mLayer->setOffset( QPointF( spinOffsetX->value(), spinOffsetY->value() ) );
1081  emit changed();
1082 }
1083 
1084 void QgsSimpleFillSymbolLayerWidget::mStrokeWidthUnitWidget_changed()
1085 {
1086  if ( mLayer )
1087  {
1088  mLayer->setStrokeWidthUnit( mStrokeWidthUnitWidget->unit() );
1089  mLayer->setStrokeWidthMapUnitScale( mStrokeWidthUnitWidget->getMapUnitScale() );
1090  emit changed();
1091  }
1092 }
1093 
1094 void QgsSimpleFillSymbolLayerWidget::mOffsetUnitWidget_changed()
1095 {
1096  if ( mLayer )
1097  {
1098  mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
1099  mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
1100  emit changed();
1101  }
1102 }
1103 
1105 
1107  : QgsSymbolLayerWidget( parent, vl )
1108 {
1109  mLayer = nullptr;
1110 
1111  setupUi( this );
1112  connect( mSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsFilledMarkerSymbolLayerWidget::mSizeUnitWidget_changed );
1113  connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsFilledMarkerSymbolLayerWidget::mOffsetUnitWidget_changed );
1114  connect( mHorizontalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsFilledMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged );
1115  connect( mVerticalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsFilledMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged );
1120 
1121  spinOffsetX->setClearValue( 0.0 );
1122  spinOffsetY->setClearValue( 0.0 );
1123  spinAngle->setClearValue( 0.0 );
1124 
1125  //make a temporary symbol for the size assistant preview
1126  mAssistantPreviewSymbol.reset( new QgsMarkerSymbol() );
1127 
1128  if ( vectorLayer() )
1129  mSizeDDBtn->setSymbol( mAssistantPreviewSymbol );
1130 
1131  int size = lstNames->iconSize().width();
1132  size = std::max( 30, static_cast< int >( std::round( Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance( 'X' ) * 3 ) ) );
1133  lstNames->setGridSize( QSize( size * 1.2, size * 1.2 ) );
1134  lstNames->setIconSize( QSize( size, size ) );
1135 
1136  const double markerSize = size * 0.8;
1138  for ( const Qgis::MarkerShape shape : shapes )
1139  {
1140  QgsSimpleMarkerSymbolLayer *lyr = new QgsSimpleMarkerSymbolLayer( shape, markerSize );
1142  lyr->setColor( QColor( 200, 200, 200 ) );
1143  lyr->setStrokeColor( QColor( 0, 0, 0 ) );
1144  const QIcon icon = QgsSymbolLayerUtils::symbolLayerPreviewIcon( lyr, QgsUnitTypes::RenderPixels, QSize( size, size ) );
1145  QListWidgetItem *item = new QListWidgetItem( icon, QString(), lstNames );
1146  item->setData( Qt::UserRole, static_cast< int >( shape ) );
1147  item->setToolTip( QgsSimpleMarkerSymbolLayerBase::encodeShape( shape ) );
1148  delete lyr;
1149  }
1150  // show at least 3 rows
1151  lstNames->setMinimumHeight( lstNames->gridSize().height() * 3.1 );
1152 
1153  connect( lstNames, &QListWidget::currentRowChanged, this, &QgsFilledMarkerSymbolLayerWidget::setShape );
1154  connect( spinSize, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsFilledMarkerSymbolLayerWidget::setSize );
1155  connect( spinAngle, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsFilledMarkerSymbolLayerWidget::setAngle );
1156  connect( spinOffsetX, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsFilledMarkerSymbolLayerWidget::setOffset );
1157  connect( spinOffsetY, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsFilledMarkerSymbolLayerWidget::setOffset );
1158  connect( this, &QgsSymbolLayerWidget::changed, this, &QgsFilledMarkerSymbolLayerWidget::updateAssistantSymbol );
1159 }
1160 
1162 
1164 {
1165  if ( layer->layerType() != QLatin1String( "FilledMarker" ) )
1166  return;
1167 
1168  // layer type is correct, we can do the cast
1169  mLayer = static_cast<QgsFilledMarkerSymbolLayer *>( layer );
1170 
1171  // set values
1172  const Qgis::MarkerShape shape = mLayer->shape();
1173  for ( int i = 0; i < lstNames->count(); ++i )
1174  {
1175  if ( static_cast< Qgis::MarkerShape >( lstNames->item( i )->data( Qt::UserRole ).toInt() ) == shape )
1176  {
1177  lstNames->setCurrentRow( i );
1178  break;
1179  }
1180  }
1181  whileBlocking( spinSize )->setValue( mLayer->size() );
1182  whileBlocking( spinAngle )->setValue( mLayer->angle() );
1183  whileBlocking( spinOffsetX )->setValue( mLayer->offset().x() );
1184  whileBlocking( spinOffsetY )->setValue( mLayer->offset().y() );
1185 
1186  mSizeUnitWidget->blockSignals( true );
1187  mSizeUnitWidget->setUnit( mLayer->sizeUnit() );
1188  mSizeUnitWidget->setMapUnitScale( mLayer->sizeMapUnitScale() );
1189  mSizeUnitWidget->blockSignals( false );
1190  mOffsetUnitWidget->blockSignals( true );
1191  mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
1192  mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
1193  mOffsetUnitWidget->blockSignals( false );
1194 
1195  //anchor points
1196  whileBlocking( mHorizontalAnchorComboBox )->setCurrentIndex( mLayer->horizontalAnchorPoint() );
1197  whileBlocking( mVerticalAnchorComboBox )->setCurrentIndex( mLayer->verticalAnchorPoint() );
1198 
1205 
1206  updateAssistantSymbol();
1207 }
1208 
1210 {
1211  return mLayer;
1212 }
1213 
1214 void QgsFilledMarkerSymbolLayerWidget::setShape()
1215 {
1216  mLayer->setShape( static_cast< Qgis::MarkerShape >( lstNames->currentItem()->data( Qt::UserRole ).toInt() ) );
1217  emit changed();
1218 }
1219 
1220 void QgsFilledMarkerSymbolLayerWidget::setSize()
1221 {
1222  mLayer->setSize( spinSize->value() );
1223  emit changed();
1224 }
1225 
1226 void QgsFilledMarkerSymbolLayerWidget::setAngle()
1227 {
1228  mLayer->setAngle( spinAngle->value() );
1229  emit changed();
1230 }
1231 
1232 void QgsFilledMarkerSymbolLayerWidget::setOffset()
1233 {
1234  mLayer->setOffset( QPointF( spinOffsetX->value(), spinOffsetY->value() ) );
1235  emit changed();
1236 }
1237 
1238 void QgsFilledMarkerSymbolLayerWidget::mSizeUnitWidget_changed()
1239 {
1240  if ( mLayer )
1241  {
1242  mLayer->setSizeUnit( mSizeUnitWidget->unit() );
1243  mLayer->setSizeMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
1244  emit changed();
1245  }
1246 }
1247 
1248 void QgsFilledMarkerSymbolLayerWidget::mOffsetUnitWidget_changed()
1249 {
1250  if ( mLayer )
1251  {
1252  mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
1253  mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
1254  emit changed();
1255  }
1256 }
1257 
1258 void QgsFilledMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged( int index )
1259 {
1260  if ( mLayer )
1261  {
1263  emit changed();
1264  }
1265 }
1266 
1267 void QgsFilledMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged( int index )
1268 {
1269  if ( mLayer )
1270  {
1272  emit changed();
1273  }
1274 }
1275 
1276 void QgsFilledMarkerSymbolLayerWidget::updateAssistantSymbol()
1277 {
1278  for ( int i = mAssistantPreviewSymbol->symbolLayerCount() - 1 ; i >= 0; --i )
1279  {
1280  mAssistantPreviewSymbol->deleteSymbolLayer( i );
1281  }
1282  mAssistantPreviewSymbol->appendSymbolLayer( mLayer->clone() );
1284  if ( ddSize )
1285  mAssistantPreviewSymbol->setDataDefinedSize( ddSize );
1286 }
1287 
1288 
1290 
1292  : QgsSymbolLayerWidget( parent, vl )
1293 {
1294  mLayer = nullptr;
1295 
1296  setupUi( this );
1297  connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsGradientFillSymbolLayerWidget::mOffsetUnitWidget_changed );
1298  connect( mSpinAngle, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsGradientFillSymbolLayerWidget::mSpinAngle_valueChanged );
1301 
1302  btnColorRamp->setShowGradientOnly( true );
1303 
1304  btnChangeColor->setAllowOpacity( true );
1305  btnChangeColor->setColorDialogTitle( tr( "Select Gradient Color" ) );
1306  btnChangeColor->setContext( QStringLiteral( "symbology" ) );
1307  btnChangeColor->setShowNoColor( true );
1308  btnChangeColor->setNoColorString( tr( "Transparent" ) );
1309  btnChangeColor2->setAllowOpacity( true );
1310  btnChangeColor2->setColorDialogTitle( tr( "Select Gradient Color" ) );
1311  btnChangeColor2->setContext( QStringLiteral( "symbology" ) );
1312  btnChangeColor2->setShowNoColor( true );
1313  btnChangeColor2->setNoColorString( tr( "Transparent" ) );
1314 
1315  mStartColorDDBtn->registerLinkedWidget( btnChangeColor );
1316  mEndColorDDBtn->registerLinkedWidget( btnChangeColor2 );
1317 
1318  spinOffsetX->setClearValue( 0.0 );
1319  spinOffsetY->setClearValue( 0.0 );
1320  mSpinAngle->setClearValue( 0.0 );
1321 
1325  connect( cboGradientType, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsGradientFillSymbolLayerWidget::setGradientType );
1326  connect( cboCoordinateMode, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsGradientFillSymbolLayerWidget::setCoordinateMode );
1327  connect( cboGradientSpread, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsGradientFillSymbolLayerWidget::setGradientSpread );
1328  connect( radioTwoColor, &QAbstractButton::toggled, this, &QgsGradientFillSymbolLayerWidget::colorModeChanged );
1329  connect( spinOffsetX, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsGradientFillSymbolLayerWidget::offsetChanged );
1330  connect( spinOffsetY, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsGradientFillSymbolLayerWidget::offsetChanged );
1331  connect( spinRefPoint1X, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsGradientFillSymbolLayerWidget::referencePointChanged );
1332  connect( spinRefPoint1Y, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsGradientFillSymbolLayerWidget::referencePointChanged );
1333  connect( checkRefPoint1Centroid, &QAbstractButton::toggled, this, &QgsGradientFillSymbolLayerWidget::referencePointChanged );
1334  connect( spinRefPoint2X, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsGradientFillSymbolLayerWidget::referencePointChanged );
1335  connect( spinRefPoint2Y, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsGradientFillSymbolLayerWidget::referencePointChanged );
1336  connect( checkRefPoint2Centroid, &QAbstractButton::toggled, this, &QgsGradientFillSymbolLayerWidget::referencePointChanged );
1337 }
1338 
1340 {
1341  if ( layer->layerType() != QLatin1String( "GradientFill" ) )
1342  return;
1343 
1344  // layer type is correct, we can do the cast
1345  mLayer = static_cast<QgsGradientFillSymbolLayer *>( layer );
1346 
1347  // set values
1348  btnChangeColor->blockSignals( true );
1349  btnChangeColor->setColor( mLayer->color() );
1350  btnChangeColor->blockSignals( false );
1351  btnChangeColor2->blockSignals( true );
1352  btnChangeColor2->setColor( mLayer->color2() );
1353  btnChangeColor2->blockSignals( false );
1354 
1356  {
1357  radioTwoColor->setChecked( true );
1358  btnColorRamp->setEnabled( false );
1359  }
1360  else
1361  {
1362  radioColorRamp->setChecked( true );
1363  btnChangeColor->setEnabled( false );
1364  btnChangeColor2->setEnabled( false );
1365  }
1366 
1367  // set source color ramp
1368  if ( mLayer->colorRamp() )
1369  {
1370  btnColorRamp->blockSignals( true );
1371  btnColorRamp->setColorRamp( mLayer->colorRamp() );
1372  btnColorRamp->blockSignals( false );
1373  }
1374 
1375  cboGradientType->blockSignals( true );
1376  switch ( mLayer->gradientType() )
1377  {
1379  cboGradientType->setCurrentIndex( 0 );
1380  break;
1382  cboGradientType->setCurrentIndex( 1 );
1383  break;
1385  cboGradientType->setCurrentIndex( 2 );
1386  break;
1387  }
1388  cboGradientType->blockSignals( false );
1389 
1390  cboCoordinateMode->blockSignals( true );
1391  switch ( mLayer->coordinateMode() )
1392  {
1394  cboCoordinateMode->setCurrentIndex( 1 );
1395  checkRefPoint1Centroid->setEnabled( false );
1396  checkRefPoint2Centroid->setEnabled( false );
1397  break;
1399  default:
1400  cboCoordinateMode->setCurrentIndex( 0 );
1401  break;
1402  }
1403  cboCoordinateMode->blockSignals( false );
1404 
1405  cboGradientSpread->blockSignals( true );
1406  switch ( mLayer->gradientSpread() )
1407  {
1409  cboGradientSpread->setCurrentIndex( 0 );
1410  break;
1412  cboGradientSpread->setCurrentIndex( 1 );
1413  break;
1415  cboGradientSpread->setCurrentIndex( 2 );
1416  break;
1417  }
1418  cboGradientSpread->blockSignals( false );
1419 
1420  spinRefPoint1X->blockSignals( true );
1421  spinRefPoint1X->setValue( mLayer->referencePoint1().x() );
1422  spinRefPoint1X->blockSignals( false );
1423  spinRefPoint1Y->blockSignals( true );
1424  spinRefPoint1Y->setValue( mLayer->referencePoint1().y() );
1425  spinRefPoint1Y->blockSignals( false );
1426  checkRefPoint1Centroid->blockSignals( true );
1427  checkRefPoint1Centroid->setChecked( mLayer->referencePoint1IsCentroid() );
1429  {
1430  spinRefPoint1X->setEnabled( false );
1431  spinRefPoint1Y->setEnabled( false );
1432  }
1433  checkRefPoint1Centroid->blockSignals( false );
1434  spinRefPoint2X->blockSignals( true );
1435  spinRefPoint2X->setValue( mLayer->referencePoint2().x() );
1436  spinRefPoint2X->blockSignals( false );
1437  spinRefPoint2Y->blockSignals( true );
1438  spinRefPoint2Y->setValue( mLayer->referencePoint2().y() );
1439  spinRefPoint2Y->blockSignals( false );
1440  checkRefPoint2Centroid->blockSignals( true );
1441  checkRefPoint2Centroid->setChecked( mLayer->referencePoint2IsCentroid() );
1443  {
1444  spinRefPoint2X->setEnabled( false );
1445  spinRefPoint2Y->setEnabled( false );
1446  }
1447  checkRefPoint2Centroid->blockSignals( false );
1448 
1449  spinOffsetX->blockSignals( true );
1450  spinOffsetX->setValue( mLayer->offset().x() );
1451  spinOffsetX->blockSignals( false );
1452  spinOffsetY->blockSignals( true );
1453  spinOffsetY->setValue( mLayer->offset().y() );
1454  spinOffsetY->blockSignals( false );
1455  mSpinAngle->blockSignals( true );
1456  mSpinAngle->setValue( mLayer->angle() );
1457  mSpinAngle->blockSignals( false );
1458 
1459  mOffsetUnitWidget->blockSignals( true );
1460  mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
1461  mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
1462  mOffsetUnitWidget->blockSignals( false );
1463 
1477 }
1478 
1480 {
1481  return mLayer;
1482 }
1483 
1485 {
1486  mLayer->setColor( color );
1487  emit changed();
1488 }
1489 
1491 {
1492  mLayer->setColor2( color );
1493  emit changed();
1494 }
1495 
1496 void QgsGradientFillSymbolLayerWidget::colorModeChanged()
1497 {
1498  if ( radioTwoColor->isChecked() )
1499  {
1501  }
1502  else
1503  {
1505  }
1506  emit changed();
1507 }
1508 
1510 {
1511  if ( btnColorRamp->isNull() )
1512  return;
1513 
1514  mLayer->setColorRamp( btnColorRamp->colorRamp()->clone() );
1515  emit changed();
1516 }
1517 
1519 {
1520  switch ( index )
1521  {
1522  case 0:
1524  //set sensible default reference points
1525  spinRefPoint1X->setValue( 0.5 );
1526  spinRefPoint1Y->setValue( 0 );
1527  spinRefPoint2X->setValue( 0.5 );
1528  spinRefPoint2Y->setValue( 1 );
1529  break;
1530  case 1:
1532  //set sensible default reference points
1533  spinRefPoint1X->setValue( 0 );
1534  spinRefPoint1Y->setValue( 0 );
1535  spinRefPoint2X->setValue( 1 );
1536  spinRefPoint2Y->setValue( 1 );
1537  break;
1538  case 2:
1540  spinRefPoint1X->setValue( 0.5 );
1541  spinRefPoint1Y->setValue( 0.5 );
1542  spinRefPoint2X->setValue( 1 );
1543  spinRefPoint2Y->setValue( 1 );
1544  break;
1545  }
1546  emit changed();
1547 }
1548 
1550 {
1551 
1552  switch ( index )
1553  {
1554  case 0:
1555  //feature coordinate mode
1557  //allow choice of centroid reference positions
1558  checkRefPoint1Centroid->setEnabled( true );
1559  checkRefPoint2Centroid->setEnabled( true );
1560  break;
1561  case 1:
1562  //viewport coordinate mode
1564  //disable choice of centroid reference positions
1565  checkRefPoint1Centroid->setChecked( Qt::Unchecked );
1566  checkRefPoint1Centroid->setEnabled( false );
1567  checkRefPoint2Centroid->setChecked( Qt::Unchecked );
1568  checkRefPoint2Centroid->setEnabled( false );
1569  break;
1570  }
1571 
1572  emit changed();
1573 }
1574 
1576 {
1577  switch ( index )
1578  {
1579  case 0:
1581  break;
1582  case 1:
1584  break;
1585  case 2:
1587  break;
1588  }
1589 
1590  emit changed();
1591 }
1592 
1593 void QgsGradientFillSymbolLayerWidget::offsetChanged()
1594 {
1595  mLayer->setOffset( QPointF( spinOffsetX->value(), spinOffsetY->value() ) );
1596  emit changed();
1597 }
1598 
1599 void QgsGradientFillSymbolLayerWidget::referencePointChanged()
1600 {
1601  mLayer->setReferencePoint1( QPointF( spinRefPoint1X->value(), spinRefPoint1Y->value() ) );
1602  mLayer->setReferencePoint1IsCentroid( checkRefPoint1Centroid->isChecked() );
1603  mLayer->setReferencePoint2( QPointF( spinRefPoint2X->value(), spinRefPoint2Y->value() ) );
1604  mLayer->setReferencePoint2IsCentroid( checkRefPoint2Centroid->isChecked() );
1605  emit changed();
1606 }
1607 
1608 void QgsGradientFillSymbolLayerWidget::mSpinAngle_valueChanged( double value )
1609 {
1610  mLayer->setAngle( value );
1611  emit changed();
1612 }
1613 
1614 void QgsGradientFillSymbolLayerWidget::mOffsetUnitWidget_changed()
1615 {
1616  if ( mLayer )
1617  {
1618  mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
1619  mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
1620  emit changed();
1621  }
1622 }
1623 
1625 
1627  : QgsSymbolLayerWidget( parent, vl )
1628 {
1629  mLayer = nullptr;
1630 
1631  setupUi( this );
1632  connect( mSpinBlurRadius, qOverload< int >( &QSpinBox::valueChanged ), this, &QgsShapeburstFillSymbolLayerWidget::mSpinBlurRadius_valueChanged );
1633  connect( mSpinMaxDistance, qOverload< double >( &QDoubleSpinBox::valueChanged ), this, &QgsShapeburstFillSymbolLayerWidget::mSpinMaxDistance_valueChanged );
1634  connect( mDistanceUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsShapeburstFillSymbolLayerWidget::mDistanceUnitWidget_changed );
1635  connect( mRadioUseWholeShape, &QRadioButton::toggled, this, &QgsShapeburstFillSymbolLayerWidget::mRadioUseWholeShape_toggled );
1636  connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsShapeburstFillSymbolLayerWidget::mOffsetUnitWidget_changed );
1637  connect( mIgnoreRingsCheckBox, &QCheckBox::stateChanged, this, &QgsShapeburstFillSymbolLayerWidget::mIgnoreRingsCheckBox_stateChanged );
1642 
1643  QButtonGroup *group1 = new QButtonGroup( this );
1644  group1->addButton( radioColorRamp );
1645  group1->addButton( radioTwoColor );
1646  QButtonGroup *group2 = new QButtonGroup( this );
1647  group2->addButton( mRadioUseMaxDistance );
1648  group2->addButton( mRadioUseWholeShape );
1649  btnChangeColor->setAllowOpacity( true );
1650  btnChangeColor->setColorDialogTitle( tr( "Select Gradient Color" ) );
1651  btnChangeColor->setContext( QStringLiteral( "symbology" ) );
1652  btnChangeColor->setShowNoColor( true );
1653  btnChangeColor->setNoColorString( tr( "Transparent" ) );
1654  btnChangeColor2->setAllowOpacity( true );
1655  btnChangeColor2->setColorDialogTitle( tr( "Select Gradient Color" ) );
1656  btnChangeColor2->setContext( QStringLiteral( "symbology" ) );
1657  btnChangeColor2->setShowNoColor( true );
1658  btnChangeColor2->setNoColorString( tr( "Transparent" ) );
1659 
1660  mStartColorDDBtn->registerLinkedWidget( btnChangeColor );
1661  mEndColorDDBtn->registerLinkedWidget( btnChangeColor2 );
1662 
1663  spinOffsetX->setClearValue( 0.0 );
1664  spinOffsetY->setClearValue( 0.0 );
1665  mSpinMaxDistance->setClearValue( 5.0 );
1666 
1667  btnColorRamp->setShowGradientOnly( true );
1668 
1669  connect( btnColorRamp, &QgsColorRampButton::colorRampChanged, this, &QgsShapeburstFillSymbolLayerWidget::applyColorRamp );
1670 
1673  connect( radioTwoColor, &QAbstractButton::toggled, this, &QgsShapeburstFillSymbolLayerWidget::colorModeChanged );
1674  connect( spinOffsetX, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsShapeburstFillSymbolLayerWidget::offsetChanged );
1675  connect( spinOffsetY, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsShapeburstFillSymbolLayerWidget::offsetChanged );
1676 
1677  connect( mBlurSlider, &QAbstractSlider::valueChanged, mSpinBlurRadius, &QSpinBox::setValue );
1678  connect( mSpinBlurRadius, static_cast < void ( QSpinBox::* )( int ) > ( &QSpinBox::valueChanged ), mBlurSlider, &QAbstractSlider::setValue );
1679 }
1680 
1682 {
1683  if ( layer->layerType() != QLatin1String( "ShapeburstFill" ) )
1684  return;
1685 
1686  // layer type is correct, we can do the cast
1687  mLayer = static_cast<QgsShapeburstFillSymbolLayer *>( layer );
1688 
1689  // set values
1690  btnChangeColor->blockSignals( true );
1691  btnChangeColor->setColor( mLayer->color() );
1692  btnChangeColor->blockSignals( false );
1693  btnChangeColor2->blockSignals( true );
1694  btnChangeColor2->setColor( mLayer->color2() );
1695  btnChangeColor2->blockSignals( false );
1696 
1698  {
1699  radioTwoColor->setChecked( true );
1700  btnColorRamp->setEnabled( false );
1701  }
1702  else
1703  {
1704  radioColorRamp->setChecked( true );
1705  btnChangeColor->setEnabled( false );
1706  btnChangeColor2->setEnabled( false );
1707  }
1708 
1709  mSpinBlurRadius->blockSignals( true );
1710  mBlurSlider->blockSignals( true );
1711  mSpinBlurRadius->setValue( mLayer->blurRadius() );
1712  mBlurSlider->setValue( mLayer->blurRadius() );
1713  mSpinBlurRadius->blockSignals( false );
1714  mBlurSlider->blockSignals( false );
1715 
1716  mSpinMaxDistance->blockSignals( true );
1717  mSpinMaxDistance->setValue( mLayer->maxDistance() );
1718  mSpinMaxDistance->blockSignals( false );
1719 
1720  mRadioUseWholeShape->blockSignals( true );
1721  mRadioUseMaxDistance->blockSignals( true );
1722  if ( mLayer->useWholeShape() )
1723  {
1724  mRadioUseWholeShape->setChecked( true );
1725  mSpinMaxDistance->setEnabled( false );
1726  mDistanceUnitWidget->setEnabled( false );
1727  }
1728  else
1729  {
1730  mRadioUseMaxDistance->setChecked( true );
1731  mSpinMaxDistance->setEnabled( true );
1732  mDistanceUnitWidget->setEnabled( true );
1733  }
1734  mRadioUseWholeShape->blockSignals( false );
1735  mRadioUseMaxDistance->blockSignals( false );
1736 
1737  mDistanceUnitWidget->blockSignals( true );
1738  mDistanceUnitWidget->setUnit( mLayer->distanceUnit() );
1739  mDistanceUnitWidget->setMapUnitScale( mLayer->distanceMapUnitScale() );
1740  mDistanceUnitWidget->blockSignals( false );
1741 
1742  mIgnoreRingsCheckBox->blockSignals( true );
1743  mIgnoreRingsCheckBox->setCheckState( mLayer->ignoreRings() ? Qt::Checked : Qt::Unchecked );
1744  mIgnoreRingsCheckBox->blockSignals( false );
1745 
1746  // set source color ramp
1747  if ( mLayer->colorRamp() )
1748  {
1749  btnColorRamp->blockSignals( true );
1750  btnColorRamp->setColorRamp( mLayer->colorRamp() );
1751  btnColorRamp->blockSignals( false );
1752  }
1753 
1754  spinOffsetX->blockSignals( true );
1755  spinOffsetX->setValue( mLayer->offset().x() );
1756  spinOffsetX->blockSignals( false );
1757  spinOffsetY->blockSignals( true );
1758  spinOffsetY->setValue( mLayer->offset().y() );
1759  spinOffsetY->blockSignals( false );
1760  mOffsetUnitWidget->blockSignals( true );
1761  mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
1762  mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
1763  mOffsetUnitWidget->blockSignals( false );
1764 
1772 }
1773 
1775 {
1776  return mLayer;
1777 }
1778 
1780 {
1781  if ( mLayer )
1782  {
1783  mLayer->setColor( color );
1784  emit changed();
1785  }
1786 }
1787 
1789 {
1790  if ( mLayer )
1791  {
1792  mLayer->setColor2( color );
1793  emit changed();
1794  }
1795 }
1796 
1797 void QgsShapeburstFillSymbolLayerWidget::colorModeChanged()
1798 {
1799  if ( !mLayer )
1800  {
1801  return;
1802  }
1803 
1804  if ( radioTwoColor->isChecked() )
1805  {
1807  }
1808  else
1809  {
1811  }
1812  emit changed();
1813 }
1814 
1815 void QgsShapeburstFillSymbolLayerWidget::mSpinBlurRadius_valueChanged( int value )
1816 {
1817  if ( mLayer )
1818  {
1819  mLayer->setBlurRadius( value );
1820  emit changed();
1821  }
1822 }
1823 
1824 void QgsShapeburstFillSymbolLayerWidget::mSpinMaxDistance_valueChanged( double value )
1825 {
1826  if ( mLayer )
1827  {
1828  mLayer->setMaxDistance( value );
1829  emit changed();
1830  }
1831 }
1832 
1833 void QgsShapeburstFillSymbolLayerWidget::mDistanceUnitWidget_changed()
1834 {
1835  if ( mLayer )
1836  {
1837  mLayer->setDistanceUnit( mDistanceUnitWidget->unit() );
1838  mLayer->setDistanceMapUnitScale( mDistanceUnitWidget->getMapUnitScale() );
1839  emit changed();
1840  }
1841 }
1842 
1843 void QgsShapeburstFillSymbolLayerWidget::mRadioUseWholeShape_toggled( bool value )
1844 {
1845  if ( mLayer )
1846  {
1847  mLayer->setUseWholeShape( value );
1848  mDistanceUnitWidget->setEnabled( !value );
1849  emit changed();
1850  }
1851 }
1852 
1853 void QgsShapeburstFillSymbolLayerWidget::applyColorRamp()
1854 {
1855  QgsColorRamp *ramp = btnColorRamp->colorRamp();
1856  if ( !ramp )
1857  return;
1858 
1859  mLayer->setColorRamp( ramp );
1860  emit changed();
1861 }
1862 
1863 void QgsShapeburstFillSymbolLayerWidget::offsetChanged()
1864 {
1865  if ( mLayer )
1866  {
1867  mLayer->setOffset( QPointF( spinOffsetX->value(), spinOffsetY->value() ) );
1868  emit changed();
1869  }
1870 }
1871 
1872 void QgsShapeburstFillSymbolLayerWidget::mOffsetUnitWidget_changed()
1873 {
1874  if ( mLayer )
1875  {
1876  mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
1877  mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
1878  emit changed();
1879  }
1880 }
1881 
1882 
1883 void QgsShapeburstFillSymbolLayerWidget::mIgnoreRingsCheckBox_stateChanged( int state )
1884 {
1885  const bool checked = ( state == Qt::Checked );
1886  mLayer->setIgnoreRings( checked );
1887  emit changed();
1888 }
1889 
1891 
1893  : QgsSymbolLayerWidget( parent, vl )
1894 {
1895  mLayer = nullptr;
1896 
1897  setupUi( this );
1898  connect( mIntervalUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsMarkerLineSymbolLayerWidget::mIntervalUnitWidget_changed );
1899  connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsMarkerLineSymbolLayerWidget::mOffsetUnitWidget_changed );
1900  connect( mOffsetAlongLineUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsMarkerLineSymbolLayerWidget::mOffsetAlongLineUnitWidget_changed );
1901  connect( mAverageAngleUnit, &QgsUnitSelectionWidget::changed, this, &QgsMarkerLineSymbolLayerWidget::averageAngleUnitChanged );
1910 
1911  mRingFilterComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "mIconAllRings.svg" ) ), tr( "All Rings" ), QgsLineSymbolLayer::AllRings );
1912  mRingFilterComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "mIconExteriorRing.svg" ) ), tr( "Exterior Ring Only" ), QgsLineSymbolLayer::ExteriorRingOnly );
1913  mRingFilterComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "mIconInteriorRings.svg" ) ), tr( "Interior Rings Only" ), QgsLineSymbolLayer::InteriorRingsOnly );
1914  connect( mRingFilterComboBox, qOverload< int >( &QComboBox::currentIndexChanged ), this, [ = ]( int )
1915  {
1916  if ( mLayer )
1917  {
1918  mLayer->setRingFilter( static_cast< QgsLineSymbolLayer::RenderRingFilter >( mRingFilterComboBox->currentData().toInt() ) );
1919  emit changed();
1920  }
1921  } );
1922 
1923  spinOffset->setClearValue( 0.0 );
1924 
1925  mSpinAverageAngleLength->setClearValue( 4.0 );
1926 
1927  connect( spinInterval, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsMarkerLineSymbolLayerWidget::setInterval );
1928  connect( mSpinOffsetAlongLine, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsMarkerLineSymbolLayerWidget::setOffsetAlongLine );
1929  connect( chkRotateMarker, &QAbstractButton::clicked, this, &QgsMarkerLineSymbolLayerWidget::setRotate );
1930  connect( spinOffset, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsMarkerLineSymbolLayerWidget::setOffset );
1931  connect( mSpinAverageAngleLength, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsMarkerLineSymbolLayerWidget::setAverageAngle );
1932  connect( mCheckInterval, &QCheckBox::toggled, this, &QgsMarkerLineSymbolLayerWidget::setPlacement );
1933  connect( mCheckVertex, &QCheckBox::toggled, this, &QgsMarkerLineSymbolLayerWidget::setPlacement );
1934  connect( mCheckVertexLast, &QCheckBox::toggled, this, &QgsMarkerLineSymbolLayerWidget::setPlacement );
1935  connect( mCheckVertexFirst, &QCheckBox::toggled, this, &QgsMarkerLineSymbolLayerWidget::setPlacement );
1936  connect( mCheckCentralPoint, &QCheckBox::toggled, this, &QgsMarkerLineSymbolLayerWidget::setPlacement );
1937  connect( mCheckCurvePoint, &QCheckBox::toggled, this, &QgsMarkerLineSymbolLayerWidget::setPlacement );
1938  connect( mCheckSegmentCentralPoint, &QCheckBox::toggled, this, &QgsMarkerLineSymbolLayerWidget::setPlacement );
1939  connect( mCheckPlaceOnEveryPart, &QCheckBox::toggled, this, [ = ]
1940  {
1941  if ( mLayer )
1942  {
1943  mLayer->setPlaceOnEveryPart( mCheckPlaceOnEveryPart->isChecked() );
1944  emit changed();
1945  }
1946  } );
1947 }
1948 
1950 {
1951  if ( layer->layerType() != QLatin1String( "MarkerLine" ) )
1952  return;
1953 
1954  // layer type is correct, we can do the cast
1955  mLayer = static_cast<QgsMarkerLineSymbolLayer *>( layer );
1956 
1957  // set values
1958  spinInterval->blockSignals( true );
1959  spinInterval->setValue( mLayer->interval() );
1960  spinInterval->blockSignals( false );
1961  mSpinOffsetAlongLine->blockSignals( true );
1962  mSpinOffsetAlongLine->setValue( mLayer->offsetAlongLine() );
1963  mSpinOffsetAlongLine->blockSignals( false );
1964  chkRotateMarker->blockSignals( true );
1965  chkRotateMarker->setChecked( mLayer->rotateSymbols() );
1966  chkRotateMarker->blockSignals( false );
1967  spinOffset->blockSignals( true );
1968  spinOffset->setValue( mLayer->offset() );
1969  spinOffset->blockSignals( false );
1970 
1971  whileBlocking( mCheckInterval )->setChecked( mLayer->placements() & Qgis::MarkerLinePlacement::Interval );
1974  whileBlocking( mCheckVertexFirst )->setChecked( mLayer->placements() & Qgis::MarkerLinePlacement::FirstVertex
1976  whileBlocking( mCheckVertexLast )->setChecked( mLayer->placements() & Qgis::MarkerLinePlacement::LastVertex
1978  whileBlocking( mCheckCentralPoint )->setChecked( mLayer->placements() & Qgis::MarkerLinePlacement::CentralPoint );
1979  whileBlocking( mCheckCurvePoint )->setChecked( mLayer->placements() & Qgis::MarkerLinePlacement::CurvePoint );
1980  whileBlocking( mCheckSegmentCentralPoint )->setChecked( mLayer->placements() & Qgis::MarkerLinePlacement::SegmentCenter );
1981  whileBlocking( mCheckPlaceOnEveryPart )->setChecked( mLayer->placeOnEveryPart() );
1982 
1983  // set units
1984  mIntervalUnitWidget->blockSignals( true );
1985  mIntervalUnitWidget->setUnit( mLayer->intervalUnit() );
1986  mIntervalUnitWidget->setMapUnitScale( mLayer->intervalMapUnitScale() );
1987  mIntervalUnitWidget->blockSignals( false );
1988  mOffsetUnitWidget->blockSignals( true );
1989  mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
1990  mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
1991  mOffsetUnitWidget->blockSignals( false );
1992  mOffsetAlongLineUnitWidget->blockSignals( true );
1993  mOffsetAlongLineUnitWidget->setUnit( mLayer->offsetAlongLineUnit() );
1994  mOffsetAlongLineUnitWidget->setMapUnitScale( mLayer->offsetAlongLineMapUnitScale() );
1995  mOffsetAlongLineUnitWidget->blockSignals( false );
1996 
1997  whileBlocking( mAverageAngleUnit )->setUnit( mLayer->averageAngleUnit() );
1998  whileBlocking( mAverageAngleUnit )->setMapUnitScale( mLayer->averageAngleMapUnitScale() );
1999  whileBlocking( mSpinAverageAngleLength )->setValue( mLayer->averageAngleLength() );
2000 
2001  whileBlocking( mRingFilterComboBox )->setCurrentIndex( mRingFilterComboBox->findData( mLayer->ringFilter() ) );
2002 
2003  setPlacement(); // update gui
2004 
2010 }
2011 
2013 {
2014  return mLayer;
2015 }
2016 
2018 {
2020 
2021  switch ( context.symbolType() )
2022  {
2025  //these settings only have an effect when the symbol layers is part of a fill symbol
2026  mRingFilterComboBox->hide();
2027  mRingsLabel->hide();
2028  break;
2029 
2032  break;
2033  }
2034 }
2035 
2037 {
2038  mLayer->setInterval( val );
2039  emit changed();
2040 }
2041 
2043 {
2044  mLayer->setOffsetAlongLine( val );
2045  emit changed();
2046 }
2047 
2048 void QgsMarkerLineSymbolLayerWidget::setRotate()
2049 {
2050  mSpinAverageAngleLength->setEnabled( chkRotateMarker->isChecked() && ( mCheckInterval->isChecked() || mCheckCentralPoint->isChecked() ) );
2051  mAverageAngleUnit->setEnabled( mSpinAverageAngleLength->isEnabled() );
2052 
2053  mLayer->setRotateSymbols( chkRotateMarker->isChecked() );
2054  emit changed();
2055 }
2056 
2057 void QgsMarkerLineSymbolLayerWidget::setOffset()
2058 {
2059  mLayer->setOffset( spinOffset->value() );
2060  emit changed();
2061 }
2062 
2063 void QgsMarkerLineSymbolLayerWidget::setPlacement()
2064 {
2065  const bool interval = mCheckInterval->isChecked();
2066  spinInterval->setEnabled( interval );
2067  mSpinOffsetAlongLine->setEnabled( mCheckInterval->isChecked() || mCheckVertexLast->isChecked() || mCheckVertexFirst->isChecked() );
2068  mOffsetAlongLineUnitWidget->setEnabled( mSpinOffsetAlongLine->isEnabled() );
2069  mSpinAverageAngleLength->setEnabled( chkRotateMarker->isChecked() && ( mCheckInterval->isChecked() || mCheckCentralPoint->isChecked() ) );
2070  mAverageAngleUnit->setEnabled( mSpinAverageAngleLength->isEnabled() );
2071 
2072  Qgis::MarkerLinePlacements placements;
2073  if ( mCheckInterval->isChecked() )
2075  if ( mCheckVertex->isChecked() )
2077  if ( mCheckVertexLast->isChecked() )
2079  if ( mCheckVertexFirst->isChecked() )
2081  if ( mCheckCurvePoint->isChecked() )
2083  if ( mCheckSegmentCentralPoint->isChecked() )
2085  if ( mCheckCentralPoint->isChecked() )
2087  mLayer->setPlacements( placements );
2088 
2089  emit changed();
2090 }
2091 
2092 void QgsMarkerLineSymbolLayerWidget::mIntervalUnitWidget_changed()
2093 {
2094  if ( mLayer )
2095  {
2096  mLayer->setIntervalUnit( mIntervalUnitWidget->unit() );
2097  mLayer->setIntervalMapUnitScale( mIntervalUnitWidget->getMapUnitScale() );
2098  emit changed();
2099  }
2100 }
2101 
2102 void QgsMarkerLineSymbolLayerWidget::mOffsetUnitWidget_changed()
2103 {
2104  if ( mLayer )
2105  {
2106  mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
2107  mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
2108  emit changed();
2109  }
2110 }
2111 
2112 void QgsMarkerLineSymbolLayerWidget::mOffsetAlongLineUnitWidget_changed()
2113 {
2114  if ( mLayer )
2115  {
2116  mLayer->setOffsetAlongLineUnit( mOffsetAlongLineUnitWidget->unit() );
2117  mLayer->setOffsetAlongLineMapUnitScale( mOffsetAlongLineUnitWidget->getMapUnitScale() );
2118  }
2119  emit changed();
2120 }
2121 
2122 void QgsMarkerLineSymbolLayerWidget::averageAngleUnitChanged()
2123 {
2124  if ( mLayer )
2125  {
2126  mLayer->setAverageAngleUnit( mAverageAngleUnit->unit() );
2127  mLayer->setAverageAngleMapUnitScale( mAverageAngleUnit->getMapUnitScale() );
2128  }
2129  emit changed();
2130 }
2131 
2132 void QgsMarkerLineSymbolLayerWidget::setAverageAngle( double val )
2133 {
2134  if ( mLayer )
2135  {
2136  mLayer->setAverageAngleLength( val );
2137  emit changed();
2138  }
2139 }
2140 
2141 
2143 
2145  : QgsSymbolLayerWidget( parent, vl )
2146 {
2147  mLayer = nullptr;
2148 
2149  setupUi( this );
2150  connect( mIntervalUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsHashedLineSymbolLayerWidget::mIntervalUnitWidget_changed );
2151  connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsHashedLineSymbolLayerWidget::mOffsetUnitWidget_changed );
2152  connect( mOffsetAlongLineUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsHashedLineSymbolLayerWidget::mOffsetAlongLineUnitWidget_changed );
2153  connect( mAverageAngleUnit, &QgsUnitSelectionWidget::changed, this, &QgsHashedLineSymbolLayerWidget::averageAngleUnitChanged );
2154  connect( mHashLengthUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsHashedLineSymbolLayerWidget::hashLengthUnitWidgetChanged );
2165 
2166  mRingFilterComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "mIconAllRings.svg" ) ), tr( "All Rings" ), QgsLineSymbolLayer::AllRings );
2167  mRingFilterComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "mIconExteriorRing.svg" ) ), tr( "Exterior Ring Only" ), QgsLineSymbolLayer::ExteriorRingOnly );
2168  mRingFilterComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "mIconInteriorRings.svg" ) ), tr( "Interior Rings Only" ), QgsLineSymbolLayer::InteriorRingsOnly );
2169  connect( mRingFilterComboBox, qOverload< int >( &QComboBox::currentIndexChanged ), this, [ = ]( int )
2170  {
2171  if ( mLayer )
2172  {
2173  mLayer->setRingFilter( static_cast< QgsLineSymbolLayer::RenderRingFilter >( mRingFilterComboBox->currentData().toInt() ) );
2174  emit changed();
2175  }
2176  } );
2177 
2178  spinOffset->setClearValue( 0.0 );
2179 
2180  mHashRotationSpinBox->setClearValue( 0 );
2181  mSpinAverageAngleLength->setClearValue( 4.0 );
2182 
2183  connect( spinInterval, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsHashedLineSymbolLayerWidget::setInterval );
2184  connect( mSpinOffsetAlongLine, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsHashedLineSymbolLayerWidget::setOffsetAlongLine );
2185  connect( mSpinHashLength, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsHashedLineSymbolLayerWidget::setHashLength );
2186  connect( mHashRotationSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsHashedLineSymbolLayerWidget::setHashAngle );
2187  connect( chkRotateMarker, &QAbstractButton::clicked, this, &QgsHashedLineSymbolLayerWidget::setRotate );
2188  connect( spinOffset, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsHashedLineSymbolLayerWidget::setOffset );
2189  connect( mSpinAverageAngleLength, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsHashedLineSymbolLayerWidget::setAverageAngle );
2190 
2191  connect( mCheckInterval, &QCheckBox::toggled, this, &QgsHashedLineSymbolLayerWidget::setPlacement );
2192  connect( mCheckVertex, &QCheckBox::toggled, this, &QgsHashedLineSymbolLayerWidget::setPlacement );
2193  connect( mCheckVertexLast, &QCheckBox::toggled, this, &QgsHashedLineSymbolLayerWidget::setPlacement );
2194  connect( mCheckVertexFirst, &QCheckBox::toggled, this, &QgsHashedLineSymbolLayerWidget::setPlacement );
2195  connect( mCheckCentralPoint, &QCheckBox::toggled, this, &QgsHashedLineSymbolLayerWidget::setPlacement );
2196  connect( mCheckCurvePoint, &QCheckBox::toggled, this, &QgsHashedLineSymbolLayerWidget::setPlacement );
2197  connect( mCheckSegmentCentralPoint, &QCheckBox::toggled, this, &QgsHashedLineSymbolLayerWidget::setPlacement );
2198 
2199  connect( mCheckPlaceOnEveryPart, &QCheckBox::toggled, this, [ = ]
2200  {
2201  if ( mLayer )
2202  {
2203  mLayer->setPlaceOnEveryPart( mCheckPlaceOnEveryPart->isChecked() );
2204  emit changed();
2205  }
2206  } );
2207 }
2208 
2210 {
2211  if ( layer->layerType() != QLatin1String( "HashLine" ) )
2212  return;
2213 
2214  // layer type is correct, we can do the cast
2215  mLayer = static_cast<QgsHashedLineSymbolLayer *>( layer );
2216 
2217  // set values
2218  spinInterval->blockSignals( true );
2219  spinInterval->setValue( mLayer->interval() );
2220  spinInterval->blockSignals( false );
2221  mSpinOffsetAlongLine->blockSignals( true );
2222  mSpinOffsetAlongLine->setValue( mLayer->offsetAlongLine() );
2223  mSpinOffsetAlongLine->blockSignals( false );
2224  whileBlocking( mSpinHashLength )->setValue( mLayer->hashLength() );
2225  whileBlocking( mHashRotationSpinBox )->setValue( mLayer->hashAngle() );
2226  chkRotateMarker->blockSignals( true );
2227  chkRotateMarker->setChecked( mLayer->rotateSymbols() );
2228  chkRotateMarker->blockSignals( false );
2229  spinOffset->blockSignals( true );
2230  spinOffset->setValue( mLayer->offset() );
2231  spinOffset->blockSignals( false );
2232 
2233  whileBlocking( mCheckInterval )->setChecked( mLayer->placements() & Qgis::MarkerLinePlacement::Interval );
2234  whileBlocking( mCheckVertex )->setChecked( mLayer->placements() & Qgis::MarkerLinePlacement::InnerVertices
2236  whileBlocking( mCheckVertexFirst )->setChecked( mLayer->placements() & Qgis::MarkerLinePlacement::FirstVertex
2238  whileBlocking( mCheckVertexLast )->setChecked( mLayer->placements() & Qgis::MarkerLinePlacement::LastVertex
2240  whileBlocking( mCheckCentralPoint )->setChecked( mLayer->placements() & Qgis::MarkerLinePlacement::CentralPoint );
2241  whileBlocking( mCheckCurvePoint )->setChecked( mLayer->placements() & Qgis::MarkerLinePlacement::CurvePoint );
2242  whileBlocking( mCheckSegmentCentralPoint )->setChecked( mLayer->placements() & Qgis::MarkerLinePlacement::SegmentCenter );
2243  whileBlocking( mCheckPlaceOnEveryPart )->setChecked( mLayer->placeOnEveryPart() );
2244 
2245  // set units
2246  mIntervalUnitWidget->blockSignals( true );
2247  mIntervalUnitWidget->setUnit( mLayer->intervalUnit() );
2248  mIntervalUnitWidget->setMapUnitScale( mLayer->intervalMapUnitScale() );
2249  mIntervalUnitWidget->blockSignals( false );
2250  mOffsetUnitWidget->blockSignals( true );
2251  mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
2252  mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
2253  mOffsetUnitWidget->blockSignals( false );
2254  mOffsetAlongLineUnitWidget->blockSignals( true );
2255  mOffsetAlongLineUnitWidget->setUnit( mLayer->offsetAlongLineUnit() );
2256  mOffsetAlongLineUnitWidget->setMapUnitScale( mLayer->offsetAlongLineMapUnitScale() );
2257  mOffsetAlongLineUnitWidget->blockSignals( false );
2258  whileBlocking( mAverageAngleUnit )->setUnit( mLayer->averageAngleUnit() );
2259  whileBlocking( mAverageAngleUnit )->setMapUnitScale( mLayer->averageAngleMapUnitScale() );
2260  whileBlocking( mSpinAverageAngleLength )->setValue( mLayer->averageAngleLength() );
2261  whileBlocking( mHashLengthUnitWidget )->setUnit( mLayer->hashLengthUnit() );
2262  whileBlocking( mHashLengthUnitWidget )->setMapUnitScale( mLayer->hashLengthMapUnitScale() );
2263 
2264  whileBlocking( mRingFilterComboBox )->setCurrentIndex( mRingFilterComboBox->findData( mLayer->ringFilter() ) );
2265 
2266  setPlacement(); // update gui
2267 
2275 }
2276 
2278 {
2279  return mLayer;
2280 }
2281 
2283 {
2285 
2286  switch ( context.symbolType() )
2287  {
2290  //these settings only have an effect when the symbol layers is part of a fill symbol
2291  mRingFilterComboBox->hide();
2292  mRingsLabel->hide();
2293  break;
2294 
2297  break;
2298  }
2299 }
2300 
2301 void QgsHashedLineSymbolLayerWidget::setInterval( double val )
2302 {
2303  mLayer->setInterval( val );
2304  emit changed();
2305 }
2306 
2307 void QgsHashedLineSymbolLayerWidget::setOffsetAlongLine( double val )
2308 {
2309  mLayer->setOffsetAlongLine( val );
2310  emit changed();
2311 }
2312 
2313 void QgsHashedLineSymbolLayerWidget::setHashLength( double val )
2314 {
2315  mLayer->setHashLength( val );
2316  emit changed();
2317 }
2318 
2319 void QgsHashedLineSymbolLayerWidget::setHashAngle( double val )
2320 {
2321  mLayer->setHashAngle( val );
2322  emit changed();
2323 }
2324 
2325 void QgsHashedLineSymbolLayerWidget::setRotate()
2326 {
2327  mSpinAverageAngleLength->setEnabled( chkRotateMarker->isChecked() && ( mCheckInterval->isChecked() || mCheckCentralPoint->isChecked() ) );
2328  mAverageAngleUnit->setEnabled( mSpinAverageAngleLength->isEnabled() );
2329 
2330  mLayer->setRotateSymbols( chkRotateMarker->isChecked() );
2331  emit changed();
2332 }
2333 
2334 void QgsHashedLineSymbolLayerWidget::setOffset()
2335 {
2336  mLayer->setOffset( spinOffset->value() );
2337  emit changed();
2338 }
2339 
2340 void QgsHashedLineSymbolLayerWidget::setPlacement()
2341 {
2342  const bool interval = mCheckInterval->isChecked();
2343  spinInterval->setEnabled( interval );
2344  mSpinOffsetAlongLine->setEnabled( mCheckInterval->isChecked() || mCheckVertexLast->isChecked() || mCheckVertexFirst->isChecked() );
2345  mOffsetAlongLineUnitWidget->setEnabled( mSpinOffsetAlongLine->isEnabled() );
2346  mSpinAverageAngleLength->setEnabled( chkRotateMarker->isChecked() && ( mCheckInterval->isChecked() || mCheckCentralPoint->isChecked() ) );
2347  mAverageAngleUnit->setEnabled( mSpinAverageAngleLength->isEnabled() );
2348 
2349  Qgis::MarkerLinePlacements placements;
2350  if ( mCheckInterval->isChecked() )
2352  if ( mCheckVertex->isChecked() )
2354  if ( mCheckVertexLast->isChecked() )
2356  if ( mCheckVertexFirst->isChecked() )
2358  if ( mCheckCurvePoint->isChecked() )
2360  if ( mCheckSegmentCentralPoint->isChecked() )
2362  if ( mCheckCentralPoint->isChecked() )
2364  mLayer->setPlacements( placements );
2365 
2366  emit changed();
2367 }
2368 
2369 void QgsHashedLineSymbolLayerWidget::mIntervalUnitWidget_changed()
2370 {
2371  if ( mLayer )
2372  {
2373  mLayer->setIntervalUnit( mIntervalUnitWidget->unit() );
2374  mLayer->setIntervalMapUnitScale( mIntervalUnitWidget->getMapUnitScale() );
2375  emit changed();
2376  }
2377 }
2378 
2379 void QgsHashedLineSymbolLayerWidget::mOffsetUnitWidget_changed()
2380 {
2381  if ( mLayer )
2382  {
2383  mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
2384  mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
2385  emit changed();
2386  }
2387 }
2388 
2389 void QgsHashedLineSymbolLayerWidget::mOffsetAlongLineUnitWidget_changed()
2390 {
2391  if ( mLayer )
2392  {
2393  mLayer->setOffsetAlongLineUnit( mOffsetAlongLineUnitWidget->unit() );
2394  mLayer->setOffsetAlongLineMapUnitScale( mOffsetAlongLineUnitWidget->getMapUnitScale() );
2395  }
2396  emit changed();
2397 }
2398 
2399 void QgsHashedLineSymbolLayerWidget::hashLengthUnitWidgetChanged()
2400 {
2401  if ( mLayer )
2402  {
2403  mLayer->setHashLengthUnit( mHashLengthUnitWidget->unit() );
2404  mLayer->setHashLengthMapUnitScale( mHashLengthUnitWidget->getMapUnitScale() );
2405  }
2406  emit changed();
2407 }
2408 
2409 void QgsHashedLineSymbolLayerWidget::averageAngleUnitChanged()
2410 {
2411  if ( mLayer )
2412  {
2413  mLayer->setAverageAngleUnit( mAverageAngleUnit->unit() );
2414  mLayer->setAverageAngleMapUnitScale( mAverageAngleUnit->getMapUnitScale() );
2415  }
2416  emit changed();
2417 }
2418 
2419 void QgsHashedLineSymbolLayerWidget::setAverageAngle( double val )
2420 {
2421  if ( mLayer )
2422  {
2423  mLayer->setAverageAngleLength( val );
2424  emit changed();
2425  }
2426 }
2427 
2429 
2430 
2432  : QgsSymbolLayerWidget( parent, vl )
2433 {
2434  mLayer = nullptr;
2435 
2436  setupUi( this );
2437 
2438  mSvgSelectorWidget->setAllowParameters( true );
2439  mSvgSelectorWidget->sourceLineEdit()->setPropertyOverrideToolButtonVisible( true );
2440  mSvgSelectorWidget->sourceLineEdit()->setLastPathSettingsKey( QStringLiteral( "/UI/lastSVGMarkerDir" ) );
2441  mSvgSelectorWidget->initParametersModel( this, vl );
2442 
2443  connect( mSvgSelectorWidget->sourceLineEdit(), &QgsSvgSourceLineEdit::sourceChanged, this, &QgsSvgMarkerSymbolLayerWidget::svgSourceChanged );
2444  connect( mChangeColorButton, &QgsColorButton::colorChanged, this, &QgsSvgMarkerSymbolLayerWidget::mChangeColorButton_colorChanged );
2445  connect( mChangeStrokeColorButton, &QgsColorButton::colorChanged, this, &QgsSvgMarkerSymbolLayerWidget::mChangeStrokeColorButton_colorChanged );
2446  connect( mStrokeWidthSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsSvgMarkerSymbolLayerWidget::mStrokeWidthSpinBox_valueChanged );
2447  connect( mSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSvgMarkerSymbolLayerWidget::mSizeUnitWidget_changed );
2448  connect( mStrokeWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSvgMarkerSymbolLayerWidget::mStrokeWidthUnitWidget_changed );
2449  connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSvgMarkerSymbolLayerWidget::mOffsetUnitWidget_changed );
2450  connect( mHorizontalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSvgMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged );
2451  connect( mVerticalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSvgMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged );
2458  mChangeColorButton->setAllowOpacity( true );
2459  mChangeColorButton->setColorDialogTitle( tr( "Select Fill color" ) );
2460  mChangeColorButton->setContext( QStringLiteral( "symbology" ) );
2461  mChangeStrokeColorButton->setAllowOpacity( true );
2462  mChangeStrokeColorButton->setColorDialogTitle( tr( "Select Stroke Color" ) );
2463  mChangeStrokeColorButton->setContext( QStringLiteral( "symbology" ) );
2464 
2465  mFillColorDDBtn->registerLinkedWidget( mChangeColorButton );
2466  mStrokeColorDDBtn->registerLinkedWidget( mChangeStrokeColorButton );
2467 
2468  spinOffsetX->setClearValue( 0.0 );
2469  spinOffsetY->setClearValue( 0.0 );
2470  spinAngle->setClearValue( 0.0 );
2471 
2472  connect( spinWidth, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsSvgMarkerSymbolLayerWidget::setWidth );
2473  connect( spinHeight, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsSvgMarkerSymbolLayerWidget::setHeight );
2474  connect( mLockAspectRatio, static_cast < void ( QgsRatioLockButton::* )( bool ) > ( &QgsRatioLockButton::lockChanged ), this, &QgsSvgMarkerSymbolLayerWidget::lockAspectRatioChanged );
2475  connect( spinAngle, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsSvgMarkerSymbolLayerWidget::setAngle );
2476  connect( spinOffsetX, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsSvgMarkerSymbolLayerWidget::setOffset );
2477  connect( spinOffsetY, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsSvgMarkerSymbolLayerWidget::setOffset );
2478  connect( this, &QgsSymbolLayerWidget::changed, this, &QgsSvgMarkerSymbolLayerWidget::updateAssistantSymbol );
2479 
2480  connect( mSvgSelectorWidget, &QgsSvgSelectorWidget::svgSelected, this, &QgsSvgMarkerSymbolLayerWidget::setSvgPath );
2482 
2483  //make a temporary symbol for the size assistant preview
2484  mAssistantPreviewSymbol.reset( new QgsMarkerSymbol() );
2485 
2486  if ( vectorLayer() )
2487  {
2488  mWidthDDBtn->setSymbol( mAssistantPreviewSymbol );
2489  mHeightDDBtn->setSymbol( mAssistantPreviewSymbol );
2490  }
2491 }
2492 
2494 
2495 #include <QTime>
2496 #include <QAbstractListModel>
2497 #include <QPixmapCache>
2498 #include <QStyle>
2499 
2500 
2501 
2502 
2503 void QgsSvgMarkerSymbolLayerWidget::setGuiForSvg( const QgsSvgMarkerSymbolLayer *layer, bool skipDefaultColors )
2504 {
2505  if ( !layer )
2506  {
2507  return;
2508  }
2509 
2510  //activate gui for svg parameters only if supported by the svg file
2511  bool hasFillParam, hasFillOpacityParam, hasStrokeParam, hasStrokeWidthParam, hasStrokeOpacityParam;
2512  QColor defaultFill, defaultStroke;
2513  double defaultStrokeWidth, defaultFillOpacity, defaultStrokeOpacity;
2514  bool hasDefaultFillColor, hasDefaultFillOpacity, hasDefaultStrokeColor, hasDefaultStrokeWidth, hasDefaultStrokeOpacity;
2515  QgsApplication::svgCache()->containsParams( layer->path(), hasFillParam, hasDefaultFillColor, defaultFill,
2516  hasFillOpacityParam, hasDefaultFillOpacity, defaultFillOpacity,
2517  hasStrokeParam, hasDefaultStrokeColor, defaultStroke,
2518  hasStrokeWidthParam, hasDefaultStrokeWidth, defaultStrokeWidth,
2519  hasStrokeOpacityParam, hasDefaultStrokeOpacity, defaultStrokeOpacity );
2520  mChangeColorButton->setEnabled( hasFillParam );
2521  mChangeColorButton->setAllowOpacity( hasFillOpacityParam );
2522  mChangeStrokeColorButton->setEnabled( hasStrokeParam );
2523  mChangeStrokeColorButton->setAllowOpacity( hasStrokeOpacityParam );
2524  mStrokeWidthSpinBox->setEnabled( hasStrokeWidthParam );
2525 
2526  if ( hasFillParam )
2527  {
2528  QColor fill = layer->fillColor();
2529  const double existingOpacity = hasFillOpacityParam ? fill.alphaF() : 1.0;
2530  if ( hasDefaultFillColor && !skipDefaultColors )
2531  {
2532  fill = defaultFill;
2533  }
2534  fill.setAlphaF( hasDefaultFillOpacity ? defaultFillOpacity : existingOpacity );
2535  mChangeColorButton->setColor( fill );
2536  }
2537  if ( hasStrokeParam )
2538  {
2539  QColor stroke = layer->strokeColor();
2540  const double existingOpacity = hasStrokeOpacityParam ? stroke.alphaF() : 1.0;
2541  if ( hasDefaultStrokeColor && !skipDefaultColors )
2542  {
2543  stroke = defaultStroke;
2544  }
2545  stroke.setAlphaF( hasDefaultStrokeOpacity ? defaultStrokeOpacity : existingOpacity );
2546  mChangeStrokeColorButton->setColor( stroke );
2547  }
2548 
2549  whileBlocking( mSvgSelectorWidget->sourceLineEdit() )->setSource( layer->path() );
2550 
2551  mStrokeWidthSpinBox->blockSignals( true );
2552  mStrokeWidthSpinBox->setValue( hasDefaultStrokeWidth ? defaultStrokeWidth : layer->strokeWidth() );
2553  mStrokeWidthSpinBox->blockSignals( false );
2554 
2555  const bool preservedAspectRatio = layer->preservedAspectRatio();
2556  spinHeight->blockSignals( true );
2557  if ( preservedAspectRatio )
2558  {
2559  spinHeight->setValue( layer->size() * layer->defaultAspectRatio() );
2560  }
2561  else
2562  {
2563  spinHeight->setValue( layer->size() * layer->fixedAspectRatio() );
2564  }
2565  spinHeight->setEnabled( layer->defaultAspectRatio() > 0.0 );
2566  spinHeight->blockSignals( false );
2567  whileBlocking( mLockAspectRatio )->setLocked( preservedAspectRatio );
2568 }
2569 
2570 void QgsSvgMarkerSymbolLayerWidget::updateAssistantSymbol()
2571 {
2572  for ( int i = mAssistantPreviewSymbol->symbolLayerCount() - 1 ; i >= 0; --i )
2573  {
2574  mAssistantPreviewSymbol->deleteSymbolLayer( i );
2575  }
2576  mAssistantPreviewSymbol->appendSymbolLayer( mLayer->clone() );
2578  if ( ddSize )
2579  mAssistantPreviewSymbol->setDataDefinedSize( ddSize );
2580 }
2581 
2582 
2584 {
2585  if ( !layer )
2586  {
2587  return;
2588  }
2589 
2590  if ( layer->layerType() != QLatin1String( "SvgMarker" ) )
2591  return;
2592 
2593  // layer type is correct, we can do the cast
2594  mLayer = static_cast<QgsSvgMarkerSymbolLayer *>( layer );
2595 
2596  // set values
2597  mSvgSelectorWidget->setSvgPath( mLayer->path() );
2598  mSvgSelectorWidget->setSvgParameters( mLayer->parameters() );
2599 
2600  spinWidth->blockSignals( true );
2601  spinWidth->setValue( mLayer->size() );
2602  spinWidth->blockSignals( false );
2603  spinAngle->blockSignals( true );
2604  spinAngle->setValue( mLayer->angle() );
2605  spinAngle->blockSignals( false );
2606 
2607  // without blocking signals the value gets changed because of slot setOffset()
2608  spinOffsetX->blockSignals( true );
2609  spinOffsetX->setValue( mLayer->offset().x() );
2610  spinOffsetX->blockSignals( false );
2611  spinOffsetY->blockSignals( true );
2612  spinOffsetY->setValue( mLayer->offset().y() );
2613  spinOffsetY->blockSignals( false );
2614 
2615  mSizeUnitWidget->blockSignals( true );
2616  mSizeUnitWidget->setUnit( mLayer->sizeUnit() );
2617  mSizeUnitWidget->setMapUnitScale( mLayer->sizeMapUnitScale() );
2618  mSizeUnitWidget->blockSignals( false );
2619  mStrokeWidthUnitWidget->blockSignals( true );
2620  mStrokeWidthUnitWidget->setUnit( mLayer->strokeWidthUnit() );
2621  mStrokeWidthUnitWidget->setMapUnitScale( mLayer->strokeWidthMapUnitScale() );
2622  mStrokeWidthUnitWidget->blockSignals( false );
2623  mOffsetUnitWidget->blockSignals( true );
2624  mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
2625  mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
2626  mOffsetUnitWidget->blockSignals( false );
2627 
2628  //anchor points
2629  mHorizontalAnchorComboBox->blockSignals( true );
2630  mVerticalAnchorComboBox->blockSignals( true );
2631  mHorizontalAnchorComboBox->setCurrentIndex( mLayer->horizontalAnchorPoint() );
2632  mVerticalAnchorComboBox->setCurrentIndex( mLayer->verticalAnchorPoint() );
2633  mHorizontalAnchorComboBox->blockSignals( false );
2634  mVerticalAnchorComboBox->blockSignals( false );
2635 
2636  setGuiForSvg( mLayer, true );
2637 
2647 
2648  registerDataDefinedButton( mSvgSelectorWidget->sourceLineEdit()->propertyOverrideToolButton(), QgsSymbolLayer::PropertyName );
2649 
2650  updateAssistantSymbol();
2651 }
2652 
2654 {
2655  return mLayer;
2656 }
2657 
2659 {
2661  mSvgSelectorWidget->sourceLineEdit()->setMessageBar( context.messageBar() );
2662 }
2663 
2665 {
2666  mLayer->setPath( name );
2667  whileBlocking( mSvgSelectorWidget->sourceLineEdit() )->setSource( name );
2668 
2669  setGuiForSvg( mLayer );
2670  emit changed();
2671 }
2672 
2673 void QgsSvgMarkerSymbolLayerWidget::setSvgParameters( const QMap<QString, QgsProperty> &parameters )
2674 {
2675  mLayer->setParameters( parameters );
2676  whileBlocking( mSvgSelectorWidget )->setSvgParameters( parameters );
2677 
2678  setGuiForSvg( mLayer );
2679  emit changed();
2680 }
2681 
2682 void QgsSvgMarkerSymbolLayerWidget::setWidth()
2683 {
2684  const double defaultAspectRatio = mLayer->defaultAspectRatio();
2685  double fixedAspectRatio = 0.0;
2686  spinHeight->blockSignals( true );
2687  if ( defaultAspectRatio <= 0.0 )
2688  {
2689  spinHeight->setValue( spinWidth->value() );
2690  }
2691  else if ( mLockAspectRatio->locked() )
2692  {
2693  spinHeight->setValue( spinWidth->value() * defaultAspectRatio );
2694  }
2695  else
2696  {
2697  fixedAspectRatio = spinHeight->value() / spinWidth->value();
2698  }
2699  spinHeight->blockSignals( false );
2700  mLayer->setSize( spinWidth->value() );
2701  mLayer->setFixedAspectRatio( fixedAspectRatio );
2702  emit changed();
2703 }
2704 
2705 void QgsSvgMarkerSymbolLayerWidget::setHeight()
2706 {
2707  const double defaultAspectRatio = mLayer->defaultAspectRatio();
2708  double fixedAspectRatio = 0.0;
2709  spinWidth->blockSignals( true );
2710  if ( defaultAspectRatio <= 0.0 )
2711  {
2712  spinWidth->setValue( spinHeight->value() );
2713  }
2714  else if ( mLockAspectRatio->locked() )
2715  {
2716  spinWidth->setValue( spinHeight->value() / defaultAspectRatio );
2717  }
2718  else
2719  {
2720  fixedAspectRatio = spinHeight->value() / spinWidth->value();
2721  }
2722  spinWidth->blockSignals( false );
2723  mLayer->setSize( spinWidth->value() );
2724  mLayer->setFixedAspectRatio( fixedAspectRatio );
2725  emit changed();
2726 }
2727 
2728 void QgsSvgMarkerSymbolLayerWidget::lockAspectRatioChanged( const bool locked )
2729 {
2730  //spinHeight->setEnabled( !locked );
2731  const double defaultAspectRatio = mLayer->defaultAspectRatio();
2732  if ( defaultAspectRatio <= 0.0 )
2733  {
2734  whileBlocking( mLockAspectRatio )->setLocked( true );
2735  }
2736  else if ( locked )
2737  {
2738  mLayer->setFixedAspectRatio( 0.0 );
2739  setWidth();
2740  }
2741  else
2742  {
2743  mLayer->setFixedAspectRatio( spinHeight->value() / spinWidth->value() );
2744  }
2745  //emit changed();
2746 }
2747 
2748 void QgsSvgMarkerSymbolLayerWidget::setAngle()
2749 {
2750  mLayer->setAngle( spinAngle->value() );
2751  emit changed();
2752 }
2753 
2754 void QgsSvgMarkerSymbolLayerWidget::setOffset()
2755 {
2756  mLayer->setOffset( QPointF( spinOffsetX->value(), spinOffsetY->value() ) );
2757  emit changed();
2758 }
2759 
2760 void QgsSvgMarkerSymbolLayerWidget::svgSourceChanged( const QString &text )
2761 {
2762  mLayer->setPath( text );
2763  setGuiForSvg( mLayer );
2764  emit changed();
2765 }
2766 
2767 void QgsSvgMarkerSymbolLayerWidget::mChangeColorButton_colorChanged( const QColor &color )
2768 {
2769  if ( !mLayer )
2770  {
2771  return;
2772  }
2773 
2774  mLayer->setFillColor( color );
2775  emit changed();
2776 }
2777 
2778 void QgsSvgMarkerSymbolLayerWidget::mChangeStrokeColorButton_colorChanged( const QColor &color )
2779 {
2780  if ( !mLayer )
2781  {
2782  return;
2783  }
2784 
2785  mLayer->setStrokeColor( color );
2786  emit changed();
2787 }
2788 
2789 void QgsSvgMarkerSymbolLayerWidget::mStrokeWidthSpinBox_valueChanged( double d )
2790 {
2791  if ( mLayer )
2792  {
2793  mLayer->setStrokeWidth( d );
2794  emit changed();
2795  }
2796 }
2797 
2798 void QgsSvgMarkerSymbolLayerWidget::mSizeUnitWidget_changed()
2799 {
2800  if ( mLayer )
2801  {
2802  mLayer->setSizeUnit( mSizeUnitWidget->unit() );
2803  mLayer->setSizeMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
2804  emit changed();
2805  }
2806 }
2807 
2808 void QgsSvgMarkerSymbolLayerWidget::mStrokeWidthUnitWidget_changed()
2809 {
2810  if ( mLayer )
2811  {
2812  mLayer->setStrokeWidthUnit( mStrokeWidthUnitWidget->unit() );
2813  mLayer->setStrokeWidthMapUnitScale( mStrokeWidthUnitWidget->getMapUnitScale() );
2814  emit changed();
2815  }
2816 }
2817 
2818 void QgsSvgMarkerSymbolLayerWidget::mOffsetUnitWidget_changed()
2819 {
2820  if ( mLayer )
2821  {
2822  mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
2823  mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
2824  emit changed();
2825  }
2826 }
2827 
2828 void QgsSvgMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged( int index )
2829 {
2830  if ( mLayer )
2831  {
2833  emit changed();
2834  }
2835 }
2836 
2837 void QgsSvgMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged( int index )
2838 {
2839  if ( mLayer )
2840  {
2842  emit changed();
2843  }
2844 }
2845 
2847 
2849 {
2850  mLayer = nullptr;
2851  setupUi( this );
2852 
2853  mSvgSelectorWidget->setAllowParameters( true );
2854  mSvgSelectorWidget->sourceLineEdit()->setPropertyOverrideToolButtonVisible( true );
2855 
2856  connect( mTextureWidthSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsSVGFillSymbolLayerWidget::mTextureWidthSpinBox_valueChanged );
2857  connect( mSvgSelectorWidget->sourceLineEdit(), &QgsSvgSourceLineEdit::sourceChanged, this, &QgsSVGFillSymbolLayerWidget::svgSourceChanged );
2858  connect( mRotationSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsSVGFillSymbolLayerWidget::mRotationSpinBox_valueChanged );
2859  connect( mChangeColorButton, &QgsColorButton::colorChanged, this, &QgsSVGFillSymbolLayerWidget::mChangeColorButton_colorChanged );
2860  connect( mChangeStrokeColorButton, &QgsColorButton::colorChanged, this, &QgsSVGFillSymbolLayerWidget::mChangeStrokeColorButton_colorChanged );
2861  connect( mStrokeWidthSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsSVGFillSymbolLayerWidget::mStrokeWidthSpinBox_valueChanged );
2862  connect( mTextureWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSVGFillSymbolLayerWidget::mTextureWidthUnitWidget_changed );
2863  connect( mSvgStrokeWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSVGFillSymbolLayerWidget::mSvgStrokeWidthUnitWidget_changed );
2868 
2869  mRotationSpinBox->setClearValue( 0.0 );
2870 
2871  mChangeColorButton->setColorDialogTitle( tr( "Select Fill Color" ) );
2872  mChangeColorButton->setContext( QStringLiteral( "symbology" ) );
2873  mChangeStrokeColorButton->setColorDialogTitle( tr( "Select Stroke Color" ) );
2874  mChangeStrokeColorButton->setContext( QStringLiteral( "symbology" ) );
2875 
2876  mFilColorDDBtn->registerLinkedWidget( mChangeColorButton );
2877  mStrokeColorDDBtn->registerLinkedWidget( mChangeStrokeColorButton );
2878 
2879  connect( mSvgSelectorWidget, &QgsSvgSelectorWidget::svgSelected, this, &QgsSVGFillSymbolLayerWidget::setFile );
2880  connect( mSvgSelectorWidget, &QgsSvgSelectorWidget::svgParametersChanged, this, &QgsSVGFillSymbolLayerWidget::setSvgParameters );
2881 }
2882 
2884 {
2885  if ( !layer )
2886  {
2887  return;
2888  }
2889 
2890  if ( layer->layerType() != QLatin1String( "SVGFill" ) )
2891  {
2892  return;
2893  }
2894 
2895  mLayer = dynamic_cast<QgsSVGFillSymbolLayer *>( layer );
2896  if ( mLayer )
2897  {
2898  const double width = mLayer->patternWidth();
2899  mTextureWidthSpinBox->blockSignals( true );
2900  mTextureWidthSpinBox->setValue( width );
2901  mTextureWidthSpinBox->blockSignals( false );
2902  whileBlocking( mSvgSelectorWidget->sourceLineEdit() )->setSource( mLayer->svgFilePath() );
2903  mRotationSpinBox->blockSignals( true );
2904  mRotationSpinBox->setValue( mLayer->angle() );
2905  mRotationSpinBox->blockSignals( false );
2906  mTextureWidthUnitWidget->blockSignals( true );
2907  mTextureWidthUnitWidget->setUnit( mLayer->patternWidthUnit() );
2908  mTextureWidthUnitWidget->setMapUnitScale( mLayer->patternWidthMapUnitScale() );
2909  mTextureWidthUnitWidget->blockSignals( false );
2910  mSvgStrokeWidthUnitWidget->blockSignals( true );
2911  mSvgStrokeWidthUnitWidget->setUnit( mLayer->svgStrokeWidthUnit() );
2912  mSvgStrokeWidthUnitWidget->setMapUnitScale( mLayer->svgStrokeWidthMapUnitScale() );
2913  mSvgStrokeWidthUnitWidget->blockSignals( false );
2914  mChangeColorButton->blockSignals( true );
2915  mChangeColorButton->setColor( mLayer->svgFillColor() );
2916  mChangeColorButton->blockSignals( false );
2917  mChangeStrokeColorButton->blockSignals( true );
2918  mChangeStrokeColorButton->setColor( mLayer->svgStrokeColor() );
2919  mChangeStrokeColorButton->blockSignals( false );
2920  mStrokeWidthSpinBox->blockSignals( true );
2921  mStrokeWidthSpinBox->setValue( mLayer->svgStrokeWidth() );
2922  mStrokeWidthSpinBox->blockSignals( false );
2923  }
2924  updateParamGui( false );
2925 
2931 
2932  registerDataDefinedButton( mSvgSelectorWidget->sourceLineEdit()->propertyOverrideToolButton(), QgsSymbolLayer::PropertyFile );
2933 }
2934 
2936 {
2937  return mLayer;
2938 }
2939 
2941 {
2943  mSvgSelectorWidget->sourceLineEdit()->setMessageBar( context.messageBar() );
2944 }
2945 
2946 void QgsSVGFillSymbolLayerWidget::mTextureWidthSpinBox_valueChanged( double d )
2947 {
2948  if ( mLayer )
2949  {
2950  mLayer->setPatternWidth( d );
2951  emit changed();
2952  }
2953 }
2954 
2955 void QgsSVGFillSymbolLayerWidget::svgSourceChanged( const QString &text )
2956 {
2957  if ( !mLayer )
2958  {
2959  return;
2960  }
2961 
2962  mLayer->setSvgFilePath( text );
2963  updateParamGui();
2964  emit changed();
2965 }
2966 
2967 void QgsSVGFillSymbolLayerWidget::setFile( const QString &name )
2968 {
2969  mLayer->setSvgFilePath( name );
2970  whileBlocking( mSvgSelectorWidget->sourceLineEdit() )->setSource( name );
2971 
2972  updateParamGui();
2973  emit changed();
2974 }
2975 
2976 void QgsSVGFillSymbolLayerWidget::setSvgParameters( const QMap<QString, QgsProperty> &parameters )
2977 {
2978  mLayer->setParameters( parameters );
2979  whileBlocking( mSvgSelectorWidget )->setSvgParameters( parameters );
2980 
2981  updateParamGui();
2982  emit changed();
2983 }
2984 
2985 
2986 void QgsSVGFillSymbolLayerWidget::mRotationSpinBox_valueChanged( double d )
2987 {
2988  if ( mLayer )
2989  {
2990  mLayer->setAngle( d );
2991  emit changed();
2992  }
2993 }
2994 
2996 {
2997  //activate gui for svg parameters only if supported by the svg file
2998  bool hasFillParam, hasFillOpacityParam, hasStrokeParam, hasStrokeWidthParam, hasStrokeOpacityParam;
2999  QColor defaultFill, defaultStroke;
3000  double defaultStrokeWidth, defaultFillOpacity, defaultStrokeOpacity;
3001  bool hasDefaultFillColor, hasDefaultFillOpacity, hasDefaultStrokeColor, hasDefaultStrokeWidth, hasDefaultStrokeOpacity;
3002  QgsApplication::svgCache()->containsParams( mSvgSelectorWidget->sourceLineEdit()->source(), hasFillParam, hasDefaultFillColor, defaultFill,
3003  hasFillOpacityParam, hasDefaultFillOpacity, defaultFillOpacity,
3004  hasStrokeParam, hasDefaultStrokeColor, defaultStroke,
3005  hasStrokeWidthParam, hasDefaultStrokeWidth, defaultStrokeWidth,
3006  hasStrokeOpacityParam, hasDefaultStrokeOpacity, defaultStrokeOpacity );
3007  if ( resetValues )
3008  {
3009  QColor fill = mChangeColorButton->color();
3010  const double newOpacity = hasFillOpacityParam ? fill.alphaF() : 1.0;
3011  if ( hasDefaultFillColor )
3012  {
3013  fill = defaultFill;
3014  }
3015  fill.setAlphaF( hasDefaultFillOpacity ? defaultFillOpacity : newOpacity );
3016  mChangeColorButton->setColor( fill );
3017  }
3018  mChangeColorButton->setEnabled( hasFillParam );
3019  mChangeColorButton->setAllowOpacity( hasFillOpacityParam );
3020  if ( resetValues )
3021  {
3022  QColor stroke = mChangeStrokeColorButton->color();
3023  const double newOpacity = hasStrokeOpacityParam ? stroke.alphaF() : 1.0;
3024  if ( hasDefaultStrokeColor )
3025  {
3026  stroke = defaultStroke;
3027  }
3028  stroke.setAlphaF( hasDefaultStrokeOpacity ? defaultStrokeOpacity : newOpacity );
3029  mChangeStrokeColorButton->setColor( stroke );
3030  }
3031  mChangeStrokeColorButton->setEnabled( hasStrokeParam );
3032  mChangeStrokeColorButton->setAllowOpacity( hasStrokeOpacityParam );
3033  if ( hasDefaultStrokeWidth && resetValues )
3034  {
3035  mStrokeWidthSpinBox->setValue( defaultStrokeWidth );
3036  }
3037  mStrokeWidthSpinBox->setEnabled( hasStrokeWidthParam );
3038 }
3039 
3040 void QgsSVGFillSymbolLayerWidget::mChangeColorButton_colorChanged( const QColor &color )
3041 {
3042  if ( !mLayer )
3043  {
3044  return;
3045  }
3046 
3047  mLayer->setSvgFillColor( color );
3048  emit changed();
3049 }
3050 
3051 void QgsSVGFillSymbolLayerWidget::mChangeStrokeColorButton_colorChanged( const QColor &color )
3052 {
3053  if ( !mLayer )
3054  {
3055  return;
3056  }
3057 
3058  mLayer->setSvgStrokeColor( color );
3059  emit changed();
3060 }
3061 
3062 void QgsSVGFillSymbolLayerWidget::mStrokeWidthSpinBox_valueChanged( double d )
3063 {
3064  if ( mLayer )
3065  {
3066  mLayer->setSvgStrokeWidth( d );
3067  emit changed();
3068  }
3069 }
3070 
3071 void QgsSVGFillSymbolLayerWidget::mTextureWidthUnitWidget_changed()
3072 {
3073  if ( mLayer )
3074  {
3075  mLayer->setPatternWidthUnit( mTextureWidthUnitWidget->unit() );
3076  mLayer->setPatternWidthMapUnitScale( mTextureWidthUnitWidget->getMapUnitScale() );
3077  emit changed();
3078  }
3079 }
3080 
3081 void QgsSVGFillSymbolLayerWidget::mSvgStrokeWidthUnitWidget_changed()
3082 {
3083  if ( mLayer )
3084  {
3085  mLayer->setSvgStrokeWidthUnit( mSvgStrokeWidthUnitWidget->unit() );
3086  mLayer->setSvgStrokeWidthMapUnitScale( mSvgStrokeWidthUnitWidget->getMapUnitScale() );
3087  emit changed();
3088  }
3089 }
3090 
3092 
3094  QgsSymbolLayerWidget( parent, vl )
3095 {
3096  setupUi( this );
3097  connect( mAngleSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLinePatternFillSymbolLayerWidget::mAngleSpinBox_valueChanged );
3098  connect( mDistanceSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLinePatternFillSymbolLayerWidget::mDistanceSpinBox_valueChanged );
3099  connect( mOffsetSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLinePatternFillSymbolLayerWidget::mOffsetSpinBox_valueChanged );
3100  connect( mDistanceUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsLinePatternFillSymbolLayerWidget::mDistanceUnitWidget_changed );
3101  connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsLinePatternFillSymbolLayerWidget::mOffsetUnitWidget_changed );
3106  mOffsetSpinBox->setClearValue( 0 );
3107  mAngleSpinBox->setClearValue( 0 );
3108 
3109  mCoordinateReferenceComboBox->addItem( tr( "Align Pattern to Feature" ), static_cast< int >( Qgis::SymbolCoordinateReference::Feature ) );
3110  mCoordinateReferenceComboBox->addItem( tr( "Align Pattern to Map Extent" ), static_cast< int >( Qgis::SymbolCoordinateReference::Viewport ) );
3111  connect( mCoordinateReferenceComboBox, qOverload< int >( &QComboBox::currentIndexChanged ), this, [ = ]
3112  {
3113  if ( mLayer )
3114  {
3115  mLayer->setCoordinateReference( static_cast< Qgis::SymbolCoordinateReference >( mCoordinateReferenceComboBox->currentData().toInt() ) );
3116  emit changed();
3117  }
3118  } );
3119 
3120  mClipModeComboBox->addItem( tr( "Clip During Render Only" ), static_cast< int >( Qgis::LineClipMode::ClipPainterOnly ) );
3121  mClipModeComboBox->addItem( tr( "Clip Lines Before Render" ), static_cast< int >( Qgis::LineClipMode::ClipToIntersection ) );
3122  mClipModeComboBox->addItem( tr( "No Clipping" ), static_cast< int >( Qgis::LineClipMode::NoClipping ) );
3123  connect( mClipModeComboBox, qOverload< int >( &QComboBox::currentIndexChanged ), this, [ = ]
3124  {
3125  if ( mLayer )
3126  {
3127  mLayer->setClipMode( static_cast< Qgis::LineClipMode >( mClipModeComboBox->currentData().toInt() ) );
3128  emit changed();
3129  }
3130  } );
3131 
3132 }
3133 
3135 {
3136  if ( layer->layerType() != QLatin1String( "LinePatternFill" ) )
3137  {
3138  return;
3139  }
3140 
3141  QgsLinePatternFillSymbolLayer *patternLayer = static_cast<QgsLinePatternFillSymbolLayer *>( layer );
3142  if ( patternLayer )
3143  {
3144  mLayer = patternLayer;
3145  whileBlocking( mAngleSpinBox )->setValue( mLayer->lineAngle() );
3146  whileBlocking( mDistanceSpinBox )->setValue( mLayer->distance() );
3147  whileBlocking( mOffsetSpinBox )->setValue( mLayer->offset() );
3148 
3149  //units
3150  mDistanceUnitWidget->blockSignals( true );
3151  mDistanceUnitWidget->setUnit( mLayer->distanceUnit() );
3152  mDistanceUnitWidget->setMapUnitScale( mLayer->distanceMapUnitScale() );
3153  mDistanceUnitWidget->blockSignals( false );
3154  mOffsetUnitWidget->blockSignals( true );
3155  mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
3156  mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
3157  mOffsetUnitWidget->blockSignals( false );
3158 
3159  whileBlocking( mCoordinateReferenceComboBox )->setCurrentIndex( mCoordinateReferenceComboBox->findData( static_cast< int >( mLayer->coordinateReference() ) ) );
3160 
3161  whileBlocking( mClipModeComboBox )->setCurrentIndex( mClipModeComboBox->findData( static_cast< int >( mLayer->clipMode() ) ) );
3162  }
3163 
3168 }
3169 
3171 {
3172  return mLayer;
3173 }
3174 
3175 void QgsLinePatternFillSymbolLayerWidget::mAngleSpinBox_valueChanged( double d )
3176 {
3177  if ( mLayer )
3178  {
3179  mLayer->setLineAngle( d );
3180  emit changed();
3181  }
3182 }
3183 
3184 void QgsLinePatternFillSymbolLayerWidget::mDistanceSpinBox_valueChanged( double d )
3185 {
3186  if ( mLayer )
3187  {
3188  mLayer->setDistance( d );
3189  emit changed();
3190  }
3191 }
3192 
3193 void QgsLinePatternFillSymbolLayerWidget::mOffsetSpinBox_valueChanged( double d )
3194 {
3195  if ( mLayer )
3196  {
3197  mLayer->setOffset( d );
3198  emit changed();
3199  }
3200 }
3201 
3202 void QgsLinePatternFillSymbolLayerWidget::mDistanceUnitWidget_changed()
3203 {
3204  if ( mLayer )
3205  {
3206  mLayer->setDistanceUnit( mDistanceUnitWidget->unit() );
3207  mLayer->setDistanceMapUnitScale( mDistanceUnitWidget->getMapUnitScale() );
3208  emit changed();
3209  }
3210 }
3211 
3212 void QgsLinePatternFillSymbolLayerWidget::mOffsetUnitWidget_changed()
3213 {
3214  if ( mLayer )
3215  {
3216  mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
3217  mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
3218  emit changed();
3219  }
3220 }
3221 
3223 
3225  QgsSymbolLayerWidget( parent, vl )
3226 {
3227  setupUi( this );
3228  connect( mHorizontalDistanceSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsPointPatternFillSymbolLayerWidget::mHorizontalDistanceSpinBox_valueChanged );
3229  connect( mVerticalDistanceSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsPointPatternFillSymbolLayerWidget::mVerticalDistanceSpinBox_valueChanged );
3230  connect( mHorizontalDisplacementSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsPointPatternFillSymbolLayerWidget::mHorizontalDisplacementSpinBox_valueChanged );
3231  connect( mVerticalDisplacementSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsPointPatternFillSymbolLayerWidget::mVerticalDisplacementSpinBox_valueChanged );
3232  connect( mHorizontalOffsetSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsPointPatternFillSymbolLayerWidget::mHorizontalOffsetSpinBox_valueChanged );
3233  connect( mVerticalOffsetSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsPointPatternFillSymbolLayerWidget::mVerticalOffsetSpinBox_valueChanged );
3234  connect( mHorizontalDistanceUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointPatternFillSymbolLayerWidget::mHorizontalDistanceUnitWidget_changed );
3235  connect( mVerticalDistanceUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointPatternFillSymbolLayerWidget::mVerticalDistanceUnitWidget_changed );
3236  connect( mHorizontalDisplacementUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointPatternFillSymbolLayerWidget::mHorizontalDisplacementUnitWidget_changed );
3237  connect( mVerticalDisplacementUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointPatternFillSymbolLayerWidget::mVerticalDisplacementUnitWidget_changed );
3238  connect( mHorizontalOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointPatternFillSymbolLayerWidget::mHorizontalOffsetUnitWidget_changed );
3239  connect( mVerticalOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointPatternFillSymbolLayerWidget::mVerticalOffsetUnitWidget_changed );
3252 
3253  mClipModeComboBox->addItem( tr( "Clip to Shape" ), static_cast< int >( Qgis::MarkerClipMode::Shape ) );
3254  mClipModeComboBox->addItem( tr( "Marker Centroid Within Shape" ), static_cast< int >( Qgis::MarkerClipMode::CentroidWithin ) );
3255  mClipModeComboBox->addItem( tr( "Marker Completely Within Shape" ), static_cast< int >( Qgis::MarkerClipMode::CompletelyWithin ) );
3256  mClipModeComboBox->addItem( tr( "No Clipping" ), static_cast< int >( Qgis::MarkerClipMode::NoClipping ) );
3257  connect( mClipModeComboBox, qOverload< int >( &QComboBox::currentIndexChanged ), this, [ = ]
3258  {
3259  if ( mLayer )
3260  {
3261  mLayer->setClipMode( static_cast< Qgis::MarkerClipMode >( mClipModeComboBox->currentData().toInt() ) );
3262  emit changed();
3263  }
3264  } );
3265 
3266  mCoordinateReferenceComboBox->addItem( tr( "Align Pattern to Feature" ), static_cast< int >( Qgis::SymbolCoordinateReference::Feature ) );
3267  mCoordinateReferenceComboBox->addItem( tr( "Align Pattern to Map Extent" ), static_cast< int >( Qgis::SymbolCoordinateReference::Viewport ) );
3268  connect( mCoordinateReferenceComboBox, qOverload< int >( &QComboBox::currentIndexChanged ), this, [ = ]
3269  {
3270  if ( mLayer )
3271  {
3272  mLayer->setCoordinateReference( static_cast< Qgis::SymbolCoordinateReference >( mCoordinateReferenceComboBox->currentData().toInt() ) );
3273  emit changed();
3274  }
3275  } );
3276 
3277  mSeedSpinBox->setShowClearButton( true );
3278  mSeedSpinBox->setClearValue( 0 );
3279  mRandomXSpinBox->setClearValue( 0 );
3280  mRandomYSpinBox->setClearValue( 0 );
3281 
3286  connect( mRandomXSpinBox, qOverload< double >( &QDoubleSpinBox::valueChanged ), this, [ = ]( double d )
3287  {
3288  if ( mLayer )
3289  {
3291  emit changed();
3292  }
3293  } );
3294  connect( mRandomYSpinBox, qOverload< double >( &QDoubleSpinBox::valueChanged ), this, [ = ]( double d )
3295  {
3296  if ( mLayer )
3297  {
3299  emit changed();
3300  }
3301  } );
3302  connect( mRandomXOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, [ = ]
3303  {
3304  if ( mLayer )
3305  {
3306  mLayer->setRandomDeviationXUnit( mRandomXOffsetUnitWidget->unit() );
3307  mLayer->setRandomDeviationXMapUnitScale( mRandomXOffsetUnitWidget->getMapUnitScale() );
3308  emit changed();
3309  }
3310  } );
3311  connect( mRandomYOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, [ = ]
3312  {
3313  if ( mLayer )
3314  {
3315  mLayer->setRandomDeviationYUnit( mRandomYOffsetUnitWidget->unit() );
3316  mLayer->setRandomDeviationYMapUnitScale( mRandomYOffsetUnitWidget->getMapUnitScale() );
3317  emit changed();
3318  }
3319  } );
3320  connect( mSeedSpinBox, qOverload< int > ( &QSpinBox::valueChanged ), this, [ = ]( int v )
3321  {
3322  if ( mLayer )
3323  {
3324  mLayer->setSeed( v );
3325  emit changed();
3326  }
3327  } );
3328 
3329  mAngleSpinBox->setShowClearButton( true );
3330  mAngleSpinBox->setClearValue( 0 );
3331  connect( mAngleSpinBox, qOverload< double >( &QDoubleSpinBox::valueChanged ), this, [ = ]( double d )
3332  {
3333  if ( mLayer )
3334  {
3335  mLayer->setAngle( d );
3336  emit changed();
3337  }
3338  } );
3339 }
3340 
3342 {
3343  if ( !layer || layer->layerType() != QLatin1String( "PointPatternFill" ) )
3344  {
3345  return;
3346  }
3347 
3348  mLayer = static_cast<QgsPointPatternFillSymbolLayer *>( layer );
3349  whileBlocking( mHorizontalDistanceSpinBox )->setValue( mLayer->distanceX() );
3350  whileBlocking( mVerticalDistanceSpinBox )->setValue( mLayer->distanceY() );
3351  whileBlocking( mHorizontalDisplacementSpinBox )->setValue( mLayer->displacementX() );
3352  whileBlocking( mVerticalDisplacementSpinBox )->setValue( mLayer->displacementY() );
3353  whileBlocking( mHorizontalOffsetSpinBox )->setValue( mLayer->offsetX() );
3354  whileBlocking( mVerticalOffsetSpinBox )->setValue( mLayer->offsetY() );
3355  whileBlocking( mAngleSpinBox )->setValue( mLayer->angle() );
3356 
3357  mHorizontalDistanceUnitWidget->blockSignals( true );
3358  mHorizontalDistanceUnitWidget->setUnit( mLayer->distanceXUnit() );
3359  mHorizontalDistanceUnitWidget->setMapUnitScale( mLayer->distanceXMapUnitScale() );
3360  mHorizontalDistanceUnitWidget->blockSignals( false );
3361  mVerticalDistanceUnitWidget->blockSignals( true );
3362  mVerticalDistanceUnitWidget->setUnit( mLayer->distanceYUnit() );
3363  mVerticalDistanceUnitWidget->setMapUnitScale( mLayer->distanceYMapUnitScale() );
3364  mVerticalDistanceUnitWidget->blockSignals( false );
3365  mHorizontalDisplacementUnitWidget->blockSignals( true );
3366  mHorizontalDisplacementUnitWidget->setUnit( mLayer->displacementXUnit() );
3367  mHorizontalDisplacementUnitWidget->setMapUnitScale( mLayer->displacementXMapUnitScale() );
3368  mHorizontalDisplacementUnitWidget->blockSignals( false );
3369  mVerticalDisplacementUnitWidget->blockSignals( true );
3370  mVerticalDisplacementUnitWidget->setUnit( mLayer->displacementYUnit() );
3371  mVerticalDisplacementUnitWidget->setMapUnitScale( mLayer->displacementYMapUnitScale() );
3372  mVerticalDisplacementUnitWidget->blockSignals( false );
3373  mHorizontalOffsetUnitWidget->blockSignals( true );
3374  mHorizontalOffsetUnitWidget->setUnit( mLayer->offsetXUnit() );
3375  mHorizontalOffsetUnitWidget->setMapUnitScale( mLayer->offsetXMapUnitScale() );
3376  mHorizontalOffsetUnitWidget->blockSignals( false );
3377  mVerticalOffsetUnitWidget->blockSignals( true );
3378  mVerticalOffsetUnitWidget->setUnit( mLayer->offsetYUnit() );
3379  mVerticalOffsetUnitWidget->setMapUnitScale( mLayer->offsetYMapUnitScale() );
3380  mVerticalOffsetUnitWidget->blockSignals( false );
3381 
3382  whileBlocking( mClipModeComboBox )->setCurrentIndex( mClipModeComboBox->findData( static_cast< int >( mLayer->clipMode() ) ) );
3383  whileBlocking( mCoordinateReferenceComboBox )->setCurrentIndex( mCoordinateReferenceComboBox->findData( static_cast< int >( mLayer->coordinateReference() ) ) );
3384 
3385  whileBlocking( mRandomXSpinBox )->setValue( mLayer->maximumRandomDeviationX() );
3386  whileBlocking( mRandomYSpinBox )->setValue( mLayer->maximumRandomDeviationY() );
3387  whileBlocking( mRandomXOffsetUnitWidget )->setUnit( mLayer->randomDeviationXUnit() );
3388  whileBlocking( mRandomXOffsetUnitWidget )->setMapUnitScale( mLayer->randomDeviationXMapUnitScale() );
3389  whileBlocking( mRandomYOffsetUnitWidget )->setUnit( mLayer->randomDeviationYUnit() );
3390  whileBlocking( mRandomYOffsetUnitWidget )->setMapUnitScale( mLayer->randomDeviationYMapUnitScale() );
3391  whileBlocking( mSeedSpinBox )->setValue( mLayer->seed() );
3392 
3393  registerDataDefinedButton( mHorizontalDistanceDDBtn, QgsSymbolLayer::PropertyDistanceX );
3395  registerDataDefinedButton( mHorizontalDisplacementDDBtn, QgsSymbolLayer::PropertyDisplacementX );
3405 }
3406 
3408 {
3409  return mLayer;
3410 }
3411 
3412 void QgsPointPatternFillSymbolLayerWidget::mHorizontalDistanceSpinBox_valueChanged( double d )
3413 {
3414  if ( mLayer )
3415  {
3416  mLayer->setDistanceX( d );
3417  emit changed();
3418  }
3419 }
3420 
3421 void QgsPointPatternFillSymbolLayerWidget::mVerticalDistanceSpinBox_valueChanged( double d )
3422 {
3423  if ( mLayer )
3424  {
3425  mLayer->setDistanceY( d );
3426  emit changed();
3427  }
3428 }
3429 
3430 void QgsPointPatternFillSymbolLayerWidget::mHorizontalDisplacementSpinBox_valueChanged( double d )
3431 {
3432  if ( mLayer )
3433  {
3434  mLayer->setDisplacementX( d );
3435  emit changed();
3436  }
3437 }
3438 
3439 void QgsPointPatternFillSymbolLayerWidget::mVerticalDisplacementSpinBox_valueChanged( double d )
3440 {
3441  if ( mLayer )
3442  {
3443  mLayer->setDisplacementY( d );
3444  emit changed();
3445  }
3446 }
3447 
3448 void QgsPointPatternFillSymbolLayerWidget::mHorizontalOffsetSpinBox_valueChanged( double d )
3449 {
3450  if ( mLayer )
3451  {
3452  mLayer->setOffsetX( d );
3453  emit changed();
3454  }
3455 }
3456 
3457 void QgsPointPatternFillSymbolLayerWidget::mVerticalOffsetSpinBox_valueChanged( double d )
3458 {
3459  if ( mLayer )
3460  {
3461  mLayer->setOffsetY( d );
3462  emit changed();
3463  }
3464 }
3465 
3466 void QgsPointPatternFillSymbolLayerWidget::mHorizontalDistanceUnitWidget_changed()
3467 {
3468  if ( mLayer )
3469  {
3470  mLayer->setDistanceXUnit( mHorizontalDistanceUnitWidget->unit() );
3471  mLayer->setDistanceXMapUnitScale( mHorizontalDistanceUnitWidget->getMapUnitScale() );
3472  emit changed();
3473  }
3474 }
3475 
3476 void QgsPointPatternFillSymbolLayerWidget::mVerticalDistanceUnitWidget_changed()
3477 {
3478  if ( mLayer )
3479  {
3480  mLayer->setDistanceYUnit( mVerticalDistanceUnitWidget->unit() );
3481  mLayer->setDistanceYMapUnitScale( mVerticalDistanceUnitWidget->getMapUnitScale() );
3482  emit changed();
3483  }
3484 }
3485 
3486 void QgsPointPatternFillSymbolLayerWidget::mHorizontalDisplacementUnitWidget_changed()
3487 {
3488  if ( mLayer )
3489  {
3490  mLayer->setDisplacementXUnit( mHorizontalDisplacementUnitWidget->unit() );
3491  mLayer->setDisplacementXMapUnitScale( mHorizontalDisplacementUnitWidget->getMapUnitScale() );
3492  emit changed();
3493  }
3494 }
3495 
3496 void QgsPointPatternFillSymbolLayerWidget::mVerticalDisplacementUnitWidget_changed()
3497 {
3498  if ( mLayer )
3499  {
3500  mLayer->setDisplacementYUnit( mVerticalDisplacementUnitWidget->unit() );
3501  mLayer->setDisplacementYMapUnitScale( mVerticalDisplacementUnitWidget->getMapUnitScale() );
3502  emit changed();
3503  }
3504 }
3505 
3506 void QgsPointPatternFillSymbolLayerWidget::mHorizontalOffsetUnitWidget_changed()
3507 {
3508  if ( mLayer )
3509  {
3510  mLayer->setOffsetXUnit( mHorizontalOffsetUnitWidget->unit() );
3511  mLayer->setOffsetXMapUnitScale( mHorizontalOffsetUnitWidget->getMapUnitScale() );
3512  emit changed();
3513  }
3514 }
3515 
3516 void QgsPointPatternFillSymbolLayerWidget::mVerticalOffsetUnitWidget_changed()
3517 {
3518  if ( mLayer )
3519  {
3520  mLayer->setOffsetYUnit( mVerticalOffsetUnitWidget->unit() );
3521  mLayer->setOffsetYMapUnitScale( mVerticalOffsetUnitWidget->getMapUnitScale() );
3522  emit changed();
3523  }
3524 }
3525 
3527 
3529  : QgsSymbolLayerWidget( parent, vl )
3530 {
3531  mLayer = nullptr;
3532 
3533  setupUi( this );
3534  connect( mSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsFontMarkerSymbolLayerWidget::mSizeUnitWidget_changed );
3535  connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsFontMarkerSymbolLayerWidget::mOffsetUnitWidget_changed );
3536  connect( mStrokeWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsFontMarkerSymbolLayerWidget::mStrokeWidthUnitWidget_changed );
3537  connect( mStrokeWidthSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsFontMarkerSymbolLayerWidget::mStrokeWidthSpinBox_valueChanged );
3538  connect( mHorizontalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsFontMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged );
3539  connect( mVerticalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsFontMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged );
3546 
3547  widgetChar = new CharacterWidget();
3548  scrollArea->setWidget( widgetChar );
3549  scrollArea->setVerticalOnly( true );
3550 
3551  btnColor->setAllowOpacity( true );
3552  btnColor->setColorDialogTitle( tr( "Select Symbol Fill Color" ) );
3553  btnColor->setContext( QStringLiteral( "symbology" ) );
3554  btnStrokeColor->setAllowOpacity( true );
3555  btnStrokeColor->setColorDialogTitle( tr( "Select Symbol Stroke Color" ) );
3556  btnStrokeColor->setContext( QStringLiteral( "symbology" ) );
3557 
3558  mColorDDBtn->registerLinkedWidget( btnColor );
3559  mStrokeColorDDBtn->registerLinkedWidget( btnStrokeColor );
3560 
3561  spinOffsetX->setClearValue( 0.0 );
3562  spinOffsetY->setClearValue( 0.0 );
3563  spinAngle->setClearValue( 0.0 );
3564 
3565  //make a temporary symbol for the size assistant preview
3566  mAssistantPreviewSymbol.reset( new QgsMarkerSymbol() );
3567 
3568  if ( vectorLayer() )
3569  mSizeDDBtn->setSymbol( mAssistantPreviewSymbol );
3570 
3571  connect( cboFont, &QFontComboBox::currentFontChanged, this, &QgsFontMarkerSymbolLayerWidget::setFontFamily );
3572  connect( mFontStyleComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsFontMarkerSymbolLayerWidget::mFontStyleComboBox_currentIndexChanged );
3573  connect( spinSize, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsFontMarkerSymbolLayerWidget::setSize );
3574  connect( cboJoinStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsFontMarkerSymbolLayerWidget::penJoinStyleChanged );
3577  connect( cboJoinStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsFontMarkerSymbolLayerWidget::penJoinStyleChanged );
3578  connect( spinAngle, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsFontMarkerSymbolLayerWidget::setAngle );
3579  connect( spinOffsetX, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsFontMarkerSymbolLayerWidget::setOffset );
3580  connect( spinOffsetY, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsFontMarkerSymbolLayerWidget::setOffset );
3582  connect( mCharLineEdit, &QLineEdit::textChanged, this, &QgsFontMarkerSymbolLayerWidget::setCharacterFromText );
3583 
3584  connect( this, &QgsSymbolLayerWidget::changed, this, &QgsFontMarkerSymbolLayerWidget::updateAssistantSymbol );
3585 }
3586 
3588 
3590 {
3591  if ( layer->layerType() != QLatin1String( "FontMarker" ) )
3592  return;
3593 
3594  // layer type is correct, we can do the cast
3595  mLayer = static_cast<QgsFontMarkerSymbolLayer *>( layer );
3596 
3597  mRefFont.setFamily( mLayer->fontFamily() );
3598  mRefFont.setStyleName( QgsFontUtils::translateNamedStyle( mLayer->fontStyle() ) );
3599 
3600  mFontStyleComboBox->blockSignals( true );
3601  populateFontStyleComboBox();
3602  mFontStyleComboBox->blockSignals( false );
3603 
3604  // set values
3605  whileBlocking( cboFont )->setCurrentFont( mRefFont );
3606  whileBlocking( spinSize )->setValue( mLayer->size() );
3607  whileBlocking( btnColor )->setColor( mLayer->color() );
3608  whileBlocking( btnStrokeColor )->setColor( mLayer->strokeColor() );
3609  whileBlocking( mStrokeWidthSpinBox )->setValue( mLayer->strokeWidth() );
3610  whileBlocking( spinAngle )->setValue( mLayer->angle() );
3611 
3612  widgetChar->blockSignals( true );
3613  widgetChar->setFont( mRefFont );
3614  if ( mLayer->character().length() == 1 )
3615  {
3616  widgetChar->setCharacter( mLayer->character().at( 0 ) );
3617  }
3618  widgetChar->blockSignals( false );
3619  whileBlocking( mCharLineEdit )->setText( mLayer->character() );
3620  mCharPreview->setFont( mRefFont );
3621 
3622  //block
3623  whileBlocking( spinOffsetX )->setValue( mLayer->offset().x() );
3624  whileBlocking( spinOffsetY )->setValue( mLayer->offset().y() );
3625 
3626  mSizeUnitWidget->blockSignals( true );
3627  mSizeUnitWidget->setUnit( mLayer->sizeUnit() );
3628  mSizeUnitWidget->setMapUnitScale( mLayer->sizeMapUnitScale() );
3629  mSizeUnitWidget->blockSignals( false );
3630 
3631  mStrokeWidthUnitWidget->blockSignals( true );
3632  mStrokeWidthUnitWidget->setUnit( mLayer->strokeWidthUnit() );
3633  mStrokeWidthUnitWidget->setMapUnitScale( mLayer->strokeWidthMapUnitScale() );
3634  mStrokeWidthUnitWidget->blockSignals( false );
3635 
3636  mOffsetUnitWidget->blockSignals( true );
3637  mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
3638  mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
3639  mOffsetUnitWidget->blockSignals( false );
3640 
3641  whileBlocking( cboJoinStyle )->setPenJoinStyle( mLayer->penJoinStyle() );
3642 
3643  //anchor points
3644  whileBlocking( mHorizontalAnchorComboBox )->setCurrentIndex( mLayer->horizontalAnchorPoint() );
3645  whileBlocking( mVerticalAnchorComboBox )->setCurrentIndex( mLayer->verticalAnchorPoint() );
3646 
3659 
3660  updateAssistantSymbol();
3661 }
3662 
3664 {
3665  return mLayer;
3666 }
3667 
3669 {
3670  if ( mLayer )
3671  {
3672  mLayer->setFontFamily( font.family() );
3673  mRefFont.setFamily( font.family() );
3674  widgetChar->setFont( mRefFont );
3675  mCharPreview->setFont( mRefFont );
3676  populateFontStyleComboBox();
3677  emit changed();
3678  }
3679 }
3680 
3681 void QgsFontMarkerSymbolLayerWidget::setFontStyle( const QString &style )
3682 {
3683  if ( mLayer )
3684  {
3685  QgsFontUtils::updateFontViaStyle( mRefFont, style );
3687  widgetChar->setFont( mRefFont );
3688  mCharPreview->setFont( mRefFont );
3689  emit changed();
3690  }
3691 }
3692 
3693 void QgsFontMarkerSymbolLayerWidget::setColor( const QColor &color )
3694 {
3695  mLayer->setColor( color );
3696  emit changed();
3697 }
3698 
3700 {
3701  mLayer->setStrokeColor( color );
3702  emit changed();
3703 }
3704 
3706 {
3707  mLayer->setSize( size );
3708  //widgetChar->updateSize(size);
3709  emit changed();
3710 }
3711 
3713 {
3714  mLayer->setAngle( angle );
3715  emit changed();
3716 }
3717 
3719 {
3720  mCharPreview->setText( text );
3721 
3722  if ( text.isEmpty() )
3723  return;
3724 
3725  // take the last character of a string for a better experience when users cycle through several characters on their keyboard
3726  QString character = text;
3727  if ( text.contains( QRegularExpression( QStringLiteral( "^0x[0-9a-fA-F]{1,4}$" ) ) ) )
3728  {
3729  bool ok = false;
3730  const unsigned int value = text.toUInt( &ok, 0 );
3731  if ( ok )
3732  {
3733  character = QChar( value );
3734  mCharPreview->setText( character );
3735  }
3736  }
3737 
3738  if ( character != mLayer->character() )
3739  {
3740  mLayer->setCharacter( character );
3741  if ( mLayer->character().length() == 1 )
3742  {
3743  whileBlocking( widgetChar )->setCharacter( mLayer->character().at( 0 ) );
3744  }
3745  else
3746  {
3748  }
3749  emit changed();
3750  }
3751 }
3752 
3754 {
3755  if ( mLayer->character().length() > 1 || QGuiApplication::keyboardModifiers() & Qt::ControlModifier )
3756  {
3757  mCharLineEdit->insert( chr );
3758  return;
3759  }
3760 
3761  mLayer->setCharacter( chr );
3762  whileBlocking( mCharLineEdit )->setText( chr );
3763  mCharPreview->setText( chr );
3764  emit changed();
3765 }
3766 
3767 void QgsFontMarkerSymbolLayerWidget::setOffset()
3768 {
3769  mLayer->setOffset( QPointF( spinOffsetX->value(), spinOffsetY->value() ) );
3770  emit changed();
3771 }
3772 
3773 void QgsFontMarkerSymbolLayerWidget::penJoinStyleChanged()
3774 {
3775  mLayer->setPenJoinStyle( cboJoinStyle->penJoinStyle() );
3776  emit changed();
3777 }
3778 
3779 void QgsFontMarkerSymbolLayerWidget::mSizeUnitWidget_changed()
3780 {
3781  if ( mLayer )
3782  {
3783  mLayer->setSizeUnit( mSizeUnitWidget->unit() );
3784  mLayer->setSizeMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
3785  emit changed();
3786  }
3787 }
3788 
3789 void QgsFontMarkerSymbolLayerWidget::mOffsetUnitWidget_changed()
3790 {
3791  if ( mLayer )
3792  {
3793  mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
3794  mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
3795  emit changed();
3796  }
3797 }
3798 
3799 void QgsFontMarkerSymbolLayerWidget::mStrokeWidthUnitWidget_changed()
3800 {
3801  if ( mLayer )
3802  {
3803  mLayer->setStrokeWidthUnit( mSizeUnitWidget->unit() );
3804  mLayer->setStrokeWidthMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
3805  emit changed();
3806  }
3807 }
3808 
3809 void QgsFontMarkerSymbolLayerWidget::populateFontStyleComboBox()
3810 {
3811  mFontStyleComboBox->clear();
3812  const QStringList styles = mFontDB.styles( mRefFont.family() );
3813  const auto constStyles = styles;
3814  for ( const QString &style : constStyles )
3815  {
3816  mFontStyleComboBox->addItem( style );
3817  }
3818 
3819  QString targetStyle = mFontDB.styleString( mRefFont );
3820  if ( !styles.contains( targetStyle ) )
3821  {
3822  const QFont f = QFont( mRefFont.family() );
3823  targetStyle = QFontInfo( f ).styleName();
3824  mRefFont.setStyleName( targetStyle );
3825  }
3826  int curIndx = 0;
3827  const int stylIndx = mFontStyleComboBox->findText( targetStyle );
3828  if ( stylIndx > -1 )
3829  {
3830  curIndx = stylIndx;
3831  }
3832 
3833  mFontStyleComboBox->setCurrentIndex( curIndx );
3834 }
3835 
3836 void QgsFontMarkerSymbolLayerWidget::mFontStyleComboBox_currentIndexChanged( int index )
3837 {
3838  Q_UNUSED( index );
3839  setFontStyle( mFontStyleComboBox->currentText() );
3840 }
3841 
3842 void QgsFontMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged( int index )
3843 {
3844  if ( mLayer )
3845  {
3847  emit changed();
3848  }
3849 }
3850 
3851 void QgsFontMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged( int index )
3852 {
3853  if ( mLayer )
3854  {
3856  emit changed();
3857  }
3858 }
3859 
3860 void QgsFontMarkerSymbolLayerWidget::mStrokeWidthSpinBox_valueChanged( double d )
3861 {
3862  if ( mLayer )
3863  {
3864  mLayer->setStrokeWidth( d );
3865  emit changed();
3866  }
3867 }
3868 
3869 void QgsFontMarkerSymbolLayerWidget::updateAssistantSymbol()
3870 {
3871  for ( int i = mAssistantPreviewSymbol->symbolLayerCount() - 1 ; i >= 0; --i )
3872  {
3873  mAssistantPreviewSymbol->deleteSymbolLayer( i );
3874  }
3875  mAssistantPreviewSymbol->appendSymbolLayer( mLayer->clone() );
3877  if ( ddSize )
3878  mAssistantPreviewSymbol->setDataDefinedSize( ddSize );
3879 }
3880 
3882 
3883 
3885  : QgsSymbolLayerWidget( parent, vl )
3886 {
3887  mLayer = nullptr;
3888 
3889  setupUi( this );
3890  connect( mDrawInsideCheckBox, &QCheckBox::stateChanged, this, &QgsCentroidFillSymbolLayerWidget::mDrawInsideCheckBox_stateChanged );
3891  connect( mDrawAllPartsCheckBox, &QCheckBox::stateChanged, this, &QgsCentroidFillSymbolLayerWidget::mDrawAllPartsCheckBox_stateChanged );
3892  connect( mClipPointsCheckBox, &QCheckBox::stateChanged, this, &QgsCentroidFillSymbolLayerWidget::mClipPointsCheckBox_stateChanged );
3893  connect( mClipOnCurrentPartOnlyCheckBox, &QCheckBox::stateChanged, this, &QgsCentroidFillSymbolLayerWidget::mClipOnCurrentPartOnlyCheckBox_stateChanged );
3894 }
3895 
3897 {
3898  if ( layer->layerType() != QLatin1String( "CentroidFill" ) )
3899  return;
3900 
3901  // layer type is correct, we can do the cast
3902  mLayer = static_cast<QgsCentroidFillSymbolLayer *>( layer );
3903 
3904  // set values
3905  whileBlocking( mDrawInsideCheckBox )->setChecked( mLayer->pointOnSurface() );
3906  whileBlocking( mDrawAllPartsCheckBox )->setChecked( mLayer->pointOnAllParts() );
3907  whileBlocking( mClipPointsCheckBox )->setChecked( mLayer->clipPoints() );
3908  whileBlocking( mClipOnCurrentPartOnlyCheckBox )->setChecked( mLayer->clipOnCurrentPartOnly() );
3909 }
3910 
3912 {
3913  return mLayer;
3914 }
3915 
3916 void QgsCentroidFillSymbolLayerWidget::mDrawInsideCheckBox_stateChanged( int state )
3917 {
3918  mLayer->setPointOnSurface( state == Qt::Checked );
3919  emit changed();
3920 }
3921 
3922 void QgsCentroidFillSymbolLayerWidget::mDrawAllPartsCheckBox_stateChanged( int state )
3923 {
3924  mLayer->setPointOnAllParts( state == Qt::Checked );
3925  emit changed();
3926 }
3927 
3928 void QgsCentroidFillSymbolLayerWidget::mClipPointsCheckBox_stateChanged( int state )
3929 {
3930  mLayer->setClipPoints( state == Qt::Checked );
3931  emit changed();
3932 }
3933 
3934 void QgsCentroidFillSymbolLayerWidget::mClipOnCurrentPartOnlyCheckBox_stateChanged( int state )
3935 {
3936  mLayer->setClipOnCurrentPartOnly( state == Qt::Checked );
3937  emit changed();
3938 }
3939 
3941 
3943  : QgsSymbolLayerWidget( parent, vl )
3944 {
3945  mLayer = nullptr;
3946 
3947  setupUi( this );
3948 
3949  mImageSourceLineEdit->setLastPathSettingsKey( QStringLiteral( "/UI/lastRasterMarkerImageDir" ) );
3950 
3951  connect( mImageSourceLineEdit, &QgsImageSourceLineEdit::sourceChanged, this, &QgsRasterMarkerSymbolLayerWidget::imageSourceChanged );
3952  connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsRasterMarkerSymbolLayerWidget::mOffsetUnitWidget_changed );
3953  connect( mRotationSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsRasterMarkerSymbolLayerWidget::setAngle );
3954  connect( mSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsRasterMarkerSymbolLayerWidget::mSizeUnitWidget_changed );
3955  connect( mWidthSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsRasterMarkerSymbolLayerWidget::setWidth );
3956  connect( mHeightSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsRasterMarkerSymbolLayerWidget::setHeight );
3957  connect( mLockAspectRatio, static_cast < void ( QgsRatioLockButton::* )( bool ) > ( &QgsRatioLockButton::lockChanged ), this, &QgsRasterMarkerSymbolLayerWidget::setLockAspectRatio );
3958 
3963 
3964  mSpinOffsetX->setClearValue( 0.0 );
3965  mSpinOffsetY->setClearValue( 0.0 );
3966  mRotationSpinBox->setClearValue( 0.0 );
3967 
3968  connect( mSpinOffsetX, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsRasterMarkerSymbolLayerWidget::setOffset );
3969  connect( mSpinOffsetY, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsRasterMarkerSymbolLayerWidget::setOffset );
3970  connect( mOpacityWidget, &QgsOpacityWidget::opacityChanged, this, &QgsRasterMarkerSymbolLayerWidget::setOpacity );
3971 
3972  connect( mHorizontalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsRasterMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged );
3973  connect( mVerticalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsRasterMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged );
3974 }
3975 
3977 {
3978  if ( !layer )
3979  {
3980  return;
3981  }
3982 
3983  if ( layer->layerType() != QLatin1String( "RasterMarker" ) )
3984  return;
3985 
3986  // layer type is correct, we can do the cast
3987  mLayer = static_cast<QgsRasterMarkerSymbolLayer *>( layer );
3988 
3989  // set values
3990  whileBlocking( mImageSourceLineEdit )->setSource( mLayer->path() );
3991 
3992  whileBlocking( mWidthSpinBox )->setValue( mLayer->size() );
3993  const bool preservedAspectRatio = mLayer->preservedAspectRatio();
3994  mHeightSpinBox->blockSignals( true );
3995  if ( preservedAspectRatio )
3996  {
3997  mHeightSpinBox->setValue( mLayer->size() );
3998  }
3999  else
4000  {
4001  mHeightSpinBox->setValue( mLayer->size() * mLayer->fixedAspectRatio() );
4002  }
4003  mHeightSpinBox->setEnabled( mLayer->defaultAspectRatio() > 0.0 );
4004  mHeightSpinBox->blockSignals( false );
4005  whileBlocking( mLockAspectRatio )->setLocked( preservedAspectRatio );
4006 
4007  whileBlocking( mRotationSpinBox )->setValue( mLayer->angle() );
4008  whileBlocking( mOpacityWidget )->setOpacity( mLayer->opacity() );
4009 
4010  whileBlocking( mSpinOffsetX )->setValue( mLayer->offset().x() );
4011  whileBlocking( mSpinOffsetY )->setValue( mLayer->offset().y() );
4012 
4013  mSizeUnitWidget->blockSignals( true );
4014  mSizeUnitWidget->setUnit( mLayer->sizeUnit() );
4015  mSizeUnitWidget->setMapUnitScale( mLayer->sizeMapUnitScale() );
4016  mSizeUnitWidget->blockSignals( false );
4017  mOffsetUnitWidget->blockSignals( true );
4018  mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
4019  mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
4020  mOffsetUnitWidget->blockSignals( false );
4021 
4022  //anchor points
4023  whileBlocking( mHorizontalAnchorComboBox )->setCurrentIndex( mLayer->horizontalAnchorPoint() );
4024  whileBlocking( mVerticalAnchorComboBox )->setCurrentIndex( mLayer->verticalAnchorPoint() );
4025 
4034 
4035  updatePreviewImage();
4036 }
4037 
4039 {
4040  return mLayer;
4041 }
4042 
4044 {
4046  mImageSourceLineEdit->setMessageBar( context.messageBar() );
4047 }
4048 
4049 void QgsRasterMarkerSymbolLayerWidget::imageSourceChanged( const QString &text )
4050 {
4051  mLayer->setPath( text );
4052  updatePreviewImage();
4053  emit changed();
4054 }
4055 
4056 void QgsRasterMarkerSymbolLayerWidget::updatePreviewImage()
4057 {
4058  bool fitsInCache = false;
4059  const QImage image = QgsApplication::imageCache()->pathAsImage( mLayer->path(), QSize( 150, 150 ), true, 1.0, fitsInCache );
4060  if ( image.isNull() )
4061  {
4062  mLabelImagePreview->setPixmap( QPixmap() );
4063  return;
4064  }
4065 
4066  QImage previewImage( 150, 150, QImage::Format_ARGB32 );
4067  previewImage.fill( Qt::transparent );
4068  const QRect imageRect( ( 150 - image.width() ) / 2.0, ( 150 - image.height() ) / 2.0, image.width(), image.height() );
4069  QPainter p;
4070  p.begin( &previewImage );
4071  //draw a checkerboard background
4072  uchar pixDataRGB[] = { 150, 150, 150, 150,
4073  100, 100, 100, 150,
4074  100, 100, 100, 150,
4075  150, 150, 150, 150
4076  };
4077  const QImage img( pixDataRGB, 2, 2, 8, QImage::Format_ARGB32 );
4078  const QPixmap pix = QPixmap::fromImage( img.scaled( 8, 8 ) );
4079  QBrush checkerBrush;
4080  checkerBrush.setTexture( pix );
4081  p.fillRect( imageRect, checkerBrush );
4082 
4083  if ( mLayer->opacity() < 1.0 )
4084  {
4085  p.setOpacity( mLayer->opacity() );
4086  }
4087 
4088  p.drawImage( imageRect.left(), imageRect.top(), image );
4089  p.end();
4090  mLabelImagePreview->setPixmap( QPixmap::fromImage( previewImage ) );
4091 }
4092 
4093 void QgsRasterMarkerSymbolLayerWidget::setWidth()
4094 {
4095  const double defaultAspectRatio = mLayer->defaultAspectRatio();
4096  double fixedAspectRatio = 0.0;
4097  mHeightSpinBox->blockSignals( true );
4098  if ( defaultAspectRatio <= 0.0 )
4099  {
4100  mHeightSpinBox->setValue( mWidthSpinBox->value() );
4101  }
4102  else if ( mLockAspectRatio->locked() )
4103  {
4104  mHeightSpinBox->setValue( mWidthSpinBox->value() * defaultAspectRatio );
4105  }
4106  else
4107  {
4108  fixedAspectRatio = mHeightSpinBox->value() / mWidthSpinBox->value();
4109  }
4110  mHeightSpinBox->blockSignals( false );
4111  mLayer->setSize( mWidthSpinBox->value() );
4112  mLayer->setFixedAspectRatio( fixedAspectRatio );
4113  emit changed();
4114 }
4115 
4116 void QgsRasterMarkerSymbolLayerWidget::setHeight()
4117 {
4118  const double defaultAspectRatio = mLayer->defaultAspectRatio();
4119  double fixedAspectRatio = 0.0;
4120  mWidthSpinBox->blockSignals( true );
4121  if ( defaultAspectRatio <= 0.0 )
4122  {
4123  mWidthSpinBox->setValue( mHeightSpinBox->value() );
4124  }
4125  else if ( mLockAspectRatio->locked() )
4126  {
4127  mWidthSpinBox->setValue( mHeightSpinBox->value() / defaultAspectRatio );
4128  }
4129  else
4130  {
4131  fixedAspectRatio = mHeightSpinBox->value() / mWidthSpinBox->value();
4132  }
4133  mWidthSpinBox->blockSignals( false );
4134  mLayer->setSize( mWidthSpinBox->value() );
4135  mLayer->setFixedAspectRatio( fixedAspectRatio );
4136  emit changed();
4137 }
4138 
4139 void QgsRasterMarkerSymbolLayerWidget::setLockAspectRatio( const bool locked )
4140 {
4141  const double defaultAspectRatio = mLayer->defaultAspectRatio();
4142  if ( defaultAspectRatio <= 0.0 )
4143  {
4144  whileBlocking( mLockAspectRatio )->setLocked( true );
4145  }
4146  else if ( locked )
4147  {
4148  mLayer->setFixedAspectRatio( 0.0 );
4149  setWidth();
4150  }
4151  else
4152  {
4153  mLayer->setFixedAspectRatio( mHeightSpinBox->value() / mWidthSpinBox->value() );
4154  }
4155 }
4156 
4157 void QgsRasterMarkerSymbolLayerWidget::setAngle()
4158 {
4159  mLayer->setAngle( mRotationSpinBox->value() );
4160  emit changed();
4161 }
4162 
4163 void QgsRasterMarkerSymbolLayerWidget::setOpacity( double value )
4164 {
4165  mLayer->setOpacity( value );
4166  emit changed();
4167  updatePreviewImage();
4168 }
4169 
4170 void QgsRasterMarkerSymbolLayerWidget::setOffset()
4171 {
4172  mLayer->setOffset( QPointF( mSpinOffsetX->value(), mSpinOffsetY->value() ) );
4173  emit changed();
4174 }
4175 
4176 void QgsRasterMarkerSymbolLayerWidget::mSizeUnitWidget_changed()
4177 {
4178  if ( mLayer )
4179  {
4180  mLayer->setSizeUnit( mSizeUnitWidget->unit() );
4181  mLayer->setSizeMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
4182  emit changed();
4183  }
4184 }
4185 
4186 void QgsRasterMarkerSymbolLayerWidget::mOffsetUnitWidget_changed()
4187 {
4188  if ( mLayer )
4189  {
4190  mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
4191  mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
4192  emit changed();
4193  }
4194 }
4195 
4196 void QgsRasterMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged( int index )
4197 {
4198  if ( mLayer )
4199  {
4201  emit changed();
4202  }
4203 }
4204 
4205 void QgsRasterMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged( int index )
4206 {
4207  if ( mLayer )
4208  {
4210  emit changed();
4211  }
4212 }
4213 
4214 
4216 
4218  : QgsSymbolLayerWidget( parent, vl )
4219 {
4220  mLayer = nullptr;
4221 
4222  setupUi( this );
4223 
4224  mImageSourceLineEdit->setLastPathSettingsKey( QStringLiteral( "/UI/lastAnimatedMarkerImageDir" ) );
4225 
4226  connect( mImageSourceLineEdit, &QgsImageSourceLineEdit::sourceChanged, this, &QgsAnimatedMarkerSymbolLayerWidget::imageSourceChanged );
4227  connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsAnimatedMarkerSymbolLayerWidget::mOffsetUnitWidget_changed );
4228  connect( mRotationSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsAnimatedMarkerSymbolLayerWidget::setAngle );
4229  connect( mSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsAnimatedMarkerSymbolLayerWidget::mSizeUnitWidget_changed );
4230  connect( mWidthSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsAnimatedMarkerSymbolLayerWidget::setWidth );
4231  connect( mHeightSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsAnimatedMarkerSymbolLayerWidget::setHeight );
4232  connect( mLockAspectRatio, static_cast < void ( QgsRatioLockButton::* )( bool ) > ( &QgsRatioLockButton::lockChanged ), this, &QgsAnimatedMarkerSymbolLayerWidget::setLockAspectRatio );
4233 
4234  mFrameRateSpin->setClearValue( 10 );
4235  mFrameRateSpin->setShowClearButton( true );
4236  connect( mFrameRateSpin, qOverload< double >( &QDoubleSpinBox::valueChanged ), this, [ = ]( double value )
4237  {
4238  mLayer->setFrameRate( value );
4239  emit changed();
4240  } );
4241 
4246 
4247  mSpinOffsetX->setClearValue( 0.0 );
4248  mSpinOffsetY->setClearValue( 0.0 );
4249  mRotationSpinBox->setClearValue( 0.0 );
4250 
4251  connect( mSpinOffsetX, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsAnimatedMarkerSymbolLayerWidget::setOffset );
4252  connect( mSpinOffsetY, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsAnimatedMarkerSymbolLayerWidget::setOffset );
4253  connect( mOpacityWidget, &QgsOpacityWidget::opacityChanged, this, &QgsAnimatedMarkerSymbolLayerWidget::setOpacity );
4254 
4255  connect( mHorizontalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsAnimatedMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged );
4256  connect( mVerticalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsAnimatedMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged );
4257 }
4258 
4260 {
4261  if ( !layer )
4262  {
4263  return;
4264  }
4265 
4266  if ( layer->layerType() != QLatin1String( "AnimatedMarker" ) )
4267  return;
4268 
4269  // layer type is correct, we can do the cast
4270  mLayer = static_cast<QgsAnimatedMarkerSymbolLayer *>( layer );
4271 
4272  // set values
4273  whileBlocking( mImageSourceLineEdit )->setSource( mLayer->path() );
4274 
4275  const double firstFrameTime = QgsApplication::imageCache()->nextFrameDelay( mLayer->path() );
4276  if ( firstFrameTime > 0 )
4277  {
4278  mFrameRateSpin->setClearValue( 1000 / firstFrameTime );
4279  }
4280  else
4281  {
4282  mFrameRateSpin->setClearValue( 10 );
4283  }
4284 
4285  whileBlocking( mWidthSpinBox )->setValue( mLayer->size() );
4286  const bool preservedAspectRatio = mLayer->preservedAspectRatio();
4287  mHeightSpinBox->blockSignals( true );
4288  if ( preservedAspectRatio )
4289  {
4290  mHeightSpinBox->setValue( mLayer->size() );
4291  }
4292  else
4293  {
4294  mHeightSpinBox->setValue( mLayer->size() * mLayer->fixedAspectRatio() );
4295  }
4296  mHeightSpinBox->setEnabled( mLayer->defaultAspectRatio() > 0.0 );
4297  mHeightSpinBox->blockSignals( false );
4298  whileBlocking( mLockAspectRatio )->setLocked( preservedAspectRatio );
4299 
4300  whileBlocking( mRotationSpinBox )->setValue( mLayer->angle() );
4301  whileBlocking( mOpacityWidget )->setOpacity( mLayer->opacity() );
4302 
4303  whileBlocking( mSpinOffsetX )->setValue( mLayer->offset().x() );
4304  whileBlocking( mSpinOffsetY )->setValue( mLayer->offset().y() );
4305 
4306  whileBlocking( mFrameRateSpin )->setValue( mLayer->frameRate() );
4307 
4308  mSizeUnitWidget->blockSignals( true );
4309  mSizeUnitWidget->setUnit( mLayer->sizeUnit() );
4310  mSizeUnitWidget->setMapUnitScale( mLayer->sizeMapUnitScale() );
4311  mSizeUnitWidget->blockSignals( false );
4312  mOffsetUnitWidget->blockSignals( true );
4313  mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
4314  mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
4315  mOffsetUnitWidget->blockSignals( false );
4316 
4317  //anchor points
4318  whileBlocking( mHorizontalAnchorComboBox )->setCurrentIndex( mLayer->horizontalAnchorPoint() );
4319  whileBlocking( mVerticalAnchorComboBox )->setCurrentIndex( mLayer->verticalAnchorPoint() );
4320 
4329 
4330  updatePreviewImage();
4331 }
4332 
4334 {
4335  return mLayer;
4336 }
4337 
4339 {
4341  mImageSourceLineEdit->setMessageBar( context.messageBar() );
4342 }
4343 
4344 void QgsAnimatedMarkerSymbolLayerWidget::imageSourceChanged( const QString &text )
4345 {
4346  mLayer->setPath( text );
4347 
4348  const double firstFrameTime = QgsApplication::imageCache()->nextFrameDelay( text );
4349  if ( firstFrameTime > 0 )
4350  {
4351  mFrameRateSpin->setClearValue( 1000 / firstFrameTime );
4352  }
4353  else
4354  {
4355  mFrameRateSpin->setClearValue( 10 );
4356  }
4357  updatePreviewImage();
4358  emit changed();
4359 }
4360 
4361 void QgsAnimatedMarkerSymbolLayerWidget::updatePreviewImage()
4362 {
4363  if ( mPreviewMovie )
4364  {
4365  mLabelImagePreview->setMovie( nullptr );
4366  mPreviewMovie->deleteLater();
4367  mPreviewMovie = nullptr;
4368  }
4369 
4370  mPreviewMovie = new QMovie( mLayer->path(), QByteArray(), this );
4371  mPreviewMovie->setScaledSize( QSize( 150, 150 ) );
4372  mLabelImagePreview->setMovie( mPreviewMovie );
4373  mPreviewMovie->start();
4374 }
4375 
4376 void QgsAnimatedMarkerSymbolLayerWidget::setWidth()
4377 {
4378  const double defaultAspectRatio = mLayer->defaultAspectRatio();
4379  double fixedAspectRatio = 0.0;
4380  mHeightSpinBox->blockSignals( true );
4381  if ( defaultAspectRatio <= 0.0 )
4382  {
4383  mHeightSpinBox->setValue( mWidthSpinBox->value() );
4384  }
4385  else if ( mLockAspectRatio->locked() )
4386  {
4387  mHeightSpinBox->setValue( mWidthSpinBox->value() * defaultAspectRatio );
4388  }
4389  else
4390  {
4391  fixedAspectRatio = mHeightSpinBox->value() / mWidthSpinBox->value();
4392  }
4393  mHeightSpinBox->blockSignals( false );
4394  mLayer->setSize( mWidthSpinBox->value() );
4395  mLayer->setFixedAspectRatio( fixedAspectRatio );
4396  emit changed();
4397 }
4398 
4399 void QgsAnimatedMarkerSymbolLayerWidget::setHeight()
4400 {
4401  const double defaultAspectRatio = mLayer->defaultAspectRatio();
4402  double fixedAspectRatio = 0.0;
4403  mWidthSpinBox->blockSignals( true );
4404  if ( defaultAspectRatio <= 0.0 )
4405  {
4406  mWidthSpinBox->setValue( mHeightSpinBox->value() );
4407  }
4408  else if ( mLockAspectRatio->locked() )
4409  {
4410  mWidthSpinBox->setValue( mHeightSpinBox->value() / defaultAspectRatio );
4411  }
4412  else
4413  {
4414  fixedAspectRatio = mHeightSpinBox->value() / mWidthSpinBox->value();
4415  }
4416  mWidthSpinBox->blockSignals( false );
4417  mLayer->setSize( mWidthSpinBox->value() );
4418  mLayer->setFixedAspectRatio( fixedAspectRatio );
4419  emit changed();
4420 }
4421 
4422 void QgsAnimatedMarkerSymbolLayerWidget::setLockAspectRatio( const bool locked )
4423 {
4424  const double defaultAspectRatio = mLayer->defaultAspectRatio();
4425  if ( defaultAspectRatio <= 0.0 )
4426  {
4427  whileBlocking( mLockAspectRatio )->setLocked( true );
4428  }
4429  else if ( locked )
4430  {
4431  mLayer->setFixedAspectRatio( 0.0 );
4432  setWidth();
4433  }
4434  else
4435  {
4436  mLayer->setFixedAspectRatio( mHeightSpinBox->value() / mWidthSpinBox->value() );
4437  }
4438 }
4439 
4440 void QgsAnimatedMarkerSymbolLayerWidget::setAngle()
4441 {
4442  mLayer->setAngle( mRotationSpinBox->value() );
4443  emit changed();
4444 }
4445 
4446 void QgsAnimatedMarkerSymbolLayerWidget::setOpacity( double value )
4447 {
4448  mLayer->setOpacity( value );
4449  emit changed();
4450  updatePreviewImage();
4451 }
4452 
4453 void QgsAnimatedMarkerSymbolLayerWidget::setOffset()
4454 {
4455  mLayer->setOffset( QPointF( mSpinOffsetX->value(), mSpinOffsetY->value() ) );
4456  emit changed();
4457 }
4458 
4459 void QgsAnimatedMarkerSymbolLayerWidget::mSizeUnitWidget_changed()
4460 {
4461  if ( mLayer )
4462  {
4463  mLayer->setSizeUnit( mSizeUnitWidget->unit() );
4464  mLayer->setSizeMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
4465  emit changed();
4466  }
4467 }
4468 
4469 void QgsAnimatedMarkerSymbolLayerWidget::mOffsetUnitWidget_changed()
4470 {
4471  if ( mLayer )
4472  {
4473  mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
4474  mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
4475  emit changed();
4476  }
4477 }
4478 
4479 void QgsAnimatedMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged( int index )
4480 {
4481  if ( mLayer )
4482  {
4484  emit changed();
4485  }
4486 }
4487 
4488 void QgsAnimatedMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged( int index )
4489 {
4490  if ( mLayer )
4491  {
4493  emit changed();
4494  }
4495 }
4496 
4498 
4500  : QgsSymbolLayerWidget( parent, vl )
4501 {
4502  mLayer = nullptr;
4503  setupUi( this );
4504 
4505  mImageSourceLineEdit->setLastPathSettingsKey( QStringLiteral( "/UI/lastRasterMarkerImageDir" ) );
4506  connect( mImageSourceLineEdit, &QgsImageSourceLineEdit::sourceChanged, this, &QgsRasterFillSymbolLayerWidget::imageSourceChanged );
4507 
4508  connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsRasterFillSymbolLayerWidget::mOffsetUnitWidget_changed );
4509  connect( mRotationSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsRasterFillSymbolLayerWidget::mRotationSpinBox_valueChanged );
4510  connect( mWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsRasterFillSymbolLayerWidget::mWidthUnitWidget_changed );
4511  connect( mWidthSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsRasterFillSymbolLayerWidget::mWidthSpinBox_valueChanged );
4512 
4517 
4518  mSpinOffsetX->setClearValue( 0.0 );
4519  mSpinOffsetY->setClearValue( 0.0 );
4520  mRotationSpinBox->setClearValue( 0.0 );
4521 
4522  connect( cboCoordinateMode, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsRasterFillSymbolLayerWidget::setCoordinateMode );
4523  connect( mSpinOffsetX, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsRasterFillSymbolLayerWidget::offsetChanged );
4524  connect( mSpinOffsetY, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsRasterFillSymbolLayerWidget::offsetChanged );
4525  connect( mOpacityWidget, &QgsOpacityWidget::opacityChanged, this, &QgsRasterFillSymbolLayerWidget::opacityChanged );
4526 }
4527 
4528 
4530 {
4531  if ( !layer )
4532  {
4533  return;
4534  }
4535 
4536  if ( layer->layerType() != QLatin1String( "RasterFill" ) )
4537  {
4538  return;
4539  }
4540 
4541  mLayer = dynamic_cast<QgsRasterFillSymbolLayer *>( layer );
4542  if ( !mLayer )
4543  {
4544  return;
4545  }
4546 
4547  whileBlocking( mImageSourceLineEdit )->setSource( mLayer->imageFilePath() );
4548 
4549  cboCoordinateMode->blockSignals( true );
4550  switch ( mLayer->coordinateMode() )
4551  {
4553  cboCoordinateMode->setCurrentIndex( 1 );
4554  break;
4556  default:
4557  cboCoordinateMode->setCurrentIndex( 0 );
4558  break;
4559  }
4560  cboCoordinateMode->blockSignals( false );
4561  whileBlocking( mOpacityWidget )->setOpacity( mLayer->opacity() );
4562  whileBlocking( mRotationSpinBox )->setValue( mLayer->angle() );
4563 
4564  whileBlocking( mSpinOffsetX )->setValue( mLayer->offset().x() );
4565  whileBlocking( mSpinOffsetY )->setValue( mLayer->offset().y() );
4566  mOffsetUnitWidget->blockSignals( true );
4567  mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
4568  mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
4569  mOffsetUnitWidget->blockSignals( false );
4570 
4571  whileBlocking( mWidthSpinBox )->setValue( mLayer->width() );
4572  mWidthUnitWidget->blockSignals( true );
4573  mWidthUnitWidget->setUnit( mLayer->widthUnit() );
4574  mWidthUnitWidget->setMapUnitScale( mLayer->widthMapUnitScale() );
4575  mWidthUnitWidget->blockSignals( false );
4576 
4577  updatePreviewImage();
4578 
4584 }
4585 
4587 {
4588  return mLayer;
4589 }
4590 
4591 void QgsRasterFillSymbolLayerWidget::imageSourceChanged( const QString &text )
4592 {
4593  mLayer->setImageFilePath( text );
4594  updatePreviewImage();
4595  emit changed();
4596 }
4597 
4598 void QgsRasterFillSymbolLayerWidget::setCoordinateMode( int index )
4599 {
4600  switch ( index )
4601  {
4602  case 0:
4603  //feature coordinate mode
4605  break;
4606  case 1:
4607  //viewport coordinate mode
4609  break;
4610  }
4611 
4612  emit changed();
4613 }
4614 
4615 void QgsRasterFillSymbolLayerWidget::opacityChanged( double value )
4616 {
4617  if ( !mLayer )
4618  {
4619  return;
4620  }
4621 
4622  mLayer->setOpacity( value );
4623  emit changed();
4624  updatePreviewImage();
4625 }
4626 
4627 void QgsRasterFillSymbolLayerWidget::offsetChanged()
4628 {
4629  mLayer->setOffset( QPointF( mSpinOffsetX->value(), mSpinOffsetY->value() ) );
4630  emit changed();
4631 }
4632 
4633 void QgsRasterFillSymbolLayerWidget::mOffsetUnitWidget_changed()
4634 {
4635  if ( !mLayer )
4636  {
4637  return;
4638  }
4639  mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
4640  mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
4641  emit changed();
4642 }
4643 
4644 void QgsRasterFillSymbolLayerWidget::mRotationSpinBox_valueChanged( double d )
4645 {
4646  if ( mLayer )
4647  {
4648  mLayer->setAngle( d );
4649  emit changed();
4650  }
4651 }
4652 
4653 void QgsRasterFillSymbolLayerWidget::mWidthUnitWidget_changed()
4654 {
4655  if ( !mLayer )
4656  {
4657  return;
4658  }
4659  mLayer->setWidthUnit( mWidthUnitWidget->unit() );
4660  mLayer->setWidthMapUnitScale( mWidthUnitWidget->getMapUnitScale() );
4661  emit changed();
4662 }
4663 
4664 void QgsRasterFillSymbolLayerWidget::mWidthSpinBox_valueChanged( double d )
4665 {
4666  if ( !mLayer )
4667  {
4668  return;
4669  }
4670  mLayer->setWidth( d );
4671  emit changed();
4672 }
4673 
4674 void QgsRasterFillSymbolLayerWidget::updatePreviewImage()
4675 {
4676  bool fitsInCache = false;
4677  const QImage image = QgsApplication::imageCache()->pathAsImage( mLayer->imageFilePath(), QSize( 150, 150 ), true, 1.0, fitsInCache );
4678  if ( image.isNull() )
4679  {
4680  mLabelImagePreview->setPixmap( QPixmap() );
4681  return;
4682  }
4683 
4684  QImage previewImage( 150, 150, QImage::Format_ARGB32 );
4685  previewImage.fill( Qt::transparent );
4686  const QRect imageRect( ( 150 - image.width() ) / 2.0, ( 150 - image.height() ) / 2.0, image.width(), image.height() );
4687  QPainter p;
4688  p.begin( &previewImage );
4689  //draw a checkerboard background
4690  uchar pixDataRGB[] = { 150, 150, 150, 150,
4691  100, 100, 100, 150,
4692  100, 100, 100, 150,
4693  150, 150, 150, 150
4694  };
4695  const QImage img( pixDataRGB, 2, 2, 8, QImage::Format_ARGB32 );
4696  const QPixmap pix = QPixmap::fromImage( img.scaled( 8, 8 ) );
4697  QBrush checkerBrush;
4698  checkerBrush.setTexture( pix );
4699  p.fillRect( imageRect, checkerBrush );
4700 
4701  if ( mLayer->opacity() < 1.0 )
4702  {
4703  p.setOpacity( mLayer->opacity() );
4704  }
4705 
4706  p.drawImage( imageRect.left(), imageRect.top(), image );
4707  p.end();
4708  mLabelImagePreview->setPixmap( QPixmap::fromImage( previewImage ) );
4709 }
4710 
4711 //
4712 // QgsRasterLineSymbolLayerWidget
4713 //
4714 
4715 
4717  : QgsSymbolLayerWidget( parent, vl )
4718 {
4719  mLayer = nullptr;
4720  setupUi( this );
4721 
4722  mImageSourceLineEdit->setLastPathSettingsKey( QStringLiteral( "/UI/lastRasterMarkerImageDir" ) );
4723 
4728 
4729  connect( mPenWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, [ = ]
4730  {
4731  if ( mLayer )
4732  {
4733  mLayer->setWidthUnit( mPenWidthUnitWidget->unit() );
4734  mLayer->setWidthMapUnitScale( mPenWidthUnitWidget->getMapUnitScale() );
4735  emit changed();
4736  }
4737  } );
4738 
4739  connect( spinWidth, qOverload< double >( &QDoubleSpinBox::valueChanged ), this, [ = ]
4740  {
4741  if ( mLayer )
4742  {
4743  mLayer->setWidth( spinWidth->value() );
4744  emit changed();
4745  }
4746  } );
4747 
4748  connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, [ = ]
4749  {
4750  if ( mLayer )
4751  {
4752  mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
4753  mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
4754  emit changed();
4755  }
4756  } );
4757 
4758 
4759  spinOffset->setClearValue( 0.0 );
4760  connect( spinOffset, qOverload< double >( &QDoubleSpinBox::valueChanged ), this, [ = ]( double val )
4761  {
4762  if ( mLayer )
4763  {
4764  mLayer->setOffset( val );
4765  emit changed();
4766  }
4767  } );
4768 
4769  connect( cboCapStyle, qOverload< int >( &QComboBox::currentIndexChanged ), this, [ = ]
4770  {
4771  if ( mLayer )
4772  {
4773  mLayer->setPenCapStyle( cboCapStyle->penCapStyle() );
4774  emit changed();
4775  }
4776  } );
4777  connect( cboJoinStyle, qOverload< int >( &QComboBox::currentIndexChanged ), this, [ = ]
4778  {
4779  if ( mLayer )
4780  {
4781  mLayer->setPenJoinStyle( cboJoinStyle->penJoinStyle() );
4782  emit changed();
4783  }
4784  } );
4785 
4786  connect( mImageSourceLineEdit, &QgsImageSourceLineEdit::sourceChanged, this, &QgsRasterLineSymbolLayerWidget::imageSourceChanged );
4787  connect( mOpacityWidget, &QgsOpacityWidget::opacityChanged, this, [ = ]( double opacity )
4788  {
4789  if ( mLayer )
4790  {
4791  mLayer->setOpacity( opacity );
4792  updatePreviewImage();
4793  emit changed();
4794  }
4795  } );
4796 }
4797 
4799 {
4800  if ( !layer )
4801  {
4802  return;
4803  }
4804 
4805  if ( layer->layerType() != QLatin1String( "RasterLine" ) )
4806  {
4807  return;
4808  }
4809 
4810  mLayer = dynamic_cast<QgsRasterLineSymbolLayer *>( layer );
4811  if ( !mLayer )
4812  {
4813  return;
4814  }
4815 
4816  whileBlocking( mImageSourceLineEdit )->setSource( mLayer->path() );
4817  whileBlocking( mOpacityWidget )->setOpacity( mLayer->opacity() );
4818 
4819  whileBlocking( spinWidth )->setValue( mLayer->width() );
4820  whileBlocking( mPenWidthUnitWidget )->setUnit( mLayer->widthUnit() );
4821  whileBlocking( mPenWidthUnitWidget )->setMapUnitScale( mLayer->widthMapUnitScale() );
4822  whileBlocking( cboJoinStyle )->setPenJoinStyle( mLayer->penJoinStyle() );
4823  whileBlocking( cboCapStyle )->setPenCapStyle( mLayer->penCapStyle() );
4824 
4825  whileBlocking( mOffsetUnitWidget )->setUnit( mLayer->offsetUnit() );
4826  whileBlocking( mOffsetUnitWidget )->setMapUnitScale( mLayer->offsetMapUnitScale() );
4827  whileBlocking( spinOffset )->setValue( mLayer->offset() );
4828 
4829  updatePreviewImage();
4830 
4837 }
4838 
4840 {
4841  return mLayer;
4842 }
4843 
4844 void QgsRasterLineSymbolLayerWidget::imageSourceChanged( const QString &text )
4845 {
4846  mLayer->setPath( text );
4847  updatePreviewImage();
4848  emit changed();
4849 }
4850 
4851 void QgsRasterLineSymbolLayerWidget::updatePreviewImage()
4852 {
4853  bool fitsInCache = false;
4854  const QImage image = QgsApplication::imageCache()->pathAsImage( mLayer->path(), QSize( 150, 150 ), true, 1.0, fitsInCache );
4855  if ( image.isNull() )
4856  {
4857  mLabelImagePreview->setPixmap( QPixmap() );
4858  return;
4859  }
4860 
4861  QImage previewImage( 150, 150, QImage::Format_ARGB32 );
4862  previewImage.fill( Qt::transparent );
4863  const QRect imageRect( ( 150 - image.width() ) / 2.0, ( 150 - image.height() ) / 2.0, image.width(), image.height() );
4864  QPainter p;
4865  p.begin( &previewImage );
4866  //draw a checkerboard background
4867  uchar pixDataRGB[] = { 150, 150, 150, 150,
4868  100, 100, 100, 150,
4869  100, 100, 100, 150,
4870  150, 150, 150, 150
4871  };
4872  const QImage img( pixDataRGB, 2, 2, 8, QImage::Format_ARGB32 );
4873  const QPixmap pix = QPixmap::fromImage( img.scaled( 8, 8 ) );
4874  QBrush checkerBrush;
4875  checkerBrush.setTexture( pix );
4876  p.fillRect( imageRect, checkerBrush );
4877 
4878  if ( mLayer->opacity() < 1.0 )
4879  {
4880  p.setOpacity( mLayer->opacity() );
4881  }
4882 
4883  p.drawImage( imageRect.left(), imageRect.top(), image );
4884  p.end();
4885  mLabelImagePreview->setPixmap( QPixmap::fromImage( previewImage ) );
4886 }
4887 
4888 
4889 
4890 //
4891 // QgsGeometryGeneratorSymbolLayerWidget
4892 //
4893 
4895  : QgsSymbolLayerWidget( parent, vl )
4896 
4897 {
4898  setupUi( this );
4899  modificationExpressionSelector->setMultiLine( true );
4900  modificationExpressionSelector->setLayer( const_cast<QgsVectorLayer *>( vl ) );
4901  modificationExpressionSelector->registerExpressionContextGenerator( this );
4902  cbxGeometryType->addItem( QgsIconUtils::iconPolygon(), tr( "Polygon / MultiPolygon" ), static_cast< int >( Qgis::SymbolType::Fill ) );
4903  cbxGeometryType->addItem( QgsIconUtils::iconLine(), tr( "LineString / MultiLineString" ), static_cast< int >( Qgis::SymbolType::Line ) );
4904  cbxGeometryType->addItem( QgsIconUtils::iconPoint(), tr( "Point / MultiPoint" ), static_cast< int >( Qgis::SymbolType::Marker ) );
4905 
4906  mUnitWidget->setUnits( {QgsUnitTypes::RenderMillimeters,
4911  } );
4912  mUnitWidget->setShowMapScaleButton( false );
4913 
4914  connect( modificationExpressionSelector, &QgsExpressionLineEdit::expressionChanged, this, &QgsGeometryGeneratorSymbolLayerWidget::updateExpression );
4915  connect( cbxGeometryType, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsGeometryGeneratorSymbolLayerWidget::updateSymbolType );
4916  connect( mUnitWidget, &QgsUnitSelectionWidget::changed, this, [ = ]
4917  {
4918  if ( !mBlockSignals )
4919  {
4920  mLayer->setUnits( mUnitWidget->unit() );
4921  emit symbolChanged();
4922  }
4923  } );
4924 }
4925 
4927 {
4928  mBlockSignals++;
4929  mLayer = static_cast<QgsGeometryGeneratorSymbolLayer *>( l );
4930  modificationExpressionSelector->setExpression( mLayer->geometryExpression() );
4931  cbxGeometryType->setCurrentIndex( cbxGeometryType->findData( static_cast< int >( mLayer->symbolType() ) ) );
4932  mUnitWidget->setUnit( mLayer->units() );
4933  mBlockSignals--;
4934 }
4935 
4937 {
4938  return mLayer;
4939 }
4940 
4941 void QgsGeometryGeneratorSymbolLayerWidget::updateExpression( const QString &string )
4942 {
4943  mLayer->setGeometryExpression( string );
4944 
4945  emit changed();
4946 }
4947 
4948 void QgsGeometryGeneratorSymbolLayerWidget::updateSymbolType()
4949 {
4950  // we try to keep the subsymbol, if we can!
4951  std::unique_ptr< QgsSymbol > subSymbol( mLayer->subSymbol()->clone() );
4952 
4953  mLayer->setSymbolType( static_cast<Qgis::SymbolType>( cbxGeometryType->currentData().toInt() ) );
4954 
4955  switch ( mLayer->symbolType() )
4956  {
4959  break;
4961  {
4962  if ( subSymbol->type() == Qgis::SymbolType::Fill )
4963  {
4964  // going from fill -> line type, so we can copy any LINE symbol layers across
4965  QgsSymbolLayerList layers;
4966  for ( int i = 0; i < subSymbol->symbolLayerCount(); ++i )
4967  {
4968  if ( dynamic_cast< const QgsLineSymbolLayer * >( subSymbol->symbolLayer( i ) ) )
4969  layers << subSymbol->symbolLayer( i )->clone();
4970  }
4971 
4972  if ( !layers.empty() )
4973  mLayer->setSubSymbol( new QgsLineSymbol( layers ) );
4974  }
4975  break;
4976  }
4978  if ( subSymbol->type() == Qgis::SymbolType::Line )
4979  {
4980  // going from line -> fill type, so copy ALL line symbol layers across
4981  QgsSymbolLayerList layers;
4982  for ( int i = 0; i < subSymbol->symbolLayerCount(); ++i )
4983  layers << subSymbol->symbolLayer( i )->clone();
4984  mLayer->setSubSymbol( new QgsFillSymbol( layers ) );
4985  }
4986  break;
4987  }
4988 
4989  emit symbolChanged();
4990 }
4991 
4992 //
4993 // QgsRandomMarkerFillSymbolLayerWidget
4994 //
4995 
4996 
4998  QgsSymbolLayerWidget( parent, vl )
4999 {
5000  setupUi( this );
5001 
5002  mCountMethodComboBox->addItem( tr( "Absolute Count" ), static_cast< int >( Qgis::PointCountMethod::Absolute ) );
5003  mCountMethodComboBox->addItem( tr( "Density-based Count" ), static_cast< int >( Qgis::PointCountMethod::DensityBased ) );
5004 
5005  mPointCountSpinBox->setShowClearButton( true );
5006  mPointCountSpinBox->setClearValue( 100 );
5007  mSeedSpinBox->setShowClearButton( true );
5008  mSeedSpinBox->setClearValue( 0 );
5009 
5010  connect( mCountMethodComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsRandomMarkerFillSymbolLayerWidget::countMethodChanged );
5011  connect( mPointCountSpinBox, static_cast < void ( QSpinBox::* )( int ) > ( &QSpinBox::valueChanged ), this, &QgsRandomMarkerFillSymbolLayerWidget::countChanged );
5012  connect( mDensityAreaSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsRandomMarkerFillSymbolLayerWidget::densityAreaChanged );
5013  connect( mSeedSpinBox, static_cast < void ( QSpinBox::* )( int ) > ( &QSpinBox::valueChanged ), this, &QgsRandomMarkerFillSymbolLayerWidget::seedChanged );
5014  connect( mClipPointsCheckBox, &QCheckBox::toggled, this, [ = ]( bool checked )
5015  {
5016  if ( mLayer )
5017  {
5018  mLayer->setClipPoints( checked );
5019  emit changed();
5020  }
5021  } );
5022 
5025 
5026  connect( mDensityAreaUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsRandomMarkerFillSymbolLayerWidget::densityAreaUnitChanged );
5027 }
5028 
5030 {
5031  if ( !layer || layer->layerType() != QLatin1String( "RandomMarkerFill" ) )
5032  {
5033  return;
5034  }
5035 
5036  mLayer = static_cast<QgsRandomMarkerFillSymbolLayer *>( layer );
5037  whileBlocking( mPointCountSpinBox )->setValue( mLayer->pointCount() );
5038  whileBlocking( mSeedSpinBox )->setValue( mLayer->seed() );
5039  whileBlocking( mClipPointsCheckBox )->setChecked( mLayer->clipPoints() );
5040 
5041  bool showDensityBasedCountWidgets = false;
5042  switch ( mLayer->countMethod() )
5043  {
5044  case Qgis::PointCountMethod::DensityBased:
5045  showDensityBasedCountWidgets = true;
5046  break;
5047  case Qgis::PointCountMethod::Absolute:
5048  break;
5049  }
5050  mDensityAreaLabel->setVisible( showDensityBasedCountWidgets );
5051  mDensityAreaSpinBox->setVisible( showDensityBasedCountWidgets );
5052  mDensityAreaUnitWidget->setVisible( showDensityBasedCountWidgets );
5053  mDensityAre