34 #include "qgssettings.h"
46 #include <QColorDialog>
48 #include <QStandardItemModel>
49 #include <QInputDialog>
50 #include <QMessageBox>
56 #include <QStandardItem>
60 static const int SYMBOL_LAYER_ITEM_TYPE = QStandardItem::UserType + 1;
70 mDDSize = mMarker->dataDefinedSize();
71 mDDAngle = mMarker->dataDefinedAngle();
73 if ( !mDDSize && !mDDAngle )
80 mDDWidth = mLine->dataDefinedWidth();
88 void DataDefinedRestorer::save()
92 mSize = mMarkerSymbolLayer->size();
93 mAngle = mMarkerSymbolLayer->angle();
94 mMarkerOffset = mMarkerSymbolLayer->offset();
98 mWidth = mLineSymbolLayer->width();
99 mLineOffset = mLineSymbolLayer->offset();
103 void DataDefinedRestorer::restore()
108 ( mSize != mMarkerSymbolLayer->size() || mMarkerOffset != mMarkerSymbolLayer->offset() ) )
109 mMarker->setDataDefinedSize( mDDSize );
111 mAngle != mMarkerSymbolLayer->angle() )
112 mMarker->setDataDefinedAngle( mDDAngle );
117 ( mWidth != mLineSymbolLayer->width() || mLineOffset != mLineSymbolLayer->offset() ) )
118 mLine->setDataDefinedWidth( mDDWidth );
125 class SymbolLayerItem :
public QStandardItem
133 explicit SymbolLayerItem(
QgsSymbol *symbol )
156 if ( !mSize.isValid() )
159 mSize = QSize( size, size );
168 if (
auto *lParent = parent() )
169 static_cast<SymbolLayerItem *
>( lParent )->updatePreview();
172 int type()
const override {
return SYMBOL_LAYER_ITEM_TYPE; }
173 bool isLayer() {
return mIsLayer; }
186 QVariant data(
int role )
const override
188 if ( role == Qt::DisplayRole || role == Qt::EditRole )
194 switch ( mSymbol->type() )
197 return QCoreApplication::translate(
"SymbolLayerItem",
"Marker" );
199 return QCoreApplication::translate(
"SymbolLayerItem",
"Fill" );
201 return QCoreApplication::translate(
"SymbolLayerItem",
"Line" );
207 else if ( role == Qt::ForegroundRole && mIsLayer )
209 QBrush brush( Qt::black, Qt::SolidPattern );
210 if ( !mLayer->enabled() )
212 brush.setColor( Qt::lightGray );
219 if ( role == Qt::CheckStateRole )
221 return QStandardItem::data( role );
242 setWindowModality( Qt::WindowModal );
246 this->layout()->setContentsMargins( 0, 0, 0, 0 );
248 layersTree->setMaximumHeight(
static_cast< int >(
Qgis::UI_SCALE_FACTOR * fontMetrics().height() * 7 ) );
249 layersTree->setMinimumHeight( layersTree->maximumHeight() );
250 lblPreview->setMaximumWidth( layersTree->maximumHeight() );
258 iconLock.addFile(
QgsApplication::iconPath( QStringLiteral(
"unlocked.svg" ) ), QSize(), QIcon::Normal, QIcon::Off );
259 iconLock.addFile(
QgsApplication::iconPath( QStringLiteral(
"unlocked.svg" ) ), QSize(), QIcon::Active, QIcon::Off );
260 btnLock->setIcon( iconLock );
265 mSymbolLayersModel =
new QStandardItemModel( layersTree );
267 layersTree->setModel( mSymbolLayersModel );
268 layersTree->setHeaderHidden(
true );
280 mPreviewExpressionContext.
setFeature( mPreviewFeature );
288 QItemSelectionModel *selModel = layersTree->selectionModel();
291 loadSymbol( mSymbol,
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->invisibleRootItem() ) );
305 QModelIndex newIndex = layersTree->model()->index( 0, 0 );
306 layersTree->setCurrentIndex( newIndex );
333 if ( !mAdvancedMenu )
335 mAdvancedMenu =
new QMenu(
this );
339 return mAdvancedMenu;
348 mPreviewExpressionContext = *lExpressionContext;
352 mPreviewExpressionContext.
setFeature( mPreviewFeature );
355 QWidget *widget = stackedWidget->currentWidget();
357 layerProp->setContext(
context );
359 listWidget->setContext(
context );
378 mSymbolLayersModel->clear();
379 parent =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->invisibleRootItem() );
382 SymbolLayerItem *symbolItem =
new SymbolLayerItem(
symbol );
383 QFont boldFont = symbolItem->font();
384 boldFont.setBold(
true );
385 symbolItem->setFont( boldFont );
386 parent->appendRow( symbolItem );
389 for (
int i = count - 1; i >= 0; i-- )
392 layerItem->setEditable(
false );
393 symbolItem->appendRow( layerItem );
398 layersTree->setExpanded( layerItem->index(),
true );
400 layersTree->setExpanded( symbolItem->index(),
true );
402 if ( mSymbol ==
symbol && !layersTree->currentIndex().isValid() )
405 layersTree->setCurrentIndex( symbolItem->index() );
409 void QgsSymbolSelectorWidget::reloadSymbol()
411 mSymbolLayersModel->clear();
412 loadSymbol( mSymbol,
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->invisibleRootItem() ) );
415 void QgsSymbolSelectorWidget::updateUi()
417 QModelIndex currentIdx = layersTree->currentIndex();
418 if ( !currentIdx.isValid() )
421 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->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 );
447 std::unique_ptr< QgsSymbol > symbolClone( mSymbol->
clone() );
448 QImage preview = symbolClone->bigSymbolPreviewImage( &mPreviewExpressionContext, Qgis::SymbolPreviewFlags() );
449 lblPreview->setPixmap( QPixmap::fromImage( preview ) );
451 if ( !mBlockModified )
458 SymbolLayerItem *item = currentLayerItem();
460 item->updatePreview();
465 SymbolLayerItem *QgsSymbolSelectorWidget::currentLayerItem()
467 QModelIndex idx = layersTree->currentIndex();
468 if ( !idx.isValid() )
471 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( idx ) );
472 if ( !item->isLayer() )
480 QModelIndex idx = layersTree->currentIndex();
481 if ( !idx.isValid() )
484 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( idx ) );
485 if ( item->isLayer() )
486 return item->layer();
495 SymbolLayerItem *currentItem =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( layersTree->currentIndex() ) );
499 if ( currentItem->isLayer() )
501 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( currentItem->parent() );
502 mDataDefineRestorer.reset(
new DataDefinedRestorer( parent->symbol(), currentItem->layer() ) );
506 setWidget( layerProp );
517 mDataDefineRestorer.reset();
519 currentItem->symbol()->setLayer( mVectorLayer );
523 symbolsList->setContext( mContext );
525 setWidget( symbolsList );
533 SymbolLayerItem *currentItem =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( layersTree->currentIndex() ) );
534 if ( !currentItem || currentItem->isLayer() )
538 if ( currentItem->parent() )
542 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( currentItem->parent() );
543 parent->removeRow( 0 );
545 layersTree->setCurrentIndex( parent->child( 0 )->index() );
546 parent->updatePreview();
552 QModelIndex newIndex = layersTree->model()->index( 0, 0 );
553 layersTree->setCurrentIndex( newIndex );
560 void QgsSymbolSelectorWidget::setWidget( QWidget *widget )
562 int index = stackedWidget->addWidget( widget );
563 stackedWidget->setCurrentIndex( index );
564 if ( mPresentWidget )
565 mPresentWidget->deleteLater();
566 mPresentWidget = widget;
569 void QgsSymbolSelectorWidget::updateLockButton()
574 btnLock->setChecked( layer->
isLocked() );
579 QModelIndex idx = layersTree->currentIndex();
580 if ( !idx.isValid() )
584 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( idx ) );
585 if ( item->isLayer() )
587 insertIdx = item->row();
588 item =
static_cast<SymbolLayerItem *
>( item->parent() );
591 QgsSymbol *parentSymbol = item->symbol();
605 if ( insertIdx == -1 )
612 static_cast<QgsMarkerSymbol *
>( parentSymbol )->setDataDefinedSize( ddSize );
614 static_cast<QgsMarkerSymbol *
>( parentSymbol )->setDataDefinedAngle( ddAngle );
616 static_cast<QgsLineSymbol *
>( parentSymbol )->setDataDefinedWidth( ddWidth );
618 SymbolLayerItem *newLayerItem =
new SymbolLayerItem( newLayer );
619 item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem );
620 item->updatePreview();
622 layersTree->setCurrentIndex( mSymbolLayersModel->indexFromItem( newLayerItem ) );
629 SymbolLayerItem *item = currentLayerItem();
630 int row = item->row();
631 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( item->parent() );
633 int layerIdx = parent->rowCount() - row - 1;
634 QgsSymbol *parentSymbol = parent->symbol();
637 parent->removeRow( row );
638 parent->updatePreview();
640 QModelIndex newIdx = parent->child( 0 )->index();
641 layersTree->setCurrentIndex( newIdx );
651 moveLayerByOffset( + 1 );
656 moveLayerByOffset( -1 );
659 void QgsSymbolSelectorWidget::moveLayerByOffset(
int offset )
661 SymbolLayerItem *item = currentLayerItem();
664 int row = item->row();
666 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( item->parent() );
667 QgsSymbol *parentSymbol = parent->symbol();
669 int layerIdx = parent->rowCount() - row - 1;
674 QList<QStandardItem *> rowItems = parent->takeRow( row );
675 parent->insertRows( row + offset, rowItems );
676 parent->updatePreview();
678 QModelIndex newIdx = rowItems[ 0 ]->index();
679 layersTree->setCurrentIndex( newIdx );
690 layer->
setLocked( btnLock->isChecked() );
696 QModelIndex idx = layersTree->currentIndex();
697 if ( !idx.isValid() )
700 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( idx ) );
701 if ( !item->isLayer() )
706 int insertIdx = item->row();
707 item =
static_cast<SymbolLayerItem *
>( item->parent() );
709 QgsSymbol *parentSymbol = item->symbol();
712 if ( insertIdx == -1 )
717 SymbolLayerItem *newLayerItem =
new SymbolLayerItem( newLayer );
718 item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem );
722 layersTree->setExpanded( newLayerItem->index(),
true );
724 item->updatePreview();
726 layersTree->setCurrentIndex( mSymbolLayersModel->indexFromItem( newLayerItem ) );
733 SymbolLayerItem *item = currentLayerItem();
738 item->removeRow( 0 );
741 item->setLayer( newLayer );
746 layersTree->setExpanded( item->index(),
true );
751 int layerIdx = item->parent()->rowCount() - item->row() - 1;
754 item->updatePreview();
763 setLayout(
new QVBoxLayout() );
766 mButtonBox =
new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::Ok );
768 connect( mButtonBox, &QDialogButtonBox::accepted,
this, &QDialog::accept );
769 connect( mButtonBox, &QDialogButtonBox::rejected,
this, &QDialog::reject );
770 connect( mButtonBox, &QDialogButtonBox::helpRequested,
this, &QgsSymbolSelectorDialog::showHelp );
772 layout()->addWidget( mSelectorWidget );
773 layout()->addWidget( mButtonBox );
777 mSelectorWidget->setMinimumSize( 460, 560 );
778 setObjectName( QStringLiteral(
"SymbolSelectorDialog" ) );
785 layout()->setContentsMargins( 0, 0, 0, 0 );
789 setWindowTitle( tr(
"Symbol Selector" ) );
811 return mSelectorWidget->
symbol();
817 if ( !isWindow() && e->key() == Qt::Key_Escape )
823 QDialog::keyPressEvent( e );
827 void QgsSymbolSelectorDialog::reloadSymbol()
829 mSelectorWidget->reloadSymbol();
837 void QgsSymbolSelectorDialog::updateUi()
839 mSelectorWidget->updateUi();
842 void QgsSymbolSelectorDialog::updateLockButton()
844 mSelectorWidget->updateLockButton();
847 SymbolLayerItem *QgsSymbolSelectorDialog::currentLayerItem()
849 return mSelectorWidget->currentLayerItem();
854 return mSelectorWidget->currentLayer();
857 void QgsSymbolSelectorDialog::moveLayerByOffset(
int offset )
859 mSelectorWidget->moveLayerByOffset( offset );
862 void QgsSymbolSelectorDialog::setWidget( QWidget *widget )
864 mSelectorWidget->setWidget( widget );
927 void QgsSymbolSelectorDialog::showHelp()
932 void QgsSymbolSelectorWidget::projectDataChanged()
934 mBlockModified =
true;
937 mBlockModified =
false;
940 void QgsSymbolSelectorWidget::layersAboutToBeRemoved(
const QList<QgsMapLayer *> &layers )
942 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.
QgsSymbolLayerAbstractMetadata * symbolLayerMetadata(const QString &name) const
Returns metadata for specified symbol layer. Returns nullptr if not found.
static QgsSymbolLayer * defaultSymbolLayer(Qgis::SymbolType type)
create a new instance of symbol layer for specified symbol type with default settings
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.
Qgis::SymbolType type() const
bool isLocked() const
Returns true if the symbol layer colors are locked and the layer will ignore any symbol-level color c...
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.
void setLocked(bool locked)
Sets whether the layer's colors are 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.
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.
Qgis::SymbolType type() const
Returns the symbol's type.
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