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