QGIS API Documentation 3.41.0-Master (57ec4277f5e)
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#include "moc_qgslabelingwidget.cpp"
21
23#include "qgslabelinggui.h"
25#include "qgsvectorlayer.h"
27#include "qgsproject.h"
28#include "qgsapplication.h"
31#include "qgsmapcanvas.h"
32
33QgsLabelingWidget::QgsLabelingWidget( QgsVectorLayer *layer, QgsMapCanvas *canvas, QWidget *parent, QgsMessageBar *messageBar )
34 : QgsMapLayerConfigWidget( layer, canvas, parent )
35 , mLayer( layer )
36 , mCanvas( canvas )
37 , mMessageBar( messageBar )
38
39{
40 setupUi( this );
41
42 mLabelModeComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "labelingNone.svg" ) ), tr( "No Labels" ), ModeNone );
43 mLabelModeComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "labelingSingle.svg" ) ), tr( "Single Labels" ), ModeSingle );
44 mLabelModeComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "labelingRuleBased.svg" ) ), tr( "Rule-based Labeling" ), ModeRuleBased );
45 mLabelModeComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "labelingObstacle.svg" ) ), tr( "Blocking" ), ModeBlocking );
46
47 connect( mLabelRulesButton, &QAbstractButton::clicked, this, &QgsLabelingWidget::showLabelingEngineRulesPrivate );
48 connect( mEngineSettingsButton, &QAbstractButton::clicked, this, &QgsLabelingWidget::showEngineConfigDialogPrivate );
49
50 connect( mLabelModeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsLabelingWidget::labelModeChanged );
51 setLayer( layer );
52
53 const int iconSize16 = QgsGuiUtils::scaleIconSize( 16 );
54 mEngineSettingsButton->setIconSize( QSize( iconSize16, iconSize16 ) );
55 mLabelRulesButton->setIconSize( QSize( iconSize16, iconSize16 ) );
56}
57
59{
60 return qobject_cast<QgsLabelingGui *>( mWidget );
61}
62
64{
65 if ( mOldSettings )
66 {
67 mLayer->setLabeling( mOldSettings.release() );
68 mLayer->setLabelsEnabled( mOldLabelsEnabled );
69 }
70 setLayer( mLayer );
71}
72
73
75{
76 if ( !mapLayer || mapLayer->type() != Qgis::LayerType::Vector )
77 {
78 setEnabled( false );
79 return;
80 }
81 else
82 {
83 setEnabled( true );
84 }
85
86 QgsVectorLayer *layer = qobject_cast<QgsVectorLayer *>( mapLayer );
87 mLayer = layer;
88 if ( mLayer->labeling() )
89 {
90 mOldSettings.reset( mLayer->labeling()->clone() );
91 }
92 else
93 mOldSettings.reset();
94 mOldLabelsEnabled = mLayer->labelsEnabled();
95
97}
98
100{
101 if ( !mLayer )
102 return;
103
104 whileBlocking( mLabelModeComboBox )->setCurrentIndex( -1 );
105
106 // pick the right mode of the layer
107 if ( mLayer->labelsEnabled() && mLayer->labeling()->type() == QLatin1String( "rule-based" ) )
108 {
109 mLabelModeComboBox->setCurrentIndex( mLabelModeComboBox->findData( ModeRuleBased ) );
110 }
111 else if ( mLayer->labelsEnabled() && mLayer->labeling()->type() == QLatin1String( "simple" ) )
112 {
113 const QgsPalLayerSettings lyr = mLayer->labeling()->settings();
114
115 mLabelModeComboBox->setCurrentIndex( mLabelModeComboBox->findData( lyr.drawLabels ? ModeSingle : ModeBlocking ) );
116 }
117 else
118 {
119 mLabelModeComboBox->setCurrentIndex( mLabelModeComboBox->findData( ModeNone ) );
120 }
121
122 if ( QgsLabelingGui *lg = qobject_cast<QgsLabelingGui *>( mWidget ) )
123 {
124 lg->updateUi();
125 }
126}
127
129{
130 const Mode mode = static_cast<Mode>( mLabelModeComboBox->currentData().toInt() );
131 switch ( mode )
132 {
133 case ModeRuleBased:
134 {
135 const QgsRuleBasedLabeling::Rule *rootRule = qobject_cast<QgsRuleBasedLabelingWidget *>( mWidget )->rootRule();
136
137 mLayer->setLabeling( new QgsRuleBasedLabeling( rootRule->clone() ) );
138 mLayer->setLabelsEnabled( true );
139 break;
140 }
141
142 case ModeSingle:
143 {
144 mLayer->setLabeling( new QgsVectorLayerSimpleLabeling( qobject_cast<QgsLabelingGui *>( mWidget )->layerSettings() ) );
145 mLayer->setLabelsEnabled( true );
146 break;
147 }
148
149 case ModeBlocking:
150 {
151 mLayer->setLabeling( new QgsVectorLayerSimpleLabeling( *mSimpleSettings ) );
152 mLayer->setLabelsEnabled( true );
153 break;
154 }
155
156 case ModeNone:
157 {
158 mLayer->setLabelsEnabled( false );
159 break;
160 }
161 }
162}
163
165{
168 // trigger refresh
169 mLayer->triggerRepaint();
170}
171
172void QgsLabelingWidget::labelModeChanged( int index )
173{
174 if ( mWidget )
175 mStackedWidget->removeWidget( mWidget );
176
177 delete mWidget;
178 mWidget = nullptr;
179
180 if ( index < 0 )
181 return;
182
183 const Mode mode = static_cast<Mode>( mLabelModeComboBox->currentData().toInt() );
184
185 switch ( mode )
186 {
187 case ModeRuleBased:
188 {
189 // note - QgsRuleBasedLabelingWidget handles conversion of existing non-rule based labels to rule based
190 QgsRuleBasedLabelingWidget *ruleWidget = new QgsRuleBasedLabelingWidget( mLayer, mCanvas, this );
191 ruleWidget->setDockMode( dockMode() );
192 connect( ruleWidget, &QgsPanelWidget::showPanel, this, &QgsPanelWidget::openPanel );
194 mWidget = ruleWidget;
195 mStackedWidget->addWidget( mWidget );
196 mStackedWidget->setCurrentWidget( mWidget );
197 break;
198 }
199
200 case ModeSingle:
201 case ModeBlocking:
202 {
203 mSimpleSettings.reset();
204 if ( mLayer->labeling() && mLayer->labeling()->type() == QLatin1String( "simple" ) )
205 {
206 mSimpleSettings.reset( new QgsPalLayerSettings( mLayer->labeling()->settings() ) );
207 }
208 else if ( mLayer->labeling() && mLayer->labeling()->type() == QLatin1String( "rule-based" ) )
209 {
210 // changing from rule-based to simple labels... grab first rule, and copy settings
211 const QgsRuleBasedLabeling *rl = static_cast<const QgsRuleBasedLabeling *>( mLayer->labeling() );
212 if ( const QgsRuleBasedLabeling::Rule *rootRule = rl->rootRule() )
213 {
214 if ( const QgsRuleBasedLabeling::Rule *firstChild = rootRule->children().value( 0 ) )
215 {
216 if ( firstChild->settings() )
217 mSimpleSettings.reset( new QgsPalLayerSettings( *firstChild->settings() ) );
218 }
219 }
220 }
221
222 if ( !mSimpleSettings )
223 {
224 mSimpleSettings = std::make_unique<QgsPalLayerSettings>( QgsAbstractVectorLayerLabeling::defaultSettingsForLayer( mLayer ) );
225 }
226
227 if ( mSimpleSettings->fieldName.isEmpty() )
228 mSimpleSettings->fieldName = mLayer->displayField();
229
231 context.setMapCanvas( mMapCanvas );
232 context.setMessageBar( mMessageBar );
233
234 switch ( mode )
235 {
236 case ModeSingle:
237 {
238 QgsLabelingGui *simpleWidget = new QgsLabelingGui( mLayer, mCanvas, *mSimpleSettings, this );
239 simpleWidget->setContext( context );
240
241 simpleWidget->setDockMode( dockMode() );
243 connect( simpleWidget, &QgsLabelingGui::auxiliaryFieldCreated, this, &QgsLabelingWidget::auxiliaryFieldCreated );
244
245 simpleWidget->setLabelMode( QgsLabelingGui::Labels );
246
247 mWidget = simpleWidget;
248 break;
249 }
250 case ModeBlocking:
251 {
252 QgsLabelObstacleSettingsWidget *obstacleWidget = new QgsLabelObstacleSettingsWidget( this, mLayer );
253 obstacleWidget->setContext( context );
254 obstacleWidget->setGeometryType( mLayer ? mLayer->geometryType() : Qgis::GeometryType::Unknown );
255 obstacleWidget->setDockMode( dockMode() );
256 obstacleWidget->setSettings( mSimpleSettings->obstacleSettings() );
257 obstacleWidget->setDataDefinedProperties( mSimpleSettings->dataDefinedProperties() );
258
259 mSimpleSettings->obstacleSettings().setIsObstacle( true );
260 mSimpleSettings->drawLabels = false;
261
262 connect( obstacleWidget, &QgsLabelSettingsWidgetBase::changed, this, [=] {
263 mSimpleSettings->setObstacleSettings( obstacleWidget->settings() );
264 obstacleWidget->updateDataDefinedProperties( mSimpleSettings->dataDefinedProperties() );
265 emit widgetChanged();
266 } );
268
269 mWidget = obstacleWidget;
270 break;
271 }
272
273 case ModeRuleBased:
274 case ModeNone:
275 break;
276 }
277
278 mStackedWidget->addWidget( mWidget );
279 mStackedWidget->setCurrentWidget( mWidget );
280 break;
281 }
282
283 case ModeNone:
284 break;
285 }
286 emit widgetChanged();
287}
288
289
291{
294 QList<QgsAbstractLabelingEngineRule *> rules;
295 for ( const QgsAbstractLabelingEngineRule *rule : settings.rules() )
296 {
297 // blame sip, it requires the widget setter to take non-const pointers?!
298 rules << const_cast<QgsAbstractLabelingEngineRule *>( rule );
299 }
300 if ( panel && panel->dockMode() )
301 {
303 widget->setRules( rules );
304 connect( widget, &QgsLabelingEngineRulesWidget::changed, widget, [widget, canvas] {
306 settings.setRules( widget->rules() );
309 if ( canvas )
310 canvas->refreshAllLayers();
311 } );
312 panel->openPanel( widget );
313 }
314 else
315 {
316 QgsLabelingEngineRulesDialog dialog( parent );
317 dialog.setRules( rules );
318 if ( dialog.exec() )
319 {
321 settings.setRules( dialog.rules() );
324 if ( canvas )
325 canvas->refreshAllLayers();
326 }
327 parent->activateWindow();
328 }
329}
330
331void QgsLabelingWidget::showLabelingEngineRulesPrivate()
332{
333 showLabelingEngineRules( this, mCanvas );
334}
335
337{
339 if ( panel && panel->dockMode() )
340 {
343 panel->openPanel( widget );
344 }
345 else
346 {
347 QgsLabelEngineConfigDialog dialog( canvas, parent );
348 dialog.exec();
349 // reactivate button's window
350 parent->activateWindow();
351 }
352}
353
354void QgsLabelingWidget::showEngineConfigDialogPrivate()
355{
356 showEngineConfiguration( this, mCanvas );
357}
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.
QList< QgsAbstractLabelingEngineRule * > rules() const
Returns the rules shown in the dialog.
void setRules(const QList< QgsAbstractLabelingEngineRule * > &rules)
Sets the rules to show in the dialog.
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 satisfied while placing labels.
QList< QgsAbstractLabelingEngineRule * > rules()
Returns a list of labeling engine rules which must be satisfied 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.
static void showLabelingEngineRules(QWidget *parent, QgsMapCanvas *canvas)
Shows the labeling engine rules.
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.
static void showEngineConfiguration(QWidget *parent, QgsMapCanvas *canvas)
Shows the labeling engine configuration.
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:5970