QGIS API Documentation 3.41.0-Master (3440c17df1d)
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::showLabelingEngineRules );
48 connect( mEngineSettingsButton, &QAbstractButton::clicked, this, &QgsLabelingWidget::showEngineConfigDialog );
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}
56
58{
59 return qobject_cast<QgsLabelingGui *>( mWidget );
60}
61
63{
64 if ( mOldSettings )
65 {
66 mLayer->setLabeling( mOldSettings.release() );
67 mLayer->setLabelsEnabled( mOldLabelsEnabled );
68 }
69 setLayer( mLayer );
70}
71
72
74{
75 if ( !mapLayer || mapLayer->type() != Qgis::LayerType::Vector )
76 {
77 setEnabled( false );
78 return;
79 }
80 else
81 {
82 setEnabled( true );
83 }
84
85 QgsVectorLayer *layer = qobject_cast<QgsVectorLayer *>( mapLayer );
86 mLayer = layer;
87 if ( mLayer->labeling() )
88 {
89 mOldSettings.reset( mLayer->labeling()->clone() );
90 }
91 else
92 mOldSettings.reset();
93 mOldLabelsEnabled = mLayer->labelsEnabled();
94
96}
97
99{
100 if ( !mLayer )
101 return;
102
103 whileBlocking( mLabelModeComboBox )->setCurrentIndex( -1 );
104
105 // pick the right mode of the layer
106 if ( mLayer->labelsEnabled() && mLayer->labeling()->type() == QLatin1String( "rule-based" ) )
107 {
108 mLabelModeComboBox->setCurrentIndex( mLabelModeComboBox->findData( ModeRuleBased ) );
109 }
110 else if ( mLayer->labelsEnabled() && mLayer->labeling()->type() == QLatin1String( "simple" ) )
111 {
112 const QgsPalLayerSettings lyr = mLayer->labeling()->settings();
113
114 mLabelModeComboBox->setCurrentIndex( mLabelModeComboBox->findData( lyr.drawLabels ? ModeSingle : ModeBlocking ) );
115 }
116 else
117 {
118 mLabelModeComboBox->setCurrentIndex( mLabelModeComboBox->findData( ModeNone ) );
119 }
120
121 if ( QgsLabelingGui *lg = qobject_cast<QgsLabelingGui *>( mWidget ) )
122 {
123 lg->updateUi();
124 }
125}
126
128{
129 const Mode mode = static_cast< Mode >( mLabelModeComboBox->currentData().toInt() );
130 switch ( mode )
131 {
132 case ModeRuleBased:
133 {
134 const QgsRuleBasedLabeling::Rule *rootRule = qobject_cast<QgsRuleBasedLabelingWidget *>( mWidget )->rootRule();
135
136 mLayer->setLabeling( new QgsRuleBasedLabeling( rootRule->clone() ) );
137 mLayer->setLabelsEnabled( true );
138 break;
139 }
140
141 case ModeSingle:
142 {
143 mLayer->setLabeling( new QgsVectorLayerSimpleLabeling( qobject_cast<QgsLabelingGui *>( mWidget )->layerSettings() ) );
144 mLayer->setLabelsEnabled( true );
145 break;
146 }
147
148 case ModeBlocking:
149 {
150 mLayer->setLabeling( new QgsVectorLayerSimpleLabeling( *mSimpleSettings ) );
151 mLayer->setLabelsEnabled( true );
152 break;
153 }
154
155 case ModeNone:
156 {
157 mLayer->setLabelsEnabled( false );
158 break;
159 }
160 }
161}
162
164{
167 // trigger refresh
168 mLayer->triggerRepaint();
169}
170
171void QgsLabelingWidget::labelModeChanged( int index )
172{
173 if ( mWidget )
174 mStackedWidget->removeWidget( mWidget );
175
176 delete mWidget;
177 mWidget = nullptr;
178
179 if ( index < 0 )
180 return;
181
182 const Mode mode = static_cast< Mode >( mLabelModeComboBox->currentData().toInt() );
183
184 switch ( mode )
185 {
186 case ModeRuleBased:
187 {
188 // note - QgsRuleBasedLabelingWidget handles conversion of existing non-rule based labels to rule based
189 QgsRuleBasedLabelingWidget *ruleWidget = new QgsRuleBasedLabelingWidget( mLayer, mCanvas, this );
190 ruleWidget->setDockMode( dockMode() );
191 connect( ruleWidget, &QgsPanelWidget::showPanel, this, &QgsPanelWidget::openPanel );
193 mWidget = ruleWidget;
194 mStackedWidget->addWidget( mWidget );
195 mStackedWidget->setCurrentWidget( mWidget );
196 break;
197 }
198
199 case ModeSingle:
200 case ModeBlocking:
201 {
202 mSimpleSettings.reset();
203 if ( mLayer->labeling() && mLayer->labeling()->type() == QLatin1String( "simple" ) )
204 {
205 mSimpleSettings.reset( new QgsPalLayerSettings( mLayer->labeling()->settings() ) );
206 }
207 else if ( mLayer->labeling() && mLayer->labeling()->type() == QLatin1String( "rule-based" ) )
208 {
209 // changing from rule-based to simple labels... grab first rule, and copy settings
210 const QgsRuleBasedLabeling *rl = static_cast<const QgsRuleBasedLabeling *>( mLayer->labeling() );
211 if ( const QgsRuleBasedLabeling::Rule *rootRule = rl->rootRule() )
212 {
213 if ( const QgsRuleBasedLabeling::Rule *firstChild = rootRule->children().value( 0 ) )
214 {
215 if ( firstChild->settings() )
216 mSimpleSettings.reset( new QgsPalLayerSettings( *firstChild->settings() ) );
217 }
218 }
219 }
220
221 if ( !mSimpleSettings )
222 {
223 mSimpleSettings = std::make_unique< QgsPalLayerSettings >( QgsAbstractVectorLayerLabeling::defaultSettingsForLayer( mLayer ) );
224 }
225
226 if ( mSimpleSettings->fieldName.isEmpty() )
227 mSimpleSettings->fieldName = mLayer->displayField();
228
230 context.setMapCanvas( mMapCanvas );
231 context.setMessageBar( mMessageBar );
232
233 switch ( mode )
234 {
235 case ModeSingle:
236 {
237 QgsLabelingGui *simpleWidget = new QgsLabelingGui( mLayer, mCanvas, *mSimpleSettings, this );
238 simpleWidget->setContext( context );
239
240 simpleWidget->setDockMode( dockMode() );
242 connect( simpleWidget, &QgsLabelingGui::auxiliaryFieldCreated, this, &QgsLabelingWidget::auxiliaryFieldCreated );
243
244 simpleWidget->setLabelMode( QgsLabelingGui::Labels );
245
246 mWidget = simpleWidget;
247 break;
248 }
249 case ModeBlocking:
250 {
251 QgsLabelObstacleSettingsWidget *obstacleWidget = new QgsLabelObstacleSettingsWidget( this, mLayer );
252 obstacleWidget->setContext( context );
253 obstacleWidget->setGeometryType( mLayer ? mLayer->geometryType() : Qgis::GeometryType::Unknown );
254 obstacleWidget->setDockMode( dockMode() );
255 obstacleWidget->setSettings( mSimpleSettings->obstacleSettings() );
256 obstacleWidget->setDataDefinedProperties( mSimpleSettings->dataDefinedProperties() );
257
258 mSimpleSettings->obstacleSettings().setIsObstacle( true );
259 mSimpleSettings->drawLabels = false;
260
261 connect( obstacleWidget, &QgsLabelSettingsWidgetBase::changed, this, [ = ]
262 {
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
289void QgsLabelingWidget::showLabelingEngineRules()
290{
293 QList< QgsAbstractLabelingEngineRule * > rules;
294 for ( const QgsAbstractLabelingEngineRule *rule : settings.rules() )
295 {
296 // blame sip, it requires the widget setter to take non-const pointers?!
297 rules << const_cast<QgsAbstractLabelingEngineRule * >( rule );
298 }
299 if ( panel && panel->dockMode() )
300 {
302 widget->setRules( rules );
303 connect( widget, &QgsLabelingEngineRulesWidget::changed, widget, [widget, this]
304 {
306 settings.setRules( widget->rules() );
309 if ( mCanvas )
310 mCanvas->refreshAllLayers();
311 } );
312 panel->openPanel( widget );
313 }
314 else
315 {
316 QgsLabelingEngineRulesDialog dialog( this );
317 dialog.setRules( rules );
318 if ( dialog.exec() )
319 {
321 settings.setRules( dialog.rules() );
324 if ( mCanvas )
325 mCanvas->refreshAllLayers();
326 }
327 activateWindow();
328 }
329}
330
331void QgsLabelingWidget::showEngineConfigDialog()
332{
334 if ( panel && panel->dockMode() )
335 {
338 panel->openPanel( widget );
339 }
340 else
341 {
342 QgsLabelEngineConfigDialog dialog( mCanvas, this );
343 dialog.exec();
344 // reactivate button's window
345 activateWindow();
346 }
347}
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:5862