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