QGIS API Documentation 4.1.0-Master (ca2ac17535b)
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::widgetChanged, this, [this, widget]() {
543 mLayer->setCustomDashVector( widget->dashDotVector() );
545 } );
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 btnChangeColorStroke->setAllowOpacity( true );
706 btnChangeColorStroke->setColorDialogTitle( tr( "Select Stroke Color" ) );
707 btnChangeColorStroke->setContext( u"symbology"_s );
708 btnChangeColorStroke->setShowNoColor( true );
709 btnChangeColorStroke->setNoColorString( tr( "Transparent Stroke" ) );
710
711 mFillColorDDBtn->registerLinkedWidget( btnChangeColorFill );
712 mStrokeColorDDBtn->registerLinkedWidget( btnChangeColorStroke );
713
714 spinOffsetX->setClearValue( 0.0 );
715 spinOffsetY->setClearValue( 0.0 );
716 spinAngle->setClearValue( 0.0 );
717
718 //make a temporary symbol for the size assistant preview
719 mAssistantPreviewSymbol = std::make_shared<QgsMarkerSymbol>();
720
721 if ( vectorLayer() )
722 mSizeDDBtn->setSymbol( mAssistantPreviewSymbol );
723
724 int size = lstNames->iconSize().width();
725
726 size = std::max( 30, static_cast<int>( std::round( Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance( 'X' ) * 3 ) ) );
727
728 lstNames->setGridSize( QSize( size * 1.2, size * 1.2 ) );
729 lstNames->setIconSize( QSize( size, size ) );
730
731 const double markerSize = size * 0.8;
733 for ( const Qgis::MarkerShape shape : shapes )
734 {
735 QgsSimpleMarkerSymbolLayer *lyr = new QgsSimpleMarkerSymbolLayer( shape, markerSize );
737 lyr->setColor( QColor( 200, 200, 200 ) );
738 lyr->setStrokeColor( QColor( 0, 0, 0 ) );
739 const QIcon icon
741 QListWidgetItem *item = new QListWidgetItem( icon, QString(), lstNames );
742 item->setData( Qt::UserRole, static_cast<int>( shape ) );
743 item->setToolTip( QgsSimpleMarkerSymbolLayerBase::encodeShape( shape ) );
744 delete lyr;
745 }
746 // show at least 3 rows
747 lstNames->setMinimumHeight( lstNames->gridSize().height() * 3.1 );
748
749 connect( lstNames, &QListWidget::currentRowChanged, this, &QgsSimpleMarkerSymbolLayerWidget::setShape );
752 connect( cboJoinStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::penJoinStyleChanged );
753 connect( cboCapStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::penCapStyleChanged );
754 connect( spinSize, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::setSize );
755 connect( spinAngle, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::setAngle );
756 connect( spinOffsetX, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::setOffset );
757 connect( spinOffsetY, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::setOffset );
758 connect( this, &QgsSymbolLayerWidget::changed, this, &QgsSimpleMarkerSymbolLayerWidget::updateAssistantSymbol );
759}
760
762
764{
765 if ( layer->layerType() != "SimpleMarker"_L1 )
766 return;
767
768 // layer type is correct, we can do the cast
769 mLayer = static_cast<QgsSimpleMarkerSymbolLayer *>( layer );
770
771 // set values
772 const Qgis::MarkerShape shape = mLayer->shape();
773 for ( int i = 0; i < lstNames->count(); ++i )
774 {
775 if ( static_cast<Qgis::MarkerShape>( lstNames->item( i )->data( Qt::UserRole ).toInt() ) == shape )
776 {
777 lstNames->setCurrentRow( i );
778 break;
779 }
780 }
781 btnChangeColorStroke->blockSignals( true );
782 btnChangeColorStroke->setColor( mLayer->strokeColor() );
783 btnChangeColorStroke->blockSignals( false );
784 btnChangeColorFill->blockSignals( true );
785 btnChangeColorFill->setColor( mLayer->fillColor() );
786 btnChangeColorFill->setEnabled( QgsSimpleMarkerSymbolLayerBase::shapeIsFilled( mLayer->shape() ) );
787 btnChangeColorFill->blockSignals( false );
788 spinSize->blockSignals( true );
789 spinSize->setValue( mLayer->size() );
790 spinSize->blockSignals( false );
791 spinAngle->blockSignals( true );
792 spinAngle->setValue( mLayer->angle() );
793 spinAngle->blockSignals( false );
794 mStrokeStyleComboBox->blockSignals( true );
795 mStrokeStyleComboBox->setPenStyle( mLayer->strokeStyle() );
796 mStrokeStyleComboBox->blockSignals( false );
797 mStrokeWidthSpinBox->blockSignals( true );
798 mStrokeWidthSpinBox->setValue( mLayer->strokeWidth() );
799 mStrokeWidthSpinBox->blockSignals( false );
800 cboJoinStyle->blockSignals( true );
801 cboJoinStyle->setPenJoinStyle( mLayer->penJoinStyle() );
802 cboJoinStyle->blockSignals( false );
803 cboCapStyle->blockSignals( true );
804 cboCapStyle->setPenCapStyle( mLayer->penCapStyle() );
805 cboCapStyle->blockSignals( false );
806
807 // without blocking signals the value gets changed because of slot setOffset()
808 spinOffsetX->blockSignals( true );
809 spinOffsetX->setValue( mLayer->offset().x() );
810 spinOffsetX->blockSignals( false );
811 spinOffsetY->blockSignals( true );
812 spinOffsetY->setValue( mLayer->offset().y() );
813 spinOffsetY->blockSignals( false );
814
815 mSizeUnitWidget->blockSignals( true );
816 mSizeUnitWidget->setUnit( mLayer->sizeUnit() );
817 mSizeUnitWidget->setMapUnitScale( mLayer->sizeMapUnitScale() );
818 mSizeUnitWidget->blockSignals( false );
819 mOffsetUnitWidget->blockSignals( true );
820 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
821 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
822 mOffsetUnitWidget->blockSignals( false );
823 mStrokeWidthUnitWidget->blockSignals( true );
824 mStrokeWidthUnitWidget->setUnit( mLayer->strokeWidthUnit() );
825 mStrokeWidthUnitWidget->setMapUnitScale( mLayer->strokeWidthMapUnitScale() );
826 mStrokeWidthUnitWidget->blockSignals( false );
827
828 //anchor points
829 mHorizontalAnchorComboBox->blockSignals( true );
830 mVerticalAnchorComboBox->blockSignals( true );
831 mHorizontalAnchorComboBox->setCurrentIndex( mHorizontalAnchorComboBox->findData( QVariant::fromValue( mLayer->horizontalAnchorPoint() ) ) );
832 mVerticalAnchorComboBox->setCurrentIndex( mVerticalAnchorComboBox->findData( QVariant::fromValue( mLayer->verticalAnchorPoint() ) ) );
833 mHorizontalAnchorComboBox->blockSignals( false );
834 mVerticalAnchorComboBox->blockSignals( false );
835
848
849 updateAssistantSymbol();
850}
851
856
857void QgsSimpleMarkerSymbolLayerWidget::setShape()
858{
859 mLayer->setShape( static_cast<Qgis::MarkerShape>( lstNames->currentItem()->data( Qt::UserRole ).toInt() ) );
860 btnChangeColorFill->setEnabled( QgsSimpleMarkerSymbolLayerBase::shapeIsFilled( mLayer->shape() ) );
861 emit changed();
862}
863
865{
866 mLayer->setStrokeColor( color );
867 emit changed();
868}
869
871{
872 mLayer->setColor( color );
873 emit changed();
874}
875
876void QgsSimpleMarkerSymbolLayerWidget::penJoinStyleChanged()
877{
878 mLayer->setPenJoinStyle( cboJoinStyle->penJoinStyle() );
879 emit changed();
880}
881
882void QgsSimpleMarkerSymbolLayerWidget::penCapStyleChanged()
883{
884 mLayer->setPenCapStyle( cboCapStyle->penCapStyle() );
885 emit changed();
886}
887
888void QgsSimpleMarkerSymbolLayerWidget::setSize()
889{
890 mLayer->setSize( spinSize->value() );
891 emit changed();
892}
893
894void QgsSimpleMarkerSymbolLayerWidget::setAngle()
895{
896 mLayer->setAngle( spinAngle->value() );
897 emit changed();
898}
899
900void QgsSimpleMarkerSymbolLayerWidget::setOffset()
901{
902 mLayer->setOffset( QPointF( spinOffsetX->value(), spinOffsetY->value() ) );
903 emit changed();
904}
905
906void QgsSimpleMarkerSymbolLayerWidget::mStrokeStyleComboBox_currentIndexChanged( int index )
907{
908 Q_UNUSED( index )
909
910 if ( mLayer )
911 {
912 mLayer->setStrokeStyle( mStrokeStyleComboBox->penStyle() );
913 emit changed();
914 }
915}
916
917void QgsSimpleMarkerSymbolLayerWidget::mStrokeWidthSpinBox_valueChanged( double d )
918{
919 if ( mLayer )
920 {
921 mLayer->setStrokeWidth( d );
922 emit changed();
923 }
924}
925
926void QgsSimpleMarkerSymbolLayerWidget::mSizeUnitWidget_changed()
927{
928 if ( mLayer )
929 {
930 mLayer->setSizeUnit( mSizeUnitWidget->unit() );
931 mLayer->setSizeMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
932 emit changed();
933 }
934}
935
936void QgsSimpleMarkerSymbolLayerWidget::mOffsetUnitWidget_changed()
937{
938 if ( mLayer )
939 {
940 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
941 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
942 emit changed();
943 }
944}
945
946void QgsSimpleMarkerSymbolLayerWidget::mStrokeWidthUnitWidget_changed()
947{
948 if ( mLayer )
949 {
950 mLayer->setStrokeWidthUnit( mStrokeWidthUnitWidget->unit() );
951 mLayer->setStrokeWidthMapUnitScale( mStrokeWidthUnitWidget->getMapUnitScale() );
952 emit changed();
953 }
954}
955
956void QgsSimpleMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged( int )
957{
958 if ( mLayer )
959 {
960 mLayer->setHorizontalAnchorPoint( mHorizontalAnchorComboBox->currentData().value< Qgis::HorizontalAnchorPoint >() );
961 emit changed();
962 }
963}
964
965void QgsSimpleMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged( int )
966{
967 if ( mLayer )
968 {
969 mLayer->setVerticalAnchorPoint( mVerticalAnchorComboBox->currentData().value< Qgis::VerticalAnchorPoint >() );
970 emit changed();
971 }
972}
973
974void QgsSimpleMarkerSymbolLayerWidget::updateAssistantSymbol()
975{
976 for ( int i = mAssistantPreviewSymbol->symbolLayerCount() - 1; i >= 0; --i )
977 {
978 mAssistantPreviewSymbol->deleteSymbolLayer( i );
979 }
980 mAssistantPreviewSymbol->appendSymbolLayer( mLayer->clone() );
981 const QgsProperty ddSize = mLayer->dataDefinedProperties().property( QgsSymbolLayer::Property::Size );
982 if ( ddSize )
983 mAssistantPreviewSymbol->setDataDefinedSize( ddSize );
984}
985
986
988
990 : QgsSymbolLayerWidget( parent, vl )
991{
992 mLayer = nullptr;
993
994 setupUi( this );
995 connect( mStrokeWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSimpleFillSymbolLayerWidget::mStrokeWidthUnitWidget_changed );
996 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSimpleFillSymbolLayerWidget::mOffsetUnitWidget_changed );
997 mStrokeWidthUnitWidget->setUnits(
999 );
1000 mOffsetUnitWidget->setUnits(
1002 );
1003
1004 btnChangeColor->setAllowOpacity( true );
1005 btnChangeColor->setColorDialogTitle( tr( "Select Fill Color" ) );
1006 btnChangeColor->setContext( u"symbology"_s );
1007 btnChangeColor->setShowNoColor( true );
1008 btnChangeColor->setNoColorString( tr( "Transparent Fill" ) );
1009 btnChangeStrokeColor->setAllowOpacity( true );
1010 btnChangeStrokeColor->setColorDialogTitle( tr( "Select Stroke Color" ) );
1011 btnChangeStrokeColor->setContext( u"symbology"_s );
1012 btnChangeStrokeColor->setShowNoColor( true );
1013 btnChangeStrokeColor->setNoColorString( tr( "Transparent Stroke" ) );
1014
1015 spinOffsetX->setClearValue( 0.0 );
1016 spinOffsetY->setClearValue( 0.0 );
1017
1019 connect( cboFillStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleFillSymbolLayerWidget::setBrushStyle );
1020 connect( btnChangeStrokeColor, &QgsColorButton::colorChanged, this, &QgsSimpleFillSymbolLayerWidget::setStrokeColor );
1021 connect( spinStrokeWidth, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleFillSymbolLayerWidget::strokeWidthChanged );
1022 connect( cboStrokeStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleFillSymbolLayerWidget::strokeStyleChanged );
1023 connect( cboJoinStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleFillSymbolLayerWidget::strokeStyleChanged );
1024 connect( spinOffsetX, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleFillSymbolLayerWidget::offsetChanged );
1025 connect( spinOffsetY, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleFillSymbolLayerWidget::offsetChanged );
1026
1027 mFillColorDDBtn->registerLinkedWidget( btnChangeColor );
1028 mStrokeColorDDBtn->registerLinkedWidget( btnChangeStrokeColor );
1029}
1030
1032{
1033 if ( layer->layerType() != "SimpleFill"_L1 )
1034 return;
1035
1036 // layer type is correct, we can do the cast
1037 mLayer = static_cast<QgsSimpleFillSymbolLayer *>( layer );
1038
1039 // set values
1040 btnChangeColor->blockSignals( true );
1041 btnChangeColor->setColor( mLayer->color() );
1042 btnChangeColor->blockSignals( false );
1043 cboFillStyle->blockSignals( true );
1044 cboFillStyle->setBrushStyle( mLayer->brushStyle() );
1045 cboFillStyle->blockSignals( false );
1046 btnChangeStrokeColor->blockSignals( true );
1047 btnChangeStrokeColor->setColor( mLayer->strokeColor() );
1048 btnChangeStrokeColor->blockSignals( false );
1049 cboStrokeStyle->blockSignals( true );
1050 cboStrokeStyle->setPenStyle( mLayer->strokeStyle() );
1051 cboStrokeStyle->blockSignals( false );
1052 spinStrokeWidth->blockSignals( true );
1053 spinStrokeWidth->setValue( mLayer->strokeWidth() );
1054 spinStrokeWidth->blockSignals( false );
1055 cboJoinStyle->blockSignals( true );
1056 cboJoinStyle->setPenJoinStyle( mLayer->penJoinStyle() );
1057 cboJoinStyle->blockSignals( false );
1058 spinOffsetX->blockSignals( true );
1059 spinOffsetX->setValue( mLayer->offset().x() );
1060 spinOffsetX->blockSignals( false );
1061 spinOffsetY->blockSignals( true );
1062 spinOffsetY->setValue( mLayer->offset().y() );
1063 spinOffsetY->blockSignals( false );
1064
1065 mStrokeWidthUnitWidget->blockSignals( true );
1066 mStrokeWidthUnitWidget->setUnit( mLayer->strokeWidthUnit() );
1067 mStrokeWidthUnitWidget->setMapUnitScale( mLayer->strokeWidthMapUnitScale() );
1068 mStrokeWidthUnitWidget->blockSignals( false );
1069 mOffsetUnitWidget->blockSignals( true );
1070 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
1071 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
1072 mOffsetUnitWidget->blockSignals( false );
1073
1081}
1082
1087
1089{
1090 mLayer->setColor( color );
1091 emit changed();
1092}
1093
1095{
1096 mLayer->setStrokeColor( color );
1097 emit changed();
1098}
1099
1100void QgsSimpleFillSymbolLayerWidget::setBrushStyle()
1101{
1102 mLayer->setBrushStyle( cboFillStyle->brushStyle() );
1103 emit changed();
1104}
1105
1106void QgsSimpleFillSymbolLayerWidget::strokeWidthChanged()
1107{
1108 mLayer->setStrokeWidth( spinStrokeWidth->value() );
1109 emit changed();
1110}
1111
1112void QgsSimpleFillSymbolLayerWidget::strokeStyleChanged()
1113{
1114 mLayer->setStrokeStyle( cboStrokeStyle->penStyle() );
1115 mLayer->setPenJoinStyle( cboJoinStyle->penJoinStyle() );
1116 emit changed();
1117}
1118
1119void QgsSimpleFillSymbolLayerWidget::offsetChanged()
1120{
1121 mLayer->setOffset( QPointF( spinOffsetX->value(), spinOffsetY->value() ) );
1122 emit changed();
1123}
1124
1125void QgsSimpleFillSymbolLayerWidget::mStrokeWidthUnitWidget_changed()
1126{
1127 if ( mLayer )
1128 {
1129 mLayer->setStrokeWidthUnit( mStrokeWidthUnitWidget->unit() );
1130 mLayer->setStrokeWidthMapUnitScale( mStrokeWidthUnitWidget->getMapUnitScale() );
1131 emit changed();
1132 }
1133}
1134
1135void QgsSimpleFillSymbolLayerWidget::mOffsetUnitWidget_changed()
1136{
1137 if ( mLayer )
1138 {
1139 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
1140 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
1141 emit changed();
1142 }
1143}
1144
1146
1148 : QgsSymbolLayerWidget( parent, vl )
1149{
1150 mLayer = nullptr;
1151
1152 setupUi( this );
1153
1154 mHorizontalAnchorComboBox->addItem( tr( "Left" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Left ) );
1155 mHorizontalAnchorComboBox->addItem( tr( "Horizontal Center" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Center ) );
1156 mHorizontalAnchorComboBox->addItem( tr( "Right" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Right ) );
1157
1158 mVerticalAnchorComboBox->addItem( tr( "Top" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Top ) );
1159 mVerticalAnchorComboBox->addItem( tr( "Vertical Center" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Center ) );
1160 mVerticalAnchorComboBox->addItem( tr( "Bottom" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Bottom ) );
1161
1162 connect( mSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsFilledMarkerSymbolLayerWidget::mSizeUnitWidget_changed );
1163 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsFilledMarkerSymbolLayerWidget::mOffsetUnitWidget_changed );
1164 connect( mHorizontalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsFilledMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged );
1165 connect( mVerticalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsFilledMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged );
1166 mSizeUnitWidget->setUnits(
1168 );
1169 mOffsetUnitWidget->setUnits(
1171 );
1172
1173 spinOffsetX->setClearValue( 0.0 );
1174 spinOffsetY->setClearValue( 0.0 );
1175 spinAngle->setClearValue( 0.0 );
1176
1177 //make a temporary symbol for the size assistant preview
1178 mAssistantPreviewSymbol = std::make_shared<QgsMarkerSymbol>();
1179
1180 if ( vectorLayer() )
1181 mSizeDDBtn->setSymbol( mAssistantPreviewSymbol );
1182
1183 int size = lstNames->iconSize().width();
1184 size = std::max( 30, static_cast<int>( std::round( Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance( 'X' ) * 3 ) ) );
1185 lstNames->setGridSize( QSize( size * 1.2, size * 1.2 ) );
1186 lstNames->setIconSize( QSize( size, size ) );
1187
1188 const double markerSize = size * 0.8;
1190 for ( const Qgis::MarkerShape shape : shapes )
1191 {
1192 QgsSimpleMarkerSymbolLayer *lyr = new QgsSimpleMarkerSymbolLayer( shape, markerSize );
1194 lyr->setColor( QColor( 200, 200, 200 ) );
1195 lyr->setStrokeColor( QColor( 0, 0, 0 ) );
1196 const QIcon icon
1198 QListWidgetItem *item = new QListWidgetItem( icon, QString(), lstNames );
1199 item->setData( Qt::UserRole, static_cast<int>( shape ) );
1200 item->setToolTip( QgsSimpleMarkerSymbolLayerBase::encodeShape( shape ) );
1201 delete lyr;
1202 }
1203 // show at least 3 rows
1204 lstNames->setMinimumHeight( lstNames->gridSize().height() * 3.1 );
1205
1206 connect( lstNames, &QListWidget::currentRowChanged, this, &QgsFilledMarkerSymbolLayerWidget::setShape );
1207 connect( spinSize, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsFilledMarkerSymbolLayerWidget::setSize );
1208 connect( spinAngle, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsFilledMarkerSymbolLayerWidget::setAngle );
1209 connect( spinOffsetX, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsFilledMarkerSymbolLayerWidget::setOffset );
1210 connect( spinOffsetY, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsFilledMarkerSymbolLayerWidget::setOffset );
1211 connect( this, &QgsSymbolLayerWidget::changed, this, &QgsFilledMarkerSymbolLayerWidget::updateAssistantSymbol );
1212}
1213
1215
1217{
1218 if ( layer->layerType() != "FilledMarker"_L1 )
1219 return;
1220
1221 // layer type is correct, we can do the cast
1222 mLayer = static_cast<QgsFilledMarkerSymbolLayer *>( layer );
1223
1224 // set values
1225 const Qgis::MarkerShape shape = mLayer->shape();
1226 for ( int i = 0; i < lstNames->count(); ++i )
1227 {
1228 if ( static_cast<Qgis::MarkerShape>( lstNames->item( i )->data( Qt::UserRole ).toInt() ) == shape )
1229 {
1230 lstNames->setCurrentRow( i );
1231 break;
1232 }
1233 }
1234 whileBlocking( spinSize )->setValue( mLayer->size() );
1235 whileBlocking( spinAngle )->setValue( mLayer->angle() );
1236 whileBlocking( spinOffsetX )->setValue( mLayer->offset().x() );
1237 whileBlocking( spinOffsetY )->setValue( mLayer->offset().y() );
1238
1239 mSizeUnitWidget->blockSignals( true );
1240 mSizeUnitWidget->setUnit( mLayer->sizeUnit() );
1241 mSizeUnitWidget->setMapUnitScale( mLayer->sizeMapUnitScale() );
1242 mSizeUnitWidget->blockSignals( false );
1243 mOffsetUnitWidget->blockSignals( true );
1244 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
1245 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
1246 mOffsetUnitWidget->blockSignals( false );
1247
1248 //anchor points
1249 whileBlocking( mHorizontalAnchorComboBox )->setCurrentIndex( mHorizontalAnchorComboBox->findData( QVariant::fromValue( mLayer->horizontalAnchorPoint() ) ) );
1250 whileBlocking( mVerticalAnchorComboBox )->setCurrentIndex( mVerticalAnchorComboBox->findData( QVariant::fromValue( mLayer->verticalAnchorPoint() ) ) );
1251
1258
1259 updateAssistantSymbol();
1260}
1261
1266
1267void QgsFilledMarkerSymbolLayerWidget::setShape()
1268{
1269 mLayer->setShape( static_cast<Qgis::MarkerShape>( lstNames->currentItem()->data( Qt::UserRole ).toInt() ) );
1270 emit changed();
1271}
1272
1273void QgsFilledMarkerSymbolLayerWidget::setSize()
1274{
1275 mLayer->setSize( spinSize->value() );
1276 emit changed();
1277}
1278
1279void QgsFilledMarkerSymbolLayerWidget::setAngle()
1280{
1281 mLayer->setAngle( spinAngle->value() );
1282 emit changed();
1283}
1284
1285void QgsFilledMarkerSymbolLayerWidget::setOffset()
1286{
1287 mLayer->setOffset( QPointF( spinOffsetX->value(), spinOffsetY->value() ) );
1288 emit changed();
1289}
1290
1291void QgsFilledMarkerSymbolLayerWidget::mSizeUnitWidget_changed()
1292{
1293 if ( mLayer )
1294 {
1295 mLayer->setSizeUnit( mSizeUnitWidget->unit() );
1296 mLayer->setSizeMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
1297 emit changed();
1298 }
1299}
1300
1301void QgsFilledMarkerSymbolLayerWidget::mOffsetUnitWidget_changed()
1302{
1303 if ( mLayer )
1304 {
1305 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
1306 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
1307 emit changed();
1308 }
1309}
1310
1311void QgsFilledMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged( int )
1312{
1313 if ( mLayer )
1314 {
1315 mLayer->setHorizontalAnchorPoint( mHorizontalAnchorComboBox->currentData().value<Qgis::HorizontalAnchorPoint>() );
1316 emit changed();
1317 }
1318}
1319
1320void QgsFilledMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged( int )
1321{
1322 if ( mLayer )
1323 {
1324 mLayer->setVerticalAnchorPoint( mVerticalAnchorComboBox->currentData().value< Qgis::VerticalAnchorPoint >() );
1325 emit changed();
1326 }
1327}
1328
1329void QgsFilledMarkerSymbolLayerWidget::updateAssistantSymbol()
1330{
1331 for ( int i = mAssistantPreviewSymbol->symbolLayerCount() - 1; i >= 0; --i )
1332 {
1333 mAssistantPreviewSymbol->deleteSymbolLayer( i );
1334 }
1335 mAssistantPreviewSymbol->appendSymbolLayer( mLayer->clone() );
1336 const QgsProperty ddSize = mLayer->dataDefinedProperties().property( QgsSymbolLayer::Property::Size );
1337 if ( ddSize )
1338 mAssistantPreviewSymbol->setDataDefinedSize( ddSize );
1339}
1340
1341
1343
1345 : QgsSymbolLayerWidget( parent, vl )
1346{
1347 mLayer = nullptr;
1348
1349 setupUi( this );
1350 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsGradientFillSymbolLayerWidget::mOffsetUnitWidget_changed );
1351 connect( mSpinAngle, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsGradientFillSymbolLayerWidget::mSpinAngle_valueChanged );
1352 mOffsetUnitWidget->setUnits(
1354 );
1355
1356 btnColorRamp->setShowGradientOnly( true );
1357
1358 btnChangeColor->setAllowOpacity( true );
1359 btnChangeColor->setColorDialogTitle( tr( "Select Gradient Color" ) );
1360 btnChangeColor->setContext( u"symbology"_s );
1361 btnChangeColor->setShowNoColor( true );
1362 btnChangeColor->setNoColorString( tr( "Transparent" ) );
1363 btnChangeColor2->setAllowOpacity( true );
1364 btnChangeColor2->setColorDialogTitle( tr( "Select Gradient Color" ) );
1365 btnChangeColor2->setContext( u"symbology"_s );
1366 btnChangeColor2->setShowNoColor( true );
1367 btnChangeColor2->setNoColorString( tr( "Transparent" ) );
1368
1369 mStartColorDDBtn->registerLinkedWidget( btnChangeColor );
1370 mEndColorDDBtn->registerLinkedWidget( btnChangeColor2 );
1371
1372 spinOffsetX->setClearValue( 0.0 );
1373 spinOffsetY->setClearValue( 0.0 );
1374 mSpinAngle->setClearValue( 0.0 );
1375
1379 connect( cboGradientType, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsGradientFillSymbolLayerWidget::setGradientType );
1380 connect( cboCoordinateMode, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsGradientFillSymbolLayerWidget::setCoordinateMode );
1381 connect( cboGradientSpread, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsGradientFillSymbolLayerWidget::setGradientSpread );
1382 connect( radioTwoColor, &QAbstractButton::toggled, this, &QgsGradientFillSymbolLayerWidget::colorModeChanged );
1383 connect( spinOffsetX, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsGradientFillSymbolLayerWidget::offsetChanged );
1384 connect( spinOffsetY, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsGradientFillSymbolLayerWidget::offsetChanged );
1385 connect( spinRefPoint1X, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsGradientFillSymbolLayerWidget::referencePointChanged );
1386 connect( spinRefPoint1Y, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsGradientFillSymbolLayerWidget::referencePointChanged );
1387 connect( checkRefPoint1Centroid, &QAbstractButton::toggled, this, &QgsGradientFillSymbolLayerWidget::referencePointChanged );
1388 connect( spinRefPoint2X, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsGradientFillSymbolLayerWidget::referencePointChanged );
1389 connect( spinRefPoint2Y, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsGradientFillSymbolLayerWidget::referencePointChanged );
1390 connect( checkRefPoint2Centroid, &QAbstractButton::toggled, this, &QgsGradientFillSymbolLayerWidget::referencePointChanged );
1391}
1392
1394{
1395 if ( layer->layerType() != "GradientFill"_L1 )
1396 return;
1397
1398 // layer type is correct, we can do the cast
1399 mLayer = static_cast<QgsGradientFillSymbolLayer *>( layer );
1400
1401 // set values
1402 btnChangeColor->blockSignals( true );
1403 btnChangeColor->setColor( mLayer->color() );
1404 btnChangeColor->blockSignals( false );
1405 btnChangeColor2->blockSignals( true );
1406 btnChangeColor2->setColor( mLayer->color2() );
1407 btnChangeColor2->blockSignals( false );
1408
1409 if ( mLayer->gradientColorType() == Qgis::GradientColorSource::SimpleTwoColor )
1410 {
1411 radioTwoColor->setChecked( true );
1412 btnColorRamp->setEnabled( false );
1413 }
1414 else
1415 {
1416 radioColorRamp->setChecked( true );
1417 btnChangeColor->setEnabled( false );
1418 btnChangeColor2->setEnabled( false );
1419 }
1420
1421 // set source color ramp
1422 if ( mLayer->colorRamp() )
1423 {
1424 btnColorRamp->blockSignals( true );
1425 btnColorRamp->setColorRamp( mLayer->colorRamp() );
1426 btnColorRamp->blockSignals( false );
1427 }
1428
1429 cboGradientType->blockSignals( true );
1430 switch ( mLayer->gradientType() )
1431 {
1433 cboGradientType->setCurrentIndex( 0 );
1434 break;
1436 cboGradientType->setCurrentIndex( 1 );
1437 break;
1439 cboGradientType->setCurrentIndex( 2 );
1440 break;
1441 }
1442 cboGradientType->blockSignals( false );
1443
1444 cboCoordinateMode->blockSignals( true );
1445 switch ( mLayer->coordinateMode() )
1446 {
1448 cboCoordinateMode->setCurrentIndex( 1 );
1449 checkRefPoint1Centroid->setEnabled( false );
1450 checkRefPoint2Centroid->setEnabled( false );
1451 break;
1453 default:
1454 cboCoordinateMode->setCurrentIndex( 0 );
1455 break;
1456 }
1457 cboCoordinateMode->blockSignals( false );
1458
1459 cboGradientSpread->blockSignals( true );
1460 switch ( mLayer->gradientSpread() )
1461 {
1463 cboGradientSpread->setCurrentIndex( 0 );
1464 break;
1466 cboGradientSpread->setCurrentIndex( 1 );
1467 break;
1469 cboGradientSpread->setCurrentIndex( 2 );
1470 break;
1471 }
1472 cboGradientSpread->blockSignals( false );
1473
1474 spinRefPoint1X->blockSignals( true );
1475 spinRefPoint1X->setValue( mLayer->referencePoint1().x() );
1476 spinRefPoint1X->blockSignals( false );
1477 spinRefPoint1Y->blockSignals( true );
1478 spinRefPoint1Y->setValue( mLayer->referencePoint1().y() );
1479 spinRefPoint1Y->blockSignals( false );
1480 checkRefPoint1Centroid->blockSignals( true );
1481 checkRefPoint1Centroid->setChecked( mLayer->referencePoint1IsCentroid() );
1482 if ( mLayer->referencePoint1IsCentroid() )
1483 {
1484 spinRefPoint1X->setEnabled( false );
1485 spinRefPoint1Y->setEnabled( false );
1486 }
1487 checkRefPoint1Centroid->blockSignals( false );
1488 spinRefPoint2X->blockSignals( true );
1489 spinRefPoint2X->setValue( mLayer->referencePoint2().x() );
1490 spinRefPoint2X->blockSignals( false );
1491 spinRefPoint2Y->blockSignals( true );
1492 spinRefPoint2Y->setValue( mLayer->referencePoint2().y() );
1493 spinRefPoint2Y->blockSignals( false );
1494 checkRefPoint2Centroid->blockSignals( true );
1495 checkRefPoint2Centroid->setChecked( mLayer->referencePoint2IsCentroid() );
1496 if ( mLayer->referencePoint2IsCentroid() )
1497 {
1498 spinRefPoint2X->setEnabled( false );
1499 spinRefPoint2Y->setEnabled( false );
1500 }
1501 checkRefPoint2Centroid->blockSignals( false );
1502
1503 spinOffsetX->blockSignals( true );
1504 spinOffsetX->setValue( mLayer->offset().x() );
1505 spinOffsetX->blockSignals( false );
1506 spinOffsetY->blockSignals( true );
1507 spinOffsetY->setValue( mLayer->offset().y() );
1508 spinOffsetY->blockSignals( false );
1509 mSpinAngle->blockSignals( true );
1510 mSpinAngle->setValue( mLayer->angle() );
1511 mSpinAngle->blockSignals( false );
1512
1513 mOffsetUnitWidget->blockSignals( true );
1514 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
1515 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
1516 mOffsetUnitWidget->blockSignals( false );
1517
1531}
1532
1537
1539{
1540 mLayer->setColor( color );
1541 emit changed();
1542}
1543
1545{
1546 mLayer->setColor2( color );
1547 emit changed();
1548}
1549
1550void QgsGradientFillSymbolLayerWidget::colorModeChanged()
1551{
1552 if ( radioTwoColor->isChecked() )
1553 {
1555 }
1556 else
1557 {
1558 mLayer->setGradientColorType( Qgis::GradientColorSource::ColorRamp );
1559 }
1560 emit changed();
1561}
1562
1564{
1565 if ( btnColorRamp->isNull() )
1566 return;
1567
1568 mLayer->setColorRamp( btnColorRamp->colorRamp()->clone() );
1569 emit changed();
1570}
1571
1573{
1574 switch ( index )
1575 {
1576 case 0:
1577 mLayer->setGradientType( Qgis::GradientType::Linear );
1578 //set sensible default reference points
1579 spinRefPoint1X->setValue( 0.5 );
1580 spinRefPoint1Y->setValue( 0 );
1581 spinRefPoint2X->setValue( 0.5 );
1582 spinRefPoint2Y->setValue( 1 );
1583 break;
1584 case 1:
1585 mLayer->setGradientType( Qgis::GradientType::Radial );
1586 //set sensible default reference points
1587 spinRefPoint1X->setValue( 0 );
1588 spinRefPoint1Y->setValue( 0 );
1589 spinRefPoint2X->setValue( 1 );
1590 spinRefPoint2Y->setValue( 1 );
1591 break;
1592 case 2:
1593 mLayer->setGradientType( Qgis::GradientType::Conical );
1594 spinRefPoint1X->setValue( 0.5 );
1595 spinRefPoint1Y->setValue( 0.5 );
1596 spinRefPoint2X->setValue( 1 );
1597 spinRefPoint2Y->setValue( 1 );
1598 break;
1599 }
1600 emit changed();
1601}
1602
1604{
1605 switch ( index )
1606 {
1607 case 0:
1608 //feature coordinate mode
1610 //allow choice of centroid reference positions
1611 checkRefPoint1Centroid->setEnabled( true );
1612 checkRefPoint2Centroid->setEnabled( true );
1613 break;
1614 case 1:
1615 //viewport coordinate mode
1617 //disable choice of centroid reference positions
1618 checkRefPoint1Centroid->setChecked( Qt::Unchecked );
1619 checkRefPoint1Centroid->setEnabled( false );
1620 checkRefPoint2Centroid->setChecked( Qt::Unchecked );
1621 checkRefPoint2Centroid->setEnabled( false );
1622 break;
1623 }
1624
1625 emit changed();
1626}
1627
1629{
1630 switch ( index )
1631 {
1632 case 0:
1633 mLayer->setGradientSpread( Qgis::GradientSpread::Pad );
1634 break;
1635 case 1:
1636 mLayer->setGradientSpread( Qgis::GradientSpread::Repeat );
1637 break;
1638 case 2:
1639 mLayer->setGradientSpread( Qgis::GradientSpread::Reflect );
1640 break;
1641 }
1642
1643 emit changed();
1644}
1645
1646void QgsGradientFillSymbolLayerWidget::offsetChanged()
1647{
1648 mLayer->setOffset( QPointF( spinOffsetX->value(), spinOffsetY->value() ) );
1649 emit changed();
1650}
1651
1652void QgsGradientFillSymbolLayerWidget::referencePointChanged()
1653{
1654 mLayer->setReferencePoint1( QPointF( spinRefPoint1X->value(), spinRefPoint1Y->value() ) );
1655 mLayer->setReferencePoint1IsCentroid( checkRefPoint1Centroid->isChecked() );
1656 mLayer->setReferencePoint2( QPointF( spinRefPoint2X->value(), spinRefPoint2Y->value() ) );
1657 mLayer->setReferencePoint2IsCentroid( checkRefPoint2Centroid->isChecked() );
1658 emit changed();
1659}
1660
1661void QgsGradientFillSymbolLayerWidget::mSpinAngle_valueChanged( double value )
1662{
1663 mLayer->setAngle( value );
1664 emit changed();
1665}
1666
1667void QgsGradientFillSymbolLayerWidget::mOffsetUnitWidget_changed()
1668{
1669 if ( mLayer )
1670 {
1671 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
1672 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
1673 emit changed();
1674 }
1675}
1676
1678
1680 : QgsSymbolLayerWidget( parent, vl )
1681{
1682 mLayer = nullptr;
1683
1684 setupUi( this );
1685 connect( mSpinBlurRadius, qOverload<int>( &QSpinBox::valueChanged ), this, &QgsShapeburstFillSymbolLayerWidget::mSpinBlurRadius_valueChanged );
1686 connect( mSpinMaxDistance, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, &QgsShapeburstFillSymbolLayerWidget::mSpinMaxDistance_valueChanged );
1687 connect( mDistanceUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsShapeburstFillSymbolLayerWidget::mDistanceUnitWidget_changed );
1688 connect( mRadioUseWholeShape, &QRadioButton::toggled, this, &QgsShapeburstFillSymbolLayerWidget::mRadioUseWholeShape_toggled );
1689 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsShapeburstFillSymbolLayerWidget::mOffsetUnitWidget_changed );
1690 connect( mIgnoreRingsCheckBox, &QCheckBox::stateChanged, this, &QgsShapeburstFillSymbolLayerWidget::mIgnoreRingsCheckBox_stateChanged );
1691 mDistanceUnitWidget->setUnits(
1693 );
1694 mOffsetUnitWidget->setUnits(
1696 );
1697
1698 QButtonGroup *group1 = new QButtonGroup( this );
1699 group1->addButton( radioColorRamp );
1700 group1->addButton( radioTwoColor );
1701 QButtonGroup *group2 = new QButtonGroup( this );
1702 group2->addButton( mRadioUseMaxDistance );
1703 group2->addButton( mRadioUseWholeShape );
1704 btnChangeColor->setAllowOpacity( true );
1705 btnChangeColor->setColorDialogTitle( tr( "Select Gradient Color" ) );
1706 btnChangeColor->setContext( u"symbology"_s );
1707 btnChangeColor->setShowNoColor( true );
1708 btnChangeColor->setNoColorString( tr( "Transparent" ) );
1709 btnChangeColor2->setAllowOpacity( true );
1710 btnChangeColor2->setColorDialogTitle( tr( "Select Gradient Color" ) );
1711 btnChangeColor2->setContext( u"symbology"_s );
1712 btnChangeColor2->setShowNoColor( true );
1713 btnChangeColor2->setNoColorString( tr( "Transparent" ) );
1714
1715 mStartColorDDBtn->registerLinkedWidget( btnChangeColor );
1716 mEndColorDDBtn->registerLinkedWidget( btnChangeColor2 );
1717
1718 spinOffsetX->setClearValue( 0.0 );
1719 spinOffsetY->setClearValue( 0.0 );
1720 mSpinMaxDistance->setClearValue( 5.0 );
1721
1722 btnColorRamp->setShowGradientOnly( true );
1723
1724 connect( btnColorRamp, &QgsColorRampButton::colorRampChanged, this, &QgsShapeburstFillSymbolLayerWidget::applyColorRamp );
1725
1728 connect( radioTwoColor, &QAbstractButton::toggled, this, &QgsShapeburstFillSymbolLayerWidget::colorModeChanged );
1729 connect( spinOffsetX, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsShapeburstFillSymbolLayerWidget::offsetChanged );
1730 connect( spinOffsetY, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsShapeburstFillSymbolLayerWidget::offsetChanged );
1731
1732 connect( mBlurSlider, &QAbstractSlider::valueChanged, mSpinBlurRadius, &QSpinBox::setValue );
1733 connect( mSpinBlurRadius, static_cast<void ( QSpinBox::* )( int )>( &QSpinBox::valueChanged ), mBlurSlider, &QAbstractSlider::setValue );
1734}
1735
1737{
1738 if ( layer->layerType() != "ShapeburstFill"_L1 )
1739 return;
1740
1741 // layer type is correct, we can do the cast
1742 mLayer = static_cast<QgsShapeburstFillSymbolLayer *>( layer );
1743
1744 // set values
1745 btnChangeColor->blockSignals( true );
1746 btnChangeColor->setColor( mLayer->color() );
1747 btnChangeColor->blockSignals( false );
1748 btnChangeColor2->blockSignals( true );
1749 btnChangeColor2->setColor( mLayer->color2() );
1750 btnChangeColor2->blockSignals( false );
1751
1753 {
1754 radioTwoColor->setChecked( true );
1755 btnColorRamp->setEnabled( false );
1756 }
1757 else
1758 {
1759 radioColorRamp->setChecked( true );
1760 btnChangeColor->setEnabled( false );
1761 btnChangeColor2->setEnabled( false );
1762 }
1763
1764 mSpinBlurRadius->blockSignals( true );
1765 mBlurSlider->blockSignals( true );
1766 mSpinBlurRadius->setValue( mLayer->blurRadius() );
1767 mBlurSlider->setValue( mLayer->blurRadius() );
1768 mSpinBlurRadius->blockSignals( false );
1769 mBlurSlider->blockSignals( false );
1770
1771 mSpinMaxDistance->blockSignals( true );
1772 mSpinMaxDistance->setValue( mLayer->maxDistance() );
1773 mSpinMaxDistance->blockSignals( false );
1774
1775 mRadioUseWholeShape->blockSignals( true );
1776 mRadioUseMaxDistance->blockSignals( true );
1777 if ( mLayer->useWholeShape() )
1778 {
1779 mRadioUseWholeShape->setChecked( true );
1780 mSpinMaxDistance->setEnabled( false );
1781 mDistanceUnitWidget->setEnabled( false );
1782 }
1783 else
1784 {
1785 mRadioUseMaxDistance->setChecked( true );
1786 mSpinMaxDistance->setEnabled( true );
1787 mDistanceUnitWidget->setEnabled( true );
1788 }
1789 mRadioUseWholeShape->blockSignals( false );
1790 mRadioUseMaxDistance->blockSignals( false );
1791
1792 mDistanceUnitWidget->blockSignals( true );
1793 mDistanceUnitWidget->setUnit( mLayer->distanceUnit() );
1794 mDistanceUnitWidget->setMapUnitScale( mLayer->distanceMapUnitScale() );
1795 mDistanceUnitWidget->blockSignals( false );
1796
1797 mIgnoreRingsCheckBox->blockSignals( true );
1798 mIgnoreRingsCheckBox->setCheckState( mLayer->ignoreRings() ? Qt::Checked : Qt::Unchecked );
1799 mIgnoreRingsCheckBox->blockSignals( false );
1800
1801 // set source color ramp
1802 if ( mLayer->colorRamp() )
1803 {
1804 btnColorRamp->blockSignals( true );
1805 btnColorRamp->setColorRamp( mLayer->colorRamp() );
1806 btnColorRamp->blockSignals( false );
1807 }
1808
1809 spinOffsetX->blockSignals( true );
1810 spinOffsetX->setValue( mLayer->offset().x() );
1811 spinOffsetX->blockSignals( false );
1812 spinOffsetY->blockSignals( true );
1813 spinOffsetY->setValue( mLayer->offset().y() );
1814 spinOffsetY->blockSignals( false );
1815 mOffsetUnitWidget->blockSignals( true );
1816 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
1817 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
1818 mOffsetUnitWidget->blockSignals( false );
1819
1827}
1828
1833
1835{
1836 if ( mLayer )
1837 {
1838 mLayer->setColor( color );
1839 emit changed();
1840 }
1841}
1842
1844{
1845 if ( mLayer )
1846 {
1847 mLayer->setColor2( color );
1848 emit changed();
1849 }
1850}
1851
1852void QgsShapeburstFillSymbolLayerWidget::colorModeChanged()
1853{
1854 if ( !mLayer )
1855 {
1856 return;
1857 }
1858
1859 if ( radioTwoColor->isChecked() )
1860 {
1862 }
1863 else
1864 {
1866 }
1867 emit changed();
1868}
1869
1870void QgsShapeburstFillSymbolLayerWidget::mSpinBlurRadius_valueChanged( int value )
1871{
1872 if ( mLayer )
1873 {
1874 mLayer->setBlurRadius( value );
1875 emit changed();
1876 }
1877}
1878
1879void QgsShapeburstFillSymbolLayerWidget::mSpinMaxDistance_valueChanged( double value )
1880{
1881 if ( mLayer )
1882 {
1883 mLayer->setMaxDistance( value );
1884 emit changed();
1885 }
1886}
1887
1888void QgsShapeburstFillSymbolLayerWidget::mDistanceUnitWidget_changed()
1889{
1890 if ( mLayer )
1891 {
1892 mLayer->setDistanceUnit( mDistanceUnitWidget->unit() );
1893 mLayer->setDistanceMapUnitScale( mDistanceUnitWidget->getMapUnitScale() );
1894 emit changed();
1895 }
1896}
1897
1898void QgsShapeburstFillSymbolLayerWidget::mRadioUseWholeShape_toggled( bool value )
1899{
1900 if ( mLayer )
1901 {
1902 mLayer->setUseWholeShape( value );
1903 mDistanceUnitWidget->setEnabled( !value );
1904 emit changed();
1905 }
1906}
1907
1908void QgsShapeburstFillSymbolLayerWidget::applyColorRamp()
1909{
1910 QgsColorRamp *ramp = btnColorRamp->colorRamp();
1911 if ( !ramp )
1912 return;
1913
1914 mLayer->setColorRamp( ramp );
1915 emit changed();
1916}
1917
1918void QgsShapeburstFillSymbolLayerWidget::offsetChanged()
1919{
1920 if ( mLayer )
1921 {
1922 mLayer->setOffset( QPointF( spinOffsetX->value(), spinOffsetY->value() ) );
1923 emit changed();
1924 }
1925}
1926
1927void QgsShapeburstFillSymbolLayerWidget::mOffsetUnitWidget_changed()
1928{
1929 if ( mLayer )
1930 {
1931 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
1932 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
1933 emit changed();
1934 }
1935}
1936
1937
1938void QgsShapeburstFillSymbolLayerWidget::mIgnoreRingsCheckBox_stateChanged( int state )
1939{
1940 const bool checked = ( state == Qt::Checked );
1941 mLayer->setIgnoreRings( checked );
1942 emit changed();
1943}
1944
1946
1948 : QgsSymbolLayerWidget( parent, vl )
1949 , mSymbolType( symbolType )
1950{
1951 mLayer = nullptr;
1952
1953 setupUi( this );
1954 connect( mIntervalUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsTemplatedLineSymbolLayerWidget::mIntervalUnitWidget_changed );
1955 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsTemplatedLineSymbolLayerWidget::mOffsetUnitWidget_changed );
1956 connect( mOffsetAlongLineUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsTemplatedLineSymbolLayerWidget::mOffsetAlongLineUnitWidget_changed );
1957 connect( mAverageAngleUnit, &QgsUnitSelectionWidget::changed, this, &QgsTemplatedLineSymbolLayerWidget::averageAngleUnitChanged );
1958 connect( mBlankSegmentsUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsTemplatedLineSymbolLayerWidget::blankSegmentsUnitChanged );
1959
1962 mIntervalUnitWidget->setUnits( units );
1963 mOffsetUnitWidget->setUnits( units );
1964 mOffsetAlongLineUnitWidget->setUnits( QgsUnitTypes::RenderUnitList( units ) << Qgis::RenderUnit::Percentage );
1965 mAverageAngleUnit->setUnits( units );
1966 mIntervalUnitWidget->setUnits( units );
1967 mBlankSegmentsUnitWidget->setUnits( units );
1968 mTrimDistanceStartUnitWidget->setUnits( QgsUnitTypes::RenderUnitList( units ) << Qgis::RenderUnit::Percentage );
1969 mTrimDistanceEndUnitWidget->setUnits( QgsUnitTypes::RenderUnitList( units ) << Qgis::RenderUnit::Percentage );
1970
1971 mRingFilterComboBox->addItem( QgsApplication::getThemeIcon( u"mIconAllRings.svg"_s ), tr( "All Rings" ), QgsLineSymbolLayer::AllRings );
1972 mRingFilterComboBox->addItem( QgsApplication::getThemeIcon( u"mIconExteriorRing.svg"_s ), tr( "Exterior Ring Only" ), QgsLineSymbolLayer::ExteriorRingOnly );
1973 mRingFilterComboBox->addItem( QgsApplication::getThemeIcon( u"mIconInteriorRings.svg"_s ), tr( "Interior Rings Only" ), QgsLineSymbolLayer::InteriorRingsOnly );
1974 connect( mRingFilterComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this]( int ) {
1975 if ( mLayer )
1976 {
1977 mLayer->setRingFilter( static_cast<QgsLineSymbolLayer::RenderRingFilter>( mRingFilterComboBox->currentData().toInt() ) );
1978 emit changed();
1979 }
1980 } );
1981
1982 spinOffset->setClearValue( 0.0 );
1983 mSpinOffsetAlongLine->setClearValue( 0.0 );
1984 mHashRotationSpinBox->setClearValue( 0 );
1985 mSpinAverageAngleLength->setClearValue( 4.0 );
1986 mTrimStartDistanceSpin->setClearValue( 0.0 );
1987 mTrimDistanceEndSpin->setClearValue( 0.0 );
1988
1989 connect( spinInterval, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsTemplatedLineSymbolLayerWidget::setInterval );
1990 connect( mSpinOffsetAlongLine, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsTemplatedLineSymbolLayerWidget::setOffsetAlongLine );
1991 connect( mSpinHashLength, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsTemplatedLineSymbolLayerWidget::setHashLength );
1992 connect( mHashRotationSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsTemplatedLineSymbolLayerWidget::setHashAngle );
1993 connect( chkRotateMarker, &QAbstractButton::clicked, this, &QgsTemplatedLineSymbolLayerWidget::setRotate );
1994 connect( spinOffset, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsTemplatedLineSymbolLayerWidget::setOffset );
1995 connect( mSpinAverageAngleLength, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsTemplatedLineSymbolLayerWidget::setAverageAngle );
1996
1997 QActionGroup *actionGroup = new QActionGroup( this );
1998 actionGroup->setExclusionPolicy( QActionGroup::ExclusionPolicy::Exclusive );
1999 actionGroup->addAction( mEditBlankSegmentsAction );
2000 actionGroup->addAction( mAddExtraItemAction );
2001 actionGroup->addAction( mModifyExtraItemAction );
2002
2003 mEditBlankSegmentsBtn->setDefaultAction( mEditBlankSegmentsAction );
2004 connect( mEditBlankSegmentsAction, &QAction::triggered, this, &QgsMarkerLineSymbolLayerWidget::toggleMapToolEditBlankSegments );
2005
2006 mAddExtraItemBtn->setDefaultAction( mAddExtraItemAction );
2007 connect( mAddExtraItemAction, &QAction::triggered, this, &QgsMarkerLineSymbolLayerWidget::toggleMapToolAddExtraItem );
2008
2009 mModifyExtraItemBtn->setDefaultAction( mModifyExtraItemAction );
2010 connect( mModifyExtraItemAction, &QAction::triggered, this, &QgsMarkerLineSymbolLayerWidget::toggleMapToolModifyExtraItem );
2011
2012 connect( mCheckInterval, &QCheckBox::toggled, this, &QgsTemplatedLineSymbolLayerWidget::setPlacement );
2013 connect( mCheckVertex, &QCheckBox::toggled, this, &QgsTemplatedLineSymbolLayerWidget::setPlacement );
2014 connect( mCheckVertexLast, &QCheckBox::toggled, this, &QgsTemplatedLineSymbolLayerWidget::setPlacement );
2015 connect( mCheckVertexFirst, &QCheckBox::toggled, this, &QgsTemplatedLineSymbolLayerWidget::setPlacement );
2016 connect( mCheckCentralPoint, &QCheckBox::toggled, this, &QgsTemplatedLineSymbolLayerWidget::setPlacement );
2017 connect( mCheckCurvePoint, &QCheckBox::toggled, this, &QgsTemplatedLineSymbolLayerWidget::setPlacement );
2018 connect( mCheckSegmentCentralPoint, &QCheckBox::toggled, this, &QgsTemplatedLineSymbolLayerWidget::setPlacement );
2019
2020 connect( mCheckPlaceOnEveryPart, &QCheckBox::toggled, this, [this] {
2021 if ( mLayer )
2022 {
2023 mLayer->setPlaceOnEveryPart( mCheckPlaceOnEveryPart->isChecked() );
2024 emit changed();
2025 }
2026 } );
2027
2028 connect( mTrimStartDistanceSpin, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, [this]( double value ) {
2029 if ( !mLayer )
2030 return;
2031
2032 mLayer->setTrimDistanceStart( value );
2033 emit changed();
2034 } );
2035 connect( mTrimDistanceStartUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
2036 if ( !mLayer )
2037 return;
2038
2039 mLayer->setTrimDistanceStartUnit( mTrimDistanceStartUnitWidget->unit() );
2040 mLayer->setTrimDistanceStartMapUnitScale( mTrimDistanceStartUnitWidget->getMapUnitScale() );
2041 emit changed();
2042 } );
2043 connect( mTrimDistanceEndSpin, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, [this]( double value ) {
2044 if ( !mLayer )
2045 return;
2046
2047 mLayer->setTrimDistanceEnd( value );
2048 emit changed();
2049 } );
2050 connect( mTrimDistanceEndUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
2051 if ( !mLayer )
2052 return;
2053
2054 mLayer->setTrimDistanceEndUnit( mTrimDistanceEndUnitWidget->unit() );
2055 mLayer->setTrimDistanceEndMapUnitScale( mTrimDistanceEndUnitWidget->getMapUnitScale() );
2056 emit changed();
2057 } );
2058
2059 switch ( mSymbolType )
2060 {
2062 {
2063 connect( mHashLengthUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsTemplatedLineSymbolLayerWidget::hashLengthUnitWidgetChanged );
2064 mHashLengthUnitWidget->setUnits(
2066 );
2067 mPlacementLabel->setText( tr( "Hash placement" ) );
2068 chkRotateMarker->setText( tr( "Rotate hash to follow line direction" ) );
2069 mSpinOffsetAlongLine->setToolTip( tr( "Offset hashes in line direction if positive or in opposite line direction if negative" ) );
2070 mHashLengthLabel->setVisible( true );
2071 mSpinHashLength->setVisible( true );
2072 mHashLengthUnitWidget->setVisible( true );
2073 mHashLengthDDBtn->setVisible( true );
2074 mHashRotationLabel->setVisible( true );
2075 mHashRotationSpinBox->setVisible( true );
2076 mHashRotationDDBtn->setVisible( true );
2077 break;
2078 }
2079
2081 mPlacementLabel->setText( tr( "Marker placement" ) );
2082 chkRotateMarker->setText( tr( "Rotate marker to follow line direction" ) );
2083 mSpinOffsetAlongLine->setToolTip( tr( "Offset markers in line direction if positive or in opposite line direction if negative" ) );
2084 mHashLengthLabel->setVisible( false );
2085 mSpinHashLength->setVisible( false );
2086 mHashLengthUnitWidget->setVisible( false );
2087 mHashLengthDDBtn->setVisible( false );
2088 mHashRotationLabel->setVisible( false );
2089 mHashRotationSpinBox->setVisible( false );
2090 mHashRotationDDBtn->setVisible( false );
2091 }
2092}
2093
2095{
2096 // to avoid deleting blank segments / extra items map tool while already deleting them in this destructor
2097 if ( context().mapCanvas() )
2098 {
2099 disconnect( context().mapCanvas(), &QgsMapCanvas::mapToolSet, this, nullptr );
2100 }
2101}
2102
2104{
2105 if ( event->type() == QEvent::Show )
2106 {
2107 // Per feature customization buttons are enabled only in dock mode. That requires for this widget to be
2108 // parented which is not the case when we create the widget. So we update on show event
2109 updatePerFeatureCustomizationWidget();
2110 }
2111
2112 return QgsSymbolLayerWidget::event( event );
2113}
2114
2116{
2117 switch ( mSymbolType )
2118 {
2120 if ( layer->layerType() != "HashLine"_L1 )
2121 return;
2122 break;
2123
2125 if ( layer->layerType() != "MarkerLine"_L1 )
2126 return;
2127 }
2128
2129 // layer type is correct, we can do the cast
2130 mLayer = static_cast<QgsTemplatedLineSymbolLayerBase *>( layer );
2131
2132 // set values
2133 spinInterval->blockSignals( true );
2134 spinInterval->setValue( mLayer->interval() );
2135 spinInterval->blockSignals( false );
2136 mSpinOffsetAlongLine->blockSignals( true );
2137 mSpinOffsetAlongLine->setValue( mLayer->offsetAlongLine() );
2138 mSpinOffsetAlongLine->blockSignals( false );
2139
2140 chkRotateMarker->blockSignals( true );
2141 chkRotateMarker->setChecked( mLayer->rotateSymbols() );
2142 chkRotateMarker->blockSignals( false );
2143 spinOffset->blockSignals( true );
2144 spinOffset->setValue( mLayer->offset() );
2145 spinOffset->blockSignals( false );
2146
2147 whileBlocking( mTrimStartDistanceSpin )->setValue( mLayer->trimDistanceStart() );
2148 whileBlocking( mTrimDistanceEndSpin )->setValue( mLayer->trimDistanceEnd() );
2149
2150 whileBlocking( mCheckInterval )->setChecked( mLayer->placements() & Qgis::MarkerLinePlacement::Interval );
2151 whileBlocking( mCheckVertex )->setChecked( mLayer->placements() & Qgis::MarkerLinePlacement::InnerVertices || mLayer->placements() & Qgis::MarkerLinePlacement::Vertex );
2152 whileBlocking( mCheckVertexFirst )->setChecked( mLayer->placements() & Qgis::MarkerLinePlacement::FirstVertex || mLayer->placements() & Qgis::MarkerLinePlacement::Vertex );
2153 whileBlocking( mCheckVertexLast )->setChecked( mLayer->placements() & Qgis::MarkerLinePlacement::LastVertex || mLayer->placements() & Qgis::MarkerLinePlacement::Vertex );
2154 whileBlocking( mCheckCentralPoint )->setChecked( mLayer->placements() & Qgis::MarkerLinePlacement::CentralPoint );
2155 whileBlocking( mCheckCurvePoint )->setChecked( mLayer->placements() & Qgis::MarkerLinePlacement::CurvePoint );
2156 whileBlocking( mCheckSegmentCentralPoint )->setChecked( mLayer->placements() & Qgis::MarkerLinePlacement::SegmentCenter );
2157 whileBlocking( mCheckPlaceOnEveryPart )->setChecked( mLayer->placeOnEveryPart() );
2158
2159 // set units
2160 mIntervalUnitWidget->blockSignals( true );
2161 mIntervalUnitWidget->setUnit( mLayer->intervalUnit() );
2162 mIntervalUnitWidget->setMapUnitScale( mLayer->intervalMapUnitScale() );
2163 mIntervalUnitWidget->blockSignals( false );
2164 mOffsetUnitWidget->blockSignals( true );
2165 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
2166 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
2167 mOffsetUnitWidget->blockSignals( false );
2168 mOffsetAlongLineUnitWidget->blockSignals( true );
2169 mOffsetAlongLineUnitWidget->setUnit( mLayer->offsetAlongLineUnit() );
2170 mOffsetAlongLineUnitWidget->setMapUnitScale( mLayer->offsetAlongLineMapUnitScale() );
2171 mOffsetAlongLineUnitWidget->blockSignals( false );
2172 whileBlocking( mAverageAngleUnit )->setUnit( mLayer->averageAngleUnit() );
2173 whileBlocking( mAverageAngleUnit )->setMapUnitScale( mLayer->averageAngleMapUnitScale() );
2174 whileBlocking( mSpinAverageAngleLength )->setValue( mLayer->averageAngleLength() );
2175 whileBlocking( mBlankSegmentsUnitWidget )->setUnit( mLayer->blankSegmentsUnit() );
2176 whileBlocking( mTrimDistanceStartUnitWidget )->setUnit( mLayer->trimDistanceStartUnit() );
2177 whileBlocking( mTrimDistanceStartUnitWidget )->setMapUnitScale( mLayer->trimDistanceStartMapUnitScale() );
2178 whileBlocking( mTrimDistanceEndUnitWidget )->setUnit( mLayer->trimDistanceEndUnit() );
2179 whileBlocking( mTrimDistanceEndUnitWidget )->setMapUnitScale( mLayer->trimDistanceEndMapUnitScale() );
2180
2181 switch ( mSymbolType )
2182 {
2184 {
2185 QgsHashedLineSymbolLayer *hashLayer = static_cast<QgsHashedLineSymbolLayer *>( mLayer );
2186 whileBlocking( mSpinHashLength )->setValue( hashLayer->hashLength() );
2187 whileBlocking( mHashRotationSpinBox )->setValue( hashLayer->hashAngle() );
2188 whileBlocking( mHashLengthUnitWidget )->setUnit( hashLayer->hashLengthUnit() );
2189 whileBlocking( mHashLengthUnitWidget )->setMapUnitScale( hashLayer->hashLengthMapUnitScale() );
2192 break;
2193 }
2194
2196 break;
2197 }
2198
2199 whileBlocking( mRingFilterComboBox )->setCurrentIndex( mRingFilterComboBox->findData( mLayer->ringFilter() ) );
2200
2201 setPlacement(); // update gui
2202
2212
2213 connect( mBlankSegmentsDDButton, &QgsPropertyOverrideButton::changed, this, &QgsMarkerLineSymbolLayerWidget::updatePerFeatureCustomizationWidget );
2214 connect( mBlankSegmentsDDButton, &QgsPropertyOverrideButton::createAuxiliaryField, this, &QgsMarkerLineSymbolLayerWidget::updatePerFeatureCustomizationWidget );
2215 connect( mExtraItemsDDBtn, &QgsPropertyOverrideButton::changed, this, &QgsMarkerLineSymbolLayerWidget::updatePerFeatureCustomizationWidget );
2216 connect( mExtraItemsDDBtn, &QgsPropertyOverrideButton::createAuxiliaryField, this, &QgsMarkerLineSymbolLayerWidget::updatePerFeatureCustomizationWidget );
2217
2218 if ( vectorLayer() )
2219 {
2220 connect( vectorLayer(), &QgsMapLayer::editingStarted, this, &QgsMarkerLineSymbolLayerWidget::updatePerFeatureCustomizationWidget );
2221 connect( vectorLayer(), &QgsMapLayer::editingStopped, this, &QgsMarkerLineSymbolLayerWidget::updatePerFeatureCustomizationWidget );
2222 }
2223
2224 updatePerFeatureCustomizationWidget();
2225}
2226
2231
2233{
2235
2236 switch ( context.symbolType() )
2237 {
2240 //these settings only have an effect when the symbol layers is part of a fill symbol
2241 mRingFilterComboBox->hide();
2242 mRingsLabel->hide();
2243 break;
2244
2247 break;
2248 }
2249
2250 if ( context.mapCanvas() )
2251 {
2252 connect( context.mapCanvas(), &QgsMapCanvas::mapToolSet, this, [this]( QgsMapTool *, QgsMapTool *oldMapTool ) {
2253 if ( oldMapTool == mMapToolAddExtraItem.get() )
2254 mMapToolAddExtraItem.reset();
2255 if ( oldMapTool == mMapToolModifyExtraItem.get() )
2256 mMapToolModifyExtraItem.reset();
2257 if ( oldMapTool == mMapToolEditBlankSegments.get() )
2258 mMapToolEditBlankSegments.reset();
2259 } );
2260 }
2261}
2262
2264{
2265 mLayer->setInterval( val );
2266 emit changed();
2267}
2268
2270{
2271 mLayer->setOffsetAlongLine( val );
2272 emit changed();
2273}
2274
2275void QgsTemplatedLineSymbolLayerWidget::setHashLength( double val )
2276{
2277 switch ( mSymbolType )
2278 {
2280 {
2281 QgsHashedLineSymbolLayer *hashLayer = static_cast<QgsHashedLineSymbolLayer *>( mLayer );
2282 hashLayer->setHashLength( val );
2283 emit changed();
2284 break;
2285 }
2286
2288 Q_ASSERT( false );
2289 }
2290}
2291
2292void QgsTemplatedLineSymbolLayerWidget::setHashAngle( double val )
2293{
2294 if ( !mLayer )
2295 return;
2296
2297 switch ( mSymbolType )
2298 {
2300 {
2301 QgsHashedLineSymbolLayer *hashLayer = static_cast<QgsHashedLineSymbolLayer *>( mLayer );
2302 hashLayer->setHashAngle( val );
2303 emit changed();
2304 break;
2305 }
2306
2308 Q_ASSERT( false );
2309 }
2310}
2311
2312void QgsTemplatedLineSymbolLayerWidget::setRotate()
2313{
2314 mSpinAverageAngleLength->setEnabled( chkRotateMarker->isChecked() && ( mCheckInterval->isChecked() || mCheckCentralPoint->isChecked() ) );
2315 mAverageAngleUnit->setEnabled( mSpinAverageAngleLength->isEnabled() );
2316
2317 mLayer->setRotateSymbols( chkRotateMarker->isChecked() );
2318 emit changed();
2319}
2320
2321void QgsTemplatedLineSymbolLayerWidget::setOffset()
2322{
2323 mLayer->setOffset( spinOffset->value() );
2324 emit changed();
2325}
2326
2327void QgsTemplatedLineSymbolLayerWidget::setPlacement()
2328{
2329 const bool interval = mCheckInterval->isChecked();
2330 spinInterval->setEnabled( interval );
2331 mSpinOffsetAlongLine->setEnabled( mCheckInterval->isChecked() || mCheckVertexLast->isChecked() || mCheckVertexFirst->isChecked() );
2332 mOffsetAlongLineUnitWidget->setEnabled( mSpinOffsetAlongLine->isEnabled() );
2333 mSpinAverageAngleLength->setEnabled( chkRotateMarker->isChecked() && ( mCheckInterval->isChecked() || mCheckCentralPoint->isChecked() ) );
2334 mAverageAngleUnit->setEnabled( mSpinAverageAngleLength->isEnabled() );
2335 mCheckPlaceOnEveryPart->setEnabled( mCheckVertexLast->isChecked() || mCheckVertexFirst->isChecked() );
2336
2337 Qgis::MarkerLinePlacements placements;
2338 if ( mCheckInterval->isChecked() )
2340 if ( mCheckVertex->isChecked() )
2342 if ( mCheckVertexLast->isChecked() )
2344 if ( mCheckVertexFirst->isChecked() )
2346 if ( mCheckCurvePoint->isChecked() )
2348 if ( mCheckSegmentCentralPoint->isChecked() )
2350 if ( mCheckCentralPoint->isChecked() )
2352 mLayer->setPlacements( placements );
2353
2354 emit changed();
2355}
2356
2357void QgsTemplatedLineSymbolLayerWidget::mIntervalUnitWidget_changed()
2358{
2359 if ( mLayer )
2360 {
2361 mLayer->setIntervalUnit( mIntervalUnitWidget->unit() );
2362 mLayer->setIntervalMapUnitScale( mIntervalUnitWidget->getMapUnitScale() );
2363 emit changed();
2364 }
2365}
2366
2367void QgsTemplatedLineSymbolLayerWidget::mOffsetUnitWidget_changed()
2368{
2369 if ( mLayer )
2370 {
2371 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
2372 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
2373 emit changed();
2374 }
2375}
2376
2377void QgsTemplatedLineSymbolLayerWidget::mOffsetAlongLineUnitWidget_changed()
2378{
2379 if ( mLayer )
2380 {
2381 mLayer->setOffsetAlongLineUnit( mOffsetAlongLineUnitWidget->unit() );
2382 mLayer->setOffsetAlongLineMapUnitScale( mOffsetAlongLineUnitWidget->getMapUnitScale() );
2383 }
2384 emit changed();
2385}
2386
2387void QgsTemplatedLineSymbolLayerWidget::hashLengthUnitWidgetChanged()
2388{
2389 if ( !mLayer )
2390 return;
2391
2392 switch ( mSymbolType )
2393 {
2395 {
2396 QgsHashedLineSymbolLayer *hashLayer = static_cast<QgsHashedLineSymbolLayer *>( mLayer );
2397 hashLayer->setHashLengthUnit( mHashLengthUnitWidget->unit() );
2398 hashLayer->setHashLengthMapUnitScale( mHashLengthUnitWidget->getMapUnitScale() );
2399 emit changed();
2400 break;
2401 }
2402
2404 Q_ASSERT( false );
2405 }
2406}
2407
2408void QgsTemplatedLineSymbolLayerWidget::averageAngleUnitChanged()
2409{
2410 if ( mLayer )
2411 {
2412 mLayer->setAverageAngleUnit( mAverageAngleUnit->unit() );
2413 mLayer->setAverageAngleMapUnitScale( mAverageAngleUnit->getMapUnitScale() );
2414 }
2415 emit changed();
2416}
2417
2418void QgsTemplatedLineSymbolLayerWidget::blankSegmentsUnitChanged()
2419{
2420 if ( mLayer )
2421 {
2422 mLayer->setBlankSegmentsUnit( mBlankSegmentsUnitWidget->unit() );
2423 }
2424 emit changed();
2425}
2426
2427void QgsTemplatedLineSymbolLayerWidget::setAverageAngle( double val )
2428{
2429 if ( mLayer )
2430 {
2431 mLayer->setAverageAngleLength( val );
2432 emit changed();
2433 }
2434}
2435
2436void QgsTemplatedLineSymbolLayerWidget::toggleMapToolEditBlankSegments( bool toggled )
2437{
2438 if ( !toggled || ( mMapToolEditBlankSegments.get() && context().mapCanvas()->mapTool() == mMapToolEditBlankSegments.get() ) )
2439 return;
2440
2441 switch ( mSymbolType )
2442 {
2444 mMapToolEditBlankSegments.reset( new QgsMapToolEditBlankSegments<QgsHashedLineSymbolLayer>( context().mapCanvas(), vectorLayer(), mLayer, mBlankSegmentsDDButton ) );
2445 break;
2446
2448 mMapToolEditBlankSegments.reset( new QgsMapToolEditBlankSegments<QgsMarkerLineSymbolLayer>( context().mapCanvas(), vectorLayer(), mLayer, mBlankSegmentsDDButton ) );
2449 break;
2450 }
2451
2452 mMapToolEditBlankSegments->setAction( mEditBlankSegmentsAction );
2453 context().mapCanvas()->setMapTool( mMapToolEditBlankSegments );
2454}
2455
2456void QgsTemplatedLineSymbolLayerWidget::toggleMapToolAddExtraItem( bool toggled )
2457{
2458 if ( !toggled || ( mMapToolAddExtraItem.get() && context().mapCanvas()->mapTool() == mMapToolAddExtraItem.get() ) )
2459 return;
2460
2461 mMapToolAddExtraItem.reset( new QgsMapToolAddExtraItem( context().mapCanvas(), vectorLayer(), mLayer, mExtraItemsDDBtn ) );
2462 mMapToolAddExtraItem->setAction( mAddExtraItemAction );
2463 context().mapCanvas()->setMapTool( mMapToolAddExtraItem );
2464}
2465
2466void QgsTemplatedLineSymbolLayerWidget::toggleMapToolModifyExtraItem( bool toggled )
2467{
2468 if ( !toggled || ( mMapToolModifyExtraItem.get() && context().mapCanvas()->mapTool() == mMapToolModifyExtraItem.get() ) )
2469 return;
2470
2471 mMapToolModifyExtraItem.reset( new QgsMapToolModifyExtraItems( context().mapCanvas(), vectorLayer(), mLayer, mExtraItemsDDBtn ) );
2472 mMapToolModifyExtraItem->setAction( mModifyExtraItemAction );
2473 context().mapCanvas()->setMapTool( mMapToolModifyExtraItem );
2474}
2475
2476void QgsTemplatedLineSymbolLayerWidget::updatePerFeatureCustomizationWidget()
2477{
2478 QString tooltipEditBlankSegment = u"<b>"_s;
2479 QString tooltipAddExtraItem = u"<b>"_s;
2480 QString tooltipModifyExtraItem = u"<b>"_s;
2481 switch ( mSymbolType )
2482 {
2484 tooltipEditBlankSegment += tr( "Create blank segments where hashed lines won't be displayed" );
2485 tooltipAddExtraItem += tr( "Add extra hash being displayed with the hashed line" );
2486 tooltipModifyExtraItem += tr( "Select and modify (move, rotate, delete) extra hashes being displayed with the hashed line" );
2487 break;
2488
2490 tooltipEditBlankSegment += tr( "Create blank segments where marker lines won't be displayed" );
2491 tooltipAddExtraItem += tr( "Add extra marker being displayed with the marker line" );
2492 tooltipModifyExtraItem += tr( "Select and modify (move, rotate, delete) extra markers being displayed with the marker line" );
2493 break;
2494 }
2495
2496 const QString info = u"</b><br/>"_s
2497 + tr(
2498 "First click to select the line you want to operate on. "
2499 "<br/>Press %1 to deselect the line and select another one."
2500 )
2501 .arg( QKeySequence( QKeySequence::StandardKey::Cancel ).toString( QKeySequence::NativeText ) );
2502 tooltipEditBlankSegment += info;
2503 tooltipAddExtraItem += info;
2504 tooltipModifyExtraItem += info;
2505
2506 bool enabled = true;
2507 if ( QgsPanelWidget *panelWidget = QgsPanelWidget::findParentPanel( this ); !panelWidget || !panelWidget->dockMode() )
2508 {
2509 // It's not possible to edit blank segments from Layer properties dialog
2510 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." );
2511 tooltipEditBlankSegment += u"<br/><br/>"_s + accessFromDialog;
2512 tooltipAddExtraItem += u"<br/><br/>"_s + accessFromDialog;
2513 tooltipModifyExtraItem += u"<br/><br/>"_s + accessFromDialog;
2514
2515 enabled = false;
2516 }
2517
2518 mEditBlankSegmentsAction->setEnabled( enabled );
2519 mAddExtraItemAction->setEnabled( enabled );
2520 mModifyExtraItemAction->setEnabled( enabled );
2521
2522 mEditBlankSegmentsAction->setToolTip( tooltipEditBlankSegment );
2523 mAddExtraItemAction->setToolTip( tooltipAddExtraItem );
2524 mModifyExtraItemAction->setToolTip( tooltipModifyExtraItem );
2525}
2526
2528
2532
2534
2538
2540
2541
2543 : QgsSymbolLayerWidget( parent, vl )
2544{
2545 mLayer = nullptr;
2546
2547 setupUi( this );
2548
2549 mHorizontalAnchorComboBox->addItem( tr( "Left" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Left ) );
2550 mHorizontalAnchorComboBox->addItem( tr( "Horizontal Center" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Center ) );
2551 mHorizontalAnchorComboBox->addItem( tr( "Right" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Right ) );
2552
2553 mVerticalAnchorComboBox->addItem( tr( "Top" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Top ) );
2554 mVerticalAnchorComboBox->addItem( tr( "Vertical Center" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Center ) );
2555 mVerticalAnchorComboBox->addItem( tr( "Bottom" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Bottom ) );
2556
2557 mSvgSelectorWidget->setAllowParameters( true );
2558 mSvgSelectorWidget->sourceLineEdit()->setPropertyOverrideToolButtonVisible( true );
2559 mSvgSelectorWidget->sourceLineEdit()->setLastPathSettingsKey( u"/UI/lastSVGMarkerDir"_s );
2560 mSvgSelectorWidget->initParametersModel( this, vl );
2561
2562 connect( mSvgSelectorWidget->sourceLineEdit(), &QgsSvgSourceLineEdit::sourceChanged, this, &QgsSvgMarkerSymbolLayerWidget::svgSourceChanged );
2563 connect( mChangeColorButton, &QgsColorButton::colorChanged, this, &QgsSvgMarkerSymbolLayerWidget::mChangeColorButton_colorChanged );
2564 connect( mChangeStrokeColorButton, &QgsColorButton::colorChanged, this, &QgsSvgMarkerSymbolLayerWidget::mChangeStrokeColorButton_colorChanged );
2565 connect( mStrokeWidthSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSvgMarkerSymbolLayerWidget::mStrokeWidthSpinBox_valueChanged );
2566 connect( mSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSvgMarkerSymbolLayerWidget::mSizeUnitWidget_changed );
2567 connect( mStrokeWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSvgMarkerSymbolLayerWidget::mStrokeWidthUnitWidget_changed );
2568 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSvgMarkerSymbolLayerWidget::mOffsetUnitWidget_changed );
2569 connect( mHorizontalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSvgMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged );
2570 connect( mVerticalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSvgMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged );
2571 mSizeUnitWidget->setUnits(
2573 );
2574 mStrokeWidthUnitWidget->setUnits(
2576 );
2577 mOffsetUnitWidget->setUnits(
2579 );
2580 mChangeColorButton->setAllowOpacity( true );
2581 mChangeColorButton->setColorDialogTitle( tr( "Select Fill color" ) );
2582 mChangeColorButton->setContext( u"symbology"_s );
2583 mChangeStrokeColorButton->setAllowOpacity( true );
2584 mChangeStrokeColorButton->setColorDialogTitle( tr( "Select Stroke Color" ) );
2585 mChangeStrokeColorButton->setContext( u"symbology"_s );
2586
2587 mFillColorDDBtn->registerLinkedWidget( mChangeColorButton );
2588 mStrokeColorDDBtn->registerLinkedWidget( mChangeStrokeColorButton );
2589
2590 spinOffsetX->setClearValue( 0.0 );
2591 spinOffsetY->setClearValue( 0.0 );
2592 spinAngle->setClearValue( 0.0 );
2593
2594 connect( spinWidth, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSvgMarkerSymbolLayerWidget::setWidth );
2595 connect( spinHeight, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSvgMarkerSymbolLayerWidget::setHeight );
2596 connect( mLockAspectRatio, static_cast<void ( QgsRatioLockButton::* )( bool )>( &QgsRatioLockButton::lockChanged ), this, &QgsSvgMarkerSymbolLayerWidget::lockAspectRatioChanged );
2597 connect( spinAngle, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSvgMarkerSymbolLayerWidget::setAngle );
2598 connect( spinOffsetX, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSvgMarkerSymbolLayerWidget::setOffset );
2599 connect( spinOffsetY, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSvgMarkerSymbolLayerWidget::setOffset );
2600 connect( this, &QgsSymbolLayerWidget::changed, this, &QgsSvgMarkerSymbolLayerWidget::updateAssistantSymbol );
2601
2604
2605 //make a temporary symbol for the size assistant preview
2606 mAssistantPreviewSymbol = std::make_shared<QgsMarkerSymbol>();
2607
2608 if ( vectorLayer() )
2609 {
2610 mWidthDDBtn->setSymbol( mAssistantPreviewSymbol );
2611 mHeightDDBtn->setSymbol( mAssistantPreviewSymbol );
2612 }
2613}
2614
2616
2617#include <QTime>
2618#include <QAbstractListModel>
2619#include <QPixmapCache>
2620#include <QStyle>
2621#include <memory>
2622
2623
2625{
2626 if ( !layer )
2627 {
2628 return;
2629 }
2630
2631 //activate gui for svg parameters only if supported by the svg file
2632 bool hasFillParam, hasFillOpacityParam, hasStrokeParam, hasStrokeWidthParam, hasStrokeOpacityParam;
2633 QColor defaultFill, defaultStroke;
2634 double defaultStrokeWidth, defaultFillOpacity, defaultStrokeOpacity;
2635 bool hasDefaultFillColor, hasDefaultFillOpacity, hasDefaultStrokeColor, hasDefaultStrokeWidth, hasDefaultStrokeOpacity;
2637 layer->path(),
2638 hasFillParam,
2639 hasDefaultFillColor,
2640 defaultFill,
2641 hasFillOpacityParam,
2642 hasDefaultFillOpacity,
2643 defaultFillOpacity,
2644 hasStrokeParam,
2645 hasDefaultStrokeColor,
2646 defaultStroke,
2647 hasStrokeWidthParam,
2648 hasDefaultStrokeWidth,
2649 defaultStrokeWidth,
2650 hasStrokeOpacityParam,
2651 hasDefaultStrokeOpacity,
2652 defaultStrokeOpacity
2653 );
2654 mChangeColorButton->setEnabled( hasFillParam );
2655 mChangeColorButton->setAllowOpacity( hasFillOpacityParam );
2656 mChangeStrokeColorButton->setEnabled( hasStrokeParam );
2657 mChangeStrokeColorButton->setAllowOpacity( hasStrokeOpacityParam );
2658 mStrokeWidthSpinBox->setEnabled( hasStrokeWidthParam );
2659
2660 if ( hasFillParam )
2661 {
2662 QColor fill = layer->fillColor();
2663 const double existingOpacity = hasFillOpacityParam ? fill.alphaF() : 1.0;
2664 if ( hasDefaultFillColor && !skipDefaultColors )
2665 {
2666 fill = defaultFill;
2667 }
2668 fill.setAlphaF( hasDefaultFillOpacity ? defaultFillOpacity : existingOpacity );
2669 mChangeColorButton->setColor( fill );
2670 }
2671 if ( hasStrokeParam )
2672 {
2673 QColor stroke = layer->strokeColor();
2674 const double existingOpacity = hasStrokeOpacityParam ? stroke.alphaF() : 1.0;
2675 if ( hasDefaultStrokeColor && !skipDefaultColors )
2676 {
2677 stroke = defaultStroke;
2678 }
2679 stroke.setAlphaF( hasDefaultStrokeOpacity ? defaultStrokeOpacity : existingOpacity );
2680 mChangeStrokeColorButton->setColor( stroke );
2681 }
2682
2683 whileBlocking( mSvgSelectorWidget->sourceLineEdit() )->setSource( layer->path() );
2684
2685 mStrokeWidthSpinBox->blockSignals( true );
2686 mStrokeWidthSpinBox->setValue( hasDefaultStrokeWidth ? defaultStrokeWidth : layer->strokeWidth() );
2687 mStrokeWidthSpinBox->blockSignals( false );
2688
2689 const bool preservedAspectRatio = layer->preservedAspectRatio();
2690 spinHeight->blockSignals( true );
2691 if ( preservedAspectRatio )
2692 {
2693 spinHeight->setValue( layer->size() * layer->defaultAspectRatio() );
2694 }
2695 else
2696 {
2697 spinHeight->setValue( layer->size() * layer->fixedAspectRatio() );
2698 }
2699 spinHeight->setEnabled( layer->defaultAspectRatio() > 0.0 );
2700 spinHeight->blockSignals( false );
2701 whileBlocking( mLockAspectRatio )->setLocked( preservedAspectRatio );
2702}
2703
2704void QgsSvgMarkerSymbolLayerWidget::updateAssistantSymbol()
2705{
2706 for ( int i = mAssistantPreviewSymbol->symbolLayerCount() - 1; i >= 0; --i )
2707 {
2708 mAssistantPreviewSymbol->deleteSymbolLayer( i );
2709 }
2710 mAssistantPreviewSymbol->appendSymbolLayer( mLayer->clone() );
2711 const QgsProperty ddSize = mLayer->dataDefinedProperties().property( QgsSymbolLayer::Property::Size );
2712 if ( ddSize )
2713 mAssistantPreviewSymbol->setDataDefinedSize( ddSize );
2714}
2715
2716
2718{
2719 if ( !layer )
2720 {
2721 return;
2722 }
2723
2724 if ( layer->layerType() != "SvgMarker"_L1 )
2725 return;
2726
2727 // layer type is correct, we can do the cast
2728 mLayer = static_cast<QgsSvgMarkerSymbolLayer *>( layer );
2729
2730 // set values
2731 mSvgSelectorWidget->setSvgPath( mLayer->path() );
2732 mSvgSelectorWidget->setSvgParameters( mLayer->parameters() );
2733
2734 spinWidth->blockSignals( true );
2735 spinWidth->setValue( mLayer->size() );
2736 spinWidth->blockSignals( false );
2737 spinAngle->blockSignals( true );
2738 spinAngle->setValue( mLayer->angle() );
2739 spinAngle->blockSignals( false );
2740
2741 // without blocking signals the value gets changed because of slot setOffset()
2742 spinOffsetX->blockSignals( true );
2743 spinOffsetX->setValue( mLayer->offset().x() );
2744 spinOffsetX->blockSignals( false );
2745 spinOffsetY->blockSignals( true );
2746 spinOffsetY->setValue( mLayer->offset().y() );
2747 spinOffsetY->blockSignals( false );
2748
2749 mSizeUnitWidget->blockSignals( true );
2750 mSizeUnitWidget->setUnit( mLayer->sizeUnit() );
2751 mSizeUnitWidget->setMapUnitScale( mLayer->sizeMapUnitScale() );
2752 mSizeUnitWidget->blockSignals( false );
2753 mStrokeWidthUnitWidget->blockSignals( true );
2754 mStrokeWidthUnitWidget->setUnit( mLayer->strokeWidthUnit() );
2755 mStrokeWidthUnitWidget->setMapUnitScale( mLayer->strokeWidthMapUnitScale() );
2756 mStrokeWidthUnitWidget->blockSignals( false );
2757 mOffsetUnitWidget->blockSignals( true );
2758 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
2759 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
2760 mOffsetUnitWidget->blockSignals( false );
2761
2762 //anchor points
2763 mHorizontalAnchorComboBox->blockSignals( true );
2764 mVerticalAnchorComboBox->blockSignals( true );
2765 mHorizontalAnchorComboBox->setCurrentIndex( mHorizontalAnchorComboBox->findData( QVariant::fromValue( mLayer->horizontalAnchorPoint() ) ) );
2766 mVerticalAnchorComboBox->setCurrentIndex( mVerticalAnchorComboBox->findData( QVariant::fromValue( mLayer->verticalAnchorPoint() ) ) );
2767 mHorizontalAnchorComboBox->blockSignals( false );
2768 mVerticalAnchorComboBox->blockSignals( false );
2769
2770 setGuiForSvg( mLayer, true );
2771
2781
2782 registerDataDefinedButton( mSvgSelectorWidget->sourceLineEdit()->propertyOverrideToolButton(), QgsSymbolLayer::Property::Name );
2783
2784 updateAssistantSymbol();
2785}
2786
2791
2793{
2795 mSvgSelectorWidget->sourceLineEdit()->setMessageBar( context.messageBar() );
2796}
2797
2799{
2800 mLayer->setPath( name );
2801 whileBlocking( mSvgSelectorWidget->sourceLineEdit() )->setSource( name );
2802
2804 emit changed();
2805}
2806
2807void QgsSvgMarkerSymbolLayerWidget::setSvgParameters( const QMap<QString, QgsProperty> &parameters )
2808{
2809 mLayer->setParameters( parameters );
2810 whileBlocking( mSvgSelectorWidget )->setSvgParameters( parameters );
2811
2813 emit changed();
2814}
2815
2816void QgsSvgMarkerSymbolLayerWidget::setWidth()
2817{
2818 const double defaultAspectRatio = mLayer->defaultAspectRatio();
2819 double fixedAspectRatio = 0.0;
2820 spinHeight->blockSignals( true );
2821 if ( defaultAspectRatio <= 0.0 )
2822 {
2823 spinHeight->setValue( spinWidth->value() );
2824 }
2825 else if ( mLockAspectRatio->locked() )
2826 {
2827 spinHeight->setValue( spinWidth->value() * defaultAspectRatio );
2828 }
2829 else
2830 {
2831 fixedAspectRatio = spinHeight->value() / spinWidth->value();
2832 }
2833 spinHeight->blockSignals( false );
2834 mLayer->setSize( spinWidth->value() );
2835 mLayer->setFixedAspectRatio( fixedAspectRatio );
2836 emit changed();
2837}
2838
2839void QgsSvgMarkerSymbolLayerWidget::setHeight()
2840{
2841 const double defaultAspectRatio = mLayer->defaultAspectRatio();
2842 double fixedAspectRatio = 0.0;
2843 spinWidth->blockSignals( true );
2844 if ( defaultAspectRatio <= 0.0 )
2845 {
2846 spinWidth->setValue( spinHeight->value() );
2847 }
2848 else if ( mLockAspectRatio->locked() )
2849 {
2850 spinWidth->setValue( spinHeight->value() / defaultAspectRatio );
2851 }
2852 else
2853 {
2854 fixedAspectRatio = spinHeight->value() / spinWidth->value();
2855 }
2856 spinWidth->blockSignals( false );
2857 mLayer->setSize( spinWidth->value() );
2858 mLayer->setFixedAspectRatio( fixedAspectRatio );
2859 emit changed();
2860}
2861
2862void QgsSvgMarkerSymbolLayerWidget::lockAspectRatioChanged( const bool locked )
2863{
2864 //spinHeight->setEnabled( !locked );
2865 const double defaultAspectRatio = mLayer->defaultAspectRatio();
2866 if ( defaultAspectRatio <= 0.0 )
2867 {
2868 whileBlocking( mLockAspectRatio )->setLocked( true );
2869 }
2870 else if ( locked )
2871 {
2872 mLayer->setFixedAspectRatio( 0.0 );
2873 setWidth();
2874 }
2875 else
2876 {
2877 mLayer->setFixedAspectRatio( spinHeight->value() / spinWidth->value() );
2878 }
2879 //emit changed();
2880}
2881
2882void QgsSvgMarkerSymbolLayerWidget::setAngle()
2883{
2884 mLayer->setAngle( spinAngle->value() );
2885 emit changed();
2886}
2887
2888void QgsSvgMarkerSymbolLayerWidget::setOffset()
2889{
2890 mLayer->setOffset( QPointF( spinOffsetX->value(), spinOffsetY->value() ) );
2891 emit changed();
2892}
2893
2894void QgsSvgMarkerSymbolLayerWidget::svgSourceChanged( const QString &text )
2895{
2896 mLayer->setPath( text );
2898 emit changed();
2899}
2900
2901void QgsSvgMarkerSymbolLayerWidget::mChangeColorButton_colorChanged( const QColor &color )
2902{
2903 if ( !mLayer )
2904 {
2905 return;
2906 }
2907
2908 mLayer->setFillColor( color );
2909 emit changed();
2910}
2911
2912void QgsSvgMarkerSymbolLayerWidget::mChangeStrokeColorButton_colorChanged( const QColor &color )
2913{
2914 if ( !mLayer )
2915 {
2916 return;
2917 }
2918
2919 mLayer->setStrokeColor( color );
2920 emit changed();
2921}
2922
2923void QgsSvgMarkerSymbolLayerWidget::mStrokeWidthSpinBox_valueChanged( double d )
2924{
2925 if ( mLayer )
2926 {
2927 mLayer->setStrokeWidth( d );
2928 emit changed();
2929 }
2930}
2931
2932void QgsSvgMarkerSymbolLayerWidget::mSizeUnitWidget_changed()
2933{
2934 if ( mLayer )
2935 {
2936 mLayer->setSizeUnit( mSizeUnitWidget->unit() );
2937 mLayer->setSizeMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
2938 emit changed();
2939 }
2940}
2941
2942void QgsSvgMarkerSymbolLayerWidget::mStrokeWidthUnitWidget_changed()
2943{
2944 if ( mLayer )
2945 {
2946 mLayer->setStrokeWidthUnit( mStrokeWidthUnitWidget->unit() );
2947 mLayer->setStrokeWidthMapUnitScale( mStrokeWidthUnitWidget->getMapUnitScale() );
2948 emit changed();
2949 }
2950}
2951
2952void QgsSvgMarkerSymbolLayerWidget::mOffsetUnitWidget_changed()
2953{
2954 if ( mLayer )
2955 {
2956 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
2957 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
2958 emit changed();
2959 }
2960}
2961
2962void QgsSvgMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged( int )
2963{
2964 if ( mLayer )
2965 {
2966 mLayer->setHorizontalAnchorPoint( mHorizontalAnchorComboBox->currentData().value< Qgis::HorizontalAnchorPoint >() );
2967 emit changed();
2968 }
2969}
2970
2971void QgsSvgMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged( int )
2972{
2973 if ( mLayer )
2974 {
2975 mLayer->setVerticalAnchorPoint( mVerticalAnchorComboBox->currentData().value< Qgis::VerticalAnchorPoint >() );
2976 emit changed();
2977 }
2978}
2979
2981
2983 : QgsSymbolLayerWidget( parent, vl )
2984{
2985 mLayer = nullptr;
2986 setupUi( this );
2987
2988 mSvgSelectorWidget->setAllowParameters( true );
2989 mSvgSelectorWidget->sourceLineEdit()->setPropertyOverrideToolButtonVisible( true );
2990
2991 connect( mTextureWidthSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSVGFillSymbolLayerWidget::mTextureWidthSpinBox_valueChanged );
2992 connect( mSvgSelectorWidget->sourceLineEdit(), &QgsSvgSourceLineEdit::sourceChanged, this, &QgsSVGFillSymbolLayerWidget::svgSourceChanged );
2993 connect( mRotationSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSVGFillSymbolLayerWidget::mRotationSpinBox_valueChanged );
2994 connect( mChangeColorButton, &QgsColorButton::colorChanged, this, &QgsSVGFillSymbolLayerWidget::mChangeColorButton_colorChanged );
2995 connect( mChangeStrokeColorButton, &QgsColorButton::colorChanged, this, &QgsSVGFillSymbolLayerWidget::mChangeStrokeColorButton_colorChanged );
2996 connect( mStrokeWidthSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSVGFillSymbolLayerWidget::mStrokeWidthSpinBox_valueChanged );
2997 connect( mTextureWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSVGFillSymbolLayerWidget::mTextureWidthUnitWidget_changed );
2998 connect( mSvgStrokeWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSVGFillSymbolLayerWidget::mSvgStrokeWidthUnitWidget_changed );
2999 mTextureWidthUnitWidget->setUnits(
3001 );
3002 mSvgStrokeWidthUnitWidget->setUnits(
3004 );
3005
3006 mRotationSpinBox->setClearValue( 0.0 );
3007
3008 mChangeColorButton->setColorDialogTitle( tr( "Select Fill Color" ) );
3009 mChangeColorButton->setContext( u"symbology"_s );
3010 mChangeStrokeColorButton->setColorDialogTitle( tr( "Select Stroke Color" ) );
3011 mChangeStrokeColorButton->setContext( u"symbology"_s );
3012
3013 mFilColorDDBtn->registerLinkedWidget( mChangeColorButton );
3014 mStrokeColorDDBtn->registerLinkedWidget( mChangeStrokeColorButton );
3015
3016 connect( mSvgSelectorWidget, &QgsSvgSelectorWidget::svgSelected, this, &QgsSVGFillSymbolLayerWidget::setFile );
3017 connect( mSvgSelectorWidget, &QgsSvgSelectorWidget::svgParametersChanged, this, &QgsSVGFillSymbolLayerWidget::setSvgParameters );
3018}
3019
3021{
3022 if ( !layer )
3023 {
3024 return;
3025 }
3026
3027 if ( layer->layerType() != "SVGFill"_L1 )
3028 {
3029 return;
3030 }
3031
3032 mLayer = dynamic_cast<QgsSVGFillSymbolLayer *>( layer );
3033 if ( mLayer )
3034 {
3035 const double width = mLayer->patternWidth();
3036 mTextureWidthSpinBox->blockSignals( true );
3037 mTextureWidthSpinBox->setValue( width );
3038 mTextureWidthSpinBox->blockSignals( false );
3039 whileBlocking( mSvgSelectorWidget->sourceLineEdit() )->setSource( mLayer->svgFilePath() );
3040 mRotationSpinBox->blockSignals( true );
3041 mRotationSpinBox->setValue( mLayer->angle() );
3042 mRotationSpinBox->blockSignals( false );
3043 mTextureWidthUnitWidget->blockSignals( true );
3044 mTextureWidthUnitWidget->setUnit( mLayer->patternWidthUnit() );
3045 mTextureWidthUnitWidget->setMapUnitScale( mLayer->patternWidthMapUnitScale() );
3046 mTextureWidthUnitWidget->blockSignals( false );
3047 mSvgStrokeWidthUnitWidget->blockSignals( true );
3048 mSvgStrokeWidthUnitWidget->setUnit( mLayer->svgStrokeWidthUnit() );
3049 mSvgStrokeWidthUnitWidget->setMapUnitScale( mLayer->svgStrokeWidthMapUnitScale() );
3050 mSvgStrokeWidthUnitWidget->blockSignals( false );
3051 mChangeColorButton->blockSignals( true );
3052 mChangeColorButton->setColor( mLayer->svgFillColor() );
3053 mChangeColorButton->blockSignals( false );
3054 mChangeStrokeColorButton->blockSignals( true );
3055 mChangeStrokeColorButton->setColor( mLayer->svgStrokeColor() );
3056 mChangeStrokeColorButton->blockSignals( false );
3057 mStrokeWidthSpinBox->blockSignals( true );
3058 mStrokeWidthSpinBox->setValue( mLayer->svgStrokeWidth() );
3059 mStrokeWidthSpinBox->blockSignals( false );
3060 }
3061 updateParamGui( false );
3062
3068
3069 registerDataDefinedButton( mSvgSelectorWidget->sourceLineEdit()->propertyOverrideToolButton(), QgsSymbolLayer::Property::File );
3070}
3071
3076
3078{
3080 mSvgSelectorWidget->sourceLineEdit()->setMessageBar( context.messageBar() );
3081}
3082
3083void QgsSVGFillSymbolLayerWidget::mTextureWidthSpinBox_valueChanged( double d )
3084{
3085 if ( mLayer )
3086 {
3087 mLayer->setPatternWidth( d );
3088 emit changed();
3089 }
3090}
3091
3092void QgsSVGFillSymbolLayerWidget::svgSourceChanged( const QString &text )
3093{
3094 if ( !mLayer )
3095 {
3096 return;
3097 }
3098
3099 mLayer->setSvgFilePath( text );
3101 emit changed();
3102}
3103
3104void QgsSVGFillSymbolLayerWidget::setFile( const QString &name )
3105{
3106 mLayer->setSvgFilePath( name );
3107 whileBlocking( mSvgSelectorWidget->sourceLineEdit() )->setSource( name );
3108
3110 emit changed();
3111}
3112
3113void QgsSVGFillSymbolLayerWidget::setSvgParameters( const QMap<QString, QgsProperty> &parameters )
3114{
3115 mLayer->setParameters( parameters );
3116 whileBlocking( mSvgSelectorWidget )->setSvgParameters( parameters );
3117
3119 emit changed();
3120}
3121
3122
3123void QgsSVGFillSymbolLayerWidget::mRotationSpinBox_valueChanged( double d )
3124{
3125 if ( mLayer )
3126 {
3127 mLayer->setAngle( d );
3128 emit changed();
3129 }
3130}
3131
3133{
3134 //activate gui for svg parameters only if supported by the svg file
3135 bool hasFillParam, hasFillOpacityParam, hasStrokeParam, hasStrokeWidthParam, hasStrokeOpacityParam;
3136 QColor defaultFill, defaultStroke;
3137 double defaultStrokeWidth, defaultFillOpacity, defaultStrokeOpacity;
3138 bool hasDefaultFillColor, hasDefaultFillOpacity, hasDefaultStrokeColor, hasDefaultStrokeWidth, hasDefaultStrokeOpacity;
3140 mSvgSelectorWidget->sourceLineEdit()->source(),
3141 hasFillParam,
3142 hasDefaultFillColor,
3143 defaultFill,
3144 hasFillOpacityParam,
3145 hasDefaultFillOpacity,
3146 defaultFillOpacity,
3147 hasStrokeParam,
3148 hasDefaultStrokeColor,
3149 defaultStroke,
3150 hasStrokeWidthParam,
3151 hasDefaultStrokeWidth,
3152 defaultStrokeWidth,
3153 hasStrokeOpacityParam,
3154 hasDefaultStrokeOpacity,
3155 defaultStrokeOpacity
3156 );
3157 if ( resetValues )
3158 {
3159 QColor fill = mChangeColorButton->color();
3160 const double newOpacity = hasFillOpacityParam ? fill.alphaF() : 1.0;
3161 if ( hasDefaultFillColor )
3162 {
3163 fill = defaultFill;
3164 }
3165 fill.setAlphaF( hasDefaultFillOpacity ? defaultFillOpacity : newOpacity );
3166 mChangeColorButton->setColor( fill );
3167 }
3168 mChangeColorButton->setEnabled( hasFillParam );
3169 mChangeColorButton->setAllowOpacity( hasFillOpacityParam );
3170 if ( resetValues )
3171 {
3172 QColor stroke = mChangeStrokeColorButton->color();
3173 const double newOpacity = hasStrokeOpacityParam ? stroke.alphaF() : 1.0;
3174 if ( hasDefaultStrokeColor )
3175 {
3176 stroke = defaultStroke;
3177 }
3178 stroke.setAlphaF( hasDefaultStrokeOpacity ? defaultStrokeOpacity : newOpacity );
3179 mChangeStrokeColorButton->setColor( stroke );
3180 }
3181 mChangeStrokeColorButton->setEnabled( hasStrokeParam );
3182 mChangeStrokeColorButton->setAllowOpacity( hasStrokeOpacityParam );
3183 if ( hasDefaultStrokeWidth && resetValues )
3184 {
3185 mStrokeWidthSpinBox->setValue( defaultStrokeWidth );
3186 }
3187 mStrokeWidthSpinBox->setEnabled( hasStrokeWidthParam );
3188}
3189
3190void QgsSVGFillSymbolLayerWidget::mChangeColorButton_colorChanged( const QColor &color )
3191{
3192 if ( !mLayer )
3193 {
3194 return;
3195 }
3196
3197 mLayer->setSvgFillColor( color );
3198 emit changed();
3199}
3200
3201void QgsSVGFillSymbolLayerWidget::mChangeStrokeColorButton_colorChanged( const QColor &color )
3202{
3203 if ( !mLayer )
3204 {
3205 return;
3206 }
3207
3208 mLayer->setSvgStrokeColor( color );
3209 emit changed();
3210}
3211
3212void QgsSVGFillSymbolLayerWidget::mStrokeWidthSpinBox_valueChanged( double d )
3213{
3214 if ( mLayer )
3215 {
3216 mLayer->setSvgStrokeWidth( d );
3217 emit changed();
3218 }
3219}
3220
3221void QgsSVGFillSymbolLayerWidget::mTextureWidthUnitWidget_changed()
3222{
3223 if ( mLayer )
3224 {
3225 mLayer->setPatternWidthUnit( mTextureWidthUnitWidget->unit() );
3226 mLayer->setPatternWidthMapUnitScale( mTextureWidthUnitWidget->getMapUnitScale() );
3227 emit changed();
3228 }
3229}
3230
3231void QgsSVGFillSymbolLayerWidget::mSvgStrokeWidthUnitWidget_changed()
3232{
3233 if ( mLayer )
3234 {
3235 mLayer->setSvgStrokeWidthUnit( mSvgStrokeWidthUnitWidget->unit() );
3236 mLayer->setSvgStrokeWidthMapUnitScale( mSvgStrokeWidthUnitWidget->getMapUnitScale() );
3237 emit changed();
3238 }
3239}
3240
3242
3244 : QgsSymbolLayerWidget( parent, vl )
3245{
3246 setupUi( this );
3247 connect( mAngleSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsLinePatternFillSymbolLayerWidget::mAngleSpinBox_valueChanged );
3248 connect( mDistanceSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsLinePatternFillSymbolLayerWidget::mDistanceSpinBox_valueChanged );
3249 connect( mOffsetSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsLinePatternFillSymbolLayerWidget::mOffsetSpinBox_valueChanged );
3250 connect( mDistanceUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsLinePatternFillSymbolLayerWidget::mDistanceUnitWidget_changed );
3251 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsLinePatternFillSymbolLayerWidget::mOffsetUnitWidget_changed );
3252 mDistanceUnitWidget->setUnits(
3254 );
3255 mOffsetUnitWidget->setUnits(
3264 );
3265 mOffsetSpinBox->setClearValue( 0 );
3266 mAngleSpinBox->setClearValue( 0 );
3267
3268 mCoordinateReferenceComboBox->addItem( tr( "Align Pattern to Feature" ), static_cast<int>( Qgis::SymbolCoordinateReference::Feature ) );
3269 mCoordinateReferenceComboBox->addItem( tr( "Align Pattern to Map Extent" ), static_cast<int>( Qgis::SymbolCoordinateReference::Viewport ) );
3270 connect( mCoordinateReferenceComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this] {
3271 if ( mLayer )
3272 {
3273 mLayer->setCoordinateReference( static_cast<Qgis::SymbolCoordinateReference>( mCoordinateReferenceComboBox->currentData().toInt() ) );
3274 emit changed();
3275 }
3276 } );
3277
3278 mClipModeComboBox->addItem( tr( "Clip During Render Only" ), static_cast<int>( Qgis::LineClipMode::ClipPainterOnly ) );
3279 mClipModeComboBox->addItem( tr( "Clip Lines Before Render" ), static_cast<int>( Qgis::LineClipMode::ClipToIntersection ) );
3280 mClipModeComboBox->addItem( tr( "No Clipping" ), static_cast<int>( Qgis::LineClipMode::NoClipping ) );
3281 connect( mClipModeComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this] {
3282 if ( mLayer )
3283 {
3284 mLayer->setClipMode( static_cast<Qgis::LineClipMode>( mClipModeComboBox->currentData().toInt() ) );
3285 emit changed();
3286 }
3287 } );
3288}
3289
3291{
3292 if ( layer->layerType() != "LinePatternFill"_L1 )
3293 {
3294 return;
3295 }
3296
3297 QgsLinePatternFillSymbolLayer *patternLayer = static_cast<QgsLinePatternFillSymbolLayer *>( layer );
3298 if ( patternLayer )
3299 {
3300 mLayer = patternLayer;
3301 whileBlocking( mAngleSpinBox )->setValue( mLayer->lineAngle() );
3302 whileBlocking( mDistanceSpinBox )->setValue( mLayer->distance() );
3303 whileBlocking( mOffsetSpinBox )->setValue( mLayer->offset() );
3304
3305 //units
3306 mDistanceUnitWidget->blockSignals( true );
3307 mDistanceUnitWidget->setUnit( mLayer->distanceUnit() );
3308 mDistanceUnitWidget->setMapUnitScale( mLayer->distanceMapUnitScale() );
3309 mDistanceUnitWidget->blockSignals( false );
3310 mOffsetUnitWidget->blockSignals( true );
3311 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
3312 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
3313 mOffsetUnitWidget->blockSignals( false );
3314
3315 whileBlocking( mCoordinateReferenceComboBox )->setCurrentIndex( mCoordinateReferenceComboBox->findData( static_cast<int>( mLayer->coordinateReference() ) ) );
3316
3317 whileBlocking( mClipModeComboBox )->setCurrentIndex( mClipModeComboBox->findData( static_cast<int>( mLayer->clipMode() ) ) );
3318 }
3319
3324}
3325
3330
3331void QgsLinePatternFillSymbolLayerWidget::mAngleSpinBox_valueChanged( double d )
3332{
3333 if ( mLayer )
3334 {
3335 mLayer->setLineAngle( d );
3336 emit changed();
3337 }
3338}
3339
3340void QgsLinePatternFillSymbolLayerWidget::mDistanceSpinBox_valueChanged( double d )
3341{
3342 if ( mLayer )
3343 {
3344 mLayer->setDistance( d );
3345 emit changed();
3346 }
3347}
3348
3349void QgsLinePatternFillSymbolLayerWidget::mOffsetSpinBox_valueChanged( double d )
3350{
3351 if ( mLayer )
3352 {
3353 mLayer->setOffset( d );
3354 emit changed();
3355 }
3356}
3357
3358void QgsLinePatternFillSymbolLayerWidget::mDistanceUnitWidget_changed()
3359{
3360 if ( mLayer )
3361 {
3362 mLayer->setDistanceUnit( mDistanceUnitWidget->unit() );
3363 mLayer->setDistanceMapUnitScale( mDistanceUnitWidget->getMapUnitScale() );
3364 emit changed();
3365 }
3366}
3367
3368void QgsLinePatternFillSymbolLayerWidget::mOffsetUnitWidget_changed()
3369{
3370 if ( mLayer )
3371 {
3372 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
3373 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
3374 emit changed();
3375 }
3376}
3377
3379
3381 : QgsSymbolLayerWidget( parent, vl )
3382{
3383 setupUi( this );
3384 connect( mHorizontalDistanceSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsPointPatternFillSymbolLayerWidget::mHorizontalDistanceSpinBox_valueChanged );
3385 connect( mVerticalDistanceSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsPointPatternFillSymbolLayerWidget::mVerticalDistanceSpinBox_valueChanged );
3386 connect( mHorizontalDisplacementSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsPointPatternFillSymbolLayerWidget::mHorizontalDisplacementSpinBox_valueChanged );
3387 connect( mVerticalDisplacementSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsPointPatternFillSymbolLayerWidget::mVerticalDisplacementSpinBox_valueChanged );
3388 connect( mHorizontalOffsetSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsPointPatternFillSymbolLayerWidget::mHorizontalOffsetSpinBox_valueChanged );
3389 connect( mVerticalOffsetSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsPointPatternFillSymbolLayerWidget::mVerticalOffsetSpinBox_valueChanged );
3390 connect( mHorizontalDistanceUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointPatternFillSymbolLayerWidget::mHorizontalDistanceUnitWidget_changed );
3391 connect( mVerticalDistanceUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointPatternFillSymbolLayerWidget::mVerticalDistanceUnitWidget_changed );
3392 connect( mHorizontalDisplacementUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointPatternFillSymbolLayerWidget::mHorizontalDisplacementUnitWidget_changed );
3393 connect( mVerticalDisplacementUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointPatternFillSymbolLayerWidget::mVerticalDisplacementUnitWidget_changed );
3394 connect( mHorizontalOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointPatternFillSymbolLayerWidget::mHorizontalOffsetUnitWidget_changed );
3395 connect( mVerticalOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointPatternFillSymbolLayerWidget::mVerticalOffsetUnitWidget_changed );
3396 mHorizontalDistanceUnitWidget->setUnits(
3398 );
3399 mVerticalDistanceUnitWidget->setUnits(
3401 );
3402 mHorizontalDisplacementUnitWidget->setUnits(
3411 );
3412 mVerticalDisplacementUnitWidget->setUnits(
3421 );
3422 mHorizontalOffsetUnitWidget->setUnits(
3431 );
3432 mVerticalOffsetUnitWidget->setUnits(
3441 );
3442
3443 mClipModeComboBox->addItem( tr( "Clip to Shape" ), static_cast<int>( Qgis::MarkerClipMode::Shape ) );
3444 mClipModeComboBox->addItem( tr( "Marker Centroid Within Shape" ), static_cast<int>( Qgis::MarkerClipMode::CentroidWithin ) );
3445 mClipModeComboBox->addItem( tr( "Marker Completely Within Shape" ), static_cast<int>( Qgis::MarkerClipMode::CompletelyWithin ) );
3446 mClipModeComboBox->addItem( tr( "No Clipping" ), static_cast<int>( Qgis::MarkerClipMode::NoClipping ) );
3447 connect( mClipModeComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this] {
3448 if ( mLayer )
3449 {
3450 mLayer->setClipMode( static_cast<Qgis::MarkerClipMode>( mClipModeComboBox->currentData().toInt() ) );
3451 emit changed();
3452 }
3453 } );
3454
3455 mCoordinateReferenceComboBox->addItem( tr( "Align Pattern to Feature" ), static_cast<int>( Qgis::SymbolCoordinateReference::Feature ) );
3456 mCoordinateReferenceComboBox->addItem( tr( "Align Pattern to Map Extent" ), static_cast<int>( Qgis::SymbolCoordinateReference::Viewport ) );
3457 connect( mCoordinateReferenceComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this] {
3458 if ( mLayer )
3459 {
3460 mLayer->setCoordinateReference( static_cast<Qgis::SymbolCoordinateReference>( mCoordinateReferenceComboBox->currentData().toInt() ) );
3461 emit changed();
3462 }
3463 } );
3464
3465 mSeedSpinBox->setShowClearButton( true );
3466 mSeedSpinBox->setClearValue( 0 );
3467 mRandomXSpinBox->setClearValue( 0 );
3468 mRandomYSpinBox->setClearValue( 0 );
3469
3470 mRandomXOffsetUnitWidget->setUnits(
3479 );
3480 mRandomYOffsetUnitWidget->setUnits(
3489 );
3490 connect( mRandomXSpinBox, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double d ) {
3491 if ( mLayer )
3492 {
3493 mLayer->setMaximumRandomDeviationX( d );
3494 emit changed();
3495 }
3496 } );
3497 connect( mRandomYSpinBox, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double d ) {
3498 if ( mLayer )
3499 {
3500 mLayer->setMaximumRandomDeviationY( d );
3501 emit changed();
3502 }
3503 } );
3504 connect( mRandomXOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
3505 if ( mLayer )
3506 {
3507 mLayer->setRandomDeviationXUnit( mRandomXOffsetUnitWidget->unit() );
3508 mLayer->setRandomDeviationXMapUnitScale( mRandomXOffsetUnitWidget->getMapUnitScale() );
3509 emit changed();
3510 }
3511 } );
3512 connect( mRandomYOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
3513 if ( mLayer )
3514 {
3515 mLayer->setRandomDeviationYUnit( mRandomYOffsetUnitWidget->unit() );
3516 mLayer->setRandomDeviationYMapUnitScale( mRandomYOffsetUnitWidget->getMapUnitScale() );
3517 emit changed();
3518 }
3519 } );
3520 connect( mSeedSpinBox, qOverload<int>( &QSpinBox::valueChanged ), this, [this]( int v ) {
3521 if ( mLayer )
3522 {
3523 mLayer->setSeed( v );
3524 emit changed();
3525 }
3526 } );
3527
3528 mAngleSpinBox->setShowClearButton( true );
3529 mAngleSpinBox->setClearValue( 0 );
3530 connect( mAngleSpinBox, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double d ) {
3531 if ( mLayer )
3532 {
3533 mLayer->setAngle( d );
3534 emit changed();
3535 }
3536 } );
3537}
3538
3540{
3541 if ( !layer || layer->layerType() != "PointPatternFill"_L1 )
3542 {
3543 return;
3544 }
3545
3546 mLayer = static_cast<QgsPointPatternFillSymbolLayer *>( layer );
3547 whileBlocking( mHorizontalDistanceSpinBox )->setValue( mLayer->distanceX() );
3548 whileBlocking( mVerticalDistanceSpinBox )->setValue( mLayer->distanceY() );
3549 whileBlocking( mHorizontalDisplacementSpinBox )->setValue( mLayer->displacementX() );
3550 whileBlocking( mVerticalDisplacementSpinBox )->setValue( mLayer->displacementY() );
3551 whileBlocking( mHorizontalOffsetSpinBox )->setValue( mLayer->offsetX() );
3552 whileBlocking( mVerticalOffsetSpinBox )->setValue( mLayer->offsetY() );
3553 whileBlocking( mAngleSpinBox )->setValue( mLayer->angle() );
3554
3555 mHorizontalDistanceUnitWidget->blockSignals( true );
3556 mHorizontalDistanceUnitWidget->setUnit( mLayer->distanceXUnit() );
3557 mHorizontalDistanceUnitWidget->setMapUnitScale( mLayer->distanceXMapUnitScale() );
3558 mHorizontalDistanceUnitWidget->blockSignals( false );
3559 mVerticalDistanceUnitWidget->blockSignals( true );
3560 mVerticalDistanceUnitWidget->setUnit( mLayer->distanceYUnit() );
3561 mVerticalDistanceUnitWidget->setMapUnitScale( mLayer->distanceYMapUnitScale() );
3562 mVerticalDistanceUnitWidget->blockSignals( false );
3563 mHorizontalDisplacementUnitWidget->blockSignals( true );
3564 mHorizontalDisplacementUnitWidget->setUnit( mLayer->displacementXUnit() );
3565 mHorizontalDisplacementUnitWidget->setMapUnitScale( mLayer->displacementXMapUnitScale() );
3566 mHorizontalDisplacementUnitWidget->blockSignals( false );
3567 mVerticalDisplacementUnitWidget->blockSignals( true );
3568 mVerticalDisplacementUnitWidget->setUnit( mLayer->displacementYUnit() );
3569 mVerticalDisplacementUnitWidget->setMapUnitScale( mLayer->displacementYMapUnitScale() );
3570 mVerticalDisplacementUnitWidget->blockSignals( false );
3571 mHorizontalOffsetUnitWidget->blockSignals( true );
3572 mHorizontalOffsetUnitWidget->setUnit( mLayer->offsetXUnit() );
3573 mHorizontalOffsetUnitWidget->setMapUnitScale( mLayer->offsetXMapUnitScale() );
3574 mHorizontalOffsetUnitWidget->blockSignals( false );
3575 mVerticalOffsetUnitWidget->blockSignals( true );
3576 mVerticalOffsetUnitWidget->setUnit( mLayer->offsetYUnit() );
3577 mVerticalOffsetUnitWidget->setMapUnitScale( mLayer->offsetYMapUnitScale() );
3578 mVerticalOffsetUnitWidget->blockSignals( false );
3579
3580 whileBlocking( mClipModeComboBox )->setCurrentIndex( mClipModeComboBox->findData( static_cast<int>( mLayer->clipMode() ) ) );
3581 whileBlocking( mCoordinateReferenceComboBox )->setCurrentIndex( mCoordinateReferenceComboBox->findData( static_cast<int>( mLayer->coordinateReference() ) ) );
3582
3583 whileBlocking( mRandomXSpinBox )->setValue( mLayer->maximumRandomDeviationX() );
3584 whileBlocking( mRandomYSpinBox )->setValue( mLayer->maximumRandomDeviationY() );
3585 whileBlocking( mRandomXOffsetUnitWidget )->setUnit( mLayer->randomDeviationXUnit() );
3586 whileBlocking( mRandomXOffsetUnitWidget )->setMapUnitScale( mLayer->randomDeviationXMapUnitScale() );
3587 whileBlocking( mRandomYOffsetUnitWidget )->setUnit( mLayer->randomDeviationYUnit() );
3588 whileBlocking( mRandomYOffsetUnitWidget )->setMapUnitScale( mLayer->randomDeviationYMapUnitScale() );
3589 whileBlocking( mSeedSpinBox )->setValue( mLayer->seed() );
3590
3603}
3604
3609
3610void QgsPointPatternFillSymbolLayerWidget::mHorizontalDistanceSpinBox_valueChanged( double d )
3611{
3612 if ( mLayer )
3613 {
3614 mLayer->setDistanceX( d );
3615 emit changed();
3616 }
3617}
3618
3619void QgsPointPatternFillSymbolLayerWidget::mVerticalDistanceSpinBox_valueChanged( double d )
3620{
3621 if ( mLayer )
3622 {
3623 mLayer->setDistanceY( d );
3624 emit changed();
3625 }
3626}
3627
3628void QgsPointPatternFillSymbolLayerWidget::mHorizontalDisplacementSpinBox_valueChanged( double d )
3629{
3630 if ( mLayer )
3631 {
3632 mLayer->setDisplacementX( d );
3633 emit changed();
3634 }
3635}
3636
3637void QgsPointPatternFillSymbolLayerWidget::mVerticalDisplacementSpinBox_valueChanged( double d )
3638{
3639 if ( mLayer )
3640 {
3641 mLayer->setDisplacementY( d );
3642 emit changed();
3643 }
3644}
3645
3646void QgsPointPatternFillSymbolLayerWidget::mHorizontalOffsetSpinBox_valueChanged( double d )
3647{
3648 if ( mLayer )
3649 {
3650 mLayer->setOffsetX( d );
3651 emit changed();
3652 }
3653}
3654
3655void QgsPointPatternFillSymbolLayerWidget::mVerticalOffsetSpinBox_valueChanged( double d )
3656{
3657 if ( mLayer )
3658 {
3659 mLayer->setOffsetY( d );
3660 emit changed();
3661 }
3662}
3663
3664void QgsPointPatternFillSymbolLayerWidget::mHorizontalDistanceUnitWidget_changed()
3665{
3666 if ( mLayer )
3667 {
3668 mLayer->setDistanceXUnit( mHorizontalDistanceUnitWidget->unit() );
3669 mLayer->setDistanceXMapUnitScale( mHorizontalDistanceUnitWidget->getMapUnitScale() );
3670 emit changed();
3671 }
3672}
3673
3674void QgsPointPatternFillSymbolLayerWidget::mVerticalDistanceUnitWidget_changed()
3675{
3676 if ( mLayer )
3677 {
3678 mLayer->setDistanceYUnit( mVerticalDistanceUnitWidget->unit() );
3679 mLayer->setDistanceYMapUnitScale( mVerticalDistanceUnitWidget->getMapUnitScale() );
3680 emit changed();
3681 }
3682}
3683
3684void QgsPointPatternFillSymbolLayerWidget::mHorizontalDisplacementUnitWidget_changed()
3685{
3686 if ( mLayer )
3687 {
3688 mLayer->setDisplacementXUnit( mHorizontalDisplacementUnitWidget->unit() );
3689 mLayer->setDisplacementXMapUnitScale( mHorizontalDisplacementUnitWidget->getMapUnitScale() );
3690 emit changed();
3691 }
3692}
3693
3694void QgsPointPatternFillSymbolLayerWidget::mVerticalDisplacementUnitWidget_changed()
3695{
3696 if ( mLayer )
3697 {
3698 mLayer->setDisplacementYUnit( mVerticalDisplacementUnitWidget->unit() );
3699 mLayer->setDisplacementYMapUnitScale( mVerticalDisplacementUnitWidget->getMapUnitScale() );
3700 emit changed();
3701 }
3702}
3703
3704void QgsPointPatternFillSymbolLayerWidget::mHorizontalOffsetUnitWidget_changed()
3705{
3706 if ( mLayer )
3707 {
3708 mLayer->setOffsetXUnit( mHorizontalOffsetUnitWidget->unit() );
3709 mLayer->setOffsetXMapUnitScale( mHorizontalOffsetUnitWidget->getMapUnitScale() );
3710 emit changed();
3711 }
3712}
3713
3714void QgsPointPatternFillSymbolLayerWidget::mVerticalOffsetUnitWidget_changed()
3715{
3716 if ( mLayer )
3717 {
3718 mLayer->setOffsetYUnit( mVerticalOffsetUnitWidget->unit() );
3719 mLayer->setOffsetYMapUnitScale( mVerticalOffsetUnitWidget->getMapUnitScale() );
3720 emit changed();
3721 }
3722}
3723
3725
3727 : QgsSymbolLayerWidget( parent, vl )
3728{
3729 mLayer = nullptr;
3730
3731 setupUi( this );
3732
3733 mHorizontalAnchorComboBox->addItem( tr( "Left" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Left ) );
3734 mHorizontalAnchorComboBox->addItem( tr( "Horizontal Center" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Center ) );
3735 mHorizontalAnchorComboBox->addItem( tr( "Right" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Right ) );
3736
3737 mVerticalAnchorComboBox->addItem( tr( "Top" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Top ) );
3738 mVerticalAnchorComboBox->addItem( tr( "Vertical Center" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Center ) );
3739 mVerticalAnchorComboBox->addItem( tr( "Bottom on Baseline" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Baseline ) );
3740 mVerticalAnchorComboBox->addItem( tr( "Bottom" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Bottom ) );
3741
3742 connect( mSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsFontMarkerSymbolLayerWidget::mSizeUnitWidget_changed );
3743 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsFontMarkerSymbolLayerWidget::mOffsetUnitWidget_changed );
3744 connect( mStrokeWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsFontMarkerSymbolLayerWidget::mStrokeWidthUnitWidget_changed );
3745 connect( mStrokeWidthSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsFontMarkerSymbolLayerWidget::mStrokeWidthSpinBox_valueChanged );
3746 connect( mHorizontalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsFontMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged );
3747 connect( mVerticalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsFontMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged );
3748 mSizeUnitWidget->setUnits(
3750 );
3751 mStrokeWidthUnitWidget->setUnits(
3753 );
3754 mOffsetUnitWidget->setUnits(
3756 );
3757
3759 scrollArea->setWidget( widgetChar );
3760 scrollArea->setVerticalOnly( true );
3761
3762 btnColor->setAllowOpacity( true );
3763 btnColor->setColorDialogTitle( tr( "Select Symbol Fill Color" ) );
3764 btnColor->setContext( u"symbology"_s );
3765 btnStrokeColor->setAllowOpacity( true );
3766 btnStrokeColor->setColorDialogTitle( tr( "Select Symbol Stroke Color" ) );
3767 btnStrokeColor->setContext( u"symbology"_s );
3768
3769 mColorDDBtn->registerLinkedWidget( btnColor );
3770 mStrokeColorDDBtn->registerLinkedWidget( btnStrokeColor );
3771
3772 spinOffsetX->setClearValue( 0.0 );
3773 spinOffsetY->setClearValue( 0.0 );
3774 spinAngle->setClearValue( 0.0 );
3775
3776 //make a temporary symbol for the size assistant preview
3777 mAssistantPreviewSymbol = std::make_shared<QgsMarkerSymbol>();
3778
3779 if ( vectorLayer() )
3780 mSizeDDBtn->setSymbol( mAssistantPreviewSymbol );
3781
3782 connect( cboFont, &QFontComboBox::currentFontChanged, this, &QgsFontMarkerSymbolLayerWidget::setFontFamily );
3783 connect( mFontStyleComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsFontMarkerSymbolLayerWidget::mFontStyleComboBox_currentIndexChanged );
3784 connect( spinSize, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsFontMarkerSymbolLayerWidget::setSize );
3785 connect( cboJoinStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsFontMarkerSymbolLayerWidget::penJoinStyleChanged );
3788 connect( cboJoinStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsFontMarkerSymbolLayerWidget::penJoinStyleChanged );
3789 connect( spinAngle, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsFontMarkerSymbolLayerWidget::setAngle );
3790 connect( spinOffsetX, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsFontMarkerSymbolLayerWidget::setOffset );
3791 connect( spinOffsetY, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsFontMarkerSymbolLayerWidget::setOffset );
3793 connect( mCharLineEdit, &QLineEdit::textChanged, this, &QgsFontMarkerSymbolLayerWidget::setCharacterFromText );
3794
3795 connect( this, &QgsSymbolLayerWidget::changed, this, &QgsFontMarkerSymbolLayerWidget::updateAssistantSymbol );
3796}
3797
3799
3801{
3802 if ( layer->layerType() != "FontMarker"_L1 )
3803 return;
3804
3805 // layer type is correct, we can do the cast
3806 mLayer = static_cast<QgsFontMarkerSymbolLayer *>( layer );
3807
3808 QgsFontUtils::setFontFamily( mRefFont, mLayer->fontFamily() );
3809 mRefFont.setStyleName( QgsFontUtils::translateNamedStyle( mLayer->fontStyle() ) );
3810
3811 mFontStyleComboBox->blockSignals( true );
3812 populateFontStyleComboBox();
3813 mFontStyleComboBox->blockSignals( false );
3814
3815 // set values
3816 whileBlocking( cboFont )->setCurrentFont( mRefFont );
3817 whileBlocking( spinSize )->setValue( mLayer->size() );
3818 whileBlocking( btnColor )->setColor( mLayer->color() );
3819 whileBlocking( btnStrokeColor )->setColor( mLayer->strokeColor() );
3820 whileBlocking( mStrokeWidthSpinBox )->setValue( mLayer->strokeWidth() );
3821 whileBlocking( spinAngle )->setValue( mLayer->angle() );
3822
3823 widgetChar->blockSignals( true );
3824 widgetChar->setFont( mRefFont );
3825 if ( mLayer->character().length() == 1 )
3826 {
3827 widgetChar->setCharacter( mLayer->character().at( 0 ) );
3828 }
3829 widgetChar->blockSignals( false );
3830 whileBlocking( mCharLineEdit )->setText( mLayer->character() );
3831 mCharPreview->setFont( mRefFont );
3832
3833 //block
3834 whileBlocking( spinOffsetX )->setValue( mLayer->offset().x() );
3835 whileBlocking( spinOffsetY )->setValue( mLayer->offset().y() );
3836
3837 mSizeUnitWidget->blockSignals( true );
3838 mSizeUnitWidget->setUnit( mLayer->sizeUnit() );
3839 mSizeUnitWidget->setMapUnitScale( mLayer->sizeMapUnitScale() );
3840 mSizeUnitWidget->blockSignals( false );
3841
3842 mStrokeWidthUnitWidget->blockSignals( true );
3843 mStrokeWidthUnitWidget->setUnit( mLayer->strokeWidthUnit() );
3844 mStrokeWidthUnitWidget->setMapUnitScale( mLayer->strokeWidthMapUnitScale() );
3845 mStrokeWidthUnitWidget->blockSignals( false );
3846
3847 mOffsetUnitWidget->blockSignals( true );
3848 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
3849 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
3850 mOffsetUnitWidget->blockSignals( false );
3851
3852 whileBlocking( cboJoinStyle )->setPenJoinStyle( mLayer->penJoinStyle() );
3853
3854 //anchor points
3855 whileBlocking( mHorizontalAnchorComboBox )->setCurrentIndex( mHorizontalAnchorComboBox->findData( QVariant::fromValue( mLayer->horizontalAnchorPoint() ) ) );
3856 whileBlocking( mVerticalAnchorComboBox )->setCurrentIndex( mVerticalAnchorComboBox->findData( QVariant::fromValue( mLayer->verticalAnchorPoint() ) ) );
3857
3870
3871 updateAssistantSymbol();
3872}
3873
3878
3880{
3881 if ( mLayer )
3882 {
3883 mLayer->setFontFamily( font.family() );
3884 QgsFontUtils::setFontFamily( mRefFont, font.family() );
3885 widgetChar->setFont( mRefFont );
3886 mCharPreview->setFont( mRefFont );
3887 populateFontStyleComboBox();
3888 emit changed();
3889 }
3890}
3891
3892void QgsFontMarkerSymbolLayerWidget::setFontStyle( const QString &style )
3893{
3894 if ( mLayer )
3895 {
3896 QgsFontUtils::updateFontViaStyle( mRefFont, style );
3898 widgetChar->setFont( mRefFont );
3899 mCharPreview->setFont( mRefFont );
3900 emit changed();
3901 }
3902}
3903
3905{
3906 mLayer->setColor( color );
3907 emit changed();
3908}
3909
3911{
3912 mLayer->setStrokeColor( color );
3913 emit changed();
3914}
3915
3917{
3918 mLayer->setSize( size );
3919 //widgetChar->updateSize(size);
3920 emit changed();
3921}
3922
3924{
3925 mLayer->setAngle( angle );
3926 emit changed();
3927}
3928
3930{
3931 mCharPreview->setText( text );
3932
3933 if ( text.isEmpty() )
3934 return;
3935
3936 // take the last character of a string for a better experience when users cycle through several characters on their keyboard
3937 QString character = text;
3938 if ( text.contains( QRegularExpression( u"^0x[0-9a-fA-F]{1,4}$"_s ) ) )
3939 {
3940 bool ok = false;
3941 const unsigned int value = text.toUInt( &ok, 0 );
3942 if ( ok )
3943 {
3944 character = QChar( value );
3945 mCharPreview->setText( character );
3946 }
3947 }
3948
3949 if ( character != mLayer->character() )
3950 {
3951 mLayer->setCharacter( character );
3952 if ( mLayer->character().length() == 1 )
3953 {
3954 whileBlocking( widgetChar )->setCharacter( mLayer->character().at( 0 ) );
3955 }
3956 else
3957 {
3958 widgetChar->clearCharacter();
3959 }
3960 emit changed();
3961 }
3962}
3963
3965{
3966 if ( mLayer->character().length() > 1 || QGuiApplication::keyboardModifiers() & Qt::ControlModifier )
3967 {
3968 mCharLineEdit->insert( chr );
3969 return;
3970 }
3971
3972 mLayer->setCharacter( chr );
3973 whileBlocking( mCharLineEdit )->setText( chr );
3974 mCharPreview->setText( chr );
3975 emit changed();
3976}
3977
3978void QgsFontMarkerSymbolLayerWidget::setOffset()
3979{
3980 mLayer->setOffset( QPointF( spinOffsetX->value(), spinOffsetY->value() ) );
3981 emit changed();
3982}
3983
3984void QgsFontMarkerSymbolLayerWidget::penJoinStyleChanged()
3985{
3986 mLayer->setPenJoinStyle( cboJoinStyle->penJoinStyle() );
3987 emit changed();
3988}
3989
3990void QgsFontMarkerSymbolLayerWidget::mSizeUnitWidget_changed()
3991{
3992 if ( mLayer )
3993 {
3994 mLayer->setSizeUnit( mSizeUnitWidget->unit() );
3995 mLayer->setSizeMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
3996 emit changed();
3997 }
3998}
3999
4000void QgsFontMarkerSymbolLayerWidget::mOffsetUnitWidget_changed()
4001{
4002 if ( mLayer )
4003 {
4004 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
4005 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
4006 emit changed();
4007 }
4008}
4009
4010void QgsFontMarkerSymbolLayerWidget::mStrokeWidthUnitWidget_changed()
4011{
4012 if ( mLayer )
4013 {
4014 mLayer->setStrokeWidthUnit( mSizeUnitWidget->unit() );
4015 mLayer->setStrokeWidthMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
4016 emit changed();
4017 }
4018}
4019
4020void QgsFontMarkerSymbolLayerWidget::populateFontStyleComboBox()
4021{
4022 mFontStyleComboBox->clear();
4023 const QStringList styles = mFontDB.styles( mRefFont.family() );
4024 const auto constStyles = styles;
4025 for ( const QString &style : constStyles )
4026 {
4027 mFontStyleComboBox->addItem( style );
4028 }
4029
4030 QString targetStyle = mFontDB.styleString( mRefFont );
4031 if ( !styles.contains( targetStyle ) )
4032 {
4033 const QFont f = QgsFontUtils::createFont( mRefFont.family() );
4034 targetStyle = QFontInfo( f ).styleName();
4035 mRefFont.setStyleName( targetStyle );
4036 }
4037 int curIndx = 0;
4038 const int stylIndx = mFontStyleComboBox->findText( targetStyle );
4039 if ( stylIndx > -1 )
4040 {
4041 curIndx = stylIndx;
4042 }
4043
4044 mFontStyleComboBox->setCurrentIndex( curIndx );
4045}
4046
4047void QgsFontMarkerSymbolLayerWidget::mFontStyleComboBox_currentIndexChanged( int index )
4048{
4049 Q_UNUSED( index );
4050 setFontStyle( mFontStyleComboBox->currentText() );
4051}
4052
4053void QgsFontMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged( int )
4054{
4055 if ( mLayer )
4056 {
4057 mLayer->setHorizontalAnchorPoint( mHorizontalAnchorComboBox->currentData().value< Qgis::HorizontalAnchorPoint >() );
4058 emit changed();
4059 }
4060}
4061
4062void QgsFontMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged( int )
4063{
4064 if ( mLayer )
4065 {
4066 mLayer->setVerticalAnchorPoint( mVerticalAnchorComboBox->currentData().value< Qgis::VerticalAnchorPoint >() );
4067 emit changed();
4068 }
4069}
4070
4071void QgsFontMarkerSymbolLayerWidget::mStrokeWidthSpinBox_valueChanged( double d )
4072{
4073 if ( mLayer )
4074 {
4075 mLayer->setStrokeWidth( d );
4076 emit changed();
4077 }
4078}
4079
4080void QgsFontMarkerSymbolLayerWidget::updateAssistantSymbol()
4081{
4082 for ( int i = mAssistantPreviewSymbol->symbolLayerCount() - 1; i >= 0; --i )
4083 {
4084 mAssistantPreviewSymbol->deleteSymbolLayer( i );
4085 }
4086 mAssistantPreviewSymbol->appendSymbolLayer( mLayer->clone() );
4087 const QgsProperty ddSize = mLayer->dataDefinedProperties().property( QgsSymbolLayer::Property::Size );
4088 if ( ddSize )
4089 mAssistantPreviewSymbol->setDataDefinedSize( ddSize );
4090}
4091
4093
4094
4096 : QgsSymbolLayerWidget( parent, vl )
4097{
4098 mLayer = nullptr;
4099
4100 setupUi( this );
4101 connect( mDrawInsideCheckBox, &QCheckBox::stateChanged, this, &QgsCentroidFillSymbolLayerWidget::mDrawInsideCheckBox_stateChanged );
4102 connect( mDrawAllPartsCheckBox, &QCheckBox::stateChanged, this, &QgsCentroidFillSymbolLayerWidget::mDrawAllPartsCheckBox_stateChanged );
4103 connect( mClipPointsCheckBox, &QCheckBox::stateChanged, this, &QgsCentroidFillSymbolLayerWidget::mClipPointsCheckBox_stateChanged );
4104 connect( mClipOnCurrentPartOnlyCheckBox, &QCheckBox::stateChanged, this, &QgsCentroidFillSymbolLayerWidget::mClipOnCurrentPartOnlyCheckBox_stateChanged );
4105}
4106
4108{
4109 if ( layer->layerType() != "CentroidFill"_L1 )
4110 return;
4111
4112 // layer type is correct, we can do the cast
4113 mLayer = static_cast<QgsCentroidFillSymbolLayer *>( layer );
4114
4115 // set values
4116 whileBlocking( mDrawInsideCheckBox )->setChecked( mLayer->pointOnSurface() );
4117 whileBlocking( mDrawAllPartsCheckBox )->setChecked( mLayer->pointOnAllParts() );
4118 whileBlocking( mClipPointsCheckBox )->setChecked( mLayer->clipPoints() );
4119 whileBlocking( mClipOnCurrentPartOnlyCheckBox )->setChecked( mLayer->clipOnCurrentPartOnly() );
4120}
4121
4126
4127void QgsCentroidFillSymbolLayerWidget::mDrawInsideCheckBox_stateChanged( int state )
4128{
4129 mLayer->setPointOnSurface( state == Qt::Checked );
4130 emit changed();
4131}
4132
4133void QgsCentroidFillSymbolLayerWidget::mDrawAllPartsCheckBox_stateChanged( int state )
4134{
4135 mLayer->setPointOnAllParts( state == Qt::Checked );
4136 emit changed();
4137}
4138
4139void QgsCentroidFillSymbolLayerWidget::mClipPointsCheckBox_stateChanged( int state )
4140{
4141 mLayer->setClipPoints( state == Qt::Checked );
4142 emit changed();
4143}
4144
4145void QgsCentroidFillSymbolLayerWidget::mClipOnCurrentPartOnlyCheckBox_stateChanged( int state )
4146{
4147 mLayer->setClipOnCurrentPartOnly( state == Qt::Checked );
4148 emit changed();
4149}
4150
4152
4154 : QgsSymbolLayerWidget( parent, vl )
4155{
4156 mLayer = nullptr;
4157
4158 setupUi( this );
4159
4160 mHorizontalAnchorComboBox->addItem( tr( "Left" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Left ) );
4161 mHorizontalAnchorComboBox->addItem( tr( "Horizontal Center" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Center ) );
4162 mHorizontalAnchorComboBox->addItem( tr( "Right" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Right ) );
4163
4164 mVerticalAnchorComboBox->addItem( tr( "Top" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Top ) );
4165 mVerticalAnchorComboBox->addItem( tr( "Vertical Center" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Center ) );
4166 mVerticalAnchorComboBox->addItem( tr( "Bottom" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Bottom ) );
4167
4168 mImageSourceLineEdit->setLastPathSettingsKey( u"/UI/lastRasterMarkerImageDir"_s );
4169
4170 connect( mImageSourceLineEdit, &QgsImageSourceLineEdit::sourceChanged, this, &QgsRasterMarkerSymbolLayerWidget::imageSourceChanged );
4171 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsRasterMarkerSymbolLayerWidget::mOffsetUnitWidget_changed );
4172 connect( mRotationSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsRasterMarkerSymbolLayerWidget::setAngle );
4173 connect( mSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsRasterMarkerSymbolLayerWidget::mSizeUnitWidget_changed );
4174 connect( mWidthSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsRasterMarkerSymbolLayerWidget::setWidth );
4175 connect( mHeightSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsRasterMarkerSymbolLayerWidget::setHeight );
4176 connect( mLockAspectRatio, static_cast<void ( QgsRatioLockButton::* )( bool )>( &QgsRatioLockButton::lockChanged ), this, &QgsRasterMarkerSymbolLayerWidget::setLockAspectRatio );
4177
4178 mSizeUnitWidget->setUnits(
4187 );
4188 mOffsetUnitWidget->setUnits(
4190 );
4191
4192 mSpinOffsetX->setClearValue( 0.0 );
4193 mSpinOffsetY->setClearValue( 0.0 );
4194 mRotationSpinBox->setClearValue( 0.0 );
4195
4196 connect( mSpinOffsetX, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsRasterMarkerSymbolLayerWidget::setOffset );
4197 connect( mSpinOffsetY, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsRasterMarkerSymbolLayerWidget::setOffset );
4198 connect( mOpacityWidget, &QgsOpacityWidget::opacityChanged, this, &QgsRasterMarkerSymbolLayerWidget::setOpacity );
4199
4200 connect( mHorizontalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsRasterMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged );
4201 connect( mVerticalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsRasterMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged );
4202}
4203
4205{
4206 if ( !layer )
4207 {
4208 return;
4209 }
4210
4211 if ( layer->layerType() != "RasterMarker"_L1 )
4212 return;
4213
4214 // layer type is correct, we can do the cast
4215 mLayer = static_cast<QgsRasterMarkerSymbolLayer *>( layer );
4216
4217 // set values
4218 whileBlocking( mImageSourceLineEdit )->setSource( mLayer->path() );
4219
4220 whileBlocking( mWidthSpinBox )->setValue( mLayer->size() );
4221 const bool preservedAspectRatio = mLayer->preservedAspectRatio();
4222 mHeightSpinBox->blockSignals( true );
4223 if ( preservedAspectRatio )
4224 {
4225 mHeightSpinBox->setValue( mLayer->size() );
4226 }
4227 else
4228 {
4229 mHeightSpinBox->setValue( mLayer->size() * mLayer->fixedAspectRatio() );
4230 }
4231 mHeightSpinBox->setEnabled( mLayer->defaultAspectRatio() > 0.0 );
4232 mHeightSpinBox->blockSignals( false );
4233 whileBlocking( mLockAspectRatio )->setLocked( preservedAspectRatio );
4234
4235 whileBlocking( mRotationSpinBox )->setValue( mLayer->angle() );
4236 whileBlocking( mOpacityWidget )->setOpacity( mLayer->opacity() );
4237
4238 whileBlocking( mSpinOffsetX )->setValue( mLayer->offset().x() );
4239 whileBlocking( mSpinOffsetY )->setValue( mLayer->offset().y() );
4240
4241 mSizeUnitWidget->blockSignals( true );
4242 mSizeUnitWidget->setUnit( mLayer->sizeUnit() );
4243 mSizeUnitWidget->setMapUnitScale( mLayer->sizeMapUnitScale() );
4244 mSizeUnitWidget->blockSignals( false );
4245 mOffsetUnitWidget->blockSignals( true );
4246 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
4247 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
4248 mOffsetUnitWidget->blockSignals( false );
4249
4250 //anchor points
4251 whileBlocking( mHorizontalAnchorComboBox )->setCurrentIndex( mHorizontalAnchorComboBox->findData( QVariant::fromValue( mLayer->horizontalAnchorPoint() ) ) );
4252 whileBlocking( mVerticalAnchorComboBox )->setCurrentIndex( mVerticalAnchorComboBox->findData( QVariant::fromValue( mLayer->verticalAnchorPoint() ) ) );
4253
4262
4263 updatePreviewImage();
4264}
4265
4270
4272{
4274 mImageSourceLineEdit->setMessageBar( context.messageBar() );
4275}
4276
4277void QgsRasterMarkerSymbolLayerWidget::imageSourceChanged( const QString &text )
4278{
4279 mLayer->setPath( text );
4280 updatePreviewImage();
4281 emit changed();
4282}
4283
4284void QgsRasterMarkerSymbolLayerWidget::updatePreviewImage()
4285{
4286 bool fitsInCache = false;
4287 const QImage image = QgsApplication::imageCache()->pathAsImage( mLayer->path(), QSize( 150, 150 ), true, 1.0, fitsInCache );
4288 if ( image.isNull() )
4289 {
4290 mLabelImagePreview->setPixmap( QPixmap() );
4291 return;
4292 }
4293
4294 QImage previewImage( 150, 150, QImage::Format_ARGB32 );
4295 previewImage.fill( Qt::transparent );
4296 const QRect imageRect( ( 150 - image.width() ) / 2.0, ( 150 - image.height() ) / 2.0, image.width(), image.height() );
4297 QPainter p;
4298 p.begin( &previewImage );
4299 //draw a checkerboard background
4300 uchar pixDataRGB[] = { 150, 150, 150, 150, 100, 100, 100, 150, 100, 100, 100, 150, 150, 150, 150, 150 };
4301 const QImage img( pixDataRGB, 2, 2, 8, QImage::Format_ARGB32 );
4302 const QPixmap pix = QPixmap::fromImage( img.scaled( 8, 8 ) );
4303 QBrush checkerBrush;
4304 checkerBrush.setTexture( pix );
4305 p.fillRect( imageRect, checkerBrush );
4306
4307 if ( mLayer->opacity() < 1.0 )
4308 {
4309 p.setOpacity( mLayer->opacity() );
4310 }
4311
4312 p.drawImage( imageRect.left(), imageRect.top(), image );
4313 p.end();
4314 mLabelImagePreview->setPixmap( QPixmap::fromImage( previewImage ) );
4315}
4316
4317void QgsRasterMarkerSymbolLayerWidget::setWidth()
4318{
4319 const double defaultAspectRatio = mLayer->defaultAspectRatio();
4320 double fixedAspectRatio = 0.0;
4321 mHeightSpinBox->blockSignals( true );
4322 if ( defaultAspectRatio <= 0.0 )
4323 {
4324 mHeightSpinBox->setValue( mWidthSpinBox->value() );
4325 }
4326 else if ( mLockAspectRatio->locked() )
4327 {
4328 mHeightSpinBox->setValue( mWidthSpinBox->value() * defaultAspectRatio );
4329 }
4330 else
4331 {
4332 fixedAspectRatio = mHeightSpinBox->value() / mWidthSpinBox->value();
4333 }
4334 mHeightSpinBox->blockSignals( false );
4335 mLayer->setSize( mWidthSpinBox->value() );
4336 mLayer->setFixedAspectRatio( fixedAspectRatio );
4337 emit changed();
4338}
4339
4340void QgsRasterMarkerSymbolLayerWidget::setHeight()
4341{
4342 const double defaultAspectRatio = mLayer->defaultAspectRatio();
4343 double fixedAspectRatio = 0.0;
4344 mWidthSpinBox->blockSignals( true );
4345 if ( defaultAspectRatio <= 0.0 )
4346 {
4347 mWidthSpinBox->setValue( mHeightSpinBox->value() );
4348 }
4349 else if ( mLockAspectRatio->locked() )
4350 {
4351 mWidthSpinBox->setValue( mHeightSpinBox->value() / defaultAspectRatio );
4352 }
4353 else
4354 {
4355 fixedAspectRatio = mHeightSpinBox->value() / mWidthSpinBox->value();
4356 }
4357 mWidthSpinBox->blockSignals( false );
4358 mLayer->setSize( mWidthSpinBox->value() );
4359 mLayer->setFixedAspectRatio( fixedAspectRatio );
4360 emit changed();
4361}
4362
4363void QgsRasterMarkerSymbolLayerWidget::setLockAspectRatio( const bool locked )
4364{
4365 const double defaultAspectRatio = mLayer->defaultAspectRatio();
4366 if ( defaultAspectRatio <= 0.0 )
4367 {
4368 whileBlocking( mLockAspectRatio )->setLocked( true );
4369 }
4370 else if ( locked )
4371 {
4372 mLayer->setFixedAspectRatio( 0.0 );
4373 setWidth();
4374 }
4375 else
4376 {
4377 mLayer->setFixedAspectRatio( mHeightSpinBox->value() / mWidthSpinBox->value() );
4378 }
4379}
4380
4381void QgsRasterMarkerSymbolLayerWidget::setAngle()
4382{
4383 mLayer->setAngle( mRotationSpinBox->value() );
4384 emit changed();
4385}
4386
4387void QgsRasterMarkerSymbolLayerWidget::setOpacity( double value )
4388{
4389 mLayer->setOpacity( value );
4390 emit changed();
4391 updatePreviewImage();
4392}
4393
4394void QgsRasterMarkerSymbolLayerWidget::setOffset()
4395{
4396 mLayer->setOffset( QPointF( mSpinOffsetX->value(), mSpinOffsetY->value() ) );
4397 emit changed();
4398}
4399
4400void QgsRasterMarkerSymbolLayerWidget::mSizeUnitWidget_changed()
4401{
4402 if ( mLayer )
4403 {
4404 mLayer->setSizeUnit( mSizeUnitWidget->unit() );
4405 mLayer->setSizeMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
4406 emit changed();
4407 }
4408}
4409
4410void QgsRasterMarkerSymbolLayerWidget::mOffsetUnitWidget_changed()
4411{
4412 if ( mLayer )
4413 {
4414 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
4415 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
4416 emit changed();
4417 }
4418}
4419
4420void QgsRasterMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged( int )
4421{
4422 if ( mLayer )
4423 {
4424 mLayer->setHorizontalAnchorPoint( mHorizontalAnchorComboBox->currentData().value< Qgis::HorizontalAnchorPoint >() );
4425 emit changed();
4426 }
4427}
4428
4429void QgsRasterMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged( int )
4430{
4431 if ( mLayer )
4432 {
4433 mLayer->setVerticalAnchorPoint( mVerticalAnchorComboBox->currentData().value< Qgis::VerticalAnchorPoint >() );
4434 emit changed();
4435 }
4436}
4437
4438
4440
4442 : QgsSymbolLayerWidget( parent, vl )
4443{
4444 mLayer = nullptr;
4445
4446 setupUi( this );
4447
4448 mHorizontalAnchorComboBox->addItem( tr( "Left" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Left ) );
4449 mHorizontalAnchorComboBox->addItem( tr( "Horizontal Center" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Center ) );
4450 mHorizontalAnchorComboBox->addItem( tr( "Right" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Right ) );
4451
4452 mVerticalAnchorComboBox->addItem( tr( "Top" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Top ) );
4453 mVerticalAnchorComboBox->addItem( tr( "Vertical Center" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Center ) );
4454 mVerticalAnchorComboBox->addItem( tr( "Bottom" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Bottom ) );
4455
4456 mImageSourceLineEdit->setLastPathSettingsKey( u"/UI/lastAnimatedMarkerImageDir"_s );
4457
4458 connect( mImageSourceLineEdit, &QgsImageSourceLineEdit::sourceChanged, this, &QgsAnimatedMarkerSymbolLayerWidget::imageSourceChanged );
4459 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsAnimatedMarkerSymbolLayerWidget::mOffsetUnitWidget_changed );
4460 connect( mRotationSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsAnimatedMarkerSymbolLayerWidget::setAngle );
4461 connect( mSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsAnimatedMarkerSymbolLayerWidget::mSizeUnitWidget_changed );
4462 connect( mWidthSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsAnimatedMarkerSymbolLayerWidget::setWidth );
4463 connect( mHeightSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsAnimatedMarkerSymbolLayerWidget::setHeight );
4464 connect( mLockAspectRatio, static_cast<void ( QgsRatioLockButton::* )( bool )>( &QgsRatioLockButton::lockChanged ), this, &QgsAnimatedMarkerSymbolLayerWidget::setLockAspectRatio );
4465
4466 mFrameRateSpin->setClearValue( 10 );
4467 mFrameRateSpin->setShowClearButton( true );
4468 connect( mFrameRateSpin, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double value ) {
4469 mLayer->setFrameRate( value );
4470 emit changed();
4471 } );
4472
4473 mSizeUnitWidget->setUnits(
4482 );
4483 mOffsetUnitWidget->setUnits(
4485 );
4486
4487 mSpinOffsetX->setClearValue( 0.0 );
4488 mSpinOffsetY->setClearValue( 0.0 );
4489 mRotationSpinBox->setClearValue( 0.0 );
4490
4491 connect( mSpinOffsetX, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsAnimatedMarkerSymbolLayerWidget::setOffset );
4492 connect( mSpinOffsetY, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsAnimatedMarkerSymbolLayerWidget::setOffset );
4493 connect( mOpacityWidget, &QgsOpacityWidget::opacityChanged, this, &QgsAnimatedMarkerSymbolLayerWidget::setOpacity );
4494
4495 connect( mHorizontalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsAnimatedMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged );
4496 connect( mVerticalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsAnimatedMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged );
4497}
4498
4500{
4501 if ( !layer )
4502 {
4503 return;
4504 }
4505
4506 if ( layer->layerType() != "AnimatedMarker"_L1 )
4507 return;
4508
4509 // layer type is correct, we can do the cast
4510 mLayer = static_cast<QgsAnimatedMarkerSymbolLayer *>( layer );
4511
4512 // set values
4513 whileBlocking( mImageSourceLineEdit )->setSource( mLayer->path() );
4514
4515 const double firstFrameTime = QgsApplication::imageCache()->nextFrameDelay( mLayer->path() );
4516 if ( firstFrameTime > 0 )
4517 {
4518 mFrameRateSpin->setClearValue( 1000 / firstFrameTime );
4519 }
4520 else
4521 {
4522 mFrameRateSpin->setClearValue( 10 );
4523 }
4524
4525 whileBlocking( mWidthSpinBox )->setValue( mLayer->size() );
4526 const bool preservedAspectRatio = mLayer->preservedAspectRatio();
4527 mHeightSpinBox->blockSignals( true );
4528 if ( preservedAspectRatio )
4529 {
4530 mHeightSpinBox->setValue( mLayer->size() );
4531 }
4532 else
4533 {
4534 mHeightSpinBox->setValue( mLayer->size() * mLayer->fixedAspectRatio() );
4535 }
4536 mHeightSpinBox->setEnabled( mLayer->defaultAspectRatio() > 0.0 );
4537 mHeightSpinBox->blockSignals( false );
4538 whileBlocking( mLockAspectRatio )->setLocked( preservedAspectRatio );
4539
4540 whileBlocking( mRotationSpinBox )->setValue( mLayer->angle() );
4541 whileBlocking( mOpacityWidget )->setOpacity( mLayer->opacity() );
4542
4543 whileBlocking( mSpinOffsetX )->setValue( mLayer->offset().x() );
4544 whileBlocking( mSpinOffsetY )->setValue( mLayer->offset().y() );
4545
4546 whileBlocking( mFrameRateSpin )->setValue( mLayer->frameRate() );
4547
4548 mSizeUnitWidget->blockSignals( true );
4549 mSizeUnitWidget->setUnit( mLayer->sizeUnit() );
4550 mSizeUnitWidget->setMapUnitScale( mLayer->sizeMapUnitScale() );
4551 mSizeUnitWidget->blockSignals( false );
4552 mOffsetUnitWidget->blockSignals( true );
4553 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
4554 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
4555 mOffsetUnitWidget->blockSignals( false );
4556
4557 //anchor points
4558 whileBlocking( mHorizontalAnchorComboBox )->setCurrentIndex( mHorizontalAnchorComboBox->findData( QVariant::fromValue( mLayer->horizontalAnchorPoint() ) ) );
4559 whileBlocking( mVerticalAnchorComboBox )->setCurrentIndex( mVerticalAnchorComboBox->findData( QVariant::fromValue( mLayer->verticalAnchorPoint() ) ) );
4560
4569
4570 updatePreviewImage();
4571}
4572
4577
4579{
4581 mImageSourceLineEdit->setMessageBar( context.messageBar() );
4582}
4583
4584void QgsAnimatedMarkerSymbolLayerWidget::imageSourceChanged( const QString &text )
4585{
4586 mLayer->setPath( text );
4587
4588 const double firstFrameTime = QgsApplication::imageCache()->nextFrameDelay( text );
4589 if ( firstFrameTime > 0 )
4590 {
4591 mFrameRateSpin->setClearValue( 1000 / firstFrameTime );
4592 }
4593 else
4594 {
4595 mFrameRateSpin->setClearValue( 10 );
4596 }
4597 updatePreviewImage();
4598 emit changed();
4599}
4600
4601void QgsAnimatedMarkerSymbolLayerWidget::updatePreviewImage()
4602{
4603 if ( mPreviewMovie )
4604 {
4605 mLabelImagePreview->setMovie( nullptr );
4606 mPreviewMovie->deleteLater();
4607 mPreviewMovie = nullptr;
4608 }
4609
4610 mPreviewMovie = new QMovie( mLayer->path(), QByteArray(), this );
4611 mPreviewMovie->setScaledSize( QSize( 150, 150 ) );
4612 mLabelImagePreview->setMovie( mPreviewMovie );
4613 mPreviewMovie->start();
4614}
4615
4616void QgsAnimatedMarkerSymbolLayerWidget::setWidth()
4617{
4618 const double defaultAspectRatio = mLayer->defaultAspectRatio();
4619 double fixedAspectRatio = 0.0;
4620 mHeightSpinBox->blockSignals( true );
4621 if ( defaultAspectRatio <= 0.0 )
4622 {
4623 mHeightSpinBox->setValue( mWidthSpinBox->value() );
4624 }
4625 else if ( mLockAspectRatio->locked() )
4626 {
4627 mHeightSpinBox->setValue( mWidthSpinBox->value() * defaultAspectRatio );
4628 }
4629 else
4630 {
4631 fixedAspectRatio = mHeightSpinBox->value() / mWidthSpinBox->value();
4632 }
4633 mHeightSpinBox->blockSignals( false );
4634 mLayer->setSize( mWidthSpinBox->value() );
4635 mLayer->setFixedAspectRatio( fixedAspectRatio );
4636 emit changed();
4637}
4638
4639void QgsAnimatedMarkerSymbolLayerWidget::setHeight()
4640{
4641 const double defaultAspectRatio = mLayer->defaultAspectRatio();
4642 double fixedAspectRatio = 0.0;
4643 mWidthSpinBox->blockSignals( true );
4644 if ( defaultAspectRatio <= 0.0 )
4645 {
4646 mWidthSpinBox->setValue( mHeightSpinBox->value() );
4647 }
4648 else if ( mLockAspectRatio->locked() )
4649 {
4650 mWidthSpinBox->setValue( mHeightSpinBox->value() / defaultAspectRatio );
4651 }
4652 else
4653 {
4654 fixedAspectRatio = mHeightSpinBox->value() / mWidthSpinBox->value();
4655 }
4656 mWidthSpinBox->blockSignals( false );
4657 mLayer->setSize( mWidthSpinBox->value() );
4658 mLayer->setFixedAspectRatio( fixedAspectRatio );
4659 emit changed();
4660}
4661
4662void QgsAnimatedMarkerSymbolLayerWidget::setLockAspectRatio( const bool locked )
4663{
4664 const double defaultAspectRatio = mLayer->defaultAspectRatio();
4665 if ( defaultAspectRatio <= 0.0 )
4666 {
4667 whileBlocking( mLockAspectRatio )->setLocked( true );
4668 }
4669 else if ( locked )
4670 {
4671 mLayer->setFixedAspectRatio( 0.0 );
4672 setWidth();
4673 }
4674 else
4675 {
4676 mLayer->setFixedAspectRatio( mHeightSpinBox->value() / mWidthSpinBox->value() );
4677 }
4678}
4679
4680void QgsAnimatedMarkerSymbolLayerWidget::setAngle()
4681{
4682 mLayer->setAngle( mRotationSpinBox->value() );
4683 emit changed();
4684}
4685
4686void QgsAnimatedMarkerSymbolLayerWidget::setOpacity( double value )
4687{
4688 mLayer->setOpacity( value );
4689 emit changed();
4690 updatePreviewImage();
4691}
4692
4693void QgsAnimatedMarkerSymbolLayerWidget::setOffset()
4694{
4695 mLayer->setOffset( QPointF( mSpinOffsetX->value(), mSpinOffsetY->value() ) );
4696 emit changed();
4697}
4698
4699void QgsAnimatedMarkerSymbolLayerWidget::mSizeUnitWidget_changed()
4700{
4701 if ( mLayer )
4702 {
4703 mLayer->setSizeUnit( mSizeUnitWidget->unit() );
4704 mLayer->setSizeMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
4705 emit changed();
4706 }
4707}
4708
4709void QgsAnimatedMarkerSymbolLayerWidget::mOffsetUnitWidget_changed()
4710{
4711 if ( mLayer )
4712 {
4713 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
4714 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
4715 emit changed();
4716 }
4717}
4718
4719void QgsAnimatedMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged( int )
4720{
4721 if ( mLayer )
4722 {
4723 mLayer->setHorizontalAnchorPoint( mHorizontalAnchorComboBox->currentData().value< Qgis::HorizontalAnchorPoint >() );
4724 emit changed();
4725 }
4726}
4727
4728void QgsAnimatedMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged( int )
4729{
4730 if ( mLayer )
4731 {
4732 mLayer->setVerticalAnchorPoint( mVerticalAnchorComboBox->currentData().value< Qgis::VerticalAnchorPoint >() );
4733 emit changed();
4734 }
4735}
4736
4738
4740 : QgsSymbolLayerWidget( parent, vl )
4741{
4742 mLayer = nullptr;
4743 setupUi( this );
4744
4745 mImageSourceLineEdit->setLastPathSettingsKey( u"/UI/lastRasterMarkerImageDir"_s );
4746 connect( mImageSourceLineEdit, &QgsImageSourceLineEdit::sourceChanged, this, &QgsRasterFillSymbolLayerWidget::imageSourceChanged );
4747
4748 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsRasterFillSymbolLayerWidget::mOffsetUnitWidget_changed );
4749 connect( mRotationSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsRasterFillSymbolLayerWidget::mRotationSpinBox_valueChanged );
4750
4751 connect( mSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
4752 if ( !mLayer )
4753 {
4754 return;
4755 }
4756 mLayer->setSizeUnit( mSizeUnitWidget->unit() );
4757 mLayer->setSizeMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
4758 emit changed();
4759 } );
4760 connect( mWidthSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, [this]( double d ) {
4761 if ( !mLayer )
4762 {
4763 return;
4764 }
4765 mLayer->setWidth( d );
4766 emit changed();
4767 } );
4768
4769 connect( mHeightSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, [this]( double d ) {
4770 if ( !mLayer )
4771 {
4772 return;
4773 }
4774 mLayer->setHeight( d );
4775 emit changed();
4776 } );
4777
4778 mSizeUnitWidget->setUnits(
4787 );
4788 mOffsetUnitWidget->setUnits(
4790 );
4791
4792 mSpinOffsetX->setClearValue( 0.0 );
4793 mSpinOffsetY->setClearValue( 0.0 );
4794 mRotationSpinBox->setClearValue( 0.0 );
4795
4796 connect( cboCoordinateMode, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsRasterFillSymbolLayerWidget::setCoordinateMode );
4797 connect( mSpinOffsetX, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsRasterFillSymbolLayerWidget::offsetChanged );
4798 connect( mSpinOffsetY, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsRasterFillSymbolLayerWidget::offsetChanged );
4799 connect( mOpacityWidget, &QgsOpacityWidget::opacityChanged, this, &QgsRasterFillSymbolLayerWidget::opacityChanged );
4800}
4801
4802
4804{
4805 if ( !layer )
4806 {
4807 return;
4808 }
4809
4810 if ( layer->layerType() != "RasterFill"_L1 )
4811 {
4812 return;
4813 }
4814
4815 mLayer = dynamic_cast<QgsRasterFillSymbolLayer *>( layer );
4816 if ( !mLayer )
4817 {
4818 return;
4819 }
4820
4821 whileBlocking( mImageSourceLineEdit )->setSource( mLayer->imageFilePath() );
4822
4823 cboCoordinateMode->blockSignals( true );
4824 switch ( mLayer->coordinateMode() )
4825 {
4827 cboCoordinateMode->setCurrentIndex( 1 );
4828 break;
4830 default:
4831 cboCoordinateMode->setCurrentIndex( 0 );
4832 break;
4833 }
4834 cboCoordinateMode->blockSignals( false );
4835 whileBlocking( mOpacityWidget )->setOpacity( mLayer->opacity() );
4836 whileBlocking( mRotationSpinBox )->setValue( mLayer->angle() );
4837
4838 whileBlocking( mSpinOffsetX )->setValue( mLayer->offset().x() );
4839 whileBlocking( mSpinOffsetY )->setValue( mLayer->offset().y() );
4840 mOffsetUnitWidget->blockSignals( true );
4841 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
4842 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
4843 mOffsetUnitWidget->blockSignals( false );
4844
4845 whileBlocking( mWidthSpinBox )->setValue( mLayer->width() );
4846 mSizeUnitWidget->blockSignals( true );
4847 mSizeUnitWidget->setUnit( mLayer->sizeUnit() );
4848 mSizeUnitWidget->setMapUnitScale( mLayer->sizeMapUnitScale() );
4849 mSizeUnitWidget->blockSignals( false );
4850
4851 whileBlocking( mHeightSpinBox )->setValue( mLayer->height() );
4852
4853 updatePreviewImage();
4854
4861}
4862
4867
4868void QgsRasterFillSymbolLayerWidget::imageSourceChanged( const QString &text )
4869{
4870 mLayer->setImageFilePath( text );
4871 updatePreviewImage();
4872 emit changed();
4873}
4874
4875void QgsRasterFillSymbolLayerWidget::setCoordinateMode( int index )
4876{
4877 switch ( index )
4878 {
4879 case 0:
4880 //feature coordinate mode
4882 break;
4883 case 1:
4884 //viewport coordinate mode
4886 break;
4887 }
4888
4889 emit changed();
4890}
4891
4892void QgsRasterFillSymbolLayerWidget::opacityChanged( double value )
4893{
4894 if ( !mLayer )
4895 {
4896 return;
4897 }
4898
4899 mLayer->setOpacity( value );
4900 emit changed();
4901 updatePreviewImage();
4902}
4903
4904void QgsRasterFillSymbolLayerWidget::offsetChanged()
4905{
4906 mLayer->setOffset( QPointF( mSpinOffsetX->value(), mSpinOffsetY->value() ) );
4907 emit changed();
4908}
4909
4910void QgsRasterFillSymbolLayerWidget::mOffsetUnitWidget_changed()
4911{
4912 if ( !mLayer )
4913 {
4914 return;
4915 }
4916 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
4917 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
4918 emit changed();
4919}
4920
4921void QgsRasterFillSymbolLayerWidget::mRotationSpinBox_valueChanged( double d )
4922{
4923 if ( mLayer )
4924 {
4925 mLayer->setAngle( d );
4926 emit changed();
4927 }
4928}
4929
4930void QgsRasterFillSymbolLayerWidget::updatePreviewImage()
4931{
4932 bool fitsInCache = false;
4933 const QImage image = QgsApplication::imageCache()->pathAsImage( mLayer->imageFilePath(), QSize( 150, 150 ), true, 1.0, fitsInCache );
4934 if ( image.isNull() )
4935 {
4936 mLabelImagePreview->setPixmap( QPixmap() );
4937 return;
4938 }
4939
4940 QImage previewImage( 150, 150, QImage::Format_ARGB32 );
4941 previewImage.fill( Qt::transparent );
4942 const QRect imageRect( ( 150 - image.width() ) / 2.0, ( 150 - image.height() ) / 2.0, image.width(), image.height() );
4943 QPainter p;
4944 p.begin( &previewImage );
4945 //draw a checkerboard background
4946 uchar pixDataRGB[] = { 150, 150, 150, 150, 100, 100, 100, 150, 100, 100, 100, 150, 150, 150, 150, 150 };
4947 const QImage img( pixDataRGB, 2, 2, 8, QImage::Format_ARGB32 );
4948 const QPixmap pix = QPixmap::fromImage( img.scaled( 8, 8 ) );
4949 QBrush checkerBrush;
4950 checkerBrush.setTexture( pix );
4951 p.fillRect( imageRect, checkerBrush );
4952
4953 if ( mLayer->opacity() < 1.0 )
4954 {
4955 p.setOpacity( mLayer->opacity() );
4956 }
4957
4958 p.drawImage( imageRect.left(), imageRect.top(), image );
4959 p.end();
4960 mLabelImagePreview->setPixmap( QPixmap::fromImage( previewImage ) );
4961}
4962
4963//
4964// QgsRasterLineSymbolLayerWidget
4965//
4966
4967
4969 : QgsSymbolLayerWidget( parent, vl )
4970{
4971 mLayer = nullptr;
4972 setupUi( this );
4973
4974 mImageSourceLineEdit->setLastPathSettingsKey( u"/UI/lastRasterMarkerImageDir"_s );
4975
4976 mPenWidthUnitWidget->setUnits(
4978 );
4979 mOffsetUnitWidget->setUnits(
4981 );
4982
4983 connect( mPenWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
4984 if ( mLayer )
4985 {
4986 mLayer->setWidthUnit( mPenWidthUnitWidget->unit() );
4987 mLayer->setWidthMapUnitScale( mPenWidthUnitWidget->getMapUnitScale() );
4988 emit changed();
4989 }
4990 } );
4991
4992 connect( spinWidth, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this] {
4993 if ( mLayer )
4994 {
4995 mLayer->setWidth( spinWidth->value() );
4996 emit changed();
4997 }
4998 } );
4999
5000 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
5001 if ( mLayer )
5002 {
5003 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
5004 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
5005 emit changed();
5006 }
5007 } );
5008
5009
5010 spinOffset->setClearValue( 0.0 );
5011 connect( spinOffset, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double val ) {
5012 if ( mLayer )
5013 {
5014 mLayer->setOffset( val );
5015 emit changed();
5016 }
5017 } );
5018
5019 connect( cboCapStyle, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this] {
5020 if ( mLayer )
5021 {
5022 mLayer->setPenCapStyle( cboCapStyle->penCapStyle() );
5023 emit changed();
5024 }
5025 } );
5026 connect( cboJoinStyle, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this] {
5027 if ( mLayer )
5028 {
5029 mLayer->setPenJoinStyle( cboJoinStyle->penJoinStyle() );
5030 emit changed();
5031 }
5032 } );
5033
5034 connect( mImageSourceLineEdit, &QgsImageSourceLineEdit::sourceChanged, this, &QgsRasterLineSymbolLayerWidget::imageSourceChanged );
5035 connect( mOpacityWidget, &QgsOpacityWidget::opacityChanged, this, [this]( double opacity ) {
5036 if ( mLayer )
5037 {
5038 mLayer->setOpacity( opacity );
5039 updatePreviewImage();
5040 emit changed();
5041 }
5042 } );
5043}
5044
5046{
5047 if ( !layer )
5048 {
5049 return;
5050 }
5051
5052 if ( layer->layerType() != "RasterLine"_L1 )
5053 {
5054 return;
5055 }
5056
5057 mLayer = dynamic_cast<QgsRasterLineSymbolLayer *>( layer );
5058 if ( !mLayer )
5059 {
5060 return;
5061 }
5062
5063 whileBlocking( mImageSourceLineEdit )->setSource( mLayer->path() );
5064 whileBlocking( mOpacityWidget )->setOpacity( mLayer->opacity() );
5065
5066 whileBlocking( spinWidth )->setValue( mLayer->width() );
5067 whileBlocking( mPenWidthUnitWidget )->setUnit( mLayer->widthUnit() );
5068 whileBlocking( mPenWidthUnitWidget )->setMapUnitScale( mLayer->widthMapUnitScale() );
5069 whileBlocking( cboJoinStyle )->setPenJoinStyle( mLayer->penJoinStyle() );
5070 whileBlocking( cboCapStyle )->setPenCapStyle( mLayer->penCapStyle() );
5071
5072 whileBlocking( mOffsetUnitWidget )->setUnit( mLayer->offsetUnit() );
5073 whileBlocking( mOffsetUnitWidget )->setMapUnitScale( mLayer->offsetMapUnitScale() );
5074 whileBlocking( spinOffset )->setValue( mLayer->offset() );
5075
5076 updatePreviewImage();
5077
5084}
5085
5090
5091void QgsRasterLineSymbolLayerWidget::imageSourceChanged( const QString &text )
5092{
5093 mLayer->setPath( text );
5094 updatePreviewImage();
5095 emit changed();
5096}
5097
5098void QgsRasterLineSymbolLayerWidget::updatePreviewImage()
5099{
5100 bool fitsInCache = false;
5101 const QImage image = QgsApplication::imageCache()->pathAsImage( mLayer->path(), QSize( 150, 150 ), true, 1.0, fitsInCache );
5102 if ( image.isNull() )
5103 {
5104 mLabelImagePreview->setPixmap( QPixmap() );
5105 return;
5106 }
5107
5108 QImage previewImage( 150, 150, QImage::Format_ARGB32 );
5109 previewImage.fill( Qt::transparent );
5110 const QRect imageRect( ( 150 - image.width() ) / 2.0, ( 150 - image.height() ) / 2.0, image.width(), image.height() );
5111 QPainter p;
5112 p.begin( &previewImage );
5113 //draw a checkerboard background
5114 uchar pixDataRGB[] = { 150, 150, 150, 150, 100, 100, 100, 150, 100, 100, 100, 150, 150, 150, 150, 150 };
5115 const QImage img( pixDataRGB, 2, 2, 8, QImage::Format_ARGB32 );
5116 const QPixmap pix = QPixmap::fromImage( img.scaled( 8, 8 ) );
5117 QBrush checkerBrush;
5118 checkerBrush.setTexture( pix );
5119 p.fillRect( imageRect, checkerBrush );
5120
5121 if ( mLayer->opacity() < 1.0 )
5122 {
5123 p.setOpacity( mLayer->opacity() );
5124 }
5125
5126 p.drawImage( imageRect.left(), imageRect.top(), image );
5127 p.end();
5128 mLabelImagePreview->setPixmap( QPixmap::fromImage( previewImage ) );
5129}
5130
5131
5132//
5133// QgsGeometryGeneratorSymbolLayerWidget
5134//
5135
5137 : QgsSymbolLayerWidget( parent, vl )
5138
5139{
5140 setupUi( this );
5141 modificationExpressionSelector->setMultiLine( true );
5142 modificationExpressionSelector->setLayer( const_cast<QgsVectorLayer *>( vl ) );
5143 modificationExpressionSelector->registerExpressionContextGenerator( this );
5144 cbxGeometryType->addItem( QgsIconUtils::iconPolygon(), tr( "Polygon / MultiPolygon" ), static_cast<int>( Qgis::SymbolType::Fill ) );
5145 cbxGeometryType->addItem( QgsIconUtils::iconLine(), tr( "LineString / MultiLineString" ), static_cast<int>( Qgis::SymbolType::Line ) );
5146 cbxGeometryType->addItem( QgsIconUtils::iconPoint(), tr( "Point / MultiPoint" ), static_cast<int>( Qgis::SymbolType::Marker ) );
5147
5149 mUnitWidget->setShowMapScaleButton( false );
5150
5151 connect( modificationExpressionSelector, &QgsExpressionLineEdit::expressionChanged, this, &QgsGeometryGeneratorSymbolLayerWidget::updateExpression );
5152 connect( cbxGeometryType, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsGeometryGeneratorSymbolLayerWidget::updateSymbolType );
5153 connect( mUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
5154 if ( !mBlockSignals )
5155 {
5156 mLayer->setUnits( mUnitWidget->unit() );
5157 emit symbolChanged();
5158 }
5159 } );
5160}
5161
5163{
5164 mBlockSignals++;
5165 mLayer = static_cast<QgsGeometryGeneratorSymbolLayer *>( l );
5166 modificationExpressionSelector->setExpression( mLayer->geometryExpression() );
5167 cbxGeometryType->setCurrentIndex( cbxGeometryType->findData( static_cast<int>( mLayer->symbolType() ) ) );
5168 mUnitWidget->setUnit( mLayer->units() );
5169 mBlockSignals--;
5170}
5171
5176
5177void QgsGeometryGeneratorSymbolLayerWidget::updateExpression( const QString &string )
5178{
5179 mLayer->setGeometryExpression( string );
5180
5181 emit changed();
5182}
5183
5184void QgsGeometryGeneratorSymbolLayerWidget::updateSymbolType()
5185{
5186 // we try to keep the subsymbol, if we can!
5187 std::unique_ptr<QgsSymbol> subSymbol( mLayer->subSymbol()->clone() );
5188
5189 mLayer->setSymbolType( static_cast<Qgis::SymbolType>( cbxGeometryType->currentData().toInt() ) );
5190
5191 switch ( mLayer->symbolType() )
5192 {
5195 break;
5197 {
5198 if ( subSymbol->type() == Qgis::SymbolType::Fill )
5199 {
5200 // going from fill -> line type, so we can copy any LINE symbol layers across
5201 QgsSymbolLayerList layers;
5202 for ( int i = 0; i < subSymbol->symbolLayerCount(); ++i )
5203 {
5204 if ( dynamic_cast<const QgsLineSymbolLayer *>( subSymbol->symbolLayer( i ) ) )
5205 layers << subSymbol->symbolLayer( i )->clone();
5206 }
5207
5208 if ( !layers.empty() )
5209 mLayer->setSubSymbol( new QgsLineSymbol( layers ) );
5210 }
5211 break;
5212 }
5214 if ( subSymbol->type() == Qgis::SymbolType::Line )
5215 {
5216 // going from line -> fill type, so copy ALL line symbol layers across
5217 QgsSymbolLayerList layers;
5218 for ( int i = 0; i < subSymbol->symbolLayerCount(); ++i )
5219 layers << subSymbol->symbolLayer( i )->clone();
5220 mLayer->setSubSymbol( new QgsFillSymbol( layers ) );
5221 }
5222 break;
5223 }
5224
5225 emit symbolChanged();
5226}
5227
5228//
5229// QgsRandomMarkerFillSymbolLayerWidget
5230//
5231
5232
5234 : QgsSymbolLayerWidget( parent, vl )
5235{
5236 setupUi( this );
5237
5238 mCountMethodComboBox->addItem( tr( "Absolute Count" ), static_cast<int>( Qgis::PointCountMethod::Absolute ) );
5239 mCountMethodComboBox->addItem( tr( "Density-based Count" ), static_cast<int>( Qgis::PointCountMethod::DensityBased ) );
5240
5241 mPointCountSpinBox->setShowClearButton( true );
5242 mPointCountSpinBox->setClearValue( 100 );
5243 mSeedSpinBox->setShowClearButton( true );
5244 mSeedSpinBox->setClearValue( 0 );
5245
5246 connect( mCountMethodComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsRandomMarkerFillSymbolLayerWidget::countMethodChanged );
5247 connect( mPointCountSpinBox, static_cast<void ( QSpinBox::* )( int )>( &QSpinBox::valueChanged ), this, &QgsRandomMarkerFillSymbolLayerWidget::countChanged );
5248 connect( mDensityAreaSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsRandomMarkerFillSymbolLayerWidget::densityAreaChanged );
5249 connect( mSeedSpinBox, static_cast<void ( QSpinBox::* )( int )>( &QSpinBox::valueChanged ), this, &QgsRandomMarkerFillSymbolLayerWidget::seedChanged );
5250 connect( mClipPointsCheckBox, &QCheckBox::toggled, this, [this]( bool checked ) {
5251 if ( mLayer )
5252 {
5253 mLayer->setClipPoints( checked );
5254 emit changed();
5255 }
5256 } );
5257
5258 mDensityAreaUnitWidget->setUnits(
5260 );
5261
5262 connect( mDensityAreaUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsRandomMarkerFillSymbolLayerWidget::densityAreaUnitChanged );
5263}
5264
5266{
5267 if ( !layer || layer->layerType() != "RandomMarkerFill"_L1 )
5268 {
5269 return;
5270 }
5271
5272 mLayer = static_cast<QgsRandomMarkerFillSymbolLayer *>( layer );
5273 whileBlocking( mPointCountSpinBox )->setValue( mLayer->pointCount() );
5274 whileBlocking( mSeedSpinBox )->setValue( mLayer->seed() );
5275 whileBlocking( mClipPointsCheckBox )->setChecked( mLayer->clipPoints() );
5276
5277 bool showDensityBasedCountWidgets = false;
5278 switch ( mLayer->countMethod() )
5279 {
5281 showDensityBasedCountWidgets = true;
5282 break;
5284 break;
5285 }
5286 mDensityAreaLabel->setVisible( showDensityBasedCountWidgets );
5287 mDensityAreaSpinBox->setVisible( showDensityBasedCountWidgets );
5288 mDensityAreaUnitWidget->setVisible( showDensityBasedCountWidgets );
5289 mDensityAreaDdbtn->setVisible( showDensityBasedCountWidgets );
5290
5291 whileBlocking( mCountMethodComboBox )->setCurrentIndex( mCountMethodComboBox->findData( static_cast<int>( mLayer->countMethod() ) ) );
5292 whileBlocking( mDensityAreaSpinBox )->setValue( mLayer->densityArea() );
5293 mDensityAreaUnitWidget->blockSignals( true );
5294 mDensityAreaUnitWidget->setUnit( mLayer->densityAreaUnit() );
5295 mDensityAreaUnitWidget->setMapUnitScale( mLayer->densityAreaUnitScale() );
5296 mDensityAreaUnitWidget->blockSignals( false );
5297
5302}
5303
5308
5309void QgsRandomMarkerFillSymbolLayerWidget::countMethodChanged( int )
5310{
5311 bool showDensityBasedCountWidgets = false;
5312 switch ( static_cast<Qgis::PointCountMethod>( mCountMethodComboBox->currentData().toInt() ) )
5313 {
5315 showDensityBasedCountWidgets = true;
5316 break;
5318 break;
5319 }
5320 mDensityAreaLabel->setVisible( showDensityBasedCountWidgets );
5321 mDensityAreaSpinBox->setVisible( showDensityBasedCountWidgets );
5322 mDensityAreaUnitWidget->setVisible( showDensityBasedCountWidgets );
5323 mDensityAreaDdbtn->setVisible( showDensityBasedCountWidgets );
5324
5325 if ( mLayer )
5326 {
5327 mLayer->setCountMethod( static_cast<Qgis::PointCountMethod>( mCountMethodComboBox->currentData().toInt() ) );
5328 emit changed();
5329 }
5330}
5331
5332void QgsRandomMarkerFillSymbolLayerWidget::countChanged( int d )
5333{
5334 if ( mLayer )
5335 {
5336 mLayer->setPointCount( d );
5337 emit changed();
5338 }
5339}
5340
5341void QgsRandomMarkerFillSymbolLayerWidget::densityAreaChanged( double d )
5342{
5343 if ( mLayer )
5344 {
5345 mLayer->setDensityArea( d );
5346 emit changed();
5347 }
5348}
5349
5350void QgsRandomMarkerFillSymbolLayerWidget::densityAreaUnitChanged()
5351{
5352 if ( mLayer )
5353 {
5354 mLayer->setDensityAreaUnit( mDensityAreaUnitWidget->unit() );
5355 mLayer->setDensityAreaUnitScale( mDensityAreaUnitWidget->getMapUnitScale() );
5356 emit changed();
5357 }
5358}
5359
5360void QgsRandomMarkerFillSymbolLayerWidget::seedChanged( int d )
5361{
5362 if ( mLayer )
5363 {
5364 mLayer->setSeed( d );
5365 emit changed();
5366 }
5367}
5368
5369//
5370// QgsGradientLineSymbolLayerWidget
5371//
5372
5374 : QgsSymbolLayerWidget( parent, vl )
5375{
5376 mLayer = nullptr;
5377 setupUi( this );
5378
5379 btnColorRamp->setShowGradientOnly( true );
5380
5381 btnChangeColor->setAllowOpacity( true );
5382 btnChangeColor->setColorDialogTitle( tr( "Select Gradient Color" ) );
5383 btnChangeColor->setContext( u"symbology"_s );
5384 btnChangeColor->setShowNoColor( true );
5385 btnChangeColor->setNoColorString( tr( "Transparent" ) );
5386 btnChangeColor2->setAllowOpacity( true );
5387 btnChangeColor2->setColorDialogTitle( tr( "Select Gradient Color" ) );
5388 btnChangeColor2->setContext( u"symbology"_s );
5389 btnChangeColor2->setShowNoColor( true );
5390 btnChangeColor2->setNoColorString( tr( "Transparent" ) );
5391
5392 mStartColorDDBtn->registerLinkedWidget( btnChangeColor );
5393 mEndColorDDBtn->registerLinkedWidget( btnChangeColor2 );
5394
5395 connect( btnChangeColor, &QgsColorButton::colorChanged, this, [this]( const QColor &color ) {
5396 if ( mLayer )
5397 {
5398 mLayer->setColor( color );
5399 emit changed();
5400 }
5401 } );
5402 connect( btnChangeColor2, &QgsColorButton::colorChanged, this, [this]( const QColor &color ) {
5403 if ( mLayer )
5404 {
5405 mLayer->setColor2( color );
5406 emit changed();
5407 }
5408 } );
5409 connect( btnColorRamp, &QgsColorRampButton::colorRampChanged, this, [this] {
5410 if ( btnColorRamp->isNull() )
5411 return;
5412
5413 if ( mLayer )
5414 {
5415 mLayer->setColorRamp( btnColorRamp->colorRamp()->clone() );
5416 emit changed();
5417 }
5418 } );
5419
5420 connect( radioTwoColor, &QAbstractButton::toggled, this, [this] {
5421 if ( mLayer )
5422 {
5423 if ( radioTwoColor->isChecked() )
5424 {
5425 mLayer->setGradientColorType( Qgis::GradientColorSource::SimpleTwoColor );
5426 btnChangeColor->setEnabled( true );
5427 btnChangeColor2->setEnabled( true );
5428 btnColorRamp->setEnabled( false );
5429 }
5430 else
5431 {
5432 mLayer->setGradientColorType( Qgis::GradientColorSource::ColorRamp );
5433 btnColorRamp->setEnabled( true );
5434 btnChangeColor->setEnabled( false );
5435 btnChangeColor2->setEnabled( false );
5436 }
5437 emit changed();
5438 }
5439 } );
5440
5441 mPenWidthUnitWidget->setUnits(
5443 );
5444 mOffsetUnitWidget->setUnits(
5446 );
5447
5448 connect( mPenWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
5449 if ( mLayer )
5450 {
5451 mLayer->setWidthUnit( mPenWidthUnitWidget->unit() );
5452 mLayer->setWidthMapUnitScale( mPenWidthUnitWidget->getMapUnitScale() );
5453 emit changed();
5454 }
5455 } );
5456
5457 connect( spinWidth, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, [this] {
5458 if ( mLayer )
5459 {
5460 mLayer->setWidth( spinWidth->value() );
5461 emit changed();
5462 }
5463 } );
5464
5465 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
5466 if ( mLayer )
5467 {
5468 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
5469 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
5470 emit changed();
5471 }
5472 } );
5473
5474 spinOffset->setClearValue( 0.0 );
5475 connect( spinOffset, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double val ) {
5476 if ( mLayer )
5477 {
5478 mLayer->setOffset( val );
5479 emit changed();
5480 }
5481 } );
5482
5483 connect( cboCapStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, [this] {
5484 if ( mLayer )
5485 {
5486 mLayer->setPenCapStyle( cboCapStyle->penCapStyle() );
5487 emit changed();
5488 }
5489 } );
5490 connect( cboJoinStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, [this] {
5491 if ( mLayer )
5492 {
5493 mLayer->setPenJoinStyle( cboJoinStyle->penJoinStyle() );
5494 emit changed();
5495 }
5496 } );
5497}
5498
5500{
5501 if ( !layer )
5502 {
5503 return;
5504 }
5505
5506 if ( layer->layerType() != "Lineburst"_L1 )
5507 {
5508 return;
5509 }
5510
5511 mLayer = dynamic_cast<QgsLineburstSymbolLayer *>( layer );
5512 if ( !mLayer )
5513 {
5514 return;
5515 }
5516
5517 btnChangeColor->blockSignals( true );
5518 btnChangeColor->setColor( mLayer->color() );
5519 btnChangeColor->blockSignals( false );
5520 btnChangeColor2->blockSignals( true );
5521 btnChangeColor2->setColor( mLayer->color2() );
5522 btnChangeColor2->blockSignals( false );
5523
5524 if ( mLayer->gradientColorType() == Qgis::GradientColorSource::SimpleTwoColor )
5525 {
5526 radioTwoColor->setChecked( true );
5527 btnColorRamp->setEnabled( false );
5528 }
5529 else
5530 {
5531 radioColorRamp->setChecked( true );
5532 btnChangeColor->setEnabled( false );
5533 btnChangeColor2->setEnabled( false );
5534 }
5535
5536 // set source color ramp
5537 if ( mLayer->colorRamp() )
5538 {
5539 btnColorRamp->blockSignals( true );
5540 btnColorRamp->setColorRamp( mLayer->colorRamp() );
5541 btnColorRamp->blockSignals( false );
5542 }
5543
5544 whileBlocking( spinWidth )->setValue( mLayer->width() );
5545 whileBlocking( mPenWidthUnitWidget )->setUnit( mLayer->widthUnit() );
5546 whileBlocking( mPenWidthUnitWidget )->setMapUnitScale( mLayer->widthMapUnitScale() );
5547
5548 whileBlocking( mOffsetUnitWidget )->setUnit( mLayer->offsetUnit() );
5549 whileBlocking( mOffsetUnitWidget )->setMapUnitScale( mLayer->offsetMapUnitScale() );
5550 whileBlocking( spinOffset )->setValue( mLayer->offset() );
5551
5552 whileBlocking( cboJoinStyle )->setPenJoinStyle( mLayer->penJoinStyle() );
5553 whileBlocking( cboCapStyle )->setPenCapStyle( mLayer->penCapStyle() );
5554
5561}
5562
5567
5568//
5569// QgsFilledLineSymbolLayerWidget
5570//
5571
5573 : QgsSymbolLayerWidget( parent, vl )
5574{
5575 mLayer = nullptr;
5576 setupUi( this );
5577
5578 mPenWidthUnitWidget->setUnits(
5580 );
5581 mOffsetUnitWidget->setUnits(
5583 );
5584
5585 connect( mPenWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
5586 if ( mLayer )
5587 {
5588 mLayer->setWidthUnit( mPenWidthUnitWidget->unit() );
5589 mLayer->setWidthMapUnitScale( mPenWidthUnitWidget->getMapUnitScale() );
5590 emit changed();
5591 }
5592 } );
5593
5594 connect( spinWidth, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, [this] {
5595 if ( mLayer )
5596 {
5597 mLayer->setWidth( spinWidth->value() );
5598 emit changed();
5599 }
5600 } );
5601
5602 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
5603 if ( mLayer )
5604 {
5605 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
5606 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
5607 emit changed();
5608 }
5609 } );
5610
5611 spinOffset->setClearValue( 0.0 );
5612 connect( spinOffset, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double val ) {
5613 if ( mLayer )
5614 {
5615 mLayer->setOffset( val );
5616 emit changed();
5617 }
5618 } );
5619
5620 connect( cboCapStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, [this] {
5621 if ( mLayer )
5622 {
5623 mLayer->setPenCapStyle( cboCapStyle->penCapStyle() );
5624 emit changed();
5625 }
5626 } );
5627 connect( cboJoinStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, [this] {
5628 if ( mLayer )
5629 {
5630 mLayer->setPenJoinStyle( cboJoinStyle->penJoinStyle() );
5631 emit changed();
5632 }
5633 } );
5634}
5635
5637
5639{
5640 if ( !layer )
5641 {
5642 return;
5643 }
5644
5645 if ( layer->layerType() != "FilledLine"_L1 )
5646 {
5647 return;
5648 }
5649
5650 mLayer = dynamic_cast<QgsFilledLineSymbolLayer *>( layer );
5651 if ( !mLayer )
5652 {
5653 return;
5654 }
5655
5656 whileBlocking( spinWidth )->setValue( mLayer->width() );
5657 whileBlocking( mPenWidthUnitWidget )->setUnit( mLayer->widthUnit() );
5658 whileBlocking( mPenWidthUnitWidget )->setMapUnitScale( mLayer->widthMapUnitScale() );
5659
5660 whileBlocking( mOffsetUnitWidget )->setUnit( mLayer->offsetUnit() );
5661 whileBlocking( mOffsetUnitWidget )->setMapUnitScale( mLayer->offsetMapUnitScale() );
5662 whileBlocking( spinOffset )->setValue( mLayer->offset() );
5663
5664 whileBlocking( cboJoinStyle )->setPenJoinStyle( mLayer->penJoinStyle() );
5665 whileBlocking( cboCapStyle )->setPenCapStyle( mLayer->penCapStyle() );
5666
5671}
5672
5677
5678//
5679// QgsLinearReferencingSymbolLayerWidget
5680//
5681
5683 : QgsSymbolLayerWidget( parent, vl )
5684{
5685 mLayer = nullptr;
5686
5687 setupUi( this );
5688
5689 mComboPlacement->addItem( tr( "Interval (Cartesian 2D Distances)" ), QVariant::fromValue( Qgis::LinearReferencingPlacement::IntervalCartesian2D ) );
5690 mComboPlacement->addItem( tr( "Interval (Z Values)" ), QVariant::fromValue( Qgis::LinearReferencingPlacement::IntervalZ ) );
5691 mComboPlacement->addItem( tr( "Interval (M Values)" ), QVariant::fromValue( Qgis::LinearReferencingPlacement::IntervalM ) );
5692 mComboPlacement->addItem( tr( "On Every Vertex" ), QVariant::fromValue( Qgis::LinearReferencingPlacement::Vertex ) );
5693
5694 mComboQuantity->addItem( tr( "Cartesian 2D Distance" ), QVariant::fromValue( Qgis::LinearReferencingLabelSource::CartesianDistance2D ) );
5695 mComboQuantity->addItem( tr( "Z Values" ), QVariant::fromValue( Qgis::LinearReferencingLabelSource::Z ) );
5696 mComboQuantity->addItem( tr( "M Values" ), QVariant::fromValue( Qgis::LinearReferencingLabelSource::M ) );
5697
5698 mSpinSkipMultiples->setClearValue( 0, tr( "Not set" ) );
5699 mSpinLabelOffsetX->setClearValue( 0 );
5700 mSpinLabelOffsetY->setClearValue( 0 );
5701 mSpinAverageAngleLength->setClearValue( 4.0 );
5702 mLabelOffsetUnitWidget->setUnits(
5704 );
5705 mAverageAngleUnit->setUnits(
5707 );
5708
5709 connect( mComboQuantity, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this] {
5710 if ( mLayer && !mBlockChangesSignal )
5711 {
5712 mLayer->setLabelSource( mComboQuantity->currentData().value<Qgis::LinearReferencingLabelSource>() );
5713 emit changed();
5714 }
5715 } );
5716 connect( mTextFormatButton, &QgsFontButton::changed, this, [this] {
5717 if ( mLayer && !mBlockChangesSignal )
5718 {
5719 mLayer->setTextFormat( mTextFormatButton->textFormat() );
5720 emit changed();
5721 }
5722 } );
5723 connect( spinInterval, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, [this] {
5724 if ( mLayer && !mBlockChangesSignal )
5725 {
5726 mLayer->setInterval( spinInterval->value() );
5727 emit changed();
5728 }
5729 } );
5730 connect( mSpinSkipMultiples, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, [this] {
5731 if ( mLayer && !mBlockChangesSignal )
5732 {
5733 mLayer->setSkipMultiplesOf( mSpinSkipMultiples->value() );
5734 emit changed();
5735 }
5736 } );
5737 connect( mCheckRotate, &QCheckBox::toggled, this, [this]( bool checked ) {
5738 if ( mLayer && !mBlockChangesSignal )
5739 {
5740 mLayer->setRotateLabels( checked );
5741 emit changed();
5742 }
5743 mSpinAverageAngleLength->setEnabled( checked );
5744 mAverageAngleUnit->setEnabled( mSpinAverageAngleLength->isEnabled() );
5745 } );
5746 connect( mCheckShowMarker, &QCheckBox::toggled, this, [this]( bool checked ) {
5747 if ( mLayer && !mBlockChangesSignal )
5748 {
5749 mLayer->setShowMarker( checked );
5750 emit symbolChanged();
5751 }
5752 } );
5753
5754 connect( mSpinLabelOffsetX, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, [this] {
5755 if ( mLayer && !mBlockChangesSignal )
5756 {
5757 mLayer->setLabelOffset( QPointF( mSpinLabelOffsetX->value(), mSpinLabelOffsetY->value() ) );
5758 emit changed();
5759 }
5760 } );
5761 connect( mSpinLabelOffsetY, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, [this] {
5762 if ( mLayer && !mBlockChangesSignal )
5763 {
5764 mLayer->setLabelOffset( QPointF( mSpinLabelOffsetX->value(), mSpinLabelOffsetY->value() ) );
5765 emit changed();
5766 }
5767 } );
5768 connect( mLabelOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
5769 if ( mLayer && !mBlockChangesSignal )
5770 {
5771 mLayer->setLabelOffsetUnit( mLabelOffsetUnitWidget->unit() );
5772 mLayer->setLabelOffsetMapUnitScale( mLabelOffsetUnitWidget->getMapUnitScale() );
5773 emit changed();
5774 }
5775 } );
5776
5777 connect( mComboPlacement, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this] {
5778 if ( mLayer && !mBlockChangesSignal )
5779 {
5780 const Qgis::LinearReferencingPlacement placement = mComboPlacement->currentData().value<Qgis::LinearReferencingPlacement>();
5781 mLayer->setPlacement( placement );
5782 switch ( placement )
5783 {
5787 mIntervalWidget->show();
5788 break;
5790 mIntervalWidget->hide();
5791 break;
5792 }
5793 emit changed();
5794 }
5795 } );
5796
5797 connect( mSpinAverageAngleLength, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, [this] {
5798 if ( mLayer && !mBlockChangesSignal )
5799 {
5800 mLayer->setAverageAngleLength( mSpinAverageAngleLength->value() );
5801 emit changed();
5802 }
5803 } );
5804 connect( mAverageAngleUnit, &QgsUnitSelectionWidget::changed, this, [this] {
5805 if ( mLayer && !mBlockChangesSignal )
5806 {
5807 mLayer->setAverageAngleUnit( mAverageAngleUnit->unit() );
5808 mLayer->setAverageAngleMapUnitScale( mAverageAngleUnit->getMapUnitScale() );
5809 emit changed();
5810 }
5811 } );
5812
5813 connect( mNumberFormatPushButton, &QPushButton::clicked, this, &QgsLinearReferencingSymbolLayerWidget::changeNumberFormat );
5814
5815 mTextFormatButton->registerExpressionContextGenerator( this );
5816}
5817
5819
5820
5822{
5823 if ( !layer || layer->layerType() != "LinearReferencing"_L1 )
5824 return;
5825
5826 // layer type is correct, we can do the cast
5827 mLayer = qgis::down_cast<QgsLinearReferencingSymbolLayer *>( layer );
5828
5829 mBlockChangesSignal = true;
5830
5831 mComboPlacement->setCurrentIndex( mComboPlacement->findData( QVariant::fromValue( mLayer->placement() ) ) );
5832 switch ( mLayer->placement() )
5833 {
5837 mIntervalWidget->show();
5838 break;
5840 mIntervalWidget->hide();
5841 break;
5842 }
5843
5844 mComboQuantity->setCurrentIndex( mComboQuantity->findData( QVariant::fromValue( mLayer->labelSource() ) ) );
5845
5846 mTextFormatButton->setTextFormat( mLayer->textFormat() );
5847 spinInterval->setValue( mLayer->interval() );
5848 mSpinSkipMultiples->setValue( mLayer->skipMultiplesOf() );
5849 mCheckRotate->setChecked( mLayer->rotateLabels() );
5850 mCheckShowMarker->setChecked( mLayer->showMarker() );
5851 mSpinLabelOffsetX->setValue( mLayer->labelOffset().x() );
5852 mSpinLabelOffsetY->setValue( mLayer->labelOffset().y() );
5853 mLabelOffsetUnitWidget->setUnit( mLayer->labelOffsetUnit() );
5854 mLabelOffsetUnitWidget->setMapUnitScale( mLayer->labelOffsetMapUnitScale() );
5855
5856 mAverageAngleUnit->setUnit( mLayer->averageAngleUnit() );
5857 mAverageAngleUnit->setMapUnitScale( mLayer->averageAngleMapUnitScale() );
5858 mSpinAverageAngleLength->setValue( mLayer->averageAngleLength() );
5859
5860 mSpinAverageAngleLength->setEnabled( mCheckRotate->isChecked() );
5861 mAverageAngleUnit->setEnabled( mSpinAverageAngleLength->isEnabled() );
5862
5867
5868 mBlockChangesSignal = false;
5869}
5870
5875
5877{
5879 mTextFormatButton->setMapCanvas( context.mapCanvas() );
5880 mTextFormatButton->setMessageBar( context.messageBar() );
5881}
5882
5883void QgsLinearReferencingSymbolLayerWidget::changeNumberFormat()
5884{
5886 if ( panel && panel->dockMode() )
5887 {
5889 widget->setPanelTitle( tr( "Number Format" ) );
5890 widget->setFormat( mLayer->numericFormat() );
5891 widget->registerExpressionContextGenerator( this );
5892 connect( widget, &QgsNumericFormatSelectorWidget::changed, this, [this, widget] {
5893 if ( !mBlockChangesSignal )
5894 {
5895 mLayer->setNumericFormat( widget->format() );
5896 emit changed();
5897 }
5898 } );
5899 panel->openPanel( widget );
5900 }
5901 else
5902 {
5903 QgsNumericFormatSelectorDialog dialog( this );
5904 dialog.setFormat( mLayer->numericFormat() );
5905 dialog.registerExpressionContextGenerator( this );
5906 if ( dialog.exec() )
5907 {
5908 mLayer->setNumericFormat( dialog.format() );
5909 emit changed();
5910 }
5911 }
5912}
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:3316
@ InnerVertices
Inner vertices (i.e. all vertices except the first and last vertex).
Definition qgis.h:3318
@ LastVertex
Place symbols on the last vertex in the line.
Definition qgis.h:3313
@ CentralPoint
Place symbols at the mid point of the line.
Definition qgis.h:3315
@ SegmentCenter
Place symbols at the center of every line segment.
Definition qgis.h:3317
@ Vertex
Place symbols on every vertex in the line.
Definition qgis.h:3312
@ Interval
Place symbols at regular intervals.
Definition qgis.h:3311
@ FirstVertex
Place symbols on the first vertex in the line.
Definition qgis.h:3314
MarkerClipMode
Marker clipping modes.
Definition qgis.h:3430
@ CompletelyWithin
Render complete markers wherever the completely fall within the polygon shape.
Definition qgis.h:3434
@ NoClipping
No clipping, render complete markers.
Definition qgis.h:3431
@ Shape
Clip to polygon shape.
Definition qgis.h:3432
@ CentroidWithin
Render complete markers wherever their centroid falls within the polygon shape.
Definition qgis.h:3433
LineClipMode
Line clipping modes.
Definition qgis.h:3444
@ NoClipping
Lines are not clipped, will extend to shape's bounding box.
Definition qgis.h:3447
@ ClipPainterOnly
Applying clipping on the painter only (i.e. line endpoints will coincide with polygon bounding box,...
Definition qgis.h:3445
@ ClipToIntersection
Clip lines to intersection with polygon shape (slower) (i.e. line endpoints will coincide with polygo...
Definition qgis.h:3446
@ ColorRamp
Gradient color ramp.
Definition qgis.h:3361
@ SimpleTwoColor
Simple two color gradient.
Definition qgis.h:3360
@ Repeat
Repeat gradient.
Definition qgis.h:3406
@ Reflect
Reflect gradient.
Definition qgis.h:3405
@ Pad
Pad out gradient using colors at endpoint of gradient.
Definition qgis.h:3404
PointCountMethod
Methods which define the number of points randomly filling a polygon.
Definition qgis.h:3418
@ Absolute
The point count is used as an absolute count of markers.
Definition qgis.h:3419
@ DensityBased
The point count is part of a marker density count.
Definition qgis.h:3420
MarkerShape
Marker shapes.
Definition qgis.h:3261
VerticalAnchorPoint
Marker symbol vertical anchor points.
Definition qgis.h:862
@ Bottom
Align to bottom of symbol.
Definition qgis.h:865
@ Center
Align to vertical center of symbol.
Definition qgis.h:864
@ Baseline
Align to baseline of symbol, e.g. font baseline for font marker symbol layers. Treated as Bottom if n...
Definition qgis.h:866
@ Top
Align to top of symbol.
Definition qgis.h:863
LinearReferencingPlacement
Defines how/where the labels should be placed in a linear referencing symbol layer.
Definition qgis.h:3330
@ IntervalZ
Place labels at regular intervals, linearly interpolated using Z values.
Definition qgis.h:3332
@ Vertex
Place labels on every vertex in the line.
Definition qgis.h:3334
@ IntervalM
Place labels at regular intervals, linearly interpolated using M values.
Definition qgis.h:3333
@ IntervalCartesian2D
Place labels at regular intervals, using Cartesian distance calculations on a 2D plane.
Definition qgis.h:3331
LinearReferencingLabelSource
Defines what quantity to use for the labels shown in a linear referencing symbol layer.
Definition qgis.h:3344
@ CartesianDistance2D
Distance along line, calculated using Cartesian calculations on a 2D plane.
Definition qgis.h:3345
@ Percentage
Percentage of another measurement (e.g., canvas size, feature size).
Definition qgis.h:5570
@ Millimeters
Millimeters.
Definition qgis.h:5567
@ Points
Points (e.g., for font sizes).
Definition qgis.h:5571
@ MapUnits
Map units.
Definition qgis.h:5568
@ Pixels
Pixels.
Definition qgis.h:5569
@ Inches
Inches.
Definition qgis.h:5572
@ MetersInMapUnits
Meters value as Map units.
Definition qgis.h:5574
@ Linear
Linear gradient.
Definition qgis.h:3374
@ Conical
Conical (polar) gradient.
Definition qgis.h:3376
@ Radial
Radial (circular) gradient.
Definition qgis.h:3375
SymbolType
Symbol types.
Definition qgis.h:637
@ Marker
Marker symbol.
Definition qgis.h:638
@ Line
Line symbol.
Definition qgis.h:639
@ Fill
Fill symbol.
Definition qgis.h:640
@ Hybrid
Hybrid symbol.
Definition qgis.h:641
SymbolCoordinateReference
Symbol coordinate reference modes.
Definition qgis.h:3388
@ Feature
Relative to feature/shape being rendered.
Definition qgis.h:3389
@ Viewport
Relative to the whole viewport/output device.
Definition qgis.h:3390
QFlags< MarkerLinePlacement > MarkerLinePlacements
Definition qgis.h:3321
HorizontalAnchorPoint
Marker symbol horizontal anchor points.
Definition qgis.h:848
@ Center
Align to horizontal center of symbol.
Definition qgis.h:850
@ Right
Align to right side of symbol.
Definition qgis.h:851
@ Left
Align to left side of symbol.
Definition qgis.h:849
static const double UI_SCALE_FACTOR
UI scaling factor.
Definition qgis.h:6848
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 widgetChanged()
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:7141
QList< QgsSymbolLayer * > QgsSymbolLayerList
Definition qgssymbol.h:30
class GUI_EXPORT QgsMapToolEditBlankSegments
Single variable definition for use within a QgsExpressionContextScope.