38#include <QColorDialog>
40#include <QStandardItemModel>
41#include <QInputDialog>
48#include <QStandardItem>
52static const int SYMBOL_LAYER_ITEM_TYPE = QStandardItem::UserType + 1;
62 mDDSize = mMarker->dataDefinedSize();
63 mDDAngle = mMarker->dataDefinedAngle();
65 if ( !mDDSize && !mDDAngle )
72 mDDWidth = mLine->dataDefinedWidth();
80void DataDefinedRestorer::save()
84 mSize = mMarkerSymbolLayer->size();
85 mAngle = mMarkerSymbolLayer->angle();
86 mMarkerOffset = mMarkerSymbolLayer->offset();
90 mWidth = mLineSymbolLayer->width();
91 mLineOffset = mLineSymbolLayer->offset();
95void DataDefinedRestorer::restore()
100 ( mSize != mMarkerSymbolLayer->size() || mMarkerOffset != mMarkerSymbolLayer->offset() ) )
101 mMarker->setDataDefinedSize( mDDSize );
103 mAngle != mMarkerSymbolLayer->angle() )
104 mMarker->setDataDefinedAngle( mDDAngle );
109 ( mWidth != mLineSymbolLayer->width() || mLineOffset != mLineSymbolLayer->offset() ) )
110 mLine->setDataDefinedWidth( mDDWidth );
117class SymbolLayerItem :
public QStandardItem
121 : mVectorLayer( vectorLayer )
123 setLayer( layer, symbolType );
127 : mVectorLayer( vectorLayer )
137 mSymbolType = symbolType;
151 if ( !mSize.isValid() )
154 mSize = QSize( size, size );
167 if (
auto *lParent = parent() )
168 static_cast<SymbolLayerItem *
>( lParent )->updatePreview();
171 int type()
const override {
return SYMBOL_LAYER_ITEM_TYPE; }
172 bool isLayer() {
return mIsLayer; }
185 QVariant data(
int role )
const override
187 if ( role == Qt::DisplayRole || role == Qt::EditRole )
199 switch ( mSymbol->type() )
202 return QCoreApplication::translate(
"SymbolLayerItem",
"Marker" );
204 return QCoreApplication::translate(
"SymbolLayerItem",
"Fill" );
206 return QCoreApplication::translate(
"SymbolLayerItem",
"Line" );
212 else if ( role == Qt::ForegroundRole && mIsLayer )
214 if ( !mLayer->enabled() )
216 QPalette
pal = qApp->palette();
217 QBrush brush = QStandardItem::data( role ).value< QBrush >();
218 brush.setColor(
pal.color( QPalette::Disabled, QPalette::WindowText ) );
229 if ( role == Qt::CheckStateRole )
231 return QStandardItem::data( role );
237 QPointer< QgsVectorLayer > mVectorLayer;
238 bool mIsLayer =
false;
254 setWindowModality( Qt::WindowModal );
258 this->layout()->setContentsMargins( 0, 0, 0, 0 );
260 layersTree->setMaximumHeight(
static_cast< int >(
Qgis::UI_SCALE_FACTOR * fontMetrics().height() * 7 ) );
261 layersTree->setMinimumHeight( layersTree->maximumHeight() );
262 lblPreview->setMaximumWidth( layersTree->maximumHeight() );
270 iconLock.addFile(
QgsApplication::iconPath( QStringLiteral(
"unlocked.svg" ) ), QSize(), QIcon::Normal, QIcon::Off );
271 iconLock.addFile(
QgsApplication::iconPath( QStringLiteral(
"unlocked.svg" ) ), QSize(), QIcon::Active, QIcon::Off );
272 btnLock->setIcon( iconLock );
277 mSymbolLayersModel =
new QStandardItemModel( layersTree );
279 layersTree->setModel( mSymbolLayersModel );
280 layersTree->setHeaderHidden(
true );
292 mPreviewExpressionContext.
setFeature( mPreviewFeature );
300 QItemSelectionModel *selModel = layersTree->selectionModel();
303 loadSymbol( mSymbol,
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->invisibleRootItem() ) );
317 const QModelIndex newIndex = layersTree->model()->index( 0, 0 );
318 layersTree->setCurrentIndex( newIndex );
345 if ( !mAdvancedMenu )
347 mAdvancedMenu =
new QMenu(
this );
351 return mAdvancedMenu;
360 mPreviewExpressionContext = *lExpressionContext;
364 mPreviewExpressionContext.
setFeature( mPreviewFeature );
367 QWidget *widget = stackedWidget->currentWidget();
369 layerProp->setContext(
context );
371 listWidget->setContext(
context );
390 mSymbolLayersModel->clear();
391 parent =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->invisibleRootItem() );
394 SymbolLayerItem *symbolItem =
new SymbolLayerItem(
symbol, mVectorLayer );
395 QFont boldFont = symbolItem->font();
396 boldFont.setBold(
true );
397 symbolItem->setFont( boldFont );
398 parent->appendRow( symbolItem );
401 for (
int i = count - 1; i >= 0; i-- )
404 layerItem->setEditable(
false );
405 symbolItem->appendRow( layerItem );
410 layersTree->setExpanded( layerItem->index(),
true );
412 layersTree->setExpanded( symbolItem->index(),
true );
414 if ( mSymbol ==
symbol && !layersTree->currentIndex().isValid() )
417 layersTree->setCurrentIndex( symbolItem->index() );
421void QgsSymbolSelectorWidget::reloadSymbol()
423 mSymbolLayersModel->clear();
424 loadSymbol( mSymbol,
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->invisibleRootItem() ) );
427void QgsSymbolSelectorWidget::updateUi()
429 const QModelIndex currentIdx = layersTree->currentIndex();
430 if ( !currentIdx.isValid() )
433 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( currentIdx ) );
434 if ( !item->isLayer() )
436 btnUp->setEnabled(
false );
437 btnDown->setEnabled(
false );
438 btnRemoveLayer->setEnabled(
false );
439 btnLock->setEnabled(
false );
440 btnDuplicate->setEnabled(
false );
444 const int rowCount = item->parent()->rowCount();
445 const int currentRow = item->row();
447 btnUp->setEnabled( currentRow > 0 );
448 btnDown->setEnabled( currentRow < rowCount - 1 );
449 btnRemoveLayer->setEnabled( rowCount > 1 );
450 btnLock->setEnabled(
true );
451 btnDuplicate->setEnabled(
true );
459 std::unique_ptr< QgsSymbol > symbolClone( mSymbol->
clone() );
461 lblPreview->setPixmap( QPixmap::fromImage( preview ) );
463 if ( !mBlockModified )
470 SymbolLayerItem *item = currentLayerItem();
472 item->updatePreview();
477SymbolLayerItem *QgsSymbolSelectorWidget::currentLayerItem()
479 const QModelIndex idx = layersTree->currentIndex();
480 if ( !idx.isValid() )
483 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( idx ) );
484 if ( !item->isLayer() )
492 const QModelIndex idx = layersTree->currentIndex();
493 if ( !idx.isValid() )
496 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( idx ) );
497 if ( item->isLayer() )
498 return item->layer();
507 SymbolLayerItem *currentItem =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( layersTree->currentIndex() ) );
511 if ( currentItem->isLayer() )
513 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( currentItem->parent() );
514 mDataDefineRestorer.reset(
new DataDefinedRestorer( parent->symbol(), currentItem->layer() ) );
518 setWidget( layerProp );
529 mDataDefineRestorer.reset();
531 currentItem->symbol()->setLayer( mVectorLayer );
535 symbolsList->setContext( mContext );
537 setWidget( symbolsList );
545 SymbolLayerItem *currentItem =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( layersTree->currentIndex() ) );
546 if ( !currentItem || currentItem->isLayer() )
550 if ( currentItem->parent() )
554 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( currentItem->parent() );
555 parent->removeRow( 0 );
557 layersTree->setCurrentIndex( parent->child( 0 )->index() );
558 parent->updatePreview();
564 const QModelIndex newIndex = layersTree->model()->index( 0, 0 );
565 layersTree->setCurrentIndex( newIndex );
572void QgsSymbolSelectorWidget::setWidget( QWidget *widget )
574 const int index = stackedWidget->addWidget( widget );
575 stackedWidget->setCurrentIndex( index );
576 if ( mPresentWidget )
577 mPresentWidget->deleteLater();
578 mPresentWidget = widget;
581void QgsSymbolSelectorWidget::updateLockButton()
586 btnLock->setChecked( layer->
isLocked() );
591 const QModelIndex idx = layersTree->currentIndex();
592 if ( !idx.isValid() )
596 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( idx ) );
597 if ( item->isLayer() )
599 insertIdx = item->row();
600 item =
static_cast<SymbolLayerItem *
>( item->parent() );
603 QgsSymbol *parentSymbol = item->symbol();
617 if ( insertIdx == -1 )
624 static_cast<QgsMarkerSymbol *
>( parentSymbol )->setDataDefinedSize( ddSize );
626 static_cast<QgsMarkerSymbol *
>( parentSymbol )->setDataDefinedAngle( ddAngle );
628 static_cast<QgsLineSymbol *
>( parentSymbol )->setDataDefinedWidth( ddWidth );
630 SymbolLayerItem *newLayerItem =
new SymbolLayerItem( newLayer, parentSymbol->
type(), mVectorLayer );
631 item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem );
632 item->updatePreview();
634 layersTree->setCurrentIndex( mSymbolLayersModel->indexFromItem( newLayerItem ) );
641 SymbolLayerItem *item = currentLayerItem();
642 const int row = item->row();
643 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( item->parent() );
645 const int layerIdx = parent->rowCount() - row - 1;
646 QgsSymbol *parentSymbol = parent->symbol();
649 parent->removeRow( row );
650 parent->updatePreview();
652 const QModelIndex newIdx = parent->child( 0 )->index();
653 layersTree->setCurrentIndex( newIdx );
663 moveLayerByOffset( + 1 );
668 moveLayerByOffset( -1 );
671void QgsSymbolSelectorWidget::moveLayerByOffset(
int offset )
673 SymbolLayerItem *item = currentLayerItem();
676 const int row = item->row();
678 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( item->parent() );
679 QgsSymbol *parentSymbol = parent->symbol();
681 const int layerIdx = parent->rowCount() - row - 1;
686 QList<QStandardItem *> rowItems = parent->takeRow( row );
687 parent->insertRows( row + offset, rowItems );
688 parent->updatePreview();
690 const QModelIndex newIdx = rowItems[ 0 ]->index();
691 layersTree->setCurrentIndex( newIdx );
702 layer->
setLocked( btnLock->isChecked() );
708 const QModelIndex idx = layersTree->currentIndex();
709 if ( !idx.isValid() )
712 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( idx ) );
713 if ( !item->isLayer() )
718 const int insertIdx = item->row();
719 item =
static_cast<SymbolLayerItem *
>( item->parent() );
721 QgsSymbol *parentSymbol = item->symbol();
725 if ( insertIdx == -1 )
730 SymbolLayerItem *newLayerItem =
new SymbolLayerItem( newLayer, parentSymbol->
type(), mVectorLayer );
731 item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem );
735 layersTree->setExpanded( newLayerItem->index(),
true );
737 item->updatePreview();
739 layersTree->setCurrentIndex( mSymbolLayersModel->indexFromItem( newLayerItem ) );
746 SymbolLayerItem *item = currentLayerItem();
751 item->removeRow( 0 );
761 layersTree->setExpanded( item->index(),
true );
765 const int layerIdx = item->parent()->rowCount() - item->row() - 1;
768 item->updatePreview();
777 setLayout(
new QVBoxLayout() );
780 mButtonBox =
new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::Ok );
782 connect( mButtonBox, &QDialogButtonBox::accepted,
this, &QDialog::accept );
783 connect( mButtonBox, &QDialogButtonBox::rejected,
this, &QDialog::reject );
784 connect( mButtonBox, &QDialogButtonBox::helpRequested,
this, &QgsSymbolSelectorDialog::showHelp );
786 layout()->addWidget( mSelectorWidget );
787 layout()->addWidget( mButtonBox );
791 mSelectorWidget->setMinimumSize( 460, 560 );
792 setObjectName( QStringLiteral(
"SymbolSelectorDialog" ) );
799 layout()->setContentsMargins( 0, 0, 0, 0 );
803 setWindowTitle( tr(
"Symbol Selector" ) );
825 return mSelectorWidget->
symbol();
831 if ( !isWindow() && e->key() == Qt::Key_Escape )
837 QDialog::keyPressEvent( e );
841void QgsSymbolSelectorDialog::reloadSymbol()
843 mSelectorWidget->reloadSymbol();
851void QgsSymbolSelectorDialog::updateUi()
853 mSelectorWidget->updateUi();
856void QgsSymbolSelectorDialog::updateLockButton()
858 mSelectorWidget->updateLockButton();
861SymbolLayerItem *QgsSymbolSelectorDialog::currentLayerItem()
863 return mSelectorWidget->currentLayerItem();
868 return mSelectorWidget->currentLayer();
871void QgsSymbolSelectorDialog::moveLayerByOffset(
int offset )
873 mSelectorWidget->moveLayerByOffset( offset );
876void QgsSymbolSelectorDialog::setWidget( QWidget *widget )
878 mSelectorWidget->setWidget( widget );
941void QgsSymbolSelectorDialog::showHelp()
946void QgsSymbolSelectorWidget::projectDataChanged()
948 mBlockModified =
true;
951 mBlockModified =
false;
954void QgsSymbolSelectorWidget::layersAboutToBeRemoved(
const QList<QgsMapLayer *> &layers )
956 if ( mVectorLayer && layers.contains( mVectorLayer ) )
@ FlagIncludeCrosshairsForMarkerSymbols
Include a crosshairs reference image in the background of marker symbol previews.
static const double UI_SCALE_FACTOR
UI scaling factor.
static QgsSymbolLayerRegistry * symbolLayerRegistry()
Returns the application's symbol layer registry, used for managing symbol layers.
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)
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...
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.
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).
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 store for object properties.
void remoteSvgFetched(const QString &url)
Emitted when the cache has finished retrieving an SVG file from a remote url.
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 QPixmap symbolPreviewPixmap(const QgsSymbol *symbol, QSize size, int padding=0, QgsRenderContext *customContext=nullptr, bool selected=false, const QgsExpressionContext *expressionContext=nullptr, const QgsLegendPatchShape *shape=nullptr)
Returns a pixmap preview for a color ramp.
static void resetSymbolLayerIds(QgsSymbol *symbol)
Regenerate recursively unique id from all symbol symbol layers.
static QIcon symbolLayerPreviewIcon(const QgsSymbolLayer *layer, Qgis::RenderUnit u, QSize size, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::SymbolType parentSymbolType=Qgis::SymbolType::Hybrid, QgsMapLayer *mapLayer=nullptr)
Draws a symbol layer preview to an icon.
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...
virtual QgsSymbol * subSymbol()
Returns the symbol's sub symbol, if present.
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 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
void loadSymbol(QgsSymbol *symbol, SymbolLayerItem *parent=nullptr)
Loads the given symbol into the widget.
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.
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.
Qgis::SymbolType type() const
Returns the symbol's type.
Q_DECL_DEPRECATED void setLayer(const QgsVectorLayer *layer)
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
#define Q_NOWARN_DEPRECATED_PUSH