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