QGIS API Documentation 3.99.0-Master (d270888f95f)
Loading...
Searching...
No Matches
qgssymbolslistwidget.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgssymbolslist.cpp
3 ---------------------
4 begin : June 2012
5 copyright : (C) 2012 by Arunmozhi
6 email : aruntheguy at gmail.com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
17
18#include "qgsauxiliarystorage.h"
20#include "qgslinesymbol.h"
21#include "qgsmarkersymbol.h"
25#include "qgsstylesavedialog.h"
28#include "qgsvectorlayer.h"
29
30#include <QAction>
31#include <QMenu>
32#include <QMessageBox>
33#include <QString>
34
35#include "moc_qgssymbolslistwidget.cpp"
36
37using namespace Qt::StringLiterals;
38
39QgsSymbolsListWidget::QgsSymbolsListWidget( QgsSymbol *symbol, QgsStyle *style, QMenu *menu, QWidget *parent, QgsVectorLayer *layer )
40 : QWidget( parent )
41 , mSymbol( symbol )
42 , mStyle( style )
43 , mAdvancedMenu( menu )
44 , mLayer( layer )
45{
46 setupUi( this );
47 spinAngle->setClearValue( 0 );
48
49 mStyleItemsListWidget->setStyle( mStyle );
50 mStyleItemsListWidget->setEntityType( QgsStyle::SymbolEntity );
51 if ( mSymbol )
52 mStyleItemsListWidget->setSymbolType( mSymbol->type() );
53 mStyleItemsListWidget->setAdvancedMenu( menu );
54
55 mClipFeaturesAction = new QAction( tr( "Clip Features to Canvas Extent" ), this );
56 mClipFeaturesAction->setCheckable( true );
57 connect( mClipFeaturesAction, &QAction::toggled, this, &QgsSymbolsListWidget::clipFeaturesToggled );
58 mStandardizeRingsAction = new QAction( tr( "Force Right-Hand-Rule Orientation" ), this );
59 mStandardizeRingsAction->setCheckable( true );
60 connect( mStandardizeRingsAction, &QAction::toggled, this, &QgsSymbolsListWidget::forceRHRToggled );
61
62 mBufferSettingsAction = new QAction( tr( "Buffer Settings…" ), this );
63 connect( mBufferSettingsAction, &QAction::triggered, this, &QgsSymbolsListWidget::showBufferSettings );
64
65 mAnimationSettingsAction = new QAction( tr( "Animation Settings…" ), this );
66 connect( mAnimationSettingsAction, &QAction::triggered, this, &QgsSymbolsListWidget::showAnimationSettings );
67
68 mExtentBufferAction = new QAction( tr( "Extent Buffer…" ), this );
69 connect( mExtentBufferAction, &QAction::triggered, this, &QgsSymbolsListWidget::showExtentBufferSettings );
70
71 // select correct page in stacked widget
72 QgsPropertyOverrideButton *opacityDDBtn = nullptr;
73 switch ( symbol->type() )
74 {
76 {
77 stackedWidget->removeWidget( stackedWidget->widget( 2 ) );
78 stackedWidget->removeWidget( stackedWidget->widget( 1 ) );
79 mSymbolColorButton = btnMarkerColor;
80 opacityDDBtn = mMarkerOpacityDDBtn;
81 mSymbolOpacityWidget = mMarkerOpacityWidget;
82 mSymbolUnitWidget = mMarkerUnitWidget;
83 connect( spinAngle, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSymbolsListWidget::setMarkerAngle );
84 connect( spinSize, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSymbolsListWidget::setMarkerSize );
85 registerDataDefinedButton( mSizeDDBtn, QgsSymbolLayer::Property::Size );
87 registerDataDefinedButton( mRotationDDBtn, QgsSymbolLayer::Property::Angle );
89 break;
90 }
91
93 {
94 stackedWidget->removeWidget( stackedWidget->widget( 2 ) );
95 stackedWidget->removeWidget( stackedWidget->widget( 0 ) );
96 mSymbolColorButton = btnLineColor;
97 opacityDDBtn = mLineOpacityDDBtn;
98 mSymbolOpacityWidget = mLineOpacityWidget;
99 mSymbolUnitWidget = mLineUnitWidget;
100 connect( spinWidth, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsSymbolsListWidget::setLineWidth );
101 registerDataDefinedButton( mWidthDDBtn, QgsSymbolLayer::Property::StrokeWidth );
103 break;
104 }
105
107 {
108 stackedWidget->removeWidget( stackedWidget->widget( 1 ) );
109 stackedWidget->removeWidget( stackedWidget->widget( 0 ) );
110 mSymbolColorButton = btnFillColor;
111 opacityDDBtn = mFillOpacityDDBtn;
112 mSymbolOpacityWidget = mFillOpacityWidget;
113 mSymbolUnitWidget = mFillUnitWidget;
114 break;
115 }
116
118 break;
119 }
120
121 stackedWidget->setCurrentIndex( 0 );
122
124
125 if ( mSymbol )
126 {
127 updateSymbolInfo();
128 }
129
130 connect( mSymbolUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSymbolsListWidget::mSymbolUnitWidget_changed );
131 connect( mSymbolColorButton, &QgsColorButton::colorChanged, this, &QgsSymbolsListWidget::setSymbolColor );
132
133 if ( opacityDDBtn )
134 {
135 registerSymbolDataDefinedButton( opacityDDBtn, QgsSymbol::Property::Opacity );
136 }
137
138 connect( this, &QgsSymbolsListWidget::changed, this, &QgsSymbolsListWidget::updateAssistantSymbol );
139 if ( mSymbol )
140 {
141 updateAssistantSymbol();
142 }
143
144 mSymbolColorButton->setAllowOpacity( true );
145 mSymbolColorButton->setColorDialogTitle( tr( "Select Color" ) );
146 mSymbolColorButton->setContext( u"symbology"_s );
147
148 connect( mSymbolOpacityWidget, &QgsOpacityWidget::opacityChanged, this, &QgsSymbolsListWidget::opacityChanged );
149
150 connect( mStyleItemsListWidget, &QgsStyleItemsListWidget::selectionChangedWithStylePath, this, &QgsSymbolsListWidget::setSymbolFromStyle );
151 connect( mStyleItemsListWidget, &QgsStyleItemsListWidget::saveEntity, this, &QgsSymbolsListWidget::saveSymbol );
152}
153
155{
156 // This action was added to the menu by this widget, clean it up
157 // The menu can be passed in the constructor, so may live longer than this widget
158 mStyleItemsListWidget->advancedMenu()->removeAction( mClipFeaturesAction );
159 mStyleItemsListWidget->advancedMenu()->removeAction( mStandardizeRingsAction );
160 mStyleItemsListWidget->advancedMenu()->removeAction( mAnimationSettingsAction );
161 mStyleItemsListWidget->advancedMenu()->removeAction( mExtentBufferAction );
162 mStyleItemsListWidget->advancedMenu()->removeAction( mBufferSettingsAction );
163}
164
165void QgsSymbolsListWidget::registerDataDefinedButton( QgsPropertyOverrideButton *button, QgsSymbolLayer::Property key )
166{
167 button->setProperty( "propertyKey", static_cast<int>( key ) );
169
170 connect( button, &QgsPropertyOverrideButton::createAuxiliaryField, this, &QgsSymbolsListWidget::createAuxiliaryField );
171}
172
173void QgsSymbolsListWidget::createAuxiliaryField()
174{
175 // try to create an auxiliary layer if not yet created
176 if ( !mLayer->auxiliaryLayer() )
177 {
178 QgsNewAuxiliaryLayerDialog dlg( mLayer, this );
179 dlg.exec();
180 }
181
182 // return if still not exists
183 if ( !mLayer->auxiliaryLayer() )
184 return;
185
186 QgsPropertyOverrideButton *button = qobject_cast<QgsPropertyOverrideButton *>( sender() );
187 const QgsSymbolLayer::Property key = static_cast<QgsSymbolLayer::Property>( button->propertyKey() );
188 const QgsPropertyDefinition def = QgsSymbolLayer::propertyDefinitions()[static_cast<int>( key )];
189
190 // create property in auxiliary storage if necessary
191 if ( !mLayer->auxiliaryLayer()->exists( def ) )
192 mLayer->auxiliaryLayer()->addAuxiliaryField( def );
193
194 // update property with join field name from auxiliary storage
195 QgsProperty property = button->toProperty();
196 property.setField( QgsAuxiliaryLayer::nameFromProperty( def, true ) );
197 property.setActive( true );
198 button->updateFieldLists();
199 button->setToProperty( property );
200
201 QgsMarkerSymbol *markerSymbol = static_cast<QgsMarkerSymbol *>( mSymbol );
202 QgsLineSymbol *lineSymbol = static_cast<QgsLineSymbol *>( mSymbol );
203 switch ( key )
204 {
206 if ( markerSymbol )
207 markerSymbol->setDataDefinedAngle( button->toProperty() );
208 break;
209
211 if ( markerSymbol )
212 {
213 markerSymbol->setDataDefinedSize( button->toProperty() );
215 }
216 break;
217
219 if ( lineSymbol )
220 lineSymbol->setDataDefinedWidth( button->toProperty() );
221 break;
222
223 default:
224 break;
225 }
226
227 emit changed();
228}
229
230void QgsSymbolsListWidget::createSymbolAuxiliaryField()
231{
232 // try to create an auxiliary layer if not yet created
233 if ( !mLayer->auxiliaryLayer() )
234 {
235 QgsNewAuxiliaryLayerDialog dlg( mLayer, this );
236 dlg.exec();
237 }
238
239 // return if still not exists
240 if ( !mLayer->auxiliaryLayer() )
241 return;
242
243 QgsPropertyOverrideButton *button = qobject_cast<QgsPropertyOverrideButton *>( sender() );
244 const QgsSymbol::Property key = static_cast<QgsSymbol::Property>( button->propertyKey() );
245 const QgsPropertyDefinition def = QgsSymbol::propertyDefinitions()[static_cast<int>( key )];
246
247 // create property in auxiliary storage if necessary
248 if ( !mLayer->auxiliaryLayer()->exists( def ) )
249 mLayer->auxiliaryLayer()->addAuxiliaryField( def );
250
251 // update property with join field name from auxiliary storage
252 QgsProperty property = button->toProperty();
253 property.setField( QgsAuxiliaryLayer::nameFromProperty( def, true ) );
254 property.setActive( true );
255 button->updateFieldLists();
256 button->setToProperty( property );
257
258 mSymbol->setDataDefinedProperty( key, button->toProperty() );
259
260 emit changed();
261}
262
264{
265 mContext = context;
266 const auto unitSelectionWidgets { findChildren<QgsUnitSelectionWidget *>() };
267 for ( QgsUnitSelectionWidget *unitWidget : unitSelectionWidgets )
268 {
269 unitWidget->setMapCanvas( mContext.mapCanvas() );
270 }
271}
272
274{
275 return mContext;
276}
277
278void QgsSymbolsListWidget::forceRHRToggled( bool checked )
279{
280 if ( !mSymbol )
281 return;
282
283 mSymbol->setForceRHR( checked );
284 emit changed();
285}
286
287void QgsSymbolsListWidget::showAnimationSettings()
288{
289 QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( this );
290 if ( panel && panel->dockMode() )
291 {
292 QgsSymbolAnimationSettingsWidget *widget = new QgsSymbolAnimationSettingsWidget( panel );
293 widget->setPanelTitle( tr( "Animation Settings" ) );
294 widget->setAnimationSettings( mSymbol->animationSettings() );
295 connect( widget, &QgsPanelWidget::widgetChanged, this, [this, widget]() {
296 mSymbol->setAnimationSettings( widget->animationSettings() );
297 emit changed();
298 } );
299 panel->openPanel( widget );
300 return;
301 }
302
303 QgsSymbolAnimationSettingsDialog d( this );
304 d.setAnimationSettings( mSymbol->animationSettings() );
305 if ( d.exec() == QDialog::Accepted )
306 {
307 mSymbol->setAnimationSettings( d.animationSettings() );
308 emit changed();
309 }
310}
311
312void QgsSymbolsListWidget::showExtentBufferSettings()
313{
314 QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( this );
315 if ( panel && panel->dockMode() )
316 {
317 QgsExtentBufferWidget *widget = new QgsExtentBufferWidget( mSymbol, mLayer, panel );
318 widget->setPanelTitle( tr( "Extent Buffer" ) );
319 widget->setContext( mContext );
320
321 connect( widget, &QgsPanelWidget::widgetChanged, this, [this, widget]() {
322 mSymbol->setExtentBuffer( widget->extentBuffer() );
323 mSymbol->setDataDefinedProperty( QgsSymbol::Property::ExtentBuffer, widget->dataDefinedProperty() );
324 mSymbol->setExtentBufferSizeUnit( widget->sizeUnit() );
325
326 emit changed();
327 } );
328
329 panel->openPanel( widget );
330 }
331 else
332 {
333 QgsExtentBufferDialog dlg( mSymbol, mLayer, panel );
334
335 if ( dlg.widget() )
336 {
337 dlg.setContext( mContext );
338 }
339
340 if ( dlg.exec() == QDialog::Accepted )
341 {
342 mSymbol->setExtentBuffer( dlg.extentBuffer() );
343 mSymbol->setDataDefinedProperty( QgsSymbol::Property::ExtentBuffer, dlg.dataDefinedProperty() );
344 mSymbol->setExtentBufferSizeUnit( dlg.sizeUnit() );
345
346 emit changed();
347 }
348 }
349}
350
351void QgsSymbolsListWidget::showBufferSettings()
352{
353 QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( this );
354 if ( panel && panel->dockMode() )
355 {
356 QgsSymbolBufferSettingsWidget *widget = new QgsSymbolBufferSettingsWidget( panel );
357 widget->setPanelTitle( tr( "Buffer Settings" ) );
358 if ( const QgsSymbolBufferSettings *settings = mSymbol->bufferSettings() )
359 widget->setBufferSettings( *settings );
360
361 connect( widget, &QgsPanelWidget::widgetChanged, this, [this, widget]() {
362 mSymbol->setBufferSettings( new QgsSymbolBufferSettings( widget->bufferSettings() ) );
363 emit changed();
364 } );
365 panel->openPanel( widget );
366 return;
367 }
368
369 QgsSymbolBufferSettingsDialog d( this );
370 if ( const QgsSymbolBufferSettings *settings = mSymbol->bufferSettings() )
371 d.setBufferSettings( *settings );
372 if ( d.exec() == QDialog::Accepted )
373 {
374 mSymbol->setBufferSettings( new QgsSymbolBufferSettings( d.bufferSettings() ) );
375 emit changed();
376 }
377}
378
379void QgsSymbolsListWidget::saveSymbol()
380{
381 QgsStyleSaveDialog saveDlg( this );
382 saveDlg.setDefaultTags( mStyleItemsListWidget->currentTagFilter() );
383 if ( !saveDlg.exec() )
384 return;
385
386 if ( saveDlg.name().isEmpty() )
387 return;
388
389 QgsStyle *style = saveDlg.destinationStyle();
390 if ( !style )
391 return;
392
393 // check if there is no symbol with same name
394 if ( style->symbolNames().contains( saveDlg.name() ) )
395 {
396 const int res = QMessageBox::warning( this, tr( "Save Symbol" ), tr( "Symbol with name '%1' already exists. Overwrite?" ).arg( saveDlg.name() ), QMessageBox::Yes | QMessageBox::No );
397 if ( res != QMessageBox::Yes )
398 {
399 return;
400 }
401 style->removeSymbol( saveDlg.name() );
402 }
403
404 const QStringList symbolTags = saveDlg.tags().split( ',' );
405
406 // add new symbol to style and re-populate the list
407 QgsSymbol *newSymbol = mSymbol->clone();
408 style->addSymbol( saveDlg.name(), newSymbol );
409
410 // make sure the symbol is stored
411 style->saveSymbol( saveDlg.name(), newSymbol, saveDlg.isFavorite(), symbolTags );
412}
413
414void QgsSymbolsListWidget::updateSymbolDataDefinedProperty()
415{
416 if ( !mSymbol )
417 return;
418
419 QgsPropertyOverrideButton *button = qobject_cast<QgsPropertyOverrideButton *>( sender() );
420 const QgsSymbol::Property key = static_cast<QgsSymbol::Property>( button->propertyKey() );
421 mSymbol->setDataDefinedProperty( key, button->toProperty() );
422 emit changed();
423}
424
425void QgsSymbolsListWidget::registerSymbolDataDefinedButton( QgsPropertyOverrideButton *button, QgsSymbol::Property key )
426{
427 button->init( static_cast<int>( key ), mSymbol ? mSymbol->dataDefinedProperties() : QgsPropertyCollection(), QgsSymbol::propertyDefinitions(), mLayer, true );
428 connect( button, &QgsPropertyOverrideButton::changed, this, &QgsSymbolsListWidget::updateSymbolDataDefinedProperty );
429 connect( button, &QgsPropertyOverrideButton::createAuxiliaryField, this, &QgsSymbolsListWidget::createSymbolAuxiliaryField );
430
432}
433
435{
436 if ( !mSymbol )
437 return;
438
439 mSymbol->setClipFeaturesToExtent( checked );
440 emit changed();
441}
442
443void QgsSymbolsListWidget::setSymbolColor( const QColor &color )
444{
445 mSymbol->setColor( color );
446 emit changed();
447}
448
450{
451 QgsMarkerSymbol *markerSymbol = static_cast<QgsMarkerSymbol *>( mSymbol );
452 if ( markerSymbol->angle() == angle )
453 return;
454 markerSymbol->setAngle( angle );
455 emit changed();
456}
457
459{
460 QgsMarkerSymbol *markerSymbol = static_cast<QgsMarkerSymbol *>( mSymbol );
461 const QgsProperty dd( mRotationDDBtn->toProperty() );
462
463 spinAngle->setEnabled( !mRotationDDBtn->isActive() );
464
465 const QgsProperty symbolDD( markerSymbol->dataDefinedAngle() );
466
467 if ( // shall we remove datadefined expressions for layers ?
468 ( !symbolDD && !dd )
469 // shall we set the "en masse" expression for properties ?
470 || dd
471 )
472 {
473 markerSymbol->setDataDefinedAngle( dd );
474 emit changed();
475 }
476}
477
479{
480 QgsMarkerSymbol *markerSymbol = static_cast<QgsMarkerSymbol *>( mSymbol );
481 if ( markerSymbol->size() == size )
482 return;
483 markerSymbol->setSize( size );
484 emit changed();
485}
486
488{
489 QgsMarkerSymbol *markerSymbol = static_cast<QgsMarkerSymbol *>( mSymbol );
490 const QgsProperty dd( mSizeDDBtn->toProperty() );
491
492 spinSize->setEnabled( !mSizeDDBtn->isActive() );
493
494 const QgsProperty symbolDD( markerSymbol->dataDefinedSize() );
495
496 if ( // shall we remove datadefined expressions for layers ?
497 ( !symbolDD && !dd )
498 // shall we set the "en masse" expression for properties ?
499 || dd
500 )
501 {
502 markerSymbol->setDataDefinedSize( dd );
504 emit changed();
505 }
506}
507
509{
510 QgsLineSymbol *lineSymbol = static_cast<QgsLineSymbol *>( mSymbol );
511 if ( lineSymbol->width() == width )
512 return;
513 lineSymbol->setWidth( width );
514 emit changed();
515}
516
518{
519 QgsLineSymbol *lineSymbol = static_cast<QgsLineSymbol *>( mSymbol );
520 const QgsProperty dd( mWidthDDBtn->toProperty() );
521
522 spinWidth->setEnabled( !mWidthDDBtn->isActive() );
523
524 const QgsProperty symbolDD( lineSymbol->dataDefinedWidth() );
525
526 if ( // shall we remove datadefined expressions for layers ?
527 ( !symbolDD && !dd )
528 // shall we set the "en masse" expression for properties ?
529 || dd
530 )
531 {
532 lineSymbol->setDataDefinedWidth( dd );
533 emit changed();
534 }
535}
536
537void QgsSymbolsListWidget::updateAssistantSymbol()
538{
539 mAssistantSymbol.reset( mSymbol->clone() );
540 if ( mSymbol->type() == Qgis::SymbolType::Marker )
541 mSizeDDBtn->setSymbol( mAssistantSymbol );
542 else if ( mSymbol->type() == Qgis::SymbolType::Line && mLayer )
543 mWidthDDBtn->setSymbol( mAssistantSymbol );
544}
545
546void QgsSymbolsListWidget::mSymbolUnitWidget_changed()
547{
548 if ( mSymbol )
549 {
550 mSymbol->setOutputUnit( mSymbolUnitWidget->unit() );
551 mSymbol->setMapUnitScale( mSymbolUnitWidget->getMapUnitScale() );
552
553 emit changed();
554 }
555}
556
557void QgsSymbolsListWidget::opacityChanged( double opacity )
558{
559 if ( mSymbol )
560 {
561 mSymbol->setOpacity( opacity );
562 emit changed();
563 }
564}
565
566void QgsSymbolsListWidget::updateSymbolColor()
567{
568 mSymbolColorButton->blockSignals( true );
569 mSymbolColorButton->setColor( mSymbol->color() );
570 mSymbolColorButton->blockSignals( false );
571}
572
574{
575 if ( auto *lExpressionContext = mContext.expressionContext() )
576 return QgsExpressionContext( *lExpressionContext );
577
578 //otherwise create a default symbol context
579 QgsExpressionContext expContext( mContext.globalProjectAtlasMapLayerScopes( layer() ) );
580
581 // additional scopes
582 const auto constAdditionalExpressionContextScopes = mContext.additionalExpressionContextScopes();
583 for ( const QgsExpressionContextScope &scope : constAdditionalExpressionContextScopes )
584 {
585 expContext.appendScope( new QgsExpressionContextScope( scope ) );
586 }
587
589
590 return expContext;
591}
592
593void QgsSymbolsListWidget::updateSymbolInfo()
594{
595 updateSymbolColor();
596
597 const QList<QgsPropertyOverrideButton *> overrideButtons { findChildren<QgsPropertyOverrideButton *>() };
598 for ( QgsPropertyOverrideButton *button : overrideButtons )
599 {
601 }
602
603 if ( mSymbol->type() == Qgis::SymbolType::Marker )
604 {
605 QgsMarkerSymbol *markerSymbol = static_cast<QgsMarkerSymbol *>( mSymbol );
606 spinSize->setValue( markerSymbol->size() );
607 spinAngle->setValue( markerSymbol->angle() );
608
609 if ( mLayer )
610 {
611 const QgsProperty ddSize( markerSymbol->dataDefinedSize() );
612 mSizeDDBtn->init( static_cast<int>( QgsSymbolLayer::Property::Size ), ddSize, QgsSymbolLayer::propertyDefinitions(), mLayer, true );
613 spinSize->setEnabled( !mSizeDDBtn->isActive() );
614 const QgsProperty ddAngle( markerSymbol->dataDefinedAngle() );
615 mRotationDDBtn->init( static_cast<int>( QgsSymbolLayer::Property::Angle ), ddAngle, QgsSymbolLayer::propertyDefinitions(), mLayer, true );
616 spinAngle->setEnabled( !mRotationDDBtn->isActive() );
617 }
618 else
619 {
620 mSizeDDBtn->setEnabled( false );
621 mRotationDDBtn->setEnabled( false );
622 }
623 }
624 else if ( mSymbol->type() == Qgis::SymbolType::Line )
625 {
626 QgsLineSymbol *lineSymbol = static_cast<QgsLineSymbol *>( mSymbol );
627 spinWidth->setValue( lineSymbol->width() );
628
629 if ( mLayer )
630 {
631 const QgsProperty dd( lineSymbol->dataDefinedWidth() );
632 mWidthDDBtn->init( static_cast<int>( QgsSymbolLayer::Property::StrokeWidth ), dd, QgsSymbolLayer::propertyDefinitions(), mLayer, true );
633 spinWidth->setEnabled( !mWidthDDBtn->isActive() );
634 }
635 else
636 {
637 mWidthDDBtn->setEnabled( false );
638 }
639 }
640
641 mSymbolUnitWidget->blockSignals( true );
642 mSymbolUnitWidget->setUnit( mSymbol->outputUnit() );
643 mSymbolUnitWidget->setMapUnitScale( mSymbol->mapUnitScale() );
644 mSymbolUnitWidget->blockSignals( false );
645
646 mSymbolOpacityWidget->setOpacity( mSymbol->opacity() );
647
648 // Clean up previous advanced symbol actions
649 const QList<QAction *> actionList( mStyleItemsListWidget->advancedMenu()->actions() );
650 for ( QAction *action : actionList )
651 {
652 for ( QAction *actionsToRemove :
653 {
654 mClipFeaturesAction,
655 mStandardizeRingsAction,
656 mAnimationSettingsAction,
657 mExtentBufferAction,
658 mBufferSettingsAction
659 } )
660 {
661 if ( actionsToRemove->text() == action->text() )
662 {
663 mStyleItemsListWidget->advancedMenu()->removeAction( action );
664 break;
665 }
666 }
667 }
668
669 if ( mSymbol->type() == Qgis::SymbolType::Line || mSymbol->type() == Qgis::SymbolType::Fill )
670 {
671 //add clip features option for line or fill symbols
672 mStyleItemsListWidget->advancedMenu()->addAction( mClipFeaturesAction );
673 }
674 if ( mSymbol->type() == Qgis::SymbolType::Fill )
675 {
676 mStyleItemsListWidget->advancedMenu()->addAction( mStandardizeRingsAction );
677 }
678 if ( mSymbol->type() == Qgis::SymbolType::Marker )
679 {
680 mStyleItemsListWidget->advancedMenu()->addAction( mBufferSettingsAction );
681 }
682 mStyleItemsListWidget->advancedMenu()->addAction( mAnimationSettingsAction );
683 mStyleItemsListWidget->advancedMenu()->addAction( mExtentBufferAction );
684
685 mStyleItemsListWidget->showAdvancedButton( mAdvancedMenu || !mStyleItemsListWidget->advancedMenu()->isEmpty() );
686
687 whileBlocking( mClipFeaturesAction )->setChecked( mSymbol->clipFeaturesToExtent() );
688 whileBlocking( mStandardizeRingsAction )->setChecked( mSymbol->forceRHR() );
689}
690
691void QgsSymbolsListWidget::setSymbolFromStyle( const QString &name, QgsStyle::StyleEntity, const QString &stylePath )
692{
693 if ( name.isEmpty() )
694 return;
695
696 QgsStyle *style = nullptr;
697 if ( mStyle != QgsStyle::defaultStyle() )
698 {
699 // get new instance of symbol from style
700 style = mStyle;
701 }
702 else
703 {
704 style = QgsProject::instance()->styleSettings()->styleAtPath( stylePath );
705 }
706
707 if ( !style )
708 return;
709
710 // get new instance of symbol from style
711 std::unique_ptr<QgsSymbol> s( style->symbol( name ) );
712 if ( !s )
713 return;
714
715 // remove all symbol layers from original symbolgroupsCombo
716 while ( mSymbol->symbolLayerCount() )
717 mSymbol->deleteSymbolLayer( 0 );
718 // move all symbol layers to our symbol
719 while ( s->symbolLayerCount() )
720 {
721 QgsSymbolLayer *sl = s->takeSymbolLayer( 0 );
722 mSymbol->appendSymbolLayer( sl );
723 }
724 mSymbol->setOpacity( s->opacity() );
725 mSymbol->setFlags( s->flags() );
726
727 updateSymbolInfo();
728 emit changed();
729}
@ ScaleDiameter
Calculate scale by the diameter.
Definition qgis.h:645
@ Millimeters
Millimeters.
Definition qgis.h:5256
@ Points
Points (e.g., for font sizes).
Definition qgis.h:5260
@ MapUnits
Map units.
Definition qgis.h:5257
@ Pixels
Pixels.
Definition qgis.h:5258
@ Inches
Inches.
Definition qgis.h:5261
@ MetersInMapUnits
Meters value as Map units.
Definition qgis.h:5263
@ Marker
Marker symbol.
Definition qgis.h:630
@ Line
Line symbol.
Definition qgis.h:631
@ Fill
Fill symbol.
Definition qgis.h:632
@ Hybrid
Hybrid symbol.
Definition qgis.h:633
static QString nameFromProperty(const QgsPropertyDefinition &def, bool joined=false)
Returns the name of the auxiliary field for a property definition.
void colorChanged(const QColor &color)
Emitted whenever a new color is set for the button.
virtual QgsExpressionContext createExpressionContext() const =0
This method needs to be reimplemented in all classes which implement this interface and return an exp...
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.
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.
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 setContext(const QgsSymbolWidgetContext &context)
Sets the context in which widget is shown, e.g., the associated map canvas and expression contexts.
double extentBuffer() const
Returns the extent buffer value currently set in the widget.
QgsProperty dataDefinedProperty() const
Returns the data defined property currently set in the widget.
Qgis::RenderUnit sizeUnit() const
Returns the extent buffer unit currently set in the widget.
A line symbol type, for rendering LineString and MultiLineString geometries.
void setDataDefinedWidth(const QgsProperty &property) const
Set data defined width for whole symbol (including all symbol layers).
void setWidth(double width) const
Sets the width for the whole line symbol.
double width() const
Returns the estimated width for the whole symbol, which is the maximum width of all marker symbol lay...
QgsProperty dataDefinedWidth() const
Returns data defined width for whole symbol (including all symbol layers).
A marker symbol type, for rendering Point and MultiPoint geometries.
void setScaleMethod(Qgis::ScaleMethod scaleMethod) const
Sets the method to use for scaling the marker's size.
void setAngle(double symbolAngle) const
Sets the angle for the whole symbol.
void setSize(double size) const
Sets the size for the whole symbol.
QgsProperty dataDefinedAngle() const
Returns data defined angle for whole symbol (including all symbol layers).
double size() const
Returns the estimated size for the whole symbol, which is the maximum size of all marker symbol layer...
double angle() const
Returns the marker angle for the whole symbol.
QgsProperty dataDefinedSize() const
Returns data defined size for whole symbol (including all symbol layers).
void setDataDefinedSize(const QgsProperty &property) const
Set data defined size for whole symbol (including all symbol layers).
void setDataDefinedAngle(const QgsProperty &property)
Set data defined angle for whole symbol (including all symbol layers).
void opacityChanged(double opacity)
Emitted when the opacity is changed in the widget, where opacity ranges from 0.0 (transparent) to 1....
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.
QgsStyle * styleAtPath(const QString &path)
Returns a reference to the style database associated with the project with matching file path.
static QgsProject * instance()
Returns the QgsProject singleton instance.
const QgsProjectStyleSettings * styleSettings() const
Returns the project's style settings, which contains settings and properties relating to how a QgsPro...
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.
A store for object properties.
void setField(const QString &field)
Sets the field name the property references.
void saveEntity()
Emitted when the user has opted to save a new entity to the style database, by clicking the "Save" bu...
void selectionChangedWithStylePath(const QString &name, QgsStyle::StyleEntity type, const QString &stylePath)
Emitted when the selected item is changed in the widget.
A database of saved style entities, including symbols, color ramps, text formats and others.
Definition qgsstyle.h:89
bool removeSymbol(const QString &name)
Removes symbol from style (and delete it).
Definition qgsstyle.cpp:286
QgsSymbol * symbol(const QString &name)
Returns a NEW copy of symbol.
Definition qgsstyle.cpp:320
StyleEntity
Enum for Entities involved in a style.
Definition qgsstyle.h:205
@ SymbolEntity
Symbols.
Definition qgsstyle.h:206
static QgsStyle * defaultStyle(bool initialize=true)
Returns the default application-wide style.
Definition qgsstyle.cpp:150
bool saveSymbol(const QString &name, const QgsSymbol *symbol, bool favorite, const QStringList &tags)
Adds the symbol to the database with tags.
Definition qgsstyle.cpp:253
bool addSymbol(const QString &name, QgsSymbol *symbol, bool update=false)
Adds a symbol to style and takes symbol's ownership.
Definition qgsstyle.cpp:228
QStringList symbolNames() const
Returns a list of names of symbols.
Definition qgsstyle.cpp:342
void setAnimationSettings(const QgsSymbolAnimationSettings &settings)
Sets the animation settings to show in the widget.
QgsSymbolAnimationSettings animationSettings() const
Returns the animation settings as defined in the widget.
QgsSymbolBufferSettings bufferSettings() const
Returns the buffer settings as defined in the widget.
void setBufferSettings(const QgsSymbolBufferSettings &settings)
Sets the buffer settings to show in the widget.
Property
Data definable properties.
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,...
Abstract base class for all rendered symbols.
Definition qgssymbol.h:231
Property
Data definable properties.
Definition qgssymbol.h:270
@ ExtentBuffer
Extent buffer.
Definition qgssymbol.h:272
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the symbol property definitions.
virtual QgsSymbol * clone() const =0
Returns a deep copy of this symbol.
Qgis::SymbolType type() const
Returns the symbol's type.
Definition qgssymbol.h:294
void setForceRHR(bool force)
Sets whether polygon features drawn by the symbol should be reoriented to follow the standard right-h...
Definition qgssymbol.h:725
void setLineWidth(double width)
QgsSymbolWidgetContext context() const
Returns the context in which the symbol widget is shown, e.g., the associated map canvas and expressi...
void setContext(const QgsSymbolWidgetContext &context)
Sets the context in which the symbol widget is shown, e.g., the associated map canvas and expression ...
void setSymbolColor(const QColor &color)
void setMarkerAngle(double angle)
QgsSymbolsListWidget(QgsSymbol *symbol, QgsStyle *style, QMenu *menu, QWidget *parent, QgsVectorLayer *layer=nullptr)
Constructor for QgsSymbolsListWidget.
const QgsVectorLayer * layer() const
Returns the vector layer associated with the widget.
void changed()
Emitted when the symbol is modified in the widget.
void clipFeaturesToggled(bool checked)
void setMarkerSize(double size)
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.
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:6804