QGIS API Documentation 3.41.0-Master (88383c3d16f)
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#include "moc_qgssymbolselectordialog.cpp"
18
19#include "qgsstyle.h"
20#include "qgssymbol.h"
21#include "qgssymbollayer.h"
22#include "qgssymbollayerutils.h"
25
26// the widgets
29#include "qgsapplication.h"
30#include "qgsvectorlayer.h"
31#include "qgssvgcache.h"
32#include "qgsimagecache.h"
33#include "qgsproject.h"
34#include "qgsguiutils.h"
35#include "qgsgui.h"
36#include "qgsmarkersymbol.h"
37#include "qgslinesymbol.h"
38#include "qscreen.h"
39
40#include <QColorDialog>
41#include <QPainter>
42#include <QStandardItemModel>
43#include <QInputDialog>
44#include <QMessageBox>
45#include <QKeyEvent>
46#include <QMenu>
47
48#include <QWidget>
49#include <QFile>
50#include <QStandardItem>
51
53
54static const int SYMBOL_LAYER_ITEM_TYPE = QStandardItem::UserType + 1;
55
56DataDefinedRestorer::DataDefinedRestorer( QgsSymbol *symbol, const QgsSymbolLayer *symbolLayer )
57
58{
59 if ( symbolLayer->type() == Qgis::SymbolType::Marker && symbol->type() == Qgis::SymbolType::Marker )
60 {
61 Q_ASSERT( symbol->type() == Qgis::SymbolType::Marker );
62 mMarker = static_cast<QgsMarkerSymbol *>( symbol );
63 mMarkerSymbolLayer = static_cast<const QgsMarkerSymbolLayer *>( symbolLayer );
64 mDDSize = mMarker->dataDefinedSize();
65 mDDAngle = mMarker->dataDefinedAngle();
66 // check if restore is actually needed
67 if ( !mDDSize && !mDDAngle )
68 mMarker = nullptr;
69 }
70 else if ( symbolLayer->type() == Qgis::SymbolType::Line && symbol->type() == Qgis::SymbolType::Line )
71 {
72 mLine = static_cast<QgsLineSymbol *>( symbol );
73 mLineSymbolLayer = static_cast<const QgsLineSymbolLayer *>( symbolLayer );
74 mDDWidth = mLine->dataDefinedWidth();
75 // check if restore is actually needed
76 if ( !mDDWidth )
77 mLine = nullptr;
78 }
79 save();
80}
81
82void DataDefinedRestorer::save()
83{
84 if ( mMarker )
85 {
86 mSize = mMarkerSymbolLayer->size();
87 mAngle = mMarkerSymbolLayer->angle();
88 mMarkerOffset = mMarkerSymbolLayer->offset();
89 }
90 else if ( mLine )
91 {
92 mWidth = mLineSymbolLayer->width();
93 mLineOffset = mLineSymbolLayer->offset();
94 }
95}
96
97void DataDefinedRestorer::restore()
98{
99 if ( mMarker )
100 {
101 if ( mDDSize && ( mSize != mMarkerSymbolLayer->size() || mMarkerOffset != mMarkerSymbolLayer->offset() ) )
102 mMarker->setDataDefinedSize( mDDSize );
103 if ( mDDAngle && mAngle != mMarkerSymbolLayer->angle() )
104 mMarker->setDataDefinedAngle( mDDAngle );
105 }
106 else if ( mLine )
107 {
108 if ( mDDWidth && ( mWidth != mLineSymbolLayer->width() || mLineOffset != mLineSymbolLayer->offset() ) )
109 mLine->setDataDefinedWidth( mDDWidth );
110 }
111 save();
112}
113
114// Hybrid item which may represent a symbol or a layer
115// Check using item->isLayer()
116class SymbolLayerItem : public QStandardItem
117{
118 public:
119 explicit SymbolLayerItem( QgsSymbolLayer *layer, Qgis::SymbolType symbolType, QgsVectorLayer *vectorLayer, QScreen *screen )
120 : mVectorLayer( vectorLayer )
121 , mScreen( screen )
122 {
123 setLayer( layer, symbolType );
124 }
125
126 explicit SymbolLayerItem( QgsSymbol *symbol, QgsVectorLayer *vectorLayer, QScreen *screen )
127 : mVectorLayer( vectorLayer )
128 , mScreen( screen )
129 {
130 setSymbol( symbol );
131 }
132
133 void setLayer( QgsSymbolLayer *layer, Qgis::SymbolType symbolType )
134 {
135 mLayer = layer;
136 mIsLayer = true;
137 mSymbol = nullptr;
138 mSymbolType = symbolType;
139 updatePreview();
140 }
141
142 void setSymbol( QgsSymbol *symbol )
143 {
144 mSymbol = symbol;
145 mIsLayer = false;
146 mLayer = nullptr;
147 updatePreview();
148 }
149
150 void updatePreview()
151 {
152 if ( !mSize.isValid() )
153 {
154 const int size = QgsGuiUtils::scaleIconSize( 16 );
155 mSize = QSize( size, size );
156 }
157 QIcon icon;
158 if ( mIsLayer )
159 icon = QgsSymbolLayerUtils::symbolLayerPreviewIcon( mLayer, Qgis::RenderUnit::Millimeters, mSize, QgsMapUnitScale(), mSymbol ? mSymbol->type() : mSymbolType, mVectorLayer, QgsScreenProperties( mScreen.data() ) );
160 else
161 {
162 QgsExpressionContext expContext;
164 icon = QIcon( QgsSymbolLayerUtils::symbolPreviewPixmap( mSymbol, mSize, 0, nullptr, false, &expContext, nullptr, QgsScreenProperties( mScreen.data() ) ) );
165 }
166 setIcon( icon );
167
168 if ( auto *lParent = parent() )
169 static_cast<SymbolLayerItem *>( lParent )->updatePreview();
170 }
171
172 int type() const override { return SYMBOL_LAYER_ITEM_TYPE; }
173 bool isLayer() { return mIsLayer; }
174
175 // returns the symbol pointer; helpful in determining a layer's parent symbol
176 QgsSymbol *symbol()
177 {
178 return mSymbol;
179 }
180
181 QgsSymbolLayer *layer()
182 {
183 return mLayer;
184 }
185
186 QVariant data( int role ) const override
187 {
188 if ( role == Qt::DisplayRole || role == Qt::EditRole )
189 {
190 if ( mIsLayer )
191 {
193 if ( m )
194 return m->visibleName();
195 else
196 return QString();
197 }
198 else
199 {
200 switch ( mSymbol->type() )
201 {
203 return QCoreApplication::translate( "SymbolLayerItem", "Marker" );
205 return QCoreApplication::translate( "SymbolLayerItem", "Fill" );
207 return QCoreApplication::translate( "SymbolLayerItem", "Line" );
208 default:
209 return "Symbol";
210 }
211 }
212 }
213 else if ( role == Qt::ForegroundRole && mIsLayer )
214 {
215 if ( !mLayer->enabled() )
216 {
217 QPalette pal = qApp->palette();
218 QBrush brush = QStandardItem::data( role ).value<QBrush>();
219 brush.setColor( pal.color( QPalette::Disabled, QPalette::WindowText ) );
220 return brush;
221 }
222 else
223 {
224 return QVariant();
225 }
226 }
227
228 // if ( role == Qt::SizeHintRole )
229 // return QVariant( QSize( 32, 32 ) );
230 if ( role == Qt::CheckStateRole )
231 return QVariant(); // could be true/false
232 return QStandardItem::data( role );
233 }
234
235 protected:
236 QgsSymbolLayer *mLayer = nullptr;
237 QgsSymbol *mSymbol = nullptr;
238 QPointer<QgsVectorLayer> mVectorLayer;
239 bool mIsLayer = false;
240 QSize mSize;
242 QPointer<QScreen> mScreen;
243};
244
246
248
250 : QgsPanelWidget( parent )
251 , mStyle( style )
252 , mSymbol( symbol )
253 , mVectorLayer( vl )
254{
255#ifdef Q_OS_MAC
256 setWindowModality( Qt::WindowModal );
257#endif
258
259 setupUi( this );
260 this->layout()->setContentsMargins( 0, 0, 0, 0 );
261
262 layersTree->setMaximumHeight( static_cast<int>( Qgis::UI_SCALE_FACTOR * fontMetrics().height() * 7 ) );
263 layersTree->setMinimumHeight( layersTree->maximumHeight() );
264 lblPreview->setMaximumWidth( layersTree->maximumHeight() );
265
266 // setup icons
267 btnAddLayer->setIcon( QIcon( QgsApplication::iconPath( "symbologyAdd.svg" ) ) );
268 btnRemoveLayer->setIcon( QIcon( QgsApplication::iconPath( "symbologyRemove.svg" ) ) );
269 QIcon iconLock;
270 iconLock.addFile( QgsApplication::iconPath( QStringLiteral( "locked.svg" ) ), QSize(), QIcon::Normal, QIcon::On );
271 iconLock.addFile( QgsApplication::iconPath( QStringLiteral( "locked.svg" ) ), QSize(), QIcon::Active, QIcon::On );
272 iconLock.addFile( QgsApplication::iconPath( QStringLiteral( "unlocked.svg" ) ), QSize(), QIcon::Normal, QIcon::Off );
273 iconLock.addFile( QgsApplication::iconPath( QStringLiteral( "unlocked.svg" ) ), QSize(), QIcon::Active, QIcon::Off );
274
275 QIcon iconColorLock;
276 iconColorLock.addFile( QgsApplication::iconPath( QStringLiteral( "mIconColorLocked.svg" ) ), QSize(), QIcon::Normal, QIcon::On );
277 iconColorLock.addFile( QgsApplication::iconPath( QStringLiteral( "mIconColorLocked.svg" ) ), QSize(), QIcon::Active, QIcon::On );
278 iconColorLock.addFile( QgsApplication::iconPath( QStringLiteral( "mIconColorUnlocked.svg" ) ), QSize(), QIcon::Normal, QIcon::Off );
279 iconColorLock.addFile( QgsApplication::iconPath( QStringLiteral( "mIconColorUnlocked.svg" ) ), QSize(), QIcon::Active, QIcon::Off );
280
281 mLockColorAction = new QAction( tr( "Lock Color" ), this );
282 mLockColorAction->setToolTip( tr( "Avoid changing the color of the layer when the symbol color is changed" ) );
283 mLockColorAction->setCheckable( true );
284 mLockColorAction->setIcon( iconColorLock );
285
286 QIcon iconSelectLock;
287 iconSelectLock.addFile( QgsApplication::iconPath( QStringLiteral( "mIconSelectLocked.svg" ) ), QSize(), QIcon::Normal, QIcon::On );
288 iconSelectLock.addFile( QgsApplication::iconPath( QStringLiteral( "mIconSelectLocked.svg" ) ), QSize(), QIcon::Active, QIcon::On );
289 iconSelectLock.addFile( QgsApplication::iconPath( QStringLiteral( "mIconSelectUnlocked.svg" ) ), QSize(), QIcon::Normal, QIcon::Off );
290 iconSelectLock.addFile( QgsApplication::iconPath( QStringLiteral( "mIconSelectUnlocked.svg" ) ), QSize(), QIcon::Active, QIcon::Off );
291
292 mLockSelectionColorAction = new QAction( tr( "Lock Color When Selected" ), this );
293 mLockSelectionColorAction->setToolTip( tr( "Avoid changing the color of the layer when a feature is selected" ) );
294 mLockSelectionColorAction->setCheckable( true );
295 mLockSelectionColorAction->setIcon( iconSelectLock );
296
297 QMenu *lockMenu = new QMenu( this );
298 lockMenu->addAction( mLockColorAction );
299 lockMenu->addAction( mLockSelectionColorAction );
300 btnLock->setMenu( lockMenu );
301 btnLock->setPopupMode( QToolButton::InstantPopup );
302
303 btnDuplicate->setIcon( QIcon( QgsApplication::iconPath( "mActionDuplicateLayer.svg" ) ) );
304 btnUp->setIcon( QIcon( QgsApplication::iconPath( "mActionArrowUp.svg" ) ) );
305 btnDown->setIcon( QIcon( QgsApplication::iconPath( "mActionArrowDown.svg" ) ) );
306
307 mSymbolLayersModel = new QStandardItemModel( layersTree );
308 // Set the symbol
309 layersTree->setModel( mSymbolLayersModel );
310 layersTree->setHeaderHidden( true );
311
312 //get first feature from layer for previews
313 if ( mVectorLayer )
314 {
315#if 0 // this is too expensive to do for many providers. TODO revisit when support for connection timeouts is complete across all providers
316 // short timeout for request - it doesn't really matter if we don't get the feature, and this call is blocking UI
317 QgsFeatureIterator it = mVectorLayer->getFeatures( QgsFeatureRequest().setLimit( 1 ).setConnectionTimeout( 100 ) );
318 it.nextFeature( mPreviewFeature );
319#endif
320 mPreviewExpressionContext.appendScopes( QgsExpressionContextUtils::globalProjectLayerScopes( mVectorLayer ) );
321#if 0
322 mPreviewExpressionContext.setFeature( mPreviewFeature );
323#endif
324 }
325 else
326 {
327 mPreviewExpressionContext.appendScopes( QgsExpressionContextUtils::globalProjectLayerScopes( nullptr ) );
328 }
329
330 QItemSelectionModel *selModel = layersTree->selectionModel();
331 connect( selModel, &QItemSelectionModel::currentChanged, this, &QgsSymbolSelectorWidget::layerChanged );
332
333 loadSymbol( mSymbol, static_cast<SymbolLayerItem *>( mSymbolLayersModel->invisibleRootItem() ) );
335
336 connect( btnUp, &QAbstractButton::clicked, this, &QgsSymbolSelectorWidget::moveLayerUp );
337 connect( btnDown, &QAbstractButton::clicked, this, &QgsSymbolSelectorWidget::moveLayerDown );
338 connect( btnAddLayer, &QAbstractButton::clicked, this, &QgsSymbolSelectorWidget::addLayer );
339 connect( btnRemoveLayer, &QAbstractButton::clicked, this, &QgsSymbolSelectorWidget::removeLayer );
340 connect( mLockColorAction, &QAction::toggled, this, &QgsSymbolSelectorWidget::lockLayer );
341 connect( mLockSelectionColorAction, &QAction::toggled, this, [=]( bool checked ) {
342 QgsSymbolLayer *layer = currentLayer();
343 if ( !layer )
344 return;
345
346 Qgis::SymbolLayerUserFlags flags = layer->userFlags();
348 layer->setUserFlags( flags );
349 updateLockButtonIcon();
350 emit symbolModified();
351 } );
352 connect( btnDuplicate, &QAbstractButton::clicked, this, &QgsSymbolSelectorWidget::duplicateLayer );
354
355 updateLockButtonIcon();
356
357 updateUi();
358
359 // set symbol as active item in the tree
360 const QModelIndex newIndex = layersTree->model()->index( 0, 0 );
361 layersTree->setCurrentIndex( newIndex );
362
363 setPanelTitle( tr( "Symbol Selector" ) );
364
365 // when a remote svg has been fetched, update the widget's previews
366 // this is required if the symbol utilizes remote svgs, and the current previews
367 // have been generated using the temporary "downloading" svg. In this case
368 // we require the preview to be regenerated to use the correct fetched
369 // svg
370 connect( QgsApplication::svgCache(), &QgsSvgCache::remoteSvgFetched, this, &QgsSymbolSelectorWidget::projectDataChanged );
371
372 // when a remote image has been fetched, update the widget's previews
373 // this is required if the symbol utilizes remote images, and the current previews
374 // have been generated using the temporary "downloading" image. In this case
375 // we require the preview to be regenerated to use the correct fetched
376 // image
377 connect( QgsApplication::imageCache(), &QgsImageCache::remoteImageFetched, this, &QgsSymbolSelectorWidget::projectDataChanged );
378
379 // if project color scheme changes, we need to redraw symbols - they may use project colors and accordingly
380 // need updating to reflect the new colors
381 connect( QgsProject::instance(), &QgsProject::projectColorsChanged, this, &QgsSymbolSelectorWidget::projectDataChanged );
382
383 connect( QgsProject::instance(), static_cast<void ( QgsProject::* )( const QList<QgsMapLayer *> &layers )>( &QgsProject::layersWillBeRemoved ), this, &QgsSymbolSelectorWidget::layersAboutToBeRemoved );
384}
385
386QgsSymbolSelectorWidget *QgsSymbolSelectorWidget::createWidgetWithSymbolOwnership( std::unique_ptr<QgsSymbol> symbol, QgsStyle *style, QgsVectorLayer *vl, QWidget *parent )
387{
388 QgsSymbolSelectorWidget *widget = new QgsSymbolSelectorWidget( symbol.get(), style, vl, parent );
389 // transfer ownership of symbol to widget, so that we are guaranteed it will last for the duration of the widget
390 widget->mOwnedSymbol = std::move( symbol );
391 return widget;
392}
393
395{
396 if ( !mAdvancedMenu )
397 {
398 mAdvancedMenu = new QMenu( this );
399 // Brute force method to activate the Advanced menu
400 layerChanged();
401 }
402 return mAdvancedMenu;
403}
404
406{
407 mContext = context;
408
409 if ( auto *lExpressionContext = mContext.expressionContext() )
410 {
411 mPreviewExpressionContext = *lExpressionContext;
412 if ( mVectorLayer )
413 mPreviewExpressionContext.appendScope( QgsExpressionContextUtils::layerScope( mVectorLayer ) );
414
415 mPreviewExpressionContext.setFeature( mPreviewFeature );
416 }
417
418 QWidget *widget = stackedWidget->currentWidget();
419 if ( QgsLayerPropertiesWidget *layerProp = qobject_cast<QgsLayerPropertiesWidget *>( widget ) )
420 {
421 layerProp->setContext( context );
422 }
423 else if ( QgsSymbolsListWidget *listWidget = qobject_cast<QgsSymbolsListWidget *>( widget ) )
424 {
425 listWidget->setContext( context );
426 }
427
428 layerChanged();
430}
431
433{
434 return mContext;
435}
436
437void QgsSymbolSelectorWidget::loadSymbol( QgsSymbol *symbol, SymbolLayerItem *parent )
438{
439 if ( !symbol )
440 return;
441
442 if ( !parent )
443 {
444 mSymbol = symbol;
445 mSymbolLayersModel->clear();
446 parent = static_cast<SymbolLayerItem *>( mSymbolLayersModel->invisibleRootItem() );
447 }
448
449 SymbolLayerItem *symbolItem = new SymbolLayerItem( symbol, mVectorLayer, screen() );
450 QFont boldFont = symbolItem->font();
451 boldFont.setBold( true );
452 symbolItem->setFont( boldFont );
453 parent->appendRow( symbolItem );
454
455 const int count = symbol->symbolLayerCount();
456 for ( int i = count - 1; i >= 0; i-- )
457 {
458 SymbolLayerItem *layerItem = new SymbolLayerItem( symbol->symbolLayer( i ), symbol->type(), mVectorLayer, screen() );
459 layerItem->setEditable( false );
460 symbolItem->appendRow( layerItem );
461 if ( symbol->symbolLayer( i )->subSymbol() )
462 {
463 loadSymbol( symbol->symbolLayer( i )->subSymbol(), layerItem );
464 }
465 layersTree->setExpanded( layerItem->index(), true );
466 }
467 layersTree->setExpanded( symbolItem->index(), true );
468
469 if ( mSymbol == symbol && !layersTree->currentIndex().isValid() )
470 {
471 // make sure root item for symbol is selected in tree
472 layersTree->setCurrentIndex( symbolItem->index() );
473 }
474}
475
476void QgsSymbolSelectorWidget::reloadSymbol()
477{
478 mSymbolLayersModel->clear();
479 loadSymbol( mSymbol, static_cast<SymbolLayerItem *>( mSymbolLayersModel->invisibleRootItem() ) );
480}
481
482void QgsSymbolSelectorWidget::updateUi()
483{
484 const QModelIndex currentIdx = layersTree->currentIndex();
485 if ( !currentIdx.isValid() )
486 return;
487
488 SymbolLayerItem *item = static_cast<SymbolLayerItem *>( mSymbolLayersModel->itemFromIndex( currentIdx ) );
489 if ( !item->isLayer() )
490 {
491 btnUp->setEnabled( false );
492 btnDown->setEnabled( false );
493 btnRemoveLayer->setEnabled( false );
494 btnLock->setEnabled( false );
495 btnDuplicate->setEnabled( false );
496 return;
497 }
498
499 const int rowCount = item->parent()->rowCount();
500 const int currentRow = item->row();
501
502 btnUp->setEnabled( currentRow > 0 );
503 btnDown->setEnabled( currentRow < rowCount - 1 );
504 btnRemoveLayer->setEnabled( rowCount > 1 );
505 btnLock->setEnabled( true );
506 btnDuplicate->setEnabled( true );
507}
508
510{
511 if ( !mSymbol )
512 return;
513
514 std::unique_ptr<QgsSymbol> symbolClone( mSymbol->clone() );
515 const QImage preview = symbolClone->bigSymbolPreviewImage( &mPreviewExpressionContext, Qgis::SymbolPreviewFlag::FlagIncludeCrosshairsForMarkerSymbols, QgsScreenProperties( screen() ) );
516 lblPreview->setPixmap( QPixmap::fromImage( preview ) );
517 // Hope this is a appropriate place
518 if ( !mBlockModified )
519 emit symbolModified();
520}
521
523{
524 // get current layer item and update its icon
525 SymbolLayerItem *item = currentLayerItem();
526 if ( item )
527 item->updatePreview();
528 // update also preview of the whole symbol
530}
531
532SymbolLayerItem *QgsSymbolSelectorWidget::currentLayerItem()
533{
534 const QModelIndex idx = layersTree->currentIndex();
535 if ( !idx.isValid() )
536 return nullptr;
537
538 SymbolLayerItem *item = static_cast<SymbolLayerItem *>( mSymbolLayersModel->itemFromIndex( idx ) );
539 if ( !item->isLayer() )
540 return nullptr;
541
542 return item;
543}
544
545QgsSymbolLayer *QgsSymbolSelectorWidget::currentLayer()
546{
547 const QModelIndex idx = layersTree->currentIndex();
548 if ( !idx.isValid() )
549 return nullptr;
550
551 SymbolLayerItem *item = static_cast<SymbolLayerItem *>( mSymbolLayersModel->itemFromIndex( idx ) );
552 if ( item->isLayer() )
553 return item->layer();
554
555 return nullptr;
556}
557
559{
560 updateUi();
561
562 SymbolLayerItem *currentItem = static_cast<SymbolLayerItem *>( mSymbolLayersModel->itemFromIndex( layersTree->currentIndex() ) );
563 if ( !currentItem )
564 return;
565
566 if ( currentItem->isLayer() )
567 {
568 SymbolLayerItem *parent = static_cast<SymbolLayerItem *>( currentItem->parent() );
569 mDataDefineRestorer.reset( new DataDefinedRestorer( parent->symbol(), currentItem->layer() ) );
570 QgsLayerPropertiesWidget *layerProp = new QgsLayerPropertiesWidget( currentItem->layer(), parent->symbol(), mVectorLayer );
571 layerProp->setDockMode( this->dockMode() );
572 layerProp->setContext( mContext );
573 setWidget( layerProp );
574 connect( layerProp, &QgsLayerPropertiesWidget::changed, mDataDefineRestorer.get(), &DataDefinedRestorer::restore );
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();
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 // connect it back once things are set
624 connect( layersTree->selectionModel(), &QItemSelectionModel::currentChanged, this, &QgsSymbolSelectorWidget::layerChanged );
625}
626
627void QgsSymbolSelectorWidget::setWidget( QWidget *widget )
628{
629 const int index = stackedWidget->addWidget( widget );
630 stackedWidget->setCurrentIndex( index );
631 if ( mPresentWidget )
632 mPresentWidget->deleteLater();
633 mPresentWidget = widget;
634}
635
636void QgsSymbolSelectorWidget::updateLockButton()
637{
638 QgsSymbolLayer *layer = currentLayer();
639 if ( !layer )
640 return;
641 mLockColorAction->setChecked( layer->isLocked() );
642 mLockSelectionColorAction->setChecked( layer->userFlags() & Qgis::SymbolLayerUserFlag::DisableSelectionRecoloring );
643
644 updateLockButtonIcon();
645}
646
647void QgsSymbolSelectorWidget::updateLockButtonIcon()
648{
649 if ( mLockColorAction->isChecked() && mLockSelectionColorAction->isChecked() )
650 btnLock->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "locked.svg" ) ) );
651 else if ( mLockColorAction->isChecked() )
652 btnLock->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "mIconColorLocked.svg" ) ) );
653 else if ( mLockSelectionColorAction->isChecked() )
654 btnLock->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "mIconSelectLocked.svg" ) ) );
655 else
656 btnLock->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "unlocked.svg" ) ) );
657}
658
660{
661 const QModelIndex idx = layersTree->currentIndex();
662 if ( !idx.isValid() )
663 return;
664
665 int insertIdx = -1;
666 SymbolLayerItem *item = static_cast<SymbolLayerItem *>( mSymbolLayersModel->itemFromIndex( idx ) );
667 if ( item->isLayer() )
668 {
669 insertIdx = item->row();
670 item = static_cast<SymbolLayerItem *>( item->parent() );
671 }
672
673 QgsSymbol *parentSymbol = item->symbol();
674
675 // save data-defined values at marker level
676 const QgsProperty ddSize( parentSymbol->type() == Qgis::SymbolType::Marker ? static_cast<QgsMarkerSymbol *>( parentSymbol )->dataDefinedSize() : QgsProperty() );
677 const QgsProperty ddAngle( parentSymbol->type() == Qgis::SymbolType::Marker ? static_cast<QgsMarkerSymbol *>( parentSymbol )->dataDefinedAngle() : QgsProperty() );
678 const QgsProperty ddWidth( parentSymbol->type() == Qgis::SymbolType::Line ? static_cast<QgsLineSymbol *>( parentSymbol )->dataDefinedWidth() : QgsProperty() );
679
681 if ( insertIdx == -1 )
682 parentSymbol->appendSymbolLayer( newLayer );
683 else
684 parentSymbol->insertSymbolLayer( item->rowCount() - insertIdx, newLayer );
685
686 // restore data-defined values at marker level
687 if ( ddSize )
688 static_cast<QgsMarkerSymbol *>( parentSymbol )->setDataDefinedSize( ddSize );
689 if ( ddAngle )
690 static_cast<QgsMarkerSymbol *>( parentSymbol )->setDataDefinedAngle( ddAngle );
691 if ( ddWidth )
692 static_cast<QgsLineSymbol *>( parentSymbol )->setDataDefinedWidth( ddWidth );
693
694 SymbolLayerItem *newLayerItem = new SymbolLayerItem( newLayer, parentSymbol->type(), mVectorLayer, screen() );
695 item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem );
696 item->updatePreview();
697
698 layersTree->setCurrentIndex( mSymbolLayersModel->indexFromItem( newLayerItem ) );
699 updateUi();
701}
702
704{
705 SymbolLayerItem *item = currentLayerItem();
706 const int row = item->row();
707 SymbolLayerItem *parent = static_cast<SymbolLayerItem *>( item->parent() );
708
709 const int layerIdx = parent->rowCount() - row - 1; // IMPORTANT
710 QgsSymbol *parentSymbol = parent->symbol();
711 QgsSymbolLayer *tmpLayer = parentSymbol->takeSymbolLayer( layerIdx );
712
713 parent->removeRow( row );
714 parent->updatePreview();
715
716 const QModelIndex newIdx = parent->child( 0 )->index();
717 layersTree->setCurrentIndex( newIdx );
718
719 updateUi();
721 //finally delete the removed layer pointer
722 delete tmpLayer;
723}
724
726{
727 moveLayerByOffset( +1 );
728}
729
731{
732 moveLayerByOffset( -1 );
733}
734
735void QgsSymbolSelectorWidget::moveLayerByOffset( int offset )
736{
737 SymbolLayerItem *item = currentLayerItem();
738 if ( !item )
739 return;
740 const int row = item->row();
741
742 SymbolLayerItem *parent = static_cast<SymbolLayerItem *>( item->parent() );
743 QgsSymbol *parentSymbol = parent->symbol();
744
745 const int layerIdx = parent->rowCount() - row - 1;
746 // switch layers
747 QgsSymbolLayer *tmpLayer = parentSymbol->takeSymbolLayer( layerIdx );
748 parentSymbol->insertSymbolLayer( layerIdx - offset, tmpLayer );
749
750 QList<QStandardItem *> rowItems = parent->takeRow( row );
751 parent->insertRows( row + offset, rowItems );
752 parent->updatePreview();
753
754 const QModelIndex newIdx = rowItems[0]->index();
755 layersTree->setCurrentIndex( newIdx );
756
758 updateUi();
759}
760
762{
763 QgsSymbolLayer *layer = currentLayer();
764 if ( !layer )
765 return;
766 layer->setLocked( mLockColorAction->isChecked() );
767 updateLockButtonIcon();
768 emit symbolModified();
769}
770
772{
773 const QModelIndex idx = layersTree->currentIndex();
774 if ( !idx.isValid() )
775 return;
776
777 SymbolLayerItem *item = static_cast<SymbolLayerItem *>( mSymbolLayersModel->itemFromIndex( idx ) );
778 if ( !item->isLayer() )
779 return;
780
781 QgsSymbolLayer *source = item->layer();
782
783 const int insertIdx = item->row();
784 item = static_cast<SymbolLayerItem *>( item->parent() );
785
786 QgsSymbol *parentSymbol = item->symbol();
787
788 QgsSymbolLayer *newLayer = source->clone();
790 if ( insertIdx == -1 )
791 parentSymbol->appendSymbolLayer( newLayer );
792 else
793 parentSymbol->insertSymbolLayer( item->rowCount() - insertIdx, newLayer );
794
795 SymbolLayerItem *newLayerItem = new SymbolLayerItem( newLayer, parentSymbol->type(), mVectorLayer, screen() );
796 item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem );
797 if ( newLayer->subSymbol() )
798 {
799 loadSymbol( newLayer->subSymbol(), newLayerItem );
800 layersTree->setExpanded( newLayerItem->index(), true );
801 }
802 item->updatePreview();
803
804 layersTree->setCurrentIndex( mSymbolLayersModel->indexFromItem( newLayerItem ) );
805 updateUi();
807}
808
810{
811 SymbolLayerItem *item = currentLayerItem();
812
813 if ( item->rowCount() > 0 )
814 {
815 item->removeRow( 0 );
816 }
817 QgsSymbol *symbol = static_cast<SymbolLayerItem *>( item->parent() )->symbol();
818
819 // update symbol layer item
820 item->setLayer( newLayer, symbol->type() );
821 // When it is a marker symbol
822 if ( newLayer->subSymbol() )
823 {
824 loadSymbol( newLayer->subSymbol(), item );
825 layersTree->setExpanded( item->index(), true );
826 }
827
828 // Change the symbol at last to avoid deleting item's layer
829 const int layerIdx = item->parent()->rowCount() - item->row() - 1;
830 symbol->changeSymbolLayer( layerIdx, newLayer );
831
832 item->updatePreview();
834 // Important: This lets the layer have its own layer properties widget
835 layerChanged();
836}
837
838QgsSymbolSelectorDialog::QgsSymbolSelectorDialog( QgsSymbol *symbol, QgsStyle *style, QgsVectorLayer *vl, QWidget *parent, bool embedded )
839 : QDialog( parent )
840{
841 setLayout( new QVBoxLayout() );
842
843 mSelectorWidget = new QgsSymbolSelectorWidget( symbol, style, vl, this );
844 mButtonBox = new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::Ok );
845
846 connect( mButtonBox, &QDialogButtonBox::accepted, this, &QDialog::accept );
847 connect( mButtonBox, &QDialogButtonBox::rejected, this, &QDialog::reject );
848 connect( mButtonBox, &QDialogButtonBox::helpRequested, this, &QgsSymbolSelectorDialog::showHelp );
849
850 layout()->addWidget( mSelectorWidget );
851 layout()->addWidget( mButtonBox );
852
853 connect( mSelectorWidget, &QgsPanelWidget::panelAccepted, this, &QDialog::reject );
854
855 mSelectorWidget->setMinimumSize( 460, 560 );
856 setObjectName( QStringLiteral( "SymbolSelectorDialog" ) );
858
859 // Can be embedded in renderer properties dialog
860 if ( embedded )
861 {
862 mButtonBox->hide();
863 layout()->setContentsMargins( 0, 0, 0, 0 );
864 }
865 else
866 {
867 setWindowTitle( tr( "Symbol Selector" ) );
868 }
869 mSelectorWidget->setDockMode( embedded );
870}
871
873{
874 return mSelectorWidget->advancedMenu();
875}
876
878{
879 mSelectorWidget->setContext( context );
880}
881
883{
884 return mSelectorWidget->context();
885}
886
888{
889 return mSelectorWidget->symbol();
890}
891
893{
894 // Ignore the ESC key to avoid close the dialog without the properties window
895 if ( !isWindow() && e->key() == Qt::Key_Escape )
896 {
897 e->ignore();
898 }
899 else
900 {
901 QDialog::keyPressEvent( e );
902 }
903}
904
905void QgsSymbolSelectorDialog::reloadSymbol()
906{
907 mSelectorWidget->reloadSymbol();
908}
909
910void QgsSymbolSelectorDialog::loadSymbol( QgsSymbol *symbol, SymbolLayerItem *parent )
911{
912 mSelectorWidget->loadSymbol( symbol, parent );
913}
914
915void QgsSymbolSelectorDialog::updateUi()
916{
917 mSelectorWidget->updateUi();
918}
919
920void QgsSymbolSelectorDialog::updateLockButton()
921{
922 mSelectorWidget->updateLockButton();
923}
924
925SymbolLayerItem *QgsSymbolSelectorDialog::currentLayerItem()
926{
927 return mSelectorWidget->currentLayerItem();
928}
929
930QgsSymbolLayer *QgsSymbolSelectorDialog::currentLayer()
931{
932 return mSelectorWidget->currentLayer();
933}
934
935void QgsSymbolSelectorDialog::moveLayerByOffset( int offset )
936{
937 mSelectorWidget->moveLayerByOffset( offset );
938}
939
940void QgsSymbolSelectorDialog::setWidget( QWidget *widget )
941{
942 mSelectorWidget->setWidget( widget );
943}
944
946{
947 mSelectorWidget->moveLayerDown();
948}
949
951{
952 mSelectorWidget->moveLayerUp();
953}
954
956{
957 mSelectorWidget->addLayer();
958}
959
961{
962 mSelectorWidget->removeLayer();
963}
964
966{
967 mSelectorWidget->lockLayer();
968}
969
971{
972 mSelectorWidget->duplicateLayer();
973}
974
976{
977 mSelectorWidget->layerChanged();
978}
979
984
986{
987 mSelectorWidget->updatePreview();
988}
989
991{
992 mSelectorWidget->symbolChanged();
993}
994
996{
997 mSelectorWidget->changeLayer( layer );
998}
999
1000QDialogButtonBox *QgsSymbolSelectorDialog::buttonBox() const
1001{
1002 return mButtonBox;
1003}
1004
1005void QgsSymbolSelectorDialog::showHelp()
1006{
1007 QgsHelp::openHelp( QStringLiteral( "style_library/symbol_selector.html" ) );
1008}
1009
1010void QgsSymbolSelectorWidget::projectDataChanged()
1011{
1012 mBlockModified = true;
1013 symbolChanged();
1014 updatePreview();
1015 mBlockModified = false;
1016}
1017
1018void QgsSymbolSelectorWidget::layersAboutToBeRemoved( const QList<QgsMapLayer *> &layers )
1019{
1020 if ( mVectorLayer && layers.contains( mVectorLayer ) )
1021 {
1022 disconnect( QgsProject::instance(), &QgsProject::projectColorsChanged, this, &QgsSymbolSelectorWidget::projectDataChanged );
1023 }
1024}
QFlags< SymbolLayerUserFlag > SymbolLayerUserFlags
Symbol layer user flags.
Definition qgis.h:844
@ Millimeters
Millimeters.
@ FlagIncludeCrosshairsForMarkerSymbols
Include a crosshairs reference image in the background of marker symbol previews.
@ DisableSelectionRecoloring
If present, indicates that the symbol layer should not be recolored when rendering selected features.
SymbolType
Symbol types.
Definition qgis.h:574
@ Marker
Marker symbol.
@ Line
Line symbol.
@ Fill
Fill symbol.
@ Hybrid
Hybrid symbol.
static const double UI_SCALE_FACTOR
UI scaling factor.
Definition qgis.h:5833
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.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
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.
This class 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:210
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition qgshelp.cpp:39
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).
Struct for storing maximum and minimum scales for measurements in map units.
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).
Base class for any widget that can be shown as a inline panel.
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 ...
void widgetChanged()
Emitted when the widget state changes.
void setPanelTitle(const QString &panelTitle)
Set the title of the panel when shown in the interface.
virtual void setDockMode(bool dockMode)
Set the widget in dock mode which tells the widget to emit panel widgets and not open dialogs.
bool dockMode()
Returns the dock mode state.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition qgsproject.h:107
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.
Stores properties relating to a screen.
void remoteSvgFetched(const QString &url)
Emitted when the cache has finished retrieving an SVG file from a remote url.
Stores metadata about one symbol layer class.
QgsSymbolLayerAbstractMetadata * symbolLayerMetadata(const QString &name) const
Returns metadata for specified symbol layer. Returns nullptr if not found.
static QgsSymbolLayer * defaultSymbolLayer(Qgis::SymbolType type)
create a new instance of symbol layer for specified symbol type with default settings
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.
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,...
QgsExpressionContext * expressionContext() const
Returns the expression context used for the widget, if set.
Abstract base class for all rendered symbols.
Definition qgssymbol.h:231
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
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.
bool changeSymbolLayer(int index, QgsSymbolLayer *layer)
Deletes the current layer at the specified index and replaces it with layer.
QgsSymbolLayer * takeSymbolLayer(int index)
Removes a symbol layer from the list and returns a pointer to it.
virtual QgsSymbol * clone() const =0
Returns a deep copy of this symbol.
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
Definition qgssymbol.h:353
Qgis::SymbolType type() const
Returns the symbol's type.
Definition qgssymbol.h:294
void changed()
Emitted when the symbol is modified in the widget.
Represents a vector layer which manages a vector based data sets.
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:6702
#define Q_NOWARN_DEPRECATED_PUSH
Definition qgis.h:6701