QGIS API Documentation  3.6.0-Noosa (5873452)
qgsrendererwidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsrendererwidget.cpp
3  ---------------------
4  begin : November 2009
5  copyright : (C) 2009 by Martin Dobias
6  email : wonder dot sk at gmail dot 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 #include "qgsrendererwidget.h"
16 
18 #include "qgssymbol.h"
19 #include "qgsvectorlayer.h"
20 #include "qgscolordialog.h"
21 #include "qgssymbollevelsdialog.h"
22 #include "qgssymbollayer.h"
24 #include "qgsmapcanvas.h"
25 #include "qgspanelwidget.h"
26 #include "qgsproject.h"
28 
29 #include <QMessageBox>
30 #include <QInputDialog>
31 #include <QMenu>
32 
34  : mLayer( layer )
35  , mStyle( style )
36 {
37  contextMenu = new QMenu( tr( "Renderer Options" ), this );
38 
39  mCopyAction = contextMenu->addAction( tr( "Copy" ), this, SLOT( copy() ) );
40  mCopyAction->setShortcut( QKeySequence( QKeySequence::Copy ) );
41  mPasteAction = contextMenu->addAction( tr( "Paste" ), this, SLOT( paste() ) );
42  mPasteAction->setShortcut( QKeySequence( QKeySequence::Paste ) );
43 
44  contextMenu->addSeparator();
45  contextMenu->addAction( tr( "Change Color…" ), this, SLOT( changeSymbolColor() ) );
46  contextMenu->addAction( tr( "Change Opacity…" ), this, SLOT( changeSymbolOpacity() ) );
47  contextMenu->addAction( tr( "Change Output Unit…" ), this, SLOT( changeSymbolUnit() ) );
48 
50  {
51  contextMenu->addAction( tr( "Change Width…" ), this, SLOT( changeSymbolWidth() ) );
52  }
54  {
55  contextMenu->addAction( tr( "Change Size…" ), this, SLOT( changeSymbolSize() ) );
56  contextMenu->addAction( tr( "Change Angle…" ), this, SLOT( changeSymbolAngle() ) );
57  }
58 }
59 
61 {
62  contextMenu->exec( QCursor::pos() );
63 }
64 
66 {
67  QList<QgsSymbol *> symbolList = selectedSymbols();
68  if ( symbolList.isEmpty() )
69  {
70  return;
71  }
72 
73  QgsSymbol *firstSymbol = nullptr;
74  Q_FOREACH ( QgsSymbol *symbol, symbolList )
75  {
76  if ( symbol )
77  {
78  firstSymbol = symbol;
79  break;
80  }
81  }
82  if ( !firstSymbol )
83  return;
84 
85  QColor color = QgsColorDialog::getColor( firstSymbol->color(), this, QStringLiteral( "Change Symbol Color" ), true );
86  if ( color.isValid() )
87  {
88  Q_FOREACH ( QgsSymbol *symbol, symbolList )
89  {
90  if ( symbol )
91  symbol->setColor( color );
92  }
94  }
95 }
96 
98 {
99  QList<QgsSymbol *> symbolList = selectedSymbols();
100  if ( symbolList.isEmpty() )
101  {
102  return;
103  }
104 
105  QgsSymbol *firstSymbol = nullptr;
106  Q_FOREACH ( QgsSymbol *symbol, symbolList )
107  {
108  if ( symbol )
109  {
110  firstSymbol = symbol;
111  break;
112  }
113  }
114  if ( !firstSymbol )
115  return;
116 
117  bool ok;
118  double oldOpacity = firstSymbol->opacity() * 100; // convert to %
119  double opacity = QInputDialog::getDouble( this, tr( "Opacity" ), tr( "Change symbol opacity [%]" ), oldOpacity, 0.0, 100.0, 1, &ok );
120  if ( ok )
121  {
122  Q_FOREACH ( QgsSymbol *symbol, symbolList )
123  {
124  if ( symbol )
125  symbol->setOpacity( opacity / 100.0 );
126  }
128  }
129 }
130 
132 {
133  QList<QgsSymbol *> symbolList = selectedSymbols();
134  if ( symbolList.isEmpty() )
135  {
136  return;
137  }
138 
139  QgsSymbol *firstSymbol = nullptr;
140  Q_FOREACH ( QgsSymbol *symbol, symbolList )
141  {
142  if ( symbol )
143  {
144  firstSymbol = symbol;
145  break;
146  }
147  }
148  if ( !firstSymbol )
149  return;
150 
151  bool ok;
152  int currentUnit = ( firstSymbol->outputUnit() == QgsUnitTypes::RenderMillimeters ) ? 0 : 1;
153  QString item = QInputDialog::getItem( this, tr( "Symbol unit" ), tr( "Select symbol unit" ), QStringList() << tr( "Millimeter" ) << tr( "Map unit" ), currentUnit, false, &ok );
154  if ( ok )
155  {
156  QgsUnitTypes::RenderUnit unit = ( item.compare( tr( "Millimeter" ) ) == 0 ) ? QgsUnitTypes::RenderMillimeters : QgsUnitTypes::RenderMapUnits;
157 
158  Q_FOREACH ( QgsSymbol *symbol, symbolList )
159  {
160  if ( symbol )
161  symbol->setOutputUnit( unit );
162  }
164  }
165 }
166 
168 {
169  QList<QgsSymbol *> symbolList = selectedSymbols();
170  if ( symbolList.isEmpty() )
171  {
172  return;
173  }
174 
175  QgsDataDefinedWidthDialog dlg( symbolList, mLayer );
176 
177  dlg.setContext( mContext );
178 
179  if ( QDialog::Accepted == dlg.exec() )
180  {
181  if ( !dlg.mDDBtn->isActive() )
182  {
183  Q_FOREACH ( QgsSymbol *symbol, symbolList )
184  {
185  if ( !symbol )
186  continue;
187 
188  if ( symbol->type() == QgsSymbol::Line )
189  static_cast<QgsLineSymbol *>( symbol )->setWidth( dlg.mSpinBox->value() );
190  }
191  }
193  }
194 }
195 
197 {
198  QList<QgsSymbol *> symbolList = selectedSymbols();
199  if ( symbolList.isEmpty() )
200  {
201  return;
202  }
203 
204  QgsDataDefinedSizeDialog dlg( symbolList, mLayer );
205  dlg.setContext( mContext );
206 
207  if ( QDialog::Accepted == dlg.exec() )
208  {
209  if ( !dlg.mDDBtn->isActive() )
210  {
211  Q_FOREACH ( QgsSymbol *symbol, symbolList )
212  {
213  if ( !symbol )
214  continue;
215 
216  if ( symbol->type() == QgsSymbol::Marker )
217  static_cast<QgsMarkerSymbol *>( symbol )->setSize( dlg.mSpinBox->value() );
218  }
219  }
221  }
222 }
223 
225 {
226  QList<QgsSymbol *> symbolList = selectedSymbols();
227  if ( symbolList.isEmpty() )
228  {
229  return;
230  }
231 
232  QgsDataDefinedRotationDialog dlg( symbolList, mLayer );
233  dlg.setContext( mContext );
234 
235  if ( QDialog::Accepted == dlg.exec() )
236  {
237  if ( !dlg.mDDBtn->isActive() )
238  {
239  Q_FOREACH ( QgsSymbol *symbol, symbolList )
240  {
241  if ( !symbol )
242  continue;
243 
244  if ( symbol->type() == QgsSymbol::Marker )
245  static_cast<QgsMarkerSymbol *>( symbol )->setAngle( dlg.mSpinBox->value() );
246  }
247  }
249  }
250 }
251 
253 {
255  if ( panel && panel->dockMode() )
256  {
257  QgsSymbolLevelsWidget *widget = new QgsSymbolLevelsWidget( r, r->usingSymbolLevels(), panel );
258  widget->setPanelTitle( tr( "Symbol Levels" ) );
259  connect( widget, &QgsPanelWidget::widgetChanged, widget, &QgsSymbolLevelsWidget::apply );
261  panel->openPanel( widget );
262  return;
263  }
264 
265  QgsSymbolLevelsDialog dlg( r, r->usingSymbolLevels(), panel );
266  if ( dlg.exec() )
267  {
268  emit widgetChanged();
269  }
270 }
271 
273 {
274  mContext = context;
275 }
276 
278 {
279  return mContext;
280 }
281 
283 {
284  apply();
285 }
286 
288 {
289  QgsProperty ddSize = symbol->dataDefinedSize();
290  if ( !ddSize || !ddSize.isActive() )
291  {
292  QMessageBox::warning( this, tr( "Data-defined Size Legend" ), tr( "Data-defined size is not enabled!" ) );
293  return nullptr;
294  }
295 
296  QgsDataDefinedSizeLegendWidget *panel = new QgsDataDefinedSizeLegendWidget( ddsLegend, ddSize, symbol->clone(), mContext.mapCanvas() );
298  return panel;
299 }
300 
301 
302 //
303 // QgsDataDefinedValueDialog
304 //
305 
306 QgsDataDefinedValueDialog::QgsDataDefinedValueDialog( const QList<QgsSymbol *> &symbolList, QgsVectorLayer *layer, const QString &label )
307  : mSymbolList( symbolList )
308  , mLayer( layer )
309 {
310  setupUi( this );
311  setWindowFlags( Qt::WindowStaysOnTopHint );
312  mLabel->setText( label );
314 }
315 
317 {
318  mContext = context;
319 }
320 
322 {
323  return mContext;
324 }
325 
326 QgsExpressionContext QgsDataDefinedValueDialog::createExpressionContext() const
327 {
328  QgsExpressionContext expContext;
332  if ( mContext.mapCanvas() )
333  {
336  }
337  else
338  {
340  }
341 
342  if ( vectorLayer() )
344 
345  // additional scopes
346  Q_FOREACH ( const QgsExpressionContextScope &scope, mContext.additionalExpressionContextScopes() )
347  {
348  expContext.appendScope( new QgsExpressionContextScope( scope ) );
349  }
350 
351  return expContext;
352 }
353 
354 void QgsDataDefinedValueDialog::init( int propertyKey )
355 {
356  QgsProperty dd( symbolDataDefined() );
357 
358  mDDBtn->init( propertyKey, dd, QgsSymbolLayer::propertyDefinitions(), mLayer );
359  mDDBtn->registerExpressionContextGenerator( this );
360 
361  QgsSymbol *initialSymbol = nullptr;
362  Q_FOREACH ( QgsSymbol *symbol, mSymbolList )
363  {
364  if ( symbol )
365  {
366  initialSymbol = symbol;
367  }
368  }
369  mSpinBox->setValue( initialSymbol ? value( initialSymbol ) : 0 );
370  mSpinBox->setEnabled( !mDDBtn->isActive() );
371 }
372 
373 QgsProperty QgsDataDefinedValueDialog::symbolDataDefined() const
374 {
375  if ( mSymbolList.isEmpty() || !mSymbolList.back() )
376  return QgsProperty();
377 
378  // check that all symbols share the same size expression
379  QgsProperty dd = symbolDataDefined( mSymbolList.back() );
380  Q_FOREACH ( QgsSymbol *it, mSymbolList )
381  {
382  QgsProperty symbolDD( symbolDataDefined( it ) );
383  if ( !it || !dd || !symbolDD || symbolDD != dd )
384  return QgsProperty();
385  }
386  return dd;
387 }
388 
390 {
391  QgsProperty dd( mDDBtn->toProperty() );
392  mSpinBox->setEnabled( !dd.isActive() );
393 
394  QgsProperty symbolDD( symbolDataDefined() );
395 
396  if ( // shall we remove datadefined expressions for layers ?
397  ( symbolDD && symbolDD.isActive() && !dd.isActive() )
398  // shall we set the "en masse" expression for properties ?
399  || dd.isActive() )
400  {
401  Q_FOREACH ( QgsSymbol *it, mSymbolList )
402  setDataDefined( it, dd );
403  }
404 }
405 
407 {
408  const QgsMarkerSymbol *marker = static_cast<const QgsMarkerSymbol *>( symbol );
409  return marker->dataDefinedSize();
410 }
411 
413 {
414  static_cast<QgsMarkerSymbol *>( symbol )->setDataDefinedSize( dd );
415  static_cast<QgsMarkerSymbol *>( symbol )->setScaleMethod( QgsSymbol::ScaleDiameter );
416 }
417 
418 
420 {
421  const QgsMarkerSymbol *marker = static_cast<const QgsMarkerSymbol *>( symbol );
422  return marker->dataDefinedAngle();
423 }
424 
426 {
427  static_cast<QgsMarkerSymbol *>( symbol )->setDataDefinedAngle( dd );
428 }
429 
430 
432 {
433  const QgsLineSymbol *line = static_cast<const QgsLineSymbol *>( symbol );
434  return line->dataDefinedWidth();
435 }
436 
438 {
439  static_cast<QgsLineSymbol *>( symbol )->setDataDefinedWidth( dd );
440 }
441 
442 void QgsRendererWidget::apply()
443 {
444 
445 }
void openPanel(QgsPanelWidget *panel)
Open a panel or dialog depending on dock mode setting If dock mode is true this method will emit the ...
static QColor getColor(const QColor &initialColor, QWidget *parent, const QString &title=QString(), bool allowOpacity=false)
Returns a color selection from a color dialog.
void changeSymbolOpacity()
Change opacity of selected symbols.
void changeSymbolWidth()
Change line widths of selected symbols.
virtual void setContext(const QgsSymbolWidgetContext &context)
Sets the context in which the renderer widget is shown, e.g., the associated map canvas and expressio...
bool dockMode()
Returns the dock mode state.
Calculate scale by the diameter.
Definition: qgssymbol.h:97
double value(const QgsSymbol *symbol) const override
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:61
virtual void refreshSymbolView()
void changeSymbolAngle()
Change marker angles of selected symbols.
QgsSymbolWidgetContext context() const
Returns the context in which the renderer widget is shown, e.g., the associated map canvas and expres...
void showSymbolLevelsDialog(QgsFeatureRenderer *r)
show a dialog with renderer&#39;s symbol level settings
double value(const QgsSymbol *symbol) const override
QgsVectorLayer * mLayer
QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
Base class for any widget that can be shown as a inline panel.
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:86
QgsProperty symbolDataDefined(const QgsSymbol *symbol) const override
A marker symbol type, for rendering Point and MultiPoint geometries.
Definition: qgssymbol.h:732
A line symbol type, for rendering LineString and MultiLineString geometries.
Definition: qgssymbol.h:920
The QgsMapSettings class contains configuration for rendering of the map.
QgsUnitTypes::RenderUnit outputUnit() const
Returns the units to use for sizes and widths within the symbol.
Definition: qgssymbol.cpp:216
void applyChanges()
This method should be called whenever the renderer is actually set on the layer.
void setOutputUnit(QgsUnitTypes::RenderUnit unit)
Sets the units to use for sizes and widths within the symbol.
Definition: qgssymbol.cpp:261
QgsProperty dataDefinedAngle() const
Returns data defined angle for whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:1231
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context...
QgsSymbolWidgetContext context() const
Returns the context in which the symbol widget is shown, e.g., the associated map canvas and expressi...
void setDataDefined(QgsSymbol *symbol, const QgsProperty &dd) override
static QgsPanelWidget * findParentPanel(QWidget *widget)
Traces through the parents of a widget to find if it is contained within a QgsPanelWidget widget...
Contains settings which reflect the context in which a symbol (or renderer) widget is shown...
void setOpacity(qreal opacity)
Sets the opacity for the symbol.
Definition: qgssymbol.h:346
Widget for configuration of appearance of legend for marker symbols with data-defined size...
A widget which allows the user to modify the rendering order of symbol layers.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void changeSymbolSize()
Change marker sizes of selected symbols.
QColor color() const
Returns the symbol&#39;s color.
Definition: qgssymbol.cpp:461
QgsDataDefinedSizeLegendWidget * createDataDefinedSizeLegendWidget(const QgsMarkerSymbol *symbol, const QgsDataDefinedSizeLegend *ddsLegend)
Creates widget to setup data-defined size legend.
Single scope for storing variables and functions for use within a QgsExpressionContext.
A store for object properties.
Definition: qgsproperty.h:229
virtual void paste()
virtual void copy()
void widgetChanged()
Emitted when the widget state changes.
QgsProperty symbolDataDefined(const QgsSymbol *symbol) const override
A dialog which allows the user to modify the rendering order of symbol layers.
double value(const QgsSymbol *symbol) const override
QgsProperty dataDefinedSize() const
Returns data defined size for whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:1428
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
void changed()
Emitted when property definition changes.
QgsMapCanvas * mapCanvas() const
Returns the map canvas associated with the widget.
Marker symbol.
Definition: qgssymbol.h:85
static QgsExpressionContextScope * atlasScope(QgsLayoutAtlas *atlas)
Creates a new scope which contains variables and functions relating to a QgsLayoutAtlas.
void apply()
Apply button.
const QgsVectorLayer * vectorLayer() const
Returns the vector layer associated with the widget.
bool usingSymbolLevels() const
Definition: qgsrenderer.h:271
static QgsExpressionContextScope * mapSettingsScope(const QgsMapSettings &mapSettings)
Creates a new scope which contains variables and functions relating to a QgsMapSettings object...
QgsSymbolWidgetContext mContext
Context in which widget is shown.
QgsExpressionContextScope & expressionContextScope()
Returns a reference to the expression context scope for the map canvas.
Definition: qgsmapcanvas.h:559
SymbolType type() const
Returns the symbol&#39;s type.
Definition: qgssymbol.h:120
virtual QList< QgsSymbol * > selectedSymbols()
Subclasses may provide the capability of changing multiple symbols at once by implementing the follow...
void init(int propertyKey)
Should be called in the constructor of child classes.
void setDataDefined(QgsSymbol *symbol, const QgsProperty &dd) override
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:430
void contextMenuViewCategories(QPoint p)
QgsProperty symbolDataDefined(const QgsSymbol *symbol) const override
QgsDataDefinedValueDialog(const QList< QgsSymbol *> &symbolList, QgsVectorLayer *layer, const QString &label)
Constructor.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
qreal opacity() const
Returns the opacity for the symbol.
Definition: qgssymbol.h:339
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the symbol layer property definitions.
void setContext(const QgsSymbolWidgetContext &context)
Sets the context in which the symbol widget is shown, e.g., the associated map canvas and expression ...
QgsRendererWidget(QgsVectorLayer *layer, QgsStyle *style)
void changeSymbolColor()
Change color of selected symbols.
Represents a vector layer which manages a vector based data sets.
Object that keeps configuration of appearance of marker symbol&#39;s data-defined size in legend...
void setPanelTitle(const QString &panelTitle)
Set the title of the panel when shown in the interface.
QgsProperty dataDefinedWidth() const
Returns data defined width for whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:1703
void changeSymbolUnit()
Change units mm/map units of selected symbols.
QgsMarkerSymbol * clone() const override
Returns a deep copy of this symbol.
Definition: qgssymbol.cpp:1585
bool isActive() const
Returns whether the property is currently active.
void setDataDefined(QgsSymbol *symbol, const QgsProperty &dd) override
RenderUnit
Rendering size units.
Definition: qgsunittypes.h:111
QList< QgsExpressionContextScope > additionalExpressionContextScopes() const
Returns the list of additional expression context scopes to show as available within the layer...
void setColor(const QColor &color)
Sets the color for the symbol.
Definition: qgssymbol.cpp:452