QGIS API Documentation 4.3.0-Master (0cfde48c85b)
Loading...
Searching...
No Matches
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
18
19#include "characterwidget.h"
20#include "qgsapplication.h"
21#include "qgsauxiliarystorage.h"
22#include "qgscolorramp.h"
23#include "qgscolorrampbutton.h"
24#include "qgsdashspacedialog.h"
26#include "qgsfillsymbol.h"
27#include "qgsfillsymbollayer.h"
28#include "qgsfontutils.h"
30#include "qgsiconutils.h"
31#include "qgsimagecache.h"
33#include "qgslinesymbol.h"
34#include "qgslinesymbollayer.h"
35#include "qgsmapcanvas.h"
36#include "qgsmapmouseevent.h"
37#include "qgsmaptoolcapture.h"
39#include "qgsmaptoolextraitem.h"
40#include "qgsmarkersymbol.h"
45#include "qgsproperty.h"
47#include "qgssnappingutils.h"
48#include "qgssvgcache.h"
50#include "qgssymbollayerutils.h"
51#include "qgsvectorlayer.h"
52#include "qgsvectorlayerutils.h"
53
54#include <QAbstractButton>
55#include <QAction>
56#include <QActionGroup>
57#include <QBuffer>
58#include <QButtonGroup>
59#include <QColorDialog>
60#include <QCursor>
61#include <QDir>
62#include <QFileDialog>
63#include <QInputDialog>
64#include <QMainWindow>
65#include <QMenu>
66#include <QMessageBox>
67#include <QMovie>
68#include <QPainter>
69#include <QRegularExpression>
70#include <QStandardItemModel>
71#include <QString>
72#include <QSvgRenderer>
73
74#include "moc_qgssymbollayerwidget.cpp"
75
76using namespace Qt::StringLiterals;
77
79{
80 if ( auto *lExpressionContext = mContext.expressionContext() )
81 return *lExpressionContext;
82
83 QgsExpressionContext expContext( mContext.globalProjectAtlasMapLayerScopes( vectorLayer() ) );
84
86 if ( const QgsSymbolLayer *symbolLayer = const_cast<QgsSymbolLayerWidget *>( this )->symbolLayer() )
87 {
88 //cheat a bit - set the symbol color variable to match the symbol layer's color (when we should really be using the *symbols*
89 //color, but that's not accessible here). 99% of the time these will be the same anyway
91 }
92 expContext << symbolScope;
98 expContext.lastScope()->addVariable( QgsExpressionContextScope::StaticVariable( u"symbol_layer_count"_s, 1, true ) );
99 expContext.lastScope()->addVariable( QgsExpressionContextScope::StaticVariable( u"symbol_layer_index"_s, 1, true ) );
100 expContext.lastScope()->addVariable( QgsExpressionContextScope::StaticVariable( u"symbol_marker_row"_s, 1, true ) );
101 expContext.lastScope()->addVariable( QgsExpressionContextScope::StaticVariable( u"symbol_marker_column"_s, 1, true ) );
102 expContext.lastScope()->addVariable( QgsExpressionContextScope::StaticVariable( u"symbol_frame"_s, 1, true ) );
103
104 // additional scopes
105 const auto constAdditionalExpressionContextScopes = mContext.additionalExpressionContextScopes();
106 for ( const QgsExpressionContextScope &scope : constAdditionalExpressionContextScopes )
107 {
108 expContext.appendScope( new QgsExpressionContextScope( scope ) );
109 }
110
111 //TODO - show actual value
112 expContext.setOriginalValueVariable( QVariant() );
113
114 QStringList highlights;
115 highlights
125 << u"symbol_layer_count"_s
126 << u"symbol_layer_index"_s
127 << u"symbol_frame"_s;
128
129
130 if ( expContext.hasVariable( u"zoom_level"_s ) )
131 {
132 highlights << u"zoom_level"_s;
133 }
134 if ( expContext.hasVariable( u"vector_tile_zoom"_s ) )
135 {
136 highlights << u"vector_tile_zoom"_s;
137 }
138
139 expContext.setHighlightedVariables( highlights );
140
141 return expContext;
142}
143
145{
146 mContext = context;
147 const auto unitSelectionWidgets = findChildren<QgsUnitSelectionWidget *>();
148 for ( QgsUnitSelectionWidget *unitWidget : unitSelectionWidgets )
149 {
150 unitWidget->setMapCanvas( mContext.mapCanvas() );
151 }
152}
153
155{
156 return mContext;
157}
158
160{
161 button->init( static_cast<int>( key ), symbolLayer()->dataDefinedProperties(), QgsSymbolLayer::propertyDefinitions(), mVectorLayer, true );
163 connect( button, &QgsPropertyOverrideButton::createAuxiliaryField, this, &QgsSymbolLayerWidget::createAuxiliaryField );
164
166}
167
168void QgsSymbolLayerWidget::createAuxiliaryField()
169{
170 // try to create an auxiliary layer if not yet created
171 if ( !mVectorLayer->auxiliaryLayer() )
172 {
173 QgsNewAuxiliaryLayerDialog dlg( mVectorLayer, this );
174 dlg.exec();
175 }
176
177 // return if still not exists
178 if ( !mVectorLayer->auxiliaryLayer() )
179 return;
180
181 QgsPropertyOverrideButton *button = qobject_cast<QgsPropertyOverrideButton *>( sender() );
182 QgsSymbolLayer::Property key = static_cast<QgsSymbolLayer::Property>( button->propertyKey() );
183 QgsPropertyDefinition def = QgsSymbolLayer::propertyDefinitions()[static_cast<int>( key )];
184
185 // create property in auxiliary storage if necessary
186 if ( !mVectorLayer->auxiliaryLayer()->exists( def ) )
187 {
188 QgsNewAuxiliaryFieldDialog dlg( def, mVectorLayer, true, this );
189 if ( dlg.exec() == QDialog::Accepted )
190 def = dlg.propertyDefinition();
191 }
192
193 // return if still not exist
194 if ( !mVectorLayer->auxiliaryLayer()->exists( def ) )
195 return;
196
197 // update property with join field name from auxiliary storage
198 QgsProperty property = button->toProperty();
199 property.setField( QgsAuxiliaryLayer::nameFromProperty( def, true ) );
200 property.setActive( true );
201 button->updateFieldLists();
202 button->setToProperty( property );
203 symbolLayer()->setDataDefinedProperty( key, button->toProperty() );
204
205 emit changed();
206}
207
209{
210 QgsPropertyOverrideButton *button = qobject_cast<QgsPropertyOverrideButton *>( sender() );
211 const QgsSymbolLayer::Property key = static_cast<QgsSymbolLayer::Property>( button->propertyKey() );
212 symbolLayer()->setDataDefinedProperty( key, button->toProperty() );
213 emit changed();
214}
215
217 : QgsSymbolLayerWidget( parent, vl )
218{
219 mLayer = nullptr;
220
221 setupUi( this );
222 connect( mCustomCheckBox, &QCheckBox::stateChanged, this, &QgsSimpleLineSymbolLayerWidget::mCustomCheckBox_stateChanged );
223 connect( mChangePatternButton, &QPushButton::clicked, this, &QgsSimpleLineSymbolLayerWidget::mChangePatternButton_clicked );
224 connect( mPenWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSimpleLineSymbolLayerWidget::mPenWidthUnitWidget_changed );
225 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSimpleLineSymbolLayerWidget::mOffsetUnitWidget_changed );
226 connect( mDashPatternUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSimpleLineSymbolLayerWidget::mDashPatternUnitWidget_changed );
227 connect( mDrawInsideCheckBox, &QCheckBox::stateChanged, this, &QgsSimpleLineSymbolLayerWidget::mDrawInsideCheckBox_stateChanged );
228 connect( mPatternOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSimpleLineSymbolLayerWidget::patternOffsetUnitChanged );
229 connect( mCheckAlignDash, &QCheckBox::toggled, this, [this] {
230 mCheckDashCorners->setEnabled( mCheckAlignDash->isChecked() );
231 if ( !mCheckAlignDash->isChecked() )
232 mCheckDashCorners->setChecked( false );
233
234 if ( mLayer )
235 {
236 mLayer->setAlignDashPattern( mCheckAlignDash->isChecked() );
237 emit changed();
238 }
239 } );
240 connect( mCheckDashCorners, &QCheckBox::toggled, this, [this] {
241 if ( mLayer )
242 {
243 mLayer->setTweakDashPatternOnCorners( mCheckDashCorners->isChecked() );
244 emit changed();
245 }
246 } );
247
248 mPenWidthUnitWidget->setUnits(
250 );
251 mOffsetUnitWidget->setUnits(
253 );
254 mDashPatternUnitWidget->setUnits(
256 );
257 mPatternOffsetUnitWidget->setUnits(
259 );
260 mTrimDistanceStartUnitWidget->setUnits(
269 );
270 mTrimDistanceEndUnitWidget->setUnits(
279 );
280
281 btnChangeColor->setAllowOpacity( true );
282 btnChangeColor->setColorDialogTitle( tr( "Select Line Color" ) );
283 btnChangeColor->setContext( u"symbology"_s );
284
285 mColorDDBtn->registerLinkedWidget( btnChangeColor );
286
287 mRingFilterComboBox->addItem( QgsApplication::getThemeIcon( u"mIconAllRings.svg"_s ), tr( "All Rings" ), QgsLineSymbolLayer::AllRings );
288 mRingFilterComboBox->addItem( QgsApplication::getThemeIcon( u"mIconExteriorRing.svg"_s ), tr( "Exterior Ring Only" ), QgsLineSymbolLayer::ExteriorRingOnly );
289 mRingFilterComboBox->addItem( QgsApplication::getThemeIcon( u"mIconInteriorRings.svg"_s ), tr( "Interior Rings Only" ), QgsLineSymbolLayer::InteriorRingsOnly );
290 connect( mRingFilterComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this]( int ) {
291 if ( mLayer )
292 {
293 mLayer->setRingFilter( static_cast<QgsLineSymbolLayer::RenderRingFilter>( mRingFilterComboBox->currentData().toInt() ) );
294 emit changed();
295 }
296 } );
297
298 spinOffset->setClearValue( 0.0 );
299 spinPatternOffset->setClearValue( 0.0 );
300
301 mTrimStartDistanceSpin->setClearValue( 0.0 );
302 mTrimDistanceEndSpin->setClearValue( 0.0 );
303
304 //make a temporary symbol for the size assistant preview
305 mAssistantPreviewSymbol = std::make_shared<QgsLineSymbol>();
306
307 if ( vectorLayer() )
308 mPenWidthDDBtn->setSymbol( mAssistantPreviewSymbol );
309
310 connect( spinWidth, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleLineSymbolLayerWidget::penWidthChanged );
311 connect( btnChangeColor, &QgsColorButton::colorChanged, this, &QgsSimpleLineSymbolLayerWidget::colorChanged );
312 connect( cboPenStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleLineSymbolLayerWidget::penStyleChanged );
313 connect( spinOffset, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleLineSymbolLayerWidget::offsetChanged );
314 connect( cboCapStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleLineSymbolLayerWidget::penStyleChanged );
315 connect( cboJoinStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleLineSymbolLayerWidget::penStyleChanged );
316 connect( spinPatternOffset, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleLineSymbolLayerWidget::patternOffsetChanged );
317
318 connect( mTrimStartDistanceSpin, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, [this]( double value ) {
319 if ( !mLayer )
320 return;
321
322 mLayer->setTrimDistanceStart( value );
323 emit changed();
324 } );
325 connect( mTrimDistanceStartUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
326 if ( !mLayer )
327 return;
328
329 mLayer->setTrimDistanceStartUnit( mTrimDistanceStartUnitWidget->unit() );
330 mLayer->setTrimDistanceStartMapUnitScale( mTrimDistanceStartUnitWidget->getMapUnitScale() );
331 emit changed();
332 } );
333 connect( mTrimDistanceEndSpin, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, [this]( double value ) {
334 if ( !mLayer )
335 return;
336
337 mLayer->setTrimDistanceEnd( value );
338 emit changed();
339 } );
340 connect( mTrimDistanceEndUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
341 if ( !mLayer )
342 return;
343
344 mLayer->setTrimDistanceEndUnit( mTrimDistanceEndUnitWidget->unit() );
345 mLayer->setTrimDistanceEndMapUnitScale( mTrimDistanceEndUnitWidget->getMapUnitScale() );
346 emit changed();
347 } );
348
349
351
352 connect( this, &QgsSymbolLayerWidget::changed, this, &QgsSimpleLineSymbolLayerWidget::updateAssistantSymbol );
353}
354
356
357void QgsSimpleLineSymbolLayerWidget::updateAssistantSymbol()
358{
359 for ( int i = mAssistantPreviewSymbol->symbolLayerCount() - 1; i >= 0; --i )
360 {
361 mAssistantPreviewSymbol->deleteSymbolLayer( i );
362 }
363 mAssistantPreviewSymbol->appendSymbolLayer( mLayer->clone() );
364 const QgsProperty ddWidth = mLayer->dataDefinedProperties().property( QgsSymbolLayer::Property::StrokeWidth );
365 if ( ddWidth )
366 mAssistantPreviewSymbol->setDataDefinedWidth( ddWidth );
367}
368
369
371{
372 if ( !layer || layer->layerType() != "SimpleLine"_L1 )
373 return;
374
375 // layer type is correct, we can do the cast
376 mLayer = static_cast<QgsSimpleLineSymbolLayer *>( layer );
377
378 // set units
379 mPenWidthUnitWidget->blockSignals( true );
380 mPenWidthUnitWidget->setUnit( mLayer->widthUnit() );
381 mPenWidthUnitWidget->setMapUnitScale( mLayer->widthMapUnitScale() );
382 mPenWidthUnitWidget->blockSignals( false );
383 mOffsetUnitWidget->blockSignals( true );
384 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
385 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
386 mOffsetUnitWidget->blockSignals( false );
387 mDashPatternUnitWidget->blockSignals( true );
388 mDashPatternUnitWidget->setUnit( mLayer->customDashPatternUnit() );
389 mDashPatternUnitWidget->setMapUnitScale( mLayer->customDashPatternMapUnitScale() );
390 mDashPatternUnitWidget->blockSignals( false );
391
392 whileBlocking( mPatternOffsetUnitWidget )->setUnit( mLayer->dashPatternOffsetUnit() );
393 whileBlocking( mPatternOffsetUnitWidget )->setMapUnitScale( mLayer->dashPatternOffsetMapUnitScale() );
394 whileBlocking( mTrimDistanceStartUnitWidget )->setUnit( mLayer->trimDistanceStartUnit() );
395 whileBlocking( mTrimDistanceStartUnitWidget )->setMapUnitScale( mLayer->trimDistanceStartMapUnitScale() );
396 whileBlocking( mTrimDistanceEndUnitWidget )->setUnit( mLayer->trimDistanceEndUnit() );
397 whileBlocking( mTrimDistanceEndUnitWidget )->setMapUnitScale( mLayer->trimDistanceEndMapUnitScale() );
398
399 // set values
400 spinWidth->blockSignals( true );
401 spinWidth->setValue( mLayer->width() );
402 spinWidth->blockSignals( false );
403 btnChangeColor->blockSignals( true );
404 btnChangeColor->setColor( mLayer->color() );
405 btnChangeColor->blockSignals( false );
406 spinOffset->blockSignals( true );
407 spinOffset->setValue( mLayer->offset() );
408 spinOffset->blockSignals( false );
409 cboPenStyle->blockSignals( true );
410 cboJoinStyle->blockSignals( true );
411 cboCapStyle->blockSignals( true );
412 cboPenStyle->setPenStyle( mLayer->penStyle() );
413 cboJoinStyle->setPenJoinStyle( mLayer->penJoinStyle() );
414 cboCapStyle->setPenCapStyle( mLayer->penCapStyle() );
415 cboPenStyle->blockSignals( false );
416 cboJoinStyle->blockSignals( false );
417 cboCapStyle->blockSignals( false );
418 whileBlocking( spinPatternOffset )->setValue( mLayer->dashPatternOffset() );
419 whileBlocking( mTrimStartDistanceSpin )->setValue( mLayer->trimDistanceStart() );
420 whileBlocking( mTrimDistanceEndSpin )->setValue( mLayer->trimDistanceEnd() );
421
422 //use a custom dash pattern?
423 const bool useCustomDashPattern = mLayer->useCustomDashPattern();
424 mChangePatternButton->setEnabled( useCustomDashPattern );
425 label_3->setEnabled( !useCustomDashPattern );
426 cboPenStyle->setEnabled( !useCustomDashPattern );
427 mCustomCheckBox->blockSignals( true );
428 mCustomCheckBox->setCheckState( useCustomDashPattern ? Qt::Checked : Qt::Unchecked );
429 mCustomCheckBox->blockSignals( false );
430
431 //make sure height of custom dash button looks good under different platforms
432 const QSize size = mChangePatternButton->minimumSizeHint();
433 const int fontHeight = static_cast<int>( Qgis::UI_SCALE_FACTOR * fontMetrics().height() * 1.4 );
434 mChangePatternButton->setMinimumSize( QSize( size.width(), std::max( size.height(), fontHeight ) ) );
435
436 //draw inside polygon?
437 const bool drawInsidePolygon = mLayer->drawInsidePolygon();
438 whileBlocking( mDrawInsideCheckBox )->setCheckState( drawInsidePolygon ? Qt::Checked : Qt::Unchecked );
439
440 whileBlocking( mRingFilterComboBox )->setCurrentIndex( mRingFilterComboBox->findData( mLayer->ringFilter() ) );
441
442 whileBlocking( mCheckAlignDash )->setChecked( mLayer->alignDashPattern() );
443 mCheckDashCorners->setEnabled( mLayer->alignDashPattern() );
444 whileBlocking( mCheckDashCorners )->setChecked( mLayer->tweakDashPatternOnCorners() && mLayer->alignDashPattern() );
445
447
458
459 updateAssistantSymbol();
460}
461
466
468{
470
471 switch ( context.symbolType() )
472 {
475 //these settings only have an effect when the symbol layers is part of a fill symbol
476 mDrawInsideCheckBox->hide();
477 mRingFilterComboBox->hide();
478 mRingsLabel->hide();
479 break;
480
483 break;
484 }
485}
486
487void QgsSimpleLineSymbolLayerWidget::penWidthChanged()
488{
489 mLayer->setWidth( spinWidth->value() );
491 emit changed();
492}
493
494void QgsSimpleLineSymbolLayerWidget::colorChanged( const QColor &color )
495{
496 mLayer->setColor( color );
497 emit changed();
498}
499
500void QgsSimpleLineSymbolLayerWidget::penStyleChanged()
501{
502 mLayer->setPenStyle( cboPenStyle->penStyle() );
503 mLayer->setPenJoinStyle( cboJoinStyle->penJoinStyle() );
504 mLayer->setPenCapStyle( cboCapStyle->penCapStyle() );
506 emit changed();
507}
508
509void QgsSimpleLineSymbolLayerWidget::offsetChanged()
510{
511 mLayer->setOffset( spinOffset->value() );
513 emit changed();
514}
515
516void QgsSimpleLineSymbolLayerWidget::patternOffsetChanged()
517{
518 mLayer->setDashPatternOffset( spinPatternOffset->value() );
520 emit changed();
521}
522
523void QgsSimpleLineSymbolLayerWidget::mCustomCheckBox_stateChanged( int state )
524{
525 const bool checked = ( state == Qt::Checked );
526 mChangePatternButton->setEnabled( checked );
527 label_3->setEnabled( !checked );
528 cboPenStyle->setEnabled( !checked );
529
530 mLayer->setUseCustomDashPattern( checked );
531 emit changed();
532}
533
534void QgsSimpleLineSymbolLayerWidget::mChangePatternButton_clicked()
535{
536 QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( this );
537 if ( panel && panel->dockMode() )
538 {
539 QgsDashSpaceWidget *widget = new QgsDashSpaceWidget( mLayer->customDashVector(), panel );
540 widget->setPanelTitle( tr( "Custom Dash Pattern" ) );
541 widget->setUnit( mDashPatternUnitWidget->unit() );
542 connect( widget, &QgsPanelWidget::changed, this, [this, widget]() {
543 mLayer->setCustomDashVector( widget->dashDotVector() );
545 } );
546 connect( widget, &QgsPanelWidget::changed, this, &QgsSymbolLayerWidget::changed );
547 panel->openPanel( widget );
548 return;
549 }
550
551 QgsDashSpaceDialog d( mLayer->customDashVector() );
552 d.setUnit( mDashPatternUnitWidget->unit() );
553 if ( d.exec() == QDialog::Accepted )
554 {
555 mLayer->setCustomDashVector( d.dashDotVector() );
557 emit changed();
558 }
559}
560
561void QgsSimpleLineSymbolLayerWidget::mPenWidthUnitWidget_changed()
562{
563 if ( mLayer )
564 {
565 mLayer->setWidthUnit( mPenWidthUnitWidget->unit() );
566 mLayer->setWidthMapUnitScale( mPenWidthUnitWidget->getMapUnitScale() );
568 emit changed();
569 }
570}
571
572void QgsSimpleLineSymbolLayerWidget::mOffsetUnitWidget_changed()
573{
574 if ( mLayer )
575 {
576 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
577 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
578 emit changed();
579 }
580}
581
582void QgsSimpleLineSymbolLayerWidget::mDashPatternUnitWidget_changed()
583{
584 if ( mLayer )
585 {
586 mLayer->setCustomDashPatternUnit( mDashPatternUnitWidget->unit() );
587 mLayer->setCustomDashPatternMapUnitScale( mDashPatternUnitWidget->getMapUnitScale() );
589 emit changed();
590 }
591}
592
593void QgsSimpleLineSymbolLayerWidget::mDrawInsideCheckBox_stateChanged( int state )
594{
595 const bool checked = ( state == Qt::Checked );
596 mLayer->setDrawInsidePolygon( checked );
597 emit changed();
598}
599
600void QgsSimpleLineSymbolLayerWidget::patternOffsetUnitChanged()
601{
602 if ( mLayer )
603 {
604 mLayer->setDashPatternOffsetUnit( mPatternOffsetUnitWidget->unit() );
605 mLayer->setDashPatternOffsetMapUnitScale( mPatternOffsetUnitWidget->getMapUnitScale() );
607 emit changed();
608 }
609}
610
612{
613 if ( !mLayer )
614 {
615 return;
616 }
617 std::unique_ptr<QgsSimpleLineSymbolLayer> layerCopy( mLayer->clone() );
618 if ( !layerCopy )
619 {
620 return;
621 }
622 const QColor color = qApp->palette().color( QPalette::WindowText );
623 layerCopy->setColor( color );
624 // reset offset, we don't want to show that in the preview
625 layerCopy->setOffset( 0 );
626 layerCopy->setUseCustomDashPattern( true );
627
628 QSize currentIconSize;
629 //icon size is button size with a small margin
630#ifdef Q_OS_WIN
631 currentIconSize = QSize( mChangePatternButton->width() - 10, mChangePatternButton->height() - 6 );
632#else
633 currentIconSize = QSize( mChangePatternButton->width() - 10, mChangePatternButton->height() - 12 );
634#endif
635
636 if ( !currentIconSize.isValid() || currentIconSize.width() <= 0 || currentIconSize.height() <= 0 )
637 {
638 return;
639 }
640
641 //create an icon pixmap
642 const std::unique_ptr<QgsLineSymbol> previewSymbol = std::make_unique<QgsLineSymbol>( QgsSymbolLayerList() << layerCopy.release() );
643 const QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( previewSymbol.get(), currentIconSize, 0, nullptr, QgsScreenProperties( screen() ) );
644 mChangePatternButton->setIconSize( currentIconSize );
645 mChangePatternButton->setIcon( icon );
646
647 // set tooltip
648 // create very large preview image
649 const int width = static_cast<int>( Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance( 'X' ) * 23 );
650 const int height = static_cast<int>( width / 1.61803398875 ); // golden ratio
651
652 const QPixmap pm = QgsSymbolLayerUtils::symbolPreviewPixmap( previewSymbol.get(), QSize( width, height ), height / 20, nullptr, false, nullptr, nullptr, QgsScreenProperties( screen() ) );
653 QByteArray data;
654 QBuffer buffer( &data );
655 pm.save( &buffer, "PNG", 100 );
656 mChangePatternButton->setToolTip( u"<img src='data:image/png;base64, %3' width=\"%4\">"_s.arg( QString( data.toBase64() ) ).arg( width ) );
657}
658
660{
661 QgsSymbolLayerWidget::resizeEvent( event );
662 // redraw custom dash pattern icon -- the button size has changed
664}
665
667
669 : QgsSymbolLayerWidget( parent, vl )
670{
671 mLayer = nullptr;
672
673 setupUi( this );
674
675 mHorizontalAnchorComboBox->addItem( tr( "Left" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Left ) );
676 mHorizontalAnchorComboBox->addItem( tr( "Horizontal Center" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Center ) );
677 mHorizontalAnchorComboBox->addItem( tr( "Right" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Right ) );
678
679 mVerticalAnchorComboBox->addItem( tr( "Top" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Top ) );
680 mVerticalAnchorComboBox->addItem( tr( "Vertical Center" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Center ) );
681 mVerticalAnchorComboBox->addItem( tr( "Bottom" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Bottom ) );
682
683 connect( mSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSimpleMarkerSymbolLayerWidget::mSizeUnitWidget_changed );
684 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSimpleMarkerSymbolLayerWidget::mOffsetUnitWidget_changed );
685 connect( mStrokeWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSimpleMarkerSymbolLayerWidget::mStrokeWidthUnitWidget_changed );
686 connect( mStrokeStyleComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::mStrokeStyleComboBox_currentIndexChanged );
687 connect( mStrokeWidthSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::mStrokeWidthSpinBox_valueChanged );
688 connect( mHorizontalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged );
689 connect( mVerticalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged );
690 mSizeUnitWidget->setUnits(
692 );
693 mOffsetUnitWidget->setUnits(
695 );
696 mStrokeWidthUnitWidget->setUnits(
698 );
699
700 btnChangeColorFill->setAllowOpacity( true );
701 btnChangeColorFill->setColorDialogTitle( tr( "Select Fill Color" ) );
702 btnChangeColorFill->setContext( u"symbology"_s );
703 btnChangeColorFill->setShowNoColor( true );
704 btnChangeColorFill->setNoColorString( tr( "Transparent Fill" ) );
705 btnChangeColorFill->setOpaqueColorString( tr( "Opaque Fill" ) );
706 btnChangeColorStroke->setAllowOpacity( true );
707 btnChangeColorStroke->setColorDialogTitle( tr( "Select Stroke Color" ) );
708 btnChangeColorStroke->setContext( u"symbology"_s );
709 btnChangeColorStroke->setShowNoColor( true );
710 btnChangeColorStroke->setNoColorString( tr( "Transparent Stroke" ) );
711 btnChangeColorStroke->setOpaqueColorString( tr( "Opaque Stroke" ) );
712
713 mFillColorDDBtn->registerLinkedWidget( btnChangeColorFill );
714 mStrokeColorDDBtn->registerLinkedWidget( btnChangeColorStroke );
715
716 spinOffsetX->setClearValue( 0.0 );
717 spinOffsetY->setClearValue( 0.0 );
718 spinAngle->setClearValue( 0.0 );
719
720 //make a temporary symbol for the size assistant preview
721 mAssistantPreviewSymbol = std::make_shared<QgsMarkerSymbol>();
722
723 if ( vectorLayer() )
724 mSizeDDBtn->setSymbol( mAssistantPreviewSymbol );
725
726 int size = lstNames->iconSize().width();
727
728 size = std::max( 30, static_cast<int>( std::round( Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance( 'X' ) * 3 ) ) );
729
730 lstNames->setGridSize( QSize( size * 1.2, size * 1.2 ) );
731 lstNames->setIconSize( QSize( size, size ) );
732
733 const double markerSize = size * 0.8;
735 for ( const Qgis::MarkerShape shape : shapes )
736 {
737 QgsSimpleMarkerSymbolLayer *lyr = new QgsSimpleMarkerSymbolLayer( shape, markerSize );
739 lyr->setColor( QColor( 200, 200, 200 ) );
740 lyr->setStrokeColor( QColor( 0, 0, 0 ) );
741 const QIcon icon
743 QListWidgetItem *item = new QListWidgetItem( icon, QString(), lstNames );
744 item->setData( Qt::UserRole, static_cast<int>( shape ) );
745 item->setToolTip( QgsSimpleMarkerSymbolLayerBase::encodeShape( shape ) );
746 delete lyr;
747 }
748 // show at least 3 rows
749 lstNames->setMinimumHeight( lstNames->gridSize().height() * 3.1 );
750
751 connect( lstNames, &QListWidget::currentRowChanged, this, &QgsSimpleMarkerSymbolLayerWidget::setShape );
754 connect( cboJoinStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::penJoinStyleChanged );
755 connect( cboCapStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::penCapStyleChanged );
756 connect( spinSize, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::setSize );
757 connect( spinAngle, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::setAngle );
758 connect( spinOffsetX, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::setOffset );
759 connect( spinOffsetY, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::setOffset );
760 connect( this, &QgsSymbolLayerWidget::changed, this, &QgsSimpleMarkerSymbolLayerWidget::updateAssistantSymbol );
761}
762
764
766{
767 if ( layer->layerType() != "SimpleMarker"_L1 )
768 return;
769
770 // layer type is correct, we can do the cast
771 mLayer = static_cast<QgsSimpleMarkerSymbolLayer *>( layer );
772
773 // set values
774 const Qgis::MarkerShape shape = mLayer->shape();
775 for ( int i = 0; i < lstNames->count(); ++i )
776 {
777 if ( static_cast<Qgis::MarkerShape>( lstNames->item( i )->data( Qt::UserRole ).toInt() ) == shape )
778 {
779 lstNames->setCurrentRow( i );
780 break;
781 }
782 }
783 btnChangeColorStroke->blockSignals( true );
784 btnChangeColorStroke->setColor( mLayer->strokeColor() );
785 btnChangeColorStroke->blockSignals( false );
786 btnChangeColorFill->blockSignals( true );
787 btnChangeColorFill->setColor( mLayer->fillColor() );
788 btnChangeColorFill->setEnabled( QgsSimpleMarkerSymbolLayerBase::shapeIsFilled( mLayer->shape() ) );
789 btnChangeColorFill->blockSignals( false );
790 spinSize->blockSignals( true );
791 spinSize->setValue( mLayer->size() );
792 spinSize->blockSignals( false );
793 spinAngle->blockSignals( true );
794 spinAngle->setValue( mLayer->angle() );
795 spinAngle->blockSignals( false );
796 mStrokeStyleComboBox->blockSignals( true );
797 mStrokeStyleComboBox->setPenStyle( mLayer->strokeStyle() );
798 mStrokeStyleComboBox->blockSignals( false );
799 mStrokeWidthSpinBox->blockSignals( true );
800 mStrokeWidthSpinBox->setValue( mLayer->strokeWidth() );
801 mStrokeWidthSpinBox->blockSignals( false );
802 cboJoinStyle->blockSignals( true );
803 cboJoinStyle->setPenJoinStyle( mLayer->penJoinStyle() );
804 cboJoinStyle->blockSignals( false );
805 cboCapStyle->blockSignals( true );
806 cboCapStyle->setPenCapStyle( mLayer->penCapStyle() );
807 cboCapStyle->blockSignals( false );
808
809 // without blocking signals the value gets changed because of slot setOffset()
810 spinOffsetX->blockSignals( true );
811 spinOffsetX->setValue( mLayer->offset().x() );
812 spinOffsetX->blockSignals( false );
813 spinOffsetY->blockSignals( true );
814 spinOffsetY->setValue( mLayer->offset().y() );
815 spinOffsetY->blockSignals( false );
816
817 mSizeUnitWidget->blockSignals( true );
818 mSizeUnitWidget->setUnit( mLayer->sizeUnit() );
819 mSizeUnitWidget->setMapUnitScale( mLayer->sizeMapUnitScale() );
820 mSizeUnitWidget->blockSignals( false );
821 mOffsetUnitWidget->blockSignals( true );
822 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
823 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
824 mOffsetUnitWidget->blockSignals( false );
825 mStrokeWidthUnitWidget->blockSignals( true );
826 mStrokeWidthUnitWidget->setUnit( mLayer->strokeWidthUnit() );
827 mStrokeWidthUnitWidget->setMapUnitScale( mLayer->strokeWidthMapUnitScale() );
828 mStrokeWidthUnitWidget->blockSignals( false );
829
830 //anchor points
831 mHorizontalAnchorComboBox->blockSignals( true );
832 mVerticalAnchorComboBox->blockSignals( true );
833 mHorizontalAnchorComboBox->setCurrentIndex( mHorizontalAnchorComboBox->findData( QVariant::fromValue( mLayer->horizontalAnchorPoint() ) ) );
834 mVerticalAnchorComboBox->setCurrentIndex( mVerticalAnchorComboBox->findData( QVariant::fromValue( mLayer->verticalAnchorPoint() ) ) );
835 mHorizontalAnchorComboBox->blockSignals( false );
836 mVerticalAnchorComboBox->blockSignals( false );
837
850
851 updateAssistantSymbol();
852}
853
858
859void QgsSimpleMarkerSymbolLayerWidget::setShape()
860{
861 mLayer->setShape( static_cast<Qgis::MarkerShape>( lstNames->currentItem()->data( Qt::UserRole ).toInt() ) );
862 btnChangeColorFill->setEnabled( QgsSimpleMarkerSymbolLayerBase::shapeIsFilled( mLayer->shape() ) );
863 emit changed();
864}
865
867{
868 mLayer->setStrokeColor( color );
869 emit changed();
870}
871
873{
874 mLayer->setColor( color );
875 emit changed();
876}
877
878void QgsSimpleMarkerSymbolLayerWidget::penJoinStyleChanged()
879{
880 mLayer->setPenJoinStyle( cboJoinStyle->penJoinStyle() );
881 emit changed();
882}
883
884void QgsSimpleMarkerSymbolLayerWidget::penCapStyleChanged()
885{
886 mLayer->setPenCapStyle( cboCapStyle->penCapStyle() );
887 emit changed();
888}
889
890void QgsSimpleMarkerSymbolLayerWidget::setSize()
891{
892 mLayer->setSize( spinSize->value() );
893 emit changed();
894}
895
896void QgsSimpleMarkerSymbolLayerWidget::setAngle()
897{
898 mLayer->setAngle( spinAngle->value() );
899 emit changed();
900}
901
902void QgsSimpleMarkerSymbolLayerWidget::setOffset()
903{
904 mLayer->setOffset( QPointF( spinOffsetX->value(), spinOffsetY->value() ) );
905 emit changed();
906}
907
908void QgsSimpleMarkerSymbolLayerWidget::mStrokeStyleComboBox_currentIndexChanged( int index )
909{
910 Q_UNUSED( index )
911
912 if ( mLayer )
913 {
914 mLayer->setStrokeStyle( mStrokeStyleComboBox->penStyle() );
915 emit changed();
916 }
917}
918
919void QgsSimpleMarkerSymbolLayerWidget::mStrokeWidthSpinBox_valueChanged( double d )
920{
921 if ( mLayer )
922 {
923 mLayer->setStrokeWidth( d );
924 emit changed();
925 }
926}
927
928void QgsSimpleMarkerSymbolLayerWidget::mSizeUnitWidget_changed()
929{
930 if ( mLayer )
931 {
932 mLayer->setSizeUnit( mSizeUnitWidget->unit() );
933 mLayer->setSizeMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
934 emit changed();
935 }
936}
937
938void QgsSimpleMarkerSymbolLayerWidget::mOffsetUnitWidget_changed()
939{
940 if ( mLayer )
941 {
942 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
943 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
944 emit changed();
945 }
946}
947
948void QgsSimpleMarkerSymbolLayerWidget::mStrokeWidthUnitWidget_changed()
949{
950 if ( mLayer )
951 {
952 mLayer->setStrokeWidthUnit( mStrokeWidthUnitWidget->unit() );
953 mLayer->setStrokeWidthMapUnitScale( mStrokeWidthUnitWidget->getMapUnitScale() );
954 emit changed();
955 }
956}
957
958void QgsSimpleMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged( int )
959{
960 if ( mLayer )
961 {
962 mLayer->setHorizontalAnchorPoint( mHorizontalAnchorComboBox->currentData().value< Qgis::HorizontalAnchorPoint >() );
963 emit changed();
964 }
965}
966
967void QgsSimpleMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged( int )
968{
969 if ( mLayer )
970 {
971 mLayer->setVerticalAnchorPoint( mVerticalAnchorComboBox->currentData().value< Qgis::VerticalAnchorPoint >() );
972 emit changed();
973 }
974}
975
976void QgsSimpleMarkerSymbolLayerWidget::updateAssistantSymbol()
977{
978 for ( int i = mAssistantPreviewSymbol->symbolLayerCount() - 1; i >= 0; --i )
979 {
980 mAssistantPreviewSymbol->deleteSymbolLayer( i );
981 }
982 mAssistantPreviewSymbol->appendSymbolLayer( mLayer->clone() );
983 const QgsProperty ddSize = mLayer->dataDefinedProperties().property( QgsSymbolLayer::Property::Size );
984 if ( ddSize )
985 mAssistantPreviewSymbol->setDataDefinedSize( ddSize );
986}
987
988
990
992 : QgsSymbolLayerWidget( parent, vl )
993{
994 mLayer = nullptr;
995
996 setupUi( this );
997 connect( mStrokeWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSimpleFillSymbolLayerWidget::mStrokeWidthUnitWidget_changed );
998 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSimpleFillSymbolLayerWidget::mOffsetUnitWidget_changed );
999 mStrokeWidthUnitWidget->setUnits(
1001 );
1002 mOffsetUnitWidget->setUnits(
1004 );
1005
1006 btnChangeColor->setAllowOpacity( true );
1007 btnChangeColor->setColorDialogTitle( tr( "Select Fill Color" ) );
1008 btnChangeColor->setContext( u"symbology"_s );
1009 btnChangeColor->setShowNoColor( true );
1010 btnChangeColor->setNoColorString( tr( "Transparent Fill" ) );
1011 btnChangeColor->setOpaqueColorString( tr( "Opaque Fill" ) );
1012 btnChangeStrokeColor->setAllowOpacity( true );
1013 btnChangeStrokeColor->setColorDialogTitle( tr( "Select Stroke Color" ) );
1014 btnChangeStrokeColor->setContext( u"symbology"_s );
1015 btnChangeStrokeColor->setShowNoColor( true );
1016 btnChangeStrokeColor->setNoColorString( tr( "Transparent Stroke" ) );
1017 btnChangeStrokeColor->setOpaqueColorString( tr( "Opaque Stroke" ) );
1018
1019 spinOffsetX->setClearValue( 0.0 );
1020 spinOffsetY->setClearValue( 0.0 );
1021
1023 connect( cboFillStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleFillSymbolLayerWidget::setBrushStyle );
1024 connect( btnChangeStrokeColor, &QgsColorButton::colorChanged, this, &QgsSimpleFillSymbolLayerWidget::setStrokeColor );
1025 connect( spinStrokeWidth, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleFillSymbolLayerWidget::strokeWidthChanged );
1026 connect( cboStrokeStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleFillSymbolLayerWidget::strokeStyleChanged );
1027 connect( cboJoinStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleFillSymbolLayerWidget::strokeStyleChanged );
1028 connect( spinOffsetX, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleFillSymbolLayerWidget::offsetChanged );
1029 connect( spinOffsetY, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleFillSymbolLayerWidget::offsetChanged );
1030
1031 mFillColorDDBtn->registerLinkedWidget( btnChangeColor );
1032 mStrokeColorDDBtn->registerLinkedWidget( btnChangeStrokeColor );
1033}
1034
1036{
1037 if ( layer->layerType() != "SimpleFill"_L1 )
1038 return;
1039
1040 // layer type is correct, we can do the cast
1041 mLayer = static_cast<QgsSimpleFillSymbolLayer *>( layer );
1042
1043 // set values
1044 btnChangeColor->blockSignals( true );
1045 btnChangeColor->setColor( mLayer->color() );
1046 btnChangeColor->blockSignals( false );
1047 cboFillStyle->blockSignals( true );
1048 cboFillStyle->setBrushStyle( mLayer->brushStyle() );
1049 cboFillStyle->blockSignals( false );
1050 btnChangeStrokeColor->blockSignals( true );
1051 btnChangeStrokeColor->setColor( mLayer->strokeColor() );
1052 btnChangeStrokeColor->blockSignals( false );
1053 cboStrokeStyle->blockSignals( true );
1054 cboStrokeStyle->setPenStyle( mLayer->strokeStyle() );
1055 cboStrokeStyle->blockSignals( false );
1056 spinStrokeWidth->blockSignals( true );
1057 spinStrokeWidth->setValue( mLayer->strokeWidth() );
1058 spinStrokeWidth->blockSignals( false );
1059 cboJoinStyle->blockSignals( true );
1060 cboJoinStyle->setPenJoinStyle( mLayer->penJoinStyle() );
1061 cboJoinStyle->blockSignals( false );
1062 spinOffsetX->blockSignals( true );
1063 spinOffsetX->setValue( mLayer->offset().x() );
1064 spinOffsetX->blockSignals( false );
1065 spinOffsetY->blockSignals( true );
1066 spinOffsetY->setValue( mLayer->offset().y() );
1067 spinOffsetY->blockSignals( false );
1068
1069 mStrokeWidthUnitWidget->blockSignals( true );
1070 mStrokeWidthUnitWidget->setUnit( mLayer->strokeWidthUnit() );
1071 mStrokeWidthUnitWidget->setMapUnitScale( mLayer->strokeWidthMapUnitScale() );
1072 mStrokeWidthUnitWidget->blockSignals( false );
1073 mOffsetUnitWidget->blockSignals( true );
1074 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
1075 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
1076 mOffsetUnitWidget->blockSignals( false );
1077
1085}
1086
1091
1093{
1094 mLayer->setColor( color );
1095 emit changed();
1096}
1097
1099{
1100 mLayer->setStrokeColor( color );
1101 emit changed();
1102}
1103
1104void QgsSimpleFillSymbolLayerWidget::setBrushStyle()
1105{
1106 mLayer->setBrushStyle( cboFillStyle->brushStyle() );
1107 emit changed();
1108}
1109
1110void QgsSimpleFillSymbolLayerWidget::strokeWidthChanged()
1111{
1112 mLayer->setStrokeWidth( spinStrokeWidth->value() );
1113 emit changed();
1114}
1115
1116void QgsSimpleFillSymbolLayerWidget::strokeStyleChanged()
1117{
1118 mLayer->setStrokeStyle( cboStrokeStyle->penStyle() );
1119 mLayer->setPenJoinStyle( cboJoinStyle->penJoinStyle() );
1120 emit changed();
1121}
1122
1123void QgsSimpleFillSymbolLayerWidget::offsetChanged()
1124{
1125 mLayer->setOffset( QPointF( spinOffsetX->value(), spinOffsetY->value() ) );
1126 emit changed();
1127}
1128
1129void QgsSimpleFillSymbolLayerWidget::mStrokeWidthUnitWidget_changed()
1130{
1131 if ( mLayer )
1132 {
1133 mLayer->setStrokeWidthUnit( mStrokeWidthUnitWidget->unit() );
1134 mLayer->setStrokeWidthMapUnitScale( mStrokeWidthUnitWidget->getMapUnitScale() );
1135 emit changed();
1136 }
1137}
1138
1139void QgsSimpleFillSymbolLayerWidget::mOffsetUnitWidget_changed()
1140{
1141 if ( mLayer )
1142 {
1143 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
1144 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
1145 emit changed();
1146 }
1147}
1148
1150
1152 : QgsSymbolLayerWidget( parent, vl )
1153{
1154 mLayer = nullptr;
1155
1156 setupUi( this );
1157
1158 mHorizontalAnchorComboBox->addItem( tr( "Left" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Left ) );
1159 mHorizontalAnchorComboBox->addItem( tr( "Horizontal Center" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Center ) );
1160 mHorizontalAnchorComboBox->addItem( tr( "Right" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Right ) );
1161
1162 mVerticalAnchorComboBox->addItem( tr( "Top" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Top ) );
1163 mVerticalAnchorComboBox->addItem( tr( "Vertical Center" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Center ) );
1164 mVerticalAnchorComboBox->addItem( tr( "Bottom" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Bottom ) );
1165
1166 connect( mSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsFilledMarkerSymbolLayerWidget::mSizeUnitWidget_changed );
1167 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsFilledMarkerSymbolLayerWidget::mOffsetUnitWidget_changed );
1168 connect( mHorizontalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsFilledMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged );
1169 connect( mVerticalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsFilledMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged );
1170 mSizeUnitWidget->setUnits(
1172 );
1173 mOffsetUnitWidget->setUnits(
1175 );
1176
1177 spinOffsetX->setClearValue( 0.0 );
1178 spinOffsetY->setClearValue( 0.0 );
1179 spinAngle->setClearValue( 0.0 );
1180
1181 //make a temporary symbol for the size assistant preview
1182 mAssistantPreviewSymbol = std::make_shared<QgsMarkerSymbol>();
1183
1184 if ( vectorLayer() )
1185 mSizeDDBtn->setSymbol( mAssistantPreviewSymbol );
1186
1187 int size = lstNames->iconSize().width();
1188 size = std::max( 30, static_cast<int>( std::round( Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance( 'X' ) * 3 ) ) );
1189 lstNames->setGridSize( QSize( size * 1.2, size * 1.2 ) );
1190 lstNames->setIconSize( QSize( size, size ) );
1191
1192 const double markerSize = size * 0.8;
1194 for ( const Qgis::MarkerShape shape : shapes )
1195 {
1196 QgsSimpleMarkerSymbolLayer *lyr = new QgsSimpleMarkerSymbolLayer( shape, markerSize );
1198 lyr->setColor( QColor( 200, 200, 200 ) );
1199 lyr->setStrokeColor( QColor( 0, 0, 0 ) );
1200 const QIcon icon
1202 QListWidgetItem *item = new QListWidgetItem( icon, QString(), lstNames );
1203 item->setData( Qt::UserRole, static_cast<int>( shape ) );
1204 item->setToolTip( QgsSimpleMarkerSymbolLayerBase::encodeShape( shape ) );
1205 delete lyr;
1206 }
1207 // show at least 3 rows
1208 lstNames->setMinimumHeight( lstNames->gridSize().height() * 3.1 );
1209
1210 connect( lstNames, &QListWidget::currentRowChanged, this, &QgsFilledMarkerSymbolLayerWidget::setShape );
1211 connect( spinSize, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsFilledMarkerSymbolLayerWidget::setSize );
1212 connect( spinAngle, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsFilledMarkerSymbolLayerWidget::setAngle );
1213 connect( spinOffsetX, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsFilledMarkerSymbolLayerWidget::setOffset );
1214 connect( spinOffsetY, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsFilledMarkerSymbolLayerWidget::setOffset );
1215 connect( this, &QgsSymbolLayerWidget::changed, this, &QgsFilledMarkerSymbolLayerWidget::updateAssistantSymbol );
1216}
1217
1219
1221{
1222 if ( layer->layerType() != "FilledMarker"_L1 )
1223 return;
1224
1225 // layer type is correct, we can do the cast
1226 mLayer = static_cast<QgsFilledMarkerSymbolLayer *>( layer );
1227
1228 // set values
1229 const Qgis::MarkerShape shape = mLayer->shape();
1230 for ( int i = 0; i < lstNames->count(); ++i )
1231 {
1232 if ( static_cast<Qgis::MarkerShape>( lstNames->item( i )->data( Qt::UserRole ).toInt() ) == shape )
1233 {
1234 lstNames->setCurrentRow( i );
1235 break;
1236 }
1237 }
1238 whileBlocking( spinSize )->setValue( mLayer->size() );
1239 whileBlocking( spinAngle )->setValue( mLayer->angle() );
1240 whileBlocking( spinOffsetX )->setValue( mLayer->offset().x() );
1241 whileBlocking( spinOffsetY )->setValue( mLayer->offset().y() );
1242
1243 mSizeUnitWidget->blockSignals( true );
1244 mSizeUnitWidget->setUnit( mLayer->sizeUnit() );
1245 mSizeUnitWidget->setMapUnitScale( mLayer->sizeMapUnitScale() );
1246 mSizeUnitWidget->blockSignals( false );
1247 mOffsetUnitWidget->blockSignals( true );
1248 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
1249 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
1250 mOffsetUnitWidget->blockSignals( false );
1251
1252 //anchor points
1253 whileBlocking( mHorizontalAnchorComboBox )->setCurrentIndex( mHorizontalAnchorComboBox->findData( QVariant::fromValue( mLayer->horizontalAnchorPoint() ) ) );
1254 whileBlocking( mVerticalAnchorComboBox )->setCurrentIndex( mVerticalAnchorComboBox->findData( QVariant::fromValue( mLayer->verticalAnchorPoint() ) ) );
1255
1262
1263 updateAssistantSymbol();
1264}
1265
1270
1271void QgsFilledMarkerSymbolLayerWidget::setShape()
1272{
1273 mLayer->setShape( static_cast<Qgis::MarkerShape>( lstNames->currentItem()->data( Qt::UserRole ).toInt() ) );
1274 emit changed();
1275}
1276
1277void QgsFilledMarkerSymbolLayerWidget::setSize()
1278{
1279 mLayer->setSize( spinSize->value() );
1280 emit changed();
1281}
1282
1283void QgsFilledMarkerSymbolLayerWidget::setAngle()
1284{
1285 mLayer->setAngle( spinAngle->value() );
1286 emit changed();
1287}
1288
1289void QgsFilledMarkerSymbolLayerWidget::setOffset()
1290{
1291 mLayer->setOffset( QPointF( spinOffsetX->value(), spinOffsetY->value() ) );
1292 emit changed();
1293}
1294
1295void QgsFilledMarkerSymbolLayerWidget::mSizeUnitWidget_changed()
1296{
1297 if ( mLayer )
1298 {
1299 mLayer->setSizeUnit( mSizeUnitWidget->unit() );
1300 mLayer->setSizeMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
1301 emit changed();
1302 }
1303}
1304
1305void QgsFilledMarkerSymbolLayerWidget::mOffsetUnitWidget_changed()
1306{
1307 if ( mLayer )
1308 {
1309 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
1310 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
1311 emit changed();
1312 }
1313}
1314
1315void QgsFilledMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged( int )
1316{
1317 if ( mLayer )
1318 {
1319 mLayer->setHorizontalAnchorPoint( mHorizontalAnchorComboBox->currentData().value<Qgis::HorizontalAnchorPoint>() );
1320 emit changed();
1321 }
1322}
1323
1324void QgsFilledMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged( int )
1325{
1326 if ( mLayer )
1327 {
1328 mLayer->setVerticalAnchorPoint( mVerticalAnchorComboBox->currentData().value< Qgis::VerticalAnchorPoint >() );
1329 emit changed();
1330 }
1331}
1332
1333void QgsFilledMarkerSymbolLayerWidget::updateAssistantSymbol()
1334{
1335 for ( int i = mAssistantPreviewSymbol->symbolLayerCount() - 1; i >= 0; --i )
1336 {
1337 mAssistantPreviewSymbol->deleteSymbolLayer( i );
1338 }
1339 mAssistantPreviewSymbol->appendSymbolLayer( mLayer->clone() );
1340 const QgsProperty ddSize = mLayer->dataDefinedProperties().property( QgsSymbolLayer::Property::Size );
1341 if ( ddSize )
1342 mAssistantPreviewSymbol->setDataDefinedSize( ddSize );
1343}
1344
1345
1347
1349 : QgsSymbolLayerWidget( parent, vl )
1350{
1351 mLayer = nullptr;
1352
1353 setupUi( this );
1354 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsGradientFillSymbolLayerWidget::mOffsetUnitWidget_changed );
1355 connect( mSpinAngle, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsGradientFillSymbolLayerWidget::mSpinAngle_valueChanged );
1356 mOffsetUnitWidget->setUnits(
1358 );
1359
1360 btnColorRamp->setShowGradientOnly( true );
1361
1362 btnChangeColor->setAllowOpacity( true );
1363 btnChangeColor->setColorDialogTitle( tr( "Select Gradient Color" ) );
1364 btnChangeColor->setContext( u"symbology"_s );
1365 btnChangeColor->setShowNoColor( true );
1366 btnChangeColor->setNoColorString( tr( "Transparent" ) );
1367 btnChangeColor->setOpaqueColorString( tr( "Opaque" ) );
1368 btnChangeColor2->setAllowOpacity( true );
1369 btnChangeColor2->setColorDialogTitle( tr( "Select Gradient Color" ) );
1370 btnChangeColor2->setContext( u"symbology"_s );
1371 btnChangeColor2->setShowNoColor( true );
1372 btnChangeColor2->setNoColorString( tr( "Transparent" ) );
1373 btnChangeColor2->setOpaqueColorString( tr( "Opaque" ) );
1374
1375 mStartColorDDBtn->registerLinkedWidget( btnChangeColor );
1376 mEndColorDDBtn->registerLinkedWidget( btnChangeColor2 );
1377
1378 spinOffsetX->setClearValue( 0.0 );
1379 spinOffsetY->setClearValue( 0.0 );
1380 mSpinAngle->setClearValue( 0.0 );
1381
1385 connect( cboGradientType, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsGradientFillSymbolLayerWidget::setGradientType );
1386 connect( cboCoordinateMode, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsGradientFillSymbolLayerWidget::setCoordinateMode );
1387 connect( cboGradientSpread, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsGradientFillSymbolLayerWidget::setGradientSpread );
1388 connect( radioTwoColor, &QAbstractButton::toggled, this, &QgsGradientFillSymbolLayerWidget::colorModeChanged );
1389 connect( spinOffsetX, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsGradientFillSymbolLayerWidget::offsetChanged );
1390 connect( spinOffsetY, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsGradientFillSymbolLayerWidget::offsetChanged );
1391 connect( spinRefPoint1X, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsGradientFillSymbolLayerWidget::referencePointChanged );
1392 connect( spinRefPoint1Y, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsGradientFillSymbolLayerWidget::referencePointChanged );
1393 connect( checkRefPoint1Centroid, &QAbstractButton::toggled, this, &QgsGradientFillSymbolLayerWidget::referencePointChanged );
1394 connect( spinRefPoint2X, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsGradientFillSymbolLayerWidget::referencePointChanged );
1395 connect( spinRefPoint2Y, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsGradientFillSymbolLayerWidget::referencePointChanged );
1396 connect( checkRefPoint2Centroid, &QAbstractButton::toggled, this, &QgsGradientFillSymbolLayerWidget::referencePointChanged );
1397}
1398
1400{
1401 if ( layer->layerType() != "GradientFill"_L1 )
1402 return;
1403
1404 // layer type is correct, we can do the cast
1405 mLayer = static_cast<QgsGradientFillSymbolLayer *>( layer );
1406
1407 // set values
1408 btnChangeColor->blockSignals( true );
1409 btnChangeColor->setColor( mLayer->color() );
1410 btnChangeColor->blockSignals( false );
1411 btnChangeColor2->blockSignals( true );
1412 btnChangeColor2->setColor( mLayer->color2() );
1413 btnChangeColor2->blockSignals( false );
1414
1415 if ( mLayer->gradientColorType() == Qgis::GradientColorSource::SimpleTwoColor )
1416 {
1417 radioTwoColor->setChecked( true );
1418 btnColorRamp->setEnabled( false );
1419 }
1420 else
1421 {
1422 radioColorRamp->setChecked( true );
1423 btnChangeColor->setEnabled( false );
1424 btnChangeColor2->setEnabled( false );
1425 }
1426
1427 // set source color ramp
1428 if ( mLayer->colorRamp() )
1429 {
1430 btnColorRamp->blockSignals( true );
1431 btnColorRamp->setColorRamp( mLayer->colorRamp() );
1432 btnColorRamp->blockSignals( false );
1433 }
1434
1435 cboGradientType->blockSignals( true );
1436 switch ( mLayer->gradientType() )
1437 {
1439 cboGradientType->setCurrentIndex( 0 );
1440 break;
1442 cboGradientType->setCurrentIndex( 1 );
1443 break;
1445 cboGradientType->setCurrentIndex( 2 );
1446 break;
1447 }
1448 cboGradientType->blockSignals( false );
1449
1450 cboCoordinateMode->blockSignals( true );
1451 switch ( mLayer->coordinateMode() )
1452 {
1454 cboCoordinateMode->setCurrentIndex( 1 );
1455 checkRefPoint1Centroid->setEnabled( false );
1456 checkRefPoint2Centroid->setEnabled( false );
1457 break;
1459 default:
1460 cboCoordinateMode->setCurrentIndex( 0 );
1461 break;
1462 }
1463 cboCoordinateMode->blockSignals( false );
1464
1465 cboGradientSpread->blockSignals( true );
1466 switch ( mLayer->gradientSpread() )
1467 {
1469 cboGradientSpread->setCurrentIndex( 0 );
1470 break;
1472 cboGradientSpread->setCurrentIndex( 1 );
1473 break;
1475 cboGradientSpread->setCurrentIndex( 2 );
1476 break;
1477 }
1478 cboGradientSpread->blockSignals( false );
1479
1480 spinRefPoint1X->blockSignals( true );
1481 spinRefPoint1X->setValue( mLayer->referencePoint1().x() );
1482 spinRefPoint1X->blockSignals( false );
1483 spinRefPoint1Y->blockSignals( true );
1484 spinRefPoint1Y->setValue( mLayer->referencePoint1().y() );
1485 spinRefPoint1Y->blockSignals( false );
1486 checkRefPoint1Centroid->blockSignals( true );
1487 checkRefPoint1Centroid->setChecked( mLayer->referencePoint1IsCentroid() );
1488 if ( mLayer->referencePoint1IsCentroid() )
1489 {
1490 spinRefPoint1X->setEnabled( false );
1491 spinRefPoint1Y->setEnabled( false );
1492 }
1493 checkRefPoint1Centroid->blockSignals( false );
1494 spinRefPoint2X->blockSignals( true );
1495 spinRefPoint2X->setValue( mLayer->referencePoint2().x() );
1496 spinRefPoint2X->blockSignals( false );
1497 spinRefPoint2Y->blockSignals( true );
1498 spinRefPoint2Y->setValue( mLayer->referencePoint2().y() );
1499 spinRefPoint2Y->blockSignals( false );
1500 checkRefPoint2Centroid->blockSignals( true );
1501 checkRefPoint2Centroid->setChecked( mLayer->referencePoint2IsCentroid() );
1502 if ( mLayer->referencePoint2IsCentroid() )
1503 {
1504 spinRefPoint2X->setEnabled( false );
1505 spinRefPoint2Y->setEnabled( false );
1506 }
1507 checkRefPoint2Centroid->blockSignals( false );
1508
1509 spinOffsetX->blockSignals( true );
1510 spinOffsetX->setValue( mLayer->offset().x() );
1511 spinOffsetX->blockSignals( false );
1512 spinOffsetY->blockSignals( true );
1513 spinOffsetY->setValue( mLayer->offset().y() );
1514 spinOffsetY->blockSignals( false );
1515 mSpinAngle->blockSignals( true );
1516 mSpinAngle->setValue( mLayer->angle() );
1517 mSpinAngle->blockSignals( false );
1518
1519 mOffsetUnitWidget->blockSignals( true );
1520 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
1521 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
1522 mOffsetUnitWidget->blockSignals( false );
1523
1537}
1538
1543
1545{
1546 mLayer->setColor( color );
1547 emit changed();
1548}
1549
1551{
1552 mLayer->setColor2( color );
1553 emit changed();
1554}
1555
1556void QgsGradientFillSymbolLayerWidget::colorModeChanged()
1557{
1558 if ( radioTwoColor->isChecked() )
1559 {
1561 }
1562 else
1563 {
1564 mLayer->setGradientColorType( Qgis::GradientColorSource::ColorRamp );
1565 }
1566 emit changed();
1567}
1568
1570{
1571 if ( btnColorRamp->isNull() )
1572 return;
1573
1574 mLayer->setColorRamp( btnColorRamp->colorRamp()->clone() );
1575 emit changed();
1576}
1577
1579{
1580 switch ( index )
1581 {
1582 case 0:
1583 mLayer->setGradientType( Qgis::GradientType::Linear );
1584 //set sensible default reference points
1585 spinRefPoint1X->setValue( 0.5 );
1586 spinRefPoint1Y->setValue( 0 );
1587 spinRefPoint2X->setValue( 0.5 );
1588 spinRefPoint2Y->setValue( 1 );
1589 break;
1590 case 1:
1591 mLayer->setGradientType( Qgis::GradientType::Radial );
1592 //set sensible default reference points
1593 spinRefPoint1X->setValue( 0 );
1594 spinRefPoint1Y->setValue( 0 );
1595 spinRefPoint2X->setValue( 1 );
1596 spinRefPoint2Y->setValue( 1 );
1597 break;
1598 case 2:
1599 mLayer->setGradientType( Qgis::GradientType::Conical );
1600 spinRefPoint1X->setValue( 0.5 );
1601 spinRefPoint1Y->setValue( 0.5 );
1602 spinRefPoint2X->setValue( 1 );
1603 spinRefPoint2Y->setValue( 1 );
1604 break;
1605 }
1606 emit changed();
1607}
1608
1610{
1611 switch ( index )
1612 {
1613 case 0:
1614 //feature coordinate mode
1616 //allow choice of centroid reference positions
1617 checkRefPoint1Centroid->setEnabled( true );
1618 checkRefPoint2Centroid->setEnabled( true );
1619 break;
1620 case 1:
1621 //viewport coordinate mode
1623 //disable choice of centroid reference positions
1624 checkRefPoint1Centroid->setChecked( Qt::Unchecked );
1625 checkRefPoint1Centroid->setEnabled( false );
1626 checkRefPoint2Centroid->setChecked( Qt::Unchecked );
1627 checkRefPoint2Centroid->setEnabled( false );
1628 break;
1629 }
1630
1631 emit changed();
1632}
1633
1635{
1636 switch ( index )
1637 {
1638 case 0:
1639 mLayer->setGradientSpread( Qgis::GradientSpread::Pad );
1640 break;
1641 case 1:
1642 mLayer->setGradientSpread( Qgis::GradientSpread::Repeat );
1643 break;
1644 case 2:
1645 mLayer->setGradientSpread( Qgis::GradientSpread::Reflect );
1646 break;
1647 }
1648
1649 emit changed();
1650}
1651
1652void QgsGradientFillSymbolLayerWidget::offsetChanged()
1653{
1654 mLayer->setOffset( QPointF( spinOffsetX->value(), spinOffsetY->value() ) );
1655 emit changed();
1656}
1657
1658void QgsGradientFillSymbolLayerWidget::referencePointChanged()
1659{
1660 mLayer->setReferencePoint1( QPointF( spinRefPoint1X->value(), spinRefPoint1Y->value() ) );
1661 mLayer->setReferencePoint1IsCentroid( checkRefPoint1Centroid->isChecked() );
1662 mLayer->setReferencePoint2( QPointF( spinRefPoint2X->value(), spinRefPoint2Y->value() ) );
1663 mLayer->setReferencePoint2IsCentroid( checkRefPoint2Centroid->isChecked() );
1664 emit changed();
1665}
1666
1667void QgsGradientFillSymbolLayerWidget::mSpinAngle_valueChanged( double value )
1668{
1669 mLayer->setAngle( value );
1670 emit changed();
1671}
1672
1673void QgsGradientFillSymbolLayerWidget::mOffsetUnitWidget_changed()
1674{
1675 if ( mLayer )
1676 {
1677 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
1678 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
1679 emit changed();
1680 }
1681}
1682
1684
1686 : QgsSymbolLayerWidget( parent, vl )
1687{
1688 mLayer = nullptr;
1689
1690 setupUi( this );
1691 connect( mSpinBlurRadius, qOverload<int>( &QSpinBox::valueChanged ), this, &QgsShapeburstFillSymbolLayerWidget::mSpinBlurRadius_valueChanged );
1692 connect( mSpinMaxDistance, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, &QgsShapeburstFillSymbolLayerWidget::mSpinMaxDistance_valueChanged );
1693 connect( mDistanceUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsShapeburstFillSymbolLayerWidget::mDistanceUnitWidget_changed );
1694 connect( mRadioUseWholeShape, &QRadioButton::toggled, this, &QgsShapeburstFillSymbolLayerWidget::mRadioUseWholeShape_toggled );
1695 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsShapeburstFillSymbolLayerWidget::mOffsetUnitWidget_changed );
1696 connect( mIgnoreRingsCheckBox, &QCheckBox::stateChanged, this, &QgsShapeburstFillSymbolLayerWidget::mIgnoreRingsCheckBox_stateChanged );
1697 mDistanceUnitWidget->setUnits(
1699 );
1700 mOffsetUnitWidget->setUnits(
1702 );
1703
1704 QButtonGroup *group1 = new QButtonGroup( this );
1705 group1->addButton( radioColorRamp );
1706 group1->addButton( radioTwoColor );
1707 QButtonGroup *group2 = new QButtonGroup( this );
1708 group2->addButton( mRadioUseMaxDistance );
1709 group2->addButton( mRadioUseWholeShape );
1710 btnChangeColor->setAllowOpacity( true );
1711 btnChangeColor->setColorDialogTitle( tr( "Select Gradient Color" ) );
1712 btnChangeColor->setContext( u"symbology"_s );
1713 btnChangeColor->setShowNoColor( true );
1714 btnChangeColor->setNoColorString( tr( "Transparent" ) );
1715 btnChangeColor->setOpaqueColorString( tr( "Opaque" ) );
1716 btnChangeColor2->setAllowOpacity( true );
1717 btnChangeColor2->setColorDialogTitle( tr( "Select Gradient Color" ) );
1718 btnChangeColor2->setContext( u"symbology"_s );
1719 btnChangeColor2->setShowNoColor( true );
1720 btnChangeColor2->setNoColorString( tr( "Transparent" ) );
1721 btnChangeColor2->setOpaqueColorString( tr( "Opaque" ) );
1722
1723 mStartColorDDBtn->registerLinkedWidget( btnChangeColor );
1724 mEndColorDDBtn->registerLinkedWidget( btnChangeColor2 );
1725
1726 spinOffsetX->setClearValue( 0.0 );
1727 spinOffsetY->setClearValue( 0.0 );
1728 mSpinMaxDistance->setClearValue( 5.0 );
1729
1730 btnColorRamp->setShowGradientOnly( true );
1731
1732 connect( btnColorRamp, &QgsColorRampButton::colorRampChanged, this, &QgsShapeburstFillSymbolLayerWidget::applyColorRamp );
1733
1736 connect( radioTwoColor, &QAbstractButton::toggled, this, &QgsShapeburstFillSymbolLayerWidget::colorModeChanged );
1737 connect( spinOffsetX, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsShapeburstFillSymbolLayerWidget::offsetChanged );
1738 connect( spinOffsetY, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsShapeburstFillSymbolLayerWidget::offsetChanged );
1739
1740 connect( mBlurSlider, &QAbstractSlider::valueChanged, mSpinBlurRadius, &QSpinBox::setValue );
1741 connect( mSpinBlurRadius, static_cast<void ( QSpinBox::* )( int )>( &QSpinBox::valueChanged ), mBlurSlider, &QAbstractSlider::setValue );
1742}
1743
1745{
1746 if ( layer->layerType() != "ShapeburstFill"_L1 )
1747 return;
1748
1749 // layer type is correct, we can do the cast
1750 mLayer = static_cast<QgsShapeburstFillSymbolLayer *>( layer );
1751
1752 // set values
1753 btnChangeColor->blockSignals( true );
1754 btnChangeColor->setColor( mLayer->color() );
1755 btnChangeColor->blockSignals( false );
1756 btnChangeColor2->blockSignals( true );
1757 btnChangeColor2->setColor( mLayer->color2() );
1758 btnChangeColor2->blockSignals( false );
1759
1761 {
1762 radioTwoColor->setChecked( true );
1763 btnColorRamp->setEnabled( false );
1764 }
1765 else
1766 {
1767 radioColorRamp->setChecked( true );
1768 btnChangeColor->setEnabled( false );
1769 btnChangeColor2->setEnabled( false );
1770 }
1771
1772 mSpinBlurRadius->blockSignals( true );
1773 mBlurSlider->blockSignals( true );
1774 mSpinBlurRadius->setValue( mLayer->blurRadius() );
1775 mBlurSlider->setValue( mLayer->blurRadius() );
1776 mSpinBlurRadius->blockSignals( false );
1777 mBlurSlider->blockSignals( false );
1778
1779 mSpinMaxDistance->blockSignals( true );
1780 mSpinMaxDistance->setValue( mLayer->maxDistance() );
1781 mSpinMaxDistance->blockSignals( false );
1782
1783 mRadioUseWholeShape->blockSignals( true );
1784 mRadioUseMaxDistance->blockSignals( true );
1785 if ( mLayer->useWholeShape() )
1786 {
1787 mRadioUseWholeShape->setChecked( true );
1788 mSpinMaxDistance->setEnabled( false );
1789 mDistanceUnitWidget->setEnabled( false );
1790 }
1791 else
1792 {
1793 mRadioUseMaxDistance->setChecked( true );
1794 mSpinMaxDistance->setEnabled( true );
1795 mDistanceUnitWidget->setEnabled( true );
1796 }
1797 mRadioUseWholeShape->blockSignals( false );
1798 mRadioUseMaxDistance->blockSignals( false );
1799
1800 mDistanceUnitWidget->blockSignals( true );
1801 mDistanceUnitWidget->setUnit( mLayer->distanceUnit() );
1802 mDistanceUnitWidget->setMapUnitScale( mLayer->distanceMapUnitScale() );
1803 mDistanceUnitWidget->blockSignals( false );
1804
1805 mIgnoreRingsCheckBox->blockSignals( true );
1806 mIgnoreRingsCheckBox->setCheckState( mLayer->ignoreRings() ? Qt::Checked : Qt::Unchecked );
1807 mIgnoreRingsCheckBox->blockSignals( false );
1808
1809 // set source color ramp
1810 if ( mLayer->colorRamp() )
1811 {
1812 btnColorRamp->blockSignals( true );
1813 btnColorRamp->setColorRamp( mLayer->colorRamp() );
1814 btnColorRamp->blockSignals( false );
1815 }
1816
1817 spinOffsetX->blockSignals( true );
1818 spinOffsetX->setValue( mLayer->offset().x() );
1819 spinOffsetX->blockSignals( false );
1820 spinOffsetY->blockSignals( true );
1821 spinOffsetY->setValue( mLayer->offset().y() );
1822 spinOffsetY->blockSignals( false );
1823 mOffsetUnitWidget->blockSignals( true );
1824 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
1825 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
1826 mOffsetUnitWidget->blockSignals( false );
1827
1835}
1836
1841
1843{
1844 if ( mLayer )
1845 {
1846 mLayer->setColor( color );
1847 emit changed();
1848 }
1849}
1850
1852{
1853 if ( mLayer )
1854 {
1855 mLayer->setColor2( color );
1856 emit changed();
1857 }
1858}
1859
1860void QgsShapeburstFillSymbolLayerWidget::colorModeChanged()
1861{
1862 if ( !mLayer )
1863 {
1864 return;
1865 }
1866
1867 if ( radioTwoColor->isChecked() )
1868 {
1870 }
1871 else
1872 {
1874 }
1875 emit changed();
1876}
1877
1878void QgsShapeburstFillSymbolLayerWidget::mSpinBlurRadius_valueChanged( int value )
1879{
1880 if ( mLayer )
1881 {
1882 mLayer->setBlurRadius( value );
1883 emit changed();
1884 }
1885}
1886
1887void QgsShapeburstFillSymbolLayerWidget::mSpinMaxDistance_valueChanged( double value )
1888{
1889 if ( mLayer )
1890 {
1891 mLayer->setMaxDistance( value );
1892 emit changed();
1893 }
1894}
1895
1896void QgsShapeburstFillSymbolLayerWidget::mDistanceUnitWidget_changed()
1897{
1898 if ( mLayer )
1899 {
1900 mLayer->setDistanceUnit( mDistanceUnitWidget->unit() );
1901 mLayer->setDistanceMapUnitScale( mDistanceUnitWidget->getMapUnitScale() );
1902 emit changed();
1903 }
1904}
1905
1906void QgsShapeburstFillSymbolLayerWidget::mRadioUseWholeShape_toggled( bool value )
1907{
1908 if ( mLayer )
1909 {
1910 mLayer->setUseWholeShape( value );
1911 mDistanceUnitWidget->setEnabled( !value );
1912 emit changed();
1913 }
1914}
1915
1916void QgsShapeburstFillSymbolLayerWidget::applyColorRamp()
1917{
1918 QgsColorRamp *ramp = btnColorRamp->colorRamp();
1919 if ( !ramp )
1920 return;
1921
1922 mLayer->setColorRamp( ramp );
1923 emit changed();
1924}
1925
1926void QgsShapeburstFillSymbolLayerWidget::offsetChanged()
1927{
1928 if ( mLayer )
1929 {
1930 mLayer->setOffset( QPointF( spinOffsetX->value(), spinOffsetY->value() ) );
1931 emit changed();
1932 }
1933}
1934
1935void QgsShapeburstFillSymbolLayerWidget::mOffsetUnitWidget_changed()
1936{
1937 if ( mLayer )
1938 {
1939 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
1940 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
1941 emit changed();
1942 }
1943}
1944
1945
1946void QgsShapeburstFillSymbolLayerWidget::mIgnoreRingsCheckBox_stateChanged( int state )
1947{
1948 const bool checked = ( state == Qt::Checked );
1949 mLayer->setIgnoreRings( checked );
1950 emit changed();
1951}
1952
1954
1956 : QgsSymbolLayerWidget( parent, vl )
1957 , mSymbolType( symbolType )
1958{
1959 mLayer = nullptr;
1960
1961 setupUi( this );
1962 connect( mIntervalUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsTemplatedLineSymbolLayerWidget::mIntervalUnitWidget_changed );
1963 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsTemplatedLineSymbolLayerWidget::mOffsetUnitWidget_changed );
1964 connect( mOffsetAlongLineUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsTemplatedLineSymbolLayerWidget::mOffsetAlongLineUnitWidget_changed );
1965 connect( mAverageAngleUnit, &QgsUnitSelectionWidget::changed, this, &QgsTemplatedLineSymbolLayerWidget::averageAngleUnitChanged );
1966 connect( mBlankSegmentsUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsTemplatedLineSymbolLayerWidget::blankSegmentsUnitChanged );
1967
1970 mIntervalUnitWidget->setUnits( units );
1971 mOffsetUnitWidget->setUnits( units );
1972 mOffsetAlongLineUnitWidget->setUnits( QgsUnitTypes::RenderUnitList( units ) << Qgis::RenderUnit::Percentage );
1973 mAverageAngleUnit->setUnits( units );
1974 mIntervalUnitWidget->setUnits( units );
1975 mBlankSegmentsUnitWidget->setUnits( units );
1976 mTrimDistanceStartUnitWidget->setUnits( QgsUnitTypes::RenderUnitList( units ) << Qgis::RenderUnit::Percentage );
1977 mTrimDistanceEndUnitWidget->setUnits( QgsUnitTypes::RenderUnitList( units ) << Qgis::RenderUnit::Percentage );
1978
1979 mRingFilterComboBox->addItem( QgsApplication::getThemeIcon( u"mIconAllRings.svg"_s ), tr( "All Rings" ), QgsLineSymbolLayer::AllRings );
1980 mRingFilterComboBox->addItem( QgsApplication::getThemeIcon( u"mIconExteriorRing.svg"_s ), tr( "Exterior Ring Only" ), QgsLineSymbolLayer::ExteriorRingOnly );
1981 mRingFilterComboBox->addItem( QgsApplication::getThemeIcon( u"mIconInteriorRings.svg"_s ), tr( "Interior Rings Only" ), QgsLineSymbolLayer::InteriorRingsOnly );
1982 connect( mRingFilterComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this]( int ) {
1983 if ( mLayer )
1984 {
1985 mLayer->setRingFilter( static_cast<QgsLineSymbolLayer::RenderRingFilter>( mRingFilterComboBox->currentData().toInt() ) );
1986 emit changed();
1987 }
1988 } );
1989
1990 spinOffset->setClearValue( 0.0 );
1991 mSpinOffsetAlongLine->setClearValue( 0.0 );
1992 mHashRotationSpinBox->setClearValue( 0 );
1993 mSpinAverageAngleLength->setClearValue( 4.0 );
1994 mTrimStartDistanceSpin->setClearValue( 0.0 );
1995 mTrimDistanceEndSpin->setClearValue( 0.0 );
1996
1997 connect( spinInterval, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsTemplatedLineSymbolLayerWidget::setInterval );
1998 connect( mSpinOffsetAlongLine, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsTemplatedLineSymbolLayerWidget::setOffsetAlongLine );
1999 connect( mSpinHashLength, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsTemplatedLineSymbolLayerWidget::setHashLength );
2000 connect( mHashRotationSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsTemplatedLineSymbolLayerWidget::setHashAngle );
2001 connect( chkRotateMarker, &QAbstractButton::clicked, this, &QgsTemplatedLineSymbolLayerWidget::setRotate );
2002 connect( spinOffset, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsTemplatedLineSymbolLayerWidget::setOffset );
2003 connect( mSpinAverageAngleLength, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsTemplatedLineSymbolLayerWidget::setAverageAngle );
2004
2005 QActionGroup *actionGroup = new QActionGroup( this );
2006 actionGroup->setExclusionPolicy( QActionGroup::ExclusionPolicy::Exclusive );
2007 actionGroup->addAction( mEditBlankSegmentsAction );
2008 actionGroup->addAction( mAddExtraItemAction );
2009 actionGroup->addAction( mModifyExtraItemAction );
2010
2011 mEditBlankSegmentsBtn->setDefaultAction( mEditBlankSegmentsAction );
2012 connect( mEditBlankSegmentsAction, &QAction::triggered, this, &QgsMarkerLineSymbolLayerWidget::toggleMapToolEditBlankSegments );
2013
2014 mAddExtraItemBtn->setDefaultAction( mAddExtraItemAction );
2015 connect( mAddExtraItemAction, &QAction::triggered, this, &QgsMarkerLineSymbolLayerWidget::toggleMapToolAddExtraItem );
2016
2017 mModifyExtraItemBtn->setDefaultAction( mModifyExtraItemAction );
2018 connect( mModifyExtraItemAction, &QAction::triggered, this, &QgsMarkerLineSymbolLayerWidget::toggleMapToolModifyExtraItem );
2019
2020 connect( mCheckInterval, &QCheckBox::toggled, this, &QgsTemplatedLineSymbolLayerWidget::setPlacement );
2021 connect( mCheckVertex, &QCheckBox::toggled, this, &QgsTemplatedLineSymbolLayerWidget::setPlacement );
2022 connect( mCheckVertexLast, &QCheckBox::toggled, this, &QgsTemplatedLineSymbolLayerWidget::setPlacement );
2023 connect( mCheckVertexFirst, &QCheckBox::toggled, this, &QgsTemplatedLineSymbolLayerWidget::setPlacement );
2024 connect( mCheckCentralPoint, &QCheckBox::toggled, this, &QgsTemplatedLineSymbolLayerWidget::setPlacement );
2025 connect( mCheckCurvePoint, &QCheckBox::toggled, this, &QgsTemplatedLineSymbolLayerWidget::setPlacement );
2026 connect( mCheckSegmentCentralPoint, &QCheckBox::toggled, this, &QgsTemplatedLineSymbolLayerWidget::setPlacement );
2027
2028 connect( mCheckPlaceOnEveryPart, &QCheckBox::toggled, this, [this] {
2029 if ( mLayer )
2030 {
2031 mLayer->setPlaceOnEveryPart( mCheckPlaceOnEveryPart->isChecked() );
2032 emit changed();
2033 }
2034 } );
2035
2036 connect( mTrimStartDistanceSpin, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, [this]( double value ) {
2037 if ( !mLayer )
2038 return;
2039
2040 mLayer->setTrimDistanceStart( value );
2041 emit changed();
2042 } );
2043 connect( mTrimDistanceStartUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
2044 if ( !mLayer )
2045 return;
2046
2047 mLayer->setTrimDistanceStartUnit( mTrimDistanceStartUnitWidget->unit() );
2048 mLayer->setTrimDistanceStartMapUnitScale( mTrimDistanceStartUnitWidget->getMapUnitScale() );
2049 emit changed();
2050 } );
2051 connect( mTrimDistanceEndSpin, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, [this]( double value ) {
2052 if ( !mLayer )
2053 return;
2054
2055 mLayer->setTrimDistanceEnd( value );
2056 emit changed();
2057 } );
2058 connect( mTrimDistanceEndUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
2059 if ( !mLayer )
2060 return;
2061
2062 mLayer->setTrimDistanceEndUnit( mTrimDistanceEndUnitWidget->unit() );
2063 mLayer->setTrimDistanceEndMapUnitScale( mTrimDistanceEndUnitWidget->getMapUnitScale() );
2064 emit changed();
2065 } );
2066
2067 switch ( mSymbolType )
2068 {
2070 {
2071 connect( mHashLengthUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsTemplatedLineSymbolLayerWidget::hashLengthUnitWidgetChanged );
2072 mHashLengthUnitWidget->setUnits(
2074 );
2075 mPlacementLabel->setText( tr( "Hash placement" ) );
2076 chkRotateMarker->setText( tr( "Rotate hash to follow line direction" ) );
2077 mSpinOffsetAlongLine->setToolTip( tr( "Offset hashes in line direction if positive or in opposite line direction if negative" ) );
2078 mHashLengthLabel->setVisible( true );
2079 mSpinHashLength->setVisible( true );
2080 mHashLengthUnitWidget->setVisible( true );
2081 mHashLengthDDBtn->setVisible( true );
2082 mHashRotationLabel->setVisible( true );
2083 mHashRotationSpinBox->setVisible( true );
2084 mHashRotationDDBtn->setVisible( true );
2085 break;
2086 }
2087
2089 mPlacementLabel->setText( tr( "Marker placement" ) );
2090 chkRotateMarker->setText( tr( "Rotate marker to follow line direction" ) );
2091 mSpinOffsetAlongLine->setToolTip( tr( "Offset markers in line direction if positive or in opposite line direction if negative" ) );
2092 mHashLengthLabel->setVisible( false );
2093 mSpinHashLength->setVisible( false );
2094 mHashLengthUnitWidget->setVisible( false );
2095 mHashLengthDDBtn->setVisible( false );
2096 mHashRotationLabel->setVisible( false );
2097 mHashRotationSpinBox->setVisible( false );
2098 mHashRotationDDBtn->setVisible( false );
2099 }
2100}
2101
2103{
2104 // to avoid deleting blank segments / extra items map tool while already deleting them in this destructor
2105 if ( context().mapCanvas() )
2106 {
2107 disconnect( context().mapCanvas(), &QgsMapCanvas::mapToolSet, this, nullptr );
2108 }
2109}
2110
2112{
2113 if ( event->type() == QEvent::Show )
2114 {
2115 // Per feature customization buttons are enabled only in dock mode. That requires for this widget to be
2116 // parented which is not the case when we create the widget. So we update on show event
2117 updatePerFeatureCustomizationWidget();
2118 }
2119
2120 return QgsSymbolLayerWidget::event( event );
2121}
2122
2124{
2125 switch ( mSymbolType )
2126 {
2128 if ( layer->layerType() != "HashLine"_L1 )
2129 return;
2130 break;
2131
2133 if ( layer->layerType() != "MarkerLine"_L1 )
2134 return;
2135 }
2136
2137 // layer type is correct, we can do the cast
2138 mLayer = static_cast<QgsTemplatedLineSymbolLayerBase *>( layer );
2139
2140 // set values
2141 spinInterval->blockSignals( true );
2142 spinInterval->setValue( mLayer->interval() );
2143 spinInterval->blockSignals( false );
2144 mSpinOffsetAlongLine->blockSignals( true );
2145 mSpinOffsetAlongLine->setValue( mLayer->offsetAlongLine() );
2146 mSpinOffsetAlongLine->blockSignals( false );
2147
2148 chkRotateMarker->blockSignals( true );
2149 chkRotateMarker->setChecked( mLayer->rotateSymbols() );
2150 chkRotateMarker->blockSignals( false );
2151 spinOffset->blockSignals( true );
2152 spinOffset->setValue( mLayer->offset() );
2153 spinOffset->blockSignals( false );
2154
2155 whileBlocking( mTrimStartDistanceSpin )->setValue( mLayer->trimDistanceStart() );
2156 whileBlocking( mTrimDistanceEndSpin )->setValue( mLayer->trimDistanceEnd() );
2157
2158 whileBlocking( mCheckInterval )->setChecked( mLayer->placements() & Qgis::MarkerLinePlacement::Interval );
2159 whileBlocking( mCheckVertex )->setChecked( mLayer->placements() & Qgis::MarkerLinePlacement::InnerVertices || mLayer->placements() & Qgis::MarkerLinePlacement::Vertex );
2160 whileBlocking( mCheckVertexFirst )->setChecked( mLayer->placements() & Qgis::MarkerLinePlacement::FirstVertex || mLayer->placements() & Qgis::MarkerLinePlacement::Vertex );
2161 whileBlocking( mCheckVertexLast )->setChecked( mLayer->placements() & Qgis::MarkerLinePlacement::LastVertex || mLayer->placements() & Qgis::MarkerLinePlacement::Vertex );
2162 whileBlocking( mCheckCentralPoint )->setChecked( mLayer->placements() & Qgis::MarkerLinePlacement::CentralPoint );
2163 whileBlocking( mCheckCurvePoint )->setChecked( mLayer->placements() & Qgis::MarkerLinePlacement::CurvePoint );
2164 whileBlocking( mCheckSegmentCentralPoint )->setChecked( mLayer->placements() & Qgis::MarkerLinePlacement::SegmentCenter );
2165 whileBlocking( mCheckPlaceOnEveryPart )->setChecked( mLayer->placeOnEveryPart() );
2166
2167 // set units
2168 mIntervalUnitWidget->blockSignals( true );
2169 mIntervalUnitWidget->setUnit( mLayer->intervalUnit() );
2170 mIntervalUnitWidget->setMapUnitScale( mLayer->intervalMapUnitScale() );
2171 mIntervalUnitWidget->blockSignals( false );
2172 mOffsetUnitWidget->blockSignals( true );
2173 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
2174 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
2175 mOffsetUnitWidget->blockSignals( false );
2176 mOffsetAlongLineUnitWidget->blockSignals( true );
2177 mOffsetAlongLineUnitWidget->setUnit( mLayer->offsetAlongLineUnit() );
2178 mOffsetAlongLineUnitWidget->setMapUnitScale( mLayer->offsetAlongLineMapUnitScale() );
2179 mOffsetAlongLineUnitWidget->blockSignals( false );
2180 whileBlocking( mAverageAngleUnit )->setUnit( mLayer->averageAngleUnit() );
2181 whileBlocking( mAverageAngleUnit )->setMapUnitScale( mLayer->averageAngleMapUnitScale() );
2182 whileBlocking( mSpinAverageAngleLength )->setValue( mLayer->averageAngleLength() );
2183 whileBlocking( mBlankSegmentsUnitWidget )->setUnit( mLayer->blankSegmentsUnit() );
2184 whileBlocking( mTrimDistanceStartUnitWidget )->setUnit( mLayer->trimDistanceStartUnit() );
2185 whileBlocking( mTrimDistanceStartUnitWidget )->setMapUnitScale( mLayer->trimDistanceStartMapUnitScale() );
2186 whileBlocking( mTrimDistanceEndUnitWidget )->setUnit( mLayer->trimDistanceEndUnit() );
2187 whileBlocking( mTrimDistanceEndUnitWidget )->setMapUnitScale( mLayer->trimDistanceEndMapUnitScale() );
2188
2189 switch ( mSymbolType )
2190 {
2192 {
2193 QgsHashedLineSymbolLayer *hashLayer = static_cast<QgsHashedLineSymbolLayer *>( mLayer );
2194 whileBlocking( mSpinHashLength )->setValue( hashLayer->hashLength() );
2195 whileBlocking( mHashRotationSpinBox )->setValue( hashLayer->hashAngle() );
2196 whileBlocking( mHashLengthUnitWidget )->setUnit( hashLayer->hashLengthUnit() );
2197 whileBlocking( mHashLengthUnitWidget )->setMapUnitScale( hashLayer->hashLengthMapUnitScale() );
2200 break;
2201 }
2202
2204 break;
2205 }
2206
2207 whileBlocking( mRingFilterComboBox )->setCurrentIndex( mRingFilterComboBox->findData( mLayer->ringFilter() ) );
2208
2209 setPlacement(); // update gui
2210
2220
2221 connect( mBlankSegmentsDDButton, &QgsPropertyOverrideButton::changed, this, &QgsMarkerLineSymbolLayerWidget::updatePerFeatureCustomizationWidget );
2222 connect( mBlankSegmentsDDButton, &QgsPropertyOverrideButton::createAuxiliaryField, this, &QgsMarkerLineSymbolLayerWidget::updatePerFeatureCustomizationWidget );
2223 connect( mExtraItemsDDBtn, &QgsPropertyOverrideButton::changed, this, &QgsMarkerLineSymbolLayerWidget::updatePerFeatureCustomizationWidget );
2224 connect( mExtraItemsDDBtn, &QgsPropertyOverrideButton::createAuxiliaryField, this, &QgsMarkerLineSymbolLayerWidget::updatePerFeatureCustomizationWidget );
2225
2226 if ( vectorLayer() )
2227 {
2228 connect( vectorLayer(), &QgsMapLayer::editingStarted, this, &QgsMarkerLineSymbolLayerWidget::updatePerFeatureCustomizationWidget );
2229 connect( vectorLayer(), &QgsMapLayer::editingStopped, this, &QgsMarkerLineSymbolLayerWidget::updatePerFeatureCustomizationWidget );
2230 }
2231
2232 updatePerFeatureCustomizationWidget();
2233}
2234
2239
2241{
2243
2244 switch ( context.symbolType() )
2245 {
2248 //these settings only have an effect when the symbol layers is part of a fill symbol
2249 mRingFilterComboBox->hide();
2250 mRingsLabel->hide();
2251 break;
2252
2255 break;
2256 }
2257
2258 if ( context.mapCanvas() )
2259 {
2260 connect( context.mapCanvas(), &QgsMapCanvas::mapToolSet, this, [this]( QgsMapTool *, QgsMapTool *oldMapTool ) {
2261 if ( oldMapTool == mMapToolAddExtraItem.get() )
2262 mMapToolAddExtraItem.reset();
2263 if ( oldMapTool == mMapToolModifyExtraItem.get() )
2264 mMapToolModifyExtraItem.reset();
2265 if ( oldMapTool == mMapToolEditBlankSegments.get() )
2266 mMapToolEditBlankSegments.reset();
2267 } );
2268 }
2269}
2270
2272{
2273 mLayer->setInterval( val );
2274 emit changed();
2275}
2276
2278{
2279 mLayer->setOffsetAlongLine( val );
2280 emit changed();
2281}
2282
2283void QgsTemplatedLineSymbolLayerWidget::setHashLength( double val )
2284{
2285 switch ( mSymbolType )
2286 {
2288 {
2289 QgsHashedLineSymbolLayer *hashLayer = static_cast<QgsHashedLineSymbolLayer *>( mLayer );
2290 hashLayer->setHashLength( val );
2291 emit changed();
2292 break;
2293 }
2294
2296 Q_ASSERT( false );
2297 }
2298}
2299
2300void QgsTemplatedLineSymbolLayerWidget::setHashAngle( double val )
2301{
2302 if ( !mLayer )
2303 return;
2304
2305 switch ( mSymbolType )
2306 {
2308 {
2309 QgsHashedLineSymbolLayer *hashLayer = static_cast<QgsHashedLineSymbolLayer *>( mLayer );
2310 hashLayer->setHashAngle( val );
2311 emit changed();
2312 break;
2313 }
2314
2316 Q_ASSERT( false );
2317 }
2318}
2319
2320void QgsTemplatedLineSymbolLayerWidget::setRotate()
2321{
2322 mSpinAverageAngleLength->setEnabled( chkRotateMarker->isChecked() && ( mCheckInterval->isChecked() || mCheckCentralPoint->isChecked() ) );
2323 mAverageAngleUnit->setEnabled( mSpinAverageAngleLength->isEnabled() );
2324
2325 mLayer->setRotateSymbols( chkRotateMarker->isChecked() );
2326 emit changed();
2327}
2328
2329void QgsTemplatedLineSymbolLayerWidget::setOffset()
2330{
2331 mLayer->setOffset( spinOffset->value() );
2332 emit changed();
2333}
2334
2335void QgsTemplatedLineSymbolLayerWidget::setPlacement()
2336{
2337 const bool interval = mCheckInterval->isChecked();
2338 spinInterval->setEnabled( interval );
2339 mSpinOffsetAlongLine->setEnabled( mCheckInterval->isChecked() || mCheckVertexLast->isChecked() || mCheckVertexFirst->isChecked() );
2340 mOffsetAlongLineUnitWidget->setEnabled( mSpinOffsetAlongLine->isEnabled() );
2341 mSpinAverageAngleLength->setEnabled( chkRotateMarker->isChecked() && ( mCheckInterval->isChecked() || mCheckCentralPoint->isChecked() ) );
2342 mAverageAngleUnit->setEnabled( mSpinAverageAngleLength->isEnabled() );
2343 mCheckPlaceOnEveryPart->setEnabled( mCheckVertexLast->isChecked() || mCheckVertexFirst->isChecked() );
2344
2345 Qgis::MarkerLinePlacements placements;
2346 if ( mCheckInterval->isChecked() )
2348 if ( mCheckVertex->isChecked() )
2350 if ( mCheckVertexLast->isChecked() )
2352 if ( mCheckVertexFirst->isChecked() )
2354 if ( mCheckCurvePoint->isChecked() )
2356 if ( mCheckSegmentCentralPoint->isChecked() )
2358 if ( mCheckCentralPoint->isChecked() )
2360 mLayer->setPlacements( placements );
2361
2362 emit changed();
2363}
2364
2365void QgsTemplatedLineSymbolLayerWidget::mIntervalUnitWidget_changed()
2366{
2367 if ( mLayer )
2368 {
2369 mLayer->setIntervalUnit( mIntervalUnitWidget->unit() );
2370 mLayer->setIntervalMapUnitScale( mIntervalUnitWidget->getMapUnitScale() );
2371 emit changed();
2372 }
2373}
2374
2375void QgsTemplatedLineSymbolLayerWidget::mOffsetUnitWidget_changed()
2376{
2377 if ( mLayer )
2378 {
2379 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
2380 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
2381 emit changed();
2382 }
2383}
2384
2385void QgsTemplatedLineSymbolLayerWidget::mOffsetAlongLineUnitWidget_changed()
2386{
2387 if ( mLayer )
2388 {
2389 mLayer->setOffsetAlongLineUnit( mOffsetAlongLineUnitWidget->unit() );
2390 mLayer->setOffsetAlongLineMapUnitScale( mOffsetAlongLineUnitWidget->getMapUnitScale() );
2391 }
2392 emit changed();
2393}
2394
2395void QgsTemplatedLineSymbolLayerWidget::hashLengthUnitWidgetChanged()
2396{
2397 if ( !mLayer )
2398 return;
2399
2400 switch ( mSymbolType )
2401 {
2403 {
2404 QgsHashedLineSymbolLayer *hashLayer = static_cast<QgsHashedLineSymbolLayer *>( mLayer );
2405 hashLayer->setHashLengthUnit( mHashLengthUnitWidget->unit() );
2406 hashLayer->setHashLengthMapUnitScale( mHashLengthUnitWidget->getMapUnitScale() );
2407 emit changed();
2408 break;
2409 }
2410
2412 Q_ASSERT( false );
2413 }
2414}
2415
2416void QgsTemplatedLineSymbolLayerWidget::averageAngleUnitChanged()
2417{
2418 if ( mLayer )
2419 {
2420 mLayer->setAverageAngleUnit( mAverageAngleUnit->unit() );
2421 mLayer->setAverageAngleMapUnitScale( mAverageAngleUnit->getMapUnitScale() );
2422 }
2423 emit changed();
2424}
2425
2426void QgsTemplatedLineSymbolLayerWidget::blankSegmentsUnitChanged()
2427{
2428 if ( mLayer )
2429 {
2430 mLayer->setBlankSegmentsUnit( mBlankSegmentsUnitWidget->unit() );
2431 }
2432 emit changed();
2433}
2434
2435void QgsTemplatedLineSymbolLayerWidget::setAverageAngle( double val )
2436{
2437 if ( mLayer )
2438 {
2439 mLayer->setAverageAngleLength( val );
2440 emit changed();
2441 }
2442}
2443
2444void QgsTemplatedLineSymbolLayerWidget::toggleMapToolEditBlankSegments( bool toggled )
2445{
2446 if ( !toggled || ( mMapToolEditBlankSegments.get() && context().mapCanvas()->mapTool() == mMapToolEditBlankSegments.get() ) )
2447 return;
2448
2449 switch ( mSymbolType )
2450 {
2452 mMapToolEditBlankSegments = make_qobject_unique<QgsMapToolEditBlankSegments<QgsHashedLineSymbolLayer>>( context().mapCanvas(), vectorLayer(), mLayer, mBlankSegmentsDDButton );
2453 break;
2454
2456 mMapToolEditBlankSegments = make_qobject_unique<QgsMapToolEditBlankSegments<QgsMarkerLineSymbolLayer>>( context().mapCanvas(), vectorLayer(), mLayer, mBlankSegmentsDDButton );
2457 break;
2458 }
2459
2460 mMapToolEditBlankSegments->setAction( mEditBlankSegmentsAction );
2461 context().mapCanvas()->setMapTool( mMapToolEditBlankSegments );
2462}
2463
2464void QgsTemplatedLineSymbolLayerWidget::toggleMapToolAddExtraItem( bool toggled )
2465{
2466 if ( !toggled || ( mMapToolAddExtraItem.get() && context().mapCanvas()->mapTool() == mMapToolAddExtraItem.get() ) )
2467 return;
2468
2469 mMapToolAddExtraItem = make_qobject_unique<QgsMapToolAddExtraItem>( context().mapCanvas(), vectorLayer(), mLayer, mExtraItemsDDBtn );
2470 mMapToolAddExtraItem->setAction( mAddExtraItemAction );
2471 context().mapCanvas()->setMapTool( mMapToolAddExtraItem );
2472}
2473
2474void QgsTemplatedLineSymbolLayerWidget::toggleMapToolModifyExtraItem( bool toggled )
2475{
2476 if ( !toggled || ( mMapToolModifyExtraItem.get() && context().mapCanvas()->mapTool() == mMapToolModifyExtraItem.get() ) )
2477 return;
2478
2479 mMapToolModifyExtraItem = make_qobject_unique<QgsMapToolModifyExtraItems>( context().mapCanvas(), vectorLayer(), mLayer, mExtraItemsDDBtn );
2480 mMapToolModifyExtraItem->setAction( mModifyExtraItemAction );
2481 context().mapCanvas()->setMapTool( mMapToolModifyExtraItem );
2482}
2483
2484void QgsTemplatedLineSymbolLayerWidget::updatePerFeatureCustomizationWidget()
2485{
2486 QString tooltipEditBlankSegment = u"<b>"_s;
2487 QString tooltipAddExtraItem = u"<b>"_s;
2488 QString tooltipModifyExtraItem = u"<b>"_s;
2489 switch ( mSymbolType )
2490 {
2492 tooltipEditBlankSegment += tr( "Create blank segments where hashed lines won't be displayed" );
2493 tooltipAddExtraItem += tr( "Add extra hash being displayed with the hashed line" );
2494 tooltipModifyExtraItem += tr( "Select and modify (move, rotate, delete) extra hashes being displayed with the hashed line" );
2495 break;
2496
2498 tooltipEditBlankSegment += tr( "Create blank segments where marker lines won't be displayed" );
2499 tooltipAddExtraItem += tr( "Add extra marker being displayed with the marker line" );
2500 tooltipModifyExtraItem += tr( "Select and modify (move, rotate, delete) extra markers being displayed with the marker line" );
2501 break;
2502 }
2503
2504 const QString info = u"</b><br/>"_s
2505 + tr(
2506 "First click to select the line you want to operate on. "
2507 "<br/>Press %1 to deselect the line and select another one."
2508 )
2509 .arg( QKeySequence( QKeySequence::StandardKey::Cancel ).toString( QKeySequence::NativeText ) );
2510 tooltipEditBlankSegment += info;
2511 tooltipAddExtraItem += info;
2512 tooltipModifyExtraItem += info;
2513
2514 bool enabled = true;
2515 if ( QgsPanelWidget *panelWidget = QgsPanelWidget::findParentPanel( this ); !panelWidget || !panelWidget->dockMode() )
2516 {
2517 // It's not possible to edit blank segments from Layer properties dialog
2518 const QString accessFromDialog = tr( "This tool is disabled because map canvas interaction is only possible from Layer Styling panel, Layer properties dialog doesn't allow blank segments creation." );
2519 tooltipEditBlankSegment += u"<br/><br/>"_s + accessFromDialog;
2520 tooltipAddExtraItem += u"<br/><br/>"_s + accessFromDialog;
2521 tooltipModifyExtraItem += u"<br/><br/>"_s + accessFromDialog;
2522
2523 enabled = false;
2524 }
2525
2526 mEditBlankSegmentsAction->setEnabled( enabled );
2527 mAddExtraItemAction->setEnabled( enabled );
2528 mModifyExtraItemAction->setEnabled( enabled );
2529
2530 mEditBlankSegmentsAction->setToolTip( tooltipEditBlankSegment );
2531 mAddExtraItemAction->setToolTip( tooltipAddExtraItem );
2532 mModifyExtraItemAction->setToolTip( tooltipModifyExtraItem );
2533}
2534
2536
2540
2542
2546
2548
2549
2551 : QgsSymbolLayerWidget( parent, vl )
2552{
2553 mLayer = nullptr;
2554
2555 setupUi( this );
2556
2557 mHorizontalAnchorComboBox->addItem( tr( "Left" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Left ) );
2558 mHorizontalAnchorComboBox->addItem( tr( "Horizontal Center" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Center ) );
2559 mHorizontalAnchorComboBox->addItem( tr( "Right" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Right ) );
2560
2561 mVerticalAnchorComboBox->addItem( tr( "Top" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Top ) );
2562 mVerticalAnchorComboBox->addItem( tr( "Vertical Center" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Center ) );
2563 mVerticalAnchorComboBox->addItem( tr( "Bottom" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Bottom ) );
2564
2565 mSvgSelectorWidget->setAllowParameters( true );
2566 mSvgSelectorWidget->sourceLineEdit()->setPropertyOverrideToolButtonVisible( true );
2567 mSvgSelectorWidget->sourceLineEdit()->setLastPathSettingsKey( u"/UI/lastSVGMarkerDir"_s );
2568 mSvgSelectorWidget->initParametersModel( this, vl );
2569
2570 connect( mSvgSelectorWidget->sourceLineEdit(), &QgsSvgSourceLineEdit::sourceChanged, this, &QgsSvgMarkerSymbolLayerWidget::svgSourceChanged );
2571 connect( mChangeColorButton, &QgsColorButton::colorChanged, this, &QgsSvgMarkerSymbolLayerWidget::mChangeColorButton_colorChanged );
2572 connect( mChangeStrokeColorButton, &QgsColorButton::colorChanged, this, &QgsSvgMarkerSymbolLayerWidget::mChangeStrokeColorButton_colorChanged );
2573 connect( mStrokeWidthSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSvgMarkerSymbolLayerWidget::mStrokeWidthSpinBox_valueChanged );
2574 connect( mSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSvgMarkerSymbolLayerWidget::mSizeUnitWidget_changed );
2575 connect( mStrokeWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSvgMarkerSymbolLayerWidget::mStrokeWidthUnitWidget_changed );
2576 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSvgMarkerSymbolLayerWidget::mOffsetUnitWidget_changed );
2577 connect( mHorizontalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSvgMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged );
2578 connect( mVerticalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSvgMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged );
2579 mSizeUnitWidget->setUnits(
2581 );
2582 mStrokeWidthUnitWidget->setUnits(
2584 );
2585 mOffsetUnitWidget->setUnits(
2587 );
2588 mChangeColorButton->setAllowOpacity( true );
2589 mChangeColorButton->setColorDialogTitle( tr( "Select Fill color" ) );
2590 mChangeColorButton->setContext( u"symbology"_s );
2591 mChangeStrokeColorButton->setAllowOpacity( true );
2592 mChangeStrokeColorButton->setColorDialogTitle( tr( "Select Stroke Color" ) );
2593 mChangeStrokeColorButton->setContext( u"symbology"_s );
2594
2595 mFillColorDDBtn->registerLinkedWidget( mChangeColorButton );
2596 mStrokeColorDDBtn->registerLinkedWidget( mChangeStrokeColorButton );
2597
2598 spinOffsetX->setClearValue( 0.0 );
2599 spinOffsetY->setClearValue( 0.0 );
2600 spinAngle->setClearValue( 0.0 );
2601
2602 connect( spinWidth, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSvgMarkerSymbolLayerWidget::setWidth );
2603 connect( spinHeight, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSvgMarkerSymbolLayerWidget::setHeight );
2604 connect( mLockAspectRatio, static_cast<void ( QgsRatioLockButton::* )( bool )>( &QgsRatioLockButton::lockChanged ), this, &QgsSvgMarkerSymbolLayerWidget::lockAspectRatioChanged );
2605 connect( spinAngle, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSvgMarkerSymbolLayerWidget::setAngle );
2606 connect( spinOffsetX, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSvgMarkerSymbolLayerWidget::setOffset );
2607 connect( spinOffsetY, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSvgMarkerSymbolLayerWidget::setOffset );
2608 connect( this, &QgsSymbolLayerWidget::changed, this, &QgsSvgMarkerSymbolLayerWidget::updateAssistantSymbol );
2609
2612
2613 //make a temporary symbol for the size assistant preview
2614 mAssistantPreviewSymbol = std::make_shared<QgsMarkerSymbol>();
2615
2616 if ( vectorLayer() )
2617 {
2618 mWidthDDBtn->setSymbol( mAssistantPreviewSymbol );
2619 mHeightDDBtn->setSymbol( mAssistantPreviewSymbol );
2620 }
2621}
2622
2624
2625#include <QTime>
2626#include <QAbstractListModel>
2627#include <QPixmapCache>
2628#include <QStyle>
2629#include <memory>
2630
2631
2633{
2634 if ( !layer )
2635 {
2636 return;
2637 }
2638
2639 //activate gui for svg parameters only if supported by the svg file
2640 bool hasFillParam, hasFillOpacityParam, hasStrokeParam, hasStrokeWidthParam, hasStrokeOpacityParam;
2641 QColor defaultFill, defaultStroke;
2642 double defaultStrokeWidth, defaultFillOpacity, defaultStrokeOpacity;
2643 bool hasDefaultFillColor, hasDefaultFillOpacity, hasDefaultStrokeColor, hasDefaultStrokeWidth, hasDefaultStrokeOpacity;
2645 layer->path(),
2646 hasFillParam,
2647 hasDefaultFillColor,
2648 defaultFill,
2649 hasFillOpacityParam,
2650 hasDefaultFillOpacity,
2651 defaultFillOpacity,
2652 hasStrokeParam,
2653 hasDefaultStrokeColor,
2654 defaultStroke,
2655 hasStrokeWidthParam,
2656 hasDefaultStrokeWidth,
2657 defaultStrokeWidth,
2658 hasStrokeOpacityParam,
2659 hasDefaultStrokeOpacity,
2660 defaultStrokeOpacity
2661 );
2662 mChangeColorButton->setEnabled( hasFillParam );
2663 mChangeColorButton->setAllowOpacity( hasFillOpacityParam );
2664 mChangeStrokeColorButton->setEnabled( hasStrokeParam );
2665 mChangeStrokeColorButton->setAllowOpacity( hasStrokeOpacityParam );
2666 mStrokeWidthSpinBox->setEnabled( hasStrokeWidthParam );
2667
2668 if ( hasFillParam )
2669 {
2670 QColor fill = layer->fillColor();
2671 const double existingOpacity = hasFillOpacityParam ? fill.alphaF() : 1.0;
2672 if ( hasDefaultFillColor && !skipDefaultColors )
2673 {
2674 fill = defaultFill;
2675 }
2676 fill.setAlphaF( hasDefaultFillOpacity ? defaultFillOpacity : existingOpacity );
2677 mChangeColorButton->setColor( fill );
2678 }
2679 if ( hasStrokeParam )
2680 {
2681 QColor stroke = layer->strokeColor();
2682 const double existingOpacity = hasStrokeOpacityParam ? stroke.alphaF() : 1.0;
2683 if ( hasDefaultStrokeColor && !skipDefaultColors )
2684 {
2685 stroke = defaultStroke;
2686 }
2687 stroke.setAlphaF( hasDefaultStrokeOpacity ? defaultStrokeOpacity : existingOpacity );
2688 mChangeStrokeColorButton->setColor( stroke );
2689 }
2690
2691 whileBlocking( mSvgSelectorWidget->sourceLineEdit() )->setSource( layer->path() );
2692
2693 mStrokeWidthSpinBox->blockSignals( true );
2694 mStrokeWidthSpinBox->setValue( hasDefaultStrokeWidth ? defaultStrokeWidth : layer->strokeWidth() );
2695 mStrokeWidthSpinBox->blockSignals( false );
2696
2697 const bool preservedAspectRatio = layer->preservedAspectRatio();
2698 spinHeight->blockSignals( true );
2699 if ( preservedAspectRatio )
2700 {
2701 spinHeight->setValue( layer->size() * layer->defaultAspectRatio() );
2702 }
2703 else
2704 {
2705 spinHeight->setValue( layer->size() * layer->fixedAspectRatio() );
2706 }
2707 spinHeight->setEnabled( layer->defaultAspectRatio() > 0.0 );
2708 spinHeight->blockSignals( false );
2709 whileBlocking( mLockAspectRatio )->setLocked( preservedAspectRatio );
2710}
2711
2712void QgsSvgMarkerSymbolLayerWidget::updateAssistantSymbol()
2713{
2714 for ( int i = mAssistantPreviewSymbol->symbolLayerCount() - 1; i >= 0; --i )
2715 {
2716 mAssistantPreviewSymbol->deleteSymbolLayer( i );
2717 }
2718 mAssistantPreviewSymbol->appendSymbolLayer( mLayer->clone() );
2719 const QgsProperty ddSize = mLayer->dataDefinedProperties().property( QgsSymbolLayer::Property::Size );
2720 if ( ddSize )
2721 mAssistantPreviewSymbol->setDataDefinedSize( ddSize );
2722}
2723
2724
2726{
2727 if ( !layer )
2728 {
2729 return;
2730 }
2731
2732 if ( layer->layerType() != "SvgMarker"_L1 )
2733 return;
2734
2735 // layer type is correct, we can do the cast
2736 mLayer = static_cast<QgsSvgMarkerSymbolLayer *>( layer );
2737
2738 // set values
2739 mSvgSelectorWidget->setSvgPath( mLayer->path() );
2740 mSvgSelectorWidget->setSvgParameters( mLayer->parameters() );
2741
2742 spinWidth->blockSignals( true );
2743 spinWidth->setValue( mLayer->size() );
2744 spinWidth->blockSignals( false );
2745 spinAngle->blockSignals( true );
2746 spinAngle->setValue( mLayer->angle() );
2747 spinAngle->blockSignals( false );
2748
2749 // without blocking signals the value gets changed because of slot setOffset()
2750 spinOffsetX->blockSignals( true );
2751 spinOffsetX->setValue( mLayer->offset().x() );
2752 spinOffsetX->blockSignals( false );
2753 spinOffsetY->blockSignals( true );
2754 spinOffsetY->setValue( mLayer->offset().y() );
2755 spinOffsetY->blockSignals( false );
2756
2757 mSizeUnitWidget->blockSignals( true );
2758 mSizeUnitWidget->setUnit( mLayer->sizeUnit() );
2759 mSizeUnitWidget->setMapUnitScale( mLayer->sizeMapUnitScale() );
2760 mSizeUnitWidget->blockSignals( false );
2761 mStrokeWidthUnitWidget->blockSignals( true );
2762 mStrokeWidthUnitWidget->setUnit( mLayer->strokeWidthUnit() );
2763 mStrokeWidthUnitWidget->setMapUnitScale( mLayer->strokeWidthMapUnitScale() );
2764 mStrokeWidthUnitWidget->blockSignals( false );
2765 mOffsetUnitWidget->blockSignals( true );
2766 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
2767 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
2768 mOffsetUnitWidget->blockSignals( false );
2769
2770 //anchor points
2771 mHorizontalAnchorComboBox->blockSignals( true );
2772 mVerticalAnchorComboBox->blockSignals( true );
2773 mHorizontalAnchorComboBox->setCurrentIndex( mHorizontalAnchorComboBox->findData( QVariant::fromValue( mLayer->horizontalAnchorPoint() ) ) );
2774 mVerticalAnchorComboBox->setCurrentIndex( mVerticalAnchorComboBox->findData( QVariant::fromValue( mLayer->verticalAnchorPoint() ) ) );
2775 mHorizontalAnchorComboBox->blockSignals( false );
2776 mVerticalAnchorComboBox->blockSignals( false );
2777
2778 setGuiForSvg( mLayer, true );
2779
2789
2790 registerDataDefinedButton( mSvgSelectorWidget->sourceLineEdit()->propertyOverrideToolButton(), QgsSymbolLayer::Property::Name );
2791
2792 updateAssistantSymbol();
2793}
2794
2799
2801{
2803 mSvgSelectorWidget->sourceLineEdit()->setMessageBar( context.messageBar() );
2804}
2805
2807{
2808 mLayer->setPath( name );
2809 whileBlocking( mSvgSelectorWidget->sourceLineEdit() )->setSource( name );
2810
2812 emit changed();
2813}
2814
2815void QgsSvgMarkerSymbolLayerWidget::setSvgParameters( const QMap<QString, QgsProperty> &parameters )
2816{
2817 mLayer->setParameters( parameters );
2818 whileBlocking( mSvgSelectorWidget )->setSvgParameters( parameters );
2819
2821 emit changed();
2822}
2823
2824void QgsSvgMarkerSymbolLayerWidget::setWidth()
2825{
2826 const double defaultAspectRatio = mLayer->defaultAspectRatio();
2827 double fixedAspectRatio = 0.0;
2828 spinHeight->blockSignals( true );
2829 if ( defaultAspectRatio <= 0.0 )
2830 {
2831 spinHeight->setValue( spinWidth->value() );
2832 }
2833 else if ( mLockAspectRatio->locked() )
2834 {
2835 spinHeight->setValue( spinWidth->value() * defaultAspectRatio );
2836 }
2837 else
2838 {
2839 fixedAspectRatio = spinHeight->value() / spinWidth->value();
2840 }
2841 spinHeight->blockSignals( false );
2842 mLayer->setSize( spinWidth->value() );
2843 mLayer->setFixedAspectRatio( fixedAspectRatio );
2844 emit changed();
2845}
2846
2847void QgsSvgMarkerSymbolLayerWidget::setHeight()
2848{
2849 const double defaultAspectRatio = mLayer->defaultAspectRatio();
2850 double fixedAspectRatio = 0.0;
2851 spinWidth->blockSignals( true );
2852 if ( defaultAspectRatio <= 0.0 )
2853 {
2854 spinWidth->setValue( spinHeight->value() );
2855 }
2856 else if ( mLockAspectRatio->locked() )
2857 {
2858 spinWidth->setValue( spinHeight->value() / defaultAspectRatio );
2859 }
2860 else
2861 {
2862 fixedAspectRatio = spinHeight->value() / spinWidth->value();
2863 }
2864 spinWidth->blockSignals( false );
2865 mLayer->setSize( spinWidth->value() );
2866 mLayer->setFixedAspectRatio( fixedAspectRatio );
2867 emit changed();
2868}
2869
2870void QgsSvgMarkerSymbolLayerWidget::lockAspectRatioChanged( const bool locked )
2871{
2872 //spinHeight->setEnabled( !locked );
2873 const double defaultAspectRatio = mLayer->defaultAspectRatio();
2874 if ( defaultAspectRatio <= 0.0 )
2875 {
2876 whileBlocking( mLockAspectRatio )->setLocked( true );
2877 }
2878 else if ( locked )
2879 {
2880 mLayer->setFixedAspectRatio( 0.0 );
2881 setWidth();
2882 }
2883 else
2884 {
2885 mLayer->setFixedAspectRatio( spinHeight->value() / spinWidth->value() );
2886 }
2887 //emit changed();
2888}
2889
2890void QgsSvgMarkerSymbolLayerWidget::setAngle()
2891{
2892 mLayer->setAngle( spinAngle->value() );
2893 emit changed();
2894}
2895
2896void QgsSvgMarkerSymbolLayerWidget::setOffset()
2897{
2898 mLayer->setOffset( QPointF( spinOffsetX->value(), spinOffsetY->value() ) );
2899 emit changed();
2900}
2901
2902void QgsSvgMarkerSymbolLayerWidget::svgSourceChanged( const QString &text )
2903{
2904 mLayer->setPath( text );
2906 emit changed();
2907}
2908
2909void QgsSvgMarkerSymbolLayerWidget::mChangeColorButton_colorChanged( const QColor &color )
2910{
2911 if ( !mLayer )
2912 {
2913 return;
2914 }
2915
2916 mLayer->setFillColor( color );
2917 emit changed();
2918}
2919
2920void QgsSvgMarkerSymbolLayerWidget::mChangeStrokeColorButton_colorChanged( const QColor &color )
2921{
2922 if ( !mLayer )
2923 {
2924 return;
2925 }
2926
2927 mLayer->setStrokeColor( color );
2928 emit changed();
2929}
2930
2931void QgsSvgMarkerSymbolLayerWidget::mStrokeWidthSpinBox_valueChanged( double d )
2932{
2933 if ( mLayer )
2934 {
2935 mLayer->setStrokeWidth( d );
2936 emit changed();
2937 }
2938}
2939
2940void QgsSvgMarkerSymbolLayerWidget::mSizeUnitWidget_changed()
2941{
2942 if ( mLayer )
2943 {
2944 mLayer->setSizeUnit( mSizeUnitWidget->unit() );
2945 mLayer->setSizeMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
2946 emit changed();
2947 }
2948}
2949
2950void QgsSvgMarkerSymbolLayerWidget::mStrokeWidthUnitWidget_changed()
2951{
2952 if ( mLayer )
2953 {
2954 mLayer->setStrokeWidthUnit( mStrokeWidthUnitWidget->unit() );
2955 mLayer->setStrokeWidthMapUnitScale( mStrokeWidthUnitWidget->getMapUnitScale() );
2956 emit changed();
2957 }
2958}
2959
2960void QgsSvgMarkerSymbolLayerWidget::mOffsetUnitWidget_changed()
2961{
2962 if ( mLayer )
2963 {
2964 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
2965 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
2966 emit changed();
2967 }
2968}
2969
2970void QgsSvgMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged( int )
2971{
2972 if ( mLayer )
2973 {
2974 mLayer->setHorizontalAnchorPoint( mHorizontalAnchorComboBox->currentData().value< Qgis::HorizontalAnchorPoint >() );
2975 emit changed();
2976 }
2977}
2978
2979void QgsSvgMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged( int )
2980{
2981 if ( mLayer )
2982 {
2983 mLayer->setVerticalAnchorPoint( mVerticalAnchorComboBox->currentData().value< Qgis::VerticalAnchorPoint >() );
2984 emit changed();
2985 }
2986}
2987
2989
2991 : QgsSymbolLayerWidget( parent, vl )
2992{
2993 mLayer = nullptr;
2994 setupUi( this );
2995
2996 mSvgSelectorWidget->setAllowParameters( true );
2997 mSvgSelectorWidget->sourceLineEdit()->setPropertyOverrideToolButtonVisible( true );
2998
2999 connect( mTextureWidthSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSVGFillSymbolLayerWidget::mTextureWidthSpinBox_valueChanged );
3000 connect( mSvgSelectorWidget->sourceLineEdit(), &QgsSvgSourceLineEdit::sourceChanged, this, &QgsSVGFillSymbolLayerWidget::svgSourceChanged );
3001 connect( mRotationSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSVGFillSymbolLayerWidget::mRotationSpinBox_valueChanged );
3002 connect( mChangeColorButton, &QgsColorButton::colorChanged, this, &QgsSVGFillSymbolLayerWidget::mChangeColorButton_colorChanged );
3003 connect( mChangeStrokeColorButton, &QgsColorButton::colorChanged, this, &QgsSVGFillSymbolLayerWidget::mChangeStrokeColorButton_colorChanged );
3004 connect( mStrokeWidthSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSVGFillSymbolLayerWidget::mStrokeWidthSpinBox_valueChanged );
3005 connect( mTextureWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSVGFillSymbolLayerWidget::mTextureWidthUnitWidget_changed );
3006 connect( mSvgStrokeWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSVGFillSymbolLayerWidget::mSvgStrokeWidthUnitWidget_changed );
3007 mTextureWidthUnitWidget->setUnits(
3009 );
3010 mSvgStrokeWidthUnitWidget->setUnits(
3012 );
3013
3014 mRotationSpinBox->setClearValue( 0.0 );
3015
3016 mChangeColorButton->setColorDialogTitle( tr( "Select Fill Color" ) );
3017 mChangeColorButton->setContext( u"symbology"_s );
3018 mChangeStrokeColorButton->setColorDialogTitle( tr( "Select Stroke Color" ) );
3019 mChangeStrokeColorButton->setContext( u"symbology"_s );
3020
3021 mFilColorDDBtn->registerLinkedWidget( mChangeColorButton );
3022 mStrokeColorDDBtn->registerLinkedWidget( mChangeStrokeColorButton );
3023
3024 connect( mSvgSelectorWidget, &QgsSvgSelectorWidget::svgSelected, this, &QgsSVGFillSymbolLayerWidget::setFile );
3025 connect( mSvgSelectorWidget, &QgsSvgSelectorWidget::svgParametersChanged, this, &QgsSVGFillSymbolLayerWidget::setSvgParameters );
3026}
3027
3029{
3030 if ( !layer )
3031 {
3032 return;
3033 }
3034
3035 if ( layer->layerType() != "SVGFill"_L1 )
3036 {
3037 return;
3038 }
3039
3040 mLayer = dynamic_cast<QgsSVGFillSymbolLayer *>( layer );
3041 if ( mLayer )
3042 {
3043 const double width = mLayer->patternWidth();
3044 mTextureWidthSpinBox->blockSignals( true );
3045 mTextureWidthSpinBox->setValue( width );
3046 mTextureWidthSpinBox->blockSignals( false );
3047 whileBlocking( mSvgSelectorWidget->sourceLineEdit() )->setSource( mLayer->svgFilePath() );
3048 mRotationSpinBox->blockSignals( true );
3049 mRotationSpinBox->setValue( mLayer->angle() );
3050 mRotationSpinBox->blockSignals( false );
3051 mTextureWidthUnitWidget->blockSignals( true );
3052 mTextureWidthUnitWidget->setUnit( mLayer->patternWidthUnit() );
3053 mTextureWidthUnitWidget->setMapUnitScale( mLayer->patternWidthMapUnitScale() );
3054 mTextureWidthUnitWidget->blockSignals( false );
3055 mSvgStrokeWidthUnitWidget->blockSignals( true );
3056 mSvgStrokeWidthUnitWidget->setUnit( mLayer->svgStrokeWidthUnit() );
3057 mSvgStrokeWidthUnitWidget->setMapUnitScale( mLayer->svgStrokeWidthMapUnitScale() );
3058 mSvgStrokeWidthUnitWidget->blockSignals( false );
3059 mChangeColorButton->blockSignals( true );
3060 mChangeColorButton->setColor( mLayer->svgFillColor() );
3061 mChangeColorButton->blockSignals( false );
3062 mChangeStrokeColorButton->blockSignals( true );
3063 mChangeStrokeColorButton->setColor( mLayer->svgStrokeColor() );
3064 mChangeStrokeColorButton->blockSignals( false );
3065 mStrokeWidthSpinBox->blockSignals( true );
3066 mStrokeWidthSpinBox->setValue( mLayer->svgStrokeWidth() );
3067 mStrokeWidthSpinBox->blockSignals( false );
3068 }
3069 updateParamGui( false );
3070
3076
3077 registerDataDefinedButton( mSvgSelectorWidget->sourceLineEdit()->propertyOverrideToolButton(), QgsSymbolLayer::Property::File );
3078}
3079
3084
3086{
3088 mSvgSelectorWidget->sourceLineEdit()->setMessageBar( context.messageBar() );
3089}
3090
3091void QgsSVGFillSymbolLayerWidget::mTextureWidthSpinBox_valueChanged( double d )
3092{
3093 if ( mLayer )
3094 {
3095 mLayer->setPatternWidth( d );
3096 emit changed();
3097 }
3098}
3099
3100void QgsSVGFillSymbolLayerWidget::svgSourceChanged( const QString &text )
3101{
3102 if ( !mLayer )
3103 {
3104 return;
3105 }
3106
3107 mLayer->setSvgFilePath( text );
3109 emit changed();
3110}
3111
3112void QgsSVGFillSymbolLayerWidget::setFile( const QString &name )
3113{
3114 mLayer->setSvgFilePath( name );
3115 whileBlocking( mSvgSelectorWidget->sourceLineEdit() )->setSource( name );
3116
3118 emit changed();
3119}
3120
3121void QgsSVGFillSymbolLayerWidget::setSvgParameters( const QMap<QString, QgsProperty> &parameters )
3122{
3123 mLayer->setParameters( parameters );
3124 whileBlocking( mSvgSelectorWidget )->setSvgParameters( parameters );
3125
3127 emit changed();
3128}
3129
3130
3131void QgsSVGFillSymbolLayerWidget::mRotationSpinBox_valueChanged( double d )
3132{
3133 if ( mLayer )
3134 {
3135 mLayer->setAngle( d );
3136 emit changed();
3137 }
3138}
3139
3141{
3142 //activate gui for svg parameters only if supported by the svg file
3143 bool hasFillParam, hasFillOpacityParam, hasStrokeParam, hasStrokeWidthParam, hasStrokeOpacityParam;
3144 QColor defaultFill, defaultStroke;
3145 double defaultStrokeWidth, defaultFillOpacity, defaultStrokeOpacity;
3146 bool hasDefaultFillColor, hasDefaultFillOpacity, hasDefaultStrokeColor, hasDefaultStrokeWidth, hasDefaultStrokeOpacity;
3148 mSvgSelectorWidget->sourceLineEdit()->source(),
3149 hasFillParam,
3150 hasDefaultFillColor,
3151 defaultFill,
3152 hasFillOpacityParam,
3153 hasDefaultFillOpacity,
3154 defaultFillOpacity,
3155 hasStrokeParam,
3156 hasDefaultStrokeColor,
3157 defaultStroke,
3158 hasStrokeWidthParam,
3159 hasDefaultStrokeWidth,
3160 defaultStrokeWidth,
3161 hasStrokeOpacityParam,
3162 hasDefaultStrokeOpacity,
3163 defaultStrokeOpacity
3164 );
3165 if ( resetValues )
3166 {
3167 QColor fill = mChangeColorButton->color();
3168 const double newOpacity = hasFillOpacityParam ? fill.alphaF() : 1.0;
3169 if ( hasDefaultFillColor )
3170 {
3171 fill = defaultFill;
3172 }
3173 fill.setAlphaF( hasDefaultFillOpacity ? defaultFillOpacity : newOpacity );
3174 mChangeColorButton->setColor( fill );
3175 }
3176 mChangeColorButton->setEnabled( hasFillParam );
3177 mChangeColorButton->setAllowOpacity( hasFillOpacityParam );
3178 if ( resetValues )
3179 {
3180 QColor stroke = mChangeStrokeColorButton->color();
3181 const double newOpacity = hasStrokeOpacityParam ? stroke.alphaF() : 1.0;
3182 if ( hasDefaultStrokeColor )
3183 {
3184 stroke = defaultStroke;
3185 }
3186 stroke.setAlphaF( hasDefaultStrokeOpacity ? defaultStrokeOpacity : newOpacity );
3187 mChangeStrokeColorButton->setColor( stroke );
3188 }
3189 mChangeStrokeColorButton->setEnabled( hasStrokeParam );
3190 mChangeStrokeColorButton->setAllowOpacity( hasStrokeOpacityParam );
3191 if ( hasDefaultStrokeWidth && resetValues )
3192 {
3193 mStrokeWidthSpinBox->setValue( defaultStrokeWidth );
3194 }
3195 mStrokeWidthSpinBox->setEnabled( hasStrokeWidthParam );
3196}
3197
3198void QgsSVGFillSymbolLayerWidget::mChangeColorButton_colorChanged( const QColor &color )
3199{
3200 if ( !mLayer )
3201 {
3202 return;
3203 }
3204
3205 mLayer->setSvgFillColor( color );
3206 emit changed();
3207}
3208
3209void QgsSVGFillSymbolLayerWidget::mChangeStrokeColorButton_colorChanged( const QColor &color )
3210{
3211 if ( !mLayer )
3212 {
3213 return;
3214 }
3215
3216 mLayer->setSvgStrokeColor( color );
3217 emit changed();
3218}
3219
3220void QgsSVGFillSymbolLayerWidget::mStrokeWidthSpinBox_valueChanged( double d )
3221{
3222 if ( mLayer )
3223 {
3224 mLayer->setSvgStrokeWidth( d );
3225 emit changed();
3226 }
3227}
3228
3229void QgsSVGFillSymbolLayerWidget::mTextureWidthUnitWidget_changed()
3230{
3231 if ( mLayer )
3232 {
3233 mLayer->setPatternWidthUnit( mTextureWidthUnitWidget->unit() );
3234 mLayer->setPatternWidthMapUnitScale( mTextureWidthUnitWidget->getMapUnitScale() );
3235 emit changed();
3236 }
3237}
3238
3239void QgsSVGFillSymbolLayerWidget::mSvgStrokeWidthUnitWidget_changed()
3240{
3241 if ( mLayer )
3242 {
3243 mLayer->setSvgStrokeWidthUnit( mSvgStrokeWidthUnitWidget->unit() );
3244 mLayer->setSvgStrokeWidthMapUnitScale( mSvgStrokeWidthUnitWidget->getMapUnitScale() );
3245 emit changed();
3246 }
3247}
3248
3250
3252 : QgsSymbolLayerWidget( parent, vl )
3253{
3254 setupUi( this );
3255 connect( mAngleSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsLinePatternFillSymbolLayerWidget::mAngleSpinBox_valueChanged );
3256 connect( mDistanceSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsLinePatternFillSymbolLayerWidget::mDistanceSpinBox_valueChanged );
3257 connect( mOffsetSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsLinePatternFillSymbolLayerWidget::mOffsetSpinBox_valueChanged );
3258 connect( mDistanceUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsLinePatternFillSymbolLayerWidget::mDistanceUnitWidget_changed );
3259 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsLinePatternFillSymbolLayerWidget::mOffsetUnitWidget_changed );
3260 mDistanceUnitWidget->setUnits(
3262 );
3263 mOffsetUnitWidget->setUnits(
3272 );
3273 mOffsetSpinBox->setClearValue( 0 );
3274 mAngleSpinBox->setClearValue( 0 );
3275
3276 mCoordinateReferenceComboBox->addItem( tr( "Align Pattern to Feature" ), static_cast<int>( Qgis::SymbolCoordinateReference::Feature ) );
3277 mCoordinateReferenceComboBox->addItem( tr( "Align Pattern to Map Extent" ), static_cast<int>( Qgis::SymbolCoordinateReference::Viewport ) );
3278 connect( mCoordinateReferenceComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this] {
3279 if ( mLayer )
3280 {
3281 mLayer->setCoordinateReference( static_cast<Qgis::SymbolCoordinateReference>( mCoordinateReferenceComboBox->currentData().toInt() ) );
3282 emit changed();
3283 }
3284 } );
3285
3286 mClipModeComboBox->addItem( tr( "Clip During Render Only" ), static_cast<int>( Qgis::LineClipMode::ClipPainterOnly ) );
3287 mClipModeComboBox->addItem( tr( "Clip Lines Before Render" ), static_cast<int>( Qgis::LineClipMode::ClipToIntersection ) );
3288 mClipModeComboBox->addItem( tr( "No Clipping" ), static_cast<int>( Qgis::LineClipMode::NoClipping ) );
3289 connect( mClipModeComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this] {
3290 if ( mLayer )
3291 {
3292 mLayer->setClipMode( static_cast<Qgis::LineClipMode>( mClipModeComboBox->currentData().toInt() ) );
3293 emit changed();
3294 }
3295 } );
3296}
3297
3299{
3300 if ( layer->layerType() != "LinePatternFill"_L1 )
3301 {
3302 return;
3303 }
3304
3305 QgsLinePatternFillSymbolLayer *patternLayer = static_cast<QgsLinePatternFillSymbolLayer *>( layer );
3306 if ( patternLayer )
3307 {
3308 mLayer = patternLayer;
3309 whileBlocking( mAngleSpinBox )->setValue( mLayer->lineAngle() );
3310 whileBlocking( mDistanceSpinBox )->setValue( mLayer->distance() );
3311 whileBlocking( mOffsetSpinBox )->setValue( mLayer->offset() );
3312
3313 //units
3314 mDistanceUnitWidget->blockSignals( true );
3315 mDistanceUnitWidget->setUnit( mLayer->distanceUnit() );
3316 mDistanceUnitWidget->setMapUnitScale( mLayer->distanceMapUnitScale() );
3317 mDistanceUnitWidget->blockSignals( false );
3318 mOffsetUnitWidget->blockSignals( true );
3319 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
3320 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
3321 mOffsetUnitWidget->blockSignals( false );
3322
3323 whileBlocking( mCoordinateReferenceComboBox )->setCurrentIndex( mCoordinateReferenceComboBox->findData( static_cast<int>( mLayer->coordinateReference() ) ) );
3324
3325 whileBlocking( mClipModeComboBox )->setCurrentIndex( mClipModeComboBox->findData( static_cast<int>( mLayer->clipMode() ) ) );
3326 }
3327
3332}
3333
3338
3339void QgsLinePatternFillSymbolLayerWidget::mAngleSpinBox_valueChanged( double d )
3340{
3341 if ( mLayer )
3342 {
3343 mLayer->setLineAngle( d );
3344 emit changed();
3345 }
3346}
3347
3348void QgsLinePatternFillSymbolLayerWidget::mDistanceSpinBox_valueChanged( double d )
3349{
3350 if ( mLayer )
3351 {
3352 mLayer->setDistance( d );
3353 emit changed();
3354 }
3355}
3356
3357void QgsLinePatternFillSymbolLayerWidget::mOffsetSpinBox_valueChanged( double d )
3358{
3359 if ( mLayer )
3360 {
3361 mLayer->setOffset( d );
3362 emit changed();
3363 }
3364}
3365
3366void QgsLinePatternFillSymbolLayerWidget::mDistanceUnitWidget_changed()
3367{
3368 if ( mLayer )
3369 {
3370 mLayer->setDistanceUnit( mDistanceUnitWidget->unit() );
3371 mLayer->setDistanceMapUnitScale( mDistanceUnitWidget->getMapUnitScale() );
3372 emit changed();
3373 }
3374}
3375
3376void QgsLinePatternFillSymbolLayerWidget::mOffsetUnitWidget_changed()
3377{
3378 if ( mLayer )
3379 {
3380 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
3381 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
3382 emit changed();
3383 }
3384}
3385
3387
3389 : QgsSymbolLayerWidget( parent, vl )
3390{
3391 setupUi( this );
3392 connect( mHorizontalDistanceSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsPointPatternFillSymbolLayerWidget::mHorizontalDistanceSpinBox_valueChanged );
3393 connect( mVerticalDistanceSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsPointPatternFillSymbolLayerWidget::mVerticalDistanceSpinBox_valueChanged );
3394 connect( mHorizontalDisplacementSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsPointPatternFillSymbolLayerWidget::mHorizontalDisplacementSpinBox_valueChanged );
3395 connect( mVerticalDisplacementSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsPointPatternFillSymbolLayerWidget::mVerticalDisplacementSpinBox_valueChanged );
3396 connect( mHorizontalOffsetSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsPointPatternFillSymbolLayerWidget::mHorizontalOffsetSpinBox_valueChanged );
3397 connect( mVerticalOffsetSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsPointPatternFillSymbolLayerWidget::mVerticalOffsetSpinBox_valueChanged );
3398 connect( mHorizontalDistanceUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointPatternFillSymbolLayerWidget::mHorizontalDistanceUnitWidget_changed );
3399 connect( mVerticalDistanceUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointPatternFillSymbolLayerWidget::mVerticalDistanceUnitWidget_changed );
3400 connect( mHorizontalDisplacementUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointPatternFillSymbolLayerWidget::mHorizontalDisplacementUnitWidget_changed );
3401 connect( mVerticalDisplacementUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointPatternFillSymbolLayerWidget::mVerticalDisplacementUnitWidget_changed );
3402 connect( mHorizontalOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointPatternFillSymbolLayerWidget::mHorizontalOffsetUnitWidget_changed );
3403 connect( mVerticalOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointPatternFillSymbolLayerWidget::mVerticalOffsetUnitWidget_changed );
3404 mHorizontalDistanceUnitWidget->setUnits(
3406 );
3407 mVerticalDistanceUnitWidget->setUnits(
3409 );
3410 mHorizontalDisplacementUnitWidget->setUnits(
3419 );
3420 mVerticalDisplacementUnitWidget->setUnits(
3429 );
3430 mHorizontalOffsetUnitWidget->setUnits(
3439 );
3440 mVerticalOffsetUnitWidget->setUnits(
3449 );
3450
3451 mClipModeComboBox->addItem( tr( "Clip to Shape" ), static_cast<int>( Qgis::MarkerClipMode::Shape ) );
3452 mClipModeComboBox->addItem( tr( "Marker Centroid Within Shape" ), static_cast<int>( Qgis::MarkerClipMode::CentroidWithin ) );
3453 mClipModeComboBox->addItem( tr( "Marker Completely Within Shape" ), static_cast<int>( Qgis::MarkerClipMode::CompletelyWithin ) );
3454 mClipModeComboBox->addItem( tr( "No Clipping" ), static_cast<int>( Qgis::MarkerClipMode::NoClipping ) );
3455 connect( mClipModeComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this] {
3456 if ( mLayer )
3457 {
3458 mLayer->setClipMode( static_cast<Qgis::MarkerClipMode>( mClipModeComboBox->currentData().toInt() ) );
3459 emit changed();
3460 }
3461 } );
3462
3463 mCoordinateReferenceComboBox->addItem( tr( "Align Pattern to Feature" ), static_cast<int>( Qgis::SymbolCoordinateReference::Feature ) );
3464 mCoordinateReferenceComboBox->addItem( tr( "Align Pattern to Map Extent" ), static_cast<int>( Qgis::SymbolCoordinateReference::Viewport ) );
3465 connect( mCoordinateReferenceComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this] {
3466 if ( mLayer )
3467 {
3468 mLayer->setCoordinateReference( static_cast<Qgis::SymbolCoordinateReference>( mCoordinateReferenceComboBox->currentData().toInt() ) );
3469 emit changed();
3470 }
3471 } );
3472
3473 mSeedSpinBox->setShowClearButton( true );
3474 mSeedSpinBox->setClearValue( 0 );
3475 mRandomXSpinBox->setClearValue( 0 );
3476 mRandomYSpinBox->setClearValue( 0 );
3477
3478 mRandomXOffsetUnitWidget->setUnits(
3487 );
3488 mRandomYOffsetUnitWidget->setUnits(
3497 );
3498 connect( mRandomXSpinBox, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double d ) {
3499 if ( mLayer )
3500 {
3501 mLayer->setMaximumRandomDeviationX( d );
3502 emit changed();
3503 }
3504 } );
3505 connect( mRandomYSpinBox, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double d ) {
3506 if ( mLayer )
3507 {
3508 mLayer->setMaximumRandomDeviationY( d );
3509 emit changed();
3510 }
3511 } );
3512 connect( mRandomXOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
3513 if ( mLayer )
3514 {
3515 mLayer->setRandomDeviationXUnit( mRandomXOffsetUnitWidget->unit() );
3516 mLayer->setRandomDeviationXMapUnitScale( mRandomXOffsetUnitWidget->getMapUnitScale() );
3517 emit changed();
3518 }
3519 } );
3520 connect( mRandomYOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
3521 if ( mLayer )
3522 {
3523 mLayer->setRandomDeviationYUnit( mRandomYOffsetUnitWidget->unit() );
3524 mLayer->setRandomDeviationYMapUnitScale( mRandomYOffsetUnitWidget->getMapUnitScale() );
3525 emit changed();
3526 }
3527 } );
3528 connect( mSeedSpinBox, qOverload<int>( &QSpinBox::valueChanged ), this, [this]( int v ) {
3529 if ( mLayer )
3530 {
3531 mLayer->setSeed( v );
3532 emit changed();
3533 }
3534 } );
3535
3536 mAngleSpinBox->setShowClearButton( true );
3537 mAngleSpinBox->setClearValue( 0 );
3538 connect( mAngleSpinBox, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double d ) {
3539 if ( mLayer )
3540 {
3541 mLayer->setAngle( d );
3542 emit changed();
3543 }
3544 } );
3545}
3546
3548{
3549 if ( !layer || layer->layerType() != "PointPatternFill"_L1 )
3550 {
3551 return;
3552 }
3553
3554 mLayer = static_cast<QgsPointPatternFillSymbolLayer *>( layer );
3555 whileBlocking( mHorizontalDistanceSpinBox )->setValue( mLayer->distanceX() );
3556 whileBlocking( mVerticalDistanceSpinBox )->setValue( mLayer->distanceY() );
3557 whileBlocking( mHorizontalDisplacementSpinBox )->setValue( mLayer->displacementX() );
3558 whileBlocking( mVerticalDisplacementSpinBox )->setValue( mLayer->displacementY() );
3559 whileBlocking( mHorizontalOffsetSpinBox )->setValue( mLayer->offsetX() );
3560 whileBlocking( mVerticalOffsetSpinBox )->setValue( mLayer->offsetY() );
3561 whileBlocking( mAngleSpinBox )->setValue( mLayer->angle() );
3562
3563 mHorizontalDistanceUnitWidget->blockSignals( true );
3564 mHorizontalDistanceUnitWidget->setUnit( mLayer->distanceXUnit() );
3565 mHorizontalDistanceUnitWidget->setMapUnitScale( mLayer->distanceXMapUnitScale() );
3566 mHorizontalDistanceUnitWidget->blockSignals( false );
3567 mVerticalDistanceUnitWidget->blockSignals( true );
3568 mVerticalDistanceUnitWidget->setUnit( mLayer->distanceYUnit() );
3569 mVerticalDistanceUnitWidget->setMapUnitScale( mLayer->distanceYMapUnitScale() );
3570 mVerticalDistanceUnitWidget->blockSignals( false );
3571 mHorizontalDisplacementUnitWidget->blockSignals( true );
3572 mHorizontalDisplacementUnitWidget->setUnit( mLayer->displacementXUnit() );
3573 mHorizontalDisplacementUnitWidget->setMapUnitScale( mLayer->displacementXMapUnitScale() );
3574 mHorizontalDisplacementUnitWidget->blockSignals( false );
3575 mVerticalDisplacementUnitWidget->blockSignals( true );
3576 mVerticalDisplacementUnitWidget->setUnit( mLayer->displacementYUnit() );
3577 mVerticalDisplacementUnitWidget->setMapUnitScale( mLayer->displacementYMapUnitScale() );
3578 mVerticalDisplacementUnitWidget->blockSignals( false );
3579 mHorizontalOffsetUnitWidget->blockSignals( true );
3580 mHorizontalOffsetUnitWidget->setUnit( mLayer->offsetXUnit() );
3581 mHorizontalOffsetUnitWidget->setMapUnitScale( mLayer->offsetXMapUnitScale() );
3582 mHorizontalOffsetUnitWidget->blockSignals( false );
3583 mVerticalOffsetUnitWidget->blockSignals( true );
3584 mVerticalOffsetUnitWidget->setUnit( mLayer->offsetYUnit() );
3585 mVerticalOffsetUnitWidget->setMapUnitScale( mLayer->offsetYMapUnitScale() );
3586 mVerticalOffsetUnitWidget->blockSignals( false );
3587
3588 whileBlocking( mClipModeComboBox )->setCurrentIndex( mClipModeComboBox->findData( static_cast<int>( mLayer->clipMode() ) ) );
3589 whileBlocking( mCoordinateReferenceComboBox )->setCurrentIndex( mCoordinateReferenceComboBox->findData( static_cast<int>( mLayer->coordinateReference() ) ) );
3590
3591 whileBlocking( mRandomXSpinBox )->setValue( mLayer->maximumRandomDeviationX() );
3592 whileBlocking( mRandomYSpinBox )->setValue( mLayer->maximumRandomDeviationY() );
3593 whileBlocking( mRandomXOffsetUnitWidget )->setUnit( mLayer->randomDeviationXUnit() );
3594 whileBlocking( mRandomXOffsetUnitWidget )->setMapUnitScale( mLayer->randomDeviationXMapUnitScale() );
3595 whileBlocking( mRandomYOffsetUnitWidget )->setUnit( mLayer->randomDeviationYUnit() );
3596 whileBlocking( mRandomYOffsetUnitWidget )->setMapUnitScale( mLayer->randomDeviationYMapUnitScale() );
3597 whileBlocking( mSeedSpinBox )->setValue( mLayer->seed() );
3598
3611}
3612
3617
3618void QgsPointPatternFillSymbolLayerWidget::mHorizontalDistanceSpinBox_valueChanged( double d )
3619{
3620 if ( mLayer )
3621 {
3622 mLayer->setDistanceX( d );
3623 emit changed();
3624 }
3625}
3626
3627void QgsPointPatternFillSymbolLayerWidget::mVerticalDistanceSpinBox_valueChanged( double d )
3628{
3629 if ( mLayer )
3630 {
3631 mLayer->setDistanceY( d );
3632 emit changed();
3633 }
3634}
3635
3636void QgsPointPatternFillSymbolLayerWidget::mHorizontalDisplacementSpinBox_valueChanged( double d )
3637{
3638 if ( mLayer )
3639 {
3640 mLayer->setDisplacementX( d );
3641 emit changed();
3642 }
3643}
3644
3645void QgsPointPatternFillSymbolLayerWidget::mVerticalDisplacementSpinBox_valueChanged( double d )
3646{
3647 if ( mLayer )
3648 {
3649 mLayer->setDisplacementY( d );
3650 emit changed();
3651 }
3652}
3653
3654void QgsPointPatternFillSymbolLayerWidget::mHorizontalOffsetSpinBox_valueChanged( double d )
3655{
3656 if ( mLayer )
3657 {
3658 mLayer->setOffsetX( d );
3659 emit changed();
3660 }
3661}
3662
3663void QgsPointPatternFillSymbolLayerWidget::mVerticalOffsetSpinBox_valueChanged( double d )
3664{
3665 if ( mLayer )
3666 {
3667 mLayer->setOffsetY( d );
3668 emit changed();
3669 }
3670}
3671
3672void QgsPointPatternFillSymbolLayerWidget::mHorizontalDistanceUnitWidget_changed()
3673{
3674 if ( mLayer )
3675 {
3676 mLayer->setDistanceXUnit( mHorizontalDistanceUnitWidget->unit() );
3677 mLayer->setDistanceXMapUnitScale( mHorizontalDistanceUnitWidget->getMapUnitScale() );
3678 emit changed();
3679 }
3680}
3681
3682void QgsPointPatternFillSymbolLayerWidget::mVerticalDistanceUnitWidget_changed()
3683{
3684 if ( mLayer )
3685 {
3686 mLayer->setDistanceYUnit( mVerticalDistanceUnitWidget->unit() );
3687 mLayer->setDistanceYMapUnitScale( mVerticalDistanceUnitWidget->getMapUnitScale() );
3688 emit changed();
3689 }
3690}
3691
3692void QgsPointPatternFillSymbolLayerWidget::mHorizontalDisplacementUnitWidget_changed()
3693{
3694 if ( mLayer )
3695 {
3696 mLayer->setDisplacementXUnit( mHorizontalDisplacementUnitWidget->unit() );
3697 mLayer->setDisplacementXMapUnitScale( mHorizontalDisplacementUnitWidget->getMapUnitScale() );
3698 emit changed();
3699 }
3700}
3701
3702void QgsPointPatternFillSymbolLayerWidget::mVerticalDisplacementUnitWidget_changed()
3703{
3704 if ( mLayer )
3705 {
3706 mLayer->setDisplacementYUnit( mVerticalDisplacementUnitWidget->unit() );
3707 mLayer->setDisplacementYMapUnitScale( mVerticalDisplacementUnitWidget->getMapUnitScale() );
3708 emit changed();
3709 }
3710}
3711
3712void QgsPointPatternFillSymbolLayerWidget::mHorizontalOffsetUnitWidget_changed()
3713{
3714 if ( mLayer )
3715 {
3716 mLayer->setOffsetXUnit( mHorizontalOffsetUnitWidget->unit() );
3717 mLayer->setOffsetXMapUnitScale( mHorizontalOffsetUnitWidget->getMapUnitScale() );
3718 emit changed();
3719 }
3720}
3721
3722void QgsPointPatternFillSymbolLayerWidget::mVerticalOffsetUnitWidget_changed()
3723{
3724 if ( mLayer )
3725 {
3726 mLayer->setOffsetYUnit( mVerticalOffsetUnitWidget->unit() );
3727 mLayer->setOffsetYMapUnitScale( mVerticalOffsetUnitWidget->getMapUnitScale() );
3728 emit changed();
3729 }
3730}
3731
3733
3735 : QgsSymbolLayerWidget( parent, vl )
3736{
3737 mLayer = nullptr;
3738
3739 setupUi( this );
3740
3741 mHorizontalAnchorComboBox->addItem( tr( "Left" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Left ) );
3742 mHorizontalAnchorComboBox->addItem( tr( "Horizontal Center" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Center ) );
3743 mHorizontalAnchorComboBox->addItem( tr( "Right" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Right ) );
3744
3745 mVerticalAnchorComboBox->addItem( tr( "Top" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Top ) );
3746 mVerticalAnchorComboBox->addItem( tr( "Vertical Center" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Center ) );
3747 mVerticalAnchorComboBox->addItem( tr( "Bottom on Baseline" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Baseline ) );
3748 mVerticalAnchorComboBox->addItem( tr( "Bottom" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Bottom ) );
3749
3750 connect( mSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsFontMarkerSymbolLayerWidget::mSizeUnitWidget_changed );
3751 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsFontMarkerSymbolLayerWidget::mOffsetUnitWidget_changed );
3752 connect( mStrokeWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsFontMarkerSymbolLayerWidget::mStrokeWidthUnitWidget_changed );
3753 connect( mStrokeWidthSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsFontMarkerSymbolLayerWidget::mStrokeWidthSpinBox_valueChanged );
3754 connect( mHorizontalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsFontMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged );
3755 connect( mVerticalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsFontMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged );
3756 mSizeUnitWidget->setUnits(
3758 );
3759 mStrokeWidthUnitWidget->setUnits(
3761 );
3762 mOffsetUnitWidget->setUnits(
3764 );
3765
3767 scrollArea->setWidget( widgetChar );
3768 scrollArea->setVerticalOnly( true );
3769
3770 btnColor->setAllowOpacity( true );
3771 btnColor->setColorDialogTitle( tr( "Select Symbol Fill Color" ) );
3772 btnColor->setContext( u"symbology"_s );
3773 btnStrokeColor->setAllowOpacity( true );
3774 btnStrokeColor->setColorDialogTitle( tr( "Select Symbol Stroke Color" ) );
3775 btnStrokeColor->setContext( u"symbology"_s );
3776
3777 mColorDDBtn->registerLinkedWidget( btnColor );
3778 mStrokeColorDDBtn->registerLinkedWidget( btnStrokeColor );
3779
3780 spinOffsetX->setClearValue( 0.0 );
3781 spinOffsetY->setClearValue( 0.0 );
3782 spinAngle->setClearValue( 0.0 );
3783
3784 //make a temporary symbol for the size assistant preview
3785 mAssistantPreviewSymbol = std::make_shared<QgsMarkerSymbol>();
3786
3787 if ( vectorLayer() )
3788 mSizeDDBtn->setSymbol( mAssistantPreviewSymbol );
3789
3790 connect( cboFont, &QFontComboBox::currentFontChanged, this, &QgsFontMarkerSymbolLayerWidget::setFontFamily );
3791 connect( mFontStyleComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsFontMarkerSymbolLayerWidget::mFontStyleComboBox_currentIndexChanged );
3792 connect( spinSize, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsFontMarkerSymbolLayerWidget::setSize );
3793 connect( cboJoinStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsFontMarkerSymbolLayerWidget::penJoinStyleChanged );
3796 connect( cboJoinStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsFontMarkerSymbolLayerWidget::penJoinStyleChanged );
3797 connect( spinAngle, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsFontMarkerSymbolLayerWidget::setAngle );
3798 connect( spinOffsetX, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsFontMarkerSymbolLayerWidget::setOffset );
3799 connect( spinOffsetY, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsFontMarkerSymbolLayerWidget::setOffset );
3801 connect( mCharLineEdit, &QLineEdit::textChanged, this, &QgsFontMarkerSymbolLayerWidget::setCharacterFromText );
3802
3803 connect( this, &QgsSymbolLayerWidget::changed, this, &QgsFontMarkerSymbolLayerWidget::updateAssistantSymbol );
3804}
3805
3807
3809{
3810 if ( layer->layerType() != "FontMarker"_L1 )
3811 return;
3812
3813 // layer type is correct, we can do the cast
3814 mLayer = static_cast<QgsFontMarkerSymbolLayer *>( layer );
3815
3816 QgsFontUtils::setFontFamily( mRefFont, mLayer->fontFamily() );
3817 mRefFont.setStyleName( QgsFontUtils::translateNamedStyle( mLayer->fontStyle() ) );
3818
3819 mFontStyleComboBox->blockSignals( true );
3820 populateFontStyleComboBox();
3821 mFontStyleComboBox->blockSignals( false );
3822
3823 // set values
3824 whileBlocking( cboFont )->setCurrentFont( mRefFont );
3825 whileBlocking( spinSize )->setValue( mLayer->size() );
3826 whileBlocking( btnColor )->setColor( mLayer->color() );
3827 whileBlocking( btnStrokeColor )->setColor( mLayer->strokeColor() );
3828 whileBlocking( mStrokeWidthSpinBox )->setValue( mLayer->strokeWidth() );
3829 whileBlocking( spinAngle )->setValue( mLayer->angle() );
3830
3831 widgetChar->blockSignals( true );
3832 widgetChar->setFont( mRefFont );
3833 if ( mLayer->character().length() == 1 )
3834 {
3835 widgetChar->setCharacter( mLayer->character().at( 0 ) );
3836 }
3837 widgetChar->blockSignals( false );
3838 whileBlocking( mCharLineEdit )->setText( mLayer->character() );
3839 mCharPreview->setFont( mRefFont );
3840
3841 //block
3842 whileBlocking( spinOffsetX )->setValue( mLayer->offset().x() );
3843 whileBlocking( spinOffsetY )->setValue( mLayer->offset().y() );
3844
3845 mSizeUnitWidget->blockSignals( true );
3846 mSizeUnitWidget->setUnit( mLayer->sizeUnit() );
3847 mSizeUnitWidget->setMapUnitScale( mLayer->sizeMapUnitScale() );
3848 mSizeUnitWidget->blockSignals( false );
3849
3850 mStrokeWidthUnitWidget->blockSignals( true );
3851 mStrokeWidthUnitWidget->setUnit( mLayer->strokeWidthUnit() );
3852 mStrokeWidthUnitWidget->setMapUnitScale( mLayer->strokeWidthMapUnitScale() );
3853 mStrokeWidthUnitWidget->blockSignals( false );
3854
3855 mOffsetUnitWidget->blockSignals( true );
3856 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
3857 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
3858 mOffsetUnitWidget->blockSignals( false );
3859
3860 whileBlocking( cboJoinStyle )->setPenJoinStyle( mLayer->penJoinStyle() );
3861
3862 //anchor points
3863 whileBlocking( mHorizontalAnchorComboBox )->setCurrentIndex( mHorizontalAnchorComboBox->findData( QVariant::fromValue( mLayer->horizontalAnchorPoint() ) ) );
3864 whileBlocking( mVerticalAnchorComboBox )->setCurrentIndex( mVerticalAnchorComboBox->findData( QVariant::fromValue( mLayer->verticalAnchorPoint() ) ) );
3865
3878
3879 updateAssistantSymbol();
3880}
3881
3886
3888{
3889 if ( mLayer )
3890 {
3891 mLayer->setFontFamily( font.family() );
3892 QgsFontUtils::setFontFamily( mRefFont, font.family() );
3893 widgetChar->setFont( mRefFont );
3894 mCharPreview->setFont( mRefFont );
3895 populateFontStyleComboBox();
3896 emit changed();
3897 }
3898}
3899
3900void QgsFontMarkerSymbolLayerWidget::setFontStyle( const QString &style )
3901{
3902 if ( mLayer )
3903 {
3904 QgsFontUtils::updateFontViaStyle( mRefFont, style );
3906 widgetChar->setFont( mRefFont );
3907 mCharPreview->setFont( mRefFont );
3908 emit changed();
3909 }
3910}
3911
3913{
3914 mLayer->setColor( color );
3915 emit changed();
3916}
3917
3919{
3920 mLayer->setStrokeColor( color );
3921 emit changed();
3922}
3923
3925{
3926 mLayer->setSize( size );
3927 //widgetChar->updateSize(size);
3928 emit changed();
3929}
3930
3932{
3933 mLayer->setAngle( angle );
3934 emit changed();
3935}
3936
3938{
3939 mCharPreview->setText( text );
3940
3941 if ( text.isEmpty() )
3942 return;
3943
3944 // take the last character of a string for a better experience when users cycle through several characters on their keyboard
3945 QString character = text;
3946 if ( text.contains( QRegularExpression( u"^0x[0-9a-fA-F]{1,4}$"_s ) ) )
3947 {
3948 bool ok = false;
3949 const unsigned int value = text.toUInt( &ok, 0 );
3950 if ( ok )
3951 {
3952 character = QChar( value );
3953 mCharPreview->setText( character );
3954 }
3955 }
3956
3957 if ( character != mLayer->character() )
3958 {
3959 mLayer->setCharacter( character );
3960 if ( mLayer->character().length() == 1 )
3961 {
3962 whileBlocking( widgetChar )->setCharacter( mLayer->character().at( 0 ) );
3963 }
3964 else
3965 {
3966 widgetChar->clearCharacter();
3967 }
3968 emit changed();
3969 }
3970}
3971
3973{
3974 if ( mLayer->character().length() > 1 || QGuiApplication::keyboardModifiers() & Qt::ControlModifier )
3975 {
3976 mCharLineEdit->insert( chr );
3977 return;
3978 }
3979
3980 mLayer->setCharacter( chr );
3981 whileBlocking( mCharLineEdit )->setText( chr );
3982 mCharPreview->setText( chr );
3983 emit changed();
3984}
3985
3986void QgsFontMarkerSymbolLayerWidget::setOffset()
3987{
3988 mLayer->setOffset( QPointF( spinOffsetX->value(), spinOffsetY->value() ) );
3989 emit changed();
3990}
3991
3992void QgsFontMarkerSymbolLayerWidget::penJoinStyleChanged()
3993{
3994 mLayer->setPenJoinStyle( cboJoinStyle->penJoinStyle() );
3995 emit changed();
3996}
3997
3998void QgsFontMarkerSymbolLayerWidget::mSizeUnitWidget_changed()
3999{
4000 if ( mLayer )
4001 {
4002 mLayer->setSizeUnit( mSizeUnitWidget->unit() );
4003 mLayer->setSizeMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
4004 emit changed();
4005 }
4006}
4007
4008void QgsFontMarkerSymbolLayerWidget::mOffsetUnitWidget_changed()
4009{
4010 if ( mLayer )
4011 {
4012 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
4013 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
4014 emit changed();
4015 }
4016}
4017
4018void QgsFontMarkerSymbolLayerWidget::mStrokeWidthUnitWidget_changed()
4019{
4020 if ( mLayer )
4021 {
4022 mLayer->setStrokeWidthUnit( mSizeUnitWidget->unit() );
4023 mLayer->setStrokeWidthMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
4024 emit changed();
4025 }
4026}
4027
4028void QgsFontMarkerSymbolLayerWidget::populateFontStyleComboBox()
4029{
4030 mFontStyleComboBox->clear();
4031 const QStringList styles = mFontDB.styles( mRefFont.family() );
4032 const auto constStyles = styles;
4033 for ( const QString &style : constStyles )
4034 {
4035 mFontStyleComboBox->addItem( style );
4036 }
4037
4038 QString targetStyle = mFontDB.styleString( mRefFont );
4039 if ( !styles.contains( targetStyle ) )
4040 {
4041 const QFont f = QgsFontUtils::createFont( mRefFont.family() );
4042 targetStyle = QFontInfo( f ).styleName();
4043 mRefFont.setStyleName( targetStyle );
4044 }
4045 int curIndx = 0;
4046 const int stylIndx = mFontStyleComboBox->findText( targetStyle );
4047 if ( stylIndx > -1 )
4048 {
4049 curIndx = stylIndx;
4050 }
4051
4052 mFontStyleComboBox->setCurrentIndex( curIndx );
4053}
4054
4055void QgsFontMarkerSymbolLayerWidget::mFontStyleComboBox_currentIndexChanged( int index )
4056{
4057 Q_UNUSED( index );
4058 setFontStyle( mFontStyleComboBox->currentText() );
4059}
4060
4061void QgsFontMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged( int )
4062{
4063 if ( mLayer )
4064 {
4065 mLayer->setHorizontalAnchorPoint( mHorizontalAnchorComboBox->currentData().value< Qgis::HorizontalAnchorPoint >() );
4066 emit changed();
4067 }
4068}
4069
4070void QgsFontMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged( int )
4071{
4072 if ( mLayer )
4073 {
4074 mLayer->setVerticalAnchorPoint( mVerticalAnchorComboBox->currentData().value< Qgis::VerticalAnchorPoint >() );
4075 emit changed();
4076 }
4077}
4078
4079void QgsFontMarkerSymbolLayerWidget::mStrokeWidthSpinBox_valueChanged( double d )
4080{
4081 if ( mLayer )
4082 {
4083 mLayer->setStrokeWidth( d );
4084 emit changed();
4085 }
4086}
4087
4088void QgsFontMarkerSymbolLayerWidget::updateAssistantSymbol()
4089{
4090 for ( int i = mAssistantPreviewSymbol->symbolLayerCount() - 1; i >= 0; --i )
4091 {
4092 mAssistantPreviewSymbol->deleteSymbolLayer( i );
4093 }
4094 mAssistantPreviewSymbol->appendSymbolLayer( mLayer->clone() );
4095 const QgsProperty ddSize = mLayer->dataDefinedProperties().property( QgsSymbolLayer::Property::Size );
4096 if ( ddSize )
4097 mAssistantPreviewSymbol->setDataDefinedSize( ddSize );
4098}
4099
4101
4102
4104 : QgsSymbolLayerWidget( parent, vl )
4105{
4106 mLayer = nullptr;
4107
4108 setupUi( this );
4109 connect( mDrawInsideCheckBox, &QCheckBox::stateChanged, this, &QgsCentroidFillSymbolLayerWidget::mDrawInsideCheckBox_stateChanged );
4110 connect( mDrawAllPartsCheckBox, &QCheckBox::stateChanged, this, &QgsCentroidFillSymbolLayerWidget::mDrawAllPartsCheckBox_stateChanged );
4111 connect( mClipPointsCheckBox, &QCheckBox::stateChanged, this, &QgsCentroidFillSymbolLayerWidget::mClipPointsCheckBox_stateChanged );
4112 connect( mClipOnCurrentPartOnlyCheckBox, &QCheckBox::stateChanged, this, &QgsCentroidFillSymbolLayerWidget::mClipOnCurrentPartOnlyCheckBox_stateChanged );
4113}
4114
4116{
4117 if ( layer->layerType() != "CentroidFill"_L1 )
4118 return;
4119
4120 // layer type is correct, we can do the cast
4121 mLayer = static_cast<QgsCentroidFillSymbolLayer *>( layer );
4122
4123 // set values
4124 whileBlocking( mDrawInsideCheckBox )->setChecked( mLayer->pointOnSurface() );
4125 whileBlocking( mDrawAllPartsCheckBox )->setChecked( mLayer->pointOnAllParts() );
4126 whileBlocking( mClipPointsCheckBox )->setChecked( mLayer->clipPoints() );
4127 whileBlocking( mClipOnCurrentPartOnlyCheckBox )->setChecked( mLayer->clipOnCurrentPartOnly() );
4128}
4129
4134
4135void QgsCentroidFillSymbolLayerWidget::mDrawInsideCheckBox_stateChanged( int state )
4136{
4137 mLayer->setPointOnSurface( state == Qt::Checked );
4138 emit changed();
4139}
4140
4141void QgsCentroidFillSymbolLayerWidget::mDrawAllPartsCheckBox_stateChanged( int state )
4142{
4143 mLayer->setPointOnAllParts( state == Qt::Checked );
4144 emit changed();
4145}
4146
4147void QgsCentroidFillSymbolLayerWidget::mClipPointsCheckBox_stateChanged( int state )
4148{
4149 mLayer->setClipPoints( state == Qt::Checked );
4150 emit changed();
4151}
4152
4153void QgsCentroidFillSymbolLayerWidget::mClipOnCurrentPartOnlyCheckBox_stateChanged( int state )
4154{
4155 mLayer->setClipOnCurrentPartOnly( state == Qt::Checked );
4156 emit changed();
4157}
4158
4160
4162 : QgsSymbolLayerWidget( parent, vl )
4163{
4164 mLayer = nullptr;
4165
4166 setupUi( this );
4167
4168 mHorizontalAnchorComboBox->addItem( tr( "Left" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Left ) );
4169 mHorizontalAnchorComboBox->addItem( tr( "Horizontal Center" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Center ) );
4170 mHorizontalAnchorComboBox->addItem( tr( "Right" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Right ) );
4171
4172 mVerticalAnchorComboBox->addItem( tr( "Top" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Top ) );
4173 mVerticalAnchorComboBox->addItem( tr( "Vertical Center" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Center ) );
4174 mVerticalAnchorComboBox->addItem( tr( "Bottom" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Bottom ) );
4175
4176 mImageSourceLineEdit->setLastPathSettingsKey( u"/UI/lastRasterMarkerImageDir"_s );
4177
4178 connect( mImageSourceLineEdit, &QgsImageSourceLineEdit::sourceChanged, this, &QgsRasterMarkerSymbolLayerWidget::imageSourceChanged );
4179 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsRasterMarkerSymbolLayerWidget::mOffsetUnitWidget_changed );
4180 connect( mRotationSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsRasterMarkerSymbolLayerWidget::setAngle );
4181 connect( mSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsRasterMarkerSymbolLayerWidget::mSizeUnitWidget_changed );
4182 connect( mWidthSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsRasterMarkerSymbolLayerWidget::setWidth );
4183 connect( mHeightSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsRasterMarkerSymbolLayerWidget::setHeight );
4184 connect( mLockAspectRatio, static_cast<void ( QgsRatioLockButton::* )( bool )>( &QgsRatioLockButton::lockChanged ), this, &QgsRasterMarkerSymbolLayerWidget::setLockAspectRatio );
4185
4186 mSizeUnitWidget->setUnits(
4195 );
4196 mOffsetUnitWidget->setUnits(
4198 );
4199
4200 mSpinOffsetX->setClearValue( 0.0 );
4201 mSpinOffsetY->setClearValue( 0.0 );
4202 mRotationSpinBox->setClearValue( 0.0 );
4203
4204 connect( mSpinOffsetX, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsRasterMarkerSymbolLayerWidget::setOffset );
4205 connect( mSpinOffsetY, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsRasterMarkerSymbolLayerWidget::setOffset );
4206 connect( mOpacityWidget, &QgsOpacityWidget::opacityChanged, this, &QgsRasterMarkerSymbolLayerWidget::setOpacity );
4207
4208 connect( mHorizontalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsRasterMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged );
4209 connect( mVerticalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsRasterMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged );
4210}
4211
4213{
4214 if ( !layer )
4215 {
4216 return;
4217 }
4218
4219 if ( layer->layerType() != "RasterMarker"_L1 )
4220 return;
4221
4222 // layer type is correct, we can do the cast
4223 mLayer = static_cast<QgsRasterMarkerSymbolLayer *>( layer );
4224
4225 // set values
4226 whileBlocking( mImageSourceLineEdit )->setSource( mLayer->path() );
4227
4228 whileBlocking( mWidthSpinBox )->setValue( mLayer->size() );
4229 const bool preservedAspectRatio = mLayer->preservedAspectRatio();
4230 mHeightSpinBox->blockSignals( true );
4231 if ( preservedAspectRatio )
4232 {
4233 mHeightSpinBox->setValue( mLayer->size() );
4234 }
4235 else
4236 {
4237 mHeightSpinBox->setValue( mLayer->size() * mLayer->fixedAspectRatio() );
4238 }
4239 mHeightSpinBox->setEnabled( mLayer->defaultAspectRatio() > 0.0 );
4240 mHeightSpinBox->blockSignals( false );
4241 whileBlocking( mLockAspectRatio )->setLocked( preservedAspectRatio );
4242
4243 whileBlocking( mRotationSpinBox )->setValue( mLayer->angle() );
4244 whileBlocking( mOpacityWidget )->setOpacity( mLayer->opacity() );
4245
4246 whileBlocking( mSpinOffsetX )->setValue( mLayer->offset().x() );
4247 whileBlocking( mSpinOffsetY )->setValue( mLayer->offset().y() );
4248
4249 mSizeUnitWidget->blockSignals( true );
4250 mSizeUnitWidget->setUnit( mLayer->sizeUnit() );
4251 mSizeUnitWidget->setMapUnitScale( mLayer->sizeMapUnitScale() );
4252 mSizeUnitWidget->blockSignals( false );
4253 mOffsetUnitWidget->blockSignals( true );
4254 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
4255 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
4256 mOffsetUnitWidget->blockSignals( false );
4257
4258 //anchor points
4259 whileBlocking( mHorizontalAnchorComboBox )->setCurrentIndex( mHorizontalAnchorComboBox->findData( QVariant::fromValue( mLayer->horizontalAnchorPoint() ) ) );
4260 whileBlocking( mVerticalAnchorComboBox )->setCurrentIndex( mVerticalAnchorComboBox->findData( QVariant::fromValue( mLayer->verticalAnchorPoint() ) ) );
4261
4270
4271 updatePreviewImage();
4272}
4273
4278
4280{
4282 mImageSourceLineEdit->setMessageBar( context.messageBar() );
4283}
4284
4285void QgsRasterMarkerSymbolLayerWidget::imageSourceChanged( const QString &text )
4286{
4287 mLayer->setPath( text );
4288 updatePreviewImage();
4289 emit changed();
4290}
4291
4292void QgsRasterMarkerSymbolLayerWidget::updatePreviewImage()
4293{
4294 bool fitsInCache = false;
4295 const QImage image = QgsApplication::imageCache()->pathAsImage( mLayer->path(), QSize( 150, 150 ), true, 1.0, fitsInCache );
4296 if ( image.isNull() )
4297 {
4298 mLabelImagePreview->setPixmap( QPixmap() );
4299 return;
4300 }
4301
4302 QImage previewImage( 150, 150, QImage::Format_ARGB32 );
4303 previewImage.fill( Qt::transparent );
4304 const QRect imageRect( ( 150 - image.width() ) / 2.0, ( 150 - image.height() ) / 2.0, image.width(), image.height() );
4305 QPainter p;
4306 p.begin( &previewImage );
4307 //draw a checkerboard background
4308 uchar pixDataRGB[] = { 150, 150, 150, 150, 100, 100, 100, 150, 100, 100, 100, 150, 150, 150, 150, 150 };
4309 const QImage img( pixDataRGB, 2, 2, 8, QImage::Format_ARGB32 );
4310 const QPixmap pix = QPixmap::fromImage( img.scaled( 8, 8 ) );
4311 QBrush checkerBrush;
4312 checkerBrush.setTexture( pix );
4313 p.fillRect( imageRect, checkerBrush );
4314
4315 if ( mLayer->opacity() < 1.0 )
4316 {
4317 p.setOpacity( mLayer->opacity() );
4318 }
4319
4320 p.drawImage( imageRect.left(), imageRect.top(), image );
4321 p.end();
4322 mLabelImagePreview->setPixmap( QPixmap::fromImage( previewImage ) );
4323}
4324
4325void QgsRasterMarkerSymbolLayerWidget::setWidth()
4326{
4327 const double defaultAspectRatio = mLayer->defaultAspectRatio();
4328 double fixedAspectRatio = 0.0;
4329 mHeightSpinBox->blockSignals( true );
4330 if ( defaultAspectRatio <= 0.0 )
4331 {
4332 mHeightSpinBox->setValue( mWidthSpinBox->value() );
4333 }
4334 else if ( mLockAspectRatio->locked() )
4335 {
4336 mHeightSpinBox->setValue( mWidthSpinBox->value() * defaultAspectRatio );
4337 }
4338 else
4339 {
4340 fixedAspectRatio = mHeightSpinBox->value() / mWidthSpinBox->value();
4341 }
4342 mHeightSpinBox->blockSignals( false );
4343 mLayer->setSize( mWidthSpinBox->value() );
4344 mLayer->setFixedAspectRatio( fixedAspectRatio );
4345 emit changed();
4346}
4347
4348void QgsRasterMarkerSymbolLayerWidget::setHeight()
4349{
4350 const double defaultAspectRatio = mLayer->defaultAspectRatio();
4351 double fixedAspectRatio = 0.0;
4352 mWidthSpinBox->blockSignals( true );
4353 if ( defaultAspectRatio <= 0.0 )
4354 {
4355 mWidthSpinBox->setValue( mHeightSpinBox->value() );
4356 }
4357 else if ( mLockAspectRatio->locked() )
4358 {
4359 mWidthSpinBox->setValue( mHeightSpinBox->value() / defaultAspectRatio );
4360 }
4361 else
4362 {
4363 fixedAspectRatio = mHeightSpinBox->value() / mWidthSpinBox->value();
4364 }
4365 mWidthSpinBox->blockSignals( false );
4366 mLayer->setSize( mWidthSpinBox->value() );
4367 mLayer->setFixedAspectRatio( fixedAspectRatio );
4368 emit changed();
4369}
4370
4371void QgsRasterMarkerSymbolLayerWidget::setLockAspectRatio( const bool locked )
4372{
4373 const double defaultAspectRatio = mLayer->defaultAspectRatio();
4374 if ( defaultAspectRatio <= 0.0 )
4375 {
4376 whileBlocking( mLockAspectRatio )->setLocked( true );
4377 }
4378 else if ( locked )
4379 {
4380 mLayer->setFixedAspectRatio( 0.0 );
4381 setWidth();
4382 }
4383 else
4384 {
4385 mLayer->setFixedAspectRatio( mHeightSpinBox->value() / mWidthSpinBox->value() );
4386 }
4387}
4388
4389void QgsRasterMarkerSymbolLayerWidget::setAngle()
4390{
4391 mLayer->setAngle( mRotationSpinBox->value() );
4392 emit changed();
4393}
4394
4395void QgsRasterMarkerSymbolLayerWidget::setOpacity( double value )
4396{
4397 mLayer->setOpacity( value );
4398 emit changed();
4399 updatePreviewImage();
4400}
4401
4402void QgsRasterMarkerSymbolLayerWidget::setOffset()
4403{
4404 mLayer->setOffset( QPointF( mSpinOffsetX->value(), mSpinOffsetY->value() ) );
4405 emit changed();
4406}
4407
4408void QgsRasterMarkerSymbolLayerWidget::mSizeUnitWidget_changed()
4409{
4410 if ( mLayer )
4411 {
4412 mLayer->setSizeUnit( mSizeUnitWidget->unit() );
4413 mLayer->setSizeMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
4414 emit changed();
4415 }
4416}
4417
4418void QgsRasterMarkerSymbolLayerWidget::mOffsetUnitWidget_changed()
4419{
4420 if ( mLayer )
4421 {
4422 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
4423 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
4424 emit changed();
4425 }
4426}
4427
4428void QgsRasterMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged( int )
4429{
4430 if ( mLayer )
4431 {
4432 mLayer->setHorizontalAnchorPoint( mHorizontalAnchorComboBox->currentData().value< Qgis::HorizontalAnchorPoint >() );
4433 emit changed();
4434 }
4435}
4436
4437void QgsRasterMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged( int )
4438{
4439 if ( mLayer )
4440 {
4441 mLayer->setVerticalAnchorPoint( mVerticalAnchorComboBox->currentData().value< Qgis::VerticalAnchorPoint >() );
4442 emit changed();
4443 }
4444}
4445
4446
4448
4450 : QgsSymbolLayerWidget( parent, vl )
4451{
4452 mLayer = nullptr;
4453
4454 setupUi( this );
4455
4456 mHorizontalAnchorComboBox->addItem( tr( "Left" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Left ) );
4457 mHorizontalAnchorComboBox->addItem( tr( "Horizontal Center" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Center ) );
4458 mHorizontalAnchorComboBox->addItem( tr( "Right" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Right ) );
4459
4460 mVerticalAnchorComboBox->addItem( tr( "Top" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Top ) );
4461 mVerticalAnchorComboBox->addItem( tr( "Vertical Center" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Center ) );
4462 mVerticalAnchorComboBox->addItem( tr( "Bottom" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Bottom ) );
4463
4464 mImageSourceLineEdit->setLastPathSettingsKey( u"/UI/lastAnimatedMarkerImageDir"_s );
4465
4466 connect( mImageSourceLineEdit, &QgsImageSourceLineEdit::sourceChanged, this, &QgsAnimatedMarkerSymbolLayerWidget::imageSourceChanged );
4467 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsAnimatedMarkerSymbolLayerWidget::mOffsetUnitWidget_changed );
4468 connect( mRotationSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsAnimatedMarkerSymbolLayerWidget::setAngle );
4469 connect( mSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsAnimatedMarkerSymbolLayerWidget::mSizeUnitWidget_changed );
4470 connect( mWidthSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsAnimatedMarkerSymbolLayerWidget::setWidth );
4471 connect( mHeightSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsAnimatedMarkerSymbolLayerWidget::setHeight );
4472 connect( mLockAspectRatio, static_cast<void ( QgsRatioLockButton::* )( bool )>( &QgsRatioLockButton::lockChanged ), this, &QgsAnimatedMarkerSymbolLayerWidget::setLockAspectRatio );
4473
4474 mFrameRateSpin->setClearValue( 10 );
4475 mFrameRateSpin->setShowClearButton( true );
4476 connect( mFrameRateSpin, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double value ) {
4477 mLayer->setFrameRate( value );
4478 emit changed();
4479 } );
4480
4481 mSizeUnitWidget->setUnits(
4490 );
4491 mOffsetUnitWidget->setUnits(
4493 );
4494
4495 mSpinOffsetX->setClearValue( 0.0 );
4496 mSpinOffsetY->setClearValue( 0.0 );
4497 mRotationSpinBox->setClearValue( 0.0 );
4498
4499 connect( mSpinOffsetX, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsAnimatedMarkerSymbolLayerWidget::setOffset );
4500 connect( mSpinOffsetY, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsAnimatedMarkerSymbolLayerWidget::setOffset );
4501 connect( mOpacityWidget, &QgsOpacityWidget::opacityChanged, this, &QgsAnimatedMarkerSymbolLayerWidget::setOpacity );
4502
4503 connect( mHorizontalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsAnimatedMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged );
4504 connect( mVerticalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsAnimatedMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged );
4505}
4506
4508{
4509 if ( !layer )
4510 {
4511 return;
4512 }
4513
4514 if ( layer->layerType() != "AnimatedMarker"_L1 )
4515 return;
4516
4517 // layer type is correct, we can do the cast
4518 mLayer = static_cast<QgsAnimatedMarkerSymbolLayer *>( layer );
4519
4520 // set values
4521 whileBlocking( mImageSourceLineEdit )->setSource( mLayer->path() );
4522
4523 const double firstFrameTime = QgsApplication::imageCache()->nextFrameDelay( mLayer->path() );
4524 if ( firstFrameTime > 0 )
4525 {
4526 mFrameRateSpin->setClearValue( 1000 / firstFrameTime );
4527 }
4528 else
4529 {
4530 mFrameRateSpin->setClearValue( 10 );
4531 }
4532
4533 whileBlocking( mWidthSpinBox )->setValue( mLayer->size() );
4534 const bool preservedAspectRatio = mLayer->preservedAspectRatio();
4535 mHeightSpinBox->blockSignals( true );
4536 if ( preservedAspectRatio )
4537 {
4538 mHeightSpinBox->setValue( mLayer->size() );
4539 }
4540 else
4541 {
4542 mHeightSpinBox->setValue( mLayer->size() * mLayer->fixedAspectRatio() );
4543 }
4544 mHeightSpinBox->setEnabled( mLayer->defaultAspectRatio() > 0.0 );
4545 mHeightSpinBox->blockSignals( false );
4546 whileBlocking( mLockAspectRatio )->setLocked( preservedAspectRatio );
4547
4548 whileBlocking( mRotationSpinBox )->setValue( mLayer->angle() );
4549 whileBlocking( mOpacityWidget )->setOpacity( mLayer->opacity() );
4550
4551 whileBlocking( mSpinOffsetX )->setValue( mLayer->offset().x() );
4552 whileBlocking( mSpinOffsetY )->setValue( mLayer->offset().y() );
4553
4554 whileBlocking( mFrameRateSpin )->setValue( mLayer->frameRate() );
4555
4556 mSizeUnitWidget->blockSignals( true );
4557 mSizeUnitWidget->setUnit( mLayer->sizeUnit() );
4558 mSizeUnitWidget->setMapUnitScale( mLayer->sizeMapUnitScale() );
4559 mSizeUnitWidget->blockSignals( false );
4560 mOffsetUnitWidget->blockSignals( true );
4561 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
4562 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
4563 mOffsetUnitWidget->blockSignals( false );
4564
4565 //anchor points
4566 whileBlocking( mHorizontalAnchorComboBox )->setCurrentIndex( mHorizontalAnchorComboBox->findData( QVariant::fromValue( mLayer->horizontalAnchorPoint() ) ) );
4567 whileBlocking( mVerticalAnchorComboBox )->setCurrentIndex( mVerticalAnchorComboBox->findData( QVariant::fromValue( mLayer->verticalAnchorPoint() ) ) );
4568
4577
4578 updatePreviewImage();
4579}
4580
4585
4587{
4589 mImageSourceLineEdit->setMessageBar( context.messageBar() );
4590}
4591
4592void QgsAnimatedMarkerSymbolLayerWidget::imageSourceChanged( const QString &text )
4593{
4594 mLayer->setPath( text );
4595
4596 const double firstFrameTime = QgsApplication::imageCache()->nextFrameDelay( text );
4597 if ( firstFrameTime > 0 )
4598 {
4599 mFrameRateSpin->setClearValue( 1000 / firstFrameTime );
4600 }
4601 else
4602 {
4603 mFrameRateSpin->setClearValue( 10 );
4604 }
4605 updatePreviewImage();
4606 emit changed();
4607}
4608
4609void QgsAnimatedMarkerSymbolLayerWidget::updatePreviewImage()
4610{
4611 if ( mPreviewMovie )
4612 {
4613 mLabelImagePreview->setMovie( nullptr );
4614 mPreviewMovie->deleteLater();
4615 mPreviewMovie = nullptr;
4616 }
4617
4618 mPreviewMovie = new QMovie( mLayer->path(), QByteArray(), this );
4619 mPreviewMovie->setScaledSize( QSize( 150, 150 ) );
4620 mLabelImagePreview->setMovie( mPreviewMovie );
4621 mPreviewMovie->start();
4622}
4623
4624void QgsAnimatedMarkerSymbolLayerWidget::setWidth()
4625{
4626 const double defaultAspectRatio = mLayer->defaultAspectRatio();
4627 double fixedAspectRatio = 0.0;
4628 mHeightSpinBox->blockSignals( true );
4629 if ( defaultAspectRatio <= 0.0 )
4630 {
4631 mHeightSpinBox->setValue( mWidthSpinBox->value() );
4632 }
4633 else if ( mLockAspectRatio->locked() )
4634 {
4635 mHeightSpinBox->setValue( mWidthSpinBox->value() * defaultAspectRatio );
4636 }
4637 else
4638 {
4639 fixedAspectRatio = mHeightSpinBox->value() / mWidthSpinBox->value();
4640 }
4641 mHeightSpinBox->blockSignals( false );
4642 mLayer->setSize( mWidthSpinBox->value() );
4643 mLayer->setFixedAspectRatio( fixedAspectRatio );
4644 emit changed();
4645}
4646
4647void QgsAnimatedMarkerSymbolLayerWidget::setHeight()
4648{
4649 const double defaultAspectRatio = mLayer->defaultAspectRatio();
4650 double fixedAspectRatio = 0.0;
4651 mWidthSpinBox->blockSignals( true );
4652 if ( defaultAspectRatio <= 0.0 )
4653 {
4654 mWidthSpinBox->setValue( mHeightSpinBox->value() );
4655 }
4656 else if ( mLockAspectRatio->locked() )
4657 {
4658 mWidthSpinBox->setValue( mHeightSpinBox->value() / defaultAspectRatio );
4659 }
4660 else
4661 {
4662 fixedAspectRatio = mHeightSpinBox->value() / mWidthSpinBox->value();
4663 }
4664 mWidthSpinBox->blockSignals( false );
4665 mLayer->setSize( mWidthSpinBox->value() );
4666 mLayer->setFixedAspectRatio( fixedAspectRatio );
4667 emit changed();
4668}
4669
4670void QgsAnimatedMarkerSymbolLayerWidget::setLockAspectRatio( const bool locked )
4671{
4672 const double defaultAspectRatio = mLayer->defaultAspectRatio();
4673 if ( defaultAspectRatio <= 0.0 )
4674 {
4675 whileBlocking( mLockAspectRatio )->setLocked( true );
4676 }
4677 else if ( locked )
4678 {
4679 mLayer->setFixedAspectRatio( 0.0 );
4680 setWidth();
4681 }
4682 else
4683 {
4684 mLayer->setFixedAspectRatio( mHeightSpinBox->value() / mWidthSpinBox->value() );
4685 }
4686}
4687
4688void QgsAnimatedMarkerSymbolLayerWidget::setAngle()
4689{
4690 mLayer->setAngle( mRotationSpinBox->value() );
4691 emit changed();
4692}
4693
4694void QgsAnimatedMarkerSymbolLayerWidget::setOpacity( double value )
4695{
4696 mLayer->setOpacity( value );
4697 emit changed();
4698 updatePreviewImage();
4699}
4700
4701void QgsAnimatedMarkerSymbolLayerWidget::setOffset()
4702{
4703 mLayer->setOffset( QPointF( mSpinOffsetX->value(), mSpinOffsetY->value() ) );
4704 emit changed();
4705}
4706
4707void QgsAnimatedMarkerSymbolLayerWidget::mSizeUnitWidget_changed()
4708{
4709 if ( mLayer )
4710 {
4711 mLayer->setSizeUnit( mSizeUnitWidget->unit() );
4712 mLayer->setSizeMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
4713 emit changed();
4714 }
4715}
4716
4717void QgsAnimatedMarkerSymbolLayerWidget::mOffsetUnitWidget_changed()
4718{
4719 if ( mLayer )
4720 {
4721 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
4722 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
4723 emit changed();
4724 }
4725}
4726
4727void QgsAnimatedMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged( int )
4728{
4729 if ( mLayer )
4730 {
4731 mLayer->setHorizontalAnchorPoint( mHorizontalAnchorComboBox->currentData().value< Qgis::HorizontalAnchorPoint >() );
4732 emit changed();
4733 }
4734}
4735
4736void QgsAnimatedMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged( int )
4737{
4738 if ( mLayer )
4739 {
4740 mLayer->setVerticalAnchorPoint( mVerticalAnchorComboBox->currentData().value< Qgis::VerticalAnchorPoint >() );
4741 emit changed();
4742 }
4743}
4744
4746
4748 : QgsSymbolLayerWidget( parent, vl )
4749{
4750 mLayer = nullptr;
4751 setupUi( this );
4752
4753 mImageSourceLineEdit->setLastPathSettingsKey( u"/UI/lastRasterMarkerImageDir"_s );
4754 connect( mImageSourceLineEdit, &QgsImageSourceLineEdit::sourceChanged, this, &QgsRasterFillSymbolLayerWidget::imageSourceChanged );
4755
4756 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsRasterFillSymbolLayerWidget::mOffsetUnitWidget_changed );
4757 connect( mRotationSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsRasterFillSymbolLayerWidget::mRotationSpinBox_valueChanged );
4758
4759 connect( mSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
4760 if ( !mLayer )
4761 {
4762 return;
4763 }
4764 mLayer->setSizeUnit( mSizeUnitWidget->unit() );
4765 mLayer->setSizeMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
4766 emit changed();
4767 } );
4768 connect( mWidthSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, [this]( double d ) {
4769 if ( !mLayer )
4770 {
4771 return;
4772 }
4773 mLayer->setWidth( d );
4774 emit changed();
4775 } );
4776
4777 connect( mHeightSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, [this]( double d ) {
4778 if ( !mLayer )
4779 {
4780 return;
4781 }
4782 mLayer->setHeight( d );
4783 emit changed();
4784 } );
4785
4786 mSizeUnitWidget->setUnits(
4795 );
4796 mOffsetUnitWidget->setUnits(
4798 );
4799
4800 mSpinOffsetX->setClearValue( 0.0 );
4801 mSpinOffsetY->setClearValue( 0.0 );
4802 mRotationSpinBox->setClearValue( 0.0 );
4803
4804 connect( cboCoordinateMode, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsRasterFillSymbolLayerWidget::setCoordinateMode );
4805 connect( mSpinOffsetX, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsRasterFillSymbolLayerWidget::offsetChanged );
4806 connect( mSpinOffsetY, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsRasterFillSymbolLayerWidget::offsetChanged );
4807 connect( mOpacityWidget, &QgsOpacityWidget::opacityChanged, this, &QgsRasterFillSymbolLayerWidget::opacityChanged );
4808}
4809
4810
4812{
4813 if ( !layer )
4814 {
4815 return;
4816 }
4817
4818 if ( layer->layerType() != "RasterFill"_L1 )
4819 {
4820 return;
4821 }
4822
4823 mLayer = dynamic_cast<QgsRasterFillSymbolLayer *>( layer );
4824 if ( !mLayer )
4825 {
4826 return;
4827 }
4828
4829 whileBlocking( mImageSourceLineEdit )->setSource( mLayer->imageFilePath() );
4830
4831 cboCoordinateMode->blockSignals( true );
4832 switch ( mLayer->coordinateMode() )
4833 {
4835 cboCoordinateMode->setCurrentIndex( 1 );
4836 break;
4838 default:
4839 cboCoordinateMode->setCurrentIndex( 0 );
4840 break;
4841 }
4842 cboCoordinateMode->blockSignals( false );
4843 whileBlocking( mOpacityWidget )->setOpacity( mLayer->opacity() );
4844 whileBlocking( mRotationSpinBox )->setValue( mLayer->angle() );
4845
4846 whileBlocking( mSpinOffsetX )->setValue( mLayer->offset().x() );
4847 whileBlocking( mSpinOffsetY )->setValue( mLayer->offset().y() );
4848 mOffsetUnitWidget->blockSignals( true );
4849 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
4850 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
4851 mOffsetUnitWidget->blockSignals( false );
4852
4853 whileBlocking( mWidthSpinBox )->setValue( mLayer->width() );
4854 mSizeUnitWidget->blockSignals( true );
4855 mSizeUnitWidget->setUnit( mLayer->sizeUnit() );
4856 mSizeUnitWidget->setMapUnitScale( mLayer->sizeMapUnitScale() );
4857 mSizeUnitWidget->blockSignals( false );
4858
4859 whileBlocking( mHeightSpinBox )->setValue( mLayer->height() );
4860
4861 updatePreviewImage();
4862
4869}
4870
4875
4876void QgsRasterFillSymbolLayerWidget::imageSourceChanged( const QString &text )
4877{
4878 mLayer->setImageFilePath( text );
4879 updatePreviewImage();
4880 emit changed();
4881}
4882
4883void QgsRasterFillSymbolLayerWidget::setCoordinateMode( int index )
4884{
4885 switch ( index )
4886 {
4887 case 0:
4888 //feature coordinate mode
4890 break;
4891 case 1:
4892 //viewport coordinate mode
4894 break;
4895 }
4896
4897 emit changed();
4898}
4899
4900void QgsRasterFillSymbolLayerWidget::opacityChanged( double value )
4901{
4902 if ( !mLayer )
4903 {
4904 return;
4905 }
4906
4907 mLayer->setOpacity( value );
4908 emit changed();
4909 updatePreviewImage();
4910}
4911
4912void QgsRasterFillSymbolLayerWidget::offsetChanged()
4913{
4914 mLayer->setOffset( QPointF( mSpinOffsetX->value(), mSpinOffsetY->value() ) );
4915 emit changed();
4916}
4917
4918void QgsRasterFillSymbolLayerWidget::mOffsetUnitWidget_changed()
4919{
4920 if ( !mLayer )
4921 {
4922 return;
4923 }
4924 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
4925 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
4926 emit changed();
4927}
4928
4929void QgsRasterFillSymbolLayerWidget::mRotationSpinBox_valueChanged( double d )
4930{
4931 if ( mLayer )
4932 {
4933 mLayer->setAngle( d );
4934 emit changed();
4935 }
4936}
4937
4938void QgsRasterFillSymbolLayerWidget::updatePreviewImage()
4939{
4940 bool fitsInCache = false;
4941 const QImage image = QgsApplication::imageCache()->pathAsImage( mLayer->imageFilePath(), QSize( 150, 150 ), true, 1.0, fitsInCache );
4942 if ( image.isNull() )
4943 {
4944 mLabelImagePreview->setPixmap( QPixmap() );
4945 return;
4946 }
4947
4948 QImage previewImage( 150, 150, QImage::Format_ARGB32 );
4949 previewImage.fill( Qt::transparent );
4950 const QRect imageRect( ( 150 - image.width() ) / 2.0, ( 150 - image.height() ) / 2.0, image.width(), image.height() );
4951 QPainter p;
4952 p.begin( &previewImage );
4953 //draw a checkerboard background
4954 uchar pixDataRGB[] = { 150, 150, 150, 150, 100, 100, 100, 150, 100, 100, 100, 150, 150, 150, 150, 150 };
4955 const QImage img( pixDataRGB, 2, 2, 8, QImage::Format_ARGB32 );
4956 const QPixmap pix = QPixmap::fromImage( img.scaled( 8, 8 ) );
4957 QBrush checkerBrush;
4958 checkerBrush.setTexture( pix );
4959 p.fillRect( imageRect, checkerBrush );
4960
4961 if ( mLayer->opacity() < 1.0 )
4962 {
4963 p.setOpacity( mLayer->opacity() );
4964 }
4965
4966 p.drawImage( imageRect.left(), imageRect.top(), image );
4967 p.end();
4968 mLabelImagePreview->setPixmap( QPixmap::fromImage( previewImage ) );
4969}
4970
4971//
4972// QgsRasterLineSymbolLayerWidget
4973//
4974
4975
4977 : QgsSymbolLayerWidget( parent, vl )
4978{
4979 mLayer = nullptr;
4980 setupUi( this );
4981
4982 mImageSourceLineEdit->setLastPathSettingsKey( u"/UI/lastRasterMarkerImageDir"_s );
4983
4984 mPenWidthUnitWidget->setUnits(
4986 );
4987 mOffsetUnitWidget->setUnits(
4989 );
4990
4991 connect( mPenWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
4992 if ( mLayer )
4993 {
4994 mLayer->setWidthUnit( mPenWidthUnitWidget->unit() );
4995 mLayer->setWidthMapUnitScale( mPenWidthUnitWidget->getMapUnitScale() );
4996 emit changed();
4997 }
4998 } );
4999
5000 connect( spinWidth, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this] {
5001 if ( mLayer )
5002 {
5003 mLayer->setWidth( spinWidth->value() );
5004 emit changed();
5005 }
5006 } );
5007
5008 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
5009 if ( mLayer )
5010 {
5011 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
5012 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
5013 emit changed();
5014 }
5015 } );
5016
5017
5018 spinOffset->setClearValue( 0.0 );
5019 connect( spinOffset, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double val ) {
5020 if ( mLayer )
5021 {
5022 mLayer->setOffset( val );
5023 emit changed();
5024 }
5025 } );
5026
5027 connect( cboCapStyle, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this] {
5028 if ( mLayer )
5029 {
5030 mLayer->setPenCapStyle( cboCapStyle->penCapStyle() );
5031 emit changed();
5032 }
5033 } );
5034 connect( cboJoinStyle, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this] {
5035 if ( mLayer )
5036 {
5037 mLayer->setPenJoinStyle( cboJoinStyle->penJoinStyle() );
5038 emit changed();
5039 }
5040 } );
5041
5042 connect( mImageSourceLineEdit, &QgsImageSourceLineEdit::sourceChanged, this, &QgsRasterLineSymbolLayerWidget::imageSourceChanged );
5043 connect( mOpacityWidget, &QgsOpacityWidget::opacityChanged, this, [this]( double opacity ) {
5044 if ( mLayer )
5045 {
5046 mLayer->setOpacity( opacity );
5047 updatePreviewImage();
5048 emit changed();
5049 }
5050 } );
5051}
5052
5054{
5055 if ( !layer )
5056 {
5057 return;
5058 }
5059
5060 if ( layer->layerType() != "RasterLine"_L1 )
5061 {
5062 return;
5063 }
5064
5065 mLayer = dynamic_cast<QgsRasterLineSymbolLayer *>( layer );
5066 if ( !mLayer )
5067 {
5068 return;
5069 }
5070
5071 whileBlocking( mImageSourceLineEdit )->setSource( mLayer->path() );
5072 whileBlocking( mOpacityWidget )->setOpacity( mLayer->opacity() );
5073
5074 whileBlocking( spinWidth )->setValue( mLayer->width() );
5075 whileBlocking( mPenWidthUnitWidget )->setUnit( mLayer->widthUnit() );
5076 whileBlocking( mPenWidthUnitWidget )->setMapUnitScale( mLayer->widthMapUnitScale() );
5077 whileBlocking( cboJoinStyle )->setPenJoinStyle( mLayer->penJoinStyle() );
5078 whileBlocking( cboCapStyle )->setPenCapStyle( mLayer->penCapStyle() );
5079
5080 whileBlocking( mOffsetUnitWidget )->setUnit( mLayer->offsetUnit() );
5081 whileBlocking( mOffsetUnitWidget )->setMapUnitScale( mLayer->offsetMapUnitScale() );
5082 whileBlocking( spinOffset )->setValue( mLayer->offset() );
5083
5084 updatePreviewImage();
5085
5092}
5093
5098
5099void QgsRasterLineSymbolLayerWidget::imageSourceChanged( const QString &text )
5100{
5101 mLayer->setPath( text );
5102 updatePreviewImage();
5103 emit changed();
5104}
5105
5106void QgsRasterLineSymbolLayerWidget::updatePreviewImage()
5107{
5108 bool fitsInCache = false;
5109 const QImage image = QgsApplication::imageCache()->pathAsImage( mLayer->path(), QSize( 150, 150 ), true, 1.0, fitsInCache );
5110 if ( image.isNull() )
5111 {
5112 mLabelImagePreview->setPixmap( QPixmap() );
5113 return;
5114 }
5115
5116 QImage previewImage( 150, 150, QImage::Format_ARGB32 );
5117 previewImage.fill( Qt::transparent );
5118 const QRect imageRect( ( 150 - image.width() ) / 2.0, ( 150 - image.height() ) / 2.0, image.width(), image.height() );
5119 QPainter p;
5120 p.begin( &previewImage );
5121 //draw a checkerboard background
5122 uchar pixDataRGB[] = { 150, 150, 150, 150, 100, 100, 100, 150, 100, 100, 100, 150, 150, 150, 150, 150 };
5123 const QImage img( pixDataRGB, 2, 2, 8, QImage::Format_ARGB32 );
5124 const QPixmap pix = QPixmap::fromImage( img.scaled( 8, 8 ) );
5125 QBrush checkerBrush;
5126 checkerBrush.setTexture( pix );
5127 p.fillRect( imageRect, checkerBrush );
5128
5129 if ( mLayer->opacity() < 1.0 )
5130 {
5131 p.setOpacity( mLayer->opacity() );
5132 }
5133
5134 p.drawImage( imageRect.left(), imageRect.top(), image );
5135 p.end();
5136 mLabelImagePreview->setPixmap( QPixmap::fromImage( previewImage ) );
5137}
5138
5139
5140//
5141// QgsGeometryGeneratorSymbolLayerWidget
5142//
5143
5145 : QgsSymbolLayerWidget( parent, vl )
5146
5147{
5148 setupUi( this );
5149 modificationExpressionSelector->setMultiLine( true );
5150 modificationExpressionSelector->setLayer( const_cast<QgsVectorLayer *>( vl ) );
5151 modificationExpressionSelector->registerExpressionContextGenerator( this );
5152 cbxGeometryType->addItem( QgsIconUtils::iconPolygon(), tr( "Polygon / MultiPolygon" ), static_cast<int>( Qgis::SymbolType::Fill ) );
5153 cbxGeometryType->addItem( QgsIconUtils::iconLine(), tr( "LineString / MultiLineString" ), static_cast<int>( Qgis::SymbolType::Line ) );
5154 cbxGeometryType->addItem( QgsIconUtils::iconPoint(), tr( "Point / MultiPoint" ), static_cast<int>( Qgis::SymbolType::Marker ) );
5155
5157 mUnitWidget->setShowMapScaleButton( false );
5158
5159 connect( modificationExpressionSelector, &QgsExpressionLineEdit::expressionChanged, this, &QgsGeometryGeneratorSymbolLayerWidget::updateExpression );
5160 connect( cbxGeometryType, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsGeometryGeneratorSymbolLayerWidget::updateSymbolType );
5161 connect( mUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
5162 if ( !mBlockSignals )
5163 {
5164 mLayer->setUnits( mUnitWidget->unit() );
5165 emit symbolChanged();
5166 }
5167 } );
5168}
5169
5171{
5172 mBlockSignals++;
5173 mLayer = static_cast<QgsGeometryGeneratorSymbolLayer *>( l );
5174 modificationExpressionSelector->setExpression( mLayer->geometryExpression() );
5175 cbxGeometryType->setCurrentIndex( cbxGeometryType->findData( static_cast<int>( mLayer->symbolType() ) ) );
5176 mUnitWidget->setUnit( mLayer->units() );
5177 mBlockSignals--;
5178}
5179
5184
5185void QgsGeometryGeneratorSymbolLayerWidget::updateExpression( const QString &string )
5186{
5187 mLayer->setGeometryExpression( string );
5188
5189 emit changed();
5190}
5191
5192void QgsGeometryGeneratorSymbolLayerWidget::updateSymbolType()
5193{
5194 // we try to keep the subsymbol, if we can!
5195 std::unique_ptr<QgsSymbol> subSymbol( mLayer->subSymbol()->clone() );
5196
5197 mLayer->setSymbolType( static_cast<Qgis::SymbolType>( cbxGeometryType->currentData().toInt() ) );
5198
5199 switch ( mLayer->symbolType() )
5200 {
5203 break;
5205 {
5206 if ( subSymbol->type() == Qgis::SymbolType::Fill )
5207 {
5208 // going from fill -> line type, so we can copy any LINE symbol layers across
5209 QgsSymbolLayerList layers;
5210 for ( int i = 0; i < subSymbol->symbolLayerCount(); ++i )
5211 {
5212 if ( dynamic_cast<const QgsLineSymbolLayer *>( subSymbol->symbolLayer( i ) ) )
5213 layers << subSymbol->symbolLayer( i )->clone();
5214 }
5215
5216 if ( !layers.empty() )
5217 mLayer->setSubSymbol( new QgsLineSymbol( layers ) );
5218 }
5219 break;
5220 }
5222 if ( subSymbol->type() == Qgis::SymbolType::Line )
5223 {
5224 // going from line -> fill type, so copy ALL line symbol layers across
5225 QgsSymbolLayerList layers;
5226 for ( int i = 0; i < subSymbol->symbolLayerCount(); ++i )
5227 layers << subSymbol->symbolLayer( i )->clone();
5228 mLayer->setSubSymbol( new QgsFillSymbol( layers ) );
5229 }
5230 break;
5231 }
5232
5233 emit symbolChanged();
5234}
5235
5236//
5237// QgsRandomMarkerFillSymbolLayerWidget
5238//
5239
5240
5242 : QgsSymbolLayerWidget( parent, vl )
5243{
5244 setupUi( this );
5245
5246 mCountMethodComboBox->addItem( tr( "Absolute Count" ), static_cast<int>( Qgis::PointCountMethod::Absolute ) );
5247 mCountMethodComboBox->addItem( tr( "Density-based Count" ), static_cast<int>( Qgis::PointCountMethod::DensityBased ) );
5248
5249 mPointCountSpinBox->setShowClearButton( true );
5250 mPointCountSpinBox->setClearValue( 100 );
5251 mSeedSpinBox->setShowClearButton( true );
5252 mSeedSpinBox->setClearValue( 0 );
5253
5254 connect( mCountMethodComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsRandomMarkerFillSymbolLayerWidget::countMethodChanged );
5255 connect( mPointCountSpinBox, static_cast<void ( QSpinBox::* )( int )>( &QSpinBox::valueChanged ), this, &QgsRandomMarkerFillSymbolLayerWidget::countChanged );
5256 connect( mDensityAreaSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsRandomMarkerFillSymbolLayerWidget::densityAreaChanged );
5257 connect( mSeedSpinBox, static_cast<void ( QSpinBox::* )( int )>( &QSpinBox::valueChanged ), this, &QgsRandomMarkerFillSymbolLayerWidget::seedChanged );
5258 connect( mClipPointsCheckBox, &QCheckBox::toggled, this, [this]( bool checked ) {
5259 if ( mLayer )
5260 {
5261 mLayer->setClipPoints( checked );
5262 emit changed();
5263 }
5264 } );
5265
5266 mDensityAreaUnitWidget->setUnits(
5268 );
5269
5270 connect( mDensityAreaUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsRandomMarkerFillSymbolLayerWidget::densityAreaUnitChanged );
5271}
5272
5274{
5275 if ( !layer || layer->layerType() != "RandomMarkerFill"_L1 )
5276 {
5277 return;
5278 }
5279
5280 mLayer = static_cast<QgsRandomMarkerFillSymbolLayer *>( layer );
5281 whileBlocking( mPointCountSpinBox )->setValue( mLayer->pointCount() );
5282 whileBlocking( mSeedSpinBox )->setValue( mLayer->seed() );
5283 whileBlocking( mClipPointsCheckBox )->setChecked( mLayer->clipPoints() );
5284
5285 bool showDensityBasedCountWidgets = false;
5286 switch ( mLayer->countMethod() )
5287 {
5289 showDensityBasedCountWidgets = true;
5290 break;
5292 break;
5293 }
5294 mDensityAreaLabel->setVisible( showDensityBasedCountWidgets );
5295 mDensityAreaSpinBox->setVisible( showDensityBasedCountWidgets );
5296 mDensityAreaUnitWidget->setVisible( showDensityBasedCountWidgets );
5297 mDensityAreaDdbtn->setVisible( showDensityBasedCountWidgets );
5298
5299 whileBlocking( mCountMethodComboBox )->setCurrentIndex( mCountMethodComboBox->findData( static_cast<int>( mLayer->countMethod() ) ) );
5300 whileBlocking( mDensityAreaSpinBox )->setValue( mLayer->densityArea() );
5301 mDensityAreaUnitWidget->blockSignals( true );
5302 mDensityAreaUnitWidget->setUnit( mLayer->densityAreaUnit() );
5303 mDensityAreaUnitWidget->setMapUnitScale( mLayer->densityAreaUnitScale() );
5304 mDensityAreaUnitWidget->blockSignals( false );
5305
5310}
5311
5316
5317void QgsRandomMarkerFillSymbolLayerWidget::countMethodChanged( int )
5318{
5319 bool showDensityBasedCountWidgets = false;
5320 switch ( static_cast<Qgis::PointCountMethod>( mCountMethodComboBox->currentData().toInt() ) )
5321 {
5323 showDensityBasedCountWidgets = true;
5324 break;
5326 break;
5327 }
5328 mDensityAreaLabel->setVisible( showDensityBasedCountWidgets );
5329 mDensityAreaSpinBox->setVisible( showDensityBasedCountWidgets );
5330 mDensityAreaUnitWidget->setVisible( showDensityBasedCountWidgets );
5331 mDensityAreaDdbtn->setVisible( showDensityBasedCountWidgets );
5332
5333 if ( mLayer )
5334 {
5335 mLayer->setCountMethod( static_cast<Qgis::PointCountMethod>( mCountMethodComboBox->currentData().toInt() ) );
5336 emit changed();
5337 }
5338}
5339
5340void QgsRandomMarkerFillSymbolLayerWidget::countChanged( int d )
5341{
5342 if ( mLayer )
5343 {
5344 mLayer->setPointCount( d );
5345 emit changed();
5346 }
5347}
5348
5349void QgsRandomMarkerFillSymbolLayerWidget::densityAreaChanged( double d )
5350{
5351 if ( mLayer )
5352 {
5353 mLayer->setDensityArea( d );
5354 emit changed();
5355 }
5356}
5357
5358void QgsRandomMarkerFillSymbolLayerWidget::densityAreaUnitChanged()
5359{
5360 if ( mLayer )
5361 {
5362 mLayer->setDensityAreaUnit( mDensityAreaUnitWidget->unit() );
5363 mLayer->setDensityAreaUnitScale( mDensityAreaUnitWidget->getMapUnitScale() );
5364 emit changed();
5365 }
5366}
5367
5368void QgsRandomMarkerFillSymbolLayerWidget::seedChanged( int d )
5369{
5370 if ( mLayer )
5371 {
5372 mLayer->setSeed( d );
5373 emit changed();
5374 }
5375}
5376
5377//
5378// QgsGradientLineSymbolLayerWidget
5379//
5380
5382 : QgsSymbolLayerWidget( parent, vl )
5383{
5384 mLayer = nullptr;
5385 setupUi( this );
5386
5387 btnColorRamp->setShowGradientOnly( true );
5388
5389 btnChangeColor->setAllowOpacity( true );
5390 btnChangeColor->setColorDialogTitle( tr( "Select Gradient Color" ) );
5391 btnChangeColor->setContext( u"symbology"_s );
5392 btnChangeColor->setShowNoColor( true );
5393 btnChangeColor->setNoColorString( tr( "Transparent" ) );
5394 btnChangeColor->setOpaqueColorString( tr( "Opaque" ) );
5395 btnChangeColor2->setAllowOpacity( true );
5396 btnChangeColor2->setColorDialogTitle( tr( "Select Gradient Color" ) );
5397 btnChangeColor2->setContext( u"symbology"_s );
5398 btnChangeColor2->setShowNoColor( true );
5399 btnChangeColor2->setNoColorString( tr( "Transparent" ) );
5400 btnChangeColor2->setOpaqueColorString( tr( "Opaque" ) );
5401
5402 mStartColorDDBtn->registerLinkedWidget( btnChangeColor );
5403 mEndColorDDBtn->registerLinkedWidget( btnChangeColor2 );
5404
5405 connect( btnChangeColor, &QgsColorButton::colorChanged, this, [this]( const QColor &color ) {
5406 if ( mLayer )
5407 {
5408 mLayer->setColor( color );
5409 emit changed();
5410 }
5411 } );
5412 connect( btnChangeColor2, &QgsColorButton::colorChanged, this, [this]( const QColor &color ) {
5413 if ( mLayer )
5414 {
5415 mLayer->setColor2( color );
5416 emit changed();
5417 }
5418 } );
5419 connect( btnColorRamp, &QgsColorRampButton::colorRampChanged, this, [this] {
5420 if ( btnColorRamp->isNull() )
5421 return;
5422
5423 if ( mLayer )
5424 {
5425 mLayer->setColorRamp( btnColorRamp->colorRamp()->clone() );
5426 emit changed();
5427 }
5428 } );
5429
5430 connect( radioTwoColor, &QAbstractButton::toggled, this, [this] {
5431 if ( mLayer )
5432 {
5433 if ( radioTwoColor->isChecked() )
5434 {
5435 mLayer->setGradientColorType( Qgis::GradientColorSource::SimpleTwoColor );
5436 btnChangeColor->setEnabled( true );
5437 btnChangeColor2->setEnabled( true );
5438 btnColorRamp->setEnabled( false );
5439 }
5440 else
5441 {
5442 mLayer->setGradientColorType( Qgis::GradientColorSource::ColorRamp );
5443 btnColorRamp->setEnabled( true );
5444 btnChangeColor->setEnabled( false );
5445 btnChangeColor2->setEnabled( false );
5446 }
5447 emit changed();
5448 }
5449 } );
5450
5451 mPenWidthUnitWidget->setUnits(
5453 );
5454 mOffsetUnitWidget->setUnits(
5456 );
5457
5458 connect( mPenWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
5459 if ( mLayer )
5460 {
5461 mLayer->setWidthUnit( mPenWidthUnitWidget->unit() );
5462 mLayer->setWidthMapUnitScale( mPenWidthUnitWidget->getMapUnitScale() );
5463 emit changed();
5464 }
5465 } );
5466
5467 connect( spinWidth, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, [this] {
5468 if ( mLayer )
5469 {
5470 mLayer->setWidth( spinWidth->value() );
5471 emit changed();
5472 }
5473 } );
5474
5475 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
5476 if ( mLayer )
5477 {
5478 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
5479 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
5480 emit changed();
5481 }
5482 } );
5483
5484 spinOffset->setClearValue( 0.0 );
5485 connect( spinOffset, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double val ) {
5486 if ( mLayer )
5487 {
5488 mLayer->setOffset( val );
5489 emit changed();
5490 }
5491 } );
5492
5493 connect( cboCapStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, [this] {
5494 if ( mLayer )
5495 {
5496 mLayer->setPenCapStyle( cboCapStyle->penCapStyle() );
5497 emit changed();
5498 }
5499 } );
5500 connect( cboJoinStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, [this] {
5501 if ( mLayer )
5502 {
5503 mLayer->setPenJoinStyle( cboJoinStyle->penJoinStyle() );
5504 emit changed();
5505 }
5506 } );
5507}
5508
5510{
5511 if ( !layer )
5512 {
5513 return;
5514 }
5515
5516 if ( layer->layerType() != "Lineburst"_L1 )
5517 {
5518 return;
5519 }
5520
5521 mLayer = dynamic_cast<QgsLineburstSymbolLayer *>( layer );
5522 if ( !mLayer )
5523 {
5524 return;
5525 }
5526
5527 btnChangeColor->blockSignals( true );
5528 btnChangeColor->setColor( mLayer->color() );
5529 btnChangeColor->blockSignals( false );
5530 btnChangeColor2->blockSignals( true );
5531 btnChangeColor2->setColor( mLayer->color2() );
5532 btnChangeColor2->blockSignals( false );
5533
5534 if ( mLayer->gradientColorType() == Qgis::GradientColorSource::SimpleTwoColor )
5535 {
5536 radioTwoColor->setChecked( true );
5537 btnColorRamp->setEnabled( false );
5538 }
5539 else
5540 {
5541 radioColorRamp->setChecked( true );
5542 btnChangeColor->setEnabled( false );
5543 btnChangeColor2->setEnabled( false );
5544 }
5545
5546 // set source color ramp
5547 if ( mLayer->colorRamp() )
5548 {
5549 btnColorRamp->blockSignals( true );
5550 btnColorRamp->setColorRamp( mLayer->colorRamp() );
5551 btnColorRamp->blockSignals( false );
5552 }
5553
5554 whileBlocking( spinWidth )->setValue( mLayer->width() );
5555 whileBlocking( mPenWidthUnitWidget )->setUnit( mLayer->widthUnit() );
5556 whileBlocking( mPenWidthUnitWidget )->setMapUnitScale( mLayer->widthMapUnitScale() );
5557
5558 whileBlocking( mOffsetUnitWidget )->setUnit( mLayer->offsetUnit() );
5559 whileBlocking( mOffsetUnitWidget )->setMapUnitScale( mLayer->offsetMapUnitScale() );
5560 whileBlocking( spinOffset )->setValue( mLayer->offset() );
5561
5562 whileBlocking( cboJoinStyle )->setPenJoinStyle( mLayer->penJoinStyle() );
5563 whileBlocking( cboCapStyle )->setPenCapStyle( mLayer->penCapStyle() );
5564
5571}
5572
5577
5578//
5579// QgsFilledLineSymbolLayerWidget
5580//
5581
5583 : QgsSymbolLayerWidget( parent, vl )
5584{
5585 mLayer = nullptr;
5586 setupUi( this );
5587
5588 mPenWidthUnitWidget->setUnits(
5590 );
5591 mOffsetUnitWidget->setUnits(
5593 );
5594
5595 connect( mPenWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
5596 if ( mLayer )
5597 {
5598 mLayer->setWidthUnit( mPenWidthUnitWidget->unit() );
5599 mLayer->setWidthMapUnitScale( mPenWidthUnitWidget->getMapUnitScale() );
5600 emit changed();
5601 }
5602 } );
5603
5604 connect( spinWidth, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, [this] {
5605 if ( mLayer )
5606 {
5607 mLayer->setWidth( spinWidth->value() );
5608 emit changed();
5609 }
5610 } );
5611
5612 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
5613 if ( mLayer )
5614 {
5615 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
5616 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
5617 emit changed();
5618 }
5619 } );
5620
5621 spinOffset->setClearValue( 0.0 );
5622 connect( spinOffset, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double val ) {
5623 if ( mLayer )
5624 {
5625 mLayer->setOffset( val );
5626 emit changed();
5627 }
5628 } );
5629
5630 connect( cboCapStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, [this] {
5631 if ( mLayer )
5632 {
5633 mLayer->setPenCapStyle( cboCapStyle->penCapStyle() );
5634 emit changed();
5635 }
5636 } );
5637 connect( cboJoinStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, [this] {
5638 if ( mLayer )
5639 {
5640 mLayer->setPenJoinStyle( cboJoinStyle->penJoinStyle() );
5641 emit changed();
5642 }
5643 } );
5644}
5645
5647
5649{
5650 if ( !layer )
5651 {
5652 return;
5653 }
5654
5655 if ( layer->layerType() != "FilledLine"_L1 )
5656 {
5657 return;
5658 }
5659
5660 mLayer = dynamic_cast<QgsFilledLineSymbolLayer *>( layer );
5661 if ( !mLayer )
5662 {
5663 return;
5664 }
5665
5666 whileBlocking( spinWidth )->setValue( mLayer->width() );
5667 whileBlocking( mPenWidthUnitWidget )->setUnit( mLayer->widthUnit() );
5668 whileBlocking( mPenWidthUnitWidget )->setMapUnitScale( mLayer->widthMapUnitScale() );
5669
5670 whileBlocking( mOffsetUnitWidget )->setUnit( mLayer->offsetUnit() );
5671 whileBlocking( mOffsetUnitWidget )->setMapUnitScale( mLayer->offsetMapUnitScale() );
5672 whileBlocking( spinOffset )->setValue( mLayer->offset() );
5673
5674 whileBlocking( cboJoinStyle )->setPenJoinStyle( mLayer->penJoinStyle() );
5675 whileBlocking( cboCapStyle )->setPenCapStyle( mLayer->penCapStyle() );
5676
5681}
5682
5687
5688//
5689// QgsLinearReferencingSymbolLayerWidget
5690//
5691
5693 : QgsSymbolLayerWidget( parent, vl )
5694{
5695 mLayer = nullptr;
5696
5697 setupUi( this );
5698
5699 mComboPlacement->addItem( tr( "Interval (Cartesian 2D Distances)" ), QVariant::fromValue( Qgis::LinearReferencingPlacement::IntervalCartesian2D ) );
5700 mComboPlacement->addItem( tr( "Interval (Z Values)" ), QVariant::fromValue( Qgis::LinearReferencingPlacement::IntervalZ ) );
5701 mComboPlacement->addItem( tr( "Interval (M Values)" ), QVariant::fromValue( Qgis::LinearReferencingPlacement::IntervalM ) );
5702 mComboPlacement->addItem( tr( "On Every Vertex" ), QVariant::fromValue( Qgis::LinearReferencingPlacement::Vertex ) );
5703
5704 mComboQuantity->addItem( tr( "Cartesian 2D Distance" ), QVariant::fromValue( Qgis::LinearReferencingLabelSource::CartesianDistance2D ) );
5705 mComboQuantity->addItem( tr( "Z Values" ), QVariant::fromValue( Qgis::LinearReferencingLabelSource::Z ) );
5706 mComboQuantity->addItem( tr( "M Values" ), QVariant::fromValue( Qgis::LinearReferencingLabelSource::M ) );
5707
5708 mSpinSkipMultiples->setClearValue( 0, tr( "Not set" ) );
5709 mSpinLabelOffsetX->setClearValue( 0 );
5710 mSpinLabelOffsetY->setClearValue( 0 );
5711 mSpinAverageAngleLength->setClearValue( 4.0 );
5712 mLabelOffsetUnitWidget->setUnits(
5714 );
5715 mAverageAngleUnit->setUnits(
5717 );
5718
5719 connect( mComboQuantity, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this] {
5720 if ( mLayer && !mBlockChangesSignal )
5721 {
5722 mLayer->setLabelSource( mComboQuantity->currentData().value<Qgis::LinearReferencingLabelSource>() );
5723 emit changed();
5724 }
5725 } );
5726 connect( mTextFormatButton, &QgsFontButton::changed, this, [this] {
5727 if ( mLayer && !mBlockChangesSignal )
5728 {
5729 mLayer->setTextFormat( mTextFormatButton->textFormat() );
5730 emit changed();
5731 }
5732 } );
5733 connect( spinInterval, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, [this] {
5734 if ( mLayer && !mBlockChangesSignal )
5735 {
5736 mLayer->setInterval( spinInterval->value() );
5737 emit changed();
5738 }
5739 } );
5740 connect( mSpinSkipMultiples, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, [this] {
5741 if ( mLayer && !mBlockChangesSignal )
5742 {
5743 mLayer->setSkipMultiplesOf( mSpinSkipMultiples->value() );
5744 emit changed();
5745 }
5746 } );
5747 connect( mCheckRotate, &QCheckBox::toggled, this, [this]( bool checked ) {
5748 if ( mLayer && !mBlockChangesSignal )
5749 {
5750 mLayer->setRotateLabels( checked );
5751 emit changed();
5752 }
5753 mSpinAverageAngleLength->setEnabled( checked );
5754 mAverageAngleUnit->setEnabled( mSpinAverageAngleLength->isEnabled() );
5755 } );
5756 connect( mCheckShowMarker, &QCheckBox::toggled, this, [this]( bool checked ) {
5757 if ( mLayer && !mBlockChangesSignal )
5758 {
5759 mLayer->setShowMarker( checked );
5760 emit symbolChanged();
5761 }
5762 } );
5763
5764 connect( mSpinLabelOffsetX, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, [this] {
5765 if ( mLayer && !mBlockChangesSignal )
5766 {
5767 mLayer->setLabelOffset( QPointF( mSpinLabelOffsetX->value(), mSpinLabelOffsetY->value() ) );
5768 emit changed();
5769 }
5770 } );
5771 connect( mSpinLabelOffsetY, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, [this] {
5772 if ( mLayer && !mBlockChangesSignal )
5773 {
5774 mLayer->setLabelOffset( QPointF( mSpinLabelOffsetX->value(), mSpinLabelOffsetY->value() ) );
5775 emit changed();
5776 }
5777 } );
5778 connect( mLabelOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
5779 if ( mLayer && !mBlockChangesSignal )
5780 {
5781 mLayer->setLabelOffsetUnit( mLabelOffsetUnitWidget->unit() );
5782 mLayer->setLabelOffsetMapUnitScale( mLabelOffsetUnitWidget->getMapUnitScale() );
5783 emit changed();
5784 }
5785 } );
5786
5787 connect( mComboPlacement, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this] {
5788 if ( mLayer && !mBlockChangesSignal )
5789 {
5790 const Qgis::LinearReferencingPlacement placement = mComboPlacement->currentData().value<Qgis::LinearReferencingPlacement>();
5791 mLayer->setPlacement( placement );
5792 switch ( placement )
5793 {
5797 mIntervalWidget->show();
5798 break;
5800 mIntervalWidget->hide();
5801 break;
5802 }
5803 emit changed();
5804 }
5805 } );
5806
5807 connect( mSpinAverageAngleLength, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, [this] {
5808 if ( mLayer && !mBlockChangesSignal )
5809 {
5810 mLayer->setAverageAngleLength( mSpinAverageAngleLength->value() );
5811 emit changed();
5812 }
5813 } );
5814 connect( mAverageAngleUnit, &QgsUnitSelectionWidget::changed, this, [this] {
5815 if ( mLayer && !mBlockChangesSignal )
5816 {
5817 mLayer->setAverageAngleUnit( mAverageAngleUnit->unit() );
5818 mLayer->setAverageAngleMapUnitScale( mAverageAngleUnit->getMapUnitScale() );
5819 emit changed();
5820 }
5821 } );
5822
5823 connect( mNumberFormatPushButton, &QPushButton::clicked, this, &QgsLinearReferencingSymbolLayerWidget::changeNumberFormat );
5824
5825 mTextFormatButton->registerExpressionContextGenerator( this );
5826}
5827
5829
5830
5832{
5833 if ( !layer || layer->layerType() != "LinearReferencing"_L1 )
5834 return;
5835
5836 // layer type is correct, we can do the cast
5837 mLayer = qgis::down_cast<QgsLinearReferencingSymbolLayer *>( layer );
5838
5839 mBlockChangesSignal = true;
5840
5841 mComboPlacement->setCurrentIndex( mComboPlacement->findData( QVariant::fromValue( mLayer->placement() ) ) );
5842 switch ( mLayer->placement() )
5843 {
5847 mIntervalWidget->show();
5848 break;
5850 mIntervalWidget->hide();
5851 break;
5852 }
5853
5854 mComboQuantity->setCurrentIndex( mComboQuantity->findData( QVariant::fromValue( mLayer->labelSource() ) ) );
5855
5856 mTextFormatButton->setTextFormat( mLayer->textFormat() );
5857 spinInterval->setValue( mLayer->interval() );
5858 mSpinSkipMultiples->setValue( mLayer->skipMultiplesOf() );
5859 mCheckRotate->setChecked( mLayer->rotateLabels() );
5860 mCheckShowMarker->setChecked( mLayer->showMarker() );
5861 mSpinLabelOffsetX->setValue( mLayer->labelOffset().x() );
5862 mSpinLabelOffsetY->setValue( mLayer->labelOffset().y() );
5863 mLabelOffsetUnitWidget->setUnit( mLayer->labelOffsetUnit() );
5864 mLabelOffsetUnitWidget->setMapUnitScale( mLayer->labelOffsetMapUnitScale() );
5865
5866 mAverageAngleUnit->setUnit( mLayer->averageAngleUnit() );
5867 mAverageAngleUnit->setMapUnitScale( mLayer->averageAngleMapUnitScale() );
5868 mSpinAverageAngleLength->setValue( mLayer->averageAngleLength() );
5869
5870 mSpinAverageAngleLength->setEnabled( mCheckRotate->isChecked() );
5871 mAverageAngleUnit->setEnabled( mSpinAverageAngleLength->isEnabled() );
5872
5877
5878 mBlockChangesSignal = false;
5879}
5880
5885
5887{
5889 mTextFormatButton->setMapCanvas( context.mapCanvas() );
5890 mTextFormatButton->setMessageBar( context.messageBar() );
5891}
5892
5893void QgsLinearReferencingSymbolLayerWidget::changeNumberFormat()
5894{
5896 if ( panel && panel->dockMode() )
5897 {
5899 widget->setPanelTitle( tr( "Number Format" ) );
5900 widget->setFormat( mLayer->numericFormat() );
5901 widget->registerExpressionContextGenerator( this );
5902 connect( widget, &QgsNumericFormatSelectorWidget::changed, this, [this, widget] {
5903 if ( !mBlockChangesSignal )
5904 {
5905 mLayer->setNumericFormat( widget->format() );
5906 emit changed();
5907 }
5908 } );
5909 panel->openPanel( widget );
5910 }
5911 else
5912 {
5913 QgsNumericFormatSelectorDialog dialog( this );
5914 dialog.setFormat( mLayer->numericFormat() );
5915 dialog.registerExpressionContextGenerator( this );
5916 if ( dialog.exec() )
5917 {
5918 mLayer->setNumericFormat( dialog.format() );
5919 emit changed();
5920 }
5921 }
5922}
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 setFont(const QFont &font)
Sets the font to show in the widget.
@ CurvePoint
Place symbols at every virtual curve point in the line (used when rendering curved geometry types onl...
Definition qgis.h:3373
@ InnerVertices
Inner vertices (i.e. all vertices except the first and last vertex).
Definition qgis.h:3375
@ LastVertex
Place symbols on the last vertex in the line.
Definition qgis.h:3370
@ CentralPoint
Place symbols at the mid point of the line.
Definition qgis.h:3372
@ SegmentCenter
Place symbols at the center of every line segment.
Definition qgis.h:3374
@ Vertex
Place symbols on every vertex in the line.
Definition qgis.h:3369
@ Interval
Place symbols at regular intervals.
Definition qgis.h:3368
@ FirstVertex
Place symbols on the first vertex in the line.
Definition qgis.h:3371
MarkerClipMode
Marker clipping modes.
Definition qgis.h:3487
@ CompletelyWithin
Render complete markers wherever the completely fall within the polygon shape.
Definition qgis.h:3491
@ NoClipping
No clipping, render complete markers.
Definition qgis.h:3488
@ Shape
Clip to polygon shape.
Definition qgis.h:3489
@ CentroidWithin
Render complete markers wherever their centroid falls within the polygon shape.
Definition qgis.h:3490
LineClipMode
Line clipping modes.
Definition qgis.h:3501
@ NoClipping
Lines are not clipped, will extend to shape's bounding box.
Definition qgis.h:3504
@ ClipPainterOnly
Applying clipping on the painter only (i.e. line endpoints will coincide with polygon bounding box,...
Definition qgis.h:3502
@ ClipToIntersection
Clip lines to intersection with polygon shape (slower) (i.e. line endpoints will coincide with polygo...
Definition qgis.h:3503
@ ColorRamp
Gradient color ramp.
Definition qgis.h:3418
@ SimpleTwoColor
Simple two color gradient.
Definition qgis.h:3417
@ Repeat
Repeat gradient.
Definition qgis.h:3463
@ Reflect
Reflect gradient.
Definition qgis.h:3462
@ Pad
Pad out gradient using colors at endpoint of gradient.
Definition qgis.h:3461
PointCountMethod
Methods which define the number of points randomly filling a polygon.
Definition qgis.h:3475
@ Absolute
The point count is used as an absolute count of markers.
Definition qgis.h:3476
@ DensityBased
The point count is part of a marker density count.
Definition qgis.h:3477
MarkerShape
Marker shapes.
Definition qgis.h:3318
VerticalAnchorPoint
Marker symbol vertical anchor points.
Definition qgis.h:896
@ Bottom
Align to bottom of symbol.
Definition qgis.h:899
@ Center
Align to vertical center of symbol.
Definition qgis.h:898
@ Baseline
Align to baseline of symbol, e.g. font baseline for font marker symbol layers. Treated as Bottom if n...
Definition qgis.h:900
@ Top
Align to top of symbol.
Definition qgis.h:897
LinearReferencingPlacement
Defines how/where the labels should be placed in a linear referencing symbol layer.
Definition qgis.h:3387
@ IntervalZ
Place labels at regular intervals, linearly interpolated using Z values.
Definition qgis.h:3389
@ Vertex
Place labels on every vertex in the line.
Definition qgis.h:3391
@ IntervalM
Place labels at regular intervals, linearly interpolated using M values.
Definition qgis.h:3390
@ IntervalCartesian2D
Place labels at regular intervals, using Cartesian distance calculations on a 2D plane.
Definition qgis.h:3388
LinearReferencingLabelSource
Defines what quantity to use for the labels shown in a linear referencing symbol layer.
Definition qgis.h:3401
@ CartesianDistance2D
Distance along line, calculated using Cartesian calculations on a 2D plane.
Definition qgis.h:3402
@ Percentage
Percentage of another measurement (e.g., canvas size, feature size).
Definition qgis.h:5762
@ Millimeters
Millimeters.
Definition qgis.h:5759
@ Points
Points (e.g., for font sizes).
Definition qgis.h:5763
@ MapUnits
Map units.
Definition qgis.h:5760
@ Pixels
Pixels.
Definition qgis.h:5761
@ Inches
Inches.
Definition qgis.h:5764
@ MetersInMapUnits
Meters value as Map units.
Definition qgis.h:5766
@ Linear
Linear gradient.
Definition qgis.h:3431
@ Conical
Conical (polar) gradient.
Definition qgis.h:3433
@ Radial
Radial (circular) gradient.
Definition qgis.h:3432
SymbolType
Symbol types.
Definition qgis.h:671
@ Marker
Marker symbol.
Definition qgis.h:672
@ Line
Line symbol.
Definition qgis.h:673
@ Fill
Fill symbol.
Definition qgis.h:674
@ Hybrid
Hybrid symbol.
Definition qgis.h:675
SymbolCoordinateReference
Symbol coordinate reference modes.
Definition qgis.h:3445
@ Feature
Relative to feature/shape being rendered.
Definition qgis.h:3446
@ Viewport
Relative to the whole viewport/output device.
Definition qgis.h:3447
QFlags< MarkerLinePlacement > MarkerLinePlacements
Definition qgis.h:3378
HorizontalAnchorPoint
Marker symbol horizontal anchor points.
Definition qgis.h:882
@ Center
Align to horizontal center of symbol.
Definition qgis.h:884
@ Right
Align to right side of symbol.
Definition qgis.h:885
@ Left
Align to left side of symbol.
Definition qgis.h:883
static const double UI_SCALE_FACTOR
UI scaling factor.
Definition qgis.h:7320
void sourceChanged(const QString &source)
Emitted whenever the file source is changed in the widget.
void setContext(const QgsSymbolWidgetContext &context) override
Sets the context in which the symbol widget is shown, e.g., the associated map canvas and expression ...
QgsAnimatedMarkerSymbolLayer * mLayer
void setSymbolLayer(QgsSymbolLayer *layer) override
QgsAnimatedMarkerSymbolLayerWidget(QgsVectorLayer *vl, QWidget *parent=nullptr)
Constructor for QgsAnimatedMarkerSymbolLayerWidget.
Animated marker symbol layer class.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
static QgsImageCache * imageCache()
Returns the application's image cache, used for caching resampled versions of raster images.
static QgsSvgCache * svgCache()
Returns the application's SVG cache, used for caching SVG images and handling parameter replacement w...
static QString nameFromProperty(const QgsPropertyDefinition &def, bool joined=false)
Returns the name of the auxiliary field for a property definition.
QgsSymbolLayer * symbolLayer() override
void setSymbolLayer(QgsSymbolLayer *layer) override
QgsCentroidFillSymbolLayer * mLayer
QgsCentroidFillSymbolLayerWidget(QgsVectorLayer *vl, QWidget *parent=nullptr)
Constructor for QgsCentroidFillSymbolLayerWidget.
A fill symbol layer which renders a marker symbol at the centroid of a polygon geometry.
void setPointOnSurface(bool pointOnSurface)
void colorChanged(const QColor &color)
Emitted whenever a new color is set for the button.
void colorRampChanged()
Emitted whenever a new color ramp is set for the button.
QVector< qreal > dashDotVector() const
Returns the dash pattern as a list of numbers.
void setUnit(Qgis::RenderUnit unit)
Sets the unit type used for the dash space pattern (used to update interface labels).
Single scope for storing variables and functions for use within a QgsExpressionContext.
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
static QgsExpressionContextScope * updateSymbolScope(const QgsSymbol *symbol, QgsExpressionContextScope *symbolScope=nullptr)
Updates a symbol scope related to a QgsSymbol to an expression context.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
static const QString EXPR_GEOMETRY_PART_COUNT
Inbuilt variable name for geometry part count variable.
static const QString EXPR_GEOMETRY_POINT_COUNT
Inbuilt variable name for point count variable.
static const QString EXPR_CLUSTER_SIZE
Inbuilt variable name for cluster size variable.
static const QString EXPR_GEOMETRY_POINT_NUM
Inbuilt variable name for point number variable.
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for the context.
static const QString EXPR_GEOMETRY_RING_NUM
Inbuilt variable name for geometry ring number variable.
static const QString EXPR_GEOMETRY_PART_NUM
Inbuilt variable name for geometry part number variable.
static const QString EXPR_SYMBOL_COLOR
Inbuilt variable name for symbol color variable.
QgsExpressionContextScope * lastScope()
Returns the last scope added to the context.
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
bool hasVariable(const QString &name) const
Check whether a variable is specified by any scope within the context.
void setHighlightedVariables(const QStringList &variableNames)
Sets the list of variable names within the context intended to be highlighted to the user.
static const QString EXPR_ORIGINAL_VALUE
Inbuilt variable name for value original value variable.
static const QString EXPR_CLUSTER_COLOR
Inbuilt variable name for cluster color variable.
void expressionChanged(const QString &expression)
Emitted when the expression is changed.
~QgsFilledLineSymbolLayerWidget() override
QgsSymbolLayer * symbolLayer() override
QgsFilledLineSymbolLayerWidget(QgsVectorLayer *vl, QWidget *parent=nullptr)
Constructor for QgsFilledLineSymbolLayerWidget.
void setSymbolLayer(QgsSymbolLayer *layer) override
A line symbol layer type which fills a stroked line with a QgsFillSymbol.
void setMapUnitScale(const QgsMapUnitScale &scale) override
QgsFilledMarkerSymbolLayer * mLayer
QgsSymbolLayer * symbolLayer() override
QgsFilledMarkerSymbolLayerWidget(QgsVectorLayer *vl, QWidget *parent=nullptr)
Constructor for QgsFilledMarkerSymbolLayerWidget.
void setSymbolLayer(QgsSymbolLayer *layer) override
Filled marker symbol layer, consisting of a shape which is rendered using a QgsFillSymbol.
void changed()
Emitted when the widget's text format settings are changed.
QgsFontMarkerSymbolLayerWidget(QgsVectorLayer *vl, QWidget *parent=nullptr)
Constructor for QgsFontMarkerSymbolLayerWidget.
void setCharacter(QChar chr)
Set the font marker character from char.
void setSymbolLayer(QgsSymbolLayer *layer) override
~QgsFontMarkerSymbolLayerWidget() override
QgsSymbolLayer * symbolLayer() override
QgsFontMarkerSymbolLayer * mLayer
void setCharacterFromText(const QString &text)
Set the font marker character from a text string.
void setColorStroke(const QColor &color)
Set stroke color.
A marker symbol layer which displays characters rendered using a font.
void setFontStyle(const QString &style)
Sets the font style for the font which will be used to render the point.
static QString translateNamedStyle(const QString &namedStyle)
Returns the localized named style of a font, if such a translation is available.
static QString untranslateNamedStyle(const QString &namedStyle)
Returns the english named style of a font, if possible.
static QFont createFont(const QString &family, int pointSize=-1, int weight=-1, bool italic=false)
Creates a font with the specified family.
static bool updateFontViaStyle(QFont &f, const QString &fontstyle, bool fallback=false)
Updates font with named style and retain all font properties.
static void setFontFamily(QFont &font, const QString &family)
Sets the family for a font object.
void setSymbolLayer(QgsSymbolLayer *layer) override
QgsGeometryGeneratorSymbolLayerWidget(QgsVectorLayer *vl, QWidget *parent=nullptr)
Constructor for QgsGeometryGeneratorSymbolLayerWidget.
A symbol layer subclass which alters rendered feature shapes through the use of QGIS expressions.
void setGeometryExpression(const QString &exp)
Set the expression to generate this geometry.
void setSymbolLayer(QgsSymbolLayer *layer) override
QgsGradientFillSymbolLayer * mLayer
QgsSymbolLayer * symbolLayer() override
void applyColorRamp()
Applies the color ramp passed on by the color ramp button.
QgsGradientFillSymbolLayerWidget(QgsVectorLayer *vl, QWidget *parent=nullptr)
Constructor for QgsGradientFillSymbolLayerWidget.
A fill symbol layer which draws a smooth color gradient over a polygon.
void setOffset(QPointF offset)
Sets an offset by which polygons will be translated during rendering.
void setGradientColorType(Qgis::GradientColorSource gradientColorType)
Sets the gradient color mode, which controls how gradient color stops are created.
QgsHashedLineSymbolLayerWidget(QgsVectorLayer *vl, QWidget *parent=nullptr)
Constructor for QgsHashedLineSymbolLayerWidget.
Line symbol layer type which draws repeating line sections along a line feature.
void setHashLength(double length)
Sets the length of hash symbols.
double hashAngle() const
Returns the angle to use when drawing the hashed lines sections, in degrees clockwise.
const QgsMapUnitScale & hashLengthMapUnitScale() const
Returns the map unit scale for the hash length.
void setHashLengthMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the hash length.
Qgis::RenderUnit hashLengthUnit() const
Returns the units for the length of hash symbols.
double hashLength() const
Returns the length of hash symbols.
void setHashLengthUnit(Qgis::RenderUnit unit)
Sets the unit for the length of hash symbols.
void setHashAngle(double angle)
Sets the angle to use when drawing the hashed lines sections, in degrees clockwise.
static QIcon iconLine()
Returns an icon representing line geometries.
static QIcon iconPolygon()
Returns an icon representing polygon geometries.
static QIcon iconPoint()
Returns an icon representing point geometries.
int nextFrameDelay(const QString &path, int currentFrame=0, bool blocking=false)
For image formats that support animation, this function returns the number of milliseconds to wait un...
QImage pathAsImage(const QString &path, const QSize size, const bool keepAspectRatio, const double opacity, bool &fitsInCache, bool blocking=false, double targetDpi=96, int frameNumber=-1, bool *isMissing=nullptr)
Returns the specified path rendered as an image.
QgsLinePatternFillSymbolLayerWidget(QgsVectorLayer *vl, QWidget *parent=nullptr)
Constructor for QgsLinePatternFillSymbolLayerWidget.
QgsLinePatternFillSymbolLayer * mLayer
void setSymbolLayer(QgsSymbolLayer *layer) override
A symbol fill consisting of repeated parallel lines.
void setMapUnitScale(const QgsMapUnitScale &scale) override
void setLineAngle(double a)
Sets the angle for the parallel lines used to fill the symbol.
RenderRingFilter
Options for filtering rings when the line symbol layer is being used to render a polygon's rings.
@ ExteriorRingOnly
Render the exterior ring only.
@ InteriorRingsOnly
Render the interior rings only.
@ AllRings
Render both exterior and interior rings.
virtual void setWidth(double width)
Sets the width of the line symbol layer.
void setSymbolLayer(QgsSymbolLayer *layer) override
void setContext(const QgsSymbolWidgetContext &context) override
Sets the context in which the symbol widget is shown, e.g., the associated map canvas and expression ...
QgsLinearReferencingSymbolLayerWidget(QgsVectorLayer *vl, QWidget *parent=nullptr)
Constructor for QgsLinearReferencingSymbolLayerWidget.
void setNumericFormat(QgsNumericFormat *format)
Sets the numeric format used to format the labels for the layer.
QgsNumericFormat * numericFormat() const
Returns the numeric format used to format the labels for the layer.
QgsLineburstSymbolLayerWidget(QgsVectorLayer *vl, QWidget *parent=nullptr)
Constructor for QgsLineburstSymbolLayerWidget.
void setSymbolLayer(QgsSymbolLayer *layer) override
QgsLineburstSymbolLayer * mLayer
QgsSymbolLayer * symbolLayer() override
Line symbol layer type which draws a gradient pattern perpendicularly along a line.
void mapToolSet(QgsMapTool *newTool, QgsMapTool *oldTool)
Emit map tool changed with the old tool.
void setMapTool(QgsMapTool *mapTool, bool clean=false)
Sets the map tool currently being used on the canvas.
void editingStopped()
Emitted when edited changes have been successfully written to the data provider.
void editingStarted()
Emitted when editing on this layer has started.
Abstract base class for all map tools.
Definition qgsmaptool.h:74
Struct for storing maximum and minimum scales for measurements in map units.
QgsMarkerLineSymbolLayerWidget(QgsVectorLayer *vl, QWidget *parent=nullptr)
Constructor for QgsMarkerLineSymbolLayerWidget.
void setOffset(QPointF offset)
Sets the marker's offset, which is the horizontal and vertical displacement which the rendered marker...
double size() const
Returns the symbol size.
void setSizeUnit(Qgis::RenderUnit unit)
Sets the units for the symbol's size.
A dialog to create a new auxiliary layer.
A widget which allows choice of numeric formats and the properties of them.
QgsNumericFormat * format() const
Returns a new format object representing the settings currently configured in the widget.
void changed()
Emitted whenever the format configured55 in the widget is changed.
void registerExpressionContextGenerator(QgsExpressionContextGenerator *generator)
Register an expression context generator class that will be used to retrieve an expression context fo...
void setFormat(const QgsNumericFormat *format)
Sets the format to show in the widget.
void opacityChanged(double opacity)
Emitted when the opacity is changed in the widget, where opacity ranges from 0.0 (transparent) to 1....
Base class for any widget that can be shown as an inline panel.
void openPanel(QgsPanelWidget *panel)
Open a panel or dialog depending on dock mode setting If dock mode is true this method will emit the ...
bool dockMode() const
Returns the dock mode state.
void changed()
Emitted when the widget state changes.
static QgsPanelWidget * findParentPanel(QWidget *widget)
Traces through the parents of a widget to find if it is contained within a QgsPanelWidget widget.
void setPanelTitle(const QString &panelTitle)
Set the title of the panel when shown in the interface.
QgsPointPatternFillSymbolLayerWidget(QgsVectorLayer *vl, QWidget *parent=nullptr)
Constructor for QgsPointPatternFillSymbolLayerWidget.
void setSymbolLayer(QgsSymbolLayer *layer) override
QgsPointPatternFillSymbolLayer * mLayer
A fill symbol layer which fills polygon shapes with repeating marker symbols.
void setMapUnitScale(const QgsMapUnitScale &scale) override
void setDistanceX(double d)
Sets the horizontal distance between rendered markers in the fill.
A button for controlling property overrides which may apply to a widget.
QgsProperty toProperty() const
Returns a QgsProperty object encapsulating the current state of the widget.
void updateFieldLists()
Updates list of fields.
void changed()
Emitted when property definition changes.
void init(int propertyKey, const QgsProperty &property, const QgsPropertiesDefinition &definitions, const QgsVectorLayer *layer=nullptr, bool auxiliaryStorageEnabled=false)
Initialize a newly constructed property button (useful if button was included in a UI layout).
void registerExpressionContextGenerator(QgsExpressionContextGenerator *generator)
Register an expression context generator class that will be used to retrieve an expression context fo...
int propertyKey() const
Returns the property key linked to the button.
void setToProperty(const QgsProperty &property)
Sets the widget to reflect the current state of a QgsProperty.
void createAuxiliaryField()
Emitted when creating a new auxiliary field.
void setField(const QString &field)
Sets the field name the property references.
QgsRandomMarkerFillSymbolLayerWidget(QgsVectorLayer *vl, QWidget *parent=nullptr)
Constructor for QgsRandomMarkerFillSymbolLayerWidget.
void setSymbolLayer(QgsSymbolLayer *layer) override
A fill symbol layer which places markers at random locations within polygons.
void setMapUnitScale(const QgsMapUnitScale &scale) override
QgsRasterFillSymbolLayer * mLayer
void setSymbolLayer(QgsSymbolLayer *layer) override
QgsSymbolLayer * symbolLayer() override
QgsRasterFillSymbolLayerWidget(QgsVectorLayer *vl, QWidget *parent=nullptr)
Constructor for QgsRasterFillSymbolLayerWidget.
A fill symbol layer which fills polygons with a repeated raster image.
void setOpacity(double opacity)
Sets the opacity for the raster image used in the fill.
void setImageFilePath(const QString &imagePath)
Sets the path to the raster image used for the fill.
void setSymbolLayer(QgsSymbolLayer *layer) override
QgsSymbolLayer * symbolLayer() override
QgsRasterLineSymbolLayer * mLayer
QgsRasterLineSymbolLayerWidget(QgsVectorLayer *vl, QWidget *parent=nullptr)
Constructor for QgsRasterLineSymbolLayerWidget.
Line symbol layer type which draws line sections using a raster image file.
void setPath(const QString &path)
Set the raster image path.
void setOpacity(double opacity)
Set the line opacity.
QgsRasterMarkerSymbolLayerWidget(QgsVectorLayer *vl, QWidget *parent=nullptr)
Constructor for QgsRasterMarkerSymbolLayerWidget.
QgsRasterMarkerSymbolLayer * mLayer
void setSymbolLayer(QgsSymbolLayer *layer) override
void setContext(const QgsSymbolWidgetContext &context) override
Sets the context in which the symbol widget is shown, e.g., the associated map canvas and expression ...
QgsSymbolLayer * symbolLayer() override
Raster marker symbol layer class.
void setPath(const QString &path)
Set the marker raster image path.
A cross platform button subclass used to represent a locked / unlocked ratio state.
void lockChanged(bool locked)
Emitted whenever the lock state changes.
QgsSymbolLayer * symbolLayer() override
void setSymbolLayer(QgsSymbolLayer *layer) override
QgsSVGFillSymbolLayer * mLayer
void updateParamGui(bool resetValues=true)
Enables or disables svg fill color, stroke color and stroke width based on whether the svg file suppo...
QgsSVGFillSymbolLayerWidget(QgsVectorLayer *vl, QWidget *parent=nullptr)
Constructor for QgsSVGFillSymbolLayerWidget.
void setContext(const QgsSymbolWidgetContext &context) override
Sets the context in which the symbol widget is shown, e.g., the associated map canvas and expression ...
A fill symbol layer which fills polygons with a repeated SVG file.
void setPatternWidth(double width)
Sets the width to render the SVG content as within the fill (i.e.
Stores properties relating to a screen.
QgsShapeburstFillSymbolLayerWidget(QgsVectorLayer *vl, QWidget *parent=nullptr)
Constructor for QgsShapeburstFillSymbolLayerWidget.
QgsShapeburstFillSymbolLayer * mLayer
void setSymbolLayer(QgsSymbolLayer *layer) override
A fill symbol layer which applies a gradient from the outer edges of a symbol to the inside.
QgsSimpleFillSymbolLayerWidget(QgsVectorLayer *vl, QWidget *parent=nullptr)
Constructor for QgsSimpleFillSymbolLayerWidget.
void setStrokeColor(const QColor &color)
void setSymbolLayer(QgsSymbolLayer *layer) override
QgsSimpleFillSymbolLayer * mLayer
QgsSymbolLayer * symbolLayer() override
Renders polygons using a single fill and stroke color.
void setBrushStyle(Qt::BrushStyle style)
void setContext(const QgsSymbolWidgetContext &context) override
Sets the context in which the symbol widget is shown, e.g., the associated map canvas and expression ...
~QgsSimpleLineSymbolLayerWidget() override
QgsSimpleLineSymbolLayer * mLayer
void setSymbolLayer(QgsSymbolLayer *layer) override
QgsSymbolLayer * symbolLayer() override
QgsSimpleLineSymbolLayerWidget(QgsVectorLayer *vl, QWidget *parent=nullptr)
Constructor for QgsSimpleLineSymbolLayerWidget.
void resizeEvent(QResizeEvent *event) override
A simple line symbol layer, which renders lines using a line in a variety of styles (e....
void setMapUnitScale(const QgsMapUnitScale &scale) override
static QList< Qgis::MarkerShape > availableShapes()
Returns a list of all available shape types.
static bool shapeIsFilled(Qgis::MarkerShape shape)
Returns true if a symbol shape has a fill.
Qgis::MarkerShape shape() const
Returns the shape for the rendered marker symbol.
static QString encodeShape(Qgis::MarkerShape shape)
Encodes a shape to its string representation.
void setShape(Qgis::MarkerShape shape)
Sets the rendered marker shape.
QgsSymbolLayer * symbolLayer() override
void setColorStroke(const QColor &color)
QgsSimpleMarkerSymbolLayerWidget(QgsVectorLayer *vl, QWidget *parent=nullptr)
Constructor for QgsSimpleMarkerSymbolLayerWidget.
QgsSimpleMarkerSymbolLayer * mLayer
void setSymbolLayer(QgsSymbolLayer *layer) override
Simple marker symbol layer, consisting of a rendered shape with solid fill color and a stroke.
void setColor(const QColor &color) override
Sets the "representative" color for the symbol layer.
void setPenJoinStyle(Qt::PenJoinStyle style)
Sets the marker's stroke join style (e.g., miter, bevel, etc).
void setStrokeColor(const QColor &color) override
Sets the marker's stroke color.
void containsParams(const QString &path, bool &hasFillParam, QColor &defaultFillColor, bool &hasStrokeParam, QColor &defaultStrokeColor, bool &hasStrokeWidthParam, double &defaultStrokeWidth, bool blocking=false) const
Tests if an SVG file contains parameters for fill, stroke color, stroke width.
void setContext(const QgsSymbolWidgetContext &context) override
Sets the context in which the symbol widget is shown, e.g., the associated map canvas and expression ...
QgsSymbolLayer * symbolLayer() override
void setSymbolLayer(QgsSymbolLayer *layer) override
void setGuiForSvg(const QgsSvgMarkerSymbolLayer *layer, bool skipDefaultColors=false)
Updates the GUI to reflect the SVG marker symbol layer.
void setSvgPath(const QString &name)
Sets the SVG path.
QgsSvgMarkerSymbolLayer * mLayer
QgsSvgMarkerSymbolLayerWidget(QgsVectorLayer *vl, QWidget *parent=nullptr)
Constructor for QgsSvgMarkerSymbolLayerWidget.
void setSvgParameters(const QMap< QString, QgsProperty > &parameters)
Sets the dynamic SVG parameters.
~QgsSvgMarkerSymbolLayerWidget() override
A marker symbol layer which renders an SVG graphic.
QColor fillColor() const override
Returns the fill color for the symbol layer.
QString path() const
Returns the marker SVG path.
bool preservedAspectRatio() const
Returns the preserved aspect ratio value, true if fixed aspect ratio has been lower or equal to 0.
double fixedAspectRatio() const
Returns the marker aspect ratio between width and height to be used in rendering, if the value set is...
void setMapUnitScale(const QgsMapUnitScale &scale) override
QColor strokeColor() const override
Returns the stroke color for the symbol layer.
double defaultAspectRatio() const
Returns the default marker aspect ratio between width and height, 0 if not yet calculated.
void svgParametersChanged(const QMap< QString, QgsProperty > &parameters)
Emitted when the parameters have changed.
void svgSelected(const QString &path)
Emitted when an SVG is selected in the widget.
static QIcon symbolLayerPreviewIcon(const QgsSymbolLayer *layer, Qgis::RenderUnit u, QSize size, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::SymbolType parentSymbolType=Qgis::SymbolType::Hybrid, QgsMapLayer *mapLayer=nullptr, const QgsScreenProperties &screen=QgsScreenProperties())
Draws a symbol layer preview to an icon.
static QPixmap symbolPreviewPixmap(const QgsSymbol *symbol, QSize size, int padding=0, QgsRenderContext *customContext=nullptr, bool selected=false, const QgsExpressionContext *expressionContext=nullptr, const QgsLegendPatchShape *shape=nullptr, const QgsScreenProperties &screen=QgsScreenProperties())
Returns a pixmap preview for a color ramp.
static QIcon symbolPreviewIcon(const QgsSymbol *symbol, QSize size, int padding=0, QgsLegendPatchShape *shape=nullptr, const QgsScreenProperties &screen=QgsScreenProperties())
Returns an icon preview for a color ramp.
QgsVectorLayer * vectorLayer() const
Returns the vector layer associated with the widget.
void registerDataDefinedButton(QgsPropertyOverrideButton *button, QgsSymbolLayer::Property key)
Registers a data defined override button.
QgsSymbolLayerWidget(QWidget *parent, QgsVectorLayer *vl=nullptr)
Constructor for QgsSymbolLayerWidget.
void changed()
Should be emitted whenever configuration changes happened on this symbol layer configuration.
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
void symbolChanged()
Should be emitted whenever the sub symbol changed on this symbol layer configuration.
virtual void setContext(const QgsSymbolWidgetContext &context)
Sets the context in which the symbol widget is shown, e.g., the associated map canvas and expression ...
virtual QgsSymbolLayer * symbolLayer()=0
QgsSymbolWidgetContext context() const
Returns the context in which the symbol widget is shown, e.g., the associated map canvas and expressi...
Abstract base class for symbol layers.
Property
Data definable properties.
@ SkipMultiples
Skip multiples of.
@ GradientType
Gradient fill type.
@ SecondaryColor
Secondary color (eg for gradient fills).
@ File
Filename, eg for svg files.
@ VerticalAnchor
Vertical anchor point.
@ GradientReference2Y
Gradient reference point 2 y.
@ GradientReference1X
Gradient reference point 1 x.
@ OffsetY
Vertical offset.
@ OffsetX
Horizontal offset.
@ GradientReference1Y
Gradient reference point 1 y.
@ BlankSegments
String list of distance to define blank segments along line for templated line symbol layers.
@ DashPatternOffset
Dash pattern offset,.
@ GradientSpread
Gradient spread mode.
@ OffsetAlongLine
Offset along line.
@ CustomDash
Custom dash pattern.
@ ShapeburstMaxDistance
Shapeburst fill from edge distance.
@ HorizontalAnchor
Horizontal anchor point.
@ StrokeStyle
Stroke style (eg solid, dashed).
@ Name
Name, eg shape name for simple markers.
@ DistanceY
Vertical distance between points.
@ ClipPoints
Whether markers should be clipped to polygon boundaries.
@ LineClipping
Line clipping mode.
@ ShapeburstIgnoreRings
Shapeburst ignore rings.
@ Character
Character, eg for font marker symbol layers.
@ ShapeburstUseWholeShape
Shapeburst use whole shape.
@ DisplacementX
Horizontal displacement.
@ CoordinateMode
Gradient coordinate mode.
@ FillStyle
Fill style (eg solid, dots).
@ GradientReference2X
Gradient reference point 2 x.
@ TrimStart
Trim distance from start of line.
@ CapStyle
Line cap style.
@ BlurRadius
Shapeburst blur radius.
@ Placement
Line marker placement.
@ MarkerClipping
Marker clipping mode.
@ RandomSeed
Random number seed.
@ LineAngle
Line angle, or angle of hash lines for hash line symbols.
@ JoinStyle
Line join style.
@ RandomOffsetY
Random offset Y.
@ DisplacementY
Vertical displacement.
@ DistanceX
Horizontal distance between points.
@ AverageAngleLength
Length to average symbol angles over.
@ GradientReference1IsCentroid
Gradient reference point 1 is centroid.
@ Interval
Line marker interval.
@ GradientReference2IsCentroid
Gradient reference point 2 is centroid.
@ LineDistance
Distance between lines, or length of lines for hash line symbols.
@ RandomOffsetX
Random offset X.
@ ExtraItems
String list of tuple (x, y and rotation angle) to define extra items to be rendered for templated lin...
@ TrimEnd
Trim distance from end of line.
virtual QString layerType() const =0
Returns a string that represents this layer type.
virtual void setDataDefinedProperty(Property key, const QgsProperty &property)
Sets a data defined property for the layer.
virtual void setColor(const QColor &color)
Sets the "representative" color for the symbol layer.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the symbol layer property definitions.
Contains settings which reflect the context in which a symbol (or renderer) widget is shown,...
QgsMapCanvas * mapCanvas() const
Returns the map canvas associated with the widget.
Base class for templated line symbols, e.g.
void setMapUnitScale(const QgsMapUnitScale &scale) final
void setInterval(double val)
Set templated line interval.
QgsSymbolLayer * symbolLayer() override
void setOffsetAlongLine(double val)
Set offset along line.
QgsTemplatedLineSymbolLayerWidget(TemplatedSymbolType symbolType, QgsVectorLayer *vl, QWidget *parent=nullptr)
Constructor for QgsTemplatedLineSymbolLayerWidget.
void setSymbolLayer(QgsSymbolLayer *layer) override
void setContext(const QgsSymbolWidgetContext &context) override
Sets the context in which the symbol widget is shown, e.g., the associated map canvas and expression ...
A widget displaying a combobox allowing the user to choose between various display units,...
void changed()
Emitted when the selected unit is changed, or the definition of the map unit scale is changed.
QList< Qgis::RenderUnit > RenderUnitList
List of render units.
Represents a vector layer which manages a vector based dataset.
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition qgis.h:7619
QList< QgsSymbolLayer * > QgsSymbolLayerList
Definition qgssymbol.h:30
constexpr QObjectUniquePtr< Tp > make_qobject_unique(Args &&...args)
Create an object owned by a QObjectUniquePtr.
Single variable definition for use within a QgsExpressionContextScope.