46 #include <QColorDialog>
48 #include <QStandardItemModel>
49 #include <QInputDialog>
50 #include <QMessageBox>
56 #include <QStandardItem>
60 static const int SYMBOL_LAYER_ITEM_TYPE = QStandardItem::UserType + 1;
70 mDDSize = mMarker->dataDefinedSize();
71 mDDAngle = mMarker->dataDefinedAngle();
73 if ( !mDDSize && !mDDAngle )
80 mDDWidth = mLine->dataDefinedWidth();
88 void DataDefinedRestorer::save()
92 mSize = mMarkerSymbolLayer->size();
93 mAngle = mMarkerSymbolLayer->angle();
94 mMarkerOffset = mMarkerSymbolLayer->offset();
98 mWidth = mLineSymbolLayer->width();
99 mLineOffset = mLineSymbolLayer->offset();
103 void DataDefinedRestorer::restore()
108 ( mSize != mMarkerSymbolLayer->size() || mMarkerOffset != mMarkerSymbolLayer->offset() ) )
109 mMarker->setDataDefinedSize( mDDSize );
111 mAngle != mMarkerSymbolLayer->angle() )
112 mMarker->setDataDefinedAngle( mDDAngle );
117 ( mWidth != mLineSymbolLayer->width() || mLineOffset != mLineSymbolLayer->offset() ) )
118 mLine->setDataDefinedWidth( mDDWidth );
125 class SymbolLayerItem :
public QStandardItem
130 setLayer( layer, symbolType );
133 explicit SymbolLayerItem(
QgsSymbol *symbol )
143 mSymbolType = symbolType;
157 if ( !mSize.isValid() )
160 mSize = QSize( size, size );
169 if (
auto *lParent = parent() )
170 static_cast<SymbolLayerItem *
>( lParent )->updatePreview();
173 int type()
const override {
return SYMBOL_LAYER_ITEM_TYPE; }
174 bool isLayer() {
return mIsLayer; }
187 QVariant data(
int role )
const override
189 if ( role == Qt::DisplayRole || role == Qt::EditRole )
201 switch ( mSymbol->type() )
204 return QCoreApplication::translate(
"SymbolLayerItem",
"Marker" );
206 return QCoreApplication::translate(
"SymbolLayerItem",
"Fill" );
208 return QCoreApplication::translate(
"SymbolLayerItem",
"Line" );
214 else if ( role == Qt::ForegroundRole && mIsLayer )
216 QBrush brush( Qt::black, Qt::SolidPattern );
217 if ( !mLayer->enabled() )
219 brush.setColor( Qt::lightGray );
226 if ( role == Qt::CheckStateRole )
228 return QStandardItem::data( role );
250 setWindowModality( Qt::WindowModal );
254 this->layout()->setContentsMargins( 0, 0, 0, 0 );
256 layersTree->setMaximumHeight(
static_cast< int >(
Qgis::UI_SCALE_FACTOR * fontMetrics().height() * 7 ) );
257 layersTree->setMinimumHeight( layersTree->maximumHeight() );
258 lblPreview->setMaximumWidth( layersTree->maximumHeight() );
266 iconLock.addFile(
QgsApplication::iconPath( QStringLiteral(
"unlocked.svg" ) ), QSize(), QIcon::Normal, QIcon::Off );
267 iconLock.addFile(
QgsApplication::iconPath( QStringLiteral(
"unlocked.svg" ) ), QSize(), QIcon::Active, QIcon::Off );
268 btnLock->setIcon( iconLock );
273 mSymbolLayersModel =
new QStandardItemModel( layersTree );
275 layersTree->setModel( mSymbolLayersModel );
276 layersTree->setHeaderHidden(
true );
288 mPreviewExpressionContext.
setFeature( mPreviewFeature );
296 QItemSelectionModel *selModel = layersTree->selectionModel();
299 loadSymbol( mSymbol,
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->invisibleRootItem() ) );
313 const QModelIndex newIndex = layersTree->model()->index( 0, 0 );
314 layersTree->setCurrentIndex( newIndex );
341 if ( !mAdvancedMenu )
343 mAdvancedMenu =
new QMenu(
this );
347 return mAdvancedMenu;
356 mPreviewExpressionContext = *lExpressionContext;
360 mPreviewExpressionContext.
setFeature( mPreviewFeature );
363 QWidget *widget = stackedWidget->currentWidget();
365 layerProp->setContext(
context );
367 listWidget->setContext(
context );
386 mSymbolLayersModel->clear();
387 parent =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->invisibleRootItem() );
390 SymbolLayerItem *symbolItem =
new SymbolLayerItem(
symbol );
391 QFont boldFont = symbolItem->font();
392 boldFont.setBold(
true );
393 symbolItem->setFont( boldFont );
394 parent->appendRow( symbolItem );
397 for (
int i = count - 1; i >= 0; i-- )
400 layerItem->setEditable(
false );
401 symbolItem->appendRow( layerItem );
406 layersTree->setExpanded( layerItem->index(),
true );
408 layersTree->setExpanded( symbolItem->index(),
true );
410 if ( mSymbol ==
symbol && !layersTree->currentIndex().isValid() )
413 layersTree->setCurrentIndex( symbolItem->index() );
417 void QgsSymbolSelectorWidget::reloadSymbol()
419 mSymbolLayersModel->clear();
420 loadSymbol( mSymbol,
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->invisibleRootItem() ) );
423 void QgsSymbolSelectorWidget::updateUi()
425 const QModelIndex currentIdx = layersTree->currentIndex();
426 if ( !currentIdx.isValid() )
429 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( currentIdx ) );
430 if ( !item->isLayer() )
432 btnUp->setEnabled(
false );
433 btnDown->setEnabled(
false );
434 btnRemoveLayer->setEnabled(
false );
435 btnLock->setEnabled(
false );
436 btnDuplicate->setEnabled(
false );
440 const int rowCount = item->parent()->rowCount();
441 const int currentRow = item->row();
443 btnUp->setEnabled( currentRow > 0 );
444 btnDown->setEnabled( currentRow < rowCount - 1 );
445 btnRemoveLayer->setEnabled( rowCount > 1 );
446 btnLock->setEnabled(
true );
447 btnDuplicate->setEnabled(
true );
455 std::unique_ptr< QgsSymbol > symbolClone( mSymbol->
clone() );
456 const QImage preview = symbolClone->bigSymbolPreviewImage( &mPreviewExpressionContext, Qgis::SymbolPreviewFlags() );
457 lblPreview->setPixmap( QPixmap::fromImage( preview ) );
459 if ( !mBlockModified )
466 SymbolLayerItem *item = currentLayerItem();
468 item->updatePreview();
473 SymbolLayerItem *QgsSymbolSelectorWidget::currentLayerItem()
475 const QModelIndex idx = layersTree->currentIndex();
476 if ( !idx.isValid() )
479 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( idx ) );
480 if ( !item->isLayer() )
488 const QModelIndex idx = layersTree->currentIndex();
489 if ( !idx.isValid() )
492 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( idx ) );
493 if ( item->isLayer() )
494 return item->layer();
503 SymbolLayerItem *currentItem =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( layersTree->currentIndex() ) );
507 if ( currentItem->isLayer() )
509 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( currentItem->parent() );
510 mDataDefineRestorer.reset(
new DataDefinedRestorer( parent->symbol(), currentItem->layer() ) );
514 setWidget( layerProp );
525 mDataDefineRestorer.reset();
527 currentItem->symbol()->setLayer( mVectorLayer );
531 symbolsList->setContext( mContext );
533 setWidget( symbolsList );
541 SymbolLayerItem *currentItem =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( layersTree->currentIndex() ) );
542 if ( !currentItem || currentItem->isLayer() )
546 if ( currentItem->parent() )
550 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( currentItem->parent() );
551 parent->removeRow( 0 );
553 layersTree->setCurrentIndex( parent->child( 0 )->index() );
554 parent->updatePreview();
560 const QModelIndex newIndex = layersTree->model()->index( 0, 0 );
561 layersTree->setCurrentIndex( newIndex );
568 void QgsSymbolSelectorWidget::setWidget( QWidget *widget )
570 const int index = stackedWidget->addWidget( widget );
571 stackedWidget->setCurrentIndex( index );
572 if ( mPresentWidget )
573 mPresentWidget->deleteLater();
574 mPresentWidget = widget;
577 void QgsSymbolSelectorWidget::updateLockButton()
582 btnLock->setChecked( layer->
isLocked() );
587 const QModelIndex idx = layersTree->currentIndex();
588 if ( !idx.isValid() )
592 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( idx ) );
593 if ( item->isLayer() )
595 insertIdx = item->row();
596 item =
static_cast<SymbolLayerItem *
>( item->parent() );
599 QgsSymbol *parentSymbol = item->symbol();
613 if ( insertIdx == -1 )
620 static_cast<QgsMarkerSymbol *
>( parentSymbol )->setDataDefinedSize( ddSize );
622 static_cast<QgsMarkerSymbol *
>( parentSymbol )->setDataDefinedAngle( ddAngle );
624 static_cast<QgsLineSymbol *
>( parentSymbol )->setDataDefinedWidth( ddWidth );
626 SymbolLayerItem *newLayerItem =
new SymbolLayerItem( newLayer, parentSymbol->
type() );
627 item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem );
628 item->updatePreview();
630 layersTree->setCurrentIndex( mSymbolLayersModel->indexFromItem( newLayerItem ) );
637 SymbolLayerItem *item = currentLayerItem();
638 const int row = item->row();
639 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( item->parent() );
641 const int layerIdx = parent->rowCount() - row - 1;
642 QgsSymbol *parentSymbol = parent->symbol();
645 parent->removeRow( row );
646 parent->updatePreview();
648 const QModelIndex newIdx = parent->child( 0 )->index();
649 layersTree->setCurrentIndex( newIdx );
659 moveLayerByOffset( + 1 );
664 moveLayerByOffset( -1 );
667 void QgsSymbolSelectorWidget::moveLayerByOffset(
int offset )
669 SymbolLayerItem *item = currentLayerItem();
672 const int row = item->row();
674 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( item->parent() );
675 QgsSymbol *parentSymbol = parent->symbol();
677 const int layerIdx = parent->rowCount() - row - 1;
682 QList<QStandardItem *> rowItems = parent->takeRow( row );
683 parent->insertRows( row + offset, rowItems );
684 parent->updatePreview();
686 const QModelIndex newIdx = rowItems[ 0 ]->index();
687 layersTree->setCurrentIndex( newIdx );
698 layer->
setLocked( btnLock->isChecked() );
704 const QModelIndex idx = layersTree->currentIndex();
705 if ( !idx.isValid() )
708 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( idx ) );
709 if ( !item->isLayer() )
714 const int insertIdx = item->row();
715 item =
static_cast<SymbolLayerItem *
>( item->parent() );
717 QgsSymbol *parentSymbol = item->symbol();
720 if ( insertIdx == -1 )
725 SymbolLayerItem *newLayerItem =
new SymbolLayerItem( newLayer, parentSymbol->
type() );
726 item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem );
730 layersTree->setExpanded( newLayerItem->index(),
true );
732 item->updatePreview();
734 layersTree->setCurrentIndex( mSymbolLayersModel->indexFromItem( newLayerItem ) );
741 SymbolLayerItem *item = currentLayerItem();
746 item->removeRow( 0 );
756 layersTree->setExpanded( item->index(),
true );
760 const int layerIdx = item->parent()->rowCount() - item->row() - 1;
763 item->updatePreview();
772 setLayout(
new QVBoxLayout() );
775 mButtonBox =
new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::Ok );
777 connect( mButtonBox, &QDialogButtonBox::accepted,
this, &QDialog::accept );
778 connect( mButtonBox, &QDialogButtonBox::rejected,
this, &QDialog::reject );
779 connect( mButtonBox, &QDialogButtonBox::helpRequested,
this, &QgsSymbolSelectorDialog::showHelp );
781 layout()->addWidget( mSelectorWidget );
782 layout()->addWidget( mButtonBox );
786 mSelectorWidget->setMinimumSize( 460, 560 );
787 setObjectName( QStringLiteral(
"SymbolSelectorDialog" ) );
794 layout()->setContentsMargins( 0, 0, 0, 0 );
798 setWindowTitle( tr(
"Symbol Selector" ) );
820 return mSelectorWidget->
symbol();
826 if ( !isWindow() && e->key() == Qt::Key_Escape )
832 QDialog::keyPressEvent( e );
836 void QgsSymbolSelectorDialog::reloadSymbol()
838 mSelectorWidget->reloadSymbol();
846 void QgsSymbolSelectorDialog::updateUi()
848 mSelectorWidget->updateUi();
851 void QgsSymbolSelectorDialog::updateLockButton()
853 mSelectorWidget->updateLockButton();
856 SymbolLayerItem *QgsSymbolSelectorDialog::currentLayerItem()
858 return mSelectorWidget->currentLayerItem();
863 return mSelectorWidget->currentLayer();
866 void QgsSymbolSelectorDialog::moveLayerByOffset(
int offset )
868 mSelectorWidget->moveLayerByOffset( offset );
871 void QgsSymbolSelectorDialog::setWidget( QWidget *widget )
873 mSelectorWidget->setWidget( widget );
936 void QgsSymbolSelectorDialog::showHelp()
941 void QgsSymbolSelectorWidget::projectDataChanged()
943 mBlockModified =
true;
946 mBlockModified =
false;
949 void QgsSymbolSelectorWidget::layersAboutToBeRemoved(
const QList<QgsMapLayer *> &layers )
951 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.
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 QgsGui * instance()
Returns a pointer to the singleton instance.
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 symbolPreviewIcon(const QgsSymbol *symbol, QSize size, int padding=0, QgsLegendPatchShape *shape=nullptr)
Returns an icon preview for a color ramp.
static QIcon symbolLayerPreviewIcon(const QgsSymbolLayer *layer, QgsUnitTypes::RenderUnit u, QSize size, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::SymbolType parentSymbolType=Qgis::SymbolType::Hybrid)
Draws a symbol layer preview to an icon.
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 QgsSymbolLayer * clone() const =0
Shall be reimplemented by subclasses to create a deep copy of the instance.
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.
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
Qgis::SymbolType type() const
Returns the symbol's type.
virtual QgsSymbol * clone() const =0
Returns a deep copy of this symbol.
Q_DECL_DEPRECATED void setLayer(const QgsVectorLayer *layer)
@ RenderMillimeters
Millimeters.
Represents a vector layer which manages a vector based data sets.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
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