QGIS API Documentation 3.39.0-Master (d85f3c2a281)
Loading...
Searching...
No Matches
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"
30#include "qgsmapcanvas.h"
31
32QgsLabelingWidget::QgsLabelingWidget( QgsVectorLayer *layer, QgsMapCanvas *canvas, QWidget *parent, QgsMessageBar *messageBar )
33 : QgsMapLayerConfigWidget( layer, canvas, parent )
34 , mLayer( layer )
35 , mCanvas( canvas )
36 , mMessageBar( messageBar )
37
38{
39 setupUi( this );
40
41 mLabelModeComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "labelingNone.svg" ) ), tr( "No Labels" ), ModeNone );
42 mLabelModeComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "labelingSingle.svg" ) ), tr( "Single Labels" ), ModeSingle );
43 mLabelModeComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "labelingRuleBased.svg" ) ), tr( "Rule-based Labeling" ), ModeRuleBased );
44 mLabelModeComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "labelingObstacle.svg" ) ), tr( "Blocking" ), ModeBlocking );
45
46 connect( mLabelRulesButton, &QAbstractButton::clicked, this, &QgsLabelingWidget::showLabelingEngineRules );
47 connect( mEngineSettingsButton, &QAbstractButton::clicked, this, &QgsLabelingWidget::showEngineConfigDialog );
48
49 connect( mLabelModeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsLabelingWidget::labelModeChanged );
50 setLayer( layer );
51
52 const int iconSize16 = QgsGuiUtils::scaleIconSize( 16 );
53 mEngineSettingsButton->setIconSize( QSize( iconSize16, iconSize16 ) );
54}
55
57{
58 return qobject_cast<QgsLabelingGui *>( mWidget );
59}
60
62{
63 if ( mOldSettings )
64 {
65 mLayer->setLabeling( mOldSettings.release() );
66 mLayer->setLabelsEnabled( mOldLabelsEnabled );
67 }
68 setLayer( mLayer );
69}
70
71
73{
74 if ( !mapLayer || mapLayer->type() != Qgis::LayerType::Vector )
75 {
76 setEnabled( false );
77 return;
78 }
79 else
80 {
81 setEnabled( true );
82 }
83
84 QgsVectorLayer *layer = qobject_cast<QgsVectorLayer *>( mapLayer );
85 mLayer = layer;
86 if ( mLayer->labeling() )
87 {
88 mOldSettings.reset( mLayer->labeling()->clone() );
89 }
90 else
91 mOldSettings.reset();
92 mOldLabelsEnabled = mLayer->labelsEnabled();
93
95}
96
98{
99 if ( !mLayer )
100 return;
101
102 whileBlocking( mLabelModeComboBox )->setCurrentIndex( -1 );
103
104 // pick the right mode of the layer
105 if ( mLayer->labelsEnabled() && mLayer->labeling()->type() == QLatin1String( "rule-based" ) )
106 {
107 mLabelModeComboBox->setCurrentIndex( mLabelModeComboBox->findData( ModeRuleBased ) );
108 }
109 else if ( mLayer->labelsEnabled() && mLayer->labeling()->type() == QLatin1String( "simple" ) )
110 {
111 const QgsPalLayerSettings lyr = mLayer->labeling()->settings();
112
113 mLabelModeComboBox->setCurrentIndex( mLabelModeComboBox->findData( lyr.drawLabels ? ModeSingle : ModeBlocking ) );
114 }
115 else
116 {
117 mLabelModeComboBox->setCurrentIndex( mLabelModeComboBox->findData( ModeNone ) );
118 }
119
120 if ( QgsLabelingGui *lg = qobject_cast<QgsLabelingGui *>( mWidget ) )
121 {
122 lg->updateUi();
123 }
124}
125
127{
128 const Mode mode = static_cast< Mode >( mLabelModeComboBox->currentData().toInt() );
129 switch ( mode )
130 {
131 case ModeRuleBased:
132 {
133 const QgsRuleBasedLabeling::Rule *rootRule = qobject_cast<QgsRuleBasedLabelingWidget *>( mWidget )->rootRule();
134
135 mLayer->setLabeling( new QgsRuleBasedLabeling( rootRule->clone() ) );
136 mLayer->setLabelsEnabled( true );
137 break;
138 }
139
140 case ModeSingle:
141 {
142 mLayer->setLabeling( new QgsVectorLayerSimpleLabeling( qobject_cast<QgsLabelingGui *>( mWidget )->layerSettings() ) );
143 mLayer->setLabelsEnabled( true );
144 break;
145 }
146
147 case ModeBlocking:
148 {
149 mLayer->setLabeling( new QgsVectorLayerSimpleLabeling( *mSimpleSettings ) );
150 mLayer->setLabelsEnabled( true );
151 break;
152 }
153
154 case ModeNone:
155 {
156 mLayer->setLabelsEnabled( false );
157 break;
158 }
159 }
160}
161
163{
166 // trigger refresh
167 mLayer->triggerRepaint();
168}
169
170void QgsLabelingWidget::labelModeChanged( int index )
171{
172 if ( mWidget )
173 mStackedWidget->removeWidget( mWidget );
174
175 delete mWidget;
176 mWidget = nullptr;
177
178 if ( index < 0 )
179 return;
180
181 const Mode mode = static_cast< Mode >( mLabelModeComboBox->currentData().toInt() );
182
183 switch ( mode )
184 {
185 case ModeRuleBased:
186 {
187 // note - QgsRuleBasedLabelingWidget handles conversion of existing non-rule based labels to rule based
188 QgsRuleBasedLabelingWidget *ruleWidget = new QgsRuleBasedLabelingWidget( mLayer, mCanvas, this );
189 ruleWidget->setDockMode( dockMode() );
190 connect( ruleWidget, &QgsPanelWidget::showPanel, this, &QgsPanelWidget::openPanel );
192 mWidget = ruleWidget;
193 mStackedWidget->addWidget( mWidget );
194 mStackedWidget->setCurrentWidget( mWidget );
195 break;
196 }
197
198 case ModeSingle:
199 case ModeBlocking:
200 {
201 mSimpleSettings.reset();
202 if ( mLayer->labeling() && mLayer->labeling()->type() == QLatin1String( "simple" ) )
203 {
204 mSimpleSettings.reset( new QgsPalLayerSettings( mLayer->labeling()->settings() ) );
205 }
206 else if ( mLayer->labeling() && mLayer->labeling()->type() == QLatin1String( "rule-based" ) )
207 {
208 // changing from rule-based to simple labels... grab first rule, and copy settings
209 const QgsRuleBasedLabeling *rl = static_cast<const QgsRuleBasedLabeling *>( mLayer->labeling() );
210 if ( const QgsRuleBasedLabeling::Rule *rootRule = rl->rootRule() )
211 {
212 if ( const QgsRuleBasedLabeling::Rule *firstChild = rootRule->children().value( 0 ) )
213 {
214 if ( firstChild->settings() )
215 mSimpleSettings.reset( new QgsPalLayerSettings( *firstChild->settings() ) );
216 }
217 }
218 }
219
220 if ( !mSimpleSettings )
221 {
222 mSimpleSettings = std::make_unique< QgsPalLayerSettings >( QgsAbstractVectorLayerLabeling::defaultSettingsForLayer( mLayer ) );
223 }
224
225 if ( mSimpleSettings->fieldName.isEmpty() )
226 mSimpleSettings->fieldName = mLayer->displayField();
227
229 context.setMapCanvas( mMapCanvas );
230 context.setMessageBar( mMessageBar );
231
232 switch ( mode )
233 {
234 case ModeSingle:
235 {
236 QgsLabelingGui *simpleWidget = new QgsLabelingGui( mLayer, mCanvas, *mSimpleSettings, this );
237 simpleWidget->setContext( context );
238
239 simpleWidget->setDockMode( dockMode() );
241 connect( simpleWidget, &QgsLabelingGui::auxiliaryFieldCreated, this, &QgsLabelingWidget::auxiliaryFieldCreated );
242
243 simpleWidget->setLabelMode( QgsLabelingGui::Labels );
244
245 mWidget = simpleWidget;
246 break;
247 }
248 case ModeBlocking:
249 {
250 QgsLabelObstacleSettingsWidget *obstacleWidget = new QgsLabelObstacleSettingsWidget( this, mLayer );
251 obstacleWidget->setContext( context );
252 obstacleWidget->setGeometryType( mLayer ? mLayer->geometryType() : Qgis::GeometryType::Unknown );
253 obstacleWidget->setDockMode( dockMode() );
254 obstacleWidget->setSettings( mSimpleSettings->obstacleSettings() );
255 obstacleWidget->setDataDefinedProperties( mSimpleSettings->dataDefinedProperties() );
256
257 mSimpleSettings->obstacleSettings().setIsObstacle( true );
258 mSimpleSettings->drawLabels = false;
259
260 connect( obstacleWidget, &QgsLabelSettingsWidgetBase::changed, this, [ = ]
261 {
262 mSimpleSettings->setObstacleSettings( obstacleWidget->settings() );
263 obstacleWidget->updateDataDefinedProperties( mSimpleSettings->dataDefinedProperties() );
264 emit widgetChanged();
265 } );
267
268 mWidget = obstacleWidget;
269 break;
270 }
271
272 case ModeRuleBased:
273 case ModeNone:
274 break;
275 }
276
277 mStackedWidget->addWidget( mWidget );
278 mStackedWidget->setCurrentWidget( mWidget );
279 break;
280 }
281
282 case ModeNone:
283 break;
284 }
285 emit widgetChanged();
286}
287
288void QgsLabelingWidget::showLabelingEngineRules()
289{
292 QList< QgsAbstractLabelingEngineRule * > rules;
293 for ( const QgsAbstractLabelingEngineRule *rule : settings.rules() )
294 {
295 // blame sip, it requires the widget setter to take non-const pointers?!
296 rules << const_cast<QgsAbstractLabelingEngineRule * >( rule );
297 }
298 if ( panel && panel->dockMode() )
299 {
301 widget->setRules( rules );
302 connect( widget, &QgsLabelingEngineRulesWidget::changed, widget, [widget, this]
303 {
305 settings.setRules( widget->rules() );
308 if ( mCanvas )
309 mCanvas->refreshAllLayers();
310 } );
311 panel->openPanel( widget );
312 }
313 else
314 {
315 QgsLabelingEngineRulesDialog dialog( this );
316 dialog.setRules( rules );
317 if ( dialog.exec() )
318 {
320 settings.setRules( dialog.rules() );
323 if ( mCanvas )
324 mCanvas->refreshAllLayers();
325 }
326 activateWindow();
327 }
328}
329
330void QgsLabelingWidget::showEngineConfigDialog()
331{
333 if ( panel && panel->dockMode() )
334 {
337 panel->openPanel( widget );
338 }
339 else
340 {
341 QgsLabelEngineConfigDialog dialog( mCanvas, this );
342 dialog.exec();
343 // reactivate button's window
344 activateWindow();
345 }
346}
The Qgis class provides global constants for use throughout the application.
Definition qgis.h:54
@ Vector
Vector layer.
Abstract base class for labeling engine rules.
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.
A dialog which allows configuration of a list of labeling engine rules.
A widget which allows configuration of a list of labeling engine rules.
void setRules(const QList< QgsAbstractLabelingEngineRule * > &rules)
Sets the rules to show in the widget.
QList< QgsAbstractLabelingEngineRule * > rules() const
Returns the rules shown in the widget.
void changed()
Emitted when the rules configured in the widget are changed.
Stores global configuration for labeling engine.
void setRules(const QList< QgsAbstractLabelingEngineRule * > &rules)
Sets the labeling engine rules which must be satifisfied while placing labels.
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.
void refreshAllLayers()
Reload all layers (including refreshing layer properties from their data sources),...
A panel widget that can be shown in the map style dock.
Base class for all map layer types.
Definition qgsmaplayer.h:76
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:86
A bar for displaying non-blocking messages to the user.
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.
void setLabelingEngineSettings(const QgsLabelingEngineSettings &settings)
Sets project's global labeling engine settings.
const QgsLabelingEngineSettings & labelingEngineSettings() const
Returns project's global labeling engine settings.
void setDirty(bool b=true)
Flag the project as dirty (modified).
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,...
@ Unknown
Unknown/invalid format.
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition qgis.h:5761