QGIS API Documentation 4.1.0-Master (467af3bbe65)
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"
37#include "qgsmarkersymbol.h"
42#include "qgsproperty.h"
44#include "qgssvgcache.h"
46#include "qgssymbollayerutils.h"
47#include "qgsvectorlayer.h"
48#include "qgsvectorlayerutils.h"
49
50#include <QAbstractButton>
51#include <QAction>
52#include <QBuffer>
53#include <QButtonGroup>
54#include <QColorDialog>
55#include <QCursor>
56#include <QDir>
57#include <QFileDialog>
58#include <QInputDialog>
59#include <QMainWindow>
60#include <QMenu>
61#include <QMessageBox>
62#include <QMovie>
63#include <QPainter>
64#include <QRegularExpression>
65#include <QStandardItemModel>
66#include <QString>
67#include <QSvgRenderer>
68
69#include "moc_qgssymbollayerwidget.cpp"
70
71using namespace Qt::StringLiterals;
72
74{
75 if ( auto *lExpressionContext = mContext.expressionContext() )
76 return *lExpressionContext;
77
78 QgsExpressionContext expContext( mContext.globalProjectAtlasMapLayerScopes( vectorLayer() ) );
79
81 if ( const QgsSymbolLayer *symbolLayer = const_cast<QgsSymbolLayerWidget *>( this )->symbolLayer() )
82 {
83 //cheat a bit - set the symbol color variable to match the symbol layer's color (when we should really be using the *symbols*
84 //color, but that's not accessible here). 99% of the time these will be the same anyway
86 }
87 expContext << symbolScope;
93 expContext.lastScope()->addVariable( QgsExpressionContextScope::StaticVariable( u"symbol_layer_count"_s, 1, true ) );
94 expContext.lastScope()->addVariable( QgsExpressionContextScope::StaticVariable( u"symbol_layer_index"_s, 1, true ) );
95 expContext.lastScope()->addVariable( QgsExpressionContextScope::StaticVariable( u"symbol_marker_row"_s, 1, true ) );
96 expContext.lastScope()->addVariable( QgsExpressionContextScope::StaticVariable( u"symbol_marker_column"_s, 1, true ) );
97 expContext.lastScope()->addVariable( QgsExpressionContextScope::StaticVariable( u"symbol_frame"_s, 1, true ) );
98
99 // additional scopes
100 const auto constAdditionalExpressionContextScopes = mContext.additionalExpressionContextScopes();
101 for ( const QgsExpressionContextScope &scope : constAdditionalExpressionContextScopes )
102 {
103 expContext.appendScope( new QgsExpressionContextScope( scope ) );
104 }
105
106 //TODO - show actual value
107 expContext.setOriginalValueVariable( QVariant() );
108
109 QStringList highlights;
110 highlights
120 << u"symbol_layer_count"_s
121 << u"symbol_layer_index"_s
122 << u"symbol_frame"_s;
123
124
125 if ( expContext.hasVariable( u"zoom_level"_s ) )
126 {
127 highlights << u"zoom_level"_s;
128 }
129 if ( expContext.hasVariable( u"vector_tile_zoom"_s ) )
130 {
131 highlights << u"vector_tile_zoom"_s;
132 }
133
134 expContext.setHighlightedVariables( highlights );
135
136 return expContext;
137}
138
140{
141 mContext = context;
142 const auto unitSelectionWidgets = findChildren<QgsUnitSelectionWidget *>();
143 for ( QgsUnitSelectionWidget *unitWidget : unitSelectionWidgets )
144 {
145 unitWidget->setMapCanvas( mContext.mapCanvas() );
146 }
147}
148
150{
151 return mContext;
152}
153
155{
156 button->init( static_cast<int>( key ), symbolLayer()->dataDefinedProperties(), QgsSymbolLayer::propertyDefinitions(), mVectorLayer, true );
158 connect( button, &QgsPropertyOverrideButton::createAuxiliaryField, this, &QgsSymbolLayerWidget::createAuxiliaryField );
159
161}
162
163void QgsSymbolLayerWidget::createAuxiliaryField()
164{
165 // try to create an auxiliary layer if not yet created
166 if ( !mVectorLayer->auxiliaryLayer() )
167 {
168 QgsNewAuxiliaryLayerDialog dlg( mVectorLayer, this );
169 dlg.exec();
170 }
171
172 // return if still not exists
173 if ( !mVectorLayer->auxiliaryLayer() )
174 return;
175
176 QgsPropertyOverrideButton *button = qobject_cast<QgsPropertyOverrideButton *>( sender() );
177 QgsSymbolLayer::Property key = static_cast<QgsSymbolLayer::Property>( button->propertyKey() );
178 QgsPropertyDefinition def = QgsSymbolLayer::propertyDefinitions()[static_cast<int>( key )];
179
180 // create property in auxiliary storage if necessary
181 if ( !mVectorLayer->auxiliaryLayer()->exists( def ) )
182 {
183 QgsNewAuxiliaryFieldDialog dlg( def, mVectorLayer, true, this );
184 if ( dlg.exec() == QDialog::Accepted )
185 def = dlg.propertyDefinition();
186 }
187
188 // return if still not exist
189 if ( !mVectorLayer->auxiliaryLayer()->exists( def ) )
190 return;
191
192 // update property with join field name from auxiliary storage
193 QgsProperty property = button->toProperty();
194 property.setField( QgsAuxiliaryLayer::nameFromProperty( def, true ) );
195 property.setActive( true );
196 button->updateFieldLists();
197 button->setToProperty( property );
198 symbolLayer()->setDataDefinedProperty( key, button->toProperty() );
199
200 emit changed();
201}
202
204{
205 QgsPropertyOverrideButton *button = qobject_cast<QgsPropertyOverrideButton *>( sender() );
206 const QgsSymbolLayer::Property key = static_cast<QgsSymbolLayer::Property>( button->propertyKey() );
207 symbolLayer()->setDataDefinedProperty( key, button->toProperty() );
208 emit changed();
209}
210
212 : QgsSymbolLayerWidget( parent, vl )
213{
214 mLayer = nullptr;
215
216 setupUi( this );
217 connect( mCustomCheckBox, &QCheckBox::stateChanged, this, &QgsSimpleLineSymbolLayerWidget::mCustomCheckBox_stateChanged );
218 connect( mChangePatternButton, &QPushButton::clicked, this, &QgsSimpleLineSymbolLayerWidget::mChangePatternButton_clicked );
219 connect( mPenWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSimpleLineSymbolLayerWidget::mPenWidthUnitWidget_changed );
220 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSimpleLineSymbolLayerWidget::mOffsetUnitWidget_changed );
221 connect( mDashPatternUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSimpleLineSymbolLayerWidget::mDashPatternUnitWidget_changed );
222 connect( mDrawInsideCheckBox, &QCheckBox::stateChanged, this, &QgsSimpleLineSymbolLayerWidget::mDrawInsideCheckBox_stateChanged );
223 connect( mPatternOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSimpleLineSymbolLayerWidget::patternOffsetUnitChanged );
224 connect( mCheckAlignDash, &QCheckBox::toggled, this, [this] {
225 mCheckDashCorners->setEnabled( mCheckAlignDash->isChecked() );
226 if ( !mCheckAlignDash->isChecked() )
227 mCheckDashCorners->setChecked( false );
228
229 if ( mLayer )
230 {
231 mLayer->setAlignDashPattern( mCheckAlignDash->isChecked() );
232 emit changed();
233 }
234 } );
235 connect( mCheckDashCorners, &QCheckBox::toggled, this, [this] {
236 if ( mLayer )
237 {
238 mLayer->setTweakDashPatternOnCorners( mCheckDashCorners->isChecked() );
239 emit changed();
240 }
241 } );
242
243 mPenWidthUnitWidget->setUnits(
245 );
246 mOffsetUnitWidget->setUnits(
248 );
249 mDashPatternUnitWidget->setUnits(
251 );
252 mPatternOffsetUnitWidget->setUnits(
254 );
255 mTrimDistanceStartUnitWidget->setUnits(
264 );
265 mTrimDistanceEndUnitWidget->setUnits(
274 );
275
276 btnChangeColor->setAllowOpacity( true );
277 btnChangeColor->setColorDialogTitle( tr( "Select Line Color" ) );
278 btnChangeColor->setContext( u"symbology"_s );
279
280 mColorDDBtn->registerLinkedWidget( btnChangeColor );
281
282 mRingFilterComboBox->addItem( QgsApplication::getThemeIcon( u"mIconAllRings.svg"_s ), tr( "All Rings" ), QgsLineSymbolLayer::AllRings );
283 mRingFilterComboBox->addItem( QgsApplication::getThemeIcon( u"mIconExteriorRing.svg"_s ), tr( "Exterior Ring Only" ), QgsLineSymbolLayer::ExteriorRingOnly );
284 mRingFilterComboBox->addItem( QgsApplication::getThemeIcon( u"mIconInteriorRings.svg"_s ), tr( "Interior Rings Only" ), QgsLineSymbolLayer::InteriorRingsOnly );
285 connect( mRingFilterComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this]( int ) {
286 if ( mLayer )
287 {
288 mLayer->setRingFilter( static_cast<QgsLineSymbolLayer::RenderRingFilter>( mRingFilterComboBox->currentData().toInt() ) );
289 emit changed();
290 }
291 } );
292
293 spinOffset->setClearValue( 0.0 );
294 spinPatternOffset->setClearValue( 0.0 );
295
296 mTrimStartDistanceSpin->setClearValue( 0.0 );
297 mTrimDistanceEndSpin->setClearValue( 0.0 );
298
299 //make a temporary symbol for the size assistant preview
300 mAssistantPreviewSymbol = std::make_shared<QgsLineSymbol>();
301
302 if ( vectorLayer() )
303 mPenWidthDDBtn->setSymbol( mAssistantPreviewSymbol );
304
305 connect( spinWidth, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleLineSymbolLayerWidget::penWidthChanged );
306 connect( btnChangeColor, &QgsColorButton::colorChanged, this, &QgsSimpleLineSymbolLayerWidget::colorChanged );
307 connect( cboPenStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleLineSymbolLayerWidget::penStyleChanged );
308 connect( spinOffset, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleLineSymbolLayerWidget::offsetChanged );
309 connect( cboCapStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleLineSymbolLayerWidget::penStyleChanged );
310 connect( cboJoinStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleLineSymbolLayerWidget::penStyleChanged );
311 connect( spinPatternOffset, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleLineSymbolLayerWidget::patternOffsetChanged );
312
313 connect( mTrimStartDistanceSpin, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, [this]( double value ) {
314 if ( !mLayer )
315 return;
316
317 mLayer->setTrimDistanceStart( value );
318 emit changed();
319 } );
320 connect( mTrimDistanceStartUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
321 if ( !mLayer )
322 return;
323
324 mLayer->setTrimDistanceStartUnit( mTrimDistanceStartUnitWidget->unit() );
325 mLayer->setTrimDistanceStartMapUnitScale( mTrimDistanceStartUnitWidget->getMapUnitScale() );
326 emit changed();
327 } );
328 connect( mTrimDistanceEndSpin, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, [this]( double value ) {
329 if ( !mLayer )
330 return;
331
332 mLayer->setTrimDistanceEnd( value );
333 emit changed();
334 } );
335 connect( mTrimDistanceEndUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
336 if ( !mLayer )
337 return;
338
339 mLayer->setTrimDistanceEndUnit( mTrimDistanceEndUnitWidget->unit() );
340 mLayer->setTrimDistanceEndMapUnitScale( mTrimDistanceEndUnitWidget->getMapUnitScale() );
341 emit changed();
342 } );
343
344
346
347 connect( this, &QgsSymbolLayerWidget::changed, this, &QgsSimpleLineSymbolLayerWidget::updateAssistantSymbol );
348}
349
351
352void QgsSimpleLineSymbolLayerWidget::updateAssistantSymbol()
353{
354 for ( int i = mAssistantPreviewSymbol->symbolLayerCount() - 1; i >= 0; --i )
355 {
356 mAssistantPreviewSymbol->deleteSymbolLayer( i );
357 }
358 mAssistantPreviewSymbol->appendSymbolLayer( mLayer->clone() );
359 const QgsProperty ddWidth = mLayer->dataDefinedProperties().property( QgsSymbolLayer::Property::StrokeWidth );
360 if ( ddWidth )
361 mAssistantPreviewSymbol->setDataDefinedWidth( ddWidth );
362}
363
364
366{
367 if ( !layer || layer->layerType() != "SimpleLine"_L1 )
368 return;
369
370 // layer type is correct, we can do the cast
371 mLayer = static_cast<QgsSimpleLineSymbolLayer *>( layer );
372
373 // set units
374 mPenWidthUnitWidget->blockSignals( true );
375 mPenWidthUnitWidget->setUnit( mLayer->widthUnit() );
376 mPenWidthUnitWidget->setMapUnitScale( mLayer->widthMapUnitScale() );
377 mPenWidthUnitWidget->blockSignals( false );
378 mOffsetUnitWidget->blockSignals( true );
379 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
380 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
381 mOffsetUnitWidget->blockSignals( false );
382 mDashPatternUnitWidget->blockSignals( true );
383 mDashPatternUnitWidget->setUnit( mLayer->customDashPatternUnit() );
384 mDashPatternUnitWidget->setMapUnitScale( mLayer->customDashPatternMapUnitScale() );
385 mDashPatternUnitWidget->blockSignals( false );
386
387 whileBlocking( mPatternOffsetUnitWidget )->setUnit( mLayer->dashPatternOffsetUnit() );
388 whileBlocking( mPatternOffsetUnitWidget )->setMapUnitScale( mLayer->dashPatternOffsetMapUnitScale() );
389 whileBlocking( mTrimDistanceStartUnitWidget )->setUnit( mLayer->trimDistanceStartUnit() );
390 whileBlocking( mTrimDistanceStartUnitWidget )->setMapUnitScale( mLayer->trimDistanceStartMapUnitScale() );
391 whileBlocking( mTrimDistanceEndUnitWidget )->setUnit( mLayer->trimDistanceEndUnit() );
392 whileBlocking( mTrimDistanceEndUnitWidget )->setMapUnitScale( mLayer->trimDistanceEndMapUnitScale() );
393
394 // set values
395 spinWidth->blockSignals( true );
396 spinWidth->setValue( mLayer->width() );
397 spinWidth->blockSignals( false );
398 btnChangeColor->blockSignals( true );
399 btnChangeColor->setColor( mLayer->color() );
400 btnChangeColor->blockSignals( false );
401 spinOffset->blockSignals( true );
402 spinOffset->setValue( mLayer->offset() );
403 spinOffset->blockSignals( false );
404 cboPenStyle->blockSignals( true );
405 cboJoinStyle->blockSignals( true );
406 cboCapStyle->blockSignals( true );
407 cboPenStyle->setPenStyle( mLayer->penStyle() );
408 cboJoinStyle->setPenJoinStyle( mLayer->penJoinStyle() );
409 cboCapStyle->setPenCapStyle( mLayer->penCapStyle() );
410 cboPenStyle->blockSignals( false );
411 cboJoinStyle->blockSignals( false );
412 cboCapStyle->blockSignals( false );
413 whileBlocking( spinPatternOffset )->setValue( mLayer->dashPatternOffset() );
414 whileBlocking( mTrimStartDistanceSpin )->setValue( mLayer->trimDistanceStart() );
415 whileBlocking( mTrimDistanceEndSpin )->setValue( mLayer->trimDistanceEnd() );
416
417 //use a custom dash pattern?
418 const bool useCustomDashPattern = mLayer->useCustomDashPattern();
419 mChangePatternButton->setEnabled( useCustomDashPattern );
420 label_3->setEnabled( !useCustomDashPattern );
421 cboPenStyle->setEnabled( !useCustomDashPattern );
422 mCustomCheckBox->blockSignals( true );
423 mCustomCheckBox->setCheckState( useCustomDashPattern ? Qt::Checked : Qt::Unchecked );
424 mCustomCheckBox->blockSignals( false );
425
426 //make sure height of custom dash button looks good under different platforms
427 const QSize size = mChangePatternButton->minimumSizeHint();
428 const int fontHeight = static_cast<int>( Qgis::UI_SCALE_FACTOR * fontMetrics().height() * 1.4 );
429 mChangePatternButton->setMinimumSize( QSize( size.width(), std::max( size.height(), fontHeight ) ) );
430
431 //draw inside polygon?
432 const bool drawInsidePolygon = mLayer->drawInsidePolygon();
433 whileBlocking( mDrawInsideCheckBox )->setCheckState( drawInsidePolygon ? Qt::Checked : Qt::Unchecked );
434
435 whileBlocking( mRingFilterComboBox )->setCurrentIndex( mRingFilterComboBox->findData( mLayer->ringFilter() ) );
436
437 whileBlocking( mCheckAlignDash )->setChecked( mLayer->alignDashPattern() );
438 mCheckDashCorners->setEnabled( mLayer->alignDashPattern() );
439 whileBlocking( mCheckDashCorners )->setChecked( mLayer->tweakDashPatternOnCorners() && mLayer->alignDashPattern() );
440
442
453
454 updateAssistantSymbol();
455}
456
461
463{
465
466 switch ( context.symbolType() )
467 {
470 //these settings only have an effect when the symbol layers is part of a fill symbol
471 mDrawInsideCheckBox->hide();
472 mRingFilterComboBox->hide();
473 mRingsLabel->hide();
474 break;
475
478 break;
479 }
480}
481
482void QgsSimpleLineSymbolLayerWidget::penWidthChanged()
483{
484 mLayer->setWidth( spinWidth->value() );
486 emit changed();
487}
488
489void QgsSimpleLineSymbolLayerWidget::colorChanged( const QColor &color )
490{
491 mLayer->setColor( color );
492 emit changed();
493}
494
495void QgsSimpleLineSymbolLayerWidget::penStyleChanged()
496{
497 mLayer->setPenStyle( cboPenStyle->penStyle() );
498 mLayer->setPenJoinStyle( cboJoinStyle->penJoinStyle() );
499 mLayer->setPenCapStyle( cboCapStyle->penCapStyle() );
501 emit changed();
502}
503
504void QgsSimpleLineSymbolLayerWidget::offsetChanged()
505{
506 mLayer->setOffset( spinOffset->value() );
508 emit changed();
509}
510
511void QgsSimpleLineSymbolLayerWidget::patternOffsetChanged()
512{
513 mLayer->setDashPatternOffset( spinPatternOffset->value() );
515 emit changed();
516}
517
518void QgsSimpleLineSymbolLayerWidget::mCustomCheckBox_stateChanged( int state )
519{
520 const bool checked = ( state == Qt::Checked );
521 mChangePatternButton->setEnabled( checked );
522 label_3->setEnabled( !checked );
523 cboPenStyle->setEnabled( !checked );
524
525 mLayer->setUseCustomDashPattern( checked );
526 emit changed();
527}
528
529void QgsSimpleLineSymbolLayerWidget::mChangePatternButton_clicked()
530{
531 QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( this );
532 if ( panel && panel->dockMode() )
533 {
534 QgsDashSpaceWidget *widget = new QgsDashSpaceWidget( mLayer->customDashVector(), panel );
535 widget->setPanelTitle( tr( "Custom Dash Pattern" ) );
536 widget->setUnit( mDashPatternUnitWidget->unit() );
537 connect( widget, &QgsPanelWidget::widgetChanged, this, [this, widget]() {
538 mLayer->setCustomDashVector( widget->dashDotVector() );
540 } );
542 panel->openPanel( widget );
543 return;
544 }
545
546 QgsDashSpaceDialog d( mLayer->customDashVector() );
547 d.setUnit( mDashPatternUnitWidget->unit() );
548 if ( d.exec() == QDialog::Accepted )
549 {
550 mLayer->setCustomDashVector( d.dashDotVector() );
552 emit changed();
553 }
554}
555
556void QgsSimpleLineSymbolLayerWidget::mPenWidthUnitWidget_changed()
557{
558 if ( mLayer )
559 {
560 mLayer->setWidthUnit( mPenWidthUnitWidget->unit() );
561 mLayer->setWidthMapUnitScale( mPenWidthUnitWidget->getMapUnitScale() );
563 emit changed();
564 }
565}
566
567void QgsSimpleLineSymbolLayerWidget::mOffsetUnitWidget_changed()
568{
569 if ( mLayer )
570 {
571 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
572 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
573 emit changed();
574 }
575}
576
577void QgsSimpleLineSymbolLayerWidget::mDashPatternUnitWidget_changed()
578{
579 if ( mLayer )
580 {
581 mLayer->setCustomDashPatternUnit( mDashPatternUnitWidget->unit() );
582 mLayer->setCustomDashPatternMapUnitScale( mDashPatternUnitWidget->getMapUnitScale() );
584 emit changed();
585 }
586}
587
588void QgsSimpleLineSymbolLayerWidget::mDrawInsideCheckBox_stateChanged( int state )
589{
590 const bool checked = ( state == Qt::Checked );
591 mLayer->setDrawInsidePolygon( checked );
592 emit changed();
593}
594
595void QgsSimpleLineSymbolLayerWidget::patternOffsetUnitChanged()
596{
597 if ( mLayer )
598 {
599 mLayer->setDashPatternOffsetUnit( mPatternOffsetUnitWidget->unit() );
600 mLayer->setDashPatternOffsetMapUnitScale( mPatternOffsetUnitWidget->getMapUnitScale() );
602 emit changed();
603 }
604}
605
607{
608 if ( !mLayer )
609 {
610 return;
611 }
612 std::unique_ptr<QgsSimpleLineSymbolLayer> layerCopy( mLayer->clone() );
613 if ( !layerCopy )
614 {
615 return;
616 }
617 const QColor color = qApp->palette().color( QPalette::WindowText );
618 layerCopy->setColor( color );
619 // reset offset, we don't want to show that in the preview
620 layerCopy->setOffset( 0 );
621 layerCopy->setUseCustomDashPattern( true );
622
623 QSize currentIconSize;
624 //icon size is button size with a small margin
625#ifdef Q_OS_WIN
626 currentIconSize = QSize( mChangePatternButton->width() - 10, mChangePatternButton->height() - 6 );
627#else
628 currentIconSize = QSize( mChangePatternButton->width() - 10, mChangePatternButton->height() - 12 );
629#endif
630
631 if ( !currentIconSize.isValid() || currentIconSize.width() <= 0 || currentIconSize.height() <= 0 )
632 {
633 return;
634 }
635
636 //create an icon pixmap
637 const std::unique_ptr<QgsLineSymbol> previewSymbol = std::make_unique<QgsLineSymbol>( QgsSymbolLayerList() << layerCopy.release() );
638 const QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( previewSymbol.get(), currentIconSize, 0, nullptr, QgsScreenProperties( screen() ) );
639 mChangePatternButton->setIconSize( currentIconSize );
640 mChangePatternButton->setIcon( icon );
641
642 // set tooltip
643 // create very large preview image
644 const int width = static_cast<int>( Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance( 'X' ) * 23 );
645 const int height = static_cast<int>( width / 1.61803398875 ); // golden ratio
646
647 const QPixmap pm = QgsSymbolLayerUtils::symbolPreviewPixmap( previewSymbol.get(), QSize( width, height ), height / 20, nullptr, false, nullptr, nullptr, QgsScreenProperties( screen() ) );
648 QByteArray data;
649 QBuffer buffer( &data );
650 pm.save( &buffer, "PNG", 100 );
651 mChangePatternButton->setToolTip( u"<img src='data:image/png;base64, %3' width=\"%4\">"_s.arg( QString( data.toBase64() ) ).arg( width ) );
652}
653
655{
656 QgsSymbolLayerWidget::resizeEvent( event );
657 // redraw custom dash pattern icon -- the button size has changed
659}
660
661
663
664
666 : QgsSymbolLayerWidget( parent, vl )
667{
668 mLayer = nullptr;
669
670 setupUi( this );
671
672 mHorizontalAnchorComboBox->addItem( tr( "Left" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Left ) );
673 mHorizontalAnchorComboBox->addItem( tr( "Horizontal Center" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Center ) );
674 mHorizontalAnchorComboBox->addItem( tr( "Right" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Right ) );
675
676 mVerticalAnchorComboBox->addItem( tr( "Top" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Top ) );
677 mVerticalAnchorComboBox->addItem( tr( "Vertical Center" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Center ) );
678 mVerticalAnchorComboBox->addItem( tr( "Bottom" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Bottom ) );
679
680 connect( mSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSimpleMarkerSymbolLayerWidget::mSizeUnitWidget_changed );
681 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSimpleMarkerSymbolLayerWidget::mOffsetUnitWidget_changed );
682 connect( mStrokeWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSimpleMarkerSymbolLayerWidget::mStrokeWidthUnitWidget_changed );
683 connect( mStrokeStyleComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::mStrokeStyleComboBox_currentIndexChanged );
684 connect( mStrokeWidthSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::mStrokeWidthSpinBox_valueChanged );
685 connect( mHorizontalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged );
686 connect( mVerticalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged );
687 mSizeUnitWidget->setUnits(
689 );
690 mOffsetUnitWidget->setUnits(
692 );
693 mStrokeWidthUnitWidget->setUnits(
695 );
696
697 btnChangeColorFill->setAllowOpacity( true );
698 btnChangeColorFill->setColorDialogTitle( tr( "Select Fill Color" ) );
699 btnChangeColorFill->setContext( u"symbology"_s );
700 btnChangeColorFill->setShowNoColor( true );
701 btnChangeColorFill->setNoColorString( tr( "Transparent Fill" ) );
702 btnChangeColorStroke->setAllowOpacity( true );
703 btnChangeColorStroke->setColorDialogTitle( tr( "Select Stroke Color" ) );
704 btnChangeColorStroke->setContext( u"symbology"_s );
705 btnChangeColorStroke->setShowNoColor( true );
706 btnChangeColorStroke->setNoColorString( tr( "Transparent Stroke" ) );
707
708 mFillColorDDBtn->registerLinkedWidget( btnChangeColorFill );
709 mStrokeColorDDBtn->registerLinkedWidget( btnChangeColorStroke );
710
711 spinOffsetX->setClearValue( 0.0 );
712 spinOffsetY->setClearValue( 0.0 );
713 spinAngle->setClearValue( 0.0 );
714
715 //make a temporary symbol for the size assistant preview
716 mAssistantPreviewSymbol = std::make_shared<QgsMarkerSymbol>();
717
718 if ( vectorLayer() )
719 mSizeDDBtn->setSymbol( mAssistantPreviewSymbol );
720
721 int size = lstNames->iconSize().width();
722
723 size = std::max( 30, static_cast<int>( std::round( Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance( 'X' ) * 3 ) ) );
724
725 lstNames->setGridSize( QSize( size * 1.2, size * 1.2 ) );
726 lstNames->setIconSize( QSize( size, size ) );
727
728 const double markerSize = size * 0.8;
730 for ( const Qgis::MarkerShape shape : shapes )
731 {
732 QgsSimpleMarkerSymbolLayer *lyr = new QgsSimpleMarkerSymbolLayer( shape, markerSize );
734 lyr->setColor( QColor( 200, 200, 200 ) );
735 lyr->setStrokeColor( QColor( 0, 0, 0 ) );
736 const QIcon icon
738 QListWidgetItem *item = new QListWidgetItem( icon, QString(), lstNames );
739 item->setData( Qt::UserRole, static_cast<int>( shape ) );
740 item->setToolTip( QgsSimpleMarkerSymbolLayerBase::encodeShape( shape ) );
741 delete lyr;
742 }
743 // show at least 3 rows
744 lstNames->setMinimumHeight( lstNames->gridSize().height() * 3.1 );
745
746 connect( lstNames, &QListWidget::currentRowChanged, this, &QgsSimpleMarkerSymbolLayerWidget::setShape );
749 connect( cboJoinStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::penJoinStyleChanged );
750 connect( cboCapStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::penCapStyleChanged );
751 connect( spinSize, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::setSize );
752 connect( spinAngle, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::setAngle );
753 connect( spinOffsetX, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::setOffset );
754 connect( spinOffsetY, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleMarkerSymbolLayerWidget::setOffset );
755 connect( this, &QgsSymbolLayerWidget::changed, this, &QgsSimpleMarkerSymbolLayerWidget::updateAssistantSymbol );
756}
757
759
761{
762 if ( layer->layerType() != "SimpleMarker"_L1 )
763 return;
764
765 // layer type is correct, we can do the cast
766 mLayer = static_cast<QgsSimpleMarkerSymbolLayer *>( layer );
767
768 // set values
769 const Qgis::MarkerShape shape = mLayer->shape();
770 for ( int i = 0; i < lstNames->count(); ++i )
771 {
772 if ( static_cast<Qgis::MarkerShape>( lstNames->item( i )->data( Qt::UserRole ).toInt() ) == shape )
773 {
774 lstNames->setCurrentRow( i );
775 break;
776 }
777 }
778 btnChangeColorStroke->blockSignals( true );
779 btnChangeColorStroke->setColor( mLayer->strokeColor() );
780 btnChangeColorStroke->blockSignals( false );
781 btnChangeColorFill->blockSignals( true );
782 btnChangeColorFill->setColor( mLayer->fillColor() );
783 btnChangeColorFill->setEnabled( QgsSimpleMarkerSymbolLayerBase::shapeIsFilled( mLayer->shape() ) );
784 btnChangeColorFill->blockSignals( false );
785 spinSize->blockSignals( true );
786 spinSize->setValue( mLayer->size() );
787 spinSize->blockSignals( false );
788 spinAngle->blockSignals( true );
789 spinAngle->setValue( mLayer->angle() );
790 spinAngle->blockSignals( false );
791 mStrokeStyleComboBox->blockSignals( true );
792 mStrokeStyleComboBox->setPenStyle( mLayer->strokeStyle() );
793 mStrokeStyleComboBox->blockSignals( false );
794 mStrokeWidthSpinBox->blockSignals( true );
795 mStrokeWidthSpinBox->setValue( mLayer->strokeWidth() );
796 mStrokeWidthSpinBox->blockSignals( false );
797 cboJoinStyle->blockSignals( true );
798 cboJoinStyle->setPenJoinStyle( mLayer->penJoinStyle() );
799 cboJoinStyle->blockSignals( false );
800 cboCapStyle->blockSignals( true );
801 cboCapStyle->setPenCapStyle( mLayer->penCapStyle() );
802 cboCapStyle->blockSignals( false );
803
804 // without blocking signals the value gets changed because of slot setOffset()
805 spinOffsetX->blockSignals( true );
806 spinOffsetX->setValue( mLayer->offset().x() );
807 spinOffsetX->blockSignals( false );
808 spinOffsetY->blockSignals( true );
809 spinOffsetY->setValue( mLayer->offset().y() );
810 spinOffsetY->blockSignals( false );
811
812 mSizeUnitWidget->blockSignals( true );
813 mSizeUnitWidget->setUnit( mLayer->sizeUnit() );
814 mSizeUnitWidget->setMapUnitScale( mLayer->sizeMapUnitScale() );
815 mSizeUnitWidget->blockSignals( false );
816 mOffsetUnitWidget->blockSignals( true );
817 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
818 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
819 mOffsetUnitWidget->blockSignals( false );
820 mStrokeWidthUnitWidget->blockSignals( true );
821 mStrokeWidthUnitWidget->setUnit( mLayer->strokeWidthUnit() );
822 mStrokeWidthUnitWidget->setMapUnitScale( mLayer->strokeWidthMapUnitScale() );
823 mStrokeWidthUnitWidget->blockSignals( false );
824
825 //anchor points
826 mHorizontalAnchorComboBox->blockSignals( true );
827 mVerticalAnchorComboBox->blockSignals( true );
828 mHorizontalAnchorComboBox->setCurrentIndex( mHorizontalAnchorComboBox->findData( QVariant::fromValue( mLayer->horizontalAnchorPoint() ) ) );
829 mVerticalAnchorComboBox->setCurrentIndex( mVerticalAnchorComboBox->findData( QVariant::fromValue( mLayer->verticalAnchorPoint() ) ) );
830 mHorizontalAnchorComboBox->blockSignals( false );
831 mVerticalAnchorComboBox->blockSignals( false );
832
845
846 updateAssistantSymbol();
847}
848
853
854void QgsSimpleMarkerSymbolLayerWidget::setShape()
855{
856 mLayer->setShape( static_cast<Qgis::MarkerShape>( lstNames->currentItem()->data( Qt::UserRole ).toInt() ) );
857 btnChangeColorFill->setEnabled( QgsSimpleMarkerSymbolLayerBase::shapeIsFilled( mLayer->shape() ) );
858 emit changed();
859}
860
862{
863 mLayer->setStrokeColor( color );
864 emit changed();
865}
866
868{
869 mLayer->setColor( color );
870 emit changed();
871}
872
873void QgsSimpleMarkerSymbolLayerWidget::penJoinStyleChanged()
874{
875 mLayer->setPenJoinStyle( cboJoinStyle->penJoinStyle() );
876 emit changed();
877}
878
879void QgsSimpleMarkerSymbolLayerWidget::penCapStyleChanged()
880{
881 mLayer->setPenCapStyle( cboCapStyle->penCapStyle() );
882 emit changed();
883}
884
885void QgsSimpleMarkerSymbolLayerWidget::setSize()
886{
887 mLayer->setSize( spinSize->value() );
888 emit changed();
889}
890
891void QgsSimpleMarkerSymbolLayerWidget::setAngle()
892{
893 mLayer->setAngle( spinAngle->value() );
894 emit changed();
895}
896
897void QgsSimpleMarkerSymbolLayerWidget::setOffset()
898{
899 mLayer->setOffset( QPointF( spinOffsetX->value(), spinOffsetY->value() ) );
900 emit changed();
901}
902
903void QgsSimpleMarkerSymbolLayerWidget::mStrokeStyleComboBox_currentIndexChanged( int index )
904{
905 Q_UNUSED( index )
906
907 if ( mLayer )
908 {
909 mLayer->setStrokeStyle( mStrokeStyleComboBox->penStyle() );
910 emit changed();
911 }
912}
913
914void QgsSimpleMarkerSymbolLayerWidget::mStrokeWidthSpinBox_valueChanged( double d )
915{
916 if ( mLayer )
917 {
918 mLayer->setStrokeWidth( d );
919 emit changed();
920 }
921}
922
923void QgsSimpleMarkerSymbolLayerWidget::mSizeUnitWidget_changed()
924{
925 if ( mLayer )
926 {
927 mLayer->setSizeUnit( mSizeUnitWidget->unit() );
928 mLayer->setSizeMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
929 emit changed();
930 }
931}
932
933void QgsSimpleMarkerSymbolLayerWidget::mOffsetUnitWidget_changed()
934{
935 if ( mLayer )
936 {
937 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
938 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
939 emit changed();
940 }
941}
942
943void QgsSimpleMarkerSymbolLayerWidget::mStrokeWidthUnitWidget_changed()
944{
945 if ( mLayer )
946 {
947 mLayer->setStrokeWidthUnit( mStrokeWidthUnitWidget->unit() );
948 mLayer->setStrokeWidthMapUnitScale( mStrokeWidthUnitWidget->getMapUnitScale() );
949 emit changed();
950 }
951}
952
953void QgsSimpleMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged( int )
954{
955 if ( mLayer )
956 {
957 mLayer->setHorizontalAnchorPoint( mHorizontalAnchorComboBox->currentData().value< Qgis::HorizontalAnchorPoint >() );
958 emit changed();
959 }
960}
961
962void QgsSimpleMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged( int )
963{
964 if ( mLayer )
965 {
966 mLayer->setVerticalAnchorPoint( mVerticalAnchorComboBox->currentData().value< Qgis::VerticalAnchorPoint >() );
967 emit changed();
968 }
969}
970
971void QgsSimpleMarkerSymbolLayerWidget::updateAssistantSymbol()
972{
973 for ( int i = mAssistantPreviewSymbol->symbolLayerCount() - 1; i >= 0; --i )
974 {
975 mAssistantPreviewSymbol->deleteSymbolLayer( i );
976 }
977 mAssistantPreviewSymbol->appendSymbolLayer( mLayer->clone() );
978 const QgsProperty ddSize = mLayer->dataDefinedProperties().property( QgsSymbolLayer::Property::Size );
979 if ( ddSize )
980 mAssistantPreviewSymbol->setDataDefinedSize( ddSize );
981}
982
983
985
987 : QgsSymbolLayerWidget( parent, vl )
988{
989 mLayer = nullptr;
990
991 setupUi( this );
992 connect( mStrokeWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSimpleFillSymbolLayerWidget::mStrokeWidthUnitWidget_changed );
993 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSimpleFillSymbolLayerWidget::mOffsetUnitWidget_changed );
994 mStrokeWidthUnitWidget->setUnits(
996 );
997 mOffsetUnitWidget->setUnits(
999 );
1000
1001 btnChangeColor->setAllowOpacity( true );
1002 btnChangeColor->setColorDialogTitle( tr( "Select Fill Color" ) );
1003 btnChangeColor->setContext( u"symbology"_s );
1004 btnChangeColor->setShowNoColor( true );
1005 btnChangeColor->setNoColorString( tr( "Transparent Fill" ) );
1006 btnChangeStrokeColor->setAllowOpacity( true );
1007 btnChangeStrokeColor->setColorDialogTitle( tr( "Select Stroke Color" ) );
1008 btnChangeStrokeColor->setContext( u"symbology"_s );
1009 btnChangeStrokeColor->setShowNoColor( true );
1010 btnChangeStrokeColor->setNoColorString( tr( "Transparent Stroke" ) );
1011
1012 spinOffsetX->setClearValue( 0.0 );
1013 spinOffsetY->setClearValue( 0.0 );
1014
1016 connect( cboFillStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleFillSymbolLayerWidget::setBrushStyle );
1017 connect( btnChangeStrokeColor, &QgsColorButton::colorChanged, this, &QgsSimpleFillSymbolLayerWidget::setStrokeColor );
1018 connect( spinStrokeWidth, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleFillSymbolLayerWidget::strokeWidthChanged );
1019 connect( cboStrokeStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleFillSymbolLayerWidget::strokeStyleChanged );
1020 connect( cboJoinStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSimpleFillSymbolLayerWidget::strokeStyleChanged );
1021 connect( spinOffsetX, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleFillSymbolLayerWidget::offsetChanged );
1022 connect( spinOffsetY, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSimpleFillSymbolLayerWidget::offsetChanged );
1023
1024 mFillColorDDBtn->registerLinkedWidget( btnChangeColor );
1025 mStrokeColorDDBtn->registerLinkedWidget( btnChangeStrokeColor );
1026}
1027
1029{
1030 if ( layer->layerType() != "SimpleFill"_L1 )
1031 return;
1032
1033 // layer type is correct, we can do the cast
1034 mLayer = static_cast<QgsSimpleFillSymbolLayer *>( layer );
1035
1036 // set values
1037 btnChangeColor->blockSignals( true );
1038 btnChangeColor->setColor( mLayer->color() );
1039 btnChangeColor->blockSignals( false );
1040 cboFillStyle->blockSignals( true );
1041 cboFillStyle->setBrushStyle( mLayer->brushStyle() );
1042 cboFillStyle->blockSignals( false );
1043 btnChangeStrokeColor->blockSignals( true );
1044 btnChangeStrokeColor->setColor( mLayer->strokeColor() );
1045 btnChangeStrokeColor->blockSignals( false );
1046 cboStrokeStyle->blockSignals( true );
1047 cboStrokeStyle->setPenStyle( mLayer->strokeStyle() );
1048 cboStrokeStyle->blockSignals( false );
1049 spinStrokeWidth->blockSignals( true );
1050 spinStrokeWidth->setValue( mLayer->strokeWidth() );
1051 spinStrokeWidth->blockSignals( false );
1052 cboJoinStyle->blockSignals( true );
1053 cboJoinStyle->setPenJoinStyle( mLayer->penJoinStyle() );
1054 cboJoinStyle->blockSignals( false );
1055 spinOffsetX->blockSignals( true );
1056 spinOffsetX->setValue( mLayer->offset().x() );
1057 spinOffsetX->blockSignals( false );
1058 spinOffsetY->blockSignals( true );
1059 spinOffsetY->setValue( mLayer->offset().y() );
1060 spinOffsetY->blockSignals( false );
1061
1062 mStrokeWidthUnitWidget->blockSignals( true );
1063 mStrokeWidthUnitWidget->setUnit( mLayer->strokeWidthUnit() );
1064 mStrokeWidthUnitWidget->setMapUnitScale( mLayer->strokeWidthMapUnitScale() );
1065 mStrokeWidthUnitWidget->blockSignals( false );
1066 mOffsetUnitWidget->blockSignals( true );
1067 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
1068 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
1069 mOffsetUnitWidget->blockSignals( false );
1070
1078}
1079
1084
1086{
1087 mLayer->setColor( color );
1088 emit changed();
1089}
1090
1092{
1093 mLayer->setStrokeColor( color );
1094 emit changed();
1095}
1096
1097void QgsSimpleFillSymbolLayerWidget::setBrushStyle()
1098{
1099 mLayer->setBrushStyle( cboFillStyle->brushStyle() );
1100 emit changed();
1101}
1102
1103void QgsSimpleFillSymbolLayerWidget::strokeWidthChanged()
1104{
1105 mLayer->setStrokeWidth( spinStrokeWidth->value() );
1106 emit changed();
1107}
1108
1109void QgsSimpleFillSymbolLayerWidget::strokeStyleChanged()
1110{
1111 mLayer->setStrokeStyle( cboStrokeStyle->penStyle() );
1112 mLayer->setPenJoinStyle( cboJoinStyle->penJoinStyle() );
1113 emit changed();
1114}
1115
1116void QgsSimpleFillSymbolLayerWidget::offsetChanged()
1117{
1118 mLayer->setOffset( QPointF( spinOffsetX->value(), spinOffsetY->value() ) );
1119 emit changed();
1120}
1121
1122void QgsSimpleFillSymbolLayerWidget::mStrokeWidthUnitWidget_changed()
1123{
1124 if ( mLayer )
1125 {
1126 mLayer->setStrokeWidthUnit( mStrokeWidthUnitWidget->unit() );
1127 mLayer->setStrokeWidthMapUnitScale( mStrokeWidthUnitWidget->getMapUnitScale() );
1128 emit changed();
1129 }
1130}
1131
1132void QgsSimpleFillSymbolLayerWidget::mOffsetUnitWidget_changed()
1133{
1134 if ( mLayer )
1135 {
1136 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
1137 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
1138 emit changed();
1139 }
1140}
1141
1143
1145 : QgsSymbolLayerWidget( parent, vl )
1146{
1147 mLayer = nullptr;
1148
1149 setupUi( this );
1150
1151 mHorizontalAnchorComboBox->addItem( tr( "Left" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Left ) );
1152 mHorizontalAnchorComboBox->addItem( tr( "Horizontal Center" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Center ) );
1153 mHorizontalAnchorComboBox->addItem( tr( "Right" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Right ) );
1154
1155 mVerticalAnchorComboBox->addItem( tr( "Top" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Top ) );
1156 mVerticalAnchorComboBox->addItem( tr( "Vertical Center" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Center ) );
1157 mVerticalAnchorComboBox->addItem( tr( "Bottom" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Bottom ) );
1158
1159 connect( mSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsFilledMarkerSymbolLayerWidget::mSizeUnitWidget_changed );
1160 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsFilledMarkerSymbolLayerWidget::mOffsetUnitWidget_changed );
1161 connect( mHorizontalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsFilledMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged );
1162 connect( mVerticalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsFilledMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged );
1163 mSizeUnitWidget->setUnits(
1165 );
1166 mOffsetUnitWidget->setUnits(
1168 );
1169
1170 spinOffsetX->setClearValue( 0.0 );
1171 spinOffsetY->setClearValue( 0.0 );
1172 spinAngle->setClearValue( 0.0 );
1173
1174 //make a temporary symbol for the size assistant preview
1175 mAssistantPreviewSymbol = std::make_shared<QgsMarkerSymbol>();
1176
1177 if ( vectorLayer() )
1178 mSizeDDBtn->setSymbol( mAssistantPreviewSymbol );
1179
1180 int size = lstNames->iconSize().width();
1181 size = std::max( 30, static_cast<int>( std::round( Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance( 'X' ) * 3 ) ) );
1182 lstNames->setGridSize( QSize( size * 1.2, size * 1.2 ) );
1183 lstNames->setIconSize( QSize( size, size ) );
1184
1185 const double markerSize = size * 0.8;
1187 for ( const Qgis::MarkerShape shape : shapes )
1188 {
1189 QgsSimpleMarkerSymbolLayer *lyr = new QgsSimpleMarkerSymbolLayer( shape, markerSize );
1191 lyr->setColor( QColor( 200, 200, 200 ) );
1192 lyr->setStrokeColor( QColor( 0, 0, 0 ) );
1193 const QIcon icon
1195 QListWidgetItem *item = new QListWidgetItem( icon, QString(), lstNames );
1196 item->setData( Qt::UserRole, static_cast<int>( shape ) );
1197 item->setToolTip( QgsSimpleMarkerSymbolLayerBase::encodeShape( shape ) );
1198 delete lyr;
1199 }
1200 // show at least 3 rows
1201 lstNames->setMinimumHeight( lstNames->gridSize().height() * 3.1 );
1202
1203 connect( lstNames, &QListWidget::currentRowChanged, this, &QgsFilledMarkerSymbolLayerWidget::setShape );
1204 connect( spinSize, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsFilledMarkerSymbolLayerWidget::setSize );
1205 connect( spinAngle, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsFilledMarkerSymbolLayerWidget::setAngle );
1206 connect( spinOffsetX, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsFilledMarkerSymbolLayerWidget::setOffset );
1207 connect( spinOffsetY, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsFilledMarkerSymbolLayerWidget::setOffset );
1208 connect( this, &QgsSymbolLayerWidget::changed, this, &QgsFilledMarkerSymbolLayerWidget::updateAssistantSymbol );
1209}
1210
1212
1214{
1215 if ( layer->layerType() != "FilledMarker"_L1 )
1216 return;
1217
1218 // layer type is correct, we can do the cast
1219 mLayer = static_cast<QgsFilledMarkerSymbolLayer *>( layer );
1220
1221 // set values
1222 const Qgis::MarkerShape shape = mLayer->shape();
1223 for ( int i = 0; i < lstNames->count(); ++i )
1224 {
1225 if ( static_cast<Qgis::MarkerShape>( lstNames->item( i )->data( Qt::UserRole ).toInt() ) == shape )
1226 {
1227 lstNames->setCurrentRow( i );
1228 break;
1229 }
1230 }
1231 whileBlocking( spinSize )->setValue( mLayer->size() );
1232 whileBlocking( spinAngle )->setValue( mLayer->angle() );
1233 whileBlocking( spinOffsetX )->setValue( mLayer->offset().x() );
1234 whileBlocking( spinOffsetY )->setValue( mLayer->offset().y() );
1235
1236 mSizeUnitWidget->blockSignals( true );
1237 mSizeUnitWidget->setUnit( mLayer->sizeUnit() );
1238 mSizeUnitWidget->setMapUnitScale( mLayer->sizeMapUnitScale() );
1239 mSizeUnitWidget->blockSignals( false );
1240 mOffsetUnitWidget->blockSignals( true );
1241 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
1242 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
1243 mOffsetUnitWidget->blockSignals( false );
1244
1245 //anchor points
1246 whileBlocking( mHorizontalAnchorComboBox )->setCurrentIndex( mHorizontalAnchorComboBox->findData( QVariant::fromValue( mLayer->horizontalAnchorPoint() ) ) );
1247 whileBlocking( mVerticalAnchorComboBox )->setCurrentIndex( mVerticalAnchorComboBox->findData( QVariant::fromValue( mLayer->verticalAnchorPoint() ) ) );
1248
1255
1256 updateAssistantSymbol();
1257}
1258
1263
1264void QgsFilledMarkerSymbolLayerWidget::setShape()
1265{
1266 mLayer->setShape( static_cast<Qgis::MarkerShape>( lstNames->currentItem()->data( Qt::UserRole ).toInt() ) );
1267 emit changed();
1268}
1269
1270void QgsFilledMarkerSymbolLayerWidget::setSize()
1271{
1272 mLayer->setSize( spinSize->value() );
1273 emit changed();
1274}
1275
1276void QgsFilledMarkerSymbolLayerWidget::setAngle()
1277{
1278 mLayer->setAngle( spinAngle->value() );
1279 emit changed();
1280}
1281
1282void QgsFilledMarkerSymbolLayerWidget::setOffset()
1283{
1284 mLayer->setOffset( QPointF( spinOffsetX->value(), spinOffsetY->value() ) );
1285 emit changed();
1286}
1287
1288void QgsFilledMarkerSymbolLayerWidget::mSizeUnitWidget_changed()
1289{
1290 if ( mLayer )
1291 {
1292 mLayer->setSizeUnit( mSizeUnitWidget->unit() );
1293 mLayer->setSizeMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
1294 emit changed();
1295 }
1296}
1297
1298void QgsFilledMarkerSymbolLayerWidget::mOffsetUnitWidget_changed()
1299{
1300 if ( mLayer )
1301 {
1302 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
1303 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
1304 emit changed();
1305 }
1306}
1307
1308void QgsFilledMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged( int )
1309{
1310 if ( mLayer )
1311 {
1312 mLayer->setHorizontalAnchorPoint( mHorizontalAnchorComboBox->currentData().value<Qgis::HorizontalAnchorPoint>() );
1313 emit changed();
1314 }
1315}
1316
1317void QgsFilledMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged( int )
1318{
1319 if ( mLayer )
1320 {
1321 mLayer->setVerticalAnchorPoint( mVerticalAnchorComboBox->currentData().value< Qgis::VerticalAnchorPoint >() );
1322 emit changed();
1323 }
1324}
1325
1326void QgsFilledMarkerSymbolLayerWidget::updateAssistantSymbol()
1327{
1328 for ( int i = mAssistantPreviewSymbol->symbolLayerCount() - 1; i >= 0; --i )
1329 {
1330 mAssistantPreviewSymbol->deleteSymbolLayer( i );
1331 }
1332 mAssistantPreviewSymbol->appendSymbolLayer( mLayer->clone() );
1333 const QgsProperty ddSize = mLayer->dataDefinedProperties().property( QgsSymbolLayer::Property::Size );
1334 if ( ddSize )
1335 mAssistantPreviewSymbol->setDataDefinedSize( ddSize );
1336}
1337
1338
1340
1342 : QgsSymbolLayerWidget( parent, vl )
1343{
1344 mLayer = nullptr;
1345
1346 setupUi( this );
1347 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsGradientFillSymbolLayerWidget::mOffsetUnitWidget_changed );
1348 connect( mSpinAngle, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsGradientFillSymbolLayerWidget::mSpinAngle_valueChanged );
1349 mOffsetUnitWidget->setUnits(
1351 );
1352
1353 btnColorRamp->setShowGradientOnly( true );
1354
1355 btnChangeColor->setAllowOpacity( true );
1356 btnChangeColor->setColorDialogTitle( tr( "Select Gradient Color" ) );
1357 btnChangeColor->setContext( u"symbology"_s );
1358 btnChangeColor->setShowNoColor( true );
1359 btnChangeColor->setNoColorString( tr( "Transparent" ) );
1360 btnChangeColor2->setAllowOpacity( true );
1361 btnChangeColor2->setColorDialogTitle( tr( "Select Gradient Color" ) );
1362 btnChangeColor2->setContext( u"symbology"_s );
1363 btnChangeColor2->setShowNoColor( true );
1364 btnChangeColor2->setNoColorString( tr( "Transparent" ) );
1365
1366 mStartColorDDBtn->registerLinkedWidget( btnChangeColor );
1367 mEndColorDDBtn->registerLinkedWidget( btnChangeColor2 );
1368
1369 spinOffsetX->setClearValue( 0.0 );
1370 spinOffsetY->setClearValue( 0.0 );
1371 mSpinAngle->setClearValue( 0.0 );
1372
1376 connect( cboGradientType, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsGradientFillSymbolLayerWidget::setGradientType );
1377 connect( cboCoordinateMode, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsGradientFillSymbolLayerWidget::setCoordinateMode );
1378 connect( cboGradientSpread, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsGradientFillSymbolLayerWidget::setGradientSpread );
1379 connect( radioTwoColor, &QAbstractButton::toggled, this, &QgsGradientFillSymbolLayerWidget::colorModeChanged );
1380 connect( spinOffsetX, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsGradientFillSymbolLayerWidget::offsetChanged );
1381 connect( spinOffsetY, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsGradientFillSymbolLayerWidget::offsetChanged );
1382 connect( spinRefPoint1X, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsGradientFillSymbolLayerWidget::referencePointChanged );
1383 connect( spinRefPoint1Y, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsGradientFillSymbolLayerWidget::referencePointChanged );
1384 connect( checkRefPoint1Centroid, &QAbstractButton::toggled, this, &QgsGradientFillSymbolLayerWidget::referencePointChanged );
1385 connect( spinRefPoint2X, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsGradientFillSymbolLayerWidget::referencePointChanged );
1386 connect( spinRefPoint2Y, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsGradientFillSymbolLayerWidget::referencePointChanged );
1387 connect( checkRefPoint2Centroid, &QAbstractButton::toggled, this, &QgsGradientFillSymbolLayerWidget::referencePointChanged );
1388}
1389
1391{
1392 if ( layer->layerType() != "GradientFill"_L1 )
1393 return;
1394
1395 // layer type is correct, we can do the cast
1396 mLayer = static_cast<QgsGradientFillSymbolLayer *>( layer );
1397
1398 // set values
1399 btnChangeColor->blockSignals( true );
1400 btnChangeColor->setColor( mLayer->color() );
1401 btnChangeColor->blockSignals( false );
1402 btnChangeColor2->blockSignals( true );
1403 btnChangeColor2->setColor( mLayer->color2() );
1404 btnChangeColor2->blockSignals( false );
1405
1406 if ( mLayer->gradientColorType() == Qgis::GradientColorSource::SimpleTwoColor )
1407 {
1408 radioTwoColor->setChecked( true );
1409 btnColorRamp->setEnabled( false );
1410 }
1411 else
1412 {
1413 radioColorRamp->setChecked( true );
1414 btnChangeColor->setEnabled( false );
1415 btnChangeColor2->setEnabled( false );
1416 }
1417
1418 // set source color ramp
1419 if ( mLayer->colorRamp() )
1420 {
1421 btnColorRamp->blockSignals( true );
1422 btnColorRamp->setColorRamp( mLayer->colorRamp() );
1423 btnColorRamp->blockSignals( false );
1424 }
1425
1426 cboGradientType->blockSignals( true );
1427 switch ( mLayer->gradientType() )
1428 {
1430 cboGradientType->setCurrentIndex( 0 );
1431 break;
1433 cboGradientType->setCurrentIndex( 1 );
1434 break;
1436 cboGradientType->setCurrentIndex( 2 );
1437 break;
1438 }
1439 cboGradientType->blockSignals( false );
1440
1441 cboCoordinateMode->blockSignals( true );
1442 switch ( mLayer->coordinateMode() )
1443 {
1445 cboCoordinateMode->setCurrentIndex( 1 );
1446 checkRefPoint1Centroid->setEnabled( false );
1447 checkRefPoint2Centroid->setEnabled( false );
1448 break;
1450 default:
1451 cboCoordinateMode->setCurrentIndex( 0 );
1452 break;
1453 }
1454 cboCoordinateMode->blockSignals( false );
1455
1456 cboGradientSpread->blockSignals( true );
1457 switch ( mLayer->gradientSpread() )
1458 {
1460 cboGradientSpread->setCurrentIndex( 0 );
1461 break;
1463 cboGradientSpread->setCurrentIndex( 1 );
1464 break;
1466 cboGradientSpread->setCurrentIndex( 2 );
1467 break;
1468 }
1469 cboGradientSpread->blockSignals( false );
1470
1471 spinRefPoint1X->blockSignals( true );
1472 spinRefPoint1X->setValue( mLayer->referencePoint1().x() );
1473 spinRefPoint1X->blockSignals( false );
1474 spinRefPoint1Y->blockSignals( true );
1475 spinRefPoint1Y->setValue( mLayer->referencePoint1().y() );
1476 spinRefPoint1Y->blockSignals( false );
1477 checkRefPoint1Centroid->blockSignals( true );
1478 checkRefPoint1Centroid->setChecked( mLayer->referencePoint1IsCentroid() );
1479 if ( mLayer->referencePoint1IsCentroid() )
1480 {
1481 spinRefPoint1X->setEnabled( false );
1482 spinRefPoint1Y->setEnabled( false );
1483 }
1484 checkRefPoint1Centroid->blockSignals( false );
1485 spinRefPoint2X->blockSignals( true );
1486 spinRefPoint2X->setValue( mLayer->referencePoint2().x() );
1487 spinRefPoint2X->blockSignals( false );
1488 spinRefPoint2Y->blockSignals( true );
1489 spinRefPoint2Y->setValue( mLayer->referencePoint2().y() );
1490 spinRefPoint2Y->blockSignals( false );
1491 checkRefPoint2Centroid->blockSignals( true );
1492 checkRefPoint2Centroid->setChecked( mLayer->referencePoint2IsCentroid() );
1493 if ( mLayer->referencePoint2IsCentroid() )
1494 {
1495 spinRefPoint2X->setEnabled( false );
1496 spinRefPoint2Y->setEnabled( false );
1497 }
1498 checkRefPoint2Centroid->blockSignals( false );
1499
1500 spinOffsetX->blockSignals( true );
1501 spinOffsetX->setValue( mLayer->offset().x() );
1502 spinOffsetX->blockSignals( false );
1503 spinOffsetY->blockSignals( true );
1504 spinOffsetY->setValue( mLayer->offset().y() );
1505 spinOffsetY->blockSignals( false );
1506 mSpinAngle->blockSignals( true );
1507 mSpinAngle->setValue( mLayer->angle() );
1508 mSpinAngle->blockSignals( false );
1509
1510 mOffsetUnitWidget->blockSignals( true );
1511 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
1512 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
1513 mOffsetUnitWidget->blockSignals( false );
1514
1528}
1529
1534
1536{
1537 mLayer->setColor( color );
1538 emit changed();
1539}
1540
1542{
1543 mLayer->setColor2( color );
1544 emit changed();
1545}
1546
1547void QgsGradientFillSymbolLayerWidget::colorModeChanged()
1548{
1549 if ( radioTwoColor->isChecked() )
1550 {
1552 }
1553 else
1554 {
1555 mLayer->setGradientColorType( Qgis::GradientColorSource::ColorRamp );
1556 }
1557 emit changed();
1558}
1559
1561{
1562 if ( btnColorRamp->isNull() )
1563 return;
1564
1565 mLayer->setColorRamp( btnColorRamp->colorRamp()->clone() );
1566 emit changed();
1567}
1568
1570{
1571 switch ( index )
1572 {
1573 case 0:
1574 mLayer->setGradientType( Qgis::GradientType::Linear );
1575 //set sensible default reference points
1576 spinRefPoint1X->setValue( 0.5 );
1577 spinRefPoint1Y->setValue( 0 );
1578 spinRefPoint2X->setValue( 0.5 );
1579 spinRefPoint2Y->setValue( 1 );
1580 break;
1581 case 1:
1582 mLayer->setGradientType( Qgis::GradientType::Radial );
1583 //set sensible default reference points
1584 spinRefPoint1X->setValue( 0 );
1585 spinRefPoint1Y->setValue( 0 );
1586 spinRefPoint2X->setValue( 1 );
1587 spinRefPoint2Y->setValue( 1 );
1588 break;
1589 case 2:
1590 mLayer->setGradientType( Qgis::GradientType::Conical );
1591 spinRefPoint1X->setValue( 0.5 );
1592 spinRefPoint1Y->setValue( 0.5 );
1593 spinRefPoint2X->setValue( 1 );
1594 spinRefPoint2Y->setValue( 1 );
1595 break;
1596 }
1597 emit changed();
1598}
1599
1601{
1602 switch ( index )
1603 {
1604 case 0:
1605 //feature coordinate mode
1607 //allow choice of centroid reference positions
1608 checkRefPoint1Centroid->setEnabled( true );
1609 checkRefPoint2Centroid->setEnabled( true );
1610 break;
1611 case 1:
1612 //viewport coordinate mode
1614 //disable choice of centroid reference positions
1615 checkRefPoint1Centroid->setChecked( Qt::Unchecked );
1616 checkRefPoint1Centroid->setEnabled( false );
1617 checkRefPoint2Centroid->setChecked( Qt::Unchecked );
1618 checkRefPoint2Centroid->setEnabled( false );
1619 break;
1620 }
1621
1622 emit changed();
1623}
1624
1626{
1627 switch ( index )
1628 {
1629 case 0:
1630 mLayer->setGradientSpread( Qgis::GradientSpread::Pad );
1631 break;
1632 case 1:
1633 mLayer->setGradientSpread( Qgis::GradientSpread::Repeat );
1634 break;
1635 case 2:
1636 mLayer->setGradientSpread( Qgis::GradientSpread::Reflect );
1637 break;
1638 }
1639
1640 emit changed();
1641}
1642
1643void QgsGradientFillSymbolLayerWidget::offsetChanged()
1644{
1645 mLayer->setOffset( QPointF( spinOffsetX->value(), spinOffsetY->value() ) );
1646 emit changed();
1647}
1648
1649void QgsGradientFillSymbolLayerWidget::referencePointChanged()
1650{
1651 mLayer->setReferencePoint1( QPointF( spinRefPoint1X->value(), spinRefPoint1Y->value() ) );
1652 mLayer->setReferencePoint1IsCentroid( checkRefPoint1Centroid->isChecked() );
1653 mLayer->setReferencePoint2( QPointF( spinRefPoint2X->value(), spinRefPoint2Y->value() ) );
1654 mLayer->setReferencePoint2IsCentroid( checkRefPoint2Centroid->isChecked() );
1655 emit changed();
1656}
1657
1658void QgsGradientFillSymbolLayerWidget::mSpinAngle_valueChanged( double value )
1659{
1660 mLayer->setAngle( value );
1661 emit changed();
1662}
1663
1664void QgsGradientFillSymbolLayerWidget::mOffsetUnitWidget_changed()
1665{
1666 if ( mLayer )
1667 {
1668 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
1669 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
1670 emit changed();
1671 }
1672}
1673
1675
1677 : QgsSymbolLayerWidget( parent, vl )
1678{
1679 mLayer = nullptr;
1680
1681 setupUi( this );
1682 connect( mSpinBlurRadius, qOverload<int>( &QSpinBox::valueChanged ), this, &QgsShapeburstFillSymbolLayerWidget::mSpinBlurRadius_valueChanged );
1683 connect( mSpinMaxDistance, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, &QgsShapeburstFillSymbolLayerWidget::mSpinMaxDistance_valueChanged );
1684 connect( mDistanceUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsShapeburstFillSymbolLayerWidget::mDistanceUnitWidget_changed );
1685 connect( mRadioUseWholeShape, &QRadioButton::toggled, this, &QgsShapeburstFillSymbolLayerWidget::mRadioUseWholeShape_toggled );
1686 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsShapeburstFillSymbolLayerWidget::mOffsetUnitWidget_changed );
1687 connect( mIgnoreRingsCheckBox, &QCheckBox::stateChanged, this, &QgsShapeburstFillSymbolLayerWidget::mIgnoreRingsCheckBox_stateChanged );
1688 mDistanceUnitWidget->setUnits(
1690 );
1691 mOffsetUnitWidget->setUnits(
1693 );
1694
1695 QButtonGroup *group1 = new QButtonGroup( this );
1696 group1->addButton( radioColorRamp );
1697 group1->addButton( radioTwoColor );
1698 QButtonGroup *group2 = new QButtonGroup( this );
1699 group2->addButton( mRadioUseMaxDistance );
1700 group2->addButton( mRadioUseWholeShape );
1701 btnChangeColor->setAllowOpacity( true );
1702 btnChangeColor->setColorDialogTitle( tr( "Select Gradient Color" ) );
1703 btnChangeColor->setContext( u"symbology"_s );
1704 btnChangeColor->setShowNoColor( true );
1705 btnChangeColor->setNoColorString( tr( "Transparent" ) );
1706 btnChangeColor2->setAllowOpacity( true );
1707 btnChangeColor2->setColorDialogTitle( tr( "Select Gradient Color" ) );
1708 btnChangeColor2->setContext( u"symbology"_s );
1709 btnChangeColor2->setShowNoColor( true );
1710 btnChangeColor2->setNoColorString( tr( "Transparent" ) );
1711
1712 mStartColorDDBtn->registerLinkedWidget( btnChangeColor );
1713 mEndColorDDBtn->registerLinkedWidget( btnChangeColor2 );
1714
1715 spinOffsetX->setClearValue( 0.0 );
1716 spinOffsetY->setClearValue( 0.0 );
1717 mSpinMaxDistance->setClearValue( 5.0 );
1718
1719 btnColorRamp->setShowGradientOnly( true );
1720
1721 connect( btnColorRamp, &QgsColorRampButton::colorRampChanged, this, &QgsShapeburstFillSymbolLayerWidget::applyColorRamp );
1722
1725 connect( radioTwoColor, &QAbstractButton::toggled, this, &QgsShapeburstFillSymbolLayerWidget::colorModeChanged );
1726 connect( spinOffsetX, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsShapeburstFillSymbolLayerWidget::offsetChanged );
1727 connect( spinOffsetY, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsShapeburstFillSymbolLayerWidget::offsetChanged );
1728
1729 connect( mBlurSlider, &QAbstractSlider::valueChanged, mSpinBlurRadius, &QSpinBox::setValue );
1730 connect( mSpinBlurRadius, static_cast<void ( QSpinBox::* )( int )>( &QSpinBox::valueChanged ), mBlurSlider, &QAbstractSlider::setValue );
1731}
1732
1734{
1735 if ( layer->layerType() != "ShapeburstFill"_L1 )
1736 return;
1737
1738 // layer type is correct, we can do the cast
1739 mLayer = static_cast<QgsShapeburstFillSymbolLayer *>( layer );
1740
1741 // set values
1742 btnChangeColor->blockSignals( true );
1743 btnChangeColor->setColor( mLayer->color() );
1744 btnChangeColor->blockSignals( false );
1745 btnChangeColor2->blockSignals( true );
1746 btnChangeColor2->setColor( mLayer->color2() );
1747 btnChangeColor2->blockSignals( false );
1748
1750 {
1751 radioTwoColor->setChecked( true );
1752 btnColorRamp->setEnabled( false );
1753 }
1754 else
1755 {
1756 radioColorRamp->setChecked( true );
1757 btnChangeColor->setEnabled( false );
1758 btnChangeColor2->setEnabled( false );
1759 }
1760
1761 mSpinBlurRadius->blockSignals( true );
1762 mBlurSlider->blockSignals( true );
1763 mSpinBlurRadius->setValue( mLayer->blurRadius() );
1764 mBlurSlider->setValue( mLayer->blurRadius() );
1765 mSpinBlurRadius->blockSignals( false );
1766 mBlurSlider->blockSignals( false );
1767
1768 mSpinMaxDistance->blockSignals( true );
1769 mSpinMaxDistance->setValue( mLayer->maxDistance() );
1770 mSpinMaxDistance->blockSignals( false );
1771
1772 mRadioUseWholeShape->blockSignals( true );
1773 mRadioUseMaxDistance->blockSignals( true );
1774 if ( mLayer->useWholeShape() )
1775 {
1776 mRadioUseWholeShape->setChecked( true );
1777 mSpinMaxDistance->setEnabled( false );
1778 mDistanceUnitWidget->setEnabled( false );
1779 }
1780 else
1781 {
1782 mRadioUseMaxDistance->setChecked( true );
1783 mSpinMaxDistance->setEnabled( true );
1784 mDistanceUnitWidget->setEnabled( true );
1785 }
1786 mRadioUseWholeShape->blockSignals( false );
1787 mRadioUseMaxDistance->blockSignals( false );
1788
1789 mDistanceUnitWidget->blockSignals( true );
1790 mDistanceUnitWidget->setUnit( mLayer->distanceUnit() );
1791 mDistanceUnitWidget->setMapUnitScale( mLayer->distanceMapUnitScale() );
1792 mDistanceUnitWidget->blockSignals( false );
1793
1794 mIgnoreRingsCheckBox->blockSignals( true );
1795 mIgnoreRingsCheckBox->setCheckState( mLayer->ignoreRings() ? Qt::Checked : Qt::Unchecked );
1796 mIgnoreRingsCheckBox->blockSignals( false );
1797
1798 // set source color ramp
1799 if ( mLayer->colorRamp() )
1800 {
1801 btnColorRamp->blockSignals( true );
1802 btnColorRamp->setColorRamp( mLayer->colorRamp() );
1803 btnColorRamp->blockSignals( false );
1804 }
1805
1806 spinOffsetX->blockSignals( true );
1807 spinOffsetX->setValue( mLayer->offset().x() );
1808 spinOffsetX->blockSignals( false );
1809 spinOffsetY->blockSignals( true );
1810 spinOffsetY->setValue( mLayer->offset().y() );
1811 spinOffsetY->blockSignals( false );
1812 mOffsetUnitWidget->blockSignals( true );
1813 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
1814 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
1815 mOffsetUnitWidget->blockSignals( false );
1816
1824}
1825
1830
1832{
1833 if ( mLayer )
1834 {
1835 mLayer->setColor( color );
1836 emit changed();
1837 }
1838}
1839
1841{
1842 if ( mLayer )
1843 {
1844 mLayer->setColor2( color );
1845 emit changed();
1846 }
1847}
1848
1849void QgsShapeburstFillSymbolLayerWidget::colorModeChanged()
1850{
1851 if ( !mLayer )
1852 {
1853 return;
1854 }
1855
1856 if ( radioTwoColor->isChecked() )
1857 {
1859 }
1860 else
1861 {
1863 }
1864 emit changed();
1865}
1866
1867void QgsShapeburstFillSymbolLayerWidget::mSpinBlurRadius_valueChanged( int value )
1868{
1869 if ( mLayer )
1870 {
1871 mLayer->setBlurRadius( value );
1872 emit changed();
1873 }
1874}
1875
1876void QgsShapeburstFillSymbolLayerWidget::mSpinMaxDistance_valueChanged( double value )
1877{
1878 if ( mLayer )
1879 {
1880 mLayer->setMaxDistance( value );
1881 emit changed();
1882 }
1883}
1884
1885void QgsShapeburstFillSymbolLayerWidget::mDistanceUnitWidget_changed()
1886{
1887 if ( mLayer )
1888 {
1889 mLayer->setDistanceUnit( mDistanceUnitWidget->unit() );
1890 mLayer->setDistanceMapUnitScale( mDistanceUnitWidget->getMapUnitScale() );
1891 emit changed();
1892 }
1893}
1894
1895void QgsShapeburstFillSymbolLayerWidget::mRadioUseWholeShape_toggled( bool value )
1896{
1897 if ( mLayer )
1898 {
1899 mLayer->setUseWholeShape( value );
1900 mDistanceUnitWidget->setEnabled( !value );
1901 emit changed();
1902 }
1903}
1904
1905void QgsShapeburstFillSymbolLayerWidget::applyColorRamp()
1906{
1907 QgsColorRamp *ramp = btnColorRamp->colorRamp();
1908 if ( !ramp )
1909 return;
1910
1911 mLayer->setColorRamp( ramp );
1912 emit changed();
1913}
1914
1915void QgsShapeburstFillSymbolLayerWidget::offsetChanged()
1916{
1917 if ( mLayer )
1918 {
1919 mLayer->setOffset( QPointF( spinOffsetX->value(), spinOffsetY->value() ) );
1920 emit changed();
1921 }
1922}
1923
1924void QgsShapeburstFillSymbolLayerWidget::mOffsetUnitWidget_changed()
1925{
1926 if ( mLayer )
1927 {
1928 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
1929 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
1930 emit changed();
1931 }
1932}
1933
1934
1935void QgsShapeburstFillSymbolLayerWidget::mIgnoreRingsCheckBox_stateChanged( int state )
1936{
1937 const bool checked = ( state == Qt::Checked );
1938 mLayer->setIgnoreRings( checked );
1939 emit changed();
1940}
1941
1943
1945 : QgsSymbolLayerWidget( parent, vl )
1946 , mSymbolType( symbolType )
1947{
1948 mLayer = nullptr;
1949
1950 setupUi( this );
1951 connect( mIntervalUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsTemplatedLineSymbolLayerWidget::mIntervalUnitWidget_changed );
1952 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsTemplatedLineSymbolLayerWidget::mOffsetUnitWidget_changed );
1953 connect( mOffsetAlongLineUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsTemplatedLineSymbolLayerWidget::mOffsetAlongLineUnitWidget_changed );
1954 connect( mAverageAngleUnit, &QgsUnitSelectionWidget::changed, this, &QgsTemplatedLineSymbolLayerWidget::averageAngleUnitChanged );
1955 connect( mBlankSegmentsUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsTemplatedLineSymbolLayerWidget::blankSegmentsUnitChanged );
1956
1959 mIntervalUnitWidget->setUnits( units );
1960 mOffsetUnitWidget->setUnits( units );
1961 mOffsetAlongLineUnitWidget->setUnits( QgsUnitTypes::RenderUnitList( units ) << Qgis::RenderUnit::Percentage );
1962 mAverageAngleUnit->setUnits( units );
1963 mIntervalUnitWidget->setUnits( units );
1964 mBlankSegmentsUnitWidget->setUnits( units );
1965 mTrimDistanceStartUnitWidget->setUnits( QgsUnitTypes::RenderUnitList( units ) << Qgis::RenderUnit::Percentage );
1966 mTrimDistanceEndUnitWidget->setUnits( QgsUnitTypes::RenderUnitList( units ) << Qgis::RenderUnit::Percentage );
1967
1968 mRingFilterComboBox->addItem( QgsApplication::getThemeIcon( u"mIconAllRings.svg"_s ), tr( "All Rings" ), QgsLineSymbolLayer::AllRings );
1969 mRingFilterComboBox->addItem( QgsApplication::getThemeIcon( u"mIconExteriorRing.svg"_s ), tr( "Exterior Ring Only" ), QgsLineSymbolLayer::ExteriorRingOnly );
1970 mRingFilterComboBox->addItem( QgsApplication::getThemeIcon( u"mIconInteriorRings.svg"_s ), tr( "Interior Rings Only" ), QgsLineSymbolLayer::InteriorRingsOnly );
1971 connect( mRingFilterComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this]( int ) {
1972 if ( mLayer )
1973 {
1974 mLayer->setRingFilter( static_cast<QgsLineSymbolLayer::RenderRingFilter>( mRingFilterComboBox->currentData().toInt() ) );
1975 emit changed();
1976 }
1977 } );
1978
1979 spinOffset->setClearValue( 0.0 );
1980 mSpinOffsetAlongLine->setClearValue( 0.0 );
1981 mHashRotationSpinBox->setClearValue( 0 );
1982 mSpinAverageAngleLength->setClearValue( 4.0 );
1983 mTrimStartDistanceSpin->setClearValue( 0.0 );
1984 mTrimDistanceEndSpin->setClearValue( 0.0 );
1985
1986 connect( spinInterval, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsTemplatedLineSymbolLayerWidget::setInterval );
1987 connect( mSpinOffsetAlongLine, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsTemplatedLineSymbolLayerWidget::setOffsetAlongLine );
1988 connect( mSpinHashLength, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsTemplatedLineSymbolLayerWidget::setHashLength );
1989 connect( mHashRotationSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsTemplatedLineSymbolLayerWidget::setHashAngle );
1990 connect( chkRotateMarker, &QAbstractButton::clicked, this, &QgsTemplatedLineSymbolLayerWidget::setRotate );
1991 connect( spinOffset, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsTemplatedLineSymbolLayerWidget::setOffset );
1992 connect( mSpinAverageAngleLength, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsTemplatedLineSymbolLayerWidget::setAverageAngle );
1993 connect( mEditBlankSegmentsBtn, &QToolButton::toggled, this, &QgsMarkerLineSymbolLayerWidget::toggleMapToolEditBlankSegments );
1994
1995 connect( mCheckInterval, &QCheckBox::toggled, this, &QgsTemplatedLineSymbolLayerWidget::setPlacement );
1996 connect( mCheckVertex, &QCheckBox::toggled, this, &QgsTemplatedLineSymbolLayerWidget::setPlacement );
1997 connect( mCheckVertexLast, &QCheckBox::toggled, this, &QgsTemplatedLineSymbolLayerWidget::setPlacement );
1998 connect( mCheckVertexFirst, &QCheckBox::toggled, this, &QgsTemplatedLineSymbolLayerWidget::setPlacement );
1999 connect( mCheckCentralPoint, &QCheckBox::toggled, this, &QgsTemplatedLineSymbolLayerWidget::setPlacement );
2000 connect( mCheckCurvePoint, &QCheckBox::toggled, this, &QgsTemplatedLineSymbolLayerWidget::setPlacement );
2001 connect( mCheckSegmentCentralPoint, &QCheckBox::toggled, this, &QgsTemplatedLineSymbolLayerWidget::setPlacement );
2002
2003 connect( mCheckPlaceOnEveryPart, &QCheckBox::toggled, this, [this] {
2004 if ( mLayer )
2005 {
2006 mLayer->setPlaceOnEveryPart( mCheckPlaceOnEveryPart->isChecked() );
2007 emit changed();
2008 }
2009 } );
2010
2011 connect( mTrimStartDistanceSpin, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, [this]( double value ) {
2012 if ( !mLayer )
2013 return;
2014
2015 mLayer->setTrimDistanceStart( value );
2016 emit changed();
2017 } );
2018 connect( mTrimDistanceStartUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
2019 if ( !mLayer )
2020 return;
2021
2022 mLayer->setTrimDistanceStartUnit( mTrimDistanceStartUnitWidget->unit() );
2023 mLayer->setTrimDistanceStartMapUnitScale( mTrimDistanceStartUnitWidget->getMapUnitScale() );
2024 emit changed();
2025 } );
2026 connect( mTrimDistanceEndSpin, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, [this]( double value ) {
2027 if ( !mLayer )
2028 return;
2029
2030 mLayer->setTrimDistanceEnd( value );
2031 emit changed();
2032 } );
2033 connect( mTrimDistanceEndUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
2034 if ( !mLayer )
2035 return;
2036
2037 mLayer->setTrimDistanceEndUnit( mTrimDistanceEndUnitWidget->unit() );
2038 mLayer->setTrimDistanceEndMapUnitScale( mTrimDistanceEndUnitWidget->getMapUnitScale() );
2039 emit changed();
2040 } );
2041
2042 switch ( mSymbolType )
2043 {
2045 {
2046 connect( mHashLengthUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsTemplatedLineSymbolLayerWidget::hashLengthUnitWidgetChanged );
2047 mHashLengthUnitWidget->setUnits(
2049 );
2050 mPlacementLabel->setText( tr( "Hash placement" ) );
2051 chkRotateMarker->setText( tr( "Rotate hash to follow line direction" ) );
2052 mSpinOffsetAlongLine->setToolTip( tr( "Offset hashes in line direction if positive or in opposite line direction if negative" ) );
2053 mHashLengthLabel->setVisible( true );
2054 mSpinHashLength->setVisible( true );
2055 mHashLengthUnitWidget->setVisible( true );
2056 mHashLengthDDBtn->setVisible( true );
2057 mHashRotationLabel->setVisible( true );
2058 mHashRotationSpinBox->setVisible( true );
2059 mHashRotationDDBtn->setVisible( true );
2060 break;
2061 }
2062
2064 mPlacementLabel->setText( tr( "Marker placement" ) );
2065 chkRotateMarker->setText( tr( "Rotate marker to follow line direction" ) );
2066 mSpinOffsetAlongLine->setToolTip( tr( "Offset markers in line direction if positive or in opposite line direction if negative" ) );
2067 mHashLengthLabel->setVisible( false );
2068 mSpinHashLength->setVisible( false );
2069 mHashLengthUnitWidget->setVisible( false );
2070 mHashLengthDDBtn->setVisible( false );
2071 mHashRotationLabel->setVisible( false );
2072 mHashRotationSpinBox->setVisible( false );
2073 mHashRotationDDBtn->setVisible( false );
2074 }
2075}
2076
2078{
2079 if ( event->type() == QEvent::Show )
2080 {
2081 // Blank segments button is enabled only in dock mode. That requires for this widget to be
2082 // parented which is not the case when we create the widget. So we update on show event
2083 updateBlankSegmentsWidget();
2084 }
2085
2086 return QgsSymbolLayerWidget::event( event );
2087}
2088
2090{
2091 switch ( mSymbolType )
2092 {
2094 if ( layer->layerType() != "HashLine"_L1 )
2095 return;
2096 break;
2097
2099 if ( layer->layerType() != "MarkerLine"_L1 )
2100 return;
2101 }
2102
2103 // layer type is correct, we can do the cast
2104 mLayer = static_cast<QgsTemplatedLineSymbolLayerBase *>( layer );
2105
2106 // set values
2107 spinInterval->blockSignals( true );
2108 spinInterval->setValue( mLayer->interval() );
2109 spinInterval->blockSignals( false );
2110 mSpinOffsetAlongLine->blockSignals( true );
2111 mSpinOffsetAlongLine->setValue( mLayer->offsetAlongLine() );
2112 mSpinOffsetAlongLine->blockSignals( false );
2113
2114 chkRotateMarker->blockSignals( true );
2115 chkRotateMarker->setChecked( mLayer->rotateSymbols() );
2116 chkRotateMarker->blockSignals( false );
2117 spinOffset->blockSignals( true );
2118 spinOffset->setValue( mLayer->offset() );
2119 spinOffset->blockSignals( false );
2120
2121 whileBlocking( mTrimStartDistanceSpin )->setValue( mLayer->trimDistanceStart() );
2122 whileBlocking( mTrimDistanceEndSpin )->setValue( mLayer->trimDistanceEnd() );
2123
2124 whileBlocking( mCheckInterval )->setChecked( mLayer->placements() & Qgis::MarkerLinePlacement::Interval );
2125 whileBlocking( mCheckVertex )->setChecked( mLayer->placements() & Qgis::MarkerLinePlacement::InnerVertices || mLayer->placements() & Qgis::MarkerLinePlacement::Vertex );
2126 whileBlocking( mCheckVertexFirst )->setChecked( mLayer->placements() & Qgis::MarkerLinePlacement::FirstVertex || mLayer->placements() & Qgis::MarkerLinePlacement::Vertex );
2127 whileBlocking( mCheckVertexLast )->setChecked( mLayer->placements() & Qgis::MarkerLinePlacement::LastVertex || mLayer->placements() & Qgis::MarkerLinePlacement::Vertex );
2128 whileBlocking( mCheckCentralPoint )->setChecked( mLayer->placements() & Qgis::MarkerLinePlacement::CentralPoint );
2129 whileBlocking( mCheckCurvePoint )->setChecked( mLayer->placements() & Qgis::MarkerLinePlacement::CurvePoint );
2130 whileBlocking( mCheckSegmentCentralPoint )->setChecked( mLayer->placements() & Qgis::MarkerLinePlacement::SegmentCenter );
2131 whileBlocking( mCheckPlaceOnEveryPart )->setChecked( mLayer->placeOnEveryPart() );
2132
2133 // set units
2134 mIntervalUnitWidget->blockSignals( true );
2135 mIntervalUnitWidget->setUnit( mLayer->intervalUnit() );
2136 mIntervalUnitWidget->setMapUnitScale( mLayer->intervalMapUnitScale() );
2137 mIntervalUnitWidget->blockSignals( false );
2138 mOffsetUnitWidget->blockSignals( true );
2139 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
2140 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
2141 mOffsetUnitWidget->blockSignals( false );
2142 mOffsetAlongLineUnitWidget->blockSignals( true );
2143 mOffsetAlongLineUnitWidget->setUnit( mLayer->offsetAlongLineUnit() );
2144 mOffsetAlongLineUnitWidget->setMapUnitScale( mLayer->offsetAlongLineMapUnitScale() );
2145 mOffsetAlongLineUnitWidget->blockSignals( false );
2146 whileBlocking( mAverageAngleUnit )->setUnit( mLayer->averageAngleUnit() );
2147 whileBlocking( mAverageAngleUnit )->setMapUnitScale( mLayer->averageAngleMapUnitScale() );
2148 whileBlocking( mSpinAverageAngleLength )->setValue( mLayer->averageAngleLength() );
2149 whileBlocking( mBlankSegmentsUnitWidget )->setUnit( mLayer->blankSegmentsUnit() );
2150 whileBlocking( mTrimDistanceStartUnitWidget )->setUnit( mLayer->trimDistanceStartUnit() );
2151 whileBlocking( mTrimDistanceStartUnitWidget )->setMapUnitScale( mLayer->trimDistanceStartMapUnitScale() );
2152 whileBlocking( mTrimDistanceEndUnitWidget )->setUnit( mLayer->trimDistanceEndUnit() );
2153 whileBlocking( mTrimDistanceEndUnitWidget )->setMapUnitScale( mLayer->trimDistanceEndMapUnitScale() );
2154
2155 switch ( mSymbolType )
2156 {
2158 {
2159 QgsHashedLineSymbolLayer *hashLayer = static_cast<QgsHashedLineSymbolLayer *>( mLayer );
2160 whileBlocking( mSpinHashLength )->setValue( hashLayer->hashLength() );
2161 whileBlocking( mHashRotationSpinBox )->setValue( hashLayer->hashAngle() );
2162 whileBlocking( mHashLengthUnitWidget )->setUnit( hashLayer->hashLengthUnit() );
2163 whileBlocking( mHashLengthUnitWidget )->setMapUnitScale( hashLayer->hashLengthMapUnitScale() );
2166 break;
2167 }
2168
2170 break;
2171 }
2172
2173 whileBlocking( mRingFilterComboBox )->setCurrentIndex( mRingFilterComboBox->findData( mLayer->ringFilter() ) );
2174
2175 setPlacement(); // update gui
2176
2185
2186 connect( mBlankSegmentsDDButton, &QgsPropertyOverrideButton::changed, this, &QgsMarkerLineSymbolLayerWidget::updateBlankSegmentsWidget );
2187 connect( mBlankSegmentsDDButton, &QgsPropertyOverrideButton::createAuxiliaryField, this, &QgsMarkerLineSymbolLayerWidget::updateBlankSegmentsWidget );
2188
2189 if ( vectorLayer() )
2190 {
2191 connect( vectorLayer(), &QgsMapLayer::editingStarted, this, &QgsMarkerLineSymbolLayerWidget::updateBlankSegmentsWidget );
2192 connect( vectorLayer(), &QgsMapLayer::editingStopped, this, &QgsMarkerLineSymbolLayerWidget::updateBlankSegmentsWidget );
2193 }
2194
2195 updateBlankSegmentsWidget();
2196}
2197
2202
2204{
2206
2207 switch ( context.symbolType() )
2208 {
2211 //these settings only have an effect when the symbol layers is part of a fill symbol
2212 mRingFilterComboBox->hide();
2213 mRingsLabel->hide();
2214 break;
2215
2218 break;
2219 }
2220}
2221
2223{
2224 mLayer->setInterval( val );
2225 emit changed();
2226}
2227
2229{
2230 mLayer->setOffsetAlongLine( val );
2231 emit changed();
2232}
2233
2234void QgsTemplatedLineSymbolLayerWidget::setHashLength( double val )
2235{
2236 switch ( mSymbolType )
2237 {
2239 {
2240 QgsHashedLineSymbolLayer *hashLayer = static_cast<QgsHashedLineSymbolLayer *>( mLayer );
2241 hashLayer->setHashLength( val );
2242 emit changed();
2243 break;
2244 }
2245
2247 Q_ASSERT( false );
2248 }
2249}
2250
2251void QgsTemplatedLineSymbolLayerWidget::setHashAngle( double val )
2252{
2253 if ( !mLayer )
2254 return;
2255
2256 switch ( mSymbolType )
2257 {
2259 {
2260 QgsHashedLineSymbolLayer *hashLayer = static_cast<QgsHashedLineSymbolLayer *>( mLayer );
2261 hashLayer->setHashAngle( val );
2262 emit changed();
2263 break;
2264 }
2265
2267 Q_ASSERT( false );
2268 }
2269}
2270
2271void QgsTemplatedLineSymbolLayerWidget::setRotate()
2272{
2273 mSpinAverageAngleLength->setEnabled( chkRotateMarker->isChecked() && ( mCheckInterval->isChecked() || mCheckCentralPoint->isChecked() ) );
2274 mAverageAngleUnit->setEnabled( mSpinAverageAngleLength->isEnabled() );
2275
2276 mLayer->setRotateSymbols( chkRotateMarker->isChecked() );
2277 emit changed();
2278}
2279
2280void QgsTemplatedLineSymbolLayerWidget::setOffset()
2281{
2282 mLayer->setOffset( spinOffset->value() );
2283 emit changed();
2284}
2285
2286void QgsTemplatedLineSymbolLayerWidget::setPlacement()
2287{
2288 const bool interval = mCheckInterval->isChecked();
2289 spinInterval->setEnabled( interval );
2290 mSpinOffsetAlongLine->setEnabled( mCheckInterval->isChecked() || mCheckVertexLast->isChecked() || mCheckVertexFirst->isChecked() );
2291 mOffsetAlongLineUnitWidget->setEnabled( mSpinOffsetAlongLine->isEnabled() );
2292 mSpinAverageAngleLength->setEnabled( chkRotateMarker->isChecked() && ( mCheckInterval->isChecked() || mCheckCentralPoint->isChecked() ) );
2293 mAverageAngleUnit->setEnabled( mSpinAverageAngleLength->isEnabled() );
2294 mCheckPlaceOnEveryPart->setEnabled( mCheckVertexLast->isChecked() || mCheckVertexFirst->isChecked() );
2295
2296 Qgis::MarkerLinePlacements placements;
2297 if ( mCheckInterval->isChecked() )
2299 if ( mCheckVertex->isChecked() )
2301 if ( mCheckVertexLast->isChecked() )
2303 if ( mCheckVertexFirst->isChecked() )
2305 if ( mCheckCurvePoint->isChecked() )
2307 if ( mCheckSegmentCentralPoint->isChecked() )
2309 if ( mCheckCentralPoint->isChecked() )
2311 mLayer->setPlacements( placements );
2312
2313 emit changed();
2314}
2315
2316void QgsTemplatedLineSymbolLayerWidget::mIntervalUnitWidget_changed()
2317{
2318 if ( mLayer )
2319 {
2320 mLayer->setIntervalUnit( mIntervalUnitWidget->unit() );
2321 mLayer->setIntervalMapUnitScale( mIntervalUnitWidget->getMapUnitScale() );
2322 emit changed();
2323 }
2324}
2325
2326void QgsTemplatedLineSymbolLayerWidget::mOffsetUnitWidget_changed()
2327{
2328 if ( mLayer )
2329 {
2330 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
2331 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
2332 emit changed();
2333 }
2334}
2335
2336void QgsTemplatedLineSymbolLayerWidget::mOffsetAlongLineUnitWidget_changed()
2337{
2338 if ( mLayer )
2339 {
2340 mLayer->setOffsetAlongLineUnit( mOffsetAlongLineUnitWidget->unit() );
2341 mLayer->setOffsetAlongLineMapUnitScale( mOffsetAlongLineUnitWidget->getMapUnitScale() );
2342 }
2343 emit changed();
2344}
2345
2346void QgsTemplatedLineSymbolLayerWidget::hashLengthUnitWidgetChanged()
2347{
2348 if ( !mLayer )
2349 return;
2350
2351 switch ( mSymbolType )
2352 {
2354 {
2355 QgsHashedLineSymbolLayer *hashLayer = static_cast<QgsHashedLineSymbolLayer *>( mLayer );
2356 hashLayer->setHashLengthUnit( mHashLengthUnitWidget->unit() );
2357 hashLayer->setHashLengthMapUnitScale( mHashLengthUnitWidget->getMapUnitScale() );
2358 emit changed();
2359 break;
2360 }
2361
2363 Q_ASSERT( false );
2364 }
2365}
2366
2367void QgsTemplatedLineSymbolLayerWidget::averageAngleUnitChanged()
2368{
2369 if ( mLayer )
2370 {
2371 mLayer->setAverageAngleUnit( mAverageAngleUnit->unit() );
2372 mLayer->setAverageAngleMapUnitScale( mAverageAngleUnit->getMapUnitScale() );
2373 }
2374 emit changed();
2375}
2376
2377void QgsTemplatedLineSymbolLayerWidget::blankSegmentsUnitChanged()
2378{
2379 if ( mLayer )
2380 {
2381 mLayer->setBlankSegmentsUnit( mBlankSegmentsUnitWidget->unit() );
2382 }
2383 emit changed();
2384}
2385
2386void QgsTemplatedLineSymbolLayerWidget::setAverageAngle( double val )
2387{
2388 if ( mLayer )
2389 {
2390 mLayer->setAverageAngleLength( val );
2391 emit changed();
2392 }
2393}
2394
2395void QgsTemplatedLineSymbolLayerWidget::toggleMapToolEditBlankSegments( bool toggled )
2396{
2397 if ( mMapToolEditBlankSegments )
2398 {
2399 context().mapCanvas()->unsetMapTool( mMapToolEditBlankSegments );
2400 mMapToolEditBlankSegments.reset();
2401 }
2402
2403 if ( toggled )
2404 {
2405 switch ( mSymbolType )
2406 {
2408 mMapToolEditBlankSegments.reset( new QgsMapToolEditBlankSegments<QgsHashedLineSymbolLayer>( context().mapCanvas(), vectorLayer(), mLayer, blankSegmentsFieldIndex() ) );
2409 break;
2410
2412 mMapToolEditBlankSegments.reset( new QgsMapToolEditBlankSegments<QgsMarkerLineSymbolLayer>( context().mapCanvas(), vectorLayer(), mLayer, blankSegmentsFieldIndex() ) );
2413 break;
2414 }
2415
2416 context().mapCanvas()->setMapTool( mMapToolEditBlankSegments );
2417 }
2418}
2419
2420void QgsTemplatedLineSymbolLayerWidget::updateBlankSegmentsWidget()
2421{
2422 QString tooltip;
2423 switch ( mSymbolType )
2424 {
2426 tooltip = tr( "Tool to create blank segments where hashed lines won't be displayed" );
2427 break;
2428
2430 tooltip = tr( "Tool to create blank segments where marker lines won't be displayed" );
2431 break;
2432 }
2433
2434 if ( QgsPanelWidget *panelWidget = QgsPanelWidget::findParentPanel( this ); !panelWidget || !panelWidget->dockMode() )
2435 {
2436 // It's not possible to edit blank segments from Layer properties dialog
2437 mEditBlankSegmentsBtn->setEnabled( false );
2438 tooltip += u"<br/><br/>"_s + 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." );
2439 }
2440 else if ( blankSegmentsFieldIndex() < 0 )
2441 {
2442 mEditBlankSegmentsBtn->setEnabled( false );
2443 tooltip += u"<br/><br/>"_s + tr( "This tool is disabled because no valid field property has been set" );
2444 }
2445 else if ( !vectorLayer() || QgsVectorLayerUtils::fieldIsReadOnly( vectorLayer(), blankSegmentsFieldIndex() ) )
2446 {
2447 mEditBlankSegmentsBtn->setEnabled( false );
2448 tooltip += u"<br/><br/>"_s + tr( "This tool is disabled because field property is not editable" );
2449 }
2450 else
2451 {
2452 mEditBlankSegmentsBtn->setEnabled( true );
2453 }
2454
2455 mEditBlankSegmentsBtn->setToolTip( tooltip );
2456}
2457
2458int QgsTemplatedLineSymbolLayerWidget::blankSegmentsFieldIndex() const
2459{
2460 const QgsProperty blankSegmentsProperty = mLayer->dataDefinedProperties().property( QgsSymbolLayer::Property::BlankSegments );
2461 return blankSegmentsProperty && blankSegmentsProperty.isActive() && blankSegmentsProperty.propertyType() == Qgis::PropertyType::Field && vectorLayer()
2462 ? vectorLayer()->fields().indexFromName( blankSegmentsProperty.field() )
2463 : -1;
2464}
2465
2467
2471
2473
2477
2479
2480
2482 : QgsSymbolLayerWidget( parent, vl )
2483{
2484 mLayer = nullptr;
2485
2486 setupUi( this );
2487
2488 mHorizontalAnchorComboBox->addItem( tr( "Left" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Left ) );
2489 mHorizontalAnchorComboBox->addItem( tr( "Horizontal Center" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Center ) );
2490 mHorizontalAnchorComboBox->addItem( tr( "Right" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Right ) );
2491
2492 mVerticalAnchorComboBox->addItem( tr( "Top" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Top ) );
2493 mVerticalAnchorComboBox->addItem( tr( "Vertical Center" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Center ) );
2494 mVerticalAnchorComboBox->addItem( tr( "Bottom" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Bottom ) );
2495
2496 mSvgSelectorWidget->setAllowParameters( true );
2497 mSvgSelectorWidget->sourceLineEdit()->setPropertyOverrideToolButtonVisible( true );
2498 mSvgSelectorWidget->sourceLineEdit()->setLastPathSettingsKey( u"/UI/lastSVGMarkerDir"_s );
2499 mSvgSelectorWidget->initParametersModel( this, vl );
2500
2501 connect( mSvgSelectorWidget->sourceLineEdit(), &QgsSvgSourceLineEdit::sourceChanged, this, &QgsSvgMarkerSymbolLayerWidget::svgSourceChanged );
2502 connect( mChangeColorButton, &QgsColorButton::colorChanged, this, &QgsSvgMarkerSymbolLayerWidget::mChangeColorButton_colorChanged );
2503 connect( mChangeStrokeColorButton, &QgsColorButton::colorChanged, this, &QgsSvgMarkerSymbolLayerWidget::mChangeStrokeColorButton_colorChanged );
2504 connect( mStrokeWidthSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSvgMarkerSymbolLayerWidget::mStrokeWidthSpinBox_valueChanged );
2505 connect( mSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSvgMarkerSymbolLayerWidget::mSizeUnitWidget_changed );
2506 connect( mStrokeWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSvgMarkerSymbolLayerWidget::mStrokeWidthUnitWidget_changed );
2507 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSvgMarkerSymbolLayerWidget::mOffsetUnitWidget_changed );
2508 connect( mHorizontalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSvgMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged );
2509 connect( mVerticalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSvgMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged );
2510 mSizeUnitWidget->setUnits(
2512 );
2513 mStrokeWidthUnitWidget->setUnits(
2515 );
2516 mOffsetUnitWidget->setUnits(
2518 );
2519 mChangeColorButton->setAllowOpacity( true );
2520 mChangeColorButton->setColorDialogTitle( tr( "Select Fill color" ) );
2521 mChangeColorButton->setContext( u"symbology"_s );
2522 mChangeStrokeColorButton->setAllowOpacity( true );
2523 mChangeStrokeColorButton->setColorDialogTitle( tr( "Select Stroke Color" ) );
2524 mChangeStrokeColorButton->setContext( u"symbology"_s );
2525
2526 mFillColorDDBtn->registerLinkedWidget( mChangeColorButton );
2527 mStrokeColorDDBtn->registerLinkedWidget( mChangeStrokeColorButton );
2528
2529 spinOffsetX->setClearValue( 0.0 );
2530 spinOffsetY->setClearValue( 0.0 );
2531 spinAngle->setClearValue( 0.0 );
2532
2533 connect( spinWidth, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSvgMarkerSymbolLayerWidget::setWidth );
2534 connect( spinHeight, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSvgMarkerSymbolLayerWidget::setHeight );
2535 connect( mLockAspectRatio, static_cast<void ( QgsRatioLockButton::* )( bool )>( &QgsRatioLockButton::lockChanged ), this, &QgsSvgMarkerSymbolLayerWidget::lockAspectRatioChanged );
2536 connect( spinAngle, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSvgMarkerSymbolLayerWidget::setAngle );
2537 connect( spinOffsetX, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSvgMarkerSymbolLayerWidget::setOffset );
2538 connect( spinOffsetY, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSvgMarkerSymbolLayerWidget::setOffset );
2539 connect( this, &QgsSymbolLayerWidget::changed, this, &QgsSvgMarkerSymbolLayerWidget::updateAssistantSymbol );
2540
2543
2544 //make a temporary symbol for the size assistant preview
2545 mAssistantPreviewSymbol = std::make_shared<QgsMarkerSymbol>();
2546
2547 if ( vectorLayer() )
2548 {
2549 mWidthDDBtn->setSymbol( mAssistantPreviewSymbol );
2550 mHeightDDBtn->setSymbol( mAssistantPreviewSymbol );
2551 }
2552}
2553
2555
2556#include <QTime>
2557#include <QAbstractListModel>
2558#include <QPixmapCache>
2559#include <QStyle>
2560#include <memory>
2561
2562
2564{
2565 if ( !layer )
2566 {
2567 return;
2568 }
2569
2570 //activate gui for svg parameters only if supported by the svg file
2571 bool hasFillParam, hasFillOpacityParam, hasStrokeParam, hasStrokeWidthParam, hasStrokeOpacityParam;
2572 QColor defaultFill, defaultStroke;
2573 double defaultStrokeWidth, defaultFillOpacity, defaultStrokeOpacity;
2574 bool hasDefaultFillColor, hasDefaultFillOpacity, hasDefaultStrokeColor, hasDefaultStrokeWidth, hasDefaultStrokeOpacity;
2576 layer->path(),
2577 hasFillParam,
2578 hasDefaultFillColor,
2579 defaultFill,
2580 hasFillOpacityParam,
2581 hasDefaultFillOpacity,
2582 defaultFillOpacity,
2583 hasStrokeParam,
2584 hasDefaultStrokeColor,
2585 defaultStroke,
2586 hasStrokeWidthParam,
2587 hasDefaultStrokeWidth,
2588 defaultStrokeWidth,
2589 hasStrokeOpacityParam,
2590 hasDefaultStrokeOpacity,
2591 defaultStrokeOpacity
2592 );
2593 mChangeColorButton->setEnabled( hasFillParam );
2594 mChangeColorButton->setAllowOpacity( hasFillOpacityParam );
2595 mChangeStrokeColorButton->setEnabled( hasStrokeParam );
2596 mChangeStrokeColorButton->setAllowOpacity( hasStrokeOpacityParam );
2597 mStrokeWidthSpinBox->setEnabled( hasStrokeWidthParam );
2598
2599 if ( hasFillParam )
2600 {
2601 QColor fill = layer->fillColor();
2602 const double existingOpacity = hasFillOpacityParam ? fill.alphaF() : 1.0;
2603 if ( hasDefaultFillColor && !skipDefaultColors )
2604 {
2605 fill = defaultFill;
2606 }
2607 fill.setAlphaF( hasDefaultFillOpacity ? defaultFillOpacity : existingOpacity );
2608 mChangeColorButton->setColor( fill );
2609 }
2610 if ( hasStrokeParam )
2611 {
2612 QColor stroke = layer->strokeColor();
2613 const double existingOpacity = hasStrokeOpacityParam ? stroke.alphaF() : 1.0;
2614 if ( hasDefaultStrokeColor && !skipDefaultColors )
2615 {
2616 stroke = defaultStroke;
2617 }
2618 stroke.setAlphaF( hasDefaultStrokeOpacity ? defaultStrokeOpacity : existingOpacity );
2619 mChangeStrokeColorButton->setColor( stroke );
2620 }
2621
2622 whileBlocking( mSvgSelectorWidget->sourceLineEdit() )->setSource( layer->path() );
2623
2624 mStrokeWidthSpinBox->blockSignals( true );
2625 mStrokeWidthSpinBox->setValue( hasDefaultStrokeWidth ? defaultStrokeWidth : layer->strokeWidth() );
2626 mStrokeWidthSpinBox->blockSignals( false );
2627
2628 const bool preservedAspectRatio = layer->preservedAspectRatio();
2629 spinHeight->blockSignals( true );
2630 if ( preservedAspectRatio )
2631 {
2632 spinHeight->setValue( layer->size() * layer->defaultAspectRatio() );
2633 }
2634 else
2635 {
2636 spinHeight->setValue( layer->size() * layer->fixedAspectRatio() );
2637 }
2638 spinHeight->setEnabled( layer->defaultAspectRatio() > 0.0 );
2639 spinHeight->blockSignals( false );
2640 whileBlocking( mLockAspectRatio )->setLocked( preservedAspectRatio );
2641}
2642
2643void QgsSvgMarkerSymbolLayerWidget::updateAssistantSymbol()
2644{
2645 for ( int i = mAssistantPreviewSymbol->symbolLayerCount() - 1; i >= 0; --i )
2646 {
2647 mAssistantPreviewSymbol->deleteSymbolLayer( i );
2648 }
2649 mAssistantPreviewSymbol->appendSymbolLayer( mLayer->clone() );
2650 const QgsProperty ddSize = mLayer->dataDefinedProperties().property( QgsSymbolLayer::Property::Size );
2651 if ( ddSize )
2652 mAssistantPreviewSymbol->setDataDefinedSize( ddSize );
2653}
2654
2655
2657{
2658 if ( !layer )
2659 {
2660 return;
2661 }
2662
2663 if ( layer->layerType() != "SvgMarker"_L1 )
2664 return;
2665
2666 // layer type is correct, we can do the cast
2667 mLayer = static_cast<QgsSvgMarkerSymbolLayer *>( layer );
2668
2669 // set values
2670 mSvgSelectorWidget->setSvgPath( mLayer->path() );
2671 mSvgSelectorWidget->setSvgParameters( mLayer->parameters() );
2672
2673 spinWidth->blockSignals( true );
2674 spinWidth->setValue( mLayer->size() );
2675 spinWidth->blockSignals( false );
2676 spinAngle->blockSignals( true );
2677 spinAngle->setValue( mLayer->angle() );
2678 spinAngle->blockSignals( false );
2679
2680 // without blocking signals the value gets changed because of slot setOffset()
2681 spinOffsetX->blockSignals( true );
2682 spinOffsetX->setValue( mLayer->offset().x() );
2683 spinOffsetX->blockSignals( false );
2684 spinOffsetY->blockSignals( true );
2685 spinOffsetY->setValue( mLayer->offset().y() );
2686 spinOffsetY->blockSignals( false );
2687
2688 mSizeUnitWidget->blockSignals( true );
2689 mSizeUnitWidget->setUnit( mLayer->sizeUnit() );
2690 mSizeUnitWidget->setMapUnitScale( mLayer->sizeMapUnitScale() );
2691 mSizeUnitWidget->blockSignals( false );
2692 mStrokeWidthUnitWidget->blockSignals( true );
2693 mStrokeWidthUnitWidget->setUnit( mLayer->strokeWidthUnit() );
2694 mStrokeWidthUnitWidget->setMapUnitScale( mLayer->strokeWidthMapUnitScale() );
2695 mStrokeWidthUnitWidget->blockSignals( false );
2696 mOffsetUnitWidget->blockSignals( true );
2697 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
2698 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
2699 mOffsetUnitWidget->blockSignals( false );
2700
2701 //anchor points
2702 mHorizontalAnchorComboBox->blockSignals( true );
2703 mVerticalAnchorComboBox->blockSignals( true );
2704 mHorizontalAnchorComboBox->setCurrentIndex( mHorizontalAnchorComboBox->findData( QVariant::fromValue( mLayer->horizontalAnchorPoint() ) ) );
2705 mVerticalAnchorComboBox->setCurrentIndex( mVerticalAnchorComboBox->findData( QVariant::fromValue( mLayer->verticalAnchorPoint() ) ) );
2706 mHorizontalAnchorComboBox->blockSignals( false );
2707 mVerticalAnchorComboBox->blockSignals( false );
2708
2709 setGuiForSvg( mLayer, true );
2710
2720
2721 registerDataDefinedButton( mSvgSelectorWidget->sourceLineEdit()->propertyOverrideToolButton(), QgsSymbolLayer::Property::Name );
2722
2723 updateAssistantSymbol();
2724}
2725
2730
2732{
2734 mSvgSelectorWidget->sourceLineEdit()->setMessageBar( context.messageBar() );
2735}
2736
2738{
2739 mLayer->setPath( name );
2740 whileBlocking( mSvgSelectorWidget->sourceLineEdit() )->setSource( name );
2741
2743 emit changed();
2744}
2745
2746void QgsSvgMarkerSymbolLayerWidget::setSvgParameters( const QMap<QString, QgsProperty> &parameters )
2747{
2748 mLayer->setParameters( parameters );
2749 whileBlocking( mSvgSelectorWidget )->setSvgParameters( parameters );
2750
2752 emit changed();
2753}
2754
2755void QgsSvgMarkerSymbolLayerWidget::setWidth()
2756{
2757 const double defaultAspectRatio = mLayer->defaultAspectRatio();
2758 double fixedAspectRatio = 0.0;
2759 spinHeight->blockSignals( true );
2760 if ( defaultAspectRatio <= 0.0 )
2761 {
2762 spinHeight->setValue( spinWidth->value() );
2763 }
2764 else if ( mLockAspectRatio->locked() )
2765 {
2766 spinHeight->setValue( spinWidth->value() * defaultAspectRatio );
2767 }
2768 else
2769 {
2770 fixedAspectRatio = spinHeight->value() / spinWidth->value();
2771 }
2772 spinHeight->blockSignals( false );
2773 mLayer->setSize( spinWidth->value() );
2774 mLayer->setFixedAspectRatio( fixedAspectRatio );
2775 emit changed();
2776}
2777
2778void QgsSvgMarkerSymbolLayerWidget::setHeight()
2779{
2780 const double defaultAspectRatio = mLayer->defaultAspectRatio();
2781 double fixedAspectRatio = 0.0;
2782 spinWidth->blockSignals( true );
2783 if ( defaultAspectRatio <= 0.0 )
2784 {
2785 spinWidth->setValue( spinHeight->value() );
2786 }
2787 else if ( mLockAspectRatio->locked() )
2788 {
2789 spinWidth->setValue( spinHeight->value() / defaultAspectRatio );
2790 }
2791 else
2792 {
2793 fixedAspectRatio = spinHeight->value() / spinWidth->value();
2794 }
2795 spinWidth->blockSignals( false );
2796 mLayer->setSize( spinWidth->value() );
2797 mLayer->setFixedAspectRatio( fixedAspectRatio );
2798 emit changed();
2799}
2800
2801void QgsSvgMarkerSymbolLayerWidget::lockAspectRatioChanged( const bool locked )
2802{
2803 //spinHeight->setEnabled( !locked );
2804 const double defaultAspectRatio = mLayer->defaultAspectRatio();
2805 if ( defaultAspectRatio <= 0.0 )
2806 {
2807 whileBlocking( mLockAspectRatio )->setLocked( true );
2808 }
2809 else if ( locked )
2810 {
2811 mLayer->setFixedAspectRatio( 0.0 );
2812 setWidth();
2813 }
2814 else
2815 {
2816 mLayer->setFixedAspectRatio( spinHeight->value() / spinWidth->value() );
2817 }
2818 //emit changed();
2819}
2820
2821void QgsSvgMarkerSymbolLayerWidget::setAngle()
2822{
2823 mLayer->setAngle( spinAngle->value() );
2824 emit changed();
2825}
2826
2827void QgsSvgMarkerSymbolLayerWidget::setOffset()
2828{
2829 mLayer->setOffset( QPointF( spinOffsetX->value(), spinOffsetY->value() ) );
2830 emit changed();
2831}
2832
2833void QgsSvgMarkerSymbolLayerWidget::svgSourceChanged( const QString &text )
2834{
2835 mLayer->setPath( text );
2837 emit changed();
2838}
2839
2840void QgsSvgMarkerSymbolLayerWidget::mChangeColorButton_colorChanged( const QColor &color )
2841{
2842 if ( !mLayer )
2843 {
2844 return;
2845 }
2846
2847 mLayer->setFillColor( color );
2848 emit changed();
2849}
2850
2851void QgsSvgMarkerSymbolLayerWidget::mChangeStrokeColorButton_colorChanged( const QColor &color )
2852{
2853 if ( !mLayer )
2854 {
2855 return;
2856 }
2857
2858 mLayer->setStrokeColor( color );
2859 emit changed();
2860}
2861
2862void QgsSvgMarkerSymbolLayerWidget::mStrokeWidthSpinBox_valueChanged( double d )
2863{
2864 if ( mLayer )
2865 {
2866 mLayer->setStrokeWidth( d );
2867 emit changed();
2868 }
2869}
2870
2871void QgsSvgMarkerSymbolLayerWidget::mSizeUnitWidget_changed()
2872{
2873 if ( mLayer )
2874 {
2875 mLayer->setSizeUnit( mSizeUnitWidget->unit() );
2876 mLayer->setSizeMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
2877 emit changed();
2878 }
2879}
2880
2881void QgsSvgMarkerSymbolLayerWidget::mStrokeWidthUnitWidget_changed()
2882{
2883 if ( mLayer )
2884 {
2885 mLayer->setStrokeWidthUnit( mStrokeWidthUnitWidget->unit() );
2886 mLayer->setStrokeWidthMapUnitScale( mStrokeWidthUnitWidget->getMapUnitScale() );
2887 emit changed();
2888 }
2889}
2890
2891void QgsSvgMarkerSymbolLayerWidget::mOffsetUnitWidget_changed()
2892{
2893 if ( mLayer )
2894 {
2895 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
2896 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
2897 emit changed();
2898 }
2899}
2900
2901void QgsSvgMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged( int )
2902{
2903 if ( mLayer )
2904 {
2905 mLayer->setHorizontalAnchorPoint( mHorizontalAnchorComboBox->currentData().value< Qgis::HorizontalAnchorPoint >() );
2906 emit changed();
2907 }
2908}
2909
2910void QgsSvgMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged( int )
2911{
2912 if ( mLayer )
2913 {
2914 mLayer->setVerticalAnchorPoint( mVerticalAnchorComboBox->currentData().value< Qgis::VerticalAnchorPoint >() );
2915 emit changed();
2916 }
2917}
2918
2920
2922 : QgsSymbolLayerWidget( parent, vl )
2923{
2924 mLayer = nullptr;
2925 setupUi( this );
2926
2927 mSvgSelectorWidget->setAllowParameters( true );
2928 mSvgSelectorWidget->sourceLineEdit()->setPropertyOverrideToolButtonVisible( true );
2929
2930 connect( mTextureWidthSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSVGFillSymbolLayerWidget::mTextureWidthSpinBox_valueChanged );
2931 connect( mSvgSelectorWidget->sourceLineEdit(), &QgsSvgSourceLineEdit::sourceChanged, this, &QgsSVGFillSymbolLayerWidget::svgSourceChanged );
2932 connect( mRotationSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSVGFillSymbolLayerWidget::mRotationSpinBox_valueChanged );
2933 connect( mChangeColorButton, &QgsColorButton::colorChanged, this, &QgsSVGFillSymbolLayerWidget::mChangeColorButton_colorChanged );
2934 connect( mChangeStrokeColorButton, &QgsColorButton::colorChanged, this, &QgsSVGFillSymbolLayerWidget::mChangeStrokeColorButton_colorChanged );
2935 connect( mStrokeWidthSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSVGFillSymbolLayerWidget::mStrokeWidthSpinBox_valueChanged );
2936 connect( mTextureWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSVGFillSymbolLayerWidget::mTextureWidthUnitWidget_changed );
2937 connect( mSvgStrokeWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSVGFillSymbolLayerWidget::mSvgStrokeWidthUnitWidget_changed );
2938 mTextureWidthUnitWidget->setUnits(
2940 );
2941 mSvgStrokeWidthUnitWidget->setUnits(
2943 );
2944
2945 mRotationSpinBox->setClearValue( 0.0 );
2946
2947 mChangeColorButton->setColorDialogTitle( tr( "Select Fill Color" ) );
2948 mChangeColorButton->setContext( u"symbology"_s );
2949 mChangeStrokeColorButton->setColorDialogTitle( tr( "Select Stroke Color" ) );
2950 mChangeStrokeColorButton->setContext( u"symbology"_s );
2951
2952 mFilColorDDBtn->registerLinkedWidget( mChangeColorButton );
2953 mStrokeColorDDBtn->registerLinkedWidget( mChangeStrokeColorButton );
2954
2955 connect( mSvgSelectorWidget, &QgsSvgSelectorWidget::svgSelected, this, &QgsSVGFillSymbolLayerWidget::setFile );
2956 connect( mSvgSelectorWidget, &QgsSvgSelectorWidget::svgParametersChanged, this, &QgsSVGFillSymbolLayerWidget::setSvgParameters );
2957}
2958
2960{
2961 if ( !layer )
2962 {
2963 return;
2964 }
2965
2966 if ( layer->layerType() != "SVGFill"_L1 )
2967 {
2968 return;
2969 }
2970
2971 mLayer = dynamic_cast<QgsSVGFillSymbolLayer *>( layer );
2972 if ( mLayer )
2973 {
2974 const double width = mLayer->patternWidth();
2975 mTextureWidthSpinBox->blockSignals( true );
2976 mTextureWidthSpinBox->setValue( width );
2977 mTextureWidthSpinBox->blockSignals( false );
2978 whileBlocking( mSvgSelectorWidget->sourceLineEdit() )->setSource( mLayer->svgFilePath() );
2979 mRotationSpinBox->blockSignals( true );
2980 mRotationSpinBox->setValue( mLayer->angle() );
2981 mRotationSpinBox->blockSignals( false );
2982 mTextureWidthUnitWidget->blockSignals( true );
2983 mTextureWidthUnitWidget->setUnit( mLayer->patternWidthUnit() );
2984 mTextureWidthUnitWidget->setMapUnitScale( mLayer->patternWidthMapUnitScale() );
2985 mTextureWidthUnitWidget->blockSignals( false );
2986 mSvgStrokeWidthUnitWidget->blockSignals( true );
2987 mSvgStrokeWidthUnitWidget->setUnit( mLayer->svgStrokeWidthUnit() );
2988 mSvgStrokeWidthUnitWidget->setMapUnitScale( mLayer->svgStrokeWidthMapUnitScale() );
2989 mSvgStrokeWidthUnitWidget->blockSignals( false );
2990 mChangeColorButton->blockSignals( true );
2991 mChangeColorButton->setColor( mLayer->svgFillColor() );
2992 mChangeColorButton->blockSignals( false );
2993 mChangeStrokeColorButton->blockSignals( true );
2994 mChangeStrokeColorButton->setColor( mLayer->svgStrokeColor() );
2995 mChangeStrokeColorButton->blockSignals( false );
2996 mStrokeWidthSpinBox->blockSignals( true );
2997 mStrokeWidthSpinBox->setValue( mLayer->svgStrokeWidth() );
2998 mStrokeWidthSpinBox->blockSignals( false );
2999 }
3000 updateParamGui( false );
3001
3007
3008 registerDataDefinedButton( mSvgSelectorWidget->sourceLineEdit()->propertyOverrideToolButton(), QgsSymbolLayer::Property::File );
3009}
3010
3015
3017{
3019 mSvgSelectorWidget->sourceLineEdit()->setMessageBar( context.messageBar() );
3020}
3021
3022void QgsSVGFillSymbolLayerWidget::mTextureWidthSpinBox_valueChanged( double d )
3023{
3024 if ( mLayer )
3025 {
3026 mLayer->setPatternWidth( d );
3027 emit changed();
3028 }
3029}
3030
3031void QgsSVGFillSymbolLayerWidget::svgSourceChanged( const QString &text )
3032{
3033 if ( !mLayer )
3034 {
3035 return;
3036 }
3037
3038 mLayer->setSvgFilePath( text );
3040 emit changed();
3041}
3042
3043void QgsSVGFillSymbolLayerWidget::setFile( const QString &name )
3044{
3045 mLayer->setSvgFilePath( name );
3046 whileBlocking( mSvgSelectorWidget->sourceLineEdit() )->setSource( name );
3047
3049 emit changed();
3050}
3051
3052void QgsSVGFillSymbolLayerWidget::setSvgParameters( const QMap<QString, QgsProperty> &parameters )
3053{
3054 mLayer->setParameters( parameters );
3055 whileBlocking( mSvgSelectorWidget )->setSvgParameters( parameters );
3056
3058 emit changed();
3059}
3060
3061
3062void QgsSVGFillSymbolLayerWidget::mRotationSpinBox_valueChanged( double d )
3063{
3064 if ( mLayer )
3065 {
3066 mLayer->setAngle( d );
3067 emit changed();
3068 }
3069}
3070
3072{
3073 //activate gui for svg parameters only if supported by the svg file
3074 bool hasFillParam, hasFillOpacityParam, hasStrokeParam, hasStrokeWidthParam, hasStrokeOpacityParam;
3075 QColor defaultFill, defaultStroke;
3076 double defaultStrokeWidth, defaultFillOpacity, defaultStrokeOpacity;
3077 bool hasDefaultFillColor, hasDefaultFillOpacity, hasDefaultStrokeColor, hasDefaultStrokeWidth, hasDefaultStrokeOpacity;
3079 mSvgSelectorWidget->sourceLineEdit()->source(),
3080 hasFillParam,
3081 hasDefaultFillColor,
3082 defaultFill,
3083 hasFillOpacityParam,
3084 hasDefaultFillOpacity,
3085 defaultFillOpacity,
3086 hasStrokeParam,
3087 hasDefaultStrokeColor,
3088 defaultStroke,
3089 hasStrokeWidthParam,
3090 hasDefaultStrokeWidth,
3091 defaultStrokeWidth,
3092 hasStrokeOpacityParam,
3093 hasDefaultStrokeOpacity,
3094 defaultStrokeOpacity
3095 );
3096 if ( resetValues )
3097 {
3098 QColor fill = mChangeColorButton->color();
3099 const double newOpacity = hasFillOpacityParam ? fill.alphaF() : 1.0;
3100 if ( hasDefaultFillColor )
3101 {
3102 fill = defaultFill;
3103 }
3104 fill.setAlphaF( hasDefaultFillOpacity ? defaultFillOpacity : newOpacity );
3105 mChangeColorButton->setColor( fill );
3106 }
3107 mChangeColorButton->setEnabled( hasFillParam );
3108 mChangeColorButton->setAllowOpacity( hasFillOpacityParam );
3109 if ( resetValues )
3110 {
3111 QColor stroke = mChangeStrokeColorButton->color();
3112 const double newOpacity = hasStrokeOpacityParam ? stroke.alphaF() : 1.0;
3113 if ( hasDefaultStrokeColor )
3114 {
3115 stroke = defaultStroke;
3116 }
3117 stroke.setAlphaF( hasDefaultStrokeOpacity ? defaultStrokeOpacity : newOpacity );
3118 mChangeStrokeColorButton->setColor( stroke );
3119 }
3120 mChangeStrokeColorButton->setEnabled( hasStrokeParam );
3121 mChangeStrokeColorButton->setAllowOpacity( hasStrokeOpacityParam );
3122 if ( hasDefaultStrokeWidth && resetValues )
3123 {
3124 mStrokeWidthSpinBox->setValue( defaultStrokeWidth );
3125 }
3126 mStrokeWidthSpinBox->setEnabled( hasStrokeWidthParam );
3127}
3128
3129void QgsSVGFillSymbolLayerWidget::mChangeColorButton_colorChanged( const QColor &color )
3130{
3131 if ( !mLayer )
3132 {
3133 return;
3134 }
3135
3136 mLayer->setSvgFillColor( color );
3137 emit changed();
3138}
3139
3140void QgsSVGFillSymbolLayerWidget::mChangeStrokeColorButton_colorChanged( const QColor &color )
3141{
3142 if ( !mLayer )
3143 {
3144 return;
3145 }
3146
3147 mLayer->setSvgStrokeColor( color );
3148 emit changed();
3149}
3150
3151void QgsSVGFillSymbolLayerWidget::mStrokeWidthSpinBox_valueChanged( double d )
3152{
3153 if ( mLayer )
3154 {
3155 mLayer->setSvgStrokeWidth( d );
3156 emit changed();
3157 }
3158}
3159
3160void QgsSVGFillSymbolLayerWidget::mTextureWidthUnitWidget_changed()
3161{
3162 if ( mLayer )
3163 {
3164 mLayer->setPatternWidthUnit( mTextureWidthUnitWidget->unit() );
3165 mLayer->setPatternWidthMapUnitScale( mTextureWidthUnitWidget->getMapUnitScale() );
3166 emit changed();
3167 }
3168}
3169
3170void QgsSVGFillSymbolLayerWidget::mSvgStrokeWidthUnitWidget_changed()
3171{
3172 if ( mLayer )
3173 {
3174 mLayer->setSvgStrokeWidthUnit( mSvgStrokeWidthUnitWidget->unit() );
3175 mLayer->setSvgStrokeWidthMapUnitScale( mSvgStrokeWidthUnitWidget->getMapUnitScale() );
3176 emit changed();
3177 }
3178}
3179
3181
3183 : QgsSymbolLayerWidget( parent, vl )
3184{
3185 setupUi( this );
3186 connect( mAngleSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsLinePatternFillSymbolLayerWidget::mAngleSpinBox_valueChanged );
3187 connect( mDistanceSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsLinePatternFillSymbolLayerWidget::mDistanceSpinBox_valueChanged );
3188 connect( mOffsetSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsLinePatternFillSymbolLayerWidget::mOffsetSpinBox_valueChanged );
3189 connect( mDistanceUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsLinePatternFillSymbolLayerWidget::mDistanceUnitWidget_changed );
3190 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsLinePatternFillSymbolLayerWidget::mOffsetUnitWidget_changed );
3191 mDistanceUnitWidget->setUnits(
3193 );
3194 mOffsetUnitWidget->setUnits(
3203 );
3204 mOffsetSpinBox->setClearValue( 0 );
3205 mAngleSpinBox->setClearValue( 0 );
3206
3207 mCoordinateReferenceComboBox->addItem( tr( "Align Pattern to Feature" ), static_cast<int>( Qgis::SymbolCoordinateReference::Feature ) );
3208 mCoordinateReferenceComboBox->addItem( tr( "Align Pattern to Map Extent" ), static_cast<int>( Qgis::SymbolCoordinateReference::Viewport ) );
3209 connect( mCoordinateReferenceComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this] {
3210 if ( mLayer )
3211 {
3212 mLayer->setCoordinateReference( static_cast<Qgis::SymbolCoordinateReference>( mCoordinateReferenceComboBox->currentData().toInt() ) );
3213 emit changed();
3214 }
3215 } );
3216
3217 mClipModeComboBox->addItem( tr( "Clip During Render Only" ), static_cast<int>( Qgis::LineClipMode::ClipPainterOnly ) );
3218 mClipModeComboBox->addItem( tr( "Clip Lines Before Render" ), static_cast<int>( Qgis::LineClipMode::ClipToIntersection ) );
3219 mClipModeComboBox->addItem( tr( "No Clipping" ), static_cast<int>( Qgis::LineClipMode::NoClipping ) );
3220 connect( mClipModeComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this] {
3221 if ( mLayer )
3222 {
3223 mLayer->setClipMode( static_cast<Qgis::LineClipMode>( mClipModeComboBox->currentData().toInt() ) );
3224 emit changed();
3225 }
3226 } );
3227}
3228
3230{
3231 if ( layer->layerType() != "LinePatternFill"_L1 )
3232 {
3233 return;
3234 }
3235
3236 QgsLinePatternFillSymbolLayer *patternLayer = static_cast<QgsLinePatternFillSymbolLayer *>( layer );
3237 if ( patternLayer )
3238 {
3239 mLayer = patternLayer;
3240 whileBlocking( mAngleSpinBox )->setValue( mLayer->lineAngle() );
3241 whileBlocking( mDistanceSpinBox )->setValue( mLayer->distance() );
3242 whileBlocking( mOffsetSpinBox )->setValue( mLayer->offset() );
3243
3244 //units
3245 mDistanceUnitWidget->blockSignals( true );
3246 mDistanceUnitWidget->setUnit( mLayer->distanceUnit() );
3247 mDistanceUnitWidget->setMapUnitScale( mLayer->distanceMapUnitScale() );
3248 mDistanceUnitWidget->blockSignals( false );
3249 mOffsetUnitWidget->blockSignals( true );
3250 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
3251 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
3252 mOffsetUnitWidget->blockSignals( false );
3253
3254 whileBlocking( mCoordinateReferenceComboBox )->setCurrentIndex( mCoordinateReferenceComboBox->findData( static_cast<int>( mLayer->coordinateReference() ) ) );
3255
3256 whileBlocking( mClipModeComboBox )->setCurrentIndex( mClipModeComboBox->findData( static_cast<int>( mLayer->clipMode() ) ) );
3257 }
3258
3263}
3264
3269
3270void QgsLinePatternFillSymbolLayerWidget::mAngleSpinBox_valueChanged( double d )
3271{
3272 if ( mLayer )
3273 {
3274 mLayer->setLineAngle( d );
3275 emit changed();
3276 }
3277}
3278
3279void QgsLinePatternFillSymbolLayerWidget::mDistanceSpinBox_valueChanged( double d )
3280{
3281 if ( mLayer )
3282 {
3283 mLayer->setDistance( d );
3284 emit changed();
3285 }
3286}
3287
3288void QgsLinePatternFillSymbolLayerWidget::mOffsetSpinBox_valueChanged( double d )
3289{
3290 if ( mLayer )
3291 {
3292 mLayer->setOffset( d );
3293 emit changed();
3294 }
3295}
3296
3297void QgsLinePatternFillSymbolLayerWidget::mDistanceUnitWidget_changed()
3298{
3299 if ( mLayer )
3300 {
3301 mLayer->setDistanceUnit( mDistanceUnitWidget->unit() );
3302 mLayer->setDistanceMapUnitScale( mDistanceUnitWidget->getMapUnitScale() );
3303 emit changed();
3304 }
3305}
3306
3307void QgsLinePatternFillSymbolLayerWidget::mOffsetUnitWidget_changed()
3308{
3309 if ( mLayer )
3310 {
3311 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
3312 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
3313 emit changed();
3314 }
3315}
3316
3318
3320 : QgsSymbolLayerWidget( parent, vl )
3321{
3322 setupUi( this );
3323 connect( mHorizontalDistanceSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsPointPatternFillSymbolLayerWidget::mHorizontalDistanceSpinBox_valueChanged );
3324 connect( mVerticalDistanceSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsPointPatternFillSymbolLayerWidget::mVerticalDistanceSpinBox_valueChanged );
3325 connect( mHorizontalDisplacementSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsPointPatternFillSymbolLayerWidget::mHorizontalDisplacementSpinBox_valueChanged );
3326 connect( mVerticalDisplacementSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsPointPatternFillSymbolLayerWidget::mVerticalDisplacementSpinBox_valueChanged );
3327 connect( mHorizontalOffsetSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsPointPatternFillSymbolLayerWidget::mHorizontalOffsetSpinBox_valueChanged );
3328 connect( mVerticalOffsetSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsPointPatternFillSymbolLayerWidget::mVerticalOffsetSpinBox_valueChanged );
3329 connect( mHorizontalDistanceUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointPatternFillSymbolLayerWidget::mHorizontalDistanceUnitWidget_changed );
3330 connect( mVerticalDistanceUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointPatternFillSymbolLayerWidget::mVerticalDistanceUnitWidget_changed );
3331 connect( mHorizontalDisplacementUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointPatternFillSymbolLayerWidget::mHorizontalDisplacementUnitWidget_changed );
3332 connect( mVerticalDisplacementUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointPatternFillSymbolLayerWidget::mVerticalDisplacementUnitWidget_changed );
3333 connect( mHorizontalOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointPatternFillSymbolLayerWidget::mHorizontalOffsetUnitWidget_changed );
3334 connect( mVerticalOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointPatternFillSymbolLayerWidget::mVerticalOffsetUnitWidget_changed );
3335 mHorizontalDistanceUnitWidget->setUnits(
3337 );
3338 mVerticalDistanceUnitWidget->setUnits(
3340 );
3341 mHorizontalDisplacementUnitWidget->setUnits(
3350 );
3351 mVerticalDisplacementUnitWidget->setUnits(
3360 );
3361 mHorizontalOffsetUnitWidget->setUnits(
3370 );
3371 mVerticalOffsetUnitWidget->setUnits(
3380 );
3381
3382 mClipModeComboBox->addItem( tr( "Clip to Shape" ), static_cast<int>( Qgis::MarkerClipMode::Shape ) );
3383 mClipModeComboBox->addItem( tr( "Marker Centroid Within Shape" ), static_cast<int>( Qgis::MarkerClipMode::CentroidWithin ) );
3384 mClipModeComboBox->addItem( tr( "Marker Completely Within Shape" ), static_cast<int>( Qgis::MarkerClipMode::CompletelyWithin ) );
3385 mClipModeComboBox->addItem( tr( "No Clipping" ), static_cast<int>( Qgis::MarkerClipMode::NoClipping ) );
3386 connect( mClipModeComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this] {
3387 if ( mLayer )
3388 {
3389 mLayer->setClipMode( static_cast<Qgis::MarkerClipMode>( mClipModeComboBox->currentData().toInt() ) );
3390 emit changed();
3391 }
3392 } );
3393
3394 mCoordinateReferenceComboBox->addItem( tr( "Align Pattern to Feature" ), static_cast<int>( Qgis::SymbolCoordinateReference::Feature ) );
3395 mCoordinateReferenceComboBox->addItem( tr( "Align Pattern to Map Extent" ), static_cast<int>( Qgis::SymbolCoordinateReference::Viewport ) );
3396 connect( mCoordinateReferenceComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this] {
3397 if ( mLayer )
3398 {
3399 mLayer->setCoordinateReference( static_cast<Qgis::SymbolCoordinateReference>( mCoordinateReferenceComboBox->currentData().toInt() ) );
3400 emit changed();
3401 }
3402 } );
3403
3404 mSeedSpinBox->setShowClearButton( true );
3405 mSeedSpinBox->setClearValue( 0 );
3406 mRandomXSpinBox->setClearValue( 0 );
3407 mRandomYSpinBox->setClearValue( 0 );
3408
3409 mRandomXOffsetUnitWidget->setUnits(
3418 );
3419 mRandomYOffsetUnitWidget->setUnits(
3428 );
3429 connect( mRandomXSpinBox, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double d ) {
3430 if ( mLayer )
3431 {
3432 mLayer->setMaximumRandomDeviationX( d );
3433 emit changed();
3434 }
3435 } );
3436 connect( mRandomYSpinBox, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double d ) {
3437 if ( mLayer )
3438 {
3439 mLayer->setMaximumRandomDeviationY( d );
3440 emit changed();
3441 }
3442 } );
3443 connect( mRandomXOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
3444 if ( mLayer )
3445 {
3446 mLayer->setRandomDeviationXUnit( mRandomXOffsetUnitWidget->unit() );
3447 mLayer->setRandomDeviationXMapUnitScale( mRandomXOffsetUnitWidget->getMapUnitScale() );
3448 emit changed();
3449 }
3450 } );
3451 connect( mRandomYOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
3452 if ( mLayer )
3453 {
3454 mLayer->setRandomDeviationYUnit( mRandomYOffsetUnitWidget->unit() );
3455 mLayer->setRandomDeviationYMapUnitScale( mRandomYOffsetUnitWidget->getMapUnitScale() );
3456 emit changed();
3457 }
3458 } );
3459 connect( mSeedSpinBox, qOverload<int>( &QSpinBox::valueChanged ), this, [this]( int v ) {
3460 if ( mLayer )
3461 {
3462 mLayer->setSeed( v );
3463 emit changed();
3464 }
3465 } );
3466
3467 mAngleSpinBox->setShowClearButton( true );
3468 mAngleSpinBox->setClearValue( 0 );
3469 connect( mAngleSpinBox, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double d ) {
3470 if ( mLayer )
3471 {
3472 mLayer->setAngle( d );
3473 emit changed();
3474 }
3475 } );
3476}
3477
3479{
3480 if ( !layer || layer->layerType() != "PointPatternFill"_L1 )
3481 {
3482 return;
3483 }
3484
3485 mLayer = static_cast<QgsPointPatternFillSymbolLayer *>( layer );
3486 whileBlocking( mHorizontalDistanceSpinBox )->setValue( mLayer->distanceX() );
3487 whileBlocking( mVerticalDistanceSpinBox )->setValue( mLayer->distanceY() );
3488 whileBlocking( mHorizontalDisplacementSpinBox )->setValue( mLayer->displacementX() );
3489 whileBlocking( mVerticalDisplacementSpinBox )->setValue( mLayer->displacementY() );
3490 whileBlocking( mHorizontalOffsetSpinBox )->setValue( mLayer->offsetX() );
3491 whileBlocking( mVerticalOffsetSpinBox )->setValue( mLayer->offsetY() );
3492 whileBlocking( mAngleSpinBox )->setValue( mLayer->angle() );
3493
3494 mHorizontalDistanceUnitWidget->blockSignals( true );
3495 mHorizontalDistanceUnitWidget->setUnit( mLayer->distanceXUnit() );
3496 mHorizontalDistanceUnitWidget->setMapUnitScale( mLayer->distanceXMapUnitScale() );
3497 mHorizontalDistanceUnitWidget->blockSignals( false );
3498 mVerticalDistanceUnitWidget->blockSignals( true );
3499 mVerticalDistanceUnitWidget->setUnit( mLayer->distanceYUnit() );
3500 mVerticalDistanceUnitWidget->setMapUnitScale( mLayer->distanceYMapUnitScale() );
3501 mVerticalDistanceUnitWidget->blockSignals( false );
3502 mHorizontalDisplacementUnitWidget->blockSignals( true );
3503 mHorizontalDisplacementUnitWidget->setUnit( mLayer->displacementXUnit() );
3504 mHorizontalDisplacementUnitWidget->setMapUnitScale( mLayer->displacementXMapUnitScale() );
3505 mHorizontalDisplacementUnitWidget->blockSignals( false );
3506 mVerticalDisplacementUnitWidget->blockSignals( true );
3507 mVerticalDisplacementUnitWidget->setUnit( mLayer->displacementYUnit() );
3508 mVerticalDisplacementUnitWidget->setMapUnitScale( mLayer->displacementYMapUnitScale() );
3509 mVerticalDisplacementUnitWidget->blockSignals( false );
3510 mHorizontalOffsetUnitWidget->blockSignals( true );
3511 mHorizontalOffsetUnitWidget->setUnit( mLayer->offsetXUnit() );
3512 mHorizontalOffsetUnitWidget->setMapUnitScale( mLayer->offsetXMapUnitScale() );
3513 mHorizontalOffsetUnitWidget->blockSignals( false );
3514 mVerticalOffsetUnitWidget->blockSignals( true );
3515 mVerticalOffsetUnitWidget->setUnit( mLayer->offsetYUnit() );
3516 mVerticalOffsetUnitWidget->setMapUnitScale( mLayer->offsetYMapUnitScale() );
3517 mVerticalOffsetUnitWidget->blockSignals( false );
3518
3519 whileBlocking( mClipModeComboBox )->setCurrentIndex( mClipModeComboBox->findData( static_cast<int>( mLayer->clipMode() ) ) );
3520 whileBlocking( mCoordinateReferenceComboBox )->setCurrentIndex( mCoordinateReferenceComboBox->findData( static_cast<int>( mLayer->coordinateReference() ) ) );
3521
3522 whileBlocking( mRandomXSpinBox )->setValue( mLayer->maximumRandomDeviationX() );
3523 whileBlocking( mRandomYSpinBox )->setValue( mLayer->maximumRandomDeviationY() );
3524 whileBlocking( mRandomXOffsetUnitWidget )->setUnit( mLayer->randomDeviationXUnit() );
3525 whileBlocking( mRandomXOffsetUnitWidget )->setMapUnitScale( mLayer->randomDeviationXMapUnitScale() );
3526 whileBlocking( mRandomYOffsetUnitWidget )->setUnit( mLayer->randomDeviationYUnit() );
3527 whileBlocking( mRandomYOffsetUnitWidget )->setMapUnitScale( mLayer->randomDeviationYMapUnitScale() );
3528 whileBlocking( mSeedSpinBox )->setValue( mLayer->seed() );
3529
3542}
3543
3548
3549void QgsPointPatternFillSymbolLayerWidget::mHorizontalDistanceSpinBox_valueChanged( double d )
3550{
3551 if ( mLayer )
3552 {
3553 mLayer->setDistanceX( d );
3554 emit changed();
3555 }
3556}
3557
3558void QgsPointPatternFillSymbolLayerWidget::mVerticalDistanceSpinBox_valueChanged( double d )
3559{
3560 if ( mLayer )
3561 {
3562 mLayer->setDistanceY( d );
3563 emit changed();
3564 }
3565}
3566
3567void QgsPointPatternFillSymbolLayerWidget::mHorizontalDisplacementSpinBox_valueChanged( double d )
3568{
3569 if ( mLayer )
3570 {
3571 mLayer->setDisplacementX( d );
3572 emit changed();
3573 }
3574}
3575
3576void QgsPointPatternFillSymbolLayerWidget::mVerticalDisplacementSpinBox_valueChanged( double d )
3577{
3578 if ( mLayer )
3579 {
3580 mLayer->setDisplacementY( d );
3581 emit changed();
3582 }
3583}
3584
3585void QgsPointPatternFillSymbolLayerWidget::mHorizontalOffsetSpinBox_valueChanged( double d )
3586{
3587 if ( mLayer )
3588 {
3589 mLayer->setOffsetX( d );
3590 emit changed();
3591 }
3592}
3593
3594void QgsPointPatternFillSymbolLayerWidget::mVerticalOffsetSpinBox_valueChanged( double d )
3595{
3596 if ( mLayer )
3597 {
3598 mLayer->setOffsetY( d );
3599 emit changed();
3600 }
3601}
3602
3603void QgsPointPatternFillSymbolLayerWidget::mHorizontalDistanceUnitWidget_changed()
3604{
3605 if ( mLayer )
3606 {
3607 mLayer->setDistanceXUnit( mHorizontalDistanceUnitWidget->unit() );
3608 mLayer->setDistanceXMapUnitScale( mHorizontalDistanceUnitWidget->getMapUnitScale() );
3609 emit changed();
3610 }
3611}
3612
3613void QgsPointPatternFillSymbolLayerWidget::mVerticalDistanceUnitWidget_changed()
3614{
3615 if ( mLayer )
3616 {
3617 mLayer->setDistanceYUnit( mVerticalDistanceUnitWidget->unit() );
3618 mLayer->setDistanceYMapUnitScale( mVerticalDistanceUnitWidget->getMapUnitScale() );
3619 emit changed();
3620 }
3621}
3622
3623void QgsPointPatternFillSymbolLayerWidget::mHorizontalDisplacementUnitWidget_changed()
3624{
3625 if ( mLayer )
3626 {
3627 mLayer->setDisplacementXUnit( mHorizontalDisplacementUnitWidget->unit() );
3628 mLayer->setDisplacementXMapUnitScale( mHorizontalDisplacementUnitWidget->getMapUnitScale() );
3629 emit changed();
3630 }
3631}
3632
3633void QgsPointPatternFillSymbolLayerWidget::mVerticalDisplacementUnitWidget_changed()
3634{
3635 if ( mLayer )
3636 {
3637 mLayer->setDisplacementYUnit( mVerticalDisplacementUnitWidget->unit() );
3638 mLayer->setDisplacementYMapUnitScale( mVerticalDisplacementUnitWidget->getMapUnitScale() );
3639 emit changed();
3640 }
3641}
3642
3643void QgsPointPatternFillSymbolLayerWidget::mHorizontalOffsetUnitWidget_changed()
3644{
3645 if ( mLayer )
3646 {
3647 mLayer->setOffsetXUnit( mHorizontalOffsetUnitWidget->unit() );
3648 mLayer->setOffsetXMapUnitScale( mHorizontalOffsetUnitWidget->getMapUnitScale() );
3649 emit changed();
3650 }
3651}
3652
3653void QgsPointPatternFillSymbolLayerWidget::mVerticalOffsetUnitWidget_changed()
3654{
3655 if ( mLayer )
3656 {
3657 mLayer->setOffsetYUnit( mVerticalOffsetUnitWidget->unit() );
3658 mLayer->setOffsetYMapUnitScale( mVerticalOffsetUnitWidget->getMapUnitScale() );
3659 emit changed();
3660 }
3661}
3662
3664
3666 : QgsSymbolLayerWidget( parent, vl )
3667{
3668 mLayer = nullptr;
3669
3670 setupUi( this );
3671
3672 mHorizontalAnchorComboBox->addItem( tr( "Left" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Left ) );
3673 mHorizontalAnchorComboBox->addItem( tr( "Horizontal Center" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Center ) );
3674 mHorizontalAnchorComboBox->addItem( tr( "Right" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Right ) );
3675
3676 mVerticalAnchorComboBox->addItem( tr( "Top" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Top ) );
3677 mVerticalAnchorComboBox->addItem( tr( "Vertical Center" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Center ) );
3678 mVerticalAnchorComboBox->addItem( tr( "Bottom on Baseline" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Baseline ) );
3679 mVerticalAnchorComboBox->addItem( tr( "Bottom" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Bottom ) );
3680
3681 connect( mSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsFontMarkerSymbolLayerWidget::mSizeUnitWidget_changed );
3682 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsFontMarkerSymbolLayerWidget::mOffsetUnitWidget_changed );
3683 connect( mStrokeWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsFontMarkerSymbolLayerWidget::mStrokeWidthUnitWidget_changed );
3684 connect( mStrokeWidthSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsFontMarkerSymbolLayerWidget::mStrokeWidthSpinBox_valueChanged );
3685 connect( mHorizontalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsFontMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged );
3686 connect( mVerticalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsFontMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged );
3687 mSizeUnitWidget->setUnits(
3689 );
3690 mStrokeWidthUnitWidget->setUnits(
3692 );
3693 mOffsetUnitWidget->setUnits(
3695 );
3696
3698 scrollArea->setWidget( widgetChar );
3699 scrollArea->setVerticalOnly( true );
3700
3701 btnColor->setAllowOpacity( true );
3702 btnColor->setColorDialogTitle( tr( "Select Symbol Fill Color" ) );
3703 btnColor->setContext( u"symbology"_s );
3704 btnStrokeColor->setAllowOpacity( true );
3705 btnStrokeColor->setColorDialogTitle( tr( "Select Symbol Stroke Color" ) );
3706 btnStrokeColor->setContext( u"symbology"_s );
3707
3708 mColorDDBtn->registerLinkedWidget( btnColor );
3709 mStrokeColorDDBtn->registerLinkedWidget( btnStrokeColor );
3710
3711 spinOffsetX->setClearValue( 0.0 );
3712 spinOffsetY->setClearValue( 0.0 );
3713 spinAngle->setClearValue( 0.0 );
3714
3715 //make a temporary symbol for the size assistant preview
3716 mAssistantPreviewSymbol = std::make_shared<QgsMarkerSymbol>();
3717
3718 if ( vectorLayer() )
3719 mSizeDDBtn->setSymbol( mAssistantPreviewSymbol );
3720
3721 connect( cboFont, &QFontComboBox::currentFontChanged, this, &QgsFontMarkerSymbolLayerWidget::setFontFamily );
3722 connect( mFontStyleComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsFontMarkerSymbolLayerWidget::mFontStyleComboBox_currentIndexChanged );
3723 connect( spinSize, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsFontMarkerSymbolLayerWidget::setSize );
3724 connect( cboJoinStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsFontMarkerSymbolLayerWidget::penJoinStyleChanged );
3727 connect( cboJoinStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsFontMarkerSymbolLayerWidget::penJoinStyleChanged );
3728 connect( spinAngle, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsFontMarkerSymbolLayerWidget::setAngle );
3729 connect( spinOffsetX, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsFontMarkerSymbolLayerWidget::setOffset );
3730 connect( spinOffsetY, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsFontMarkerSymbolLayerWidget::setOffset );
3732 connect( mCharLineEdit, &QLineEdit::textChanged, this, &QgsFontMarkerSymbolLayerWidget::setCharacterFromText );
3733
3734 connect( this, &QgsSymbolLayerWidget::changed, this, &QgsFontMarkerSymbolLayerWidget::updateAssistantSymbol );
3735}
3736
3738
3740{
3741 if ( layer->layerType() != "FontMarker"_L1 )
3742 return;
3743
3744 // layer type is correct, we can do the cast
3745 mLayer = static_cast<QgsFontMarkerSymbolLayer *>( layer );
3746
3747 QgsFontUtils::setFontFamily( mRefFont, mLayer->fontFamily() );
3748 mRefFont.setStyleName( QgsFontUtils::translateNamedStyle( mLayer->fontStyle() ) );
3749
3750 mFontStyleComboBox->blockSignals( true );
3751 populateFontStyleComboBox();
3752 mFontStyleComboBox->blockSignals( false );
3753
3754 // set values
3755 whileBlocking( cboFont )->setCurrentFont( mRefFont );
3756 whileBlocking( spinSize )->setValue( mLayer->size() );
3757 whileBlocking( btnColor )->setColor( mLayer->color() );
3758 whileBlocking( btnStrokeColor )->setColor( mLayer->strokeColor() );
3759 whileBlocking( mStrokeWidthSpinBox )->setValue( mLayer->strokeWidth() );
3760 whileBlocking( spinAngle )->setValue( mLayer->angle() );
3761
3762 widgetChar->blockSignals( true );
3763 widgetChar->setFont( mRefFont );
3764 if ( mLayer->character().length() == 1 )
3765 {
3766 widgetChar->setCharacter( mLayer->character().at( 0 ) );
3767 }
3768 widgetChar->blockSignals( false );
3769 whileBlocking( mCharLineEdit )->setText( mLayer->character() );
3770 mCharPreview->setFont( mRefFont );
3771
3772 //block
3773 whileBlocking( spinOffsetX )->setValue( mLayer->offset().x() );
3774 whileBlocking( spinOffsetY )->setValue( mLayer->offset().y() );
3775
3776 mSizeUnitWidget->blockSignals( true );
3777 mSizeUnitWidget->setUnit( mLayer->sizeUnit() );
3778 mSizeUnitWidget->setMapUnitScale( mLayer->sizeMapUnitScale() );
3779 mSizeUnitWidget->blockSignals( false );
3780
3781 mStrokeWidthUnitWidget->blockSignals( true );
3782 mStrokeWidthUnitWidget->setUnit( mLayer->strokeWidthUnit() );
3783 mStrokeWidthUnitWidget->setMapUnitScale( mLayer->strokeWidthMapUnitScale() );
3784 mStrokeWidthUnitWidget->blockSignals( false );
3785
3786 mOffsetUnitWidget->blockSignals( true );
3787 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
3788 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
3789 mOffsetUnitWidget->blockSignals( false );
3790
3791 whileBlocking( cboJoinStyle )->setPenJoinStyle( mLayer->penJoinStyle() );
3792
3793 //anchor points
3794 whileBlocking( mHorizontalAnchorComboBox )->setCurrentIndex( mHorizontalAnchorComboBox->findData( QVariant::fromValue( mLayer->horizontalAnchorPoint() ) ) );
3795 whileBlocking( mVerticalAnchorComboBox )->setCurrentIndex( mVerticalAnchorComboBox->findData( QVariant::fromValue( mLayer->verticalAnchorPoint() ) ) );
3796
3809
3810 updateAssistantSymbol();
3811}
3812
3817
3819{
3820 if ( mLayer )
3821 {
3822 mLayer->setFontFamily( font.family() );
3823 QgsFontUtils::setFontFamily( mRefFont, font.family() );
3824 widgetChar->setFont( mRefFont );
3825 mCharPreview->setFont( mRefFont );
3826 populateFontStyleComboBox();
3827 emit changed();
3828 }
3829}
3830
3831void QgsFontMarkerSymbolLayerWidget::setFontStyle( const QString &style )
3832{
3833 if ( mLayer )
3834 {
3835 QgsFontUtils::updateFontViaStyle( mRefFont, style );
3837 widgetChar->setFont( mRefFont );
3838 mCharPreview->setFont( mRefFont );
3839 emit changed();
3840 }
3841}
3842
3844{
3845 mLayer->setColor( color );
3846 emit changed();
3847}
3848
3850{
3851 mLayer->setStrokeColor( color );
3852 emit changed();
3853}
3854
3856{
3857 mLayer->setSize( size );
3858 //widgetChar->updateSize(size);
3859 emit changed();
3860}
3861
3863{
3864 mLayer->setAngle( angle );
3865 emit changed();
3866}
3867
3869{
3870 mCharPreview->setText( text );
3871
3872 if ( text.isEmpty() )
3873 return;
3874
3875 // take the last character of a string for a better experience when users cycle through several characters on their keyboard
3876 QString character = text;
3877 if ( text.contains( QRegularExpression( u"^0x[0-9a-fA-F]{1,4}$"_s ) ) )
3878 {
3879 bool ok = false;
3880 const unsigned int value = text.toUInt( &ok, 0 );
3881 if ( ok )
3882 {
3883 character = QChar( value );
3884 mCharPreview->setText( character );
3885 }
3886 }
3887
3888 if ( character != mLayer->character() )
3889 {
3890 mLayer->setCharacter( character );
3891 if ( mLayer->character().length() == 1 )
3892 {
3893 whileBlocking( widgetChar )->setCharacter( mLayer->character().at( 0 ) );
3894 }
3895 else
3896 {
3897 widgetChar->clearCharacter();
3898 }
3899 emit changed();
3900 }
3901}
3902
3904{
3905 if ( mLayer->character().length() > 1 || QGuiApplication::keyboardModifiers() & Qt::ControlModifier )
3906 {
3907 mCharLineEdit->insert( chr );
3908 return;
3909 }
3910
3911 mLayer->setCharacter( chr );
3912 whileBlocking( mCharLineEdit )->setText( chr );
3913 mCharPreview->setText( chr );
3914 emit changed();
3915}
3916
3917void QgsFontMarkerSymbolLayerWidget::setOffset()
3918{
3919 mLayer->setOffset( QPointF( spinOffsetX->value(), spinOffsetY->value() ) );
3920 emit changed();
3921}
3922
3923void QgsFontMarkerSymbolLayerWidget::penJoinStyleChanged()
3924{
3925 mLayer->setPenJoinStyle( cboJoinStyle->penJoinStyle() );
3926 emit changed();
3927}
3928
3929void QgsFontMarkerSymbolLayerWidget::mSizeUnitWidget_changed()
3930{
3931 if ( mLayer )
3932 {
3933 mLayer->setSizeUnit( mSizeUnitWidget->unit() );
3934 mLayer->setSizeMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
3935 emit changed();
3936 }
3937}
3938
3939void QgsFontMarkerSymbolLayerWidget::mOffsetUnitWidget_changed()
3940{
3941 if ( mLayer )
3942 {
3943 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
3944 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
3945 emit changed();
3946 }
3947}
3948
3949void QgsFontMarkerSymbolLayerWidget::mStrokeWidthUnitWidget_changed()
3950{
3951 if ( mLayer )
3952 {
3953 mLayer->setStrokeWidthUnit( mSizeUnitWidget->unit() );
3954 mLayer->setStrokeWidthMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
3955 emit changed();
3956 }
3957}
3958
3959void QgsFontMarkerSymbolLayerWidget::populateFontStyleComboBox()
3960{
3961 mFontStyleComboBox->clear();
3962 const QStringList styles = mFontDB.styles( mRefFont.family() );
3963 const auto constStyles = styles;
3964 for ( const QString &style : constStyles )
3965 {
3966 mFontStyleComboBox->addItem( style );
3967 }
3968
3969 QString targetStyle = mFontDB.styleString( mRefFont );
3970 if ( !styles.contains( targetStyle ) )
3971 {
3972 const QFont f = QgsFontUtils::createFont( mRefFont.family() );
3973 targetStyle = QFontInfo( f ).styleName();
3974 mRefFont.setStyleName( targetStyle );
3975 }
3976 int curIndx = 0;
3977 const int stylIndx = mFontStyleComboBox->findText( targetStyle );
3978 if ( stylIndx > -1 )
3979 {
3980 curIndx = stylIndx;
3981 }
3982
3983 mFontStyleComboBox->setCurrentIndex( curIndx );
3984}
3985
3986void QgsFontMarkerSymbolLayerWidget::mFontStyleComboBox_currentIndexChanged( int index )
3987{
3988 Q_UNUSED( index );
3989 setFontStyle( mFontStyleComboBox->currentText() );
3990}
3991
3992void QgsFontMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged( int )
3993{
3994 if ( mLayer )
3995 {
3996 mLayer->setHorizontalAnchorPoint( mHorizontalAnchorComboBox->currentData().value< Qgis::HorizontalAnchorPoint >() );
3997 emit changed();
3998 }
3999}
4000
4001void QgsFontMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged( int )
4002{
4003 if ( mLayer )
4004 {
4005 mLayer->setVerticalAnchorPoint( mVerticalAnchorComboBox->currentData().value< Qgis::VerticalAnchorPoint >() );
4006 emit changed();
4007 }
4008}
4009
4010void QgsFontMarkerSymbolLayerWidget::mStrokeWidthSpinBox_valueChanged( double d )
4011{
4012 if ( mLayer )
4013 {
4014 mLayer->setStrokeWidth( d );
4015 emit changed();
4016 }
4017}
4018
4019void QgsFontMarkerSymbolLayerWidget::updateAssistantSymbol()
4020{
4021 for ( int i = mAssistantPreviewSymbol->symbolLayerCount() - 1; i >= 0; --i )
4022 {
4023 mAssistantPreviewSymbol->deleteSymbolLayer( i );
4024 }
4025 mAssistantPreviewSymbol->appendSymbolLayer( mLayer->clone() );
4026 const QgsProperty ddSize = mLayer->dataDefinedProperties().property( QgsSymbolLayer::Property::Size );
4027 if ( ddSize )
4028 mAssistantPreviewSymbol->setDataDefinedSize( ddSize );
4029}
4030
4032
4033
4035 : QgsSymbolLayerWidget( parent, vl )
4036{
4037 mLayer = nullptr;
4038
4039 setupUi( this );
4040 connect( mDrawInsideCheckBox, &QCheckBox::stateChanged, this, &QgsCentroidFillSymbolLayerWidget::mDrawInsideCheckBox_stateChanged );
4041 connect( mDrawAllPartsCheckBox, &QCheckBox::stateChanged, this, &QgsCentroidFillSymbolLayerWidget::mDrawAllPartsCheckBox_stateChanged );
4042 connect( mClipPointsCheckBox, &QCheckBox::stateChanged, this, &QgsCentroidFillSymbolLayerWidget::mClipPointsCheckBox_stateChanged );
4043 connect( mClipOnCurrentPartOnlyCheckBox, &QCheckBox::stateChanged, this, &QgsCentroidFillSymbolLayerWidget::mClipOnCurrentPartOnlyCheckBox_stateChanged );
4044}
4045
4047{
4048 if ( layer->layerType() != "CentroidFill"_L1 )
4049 return;
4050
4051 // layer type is correct, we can do the cast
4052 mLayer = static_cast<QgsCentroidFillSymbolLayer *>( layer );
4053
4054 // set values
4055 whileBlocking( mDrawInsideCheckBox )->setChecked( mLayer->pointOnSurface() );
4056 whileBlocking( mDrawAllPartsCheckBox )->setChecked( mLayer->pointOnAllParts() );
4057 whileBlocking( mClipPointsCheckBox )->setChecked( mLayer->clipPoints() );
4058 whileBlocking( mClipOnCurrentPartOnlyCheckBox )->setChecked( mLayer->clipOnCurrentPartOnly() );
4059}
4060
4065
4066void QgsCentroidFillSymbolLayerWidget::mDrawInsideCheckBox_stateChanged( int state )
4067{
4068 mLayer->setPointOnSurface( state == Qt::Checked );
4069 emit changed();
4070}
4071
4072void QgsCentroidFillSymbolLayerWidget::mDrawAllPartsCheckBox_stateChanged( int state )
4073{
4074 mLayer->setPointOnAllParts( state == Qt::Checked );
4075 emit changed();
4076}
4077
4078void QgsCentroidFillSymbolLayerWidget::mClipPointsCheckBox_stateChanged( int state )
4079{
4080 mLayer->setClipPoints( state == Qt::Checked );
4081 emit changed();
4082}
4083
4084void QgsCentroidFillSymbolLayerWidget::mClipOnCurrentPartOnlyCheckBox_stateChanged( int state )
4085{
4086 mLayer->setClipOnCurrentPartOnly( state == Qt::Checked );
4087 emit changed();
4088}
4089
4091
4093 : QgsSymbolLayerWidget( parent, vl )
4094{
4095 mLayer = nullptr;
4096
4097 setupUi( this );
4098
4099 mHorizontalAnchorComboBox->addItem( tr( "Left" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Left ) );
4100 mHorizontalAnchorComboBox->addItem( tr( "Horizontal Center" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Center ) );
4101 mHorizontalAnchorComboBox->addItem( tr( "Right" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Right ) );
4102
4103 mVerticalAnchorComboBox->addItem( tr( "Top" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Top ) );
4104 mVerticalAnchorComboBox->addItem( tr( "Vertical Center" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Center ) );
4105 mVerticalAnchorComboBox->addItem( tr( "Bottom" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Bottom ) );
4106
4107 mImageSourceLineEdit->setLastPathSettingsKey( u"/UI/lastRasterMarkerImageDir"_s );
4108
4109 connect( mImageSourceLineEdit, &QgsImageSourceLineEdit::sourceChanged, this, &QgsRasterMarkerSymbolLayerWidget::imageSourceChanged );
4110 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsRasterMarkerSymbolLayerWidget::mOffsetUnitWidget_changed );
4111 connect( mRotationSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsRasterMarkerSymbolLayerWidget::setAngle );
4112 connect( mSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsRasterMarkerSymbolLayerWidget::mSizeUnitWidget_changed );
4113 connect( mWidthSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsRasterMarkerSymbolLayerWidget::setWidth );
4114 connect( mHeightSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsRasterMarkerSymbolLayerWidget::setHeight );
4115 connect( mLockAspectRatio, static_cast<void ( QgsRatioLockButton::* )( bool )>( &QgsRatioLockButton::lockChanged ), this, &QgsRasterMarkerSymbolLayerWidget::setLockAspectRatio );
4116
4117 mSizeUnitWidget->setUnits(
4126 );
4127 mOffsetUnitWidget->setUnits(
4129 );
4130
4131 mSpinOffsetX->setClearValue( 0.0 );
4132 mSpinOffsetY->setClearValue( 0.0 );
4133 mRotationSpinBox->setClearValue( 0.0 );
4134
4135 connect( mSpinOffsetX, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsRasterMarkerSymbolLayerWidget::setOffset );
4136 connect( mSpinOffsetY, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsRasterMarkerSymbolLayerWidget::setOffset );
4137 connect( mOpacityWidget, &QgsOpacityWidget::opacityChanged, this, &QgsRasterMarkerSymbolLayerWidget::setOpacity );
4138
4139 connect( mHorizontalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsRasterMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged );
4140 connect( mVerticalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsRasterMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged );
4141}
4142
4144{
4145 if ( !layer )
4146 {
4147 return;
4148 }
4149
4150 if ( layer->layerType() != "RasterMarker"_L1 )
4151 return;
4152
4153 // layer type is correct, we can do the cast
4154 mLayer = static_cast<QgsRasterMarkerSymbolLayer *>( layer );
4155
4156 // set values
4157 whileBlocking( mImageSourceLineEdit )->setSource( mLayer->path() );
4158
4159 whileBlocking( mWidthSpinBox )->setValue( mLayer->size() );
4160 const bool preservedAspectRatio = mLayer->preservedAspectRatio();
4161 mHeightSpinBox->blockSignals( true );
4162 if ( preservedAspectRatio )
4163 {
4164 mHeightSpinBox->setValue( mLayer->size() );
4165 }
4166 else
4167 {
4168 mHeightSpinBox->setValue( mLayer->size() * mLayer->fixedAspectRatio() );
4169 }
4170 mHeightSpinBox->setEnabled( mLayer->defaultAspectRatio() > 0.0 );
4171 mHeightSpinBox->blockSignals( false );
4172 whileBlocking( mLockAspectRatio )->setLocked( preservedAspectRatio );
4173
4174 whileBlocking( mRotationSpinBox )->setValue( mLayer->angle() );
4175 whileBlocking( mOpacityWidget )->setOpacity( mLayer->opacity() );
4176
4177 whileBlocking( mSpinOffsetX )->setValue( mLayer->offset().x() );
4178 whileBlocking( mSpinOffsetY )->setValue( mLayer->offset().y() );
4179
4180 mSizeUnitWidget->blockSignals( true );
4181 mSizeUnitWidget->setUnit( mLayer->sizeUnit() );
4182 mSizeUnitWidget->setMapUnitScale( mLayer->sizeMapUnitScale() );
4183 mSizeUnitWidget->blockSignals( false );
4184 mOffsetUnitWidget->blockSignals( true );
4185 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
4186 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
4187 mOffsetUnitWidget->blockSignals( false );
4188
4189 //anchor points
4190 whileBlocking( mHorizontalAnchorComboBox )->setCurrentIndex( mHorizontalAnchorComboBox->findData( QVariant::fromValue( mLayer->horizontalAnchorPoint() ) ) );
4191 whileBlocking( mVerticalAnchorComboBox )->setCurrentIndex( mVerticalAnchorComboBox->findData( QVariant::fromValue( mLayer->verticalAnchorPoint() ) ) );
4192
4201
4202 updatePreviewImage();
4203}
4204
4209
4211{
4213 mImageSourceLineEdit->setMessageBar( context.messageBar() );
4214}
4215
4216void QgsRasterMarkerSymbolLayerWidget::imageSourceChanged( const QString &text )
4217{
4218 mLayer->setPath( text );
4219 updatePreviewImage();
4220 emit changed();
4221}
4222
4223void QgsRasterMarkerSymbolLayerWidget::updatePreviewImage()
4224{
4225 bool fitsInCache = false;
4226 const QImage image = QgsApplication::imageCache()->pathAsImage( mLayer->path(), QSize( 150, 150 ), true, 1.0, fitsInCache );
4227 if ( image.isNull() )
4228 {
4229 mLabelImagePreview->setPixmap( QPixmap() );
4230 return;
4231 }
4232
4233 QImage previewImage( 150, 150, QImage::Format_ARGB32 );
4234 previewImage.fill( Qt::transparent );
4235 const QRect imageRect( ( 150 - image.width() ) / 2.0, ( 150 - image.height() ) / 2.0, image.width(), image.height() );
4236 QPainter p;
4237 p.begin( &previewImage );
4238 //draw a checkerboard background
4239 uchar pixDataRGB[] = { 150, 150, 150, 150, 100, 100, 100, 150, 100, 100, 100, 150, 150, 150, 150, 150 };
4240 const QImage img( pixDataRGB, 2, 2, 8, QImage::Format_ARGB32 );
4241 const QPixmap pix = QPixmap::fromImage( img.scaled( 8, 8 ) );
4242 QBrush checkerBrush;
4243 checkerBrush.setTexture( pix );
4244 p.fillRect( imageRect, checkerBrush );
4245
4246 if ( mLayer->opacity() < 1.0 )
4247 {
4248 p.setOpacity( mLayer->opacity() );
4249 }
4250
4251 p.drawImage( imageRect.left(), imageRect.top(), image );
4252 p.end();
4253 mLabelImagePreview->setPixmap( QPixmap::fromImage( previewImage ) );
4254}
4255
4256void QgsRasterMarkerSymbolLayerWidget::setWidth()
4257{
4258 const double defaultAspectRatio = mLayer->defaultAspectRatio();
4259 double fixedAspectRatio = 0.0;
4260 mHeightSpinBox->blockSignals( true );
4261 if ( defaultAspectRatio <= 0.0 )
4262 {
4263 mHeightSpinBox->setValue( mWidthSpinBox->value() );
4264 }
4265 else if ( mLockAspectRatio->locked() )
4266 {
4267 mHeightSpinBox->setValue( mWidthSpinBox->value() * defaultAspectRatio );
4268 }
4269 else
4270 {
4271 fixedAspectRatio = mHeightSpinBox->value() / mWidthSpinBox->value();
4272 }
4273 mHeightSpinBox->blockSignals( false );
4274 mLayer->setSize( mWidthSpinBox->value() );
4275 mLayer->setFixedAspectRatio( fixedAspectRatio );
4276 emit changed();
4277}
4278
4279void QgsRasterMarkerSymbolLayerWidget::setHeight()
4280{
4281 const double defaultAspectRatio = mLayer->defaultAspectRatio();
4282 double fixedAspectRatio = 0.0;
4283 mWidthSpinBox->blockSignals( true );
4284 if ( defaultAspectRatio <= 0.0 )
4285 {
4286 mWidthSpinBox->setValue( mHeightSpinBox->value() );
4287 }
4288 else if ( mLockAspectRatio->locked() )
4289 {
4290 mWidthSpinBox->setValue( mHeightSpinBox->value() / defaultAspectRatio );
4291 }
4292 else
4293 {
4294 fixedAspectRatio = mHeightSpinBox->value() / mWidthSpinBox->value();
4295 }
4296 mWidthSpinBox->blockSignals( false );
4297 mLayer->setSize( mWidthSpinBox->value() );
4298 mLayer->setFixedAspectRatio( fixedAspectRatio );
4299 emit changed();
4300}
4301
4302void QgsRasterMarkerSymbolLayerWidget::setLockAspectRatio( const bool locked )
4303{
4304 const double defaultAspectRatio = mLayer->defaultAspectRatio();
4305 if ( defaultAspectRatio <= 0.0 )
4306 {
4307 whileBlocking( mLockAspectRatio )->setLocked( true );
4308 }
4309 else if ( locked )
4310 {
4311 mLayer->setFixedAspectRatio( 0.0 );
4312 setWidth();
4313 }
4314 else
4315 {
4316 mLayer->setFixedAspectRatio( mHeightSpinBox->value() / mWidthSpinBox->value() );
4317 }
4318}
4319
4320void QgsRasterMarkerSymbolLayerWidget::setAngle()
4321{
4322 mLayer->setAngle( mRotationSpinBox->value() );
4323 emit changed();
4324}
4325
4326void QgsRasterMarkerSymbolLayerWidget::setOpacity( double value )
4327{
4328 mLayer->setOpacity( value );
4329 emit changed();
4330 updatePreviewImage();
4331}
4332
4333void QgsRasterMarkerSymbolLayerWidget::setOffset()
4334{
4335 mLayer->setOffset( QPointF( mSpinOffsetX->value(), mSpinOffsetY->value() ) );
4336 emit changed();
4337}
4338
4339void QgsRasterMarkerSymbolLayerWidget::mSizeUnitWidget_changed()
4340{
4341 if ( mLayer )
4342 {
4343 mLayer->setSizeUnit( mSizeUnitWidget->unit() );
4344 mLayer->setSizeMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
4345 emit changed();
4346 }
4347}
4348
4349void QgsRasterMarkerSymbolLayerWidget::mOffsetUnitWidget_changed()
4350{
4351 if ( mLayer )
4352 {
4353 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
4354 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
4355 emit changed();
4356 }
4357}
4358
4359void QgsRasterMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged( int )
4360{
4361 if ( mLayer )
4362 {
4363 mLayer->setHorizontalAnchorPoint( mHorizontalAnchorComboBox->currentData().value< Qgis::HorizontalAnchorPoint >() );
4364 emit changed();
4365 }
4366}
4367
4368void QgsRasterMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged( int )
4369{
4370 if ( mLayer )
4371 {
4372 mLayer->setVerticalAnchorPoint( mVerticalAnchorComboBox->currentData().value< Qgis::VerticalAnchorPoint >() );
4373 emit changed();
4374 }
4375}
4376
4377
4379
4381 : QgsSymbolLayerWidget( parent, vl )
4382{
4383 mLayer = nullptr;
4384
4385 setupUi( this );
4386
4387 mHorizontalAnchorComboBox->addItem( tr( "Left" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Left ) );
4388 mHorizontalAnchorComboBox->addItem( tr( "Horizontal Center" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Center ) );
4389 mHorizontalAnchorComboBox->addItem( tr( "Right" ), QVariant::fromValue( Qgis::HorizontalAnchorPoint::Right ) );
4390
4391 mVerticalAnchorComboBox->addItem( tr( "Top" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Top ) );
4392 mVerticalAnchorComboBox->addItem( tr( "Vertical Center" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Center ) );
4393 mVerticalAnchorComboBox->addItem( tr( "Bottom" ), QVariant::fromValue( Qgis::VerticalAnchorPoint::Bottom ) );
4394
4395 mImageSourceLineEdit->setLastPathSettingsKey( u"/UI/lastAnimatedMarkerImageDir"_s );
4396
4397 connect( mImageSourceLineEdit, &QgsImageSourceLineEdit::sourceChanged, this, &QgsAnimatedMarkerSymbolLayerWidget::imageSourceChanged );
4398 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsAnimatedMarkerSymbolLayerWidget::mOffsetUnitWidget_changed );
4399 connect( mRotationSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsAnimatedMarkerSymbolLayerWidget::setAngle );
4400 connect( mSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsAnimatedMarkerSymbolLayerWidget::mSizeUnitWidget_changed );
4401 connect( mWidthSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsAnimatedMarkerSymbolLayerWidget::setWidth );
4402 connect( mHeightSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsAnimatedMarkerSymbolLayerWidget::setHeight );
4403 connect( mLockAspectRatio, static_cast<void ( QgsRatioLockButton::* )( bool )>( &QgsRatioLockButton::lockChanged ), this, &QgsAnimatedMarkerSymbolLayerWidget::setLockAspectRatio );
4404
4405 mFrameRateSpin->setClearValue( 10 );
4406 mFrameRateSpin->setShowClearButton( true );
4407 connect( mFrameRateSpin, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double value ) {
4408 mLayer->setFrameRate( value );
4409 emit changed();
4410 } );
4411
4412 mSizeUnitWidget->setUnits(
4421 );
4422 mOffsetUnitWidget->setUnits(
4424 );
4425
4426 mSpinOffsetX->setClearValue( 0.0 );
4427 mSpinOffsetY->setClearValue( 0.0 );
4428 mRotationSpinBox->setClearValue( 0.0 );
4429
4430 connect( mSpinOffsetX, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsAnimatedMarkerSymbolLayerWidget::setOffset );
4431 connect( mSpinOffsetY, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsAnimatedMarkerSymbolLayerWidget::setOffset );
4432 connect( mOpacityWidget, &QgsOpacityWidget::opacityChanged, this, &QgsAnimatedMarkerSymbolLayerWidget::setOpacity );
4433
4434 connect( mHorizontalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsAnimatedMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged );
4435 connect( mVerticalAnchorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsAnimatedMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged );
4436}
4437
4439{
4440 if ( !layer )
4441 {
4442 return;
4443 }
4444
4445 if ( layer->layerType() != "AnimatedMarker"_L1 )
4446 return;
4447
4448 // layer type is correct, we can do the cast
4449 mLayer = static_cast<QgsAnimatedMarkerSymbolLayer *>( layer );
4450
4451 // set values
4452 whileBlocking( mImageSourceLineEdit )->setSource( mLayer->path() );
4453
4454 const double firstFrameTime = QgsApplication::imageCache()->nextFrameDelay( mLayer->path() );
4455 if ( firstFrameTime > 0 )
4456 {
4457 mFrameRateSpin->setClearValue( 1000 / firstFrameTime );
4458 }
4459 else
4460 {
4461 mFrameRateSpin->setClearValue( 10 );
4462 }
4463
4464 whileBlocking( mWidthSpinBox )->setValue( mLayer->size() );
4465 const bool preservedAspectRatio = mLayer->preservedAspectRatio();
4466 mHeightSpinBox->blockSignals( true );
4467 if ( preservedAspectRatio )
4468 {
4469 mHeightSpinBox->setValue( mLayer->size() );
4470 }
4471 else
4472 {
4473 mHeightSpinBox->setValue( mLayer->size() * mLayer->fixedAspectRatio() );
4474 }
4475 mHeightSpinBox->setEnabled( mLayer->defaultAspectRatio() > 0.0 );
4476 mHeightSpinBox->blockSignals( false );
4477 whileBlocking( mLockAspectRatio )->setLocked( preservedAspectRatio );
4478
4479 whileBlocking( mRotationSpinBox )->setValue( mLayer->angle() );
4480 whileBlocking( mOpacityWidget )->setOpacity( mLayer->opacity() );
4481
4482 whileBlocking( mSpinOffsetX )->setValue( mLayer->offset().x() );
4483 whileBlocking( mSpinOffsetY )->setValue( mLayer->offset().y() );
4484
4485 whileBlocking( mFrameRateSpin )->setValue( mLayer->frameRate() );
4486
4487 mSizeUnitWidget->blockSignals( true );
4488 mSizeUnitWidget->setUnit( mLayer->sizeUnit() );
4489 mSizeUnitWidget->setMapUnitScale( mLayer->sizeMapUnitScale() );
4490 mSizeUnitWidget->blockSignals( false );
4491 mOffsetUnitWidget->blockSignals( true );
4492 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
4493 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
4494 mOffsetUnitWidget->blockSignals( false );
4495
4496 //anchor points
4497 whileBlocking( mHorizontalAnchorComboBox )->setCurrentIndex( mHorizontalAnchorComboBox->findData( QVariant::fromValue( mLayer->horizontalAnchorPoint() ) ) );
4498 whileBlocking( mVerticalAnchorComboBox )->setCurrentIndex( mVerticalAnchorComboBox->findData( QVariant::fromValue( mLayer->verticalAnchorPoint() ) ) );
4499
4508
4509 updatePreviewImage();
4510}
4511
4516
4518{
4520 mImageSourceLineEdit->setMessageBar( context.messageBar() );
4521}
4522
4523void QgsAnimatedMarkerSymbolLayerWidget::imageSourceChanged( const QString &text )
4524{
4525 mLayer->setPath( text );
4526
4527 const double firstFrameTime = QgsApplication::imageCache()->nextFrameDelay( text );
4528 if ( firstFrameTime > 0 )
4529 {
4530 mFrameRateSpin->setClearValue( 1000 / firstFrameTime );
4531 }
4532 else
4533 {
4534 mFrameRateSpin->setClearValue( 10 );
4535 }
4536 updatePreviewImage();
4537 emit changed();
4538}
4539
4540void QgsAnimatedMarkerSymbolLayerWidget::updatePreviewImage()
4541{
4542 if ( mPreviewMovie )
4543 {
4544 mLabelImagePreview->setMovie( nullptr );
4545 mPreviewMovie->deleteLater();
4546 mPreviewMovie = nullptr;
4547 }
4548
4549 mPreviewMovie = new QMovie( mLayer->path(), QByteArray(), this );
4550 mPreviewMovie->setScaledSize( QSize( 150, 150 ) );
4551 mLabelImagePreview->setMovie( mPreviewMovie );
4552 mPreviewMovie->start();
4553}
4554
4555void QgsAnimatedMarkerSymbolLayerWidget::setWidth()
4556{
4557 const double defaultAspectRatio = mLayer->defaultAspectRatio();
4558 double fixedAspectRatio = 0.0;
4559 mHeightSpinBox->blockSignals( true );
4560 if ( defaultAspectRatio <= 0.0 )
4561 {
4562 mHeightSpinBox->setValue( mWidthSpinBox->value() );
4563 }
4564 else if ( mLockAspectRatio->locked() )
4565 {
4566 mHeightSpinBox->setValue( mWidthSpinBox->value() * defaultAspectRatio );
4567 }
4568 else
4569 {
4570 fixedAspectRatio = mHeightSpinBox->value() / mWidthSpinBox->value();
4571 }
4572 mHeightSpinBox->blockSignals( false );
4573 mLayer->setSize( mWidthSpinBox->value() );
4574 mLayer->setFixedAspectRatio( fixedAspectRatio );
4575 emit changed();
4576}
4577
4578void QgsAnimatedMarkerSymbolLayerWidget::setHeight()
4579{
4580 const double defaultAspectRatio = mLayer->defaultAspectRatio();
4581 double fixedAspectRatio = 0.0;
4582 mWidthSpinBox->blockSignals( true );
4583 if ( defaultAspectRatio <= 0.0 )
4584 {
4585 mWidthSpinBox->setValue( mHeightSpinBox->value() );
4586 }
4587 else if ( mLockAspectRatio->locked() )
4588 {
4589 mWidthSpinBox->setValue( mHeightSpinBox->value() / defaultAspectRatio );
4590 }
4591 else
4592 {
4593 fixedAspectRatio = mHeightSpinBox->value() / mWidthSpinBox->value();
4594 }
4595 mWidthSpinBox->blockSignals( false );
4596 mLayer->setSize( mWidthSpinBox->value() );
4597 mLayer->setFixedAspectRatio( fixedAspectRatio );
4598 emit changed();
4599}
4600
4601void QgsAnimatedMarkerSymbolLayerWidget::setLockAspectRatio( const bool locked )
4602{
4603 const double defaultAspectRatio = mLayer->defaultAspectRatio();
4604 if ( defaultAspectRatio <= 0.0 )
4605 {
4606 whileBlocking( mLockAspectRatio )->setLocked( true );
4607 }
4608 else if ( locked )
4609 {
4610 mLayer->setFixedAspectRatio( 0.0 );
4611 setWidth();
4612 }
4613 else
4614 {
4615 mLayer->setFixedAspectRatio( mHeightSpinBox->value() / mWidthSpinBox->value() );
4616 }
4617}
4618
4619void QgsAnimatedMarkerSymbolLayerWidget::setAngle()
4620{
4621 mLayer->setAngle( mRotationSpinBox->value() );
4622 emit changed();
4623}
4624
4625void QgsAnimatedMarkerSymbolLayerWidget::setOpacity( double value )
4626{
4627 mLayer->setOpacity( value );
4628 emit changed();
4629 updatePreviewImage();
4630}
4631
4632void QgsAnimatedMarkerSymbolLayerWidget::setOffset()
4633{
4634 mLayer->setOffset( QPointF( mSpinOffsetX->value(), mSpinOffsetY->value() ) );
4635 emit changed();
4636}
4637
4638void QgsAnimatedMarkerSymbolLayerWidget::mSizeUnitWidget_changed()
4639{
4640 if ( mLayer )
4641 {
4642 mLayer->setSizeUnit( mSizeUnitWidget->unit() );
4643 mLayer->setSizeMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
4644 emit changed();
4645 }
4646}
4647
4648void QgsAnimatedMarkerSymbolLayerWidget::mOffsetUnitWidget_changed()
4649{
4650 if ( mLayer )
4651 {
4652 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
4653 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
4654 emit changed();
4655 }
4656}
4657
4658void QgsAnimatedMarkerSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged( int )
4659{
4660 if ( mLayer )
4661 {
4662 mLayer->setHorizontalAnchorPoint( mHorizontalAnchorComboBox->currentData().value< Qgis::HorizontalAnchorPoint >() );
4663 emit changed();
4664 }
4665}
4666
4667void QgsAnimatedMarkerSymbolLayerWidget::mVerticalAnchorComboBox_currentIndexChanged( int )
4668{
4669 if ( mLayer )
4670 {
4671 mLayer->setVerticalAnchorPoint( mVerticalAnchorComboBox->currentData().value< Qgis::VerticalAnchorPoint >() );
4672 emit changed();
4673 }
4674}
4675
4677
4679 : QgsSymbolLayerWidget( parent, vl )
4680{
4681 mLayer = nullptr;
4682 setupUi( this );
4683
4684 mImageSourceLineEdit->setLastPathSettingsKey( u"/UI/lastRasterMarkerImageDir"_s );
4685 connect( mImageSourceLineEdit, &QgsImageSourceLineEdit::sourceChanged, this, &QgsRasterFillSymbolLayerWidget::imageSourceChanged );
4686
4687 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsRasterFillSymbolLayerWidget::mOffsetUnitWidget_changed );
4688 connect( mRotationSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsRasterFillSymbolLayerWidget::mRotationSpinBox_valueChanged );
4689
4690 connect( mSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
4691 if ( !mLayer )
4692 {
4693 return;
4694 }
4695 mLayer->setSizeUnit( mSizeUnitWidget->unit() );
4696 mLayer->setSizeMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
4697 emit changed();
4698 } );
4699 connect( mWidthSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, [this]( double d ) {
4700 if ( !mLayer )
4701 {
4702 return;
4703 }
4704 mLayer->setWidth( d );
4705 emit changed();
4706 } );
4707
4708 connect( mHeightSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, [this]( double d ) {
4709 if ( !mLayer )
4710 {
4711 return;
4712 }
4713 mLayer->setHeight( d );
4714 emit changed();
4715 } );
4716
4717 mSizeUnitWidget->setUnits(
4726 );
4727 mOffsetUnitWidget->setUnits(
4729 );
4730
4731 mSpinOffsetX->setClearValue( 0.0 );
4732 mSpinOffsetY->setClearValue( 0.0 );
4733 mRotationSpinBox->setClearValue( 0.0 );
4734
4735 connect( cboCoordinateMode, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsRasterFillSymbolLayerWidget::setCoordinateMode );
4736 connect( mSpinOffsetX, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsRasterFillSymbolLayerWidget::offsetChanged );
4737 connect( mSpinOffsetY, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsRasterFillSymbolLayerWidget::offsetChanged );
4738 connect( mOpacityWidget, &QgsOpacityWidget::opacityChanged, this, &QgsRasterFillSymbolLayerWidget::opacityChanged );
4739}
4740
4741
4743{
4744 if ( !layer )
4745 {
4746 return;
4747 }
4748
4749 if ( layer->layerType() != "RasterFill"_L1 )
4750 {
4751 return;
4752 }
4753
4754 mLayer = dynamic_cast<QgsRasterFillSymbolLayer *>( layer );
4755 if ( !mLayer )
4756 {
4757 return;
4758 }
4759
4760 whileBlocking( mImageSourceLineEdit )->setSource( mLayer->imageFilePath() );
4761
4762 cboCoordinateMode->blockSignals( true );
4763 switch ( mLayer->coordinateMode() )
4764 {
4766 cboCoordinateMode->setCurrentIndex( 1 );
4767 break;
4769 default:
4770 cboCoordinateMode->setCurrentIndex( 0 );
4771 break;
4772 }
4773 cboCoordinateMode->blockSignals( false );
4774 whileBlocking( mOpacityWidget )->setOpacity( mLayer->opacity() );
4775 whileBlocking( mRotationSpinBox )->setValue( mLayer->angle() );
4776
4777 whileBlocking( mSpinOffsetX )->setValue( mLayer->offset().x() );
4778 whileBlocking( mSpinOffsetY )->setValue( mLayer->offset().y() );
4779 mOffsetUnitWidget->blockSignals( true );
4780 mOffsetUnitWidget->setUnit( mLayer->offsetUnit() );
4781 mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
4782 mOffsetUnitWidget->blockSignals( false );
4783
4784 whileBlocking( mWidthSpinBox )->setValue( mLayer->width() );
4785 mSizeUnitWidget->blockSignals( true );
4786 mSizeUnitWidget->setUnit( mLayer->sizeUnit() );
4787 mSizeUnitWidget->setMapUnitScale( mLayer->sizeMapUnitScale() );
4788 mSizeUnitWidget->blockSignals( false );
4789
4790 whileBlocking( mHeightSpinBox )->setValue( mLayer->height() );
4791
4792 updatePreviewImage();
4793
4800}
4801
4806
4807void QgsRasterFillSymbolLayerWidget::imageSourceChanged( const QString &text )
4808{
4809 mLayer->setImageFilePath( text );
4810 updatePreviewImage();
4811 emit changed();
4812}
4813
4814void QgsRasterFillSymbolLayerWidget::setCoordinateMode( int index )
4815{
4816 switch ( index )
4817 {
4818 case 0:
4819 //feature coordinate mode
4821 break;
4822 case 1:
4823 //viewport coordinate mode
4825 break;
4826 }
4827
4828 emit changed();
4829}
4830
4831void QgsRasterFillSymbolLayerWidget::opacityChanged( double value )
4832{
4833 if ( !mLayer )
4834 {
4835 return;
4836 }
4837
4838 mLayer->setOpacity( value );
4839 emit changed();
4840 updatePreviewImage();
4841}
4842
4843void QgsRasterFillSymbolLayerWidget::offsetChanged()
4844{
4845 mLayer->setOffset( QPointF( mSpinOffsetX->value(), mSpinOffsetY->value() ) );
4846 emit changed();
4847}
4848
4849void QgsRasterFillSymbolLayerWidget::mOffsetUnitWidget_changed()
4850{
4851 if ( !mLayer )
4852 {
4853 return;
4854 }
4855 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
4856 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
4857 emit changed();
4858}
4859
4860void QgsRasterFillSymbolLayerWidget::mRotationSpinBox_valueChanged( double d )
4861{
4862 if ( mLayer )
4863 {
4864 mLayer->setAngle( d );
4865 emit changed();
4866 }
4867}
4868
4869void QgsRasterFillSymbolLayerWidget::updatePreviewImage()
4870{
4871 bool fitsInCache = false;
4872 const QImage image = QgsApplication::imageCache()->pathAsImage( mLayer->imageFilePath(), QSize( 150, 150 ), true, 1.0, fitsInCache );
4873 if ( image.isNull() )
4874 {
4875 mLabelImagePreview->setPixmap( QPixmap() );
4876 return;
4877 }
4878
4879 QImage previewImage( 150, 150, QImage::Format_ARGB32 );
4880 previewImage.fill( Qt::transparent );
4881 const QRect imageRect( ( 150 - image.width() ) / 2.0, ( 150 - image.height() ) / 2.0, image.width(), image.height() );
4882 QPainter p;
4883 p.begin( &previewImage );
4884 //draw a checkerboard background
4885 uchar pixDataRGB[] = { 150, 150, 150, 150, 100, 100, 100, 150, 100, 100, 100, 150, 150, 150, 150, 150 };
4886 const QImage img( pixDataRGB, 2, 2, 8, QImage::Format_ARGB32 );
4887 const QPixmap pix = QPixmap::fromImage( img.scaled( 8, 8 ) );
4888 QBrush checkerBrush;
4889 checkerBrush.setTexture( pix );
4890 p.fillRect( imageRect, checkerBrush );
4891
4892 if ( mLayer->opacity() < 1.0 )
4893 {
4894 p.setOpacity( mLayer->opacity() );
4895 }
4896
4897 p.drawImage( imageRect.left(), imageRect.top(), image );
4898 p.end();
4899 mLabelImagePreview->setPixmap( QPixmap::fromImage( previewImage ) );
4900}
4901
4902//
4903// QgsRasterLineSymbolLayerWidget
4904//
4905
4906
4908 : QgsSymbolLayerWidget( parent, vl )
4909{
4910 mLayer = nullptr;
4911 setupUi( this );
4912
4913 mImageSourceLineEdit->setLastPathSettingsKey( u"/UI/lastRasterMarkerImageDir"_s );
4914
4915 mPenWidthUnitWidget->setUnits(
4917 );
4918 mOffsetUnitWidget->setUnits(
4920 );
4921
4922 connect( mPenWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
4923 if ( mLayer )
4924 {
4925 mLayer->setWidthUnit( mPenWidthUnitWidget->unit() );
4926 mLayer->setWidthMapUnitScale( mPenWidthUnitWidget->getMapUnitScale() );
4927 emit changed();
4928 }
4929 } );
4930
4931 connect( spinWidth, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this] {
4932 if ( mLayer )
4933 {
4934 mLayer->setWidth( spinWidth->value() );
4935 emit changed();
4936 }
4937 } );
4938
4939 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
4940 if ( mLayer )
4941 {
4942 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
4943 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
4944 emit changed();
4945 }
4946 } );
4947
4948
4949 spinOffset->setClearValue( 0.0 );
4950 connect( spinOffset, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double val ) {
4951 if ( mLayer )
4952 {
4953 mLayer->setOffset( val );
4954 emit changed();
4955 }
4956 } );
4957
4958 connect( cboCapStyle, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this] {
4959 if ( mLayer )
4960 {
4961 mLayer->setPenCapStyle( cboCapStyle->penCapStyle() );
4962 emit changed();
4963 }
4964 } );
4965 connect( cboJoinStyle, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this] {
4966 if ( mLayer )
4967 {
4968 mLayer->setPenJoinStyle( cboJoinStyle->penJoinStyle() );
4969 emit changed();
4970 }
4971 } );
4972
4973 connect( mImageSourceLineEdit, &QgsImageSourceLineEdit::sourceChanged, this, &QgsRasterLineSymbolLayerWidget::imageSourceChanged );
4974 connect( mOpacityWidget, &QgsOpacityWidget::opacityChanged, this, [this]( double opacity ) {
4975 if ( mLayer )
4976 {
4977 mLayer->setOpacity( opacity );
4978 updatePreviewImage();
4979 emit changed();
4980 }
4981 } );
4982}
4983
4985{
4986 if ( !layer )
4987 {
4988 return;
4989 }
4990
4991 if ( layer->layerType() != "RasterLine"_L1 )
4992 {
4993 return;
4994 }
4995
4996 mLayer = dynamic_cast<QgsRasterLineSymbolLayer *>( layer );
4997 if ( !mLayer )
4998 {
4999 return;
5000 }
5001
5002 whileBlocking( mImageSourceLineEdit )->setSource( mLayer->path() );
5003 whileBlocking( mOpacityWidget )->setOpacity( mLayer->opacity() );
5004
5005 whileBlocking( spinWidth )->setValue( mLayer->width() );
5006 whileBlocking( mPenWidthUnitWidget )->setUnit( mLayer->widthUnit() );
5007 whileBlocking( mPenWidthUnitWidget )->setMapUnitScale( mLayer->widthMapUnitScale() );
5008 whileBlocking( cboJoinStyle )->setPenJoinStyle( mLayer->penJoinStyle() );
5009 whileBlocking( cboCapStyle )->setPenCapStyle( mLayer->penCapStyle() );
5010
5011 whileBlocking( mOffsetUnitWidget )->setUnit( mLayer->offsetUnit() );
5012 whileBlocking( mOffsetUnitWidget )->setMapUnitScale( mLayer->offsetMapUnitScale() );
5013 whileBlocking( spinOffset )->setValue( mLayer->offset() );
5014
5015 updatePreviewImage();
5016
5023}
5024
5029
5030void QgsRasterLineSymbolLayerWidget::imageSourceChanged( const QString &text )
5031{
5032 mLayer->setPath( text );
5033 updatePreviewImage();
5034 emit changed();
5035}
5036
5037void QgsRasterLineSymbolLayerWidget::updatePreviewImage()
5038{
5039 bool fitsInCache = false;
5040 const QImage image = QgsApplication::imageCache()->pathAsImage( mLayer->path(), QSize( 150, 150 ), true, 1.0, fitsInCache );
5041 if ( image.isNull() )
5042 {
5043 mLabelImagePreview->setPixmap( QPixmap() );
5044 return;
5045 }
5046
5047 QImage previewImage( 150, 150, QImage::Format_ARGB32 );
5048 previewImage.fill( Qt::transparent );
5049 const QRect imageRect( ( 150 - image.width() ) / 2.0, ( 150 - image.height() ) / 2.0, image.width(), image.height() );
5050 QPainter p;
5051 p.begin( &previewImage );
5052 //draw a checkerboard background
5053 uchar pixDataRGB[] = { 150, 150, 150, 150, 100, 100, 100, 150, 100, 100, 100, 150, 150, 150, 150, 150 };
5054 const QImage img( pixDataRGB, 2, 2, 8, QImage::Format_ARGB32 );
5055 const QPixmap pix = QPixmap::fromImage( img.scaled( 8, 8 ) );
5056 QBrush checkerBrush;
5057 checkerBrush.setTexture( pix );
5058 p.fillRect( imageRect, checkerBrush );
5059
5060 if ( mLayer->opacity() < 1.0 )
5061 {
5062 p.setOpacity( mLayer->opacity() );
5063 }
5064
5065 p.drawImage( imageRect.left(), imageRect.top(), image );
5066 p.end();
5067 mLabelImagePreview->setPixmap( QPixmap::fromImage( previewImage ) );
5068}
5069
5070
5071//
5072// QgsGeometryGeneratorSymbolLayerWidget
5073//
5074
5076 : QgsSymbolLayerWidget( parent, vl )
5077
5078{
5079 setupUi( this );
5080 modificationExpressionSelector->setMultiLine( true );
5081 modificationExpressionSelector->setLayer( const_cast<QgsVectorLayer *>( vl ) );
5082 modificationExpressionSelector->registerExpressionContextGenerator( this );
5083 cbxGeometryType->addItem( QgsIconUtils::iconPolygon(), tr( "Polygon / MultiPolygon" ), static_cast<int>( Qgis::SymbolType::Fill ) );
5084 cbxGeometryType->addItem( QgsIconUtils::iconLine(), tr( "LineString / MultiLineString" ), static_cast<int>( Qgis::SymbolType::Line ) );
5085 cbxGeometryType->addItem( QgsIconUtils::iconPoint(), tr( "Point / MultiPoint" ), static_cast<int>( Qgis::SymbolType::Marker ) );
5086
5088 mUnitWidget->setShowMapScaleButton( false );
5089
5090 connect( modificationExpressionSelector, &QgsExpressionLineEdit::expressionChanged, this, &QgsGeometryGeneratorSymbolLayerWidget::updateExpression );
5091 connect( cbxGeometryType, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsGeometryGeneratorSymbolLayerWidget::updateSymbolType );
5092 connect( mUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
5093 if ( !mBlockSignals )
5094 {
5095 mLayer->setUnits( mUnitWidget->unit() );
5096 emit symbolChanged();
5097 }
5098 } );
5099}
5100
5102{
5103 mBlockSignals++;
5104 mLayer = static_cast<QgsGeometryGeneratorSymbolLayer *>( l );
5105 modificationExpressionSelector->setExpression( mLayer->geometryExpression() );
5106 cbxGeometryType->setCurrentIndex( cbxGeometryType->findData( static_cast<int>( mLayer->symbolType() ) ) );
5107 mUnitWidget->setUnit( mLayer->units() );
5108 mBlockSignals--;
5109}
5110
5115
5116void QgsGeometryGeneratorSymbolLayerWidget::updateExpression( const QString &string )
5117{
5118 mLayer->setGeometryExpression( string );
5119
5120 emit changed();
5121}
5122
5123void QgsGeometryGeneratorSymbolLayerWidget::updateSymbolType()
5124{
5125 // we try to keep the subsymbol, if we can!
5126 std::unique_ptr<QgsSymbol> subSymbol( mLayer->subSymbol()->clone() );
5127
5128 mLayer->setSymbolType( static_cast<Qgis::SymbolType>( cbxGeometryType->currentData().toInt() ) );
5129
5130 switch ( mLayer->symbolType() )
5131 {
5134 break;
5136 {
5137 if ( subSymbol->type() == Qgis::SymbolType::Fill )
5138 {
5139 // going from fill -> line type, so we can copy any LINE symbol layers across
5140 QgsSymbolLayerList layers;
5141 for ( int i = 0; i < subSymbol->symbolLayerCount(); ++i )
5142 {
5143 if ( dynamic_cast<const QgsLineSymbolLayer *>( subSymbol->symbolLayer( i ) ) )
5144 layers << subSymbol->symbolLayer( i )->clone();
5145 }
5146
5147 if ( !layers.empty() )
5148 mLayer->setSubSymbol( new QgsLineSymbol( layers ) );
5149 }
5150 break;
5151 }
5153 if ( subSymbol->type() == Qgis::SymbolType::Line )
5154 {
5155 // going from line -> fill type, so copy ALL line symbol layers across
5156 QgsSymbolLayerList layers;
5157 for ( int i = 0; i < subSymbol->symbolLayerCount(); ++i )
5158 layers << subSymbol->symbolLayer( i )->clone();
5159 mLayer->setSubSymbol( new QgsFillSymbol( layers ) );
5160 }
5161 break;
5162 }
5163
5164 emit symbolChanged();
5165}
5166
5167//
5168// QgsRandomMarkerFillSymbolLayerWidget
5169//
5170
5171
5173 : QgsSymbolLayerWidget( parent, vl )
5174{
5175 setupUi( this );
5176
5177 mCountMethodComboBox->addItem( tr( "Absolute Count" ), static_cast<int>( Qgis::PointCountMethod::Absolute ) );
5178 mCountMethodComboBox->addItem( tr( "Density-based Count" ), static_cast<int>( Qgis::PointCountMethod::DensityBased ) );
5179
5180 mPointCountSpinBox->setShowClearButton( true );
5181 mPointCountSpinBox->setClearValue( 100 );
5182 mSeedSpinBox->setShowClearButton( true );
5183 mSeedSpinBox->setClearValue( 0 );
5184
5185 connect( mCountMethodComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsRandomMarkerFillSymbolLayerWidget::countMethodChanged );
5186 connect( mPointCountSpinBox, static_cast<void ( QSpinBox::* )( int )>( &QSpinBox::valueChanged ), this, &QgsRandomMarkerFillSymbolLayerWidget::countChanged );
5187 connect( mDensityAreaSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsRandomMarkerFillSymbolLayerWidget::densityAreaChanged );
5188 connect( mSeedSpinBox, static_cast<void ( QSpinBox::* )( int )>( &QSpinBox::valueChanged ), this, &QgsRandomMarkerFillSymbolLayerWidget::seedChanged );
5189 connect( mClipPointsCheckBox, &QCheckBox::toggled, this, [this]( bool checked ) {
5190 if ( mLayer )
5191 {
5192 mLayer->setClipPoints( checked );
5193 emit changed();
5194 }
5195 } );
5196
5197 mDensityAreaUnitWidget->setUnits(
5199 );
5200
5201 connect( mDensityAreaUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsRandomMarkerFillSymbolLayerWidget::densityAreaUnitChanged );
5202}
5203
5205{
5206 if ( !layer || layer->layerType() != "RandomMarkerFill"_L1 )
5207 {
5208 return;
5209 }
5210
5211 mLayer = static_cast<QgsRandomMarkerFillSymbolLayer *>( layer );
5212 whileBlocking( mPointCountSpinBox )->setValue( mLayer->pointCount() );
5213 whileBlocking( mSeedSpinBox )->setValue( mLayer->seed() );
5214 whileBlocking( mClipPointsCheckBox )->setChecked( mLayer->clipPoints() );
5215
5216 bool showDensityBasedCountWidgets = false;
5217 switch ( mLayer->countMethod() )
5218 {
5220 showDensityBasedCountWidgets = true;
5221 break;
5223 break;
5224 }
5225 mDensityAreaLabel->setVisible( showDensityBasedCountWidgets );
5226 mDensityAreaSpinBox->setVisible( showDensityBasedCountWidgets );
5227 mDensityAreaUnitWidget->setVisible( showDensityBasedCountWidgets );
5228 mDensityAreaDdbtn->setVisible( showDensityBasedCountWidgets );
5229
5230 whileBlocking( mCountMethodComboBox )->setCurrentIndex( mCountMethodComboBox->findData( static_cast<int>( mLayer->countMethod() ) ) );
5231 whileBlocking( mDensityAreaSpinBox )->setValue( mLayer->densityArea() );
5232 mDensityAreaUnitWidget->blockSignals( true );
5233 mDensityAreaUnitWidget->setUnit( mLayer->densityAreaUnit() );
5234 mDensityAreaUnitWidget->setMapUnitScale( mLayer->densityAreaUnitScale() );
5235 mDensityAreaUnitWidget->blockSignals( false );
5236
5241}
5242
5247
5248void QgsRandomMarkerFillSymbolLayerWidget::countMethodChanged( int )
5249{
5250 bool showDensityBasedCountWidgets = false;
5251 switch ( static_cast<Qgis::PointCountMethod>( mCountMethodComboBox->currentData().toInt() ) )
5252 {
5254 showDensityBasedCountWidgets = true;
5255 break;
5257 break;
5258 }
5259 mDensityAreaLabel->setVisible( showDensityBasedCountWidgets );
5260 mDensityAreaSpinBox->setVisible( showDensityBasedCountWidgets );
5261 mDensityAreaUnitWidget->setVisible( showDensityBasedCountWidgets );
5262 mDensityAreaDdbtn->setVisible( showDensityBasedCountWidgets );
5263
5264 if ( mLayer )
5265 {
5266 mLayer->setCountMethod( static_cast<Qgis::PointCountMethod>( mCountMethodComboBox->currentData().toInt() ) );
5267 emit changed();
5268 }
5269}
5270
5271void QgsRandomMarkerFillSymbolLayerWidget::countChanged( int d )
5272{
5273 if ( mLayer )
5274 {
5275 mLayer->setPointCount( d );
5276 emit changed();
5277 }
5278}
5279
5280void QgsRandomMarkerFillSymbolLayerWidget::densityAreaChanged( double d )
5281{
5282 if ( mLayer )
5283 {
5284 mLayer->setDensityArea( d );
5285 emit changed();
5286 }
5287}
5288
5289void QgsRandomMarkerFillSymbolLayerWidget::densityAreaUnitChanged()
5290{
5291 if ( mLayer )
5292 {
5293 mLayer->setDensityAreaUnit( mDensityAreaUnitWidget->unit() );
5294 mLayer->setDensityAreaUnitScale( mDensityAreaUnitWidget->getMapUnitScale() );
5295 emit changed();
5296 }
5297}
5298
5299void QgsRandomMarkerFillSymbolLayerWidget::seedChanged( int d )
5300{
5301 if ( mLayer )
5302 {
5303 mLayer->setSeed( d );
5304 emit changed();
5305 }
5306}
5307
5308//
5309// QgsGradientLineSymbolLayerWidget
5310//
5311
5313 : QgsSymbolLayerWidget( parent, vl )
5314{
5315 mLayer = nullptr;
5316 setupUi( this );
5317
5318 btnColorRamp->setShowGradientOnly( true );
5319
5320 btnChangeColor->setAllowOpacity( true );
5321 btnChangeColor->setColorDialogTitle( tr( "Select Gradient Color" ) );
5322 btnChangeColor->setContext( u"symbology"_s );
5323 btnChangeColor->setShowNoColor( true );
5324 btnChangeColor->setNoColorString( tr( "Transparent" ) );
5325 btnChangeColor2->setAllowOpacity( true );
5326 btnChangeColor2->setColorDialogTitle( tr( "Select Gradient Color" ) );
5327 btnChangeColor2->setContext( u"symbology"_s );
5328 btnChangeColor2->setShowNoColor( true );
5329 btnChangeColor2->setNoColorString( tr( "Transparent" ) );
5330
5331 mStartColorDDBtn->registerLinkedWidget( btnChangeColor );
5332 mEndColorDDBtn->registerLinkedWidget( btnChangeColor2 );
5333
5334 connect( btnChangeColor, &QgsColorButton::colorChanged, this, [this]( const QColor &color ) {
5335 if ( mLayer )
5336 {
5337 mLayer->setColor( color );
5338 emit changed();
5339 }
5340 } );
5341 connect( btnChangeColor2, &QgsColorButton::colorChanged, this, [this]( const QColor &color ) {
5342 if ( mLayer )
5343 {
5344 mLayer->setColor2( color );
5345 emit changed();
5346 }
5347 } );
5348 connect( btnColorRamp, &QgsColorRampButton::colorRampChanged, this, [this] {
5349 if ( btnColorRamp->isNull() )
5350 return;
5351
5352 if ( mLayer )
5353 {
5354 mLayer->setColorRamp( btnColorRamp->colorRamp()->clone() );
5355 emit changed();
5356 }
5357 } );
5358
5359 connect( radioTwoColor, &QAbstractButton::toggled, this, [this] {
5360 if ( mLayer )
5361 {
5362 if ( radioTwoColor->isChecked() )
5363 {
5364 mLayer->setGradientColorType( Qgis::GradientColorSource::SimpleTwoColor );
5365 btnChangeColor->setEnabled( true );
5366 btnChangeColor2->setEnabled( true );
5367 btnColorRamp->setEnabled( false );
5368 }
5369 else
5370 {
5371 mLayer->setGradientColorType( Qgis::GradientColorSource::ColorRamp );
5372 btnColorRamp->setEnabled( true );
5373 btnChangeColor->setEnabled( false );
5374 btnChangeColor2->setEnabled( false );
5375 }
5376 emit changed();
5377 }
5378 } );
5379
5380 mPenWidthUnitWidget->setUnits(
5382 );
5383 mOffsetUnitWidget->setUnits(
5385 );
5386
5387 connect( mPenWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
5388 if ( mLayer )
5389 {
5390 mLayer->setWidthUnit( mPenWidthUnitWidget->unit() );
5391 mLayer->setWidthMapUnitScale( mPenWidthUnitWidget->getMapUnitScale() );
5392 emit changed();
5393 }
5394 } );
5395
5396 connect( spinWidth, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, [this] {
5397 if ( mLayer )
5398 {
5399 mLayer->setWidth( spinWidth->value() );
5400 emit changed();
5401 }
5402 } );
5403
5404 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
5405 if ( mLayer )
5406 {
5407 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
5408 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
5409 emit changed();
5410 }
5411 } );
5412
5413 spinOffset->setClearValue( 0.0 );
5414 connect( spinOffset, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double val ) {
5415 if ( mLayer )
5416 {
5417 mLayer->setOffset( val );
5418 emit changed();
5419 }
5420 } );
5421
5422 connect( cboCapStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, [this] {
5423 if ( mLayer )
5424 {
5425 mLayer->setPenCapStyle( cboCapStyle->penCapStyle() );
5426 emit changed();
5427 }
5428 } );
5429 connect( cboJoinStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, [this] {
5430 if ( mLayer )
5431 {
5432 mLayer->setPenJoinStyle( cboJoinStyle->penJoinStyle() );
5433 emit changed();
5434 }
5435 } );
5436}
5437
5439{
5440 if ( !layer )
5441 {
5442 return;
5443 }
5444
5445 if ( layer->layerType() != "Lineburst"_L1 )
5446 {
5447 return;
5448 }
5449
5450 mLayer = dynamic_cast<QgsLineburstSymbolLayer *>( layer );
5451 if ( !mLayer )
5452 {
5453 return;
5454 }
5455
5456 btnChangeColor->blockSignals( true );
5457 btnChangeColor->setColor( mLayer->color() );
5458 btnChangeColor->blockSignals( false );
5459 btnChangeColor2->blockSignals( true );
5460 btnChangeColor2->setColor( mLayer->color2() );
5461 btnChangeColor2->blockSignals( false );
5462
5463 if ( mLayer->gradientColorType() == Qgis::GradientColorSource::SimpleTwoColor )
5464 {
5465 radioTwoColor->setChecked( true );
5466 btnColorRamp->setEnabled( false );
5467 }
5468 else
5469 {
5470 radioColorRamp->setChecked( true );
5471 btnChangeColor->setEnabled( false );
5472 btnChangeColor2->setEnabled( false );
5473 }
5474
5475 // set source color ramp
5476 if ( mLayer->colorRamp() )
5477 {
5478 btnColorRamp->blockSignals( true );
5479 btnColorRamp->setColorRamp( mLayer->colorRamp() );
5480 btnColorRamp->blockSignals( false );
5481 }
5482
5483 whileBlocking( spinWidth )->setValue( mLayer->width() );
5484 whileBlocking( mPenWidthUnitWidget )->setUnit( mLayer->widthUnit() );
5485 whileBlocking( mPenWidthUnitWidget )->setMapUnitScale( mLayer->widthMapUnitScale() );
5486
5487 whileBlocking( mOffsetUnitWidget )->setUnit( mLayer->offsetUnit() );
5488 whileBlocking( mOffsetUnitWidget )->setMapUnitScale( mLayer->offsetMapUnitScale() );
5489 whileBlocking( spinOffset )->setValue( mLayer->offset() );
5490
5491 whileBlocking( cboJoinStyle )->setPenJoinStyle( mLayer->penJoinStyle() );
5492 whileBlocking( cboCapStyle )->setPenCapStyle( mLayer->penCapStyle() );
5493
5500}
5501
5506
5507//
5508// QgsFilledLineSymbolLayerWidget
5509//
5510
5512 : QgsSymbolLayerWidget( parent, vl )
5513{
5514 mLayer = nullptr;
5515 setupUi( this );
5516
5517 mPenWidthUnitWidget->setUnits(
5519 );
5520 mOffsetUnitWidget->setUnits(
5522 );
5523
5524 connect( mPenWidthUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
5525 if ( mLayer )
5526 {
5527 mLayer->setWidthUnit( mPenWidthUnitWidget->unit() );
5528 mLayer->setWidthMapUnitScale( mPenWidthUnitWidget->getMapUnitScale() );
5529 emit changed();
5530 }
5531 } );
5532
5533 connect( spinWidth, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, [this] {
5534 if ( mLayer )
5535 {
5536 mLayer->setWidth( spinWidth->value() );
5537 emit changed();
5538 }
5539 } );
5540
5541 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
5542 if ( mLayer )
5543 {
5544 mLayer->setOffsetUnit( mOffsetUnitWidget->unit() );
5545 mLayer->setOffsetMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
5546 emit changed();
5547 }
5548 } );
5549
5550 spinOffset->setClearValue( 0.0 );
5551 connect( spinOffset, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double val ) {
5552 if ( mLayer )
5553 {
5554 mLayer->setOffset( val );
5555 emit changed();
5556 }
5557 } );
5558
5559 connect( cboCapStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, [this] {
5560 if ( mLayer )
5561 {
5562 mLayer->setPenCapStyle( cboCapStyle->penCapStyle() );
5563 emit changed();
5564 }
5565 } );
5566 connect( cboJoinStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, [this] {
5567 if ( mLayer )
5568 {
5569 mLayer->setPenJoinStyle( cboJoinStyle->penJoinStyle() );
5570 emit changed();
5571 }
5572 } );
5573}
5574
5576
5578{
5579 if ( !layer )
5580 {
5581 return;
5582 }
5583
5584 if ( layer->layerType() != "FilledLine"_L1 )
5585 {
5586 return;
5587 }
5588
5589 mLayer = dynamic_cast<QgsFilledLineSymbolLayer *>( layer );
5590 if ( !mLayer )
5591 {
5592 return;
5593 }
5594
5595 whileBlocking( spinWidth )->setValue( mLayer->width() );
5596 whileBlocking( mPenWidthUnitWidget )->setUnit( mLayer->widthUnit() );
5597 whileBlocking( mPenWidthUnitWidget )->setMapUnitScale( mLayer->widthMapUnitScale() );
5598
5599 whileBlocking( mOffsetUnitWidget )->setUnit( mLayer->offsetUnit() );
5600 whileBlocking( mOffsetUnitWidget )->setMapUnitScale( mLayer->offsetMapUnitScale() );
5601 whileBlocking( spinOffset )->setValue( mLayer->offset() );
5602
5603 whileBlocking( cboJoinStyle )->setPenJoinStyle( mLayer->penJoinStyle() );
5604 whileBlocking( cboCapStyle )->setPenCapStyle( mLayer->penCapStyle() );
5605
5610}
5611
5616
5617//
5618// QgsLinearReferencingSymbolLayerWidget
5619//
5620
5622 : QgsSymbolLayerWidget( parent, vl )
5623{
5624 mLayer = nullptr;
5625
5626 setupUi( this );
5627
5628 mComboPlacement->addItem( tr( "Interval (Cartesian 2D Distances)" ), QVariant::fromValue( Qgis::LinearReferencingPlacement::IntervalCartesian2D ) );
5629 mComboPlacement->addItem( tr( "Interval (Z Values)" ), QVariant::fromValue( Qgis::LinearReferencingPlacement::IntervalZ ) );
5630 mComboPlacement->addItem( tr( "Interval (M Values)" ), QVariant::fromValue( Qgis::LinearReferencingPlacement::IntervalM ) );
5631 mComboPlacement->addItem( tr( "On Every Vertex" ), QVariant::fromValue( Qgis::LinearReferencingPlacement::Vertex ) );
5632
5633 mComboQuantity->addItem( tr( "Cartesian 2D Distance" ), QVariant::fromValue( Qgis::LinearReferencingLabelSource::CartesianDistance2D ) );
5634 mComboQuantity->addItem( tr( "Z Values" ), QVariant::fromValue( Qgis::LinearReferencingLabelSource::Z ) );
5635 mComboQuantity->addItem( tr( "M Values" ), QVariant::fromValue( Qgis::LinearReferencingLabelSource::M ) );
5636
5637 mSpinSkipMultiples->setClearValue( 0, tr( "Not set" ) );
5638 mSpinLabelOffsetX->setClearValue( 0 );
5639 mSpinLabelOffsetY->setClearValue( 0 );
5640 mSpinAverageAngleLength->setClearValue( 4.0 );
5641 mLabelOffsetUnitWidget->setUnits(
5643 );
5644 mAverageAngleUnit->setUnits(
5646 );
5647
5648 connect( mComboQuantity, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this] {
5649 if ( mLayer && !mBlockChangesSignal )
5650 {
5651 mLayer->setLabelSource( mComboQuantity->currentData().value<Qgis::LinearReferencingLabelSource>() );
5652 emit changed();
5653 }
5654 } );
5655 connect( mTextFormatButton, &QgsFontButton::changed, this, [this] {
5656 if ( mLayer && !mBlockChangesSignal )
5657 {
5658 mLayer->setTextFormat( mTextFormatButton->textFormat() );
5659 emit changed();
5660 }
5661 } );
5662 connect( spinInterval, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, [this] {
5663 if ( mLayer && !mBlockChangesSignal )
5664 {
5665 mLayer->setInterval( spinInterval->value() );
5666 emit changed();
5667 }
5668 } );
5669 connect( mSpinSkipMultiples, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, [this] {
5670 if ( mLayer && !mBlockChangesSignal )
5671 {
5672 mLayer->setSkipMultiplesOf( mSpinSkipMultiples->value() );
5673 emit changed();
5674 }
5675 } );
5676 connect( mCheckRotate, &QCheckBox::toggled, this, [this]( bool checked ) {
5677 if ( mLayer && !mBlockChangesSignal )
5678 {
5679 mLayer->setRotateLabels( checked );
5680 emit changed();
5681 }
5682 mSpinAverageAngleLength->setEnabled( checked );
5683 mAverageAngleUnit->setEnabled( mSpinAverageAngleLength->isEnabled() );
5684 } );
5685 connect( mCheckShowMarker, &QCheckBox::toggled, this, [this]( bool checked ) {
5686 if ( mLayer && !mBlockChangesSignal )
5687 {
5688 mLayer->setShowMarker( checked );
5689 emit symbolChanged();
5690 }
5691 } );
5692
5693 connect( mSpinLabelOffsetX, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, [this] {
5694 if ( mLayer && !mBlockChangesSignal )
5695 {
5696 mLayer->setLabelOffset( QPointF( mSpinLabelOffsetX->value(), mSpinLabelOffsetY->value() ) );
5697 emit changed();
5698 }
5699 } );
5700 connect( mSpinLabelOffsetY, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, [this] {
5701 if ( mLayer && !mBlockChangesSignal )
5702 {
5703 mLayer->setLabelOffset( QPointF( mSpinLabelOffsetX->value(), mSpinLabelOffsetY->value() ) );
5704 emit changed();
5705 }
5706 } );
5707 connect( mLabelOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
5708 if ( mLayer && !mBlockChangesSignal )
5709 {
5710 mLayer->setLabelOffsetUnit( mLabelOffsetUnitWidget->unit() );
5711 mLayer->setLabelOffsetMapUnitScale( mLabelOffsetUnitWidget->getMapUnitScale() );
5712 emit changed();
5713 }
5714 } );
5715
5716 connect( mComboPlacement, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this] {
5717 if ( mLayer && !mBlockChangesSignal )
5718 {
5719 const Qgis::LinearReferencingPlacement placement = mComboPlacement->currentData().value<Qgis::LinearReferencingPlacement>();
5720 mLayer->setPlacement( placement );
5721 switch ( placement )
5722 {
5726 mIntervalWidget->show();
5727 break;
5729 mIntervalWidget->hide();
5730 break;
5731 }
5732 emit changed();
5733 }
5734 } );
5735
5736 connect( mSpinAverageAngleLength, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, [this] {
5737 if ( mLayer && !mBlockChangesSignal )
5738 {
5739 mLayer->setAverageAngleLength( mSpinAverageAngleLength->value() );
5740 emit changed();
5741 }
5742 } );
5743 connect( mAverageAngleUnit, &QgsUnitSelectionWidget::changed, this, [this] {
5744 if ( mLayer && !mBlockChangesSignal )
5745 {
5746 mLayer->setAverageAngleUnit( mAverageAngleUnit->unit() );
5747 mLayer->setAverageAngleMapUnitScale( mAverageAngleUnit->getMapUnitScale() );
5748 emit changed();
5749 }
5750 } );
5751
5752 connect( mNumberFormatPushButton, &QPushButton::clicked, this, &QgsLinearReferencingSymbolLayerWidget::changeNumberFormat );
5753
5754 mTextFormatButton->registerExpressionContextGenerator( this );
5755}
5756
5758
5759
5761{
5762 if ( !layer || layer->layerType() != "LinearReferencing"_L1 )
5763 return;
5764
5765 // layer type is correct, we can do the cast
5766 mLayer = qgis::down_cast<QgsLinearReferencingSymbolLayer *>( layer );
5767
5768 mBlockChangesSignal = true;
5769
5770 mComboPlacement->setCurrentIndex( mComboPlacement->findData( QVariant::fromValue( mLayer->placement() ) ) );
5771 switch ( mLayer->placement() )
5772 {
5776 mIntervalWidget->show();
5777 break;
5779 mIntervalWidget->hide();
5780 break;
5781 }
5782
5783 mComboQuantity->setCurrentIndex( mComboQuantity->findData( QVariant::fromValue( mLayer->labelSource() ) ) );
5784
5785 mTextFormatButton->setTextFormat( mLayer->textFormat() );
5786 spinInterval->setValue( mLayer->interval() );
5787 mSpinSkipMultiples->setValue( mLayer->skipMultiplesOf() );
5788 mCheckRotate->setChecked( mLayer->rotateLabels() );
5789 mCheckShowMarker->setChecked( mLayer->showMarker() );
5790 mSpinLabelOffsetX->setValue( mLayer->labelOffset().x() );
5791 mSpinLabelOffsetY->setValue( mLayer->labelOffset().y() );
5792 mLabelOffsetUnitWidget->setUnit( mLayer->labelOffsetUnit() );
5793 mLabelOffsetUnitWidget->setMapUnitScale( mLayer->labelOffsetMapUnitScale() );
5794
5795 mAverageAngleUnit->setUnit( mLayer->averageAngleUnit() );
5796 mAverageAngleUnit->setMapUnitScale( mLayer->averageAngleMapUnitScale() );
5797 mSpinAverageAngleLength->setValue( mLayer->averageAngleLength() );
5798
5799 mSpinAverageAngleLength->setEnabled( mCheckRotate->isChecked() );
5800 mAverageAngleUnit->setEnabled( mSpinAverageAngleLength->isEnabled() );
5801
5806
5807 mBlockChangesSignal = false;
5808}
5809
5814
5816{
5818 mTextFormatButton->setMapCanvas( context.mapCanvas() );
5819 mTextFormatButton->setMessageBar( context.messageBar() );
5820}
5821
5822void QgsLinearReferencingSymbolLayerWidget::changeNumberFormat()
5823{
5825 if ( panel && panel->dockMode() )
5826 {
5828 widget->setPanelTitle( tr( "Number Format" ) );
5829 widget->setFormat( mLayer->numericFormat() );
5830 widget->registerExpressionContextGenerator( this );
5831 connect( widget, &QgsNumericFormatSelectorWidget::changed, this, [this, widget] {
5832 if ( !mBlockChangesSignal )
5833 {
5834 mLayer->setNumericFormat( widget->format() );
5835 emit changed();
5836 }
5837 } );
5838 panel->openPanel( widget );
5839 }
5840 else
5841 {
5842 QgsNumericFormatSelectorDialog dialog( this );
5843 dialog.setFormat( mLayer->numericFormat() );
5844 dialog.registerExpressionContextGenerator( this );
5845 if ( dialog.exec() )
5846 {
5847 mLayer->setNumericFormat( dialog.format() );
5848 emit changed();
5849 }
5850 }
5851}
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:3301
@ InnerVertices
Inner vertices (i.e. all vertices except the first and last vertex).
Definition qgis.h:3303
@ LastVertex
Place symbols on the last vertex in the line.
Definition qgis.h:3298
@ CentralPoint
Place symbols at the mid point of the line.
Definition qgis.h:3300
@ SegmentCenter
Place symbols at the center of every line segment.
Definition qgis.h:3302
@ Vertex
Place symbols on every vertex in the line.
Definition qgis.h:3297
@ Interval
Place symbols at regular intervals.
Definition qgis.h:3296
@ FirstVertex
Place symbols on the first vertex in the line.
Definition qgis.h:3299
MarkerClipMode
Marker clipping modes.
Definition qgis.h:3415
@ CompletelyWithin
Render complete markers wherever the completely fall within the polygon shape.
Definition qgis.h:3419
@ NoClipping
No clipping, render complete markers.
Definition qgis.h:3416
@ Shape
Clip to polygon shape.
Definition qgis.h:3417
@ CentroidWithin
Render complete markers wherever their centroid falls within the polygon shape.
Definition qgis.h:3418
LineClipMode
Line clipping modes.
Definition qgis.h:3429
@ NoClipping
Lines are not clipped, will extend to shape's bounding box.
Definition qgis.h:3432
@ ClipPainterOnly
Applying clipping on the painter only (i.e. line endpoints will coincide with polygon bounding box,...
Definition qgis.h:3430
@ ClipToIntersection
Clip lines to intersection with polygon shape (slower) (i.e. line endpoints will coincide with polygo...
Definition qgis.h:3431
@ ColorRamp
Gradient color ramp.
Definition qgis.h:3346
@ SimpleTwoColor
Simple two color gradient.
Definition qgis.h:3345
@ Repeat
Repeat gradient.
Definition qgis.h:3391
@ Reflect
Reflect gradient.
Definition qgis.h:3390
@ Pad
Pad out gradient using colors at endpoint of gradient.
Definition qgis.h:3389
PointCountMethod
Methods which define the number of points randomly filling a polygon.
Definition qgis.h:3403
@ Absolute
The point count is used as an absolute count of markers.
Definition qgis.h:3404
@ DensityBased
The point count is part of a marker density count.
Definition qgis.h:3405
@ Field
Field based property.
Definition qgis.h:711
MarkerShape
Marker shapes.
Definition qgis.h:3246
VerticalAnchorPoint
Marker symbol vertical anchor points.
Definition qgis.h:861
@ Bottom
Align to bottom of symbol.
Definition qgis.h:864
@ Center
Align to vertical center of symbol.
Definition qgis.h:863
@ Baseline
Align to baseline of symbol, e.g. font baseline for font marker symbol layers. Treated as Bottom if n...
Definition qgis.h:865
@ Top
Align to top of symbol.
Definition qgis.h:862
LinearReferencingPlacement
Defines how/where the labels should be placed in a linear referencing symbol layer.
Definition qgis.h:3315
@ IntervalZ
Place labels at regular intervals, linearly interpolated using Z values.
Definition qgis.h:3317
@ Vertex
Place labels on every vertex in the line.
Definition qgis.h:3319
@ IntervalM
Place labels at regular intervals, linearly interpolated using M values.
Definition qgis.h:3318
@ IntervalCartesian2D
Place labels at regular intervals, using Cartesian distance calculations on a 2D plane.
Definition qgis.h:3316
LinearReferencingLabelSource
Defines what quantity to use for the labels shown in a linear referencing symbol layer.
Definition qgis.h:3329
@ CartesianDistance2D
Distance along line, calculated using Cartesian calculations on a 2D plane.
Definition qgis.h:3330
@ Percentage
Percentage of another measurement (e.g., canvas size, feature size).
Definition qgis.h:5443
@ Millimeters
Millimeters.
Definition qgis.h:5440
@ Points
Points (e.g., for font sizes).
Definition qgis.h:5444
@ MapUnits
Map units.
Definition qgis.h:5441
@ Pixels
Pixels.
Definition qgis.h:5442
@ Inches
Inches.
Definition qgis.h:5445
@ MetersInMapUnits
Meters value as Map units.
Definition qgis.h:5447
@ Linear
Linear gradient.
Definition qgis.h:3359
@ Conical
Conical (polar) gradient.
Definition qgis.h:3361
@ Radial
Radial (circular) gradient.
Definition qgis.h:3360
SymbolType
Symbol types.
Definition qgis.h:636
@ Marker
Marker symbol.
Definition qgis.h:637
@ Line
Line symbol.
Definition qgis.h:638
@ Fill
Fill symbol.
Definition qgis.h:639
@ Hybrid
Hybrid symbol.
Definition qgis.h:640
SymbolCoordinateReference
Symbol coordinate reference modes.
Definition qgis.h:3373
@ Feature
Relative to feature/shape being rendered.
Definition qgis.h:3374
@ Viewport
Relative to the whole viewport/output device.
Definition qgis.h:3375
QFlags< MarkerLinePlacement > MarkerLinePlacements
Definition qgis.h:3306
HorizontalAnchorPoint
Marker symbol horizontal anchor points.
Definition qgis.h:847
@ Center
Align to horizontal center of symbol.
Definition qgis.h:849
@ Right
Align to right side of symbol.
Definition qgis.h:850
@ Left
Align to left side of symbol.
Definition qgis.h:848
static const double UI_SCALE_FACTOR
UI scaling factor.
Definition qgis.h:6690
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.
Q_INVOKABLE int indexFromName(const QString &fieldName) const
Gets the field index from the field name.
~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 unsetMapTool(QgsMapTool *mapTool)
Unset the current map tool or last non zoom 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.
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.
Qgis::PropertyType propertyType() const
Returns the property type.
QString field() const
Returns the current field name the property references.
bool isActive() const
Returns whether the property is currently active.
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.
@ 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.
static bool fieldIsReadOnly(const QgsVectorLayer *layer, int fieldIndex)
Returns true if the field at index fieldIndex from layer is editable, false if the field is read only...
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:6982
QList< QgsSymbolLayer * > QgsSymbolLayerList
Definition qgssymbol.h:30
class GUI_EXPORT QgsMapToolEditBlankSegments
Single variable definition for use within a QgsExpressionContextScope.