43 #include <QColorDialog> 45 #include <QStandardItemModel> 46 #include <QInputDialog> 47 #include <QMessageBox> 53 #include <QStandardItem> 57 static const int SYMBOL_LAYER_ITEM_TYPE = QStandardItem::UserType + 1;
67 mDDSize = mMarker->dataDefinedSize();
68 mDDAngle = mMarker->dataDefinedAngle();
70 if ( !mDDSize && !mDDAngle )
77 mDDWidth = mLine->dataDefinedWidth();
85 void DataDefinedRestorer::save()
89 mSize = mMarkerSymbolLayer->size();
90 mAngle = mMarkerSymbolLayer->angle();
91 mMarkerOffset = mMarkerSymbolLayer->offset();
95 mWidth = mLineSymbolLayer->width();
96 mLineOffset = mLineSymbolLayer->offset();
100 void DataDefinedRestorer::restore()
105 ( mSize != mMarkerSymbolLayer->size() || mMarkerOffset != mMarkerSymbolLayer->offset() ) )
106 mMarker->setDataDefinedSize( mDDSize );
108 mAngle != mMarkerSymbolLayer->angle() )
109 mMarker->setDataDefinedAngle( mDDAngle );
114 ( mWidth != mLineSymbolLayer->width() || mLineOffset != mLineSymbolLayer->offset() ) )
115 mLine->setDataDefinedWidth( mDDWidth );
122 class SymbolLayerItem :
public QStandardItem
130 explicit SymbolLayerItem(
QgsSymbol *symbol )
153 if ( !mSize.isValid() )
156 mSize = QSize( size, size );
166 static_cast<SymbolLayerItem *
>( parent() )->updatePreview();
169 int type()
const override {
return SYMBOL_LAYER_ITEM_TYPE; }
170 bool isLayer() {
return mIsLayer; }
183 QVariant data(
int role )
const override 185 if ( role == Qt::DisplayRole || role == Qt::EditRole )
191 switch ( mSymbol->type() )
194 return QCoreApplication::translate(
"SymbolLayerItem",
"Marker",
nullptr, QCoreApplication::UnicodeUTF8 );
196 return QCoreApplication::translate(
"SymbolLayerItem",
"Fill",
nullptr, QCoreApplication::UnicodeUTF8 );
198 return QCoreApplication::translate(
"SymbolLayerItem",
"Line",
nullptr, QCoreApplication::UnicodeUTF8 );
204 else if ( role == Qt::ForegroundRole && mIsLayer )
206 QBrush brush( Qt::black, Qt::SolidPattern );
207 if ( !mLayer->enabled() )
209 brush.setColor( Qt::lightGray );
216 if ( role == Qt::CheckStateRole )
218 return QStandardItem::data( role );
237 setWindowModality( Qt::WindowModal );
241 mPresentWidget =
nullptr;
244 this->layout()->setContentsMargins( 0, 0, 0, 0 );
246 layersTree->setMaximumHeight( static_cast< int >(
Qgis::UI_SCALE_FACTOR * fontMetrics().height() * 7 ) );
247 layersTree->setMinimumHeight( layersTree->maximumHeight() );
248 lblPreview->setMaximumWidth( layersTree->maximumHeight() );
256 iconLock.addFile(
QgsApplication::iconPath( QStringLiteral(
"unlocked.svg" ) ), QSize(), QIcon::Normal, QIcon::Off );
257 iconLock.addFile(
QgsApplication::iconPath( QStringLiteral(
"unlocked.svg" ) ), QSize(), QIcon::Active, QIcon::Off );
258 btnLock->setIcon( iconLock );
263 model =
new QStandardItemModel( layersTree );
265 layersTree->setModel( model );
266 layersTree->setHeaderHidden(
true );
271 #if 0 // this is too expensive to do for many providers. TODO revisit when support for connection timeouts is complete across all providers 278 mPreviewExpressionContext.
setFeature( mPreviewFeature );
286 QItemSelectionModel *selModel = layersTree->selectionModel();
289 loadSymbol( symbol, static_cast<SymbolLayerItem *>( model->invisibleRootItem() ) );
303 QModelIndex newIndex = layersTree->model()->index( 0, 0 );
304 layersTree->setCurrentIndex( newIndex );
315 mBlockModified =
true;
318 mBlockModified =
false;
327 mBlockModified =
true;
330 mBlockModified =
false;
337 mBlockModified =
true;
340 mBlockModified =
false;
346 if ( !mAdvancedMenu )
348 mAdvancedMenu =
new QMenu(
this );
352 return mAdvancedMenu;
365 mPreviewExpressionContext.
setFeature( mPreviewFeature );
368 QWidget *widget = stackedWidget->currentWidget();
392 parent =
static_cast<SymbolLayerItem *
>( model->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-- )
404 SymbolLayerItem *layerItem =
new SymbolLayerItem( symbol->
symbolLayer( i ) );
405 layerItem->setEditable(
false );
406 symbolItem->appendRow( layerItem );
411 layersTree->setExpanded( layerItem->index(), true );
413 layersTree->setExpanded( symbolItem->index(), true );
417 void QgsSymbolSelectorWidget::reloadSymbol()
420 loadSymbol( mSymbol, static_cast<SymbolLayerItem *>( model->invisibleRootItem() ) );
423 void QgsSymbolSelectorWidget::updateUi()
425 QModelIndex currentIdx = layersTree->currentIndex();
426 if ( !currentIdx.isValid() )
429 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( model->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 int rowCount = item->parent()->rowCount();
441 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 );
452 std::unique_ptr< QgsSymbol > symbolClone( mSymbol->
clone() );
453 QImage preview = symbolClone->bigSymbolPreviewImage( &mPreviewExpressionContext );
454 lblPreview->setPixmap( QPixmap::fromImage( preview ) );
456 if ( !mBlockModified )
463 SymbolLayerItem *item = currentLayerItem();
465 item->updatePreview();
470 SymbolLayerItem *QgsSymbolSelectorWidget::currentLayerItem()
472 QModelIndex idx = layersTree->currentIndex();
473 if ( !idx.isValid() )
476 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( model->itemFromIndex( idx ) );
477 if ( !item->isLayer() )
485 QModelIndex idx = layersTree->currentIndex();
486 if ( !idx.isValid() )
489 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( model->itemFromIndex( idx ) );
490 if ( item->isLayer() )
491 return item->layer();
500 SymbolLayerItem *currentItem =
static_cast<SymbolLayerItem *
>( model->itemFromIndex( layersTree->currentIndex() ) );
504 if ( currentItem->isLayer() )
506 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( currentItem->parent() );
507 mDataDefineRestorer.reset(
new DataDefinedRestorer( parent->symbol(), currentItem->layer() ) );
511 setWidget( layerProp );
521 mDataDefineRestorer.reset();
524 currentItem->symbol()->setLayer( mVectorLayer );
530 setWidget( symbolsList );
538 SymbolLayerItem *currentItem =
static_cast<SymbolLayerItem *
>( model->itemFromIndex( layersTree->currentIndex() ) );
539 if ( !currentItem || currentItem->isLayer() )
543 if ( currentItem->parent() )
546 QgsSymbol *symbol = currentItem->symbol();
547 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( currentItem->parent() );
548 parent->removeRow( 0 );
550 layersTree->setCurrentIndex( parent->child( 0 )->index() );
551 parent->updatePreview();
557 QModelIndex newIndex = layersTree->model()->index( 0, 0 );
558 layersTree->setCurrentIndex( newIndex );
565 void QgsSymbolSelectorWidget::setWidget( QWidget *widget )
567 int index = stackedWidget->addWidget( widget );
568 stackedWidget->setCurrentIndex( index );
569 if ( mPresentWidget )
570 mPresentWidget->deleteLater();
571 mPresentWidget = widget;
574 void QgsSymbolSelectorWidget::updateLockButton()
579 btnLock->setChecked( layer->
isLocked() );
584 QModelIndex idx = layersTree->currentIndex();
585 if ( !idx.isValid() )
589 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( model->itemFromIndex( idx ) );
590 if ( item->isLayer() )
592 insertIdx = item->row();
593 item =
static_cast<SymbolLayerItem *
>( item->parent() );
596 QgsSymbol *parentSymbol = item->symbol();
606 ?
static_cast<QgsLineSymbol *
>( parentSymbol )->dataDefinedWidth()
610 if ( insertIdx == -1 )
617 static_cast<QgsMarkerSymbol *
>( parentSymbol )->setDataDefinedSize( ddSize );
619 static_cast<QgsMarkerSymbol *
>( parentSymbol )->setDataDefinedAngle( ddAngle );
621 static_cast<QgsLineSymbol *
>( parentSymbol )->setDataDefinedWidth( ddWidth );
623 SymbolLayerItem *newLayerItem =
new SymbolLayerItem( newLayer );
624 item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem );
625 item->updatePreview();
627 layersTree->setCurrentIndex( model->indexFromItem( newLayerItem ) );
634 SymbolLayerItem *item = currentLayerItem();
635 int row = item->row();
636 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( item->parent() );
638 int layerIdx = parent->rowCount() - row - 1;
639 QgsSymbol *parentSymbol = parent->symbol();
642 parent->removeRow( row );
643 parent->updatePreview();
645 QModelIndex newIdx = parent->child( 0 )->index();
646 layersTree->setCurrentIndex( newIdx );
656 moveLayerByOffset( + 1 );
661 moveLayerByOffset( -1 );
664 void QgsSymbolSelectorWidget::moveLayerByOffset(
int offset )
666 SymbolLayerItem *item = currentLayerItem();
669 int row = item->row();
671 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( item->parent() );
672 QgsSymbol *parentSymbol = parent->symbol();
674 int layerIdx = parent->rowCount() - row - 1;
679 QList<QStandardItem *> rowItems = parent->takeRow( row );
680 parent->insertRows( row + offset, rowItems );
681 parent->updatePreview();
683 QModelIndex newIdx = rowItems[ 0 ]->index();
684 layersTree->setCurrentIndex( newIdx );
695 layer->
setLocked( btnLock->isChecked() );
701 QModelIndex idx = layersTree->currentIndex();
702 if ( !idx.isValid() )
705 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( model->itemFromIndex( idx ) );
706 if ( !item->isLayer() )
711 int insertIdx = item->row();
712 item =
static_cast<SymbolLayerItem *
>( item->parent() );
714 QgsSymbol *parentSymbol = item->symbol();
717 if ( insertIdx == -1 )
722 SymbolLayerItem *newLayerItem =
new SymbolLayerItem( newLayer );
723 item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem );
727 layersTree->setExpanded( newLayerItem->index(), true );
729 item->updatePreview();
731 layersTree->setCurrentIndex( model->indexFromItem( newLayerItem ) );
738 SymbolLayerItem *item = currentLayerItem();
743 item->removeRow( 0 );
746 item->setLayer( newLayer );
751 layersTree->setExpanded( item->index(), true );
755 QgsSymbol *symbol =
static_cast<SymbolLayerItem *
>( item->parent() )->
symbol();
756 int layerIdx = item->parent()->rowCount() - item->row() - 1;
759 item->updatePreview();
768 setLayout(
new QVBoxLayout() );
770 mButtonBox =
new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::Ok );
772 connect( mButtonBox, &QDialogButtonBox::accepted,
this, &QDialog::accept );
773 connect( mButtonBox, &QDialogButtonBox::rejected,
this, &QDialog::reject );
774 connect( mButtonBox, &QDialogButtonBox::helpRequested,
this, &QgsSymbolSelectorDialog::showHelp );
776 layout()->addWidget( mSelectorWidget );
777 layout()->addWidget( mButtonBox );
779 mSelectorWidget->setMinimumSize( 460, 560 );
780 setObjectName( QStringLiteral(
"SymbolSelectorDialog" ) );
787 layout()->setContentsMargins( 0, 0, 0, 0 );
791 setWindowTitle( tr(
"Symbol Selector" ) );
813 return mSelectorWidget->
symbol();
819 if ( !isWindow() && e->key() == Qt::Key_Escape )
825 QDialog::keyPressEvent( e );
829 void QgsSymbolSelectorDialog::reloadSymbol()
831 mSelectorWidget->reloadSymbol();
836 mSelectorWidget->
loadSymbol( symbol, parent );
839 void QgsSymbolSelectorDialog::updateUi()
841 mSelectorWidget->updateUi();
844 void QgsSymbolSelectorDialog::updateLockButton()
846 mSelectorWidget->updateLockButton();
849 SymbolLayerItem *QgsSymbolSelectorDialog::currentLayerItem()
851 return mSelectorWidget->currentLayerItem();
856 return mSelectorWidget->currentLayer();
859 void QgsSymbolSelectorDialog::moveLayerByOffset(
int offset )
861 mSelectorWidget->moveLayerByOffset( offset );
864 void QgsSymbolSelectorDialog::setWidget( QWidget *widget )
866 mSelectorWidget->setWidget( widget );
929 void QgsSymbolSelectorDialog::showHelp()
931 QgsHelp::openHelp( QStringLiteral(
"working_with_vector/style_library.html#the-symbol-selector" ) );
void duplicateLayer()
Duplicates the current symbol layer and places the duplicated layer above the current symbol layer...
bool insertSymbolLayer(int index, QgsSymbolLayer *layer)
Inserts a symbol layer to specified index.
static QgsSymbolLayerRegistry * symbolLayerRegistry()
Returns the application's symbol layer registry, used for managing symbol layers. ...
static QgsSvgCache * svgCache()
Returns the application's SVG cache, used for caching SVG images and handling parameter replacement w...
Wrapper for iterator of features from vector data provider or vector layer.
static QIcon symbolLayerPreviewIcon(const QgsSymbolLayer *layer, QgsUnitTypes::RenderUnit u, QSize size, const QgsMapUnitScale &scale=QgsMapUnitScale())
Draws a symbol layer preview to an icon.
void setLocked(bool locked)
Abstract base class for all rendered symbols.
virtual QgsSymbol * subSymbol()
Returns the symbol's sub symbol, if present.
static const double UI_SCALE_FACTOR
UI scaling factor.
bool appendSymbolLayer(QgsSymbolLayer *layer)
Appends a symbol layer at the end of the current symbol layer list.
QgsSymbolSelectorDialog(QgsSymbol *symbol, QgsStyle *style, QgsVectorLayer *vl, QWidget *parent=nullptr, bool embedded=false)
Constructor for QgsSymbolSelectorDialog.
int scaleIconSize(int standardSize)
Scales an icon size to compensate for display pixel density, making the icon size hi-dpi friendly...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
static QgsImageCache * imageCache()
Returns the application's image cache, used for caching resampled versions of raster images...
static QgsSymbolLayer * defaultSymbolLayer(QgsSymbol::SymbolType type)
create a new instance of symbol layer for specified symbol type with default settings ...
static QString iconPath(const QString &iconFile)
Returns path to the desired icon file.
static QIcon symbolPreviewIcon(const QgsSymbol *symbol, QSize size, int padding=0)
Returns an icon preview for a color ramp.
#define Q_NOWARN_DEPRECATED_PUSH
void projectColorsChanged()
Emitted whenever the project's color scheme has been changed.
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
static QgsGui * instance()
Returns a pointer to the singleton instance.
A marker symbol type, for rendering Point and MultiPoint geometries.
A line symbol type, for rendering LineString and MultiLineString geometries.
QgsSymbolWidgetContext context() const
Returns the context in which the symbol widget is shown, e.g., the associated map canvas and expressi...
QgsSymbolLayerAbstractMetadata * symbolLayerMetadata(const QString &name) const
Returns metadata for specified symbol layer. Returns nullptr if not found.
Contains settings which reflect the context in which a symbol (or renderer) widget is shown...
void updateLayerPreview()
virtual QgsSymbolLayer * clone() const =0
Shall be reimplemented by subclasses to create a deep copy of the instance.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
void symbolChanged()
Slot to update tree when a new symbol from style.
QgsSymbol::SymbolType type() const
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
A store for object properties.
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
QMenu * advancedMenu()
Returns menu for "advanced" button - create it if doesn't exist and show the advanced button...
void remoteImageFetched(const QString &url)
Emitted when the cache has finished retrieving an image file from a remote url.
#define Q_NOWARN_DEPRECATED_POP
bool changeSymbolLayer(int index, QgsSymbolLayer *layer)
Deletes the current layer at the specified index and replaces it with layer.
QgsExpressionContext * expressionContext() const
Returns the expression context used for the widget, if set.
Abstract base class for marker symbol layers.
void setContext(const QgsSymbolWidgetContext &context)
Sets the context in which the symbol widget is shown, e.g., the associated map canvas and expression ...
SymbolType type() const
Returns the symbol's type.
virtual QgsSymbol * clone() const =0
Returns a deep copy of this symbol.
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
static QgsProject * instance()
Returns the QgsProject singleton instance.
void changeLayer(QgsSymbolLayer *layer)
alters tree and sets proper widget when Layer Type is changed
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.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
QgsSymbolLayer * takeSymbolLayer(int index)
Removes a symbol layer from the list and returns a pointer to it.
void remoteSvgFetched(const QString &url)
Emitted when the cache has finished retrieving an SVG file from a remote url.
void appendScopes(const QList< QgsExpressionContextScope *> &scopes)
Appends a list of scopes to the end of the context.
QgsSymbol * symbol()
Returns the symbol that is currently active in the widget.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
bool nextFeature(QgsFeature &f)
void keyPressEvent(QKeyEvent *e) override
QDialogButtonBox * buttonBox() const
Returns a reference to the dialog's button box.
Represents a vector layer which manages a vector based data sets.
void loadSymbol(QgsSymbol *symbol, SymbolLayerItem *parent=nullptr)
Loads the given symbol into the widget.