QGIS API Documentation  2.12.0-Lyon
qgsrendererv2widget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsrendererv2widget.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 "qgsrendererv2widget.h"
16 #include "qgssymbolv2.h"
17 #include "qgsvectorlayer.h"
18 #include "qgscolordialog.h"
21 #include "qgsmapcanvas.h"
22 
23 #include <QMessageBox>
24 #include <QInputDialog>
25 #include <QMenu>
26 
28  : QWidget()
29  , mLayer( layer )
30  , mStyle( style )
31  , mMapCanvas( 0 )
32 {
33  contextMenu = new QMenu( tr( "Renderer Options" ), this );
34 
35  mCopyAction = contextMenu->addAction( tr( "Copy" ), this, SLOT( copy() ) );
36  mCopyAction->setShortcut( QKeySequence( QKeySequence::Copy ) );
37  mPasteAction = contextMenu->addAction( tr( "Paste" ), this, SLOT( paste() ) );
38  mPasteAction->setShortcut( QKeySequence( QKeySequence::Paste ) );
39 
41  contextMenu->addAction( tr( "Change color" ), this, SLOT( changeSymbolColor() ) );
42  contextMenu->addAction( tr( "Change transparency" ), this, SLOT( changeSymbolTransparency() ) );
43  contextMenu->addAction( tr( "Change output unit" ), this, SLOT( changeSymbolUnit() ) );
44 
45  if ( mLayer && mLayer->geometryType() == QGis::Line )
46  {
47  contextMenu->addAction( tr( "Change width" ), this, SLOT( changeSymbolWidth() ) );
48  }
49  else if ( mLayer && mLayer->geometryType() == QGis::Point )
50  {
51  contextMenu->addAction( tr( "Change size" ), this, SLOT( changeSymbolSize() ) );
52  contextMenu->addAction( tr( "Change angle" ), this, SLOT( changeSymbolAngle() ) );
53  }
54 }
55 
57 {
59 }
60 
62 {
63  QList<QgsSymbolV2*> symbolList = selectedSymbols();
64  if ( symbolList.size() < 1 )
65  {
66  return;
67  }
68 
69  QColor color = QgsColorDialogV2::getColor( symbolList.at( 0 )->color(), this, "Change Symbol Color", true );
70  if ( color.isValid() )
71  {
72  QList<QgsSymbolV2*>::iterator symbolIt = symbolList.begin();
73  for ( ; symbolIt != symbolList.end(); ++symbolIt )
74  {
75  ( *symbolIt )->setColor( color );
76  }
78  }
79 }
80 
82 {
83  QList<QgsSymbolV2*> symbolList = selectedSymbols();
84  if ( symbolList.size() < 1 )
85  {
86  return;
87  }
88 
89  bool ok;
90  double oldTransparency = ( 1 - symbolList.at( 0 )->alpha() ) * 100; // convert to percents
91  double transparency = QInputDialog::getDouble( this, tr( "Transparency" ), tr( "Change symbol transparency [%]" ), oldTransparency, 0.0, 100.0, 0, &ok );
92  if ( ok )
93  {
94  QList<QgsSymbolV2*>::iterator symbolIt = symbolList.begin();
95  for ( ; symbolIt != symbolList.end(); ++symbolIt )
96  {
97  ( *symbolIt )->setAlpha( 1 - transparency / 100 );
98  }
100  }
101 }
102 
104 {
105  QList<QgsSymbolV2*> symbolList = selectedSymbols();
106  if ( symbolList.size() < 1 )
107  {
108  return;
109  }
110 
111  bool ok;
112  int currentUnit = ( symbolList.at( 0 )->outputUnit() == QgsSymbolV2::MM ) ? 0 : 1;
113  QString item = QInputDialog::getItem( this, tr( "Symbol unit" ), tr( "Select symbol unit" ), QStringList() << tr( "Millimeter" ) << tr( "Map unit" ), currentUnit, false, &ok );
114  if ( ok )
115  {
116  QgsSymbolV2::OutputUnit unit = ( item.compare( tr( "Millimeter" ) ) == 0 ) ? QgsSymbolV2::MM : QgsSymbolV2::MapUnit;
117 
118  QList<QgsSymbolV2*>::iterator symbolIt = symbolList.begin();
119  for ( ; symbolIt != symbolList.end(); ++symbolIt )
120  {
121  ( *symbolIt )->setOutputUnit( unit );
122  }
124  }
125 }
126 
128 {
129  QList<QgsSymbolV2*> symbolList = selectedSymbols();
130  if ( symbolList.size() < 1 )
131  {
132  return;
133  }
134 
135  QgsDataDefinedWidthDialog dlg( symbolList, mLayer );
136  dlg.setMapCanvas( mMapCanvas );
137 
138  if ( QDialog::Accepted == dlg.exec() )
139  {
140  if ( !dlg.mDDBtn->isActive() )
141  {
142  QList<QgsSymbolV2*>::iterator symbolIt = symbolList.begin();
143  for ( ; symbolIt != symbolList.end(); ++symbolIt )
144  {
145  if (( *symbolIt )->type() == QgsSymbolV2::Line )
146  static_cast<QgsLineSymbolV2*>( *symbolIt )->setWidth( dlg.mSpinBox->value() );
147  }
148  }
150  }
151 }
152 
154 {
155  QList<QgsSymbolV2*> symbolList = selectedSymbols();
156  if ( symbolList.size() < 1 )
157  {
158  return;
159  }
160 
161  QgsDataDefinedSizeDialog dlg( symbolList, mLayer );
162  dlg.setMapCanvas( mMapCanvas );
163 
164  if ( QDialog::Accepted == dlg.exec() )
165  {
166  if ( !dlg.mDDBtn->isActive() )
167  {
168  QList<QgsSymbolV2*>::iterator symbolIt = symbolList.begin();
169  for ( ; symbolIt != symbolList.end(); ++symbolIt )
170  {
171  if (( *symbolIt )->type() == QgsSymbolV2::Marker )
172  static_cast<QgsMarkerSymbolV2*>( *symbolIt )->setSize( dlg.mSpinBox->value() );
173  }
174  }
176  }
177 }
178 
180 {
181  QList<QgsSymbolV2*> symbolList = selectedSymbols();
182  if ( symbolList.size() < 1 )
183  {
184  return;
185  }
186 
187  QgsDataDefinedRotationDialog dlg( symbolList, mLayer );
188  dlg.setMapCanvas( mMapCanvas );
189 
190  if ( QDialog::Accepted == dlg.exec() )
191  {
192  if ( !dlg.mDDBtn->isActive() )
193  {
194  QList<QgsSymbolV2*>::iterator symbolIt = symbolList.begin();
195  for ( ; symbolIt != symbolList.end(); ++symbolIt )
196  {
197  if (( *symbolIt )->type() == QgsSymbolV2::Marker )
198  static_cast<QgsMarkerSymbolV2*>( *symbolIt )->setAngle( dlg.mSpinBox->value() );
199  }
200  }
202  }
203 }
204 
206 {
207  QgsLegendSymbolList symbols = r->legendSymbolItems();
208 
209  QgsSymbolLevelsV2Dialog dlg( symbols, r->usingSymbolLevels(), this );
210 
211  if ( dlg.exec() )
212  {
213  r->setUsingSymbolLevels( dlg.usingLevels() );
214  }
215 }
216 
218 {
219  mMapCanvas = canvas;
220 }
221 
223 {
224  return mMapCanvas;
225 }
226 
227 
229 
230 #include "qgsfield.h"
231 
232 QgsRendererV2DataDefinedMenus::QgsRendererV2DataDefinedMenus( QMenu* menu, QgsVectorLayer* layer, const QString& rotationField, const QString& sizeScaleField, QgsSymbolV2::ScaleMethod scaleMethod )
233  : QObject( menu ), mLayer( layer )
234 {
235  mRotationMenu = new QMenu( tr( "Rotation field" ) );
236  mSizeScaleMenu = new QMenu( tr( "Size scale field" ) );
237 
241 
244 
246 
247  QAction* aScaleByArea = new QAction( tr( "Scale area" ), mSizeMethodActionGroup );
248  QAction* aScaleByDiameter = new QAction( tr( "Scale diameter" ), mSizeMethodActionGroup );
249 
250  aScaleByArea->setCheckable( true );
251  aScaleByDiameter->setCheckable( true );
252 
253  if ( scaleMethod == QgsSymbolV2::ScaleDiameter )
254  {
255  aScaleByDiameter->setChecked( true );
256  }
257  else
258  {
259  aScaleByArea->setChecked( true );
260  }
261 
263 
264  //@todo cleanup the class since Rotation and SizeScale are now
265  //defined using QgsDataDefinedButton
266  //
267  //menu->addMenu( mRotationMenu );
268  //menu->addMenu( mSizeScaleMenu );
269 
270  connect( mSizeMethodActionGroup, SIGNAL( triggered( QAction* ) ), this, SLOT( scaleMethodSelected( QAction* ) ) );
271  connect( mRotationAttributeActionGroup, SIGNAL( triggered( QAction* ) ), this, SLOT( rotationFieldSelected( QAction* ) ) );
272  connect( mSizeAttributeActionGroup, SIGNAL( triggered( QAction* ) ), this, SLOT( sizeScaleFieldSelected( QAction* ) ) );
273 }
274 
276 {
277  delete mSizeMethodActionGroup;
280  delete mRotationMenu;
281  delete mSizeScaleMenu;
282 }
283 
284 void QgsRendererV2DataDefinedMenus::populateMenu( QMenu* menu, const QString& fieldName, QActionGroup *actionGroup )
285 {
286  QAction* aExpr = new QAction( tr( "- expression -" ), actionGroup );
287  aExpr->setCheckable( true );
288  menu->addAction( aExpr );
289  menu->addSeparator();
290  QAction* aNo = new QAction( tr( "- no field -" ), actionGroup );
291  aNo->setCheckable( true );
292  menu->addAction( aNo );
293  menu->addSeparator();
294 
295  bool hasField = false;
296  const QgsFields & flds = mLayer->fields();
297  for ( int idx = 0; idx < flds.count(); ++idx )
298  {
299  const QgsField& fld = flds[idx];
300  if ( fld.type() == QVariant::Int || fld.type() == QVariant::Double )
301  {
302  QAction* a = new QAction( fld.name(), actionGroup );
303  a->setCheckable( true );
304  if ( fieldName == fld.name() )
305  {
306  a->setChecked( true );
307  hasField = true;
308  }
309  menu->addAction( a );
310  }
311  }
312 
313  if ( !hasField )
314  {
315  if ( fieldName.isEmpty() )
316  {
317  aNo->setChecked( true );
318  }
319  else
320  {
321  aExpr->setChecked( true );
322  aExpr->setText( tr( "- expression -" ) + fieldName );
323  }
324  }
325 
326 }
327 
329 {
330  if ( a == NULL )
331  return;
332 
333  QString fldName = a->text();
334 #if 0
335  updateMenu( mRotationAttributeActionGroup, fldName );
336 #endif
337  if ( fldName == tr( "- no field -" ) )
338  {
339  fldName = QString();
340  }
341  else if ( fldName.startsWith( tr( "- expression -" ) ) )
342  {
343  QString expr( fldName );
344  expr.replace( 0, tr( "- expression -" ).length(), "" );
345  QgsExpressionBuilderDialog dialog( mLayer, expr );
346  if ( !dialog.exec() ) return;
347  fldName = dialog.expressionText();
348  Q_ASSERT( !QgsExpression( fldName ).hasParserError() );
349  a->setText( tr( "- expression -" ) + fldName );
350  }
351 
352  emit rotationFieldChanged( fldName );
353 }
354 
356 {
357  if ( a == NULL )
358  return;
359 
360  QString fldName = a->text();
361 #if 0
362  updateMenu( mSizeAttributeActionGroup, fldName );
363 #endif
364  if ( fldName == tr( "- no field -" ) )
365  {
366  fldName = QString();
367  }
368  else if ( fldName.startsWith( tr( "- expression -" ) ) )
369  {
370  QString expr( fldName );
371  expr.replace( 0, tr( "- expression -" ).length(), "" );
372  QgsExpressionBuilderDialog dialog( mLayer, expr );
373  if ( !dialog.exec() ) return;
374  fldName = dialog.expressionText();
375  Q_ASSERT( !QgsExpression( fldName ).hasParserError() );
376  a->setText( tr( "- expression -" ) + fldName );
377  }
378 
379  emit sizeScaleFieldChanged( fldName );
380 }
381 
383 {
384  if ( a == NULL )
385  return;
386 
387  if ( a->text() == tr( "Scale area" ) )
388  {
390  }
391  else if ( a->text() == tr( "Scale diameter" ) )
392  {
394  }
395 }
396 #if 0 // MK: is there any reason for this?
397 void QgsRendererV2DataDefinedMenus::updateMenu( QActionGroup* actionGroup, QString fieldName )
398 {
399  Q_FOREACH ( QAction* a, actionGroup->actions() )
400  {
401  a->setChecked( a->text() == fieldName );
402  }
403 }
404 #endif
405 
407  : mSymbolList( symbolList )
408  , mLayer( layer )
409  , mMapCanvas( 0 )
410 {
411  setupUi( this );
412  setWindowFlags( Qt::WindowStaysOnTopHint );
413  mLabel->setText( label );
414  connect( mDDBtn, SIGNAL( dataDefinedChanged( const QString& ) ), this, SLOT( dataDefinedChanged() ) );
415  connect( mDDBtn, SIGNAL( dataDefinedActivated( bool ) ), this, SLOT( dataDefinedChanged() ) );
416 
417 }
418 
420 {
421  mMapCanvas = canvas;
422  Q_FOREACH ( QgsDataDefinedButton* ddButton, findChildren<QgsDataDefinedButton*>() )
423  {
424  if ( ddButton->assistant() )
425  ddButton->assistant()->setMapCanvas( mMapCanvas );
426  }
427 }
428 
430 {
431  return mMapCanvas;
432 }
433 
434 static QgsExpressionContext _getExpressionContext( const void* context )
435 {
436  const QgsDataDefinedValueDialog* widget = ( const QgsDataDefinedValueDialog* ) context;
437 
438  QgsExpressionContext expContext;
442  if ( widget->mapCanvas() )
443  {
446  }
447  else
448  {
450  }
451 
452  if ( widget->vectorLayer() )
453  expContext << QgsExpressionContextUtils::layerScope( widget->vectorLayer() );
454 
455  return expContext;
456 }
457 
458 void QgsDataDefinedValueDialog::init( const QString & description )
459 {
461  mDDBtn->init( mLayer, &dd, QgsDataDefinedButton::Double, description );
462  mDDBtn->registerGetExpressionContextCallback( &_getExpressionContext, this );
463  mSpinBox->setValue( value( mSymbolList.back() ) );
464  mSpinBox->setEnabled( !mDDBtn->isActive() );
465 }
466 
468 {
469  // check that all symbols share the same size expression
471  Q_FOREACH ( QgsSymbolV2 * it, mSymbolList )
472  {
473  if ( symbolDataDefined( it ) != dd ) return QgsDataDefined();
474  }
475  return dd;
476 }
477 
479 {
480  QgsDataDefined dd = mDDBtn->currentDataDefined();
481  mSpinBox->setEnabled( !dd.isActive() );
482 
483  if ( // shall we remove datadefined expressions for layers ?
484  ( symbolDataDefined().isActive() && !dd.isActive() )
485  // shall we set the "en masse" expression for properties ?
486  || dd.isActive() )
487  {
488  Q_FOREACH ( QgsSymbolV2 * it, mSymbolList )
489  setDataDefined( it, dd );
490  }
491 }
492 
494 {
495  const QgsMarkerSymbolV2* marker = static_cast<const QgsMarkerSymbolV2*>( symbol );
496  return marker->dataDefinedSize();
497 }
498 
500 {
501  static_cast<QgsMarkerSymbolV2*>( symbol )->setDataDefinedSize( dd );
502 }
503 
504 
506 {
507  const QgsMarkerSymbolV2* marker = static_cast<const QgsMarkerSymbolV2*>( symbol );
508  return marker->dataDefinedAngle();
509 }
510 
512 {
513  static_cast<QgsMarkerSymbolV2*>( symbol )->setDataDefinedAngle( dd );
514 }
515 
516 
518 {
519  const QgsLineSymbolV2* line = static_cast<const QgsLineSymbolV2*>( symbol );
520  return line->dataDefinedWidth();
521 }
522 
524 {
525  static_cast<QgsLineSymbolV2*>( symbol )->setDataDefinedWidth( dd );
526 }
double value(const QgsSymbolV2 *symbol) const override
void setText(const QString &text)
Class for parsing and evaluation of expressions (formerly called "search strings").
Definition: qgsexpression.h:92
void showSymbolLevelsDialog(QgsFeatureRendererV2 *r)
show a dialog with renderer's symbol level settings
const QString & name() const
Gets the name of the field.
Definition: qgsfield.cpp:72
virtual QList< QgsSymbolV2 * > selectedSymbols()
Subclasses may provide the capability of changing multiple symbols at once by implementing the follow...
void setupUi(QWidget *widget)
OutputUnit
The unit of the output.
Definition: qgssymbolv2.h:55
void changeSymbolTransparency()
Change opacity of selected symbols.
A container class for data source field mapping or expression.
QString getItem(QWidget *parent, const QString &title, const QString &label, const QStringList &items, int current, bool editable, bool *ok, QFlags< Qt::WindowType > flags, QFlags< Qt::InputMethodHint > inputMethodHints)
void init(const QString &description)
void changeSymbolSize()
Change marker sizes of selected symbols.
void contextMenuViewCategories(const QPoint &p)
static QgsExpressionContextScope * atlasScope(const QgsAtlasComposition *atlas)
Creates a new scope which contains variables and functions relating to a QgsAtlasComposition.
void addActions(QList< QAction * > actions)
void setDataDefined(QgsSymbolV2 *symbol, const QgsDataDefined &dd) override
QgsFields fields() const
Returns the list of fields of this layer.
void setChecked(bool)
void setDataDefined(QgsSymbolV2 *symbol, const QgsDataDefined &dd) override
QgsDataDefined dataDefinedSize() const
Returns data defined size for whole symbol (including all symbol layers).
Calculate scale by the diameter.
Definition: qgssymbolv2.h:81
const T & at(int i) const
void addAction(QAction *action)
QgsMapCanvas * mMapCanvas
Q_DECL_DEPRECATED QgsRendererV2DataDefinedMenus(QMenu *menu, QgsVectorLayer *layer, const QString &rotationField, const QString &sizeScaleField, QgsSymbolV2::ScaleMethod scaleMethod)
const QgsMapSettings & mapSettings() const
Get access to properties used for map rendering.
int exec()
Container of fields for a vector layer.
Definition: qgsfield.h:177
const QgsMapCanvas * mapCanvas() const
Returns the map canvas associated with the widget.
Line symbol.
Definition: qgssymbolv2.h:71
void changeSymbolWidth()
Change line widths of selected symbols.
void populateMenu(QMenu *menu, const QString &fieldName, QActionGroup *actionGroup)
QString tr(const char *sourceText, const char *disambiguation, int n)
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:107
double value(const QgsSymbolV2 *symbol) const override
Marker symbol.
Definition: qgssymbolv2.h:70
int size() const
QgsDataDefined dataDefinedWidth() const
Returns data defined size for whole symbol (including all symbol layers).
The QgsMapSettings class contains configuration for rendering of the map.
QgsDataDefined symbolDataDefined() const
void changeSymbolAngle()
Change marker angles of selected symbols.
Utility classes for "en masse" size definition.
The output shall be in millimeters.
Definition: qgssymbolv2.h:57
QgsVectorLayer * mLayer
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context...
virtual void setMapCanvas(QgsMapCanvas *canvas)
Sets the map canvas associated with the widget.
virtual QgsLegendSymbolList legendSymbolItems(double scaleDenominator=-1, const QString &rule="")
return a list of item text / symbol
void changeSymbolUnit()
Change units mm/map units of selected symbols.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
virtual void setMapCanvas(QgsMapCanvas *canvas)
Sets the map canvas associated with the dialog.
bool isEmpty() const
const QgsMapCanvas * mapCanvas() const
Returns the map canvas associated with the widget.
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
The output shall be in map unitx.
Definition: qgssymbolv2.h:58
void rotationFieldChanged(QString fldName)
void changeSymbolColor()
Change color of selected symbols.
int count() const
Return number of items.
Definition: qgsfield.cpp:311
QGis::GeometryType geometryType() const
Returns point, line or polygon.
double getDouble(QWidget *parent, const QString &title, const QString &label, double value, double min, double max, int decimals, bool *ok, QFlags< Qt::WindowType > flags)
double value(const QgsSymbolV2 *symbol) const override
QAction * addSeparator()
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:40
QgsDataDefinedAssistant * assistant()
Returns the assistant used to defined the data defined object properties, if set. ...
Single scope for storing variables and functions for use within a QgsExpressionContext.
QAction * exec()
void scaleMethodChanged(QgsSymbolV2::ScaleMethod scaleMethod)
virtual double value(const QgsSymbolV2 *) const =0
A button for defining data source field mappings or expressions.
iterator end()
QgsRendererV2Widget(QgsVectorLayer *layer, QgsStyleV2 *style)
void setShortcut(const QKeySequence &shortcut)
void setDataDefined(QgsSymbolV2 *symbol, const QgsDataDefined &dd) override
void setCheckable(bool)
void setUsingSymbolLevels(bool usingSymbolLevels)
QString & replace(int position, int n, QChar after)
QList< QgsSymbolV2 * > mSymbolList
const QgsVectorLayer * vectorLayer() const
Returns the vector layer associated with the widget.
void setWindowFlags(QFlags< Qt::WindowType > type)
QList< QAction * > actions() const
static QColor getColor(const QColor &initialColor, QWidget *parent, const QString &title=QString(), const bool allowAlpha=false)
Return a color selection from a color dialog.
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:429
QgsDataDefined dataDefinedAngle() const
Returns data defined angle for whole symbol (including all symbol layers).
QPoint pos()
ScaleMethod
Scale method.
Definition: qgssymbolv2.h:78
virtual void setDataDefined(QgsSymbolV2 *symbol, const QgsDataDefined &dd)=0
void sizeScaleFieldChanged(QString fldName)
bool usingSymbolLevels() const
Calculate scale by the area.
Definition: qgssymbolv2.h:80
static QgsExpressionContextScope * projectScope()
Creates a new scope which contains variables and functions relating to the current QGIS project...
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
virtual void refreshSymbolView()
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
Represents a vector layer which manages a vector based data sets.
int compare(const QString &other) const
bool isActive() const
T & back()
iterator begin()
A generic dialog for building expression strings.
virtual void setMapCanvas(QgsMapCanvas *canvas)
Sets the map canvas associated with the widget.
static QgsExpressionContext _getExpressionContext(const void *context)
QgsDataDefinedValueDialog(const QList< QgsSymbolV2 * > &symbolList, QgsVectorLayer *layer, const QString &label)
Constructor.
bool isValid() const
QVariant::Type type() const
Gets variant type of the field as it will be retrieved from data source.
Definition: qgsfield.cpp:77