QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
qgslabelingwidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgslabelingwidget.cpp
3  ---------------------
4  begin : September 2015
5  copyright : (C) 2015 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 
16 #include <QDialogButtonBox>
17 #include <QDomElement>
18 
19 #include "qgslabelingwidget.h"
20 
22 #include "qgslabelinggui.h"
23 #include "qgsreadwritecontext.h"
25 #include "qgsvectorlayer.h"
26 #include "qgsvectorlayerlabeling.h"
27 #include "qgsproject.h"
28 #include "qgsapplication.h"
30 
31 QgsLabelingWidget::QgsLabelingWidget( QgsVectorLayer *layer, QgsMapCanvas *canvas, QWidget *parent, QgsMessageBar *messageBar )
32  : QgsMapLayerConfigWidget( layer, canvas, parent )
33  , mLayer( layer )
34  , mCanvas( canvas )
35  , mMessageBar( messageBar )
36 
37 {
38  setupUi( this );
39 
40  mLabelModeComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "labelingNone.svg" ) ), tr( "No Labels" ), ModeNone );
41  mLabelModeComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "labelingSingle.svg" ) ), tr( "Single Labels" ), ModeSingle );
42  mLabelModeComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "labelingRuleBased.svg" ) ), tr( "Rule-based Labeling" ), ModeRuleBased );
43  mLabelModeComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "labelingObstacle.svg" ) ), tr( "Blocking" ), ModeBlocking );
44 
45  connect( mEngineSettingsButton, &QAbstractButton::clicked, this, &QgsLabelingWidget::showEngineConfigDialog );
46 
47  connect( mLabelModeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsLabelingWidget::labelModeChanged );
48  setLayer( layer );
49 
50  const int iconSize16 = QgsGuiUtils::scaleIconSize( 16 );
51  mEngineSettingsButton->setIconSize( QSize( iconSize16, iconSize16 ) );
52 }
53 
55 {
56  return qobject_cast<QgsLabelingGui *>( mWidget );
57 }
58 
60 {
61  if ( mOldSettings )
62  {
63  mLayer->setLabeling( mOldSettings.release() );
64  mLayer->setLabelsEnabled( mOldLabelsEnabled );
65  }
66  setLayer( mLayer );
67 }
68 
69 
71 {
72  if ( !mapLayer || mapLayer->type() != QgsMapLayerType::VectorLayer )
73  {
74  setEnabled( false );
75  return;
76  }
77  else
78  {
79  setEnabled( true );
80  }
81 
82  QgsVectorLayer *layer = qobject_cast<QgsVectorLayer *>( mapLayer );
83  mLayer = layer;
84  if ( mLayer->labeling() )
85  {
86  mOldSettings.reset( mLayer->labeling()->clone() );
87  }
88  else
89  mOldSettings.reset();
90  mOldLabelsEnabled = mLayer->labelsEnabled();
91 
92  adaptToLayer();
93 }
94 
96 {
97  if ( !mLayer )
98  return;
99 
100  whileBlocking( mLabelModeComboBox )->setCurrentIndex( -1 );
101 
102  // pick the right mode of the layer
103  if ( mLayer->labelsEnabled() && mLayer->labeling()->type() == QLatin1String( "rule-based" ) )
104  {
105  mLabelModeComboBox->setCurrentIndex( mLabelModeComboBox->findData( ModeRuleBased ) );
106  }
107  else if ( mLayer->labelsEnabled() && mLayer->labeling()->type() == QLatin1String( "simple" ) )
108  {
109  QgsPalLayerSettings lyr = mLayer->labeling()->settings();
110 
111  mLabelModeComboBox->setCurrentIndex( mLabelModeComboBox->findData( lyr.drawLabels ? ModeSingle : ModeBlocking ) );
112  }
113  else
114  {
115  mLabelModeComboBox->setCurrentIndex( mLabelModeComboBox->findData( ModeNone ) );
116  }
117 
118  if ( QgsLabelingGui *lg = qobject_cast<QgsLabelingGui *>( mWidget ) )
119  {
120  lg->updateUi();
121  }
122 }
123 
125 {
126  const Mode mode = static_cast< Mode >( mLabelModeComboBox->currentData().toInt() );
127  switch ( mode )
128  {
129  case ModeRuleBased:
130  {
131  const QgsRuleBasedLabeling::Rule *rootRule = qobject_cast<QgsRuleBasedLabelingWidget *>( mWidget )->rootRule();
132 
133  mLayer->setLabeling( new QgsRuleBasedLabeling( rootRule->clone() ) );
134  mLayer->setLabelsEnabled( true );
135  break;
136  }
137 
138  case ModeSingle:
139  {
140  mLayer->setLabeling( new QgsVectorLayerSimpleLabeling( qobject_cast<QgsLabelingGui *>( mWidget )->layerSettings() ) );
141  mLayer->setLabelsEnabled( true );
142  break;
143  }
144 
145  case ModeBlocking:
146  {
147  mLayer->setLabeling( new QgsVectorLayerSimpleLabeling( *mSimpleSettings ) );
148  mLayer->setLabelsEnabled( true );
149  break;
150  }
151 
152  case ModeNone:
153  {
154  mLayer->setLabelsEnabled( false );
155  break;
156  }
157  }
158 }
159 
161 {
162  writeSettingsToLayer();
164  // trigger refresh
165  mLayer->triggerRepaint();
166 }
167 
168 void QgsLabelingWidget::labelModeChanged( int index )
169 {
170  if ( mWidget )
171  mStackedWidget->removeWidget( mWidget );
172 
173  delete mWidget;
174  mWidget = nullptr;
175 
176  if ( index < 0 )
177  return;
178 
179  const Mode mode = static_cast< Mode >( mLabelModeComboBox->currentData().toInt() );
180 
181  switch ( mode )
182  {
183  case ModeRuleBased:
184  {
185  // note - QgsRuleBasedLabelingWidget handles conversion of existing non-rule based labels to rule based
186  QgsRuleBasedLabelingWidget *ruleWidget = new QgsRuleBasedLabelingWidget( mLayer, mCanvas, this );
187  ruleWidget->setDockMode( dockMode() );
188  connect( ruleWidget, &QgsPanelWidget::showPanel, this, &QgsPanelWidget::openPanel );
190  mWidget = ruleWidget;
191  mStackedWidget->addWidget( mWidget );
192  mStackedWidget->setCurrentWidget( mWidget );
193  break;
194  }
195 
196  case ModeSingle:
197  case ModeBlocking:
198  {
199  mSimpleSettings.reset();
200  if ( mLayer->labeling() && mLayer->labeling()->type() == QLatin1String( "simple" ) )
201  {
202  mSimpleSettings.reset( new QgsPalLayerSettings( mLayer->labeling()->settings() ) );
203  }
204  else if ( mLayer->labeling() && mLayer->labeling()->type() == QLatin1String( "rule-based" ) )
205  {
206  // changing from rule-based to simple labels... grab first rule, and copy settings
207  const QgsRuleBasedLabeling *rl = static_cast<const QgsRuleBasedLabeling *>( mLayer->labeling() );
208  if ( const QgsRuleBasedLabeling::Rule *rootRule = rl->rootRule() )
209  {
210  if ( const QgsRuleBasedLabeling::Rule *firstChild = rootRule->children().value( 0 ) )
211  {
212  if ( firstChild->settings() )
213  mSimpleSettings.reset( new QgsPalLayerSettings( *firstChild->settings() ) );
214  }
215  }
216  }
217 
218  if ( !mSimpleSettings )
219  mSimpleSettings.reset( new QgsPalLayerSettings() );
220 
221  if ( mSimpleSettings->fieldName.isEmpty() )
222  mSimpleSettings->fieldName = mLayer->displayField();
223 
224  QgsSymbolWidgetContext context;
225  context.setMapCanvas( mMapCanvas );
226  context.setMessageBar( mMessageBar );
227 
228  switch ( mode )
229  {
230  case ModeSingle:
231  {
232  QgsLabelingGui *simpleWidget = new QgsLabelingGui( mLayer, mCanvas, *mSimpleSettings, this );
233  simpleWidget->setContext( context );
234 
235  simpleWidget->setDockMode( dockMode() );
237  connect( simpleWidget, &QgsLabelingGui::auxiliaryFieldCreated, this, &QgsLabelingWidget::auxiliaryFieldCreated );
238 
239  simpleWidget->setLabelMode( QgsLabelingGui::Labels );
240 
241  mWidget = simpleWidget;
242  break;
243  }
244  case ModeBlocking:
245  {
246  QgsLabelObstacleSettingsWidget *obstacleWidget = new QgsLabelObstacleSettingsWidget( this, mLayer );
247  obstacleWidget->setContext( context );
248  obstacleWidget->setGeometryType( mLayer ? mLayer->geometryType() : QgsWkbTypes::UnknownGeometry );
249  obstacleWidget->setDockMode( dockMode() );
250  obstacleWidget->setSettings( mSimpleSettings->obstacleSettings() );
251  obstacleWidget->setDataDefinedProperties( mSimpleSettings->dataDefinedProperties() );
252 
253  mSimpleSettings->obstacleSettings().setIsObstacle( true );
254  mSimpleSettings->drawLabels = false;
255 
256  connect( obstacleWidget, &QgsLabelSettingsWidgetBase::changed, this, [ = ]
257  {
258  mSimpleSettings->setObstacleSettings( obstacleWidget->settings() );
259  obstacleWidget->updateDataDefinedProperties( mSimpleSettings->dataDefinedProperties() );
260  emit widgetChanged();
261  } );
263 
264  mWidget = obstacleWidget;
265  break;
266  }
267 
268  case ModeRuleBased:
269  case ModeNone:
270  break;
271  }
272 
273  mStackedWidget->addWidget( mWidget );
274  mStackedWidget->setCurrentWidget( mWidget );
275  break;
276  }
277 
278  case ModeNone:
279  break;
280  }
281  emit widgetChanged();
282 }
283 
284 void QgsLabelingWidget::showEngineConfigDialog()
285 {
287  if ( panel && panel->dockMode() )
288  {
291  panel->openPanel( widget );
292  }
293  else
294  {
295  QgsLabelEngineConfigDialog dialog( mCanvas, this );
296  dialog.exec();
297  // reactivate button's window
298  activateWindow();
299  }
300 }
QgsApplication::getThemeIcon
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
Definition: qgsapplication.cpp:626
QgsRuleBasedLabeling::Rule
Definition: qgsrulebasedlabeling.h:53
QgsLabelObstacleSettingsWidget::setSettings
void setSettings(const QgsLabelObstacleSettings &settings)
Sets the obstacle settings to show in the widget.
Definition: qgslabelobstaclesettingswidget.cpp:45
qgslabelingwidget.h
QgsMapLayerType::VectorLayer
@ VectorLayer
QgsPanelWidget::setDockMode
virtual void setDockMode(bool dockMode)
Set the widget in dock mode which tells the widget to emit panel widgets and not open dialogs.
Definition: qgspanelwidget.cpp:44
QgsLabelSettingsWidgetBase::auxiliaryFieldCreated
void auxiliaryFieldCreated()
Emitted when an auxiliary field is created in the widget.
QgsPalLayerSettings
Definition: qgspallabeling.h:207
QgsPanelWidget::findParentPanel
static QgsPanelWidget * findParentPanel(QWidget *widget)
Traces through the parents of a widget to find if it is contained within a QgsPanelWidget widget.
Definition: qgspanelwidget.cpp:49
qgslabelobstaclesettingswidget.h
QgsLabelEngineConfigWidget
Widget for configuring the labeling engine.
Definition: qgslabelengineconfigdialog.h:38
qgsreadwritecontext.h
QgsSymbolWidgetContext
Contains settings which reflect the context in which a symbol (or renderer) widget is shown,...
Definition: qgssymbolwidgetcontext.h:36
QgsMapCanvas
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:85
QgsPanelWidget::openPanel
void openPanel(QgsPanelWidget *panel)
Open a panel or dialog depending on dock mode setting If dock mode is true this method will emit the ...
Definition: qgspanelwidget.cpp:79
QgsProject::instance
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:468
QgsLabelEngineConfigWidget::apply
void apply()
Applies the changes.
Definition: qgslabelengineconfigdialog.cpp:108
QgsLabelObstacleSettingsWidget::updateDataDefinedProperties
void updateDataDefinedProperties(QgsPropertyCollection &properties) override
Updates a data defined properties collection, correctly setting the values for any properties related...
Definition: qgslabelobstaclesettingswidget.cpp:67
QgsLabelingWidget::QgsLabelingWidget
QgsLabelingWidget(QgsVectorLayer *layer, QgsMapCanvas *canvas, QWidget *parent=nullptr, QgsMessageBar *messageBar=nullptr)
constructor
Definition: qgslabelingwidget.cpp:31
QgsPanelWidget::dockMode
bool dockMode()
Returns the dock mode state.
Definition: qgspanelwidget.h:83
QgsRuleBasedLabeling
Definition: qgsrulebasedlabeling.h:41
QgsMapLayerConfigWidget
A panel widget that can be shown in the map style dock.
Definition: qgsmaplayerconfigwidget.h:34
QgsSymbolWidgetContext::setMapCanvas
void setMapCanvas(QgsMapCanvas *canvas)
Sets the map canvas associated with the widget.
Definition: qgssymbolwidgetcontext.cpp:49
QgsPanelWidget::showPanel
void showPanel(QgsPanelWidget *panel)
Emit when you require a panel to be show in the interface.
qgsapplication.h
QgsSymbolWidgetContext::setMessageBar
void setMessageBar(QgsMessageBar *bar)
Sets the message bar associated with the widget.
Definition: qgssymbolwidgetcontext.cpp:59
QgsPanelWidget
Base class for any widget that can be shown as a inline panel.
Definition: qgspanelwidget.h:30
QgsLabelingWidget::resetSettings
void resetSettings()
Reset the settings.
Definition: qgslabelingwidget.cpp:59
QgsLabelingWidget::apply
void apply() override
Saves the labeling configuration and immediately updates the map canvas to reflect the changes.
Definition: qgslabelingwidget.cpp:160
QgsLabelSettingsWidgetBase::setContext
virtual void setContext(const QgsSymbolWidgetContext &context)
Sets the context in which the symbol widget is shown, e.g., the associated map canvas and expression ...
Definition: qgslabelsettingswidgetbase.cpp:32
whileBlocking
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:262
QgsRuleBasedLabeling::rootRule
QgsRuleBasedLabeling::Rule * rootRule()
Definition: qgsrulebasedlabeling.cpp:447
QgsLabelingWidget::auxiliaryFieldCreated
void auxiliaryFieldCreated()
Emitted when an auxiliary field is created.
QgsPalLayerSettings::drawLabels
bool drawLabels
Whether to draw labels for this layer.
Definition: qgspallabeling.h:530
QgsMessageBar
A bar for displaying non-blocking messages to the user.
Definition: qgsmessagebar.h:61
QgsPanelWidget::widgetChanged
void widgetChanged()
Emitted when the widget state changes.
QgsLabelingWidget::writeSettingsToLayer
void writeSettingsToLayer()
save config to layer
Definition: qgslabelingwidget.cpp:124
QgsProject::setDirty
void setDirty(bool b=true)
Flag the project as dirty (modified).
Definition: qgsproject.cpp:519
QgsLabelSettingsWidgetBase::setDataDefinedProperties
void setDataDefinedProperties(const QgsPropertyCollection &dataDefinedProperties)
Sets the current data defined properties to show in the widget.
Definition: qgslabelsettingswidgetbase.cpp:128
QgsLabelObstacleSettingsWidget::setGeometryType
void setGeometryType(QgsWkbTypes::GeometryType type) override
Sets the geometry type of the features to customize the widget accordingly.
Definition: qgslabelobstaclesettingswidget.cpp:61
qgsvectorlayer.h
QgsLabelingWidget::adaptToLayer
void adaptToLayer()
reload the settings shown in the dialog from the current layer
Definition: qgslabelingwidget.cpp:95
QgsLabelingWidget::setLayer
void setLayer(QgsMapLayer *layer)
Sets the layer to configure.
Definition: qgslabelingwidget.cpp:70
QgsVectorLayerSimpleLabeling
Basic implementation of the labeling interface.
Definition: qgsvectorlayerlabeling.h:157
QgsRuleBasedLabeling::Rule::clone
QgsRuleBasedLabeling::Rule * clone() const
clone this rule, return new instance
Definition: qgsrulebasedlabeling.cpp:227
QgsRuleBasedLabeling::Rule::children
const QgsRuleBasedLabeling::RuleList & children() const
Returns all children rules of this rule.
Definition: qgsrulebasedlabeling.h:192
QgsTextFormatWidget::widgetChanged
void widgetChanged()
Emitted when the text format defined by the widget changes.
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:387
QgsMapLayer
Base class for all map layer types.
Definition: qgsmaplayer.h:83
QgsWkbTypes::UnknownGeometry
@ UnknownGeometry
Definition: qgswkbtypes.h:145
qgsrulebasedlabelingwidget.h
QgsLabelObstacleSettingsWidget
A widget for customising label obstacle settings.
Definition: qgslabelobstaclesettingswidget.h:32
qgsvectorlayerlabeling.h
QgsLabelObstacleSettingsWidget::settings
QgsLabelObstacleSettings settings() const
Returns the obstacle settings defined by the widget.
Definition: qgslabelobstaclesettingswidget.cpp:53
qgslabelengineconfigdialog.h
QgsLabelEngineConfigDialog
Dialog for configuring the labeling engine.
Definition: qgslabelengineconfigdialog.h:71
QgsLabelSettingsWidgetBase::changed
void changed()
Emitted when any of the settings described by the widget are changed.
QgsGuiUtils::scaleIconSize
int scaleIconSize(int standardSize)
Scales an icon size to compensate for display pixel density, making the icon size hi-dpi friendly,...
Definition: qgsguiutils.cpp:245
QgsLabelingWidget::labelingGui
QgsLabelingGui * labelingGui()
Returns the labeling gui widget or nullptr if none.
Definition: qgslabelingwidget.cpp:54
qgsproject.h
qgslabelinggui.h
QgsVectorLayer::labelsEnabled
bool labelsEnabled() const
Returns whether the layer contains labels which are enabled and should be drawn.
Definition: qgsvectorlayer.cpp:728
QgsMapLayer::type
QgsMapLayerType type
Definition: qgsmaplayer.h:90