29#include "moc_qgssymbolselectordialog.cpp"
31using namespace Qt::StringLiterals;
46#include <QColorDialog>
48#include <QInputDialog>
68 mDDSize = mMarker->dataDefinedSize();
69 mDDAngle = mMarker->dataDefinedAngle();
71 if ( !mDDSize && !mDDAngle )
78 mDDWidth = mLine->dataDefinedWidth();
86void DataDefinedRestorer::save()
90 mSize = mMarkerSymbolLayer->size();
91 mAngle = mMarkerSymbolLayer->angle();
92 mMarkerOffset = mMarkerSymbolLayer->offset();
96 mWidth = mLineSymbolLayer->width();
97 mLineOffset = mLineSymbolLayer->offset();
101void DataDefinedRestorer::restore()
103 if ( mMarker && mMarker->symbolLayerCount() > 1 )
105 if ( mDDSize && ( mSize != mMarkerSymbolLayer->size() || mMarkerOffset != mMarkerSymbolLayer->offset() ) )
106 mMarker->setDataDefinedSize( mDDSize );
107 if ( mDDAngle && mAngle != mMarkerSymbolLayer->angle() )
108 mMarker->setDataDefinedAngle( mDDAngle );
110 else if ( mLine && mLine->symbolLayerCount() > 1 )
112 if ( mDDWidth && ( mWidth != mLineSymbolLayer->width() || mLineOffset != mLineSymbolLayer->offset() ) )
113 mLine->setDataDefinedWidth( mDDWidth );
129 setWindowModality( Qt::WindowModal );
133 this->layout()->setContentsMargins( 0, 0, 0, 0 );
135 layersTree->setMaximumHeight(
static_cast<int>(
Qgis::UI_SCALE_FACTOR * fontMetrics().height() * 7 ) );
136 layersTree->setMinimumHeight( layersTree->maximumHeight() );
137 lblPreview->setMaximumWidth( layersTree->maximumHeight() );
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 );
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 );
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 );
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 );
170 QMenu *lockMenu =
new QMenu(
this );
171 lockMenu->addAction( mLockColorAction );
172 lockMenu->addAction( mLockSelectionColorAction );
173 btnLock->setMenu( lockMenu );
174 btnLock->setPopupMode( QToolButton::InstantPopup );
183 layersTree->setModel( mSymbolLayersModel );
184 layersTree->setHeaderHidden(
true );
196 mPreviewExpressionContext.setFeature( mPreviewFeature );
204 QItemSelectionModel *selModel = layersTree->selectionModel();
207 mSymbolLayersModel->setSymbol( mSymbol );
209 layersTree->expandAll();
217 connect( mLockSelectionColorAction, &QAction::toggled,
this, [
this](
bool checked ) {
225 updateLockButtonIcon();
231 updateLockButtonIcon();
236 const QModelIndex newIndex = layersTree->model()->index( 0, 0 );
237 layersTree->setCurrentIndex( newIndex );
270 widget->mOwnedSymbol = std::move(
symbol );
276 if ( !mAdvancedMenu )
278 mAdvancedMenu =
new QMenu(
this );
282 return mAdvancedMenu;
289 if (
auto *lExpressionContext = mContext.expressionContext() )
291 mPreviewExpressionContext = *lExpressionContext;
295 mPreviewExpressionContext.setFeature( mPreviewFeature );
298 QWidget *widget = stackedWidget->currentWidget();
301 layerProp->setContext(
context );
305 listWidget->setContext(
context );
326void QgsSymbolSelectorWidget::reloadSymbol()
328 mSymbolLayersModel->
setSymbol( mSymbol );
329 layersTree->expandAll();
332void QgsSymbolSelectorWidget::updateUi()
334 QgsSymbolLayerModelNode *node = currentNode();
340 btnUp->setEnabled(
false );
341 btnDown->setEnabled(
false );
342 btnRemoveLayer->setEnabled(
false );
343 btnLock->setEnabled(
false );
344 btnDuplicate->setEnabled(
false );
349 const int currentRow = node->
rowIndex();
351 btnUp->setEnabled( currentRow > 0 );
352 btnDown->setEnabled( currentRow < rowCount - 1 );
353 btnRemoveLayer->setEnabled( rowCount > 1 );
354 btnLock->setEnabled(
true );
355 btnDuplicate->setEnabled(
true );
363 std::unique_ptr<QgsSymbol> symbolClone( mSymbol->clone() );
365 lblPreview->setPixmap( QPixmap::fromImage( preview ) );
374 mSymbolLayersModel->updatePreview( node );
382 if ( !node || !node->
isLayer() )
390 QgsSymbolLayerModelNode *node = currentLayerNode();
391 return node ? node->
layer() :
nullptr;
396 const QModelIndex idx = layersTree->currentIndex();
397 if ( !idx.isValid() )
400 return mSymbolLayersModel->index2node( idx );
414 mDataDefineRestorer = std::make_unique<DataDefinedRestorer>( parent->
symbol(), node->
layer() );
418 setWidget( layerProp );
430 mDataDefineRestorer.reset();
436 symbolsList->setContext( mContext );
438 setWidget( symbolsList );
447 if ( !node || node->
isLayer() )
458 mSymbolLayersModel->updateNode(
symbol, parent );
460 layersTree->expandRecursively( mSymbolLayersModel->node2index( parent->
childAt( 0 ) ) );
461 layersTree->setCurrentIndex( mSymbolLayersModel->node2index( parent->
childAt( 0 ) ) );
467 const QModelIndex newIndex = layersTree->model()->index( 0, 0 );
468 layersTree->setCurrentIndex( newIndex );
471 emitSymbolModified();
476void QgsSymbolSelectorWidget::setWidget( QWidget *widget )
478 const int index = stackedWidget->addWidget( widget );
479 stackedWidget->setCurrentIndex( index );
480 if ( mPresentWidget )
481 mPresentWidget->deleteLater();
482 mPresentWidget = widget;
485void QgsSymbolSelectorWidget::updateLockButton()
487 QgsSymbolLayer *layer = currentLayer();
490 mLockColorAction->setChecked( layer->
isLocked() );
493 updateLockButtonIcon();
496void QgsSymbolSelectorWidget::updateLockButtonIcon()
498 if ( mLockColorAction->isChecked() && mLockSelectionColorAction->isChecked() )
500 else if ( mLockColorAction->isChecked() )
502 else if ( mLockSelectionColorAction->isChecked() )
510 const QModelIndex idx = layersTree->currentIndex();
514 layersTree->expandRecursively( mSymbolLayersModel->node2index( newNode ) );
515 layersTree->setCurrentIndex( mSymbolLayersModel->node2index( newNode ) );
518 emitSymbolModified();
527 mSymbolLayersModel->removeLayer( node );
531 emitSymbolModified();
536 moveLayerByOffset( +1 );
541 moveLayerByOffset( -1 );
544void QgsSymbolSelectorWidget::moveLayerByOffset(
int offset )
552 layersTree->setCurrentIndex( mSymbolLayersModel->
node2index( node ) );
555 emitSymbolModified();
564 layer->
setLocked( mLockColorAction->isChecked() );
565 updateLockButtonIcon();
579 layersTree->expandRecursively( mSymbolLayersModel->node2index( newNode ) );
580 layersTree->setCurrentIndex( mSymbolLayersModel->node2index( newNode ) );
585 emitSymbolModified();
592 mSymbolLayersModel->changeLayer( node, newLayer );
594 QModelIndex nodeIndex = mSymbolLayersModel->node2index( node );
595 layersTree->expandRecursively( nodeIndex );
596 layersTree->setCurrentIndex( nodeIndex );
599 emitSymbolModified();
604void QgsSymbolSelectorWidget::updateListIcons()
606 mSymbolLayersModel->
setScreen( screen() );
613 setLayout(
new QVBoxLayout() );
616 mButtonBox =
new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::Ok );
618 connect( mButtonBox, &QDialogButtonBox::accepted,
this, &QDialog::accept );
619 connect( mButtonBox, &QDialogButtonBox::rejected,
this, &QDialog::reject );
620 connect( mButtonBox, &QDialogButtonBox::helpRequested,
this, &QgsSymbolSelectorDialog::showHelp );
622 layout()->addWidget( mSelectorWidget );
623 layout()->addWidget( mButtonBox );
627 mSelectorWidget->setMinimumSize( 460, 560 );
628 setObjectName( u
"SymbolSelectorDialog"_s );
635 layout()->setContentsMargins( 0, 0, 0, 0 );
639 setWindowTitle( tr(
"Symbol Selector" ) );
641 mSelectorWidget->setDockMode( embedded );
646 return mSelectorWidget->advancedMenu();
651 mSelectorWidget->setContext(
context );
656 return mSelectorWidget->context();
661 return mSelectorWidget->symbol();
667 if ( !isWindow() && e->key() == Qt::Key_Escape )
673 QDialog::keyPressEvent( e );
677void QgsSymbolSelectorDialog::reloadSymbol()
679 mSelectorWidget->reloadSymbol();
684 mSelectorWidget->loadSymbol(
symbol );
687void QgsSymbolSelectorDialog::updateUi()
689 mSelectorWidget->updateUi();
692void QgsSymbolSelectorDialog::updateLockButton()
694 mSelectorWidget->updateLockButton();
699 return mSelectorWidget->currentLayerNode();
704 return mSelectorWidget->currentLayer();
707void QgsSymbolSelectorDialog::moveLayerByOffset(
int offset )
709 mSelectorWidget->moveLayerByOffset( offset );
712void QgsSymbolSelectorDialog::setWidget( QWidget *widget )
714 mSelectorWidget->setWidget( widget );
719 mSelectorWidget->moveLayerDown();
724 mSelectorWidget->moveLayerUp();
729 mSelectorWidget->addLayer();
734 mSelectorWidget->removeLayer();
739 mSelectorWidget->lockLayer();
744 mSelectorWidget->duplicateLayer();
749 mSelectorWidget->layerChanged();
754 mSelectorWidget->updateLayerPreview();
759 mSelectorWidget->updatePreview();
764 mSelectorWidget->symbolChanged();
769 mSelectorWidget->changeLayer( layer );
777void QgsSymbolSelectorDialog::showHelp()
782void QgsSymbolSelectorWidget::projectDataChanged()
784 mBlockModified =
true;
787 mBlockModified =
false;
790void QgsSymbolSelectorWidget::layersAboutToBeRemoved(
const QList<QgsMapLayer *> &layers )
792 if ( mVectorLayer && layers.contains( mVectorLayer ) )
798void QgsSymbolSelectorWidget::emitSymbolModified()
800 if ( !mBlockModified )
QFlags< SymbolLayerUserFlag > SymbolLayerUserFlags
Symbol layer user flags.
@ 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.
static const double UI_SCALE_FACTOR
UI scaling factor.
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...
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
void remoteImageFetched(const QString &url)
Emitted when the cache has finished retrieving an image file from a remote url.
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.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
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.
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 updateLayerPreview()
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.
Contains settings which reflect the context in which a symbol (or renderer) widget is shown,...
Abstract base class for all rendered symbols.
Qgis::SymbolType type() const
Returns the symbol's type.
Q_DECL_DEPRECATED void setLayer(const QgsVectorLayer *layer)
Sets the vector layer associated with the symbol.
Represents a vector layer which manages a vector based dataset.
#define Q_NOWARN_DEPRECATED_POP
#define Q_NOWARN_DEPRECATED_PUSH