QGIS API Documentation 4.3.0-Master (6402a64e93b)
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"
23#include "qgssymbollayermodel.h"
25#include "qgssymbollayerutils.h"
26
27#include <QString>
28
29#include "moc_qgssymbolselectordialog.cpp"
30
31using namespace Qt::StringLiterals;
32
33// the widgets
36#include "qgsapplication.h"
37#include "qgsvectorlayer.h"
38#include "qgssvgcache.h"
39#include "qgsimagecache.h"
40#include "qgsproject.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 <QInputDialog>
49#include <QMessageBox>
50#include <QKeyEvent>
51#include <QMenu>
52
53#include <QWidget>
54#include <QFile>
55#include <memory>
56
58
59
60DataDefinedRestorer::DataDefinedRestorer( QgsSymbol *symbol, const QgsSymbolLayer *symbolLayer )
61
62{
63 if ( symbolLayer->type() == Qgis::SymbolType::Marker && symbol->type() == Qgis::SymbolType::Marker )
64 {
65 Q_ASSERT( symbol->type() == Qgis::SymbolType::Marker );
66 mMarker = static_cast<QgsMarkerSymbol *>( symbol );
67 mMarkerSymbolLayer = static_cast<const QgsMarkerSymbolLayer *>( symbolLayer );
68 mDDSize = mMarker->dataDefinedSize();
69 mDDAngle = mMarker->dataDefinedAngle();
70 // check if restore is actually needed
71 if ( !mDDSize && !mDDAngle )
72 mMarker = nullptr;
73 }
74 else if ( symbolLayer->type() == Qgis::SymbolType::Line && symbol->type() == Qgis::SymbolType::Line )
75 {
76 mLine = static_cast<QgsLineSymbol *>( symbol );
77 mLineSymbolLayer = static_cast<const QgsLineSymbolLayer *>( symbolLayer );
78 mDDWidth = mLine->dataDefinedWidth();
79 // check if restore is actually needed
80 if ( !mDDWidth )
81 mLine = nullptr;
82 }
83 save();
84}
85
86void DataDefinedRestorer::save()
87{
88 if ( mMarker )
89 {
90 mSize = mMarkerSymbolLayer->size();
91 mAngle = mMarkerSymbolLayer->angle();
92 mMarkerOffset = mMarkerSymbolLayer->offset();
93 }
94 else if ( mLine )
95 {
96 mWidth = mLineSymbolLayer->width();
97 mLineOffset = mLineSymbolLayer->offset();
98 }
99}
100
101void DataDefinedRestorer::restore()
102{
103 if ( mMarker && mMarker->symbolLayerCount() > 1 )
104 {
105 if ( mDDSize && ( mSize != mMarkerSymbolLayer->size() || mMarkerOffset != mMarkerSymbolLayer->offset() ) )
106 mMarker->setDataDefinedSize( mDDSize );
107 if ( mDDAngle && mAngle != mMarkerSymbolLayer->angle() )
108 mMarker->setDataDefinedAngle( mDDAngle );
109 }
110 else if ( mLine && mLine->symbolLayerCount() > 1 )
111 {
112 if ( mDDWidth && ( mWidth != mLineSymbolLayer->width() || mLineOffset != mLineSymbolLayer->offset() ) )
113 mLine->setDataDefinedWidth( mDDWidth );
114 }
115 save();
116}
117
119
121
123 : QgsPanelWidget( parent )
124 , mStyle( style )
125 , mSymbol( symbol )
126 , mVectorLayer( vl )
127{
128#ifdef Q_OS_MAC
129 setWindowModality( Qt::WindowModal );
130#endif
131
132 setupUi( this );
133 this->layout()->setContentsMargins( 0, 0, 0, 0 );
134
135 layersTree->setMaximumHeight( static_cast<int>( Qgis::UI_SCALE_FACTOR * fontMetrics().height() * 7 ) );
136 layersTree->setMinimumHeight( layersTree->maximumHeight() );
137 lblPreview->setMaximumWidth( layersTree->maximumHeight() );
138
139 // setup icons
140 btnAddLayer->setIcon( QIcon( QgsApplication::iconPath( "symbologyAdd.svg" ) ) );
141 btnRemoveLayer->setIcon( QIcon( QgsApplication::iconPath( "symbologyRemove.svg" ) ) );
142 QIcon iconLock;
143 iconLock.addFile( QgsApplication::iconPath( u"locked.svg"_s ), QSize(), QIcon::Normal, QIcon::On );
144 iconLock.addFile( QgsApplication::iconPath( u"locked.svg"_s ), QSize(), QIcon::Active, QIcon::On );
145 iconLock.addFile( QgsApplication::iconPath( u"unlocked.svg"_s ), QSize(), QIcon::Normal, QIcon::Off );
146 iconLock.addFile( QgsApplication::iconPath( u"unlocked.svg"_s ), QSize(), QIcon::Active, QIcon::Off );
147
148 QIcon iconColorLock;
149 iconColorLock.addFile( QgsApplication::iconPath( u"mIconColorLocked.svg"_s ), QSize(), QIcon::Normal, QIcon::On );
150 iconColorLock.addFile( QgsApplication::iconPath( u"mIconColorLocked.svg"_s ), QSize(), QIcon::Active, QIcon::On );
151 iconColorLock.addFile( QgsApplication::iconPath( u"mIconColorUnlocked.svg"_s ), QSize(), QIcon::Normal, QIcon::Off );
152 iconColorLock.addFile( QgsApplication::iconPath( u"mIconColorUnlocked.svg"_s ), QSize(), QIcon::Active, QIcon::Off );
153
154 mLockColorAction = new QAction( tr( "Lock Color" ), this );
155 mLockColorAction->setToolTip( tr( "Avoid changing the color of the layer when the symbol color is changed" ) );
156 mLockColorAction->setCheckable( true );
157 mLockColorAction->setIcon( iconColorLock );
158
159 QIcon iconSelectLock;
160 iconSelectLock.addFile( QgsApplication::iconPath( u"mIconSelectLocked.svg"_s ), QSize(), QIcon::Normal, QIcon::On );
161 iconSelectLock.addFile( QgsApplication::iconPath( u"mIconSelectLocked.svg"_s ), QSize(), QIcon::Active, QIcon::On );
162 iconSelectLock.addFile( QgsApplication::iconPath( u"mIconSelectUnlocked.svg"_s ), QSize(), QIcon::Normal, QIcon::Off );
163 iconSelectLock.addFile( QgsApplication::iconPath( u"mIconSelectUnlocked.svg"_s ), QSize(), QIcon::Active, QIcon::Off );
164
165 mLockSelectionColorAction = new QAction( tr( "Lock Color When Selected" ), this );
166 mLockSelectionColorAction->setToolTip( tr( "Avoid changing the color of the layer when a feature is selected" ) );
167 mLockSelectionColorAction->setCheckable( true );
168 mLockSelectionColorAction->setIcon( iconSelectLock );
169
170 QMenu *lockMenu = new QMenu( this );
171 lockMenu->addAction( mLockColorAction );
172 lockMenu->addAction( mLockSelectionColorAction );
173 btnLock->setMenu( lockMenu );
174 btnLock->setPopupMode( QToolButton::InstantPopup );
175
176 btnDuplicate->setIcon( QIcon( QgsApplication::iconPath( "mActionDuplicateLayer.svg" ) ) );
177 btnUp->setIcon( QIcon( QgsApplication::iconPath( "mActionArrowUp.svg" ) ) );
178 btnDown->setIcon( QIcon( QgsApplication::iconPath( "mActionArrowDown.svg" ) ) );
179
180 mSymbolLayersModel = new QgsSymbolLayerModel( mVectorLayer, layersTree, screen() );
181
182 // Set the symbol
183 layersTree->setModel( mSymbolLayersModel );
184 layersTree->setHeaderHidden( true );
185
186 //get first feature from layer for previews
187 if ( mVectorLayer )
188 {
189#if 0 // this is too expensive to do for many providers. TODO revisit when support for connection timeouts is complete across all providers
190 // short timeout for request - it doesn't really matter if we don't get the feature, and this call is blocking UI
191 QgsFeatureIterator it = mVectorLayer->getFeatures( QgsFeatureRequest().setLimit( 1 ).setConnectionTimeout( 100 ) );
192 it.nextFeature( mPreviewFeature );
193#endif
194 mPreviewExpressionContext.appendScopes( QgsExpressionContextUtils::globalProjectLayerScopes( mVectorLayer ) );
195#if 0
196 mPreviewExpressionContext.setFeature( mPreviewFeature );
197#endif
198 }
199 else
200 {
201 mPreviewExpressionContext.appendScopes( QgsExpressionContextUtils::globalProjectLayerScopes( nullptr ) );
202 }
203
204 QItemSelectionModel *selModel = layersTree->selectionModel();
205 connect( selModel, &QItemSelectionModel::currentChanged, this, &QgsSymbolSelectorWidget::layerChanged );
206
207 mSymbolLayersModel->setSymbol( mSymbol );
208
209 layersTree->expandAll();
211
212 connect( btnUp, &QAbstractButton::clicked, this, &QgsSymbolSelectorWidget::moveLayerUp );
213 connect( btnDown, &QAbstractButton::clicked, this, &QgsSymbolSelectorWidget::moveLayerDown );
214 connect( btnAddLayer, &QAbstractButton::clicked, this, &QgsSymbolSelectorWidget::addLayer );
215 connect( btnRemoveLayer, &QAbstractButton::clicked, this, &QgsSymbolSelectorWidget::removeLayer );
216 connect( mLockColorAction, &QAction::toggled, this, &QgsSymbolSelectorWidget::lockLayer );
217 connect( mLockSelectionColorAction, &QAction::toggled, this, [this]( bool checked ) {
218 QgsSymbolLayer *layer = currentLayer();
219 if ( !layer )
220 return;
221
222 Qgis::SymbolLayerUserFlags flags = layer->userFlags();
224 layer->setUserFlags( flags );
225 updateLockButtonIcon();
226 emit symbolModified();
227 } );
228 connect( btnDuplicate, &QAbstractButton::clicked, this, &QgsSymbolSelectorWidget::duplicateLayer );
230
231 updateLockButtonIcon();
232
233 updateUi();
234
235 // set symbol as active item in the tree
236 const QModelIndex newIndex = layersTree->model()->index( 0, 0 );
237 layersTree->setCurrentIndex( newIndex );
238
239 setPanelTitle( tr( "Symbol Selector" ) );
240
241 // when a remote svg has been fetched, update the widget's previews
242 // this is required if the symbol utilizes remote svgs, and the current previews
243 // have been generated using the temporary "downloading" svg. In this case
244 // we require the preview to be regenerated to use the correct fetched
245 // svg
246 connect( QgsApplication::svgCache(), &QgsSvgCache::remoteSvgFetched, this, &QgsSymbolSelectorWidget::projectDataChanged );
247
248 // when a remote image has been fetched, update the widget's previews
249 // this is required if the symbol utilizes remote images, and the current previews
250 // have been generated using the temporary "downloading" image. In this case
251 // we require the preview to be regenerated to use the correct fetched
252 // image
253 connect( QgsApplication::imageCache(), &QgsImageCache::remoteImageFetched, this, &QgsSymbolSelectorWidget::projectDataChanged );
254
255 // if project color scheme changes, we need to redraw symbols - they may use project colors and accordingly
256 // need updating to reflect the new colors
257 connect( QgsProject::instance(), &QgsProject::projectColorsChanged, this, &QgsSymbolSelectorWidget::projectDataChanged );
258
259 connect( QgsProject::instance(), static_cast<void ( QgsProject::* )( const QList<QgsMapLayer *> &layers )>( &QgsProject::layersWillBeRemoved ), this, &QgsSymbolSelectorWidget::layersAboutToBeRemoved );
260
261 auto screenHelper = new QgsScreenHelper( this );
263 connect( screenHelper, &QgsScreenHelper::screenDpiChanged, this, &QgsSymbolSelectorWidget::updateListIcons );
264}
265
267{
268 QgsSymbolSelectorWidget *widget = new QgsSymbolSelectorWidget( symbol.get(), style, vl, parent );
269 // transfer ownership of symbol to widget, so that we are guaranteed it will last for the duration of the widget
270 widget->mOwnedSymbol = std::move( symbol );
271 return widget;
272}
273
275{
276 if ( !mAdvancedMenu )
277 {
278 mAdvancedMenu = new QMenu( this );
279 // Brute force method to activate the Advanced menu
280 layerChanged();
281 }
282 return mAdvancedMenu;
283}
284
286{
287 mContext = context;
288
289 if ( auto *lExpressionContext = mContext.expressionContext() )
290 {
291 mPreviewExpressionContext = *lExpressionContext;
292 if ( mVectorLayer )
293 mPreviewExpressionContext.appendScope( QgsExpressionContextUtils::layerScope( mVectorLayer ) );
294
295 mPreviewExpressionContext.setFeature( mPreviewFeature );
296 }
297
298 QWidget *widget = stackedWidget->currentWidget();
299 if ( QgsLayerPropertiesWidget *layerProp = qobject_cast<QgsLayerPropertiesWidget *>( widget ) )
300 {
301 layerProp->setContext( context );
302 }
303 else if ( QgsSymbolsListWidget *listWidget = qobject_cast<QgsSymbolsListWidget *>( widget ) )
304 {
305 listWidget->setContext( context );
306 }
307
308 layerChanged();
310}
311
313{
314 return mContext;
315}
316
318{
319 if ( !symbol )
320 return;
321
322 mSymbol = symbol;
323 reloadSymbol();
324}
325
326void QgsSymbolSelectorWidget::reloadSymbol()
327{
328 mSymbolLayersModel->setSymbol( mSymbol );
329 layersTree->expandAll();
330}
331
332void QgsSymbolSelectorWidget::updateUi()
333{
334 QgsSymbolLayerModelNode *node = currentNode();
335 if ( !node )
336 return;
337
338 if ( !node->isLayer() )
339 {
340 btnUp->setEnabled( false );
341 btnDown->setEnabled( false );
342 btnRemoveLayer->setEnabled( false );
343 btnLock->setEnabled( false );
344 btnDuplicate->setEnabled( false );
345 return;
346 }
347
348 const int rowCount = node->parent()->rowCount();
349 const int currentRow = node->rowIndex();
350
351 btnUp->setEnabled( currentRow > 0 );
352 btnDown->setEnabled( currentRow < rowCount - 1 );
353 btnRemoveLayer->setEnabled( rowCount > 1 );
354 btnLock->setEnabled( true );
355 btnDuplicate->setEnabled( true );
356}
357
359{
360 if ( !mSymbol )
361 return;
362
363 std::unique_ptr<QgsSymbol> symbolClone( mSymbol->clone() );
364 const QImage preview = symbolClone->bigSymbolPreviewImage( &mPreviewExpressionContext, Qgis::SymbolPreviewFlag::FlagIncludeCrosshairsForMarkerSymbols, QgsScreenProperties( screen() ) );
365 lblPreview->setPixmap( QPixmap::fromImage( preview ) );
366}
367
369{
370 // get current layer item and update its icon
371
372 QgsSymbolLayerModelNode *node = currentLayerNode();
373 if ( node )
374 mSymbolLayersModel->updatePreview( node );
375 // update also preview of the whole symbol
377}
378
379QgsSymbolLayerModelNode *QgsSymbolSelectorWidget::currentLayerNode()
380{
381 QgsSymbolLayerModelNode *node = currentNode();
382 if ( !node || !node->isLayer() )
383 return nullptr;
384
385 return node;
386}
387
388QgsSymbolLayer *QgsSymbolSelectorWidget::currentLayer()
389{
390 QgsSymbolLayerModelNode *node = currentLayerNode();
391 return node ? node->layer() : nullptr;
392}
393
394QgsSymbolLayerModelNode *QgsSymbolSelectorWidget::currentNode()
395{
396 const QModelIndex idx = layersTree->currentIndex();
397 if ( !idx.isValid() )
398 return nullptr;
399
400 return mSymbolLayersModel->index2node( idx );
401}
402
404{
405 updateUi();
406
407 QgsSymbolLayerModelNode *node = currentNode();
408 if ( !node )
409 return;
410
411 if ( node->isLayer() )
412 {
413 QgsSymbolLayerModelNode *parent = node->parent();
414 mDataDefineRestorer = std::make_unique<DataDefinedRestorer>( parent->symbol(), node->layer() );
415 QgsLayerPropertiesWidget *layerProp = new QgsLayerPropertiesWidget( node->layer(), parent->symbol(), mVectorLayer );
416 layerProp->setDockMode( this->dockMode() );
417 layerProp->setContext( mContext );
418 setWidget( layerProp );
419 connect( layerProp, &QgsLayerPropertiesWidget::changed, mDataDefineRestorer.get(), &DataDefinedRestorer::restore );
421 connect( layerProp, &QgsLayerPropertiesWidget::changed, this, &QgsSymbolSelectorWidget::emitSymbolModified );
422 // This connection when layer type is changed
424
425 connectChildPanel( layerProp );
426 }
427 else
428 {
429 // then it must be a symbol
430 mDataDefineRestorer.reset();
432 node->symbol()->setLayer( mVectorLayer );
434 // Now populate symbols of that type using the symbols list widget:
435 QgsSymbolsListWidget *symbolsList = new QgsSymbolsListWidget( node->symbol(), mStyle, mAdvancedMenu, this, mVectorLayer );
436 symbolsList->setContext( mContext );
437
438 setWidget( symbolsList );
440 }
441 updateLockButton();
442}
443
445{
446 QgsSymbolLayerModelNode *node = currentNode();
447 if ( !node || node->isLayer() )
448 return;
449 // disconnect to avoid recreating widget
450 disconnect( layersTree->selectionModel(), &QItemSelectionModel::currentChanged, this, &QgsSymbolSelectorWidget::layerChanged );
451 if ( node->parent() && !node->parent()->isRootNode() )
452 {
453 // it is a sub-symbol
454
455 QgsSymbol *symbol = node->symbol();
456 QgsSymbolLayerModelNode *parent = node->parent();
457
458 mSymbolLayersModel->updateNode( symbol, parent );
459
460 layersTree->expandRecursively( mSymbolLayersModel->node2index( parent->childAt( 0 ) ) );
461 layersTree->setCurrentIndex( mSymbolLayersModel->node2index( parent->childAt( 0 ) ) );
462 }
463 else
464 {
465 //it is the symbol itself
466 reloadSymbol();
467 const QModelIndex newIndex = layersTree->model()->index( 0, 0 );
468 layersTree->setCurrentIndex( newIndex );
469 }
471 emitSymbolModified();
472 // connect it back once things are set
473 connect( layersTree->selectionModel(), &QItemSelectionModel::currentChanged, this, &QgsSymbolSelectorWidget::layerChanged );
474}
475
476void QgsSymbolSelectorWidget::setWidget( QWidget *widget )
477{
478 const int index = stackedWidget->addWidget( widget );
479 stackedWidget->setCurrentIndex( index );
480 if ( mPresentWidget )
481 mPresentWidget->deleteLater();
482 mPresentWidget = widget;
483}
484
485void QgsSymbolSelectorWidget::updateLockButton()
486{
487 QgsSymbolLayer *layer = currentLayer();
488 if ( !layer )
489 return;
490 mLockColorAction->setChecked( layer->isLocked() );
491 mLockSelectionColorAction->setChecked( layer->userFlags() & Qgis::SymbolLayerUserFlag::DisableSelectionRecoloring );
492
493 updateLockButtonIcon();
494}
495
496void QgsSymbolSelectorWidget::updateLockButtonIcon()
497{
498 if ( mLockColorAction->isChecked() && mLockSelectionColorAction->isChecked() )
499 btnLock->setIcon( QgsApplication::getThemeIcon( u"locked.svg"_s ) );
500 else if ( mLockColorAction->isChecked() )
501 btnLock->setIcon( QgsApplication::getThemeIcon( u"mIconColorLocked.svg"_s ) );
502 else if ( mLockSelectionColorAction->isChecked() )
503 btnLock->setIcon( QgsApplication::getThemeIcon( u"mIconSelectLocked.svg"_s ) );
504 else
505 btnLock->setIcon( QgsApplication::getThemeIcon( u"unlocked.svg"_s ) );
506}
507
509{
510 const QModelIndex idx = layersTree->currentIndex();
511
512 QgsSymbolLayerModelNode *newNode = mSymbolLayersModel->addLayer( idx );
513
514 layersTree->expandRecursively( mSymbolLayersModel->node2index( newNode ) );
515 layersTree->setCurrentIndex( mSymbolLayersModel->node2index( newNode ) );
516 updateUi();
518 emitSymbolModified();
519}
520
522{
523 QgsSymbolLayerModelNode *node = currentLayerNode();
524 if ( !node )
525 return;
526
527 mSymbolLayersModel->removeLayer( node );
528
529 updateUi();
531 emitSymbolModified();
532}
533
535{
536 moveLayerByOffset( +1 );
537}
538
540{
541 moveLayerByOffset( -1 );
542}
543
544void QgsSymbolSelectorWidget::moveLayerByOffset( int offset )
545{
546 QgsSymbolLayerModelNode *node = currentLayerNode();
547 if ( !node )
548 return;
549
550 mSymbolLayersModel->moveLayerByOffset( node, offset );
551
552 layersTree->setCurrentIndex( mSymbolLayersModel->node2index( node ) );
553
555 emitSymbolModified();
556 updateUi();
557}
558
560{
561 QgsSymbolLayer *layer = currentLayer();
562 if ( !layer )
563 return;
564 layer->setLocked( mLockColorAction->isChecked() );
565 updateLockButtonIcon();
566 emit symbolModified();
567}
568
570{
571 QgsSymbolLayerModelNode *node = currentLayerNode();
572 if ( !node )
573 return;
574
575 QgsSymbolLayerModelNode *newNode = mSymbolLayersModel->duplicateLayer( node );
576
577 if ( newNode )
578 {
579 layersTree->expandRecursively( mSymbolLayersModel->node2index( newNode ) );
580 layersTree->setCurrentIndex( mSymbolLayersModel->node2index( newNode ) );
581 }
582
583 updateUi();
585 emitSymbolModified();
586}
587
589{
590 QgsSymbolLayerModelNode *node = currentLayerNode();
591
592 mSymbolLayersModel->changeLayer( node, newLayer );
593
594 QModelIndex nodeIndex = mSymbolLayersModel->node2index( node );
595 layersTree->expandRecursively( nodeIndex );
596 layersTree->setCurrentIndex( nodeIndex );
597
599 emitSymbolModified();
600 // Important: This lets the layer have its own layer properties widget
601 layerChanged();
602}
603
604void QgsSymbolSelectorWidget::updateListIcons()
605{
606 mSymbolLayersModel->setScreen( screen() );
607}
608
609
611 : QDialog( parent )
612{
613 setLayout( new QVBoxLayout() );
614
615 mSelectorWidget = new QgsSymbolSelectorWidget( symbol, style, vl, this );
616 mButtonBox = new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::Ok );
617
618 connect( mButtonBox, &QDialogButtonBox::accepted, this, &QDialog::accept );
619 connect( mButtonBox, &QDialogButtonBox::rejected, this, &QDialog::reject );
620 connect( mButtonBox, &QDialogButtonBox::helpRequested, this, &QgsSymbolSelectorDialog::showHelp );
621
622 layout()->addWidget( mSelectorWidget );
623 layout()->addWidget( mButtonBox );
624
625 connect( mSelectorWidget, &QgsPanelWidget::panelAccepted, this, &QDialog::reject );
626
627 mSelectorWidget->setMinimumSize( 460, 560 );
628 setObjectName( u"SymbolSelectorDialog"_s );
630
631 // Can be embedded in renderer properties dialog
632 if ( embedded )
633 {
634 mButtonBox->hide();
635 layout()->setContentsMargins( 0, 0, 0, 0 );
636 }
637 else
638 {
639 setWindowTitle( tr( "Symbol Selector" ) );
640 }
641 mSelectorWidget->setDockMode( embedded );
642}
643
645{
646 return mSelectorWidget->advancedMenu();
647}
648
650{
651 mSelectorWidget->setContext( context );
652}
653
655{
656 return mSelectorWidget->context();
657}
658
660{
661 return mSelectorWidget->symbol();
662}
663
665{
666 // Ignore the ESC key to avoid close the dialog without the properties window
667 if ( !isWindow() && e->key() == Qt::Key_Escape )
668 {
669 e->ignore();
670 }
671 else
672 {
673 QDialog::keyPressEvent( e );
674 }
675}
676
677void QgsSymbolSelectorDialog::reloadSymbol()
678{
679 mSelectorWidget->reloadSymbol();
680}
681
683{
684 mSelectorWidget->loadSymbol( symbol );
685}
686
687void QgsSymbolSelectorDialog::updateUi()
688{
689 mSelectorWidget->updateUi();
690}
691
692void QgsSymbolSelectorDialog::updateLockButton()
693{
694 mSelectorWidget->updateLockButton();
695}
696
697QgsSymbolLayerModelNode *QgsSymbolSelectorDialog::currentLayerNode()
698{
699 return mSelectorWidget->currentLayerNode();
700}
701
702QgsSymbolLayer *QgsSymbolSelectorDialog::currentLayer()
703{
704 return mSelectorWidget->currentLayer();
705}
706
707void QgsSymbolSelectorDialog::moveLayerByOffset( int offset )
708{
709 mSelectorWidget->moveLayerByOffset( offset );
710}
711
712void QgsSymbolSelectorDialog::setWidget( QWidget *widget )
713{
714 mSelectorWidget->setWidget( widget );
715}
716
718{
719 mSelectorWidget->moveLayerDown();
720}
721
723{
724 mSelectorWidget->moveLayerUp();
725}
726
728{
729 mSelectorWidget->addLayer();
730}
731
733{
734 mSelectorWidget->removeLayer();
735}
736
738{
739 mSelectorWidget->lockLayer();
740}
741
743{
744 mSelectorWidget->duplicateLayer();
745}
746
748{
749 mSelectorWidget->layerChanged();
750}
751
753{
754 mSelectorWidget->updateLayerPreview();
755}
756
758{
759 mSelectorWidget->updatePreview();
760}
761
763{
764 mSelectorWidget->symbolChanged();
765}
766
768{
769 mSelectorWidget->changeLayer( layer );
770}
771
772QDialogButtonBox *QgsSymbolSelectorDialog::buttonBox() const
773{
774 return mButtonBox;
775}
776
777void QgsSymbolSelectorDialog::showHelp()
778{
779 QgsHelp::openHelp( u"style_library/symbol_selector.html"_s );
780}
781
782void QgsSymbolSelectorWidget::projectDataChanged()
783{
784 mBlockModified = true;
787 mBlockModified = false;
788}
789
790void QgsSymbolSelectorWidget::layersAboutToBeRemoved( const QList<QgsMapLayer *> &layers )
791{
792 if ( mVectorLayer && layers.contains( mVectorLayer ) )
793 {
794 disconnect( QgsProject::instance(), &QgsProject::projectColorsChanged, this, &QgsSymbolSelectorWidget::projectDataChanged );
795 }
796}
797
798void QgsSymbolSelectorWidget::emitSymbolModified()
799{
800 if ( !mBlockModified )
801 {
802 emit symbolModified();
803 }
804}
QFlags< SymbolLayerUserFlag > SymbolLayerUserFlags
Symbol layer user flags.
Definition qgis.h:972
@ FlagIncludeCrosshairsForMarkerSymbols
Include a crosshairs reference image in the background of marker symbol previews.
Definition qgis.h:925
@ DisableSelectionRecoloring
If present, indicates that the symbol layer should not be recolored when rendering selected features.
Definition qgis.h:963
@ Marker
Marker symbol.
Definition qgis.h:652
@ Line
Line symbol.
Definition qgis.h:653
static const double UI_SCALE_FACTOR
UI scaling factor.
Definition qgis.h:7084
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.
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.
Abstract base class for marker symbol layers.
A marker symbol type, for rendering Point and MultiPoint geometries.
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 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.
A node contained within a QgsSymbolLayerModel.
QgsSymbolLayerModelNode * parent()
Returns the pointer of the parent node. If parent is nullptr, the node is a root node.
QgsSymbol * symbol()
Returns the symbol pointer; helpful in determining a layer's parent symbol.
QgsSymbolLayer * layer()
Returns the symbol layer pointer.
int rowCount() const
Returns the number of rows(children) belonging to the node.
QgsSymbolLayerModelNode * childAt(int index) const
Returns the child node at the given index.
int rowIndex() const
Returns the row index of the node within its parent.
bool isRootNode() const
Returns true if the node is a root node (i.e. has no parent).
bool isLayer() const
Returns true if the node is a symbol layer. And otherwise, it is a symbol.
A QAbstractItemModel subclass for displaying a QgsSymbol in a tree view in the symbology panel.
void moveLayerByOffset(QgsSymbolLayerModelNode *node, int offset)
Moves the symbol layer node by the offset in the parent hierarchy.
QModelIndex node2index(QgsSymbolLayerModelNode *node) const
Returns the model index corresponding to the given node.
void setSymbol(QgsSymbol *symbol)
Sets the symbol associated with the model.
void setScreen(QScreen *screen)
Set the QScreen of the model itself.
Abstract base class for symbol layers.
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.
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 loadSymbol(QgsSymbol *symbol)
Loads the given symbol into the widget.
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.
Symbol selector widget that can be used to select and build a symbol.
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 loadSymbol(QgsSymbol *symbol)
Loads the given symbol into the widget.
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
Qgis::SymbolType type() const
Returns the symbol's type.
Definition qgssymbol.h:296
Q_DECL_DEPRECATED void setLayer(const QgsVectorLayer *layer)
Sets the vector layer associated with the symbol.
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.
#define Q_NOWARN_DEPRECATED_POP
Definition qgis.h:8086
#define Q_NOWARN_DEPRECATED_PUSH
Definition qgis.h:8085