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