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() );
460 const QImage preview = symbolClone->bigSymbolPreviewImage( &mPreviewExpressionContext, Qgis::SymbolPreviewFlags() );
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();
724 if ( insertIdx == -1 )
729 SymbolLayerItem *newLayerItem =
new SymbolLayerItem( newLayer, parentSymbol->
type(), mVectorLayer );
730 item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem );
734 layersTree->setExpanded( newLayerItem->index(),
true );
736 item->updatePreview();
738 layersTree->setCurrentIndex( mSymbolLayersModel->indexFromItem( newLayerItem ) );
745 SymbolLayerItem *item = currentLayerItem();
750 item->removeRow( 0 );
760 layersTree->setExpanded( item->index(),
true );
764 const int layerIdx = item->parent()->rowCount() - item->row() - 1;
767 item->updatePreview();
776 setLayout(
new QVBoxLayout() );
779 mButtonBox =
new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::Ok );
781 connect( mButtonBox, &QDialogButtonBox::accepted,
this, &QDialog::accept );
782 connect( mButtonBox, &QDialogButtonBox::rejected,
this, &QDialog::reject );
783 connect( mButtonBox, &QDialogButtonBox::helpRequested,
this, &QgsSymbolSelectorDialog::showHelp );
785 layout()->addWidget( mSelectorWidget );
786 layout()->addWidget( mButtonBox );
790 mSelectorWidget->setMinimumSize( 460, 560 );
791 setObjectName( QStringLiteral(
"SymbolSelectorDialog" ) );
798 layout()->setContentsMargins( 0, 0, 0, 0 );
802 setWindowTitle( tr(
"Symbol Selector" ) );
824 return mSelectorWidget->
symbol();
830 if ( !isWindow() && e->key() == Qt::Key_Escape )
836 QDialog::keyPressEvent( e );
840void QgsSymbolSelectorDialog::reloadSymbol()
842 mSelectorWidget->reloadSymbol();
850void QgsSymbolSelectorDialog::updateUi()
852 mSelectorWidget->updateUi();
855void QgsSymbolSelectorDialog::updateLockButton()
857 mSelectorWidget->updateLockButton();
860SymbolLayerItem *QgsSymbolSelectorDialog::currentLayerItem()
862 return mSelectorWidget->currentLayerItem();
867 return mSelectorWidget->currentLayer();
870void QgsSymbolSelectorDialog::moveLayerByOffset(
int offset )
872 mSelectorWidget->moveLayerByOffset( offset );
875void QgsSymbolSelectorDialog::setWidget( QWidget *widget )
877 mSelectorWidget->setWidget( widget );
940void QgsSymbolSelectorDialog::showHelp()
945void QgsSymbolSelectorWidget::projectDataChanged()
947 mBlockModified =
true;
950 mBlockModified =
false;
953void QgsSymbolSelectorWidget::layersAboutToBeRemoved(
const QList<QgsMapLayer *> &layers )
955 if ( mVectorLayer && layers.contains( mVectorLayer ) )
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 QIcon symbolLayerPreviewIcon(const QgsSymbolLayer *layer, QgsUnitTypes::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.
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.
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)
@ RenderMillimeters
Millimeters.
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