39#include <QColorDialog>
41#include <QStandardItemModel>
42#include <QInputDialog>
49#include <QStandardItem>
53static const int SYMBOL_LAYER_ITEM_TYPE = QStandardItem::UserType + 1;
63 mDDSize = mMarker->dataDefinedSize();
64 mDDAngle = mMarker->dataDefinedAngle();
66 if ( !mDDSize && !mDDAngle )
73 mDDWidth = mLine->dataDefinedWidth();
81void DataDefinedRestorer::save()
85 mSize = mMarkerSymbolLayer->size();
86 mAngle = mMarkerSymbolLayer->angle();
87 mMarkerOffset = mMarkerSymbolLayer->offset();
91 mWidth = mLineSymbolLayer->width();
92 mLineOffset = mLineSymbolLayer->offset();
96void DataDefinedRestorer::restore()
101 ( mSize != mMarkerSymbolLayer->size() || mMarkerOffset != mMarkerSymbolLayer->offset() ) )
102 mMarker->setDataDefinedSize( mDDSize );
104 mAngle != mMarkerSymbolLayer->angle() )
105 mMarker->setDataDefinedAngle( mDDAngle );
110 ( mWidth != mLineSymbolLayer->width() || mLineOffset != mLineSymbolLayer->offset() ) )
111 mLine->setDataDefinedWidth( mDDWidth );
118class SymbolLayerItem :
public QStandardItem
122 : mVectorLayer( vectorLayer )
125 setLayer( layer, symbolType );
129 : mVectorLayer( vectorLayer )
140 mSymbolType = symbolType;
154 if ( !mSize.isValid() )
157 mSize = QSize( size, size );
170 if (
auto *lParent = parent() )
171 static_cast<SymbolLayerItem *
>( lParent )->updatePreview();
174 int type()
const override {
return SYMBOL_LAYER_ITEM_TYPE; }
175 bool isLayer() {
return mIsLayer; }
188 QVariant data(
int role )
const override
190 if ( role == Qt::DisplayRole || role == Qt::EditRole )
202 switch ( mSymbol->type() )
205 return QCoreApplication::translate(
"SymbolLayerItem",
"Marker" );
207 return QCoreApplication::translate(
"SymbolLayerItem",
"Fill" );
209 return QCoreApplication::translate(
"SymbolLayerItem",
"Line" );
215 else if ( role == Qt::ForegroundRole && mIsLayer )
217 if ( !mLayer->enabled() )
219 QPalette
pal = qApp->palette();
220 QBrush brush = QStandardItem::data( role ).value< QBrush >();
221 brush.setColor(
pal.color( QPalette::Disabled, QPalette::WindowText ) );
232 if ( role == Qt::CheckStateRole )
234 return QStandardItem::data( role );
240 QPointer< QgsVectorLayer > mVectorLayer;
241 bool mIsLayer =
false;
244 QPointer< QScreen > mScreen;
258 setWindowModality( Qt::WindowModal );
262 this->layout()->setContentsMargins( 0, 0, 0, 0 );
264 layersTree->setMaximumHeight(
static_cast< int >(
Qgis::UI_SCALE_FACTOR * fontMetrics().height() * 7 ) );
265 layersTree->setMinimumHeight( layersTree->maximumHeight() );
266 lblPreview->setMaximumWidth( layersTree->maximumHeight() );
274 iconLock.addFile(
QgsApplication::iconPath( QStringLiteral(
"unlocked.svg" ) ), QSize(), QIcon::Normal, QIcon::Off );
275 iconLock.addFile(
QgsApplication::iconPath( QStringLiteral(
"unlocked.svg" ) ), QSize(), QIcon::Active, QIcon::Off );
276 btnLock->setIcon( iconLock );
281 mSymbolLayersModel =
new QStandardItemModel( layersTree );
283 layersTree->setModel( mSymbolLayersModel );
284 layersTree->setHeaderHidden(
true );
296 mPreviewExpressionContext.
setFeature( mPreviewFeature );
304 QItemSelectionModel *selModel = layersTree->selectionModel();
307 loadSymbol( mSymbol,
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->invisibleRootItem() ) );
321 const QModelIndex newIndex = layersTree->model()->index( 0, 0 );
322 layersTree->setCurrentIndex( newIndex );
349 if ( !mAdvancedMenu )
351 mAdvancedMenu =
new QMenu(
this );
355 return mAdvancedMenu;
364 mPreviewExpressionContext = *lExpressionContext;
368 mPreviewExpressionContext.
setFeature( mPreviewFeature );
371 QWidget *widget = stackedWidget->currentWidget();
373 layerProp->setContext(
context );
375 listWidget->setContext(
context );
394 mSymbolLayersModel->clear();
395 parent =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->invisibleRootItem() );
398 SymbolLayerItem *symbolItem =
new SymbolLayerItem(
symbol, mVectorLayer, screen() );
399 QFont boldFont = symbolItem->font();
400 boldFont.setBold(
true );
401 symbolItem->setFont( boldFont );
402 parent->appendRow( symbolItem );
405 for (
int i = count - 1; i >= 0; i-- )
408 layerItem->setEditable(
false );
409 symbolItem->appendRow( layerItem );
414 layersTree->setExpanded( layerItem->index(),
true );
416 layersTree->setExpanded( symbolItem->index(),
true );
418 if ( mSymbol ==
symbol && !layersTree->currentIndex().isValid() )
421 layersTree->setCurrentIndex( symbolItem->index() );
425void QgsSymbolSelectorWidget::reloadSymbol()
427 mSymbolLayersModel->clear();
428 loadSymbol( mSymbol,
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->invisibleRootItem() ) );
431void QgsSymbolSelectorWidget::updateUi()
433 const QModelIndex currentIdx = layersTree->currentIndex();
434 if ( !currentIdx.isValid() )
437 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( currentIdx ) );
438 if ( !item->isLayer() )
440 btnUp->setEnabled(
false );
441 btnDown->setEnabled(
false );
442 btnRemoveLayer->setEnabled(
false );
443 btnLock->setEnabled(
false );
444 btnDuplicate->setEnabled(
false );
448 const int rowCount = item->parent()->rowCount();
449 const int currentRow = item->row();
451 btnUp->setEnabled( currentRow > 0 );
452 btnDown->setEnabled( currentRow < rowCount - 1 );
453 btnRemoveLayer->setEnabled( rowCount > 1 );
454 btnLock->setEnabled(
true );
455 btnDuplicate->setEnabled(
true );
463 std::unique_ptr< QgsSymbol > symbolClone( mSymbol->
clone() );
465 lblPreview->setPixmap( QPixmap::fromImage( preview ) );
467 if ( !mBlockModified )
474 SymbolLayerItem *item = currentLayerItem();
476 item->updatePreview();
481SymbolLayerItem *QgsSymbolSelectorWidget::currentLayerItem()
483 const QModelIndex idx = layersTree->currentIndex();
484 if ( !idx.isValid() )
487 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( idx ) );
488 if ( !item->isLayer() )
496 const QModelIndex idx = layersTree->currentIndex();
497 if ( !idx.isValid() )
500 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( idx ) );
501 if ( item->isLayer() )
502 return item->layer();
511 SymbolLayerItem *currentItem =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( layersTree->currentIndex() ) );
515 if ( currentItem->isLayer() )
517 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( currentItem->parent() );
518 mDataDefineRestorer.reset(
new DataDefinedRestorer( parent->symbol(), currentItem->layer() ) );
522 setWidget( layerProp );
533 mDataDefineRestorer.reset();
535 currentItem->symbol()->setLayer( mVectorLayer );
539 symbolsList->setContext( mContext );
541 setWidget( symbolsList );
549 SymbolLayerItem *currentItem =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( layersTree->currentIndex() ) );
550 if ( !currentItem || currentItem->isLayer() )
554 if ( currentItem->parent() )
558 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( currentItem->parent() );
559 parent->removeRow( 0 );
561 layersTree->setCurrentIndex( parent->child( 0 )->index() );
562 parent->updatePreview();
568 const QModelIndex newIndex = layersTree->model()->index( 0, 0 );
569 layersTree->setCurrentIndex( newIndex );
576void QgsSymbolSelectorWidget::setWidget( QWidget *widget )
578 const int index = stackedWidget->addWidget( widget );
579 stackedWidget->setCurrentIndex( index );
580 if ( mPresentWidget )
581 mPresentWidget->deleteLater();
582 mPresentWidget = widget;
585void QgsSymbolSelectorWidget::updateLockButton()
590 btnLock->setChecked( layer->
isLocked() );
595 const QModelIndex idx = layersTree->currentIndex();
596 if ( !idx.isValid() )
600 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( idx ) );
601 if ( item->isLayer() )
603 insertIdx = item->row();
604 item =
static_cast<SymbolLayerItem *
>( item->parent() );
607 QgsSymbol *parentSymbol = item->symbol();
621 if ( insertIdx == -1 )
628 static_cast<QgsMarkerSymbol *
>( parentSymbol )->setDataDefinedSize( ddSize );
630 static_cast<QgsMarkerSymbol *
>( parentSymbol )->setDataDefinedAngle( ddAngle );
632 static_cast<QgsLineSymbol *
>( parentSymbol )->setDataDefinedWidth( ddWidth );
634 SymbolLayerItem *newLayerItem =
new SymbolLayerItem( newLayer, parentSymbol->
type(), mVectorLayer, screen() );
635 item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem );
636 item->updatePreview();
638 layersTree->setCurrentIndex( mSymbolLayersModel->indexFromItem( newLayerItem ) );
645 SymbolLayerItem *item = currentLayerItem();
646 const int row = item->row();
647 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( item->parent() );
649 const int layerIdx = parent->rowCount() - row - 1;
650 QgsSymbol *parentSymbol = parent->symbol();
653 parent->removeRow( row );
654 parent->updatePreview();
656 const QModelIndex newIdx = parent->child( 0 )->index();
657 layersTree->setCurrentIndex( newIdx );
667 moveLayerByOffset( + 1 );
672 moveLayerByOffset( -1 );
675void QgsSymbolSelectorWidget::moveLayerByOffset(
int offset )
677 SymbolLayerItem *item = currentLayerItem();
680 const int row = item->row();
682 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( item->parent() );
683 QgsSymbol *parentSymbol = parent->symbol();
685 const int layerIdx = parent->rowCount() - row - 1;
690 QList<QStandardItem *> rowItems = parent->takeRow( row );
691 parent->insertRows( row + offset, rowItems );
692 parent->updatePreview();
694 const QModelIndex newIdx = rowItems[ 0 ]->index();
695 layersTree->setCurrentIndex( newIdx );
706 layer->
setLocked( btnLock->isChecked() );
712 const QModelIndex idx = layersTree->currentIndex();
713 if ( !idx.isValid() )
716 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( idx ) );
717 if ( !item->isLayer() )
722 const int insertIdx = item->row();
723 item =
static_cast<SymbolLayerItem *
>( item->parent() );
725 QgsSymbol *parentSymbol = item->symbol();
729 if ( insertIdx == -1 )
734 SymbolLayerItem *newLayerItem =
new SymbolLayerItem( newLayer, parentSymbol->
type(), mVectorLayer, screen() );
735 item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem );
739 layersTree->setExpanded( newLayerItem->index(),
true );
741 item->updatePreview();
743 layersTree->setCurrentIndex( mSymbolLayersModel->indexFromItem( newLayerItem ) );
750 SymbolLayerItem *item = currentLayerItem();
755 item->removeRow( 0 );
765 layersTree->setExpanded( item->index(),
true );
769 const int layerIdx = item->parent()->rowCount() - item->row() - 1;
772 item->updatePreview();
781 setLayout(
new QVBoxLayout() );
784 mButtonBox =
new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::Ok );
786 connect( mButtonBox, &QDialogButtonBox::accepted,
this, &QDialog::accept );
787 connect( mButtonBox, &QDialogButtonBox::rejected,
this, &QDialog::reject );
788 connect( mButtonBox, &QDialogButtonBox::helpRequested,
this, &QgsSymbolSelectorDialog::showHelp );
790 layout()->addWidget( mSelectorWidget );
791 layout()->addWidget( mButtonBox );
795 mSelectorWidget->setMinimumSize( 460, 560 );
796 setObjectName( QStringLiteral(
"SymbolSelectorDialog" ) );
803 layout()->setContentsMargins( 0, 0, 0, 0 );
807 setWindowTitle( tr(
"Symbol Selector" ) );
829 return mSelectorWidget->
symbol();
835 if ( !isWindow() && e->key() == Qt::Key_Escape )
841 QDialog::keyPressEvent( e );
845void QgsSymbolSelectorDialog::reloadSymbol()
847 mSelectorWidget->reloadSymbol();
855void QgsSymbolSelectorDialog::updateUi()
857 mSelectorWidget->updateUi();
860void QgsSymbolSelectorDialog::updateLockButton()
862 mSelectorWidget->updateLockButton();
865SymbolLayerItem *QgsSymbolSelectorDialog::currentLayerItem()
867 return mSelectorWidget->currentLayerItem();
872 return mSelectorWidget->currentLayer();
875void QgsSymbolSelectorDialog::moveLayerByOffset(
int offset )
877 mSelectorWidget->moveLayerByOffset( offset );
880void QgsSymbolSelectorDialog::setWidget( QWidget *widget )
882 mSelectorWidget->setWidget( widget );
945void QgsSymbolSelectorDialog::showHelp()
950void QgsSymbolSelectorWidget::projectDataChanged()
952 mBlockModified =
true;
955 mBlockModified =
false;
958void QgsSymbolSelectorWidget::layersAboutToBeRemoved(
const QList<QgsMapLayer *> &layers )
960 if ( mVectorLayer && layers.contains( mVectorLayer ) )
@ FlagIncludeCrosshairsForMarkerSymbols
Include a crosshairs reference image in the background of marker symbol previews.
SymbolType
Attribute editing capabilities which may be supported by vector data providers.
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.
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.
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...
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