QGIS API Documentation  3.8.0-Zanzibar (11aff65)
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 
32 #include <QButtonGroup>
33 
34 QgsTextFormatWidget::QgsTextFormatWidget( const QgsTextFormat &format, QgsMapCanvas *mapCanvas, QWidget *parent )
35  : QWidget( parent )
36  , mMapCanvas( mapCanvas )
37 {
38  initWidget();
39  setWidgetMode( Text );
40  updateWidgetForFormat( format );
41 }
42 
43 QgsTextFormatWidget::QgsTextFormatWidget( QgsMapCanvas *mapCanvas, QWidget *parent, Mode mode )
44  : QWidget( parent )
45  , mWidgetMode( mode )
46  , mMapCanvas( mapCanvas )
47 {
48  initWidget();
49  setWidgetMode( mode );
50 }
51 
52 void QgsTextFormatWidget::initWidget()
53 {
54  setupUi( this );
55  connect( mShapeSVGPathLineEdit, &QLineEdit::textChanged, this, &QgsTextFormatWidget::mShapeSVGPathLineEdit_textChanged );
56  connect( mFontSizeSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsTextFormatWidget::mFontSizeSpinBox_valueChanged );
57  connect( mFontCapitalsComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsTextFormatWidget::mFontCapitalsComboBox_currentIndexChanged );
58  connect( mFontFamilyCmbBx, &QFontComboBox::currentFontChanged, this, &QgsTextFormatWidget::mFontFamilyCmbBx_currentFontChanged );
59  connect( mFontStyleComboBox, static_cast<void ( QComboBox::* )( const QString & )>( &QComboBox::currentIndexChanged ), this, &QgsTextFormatWidget::mFontStyleComboBox_currentIndexChanged );
60  connect( mFontUnderlineBtn, &QToolButton::toggled, this, &QgsTextFormatWidget::mFontUnderlineBtn_toggled );
61  connect( mFontStrikethroughBtn, &QToolButton::toggled, this, &QgsTextFormatWidget::mFontStrikethroughBtn_toggled );
62  connect( mFontWordSpacingSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsTextFormatWidget::mFontWordSpacingSpinBox_valueChanged );
63  connect( mFontLetterSpacingSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsTextFormatWidget::mFontLetterSpacingSpinBox_valueChanged );
64  connect( mFontSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsTextFormatWidget::mFontSizeUnitWidget_changed );
65  connect( mFontMinPixelSpinBox, static_cast < void ( QSpinBox::* )( int ) > ( &QSpinBox::valueChanged ), this, &QgsTextFormatWidget::mFontMinPixelSpinBox_valueChanged );
66  connect( mFontMaxPixelSpinBox, static_cast < void ( QSpinBox::* )( int ) > ( &QSpinBox::valueChanged ), this, &QgsTextFormatWidget::mFontMaxPixelSpinBox_valueChanged );
67  connect( mBufferUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsTextFormatWidget::mBufferUnitWidget_changed );
68  connect( mCoordXDDBtn, &QgsPropertyOverrideButton::activated, this, &QgsTextFormatWidget::mCoordXDDBtn_activated );
69  connect( mCoordYDDBtn, &QgsPropertyOverrideButton::activated, this, &QgsTextFormatWidget::mCoordYDDBtn_activated );
70  connect( mShapeTypeCmbBx, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsTextFormatWidget::mShapeTypeCmbBx_currentIndexChanged );
71  connect( mShapeRotationCmbBx, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsTextFormatWidget::mShapeRotationCmbBx_currentIndexChanged );
72  connect( mShapeSVGParamsBtn, &QPushButton::clicked, this, &QgsTextFormatWidget::mShapeSVGParamsBtn_clicked );
73  connect( mShapeSVGSelectorBtn, &QPushButton::clicked, this, &QgsTextFormatWidget::mShapeSVGSelectorBtn_clicked );
74  connect( mPreviewTextEdit, &QLineEdit::textChanged, this, &QgsTextFormatWidget::mPreviewTextEdit_textChanged );
75  connect( mPreviewTextBtn, &QToolButton::clicked, this, &QgsTextFormatWidget::mPreviewTextBtn_clicked );
76  connect( mPreviewBackgroundBtn, &QgsColorButton::colorChanged, this, &QgsTextFormatWidget::mPreviewBackgroundBtn_colorChanged );
77  connect( mDirectSymbLeftToolBtn, &QToolButton::clicked, this, &QgsTextFormatWidget::mDirectSymbLeftToolBtn_clicked );
78  connect( mDirectSymbRightToolBtn, &QToolButton::clicked, this, &QgsTextFormatWidget::mDirectSymbRightToolBtn_clicked );
79  connect( mChkNoObstacle, &QCheckBox::toggled, this, &QgsTextFormatWidget::mChkNoObstacle_toggled );
80  connect( chkLineOrientationDependent, &QCheckBox::toggled, this, &QgsTextFormatWidget::chkLineOrientationDependent_toggled );
81  connect( mToolButtonConfigureSubstitutes, &QToolButton::clicked, this, &QgsTextFormatWidget::mToolButtonConfigureSubstitutes_clicked );
82 
83  const int iconSize = QgsGuiUtils::scaleIconSize( 20 );
84  mOptionsTab->setIconSize( QSize( iconSize, iconSize ) );
85  const int iconSize32 = QgsGuiUtils::scaleIconSize( 32 );
86  const int iconSize24 = QgsGuiUtils::scaleIconSize( 24 );
87  const int iconSize18 = QgsGuiUtils::scaleIconSize( 18 );
88  mPointOffsetAboveLeft->setIconSize( QSize( iconSize32, iconSize18 ) );
89  mPointOffsetAbove->setIconSize( QSize( iconSize32, iconSize18 ) );
90  mPointOffsetAboveRight->setIconSize( QSize( iconSize32, iconSize18 ) );
91  mPointOffsetLeft->setIconSize( QSize( iconSize32, iconSize18 ) );
92  mPointOffsetOver ->setIconSize( QSize( iconSize32, iconSize18 ) );
93  mPointOffsetRight->setIconSize( QSize( iconSize32, iconSize18 ) );
94  mPointOffsetBelowLeft->setIconSize( QSize( iconSize32, iconSize18 ) );
95  mPointOffsetBelow->setIconSize( QSize( iconSize32, iconSize18 ) );
96  mPointOffsetBelowRight->setIconSize( QSize( iconSize32, iconSize18 ) );
97  mLabelMinScale->setPixmap( QgsApplication::getThemeIcon( QStringLiteral( "/mActionZoomOut.svg" ) ).pixmap( QSize( iconSize24, iconSize24 ) ) );
98  mLabelMaxScale->setPixmap( QgsApplication::getThemeIcon( QStringLiteral( "/mActionZoomIn.svg" ) ).pixmap( QSize( iconSize24, iconSize24 ) ) );
99 
100  const int buttonSize = QgsGuiUtils::scaleIconSize( 24 );
101  mFontUnderlineBtn->setMinimumSize( buttonSize, buttonSize );
102  mFontUnderlineBtn->setMaximumSize( buttonSize, buttonSize );
103  mFontStrikethroughBtn->setMinimumSize( buttonSize, buttonSize );
104  mFontStrikethroughBtn->setMaximumSize( buttonSize, buttonSize );
105  mFontBoldBtn->setMinimumSize( buttonSize, buttonSize );
106  mFontBoldBtn->setMaximumSize( buttonSize, buttonSize );
107  mFontItalicBtn->setMinimumSize( buttonSize, buttonSize );
108  mFontItalicBtn->setMaximumSize( buttonSize, buttonSize );
109 
110  mPreviewScaleComboBox->setMapCanvas( mMapCanvas );
111  mPreviewScaleComboBox->setShowCurrentScaleButton( true );
112  connect( mPreviewScaleComboBox, &QgsScaleWidget::scaleChanged, this, &QgsTextFormatWidget::previewScaleChanged );
113 
114  const auto unitWidgets = findChildren<QgsUnitSelectionWidget *>();
115  for ( QgsUnitSelectionWidget *unitWidget : unitWidgets )
116  {
117  unitWidget->setMapCanvas( mMapCanvas );
118  }
142 
143  mFontLineHeightSpinBox->setClearValue( 1.0 );
144  mShapeRotationDblSpnBx->setClearValue( 0.0 );
145  mShapeOffsetXSpnBx->setClearValue( 0.0 );
146  mShapeOffsetYSpnBx->setClearValue( 0.0 );
147  mPointOffsetXSpinBox->setClearValue( 0.0 );
148  mPointOffsetYSpinBox->setClearValue( 0.0 );
149  mPointAngleSpinBox->setClearValue( 0.0 );
150  mFontLetterSpacingSpinBox->setClearValue( 0.0 );
151  mFontWordSpacingSpinBox->setClearValue( 0.0 );
152  mZIndexSpinBox->setClearValue( 0.0 );
153  mLineDistanceSpnBx->setClearValue( 0.0 );
154 
155  mObstacleTypeComboBox->addItem( tr( "Over the feature's interior" ), QgsPalLayerSettings::PolygonInterior );
156  mObstacleTypeComboBox->addItem( tr( "Over the feature's boundary" ), QgsPalLayerSettings::PolygonBoundary );
157 
158  mOffsetTypeComboBox->addItem( tr( "From point" ), QgsPalLayerSettings::FromPoint );
159  mOffsetTypeComboBox->addItem( tr( "From symbol bounds" ), QgsPalLayerSettings::FromSymbolBounds );
160 
161  mCharDlg = new QgsCharacterSelectorDialog( this );
162 
163  mRefFont = lblFontPreview->font();
164 
165  // internal connections
166  connect( mShadowOffsetAngleDial, &QAbstractSlider::valueChanged, mShadowOffsetAngleSpnBx, &QSpinBox::setValue );
167  connect( mShadowOffsetAngleSpnBx, static_cast < void ( QSpinBox::* )( int ) > ( &QSpinBox::valueChanged ), mShadowOffsetAngleDial, &QAbstractSlider::setValue );
168  connect( mLimitLabelChkBox, &QAbstractButton::toggled, mLimitLabelSpinBox, &QWidget::setEnabled );
169  connect( mCheckBoxSubstituteText, &QAbstractButton::toggled, mToolButtonConfigureSubstitutes, &QWidget::setEnabled );
170 
171  //connections to prevent users removing all line placement positions
172  connect( chkLineAbove, &QAbstractButton::toggled, this, &QgsTextFormatWidget::updateLinePlacementOptions );
173  connect( chkLineBelow, &QAbstractButton::toggled, this, &QgsTextFormatWidget::updateLinePlacementOptions );
174  connect( chkLineOn, &QAbstractButton::toggled, this, &QgsTextFormatWidget::updateLinePlacementOptions );
175 
176  populateFontCapitalsComboBox();
177 
178  // color buttons
179  mPreviewBackgroundBtn->setColorDialogTitle( tr( "Select Fill Color" ) );
180  mPreviewBackgroundBtn->setContext( QStringLiteral( "labeling" ) );
181  mPreviewBackgroundBtn->setColor( QColor( 255, 255, 255 ) );
182  btnTextColor->setColorDialogTitle( tr( "Select Text Color" ) );
183  btnTextColor->setContext( QStringLiteral( "labeling" ) );
184  btnTextColor->setDefaultColor( Qt::black );
185  btnBufferColor->setColorDialogTitle( tr( "Select Buffer Color" ) );
186  btnBufferColor->setContext( QStringLiteral( "labeling" ) );
187  btnBufferColor->setDefaultColor( Qt::white );
188  mShapeStrokeColorBtn->setColorDialogTitle( tr( "Select Stroke Color" ) );
189  mShapeStrokeColorBtn->setContext( QStringLiteral( "labeling" ) );
190  mShapeFillColorBtn->setColorDialogTitle( tr( "Select Fill Color" ) );
191  mShapeFillColorBtn->setContext( QStringLiteral( "labeling" ) );
192  mShadowColorBtn->setColorDialogTitle( tr( "Select Shadow Color" ) );
193  mShadowColorBtn->setContext( QStringLiteral( "labeling" ) );
194  mShadowColorBtn->setDefaultColor( Qt::black );
195 
196  mFontColorDDBtn->registerLinkedWidget( btnTextColor );
197  mBufferColorDDBtn->registerLinkedWidget( btnBufferColor );
198  mShapeStrokeColorDDBtn->registerLinkedWidget( mShapeStrokeColorBtn );
199  mShapeFillColorDDBtn->registerLinkedWidget( mShapeFillColorBtn );
200  mShadowColorDDBtn->registerLinkedWidget( mShadowColorBtn );
201 
202  // set up quadrant offset button group
203  mQuadrantBtnGrp = new QButtonGroup( this );
204  mQuadrantBtnGrp->addButton( mPointOffsetAboveLeft, static_cast<int>( QgsPalLayerSettings::QuadrantAboveLeft ) );
205  mQuadrantBtnGrp->addButton( mPointOffsetAbove, static_cast<int>( QgsPalLayerSettings::QuadrantAbove ) );
206  mQuadrantBtnGrp->addButton( mPointOffsetAboveRight, static_cast<int>( QgsPalLayerSettings::QuadrantAboveRight ) );
207  mQuadrantBtnGrp->addButton( mPointOffsetLeft, static_cast<int>( QgsPalLayerSettings::QuadrantLeft ) );
208  mQuadrantBtnGrp->addButton( mPointOffsetOver, static_cast<int>( QgsPalLayerSettings::QuadrantOver ) );
209  mQuadrantBtnGrp->addButton( mPointOffsetRight, static_cast<int>( QgsPalLayerSettings::QuadrantRight ) );
210  mQuadrantBtnGrp->addButton( mPointOffsetBelowLeft, static_cast<int>( QgsPalLayerSettings::QuadrantBelowLeft ) );
211  mQuadrantBtnGrp->addButton( mPointOffsetBelow, static_cast<int>( QgsPalLayerSettings::QuadrantBelow ) );
212  mQuadrantBtnGrp->addButton( mPointOffsetBelowRight, static_cast<int>( QgsPalLayerSettings::QuadrantBelowRight ) );
213  mQuadrantBtnGrp->setExclusive( true );
214 
215  // setup direction symbol(s) button group
216  mDirectSymbBtnGrp = new QButtonGroup( this );
217  mDirectSymbBtnGrp->addButton( mDirectSymbRadioBtnLR, static_cast<int>( QgsPalLayerSettings::SymbolLeftRight ) );
218  mDirectSymbBtnGrp->addButton( mDirectSymbRadioBtnAbove, static_cast<int>( QgsPalLayerSettings::SymbolAbove ) );
219  mDirectSymbBtnGrp->addButton( mDirectSymbRadioBtnBelow, static_cast<int>( QgsPalLayerSettings::SymbolBelow ) );
220  mDirectSymbBtnGrp->setExclusive( true );
221 
222  // upside-down labels button group
223  mUpsidedownBtnGrp = new QButtonGroup( this );
224  mUpsidedownBtnGrp->addButton( mUpsidedownRadioOff, static_cast<int>( QgsPalLayerSettings::Upright ) );
225  mUpsidedownBtnGrp->addButton( mUpsidedownRadioDefined, static_cast<int>( QgsPalLayerSettings::ShowDefined ) );
226  mUpsidedownBtnGrp->addButton( mUpsidedownRadioAll, static_cast<int>( QgsPalLayerSettings::ShowAll ) );
227  mUpsidedownBtnGrp->setExclusive( true );
228 
229  //mShapeCollisionsChkBx->setVisible( false ); // until implemented
230 
231  // post updatePlacementWidgets() connections
232  connect( chkLineAbove, &QAbstractButton::toggled, this, &QgsTextFormatWidget::updatePlacementWidgets );
233  connect( chkLineBelow, &QAbstractButton::toggled, this, &QgsTextFormatWidget::updatePlacementWidgets );
234 
235  // setup point placement button group
236  mPlacePointBtnGrp = new QButtonGroup( this );
237  mPlacePointBtnGrp->addButton( radPredefinedOrder, static_cast<int>( QgsPalLayerSettings::OrderedPositionsAroundPoint ) );
238  mPlacePointBtnGrp->addButton( radAroundPoint, static_cast<int>( QgsPalLayerSettings::AroundPoint ) );
239  mPlacePointBtnGrp->addButton( radOverPoint, static_cast<int>( QgsPalLayerSettings::OverPoint ) );
240  mPlacePointBtnGrp->setExclusive( true );
241  connect( mPlacePointBtnGrp, static_cast<void ( QButtonGroup::* )( int )>( &QButtonGroup::buttonClicked ), this, &QgsTextFormatWidget::updatePlacementWidgets );
242 
243  // setup line placement button group (assigned enum id currently unused)
244  mPlaceLineBtnGrp = new QButtonGroup( this );
245  mPlaceLineBtnGrp->addButton( radLineParallel, static_cast<int>( QgsPalLayerSettings::Line ) );
246  mPlaceLineBtnGrp->addButton( radLineCurved, static_cast<int>( QgsPalLayerSettings::Curved ) );
247  mPlaceLineBtnGrp->addButton( radLineHorizontal, static_cast<int>( QgsPalLayerSettings::Horizontal ) );
248  mPlaceLineBtnGrp->setExclusive( true );
249  connect( mPlaceLineBtnGrp, static_cast<void ( QButtonGroup::* )( int )>( &QButtonGroup::buttonClicked ), this, &QgsTextFormatWidget::updatePlacementWidgets );
250 
251  // setup polygon placement button group (assigned enum id currently unused)
252  mPlacePolygonBtnGrp = new QButtonGroup( this );
253  mPlacePolygonBtnGrp->addButton( radOverCentroid, static_cast<int>( QgsPalLayerSettings::OverPoint ) );
254  mPlacePolygonBtnGrp->addButton( radAroundCentroid, static_cast<int>( QgsPalLayerSettings::AroundPoint ) );
255  mPlacePolygonBtnGrp->addButton( radPolygonHorizontal, static_cast<int>( QgsPalLayerSettings::Horizontal ) );
256  mPlacePolygonBtnGrp->addButton( radPolygonFree, static_cast<int>( QgsPalLayerSettings::Free ) );
257  mPlacePolygonBtnGrp->addButton( radPolygonPerimeter, static_cast<int>( QgsPalLayerSettings::Line ) );
258  mPlacePolygonBtnGrp->addButton( radPolygonPerimeterCurved, static_cast<int>( QgsPalLayerSettings::PerimeterCurved ) );
259  mPlacePolygonBtnGrp->setExclusive( true );
260  connect( mPlacePolygonBtnGrp, static_cast<void ( QButtonGroup::* )( int )>( &QButtonGroup::buttonClicked ), this, &QgsTextFormatWidget::updatePlacementWidgets );
261 
262  // Global settings group for groupboxes' saved/restored collapsed state
263  // maintains state across different dialogs
264  const auto groupBoxes = findChildren<QgsCollapsibleGroupBox *>();
265  for ( QgsCollapsibleGroupBox *grpbox : groupBoxes )
266  {
267  grpbox->setSettingGroup( QStringLiteral( "mAdvLabelingDlg" ) );
268  }
269 
270  connect( groupBox_mPreview, &QgsCollapsibleGroupBoxBasic::collapsedStateChanged, this, &QgsTextFormatWidget::collapseSample );
271 
272  // get rid of annoying outer focus rect on Mac
273  mLabelingOptionsListWidget->setAttribute( Qt::WA_MacShowFocusRect, false );
274 
275  QgsSettings settings;
276 
277  // reset horiz stretch of left side of options splitter (set to 1 for previewing in Qt Designer)
278  QSizePolicy policy( mLabelingOptionsListFrame->sizePolicy() );
279  policy.setHorizontalStretch( 0 );
280  mLabelingOptionsListFrame->setSizePolicy( policy );
281  if ( !settings.contains( QStringLiteral( "/Windows/Labeling/OptionsSplitState" ) ) )
282  {
283  // set left list widget width on initial showing
284  QList<int> splitsizes;
285  splitsizes << 115;
286  mLabelingOptionsSplitter->setSizes( splitsizes );
287  }
288 
289  // set up reverse connection from stack to list
290  connect( mLabelStackedWidget, &QStackedWidget::currentChanged, this, &QgsTextFormatWidget::optionsStackedWidget_CurrentChanged );
291 
292  // restore dialog, splitters and current tab
293  mFontPreviewSplitter->restoreState( settings.value( QStringLiteral( "Windows/Labeling/FontPreviewSplitState" ) ).toByteArray() );
294  mLabelingOptionsSplitter->restoreState( settings.value( QStringLiteral( "Windows/Labeling/OptionsSplitState" ) ).toByteArray() );
295 
296  mLabelingOptionsListWidget->setCurrentRow( settings.value( QStringLiteral( "Windows/Labeling/Tab" ), 0 ).toInt() );
297 
298  mBufferEffect.reset( QgsPaintEffectRegistry::defaultStack() );
299  connect( mBufferEffectWidget, &QgsEffectStackCompactWidget::changed, this, &QgsTextFormatWidget::updatePreview );
300  mBufferEffectWidget->setPaintEffect( mBufferEffect.get() );
301  mBackgroundEffect.reset( QgsPaintEffectRegistry::defaultStack() );
302  connect( mBackgroundEffectWidget, &QgsEffectStackCompactWidget::changed, this, &QgsTextFormatWidget::updatePreview );
303  mBackgroundEffectWidget->setPaintEffect( mBackgroundEffect.get() );
304 
305  setDockMode( false );
306 
307  QList<QWidget *> widgets;
308  widgets << btnBufferColor
309  << btnTextColor
310  << chkLabelPerFeaturePart
311  << chkLineAbove
312  << chkLineBelow
313  << chkLineOn
314  << chkLineOrientationDependent
315  << chkMergeLines
316  << chkPreserveRotation
317  << comboBlendMode
318  << comboBufferBlendMode
319  << mAlwaysShowDDBtn
320  << mBufferBlendModeDDBtn
321  << mBufferColorDDBtn
322  << mBufferDrawChkBx
323  << mBufferDrawDDBtn
324  << mBufferJoinStyleComboBox
325  << mBufferJoinStyleDDBtn
326  << mBufferSizeDDBtn
327  << mBufferOpacityDDBtn
328  << mBufferTranspFillChbx
329  << mBufferOpacityWidget
330  << mBufferUnitsDDBtn
331  << mCentroidDDBtn
332  << mCentroidInsideCheckBox
333  << mChkNoObstacle
334  << mCoordAlignmentHDDBtn
335  << mCoordAlignmentVDDBtn
336  << mCoordRotationDDBtn
337  << mCoordXDDBtn
338  << mCoordYDDBtn
339  << mDirectSymbChkBx
340  << mDirectSymbDDBtn
341  << mDirectSymbLeftDDBtn
342  << mDirectSymbLeftLineEdit
343  << mDirectSymbPlacementDDBtn
344  << mDirectSymbRevChkBx
345  << mDirectSymbRevDDBtn
346  << mDirectSymbRightDDBtn
347  << mDirectSymbRightLineEdit
348  << mFitInsidePolygonCheckBox
349  << mFontBlendModeDDBtn
350  << mFontBoldDDBtn
351  << mFontCapitalsComboBox
352  << mFontCaseDDBtn
353  << mFontColorDDBtn
354  << mFontDDBtn
355  << mFontItalicDDBtn
356  << mFontLetterSpacingDDBtn
357  << mFontLetterSpacingSpinBox
358  << mFontLimitPixelChkBox
359  << mFontLimitPixelDDBtn
360  << mFontLineHeightDDBtn
361  << mFontLineHeightSpinBox
362  << mFontMaxPixelDDBtn
363  << mFontMaxPixelSpinBox
364  << mFontMinPixelDDBtn
365  << mFontMinPixelSpinBox
366  << mFontMultiLineAlignComboBox
367  << mFontMultiLineAlignDDBtn
368  << mFontSizeDDBtn
369  << mFontSizeSpinBox
370  << mFontStrikeoutDDBtn
371  << mFontStyleComboBox
372  << mFontStyleDDBtn
373  << mFontOpacityDDBtn
374  << mTextOpacityWidget
375  << mFontUnderlineDDBtn
376  << mFontUnitsDDBtn
377  << mFontWordSpacingDDBtn
378  << mFontWordSpacingSpinBox
379  << mFormatNumChkBx
380  << mFormatNumDDBtn
381  << mFormatNumDecimalsDDBtn
382  << mFormatNumDecimalsSpnBx
383  << mFormatNumPlusSignChkBx
384  << mFormatNumPlusSignDDBtn
385  << mIsObstacleDDBtn
386  << mLimitLabelChkBox
387  << mLimitLabelSpinBox
388  << mLineDistanceDDBtn
389  << mLineDistanceSpnBx
390  << mLineDistanceUnitDDBtn
391  << mLineDistanceUnitWidget
392  << mMaxCharAngleDDBtn
393  << mMaxCharAngleInDSpinBox
394  << mMaxCharAngleOutDSpinBox
395  << mMinSizeSpinBox
396  << mObstacleFactorDDBtn
397  << mObstacleFactorSlider
398  << mObstacleTypeComboBox
399  << mOffsetTypeComboBox
400  << mPalShowAllLabelsForLayerChkBx
401  << mPointAngleSpinBox
402  << mPointOffsetDDBtn
403  << mPointOffsetUnitsDDBtn
404  << mPointOffsetUnitWidget
405  << mPointOffsetXSpinBox
406  << mPointOffsetYSpinBox
407  << mPointPositionOrderDDBtn
408  << mPointQuadOffsetDDBtn
409  << mPreviewBackgroundBtn
410  << mPreviewTextEdit
411  << mPriorityDDBtn
412  << mPrioritySlider
413  << mRepeatDistanceDDBtn
414  << mRepeatDistanceSpinBox
415  << mRepeatDistanceUnitDDBtn
416  << mRepeatDistanceUnitWidget
417  << mScaleBasedVisibilityChkBx
418  << mScaleBasedVisibilityDDBtn
419  << mScaleBasedVisibilityMaxDDBtn
420  << mMaxScaleWidget
421  << mScaleBasedVisibilityMinDDBtn
422  << mMinScaleWidget
423  << mShadowBlendCmbBx
424  << mShadowBlendDDBtn
425  << mShadowColorBtn
426  << mShadowColorDDBtn
427  << mShadowDrawChkBx
428  << mShadowDrawDDBtn
429  << mShadowOffsetAngleDDBtn
430  << mShadowOffsetAngleSpnBx
431  << mShadowOffsetDDBtn
432  << mShadowOffsetGlobalChkBx
433  << mShadowOffsetSpnBx
434  << mShadowOffsetUnitsDDBtn
435  << mShadowOffsetUnitWidget
436  << mShadowRadiusAlphaChkBx
437  << mShadowRadiusDDBtn
438  << mShadowRadiusDblSpnBx
439  << mShadowRadiusUnitsDDBtn
440  << mShadowRadiusUnitWidget
441  << mShadowScaleDDBtn
442  << mShadowScaleSpnBx
443  << mShadowOpacityDDBtn
444  << mShadowOpacityWidget
445  << mShadowUnderCmbBx
446  << mShadowUnderDDBtn
447  << mShapeBlendCmbBx
448  << mShapeBlendModeDDBtn
449  << mShapeStrokeColorBtn
450  << mShapeStrokeColorDDBtn
451  << mShapeStrokeUnitsDDBtn
452  << mShapeStrokeWidthDDBtn
453  << mShapeStrokeWidthSpnBx
454  << mShapeStrokeWidthUnitWidget
455  << mShapeDrawChkBx
456  << mShapeDrawDDBtn
457  << mShapeFillColorBtn
458  << mShapeFillColorDDBtn
459  << mShapeOffsetDDBtn
460  << mShapeOffsetUnitsDDBtn
461  << mShapeOffsetXSpnBx
462  << mShapeOffsetYSpnBx
463  << mShapeOffsetUnitWidget
464  << mShapePenStyleCmbBx
465  << mShapePenStyleDDBtn
466  << mShapeRadiusDDBtn
467  << mShapeRadiusUnitsDDBtn
468  << mShapeRadiusXDbSpnBx
469  << mShapeRadiusYDbSpnBx
470  << mShapeRotationCmbBx
471  << mShapeRotationDDBtn
472  << mShapeRotationDblSpnBx
473  << mShapeRotationTypeDDBtn
474  << mShapeRadiusUnitWidget
475  << mShapeSVGPathDDBtn
476  << mShapeSVGPathLineEdit
477  << mShapeSizeCmbBx
478  << mShapeSizeTypeDDBtn
479  << mShapeSizeUnitsDDBtn
480  << mShapeSizeUnitWidget
481  << mShapeSizeXDDBtn
482  << mShapeSizeXSpnBx
483  << mShapeSizeYDDBtn
484  << mShapeSizeYSpnBx
485  << mShapeOpacityDDBtn
486  << mBackgroundOpacityWidget
487  << mShapeTypeCmbBx
488  << mShapeTypeDDBtn
489  << mShowLabelDDBtn
490  << mWrapCharDDBtn
491  << mAutoWrapLengthDDBtn
492  << mZIndexDDBtn
493  << mZIndexSpinBox
494  << spinBufferSize
495  << wrapCharacterEdit
496  << mAutoWrapLengthSpinBox
497  << mAutoWrapTypeComboBox
498  << mCentroidRadioVisible
499  << mCentroidRadioWhole
500  << mDirectSymbRadioBtnAbove
501  << mDirectSymbRadioBtnBelow
502  << mDirectSymbRadioBtnLR
503  << mUpsidedownRadioAll
504  << mUpsidedownRadioDefined
505  << mUpsidedownRadioOff
506  << radAroundCentroid
507  << radAroundPoint
508  << radLineCurved
509  << radLineHorizontal
510  << radLineParallel
511  << radOverCentroid
512  << radOverPoint
513  << radPolygonFree
514  << radPolygonHorizontal
515  << radPolygonPerimeter
516  << radPolygonPerimeterCurved
517  << radPredefinedOrder
518  << mFieldExpressionWidget
519  << mCheckBoxSubstituteText
520  << mGeometryGeneratorGroupBox
521  << mGeometryGenerator
522  << mGeometryGeneratorType
523  << mLinePlacementFlagsDDBtn;
524  connectValueChanged( widgets, SLOT( updatePreview() ) );
525 
526  connect( mQuadrantBtnGrp, static_cast<void ( QButtonGroup::* )( int )>( &QButtonGroup::buttonClicked ), this, &QgsTextFormatWidget::updatePreview );
527 
528  mGeometryGeneratorType->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconPolygonLayer.svg" ) ), tr( "Polygon / MultiPolygon" ), QgsWkbTypes::GeometryType::PolygonGeometry );
529  mGeometryGeneratorType->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconLineLayer.svg" ) ), tr( "LineString / MultiLineString" ), QgsWkbTypes::GeometryType::LineGeometry );
530  mGeometryGeneratorType->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconPointLayer.svg" ) ), tr( "Point / MultiPoint" ), QgsWkbTypes::GeometryType::PointGeometry );
531 
532  // set correct initial tab to match displayed setting page
533  whileBlocking( mOptionsTab )->setCurrentIndex( mLabelStackedWidget->currentIndex() );
534 
535  if ( mMapCanvas )
536  {
537  lblFontPreview->setMapUnits( mMapCanvas->mapSettings().mapUnits() );
538  mPreviewScaleComboBox->setScale( mMapCanvas->mapSettings().scale() );
539  }
540 }
541 
542 void QgsTextFormatWidget::setWidgetMode( QgsTextFormatWidget::Mode mode )
543 {
544  mWidgetMode = mode;
545  switch ( mode )
546  {
547  case Labeling:
548  toggleDDButtons( true );
549  break;
550 
551  case Text:
552  toggleDDButtons( false );
553  delete mLabelingOptionsListWidget->takeItem( 6 );
554  delete mLabelingOptionsListWidget->takeItem( 5 );
555  mOptionsTab->removeTab( 6 );
556  mOptionsTab->removeTab( 5 );
557 
558  frameLabelWith->hide();
559  mDirectSymbolsFrame->hide();
560  mFormatNumFrame->hide();
561  mFormatNumChkBx->hide();
562  mFormatNumDDBtn->hide();
563  mSubstitutionsFrame->hide();
564  mFontBoldBtn->hide();
565  mFontItalicBtn->hide();
566 
567  break;
568  }
569 }
570 
571 void QgsTextFormatWidget::toggleDDButtons( bool visible )
572 {
573  const auto buttons = findChildren< QgsPropertyOverrideButton * >();
574  for ( QgsPropertyOverrideButton *button : buttons )
575  {
576  button->setVisible( visible );
577  }
578 }
579 
581 {
582  mOptionsTab->setVisible( enabled );
583  mOptionsTab->setTabToolTip( 0, tr( "Text" ) );
584  mOptionsTab->setTabToolTip( 1, tr( "Formatting" ) );
585  mOptionsTab->setTabToolTip( 2, tr( "Buffer" ) );
586  mOptionsTab->setTabToolTip( 3, tr( "Background" ) );
587  mOptionsTab->setTabToolTip( 4, tr( "Shadow" ) );
588  mOptionsTab->setTabToolTip( 5, tr( "Placement" ) );
589  mOptionsTab->setTabToolTip( 6, tr( "Rendering" ) );
590 
591  mLabelingOptionsListFrame->setVisible( !enabled );
592  groupBox_mPreview->setVisible( !enabled );
593  mDockMode = enabled;
594 }
595 
596 void QgsTextFormatWidget::connectValueChanged( const QList<QWidget *> &widgets, const char *slot )
597 {
598  const auto constWidgets = widgets;
599  for ( QWidget *widget : constWidgets )
600  {
601  if ( QgsPropertyOverrideButton *w = qobject_cast<QgsPropertyOverrideButton *>( widget ) )
602  {
603  connect( w, SIGNAL( changed() ), this, slot );
604  }
605  else if ( QgsFieldExpressionWidget *w = qobject_cast< QgsFieldExpressionWidget *>( widget ) )
606  {
607  connect( w, SIGNAL( fieldChanged( QString ) ), this, slot );
608  }
609  else if ( QgsOpacityWidget *w = qobject_cast< QgsOpacityWidget *>( widget ) )
610  {
611  connect( w, SIGNAL( opacityChanged( double ) ), this, slot );
612  }
613  else if ( QgsScaleWidget *w = qobject_cast< QgsScaleWidget *>( widget ) )
614  {
615  connect( w, SIGNAL( scaleChanged( double ) ), this, slot );
616  }
617  else if ( QgsUnitSelectionWidget *w = qobject_cast<QgsUnitSelectionWidget *>( widget ) )
618  {
619  connect( w, SIGNAL( changed() ), this, slot );
620  }
621  else if ( QComboBox *w = qobject_cast<QComboBox *>( widget ) )
622  {
623  connect( w, SIGNAL( currentIndexChanged( int ) ), this, slot );
624  }
625  else if ( QSpinBox *w = qobject_cast<QSpinBox *>( widget ) )
626  {
627  connect( w, SIGNAL( valueChanged( int ) ), this, slot );
628  }
629  else if ( QDoubleSpinBox *w = qobject_cast<QDoubleSpinBox *>( widget ) )
630  {
631  connect( w, SIGNAL( valueChanged( double ) ), this, slot );
632  }
633  else if ( QgsColorButton *w = qobject_cast<QgsColorButton *>( widget ) )
634  {
635  connect( w, SIGNAL( colorChanged( QColor ) ), this, slot );
636  }
637  else if ( QCheckBox *w = qobject_cast<QCheckBox *>( widget ) )
638  {
639  connect( w, SIGNAL( toggled( bool ) ), this, slot );
640  }
641  else if ( QRadioButton *w = qobject_cast<QRadioButton *>( widget ) )
642  {
643  connect( w, SIGNAL( toggled( bool ) ), this, slot );
644  }
645  else if ( QLineEdit *w = qobject_cast<QLineEdit *>( widget ) )
646  {
647  connect( w, SIGNAL( textEdited( QString ) ), this, slot );
648  }
649  else if ( QSlider *w = qobject_cast<QSlider *>( widget ) )
650  {
651  connect( w, SIGNAL( valueChanged( int ) ), this, slot );
652  }
653  else if ( QGroupBox *w = qobject_cast<QGroupBox *>( widget ) )
654  {
655  connect( w, SIGNAL( toggled( bool ) ), this, slot );
656  }
657  else if ( QgsCodeEditorExpression *w = qobject_cast<QgsCodeEditorExpression *>( widget ) )
658  {
659  connect( w, SIGNAL( textChanged() ), this, slot );
660  }
661  else
662  {
663  QgsLogger::warning( QStringLiteral( "Could not create connection for widget %1" ).arg( widget->objectName() ) );
664  }
665  }
666 }
667 
669 {
670  QgsTextBufferSettings buffer = format.buffer();
671  QgsTextBackgroundSettings background = format.background();
672  QgsTextShadowSettings shadow = format.shadow();
673 
674  // buffer
675  mBufferDrawChkBx->setChecked( buffer.enabled() );
676  spinBufferSize->setValue( buffer.size() );
677  mBufferUnitWidget->setUnit( buffer.sizeUnit() );
678  mBufferUnitWidget->setMapUnitScale( buffer.sizeMapUnitScale() );
679  btnBufferColor->setColor( buffer.color() );
680  mBufferOpacityWidget->setOpacity( buffer.opacity() );
681  mBufferJoinStyleComboBox->setPenJoinStyle( buffer.joinStyle() );
682  mBufferTranspFillChbx->setChecked( buffer.fillBufferInterior() );
683  comboBufferBlendMode->setBlendMode( buffer.blendMode() );
684  if ( buffer.paintEffect() )
685  mBufferEffect.reset( buffer.paintEffect()->clone() );
686  else
687  {
688  mBufferEffect.reset( QgsPaintEffectRegistry::defaultStack() );
689  mBufferEffect->setEnabled( false );
690  }
691  mBufferEffectWidget->setPaintEffect( mBufferEffect.get() );
692 
693  mFontSizeUnitWidget->setUnit( format.sizeUnit() );
694  mFontSizeUnitWidget->setMapUnitScale( format.sizeMapUnitScale() );
695  mRefFont = format.font();
696  mFontSizeSpinBox->setValue( format.size() );
697  btnTextColor->setColor( format.color() );
698  mTextOpacityWidget->setOpacity( format.opacity() );
699  comboBlendMode->setBlendMode( format.blendMode() );
700 
701  mFontWordSpacingSpinBox->setValue( format.font().wordSpacing() );
702  mFontLetterSpacingSpinBox->setValue( format.font().letterSpacing() );
703 
704  QgsFontUtils::updateFontViaStyle( mRefFont, format.namedStyle() );
705  updateFont( mRefFont );
706 
707  // show 'font not found' if substitution has occurred (should come after updateFont())
708  mFontMissingLabel->setVisible( !format.fontFound() );
709  if ( !format.fontFound() )
710  {
711  QString missingTxt = tr( "%1 not found. Default substituted." );
712  QString txtPrepend = tr( "Chosen font" );
713  if ( !format.resolvedFontFamily().isEmpty() )
714  {
715  txtPrepend = QStringLiteral( "'%1'" ).arg( format.resolvedFontFamily() );
716  }
717  mFontMissingLabel->setText( missingTxt.arg( txtPrepend ) );
718 
719  // ensure user is sent to 'Text style' section to see notice
720  mLabelingOptionsListWidget->setCurrentRow( 0 );
721  }
722  mFontLineHeightSpinBox->setValue( format.lineHeight() );
723 
724  // shape background
725  mShapeDrawChkBx->setChecked( background.enabled() );
726  mShapeTypeCmbBx->blockSignals( true );
727  mShapeTypeCmbBx->setCurrentIndex( background.type() );
728  mShapeTypeCmbBx->blockSignals( false );
729  mShapeSVGPathLineEdit->setText( background.svgFile() );
730 
731  mShapeSizeCmbBx->setCurrentIndex( background.sizeType() );
732  mShapeSizeXSpnBx->setValue( background.size().width() );
733  mShapeSizeYSpnBx->setValue( background.size().height() );
734  mShapeSizeUnitWidget->setUnit( background.sizeUnit() );
735  mShapeSizeUnitWidget->setMapUnitScale( background.sizeMapUnitScale() );
736  mShapeRotationCmbBx->setCurrentIndex( background.rotationType() );
737  mShapeRotationDblSpnBx->setEnabled( background.rotationType() != QgsTextBackgroundSettings::RotationSync );
738  mShapeRotationDDBtn->setEnabled( background.rotationType() != QgsTextBackgroundSettings::RotationSync );
739  mShapeRotationDblSpnBx->setValue( background.rotation() );
740  mShapeOffsetXSpnBx->setValue( background.offset().x() );
741  mShapeOffsetYSpnBx->setValue( background.offset().y() );
742  mShapeOffsetUnitWidget->setUnit( background.offsetUnit() );
743  mShapeOffsetUnitWidget->setMapUnitScale( background.offsetMapUnitScale() );
744  mShapeRadiusXDbSpnBx->setValue( background.radii().width() );
745  mShapeRadiusYDbSpnBx->setValue( background.radii().height() );
746  mShapeRadiusUnitWidget->setUnit( background.radiiUnit() );
747  mShapeRadiusUnitWidget->setMapUnitScale( background.radiiMapUnitScale() );
748 
749  mShapeFillColorBtn->setColor( background.fillColor() );
750  mShapeStrokeColorBtn->setColor( background.strokeColor() );
751  mShapeStrokeWidthSpnBx->setValue( background.strokeWidth() );
752  mShapeStrokeWidthUnitWidget->setUnit( background.strokeWidthUnit() );
753  mShapeStrokeWidthUnitWidget->setMapUnitScale( background.strokeWidthMapUnitScale() );
754  mShapePenStyleCmbBx->setPenJoinStyle( background.joinStyle() );
755 
756  mBackgroundOpacityWidget->setOpacity( background.opacity() );
757  mShapeBlendCmbBx->setBlendMode( background.blendMode() );
758 
759  mLoadSvgParams = false;
760  mShapeTypeCmbBx_currentIndexChanged( background.type() ); // force update of shape background gui
761 
762  if ( background.paintEffect() )
763  mBackgroundEffect.reset( background.paintEffect()->clone() );
764  else
765  {
766  mBackgroundEffect.reset( QgsPaintEffectRegistry::defaultStack() );
767  mBackgroundEffect->setEnabled( false );
768  }
769  mBackgroundEffectWidget->setPaintEffect( mBackgroundEffect.get() );
770 
771  // drop shadow
772  mShadowDrawChkBx->setChecked( shadow.enabled() );
773  mShadowUnderCmbBx->setCurrentIndex( shadow.shadowPlacement() );
774  mShadowOffsetAngleSpnBx->setValue( shadow.offsetAngle() );
775  mShadowOffsetSpnBx->setValue( shadow.offsetDistance() );
776  mShadowOffsetUnitWidget->setUnit( shadow.offsetUnit() );
777  mShadowOffsetUnitWidget->setMapUnitScale( shadow.offsetMapUnitScale() );
778  mShadowOffsetGlobalChkBx->setChecked( shadow.offsetGlobal() );
779 
780  mShadowRadiusDblSpnBx->setValue( shadow.blurRadius() );
781  mShadowRadiusUnitWidget->setUnit( shadow.blurRadiusUnit() );
782  mShadowRadiusUnitWidget->setMapUnitScale( shadow.blurRadiusMapUnitScale() );
783  mShadowRadiusAlphaChkBx->setChecked( shadow.blurAlphaOnly() );
784  mShadowOpacityWidget->setOpacity( shadow.opacity() );
785  mShadowScaleSpnBx->setValue( shadow.scale() );
786 
787  mShadowColorBtn->setColor( shadow.color() );
788  mShadowBlendCmbBx->setBlendMode( shadow.blendMode() );
789 
790 }
791 
793 {
794  QgsSettings settings;
795  settings.setValue( QStringLiteral( "Windows/Labeling/FontPreviewSplitState" ), mFontPreviewSplitter->saveState() );
796  settings.setValue( QStringLiteral( "Windows/Labeling/OptionsSplitState" ), mLabelingOptionsSplitter->saveState() );
797  settings.setValue( QStringLiteral( "Windows/Labeling/Tab" ), mLabelingOptionsListWidget->currentRow() );
798 }
799 
801 {
803  format.setColor( btnTextColor->color() );
804  format.setFont( mRefFont );
805  format.setSize( mFontSizeSpinBox->value() );
806  format.setNamedStyle( mFontStyleComboBox->currentText() );
807  format.setOpacity( mTextOpacityWidget->opacity() );
808  format.setBlendMode( comboBlendMode->blendMode() );
809  format.setSizeUnit( mFontSizeUnitWidget->unit() );
810  format.setSizeMapUnitScale( mFontSizeUnitWidget->getMapUnitScale() );
811  format.setLineHeight( mFontLineHeightSpinBox->value() );
812 
813  // buffer
814  QgsTextBufferSettings buffer;
815  buffer.setEnabled( mBufferDrawChkBx->isChecked() );
816  buffer.setSize( spinBufferSize->value() );
817  buffer.setColor( btnBufferColor->color() );
818  buffer.setOpacity( mBufferOpacityWidget->opacity() );
819  buffer.setSizeUnit( mBufferUnitWidget->unit() );
820  buffer.setSizeMapUnitScale( mBufferUnitWidget->getMapUnitScale() );
821  buffer.setJoinStyle( mBufferJoinStyleComboBox->penJoinStyle() );
822  buffer.setFillBufferInterior( mBufferTranspFillChbx->isChecked() );
823  buffer.setBlendMode( comboBufferBlendMode->blendMode() );
824  if ( mBufferEffect && !QgsPaintEffectRegistry::isDefaultStack( mBufferEffect.get() ) )
825  buffer.setPaintEffect( mBufferEffect->clone() );
826  else
827  buffer.setPaintEffect( nullptr );
828  format.setBuffer( buffer );
829 
830  // shape background
831  QgsTextBackgroundSettings background;
832  background.setEnabled( mShapeDrawChkBx->isChecked() );
833  background.setType( ( QgsTextBackgroundSettings::ShapeType )mShapeTypeCmbBx->currentIndex() );
834  background.setSvgFile( mShapeSVGPathLineEdit->text() );
835  background.setSizeType( ( QgsTextBackgroundSettings::SizeType )mShapeSizeCmbBx->currentIndex() );
836  background.setSize( QSizeF( mShapeSizeXSpnBx->value(), mShapeSizeYSpnBx->value() ) );
837  background.setSizeUnit( mShapeSizeUnitWidget->unit() );
838  background.setSizeMapUnitScale( mShapeSizeUnitWidget->getMapUnitScale() );
839  background.setRotationType( ( QgsTextBackgroundSettings::RotationType )( mShapeRotationCmbBx->currentIndex() ) );
840  background.setRotation( mShapeRotationDblSpnBx->value() );
841  background.setOffset( QPointF( mShapeOffsetXSpnBx->value(), mShapeOffsetYSpnBx->value() ) );
842  background.setOffsetUnit( mShapeOffsetUnitWidget->unit() );
843  background.setOffsetMapUnitScale( mShapeOffsetUnitWidget->getMapUnitScale() );
844  background.setRadii( QSizeF( mShapeRadiusXDbSpnBx->value(), mShapeRadiusYDbSpnBx->value() ) );
845  background.setRadiiUnit( mShapeRadiusUnitWidget->unit() );
846  background.setRadiiMapUnitScale( mShapeRadiusUnitWidget->getMapUnitScale() );
847 
848  background.setFillColor( mShapeFillColorBtn->color() );
849  background.setStrokeColor( mShapeStrokeColorBtn->color() );
850  background.setStrokeWidth( mShapeStrokeWidthSpnBx->value() );
851  background.setStrokeWidthUnit( mShapeStrokeWidthUnitWidget->unit() );
852  background.setStrokeWidthMapUnitScale( mShapeStrokeWidthUnitWidget->getMapUnitScale() );
853  background.setJoinStyle( mShapePenStyleCmbBx->penJoinStyle() );
854  background.setOpacity( mBackgroundOpacityWidget->opacity() );
855  background.setBlendMode( mShapeBlendCmbBx->blendMode() );
856  if ( mBackgroundEffect && !QgsPaintEffectRegistry::isDefaultStack( mBackgroundEffect.get() ) )
857  background.setPaintEffect( mBackgroundEffect->clone() );
858  else
859  background.setPaintEffect( nullptr );
860  format.setBackground( background );
861 
862  // drop shadow
863  QgsTextShadowSettings shadow;
864  shadow.setEnabled( mShadowDrawChkBx->isChecked() );
865  shadow.setShadowPlacement( ( QgsTextShadowSettings::ShadowPlacement )mShadowUnderCmbBx->currentIndex() );
866  shadow.setOffsetAngle( mShadowOffsetAngleSpnBx->value() );
867  shadow.setOffsetDistance( mShadowOffsetSpnBx->value() );
868  shadow.setOffsetUnit( mShadowOffsetUnitWidget->unit() );
869  shadow.setOffsetMapUnitScale( mShadowOffsetUnitWidget->getMapUnitScale() );
870  shadow.setOffsetGlobal( mShadowOffsetGlobalChkBx->isChecked() );
871  shadow.setBlurRadius( mShadowRadiusDblSpnBx->value() );
872  shadow.setBlurRadiusUnit( mShadowRadiusUnitWidget->unit() );
873  shadow.setBlurRadiusMapUnitScale( mShadowRadiusUnitWidget->getMapUnitScale() );
874  shadow.setBlurAlphaOnly( mShadowRadiusAlphaChkBx->isChecked() );
875  shadow.setOpacity( mShadowOpacityWidget->opacity() );
876  shadow.setScale( mShadowScaleSpnBx->value() );
877  shadow.setColor( mShadowColorBtn->color() );
878  shadow.setBlendMode( mShadowBlendCmbBx->blendMode() );
879  format.setShadow( shadow );
880 
881  return format;
882 }
883 
885 {
886  updateWidgetForFormat( format );
887 }
888 
889 void QgsTextFormatWidget::optionsStackedWidget_CurrentChanged( int indx )
890 {
891  mLabelingOptionsListWidget->blockSignals( true );
892  mLabelingOptionsListWidget->setCurrentRow( indx );
893  mLabelingOptionsListWidget->blockSignals( false );
894 }
895 
896 void QgsTextFormatWidget::collapseSample( bool collapse )
897 {
898  if ( collapse )
899  {
900  QList<int> splitSizes = mFontPreviewSplitter->sizes();
901  if ( splitSizes[0] > groupBox_mPreview->height() )
902  {
903  int delta = splitSizes[0] - groupBox_mPreview->height();
904  splitSizes[0] -= delta;
905  splitSizes[1] += delta;
906  mFontPreviewSplitter->setSizes( splitSizes );
907  }
908  }
909 }
910 
911 void QgsTextFormatWidget::changeTextColor( const QColor &color )
912 {
913  Q_UNUSED( color )
914  updatePreview();
915 }
916 
917 void QgsTextFormatWidget::updateFont( const QFont &font )
918 {
919  // update background reference font
920  if ( font != mRefFont )
921  {
922  mRefFont = font;
923  }
924 
925  // test if font is actually available
926  // NOTE: QgsFontUtils::fontMatchOnSystem may fail here, just crosscheck family
927  mFontMissingLabel->setVisible( !QgsFontUtils::fontFamilyMatchOnSystem( mRefFont.family() ) );
928 
929  mDirectSymbLeftLineEdit->setFont( mRefFont );
930  mDirectSymbRightLineEdit->setFont( mRefFont );
931 
932  blockFontChangeSignals( true );
933  mFontFamilyCmbBx->setCurrentFont( mRefFont );
934  populateFontStyleComboBox();
935  int idx = mFontCapitalsComboBox->findData( QVariant( ( unsigned int ) mRefFont.capitalization() ) );
936  mFontCapitalsComboBox->setCurrentIndex( idx == -1 ? 0 : idx );
937  mFontUnderlineBtn->setChecked( mRefFont.underline() );
938  mFontStrikethroughBtn->setChecked( mRefFont.strikeOut() );
939  blockFontChangeSignals( false );
940 
941  // update font name with font face
942 // font.setPixelSize( 24 );
943 
944  updatePreview();
945 }
946 
947 void QgsTextFormatWidget::blockFontChangeSignals( bool blk )
948 {
949  mFontFamilyCmbBx->blockSignals( blk );
950  mFontStyleComboBox->blockSignals( blk );
951  mFontCapitalsComboBox->blockSignals( blk );
952  mFontUnderlineBtn->blockSignals( blk );
953  mFontStrikethroughBtn->blockSignals( blk );
954  mFontWordSpacingSpinBox->blockSignals( blk );
955  mFontLetterSpacingSpinBox->blockSignals( blk );
956 }
957 
958 void QgsTextFormatWidget::updatePreview()
959 {
960  // In dock mode we don't have a preview we
961  // just let stuff know we have changed because
962  // there might be live updates connected.
963  if ( mDockMode )
964  {
965  emit widgetChanged();
966  return;
967  }
968 
969  scrollPreview();
970  lblFontPreview->setFormat( format() );
971 }
972 
973 void QgsTextFormatWidget::scrollPreview()
974 {
975  scrollArea_mPreview->ensureVisible( 0, 0, 0, 0 );
976 }
977 
978 void QgsTextFormatWidget::setPreviewBackground( const QColor &color )
979 {
980  scrollArea_mPreview->widget()->setStyleSheet( QStringLiteral( "background: rgb(%1, %2, %3);" ).arg( QString::number( color.red() ),
981  QString::number( color.green() ),
982  QString::number( color.blue() ) ) );
983 }
984 
985 void QgsTextFormatWidget::changeBufferColor( const QColor &color )
986 {
987  Q_UNUSED( color )
988  updatePreview();
989 }
990 
992 {
993  QWidget *curWdgt = stackedPlacement->currentWidget();
994 
995  bool showLineFrame = false;
996  bool showCentroidFrame = false;
997  bool showQuadrantFrame = false;
998  bool showFixedQuadrantFrame = false;
999  bool showPlacementPriorityFrame = false;
1000  bool showOffsetTypeFrame = false;
1001  bool showOffsetFrame = false;
1002  bool showDistanceFrame = false;
1003  bool showRotationFrame = false;
1004  bool showMaxCharAngleFrame = false;
1005 
1006  bool enableMultiLinesFrame = true;
1007 
1008  if ( ( curWdgt == pagePoint && radAroundPoint->isChecked() )
1009  || ( curWdgt == pagePolygon && radAroundCentroid->isChecked() ) )
1010  {
1011  showCentroidFrame = ( curWdgt == pagePolygon && radAroundCentroid->isChecked() );
1012  showDistanceFrame = true;
1013  //showRotationFrame = true; // TODO: uncomment when supported
1014  if ( curWdgt == pagePoint )
1015  {
1016  showQuadrantFrame = true;
1017  }
1018  }
1019  else if ( ( curWdgt == pagePoint && radOverPoint->isChecked() )
1020  || ( curWdgt == pagePolygon && radOverCentroid->isChecked() ) )
1021  {
1022  showCentroidFrame = ( curWdgt == pagePolygon && radOverCentroid->isChecked() );
1023  showQuadrantFrame = true;
1024  showFixedQuadrantFrame = true;
1025  showOffsetFrame = true;
1026  showRotationFrame = true;
1027  }
1028  else if ( curWdgt == pagePoint && radPredefinedOrder->isChecked() )
1029  {
1030  showDistanceFrame = true;
1031  showPlacementPriorityFrame = true;
1032  showOffsetTypeFrame = true;
1033  }
1034  else if ( ( curWdgt == pageLine && radLineParallel->isChecked() )
1035  || ( curWdgt == pagePolygon && radPolygonPerimeter->isChecked() )
1036  || ( curWdgt == pageLine && radLineCurved->isChecked() )
1037  || ( curWdgt == pagePolygon && radPolygonPerimeterCurved->isChecked() ) )
1038  {
1039  showLineFrame = true;
1040  showDistanceFrame = true;
1041  //showRotationFrame = true; // TODO: uncomment when supported
1042 
1043  bool offline = chkLineAbove->isChecked() || chkLineBelow->isChecked();
1044  chkLineOrientationDependent->setEnabled( offline );
1045  mPlacementDistanceFrame->setEnabled( offline );
1046 
1047  bool isCurved = ( curWdgt == pageLine && radLineCurved->isChecked() )
1048  || ( curWdgt == pagePolygon && radPolygonPerimeterCurved->isChecked() );
1049  showMaxCharAngleFrame = isCurved;
1050  // TODO: enable mMultiLinesFrame when supported for curved labels
1051  enableMultiLinesFrame = !isCurved;
1052  }
1053 
1054  mPlacementLineFrame->setVisible( showLineFrame );
1055  mPlacementCentroidFrame->setVisible( showCentroidFrame );
1056  mPlacementQuadrantFrame->setVisible( showQuadrantFrame );
1057  mPlacementFixedQuadrantFrame->setVisible( showFixedQuadrantFrame );
1058  mPlacementCartographicFrame->setVisible( showPlacementPriorityFrame );
1059  mPlacementOffsetFrame->setVisible( showOffsetFrame );
1060  mPlacementDistanceFrame->setVisible( showDistanceFrame );
1061  mPlacementOffsetTypeFrame->setVisible( showOffsetTypeFrame );
1062  mPlacementRotationFrame->setVisible( showRotationFrame );
1063  mPlacementRepeatDistanceFrame->setVisible( curWdgt == pageLine || ( curWdgt == pagePolygon &&
1064  ( radPolygonPerimeter->isChecked() || radPolygonPerimeterCurved->isChecked() ) ) );
1065  mPlacementMaxCharAngleFrame->setVisible( showMaxCharAngleFrame );
1066 
1067  mMultiLinesFrame->setEnabled( enableMultiLinesFrame );
1068 }
1069 
1070 void QgsTextFormatWidget::populateFontCapitalsComboBox()
1071 {
1072  mFontCapitalsComboBox->addItem( tr( "No change" ), QVariant( 0 ) );
1073  mFontCapitalsComboBox->addItem( tr( "All uppercase" ), QVariant( 1 ) );
1074  mFontCapitalsComboBox->addItem( tr( "All lowercase" ), QVariant( 2 ) );
1075  // Small caps doesn't work right with QPainterPath::addText()
1076  // https://bugreports.qt.io/browse/QTBUG-13965
1077 // mFontCapitalsComboBox->addItem( tr( "Small caps" ), QVariant( 3 ) );
1078  mFontCapitalsComboBox->addItem( tr( "Capitalize first letter" ), QVariant( 4 ) );
1079 }
1080 
1081 void QgsTextFormatWidget::populateFontStyleComboBox()
1082 {
1083  mFontStyleComboBox->clear();
1084  QStringList styles = mFontDB.styles( mRefFont.family() );
1085  const auto constStyles = styles;
1086  for ( const QString &style : constStyles )
1087  {
1088  mFontStyleComboBox->addItem( style );
1089  }
1090 
1091  QString targetStyle = mFontDB.styleString( mRefFont );
1092  if ( !styles.contains( targetStyle ) )
1093  {
1094  QFont f = QFont( mRefFont.family() );
1095  targetStyle = QFontInfo( f ).styleName();
1096  mRefFont.setStyleName( targetStyle );
1097  }
1098  int curIndx = 0;
1099  int stylIndx = mFontStyleComboBox->findText( targetStyle );
1100  if ( stylIndx > -1 )
1101  {
1102  curIndx = stylIndx;
1103  }
1104 
1105  mFontStyleComboBox->setCurrentIndex( curIndx );
1106 }
1107 
1108 void QgsTextFormatWidget::mFontSizeSpinBox_valueChanged( double d )
1109 {
1110  mRefFont.setPointSizeF( d );
1111  updateFont( mRefFont );
1112 }
1113 
1114 void QgsTextFormatWidget::mFontCapitalsComboBox_currentIndexChanged( int index )
1115 {
1116  int capitalsindex = mFontCapitalsComboBox->itemData( index ).toInt();
1117  mRefFont.setCapitalization( ( QFont::Capitalization ) capitalsindex );
1118  updateFont( mRefFont );
1119 }
1120 
1121 void QgsTextFormatWidget::mFontFamilyCmbBx_currentFontChanged( const QFont &f )
1122 {
1123  mRefFont.setFamily( f.family() );
1124  updateFont( mRefFont );
1125 }
1126 
1127 void QgsTextFormatWidget::mFontStyleComboBox_currentIndexChanged( const QString &text )
1128 {
1129  QgsFontUtils::updateFontViaStyle( mRefFont, text );
1130  updateFont( mRefFont );
1131 }
1132 
1133 void QgsTextFormatWidget::mFontUnderlineBtn_toggled( bool ckd )
1134 {
1135  mRefFont.setUnderline( ckd );
1136  updateFont( mRefFont );
1137 }
1138 
1139 void QgsTextFormatWidget::mFontStrikethroughBtn_toggled( bool ckd )
1140 {
1141  mRefFont.setStrikeOut( ckd );
1142  updateFont( mRefFont );
1143 }
1144 
1145 void QgsTextFormatWidget::mFontWordSpacingSpinBox_valueChanged( double spacing )
1146 {
1147  mRefFont.setWordSpacing( spacing );
1148  updateFont( mRefFont );
1149 }
1150 
1151 void QgsTextFormatWidget::mFontLetterSpacingSpinBox_valueChanged( double spacing )
1152 {
1153  mRefFont.setLetterSpacing( QFont::AbsoluteSpacing, spacing );
1154  updateFont( mRefFont );
1155 }
1156 
1157 void QgsTextFormatWidget::mFontSizeUnitWidget_changed()
1158 {
1159  // disable pixel size limiting for labels defined in points
1160  if ( mFontSizeUnitWidget->unit() != QgsUnitTypes::RenderMapUnits )
1161  {
1162  mFontLimitPixelChkBox->setChecked( false );
1163  }
1164  else if ( mMinPixelLimit == 0 )
1165  {
1166  // initial minimum trigger value set, turn on pixel size limiting by default
1167  // for labels defined in map units (ignored after first settings save)
1168  mFontLimitPixelChkBox->setChecked( true );
1169  }
1170  updateFont( mRefFont );
1171 }
1172 
1173 void QgsTextFormatWidget::mFontMinPixelSpinBox_valueChanged( int px )
1174 {
1175  // ensure max font pixel size for map unit labels can't be lower than min
1176  mFontMaxPixelSpinBox->setMinimum( px );
1177  mFontMaxPixelSpinBox->update();
1178 }
1179 
1180 void QgsTextFormatWidget::mFontMaxPixelSpinBox_valueChanged( int px )
1181 {
1182  // ensure max font pixel size for map unit labels can't be lower than min
1183  if ( px < mFontMinPixelSpinBox->value() )
1184  {
1185  mFontMaxPixelSpinBox->blockSignals( true );
1186  mFontMaxPixelSpinBox->setValue( mFontMinPixelSpinBox->value() );
1187  mFontMaxPixelSpinBox->blockSignals( false );
1188  }
1189  mFontMaxPixelSpinBox->setMinimum( mFontMinPixelSpinBox->value() );
1190 }
1191 
1192 void QgsTextFormatWidget::mBufferUnitWidget_changed()
1193 {
1194  updateFont( mRefFont );
1195 }
1196 
1197 void QgsTextFormatWidget::mCoordXDDBtn_activated( bool active )
1198 {
1199  if ( !active ) //no data defined alignment without data defined position
1200  {
1201  enableDataDefinedAlignment( false );
1202  }
1203  else if ( mCoordYDDBtn->isActive() )
1204  {
1206  }
1207 }
1208 
1209 void QgsTextFormatWidget::mCoordYDDBtn_activated( bool active )
1210 {
1211  if ( !active ) //no data defined alignment without data defined position
1212  {
1213  enableDataDefinedAlignment( false );
1214  }
1215  else if ( mCoordXDDBtn->isActive() )
1216  {
1218  }
1219 }
1220 
1221 void QgsTextFormatWidget::mShapeTypeCmbBx_currentIndexChanged( int index )
1222 {
1223  // shape background
1227 
1228  showBackgroundPenStyle( isRect );
1229  showBackgroundRadius( isRect );
1230 
1231  mShapeSVGPathFrame->setVisible( isSVG );
1232  // symbology SVG renderer only supports size^2 scaling, so we only use the x size spinbox
1233  mShapeSizeYLabel->setVisible( !isSVG );
1234  mShapeSizeYSpnBx->setVisible( !isSVG );
1235  mShapeSizeYDDBtn->setVisible( !isSVG && mWidgetMode == Labeling );
1236  mShapeSizeXLabel->setText( tr( "Size%1" ).arg( !isSVG ? tr( " X" ) : QString() ) );
1237 
1238  // SVG parameter setting doesn't support color's alpha component yet
1239  mShapeFillColorBtn->setAllowOpacity( !isSVG );
1240  mShapeFillColorBtn->setButtonBackground();
1241  mShapeStrokeColorBtn->setAllowOpacity( !isSVG );
1242  mShapeStrokeColorBtn->setButtonBackground();
1243 
1244  // configure SVG parameter widgets
1245  mShapeSVGParamsBtn->setVisible( isSVG );
1246  if ( isSVG )
1247  {
1248  updateSvgWidgets( mShapeSVGPathLineEdit->text() );
1249  }
1250  else
1251  {
1252  mShapeFillColorLabel->setEnabled( true );
1253  mShapeFillColorBtn->setEnabled( true );
1254  mShapeFillColorDDBtn->setEnabled( true );
1255  mShapeStrokeColorLabel->setEnabled( true );
1256  mShapeStrokeColorBtn->setEnabled( true );
1257  mShapeStrokeColorDDBtn->setEnabled( true );
1258  mShapeStrokeWidthLabel->setEnabled( true );
1259  mShapeStrokeWidthSpnBx->setEnabled( true );
1260  mShapeStrokeWidthDDBtn->setEnabled( true );
1261  }
1262  // TODO: fix overriding SVG symbol's stroke width units in QgsSvgCache
1263  // currently broken, fall back to symbol units only
1264  mShapeStrokeWidthUnitWidget->setVisible( !isSVG );
1265  mShapeSVGUnitsLabel->setVisible( isSVG );
1266  mShapeStrokeUnitsDDBtn->setEnabled( !isSVG );
1267 }
1268 
1269 void QgsTextFormatWidget::mShapeSVGPathLineEdit_textChanged( const QString &text )
1270 {
1271  updateSvgWidgets( text );
1272 }
1273 
1275 {
1276  int numOptionsChecked = ( chkLineAbove->isChecked() ? 1 : 0 ) +
1277  ( chkLineBelow->isChecked() ? 1 : 0 ) +
1278  ( chkLineOn->isChecked() ? 1 : 0 );
1279 
1280  if ( numOptionsChecked == 1 )
1281  {
1282  //prevent unchecking last option
1283  chkLineAbove->setEnabled( !chkLineAbove->isChecked() );
1284  chkLineBelow->setEnabled( !chkLineBelow->isChecked() );
1285  chkLineOn->setEnabled( !chkLineOn->isChecked() );
1286  }
1287  else
1288  {
1289  chkLineAbove->setEnabled( true );
1290  chkLineBelow->setEnabled( true );
1291  chkLineOn->setEnabled( true );
1292  }
1293 }
1294 
1295 void QgsTextFormatWidget::onSubstitutionsChanged( const QgsStringReplacementCollection &substitutions )
1296 {
1297  mSubstitutions = substitutions;
1298  emit widgetChanged();
1299 }
1300 
1301 void QgsTextFormatWidget::previewScaleChanged( double scale )
1302 {
1303  lblFontPreview->setScale( scale );
1304 }
1305 
1306 void QgsTextFormatWidget::updateSvgWidgets( const QString &svgPath )
1307 {
1308  if ( mShapeSVGPathLineEdit->text() != svgPath )
1309  {
1310  mShapeSVGPathLineEdit->setText( svgPath );
1311  }
1312 
1313  QString resolvedPath;
1314  bool validSVG = true;
1315  if ( ! svgPath.startsWith( QLatin1String( "base64:" ), Qt::CaseInsensitive ) )
1316  {
1317  resolvedPath = QgsSymbolLayerUtils::svgSymbolNameToPath( svgPath, QgsProject::instance()->pathResolver() );
1318  validSVG = QFileInfo::exists( resolvedPath );
1319  }
1320  else
1321  {
1322  resolvedPath = svgPath;
1323  validSVG = true;
1324  }
1325 
1326  // draw red text for path field if invalid (path can't be resolved)
1327  mShapeSVGPathLineEdit->setStyleSheet( !validSVG ? QStringLiteral( "QLineEdit{ color: rgb(225, 0, 0); }" ) : QString() );
1328  mShapeSVGPathLineEdit->setToolTip( !validSVG ? tr( "File not found" ) : resolvedPath );
1329 
1330  QColor fill, stroke;
1331  double strokeWidth = 0.0;
1332  bool fillParam = false, strokeParam = false, strokeWidthParam = false;
1333  if ( validSVG )
1334  {
1335  QgsApplication::svgCache()->containsParams( resolvedPath, fillParam, fill, strokeParam, stroke, strokeWidthParam, strokeWidth );
1336  }
1337 
1338  mShapeSVGParamsBtn->setEnabled( validSVG && ( fillParam || strokeParam || strokeWidthParam ) );
1339 
1340  mShapeFillColorLabel->setEnabled( validSVG && fillParam );
1341  mShapeFillColorBtn->setEnabled( validSVG && fillParam );
1342  mShapeFillColorDDBtn->setEnabled( validSVG && fillParam );
1343  if ( mLoadSvgParams && validSVG && fillParam )
1344  mShapeFillColorBtn->setColor( fill );
1345 
1346  mShapeStrokeColorLabel->setEnabled( validSVG && strokeParam );
1347  mShapeStrokeColorBtn->setEnabled( validSVG && strokeParam );
1348  mShapeStrokeColorDDBtn->setEnabled( validSVG && strokeParam );
1349  if ( mLoadSvgParams && validSVG && strokeParam )
1350  mShapeStrokeColorBtn->setColor( stroke );
1351 
1352  mShapeStrokeWidthLabel->setEnabled( validSVG && strokeWidthParam );
1353  mShapeStrokeWidthSpnBx->setEnabled( validSVG && strokeWidthParam );
1354  mShapeStrokeWidthDDBtn->setEnabled( validSVG && strokeWidthParam );
1355  if ( mLoadSvgParams && validSVG && strokeWidthParam )
1356  mShapeStrokeWidthSpnBx->setValue( strokeWidth );
1357 
1358  // TODO: fix overriding SVG symbol's stroke width units in QgsSvgCache
1359  // currently broken, fall back to symbol's
1360  //mShapeStrokeWidthUnitWidget->setEnabled( validSVG && strokeWidthParam );
1361  //mShapeStrokeUnitsDDBtn->setEnabled( validSVG && strokeWidthParam );
1362  mShapeSVGUnitsLabel->setEnabled( validSVG && strokeWidthParam );
1363 }
1364 
1365 void QgsTextFormatWidget::mShapeSVGSelectorBtn_clicked()
1366 {
1367  QgsSvgSelectorDialog svgDlg( this );
1368  svgDlg.setWindowTitle( tr( "Select SVG file" ) );
1369  svgDlg.svgSelector()->setSvgPath( mShapeSVGPathLineEdit->text().trimmed() );
1370 
1371  if ( svgDlg.exec() == QDialog::Accepted )
1372  {
1373  QString svgPath = svgDlg.svgSelector()->currentSvgPath();
1374  if ( !svgPath.isEmpty() )
1375  {
1376  mShapeSVGPathLineEdit->setText( svgPath );
1377  updatePreview();
1378  }
1379  }
1380 }
1381 
1382 void QgsTextFormatWidget::mShapeSVGParamsBtn_clicked()
1383 {
1384  QString svgPath = mShapeSVGPathLineEdit->text();
1385  mLoadSvgParams = true;
1386  updateSvgWidgets( svgPath );
1387  mLoadSvgParams = false;
1388 }
1389 
1390 void QgsTextFormatWidget::mShapeRotationCmbBx_currentIndexChanged( int index )
1391 {
1392  mShapeRotationDblSpnBx->setEnabled( ( QgsTextBackgroundSettings::RotationType )index != QgsTextBackgroundSettings::RotationSync );
1393  mShapeRotationDDBtn->setEnabled( ( QgsTextBackgroundSettings::RotationType )index != QgsTextBackgroundSettings::RotationSync );
1394 }
1395 
1396 void QgsTextFormatWidget::mPreviewTextEdit_textChanged( const QString &text )
1397 {
1398  lblFontPreview->setText( text );
1399  updatePreview();
1400 }
1401 
1402 void QgsTextFormatWidget::mPreviewTextBtn_clicked()
1403 {
1404  mPreviewTextEdit->setText( QStringLiteral( "Lorem Ipsum" ) );
1405  updatePreview();
1406 }
1407 
1408 void QgsTextFormatWidget::mPreviewBackgroundBtn_colorChanged( const QColor &color )
1409 {
1410  setPreviewBackground( color );
1411 }
1412 
1413 void QgsTextFormatWidget::mDirectSymbLeftToolBtn_clicked()
1414 {
1415  bool gotChar = false;
1416 
1417  const QChar initial = !mDirectSymbLeftLineEdit->text().isEmpty() ? mDirectSymbLeftLineEdit->text().at( 0 ) : QChar();
1418  QChar dirSymb = mCharDlg->selectCharacter( &gotChar, mRefFont, mFontDB.styleString( mRefFont ), initial );
1419 
1420  if ( !gotChar )
1421  return;
1422 
1423  if ( !dirSymb.isNull() )
1424  mDirectSymbLeftLineEdit->setText( QString( dirSymb ) );
1425 }
1426 
1427 void QgsTextFormatWidget::mDirectSymbRightToolBtn_clicked()
1428 {
1429  bool gotChar = false;
1430  const QChar initial = !mDirectSymbRightLineEdit->text().isEmpty() ? mDirectSymbRightLineEdit->text().at( 0 ) : QChar();
1431  QChar dirSymb = mCharDlg->selectCharacter( &gotChar, mRefFont, mFontDB.styleString( mRefFont ), initial );
1432 
1433  if ( !gotChar )
1434  return;
1435 
1436  if ( !dirSymb.isNull() )
1437  mDirectSymbRightLineEdit->setText( QString( dirSymb ) );
1438 }
1439 
1440 void QgsTextFormatWidget::mChkNoObstacle_toggled( bool active )
1441 {
1442  mPolygonObstacleTypeFrame->setEnabled( active );
1443  mObstaclePriorityFrame->setEnabled( active );
1444 }
1445 
1446 void QgsTextFormatWidget::chkLineOrientationDependent_toggled( bool active )
1447 {
1448  if ( active )
1449  {
1450  chkLineAbove->setText( tr( "Left of line" ) );
1451  chkLineBelow->setText( tr( "Right of line" ) );
1452  }
1453  else
1454  {
1455  chkLineAbove->setText( tr( "Above line" ) );
1456  chkLineBelow->setText( tr( "Below line" ) );
1457  }
1458 }
1459 
1460 
1461 void QgsTextFormatWidget::mToolButtonConfigureSubstitutes_clicked()
1462 {
1464  if ( panel && panel->dockMode() )
1465  {
1467  widget->setPanelTitle( tr( "Substitutions" ) );
1468  widget->setSubstitutions( mSubstitutions );
1469  connect( widget, &QgsSubstitutionListWidget::substitutionsChanged, this, &QgsTextFormatWidget::onSubstitutionsChanged );
1470  panel->openPanel( widget );
1471  return;
1472  }
1473 
1474  QgsSubstitutionListDialog dlg( this );
1476  if ( dlg.exec() == QDialog::Accepted )
1477  {
1478  mSubstitutions = dlg.substitutions();
1479  emit widgetChanged();
1480  }
1481 }
1482 
1483 void QgsTextFormatWidget::showBackgroundRadius( bool show )
1484 {
1485  mShapeRadiusLabel->setVisible( show );
1486  mShapeRadiusXDbSpnBx->setVisible( show );
1487 
1488  mShapeRadiusYDbSpnBx->setVisible( show );
1489 
1490  mShapeRadiusUnitWidget->setVisible( show );
1491 
1492  mShapeRadiusDDBtn->setVisible( show && mWidgetMode == Labeling );
1493  mShapeRadiusUnitsDDBtn->setVisible( show && mWidgetMode == Labeling );
1494 }
1495 
1496 void QgsTextFormatWidget::showBackgroundPenStyle( bool show )
1497 {
1498  mShapePenStyleLabel->setVisible( show );
1499  mShapePenStyleCmbBx->setVisible( show );
1500 
1501  mShapePenStyleDDBtn->setVisible( show && mWidgetMode == Labeling );
1502 }
1503 
1505 {
1506  mCoordAlignmentFrame->setEnabled( enable );
1507 }
1508 
1509 
1510 //
1511 // QgsTextFormatDialog
1512 //
1513 
1514 QgsTextFormatDialog::QgsTextFormatDialog( const QgsTextFormat &format, QgsMapCanvas *mapCanvas, QWidget *parent, Qt::WindowFlags fl )
1515  : QDialog( parent, fl )
1516 {
1517  setWindowTitle( tr( "Text Settings" ) );
1518 
1519  mFormatWidget = new QgsTextFormatWidget( format, mapCanvas, this );
1520  mFormatWidget->layout()->setContentsMargins( 0, 0, 0, 0 );
1521 
1522  QVBoxLayout *layout = new QVBoxLayout( this );
1523  layout->addWidget( mFormatWidget );
1524 
1525  QDialogButtonBox *buttonBox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this );
1526  layout->addWidget( buttonBox );
1527 
1528  setLayout( layout );
1529 
1530  QgsSettings settings;
1531  restoreGeometry( settings.value( QStringLiteral( "Windows/TextFormatDialog/geometry" ) ).toByteArray() );
1532 
1533  connect( buttonBox->button( QDialogButtonBox::Ok ), &QAbstractButton::clicked, this, &QDialog::accept );
1534  connect( buttonBox->button( QDialogButtonBox::Cancel ), &QAbstractButton::clicked, this, &QDialog::reject );
1535 }
1536 
1538 {
1539  QgsSettings settings;
1540  settings.setValue( QStringLiteral( "Windows/TextFormatDialog/geometry" ), saveGeometry() );
1541 }
1542 
1544 {
1545  return mFormatWidget->format();
1546 }
1547 
1549  : QgsPanelWidgetWrapper( new QgsTextFormatWidget( format, mapCanvas ), parent )
1550 {
1551  mFormatWidget = qobject_cast< QgsTextFormatWidget * >( widget() );
1552  connect( mFormatWidget, &QgsTextFormatWidget::widgetChanged, this, &QgsPanelWidget::widgetChanged );
1553 }
1554 
1556 {
1557  return mFormatWidget->format();
1558 }
1559 
1561 {
1562  mFormatWidget->setDockMode( dockMode );
1564 }
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 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:120
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).
RotationType
Methods for determining the rotation of the background shape.
void setOffsetMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale object for the shadow offset distance.
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 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.
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.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:58
A groupbox that collapses/expands when toggled and can save its collapsed and checked states...
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.
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...
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:121
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 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.
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.
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.
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.
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:116
QgsMapUnitScale offsetMapUnitScale() const
Returns the map unit scale object for the shape offset.
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.
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:184
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:73
Show labeling settings in addition to text formatting settings.
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.
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.
QgsMapUnitScale sizeMapUnitScale() const
Returns the map unit scale object for the buffer size.
void saveGeometry(QWidget *widget, const QString &keyName)
Save the wigget geometry into settings.
Place direction symbols on left/right of label.
bool restoreGeometry(QWidget *widget, const QString &keyName)
Restore the wigget geometry from settings.
void setBlendMode(QPainter::CompositionMode mode)
Sets the blending mode used for drawing the background shape.
QgsMapUnitScale offsetMapUnitScale() const
Returns the map unit scale object for the shadow offset distance.
QPainter::CompositionMode blendMode() const
Returns the blending mode used for drawing the text.
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.
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. ...
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.
bool fillBufferInterior() const
Returns whether the interior of the buffer will be filled in.
static QgsPanelWidget * findParentPanel(QWidget *widget)
Traces through the parents of a widget to find if it is contained within a QgsPanelWidget widget...
void setOffsetMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale object for the shape offset.
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 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 setColor(const QColor &color)
Sets the color for the drop shadow.
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.
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.
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.
SizeType
Methods for determining the background shape size.
double opacity() const
Returns the buffer opacity.
void updateLinePlacementOptions()
Updates line placement options to reflect current state of 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.
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.
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.
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...
void setType(ShapeType type)
Sets the type of background shape to draw (e.g., square, ellipse, SVG).
Place direction symbols on above label.
QPainter::CompositionMode blendMode() const
Returns the blending mode used for drawing the background shape.
QgsTextFormat format() const
Returns the current formatting settings defined by the widget.
void containsParams(const QString &path, bool &hasFillParam, QColor &defaultFillColor, bool &hasStrokeParam, QColor &defaultStrokeColor, bool &hasStrokeWidthParam, double &defaultStrokeWidth) const
Tests if an svg file contains parameters for fill, stroke color, stroke width.
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.
void colorChanged(const QColor &color)
Emitted whenever a new color is set for the button.
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.
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:212
static bool fontFamilyMatchOnSystem(const QString &family, QString *chosen=nullptr, bool *match=nullptr)
Check whether font family is on system.
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:117
QgsUnitTypes::RenderUnit offsetUnit() const
Returns the units used for the shadow&#39;s offset.
bool enabled() const
Returns whether the shadow is enabled.
QgsTextFormatWidget(const QgsTextFormat &format=QgsTextFormat(), QgsMapCanvas *mapCanvas=nullptr, QWidget *parent=nullptr)
Constructor for QgsTextFormatWidget.
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.
void setFillColor(const QColor &color)
Sets the color used for filing the background shape.
static bool updateFontViaStyle(QFont &f, const QString &fontstyle, bool fallback=false)
Updates font with named style and retain all font properties.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:438
double size() const
Returns the size for rendered text.
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.
int mMinPixelLimit
Pixel size font limit.
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).
Shape rotation is synced with text rotation.
QButtonGroup * mQuadrantBtnGrp
Quadrant button group.
void setShadowPlacement(QgsTextShadowSettings::ShadowPlacement placement)
Sets the placement for the drop shadow.
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.
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.
Show upside down when rotation is layer- or data-defined.
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.
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.
A widget displaying a combobox allowing the user to choose between various display units...
void setSvgFile(const QString &file)
Sets the path to the background SVG file.
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.
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.
Square - buffered sizes only.
Wrapper widget for existing widgets which can&#39;t have the inheritance tree changed, e.g dialogs.
QgsStringReplacementCollection substitutions
void setPanelTitle(const QString &panelTitle)
Set the title of the panel when shown in the interface.
QgsTextFormatPanelWidget(const QgsTextFormat &format, QgsMapCanvas *mapCanvas=nullptr, QWidget *parent=nullptr)
Constructor for QgsTextFormatPanelWidget.
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.
double opacity() const
Returns the shadow&#39;s opacity.
void setOpacity(double opacity)
Sets the background shape&#39;s opacity.
void setPaintEffect(QgsPaintEffect *effect)
Sets the current paint effect for the background shape.
QString resolvedFontFamily() const
Returns the family for the resolved font, ie if the specified font was not found on the system this w...
QgsTextFormatDialog(const QgsTextFormat &format, QgsMapCanvas *mapCanvas=nullptr, QWidget *parent=nullptr, Qt::WindowFlags fl=QgsGuiUtils::ModalDialogFlags)
Constructor for QgsTextFormatDialog.
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.