QGIS API Documentation  2.15.0-Master (1f0fce7)
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( checkboxEnableOrderBy, SIGNAL( toggled( bool ) ), lineEditOrderBy, SLOT( setEnabled( bool ) ) );
122  connect( btnOrderBy, SIGNAL( clicked( bool ) ), this, SLOT( showOrderByDialog() ) );
123 
124  syncToLayer();
125 
126  QList<QWidget*> widgets;
127  widgets << mLayerTransparencySpnBx
128  << cboRenderers
129  << checkboxEnableOrderBy
130  << lineEditOrderBy
131  << mBlendModeComboBox
132  << mFeatureBlendComboBox
133  << mEffectWidget;
134 
135  connectValueChanged( widgets, SIGNAL( widgetChanged() ) );
136  connect( mEffectWidget, SIGNAL( showPanel( QgsPanelWidget* ) ), this, SLOT( openPanel( QgsPanelWidget* ) ) );
137 }
138 
140 {
141  Q_FOREACH ( QWidget* widget, widgets )
142  {
143  if ( QgsDataDefinedButton* w = qobject_cast<QgsDataDefinedButton*>( widget ) )
144  {
145  connect( w, SIGNAL( dataDefinedActivated( bool ) ), this, slot );
146  connect( w, SIGNAL( dataDefinedChanged( QString ) ), this, slot );
147  }
148  else if ( QgsFieldExpressionWidget* w = qobject_cast<QgsFieldExpressionWidget*>( widget ) )
149  {
150  connect( w, SIGNAL( fieldChanged( QString ) ), this, slot );
151  }
152  else if ( QComboBox* w = qobject_cast<QComboBox*>( widget ) )
153  {
154  connect( w, SIGNAL( currentIndexChanged( int ) ), this, slot );
155  }
156  else if ( QSpinBox* w = qobject_cast<QSpinBox*>( widget ) )
157  {
158  connect( w, SIGNAL( valueChanged( int ) ), this, slot );
159  }
160  else if ( QDoubleSpinBox* w = qobject_cast<QDoubleSpinBox*>( widget ) )
161  {
162  connect( w , SIGNAL( valueChanged( double ) ), this, slot );
163  }
164  else if ( QgsColorButtonV2* w = qobject_cast<QgsColorButtonV2*>( widget ) )
165  {
166  connect( w, SIGNAL( colorChanged( QColor ) ), this, slot );
167  }
168  else if ( QCheckBox* w = qobject_cast<QCheckBox*>( widget ) )
169  {
170  connect( w, SIGNAL( toggled( bool ) ), this, slot );
171  }
172  else if ( QLineEdit* w = qobject_cast<QLineEdit*>( widget ) )
173  {
174  connect( w, SIGNAL( textEdited( QString ) ), this, slot );
175  connect( w, SIGNAL( textChanged( QString ) ), this, slot );
176  }
177  else if ( QgsEffectStackCompactWidget* w = qobject_cast<QgsEffectStackCompactWidget*>( widget ) )
178  {
179  connect( w, SIGNAL( changed() ), this, slot );
180  }
181  }
182 }
183 
185 {
186  delete mPaintEffect;
187 }
188 
190 {
191  mMapCanvas = canvas;
192  if ( mActiveWidget )
194 }
195 
197 {
198  mDockMode = dockMode;
199  mEffectWidget->setDockMode( dockMode );
200  if ( mActiveWidget )
201  mActiveWidget->setDockMode( mDockMode );
202 }
203 
204 
206 {
207  if ( cboRenderers->currentIndex() == -1 )
208  {
209  QgsDebugMsg( "No current item -- this should never happen!" );
210  return;
211  }
212 
213  QString rendererName = cboRenderers->itemData( cboRenderers->currentIndex() ).toString();
214 
215  //Retrieve the previous renderer: from the old active widget if possible, otherwise from the layer
216  QgsFeatureRendererV2* oldRenderer;
218  {
219  oldRenderer = mActiveWidget->renderer()->clone();
220  }
221  else
222  {
223  oldRenderer = mLayer->rendererV2()->clone();
224  }
225 
226  // get rid of old active widget (if any)
227  if ( mActiveWidget )
228  {
229  stackedWidget->removeWidget( mActiveWidget );
230 
231  delete mActiveWidget;
232  mActiveWidget = nullptr;
233  }
234 
235  QgsRendererV2Widget* w = nullptr;
237  if ( m )
238  w = m->createRendererWidget( mLayer, mStyle, oldRenderer );
239  delete oldRenderer;
240 
241  if ( w )
242  {
243  // instantiate the widget and set as active
244  mActiveWidget = w;
245  stackedWidget->addWidget( mActiveWidget );
246  stackedWidget->setCurrentWidget( mActiveWidget );
247  if ( mActiveWidget->renderer() )
248  {
249  if ( mMapCanvas )
251  changeOrderBy( mActiveWidget->renderer()->orderBy(), mActiveWidget->renderer()->orderByEnabled() );
252  connect( mActiveWidget, SIGNAL( layerVariablesChanged() ), this, SIGNAL( layerVariablesChanged() ) );
253  }
254  connect( mActiveWidget, SIGNAL( widgetChanged() ), this, SIGNAL( widgetChanged() ) );
255  connect( mActiveWidget, SIGNAL( showPanel( QgsPanelWidget* ) ), this, SLOT( openPanel( QgsPanelWidget* ) ) );
256  w->setDockMode( mDockMode );
257  }
258  else
259  {
260  // set default "no edit widget available" page
261  stackedWidget->setCurrentWidget( pageNoWidget );
262  }
263 }
264 
266 {
267  if ( !mActiveWidget || !mLayer )
268  {
269  return;
270  }
271 
273 
275  if ( renderer )
276  {
277  renderer->setPaintEffect( mPaintEffect->clone() );
278  // set the order by
279  renderer->setOrderBy( mOrderBy );
280  renderer->setOrderByEnabled( checkboxEnableOrderBy->isChecked() );
281 
282  mLayer->setRendererV2( renderer->clone() );
283  }
284 
285  // set the blend modes for the layer
286  mLayer->setBlendMode( mBlendModeComboBox->blendMode() );
287  mLayer->setFeatureBlendMode( mFeatureBlendComboBox->blendMode() );
288 
289  // set transparency for the layer
290  mLayer->setLayerTransparency( mLayerTransparencySlider->value() );
291 }
292 
294 {
295  apply();
296  accept();
297 }
298 
300 {
301  QgsDebugMsg( "Open panel!!!" );
302  if ( mDockMode )
303  {
304  QgsDebugMsg( "DOCK MODE" );
305  emit showPanel( panel );
306  }
307  else
308  {
309  QgsDebugMsg( "DIALOG MODE" );
310  // Show the dialog version if no one is connected
311  QDialog* dlg = new QDialog();
312  QString key = QString( "/UI/paneldialog/%1" ).arg( panel->panelTitle() );
313  QSettings settings;
314  dlg->restoreGeometry( settings.value( key ).toByteArray() );
315  dlg->setWindowTitle( panel->panelTitle() );
316  dlg->setLayout( new QVBoxLayout() );
317  dlg->layout()->addWidget( panel );
318  QDialogButtonBox* buttonBox = new QDialogButtonBox( QDialogButtonBox::Ok );
319  connect( buttonBox, SIGNAL( accepted() ), dlg, SLOT( accept() ) );
320  dlg->layout()->addWidget( buttonBox );
321  dlg->exec();
322  settings.setValue( key, dlg->saveGeometry() );
323  panel->acceptPanel();
324  }
325 }
326 
327 void QgsRendererV2PropertiesDialog::syncToLayer()
328 {
329  // Blend mode
330  mBlendModeComboBox->setBlendMode( mLayer->blendMode() );
331 
332  // Feature blend mode
333  mFeatureBlendComboBox->setBlendMode( mLayer->featureBlendMode() );
334 
335  // Layer transparency
336  mLayerTransparencySlider->setValue( mLayer->layerTransparency() );
337  mLayerTransparencySpnBx->setValue( mLayer->layerTransparency() );
338 
339  //paint effect widget
340  if ( mLayer->rendererV2() )
341  {
342  if ( mLayer->rendererV2()->paintEffect() )
343  {
345  mEffectWidget->setPaintEffect( mPaintEffect );
346  }
347 
349  }
350 
351  lineEditOrderBy->setText( mOrderBy.dump() );
352 
353  // setup slot rendererChanged()
354  //setup order by
355  if ( mLayer->rendererV2() &&
357  {
358  checkboxEnableOrderBy->setChecked( true );
359  }
360  else
361  {
362  btnOrderBy->setEnabled( false );
363  checkboxEnableOrderBy->setChecked( false );
364  lineEditOrderBy->setEnabled( false );
365  }
366  lineEditOrderBy->setReadOnly( true );
367 
368  if ( mLayer->rendererV2() )
369  {
370  // set current renderer from layer
371  QString rendererName = mLayer->rendererV2()->type();
372 
373  int rendererIdx = cboRenderers->findData( rendererName );
374  cboRenderers->setCurrentIndex( rendererIdx );
375 
376  // no renderer found... this mustn't happen
377  Q_ASSERT( rendererIdx != -1 && "there must be a renderer!" );
378  }
379 
380 }
381 
382 void QgsRendererV2PropertiesDialog::showOrderByDialog()
383 {
384  QgsOrderByDialog dlg( mLayer, this );
385 
386  dlg.setOrderBy( mOrderBy );
387  if ( dlg.exec() )
388  {
389  mOrderBy = dlg.orderBy();
390  lineEditOrderBy->setText( mOrderBy.dump() );
391  }
392 }
393 
394 void QgsRendererV2PropertiesDialog::changeOrderBy( const QgsFeatureRequest::OrderBy& orderBy, bool orderByEnabled )
395 {
396  mOrderBy = orderBy;
397  lineEditOrderBy->setText( mOrderBy.dump() );
398  checkboxEnableOrderBy->setChecked( orderByEnabled );
399 }
400 
401 void QgsRendererV2PropertiesDialog::updateUIState( bool hidden )
402 {
403  mLayerRenderingGroupBox->setHidden( hidden );
404  cboRenderers->setHidden( hidden );
405 }
406 
407 
409 {
410  // Ignore the ESC key to avoid close the dialog without the properties window
411  if ( !isWindow() && e->key() == Qt::Key_Escape )
412  {
413  e->ignore();
414  }
415  else
416  {
418  }
419 }
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:86
void setWidgetFunction(QgsRendererV2WidgetFunc f)
void setValue(const QString &key, const QVariant &value)
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.
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.