QGIS API Documentation  2.10.1-Pisa
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 
22 #include <QMessageBox>
23 #include <QInputDialog>
24 #include <QMenu>
25 
27  : QWidget(), mLayer( layer ), mStyle( style )
28 {
29  contextMenu = new QMenu( "Renderer Options " );
30 
31  mCopyAction = contextMenu->addAction( tr( "Copy" ), this, SLOT( copy() ) );
32  mCopyAction->setShortcut( QKeySequence( QKeySequence::Copy ) );
33  mPasteAction = contextMenu->addAction( tr( "Paste" ), this, SLOT( paste() ) );
34  mPasteAction->setShortcut( QKeySequence( QKeySequence::Paste ) );
35 
37  contextMenu->addAction( tr( "Change color" ), this, SLOT( changeSymbolColor() ) );
38  contextMenu->addAction( tr( "Change transparency" ), this, SLOT( changeSymbolTransparency() ) );
39  contextMenu->addAction( tr( "Change output unit" ), this, SLOT( changeSymbolUnit() ) );
40 
41  if ( mLayer && mLayer->geometryType() == QGis::Line )
42  {
43  contextMenu->addAction( tr( "Change width" ), this, SLOT( changeSymbolWidth() ) );
44  }
45  else if ( mLayer && mLayer->geometryType() == QGis::Point )
46  {
47  contextMenu->addAction( tr( "Change size" ), this, SLOT( changeSymbolSize() ) );
48  contextMenu->addAction( tr( "Change angle" ), this, SLOT( changeSymbolAngle() ) );
49  }
50 }
51 
53 {
55 }
56 
58 {
59  QList<QgsSymbolV2*> symbolList = selectedSymbols();
60  if ( symbolList.size() < 1 )
61  {
62  return;
63  }
64 
65  QColor color = QgsColorDialogV2::getColor( symbolList.at( 0 )->color(), this, "Change Symbol Color", true );
66  if ( color.isValid() )
67  {
68  QList<QgsSymbolV2*>::iterator symbolIt = symbolList.begin();
69  for ( ; symbolIt != symbolList.end(); ++symbolIt )
70  {
71  ( *symbolIt )->setColor( color );
72  }
74  }
75 }
76 
78 {
79  QList<QgsSymbolV2*> symbolList = selectedSymbols();
80  if ( symbolList.size() < 1 )
81  {
82  return;
83  }
84 
85  bool ok;
86  double oldTransparency = ( 1 - symbolList.at( 0 )->alpha() ) * 100; // convert to percents
87  double transparency = QInputDialog::getDouble( this, tr( "Transparency" ), tr( "Change symbol transparency [%]" ), oldTransparency, 0.0, 100.0, 0, &ok );
88  if ( ok )
89  {
90  QList<QgsSymbolV2*>::iterator symbolIt = symbolList.begin();
91  for ( ; symbolIt != symbolList.end(); ++symbolIt )
92  {
93  ( *symbolIt )->setAlpha( 1 - transparency / 100 );
94  }
96  }
97 }
98 
100 {
101  QList<QgsSymbolV2*> symbolList = selectedSymbols();
102  if ( symbolList.size() < 1 )
103  {
104  return;
105  }
106 
107  bool ok;
108  int currentUnit = ( symbolList.at( 0 )->outputUnit() == QgsSymbolV2::MM ) ? 0 : 1;
109  QString item = QInputDialog::getItem( this, tr( "Symbol unit" ), tr( "Select symbol unit" ), QStringList() << tr( "Millimeter" ) << tr( "Map unit" ), currentUnit, false, &ok );
110  if ( ok )
111  {
112  QgsSymbolV2::OutputUnit unit = ( item.compare( tr( "Millimeter" ) ) == 0 ) ? QgsSymbolV2::MM : QgsSymbolV2::MapUnit;
113 
114  QList<QgsSymbolV2*>::iterator symbolIt = symbolList.begin();
115  for ( ; symbolIt != symbolList.end(); ++symbolIt )
116  {
117  ( *symbolIt )->setOutputUnit( unit );
118  }
120  }
121 }
122 
124 {
125  QList<QgsSymbolV2*> symbolList = selectedSymbols();
126  if ( symbolList.size() < 1 )
127  {
128  return;
129  }
130 
131  QgsDataDefinedWidthDialog dlg( symbolList, mLayer );
132 
133  if ( QDialog::Accepted == dlg.exec() )
134  {
135  if ( !dlg.mDDBtn->isActive() )
136  {
137  QList<QgsSymbolV2*>::iterator symbolIt = symbolList.begin();
138  for ( ; symbolIt != symbolList.end(); ++symbolIt )
139  {
140  if (( *symbolIt )->type() == QgsSymbolV2::Line )
141  static_cast<QgsLineSymbolV2*>( *symbolIt )->setWidth( dlg.mSpinBox->value() );
142  }
143  }
145  }
146 }
147 
149 {
150  QList<QgsSymbolV2*> symbolList = selectedSymbols();
151  if ( symbolList.size() < 1 )
152  {
153  return;
154  }
155 
156  QgsDataDefinedSizeDialog dlg( symbolList, mLayer );
157 
158  if ( QDialog::Accepted == dlg.exec() )
159  {
160  if ( !dlg.mDDBtn->isActive() )
161  {
162  QList<QgsSymbolV2*>::iterator symbolIt = symbolList.begin();
163  for ( ; symbolIt != symbolList.end(); ++symbolIt )
164  {
165  if (( *symbolIt )->type() == QgsSymbolV2::Marker )
166  static_cast<QgsMarkerSymbolV2*>( *symbolIt )->setSize( dlg.mSpinBox->value() );
167  }
168  }
170  }
171 }
172 
174 {
175  QList<QgsSymbolV2*> symbolList = selectedSymbols();
176  if ( symbolList.size() < 1 )
177  {
178  return;
179  }
180 
181  QgsDataDefinedRotationDialog dlg( symbolList, mLayer );
182 
183  if ( QDialog::Accepted == dlg.exec() )
184  {
185  if ( !dlg.mDDBtn->isActive() )
186  {
187  QList<QgsSymbolV2*>::iterator symbolIt = symbolList.begin();
188  for ( ; symbolIt != symbolList.end(); ++symbolIt )
189  {
190  if (( *symbolIt )->type() == QgsSymbolV2::Marker )
191  static_cast<QgsMarkerSymbolV2*>( *symbolIt )->setAngle( dlg.mSpinBox->value() );
192  }
193  }
195  }
196 }
197 
199 {
200  QgsLegendSymbolList symbols = r->legendSymbolItems();
201 
202  QgsSymbolLevelsV2Dialog dlg( symbols, r->usingSymbolLevels(), this );
203 
204  if ( dlg.exec() )
205  {
206  r->setUsingSymbolLevels( dlg.usingLevels() );
207  }
208 }
209 
210 
212 
213 #include "qgsfield.h"
214 
216  : QObject( menu ), mLayer( layer )
217 {
218  mRotationMenu = new QMenu( tr( "Rotation field" ) );
219  mSizeScaleMenu = new QMenu( tr( "Size scale field" ) );
220 
224 
227 
229 
230  QAction* aScaleByArea = new QAction( tr( "Scale area" ), mSizeMethodActionGroup );
231  QAction* aScaleByDiameter = new QAction( tr( "Scale diameter" ), mSizeMethodActionGroup );
232 
233  aScaleByArea->setCheckable( true );
234  aScaleByDiameter->setCheckable( true );
235 
236  if ( scaleMethod == QgsSymbolV2::ScaleDiameter )
237  {
238  aScaleByDiameter->setChecked( true );
239  }
240  else
241  {
242  aScaleByArea->setChecked( true );
243  }
244 
246 
247  //@todo cleanup the class since Rotation and SizeScale are now
248  //defined using QgsDataDefinedButton
249  //
250  //menu->addMenu( mRotationMenu );
251  //menu->addMenu( mSizeScaleMenu );
252 
253  connect( mSizeMethodActionGroup, SIGNAL( triggered( QAction* ) ), this, SLOT( scaleMethodSelected( QAction* ) ) );
254  connect( mRotationAttributeActionGroup, SIGNAL( triggered( QAction* ) ), this, SLOT( rotationFieldSelected( QAction* ) ) );
255  connect( mSizeAttributeActionGroup, SIGNAL( triggered( QAction* ) ), this, SLOT( sizeScaleFieldSelected( QAction* ) ) );
256 }
257 
259 {
260  delete mSizeMethodActionGroup;
263  delete mRotationMenu;
264  delete mSizeScaleMenu;
265 }
266 
268 {
269  QAction* aExpr = new QAction( tr( "- expression -" ), actionGroup );
270  aExpr->setCheckable( true );
271  menu->addAction( aExpr );
272  menu->addSeparator();
273  QAction* aNo = new QAction( tr( "- no field -" ), actionGroup );
274  aNo->setCheckable( true );
275  menu->addAction( aNo );
276  menu->addSeparator();
277 
278  bool hasField = false;
279  const QgsFields & flds = mLayer->pendingFields();
280  for ( int idx = 0; idx < flds.count(); ++idx )
281  {
282  const QgsField& fld = flds[idx];
283  if ( fld.type() == QVariant::Int || fld.type() == QVariant::Double )
284  {
285  QAction* a = new QAction( fld.name(), actionGroup );
286  a->setCheckable( true );
287  if ( fieldName == fld.name() )
288  {
289  a->setChecked( true );
290  hasField = true;
291  }
292  menu->addAction( a );
293  }
294  }
295 
296  if ( !hasField )
297  {
298  if ( fieldName.isEmpty() )
299  {
300  aNo->setChecked( true );
301  }
302  else
303  {
304  aExpr->setChecked( true );
305  aExpr->setText( tr( "- expression -" ) + fieldName );
306  }
307  }
308 
309 }
310 
312 {
313  if ( a == NULL )
314  return;
315 
316  QString fldName = a->text();
317 #if 0
318  updateMenu( mRotationAttributeActionGroup, fldName );
319 #endif
320  if ( fldName == tr( "- no field -" ) )
321  {
322  fldName = QString();
323  }
324  else if ( fldName.startsWith( tr( "- expression -" ) ) )
325  {
326  QString expr( fldName );
327  expr.replace( 0, tr( "- expression -" ).length(), "" );
328  QgsExpressionBuilderDialog dialog( mLayer, expr );
329  if ( !dialog.exec() ) return;
330  fldName = dialog.expressionText();
331  Q_ASSERT( !QgsExpression( fldName ).hasParserError() );
332  a->setText( tr( "- expression -" ) + fldName );
333  }
334 
335  emit rotationFieldChanged( fldName );
336 }
337 
339 {
340  if ( a == NULL )
341  return;
342 
343  QString fldName = a->text();
344 #if 0
345  updateMenu( mSizeAttributeActionGroup, fldName );
346 #endif
347  if ( fldName == tr( "- no field -" ) )
348  {
349  fldName = QString();
350  }
351  else if ( fldName.startsWith( tr( "- expression -" ) ) )
352  {
353  QString expr( fldName );
354  expr.replace( 0, tr( "- expression -" ).length(), "" );
355  QgsExpressionBuilderDialog dialog( mLayer, expr );
356  if ( !dialog.exec() ) return;
357  fldName = dialog.expressionText();
358  Q_ASSERT( !QgsExpression( fldName ).hasParserError() );
359  a->setText( tr( "- expression -" ) + fldName );
360  }
361 
362  emit sizeScaleFieldChanged( fldName );
363 }
364 
366 {
367  if ( a == NULL )
368  return;
369 
370  if ( a->text() == tr( "Scale area" ) )
371  {
373  }
374  else if ( a->text() == tr( "Scale diameter" ) )
375  {
377  }
378 }
379 #if 0 // MK: is there any reason for this?
380 void QgsRendererV2DataDefinedMenus::updateMenu( QActionGroup* actionGroup, QString fieldName )
381 {
382  foreach ( QAction* a, actionGroup->actions() )
383  {
384  a->setChecked( a->text() == fieldName );
385  }
386 }
387 #endif
388 
390  : mSymbolList( symbolList )
391  , mLayer( layer )
392 {
393  setupUi( this );
394  setWindowFlags( Qt::WindowStaysOnTopHint );
395  mLabel->setText( label );
396  connect( mDDBtn, SIGNAL( dataDefinedChanged( const QString& ) ), this, SLOT( dataDefinedChanged() ) );
397  connect( mDDBtn, SIGNAL( dataDefinedActivated( bool ) ), this, SLOT( dataDefinedChanged() ) );
398 
399 }
400 
401 void QgsDataDefinedValueDialog::init( const QString & description )
402 {
404  mDDBtn->init( mLayer, &dd, QgsDataDefinedButton::Double, description );
405  mSpinBox->setValue( value( mSymbolList.back() ) );
406  mSpinBox->setEnabled( !mDDBtn->isActive() );
407 }
408 
410 {
411  // check that all symbols share the same size expression
413  foreach ( QgsSymbolV2 * it, mSymbolList )
414  {
415  if ( symbolDataDefined( it ) != dd ) return QgsDataDefined();
416  }
417  return dd;
418 }
419 
421 {
422  QgsDataDefined dd = mDDBtn->currentDataDefined();
423  mSpinBox->setEnabled( !dd.isActive() );
424 
425  if ( // shall we remove datadefined expressions for layers ?
426  ( symbolDataDefined().isActive() && !dd.isActive() )
427  // shall we set the "en masse" expression for properties ?
428  || dd.isActive() )
429  {
430  foreach ( QgsSymbolV2 * it, mSymbolList )
431  setDataDefined( it, dd );
432  }
433 }
434 
436 {
437  const QgsMarkerSymbolV2* marker = static_cast<const QgsMarkerSymbolV2*>( symbol );
438  return marker->dataDefinedSize();
439 }
440 
442 {
443  static_cast<QgsMarkerSymbolV2*>( symbol )->setDataDefinedSize( dd );
444 }
445 
446 
448 {
449  const QgsMarkerSymbolV2* marker = static_cast<const QgsMarkerSymbolV2*>( symbol );
450  return marker->dataDefinedAngle();
451 }
452 
454 {
455  static_cast<QgsMarkerSymbolV2*>( symbol )->setDataDefinedAngle( dd );
456 }
457 
458 
460 {
461  const QgsLineSymbolV2* line = static_cast<const QgsLineSymbolV2*>( symbol );
462  return line->dataDefinedWidth();
463 }
464 
466 {
467  static_cast<QgsLineSymbolV2*>( symbol )->setDataDefinedWidth( dd );
468 }
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:86
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:69
virtual QList< QgsSymbolV2 * > selectedSymbols()
Subclasses may provide the capability of changing multiple symbols at once by implementing the follow...
void setupUi(QWidget *widget)
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)
void addActions(QList< QAction * > actions)
void setDataDefined(QgsSymbolV2 *symbol, const QgsDataDefined &dd) override
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).
const T & at(int i) const
void addAction(QAction *action)
virtual QgsLegendSymbolList legendSymbolItems(double scaleDenominator=-1, QString rule="")
return a list of item text / symbol
int exec()
Container of fields for a vector layer.
Definition: qgsfield.h:173
void populateMenu(QMenu *menu, QString fieldName, QActionGroup *actionGroup)
void changeSymbolWidth()
Change line widths of selected symbols.
QString tr(const char *sourceText, const char *disambiguation, int n)
double value(const QgsSymbolV2 *symbol) const override
int size() const
QgsDataDefined dataDefinedWidth() const
Returns data defined size for whole symbol (including all symbol layers).
QgsDataDefined symbolDataDefined() const
void changeSymbolAngle()
Change marker angles of selected symbols.
QgsVectorLayer * mLayer
void changeSymbolUnit()
Change units mm/map units of selected symbols.
bool isEmpty() const
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
void rotationFieldChanged(QString fldName)
void changeSymbolColor()
Change color of selected symbols.
int count() const
Return number of items.
Definition: qgsfield.cpp:283
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:38
QAction * exec()
void scaleMethodChanged(QgsSymbolV2::ScaleMethod scaleMethod)
virtual double value(const QgsSymbolV2 *) const =0
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
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.
QgsDataDefined dataDefinedAngle() const
Returns data defined angle for whole symbol (including all symbol layers).
QPoint pos()
virtual void setDataDefined(QgsSymbolV2 *symbol, const QgsDataDefined &dd)=0
void sizeScaleFieldChanged(QString fldName)
bool usingSymbolLevels() const
const QgsFields & pendingFields() const
returns field list in the to-be-committed state
virtual void refreshSymbolView()
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QgsRendererV2DataDefinedMenus(QMenu *menu, QgsVectorLayer *layer, QString rotationField, QString sizeScaleField, QgsSymbolV2::ScaleMethod scaleMethod)
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.
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:74