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