QGIS API Documentation 4.2.0-Belém do Pará (ec9a7f91d0f)
Loading...
Searching...
No Matches
qgssymbolselectordialog.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgssymbolselectordialog.cpp
3 ---------------------
4 begin : November 2009
5 copyright : (C) 2009 by Martin Dobias
6 email : wonder dot sk at gmail dot 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
19#include "qgsscreenhelper.h"
20#include "qgsstyle.h"
21#include "qgssymbol.h"
22#include "qgssymbollayer.h"
24#include "qgssymbollayerutils.h"
25
26#include <QString>
27
28#include "moc_qgssymbolselectordialog.cpp"
29
30using namespace Qt::StringLiterals;
31
32// the widgets
35#include "qgsapplication.h"
36#include "qgsvectorlayer.h"
37#include "qgssvgcache.h"
38#include "qgsimagecache.h"
39#include "qgsproject.h"
40#include "qgsguiutils.h"
41#include "qgsgui.h"
42#include "qgsmarkersymbol.h"
43#include "qgslinesymbol.h"
44#include "qscreen.h"
45
46#include <QColorDialog>
47#include <QPainter>
48#include <QStandardItemModel>
49#include <QInputDialog>
50#include <QMessageBox>
51#include <QKeyEvent>
52#include <QMenu>
53
54#include <QWidget>
55#include <QFile>
56#include <QStandardItem>
57#include <memory>
58
60
61static const int SYMBOL_LAYER_ITEM_TYPE = QStandardItem::UserType + 1;
62
63DataDefinedRestorer::DataDefinedRestorer( QgsSymbol *symbol, const QgsSymbolLayer *symbolLayer )
64
65{
66 if ( symbolLayer->type() == Qgis::SymbolType::Marker && symbol->type() == Qgis::SymbolType::Marker )
67 {
68 Q_ASSERT( symbol->type() == Qgis::SymbolType::Marker );
69 mMarker = static_cast<QgsMarkerSymbol *>( symbol );
70 mMarkerSymbolLayer = static_cast<const QgsMarkerSymbolLayer *>( symbolLayer );
71 mDDSize = mMarker->dataDefinedSize();
72 mDDAngle = mMarker->dataDefinedAngle();
73 // check if restore is actually needed
74 if ( !mDDSize && !mDDAngle )
75 mMarker = nullptr;
76 }
77 else if ( symbolLayer->type() == Qgis::SymbolType::Line && symbol->type() == Qgis::SymbolType::Line )
78 {
79 mLine = static_cast<QgsLineSymbol *>( symbol );
80 mLineSymbolLayer = static_cast<const QgsLineSymbolLayer *>( symbolLayer );
81 mDDWidth = mLine->dataDefinedWidth();
82 // check if restore is actually needed
83 if ( !mDDWidth )
84 mLine = nullptr;
85 }
86 save();
87}
88
89void DataDefinedRestorer::save()
90{
91 if ( mMarker )
92 {
93 mSize = mMarkerSymbolLayer->size();
94 mAngle = mMarkerSymbolLayer->angle();
95 mMarkerOffset = mMarkerSymbolLayer->offset();
96 }
97 else if ( mLine )
98 {
99 mWidth = mLineSymbolLayer->width();
100 mLineOffset = mLineSymbolLayer->offset();
101 }
102}
103
104void DataDefinedRestorer::restore()
105{
106 if ( mMarker && mMarker->symbolLayerCount() > 1 )
107 {
108 if ( mDDSize && ( mSize != mMarkerSymbolLayer->size() || mMarkerOffset != mMarkerSymbolLayer->offset() ) )
109 mMarker->setDataDefinedSize( mDDSize );
110 if ( mDDAngle && mAngle != mMarkerSymbolLayer->angle() )
111 mMarker->setDataDefinedAngle( mDDAngle );
112 }
113 else if ( mLine && mLine->symbolLayerCount() > 1 )
114 {
115 if ( mDDWidth && ( mWidth != mLineSymbolLayer->width() || mLineOffset != mLineSymbolLayer->offset() ) )
116 mLine->setDataDefinedWidth( mDDWidth );
117 }
118 save();
119}
120
121// Hybrid item which may represent a symbol or a layer
122// Check using item->isLayer()
123class SymbolLayerItem : public QStandardItem
124{
125 public:
126 explicit SymbolLayerItem( QgsSymbolLayer *layer, Qgis::SymbolType symbolType, QgsVectorLayer *vectorLayer, QScreen *screen )
127 : mVectorLayer( vectorLayer )
128 {
129 setLayer( layer, symbolType, screen );
130 }
131
132 explicit SymbolLayerItem( QgsSymbol *symbol, QgsVectorLayer *vectorLayer, QScreen *screen )
133 : mVectorLayer( vectorLayer )
134 {
135 setSymbol( symbol, screen );
136 }
137
138 void setLayer( QgsSymbolLayer *layer, Qgis::SymbolType symbolType, QScreen *screen )
139 {
140 mLayer = layer;
141 mIsLayer = true;
142 mSymbol = nullptr;
143 mSymbolType = symbolType;
144 updatePreview( screen );
145 }
146
147 void setSymbol( QgsSymbol *symbol, QScreen *screen )
148 {
149 mSymbol = symbol;
150 mIsLayer = false;
151 mLayer = nullptr;
152 updatePreview( screen );
153 }
154
155 void updatePreview( QScreen *screen )
156 {
157 if ( !mSize.isValid() )
158 {
159 const int size = QgsGuiUtils::scaleIconSize( 16 );
160 mSize = QSize( size, size );
161 }
162 QIcon icon;
163 if ( mIsLayer )
164 icon = QgsSymbolLayerUtils::symbolLayerPreviewIcon( mLayer, Qgis::RenderUnit::Millimeters, mSize, QgsMapUnitScale(), mSymbol ? mSymbol->type() : mSymbolType, mVectorLayer, QgsScreenProperties( screen ) );
165 else
166 {
167 QgsExpressionContext expContext;
169 icon = QIcon( QgsSymbolLayerUtils::symbolPreviewPixmap( mSymbol, mSize, 0, nullptr, false, &expContext, nullptr, QgsScreenProperties( screen ) ) );
170 }
171 setIcon( icon );
172
173 if ( auto *lParent = parent() )
174 static_cast<SymbolLayerItem *>( lParent )->updatePreview( screen );
175 }
176
177 int type() const override { return SYMBOL_LAYER_ITEM_TYPE; }
178 bool isLayer() const { return mIsLayer; }
179
180 // returns the symbol pointer; helpful in determining a layer's parent symbol
181 QgsSymbol *symbol() { return mSymbol; }
182
183 QgsSymbolLayer *layer() { return mLayer; }
184
185 QVariant data( int role ) const override
186 {
187 if ( role == Qt::DisplayRole || role == Qt::EditRole )
188 {
189 if ( mIsLayer )
190 {
191 QgsSymbolLayerAbstractMetadata *m = QgsApplication::symbolLayerRegistry()->symbolLayerMetadata( mLayer->layerType() );
192 if ( m )
193 return m->visibleName();
194 else
195 return QString();
196 }
197 else
198 {
199 switch ( mSymbol->type() )
200 {
202 return QCoreApplication::translate( "SymbolLayerItem", "Marker" );
204 return QCoreApplication::translate( "SymbolLayerItem", "Fill" );
206 return QCoreApplication::translate( "SymbolLayerItem", "Line" );
207 default:
208 return "Symbol";
209 }
210 }
211 }
212 else if ( role == Qt::ForegroundRole && mIsLayer )
213 {
214 if ( !mLayer->enabled() )
215 {
216 QPalette pal = qApp->palette();
217 QBrush brush = QStandardItem::data( role ).value<QBrush>();
218 brush.setColor( pal.color( QPalette::Disabled, QPalette::WindowText ) );
219 return brush;
220 }
221 else
222 {
223 return QVariant();
224 }
225 }
226
227 // if ( role == Qt::SizeHintRole )
228 // return QVariant( QSize( 32, 32 ) );
229 if ( role == Qt::CheckStateRole )
230 return QVariant(); // could be true/false
231 return QStandardItem::data( role );
232 }
233
234 protected:
235 QgsSymbolLayer *mLayer = nullptr;
236 QgsSymbol *mSymbol = nullptr;
237 QPointer<QgsVectorLayer> mVectorLayer;
238 bool mIsLayer = false;
239 QSize mSize;
241};
242
244
246
248 : QgsPanelWidget( parent )
249 , mStyle( style )
250 , mSymbol( symbol )
251 , mVectorLayer( vl )
252{
253#ifdef Q_OS_MAC
254 setWindowModality( Qt::WindowModal );
255#endif
256
257 setupUi( this );
258 this->layout()->setContentsMargins( 0, 0, 0, 0 );
259
260 layersTree->setMaximumHeight( static_cast<int>( Qgis::UI_SCALE_FACTOR * fontMetrics().height() * 7 ) );
261 layersTree->setMinimumHeight( layersTree->maximumHeight() );
262 lblPreview->setMaximumWidth( layersTree->maximumHeight() );
263
264 // setup icons
265 btnAddLayer->setIcon( QIcon( QgsApplication::iconPath( "symbologyAdd.svg" ) ) );
266 btnRemoveLayer->setIcon( QIcon( QgsApplication::iconPath( "symbologyRemove.svg" ) ) );
267 QIcon iconLock;
268 iconLock.addFile( QgsApplication::iconPath( u"locked.svg"_s ), QSize(), QIcon::Normal, QIcon::On );
269 iconLock.addFile( QgsApplication::iconPath( u"locked.svg"_s ), QSize(), QIcon::Active, QIcon::On );
270 iconLock.addFile( QgsApplication::iconPath( u"unlocked.svg"_s ), QSize(), QIcon::Normal, QIcon::Off );
271 iconLock.addFile( QgsApplication::iconPath( u"unlocked.svg"_s ), QSize(), QIcon::Active, QIcon::Off );
272
273 QIcon iconColorLock;
274 iconColorLock.addFile( QgsApplication::iconPath( u"mIconColorLocked.svg"_s ), QSize(), QIcon::Normal, QIcon::On );
275 iconColorLock.addFile( QgsApplication::iconPath( u"mIconColorLocked.svg"_s ), QSize(), QIcon::Active, QIcon::On );
276 iconColorLock.addFile( QgsApplication::iconPath( u"mIconColorUnlocked.svg"_s ), QSize(), QIcon::Normal, QIcon::Off );
277 iconColorLock.addFile( QgsApplication::iconPath( u"mIconColorUnlocked.svg"_s ), QSize(), QIcon::Active, QIcon::Off );
278
279 mLockColorAction = new QAction( tr( "Lock Color" ), this );
280 mLockColorAction->setToolTip( tr( "Avoid changing the color of the layer when the symbol color is changed" ) );
281 mLockColorAction->setCheckable( true );
282 mLockColorAction->setIcon( iconColorLock );
283
284 QIcon iconSelectLock;
285 iconSelectLock.addFile( QgsApplication::iconPath( u"mIconSelectLocked.svg"_s ), QSize(), QIcon::Normal, QIcon::On );
286 iconSelectLock.addFile( QgsApplication::iconPath( u"mIconSelectLocked.svg"_s ), QSize(), QIcon::Active, QIcon::On );
287 iconSelectLock.addFile( QgsApplication::iconPath( u"mIconSelectUnlocked.svg"_s ), QSize(), QIcon::Normal, QIcon::Off );
288 iconSelectLock.addFile( QgsApplication::iconPath( u"mIconSelectUnlocked.svg"_s ), QSize(), QIcon::Active, QIcon::Off );
289
290 mLockSelectionColorAction = new QAction( tr( "Lock Color When Selected" ), this );
291 mLockSelectionColorAction->setToolTip( tr( "Avoid changing the color of the layer when a feature is selected" ) );
292 mLockSelectionColorAction->setCheckable( true );
293 mLockSelectionColorAction->setIcon( iconSelectLock );
294
295 QMenu *lockMenu = new QMenu( this );
296 lockMenu->addAction( mLockColorAction );
297 lockMenu->addAction( mLockSelectionColorAction );
298 btnLock->setMenu( lockMenu );
299 btnLock->setPopupMode( QToolButton::InstantPopup );
300
301 btnDuplicate->setIcon( QIcon( QgsApplication::iconPath( "mActionDuplicateLayer.svg" ) ) );
302 btnUp->setIcon( QIcon( QgsApplication::iconPath( "mActionArrowUp.svg" ) ) );
303 btnDown->setIcon( QIcon( QgsApplication::iconPath( "mActionArrowDown.svg" ) ) );
304
305 mSymbolLayersModel = new QStandardItemModel( layersTree );
306 // Set the symbol
307 layersTree->setModel( mSymbolLayersModel );
308 layersTree->setHeaderHidden( true );
309
310 //get first feature from layer for previews
311 if ( mVectorLayer )
312 {
313#if 0 // this is too expensive to do for many providers. TODO revisit when support for connection timeouts is complete across all providers
314 // short timeout for request - it doesn't really matter if we don't get the feature, and this call is blocking UI
315 QgsFeatureIterator it = mVectorLayer->getFeatures( QgsFeatureRequest().setLimit( 1 ).setConnectionTimeout( 100 ) );
316 it.nextFeature( mPreviewFeature );
317#endif
318 mPreviewExpressionContext.appendScopes( QgsExpressionContextUtils::globalProjectLayerScopes( mVectorLayer ) );
319#if 0
320 mPreviewExpressionContext.setFeature( mPreviewFeature );
321#endif
322 }
323 else
324 {
325 mPreviewExpressionContext.appendScopes( QgsExpressionContextUtils::globalProjectLayerScopes( nullptr ) );
326 }
327
328 QItemSelectionModel *selModel = layersTree->selectionModel();
329 connect( selModel, &QItemSelectionModel::currentChanged, this, &QgsSymbolSelectorWidget::layerChanged );
330
331 loadSymbol( mSymbol, static_cast<SymbolLayerItem *>( mSymbolLayersModel->invisibleRootItem() ) );
333
334 connect( btnUp, &QAbstractButton::clicked, this, &QgsSymbolSelectorWidget::moveLayerUp );
335 connect( btnDown, &QAbstractButton::clicked, this, &QgsSymbolSelectorWidget::moveLayerDown );
336 connect( btnAddLayer, &QAbstractButton::clicked, this, &QgsSymbolSelectorWidget::addLayer );
337 connect( btnRemoveLayer, &QAbstractButton::clicked, this, &QgsSymbolSelectorWidget::removeLayer );
338 connect( mLockColorAction, &QAction::toggled, this, &QgsSymbolSelectorWidget::lockLayer );
339 connect( mLockSelectionColorAction, &QAction::toggled, this, [this]( bool checked ) {
340 QgsSymbolLayer *layer = currentLayer();
341 if ( !layer )
342 return;
343
344 Qgis::SymbolLayerUserFlags flags = layer->userFlags();
346 layer->setUserFlags( flags );
347 updateLockButtonIcon();
348 emit symbolModified();
349 } );
350 connect( btnDuplicate, &QAbstractButton::clicked, this, &QgsSymbolSelectorWidget::duplicateLayer );
352
353 updateLockButtonIcon();
354
355 updateUi();
356
357 // set symbol as active item in the tree
358 const QModelIndex newIndex = layersTree->model()->index( 0, 0 );
359 layersTree->setCurrentIndex( newIndex );
360
361 setPanelTitle( tr( "Symbol Selector" ) );
362
363 // when a remote svg has been fetched, update the widget's previews
364 // this is required if the symbol utilizes remote svgs, and the current previews
365 // have been generated using the temporary "downloading" svg. In this case
366 // we require the preview to be regenerated to use the correct fetched
367 // svg
368 connect( QgsApplication::svgCache(), &QgsSvgCache::remoteSvgFetched, this, &QgsSymbolSelectorWidget::projectDataChanged );
369
370 // when a remote image has been fetched, update the widget's previews
371 // this is required if the symbol utilizes remote images, and the current previews
372 // have been generated using the temporary "downloading" image. In this case
373 // we require the preview to be regenerated to use the correct fetched
374 // image
375 connect( QgsApplication::imageCache(), &QgsImageCache::remoteImageFetched, this, &QgsSymbolSelectorWidget::projectDataChanged );
376
377 // if project color scheme changes, we need to redraw symbols - they may use project colors and accordingly
378 // need updating to reflect the new colors
379 connect( QgsProject::instance(), &QgsProject::projectColorsChanged, this, &QgsSymbolSelectorWidget::projectDataChanged );
380
381 connect( QgsProject::instance(), static_cast<void ( QgsProject::* )( const QList<QgsMapLayer *> &layers )>( &QgsProject::layersWillBeRemoved ), this, &QgsSymbolSelectorWidget::layersAboutToBeRemoved );
382
383 auto screenHelper = new QgsScreenHelper( this );
385 connect( screenHelper, &QgsScreenHelper::screenDpiChanged, this, &QgsSymbolSelectorWidget::updateListIcons );
386}
387
389{
390 QgsSymbolSelectorWidget *widget = new QgsSymbolSelectorWidget( symbol.get(), style, vl, parent );
391 // transfer ownership of symbol to widget, so that we are guaranteed it will last for the duration of the widget
392 widget->mOwnedSymbol = std::move( symbol );
393 return widget;
394}
395
397{
398 if ( !mAdvancedMenu )
399 {
400 mAdvancedMenu = new QMenu( this );
401 // Brute force method to activate the Advanced menu
402 layerChanged();
403 }
404 return mAdvancedMenu;
405}
406
408{
409 mContext = context;
410
411 if ( auto *lExpressionContext = mContext.expressionContext() )
412 {
413 mPreviewExpressionContext = *lExpressionContext;
414 if ( mVectorLayer )
415 mPreviewExpressionContext.appendScope( QgsExpressionContextUtils::layerScope( mVectorLayer ) );
416
417 mPreviewExpressionContext.setFeature( mPreviewFeature );
418 }
419
420 QWidget *widget = stackedWidget->currentWidget();
421 if ( QgsLayerPropertiesWidget *layerProp = qobject_cast<QgsLayerPropertiesWidget *>( widget ) )
422 {
423 layerProp->setContext( context );
424 }
425 else if ( QgsSymbolsListWidget *listWidget = qobject_cast<QgsSymbolsListWidget *>( widget ) )
426 {
427 listWidget->setContext( context );
428 }
429
430 layerChanged();
432}
433
435{
436 return mContext;
437}
438
439void QgsSymbolSelectorWidget::loadSymbol( QgsSymbol *symbol, SymbolLayerItem *parent )
440{
441 if ( !symbol )
442 return;
443
444 if ( !parent )
445 {
446 mSymbol = symbol;
447 mSymbolLayersModel->clear();
448 parent = static_cast<SymbolLayerItem *>( mSymbolLayersModel->invisibleRootItem() );
449 }
450
451 SymbolLayerItem *symbolItem = new SymbolLayerItem( symbol, mVectorLayer, screen() );
452 QFont boldFont = symbolItem->font();
453 boldFont.setBold( true );
454 symbolItem->setFont( boldFont );
455 parent->appendRow( symbolItem );
456
457 const int count = symbol->symbolLayerCount();
458 for ( int i = count - 1; i >= 0; i-- )
459 {
460 SymbolLayerItem *layerItem = new SymbolLayerItem( symbol->symbolLayer( i ), symbol->type(), mVectorLayer, screen() );
461 layerItem->setEditable( false );
462 symbolItem->appendRow( layerItem );
463 if ( symbol->symbolLayer( i )->subSymbol() )
464 {
465 loadSymbol( symbol->symbolLayer( i )->subSymbol(), layerItem );
466 }
467 layersTree->setExpanded( layerItem->index(), true );
468 }
469 layersTree->setExpanded( symbolItem->index(), true );
470
471 if ( mSymbol == symbol && !layersTree->currentIndex().isValid() )
472 {
473 // make sure root item for symbol is selected in tree
474 layersTree->setCurrentIndex( symbolItem->index() );
475 }
476}
477
478void QgsSymbolSelectorWidget::reloadSymbol()
479{
480 mSymbolLayersModel->clear();
481 loadSymbol( mSymbol, static_cast<SymbolLayerItem *>( mSymbolLayersModel->invisibleRootItem() ) );
482}
483
484void QgsSymbolSelectorWidget::updateUi()
485{
486 const QModelIndex currentIdx = layersTree->currentIndex();
487 if ( !currentIdx.isValid() )
488 return;
489
490 SymbolLayerItem *item = static_cast<SymbolLayerItem *>( mSymbolLayersModel->itemFromIndex( currentIdx ) );
491 if ( !item->isLayer() )
492 {
493 btnUp->setEnabled( false );
494 btnDown->setEnabled( false );
495 btnRemoveLayer->setEnabled( false );
496 btnLock->setEnabled( false );
497 btnDuplicate->setEnabled( false );
498 return;
499 }
500
501 const int rowCount = item->parent()->rowCount();
502 const int currentRow = item->row();
503
504 btnUp->setEnabled( currentRow > 0 );
505 btnDown->setEnabled( currentRow < rowCount - 1 );
506 btnRemoveLayer->setEnabled( rowCount > 1 );
507 btnLock->setEnabled( true );
508 btnDuplicate->setEnabled( true );
509}
510
512{
513 if ( !mSymbol )
514 return;
515
516 std::unique_ptr<QgsSymbol> symbolClone( mSymbol->clone() );
517 const QImage preview = symbolClone->bigSymbolPreviewImage( &mPreviewExpressionContext, Qgis::SymbolPreviewFlag::FlagIncludeCrosshairsForMarkerSymbols, QgsScreenProperties( screen() ) );
518 lblPreview->setPixmap( QPixmap::fromImage( preview ) );
519}
520
522{
523 // get current layer item and update its icon
524 SymbolLayerItem *item = currentLayerItem();
525 if ( item )
526 item->updatePreview( screen() );
527 // update also preview of the whole symbol
529}
530
531SymbolLayerItem *QgsSymbolSelectorWidget::currentLayerItem()
532{
533 const QModelIndex idx = layersTree->currentIndex();
534 if ( !idx.isValid() )
535 return nullptr;
536
537 SymbolLayerItem *item = static_cast<SymbolLayerItem *>( mSymbolLayersModel->itemFromIndex( idx ) );
538 if ( !item->isLayer() )
539 return nullptr;
540
541 return item;
542}
543
544QgsSymbolLayer *QgsSymbolSelectorWidget::currentLayer()
545{
546 const QModelIndex idx = layersTree->currentIndex();
547 if ( !idx.isValid() )
548 return nullptr;
549
550 SymbolLayerItem *item = static_cast<SymbolLayerItem *>( mSymbolLayersModel->itemFromIndex( idx ) );
551 if ( item->isLayer() )
552 return item->layer();
553
554 return nullptr;
555}
556
558{
559 updateUi();
560
561 SymbolLayerItem *currentItem = static_cast<SymbolLayerItem *>( mSymbolLayersModel->itemFromIndex( layersTree->currentIndex() ) );
562 if ( !currentItem )
563 return;
564
565 if ( currentItem->isLayer() )
566 {
567 SymbolLayerItem *parent = static_cast<SymbolLayerItem *>( currentItem->parent() );
568 mDataDefineRestorer = std::make_unique<DataDefinedRestorer>( parent->symbol(), currentItem->layer() );
569 QgsLayerPropertiesWidget *layerProp = new QgsLayerPropertiesWidget( currentItem->layer(), parent->symbol(), mVectorLayer );
570 layerProp->setDockMode( this->dockMode() );
571 layerProp->setContext( mContext );
572 setWidget( layerProp );
573 connect( layerProp, &QgsLayerPropertiesWidget::changed, mDataDefineRestorer.get(), &DataDefinedRestorer::restore );
575 connect( layerProp, &QgsLayerPropertiesWidget::changed, this, &QgsSymbolSelectorWidget::emitSymbolModified );
576 // This connection when layer type is changed
578
579 connectChildPanel( layerProp );
580 }
581 else
582 {
583 // then it must be a symbol
584 mDataDefineRestorer.reset();
586 currentItem->symbol()->setLayer( mVectorLayer );
588 // Now populate symbols of that type using the symbols list widget:
589 QgsSymbolsListWidget *symbolsList = new QgsSymbolsListWidget( currentItem->symbol(), mStyle, mAdvancedMenu, this, mVectorLayer );
590 symbolsList->setContext( mContext );
591
592 setWidget( symbolsList );
594 }
595 updateLockButton();
596}
597
599{
600 SymbolLayerItem *currentItem = static_cast<SymbolLayerItem *>( mSymbolLayersModel->itemFromIndex( layersTree->currentIndex() ) );
601 if ( !currentItem || currentItem->isLayer() )
602 return;
603 // disconnect to avoid recreating widget
604 disconnect( layersTree->selectionModel(), &QItemSelectionModel::currentChanged, this, &QgsSymbolSelectorWidget::layerChanged );
605 if ( currentItem->parent() )
606 {
607 // it is a sub-symbol
608 QgsSymbol *symbol = currentItem->symbol();
609 SymbolLayerItem *parent = static_cast<SymbolLayerItem *>( currentItem->parent() );
610 parent->removeRow( 0 );
611 loadSymbol( symbol, parent );
612 layersTree->setCurrentIndex( parent->child( 0 )->index() );
613 parent->updatePreview( screen() );
614 }
615 else
616 {
617 //it is the symbol itself
618 reloadSymbol();
619 const QModelIndex newIndex = layersTree->model()->index( 0, 0 );
620 layersTree->setCurrentIndex( newIndex );
621 }
623 emitSymbolModified();
624 // connect it back once things are set
625 connect( layersTree->selectionModel(), &QItemSelectionModel::currentChanged, this, &QgsSymbolSelectorWidget::layerChanged );
626}
627
628void QgsSymbolSelectorWidget::setWidget( QWidget *widget )
629{
630 const int index = stackedWidget->addWidget( widget );
631 stackedWidget->setCurrentIndex( index );
632 if ( mPresentWidget )
633 mPresentWidget->deleteLater();
634 mPresentWidget = widget;
635}
636
637void QgsSymbolSelectorWidget::updateLockButton()
638{
639 QgsSymbolLayer *layer = currentLayer();
640 if ( !layer )
641 return;
642 mLockColorAction->setChecked( layer->isLocked() );
643 mLockSelectionColorAction->setChecked( layer->userFlags() & Qgis::SymbolLayerUserFlag::DisableSelectionRecoloring );
644
645 updateLockButtonIcon();
646}
647
648void QgsSymbolSelectorWidget::updateLockButtonIcon()
649{
650 if ( mLockColorAction->isChecked() && mLockSelectionColorAction->isChecked() )
651 btnLock->setIcon( QgsApplication::getThemeIcon( u"locked.svg"_s ) );
652 else if ( mLockColorAction->isChecked() )
653 btnLock->setIcon( QgsApplication::getThemeIcon( u"mIconColorLocked.svg"_s ) );
654 else if ( mLockSelectionColorAction->isChecked() )
655 btnLock->setIcon( QgsApplication::getThemeIcon( u"mIconSelectLocked.svg"_s ) );
656 else
657 btnLock->setIcon( QgsApplication::getThemeIcon( u"unlocked.svg"_s ) );
658}
659
661{
662 const QModelIndex idx = layersTree->currentIndex();
663 if ( !idx.isValid() )
664 return;
665
666 int insertIdx = -1;
667 SymbolLayerItem *item = static_cast<SymbolLayerItem *>( mSymbolLayersModel->itemFromIndex( idx ) );
668 if ( item->isLayer() )
669 {
670 insertIdx = item->row();
671 item = static_cast<SymbolLayerItem *>( item->parent() );
672 }
673
674 QgsSymbol *parentSymbol = item->symbol();
675
676 // save data-defined values at marker level
677 const QgsProperty ddSize( parentSymbol->type() == Qgis::SymbolType::Marker ? static_cast<QgsMarkerSymbol *>( parentSymbol )->dataDefinedSize() : QgsProperty() );
678 const QgsProperty ddAngle( parentSymbol->type() == Qgis::SymbolType::Marker ? static_cast<QgsMarkerSymbol *>( parentSymbol )->dataDefinedAngle() : QgsProperty() );
679 const QgsProperty ddWidth( parentSymbol->type() == Qgis::SymbolType::Line ? static_cast<QgsLineSymbol *>( parentSymbol )->dataDefinedWidth() : QgsProperty() );
680
681 QgsSymbolLayer *newLayerPtr = nullptr;
682 {
683 std::unique_ptr< QgsSymbolLayer > newLayer = QgsSymbolLayerRegistry::defaultSymbolLayer( parentSymbol->type() );
684 newLayerPtr = newLayer.get();
685 if ( insertIdx == -1 )
686 parentSymbol->appendSymbolLayer( newLayer.release() );
687 else
688 parentSymbol->insertSymbolLayer( item->rowCount() - insertIdx, newLayer.release() );
689 }
690
691 // restore data-defined values at marker level
692 if ( ddSize )
693 static_cast<QgsMarkerSymbol *>( parentSymbol )->setDataDefinedSize( ddSize );
694 if ( ddAngle )
695 static_cast<QgsMarkerSymbol *>( parentSymbol )->setDataDefinedAngle( ddAngle );
696 if ( ddWidth )
697 static_cast<QgsLineSymbol *>( parentSymbol )->setDataDefinedWidth( ddWidth );
698
699 // TODO -- using newLayerPtr is not safe in some circumstances here. This needs reworking so that SymbolLayerItem does has
700 // its own owned QgsSymbolLayer clone, and isn't reliant on a pointer to the object owned by parentSymbol.
701 SymbolLayerItem *newLayerItem = new SymbolLayerItem( newLayerPtr, parentSymbol->type(), mVectorLayer, screen() ); // cppcheck-suppress invalidLifetime
702 item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem );
703 item->updatePreview( screen() );
704
705 layersTree->setCurrentIndex( mSymbolLayersModel->indexFromItem( newLayerItem ) );
706 updateUi();
708 emitSymbolModified();
709}
710
712{
713 SymbolLayerItem *item = currentLayerItem();
714 const int row = item->row();
715 SymbolLayerItem *parent = static_cast<SymbolLayerItem *>( item->parent() );
716
717 const int layerIdx = parent->rowCount() - row - 1; // IMPORTANT
718 QgsSymbol *parentSymbol = parent->symbol();
719 QgsSymbolLayer *tmpLayer = parentSymbol->takeSymbolLayer( layerIdx );
720
721 parent->removeRow( row );
722 parent->updatePreview( screen() );
723
724 const QModelIndex newIdx = parent->child( 0 )->index();
725 layersTree->setCurrentIndex( newIdx );
726
727 updateUi();
729 emitSymbolModified();
730 //finally delete the removed layer pointer
731 delete tmpLayer;
732}
733
735{
736 moveLayerByOffset( +1 );
737}
738
740{
741 moveLayerByOffset( -1 );
742}
743
744void QgsSymbolSelectorWidget::moveLayerByOffset( int offset )
745{
746 SymbolLayerItem *item = currentLayerItem();
747 if ( !item )
748 return;
749 const int row = item->row();
750
751 SymbolLayerItem *parent = static_cast<SymbolLayerItem *>( item->parent() );
752 QgsSymbol *parentSymbol = parent->symbol();
753
754 const int layerIdx = parent->rowCount() - row - 1;
755 // switch layers
756 QgsSymbolLayer *tmpLayer = parentSymbol->takeSymbolLayer( layerIdx );
757 parentSymbol->insertSymbolLayer( layerIdx - offset, tmpLayer );
758
759 QList<QStandardItem *> rowItems = parent->takeRow( row );
760 parent->insertRows( row + offset, rowItems );
761 parent->updatePreview( screen() );
762
763 const QModelIndex newIdx = rowItems[0]->index();
764 layersTree->setCurrentIndex( newIdx );
765
767 emitSymbolModified();
768 updateUi();
769}
770
772{
773 QgsSymbolLayer *layer = currentLayer();
774 if ( !layer )
775 return;
776 layer->setLocked( mLockColorAction->isChecked() );
777 updateLockButtonIcon();
778 emit symbolModified();
779}
780
782{
783 const QModelIndex idx = layersTree->currentIndex();
784 if ( !idx.isValid() )
785 return;
786
787 SymbolLayerItem *item = static_cast<SymbolLayerItem *>( mSymbolLayersModel->itemFromIndex( idx ) );
788 if ( !item->isLayer() )
789 return;
790
791 QgsSymbolLayer *source = item->layer();
792
793 const int insertIdx = item->row();
794 item = static_cast<SymbolLayerItem *>( item->parent() );
795
796 QgsSymbol *parentSymbol = item->symbol();
797
798 QgsSymbolLayer *newLayer = source->clone();
800 if ( insertIdx == -1 )
801 parentSymbol->appendSymbolLayer( newLayer );
802 else
803 parentSymbol->insertSymbolLayer( item->rowCount() - insertIdx, newLayer );
804
805 SymbolLayerItem *newLayerItem = new SymbolLayerItem( newLayer, parentSymbol->type(), mVectorLayer, screen() );
806 item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem );
807 if ( newLayer->subSymbol() )
808 {
809 loadSymbol( newLayer->subSymbol(), newLayerItem );
810 layersTree->setExpanded( newLayerItem->index(), true );
811 }
812 item->updatePreview( screen() );
813
814 layersTree->setCurrentIndex( mSymbolLayersModel->indexFromItem( newLayerItem ) );
815 updateUi();
817 emitSymbolModified();
818}
819
821{
822 SymbolLayerItem *item = currentLayerItem();
823
824 if ( item->rowCount() > 0 )
825 {
826 item->removeRow( 0 );
827 }
828 QgsSymbol *symbol = static_cast<SymbolLayerItem *>( item->parent() )->symbol();
829
830 // update symbol layer item
831 item->setLayer( newLayer, symbol->type(), screen() );
832 // When it is a marker symbol
833 if ( newLayer->subSymbol() )
834 {
835 loadSymbol( newLayer->subSymbol(), item );
836 layersTree->setExpanded( item->index(), true );
837 }
838
839 // Change the symbol at last to avoid deleting item's layer
840 const int layerIdx = item->parent()->rowCount() - item->row() - 1;
841 symbol->changeSymbolLayer( layerIdx, newLayer );
842
843 item->updatePreview( screen() );
845 emitSymbolModified();
846 // Important: This lets the layer have its own layer properties widget
847 layerChanged();
848}
849
850void QgsSymbolSelectorWidget::updateListIcons()
851{
852 QScreen *currentScreen = screen();
853 std::function<void( SymbolLayerItem * item )> updateItem;
854 updateItem = [currentScreen, &updateItem]( SymbolLayerItem *item ) {
855 for ( int row = 0; row < item->rowCount(); ++row )
856 {
857 if ( auto child = dynamic_cast< SymbolLayerItem * >( item->child( row ) ) )
858 {
859 updateItem( child );
860 child->updatePreview( currentScreen );
861 }
862 }
863 };
864
865 updateItem( static_cast<SymbolLayerItem *>( mSymbolLayersModel->invisibleRootItem() ) );
866}
867
868
870 : QDialog( parent )
871{
872 setLayout( new QVBoxLayout() );
873
874 mSelectorWidget = new QgsSymbolSelectorWidget( symbol, style, vl, this );
875 mButtonBox = new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::Ok );
876
877 connect( mButtonBox, &QDialogButtonBox::accepted, this, &QDialog::accept );
878 connect( mButtonBox, &QDialogButtonBox::rejected, this, &QDialog::reject );
879 connect( mButtonBox, &QDialogButtonBox::helpRequested, this, &QgsSymbolSelectorDialog::showHelp );
880
881 layout()->addWidget( mSelectorWidget );
882 layout()->addWidget( mButtonBox );
883
884 connect( mSelectorWidget, &QgsPanelWidget::panelAccepted, this, &QDialog::reject );
885
886 mSelectorWidget->setMinimumSize( 460, 560 );
887 setObjectName( u"SymbolSelectorDialog"_s );
889
890 // Can be embedded in renderer properties dialog
891 if ( embedded )
892 {
893 mButtonBox->hide();
894 layout()->setContentsMargins( 0, 0, 0, 0 );
895 }
896 else
897 {
898 setWindowTitle( tr( "Symbol Selector" ) );
899 }
900 mSelectorWidget->setDockMode( embedded );
901}
902
904{
905 return mSelectorWidget->advancedMenu();
906}
907
909{
910 mSelectorWidget->setContext( context );
911}
912
914{
915 return mSelectorWidget->context();
916}
917
919{
920 return mSelectorWidget->symbol();
921}
922
924{
925 // Ignore the ESC key to avoid close the dialog without the properties window
926 if ( !isWindow() && e->key() == Qt::Key_Escape )
927 {
928 e->ignore();
929 }
930 else
931 {
932 QDialog::keyPressEvent( e );
933 }
934}
935
936void QgsSymbolSelectorDialog::reloadSymbol()
937{
938 mSelectorWidget->reloadSymbol();
939}
940
941void QgsSymbolSelectorDialog::loadSymbol( QgsSymbol *symbol, SymbolLayerItem *parent )
942{
943 mSelectorWidget->loadSymbol( symbol, parent );
944}
945
946void QgsSymbolSelectorDialog::updateUi()
947{
948 mSelectorWidget->updateUi();
949}
950
951void QgsSymbolSelectorDialog::updateLockButton()
952{
953 mSelectorWidget->updateLockButton();
954}
955
956SymbolLayerItem *QgsSymbolSelectorDialog::currentLayerItem()
957{
958 return mSelectorWidget->currentLayerItem();
959}
960
961QgsSymbolLayer *QgsSymbolSelectorDialog::currentLayer()
962{
963 return mSelectorWidget->currentLayer();
964}
965
966void QgsSymbolSelectorDialog::moveLayerByOffset( int offset )
967{
968 mSelectorWidget->moveLayerByOffset( offset );
969}
970
971void QgsSymbolSelectorDialog::setWidget( QWidget *widget )
972{
973 mSelectorWidget->setWidget( widget );
974}
975
977{
978 mSelectorWidget->moveLayerDown();
979}
980
982{
983 mSelectorWidget->moveLayerUp();
984}
985
987{
988 mSelectorWidget->addLayer();
989}
990
992{
993 mSelectorWidget->removeLayer();
994}
995
997{
998 mSelectorWidget->lockLayer();
999}
1000
1002{
1003 mSelectorWidget->duplicateLayer();
1004}
1005
1007{
1008 mSelectorWidget->layerChanged();
1009}
1010
1012{
1013 mSelectorWidget->updateLayerPreview();
1014}
1015
1017{
1018 mSelectorWidget->updatePreview();
1019}
1020
1022{
1023 mSelectorWidget->symbolChanged();
1024}
1025
1027{
1028 mSelectorWidget->changeLayer( layer );
1029}
1030
1031QDialogButtonBox *QgsSymbolSelectorDialog::buttonBox() const
1032{
1033 return mButtonBox;
1034}
1035
1036void QgsSymbolSelectorDialog::showHelp()
1037{
1038 QgsHelp::openHelp( u"style_library/symbol_selector.html"_s );
1039}
1040
1041void QgsSymbolSelectorWidget::projectDataChanged()
1042{
1043 mBlockModified = true;
1044 symbolChanged();
1045 updatePreview();
1046 mBlockModified = false;
1047}
1048
1049void QgsSymbolSelectorWidget::layersAboutToBeRemoved( const QList<QgsMapLayer *> &layers )
1050{
1051 if ( mVectorLayer && layers.contains( mVectorLayer ) )
1052 {
1053 disconnect( QgsProject::instance(), &QgsProject::projectColorsChanged, this, &QgsSymbolSelectorWidget::projectDataChanged );
1054 }
1055}
1056
1057void QgsSymbolSelectorWidget::emitSymbolModified()
1058{
1059 if ( !mBlockModified )
1060 {
1061 emit symbolModified();
1062 }
1063}
QFlags< SymbolLayerUserFlag > SymbolLayerUserFlags
Symbol layer user flags.
Definition qgis.h:959
@ Millimeters
Millimeters.
Definition qgis.h:5608
@ FlagIncludeCrosshairsForMarkerSymbols
Include a crosshairs reference image in the background of marker symbol previews.
Definition qgis.h:912
@ DisableSelectionRecoloring
If present, indicates that the symbol layer should not be recolored when rendering selected features.
Definition qgis.h:950
SymbolType
Symbol types.
Definition qgis.h:638
@ Marker
Marker symbol.
Definition qgis.h:639
@ Line
Line symbol.
Definition qgis.h:640
@ Fill
Fill symbol.
Definition qgis.h:641
@ Hybrid
Hybrid symbol.
Definition qgis.h:642
static const double UI_SCALE_FACTOR
UI scaling factor.
Definition qgis.h:6938
static QgsSymbolLayerRegistry * symbolLayerRegistry()
Returns the application's symbol layer registry, used for managing symbol layers.
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 iconPath(const QString &iconFile)
Returns path to the desired icon file.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
void appendScopes(const QList< QgsExpressionContextScope * > &scopes)
Appends a list of scopes to the end of the context.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
Wraps a request for features to a vector layer (or directly its vector data provider).
static void enableAutoGeometryRestore(QWidget *widget, const QString &key=QString())
Register the widget to allow its position to be automatically saved and restored when open and closed...
Definition qgsgui.cpp:224
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition qgshelp.cpp:41
void remoteImageFetched(const QString &url)
Emitted when the cache has finished retrieving an image file from a remote url.
A widget which allows configuration of the properties of a single QgsSymbolLayer.
void setDockMode(bool dockMode) override
Set the widget in dock mode which tells the widget to emit panel widgets and not open dialogs.
void changeLayer(QgsSymbolLayer *layer)
Emitted when the symbol layer is changed in the widget.
void setContext(const QgsSymbolWidgetContext &context)
Sets the context in which the symbol widget is shown, e.g., the associated map canvas and expression ...
void changed()
Emitted when the symbol layer configuration is changed in the widget.
Abstract base class for line symbol layers.
A line symbol type, for rendering LineString and MultiLineString geometries.
QgsProperty dataDefinedWidth() const
Returns data defined width for whole symbol (including all symbol layers).
Abstract base class for marker symbol layers.
A marker symbol type, for rendering Point and MultiPoint geometries.
QgsProperty dataDefinedAngle() const
Returns data defined angle for whole symbol (including all symbol layers).
QgsProperty dataDefinedSize() const
Returns data defined size for whole symbol (including all symbol layers).
bool dockMode() const
Returns the dock mode state.
void panelAccepted(QgsPanelWidget *panel)
Emitted when the panel is accepted by the user.
void connectChildPanel(QgsPanelWidget *panel)
Connect the given sub panel widgets showPanel signals to this current panels main showPanel event to ...
QgsPanelWidget(QWidget *parent=nullptr)
Base class for any widget that can be shown as an inline panel.
void widgetChanged()
Emitted when the widget state changes.
void setPanelTitle(const QString &panelTitle)
Set the title of the panel when shown in the interface.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition qgsproject.h:114
static QgsProject * instance()
Returns the QgsProject singleton instance.
void layersWillBeRemoved(const QStringList &layerIds)
Emitted when one or more layers are about to be removed from the registry.
void projectColorsChanged()
Emitted whenever the project's color scheme has been changed.
A store for object properties.
A utility class for dynamic handling of changes to screen properties.
void screenDpiChanged(double dpi)
Emitted whenever the screen dpi associated with the widget is changed.
Stores properties relating to a screen.
A database of saved style entities, including symbols, color ramps, text formats and others.
Definition qgsstyle.h:91
void remoteSvgFetched(const QString &url)
Emitted when the cache has finished retrieving an SVG file from a remote url.
static std::unique_ptr< QgsSymbolLayer > defaultSymbolLayer(Qgis::SymbolType type)
create a new instance of symbol layer for specified symbol type with default settings
QgsSymbolLayerAbstractMetadata * symbolLayerMetadata(const QString &name) const
Returns metadata for specified symbol layer. Returns nullptr if not found.
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 void resetSymbolLayerIds(QgsSymbol *symbol)
Regenerate recursively unique id from all symbol symbol layers.
Abstract base class for symbol layers.
virtual QgsSymbolLayer * clone() const =0
Shall be reimplemented by subclasses to create a deep copy of the instance.
Qgis::SymbolType type() const
bool isLocked() const
Returns true if the symbol layer colors are locked and the layer will ignore any symbol-level color c...
void setUserFlags(Qgis::SymbolLayerUserFlags flags)
Sets user-controlled flags which control the symbol layer's behavior.
virtual QgsSymbol * subSymbol()
Returns the symbol's sub symbol, if present.
Qgis::SymbolLayerUserFlags userFlags() const
Returns user-controlled flags which control the symbol layer's behavior.
void setLocked(bool locked)
Sets whether the layer's colors are locked.
void setContext(const QgsSymbolWidgetContext &context)
Sets the context in which the symbol widget is shown, e.g., the associated map canvas and expression ...
QgsSymbolSelectorDialog(QgsSymbol *symbol, QgsStyle *style, QgsVectorLayer *vl, QWidget *parent=nullptr, bool embedded=false)
Constructor for QgsSymbolSelectorDialog.
QgsSymbolWidgetContext context() const
Returns the context in which the symbol widget is shown, e.g., the associated map canvas and expressi...
QMenu * advancedMenu()
Returns menu for "advanced" button - create it if doesn't exist and show the advanced button.
void symbolChanged()
Slot to update tree when a new symbol from style.
QDialogButtonBox * buttonBox() const
Returns a reference to the dialog's button box.
QgsSymbol * symbol()
Returns the symbol that is currently active in the widget.
void keyPressEvent(QKeyEvent *e) override
void duplicateLayer()
Duplicates the current symbol layer and places the duplicated layer above the current symbol layer.
void changeLayer(QgsSymbolLayer *layer)
Alters tree and sets proper widget when Layer Type is changed.
void loadSymbol(QgsSymbol *symbol, SymbolLayerItem *parent=nullptr)
Loads the given symbol into the widget.
Symbol selector widget that can be used to select and build a symbol.
void loadSymbol(QgsSymbol *symbol, SymbolLayerItem *parent=nullptr)
Loads the given symbol into the widget.
void symbolChanged()
Slot to update tree when a new symbol from style.
void addLayer()
Add a symbol layer to the bottom of the stack.
QMenu * advancedMenu()
Returns menu for "advanced" button - create it if doesn't exist and show the advanced button.
void layerChanged()
Called when the layer changes in the widget.
void changeLayer(QgsSymbolLayer *layer)
Alters tree and sets proper widget when Layer Type is changed.
void updatePreview()
Update the preview of the whole symbol in the interface.
QgsSymbolSelectorWidget(QgsSymbol *symbol, QgsStyle *style, QgsVectorLayer *vl, QWidget *parent=nullptr)
Symbol selector widget that can be used to select and build a symbol.
void removeLayer()
Remove the current active symbol layer.
QgsSymbolWidgetContext context() const
Returns the context in which the symbol widget is shown, e.g., the associated map canvas and expressi...
void moveLayerDown()
Move the active symbol layer down.
void symbolModified()
Emitted when a symbol is modified in the widget.
void duplicateLayer()
Duplicates the current symbol layer and places the duplicated layer above the current symbol layer.
void lockLayer()
Lock the current active symbol layer.
void updateLayerPreview()
Update the single symbol layer preview in the widget.
void setContext(const QgsSymbolWidgetContext &context)
Sets the context in which the symbol widget is shown, e.g., the associated map canvas and expression ...
QgsSymbol * symbol()
Returns the symbol that is currently active in the widget.
void moveLayerUp()
Move the active symbol layer up.
static QgsSymbolSelectorWidget * createWidgetWithSymbolOwnership(std::unique_ptr< QgsSymbol > symbol, QgsStyle *style, QgsVectorLayer *vl, QWidget *parent=nullptr)
Creates a QgsSymbolSelectorWidget which takes ownership of a symbol and maintains the ownership for t...
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:227
bool appendSymbolLayer(QgsSymbolLayer *layer)
Appends a symbol layer at the end of the current symbol layer list.
bool insertSymbolLayer(int index, QgsSymbolLayer *layer)
Inserts a symbol layer to specified index.
QgsSymbolLayer * takeSymbolLayer(int index)
Removes a symbol layer from the list and returns a pointer to it.
Qgis::SymbolType type() const
Returns the symbol's type.
Definition qgssymbol.h:296
A widget which presents symbol-level properties (such as size), and allows selection of symbols from ...
void changed()
Emitted when the symbol is modified in the widget.
Represents a vector layer which manages a vector based dataset.
int scaleIconSize(int standardSize)
Scales an icon size to compensate for display pixel density, making the icon size hi-dpi friendly,...
#define Q_NOWARN_DEPRECATED_POP
Definition qgis.h:7938
#define Q_NOWARN_DEPRECATED_PUSH
Definition qgis.h:7937