QGIS API Documentation  2.99.0-Master (0a63d1f)
qgslayerpropertieswidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgslayerpropertieswidget.cpp
3  ----------------------------
4  begin : June 2012
5  copyright : (C) 2012 by Arunmozhi
6  email : aruntheguy at gmail.com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
17 
18 #include <QFile>
19 #include <QStandardItem>
20 #include <QKeyEvent>
21 #include <QMessageBox>
22 #include <QPicture>
23 
24 #include "qgssymbollayer.h"
25 #include "qgssymbollayerregistry.h"
26 
27 #include "qgsapplication.h"
28 #include "qgslogger.h"
29 
30 #include "qgssymbollayerwidget.h"
34 #include "qgssymbol.h" //for the unit
35 #include "qgspanelwidget.h"
36 #include "qgsdatadefined.h"
37 #include "qgsmapcanvas.h"
38 #include "qgsproject.h"
39 #include "qgsvectorlayer.h"
40 
41 static bool _initWidgetFunction( const QString& name, QgsSymbolLayerWidgetFunc f )
42 {
44 
45  QgsSymbolLayerAbstractMetadata* abstractMetadata = reg->symbolLayerMetadata( name );
46  if ( !abstractMetadata )
47  {
48  QgsDebugMsg( "Failed to find symbol layer's entry in registry: " + name );
49  return false;
50  }
51  QgsSymbolLayerMetadata* metadata = dynamic_cast<QgsSymbolLayerMetadata*>( abstractMetadata );
52  if ( !metadata )
53  {
54  QgsDebugMsg( "Failed to cast symbol layer's metadata: " + name );
55  return false;
56  }
57  metadata->setWidgetFunction( f );
58  return true;
59 }
60 
61 static void _initWidgetFunctions()
62 {
63  static bool sInitialized = false;
64  if ( sInitialized )
65  return;
66 
67  _initWidgetFunction( QStringLiteral( "SimpleLine" ), QgsSimpleLineSymbolLayerWidget::create );
68  _initWidgetFunction( QStringLiteral( "MarkerLine" ), QgsMarkerLineSymbolLayerWidget::create );
69  _initWidgetFunction( QStringLiteral( "ArrowLine" ), QgsArrowSymbolLayerWidget::create );
70 
71  _initWidgetFunction( QStringLiteral( "SimpleMarker" ), QgsSimpleMarkerSymbolLayerWidget::create );
72  _initWidgetFunction( QStringLiteral( "FilledMarker" ), QgsFilledMarkerSymbolLayerWidget::create );
73  _initWidgetFunction( QStringLiteral( "SvgMarker" ), QgsSvgMarkerSymbolLayerWidget::create );
74  _initWidgetFunction( QStringLiteral( "FontMarker" ), QgsFontMarkerSymbolLayerWidget::create );
75  _initWidgetFunction( QStringLiteral( "EllipseMarker" ), QgsEllipseSymbolLayerWidget::create );
76  _initWidgetFunction( QStringLiteral( "VectorField" ), QgsVectorFieldSymbolLayerWidget::create );
77 
78  _initWidgetFunction( QStringLiteral( "SimpleFill" ), QgsSimpleFillSymbolLayerWidget::create );
79  _initWidgetFunction( QStringLiteral( "GradientFill" ), QgsGradientFillSymbolLayerWidget::create );
80  _initWidgetFunction( QStringLiteral( "ShapeburstFill" ), QgsShapeburstFillSymbolLayerWidget::create );
81  _initWidgetFunction( QStringLiteral( "RasterFill" ), QgsRasterFillSymbolLayerWidget::create );
82  _initWidgetFunction( QStringLiteral( "SVGFill" ), QgsSVGFillSymbolLayerWidget::create );
83  _initWidgetFunction( QStringLiteral( "CentroidFill" ), QgsCentroidFillSymbolLayerWidget::create );
84  _initWidgetFunction( QStringLiteral( "LinePatternFill" ), QgsLinePatternFillSymbolLayerWidget::create );
85  _initWidgetFunction( QStringLiteral( "PointPatternFill" ), QgsPointPatternFillSymbolLayerWidget::create );
86 
87  _initWidgetFunction( QStringLiteral( "GeometryGenerator" ), QgsGeometryGeneratorSymbolLayerWidget::create );
88 
89  sInitialized = true;
90 }
91 
92 
94  : QgsPanelWidget( parent )
95  , mLayer( layer )
96  , mSymbol( symbol )
97  , mVectorLayer( vl )
98 {
99 
100  setupUi( this );
101  // initialize the sub-widgets
102  // XXX Should this thing be here this way? Initialize all the widgets just for the sake of one layer?
103  // TODO Make this on demand creation
105 
106  // TODO Algorithm
107  //
108  // 3. populate the combo box with the supported layer type
109  // 4. set the present layer type
110  // 5. create the widget for the present layer type and set inn stacked widget
111  // 6. connect comboBox type changed to two things
112  // 1. emit signal that type has beed changed
113  // 2. remove the widget and place the new widget corresponding to the changed layer type
114  //
116  // update layer type combo box
117  int idx = cboLayerType->findData( mLayer->layerType() );
118  cboLayerType->setCurrentIndex( idx );
119 
120  connect( mEnabledCheckBox, SIGNAL( toggled( bool ) ), mEnabledDDBtn, SLOT( setEnabled( bool ) ) );
121  mEnabledCheckBox->setChecked( mLayer->enabled() );
122 
123  // set the corresponding widget
124  updateSymbolLayerWidget( layer );
125  connect( cboLayerType, SIGNAL( currentIndexChanged( int ) ), this, SLOT( layerTypeChanged() ) );
126 
127  connect( mEffectWidget, SIGNAL( changed() ), this, SLOT( emitSignalChanged() ) );
128 
129  this->connectChildPanel( mEffectWidget );
130 
131  mEffectWidget->setPaintEffect( mLayer->paintEffect() );
132 
135  connect( mEnabledDDBtn, SIGNAL( dataDefinedChanged( const QString& ) ), this, SLOT( updateDataDefinedEnable() ) );
136  connect( mEnabledDDBtn, SIGNAL( dataDefinedActivated( bool ) ), this, SLOT( updateDataDefinedEnable() ) );
137  mEnabledDDBtn->registerExpressionContextGenerator( this );
138 }
139 
140 void QgsLayerPropertiesWidget::updateDataDefinedEnable()
141 {
143  if ( !dd )
144  {
145  dd = new QgsDataDefined();
147  }
148  mEnabledDDBtn->updateDataDefined( dd );
149 
150  emit changed();
151 }
152 
154 {
155  mContext = context;
156 
157  QgsSymbolLayerWidget* w = dynamic_cast< QgsSymbolLayerWidget* >( stackedWidget->currentWidget() );
158  if ( w )
159  w->setContext( mContext );
160 }
161 
163 {
164  return mContext;
165 }
166 
168 {
169  QgsPanelWidget::setDockMode( dockMode );
170  mEffectWidget->setDockMode( this->dockMode() );
171 }
172 
174 {
175  QStringList symbolLayerIds = QgsApplication::symbolLayerRegistry()->symbolLayersForType( mSymbol->type() );
176 
177  Q_FOREACH ( const QString& symbolLayerId, symbolLayerIds )
178  cboLayerType->addItem( QgsApplication::symbolLayerRegistry()->symbolLayerMetadata( symbolLayerId )->visibleName(), symbolLayerId );
179 
180  if ( mSymbol->type() == QgsSymbol::Fill )
181  {
183  Q_FOREACH ( const QString& lineLayerId, lineLayerIds )
184  {
186  if ( layerInfo->type() != QgsSymbol::Hybrid )
187  {
188  QString visibleName = layerInfo->visibleName();
189  QString name = QString( tr( "Outline: %1" ) ).arg( visibleName );
190  cboLayerType->addItem( name, lineLayerId );
191  }
192  }
193  }
194 }
195 
197 {
198  if ( stackedWidget->currentWidget() != pageDummy )
199  {
200  // stop updating from the original widget
201  disconnect( stackedWidget->currentWidget(), SIGNAL( changed() ), this, SLOT( emitSignalChanged() ) );
202  stackedWidget->removeWidget( stackedWidget->currentWidget() );
203  }
204 
206 
207  QString layerType = layer->layerType();
208  QgsSymbolLayerAbstractMetadata* am = pReg->symbolLayerMetadata( layerType );
209  if ( am )
210  {
212  if ( w )
213  {
214  w->setContext( mContext );
215  w->setSymbolLayer( layer );
216  stackedWidget->addWidget( w );
217  stackedWidget->setCurrentWidget( w );
218  // start receiving updates from widget
219  connect( w, SIGNAL( changed() ), this, SLOT( emitSignalChanged() ) );
220  connect( w, SIGNAL( symbolChanged() ), this, SLOT( reloadLayer() ) );
221  return;
222  }
223  }
224  // When anything is not right
225  stackedWidget->setCurrentWidget( pageDummy );
226 }
227 
229 {
230  if ( mContext.expressionContext() )
231  return *mContext.expressionContext();
232 
233  QgsExpressionContext expContext;
237 
238  if ( mContext.mapCanvas() )
239  {
242  }
243  else
244  {
246  }
247 
249 
251  if ( mLayer )
252  {
253  //cheat a bit - set the symbol color variable to match the symbol layer's color (when we should really be using the *symbols*
254  //color, but that's not accessible here). 99% of the time these will be the same anyway
256  }
257  expContext << symbolScope;
262 
263  // additional scopes
264  Q_FOREACH ( const QgsExpressionContextScope& scope, mContext.additionalExpressionContextScopes() )
265  {
266  expContext.appendScope( new QgsExpressionContextScope( scope ) );
267  }
268 
269  //TODO - show actual value
270  expContext.setOriginalValueVariable( QVariant() );
271 
276 
277  return expContext;
278 }
279 
281 {
282  QgsSymbolLayer* layer = mLayer;
283  if ( !layer )
284  return;
285  QString newLayerType = cboLayerType->currentData().toString();
286  if ( layer->layerType() == newLayerType )
287  return;
288 
289  // get creation function for new layer from registry
291  QgsSymbolLayerAbstractMetadata* am = pReg->symbolLayerMetadata( newLayerType );
292  if ( !am ) // check whether the metadata is assigned
293  return;
294 
295  // change layer to a new (with different type)
296  // base new layer on existing layer's properties
297  QgsSymbolLayer* newLayer = am->createSymbolLayer( layer->properties() );
298  if ( !newLayer )
299  return;
300 
301  updateSymbolLayerWidget( newLayer );
302  emit changeLayer( newLayer );
303 }
304 
306 {
307  emit changed();
308 
309  // also update paint effect preview
310  mEffectWidget->setPreviewPicture( QgsSymbolLayerUtils::symbolLayerPreviewPicture( mLayer, QgsUnitTypes::RenderMillimeters, QSize( 80, 80 ) ) );
311  emit widgetChanged();
312 }
313 
314 void QgsLayerPropertiesWidget::reloadLayer()
315 {
316  emit changeLayer( mLayer );
317 }
318 
319 void QgsLayerPropertiesWidget::on_mEnabledCheckBox_toggled( bool enabled )
320 {
321  mLayer->setEnabled( enabled );
323 }
static const QString EXPR_ORIGINAL_VALUE
Inbuilt variable name for value original value variable.
static QgsSymbolLayerRegistry * symbolLayerRegistry()
Returns the application&#39;s symbol layer registry, used for managing symbol layers. ...
static QgsExpressionContextScope * updateSymbolScope(const QgsSymbol *symbol, QgsExpressionContextScope *symbolScope=nullptr)
Updates a symbol scope related to a QgsSymbol to an expression context.
static const QString EXPR_CLUSTER_COLOR
Inbuilt variable name for cluster color variable.
static QgsSymbolLayerWidget * create(const QgsVectorLayer *vl)
Creates a new QgsFilledMarkerSymbolLayerWidget.
Single variable definition for use within a QgsExpressionContextScope.
void connectChildPanel(QgsPanelWidget *panel)
Connect the given sub panel widgets showPanel signals to this current panels main showPanel event to ...
Stores metadata about one symbol layer class.
bool dockMode()
Return the dock mode state.
A container class for data source field mapping or expression.
static const QString EXPR_GEOMETRY_POINT_COUNT
Inbuilt variable name for point count variable.
QgsPaintEffect * paintEffect() const
Returns the current paint effect for the layer.
static QgsSymbolLayerWidget * create(const QgsVectorLayer *vl)
static QgsExpressionContextScope * atlasScope(const QgsAtlasComposition *atlas)
Creates a new scope which contains variables and functions relating to a QgsAtlasComposition.
static QgsSymbolLayerWidget * create(const QgsVectorLayer *vl)
void setWidgetFunction(QgsSymbolLayerWidgetFunc f)
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
static QgsSymbolLayerWidget * create(const QgsVectorLayer *vl)
QgsSymbolWidgetContext context() const
Returns the context in which the symbol widget is shown, e.g., the associated map canvas and expressi...
QStringList symbolLayersForType(QgsSymbol::SymbolType type)
return a list of available symbol layers for a specified symbol type
virtual void setDataDefinedProperty(const QString &property, QgsDataDefined *dataDefined)
Sets a data defined property for the layer.
virtual void setDockMode(bool dockMode) override
Set the widget in dock mode which tells the widget to emit panel widgets and not open dialogs...
static QgsSymbolLayerWidget * create(const QgsVectorLayer *vl)
virtual QgsSymbolLayerWidget * createSymbolLayerWidget(const QgsVectorLayer *)
Create widget for symbol layer of this type. Can return NULL if there&#39;s no GUI.
static bool _initWidgetFunction(const QString &name, QgsSymbolLayerWidgetFunc f)
Base class for any widget that can be shown as a inline panel.
void setContext(const QgsSymbolWidgetContext &context)
Sets the context in which the symbol widget is shown, e.g., the associated map canvas and expression ...
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
Line symbol.
Definition: qgssymbol.h:70
virtual QgsStringMap properties() const =0
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
void updateSymbolLayerWidget(QgsSymbolLayer *layer)
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
static void _initWidgetFunctions()
virtual void setDockMode(bool dockMode)
Set the widget in dock mode which tells the widget to emit panel widgets and not open dialogs...
static QgsSymbolLayerWidget * create(const QgsVectorLayer *vl)
Will be registered as factory.
The QgsMapSettings class contains configuration for rendering of the map.
QgsExpressionContextScope * lastScope()
Returns the last scope added to the context.
Convenience metadata class that uses static functions to create symbol layer and its widget...
static QgsSymbolLayerWidget * create(const QgsVectorLayer *layer)
Static creation method.
virtual void setSymbolLayer(QgsSymbolLayer *layer)=0
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context...
static QgsSymbolLayerWidget * create(const QgsVectorLayer *vl)
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
static QgsSymbolLayerWidget * create(const QgsVectorLayer *vl)
QgsSymbolLayerAbstractMetadata * symbolLayerMetadata(const QString &name) const
return metadata for specified symbol layer. Returns NULL if not found
static QgsSymbolLayerWidget * create(const QgsVectorLayer *vl)
Registry of available symbol layer classes.
Contains settings which reflect the context in which a symbol (or renderer) widget is shown...
static QgsSymbolLayerWidget * create(const QgsVectorLayer *vl)
static QgsSymbolLayerWidget * create(const QgsVectorLayer *vl)
static QgsSymbolLayerWidget * create(const QgsVectorLayer *vl)
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QgsSymbolLayerWidget *(* QgsSymbolLayerWidgetFunc)(const QgsVectorLayer *)
virtual QColor color() const
The fill color.
static const QString EXPR_SYMBOL_COLOR
Inbuilt variable name for symbol color variable.
Single scope for storing variables and functions for use within a QgsExpressionContext.
void setEnabled(bool enabled)
Sets whether symbol layer is enabled and should be drawn.
void widgetChanged()
Emitted when the widget state changes.
virtual QgsSymbolLayer * createSymbolLayer(const QgsStringMap &map)=0
Create a symbol layer of this type given the map of properties.
static QgsSymbolLayerWidget * create(const QgsVectorLayer *vl)
const QgsMapSettings & mapSettings() const
Get access to properties used for map rendering.
static QgsSymbolLayerWidget * create(const QgsVectorLayer *vl)
QgsMapCanvas * mapCanvas() const
Returns the map canvas associated with the widget.
virtual QgsDataDefined * getDataDefinedProperty(const QString &property) const
Returns the data defined property corresponding to the specified property key.
QgsExpressionContext * expressionContext() const
Returns the expression context used for the widget, if set.
Fill symbol.
Definition: qgssymbol.h:71
static QgsExpressionContextScope * mapSettingsScope(const QgsMapSettings &mapSettings)
Creates a new scope which contains variables and functions relating to a QgsMapSettings object...
QgsExpressionContextScope & expressionContextScope()
Returns a reference to the expression context scope for the map canvas.
Definition: qgsmapcanvas.h:385
static QPicture symbolLayerPreviewPicture(QgsSymbolLayer *layer, QgsUnitTypes::RenderUnit units, QSize size, const QgsMapUnitScale &scale=QgsMapUnitScale())
Draws a symbol layer preview to a QPicture.
bool enabled() const
Returns true if symbol layer is enabled and will be drawn.
static QgsSymbolLayerWidget * create(const QgsVectorLayer *vl)
SymbolType type() const
Definition: qgssymbol.h:97
static QgsSymbolLayerWidget * create(const QgsVectorLayer *vl)
QgsSymbol::SymbolType type() const
static QgsSymbolLayerWidget * create(const QgsVectorLayer *vl)
QgsLayerPropertiesWidget(QgsSymbolLayer *layer, const QgsSymbol *symbol, const QgsVectorLayer *vl, QWidget *parent=nullptr)
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:350
void setContext(const QgsSymbolWidgetContext &context)
Sets the context in which the symbol widget is shown, e.g., the associated map canvas and expression ...
void changeLayer(QgsSymbolLayer *)
static const QString EXPR_CLUSTER_SIZE
Inbuilt variable name for cluster size variable.
static const QString EXPR_GEOMETRY_POINT_NUM
Inbuilt variable name for point number variable.
void setHighlightedVariables(const QStringList &variableNames)
Sets the list of variable names within the context intended to be highlighted to the user...
static const QString EXPR_LAYER_ENABLED
Data defined layer enabled string.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
static const QString EXPR_GEOMETRY_PART_NUM
Inbuilt variable name for geometry part number variable.
Represents a vector layer which manages a vector based data sets.
static const QString EXPR_GEOMETRY_PART_COUNT
Inbuilt variable name for geometry part count variable.
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for the context.
Hybrid symbol.
Definition: qgssymbol.h:72
QList< QgsExpressionContextScope > additionalExpressionContextScopes() const
Returns the list of additional expression context scopes to show as available within the layer...
const QgsVectorLayer * mVectorLayer
virtual QString layerType() const =0
Returns a string that represents this layer type.