QGIS API Documentation  2.15.0-Master (94d88e6)
qgsrendererv2propertiesdialog.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsrendererv2propertiesdialog.cpp
3  ---------------------
4  begin : December 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  ***************************************************************************/
16 
17 #include "qgsrendererv2.h"
18 #include "qgsrendererv2registry.h"
19 
20 #include "qgsrendererv2widget.h"
28 #include "qgs25drendererwidget.h"
30 
31 #include "qgsorderbydialog.h"
32 #include "qgsapplication.h"
33 #include "qgslogger.h"
34 #include "qgsvectorlayer.h"
35 
36 #include <QKeyEvent>
37 #include <QMessageBox>
38 
39 static bool _initRenderer( const QString& name, QgsRendererV2WidgetFunc f, const QString& iconName = QString() )
40 {
43  if ( !am )
44  return false;
45  QgsRendererV2Metadata* m = dynamic_cast<QgsRendererV2Metadata*>( am );
46  if ( !m )
47  return false;
48 
49  m->setWidgetFunction( f );
50 
51  if ( !iconName.isEmpty() )
52  {
54  QPixmap pix;
55  if ( pix.load( iconPath ) )
56  m->setIcon( pix );
57  }
58 
59  QgsDebugMsg( "Set for " + name );
60  return true;
61 }
62 
64 {
65  static bool initialized = false;
66  if ( initialized )
67  return;
68 
69  _initRenderer( "singleSymbol", QgsSingleSymbolRendererV2Widget::create, "rendererSingleSymbol.svg" );
70  _initRenderer( "categorizedSymbol", QgsCategorizedSymbolRendererV2Widget::create, "rendererCategorizedSymbol.svg" );
71  _initRenderer( "graduatedSymbol", QgsGraduatedSymbolRendererV2Widget::create, "rendererGraduatedSymbol.svg" );
72  _initRenderer( "RuleRenderer", QgsRuleBasedRendererV2Widget::create, "rendererRuleBasedSymbol.svg" );
73  _initRenderer( "pointDisplacement", QgsPointDisplacementRendererWidget::create, "rendererPointDisplacementSymbol.svg" );
74  _initRenderer( "invertedPolygonRenderer", QgsInvertedPolygonRendererWidget::create, "rendererInvertedSymbol.svg" );
75  _initRenderer( "heatmapRenderer", QgsHeatmapRendererWidget::create, "rendererHeatmapSymbol.svg" );
76  _initRenderer( "25dRenderer", Qgs25DRendererWidget::create, "renderer25dSymbol.svg" );
77  _initRenderer( "nullSymbol", QgsNullSymbolRendererWidget::create, "rendererNullSymbol.svg" );
78  initialized = true;
79 }
80 
82  : mLayer( layer )
83  , mStyle( style )
84  , mActiveWidget( nullptr )
85  , mPaintEffect( nullptr )
86  , mMapCanvas( nullptr )
87 {
88  setupUi( this );
89 
90  // can be embedded in vector layer properties
91  if ( embedded )
92  {
93  buttonBox->hide();
94  layout()->setContentsMargins( 0, 0, 0, 0 );
95  }
96 
97 
98  connect( buttonBox, SIGNAL( accepted() ), this, SLOT( onOK() ) );
99 
100  // initialize registry's widget functions
102 
103  // Blend mode
104  mBlendModeComboBox->setBlendMode( mLayer->blendMode() );
105 
106  // Feature blend mode
107  mFeatureBlendComboBox->setBlendMode( mLayer->featureBlendMode() );
108 
109  // Layer transparency
110  mLayerTransparencySlider->setValue( mLayer->layerTransparency() );
111  mLayerTransparencySpnBx->setValue( mLayer->layerTransparency() );
112 
113  // connect layer transparency slider and spin box
114  connect( mLayerTransparencySlider, SIGNAL( valueChanged( int ) ), mLayerTransparencySpnBx, SLOT( setValue( int ) ) );
115  connect( mLayerTransparencySpnBx, SIGNAL( valueChanged( int ) ), mLayerTransparencySlider, SLOT( setValue( int ) ) );
116 
117  //paint effect widget
118  if ( mLayer->rendererV2() )
119  {
120  if ( mLayer->rendererV2()->paintEffect() )
121  {
123  mEffectWidget->setPaintEffect( mPaintEffect );
124  }
125 
127  }
128 
130  QStringList renderers = reg->renderersList();
131  Q_FOREACH ( const QString& name, renderers )
132  {
134  cboRenderers->addItem( m->icon(), m->visibleName(), name );
135  }
136 
137  cboRenderers->setCurrentIndex( -1 ); // set no current renderer
138 
139  // setup slot rendererChanged()
140  connect( cboRenderers, SIGNAL( currentIndexChanged( int ) ), this, SLOT( rendererChanged() ) );
141  //setup order by
142  if ( mLayer->rendererV2()->orderByEnabled() )
143  {
144  checkboxEnableOrderBy->setChecked( true );
145  }
146  else
147  {
148  btnOrderBy->setEnabled( false );
149  checkboxEnableOrderBy->setChecked( false );
150  lineEditOrderBy->setEnabled( false );
151  }
152  lineEditOrderBy->setReadOnly( true );
153  connect( checkboxEnableOrderBy, SIGNAL( toggled( bool ) ), btnOrderBy, SLOT( setEnabled( bool ) ) );
154  connect( checkboxEnableOrderBy, SIGNAL( toggled( bool ) ), lineEditOrderBy, SLOT( setEnabled( bool ) ) );
155  connect( btnOrderBy, SIGNAL( clicked( bool ) ), this, SLOT( showOrderByDialog() ) );
156  lineEditOrderBy->setText( mOrderBy.dump() );
157 
158  // set current renderer from layer
159  QString rendererName = mLayer->rendererV2()->type();
160 
161  int rendererIdx = cboRenderers->findData( rendererName );
162  cboRenderers->setCurrentIndex( rendererIdx );
163 
164  // no renderer found... this mustn't happen
165  Q_ASSERT( rendererIdx != -1 && "there must be a renderer!" );
166  connectValueChanged( findChildren<QWidget*>(), SIGNAL( widgetChanged() ) );
167 }
168 
170 {
171  Q_FOREACH ( QWidget* widget, widgets )
172  {
173  if ( QgsDataDefinedButton* w = qobject_cast<QgsDataDefinedButton*>( widget ) )
174  {
175  connect( w, SIGNAL( dataDefinedActivated( bool ) ), this, slot );
176  connect( w, SIGNAL( dataDefinedChanged( QString ) ), this, slot );
177  }
178  else if ( QgsFieldExpressionWidget* w = qobject_cast<QgsFieldExpressionWidget*>( widget ) )
179  {
180  connect( w, SIGNAL( fieldChanged( QString ) ), this, slot );
181  }
182  else if ( QComboBox* w = qobject_cast<QComboBox*>( widget ) )
183  {
184  connect( w, SIGNAL( currentIndexChanged( int ) ), this, slot );
185  }
186  else if ( QSpinBox* w = qobject_cast<QSpinBox*>( widget ) )
187  {
188  connect( w, SIGNAL( valueChanged( int ) ), this, slot );
189  }
190  else if ( QDoubleSpinBox* w = qobject_cast<QDoubleSpinBox*>( widget ) )
191  {
192  connect( w , SIGNAL( valueChanged( double ) ), this, slot );
193  }
194  else if ( QgsColorButtonV2* w = qobject_cast<QgsColorButtonV2*>( widget ) )
195  {
196  connect( w, SIGNAL( colorChanged( QColor ) ), this, slot );
197  }
198  else if ( QCheckBox* w = qobject_cast<QCheckBox*>( widget ) )
199  {
200  connect( w, SIGNAL( toggled( bool ) ), this, slot );
201  }
202  else if ( QLineEdit* w = qobject_cast<QLineEdit*>( widget ) )
203  {
204  connect( w, SIGNAL( textEdited( QString ) ), this, slot );
205  }
206  }
207 }
208 
210 {
211  delete mPaintEffect;
212 }
213 
215 {
216  mMapCanvas = canvas;
217  if ( mActiveWidget )
219 }
220 
221 
223 {
224 
225  if ( cboRenderers->currentIndex() == -1 )
226  {
227  QgsDebugMsg( "No current item -- this should never happen!" );
228  return;
229  }
230 
231  QString rendererName = cboRenderers->itemData( cboRenderers->currentIndex() ).toString();
232 
233  //Retrieve the previous renderer: from the old active widget if possible, otherwise from the layer
234  QgsFeatureRendererV2* oldRenderer;
236  {
237  oldRenderer = mActiveWidget->renderer()->clone();
238  }
239  else
240  {
241  oldRenderer = mLayer->rendererV2()->clone();
242  }
243 
244  // get rid of old active widget (if any)
245  if ( mActiveWidget )
246  {
247  stackedWidget->removeWidget( mActiveWidget );
248 
249  delete mActiveWidget;
250  mActiveWidget = nullptr;
251  }
252 
253  QgsRendererV2Widget* w = nullptr;
255  if ( m )
256  w = m->createRendererWidget( mLayer, mStyle, oldRenderer );
257  delete oldRenderer;
258 
259  if ( w )
260  {
261  // instantiate the widget and set as active
262  mActiveWidget = w;
263  stackedWidget->addWidget( mActiveWidget );
264  stackedWidget->setCurrentWidget( mActiveWidget );
265  if ( mActiveWidget->renderer() )
266  {
267  if ( mMapCanvas )
269  changeOrderBy( mActiveWidget->renderer()->orderBy(), mActiveWidget->renderer()->orderByEnabled() );
270  connect( mActiveWidget, SIGNAL( layerVariablesChanged() ), this, SIGNAL( layerVariablesChanged() ) );
271  }
272  connect( mActiveWidget, SIGNAL( widgetChanged() ), this, SIGNAL( widgetChanged() ) );
273  }
274  else
275  {
276  // set default "no edit widget available" page
277  stackedWidget->setCurrentWidget( pageNoWidget );
278  }
279 }
280 
282 {
283  if ( !mActiveWidget || !mLayer )
284  {
285  return;
286  }
287 
289 
291  if ( renderer )
292  {
293  renderer->setPaintEffect( mPaintEffect->clone() );
294  // set the order by
295  renderer->setOrderBy( mOrderBy );
296  renderer->setOrderByEnabled( checkboxEnableOrderBy->isChecked() );
297 
298  mLayer->setRendererV2( renderer->clone() );
299  }
300 
301  // set the blend modes for the layer
302  mLayer->setBlendMode( mBlendModeComboBox->blendMode() );
303  mLayer->setFeatureBlendMode( mFeatureBlendComboBox->blendMode() );
304 
305  // set transparency for the layer
306  mLayer->setLayerTransparency( mLayerTransparencySlider->value() );
307 }
308 
310 {
311  apply();
312  accept();
313 }
314 
315 void QgsRendererV2PropertiesDialog::showOrderByDialog()
316 {
317  QgsOrderByDialog dlg( mLayer, this );
318 
319  dlg.setOrderBy( mOrderBy );
320  if ( dlg.exec() )
321  {
322  mOrderBy = dlg.orderBy();
323  lineEditOrderBy->setText( mOrderBy.dump() );
324  }
325 }
326 
327 void QgsRendererV2PropertiesDialog::changeOrderBy( const QgsFeatureRequest::OrderBy& orderBy, bool orderByEnabled )
328 {
329  mOrderBy = orderBy;
330  lineEditOrderBy->setText( mOrderBy.dump() );
331  checkboxEnableOrderBy->setChecked( orderByEnabled );
332 }
333 
334 
336 {
337  // Ignore the ESC key to avoid close the dialog without the properties window
338  if ( !isWindow() && e->key() == Qt::Key_Escape )
339  {
340  e->ignore();
341  }
342  else
343  {
345  }
346 }
QLayout * layout() const
void setMapCanvas(QgsMapCanvas *canvas)
Sets the map canvas associated with the dialog.
The QgsFieldExpressionWidget class reates a widget to choose fields and edit expressions It contains ...
static QgsRendererV2Registry * instance()
This is a dialog to build and manage a list of order by clauses.
void setContentsMargins(int left, int top, int right, int bottom)
void setupUi(QWidget *widget)
A cross platform button subclass for selecting colors.
void setOrderBy(const QgsFeatureRequest::OrderBy &orderBy)
Set the order by to manage.
QgsFeatureRequest::OrderBy orderBy() const
Get the order in which features shall be processed by this renderer.
static QString defaultThemePath()
Returns the path to the default theme directory.
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
bool orderByEnabled() const
Returns whether custom ordering will be applied before features are processed by this renderer...
void setRendererV2(QgsFeatureRendererV2 *r)
Set renderer which will be invoked to represent this layer.
void connectValueChanged(QList< QWidget * > widgets, const char *slot)
Connect the given slot to the value changed event for the set of widgets Each widget is checked for t...
void setFeatureBlendMode(QPainter::CompositionMode blendMode)
Set the blending mode used for rendering each feature.
static QgsRendererV2Widget * create(QgsVectorLayer *layer, QgsStyleV2 *style, QgsFeatureRendererV2 *renderer)
void accepted()
int exec()
void setLayerTransparency(int layerTransparency)
Set the transparency for the vector layer.
Stores metadata about one renderer class.
QString iconPath(const QString &iconFile)
void setBlendMode(QPainter::CompositionMode blendMode)
Set the blending mode used for rendering a layer.
Registry of renderers.
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:108
QgsRendererV2AbstractMetadata * rendererMetadata(const QString &rendererName)
get metadata for particular renderer. Returns NULL if not found in registry.
virtual QgsPaintEffect * clone() const =0
Duplicates an effect by creating a deep copy of the effect.
void setIcon(const QIcon &icon)
static void _initRendererWidgetFunctions()
QString type() const
Definition: qgsrendererv2.h:86
void setWidgetFunction(QgsRendererV2WidgetFunc f)
QString CORE_EXPORT dump() const
Dumps the content to an SQL equivalent syntax.
const char * name() const
virtual QgsFeatureRendererV2 * clone() const =0
QgsFeatureRendererV2 * rendererV2()
Return renderer V2.
void setEnabled(bool)
QPainter::CompositionMode blendMode() const
Returns the current blending mode for a layer.
void ignore()
QPainter::CompositionMode featureBlendMode() const
Returns the current blending mode for features.
QStringList renderersList()
return a list of available renderers
void layerVariablesChanged()
Emitted when expression context variables on the associated vector layers have been changed...
static QgsRendererV2Widget * create(QgsVectorLayer *layer, QgsStyleV2 *style, QgsFeatureRendererV2 *renderer)
void setOrderByEnabled(bool enabled)
Sets whether custom ordering should be applied before features are processed by this renderer...
void setPaintEffect(QgsPaintEffect *effect)
Sets the current paint effect for the renderer.
static QgsRendererV2Widget * create(QgsVectorLayer *layer, QgsStyleV2 *style, QgsFeatureRendererV2 *renderer)
void applyChanges()
This method should be called whenever the renderer is actually set on the layer.
bool load(const QString &fileName, const char *format, QFlags< Qt::ImageConversionFlag > flags)
static QgsRendererV2Widget * create(QgsVectorLayer *layer, QgsStyleV2 *style, QgsFeatureRendererV2 *renderer)
virtual void accept()
bool isWindow() const
A button for defining data source field mappings or expressions.
QgsRendererV2PropertiesDialog(QgsVectorLayer *layer, QgsStyleV2 *style, bool embedded=false)
int key() const
static bool _initRenderer(const QString &name, QgsRendererV2WidgetFunc f, const QString &iconName=QString())
static QgsRendererV2Widget * create(QgsVectorLayer *layer, QgsStyleV2 *style, QgsFeatureRendererV2 *renderer)
Static creation method.
void rendererChanged()
called when user changes renderer type
int layerTransparency() const
Returns the current transparency for the vector layer.
void onOK()
Apply and accept the changes for the dialog.
virtual void keyPressEvent(QKeyEvent *e)
static QgsRendererV2Widget * create(QgsVectorLayer *layer, QgsStyleV2 *style, QgsFeatureRendererV2 *renderer)
Creates a new QgsNullSymbolRendererWidget object.
static QgsRendererV2Widget * create(QgsVectorLayer *layer, QgsStyleV2 *style, QgsFeatureRendererV2 *renderer)
Static creation method.
void setOrderBy(const QgsFeatureRequest::OrderBy &orderBy)
Define the order in which features shall be processed by this renderer.
Convenience metadata class that uses static functions to create renderer and its widget.
void keyPressEvent(QKeyEvent *event) override
Reimplements dialog keyPress event so we can ignore it.
void widgetChanged()
Emmited when something on the widget has changed.
virtual QgsRendererV2Widget * createRendererWidget(QgsVectorLayer *layer, QgsStyleV2 *style, QgsFeatureRendererV2 *oldRenderer)
Return new instance of settings widget for the renderer.
QgsPaintEffect * paintEffect() const
Returns the current paint effect for the renderer.
Base class for renderer settings widgets.
static QgsRendererV2Widget * create(QgsVectorLayer *layer, QgsStyleV2 *style, QgsFeatureRendererV2 *renderer)
QgsFeatureRequest::OrderBy orderBy()
Get the order by defined in the dialog.
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void apply()
Apply the changes from the dialog to the layer.
Represents a vector layer which manages a vector based data sets.
virtual QgsFeatureRendererV2 * renderer()=0
return pointer to the renderer (no transfer of ownership)
QgsRendererV2Widget *(* QgsRendererV2WidgetFunc)(QgsVectorLayer *, QgsStyleV2 *, QgsFeatureRendererV2 *)
virtual void setMapCanvas(QgsMapCanvas *canvas)
Sets the map canvas associated with the widget.
Represents a list of OrderByClauses, with the most important first and the least important last...
static QgsRendererV2Widget * create(QgsVectorLayer *layer, QgsStyleV2 *style, QgsFeatureRendererV2 *renderer)
Static creation method.