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" );
196 return QCoreApplication::translate(
"SymbolLayerItem",
"Fill" );
198 return QCoreApplication::translate(
"SymbolLayerItem",
"Line" );
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();
395 parent =
static_cast<SymbolLayerItem *
>( model->invisibleRootItem() );
398 SymbolLayerItem *symbolItem =
new SymbolLayerItem( symbol );
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-- )
407 SymbolLayerItem *layerItem =
new SymbolLayerItem( symbol->
symbolLayer( i ) );
408 layerItem->setEditable(
false );
409 symbolItem->appendRow( layerItem );
414 layersTree->setExpanded( layerItem->index(), true );
416 layersTree->setExpanded( symbolItem->index(), true );
420 void QgsSymbolSelectorWidget::reloadSymbol()
423 loadSymbol( mSymbol, static_cast<SymbolLayerItem *>( model->invisibleRootItem() ) );
426 void QgsSymbolSelectorWidget::updateUi()
428 QModelIndex currentIdx = layersTree->currentIndex();
429 if ( !currentIdx.isValid() )
432 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( model->itemFromIndex( currentIdx ) );
433 if ( !item->isLayer() )
435 btnUp->setEnabled(
false );
436 btnDown->setEnabled(
false );
437 btnRemoveLayer->setEnabled(
false );
438 btnLock->setEnabled(
false );
439 btnDuplicate->setEnabled(
false );
443 int rowCount = item->parent()->rowCount();
444 int currentRow = item->row();
446 btnUp->setEnabled( currentRow > 0 );
447 btnDown->setEnabled( currentRow < rowCount - 1 );
448 btnRemoveLayer->setEnabled( rowCount > 1 );
449 btnLock->setEnabled(
true );
450 btnDuplicate->setEnabled(
true );
458 std::unique_ptr< QgsSymbol > symbolClone( mSymbol->
clone() );
459 QImage preview = symbolClone->bigSymbolPreviewImage( &mPreviewExpressionContext );
460 lblPreview->setPixmap( QPixmap::fromImage( preview ) );
462 if ( !mBlockModified )
469 SymbolLayerItem *item = currentLayerItem();
471 item->updatePreview();
476 SymbolLayerItem *QgsSymbolSelectorWidget::currentLayerItem()
478 QModelIndex idx = layersTree->currentIndex();
479 if ( !idx.isValid() )
482 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( model->itemFromIndex( idx ) );
483 if ( !item->isLayer() )
491 QModelIndex idx = layersTree->currentIndex();
492 if ( !idx.isValid() )
495 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( model->itemFromIndex( idx ) );
496 if ( item->isLayer() )
497 return item->layer();
506 SymbolLayerItem *currentItem =
static_cast<SymbolLayerItem *
>( model->itemFromIndex( layersTree->currentIndex() ) );
510 if ( currentItem->isLayer() )
512 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( currentItem->parent() );
513 mDataDefineRestorer.reset(
new DataDefinedRestorer( parent->symbol(), currentItem->layer() ) );
517 setWidget( layerProp );
527 mDataDefineRestorer.reset();
530 currentItem->symbol()->setLayer( mVectorLayer );
536 setWidget( symbolsList );
544 SymbolLayerItem *currentItem =
static_cast<SymbolLayerItem *
>( model->itemFromIndex( layersTree->currentIndex() ) );
545 if ( !currentItem || currentItem->isLayer() )
549 if ( currentItem->parent() )
552 QgsSymbol *symbol = currentItem->symbol();
553 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( currentItem->parent() );
554 parent->removeRow( 0 );
556 layersTree->setCurrentIndex( parent->child( 0 )->index() );
557 parent->updatePreview();
563 QModelIndex newIndex = layersTree->model()->index( 0, 0 );
564 layersTree->setCurrentIndex( newIndex );
571 void QgsSymbolSelectorWidget::setWidget( QWidget *widget )
573 int index = stackedWidget->addWidget( widget );
574 stackedWidget->setCurrentIndex( index );
575 if ( mPresentWidget )
576 mPresentWidget->deleteLater();
577 mPresentWidget = widget;
580 void QgsSymbolSelectorWidget::updateLockButton()
585 btnLock->setChecked( layer->
isLocked() );
590 QModelIndex idx = layersTree->currentIndex();
591 if ( !idx.isValid() )
595 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( model->itemFromIndex( idx ) );
596 if ( item->isLayer() )
598 insertIdx = item->row();
599 item =
static_cast<SymbolLayerItem *
>( item->parent() );
602 QgsSymbol *parentSymbol = item->symbol();
612 ?
static_cast<QgsLineSymbol *
>( parentSymbol )->dataDefinedWidth()
616 if ( insertIdx == -1 )
623 static_cast<QgsMarkerSymbol *
>( parentSymbol )->setDataDefinedSize( ddSize );
625 static_cast<QgsMarkerSymbol *
>( parentSymbol )->setDataDefinedAngle( ddAngle );
627 static_cast<QgsLineSymbol *
>( parentSymbol )->setDataDefinedWidth( ddWidth );
629 SymbolLayerItem *newLayerItem =
new SymbolLayerItem( newLayer );
630 item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem );
631 item->updatePreview();
633 layersTree->setCurrentIndex( model->indexFromItem( newLayerItem ) );
640 SymbolLayerItem *item = currentLayerItem();
641 int row = item->row();
642 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( item->parent() );
644 int layerIdx = parent->rowCount() - row - 1;
645 QgsSymbol *parentSymbol = parent->symbol();
648 parent->removeRow( row );
649 parent->updatePreview();
651 QModelIndex newIdx = parent->child( 0 )->index();
652 layersTree->setCurrentIndex( newIdx );
662 moveLayerByOffset( + 1 );
667 moveLayerByOffset( -1 );
670 void QgsSymbolSelectorWidget::moveLayerByOffset(
int offset )
672 SymbolLayerItem *item = currentLayerItem();
675 int row = item->row();
677 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( item->parent() );
678 QgsSymbol *parentSymbol = parent->symbol();
680 int layerIdx = parent->rowCount() - row - 1;
685 QList<QStandardItem *> rowItems = parent->takeRow( row );
686 parent->insertRows( row + offset, rowItems );
687 parent->updatePreview();
689 QModelIndex newIdx = rowItems[ 0 ]->index();
690 layersTree->setCurrentIndex( newIdx );
701 layer->
setLocked( btnLock->isChecked() );
707 QModelIndex idx = layersTree->currentIndex();
708 if ( !idx.isValid() )
711 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( model->itemFromIndex( idx ) );
712 if ( !item->isLayer() )
717 int insertIdx = item->row();
718 item =
static_cast<SymbolLayerItem *
>( item->parent() );
720 QgsSymbol *parentSymbol = item->symbol();
723 if ( insertIdx == -1 )
728 SymbolLayerItem *newLayerItem =
new SymbolLayerItem( newLayer );
729 item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem );
733 layersTree->setExpanded( newLayerItem->index(), true );
735 item->updatePreview();
737 layersTree->setCurrentIndex( model->indexFromItem( newLayerItem ) );
744 SymbolLayerItem *item = currentLayerItem();
749 item->removeRow( 0 );
752 item->setLayer( newLayer );
757 layersTree->setExpanded( item->index(), true );
761 QgsSymbol *symbol =
static_cast<SymbolLayerItem *
>( item->parent() )->
symbol();
762 int layerIdx = item->parent()->rowCount() - item->row() - 1;
765 item->updatePreview();
774 setLayout(
new QVBoxLayout() );
776 mButtonBox =
new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::Ok );
778 connect( mButtonBox, &QDialogButtonBox::accepted,
this, &QDialog::accept );
779 connect( mButtonBox, &QDialogButtonBox::rejected,
this, &QDialog::reject );
780 connect( mButtonBox, &QDialogButtonBox::helpRequested,
this, &QgsSymbolSelectorDialog::showHelp );
782 layout()->addWidget( mSelectorWidget );
783 layout()->addWidget( mButtonBox );
787 mSelectorWidget->setMinimumSize( 460, 560 );
788 setObjectName( QStringLiteral(
"SymbolSelectorDialog" ) );
795 layout()->setContentsMargins( 0, 0, 0, 0 );
799 setWindowTitle( tr(
"Symbol Selector" ) );
821 return mSelectorWidget->
symbol();
827 if ( !isWindow() && e->key() == Qt::Key_Escape )
833 QDialog::keyPressEvent( e );
837 void QgsSymbolSelectorDialog::reloadSymbol()
839 mSelectorWidget->reloadSymbol();
844 mSelectorWidget->
loadSymbol( symbol, parent );
847 void QgsSymbolSelectorDialog::updateUi()
849 mSelectorWidget->updateUi();
852 void QgsSymbolSelectorDialog::updateLockButton()
854 mSelectorWidget->updateLockButton();
857 SymbolLayerItem *QgsSymbolSelectorDialog::currentLayerItem()
859 return mSelectorWidget->currentLayerItem();
864 return mSelectorWidget->currentLayer();
867 void QgsSymbolSelectorDialog::moveLayerByOffset(
int offset )
869 mSelectorWidget->moveLayerByOffset( offset );
872 void QgsSymbolSelectorDialog::setWidget( QWidget *widget )
874 mSelectorWidget->setWidget( widget );
937 void QgsSymbolSelectorDialog::showHelp()
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.