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