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