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