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 );
165 if (
auto *lParent = parent() )
166 static_cast<SymbolLayerItem *
>( lParent )->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 );
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 );
331 if ( !mAdvancedMenu )
333 mAdvancedMenu =
new QMenu(
this );
337 return mAdvancedMenu;
346 mPreviewExpressionContext = *lExpressionContext;
350 mPreviewExpressionContext.
setFeature( mPreviewFeature );
353 QWidget *widget = stackedWidget->currentWidget();
380 parent =
static_cast<SymbolLayerItem *
>( model->invisibleRootItem() );
383 SymbolLayerItem *symbolItem =
new SymbolLayerItem(
symbol );
384 QFont boldFont = symbolItem->font();
385 boldFont.setBold(
true );
386 symbolItem->setFont( boldFont );
387 parent->appendRow( symbolItem );
390 for (
int i = count - 1; i >= 0; i-- )
393 layerItem->setEditable(
false );
394 symbolItem->appendRow( layerItem );
399 layersTree->setExpanded( layerItem->index(),
true );
401 layersTree->setExpanded( symbolItem->index(),
true );
405 void QgsSymbolSelectorWidget::reloadSymbol()
408 loadSymbol( mSymbol,
static_cast<SymbolLayerItem *
>( model->invisibleRootItem() ) );
411 void QgsSymbolSelectorWidget::updateUi()
413 QModelIndex currentIdx = layersTree->currentIndex();
414 if ( !currentIdx.isValid() )
417 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( model->itemFromIndex( currentIdx ) );
418 if ( !item->isLayer() )
420 btnUp->setEnabled(
false );
421 btnDown->setEnabled(
false );
422 btnRemoveLayer->setEnabled(
false );
423 btnLock->setEnabled(
false );
424 btnDuplicate->setEnabled(
false );
428 int rowCount = item->parent()->rowCount();
429 int currentRow = item->row();
431 btnUp->setEnabled( currentRow > 0 );
432 btnDown->setEnabled( currentRow < rowCount - 1 );
433 btnRemoveLayer->setEnabled( rowCount > 1 );
434 btnLock->setEnabled(
true );
435 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 )
454 SymbolLayerItem *item = currentLayerItem();
456 item->updatePreview();
461 SymbolLayerItem *QgsSymbolSelectorWidget::currentLayerItem()
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() ) );
502 setWidget( layerProp );
512 mDataDefineRestorer.reset();
515 currentItem->symbol()->setLayer( mVectorLayer );
519 symbolsList->setContext( mContext );
521 setWidget( symbolsList );
529 SymbolLayerItem *currentItem =
static_cast<SymbolLayerItem *
>( model->itemFromIndex( layersTree->currentIndex() ) );
530 if ( !currentItem || currentItem->isLayer() )
534 if ( currentItem->parent() )
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 );
556 void QgsSymbolSelectorWidget::setWidget( QWidget *widget )
558 int index = stackedWidget->addWidget( widget );
559 stackedWidget->setCurrentIndex( index );
560 if ( mPresentWidget )
561 mPresentWidget->deleteLater();
562 mPresentWidget = widget;
565 void QgsSymbolSelectorWidget::updateLockButton()
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();
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 ) );
625 SymbolLayerItem *item = currentLayerItem();
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 );
647 moveLayerByOffset( + 1 );
652 moveLayerByOffset( -1 );
655 void QgsSymbolSelectorWidget::moveLayerByOffset(
int offset )
657 SymbolLayerItem *item = currentLayerItem();
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 ) );
729 SymbolLayerItem *item = currentLayerItem();
734 item->removeRow( 0 );
737 item->setLayer( newLayer );
742 layersTree->setExpanded( item->index(),
true );
747 int layerIdx = item->parent()->rowCount() - item->row() - 1;
750 item->updatePreview();
759 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 );
773 mSelectorWidget->setMinimumSize( 460, 560 );
774 setObjectName( QStringLiteral(
"SymbolSelectorDialog" ) );
781 layout()->setContentsMargins( 0, 0, 0, 0 );
785 setWindowTitle( tr(
"Symbol Selector" ) );
807 return mSelectorWidget->
symbol();
813 if ( !isWindow() && e->key() == Qt::Key_Escape )
819 QDialog::keyPressEvent( e );
823 void QgsSymbolSelectorDialog::reloadSymbol()
825 mSelectorWidget->reloadSymbol();
833 void QgsSymbolSelectorDialog::updateUi()
835 mSelectorWidget->updateUi();
838 void QgsSymbolSelectorDialog::updateLockButton()
840 mSelectorWidget->updateLockButton();
843 SymbolLayerItem *QgsSymbolSelectorDialog::currentLayerItem()
845 return mSelectorWidget->currentLayerItem();
850 return mSelectorWidget->currentLayer();
853 void QgsSymbolSelectorDialog::moveLayerByOffset(
int offset )
855 mSelectorWidget->moveLayerByOffset( offset );
858 void QgsSymbolSelectorDialog::setWidget( QWidget *widget )
860 mSelectorWidget->setWidget( widget );
923 void QgsSymbolSelectorDialog::showHelp()
928 void QgsSymbolSelectorWidget::projectDataChanged()
930 mBlockModified =
true;
933 mBlockModified =
false;
936 void QgsSymbolSelectorWidget::layersAboutToBeRemoved(
const QList<QgsMapLayer *> &layers )
938 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 QgsGui * instance()
Returns a pointer to the singleton instance.
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).
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.
static QgsSymbolLayer * defaultSymbolLayer(QgsSymbol::SymbolType type)
create a new instance of symbol layer for specified symbol type with default settings
QgsSymbolLayerAbstractMetadata * symbolLayerMetadata(const QString &name) const
Returns metadata for specified symbol layer. Returns nullptr if not found.
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())
Draws a symbol layer preview to an icon.
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.
QgsSymbol::SymbolType type() const
void setLocked(bool 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.
SymbolType type() const
Returns the symbol's type.
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.
virtual QgsSymbol * clone() const =0
Returns a deep copy of this symbol.
@ 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