QGIS API Documentation  2.17.0-Master (872e6d2)
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 #include "qgspanelwidget.h"
31 
32 #include "qgsorderbydialog.h"
33 #include "qgsapplication.h"
34 #include "qgslogger.h"
35 #include "qgsvectorlayer.h"
36 
37 #include <QKeyEvent>
38 #include <QMessageBox>
39 
40 static bool _initRenderer( const QString& name, QgsRendererV2WidgetFunc f, const QString& iconName = QString() )
41 {
44  if ( !am )
45  return false;
46  QgsRendererV2Metadata* m = dynamic_cast<QgsRendererV2Metadata*>( am );
47  if ( !m )
48  return false;
49 
50  m->setWidgetFunction( f );
51 
52  if ( !iconName.isEmpty() )
53  {
55  QPixmap pix;
56  if ( pix.load( iconPath ) )
57  m->setIcon( pix );
58  }
59 
60  QgsDebugMsg( "Set for " + name );
61  return true;
62 }
63 
65 {
66  static bool initialized = false;
67  if ( initialized )
68  return;
69 
70  _initRenderer( "singleSymbol", QgsSingleSymbolRendererV2Widget::create, "rendererSingleSymbol.svg" );
71  _initRenderer( "categorizedSymbol", QgsCategorizedSymbolRendererV2Widget::create, "rendererCategorizedSymbol.svg" );
72  _initRenderer( "graduatedSymbol", QgsGraduatedSymbolRendererV2Widget::create, "rendererGraduatedSymbol.svg" );
73  _initRenderer( "RuleRenderer", QgsRuleBasedRendererV2Widget::create, "rendererRuleBasedSymbol.svg" );
74  _initRenderer( "pointDisplacement", QgsPointDisplacementRendererWidget::create, "rendererPointDisplacementSymbol.svg" );
75  _initRenderer( "invertedPolygonRenderer", QgsInvertedPolygonRendererWidget::create, "rendererInvertedSymbol.svg" );
76  _initRenderer( "heatmapRenderer", QgsHeatmapRendererWidget::create, "rendererHeatmapSymbol.svg" );
77  _initRenderer( "25dRenderer", Qgs25DRendererWidget::create, "renderer25dSymbol.svg" );
78  _initRenderer( "nullSymbol", QgsNullSymbolRendererWidget::create, "rendererNullSymbol.svg" );
79  initialized = true;
80 }
81 
83  : QDialog( parent )
84  , mLayer( layer )
85  , mStyle( style )
86  , mActiveWidget( nullptr )
87  , mPaintEffect( nullptr )
88  , mMapCanvas( nullptr )
89 {
90  setupUi( this );
91  mLayerRenderingGroupBox->setSettingGroup( "layerRenderingGroupBox" );
92 
93  // can be embedded in vector layer properties
94  if ( embedded )
95  {
96  buttonBox->hide();
97  layout()->setContentsMargins( 0, 0, 0, 0 );
98  }
99 
100  // initialize registry's widget functions
102 
104  QStringList renderers = reg->renderersList( mLayer );
105  Q_FOREACH ( const QString& name, renderers )
106  {
108  cboRenderers->addItem( m->icon(), m->visibleName(), name );
109  }
110 
111  cboRenderers->setCurrentIndex( -1 ); // set no current renderer
112 
113  connect( buttonBox, SIGNAL( accepted() ), this, SLOT( onOK() ) );
114 
115  // connect layer transparency slider and spin box
116  connect( mLayerTransparencySlider, SIGNAL( valueChanged( int ) ), mLayerTransparencySpnBx, SLOT( setValue( int ) ) );
117  connect( mLayerTransparencySpnBx, SIGNAL( valueChanged( int ) ), mLayerTransparencySlider, SLOT( setValue( int ) ) );
118 
119  connect( cboRenderers, SIGNAL( currentIndexChanged( int ) ), this, SLOT( rendererChanged() ) );
120  connect( checkboxEnableOrderBy, SIGNAL( toggled( bool ) ), btnOrderBy, SLOT( setEnabled( bool ) ) );
121  connect( btnOrderBy, SIGNAL( clicked( bool ) ), this, SLOT( showOrderByDialog() ) );
122 
123  syncToLayer();
124 
125  QList<QWidget*> widgets;
126  widgets << mLayerTransparencySpnBx
127  << cboRenderers
128  << checkboxEnableOrderBy
129  << mBlendModeComboBox
130  << mFeatureBlendComboBox
131  << mEffectWidget;
132 
133  connectValueChanged( widgets, SIGNAL( widgetChanged() ) );
134  connect( mEffectWidget, SIGNAL( showPanel( QgsPanelWidget* ) ), this, SLOT( openPanel( QgsPanelWidget* ) ) );
135 }
136 
138 {
139  Q_FOREACH ( QWidget* widget, widgets )
140  {
141  if ( QgsDataDefinedButton* w = qobject_cast<QgsDataDefinedButton*>( widget ) )
142  {
143  connect( w, SIGNAL( dataDefinedActivated( bool ) ), this, slot );
144  connect( w, SIGNAL( dataDefinedChanged( QString ) ), this, slot );
145  }
146  else if ( QgsFieldExpressionWidget* w = qobject_cast<QgsFieldExpressionWidget*>( widget ) )
147  {
148  connect( w, SIGNAL( fieldChanged( QString ) ), this, slot );
149  }
150  else if ( QComboBox* w = qobject_cast<QComboBox*>( widget ) )
151  {
152  connect( w, SIGNAL( currentIndexChanged( int ) ), this, slot );
153  }
154  else if ( QSpinBox* w = qobject_cast<QSpinBox*>( widget ) )
155  {
156  connect( w, SIGNAL( valueChanged( int ) ), this, slot );
157  }
158  else if ( QDoubleSpinBox* w = qobject_cast<QDoubleSpinBox*>( widget ) )
159  {
160  connect( w , SIGNAL( valueChanged( double ) ), this, slot );
161  }
162  else if ( QgsColorButtonV2* w = qobject_cast<QgsColorButtonV2*>( widget ) )
163  {
164  connect( w, SIGNAL( colorChanged( QColor ) ), this, slot );
165  }
166  else if ( QCheckBox* w = qobject_cast<QCheckBox*>( widget ) )
167  {
168  connect( w, SIGNAL( toggled( bool ) ), this, slot );
169  }
170  else if ( QLineEdit* w = qobject_cast<QLineEdit*>( widget ) )
171  {
172  connect( w, SIGNAL( textEdited( QString ) ), this, slot );
173  connect( w, SIGNAL( textChanged( QString ) ), this, slot );
174  }
175  else if ( QgsEffectStackCompactWidget* w = qobject_cast<QgsEffectStackCompactWidget*>( widget ) )
176  {
177  connect( w, SIGNAL( changed() ), this, slot );
178  }
179  }
180 }
181 
183 {
184  delete mPaintEffect;
185 }
186 
188 {
189  mMapCanvas = canvas;
190  if ( mActiveWidget )
192 }
193 
195 {
196  mDockMode = dockMode;
197  mEffectWidget->setDockMode( dockMode );
198  if ( mActiveWidget )
199  mActiveWidget->setDockMode( mDockMode );
200 }
201 
202 
204 {
205  if ( cboRenderers->currentIndex() == -1 )
206  {
207  QgsDebugMsg( "No current item -- this should never happen!" );
208  return;
209  }
210 
211  QString rendererName = cboRenderers->itemData( cboRenderers->currentIndex() ).toString();
212 
213  //Retrieve the previous renderer: from the old active widget if possible, otherwise from the layer
214  QgsFeatureRendererV2* oldRenderer;
216  {
217  oldRenderer = mActiveWidget->renderer()->clone();
218  }
219  else
220  {
221  oldRenderer = mLayer->rendererV2()->clone();
222  }
223 
224  // get rid of old active widget (if any)
225  if ( mActiveWidget )
226  {
227  stackedWidget->removeWidget( mActiveWidget );
228 
229  delete mActiveWidget;
230  mActiveWidget = nullptr;
231  }
232 
233  QgsRendererV2Widget* w = nullptr;
235  if ( m )
236  w = m->createRendererWidget( mLayer, mStyle, oldRenderer );
237  delete oldRenderer;
238 
239  if ( w )
240  {
241  // instantiate the widget and set as active
242  mActiveWidget = w;
243  stackedWidget->addWidget( mActiveWidget );
244  stackedWidget->setCurrentWidget( mActiveWidget );
245  if ( mActiveWidget->renderer() )
246  {
247  if ( mMapCanvas )
249  changeOrderBy( mActiveWidget->renderer()->orderBy(), mActiveWidget->renderer()->orderByEnabled() );
250  connect( mActiveWidget, SIGNAL( layerVariablesChanged() ), this, SIGNAL( layerVariablesChanged() ) );
251  }
252  connect( mActiveWidget, SIGNAL( widgetChanged() ), this, SIGNAL( widgetChanged() ) );
253  connect( mActiveWidget, SIGNAL( showPanel( QgsPanelWidget* ) ), this, SLOT( openPanel( QgsPanelWidget* ) ) );
254  w->setDockMode( mDockMode );
255  }
256  else
257  {
258  // set default "no edit widget available" page
259  stackedWidget->setCurrentWidget( pageNoWidget );
260  }
261 }
262 
264 {
265  if ( !mActiveWidget || !mLayer )
266  {
267  return;
268  }
269 
271 
273  if ( renderer )
274  {
275  renderer->setPaintEffect( mPaintEffect->clone() );
276  // set the order by
277  renderer->setOrderBy( mOrderBy );
278  renderer->setOrderByEnabled( checkboxEnableOrderBy->isChecked() );
279 
280  mLayer->setRendererV2( renderer->clone() );
281  }
282 
283  // set the blend modes for the layer
284  mLayer->setBlendMode( mBlendModeComboBox->blendMode() );
285  mLayer->setFeatureBlendMode( mFeatureBlendComboBox->blendMode() );
286 
287  // set transparency for the layer
288  mLayer->setLayerTransparency( mLayerTransparencySlider->value() );
289 }
290 
292 {
293  apply();
294  accept();
295 }
296 
298 {
299  QgsDebugMsg( "Open panel!!!" );
300  if ( mDockMode )
301  {
302  QgsDebugMsg( "DOCK MODE" );
303  emit showPanel( panel );
304  }
305  else
306  {
307  QgsDebugMsg( "DIALOG MODE" );
308  // Show the dialog version if no one is connected
309  QDialog* dlg = new QDialog();
310  QString key = QString( "/UI/paneldialog/%1" ).arg( panel->panelTitle() );
311  QSettings settings;
312  dlg->restoreGeometry( settings.value( key ).toByteArray() );
313  dlg->setWindowTitle( panel->panelTitle() );
314  dlg->setLayout( new QVBoxLayout() );
315  dlg->layout()->addWidget( panel );
316  QDialogButtonBox* buttonBox = new QDialogButtonBox( QDialogButtonBox::Ok );
317  connect( buttonBox, SIGNAL( accepted() ), dlg, SLOT( accept() ) );
318  dlg->layout()->addWidget( buttonBox );
319  dlg->exec();
320  settings.setValue( key, dlg->saveGeometry() );
321  panel->acceptPanel();
322  }
323 }
324 
325 void QgsRendererV2PropertiesDialog::syncToLayer()
326 {
327  // Blend mode
328  mBlendModeComboBox->setBlendMode( mLayer->blendMode() );
329 
330  // Feature blend mode
331  mFeatureBlendComboBox->setBlendMode( mLayer->featureBlendMode() );
332 
333  // Layer transparency
334  mLayerTransparencySlider->setValue( mLayer->layerTransparency() );
335  mLayerTransparencySpnBx->setValue( mLayer->layerTransparency() );
336 
337  //paint effect widget
338  if ( mLayer->rendererV2() )
339  {
340  if ( mLayer->rendererV2()->paintEffect() )
341  {
343  mEffectWidget->setPaintEffect( mPaintEffect );
344  }
345 
347  }
348 
349  // setup slot rendererChanged()
350  //setup order by
351  if ( mLayer->rendererV2() &&
353  {
354  checkboxEnableOrderBy->setChecked( true );
355  }
356  else
357  {
358  btnOrderBy->setEnabled( false );
359  checkboxEnableOrderBy->setChecked( false );
360  }
361 
362  if ( mLayer->rendererV2() )
363  {
364  // set current renderer from layer
365  QString rendererName = mLayer->rendererV2()->type();
366 
367  int rendererIdx = cboRenderers->findData( rendererName );
368  cboRenderers->setCurrentIndex( rendererIdx );
369 
370  // no renderer found... this mustn't happen
371  Q_ASSERT( rendererIdx != -1 && "there must be a renderer!" );
372  }
373 
374 }
375 
376 void QgsRendererV2PropertiesDialog::showOrderByDialog()
377 {
378  QgsOrderByDialog dlg( mLayer, this );
379 
380  dlg.setOrderBy( mOrderBy );
381  if ( dlg.exec() )
382  {
383  mOrderBy = dlg.orderBy();
384  emit widgetChanged();
385  }
386 }
387 
388 void QgsRendererV2PropertiesDialog::changeOrderBy( const QgsFeatureRequest::OrderBy& orderBy, bool orderByEnabled )
389 {
390  mOrderBy = orderBy;
391  checkboxEnableOrderBy->setChecked( orderByEnabled );
392 }
393 
394 void QgsRendererV2PropertiesDialog::updateUIState( bool hidden )
395 {
396  mLayerRenderingGroupBox->setHidden( hidden );
397  cboRenderers->setHidden( hidden );
398 }
399 
400 
402 {
403  // Ignore the ESC key to avoid close the dialog without the properties window
404  if ( !isWindow() && e->key() == Qt::Key_Escape )
405  {
406  e->ignore();
407  }
408  else
409  {
411  }
412 }
QLayout * layout() const
void showPanel(QgsPanelWidget *panel)
Emit when you require a panel to be show in the interface.
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()
Returns a pointer to the QgsRendererV2Registry singleton.
QByteArray toByteArray() const
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 openPanel(QgsPanelWidget *panel)
Open a panel or dialog depending on dock mode setting If dock mode is true this method will emit the ...
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()
QgsRendererV2PropertiesDialog(QgsVectorLayer *layer, QgsStyleV2 *style, bool embedded=false, QWidget *parent=nullptr)
Constructor for QgsRendererV2PropertiesDialog.
void setLayerTransparency(int layerTransparency)
Set the transparency for the vector layer.
Stores metadata about one renderer class.
Base class for any widget that can be shown as a inline panel.
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:109
QgsRendererV2AbstractMetadata * rendererMetadata(const QString &rendererName)
Returns the metadata for a specified renderer.
virtual QgsPaintEffect * clone() const =0
Duplicates an effect by creating a deep copy of the effect.
virtual void setDockMode(bool dockMode)
Set the widget in dock mode which tells the widget to emit panel widgets and not open dialogs...
void setIcon(const QIcon &icon)
static void _initRendererWidgetFunctions()
QString type() const
Definition: qgsrendererv2.h:92
void setWidgetFunction(QgsRendererV2WidgetFunc f)
void setValue(const QString &key, const QVariant &value)
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.
void setLayout(QLayout *layout)
bool restoreGeometry(const QByteArray &geometry)
void layerVariablesChanged()
Emitted when expression context variables on the associated vector layers have been changed...
void acceptPanel()
Accept the panel.
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.
QString panelTitle()
The title of the panel.
A small widget consisting of a check box for enabling/disabling an effect stack and a button for open...
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.
void setDockMode(bool dockMode)
Set the widget in dock mode which tells the widget to emit panel widgets and not open dialogs...
bool load(const QString &fileName, const char *format, QFlags< Qt::ImageConversionFlag > flags)
static QgsRendererV2Widget * create(QgsVectorLayer *layer, QgsStyleV2 *style, QgsFeatureRendererV2 *renderer)
void addWidget(QWidget *w)
virtual void accept()
bool isWindow() const
A button for defining data source field mappings or expressions.
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.
QVariant value(const QString &key, const QVariant &defaultValue) const
void setOrderBy(const QgsFeatureRequest::OrderBy &orderBy)
Define the order in which features shall be processed by this renderer.
QByteArray saveGeometry() const
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()
Emitted 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.
void setWindowTitle(const QString &)
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)
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
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...
QDialog(QWidget *parent, QFlags< Qt::WindowType > f)
QStringList renderersList(QgsRendererV2AbstractMetadata::LayerTypes layerTypes=QgsRendererV2AbstractMetadata::All) const
Returns a list of available renderers.
static QgsRendererV2Widget * create(QgsVectorLayer *layer, QgsStyleV2 *style, QgsFeatureRendererV2 *renderer)
Static creation method.