QGIS API Documentation 3.27.0-Master (0a97e3138f)
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"
23#include "qgsreadwritecontext.h"
25#include "qgsvectorlayer.h"
27#include "qgsproject.h"
28#include "qgsapplication.h"
30
31QgsLabelingWidget::QgsLabelingWidget( QgsVectorLayer *layer, QgsMapCanvas *canvas, QWidget *parent, QgsMessageBar *messageBar )
32 : QgsMapLayerConfigWidget( layer, canvas, parent )
33 , mLayer( layer )
34 , mCanvas( canvas )
35 , mMessageBar( messageBar )
36
37{
38 setupUi( this );
39
40 mLabelModeComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "labelingNone.svg" ) ), tr( "No Labels" ), ModeNone );
41 mLabelModeComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "labelingSingle.svg" ) ), tr( "Single Labels" ), ModeSingle );
42 mLabelModeComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "labelingRuleBased.svg" ) ), tr( "Rule-based Labeling" ), ModeRuleBased );
43 mLabelModeComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "labelingObstacle.svg" ) ), tr( "Blocking" ), ModeBlocking );
44
45 connect( mEngineSettingsButton, &QAbstractButton::clicked, this, &QgsLabelingWidget::showEngineConfigDialog );
46
47 connect( mLabelModeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsLabelingWidget::labelModeChanged );
48 setLayer( layer );
49
50 const int iconSize16 = QgsGuiUtils::scaleIconSize( 16 );
51 mEngineSettingsButton->setIconSize( QSize( iconSize16, iconSize16 ) );
52}
53
55{
56 return qobject_cast<QgsLabelingGui *>( mWidget );
57}
58
60{
61 if ( mOldSettings )
62 {
63 mLayer->setLabeling( mOldSettings.release() );
64 mLayer->setLabelsEnabled( mOldLabelsEnabled );
65 }
66 setLayer( mLayer );
67}
68
69
71{
72 if ( !mapLayer || mapLayer->type() != QgsMapLayerType::VectorLayer )
73 {
74 setEnabled( false );
75 return;
76 }
77 else
78 {
79 setEnabled( true );
80 }
81
82 QgsVectorLayer *layer = qobject_cast<QgsVectorLayer *>( mapLayer );
83 mLayer = layer;
84 if ( mLayer->labeling() )
85 {
86 mOldSettings.reset( mLayer->labeling()->clone() );
87 }
88 else
89 mOldSettings.reset();
90 mOldLabelsEnabled = mLayer->labelsEnabled();
91
93}
94
96{
97 if ( !mLayer )
98 return;
99
100 whileBlocking( mLabelModeComboBox )->setCurrentIndex( -1 );
101
102 // pick the right mode of the layer
103 if ( mLayer->labelsEnabled() && mLayer->labeling()->type() == QLatin1String( "rule-based" ) )
104 {
105 mLabelModeComboBox->setCurrentIndex( mLabelModeComboBox->findData( ModeRuleBased ) );
106 }
107 else if ( mLayer->labelsEnabled() && mLayer->labeling()->type() == QLatin1String( "simple" ) )
108 {
109 const QgsPalLayerSettings lyr = mLayer->labeling()->settings();
110
111 mLabelModeComboBox->setCurrentIndex( mLabelModeComboBox->findData( lyr.drawLabels ? ModeSingle : ModeBlocking ) );
112 }
113 else
114 {
115 mLabelModeComboBox->setCurrentIndex( mLabelModeComboBox->findData( ModeNone ) );
116 }
117
118 if ( QgsLabelingGui *lg = qobject_cast<QgsLabelingGui *>( mWidget ) )
119 {
120 lg->updateUi();
121 }
122}
123
125{
126 const Mode mode = static_cast< Mode >( mLabelModeComboBox->currentData().toInt() );
127 switch ( mode )
128 {
129 case ModeRuleBased:
130 {
131 const QgsRuleBasedLabeling::Rule *rootRule = qobject_cast<QgsRuleBasedLabelingWidget *>( mWidget )->rootRule();
132
133 mLayer->setLabeling( new QgsRuleBasedLabeling( rootRule->clone() ) );
134 mLayer->setLabelsEnabled( true );
135 break;
136 }
137
138 case ModeSingle:
139 {
140 mLayer->setLabeling( new QgsVectorLayerSimpleLabeling( qobject_cast<QgsLabelingGui *>( mWidget )->layerSettings() ) );
141 mLayer->setLabelsEnabled( true );
142 break;
143 }
144
145 case ModeBlocking:
146 {
147 mLayer->setLabeling( new QgsVectorLayerSimpleLabeling( *mSimpleSettings ) );
148 mLayer->setLabelsEnabled( true );
149 break;
150 }
151
152 case ModeNone:
153 {
154 mLayer->setLabelsEnabled( false );
155 break;
156 }
157 }
158}
159
161{
164 // trigger refresh
165 mLayer->triggerRepaint();
166}
167
168void QgsLabelingWidget::labelModeChanged( int index )
169{
170 if ( mWidget )
171 mStackedWidget->removeWidget( mWidget );
172
173 delete mWidget;
174 mWidget = nullptr;
175
176 if ( index < 0 )
177 return;
178
179 const Mode mode = static_cast< Mode >( mLabelModeComboBox->currentData().toInt() );
180
181 switch ( mode )
182 {
183 case ModeRuleBased:
184 {
185 // note - QgsRuleBasedLabelingWidget handles conversion of existing non-rule based labels to rule based
186 QgsRuleBasedLabelingWidget *ruleWidget = new QgsRuleBasedLabelingWidget( mLayer, mCanvas, this );
187 ruleWidget->setDockMode( dockMode() );
188 connect( ruleWidget, &QgsPanelWidget::showPanel, this, &QgsPanelWidget::openPanel );
190 mWidget = ruleWidget;
191 mStackedWidget->addWidget( mWidget );
192 mStackedWidget->setCurrentWidget( mWidget );
193 break;
194 }
195
196 case ModeSingle:
197 case ModeBlocking:
198 {
199 mSimpleSettings.reset();
200 if ( mLayer->labeling() && mLayer->labeling()->type() == QLatin1String( "simple" ) )
201 {
202 mSimpleSettings.reset( new QgsPalLayerSettings( mLayer->labeling()->settings() ) );
203 }
204 else if ( mLayer->labeling() && mLayer->labeling()->type() == QLatin1String( "rule-based" ) )
205 {
206 // changing from rule-based to simple labels... grab first rule, and copy settings
207 const QgsRuleBasedLabeling *rl = static_cast<const QgsRuleBasedLabeling *>( mLayer->labeling() );
208 if ( const QgsRuleBasedLabeling::Rule *rootRule = rl->rootRule() )
209 {
210 if ( const QgsRuleBasedLabeling::Rule *firstChild = rootRule->children().value( 0 ) )
211 {
212 if ( firstChild->settings() )
213 mSimpleSettings.reset( new QgsPalLayerSettings( *firstChild->settings() ) );
214 }
215 }
216 }
217
218 if ( !mSimpleSettings )
219 {
220 mSimpleSettings = std::make_unique< QgsPalLayerSettings >( QgsAbstractVectorLayerLabeling::defaultSettingsForLayer( mLayer ) );
221 }
222
223 if ( mSimpleSettings->fieldName.isEmpty() )
224 mSimpleSettings->fieldName = mLayer->displayField();
225
227 context.setMapCanvas( mMapCanvas );
228 context.setMessageBar( mMessageBar );
229
230 switch ( mode )
231 {
232 case ModeSingle:
233 {
234 QgsLabelingGui *simpleWidget = new QgsLabelingGui( mLayer, mCanvas, *mSimpleSettings, this );
235 simpleWidget->setContext( context );
236
237 simpleWidget->setDockMode( dockMode() );
239 connect( simpleWidget, &QgsLabelingGui::auxiliaryFieldCreated, this, &QgsLabelingWidget::auxiliaryFieldCreated );
240
241 simpleWidget->setLabelMode( QgsLabelingGui::Labels );
242
243 mWidget = simpleWidget;
244 break;
245 }
246 case ModeBlocking:
247 {
248 QgsLabelObstacleSettingsWidget *obstacleWidget = new QgsLabelObstacleSettingsWidget( this, mLayer );
249 obstacleWidget->setContext( context );
250 obstacleWidget->setGeometryType( mLayer ? mLayer->geometryType() : QgsWkbTypes::UnknownGeometry );
251 obstacleWidget->setDockMode( dockMode() );
252 obstacleWidget->setSettings( mSimpleSettings->obstacleSettings() );
253 obstacleWidget->setDataDefinedProperties( mSimpleSettings->dataDefinedProperties() );
254
255 mSimpleSettings->obstacleSettings().setIsObstacle( true );
256 mSimpleSettings->drawLabels = false;
257
258 connect( obstacleWidget, &QgsLabelSettingsWidgetBase::changed, this, [ = ]
259 {
260 mSimpleSettings->setObstacleSettings( obstacleWidget->settings() );
261 obstacleWidget->updateDataDefinedProperties( mSimpleSettings->dataDefinedProperties() );
262 emit widgetChanged();
263 } );
265
266 mWidget = obstacleWidget;
267 break;
268 }
269
270 case ModeRuleBased:
271 case ModeNone:
272 break;
273 }
274
275 mStackedWidget->addWidget( mWidget );
276 mStackedWidget->setCurrentWidget( mWidget );
277 break;
278 }
279
280 case ModeNone:
281 break;
282 }
283 emit widgetChanged();
284}
285
286void QgsLabelingWidget::showEngineConfigDialog()
287{
289 if ( panel && panel->dockMode() )
290 {
293 panel->openPanel( widget );
294 }
295 else
296 {
297 QgsLabelEngineConfigDialog dialog( mCanvas, this );
298 dialog.exec();
299 // reactivate button's window
300 activateWindow();
301 }
302}
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.
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 setGeometryType(QgsWkbTypes::GeometryType type) override
Sets the geometry type of the features to customize the widget accordingly.
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:90
A panel widget that can be shown in the map style dock.
Base class for all map layer types.
Definition: qgsmaplayer.h:73
QgsMapLayerType type
Definition: qgsmaplayer.h:80
void triggerRepaint(bool deferredUpdate=false)
Will advise the map canvas (and any other interested party) that this layer requires to be repainted.
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:478
void setDirty(bool b=true)
Flag the project as dirty (modified).
Definition: qgsproject.cpp:574
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.
Q_INVOKABLE QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
void setLabelsEnabled(bool enabled)
Sets whether labels should be enabled for the layer.
const QgsAbstractVectorLayerLabeling * labeling() const
Access to const labeling configuration.
QString displayField() const
This is a shorthand for accessing the displayExpression if it is a simple field.
@ VectorLayer
Vector layer.
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:2330