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() );
254 iconLock.addFile(
QgsApplication::iconPath( QStringLiteral(
"unlocked.svg" ) ), QSize(), QIcon::Normal, QIcon::Off );
255 iconLock.addFile(
QgsApplication::iconPath( QStringLiteral(
"unlocked.svg" ) ), QSize(), QIcon::Active, QIcon::Off );
256 btnLock->setIcon( iconLock );
261 model =
new QStandardItemModel( layersTree );
263 layersTree->setModel(
model );
264 layersTree->setHeaderHidden(
true );
269 #if 0 // this is too expensive to do for many providers. TODO revisit when support for connection timeouts is complete across all providers 276 mPreviewExpressionContext.
setFeature( mPreviewFeature );
284 QItemSelectionModel *selModel = layersTree->selectionModel();
287 loadSymbol( symbol, static_cast<SymbolLayerItem *>(
model->invisibleRootItem() ) );
301 QModelIndex newIndex = layersTree->model()->index( 0, 0 );
302 layersTree->setCurrentIndex( newIndex );
313 mBlockModified =
true;
316 mBlockModified =
false;
325 mBlockModified =
true;
328 mBlockModified =
false;
335 mBlockModified =
true;
338 mBlockModified =
false;
363 mPreviewExpressionContext.
setFeature( mPreviewFeature );
366 QWidget *widget = stackedWidget->currentWidget();
386 SymbolLayerItem *symbolItem =
new SymbolLayerItem( symbol );
387 QFont boldFont = symbolItem->font();
388 boldFont.setBold(
true );
389 symbolItem->setFont( boldFont );
390 parent->appendRow( symbolItem );
393 for (
int i = count - 1; i >= 0; i-- )
395 SymbolLayerItem *layerItem =
new SymbolLayerItem( symbol->
symbolLayer( i ) );
396 layerItem->setEditable(
false );
397 symbolItem->appendRow( layerItem );
402 layersTree->setExpanded( layerItem->index(), true );
404 layersTree->setExpanded( symbolItem->index(), true );
416 QModelIndex currentIdx = layersTree->currentIndex();
417 if ( !currentIdx.isValid() )
420 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>(
model->itemFromIndex( currentIdx ) );
421 if ( !item->isLayer() )
423 btnUp->setEnabled(
false );
424 btnDown->setEnabled(
false );
425 btnRemoveLayer->setEnabled(
false );
426 btnLock->setEnabled(
false );
427 btnDuplicate->setEnabled(
false );
431 int rowCount = item->parent()->rowCount();
432 int currentRow = item->row();
434 btnUp->setEnabled( currentRow > 0 );
435 btnDown->setEnabled( currentRow < rowCount - 1 );
436 btnRemoveLayer->setEnabled( rowCount > 1 );
437 btnLock->setEnabled(
true );
438 btnDuplicate->setEnabled(
true );
443 std::unique_ptr< QgsSymbol > symbolClone(
mSymbol->
clone() );
444 QImage preview = symbolClone->bigSymbolPreviewImage( &mPreviewExpressionContext );
445 lblPreview->setPixmap( QPixmap::fromImage( preview ) );
447 if ( !mBlockModified )
456 item->updatePreview();
463 QModelIndex idx = layersTree->currentIndex();
464 if ( !idx.isValid() )
467 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>(
model->itemFromIndex( idx ) );
468 if ( !item->isLayer() )
476 QModelIndex idx = layersTree->currentIndex();
477 if ( !idx.isValid() )
480 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>(
model->itemFromIndex( idx ) );
481 if ( item->isLayer() )
482 return item->layer();
491 SymbolLayerItem *currentItem =
static_cast<SymbolLayerItem *
>(
model->itemFromIndex( layersTree->currentIndex() ) );
495 if ( currentItem->isLayer() )
497 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( currentItem->parent() );
498 mDataDefineRestorer.reset(
new DataDefinedRestorer( parent->symbol(), currentItem->layer() ) );
512 mDataDefineRestorer.reset();
529 SymbolLayerItem *currentItem =
static_cast<SymbolLayerItem *
>(
model->itemFromIndex( layersTree->currentIndex() ) );
530 if ( !currentItem || currentItem->isLayer() )
534 if ( currentItem->parent() )
537 QgsSymbol *symbol = currentItem->symbol();
538 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( currentItem->parent() );
539 parent->removeRow( 0 );
541 layersTree->setCurrentIndex( parent->child( 0 )->index() );
542 parent->updatePreview();
548 QModelIndex newIndex = layersTree->model()->index( 0, 0 );
549 layersTree->setCurrentIndex( newIndex );
558 int index = stackedWidget->addWidget( widget );
559 stackedWidget->setCurrentIndex( index );
570 btnLock->setChecked( layer->
isLocked() );
575 QModelIndex idx = layersTree->currentIndex();
576 if ( !idx.isValid() )
580 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>(
model->itemFromIndex( idx ) );
581 if ( item->isLayer() )
583 insertIdx = item->row();
584 item =
static_cast<SymbolLayerItem *
>( item->parent() );
587 QgsSymbol *parentSymbol = item->symbol();
597 ?
static_cast<QgsLineSymbol *
>( parentSymbol )->dataDefinedWidth()
601 if ( insertIdx == -1 )
608 static_cast<QgsMarkerSymbol *
>( parentSymbol )->setDataDefinedSize( ddSize );
610 static_cast<QgsMarkerSymbol *
>( parentSymbol )->setDataDefinedAngle( ddAngle );
612 static_cast<QgsLineSymbol *
>( parentSymbol )->setDataDefinedWidth( ddWidth );
614 SymbolLayerItem *newLayerItem =
new SymbolLayerItem( newLayer );
615 item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem );
616 item->updatePreview();
618 layersTree->setCurrentIndex(
model->indexFromItem( newLayerItem ) );
626 int row = item->row();
627 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( item->parent() );
629 int layerIdx = parent->rowCount() - row - 1;
630 QgsSymbol *parentSymbol = parent->symbol();
633 parent->removeRow( row );
634 parent->updatePreview();
636 QModelIndex newIdx = parent->child( 0 )->index();
637 layersTree->setCurrentIndex( newIdx );
660 int row = item->row();
662 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( item->parent() );
663 QgsSymbol *parentSymbol = parent->symbol();
665 int layerIdx = parent->rowCount() - row - 1;
670 QList<QStandardItem *> rowItems = parent->takeRow( row );
671 parent->insertRows( row + offset, rowItems );
672 parent->updatePreview();
674 QModelIndex newIdx = rowItems[ 0 ]->index();
675 layersTree->setCurrentIndex( newIdx );
686 layer->
setLocked( btnLock->isChecked() );
692 QModelIndex idx = layersTree->currentIndex();
693 if ( !idx.isValid() )
696 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>(
model->itemFromIndex( idx ) );
697 if ( !item->isLayer() )
702 int insertIdx = item->row();
703 item =
static_cast<SymbolLayerItem *
>( item->parent() );
705 QgsSymbol *parentSymbol = item->symbol();
708 if ( insertIdx == -1 )
713 SymbolLayerItem *newLayerItem =
new SymbolLayerItem( newLayer );
714 item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem );
718 layersTree->setExpanded( newLayerItem->index(), true );
720 item->updatePreview();
722 layersTree->setCurrentIndex(
model->indexFromItem( newLayerItem ) );
734 item->removeRow( 0 );
737 item->setLayer( newLayer );
742 layersTree->setExpanded( item->index(), true );
746 QgsSymbol *symbol =
static_cast<SymbolLayerItem *
>( item->parent() )->
symbol();
747 int layerIdx = item->parent()->rowCount() - item->row() - 1;
750 item->updatePreview();
759 setLayout(
new QVBoxLayout() );
761 mButtonBox =
new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::Ok );
763 connect( mButtonBox, &QDialogButtonBox::accepted,
this, &QDialog::accept );
764 connect( mButtonBox, &QDialogButtonBox::rejected,
this, &QDialog::reject );
765 connect( mButtonBox, &QDialogButtonBox::helpRequested,
this, &QgsSymbolSelectorDialog::showHelp );
767 layout()->addWidget( mSelectorWidget );
768 layout()->addWidget( mButtonBox );
771 restoreGeometry( settings.
value( QStringLiteral(
"Windows/SymbolSelectorWidget/geometry" ) ).toByteArray() );
777 layout()->setContentsMargins( 0, 0, 0, 0 );
781 setWindowTitle( tr(
"Symbol Selector" ) );
809 return mSelectorWidget->
symbol();
815 if ( !isWindow() && e->key() == Qt::Key_Escape )
821 QDialog::keyPressEvent( e );
832 mSelectorWidget->
loadSymbol( symbol, parent );
920 void QgsSymbolSelectorDialog::showHelp()
922 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 NULL 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
Query 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.