QGIS API Documentation 4.1.0-Master (376402f9aeb)
Loading...
Searching...
No Matches
qgslabelinggui.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgslabelinggui.cpp
3 Smart labeling for vector layers
4 -------------------
5 begin : June 2009
6 copyright : (C) Martin Dobias
7 email : wonder dot sk at gmail dot com
8
9 ***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18#include "qgslabelinggui.h"
19
21#include "qgsapplication.h"
22#include "qgscallout.h"
23#include "qgscalloutsregistry.h"
26#include "qgsgui.h"
27#include "qgshelp.h"
31#include "qgsmapcanvas.h"
32#include "qgsmeshlayer.h"
33#include "qgsproject.h"
35#include "qgsstylesavedialog.h"
36#include "qgsvectorlayer.h"
37#include "qgsvectortilelayer.h"
38
39#include <QButtonGroup>
40#include <QMessageBox>
41#include <QString>
42
43#include "moc_qgslabelinggui.cpp"
44
45using namespace Qt::StringLiterals;
46
48
49QgsExpressionContext QgsLabelingGui::createExpressionContext() const
50{
51 QgsExpressionContext expContext;
52 if ( mMapCanvas )
53 {
54 expContext = mMapCanvas->createExpressionContext();
55 }
56 else
57 {
59 }
60
61 if ( mLayer )
62 expContext << QgsExpressionContextUtils::layerScope( mLayer );
63
64 if ( mLayer && mLayer->type() == Qgis::LayerType::Mesh )
65 {
66 if ( mGeomType == Qgis::GeometryType::Point )
68 else if ( mGeomType == Qgis::GeometryType::Polygon )
70 }
71
72 expContext << QgsExpressionContextUtils::updateSymbolScope( nullptr, new QgsExpressionContextScope() );
73
74 //TODO - show actual value
75 expContext.setOriginalValueVariable( QVariant() );
77
78 return expContext;
79}
80
81void QgsLabelingGui::updateCalloutWidget( QgsCallout *callout )
82{
83 if ( !callout )
84 {
85 mCalloutStackedWidget->setCurrentWidget( pageDummy );
86 return;
87 }
88
89 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( mLayer );
90 if ( !vLayer )
91 {
92 mCalloutStackedWidget->setCurrentWidget( pageDummy );
93 return;
94 }
95
96 if ( mCalloutStackedWidget->currentWidget() != pageDummy )
97 {
98 // stop updating from the original widget
99 if ( QgsCalloutWidget *pew = qobject_cast<QgsCalloutWidget *>( mCalloutStackedWidget->currentWidget() ) )
100 disconnect( pew, &QgsCalloutWidget::changed, this, &QgsLabelingGui::updatePreview );
101 }
102
103 QgsCalloutRegistry *registry = QgsApplication::calloutRegistry();
104 if ( QgsCalloutAbstractMetadata *am = registry->calloutMetadata( callout->type() ) )
105 {
106 if ( QgsCalloutWidget *w = am->createCalloutWidget( vLayer ) )
107 {
108 Qgis::GeometryType geometryType = mGeomType;
109 if ( mGeometryGeneratorGroupBox->isChecked() )
110 geometryType = mGeometryGeneratorType->currentData().value<Qgis::GeometryType>();
111 else if ( vLayer )
112 geometryType = vLayer->geometryType();
113 w->setGeometryType( geometryType );
114 w->setCallout( callout );
115
116 w->setContext( context() );
117 mCalloutStackedWidget->addWidget( w );
118 mCalloutStackedWidget->setCurrentWidget( w );
119 // start receiving updates from widget
120 connect( w, &QgsCalloutWidget::changed, this, &QgsLabelingGui::updatePreview );
121 return;
122 }
123 }
124 // When anything is not right
125 mCalloutStackedWidget->setCurrentWidget( pageDummy );
126}
127
128void QgsLabelingGui::showObstacleSettings()
129{
130 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( mLayer );
131 if ( !vLayer )
132 {
133 return;
134 }
135
136 QgsExpressionContext context = createExpressionContext();
137
138 QgsSymbolWidgetContext symbolContext;
139 symbolContext.setExpressionContext( &context );
140 symbolContext.setMapCanvas( mMapCanvas );
141
142 QgsLabelObstacleSettingsWidget *widget = new QgsLabelObstacleSettingsWidget( nullptr, vLayer );
143 widget->setDataDefinedProperties( mDataDefinedProperties );
144 widget->setSettings( mObstacleSettings );
145 widget->setGeometryType( vLayer->geometryType() );
146 widget->setContext( symbolContext );
147
148 auto applySettings = [this, widget] {
149 mObstacleSettings = widget->settings();
150 const QgsPropertyCollection obstacleDataDefinedProperties = widget->dataDefinedProperties();
151 widget->updateDataDefinedProperties( mDataDefinedProperties );
152 emit widgetChanged();
153 };
154
155 QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( this );
156 if ( panel && panel->dockMode() )
157 {
158 connect( widget, &QgsLabelSettingsWidgetBase::changed, this, [applySettings] { applySettings(); } );
159 panel->openPanel( widget );
160 }
161 else
162 {
163 QgsLabelSettingsWidgetDialog dialog( widget, this );
164
165 dialog.buttonBox()->addButton( QDialogButtonBox::Help );
166 connect( dialog.buttonBox(), &QDialogButtonBox::helpRequested, this, [] { QgsHelp::openHelp( u"style_library/label_settings.html#obstacles"_s ); } );
167
168 if ( dialog.exec() )
169 {
170 applySettings();
171 }
172 // reactivate button's window
173 activateWindow();
174 }
175}
176
177void QgsLabelingGui::showLineAnchorSettings()
178{
179 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( mLayer );
180 if ( !vLayer )
181 {
182 return;
183 }
184
185 QgsExpressionContext context = createExpressionContext();
186
187 QgsSymbolWidgetContext symbolContext;
188 symbolContext.setExpressionContext( &context );
189 symbolContext.setMapCanvas( mMapCanvas );
190
191 QgsLabelLineAnchorWidget *widget = new QgsLabelLineAnchorWidget( nullptr, vLayer );
192 widget->setDataDefinedProperties( mDataDefinedProperties );
193 widget->setSettings( mLineSettings );
194 widget->setGeometryType( vLayer->geometryType() );
195 widget->setContext( symbolContext );
196
197 auto applySettings = [this, widget] {
198 const QgsLabelLineSettings widgetSettings = widget->settings();
199 mLineSettings.setLineAnchorPercent( widgetSettings.lineAnchorPercent() );
200 mLineSettings.setAnchorType( widgetSettings.anchorType() );
201 mLineSettings.setAnchorClipping( widgetSettings.anchorClipping() );
202 mLineSettings.setAnchorTextPoint( widgetSettings.anchorTextPoint() );
203 const QgsPropertyCollection obstacleDataDefinedProperties = widget->dataDefinedProperties();
204 widget->updateDataDefinedProperties( mDataDefinedProperties );
205 emit widgetChanged();
206 };
207
208 QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( this );
209 if ( panel && panel->dockMode() )
210 {
211 connect( widget, &QgsLabelSettingsWidgetBase::changed, this, [applySettings] { applySettings(); } );
212 panel->openPanel( widget );
213 }
214 else
215 {
216 QgsLabelSettingsWidgetDialog dialog( widget, this );
217
218 dialog.buttonBox()->addButton( QDialogButtonBox::Help );
219 connect( dialog.buttonBox(), &QDialogButtonBox::helpRequested, this, [] { QgsHelp::openHelp( u"style_library/label_settings.html#placement-for-line-layers"_s ); } );
220
221 if ( dialog.exec() )
222 {
223 applySettings();
224 }
225 // reactivate button's window
226 activateWindow();
227 }
228}
229
230void QgsLabelingGui::showDuplicateSettings()
231{
232 QgsExpressionContext context = createExpressionContext();
233
234 QgsSymbolWidgetContext symbolContext;
235 symbolContext.setExpressionContext( &context );
236 symbolContext.setMapCanvas( mMapCanvas );
237
238 QgsLabelRemoveDuplicatesSettingsWidget *widget = new QgsLabelRemoveDuplicatesSettingsWidget( nullptr, mLayer );
239 widget->setDataDefinedProperties( mDataDefinedProperties );
240 widget->setSettings( mThinningSettings );
241 auto vectorLayer = qobject_cast< QgsVectorLayer * >( mLayer );
242 widget->setGeometryType( vectorLayer ? vectorLayer->geometryType() : Qgis::GeometryType::Unknown );
243 widget->setContext( symbolContext );
244
245 auto applySettings = [this, widget] {
246 mThinningSettings = widget->settings();
247 const QgsPropertyCollection obstacleDataDefinedProperties = widget->dataDefinedProperties();
248 widget->updateDataDefinedProperties( mDataDefinedProperties );
249 emit widgetChanged();
250 };
251
252 QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( this );
253 if ( panel && panel->dockMode() )
254 {
255 connect( widget, &QgsLabelSettingsWidgetBase::changed, this, [applySettings] { applySettings(); } );
256 panel->openPanel( widget );
257 }
258 else
259 {
260 QgsLabelSettingsWidgetDialog dialog( widget, this );
261 if ( dialog.exec() )
262 {
263 applySettings();
264 }
265 // reactivate button's window
266 activateWindow();
267 }
268}
269
270QgsLabelingGui::QgsLabelingGui( QgsVectorLayer *layer, QgsMapCanvas *mapCanvas, const QgsPalLayerSettings &layerSettings, QWidget *parent, Qgis::GeometryType geomType )
271 : QgsTextFormatWidget( mapCanvas, parent, QgsTextFormatWidget::Labeling, layer )
272 , mMode( NoLabels )
273 , mSettings( layerSettings )
274{
275 mGeomType = geomType;
276
277 init();
278
279 setLayer( layer );
280}
281
282QgsLabelingGui::QgsLabelingGui( QgsMeshLayer *layer, QgsMapCanvas *mapCanvas, const QgsPalLayerSettings &settings, QWidget *parent, Qgis::GeometryType geomType )
283 : QgsTextFormatWidget( mapCanvas, parent, QgsTextFormatWidget::Labeling, layer )
284 , mMode( NoLabels )
285 , mSettings( settings )
286{
287 mGeomType = geomType;
288
289 init();
290
291 setLayer( layer );
292}
293
294QgsLabelingGui::QgsLabelingGui( QgsVectorTileLayer *layer, QgsMapCanvas *mapCanvas, const QgsPalLayerSettings &settings, QWidget *parent, Qgis::GeometryType geomType )
295 : QgsTextFormatWidget( mapCanvas, parent, QgsTextFormatWidget::Labeling, layer )
296 , mMode( NoLabels )
297 , mSettings( settings )
298{
299 mGeomType = geomType;
300
301 init();
302
303 setLayer( layer );
304}
305
306
307QgsLabelingGui::QgsLabelingGui( QgsMapCanvas *mapCanvas, QWidget *parent, QgsMapLayer *layer )
308 : QgsTextFormatWidget( mapCanvas, parent, QgsTextFormatWidget::Labeling, layer )
309 , mMode( NoLabels )
310{}
311
312
313QgsLabelingGui::QgsLabelingGui( QgsMapCanvas *mapCanvas, const QgsPalLayerSettings &settings, QWidget *parent )
314 : QgsTextFormatWidget( mapCanvas, parent, QgsTextFormatWidget::Labeling, nullptr )
315 , mMode( NoLabels )
316 , mSettings( settings )
317{
318 init();
319
320 setLayer( nullptr );
321}
322
323void QgsLabelingGui::init()
324{
326
327 mStackedWidgetLabelWith->setSizeMode( QgsStackedWidget::SizeMode::CurrentPageOnly );
328
329 mFontMultiLineAlignComboBox->addItem( tr( "Left" ), static_cast<int>( Qgis::LabelMultiLineAlignment::Left ) );
330 mFontMultiLineAlignComboBox->addItem( tr( "Center" ), static_cast<int>( Qgis::LabelMultiLineAlignment::Center ) );
331 mFontMultiLineAlignComboBox->addItem( tr( "Right" ), static_cast<int>( Qgis::LabelMultiLineAlignment::Right ) );
332 mFontMultiLineAlignComboBox->addItem( tr( "Justify" ), static_cast<int>( Qgis::LabelMultiLineAlignment::Justify ) );
333
334 mCoordRotationUnitComboBox->addItem( QgsUnitTypes::toString( Qgis::AngleUnit::Degrees ), static_cast<int>( Qgis::AngleUnit::Degrees ) );
335 mCoordRotationUnitComboBox->addItem( QgsUnitTypes::toString( Qgis::AngleUnit::Radians ), static_cast<int>( Qgis::AngleUnit::Radians ) );
336 mCoordRotationUnitComboBox->addItem( QgsUnitTypes::toString( Qgis::AngleUnit::Gon ), static_cast<int>( Qgis::AngleUnit::Gon ) );
337 mCoordRotationUnitComboBox->addItem( QgsUnitTypes::toString( Qgis::AngleUnit::MinutesOfArc ), static_cast<int>( Qgis::AngleUnit::MinutesOfArc ) );
338 mCoordRotationUnitComboBox->addItem( QgsUnitTypes::toString( Qgis::AngleUnit::SecondsOfArc ), static_cast<int>( Qgis::AngleUnit::SecondsOfArc ) );
339 mCoordRotationUnitComboBox->addItem( QgsUnitTypes::toString( Qgis::AngleUnit::Turn ), static_cast<int>( Qgis::AngleUnit::Turn ) );
340 mCoordRotationUnitComboBox->addItem( QgsUnitTypes::toString( Qgis::AngleUnit::MilliradiansSI ), static_cast<int>( Qgis::AngleUnit::MilliradiansSI ) );
341 mCoordRotationUnitComboBox->addItem( QgsUnitTypes::toString( Qgis::AngleUnit::MilNATO ), static_cast<int>( Qgis::AngleUnit::MilNATO ) );
342
343 // connections for groupboxes with separate activation checkboxes (that need to honor data defined setting)
344 connect( mBufferDrawChkBx, &QAbstractButton::toggled, this, &QgsLabelingGui::updateUi );
345 connect( mBufferDrawDDBtn, &QgsPropertyOverrideButton::changed, this, &QgsLabelingGui::updateUi );
346 connect( mEnableMaskChkBx, &QAbstractButton::toggled, this, &QgsLabelingGui::updateUi );
347 connect( mShapeDrawChkBx, &QAbstractButton::toggled, this, &QgsLabelingGui::updateUi );
348 connect( mCalloutsDrawCheckBox, &QAbstractButton::toggled, this, &QgsLabelingGui::updateUi );
349 connect( mShadowDrawChkBx, &QAbstractButton::toggled, this, &QgsLabelingGui::updateUi );
350 connect( mDirectSymbChkBx, &QAbstractButton::toggled, this, &QgsLabelingGui::updateUi );
351 connect( mFormatNumChkBx, &QAbstractButton::toggled, this, &QgsLabelingGui::updateUi );
352 connect( mScaleBasedVisibilityChkBx, &QAbstractButton::toggled, this, &QgsLabelingGui::updateUi );
353 connect( mFontLimitPixelChkBox, &QAbstractButton::toggled, this, &QgsLabelingGui::updateUi );
354 connect( mGeometryGeneratorGroupBox, &QGroupBox::toggled, this, &QgsLabelingGui::updateGeometryTypeBasedWidgets );
355 connect( mGeometryGeneratorType, qOverload<int>( &QComboBox::currentIndexChanged ), this, &QgsLabelingGui::updateGeometryTypeBasedWidgets );
356 connect( mGeometryGeneratorExpressionButton, &QToolButton::clicked, this, &QgsLabelingGui::showGeometryGeneratorExpressionBuilder );
357 connect( mGeometryGeneratorGroupBox, &QGroupBox::toggled, this, &QgsLabelingGui::validateGeometryGeneratorExpression );
358 connect( mGeometryGenerator, &QgsCodeEditorExpression::textChanged, this, &QgsLabelingGui::validateGeometryGeneratorExpression );
359 connect( mGeometryGeneratorType, qOverload<int>( &QComboBox::currentIndexChanged ), this, &QgsLabelingGui::validateGeometryGeneratorExpression );
360 connect( mObstacleSettingsButton, &QAbstractButton::clicked, this, &QgsLabelingGui::showObstacleSettings );
361 connect( mLineAnchorSettingsButton, &QAbstractButton::clicked, this, &QgsLabelingGui::showLineAnchorSettings );
362 connect( mDuplicateSettingsButton, &QAbstractButton::clicked, this, &QgsLabelingGui::showDuplicateSettings );
363
364 mFieldExpressionWidget->registerExpressionContextGenerator( this );
365
366 mMinScaleWidget->setMapCanvas( mMapCanvas );
367 mMinScaleWidget->setShowCurrentScaleButton( true );
368 mMaxScaleWidget->setMapCanvas( mMapCanvas );
369 mMaxScaleWidget->setShowCurrentScaleButton( true );
370
371 mGeometryGeneratorExpressionButton->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
372 mGeometryGeneratorExpressionButton->setIcon( QgsApplication::getThemeIcon( u"/mIconExpression.svg"_s ) );
373
374 const QStringList calloutTypes = QgsApplication::calloutRegistry()->calloutTypes();
375 for ( const QString &type : calloutTypes )
376 {
377 mCalloutStyleComboBox->addItem( QgsApplication::calloutRegistry()->calloutMetadata( type )->icon(), QgsApplication::calloutRegistry()->calloutMetadata( type )->visibleName(), type );
378 }
379
380 mGeometryGeneratorWarningLabel->setStyleSheet( u"color: #FFC107;"_s );
381 mGeometryGeneratorWarningLabel->setTextInteractionFlags( Qt::TextBrowserInteraction );
382 connect( mGeometryGeneratorWarningLabel, &QLabel::linkActivated, this, [this]( const QString &link ) {
383 if ( link == "#determineGeometryGeneratorType"_L1 )
384 determineGeometryGeneratorType();
385 } );
386
387 connect( mCalloutStyleComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsLabelingGui::calloutTypeChanged );
388
389 mLblNoObstacle1->installEventFilter( this );
390}
391
392void QgsLabelingGui::setLayer( QgsMapLayer *mapLayer )
393{
394 mPreviewFeature = QgsFeature();
395
396 if ( ( !mapLayer || mapLayer->type() != Qgis::LayerType::Vector ) && mGeomType == Qgis::GeometryType::Unknown )
397 {
398 setEnabled( false );
399 return;
400 }
401
402 setEnabled( true );
403
404 mLayer = mapLayer;
405 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( mapLayer );
406
407 mTextFormatsListWidget->setLayerType( vLayer ? vLayer->geometryType() : mGeomType );
408 mBackgroundMarkerSymbolButton->setLayer( vLayer );
409 mBackgroundFillSymbolButton->setLayer( vLayer );
410
411 // load labeling settings from layer
412 updateGeometryTypeBasedWidgets();
413
414 mFieldExpressionWidget->setLayer( mapLayer );
415 QgsDistanceArea da;
416 if ( mLayer )
417 da.setSourceCrs( mLayer->crs(), QgsProject::instance()->transformContext() );
418 da.setEllipsoid( QgsProject::instance()->ellipsoid() );
419 mFieldExpressionWidget->setGeomCalculator( da );
420
421 mFieldExpressionWidget->setEnabled( mMode == Labels || !mLayer );
422 mLabelingFrame->setEnabled( mMode == Labels || !mLayer );
423
424 blockInitSignals( true );
425
426 mGeometryGenerator->setText( mSettings.geometryGenerator );
427 mGeometryGeneratorGroupBox->setChecked( mSettings.geometryGeneratorEnabled );
428 if ( !mSettings.geometryGeneratorEnabled )
429 mGeometryGeneratorGroupBox->setCollapsed( true );
430 mGeometryGeneratorType->setCurrentIndex( mGeometryGeneratorType->findData( QVariant::fromValue( mSettings.geometryGeneratorType ) ) );
431
432 updateWidgetForFormat( mSettings.format().isValid() ? mSettings.format() : QgsStyle::defaultTextFormatForProject( QgsProject::instance(), QgsStyle::TextFormatContext::Labeling ) );
433
434 mFieldExpressionWidget->setRow( -1 );
435 mFieldExpressionWidget->setField( mSettings.fieldName );
436 mCheckBoxSubstituteText->setChecked( mSettings.useSubstitutions );
437 mSubstitutions = mSettings.substitutions;
438
439 // populate placement options
440 mCentroidRadioWhole->setChecked( mSettings.centroidWhole );
441 mCentroidInsideCheckBox->setChecked( mSettings.centroidInside );
442 mFitInsidePolygonCheckBox->setChecked( mSettings.fitInPolygonOnly );
443 mLineDistanceSpnBx->setValue( mSettings.dist );
444 mLineDistanceUnitWidget->setUnit( mSettings.distUnits );
445 mLineDistanceUnitWidget->setMapUnitScale( mSettings.distMapUnitScale );
446
447 mMaximumDistanceSpnBx->setValue( mSettings.pointSettings().maximumDistance() );
448 mMaximumDistanceUnitWidget->setUnit( mSettings.pointSettings().maximumDistanceUnit() );
449 mMaximumDistanceUnitWidget->setMapUnitScale( mSettings.pointSettings().maximumDistanceMapUnitScale() );
450
451 mOffsetTypeComboBox->setCurrentIndex( mOffsetTypeComboBox->findData( static_cast<int>( mSettings.offsetType ) ) );
452 mQuadrantBtnGrp->button( static_cast<int>( mSettings.pointSettings().quadrant() ) )->setChecked( true );
453 mPointOffsetXSpinBox->setValue( mSettings.xOffset );
454 mPointOffsetYSpinBox->setValue( mSettings.yOffset );
455 mPointOffsetUnitWidget->setUnit( mSettings.offsetUnits );
456 mPointOffsetUnitWidget->setMapUnitScale( mSettings.labelOffsetMapUnitScale );
457 mPointAngleSpinBox->setValue( mSettings.angleOffset );
458 chkLineAbove->setChecked( mSettings.lineSettings().placementFlags() & Qgis::LabelLinePlacementFlag::AboveLine );
459 chkLineBelow->setChecked( mSettings.lineSettings().placementFlags() & Qgis::LabelLinePlacementFlag::BelowLine );
460 chkLineOn->setChecked( mSettings.lineSettings().placementFlags() & Qgis::LabelLinePlacementFlag::OnLine );
461 chkLineOrientationDependent->setChecked( !( mSettings.lineSettings().placementFlags() & Qgis::LabelLinePlacementFlag::MapOrientation ) );
462
463 mCheckAllowLabelsOutsidePolygons->setChecked( mSettings.polygonPlacementFlags() & Qgis::LabelPolygonPlacementFlag::AllowPlacementOutsideOfPolygon );
464
465 const int placementIndex = mPlacementModeComboBox->findData( static_cast<int>( mSettings.placement ) );
466 if ( placementIndex >= 0 )
467 {
468 mPlacementModeComboBox->setCurrentIndex( placementIndex );
469 }
470 else
471 {
472 // use default placement for layer type
473 mPlacementModeComboBox->setCurrentIndex( 0 );
474 }
475
476 // Label repeat distance
477 mRepeatDistanceSpinBox->setValue( mSettings.repeatDistance );
478 mRepeatDistanceUnitWidget->setUnit( mSettings.repeatDistanceUnit );
479 mRepeatDistanceUnitWidget->setMapUnitScale( mSettings.repeatDistanceMapUnitScale );
480
481 mOverrunDistanceSpinBox->setValue( mSettings.lineSettings().overrunDistance() );
482 mOverrunDistanceUnitWidget->setUnit( mSettings.lineSettings().overrunDistanceUnit() );
483 mOverrunDistanceUnitWidget->setMapUnitScale( mSettings.lineSettings().overrunDistanceMapUnitScale() );
484
485 mThinningSettings = mSettings.thinningSettings();
486
487 mLabelMarginSpinBox->setValue( mThinningSettings.labelMarginDistance() );
488 mLabelMarginUnitWidget->setUnit( mThinningSettings.labelMarginDistanceUnit() );
489 mLabelMarginUnitWidget->setMapUnitScale( mThinningSettings.labelMarginDistanceMapUnitScale() );
490
491 mPrioritySlider->setValue( mSettings.priority );
492 mChkNoObstacle->setChecked( mSettings.obstacleSettings().isObstacle() );
493
494 mObstacleSettings = mSettings.obstacleSettings();
495
496 mChkNoDuplicates->setChecked( mThinningSettings.allowDuplicateRemoval() );
497
498 mLineSettings = mSettings.lineSettings();
499
500 mComboMultipartBehavior->setCurrentIndex( mComboMultipartBehavior->findData( QVariant::fromValue( mSettings.placementSettings().multiPartBehavior() ) ) );
501
502 mComboOverlapHandling->setCurrentIndex( mComboOverlapHandling->findData( static_cast<int>( mSettings.placementSettings().overlapHandling() ) ) );
503 mCheckAllowDegradedPlacement->setChecked( mSettings.placementSettings().allowDegradedPlacement() );
504 mPrioritizationComboBox->setCurrentIndex( mPrioritizationComboBox->findData( QVariant::fromValue( mSettings.placementSettings().prioritization() ) ) );
505
506 mComboCurvedLabelMode->setCurrentIndex( mComboCurvedLabelMode->findData( QVariant::fromValue( mSettings.lineSettings().curvedLabelMode() ) ) );
507
508 mCheckWhitespaceIsNotACollision->setChecked( mSettings.placementSettings().whitespaceCollisionHandling() == Qgis::LabelWhitespaceCollisionHandling::IgnoreWhitespaceCollisions );
509
510 chkMergeLines->setChecked( mSettings.lineSettings().mergeLines() );
511 mMinSizeSpinBox->setValue( mThinningSettings.minimumFeatureSize() );
512 mLimitLabelChkBox->setChecked( mThinningSettings.limitNumberOfLabelsEnabled() );
513 mLimitLabelSpinBox->setValue( mThinningSettings.maximumNumberLabels() );
514
515 // direction symbol(s)
516 mDirectSymbChkBx->setChecked( mSettings.lineSettings().addDirectionSymbol() );
517 mDirectSymbLeftLineEdit->setText( mSettings.lineSettings().leftDirectionSymbol() );
518 mDirectSymbRightLineEdit->setText( mSettings.lineSettings().rightDirectionSymbol() );
519 mDirectSymbRevChkBx->setChecked( mSettings.lineSettings().reverseDirectionSymbol() );
520
521 mDirectSymbBtnGrp->button( static_cast<int>( mSettings.lineSettings().directionSymbolPlacement() ) )->setChecked( true );
522 mUpsidedownBtnGrp->button( static_cast<int>( mSettings.upsidedownLabels ) )->setChecked( true );
523
524 // curved label max character angles
525 mMaxCharAngleInDSpinBox->setValue( mSettings.maxCurvedCharAngleIn );
526 // lyr.maxCurvedCharAngleOut must be negative, but it is shown as positive spinbox in GUI
527 mMaxCharAngleOutDSpinBox->setValue( std::fabs( mSettings.maxCurvedCharAngleOut ) );
528
529 wrapCharacterEdit->setText( mSettings.wrapChar );
530 mAutoWrapLengthSpinBox->setValue( mSettings.autoWrapLength );
531 mAutoWrapTypeComboBox->setCurrentIndex( mSettings.useMaxLineLengthForAutoWrap ? 0 : 1 );
532
533 if ( mFontMultiLineAlignComboBox->findData( static_cast<int>( mSettings.multilineAlign ) ) != -1 )
534 {
535 mFontMultiLineAlignComboBox->setCurrentIndex( mFontMultiLineAlignComboBox->findData( static_cast<int>( mSettings.multilineAlign ) ) );
536 }
537 else
538 {
539 // the default pal layer settings for multiline alignment is to follow label placement, which isn't always available
540 // revert to left alignment in such case
541 mFontMultiLineAlignComboBox->setCurrentIndex( 0 );
542 }
543
544 chkPreserveRotation->setChecked( mSettings.preserveRotation );
545
546 mCoordRotationUnitComboBox->setCurrentIndex( 0 );
547 if ( mCoordRotationUnitComboBox->findData( static_cast<unsigned int>( mSettings.rotationUnit() ) ) >= 0 )
548 mCoordRotationUnitComboBox->setCurrentIndex( mCoordRotationUnitComboBox->findData( static_cast<unsigned int>( mSettings.rotationUnit() ) ) );
549
550 mScaleBasedVisibilityChkBx->setChecked( mSettings.scaleVisibility );
551 mMinScaleWidget->setScale( mSettings.minimumScale );
552 mMaxScaleWidget->setScale( mSettings.maximumScale );
553
554 mFormatNumChkBx->setChecked( mSettings.formatNumbers );
555 mFormatNumDecimalsSpnBx->setValue( mSettings.decimals );
556 mFormatNumPlusSignChkBx->setChecked( mSettings.plusSign );
557
558 // set pixel size limiting checked state before unit choice so limiting can be
559 // turned on as a default for map units, if minimum trigger value of 0 is used
560 mFontLimitPixelChkBox->setChecked( mSettings.fontLimitPixelSize );
561 mMinPixelLimit = mSettings.fontMinPixelSize; // ignored after first settings save
562 mFontMinPixelSpinBox->setValue( mSettings.fontMinPixelSize == 0 ? 3 : mSettings.fontMinPixelSize );
563 mFontMaxPixelSpinBox->setValue( mSettings.fontMaxPixelSize );
564
565 mZIndexSpinBox->setValue( mSettings.zIndex );
566
567 mDataDefinedProperties = mSettings.dataDefinedProperties();
568
569 // callout settings, to move to custom widget when multiple styles exist
570 if ( auto *lCallout = mSettings.callout() )
571 {
572 whileBlocking( mCalloutsDrawCheckBox )->setChecked( lCallout->enabled() );
573 whileBlocking( mCalloutStyleComboBox )->setCurrentIndex( mCalloutStyleComboBox->findData( lCallout->type() ) );
574 updateCalloutWidget( lCallout );
575 }
576 else
577 {
578 std::unique_ptr<QgsCallout> defaultCallout( QgsCalloutRegistry::defaultCallout() );
579 whileBlocking( mCalloutStyleComboBox )->setCurrentIndex( mCalloutStyleComboBox->findData( defaultCallout->type() ) );
580 whileBlocking( mCalloutsDrawCheckBox )->setChecked( false );
581 updateCalloutWidget( defaultCallout.get() );
582 }
583
584 updatePlacementWidgets();
585 updateLinePlacementOptions();
586
587 // needs to come before data defined setup, so connections work
588 blockInitSignals( false );
589
590 // set up data defined toolbuttons
591 // do this after other widgets are configured, so they can be enabled/disabled
592 populateDataDefinedButtons();
593
594 updateUi(); // should come after data defined button setup
595}
596
597void QgsLabelingGui::setSettings( const QgsPalLayerSettings &settings )
598{
599 mSettings = settings;
600 setLayer( mLayer );
601}
602
603void QgsLabelingGui::blockInitSignals( bool block )
604{
605 chkLineAbove->blockSignals( block );
606 chkLineBelow->blockSignals( block );
607 mPlacementModeComboBox->blockSignals( block );
608}
609
610void QgsLabelingGui::setLabelMode( LabelMode mode )
611{
612 mMode = mode;
613 mFieldExpressionWidget->setEnabled( mMode == Labels );
614 mLabelingFrame->setEnabled( mMode == Labels );
615}
616
617QgsPalLayerSettings QgsLabelingGui::layerSettings()
618{
619 QgsPalLayerSettings lyr;
620
621 // restore properties which aren't exposed in GUI
622 lyr.setUnplacedVisibility( mSettings.unplacedVisibility() );
623
624 lyr.drawLabels = ( mMode == Labels ) || !mLayer;
625
626 bool isExpression;
627 lyr.fieldName = mFieldExpressionWidget->currentField( &isExpression );
628 lyr.isExpression = isExpression;
629
630 lyr.dist = 0;
631
633 if ( mCheckAllowLabelsOutsidePolygons->isChecked() )
635 lyr.setPolygonPlacementFlags( polygonPlacementFlags );
636
637 lyr.centroidWhole = mCentroidRadioWhole->isChecked();
638 lyr.centroidInside = mCentroidInsideCheckBox->isChecked();
639 lyr.fitInPolygonOnly = mFitInsidePolygonCheckBox->isChecked();
640 lyr.dist = mLineDistanceSpnBx->value();
641 lyr.distUnits = mLineDistanceUnitWidget->unit();
642 lyr.distMapUnitScale = mLineDistanceUnitWidget->getMapUnitScale();
643
644 lyr.pointSettings().setMaximumDistance( mMaximumDistanceSpnBx->value() );
645 lyr.pointSettings().setMaximumDistanceUnit( mMaximumDistanceUnitWidget->unit() );
646 lyr.pointSettings().setMaximumDistanceMapUnitScale( mMaximumDistanceUnitWidget->getMapUnitScale() );
647
648 lyr.offsetType = static_cast<Qgis::LabelOffsetType>( mOffsetTypeComboBox->currentData().toInt() );
649 if ( mQuadrantBtnGrp )
650 {
651 lyr.pointSettings().setQuadrant( static_cast<Qgis::LabelQuadrantPosition>( mQuadrantBtnGrp->checkedId() ) );
652 }
653 lyr.xOffset = mPointOffsetXSpinBox->value();
654 lyr.yOffset = mPointOffsetYSpinBox->value();
655 lyr.offsetUnits = mPointOffsetUnitWidget->unit();
656 lyr.labelOffsetMapUnitScale = mPointOffsetUnitWidget->getMapUnitScale();
657 lyr.angleOffset = mPointAngleSpinBox->value();
658
660 if ( chkLineAbove->isChecked() )
661 linePlacementFlags |= Qgis::LabelLinePlacementFlag::AboveLine;
662 if ( chkLineBelow->isChecked() )
663 linePlacementFlags |= Qgis::LabelLinePlacementFlag::BelowLine;
664 if ( chkLineOn->isChecked() )
665 linePlacementFlags |= Qgis::LabelLinePlacementFlag::OnLine;
666 if ( !chkLineOrientationDependent->isChecked() )
668 lyr.lineSettings().setPlacementFlags( linePlacementFlags );
669
670 lyr.placement = static_cast<Qgis::LabelPlacement>( mPlacementModeComboBox->currentData().toInt() );
671
672 lyr.repeatDistance = mRepeatDistanceSpinBox->value();
673 lyr.repeatDistanceUnit = mRepeatDistanceUnitWidget->unit();
674 lyr.repeatDistanceMapUnitScale = mRepeatDistanceUnitWidget->getMapUnitScale();
675
676 lyr.lineSettings().setOverrunDistance( mOverrunDistanceSpinBox->value() );
677 lyr.lineSettings().setOverrunDistanceUnit( mOverrunDistanceUnitWidget->unit() );
678 lyr.lineSettings().setOverrunDistanceMapUnitScale( mOverrunDistanceUnitWidget->getMapUnitScale() );
679
680 mThinningSettings.setLabelMarginDistance( mLabelMarginSpinBox->value() );
681 mThinningSettings.setLabelMarginDistanceUnit( mLabelMarginUnitWidget->unit() );
682 mThinningSettings.setLabelMarginDistanceMapUnitScale( mLabelMarginUnitWidget->getMapUnitScale() );
683
684 lyr.priority = mPrioritySlider->value();
685
686 mObstacleSettings.setIsObstacle( mChkNoObstacle->isChecked() || mMode == ObstaclesOnly );
687 lyr.setObstacleSettings( mObstacleSettings );
688
689 lyr.lineSettings().setLineAnchorPercent( mLineSettings.lineAnchorPercent() );
690 lyr.lineSettings().setAnchorType( mLineSettings.anchorType() );
691 lyr.lineSettings().setAnchorClipping( mLineSettings.anchorClipping() );
692 lyr.lineSettings().setAnchorTextPoint( mLineSettings.anchorTextPoint() );
693
694 mThinningSettings.setAllowDuplicateRemoval( mChkNoDuplicates->isChecked() );
695
696 lyr.placementSettings().setMultiPartBehavior( mComboMultipartBehavior->currentData().value< Qgis::MultiPartLabelingBehavior >() );
697 lyr.placementSettings().setOverlapHandling( static_cast<Qgis::LabelOverlapHandling>( mComboOverlapHandling->currentData().toInt() ) );
698 lyr.placementSettings().setAllowDegradedPlacement( mCheckAllowDegradedPlacement->isChecked() );
699 lyr.placementSettings().setPrioritization( mPrioritizationComboBox->currentData().value<Qgis::LabelPrioritization>() );
702 );
703
704 lyr.lineSettings().setMergeLines( chkMergeLines->isChecked() );
705 lyr.lineSettings().setCurvedLabelMode( mComboCurvedLabelMode->currentData().value< Qgis::CurvedLabelMode >() );
706
707 lyr.scaleVisibility = mScaleBasedVisibilityChkBx->isChecked();
708 lyr.minimumScale = mMinScaleWidget->scale();
709 lyr.maximumScale = mMaxScaleWidget->scale();
710 lyr.useSubstitutions = mCheckBoxSubstituteText->isChecked();
711 lyr.substitutions = mSubstitutions;
712
713 lyr.setFormat( format( false ) );
714
715 // format numbers
716 lyr.formatNumbers = mFormatNumChkBx->isChecked();
717 lyr.decimals = mFormatNumDecimalsSpnBx->value();
718 lyr.plusSign = mFormatNumPlusSignChkBx->isChecked();
719
720 // direction symbol(s)
721 lyr.lineSettings().setAddDirectionSymbol( mDirectSymbChkBx->isChecked() );
722 lyr.lineSettings().setLeftDirectionSymbol( mDirectSymbLeftLineEdit->text() );
723 lyr.lineSettings().setRightDirectionSymbol( mDirectSymbRightLineEdit->text() );
724 lyr.lineSettings().setReverseDirectionSymbol( mDirectSymbRevChkBx->isChecked() );
725 if ( mDirectSymbBtnGrp )
726 {
727 lyr.lineSettings().setDirectionSymbolPlacement( static_cast<QgsLabelLineSettings::DirectionSymbolPlacement>( mDirectSymbBtnGrp->checkedId() ) );
728 }
729 if ( mUpsidedownBtnGrp )
730 {
731 lyr.upsidedownLabels = static_cast<Qgis::UpsideDownLabelHandling>( mUpsidedownBtnGrp->checkedId() );
732 }
733
734 lyr.maxCurvedCharAngleIn = mMaxCharAngleInDSpinBox->value();
735 // lyr.maxCurvedCharAngleOut must be negative, but it is shown as positive spinbox in GUI
736 lyr.maxCurvedCharAngleOut = -mMaxCharAngleOutDSpinBox->value();
737
738 mThinningSettings.setMinimumFeatureSize( mMinSizeSpinBox->value() );
739 mThinningSettings.setLimitNumberLabelsEnabled( mLimitLabelChkBox->isChecked() );
740 mThinningSettings.setMaximumNumberLabels( mLimitLabelSpinBox->value() );
741
742 lyr.setThinningSettings( mThinningSettings );
743
744 lyr.fontLimitPixelSize = mFontLimitPixelChkBox->isChecked();
745 lyr.fontMinPixelSize = mFontMinPixelSpinBox->value();
746 lyr.fontMaxPixelSize = mFontMaxPixelSpinBox->value();
747 lyr.wrapChar = wrapCharacterEdit->text();
748 lyr.autoWrapLength = mAutoWrapLengthSpinBox->value();
749 lyr.useMaxLineLengthForAutoWrap = mAutoWrapTypeComboBox->currentIndex() == 0;
750 lyr.multilineAlign = static_cast<Qgis::LabelMultiLineAlignment>( mFontMultiLineAlignComboBox->currentData().toInt() );
751 lyr.preserveRotation = chkPreserveRotation->isChecked();
752 lyr.setRotationUnit( static_cast<Qgis::AngleUnit>( mCoordRotationUnitComboBox->currentData().toInt() ) );
753 lyr.geometryGenerator = mGeometryGenerator->text();
754 lyr.geometryGeneratorType = mGeometryGeneratorType->currentData().value<Qgis::GeometryType>();
755 lyr.geometryGeneratorEnabled = mGeometryGeneratorGroupBox->isChecked();
756
757 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( mLayer );
758 lyr.layerType = vLayer ? vLayer->geometryType() : mGeomType;
759
760 lyr.zIndex = mZIndexSpinBox->value();
761
762 lyr.setDataDefinedProperties( mDataDefinedProperties );
763
764 // callout settings
765 const QString calloutType = mCalloutStyleComboBox->currentData().toString();
766 std::unique_ptr<QgsCallout> callout;
767 if ( QgsCalloutWidget *pew = qobject_cast<QgsCalloutWidget *>( mCalloutStackedWidget->currentWidget() ) )
768 {
769 callout.reset( pew->callout()->clone() );
770 }
771 if ( !callout )
772 callout.reset( QgsApplication::calloutRegistry()->createCallout( calloutType ) );
773
774 callout->setEnabled( mCalloutsDrawCheckBox->isChecked() );
775 lyr.setCallout( callout.release() );
776
777 return lyr;
778}
779
780void QgsLabelingGui::syncDefinedCheckboxFrame( QgsPropertyOverrideButton *ddBtn, QCheckBox *chkBx, QFrame *f )
781{
782 f->setEnabled( chkBx->isChecked() || ddBtn->isActive() );
783}
784
785bool QgsLabelingGui::eventFilter( QObject *object, QEvent *event )
786{
787 if ( object == mLblNoObstacle1 )
788 {
789 if ( event->type() == QEvent::MouseButtonPress && qgis::down_cast<QMouseEvent *>( event )->button() == Qt::LeftButton )
790 {
791 // clicking the obstacle label toggles the checkbox, just like a "normal" checkbox label...
792 mChkNoObstacle->setChecked( !mChkNoObstacle->isChecked() );
793 return true;
794 }
795 return false;
796 }
797 return QgsTextFormatWidget::eventFilter( object, event );
798}
799
800void QgsLabelingGui::updateUi()
801{
802 // enable/disable inline groupbox-like setups (that need to honor data defined setting)
803
804 syncDefinedCheckboxFrame( mBufferDrawDDBtn, mBufferDrawChkBx, mBufferFrame );
805 syncDefinedCheckboxFrame( mEnableMaskDDBtn, mEnableMaskChkBx, mMaskFrame );
806 syncDefinedCheckboxFrame( mShapeDrawDDBtn, mShapeDrawChkBx, mShapeFrame );
807 syncDefinedCheckboxFrame( mShadowDrawDDBtn, mShadowDrawChkBx, mShadowFrame );
808 syncDefinedCheckboxFrame( mCalloutDrawDDBtn, mCalloutsDrawCheckBox, mCalloutFrame );
809
810 syncDefinedCheckboxFrame( mDirectSymbDDBtn, mDirectSymbChkBx, mDirectSymbFrame );
811 syncDefinedCheckboxFrame( mFormatNumDDBtn, mFormatNumChkBx, mFormatNumFrame );
812 syncDefinedCheckboxFrame( mScaleBasedVisibilityDDBtn, mScaleBasedVisibilityChkBx, mScaleBasedVisibilityFrame );
813 syncDefinedCheckboxFrame( mFontLimitPixelDDBtn, mFontLimitPixelChkBox, mFontLimitPixelFrame );
814
815 chkMergeLines->setEnabled( !mDirectSymbChkBx->isChecked() );
816 if ( mDirectSymbChkBx->isChecked() )
817 {
818 chkMergeLines->setToolTip( tr( "This option is not compatible with line direction symbols." ) );
819 }
820 else
821 {
822 chkMergeLines->setToolTip( QString() );
823 }
824}
825
826void QgsLabelingGui::setFormatFromStyle( const QString &name, QgsStyle::StyleEntity type, const QString &stylePath )
827{
828 QgsStyle *style = QgsProject::instance()->styleSettings()->styleAtPath( stylePath );
829
830 if ( !style )
831 style = QgsStyle::defaultStyle();
832
833 switch ( type )
834 {
843 {
844 QgsTextFormatWidget::setFormatFromStyle( name, type, stylePath );
845 return;
846 }
847
849 {
850 if ( !style->labelSettingsNames().contains( name ) )
851 return;
852
853 QgsPalLayerSettings settings = style->labelSettings( name );
854 if ( settings.fieldName.isEmpty() )
855 {
856 // if saved settings doesn't have a field name stored, retain the current one
857 bool isExpression;
858 settings.fieldName = mFieldExpressionWidget->currentField( &isExpression );
859 settings.isExpression = isExpression;
860 }
861 setSettings( settings );
862 break;
863 }
864 }
865}
866
867void QgsLabelingGui::setContext( const QgsSymbolWidgetContext &context )
868{
869 if ( QgsCalloutWidget *cw = qobject_cast<QgsCalloutWidget *>( mCalloutStackedWidget->currentWidget() ) )
870 {
871 cw->setContext( context );
872 }
874}
875
876void QgsLabelingGui::saveFormat()
877{
878 QgsStyleSaveDialog saveDlg( this, QgsStyle::LabelSettingsEntity );
879 saveDlg.setDefaultTags( mTextFormatsListWidget->currentTagFilter() );
880 if ( !saveDlg.exec() )
881 return;
882
883 if ( saveDlg.name().isEmpty() )
884 return;
885
886 QgsStyle *style = saveDlg.destinationStyle();
887 if ( !style )
888 return;
889
890 switch ( saveDlg.selectedType() )
891 {
893 {
894 // check if there is no format with same name
895 if ( style->textFormatNames().contains( saveDlg.name() ) )
896 {
897 const int res = QMessageBox::warning( this, tr( "Save Text Format" ), tr( "Format with name '%1' already exists. Overwrite?" ).arg( saveDlg.name() ), QMessageBox::Yes | QMessageBox::No );
898 if ( res != QMessageBox::Yes )
899 {
900 return;
901 }
902 style->removeTextFormat( saveDlg.name() );
903 }
904 const QStringList symbolTags = saveDlg.tags().split( ',' );
905
906 const QgsTextFormat newFormat = format();
907 style->addTextFormat( saveDlg.name(), newFormat );
908 style->saveTextFormat( saveDlg.name(), newFormat, saveDlg.isFavorite(), symbolTags );
909 break;
910 }
911
913 {
914 // check if there is no settings with same name
915 if ( style->labelSettingsNames().contains( saveDlg.name() ) )
916 {
917 const int res
918 = QMessageBox::warning( this, tr( "Save Label Settings" ), tr( "Label settings with the name '%1' already exist. Overwrite?" ).arg( saveDlg.name() ), QMessageBox::Yes | QMessageBox::No );
919 if ( res != QMessageBox::Yes )
920 {
921 return;
922 }
923 style->removeLabelSettings( saveDlg.name() );
924 }
925 const QStringList symbolTags = saveDlg.tags().split( ',' );
926
927 const QgsPalLayerSettings newSettings = layerSettings();
928 style->addLabelSettings( saveDlg.name(), newSettings );
929 style->saveLabelSettings( saveDlg.name(), newSettings, saveDlg.isFavorite(), symbolTags );
930 break;
931 }
932
940 break;
941 }
942}
943
944void QgsLabelingGui::updateGeometryTypeBasedWidgets()
945{
946 Qgis::GeometryType geometryType = mGeomType;
947
948 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( mLayer );
949
950 if ( mGeometryGeneratorGroupBox->isChecked() )
951 geometryType = mGeometryGeneratorType->currentData().value<Qgis::GeometryType>();
952 else if ( vLayer )
953 geometryType = vLayer->geometryType();
954
955 // show/hide options based upon geometry type
956 chkMergeLines->setVisible( geometryType == Qgis::GeometryType::Line );
957 mDirectSymbolsFrame->setVisible( geometryType == Qgis::GeometryType::Line );
958 mMinSizeFrame->setVisible( geometryType != Qgis::GeometryType::Point );
959 mPolygonFeatureOptionsFrame->setVisible( geometryType == Qgis::GeometryType::Polygon );
960
961
962 const Qgis::LabelPlacement prevPlacement = static_cast<Qgis::LabelPlacement>( mPlacementModeComboBox->currentData().toInt() );
963 mPlacementModeComboBox->clear();
964
965 switch ( geometryType )
966 {
968 mPlacementModeComboBox->addItem( tr( "Cartographic" ), static_cast<int>( Qgis::LabelPlacement::OrderedPositionsAroundPoint ) );
969 mPlacementModeComboBox->addItem( tr( "Around Point" ), static_cast<int>( Qgis::LabelPlacement::AroundPoint ) );
970 mPlacementModeComboBox->addItem( tr( "Offset from Point" ), static_cast<int>( Qgis::LabelPlacement::OverPoint ) );
971 break;
972
974 mPlacementModeComboBox->addItem( tr( "Parallel" ), static_cast<int>( Qgis::LabelPlacement::Line ) );
975 mPlacementModeComboBox->addItem( tr( "Curved" ), static_cast<int>( Qgis::LabelPlacement::Curved ) );
976 mPlacementModeComboBox->addItem( tr( "Horizontal" ), static_cast<int>( Qgis::LabelPlacement::Horizontal ) );
977 break;
978
980 mPlacementModeComboBox->addItem( tr( "Offset from Centroid" ), static_cast<int>( Qgis::LabelPlacement::OverPoint ) );
981 mPlacementModeComboBox->addItem( tr( "Around Centroid" ), static_cast<int>( Qgis::LabelPlacement::AroundPoint ) );
982 mPlacementModeComboBox->addItem( tr( "Horizontal" ), static_cast<int>( Qgis::LabelPlacement::Horizontal ) );
983 mPlacementModeComboBox->addItem( tr( "Free (Angled)" ), static_cast<int>( Qgis::LabelPlacement::Free ) );
984 mPlacementModeComboBox->addItem( tr( "Using Perimeter" ), static_cast<int>( Qgis::LabelPlacement::Line ) );
985 mPlacementModeComboBox->addItem( tr( "Using Perimeter (Curved)" ), static_cast<int>( Qgis::LabelPlacement::PerimeterCurved ) );
986 mPlacementModeComboBox->addItem( tr( "Outside Polygons" ), static_cast<int>( Qgis::LabelPlacement::OutsidePolygons ) );
987 break;
988
990 break;
992 qFatal( "unknown geometry type unexpected" );
993 }
994
995 if ( mPlacementModeComboBox->findData( static_cast<int>( prevPlacement ) ) != -1 )
996 {
997 mPlacementModeComboBox->setCurrentIndex( mPlacementModeComboBox->findData( static_cast<int>( prevPlacement ) ) );
998 }
999
1000 if ( geometryType == Qgis::GeometryType::Point || geometryType == Qgis::GeometryType::Polygon )
1001 {
1002 // follow placement alignment is only valid for point or polygon layers
1003 if ( mFontMultiLineAlignComboBox->findData( static_cast<int>( Qgis::LabelMultiLineAlignment::FollowPlacement ) ) == -1 )
1004 mFontMultiLineAlignComboBox->addItem( tr( "Follow Label Placement" ), static_cast<int>( Qgis::LabelMultiLineAlignment::FollowPlacement ) );
1005 }
1006 else
1007 {
1008 const int idx = mFontMultiLineAlignComboBox->findData( static_cast<int>( Qgis::LabelMultiLineAlignment::FollowPlacement ) );
1009 if ( idx >= 0 )
1010 mFontMultiLineAlignComboBox->removeItem( idx );
1011 }
1012
1013 updatePlacementWidgets();
1014 updateLinePlacementOptions();
1015}
1016
1017void QgsLabelingGui::showGeometryGeneratorExpressionBuilder()
1018{
1019 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( mLayer );
1020 QgsExpressionBuilderDialog expressionBuilder( vLayer );
1021
1022 expressionBuilder.setExpressionText( mGeometryGenerator->text() );
1023 expressionBuilder.setExpressionContext( createExpressionContext() );
1024
1025 if ( expressionBuilder.exec() )
1026 {
1027 mGeometryGenerator->setText( expressionBuilder.expressionText() );
1028 }
1029}
1030
1031void QgsLabelingGui::validateGeometryGeneratorExpression()
1032{
1033 bool valid = true;
1034
1035 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( mLayer );
1036
1037 if ( mGeometryGeneratorGroupBox->isChecked() )
1038 {
1039 if ( !mPreviewFeature.isValid() && vLayer )
1040 vLayer->getFeatures( QgsFeatureRequest().setLimit( 1 ) ).nextFeature( mPreviewFeature );
1041
1042 QgsExpression expression( mGeometryGenerator->text() );
1043 QgsExpressionContext context = createExpressionContext();
1044 context.setFeature( mPreviewFeature );
1045
1046 expression.prepare( &context );
1047
1048 if ( expression.hasParserError() )
1049 {
1050 mGeometryGeneratorWarningLabel->setText( expression.parserErrorString() );
1051 valid = false;
1052 }
1053 else
1054 {
1055 const QVariant result = expression.evaluate( &context );
1056 const QgsGeometry geometry = result.value<QgsGeometry>();
1057 const Qgis::GeometryType configuredGeometryType = mGeometryGeneratorType->currentData().value<Qgis::GeometryType>();
1058 if ( geometry.isNull() )
1059 {
1060 mGeometryGeneratorWarningLabel->setText( tr( "Result of the expression is not a geometry" ) );
1061 valid = false;
1062 }
1063 else if ( geometry.type() != configuredGeometryType )
1064 {
1065 mGeometryGeneratorWarningLabel->setText(
1066 u"<p>%1</p><p><a href=\"#determineGeometryGeneratorType\">%2</a></p>"_s
1067 .arg( tr( "Result of the expression does not match configured geometry type." ), tr( "Change to %1" ).arg( QgsWkbTypes::geometryDisplayString( geometry.type() ) ) )
1068 );
1069 valid = false;
1070 }
1071 }
1072 }
1073
1074 // The collapsible groupbox internally changes the visibility of this
1075 // Work around by setting the visibility deferred in the next event loop cycle.
1076 QTimer *timer = new QTimer();
1077 connect( timer, &QTimer::timeout, this, [this, valid]() { mGeometryGeneratorWarningLabel->setVisible( !valid ); } );
1078 connect( timer, &QTimer::timeout, timer, &QTimer::deleteLater );
1079 timer->start( 0 );
1080}
1081
1082void QgsLabelingGui::determineGeometryGeneratorType()
1083{
1084 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( mLayer );
1085 if ( !mPreviewFeature.isValid() && vLayer )
1086 vLayer->getFeatures( QgsFeatureRequest().setLimit( 1 ) ).nextFeature( mPreviewFeature );
1087
1088 QgsExpression expression( mGeometryGenerator->text() );
1089 QgsExpressionContext context = createExpressionContext();
1090 context.setFeature( mPreviewFeature );
1091
1092 expression.prepare( &context );
1093 const QgsGeometry geometry = expression.evaluate( &context ).value<QgsGeometry>();
1094
1095 mGeometryGeneratorType->setCurrentIndex( mGeometryGeneratorType->findData( QVariant::fromValue( geometry.type() ) ) );
1096}
1097
1098void QgsLabelingGui::calloutTypeChanged()
1099{
1100 const QString newCalloutType = mCalloutStyleComboBox->currentData().toString();
1101 QgsCalloutWidget *pew = qobject_cast<QgsCalloutWidget *>( mCalloutStackedWidget->currentWidget() );
1102 if ( pew )
1103 {
1104 if ( pew->callout() && pew->callout()->type() == newCalloutType )
1105 return;
1106 }
1107
1108 // get creation function for new callout from registry
1109 QgsCalloutRegistry *registry = QgsApplication::calloutRegistry();
1110 QgsCalloutAbstractMetadata *am = registry->calloutMetadata( newCalloutType );
1111 if ( !am ) // check whether the metadata is assigned
1112 return;
1113
1114 // change callout to a new one (with different type)
1115 // base new callout on existing callout's properties
1116 const std::unique_ptr<QgsCallout> newCallout( am->createCallout( pew && pew->callout() ? pew->callout()->properties( QgsReadWriteContext() ) : QVariantMap(), QgsReadWriteContext() ) );
1117 if ( !newCallout )
1118 return;
1119
1120 updateCalloutWidget( newCallout.get() );
1121 updatePreview();
1122}
1123
1124
1125//
1126// QgsLabelSettingsDialog
1127//
1128
1129QgsLabelSettingsDialog::QgsLabelSettingsDialog( const QgsPalLayerSettings &settings, QgsVectorLayer *layer, QgsMapCanvas *mapCanvas, QWidget *parent, Qgis::GeometryType geomType )
1130 : QDialog( parent )
1131{
1132 QVBoxLayout *vLayout = new QVBoxLayout();
1133 mWidget = new QgsLabelingGui( layer, mapCanvas, settings, nullptr, geomType );
1134 vLayout->addWidget( mWidget );
1135 mButtonBox = new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::Ok, Qt::Horizontal );
1136 connect( mButtonBox, &QDialogButtonBox::accepted, this, &QDialog::accept );
1137 connect( mButtonBox, &QDialogButtonBox::rejected, this, &QDialog::reject );
1138 connect( mButtonBox, &QDialogButtonBox::helpRequested, this, &QgsLabelSettingsDialog::showHelp );
1139 vLayout->addWidget( mButtonBox );
1140 setLayout( vLayout );
1141 setWindowTitle( tr( "Label Settings" ) );
1142}
1143
1144QDialogButtonBox *QgsLabelSettingsDialog::buttonBox() const
1145{
1146 return mButtonBox;
1147}
1148
1149void QgsLabelSettingsDialog::showHelp()
1150{
1151 QgsHelp::openHelp( u"style_library/label_settings.html"_s );
1152}
1153
1154
CurvedLabelMode
Modes which determine how curved labels are generated and placed.
Definition qgis.h:1292
MultiPartLabelingBehavior
Behavior modifier for labeling features with multi-part geometries.
Definition qgis.h:1331
@ BelowLine
Labels can be placed below a line feature. Unless MapOrientation is also specified this mode respects...
Definition qgis.h:1384
@ MapOrientation
Signifies that the AboveLine and BelowLine flags should respect the map's orientation rather than the...
Definition qgis.h:1385
@ OnLine
Labels can be placed directly over a line feature.
Definition qgis.h:1382
@ AboveLine
Labels can be placed above a line feature. Unless MapOrientation is also specified this mode respects...
Definition qgis.h:1383
AngleUnit
Units of angles.
Definition qgis.h:5451
@ SecondsOfArc
Seconds of arc.
Definition qgis.h:5456
@ Radians
Square kilometers.
Definition qgis.h:5453
@ Turn
Turn/revolutions.
Definition qgis.h:5457
@ MinutesOfArc
Minutes of arc.
Definition qgis.h:5455
@ MilliradiansSI
Angular milliradians (SI definition, 1/1000 of radian).
Definition qgis.h:5458
@ Degrees
Degrees.
Definition qgis.h:5452
@ Gon
Gon/gradian.
Definition qgis.h:5454
@ MilNATO
Angular mil (NATO definition, 6400 mil = 2PI radians).
Definition qgis.h:5459
LabelOffsetType
Behavior modifier for label offset and distance, only applies in some label placement modes.
Definition qgis.h:1347
LabelPrioritization
Label prioritization.
Definition qgis.h:1259
LabelPlacement
Placement modes which determine how label candidates are generated for a feature.
Definition qgis.h:1273
@ OverPoint
Arranges candidates over a point (or centroid of a polygon), or at a preset offset from the point....
Definition qgis.h:1275
@ Curved
Arranges candidates following the curvature of a line feature. Applies to line layers only.
Definition qgis.h:1277
@ AroundPoint
Arranges candidates in a circle around a point (or centroid of a polygon). Applies to point or polygo...
Definition qgis.h:1274
@ Line
Arranges candidates parallel to a generalised line representing the feature or parallel to a polygon'...
Definition qgis.h:1276
@ Free
Arranges candidates scattered throughout a polygon feature. Candidates are rotated to respect the pol...
Definition qgis.h:1279
@ OrderedPositionsAroundPoint
Candidates are placed in predefined positions around a point. Preference is given to positions with g...
Definition qgis.h:1280
@ Horizontal
Arranges horizontal candidates scattered throughout a polygon feature. Applies to polygon layers only...
Definition qgis.h:1278
@ PerimeterCurved
Arranges candidates following the curvature of a polygon's boundary. Applies to polygon layers only.
Definition qgis.h:1281
@ OutsidePolygons
Candidates are placed outside of polygon boundaries. Applies to polygon layers only.
Definition qgis.h:1282
@ AllowPlacementInsideOfPolygon
Labels can be placed inside a polygon feature.
Definition qgis.h:1408
@ AllowPlacementOutsideOfPolygon
Labels can be placed outside of a polygon feature.
Definition qgis.h:1407
QFlags< LabelLinePlacementFlag > LabelLinePlacementFlags
Line placement flags, which control how candidates are generated for a linear feature.
Definition qgis.h:1396
QFlags< LabelPolygonPlacementFlag > LabelPolygonPlacementFlags
Polygon placement flags, which control how candidates are generated for a polygon feature.
Definition qgis.h:1418
LabelQuadrantPosition
Label quadrant positions.
Definition qgis.h:1361
GeometryType
The geometry types are used to group Qgis::WkbType in a coarse way.
Definition qgis.h:379
@ Point
Points.
Definition qgis.h:380
@ Line
Lines.
Definition qgis.h:381
@ Polygon
Polygons.
Definition qgis.h:382
@ Unknown
Unknown types.
Definition qgis.h:383
@ Null
No geometry.
Definition qgis.h:384
LabelMultiLineAlignment
Text alignment for multi-line labels.
Definition qgis.h:1444
@ Center
Center align.
Definition qgis.h:1446
@ FollowPlacement
Alignment follows placement of label, e.g., labels to the left of a feature will be drawn with right ...
Definition qgis.h:1448
@ Vector
Vector layer.
Definition qgis.h:207
@ Mesh
Mesh layer. Added in QGIS 3.2.
Definition qgis.h:210
@ TreatWhitespaceAsCollision
Treat overlapping whitespace text in labels and whitespace overlapping obstacles as collisions.
Definition qgis.h:1248
@ IgnoreWhitespaceCollisions
Ignore overlapping whitespace text in labels and whitespace overlapping obstacles.
Definition qgis.h:1249
LabelOverlapHandling
Label overlap handling.
Definition qgis.h:1234
UpsideDownLabelHandling
Handling techniques for upside down labels.
Definition qgis.h:1429
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
static QgsCalloutRegistry * calloutRegistry()
Returns the application's callout registry, used for managing callout types.
virtual QgsCallout * createCallout(const QVariantMap &properties, const QgsReadWriteContext &context)=0
Create a callout of this type given the map of properties.
QgsCalloutAbstractMetadata * calloutMetadata(const QString &type) const
Returns the metadata for specified the specified callout type.
static QgsCallout * defaultCallout()
Create a new instance of a callout with default settings.
QStringList calloutTypes() const
Returns a list of all available callout types.
virtual QgsCallout * callout()=0
Returns the callout defined by the current settings in the widget.
void changed()
Should be emitted whenever configuration changes happened on this symbol layer configuration.
Abstract base class for callout renderers.
Definition qgscallout.h:55
virtual QString type() const =0
Returns a unique string representing the callout type.
virtual QVariantMap properties(const QgsReadWriteContext &context) const
Returns the properties describing the callout encoded in a string format.
void setSourceCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets source spatial reference system crs.
bool setEllipsoid(const QString &ellipsoid)
Sets the ellipsoid by its acronym.
static QgsExpressionContextScope * updateSymbolScope(const QgsSymbol *symbol, QgsExpressionContextScope *symbolScope=nullptr)
Updates a symbol scope related to a QgsSymbol to an expression context.
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
static QgsExpressionContextScope * atlasScope(const QgsLayoutAtlas *atlas)
Creates a new scope which contains variables and functions relating to a QgsLayoutAtlas.
static QgsExpressionContextScope * meshExpressionScope(QgsMesh::ElementType elementType)
Creates a new scope which contains functions relating to mesh layer element elementType.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for the context.
static const QString EXPR_SYMBOL_COLOR
Inbuilt variable name for symbol color variable.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
void setHighlightedVariables(const QStringList &variableNames)
Sets the list of variable names within the context intended to be highlighted to the user.
static const QString EXPR_ORIGINAL_VALUE
Inbuilt variable name for value original value variable.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
Qgis::GeometryType type
static void initCalloutWidgets()
Initializes callout widgets.
Definition qgsgui.cpp:426
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition qgshelp.cpp:41
void updateDataDefinedProperties(QgsPropertyCollection &properties) override
Updates a data defined properties collection, correctly setting the values for any properties related...
QgsLabelLineSettings settings() const
Returns the line settings defined by the widget.
void setSettings(const QgsLabelLineSettings &settings)
Sets the line settings to show in the widget.
void setPlacementFlags(Qgis::LabelLinePlacementFlags flags)
Returns the line placement flags, which dictate how line labels can be placed above or below the line...
void setLineAnchorPercent(double percent)
Sets the percent along the line at which labels should be placed.
void setDirectionSymbolPlacement(DirectionSymbolPlacement placement)
Sets the placement for direction symbols.
AnchorType anchorType() const
Returns the line anchor type, which dictates how the lineAnchorPercent() setting is handled.
void setAnchorTextPoint(AnchorTextPoint point)
Sets the line anchor text point, which dictates which part of the label text should be placed at the ...
void setLeftDirectionSymbol(const QString &symbol)
Sets the string to use for left direction arrows.
AnchorTextPoint anchorTextPoint() const
Returns the line anchor text point, which dictates which part of the label text should be placed at t...
void setMergeLines(bool merge)
Sets whether connected line features with identical label text should be merged prior to generating l...
DirectionSymbolPlacement
Placement options for direction symbols.
void setRightDirectionSymbol(const QString &symbol)
Sets the string to use for right direction arrows.
void setAnchorClipping(AnchorClipping clipping)
Sets the line anchor clipping mode, which dictates how line strings are clipped before calculating th...
void setOverrunDistanceMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for label overrun distance.
double lineAnchorPercent() const
Returns the percent along the line at which labels should be placed.
void setAnchorType(AnchorType type)
Sets the line anchor type, which dictates how the lineAnchorPercent() setting is handled.
void setOverrunDistanceUnit(const Qgis::RenderUnit &unit)
Sets the unit for label overrun distance.
void setOverrunDistance(double distance)
Sets the distance which labels are allowed to overrun past the start or end of line features.
AnchorClipping anchorClipping() const
Returns the line anchor clipping mode, which dictates how line strings are clipped before calculating...
void setReverseDirectionSymbol(bool reversed)
Sets whether the direction symbols should be reversed.
void setAddDirectionSymbol(bool enabled)
Sets whether '<' or '>' (or custom strings set via leftDirectionSymbol and rightDirectionSymbol) will...
void setCurvedLabelMode(Qgis::CurvedLabelMode mode)
Sets the mode which determine how curved labels are generated and placed.
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 setOverlapHandling(Qgis::LabelOverlapHandling handling)
Sets the technique used to handle overlapping labels.
void setMultiPartBehavior(Qgis::MultiPartLabelingBehavior behavior)
Sets the multipart labeling behavior.
void setPrioritization(Qgis::LabelPrioritization prioritization)
Sets the technique used to prioritize labels.
void setAllowDegradedPlacement(bool allow)
Sets whether labels can be placed in inferior fallback positions if they cannot otherwise be placed.
void setWhitespaceCollisionHandling(Qgis::LabelWhitespaceCollisionHandling handling)
Sets the whitespace collision handling.
void setMaximumDistance(double distance)
Sets the maximum distance which labels are allowed to be from their corresponding points.
void setMaximumDistanceMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for label maximum distance.
void setQuadrant(Qgis::LabelQuadrantPosition quadrant)
Sets the quadrant in which to offset labels from the point.
void setMaximumDistanceUnit(Qgis::RenderUnit unit)
Sets the unit for label maximum distance.
void setSettings(const QgsLabelThinningSettings &settings)
Sets the thinning settings to show in the widget.
QgsLabelThinningSettings settings() const
Returns the thinning 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 setGeometryType(Qgis::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 ...
virtual void setGeometryType(Qgis::GeometryType type)
Sets the geometry type of the features to customize the widget accordingly.
void setDataDefinedProperties(const QgsPropertyCollection &dataDefinedProperties)
Sets the current data defined properties to show in the widget.
QgsPropertyCollection dataDefinedProperties() const
Returns the current data defined properties state as specified in the widget.
Map canvas is a class for displaying all GIS data types on a canvas.
Base class for all map layer types.
Definition qgsmaplayer.h:83
Qgis::LayerType type
Definition qgsmaplayer.h:93
Represents a mesh layer supporting display of data on structured or unstructured meshes.
Contains settings for how a map layer will be labeled.
bool fitInPolygonOnly
true if only labels which completely fit within a polygon are allowed.
double yOffset
Vertical offset of label.
QgsMapUnitScale labelOffsetMapUnitScale
Map unit scale for label offset.
int fontMaxPixelSize
Maximum pixel size for showing rendered map unit labels (1 - 10000).
void setObstacleSettings(const QgsLabelObstacleSettings &settings)
Sets the label obstacle settings.
const QgsLabelPlacementSettings & placementSettings() const
Returns the label placement settings.
double maxCurvedCharAngleIn
Maximum angle between inside curved label characters (valid range 20.0 to 60.0).
void setFormat(const QgsTextFormat &format)
Sets the label text formatting settings, e.g., font settings, buffer settings, etc.
double zIndex
Z-Index of label, where labels with a higher z-index are rendered on top of labels with a lower z-ind...
void setPolygonPlacementFlags(Qgis::LabelPolygonPlacementFlags flags)
Sets the polygon placement flags, which dictate how polygon labels can be placed.
QString wrapChar
Wrapping character string.
Qgis::LabelOffsetType offsetType
Offset type for layer (only applies in certain placement modes).
double xOffset
Horizontal offset of label.
Qgis::LabelPlacement placement
Label placement mode.
bool drawLabels
Whether to draw labels for this layer.
bool fontLimitPixelSize
true if label sizes should be limited by pixel size.
double minimumScale
The minimum map scale (i.e.
bool scaleVisibility
Set to true to limit label visibility to a range of scales.
double repeatDistance
Distance for repeating labels for a single feature.
bool geometryGeneratorEnabled
Defines if the geometry generator is enabled or not. If disabled, the standard geometry will be taken...
Qgis::LabelMultiLineAlignment multilineAlign
Horizontal alignment of multi-line labels.
bool centroidInside
true if centroid positioned labels must be placed inside their corresponding feature polygon,...
int priority
Label priority.
Qgis::GeometryType geometryGeneratorType
The type of the result geometry of the geometry generator.
int fontMinPixelSize
Minimum pixel size for showing rendered map unit labels (1 - 1000).
double angleOffset
Label rotation, in degrees clockwise.
double maxCurvedCharAngleOut
Maximum angle between outside curved label characters (valid range -20.0 to -95.0).
Qgis::GeometryType layerType
Geometry type of layers associated with these settings.
void setThinningSettings(const QgsLabelThinningSettings &settings)
Sets the label thinning settings.
Qgis::RenderUnit offsetUnits
Units for offsets of label.
void setDataDefinedProperties(const QgsPropertyCollection &collection)
Sets the label's property collection, used for data defined overrides.
bool isExpression
true if this label is made from a expression string, e.g., FieldName || 'mm'
bool preserveRotation
True if label rotation should be preserved during label pin/unpin operations.
bool plusSign
Whether '+' signs should be prepended to positive numeric labels.
QString geometryGenerator
The geometry generator expression. Null if disabled.
const QgsLabelLineSettings & lineSettings() const
Returns the label line settings, which contain settings related to how the label engine places and fo...
QgsMapUnitScale distMapUnitScale
Map unit scale for label feature distance.
QgsStringReplacementCollection substitutions
Substitution collection for automatic text substitution with labels.
int decimals
Number of decimal places to show for numeric labels.
double dist
Distance from feature to the label.
void setRotationUnit(Qgis::AngleUnit angleUnit)
Set unit for rotation of labels.
QgsMapUnitScale repeatDistanceMapUnitScale
Map unit scale for repeating labels for a single feature.
Qgis::RenderUnit distUnits
Units the distance from feature to the label.
bool centroidWhole
true if feature centroid should be calculated from the whole feature, or false if only the visible pa...
Qgis::RenderUnit repeatDistanceUnit
Units for repeating labels for a single feature.
Qgis::UpsideDownLabelHandling upsidedownLabels
Controls whether upside down labels are displayed and how they are handled.
QString fieldName
Name of field (or an expression) to use for label text.
bool formatNumbers
Set to true to format numeric label text as numbers (e.g.
void setCallout(QgsCallout *callout)
Sets the label callout renderer, responsible for drawing label callouts.
double maximumScale
The maximum map scale (i.e.
int autoWrapLength
If non-zero, indicates that label text should be automatically wrapped to (ideally) the specified num...
bool useMaxLineLengthForAutoWrap
If true, indicates that when auto wrapping label text the autoWrapLength length indicates the maximum...
void setUnplacedVisibility(Qgis::UnplacedLabelVisibility visibility)
Sets the layer's unplaced label visibility.
const QgsLabelPointSettings & pointSettings() const
Returns the label point settings, which contain settings related to how the label engine places and f...
bool useSubstitutions
True if substitutions should be applied.
void openPanel(QgsPanelWidget *panel)
Open a panel or dialog depending on dock mode setting If dock mode is true this method will emit the ...
bool dockMode() const
Returns the dock mode state.
static QgsPanelWidget * findParentPanel(QWidget *widget)
Traces through the parents of a widget to find if it is contained within a QgsPanelWidget widget.
QgsStyle * styleAtPath(const QString &path)
Returns a reference to the style database associated with the project with matching file path.
static QgsProject * instance()
Returns the QgsProject singleton instance.
const QgsProjectStyleSettings * styleSettings() const
Returns the project's style settings, which contains settings and properties relating to how a QgsPro...
QgsCoordinateTransformContext transformContext
Definition qgsproject.h:121
A button for controlling property overrides which may apply to a widget.
bool isActive() const
Returns true if the button has an active property.
void changed()
Emitted when property definition changes.
@ CurrentPageOnly
Only the size of the current page is considered when calculating the stacked widget size.
bool removeLabelSettings(const QString &name)
Removes label settings from the style.
bool saveLabelSettings(const QString &name, const QgsPalLayerSettings &settings, bool favorite, const QStringList &tags)
Adds label settings to the database.
QStringList textFormatNames() const
Returns a list of names of text formats in the style.
bool removeTextFormat(const QString &name)
Removes a text format from the style.
StyleEntity
Enum for Entities involved in a style.
Definition qgsstyle.h:206
@ LabelSettingsEntity
Label settings.
Definition qgsstyle.h:212
@ TextFormatEntity
Text formats.
Definition qgsstyle.h:211
@ SmartgroupEntity
Smart groups.
Definition qgsstyle.h:210
@ Symbol3DEntity
3D symbol entity
Definition qgsstyle.h:214
@ SymbolEntity
Symbols.
Definition qgsstyle.h:207
@ TagEntity
Tags.
Definition qgsstyle.h:208
@ ColorrampEntity
Color ramps.
Definition qgsstyle.h:209
@ LegendPatchShapeEntity
Legend patch shape.
Definition qgsstyle.h:213
@ MaterialSettingsEntity
Material settings.
Definition qgsstyle.h:215
static QgsStyle * defaultStyle(bool initialize=true)
Returns the default application-wide style.
Definition qgsstyle.cpp:164
QStringList labelSettingsNames() const
Returns a list of names of label settings in the style.
static QgsTextFormat defaultTextFormatForProject(QgsProject *project, QgsStyle::TextFormatContext context=QgsStyle::TextFormatContext::Labeling)
Returns the default text format to use for new text based objects for the specified project,...
bool addTextFormat(const QString &name, const QgsTextFormat &format, bool update=false)
Adds a text format with the specified name to the style.
Definition qgsstyle.cpp:388
QgsPalLayerSettings labelSettings(const QString &name) const
Returns the label settings with the specified name.
@ Labeling
Text format used in labeling.
Definition qgsstyle.h:828
bool saveTextFormat(const QString &name, const QgsTextFormat &format, bool favorite, const QStringList &tags)
Adds a text format to the database.
bool addLabelSettings(const QString &name, const QgsPalLayerSettings &settings, bool update=false)
Adds label settings with the specified name to the style.
Definition qgsstyle.cpp:410
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 setExpressionContext(QgsExpressionContext *context)
Sets the optional expression context used for the widget.
A widget for customizing text formatting settings.
virtual void setContext(const QgsSymbolWidgetContext &context)
Sets the context in which the widget is shown, e.g., the associated map canvas and expression context...
virtual void setFormatFromStyle(const QString &name, QgsStyle::StyleEntity type, const QString &stylePath)
Sets the current text settings from a style entry.
static Q_INVOKABLE QString toString(Qgis::DistanceUnit unit)
Returns a translated string representing a distance unit.
Represents a vector layer which manages a vector based dataset.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const final
Queries the layer for features specified in request.
Q_INVOKABLE Qgis::GeometryType geometryType() const
Returns point, line or polygon.
Implements a map layer that is dedicated to rendering of vector tiles.
static Q_INVOKABLE QString geometryDisplayString(Qgis::GeometryType type)
Returns a display string for a geometry type.
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition qgis.h:7039