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