QGIS API Documentation  2.99.0-Master (d55fa22)
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 "qgsmapcanvas.h"
37 #include "qgsproject.h"
38 #include "qgsvectorlayer.h"
39 
40 static bool _initWidgetFunction( const QString &name, QgsSymbolLayerWidgetFunc f )
41 {
43 
44  QgsSymbolLayerAbstractMetadata *abstractMetadata = reg->symbolLayerMetadata( name );
45  if ( !abstractMetadata )
46  {
47  QgsDebugMsg( "Failed to find symbol layer's entry in registry: " + name );
48  return false;
49  }
50  QgsSymbolLayerMetadata *metadata = dynamic_cast<QgsSymbolLayerMetadata *>( abstractMetadata );
51  if ( !metadata )
52  {
53  QgsDebugMsg( "Failed to cast symbol layer's metadata: " + name );
54  return false;
55  }
56  metadata->setWidgetFunction( f );
57  return true;
58 }
59 
60 static void _initWidgetFunctions()
61 {
62  static bool sInitialized = false;
63  if ( sInitialized )
64  return;
65 
66  _initWidgetFunction( QStringLiteral( "SimpleLine" ), QgsSimpleLineSymbolLayerWidget::create );
67  _initWidgetFunction( QStringLiteral( "MarkerLine" ), QgsMarkerLineSymbolLayerWidget::create );
68  _initWidgetFunction( QStringLiteral( "ArrowLine" ), QgsArrowSymbolLayerWidget::create );
69 
70  _initWidgetFunction( QStringLiteral( "SimpleMarker" ), QgsSimpleMarkerSymbolLayerWidget::create );
71  _initWidgetFunction( QStringLiteral( "FilledMarker" ), QgsFilledMarkerSymbolLayerWidget::create );
72  _initWidgetFunction( QStringLiteral( "SvgMarker" ), QgsSvgMarkerSymbolLayerWidget::create );
73  _initWidgetFunction( QStringLiteral( "FontMarker" ), QgsFontMarkerSymbolLayerWidget::create );
74  _initWidgetFunction( QStringLiteral( "EllipseMarker" ), QgsEllipseSymbolLayerWidget::create );
75  _initWidgetFunction( QStringLiteral( "VectorField" ), QgsVectorFieldSymbolLayerWidget::create );
76 
77  _initWidgetFunction( QStringLiteral( "SimpleFill" ), QgsSimpleFillSymbolLayerWidget::create );
78  _initWidgetFunction( QStringLiteral( "GradientFill" ), QgsGradientFillSymbolLayerWidget::create );
79  _initWidgetFunction( QStringLiteral( "ShapeburstFill" ), QgsShapeburstFillSymbolLayerWidget::create );
80  _initWidgetFunction( QStringLiteral( "RasterFill" ), QgsRasterFillSymbolLayerWidget::create );
81  _initWidgetFunction( QStringLiteral( "SVGFill" ), QgsSVGFillSymbolLayerWidget::create );
82  _initWidgetFunction( QStringLiteral( "CentroidFill" ), QgsCentroidFillSymbolLayerWidget::create );
83  _initWidgetFunction( QStringLiteral( "LinePatternFill" ), QgsLinePatternFillSymbolLayerWidget::create );
84  _initWidgetFunction( QStringLiteral( "PointPatternFill" ), QgsPointPatternFillSymbolLayerWidget::create );
85 
86  _initWidgetFunction( QStringLiteral( "GeometryGenerator" ), QgsGeometryGeneratorSymbolLayerWidget::create );
87 
88  sInitialized = true;
89 }
90 
91 
93  : QgsPanelWidget( parent )
94  , mLayer( layer )
95  , mSymbol( symbol )
96  , mVectorLayer( vl )
97 {
98 
99  setupUi( this );
100  // initialize the sub-widgets
101  // XXX Should this thing be here this way? Initialize all the widgets just for the sake of one layer?
102  // TODO Make this on demand creation
103  _initWidgetFunctions();
104 
105  // TODO Algorithm
106  //
107  // 3. populate the combo box with the supported layer type
108  // 4. set the present layer type
109  // 5. create the widget for the present layer type and set inn stacked widget
110  // 6. connect comboBox type changed to two things
111  // 1. emit signal that type has beed changed
112  // 2. remove the widget and place the new widget corresponding to the changed layer type
113  //
115  // update layer type combo box
116  int idx = cboLayerType->findData( mLayer->layerType() );
117  cboLayerType->setCurrentIndex( idx );
118 
119  connect( mEnabledCheckBox, &QAbstractButton::toggled, mEnabledDDBtn, &QWidget::setEnabled );
120  mEnabledCheckBox->setChecked( mLayer->enabled() );
121 
122  // set the corresponding widget
123  updateSymbolLayerWidget( layer );
124  connect( cboLayerType, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsLayerPropertiesWidget::layerTypeChanged );
125 
127 
128  this->connectChildPanel( mEffectWidget );
129 
130  mEffectWidget->setPaintEffect( mLayer->paintEffect() );
131 
133 }
134 
136 {
137  mContext = context;
138 
139  QgsSymbolLayerWidget *w = dynamic_cast< QgsSymbolLayerWidget * >( stackedWidget->currentWidget() );
140  if ( w )
141  w->setContext( mContext );
142 }
143 
145 {
146  return mContext;
147 }
148 
150 {
151  QgsPanelWidget::setDockMode( dockMode );
152  mEffectWidget->setDockMode( this->dockMode() );
153 }
154 
156 {
157  QStringList symbolLayerIds = QgsApplication::symbolLayerRegistry()->symbolLayersForType( mSymbol->type() );
158 
159  Q_FOREACH ( const QString &symbolLayerId, symbolLayerIds )
160  cboLayerType->addItem( QgsApplication::symbolLayerRegistry()->symbolLayerMetadata( symbolLayerId )->visibleName(), symbolLayerId );
161 
162  if ( mSymbol->type() == QgsSymbol::Fill )
163  {
165  Q_FOREACH ( const QString &lineLayerId, lineLayerIds )
166  {
168  if ( layerInfo->type() != QgsSymbol::Hybrid )
169  {
170  QString visibleName = layerInfo->visibleName();
171  QString name = QString( tr( "Outline: %1" ) ).arg( visibleName );
172  cboLayerType->addItem( name, lineLayerId );
173  }
174  }
175  }
176 }
177 
179 {
180  if ( stackedWidget->currentWidget() != pageDummy )
181  {
182  // stop updating from the original widget
183  if ( QgsSymbolLayerWidget *w = qobject_cast< QgsSymbolLayerWidget * >( stackedWidget->currentWidget() ) )
185  stackedWidget->removeWidget( stackedWidget->currentWidget() );
186  }
187 
189 
190  QString layerType = layer->layerType();
191  QgsSymbolLayerAbstractMetadata *am = pReg->symbolLayerMetadata( layerType );
192  if ( am )
193  {
195  if ( w )
196  {
197  w->setContext( mContext );
198  w->setSymbolLayer( layer );
199  stackedWidget->addWidget( w );
200  stackedWidget->setCurrentWidget( w );
201  // start receiving updates from widget
203  connect( w, &QgsSymbolLayerWidget::symbolChanged, this, &QgsLayerPropertiesWidget::reloadLayer );
204  return;
205  }
206  }
207  // When anything is not right
208  stackedWidget->setCurrentWidget( pageDummy );
209 }
210 
212 {
213  if ( mContext.expressionContext() )
214  return *mContext.expressionContext();
215 
216  QgsExpressionContext expContext;
220 
221  if ( mContext.mapCanvas() )
222  {
225  }
226  else
227  {
229  }
230 
232 
234  if ( mLayer )
235  {
236  //cheat a bit - set the symbol color variable to match the symbol layer's color (when we should really be using the *symbols*
237  //color, but that's not accessible here). 99% of the time these will be the same anyway
239  }
240  expContext << symbolScope;
245 
246  // additional scopes
247  Q_FOREACH ( const QgsExpressionContextScope &scope, mContext.additionalExpressionContextScopes() )
248  {
249  expContext.appendScope( new QgsExpressionContextScope( scope ) );
250  }
251 
252  //TODO - show actual value
253  expContext.setOriginalValueVariable( QVariant() );
254 
259 
260  return expContext;
261 }
262 
264 {
266  connect( button, &QgsPropertyOverrideButton::changed, this, &QgsLayerPropertiesWidget::updateProperty );
267  button->registerExpressionContextGenerator( this );
268 }
269 
270 void QgsLayerPropertiesWidget::updateProperty()
271 {
272  QgsPropertyOverrideButton *button = qobject_cast<QgsPropertyOverrideButton *>( sender() );
273  QgsSymbolLayer::Property key = static_cast< QgsSymbolLayer::Property >( button->propertyKey() );
274  mLayer->setDataDefinedProperty( key, button->toProperty() );
275  emit changed();
276 }
277 
279 {
280  QgsSymbolLayer *layer = mLayer;
281  if ( !layer )
282  return;
283  QString newLayerType = cboLayerType->currentData().toString();
284  if ( layer->layerType() == newLayerType )
285  return;
286 
287  // get creation function for new layer from registry
289  QgsSymbolLayerAbstractMetadata *am = pReg->symbolLayerMetadata( newLayerType );
290  if ( !am ) // check whether the metadata is assigned
291  return;
292 
293  // change layer to a new (with different type)
294  // base new layer on existing layer's properties
295  QgsSymbolLayer *newLayer = am->createSymbolLayer( layer->properties() );
296  if ( !newLayer )
297  return;
298 
299  updateSymbolLayerWidget( newLayer );
300  emit changeLayer( newLayer );
301 }
302 
304 {
305  emit changed();
306 
307  // also update paint effect preview
308  mEffectWidget->setPreviewPicture( QgsSymbolLayerUtils::symbolLayerPreviewPicture( mLayer, QgsUnitTypes::RenderMillimeters, QSize( 80, 80 ) ) );
309  emit widgetChanged();
310 }
311 
312 void QgsLayerPropertiesWidget::reloadLayer()
313 {
314  emit changeLayer( mLayer );
315 }
316 
317 void QgsLayerPropertiesWidget::on_mEnabledCheckBox_toggled( bool enabled )
318 {
319  mLayer->setEnabled( enabled );
321 }
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 ...
void symbolChanged()
Should be emitted whenever the sub symbol changed on this symbol layer configuration.
Stores metadata about one symbol layer class.
bool dockMode()
Return the dock mode state.
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:37
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 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.
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:72
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.
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...
void changed()
Should be emitted whenever configuration changes happened on this symbol layer configuration.
static QgsSymbolLayerWidget * create(const QgsVectorLayer *layer)
Static creation method.
A button for controlling property overrides which may apply to a widget.
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...
QgsProperty toProperty() const
Returns a QgsProperty object encapsulating the current state of the widget.
static QgsSymbolLayerWidget * create(const QgsVectorLayer *vl)
static QgsSymbolLayerWidget * create(const QgsVectorLayer *vl)
void registerExpressionContextGenerator(QgsExpressionContextGenerator *generator)
Register an expression context generator class that will be used to retrieve an expression context fo...
static QgsSymbolLayerWidget * create(const QgsVectorLayer *vl)
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol layer&#39;s property collection, used for data defined overrides...
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.
void registerDataDefinedButton(QgsPropertyOverrideButton *button, QgsSymbolLayer::Property key)
Registers a data defined override button.
virtual QgsSymbolLayer * createSymbolLayer(const QgsStringMap &map)=0
Create a symbol layer of this type given the map of properties.
void init(int propertyKey, const QgsProperty &property, const QgsPropertiesDefinition &definitions, const QgsVectorLayer *layer=nullptr)
Initialize a newly constructed property button (useful if button was included in a UI layout)...
static QgsSymbolLayerWidget * create(const QgsVectorLayer *vl)
const QgsMapSettings & mapSettings() const
Get access to properties used for map rendering.
void changed()
Emitted when property definition changes.
static QgsSymbolLayerWidget * create(const QgsVectorLayer *vl)
QgsMapCanvas * mapCanvas() const
Returns the map canvas associated with the widget.
QgsExpressionContext * expressionContext() const
Returns the expression context used for the widget, if set.
Fill symbol.
Definition: qgssymbol.h:73
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:461
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:99
static QgsSymbolLayerWidget * create(const QgsVectorLayer *vl)
void changed()
Emitted when the paint effect properties change.
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:377
void setContext(const QgsSymbolWidgetContext &context)
Sets the context in which the symbol widget is shown, e.g., the associated map canvas and expression ...
int propertyKey() const
Returns the property key linked to the button.
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 QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the symbol layer property definitions.
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.
Whether symbol layer is enabled.
Hybrid symbol.
Definition: qgssymbol.h:74
Property
Data definable properties.
virtual void setDataDefinedProperty(Property key, const QgsProperty &property)
Sets a data defined property for the layer.
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.