QGIS API Documentation 3.43.0-Master (c4a2e9c6d2f)
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#include "moc_qgslabelinggui.cpp"
20#include "qgsvectorlayer.h"
21#include "qgsmapcanvas.h"
22#include "qgsproject.h"
25#include "qgshelp.h"
26#include "qgsstylesavedialog.h"
27#include "qgscallout.h"
28#include "qgsapplication.h"
29#include "qgscalloutsregistry.h"
35#include "qgsgui.h"
36#include "qgsmeshlayer.h"
37#include "qgsvectortilelayer.h"
38
39#include <QButtonGroup>
40#include <QMessageBox>
41
43
44QgsExpressionContext QgsLabelingGui::createExpressionContext() const
45{
46 QgsExpressionContext expContext;
47 if ( mMapCanvas )
48 {
49 expContext = mMapCanvas->createExpressionContext();
50 }
51 else
52 {
56 }
57
58 if ( mLayer )
59 expContext << QgsExpressionContextUtils::layerScope( mLayer );
60
61 if ( mLayer && mLayer->type() == Qgis::LayerType::Mesh )
62 {
63 if ( mGeomType == Qgis::GeometryType::Point )
65 else if ( mGeomType == Qgis::GeometryType::Polygon )
67 }
68
70
71 //TODO - show actual value
72 expContext.setOriginalValueVariable( QVariant() );
74
75 return expContext;
76}
77
78void QgsLabelingGui::updateCalloutWidget( QgsCallout *callout )
79{
80 if ( !callout )
81 {
82 mCalloutStackedWidget->setCurrentWidget( pageDummy );
83 return;
84 }
85
86 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( mLayer );
87 if ( !vLayer )
88 {
89 mCalloutStackedWidget->setCurrentWidget( pageDummy );
90 return;
91 }
92
93 if ( mCalloutStackedWidget->currentWidget() != pageDummy )
94 {
95 // stop updating from the original widget
96 if ( QgsCalloutWidget *pew = qobject_cast<QgsCalloutWidget *>( mCalloutStackedWidget->currentWidget() ) )
97 disconnect( pew, &QgsCalloutWidget::changed, this, &QgsLabelingGui::updatePreview );
98 }
99
101 if ( QgsCalloutAbstractMetadata *am = registry->calloutMetadata( callout->type() ) )
102 {
103 if ( QgsCalloutWidget *w = am->createCalloutWidget( vLayer ) )
104 {
105 Qgis::GeometryType geometryType = mGeomType;
106 if ( mGeometryGeneratorGroupBox->isChecked() )
107 geometryType = mGeometryGeneratorType->currentData().value<Qgis::GeometryType>();
108 else if ( vLayer )
109 geometryType = vLayer->geometryType();
110 w->setGeometryType( geometryType );
111 w->setCallout( callout );
112
113 w->setContext( context() );
114 mCalloutStackedWidget->addWidget( w );
115 mCalloutStackedWidget->setCurrentWidget( w );
116 // start receiving updates from widget
117 connect( w, &QgsCalloutWidget::changed, this, &QgsLabelingGui::updatePreview );
118 return;
119 }
120 }
121 // When anything is not right
122 mCalloutStackedWidget->setCurrentWidget( pageDummy );
123}
124
125void QgsLabelingGui::showObstacleSettings()
126{
127 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( mLayer );
128 if ( !vLayer )
129 {
130 return;
131 }
132
133 QgsExpressionContext context = createExpressionContext();
134
135 QgsSymbolWidgetContext symbolContext;
136 symbolContext.setExpressionContext( &context );
137 symbolContext.setMapCanvas( mMapCanvas );
138
139 QgsLabelObstacleSettingsWidget *widget = new QgsLabelObstacleSettingsWidget( nullptr, vLayer );
140 widget->setDataDefinedProperties( mDataDefinedProperties );
141 widget->setSettings( mObstacleSettings );
142 widget->setGeometryType( vLayer ? vLayer->geometryType() : Qgis::GeometryType::Unknown );
143 widget->setContext( symbolContext );
144
145 auto applySettings = [=] {
146 mObstacleSettings = widget->settings();
147 const QgsPropertyCollection obstacleDataDefinedProperties = widget->dataDefinedProperties();
148 widget->updateDataDefinedProperties( mDataDefinedProperties );
149 emit widgetChanged();
150 };
151
153 if ( panel && panel->dockMode() )
154 {
155 connect( widget, &QgsLabelSettingsWidgetBase::changed, this, [=] {
156 applySettings();
157 } );
158 panel->openPanel( widget );
159 }
160 else
161 {
162 QgsLabelSettingsWidgetDialog dialog( widget, this );
163
164 dialog.buttonBox()->addButton( QDialogButtonBox::Help );
165 connect( dialog.buttonBox(), &QDialogButtonBox::helpRequested, this, [=] {
166 QgsHelp::openHelp( QStringLiteral( "style_library/label_settings.html#obstacles" ) );
167 } );
168
169 if ( dialog.exec() )
170 {
171 applySettings();
172 }
173 // reactivate button's window
174 activateWindow();
175 }
176}
177
178void QgsLabelingGui::showLineAnchorSettings()
179{
180 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( mLayer );
181 if ( !vLayer )
182 {
183 return;
184 }
185
186 QgsExpressionContext context = createExpressionContext();
187
188 QgsSymbolWidgetContext symbolContext;
189 symbolContext.setExpressionContext( &context );
190 symbolContext.setMapCanvas( mMapCanvas );
191
192 QgsLabelLineAnchorWidget *widget = new QgsLabelLineAnchorWidget( nullptr, vLayer );
193 widget->setDataDefinedProperties( mDataDefinedProperties );
194 widget->setSettings( mLineSettings );
195 widget->setGeometryType( vLayer ? vLayer->geometryType() : Qgis::GeometryType::Unknown );
196 widget->setContext( symbolContext );
197
198 auto applySettings = [=] {
199 const QgsLabelLineSettings widgetSettings = widget->settings();
200 mLineSettings.setLineAnchorPercent( widgetSettings.lineAnchorPercent() );
201 mLineSettings.setAnchorType( widgetSettings.anchorType() );
202 mLineSettings.setAnchorClipping( widgetSettings.anchorClipping() );
203 mLineSettings.setAnchorTextPoint( widgetSettings.anchorTextPoint() );
204 const QgsPropertyCollection obstacleDataDefinedProperties = widget->dataDefinedProperties();
205 widget->updateDataDefinedProperties( mDataDefinedProperties );
206 emit widgetChanged();
207 };
208
210 if ( panel && panel->dockMode() )
211 {
212 connect( widget, &QgsLabelSettingsWidgetBase::changed, this, [=] {
213 applySettings();
214 } );
215 panel->openPanel( widget );
216 }
217 else
218 {
219 QgsLabelSettingsWidgetDialog dialog( widget, this );
220
221 dialog.buttonBox()->addButton( QDialogButtonBox::Help );
222 connect( dialog.buttonBox(), &QDialogButtonBox::helpRequested, this, [=] {
223 QgsHelp::openHelp( QStringLiteral( "style_library/label_settings.html#placement-for-line-layers" ) );
224 } );
225
226 if ( dialog.exec() )
227 {
228 applySettings();
229 }
230 // reactivate button's window
231 activateWindow();
232 }
233}
234
235void QgsLabelingGui::showDuplicateSettings()
236{
237 QgsExpressionContext context = createExpressionContext();
238
239 QgsSymbolWidgetContext symbolContext;
240 symbolContext.setExpressionContext( &context );
241 symbolContext.setMapCanvas( mMapCanvas );
242
244 widget->setDataDefinedProperties( mDataDefinedProperties );
245 widget->setSettings( mThinningSettings );
246 auto vectorLayer = qobject_cast< QgsVectorLayer * >( mLayer );
247 widget->setGeometryType( vectorLayer ? vectorLayer->geometryType() : Qgis::GeometryType::Unknown );
248 widget->setContext( symbolContext );
249
250 auto applySettings = [=] {
251 mThinningSettings = widget->settings();
252 const QgsPropertyCollection obstacleDataDefinedProperties = widget->dataDefinedProperties();
253 widget->updateDataDefinedProperties( mDataDefinedProperties );
254 emit widgetChanged();
255 };
256
258 if ( panel && panel->dockMode() )
259 {
260 connect( widget, &QgsLabelSettingsWidgetBase::changed, this, [=] {
261 applySettings();
262 } );
263 panel->openPanel( widget );
264 }
265 else
266 {
267 QgsLabelSettingsWidgetDialog dialog( widget, this );
268 if ( dialog.exec() )
269 {
270 applySettings();
271 }
272 // reactivate button's window
273 activateWindow();
274 }
275}
276
277QgsLabelingGui::QgsLabelingGui( QgsVectorLayer *layer, QgsMapCanvas *mapCanvas, const QgsPalLayerSettings &layerSettings, QWidget *parent, Qgis::GeometryType geomType )
278 : QgsTextFormatWidget( mapCanvas, parent, QgsTextFormatWidget::Labeling, layer )
279 , mMode( NoLabels )
280 , mSettings( layerSettings )
281{
282 mGeomType = geomType;
283
284 init();
285
286 setLayer( layer );
287}
288
289QgsLabelingGui::QgsLabelingGui( QgsMeshLayer *layer, QgsMapCanvas *mapCanvas, const QgsPalLayerSettings &settings, QWidget *parent, Qgis::GeometryType geomType )
290 : QgsTextFormatWidget( mapCanvas, parent, QgsTextFormatWidget::Labeling, layer )
291 , mMode( NoLabels )
292 , mSettings( settings )
293{
294 mGeomType = geomType;
295
296 init();
297
298 setLayer( layer );
299}
300
301QgsLabelingGui::QgsLabelingGui( QgsVectorTileLayer *layer, QgsMapCanvas *mapCanvas, const QgsPalLayerSettings &settings, QWidget *parent, Qgis::GeometryType geomType )
302 : QgsTextFormatWidget( mapCanvas, parent, QgsTextFormatWidget::Labeling, layer )
303 , mMode( NoLabels )
304 , mSettings( settings )
305{
306 mGeomType = geomType;
307
308 init();
309
310 setLayer( layer );
311}
312
313
314QgsLabelingGui::QgsLabelingGui( QgsMapCanvas *mapCanvas, QWidget *parent, QgsMapLayer *layer )
315 : QgsTextFormatWidget( mapCanvas, parent, QgsTextFormatWidget::Labeling, layer )
316 , mMode( NoLabels )
317{
318}
319
320
321QgsLabelingGui::QgsLabelingGui( QgsMapCanvas *mapCanvas, const QgsPalLayerSettings &settings, QWidget *parent )
322 : QgsTextFormatWidget( mapCanvas, parent, QgsTextFormatWidget::Labeling, nullptr )
323 , mMode( NoLabels )
324 , mSettings( settings )
325{
326 init();
327
328 setLayer( nullptr );
329}
330
331void QgsLabelingGui::init()
332{
334
335 mStackedWidgetLabelWith->setSizeMode( QgsStackedWidget::SizeMode::CurrentPageOnly );
336
337 mFontMultiLineAlignComboBox->addItem( tr( "Left" ), static_cast<int>( Qgis::LabelMultiLineAlignment::Left ) );
338 mFontMultiLineAlignComboBox->addItem( tr( "Center" ), static_cast<int>( Qgis::LabelMultiLineAlignment::Center ) );
339 mFontMultiLineAlignComboBox->addItem( tr( "Right" ), static_cast<int>( Qgis::LabelMultiLineAlignment::Right ) );
340 mFontMultiLineAlignComboBox->addItem( tr( "Justify" ), static_cast<int>( Qgis::LabelMultiLineAlignment::Justify ) );
341
342 mCoordRotationUnitComboBox->addItem( QgsUnitTypes::toString( Qgis::AngleUnit::Degrees ), static_cast<int>( Qgis::AngleUnit::Degrees ) );
343 mCoordRotationUnitComboBox->addItem( QgsUnitTypes::toString( Qgis::AngleUnit::Radians ), static_cast<int>( Qgis::AngleUnit::Radians ) );
344 mCoordRotationUnitComboBox->addItem( QgsUnitTypes::toString( Qgis::AngleUnit::Gon ), static_cast<int>( Qgis::AngleUnit::Gon ) );
345 mCoordRotationUnitComboBox->addItem( QgsUnitTypes::toString( Qgis::AngleUnit::MinutesOfArc ), static_cast<int>( Qgis::AngleUnit::MinutesOfArc ) );
346 mCoordRotationUnitComboBox->addItem( QgsUnitTypes::toString( Qgis::AngleUnit::SecondsOfArc ), static_cast<int>( Qgis::AngleUnit::SecondsOfArc ) );
347 mCoordRotationUnitComboBox->addItem( QgsUnitTypes::toString( Qgis::AngleUnit::Turn ), static_cast<int>( Qgis::AngleUnit::Turn ) );
348 mCoordRotationUnitComboBox->addItem( QgsUnitTypes::toString( Qgis::AngleUnit::MilliradiansSI ), static_cast<int>( Qgis::AngleUnit::MilliradiansSI ) );
349 mCoordRotationUnitComboBox->addItem( QgsUnitTypes::toString( Qgis::AngleUnit::MilNATO ), static_cast<int>( Qgis::AngleUnit::MilNATO ) );
350
351 // connections for groupboxes with separate activation checkboxes (that need to honor data defined setting)
352 connect( mBufferDrawChkBx, &QAbstractButton::toggled, this, &QgsLabelingGui::updateUi );
353 connect( mBufferDrawDDBtn, &QgsPropertyOverrideButton::changed, this, &QgsLabelingGui::updateUi );
354 connect( mEnableMaskChkBx, &QAbstractButton::toggled, this, &QgsLabelingGui::updateUi );
355 connect( mShapeDrawChkBx, &QAbstractButton::toggled, this, &QgsLabelingGui::updateUi );
356 connect( mCalloutsDrawCheckBox, &QAbstractButton::toggled, this, &QgsLabelingGui::updateUi );
357 connect( mShadowDrawChkBx, &QAbstractButton::toggled, this, &QgsLabelingGui::updateUi );
358 connect( mDirectSymbChkBx, &QAbstractButton::toggled, this, &QgsLabelingGui::updateUi );
359 connect( mFormatNumChkBx, &QAbstractButton::toggled, this, &QgsLabelingGui::updateUi );
360 connect( mScaleBasedVisibilityChkBx, &QAbstractButton::toggled, this, &QgsLabelingGui::updateUi );
361 connect( mFontLimitPixelChkBox, &QAbstractButton::toggled, this, &QgsLabelingGui::updateUi );
362 connect( mGeometryGeneratorGroupBox, &QGroupBox::toggled, this, &QgsLabelingGui::updateGeometryTypeBasedWidgets );
363 connect( mGeometryGeneratorType, qOverload<int>( &QComboBox::currentIndexChanged ), this, &QgsLabelingGui::updateGeometryTypeBasedWidgets );
364 connect( mGeometryGeneratorExpressionButton, &QToolButton::clicked, this, &QgsLabelingGui::showGeometryGeneratorExpressionBuilder );
365 connect( mGeometryGeneratorGroupBox, &QGroupBox::toggled, this, &QgsLabelingGui::validateGeometryGeneratorExpression );
366 connect( mGeometryGenerator, &QgsCodeEditorExpression::textChanged, this, &QgsLabelingGui::validateGeometryGeneratorExpression );
367 connect( mGeometryGeneratorType, qOverload<int>( &QComboBox::currentIndexChanged ), this, &QgsLabelingGui::validateGeometryGeneratorExpression );
368 connect( mObstacleSettingsButton, &QAbstractButton::clicked, this, &QgsLabelingGui::showObstacleSettings );
369 connect( mLineAnchorSettingsButton, &QAbstractButton::clicked, this, &QgsLabelingGui::showLineAnchorSettings );
370 connect( mDuplicateSettingsButton, &QAbstractButton::clicked, this, &QgsLabelingGui::showDuplicateSettings );
371
372 mFieldExpressionWidget->registerExpressionContextGenerator( this );
373
374 mMinScaleWidget->setMapCanvas( mMapCanvas );
375 mMinScaleWidget->setShowCurrentScaleButton( true );
376 mMaxScaleWidget->setMapCanvas( mMapCanvas );
377 mMaxScaleWidget->setShowCurrentScaleButton( true );
378
379 mGeometryGeneratorExpressionButton->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
380 mGeometryGeneratorExpressionButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mIconExpression.svg" ) ) );
381
382 const QStringList calloutTypes = QgsApplication::calloutRegistry()->calloutTypes();
383 for ( const QString &type : calloutTypes )
384 {
385 mCalloutStyleComboBox->addItem( QgsApplication::calloutRegistry()->calloutMetadata( type )->icon(), QgsApplication::calloutRegistry()->calloutMetadata( type )->visibleName(), type );
386 }
387
388 mGeometryGeneratorWarningLabel->setStyleSheet( QStringLiteral( "color: #FFC107;" ) );
389 mGeometryGeneratorWarningLabel->setTextInteractionFlags( Qt::TextBrowserInteraction );
390 connect( mGeometryGeneratorWarningLabel, &QLabel::linkActivated, this, [this]( const QString &link ) {
391 if ( link == QLatin1String( "#determineGeometryGeneratorType" ) )
392 determineGeometryGeneratorType();
393 } );
394
395 connect( mCalloutStyleComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsLabelingGui::calloutTypeChanged );
396
397 mLblNoObstacle1->installEventFilter( this );
398}
399
400void QgsLabelingGui::setLayer( QgsMapLayer *mapLayer )
401{
402 mPreviewFeature = QgsFeature();
403
404 if ( ( !mapLayer || mapLayer->type() != Qgis::LayerType::Vector ) && mGeomType == Qgis::GeometryType::Unknown )
405 {
406 setEnabled( false );
407 return;
408 }
409
410 setEnabled( true );
411
412 mLayer = mapLayer;
413 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( mapLayer );
414
415 mTextFormatsListWidget->setLayerType( vLayer ? vLayer->geometryType() : mGeomType );
416 mBackgroundMarkerSymbolButton->setLayer( vLayer );
417 mBackgroundFillSymbolButton->setLayer( vLayer );
418
419 // load labeling settings from layer
420 updateGeometryTypeBasedWidgets();
421
422 mFieldExpressionWidget->setLayer( mapLayer );
424 if ( mLayer )
425 da.setSourceCrs( mLayer->crs(), QgsProject::instance()->transformContext() );
426 da.setEllipsoid( QgsProject::instance()->ellipsoid() );
427 mFieldExpressionWidget->setGeomCalculator( da );
428
429 mFieldExpressionWidget->setEnabled( mMode == Labels || !mLayer );
430 mLabelingFrame->setEnabled( mMode == Labels || !mLayer );
431
432 blockInitSignals( true );
433
434 mGeometryGenerator->setText( mSettings.geometryGenerator );
435 mGeometryGeneratorGroupBox->setChecked( mSettings.geometryGeneratorEnabled );
436 if ( !mSettings.geometryGeneratorEnabled )
437 mGeometryGeneratorGroupBox->setCollapsed( true );
438 mGeometryGeneratorType->setCurrentIndex( mGeometryGeneratorType->findData( QVariant::fromValue( mSettings.geometryGeneratorType ) ) );
439
440 updateWidgetForFormat( mSettings.format().isValid() ? mSettings.format() : QgsStyle::defaultTextFormatForProject( QgsProject::instance(), QgsStyle::TextFormatContext::Labeling ) );
441
442 mFieldExpressionWidget->setRow( -1 );
443 mFieldExpressionWidget->setField( mSettings.fieldName );
444 mCheckBoxSubstituteText->setChecked( mSettings.useSubstitutions );
445 mSubstitutions = mSettings.substitutions;
446
447 // populate placement options
448 mCentroidRadioWhole->setChecked( mSettings.centroidWhole );
449 mCentroidInsideCheckBox->setChecked( mSettings.centroidInside );
450 mFitInsidePolygonCheckBox->setChecked( mSettings.fitInPolygonOnly );
451 mLineDistanceSpnBx->setValue( mSettings.dist );
452 mLineDistanceUnitWidget->setUnit( mSettings.distUnits );
453 mLineDistanceUnitWidget->setMapUnitScale( mSettings.distMapUnitScale );
454
455 mMaximumDistanceSpnBx->setValue( mSettings.pointSettings().maximumDistance() );
456 mMaximumDistanceUnitWidget->setUnit( mSettings.pointSettings().maximumDistanceUnit() );
457 mMaximumDistanceUnitWidget->setMapUnitScale( mSettings.pointSettings().maximumDistanceMapUnitScale() );
458
459 mOffsetTypeComboBox->setCurrentIndex( mOffsetTypeComboBox->findData( static_cast<int>( mSettings.offsetType ) ) );
460 mQuadrantBtnGrp->button( static_cast<int>( mSettings.pointSettings().quadrant() ) )->setChecked( true );
461 mPointOffsetXSpinBox->setValue( mSettings.xOffset );
462 mPointOffsetYSpinBox->setValue( mSettings.yOffset );
463 mPointOffsetUnitWidget->setUnit( mSettings.offsetUnits );
464 mPointOffsetUnitWidget->setMapUnitScale( mSettings.labelOffsetMapUnitScale );
465 mPointAngleSpinBox->setValue( mSettings.angleOffset );
466 chkLineAbove->setChecked( mSettings.lineSettings().placementFlags() & Qgis::LabelLinePlacementFlag::AboveLine );
467 chkLineBelow->setChecked( mSettings.lineSettings().placementFlags() & Qgis::LabelLinePlacementFlag::BelowLine );
468 chkLineOn->setChecked( mSettings.lineSettings().placementFlags() & Qgis::LabelLinePlacementFlag::OnLine );
469 chkLineOrientationDependent->setChecked( !( mSettings.lineSettings().placementFlags() & Qgis::LabelLinePlacementFlag::MapOrientation ) );
470
471 mCheckAllowLabelsOutsidePolygons->setChecked( mSettings.polygonPlacementFlags() & Qgis::LabelPolygonPlacementFlag::AllowPlacementOutsideOfPolygon );
472
473 const int placementIndex = mPlacementModeComboBox->findData( static_cast<int>( mSettings.placement ) );
474 if ( placementIndex >= 0 )
475 {
476 mPlacementModeComboBox->setCurrentIndex( placementIndex );
477 }
478 else
479 {
480 // use default placement for layer type
481 mPlacementModeComboBox->setCurrentIndex( 0 );
482 }
483
484 // Label repeat distance
485 mRepeatDistanceSpinBox->setValue( mSettings.repeatDistance );
486 mRepeatDistanceUnitWidget->setUnit( mSettings.repeatDistanceUnit );
487 mRepeatDistanceUnitWidget->setMapUnitScale( mSettings.repeatDistanceMapUnitScale );
488
489 mOverrunDistanceSpinBox->setValue( mSettings.lineSettings().overrunDistance() );
490 mOverrunDistanceUnitWidget->setUnit( mSettings.lineSettings().overrunDistanceUnit() );
491 mOverrunDistanceUnitWidget->setMapUnitScale( mSettings.lineSettings().overrunDistanceMapUnitScale() );
492
493 mThinningSettings = mSettings.thinningSettings();
494
495 mLabelMarginSpinBox->setValue( mThinningSettings.labelMarginDistance() );
496 mLabelMarginUnitWidget->setUnit( mThinningSettings.labelMarginDistanceUnit() );
497 mLabelMarginUnitWidget->setMapUnitScale( mThinningSettings.labelMarginDistanceMapUnitScale() );
498
499 mPrioritySlider->setValue( mSettings.priority );
500 mChkNoObstacle->setChecked( mSettings.obstacleSettings().isObstacle() );
501
502 mObstacleSettings = mSettings.obstacleSettings();
503
504 mChkNoDuplicates->setChecked( mThinningSettings.allowDuplicateRemoval() );
505
506 mLineSettings = mSettings.lineSettings();
507
508 chkLabelPerFeaturePart->setChecked( mSettings.labelPerPart );
509
510 mComboOverlapHandling->setCurrentIndex( mComboOverlapHandling->findData( static_cast<int>( mSettings.placementSettings().overlapHandling() ) ) );
511 mCheckAllowDegradedPlacement->setChecked( mSettings.placementSettings().allowDegradedPlacement() );
512 mPrioritizationComboBox->setCurrentIndex( mPrioritizationComboBox->findData( QVariant::fromValue( mSettings.placementSettings().prioritization() ) ) );
513
514 chkMergeLines->setChecked( mSettings.lineSettings().mergeLines() );
515 mMinSizeSpinBox->setValue( mThinningSettings.minimumFeatureSize() );
516 mLimitLabelChkBox->setChecked( mThinningSettings.limitNumberOfLabelsEnabled() );
517 mLimitLabelSpinBox->setValue( mThinningSettings.maximumNumberLabels() );
518
519 // direction symbol(s)
520 mDirectSymbChkBx->setChecked( mSettings.lineSettings().addDirectionSymbol() );
521 mDirectSymbLeftLineEdit->setText( mSettings.lineSettings().leftDirectionSymbol() );
522 mDirectSymbRightLineEdit->setText( mSettings.lineSettings().rightDirectionSymbol() );
523 mDirectSymbRevChkBx->setChecked( mSettings.lineSettings().reverseDirectionSymbol() );
524
525 mDirectSymbBtnGrp->button( static_cast<int>( mSettings.lineSettings().directionSymbolPlacement() ) )->setChecked( true );
526 mUpsidedownBtnGrp->button( static_cast<int>( mSettings.upsidedownLabels ) )->setChecked( true );
527
528 // curved label max character angles
529 mMaxCharAngleInDSpinBox->setValue( mSettings.maxCurvedCharAngleIn );
530 // lyr.maxCurvedCharAngleOut must be negative, but it is shown as positive spinbox in GUI
531 mMaxCharAngleOutDSpinBox->setValue( std::fabs( mSettings.maxCurvedCharAngleOut ) );
532
533 wrapCharacterEdit->setText( mSettings.wrapChar );
534 mAutoWrapLengthSpinBox->setValue( mSettings.autoWrapLength );
535 mAutoWrapTypeComboBox->setCurrentIndex( mSettings.useMaxLineLengthForAutoWrap ? 0 : 1 );
536
537 if ( mFontMultiLineAlignComboBox->findData( static_cast<int>( mSettings.multilineAlign ) ) != -1 )
538 {
539 mFontMultiLineAlignComboBox->setCurrentIndex( mFontMultiLineAlignComboBox->findData( static_cast<int>( mSettings.multilineAlign ) ) );
540 }
541 else
542 {
543 // the default pal layer settings for multiline alignment is to follow label placement, which isn't always available
544 // revert to left alignment in such case
545 mFontMultiLineAlignComboBox->setCurrentIndex( 0 );
546 }
547
548 chkPreserveRotation->setChecked( mSettings.preserveRotation );
549
550 mCoordRotationUnitComboBox->setCurrentIndex( 0 );
551 if ( mCoordRotationUnitComboBox->findData( static_cast<unsigned int>( mSettings.rotationUnit() ) ) >= 0 )
552 mCoordRotationUnitComboBox->setCurrentIndex( mCoordRotationUnitComboBox->findData( static_cast<unsigned int>( mSettings.rotationUnit() ) ) );
553
554 mScaleBasedVisibilityChkBx->setChecked( mSettings.scaleVisibility );
555 mMinScaleWidget->setScale( mSettings.minimumScale );
556 mMaxScaleWidget->setScale( mSettings.maximumScale );
557
558 mFormatNumChkBx->setChecked( mSettings.formatNumbers );
559 mFormatNumDecimalsSpnBx->setValue( mSettings.decimals );
560 mFormatNumPlusSignChkBx->setChecked( mSettings.plusSign );
561
562 // set pixel size limiting checked state before unit choice so limiting can be
563 // turned on as a default for map units, if minimum trigger value of 0 is used
564 mFontLimitPixelChkBox->setChecked( mSettings.fontLimitPixelSize );
565 mMinPixelLimit = mSettings.fontMinPixelSize; // ignored after first settings save
566 mFontMinPixelSpinBox->setValue( mSettings.fontMinPixelSize == 0 ? 3 : mSettings.fontMinPixelSize );
567 mFontMaxPixelSpinBox->setValue( mSettings.fontMaxPixelSize );
568
569 mZIndexSpinBox->setValue( mSettings.zIndex );
570
571 mDataDefinedProperties = mSettings.dataDefinedProperties();
572
573 // callout settings, to move to custom widget when multiple styles exist
574 if ( auto *lCallout = mSettings.callout() )
575 {
576 whileBlocking( mCalloutsDrawCheckBox )->setChecked( lCallout->enabled() );
577 whileBlocking( mCalloutStyleComboBox )->setCurrentIndex( mCalloutStyleComboBox->findData( lCallout->type() ) );
578 updateCalloutWidget( lCallout );
579 }
580 else
581 {
582 std::unique_ptr<QgsCallout> defaultCallout( QgsCalloutRegistry::defaultCallout() );
583 whileBlocking( mCalloutStyleComboBox )->setCurrentIndex( mCalloutStyleComboBox->findData( defaultCallout->type() ) );
584 whileBlocking( mCalloutsDrawCheckBox )->setChecked( false );
585 updateCalloutWidget( defaultCallout.get() );
586 }
587
588 updatePlacementWidgets();
589 updateLinePlacementOptions();
590
591 // needs to come before data defined setup, so connections work
592 blockInitSignals( false );
593
594 // set up data defined toolbuttons
595 // do this after other widgets are configured, so they can be enabled/disabled
596 populateDataDefinedButtons();
597
598 updateUi(); // should come after data defined button setup
599}
600
601void QgsLabelingGui::setSettings( const QgsPalLayerSettings &settings )
602{
603 mSettings = settings;
604 setLayer( mLayer );
605}
606
607void QgsLabelingGui::blockInitSignals( bool block )
608{
609 chkLineAbove->blockSignals( block );
610 chkLineBelow->blockSignals( block );
611 mPlacementModeComboBox->blockSignals( block );
612}
613
614void QgsLabelingGui::setLabelMode( LabelMode mode )
615{
616 mMode = mode;
617 mFieldExpressionWidget->setEnabled( mMode == Labels );
618 mLabelingFrame->setEnabled( mMode == Labels );
619}
620
621QgsPalLayerSettings QgsLabelingGui::layerSettings()
622{
624
625 // restore properties which aren't exposed in GUI
626 lyr.setUnplacedVisibility( mSettings.unplacedVisibility() );
627
628 lyr.drawLabels = ( mMode == Labels ) || !mLayer;
629
630 bool isExpression;
631 lyr.fieldName = mFieldExpressionWidget->currentField( &isExpression );
632 lyr.isExpression = isExpression;
633
634 lyr.dist = 0;
635
637 if ( mCheckAllowLabelsOutsidePolygons->isChecked() )
639 lyr.setPolygonPlacementFlags( polygonPlacementFlags );
640
641 lyr.centroidWhole = mCentroidRadioWhole->isChecked();
642 lyr.centroidInside = mCentroidInsideCheckBox->isChecked();
643 lyr.fitInPolygonOnly = mFitInsidePolygonCheckBox->isChecked();
644 lyr.dist = mLineDistanceSpnBx->value();
645 lyr.distUnits = mLineDistanceUnitWidget->unit();
646 lyr.distMapUnitScale = mLineDistanceUnitWidget->getMapUnitScale();
647
648 lyr.pointSettings().setMaximumDistance( mMaximumDistanceSpnBx->value() );
649 lyr.pointSettings().setMaximumDistanceUnit( mMaximumDistanceUnitWidget->unit() );
650 lyr.pointSettings().setMaximumDistanceMapUnitScale( mMaximumDistanceUnitWidget->getMapUnitScale() );
651
652 lyr.offsetType = static_cast<Qgis::LabelOffsetType>( mOffsetTypeComboBox->currentData().toInt() );
653 if ( mQuadrantBtnGrp )
654 {
655 lyr.pointSettings().setQuadrant( static_cast<Qgis::LabelQuadrantPosition>( mQuadrantBtnGrp->checkedId() ) );
656 }
657 lyr.xOffset = mPointOffsetXSpinBox->value();
658 lyr.yOffset = mPointOffsetYSpinBox->value();
659 lyr.offsetUnits = mPointOffsetUnitWidget->unit();
660 lyr.labelOffsetMapUnitScale = mPointOffsetUnitWidget->getMapUnitScale();
661 lyr.angleOffset = mPointAngleSpinBox->value();
662
664 if ( chkLineAbove->isChecked() )
665 linePlacementFlags |= Qgis::LabelLinePlacementFlag::AboveLine;
666 if ( chkLineBelow->isChecked() )
667 linePlacementFlags |= Qgis::LabelLinePlacementFlag::BelowLine;
668 if ( chkLineOn->isChecked() )
669 linePlacementFlags |= Qgis::LabelLinePlacementFlag::OnLine;
670 if ( !chkLineOrientationDependent->isChecked() )
672 lyr.lineSettings().setPlacementFlags( linePlacementFlags );
673
674 lyr.placement = static_cast<Qgis::LabelPlacement>( mPlacementModeComboBox->currentData().toInt() );
675
676 lyr.repeatDistance = mRepeatDistanceSpinBox->value();
677 lyr.repeatDistanceUnit = mRepeatDistanceUnitWidget->unit();
678 lyr.repeatDistanceMapUnitScale = mRepeatDistanceUnitWidget->getMapUnitScale();
679
680 lyr.lineSettings().setOverrunDistance( mOverrunDistanceSpinBox->value() );
681 lyr.lineSettings().setOverrunDistanceUnit( mOverrunDistanceUnitWidget->unit() );
682 lyr.lineSettings().setOverrunDistanceMapUnitScale( mOverrunDistanceUnitWidget->getMapUnitScale() );
683
684 mThinningSettings.setLabelMarginDistance( mLabelMarginSpinBox->value() );
685 mThinningSettings.setLabelMarginDistanceUnit( mLabelMarginUnitWidget->unit() );
686 mThinningSettings.setLabelMarginDistanceMapUnitScale( mLabelMarginUnitWidget->getMapUnitScale() );
687
688 lyr.priority = mPrioritySlider->value();
689
690 mObstacleSettings.setIsObstacle( mChkNoObstacle->isChecked() || mMode == ObstaclesOnly );
691 lyr.setObstacleSettings( mObstacleSettings );
692
693 lyr.lineSettings().setLineAnchorPercent( mLineSettings.lineAnchorPercent() );
694 lyr.lineSettings().setAnchorType( mLineSettings.anchorType() );
695 lyr.lineSettings().setAnchorClipping( mLineSettings.anchorClipping() );
696 lyr.lineSettings().setAnchorTextPoint( mLineSettings.anchorTextPoint() );
697
698 mThinningSettings.setAllowDuplicateRemoval( mChkNoDuplicates->isChecked() );
699
700 lyr.labelPerPart = chkLabelPerFeaturePart->isChecked();
701 lyr.placementSettings().setOverlapHandling( static_cast<Qgis::LabelOverlapHandling>( mComboOverlapHandling->currentData().toInt() ) );
702 lyr.placementSettings().setAllowDegradedPlacement( mCheckAllowDegradedPlacement->isChecked() );
703 lyr.placementSettings().setPrioritization( mPrioritizationComboBox->currentData().value<Qgis::LabelPrioritization>() );
704
705 lyr.lineSettings().setMergeLines( chkMergeLines->isChecked() );
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 {
842 {
843 QgsTextFormatWidget::setFormatFromStyle( name, type, stylePath );
844 return;
845 }
846
848 {
849 if ( !style->labelSettingsNames().contains( name ) )
850 return;
851
852 QgsPalLayerSettings settings = style->labelSettings( name );
853 if ( settings.fieldName.isEmpty() )
854 {
855 // if saved settings doesn't have a field name stored, retain the current one
856 bool isExpression;
857 settings.fieldName = mFieldExpressionWidget->currentField( &isExpression );
858 settings.isExpression = isExpression;
859 }
860 setSettings( settings );
861 break;
862 }
863 }
864}
865
866void QgsLabelingGui::setContext( const QgsSymbolWidgetContext &context )
867{
868 if ( QgsCalloutWidget *cw = qobject_cast<QgsCalloutWidget *>( mCalloutStackedWidget->currentWidget() ) )
869 {
870 cw->setContext( context );
871 }
873}
874
875void QgsLabelingGui::saveFormat()
876{
878 saveDlg.setDefaultTags( mTextFormatsListWidget->currentTagFilter() );
879 if ( !saveDlg.exec() )
880 return;
881
882 if ( saveDlg.name().isEmpty() )
883 return;
884
885 QgsStyle *style = saveDlg.destinationStyle();
886 if ( !style )
887 return;
888
889 switch ( saveDlg.selectedType() )
890 {
892 {
893 // check if there is no format with same name
894 if ( style->textFormatNames().contains( saveDlg.name() ) )
895 {
896 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 );
897 if ( res != QMessageBox::Yes )
898 {
899 return;
900 }
901 style->removeTextFormat( saveDlg.name() );
902 }
903 const QStringList symbolTags = saveDlg.tags().split( ',' );
904
905 const QgsTextFormat newFormat = format();
906 style->addTextFormat( saveDlg.name(), newFormat );
907 style->saveTextFormat( saveDlg.name(), newFormat, saveDlg.isFavorite(), symbolTags );
908 break;
909 }
910
912 {
913 // check if there is no settings with same name
914 if ( style->labelSettingsNames().contains( saveDlg.name() ) )
915 {
916 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 );
917 if ( res != QMessageBox::Yes )
918 {
919 return;
920 }
921 style->removeLabelSettings( saveDlg.name() );
922 }
923 const QStringList symbolTags = saveDlg.tags().split( ',' );
924
925 const QgsPalLayerSettings newSettings = layerSettings();
926 style->addLabelSettings( saveDlg.name(), newSettings );
927 style->saveLabelSettings( saveDlg.name(), newSettings, saveDlg.isFavorite(), symbolTags );
928 break;
929 }
930
937 break;
938 }
939}
940
941void QgsLabelingGui::updateGeometryTypeBasedWidgets()
942{
943 Qgis::GeometryType geometryType = mGeomType;
944
945 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( mLayer );
946
947 if ( mGeometryGeneratorGroupBox->isChecked() )
948 geometryType = mGeometryGeneratorType->currentData().value<Qgis::GeometryType>();
949 else if ( vLayer )
950 geometryType = vLayer->geometryType();
951
952 // show/hide options based upon geometry type
953 chkMergeLines->setVisible( geometryType == Qgis::GeometryType::Line );
954 mDirectSymbolsFrame->setVisible( geometryType == Qgis::GeometryType::Line );
955 mMinSizeFrame->setVisible( geometryType != Qgis::GeometryType::Point );
956 mPolygonFeatureOptionsFrame->setVisible( geometryType == Qgis::GeometryType::Polygon );
957
958
959 const Qgis::LabelPlacement prevPlacement = static_cast<Qgis::LabelPlacement>( mPlacementModeComboBox->currentData().toInt() );
960 mPlacementModeComboBox->clear();
961
962 switch ( geometryType )
963 {
965 mPlacementModeComboBox->addItem( tr( "Cartographic" ), static_cast<int>( Qgis::LabelPlacement::OrderedPositionsAroundPoint ) );
966 mPlacementModeComboBox->addItem( tr( "Around Point" ), static_cast<int>( Qgis::LabelPlacement::AroundPoint ) );
967 mPlacementModeComboBox->addItem( tr( "Offset from Point" ), static_cast<int>( Qgis::LabelPlacement::OverPoint ) );
968 break;
969
971 mPlacementModeComboBox->addItem( tr( "Parallel" ), static_cast<int>( Qgis::LabelPlacement::Line ) );
972 mPlacementModeComboBox->addItem( tr( "Curved" ), static_cast<int>( Qgis::LabelPlacement::Curved ) );
973 mPlacementModeComboBox->addItem( tr( "Horizontal" ), static_cast<int>( Qgis::LabelPlacement::Horizontal ) );
974 break;
975
977 mPlacementModeComboBox->addItem( tr( "Offset from Centroid" ), static_cast<int>( Qgis::LabelPlacement::OverPoint ) );
978 mPlacementModeComboBox->addItem( tr( "Around Centroid" ), static_cast<int>( Qgis::LabelPlacement::AroundPoint ) );
979 mPlacementModeComboBox->addItem( tr( "Horizontal" ), static_cast<int>( Qgis::LabelPlacement::Horizontal ) );
980 mPlacementModeComboBox->addItem( tr( "Free (Angled)" ), static_cast<int>( Qgis::LabelPlacement::Free ) );
981 mPlacementModeComboBox->addItem( tr( "Using Perimeter" ), static_cast<int>( Qgis::LabelPlacement::Line ) );
982 mPlacementModeComboBox->addItem( tr( "Using Perimeter (Curved)" ), static_cast<int>( Qgis::LabelPlacement::PerimeterCurved ) );
983 mPlacementModeComboBox->addItem( tr( "Outside Polygons" ), static_cast<int>( Qgis::LabelPlacement::OutsidePolygons ) );
984 break;
985
987 break;
989 qFatal( "unknown geometry type unexpected" );
990 }
991
992 if ( mPlacementModeComboBox->findData( static_cast<int>( prevPlacement ) ) != -1 )
993 {
994 mPlacementModeComboBox->setCurrentIndex( mPlacementModeComboBox->findData( static_cast<int>( prevPlacement ) ) );
995 }
996
997 if ( geometryType == Qgis::GeometryType::Point || geometryType == Qgis::GeometryType::Polygon )
998 {
999 // follow placement alignment is only valid for point or polygon layers
1000 if ( mFontMultiLineAlignComboBox->findData( static_cast<int>( Qgis::LabelMultiLineAlignment::FollowPlacement ) ) == -1 )
1001 mFontMultiLineAlignComboBox->addItem( tr( "Follow Label Placement" ), static_cast<int>( Qgis::LabelMultiLineAlignment::FollowPlacement ) );
1002 }
1003 else
1004 {
1005 const int idx = mFontMultiLineAlignComboBox->findData( static_cast<int>( Qgis::LabelMultiLineAlignment::FollowPlacement ) );
1006 if ( idx >= 0 )
1007 mFontMultiLineAlignComboBox->removeItem( idx );
1008 }
1009
1010 updatePlacementWidgets();
1011 updateLinePlacementOptions();
1012}
1013
1014void QgsLabelingGui::showGeometryGeneratorExpressionBuilder()
1015{
1016 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( mLayer );
1017 QgsExpressionBuilderDialog expressionBuilder( vLayer );
1018
1019 expressionBuilder.setExpressionText( mGeometryGenerator->text() );
1020 expressionBuilder.setExpressionContext( createExpressionContext() );
1021
1022 if ( expressionBuilder.exec() )
1023 {
1024 mGeometryGenerator->setText( expressionBuilder.expressionText() );
1025 }
1026}
1027
1028void QgsLabelingGui::validateGeometryGeneratorExpression()
1029{
1030 bool valid = true;
1031
1032 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( mLayer );
1033
1034 if ( mGeometryGeneratorGroupBox->isChecked() )
1035 {
1036 if ( !mPreviewFeature.isValid() && vLayer )
1037 vLayer->getFeatures( QgsFeatureRequest().setLimit( 1 ) ).nextFeature( mPreviewFeature );
1038
1039 QgsExpression expression( mGeometryGenerator->text() );
1040 QgsExpressionContext context = createExpressionContext();
1041 context.setFeature( mPreviewFeature );
1042
1043 expression.prepare( &context );
1044
1045 if ( expression.hasParserError() )
1046 {
1047 mGeometryGeneratorWarningLabel->setText( expression.parserErrorString() );
1048 valid = false;
1049 }
1050 else
1051 {
1052 const QVariant result = expression.evaluate( &context );
1053 const QgsGeometry geometry = result.value<QgsGeometry>();
1054 const Qgis::GeometryType configuredGeometryType = mGeometryGeneratorType->currentData().value<Qgis::GeometryType>();
1055 if ( geometry.isNull() )
1056 {
1057 mGeometryGeneratorWarningLabel->setText( tr( "Result of the expression is not a geometry" ) );
1058 valid = false;
1059 }
1060 else if ( geometry.type() != configuredGeometryType )
1061 {
1062 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() ) ) ) );
1063 valid = false;
1064 }
1065 }
1066 }
1067
1068 // The collapsible groupbox internally changes the visibility of this
1069 // Work around by setting the visibility deferred in the next event loop cycle.
1070 QTimer *timer = new QTimer();
1071 connect( timer, &QTimer::timeout, this, [this, valid]() {
1072 mGeometryGeneratorWarningLabel->setVisible( !valid );
1073 } );
1074 connect( timer, &QTimer::timeout, timer, &QTimer::deleteLater );
1075 timer->start( 0 );
1076}
1077
1078void QgsLabelingGui::determineGeometryGeneratorType()
1079{
1080 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( mLayer );
1081 if ( !mPreviewFeature.isValid() && vLayer )
1082 vLayer->getFeatures( QgsFeatureRequest().setLimit( 1 ) ).nextFeature( mPreviewFeature );
1083
1084 QgsExpression expression( mGeometryGenerator->text() );
1085 QgsExpressionContext context = createExpressionContext();
1086 context.setFeature( mPreviewFeature );
1087
1088 expression.prepare( &context );
1089 const QgsGeometry geometry = expression.evaluate( &context ).value<QgsGeometry>();
1090
1091 mGeometryGeneratorType->setCurrentIndex( mGeometryGeneratorType->findData( QVariant::fromValue( geometry.type() ) ) );
1092}
1093
1094void QgsLabelingGui::calloutTypeChanged()
1095{
1096 const QString newCalloutType = mCalloutStyleComboBox->currentData().toString();
1097 QgsCalloutWidget *pew = qobject_cast<QgsCalloutWidget *>( mCalloutStackedWidget->currentWidget() );
1098 if ( pew )
1099 {
1100 if ( pew->callout() && pew->callout()->type() == newCalloutType )
1101 return;
1102 }
1103
1104 // get creation function for new callout from registry
1106 QgsCalloutAbstractMetadata *am = registry->calloutMetadata( newCalloutType );
1107 if ( !am ) // check whether the metadata is assigned
1108 return;
1109
1110 // change callout to a new one (with different type)
1111 // base new callout on existing callout's properties
1112 const std::unique_ptr<QgsCallout> newCallout( am->createCallout( pew && pew->callout() ? pew->callout()->properties( QgsReadWriteContext() ) : QVariantMap(), QgsReadWriteContext() ) );
1113 if ( !newCallout )
1114 return;
1115
1116 updateCalloutWidget( newCallout.get() );
1117 updatePreview();
1118}
1119
1120
1121//
1122// QgsLabelSettingsDialog
1123//
1124
1125QgsLabelSettingsDialog::QgsLabelSettingsDialog( const QgsPalLayerSettings &settings, QgsVectorLayer *layer, QgsMapCanvas *mapCanvas, QWidget *parent, Qgis::GeometryType geomType )
1126 : QDialog( parent )
1127{
1128 QVBoxLayout *vLayout = new QVBoxLayout();
1129 mWidget = new QgsLabelingGui( layer, mapCanvas, settings, nullptr, geomType );
1130 vLayout->addWidget( mWidget );
1131 mButtonBox = new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::Ok, Qt::Horizontal );
1132 connect( mButtonBox, &QDialogButtonBox::accepted, this, &QDialog::accept );
1133 connect( mButtonBox, &QDialogButtonBox::rejected, this, &QDialog::reject );
1134 connect( mButtonBox, &QDialogButtonBox::helpRequested, this, &QgsLabelSettingsDialog::showHelp );
1135 vLayout->addWidget( mButtonBox );
1136 setLayout( vLayout );
1137 setWindowTitle( tr( "Label Settings" ) );
1138}
1139
1140QDialogButtonBox *QgsLabelSettingsDialog::buttonBox() const
1141{
1142 return mButtonBox;
1143}
1144
1145void QgsLabelSettingsDialog::showHelp()
1146{
1147 QgsHelp::openHelp( QStringLiteral( "style_library/label_settings.html" ) );
1148}
1149
1150
Provides global constants and enumerations for use throughout the application.
Definition qgis.h:54
@ BelowLine
Labels can be placed below a line feature. Unless MapOrientation is also specified this mode respects...
@ MapOrientation
Signifies that the AboveLine and BelowLine flags should respect the map's orientation rather than the...
@ OnLine
Labels can be placed directly over a line feature.
@ AboveLine
Labels can be placed above a line feature. Unless MapOrientation is also specified this mode respects...
AngleUnit
Units of angles.
Definition qgis.h:4969
@ SecondsOfArc
Seconds of arc.
@ Radians
Square kilometers.
@ Turn
Turn/revolutions.
@ MinutesOfArc
Minutes of arc.
@ MilliradiansSI
Angular milliradians (SI definition, 1/1000 of radian)
@ Degrees
Degrees.
@ Gon
Gon/gradian.
@ MilNATO
Angular mil (NATO definition, 6400 mil = 2PI radians)
LabelOffsetType
Behavior modifier for label offset and distance, only applies in some label placement modes.
Definition qgis.h:1205
LabelPrioritization
Label prioritization.
Definition qgis.h:1144
LabelPlacement
Placement modes which determine how label candidates are generated for a feature.
Definition qgis.h:1158
@ OverPoint
Arranges candidates over a point (or centroid of a polygon), or at a preset offset from the point....
@ Curved
Arranges candidates following the curvature of a line feature. Applies to line layers only.
@ AroundPoint
Arranges candidates in a circle around a point (or centroid of a polygon). Applies to point or polygo...
@ Line
Arranges candidates parallel to a generalised line representing the feature or parallel to a polygon'...
@ Free
Arranges candidates scattered throughout a polygon feature. Candidates are rotated to respect the pol...
@ OrderedPositionsAroundPoint
Candidates are placed in predefined positions around a point. Preference is given to positions with g...
@ Horizontal
Arranges horizontal candidates scattered throughout a polygon feature. Applies to polygon layers only...
@ PerimeterCurved
Arranges candidates following the curvature of a polygon's boundary. Applies to polygon layers only.
@ OutsidePolygons
Candidates are placed outside of polygon boundaries. Applies to polygon layers only.
@ AllowPlacementInsideOfPolygon
Labels can be placed inside a polygon feature.
@ AllowPlacementOutsideOfPolygon
Labels can be placed outside of a polygon feature.
QFlags< LabelLinePlacementFlag > LabelLinePlacementFlags
Line placement flags, which control how candidates are generated for a linear feature.
Definition qgis.h:1254
QFlags< LabelPolygonPlacementFlag > LabelPolygonPlacementFlags
Polygon placement flags, which control how candidates are generated for a polygon feature.
Definition qgis.h:1276
LabelQuadrantPosition
Label quadrant positions.
Definition qgis.h:1219
GeometryType
The geometry types are used to group Qgis::WkbType in a coarse way.
Definition qgis.h:337
@ Polygon
Polygons.
@ Unknown
Unknown types.
@ Null
No geometry.
LabelMultiLineAlignment
Text alignment for multi-line labels.
Definition qgis.h:1302
@ FollowPlacement
Alignment follows placement of label, e.g., labels to the left of a feature will be drawn with right ...
@ Vector
Vector layer.
@ Mesh
Mesh layer. Added in QGIS 3.2.
LabelOverlapHandling
Label overlap handling.
Definition qgis.h:1131
UpsideDownLabelHandling
Handling techniques for upside down labels.
Definition qgis.h:1287
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.
Stores metadata about one callout renderer class.
virtual QgsCallout * createCallout(const QVariantMap &properties, const QgsReadWriteContext &context)=0
Create a callout of this type given the map of properties.
Registry of available callout classes.
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.
Base class for widgets which allow control over the properties of callouts.
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:54
void setEnabled(bool enabled)
Sets whether the callout is enabled.
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.
A general purpose distance and area calculator, capable of performing ellipsoid based calculations.
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.
A generic dialog for building expression strings.
Single scope for storing variables and functions for use within a QgsExpressionContext.
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.
Handles parsing and evaluation of expressions (formerly called "search strings").
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
Wraps a request for features to a vector layer (or directly its vector data provider).
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:58
A geometry is the spatial representation of a feature.
Qgis::GeometryType type
static void initCalloutWidgets()
Initializes callout widgets.
Definition qgsgui.cpp:501
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition qgshelp.cpp:39
A widget for customising label line anchor settings.
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.
Contains settings related to how the label engine places and formats labels for line features (or pol...
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...
A widget for customising label obstacle settings.
void setGeometryType(Qgis::GeometryType type) override
Sets the geometry type of the features to customize the widget accordingly.
QgsLabelObstacleSettings settings() const
Returns the obstacle settings defined by the widget.
void updateDataDefinedProperties(QgsPropertyCollection &properties) override
Updates a data defined properties collection, correctly setting the values for any properties related...
void setSettings(const QgsLabelObstacleSettings &settings)
Sets the obstacle settings to show in the widget.
void 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.
A widget for customising label duplicate removal settings.
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.
A blocking dialog containing a QgsLabelSettingsWidgetBase.
Map canvas is a class for displaying all GIS data types on a canvas.
Base class for all map layer types.
Definition qgsmaplayer.h:77
Qgis::LayerType type
Definition qgsmaplayer.h:87
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.
Base class for any widget that can be shown as an inline panel.
void openPanel(QgsPanelWidget *panel)
Open a panel or dialog depending on dock mode setting If dock mode is true this method will emit the ...
static QgsPanelWidget * findParentPanel(QWidget *widget)
Traces through the parents of a widget to find if it is contained within a QgsPanelWidget widget.
bool dockMode()
Returns the dock mode state.
QgsStyle * styleAtPath(const QString &path)
Returns a reference to the style database associated with the project with matching file path.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition qgsproject.h:107
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:113
A grouped map of multiple QgsProperty objects, each referenced by an integer key value.
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.
A container for the context for various read/write operations on objects.
@ CurrentPageOnly
Only the size of the current page is considered when calculating the stacked widget size.
A dialog for setting properties of a newly saved style.
A database of saved style entities, including symbols, color ramps, text formats and others.
Definition qgsstyle.h:88
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:146
QStringList labelSettingsNames() const
Returns a list of names of label settings in the style.
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:370
QgsPalLayerSettings labelSettings(const QString &name) const
Returns the label settings with the specified name.
bool saveTextFormat(const QString &name, const QgsTextFormat &format, bool favorite, const QStringList &tags)
Adds a text format to the database.
Definition qgsstyle.cpp:974
bool addLabelSettings(const QString &name, const QgsPalLayerSettings &settings, bool update=false)
Adds label settings with the specified name to the style.
Definition qgsstyle.cpp:391
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.
Container for all settings relating to text rendering.
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 QString geometryDisplayString(Qgis::GeometryType type)
Returns a display string for a geometry type.
@ Unknown
Unknown/invalid format.
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition qgis.h:6191