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 if ( !mLayer->enabled() )
218 QPalette
pal = qApp->palette();
219 QBrush brush = QStandardItem::data( role ).value< QBrush >();
220 brush.setColor(
pal.color( QPalette::Disabled, QPalette::WindowText ) );
231 if ( role == Qt::CheckStateRole )
233 return QStandardItem::data( role );
255 setWindowModality( Qt::WindowModal );
259 this->layout()->setContentsMargins( 0, 0, 0, 0 );
261 layersTree->setMaximumHeight(
static_cast< int >(
Qgis::UI_SCALE_FACTOR * fontMetrics().height() * 7 ) );
262 layersTree->setMinimumHeight( layersTree->maximumHeight() );
263 lblPreview->setMaximumWidth( layersTree->maximumHeight() );
271 iconLock.addFile(
QgsApplication::iconPath( QStringLiteral(
"unlocked.svg" ) ), QSize(), QIcon::Normal, QIcon::Off );
272 iconLock.addFile(
QgsApplication::iconPath( QStringLiteral(
"unlocked.svg" ) ), QSize(), QIcon::Active, QIcon::Off );
273 btnLock->setIcon( iconLock );
278 mSymbolLayersModel =
new QStandardItemModel( layersTree );
280 layersTree->setModel( mSymbolLayersModel );
281 layersTree->setHeaderHidden(
true );
293 mPreviewExpressionContext.
setFeature( mPreviewFeature );
301 QItemSelectionModel *selModel = layersTree->selectionModel();
304 loadSymbol( mSymbol,
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->invisibleRootItem() ) );
318 const QModelIndex newIndex = layersTree->model()->index( 0, 0 );
319 layersTree->setCurrentIndex( newIndex );
346 if ( !mAdvancedMenu )
348 mAdvancedMenu =
new QMenu(
this );
352 return mAdvancedMenu;
361 mPreviewExpressionContext = *lExpressionContext;
365 mPreviewExpressionContext.
setFeature( mPreviewFeature );
368 QWidget *widget = stackedWidget->currentWidget();
370 layerProp->setContext(
context );
372 listWidget->setContext(
context );
391 mSymbolLayersModel->clear();
392 parent =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->invisibleRootItem() );
395 SymbolLayerItem *symbolItem =
new SymbolLayerItem(
symbol );
396 QFont boldFont = symbolItem->font();
397 boldFont.setBold(
true );
398 symbolItem->setFont( boldFont );
399 parent->appendRow( symbolItem );
402 for (
int i = count - 1; i >= 0; i-- )
405 layerItem->setEditable(
false );
406 symbolItem->appendRow( layerItem );
411 layersTree->setExpanded( layerItem->index(),
true );
413 layersTree->setExpanded( symbolItem->index(),
true );
415 if ( mSymbol ==
symbol && !layersTree->currentIndex().isValid() )
418 layersTree->setCurrentIndex( symbolItem->index() );
422 void QgsSymbolSelectorWidget::reloadSymbol()
424 mSymbolLayersModel->clear();
425 loadSymbol( mSymbol,
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->invisibleRootItem() ) );
428 void QgsSymbolSelectorWidget::updateUi()
430 const QModelIndex currentIdx = layersTree->currentIndex();
431 if ( !currentIdx.isValid() )
434 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( currentIdx ) );
435 if ( !item->isLayer() )
437 btnUp->setEnabled(
false );
438 btnDown->setEnabled(
false );
439 btnRemoveLayer->setEnabled(
false );
440 btnLock->setEnabled(
false );
441 btnDuplicate->setEnabled(
false );
445 const int rowCount = item->parent()->rowCount();
446 const int currentRow = item->row();
448 btnUp->setEnabled( currentRow > 0 );
449 btnDown->setEnabled( currentRow < rowCount - 1 );
450 btnRemoveLayer->setEnabled( rowCount > 1 );
451 btnLock->setEnabled(
true );
452 btnDuplicate->setEnabled(
true );
460 std::unique_ptr< QgsSymbol > symbolClone( mSymbol->
clone() );
461 const QImage preview = symbolClone->bigSymbolPreviewImage( &mPreviewExpressionContext, Qgis::SymbolPreviewFlags() );
462 lblPreview->setPixmap( QPixmap::fromImage( preview ) );
464 if ( !mBlockModified )
471 SymbolLayerItem *item = currentLayerItem();
473 item->updatePreview();
478 SymbolLayerItem *QgsSymbolSelectorWidget::currentLayerItem()
480 const QModelIndex idx = layersTree->currentIndex();
481 if ( !idx.isValid() )
484 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( idx ) );
485 if ( !item->isLayer() )
493 const QModelIndex idx = layersTree->currentIndex();
494 if ( !idx.isValid() )
497 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( idx ) );
498 if ( item->isLayer() )
499 return item->layer();
508 SymbolLayerItem *currentItem =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( layersTree->currentIndex() ) );
512 if ( currentItem->isLayer() )
514 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( currentItem->parent() );
515 mDataDefineRestorer.reset(
new DataDefinedRestorer( parent->symbol(), currentItem->layer() ) );
519 setWidget( layerProp );
530 mDataDefineRestorer.reset();
532 currentItem->symbol()->setLayer( mVectorLayer );
536 symbolsList->setContext( mContext );
538 setWidget( symbolsList );
546 SymbolLayerItem *currentItem =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( layersTree->currentIndex() ) );
547 if ( !currentItem || currentItem->isLayer() )
551 if ( currentItem->parent() )
555 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( currentItem->parent() );
556 parent->removeRow( 0 );
558 layersTree->setCurrentIndex( parent->child( 0 )->index() );
559 parent->updatePreview();
565 const QModelIndex newIndex = layersTree->model()->index( 0, 0 );
566 layersTree->setCurrentIndex( newIndex );
573 void QgsSymbolSelectorWidget::setWidget( QWidget *widget )
575 const int index = stackedWidget->addWidget( widget );
576 stackedWidget->setCurrentIndex( index );
577 if ( mPresentWidget )
578 mPresentWidget->deleteLater();
579 mPresentWidget = widget;
582 void QgsSymbolSelectorWidget::updateLockButton()
587 btnLock->setChecked( layer->
isLocked() );
592 const QModelIndex idx = layersTree->currentIndex();
593 if ( !idx.isValid() )
597 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( idx ) );
598 if ( item->isLayer() )
600 insertIdx = item->row();
601 item =
static_cast<SymbolLayerItem *
>( item->parent() );
604 QgsSymbol *parentSymbol = item->symbol();
618 if ( insertIdx == -1 )
625 static_cast<QgsMarkerSymbol *
>( parentSymbol )->setDataDefinedSize( ddSize );
627 static_cast<QgsMarkerSymbol *
>( parentSymbol )->setDataDefinedAngle( ddAngle );
629 static_cast<QgsLineSymbol *
>( parentSymbol )->setDataDefinedWidth( ddWidth );
631 SymbolLayerItem *newLayerItem =
new SymbolLayerItem( newLayer, parentSymbol->
type() );
632 item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem );
633 item->updatePreview();
635 layersTree->setCurrentIndex( mSymbolLayersModel->indexFromItem( newLayerItem ) );
642 SymbolLayerItem *item = currentLayerItem();
643 const int row = item->row();
644 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( item->parent() );
646 const int layerIdx = parent->rowCount() - row - 1;
647 QgsSymbol *parentSymbol = parent->symbol();
650 parent->removeRow( row );
651 parent->updatePreview();
653 const QModelIndex newIdx = parent->child( 0 )->index();
654 layersTree->setCurrentIndex( newIdx );
664 moveLayerByOffset( + 1 );
669 moveLayerByOffset( -1 );
672 void QgsSymbolSelectorWidget::moveLayerByOffset(
int offset )
674 SymbolLayerItem *item = currentLayerItem();
677 const int row = item->row();
679 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( item->parent() );
680 QgsSymbol *parentSymbol = parent->symbol();
682 const int layerIdx = parent->rowCount() - row - 1;
687 QList<QStandardItem *> rowItems = parent->takeRow( row );
688 parent->insertRows( row + offset, rowItems );
689 parent->updatePreview();
691 const QModelIndex newIdx = rowItems[ 0 ]->index();
692 layersTree->setCurrentIndex( newIdx );
703 layer->
setLocked( btnLock->isChecked() );
709 const QModelIndex idx = layersTree->currentIndex();
710 if ( !idx.isValid() )
713 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( idx ) );
714 if ( !item->isLayer() )
719 const int insertIdx = item->row();
720 item =
static_cast<SymbolLayerItem *
>( item->parent() );
722 QgsSymbol *parentSymbol = item->symbol();
725 if ( insertIdx == -1 )
730 SymbolLayerItem *newLayerItem =
new SymbolLayerItem( newLayer, parentSymbol->
type() );
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 );
841 void QgsSymbolSelectorDialog::reloadSymbol()
843 mSelectorWidget->reloadSymbol();
851 void QgsSymbolSelectorDialog::updateUi()
853 mSelectorWidget->updateUi();
856 void QgsSymbolSelectorDialog::updateLockButton()
858 mSelectorWidget->updateLockButton();
861 SymbolLayerItem *QgsSymbolSelectorDialog::currentLayerItem()
863 return mSelectorWidget->currentLayerItem();
868 return mSelectorWidget->currentLayer();
871 void QgsSymbolSelectorDialog::moveLayerByOffset(
int offset )
873 mSelectorWidget->moveLayerByOffset( offset );
876 void QgsSymbolSelectorDialog::setWidget( QWidget *widget )
878 mSelectorWidget->setWidget( widget );
941 void QgsSymbolSelectorDialog::showHelp()
946 void QgsSymbolSelectorWidget::projectDataChanged()
948 mBlockModified =
true;
951 mBlockModified =
false;
954 void QgsSymbolSelectorWidget::layersAboutToBeRemoved(
const QList<QgsMapLayer *> &layers )
956 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 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