QGIS API Documentation  3.24.2-Tisler (13c1a02865)
qgstextformatwidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgstextformatwidget.h
3  ---------------------
4  begin : June 2009
5  copyright : (C) Martin Dobias
6  email : wonder dot sk at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgstextformatwidget.h"
17 #include "qgsmapcanvas.h"
19 #include "qgslogger.h"
20 #include "qgsfontutils.h"
21 #include "qgssymbollayerutils.h"
22 #include "qgssvgcache.h"
23 #include "qgssvgselectorwidget.h"
25 #include "qgspallabeling.h" // for enum values
26 #include "qgspathresolver.h"
27 #include "qgsproject.h"
28 #include "qgssettings.h"
29 #include "qgseffectstack.h"
30 #include "qgspainteffectregistry.h"
31 #include "qgsstylesavedialog.h"
33 #include "qgsgui.h"
34 #include "qgsvectorlayer.h"
35 #include "qgsauxiliarystorage.h"
37 #include "qgshelp.h"
38 #include "qgsmarkersymbol.h"
39 #include "qgsfillsymbol.h"
40 #include "qgsiconutils.h"
42 #include "qgsconfig.h"
43 
44 #include <QButtonGroup>
45 #include <QMessageBox>
46 
47 QgsTextFormatWidget::QgsTextFormatWidget( const QgsTextFormat &format, QgsMapCanvas *mapCanvas, QWidget *parent, QgsVectorLayer *layer )
48  : QWidget( parent )
49  , mMapCanvas( mapCanvas )
50  , mLayer( layer )
51 {
52  initWidget();
53  setWidgetMode( Text );
56 }
57 
58 QgsTextFormatWidget::QgsTextFormatWidget( QgsMapCanvas *mapCanvas, QWidget *parent, Mode mode, QgsVectorLayer *layer )
59  : QWidget( parent )
60  , mMapCanvas( mapCanvas )
61  , mLayer( layer )
62  , mWidgetMode( mode )
63 {
64  initWidget();
65  if ( mode == Text )
67  setWidgetMode( mode );
68 }
69 
70 void QgsTextFormatWidget::initWidget()
71 {
72  setupUi( this );
73 
74  mGeometryGeneratorGroupBox->setCollapsed( true );
75 
76  connect( mShapeSVGPathLineEdit, &QLineEdit::textChanged, this, &QgsTextFormatWidget::mShapeSVGPathLineEdit_textChanged );
77  connect( mFontSizeSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsTextFormatWidget::mFontSizeSpinBox_valueChanged );
78  connect( mFontFamilyCmbBx, &QFontComboBox::currentFontChanged, this, &QgsTextFormatWidget::mFontFamilyCmbBx_currentFontChanged );
79  connect( mFontStyleComboBox, &QComboBox::currentTextChanged, this, &QgsTextFormatWidget::mFontStyleComboBox_currentIndexChanged );
80  connect( mFontUnderlineBtn, &QToolButton::toggled, this, &QgsTextFormatWidget::mFontUnderlineBtn_toggled );
81  connect( mFontStrikethroughBtn, &QToolButton::toggled, this, &QgsTextFormatWidget::mFontStrikethroughBtn_toggled );
82  connect( mFontWordSpacingSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsTextFormatWidget::mFontWordSpacingSpinBox_valueChanged );
83  connect( mFontLetterSpacingSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsTextFormatWidget::mFontLetterSpacingSpinBox_valueChanged );
84  connect( mFontSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsTextFormatWidget::mFontSizeUnitWidget_changed );
85  connect( mFontMinPixelSpinBox, static_cast < void ( QSpinBox::* )( int ) > ( &QSpinBox::valueChanged ), this, &QgsTextFormatWidget::mFontMinPixelSpinBox_valueChanged );
86  connect( mFontMaxPixelSpinBox, static_cast < void ( QSpinBox::* )( int ) > ( &QSpinBox::valueChanged ), this, &QgsTextFormatWidget::mFontMaxPixelSpinBox_valueChanged );
87  connect( mBufferUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsTextFormatWidget::mBufferUnitWidget_changed );
88  connect( mMaskBufferUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsTextFormatWidget::mMaskBufferUnitWidget_changed );
89  connect( mCoordXDDBtn, &QgsPropertyOverrideButton::changed, this, &QgsTextFormatWidget::mCoordXDDBtn_changed );
90  connect( mCoordXDDBtn, &QgsPropertyOverrideButton::activated, this, &QgsTextFormatWidget::mCoordXDDBtn_activated );
91  connect( mCoordYDDBtn, &QgsPropertyOverrideButton::changed, this, &QgsTextFormatWidget::mCoordYDDBtn_changed );
92  connect( mCoordYDDBtn, &QgsPropertyOverrideButton::activated, this, &QgsTextFormatWidget::mCoordYDDBtn_activated );
93  connect( mCoordPointDDBtn, &QgsPropertyOverrideButton::changed, this, &QgsTextFormatWidget::mCoordPointDDBtn_changed );
94  connect( mCoordPointDDBtn, &QgsPropertyOverrideButton::activated, this, &QgsTextFormatWidget::mCoordPointDDBtn_activated );
95  connect( mShapeTypeCmbBx, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsTextFormatWidget::mShapeTypeCmbBx_currentIndexChanged );
96  connect( mShapeRotationCmbBx, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsTextFormatWidget::mShapeRotationCmbBx_currentIndexChanged );
97  connect( mShapeSVGParamsBtn, &QPushButton::clicked, this, &QgsTextFormatWidget::mShapeSVGParamsBtn_clicked );
98  connect( mShapeSVGSelectorBtn, &QPushButton::clicked, this, &QgsTextFormatWidget::mShapeSVGSelectorBtn_clicked );
99  connect( mPreviewTextEdit, &QLineEdit::textChanged, this, &QgsTextFormatWidget::mPreviewTextEdit_textChanged );
100  connect( mPreviewTextBtn, &QToolButton::clicked, this, &QgsTextFormatWidget::mPreviewTextBtn_clicked );
101  connect( mPreviewBackgroundBtn, &QgsColorButton::colorChanged, this, &QgsTextFormatWidget::mPreviewBackgroundBtn_colorChanged );
102  connect( mDirectSymbLeftToolBtn, &QToolButton::clicked, this, &QgsTextFormatWidget::mDirectSymbLeftToolBtn_clicked );
103  connect( mDirectSymbRightToolBtn, &QToolButton::clicked, this, &QgsTextFormatWidget::mDirectSymbRightToolBtn_clicked );
104  connect( chkLineOrientationDependent, &QCheckBox::toggled, this, &QgsTextFormatWidget::chkLineOrientationDependent_toggled );
105  connect( mToolButtonConfigureSubstitutes, &QToolButton::clicked, this, &QgsTextFormatWidget::mToolButtonConfigureSubstitutes_clicked );
106  connect( mKerningCheckBox, &QCheckBox::toggled, this, &QgsTextFormatWidget::kerningToggled );
107 
108  const int iconSize = QgsGuiUtils::scaleIconSize( 20 );
109  mOptionsTab->setIconSize( QSize( iconSize, iconSize ) );
110  mLabelingOptionsListWidget->setIconSize( QSize( iconSize, iconSize ) ) ;
111  const int iconSize32 = QgsGuiUtils::scaleIconSize( 32 );
112  const int iconSize24 = QgsGuiUtils::scaleIconSize( 24 );
113  const int iconSize18 = QgsGuiUtils::scaleIconSize( 18 );
114  const int iconSize16 = QgsGuiUtils::scaleIconSize( 16 );
115 
116  mPreviewTextBtn->setIconSize( QSize( iconSize16, iconSize16 ) );
117  mPointOffsetAboveLeft->setIconSize( QSize( iconSize32, iconSize18 ) );
118  mPointOffsetAbove->setIconSize( QSize( iconSize32, iconSize18 ) );
119  mPointOffsetAboveRight->setIconSize( QSize( iconSize32, iconSize18 ) );
120  mPointOffsetLeft->setIconSize( QSize( iconSize32, iconSize18 ) );
121  mPointOffsetOver ->setIconSize( QSize( iconSize32, iconSize18 ) );
122  mPointOffsetRight->setIconSize( QSize( iconSize32, iconSize18 ) );
123  mPointOffsetBelowLeft->setIconSize( QSize( iconSize32, iconSize18 ) );
124  mPointOffsetBelow->setIconSize( QSize( iconSize32, iconSize18 ) );
125  mPointOffsetBelowRight->setIconSize( QSize( iconSize32, iconSize18 ) );
126  mLabelMinScale->setPixmap( QgsApplication::getThemeIcon( QStringLiteral( "/mActionZoomOut.svg" ) ).pixmap( QSize( iconSize24, iconSize24 ) ) );
127  mLabelMaxScale->setPixmap( QgsApplication::getThemeIcon( QStringLiteral( "/mActionZoomIn.svg" ) ).pixmap( QSize( iconSize24, iconSize24 ) ) );
128 
129  const int buttonSize = QgsGuiUtils::scaleIconSize( 24 );
130  mFontUnderlineBtn->setMinimumSize( buttonSize, buttonSize );
131  mFontUnderlineBtn->setMaximumSize( buttonSize, buttonSize );
132  mFontStrikethroughBtn->setMinimumSize( buttonSize, buttonSize );
133  mFontStrikethroughBtn->setMaximumSize( buttonSize, buttonSize );
134  mFontBoldBtn->setMinimumSize( buttonSize, buttonSize );
135  mFontBoldBtn->setMaximumSize( buttonSize, buttonSize );
136  mFontItalicBtn->setMinimumSize( buttonSize, buttonSize );
137  mFontItalicBtn->setMaximumSize( buttonSize, buttonSize );
138 
139  mPreviewScaleComboBox->setMapCanvas( mMapCanvas );
140  mPreviewScaleComboBox->setShowCurrentScaleButton( true );
141  connect( mPreviewScaleComboBox, &QgsScaleWidget::scaleChanged, this, &QgsTextFormatWidget::previewScaleChanged );
142 
143  const auto unitWidgets = findChildren<QgsUnitSelectionWidget *>();
144  for ( QgsUnitSelectionWidget *unitWidget : unitWidgets )
145  {
146  unitWidget->setMapCanvas( mMapCanvas );
147  }
175  mFontLineHeightSpinBox->setClearValue( 1.0 );
176  mShapeRotationDblSpnBx->setClearValue( 0.0 );
177  mShapeOffsetXSpnBx->setClearValue( 0.0 );
178  mShapeOffsetYSpnBx->setClearValue( 0.0 );
179  mPointOffsetXSpinBox->setClearValue( 0.0 );
180  mPointOffsetYSpinBox->setClearValue( 0.0 );
181  mPointAngleSpinBox->setClearValue( 0.0 );
182  mFontLetterSpacingSpinBox->setClearValue( 0.0 );
183  mFontWordSpacingSpinBox->setClearValue( 0.0 );
184  mZIndexSpinBox->setClearValue( 0.0 );
185  mLineDistanceSpnBx->setClearValue( 0.0 );
186  mSpinStretch->setClearValue( 100 );
187 
188  mOffsetTypeComboBox->addItem( tr( "From Point" ), QgsPalLayerSettings::FromPoint );
189  mOffsetTypeComboBox->addItem( tr( "From Symbol Bounds" ), QgsPalLayerSettings::FromSymbolBounds );
190 
191  mShapeTypeCmbBx->addItem( tr( "Rectangle" ), QgsTextBackgroundSettings::ShapeRectangle );
192  mShapeTypeCmbBx->addItem( tr( "Square" ), QgsTextBackgroundSettings::ShapeSquare );
193  mShapeTypeCmbBx->addItem( tr( "Ellipse" ), QgsTextBackgroundSettings::ShapeEllipse );
194  mShapeTypeCmbBx->addItem( tr( "Circle" ), QgsTextBackgroundSettings::ShapeCircle );
195  mShapeTypeCmbBx->addItem( tr( "SVG" ), QgsTextBackgroundSettings::ShapeSVG );
196  mShapeTypeCmbBx->addItem( tr( "Marker Symbol" ), QgsTextBackgroundSettings::ShapeMarkerSymbol );
197 
198  updateAvailableShadowPositions();
199 
200  mBackgroundMarkerSymbolButton->setSymbolType( Qgis::SymbolType::Marker );
201  mBackgroundMarkerSymbolButton->setDialogTitle( tr( "Background Symbol" ) );
202  mBackgroundMarkerSymbolButton->registerExpressionContextGenerator( this );
203  mBackgroundMarkerSymbolButton->setMapCanvas( mMapCanvas );
204  mBackgroundFillSymbolButton->setSymbolType( Qgis::SymbolType::Fill );
205  mBackgroundFillSymbolButton->setDialogTitle( tr( "Background Symbol" ) );
206  mBackgroundFillSymbolButton->registerExpressionContextGenerator( this );
207  mBackgroundFillSymbolButton->setMapCanvas( mMapCanvas );
208 
209  mCharDlg = new QgsCharacterSelectorDialog( this );
210 
211  mRefFont = lblFontPreview->font();
212 
213  // internal connections
214  connect( mShadowOffsetAngleDial, &QAbstractSlider::valueChanged, mShadowOffsetAngleSpnBx, &QSpinBox::setValue );
215  connect( mShadowOffsetAngleSpnBx, static_cast < void ( QSpinBox::* )( int ) > ( &QSpinBox::valueChanged ), mShadowOffsetAngleDial, &QAbstractSlider::setValue );
216  connect( mLimitLabelChkBox, &QAbstractButton::toggled, mLimitLabelSpinBox, &QWidget::setEnabled );
217  connect( mCheckBoxSubstituteText, &QAbstractButton::toggled, mToolButtonConfigureSubstitutes, &QWidget::setEnabled );
218 
219  //connections to prevent users removing all line placement positions
220  connect( chkLineAbove, &QAbstractButton::toggled, this, &QgsTextFormatWidget::updateLinePlacementOptions );
221  connect( chkLineBelow, &QAbstractButton::toggled, this, &QgsTextFormatWidget::updateLinePlacementOptions );
222  connect( chkLineOn, &QAbstractButton::toggled, this, &QgsTextFormatWidget::updateLinePlacementOptions );
223 
224  mTextOrientationComboBox->addItem( tr( "Horizontal" ), QgsTextFormat::HorizontalOrientation );
225  mTextOrientationComboBox->addItem( tr( "Vertical" ), QgsTextFormat::VerticalOrientation );
226 
227  populateFontCapitalsComboBox();
228 
229  // color buttons
230  mPreviewBackgroundBtn->setColorDialogTitle( tr( "Select Fill Color" ) );
231  mPreviewBackgroundBtn->setContext( QStringLiteral( "labeling" ) );
232  mPreviewBackgroundBtn->setColor( QColor( 255, 255, 255 ) );
233  btnTextColor->setColorDialogTitle( tr( "Select Text Color" ) );
234  btnTextColor->setContext( QStringLiteral( "labeling" ) );
235  btnTextColor->setDefaultColor( Qt::black );
236  btnBufferColor->setColorDialogTitle( tr( "Select Buffer Color" ) );
237  btnBufferColor->setContext( QStringLiteral( "labeling" ) );
238  btnBufferColor->setDefaultColor( Qt::white );
239  mShapeStrokeColorBtn->setColorDialogTitle( tr( "Select Stroke Color" ) );
240  mShapeStrokeColorBtn->setContext( QStringLiteral( "labeling" ) );
241  mShapeFillColorBtn->setColorDialogTitle( tr( "Select Fill Color" ) );
242  mShapeFillColorBtn->setContext( QStringLiteral( "labeling" ) );
243  mShadowColorBtn->setColorDialogTitle( tr( "Select Shadow Color" ) );
244  mShadowColorBtn->setContext( QStringLiteral( "labeling" ) );
245  mShadowColorBtn->setDefaultColor( Qt::black );
246 
247  mFontColorDDBtn->registerLinkedWidget( btnTextColor );
248  mBufferColorDDBtn->registerLinkedWidget( btnBufferColor );
249  mShapeStrokeColorDDBtn->registerLinkedWidget( mShapeStrokeColorBtn );
250  mShapeFillColorDDBtn->registerLinkedWidget( mShapeFillColorBtn );
251  mShadowColorDDBtn->registerLinkedWidget( mShadowColorBtn );
252 
253  // set up quadrant offset button group
254  mQuadrantBtnGrp = new QButtonGroup( this );
255  mQuadrantBtnGrp->addButton( mPointOffsetAboveLeft, static_cast<int>( QgsPalLayerSettings::QuadrantAboveLeft ) );
256  mQuadrantBtnGrp->addButton( mPointOffsetAbove, static_cast<int>( QgsPalLayerSettings::QuadrantAbove ) );
257  mQuadrantBtnGrp->addButton( mPointOffsetAboveRight, static_cast<int>( QgsPalLayerSettings::QuadrantAboveRight ) );
258  mQuadrantBtnGrp->addButton( mPointOffsetLeft, static_cast<int>( QgsPalLayerSettings::QuadrantLeft ) );
259  mQuadrantBtnGrp->addButton( mPointOffsetOver, static_cast<int>( QgsPalLayerSettings::QuadrantOver ) );
260  mQuadrantBtnGrp->addButton( mPointOffsetRight, static_cast<int>( QgsPalLayerSettings::QuadrantRight ) );
261  mQuadrantBtnGrp->addButton( mPointOffsetBelowLeft, static_cast<int>( QgsPalLayerSettings::QuadrantBelowLeft ) );
262  mQuadrantBtnGrp->addButton( mPointOffsetBelow, static_cast<int>( QgsPalLayerSettings::QuadrantBelow ) );
263  mQuadrantBtnGrp->addButton( mPointOffsetBelowRight, static_cast<int>( QgsPalLayerSettings::QuadrantBelowRight ) );
264  mQuadrantBtnGrp->setExclusive( true );
265 
266  // setup direction symbol(s) button group
267  mDirectSymbBtnGrp = new QButtonGroup( this );
268  mDirectSymbBtnGrp->addButton( mDirectSymbRadioBtnLR, static_cast<int>( QgsLabelLineSettings::DirectionSymbolPlacement::SymbolLeftRight ) );
269  mDirectSymbBtnGrp->addButton( mDirectSymbRadioBtnAbove, static_cast<int>( QgsLabelLineSettings::DirectionSymbolPlacement::SymbolAbove ) );
270  mDirectSymbBtnGrp->addButton( mDirectSymbRadioBtnBelow, static_cast<int>( QgsLabelLineSettings::DirectionSymbolPlacement::SymbolBelow ) );
271  mDirectSymbBtnGrp->setExclusive( true );
272 
273  // upside-down labels button group
274  mUpsidedownBtnGrp = new QButtonGroup( this );
275  mUpsidedownBtnGrp->addButton( mUpsidedownRadioOff, static_cast<int>( QgsPalLayerSettings::Upright ) );
276  mUpsidedownBtnGrp->addButton( mUpsidedownRadioDefined, static_cast<int>( QgsPalLayerSettings::ShowDefined ) );
277  mUpsidedownBtnGrp->addButton( mUpsidedownRadioAll, static_cast<int>( QgsPalLayerSettings::ShowAll ) );
278  mUpsidedownBtnGrp->setExclusive( true );
279 
280  //mShapeCollisionsChkBx->setVisible( false ); // until implemented
281 
282  // post updatePlacementWidgets() connections
283  connect( chkLineAbove, &QAbstractButton::toggled, this, &QgsTextFormatWidget::updatePlacementWidgets );
284  connect( chkLineBelow, &QAbstractButton::toggled, this, &QgsTextFormatWidget::updatePlacementWidgets );
285  connect( mCheckAllowLabelsOutsidePolygons, &QAbstractButton::toggled, this, &QgsTextFormatWidget::updatePlacementWidgets );
286  connect( mAllowOutsidePolygonsDDBtn, &QgsPropertyOverrideButton::changed, this, &QgsTextFormatWidget::updatePlacementWidgets );
287 
288  connect( mPlacementModeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsTextFormatWidget::updatePlacementWidgets );
289 
290  // Global settings group for groupboxes' saved/restored collapsed state
291  // maintains state across different dialogs
292  const auto groupBoxes = findChildren<QgsCollapsibleGroupBox *>();
293  for ( QgsCollapsibleGroupBox *grpbox : groupBoxes )
294  {
295  grpbox->setSettingGroup( QStringLiteral( "mAdvLabelingDlg" ) );
296  }
297 
298  connect( groupBox_mPreview, &QgsCollapsibleGroupBoxBasic::collapsedStateChanged, this, &QgsTextFormatWidget::collapseSample );
299 
300  // get rid of annoying outer focus rect on Mac
301  mLabelingOptionsListWidget->setAttribute( Qt::WA_MacShowFocusRect, false );
302 
303  const QgsSettings settings;
304 
305  // reset horiz stretch of left side of options splitter (set to 1 for previewing in Qt Designer)
306  QSizePolicy policy( mLabelingOptionsListFrame->sizePolicy() );
307  policy.setHorizontalStretch( 0 );
308  mLabelingOptionsListFrame->setSizePolicy( policy );
309  if ( !settings.contains( QStringLiteral( "/Windows/Labeling/OptionsSplitState" ) ) )
310  {
311  // set left list widget width on initial showing
312  QList<int> splitsizes;
313  splitsizes << 115;
314  mLabelingOptionsSplitter->setSizes( splitsizes );
315  }
316 
317  // set up reverse connection from stack to list
318  connect( mLabelStackedWidget, &QStackedWidget::currentChanged, this, &QgsTextFormatWidget::optionsStackedWidget_CurrentChanged );
319 
320  // restore dialog, splitters and current tab
321  mFontPreviewSplitter->restoreState( settings.value( QStringLiteral( "Windows/Labeling/FontPreviewSplitState" ) ).toByteArray() );
322  mLabelingOptionsSplitter->restoreState( settings.value( QStringLiteral( "Windows/Labeling/OptionsSplitState" ) ).toByteArray() );
323 
324  mLabelingOptionsListWidget->setCurrentRow( settings.value( QStringLiteral( "Windows/Labeling/Tab" ), 0 ).toInt() );
325 
326  mBufferEffect.reset( QgsPaintEffectRegistry::defaultStack() );
327  connect( mBufferEffectWidget, &QgsEffectStackCompactWidget::changed, this, &QgsTextFormatWidget::updatePreview );
328  mBufferEffectWidget->setPaintEffect( mBufferEffect.get() );
329 
330  mMaskEffect.reset( QgsPaintEffectRegistry::defaultStack() );
331  connect( mMaskEffectWidget, &QgsEffectStackCompactWidget::changed, this, &QgsTextFormatWidget::updatePreview );
332  mMaskEffectWidget->setPaintEffect( mMaskEffect.get() );
333 
334  mBackgroundEffect.reset( QgsPaintEffectRegistry::defaultStack() );
335  connect( mBackgroundEffectWidget, &QgsEffectStackCompactWidget::changed, this, &QgsTextFormatWidget::updatePreview );
336  mBackgroundEffectWidget->setPaintEffect( mBackgroundEffect.get() );
337 
338 #ifndef HAS_KDE_QT5_FONT_STRETCH_FIX
339  mLabelStretch->hide();
340  mSpinStretch->hide();
341  mFontStretchDDBtn->hide();
342 #endif
343 
344  setDockMode( false );
345 
346  QList<QWidget *> widgets;
347  widgets << btnBufferColor
348  << btnTextColor
349  << chkLabelPerFeaturePart
350  << chkLineAbove
351  << chkLineBelow
352  << chkLineOn
353  << chkLineOrientationDependent
354  << chkMergeLines
355  << chkPreserveRotation
356  << comboBlendMode
357  << comboBufferBlendMode
358  << mBufferDrawChkBx
359  << mBufferJoinStyleComboBox
360  << mBufferTranspFillChbx
361  << mBufferOpacityWidget
362  << mCentroidInsideCheckBox
363  << mChkNoObstacle
364  << mCoordRotationUnitComboBox
365  << mDirectSymbChkBx
366  << mDirectSymbLeftLineEdit
367  << mDirectSymbRevChkBx
368  << mDirectSymbRightLineEdit
369  << mFitInsidePolygonCheckBox
370  << mFontCapitalsComboBox
371  << mFontLetterSpacingSpinBox
372  << mFontLimitPixelChkBox
373  << mFontLineHeightSpinBox
374  << mFontMaxPixelSpinBox
375  << mFontMinPixelSpinBox
376  << mFontMultiLineAlignComboBox
377  << mFontSizeSpinBox
378  << mFontStyleComboBox
379  << mTextOrientationComboBox
380  << mTextOpacityWidget
381  << mSpinStretch
382  << mFontWordSpacingSpinBox
383  << mFormatNumChkBx
384  << mFormatNumDecimalsSpnBx
385  << mFormatNumPlusSignChkBx
386  << mLimitLabelChkBox
387  << mLimitLabelSpinBox
388  << mLineDistanceSpnBx
389  << mLineDistanceUnitWidget
390  << mMaxCharAngleInDSpinBox
391  << mMaxCharAngleOutDSpinBox
392  << mMinSizeSpinBox
393  << mOffsetTypeComboBox
394  << mPalShowAllLabelsForLayerChkBx
395  << mPointAngleSpinBox
396  << mPointOffsetUnitWidget
397  << mPointOffsetXSpinBox
398  << mPointOffsetYSpinBox
399  << mPreviewBackgroundBtn
400  << mPreviewTextEdit
401  << mPrioritySlider
402  << mRepeatDistanceSpinBox
403  << mRepeatDistanceUnitWidget
404  << mOverrunDistanceSpinBox
405  << mOverrunDistanceUnitWidget
406  << mScaleBasedVisibilityChkBx
407  << mMaxScaleWidget
408  << mMinScaleWidget
409  << mShadowBlendCmbBx
410  << mShadowColorBtn
411  << mShadowDrawChkBx
412  << mShadowOffsetAngleSpnBx
413  << mShadowOffsetGlobalChkBx
414  << mShadowOffsetSpnBx
415  << mShadowOffsetUnitWidget
416  << mShadowRadiusAlphaChkBx
417  << mShadowRadiusDblSpnBx
418  << mShadowRadiusUnitWidget
419  << mShadowScaleSpnBx
420  << mShadowOpacityWidget
421  << mShadowUnderCmbBx
422  << mShapeBlendCmbBx
423  << mShapeStrokeColorBtn
424  << mShapeStrokeWidthSpnBx
425  << mShapeStrokeWidthUnitWidget
426  << mShapeDrawChkBx
427  << mShapeFillColorBtn
428  << mShapeOffsetXSpnBx
429  << mShapeOffsetYSpnBx
430  << mShapeOffsetUnitWidget
431  << mShapeRadiusXDbSpnBx
432  << mShapeRadiusYDbSpnBx
433  << mShapeRotationCmbBx
434  << mShapeRotationDblSpnBx
435  << mShapeRadiusUnitWidget
436  << mShapeSVGPathLineEdit
437  << mShapeSizeCmbBx
438  << mShapeSizeUnitWidget
439  << mShapeSizeXSpnBx
440  << mShapeSizeYSpnBx
441  << mBackgroundOpacityWidget
442  << mShapeTypeCmbBx
443  << mZIndexSpinBox
444  << spinBufferSize
445  << wrapCharacterEdit
446  << mAutoWrapLengthSpinBox
447  << mAutoWrapTypeComboBox
448  << mCentroidRadioVisible
449  << mCentroidRadioWhole
450  << mDirectSymbRadioBtnAbove
451  << mDirectSymbRadioBtnBelow
452  << mDirectSymbRadioBtnLR
453  << mUpsidedownRadioAll
454  << mUpsidedownRadioDefined
455  << mUpsidedownRadioOff
456  << mPlacementModeComboBox
457  << mFieldExpressionWidget
458  << mCheckBoxSubstituteText
459  << mGeometryGeneratorGroupBox
460  << mGeometryGenerator
461  << mGeometryGeneratorType
462  << mBackgroundMarkerSymbolButton
463  << mBackgroundFillSymbolButton
464  << mCalloutsDrawCheckBox
465  << mCalloutStyleComboBox
466  << mKerningCheckBox
467  << mEnableMaskChkBx
468  << mMaskJoinStyleComboBox
469  << mMaskBufferSizeSpinBox
470  << mMaskOpacityWidget
471  << mCheckAllowLabelsOutsidePolygons
472  << mHtmlFormattingCheckBox;
473 
474  connectValueChanged( widgets, SLOT( updatePreview() ) );
475 
476  connect( mQuadrantBtnGrp, qOverload< QAbstractButton * >( &QButtonGroup::buttonClicked ), this, &QgsTextFormatWidget::updatePreview );
477 
478  connect( mBufferDrawDDBtn, &QgsPropertyOverrideButton::activated, this, &QgsTextFormatWidget::updateBufferFrameStatus );
479  connect( mBufferDrawChkBx, &QCheckBox::stateChanged, this, [ = ]( int )
480  {
481  updateBufferFrameStatus();
482  } );
483  connect( mShapeDrawDDBtn, &QgsPropertyOverrideButton::activated, this, &QgsTextFormatWidget::updateShapeFrameStatus );
484  connect( mShapeDrawChkBx, &QCheckBox::stateChanged, this, [ = ]( int )
485  {
486  updateShapeFrameStatus();
487  } );
488  connect( mShadowDrawDDBtn, &QgsPropertyOverrideButton::activated, this, &QgsTextFormatWidget::updateShadowFrameStatus );
489  connect( mShadowDrawChkBx, &QCheckBox::stateChanged, this, [ = ]( int )
490  {
491  updateShadowFrameStatus();
492  } );
493  connect( mCalloutDrawDDBtn, &QgsPropertyOverrideButton::changed, this, &QgsTextFormatWidget::updateCalloutFrameStatus );
494  connect( mCalloutsDrawCheckBox, &QCheckBox::stateChanged, this, [ = ]( int )
495  {
496  updateCalloutFrameStatus();
497  } );
498 
499  mGeometryGeneratorType->addItem( QgsIconUtils::iconForWkbType( QgsWkbTypes::Polygon ), tr( "Polygon / MultiPolygon" ), QgsWkbTypes::GeometryType::PolygonGeometry );
500  mGeometryGeneratorType->addItem( QgsIconUtils::iconForWkbType( QgsWkbTypes::LineString ), tr( "LineString / MultiLineString" ), QgsWkbTypes::GeometryType::LineGeometry );
501  mGeometryGeneratorType->addItem( QgsIconUtils::iconForWkbType( QgsWkbTypes::Point ), tr( "Point / MultiPoint" ), QgsWkbTypes::GeometryType::PointGeometry );
502 
503  // set correct initial tab to match displayed setting page
504  whileBlocking( mOptionsTab )->setCurrentIndex( mLabelStackedWidget->currentIndex() );
505  mOptionsTab->tabBar()->setUsesScrollButtons( true );
506 
507 
508  if ( mMapCanvas )
509  {
510  lblFontPreview->setMapUnits( mMapCanvas->mapSettings().mapUnits() );
511  mPreviewScaleComboBox->setScale( mMapCanvas->mapSettings().scale() );
512  }
513 
514  mTextFormatsListWidget->setStyle( QgsStyle::defaultStyle() );
515  mTextFormatsListWidget->setEntityType( QgsStyle::TextFormatEntity );
517  connect( mTextFormatsListWidget, &QgsStyleItemsListWidget::saveEntity, this, &QgsTextFormatWidget::saveFormat );
518 }
519 
520 void QgsTextFormatWidget::setWidgetMode( QgsTextFormatWidget::Mode mode )
521 {
522  mWidgetMode = mode;
523  switch ( mode )
524  {
525  case Labeling:
526  toggleDDButtons( true );
527  mTextFormatsListWidget->setEntityTypes( QList< QgsStyle::StyleEntity >() << QgsStyle::TextFormatEntity << QgsStyle::LabelSettingsEntity );
528  mTextOrientationComboBox->addItem( tr( "Rotation-based" ), QgsTextFormat::RotationBasedOrientation );
529  break;
530 
531  case Text:
532  {
533  const int prevIndex = mOptionsTab->currentIndex();
534  toggleDDButtons( true );
535  delete mLabelingOptionsListWidget->takeItem( 8 ); // rendering
536  delete mLabelingOptionsListWidget->takeItem( 7 ); // placement
537  delete mLabelingOptionsListWidget->takeItem( 6 ); // callouts
538  delete mLabelingOptionsListWidget->takeItem( 3 ); // mask
539  mOptionsTab->removeTab( 8 );
540  mOptionsTab->removeTab( 7 );
541  mOptionsTab->removeTab( 6 );
542  mOptionsTab->removeTab( 3 );
543  mLabelStackedWidget->removeWidget( mLabelPage_Rendering );
544  mLabelStackedWidget->removeWidget( mLabelPage_Callouts );
545  mLabelStackedWidget->removeWidget( mLabelPage_Mask );
546  mLabelStackedWidget->removeWidget( mLabelPage_Placement );
547  switch ( prevIndex )
548  {
549  case 0:
550  case 1:
551  case 2:
552  break;
553 
554  case 4: // background - account for removed mask tab
555  case 5: // shadow
556  mLabelStackedWidget->setCurrentIndex( prevIndex - 1 );
557  mOptionsTab->setCurrentIndex( prevIndex - 1 );
558  break;
559 
560  case 3: // mask
561  case 6: // callouts
562  case 7: // placement
563  case 8: // rendering
564  mLabelStackedWidget->setCurrentIndex( 0 );
565  mOptionsTab->setCurrentIndex( 0 );
566  break;
567  }
568 
569  frameLabelWith->hide();
570  mDirectSymbolsFrame->hide();
571  mFormatNumFrame->hide();
572  mFormatNumChkBx->hide();
573  mFormatNumDDBtn->hide();
574  mCheckBoxSubstituteText->hide();
575  mToolButtonConfigureSubstitutes->hide();
576  mLabelWrapOnCharacter->hide();
577  wrapCharacterEdit->hide();
578  mWrapCharDDBtn->hide();
579  mLabelWrapLinesTo->hide();
580  mAutoWrapLengthSpinBox->hide();
581  mAutoWrapLengthDDBtn->hide();
582  mAutoWrapTypeComboBox->hide();
583  mFontMultiLineLabel->hide();
584  mFontMultiLineAlignComboBox->hide();
585  mFontMultiLineAlignDDBtn->hide();
586 
587  mTextOrientationComboBox->removeItem( mTextOrientationComboBox->findData( QgsTextFormat::RotationBasedOrientation ) );
588  break;
589  }
590  }
591 }
592 
593 void QgsTextFormatWidget::toggleDDButtons( bool visible )
594 {
595  const auto buttons = findChildren< QgsPropertyOverrideButton * >();
596  for ( QgsPropertyOverrideButton *button : buttons )
597  {
598 #ifndef HAS_KDE_QT5_FONT_STRETCH_FIX
599  if ( button == mFontStretchDDBtn )
600  continue; // always hidden
601 #endif
602  button->setVisible( visible );
603  }
604 }
605 
607 {
608  mOptionsTab->setVisible( enabled );
609  mOptionsTab->setTabToolTip( 0, tr( "Text" ) );
610  mOptionsTab->setTabToolTip( 1, tr( "Formatting" ) );
611  mOptionsTab->setTabToolTip( 2, tr( "Buffer" ) );
612  mOptionsTab->setTabToolTip( 3, tr( "Mask" ) );
613  mOptionsTab->setTabToolTip( 4, tr( "Background" ) );
614  mOptionsTab->setTabToolTip( 5, tr( "Shadow" ) );
615  mOptionsTab->setTabToolTip( 6, tr( "Callouts" ) );
616  mOptionsTab->setTabToolTip( 7, tr( "Placement" ) );
617  mOptionsTab->setTabToolTip( 8, tr( "Rendering" ) );
618 
619  mLabelingOptionsListFrame->setVisible( !enabled );
620  groupBox_mPreview->setVisible( !enabled );
621  mDockMode = enabled;
622 }
623 
624 void QgsTextFormatWidget::connectValueChanged( const QList<QWidget *> &widgets, const char *slot )
625 {
626  const auto constWidgets = widgets;
627  for ( QWidget *widget : constWidgets )
628  {
629  if ( QgsSymbolButton *w = qobject_cast<QgsSymbolButton *>( widget ) )
630  {
631  connect( w, SIGNAL( changed() ), this, slot );
632  }
633  else if ( QgsFieldExpressionWidget *w = qobject_cast< QgsFieldExpressionWidget *>( widget ) )
634  {
635  connect( w, SIGNAL( fieldChanged( QString ) ), this, slot );
636  }
637  else if ( QgsOpacityWidget *w = qobject_cast< QgsOpacityWidget *>( widget ) )
638  {
639  connect( w, SIGNAL( opacityChanged( double ) ), this, slot );
640  }
641  else if ( QgsScaleWidget *w = qobject_cast< QgsScaleWidget *>( widget ) )
642  {
643  connect( w, SIGNAL( scaleChanged( double ) ), this, slot );
644  }
645  else if ( QgsUnitSelectionWidget *w = qobject_cast<QgsUnitSelectionWidget *>( widget ) )
646  {
647  connect( w, SIGNAL( changed() ), this, slot );
648  }
649  else if ( QComboBox *w = qobject_cast<QComboBox *>( widget ) )
650  {
651  connect( w, SIGNAL( currentIndexChanged( int ) ), this, slot );
652  }
653  else if ( QSpinBox *w = qobject_cast<QSpinBox *>( widget ) )
654  {
655  connect( w, SIGNAL( valueChanged( int ) ), this, slot );
656  }
657  else if ( QDoubleSpinBox *w = qobject_cast<QDoubleSpinBox *>( widget ) )
658  {
659  connect( w, SIGNAL( valueChanged( double ) ), this, slot );
660  }
661  else if ( QgsColorButton *w = qobject_cast<QgsColorButton *>( widget ) )
662  {
663  connect( w, SIGNAL( colorChanged( QColor ) ), this, slot );
664  }
665  else if ( QCheckBox *w = qobject_cast<QCheckBox *>( widget ) )
666  {
667  connect( w, SIGNAL( toggled( bool ) ), this, slot );
668  }
669  else if ( QRadioButton *w = qobject_cast<QRadioButton *>( widget ) )
670  {
671  connect( w, SIGNAL( toggled( bool ) ), this, slot );
672  }
673  else if ( QLineEdit *w = qobject_cast<QLineEdit *>( widget ) )
674  {
675  connect( w, SIGNAL( textEdited( QString ) ), this, slot );
676  }
677  else if ( QSlider *w = qobject_cast<QSlider *>( widget ) )
678  {
679  connect( w, SIGNAL( valueChanged( int ) ), this, slot );
680  }
681  else if ( QGroupBox *w = qobject_cast<QGroupBox *>( widget ) )
682  {
683  connect( w, SIGNAL( toggled( bool ) ), this, slot );
684  }
685  else if ( QgsCodeEditorExpression *w = qobject_cast<QgsCodeEditorExpression *>( widget ) )
686  {
687  connect( w, SIGNAL( textChanged() ), this, slot );
688  }
689  else
690  {
691  QgsLogger::warning( QStringLiteral( "Could not create connection for widget %1" ).arg( widget->objectName() ) );
692  }
693  }
694 }
695 
697 {
698  // text style
699  registerDataDefinedButton( mFontDDBtn, QgsPalLayerSettings::Family );
700  registerDataDefinedButton( mFontStyleDDBtn, QgsPalLayerSettings::FontStyle );
701  registerDataDefinedButton( mFontUnderlineDDBtn, QgsPalLayerSettings::Underline );
702  registerDataDefinedButton( mFontStrikeoutDDBtn, QgsPalLayerSettings::Strikeout );
703  registerDataDefinedButton( mFontBoldDDBtn, QgsPalLayerSettings::Bold );
704  registerDataDefinedButton( mFontItalicDDBtn, QgsPalLayerSettings::Italic );
705  registerDataDefinedButton( mFontSizeDDBtn, QgsPalLayerSettings::Size );
706  registerDataDefinedButton( mFontUnitsDDBtn, QgsPalLayerSettings::FontSizeUnit );
707  registerDataDefinedButton( mFontColorDDBtn, QgsPalLayerSettings::Color );
708  registerDataDefinedButton( mFontOpacityDDBtn, QgsPalLayerSettings::FontOpacity );
709  registerDataDefinedButton( mFontCaseDDBtn, QgsPalLayerSettings::FontCase );
710  registerDataDefinedButton( mFontLetterSpacingDDBtn, QgsPalLayerSettings::FontLetterSpacing );
711  registerDataDefinedButton( mFontWordSpacingDDBtn, QgsPalLayerSettings::FontWordSpacing );
712  registerDataDefinedButton( mFontBlendModeDDBtn, QgsPalLayerSettings::FontBlendMode );
713  registerDataDefinedButton( mFontStretchDDBtn, QgsPalLayerSettings::FontStretchFactor );
714 
715  // text formatting
716  registerDataDefinedButton( mWrapCharDDBtn, QgsPalLayerSettings::MultiLineWrapChar );
717  registerDataDefinedButton( mAutoWrapLengthDDBtn, QgsPalLayerSettings::AutoWrapLength );
718  registerDataDefinedButton( mFontLineHeightDDBtn, QgsPalLayerSettings::MultiLineHeight );
719  registerDataDefinedButton( mFontMultiLineAlignDDBtn, QgsPalLayerSettings::MultiLineAlignment );
720  registerDataDefinedButton( mTextOrientationDDBtn, QgsPalLayerSettings::TextOrientation );
721 
722  registerDataDefinedButton( mDirectSymbDDBtn, QgsPalLayerSettings::DirSymbDraw );
723  mDirectSymbDDBtn->registerCheckedWidget( mDirectSymbChkBx );
724  registerDataDefinedButton( mDirectSymbLeftDDBtn, QgsPalLayerSettings::DirSymbLeft );
725  registerDataDefinedButton( mDirectSymbRightDDBtn, QgsPalLayerSettings::DirSymbRight );
726 
727  registerDataDefinedButton( mDirectSymbPlacementDDBtn, QgsPalLayerSettings::DirSymbPlacement );
728  registerDataDefinedButton( mDirectSymbRevDDBtn, QgsPalLayerSettings::DirSymbReverse );
729 
730  registerDataDefinedButton( mFormatNumDDBtn, QgsPalLayerSettings::NumFormat );
731  mFormatNumDDBtn->registerCheckedWidget( mFormatNumChkBx );
732  registerDataDefinedButton( mFormatNumDecimalsDDBtn, QgsPalLayerSettings::NumDecimals );
733  registerDataDefinedButton( mFormatNumPlusSignDDBtn, QgsPalLayerSettings::NumPlusSign );
734 
735  // text buffer
736  registerDataDefinedButton( mBufferDrawDDBtn, QgsPalLayerSettings::BufferDraw );
737  registerDataDefinedButton( mBufferSizeDDBtn, QgsPalLayerSettings::BufferSize );
738  registerDataDefinedButton( mBufferUnitsDDBtn, QgsPalLayerSettings::BufferUnit );
739  registerDataDefinedButton( mBufferColorDDBtn, QgsPalLayerSettings::BufferColor );
740  registerDataDefinedButton( mBufferOpacityDDBtn, QgsPalLayerSettings::BufferOpacity );
741  registerDataDefinedButton( mBufferJoinStyleDDBtn, QgsPalLayerSettings::BufferJoinStyle );
742  registerDataDefinedButton( mBufferBlendModeDDBtn, QgsPalLayerSettings::BufferBlendMode );
743 
744  // mask
745  registerDataDefinedButton( mEnableMaskDDBtn, QgsPalLayerSettings::MaskEnabled );
746  mEnableMaskDDBtn->registerCheckedWidget( mEnableMaskChkBx );
747  registerDataDefinedButton( mMaskBufferSizeDDBtn, QgsPalLayerSettings::MaskBufferSize );
748  registerDataDefinedButton( mMaskBufferUnitsDDBtn, QgsPalLayerSettings::MaskBufferUnit );
749  registerDataDefinedButton( mMaskOpacityDDBtn, QgsPalLayerSettings::MaskOpacity );
750  registerDataDefinedButton( mMaskJoinStyleDDBtn, QgsPalLayerSettings::MaskJoinStyle );
751 
752  // background
753  registerDataDefinedButton( mShapeDrawDDBtn, QgsPalLayerSettings::ShapeDraw );
754  mShapeDrawDDBtn->registerCheckedWidget( mShapeDrawChkBx );
755  registerDataDefinedButton( mShapeTypeDDBtn, QgsPalLayerSettings::ShapeKind );
756  registerDataDefinedButton( mShapeSVGPathDDBtn, QgsPalLayerSettings::ShapeSVGFile );
757  registerDataDefinedButton( mShapeSizeTypeDDBtn, QgsPalLayerSettings::ShapeSizeType );
758  registerDataDefinedButton( mShapeSizeXDDBtn, QgsPalLayerSettings::ShapeSizeX );
759  registerDataDefinedButton( mShapeSizeYDDBtn, QgsPalLayerSettings::ShapeSizeY );
760  registerDataDefinedButton( mShapeSizeUnitsDDBtn, QgsPalLayerSettings::ShapeSizeUnits );
761  registerDataDefinedButton( mShapeRotationTypeDDBtn, QgsPalLayerSettings::ShapeRotationType );
762  registerDataDefinedButton( mShapeRotationDDBtn, QgsPalLayerSettings::ShapeRotation );
763  registerDataDefinedButton( mShapeOffsetDDBtn, QgsPalLayerSettings::ShapeOffset );
764  registerDataDefinedButton( mShapeOffsetUnitsDDBtn, QgsPalLayerSettings::ShapeOffsetUnits );
765  registerDataDefinedButton( mShapeRadiusDDBtn, QgsPalLayerSettings::ShapeRadii );
766  registerDataDefinedButton( mShapeRadiusUnitsDDBtn, QgsPalLayerSettings::ShapeRadiiUnits );
767  registerDataDefinedButton( mShapeOpacityDDBtn, QgsPalLayerSettings::ShapeOpacity );
768  registerDataDefinedButton( mShapeBlendModeDDBtn, QgsPalLayerSettings::ShapeBlendMode );
769  registerDataDefinedButton( mShapeFillColorDDBtn, QgsPalLayerSettings::ShapeFillColor );
770  registerDataDefinedButton( mShapeStrokeColorDDBtn, QgsPalLayerSettings::ShapeStrokeColor );
771  registerDataDefinedButton( mShapeStrokeWidthDDBtn, QgsPalLayerSettings::ShapeStrokeWidth );
772  registerDataDefinedButton( mShapeStrokeUnitsDDBtn, QgsPalLayerSettings::ShapeStrokeWidthUnits );
773 
774  // drop shadows
775  registerDataDefinedButton( mShadowDrawDDBtn, QgsPalLayerSettings::ShadowDraw );
776  mShadowDrawDDBtn->registerCheckedWidget( mShadowDrawChkBx );
777  registerDataDefinedButton( mShadowUnderDDBtn, QgsPalLayerSettings::ShadowUnder );
778  registerDataDefinedButton( mShadowOffsetAngleDDBtn, QgsPalLayerSettings::ShadowOffsetAngle );
779  registerDataDefinedButton( mShadowOffsetDDBtn, QgsPalLayerSettings::ShadowOffsetDist );
780  registerDataDefinedButton( mShadowOffsetUnitsDDBtn, QgsPalLayerSettings::ShadowOffsetUnits );
781  registerDataDefinedButton( mShadowRadiusDDBtn, QgsPalLayerSettings::ShadowRadius );
782  registerDataDefinedButton( mShadowRadiusUnitsDDBtn, QgsPalLayerSettings::ShadowRadiusUnits );
783  registerDataDefinedButton( mShadowOpacityDDBtn, QgsPalLayerSettings::ShadowOpacity );
784  registerDataDefinedButton( mShadowScaleDDBtn, QgsPalLayerSettings::ShadowScale );
785  registerDataDefinedButton( mShadowColorDDBtn, QgsPalLayerSettings::ShadowColor );
786  registerDataDefinedButton( mShadowBlendDDBtn, QgsPalLayerSettings::ShadowBlendMode );
787 
788  // placement
789  registerDataDefinedButton( mCentroidDDBtn, QgsPalLayerSettings::CentroidWhole );
790  registerDataDefinedButton( mPointQuadOffsetDDBtn, QgsPalLayerSettings::OffsetQuad );
791  registerDataDefinedButton( mPointPositionOrderDDBtn, QgsPalLayerSettings::PredefinedPositionOrder );
792  registerDataDefinedButton( mLinePlacementFlagsDDBtn, QgsPalLayerSettings::LinePlacementOptions );
793  registerDataDefinedButton( mPointOffsetDDBtn, QgsPalLayerSettings::OffsetXY );
794  registerDataDefinedButton( mPointOffsetUnitsDDBtn, QgsPalLayerSettings::OffsetUnits );
795  registerDataDefinedButton( mLineDistanceDDBtn, QgsPalLayerSettings::LabelDistance );
796  registerDataDefinedButton( mLineDistanceUnitDDBtn, QgsPalLayerSettings::DistanceUnits );
797  registerDataDefinedButton( mPriorityDDBtn, QgsPalLayerSettings::Priority );
798  registerDataDefinedButton( mAllowOutsidePolygonsDDBtn, QgsPalLayerSettings::PolygonLabelOutside );
799 
800  // TODO: is this necessary? maybe just use the data defined-only rotation?
801  //mPointAngleDDBtn, QgsPalLayerSettings::OffsetRotation,
802  // QgsPropertyOverrideButton::AnyType, QgsPropertyOverrideButton::double180RotDesc() );
803  registerDataDefinedButton( mMaxCharAngleDDBtn, QgsPalLayerSettings::CurvedCharAngleInOut );
804  registerDataDefinedButton( mRepeatDistanceDDBtn, QgsPalLayerSettings::RepeatDistance );
805  registerDataDefinedButton( mRepeatDistanceUnitDDBtn, QgsPalLayerSettings::RepeatDistanceUnit );
806  registerDataDefinedButton( mOverrunDistanceDDBtn, QgsPalLayerSettings::OverrunDistance );
807 
808  // data defined-only
809  registerDataDefinedButton( mCoordXDDBtn, QgsPalLayerSettings::PositionX );
810  registerDataDefinedButton( mCoordYDDBtn, QgsPalLayerSettings::PositionY );
811  registerDataDefinedButton( mCoordPointDDBtn, QgsPalLayerSettings::PositionPoint );
812  registerDataDefinedButton( mCoordAlignmentHDDBtn, QgsPalLayerSettings::Hali );
813  registerDataDefinedButton( mCoordAlignmentVDDBtn, QgsPalLayerSettings::Vali );
814  registerDataDefinedButton( mCoordRotationDDBtn, QgsPalLayerSettings::LabelRotation );
815 
816  updateDataDefinedAlignment();
817 
818  // rendering
819  const QString ddScaleVisInfo = tr( "Value &lt; 0 represents a scale closer than 1:1, e.g. -10 = 10:1<br>"
820  "Value of 0 disables the specific limit." );
821  registerDataDefinedButton( mScaleBasedVisibilityDDBtn, QgsPalLayerSettings::ScaleVisibility );
822  mScaleBasedVisibilityDDBtn->registerCheckedWidget( mScaleBasedVisibilityChkBx );
823  registerDataDefinedButton( mScaleBasedVisibilityMinDDBtn, QgsPalLayerSettings::MinimumScale );
824  mScaleBasedVisibilityMinDDBtn->setUsageInfo( ddScaleVisInfo );
825  registerDataDefinedButton( mScaleBasedVisibilityMaxDDBtn, QgsPalLayerSettings::MaximumScale );
826  mScaleBasedVisibilityMaxDDBtn->setUsageInfo( ddScaleVisInfo );
827 
828  registerDataDefinedButton( mFontLimitPixelDDBtn, QgsPalLayerSettings::FontLimitPixel );
829  mFontLimitPixelDDBtn->registerCheckedWidget( mFontLimitPixelChkBox );
830  registerDataDefinedButton( mFontMinPixelDDBtn, QgsPalLayerSettings::FontMinPixel );
831  registerDataDefinedButton( mFontMaxPixelDDBtn, QgsPalLayerSettings::FontMaxPixel );
832 
833  registerDataDefinedButton( mShowLabelDDBtn, QgsPalLayerSettings::Show );
834 
835  registerDataDefinedButton( mAlwaysShowDDBtn, QgsPalLayerSettings::AlwaysShow );
836 
837  registerDataDefinedButton( mIsObstacleDDBtn, QgsPalLayerSettings::IsObstacle );
838  registerDataDefinedButton( mZIndexDDBtn, QgsPalLayerSettings::ZIndex );
839 
840  registerDataDefinedButton( mCalloutDrawDDBtn, QgsPalLayerSettings::CalloutDraw );
841 
842  registerDataDefinedButton( mLabelAllPartsDDBtn, QgsPalLayerSettings::LabelAllParts );
843 }
844 
845 void QgsTextFormatWidget::registerDataDefinedButton( QgsPropertyOverrideButton *button, QgsPalLayerSettings::Property key )
846 {
848  if ( !mButtons.contains( key ) )
849  {
850  connect( button, &QgsPropertyOverrideButton::changed, this, &QgsTextFormatWidget::updateProperty );
851  connect( button, &QgsPropertyOverrideButton::createAuxiliaryField, this, &QgsTextFormatWidget::createAuxiliaryField );
852  button->registerExpressionContextGenerator( this );
853  mButtons[key] = button;
854  }
855 }
856 
858 {
859  const QgsTextBufferSettings buffer = format.buffer();
860  const QgsTextMaskSettings mask = format.mask();
861  const QgsTextBackgroundSettings background = format.background();
862  const QgsTextShadowSettings shadow = format.shadow();
863 
864  if ( mWidgetMode != Labeling )
865  {
867  }
868 
869  // buffer
870  mBufferDrawChkBx->setChecked( buffer.enabled() );
871  mBufferFrame->setEnabled( buffer.enabled() );
872  spinBufferSize->setValue( buffer.size() );
873  mBufferUnitWidget->setUnit( buffer.sizeUnit() );
874  mBufferUnitWidget->setMapUnitScale( buffer.sizeMapUnitScale() );
875  btnBufferColor->setColor( buffer.color() );
876  mBufferOpacityWidget->setOpacity( buffer.opacity() );
877  mBufferJoinStyleComboBox->setPenJoinStyle( buffer.joinStyle() );
878  mBufferTranspFillChbx->setChecked( buffer.fillBufferInterior() );
879  comboBufferBlendMode->setBlendMode( buffer.blendMode() );
880  if ( auto *lPaintEffect = buffer.paintEffect() )
881  mBufferEffect.reset( lPaintEffect->clone() );
882  else
883  {
884  mBufferEffect.reset( QgsPaintEffectRegistry::defaultStack() );
885  mBufferEffect->setEnabled( false );
886  }
887  mBufferEffectWidget->setPaintEffect( mBufferEffect.get() );
888 
889  // mask
891  mEnableMaskChkBx->setChecked( mask.enabled() );
892  mMaskBufferSizeSpinBox->setValue( mask.size() );
893  mMaskBufferUnitWidget->setUnit( mask.sizeUnit() );
894  mMaskBufferUnitWidget->setMapUnitScale( mask.sizeMapUnitScale() );
895  mMaskOpacityWidget->setOpacity( mask.opacity() );
896  mMaskJoinStyleComboBox->setPenJoinStyle( mask.joinStyle() );
897  if ( auto *lPaintEffect = mask.paintEffect() )
898  mMaskEffect.reset( lPaintEffect->clone() );
899  else
900  {
901  mMaskEffect.reset( QgsPaintEffectRegistry::defaultStack() );
902  mMaskEffect->setEnabled( false );
903  }
904  mMaskEffectWidget->setPaintEffect( mMaskEffect.get() );
905 
906  mFontSizeUnitWidget->setUnit( format.sizeUnit() );
907  mFontSizeUnitWidget->setMapUnitScale( format.sizeMapUnitScale() );
908  mRefFont = format.font();
909  mFontSizeSpinBox->setValue( format.size() );
910  btnTextColor->setColor( format.color() );
911  whileBlocking( mSpinStretch )->setValue( format.stretchFactor() );
912  mTextOpacityWidget->setOpacity( format.opacity() );
913  comboBlendMode->setBlendMode( format.blendMode() );
914  mTextOrientationComboBox->setCurrentIndex( mTextOrientationComboBox->findData( format.orientation() ) );
915  mHtmlFormattingCheckBox->setChecked( format.allowHtmlFormatting() );
916 
917  mFontWordSpacingSpinBox->setValue( format.font().wordSpacing() );
918  mFontLetterSpacingSpinBox->setValue( format.font().letterSpacing() );
919  whileBlocking( mKerningCheckBox )->setChecked( format.font().kerning() );
920 
921  whileBlocking( mFontCapitalsComboBox )->setCurrentIndex( mFontCapitalsComboBox->findData( static_cast< int >( format.capitalization() ) ) );
923  updateFont( mRefFont );
924 
925  // show 'font not found' if substitution has occurred (should come after updateFont())
926  mFontMissingLabel->setVisible( !format.fontFound() );
927  if ( !format.fontFound() )
928  {
929  const QString missingTxt = tr( "%1 not found. Default substituted." );
930  QString txtPrepend = tr( "Chosen font" );
931  if ( !format.resolvedFontFamily().isEmpty() )
932  {
933  txtPrepend = QStringLiteral( "'%1'" ).arg( format.resolvedFontFamily() );
934  }
935  mFontMissingLabel->setText( missingTxt.arg( txtPrepend ) );
936 
937  // ensure user is sent to 'Text style' section to see notice
938  mLabelingOptionsListWidget->setCurrentRow( 0 );
939  whileBlocking( mOptionsTab )->setCurrentIndex( 0 );
940  }
941  mFontLineHeightSpinBox->setValue( format.lineHeight() );
942 
943  // shape background
944  mShapeDrawChkBx->setChecked( background.enabled() );
945  mShapeFrame->setEnabled( background.enabled() );
946  mShapeTypeCmbBx->blockSignals( true );
947  mShapeTypeCmbBx->setCurrentIndex( mShapeTypeCmbBx->findData( background.type() ) );
948  mShapeTypeCmbBx->blockSignals( false );
949  updateAvailableShadowPositions();
950  mShapeSVGPathLineEdit->setText( background.svgFile() );
951 
952  mShapeSizeCmbBx->setCurrentIndex( background.sizeType() );
953  mShapeSizeXSpnBx->setValue( background.size().width() );
954  mShapeSizeYSpnBx->setValue( background.size().height() );
955  mShapeSizeUnitWidget->setUnit( background.sizeUnit() );
956  mShapeSizeUnitWidget->setMapUnitScale( background.sizeMapUnitScale() );
957  mShapeRotationCmbBx->setCurrentIndex( background.rotationType() );
958  mShapeRotationDblSpnBx->setEnabled( background.rotationType() != QgsTextBackgroundSettings::RotationSync );
959  mShapeRotationDDBtn->setEnabled( background.rotationType() != QgsTextBackgroundSettings::RotationSync );
960  mShapeRotationDblSpnBx->setValue( background.rotation() );
961  mShapeOffsetXSpnBx->setValue( background.offset().x() );
962  mShapeOffsetYSpnBx->setValue( background.offset().y() );
963  mShapeOffsetUnitWidget->setUnit( background.offsetUnit() );
964  mShapeOffsetUnitWidget->setMapUnitScale( background.offsetMapUnitScale() );
965  mShapeRadiusXDbSpnBx->setValue( background.radii().width() );
966  mShapeRadiusYDbSpnBx->setValue( background.radii().height() );
967  mShapeRadiusUnitWidget->setUnit( background.radiiUnit() );
968  mShapeRadiusUnitWidget->setMapUnitScale( background.radiiMapUnitScale() );
969 
970  mShapeFillColorBtn->setColor( background.fillColor() );
971  mShapeStrokeColorBtn->setColor( background.strokeColor() );
972  mShapeStrokeWidthSpnBx->setValue( background.strokeWidth() );
973  mShapeStrokeWidthUnitWidget->setUnit( background.strokeWidthUnit() );
974  mShapeStrokeWidthUnitWidget->setMapUnitScale( background.strokeWidthMapUnitScale() );
975 
976  mBackgroundOpacityWidget->setOpacity( background.opacity() );
977  mShapeBlendCmbBx->setBlendMode( background.blendMode() );
978 
979  mLoadSvgParams = false;
980  mShapeTypeCmbBx_currentIndexChanged( background.type() ); // force update of shape background gui
981 
982  if ( auto *lPaintEffect = background.paintEffect() )
983  mBackgroundEffect.reset( lPaintEffect->clone() );
984  else
985  {
986  mBackgroundEffect.reset( QgsPaintEffectRegistry::defaultStack() );
987  mBackgroundEffect->setEnabled( false );
988  }
989  mBackgroundEffectWidget->setPaintEffect( mBackgroundEffect.get() );
990 
991  mBackgroundMarkerSymbolButton->setSymbol( background.markerSymbol() ? background.markerSymbol()->clone() : QgsSymbol::defaultSymbol( QgsWkbTypes::PointGeometry ) );
992  mBackgroundFillSymbolButton->setSymbol( background.fillSymbol() ? background.fillSymbol()->clone() : QgsSymbol::defaultSymbol( QgsWkbTypes::PolygonGeometry ) );
993 
994  // drop shadow
995  mShadowDrawChkBx->setChecked( shadow.enabled() );
996  mShadowFrame->setEnabled( shadow.enabled() );
997  mShadowUnderCmbBx->setCurrentIndex( mShadowUnderCmbBx->findData( shadow.shadowPlacement() ) );
998  mShadowOffsetAngleSpnBx->setValue( shadow.offsetAngle() );
999  mShadowOffsetSpnBx->setValue( shadow.offsetDistance() );
1000  mShadowOffsetUnitWidget->setUnit( shadow.offsetUnit() );
1001  mShadowOffsetUnitWidget->setMapUnitScale( shadow.offsetMapUnitScale() );
1002  mShadowOffsetGlobalChkBx->setChecked( shadow.offsetGlobal() );
1003 
1004  mShadowRadiusDblSpnBx->setValue( shadow.blurRadius() );
1005  mShadowRadiusUnitWidget->setUnit( shadow.blurRadiusUnit() );
1006  mShadowRadiusUnitWidget->setMapUnitScale( shadow.blurRadiusMapUnitScale() );
1007  mShadowRadiusAlphaChkBx->setChecked( shadow.blurAlphaOnly() );
1008  mShadowOpacityWidget->setOpacity( shadow.opacity() );
1009  mShadowScaleSpnBx->setValue( shadow.scale() );
1010 
1011  mShadowColorBtn->setColor( shadow.color() );
1012  mShadowBlendCmbBx->setBlendMode( shadow.blendMode() );
1013 
1014  mPreviewBackgroundBtn->setColor( format.previewBackgroundColor() );
1015  mPreviewBackgroundBtn->setDefaultColor( format.previewBackgroundColor() );
1017 
1019 }
1020 
1022 {
1023  QgsSettings settings;
1024  settings.setValue( QStringLiteral( "Windows/Labeling/FontPreviewSplitState" ), mFontPreviewSplitter->saveState() );
1025  settings.setValue( QStringLiteral( "Windows/Labeling/OptionsSplitState" ), mLabelingOptionsSplitter->saveState() );
1026 
1027  int prevIndex = mLabelingOptionsListWidget->currentRow();
1028  if ( mWidgetMode == Text )
1029  {
1030  switch ( prevIndex )
1031  {
1032  case 3: // background - account for removed mask tab
1033  case 4: // shadow - account for removed mask tab
1034  prevIndex++;
1035  break;
1036  }
1037  }
1038 
1039  settings.setValue( QStringLiteral( "Windows/Labeling/Tab" ), prevIndex );
1040 }
1041 
1042 QgsTextFormat QgsTextFormatWidget::format( bool includeDataDefinedProperties ) const
1043 {
1045  format.setColor( btnTextColor->color() );
1046  format.setFont( mRefFont );
1047  format.setSize( mFontSizeSpinBox->value() );
1048  format.setNamedStyle( mFontStyleComboBox->currentText() );
1049  format.setOpacity( mTextOpacityWidget->opacity() );
1050  format.setStretchFactor( mSpinStretch->value() );
1051  format.setBlendMode( comboBlendMode->blendMode() );
1052  format.setSizeUnit( mFontSizeUnitWidget->unit() );
1053  format.setSizeMapUnitScale( mFontSizeUnitWidget->getMapUnitScale() );
1054  format.setLineHeight( mFontLineHeightSpinBox->value() );
1055  format.setPreviewBackgroundColor( mPreviewBackgroundColor );
1056  format.setOrientation( static_cast< QgsTextFormat::TextOrientation >( mTextOrientationComboBox->currentData().toInt() ) );
1057  format.setAllowHtmlFormatting( mHtmlFormattingCheckBox->isChecked( ) );
1058  format.setCapitalization( static_cast< Qgis::Capitalization >( mFontCapitalsComboBox->currentData().toInt() ) );
1059 
1060  // buffer
1061  QgsTextBufferSettings buffer;
1062  buffer.setEnabled( mBufferDrawChkBx->isChecked() );
1063  buffer.setSize( spinBufferSize->value() );
1064  buffer.setColor( btnBufferColor->color() );
1065  buffer.setOpacity( mBufferOpacityWidget->opacity() );
1066  buffer.setSizeUnit( mBufferUnitWidget->unit() );
1067  buffer.setSizeMapUnitScale( mBufferUnitWidget->getMapUnitScale() );
1068  buffer.setJoinStyle( mBufferJoinStyleComboBox->penJoinStyle() );
1069  buffer.setFillBufferInterior( mBufferTranspFillChbx->isChecked() );
1070  buffer.setBlendMode( comboBufferBlendMode->blendMode() );
1071  if ( mBufferEffect && ( !QgsPaintEffectRegistry::isDefaultStack( mBufferEffect.get() ) || mBufferEffect->enabled() ) )
1072  buffer.setPaintEffect( mBufferEffect->clone() );
1073  else
1074  buffer.setPaintEffect( nullptr );
1075  format.setBuffer( buffer );
1076 
1077  // mask
1078  QgsTextMaskSettings mask;
1079  mask.setEnabled( mEnableMaskChkBx->isChecked() );
1080  mask.setSize( mMaskBufferSizeSpinBox->value() );
1081  mask.setOpacity( mMaskOpacityWidget->opacity() );
1082  mask.setSizeUnit( mMaskBufferUnitWidget->unit() );
1083  mask.setSizeMapUnitScale( mMaskBufferUnitWidget->getMapUnitScale() );
1084  mask.setJoinStyle( mMaskJoinStyleComboBox->penJoinStyle() );
1085  if ( mMaskEffect && ( !QgsPaintEffectRegistry::isDefaultStack( mMaskEffect.get() ) || mMaskEffect->enabled() ) )
1086  mask.setPaintEffect( mMaskEffect->clone() );
1087  else
1088  mask.setPaintEffect( nullptr );
1090  format.setMask( mask );
1091 
1092  // shape background
1093  QgsTextBackgroundSettings background;
1094  background.setEnabled( mShapeDrawChkBx->isChecked() );
1095  background.setType( static_cast< QgsTextBackgroundSettings::ShapeType >( mShapeTypeCmbBx->currentData().toInt() ) );
1096  background.setSvgFile( mShapeSVGPathLineEdit->text() );
1097  background.setSizeType( static_cast< QgsTextBackgroundSettings::SizeType >( mShapeSizeCmbBx->currentIndex() ) );
1098  background.setSize( QSizeF( mShapeSizeXSpnBx->value(), mShapeSizeYSpnBx->value() ) );
1099  background.setSizeUnit( mShapeSizeUnitWidget->unit() );
1100  background.setSizeMapUnitScale( mShapeSizeUnitWidget->getMapUnitScale() );
1101  background.setRotationType( static_cast< QgsTextBackgroundSettings::RotationType >( mShapeRotationCmbBx->currentIndex() ) );
1102  background.setRotation( mShapeRotationDblSpnBx->value() );
1103  background.setOffset( QPointF( mShapeOffsetXSpnBx->value(), mShapeOffsetYSpnBx->value() ) );
1104  background.setOffsetUnit( mShapeOffsetUnitWidget->unit() );
1105  background.setOffsetMapUnitScale( mShapeOffsetUnitWidget->getMapUnitScale() );
1106  background.setRadii( QSizeF( mShapeRadiusXDbSpnBx->value(), mShapeRadiusYDbSpnBx->value() ) );
1107  background.setRadiiUnit( mShapeRadiusUnitWidget->unit() );
1108  background.setRadiiMapUnitScale( mShapeRadiusUnitWidget->getMapUnitScale() );
1109 
1110  background.setFillColor( mShapeFillColorBtn->color() );
1111  background.setStrokeColor( mShapeStrokeColorBtn->color() );
1112  background.setStrokeWidth( mShapeStrokeWidthSpnBx->value() );
1113  background.setStrokeWidthUnit( mShapeStrokeWidthUnitWidget->unit() );
1114  background.setStrokeWidthMapUnitScale( mShapeStrokeWidthUnitWidget->getMapUnitScale() );
1115  background.setOpacity( mBackgroundOpacityWidget->opacity() );
1116  background.setBlendMode( mShapeBlendCmbBx->blendMode() );
1117  if ( mBackgroundEffect && ( !QgsPaintEffectRegistry::isDefaultStack( mBackgroundEffect.get() ) || mBackgroundEffect->enabled() ) )
1118  background.setPaintEffect( mBackgroundEffect->clone() );
1119  else
1120  background.setPaintEffect( nullptr );
1121  background.setMarkerSymbol( mBackgroundMarkerSymbolButton->clonedSymbol< QgsMarkerSymbol >() );
1122  background.setFillSymbol( mBackgroundFillSymbolButton->clonedSymbol< QgsFillSymbol >() );
1123  format.setBackground( background );
1124 
1125  // drop shadow
1126  QgsTextShadowSettings shadow;
1127  shadow.setEnabled( mShadowDrawChkBx->isChecked() );
1128  shadow.setShadowPlacement( static_cast< QgsTextShadowSettings::ShadowPlacement >( mShadowUnderCmbBx->currentData().toInt() ) );
1129  shadow.setOffsetAngle( mShadowOffsetAngleSpnBx->value() );
1130  shadow.setOffsetDistance( mShadowOffsetSpnBx->value() );
1131  shadow.setOffsetUnit( mShadowOffsetUnitWidget->unit() );
1132  shadow.setOffsetMapUnitScale( mShadowOffsetUnitWidget->getMapUnitScale() );
1133  shadow.setOffsetGlobal( mShadowOffsetGlobalChkBx->isChecked() );
1134  shadow.setBlurRadius( mShadowRadiusDblSpnBx->value() );
1135  shadow.setBlurRadiusUnit( mShadowRadiusUnitWidget->unit() );
1136  shadow.setBlurRadiusMapUnitScale( mShadowRadiusUnitWidget->getMapUnitScale() );
1137  shadow.setBlurAlphaOnly( mShadowRadiusAlphaChkBx->isChecked() );
1138  shadow.setOpacity( mShadowOpacityWidget->opacity() );
1139  shadow.setScale( mShadowScaleSpnBx->value() );
1140  shadow.setColor( mShadowColorBtn->color() );
1141  shadow.setBlendMode( mShadowBlendCmbBx->blendMode() );
1142  format.setShadow( shadow );
1143 
1144  if ( includeDataDefinedProperties )
1146 
1147  return format;
1148 }
1149 
1151 {
1152  if ( mWidgetMode != Labeling )
1153  {
1154  // we need to combine any data defined properties from the text format with existing ones from the label settings
1155  const QgsPropertyCollection formatProps = format.dataDefinedProperties();
1156  for ( const int key : formatProps.propertyKeys() )
1157  {
1158  if ( formatProps.isActive( key ) )
1159  {
1160  mDataDefinedProperties.setProperty( key, formatProps.property( key ) );
1161  }
1162  }
1163  }
1164 
1166 }
1167 
1169 {
1170  return mContext;
1171 }
1172 
1174 {
1175  if ( mButtons.contains( key ) )
1176  {
1177  QgsPropertyOverrideButton *button = mButtons[ key ];
1178  button->updateFieldLists();
1179  button->setToProperty( QgsProperty() );
1181  }
1182 }
1183 
1184 void QgsTextFormatWidget::optionsStackedWidget_CurrentChanged( int indx )
1185 {
1186  mLabelingOptionsListWidget->blockSignals( true );
1187  mLabelingOptionsListWidget->setCurrentRow( indx );
1188  mLabelingOptionsListWidget->blockSignals( false );
1189 }
1190 
1192 {
1193  mContext = context;
1194 
1195  if ( auto *lExpressionContext = mContext.expressionContext() )
1196  {
1197  mPreviewExpressionContext = *lExpressionContext;
1198  if ( mLayer )
1199  mPreviewExpressionContext.appendScope( QgsExpressionContextUtils::layerScope( mLayer ) );
1200  }
1201 
1202  const auto symbolButtonWidgets = findChildren<QgsSymbolButton *>();
1203  for ( QgsSymbolButton *symbolWidget : symbolButtonWidgets )
1204  {
1205  symbolWidget->setMapCanvas( mContext.mapCanvas() );
1206  symbolWidget->setMessageBar( mContext.messageBar() );
1207  }
1208 }
1209 
1210 void QgsTextFormatWidget::collapseSample( bool collapse )
1211 {
1212  if ( collapse )
1213  {
1214  QList<int> splitSizes = mFontPreviewSplitter->sizes();
1215  if ( splitSizes[0] > groupBox_mPreview->height() )
1216  {
1217  const int delta = splitSizes[0] - groupBox_mPreview->height();
1218  splitSizes[0] -= delta;
1219  splitSizes[1] += delta;
1220  mFontPreviewSplitter->setSizes( splitSizes );
1221  }
1222  }
1223 }
1224 
1225 void QgsTextFormatWidget::changeTextColor( const QColor &color )
1226 {
1227  Q_UNUSED( color )
1228  updatePreview();
1229 }
1230 
1231 void QgsTextFormatWidget::updateFont( const QFont &font )
1232 {
1233  // update background reference font
1234  if ( font != mRefFont )
1235  {
1236  mRefFont = font;
1237  }
1238 
1239  // test if font is actually available
1240  // NOTE: QgsFontUtils::fontMatchOnSystem may fail here, just crosscheck family
1241  mFontMissingLabel->setVisible( !QgsFontUtils::fontFamilyMatchOnSystem( mRefFont.family() ) );
1242 
1243  mDirectSymbLeftLineEdit->setFont( mRefFont );
1244  mDirectSymbRightLineEdit->setFont( mRefFont );
1245 
1246  blockFontChangeSignals( true );
1247  mFontFamilyCmbBx->setCurrentFont( mRefFont );
1248  populateFontStyleComboBox();
1249  mFontUnderlineBtn->setChecked( mRefFont.underline() );
1250  mFontStrikethroughBtn->setChecked( mRefFont.strikeOut() );
1251  mKerningCheckBox->setChecked( mRefFont.kerning() );
1252  blockFontChangeSignals( false );
1253 
1254  // update font name with font face
1255 // font.setPixelSize( 24 );
1256 
1257  updatePreview();
1258 }
1259 
1260 void QgsTextFormatWidget::blockFontChangeSignals( bool blk )
1261 {
1262  mFontFamilyCmbBx->blockSignals( blk );
1263  mFontStyleComboBox->blockSignals( blk );
1264  mFontCapitalsComboBox->blockSignals( blk );
1265  mFontUnderlineBtn->blockSignals( blk );
1266  mFontStrikethroughBtn->blockSignals( blk );
1267  mFontWordSpacingSpinBox->blockSignals( blk );
1268  mFontLetterSpacingSpinBox->blockSignals( blk );
1269  mKerningCheckBox->blockSignals( blk );
1270 }
1271 
1273 {
1274  // In dock mode we don't have a preview we
1275  // just let stuff know we have changed because
1276  // there might be live updates connected.
1277  if ( mDockMode )
1278  {
1279  emit widgetChanged();
1280  return;
1281  }
1282 
1283  scrollPreview();
1284  lblFontPreview->setFormat( format() );
1285 }
1286 
1287 void QgsTextFormatWidget::scrollPreview()
1288 {
1289  scrollArea_mPreview->ensureVisible( 0, 0, 0, 0 );
1290 }
1291 
1293 {
1294  mPreviewBackgroundColor = color;
1295 
1296  scrollArea_mPreview->widget()->setStyleSheet( QStringLiteral( "background: rgb(%1, %2, %3);" ).arg( QString::number( color.red() ),
1297  QString::number( color.green() ),
1298  QString::number( color.blue() ) ) );
1299 }
1300 
1301 void QgsTextFormatWidget::changeBufferColor( const QColor &color )
1302 {
1303  Q_UNUSED( color )
1304  updatePreview();
1305 }
1306 
1308 {
1309  const QgsWkbTypes::GeometryType currentGeometryType = labelGeometryType();
1310  bool showLineFrame = false;
1311  bool showCentroidFrame = false;
1312  bool showQuadrantFrame = false;
1313  bool showFixedQuadrantFrame = false;
1314  bool showPlacementPriorityFrame = false;
1315  bool showOffsetTypeFrame = false;
1316  bool showOffsetFrame = false;
1317  bool showDistanceFrame = false;
1318  bool showRotationFrame = false;
1319  bool showMaxCharAngleFrame = false;
1320 
1321  const QgsPalLayerSettings::Placement currentPlacement = static_cast< QgsPalLayerSettings::Placement >( mPlacementModeComboBox->currentData().toInt() );
1322  const bool showPolygonPlacementOptions = ( currentGeometryType == QgsWkbTypes::PolygonGeometry && currentPlacement != QgsPalLayerSettings::Line && currentPlacement != QgsPalLayerSettings::PerimeterCurved && currentPlacement != QgsPalLayerSettings::OutsidePolygons );
1323 
1324  bool enableMultiLinesFrame = true;
1325 
1326  if ( currentPlacement == QgsPalLayerSettings::AroundPoint
1327  && ( currentGeometryType == QgsWkbTypes::PointGeometry || currentGeometryType == QgsWkbTypes::PolygonGeometry ) )
1328  {
1329  showCentroidFrame = currentGeometryType == QgsWkbTypes::PolygonGeometry;
1330  showDistanceFrame = true;
1331  //showRotationFrame = true; // TODO: uncomment when supported
1332  showQuadrantFrame = currentGeometryType == QgsWkbTypes::PointGeometry;
1333  }
1334  else if ( currentPlacement == QgsPalLayerSettings::OverPoint
1335  && ( currentGeometryType == QgsWkbTypes::PointGeometry || currentGeometryType == QgsWkbTypes::PolygonGeometry ) )
1336  {
1337  showCentroidFrame = currentGeometryType == QgsWkbTypes::PolygonGeometry;
1338  showQuadrantFrame = true;
1339  showFixedQuadrantFrame = true;
1340  showOffsetFrame = true;
1341  showRotationFrame = true;
1342  }
1343  else if ( currentGeometryType == QgsWkbTypes::PointGeometry && currentPlacement == QgsPalLayerSettings::OrderedPositionsAroundPoint )
1344  {
1345  showDistanceFrame = true;
1346  showPlacementPriorityFrame = true;
1347  showOffsetTypeFrame = true;
1348  }
1349  else if ( ( currentGeometryType == QgsWkbTypes::LineGeometry && currentPlacement == QgsPalLayerSettings::Line )
1350  || ( currentGeometryType == QgsWkbTypes::PolygonGeometry && currentPlacement == QgsPalLayerSettings::Line )
1351  || ( currentGeometryType == QgsWkbTypes::LineGeometry && currentPlacement == QgsPalLayerSettings::Curved )
1352  || ( currentGeometryType == QgsWkbTypes::PolygonGeometry && currentPlacement == QgsPalLayerSettings::PerimeterCurved ) )
1353  {
1354  showLineFrame = true;
1355  showDistanceFrame = true;
1356  //showRotationFrame = true; // TODO: uncomment when supported
1357 
1358  const bool offline = chkLineAbove->isChecked() || chkLineBelow->isChecked();
1359  chkLineOrientationDependent->setEnabled( offline );
1360  mPlacementDistanceFrame->setEnabled( offline );
1361 
1362  const bool isCurved = ( currentGeometryType == QgsWkbTypes::LineGeometry && currentPlacement == QgsPalLayerSettings::Curved )
1363  || ( currentGeometryType == QgsWkbTypes::PolygonGeometry && currentPlacement == QgsPalLayerSettings::PerimeterCurved );
1364  showMaxCharAngleFrame = isCurved;
1365  // TODO: enable mMultiLinesFrame when supported for curved labels
1366  enableMultiLinesFrame = !isCurved;
1367  }
1368  else if ( currentGeometryType == QgsWkbTypes::PolygonGeometry
1369  && ( currentPlacement == QgsPalLayerSettings::OutsidePolygons || mCheckAllowLabelsOutsidePolygons->isChecked() || mAllowOutsidePolygonsDDBtn->isActive() ) )
1370  {
1371  showDistanceFrame = true;
1372  }
1373 
1374  mPlacementLineFrame->setVisible( showLineFrame );
1375  mPlacementPolygonFrame->setVisible( showPolygonPlacementOptions );
1376  mPlacementCentroidFrame->setVisible( showCentroidFrame );
1377  mPlacementQuadrantFrame->setVisible( showQuadrantFrame );
1378  mPlacementFixedQuadrantFrame->setVisible( showFixedQuadrantFrame );
1379  mPlacementCartographicFrame->setVisible( showPlacementPriorityFrame );
1380  mPlacementOffsetFrame->setVisible( showOffsetFrame );
1381  mPlacementDistanceFrame->setVisible( showDistanceFrame );
1382  mPlacementOffsetTypeFrame->setVisible( showOffsetTypeFrame );
1383  mPlacementRotationFrame->setVisible( showRotationFrame );
1384  mPlacementRepeatGroupBox->setVisible( currentGeometryType == QgsWkbTypes::LineGeometry || ( currentGeometryType == QgsWkbTypes::PolygonGeometry &&
1385  ( currentPlacement == QgsPalLayerSettings::Line || currentPlacement == QgsPalLayerSettings::PerimeterCurved ) ) );
1386  mPlacementOverrunGroupBox->setVisible( currentGeometryType == QgsWkbTypes::LineGeometry && currentPlacement != QgsPalLayerSettings::Horizontal );
1387  mLineAnchorGroupBox->setVisible( currentGeometryType == QgsWkbTypes::LineGeometry );
1388  mPlacementMaxCharAngleFrame->setVisible( showMaxCharAngleFrame );
1389 
1390  mMultiLinesFrame->setEnabled( enableMultiLinesFrame );
1391 
1392 
1393  QString helperText;
1394  switch ( currentPlacement )
1395  {
1397  if ( currentGeometryType == QgsWkbTypes::PointGeometry )
1398  helperText = tr( "Arranges label candidates in a clockwise circle around the feature, preferring placements to the top-right of the feature." );
1399  else if ( currentGeometryType == QgsWkbTypes::PolygonGeometry )
1400  helperText = tr( "Arranges label candidates in a cluster around the feature's centroid, preferring placements directly over the centroid." );
1401  break;
1403  if ( currentGeometryType == QgsWkbTypes::PointGeometry )
1404  helperText = tr( "Arranges label candidates directly over the feature or at a preset offset from the feature." );
1405  else if ( currentGeometryType == QgsWkbTypes::PolygonGeometry )
1406  helperText = tr( "Arranges label candidates directly over the feature's centroid, or at a preset offset from the centroid." );
1407  break;
1409  if ( currentGeometryType == QgsWkbTypes::LineGeometry )
1410  helperText = tr( "Arranges label candidates parallel to a generalised line representing the feature. Placements which fall over straighter portions of the line are preferred." );
1411  else if ( currentGeometryType == QgsWkbTypes::PolygonGeometry )
1412  helperText = tr( "Arranges label candidates parallel to a generalised line representing the polygon's perimeter. Placements which fall over straighter portions of the perimeter are preferred." );
1413  break;
1415  if ( currentGeometryType == QgsWkbTypes::LineGeometry )
1416  helperText = tr( "Arranges candidates following the curvature of a line feature. Placements which fall over straighter portions of the line are preferred." );
1417  break;
1419  if ( currentGeometryType == QgsWkbTypes::PolygonGeometry )
1420  helperText = tr( "Arranges label candidates scattered throughout the polygon. Labels will always be placed horizontally, with placements further from the edges of the polygon preferred." );
1421  else if ( currentGeometryType == QgsWkbTypes::LineGeometry )
1422  helperText = tr( "Label candidates are arranged horizontally along the length of the feature." );
1423  break;
1425  if ( currentGeometryType == QgsWkbTypes::PolygonGeometry )
1426  helperText = tr( "Arranges label candidates scattered throughout the polygon. Labels are rotated to respect the polygon's orientation, with placements further from the edges of the polygon preferred." );
1427  break;
1429  if ( currentGeometryType == QgsWkbTypes::PointGeometry )
1430  helperText = tr( "Label candidates are placed in predefined positions around the features. Preference is given to positions with greatest cartographic appeal, e.g., top right and bottom right of the feature." );
1431  break;
1433  if ( currentGeometryType == QgsWkbTypes::PolygonGeometry )
1434  helperText = tr( "Arranges candidates following the curvature of the feature's perimeter. Placements which fall over straighter portions of the perimeter are preferred." );
1435  break;
1437  if ( currentGeometryType == QgsWkbTypes::PolygonGeometry )
1438  helperText = tr( "Label candidates are placed outside of the features, preferring placements which give greatest visual association between the label and the feature." );
1439  break;
1440  }
1441  mPlacementModeDescriptionLabel->setText( QStringLiteral( "<i>%1</i>" ).arg( helperText ) );
1442 }
1443 
1444 void QgsTextFormatWidget::populateFontCapitalsComboBox()
1445 {
1446  mFontCapitalsComboBox->addItem( tr( "No Change" ), static_cast< int >( Qgis::Capitalization::MixedCase ) );
1447  mFontCapitalsComboBox->addItem( tr( "All Uppercase" ), static_cast< int >( Qgis::Capitalization::AllUppercase ) );
1448  mFontCapitalsComboBox->addItem( tr( "All Lowercase" ), static_cast< int >( Qgis::Capitalization::AllLowercase ) );
1449 #if defined(HAS_KDE_QT5_SMALL_CAPS_FIX) || QT_VERSION >= QT_VERSION_CHECK(6, 3, 0)
1450  // Requires new enough build due to
1451  // https://bugreports.qt.io/browse/QTBUG-13965
1452  mFontCapitalsComboBox->addItem( tr( "Small Caps" ), static_cast< int >( Qgis::Capitalization::SmallCaps ) );
1453  mFontCapitalsComboBox->addItem( tr( "All Small Caps" ), static_cast< int >( Qgis::Capitalization::AllSmallCaps ) );
1454 #endif
1455  mFontCapitalsComboBox->addItem( tr( "Title Case" ), static_cast< int >( Qgis::Capitalization::TitleCase ) );
1456  mFontCapitalsComboBox->addItem( tr( "Force First Letter to Capital" ), static_cast< int >( Qgis::Capitalization::ForceFirstLetterToCapital ) );
1457 }
1458 
1459 void QgsTextFormatWidget::populateFontStyleComboBox()
1460 {
1461  mFontStyleComboBox->clear();
1462  const QStringList styles = mFontDB.styles( mRefFont.family() );
1463  const auto constStyles = styles;
1464  for ( const QString &style : constStyles )
1465  {
1466  mFontStyleComboBox->addItem( style );
1467  }
1468 
1469  QString targetStyle = mFontDB.styleString( mRefFont );
1470  if ( !styles.contains( targetStyle ) )
1471  {
1472  const QFont f = QFont( mRefFont.family() );
1473  targetStyle = QFontInfo( f ).styleName();
1474  mRefFont.setStyleName( targetStyle );
1475  }
1476  int curIndx = 0;
1477  const int stylIndx = mFontStyleComboBox->findText( targetStyle );
1478  if ( stylIndx > -1 )
1479  {
1480  curIndx = stylIndx;
1481  }
1482 
1483  mFontStyleComboBox->setCurrentIndex( curIndx );
1484 }
1485 
1486 void QgsTextFormatWidget::mFontSizeSpinBox_valueChanged( double d )
1487 {
1488  mRefFont.setPointSizeF( d );
1489  updateFont( mRefFont );
1490 }
1491 
1492 void QgsTextFormatWidget::mFontFamilyCmbBx_currentFontChanged( const QFont &f )
1493 {
1494  mRefFont.setFamily( f.family() );
1495  updateFont( mRefFont );
1496 }
1497 
1498 void QgsTextFormatWidget::mFontStyleComboBox_currentIndexChanged( const QString &text )
1499 {
1500  QgsFontUtils::updateFontViaStyle( mRefFont, text );
1501  updateFont( mRefFont );
1502 }
1503 
1504 void QgsTextFormatWidget::mFontUnderlineBtn_toggled( bool ckd )
1505 {
1506  mRefFont.setUnderline( ckd );
1507  updateFont( mRefFont );
1508 }
1509 
1510 void QgsTextFormatWidget::mFontStrikethroughBtn_toggled( bool ckd )
1511 {
1512  mRefFont.setStrikeOut( ckd );
1513  updateFont( mRefFont );
1514 }
1515 
1516 void QgsTextFormatWidget::kerningToggled( bool checked )
1517 {
1518  mRefFont.setKerning( checked );
1519  updateFont( mRefFont );
1520 }
1521 
1522 void QgsTextFormatWidget::mFontWordSpacingSpinBox_valueChanged( double spacing )
1523 {
1524  mRefFont.setWordSpacing( spacing );
1525  updateFont( mRefFont );
1526 }
1527 
1528 void QgsTextFormatWidget::mFontLetterSpacingSpinBox_valueChanged( double spacing )
1529 {
1530  mRefFont.setLetterSpacing( QFont::AbsoluteSpacing, spacing );
1531  updateFont( mRefFont );
1532 }
1533 
1534 void QgsTextFormatWidget::mFontSizeUnitWidget_changed()
1535 {
1536  // disable pixel size limiting for labels defined in points
1537  if ( mFontSizeUnitWidget->unit() != QgsUnitTypes::RenderMapUnits )
1538  {
1539  mFontLimitPixelChkBox->setChecked( false );
1540  }
1541  else if ( mMinPixelLimit == 0 )
1542  {
1543  // initial minimum trigger value set, turn on pixel size limiting by default
1544  // for labels defined in map units (ignored after first settings save)
1545  mFontLimitPixelChkBox->setChecked( true );
1546  }
1547  updateFont( mRefFont );
1548 }
1549 
1550 void QgsTextFormatWidget::mFontMinPixelSpinBox_valueChanged( int px )
1551 {
1552  // ensure max font pixel size for map unit labels can't be lower than min
1553  mFontMaxPixelSpinBox->setMinimum( px );
1554  mFontMaxPixelSpinBox->update();
1555 }
1556 
1557 void QgsTextFormatWidget::mFontMaxPixelSpinBox_valueChanged( int px )
1558 {
1559  // ensure max font pixel size for map unit labels can't be lower than min
1560  if ( px < mFontMinPixelSpinBox->value() )
1561  {
1562  mFontMaxPixelSpinBox->blockSignals( true );
1563  mFontMaxPixelSpinBox->setValue( mFontMinPixelSpinBox->value() );
1564  mFontMaxPixelSpinBox->blockSignals( false );
1565  }
1566  mFontMaxPixelSpinBox->setMinimum( mFontMinPixelSpinBox->value() );
1567 }
1568 
1569 void QgsTextFormatWidget::mBufferUnitWidget_changed()
1570 {
1571  updateFont( mRefFont );
1572 }
1573 
1574 void QgsTextFormatWidget::mMaskBufferUnitWidget_changed()
1575 {
1576  updateFont( mRefFont );
1577 }
1578 
1579 void QgsTextFormatWidget::mCoordXDDBtn_changed()
1580 {
1581  updateDataDefinedAlignment();
1582 }
1583 
1584 void QgsTextFormatWidget::mCoordXDDBtn_activated( bool isActive )
1585 {
1586  if ( !isActive )
1587  return;
1588 
1589  mCoordPointDDBtn->setActive( false );
1590 }
1591 
1592 void QgsTextFormatWidget::mCoordYDDBtn_changed()
1593 {
1594  updateDataDefinedAlignment();
1595 }
1596 
1597 void QgsTextFormatWidget::mCoordYDDBtn_activated( bool isActive )
1598 {
1599  if ( !isActive )
1600  return;
1601 
1602  mCoordPointDDBtn->setActive( false );
1603 }
1604 
1605 void QgsTextFormatWidget::mCoordPointDDBtn_changed()
1606 {
1607  updateDataDefinedAlignment();
1608 }
1609 
1610 void QgsTextFormatWidget::mCoordPointDDBtn_activated( bool isActive )
1611 {
1612  if ( !isActive )
1613  return;
1614 
1615  mCoordXDDBtn->setActive( false );
1616  mCoordYDDBtn->setActive( false );
1617 }
1618 
1619 void QgsTextFormatWidget::mShapeTypeCmbBx_currentIndexChanged( int )
1620 {
1621  // shape background
1622  const QgsTextBackgroundSettings::ShapeType type = static_cast< QgsTextBackgroundSettings::ShapeType >( mShapeTypeCmbBx->currentData().toInt() );
1624  const bool isSVG = type == QgsTextBackgroundSettings::ShapeSVG;
1625  const bool isMarker = type == QgsTextBackgroundSettings::ShapeMarkerSymbol;
1626 
1627  showBackgroundRadius( isRect );
1628 
1629  mShapeSVGPathFrame->setVisible( isSVG );
1630  mBackgroundMarkerSymbolButton->setVisible( isMarker );
1631  mBackgroundFillSymbolButton->setVisible( !isSVG && !isMarker );
1632 
1633  // symbology SVG and marker renderers only support size^2 scaling,
1634  // so we only use the x size spinbox
1635  mShapeSizeYLabel->setVisible( !isSVG && !isMarker );
1636  mShapeSizeYSpnBx->setVisible( !isSVG && !isMarker );
1637  mShapeSizeYDDBtn->setVisible( !isSVG && !isMarker );
1638  mShapeSizeXLabel->setText( tr( "Size%1" ).arg( !isSVG && !isMarker ? tr( " X" ) : QString() ) );
1639 
1640  // SVG parameter setting doesn't support color's alpha component yet
1641  mShapeFillColorBtn->setAllowOpacity( !isSVG );
1642  mShapeFillColorBtn->setButtonBackground();
1643  mShapeStrokeColorBtn->setAllowOpacity( !isSVG );
1644  mShapeStrokeColorBtn->setButtonBackground();
1645 
1646  // Hide parameter widgets not used by marker symbol
1647  mShapeFillColorLabel->setVisible( isSVG );
1648  mShapeFillColorLabel->setEnabled( isSVG );
1649  mShapeFillColorBtn->setVisible( isSVG );
1650  mShapeFillColorBtn->setEnabled( isSVG );
1651  mShapeFillColorDDBtn->setVisible( isSVG );
1652  mShapeFillColorDDBtn->setEnabled( isSVG );
1653  mShapeStrokeColorLabel->setVisible( isSVG );
1654  mShapeStrokeColorLabel->setEnabled( isSVG );
1655  mShapeStrokeColorBtn->setVisible( isSVG );
1656  mShapeStrokeColorBtn->setEnabled( isSVG );
1657  mShapeStrokeColorDDBtn->setVisible( isSVG );
1658  mShapeStrokeColorDDBtn->setEnabled( isSVG );
1659  mShapeStrokeWidthLabel->setVisible( isSVG );
1660  mShapeStrokeWidthLabel->setEnabled( isSVG );
1661  mShapeStrokeWidthSpnBx->setVisible( isSVG );
1662  mShapeStrokeWidthSpnBx->setEnabled( isSVG );
1663  mShapeStrokeWidthDDBtn->setVisible( isSVG );
1664  mShapeStrokeWidthDDBtn->setEnabled( isSVG );
1665 
1666  // configure SVG parameter widgets
1667  mShapeSVGParamsBtn->setVisible( isSVG );
1668  if ( isSVG )
1669  {
1670  updateSvgWidgets( mShapeSVGPathLineEdit->text() );
1671  }
1672  // TODO: fix overriding SVG symbol's stroke width units in QgsSvgCache
1673  // currently broken, fall back to symbol units only
1674  mShapeSVGUnitsLabel->setVisible( isSVG );
1675  mShapeStrokeWidthUnitWidget->setVisible( false );
1676  mShapeStrokeUnitsDDBtn->setVisible( false );
1677  mShapeStrokeUnitsDDBtn->setEnabled( false );
1678 
1679  updateAvailableShadowPositions();
1680 }
1681 
1682 void QgsTextFormatWidget::mShapeSVGPathLineEdit_textChanged( const QString &text )
1683 {
1684  updateSvgWidgets( text );
1685 }
1686 
1688 {
1689  const int numOptionsChecked = ( chkLineAbove->isChecked() ? 1 : 0 ) +
1690  ( chkLineBelow->isChecked() ? 1 : 0 ) +
1691  ( chkLineOn->isChecked() ? 1 : 0 );
1692 
1693  if ( numOptionsChecked == 1 )
1694  {
1695  //prevent unchecking last option
1696  chkLineAbove->setEnabled( !chkLineAbove->isChecked() );
1697  chkLineBelow->setEnabled( !chkLineBelow->isChecked() );
1698  chkLineOn->setEnabled( !chkLineOn->isChecked() );
1699  }
1700  else
1701  {
1702  chkLineAbove->setEnabled( true );
1703  chkLineBelow->setEnabled( true );
1704  chkLineOn->setEnabled( true );
1705  }
1706 }
1707 
1708 void QgsTextFormatWidget::onSubstitutionsChanged( const QgsStringReplacementCollection &substitutions )
1709 {
1710  mSubstitutions = substitutions;
1711  emit widgetChanged();
1712 }
1713 
1714 void QgsTextFormatWidget::previewScaleChanged( double scale )
1715 {
1716  lblFontPreview->setScale( scale );
1717 }
1718 
1719 void QgsTextFormatWidget::updateSvgWidgets( const QString &svgPath )
1720 {
1721  if ( mShapeSVGPathLineEdit->text() != svgPath )
1722  {
1723  mShapeSVGPathLineEdit->setText( svgPath );
1724  }
1725 
1726  QString resolvedPath;
1727  bool validSVG = true;
1728  if ( ! svgPath.startsWith( QLatin1String( "base64:" ), Qt::CaseInsensitive ) )
1729  {
1730  resolvedPath = QgsSymbolLayerUtils::svgSymbolNameToPath( svgPath, QgsProject::instance()->pathResolver() );
1731  validSVG = QFileInfo::exists( resolvedPath );
1732  }
1733  else
1734  {
1735  resolvedPath = svgPath;
1736  validSVG = true;
1737  }
1738 
1739  // draw red text for path field if invalid (path can't be resolved)
1740  mShapeSVGPathLineEdit->setStyleSheet( !validSVG ? QStringLiteral( "QLineEdit{ color: rgb(225, 0, 0); }" ) : QString() );
1741  mShapeSVGPathLineEdit->setToolTip( !validSVG ? tr( "File not found" ) : resolvedPath );
1742 
1743  QColor fill, stroke;
1744  double strokeWidth = 0.0;
1745  bool fillParam = false, strokeParam = false, strokeWidthParam = false;
1746  if ( validSVG )
1747  {
1748  QgsApplication::svgCache()->containsParams( resolvedPath, fillParam, fill, strokeParam, stroke, strokeWidthParam, strokeWidth );
1749  }
1750 
1751  mShapeSVGParamsBtn->setEnabled( validSVG && ( fillParam || strokeParam || strokeWidthParam ) );
1752 
1753  mShapeFillColorLabel->setEnabled( validSVG && fillParam );
1754  mShapeFillColorBtn->setEnabled( validSVG && fillParam );
1755  mShapeFillColorDDBtn->setEnabled( validSVG && fillParam );
1756  if ( mLoadSvgParams && validSVG && fillParam )
1757  mShapeFillColorBtn->setColor( fill );
1758 
1759  mShapeStrokeColorLabel->setEnabled( validSVG && strokeParam );
1760  mShapeStrokeColorBtn->setEnabled( validSVG && strokeParam );
1761  mShapeStrokeColorDDBtn->setEnabled( validSVG && strokeParam );
1762  if ( mLoadSvgParams && validSVG && strokeParam )
1763  mShapeStrokeColorBtn->setColor( stroke );
1764 
1765  mShapeStrokeWidthLabel->setEnabled( validSVG && strokeWidthParam );
1766  mShapeStrokeWidthSpnBx->setEnabled( validSVG && strokeWidthParam );
1767  mShapeStrokeWidthDDBtn->setEnabled( validSVG && strokeWidthParam );
1768  if ( mLoadSvgParams && validSVG && strokeWidthParam )
1769  mShapeStrokeWidthSpnBx->setValue( strokeWidth );
1770 
1771  // TODO: fix overriding SVG symbol's stroke width units in QgsSvgCache
1772  // currently broken, fall back to symbol's
1773  //mShapeStrokeWidthUnitWidget->setEnabled( validSVG && strokeWidthParam );
1774  //mShapeStrokeUnitsDDBtn->setEnabled( validSVG && strokeWidthParam );
1775  mShapeSVGUnitsLabel->setEnabled( validSVG && strokeWidthParam );
1776 }
1777 
1778 void QgsTextFormatWidget::updateAvailableShadowPositions()
1779 {
1780  if ( mShadowUnderCmbBx->count() == 0
1781  || ( mShadowUnderCmbBx->findData( QgsTextShadowSettings::ShadowShape ) > -1 && mShapeTypeCmbBx->currentData().toInt() == QgsTextBackgroundSettings::ShapeMarkerSymbol )
1782  || ( mShadowUnderCmbBx->findData( QgsTextShadowSettings::ShadowShape ) == -1 && mShapeTypeCmbBx->currentData().toInt() != QgsTextBackgroundSettings::ShapeMarkerSymbol ) )
1783  {
1784  // showing invalid choices, have to rebuild the list
1785  const QgsTextShadowSettings::ShadowPlacement currentPlacement = static_cast< QgsTextShadowSettings::ShadowPlacement >( mShadowUnderCmbBx->currentData().toInt() );
1786  mShadowUnderCmbBx->clear();
1787 
1788  mShadowUnderCmbBx->addItem( tr( "Lowest Label Component" ), QgsTextShadowSettings::ShadowLowest );
1789  mShadowUnderCmbBx->addItem( tr( "Text" ), QgsTextShadowSettings::ShadowText );
1790  mShadowUnderCmbBx->addItem( tr( "Buffer" ), QgsTextShadowSettings::ShadowBuffer );
1791  if ( mShapeTypeCmbBx->currentData().toInt() != QgsTextBackgroundSettings::ShapeMarkerSymbol )
1792  mShadowUnderCmbBx->addItem( tr( "Background" ), QgsTextShadowSettings::ShadowShape ); // not supported for marker symbol background shapes
1793 
1794  mShadowUnderCmbBx->setCurrentIndex( mShadowUnderCmbBx->findData( currentPlacement ) );
1795  if ( mShadowUnderCmbBx->currentIndex() == -1 )
1796  mShadowUnderCmbBx->setCurrentIndex( 0 );
1797  }
1798 }
1799 
1800 void QgsTextFormatWidget::updateProperty()
1801 {
1802  QgsPropertyOverrideButton *button = qobject_cast<QgsPropertyOverrideButton *>( sender() );
1803  const QgsPalLayerSettings::Property key = static_cast< QgsPalLayerSettings::Property >( button->propertyKey() );
1804  mDataDefinedProperties.setProperty( key, button->toProperty() );
1805  updatePreview();
1806 }
1807 
1808 void QgsTextFormatWidget::createAuxiliaryField()
1809 {
1810  if ( !mLayer )
1811  return;
1812 
1813  // try to create an auxiliary layer if not yet created
1814  if ( !mLayer->auxiliaryLayer() )
1815  {
1816  QgsNewAuxiliaryLayerDialog dlg( mLayer, this );
1817  dlg.exec();
1818  }
1819 
1820  // return if still not exists
1821  if ( !mLayer->auxiliaryLayer() )
1822  return;
1823 
1824  QgsPropertyOverrideButton *button = qobject_cast<QgsPropertyOverrideButton *>( sender() );
1825  const QgsPalLayerSettings::Property key = static_cast< QgsPalLayerSettings::Property >( button->propertyKey() );
1827 
1828  // create property in auxiliary storage if necessary
1829  if ( !mLayer->auxiliaryLayer()->exists( def ) )
1831 
1832  // update property with join field name from auxiliary storage
1833  QgsProperty property = button->toProperty();
1834  property.setField( QgsAuxiliaryLayer::nameFromProperty( def, true ) );
1835  property.setActive( true );
1836  button->updateFieldLists();
1837  button->setToProperty( property );
1838  mDataDefinedProperties.setProperty( key, button->toProperty() );
1839  updatePreview();
1840  emit auxiliaryFieldCreated();
1841 }
1842 
1843 
1844 void QgsTextFormatWidget::updateShapeFrameStatus()
1845 {
1846  mShapeFrame->setEnabled( mShapeDrawDDBtn->isActive() || mShapeDrawChkBx->isChecked() );
1847 }
1848 
1849 void QgsTextFormatWidget::updateBufferFrameStatus()
1850 {
1851  mBufferFrame->setEnabled( mBufferDrawDDBtn->isActive() || mBufferDrawChkBx->isChecked() );
1852 }
1853 
1854 void QgsTextFormatWidget::updateShadowFrameStatus()
1855 {
1856  mShadowFrame->setEnabled( mShadowDrawDDBtn->isActive() || mShadowDrawChkBx->isChecked() );
1857 }
1858 
1859 void QgsTextFormatWidget::updateCalloutFrameStatus()
1860 {
1861  mCalloutFrame->setEnabled( mCalloutDrawDDBtn->isActive() || mCalloutsDrawCheckBox->isChecked() );
1862 }
1863 
1864 void QgsTextFormatWidget::updateDataDefinedAlignment()
1865 {
1866  // no data defined alignment without data defined position
1867  mCoordAlignmentFrame->setEnabled( ( mCoordXDDBtn->isActive() && mCoordYDDBtn->isActive() )
1868  || mCoordPointDDBtn->isActive() );
1869 }
1870 
1872 {
1873  switch ( type )
1874  {
1877  case QgsStyle::TagEntity:
1881  return;
1882 
1884  {
1885  if ( !QgsStyle::defaultStyle()->textFormatNames().contains( name ) )
1886  return;
1887 
1888  const QgsTextFormat newFormat = QgsStyle::defaultStyle()->textFormat( name );
1889  setFormat( newFormat );
1890  break;
1891  }
1892 
1894  {
1895  if ( !QgsStyle::defaultStyle()->labelSettingsNames().contains( name ) )
1896  return;
1897 
1898  const QgsTextFormat newFormat = QgsStyle::defaultStyle()->labelSettings( name ).format();
1899  setFormat( newFormat );
1900  break;
1901  }
1902  }
1903 }
1904 
1906 {
1907  QgsStyle *style = QgsStyle::defaultStyle();
1908  if ( !style )
1909  return;
1910 
1912  saveDlg.setDefaultTags( mTextFormatsListWidget->currentTagFilter() );
1913  if ( !saveDlg.exec() )
1914  return;
1915 
1916  if ( saveDlg.name().isEmpty() )
1917  return;
1918 
1919  // check if there is no format with same name
1920  if ( style->textFormatNames().contains( saveDlg.name() ) )
1921  {
1922  const int res = QMessageBox::warning( this, tr( "Save Text Format" ),
1923  tr( "Format with name '%1' already exists. Overwrite?" )
1924  .arg( saveDlg.name() ),
1925  QMessageBox::Yes | QMessageBox::No );
1926  if ( res != QMessageBox::Yes )
1927  {
1928  return;
1929  }
1930  style->removeTextFormat( saveDlg.name() );
1931  }
1932 
1933  const QStringList symbolTags = saveDlg.tags().split( ',' );
1934 
1935  const QgsTextFormat newFormat = format();
1936  style->addTextFormat( saveDlg.name(), newFormat );
1937  style->saveTextFormat( saveDlg.name(), newFormat, saveDlg.isFavorite(), symbolTags );
1938 }
1939 
1940 void QgsTextFormatWidget::mShapeSVGSelectorBtn_clicked()
1941 {
1942  QgsSvgSelectorDialog svgDlg( this );
1943  svgDlg.setWindowTitle( tr( "Select SVG file" ) );
1944  svgDlg.svgSelector()->setSvgPath( mShapeSVGPathLineEdit->text().trimmed() );
1945 
1946  if ( svgDlg.exec() == QDialog::Accepted )
1947  {
1948  const QString svgPath = svgDlg.svgSelector()->currentSvgPath();
1949  if ( !svgPath.isEmpty() )
1950  {
1951  mShapeSVGPathLineEdit->setText( svgPath );
1952  updatePreview();
1953  }
1954  }
1955 }
1956 
1957 void QgsTextFormatWidget::mShapeSVGParamsBtn_clicked()
1958 {
1959  const QString svgPath = mShapeSVGPathLineEdit->text();
1960  mLoadSvgParams = true;
1961  updateSvgWidgets( svgPath );
1962  mLoadSvgParams = false;
1963 }
1964 
1965 void QgsTextFormatWidget::mShapeRotationCmbBx_currentIndexChanged( int index )
1966 {
1967  mShapeRotationDblSpnBx->setEnabled( static_cast< QgsTextBackgroundSettings::RotationType >( index ) != QgsTextBackgroundSettings::RotationSync );
1968  mShapeRotationDDBtn->setEnabled( static_cast< QgsTextBackgroundSettings::RotationType >( index ) != QgsTextBackgroundSettings::RotationSync );
1969 }
1970 
1971 void QgsTextFormatWidget::mPreviewTextEdit_textChanged( const QString &text )
1972 {
1973  lblFontPreview->setText( text );
1974  updatePreview();
1975 }
1976 
1977 void QgsTextFormatWidget::mPreviewTextBtn_clicked()
1978 {
1979  mPreviewTextEdit->setText( QStringLiteral( "Lorem Ipsum" ) );
1980  updatePreview();
1981 }
1982 
1983 void QgsTextFormatWidget::mPreviewBackgroundBtn_colorChanged( const QColor &color )
1984 {
1985  setPreviewBackground( color );
1986 }
1987 
1988 void QgsTextFormatWidget::mDirectSymbLeftToolBtn_clicked()
1989 {
1990  bool gotChar = false;
1991 
1992  const QChar initial = !mDirectSymbLeftLineEdit->text().isEmpty() ? mDirectSymbLeftLineEdit->text().at( 0 ) : QChar();
1993  const QChar dirSymb = mCharDlg->selectCharacter( &gotChar, mRefFont, mFontDB.styleString( mRefFont ), initial );
1994 
1995  if ( !gotChar )
1996  return;
1997 
1998  if ( !dirSymb.isNull() )
1999  mDirectSymbLeftLineEdit->setText( QString( dirSymb ) );
2000 }
2001 
2002 void QgsTextFormatWidget::mDirectSymbRightToolBtn_clicked()
2003 {
2004  bool gotChar = false;
2005  const QChar initial = !mDirectSymbRightLineEdit->text().isEmpty() ? mDirectSymbRightLineEdit->text().at( 0 ) : QChar();
2006  const QChar dirSymb = mCharDlg->selectCharacter( &gotChar, mRefFont, mFontDB.styleString( mRefFont ), initial );
2007 
2008  if ( !gotChar )
2009  return;
2010 
2011  if ( !dirSymb.isNull() )
2012  mDirectSymbRightLineEdit->setText( QString( dirSymb ) );
2013 }
2014 
2015 void QgsTextFormatWidget::chkLineOrientationDependent_toggled( bool active )
2016 {
2017  if ( active )
2018  {
2019  chkLineAbove->setText( tr( "Left of line" ) );
2020  chkLineBelow->setText( tr( "Right of line" ) );
2021  }
2022  else
2023  {
2024  chkLineAbove->setText( tr( "Above line" ) );
2025  chkLineBelow->setText( tr( "Below line" ) );
2026  }
2027 }
2028 
2029 
2030 void QgsTextFormatWidget::mToolButtonConfigureSubstitutes_clicked()
2031 {
2033  if ( panel && panel->dockMode() )
2034  {
2036  widget->setPanelTitle( tr( "Substitutions" ) );
2037  widget->setSubstitutions( mSubstitutions );
2038  connect( widget, &QgsSubstitutionListWidget::substitutionsChanged, this, &QgsTextFormatWidget::onSubstitutionsChanged );
2039  panel->openPanel( widget );
2040  return;
2041  }
2042 
2043  QgsSubstitutionListDialog dlg( this );
2044  dlg.setSubstitutions( mSubstitutions );
2045  if ( dlg.exec() == QDialog::Accepted )
2046  {
2047  mSubstitutions = dlg.substitutions();
2048  emit widgetChanged();
2049  }
2050 }
2051 
2052 void QgsTextFormatWidget::showBackgroundRadius( bool show )
2053 {
2054  mShapeRadiusLabel->setVisible( show );
2055  mShapeRadiusXDbSpnBx->setVisible( show );
2056 
2057  mShapeRadiusYDbSpnBx->setVisible( show );
2058 
2059  mShapeRadiusUnitWidget->setVisible( show );
2060 
2061  mShapeRadiusDDBtn->setVisible( show );
2062  mShapeRadiusUnitsDDBtn->setVisible( show );
2063 }
2064 
2066 {
2067  if ( auto *lExpressionContext = mContext.expressionContext() )
2068  return *lExpressionContext;
2069 
2070  QgsExpressionContext expContext;
2074  if ( mMapCanvas )
2076 
2077  if ( mLayer )
2079 
2080  //TODO - show actual value
2081  expContext.setOriginalValueVariable( QVariant() );
2083 
2084  return expContext;
2085 }
2086 
2088 {
2089  if ( mGeometryGeneratorGroupBox->isChecked() )
2090  return mGeometryGeneratorType->currentData().value<QgsWkbTypes::GeometryType>();
2091  else if ( mLayer )
2092  return mLayer->geometryType();
2093  else
2094  return mGeomType;
2095 }
2096 
2097 
2098 //
2099 // QgsTextFormatDialog
2100 //
2101 
2102 QgsTextFormatDialog::QgsTextFormatDialog( const QgsTextFormat &format, QgsMapCanvas *mapCanvas, QWidget *parent, Qt::WindowFlags fl, QgsVectorLayer *layer )
2103  : QDialog( parent, fl )
2104 {
2105  setWindowTitle( tr( "Text Settings" ) );
2106 
2107  mFormatWidget = new QgsTextFormatWidget( format, mapCanvas, this, layer );
2108  mFormatWidget->layout()->setContentsMargins( 0, 0, 0, 0 );
2109 
2110  QVBoxLayout *layout = new QVBoxLayout( this );
2111  layout->addWidget( mFormatWidget );
2112 
2113  mButtonBox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Help, Qt::Horizontal, this );
2114  layout->addWidget( mButtonBox );
2115 
2116  setLayout( layout );
2118 
2119  connect( mButtonBox->button( QDialogButtonBox::Ok ), &QAbstractButton::clicked, this, &QDialog::accept );
2120  connect( mButtonBox->button( QDialogButtonBox::Cancel ), &QAbstractButton::clicked, this, &QDialog::reject );
2121  connect( mButtonBox->button( QDialogButtonBox::Help ), &QAbstractButton::clicked, this, &QgsTextFormatDialog::showHelp );
2122 }
2123 
2125 {
2126  return mFormatWidget->format();
2127 }
2128 
2129 void QgsTextFormatDialog::showHelp()
2130 {
2131  QgsHelp::openHelp( QStringLiteral( "style_library/label_settings.html#formatting-the-label-text" ) );
2132 }
2133 
2135 {
2136  mFormatWidget->setContext( context );
2137 }
2138 
2139 QDialogButtonBox *QgsTextFormatDialog::buttonBox() const
2140 {
2141  return mButtonBox;
2142 }
2143 
2145  : QgsPanelWidgetWrapper( new QgsTextFormatWidget( format, mapCanvas, nullptr, layer ), parent )
2146 {
2147  mFormatWidget = qobject_cast< QgsTextFormatWidget * >( widget() );
2148  connect( mFormatWidget, &QgsTextFormatWidget::widgetChanged, this, [ = ]
2149  {
2150  if ( !mBlockSignals )
2151  emit widgetChanged();
2152  } );
2153 }
2154 
2156 {
2157  return mFormatWidget->format();
2158 }
2159 
2161 {
2162  mBlockSignals = true;
2163  mFormatWidget->setFormat( format );
2164  mBlockSignals = false;
2165 }
2166 
2168 {
2169  mFormatWidget->setContext( context );
2170 }
2171 
2173 {
2174  mFormatWidget->setDockMode( dockMode );
2176 }
Capitalization
String capitalization options.
Definition: qgis.h:1236
@ AllSmallCaps
Force all characters to small caps (since QGIS 3.24)
@ MixedCase
Mixed case, ie no change.
@ AllLowercase
Convert all characters to lowercase.
@ TitleCase
Simple title case conversion - does not fully grammatically parse the text and uses simple rules only...
@ SmallCaps
Mixed case small caps (since QGIS 3.24)
@ ForceFirstLetterToCapital
Convert just the first letter of each word to uppercase, leave the rest untouched.
@ AllUppercase
Convert all characters to uppercase.
@ Marker
Marker symbol.
@ Fill
Fill symbol.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
static QgsSvgCache * svgCache()
Returns the application's SVG cache, used for caching SVG images and handling parameter replacement w...
bool addAuxiliaryField(const QgsPropertyDefinition &definition)
Adds an auxiliary field for the given property.
static QString nameFromProperty(const QgsPropertyDefinition &def, bool joined=false)
Returns the name of the auxiliary field for a property definition.
bool exists(const QgsPropertyDefinition &definition) const
Returns true if the property is stored in the layer already, false otherwise.
A dialog for selecting a single character from a single font.
QChar selectCharacter(bool *gotChar, const QFont &font, const QString &style, QChar initialSelection=QChar())
Opens the dialog modally and returns when the user has selected a character.
A QGIS expression editor based on QScintilla2.
void collapsedStateChanged(bool collapsed)
Signal emitted when groupbox collapsed/expanded state is changed, and when first shown.
A groupbox that collapses/expands when toggled and can save its collapsed and checked states.
A cross platform button subclass for selecting colors.
void colorChanged(const QColor &color)
Emitted whenever a new color is set for the button.
void changed()
Emitted when the paint effect properties change.
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 * 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.
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of 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.
The QgsFieldExpressionWidget class reates a widget to choose fields and edit expressions It contains ...
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
Definition: qgsfillsymbol.h:30
QgsFillSymbol * clone() const override
Returns a deep copy of this symbol.
static bool fontFamilyMatchOnSystem(const QString &family, QString *chosen=nullptr, bool *match=nullptr)
Check whether font family is on system.
static bool updateFontViaStyle(QFont &f, const QString &fontstyle, bool fallback=false)
Updates font with named style and retain all font properties.
static void enableAutoGeometryRestore(QWidget *widget, const QString &key=QString())
Register the widget to allow its position to be automatically saved and restored when open and closed...
Definition: qgsgui.cpp:174
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition: qgshelp.cpp:36
static QIcon iconForWkbType(QgsWkbTypes::Type type)
Returns the icon for a vector layer whose geometry type is provided.
@ SymbolLeftRight
Place direction symbols on left/right of label.
@ SymbolAbove
Place direction symbols on above label.
@ SymbolBelow
Place direction symbols on below label.
static void warning(const QString &msg)
Goes to qWarning.
Definition: qgslogger.cpp:122
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:90
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
double scale() const
Returns the calculated map scale.
QgsUnitTypes::DistanceUnit mapUnits() const
Returns the units of the map's geographical coordinates - used for scale calculation.
A marker symbol type, for rendering Point and MultiPoint geometries.
QgsMarkerSymbol * clone() const override
Returns a deep copy of this symbol.
A dialog to create a new auxiliary layer.
A widget for setting an opacity value.
static QgsPaintEffect * defaultStack()
Returns a new effect stack consisting of a sensible selection of default effects.
static bool isDefaultStack(QgsPaintEffect *effect)
Tests whether a paint effect matches the default effects stack.
@ ShowDefined
Show upside down when rotation is layer- or data-defined.
@ Upright
Upside-down labels (90 <= angle < 270) are shown upright.
@ ShowAll
Show upside down for all labels, including dynamic ones.
Placement
Placement modes which determine how label candidates are generated for a feature.
@ PerimeterCurved
Arranges candidates following the curvature of a polygon's boundary. Applies to polygon layers only.
@ Curved
Arranges candidates following the curvature of a line feature. Applies to line layers only.
@ Horizontal
Arranges horizontal candidates scattered throughout a polygon feature. Applies to polygon layers only...
@ Free
Arranges candidates scattered throughout a polygon feature. Candidates are rotated to respect the pol...
@ OverPoint
Arranges candidates over a point (or centroid of a polygon), or at a preset offset from the point....
@ 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'...
@ OrderedPositionsAroundPoint
Candidates are placed in predefined positions around a point. Preference is given to positions with g...
@ OutsidePolygons
Candidates are placed outside of polygon boundaries. Applies to polygon layers only....
Property
Data definable properties.
@ MaskEnabled
Whether the mask is enabled.
@ LabelRotation
Label rotation.
@ PositionY
Y-coordinate data defined label position.
@ OverrunDistance
Distance which labels can extend past either end of linear features.
@ Strikeout
Use strikeout.
@ FontStyle
Font style name.
@ PositionX
X-coordinate data defined label position.
@ CalloutDraw
Show callout.
@ Underline
Use underline.
@ FontLetterSpacing
Letter spacing.
@ MaskJoinStyle
Mask join style.
@ PositionPoint
Point-coordinate data defined label position.
@ Bold
Use bold style.
@ Hali
Horizontal alignment for data defined label position (Left, Center, Right)
@ FontStretchFactor
Font stretch factor, since QGIS 3.24.
@ MaskBufferUnit
Mask buffer size unit.
@ LabelAllParts
Whether all parts of multi-part features should be labeled.
@ ShadowOpacity
Shadow opacity.
@ BufferOpacity
Buffer opacity.
@ ShapeOpacity
Shape opacity.
@ FontSizeUnit
Font size units.
@ Italic
Use italic style.
@ FontWordSpacing
Word spacing.
@ MaskBufferSize
Mask buffer size.
@ MinimumScale
Minimum map scale (ie most "zoomed out")
@ FontBlendMode
Text blend mode.
@ MaximumScale
Maximum map scale (ie most "zoomed in")
@ MaskOpacity
Mask opacity.
@ Family
Font family.
@ PolygonLabelOutside
Whether labels outside a polygon feature are permitted, or should be forced (since QGIS 3....
@ FontCase
Label text case.
@ LinePlacementOptions
Line placement flags.
@ Vali
Vertical alignment for data defined label position (Bottom, Base, Half, Cap, Top)
@ FontOpacity
Text opacity.
@ FromPoint
Offset distance applies from point geometry.
@ FromSymbolBounds
Offset distance applies from rendered symbol bounds.
const QgsTextFormat & format() const
Returns the label text formatting settings, e.g., font settings, buffer settings, etc.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the labeling property definitions.
Wrapper widget for existing widgets which can't have the inheritance tree changed,...
QWidget * widget()
Returns the internal widget that is wrapped in this panel.
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 ...
void widgetChanged()
Emitted when the widget state changes.
static QgsPanelWidget * findParentPanel(QWidget *widget)
Traces through the parents of a widget to find if it is contained within a QgsPanelWidget widget.
void setPanelTitle(const QString &panelTitle)
Set the title of the panel when shown in the interface.
virtual void setDockMode(bool dockMode)
Set the widget in dock mode which tells the widget to emit panel widgets and not open dialogs.
bool dockMode()
Returns the dock mode state.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:470
A grouped map of multiple QgsProperty objects, each referenced by a integer key value.
QgsProperty property(int key) const override
Returns a matching property from the collection, if one exists.
void setProperty(int key, const QgsProperty &property)
Adds a property to the collection and takes ownership of it.
QSet< int > propertyKeys() const override
Returns a list of property keys contained within the collection.
bool isActive(int key) const override
Returns true if the collection contains an active property with the specified key.
Definition for a property.
Definition: qgsproperty.h:47
A button for controlling property overrides which may apply to a widget.
QgsProperty toProperty() const
Returns a QgsProperty object encapsulating the current state of the widget.
void updateFieldLists()
Updates list of fields.
void changed()
Emitted when property definition changes.
void activated(bool isActive)
Emitted when the activated status of the widget changes.
void init(int propertyKey, const QgsProperty &property, const QgsPropertiesDefinition &definitions, const QgsVectorLayer *layer=nullptr, bool auxiliaryStorageEnabled=false)
Initialize a newly constructed property button (useful if button was included in a UI layout).
void registerExpressionContextGenerator(QgsExpressionContextGenerator *generator)
Register an expression context generator class that will be used to retrieve an expression context fo...
int propertyKey() const
Returns the property key linked to the button.
void setToProperty(const QgsProperty &property)
Sets the widget to reflect the current state of a QgsProperty.
void createAuxiliaryField()
Emitted when creating a new auxiliary field.
A store for object properties.
Definition: qgsproperty.h:231
void setField(const QString &field)
Sets the field name the property references.
A combobox which lets the user select map scale from predefined list and highlights nearest to curren...
void scaleChanged(double scale)
Emitted when user has finished editing/selecting a new scale.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:62
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
bool contains(const QString &key, QgsSettings::Section section=QgsSettings::NoSection) const
Returns true if there exists a setting called key; returns false otherwise.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
A collection of string replacements (specified using QgsStringReplacement objects).
void selectionChanged(const QString &name, QgsStyle::StyleEntity type)
Emitted when the selected item is changed in the widget.
void saveEntity()
Emitted when the user has opted to save a new entity to the style database, by clicking the "Save" bu...
a dialog for setting properties of a newly saved style.
bool isFavorite() const
Returns true if the favorite is checked for the symbol.
QString name() const
Returns the entered name for the new symbol.
void setDefaultTags(const QString &tags)
Sets the default tags for the newly created item.
QString tags() const
Returns any tags entered for the new symbol (as a comma separated value list).
QgsTextFormat textFormat(const QString &name) const
Returns the text format with the specified name.
Definition: qgsstyle.cpp:2125
QgsTextFormat defaultTextFormat(QgsStyle::TextFormatContext context=QgsStyle::TextFormatContext::Labeling) const
Returns the default text format to use for new text based objects in the specified context.
Definition: qgsstyle.cpp:1231
QStringList textFormatNames() const
Returns a list of names of text formats in the style.
Definition: qgsstyle.cpp:2135
bool removeTextFormat(const QString &name)
Removes a text format from the style.
Definition: qgsstyle.cpp:996
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()
Returns default application-wide style.
Definition: qgsstyle.cpp:131
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:324
QgsPalLayerSettings labelSettings(const QString &name) const
Returns the label settings with the specified name.
Definition: qgsstyle.cpp:2145
bool saveTextFormat(const QString &name, const QgsTextFormat &format, bool favorite, const QStringList &tags)
Adds a text format to the database.
Definition: qgsstyle.cpp:960
A dialog which allows users to specify a list of substitutions to apply to a string,...
A widget which allows users to specify a list of substitutions to apply to a string,...
void setSubstitutions(const QgsStringReplacementCollection &substitutions)
Sets the list of substitutions to show in the widget.
void substitutionsChanged(const QgsStringReplacementCollection &substitutions)
Emitted when the substitution definitions change.
void containsParams(const QString &path, bool &hasFillParam, QColor &defaultFillColor, bool &hasStrokeParam, QColor &defaultStrokeColor, bool &hasStrokeWidthParam, double &defaultStrokeWidth, bool blocking=false) const
Tests if an SVG file contains parameters for fill, stroke color, stroke width.
A button for creating and modifying QgsSymbol settings.
static QString svgSymbolNameToPath(const QString &name, const QgsPathResolver &pathResolver)
Determines an SVG symbol's path from its name.
Contains settings which reflect the context in which a symbol (or renderer) widget is shown,...
QgsExpressionContext * expressionContext() const
Returns the expression context used for the widget, if set.
QgsMapCanvas * mapCanvas() const
Returns the map canvas associated with the widget.
QgsMessageBar * messageBar() const
Returns the message bar associated with the widget.
static QgsSymbol * defaultSymbol(QgsWkbTypes::GeometryType geomType)
Returns a new default symbol for the specified geometry type.
Definition: qgssymbol.cpp:355
Container for settings relating to a text background object.
QgsMapUnitScale strokeWidthMapUnitScale() const
Returns the map unit scale object for the shape stroke width.
void setFillSymbol(QgsFillSymbol *symbol)
Sets the current fill symbol for the background shape.
RotationType rotationType() const
Returns the method used for rotating the background shape.
QString svgFile() const
Returns the absolute path to the background SVG file, if set.
QSizeF size() const
Returns the size of the background shape.
QSizeF radii() const
Returns the radii used for rounding the corners of shapes.
QgsMapUnitScale radiiMapUnitScale() const
Returns the map unit scale object for the shape radii.
void setOpacity(double opacity)
Sets the background shape's opacity.
void setStrokeColor(const QColor &color)
Sets the color used for outlining the background shape.
QgsUnitTypes::RenderUnit strokeWidthUnit() const
Returns the units used for the shape's stroke width.
void setSizeMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale object for the shape size.
QPainter::CompositionMode blendMode() const
Returns the blending mode used for drawing the background shape.
SizeType
Methods for determining the background shape size.
bool enabled() const
Returns whether the background is enabled.
void setRadiiUnit(QgsUnitTypes::RenderUnit units)
Sets the units used for the shape's radii.
double opacity() const
Returns the background shape's opacity.
void setStrokeWidthMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale object for the shape stroke width.
QgsUnitTypes::RenderUnit offsetUnit() const
Returns the units used for the shape's offset.
double rotation() const
Returns the rotation for the background shape, in degrees clockwise.
QColor fillColor() const
Returns the color used for filing the background shape.
void setMarkerSymbol(QgsMarkerSymbol *symbol)
Sets the current marker symbol for the background shape.
void setRadii(QSizeF radii)
Sets the radii used for rounding the corners of shapes.
SizeType sizeType() const
Returns the method used to determine the size of the background shape (e.g., fixed size or buffer aro...
ShapeType type() const
Returns the type of background shape (e.g., square, ellipse, SVG).
double strokeWidth() const
Returns the width of the shape's stroke (stroke).
void setSizeType(SizeType type)
Sets the method used to determine the size of the background shape (e.g., fixed size or buffer around...
ShapeType
Background shape types.
@ ShapeSquare
Square - buffered sizes only.
void setFillColor(const QColor &color)
Sets the color used for filing the background shape.
void setPaintEffect(QgsPaintEffect *effect)
Sets the current paint effect for the background shape.
void setStrokeWidthUnit(QgsUnitTypes::RenderUnit units)
Sets the units used for the shape's stroke width.
QColor strokeColor() const
Returns the color used for outlining the background shape.
void setRotationType(RotationType type)
Sets the method used for rotating the background shape.
void setOffsetMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale object for the shape offset.
QgsFillSymbol * fillSymbol() const
Returns the fill symbol to be rendered in the background.
void setBlendMode(QPainter::CompositionMode mode)
Sets the blending mode used for drawing the background shape.
QgsMapUnitScale sizeMapUnitScale() const
Returns the map unit scale object for the shape size.
void setType(ShapeType type)
Sets the type of background shape to draw (e.g., square, ellipse, SVG).
QgsUnitTypes::RenderUnit sizeUnit() const
Returns the units used for the shape's size.
RotationType
Methods for determining the rotation of the background shape.
@ RotationSync
Shape rotation is synced with text rotation.
QgsUnitTypes::RenderUnit radiiUnit() const
Returns the units used for the shape's radii.
void setEnabled(bool enabled)
Sets whether the text background will be drawn.
QgsMarkerSymbol * markerSymbol() const
Returns the marker symbol to be rendered in the background.
void setRadiiMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale object for the shape radii.
void setRotation(double rotation)
Sets the rotation for the background shape, in degrees clockwise.
void setOffset(QPointF offset)
Sets the offset used for drawing the background shape.
void setSize(QSizeF size)
Sets the size of the background shape.
void setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the units used for the shape's size.
const QgsPaintEffect * paintEffect() const
Returns the current paint effect for the background shape.
void setSvgFile(const QString &file)
Sets the path to the background SVG file.
QgsMapUnitScale offsetMapUnitScale() const
Returns the map unit scale object for the shape offset.
void setStrokeWidth(double width)
Sets the width of the shape's stroke (stroke).
QPointF offset() const
Returns the offset used for drawing the background shape.
void setOffsetUnit(QgsUnitTypes::RenderUnit units)
Sets the units used for the shape's offset.
Container for settings relating to a text buffer.
void setFillBufferInterior(bool fill)
Sets whether the interior of the buffer will be filled in.
void setBlendMode(QPainter::CompositionMode mode)
Sets the blending mode used for drawing the buffer.
Qt::PenJoinStyle joinStyle() const
Returns the buffer join style.
double size() const
Returns the size of the buffer.
void setColor(const QColor &color)
Sets the color for the buffer.
void setSizeMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale object for the buffer size.
void setOpacity(double opacity)
Sets the buffer opacity.
QgsMapUnitScale sizeMapUnitScale() const
Returns the map unit scale object for the buffer size.
bool enabled() const
Returns whether the buffer is enabled.
double opacity() const
Returns the buffer opacity.
bool fillBufferInterior() const
Returns whether the interior of the buffer will be filled in.
void setEnabled(bool enabled)
Sets whether the text buffer will be drawn.
QgsUnitTypes::RenderUnit sizeUnit() const
Returns the units for the buffer size.
void setPaintEffect(QgsPaintEffect *effect)
Sets the current paint effect for the buffer.
const QgsPaintEffect * paintEffect() const
Returns the current paint effect for the buffer.
QColor color() const
Returns the color of the buffer.
QPainter::CompositionMode blendMode() const
Returns the blending mode used for drawing the buffer.
void setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the units used for the buffer size.
void setJoinStyle(Qt::PenJoinStyle style)
Sets the join style used for drawing the buffer.
void setSize(double size)
Sets the size of the buffer.
QgsTextFormatDialog(const QgsTextFormat &format, QgsMapCanvas *mapCanvas=nullptr, QWidget *parent=nullptr, Qt::WindowFlags fl=QgsGuiUtils::ModalDialogFlags, QgsVectorLayer *layer=nullptr)
Constructor for QgsTextFormatDialog.
QgsTextFormat format() const
Returns the current formatting settings defined by the widget.
QDialogButtonBox * buttonBox() const
Returns a reference to the dialog's button box.
void setContext(const QgsSymbolWidgetContext &context)
Sets the context in which the widget is shown, e.g., the associated map canvas and expression context...
void setFormat(const QgsTextFormat &format)
Sets the format to show in the widget.
void setDockMode(bool dockMode) override
Set the widget in dock mode which tells the widget to emit panel widgets and not open dialogs.
QgsTextFormat format() const
Returns the current formatting settings defined by the widget.
void setContext(const QgsSymbolWidgetContext &context)
Sets the context in which the widget is shown, e.g., the associated map canvas and expression context...
QgsTextFormatPanelWidget(const QgsTextFormat &format, QgsMapCanvas *mapCanvas=nullptr, QWidget *parent=nullptr, QgsVectorLayer *layer=nullptr)
Constructor for QgsTextFormatPanelWidget.
A widget for customizing text formatting settings.
void updatePlacementWidgets()
Updates label placement options to reflect current state of widget.
QButtonGroup * mUpsidedownBtnGrp
Upside down labels button group.
QgsTextFormatWidget(const QgsTextFormat &format=QgsTextFormat(), QgsMapCanvas *mapCanvas=nullptr, QWidget *parent=nullptr, QgsVectorLayer *layer=nullptr)
Constructor for QgsTextFormatWidget.
int mMinPixelLimit
Pixel size font limit.
void setDockMode(bool enabled)
Sets whether the widget should be shown in a compact dock mode.
QgsMapCanvas * mMapCanvas
Associated map canvas.
QgsSymbolWidgetContext context() const
Returns the context in which the widget is shown, e.g., the associated map canvas and expression cont...
void deactivateField(QgsPalLayerSettings::Property key)
Deactivate a field from data defined properties and update the corresponding button.
void setFormat(const QgsTextFormat &format)
Sets the current formatting settings.
virtual void setFormatFromStyle(const QString &name, QgsStyle::StyleEntity type)
Sets the current text settings from a style entry.
QButtonGroup * mDirectSymbBtnGrp
Symbol direction button group.
void updateWidgetForFormat(const QgsTextFormat &format)
Updates the widget's state to reflect the settings in a QgsTextFormat.
QList< QgsSymbolLayerReference > mMaskedSymbolLayers
void widgetChanged()
Emitted when the text format defined by the widget changes.
void setPreviewBackground(const QColor &color)
Sets the background color for the text preview widget.
QButtonGroup * mQuadrantBtnGrp
Quadrant button group.
QgsWkbTypes::GeometryType labelGeometryType() const
Returns the geometry type which will be used by the labeling engine when registering labels for the l...
QgsWkbTypes::GeometryType mGeomType
Geometry type for layer, if known.
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
QgsSymbolWidgetContext mContext
Context in which widget is shown.
void updateLinePlacementOptions()
Updates line placement options to reflect current state of widget.
void populateDataDefinedButtons()
Sets up connections required for data defined buttons, or updates the existing definition of these bu...
virtual void setContext(const QgsSymbolWidgetContext &context)
Sets the context in which the widget is shown, e.g., the associated map canvas and expression context...
void updatePreview()
Updates the text preview.
void auxiliaryFieldCreated()
Emitted when an auxiliary field is created in the widget.
QgsStringReplacementCollection mSubstitutions
Text substitution list.
@ Text
Default mode, show text formatting settings only.
@ Labeling
Show labeling settings in addition to text formatting settings.
virtual void saveFormat()
Saves the current text settings to a style entry.
QgsPropertyCollection mDataDefinedProperties
Data defined properties as defined in the widget.
QgsVectorLayer * mLayer
Associated vector layer.
Container for all settings relating to text rendering.
Definition: qgstextformat.h:41
void setColor(const QColor &color)
Sets the color that text will be rendered in.
void setBlendMode(QPainter::CompositionMode mode)
Sets the blending mode used for drawing the text.
void setSize(double size)
Sets the size for rendered text.
QgsMapUnitScale sizeMapUnitScale() const
Returns the map unit scale object for the size.
void setCapitalization(Qgis::Capitalization capitalization)
Sets the text capitalization style.
void setDataDefinedProperties(const QgsPropertyCollection &collection)
Sets the format's property collection, used for data defined overrides.
void setFont(const QFont &font)
Sets the font used for rendering text.
double lineHeight() const
Returns the line height for text.
QgsUnitTypes::RenderUnit sizeUnit() const
Returns the units for the size of rendered text.
int stretchFactor() const
Returns the text's stretch factor.
void setOrientation(TextOrientation orientation)
Sets the orientation for the text.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the format's property collection, used for data defined overrides.
void setStretchFactor(int factor)
Sets the text's stretch factor.
void setShadow(const QgsTextShadowSettings &shadowSettings)
Sets the text's drop shadow settings.
void setMask(const QgsTextMaskSettings &maskSettings)
Sets the text's masking settings.
bool fontFound() const
Returns true if the specified font was found on the system, or false if the font was not found and a ...
void setPreviewBackgroundColor(const QColor &color)
Sets the background color that text will be rendered on for previews.
void setOpacity(double opacity)
Sets the text's opacity.
QPainter::CompositionMode blendMode() const
Returns the blending mode used for drawing the text.
TextOrientation orientation() const
Returns the orientation of the text.
void setAllowHtmlFormatting(bool allow)
Sets whether text should be treated as a HTML document and HTML tags should be used for formatting th...
Qgis::Capitalization capitalization() const
Returns the text capitalization style.
QString resolvedFontFamily() const
Returns the family for the resolved font, ie if the specified font was not found on the system this w...
QgsTextMaskSettings & mask()
Returns a reference to the masking settings.
bool isValid() const
Returns true if the format is valid.
void setBuffer(const QgsTextBufferSettings &bufferSettings)
Sets the text's buffer settings.
QgsTextBackgroundSettings & background()
Returns a reference to the text background settings.
TextOrientation
Text orientation.
Definition: qgstextformat.h:46
@ HorizontalOrientation
Vertically oriented text.
Definition: qgstextformat.h:47
@ RotationBasedOrientation
Horizontally or vertically oriented text based on rotation (only available for map labeling)
Definition: qgstextformat.h:49
@ VerticalOrientation
Horizontally oriented text.
Definition: qgstextformat.h:48
bool allowHtmlFormatting() const
Returns true if text should be treated as a HTML document and HTML tags should be used for formatting...
void setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the size of rendered text.
double opacity() const
Returns the text's opacity.
QString namedStyle() const
Returns the named style for the font used for rendering text (e.g., "bold").
double size() const
Returns the size for rendered text.
QgsTextShadowSettings & shadow()
Returns a reference to the text drop shadow settings.
void setBackground(const QgsTextBackgroundSettings &backgroundSettings)
Sets the text's background settings.q.
void setSizeMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale object for the size.
void setNamedStyle(const QString &style)
Sets the named style for the font used for rendering text.
QColor color() const
Returns the color that text will be rendered in.
QFont font() const
Returns the font used for rendering text.
QColor previewBackgroundColor() const
Returns the background color for text previews.
QgsTextBufferSettings & buffer()
Returns a reference to the text buffer settings.
void setLineHeight(double height)
Sets the line height for text.
Container for settings relating to a selective masking around a text.
void setEnabled(bool)
Returns whether the mask is enabled.
void setMaskedSymbolLayers(const QList< QgsSymbolLayerReference > &maskedLayers)
Sets the symbol layers that will be masked by this buffer.
QList< QgsSymbolLayerReference > maskedSymbolLayers() const
Returns a list of references to symbol layers that are masked by this buffer.
void setSize(double size)
Sets the size of the buffer.
QgsMapUnitScale sizeMapUnitScale() const
Returns the map unit scale object for the buffer size.
double size() const
Returns the size of the buffer.
void setSizeMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale object for the buffer size.
void setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the units used for the buffer size.
QgsPaintEffect * paintEffect() const
Returns the current paint effect for the mask.
void setJoinStyle(Qt::PenJoinStyle style)
Sets the join style used for drawing the buffer.
QgsUnitTypes::RenderUnit sizeUnit() const
Returns the units for the buffer size.
double opacity() const
Returns the mask's opacity.
bool enabled() const
Returns whether the mask is enabled.
void setPaintEffect(QgsPaintEffect *effect)
Sets the current paint effect for the mask.
Qt::PenJoinStyle joinStyle() const
Returns the buffer join style.
void setOpacity(double opacity)
Sets the mask's opacity.
Container for settings relating to a text shadow.
int offsetAngle() const
Returns the angle for offsetting the position of the shadow from the text.
void setBlurRadiusMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale object for the shadow blur radius.
bool enabled() const
Returns whether the shadow is enabled.
int scale() const
Returns the scaling used for the drop shadow (in percentage of original size).
void setShadowPlacement(QgsTextShadowSettings::ShadowPlacement placement)
Sets the placement for the drop shadow.
double opacity() const
Returns the shadow's opacity.
QgsMapUnitScale blurRadiusMapUnitScale() const
Returns the map unit scale object for the shadow blur radius.
void setOffsetMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale object for the shadow offset distance.
void setBlendMode(QPainter::CompositionMode mode)
Sets the blending mode used for drawing the drop shadow.
void setColor(const QColor &color)
Sets the color for the drop shadow.
QColor color() const
Returns the color of the drop shadow.
void setOffsetGlobal(bool global)
Sets whether the global shadow offset should be used.
ShadowPlacement
Placement positions for text shadow.
@ ShadowBuffer
Draw shadow under buffer.
@ ShadowShape
Draw shadow under background shape.
@ ShadowLowest
Draw shadow below all text components.
@ ShadowText
Draw shadow under text.
void setScale(int scale)
Sets the scaling used for the drop shadow (in percentage of original size).
void setBlurAlphaOnly(bool alphaOnly)
Sets whether only the alpha channel for the shadow should be blurred.
QgsTextShadowSettings::ShadowPlacement shadowPlacement() const
Returns the placement for the drop shadow.
double offsetDistance() const
Returns the distance for offsetting the position of the shadow from the text.
QPainter::CompositionMode blendMode() const
Returns the blending mode used for drawing the drop shadow.
void setOffsetDistance(double distance)
Sets the distance for offsetting the position of the shadow from the text.
void setOpacity(double opacity)
Sets the shadow's opacity.
QgsMapUnitScale offsetMapUnitScale() const
Returns the map unit scale object for the shadow offset distance.
QgsUnitTypes::RenderUnit blurRadiusUnit() const
Returns the units used for the shadow's blur radius.
bool blurAlphaOnly() const
Returns whether only the alpha channel for the shadow will be blurred.
bool offsetGlobal() const
Returns true if the global shadow offset will be used.
void setOffsetAngle(int angle)
Sets the angle for offsetting the position of the shadow from the text.
QgsUnitTypes::RenderUnit offsetUnit() const
Returns the units used for the shadow's offset.
void setBlurRadiusUnit(QgsUnitTypes::RenderUnit units)
Sets the units used for the shadow's blur radius.
double blurRadius() const
Returns the blur radius for the shadow.
void setBlurRadius(double blurRadius)
Sets the blur radius for the shadow.
void setOffsetUnit(QgsUnitTypes::RenderUnit units)
Sets the units used for the shadow's offset.
void setEnabled(bool enabled)
Sets whether the text shadow will be drawn.
A widget displaying a combobox allowing the user to choose between various display units,...
QList< QgsUnitTypes::RenderUnit > RenderUnitList
List of render units.
Definition: qgsunittypes.h:240
@ RenderMetersInMapUnits
Meters value as Map units.
Definition: qgsunittypes.h:176
@ RenderPercentage
Percentage of another measurement (e.g., canvas size, feature size)
Definition: qgsunittypes.h:172
@ RenderPoints
Points (e.g., for font sizes)
Definition: qgsunittypes.h:173
@ RenderPixels
Pixels.
Definition: qgsunittypes.h:171
@ RenderInches
Inches.
Definition: qgsunittypes.h:174
@ RenderMillimeters
Millimeters.
Definition: qgsunittypes.h:169
@ RenderMapUnits
Map units.
Definition: qgsunittypes.h:170
Represents a vector layer which manages a vector based data sets.
Q_INVOKABLE QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
QgsAuxiliaryLayer * auxiliaryLayer()
Returns the current auxiliary layer.
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
Definition: qgswkbtypes.h:141
QSize iconSize(bool dockableToolbar)
Returns the user-preferred size of a window's toolbar icons.
int scaleIconSize(int standardSize)
Scales an icon size to compensate for display pixel density, making the icon size hi-dpi friendly,...
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:1517