QGIS API Documentation 3.41.0-Master (cea29feecf2)
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 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] {
304 settings.setRules( widget->rules() );
307 if ( mCanvas )
308 mCanvas->refreshAllLayers();
309 } );
310 panel->openPanel( widget );
311 }
312 else
313 {
314 QgsLabelingEngineRulesDialog dialog( this );
315 dialog.setRules( rules );
316 if ( dialog.exec() )
317 {
319 settings.setRules( dialog.rules() );
322 if ( mCanvas )
323 mCanvas->refreshAllLayers();
324 }
325 activateWindow();
326 }
327}
328
329void QgsLabelingWidget::showEngineConfigDialog()
330{
332 if ( panel && panel->dockMode() )
333 {
336 panel->openPanel( widget );
337 }
338 else
339 {
340 QgsLabelEngineConfigDialog dialog( mCanvas, this );
341 dialog.exec();
342 // reactivate button's window
343 activateWindow();
344 }
345}
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:5928