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