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