QGIS API Documentation 3.99.0-Master (2fe06baccd8)
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
42#include "moc_qgslabelinggui.cpp"
43
45
46QgsExpressionContext QgsLabelingGui::createExpressionContext() const
47{
48 QgsExpressionContext expContext;
49 if ( mMapCanvas )
50 {
51 expContext = mMapCanvas->createExpressionContext();
52 }
53 else
54 {
58 }
59
60 if ( mLayer )
61 expContext << QgsExpressionContextUtils::layerScope( mLayer );
62
63 if ( mLayer && mLayer->type() == Qgis::LayerType::Mesh )
64 {
65 if ( mGeomType == Qgis::GeometryType::Point )
67 else if ( mGeomType == Qgis::GeometryType::Polygon )
69 }
70
71 expContext << QgsExpressionContextUtils::updateSymbolScope( nullptr, new QgsExpressionContextScope() );
72
73 //TODO - show actual value
74 expContext.setOriginalValueVariable( QVariant() );
76
77 return expContext;
78}
79
80void QgsLabelingGui::updateCalloutWidget( QgsCallout *callout )
81{
82 if ( !callout )
83 {
84 mCalloutStackedWidget->setCurrentWidget( pageDummy );
85 return;
86 }
87
88 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( mLayer );
89 if ( !vLayer )
90 {
91 mCalloutStackedWidget->setCurrentWidget( pageDummy );
92 return;
93 }
94
95 if ( mCalloutStackedWidget->currentWidget() != pageDummy )
96 {
97 // stop updating from the original widget
98 if ( QgsCalloutWidget *pew = qobject_cast<QgsCalloutWidget *>( mCalloutStackedWidget->currentWidget() ) )
99 disconnect( pew, &QgsCalloutWidget::changed, this, &QgsLabelingGui::updatePreview );
100 }
101
102 QgsCalloutRegistry *registry = QgsApplication::calloutRegistry();
103 if ( QgsCalloutAbstractMetadata *am = registry->calloutMetadata( callout->type() ) )
104 {
105 if ( QgsCalloutWidget *w = am->createCalloutWidget( vLayer ) )
106 {
107 Qgis::GeometryType geometryType = mGeomType;
108 if ( mGeometryGeneratorGroupBox->isChecked() )
109 geometryType = mGeometryGeneratorType->currentData().value<Qgis::GeometryType>();
110 else if ( vLayer )
111 geometryType = vLayer->geometryType();
112 w->setGeometryType( geometryType );
113 w->setCallout( callout );
114
115 w->setContext( context() );
116 mCalloutStackedWidget->addWidget( w );
117 mCalloutStackedWidget->setCurrentWidget( w );
118 // start receiving updates from widget
119 connect( w, &QgsCalloutWidget::changed, this, &QgsLabelingGui::updatePreview );
120 return;
121 }
122 }
123 // When anything is not right
124 mCalloutStackedWidget->setCurrentWidget( pageDummy );
125}
126
127void QgsLabelingGui::showObstacleSettings()
128{
129 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( mLayer );
130 if ( !vLayer )
131 {
132 return;
133 }
134
135 QgsExpressionContext context = createExpressionContext();
136
137 QgsSymbolWidgetContext symbolContext;
138 symbolContext.setExpressionContext( &context );
139 symbolContext.setMapCanvas( mMapCanvas );
140
141 QgsLabelObstacleSettingsWidget *widget = new QgsLabelObstacleSettingsWidget( nullptr, vLayer );
142 widget->setDataDefinedProperties( mDataDefinedProperties );
143 widget->setSettings( mObstacleSettings );
144 widget->setGeometryType( vLayer->geometryType() );
145 widget->setContext( symbolContext );
146
147 auto applySettings = [this, widget] {
148 mObstacleSettings = widget->settings();
149 const QgsPropertyCollection obstacleDataDefinedProperties = widget->dataDefinedProperties();
150 widget->updateDataDefinedProperties( mDataDefinedProperties );
151 emit widgetChanged();
152 };
153
154 QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( this );
155 if ( panel && panel->dockMode() )
156 {
157 connect( widget, &QgsLabelSettingsWidgetBase::changed, this, [applySettings] {
158 applySettings();
159 } );
160 panel->openPanel( widget );
161 }
162 else
163 {
164 QgsLabelSettingsWidgetDialog dialog( widget, this );
165
166 dialog.buttonBox()->addButton( QDialogButtonBox::Help );
167 connect( dialog.buttonBox(), &QDialogButtonBox::helpRequested, this, [] {
168 QgsHelp::openHelp( QStringLiteral( "style_library/label_settings.html#obstacles" ) );
169 } );
170
171 if ( dialog.exec() )
172 {
173 applySettings();
174 }
175 // reactivate button's window
176 activateWindow();
177 }
178}
179
180void QgsLabelingGui::showLineAnchorSettings()
181{
182 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( mLayer );
183 if ( !vLayer )
184 {
185 return;
186 }
187
188 QgsExpressionContext context = createExpressionContext();
189
190 QgsSymbolWidgetContext symbolContext;
191 symbolContext.setExpressionContext( &context );
192 symbolContext.setMapCanvas( mMapCanvas );
193
194 QgsLabelLineAnchorWidget *widget = new QgsLabelLineAnchorWidget( nullptr, vLayer );
195 widget->setDataDefinedProperties( mDataDefinedProperties );
196 widget->setSettings( mLineSettings );
197 widget->setGeometryType( vLayer->geometryType() );
198 widget->setContext( symbolContext );
199
200 auto applySettings = [this, widget] {
201 const QgsLabelLineSettings widgetSettings = widget->settings();
202 mLineSettings.setLineAnchorPercent( widgetSettings.lineAnchorPercent() );
203 mLineSettings.setAnchorType( widgetSettings.anchorType() );
204 mLineSettings.setAnchorClipping( widgetSettings.anchorClipping() );
205 mLineSettings.setAnchorTextPoint( widgetSettings.anchorTextPoint() );
206 const QgsPropertyCollection obstacleDataDefinedProperties = widget->dataDefinedProperties();
207 widget->updateDataDefinedProperties( mDataDefinedProperties );
208 emit widgetChanged();
209 };
210
211 QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( this );
212 if ( panel && panel->dockMode() )
213 {
214 connect( widget, &QgsLabelSettingsWidgetBase::changed, this, [applySettings] {
215 applySettings();
216 } );
217 panel->openPanel( widget );
218 }
219 else
220 {
221 QgsLabelSettingsWidgetDialog dialog( widget, this );
222
223 dialog.buttonBox()->addButton( QDialogButtonBox::Help );
224 connect( dialog.buttonBox(), &QDialogButtonBox::helpRequested, this, [] {
225 QgsHelp::openHelp( QStringLiteral( "style_library/label_settings.html#placement-for-line-layers" ) );
226 } );
227
228 if ( dialog.exec() )
229 {
230 applySettings();
231 }
232 // reactivate button's window
233 activateWindow();
234 }
235}
236
237void QgsLabelingGui::showDuplicateSettings()
238{
239 QgsExpressionContext context = createExpressionContext();
240
241 QgsSymbolWidgetContext symbolContext;
242 symbolContext.setExpressionContext( &context );
243 symbolContext.setMapCanvas( mMapCanvas );
244
245 QgsLabelRemoveDuplicatesSettingsWidget *widget = new QgsLabelRemoveDuplicatesSettingsWidget( nullptr, mLayer );
246 widget->setDataDefinedProperties( mDataDefinedProperties );
247 widget->setSettings( mThinningSettings );
248 auto vectorLayer = qobject_cast< QgsVectorLayer * >( mLayer );
249 widget->setGeometryType( vectorLayer ? vectorLayer->geometryType() : Qgis::GeometryType::Unknown );
250 widget->setContext( symbolContext );
251
252 auto applySettings = [this, widget] {
253 mThinningSettings = widget->settings();
254 const QgsPropertyCollection obstacleDataDefinedProperties = widget->dataDefinedProperties();
255 widget->updateDataDefinedProperties( mDataDefinedProperties );
256 emit widgetChanged();
257 };
258
259 QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( this );
260 if ( panel && panel->dockMode() )
261 {
262 connect( widget, &QgsLabelSettingsWidgetBase::changed, this, [applySettings] {
263 applySettings();
264 } );
265 panel->openPanel( widget );
266 }
267 else
268 {
269 QgsLabelSettingsWidgetDialog dialog( widget, this );
270 if ( dialog.exec() )
271 {
272 applySettings();
273 }
274 // reactivate button's window
275 activateWindow();
276 }
277}
278
279QgsLabelingGui::QgsLabelingGui( QgsVectorLayer *layer, QgsMapCanvas *mapCanvas, const QgsPalLayerSettings &layerSettings, QWidget *parent, Qgis::GeometryType geomType )
280 : QgsTextFormatWidget( mapCanvas, parent, QgsTextFormatWidget::Labeling, layer )
281 , mMode( NoLabels )
282 , mSettings( layerSettings )
283{
284 mGeomType = geomType;
285
286 init();
287
288 setLayer( layer );
289}
290
291QgsLabelingGui::QgsLabelingGui( QgsMeshLayer *layer, QgsMapCanvas *mapCanvas, const QgsPalLayerSettings &settings, QWidget *parent, Qgis::GeometryType geomType )
292 : QgsTextFormatWidget( mapCanvas, parent, QgsTextFormatWidget::Labeling, layer )
293 , mMode( NoLabels )
294 , mSettings( settings )
295{
296 mGeomType = geomType;
297
298 init();
299
300 setLayer( layer );
301}
302
303QgsLabelingGui::QgsLabelingGui( QgsVectorTileLayer *layer, QgsMapCanvas *mapCanvas, const QgsPalLayerSettings &settings, QWidget *parent, Qgis::GeometryType geomType )
304 : QgsTextFormatWidget( mapCanvas, parent, QgsTextFormatWidget::Labeling, layer )
305 , mMode( NoLabels )
306 , mSettings( settings )
307{
308 mGeomType = geomType;
309
310 init();
311
312 setLayer( layer );
313}
314
315
316QgsLabelingGui::QgsLabelingGui( QgsMapCanvas *mapCanvas, QWidget *parent, QgsMapLayer *layer )
317 : QgsTextFormatWidget( mapCanvas, parent, QgsTextFormatWidget::Labeling, layer )
318 , mMode( NoLabels )
319{
320}
321
322
323QgsLabelingGui::QgsLabelingGui( QgsMapCanvas *mapCanvas, const QgsPalLayerSettings &settings, QWidget *parent )
324 : QgsTextFormatWidget( mapCanvas, parent, QgsTextFormatWidget::Labeling, nullptr )
325 , mMode( NoLabels )
326 , mSettings( settings )
327{
328 init();
329
330 setLayer( nullptr );
331}
332
333void QgsLabelingGui::init()
334{
336
337 mStackedWidgetLabelWith->setSizeMode( QgsStackedWidget::SizeMode::CurrentPageOnly );
338
339 mFontMultiLineAlignComboBox->addItem( tr( "Left" ), static_cast<int>( Qgis::LabelMultiLineAlignment::Left ) );
340 mFontMultiLineAlignComboBox->addItem( tr( "Center" ), static_cast<int>( Qgis::LabelMultiLineAlignment::Center ) );
341 mFontMultiLineAlignComboBox->addItem( tr( "Right" ), static_cast<int>( Qgis::LabelMultiLineAlignment::Right ) );
342 mFontMultiLineAlignComboBox->addItem( tr( "Justify" ), static_cast<int>( Qgis::LabelMultiLineAlignment::Justify ) );
343
344 mCoordRotationUnitComboBox->addItem( QgsUnitTypes::toString( Qgis::AngleUnit::Degrees ), static_cast<int>( Qgis::AngleUnit::Degrees ) );
345 mCoordRotationUnitComboBox->addItem( QgsUnitTypes::toString( Qgis::AngleUnit::Radians ), static_cast<int>( Qgis::AngleUnit::Radians ) );
346 mCoordRotationUnitComboBox->addItem( QgsUnitTypes::toString( Qgis::AngleUnit::Gon ), static_cast<int>( Qgis::AngleUnit::Gon ) );
347 mCoordRotationUnitComboBox->addItem( QgsUnitTypes::toString( Qgis::AngleUnit::MinutesOfArc ), static_cast<int>( Qgis::AngleUnit::MinutesOfArc ) );
348 mCoordRotationUnitComboBox->addItem( QgsUnitTypes::toString( Qgis::AngleUnit::SecondsOfArc ), static_cast<int>( Qgis::AngleUnit::SecondsOfArc ) );
349 mCoordRotationUnitComboBox->addItem( QgsUnitTypes::toString( Qgis::AngleUnit::Turn ), static_cast<int>( Qgis::AngleUnit::Turn ) );
350 mCoordRotationUnitComboBox->addItem( QgsUnitTypes::toString( Qgis::AngleUnit::MilliradiansSI ), static_cast<int>( Qgis::AngleUnit::MilliradiansSI ) );
351 mCoordRotationUnitComboBox->addItem( QgsUnitTypes::toString( Qgis::AngleUnit::MilNATO ), static_cast<int>( Qgis::AngleUnit::MilNATO ) );
352
353 // connections for groupboxes with separate activation checkboxes (that need to honor data defined setting)
354 connect( mBufferDrawChkBx, &QAbstractButton::toggled, this, &QgsLabelingGui::updateUi );
355 connect( mBufferDrawDDBtn, &QgsPropertyOverrideButton::changed, this, &QgsLabelingGui::updateUi );
356 connect( mEnableMaskChkBx, &QAbstractButton::toggled, this, &QgsLabelingGui::updateUi );
357 connect( mShapeDrawChkBx, &QAbstractButton::toggled, this, &QgsLabelingGui::updateUi );
358 connect( mCalloutsDrawCheckBox, &QAbstractButton::toggled, this, &QgsLabelingGui::updateUi );
359 connect( mShadowDrawChkBx, &QAbstractButton::toggled, this, &QgsLabelingGui::updateUi );
360 connect( mDirectSymbChkBx, &QAbstractButton::toggled, this, &QgsLabelingGui::updateUi );
361 connect( mFormatNumChkBx, &QAbstractButton::toggled, this, &QgsLabelingGui::updateUi );
362 connect( mScaleBasedVisibilityChkBx, &QAbstractButton::toggled, this, &QgsLabelingGui::updateUi );
363 connect( mFontLimitPixelChkBox, &QAbstractButton::toggled, this, &QgsLabelingGui::updateUi );
364 connect( mGeometryGeneratorGroupBox, &QGroupBox::toggled, this, &QgsLabelingGui::updateGeometryTypeBasedWidgets );
365 connect( mGeometryGeneratorType, qOverload<int>( &QComboBox::currentIndexChanged ), this, &QgsLabelingGui::updateGeometryTypeBasedWidgets );
366 connect( mGeometryGeneratorExpressionButton, &QToolButton::clicked, this, &QgsLabelingGui::showGeometryGeneratorExpressionBuilder );
367 connect( mGeometryGeneratorGroupBox, &QGroupBox::toggled, this, &QgsLabelingGui::validateGeometryGeneratorExpression );
368 connect( mGeometryGenerator, &QgsCodeEditorExpression::textChanged, this, &QgsLabelingGui::validateGeometryGeneratorExpression );
369 connect( mGeometryGeneratorType, qOverload<int>( &QComboBox::currentIndexChanged ), this, &QgsLabelingGui::validateGeometryGeneratorExpression );
370 connect( mObstacleSettingsButton, &QAbstractButton::clicked, this, &QgsLabelingGui::showObstacleSettings );
371 connect( mLineAnchorSettingsButton, &QAbstractButton::clicked, this, &QgsLabelingGui::showLineAnchorSettings );
372 connect( mDuplicateSettingsButton, &QAbstractButton::clicked, this, &QgsLabelingGui::showDuplicateSettings );
373
374 mFieldExpressionWidget->registerExpressionContextGenerator( this );
375
376 mMinScaleWidget->setMapCanvas( mMapCanvas );
377 mMinScaleWidget->setShowCurrentScaleButton( true );
378 mMaxScaleWidget->setMapCanvas( mMapCanvas );
379 mMaxScaleWidget->setShowCurrentScaleButton( true );
380
381 mGeometryGeneratorExpressionButton->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
382 mGeometryGeneratorExpressionButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mIconExpression.svg" ) ) );
383
384 const QStringList calloutTypes = QgsApplication::calloutRegistry()->calloutTypes();
385 for ( const QString &type : calloutTypes )
386 {
387 mCalloutStyleComboBox->addItem( QgsApplication::calloutRegistry()->calloutMetadata( type )->icon(), QgsApplication::calloutRegistry()->calloutMetadata( type )->visibleName(), type );
388 }
389
390 mGeometryGeneratorWarningLabel->setStyleSheet( QStringLiteral( "color: #FFC107;" ) );
391 mGeometryGeneratorWarningLabel->setTextInteractionFlags( Qt::TextBrowserInteraction );
392 connect( mGeometryGeneratorWarningLabel, &QLabel::linkActivated, this, [this]( const QString &link ) {
393 if ( link == QLatin1String( "#determineGeometryGeneratorType" ) )
394 determineGeometryGeneratorType();
395 } );
396
397 connect( mCalloutStyleComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsLabelingGui::calloutTypeChanged );
398
399 mLblNoObstacle1->installEventFilter( this );
400}
401
402void QgsLabelingGui::setLayer( QgsMapLayer *mapLayer )
403{
404 mPreviewFeature = QgsFeature();
405
406 if ( ( !mapLayer || mapLayer->type() != Qgis::LayerType::Vector ) && mGeomType == Qgis::GeometryType::Unknown )
407 {
408 setEnabled( false );
409 return;
410 }
411
412 setEnabled( true );
413
414 mLayer = mapLayer;
415 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( mapLayer );
416
417 mTextFormatsListWidget->setLayerType( vLayer ? vLayer->geometryType() : mGeomType );
418 mBackgroundMarkerSymbolButton->setLayer( vLayer );
419 mBackgroundFillSymbolButton->setLayer( vLayer );
420
421 // load labeling settings from layer
422 updateGeometryTypeBasedWidgets();
423
424 mFieldExpressionWidget->setLayer( mapLayer );
425 QgsDistanceArea da;
426 if ( mLayer )
427 da.setSourceCrs( mLayer->crs(), QgsProject::instance()->transformContext() );
428 da.setEllipsoid( QgsProject::instance()->ellipsoid() );
429 mFieldExpressionWidget->setGeomCalculator( da );
430
431 mFieldExpressionWidget->setEnabled( mMode == Labels || !mLayer );
432 mLabelingFrame->setEnabled( mMode == Labels || !mLayer );
433
434 blockInitSignals( true );
435
436 mGeometryGenerator->setText( mSettings.geometryGenerator );
437 mGeometryGeneratorGroupBox->setChecked( mSettings.geometryGeneratorEnabled );
438 if ( !mSettings.geometryGeneratorEnabled )
439 mGeometryGeneratorGroupBox->setCollapsed( true );
440 mGeometryGeneratorType->setCurrentIndex( mGeometryGeneratorType->findData( QVariant::fromValue( mSettings.geometryGeneratorType ) ) );
441
442 updateWidgetForFormat( mSettings.format().isValid() ? mSettings.format() : QgsStyle::defaultTextFormatForProject( QgsProject::instance(), QgsStyle::TextFormatContext::Labeling ) );
443
444 mFieldExpressionWidget->setRow( -1 );
445 mFieldExpressionWidget->setField( mSettings.fieldName );
446 mCheckBoxSubstituteText->setChecked( mSettings.useSubstitutions );
447 mSubstitutions = mSettings.substitutions;
448
449 // populate placement options
450 mCentroidRadioWhole->setChecked( mSettings.centroidWhole );
451 mCentroidInsideCheckBox->setChecked( mSettings.centroidInside );
452 mFitInsidePolygonCheckBox->setChecked( mSettings.fitInPolygonOnly );
453 mLineDistanceSpnBx->setValue( mSettings.dist );
454 mLineDistanceUnitWidget->setUnit( mSettings.distUnits );
455 mLineDistanceUnitWidget->setMapUnitScale( mSettings.distMapUnitScale );
456
457 mMaximumDistanceSpnBx->setValue( mSettings.pointSettings().maximumDistance() );
458 mMaximumDistanceUnitWidget->setUnit( mSettings.pointSettings().maximumDistanceUnit() );
459 mMaximumDistanceUnitWidget->setMapUnitScale( mSettings.pointSettings().maximumDistanceMapUnitScale() );
460
461 mOffsetTypeComboBox->setCurrentIndex( mOffsetTypeComboBox->findData( static_cast<int>( mSettings.offsetType ) ) );
462 mQuadrantBtnGrp->button( static_cast<int>( mSettings.pointSettings().quadrant() ) )->setChecked( true );
463 mPointOffsetXSpinBox->setValue( mSettings.xOffset );
464 mPointOffsetYSpinBox->setValue( mSettings.yOffset );
465 mPointOffsetUnitWidget->setUnit( mSettings.offsetUnits );
466 mPointOffsetUnitWidget->setMapUnitScale( mSettings.labelOffsetMapUnitScale );
467 mPointAngleSpinBox->setValue( mSettings.angleOffset );
468 chkLineAbove->setChecked( mSettings.lineSettings().placementFlags() & Qgis::LabelLinePlacementFlag::AboveLine );
469 chkLineBelow->setChecked( mSettings.lineSettings().placementFlags() & Qgis::LabelLinePlacementFlag::BelowLine );
470 chkLineOn->setChecked( mSettings.lineSettings().placementFlags() & Qgis::LabelLinePlacementFlag::OnLine );
471 chkLineOrientationDependent->setChecked( !( mSettings.lineSettings().placementFlags() & Qgis::LabelLinePlacementFlag::MapOrientation ) );
472
473 mCheckAllowLabelsOutsidePolygons->setChecked( mSettings.polygonPlacementFlags() & Qgis::LabelPolygonPlacementFlag::AllowPlacementOutsideOfPolygon );
474
475 const int placementIndex = mPlacementModeComboBox->findData( static_cast<int>( mSettings.placement ) );
476 if ( placementIndex >= 0 )
477 {
478 mPlacementModeComboBox->setCurrentIndex( placementIndex );
479 }
480 else
481 {
482 // use default placement for layer type
483 mPlacementModeComboBox->setCurrentIndex( 0 );
484 }
485
486 // Label repeat distance
487 mRepeatDistanceSpinBox->setValue( mSettings.repeatDistance );
488 mRepeatDistanceUnitWidget->setUnit( mSettings.repeatDistanceUnit );
489 mRepeatDistanceUnitWidget->setMapUnitScale( mSettings.repeatDistanceMapUnitScale );
490
491 mOverrunDistanceSpinBox->setValue( mSettings.lineSettings().overrunDistance() );
492 mOverrunDistanceUnitWidget->setUnit( mSettings.lineSettings().overrunDistanceUnit() );
493 mOverrunDistanceUnitWidget->setMapUnitScale( mSettings.lineSettings().overrunDistanceMapUnitScale() );
494
495 mThinningSettings = mSettings.thinningSettings();
496
497 mLabelMarginSpinBox->setValue( mThinningSettings.labelMarginDistance() );
498 mLabelMarginUnitWidget->setUnit( mThinningSettings.labelMarginDistanceUnit() );
499 mLabelMarginUnitWidget->setMapUnitScale( mThinningSettings.labelMarginDistanceMapUnitScale() );
500
501 mPrioritySlider->setValue( mSettings.priority );
502 mChkNoObstacle->setChecked( mSettings.obstacleSettings().isObstacle() );
503
504 mObstacleSettings = mSettings.obstacleSettings();
505
506 mChkNoDuplicates->setChecked( mThinningSettings.allowDuplicateRemoval() );
507
508 mLineSettings = mSettings.lineSettings();
509
510 chkLabelPerFeaturePart->setChecked( mSettings.labelPerPart );
511
512 mComboOverlapHandling->setCurrentIndex( mComboOverlapHandling->findData( static_cast<int>( mSettings.placementSettings().overlapHandling() ) ) );
513 mCheckAllowDegradedPlacement->setChecked( mSettings.placementSettings().allowDegradedPlacement() );
514 mPrioritizationComboBox->setCurrentIndex( mPrioritizationComboBox->findData( QVariant::fromValue( mSettings.placementSettings().prioritization() ) ) );
515
516 chkMergeLines->setChecked( mSettings.lineSettings().mergeLines() );
517 mMinSizeSpinBox->setValue( mThinningSettings.minimumFeatureSize() );
518 mLimitLabelChkBox->setChecked( mThinningSettings.limitNumberOfLabelsEnabled() );
519 mLimitLabelSpinBox->setValue( mThinningSettings.maximumNumberLabels() );
520
521 // direction symbol(s)
522 mDirectSymbChkBx->setChecked( mSettings.lineSettings().addDirectionSymbol() );
523 mDirectSymbLeftLineEdit->setText( mSettings.lineSettings().leftDirectionSymbol() );
524 mDirectSymbRightLineEdit->setText( mSettings.lineSettings().rightDirectionSymbol() );
525 mDirectSymbRevChkBx->setChecked( mSettings.lineSettings().reverseDirectionSymbol() );
526
527 mDirectSymbBtnGrp->button( static_cast<int>( mSettings.lineSettings().directionSymbolPlacement() ) )->setChecked( true );
528 mUpsidedownBtnGrp->button( static_cast<int>( mSettings.upsidedownLabels ) )->setChecked( true );
529
530 // curved label max character angles
531 mMaxCharAngleInDSpinBox->setValue( mSettings.maxCurvedCharAngleIn );
532 // lyr.maxCurvedCharAngleOut must be negative, but it is shown as positive spinbox in GUI
533 mMaxCharAngleOutDSpinBox->setValue( std::fabs( mSettings.maxCurvedCharAngleOut ) );
534
535 wrapCharacterEdit->setText( mSettings.wrapChar );
536 mAutoWrapLengthSpinBox->setValue( mSettings.autoWrapLength );
537 mAutoWrapTypeComboBox->setCurrentIndex( mSettings.useMaxLineLengthForAutoWrap ? 0 : 1 );
538
539 if ( mFontMultiLineAlignComboBox->findData( static_cast<int>( mSettings.multilineAlign ) ) != -1 )
540 {
541 mFontMultiLineAlignComboBox->setCurrentIndex( mFontMultiLineAlignComboBox->findData( static_cast<int>( mSettings.multilineAlign ) ) );
542 }
543 else
544 {
545 // the default pal layer settings for multiline alignment is to follow label placement, which isn't always available
546 // revert to left alignment in such case
547 mFontMultiLineAlignComboBox->setCurrentIndex( 0 );
548 }
549
550 chkPreserveRotation->setChecked( mSettings.preserveRotation );
551
552 mCoordRotationUnitComboBox->setCurrentIndex( 0 );
553 if ( mCoordRotationUnitComboBox->findData( static_cast<unsigned int>( mSettings.rotationUnit() ) ) >= 0 )
554 mCoordRotationUnitComboBox->setCurrentIndex( mCoordRotationUnitComboBox->findData( static_cast<unsigned int>( mSettings.rotationUnit() ) ) );
555
556 mScaleBasedVisibilityChkBx->setChecked( mSettings.scaleVisibility );
557 mMinScaleWidget->setScale( mSettings.minimumScale );
558 mMaxScaleWidget->setScale( mSettings.maximumScale );
559
560 mFormatNumChkBx->setChecked( mSettings.formatNumbers );
561 mFormatNumDecimalsSpnBx->setValue( mSettings.decimals );
562 mFormatNumPlusSignChkBx->setChecked( mSettings.plusSign );
563
564 // set pixel size limiting checked state before unit choice so limiting can be
565 // turned on as a default for map units, if minimum trigger value of 0 is used
566 mFontLimitPixelChkBox->setChecked( mSettings.fontLimitPixelSize );
567 mMinPixelLimit = mSettings.fontMinPixelSize; // ignored after first settings save
568 mFontMinPixelSpinBox->setValue( mSettings.fontMinPixelSize == 0 ? 3 : mSettings.fontMinPixelSize );
569 mFontMaxPixelSpinBox->setValue( mSettings.fontMaxPixelSize );
570
571 mZIndexSpinBox->setValue( mSettings.zIndex );
572
573 mDataDefinedProperties = mSettings.dataDefinedProperties();
574
575 // callout settings, to move to custom widget when multiple styles exist
576 if ( auto *lCallout = mSettings.callout() )
577 {
578 whileBlocking( mCalloutsDrawCheckBox )->setChecked( lCallout->enabled() );
579 whileBlocking( mCalloutStyleComboBox )->setCurrentIndex( mCalloutStyleComboBox->findData( lCallout->type() ) );
580 updateCalloutWidget( lCallout );
581 }
582 else
583 {
584 std::unique_ptr<QgsCallout> defaultCallout( QgsCalloutRegistry::defaultCallout() );
585 whileBlocking( mCalloutStyleComboBox )->setCurrentIndex( mCalloutStyleComboBox->findData( defaultCallout->type() ) );
586 whileBlocking( mCalloutsDrawCheckBox )->setChecked( false );
587 updateCalloutWidget( defaultCallout.get() );
588 }
589
590 updatePlacementWidgets();
591 updateLinePlacementOptions();
592
593 // needs to come before data defined setup, so connections work
594 blockInitSignals( false );
595
596 // set up data defined toolbuttons
597 // do this after other widgets are configured, so they can be enabled/disabled
598 populateDataDefinedButtons();
599
600 updateUi(); // should come after data defined button setup
601}
602
603void QgsLabelingGui::setSettings( const QgsPalLayerSettings &settings )
604{
605 mSettings = settings;
606 setLayer( mLayer );
607}
608
609void QgsLabelingGui::blockInitSignals( bool block )
610{
611 chkLineAbove->blockSignals( block );
612 chkLineBelow->blockSignals( block );
613 mPlacementModeComboBox->blockSignals( block );
614}
615
616void QgsLabelingGui::setLabelMode( LabelMode mode )
617{
618 mMode = mode;
619 mFieldExpressionWidget->setEnabled( mMode == Labels );
620 mLabelingFrame->setEnabled( mMode == Labels );
621}
622
623QgsPalLayerSettings QgsLabelingGui::layerSettings()
624{
625 QgsPalLayerSettings lyr;
626
627 // restore properties which aren't exposed in GUI
628 lyr.setUnplacedVisibility( mSettings.unplacedVisibility() );
629
630 lyr.drawLabels = ( mMode == Labels ) || !mLayer;
631
632 bool isExpression;
633 lyr.fieldName = mFieldExpressionWidget->currentField( &isExpression );
634 lyr.isExpression = isExpression;
635
636 lyr.dist = 0;
637
639 if ( mCheckAllowLabelsOutsidePolygons->isChecked() )
641 lyr.setPolygonPlacementFlags( polygonPlacementFlags );
642
643 lyr.centroidWhole = mCentroidRadioWhole->isChecked();
644 lyr.centroidInside = mCentroidInsideCheckBox->isChecked();
645 lyr.fitInPolygonOnly = mFitInsidePolygonCheckBox->isChecked();
646 lyr.dist = mLineDistanceSpnBx->value();
647 lyr.distUnits = mLineDistanceUnitWidget->unit();
648 lyr.distMapUnitScale = mLineDistanceUnitWidget->getMapUnitScale();
649
650 lyr.pointSettings().setMaximumDistance( mMaximumDistanceSpnBx->value() );
651 lyr.pointSettings().setMaximumDistanceUnit( mMaximumDistanceUnitWidget->unit() );
652 lyr.pointSettings().setMaximumDistanceMapUnitScale( mMaximumDistanceUnitWidget->getMapUnitScale() );
653
654 lyr.offsetType = static_cast<Qgis::LabelOffsetType>( mOffsetTypeComboBox->currentData().toInt() );
655 if ( mQuadrantBtnGrp )
656 {
657 lyr.pointSettings().setQuadrant( static_cast<Qgis::LabelQuadrantPosition>( mQuadrantBtnGrp->checkedId() ) );
658 }
659 lyr.xOffset = mPointOffsetXSpinBox->value();
660 lyr.yOffset = mPointOffsetYSpinBox->value();
661 lyr.offsetUnits = mPointOffsetUnitWidget->unit();
662 lyr.labelOffsetMapUnitScale = mPointOffsetUnitWidget->getMapUnitScale();
663 lyr.angleOffset = mPointAngleSpinBox->value();
664
666 if ( chkLineAbove->isChecked() )
667 linePlacementFlags |= Qgis::LabelLinePlacementFlag::AboveLine;
668 if ( chkLineBelow->isChecked() )
669 linePlacementFlags |= Qgis::LabelLinePlacementFlag::BelowLine;
670 if ( chkLineOn->isChecked() )
671 linePlacementFlags |= Qgis::LabelLinePlacementFlag::OnLine;
672 if ( !chkLineOrientationDependent->isChecked() )
674 lyr.lineSettings().setPlacementFlags( linePlacementFlags );
675
676 lyr.placement = static_cast<Qgis::LabelPlacement>( mPlacementModeComboBox->currentData().toInt() );
677
678 lyr.repeatDistance = mRepeatDistanceSpinBox->value();
679 lyr.repeatDistanceUnit = mRepeatDistanceUnitWidget->unit();
680 lyr.repeatDistanceMapUnitScale = mRepeatDistanceUnitWidget->getMapUnitScale();
681
682 lyr.lineSettings().setOverrunDistance( mOverrunDistanceSpinBox->value() );
683 lyr.lineSettings().setOverrunDistanceUnit( mOverrunDistanceUnitWidget->unit() );
684 lyr.lineSettings().setOverrunDistanceMapUnitScale( mOverrunDistanceUnitWidget->getMapUnitScale() );
685
686 mThinningSettings.setLabelMarginDistance( mLabelMarginSpinBox->value() );
687 mThinningSettings.setLabelMarginDistanceUnit( mLabelMarginUnitWidget->unit() );
688 mThinningSettings.setLabelMarginDistanceMapUnitScale( mLabelMarginUnitWidget->getMapUnitScale() );
689
690 lyr.priority = mPrioritySlider->value();
691
692 mObstacleSettings.setIsObstacle( mChkNoObstacle->isChecked() || mMode == ObstaclesOnly );
693 lyr.setObstacleSettings( mObstacleSettings );
694
695 lyr.lineSettings().setLineAnchorPercent( mLineSettings.lineAnchorPercent() );
696 lyr.lineSettings().setAnchorType( mLineSettings.anchorType() );
697 lyr.lineSettings().setAnchorClipping( mLineSettings.anchorClipping() );
698 lyr.lineSettings().setAnchorTextPoint( mLineSettings.anchorTextPoint() );
699
700 mThinningSettings.setAllowDuplicateRemoval( mChkNoDuplicates->isChecked() );
701
702 lyr.labelPerPart = chkLabelPerFeaturePart->isChecked();
703 lyr.placementSettings().setOverlapHandling( static_cast<Qgis::LabelOverlapHandling>( mComboOverlapHandling->currentData().toInt() ) );
704 lyr.placementSettings().setAllowDegradedPlacement( mCheckAllowDegradedPlacement->isChecked() );
705 lyr.placementSettings().setPrioritization( mPrioritizationComboBox->currentData().value<Qgis::LabelPrioritization>() );
706
707 lyr.lineSettings().setMergeLines( chkMergeLines->isChecked() );
708
709 lyr.scaleVisibility = mScaleBasedVisibilityChkBx->isChecked();
710 lyr.minimumScale = mMinScaleWidget->scale();
711 lyr.maximumScale = mMaxScaleWidget->scale();
712 lyr.useSubstitutions = mCheckBoxSubstituteText->isChecked();
713 lyr.substitutions = mSubstitutions;
714
715 lyr.setFormat( format( false ) );
716
717 // format numbers
718 lyr.formatNumbers = mFormatNumChkBx->isChecked();
719 lyr.decimals = mFormatNumDecimalsSpnBx->value();
720 lyr.plusSign = mFormatNumPlusSignChkBx->isChecked();
721
722 // direction symbol(s)
723 lyr.lineSettings().setAddDirectionSymbol( mDirectSymbChkBx->isChecked() );
724 lyr.lineSettings().setLeftDirectionSymbol( mDirectSymbLeftLineEdit->text() );
725 lyr.lineSettings().setRightDirectionSymbol( mDirectSymbRightLineEdit->text() );
726 lyr.lineSettings().setReverseDirectionSymbol( mDirectSymbRevChkBx->isChecked() );
727 if ( mDirectSymbBtnGrp )
728 {
729 lyr.lineSettings().setDirectionSymbolPlacement( static_cast<QgsLabelLineSettings::DirectionSymbolPlacement>( mDirectSymbBtnGrp->checkedId() ) );
730 }
731 if ( mUpsidedownBtnGrp )
732 {
733 lyr.upsidedownLabels = static_cast<Qgis::UpsideDownLabelHandling>( mUpsidedownBtnGrp->checkedId() );
734 }
735
736 lyr.maxCurvedCharAngleIn = mMaxCharAngleInDSpinBox->value();
737 // lyr.maxCurvedCharAngleOut must be negative, but it is shown as positive spinbox in GUI
738 lyr.maxCurvedCharAngleOut = -mMaxCharAngleOutDSpinBox->value();
739
740 mThinningSettings.setMinimumFeatureSize( mMinSizeSpinBox->value() );
741 mThinningSettings.setLimitNumberLabelsEnabled( mLimitLabelChkBox->isChecked() );
742 mThinningSettings.setMaximumNumberLabels( mLimitLabelSpinBox->value() );
743
744 lyr.setThinningSettings( mThinningSettings );
745
746 lyr.fontLimitPixelSize = mFontLimitPixelChkBox->isChecked();
747 lyr.fontMinPixelSize = mFontMinPixelSpinBox->value();
748 lyr.fontMaxPixelSize = mFontMaxPixelSpinBox->value();
749 lyr.wrapChar = wrapCharacterEdit->text();
750 lyr.autoWrapLength = mAutoWrapLengthSpinBox->value();
751 lyr.useMaxLineLengthForAutoWrap = mAutoWrapTypeComboBox->currentIndex() == 0;
752 lyr.multilineAlign = static_cast<Qgis::LabelMultiLineAlignment>( mFontMultiLineAlignComboBox->currentData().toInt() );
753 lyr.preserveRotation = chkPreserveRotation->isChecked();
754 lyr.setRotationUnit( static_cast<Qgis::AngleUnit>( mCoordRotationUnitComboBox->currentData().toInt() ) );
755 lyr.geometryGenerator = mGeometryGenerator->text();
756 lyr.geometryGeneratorType = mGeometryGeneratorType->currentData().value<Qgis::GeometryType>();
757 lyr.geometryGeneratorEnabled = mGeometryGeneratorGroupBox->isChecked();
758
759 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( mLayer );
760 lyr.layerType = vLayer ? vLayer->geometryType() : mGeomType;
761
762 lyr.zIndex = mZIndexSpinBox->value();
763
764 lyr.setDataDefinedProperties( mDataDefinedProperties );
765
766 // callout settings
767 const QString calloutType = mCalloutStyleComboBox->currentData().toString();
768 std::unique_ptr<QgsCallout> callout;
769 if ( QgsCalloutWidget *pew = qobject_cast<QgsCalloutWidget *>( mCalloutStackedWidget->currentWidget() ) )
770 {
771 callout.reset( pew->callout()->clone() );
772 }
773 if ( !callout )
774 callout.reset( QgsApplication::calloutRegistry()->createCallout( calloutType ) );
775
776 callout->setEnabled( mCalloutsDrawCheckBox->isChecked() );
777 lyr.setCallout( callout.release() );
778
779 return lyr;
780}
781
782void QgsLabelingGui::syncDefinedCheckboxFrame( QgsPropertyOverrideButton *ddBtn, QCheckBox *chkBx, QFrame *f )
783{
784 f->setEnabled( chkBx->isChecked() || ddBtn->isActive() );
785}
786
787bool QgsLabelingGui::eventFilter( QObject *object, QEvent *event )
788{
789 if ( object == mLblNoObstacle1 )
790 {
791 if ( event->type() == QEvent::MouseButtonPress && qgis::down_cast<QMouseEvent *>( event )->button() == Qt::LeftButton )
792 {
793 // clicking the obstacle label toggles the checkbox, just like a "normal" checkbox label...
794 mChkNoObstacle->setChecked( !mChkNoObstacle->isChecked() );
795 return true;
796 }
797 return false;
798 }
799 return QgsTextFormatWidget::eventFilter( object, event );
800}
801
802void QgsLabelingGui::updateUi()
803{
804 // enable/disable inline groupbox-like setups (that need to honor data defined setting)
805
806 syncDefinedCheckboxFrame( mBufferDrawDDBtn, mBufferDrawChkBx, mBufferFrame );
807 syncDefinedCheckboxFrame( mEnableMaskDDBtn, mEnableMaskChkBx, mMaskFrame );
808 syncDefinedCheckboxFrame( mShapeDrawDDBtn, mShapeDrawChkBx, mShapeFrame );
809 syncDefinedCheckboxFrame( mShadowDrawDDBtn, mShadowDrawChkBx, mShadowFrame );
810 syncDefinedCheckboxFrame( mCalloutDrawDDBtn, mCalloutsDrawCheckBox, mCalloutFrame );
811
812 syncDefinedCheckboxFrame( mDirectSymbDDBtn, mDirectSymbChkBx, mDirectSymbFrame );
813 syncDefinedCheckboxFrame( mFormatNumDDBtn, mFormatNumChkBx, mFormatNumFrame );
814 syncDefinedCheckboxFrame( mScaleBasedVisibilityDDBtn, mScaleBasedVisibilityChkBx, mScaleBasedVisibilityFrame );
815 syncDefinedCheckboxFrame( mFontLimitPixelDDBtn, mFontLimitPixelChkBox, mFontLimitPixelFrame );
816
817 chkMergeLines->setEnabled( !mDirectSymbChkBx->isChecked() );
818 if ( mDirectSymbChkBx->isChecked() )
819 {
820 chkMergeLines->setToolTip( tr( "This option is not compatible with line direction symbols." ) );
821 }
822 else
823 {
824 chkMergeLines->setToolTip( QString() );
825 }
826}
827
828void QgsLabelingGui::setFormatFromStyle( const QString &name, QgsStyle::StyleEntity type, const QString &stylePath )
829{
830 QgsStyle *style = QgsProject::instance()->styleSettings()->styleAtPath( stylePath );
831
832 if ( !style )
833 style = QgsStyle::defaultStyle();
834
835 switch ( type )
836 {
844 {
845 QgsTextFormatWidget::setFormatFromStyle( name, type, stylePath );
846 return;
847 }
848
850 {
851 if ( !style->labelSettingsNames().contains( name ) )
852 return;
853
854 QgsPalLayerSettings settings = style->labelSettings( name );
855 if ( settings.fieldName.isEmpty() )
856 {
857 // if saved settings doesn't have a field name stored, retain the current one
858 bool isExpression;
859 settings.fieldName = mFieldExpressionWidget->currentField( &isExpression );
860 settings.isExpression = isExpression;
861 }
862 setSettings( settings );
863 break;
864 }
865 }
866}
867
868void QgsLabelingGui::setContext( const QgsSymbolWidgetContext &context )
869{
870 if ( QgsCalloutWidget *cw = qobject_cast<QgsCalloutWidget *>( mCalloutStackedWidget->currentWidget() ) )
871 {
872 cw->setContext( context );
873 }
875}
876
877void QgsLabelingGui::saveFormat()
878{
879 QgsStyleSaveDialog saveDlg( this, QgsStyle::LabelSettingsEntity );
880 saveDlg.setDefaultTags( mTextFormatsListWidget->currentTagFilter() );
881 if ( !saveDlg.exec() )
882 return;
883
884 if ( saveDlg.name().isEmpty() )
885 return;
886
887 QgsStyle *style = saveDlg.destinationStyle();
888 if ( !style )
889 return;
890
891 switch ( saveDlg.selectedType() )
892 {
894 {
895 // check if there is no format with same name
896 if ( style->textFormatNames().contains( saveDlg.name() ) )
897 {
898 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 );
899 if ( res != QMessageBox::Yes )
900 {
901 return;
902 }
903 style->removeTextFormat( saveDlg.name() );
904 }
905 const QStringList symbolTags = saveDlg.tags().split( ',' );
906
907 const QgsTextFormat newFormat = format();
908 style->addTextFormat( saveDlg.name(), newFormat );
909 style->saveTextFormat( saveDlg.name(), newFormat, saveDlg.isFavorite(), symbolTags );
910 break;
911 }
912
914 {
915 // check if there is no settings with same name
916 if ( style->labelSettingsNames().contains( saveDlg.name() ) )
917 {
918 const int res = 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
939 break;
940 }
941}
942
943void QgsLabelingGui::updateGeometryTypeBasedWidgets()
944{
945 Qgis::GeometryType geometryType = mGeomType;
946
947 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( mLayer );
948
949 if ( mGeometryGeneratorGroupBox->isChecked() )
950 geometryType = mGeometryGeneratorType->currentData().value<Qgis::GeometryType>();
951 else if ( vLayer )
952 geometryType = vLayer->geometryType();
953
954 // show/hide options based upon geometry type
955 chkMergeLines->setVisible( geometryType == Qgis::GeometryType::Line );
956 mDirectSymbolsFrame->setVisible( geometryType == Qgis::GeometryType::Line );
957 mMinSizeFrame->setVisible( geometryType != Qgis::GeometryType::Point );
958 mPolygonFeatureOptionsFrame->setVisible( geometryType == Qgis::GeometryType::Polygon );
959
960
961 const Qgis::LabelPlacement prevPlacement = static_cast<Qgis::LabelPlacement>( mPlacementModeComboBox->currentData().toInt() );
962 mPlacementModeComboBox->clear();
963
964 switch ( geometryType )
965 {
967 mPlacementModeComboBox->addItem( tr( "Cartographic" ), static_cast<int>( Qgis::LabelPlacement::OrderedPositionsAroundPoint ) );
968 mPlacementModeComboBox->addItem( tr( "Around Point" ), static_cast<int>( Qgis::LabelPlacement::AroundPoint ) );
969 mPlacementModeComboBox->addItem( tr( "Offset from Point" ), static_cast<int>( Qgis::LabelPlacement::OverPoint ) );
970 break;
971
973 mPlacementModeComboBox->addItem( tr( "Parallel" ), static_cast<int>( Qgis::LabelPlacement::Line ) );
974 mPlacementModeComboBox->addItem( tr( "Curved" ), static_cast<int>( Qgis::LabelPlacement::Curved ) );
975 mPlacementModeComboBox->addItem( tr( "Horizontal" ), static_cast<int>( Qgis::LabelPlacement::Horizontal ) );
976 break;
977
979 mPlacementModeComboBox->addItem( tr( "Offset from Centroid" ), static_cast<int>( Qgis::LabelPlacement::OverPoint ) );
980 mPlacementModeComboBox->addItem( tr( "Around Centroid" ), static_cast<int>( Qgis::LabelPlacement::AroundPoint ) );
981 mPlacementModeComboBox->addItem( tr( "Horizontal" ), static_cast<int>( Qgis::LabelPlacement::Horizontal ) );
982 mPlacementModeComboBox->addItem( tr( "Free (Angled)" ), static_cast<int>( Qgis::LabelPlacement::Free ) );
983 mPlacementModeComboBox->addItem( tr( "Using Perimeter" ), static_cast<int>( Qgis::LabelPlacement::Line ) );
984 mPlacementModeComboBox->addItem( tr( "Using Perimeter (Curved)" ), static_cast<int>( Qgis::LabelPlacement::PerimeterCurved ) );
985 mPlacementModeComboBox->addItem( tr( "Outside Polygons" ), static_cast<int>( Qgis::LabelPlacement::OutsidePolygons ) );
986 break;
987
989 break;
991 qFatal( "unknown geometry type unexpected" );
992 }
993
994 if ( mPlacementModeComboBox->findData( static_cast<int>( prevPlacement ) ) != -1 )
995 {
996 mPlacementModeComboBox->setCurrentIndex( mPlacementModeComboBox->findData( static_cast<int>( prevPlacement ) ) );
997 }
998
999 if ( geometryType == Qgis::GeometryType::Point || geometryType == Qgis::GeometryType::Polygon )
1000 {
1001 // follow placement alignment is only valid for point or polygon layers
1002 if ( mFontMultiLineAlignComboBox->findData( static_cast<int>( Qgis::LabelMultiLineAlignment::FollowPlacement ) ) == -1 )
1003 mFontMultiLineAlignComboBox->addItem( tr( "Follow Label Placement" ), static_cast<int>( Qgis::LabelMultiLineAlignment::FollowPlacement ) );
1004 }
1005 else
1006 {
1007 const int idx = mFontMultiLineAlignComboBox->findData( static_cast<int>( Qgis::LabelMultiLineAlignment::FollowPlacement ) );
1008 if ( idx >= 0 )
1009 mFontMultiLineAlignComboBox->removeItem( idx );
1010 }
1011
1012 updatePlacementWidgets();
1013 updateLinePlacementOptions();
1014}
1015
1016void QgsLabelingGui::showGeometryGeneratorExpressionBuilder()
1017{
1018 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( mLayer );
1019 QgsExpressionBuilderDialog expressionBuilder( vLayer );
1020
1021 expressionBuilder.setExpressionText( mGeometryGenerator->text() );
1022 expressionBuilder.setExpressionContext( createExpressionContext() );
1023
1024 if ( expressionBuilder.exec() )
1025 {
1026 mGeometryGenerator->setText( expressionBuilder.expressionText() );
1027 }
1028}
1029
1030void QgsLabelingGui::validateGeometryGeneratorExpression()
1031{
1032 bool valid = true;
1033
1034 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( mLayer );
1035
1036 if ( mGeometryGeneratorGroupBox->isChecked() )
1037 {
1038 if ( !mPreviewFeature.isValid() && vLayer )
1039 vLayer->getFeatures( QgsFeatureRequest().setLimit( 1 ) ).nextFeature( mPreviewFeature );
1040
1041 QgsExpression expression( mGeometryGenerator->text() );
1042 QgsExpressionContext context = createExpressionContext();
1043 context.setFeature( mPreviewFeature );
1044
1045 expression.prepare( &context );
1046
1047 if ( expression.hasParserError() )
1048 {
1049 mGeometryGeneratorWarningLabel->setText( expression.parserErrorString() );
1050 valid = false;
1051 }
1052 else
1053 {
1054 const QVariant result = expression.evaluate( &context );
1055 const QgsGeometry geometry = result.value<QgsGeometry>();
1056 const Qgis::GeometryType configuredGeometryType = mGeometryGeneratorType->currentData().value<Qgis::GeometryType>();
1057 if ( geometry.isNull() )
1058 {
1059 mGeometryGeneratorWarningLabel->setText( tr( "Result of the expression is not a geometry" ) );
1060 valid = false;
1061 }
1062 else if ( geometry.type() != configuredGeometryType )
1063 {
1064 mGeometryGeneratorWarningLabel->setText( QStringLiteral( "<p>%1</p><p><a href=\"#determineGeometryGeneratorType\">%2</a></p>" ).arg( tr( "Result of the expression does not match configured geometry type." ), tr( "Change to %1" ).arg( QgsWkbTypes::geometryDisplayString( geometry.type() ) ) ) );
1065 valid = false;
1066 }
1067 }
1068 }
1069
1070 // The collapsible groupbox internally changes the visibility of this
1071 // Work around by setting the visibility deferred in the next event loop cycle.
1072 QTimer *timer = new QTimer();
1073 connect( timer, &QTimer::timeout, this, [this, valid]() {
1074 mGeometryGeneratorWarningLabel->setVisible( !valid );
1075 } );
1076 connect( timer, &QTimer::timeout, timer, &QTimer::deleteLater );
1077 timer->start( 0 );
1078}
1079
1080void QgsLabelingGui::determineGeometryGeneratorType()
1081{
1082 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( mLayer );
1083 if ( !mPreviewFeature.isValid() && vLayer )
1084 vLayer->getFeatures( QgsFeatureRequest().setLimit( 1 ) ).nextFeature( mPreviewFeature );
1085
1086 QgsExpression expression( mGeometryGenerator->text() );
1087 QgsExpressionContext context = createExpressionContext();
1088 context.setFeature( mPreviewFeature );
1089
1090 expression.prepare( &context );
1091 const QgsGeometry geometry = expression.evaluate( &context ).value<QgsGeometry>();
1092
1093 mGeometryGeneratorType->setCurrentIndex( mGeometryGeneratorType->findData( QVariant::fromValue( geometry.type() ) ) );
1094}
1095
1096void QgsLabelingGui::calloutTypeChanged()
1097{
1098 const QString newCalloutType = mCalloutStyleComboBox->currentData().toString();
1099 QgsCalloutWidget *pew = qobject_cast<QgsCalloutWidget *>( mCalloutStackedWidget->currentWidget() );
1100 if ( pew )
1101 {
1102 if ( pew->callout() && pew->callout()->type() == newCalloutType )
1103 return;
1104 }
1105
1106 // get creation function for new callout from registry
1107 QgsCalloutRegistry *registry = QgsApplication::calloutRegistry();
1108 QgsCalloutAbstractMetadata *am = registry->calloutMetadata( newCalloutType );
1109 if ( !am ) // check whether the metadata is assigned
1110 return;
1111
1112 // change callout to a new one (with different type)
1113 // base new callout on existing callout's properties
1114 const std::unique_ptr<QgsCallout> newCallout( am->createCallout( pew && pew->callout() ? pew->callout()->properties( QgsReadWriteContext() ) : QVariantMap(), QgsReadWriteContext() ) );
1115 if ( !newCallout )
1116 return;
1117
1118 updateCalloutWidget( newCallout.get() );
1119 updatePreview();
1120}
1121
1122
1123//
1124// QgsLabelSettingsDialog
1125//
1126
1127QgsLabelSettingsDialog::QgsLabelSettingsDialog( const QgsPalLayerSettings &settings, QgsVectorLayer *layer, QgsMapCanvas *mapCanvas, QWidget *parent, Qgis::GeometryType geomType )
1128 : QDialog( parent )
1129{
1130 QVBoxLayout *vLayout = new QVBoxLayout();
1131 mWidget = new QgsLabelingGui( layer, mapCanvas, settings, nullptr, geomType );
1132 vLayout->addWidget( mWidget );
1133 mButtonBox = new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::Ok, Qt::Horizontal );
1134 connect( mButtonBox, &QDialogButtonBox::accepted, this, &QDialog::accept );
1135 connect( mButtonBox, &QDialogButtonBox::rejected, this, &QDialog::reject );
1136 connect( mButtonBox, &QDialogButtonBox::helpRequested, this, &QgsLabelSettingsDialog::showHelp );
1137 vLayout->addWidget( mButtonBox );
1138 setLayout( vLayout );
1139 setWindowTitle( tr( "Label Settings" ) );
1140}
1141
1142QDialogButtonBox *QgsLabelSettingsDialog::buttonBox() const
1143{
1144 return mButtonBox;
1145}
1146
1147void QgsLabelSettingsDialog::showHelp()
1148{
1149 QgsHelp::openHelp( QStringLiteral( "style_library/label_settings.html" ) );
1150}
1151
1152
@ BelowLine
Labels can be placed below a line feature. Unless MapOrientation is also specified this mode respects...
Definition qgis.h:1278
@ MapOrientation
Signifies that the AboveLine and BelowLine flags should respect the map's orientation rather than the...
Definition qgis.h:1279
@ OnLine
Labels can be placed directly over a line feature.
Definition qgis.h:1276
@ AboveLine
Labels can be placed above a line feature. Unless MapOrientation is also specified this mode respects...
Definition qgis.h:1277
AngleUnit
Units of angles.
Definition qgis.h:5138
@ SecondsOfArc
Seconds of arc.
Definition qgis.h:5143
@ Radians
Square kilometers.
Definition qgis.h:5140
@ Turn
Turn/revolutions.
Definition qgis.h:5144
@ MinutesOfArc
Minutes of arc.
Definition qgis.h:5142
@ MilliradiansSI
Angular milliradians (SI definition, 1/1000 of radian).
Definition qgis.h:5145
@ Degrees
Degrees.
Definition qgis.h:5139
@ Gon
Gon/gradian.
Definition qgis.h:5141
@ MilNATO
Angular mil (NATO definition, 6400 mil = 2PI radians).
Definition qgis.h:5146
LabelOffsetType
Behavior modifier for label offset and distance, only applies in some label placement modes.
Definition qgis.h:1241
LabelPrioritization
Label prioritization.
Definition qgis.h:1180
LabelPlacement
Placement modes which determine how label candidates are generated for a feature.
Definition qgis.h:1194
@ OverPoint
Arranges candidates over a point (or centroid of a polygon), or at a preset offset from the point....
Definition qgis.h:1196
@ Curved
Arranges candidates following the curvature of a line feature. Applies to line layers only.
Definition qgis.h:1198
@ AroundPoint
Arranges candidates in a circle around a point (or centroid of a polygon). Applies to point or polygo...
Definition qgis.h:1195
@ Line
Arranges candidates parallel to a generalised line representing the feature or parallel to a polygon'...
Definition qgis.h:1197
@ Free
Arranges candidates scattered throughout a polygon feature. Candidates are rotated to respect the pol...
Definition qgis.h:1200
@ OrderedPositionsAroundPoint
Candidates are placed in predefined positions around a point. Preference is given to positions with g...
Definition qgis.h:1201
@ Horizontal
Arranges horizontal candidates scattered throughout a polygon feature. Applies to polygon layers only...
Definition qgis.h:1199
@ PerimeterCurved
Arranges candidates following the curvature of a polygon's boundary. Applies to polygon layers only.
Definition qgis.h:1202
@ OutsidePolygons
Candidates are placed outside of polygon boundaries. Applies to polygon layers only.
Definition qgis.h:1203
@ AllowPlacementInsideOfPolygon
Labels can be placed inside a polygon feature.
Definition qgis.h:1302
@ AllowPlacementOutsideOfPolygon
Labels can be placed outside of a polygon feature.
Definition qgis.h:1301
QFlags< LabelLinePlacementFlag > LabelLinePlacementFlags
Line placement flags, which control how candidates are generated for a linear feature.
Definition qgis.h:1290
QFlags< LabelPolygonPlacementFlag > LabelPolygonPlacementFlags
Polygon placement flags, which control how candidates are generated for a polygon feature.
Definition qgis.h:1312
LabelQuadrantPosition
Label quadrant positions.
Definition qgis.h:1255
GeometryType
The geometry types are used to group Qgis::WkbType in a coarse way.
Definition qgis.h:358
@ Point
Points.
Definition qgis.h:359
@ Line
Lines.
Definition qgis.h:360
@ Polygon
Polygons.
Definition qgis.h:361
@ Unknown
Unknown types.
Definition qgis.h:362
@ Null
No geometry.
Definition qgis.h:363
LabelMultiLineAlignment
Text alignment for multi-line labels.
Definition qgis.h:1338
@ Center
Center align.
Definition qgis.h:1340
@ FollowPlacement
Alignment follows placement of label, e.g., labels to the left of a feature will be drawn with right ...
Definition qgis.h:1342
@ Vector
Vector layer.
Definition qgis.h:191
@ Mesh
Mesh layer. Added in QGIS 3.2.
Definition qgis.h:194
LabelOverlapHandling
Label overlap handling.
Definition qgis.h:1167
UpsideDownLabelHandling
Handling techniques for upside down labels.
Definition qgis.h:1323
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:428
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition qgshelp.cpp:38
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 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 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 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:80
Qgis::LayerType type
Definition qgsmaplayer.h:90
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.
bool labelPerPart
true if every part of a multi-part feature should be labeled.
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:116
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:204
@ LabelSettingsEntity
Label settings.
Definition qgsstyle.h:210
@ TextFormatEntity
Text formats.
Definition qgsstyle.h:209
@ SmartgroupEntity
Smart groups.
Definition qgsstyle.h:208
@ Symbol3DEntity
3D symbol entity
Definition qgsstyle.h:212
@ SymbolEntity
Symbols.
Definition qgsstyle.h:205
@ TagEntity
Tags.
Definition qgsstyle.h:206
@ ColorrampEntity
Color ramps.
Definition qgsstyle.h:207
@ LegendPatchShapeEntity
Legend patch shape.
Definition qgsstyle.h:211
static QgsStyle * defaultStyle(bool initialize=true)
Returns the default application-wide style.
Definition qgsstyle.cpp:147
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:373
QgsPalLayerSettings labelSettings(const QString &name) const
Returns the label settings with the specified name.
@ Labeling
Text format used in labeling.
Definition qgsstyle.h:812
bool saveTextFormat(const QString &name, const QgsTextFormat &format, bool favorite, const QStringList &tags)
Adds a text format to the database.
Definition qgsstyle.cpp:981
bool addLabelSettings(const QString &name, const QgsPalLayerSettings &settings, bool update=false)
Adds label settings with the specified name to the style.
Definition qgsstyle.cpp:395
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:6511