42 #include <QColorDialog> 44 #include <QStandardItemModel> 45 #include <QInputDialog> 46 #include <QMessageBox> 52 #include <QStandardItem> 56 static const int SYMBOL_LAYER_ITEM_TYPE = QStandardItem::UserType + 1;
66 mDDSize = mMarker->dataDefinedSize();
67 mDDAngle = mMarker->dataDefinedAngle();
69 if ( !mDDSize && !mDDAngle )
76 mDDWidth = mLine->dataDefinedWidth();
84 void DataDefinedRestorer::save()
88 mSize = mMarkerSymbolLayer->size();
89 mAngle = mMarkerSymbolLayer->angle();
90 mMarkerOffset = mMarkerSymbolLayer->offset();
94 mWidth = mLineSymbolLayer->width();
95 mLineOffset = mLineSymbolLayer->offset();
99 void DataDefinedRestorer::restore()
104 ( mSize != mMarkerSymbolLayer->size() || mMarkerOffset != mMarkerSymbolLayer->offset() ) )
105 mMarker->setDataDefinedSize( mDDSize );
107 mAngle != mMarkerSymbolLayer->angle() )
108 mMarker->setDataDefinedAngle( mDDAngle );
113 ( mWidth != mLineSymbolLayer->width() || mLineOffset != mLineSymbolLayer->offset() ) )
114 mLine->setDataDefinedWidth( mDDWidth );
121 class SymbolLayerItem :
public QStandardItem
129 explicit SymbolLayerItem(
QgsSymbol *symbol )
152 if ( !mSize.isValid() )
155 mSize = QSize( size, size );
165 static_cast<SymbolLayerItem *
>( parent() )->updatePreview();
168 int type()
const override {
return SYMBOL_LAYER_ITEM_TYPE; }
169 bool isLayer() {
return mIsLayer; }
182 QVariant data(
int role )
const override 184 if ( role == Qt::DisplayRole || role == Qt::EditRole )
190 switch ( mSymbol->type() )
193 return QCoreApplication::translate(
"SymbolLayerItem",
"Marker",
nullptr, QCoreApplication::UnicodeUTF8 );
195 return QCoreApplication::translate(
"SymbolLayerItem",
"Fill",
nullptr, QCoreApplication::UnicodeUTF8 );
197 return QCoreApplication::translate(
"SymbolLayerItem",
"Line",
nullptr, QCoreApplication::UnicodeUTF8 );
203 else if ( role == Qt::ForegroundRole && mIsLayer )
205 QBrush brush( Qt::black, Qt::SolidPattern );
206 if ( !mLayer->enabled() )
208 brush.setColor( Qt::lightGray );
215 if ( role == Qt::CheckStateRole )
217 return QStandardItem::data( role );
236 setWindowModality( Qt::WindowModal );
243 this->layout()->setContentsMargins( 0, 0, 0, 0 );
245 layersTree->setMaximumHeight( static_cast< int >(
Qgis::UI_SCALE_FACTOR * fontMetrics().height() * 7 ) );
246 layersTree->setMinimumHeight( layersTree->maximumHeight() );
247 lblPreview->setMaximumWidth( layersTree->maximumHeight() );
255 iconLock.addFile(
QgsApplication::iconPath( QStringLiteral(
"unlocked.svg" ) ), QSize(), QIcon::Normal, QIcon::Off );
256 iconLock.addFile(
QgsApplication::iconPath( QStringLiteral(
"unlocked.svg" ) ), QSize(), QIcon::Active, QIcon::Off );
257 btnLock->setIcon( iconLock );
262 model =
new QStandardItemModel( layersTree );
264 layersTree->setModel(
model );
265 layersTree->setHeaderHidden(
true );
270 #if 0 // this is too expensive to do for many providers. TODO revisit when support for connection timeouts is complete across all providers 277 mPreviewExpressionContext.
setFeature( mPreviewFeature );
285 QItemSelectionModel *selModel = layersTree->selectionModel();
288 loadSymbol( symbol, static_cast<SymbolLayerItem *>(
model->invisibleRootItem() ) );
302 QModelIndex newIndex = layersTree->model()->index( 0, 0 );
303 layersTree->setCurrentIndex( newIndex );
314 mBlockModified =
true;
317 mBlockModified =
false;
326 mBlockModified =
true;
329 mBlockModified =
false;
336 mBlockModified =
true;
339 mBlockModified =
false;
364 mPreviewExpressionContext.
setFeature( mPreviewFeature );
367 QWidget *widget = stackedWidget->currentWidget();
387 SymbolLayerItem *symbolItem =
new SymbolLayerItem( symbol );
388 QFont boldFont = symbolItem->font();
389 boldFont.setBold(
true );
390 symbolItem->setFont( boldFont );
391 parent->appendRow( symbolItem );
394 for (
int i = count - 1; i >= 0; i-- )
396 SymbolLayerItem *layerItem =
new SymbolLayerItem( symbol->
symbolLayer( i ) );
397 layerItem->setEditable(
false );
398 symbolItem->appendRow( layerItem );
403 layersTree->setExpanded( layerItem->index(), true );
405 layersTree->setExpanded( symbolItem->index(), true );
417 QModelIndex currentIdx = layersTree->currentIndex();
418 if ( !currentIdx.isValid() )
421 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>(
model->itemFromIndex( currentIdx ) );
422 if ( !item->isLayer() )
424 btnUp->setEnabled(
false );
425 btnDown->setEnabled(
false );
426 btnRemoveLayer->setEnabled(
false );
427 btnLock->setEnabled(
false );
428 btnDuplicate->setEnabled(
false );
432 int rowCount = item->parent()->rowCount();
433 int currentRow = item->row();
435 btnUp->setEnabled( currentRow > 0 );
436 btnDown->setEnabled( currentRow < rowCount - 1 );
437 btnRemoveLayer->setEnabled( rowCount > 1 );
438 btnLock->setEnabled(
true );
439 btnDuplicate->setEnabled(
true );
444 std::unique_ptr< QgsSymbol > symbolClone(
mSymbol->
clone() );
445 QImage preview = symbolClone->bigSymbolPreviewImage( &mPreviewExpressionContext );
446 lblPreview->setPixmap( QPixmap::fromImage( preview ) );
448 if ( !mBlockModified )
457 item->updatePreview();
464 QModelIndex idx = layersTree->currentIndex();
465 if ( !idx.isValid() )
468 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>(
model->itemFromIndex( idx ) );
469 if ( !item->isLayer() )
477 QModelIndex idx = layersTree->currentIndex();
478 if ( !idx.isValid() )
481 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>(
model->itemFromIndex( idx ) );
482 if ( item->isLayer() )
483 return item->layer();
492 SymbolLayerItem *currentItem =
static_cast<SymbolLayerItem *
>(
model->itemFromIndex( layersTree->currentIndex() ) );
496 if ( currentItem->isLayer() )
498 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( currentItem->parent() );
499 mDataDefineRestorer.reset(
new DataDefinedRestorer( parent->symbol(), currentItem->layer() ) );
513 mDataDefineRestorer.reset();
530 SymbolLayerItem *currentItem =
static_cast<SymbolLayerItem *
>(
model->itemFromIndex( layersTree->currentIndex() ) );
531 if ( !currentItem || currentItem->isLayer() )
535 if ( currentItem->parent() )
538 QgsSymbol *symbol = currentItem->symbol();
539 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( currentItem->parent() );
540 parent->removeRow( 0 );
542 layersTree->setCurrentIndex( parent->child( 0 )->index() );
543 parent->updatePreview();
549 QModelIndex newIndex = layersTree->model()->index( 0, 0 );
550 layersTree->setCurrentIndex( newIndex );
559 int index = stackedWidget->addWidget( widget );
560 stackedWidget->setCurrentIndex( index );
571 btnLock->setChecked( layer->
isLocked() );
576 QModelIndex idx = layersTree->currentIndex();
577 if ( !idx.isValid() )
581 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>(
model->itemFromIndex( idx ) );
582 if ( item->isLayer() )
584 insertIdx = item->row();
585 item =
static_cast<SymbolLayerItem *
>( item->parent() );
588 QgsSymbol *parentSymbol = item->symbol();
598 ?
static_cast<QgsLineSymbol *
>( parentSymbol )->dataDefinedWidth()
602 if ( insertIdx == -1 )
609 static_cast<QgsMarkerSymbol *
>( parentSymbol )->setDataDefinedSize( ddSize );
611 static_cast<QgsMarkerSymbol *
>( parentSymbol )->setDataDefinedAngle( ddAngle );
613 static_cast<QgsLineSymbol *
>( parentSymbol )->setDataDefinedWidth( ddWidth );
615 SymbolLayerItem *newLayerItem =
new SymbolLayerItem( newLayer );
616 item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem );
617 item->updatePreview();
619 layersTree->setCurrentIndex(
model->indexFromItem( newLayerItem ) );
627 int row = item->row();
628 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( item->parent() );
630 int layerIdx = parent->rowCount() - row - 1;
631 QgsSymbol *parentSymbol = parent->symbol();
634 parent->removeRow( row );
635 parent->updatePreview();
637 QModelIndex newIdx = parent->child( 0 )->index();
638 layersTree->setCurrentIndex( newIdx );
661 int row = item->row();
663 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( item->parent() );
664 QgsSymbol *parentSymbol = parent->symbol();
666 int layerIdx = parent->rowCount() - row - 1;
671 QList<QStandardItem *> rowItems = parent->takeRow( row );
672 parent->insertRows( row + offset, rowItems );
673 parent->updatePreview();
675 QModelIndex newIdx = rowItems[ 0 ]->index();
676 layersTree->setCurrentIndex( newIdx );
687 layer->
setLocked( btnLock->isChecked() );
693 QModelIndex idx = layersTree->currentIndex();
694 if ( !idx.isValid() )
697 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>(
model->itemFromIndex( idx ) );
698 if ( !item->isLayer() )
703 int insertIdx = item->row();
704 item =
static_cast<SymbolLayerItem *
>( item->parent() );
706 QgsSymbol *parentSymbol = item->symbol();
709 if ( insertIdx == -1 )
714 SymbolLayerItem *newLayerItem =
new SymbolLayerItem( newLayer );
715 item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem );
719 layersTree->setExpanded( newLayerItem->index(), true );
721 item->updatePreview();
723 layersTree->setCurrentIndex(
model->indexFromItem( newLayerItem ) );
735 item->removeRow( 0 );
738 item->setLayer( newLayer );
743 layersTree->setExpanded( item->index(), true );
747 QgsSymbol *symbol =
static_cast<SymbolLayerItem *
>( item->parent() )->
symbol();
748 int layerIdx = item->parent()->rowCount() - item->row() - 1;
751 item->updatePreview();
760 setLayout(
new QVBoxLayout() );
762 mButtonBox =
new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::Ok );
764 connect( mButtonBox, &QDialogButtonBox::accepted,
this, &QDialog::accept );
765 connect( mButtonBox, &QDialogButtonBox::rejected,
this, &QDialog::reject );
766 connect( mButtonBox, &QDialogButtonBox::helpRequested,
this, &QgsSymbolSelectorDialog::showHelp );
768 layout()->addWidget( mSelectorWidget );
769 layout()->addWidget( mButtonBox );
772 restoreGeometry( settings.
value( QStringLiteral(
"Windows/SymbolSelectorWidget/geometry" ) ).toByteArray() );
778 layout()->setContentsMargins( 0, 0, 0, 0 );
782 setWindowTitle( tr(
"Symbol Selector" ) );
810 return mSelectorWidget->
symbol();
816 if ( !isWindow() && e->key() == Qt::Key_Escape )
822 QDialog::keyPressEvent( e );
833 mSelectorWidget->
loadSymbol( symbol, parent );
921 void QgsSymbolSelectorDialog::showHelp()
923 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)
QgsSymbolLayer * currentLayer()
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.
This class is a composition of two QSettings instances:
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.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
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.
A marker symbol type, for rendering Point and MultiPoint geometries.
A line symbol type, for rendering LineString and MultiLineString geometries.
void saveGeometry(QWidget *widget, const QString &keyName)
Save the wigget geometry into settings.
QgsSymbolWidgetContext context() const
Returns the context in which the symbol widget is shown, e.g., the associated map canvas and expressi...
bool restoreGeometry(QWidget *widget, const QString &keyName)
Restore the wigget geometry from settings.
void moveLayerByOffset(int offset)
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.
void setWidget(QWidget *widget)
A store for object properties.
QgsSymbolLayer * symbolLayer(int layer)
Returns a specific symbol layer contained in the symbol.
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
SymbolLayerItem * currentLayerItem()
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.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
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 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
~QgsSymbolSelectorDialog() override
Represents a vector layer which manages a vector based data sets.